diff options
Diffstat (limited to 'drivers/media/video')
137 files changed, 7124 insertions, 21768 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 27e2acce3c3a..2e15903b976d 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -517,19 +517,6 @@ config VIDEO_UPD64083 | |||
517 | 517 | ||
518 | endmenu # encoder / decoder chips | 518 | endmenu # encoder / decoder chips |
519 | 519 | ||
520 | config DISPLAY_DAVINCI_DM646X_EVM | ||
521 | tristate "DM646x EVM Video Display" | ||
522 | depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM | ||
523 | select VIDEOBUF_DMA_CONTIG | ||
524 | select VIDEO_DAVINCI_VPIF | ||
525 | select VIDEO_ADV7343 | ||
526 | select VIDEO_THS7303 | ||
527 | help | ||
528 | Support for DM6467 based display device. | ||
529 | |||
530 | To compile this driver as a module, choose M here: the | ||
531 | module will be called vpif_display. | ||
532 | |||
533 | config VIDEO_SH_VOU | 520 | config VIDEO_SH_VOU |
534 | tristate "SuperH VOU video output driver" | 521 | tristate "SuperH VOU video output driver" |
535 | depends on VIDEO_DEV && ARCH_SHMOBILE | 522 | depends on VIDEO_DEV && ARCH_SHMOBILE |
@@ -537,29 +524,22 @@ config VIDEO_SH_VOU | |||
537 | help | 524 | help |
538 | Support for the Video Output Unit (VOU) on SuperH SoCs. | 525 | Support for the Video Output Unit (VOU) on SuperH SoCs. |
539 | 526 | ||
540 | config CAPTURE_DAVINCI_DM646X_EVM | 527 | config VIDEO_VIU |
541 | tristate "DM646x EVM Video Capture" | 528 | tristate "Freescale VIU Video Driver" |
542 | depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM | 529 | depends on VIDEO_V4L2 && PPC_MPC512x |
543 | select VIDEOBUF_DMA_CONTIG | 530 | select VIDEOBUF_DMA_CONTIG |
544 | select VIDEO_DAVINCI_VPIF | 531 | default y |
545 | help | 532 | ---help--- |
546 | Support for DM6467 based capture device. | 533 | Support for Freescale VIU video driver. This device captures |
547 | 534 | video data, or overlays video on DIU frame buffer. | |
548 | To compile this driver as a module, choose M here: the | ||
549 | module will be called vpif_capture. | ||
550 | |||
551 | config VIDEO_DAVINCI_VPIF | ||
552 | tristate "DaVinci VPIF Driver" | ||
553 | depends on DISPLAY_DAVINCI_DM646X_EVM | ||
554 | help | ||
555 | Support for DaVinci VPIF Driver. | ||
556 | 535 | ||
557 | To compile this driver as a module, choose M here: the | 536 | Say Y here if you want to enable VIU device on MPC5121e Rev2+. |
558 | module will be called vpif. | 537 | In doubt, say N. |
559 | 538 | ||
560 | config VIDEO_VIVI | 539 | config VIDEO_VIVI |
561 | tristate "Virtual Video Driver" | 540 | tristate "Virtual Video Driver" |
562 | depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 && FONTS | 541 | depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 |
542 | depends on (FRAMEBUFFER_CONSOLE || STI_CONSOLE) && FONTS | ||
563 | select FONT_8x16 | 543 | select FONT_8x16 |
564 | select VIDEOBUF_VMALLOC | 544 | select VIDEOBUF_VMALLOC |
565 | default n | 545 | default n |
@@ -570,66 +550,7 @@ config VIDEO_VIVI | |||
570 | Say Y here if you want to test video apps or debug V4L devices. | 550 | Say Y here if you want to test video apps or debug V4L devices. |
571 | In doubt, say N. | 551 | In doubt, say N. |
572 | 552 | ||
573 | config VIDEO_VPSS_SYSTEM | 553 | source "drivers/media/video/davinci/Kconfig" |
574 | tristate "VPSS System module driver" | ||
575 | depends on ARCH_DAVINCI | ||
576 | help | ||
577 | Support for vpss system module for video driver | ||
578 | |||
579 | config VIDEO_VPFE_CAPTURE | ||
580 | tristate "VPFE Video Capture Driver" | ||
581 | depends on VIDEO_V4L2 && ARCH_DAVINCI | ||
582 | select VIDEOBUF_DMA_CONTIG | ||
583 | help | ||
584 | Support for DMXXXX VPFE based frame grabber. This is the | ||
585 | common V4L2 module for following DMXXX SoCs from Texas | ||
586 | Instruments:- DM6446 & DM355. | ||
587 | |||
588 | To compile this driver as a module, choose M here: the | ||
589 | module will be called vpfe-capture. | ||
590 | |||
591 | config VIDEO_DM6446_CCDC | ||
592 | tristate "DM6446 CCDC HW module" | ||
593 | depends on ARCH_DAVINCI_DM644x && VIDEO_VPFE_CAPTURE | ||
594 | select VIDEO_VPSS_SYSTEM | ||
595 | default y | ||
596 | help | ||
597 | Enables DaVinci CCD hw module. DaVinci CCDC hw interfaces | ||
598 | with decoder modules such as TVP5146 over BT656 or | ||
599 | sensor module such as MT9T001 over a raw interface. This | ||
600 | module configures the interface and CCDC/ISIF to do | ||
601 | video frame capture from slave decoders. | ||
602 | |||
603 | To compile this driver as a module, choose M here: the | ||
604 | module will be called vpfe. | ||
605 | |||
606 | config VIDEO_DM355_CCDC | ||
607 | tristate "DM355 CCDC HW module" | ||
608 | depends on ARCH_DAVINCI_DM355 && VIDEO_VPFE_CAPTURE | ||
609 | select VIDEO_VPSS_SYSTEM | ||
610 | default y | ||
611 | help | ||
612 | Enables DM355 CCD hw module. DM355 CCDC hw interfaces | ||
613 | with decoder modules such as TVP5146 over BT656 or | ||
614 | sensor module such as MT9T001 over a raw interface. This | ||
615 | module configures the interface and CCDC/ISIF to do | ||
616 | video frame capture from a slave decoders | ||
617 | |||
618 | To compile this driver as a module, choose M here: the | ||
619 | module will be called vpfe. | ||
620 | |||
621 | config VIDEO_ISIF | ||
622 | tristate "ISIF HW module" | ||
623 | depends on ARCH_DAVINCI_DM365 && VIDEO_VPFE_CAPTURE | ||
624 | select VIDEO_VPSS_SYSTEM | ||
625 | default y | ||
626 | help | ||
627 | Enables ISIF hw module. This is the hardware module for | ||
628 | configuring ISIF in VPFE to capture Raw Bayer RGB data from | ||
629 | a image sensor or YUV data from a YUV source. | ||
630 | |||
631 | To compile this driver as a module, choose M here: the | ||
632 | module will be called vpfe. | ||
633 | 554 | ||
634 | source "drivers/media/video/omap/Kconfig" | 555 | source "drivers/media/video/omap/Kconfig" |
635 | 556 | ||
@@ -955,6 +876,12 @@ config VIDEO_PXA27x | |||
955 | ---help--- | 876 | ---help--- |
956 | This is a v4l2 driver for the PXA27x Quick Capture Interface | 877 | This is a v4l2 driver for the PXA27x Quick Capture Interface |
957 | 878 | ||
879 | config VIDEO_SH_MOBILE_CSI2 | ||
880 | tristate "SuperH Mobile MIPI CSI-2 Interface driver" | ||
881 | depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK | ||
882 | ---help--- | ||
883 | This is a v4l2 driver for the SuperH MIPI CSI-2 Interface | ||
884 | |||
958 | config VIDEO_SH_MOBILE_CEU | 885 | config VIDEO_SH_MOBILE_CEU |
959 | tristate "SuperH Mobile CEU Interface driver" | 886 | tristate "SuperH Mobile CEU Interface driver" |
960 | depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK | 887 | depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK |
@@ -1013,61 +940,6 @@ source "drivers/media/video/usbvideo/Kconfig" | |||
1013 | 940 | ||
1014 | source "drivers/media/video/et61x251/Kconfig" | 941 | source "drivers/media/video/et61x251/Kconfig" |
1015 | 942 | ||
1016 | config VIDEO_OVCAMCHIP | ||
1017 | tristate "OmniVision Camera Chip support (DEPRECATED)" | ||
1018 | depends on I2C && VIDEO_V4L1 | ||
1019 | default n | ||
1020 | ---help--- | ||
1021 | This driver is DEPRECATED please use the gspca ov519 module | ||
1022 | instead. Note that for the ov511 / ov518 support of the gspca module | ||
1023 | you need atleast version 0.6.0 of libv4l and for the w9968cf | ||
1024 | atleast version 0.6.3 of libv4l. | ||
1025 | |||
1026 | Support for the OmniVision OV6xxx and OV7xxx series of camera chips. | ||
1027 | This driver is intended to be used with the ov511 and w9968cf USB | ||
1028 | camera drivers. | ||
1029 | |||
1030 | To compile this driver as a module, choose M here: the | ||
1031 | module will be called ovcamchip. | ||
1032 | |||
1033 | config USB_W9968CF | ||
1034 | tristate "USB W996[87]CF JPEG Dual Mode Camera support (DEPRECATED)" | ||
1035 | depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP | ||
1036 | default n | ||
1037 | ---help--- | ||
1038 | This driver is DEPRECATED please use the gspca ov519 module | ||
1039 | instead. Note that for the w9968cf support of the gspca module | ||
1040 | you need atleast version 0.6.3 of libv4l. | ||
1041 | |||
1042 | Say Y here if you want support for cameras based on OV681 or | ||
1043 | Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. | ||
1044 | |||
1045 | This driver has an optional plugin, which is distributed as a | ||
1046 | separate module only (released under GPL). It allows to use higher | ||
1047 | resolutions and framerates, but cannot be included in the official | ||
1048 | Linux kernel for performance purposes. | ||
1049 | |||
1050 | See <file:Documentation/video4linux/w9968cf.txt> for more info. | ||
1051 | |||
1052 | To compile this driver as a module, choose M here: the | ||
1053 | module will be called w9968cf. | ||
1054 | |||
1055 | config USB_OV511 | ||
1056 | tristate "USB OV511 Camera support (DEPRECATED)" | ||
1057 | depends on VIDEO_V4L1 | ||
1058 | default n | ||
1059 | ---help--- | ||
1060 | This driver is DEPRECATED please use the gspca ov519 module | ||
1061 | instead. Note that for the ov511 / ov518 support of the gspca module | ||
1062 | you need atleast version 0.6.0 of libv4l. | ||
1063 | |||
1064 | Say Y here if you want to connect this type of camera to your | ||
1065 | computer's USB port. See <file:Documentation/video4linux/ov511.txt> | ||
1066 | for more information and for a list of supported cameras. | ||
1067 | |||
1068 | To compile this driver as a module, choose M here: the | ||
1069 | module will be called ov511. | ||
1070 | |||
1071 | config USB_SE401 | 943 | config USB_SE401 |
1072 | tristate "USB SE401 Camera support" | 944 | tristate "USB SE401 Camera support" |
1073 | depends on VIDEO_V4L1 | 945 | depends on VIDEO_V4L1 |
@@ -1081,25 +953,6 @@ config USB_SE401 | |||
1081 | 953 | ||
1082 | source "drivers/media/video/sn9c102/Kconfig" | 954 | source "drivers/media/video/sn9c102/Kconfig" |
1083 | 955 | ||
1084 | config USB_STV680 | ||
1085 | tristate "USB STV680 (Pencam) Camera support (DEPRECATED)" | ||
1086 | depends on VIDEO_V4L1 | ||
1087 | default n | ||
1088 | ---help--- | ||
1089 | This driver is DEPRECATED please use the gspca stv0680 module | ||
1090 | instead. Note that for the gspca stv0680 module you need | ||
1091 | atleast version 0.6.3 of libv4l. | ||
1092 | |||
1093 | Say Y here if you want to connect this type of camera to your | ||
1094 | computer's USB port. This includes the Pencam line of cameras. | ||
1095 | See <file:Documentation/video4linux/stv680.txt> for more information | ||
1096 | and for a list of supported cameras. | ||
1097 | |||
1098 | To compile this driver as a module, choose M here: the | ||
1099 | module will be called stv680. | ||
1100 | |||
1101 | source "drivers/media/video/zc0301/Kconfig" | ||
1102 | |||
1103 | source "drivers/media/video/pwc/Kconfig" | 956 | source "drivers/media/video/pwc/Kconfig" |
1104 | 957 | ||
1105 | config USB_ZR364XX | 958 | config USB_ZR364XX |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index b08bd2b65cd0..1051ecc602e7 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -105,7 +105,6 @@ obj-$(CONFIG_VIDEO_TLG2300) += tlg2300/ | |||
105 | obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/ | 105 | obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/ |
106 | obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ | 106 | obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ |
107 | obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/ | 107 | obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/ |
108 | obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ | ||
109 | obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ | 108 | obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ |
110 | obj-$(CONFIG_VIDEO_MXB) += mxb.o | 109 | obj-$(CONFIG_VIDEO_MXB) += mxb.o |
111 | obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o | 110 | obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o |
@@ -127,17 +126,13 @@ obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o | |||
127 | obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o | 126 | obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o |
128 | 127 | ||
129 | obj-$(CONFIG_USB_DABUSB) += dabusb.o | 128 | obj-$(CONFIG_USB_DABUSB) += dabusb.o |
130 | obj-$(CONFIG_USB_OV511) += ov511.o | ||
131 | obj-$(CONFIG_USB_SE401) += se401.o | 129 | obj-$(CONFIG_USB_SE401) += se401.o |
132 | obj-$(CONFIG_USB_STV680) += stv680.o | ||
133 | obj-$(CONFIG_USB_W9968CF) += w9968cf.o | ||
134 | obj-$(CONFIG_USB_ZR364XX) += zr364xx.o | 130 | obj-$(CONFIG_USB_ZR364XX) += zr364xx.o |
135 | obj-$(CONFIG_USB_STKWEBCAM) += stkwebcam.o | 131 | obj-$(CONFIG_USB_STKWEBCAM) += stkwebcam.o |
136 | 132 | ||
137 | obj-$(CONFIG_USB_SN9C102) += sn9c102/ | 133 | obj-$(CONFIG_USB_SN9C102) += sn9c102/ |
138 | obj-$(CONFIG_USB_ET61X251) += et61x251/ | 134 | obj-$(CONFIG_USB_ET61X251) += et61x251/ |
139 | obj-$(CONFIG_USB_PWC) += pwc/ | 135 | obj-$(CONFIG_USB_PWC) += pwc/ |
140 | obj-$(CONFIG_USB_ZC0301) += zc0301/ | ||
141 | obj-$(CONFIG_USB_GSPCA) += gspca/ | 136 | obj-$(CONFIG_USB_GSPCA) += gspca/ |
142 | 137 | ||
143 | obj-$(CONFIG_VIDEO_HDPVR) += hdpvr/ | 138 | obj-$(CONFIG_VIDEO_HDPVR) += hdpvr/ |
@@ -151,6 +146,7 @@ obj-$(CONFIG_USB_S2255) += s2255drv.o | |||
151 | obj-$(CONFIG_VIDEO_IVTV) += ivtv/ | 146 | obj-$(CONFIG_VIDEO_IVTV) += ivtv/ |
152 | obj-$(CONFIG_VIDEO_CX18) += cx18/ | 147 | obj-$(CONFIG_VIDEO_CX18) += cx18/ |
153 | 148 | ||
149 | obj-$(CONFIG_VIDEO_VIU) += fsl-viu.o | ||
154 | obj-$(CONFIG_VIDEO_VIVI) += vivi.o | 150 | obj-$(CONFIG_VIDEO_VIVI) += vivi.o |
155 | obj-$(CONFIG_VIDEO_MEM2MEM_TESTDEV) += mem2mem_testdev.o | 151 | obj-$(CONFIG_VIDEO_MEM2MEM_TESTDEV) += mem2mem_testdev.o |
156 | obj-$(CONFIG_VIDEO_CX23885) += cx23885/ | 152 | obj-$(CONFIG_VIDEO_CX23885) += cx23885/ |
@@ -165,6 +161,7 @@ obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o | |||
165 | obj-$(CONFIG_VIDEO_MX2) += mx2_camera.o | 161 | obj-$(CONFIG_VIDEO_MX2) += mx2_camera.o |
166 | obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o | 162 | obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o |
167 | obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o | 163 | obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o |
164 | obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o | ||
168 | obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o | 165 | obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o |
169 | 166 | ||
170 | obj-$(CONFIG_ARCH_DAVINCI) += davinci/ | 167 | obj-$(CONFIG_ARCH_DAVINCI) += davinci/ |
@@ -178,7 +175,7 @@ obj-$(CONFIG_VIDEO_SAA7164) += saa7164/ | |||
178 | 175 | ||
179 | obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o | 176 | obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o |
180 | 177 | ||
181 | obj-$(CONFIG_ARCH_DAVINCI) += davinci/ | 178 | obj-y += davinci/ |
182 | 179 | ||
183 | obj-$(CONFIG_ARCH_OMAP) += omap/ | 180 | obj-$(CONFIG_ARCH_OMAP) += omap/ |
184 | 181 | ||
diff --git a/drivers/media/video/ak881x.c b/drivers/media/video/ak881x.c index 1573392f74bd..b388654d48cd 100644 --- a/drivers/media/video/ak881x.c +++ b/drivers/media/video/ak881x.c | |||
@@ -126,7 +126,7 @@ static int ak881x_try_g_mbus_fmt(struct v4l2_subdev *sd, | |||
126 | v4l_bound_align_image(&mf->width, 0, 720, 2, | 126 | v4l_bound_align_image(&mf->width, 0, 720, 2, |
127 | &mf->height, 0, ak881x->lines, 1, 0); | 127 | &mf->height, 0, ak881x->lines, 1, 0); |
128 | mf->field = V4L2_FIELD_INTERLACED; | 128 | mf->field = V4L2_FIELD_INTERLACED; |
129 | mf->code = V4L2_MBUS_FMT_YUYV8_2X8_LE; | 129 | mf->code = V4L2_MBUS_FMT_YUYV8_2X8; |
130 | mf->colorspace = V4L2_COLORSPACE_SMPTE170M; | 130 | mf->colorspace = V4L2_COLORSPACE_SMPTE170M; |
131 | 131 | ||
132 | return 0; | 132 | return 0; |
@@ -136,7 +136,7 @@ static int ak881x_s_mbus_fmt(struct v4l2_subdev *sd, | |||
136 | struct v4l2_mbus_framefmt *mf) | 136 | struct v4l2_mbus_framefmt *mf) |
137 | { | 137 | { |
138 | if (mf->field != V4L2_FIELD_INTERLACED || | 138 | if (mf->field != V4L2_FIELD_INTERLACED || |
139 | mf->code != V4L2_MBUS_FMT_YUYV8_2X8_LE) | 139 | mf->code != V4L2_MBUS_FMT_YUYV8_2X8) |
140 | return -EINVAL; | 140 | return -EINVAL; |
141 | 141 | ||
142 | return ak881x_try_g_mbus_fmt(sd, mf); | 142 | return ak881x_try_g_mbus_fmt(sd, mf); |
@@ -148,7 +148,7 @@ static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index, | |||
148 | if (index) | 148 | if (index) |
149 | return -EINVAL; | 149 | return -EINVAL; |
150 | 150 | ||
151 | *code = V4L2_MBUS_FMT_YUYV8_2X8_LE; | 151 | *code = V4L2_MBUS_FMT_YUYV8_2X8; |
152 | return 0; | 152 | return 0; |
153 | } | 153 | } |
154 | 154 | ||
diff --git a/drivers/media/video/au0828/Makefile b/drivers/media/video/au0828/Makefile index 4d2623158188..5c7f2f7d9805 100644 --- a/drivers/media/video/au0828/Makefile +++ b/drivers/media/video/au0828/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | au0828-objs := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o au0828-video.o | 1 | au0828-objs := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o au0828-video.o au0828-vbi.o |
2 | 2 | ||
3 | obj-$(CONFIG_VIDEO_AU0828) += au0828.o | 3 | obj-$(CONFIG_VIDEO_AU0828) += au0828.o |
4 | 4 | ||
diff --git a/drivers/media/video/au0828/au0828-vbi.c b/drivers/media/video/au0828/au0828-vbi.c new file mode 100644 index 000000000000..63f593070ee8 --- /dev/null +++ b/drivers/media/video/au0828/au0828-vbi.c | |||
@@ -0,0 +1,138 @@ | |||
1 | /* | ||
2 | au0828-vbi.c - VBI driver for au0828 | ||
3 | |||
4 | Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com> | ||
5 | |||
6 | This work was sponsored by GetWellNetwork Inc. | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
21 | 02110-1301, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/slab.h> | ||
28 | |||
29 | #include "au0828.h" | ||
30 | |||
31 | static unsigned int vbibufs = 5; | ||
32 | module_param(vbibufs, int, 0644); | ||
33 | MODULE_PARM_DESC(vbibufs, "number of vbi buffers, range 2-32"); | ||
34 | |||
35 | /* ------------------------------------------------------------------ */ | ||
36 | |||
37 | static void | ||
38 | free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf) | ||
39 | { | ||
40 | struct au0828_fh *fh = vq->priv_data; | ||
41 | struct au0828_dev *dev = fh->dev; | ||
42 | unsigned long flags = 0; | ||
43 | if (in_interrupt()) | ||
44 | BUG(); | ||
45 | |||
46 | /* We used to wait for the buffer to finish here, but this didn't work | ||
47 | because, as we were keeping the state as VIDEOBUF_QUEUED, | ||
48 | videobuf_queue_cancel marked it as finished for us. | ||
49 | (Also, it could wedge forever if the hardware was misconfigured.) | ||
50 | |||
51 | This should be safe; by the time we get here, the buffer isn't | ||
52 | queued anymore. If we ever start marking the buffers as | ||
53 | VIDEOBUF_ACTIVE, it won't be, though. | ||
54 | */ | ||
55 | spin_lock_irqsave(&dev->slock, flags); | ||
56 | if (dev->isoc_ctl.vbi_buf == buf) | ||
57 | dev->isoc_ctl.vbi_buf = NULL; | ||
58 | spin_unlock_irqrestore(&dev->slock, flags); | ||
59 | |||
60 | videobuf_vmalloc_free(&buf->vb); | ||
61 | buf->vb.state = VIDEOBUF_NEEDS_INIT; | ||
62 | } | ||
63 | |||
64 | static int | ||
65 | vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) | ||
66 | { | ||
67 | struct au0828_fh *fh = q->priv_data; | ||
68 | struct au0828_dev *dev = fh->dev; | ||
69 | |||
70 | *size = dev->vbi_width * dev->vbi_height * 2; | ||
71 | |||
72 | if (0 == *count) | ||
73 | *count = vbibufs; | ||
74 | if (*count < 2) | ||
75 | *count = 2; | ||
76 | if (*count > 32) | ||
77 | *count = 32; | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static int | ||
82 | vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | ||
83 | enum v4l2_field field) | ||
84 | { | ||
85 | struct au0828_fh *fh = q->priv_data; | ||
86 | struct au0828_dev *dev = fh->dev; | ||
87 | struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb); | ||
88 | int rc = 0; | ||
89 | |||
90 | buf->vb.size = dev->vbi_width * dev->vbi_height * 2; | ||
91 | |||
92 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) | ||
93 | return -EINVAL; | ||
94 | |||
95 | buf->vb.width = dev->vbi_width; | ||
96 | buf->vb.height = dev->vbi_height; | ||
97 | buf->vb.field = field; | ||
98 | |||
99 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | ||
100 | rc = videobuf_iolock(q, &buf->vb, NULL); | ||
101 | if (rc < 0) | ||
102 | goto fail; | ||
103 | } | ||
104 | |||
105 | buf->vb.state = VIDEOBUF_PREPARED; | ||
106 | return 0; | ||
107 | |||
108 | fail: | ||
109 | free_buffer(q, buf); | ||
110 | return rc; | ||
111 | } | ||
112 | |||
113 | static void | ||
114 | vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
115 | { | ||
116 | struct au0828_buffer *buf = container_of(vb, | ||
117 | struct au0828_buffer, | ||
118 | vb); | ||
119 | struct au0828_fh *fh = vq->priv_data; | ||
120 | struct au0828_dev *dev = fh->dev; | ||
121 | struct au0828_dmaqueue *vbiq = &dev->vbiq; | ||
122 | |||
123 | buf->vb.state = VIDEOBUF_QUEUED; | ||
124 | list_add_tail(&buf->vb.queue, &vbiq->active); | ||
125 | } | ||
126 | |||
127 | static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
128 | { | ||
129 | struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb); | ||
130 | free_buffer(q, buf); | ||
131 | } | ||
132 | |||
133 | struct videobuf_queue_ops au0828_vbi_qops = { | ||
134 | .buf_setup = vbi_setup, | ||
135 | .buf_prepare = vbi_prepare, | ||
136 | .buf_queue = vbi_queue, | ||
137 | .buf_release = vbi_release, | ||
138 | }; | ||
diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 52f25aabb6dc..7989a7ba7c40 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c | |||
@@ -314,6 +314,23 @@ static inline void buffer_filled(struct au0828_dev *dev, | |||
314 | wake_up(&buf->vb.done); | 314 | wake_up(&buf->vb.done); |
315 | } | 315 | } |
316 | 316 | ||
317 | static inline void vbi_buffer_filled(struct au0828_dev *dev, | ||
318 | struct au0828_dmaqueue *dma_q, | ||
319 | struct au0828_buffer *buf) | ||
320 | { | ||
321 | /* Advice that buffer was filled */ | ||
322 | au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); | ||
323 | |||
324 | buf->vb.state = VIDEOBUF_DONE; | ||
325 | buf->vb.field_count++; | ||
326 | do_gettimeofday(&buf->vb.ts); | ||
327 | |||
328 | dev->isoc_ctl.vbi_buf = NULL; | ||
329 | |||
330 | list_del(&buf->vb.queue); | ||
331 | wake_up(&buf->vb.done); | ||
332 | } | ||
333 | |||
317 | /* | 334 | /* |
318 | * Identify the buffer header type and properly handles | 335 | * Identify the buffer header type and properly handles |
319 | */ | 336 | */ |
@@ -327,6 +344,9 @@ static void au0828_copy_video(struct au0828_dev *dev, | |||
327 | int linesdone, currlinedone, offset, lencopy, remain; | 344 | int linesdone, currlinedone, offset, lencopy, remain; |
328 | int bytesperline = dev->width << 1; /* Assumes 16-bit depth @@@@ */ | 345 | int bytesperline = dev->width << 1; /* Assumes 16-bit depth @@@@ */ |
329 | 346 | ||
347 | if (len == 0) | ||
348 | return; | ||
349 | |||
330 | if (dma_q->pos + len > buf->vb.size) | 350 | if (dma_q->pos + len > buf->vb.size) |
331 | len = buf->vb.size - dma_q->pos; | 351 | len = buf->vb.size - dma_q->pos; |
332 | 352 | ||
@@ -414,17 +434,98 @@ static inline void get_next_buf(struct au0828_dmaqueue *dma_q, | |||
414 | return; | 434 | return; |
415 | } | 435 | } |
416 | 436 | ||
437 | static void au0828_copy_vbi(struct au0828_dev *dev, | ||
438 | struct au0828_dmaqueue *dma_q, | ||
439 | struct au0828_buffer *buf, | ||
440 | unsigned char *p, | ||
441 | unsigned char *outp, unsigned long len) | ||
442 | { | ||
443 | unsigned char *startwrite, *startread; | ||
444 | int bytesperline; | ||
445 | int i, j = 0; | ||
446 | |||
447 | if (dev == NULL) { | ||
448 | au0828_isocdbg("dev is null\n"); | ||
449 | return; | ||
450 | } | ||
451 | |||
452 | if (dma_q == NULL) { | ||
453 | au0828_isocdbg("dma_q is null\n"); | ||
454 | return; | ||
455 | } | ||
456 | if (buf == NULL) | ||
457 | return; | ||
458 | if (p == NULL) { | ||
459 | au0828_isocdbg("p is null\n"); | ||
460 | return; | ||
461 | } | ||
462 | if (outp == NULL) { | ||
463 | au0828_isocdbg("outp is null\n"); | ||
464 | return; | ||
465 | } | ||
466 | |||
467 | bytesperline = dev->vbi_width; | ||
468 | |||
469 | if (dma_q->pos + len > buf->vb.size) | ||
470 | len = buf->vb.size - dma_q->pos; | ||
471 | |||
472 | startread = p; | ||
473 | startwrite = outp + (dma_q->pos / 2); | ||
474 | |||
475 | /* Make sure the bottom field populates the second half of the frame */ | ||
476 | if (buf->top_field == 0) | ||
477 | startwrite += bytesperline * dev->vbi_height; | ||
478 | |||
479 | for (i = 0; i < len; i += 2) | ||
480 | startwrite[j++] = startread[i+1]; | ||
481 | |||
482 | dma_q->pos += len; | ||
483 | } | ||
484 | |||
485 | |||
486 | /* | ||
487 | * video-buf generic routine to get the next available VBI buffer | ||
488 | */ | ||
489 | static inline void vbi_get_next_buf(struct au0828_dmaqueue *dma_q, | ||
490 | struct au0828_buffer **buf) | ||
491 | { | ||
492 | struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vbiq); | ||
493 | char *outp; | ||
494 | |||
495 | if (list_empty(&dma_q->active)) { | ||
496 | au0828_isocdbg("No active queue to serve\n"); | ||
497 | dev->isoc_ctl.vbi_buf = NULL; | ||
498 | *buf = NULL; | ||
499 | return; | ||
500 | } | ||
501 | |||
502 | /* Get the next buffer */ | ||
503 | *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue); | ||
504 | /* Cleans up buffer - Usefull for testing for frame/URB loss */ | ||
505 | outp = videobuf_to_vmalloc(&(*buf)->vb); | ||
506 | memset(outp, 0x00, (*buf)->vb.size); | ||
507 | |||
508 | dev->isoc_ctl.vbi_buf = *buf; | ||
509 | |||
510 | return; | ||
511 | } | ||
512 | |||
417 | /* | 513 | /* |
418 | * Controls the isoc copy of each urb packet | 514 | * Controls the isoc copy of each urb packet |
419 | */ | 515 | */ |
420 | static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) | 516 | static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) |
421 | { | 517 | { |
422 | struct au0828_buffer *buf; | 518 | struct au0828_buffer *buf; |
519 | struct au0828_buffer *vbi_buf; | ||
423 | struct au0828_dmaqueue *dma_q = urb->context; | 520 | struct au0828_dmaqueue *dma_q = urb->context; |
521 | struct au0828_dmaqueue *vbi_dma_q = &dev->vbiq; | ||
424 | unsigned char *outp = NULL; | 522 | unsigned char *outp = NULL; |
523 | unsigned char *vbioutp = NULL; | ||
425 | int i, len = 0, rc = 1; | 524 | int i, len = 0, rc = 1; |
426 | unsigned char *p; | 525 | unsigned char *p; |
427 | unsigned char fbyte; | 526 | unsigned char fbyte; |
527 | unsigned int vbi_field_size; | ||
528 | unsigned int remain, lencopy; | ||
428 | 529 | ||
429 | if (!dev) | 530 | if (!dev) |
430 | return 0; | 531 | return 0; |
@@ -443,6 +544,10 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) | |||
443 | if (buf != NULL) | 544 | if (buf != NULL) |
444 | outp = videobuf_to_vmalloc(&buf->vb); | 545 | outp = videobuf_to_vmalloc(&buf->vb); |
445 | 546 | ||
547 | vbi_buf = dev->isoc_ctl.vbi_buf; | ||
548 | if (vbi_buf != NULL) | ||
549 | vbioutp = videobuf_to_vmalloc(&vbi_buf->vb); | ||
550 | |||
446 | for (i = 0; i < urb->number_of_packets; i++) { | 551 | for (i = 0; i < urb->number_of_packets; i++) { |
447 | int status = urb->iso_frame_desc[i].status; | 552 | int status = urb->iso_frame_desc[i].status; |
448 | 553 | ||
@@ -472,6 +577,19 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) | |||
472 | au0828_isocdbg("Video frame %s\n", | 577 | au0828_isocdbg("Video frame %s\n", |
473 | (fbyte & 0x40) ? "odd" : "even"); | 578 | (fbyte & 0x40) ? "odd" : "even"); |
474 | if (!(fbyte & 0x40)) { | 579 | if (!(fbyte & 0x40)) { |
580 | /* VBI */ | ||
581 | if (vbi_buf != NULL) | ||
582 | vbi_buffer_filled(dev, | ||
583 | vbi_dma_q, | ||
584 | vbi_buf); | ||
585 | vbi_get_next_buf(vbi_dma_q, &vbi_buf); | ||
586 | if (vbi_buf == NULL) | ||
587 | vbioutp = NULL; | ||
588 | else | ||
589 | vbioutp = videobuf_to_vmalloc( | ||
590 | &vbi_buf->vb); | ||
591 | |||
592 | /* Video */ | ||
475 | if (buf != NULL) | 593 | if (buf != NULL) |
476 | buffer_filled(dev, dma_q, buf); | 594 | buffer_filled(dev, dma_q, buf); |
477 | get_next_buf(dma_q, &buf); | 595 | get_next_buf(dma_q, &buf); |
@@ -488,9 +606,36 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) | |||
488 | buf->top_field = 0; | 606 | buf->top_field = 0; |
489 | } | 607 | } |
490 | 608 | ||
609 | if (vbi_buf != NULL) { | ||
610 | if (fbyte & 0x40) | ||
611 | vbi_buf->top_field = 1; | ||
612 | else | ||
613 | vbi_buf->top_field = 0; | ||
614 | } | ||
615 | |||
616 | dev->vbi_read = 0; | ||
617 | vbi_dma_q->pos = 0; | ||
491 | dma_q->pos = 0; | 618 | dma_q->pos = 0; |
492 | } | 619 | } |
493 | if (buf != NULL) | 620 | |
621 | vbi_field_size = dev->vbi_width * dev->vbi_height * 2; | ||
622 | if (dev->vbi_read < vbi_field_size) { | ||
623 | remain = vbi_field_size - dev->vbi_read; | ||
624 | if (len < remain) | ||
625 | lencopy = len; | ||
626 | else | ||
627 | lencopy = remain; | ||
628 | |||
629 | if (vbi_buf != NULL) | ||
630 | au0828_copy_vbi(dev, vbi_dma_q, vbi_buf, p, | ||
631 | vbioutp, len); | ||
632 | |||
633 | len -= lencopy; | ||
634 | p += lencopy; | ||
635 | dev->vbi_read += lencopy; | ||
636 | } | ||
637 | |||
638 | if (dev->vbi_read >= vbi_field_size && buf != NULL) | ||
494 | au0828_copy_video(dev, dma_q, buf, p, outp, len); | 639 | au0828_copy_video(dev, dma_q, buf, p, outp, len); |
495 | } | 640 | } |
496 | return rc; | 641 | return rc; |
@@ -642,7 +787,7 @@ int au0828_analog_stream_enable(struct au0828_dev *d) | |||
642 | au0828_writereg(d, 0x114, 0xa0); | 787 | au0828_writereg(d, 0x114, 0xa0); |
643 | au0828_writereg(d, 0x115, 0x05); | 788 | au0828_writereg(d, 0x115, 0x05); |
644 | /* set y position */ | 789 | /* set y position */ |
645 | au0828_writereg(d, 0x112, 0x02); | 790 | au0828_writereg(d, 0x112, 0x00); |
646 | au0828_writereg(d, 0x113, 0x00); | 791 | au0828_writereg(d, 0x113, 0x00); |
647 | au0828_writereg(d, 0x116, 0xf2); | 792 | au0828_writereg(d, 0x116, 0xf2); |
648 | au0828_writereg(d, 0x117, 0x00); | 793 | au0828_writereg(d, 0x117, 0x00); |
@@ -703,47 +848,83 @@ void au0828_analog_unregister(struct au0828_dev *dev) | |||
703 | 848 | ||
704 | 849 | ||
705 | /* Usage lock check functions */ | 850 | /* Usage lock check functions */ |
706 | static int res_get(struct au0828_fh *fh) | 851 | static int res_get(struct au0828_fh *fh, unsigned int bit) |
707 | { | 852 | { |
708 | struct au0828_dev *dev = fh->dev; | 853 | struct au0828_dev *dev = fh->dev; |
709 | int rc = 0; | ||
710 | 854 | ||
711 | /* This instance already has stream_on */ | 855 | if (fh->resources & bit) |
712 | if (fh->stream_on) | 856 | /* have it already allocated */ |
713 | return rc; | 857 | return 1; |
714 | 858 | ||
715 | if (dev->stream_on) | 859 | /* is it free? */ |
716 | return -EBUSY; | 860 | mutex_lock(&dev->lock); |
861 | if (dev->resources & bit) { | ||
862 | /* no, someone else uses it */ | ||
863 | mutex_unlock(&dev->lock); | ||
864 | return 0; | ||
865 | } | ||
866 | /* it's free, grab it */ | ||
867 | fh->resources |= bit; | ||
868 | dev->resources |= bit; | ||
869 | dprintk(1, "res: get %d\n", bit); | ||
870 | mutex_unlock(&dev->lock); | ||
871 | return 1; | ||
872 | } | ||
717 | 873 | ||
718 | dev->stream_on = 1; | 874 | static int res_check(struct au0828_fh *fh, unsigned int bit) |
719 | fh->stream_on = 1; | 875 | { |
720 | return rc; | 876 | return fh->resources & bit; |
721 | } | 877 | } |
722 | 878 | ||
723 | static int res_check(struct au0828_fh *fh) | 879 | static int res_locked(struct au0828_dev *dev, unsigned int bit) |
724 | { | 880 | { |
725 | return fh->stream_on; | 881 | return dev->resources & bit; |
726 | } | 882 | } |
727 | 883 | ||
728 | static void res_free(struct au0828_fh *fh) | 884 | static void res_free(struct au0828_fh *fh, unsigned int bits) |
729 | { | 885 | { |
730 | struct au0828_dev *dev = fh->dev; | 886 | struct au0828_dev *dev = fh->dev; |
731 | 887 | ||
732 | fh->stream_on = 0; | 888 | BUG_ON((fh->resources & bits) != bits); |
733 | dev->stream_on = 0; | 889 | |
890 | mutex_lock(&dev->lock); | ||
891 | fh->resources &= ~bits; | ||
892 | dev->resources &= ~bits; | ||
893 | dprintk(1, "res: put %d\n", bits); | ||
894 | mutex_unlock(&dev->lock); | ||
895 | } | ||
896 | |||
897 | static int get_ressource(struct au0828_fh *fh) | ||
898 | { | ||
899 | switch (fh->type) { | ||
900 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
901 | return AU0828_RESOURCE_VIDEO; | ||
902 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
903 | return AU0828_RESOURCE_VBI; | ||
904 | default: | ||
905 | BUG(); | ||
906 | return 0; | ||
907 | } | ||
734 | } | 908 | } |
735 | 909 | ||
736 | static int au0828_v4l2_open(struct file *filp) | 910 | static int au0828_v4l2_open(struct file *filp) |
737 | { | 911 | { |
738 | int ret = 0; | 912 | int ret = 0; |
913 | struct video_device *vdev = video_devdata(filp); | ||
739 | struct au0828_dev *dev = video_drvdata(filp); | 914 | struct au0828_dev *dev = video_drvdata(filp); |
740 | struct au0828_fh *fh; | 915 | struct au0828_fh *fh; |
741 | int type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 916 | int type; |
742 | 917 | ||
743 | #ifdef VBI_IS_WORKING | 918 | switch (vdev->vfl_type) { |
744 | if (video_devdata(filp)->vfl_type == VFL_TYPE_GRABBER) | 919 | case VFL_TYPE_GRABBER: |
920 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
921 | break; | ||
922 | case VFL_TYPE_VBI: | ||
745 | type = V4L2_BUF_TYPE_VBI_CAPTURE; | 923 | type = V4L2_BUF_TYPE_VBI_CAPTURE; |
746 | #endif | 924 | break; |
925 | default: | ||
926 | return -EINVAL; | ||
927 | } | ||
747 | 928 | ||
748 | fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL); | 929 | fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL); |
749 | if (NULL == fh) { | 930 | if (NULL == fh) { |
@@ -781,10 +962,21 @@ static int au0828_v4l2_open(struct file *filp) | |||
781 | dev->users++; | 962 | dev->users++; |
782 | 963 | ||
783 | videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops, | 964 | videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops, |
784 | NULL, &dev->slock, fh->type, | 965 | NULL, &dev->slock, |
966 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
785 | V4L2_FIELD_INTERLACED, | 967 | V4L2_FIELD_INTERLACED, |
786 | sizeof(struct au0828_buffer), fh); | 968 | sizeof(struct au0828_buffer), fh); |
787 | 969 | ||
970 | /* VBI Setup */ | ||
971 | dev->vbi_width = 720; | ||
972 | dev->vbi_height = 1; | ||
973 | videobuf_queue_vmalloc_init(&fh->vb_vbiq, &au0828_vbi_qops, | ||
974 | NULL, &dev->slock, | ||
975 | V4L2_BUF_TYPE_VBI_CAPTURE, | ||
976 | V4L2_FIELD_SEQ_TB, | ||
977 | sizeof(struct au0828_buffer), fh); | ||
978 | |||
979 | |||
788 | return ret; | 980 | return ret; |
789 | } | 981 | } |
790 | 982 | ||
@@ -794,17 +986,19 @@ static int au0828_v4l2_close(struct file *filp) | |||
794 | struct au0828_fh *fh = filp->private_data; | 986 | struct au0828_fh *fh = filp->private_data; |
795 | struct au0828_dev *dev = fh->dev; | 987 | struct au0828_dev *dev = fh->dev; |
796 | 988 | ||
797 | mutex_lock(&dev->lock); | 989 | if (res_check(fh, AU0828_RESOURCE_VIDEO)) { |
798 | if (res_check(fh)) | ||
799 | res_free(fh); | ||
800 | |||
801 | if (dev->users == 1) { | ||
802 | videobuf_stop(&fh->vb_vidq); | 990 | videobuf_stop(&fh->vb_vidq); |
803 | videobuf_mmap_free(&fh->vb_vidq); | 991 | res_free(fh, AU0828_RESOURCE_VIDEO); |
992 | } | ||
993 | |||
994 | if (res_check(fh, AU0828_RESOURCE_VBI)) { | ||
995 | videobuf_stop(&fh->vb_vbiq); | ||
996 | res_free(fh, AU0828_RESOURCE_VBI); | ||
997 | } | ||
804 | 998 | ||
999 | if (dev->users == 1) { | ||
805 | if (dev->dev_state & DEV_DISCONNECTED) { | 1000 | if (dev->dev_state & DEV_DISCONNECTED) { |
806 | au0828_analog_unregister(dev); | 1001 | au0828_analog_unregister(dev); |
807 | mutex_unlock(&dev->lock); | ||
808 | kfree(dev); | 1002 | kfree(dev); |
809 | return 0; | 1003 | return 0; |
810 | } | 1004 | } |
@@ -823,10 +1017,11 @@ static int au0828_v4l2_close(struct file *filp) | |||
823 | printk(KERN_INFO "Au0828 can't set alternate to 0!\n"); | 1017 | printk(KERN_INFO "Au0828 can't set alternate to 0!\n"); |
824 | } | 1018 | } |
825 | 1019 | ||
1020 | videobuf_mmap_free(&fh->vb_vidq); | ||
1021 | videobuf_mmap_free(&fh->vb_vbiq); | ||
826 | kfree(fh); | 1022 | kfree(fh); |
827 | dev->users--; | 1023 | dev->users--; |
828 | wake_up_interruptible_nr(&dev->open, 1); | 1024 | wake_up_interruptible_nr(&dev->open, 1); |
829 | mutex_unlock(&dev->lock); | ||
830 | return 0; | 1025 | return 0; |
831 | } | 1026 | } |
832 | 1027 | ||
@@ -842,16 +1037,21 @@ static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf, | |||
842 | return rc; | 1037 | return rc; |
843 | 1038 | ||
844 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1039 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
845 | mutex_lock(&dev->lock); | 1040 | if (res_locked(dev, AU0828_RESOURCE_VIDEO)) |
846 | rc = res_get(fh); | 1041 | return -EBUSY; |
847 | mutex_unlock(&dev->lock); | ||
848 | |||
849 | if (unlikely(rc < 0)) | ||
850 | return rc; | ||
851 | 1042 | ||
852 | return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, | 1043 | return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, |
853 | filp->f_flags & O_NONBLOCK); | 1044 | filp->f_flags & O_NONBLOCK); |
854 | } | 1045 | } |
1046 | |||
1047 | if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { | ||
1048 | if (!res_get(fh, AU0828_RESOURCE_VBI)) | ||
1049 | return -EBUSY; | ||
1050 | |||
1051 | return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0, | ||
1052 | filp->f_flags & O_NONBLOCK); | ||
1053 | } | ||
1054 | |||
855 | return 0; | 1055 | return 0; |
856 | } | 1056 | } |
857 | 1057 | ||
@@ -865,17 +1065,17 @@ static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait) | |||
865 | if (rc < 0) | 1065 | if (rc < 0) |
866 | return rc; | 1066 | return rc; |
867 | 1067 | ||
868 | mutex_lock(&dev->lock); | 1068 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
869 | rc = res_get(fh); | 1069 | if (!res_get(fh, AU0828_RESOURCE_VIDEO)) |
870 | mutex_unlock(&dev->lock); | 1070 | return POLLERR; |
871 | 1071 | return videobuf_poll_stream(filp, &fh->vb_vidq, wait); | |
872 | if (unlikely(rc < 0)) | 1072 | } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { |
873 | return POLLERR; | 1073 | if (!res_get(fh, AU0828_RESOURCE_VBI)) |
874 | 1074 | return POLLERR; | |
875 | if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) | 1075 | return videobuf_poll_stream(filp, &fh->vb_vbiq, wait); |
1076 | } else { | ||
876 | return POLLERR; | 1077 | return POLLERR; |
877 | 1078 | } | |
878 | return videobuf_poll_stream(filp, &fh->vb_vidq, wait); | ||
879 | } | 1079 | } |
880 | 1080 | ||
881 | static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) | 1081 | static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) |
@@ -888,14 +1088,10 @@ static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) | |||
888 | if (rc < 0) | 1088 | if (rc < 0) |
889 | return rc; | 1089 | return rc; |
890 | 1090 | ||
891 | mutex_lock(&dev->lock); | 1091 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) |
892 | rc = res_get(fh); | 1092 | rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); |
893 | mutex_unlock(&dev->lock); | 1093 | else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) |
894 | 1094 | rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma); | |
895 | if (unlikely(rc < 0)) | ||
896 | return rc; | ||
897 | |||
898 | rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); | ||
899 | 1095 | ||
900 | return rc; | 1096 | return rc; |
901 | } | 1097 | } |
@@ -911,14 +1107,6 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, | |||
911 | maxwidth = 720; | 1107 | maxwidth = 720; |
912 | maxheight = 480; | 1108 | maxheight = 480; |
913 | 1109 | ||
914 | #ifdef VBI_IS_WORKING | ||
915 | if (format->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { | ||
916 | dprintk(1, "VBI format set: to be supported!\n"); | ||
917 | return 0; | ||
918 | } | ||
919 | if (format->type == V4L2_BUF_TYPE_VBI_CAPTURE) | ||
920 | return 0; | ||
921 | #endif | ||
922 | if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1110 | if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
923 | return -EINVAL; | 1111 | return -EINVAL; |
924 | 1112 | ||
@@ -999,9 +1187,7 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
999 | 1187 | ||
1000 | /*set the device capabilities */ | 1188 | /*set the device capabilities */ |
1001 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | | 1189 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | |
1002 | #ifdef VBI_IS_WORKING | ||
1003 | V4L2_CAP_VBI_CAPTURE | | 1190 | V4L2_CAP_VBI_CAPTURE | |
1004 | #endif | ||
1005 | V4L2_CAP_AUDIO | | 1191 | V4L2_CAP_AUDIO | |
1006 | V4L2_CAP_READWRITE | | 1192 | V4L2_CAP_READWRITE | |
1007 | V4L2_CAP_STREAMING | | 1193 | V4L2_CAP_STREAMING | |
@@ -1056,20 +1242,21 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
1056 | struct au0828_dev *dev = fh->dev; | 1242 | struct au0828_dev *dev = fh->dev; |
1057 | int rc; | 1243 | int rc; |
1058 | 1244 | ||
1245 | rc = check_dev(dev); | ||
1246 | if (rc < 0) | ||
1247 | return rc; | ||
1248 | |||
1249 | mutex_lock(&dev->lock); | ||
1250 | |||
1059 | if (videobuf_queue_is_busy(&fh->vb_vidq)) { | 1251 | if (videobuf_queue_is_busy(&fh->vb_vidq)) { |
1060 | printk(KERN_INFO "%s queue busy\n", __func__); | 1252 | printk(KERN_INFO "%s queue busy\n", __func__); |
1061 | rc = -EBUSY; | 1253 | rc = -EBUSY; |
1062 | goto out; | 1254 | goto out; |
1063 | } | 1255 | } |
1064 | 1256 | ||
1065 | if (dev->stream_on && !fh->stream_on) { | 1257 | rc = au0828_set_format(dev, VIDIOC_S_FMT, f); |
1066 | printk(KERN_INFO "%s device in use by another fh\n", __func__); | ||
1067 | rc = -EBUSY; | ||
1068 | goto out; | ||
1069 | } | ||
1070 | |||
1071 | return au0828_set_format(dev, VIDIOC_S_FMT, f); | ||
1072 | out: | 1258 | out: |
1259 | mutex_unlock(&dev->lock); | ||
1073 | return rc; | 1260 | return rc; |
1074 | } | 1261 | } |
1075 | 1262 | ||
@@ -1300,6 +1487,29 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
1300 | return 0; | 1487 | return 0; |
1301 | } | 1488 | } |
1302 | 1489 | ||
1490 | |||
1491 | /* RAW VBI ioctls */ | ||
1492 | |||
1493 | static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, | ||
1494 | struct v4l2_format *format) | ||
1495 | { | ||
1496 | struct au0828_fh *fh = priv; | ||
1497 | struct au0828_dev *dev = fh->dev; | ||
1498 | |||
1499 | format->fmt.vbi.samples_per_line = dev->vbi_width; | ||
1500 | format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; | ||
1501 | format->fmt.vbi.offset = 0; | ||
1502 | format->fmt.vbi.flags = 0; | ||
1503 | format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; | ||
1504 | |||
1505 | format->fmt.vbi.count[0] = dev->vbi_height; | ||
1506 | format->fmt.vbi.count[1] = dev->vbi_height; | ||
1507 | format->fmt.vbi.start[0] = 21; | ||
1508 | format->fmt.vbi.start[1] = 284; | ||
1509 | |||
1510 | return 0; | ||
1511 | } | ||
1512 | |||
1303 | static int vidioc_g_chip_ident(struct file *file, void *priv, | 1513 | static int vidioc_g_chip_ident(struct file *file, void *priv, |
1304 | struct v4l2_dbg_chip_ident *chip) | 1514 | struct v4l2_dbg_chip_ident *chip) |
1305 | { | 1515 | { |
@@ -1345,25 +1555,32 @@ static int vidioc_cropcap(struct file *file, void *priv, | |||
1345 | static int vidioc_streamon(struct file *file, void *priv, | 1555 | static int vidioc_streamon(struct file *file, void *priv, |
1346 | enum v4l2_buf_type type) | 1556 | enum v4l2_buf_type type) |
1347 | { | 1557 | { |
1348 | struct au0828_fh *fh = priv; | 1558 | struct au0828_fh *fh = priv; |
1349 | struct au0828_dev *dev = fh->dev; | 1559 | struct au0828_dev *dev = fh->dev; |
1350 | int rc; | 1560 | int rc = -EINVAL; |
1351 | 1561 | ||
1352 | rc = check_dev(dev); | 1562 | rc = check_dev(dev); |
1353 | if (rc < 0) | 1563 | if (rc < 0) |
1354 | return rc; | 1564 | return rc; |
1355 | 1565 | ||
1566 | if (unlikely(type != fh->type)) | ||
1567 | return -EINVAL; | ||
1568 | |||
1569 | dprintk(1, "vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n", | ||
1570 | fh, type, fh->resources, dev->resources); | ||
1571 | |||
1572 | if (unlikely(!res_get(fh, get_ressource(fh)))) | ||
1573 | return -EBUSY; | ||
1574 | |||
1356 | if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1575 | if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
1357 | au0828_analog_stream_enable(dev); | 1576 | au0828_analog_stream_enable(dev); |
1358 | v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1); | 1577 | v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1); |
1359 | } | 1578 | } |
1360 | 1579 | ||
1361 | mutex_lock(&dev->lock); | 1580 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1362 | rc = res_get(fh); | ||
1363 | |||
1364 | if (likely(rc >= 0)) | ||
1365 | rc = videobuf_streamon(&fh->vb_vidq); | 1581 | rc = videobuf_streamon(&fh->vb_vidq); |
1366 | mutex_unlock(&dev->lock); | 1582 | else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) |
1583 | rc = videobuf_streamon(&fh->vb_vbiq); | ||
1367 | 1584 | ||
1368 | return rc; | 1585 | return rc; |
1369 | } | 1586 | } |
@@ -1371,38 +1588,42 @@ static int vidioc_streamon(struct file *file, void *priv, | |||
1371 | static int vidioc_streamoff(struct file *file, void *priv, | 1588 | static int vidioc_streamoff(struct file *file, void *priv, |
1372 | enum v4l2_buf_type type) | 1589 | enum v4l2_buf_type type) |
1373 | { | 1590 | { |
1374 | struct au0828_fh *fh = priv; | 1591 | struct au0828_fh *fh = priv; |
1375 | struct au0828_dev *dev = fh->dev; | 1592 | struct au0828_dev *dev = fh->dev; |
1376 | int i; | 1593 | int rc; |
1377 | int ret; | 1594 | int i; |
1378 | int rc; | ||
1379 | 1595 | ||
1380 | rc = check_dev(dev); | 1596 | rc = check_dev(dev); |
1381 | if (rc < 0) | 1597 | if (rc < 0) |
1382 | return rc; | 1598 | return rc; |
1383 | 1599 | ||
1384 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1600 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && |
1601 | fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) | ||
1385 | return -EINVAL; | 1602 | return -EINVAL; |
1386 | if (type != fh->type) | 1603 | if (type != fh->type) |
1387 | return -EINVAL; | 1604 | return -EINVAL; |
1388 | 1605 | ||
1389 | if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1606 | dprintk(1, "vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n", |
1607 | fh, type, fh->resources, dev->resources); | ||
1608 | |||
1609 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1390 | v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); | 1610 | v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); |
1391 | ret = au0828_stream_interrupt(dev); | 1611 | rc = au0828_stream_interrupt(dev); |
1392 | if (ret != 0) | 1612 | if (rc != 0) |
1393 | return ret; | 1613 | return rc; |
1394 | } | ||
1395 | 1614 | ||
1396 | for (i = 0; i < AU0828_MAX_INPUT; i++) { | 1615 | for (i = 0; i < AU0828_MAX_INPUT; i++) { |
1397 | if (AUVI_INPUT(i).audio_setup == NULL) | 1616 | if (AUVI_INPUT(i).audio_setup == NULL) |
1398 | continue; | 1617 | continue; |
1399 | (AUVI_INPUT(i).audio_setup)(dev, 0); | 1618 | (AUVI_INPUT(i).audio_setup)(dev, 0); |
1400 | } | 1619 | } |
1401 | 1620 | ||
1402 | mutex_lock(&dev->lock); | 1621 | videobuf_streamoff(&fh->vb_vidq); |
1403 | videobuf_streamoff(&fh->vb_vidq); | 1622 | res_free(fh, AU0828_RESOURCE_VIDEO); |
1404 | res_free(fh); | 1623 | } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { |
1405 | mutex_unlock(&dev->lock); | 1624 | videobuf_streamoff(&fh->vb_vbiq); |
1625 | res_free(fh, AU0828_RESOURCE_VBI); | ||
1626 | } | ||
1406 | 1627 | ||
1407 | return 0; | 1628 | return 0; |
1408 | } | 1629 | } |
@@ -1527,19 +1748,11 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { | |||
1527 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 1748 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, |
1528 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | 1749 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, |
1529 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | 1750 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, |
1530 | #ifdef VBI_IS_WORKING | ||
1531 | .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, | 1751 | .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, |
1532 | .vidioc_try_fmt_vbi_cap = vidioc_s_fmt_vbi_cap, | 1752 | .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, |
1533 | .vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap, | ||
1534 | #endif | ||
1535 | .vidioc_g_audio = vidioc_g_audio, | 1753 | .vidioc_g_audio = vidioc_g_audio, |
1536 | .vidioc_s_audio = vidioc_s_audio, | 1754 | .vidioc_s_audio = vidioc_s_audio, |
1537 | .vidioc_cropcap = vidioc_cropcap, | 1755 | .vidioc_cropcap = vidioc_cropcap, |
1538 | #ifdef VBI_IS_WORKING | ||
1539 | .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap, | ||
1540 | .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, | ||
1541 | .vidioc_s_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, | ||
1542 | #endif | ||
1543 | .vidioc_reqbufs = vidioc_reqbufs, | 1756 | .vidioc_reqbufs = vidioc_reqbufs, |
1544 | .vidioc_querybuf = vidioc_querybuf, | 1757 | .vidioc_querybuf = vidioc_querybuf, |
1545 | .vidioc_qbuf = vidioc_qbuf, | 1758 | .vidioc_qbuf = vidioc_qbuf, |
@@ -1621,8 +1834,11 @@ int au0828_analog_register(struct au0828_dev *dev, | |||
1621 | spin_lock_init(&dev->slock); | 1834 | spin_lock_init(&dev->slock); |
1622 | mutex_init(&dev->lock); | 1835 | mutex_init(&dev->lock); |
1623 | 1836 | ||
1837 | /* init video dma queues */ | ||
1624 | INIT_LIST_HEAD(&dev->vidq.active); | 1838 | INIT_LIST_HEAD(&dev->vidq.active); |
1625 | INIT_LIST_HEAD(&dev->vidq.queued); | 1839 | INIT_LIST_HEAD(&dev->vidq.queued); |
1840 | INIT_LIST_HEAD(&dev->vbiq.active); | ||
1841 | INIT_LIST_HEAD(&dev->vbiq.queued); | ||
1626 | 1842 | ||
1627 | dev->width = NTSC_STD_W; | 1843 | dev->width = NTSC_STD_W; |
1628 | dev->height = NTSC_STD_H; | 1844 | dev->height = NTSC_STD_H; |
@@ -1638,26 +1854,23 @@ int au0828_analog_register(struct au0828_dev *dev, | |||
1638 | return -ENOMEM; | 1854 | return -ENOMEM; |
1639 | } | 1855 | } |
1640 | 1856 | ||
1641 | #ifdef VBI_IS_WORKING | 1857 | /* allocate the VBI struct */ |
1642 | dev->vbi_dev = video_device_alloc(); | 1858 | dev->vbi_dev = video_device_alloc(); |
1643 | if (NULL == dev->vbi_dev) { | 1859 | if (NULL == dev->vbi_dev) { |
1644 | dprintk(1, "Can't allocate vbi_device.\n"); | 1860 | dprintk(1, "Can't allocate vbi_device.\n"); |
1645 | kfree(dev->vdev); | 1861 | kfree(dev->vdev); |
1646 | return -ENOMEM; | 1862 | return -ENOMEM; |
1647 | } | 1863 | } |
1648 | #endif | ||
1649 | 1864 | ||
1650 | /* Fill the video capture device struct */ | 1865 | /* Fill the video capture device struct */ |
1651 | *dev->vdev = au0828_video_template; | 1866 | *dev->vdev = au0828_video_template; |
1652 | dev->vdev->parent = &dev->usbdev->dev; | 1867 | dev->vdev->parent = &dev->usbdev->dev; |
1653 | strcpy(dev->vdev->name, "au0828a video"); | 1868 | strcpy(dev->vdev->name, "au0828a video"); |
1654 | 1869 | ||
1655 | #ifdef VBI_IS_WORKING | ||
1656 | /* Setup the VBI device */ | 1870 | /* Setup the VBI device */ |
1657 | *dev->vbi_dev = au0828_video_template; | 1871 | *dev->vbi_dev = au0828_video_template; |
1658 | dev->vbi_dev->parent = &dev->usbdev->dev; | 1872 | dev->vbi_dev->parent = &dev->usbdev->dev; |
1659 | strcpy(dev->vbi_dev->name, "au0828a vbi"); | 1873 | strcpy(dev->vbi_dev->name, "au0828a vbi"); |
1660 | #endif | ||
1661 | 1874 | ||
1662 | /* Register the v4l2 device */ | 1875 | /* Register the v4l2 device */ |
1663 | video_set_drvdata(dev->vdev, dev); | 1876 | video_set_drvdata(dev->vdev, dev); |
@@ -1669,7 +1882,6 @@ int au0828_analog_register(struct au0828_dev *dev, | |||
1669 | return -ENODEV; | 1882 | return -ENODEV; |
1670 | } | 1883 | } |
1671 | 1884 | ||
1672 | #ifdef VBI_IS_WORKING | ||
1673 | /* Register the vbi device */ | 1885 | /* Register the vbi device */ |
1674 | video_set_drvdata(dev->vbi_dev, dev); | 1886 | video_set_drvdata(dev->vbi_dev, dev); |
1675 | retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1); | 1887 | retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1); |
@@ -1680,7 +1892,6 @@ int au0828_analog_register(struct au0828_dev *dev, | |||
1680 | video_device_release(dev->vdev); | 1892 | video_device_release(dev->vdev); |
1681 | return -ENODEV; | 1893 | return -ENODEV; |
1682 | } | 1894 | } |
1683 | #endif | ||
1684 | 1895 | ||
1685 | dprintk(1, "%s completed!\n", __func__); | 1896 | dprintk(1, "%s completed!\n", __func__); |
1686 | 1897 | ||
diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index 207f32dec6a6..9905bc4f5f59 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h | |||
@@ -60,6 +60,10 @@ | |||
60 | 60 | ||
61 | #define AU0828_MAX_INPUT 4 | 61 | #define AU0828_MAX_INPUT 4 |
62 | 62 | ||
63 | /* au0828 resource types (used for res_get/res_lock etc */ | ||
64 | #define AU0828_RESOURCE_VIDEO 0x01 | ||
65 | #define AU0828_RESOURCE_VBI 0x02 | ||
66 | |||
63 | enum au0828_itype { | 67 | enum au0828_itype { |
64 | AU0828_VMUX_UNDEFINED = 0, | 68 | AU0828_VMUX_UNDEFINED = 0, |
65 | AU0828_VMUX_COMPOSITE, | 69 | AU0828_VMUX_COMPOSITE, |
@@ -115,8 +119,10 @@ enum au0828_dev_state { | |||
115 | 119 | ||
116 | struct au0828_fh { | 120 | struct au0828_fh { |
117 | struct au0828_dev *dev; | 121 | struct au0828_dev *dev; |
118 | unsigned int stream_on:1; /* Locks streams */ | 122 | unsigned int resources; |
123 | |||
119 | struct videobuf_queue vb_vidq; | 124 | struct videobuf_queue vb_vidq; |
125 | struct videobuf_queue vb_vbiq; | ||
120 | enum v4l2_buf_type type; | 126 | enum v4l2_buf_type type; |
121 | }; | 127 | }; |
122 | 128 | ||
@@ -145,7 +151,8 @@ struct au0828_usb_isoc_ctl { | |||
145 | int tmp_buf_len; | 151 | int tmp_buf_len; |
146 | 152 | ||
147 | /* Stores already requested buffers */ | 153 | /* Stores already requested buffers */ |
148 | struct au0828_buffer *buf; | 154 | struct au0828_buffer *buf; |
155 | struct au0828_buffer *vbi_buf; | ||
149 | 156 | ||
150 | /* Stores the number of received fields */ | 157 | /* Stores the number of received fields */ |
151 | int nfields; | 158 | int nfields; |
@@ -194,11 +201,14 @@ struct au0828_dev { | |||
194 | /* Analog */ | 201 | /* Analog */ |
195 | struct v4l2_device v4l2_dev; | 202 | struct v4l2_device v4l2_dev; |
196 | int users; | 203 | int users; |
197 | unsigned int stream_on:1; /* Locks streams */ | 204 | unsigned int resources; /* resources in use */ |
198 | struct video_device *vdev; | 205 | struct video_device *vdev; |
199 | struct video_device *vbi_dev; | 206 | struct video_device *vbi_dev; |
200 | int width; | 207 | int width; |
201 | int height; | 208 | int height; |
209 | int vbi_width; | ||
210 | int vbi_height; | ||
211 | u32 vbi_read; | ||
202 | u32 field_size; | 212 | u32 field_size; |
203 | u32 frame_size; | 213 | u32 frame_size; |
204 | u32 bytesperline; | 214 | u32 bytesperline; |
@@ -219,6 +229,7 @@ struct au0828_dev { | |||
219 | 229 | ||
220 | /* Isoc control struct */ | 230 | /* Isoc control struct */ |
221 | struct au0828_dmaqueue vidq; | 231 | struct au0828_dmaqueue vidq; |
232 | struct au0828_dmaqueue vbiq; | ||
222 | struct au0828_usb_isoc_ctl isoc_ctl; | 233 | struct au0828_usb_isoc_ctl isoc_ctl; |
223 | spinlock_t slock; | 234 | spinlock_t slock; |
224 | 235 | ||
@@ -278,6 +289,9 @@ void au0828_analog_unregister(struct au0828_dev *dev); | |||
278 | extern int au0828_dvb_register(struct au0828_dev *dev); | 289 | extern int au0828_dvb_register(struct au0828_dev *dev); |
279 | extern void au0828_dvb_unregister(struct au0828_dev *dev); | 290 | extern void au0828_dvb_unregister(struct au0828_dev *dev); |
280 | 291 | ||
292 | /* au0828-vbi.c */ | ||
293 | extern struct videobuf_queue_ops au0828_vbi_qops; | ||
294 | |||
281 | #define dprintk(level, fmt, arg...)\ | 295 | #define dprintk(level, fmt, arg...)\ |
282 | do { if (au0828_debug & level)\ | 296 | do { if (au0828_debug & level)\ |
283 | printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\ | 297 | printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\ |
diff --git a/drivers/media/video/bt8xx/bttv-risc.c b/drivers/media/video/bt8xx/bttv-risc.c index c24b1c100e13..0fa9f39f37a3 100644 --- a/drivers/media/video/bt8xx/bttv-risc.c +++ b/drivers/media/video/bt8xx/bttv-risc.c | |||
@@ -583,7 +583,7 @@ bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf | |||
583 | 583 | ||
584 | BUG_ON(in_interrupt()); | 584 | BUG_ON(in_interrupt()); |
585 | videobuf_waiton(&buf->vb,0,0); | 585 | videobuf_waiton(&buf->vb,0,0); |
586 | videobuf_dma_unmap(q, dma); | 586 | videobuf_dma_unmap(q->dev, dma); |
587 | videobuf_dma_free(dma); | 587 | videobuf_dma_free(dma); |
588 | btcx_riscmem_free(btv->c.pci,&buf->bottom); | 588 | btcx_riscmem_free(btv->c.pci,&buf->bottom); |
589 | btcx_riscmem_free(btv->c.pci,&buf->top); | 589 | btcx_riscmem_free(btv->c.pci,&buf->top); |
diff --git a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c index ef1f89399983..58d193ff591c 100644 --- a/drivers/media/video/cpia_usb.c +++ b/drivers/media/video/cpia_usb.c | |||
@@ -584,7 +584,6 @@ static void cpia_disconnect(struct usb_interface *intf) | |||
584 | { | 584 | { |
585 | struct cam_data *cam = usb_get_intfdata(intf); | 585 | struct cam_data *cam = usb_get_intfdata(intf); |
586 | struct usb_cpia *ucpia; | 586 | struct usb_cpia *ucpia; |
587 | struct usb_device *udev; | ||
588 | 587 | ||
589 | usb_set_intfdata(intf, NULL); | 588 | usb_set_intfdata(intf, NULL); |
590 | if (!cam) | 589 | if (!cam) |
@@ -606,8 +605,6 @@ static void cpia_disconnect(struct usb_interface *intf) | |||
606 | if (waitqueue_active(&ucpia->wq_stream)) | 605 | if (waitqueue_active(&ucpia->wq_stream)) |
607 | wake_up_interruptible(&ucpia->wq_stream); | 606 | wake_up_interruptible(&ucpia->wq_stream); |
608 | 607 | ||
609 | udev = interface_to_usbdev(intf); | ||
610 | |||
611 | ucpia->curbuff = ucpia->workbuff = NULL; | 608 | ucpia->curbuff = ucpia->workbuff = NULL; |
612 | 609 | ||
613 | vfree(ucpia->buffers[2]); | 610 | vfree(ucpia->buffers[2]); |
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 20eaf38ba959..d6792405f8d3 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c | |||
@@ -1081,7 +1081,7 @@ long cx18_v4l2_ioctl(struct file *filp, unsigned int cmd, | |||
1081 | unsigned long arg) | 1081 | unsigned long arg) |
1082 | { | 1082 | { |
1083 | struct video_device *vfd = video_devdata(filp); | 1083 | struct video_device *vfd = video_devdata(filp); |
1084 | struct cx18_open_id *id = (struct cx18_open_id *)filp->private_data; | 1084 | struct cx18_open_id *id = filp->private_data; |
1085 | struct cx18 *cx = id->cx; | 1085 | struct cx18 *cx = id->cx; |
1086 | long res; | 1086 | long res; |
1087 | 1087 | ||
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index d639186f645d..2014daedee8b 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c | |||
@@ -408,10 +408,18 @@ struct cx23885_subid cx23885_subids[] = { | |||
408 | .card = CX23885_BOARD_HAUPPAUGE_HVR1275, | 408 | .card = CX23885_BOARD_HAUPPAUGE_HVR1275, |
409 | }, { | 409 | }, { |
410 | .subvendor = 0x0070, | 410 | .subvendor = 0x0070, |
411 | .subdevice = 0x221d, | ||
412 | .card = CX23885_BOARD_HAUPPAUGE_HVR1275, | ||
413 | }, { | ||
414 | .subvendor = 0x0070, | ||
411 | .subdevice = 0x2251, | 415 | .subdevice = 0x2251, |
412 | .card = CX23885_BOARD_HAUPPAUGE_HVR1255, | 416 | .card = CX23885_BOARD_HAUPPAUGE_HVR1255, |
413 | }, { | 417 | }, { |
414 | .subvendor = 0x0070, | 418 | .subvendor = 0x0070, |
419 | .subdevice = 0x2259, | ||
420 | .card = CX23885_BOARD_HAUPPAUGE_HVR1255, | ||
421 | }, { | ||
422 | .subvendor = 0x0070, | ||
415 | .subdevice = 0x2291, | 423 | .subdevice = 0x2291, |
416 | .card = CX23885_BOARD_HAUPPAUGE_HVR1210, | 424 | .card = CX23885_BOARD_HAUPPAUGE_HVR1210, |
417 | }, { | 425 | }, { |
@@ -419,6 +427,38 @@ struct cx23885_subid cx23885_subids[] = { | |||
419 | .subdevice = 0x2295, | 427 | .subdevice = 0x2295, |
420 | .card = CX23885_BOARD_HAUPPAUGE_HVR1210, | 428 | .card = CX23885_BOARD_HAUPPAUGE_HVR1210, |
421 | }, { | 429 | }, { |
430 | .subvendor = 0x0070, | ||
431 | .subdevice = 0x2299, | ||
432 | .card = CX23885_BOARD_HAUPPAUGE_HVR1210, | ||
433 | }, { | ||
434 | .subvendor = 0x0070, | ||
435 | .subdevice = 0x229d, | ||
436 | .card = CX23885_BOARD_HAUPPAUGE_HVR1210, /* HVR1215 */ | ||
437 | }, { | ||
438 | .subvendor = 0x0070, | ||
439 | .subdevice = 0x22f0, | ||
440 | .card = CX23885_BOARD_HAUPPAUGE_HVR1210, | ||
441 | }, { | ||
442 | .subvendor = 0x0070, | ||
443 | .subdevice = 0x22f1, | ||
444 | .card = CX23885_BOARD_HAUPPAUGE_HVR1255, | ||
445 | }, { | ||
446 | .subvendor = 0x0070, | ||
447 | .subdevice = 0x22f2, | ||
448 | .card = CX23885_BOARD_HAUPPAUGE_HVR1275, | ||
449 | }, { | ||
450 | .subvendor = 0x0070, | ||
451 | .subdevice = 0x22f3, | ||
452 | .card = CX23885_BOARD_HAUPPAUGE_HVR1210, /* HVR1215 */ | ||
453 | }, { | ||
454 | .subvendor = 0x0070, | ||
455 | .subdevice = 0x22f4, | ||
456 | .card = CX23885_BOARD_HAUPPAUGE_HVR1210, | ||
457 | }, { | ||
458 | .subvendor = 0x0070, | ||
459 | .subdevice = 0x22f5, | ||
460 | .card = CX23885_BOARD_HAUPPAUGE_HVR1210, /* HVR1215 */ | ||
461 | }, { | ||
422 | .subvendor = 0x14f1, | 462 | .subvendor = 0x14f1, |
423 | .subdevice = 0x8651, | 463 | .subdevice = 0x8651, |
424 | .card = CX23885_BOARD_MYGICA_X8506, | 464 | .card = CX23885_BOARD_MYGICA_X8506, |
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index 0dde57e96d30..ff76f64edac1 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c | |||
@@ -1142,7 +1142,7 @@ void cx23885_free_buffer(struct videobuf_queue *q, struct cx23885_buffer *buf) | |||
1142 | 1142 | ||
1143 | BUG_ON(in_interrupt()); | 1143 | BUG_ON(in_interrupt()); |
1144 | videobuf_waiton(&buf->vb, 0, 0); | 1144 | videobuf_waiton(&buf->vb, 0, 0); |
1145 | videobuf_dma_unmap(q, dma); | 1145 | videobuf_dma_unmap(q->dev, dma); |
1146 | videobuf_dma_free(dma); | 1146 | videobuf_dma_free(dma); |
1147 | btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); | 1147 | btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); |
1148 | buf->vb.state = VIDEOBUF_NEEDS_INIT; | 1148 | buf->vb.state = VIDEOBUF_NEEDS_INIT; |
@@ -1953,8 +1953,12 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, | |||
1953 | goto fail_irq; | 1953 | goto fail_irq; |
1954 | } | 1954 | } |
1955 | 1955 | ||
1956 | err = request_irq(pci_dev->irq, cx23885_irq, | 1956 | if (!pci_enable_msi(pci_dev)) |
1957 | IRQF_SHARED | IRQF_DISABLED, dev->name, dev); | 1957 | err = request_irq(pci_dev->irq, cx23885_irq, |
1958 | IRQF_DISABLED, dev->name, dev); | ||
1959 | else | ||
1960 | err = request_irq(pci_dev->irq, cx23885_irq, | ||
1961 | IRQF_SHARED | IRQF_DISABLED, dev->name, dev); | ||
1958 | if (err < 0) { | 1962 | if (err < 0) { |
1959 | printk(KERN_ERR "%s: can't get IRQ %d\n", | 1963 | printk(KERN_ERR "%s: can't get IRQ %d\n", |
1960 | dev->name, pci_dev->irq); | 1964 | dev->name, pci_dev->irq); |
@@ -2000,6 +2004,7 @@ static void __devexit cx23885_finidev(struct pci_dev *pci_dev) | |||
2000 | 2004 | ||
2001 | /* unregister stuff */ | 2005 | /* unregister stuff */ |
2002 | free_irq(pci_dev->irq, dev); | 2006 | free_irq(pci_dev->irq, dev); |
2007 | pci_disable_msi(pci_dev); | ||
2003 | 2008 | ||
2004 | cx23885_dev_unregister(dev); | 2009 | cx23885_dev_unregister(dev); |
2005 | v4l2_device_unregister(v4l2_dev); | 2010 | v4l2_device_unregister(v4l2_dev); |
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 0a199d774d9b..3d70af283881 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c | |||
@@ -991,7 +991,7 @@ static int dvb_register(struct cx23885_tsport *port) | |||
991 | ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, | 991 | ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, |
992 | &dev->pci->dev, adapter_nr, 0, | 992 | &dev->pci->dev, adapter_nr, 0, |
993 | cx23885_dvb_fe_ioctl_override); | 993 | cx23885_dvb_fe_ioctl_override); |
994 | if (!ret) | 994 | if (ret) |
995 | return ret; | 995 | return ret; |
996 | 996 | ||
997 | /* init CI & MAC */ | 997 | /* init CI & MAC */ |
diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c index 5de6ba98f7a8..d0b1613ede2f 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/video/cx23885/cx23885-input.c | |||
@@ -37,161 +37,55 @@ | |||
37 | 37 | ||
38 | #include <linux/input.h> | 38 | #include <linux/input.h> |
39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
40 | #include <media/ir-common.h> | 40 | #include <media/ir-core.h> |
41 | #include <media/v4l2-subdev.h> | 41 | #include <media/v4l2-subdev.h> |
42 | 42 | ||
43 | #include "cx23885.h" | 43 | #include "cx23885.h" |
44 | 44 | ||
45 | #define RC5_BITS 14 | ||
46 | #define RC5_HALF_BITS (2*RC5_BITS) | ||
47 | #define RC5_HALF_BITS_MASK ((1 << RC5_HALF_BITS) - 1) | ||
48 | |||
49 | #define RC5_START_BITS_NORMAL 0x3 /* Command range 0 - 63 */ | ||
50 | #define RC5_START_BITS_EXTENDED 0x2 /* Command range 64 - 127 */ | ||
51 | |||
52 | #define RC5_EXTENDED_COMMAND_OFFSET 64 | ||
53 | |||
54 | #define MODULE_NAME "cx23885" | 45 | #define MODULE_NAME "cx23885" |
55 | 46 | ||
56 | static inline unsigned int rc5_command(u32 rc5_baseband) | 47 | static void convert_measurement(u32 x, struct ir_raw_event *y) |
57 | { | 48 | { |
58 | return RC5_INSTR(rc5_baseband) + | 49 | if (x == V4L2_SUBDEV_IR_PULSE_RX_SEQ_END) { |
59 | ((RC5_START(rc5_baseband) == RC5_START_BITS_EXTENDED) | 50 | y->pulse = false; |
60 | ? RC5_EXTENDED_COMMAND_OFFSET : 0); | 51 | y->duration = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS; |
61 | } | ||
62 | |||
63 | static void cx23885_input_process_raw_rc5(struct cx23885_dev *dev) | ||
64 | { | ||
65 | struct card_ir *ir_input = dev->ir_input; | ||
66 | unsigned int code, command; | ||
67 | u32 rc5; | ||
68 | |||
69 | /* Ignore codes that are too short to be valid RC-5 */ | ||
70 | if (ir_input->last_bit < (RC5_HALF_BITS - 1)) | ||
71 | return; | ||
72 | |||
73 | /* The library has the manchester coding backwards; XOR to adapt. */ | ||
74 | code = (ir_input->code & RC5_HALF_BITS_MASK) ^ RC5_HALF_BITS_MASK; | ||
75 | rc5 = ir_rc5_decode(code); | ||
76 | |||
77 | switch (RC5_START(rc5)) { | ||
78 | case RC5_START_BITS_NORMAL: | ||
79 | break; | ||
80 | case RC5_START_BITS_EXTENDED: | ||
81 | /* Don't allow if the remote only emits standard commands */ | ||
82 | if (ir_input->start == RC5_START_BITS_NORMAL) | ||
83 | return; | ||
84 | break; | ||
85 | default: | ||
86 | return; | 52 | return; |
87 | } | 53 | } |
88 | 54 | ||
89 | if (ir_input->addr != RC5_ADDR(rc5)) | 55 | y->pulse = (x & V4L2_SUBDEV_IR_PULSE_LEVEL_MASK) ? true : false; |
90 | return; | 56 | y->duration = x & V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS; |
91 | |||
92 | /* Don't generate a keypress for RC-5 auto-repeated keypresses */ | ||
93 | command = rc5_command(rc5); | ||
94 | if (RC5_TOGGLE(rc5) != RC5_TOGGLE(ir_input->last_rc5) || | ||
95 | command != rc5_command(ir_input->last_rc5) || | ||
96 | /* Catch T == 0, CMD == 0 (e.g. '0') as first keypress after init */ | ||
97 | RC5_START(ir_input->last_rc5) == 0) { | ||
98 | /* This keypress is differnet: not an auto repeat */ | ||
99 | ir_input_nokey(ir_input->dev, &ir_input->ir); | ||
100 | ir_input_keydown(ir_input->dev, &ir_input->ir, command); | ||
101 | } | ||
102 | ir_input->last_rc5 = rc5; | ||
103 | |||
104 | /* Schedule when we should do the key up event: ir_input_nokey() */ | ||
105 | mod_timer(&ir_input->timer_keyup, | ||
106 | jiffies + msecs_to_jiffies(ir_input->rc5_key_timeout)); | ||
107 | } | 57 | } |
108 | 58 | ||
109 | static void cx23885_input_next_pulse_width_rc5(struct cx23885_dev *dev, | 59 | static void cx23885_input_process_measurements(struct cx23885_dev *dev, |
110 | u32 ns_pulse) | 60 | bool overrun) |
111 | { | 61 | { |
112 | const int rc5_quarterbit_ns = 444444; /* 32 cycles/36 kHz/2 = 444 us */ | 62 | struct cx23885_kernel_ir *kernel_ir = dev->kernel_ir; |
113 | struct card_ir *ir_input = dev->ir_input; | 63 | struct ir_raw_event kernel_ir_event; |
114 | int i, level, quarterbits, halfbits; | ||
115 | |||
116 | if (!ir_input->active) { | ||
117 | ir_input->active = 1; | ||
118 | /* assume an initial space that we may not detect or measure */ | ||
119 | ir_input->code = 0; | ||
120 | ir_input->last_bit = 0; | ||
121 | } | ||
122 | 64 | ||
123 | if (ns_pulse == V4L2_SUBDEV_IR_PULSE_RX_SEQ_END) { | 65 | u32 sd_ir_data[64]; |
124 | ir_input->last_bit++; /* Account for the final space */ | 66 | ssize_t num; |
125 | ir_input->active = 0; | ||
126 | cx23885_input_process_raw_rc5(dev); | ||
127 | return; | ||
128 | } | ||
129 | |||
130 | level = (ns_pulse & V4L2_SUBDEV_IR_PULSE_LEVEL_MASK) ? 1 : 0; | ||
131 | |||
132 | /* Skip any leading space to sync to the start bit */ | ||
133 | if (ir_input->last_bit == 0 && level == 0) | ||
134 | return; | ||
135 | |||
136 | /* | ||
137 | * With valid RC-5 we can get up to two consecutive half-bits in a | ||
138 | * single pulse measurment. Experiments have shown that the duration | ||
139 | * of a half-bit can vary. Make sure we always end up with an even | ||
140 | * number of quarter bits at the same level (mark or space). | ||
141 | */ | ||
142 | ns_pulse &= V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS; | ||
143 | quarterbits = ns_pulse / rc5_quarterbit_ns; | ||
144 | if (quarterbits & 1) | ||
145 | quarterbits++; | ||
146 | halfbits = quarterbits / 2; | ||
147 | |||
148 | for (i = 0; i < halfbits; i++) { | ||
149 | ir_input->last_bit++; | ||
150 | ir_input->code |= (level << ir_input->last_bit); | ||
151 | |||
152 | if (ir_input->last_bit >= RC5_HALF_BITS-1) { | ||
153 | ir_input->active = 0; | ||
154 | cx23885_input_process_raw_rc5(dev); | ||
155 | /* | ||
156 | * If level is 1, a leading mark is invalid for RC5. | ||
157 | * If level is 0, we scan past extra intial space. | ||
158 | * Either way we don't want to reactivate collecting | ||
159 | * marks or spaces here with any left over half-bits. | ||
160 | */ | ||
161 | break; | ||
162 | } | ||
163 | } | ||
164 | } | ||
165 | |||
166 | static void cx23885_input_process_pulse_widths_rc5(struct cx23885_dev *dev, | ||
167 | bool add_eom) | ||
168 | { | ||
169 | struct card_ir *ir_input = dev->ir_input; | ||
170 | struct ir_input_state *ir_input_state = &ir_input->ir; | ||
171 | |||
172 | u32 ns_pulse[RC5_HALF_BITS+1]; | ||
173 | ssize_t num = 0; | ||
174 | int count, i; | 67 | int count, i; |
68 | bool handle = false; | ||
175 | 69 | ||
176 | do { | 70 | do { |
177 | v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) ns_pulse, | 71 | num = 0; |
178 | sizeof(ns_pulse), &num); | 72 | v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) sd_ir_data, |
73 | sizeof(sd_ir_data), &num); | ||
179 | 74 | ||
180 | count = num / sizeof(u32); | 75 | count = num / sizeof(u32); |
181 | 76 | ||
182 | /* Append an end of Rx seq, if the caller requested */ | 77 | for (i = 0; i < count; i++) { |
183 | if (add_eom && count < ARRAY_SIZE(ns_pulse)) { | 78 | convert_measurement(sd_ir_data[i], &kernel_ir_event); |
184 | ns_pulse[count] = V4L2_SUBDEV_IR_PULSE_RX_SEQ_END; | 79 | ir_raw_event_store(kernel_ir->inp_dev, |
185 | count++; | 80 | &kernel_ir_event); |
81 | handle = true; | ||
186 | } | 82 | } |
187 | |||
188 | /* Just drain the Rx FIFO, if we're called, but not RC-5 */ | ||
189 | if (ir_input_state->ir_type != IR_TYPE_RC5) | ||
190 | continue; | ||
191 | |||
192 | for (i = 0; i < count; i++) | ||
193 | cx23885_input_next_pulse_width_rc5(dev, ns_pulse[i]); | ||
194 | } while (num != 0); | 83 | } while (num != 0); |
84 | |||
85 | if (overrun) | ||
86 | ir_raw_event_reset(kernel_ir->inp_dev); | ||
87 | else if (handle) | ||
88 | ir_raw_event_handle(kernel_ir->inp_dev); | ||
195 | } | 89 | } |
196 | 90 | ||
197 | void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events) | 91 | void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events) |
@@ -230,7 +124,7 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events) | |||
230 | } | 124 | } |
231 | 125 | ||
232 | if (data_available) | 126 | if (data_available) |
233 | cx23885_input_process_pulse_widths_rc5(dev, overrun); | 127 | cx23885_input_process_measurements(dev, overrun); |
234 | 128 | ||
235 | if (overrun) { | 129 | if (overrun) { |
236 | /* If there was a FIFO overrun, clear & restart the device */ | 130 | /* If there was a FIFO overrun, clear & restart the device */ |
@@ -241,34 +135,15 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events) | |||
241 | } | 135 | } |
242 | } | 136 | } |
243 | 137 | ||
244 | static void cx23885_input_ir_start(struct cx23885_dev *dev) | 138 | static int cx23885_input_ir_start(struct cx23885_dev *dev) |
245 | { | 139 | { |
246 | struct card_ir *ir_input = dev->ir_input; | ||
247 | struct ir_input_state *ir_input_state = &ir_input->ir; | ||
248 | struct v4l2_subdev_ir_parameters params; | 140 | struct v4l2_subdev_ir_parameters params; |
249 | 141 | ||
250 | if (dev->sd_ir == NULL) | 142 | if (dev->sd_ir == NULL) |
251 | return; | 143 | return -ENODEV; |
252 | 144 | ||
253 | atomic_set(&dev->ir_input_stopping, 0); | 145 | atomic_set(&dev->ir_input_stopping, 0); |
254 | 146 | ||
255 | /* keyup timer set up, if needed */ | ||
256 | switch (dev->board) { | ||
257 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | ||
258 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | ||
259 | setup_timer(&ir_input->timer_keyup, | ||
260 | ir_rc5_timer_keyup, /* Not actually RC-5 specific */ | ||
261 | (unsigned long) ir_input); | ||
262 | if (ir_input_state->ir_type == IR_TYPE_RC5) { | ||
263 | /* | ||
264 | * RC-5 repeats a held key every | ||
265 | * 64 bits * (2 * 32/36000) sec/bit = 113.778 ms | ||
266 | */ | ||
267 | ir_input->rc5_key_timeout = 115; | ||
268 | } | ||
269 | break; | ||
270 | } | ||
271 | |||
272 | v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, ¶ms); | 147 | v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, ¶ms); |
273 | switch (dev->board) { | 148 | switch (dev->board) { |
274 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | 149 | case CX23885_BOARD_HAUPPAUGE_HVR1850: |
@@ -299,11 +174,21 @@ static void cx23885_input_ir_start(struct cx23885_dev *dev) | |||
299 | break; | 174 | break; |
300 | } | 175 | } |
301 | v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, ¶ms); | 176 | v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, ¶ms); |
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static int cx23885_input_ir_open(void *priv) | ||
181 | { | ||
182 | struct cx23885_kernel_ir *kernel_ir = priv; | ||
183 | |||
184 | if (kernel_ir->cx == NULL) | ||
185 | return -ENODEV; | ||
186 | |||
187 | return cx23885_input_ir_start(kernel_ir->cx); | ||
302 | } | 188 | } |
303 | 189 | ||
304 | static void cx23885_input_ir_stop(struct cx23885_dev *dev) | 190 | static void cx23885_input_ir_stop(struct cx23885_dev *dev) |
305 | { | 191 | { |
306 | struct card_ir *ir_input = dev->ir_input; | ||
307 | struct v4l2_subdev_ir_parameters params; | 192 | struct v4l2_subdev_ir_parameters params; |
308 | 193 | ||
309 | if (dev->sd_ir == NULL) | 194 | if (dev->sd_ir == NULL) |
@@ -327,21 +212,26 @@ static void cx23885_input_ir_stop(struct cx23885_dev *dev) | |||
327 | } | 212 | } |
328 | 213 | ||
329 | flush_scheduled_work(); | 214 | flush_scheduled_work(); |
215 | } | ||
330 | 216 | ||
331 | switch (dev->board) { | 217 | static void cx23885_input_ir_close(void *priv) |
332 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | 218 | { |
333 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | 219 | struct cx23885_kernel_ir *kernel_ir = priv; |
334 | del_timer_sync(&ir_input->timer_keyup); | 220 | |
335 | break; | 221 | if (kernel_ir->cx != NULL) |
336 | } | 222 | cx23885_input_ir_stop(kernel_ir->cx); |
337 | } | 223 | } |
338 | 224 | ||
339 | int cx23885_input_init(struct cx23885_dev *dev) | 225 | int cx23885_input_init(struct cx23885_dev *dev) |
340 | { | 226 | { |
341 | struct card_ir *ir; | 227 | struct cx23885_kernel_ir *kernel_ir; |
342 | struct input_dev *input_dev; | 228 | struct input_dev *inp_dev; |
343 | char *ir_codes = NULL; | 229 | struct ir_dev_props *props; |
344 | int ir_type, ir_addr, ir_start; | 230 | |
231 | char *rc_map; | ||
232 | enum rc_driver_type driver_type; | ||
233 | unsigned long allowed_protos; | ||
234 | |||
345 | int ret; | 235 | int ret; |
346 | 236 | ||
347 | /* | 237 | /* |
@@ -354,53 +244,59 @@ int cx23885_input_init(struct cx23885_dev *dev) | |||
354 | switch (dev->board) { | 244 | switch (dev->board) { |
355 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | 245 | case CX23885_BOARD_HAUPPAUGE_HVR1850: |
356 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | 246 | case CX23885_BOARD_HAUPPAUGE_HVR1290: |
357 | /* Parameters for the grey Hauppauge remote for the HVR-1850 */ | 247 | /* Integrated CX23888 IR controller */ |
358 | ir_codes = RC_MAP_HAUPPAUGE_NEW; | 248 | driver_type = RC_DRIVER_IR_RAW; |
359 | ir_type = IR_TYPE_RC5; | 249 | allowed_protos = IR_TYPE_ALL; |
360 | ir_addr = 0x1e; /* RC-5 system bits emitted by the remote */ | 250 | /* The grey Hauppauge RC-5 remote */ |
361 | ir_start = RC5_START_BITS_NORMAL; /* A basic RC-5 remote */ | 251 | rc_map = RC_MAP_RC5_HAUPPAUGE_NEW; |
362 | break; | 252 | break; |
363 | } | 253 | default: |
364 | if (ir_codes == NULL) | ||
365 | return -ENODEV; | 254 | return -ENODEV; |
366 | |||
367 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | ||
368 | input_dev = input_allocate_device(); | ||
369 | if (!ir || !input_dev) { | ||
370 | ret = -ENOMEM; | ||
371 | goto err_out_free; | ||
372 | } | 255 | } |
373 | 256 | ||
374 | ir->dev = input_dev; | 257 | /* cx23885 board instance kernel IR state */ |
375 | ir->addr = ir_addr; | 258 | kernel_ir = kzalloc(sizeof(struct cx23885_kernel_ir), GFP_KERNEL); |
376 | ir->start = ir_start; | 259 | if (kernel_ir == NULL) |
260 | return -ENOMEM; | ||
377 | 261 | ||
378 | /* init input device */ | 262 | kernel_ir->cx = dev; |
379 | snprintf(ir->name, sizeof(ir->name), "cx23885 IR (%s)", | 263 | kernel_ir->name = kasprintf(GFP_KERNEL, "cx23885 IR (%s)", |
380 | cx23885_boards[dev->board].name); | 264 | cx23885_boards[dev->board].name); |
381 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(dev->pci)); | 265 | kernel_ir->phys = kasprintf(GFP_KERNEL, "pci-%s/ir0", |
266 | pci_name(dev->pci)); | ||
382 | 267 | ||
383 | ret = ir_input_init(input_dev, &ir->ir, ir_type); | 268 | /* input device */ |
384 | if (ret < 0) | 269 | inp_dev = input_allocate_device(); |
270 | if (inp_dev == NULL) { | ||
271 | ret = -ENOMEM; | ||
385 | goto err_out_free; | 272 | goto err_out_free; |
273 | } | ||
386 | 274 | ||
387 | input_dev->name = ir->name; | 275 | kernel_ir->inp_dev = inp_dev; |
388 | input_dev->phys = ir->phys; | 276 | inp_dev->name = kernel_ir->name; |
389 | input_dev->id.bustype = BUS_PCI; | 277 | inp_dev->phys = kernel_ir->phys; |
390 | input_dev->id.version = 1; | 278 | inp_dev->id.bustype = BUS_PCI; |
279 | inp_dev->id.version = 1; | ||
391 | if (dev->pci->subsystem_vendor) { | 280 | if (dev->pci->subsystem_vendor) { |
392 | input_dev->id.vendor = dev->pci->subsystem_vendor; | 281 | inp_dev->id.vendor = dev->pci->subsystem_vendor; |
393 | input_dev->id.product = dev->pci->subsystem_device; | 282 | inp_dev->id.product = dev->pci->subsystem_device; |
394 | } else { | 283 | } else { |
395 | input_dev->id.vendor = dev->pci->vendor; | 284 | inp_dev->id.vendor = dev->pci->vendor; |
396 | input_dev->id.product = dev->pci->device; | 285 | inp_dev->id.product = dev->pci->device; |
397 | } | 286 | } |
398 | input_dev->dev.parent = &dev->pci->dev; | 287 | inp_dev->dev.parent = &dev->pci->dev; |
399 | 288 | ||
400 | dev->ir_input = ir; | 289 | /* kernel ir device properties */ |
401 | cx23885_input_ir_start(dev); | 290 | props = &kernel_ir->props; |
402 | 291 | props->driver_type = driver_type; | |
403 | ret = ir_input_register(ir->dev, ir_codes, NULL, MODULE_NAME); | 292 | props->allowed_protos = allowed_protos; |
293 | props->priv = kernel_ir; | ||
294 | props->open = cx23885_input_ir_open; | ||
295 | props->close = cx23885_input_ir_close; | ||
296 | |||
297 | /* Go */ | ||
298 | dev->kernel_ir = kernel_ir; | ||
299 | ret = ir_input_register(inp_dev, rc_map, props, MODULE_NAME); | ||
404 | if (ret) | 300 | if (ret) |
405 | goto err_out_stop; | 301 | goto err_out_stop; |
406 | 302 | ||
@@ -408,9 +304,12 @@ int cx23885_input_init(struct cx23885_dev *dev) | |||
408 | 304 | ||
409 | err_out_stop: | 305 | err_out_stop: |
410 | cx23885_input_ir_stop(dev); | 306 | cx23885_input_ir_stop(dev); |
411 | dev->ir_input = NULL; | 307 | dev->kernel_ir = NULL; |
308 | /* TODO: double check clean-up of kernel_ir->inp_dev */ | ||
412 | err_out_free: | 309 | err_out_free: |
413 | kfree(ir); | 310 | kfree(kernel_ir->phys); |
311 | kfree(kernel_ir->name); | ||
312 | kfree(kernel_ir); | ||
414 | return ret; | 313 | return ret; |
415 | } | 314 | } |
416 | 315 | ||
@@ -419,9 +318,11 @@ void cx23885_input_fini(struct cx23885_dev *dev) | |||
419 | /* Always stop the IR hardware from generating interrupts */ | 318 | /* Always stop the IR hardware from generating interrupts */ |
420 | cx23885_input_ir_stop(dev); | 319 | cx23885_input_ir_stop(dev); |
421 | 320 | ||
422 | if (dev->ir_input == NULL) | 321 | if (dev->kernel_ir == NULL) |
423 | return; | 322 | return; |
424 | ir_input_unregister(dev->ir_input->dev); | 323 | ir_input_unregister(dev->kernel_ir->inp_dev); |
425 | kfree(dev->ir_input); | 324 | kfree(dev->kernel_ir->phys); |
426 | dev->ir_input = NULL; | 325 | kfree(dev->kernel_ir->name); |
326 | kfree(dev->kernel_ir); | ||
327 | dev->kernel_ir = NULL; | ||
427 | } | 328 | } |
diff --git a/drivers/media/video/cx23885/cx23885-ir.c b/drivers/media/video/cx23885/cx23885-ir.c index 9a677eb080af..6ceabd4fba07 100644 --- a/drivers/media/video/cx23885/cx23885-ir.c +++ b/drivers/media/video/cx23885/cx23885-ir.c | |||
@@ -53,7 +53,7 @@ void cx23885_ir_rx_work_handler(struct work_struct *work) | |||
53 | if (events == 0) | 53 | if (events == 0) |
54 | return; | 54 | return; |
55 | 55 | ||
56 | if (dev->ir_input) | 56 | if (dev->kernel_ir) |
57 | cx23885_input_rx_work_handler(dev, events); | 57 | cx23885_input_rx_work_handler(dev, events); |
58 | } | 58 | } |
59 | 59 | ||
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 8d6a55e54ee7..a33f2b71467b 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <media/tveeprom.h> | 30 | #include <media/tveeprom.h> |
31 | #include <media/videobuf-dma-sg.h> | 31 | #include <media/videobuf-dma-sg.h> |
32 | #include <media/videobuf-dvb.h> | 32 | #include <media/videobuf-dvb.h> |
33 | #include <media/ir-core.h> | ||
33 | 34 | ||
34 | #include "btcx-risc.h" | 35 | #include "btcx-risc.h" |
35 | #include "cx23885-reg.h" | 36 | #include "cx23885-reg.h" |
@@ -304,6 +305,15 @@ struct cx23885_tsport { | |||
304 | void *port_priv; | 305 | void *port_priv; |
305 | }; | 306 | }; |
306 | 307 | ||
308 | struct cx23885_kernel_ir { | ||
309 | struct cx23885_dev *cx; | ||
310 | char *name; | ||
311 | char *phys; | ||
312 | |||
313 | struct input_dev *inp_dev; | ||
314 | struct ir_dev_props props; | ||
315 | }; | ||
316 | |||
307 | struct cx23885_dev { | 317 | struct cx23885_dev { |
308 | atomic_t refcount; | 318 | atomic_t refcount; |
309 | struct v4l2_device v4l2_dev; | 319 | struct v4l2_device v4l2_dev; |
@@ -363,7 +373,7 @@ struct cx23885_dev { | |||
363 | struct work_struct ir_tx_work; | 373 | struct work_struct ir_tx_work; |
364 | unsigned long ir_tx_notifications; | 374 | unsigned long ir_tx_notifications; |
365 | 375 | ||
366 | struct card_ir *ir_input; | 376 | struct cx23885_kernel_ir *kernel_ir; |
367 | atomic_t ir_input_stopping; | 377 | atomic_t ir_input_stopping; |
368 | 378 | ||
369 | /* V4l */ | 379 | /* V4l */ |
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 33082c96745e..4f383cdf5296 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c | |||
@@ -54,6 +54,12 @@ | |||
54 | Data type declarations - Can be moded to a header file later | 54 | Data type declarations - Can be moded to a header file later |
55 | ****************************************************************************/ | 55 | ****************************************************************************/ |
56 | 56 | ||
57 | struct cx88_audio_buffer { | ||
58 | unsigned int bpl; | ||
59 | struct btcx_riscmem risc; | ||
60 | struct videobuf_dmabuf dma; | ||
61 | }; | ||
62 | |||
57 | struct cx88_audio_dev { | 63 | struct cx88_audio_dev { |
58 | struct cx88_core *core; | 64 | struct cx88_core *core; |
59 | struct cx88_dmaqueue q; | 65 | struct cx88_dmaqueue q; |
@@ -75,7 +81,7 @@ struct cx88_audio_dev { | |||
75 | 81 | ||
76 | struct videobuf_dmabuf *dma_risc; | 82 | struct videobuf_dmabuf *dma_risc; |
77 | 83 | ||
78 | struct cx88_buffer *buf; | 84 | struct cx88_audio_buffer *buf; |
79 | 85 | ||
80 | struct snd_pcm_substream *substream; | 86 | struct snd_pcm_substream *substream; |
81 | }; | 87 | }; |
@@ -123,7 +129,7 @@ MODULE_PARM_DESC(debug,"enable debug messages"); | |||
123 | 129 | ||
124 | static int _cx88_start_audio_dma(snd_cx88_card_t *chip) | 130 | static int _cx88_start_audio_dma(snd_cx88_card_t *chip) |
125 | { | 131 | { |
126 | struct cx88_buffer *buf = chip->buf; | 132 | struct cx88_audio_buffer *buf = chip->buf; |
127 | struct cx88_core *core=chip->core; | 133 | struct cx88_core *core=chip->core; |
128 | struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25]; | 134 | struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25]; |
129 | 135 | ||
@@ -283,7 +289,7 @@ static int dsp_buffer_free(snd_cx88_card_t *chip) | |||
283 | BUG_ON(!chip->dma_size); | 289 | BUG_ON(!chip->dma_size); |
284 | 290 | ||
285 | dprintk(2,"Freeing buffer\n"); | 291 | dprintk(2,"Freeing buffer\n"); |
286 | videobuf_sg_dma_unmap(&chip->pci->dev, chip->dma_risc); | 292 | videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc); |
287 | videobuf_dma_free(chip->dma_risc); | 293 | videobuf_dma_free(chip->dma_risc); |
288 | btcx_riscmem_free(chip->pci,&chip->buf->risc); | 294 | btcx_riscmem_free(chip->pci,&chip->buf->risc); |
289 | kfree(chip->buf); | 295 | kfree(chip->buf); |
@@ -376,7 +382,7 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream, | |||
376 | snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); | 382 | snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); |
377 | struct videobuf_dmabuf *dma; | 383 | struct videobuf_dmabuf *dma; |
378 | 384 | ||
379 | struct cx88_buffer *buf; | 385 | struct cx88_audio_buffer *buf; |
380 | int ret; | 386 | int ret; |
381 | 387 | ||
382 | if (substream->runtime->dma_area) { | 388 | if (substream->runtime->dma_area) { |
@@ -391,30 +397,25 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream, | |||
391 | BUG_ON(!chip->dma_size); | 397 | BUG_ON(!chip->dma_size); |
392 | BUG_ON(chip->num_periods & (chip->num_periods-1)); | 398 | BUG_ON(chip->num_periods & (chip->num_periods-1)); |
393 | 399 | ||
394 | buf = videobuf_sg_alloc(sizeof(*buf)); | 400 | buf = kzalloc(sizeof(*buf), GFP_KERNEL); |
395 | if (NULL == buf) | 401 | if (NULL == buf) |
396 | return -ENOMEM; | 402 | return -ENOMEM; |
397 | 403 | ||
398 | buf->vb.memory = V4L2_MEMORY_MMAP; | 404 | buf->bpl = chip->period_size; |
399 | buf->vb.field = V4L2_FIELD_NONE; | ||
400 | buf->vb.width = chip->period_size; | ||
401 | buf->bpl = chip->period_size; | ||
402 | buf->vb.height = chip->num_periods; | ||
403 | buf->vb.size = chip->dma_size; | ||
404 | 405 | ||
405 | dma = videobuf_to_dma(&buf->vb); | 406 | dma = &buf->dma; |
406 | videobuf_dma_init(dma); | 407 | videobuf_dma_init(dma); |
407 | ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE, | 408 | ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE, |
408 | (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT)); | 409 | (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT)); |
409 | if (ret < 0) | 410 | if (ret < 0) |
410 | goto error; | 411 | goto error; |
411 | 412 | ||
412 | ret = videobuf_sg_dma_map(&chip->pci->dev, dma); | 413 | ret = videobuf_dma_map(&chip->pci->dev, dma); |
413 | if (ret < 0) | 414 | if (ret < 0) |
414 | goto error; | 415 | goto error; |
415 | 416 | ||
416 | ret = cx88_risc_databuffer(chip->pci, &buf->risc, dma->sglist, | 417 | ret = cx88_risc_databuffer(chip->pci, &buf->risc, dma->sglist, |
417 | buf->vb.width, buf->vb.height, 1); | 418 | chip->period_size, chip->num_periods, 1); |
418 | if (ret < 0) | 419 | if (ret < 0) |
419 | goto error; | 420 | goto error; |
420 | 421 | ||
@@ -422,12 +423,10 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream, | |||
422 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC); | 423 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC); |
423 | buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | 424 | buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); |
424 | 425 | ||
425 | buf->vb.state = VIDEOBUF_PREPARED; | ||
426 | |||
427 | chip->buf = buf; | 426 | chip->buf = buf; |
428 | chip->dma_risc = dma; | 427 | chip->dma_risc = dma; |
429 | 428 | ||
430 | substream->runtime->dma_area = chip->dma_risc->vmalloc; | 429 | substream->runtime->dma_area = chip->dma_risc->vaddr; |
431 | substream->runtime->dma_bytes = chip->dma_size; | 430 | substream->runtime->dma_bytes = chip->dma_size; |
432 | substream->runtime->dma_addr = 0; | 431 | substream->runtime->dma_addr = 0; |
433 | return 0; | 432 | return 0; |
@@ -740,7 +739,7 @@ static int __devinit snd_cx88_create(struct snd_card *card, | |||
740 | 739 | ||
741 | pci_set_master(pci); | 740 | pci_set_master(pci); |
742 | 741 | ||
743 | chip = (snd_cx88_card_t *) card->private_data; | 742 | chip = card->private_data; |
744 | 743 | ||
745 | core = cx88_core_get(pci); | 744 | core = cx88_core_get(pci); |
746 | if (NULL == core) { | 745 | if (NULL == core) { |
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 2918a6e38fe8..e8416b76da67 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
@@ -45,6 +45,10 @@ static unsigned int latency = UNSET; | |||
45 | module_param(latency,int,0444); | 45 | module_param(latency,int,0444); |
46 | MODULE_PARM_DESC(latency,"pci latency timer"); | 46 | MODULE_PARM_DESC(latency,"pci latency timer"); |
47 | 47 | ||
48 | static int disable_ir; | ||
49 | module_param(disable_ir, int, 0444); | ||
50 | MODULE_PARM_DESC(latency, "Disable IR support"); | ||
51 | |||
48 | #define info_printk(core, fmt, arg...) \ | 52 | #define info_printk(core, fmt, arg...) \ |
49 | printk(KERN_INFO "%s: " fmt, core->name , ## arg) | 53 | printk(KERN_INFO "%s: " fmt, core->name , ## arg) |
50 | 54 | ||
@@ -3498,7 +3502,10 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) | |||
3498 | } | 3502 | } |
3499 | 3503 | ||
3500 | cx88_card_setup(core); | 3504 | cx88_card_setup(core); |
3501 | cx88_ir_init(core, pci); | 3505 | if (!disable_ir) { |
3506 | cx88_i2c_init_ir(core); | ||
3507 | cx88_ir_init(core, pci); | ||
3508 | } | ||
3502 | 3509 | ||
3503 | return core; | 3510 | return core; |
3504 | } | 3511 | } |
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 8b21457111b1..85eb266fb351 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c | |||
@@ -218,7 +218,7 @@ cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf) | |||
218 | 218 | ||
219 | BUG_ON(in_interrupt()); | 219 | BUG_ON(in_interrupt()); |
220 | videobuf_waiton(&buf->vb,0,0); | 220 | videobuf_waiton(&buf->vb,0,0); |
221 | videobuf_dma_unmap(q, dma); | 221 | videobuf_dma_unmap(q->dev, dma); |
222 | videobuf_dma_free(dma); | 222 | videobuf_dma_free(dma); |
223 | btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); | 223 | btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); |
224 | buf->vb.state = VIDEOBUF_NEEDS_INIT; | 224 | buf->vb.state = VIDEOBUF_NEEDS_INIT; |
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index fb39f1184558..375ad53f7961 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c | |||
@@ -181,6 +181,11 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) | |||
181 | } else | 181 | } else |
182 | printk("%s: i2c register FAILED\n", core->name); | 182 | printk("%s: i2c register FAILED\n", core->name); |
183 | 183 | ||
184 | return core->i2c_rc; | ||
185 | } | ||
186 | |||
187 | void cx88_i2c_init_ir(struct cx88_core *core) | ||
188 | { | ||
184 | /* Instantiate the IR receiver device, if present */ | 189 | /* Instantiate the IR receiver device, if present */ |
185 | if (0 == core->i2c_rc) { | 190 | if (0 == core->i2c_rc) { |
186 | struct i2c_board_info info; | 191 | struct i2c_board_info info; |
@@ -207,7 +212,6 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) | |||
207 | } | 212 | } |
208 | } | 213 | } |
209 | } | 214 | } |
210 | return core->i2c_rc; | ||
211 | } | 215 | } |
212 | 216 | ||
213 | /* ----------------------------------------------------------------------- */ | 217 | /* ----------------------------------------------------------------------- */ |
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index e185289e446c..eccc5e49a350 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | 31 | ||
32 | #include "cx88.h" | 32 | #include "cx88.h" |
33 | #include <media/ir-core.h> | ||
33 | #include <media/ir-common.h> | 34 | #include <media/ir-common.h> |
34 | 35 | ||
35 | #define MODULE_NAME "cx88xx" | 36 | #define MODULE_NAME "cx88xx" |
@@ -39,8 +40,8 @@ | |||
39 | struct cx88_IR { | 40 | struct cx88_IR { |
40 | struct cx88_core *core; | 41 | struct cx88_core *core; |
41 | struct input_dev *input; | 42 | struct input_dev *input; |
42 | struct ir_input_state ir; | ||
43 | struct ir_dev_props props; | 43 | struct ir_dev_props props; |
44 | u64 ir_type; | ||
44 | 45 | ||
45 | int users; | 46 | int users; |
46 | 47 | ||
@@ -51,7 +52,6 @@ struct cx88_IR { | |||
51 | u32 sampling; | 52 | u32 sampling; |
52 | u32 samples[16]; | 53 | u32 samples[16]; |
53 | int scount; | 54 | int scount; |
54 | unsigned long release; | ||
55 | 55 | ||
56 | /* poll external decoder */ | 56 | /* poll external decoder */ |
57 | int polling; | 57 | int polling; |
@@ -125,29 +125,21 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) | |||
125 | 125 | ||
126 | data = (data << 4) | ((gpio_key & 0xf0) >> 4); | 126 | data = (data << 4) | ((gpio_key & 0xf0) >> 4); |
127 | 127 | ||
128 | ir_input_keydown(ir->input, &ir->ir, data); | 128 | ir_keydown(ir->input, data, 0); |
129 | ir_input_nokey(ir->input, &ir->ir); | ||
130 | 129 | ||
131 | } else if (ir->mask_keydown) { | 130 | } else if (ir->mask_keydown) { |
132 | /* bit set on keydown */ | 131 | /* bit set on keydown */ |
133 | if (gpio & ir->mask_keydown) { | 132 | if (gpio & ir->mask_keydown) |
134 | ir_input_keydown(ir->input, &ir->ir, data); | 133 | ir_keydown(ir->input, data, 0); |
135 | } else { | ||
136 | ir_input_nokey(ir->input, &ir->ir); | ||
137 | } | ||
138 | 134 | ||
139 | } else if (ir->mask_keyup) { | 135 | } else if (ir->mask_keyup) { |
140 | /* bit cleared on keydown */ | 136 | /* bit cleared on keydown */ |
141 | if (0 == (gpio & ir->mask_keyup)) { | 137 | if (0 == (gpio & ir->mask_keyup)) |
142 | ir_input_keydown(ir->input, &ir->ir, data); | 138 | ir_keydown(ir->input, data, 0); |
143 | } else { | ||
144 | ir_input_nokey(ir->input, &ir->ir); | ||
145 | } | ||
146 | 139 | ||
147 | } else { | 140 | } else { |
148 | /* can't distinguish keydown/up :-/ */ | 141 | /* can't distinguish keydown/up :-/ */ |
149 | ir_input_keydown(ir->input, &ir->ir, data); | 142 | ir_keydown(ir->input, data, 0); |
150 | ir_input_nokey(ir->input, &ir->ir); | ||
151 | } | 143 | } |
152 | } | 144 | } |
153 | 145 | ||
@@ -439,9 +431,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
439 | snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name); | 431 | snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name); |
440 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci)); | 432 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci)); |
441 | 433 | ||
442 | err = ir_input_init(input_dev, &ir->ir, ir_type); | 434 | ir->ir_type = ir_type; |
443 | if (err < 0) | ||
444 | goto err_out_free; | ||
445 | 435 | ||
446 | input_dev->name = ir->name; | 436 | input_dev->name = ir->name; |
447 | input_dev->phys = ir->phys; | 437 | input_dev->phys = ir->phys; |
@@ -516,8 +506,6 @@ void cx88_ir_irq(struct cx88_core *core) | |||
516 | } | 506 | } |
517 | if (!ir->scount) { | 507 | if (!ir->scount) { |
518 | /* nothing to sample */ | 508 | /* nothing to sample */ |
519 | if (ir->ir.keypressed && time_after(jiffies, ir->release)) | ||
520 | ir_input_nokey(ir->input, &ir->ir); | ||
521 | return; | 509 | return; |
522 | } | 510 | } |
523 | 511 | ||
@@ -553,7 +541,7 @@ void cx88_ir_irq(struct cx88_core *core) | |||
553 | 541 | ||
554 | if (ircode == 0) { /* key still pressed */ | 542 | if (ircode == 0) { /* key still pressed */ |
555 | ir_dprintk("pulse distance decoded repeat code\n"); | 543 | ir_dprintk("pulse distance decoded repeat code\n"); |
556 | ir->release = jiffies + msecs_to_jiffies(120); | 544 | ir_repeat(ir->input); |
557 | break; | 545 | break; |
558 | } | 546 | } |
559 | 547 | ||
@@ -567,10 +555,8 @@ void cx88_ir_irq(struct cx88_core *core) | |||
567 | break; | 555 | break; |
568 | } | 556 | } |
569 | 557 | ||
570 | ir_dprintk("Key Code: %x\n", (ircode >> 16) & 0x7f); | 558 | ir_dprintk("Key Code: %x\n", (ircode >> 16) & 0xff); |
571 | 559 | ir_keydown(ir->input, (ircode >> 16) & 0xff, 0); | |
572 | ir_input_keydown(ir->input, &ir->ir, (ircode >> 16) & 0x7f); | ||
573 | ir->release = jiffies + msecs_to_jiffies(120); | ||
574 | break; | 560 | break; |
575 | case CX88_BOARD_HAUPPAUGE: | 561 | case CX88_BOARD_HAUPPAUGE: |
576 | case CX88_BOARD_HAUPPAUGE_DVB_T1: | 562 | case CX88_BOARD_HAUPPAUGE_DVB_T1: |
@@ -606,16 +592,16 @@ void cx88_ir_irq(struct cx88_core *core) | |||
606 | if ( dev != 0x1e && dev != 0x1f ) | 592 | if ( dev != 0x1e && dev != 0x1f ) |
607 | /* not a hauppauge remote */ | 593 | /* not a hauppauge remote */ |
608 | break; | 594 | break; |
609 | ir_input_keydown(ir->input, &ir->ir, code); | 595 | ir_keydown(ir->input, code, toggle); |
610 | ir->release = jiffies + msecs_to_jiffies(120); | ||
611 | break; | 596 | break; |
612 | case CX88_BOARD_PINNACLE_PCTV_HD_800i: | 597 | case CX88_BOARD_PINNACLE_PCTV_HD_800i: |
613 | ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); | 598 | ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); |
614 | ir_dprintk("biphase decoded: %x\n", ircode); | 599 | ir_dprintk("biphase decoded: %x\n", ircode); |
615 | if ((ircode & 0xfffff000) != 0x3000) | 600 | if ((ircode & 0xfffff000) != 0x3000) |
616 | break; | 601 | break; |
617 | ir_input_keydown(ir->input, &ir->ir, ircode & 0x3f); | 602 | /* Note: bit 0x800 being the toggle is assumed, not checked |
618 | ir->release = jiffies + msecs_to_jiffies(120); | 603 | with real hardware */ |
604 | ir_keydown(ir->input, ircode & 0x3f, ircode & 0x0800 ? 1 : 0); | ||
619 | break; | 605 | break; |
620 | } | 606 | } |
621 | 607 | ||
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index bdb03d336536..33d161a11725 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
@@ -636,6 +636,7 @@ extern struct videobuf_queue_ops cx8800_vbi_qops; | |||
636 | /* cx88-i2c.c */ | 636 | /* cx88-i2c.c */ |
637 | 637 | ||
638 | extern int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci); | 638 | extern int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci); |
639 | extern void cx88_i2c_init_ir(struct cx88_core *core); | ||
639 | 640 | ||
640 | 641 | ||
641 | /* ----------------------------------------------------------- */ | 642 | /* ----------------------------------------------------------- */ |
diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c index 0f505086774c..5b176bd7afdb 100644 --- a/drivers/media/video/dabusb.c +++ b/drivers/media/video/dabusb.c | |||
@@ -706,16 +706,11 @@ static long dabusb_ioctl (struct file *file, unsigned int cmd, unsigned long arg | |||
706 | switch (cmd) { | 706 | switch (cmd) { |
707 | 707 | ||
708 | case IOCTL_DAB_BULK: | 708 | case IOCTL_DAB_BULK: |
709 | pbulk = kmalloc(sizeof (bulk_transfer_t), GFP_KERNEL); | 709 | pbulk = memdup_user((void __user *)arg, |
710 | sizeof(bulk_transfer_t)); | ||
710 | 711 | ||
711 | if (!pbulk) { | 712 | if (IS_ERR(pbulk)) { |
712 | ret = -ENOMEM; | 713 | ret = PTR_ERR(pbulk); |
713 | break; | ||
714 | } | ||
715 | |||
716 | if (copy_from_user (pbulk, (void __user *) arg, sizeof (bulk_transfer_t))) { | ||
717 | ret = -EFAULT; | ||
718 | kfree (pbulk); | ||
719 | break; | 714 | break; |
720 | } | 715 | } |
721 | 716 | ||
diff --git a/drivers/media/video/davinci/Kconfig b/drivers/media/video/davinci/Kconfig new file mode 100644 index 000000000000..6b1954035649 --- /dev/null +++ b/drivers/media/video/davinci/Kconfig | |||
@@ -0,0 +1,93 @@ | |||
1 | config DISPLAY_DAVINCI_DM646X_EVM | ||
2 | tristate "DM646x EVM Video Display" | ||
3 | depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM | ||
4 | select VIDEOBUF_DMA_CONTIG | ||
5 | select VIDEO_DAVINCI_VPIF | ||
6 | select VIDEO_ADV7343 | ||
7 | select VIDEO_THS7303 | ||
8 | help | ||
9 | Support for DM6467 based display device. | ||
10 | |||
11 | To compile this driver as a module, choose M here: the | ||
12 | module will be called vpif_display. | ||
13 | |||
14 | config CAPTURE_DAVINCI_DM646X_EVM | ||
15 | tristate "DM646x EVM Video Capture" | ||
16 | depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM | ||
17 | select VIDEOBUF_DMA_CONTIG | ||
18 | select VIDEO_DAVINCI_VPIF | ||
19 | help | ||
20 | Support for DM6467 based capture device. | ||
21 | |||
22 | To compile this driver as a module, choose M here: the | ||
23 | module will be called vpif_capture. | ||
24 | |||
25 | config VIDEO_DAVINCI_VPIF | ||
26 | tristate "DaVinci VPIF Driver" | ||
27 | depends on DISPLAY_DAVINCI_DM646X_EVM | ||
28 | help | ||
29 | Support for DaVinci VPIF Driver. | ||
30 | |||
31 | To compile this driver as a module, choose M here: the | ||
32 | module will be called vpif. | ||
33 | |||
34 | config VIDEO_VPSS_SYSTEM | ||
35 | tristate "VPSS System module driver" | ||
36 | depends on ARCH_DAVINCI | ||
37 | help | ||
38 | Support for vpss system module for video driver | ||
39 | |||
40 | config VIDEO_VPFE_CAPTURE | ||
41 | tristate "VPFE Video Capture Driver" | ||
42 | depends on VIDEO_V4L2 && (ARCH_DAVINCI || ARCH_OMAP3) | ||
43 | select VIDEOBUF_DMA_CONTIG | ||
44 | help | ||
45 | Support for DMx/AMx VPFE based frame grabber. This is the | ||
46 | common V4L2 module for following DMx/AMx SoCs from Texas | ||
47 | Instruments:- DM6446, DM365, DM355 & AM3517/05. | ||
48 | |||
49 | To compile this driver as a module, choose M here: the | ||
50 | module will be called vpfe-capture. | ||
51 | |||
52 | config VIDEO_DM6446_CCDC | ||
53 | tristate "DM6446 CCDC HW module" | ||
54 | depends on VIDEO_VPFE_CAPTURE | ||
55 | select VIDEO_VPSS_SYSTEM | ||
56 | default y | ||
57 | help | ||
58 | Enables DaVinci CCD hw module. DaVinci CCDC hw interfaces | ||
59 | with decoder modules such as TVP5146 over BT656 or | ||
60 | sensor module such as MT9T001 over a raw interface. This | ||
61 | module configures the interface and CCDC/ISIF to do | ||
62 | video frame capture from slave decoders. | ||
63 | |||
64 | To compile this driver as a module, choose M here: the | ||
65 | module will be called vpfe. | ||
66 | |||
67 | config VIDEO_DM355_CCDC | ||
68 | tristate "DM355 CCDC HW module" | ||
69 | depends on ARCH_DAVINCI_DM355 && VIDEO_VPFE_CAPTURE | ||
70 | select VIDEO_VPSS_SYSTEM | ||
71 | default y | ||
72 | help | ||
73 | Enables DM355 CCD hw module. DM355 CCDC hw interfaces | ||
74 | with decoder modules such as TVP5146 over BT656 or | ||
75 | sensor module such as MT9T001 over a raw interface. This | ||
76 | module configures the interface and CCDC/ISIF to do | ||
77 | video frame capture from a slave decoders | ||
78 | |||
79 | To compile this driver as a module, choose M here: the | ||
80 | module will be called vpfe. | ||
81 | |||
82 | config VIDEO_ISIF | ||
83 | tristate "ISIF HW module" | ||
84 | depends on ARCH_DAVINCI_DM365 && VIDEO_VPFE_CAPTURE | ||
85 | select VIDEO_VPSS_SYSTEM | ||
86 | default y | ||
87 | help | ||
88 | Enables ISIF hw module. This is the hardware module for | ||
89 | configuring ISIF in VPFE to capture Raw Bayer RGB data from | ||
90 | a image sensor or YUV data from a YUV source. | ||
91 | |||
92 | To compile this driver as a module, choose M here: the | ||
93 | module will be called vpfe. | ||
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 3a4fd8514511..ffbe544e30f4 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -158,6 +158,22 @@ static struct em28xx_reg_seq evga_indtube_digital[] = { | |||
158 | { -1, -1, -1, -1}, | 158 | { -1, -1, -1, -1}, |
159 | }; | 159 | }; |
160 | 160 | ||
161 | /* | ||
162 | * KWorld PlusTV 340U and UB435-Q (ATSC) GPIOs map: | ||
163 | * EM_GPIO_0 - currently unknown | ||
164 | * EM_GPIO_1 - LED disable/enable (1 = off, 0 = on) | ||
165 | * EM_GPIO_2 - currently unknown | ||
166 | * EM_GPIO_3 - currently unknown | ||
167 | * EM_GPIO_4 - TDA18271HD/C1 tuner (1 = active, 0 = in reset) | ||
168 | * EM_GPIO_5 - LGDT3304 ATSC/QAM demod (1 = active, 0 = in reset) | ||
169 | * EM_GPIO_6 - currently unknown | ||
170 | * EM_GPIO_7 - currently unknown | ||
171 | */ | ||
172 | static struct em28xx_reg_seq kworld_a340_digital[] = { | ||
173 | {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, | ||
174 | { -1, -1, -1, -1}, | ||
175 | }; | ||
176 | |||
161 | /* Pinnacle Hybrid Pro eb1a:2881 */ | 177 | /* Pinnacle Hybrid Pro eb1a:2881 */ |
162 | static struct em28xx_reg_seq pinnacle_hybrid_pro_analog[] = { | 178 | static struct em28xx_reg_seq pinnacle_hybrid_pro_analog[] = { |
163 | {EM28XX_R08_GPIO, 0xfd, ~EM_GPIO_4, 10}, | 179 | {EM28XX_R08_GPIO, 0xfd, ~EM_GPIO_4, 10}, |
@@ -1667,6 +1683,16 @@ struct em28xx_board em28xx_boards[] = { | |||
1667 | .tuner_gpio = reddo_dvb_c_usb_box, | 1683 | .tuner_gpio = reddo_dvb_c_usb_box, |
1668 | .has_dvb = 1, | 1684 | .has_dvb = 1, |
1669 | }, | 1685 | }, |
1686 | /* 1b80:a340 - Empia EM2870, NXP TDA18271HD and LG DT3304, sold | ||
1687 | * initially as the KWorld PlusTV 340U, then as the UB435-Q. | ||
1688 | * Early variants have a TDA18271HD/C1, later ones a TDA18271HD/C2 */ | ||
1689 | [EM2870_BOARD_KWORLD_A340] = { | ||
1690 | .name = "KWorld PlusTV 340U or UB435-Q (ATSC)", | ||
1691 | .tuner_type = TUNER_ABSENT, /* Digital-only TDA18271HD */ | ||
1692 | .has_dvb = 1, | ||
1693 | .dvb_gpio = kworld_a340_digital, | ||
1694 | .tuner_gpio = default_tuner_gpio, | ||
1695 | }, | ||
1670 | }; | 1696 | }; |
1671 | const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); | 1697 | const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); |
1672 | 1698 | ||
@@ -1788,6 +1814,8 @@ struct usb_device_id em28xx_id_table[] = { | |||
1788 | .driver_info = EM2820_BOARD_IODATA_GVMVP_SZ }, | 1814 | .driver_info = EM2820_BOARD_IODATA_GVMVP_SZ }, |
1789 | { USB_DEVICE(0xeb1a, 0x50a6), | 1815 | { USB_DEVICE(0xeb1a, 0x50a6), |
1790 | .driver_info = EM2860_BOARD_GADMEI_UTV330 }, | 1816 | .driver_info = EM2860_BOARD_GADMEI_UTV330 }, |
1817 | { USB_DEVICE(0x1b80, 0xa340), | ||
1818 | .driver_info = EM2870_BOARD_KWORLD_A340 }, | ||
1791 | { }, | 1819 | { }, |
1792 | }; | 1820 | }; |
1793 | MODULE_DEVICE_TABLE(usb, em28xx_id_table); | 1821 | MODULE_DEVICE_TABLE(usb, em28xx_id_table); |
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index cf1d8c3655fc..3ac8d3025fea 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c | |||
@@ -30,11 +30,13 @@ | |||
30 | #include "tuner-simple.h" | 30 | #include "tuner-simple.h" |
31 | 31 | ||
32 | #include "lgdt330x.h" | 32 | #include "lgdt330x.h" |
33 | #include "lgdt3305.h" | ||
33 | #include "zl10353.h" | 34 | #include "zl10353.h" |
34 | #include "s5h1409.h" | 35 | #include "s5h1409.h" |
35 | #include "mt352.h" | 36 | #include "mt352.h" |
36 | #include "mt352_priv.h" /* FIXME */ | 37 | #include "mt352_priv.h" /* FIXME */ |
37 | #include "tda1002x.h" | 38 | #include "tda1002x.h" |
39 | #include "tda18271.h" | ||
38 | 40 | ||
39 | MODULE_DESCRIPTION("driver for em28xx based DVB cards"); | 41 | MODULE_DESCRIPTION("driver for em28xx based DVB cards"); |
40 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); | 42 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); |
@@ -231,6 +233,18 @@ static struct lgdt330x_config em2880_lgdt3303_dev = { | |||
231 | .demod_chip = LGDT3303, | 233 | .demod_chip = LGDT3303, |
232 | }; | 234 | }; |
233 | 235 | ||
236 | static struct lgdt3305_config em2870_lgdt3304_dev = { | ||
237 | .i2c_addr = 0x0e, | ||
238 | .demod_chip = LGDT3304, | ||
239 | .spectral_inversion = 1, | ||
240 | .deny_i2c_rptr = 1, | ||
241 | .mpeg_mode = LGDT3305_MPEG_PARALLEL, | ||
242 | .tpclk_edge = LGDT3305_TPCLK_FALLING_EDGE, | ||
243 | .tpvalid_polarity = LGDT3305_TP_VALID_HIGH, | ||
244 | .vsb_if_khz = 3250, | ||
245 | .qam_if_khz = 4000, | ||
246 | }; | ||
247 | |||
234 | static struct zl10353_config em28xx_zl10353_with_xc3028 = { | 248 | static struct zl10353_config em28xx_zl10353_with_xc3028 = { |
235 | .demod_address = (0x1e >> 1), | 249 | .demod_address = (0x1e >> 1), |
236 | .no_tuner = 1, | 250 | .no_tuner = 1, |
@@ -247,6 +261,17 @@ static struct s5h1409_config em28xx_s5h1409_with_xc3028 = { | |||
247 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK | 261 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK |
248 | }; | 262 | }; |
249 | 263 | ||
264 | static struct tda18271_std_map kworld_a340_std_map = { | ||
265 | .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 0, | ||
266 | .if_lvl = 1, .rfagc_top = 0x37, }, | ||
267 | .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 1, | ||
268 | .if_lvl = 1, .rfagc_top = 0x37, }, | ||
269 | }; | ||
270 | |||
271 | static struct tda18271_config kworld_a340_config = { | ||
272 | .std_map = &kworld_a340_std_map, | ||
273 | }; | ||
274 | |||
250 | static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = { | 275 | static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = { |
251 | .demod_address = (0x1e >> 1), | 276 | .demod_address = (0x1e >> 1), |
252 | .no_tuner = 1, | 277 | .no_tuner = 1, |
@@ -572,6 +597,14 @@ static int dvb_init(struct em28xx *dev) | |||
572 | } | 597 | } |
573 | } | 598 | } |
574 | break; | 599 | break; |
600 | case EM2870_BOARD_KWORLD_A340: | ||
601 | dvb->frontend = dvb_attach(lgdt3305_attach, | ||
602 | &em2870_lgdt3304_dev, | ||
603 | &dev->i2c_adap); | ||
604 | if (dvb->frontend != NULL) | ||
605 | dvb_attach(tda18271_attach, dvb->frontend, 0x60, | ||
606 | &dev->i2c_adap, &kworld_a340_config); | ||
607 | break; | ||
575 | default: | 608 | default: |
576 | em28xx_errdev("/2: The frontend of your DVB/ATSC card" | 609 | em28xx_errdev("/2: The frontend of your DVB/ATSC card" |
577 | " isn't supported yet\n"); | 610 | " isn't supported yet\n"); |
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 5c3fd9411b1f..6759cd5570dd 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c | |||
@@ -65,17 +65,14 @@ struct em28xx_ir_poll_result { | |||
65 | struct em28xx_IR { | 65 | struct em28xx_IR { |
66 | struct em28xx *dev; | 66 | struct em28xx *dev; |
67 | struct input_dev *input; | 67 | struct input_dev *input; |
68 | struct ir_input_state ir; | ||
69 | char name[32]; | 68 | char name[32]; |
70 | char phys[32]; | 69 | char phys[32]; |
71 | 70 | ||
72 | /* poll external decoder */ | 71 | /* poll external decoder */ |
73 | int polling; | 72 | int polling; |
74 | struct delayed_work work; | 73 | struct delayed_work work; |
75 | unsigned int last_toggle:1; | ||
76 | unsigned int full_code:1; | 74 | unsigned int full_code:1; |
77 | unsigned int last_readcount; | 75 | unsigned int last_readcount; |
78 | unsigned int repeat_interval; | ||
79 | 76 | ||
80 | int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *); | 77 | int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *); |
81 | 78 | ||
@@ -291,67 +288,39 @@ static int em2874_polling_getkey(struct em28xx_IR *ir, | |||
291 | static void em28xx_ir_handle_key(struct em28xx_IR *ir) | 288 | static void em28xx_ir_handle_key(struct em28xx_IR *ir) |
292 | { | 289 | { |
293 | int result; | 290 | int result; |
294 | int do_sendkey = 0; | ||
295 | struct em28xx_ir_poll_result poll_result; | 291 | struct em28xx_ir_poll_result poll_result; |
296 | 292 | ||
297 | /* read the registers containing the IR status */ | 293 | /* read the registers containing the IR status */ |
298 | result = ir->get_key(ir, &poll_result); | 294 | result = ir->get_key(ir, &poll_result); |
299 | if (result < 0) { | 295 | if (unlikely(result < 0)) { |
300 | dprintk("ir->get_key() failed %d\n", result); | 296 | dprintk("ir->get_key() failed %d\n", result); |
301 | return; | 297 | return; |
302 | } | 298 | } |
303 | 299 | ||
304 | dprintk("ir->get_key result tb=%02x rc=%02x lr=%02x data=%02x%02x\n", | 300 | if (unlikely(poll_result.read_count != ir->last_readcount)) { |
305 | poll_result.toggle_bit, poll_result.read_count, | 301 | dprintk("%s: toggle: %d, count: %d, key 0x%02x%02x\n", __func__, |
306 | ir->last_readcount, poll_result.rc_address, | 302 | poll_result.toggle_bit, poll_result.read_count, |
307 | poll_result.rc_data[0]); | 303 | poll_result.rc_address, poll_result.rc_data[0]); |
308 | |||
309 | if (ir->dev->chip_id == CHIP_ID_EM2874) { | ||
310 | /* The em2874 clears the readcount field every time the | ||
311 | register is read. The em2860/2880 datasheet says that it | ||
312 | is supposed to clear the readcount, but it doesn't. So with | ||
313 | the em2874, we are looking for a non-zero read count as | ||
314 | opposed to a readcount that is incrementing */ | ||
315 | ir->last_readcount = 0; | ||
316 | } | ||
317 | |||
318 | if (poll_result.read_count == 0) { | ||
319 | /* The button has not been pressed since the last read */ | ||
320 | } else if (ir->last_toggle != poll_result.toggle_bit) { | ||
321 | /* A button has been pressed */ | ||
322 | dprintk("button has been pressed\n"); | ||
323 | ir->last_toggle = poll_result.toggle_bit; | ||
324 | ir->repeat_interval = 0; | ||
325 | do_sendkey = 1; | ||
326 | } else if (poll_result.toggle_bit == ir->last_toggle && | ||
327 | poll_result.read_count > 0 && | ||
328 | poll_result.read_count != ir->last_readcount) { | ||
329 | /* The button is still being held down */ | ||
330 | dprintk("button being held down\n"); | ||
331 | |||
332 | /* Debouncer for first keypress */ | ||
333 | if (ir->repeat_interval++ > 9) { | ||
334 | /* Start repeating after 1 second */ | ||
335 | do_sendkey = 1; | ||
336 | } | ||
337 | } | ||
338 | |||
339 | if (do_sendkey) { | ||
340 | dprintk("sending keypress\n"); | ||
341 | |||
342 | if (ir->full_code) | 304 | if (ir->full_code) |
343 | ir_input_keydown(ir->input, &ir->ir, | 305 | ir_keydown(ir->input, |
344 | poll_result.rc_address << 8 | | 306 | poll_result.rc_address << 8 | |
345 | poll_result.rc_data[0]); | 307 | poll_result.rc_data[0], |
308 | poll_result.toggle_bit); | ||
346 | else | 309 | else |
347 | ir_input_keydown(ir->input, &ir->ir, | 310 | ir_keydown(ir->input, |
348 | poll_result.rc_data[0]); | 311 | poll_result.rc_data[0], |
349 | 312 | poll_result.toggle_bit); | |
350 | ir_input_nokey(ir->input, &ir->ir); | 313 | |
314 | if (ir->dev->chip_id == CHIP_ID_EM2874) | ||
315 | /* The em2874 clears the readcount field every time the | ||
316 | register is read. The em2860/2880 datasheet says that it | ||
317 | is supposed to clear the readcount, but it doesn't. So with | ||
318 | the em2874, we are looking for a non-zero read count as | ||
319 | opposed to a readcount that is incrementing */ | ||
320 | ir->last_readcount = 0; | ||
321 | else | ||
322 | ir->last_readcount = poll_result.read_count; | ||
351 | } | 323 | } |
352 | |||
353 | ir->last_readcount = poll_result.read_count; | ||
354 | return; | ||
355 | } | 324 | } |
356 | 325 | ||
357 | static void em28xx_ir_work(struct work_struct *work) | 326 | static void em28xx_ir_work(struct work_struct *work) |
@@ -466,11 +435,6 @@ int em28xx_ir_init(struct em28xx *dev) | |||
466 | usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); | 435 | usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); |
467 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); | 436 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); |
468 | 437 | ||
469 | /* Set IR protocol */ | ||
470 | err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER); | ||
471 | if (err < 0) | ||
472 | goto err_out_free; | ||
473 | |||
474 | input_dev->name = ir->name; | 438 | input_dev->name = ir->name; |
475 | input_dev->phys = ir->phys; | 439 | input_dev->phys = ir->phys; |
476 | input_dev->id.bustype = BUS_USB; | 440 | input_dev->id.bustype = BUS_USB; |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 20090e34173a..7b9ec6e493e4 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -654,12 +654,12 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) | |||
654 | } | 654 | } |
655 | 655 | ||
656 | if (buf != NULL && dev->capture_type == 2) { | 656 | if (buf != NULL && dev->capture_type == 2) { |
657 | if (len > 4 && p[0] == 0x88 && p[1] == 0x88 && | 657 | if (len >= 4 && p[0] == 0x88 && p[1] == 0x88 && |
658 | p[2] == 0x88 && p[3] == 0x88) { | 658 | p[2] == 0x88 && p[3] == 0x88) { |
659 | p += 4; | 659 | p += 4; |
660 | len -= 4; | 660 | len -= 4; |
661 | } | 661 | } |
662 | if (len > 4 && p[0] == 0x22 && p[1] == 0x5a) { | 662 | if (len >= 4 && p[0] == 0x22 && p[1] == 0x5a) { |
663 | em28xx_isocdbg("Video frame %d, len=%i, %s\n", | 663 | em28xx_isocdbg("Video frame %d, len=%i, %s\n", |
664 | p[2], len, (p[2] & 1) ? | 664 | p[2], len, (p[2] & 1) ? |
665 | "odd" : "even"); | 665 | "odd" : "even"); |
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index b252d1b1b2a7..1c61a6b65d28 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/i2c.h> | 32 | #include <linux/i2c.h> |
33 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
34 | #include <media/ir-kbd-i2c.h> | 34 | #include <media/ir-kbd-i2c.h> |
35 | #include <media/ir-core.h> | ||
35 | #if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE) | 36 | #if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE) |
36 | #include <media/videobuf-dvb.h> | 37 | #include <media/videobuf-dvb.h> |
37 | #endif | 38 | #endif |
@@ -113,6 +114,7 @@ | |||
113 | #define EM2870_BOARD_REDDO_DVB_C_USB_BOX 73 | 114 | #define EM2870_BOARD_REDDO_DVB_C_USB_BOX 73 |
114 | #define EM2800_BOARD_VC211A 74 | 115 | #define EM2800_BOARD_VC211A 74 |
115 | #define EM2882_BOARD_DIKOM_DK300 75 | 116 | #define EM2882_BOARD_DIKOM_DK300 75 |
117 | #define EM2870_BOARD_KWORLD_A340 76 | ||
116 | 118 | ||
117 | /* Limits minimum and default number of buffers */ | 119 | /* Limits minimum and default number of buffers */ |
118 | #define EM28XX_MIN_BUF 4 | 120 | #define EM28XX_MIN_BUF 4 |
diff --git a/drivers/media/video/fsl-viu.c b/drivers/media/video/fsl-viu.c new file mode 100644 index 000000000000..8f1c94f7e00c --- /dev/null +++ b/drivers/media/video/fsl-viu.c | |||
@@ -0,0 +1,1632 @@ | |||
1 | /* | ||
2 | * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. | ||
3 | * | ||
4 | * Freescale VIU video driver | ||
5 | * | ||
6 | * Authors: Hongjun Chen <hong-jun.chen@freescale.com> | ||
7 | * Porting to 2.6.35 by DENX Software Engineering, | ||
8 | * Anatolij Gustschin <agust@denx.de> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/io.h> | ||
24 | #include <linux/of_platform.h> | ||
25 | #include <linux/version.h> | ||
26 | #include <media/v4l2-common.h> | ||
27 | #include <media/v4l2-device.h> | ||
28 | #include <media/v4l2-ioctl.h> | ||
29 | #include <media/videobuf-dma-contig.h> | ||
30 | |||
31 | #define DRV_NAME "fsl_viu" | ||
32 | #define VIU_MAJOR_VERSION 0 | ||
33 | #define VIU_MINOR_VERSION 5 | ||
34 | #define VIU_RELEASE 0 | ||
35 | #define VIU_VERSION KERNEL_VERSION(VIU_MAJOR_VERSION, \ | ||
36 | VIU_MINOR_VERSION, \ | ||
37 | VIU_RELEASE) | ||
38 | |||
39 | #define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */ | ||
40 | |||
41 | #define VIU_VID_MEM_LIMIT 4 /* Video memory limit, in Mb */ | ||
42 | |||
43 | /* I2C address of video decoder chip is 0x4A */ | ||
44 | #define VIU_VIDEO_DECODER_ADDR 0x25 | ||
45 | |||
46 | /* supported controls */ | ||
47 | static struct v4l2_queryctrl viu_qctrl[] = { | ||
48 | { | ||
49 | .id = V4L2_CID_BRIGHTNESS, | ||
50 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
51 | .name = "Brightness", | ||
52 | .minimum = 0, | ||
53 | .maximum = 255, | ||
54 | .step = 1, | ||
55 | .default_value = 127, | ||
56 | .flags = 0, | ||
57 | }, { | ||
58 | .id = V4L2_CID_CONTRAST, | ||
59 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
60 | .name = "Contrast", | ||
61 | .minimum = 0, | ||
62 | .maximum = 255, | ||
63 | .step = 0x1, | ||
64 | .default_value = 0x10, | ||
65 | .flags = 0, | ||
66 | }, { | ||
67 | .id = V4L2_CID_SATURATION, | ||
68 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
69 | .name = "Saturation", | ||
70 | .minimum = 0, | ||
71 | .maximum = 255, | ||
72 | .step = 0x1, | ||
73 | .default_value = 127, | ||
74 | .flags = 0, | ||
75 | }, { | ||
76 | .id = V4L2_CID_HUE, | ||
77 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
78 | .name = "Hue", | ||
79 | .minimum = -128, | ||
80 | .maximum = 127, | ||
81 | .step = 0x1, | ||
82 | .default_value = 0, | ||
83 | .flags = 0, | ||
84 | } | ||
85 | }; | ||
86 | |||
87 | static int qctl_regs[ARRAY_SIZE(viu_qctrl)]; | ||
88 | |||
89 | static int info_level; | ||
90 | |||
91 | #define dprintk(level, fmt, arg...) \ | ||
92 | do { \ | ||
93 | if (level <= info_level) \ | ||
94 | printk(KERN_DEBUG "viu: " fmt , ## arg); \ | ||
95 | } while (0) | ||
96 | |||
97 | /* | ||
98 | * Basic structures | ||
99 | */ | ||
100 | struct viu_fmt { | ||
101 | char name[32]; | ||
102 | u32 fourcc; /* v4l2 format id */ | ||
103 | u32 pixelformat; | ||
104 | int depth; | ||
105 | }; | ||
106 | |||
107 | static struct viu_fmt formats[] = { | ||
108 | { | ||
109 | .name = "RGB-16 (5/B-6/G-5/R)", | ||
110 | .fourcc = V4L2_PIX_FMT_RGB565, | ||
111 | .pixelformat = V4L2_PIX_FMT_RGB565, | ||
112 | .depth = 16, | ||
113 | }, { | ||
114 | .name = "RGB-32 (A-R-G-B)", | ||
115 | .fourcc = V4L2_PIX_FMT_RGB32, | ||
116 | .pixelformat = V4L2_PIX_FMT_RGB32, | ||
117 | .depth = 32, | ||
118 | } | ||
119 | }; | ||
120 | |||
121 | struct viu_dev; | ||
122 | struct viu_buf; | ||
123 | |||
124 | /* buffer for one video frame */ | ||
125 | struct viu_buf { | ||
126 | /* common v4l buffer stuff -- must be first */ | ||
127 | struct videobuf_buffer vb; | ||
128 | struct viu_fmt *fmt; | ||
129 | }; | ||
130 | |||
131 | struct viu_dmaqueue { | ||
132 | struct viu_dev *dev; | ||
133 | struct list_head active; | ||
134 | struct list_head queued; | ||
135 | struct timer_list timeout; | ||
136 | }; | ||
137 | |||
138 | struct viu_status { | ||
139 | u32 field_irq; | ||
140 | u32 vsync_irq; | ||
141 | u32 hsync_irq; | ||
142 | u32 vstart_irq; | ||
143 | u32 dma_end_irq; | ||
144 | u32 error_irq; | ||
145 | }; | ||
146 | |||
147 | struct viu_reg { | ||
148 | u32 status_cfg; | ||
149 | u32 luminance; | ||
150 | u32 chroma_r; | ||
151 | u32 chroma_g; | ||
152 | u32 chroma_b; | ||
153 | u32 field_base_addr; | ||
154 | u32 dma_inc; | ||
155 | u32 picture_count; | ||
156 | u32 req_alarm; | ||
157 | u32 alpha; | ||
158 | } __attribute__ ((packed)); | ||
159 | |||
160 | struct viu_dev { | ||
161 | struct v4l2_device v4l2_dev; | ||
162 | struct mutex lock; | ||
163 | spinlock_t slock; | ||
164 | int users; | ||
165 | |||
166 | struct device *dev; | ||
167 | /* various device info */ | ||
168 | struct video_device *vdev; | ||
169 | struct viu_dmaqueue vidq; | ||
170 | enum v4l2_field capfield; | ||
171 | int field; | ||
172 | int first; | ||
173 | int dma_done; | ||
174 | |||
175 | /* Hardware register area */ | ||
176 | struct viu_reg *vr; | ||
177 | |||
178 | /* Interrupt vector */ | ||
179 | int irq; | ||
180 | struct viu_status irqs; | ||
181 | |||
182 | /* video overlay */ | ||
183 | struct v4l2_framebuffer ovbuf; | ||
184 | struct viu_fmt *ovfmt; | ||
185 | unsigned int ovenable; | ||
186 | enum v4l2_field ovfield; | ||
187 | |||
188 | /* crop */ | ||
189 | struct v4l2_rect crop_current; | ||
190 | |||
191 | /* clock pointer */ | ||
192 | struct clk *clk; | ||
193 | |||
194 | /* decoder */ | ||
195 | struct v4l2_subdev *decoder; | ||
196 | }; | ||
197 | |||
198 | struct viu_fh { | ||
199 | struct viu_dev *dev; | ||
200 | |||
201 | /* video capture */ | ||
202 | struct videobuf_queue vb_vidq; | ||
203 | spinlock_t vbq_lock; /* spinlock for the videobuf queue */ | ||
204 | |||
205 | /* video overlay */ | ||
206 | struct v4l2_window win; | ||
207 | struct v4l2_clip clips[1]; | ||
208 | |||
209 | /* video capture */ | ||
210 | struct viu_fmt *fmt; | ||
211 | int width, height, sizeimage; | ||
212 | enum v4l2_buf_type type; | ||
213 | }; | ||
214 | |||
215 | static struct viu_reg reg_val; | ||
216 | |||
217 | /* | ||
218 | * Macro definitions of VIU registers | ||
219 | */ | ||
220 | |||
221 | /* STATUS_CONFIG register */ | ||
222 | enum status_config { | ||
223 | SOFT_RST = 1 << 0, | ||
224 | |||
225 | ERR_MASK = 0x0f << 4, /* Error code mask */ | ||
226 | ERR_NO = 0x00, /* No error */ | ||
227 | ERR_DMA_V = 0x01 << 4, /* DMA in vertical active */ | ||
228 | ERR_DMA_VB = 0x02 << 4, /* DMA in vertical blanking */ | ||
229 | ERR_LINE_TOO_LONG = 0x04 << 4, /* Line too long */ | ||
230 | ERR_TOO_MANG_LINES = 0x05 << 4, /* Too many lines in field */ | ||
231 | ERR_LINE_TOO_SHORT = 0x06 << 4, /* Line too short */ | ||
232 | ERR_NOT_ENOUGH_LINE = 0x07 << 4, /* Not enough lines in field */ | ||
233 | ERR_FIFO_OVERFLOW = 0x08 << 4, /* FIFO overflow */ | ||
234 | ERR_FIFO_UNDERFLOW = 0x09 << 4, /* FIFO underflow */ | ||
235 | ERR_1bit_ECC = 0x0a << 4, /* One bit ECC error */ | ||
236 | ERR_MORE_ECC = 0x0b << 4, /* Two/more bits ECC error */ | ||
237 | |||
238 | INT_FIELD_EN = 0x01 << 8, /* Enable field interrupt */ | ||
239 | INT_VSYNC_EN = 0x01 << 9, /* Enable vsync interrupt */ | ||
240 | INT_HSYNC_EN = 0x01 << 10, /* Enable hsync interrupt */ | ||
241 | INT_VSTART_EN = 0x01 << 11, /* Enable vstart interrupt */ | ||
242 | INT_DMA_END_EN = 0x01 << 12, /* Enable DMA end interrupt */ | ||
243 | INT_ERROR_EN = 0x01 << 13, /* Enable error interrupt */ | ||
244 | INT_ECC_EN = 0x01 << 14, /* Enable ECC interrupt */ | ||
245 | |||
246 | INT_FIELD_STATUS = 0x01 << 16, /* field interrupt status */ | ||
247 | INT_VSYNC_STATUS = 0x01 << 17, /* vsync interrupt status */ | ||
248 | INT_HSYNC_STATUS = 0x01 << 18, /* hsync interrupt status */ | ||
249 | INT_VSTART_STATUS = 0x01 << 19, /* vstart interrupt status */ | ||
250 | INT_DMA_END_STATUS = 0x01 << 20, /* DMA end interrupt status */ | ||
251 | INT_ERROR_STATUS = 0x01 << 21, /* error interrupt status */ | ||
252 | |||
253 | DMA_ACT = 0x01 << 27, /* Enable DMA transfer */ | ||
254 | FIELD_NO = 0x01 << 28, /* Field number */ | ||
255 | DITHER_ON = 0x01 << 29, /* Dithering is on */ | ||
256 | ROUND_ON = 0x01 << 30, /* Round is on */ | ||
257 | MODE_32BIT = 0x01 << 31, /* Data in RGBa888, | ||
258 | * 0 in RGB565 | ||
259 | */ | ||
260 | }; | ||
261 | |||
262 | #define norm_maxw() 720 | ||
263 | #define norm_maxh() 576 | ||
264 | |||
265 | #define INT_ALL_STATUS (INT_FIELD_STATUS | INT_VSYNC_STATUS | \ | ||
266 | INT_HSYNC_STATUS | INT_VSTART_STATUS | \ | ||
267 | INT_DMA_END_STATUS | INT_ERROR_STATUS) | ||
268 | |||
269 | #define NUM_FORMATS ARRAY_SIZE(formats) | ||
270 | |||
271 | static irqreturn_t viu_intr(int irq, void *dev_id); | ||
272 | |||
273 | struct viu_fmt *format_by_fourcc(int fourcc) | ||
274 | { | ||
275 | int i; | ||
276 | |||
277 | for (i = 0; i < NUM_FORMATS; i++) { | ||
278 | if (formats[i].pixelformat == fourcc) | ||
279 | return formats + i; | ||
280 | } | ||
281 | |||
282 | dprintk(0, "unknown pixelformat:'%4.4s'\n", (char *)&fourcc); | ||
283 | return NULL; | ||
284 | } | ||
285 | |||
286 | void viu_start_dma(struct viu_dev *dev) | ||
287 | { | ||
288 | struct viu_reg *vr = dev->vr; | ||
289 | |||
290 | dev->field = 0; | ||
291 | |||
292 | /* Enable DMA operation */ | ||
293 | out_be32(&vr->status_cfg, SOFT_RST); | ||
294 | out_be32(&vr->status_cfg, INT_FIELD_EN); | ||
295 | } | ||
296 | |||
297 | void viu_stop_dma(struct viu_dev *dev) | ||
298 | { | ||
299 | struct viu_reg *vr = dev->vr; | ||
300 | int cnt = 100; | ||
301 | u32 status_cfg; | ||
302 | |||
303 | out_be32(&vr->status_cfg, 0); | ||
304 | |||
305 | /* Clear pending interrupts */ | ||
306 | status_cfg = in_be32(&vr->status_cfg); | ||
307 | if (status_cfg & 0x3f0000) | ||
308 | out_be32(&vr->status_cfg, status_cfg & 0x3f0000); | ||
309 | |||
310 | if (status_cfg & DMA_ACT) { | ||
311 | do { | ||
312 | status_cfg = in_be32(&vr->status_cfg); | ||
313 | if (status_cfg & INT_DMA_END_STATUS) | ||
314 | break; | ||
315 | } while (cnt--); | ||
316 | |||
317 | if (cnt < 0) { | ||
318 | /* timed out, issue soft reset */ | ||
319 | out_be32(&vr->status_cfg, SOFT_RST); | ||
320 | out_be32(&vr->status_cfg, 0); | ||
321 | } else { | ||
322 | /* clear DMA_END and other pending irqs */ | ||
323 | out_be32(&vr->status_cfg, status_cfg & 0x3f0000); | ||
324 | } | ||
325 | } | ||
326 | |||
327 | dev->field = 0; | ||
328 | } | ||
329 | |||
330 | static int restart_video_queue(struct viu_dmaqueue *vidq) | ||
331 | { | ||
332 | struct viu_buf *buf, *prev; | ||
333 | |||
334 | dprintk(1, "%s vidq=0x%08lx\n", __func__, (unsigned long)vidq); | ||
335 | if (!list_empty(&vidq->active)) { | ||
336 | buf = list_entry(vidq->active.next, struct viu_buf, vb.queue); | ||
337 | dprintk(2, "restart_queue [%p/%d]: restart dma\n", | ||
338 | buf, buf->vb.i); | ||
339 | |||
340 | viu_stop_dma(vidq->dev); | ||
341 | |||
342 | /* cancel all outstanding capture requests */ | ||
343 | list_for_each_entry_safe(buf, prev, &vidq->active, vb.queue) { | ||
344 | list_del(&buf->vb.queue); | ||
345 | buf->vb.state = VIDEOBUF_ERROR; | ||
346 | wake_up(&buf->vb.done); | ||
347 | } | ||
348 | mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT); | ||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | prev = NULL; | ||
353 | for (;;) { | ||
354 | if (list_empty(&vidq->queued)) | ||
355 | return 0; | ||
356 | buf = list_entry(vidq->queued.next, struct viu_buf, vb.queue); | ||
357 | if (prev == NULL) { | ||
358 | list_del(&buf->vb.queue); | ||
359 | list_add_tail(&buf->vb.queue, &vidq->active); | ||
360 | |||
361 | dprintk(1, "Restarting video dma\n"); | ||
362 | viu_stop_dma(vidq->dev); | ||
363 | viu_start_dma(vidq->dev); | ||
364 | |||
365 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
366 | mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT); | ||
367 | dprintk(2, "[%p/%d] restart_queue - first active\n", | ||
368 | buf, buf->vb.i); | ||
369 | |||
370 | } else if (prev->vb.width == buf->vb.width && | ||
371 | prev->vb.height == buf->vb.height && | ||
372 | prev->fmt == buf->fmt) { | ||
373 | list_del(&buf->vb.queue); | ||
374 | list_add_tail(&buf->vb.queue, &vidq->active); | ||
375 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
376 | dprintk(2, "[%p/%d] restart_queue - move to active\n", | ||
377 | buf, buf->vb.i); | ||
378 | } else { | ||
379 | return 0; | ||
380 | } | ||
381 | prev = buf; | ||
382 | } | ||
383 | } | ||
384 | |||
385 | static void viu_vid_timeout(unsigned long data) | ||
386 | { | ||
387 | struct viu_dev *dev = (struct viu_dev *)data; | ||
388 | struct viu_buf *buf; | ||
389 | struct viu_dmaqueue *vidq = &dev->vidq; | ||
390 | |||
391 | while (!list_empty(&vidq->active)) { | ||
392 | buf = list_entry(vidq->active.next, struct viu_buf, vb.queue); | ||
393 | list_del(&buf->vb.queue); | ||
394 | buf->vb.state = VIDEOBUF_ERROR; | ||
395 | wake_up(&buf->vb.done); | ||
396 | dprintk(1, "viu/0: [%p/%d] timeout\n", buf, buf->vb.i); | ||
397 | } | ||
398 | |||
399 | restart_video_queue(vidq); | ||
400 | } | ||
401 | |||
402 | /* | ||
403 | * Videobuf operations | ||
404 | */ | ||
405 | static int buffer_setup(struct videobuf_queue *vq, unsigned int *count, | ||
406 | unsigned int *size) | ||
407 | { | ||
408 | struct viu_fh *fh = vq->priv_data; | ||
409 | |||
410 | *size = fh->width * fh->height * fh->fmt->depth >> 3; | ||
411 | if (*count == 0) | ||
412 | *count = 32; | ||
413 | |||
414 | while (*size * *count > VIU_VID_MEM_LIMIT * 1024 * 1024) | ||
415 | (*count)--; | ||
416 | |||
417 | dprintk(1, "%s, count=%d, size=%d\n", __func__, *count, *size); | ||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | static void free_buffer(struct videobuf_queue *vq, struct viu_buf *buf) | ||
422 | { | ||
423 | struct videobuf_buffer *vb = &buf->vb; | ||
424 | void *vaddr = NULL; | ||
425 | |||
426 | BUG_ON(in_interrupt()); | ||
427 | |||
428 | videobuf_waiton(&buf->vb, 0, 0); | ||
429 | |||
430 | if (vq->int_ops && vq->int_ops->vaddr) | ||
431 | vaddr = vq->int_ops->vaddr(vb); | ||
432 | |||
433 | if (vaddr) | ||
434 | videobuf_dma_contig_free(vq, &buf->vb); | ||
435 | |||
436 | buf->vb.state = VIDEOBUF_NEEDS_INIT; | ||
437 | } | ||
438 | |||
439 | inline int buffer_activate(struct viu_dev *dev, struct viu_buf *buf) | ||
440 | { | ||
441 | struct viu_reg *vr = dev->vr; | ||
442 | int bpp; | ||
443 | |||
444 | /* setup the DMA base address */ | ||
445 | reg_val.field_base_addr = videobuf_to_dma_contig(&buf->vb); | ||
446 | |||
447 | dprintk(1, "buffer_activate [%p/%d]: dma addr 0x%lx\n", | ||
448 | buf, buf->vb.i, (unsigned long)reg_val.field_base_addr); | ||
449 | |||
450 | /* interlace is on by default, set horizontal DMA increment */ | ||
451 | reg_val.status_cfg = 0; | ||
452 | bpp = buf->fmt->depth >> 3; | ||
453 | switch (bpp) { | ||
454 | case 2: | ||
455 | reg_val.status_cfg &= ~MODE_32BIT; | ||
456 | reg_val.dma_inc = buf->vb.width * 2; | ||
457 | break; | ||
458 | case 4: | ||
459 | reg_val.status_cfg |= MODE_32BIT; | ||
460 | reg_val.dma_inc = buf->vb.width * 4; | ||
461 | break; | ||
462 | default: | ||
463 | dprintk(0, "doesn't support color depth(%d)\n", | ||
464 | bpp * 8); | ||
465 | return -EINVAL; | ||
466 | } | ||
467 | |||
468 | /* setup picture_count register */ | ||
469 | reg_val.picture_count = (buf->vb.height / 2) << 16 | | ||
470 | buf->vb.width; | ||
471 | |||
472 | reg_val.status_cfg |= DMA_ACT | INT_DMA_END_EN | INT_FIELD_EN; | ||
473 | |||
474 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
475 | dev->capfield = buf->vb.field; | ||
476 | |||
477 | /* reset dma increment if needed */ | ||
478 | if (!V4L2_FIELD_HAS_BOTH(buf->vb.field)) | ||
479 | reg_val.dma_inc = 0; | ||
480 | |||
481 | out_be32(&vr->dma_inc, reg_val.dma_inc); | ||
482 | out_be32(&vr->picture_count, reg_val.picture_count); | ||
483 | out_be32(&vr->field_base_addr, reg_val.field_base_addr); | ||
484 | mod_timer(&dev->vidq.timeout, jiffies + BUFFER_TIMEOUT); | ||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | static int buffer_prepare(struct videobuf_queue *vq, | ||
489 | struct videobuf_buffer *vb, | ||
490 | enum v4l2_field field) | ||
491 | { | ||
492 | struct viu_fh *fh = vq->priv_data; | ||
493 | struct viu_buf *buf = container_of(vb, struct viu_buf, vb); | ||
494 | int rc; | ||
495 | |||
496 | BUG_ON(fh->fmt == NULL); | ||
497 | |||
498 | if (fh->width < 48 || fh->width > norm_maxw() || | ||
499 | fh->height < 32 || fh->height > norm_maxh()) | ||
500 | return -EINVAL; | ||
501 | buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3; | ||
502 | if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size) | ||
503 | return -EINVAL; | ||
504 | |||
505 | if (buf->fmt != fh->fmt || | ||
506 | buf->vb.width != fh->width || | ||
507 | buf->vb.height != fh->height || | ||
508 | buf->vb.field != field) { | ||
509 | buf->fmt = fh->fmt; | ||
510 | buf->vb.width = fh->width; | ||
511 | buf->vb.height = fh->height; | ||
512 | buf->vb.field = field; | ||
513 | } | ||
514 | |||
515 | if (buf->vb.state == VIDEOBUF_NEEDS_INIT) { | ||
516 | rc = videobuf_iolock(vq, &buf->vb, NULL); | ||
517 | if (rc != 0) | ||
518 | goto fail; | ||
519 | |||
520 | buf->vb.width = fh->width; | ||
521 | buf->vb.height = fh->height; | ||
522 | buf->vb.field = field; | ||
523 | buf->fmt = fh->fmt; | ||
524 | } | ||
525 | |||
526 | buf->vb.state = VIDEOBUF_PREPARED; | ||
527 | return 0; | ||
528 | |||
529 | fail: | ||
530 | free_buffer(vq, buf); | ||
531 | return rc; | ||
532 | } | ||
533 | |||
534 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
535 | { | ||
536 | struct viu_buf *buf = container_of(vb, struct viu_buf, vb); | ||
537 | struct viu_fh *fh = vq->priv_data; | ||
538 | struct viu_dev *dev = fh->dev; | ||
539 | struct viu_dmaqueue *vidq = &dev->vidq; | ||
540 | struct viu_buf *prev; | ||
541 | |||
542 | if (!list_empty(&vidq->queued)) { | ||
543 | dprintk(1, "adding vb queue=0x%08lx\n", | ||
544 | (unsigned long)&buf->vb.queue); | ||
545 | dprintk(1, "vidq pointer 0x%p, queued 0x%p\n", | ||
546 | vidq, &vidq->queued); | ||
547 | dprintk(1, "dev %p, queued: self %p, next %p, head %p\n", | ||
548 | dev, &vidq->queued, vidq->queued.next, | ||
549 | vidq->queued.prev); | ||
550 | list_add_tail(&buf->vb.queue, &vidq->queued); | ||
551 | buf->vb.state = VIDEOBUF_QUEUED; | ||
552 | dprintk(2, "[%p/%d] buffer_queue - append to queued\n", | ||
553 | buf, buf->vb.i); | ||
554 | } else if (list_empty(&vidq->active)) { | ||
555 | dprintk(1, "adding vb active=0x%08lx\n", | ||
556 | (unsigned long)&buf->vb.queue); | ||
557 | list_add_tail(&buf->vb.queue, &vidq->active); | ||
558 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
559 | mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT); | ||
560 | dprintk(2, "[%p/%d] buffer_queue - first active\n", | ||
561 | buf, buf->vb.i); | ||
562 | |||
563 | buffer_activate(dev, buf); | ||
564 | } else { | ||
565 | dprintk(1, "adding vb queue2=0x%08lx\n", | ||
566 | (unsigned long)&buf->vb.queue); | ||
567 | prev = list_entry(vidq->active.prev, struct viu_buf, vb.queue); | ||
568 | if (prev->vb.width == buf->vb.width && | ||
569 | prev->vb.height == buf->vb.height && | ||
570 | prev->fmt == buf->fmt) { | ||
571 | list_add_tail(&buf->vb.queue, &vidq->active); | ||
572 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
573 | dprintk(2, "[%p/%d] buffer_queue - append to active\n", | ||
574 | buf, buf->vb.i); | ||
575 | } else { | ||
576 | list_add_tail(&buf->vb.queue, &vidq->queued); | ||
577 | buf->vb.state = VIDEOBUF_QUEUED; | ||
578 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", | ||
579 | buf, buf->vb.i); | ||
580 | } | ||
581 | } | ||
582 | } | ||
583 | |||
584 | static void buffer_release(struct videobuf_queue *vq, | ||
585 | struct videobuf_buffer *vb) | ||
586 | { | ||
587 | struct viu_buf *buf = container_of(vb, struct viu_buf, vb); | ||
588 | struct viu_fh *fh = vq->priv_data; | ||
589 | struct viu_dev *dev = (struct viu_dev *)fh->dev; | ||
590 | |||
591 | viu_stop_dma(dev); | ||
592 | free_buffer(vq, buf); | ||
593 | } | ||
594 | |||
595 | static struct videobuf_queue_ops viu_video_qops = { | ||
596 | .buf_setup = buffer_setup, | ||
597 | .buf_prepare = buffer_prepare, | ||
598 | .buf_queue = buffer_queue, | ||
599 | .buf_release = buffer_release, | ||
600 | }; | ||
601 | |||
602 | /* | ||
603 | * IOCTL vidioc handling | ||
604 | */ | ||
605 | static int vidioc_querycap(struct file *file, void *priv, | ||
606 | struct v4l2_capability *cap) | ||
607 | { | ||
608 | strcpy(cap->driver, "viu"); | ||
609 | strcpy(cap->card, "viu"); | ||
610 | cap->version = VIU_VERSION; | ||
611 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | | ||
612 | V4L2_CAP_STREAMING | | ||
613 | V4L2_CAP_VIDEO_OVERLAY | | ||
614 | V4L2_CAP_READWRITE; | ||
615 | return 0; | ||
616 | } | ||
617 | |||
618 | static int vidioc_enum_fmt(struct file *file, void *priv, | ||
619 | struct v4l2_fmtdesc *f) | ||
620 | { | ||
621 | int index = f->index; | ||
622 | |||
623 | if (f->index > NUM_FORMATS) | ||
624 | return -EINVAL; | ||
625 | |||
626 | strlcpy(f->description, formats[index].name, sizeof(f->description)); | ||
627 | f->pixelformat = formats[index].fourcc; | ||
628 | return 0; | ||
629 | } | ||
630 | |||
631 | static int vidioc_g_fmt_cap(struct file *file, void *priv, | ||
632 | struct v4l2_format *f) | ||
633 | { | ||
634 | struct viu_fh *fh = priv; | ||
635 | |||
636 | f->fmt.pix.width = fh->width; | ||
637 | f->fmt.pix.height = fh->height; | ||
638 | f->fmt.pix.field = fh->vb_vidq.field; | ||
639 | f->fmt.pix.pixelformat = fh->fmt->pixelformat; | ||
640 | f->fmt.pix.bytesperline = | ||
641 | (f->fmt.pix.width * fh->fmt->depth) >> 3; | ||
642 | f->fmt.pix.sizeimage = fh->sizeimage; | ||
643 | return 0; | ||
644 | } | ||
645 | |||
646 | static int vidioc_try_fmt_cap(struct file *file, void *priv, | ||
647 | struct v4l2_format *f) | ||
648 | { | ||
649 | struct viu_fmt *fmt; | ||
650 | enum v4l2_field field; | ||
651 | unsigned int maxw, maxh; | ||
652 | |||
653 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
654 | if (!fmt) { | ||
655 | dprintk(1, "Fourcc format (0x%08x) invalid.", | ||
656 | f->fmt.pix.pixelformat); | ||
657 | return -EINVAL; | ||
658 | } | ||
659 | |||
660 | field = f->fmt.pix.field; | ||
661 | |||
662 | if (field == V4L2_FIELD_ANY) { | ||
663 | field = V4L2_FIELD_INTERLACED; | ||
664 | } else if (field != V4L2_FIELD_INTERLACED) { | ||
665 | dprintk(1, "Field type invalid.\n"); | ||
666 | return -EINVAL; | ||
667 | } | ||
668 | |||
669 | maxw = norm_maxw(); | ||
670 | maxh = norm_maxh(); | ||
671 | |||
672 | f->fmt.pix.field = field; | ||
673 | if (f->fmt.pix.height < 32) | ||
674 | f->fmt.pix.height = 32; | ||
675 | if (f->fmt.pix.height > maxh) | ||
676 | f->fmt.pix.height = maxh; | ||
677 | if (f->fmt.pix.width < 48) | ||
678 | f->fmt.pix.width = 48; | ||
679 | if (f->fmt.pix.width > maxw) | ||
680 | f->fmt.pix.width = maxw; | ||
681 | f->fmt.pix.width &= ~0x03; | ||
682 | f->fmt.pix.bytesperline = | ||
683 | (f->fmt.pix.width * fmt->depth) >> 3; | ||
684 | |||
685 | return 0; | ||
686 | } | ||
687 | |||
688 | static int vidioc_s_fmt_cap(struct file *file, void *priv, | ||
689 | struct v4l2_format *f) | ||
690 | { | ||
691 | struct viu_fh *fh = priv; | ||
692 | int ret; | ||
693 | |||
694 | ret = vidioc_try_fmt_cap(file, fh, f); | ||
695 | if (ret < 0) | ||
696 | return ret; | ||
697 | |||
698 | fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
699 | fh->width = f->fmt.pix.width; | ||
700 | fh->height = f->fmt.pix.height; | ||
701 | fh->sizeimage = f->fmt.pix.sizeimage; | ||
702 | fh->vb_vidq.field = f->fmt.pix.field; | ||
703 | fh->type = f->type; | ||
704 | dprintk(1, "set to pixelformat '%4.6s'\n", (char *)&fh->fmt->name); | ||
705 | return 0; | ||
706 | } | ||
707 | |||
708 | static int vidioc_g_fmt_overlay(struct file *file, void *priv, | ||
709 | struct v4l2_format *f) | ||
710 | { | ||
711 | struct viu_fh *fh = priv; | ||
712 | |||
713 | f->fmt.win = fh->win; | ||
714 | return 0; | ||
715 | } | ||
716 | |||
717 | static int verify_preview(struct viu_dev *dev, struct v4l2_window *win) | ||
718 | { | ||
719 | enum v4l2_field field; | ||
720 | int maxw, maxh; | ||
721 | |||
722 | if (dev->ovbuf.base == NULL) | ||
723 | return -EINVAL; | ||
724 | if (dev->ovfmt == NULL) | ||
725 | return -EINVAL; | ||
726 | if (win->w.width < 48 || win->w.height < 32) | ||
727 | return -EINVAL; | ||
728 | |||
729 | field = win->field; | ||
730 | maxw = dev->crop_current.width; | ||
731 | maxh = dev->crop_current.height; | ||
732 | |||
733 | if (field == V4L2_FIELD_ANY) { | ||
734 | field = (win->w.height > maxh/2) | ||
735 | ? V4L2_FIELD_INTERLACED | ||
736 | : V4L2_FIELD_TOP; | ||
737 | } | ||
738 | switch (field) { | ||
739 | case V4L2_FIELD_TOP: | ||
740 | case V4L2_FIELD_BOTTOM: | ||
741 | maxh = maxh / 2; | ||
742 | break; | ||
743 | case V4L2_FIELD_INTERLACED: | ||
744 | break; | ||
745 | default: | ||
746 | return -EINVAL; | ||
747 | } | ||
748 | |||
749 | win->field = field; | ||
750 | if (win->w.width > maxw) | ||
751 | win->w.width = maxw; | ||
752 | if (win->w.height > maxh) | ||
753 | win->w.height = maxh; | ||
754 | return 0; | ||
755 | } | ||
756 | |||
757 | inline void viu_activate_overlay(struct viu_reg *viu_reg) | ||
758 | { | ||
759 | struct viu_reg *vr = viu_reg; | ||
760 | |||
761 | out_be32(&vr->field_base_addr, reg_val.field_base_addr); | ||
762 | out_be32(&vr->dma_inc, reg_val.dma_inc); | ||
763 | out_be32(&vr->picture_count, reg_val.picture_count); | ||
764 | } | ||
765 | |||
766 | static int viu_start_preview(struct viu_dev *dev, struct viu_fh *fh) | ||
767 | { | ||
768 | int bpp; | ||
769 | |||
770 | dprintk(1, "%s %dx%d %s\n", __func__, | ||
771 | fh->win.w.width, fh->win.w.height, dev->ovfmt->name); | ||
772 | |||
773 | reg_val.status_cfg = 0; | ||
774 | |||
775 | /* setup window */ | ||
776 | reg_val.picture_count = (fh->win.w.height / 2) << 16 | | ||
777 | fh->win.w.width; | ||
778 | |||
779 | /* setup color depth and dma increment */ | ||
780 | bpp = dev->ovfmt->depth / 8; | ||
781 | switch (bpp) { | ||
782 | case 2: | ||
783 | reg_val.status_cfg &= ~MODE_32BIT; | ||
784 | reg_val.dma_inc = fh->win.w.width * 2; | ||
785 | break; | ||
786 | case 4: | ||
787 | reg_val.status_cfg |= MODE_32BIT; | ||
788 | reg_val.dma_inc = fh->win.w.width * 4; | ||
789 | break; | ||
790 | default: | ||
791 | dprintk(0, "device doesn't support color depth(%d)\n", | ||
792 | bpp * 8); | ||
793 | return -EINVAL; | ||
794 | } | ||
795 | |||
796 | dev->ovfield = fh->win.field; | ||
797 | if (!V4L2_FIELD_HAS_BOTH(dev->ovfield)) | ||
798 | reg_val.dma_inc = 0; | ||
799 | |||
800 | reg_val.status_cfg |= DMA_ACT | INT_DMA_END_EN | INT_FIELD_EN; | ||
801 | |||
802 | /* setup the base address of the overlay buffer */ | ||
803 | reg_val.field_base_addr = (u32)dev->ovbuf.base; | ||
804 | |||
805 | dev->ovenable = 1; | ||
806 | viu_activate_overlay(dev->vr); | ||
807 | |||
808 | /* start dma */ | ||
809 | viu_start_dma(dev); | ||
810 | return 0; | ||
811 | } | ||
812 | |||
813 | static int vidioc_s_fmt_overlay(struct file *file, void *priv, | ||
814 | struct v4l2_format *f) | ||
815 | { | ||
816 | struct viu_fh *fh = priv; | ||
817 | struct viu_dev *dev = (struct viu_dev *)fh->dev; | ||
818 | unsigned long flags; | ||
819 | int err; | ||
820 | |||
821 | err = verify_preview(dev, &f->fmt.win); | ||
822 | if (err) | ||
823 | return err; | ||
824 | |||
825 | mutex_lock(&dev->lock); | ||
826 | fh->win = f->fmt.win; | ||
827 | |||
828 | spin_lock_irqsave(&dev->slock, flags); | ||
829 | viu_start_preview(dev, fh); | ||
830 | spin_unlock_irqrestore(&dev->slock, flags); | ||
831 | mutex_unlock(&dev->lock); | ||
832 | return 0; | ||
833 | } | ||
834 | |||
835 | static int vidioc_try_fmt_overlay(struct file *file, void *priv, | ||
836 | struct v4l2_format *f) | ||
837 | { | ||
838 | return 0; | ||
839 | } | ||
840 | |||
841 | int vidioc_g_fbuf(struct file *file, void *priv, struct v4l2_framebuffer *arg) | ||
842 | { | ||
843 | struct viu_fh *fh = priv; | ||
844 | struct viu_dev *dev = fh->dev; | ||
845 | struct v4l2_framebuffer *fb = arg; | ||
846 | |||
847 | *fb = dev->ovbuf; | ||
848 | fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING; | ||
849 | return 0; | ||
850 | } | ||
851 | |||
852 | int vidioc_s_fbuf(struct file *file, void *priv, struct v4l2_framebuffer *arg) | ||
853 | { | ||
854 | struct viu_fh *fh = priv; | ||
855 | struct viu_dev *dev = fh->dev; | ||
856 | struct v4l2_framebuffer *fb = arg; | ||
857 | struct viu_fmt *fmt; | ||
858 | |||
859 | if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO)) | ||
860 | return -EPERM; | ||
861 | |||
862 | /* check args */ | ||
863 | fmt = format_by_fourcc(fb->fmt.pixelformat); | ||
864 | if (fmt == NULL) | ||
865 | return -EINVAL; | ||
866 | |||
867 | /* ok, accept it */ | ||
868 | dev->ovbuf = *fb; | ||
869 | dev->ovfmt = fmt; | ||
870 | if (dev->ovbuf.fmt.bytesperline == 0) { | ||
871 | dev->ovbuf.fmt.bytesperline = | ||
872 | dev->ovbuf.fmt.width * fmt->depth / 8; | ||
873 | } | ||
874 | return 0; | ||
875 | } | ||
876 | |||
877 | static int vidioc_reqbufs(struct file *file, void *priv, | ||
878 | struct v4l2_requestbuffers *p) | ||
879 | { | ||
880 | struct viu_fh *fh = priv; | ||
881 | |||
882 | return videobuf_reqbufs(&fh->vb_vidq, p); | ||
883 | } | ||
884 | |||
885 | static int vidioc_querybuf(struct file *file, void *priv, | ||
886 | struct v4l2_buffer *p) | ||
887 | { | ||
888 | struct viu_fh *fh = priv; | ||
889 | |||
890 | return videobuf_querybuf(&fh->vb_vidq, p); | ||
891 | } | ||
892 | |||
893 | static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
894 | { | ||
895 | struct viu_fh *fh = priv; | ||
896 | |||
897 | return videobuf_qbuf(&fh->vb_vidq, p); | ||
898 | } | ||
899 | |||
900 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
901 | { | ||
902 | struct viu_fh *fh = priv; | ||
903 | |||
904 | return videobuf_dqbuf(&fh->vb_vidq, p, | ||
905 | file->f_flags & O_NONBLOCK); | ||
906 | } | ||
907 | |||
908 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
909 | { | ||
910 | struct viu_fh *fh = priv; | ||
911 | |||
912 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
913 | return -EINVAL; | ||
914 | if (fh->type != i) | ||
915 | return -EINVAL; | ||
916 | |||
917 | return videobuf_streamon(&fh->vb_vidq); | ||
918 | } | ||
919 | |||
920 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
921 | { | ||
922 | struct viu_fh *fh = priv; | ||
923 | |||
924 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
925 | return -EINVAL; | ||
926 | if (fh->type != i) | ||
927 | return -EINVAL; | ||
928 | |||
929 | return videobuf_streamoff(&fh->vb_vidq); | ||
930 | } | ||
931 | |||
932 | #define decoder_call(viu, o, f, args...) \ | ||
933 | v4l2_subdev_call(viu->decoder, o, f, ##args) | ||
934 | |||
935 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id) | ||
936 | { | ||
937 | struct viu_fh *fh = priv; | ||
938 | |||
939 | decoder_call(fh->dev, core, s_std, *id); | ||
940 | return 0; | ||
941 | } | ||
942 | |||
943 | /* only one input in this driver */ | ||
944 | static int vidioc_enum_input(struct file *file, void *priv, | ||
945 | struct v4l2_input *inp) | ||
946 | { | ||
947 | struct viu_fh *fh = priv; | ||
948 | |||
949 | if (inp->index != 0) | ||
950 | return -EINVAL; | ||
951 | |||
952 | inp->type = V4L2_INPUT_TYPE_CAMERA; | ||
953 | inp->std = fh->dev->vdev->tvnorms; | ||
954 | strcpy(inp->name, "Camera"); | ||
955 | return 0; | ||
956 | } | ||
957 | |||
958 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) | ||
959 | { | ||
960 | *i = 0; | ||
961 | return 0; | ||
962 | } | ||
963 | |||
964 | static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | ||
965 | { | ||
966 | struct viu_fh *fh = priv; | ||
967 | |||
968 | if (i > 1) | ||
969 | return -EINVAL; | ||
970 | |||
971 | decoder_call(fh->dev, video, s_routing, i, 0, 0); | ||
972 | return 0; | ||
973 | } | ||
974 | |||
975 | /* Controls */ | ||
976 | static int vidioc_queryctrl(struct file *file, void *priv, | ||
977 | struct v4l2_queryctrl *qc) | ||
978 | { | ||
979 | int i; | ||
980 | |||
981 | for (i = 0; i < ARRAY_SIZE(viu_qctrl); i++) { | ||
982 | if (qc->id && qc->id == viu_qctrl[i].id) { | ||
983 | memcpy(qc, &(viu_qctrl[i]), sizeof(*qc)); | ||
984 | return 0; | ||
985 | } | ||
986 | } | ||
987 | return -EINVAL; | ||
988 | } | ||
989 | |||
990 | static int vidioc_g_ctrl(struct file *file, void *priv, | ||
991 | struct v4l2_control *ctrl) | ||
992 | { | ||
993 | int i; | ||
994 | |||
995 | for (i = 0; i < ARRAY_SIZE(viu_qctrl); i++) { | ||
996 | if (ctrl->id == viu_qctrl[i].id) { | ||
997 | ctrl->value = qctl_regs[i]; | ||
998 | return 0; | ||
999 | } | ||
1000 | } | ||
1001 | return -EINVAL; | ||
1002 | } | ||
1003 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
1004 | struct v4l2_control *ctrl) | ||
1005 | { | ||
1006 | int i; | ||
1007 | |||
1008 | for (i = 0; i < ARRAY_SIZE(viu_qctrl); i++) { | ||
1009 | if (ctrl->id == viu_qctrl[i].id) { | ||
1010 | if (ctrl->value < viu_qctrl[i].minimum | ||
1011 | || ctrl->value > viu_qctrl[i].maximum) | ||
1012 | return -ERANGE; | ||
1013 | qctl_regs[i] = ctrl->value; | ||
1014 | return 0; | ||
1015 | } | ||
1016 | } | ||
1017 | return -EINVAL; | ||
1018 | } | ||
1019 | |||
1020 | inline void viu_activate_next_buf(struct viu_dev *dev, | ||
1021 | struct viu_dmaqueue *viuq) | ||
1022 | { | ||
1023 | struct viu_dmaqueue *vidq = viuq; | ||
1024 | struct viu_buf *buf; | ||
1025 | |||
1026 | /* launch another DMA operation for an active/queued buffer */ | ||
1027 | if (!list_empty(&vidq->active)) { | ||
1028 | buf = list_entry(vidq->active.next, struct viu_buf, | ||
1029 | vb.queue); | ||
1030 | dprintk(1, "start another queued buffer: 0x%p\n", buf); | ||
1031 | buffer_activate(dev, buf); | ||
1032 | } else if (!list_empty(&vidq->queued)) { | ||
1033 | buf = list_entry(vidq->queued.next, struct viu_buf, | ||
1034 | vb.queue); | ||
1035 | list_del(&buf->vb.queue); | ||
1036 | |||
1037 | dprintk(1, "start another queued buffer: 0x%p\n", buf); | ||
1038 | list_add_tail(&buf->vb.queue, &vidq->active); | ||
1039 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
1040 | buffer_activate(dev, buf); | ||
1041 | } | ||
1042 | } | ||
1043 | |||
1044 | inline void viu_default_settings(struct viu_reg *viu_reg) | ||
1045 | { | ||
1046 | struct viu_reg *vr = viu_reg; | ||
1047 | |||
1048 | out_be32(&vr->luminance, 0x9512A254); | ||
1049 | out_be32(&vr->chroma_r, 0x03310000); | ||
1050 | out_be32(&vr->chroma_g, 0x06600F38); | ||
1051 | out_be32(&vr->chroma_b, 0x00000409); | ||
1052 | out_be32(&vr->alpha, 0x000000ff); | ||
1053 | out_be32(&vr->req_alarm, 0x00000090); | ||
1054 | dprintk(1, "status reg: 0x%08x, field base: 0x%08x\n", | ||
1055 | in_be32(&vr->status_cfg), in_be32(&vr->field_base_addr)); | ||
1056 | } | ||
1057 | |||
1058 | static void viu_overlay_intr(struct viu_dev *dev, u32 status) | ||
1059 | { | ||
1060 | struct viu_reg *vr = dev->vr; | ||
1061 | |||
1062 | if (status & INT_DMA_END_STATUS) | ||
1063 | dev->dma_done = 1; | ||
1064 | |||
1065 | if (status & INT_FIELD_STATUS) { | ||
1066 | if (dev->dma_done) { | ||
1067 | u32 addr = reg_val.field_base_addr; | ||
1068 | |||
1069 | dev->dma_done = 0; | ||
1070 | if (status & FIELD_NO) | ||
1071 | addr += reg_val.dma_inc; | ||
1072 | |||
1073 | out_be32(&vr->field_base_addr, addr); | ||
1074 | out_be32(&vr->dma_inc, reg_val.dma_inc); | ||
1075 | out_be32(&vr->status_cfg, | ||
1076 | (status & 0xffc0ffff) | | ||
1077 | (status & INT_ALL_STATUS) | | ||
1078 | reg_val.status_cfg); | ||
1079 | } else if (status & INT_VSYNC_STATUS) { | ||
1080 | out_be32(&vr->status_cfg, | ||
1081 | (status & 0xffc0ffff) | | ||
1082 | (status & INT_ALL_STATUS) | | ||
1083 | reg_val.status_cfg); | ||
1084 | } | ||
1085 | } | ||
1086 | } | ||
1087 | |||
1088 | static void viu_capture_intr(struct viu_dev *dev, u32 status) | ||
1089 | { | ||
1090 | struct viu_dmaqueue *vidq = &dev->vidq; | ||
1091 | struct viu_reg *vr = dev->vr; | ||
1092 | struct viu_buf *buf; | ||
1093 | int field_num; | ||
1094 | int need_two; | ||
1095 | int dma_done = 0; | ||
1096 | |||
1097 | field_num = status & FIELD_NO; | ||
1098 | need_two = V4L2_FIELD_HAS_BOTH(dev->capfield); | ||
1099 | |||
1100 | if (status & INT_DMA_END_STATUS) { | ||
1101 | dma_done = 1; | ||
1102 | if (((field_num == 0) && (dev->field == 0)) || | ||
1103 | (field_num && (dev->field == 1))) | ||
1104 | dev->field++; | ||
1105 | } | ||
1106 | |||
1107 | if (status & INT_FIELD_STATUS) { | ||
1108 | dprintk(1, "irq: field %d, done %d\n", | ||
1109 | !!field_num, dma_done); | ||
1110 | if (unlikely(dev->first)) { | ||
1111 | if (field_num == 0) { | ||
1112 | dev->first = 0; | ||
1113 | dprintk(1, "activate first buf\n"); | ||
1114 | viu_activate_next_buf(dev, vidq); | ||
1115 | } else | ||
1116 | dprintk(1, "wait field 0\n"); | ||
1117 | return; | ||
1118 | } | ||
1119 | |||
1120 | /* setup buffer address for next dma operation */ | ||
1121 | if (!list_empty(&vidq->active)) { | ||
1122 | u32 addr = reg_val.field_base_addr; | ||
1123 | |||
1124 | if (field_num && need_two) { | ||
1125 | addr += reg_val.dma_inc; | ||
1126 | dprintk(1, "field 1, 0x%lx, dev field %d\n", | ||
1127 | (unsigned long)addr, dev->field); | ||
1128 | } | ||
1129 | out_be32(&vr->field_base_addr, addr); | ||
1130 | out_be32(&vr->dma_inc, reg_val.dma_inc); | ||
1131 | out_be32(&vr->status_cfg, | ||
1132 | (status & 0xffc0ffff) | | ||
1133 | (status & INT_ALL_STATUS) | | ||
1134 | reg_val.status_cfg); | ||
1135 | return; | ||
1136 | } | ||
1137 | } | ||
1138 | |||
1139 | if (dma_done && field_num && (dev->field == 2)) { | ||
1140 | dev->field = 0; | ||
1141 | buf = list_entry(vidq->active.next, | ||
1142 | struct viu_buf, vb.queue); | ||
1143 | dprintk(1, "viu/0: [%p/%d] 0x%lx/0x%lx: dma complete\n", | ||
1144 | buf, buf->vb.i, | ||
1145 | (unsigned long)videobuf_to_dma_contig(&buf->vb), | ||
1146 | (unsigned long)in_be32(&vr->field_base_addr)); | ||
1147 | |||
1148 | if (waitqueue_active(&buf->vb.done)) { | ||
1149 | list_del(&buf->vb.queue); | ||
1150 | do_gettimeofday(&buf->vb.ts); | ||
1151 | buf->vb.state = VIDEOBUF_DONE; | ||
1152 | buf->vb.field_count++; | ||
1153 | wake_up(&buf->vb.done); | ||
1154 | } | ||
1155 | /* activate next dma buffer */ | ||
1156 | viu_activate_next_buf(dev, vidq); | ||
1157 | } | ||
1158 | } | ||
1159 | |||
1160 | static irqreturn_t viu_intr(int irq, void *dev_id) | ||
1161 | { | ||
1162 | struct viu_dev *dev = (struct viu_dev *)dev_id; | ||
1163 | struct viu_reg *vr = dev->vr; | ||
1164 | u32 status; | ||
1165 | u32 error; | ||
1166 | |||
1167 | status = in_be32(&vr->status_cfg); | ||
1168 | |||
1169 | if (status & INT_ERROR_STATUS) { | ||
1170 | dev->irqs.error_irq++; | ||
1171 | error = status & ERR_MASK; | ||
1172 | if (error) | ||
1173 | dprintk(1, "Err: error(%d), times:%d!\n", | ||
1174 | error >> 4, dev->irqs.error_irq); | ||
1175 | /* Clear interrupt error bit and error flags */ | ||
1176 | out_be32(&vr->status_cfg, | ||
1177 | (status & 0xffc0ffff) | INT_ERROR_STATUS); | ||
1178 | } | ||
1179 | |||
1180 | if (status & INT_DMA_END_STATUS) { | ||
1181 | dev->irqs.dma_end_irq++; | ||
1182 | dev->dma_done = 1; | ||
1183 | dprintk(2, "VIU DMA end interrupt times: %d\n", | ||
1184 | dev->irqs.dma_end_irq); | ||
1185 | } | ||
1186 | |||
1187 | if (status & INT_HSYNC_STATUS) | ||
1188 | dev->irqs.hsync_irq++; | ||
1189 | |||
1190 | if (status & INT_FIELD_STATUS) { | ||
1191 | dev->irqs.field_irq++; | ||
1192 | dprintk(2, "VIU field interrupt times: %d\n", | ||
1193 | dev->irqs.field_irq); | ||
1194 | } | ||
1195 | |||
1196 | if (status & INT_VSTART_STATUS) | ||
1197 | dev->irqs.vstart_irq++; | ||
1198 | |||
1199 | if (status & INT_VSYNC_STATUS) { | ||
1200 | dev->irqs.vsync_irq++; | ||
1201 | dprintk(2, "VIU vsync interrupt times: %d\n", | ||
1202 | dev->irqs.vsync_irq); | ||
1203 | } | ||
1204 | |||
1205 | /* clear all pending irqs */ | ||
1206 | status = in_be32(&vr->status_cfg); | ||
1207 | out_be32(&vr->status_cfg, | ||
1208 | (status & 0xffc0ffff) | (status & INT_ALL_STATUS)); | ||
1209 | |||
1210 | if (dev->ovenable) { | ||
1211 | viu_overlay_intr(dev, status); | ||
1212 | return IRQ_HANDLED; | ||
1213 | } | ||
1214 | |||
1215 | /* Capture mode */ | ||
1216 | viu_capture_intr(dev, status); | ||
1217 | return IRQ_HANDLED; | ||
1218 | } | ||
1219 | |||
1220 | /* | ||
1221 | * File operations for the device | ||
1222 | */ | ||
1223 | static int viu_open(struct file *file) | ||
1224 | { | ||
1225 | struct video_device *vdev = video_devdata(file); | ||
1226 | struct viu_dev *dev = video_get_drvdata(vdev); | ||
1227 | struct viu_fh *fh; | ||
1228 | struct viu_reg *vr; | ||
1229 | int minor = vdev->minor; | ||
1230 | u32 status_cfg; | ||
1231 | int i; | ||
1232 | |||
1233 | dprintk(1, "viu: open (minor=%d)\n", minor); | ||
1234 | |||
1235 | dev->users++; | ||
1236 | if (dev->users > 1) { | ||
1237 | dev->users--; | ||
1238 | return -EBUSY; | ||
1239 | } | ||
1240 | |||
1241 | vr = dev->vr; | ||
1242 | |||
1243 | dprintk(1, "open minor=%d type=%s users=%d\n", minor, | ||
1244 | v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users); | ||
1245 | |||
1246 | /* allocate and initialize per filehandle data */ | ||
1247 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
1248 | if (!fh) { | ||
1249 | dev->users--; | ||
1250 | return -ENOMEM; | ||
1251 | } | ||
1252 | |||
1253 | file->private_data = fh; | ||
1254 | fh->dev = dev; | ||
1255 | |||
1256 | fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1257 | fh->fmt = format_by_fourcc(V4L2_PIX_FMT_RGB32); | ||
1258 | fh->width = norm_maxw(); | ||
1259 | fh->height = norm_maxh(); | ||
1260 | dev->crop_current.width = fh->width; | ||
1261 | dev->crop_current.height = fh->height; | ||
1262 | |||
1263 | /* Put all controls at a sane state */ | ||
1264 | for (i = 0; i < ARRAY_SIZE(viu_qctrl); i++) | ||
1265 | qctl_regs[i] = viu_qctrl[i].default_value; | ||
1266 | |||
1267 | dprintk(1, "Open: fh=0x%08lx, dev=0x%08lx, dev->vidq=0x%08lx\n", | ||
1268 | (unsigned long)fh, (unsigned long)dev, | ||
1269 | (unsigned long)&dev->vidq); | ||
1270 | dprintk(1, "Open: list_empty queued=%d\n", | ||
1271 | list_empty(&dev->vidq.queued)); | ||
1272 | dprintk(1, "Open: list_empty active=%d\n", | ||
1273 | list_empty(&dev->vidq.active)); | ||
1274 | |||
1275 | viu_default_settings(vr); | ||
1276 | |||
1277 | status_cfg = in_be32(&vr->status_cfg); | ||
1278 | out_be32(&vr->status_cfg, | ||
1279 | status_cfg & ~(INT_VSYNC_EN | INT_HSYNC_EN | | ||
1280 | INT_FIELD_EN | INT_VSTART_EN | | ||
1281 | INT_DMA_END_EN | INT_ERROR_EN | INT_ECC_EN)); | ||
1282 | |||
1283 | status_cfg = in_be32(&vr->status_cfg); | ||
1284 | out_be32(&vr->status_cfg, status_cfg | INT_ALL_STATUS); | ||
1285 | |||
1286 | spin_lock_init(&fh->vbq_lock); | ||
1287 | videobuf_queue_dma_contig_init(&fh->vb_vidq, &viu_video_qops, | ||
1288 | dev->dev, &fh->vbq_lock, | ||
1289 | fh->type, V4L2_FIELD_INTERLACED, | ||
1290 | sizeof(struct viu_buf), fh); | ||
1291 | return 0; | ||
1292 | } | ||
1293 | |||
1294 | static ssize_t viu_read(struct file *file, char __user *data, size_t count, | ||
1295 | loff_t *ppos) | ||
1296 | { | ||
1297 | struct viu_fh *fh = file->private_data; | ||
1298 | struct viu_dev *dev = fh->dev; | ||
1299 | int ret = 0; | ||
1300 | |||
1301 | dprintk(2, "%s\n", __func__); | ||
1302 | if (dev->ovenable) | ||
1303 | dev->ovenable = 0; | ||
1304 | |||
1305 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1306 | viu_start_dma(dev); | ||
1307 | ret = videobuf_read_stream(&fh->vb_vidq, data, count, | ||
1308 | ppos, 0, file->f_flags & O_NONBLOCK); | ||
1309 | return ret; | ||
1310 | } | ||
1311 | return 0; | ||
1312 | } | ||
1313 | |||
1314 | static unsigned int viu_poll(struct file *file, struct poll_table_struct *wait) | ||
1315 | { | ||
1316 | struct viu_fh *fh = file->private_data; | ||
1317 | struct videobuf_queue *q = &fh->vb_vidq; | ||
1318 | |||
1319 | if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) | ||
1320 | return POLLERR; | ||
1321 | |||
1322 | return videobuf_poll_stream(file, q, wait); | ||
1323 | } | ||
1324 | |||
1325 | static int viu_release(struct file *file) | ||
1326 | { | ||
1327 | struct viu_fh *fh = file->private_data; | ||
1328 | struct viu_dev *dev = fh->dev; | ||
1329 | int minor = video_devdata(file)->minor; | ||
1330 | |||
1331 | viu_stop_dma(dev); | ||
1332 | videobuf_stop(&fh->vb_vidq); | ||
1333 | |||
1334 | kfree(fh); | ||
1335 | |||
1336 | dev->users--; | ||
1337 | dprintk(1, "close (minor=%d, users=%d)\n", | ||
1338 | minor, dev->users); | ||
1339 | return 0; | ||
1340 | } | ||
1341 | |||
1342 | void viu_reset(struct viu_reg *reg) | ||
1343 | { | ||
1344 | out_be32(®->status_cfg, 0); | ||
1345 | out_be32(®->luminance, 0x9512a254); | ||
1346 | out_be32(®->chroma_r, 0x03310000); | ||
1347 | out_be32(®->chroma_g, 0x06600f38); | ||
1348 | out_be32(®->chroma_b, 0x00000409); | ||
1349 | out_be32(®->field_base_addr, 0); | ||
1350 | out_be32(®->dma_inc, 0); | ||
1351 | out_be32(®->picture_count, 0x01e002d0); | ||
1352 | out_be32(®->req_alarm, 0x00000090); | ||
1353 | out_be32(®->alpha, 0x000000ff); | ||
1354 | } | ||
1355 | |||
1356 | static int viu_mmap(struct file *file, struct vm_area_struct *vma) | ||
1357 | { | ||
1358 | struct viu_fh *fh = file->private_data; | ||
1359 | int ret; | ||
1360 | |||
1361 | dprintk(1, "mmap called, vma=0x%08lx\n", (unsigned long)vma); | ||
1362 | |||
1363 | ret = videobuf_mmap_mapper(&fh->vb_vidq, vma); | ||
1364 | |||
1365 | dprintk(1, "vma start=0x%08lx, size=%ld, ret=%d\n", | ||
1366 | (unsigned long)vma->vm_start, | ||
1367 | (unsigned long)vma->vm_end-(unsigned long)vma->vm_start, | ||
1368 | ret); | ||
1369 | |||
1370 | return ret; | ||
1371 | } | ||
1372 | |||
1373 | static struct v4l2_file_operations viu_fops = { | ||
1374 | .owner = THIS_MODULE, | ||
1375 | .open = viu_open, | ||
1376 | .release = viu_release, | ||
1377 | .read = viu_read, | ||
1378 | .poll = viu_poll, | ||
1379 | .ioctl = video_ioctl2, /* V4L2 ioctl handler */ | ||
1380 | .mmap = viu_mmap, | ||
1381 | }; | ||
1382 | |||
1383 | static const struct v4l2_ioctl_ops viu_ioctl_ops = { | ||
1384 | .vidioc_querycap = vidioc_querycap, | ||
1385 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt, | ||
1386 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_cap, | ||
1387 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_cap, | ||
1388 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_cap, | ||
1389 | .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt, | ||
1390 | .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_overlay, | ||
1391 | .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_overlay, | ||
1392 | .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_overlay, | ||
1393 | .vidioc_g_fbuf = vidioc_g_fbuf, | ||
1394 | .vidioc_s_fbuf = vidioc_s_fbuf, | ||
1395 | .vidioc_reqbufs = vidioc_reqbufs, | ||
1396 | .vidioc_querybuf = vidioc_querybuf, | ||
1397 | .vidioc_qbuf = vidioc_qbuf, | ||
1398 | .vidioc_dqbuf = vidioc_dqbuf, | ||
1399 | .vidioc_s_std = vidioc_s_std, | ||
1400 | .vidioc_enum_input = vidioc_enum_input, | ||
1401 | .vidioc_g_input = vidioc_g_input, | ||
1402 | .vidioc_s_input = vidioc_s_input, | ||
1403 | .vidioc_queryctrl = vidioc_queryctrl, | ||
1404 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
1405 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
1406 | .vidioc_streamon = vidioc_streamon, | ||
1407 | .vidioc_streamoff = vidioc_streamoff, | ||
1408 | }; | ||
1409 | |||
1410 | static struct video_device viu_template = { | ||
1411 | .name = "FSL viu", | ||
1412 | .fops = &viu_fops, | ||
1413 | .minor = -1, | ||
1414 | .ioctl_ops = &viu_ioctl_ops, | ||
1415 | .release = video_device_release, | ||
1416 | |||
1417 | .tvnorms = V4L2_STD_NTSC_M | V4L2_STD_PAL, | ||
1418 | .current_norm = V4L2_STD_NTSC_M, | ||
1419 | }; | ||
1420 | |||
1421 | static int __devinit viu_of_probe(struct of_device *op, | ||
1422 | const struct of_device_id *match) | ||
1423 | { | ||
1424 | struct viu_dev *viu_dev; | ||
1425 | struct video_device *vdev; | ||
1426 | struct resource r; | ||
1427 | struct viu_reg __iomem *viu_regs; | ||
1428 | struct i2c_adapter *ad; | ||
1429 | int ret, viu_irq; | ||
1430 | |||
1431 | ret = of_address_to_resource(op->dev.of_node, 0, &r); | ||
1432 | if (ret) { | ||
1433 | dev_err(&op->dev, "Can't parse device node resource\n"); | ||
1434 | return -ENODEV; | ||
1435 | } | ||
1436 | |||
1437 | viu_irq = irq_of_parse_and_map(op->dev.of_node, 0); | ||
1438 | if (viu_irq == NO_IRQ) { | ||
1439 | dev_err(&op->dev, "Error while mapping the irq\n"); | ||
1440 | return -EINVAL; | ||
1441 | } | ||
1442 | |||
1443 | /* request mem region */ | ||
1444 | if (!devm_request_mem_region(&op->dev, r.start, | ||
1445 | sizeof(struct viu_reg), DRV_NAME)) { | ||
1446 | dev_err(&op->dev, "Error while requesting mem region\n"); | ||
1447 | ret = -EBUSY; | ||
1448 | goto err; | ||
1449 | } | ||
1450 | |||
1451 | /* remap registers */ | ||
1452 | viu_regs = devm_ioremap(&op->dev, r.start, sizeof(struct viu_reg)); | ||
1453 | if (!viu_regs) { | ||
1454 | dev_err(&op->dev, "Can't map register set\n"); | ||
1455 | ret = -ENOMEM; | ||
1456 | goto err; | ||
1457 | } | ||
1458 | |||
1459 | /* Prepare our private structure */ | ||
1460 | viu_dev = devm_kzalloc(&op->dev, sizeof(struct viu_dev), GFP_ATOMIC); | ||
1461 | if (!viu_dev) { | ||
1462 | dev_err(&op->dev, "Can't allocate private structure\n"); | ||
1463 | ret = -ENOMEM; | ||
1464 | goto err; | ||
1465 | } | ||
1466 | |||
1467 | viu_dev->vr = viu_regs; | ||
1468 | viu_dev->irq = viu_irq; | ||
1469 | viu_dev->dev = &op->dev; | ||
1470 | |||
1471 | /* init video dma queues */ | ||
1472 | INIT_LIST_HEAD(&viu_dev->vidq.active); | ||
1473 | INIT_LIST_HEAD(&viu_dev->vidq.queued); | ||
1474 | |||
1475 | /* initialize locks */ | ||
1476 | mutex_init(&viu_dev->lock); | ||
1477 | |||
1478 | snprintf(viu_dev->v4l2_dev.name, | ||
1479 | sizeof(viu_dev->v4l2_dev.name), "%s", "VIU"); | ||
1480 | ret = v4l2_device_register(viu_dev->dev, &viu_dev->v4l2_dev); | ||
1481 | if (ret < 0) { | ||
1482 | dev_err(&op->dev, "v4l2_device_register() failed: %d\n", ret); | ||
1483 | goto err; | ||
1484 | } | ||
1485 | |||
1486 | ad = i2c_get_adapter(0); | ||
1487 | viu_dev->decoder = v4l2_i2c_new_subdev(&viu_dev->v4l2_dev, ad, | ||
1488 | "saa7115", "saa7113", VIU_VIDEO_DECODER_ADDR, NULL); | ||
1489 | |||
1490 | viu_dev->vidq.timeout.function = viu_vid_timeout; | ||
1491 | viu_dev->vidq.timeout.data = (unsigned long)viu_dev; | ||
1492 | init_timer(&viu_dev->vidq.timeout); | ||
1493 | viu_dev->first = 1; | ||
1494 | |||
1495 | /* Allocate memory for video device */ | ||
1496 | vdev = video_device_alloc(); | ||
1497 | if (vdev == NULL) { | ||
1498 | ret = -ENOMEM; | ||
1499 | goto err_vdev; | ||
1500 | } | ||
1501 | |||
1502 | memcpy(vdev, &viu_template, sizeof(viu_template)); | ||
1503 | |||
1504 | vdev->v4l2_dev = &viu_dev->v4l2_dev; | ||
1505 | |||
1506 | viu_dev->vdev = vdev; | ||
1507 | |||
1508 | video_set_drvdata(viu_dev->vdev, viu_dev); | ||
1509 | |||
1510 | ret = video_register_device(viu_dev->vdev, VFL_TYPE_GRABBER, -1); | ||
1511 | if (ret < 0) { | ||
1512 | video_device_release(viu_dev->vdev); | ||
1513 | goto err_vdev; | ||
1514 | } | ||
1515 | |||
1516 | /* enable VIU clock */ | ||
1517 | viu_dev->clk = clk_get(&op->dev, "viu_clk"); | ||
1518 | if (IS_ERR(viu_dev->clk)) { | ||
1519 | dev_err(&op->dev, "failed to find the clock module!\n"); | ||
1520 | ret = -ENODEV; | ||
1521 | goto err_clk; | ||
1522 | } else { | ||
1523 | clk_enable(viu_dev->clk); | ||
1524 | } | ||
1525 | |||
1526 | /* reset VIU module */ | ||
1527 | viu_reset(viu_dev->vr); | ||
1528 | |||
1529 | /* install interrupt handler */ | ||
1530 | if (request_irq(viu_dev->irq, viu_intr, 0, "viu", (void *)viu_dev)) { | ||
1531 | dev_err(&op->dev, "Request VIU IRQ failed.\n"); | ||
1532 | ret = -ENODEV; | ||
1533 | goto err_irq; | ||
1534 | } | ||
1535 | |||
1536 | dev_info(&op->dev, "Freescale VIU Video Capture Board\n"); | ||
1537 | return ret; | ||
1538 | |||
1539 | err_irq: | ||
1540 | clk_disable(viu_dev->clk); | ||
1541 | clk_put(viu_dev->clk); | ||
1542 | err_clk: | ||
1543 | video_unregister_device(viu_dev->vdev); | ||
1544 | err_vdev: | ||
1545 | i2c_put_adapter(ad); | ||
1546 | v4l2_device_unregister(&viu_dev->v4l2_dev); | ||
1547 | err: | ||
1548 | irq_dispose_mapping(viu_irq); | ||
1549 | return ret; | ||
1550 | } | ||
1551 | |||
1552 | static int __devexit viu_of_remove(struct of_device *op) | ||
1553 | { | ||
1554 | struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev); | ||
1555 | struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev); | ||
1556 | struct v4l2_subdev *sdev = list_entry(v4l2_dev->subdevs.next, | ||
1557 | struct v4l2_subdev, list); | ||
1558 | struct i2c_client *client = v4l2_get_subdevdata(sdev); | ||
1559 | |||
1560 | free_irq(dev->irq, (void *)dev); | ||
1561 | irq_dispose_mapping(dev->irq); | ||
1562 | |||
1563 | clk_disable(dev->clk); | ||
1564 | clk_put(dev->clk); | ||
1565 | |||
1566 | video_unregister_device(dev->vdev); | ||
1567 | i2c_put_adapter(client->adapter); | ||
1568 | v4l2_device_unregister(&dev->v4l2_dev); | ||
1569 | return 0; | ||
1570 | } | ||
1571 | |||
1572 | #ifdef CONFIG_PM | ||
1573 | static int viu_suspend(struct of_device *op, pm_message_t state) | ||
1574 | { | ||
1575 | struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev); | ||
1576 | struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev); | ||
1577 | |||
1578 | clk_disable(dev->clk); | ||
1579 | return 0; | ||
1580 | } | ||
1581 | |||
1582 | static int viu_resume(struct of_device *op) | ||
1583 | { | ||
1584 | struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev); | ||
1585 | struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev); | ||
1586 | |||
1587 | clk_enable(dev->clk); | ||
1588 | return 0; | ||
1589 | } | ||
1590 | #endif | ||
1591 | |||
1592 | /* | ||
1593 | * Initialization and module stuff | ||
1594 | */ | ||
1595 | static struct of_device_id mpc512x_viu_of_match[] = { | ||
1596 | { | ||
1597 | .compatible = "fsl,mpc5121-viu", | ||
1598 | }, | ||
1599 | {}, | ||
1600 | }; | ||
1601 | MODULE_DEVICE_TABLE(of, mpc512x_viu_of_match); | ||
1602 | |||
1603 | static struct of_platform_driver viu_of_platform_driver = { | ||
1604 | .probe = viu_of_probe, | ||
1605 | .remove = __devexit_p(viu_of_remove), | ||
1606 | #ifdef CONFIG_PM | ||
1607 | .suspend = viu_suspend, | ||
1608 | .resume = viu_resume, | ||
1609 | #endif | ||
1610 | .driver = { | ||
1611 | .name = DRV_NAME, | ||
1612 | .owner = THIS_MODULE, | ||
1613 | .of_match_table = mpc512x_viu_of_match, | ||
1614 | }, | ||
1615 | }; | ||
1616 | |||
1617 | static int __init viu_init(void) | ||
1618 | { | ||
1619 | return of_register_platform_driver(&viu_of_platform_driver); | ||
1620 | } | ||
1621 | |||
1622 | static void __exit viu_exit(void) | ||
1623 | { | ||
1624 | of_unregister_platform_driver(&viu_of_platform_driver); | ||
1625 | } | ||
1626 | |||
1627 | module_init(viu_init); | ||
1628 | module_exit(viu_exit); | ||
1629 | |||
1630 | MODULE_DESCRIPTION("Freescale Video-In(VIU)"); | ||
1631 | MODULE_AUTHOR("Hongjun Chen"); | ||
1632 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index 5d920e584de7..23db0c29f68c 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig | |||
@@ -246,6 +246,15 @@ config USB_GSPCA_SPCA561 | |||
246 | To compile this driver as a module, choose M here: the | 246 | To compile this driver as a module, choose M here: the |
247 | module will be called gspca_spca561. | 247 | module will be called gspca_spca561. |
248 | 248 | ||
249 | config USB_GSPCA_SPCA1528 | ||
250 | tristate "SPCA1528 USB Camera Driver" | ||
251 | depends on VIDEO_V4L2 && USB_GSPCA | ||
252 | help | ||
253 | Say Y here if you want support for cameras based on the SPCA1528 chip. | ||
254 | |||
255 | To compile this driver as a module, choose M here: the | ||
256 | module will be called gspca_spca1528. | ||
257 | |||
249 | config USB_GSPCA_SQ905 | 258 | config USB_GSPCA_SQ905 |
250 | tristate "SQ Technologies SQ905 based USB Camera Driver" | 259 | tristate "SQ Technologies SQ905 based USB Camera Driver" |
251 | depends on VIDEO_V4L2 && USB_GSPCA | 260 | depends on VIDEO_V4L2 && USB_GSPCA |
@@ -264,6 +273,15 @@ config USB_GSPCA_SQ905C | |||
264 | To compile this driver as a module, choose M here: the | 273 | To compile this driver as a module, choose M here: the |
265 | module will be called gspca_sq905c. | 274 | module will be called gspca_sq905c. |
266 | 275 | ||
276 | config USB_GSPCA_SQ930X | ||
277 | tristate "SQ Technologies SQ930X based USB Camera Driver" | ||
278 | depends on VIDEO_V4L2 && USB_GSPCA | ||
279 | help | ||
280 | Say Y here if you want support for cameras based on the SQ930X chip. | ||
281 | |||
282 | To compile this driver as a module, choose M here: the | ||
283 | module will be called gspca_sq930x. | ||
284 | |||
267 | config USB_GSPCA_STK014 | 285 | config USB_GSPCA_STK014 |
268 | tristate "Syntek DV4000 (STK014) USB Camera Driver" | 286 | tristate "Syntek DV4000 (STK014) USB Camera Driver" |
269 | depends on VIDEO_V4L2 && USB_GSPCA | 287 | depends on VIDEO_V4L2 && USB_GSPCA |
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index 6e4cf1ce01c9..f6616db0b7f8 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile | |||
@@ -23,8 +23,10 @@ obj-$(CONFIG_USB_GSPCA_SPCA505) += gspca_spca505.o | |||
23 | obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o | 23 | obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o |
24 | obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o | 24 | obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o |
25 | obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o | 25 | obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o |
26 | obj-$(CONFIG_USB_GSPCA_SPCA1528) += gspca_spca1528.o | ||
26 | obj-$(CONFIG_USB_GSPCA_SQ905) += gspca_sq905.o | 27 | obj-$(CONFIG_USB_GSPCA_SQ905) += gspca_sq905.o |
27 | obj-$(CONFIG_USB_GSPCA_SQ905C) += gspca_sq905c.o | 28 | obj-$(CONFIG_USB_GSPCA_SQ905C) += gspca_sq905c.o |
29 | obj-$(CONFIG_USB_GSPCA_SQ930X) += gspca_sq930x.o | ||
28 | obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o | 30 | obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o |
29 | obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o | 31 | obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o |
30 | obj-$(CONFIG_USB_GSPCA_STV0680) += gspca_stv0680.o | 32 | obj-$(CONFIG_USB_GSPCA_STV0680) += gspca_stv0680.o |
@@ -58,8 +60,10 @@ gspca_spca505-objs := spca505.o | |||
58 | gspca_spca506-objs := spca506.o | 60 | gspca_spca506-objs := spca506.o |
59 | gspca_spca508-objs := spca508.o | 61 | gspca_spca508-objs := spca508.o |
60 | gspca_spca561-objs := spca561.o | 62 | gspca_spca561-objs := spca561.o |
63 | gspca_spca1528-objs := spca1528.o | ||
61 | gspca_sq905-objs := sq905.o | 64 | gspca_sq905-objs := sq905.o |
62 | gspca_sq905c-objs := sq905c.o | 65 | gspca_sq905c-objs := sq905c.o |
66 | gspca_sq930x-objs := sq930x.o | ||
63 | gspca_stk014-objs := stk014.o | 67 | gspca_stk014-objs := stk014.o |
64 | gspca_stv0680-objs := stv0680.o | 68 | gspca_stv0680-objs := stv0680.o |
65 | gspca_sunplus-objs := sunplus.o | 69 | gspca_sunplus-objs := sunplus.o |
diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index 19fe6b24c9a3..d6a75772f3f8 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c | |||
@@ -41,7 +41,7 @@ struct sd { | |||
41 | #define QUALITY_MAX 60 | 41 | #define QUALITY_MAX 60 |
42 | #define QUALITY_DEF 40 | 42 | #define QUALITY_DEF 40 |
43 | 43 | ||
44 | u8 *jpeg_hdr; | 44 | u8 jpeg_hdr[JPEG_HDR_SZ]; |
45 | }; | 45 | }; |
46 | 46 | ||
47 | /* V4L2 controls supported by the driver */ | 47 | /* V4L2 controls supported by the driver */ |
@@ -845,9 +845,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
845 | struct sd *sd = (struct sd *) gspca_dev; | 845 | struct sd *sd = (struct sd *) gspca_dev; |
846 | 846 | ||
847 | /* create the JPEG header */ | 847 | /* create the JPEG header */ |
848 | sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); | ||
849 | if (!sd->jpeg_hdr) | ||
850 | return -ENOMEM; | ||
851 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, | 848 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, |
852 | 0x22); /* JPEG 411 */ | 849 | 0x22); /* JPEG 411 */ |
853 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | 850 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); |
@@ -862,11 +859,8 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
862 | /* called on streamoff with alt 0 and on disconnect */ | 859 | /* called on streamoff with alt 0 and on disconnect */ |
863 | static void sd_stop0(struct gspca_dev *gspca_dev) | 860 | static void sd_stop0(struct gspca_dev *gspca_dev) |
864 | { | 861 | { |
865 | struct sd *sd = (struct sd *) gspca_dev; | ||
866 | int retry = 50; | 862 | int retry = 50; |
867 | 863 | ||
868 | kfree(sd->jpeg_hdr); | ||
869 | |||
870 | if (!gspca_dev->present) | 864 | if (!gspca_dev->present) |
871 | return; | 865 | return; |
872 | reg_w_val(gspca_dev, 0x0000, 0x00); | 866 | reg_w_val(gspca_dev, 0x0000, 0x00); |
diff --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/video/gspca/cpia1.c index 58b696f455be..3747a1dcff54 100644 --- a/drivers/media/video/gspca/cpia1.c +++ b/drivers/media/video/gspca/cpia1.c | |||
@@ -1760,22 +1760,19 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1760 | data[25] == sd->params.roi.colEnd && | 1760 | data[25] == sd->params.roi.colEnd && |
1761 | data[26] == sd->params.roi.rowStart && | 1761 | data[26] == sd->params.roi.rowStart && |
1762 | data[27] == sd->params.roi.rowEnd) { | 1762 | data[27] == sd->params.roi.rowEnd) { |
1763 | struct gspca_frame *frame = gspca_get_i_frame(gspca_dev); | 1763 | u8 *image; |
1764 | 1764 | ||
1765 | atomic_set(&sd->cam_exposure, data[39] * 2); | 1765 | atomic_set(&sd->cam_exposure, data[39] * 2); |
1766 | atomic_set(&sd->fps, data[41]); | 1766 | atomic_set(&sd->fps, data[41]); |
1767 | 1767 | ||
1768 | if (frame == NULL) { | ||
1769 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
1770 | return; | ||
1771 | } | ||
1772 | |||
1773 | /* Check for proper EOF for last frame */ | 1768 | /* Check for proper EOF for last frame */ |
1774 | if ((frame->data_end - frame->data) > 4 && | 1769 | image = gspca_dev->image; |
1775 | frame->data_end[-4] == 0xff && | 1770 | if (image != NULL && |
1776 | frame->data_end[-3] == 0xff && | 1771 | gspca_dev->image_len > 4 && |
1777 | frame->data_end[-2] == 0xff && | 1772 | image[gspca_dev->image_len - 4] == 0xff && |
1778 | frame->data_end[-1] == 0xff) | 1773 | image[gspca_dev->image_len - 3] == 0xff && |
1774 | image[gspca_dev->image_len - 2] == 0xff && | ||
1775 | image[gspca_dev->image_len - 1] == 0xff) | ||
1779 | gspca_frame_add(gspca_dev, LAST_PACKET, | 1776 | gspca_frame_add(gspca_dev, LAST_PACKET, |
1780 | NULL, 0); | 1777 | NULL, 0); |
1781 | 1778 | ||
diff --git a/drivers/media/video/gspca/gl860/gl860-mi2020.c b/drivers/media/video/gspca/gl860/gl860-mi2020.c index 7c31b4f2abea..57782e011c9e 100644 --- a/drivers/media/video/gspca/gl860/gl860-mi2020.c +++ b/drivers/media/video/gspca/gl860/gl860-mi2020.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* Subdriver for the GL860 chip with the MI2020 sensor | 1 | /* Subdriver for the GL860 chip with the MI2020 sensor |
2 | * Author Olivier LORIN, from Ice/Soro2005's logs(A), Fret_saw/Hulkie's | 2 | * Author Olivier LORIN, from logs by Iceman/Soro2005 + Fret_saw/Hulkie/Tricid |
3 | * logs(B) and Tricid"s logs(C). With the help of Kytrix/BUGabundo/Blazercist. | 3 | * with the help of Kytrix/BUGabundo/Blazercist. |
4 | * Driver achieved thanks to a webcam gift by Kytrix. | ||
4 | * | 5 | * |
5 | * This program is free software; you can redistribute it and/or modify | 6 | * 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 | * it under the terms of the GNU General Public License as published by |
@@ -20,47 +21,70 @@ | |||
20 | 21 | ||
21 | #include "gl860.h" | 22 | #include "gl860.h" |
22 | 23 | ||
24 | static u8 dat_wbal1[] = {0x8c, 0xa2, 0x0c}; | ||
25 | |||
23 | static u8 dat_bright1[] = {0x8c, 0xa2, 0x06}; | 26 | static u8 dat_bright1[] = {0x8c, 0xa2, 0x06}; |
24 | static u8 dat_bright3[] = {0x8c, 0xa1, 0x02}; | 27 | static u8 dat_bright3[] = {0x8c, 0xa1, 0x02}; |
25 | static u8 dat_bright4[] = {0x90, 0x00, 0x0f}; | 28 | static u8 dat_bright4[] = {0x90, 0x00, 0x0f}; |
26 | static u8 dat_bright5[] = {0x8c, 0xa1, 0x03}; | 29 | static u8 dat_bright5[] = {0x8c, 0xa1, 0x03}; |
27 | static u8 dat_bright6[] = {0x90, 0x00, 0x05}; | 30 | static u8 dat_bright6[] = {0x90, 0x00, 0x05}; |
28 | 31 | ||
29 | static u8 dat_dummy1[] = {0x90, 0x00, 0x06}; | ||
30 | /*static u8 dummy2[] = {0x8c, 0xa1, 0x02};*/ | ||
31 | /*static u8 dummy3[] = {0x90, 0x00, 0x1f};*/ | ||
32 | |||
33 | static u8 dat_hvflip1[] = {0x8c, 0x27, 0x19}; | 32 | static u8 dat_hvflip1[] = {0x8c, 0x27, 0x19}; |
34 | static u8 dat_hvflip3[] = {0x8c, 0x27, 0x3b}; | 33 | static u8 dat_hvflip3[] = {0x8c, 0x27, 0x3b}; |
35 | static u8 dat_hvflip5[] = {0x8c, 0xa1, 0x03}; | 34 | static u8 dat_hvflip5[] = {0x8c, 0xa1, 0x03}; |
36 | static u8 dat_hvflip6[] = {0x90, 0x00, 0x06}; | 35 | static u8 dat_hvflip6[] = {0x90, 0x00, 0x06}; |
37 | 36 | ||
37 | static struct idxdata tbl_middle_hvflip_low[] = { | ||
38 | {0x33, "\x90\x00\x06"}, | ||
39 | {6, "\xff\xff\xff"}, | ||
40 | {0x33, "\x90\x00\x06"}, | ||
41 | {6, "\xff\xff\xff"}, | ||
42 | {0x33, "\x90\x00\x06"}, | ||
43 | {6, "\xff\xff\xff"}, | ||
44 | {0x33, "\x90\x00\x06"}, | ||
45 | {6, "\xff\xff\xff"}, | ||
46 | }; | ||
47 | |||
48 | static struct idxdata tbl_middle_hvflip_big[] = { | ||
49 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x01"}, {0x33, "\x8c\xa1\x20"}, | ||
50 | {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x00"}, | ||
51 | {102, "\xff\xff\xff"}, | ||
52 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa1\x20"}, | ||
53 | {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"}, | ||
54 | }; | ||
55 | |||
56 | static struct idxdata tbl_end_hvflip[] = { | ||
57 | {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"}, | ||
58 | {6, "\xff\xff\xff"}, | ||
59 | {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"}, | ||
60 | {6, "\xff\xff\xff"}, | ||
61 | {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"}, | ||
62 | {6, "\xff\xff\xff"}, | ||
63 | {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"}, | ||
64 | }; | ||
65 | |||
38 | static u8 dat_freq1[] = { 0x8c, 0xa4, 0x04 }; | 66 | static u8 dat_freq1[] = { 0x8c, 0xa4, 0x04 }; |
39 | 67 | ||
40 | static u8 dat_multi5[] = { 0x8c, 0xa1, 0x03 }; | 68 | static u8 dat_multi5[] = { 0x8c, 0xa1, 0x03 }; |
41 | static u8 dat_multi6[] = { 0x90, 0x00, 0x05 }; | 69 | static u8 dat_multi6[] = { 0x90, 0x00, 0x05 }; |
42 | 70 | ||
43 | static struct validx tbl_common1[] = { | 71 | static struct validx tbl_init_at_startup[] = { |
44 | {0x0000, 0x0000}, | 72 | {0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001,0x00c1}, |
45 | {1, 0xffff}, /* msleep(35); */ | 73 | {0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d}, |
46 | {0x006a, 0x0007}, {0x0063, 0x0006}, {0x006a, 0x000d}, {0x0000, 0x00c0}, | 74 | {53, 0xffff}, |
47 | {0x0010, 0x0010}, {0x0003, 0x00c1}, {0x0042, 0x00c2}, {0x0004, 0x00d8}, | 75 | {0x0040, 0x0000}, {0x0063, 0x0006}, |
48 | {0x0000, 0x0058}, {0x0002, 0x0004}, {0x0041, 0x0000}, | ||
49 | }; | 76 | }; |
50 | 77 | ||
51 | static struct validx tbl_common2[] = { | 78 | static struct validx tbl_common_0B[] = { |
52 | {0x006a, 0x0007}, | 79 | {0x0002, 0x0004}, {0x006a, 0x0007}, {0x00ef, 0x0006}, {0x006a,0x000d}, |
53 | {35, 0xffff}, | 80 | {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0003, 0x00c1}, {0x0042,0x00c2}, |
54 | {0x00ef, 0x0006}, | ||
55 | {35, 0xffff}, | ||
56 | {0x006a, 0x000d}, | ||
57 | {35, 0xffff}, | ||
58 | {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0003, 0x00c1}, {0x0042, 0x00c2}, | ||
59 | {0x0004, 0x00d8}, {0x0000, 0x0058}, {0x0041, 0x0000}, | 81 | {0x0004, 0x00d8}, {0x0000, 0x0058}, {0x0041, 0x0000}, |
60 | }; | 82 | }; |
61 | 83 | ||
62 | static struct idxdata tbl_common3[] = { | 84 | static struct idxdata tbl_common_3B[] = { |
63 | {0x32, "\x02\x00\x08"}, {0x33, "\xf4\x03\x1d"}, | 85 | {0x33, "\x86\x25\x01"}, {0x33, "\x86\x25\x00"}, |
86 | {2, "\xff\xff\xff"}, | ||
87 | {0x30, "\x1a\x0a\xcc"}, {0x32, "\x02\x00\x08"}, {0x33, "\xf4\x03\x1d"}, | ||
64 | {6, "\xff\xff\xff"}, /* 12 */ | 88 | {6, "\xff\xff\xff"}, /* 12 */ |
65 | {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"}, | 89 | {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"}, |
66 | {2, "\xff\xff\xff"}, /* - */ | 90 | {2, "\xff\xff\xff"}, /* - */ |
@@ -98,85 +122,58 @@ static struct idxdata tbl_common3[] = { | |||
98 | {0x35, "\x50\x00\x06"}, {0x35, "\x48\x07\xff"}, {0x35, "\x60\x05\x89"}, | 122 | {0x35, "\x50\x00\x06"}, {0x35, "\x48\x07\xff"}, {0x35, "\x60\x05\x89"}, |
99 | {0x35, "\x58\x07\xff"}, {0x35, "\x40\x00\xa0"}, {0x35, "\x42\x00\x00"}, | 123 | {0x35, "\x58\x07\xff"}, {0x35, "\x40\x00\xa0"}, {0x35, "\x42\x00\x00"}, |
100 | {0x32, "\x10\x01\xfc"}, {0x33, "\x8c\xa1\x18"}, {0x33, "\x90\x00\x3c"}, | 124 | {0x32, "\x10\x01\xfc"}, {0x33, "\x8c\xa1\x18"}, {0x33, "\x90\x00\x3c"}, |
101 | {1, "\xff\xff\xff"}, | ||
102 | {0x33, "\x78\x00\x00"}, | 125 | {0x33, "\x78\x00\x00"}, |
103 | {1, "\xff\xff\xff"}, | 126 | {2, "\xff\xff\xff"}, |
104 | {0x35, "\xb8\x1f\x20"}, {0x33, "\x8c\xa2\x06"}, {0x33, "\x90\x00\x10"}, | 127 | {0x35, "\xb8\x1f\x20"}, {0x33, "\x8c\xa2\x06"}, {0x33, "\x90\x00\x10"}, |
105 | {0x33, "\x8c\xa2\x07"}, {0x33, "\x90\x00\x08"}, {0x33, "\x8c\xa2\x42"}, | 128 | {0x33, "\x8c\xa2\x07"}, {0x33, "\x90\x00\x08"}, {0x33, "\x8c\xa2\x42"}, |
106 | {0x33, "\x90\x00\x0b"}, {0x33, "\x8c\xa2\x4a"}, {0x33, "\x90\x00\x8c"}, | 129 | {0x33, "\x90\x00\x0b"}, {0x33, "\x8c\xa2\x4a"}, {0x33, "\x90\x00\x8c"}, |
107 | {0x35, "\xba\xfa\x08"}, {0x33, "\x8c\xa2\x02"}, {0x33, "\x90\x00\x22"}, | 130 | {0x35, "\xba\xfa\x08"}, {0x33, "\x8c\xa2\x02"}, {0x33, "\x90\x00\x22"}, |
108 | {0x33, "\x8c\xa2\x03"}, {0x33, "\x90\x00\xbb"}, | 131 | {0x33, "\x8c\xa2\x03"}, {0x33, "\x90\x00\xbb"}, {0x33, "\x8c\xa4\x04"}, |
109 | }; | 132 | {0x33, "\x90\x00\x80"}, {0x33, "\x8c\xa7\x9d"}, {0x33, "\x90\x00\x00"}, |
110 | 133 | {0x33, "\x8c\xa7\x9e"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa2\x0c"}, | |
111 | static struct idxdata tbl_common4[] = { | 134 | {0x33, "\x90\x00\x17"}, {0x33, "\x8c\xa2\x15"}, {0x33, "\x90\x00\x04"}, |
112 | {0x33, "\x8c\x22\x2e"}, {0x33, "\x90\x00\xa0"}, {0x33, "\x8c\xa4\x08"}, | 135 | {0x33, "\x8c\xa2\x14"}, {0x33, "\x90\x00\x20"}, {0x33, "\x8c\xa1\x03"}, |
136 | {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x17"}, {0x33, "\x90\x21\x11"}, | ||
137 | {0x33, "\x8c\x27\x1b"}, {0x33, "\x90\x02\x4f"}, {0x33, "\x8c\x27\x25"}, | ||
138 | {0x33, "\x90\x06\x0f"}, {0x33, "\x8c\x27\x39"}, {0x33, "\x90\x21\x11"}, | ||
139 | {0x33, "\x8c\x27\x3d"}, {0x33, "\x90\x01\x20"}, {0x33, "\x8c\x27\x47"}, | ||
140 | {0x33, "\x90\x09\x4c"}, {0x33, "\x8c\x27\x03"}, {0x33, "\x90\x02\x84"}, | ||
141 | {0x33, "\x8c\x27\x05"}, {0x33, "\x90\x01\xe2"}, {0x33, "\x8c\x27\x07"}, | ||
142 | {0x33, "\x90\x06\x40"}, {0x33, "\x8c\x27\x09"}, {0x33, "\x90\x04\xb0"}, | ||
143 | {0x33, "\x8c\x27\x0d"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x0f"}, | ||
144 | {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x11"}, {0x33, "\x90\x04\xbd"}, | ||
145 | {0x33, "\x8c\x27\x13"}, {0x33, "\x90\x06\x4d"}, {0x33, "\x8c\x27\x15"}, | ||
146 | {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x17"}, {0x33, "\x90\x21\x11"}, | ||
147 | {0x33, "\x8c\x27\x19"}, {0x33, "\x90\x04\x6c"}, {0x33, "\x8c\x27\x1b"}, | ||
148 | {0x33, "\x90\x02\x4f"}, {0x33, "\x8c\x27\x1d"}, {0x33, "\x90\x01\x02"}, | ||
149 | {0x33, "\x8c\x27\x1f"}, {0x33, "\x90\x02\x79"}, {0x33, "\x8c\x27\x21"}, | ||
150 | {0x33, "\x90\x01\x55"}, {0x33, "\x8c\x27\x23"}, {0x33, "\x90\x02\x85"}, | ||
151 | {0x33, "\x8c\x27\x25"}, {0x33, "\x90\x06\x0f"}, {0x33, "\x8c\x27\x27"}, | ||
152 | {0x33, "\x90\x20\x20"}, {0x33, "\x8c\x27\x29"}, {0x33, "\x90\x20\x20"}, | ||
153 | {0x33, "\x8c\x27\x2b"}, {0x33, "\x90\x10\x20"}, {0x33, "\x8c\x27\x2d"}, | ||
154 | {0x33, "\x90\x20\x07"}, {0x33, "\x8c\x27\x2f"}, {0x33, "\x90\x00\x04"}, | ||
155 | {0x33, "\x8c\x27\x31"}, {0x33, "\x90\x00\x04"}, {0x33, "\x8c\x27\x33"}, | ||
156 | {0x33, "\x90\x04\xbb"}, {0x33, "\x8c\x27\x35"}, {0x33, "\x90\x06\x4b"}, | ||
157 | {0x33, "\x8c\x27\x37"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x39"}, | ||
158 | {0x33, "\x90\x21\x11"}, {0x33, "\x8c\x27\x3b"}, {0x33, "\x90\x00\x24"}, | ||
159 | {0x33, "\x8c\x27\x3d"}, {0x33, "\x90\x01\x20"}, {0x33, "\x8c\x27\x41"}, | ||
160 | {0x33, "\x90\x01\x69"}, {0x33, "\x8c\x27\x45"}, {0x33, "\x90\x04\xed"}, | ||
161 | {0x33, "\x8c\x27\x47"}, {0x33, "\x90\x09\x4c"}, {0x33, "\x8c\x27\x51"}, | ||
162 | {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x53"}, {0x33, "\x90\x03\x20"}, | ||
163 | {0x33, "\x8c\x27\x55"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x57"}, | ||
164 | {0x33, "\x90\x02\x58"}, {0x33, "\x8c\x27\x5f"}, {0x33, "\x90\x00\x00"}, | ||
165 | {0x33, "\x8c\x27\x61"}, {0x33, "\x90\x06\x40"}, {0x33, "\x8c\x27\x63"}, | ||
166 | {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x65"}, {0x33, "\x90\x04\xb0"}, | ||
167 | {0x33, "\x8c\x22\x2e"}, {0x33, "\x90\x00\xa1"}, {0x33, "\x8c\xa4\x08"}, | ||
113 | {0x33, "\x90\x00\x1f"}, {0x33, "\x8c\xa4\x09"}, {0x33, "\x90\x00\x21"}, | 168 | {0x33, "\x90\x00\x1f"}, {0x33, "\x8c\xa4\x09"}, {0x33, "\x90\x00\x21"}, |
114 | {0x33, "\x8c\xa4\x0a"}, {0x33, "\x90\x00\x25"}, {0x33, "\x8c\xa4\x0b"}, | 169 | {0x33, "\x8c\xa4\x0a"}, {0x33, "\x90\x00\x25"}, {0x33, "\x8c\xa4\x0b"}, |
115 | {0x33, "\x90\x00\x27"}, {0x33, "\x8c\x24\x11"}, {0x33, "\x90\x00\xa0"}, | 170 | {0x33, "\x90\x00\x27"}, {0x33, "\x8c\x24\x11"}, {0x33, "\x90\x00\xa1"}, |
116 | {0x33, "\x8c\x24\x13"}, {0x33, "\x90\x00\xc0"}, {0x33, "\x8c\x24\x15"}, | 171 | {0x33, "\x8c\x24\x13"}, {0x33, "\x90\x00\xc1"}, {0x33, "\x8c\x24\x15"}, |
117 | {0x33, "\x90\x00\xa0"}, {0x33, "\x8c\x24\x17"}, {0x33, "\x90\x00\xc0"}, | 172 | {0x33, "\x90\x00\x6a"}, {0x33, "\x8c\x24\x17"}, {0x33, "\x90\x00\x80"}, |
118 | }; | 173 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"}, |
119 | 174 | {2, "\xff\xff\xff"}, | |
120 | static struct idxdata tbl_common5[] = { | 175 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, |
121 | {0x33, "\x8c\xa4\x04"}, {0x33, "\x90\x00\x80"}, {0x33, "\x8c\xa7\x9d"}, | 176 | {3, "\xff\xff\xff"}, |
122 | {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa7\x9e"}, {0x33, "\x90\x00\x00"}, | ||
123 | {0x33, "\x8c\xa2\x0c"}, {0x33, "\x90\x00\x17"}, {0x33, "\x8c\xa2\x15"}, | ||
124 | {0x33, "\x90\x00\x04"}, {0x33, "\x8c\xa2\x14"}, {0x33, "\x90\x00\x20"}, | ||
125 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x17"}, | ||
126 | /* msleep(53); */ | ||
127 | {0x33, "\x90\x21\x11"}, {0x33, "\x8c\x27\x1b"}, {0x33, "\x90\x02\x4f"}, | ||
128 | {0x33, "\x8c\x27\x25"}, {0x33, "\x90\x06\x0f"}, {0x33, "\x8c\x27\x39"}, | ||
129 | {0x33, "\x90\x21\x11"}, {0x33, "\x8c\x27\x3d"}, {0x33, "\x90\x01\x20"}, | ||
130 | {0x33, "\x8c\x27\x47"}, {0x33, "\x90\x09\x4c"}, {0x33, "\x8c\x27\x03"}, | ||
131 | {0x33, "\x90\x02\x84"}, {0x33, "\x8c\x27\x05"}, {0x33, "\x90\x01\xe2"}, | ||
132 | {0x33, "\x8c\x27\x07"}, {0x33, "\x90\x06\x40"}, {0x33, "\x8c\x27\x09"}, | ||
133 | {0x33, "\x90\x04\xb0"}, {0x33, "\x8c\x27\x0d"}, {0x33, "\x90\x00\x00"}, | ||
134 | {0x33, "\x8c\x27\x0f"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x11"}, | ||
135 | {0x33, "\x90\x04\xbd"}, {0x33, "\x8c\x27\x13"}, {0x33, "\x90\x06\x4d"}, | ||
136 | {0x33, "\x8c\x27\x15"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x17"}, | ||
137 | {0x33, "\x90\x21\x11"}, {0x33, "\x8c\x27\x19"}, {0x33, "\x90\x04\x6c"}, | ||
138 | {0x33, "\x8c\x27\x1b"}, {0x33, "\x90\x02\x4f"}, {0x33, "\x8c\x27\x1d"}, | ||
139 | {0x33, "\x90\x01\x02"}, {0x33, "\x8c\x27\x1f"}, {0x33, "\x90\x02\x79"}, | ||
140 | {0x33, "\x8c\x27\x21"}, {0x33, "\x90\x01\x55"}, {0x33, "\x8c\x27\x23"}, | ||
141 | {0x33, "\x90\x02\x85"}, {0x33, "\x8c\x27\x25"}, {0x33, "\x90\x06\x0f"}, | ||
142 | {0x33, "\x8c\x27\x27"}, {0x33, "\x90\x20\x20"}, {0x33, "\x8c\x27\x29"}, | ||
143 | {0x33, "\x90\x20\x20"}, {0x33, "\x8c\x27\x2b"}, {0x33, "\x90\x10\x20"}, | ||
144 | {0x33, "\x8c\x27\x2d"}, {0x33, "\x90\x20\x07"}, {0x33, "\x8c\x27\x2f"}, | ||
145 | {0x33, "\x90\x00\x04"}, {0x33, "\x8c\x27\x31"}, {0x33, "\x90\x00\x04"}, | ||
146 | {0x33, "\x8c\x27\x33"}, {0x33, "\x90\x04\xbb"}, {0x33, "\x8c\x27\x35"}, | ||
147 | {0x33, "\x90\x06\x4b"}, {0x33, "\x8c\x27\x37"}, {0x33, "\x90\x00\x00"}, | ||
148 | {0x33, "\x8c\x27\x39"}, {0x33, "\x90\x21\x11"}, {0x33, "\x8c\x27\x3b"}, | ||
149 | {0x33, "\x90\x00\x24"}, {0x33, "\x8c\x27\x3d"}, {0x33, "\x90\x01\x20"}, | ||
150 | {0x33, "\x8c\x27\x41"}, {0x33, "\x90\x01\x69"}, {0x33, "\x8c\x27\x45"}, | ||
151 | {0x33, "\x90\x04\xed"}, {0x33, "\x8c\x27\x47"}, {0x33, "\x90\x09\x4c"}, | ||
152 | {0x33, "\x8c\x27\x51"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x53"}, | ||
153 | {0x33, "\x90\x03\x20"}, {0x33, "\x8c\x27\x55"}, {0x33, "\x90\x00\x00"}, | ||
154 | {0x33, "\x8c\x27\x57"}, {0x33, "\x90\x02\x58"}, {0x33, "\x8c\x27\x5f"}, | ||
155 | {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x61"}, {0x33, "\x90\x06\x40"}, | ||
156 | {0x33, "\x8c\x27\x63"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x65"}, | ||
157 | {0x33, "\x90\x04\xb0"}, {0x33, "\x8c\x22\x2e"}, {0x33, "\x90\x00\xa1"}, | ||
158 | {0x33, "\x8c\xa4\x08"}, {0x33, "\x90\x00\x1f"}, {0x33, "\x8c\xa4\x09"}, | ||
159 | {0x33, "\x90\x00\x21"}, {0x33, "\x8c\xa4\x0a"}, {0x33, "\x90\x00\x25"}, | ||
160 | {0x33, "\x8c\xa4\x0b"}, {0x33, "\x90\x00\x27"}, {0x33, "\x8c\x24\x11"}, | ||
161 | {0x33, "\x90\x00\xa1"}, {0x33, "\x8c\x24\x13"}, {0x33, "\x90\x00\xc1"}, | ||
162 | {0x33, "\x8c\x24\x15"}, | ||
163 | }; | ||
164 | |||
165 | static struct validx tbl_init_at_startup[] = { | ||
166 | {0x0000, 0x0000}, | ||
167 | {53, 0xffff}, | ||
168 | {0x0010, 0x0010}, | ||
169 | {53, 0xffff}, | ||
170 | {0x0008, 0x00c0}, | ||
171 | {53, 0xffff}, | ||
172 | {0x0001, 0x00c1}, | ||
173 | {53, 0xffff}, | ||
174 | {0x0001, 0x00c2}, | ||
175 | {53, 0xffff}, | ||
176 | {0x0020, 0x0006}, | ||
177 | {53, 0xffff}, | ||
178 | {0x006a, 0x000d}, | ||
179 | {53, 0xffff}, | ||
180 | }; | 177 | }; |
181 | 178 | ||
182 | static struct idxdata tbl_init_post_alt_low1[] = { | 179 | static struct idxdata tbl_init_post_alt_low1[] = { |
@@ -209,7 +206,7 @@ static struct idxdata tbl_init_post_alt_low3[] = { | |||
209 | {2, "\xff\xff\xff"}, | 206 | {2, "\xff\xff\xff"}, |
210 | {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa1\x03"}, | 207 | {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa1\x03"}, |
211 | {0x33, "\x90\x00\x01"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x00"}, | 208 | {0x33, "\x90\x00\x01"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x00"}, |
212 | {2, "\xff\xff\xff"}, /* - * */ | 209 | {2, "\xff\xff\xff"}, |
213 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"}, | 210 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"}, |
214 | {2, "\xff\xff\xff"}, | 211 | {2, "\xff\xff\xff"}, |
215 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, | 212 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, |
@@ -217,61 +214,15 @@ static struct idxdata tbl_init_post_alt_low3[] = { | |||
217 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"}, | 214 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"}, |
218 | {2, "\xff\xff\xff"}, | 215 | {2, "\xff\xff\xff"}, |
219 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, | 216 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, |
220 | {1, "\xff\xff\xff"}, | ||
221 | }; | ||
222 | |||
223 | static struct idxdata tbl_init_post_alt_low4[] = { | ||
224 | {0x32, "\x10\x01\xf8"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"}, | ||
225 | {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"}, | ||
226 | {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"}, | ||
227 | {0x34, "\xde\x01\x5b"}, {0x34, "\xe6\x01\x13"}, {0x34, "\xee\x0b\xf0"}, | ||
228 | {0x34, "\xf6\x0b\xa4"}, {0x35, "\x00\xf6\xe7"}, {0x35, "\x08\x0d\xfd"}, | ||
229 | {0x35, "\x10\x25\x63"}, {0x35, "\x18\x35\x6c"}, {0x35, "\x20\x42\x7e"}, | ||
230 | {0x35, "\x28\x19\x44"}, {0x35, "\x30\x39\xd4"}, {0x35, "\x38\xf5\xa8"}, | ||
231 | {0x35, "\x4c\x07\x90"}, {0x35, "\x44\x07\xb8"}, {0x35, "\x5c\x06\x88"}, | ||
232 | {0x35, "\x54\x07\xff"}, {0x34, "\xe0\x01\x52"}, {0x34, "\xe8\x00\xcc"}, | ||
233 | {0x34, "\xf0\x0d\x83"}, {0x34, "\xf8\x0c\xb3"}, {0x35, "\x02\xfe\xba"}, | ||
234 | {0x35, "\x0a\x04\xe0"}, {0x35, "\x12\x1c\x63"}, {0x35, "\x1a\x2b\x5a"}, | ||
235 | {0x35, "\x22\x32\x5e"}, {0x35, "\x2a\x0d\x28"}, {0x35, "\x32\x2c\x02"}, | ||
236 | {0x35, "\x3a\xf4\xfa"}, {0x35, "\x4e\x07\xef"}, {0x35, "\x46\x07\x88"}, | ||
237 | {0x35, "\x5e\x07\xc1"}, {0x35, "\x56\x04\x64"}, {0x34, "\xe4\x01\x15"}, | ||
238 | {0x34, "\xec\x00\x82"}, {0x34, "\xf4\x0c\xce"}, {0x34, "\xfc\x0c\xba"}, | ||
239 | {0x35, "\x06\x1f\x02"}, {0x35, "\x0e\x02\xe3"}, {0x35, "\x16\x1a\x50"}, | ||
240 | {0x35, "\x1e\x24\x39"}, {0x35, "\x26\x23\x4c"}, {0x35, "\x2e\xf9\x1b"}, | ||
241 | {0x35, "\x36\x23\x19"}, {0x35, "\x3e\x12\x08"}, {0x35, "\x52\x07\x22"}, | ||
242 | {0x35, "\x4a\x03\xd3"}, {0x35, "\x62\x06\x54"}, {0x35, "\x5a\x04\x5d"}, | ||
243 | {0x34, "\xe2\x01\x04"}, {0x34, "\xea\x00\xa0"}, {0x34, "\xf2\x0c\xbc"}, | ||
244 | {0x34, "\xfa\x0c\x5b"}, {0x35, "\x04\x17\xf2"}, {0x35, "\x0c\x02\x08"}, | ||
245 | {0x35, "\x14\x28\x43"}, {0x35, "\x1c\x28\x62"}, {0x35, "\x24\x2b\x60"}, | ||
246 | {0x35, "\x2c\x07\x33"}, {0x35, "\x34\x1f\xb0"}, {0x35, "\x3c\xed\xcd"}, | ||
247 | {0x35, "\x50\x00\x06"}, {0x35, "\x48\x07\xff"}, {0x35, "\x60\x05\x89"}, | ||
248 | {0x35, "\x58\x07\xff"}, {0x35, "\x40\x00\xa0"}, {0x35, "\x42\x00\x00"}, | ||
249 | {0x32, "\x10\x01\xfc"}, {0x33, "\x8c\xa1\x18"}, | ||
250 | /* Flip/Mirror h/v=1 */ | ||
251 | {0x33, "\x90\x00\x3c"}, {0x33, "\x8c\x27\x19"}, {0x33, "\x90\x04\x6c"}, | ||
252 | {0x33, "\x8c\x27\x3b"}, {0x33, "\x90\x00\x24"}, {0x33, "\x8c\xa1\x03"}, | ||
253 | {0x33, "\x90\x00\x06"}, | ||
254 | {130, "\xff\xff\xff"}, | ||
255 | {0x33, "\x90\x00\x06"}, {0x33, "\x90\x00\x06"}, {0x33, "\x90\x00\x06"}, | ||
256 | {0x33, "\x90\x00\x06"}, {0x33, "\x90\x00\x06"}, {0x33, "\x90\x00\x06"}, | ||
257 | {100, "\xff\xff\xff"}, | ||
258 | /* ?? */ | ||
259 | {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"}, {0x33, "\x8c\xa1\x02"}, | ||
260 | {0x33, "\x90\x00\x1f"}, {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"}, | ||
261 | {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"}, | ||
262 | /* Brigthness=70 */ | ||
263 | {0x33, "\x8c\xa2\x06"}, {0x33, "\x90\x00\x46"}, {0x33, "\x8c\xa1\x02"}, | ||
264 | {0x33, "\x90\x00\x0f"}, {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"}, | ||
265 | /* Sharpness=20 */ | ||
266 | {0x32, "\x6c\x14\x08"}, | ||
267 | }; | 217 | }; |
268 | 218 | ||
269 | static struct idxdata tbl_init_post_alt_big1[] = { | 219 | static struct idxdata tbl_init_post_alt_big[] = { |
270 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"}, | 220 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"}, |
271 | {2, "\xff\xff\xff"}, | 221 | {2, "\xff\xff\xff"}, |
272 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, | 222 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, |
273 | {2, "\xff\xff\xff"}, | 223 | {2, "\xff\xff\xff"}, |
274 | {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"}, | 224 | {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"}, |
225 | {2, "\xff\xff\xff"}, | ||
275 | {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\xa1\x03"}, | 226 | {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\xa1\x03"}, |
276 | {0x33, "\x90\x00\x05"}, | 227 | {0x33, "\x90\x00\x05"}, |
277 | {2, "\xff\xff\xff"}, | 228 | {2, "\xff\xff\xff"}, |
@@ -285,9 +236,17 @@ static struct idxdata tbl_init_post_alt_big1[] = { | |||
285 | {0x33, "\x90\x00\x03"}, {0x33, "\x8c\xa1\x34"}, {0x33, "\x90\x00\x03"}, | 236 | {0x33, "\x90\x00\x03"}, {0x33, "\x8c\xa1\x34"}, {0x33, "\x90\x00\x03"}, |
286 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x02"}, {0x33, "\x2e\x01\x00"}, | 237 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x02"}, {0x33, "\x2e\x01\x00"}, |
287 | {0x34, "\x04\x00\x2a"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"}, | 238 | {0x34, "\x04\x00\x2a"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"}, |
239 | {0x33, "\x8c\x27\x97"}, {0x33, "\x90\x01\x00"}, | ||
240 | {51, "\xff\xff\xff"}, | ||
241 | {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa1\x03"}, | ||
242 | {0x33, "\x90\x00\x01"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x00"}, | ||
243 | {51, "\xff\xff\xff"}, | ||
244 | {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa1\x03"}, | ||
245 | {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"}, | ||
246 | {51, "\xff\xff\xff"}, | ||
288 | }; | 247 | }; |
289 | 248 | ||
290 | static struct idxdata tbl_init_post_alt_big2[] = { | 249 | static struct idxdata tbl_init_post_alt_3B[] = { |
291 | {0x32, "\x10\x01\xf8"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"}, | 250 | {0x32, "\x10\x01\xf8"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"}, |
292 | {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"}, | 251 | {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"}, |
293 | {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"}, | 252 | {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"}, |
@@ -316,17 +275,6 @@ static struct idxdata tbl_init_post_alt_big2[] = { | |||
316 | {0x32, "\x10\x01\xfc"}, {0x33, "\x8c\xa1\x18"}, {0x33, "\x90\x00\x3c"}, | 275 | {0x32, "\x10\x01\xfc"}, {0x33, "\x8c\xa1\x18"}, {0x33, "\x90\x00\x3c"}, |
317 | }; | 276 | }; |
318 | 277 | ||
319 | static struct idxdata tbl_init_post_alt_big3[] = { | ||
320 | {0x33, "\x8c\xa1\x02"}, | ||
321 | {0x33, "\x90\x00\x1f"}, | ||
322 | {0x33, "\x8c\xa1\x02"}, | ||
323 | {0x33, "\x90\x00\x1f"}, | ||
324 | {0x33, "\x8c\xa1\x02"}, | ||
325 | {0x33, "\x90\x00\x1f"}, | ||
326 | {0x33, "\x8c\xa1\x02"}, | ||
327 | {0x33, "\x90\x00\x1f"}, | ||
328 | }; | ||
329 | |||
330 | static u8 *dat_640 = "\xd0\x02\xd1\x08\xd2\xe1\xd3\x02\xd4\x10\xd5\x81"; | 278 | static u8 *dat_640 = "\xd0\x02\xd1\x08\xd2\xe1\xd3\x02\xd4\x10\xd5\x81"; |
331 | static u8 *dat_800 = "\xd0\x02\xd1\x10\xd2\x57\xd3\x02\xd4\x18\xd5\x21"; | 279 | static u8 *dat_800 = "\xd0\x02\xd1\x10\xd2\x57\xd3\x02\xd4\x18\xd5\x21"; |
332 | static u8 *dat_1280 = "\xd0\x02\xd1\x20\xd2\x01\xd3\x02\xd4\x28\xd5\x01"; | 280 | static u8 *dat_1280 = "\xd0\x02\xd1\x20\xd2\x01\xd3\x02\xd4\x28\xd5\x01"; |
@@ -351,7 +299,7 @@ void mi2020_init_settings(struct gspca_dev *gspca_dev) | |||
351 | sd->vcur.gamma = 0; | 299 | sd->vcur.gamma = 0; |
352 | sd->vcur.hue = 0; | 300 | sd->vcur.hue = 0; |
353 | sd->vcur.saturation = 60; | 301 | sd->vcur.saturation = 60; |
354 | sd->vcur.whitebal = 50; | 302 | sd->vcur.whitebal = 0; /* 50, not done by hardware */ |
355 | sd->vcur.mirror = 0; | 303 | sd->vcur.mirror = 0; |
356 | sd->vcur.flip = 0; | 304 | sd->vcur.flip = 0; |
357 | sd->vcur.AC50Hz = 1; | 305 | sd->vcur.AC50Hz = 1; |
@@ -361,17 +309,12 @@ void mi2020_init_settings(struct gspca_dev *gspca_dev) | |||
361 | sd->vmax.sharpness = 40; | 309 | sd->vmax.sharpness = 40; |
362 | sd->vmax.contrast = 3; | 310 | sd->vmax.contrast = 3; |
363 | sd->vmax.gamma = 2; | 311 | sd->vmax.gamma = 2; |
364 | sd->vmax.hue = 0 + 1; /* 200 */ | 312 | sd->vmax.hue = 0 + 1; /* 200, not done by hardware */ |
365 | sd->vmax.saturation = 0; /* 100 */ | 313 | sd->vmax.saturation = 0; /* 100, not done by hardware */ |
366 | sd->vmax.whitebal = 0; /* 100 */ | 314 | sd->vmax.whitebal = 2; /* 100, not done by hardware */ |
367 | sd->vmax.mirror = 1; | 315 | sd->vmax.mirror = 1; |
368 | sd->vmax.flip = 1; | 316 | sd->vmax.flip = 1; |
369 | sd->vmax.AC50Hz = 1; | 317 | sd->vmax.AC50Hz = 1; |
370 | if (_MI2020b_) { | ||
371 | sd->vmax.contrast = 0; | ||
372 | sd->vmax.gamma = 0; | ||
373 | sd->vmax.backlight = 0; | ||
374 | } | ||
375 | 318 | ||
376 | sd->dev_camera_settings = mi2020_camera_settings; | 319 | sd->dev_camera_settings = mi2020_camera_settings; |
377 | sd->dev_init_at_startup = mi2020_init_at_startup; | 320 | sd->dev_init_at_startup = mi2020_init_at_startup; |
@@ -384,51 +327,9 @@ void mi2020_init_settings(struct gspca_dev *gspca_dev) | |||
384 | 327 | ||
385 | static void common(struct gspca_dev *gspca_dev) | 328 | static void common(struct gspca_dev *gspca_dev) |
386 | { | 329 | { |
387 | s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; | 330 | fetch_validx(gspca_dev, tbl_common_0B, ARRAY_SIZE(tbl_common_0B)); |
388 | 331 | fetch_idxdata(gspca_dev, tbl_common_3B, ARRAY_SIZE(tbl_common_3B)); | |
389 | if (_MI2020b_) { | 332 | ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x0000, 0, NULL); |
390 | fetch_validx(gspca_dev, tbl_common1, ARRAY_SIZE(tbl_common1)); | ||
391 | } else { | ||
392 | if (_MI2020_) | ||
393 | ctrl_out(gspca_dev, 0x40, 1, 0x0008, 0x0004, 0, NULL); | ||
394 | else | ||
395 | ctrl_out(gspca_dev, 0x40, 1, 0x0002, 0x0004, 0, NULL); | ||
396 | msleep(35); | ||
397 | fetch_validx(gspca_dev, tbl_common2, ARRAY_SIZE(tbl_common2)); | ||
398 | } | ||
399 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x86\x25\x01"); | ||
400 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x86\x25\x00"); | ||
401 | msleep(2); /* - * */ | ||
402 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0030, 3, "\x1a\x0a\xcc"); | ||
403 | if (reso == IMAGE_1600) | ||
404 | msleep(2); /* 1600 */ | ||
405 | fetch_idxdata(gspca_dev, tbl_common3, ARRAY_SIZE(tbl_common3)); | ||
406 | |||
407 | if (_MI2020b_ || _MI2020_) | ||
408 | fetch_idxdata(gspca_dev, tbl_common4, | ||
409 | ARRAY_SIZE(tbl_common4)); | ||
410 | |||
411 | fetch_idxdata(gspca_dev, tbl_common5, ARRAY_SIZE(tbl_common5)); | ||
412 | if (_MI2020b_ || _MI2020_) { | ||
413 | /* Different from fret */ | ||
414 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x78"); | ||
415 | /* Same as fret */ | ||
416 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\x24\x17"); | ||
417 | /* Different from fret */ | ||
418 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x90"); | ||
419 | } else { | ||
420 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x6a"); | ||
421 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\x24\x17"); | ||
422 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x80"); | ||
423 | } | ||
424 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x03"); | ||
425 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x05"); | ||
426 | msleep(2); | ||
427 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x03"); | ||
428 | if (reso == IMAGE_1600) | ||
429 | msleep(14); /* 1600 */ | ||
430 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x06"); | ||
431 | msleep(2); | ||
432 | } | 333 | } |
433 | 334 | ||
434 | static int mi2020_init_at_startup(struct gspca_dev *gspca_dev) | 335 | static int mi2020_init_at_startup(struct gspca_dev *gspca_dev) |
@@ -441,8 +342,16 @@ static int mi2020_init_at_startup(struct gspca_dev *gspca_dev) | |||
441 | fetch_validx(gspca_dev, tbl_init_at_startup, | 342 | fetch_validx(gspca_dev, tbl_init_at_startup, |
442 | ARRAY_SIZE(tbl_init_at_startup)); | 343 | ARRAY_SIZE(tbl_init_at_startup)); |
443 | 344 | ||
345 | ctrl_out(gspca_dev, 0x40, 1, 0x7a00, 0x8030, 0, NULL); | ||
346 | ctrl_in(gspca_dev, 0xc0, 2, 0x7a00, 0x8030, 1, &c); | ||
347 | |||
444 | common(gspca_dev); | 348 | common(gspca_dev); |
445 | 349 | ||
350 | msleep(61); | ||
351 | /* ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL); */ | ||
352 | /* msleep(36); */ | ||
353 | ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0000, 0, NULL); | ||
354 | |||
446 | return 0; | 355 | return 0; |
447 | } | 356 | } |
448 | 357 | ||
@@ -450,17 +359,17 @@ static int mi2020_init_pre_alt(struct gspca_dev *gspca_dev) | |||
450 | { | 359 | { |
451 | struct sd *sd = (struct sd *) gspca_dev; | 360 | struct sd *sd = (struct sd *) gspca_dev; |
452 | 361 | ||
453 | sd->mirrorMask = 0; | 362 | sd->mirrorMask = 0; |
363 | sd->vold.hue = -1; | ||
454 | 364 | ||
455 | sd->vold.backlight = -1; | 365 | /* These controls need to be reset */ |
456 | sd->vold.brightness = -1; | 366 | sd->vold.brightness = -1; |
457 | sd->vold.sharpness = -1; | 367 | sd->vold.sharpness = -1; |
458 | sd->vold.contrast = -1; | 368 | |
459 | sd->vold.gamma = -1; | 369 | /* If not different from default, they do not need to be set */ |
460 | sd->vold.hue = -1; | 370 | sd->vold.contrast = 0; |
461 | sd->vold.mirror = -1; | 371 | sd->vold.gamma = 0; |
462 | sd->vold.flip = -1; | 372 | sd->vold.backlight = 0; |
463 | sd->vold.AC50Hz = -1; | ||
464 | 373 | ||
465 | mi2020_init_post_alt(gspca_dev); | 374 | mi2020_init_post_alt(gspca_dev); |
466 | 375 | ||
@@ -472,10 +381,10 @@ static int mi2020_init_post_alt(struct gspca_dev *gspca_dev) | |||
472 | struct sd *sd = (struct sd *) gspca_dev; | 381 | struct sd *sd = (struct sd *) gspca_dev; |
473 | s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; | 382 | s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; |
474 | 383 | ||
475 | s32 backlight = sd->vcur.backlight; | ||
476 | s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0); | 384 | s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0); |
477 | s32 flip = (((sd->vcur.flip > 0) ^ sd->mirrorMask) > 0); | 385 | s32 flip = (((sd->vcur.flip > 0) ^ sd->mirrorMask) > 0); |
478 | s32 freq = (sd->vcur.AC50Hz > 0); | 386 | s32 freq = (sd->vcur.AC50Hz > 0); |
387 | s32 wbal = sd->vcur.whitebal; | ||
479 | 388 | ||
480 | u8 dat_freq2[] = {0x90, 0x00, 0x80}; | 389 | u8 dat_freq2[] = {0x90, 0x00, 0x80}; |
481 | u8 dat_multi1[] = {0x8c, 0xa7, 0x00}; | 390 | u8 dat_multi1[] = {0x8c, 0xa7, 0x00}; |
@@ -484,6 +393,7 @@ static int mi2020_init_post_alt(struct gspca_dev *gspca_dev) | |||
484 | u8 dat_multi4[] = {0x90, 0x00, 0x00}; | 393 | u8 dat_multi4[] = {0x90, 0x00, 0x00}; |
485 | u8 dat_hvflip2[] = {0x90, 0x04, 0x6c}; | 394 | u8 dat_hvflip2[] = {0x90, 0x04, 0x6c}; |
486 | u8 dat_hvflip4[] = {0x90, 0x00, 0x24}; | 395 | u8 dat_hvflip4[] = {0x90, 0x00, 0x24}; |
396 | u8 dat_wbal2[] = {0x90, 0x00, 0x00}; | ||
487 | u8 c; | 397 | u8 c; |
488 | 398 | ||
489 | sd->nbIm = -1; | 399 | sd->nbIm = -1; |
@@ -491,23 +401,26 @@ static int mi2020_init_post_alt(struct gspca_dev *gspca_dev) | |||
491 | dat_freq2[2] = freq ? 0xc0 : 0x80; | 401 | dat_freq2[2] = freq ? 0xc0 : 0x80; |
492 | dat_multi1[2] = 0x9d; | 402 | dat_multi1[2] = 0x9d; |
493 | dat_multi3[2] = dat_multi1[2] + 1; | 403 | dat_multi3[2] = dat_multi1[2] + 1; |
494 | dat_multi4[2] = dat_multi2[2] = backlight; | 404 | if (wbal == 0) { |
405 | dat_multi4[2] = dat_multi2[2] = 0; | ||
406 | dat_wbal2[2] = 0x17; | ||
407 | } else if (wbal == 1) { | ||
408 | dat_multi4[2] = dat_multi2[2] = 0; | ||
409 | dat_wbal2[2] = 0x35; | ||
410 | } else if (wbal == 2) { | ||
411 | dat_multi4[2] = dat_multi2[2] = 0x20; | ||
412 | dat_wbal2[2] = 0x17; | ||
413 | } | ||
495 | dat_hvflip2[2] = 0x6c + 2 * (1 - flip) + (1 - mirror); | 414 | dat_hvflip2[2] = 0x6c + 2 * (1 - flip) + (1 - mirror); |
496 | dat_hvflip4[2] = 0x24 + 2 * (1 - flip) + (1 - mirror); | 415 | dat_hvflip4[2] = 0x24 + 2 * (1 - flip) + (1 - mirror); |
497 | 416 | ||
498 | msleep(200); | 417 | msleep(200); |
499 | |||
500 | ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL); | 418 | ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL); |
501 | msleep(3); /* 35 * */ | 419 | msleep(2); |
502 | 420 | ||
503 | common(gspca_dev); | 421 | common(gspca_dev); |
504 | 422 | ||
505 | ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x0000, 0, NULL); | 423 | msleep(142); |
506 | msleep(70); | ||
507 | |||
508 | if (_MI2020b_) | ||
509 | ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL); | ||
510 | |||
511 | ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL); | 424 | ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL); |
512 | ctrl_out(gspca_dev, 0x40, 1, 0x0003, 0x00c1, 0, NULL); | 425 | ctrl_out(gspca_dev, 0x40, 1, 0x0003, 0x00c1, 0, NULL); |
513 | ctrl_out(gspca_dev, 0x40, 1, 0x0042, 0x00c2, 0, NULL); | 426 | ctrl_out(gspca_dev, 0x40, 1, 0x0042, 0x00c2, 0, NULL); |
@@ -523,8 +436,7 @@ static int mi2020_init_post_alt(struct gspca_dev *gspca_dev) | |||
523 | ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, | 436 | ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, |
524 | 12, dat_800); | 437 | 12, dat_800); |
525 | 438 | ||
526 | if (_MI2020c_) | 439 | fetch_idxdata(gspca_dev, tbl_init_post_alt_low1, |
527 | fetch_idxdata(gspca_dev, tbl_init_post_alt_low1, | ||
528 | ARRAY_SIZE(tbl_init_post_alt_low1)); | 440 | ARRAY_SIZE(tbl_init_post_alt_low1)); |
529 | 441 | ||
530 | if (reso == IMAGE_800) | 442 | if (reso == IMAGE_800) |
@@ -534,87 +446,10 @@ static int mi2020_init_post_alt(struct gspca_dev *gspca_dev) | |||
534 | fetch_idxdata(gspca_dev, tbl_init_post_alt_low3, | 446 | fetch_idxdata(gspca_dev, tbl_init_post_alt_low3, |
535 | ARRAY_SIZE(tbl_init_post_alt_low3)); | 447 | ARRAY_SIZE(tbl_init_post_alt_low3)); |
536 | 448 | ||
537 | if (_MI2020b_) { | 449 | ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL); |
538 | ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0010, 0, NULL); | 450 | ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL); |
539 | ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL); | 451 | ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL); |
540 | ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL); | 452 | msleep(120); |
541 | msleep(150); | ||
542 | } else if (_MI2020c_) { | ||
543 | ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL); | ||
544 | ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL); | ||
545 | ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL); | ||
546 | msleep(120); | ||
547 | ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL); | ||
548 | msleep(30); | ||
549 | } else if (_MI2020_) { | ||
550 | ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0010, 0, NULL); | ||
551 | ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL); | ||
552 | ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL); | ||
553 | msleep(120); | ||
554 | ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL); | ||
555 | msleep(30); | ||
556 | } | ||
557 | |||
558 | /* AC power frequency */ | ||
559 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq1); | ||
560 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq2); | ||
561 | msleep(20); | ||
562 | /* backlight */ | ||
563 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1); | ||
564 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2); | ||
565 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3); | ||
566 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4); | ||
567 | /* at init time but not after */ | ||
568 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa2\x0c"); | ||
569 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x17"); | ||
570 | /* finish the backlight */ | ||
571 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5); | ||
572 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6); | ||
573 | msleep(5);/* " */ | ||
574 | |||
575 | if (_MI2020c_) { | ||
576 | fetch_idxdata(gspca_dev, tbl_init_post_alt_low4, | ||
577 | ARRAY_SIZE(tbl_init_post_alt_low4)); | ||
578 | } else { | ||
579 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, &c); | ||
580 | msleep(14); /* 0xd8 */ | ||
581 | |||
582 | /* flip/mirror */ | ||
583 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, | ||
584 | 3, dat_hvflip1); | ||
585 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, | ||
586 | 3, dat_hvflip2); | ||
587 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, | ||
588 | 3, dat_hvflip3); | ||
589 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, | ||
590 | 3, dat_hvflip4); | ||
591 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, | ||
592 | 3, dat_hvflip5); | ||
593 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, | ||
594 | 3, dat_hvflip6); | ||
595 | msleep(21); | ||
596 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, | ||
597 | 3, dat_dummy1); | ||
598 | msleep(5); | ||
599 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, | ||
600 | 3, dat_dummy1); | ||
601 | msleep(5); | ||
602 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, | ||
603 | 3, dat_dummy1); | ||
604 | msleep(5); | ||
605 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, | ||
606 | 3, dat_dummy1); | ||
607 | msleep(5); | ||
608 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, | ||
609 | 3, dat_dummy1); | ||
610 | msleep(5); | ||
611 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, | ||
612 | 3, dat_dummy1); | ||
613 | /* end of flip/mirror main part */ | ||
614 | msleep(246); /* 146 */ | ||
615 | |||
616 | sd->nbIm = 0; | ||
617 | } | ||
618 | break; | 453 | break; |
619 | 454 | ||
620 | case IMAGE_1280: | 455 | case IMAGE_1280: |
@@ -643,108 +478,62 @@ static int mi2020_init_post_alt(struct gspca_dev *gspca_dev) | |||
643 | 3, "\x90\x04\xb0"); | 478 | 3, "\x90\x04\xb0"); |
644 | } | 479 | } |
645 | 480 | ||
646 | fetch_idxdata(gspca_dev, tbl_init_post_alt_big1, | 481 | fetch_idxdata(gspca_dev, tbl_init_post_alt_big, |
647 | ARRAY_SIZE(tbl_init_post_alt_big1)); | 482 | ARRAY_SIZE(tbl_init_post_alt_big)); |
648 | |||
649 | if (reso == IMAGE_1600) | ||
650 | msleep(13); /* 1600 */ | ||
651 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\x27\x97"); | ||
652 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x01\x00"); | ||
653 | msleep(53); | ||
654 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x20"); | ||
655 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x00"); | ||
656 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x03"); | ||
657 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x01"); | ||
658 | if (reso == IMAGE_1600) | ||
659 | msleep(13); /* 1600 */ | ||
660 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa7\x02"); | ||
661 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x00"); | ||
662 | msleep(53); | ||
663 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x20"); | ||
664 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x72"); | ||
665 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x03"); | ||
666 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x02"); | ||
667 | if (reso == IMAGE_1600) | ||
668 | msleep(13); /* 1600 */ | ||
669 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa7\x02"); | ||
670 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x01"); | ||
671 | msleep(53); | ||
672 | |||
673 | if (_MI2020b_) { | ||
674 | ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0010, 0, NULL); | ||
675 | if (reso == IMAGE_1600) | ||
676 | msleep(500); /* 1600 */ | ||
677 | ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL); | ||
678 | ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL); | ||
679 | msleep(1850); | ||
680 | } else if (_MI2020c_ || _MI2020_) { | ||
681 | ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0010, 0, NULL); | ||
682 | ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL); | ||
683 | ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL); | ||
684 | msleep(1850); | ||
685 | ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL); | ||
686 | msleep(30); | ||
687 | } | ||
688 | 483 | ||
689 | /* AC power frequency */ | 484 | ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0010, 0, NULL); |
690 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq1); | 485 | ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL); |
691 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq2); | 486 | ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL); |
692 | msleep(20); | 487 | msleep(1850); |
693 | /* backlight */ | 488 | } |
694 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1); | ||
695 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2); | ||
696 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3); | ||
697 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4); | ||
698 | /* at init time but not after */ | ||
699 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa2\x0c"); | ||
700 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x17"); | ||
701 | /* finish the backlight */ | ||
702 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5); | ||
703 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6); | ||
704 | msleep(6); /* " */ | ||
705 | 489 | ||
706 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, &c); | 490 | ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL); |
707 | msleep(14); | 491 | msleep(40); |
492 | |||
493 | /* AC power frequency */ | ||
494 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq1); | ||
495 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq2); | ||
496 | msleep(33); | ||
497 | /* light source */ | ||
498 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1); | ||
499 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2); | ||
500 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3); | ||
501 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4); | ||
502 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal1); | ||
503 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal2); | ||
504 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5); | ||
505 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6); | ||
506 | msleep(7); | ||
507 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, &c); | ||
508 | |||
509 | fetch_idxdata(gspca_dev, tbl_init_post_alt_3B, | ||
510 | ARRAY_SIZE(tbl_init_post_alt_3B)); | ||
511 | |||
512 | /* hvflip */ | ||
513 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1); | ||
514 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip2); | ||
515 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip3); | ||
516 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip4); | ||
517 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip5); | ||
518 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip6); | ||
519 | msleep(250); | ||
520 | |||
521 | if (reso == IMAGE_640 || reso == IMAGE_800) | ||
522 | fetch_idxdata(gspca_dev, tbl_middle_hvflip_low, | ||
523 | ARRAY_SIZE(tbl_middle_hvflip_low)); | ||
524 | else | ||
525 | fetch_idxdata(gspca_dev, tbl_middle_hvflip_big, | ||
526 | ARRAY_SIZE(tbl_middle_hvflip_big)); | ||
708 | 527 | ||
709 | if (_MI2020c_) | 528 | fetch_idxdata(gspca_dev, tbl_end_hvflip, |
710 | fetch_idxdata(gspca_dev, tbl_init_post_alt_big2, | 529 | ARRAY_SIZE(tbl_end_hvflip)); |
711 | ARRAY_SIZE(tbl_init_post_alt_big2)); | ||
712 | 530 | ||
713 | /* flip/mirror */ | 531 | sd->nbIm = 0; |
714 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1); | ||
715 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip2); | ||
716 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip3); | ||
717 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip4); | ||
718 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip5); | ||
719 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip6); | ||
720 | /* end of flip/mirror main part */ | ||
721 | msleep(16); | ||
722 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x03"); | ||
723 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x01"); | ||
724 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x20"); | ||
725 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x00"); | ||
726 | if (reso == IMAGE_1600) | ||
727 | msleep(25); /* 1600 */ | ||
728 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa7\x02"); | ||
729 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x00"); | ||
730 | msleep(103); | ||
731 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x03"); | ||
732 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x02"); | ||
733 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x20"); | ||
734 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x72"); | ||
735 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa7\x02"); | ||
736 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x01"); | ||
737 | sd->nbIm = 0; | ||
738 | |||
739 | if (_MI2020c_) | ||
740 | fetch_idxdata(gspca_dev, tbl_init_post_alt_big3, | ||
741 | ARRAY_SIZE(tbl_init_post_alt_big3)); | ||
742 | } | ||
743 | 532 | ||
744 | sd->vold.mirror = mirror; | 533 | sd->vold.mirror = mirror; |
745 | sd->vold.flip = flip; | 534 | sd->vold.flip = flip; |
746 | sd->vold.AC50Hz = freq; | 535 | sd->vold.AC50Hz = freq; |
747 | sd->vold.backlight = backlight; | 536 | sd->vold.whitebal = wbal; |
748 | 537 | ||
749 | mi2020_camera_settings(gspca_dev); | 538 | mi2020_camera_settings(gspca_dev); |
750 | 539 | ||
@@ -772,6 +561,7 @@ static int mi2020_configure_alt(struct gspca_dev *gspca_dev) | |||
772 | static int mi2020_camera_settings(struct gspca_dev *gspca_dev) | 561 | static int mi2020_camera_settings(struct gspca_dev *gspca_dev) |
773 | { | 562 | { |
774 | struct sd *sd = (struct sd *) gspca_dev; | 563 | struct sd *sd = (struct sd *) gspca_dev; |
564 | s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; | ||
775 | 565 | ||
776 | s32 backlight = sd->vcur.backlight; | 566 | s32 backlight = sd->vcur.backlight; |
777 | s32 bright = sd->vcur.brightness; | 567 | s32 bright = sd->vcur.brightness; |
@@ -782,6 +572,7 @@ static int mi2020_camera_settings(struct gspca_dev *gspca_dev) | |||
782 | s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0); | 572 | s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0); |
783 | s32 flip = (((sd->vcur.flip > 0) ^ sd->mirrorMask) > 0); | 573 | s32 flip = (((sd->vcur.flip > 0) ^ sd->mirrorMask) > 0); |
784 | s32 freq = (sd->vcur.AC50Hz > 0); | 574 | s32 freq = (sd->vcur.AC50Hz > 0); |
575 | s32 wbal = sd->vcur.whitebal; | ||
785 | 576 | ||
786 | u8 dat_sharp[] = {0x6c, 0x00, 0x08}; | 577 | u8 dat_sharp[] = {0x6c, 0x00, 0x08}; |
787 | u8 dat_bright2[] = {0x90, 0x00, 0x00}; | 578 | u8 dat_bright2[] = {0x90, 0x00, 0x00}; |
@@ -792,6 +583,7 @@ static int mi2020_camera_settings(struct gspca_dev *gspca_dev) | |||
792 | u8 dat_multi4[] = {0x90, 0x00, 0x00}; | 583 | u8 dat_multi4[] = {0x90, 0x00, 0x00}; |
793 | u8 dat_hvflip2[] = {0x90, 0x04, 0x6c}; | 584 | u8 dat_hvflip2[] = {0x90, 0x04, 0x6c}; |
794 | u8 dat_hvflip4[] = {0x90, 0x00, 0x24}; | 585 | u8 dat_hvflip4[] = {0x90, 0x00, 0x24}; |
586 | u8 dat_wbal2[] = {0x90, 0x00, 0x00}; | ||
795 | 587 | ||
796 | /* Less than 4 images received -> too early to set the settings */ | 588 | /* Less than 4 images received -> too early to set the settings */ |
797 | if (sd->nbIm < 4) { | 589 | if (sd->nbIm < 4) { |
@@ -809,67 +601,89 @@ static int mi2020_camera_settings(struct gspca_dev *gspca_dev) | |||
809 | msleep(20); | 601 | msleep(20); |
810 | } | 602 | } |
811 | 603 | ||
604 | if (wbal != sd->vold.whitebal) { | ||
605 | sd->vold.whitebal = wbal; | ||
606 | if (wbal < 0 || wbal > sd->vmax.whitebal) | ||
607 | wbal = 0; | ||
608 | |||
609 | dat_multi1[2] = 0x9d; | ||
610 | dat_multi3[2] = dat_multi1[2] + 1; | ||
611 | if (wbal == 0) { | ||
612 | dat_multi4[2] = dat_multi2[2] = 0; | ||
613 | dat_wbal2[2] = 0x17; | ||
614 | } else if (wbal == 1) { | ||
615 | dat_multi4[2] = dat_multi2[2] = 0; | ||
616 | dat_wbal2[2] = 0x35; | ||
617 | } else if (wbal == 2) { | ||
618 | dat_multi4[2] = dat_multi2[2] = 0x20; | ||
619 | dat_wbal2[2] = 0x17; | ||
620 | } | ||
621 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1); | ||
622 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2); | ||
623 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3); | ||
624 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4); | ||
625 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal1); | ||
626 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal2); | ||
627 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5); | ||
628 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6); | ||
629 | } | ||
630 | |||
812 | if (mirror != sd->vold.mirror || flip != sd->vold.flip) { | 631 | if (mirror != sd->vold.mirror || flip != sd->vold.flip) { |
813 | sd->vold.mirror = mirror; | 632 | sd->vold.mirror = mirror; |
814 | sd->vold.flip = flip; | 633 | sd->vold.flip = flip; |
815 | 634 | ||
816 | dat_hvflip2[2] = 0x6c + 2 * (1 - flip) + (1 - mirror); | 635 | dat_hvflip2[2] = 0x6c + 2 * (1 - flip) + (1 - mirror); |
817 | dat_hvflip4[2] = 0x24 + 2 * (1 - flip) + (1 - mirror); | 636 | dat_hvflip4[2] = 0x24 + 2 * (1 - flip) + (1 - mirror); |
637 | |||
638 | fetch_idxdata(gspca_dev, tbl_init_post_alt_3B, | ||
639 | ARRAY_SIZE(tbl_init_post_alt_3B)); | ||
640 | |||
818 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1); | 641 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1); |
819 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip2); | 642 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip2); |
820 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip3); | 643 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip3); |
821 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip4); | 644 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip4); |
822 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip5); | 645 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip5); |
823 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip6); | 646 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip6); |
824 | msleep(130); | 647 | msleep(40); |
825 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_dummy1); | 648 | |
826 | msleep(6); | 649 | if (reso == IMAGE_640 || reso == IMAGE_800) |
827 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_dummy1); | 650 | fetch_idxdata(gspca_dev, tbl_middle_hvflip_low, |
828 | msleep(6); | 651 | ARRAY_SIZE(tbl_middle_hvflip_low)); |
829 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_dummy1); | 652 | else |
830 | msleep(6); | 653 | fetch_idxdata(gspca_dev, tbl_middle_hvflip_big, |
831 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_dummy1); | 654 | ARRAY_SIZE(tbl_middle_hvflip_big)); |
832 | msleep(6); | 655 | |
833 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_dummy1); | 656 | fetch_idxdata(gspca_dev, tbl_end_hvflip, |
834 | msleep(6); | 657 | ARRAY_SIZE(tbl_end_hvflip)); |
835 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_dummy1); | ||
836 | msleep(6); | ||
837 | |||
838 | /* Sometimes present, sometimes not, useful? */ | ||
839 | /* ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dummy2); | ||
840 | * ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dummy3); | ||
841 | * ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dummy2); | ||
842 | * ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dummy3); | ||
843 | * ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dummy2); | ||
844 | * ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dummy3); | ||
845 | * ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dummy2); | ||
846 | * ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dummy3);*/ | ||
847 | } | 658 | } |
848 | 659 | ||
849 | if (backlight != sd->vold.backlight) { | 660 | if (bright != sd->vold.brightness) { |
850 | sd->vold.backlight = backlight; | 661 | sd->vold.brightness = bright; |
851 | if (backlight < 0 || backlight > sd->vmax.backlight) | 662 | if (bright < 0 || bright > sd->vmax.brightness) |
852 | backlight = 0; | 663 | bright = 0; |
853 | 664 | ||
854 | dat_multi1[2] = 0x9d; | 665 | dat_bright2[2] = bright; |
855 | dat_multi3[2] = dat_multi1[2] + 1; | 666 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright1); |
856 | dat_multi4[2] = dat_multi2[2] = backlight; | 667 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright2); |
857 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1); | 668 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright3); |
858 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2); | 669 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright4); |
859 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3); | 670 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright5); |
860 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4); | 671 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright6); |
861 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5); | ||
862 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6); | ||
863 | } | 672 | } |
864 | 673 | ||
865 | if (gam != sd->vold.gamma) { | 674 | if (cntr != sd->vold.contrast || gam != sd->vold.gamma) { |
675 | sd->vold.contrast = cntr; | ||
676 | if (cntr < 0 || cntr > sd->vmax.contrast) | ||
677 | cntr = 0; | ||
866 | sd->vold.gamma = gam; | 678 | sd->vold.gamma = gam; |
867 | if (gam < 0 || gam > sd->vmax.gamma) | 679 | if (gam < 0 || gam > sd->vmax.gamma) |
868 | gam = 0; | 680 | gam = 0; |
869 | 681 | ||
870 | dat_multi1[2] = 0x6d; | 682 | dat_multi1[2] = 0x6d; |
871 | dat_multi3[2] = dat_multi1[2] + 1; | 683 | dat_multi3[2] = dat_multi1[2] + 1; |
872 | dat_multi4[2] = dat_multi2[2] = 0x40 + gam; | 684 | if (cntr == 0) |
685 | cntr = 4; | ||
686 | dat_multi4[2] = dat_multi2[2] = cntr * 0x10 + 2 - gam; | ||
873 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1); | 687 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1); |
874 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2); | 688 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2); |
875 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3); | 689 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3); |
@@ -878,14 +692,14 @@ static int mi2020_camera_settings(struct gspca_dev *gspca_dev) | |||
878 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6); | 692 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6); |
879 | } | 693 | } |
880 | 694 | ||
881 | if (cntr != sd->vold.contrast) { | 695 | if (backlight != sd->vold.backlight) { |
882 | sd->vold.contrast = cntr; | 696 | sd->vold.backlight = backlight; |
883 | if (cntr < 0 || cntr > sd->vmax.contrast) | 697 | if (backlight < 0 || backlight > sd->vmax.backlight) |
884 | cntr = 0; | 698 | backlight = 0; |
885 | 699 | ||
886 | dat_multi1[2] = 0x6d; | 700 | dat_multi1[2] = 0x9d; |
887 | dat_multi3[2] = dat_multi1[2] + 1; | 701 | dat_multi3[2] = dat_multi1[2] + 1; |
888 | dat_multi4[2] = dat_multi2[2] = 0x12 + 16 * cntr; | 702 | dat_multi4[2] = dat_multi2[2] = backlight; |
889 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1); | 703 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1); |
890 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2); | 704 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2); |
891 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3); | 705 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3); |
@@ -894,20 +708,6 @@ static int mi2020_camera_settings(struct gspca_dev *gspca_dev) | |||
894 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6); | 708 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6); |
895 | } | 709 | } |
896 | 710 | ||
897 | if (bright != sd->vold.brightness) { | ||
898 | sd->vold.brightness = bright; | ||
899 | if (bright < 0 || bright > sd->vmax.brightness) | ||
900 | bright = 0; | ||
901 | |||
902 | dat_bright2[2] = bright; | ||
903 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright1); | ||
904 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright2); | ||
905 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright3); | ||
906 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright4); | ||
907 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright5); | ||
908 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright6); | ||
909 | } | ||
910 | |||
911 | if (sharp != sd->vold.sharpness) { | 711 | if (sharp != sd->vold.sharpness) { |
912 | sd->vold.sharpness = sharp; | 712 | sd->vold.sharpness = sharp; |
913 | if (sharp < 0 || sharp > sd->vmax.sharpness) | 713 | if (sharp < 0 || sharp > sd->vmax.sharpness) |
@@ -928,9 +728,6 @@ static int mi2020_camera_settings(struct gspca_dev *gspca_dev) | |||
928 | static void mi2020_post_unset_alt(struct gspca_dev *gspca_dev) | 728 | static void mi2020_post_unset_alt(struct gspca_dev *gspca_dev) |
929 | { | 729 | { |
930 | ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL); | 730 | ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL); |
931 | msleep(20); | 731 | msleep(40); |
932 | if (_MI2020c_ || _MI2020_) | 732 | ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0000, 0, NULL); |
933 | ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0000, 0, NULL); | ||
934 | else | ||
935 | ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x0000, 0, NULL); | ||
936 | } | 733 | } |
diff --git a/drivers/media/video/gspca/gl860/gl860-ov9655.c b/drivers/media/video/gspca/gl860/gl860-ov9655.c index d412694c50af..5ae9619d72a5 100644 --- a/drivers/media/video/gspca/gl860/gl860-ov9655.c +++ b/drivers/media/video/gspca/gl860/gl860-ov9655.c | |||
@@ -69,7 +69,7 @@ static u8 *tbl_640[] = { | |||
69 | "\xd0\x01\xd1\x08\xd2\xe0\xd3\x01" "\xd4\x10\xd5\x80" | 69 | "\xd0\x01\xd1\x08\xd2\xe0\xd3\x01" "\xd4\x10\xd5\x80" |
70 | }; | 70 | }; |
71 | 71 | ||
72 | static u8 *tbl_800[] = { | 72 | static u8 *tbl_1280[] = { |
73 | "\x00\x40\x07\x6a\x06\xf3\x0d\x6a" "\x10\x10\xc1\x01" | 73 | "\x00\x40\x07\x6a\x06\xf3\x0d\x6a" "\x10\x10\xc1\x01" |
74 | , | 74 | , |
75 | "\x12\x80\x00\x00\x01\x98\x02\x80" "\x03\x12\x04\x01\x0b\x57\x0e\x61" | 75 | "\x12\x80\x00\x00\x01\x98\x02\x80" "\x03\x12\x04\x01\x0b\x57\x0e\x61" |
@@ -217,7 +217,7 @@ static int ov9655_init_post_alt(struct gspca_dev *gspca_dev) | |||
217 | 217 | ||
218 | ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL); | 218 | ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL); |
219 | 219 | ||
220 | tbl = (reso == IMAGE_640) ? tbl_640 : tbl_800; | 220 | tbl = (reso == IMAGE_640) ? tbl_640 : tbl_1280; |
221 | 221 | ||
222 | ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, | 222 | ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, |
223 | tbl_length[0], tbl[0]); | 223 | tbl_length[0], tbl[0]); |
diff --git a/drivers/media/video/gspca/gl860/gl860.c b/drivers/media/video/gspca/gl860/gl860.c index 9e42476c0eaf..e86eb8b4aedc 100644 --- a/drivers/media/video/gspca/gl860/gl860.c +++ b/drivers/media/video/gspca/gl860/gl860.c | |||
@@ -63,7 +63,7 @@ static int sd_set_##thename(struct gspca_dev *gspca_dev, s32 val)\ | |||
63 | \ | 63 | \ |
64 | sd->vcur.thename = val;\ | 64 | sd->vcur.thename = val;\ |
65 | if (gspca_dev->streaming)\ | 65 | if (gspca_dev->streaming)\ |
66 | sd->dev_camera_settings(gspca_dev);\ | 66 | sd->waitSet = 1;\ |
67 | return 0;\ | 67 | return 0;\ |
68 | } \ | 68 | } \ |
69 | static int sd_get_##thename(struct gspca_dev *gspca_dev, s32 *val)\ | 69 | static int sd_get_##thename(struct gspca_dev *gspca_dev, s32 *val)\ |
@@ -91,7 +91,6 @@ SD_SETGET(contrast) | |||
91 | /* control table */ | 91 | /* control table */ |
92 | static struct ctrl sd_ctrls_mi1320[GL860_NCTRLS]; | 92 | static struct ctrl sd_ctrls_mi1320[GL860_NCTRLS]; |
93 | static struct ctrl sd_ctrls_mi2020[GL860_NCTRLS]; | 93 | static struct ctrl sd_ctrls_mi2020[GL860_NCTRLS]; |
94 | static struct ctrl sd_ctrls_mi2020b[GL860_NCTRLS]; | ||
95 | static struct ctrl sd_ctrls_ov2640[GL860_NCTRLS]; | 94 | static struct ctrl sd_ctrls_ov2640[GL860_NCTRLS]; |
96 | static struct ctrl sd_ctrls_ov9655[GL860_NCTRLS]; | 95 | static struct ctrl sd_ctrls_ov9655[GL860_NCTRLS]; |
97 | 96 | ||
@@ -121,8 +120,6 @@ static int gl860_build_control_table(struct gspca_dev *gspca_dev) | |||
121 | sd_ctrls = sd_ctrls_mi1320; | 120 | sd_ctrls = sd_ctrls_mi1320; |
122 | else if (_MI2020_) | 121 | else if (_MI2020_) |
123 | sd_ctrls = sd_ctrls_mi2020; | 122 | sd_ctrls = sd_ctrls_mi2020; |
124 | else if (_MI2020b_) | ||
125 | sd_ctrls = sd_ctrls_mi2020b; | ||
126 | else if (_OV2640_) | 123 | else if (_OV2640_) |
127 | sd_ctrls = sd_ctrls_ov2640; | 124 | sd_ctrls = sd_ctrls_ov2640; |
128 | else if (_OV9655_) | 125 | else if (_OV9655_) |
@@ -187,19 +184,6 @@ static const struct sd_desc sd_desc_mi2020 = { | |||
187 | .dq_callback = sd_callback, | 184 | .dq_callback = sd_callback, |
188 | }; | 185 | }; |
189 | 186 | ||
190 | static const struct sd_desc sd_desc_mi2020b = { | ||
191 | .name = MODULE_NAME, | ||
192 | .ctrls = sd_ctrls_mi2020b, | ||
193 | .nctrls = GL860_NCTRLS, | ||
194 | .config = sd_config, | ||
195 | .init = sd_init, | ||
196 | .isoc_init = sd_isoc_init, | ||
197 | .start = sd_start, | ||
198 | .stop0 = sd_stop0, | ||
199 | .pkt_scan = sd_pkt_scan, | ||
200 | .dq_callback = sd_callback, | ||
201 | }; | ||
202 | |||
203 | static const struct sd_desc sd_desc_ov2640 = { | 187 | static const struct sd_desc sd_desc_ov2640 = { |
204 | .name = MODULE_NAME, | 188 | .name = MODULE_NAME, |
205 | .ctrls = sd_ctrls_ov2640, | 189 | .ctrls = sd_ctrls_ov2640, |
@@ -235,9 +219,9 @@ static struct v4l2_pix_format mi2020_mode[] = { | |||
235 | .colorspace = V4L2_COLORSPACE_SRGB, | 219 | .colorspace = V4L2_COLORSPACE_SRGB, |
236 | .priv = 0 | 220 | .priv = 0 |
237 | }, | 221 | }, |
238 | { 800, 600, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, | 222 | { 800, 598, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, |
239 | .bytesperline = 800, | 223 | .bytesperline = 800, |
240 | .sizeimage = 800 * 600, | 224 | .sizeimage = 800 * 598, |
241 | .colorspace = V4L2_COLORSPACE_SRGB, | 225 | .colorspace = V4L2_COLORSPACE_SRGB, |
242 | .priv = 1 | 226 | .priv = 1 |
243 | }, | 227 | }, |
@@ -247,9 +231,9 @@ static struct v4l2_pix_format mi2020_mode[] = { | |||
247 | .colorspace = V4L2_COLORSPACE_SRGB, | 231 | .colorspace = V4L2_COLORSPACE_SRGB, |
248 | .priv = 2 | 232 | .priv = 2 |
249 | }, | 233 | }, |
250 | {1600, 1200, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, | 234 | {1600, 1198, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, |
251 | .bytesperline = 1600, | 235 | .bytesperline = 1600, |
252 | .sizeimage = 1600 * 1200, | 236 | .sizeimage = 1600 * 1198, |
253 | .colorspace = V4L2_COLORSPACE_SRGB, | 237 | .colorspace = V4L2_COLORSPACE_SRGB, |
254 | .priv = 3 | 238 | .priv = 3 |
255 | }, | 239 | }, |
@@ -344,8 +328,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
344 | sd->sensor = ID_OV9655; | 328 | sd->sensor = ID_OV9655; |
345 | else if (strcmp(sensor, "MI2020") == 0) | 329 | else if (strcmp(sensor, "MI2020") == 0) |
346 | sd->sensor = ID_MI2020; | 330 | sd->sensor = ID_MI2020; |
347 | else if (strcmp(sensor, "MI2020b") == 0) | ||
348 | sd->sensor = ID_MI2020b; | ||
349 | 331 | ||
350 | /* Get sensor and set the suitable init/start/../stop functions */ | 332 | /* Get sensor and set the suitable init/start/../stop functions */ |
351 | if (gl860_guess_sensor(gspca_dev, vendor_id, product_id) == -1) | 333 | if (gl860_guess_sensor(gspca_dev, vendor_id, product_id) == -1) |
@@ -369,13 +351,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
369 | dev_init_settings = mi2020_init_settings; | 351 | dev_init_settings = mi2020_init_settings; |
370 | break; | 352 | break; |
371 | 353 | ||
372 | case ID_MI2020b: | ||
373 | gspca_dev->sd_desc = &sd_desc_mi2020b; | ||
374 | cam->cam_mode = mi2020_mode; | ||
375 | cam->nmodes = ARRAY_SIZE(mi2020_mode); | ||
376 | dev_init_settings = mi2020_init_settings; | ||
377 | break; | ||
378 | |||
379 | case ID_OV2640: | 354 | case ID_OV2640: |
380 | gspca_dev->sd_desc = &sd_desc_ov2640; | 355 | gspca_dev->sd_desc = &sd_desc_ov2640; |
381 | cam->cam_mode = ov2640_mode; | 356 | cam->cam_mode = ov2640_mode; |
@@ -620,10 +595,7 @@ int gl860_RTx(struct gspca_dev *gspca_dev, | |||
620 | else if (len > 1 && r < len) | 595 | else if (len > 1 && r < len) |
621 | PDEBUG(D_ERR, "short ctrl transfer %d/%d", r, len); | 596 | PDEBUG(D_ERR, "short ctrl transfer %d/%d", r, len); |
622 | 597 | ||
623 | if ((_MI2020_ || _MI2020b_ || _MI2020c_) && (val || index)) | 598 | msleep(1); |
624 | msleep(1); | ||
625 | if (_OV2640_) | ||
626 | msleep(1); | ||
627 | 599 | ||
628 | return r; | 600 | return r; |
629 | } | 601 | } |
@@ -767,8 +739,6 @@ static int gl860_guess_sensor(struct gspca_dev *gspca_dev, | |||
767 | PDEBUG(D_PROBE, "05e3:f191 sensor MI1320 (1.3M)"); | 739 | PDEBUG(D_PROBE, "05e3:f191 sensor MI1320 (1.3M)"); |
768 | } else if (_MI2020_) { | 740 | } else if (_MI2020_) { |
769 | PDEBUG(D_PROBE, "05e3:0503 sensor MI2020 (2.0M)"); | 741 | PDEBUG(D_PROBE, "05e3:0503 sensor MI2020 (2.0M)"); |
770 | } else if (_MI2020b_) { | ||
771 | PDEBUG(D_PROBE, "05e3:0503 sensor MI2020 alt. driver (2.0M)"); | ||
772 | } else if (_OV9655_) { | 742 | } else if (_OV9655_) { |
773 | PDEBUG(D_PROBE, "05e3:0503 sensor OV9655 (1.3M)"); | 743 | PDEBUG(D_PROBE, "05e3:0503 sensor OV9655 (1.3M)"); |
774 | } else if (_OV2640_) { | 744 | } else if (_OV2640_) { |
diff --git a/drivers/media/video/gspca/gl860/gl860.h b/drivers/media/video/gspca/gl860/gl860.h index 305061ff8387..49ad4acbf602 100644 --- a/drivers/media/video/gspca/gl860/gl860.h +++ b/drivers/media/video/gspca/gl860/gl860.h | |||
@@ -32,19 +32,16 @@ | |||
32 | #define ID_OV2640 2 | 32 | #define ID_OV2640 2 |
33 | #define ID_OV9655 4 | 33 | #define ID_OV9655 4 |
34 | #define ID_MI2020 8 | 34 | #define ID_MI2020 8 |
35 | #define ID_MI2020b 16 | ||
36 | 35 | ||
37 | #define _MI1320_ (((struct sd *) gspca_dev)->sensor == ID_MI1320) | 36 | #define _MI1320_ (((struct sd *) gspca_dev)->sensor == ID_MI1320) |
38 | #define _MI2020_ (((struct sd *) gspca_dev)->sensor == ID_MI2020) | 37 | #define _MI2020_ (((struct sd *) gspca_dev)->sensor == ID_MI2020) |
39 | #define _MI2020b_ (((struct sd *) gspca_dev)->sensor == ID_MI2020b) | ||
40 | #define _MI2020c_ 0 | ||
41 | #define _OV2640_ (((struct sd *) gspca_dev)->sensor == ID_OV2640) | 38 | #define _OV2640_ (((struct sd *) gspca_dev)->sensor == ID_OV2640) |
42 | #define _OV9655_ (((struct sd *) gspca_dev)->sensor == ID_OV9655) | 39 | #define _OV9655_ (((struct sd *) gspca_dev)->sensor == ID_OV9655) |
43 | 40 | ||
44 | #define IMAGE_640 0 | 41 | #define IMAGE_640 0 |
45 | #define IMAGE_800 1 | 42 | #define IMAGE_800 1 |
46 | #define IMAGE_1280 2 | 43 | #define IMAGE_1280 2 |
47 | #define IMAGE_1600 3 | 44 | #define IMAGE_1600 3 |
48 | 45 | ||
49 | struct sd_gl860 { | 46 | struct sd_gl860 { |
50 | u16 backlight; | 47 | u16 backlight; |
@@ -75,10 +72,10 @@ struct sd { | |||
75 | int (*dev_camera_settings)(struct gspca_dev *); | 72 | int (*dev_camera_settings)(struct gspca_dev *); |
76 | 73 | ||
77 | u8 swapRB; | 74 | u8 swapRB; |
78 | u8 mirrorMask; | 75 | u8 mirrorMask; |
79 | u8 sensor; | 76 | u8 sensor; |
80 | s32 nbIm; | 77 | s32 nbIm; |
81 | s32 nbRightUp; | 78 | s32 nbRightUp; |
82 | u8 waitSet; | 79 | u8 waitSet; |
83 | }; | 80 | }; |
84 | 81 | ||
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 678675bb3652..d951b0f0e053 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -201,7 +201,7 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev, | |||
201 | 201 | ||
202 | buffer_len = le16_to_cpu(ep->wMaxPacketSize); | 202 | buffer_len = le16_to_cpu(ep->wMaxPacketSize); |
203 | interval = ep->bInterval; | 203 | interval = ep->bInterval; |
204 | PDEBUG(D_PROBE, "found int in endpoint: 0x%x, " | 204 | PDEBUG(D_CONF, "found int in endpoint: 0x%x, " |
205 | "buffer_len=%u, interval=%u", | 205 | "buffer_len=%u, interval=%u", |
206 | ep->bEndpointAddress, buffer_len, interval); | 206 | ep->bEndpointAddress, buffer_len, interval); |
207 | 207 | ||
@@ -226,7 +226,7 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev, | |||
226 | gspca_dev->int_urb = urb; | 226 | gspca_dev->int_urb = urb; |
227 | ret = usb_submit_urb(urb, GFP_KERNEL); | 227 | ret = usb_submit_urb(urb, GFP_KERNEL); |
228 | if (ret < 0) { | 228 | if (ret < 0) { |
229 | PDEBUG(D_ERR, "submit URB failed with error %i", ret); | 229 | PDEBUG(D_ERR, "submit int URB failed with error %i", ret); |
230 | goto error_submit; | 230 | goto error_submit; |
231 | } | 231 | } |
232 | return ret; | 232 | return ret; |
@@ -294,19 +294,6 @@ static inline int gspca_input_connect(struct gspca_dev *dev) | |||
294 | } | 294 | } |
295 | #endif | 295 | #endif |
296 | 296 | ||
297 | /* get the current input frame buffer */ | ||
298 | struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev) | ||
299 | { | ||
300 | struct gspca_frame *frame; | ||
301 | |||
302 | frame = gspca_dev->cur_frame; | ||
303 | if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) | ||
304 | != V4L2_BUF_FLAG_QUEUED) | ||
305 | return NULL; | ||
306 | return frame; | ||
307 | } | ||
308 | EXPORT_SYMBOL(gspca_get_i_frame); | ||
309 | |||
310 | /* | 297 | /* |
311 | * fill a video frame from an URB and resubmit | 298 | * fill a video frame from an URB and resubmit |
312 | */ | 299 | */ |
@@ -439,20 +426,20 @@ void gspca_frame_add(struct gspca_dev *gspca_dev, | |||
439 | 426 | ||
440 | PDEBUG(D_PACK, "add t:%d l:%d", packet_type, len); | 427 | PDEBUG(D_PACK, "add t:%d l:%d", packet_type, len); |
441 | 428 | ||
442 | /* check the availability of the frame buffer */ | ||
443 | frame = gspca_dev->cur_frame; | ||
444 | if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) | ||
445 | != V4L2_BUF_FLAG_QUEUED) { | ||
446 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
447 | return; | ||
448 | } | ||
449 | |||
450 | /* when start of a new frame, if the current frame buffer | ||
451 | * is not queued, discard the whole frame */ | ||
452 | if (packet_type == FIRST_PACKET) { | 429 | if (packet_type == FIRST_PACKET) { |
453 | frame->data_end = frame->data; | 430 | i = atomic_read(&gspca_dev->fr_i); |
431 | |||
432 | /* if there are no queued buffer, discard the whole frame */ | ||
433 | if (i == atomic_read(&gspca_dev->fr_q)) { | ||
434 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
435 | return; | ||
436 | } | ||
437 | j = gspca_dev->fr_queue[i]; | ||
438 | frame = &gspca_dev->frame[j]; | ||
454 | frame->v4l2_buf.timestamp = ktime_to_timeval(ktime_get()); | 439 | frame->v4l2_buf.timestamp = ktime_to_timeval(ktime_get()); |
455 | frame->v4l2_buf.sequence = ++gspca_dev->sequence; | 440 | frame->v4l2_buf.sequence = ++gspca_dev->sequence; |
441 | gspca_dev->image = frame->data; | ||
442 | gspca_dev->image_len = 0; | ||
456 | } else if (gspca_dev->last_packet_type == DISCARD_PACKET) { | 443 | } else if (gspca_dev->last_packet_type == DISCARD_PACKET) { |
457 | if (packet_type == LAST_PACKET) | 444 | if (packet_type == LAST_PACKET) |
458 | gspca_dev->last_packet_type = packet_type; | 445 | gspca_dev->last_packet_type = packet_type; |
@@ -461,34 +448,37 @@ void gspca_frame_add(struct gspca_dev *gspca_dev, | |||
461 | 448 | ||
462 | /* append the packet to the frame buffer */ | 449 | /* append the packet to the frame buffer */ |
463 | if (len > 0) { | 450 | if (len > 0) { |
464 | if (frame->data_end - frame->data + len | 451 | if (gspca_dev->image_len + len > gspca_dev->frsz) { |
465 | > frame->v4l2_buf.length) { | 452 | PDEBUG(D_ERR|D_PACK, "frame overflow %d > %d", |
466 | PDEBUG(D_ERR|D_PACK, "frame overflow %zd > %d", | 453 | gspca_dev->image_len + len, |
467 | frame->data_end - frame->data + len, | 454 | gspca_dev->frsz); |
468 | frame->v4l2_buf.length); | ||
469 | packet_type = DISCARD_PACKET; | 455 | packet_type = DISCARD_PACKET; |
470 | } else { | 456 | } else { |
471 | memcpy(frame->data_end, data, len); | 457 | memcpy(gspca_dev->image + gspca_dev->image_len, |
472 | frame->data_end += len; | 458 | data, len); |
459 | gspca_dev->image_len += len; | ||
473 | } | 460 | } |
474 | } | 461 | } |
475 | gspca_dev->last_packet_type = packet_type; | 462 | gspca_dev->last_packet_type = packet_type; |
476 | 463 | ||
477 | /* if last packet, wake up the application and advance in the queue */ | 464 | /* if last packet, invalidate packet concatenation until |
465 | * next first packet, wake up the application and advance | ||
466 | * in the queue */ | ||
478 | if (packet_type == LAST_PACKET) { | 467 | if (packet_type == LAST_PACKET) { |
479 | frame->v4l2_buf.bytesused = frame->data_end - frame->data; | 468 | i = atomic_read(&gspca_dev->fr_i); |
480 | frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED; | ||
481 | frame->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE; | ||
482 | wake_up_interruptible(&gspca_dev->wq); /* event = new frame */ | ||
483 | i = (gspca_dev->fr_i + 1) % gspca_dev->nframes; | ||
484 | gspca_dev->fr_i = i; | ||
485 | PDEBUG(D_FRAM, "frame complete len:%d q:%d i:%d o:%d", | ||
486 | frame->v4l2_buf.bytesused, | ||
487 | gspca_dev->fr_q, | ||
488 | i, | ||
489 | gspca_dev->fr_o); | ||
490 | j = gspca_dev->fr_queue[i]; | 469 | j = gspca_dev->fr_queue[i]; |
491 | gspca_dev->cur_frame = &gspca_dev->frame[j]; | 470 | frame = &gspca_dev->frame[j]; |
471 | frame->v4l2_buf.bytesused = gspca_dev->image_len; | ||
472 | frame->v4l2_buf.flags = (frame->v4l2_buf.flags | ||
473 | | V4L2_BUF_FLAG_DONE) | ||
474 | & ~V4L2_BUF_FLAG_QUEUED; | ||
475 | i = (i + 1) % GSPCA_MAX_FRAMES; | ||
476 | atomic_set(&gspca_dev->fr_i, i); | ||
477 | wake_up_interruptible(&gspca_dev->wq); /* event = new frame */ | ||
478 | PDEBUG(D_FRAM, "frame complete len:%d", | ||
479 | frame->v4l2_buf.bytesused); | ||
480 | gspca_dev->image = NULL; | ||
481 | gspca_dev->image_len = 0; | ||
492 | } | 482 | } |
493 | } | 483 | } |
494 | EXPORT_SYMBOL(gspca_frame_add); | 484 | EXPORT_SYMBOL(gspca_frame_add); |
@@ -506,36 +496,6 @@ static int gspca_is_compressed(__u32 format) | |||
506 | return 0; | 496 | return 0; |
507 | } | 497 | } |
508 | 498 | ||
509 | static void *rvmalloc(long size) | ||
510 | { | ||
511 | void *mem; | ||
512 | unsigned long adr; | ||
513 | |||
514 | mem = vmalloc_32(size); | ||
515 | if (mem != NULL) { | ||
516 | adr = (unsigned long) mem; | ||
517 | while (size > 0) { | ||
518 | SetPageReserved(vmalloc_to_page((void *) adr)); | ||
519 | adr += PAGE_SIZE; | ||
520 | size -= PAGE_SIZE; | ||
521 | } | ||
522 | } | ||
523 | return mem; | ||
524 | } | ||
525 | |||
526 | static void rvfree(void *mem, long size) | ||
527 | { | ||
528 | unsigned long adr; | ||
529 | |||
530 | adr = (unsigned long) mem; | ||
531 | while (size > 0) { | ||
532 | ClearPageReserved(vmalloc_to_page((void *) adr)); | ||
533 | adr += PAGE_SIZE; | ||
534 | size -= PAGE_SIZE; | ||
535 | } | ||
536 | vfree(mem); | ||
537 | } | ||
538 | |||
539 | static int frame_alloc(struct gspca_dev *gspca_dev, | 499 | static int frame_alloc(struct gspca_dev *gspca_dev, |
540 | unsigned int count) | 500 | unsigned int count) |
541 | { | 501 | { |
@@ -548,9 +508,9 @@ static int frame_alloc(struct gspca_dev *gspca_dev, | |||
548 | PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz); | 508 | PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz); |
549 | frsz = PAGE_ALIGN(frsz); | 509 | frsz = PAGE_ALIGN(frsz); |
550 | gspca_dev->frsz = frsz; | 510 | gspca_dev->frsz = frsz; |
551 | if (count > GSPCA_MAX_FRAMES) | 511 | if (count >= GSPCA_MAX_FRAMES) |
552 | count = GSPCA_MAX_FRAMES; | 512 | count = GSPCA_MAX_FRAMES - 1; |
553 | gspca_dev->frbuf = rvmalloc(frsz * count); | 513 | gspca_dev->frbuf = vmalloc_32(frsz * count); |
554 | if (!gspca_dev->frbuf) { | 514 | if (!gspca_dev->frbuf) { |
555 | err("frame alloc failed"); | 515 | err("frame alloc failed"); |
556 | return -ENOMEM; | 516 | return -ENOMEM; |
@@ -565,14 +525,12 @@ static int frame_alloc(struct gspca_dev *gspca_dev, | |||
565 | frame->v4l2_buf.length = frsz; | 525 | frame->v4l2_buf.length = frsz; |
566 | frame->v4l2_buf.memory = gspca_dev->memory; | 526 | frame->v4l2_buf.memory = gspca_dev->memory; |
567 | frame->v4l2_buf.sequence = 0; | 527 | frame->v4l2_buf.sequence = 0; |
568 | frame->data = frame->data_end = | 528 | frame->data = gspca_dev->frbuf + i * frsz; |
569 | gspca_dev->frbuf + i * frsz; | ||
570 | frame->v4l2_buf.m.offset = i * frsz; | 529 | frame->v4l2_buf.m.offset = i * frsz; |
571 | } | 530 | } |
572 | gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0; | 531 | atomic_set(&gspca_dev->fr_q, 0); |
573 | gspca_dev->cur_frame = &gspca_dev->frame[0]; | 532 | atomic_set(&gspca_dev->fr_i, 0); |
574 | gspca_dev->last_packet_type = DISCARD_PACKET; | 533 | gspca_dev->fr_o = 0; |
575 | gspca_dev->sequence = 0; | ||
576 | return 0; | 534 | return 0; |
577 | } | 535 | } |
578 | 536 | ||
@@ -582,8 +540,7 @@ static void frame_free(struct gspca_dev *gspca_dev) | |||
582 | 540 | ||
583 | PDEBUG(D_STREAM, "frame free"); | 541 | PDEBUG(D_STREAM, "frame free"); |
584 | if (gspca_dev->frbuf != NULL) { | 542 | if (gspca_dev->frbuf != NULL) { |
585 | rvfree(gspca_dev->frbuf, | 543 | vfree(gspca_dev->frbuf); |
586 | gspca_dev->nframes * gspca_dev->frsz); | ||
587 | gspca_dev->frbuf = NULL; | 544 | gspca_dev->frbuf = NULL; |
588 | for (i = 0; i < gspca_dev->nframes; i++) | 545 | for (i = 0; i < gspca_dev->nframes; i++) |
589 | gspca_dev->frame[i].data = NULL; | 546 | gspca_dev->frame[i].data = NULL; |
@@ -683,12 +640,16 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) | |||
683 | : USB_ENDPOINT_XFER_ISOC; | 640 | : USB_ENDPOINT_XFER_ISOC; |
684 | i = gspca_dev->alt; /* previous alt setting */ | 641 | i = gspca_dev->alt; /* previous alt setting */ |
685 | if (gspca_dev->cam.reverse_alts) { | 642 | if (gspca_dev->cam.reverse_alts) { |
643 | if (gspca_dev->audio) | ||
644 | i++; | ||
686 | while (++i < gspca_dev->nbalt) { | 645 | while (++i < gspca_dev->nbalt) { |
687 | ep = alt_xfer(&intf->altsetting[i], xfer); | 646 | ep = alt_xfer(&intf->altsetting[i], xfer); |
688 | if (ep) | 647 | if (ep) |
689 | break; | 648 | break; |
690 | } | 649 | } |
691 | } else { | 650 | } else { |
651 | if (gspca_dev->audio) | ||
652 | i--; | ||
692 | while (--i >= 0) { | 653 | while (--i >= 0) { |
693 | ep = alt_xfer(&intf->altsetting[i], xfer); | 654 | ep = alt_xfer(&intf->altsetting[i], xfer); |
694 | if (ep) | 655 | if (ep) |
@@ -811,6 +772,12 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
811 | goto out; | 772 | goto out; |
812 | } | 773 | } |
813 | 774 | ||
775 | /* reset the streaming variables */ | ||
776 | gspca_dev->image = NULL; | ||
777 | gspca_dev->image_len = 0; | ||
778 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
779 | gspca_dev->sequence = 0; | ||
780 | |||
814 | gspca_dev->usb_err = 0; | 781 | gspca_dev->usb_err = 0; |
815 | 782 | ||
816 | /* set the higher alternate setting and | 783 | /* set the higher alternate setting and |
@@ -1433,34 +1400,6 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
1433 | return ret; | 1400 | return ret; |
1434 | } | 1401 | } |
1435 | 1402 | ||
1436 | /*fixme: have an audio flag in gspca_dev?*/ | ||
1437 | static int vidioc_s_audio(struct file *file, void *priv, | ||
1438 | struct v4l2_audio *audio) | ||
1439 | { | ||
1440 | if (audio->index != 0) | ||
1441 | return -EINVAL; | ||
1442 | return 0; | ||
1443 | } | ||
1444 | |||
1445 | static int vidioc_g_audio(struct file *file, void *priv, | ||
1446 | struct v4l2_audio *audio) | ||
1447 | { | ||
1448 | strcpy(audio->name, "Microphone"); | ||
1449 | return 0; | ||
1450 | } | ||
1451 | |||
1452 | static int vidioc_enumaudio(struct file *file, void *priv, | ||
1453 | struct v4l2_audio *audio) | ||
1454 | { | ||
1455 | if (audio->index != 0) | ||
1456 | return -EINVAL; | ||
1457 | |||
1458 | strcpy(audio->name, "Microphone"); | ||
1459 | audio->capability = 0; | ||
1460 | audio->mode = 0; | ||
1461 | return 0; | ||
1462 | } | ||
1463 | |||
1464 | static int vidioc_querymenu(struct file *file, void *priv, | 1403 | static int vidioc_querymenu(struct file *file, void *priv, |
1465 | struct v4l2_querymenu *qmenu) | 1404 | struct v4l2_querymenu *qmenu) |
1466 | { | 1405 | { |
@@ -1504,7 +1443,8 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
1504 | struct gspca_dev *gspca_dev = priv; | 1443 | struct gspca_dev *gspca_dev = priv; |
1505 | int i, ret = 0, streaming; | 1444 | int i, ret = 0, streaming; |
1506 | 1445 | ||
1507 | switch (rb->memory) { | 1446 | i = rb->memory; /* (avoid compilation warning) */ |
1447 | switch (i) { | ||
1508 | case GSPCA_MEMORY_READ: /* (internal call) */ | 1448 | case GSPCA_MEMORY_READ: /* (internal call) */ |
1509 | case V4L2_MEMORY_MMAP: | 1449 | case V4L2_MEMORY_MMAP: |
1510 | case V4L2_MEMORY_USERPTR: | 1450 | case V4L2_MEMORY_USERPTR: |
@@ -1626,7 +1566,7 @@ static int vidioc_streamoff(struct file *file, void *priv, | |||
1626 | enum v4l2_buf_type buf_type) | 1566 | enum v4l2_buf_type buf_type) |
1627 | { | 1567 | { |
1628 | struct gspca_dev *gspca_dev = priv; | 1568 | struct gspca_dev *gspca_dev = priv; |
1629 | int i, ret; | 1569 | int ret; |
1630 | 1570 | ||
1631 | if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1571 | if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1632 | return -EINVAL; | 1572 | return -EINVAL; |
@@ -1650,12 +1590,10 @@ static int vidioc_streamoff(struct file *file, void *priv, | |||
1650 | gspca_stream_off(gspca_dev); | 1590 | gspca_stream_off(gspca_dev); |
1651 | mutex_unlock(&gspca_dev->usb_lock); | 1591 | mutex_unlock(&gspca_dev->usb_lock); |
1652 | 1592 | ||
1653 | /* empty the application queues */ | 1593 | /* empty the transfer queues */ |
1654 | for (i = 0; i < gspca_dev->nframes; i++) | 1594 | atomic_set(&gspca_dev->fr_q, 0); |
1655 | gspca_dev->frame[i].v4l2_buf.flags &= ~BUF_ALL_FLAGS; | 1595 | atomic_set(&gspca_dev->fr_i, 0); |
1656 | gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0; | 1596 | gspca_dev->fr_o = 0; |
1657 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
1658 | gspca_dev->sequence = 0; | ||
1659 | ret = 0; | 1597 | ret = 0; |
1660 | out: | 1598 | out: |
1661 | mutex_unlock(&gspca_dev->queue_lock); | 1599 | mutex_unlock(&gspca_dev->queue_lock); |
@@ -1732,7 +1670,7 @@ static int vidioc_s_parm(struct file *filp, void *priv, | |||
1732 | int n; | 1670 | int n; |
1733 | 1671 | ||
1734 | n = parm->parm.capture.readbuffers; | 1672 | n = parm->parm.capture.readbuffers; |
1735 | if (n == 0 || n > GSPCA_MAX_FRAMES) | 1673 | if (n == 0 || n >= GSPCA_MAX_FRAMES) |
1736 | parm->parm.capture.readbuffers = gspca_dev->nbufread; | 1674 | parm->parm.capture.readbuffers = gspca_dev->nbufread; |
1737 | else | 1675 | else |
1738 | gspca_dev->nbufread = n; | 1676 | gspca_dev->nbufread = n; |
@@ -1755,49 +1693,6 @@ static int vidioc_s_parm(struct file *filp, void *priv, | |||
1755 | return 0; | 1693 | return 0; |
1756 | } | 1694 | } |
1757 | 1695 | ||
1758 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
1759 | static int vidiocgmbuf(struct file *file, void *priv, | ||
1760 | struct video_mbuf *mbuf) | ||
1761 | { | ||
1762 | struct gspca_dev *gspca_dev = file->private_data; | ||
1763 | int i; | ||
1764 | |||
1765 | PDEBUG(D_STREAM, "cgmbuf"); | ||
1766 | if (gspca_dev->nframes == 0) { | ||
1767 | int ret; | ||
1768 | |||
1769 | { | ||
1770 | struct v4l2_format fmt; | ||
1771 | |||
1772 | fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1773 | i = gspca_dev->cam.nmodes - 1; /* highest mode */ | ||
1774 | fmt.fmt.pix.width = gspca_dev->cam.cam_mode[i].width; | ||
1775 | fmt.fmt.pix.height = gspca_dev->cam.cam_mode[i].height; | ||
1776 | fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24; | ||
1777 | ret = vidioc_s_fmt_vid_cap(file, priv, &fmt); | ||
1778 | if (ret != 0) | ||
1779 | return ret; | ||
1780 | } | ||
1781 | { | ||
1782 | struct v4l2_requestbuffers rb; | ||
1783 | |||
1784 | memset(&rb, 0, sizeof rb); | ||
1785 | rb.count = 4; | ||
1786 | rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1787 | rb.memory = V4L2_MEMORY_MMAP; | ||
1788 | ret = vidioc_reqbufs(file, priv, &rb); | ||
1789 | if (ret != 0) | ||
1790 | return ret; | ||
1791 | } | ||
1792 | } | ||
1793 | mbuf->frames = gspca_dev->nframes; | ||
1794 | mbuf->size = gspca_dev->frsz * gspca_dev->nframes; | ||
1795 | for (i = 0; i < mbuf->frames; i++) | ||
1796 | mbuf->offsets[i] = gspca_dev->frame[i].v4l2_buf.m.offset; | ||
1797 | return 0; | ||
1798 | } | ||
1799 | #endif | ||
1800 | |||
1801 | static int dev_mmap(struct file *file, struct vm_area_struct *vma) | 1696 | static int dev_mmap(struct file *file, struct vm_area_struct *vma) |
1802 | { | 1697 | { |
1803 | struct gspca_dev *gspca_dev = file->private_data; | 1698 | struct gspca_dev *gspca_dev = file->private_data; |
@@ -1838,12 +1733,7 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma) | |||
1838 | ret = -EINVAL; | 1733 | ret = -EINVAL; |
1839 | goto out; | 1734 | goto out; |
1840 | } | 1735 | } |
1841 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 1736 | if (size != frame->v4l2_buf.length) { |
1842 | /* v4l1 maps all the buffers */ | ||
1843 | if (i != 0 | ||
1844 | || size != frame->v4l2_buf.length * gspca_dev->nframes) | ||
1845 | #endif | ||
1846 | if (size != frame->v4l2_buf.length) { | ||
1847 | PDEBUG(D_STREAM, "mmap bad size"); | 1737 | PDEBUG(D_STREAM, "mmap bad size"); |
1848 | ret = -EINVAL; | 1738 | ret = -EINVAL; |
1849 | goto out; | 1739 | goto out; |
@@ -1883,21 +1773,17 @@ out: | |||
1883 | static int frame_wait(struct gspca_dev *gspca_dev, | 1773 | static int frame_wait(struct gspca_dev *gspca_dev, |
1884 | int nonblock_ing) | 1774 | int nonblock_ing) |
1885 | { | 1775 | { |
1886 | struct gspca_frame *frame; | 1776 | int i, ret; |
1887 | int i, j, ret; | ||
1888 | 1777 | ||
1889 | /* check if a frame is ready */ | 1778 | /* check if a frame is ready */ |
1890 | i = gspca_dev->fr_o; | 1779 | i = gspca_dev->fr_o; |
1891 | j = gspca_dev->fr_queue[i]; | 1780 | if (i == atomic_read(&gspca_dev->fr_i)) { |
1892 | frame = &gspca_dev->frame[j]; | ||
1893 | |||
1894 | if (!(frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE)) { | ||
1895 | if (nonblock_ing) | 1781 | if (nonblock_ing) |
1896 | return -EAGAIN; | 1782 | return -EAGAIN; |
1897 | 1783 | ||
1898 | /* wait till a frame is ready */ | 1784 | /* wait till a frame is ready */ |
1899 | ret = wait_event_interruptible_timeout(gspca_dev->wq, | 1785 | ret = wait_event_interruptible_timeout(gspca_dev->wq, |
1900 | (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE) || | 1786 | i != atomic_read(&gspca_dev->fr_i) || |
1901 | !gspca_dev->streaming || !gspca_dev->present, | 1787 | !gspca_dev->streaming || !gspca_dev->present, |
1902 | msecs_to_jiffies(3000)); | 1788 | msecs_to_jiffies(3000)); |
1903 | if (ret < 0) | 1789 | if (ret < 0) |
@@ -1906,11 +1792,7 @@ static int frame_wait(struct gspca_dev *gspca_dev, | |||
1906 | return -EIO; | 1792 | return -EIO; |
1907 | } | 1793 | } |
1908 | 1794 | ||
1909 | gspca_dev->fr_o = (i + 1) % gspca_dev->nframes; | 1795 | gspca_dev->fr_o = (i + 1) % GSPCA_MAX_FRAMES; |
1910 | PDEBUG(D_FRAM, "frame wait q:%d i:%d o:%d", | ||
1911 | gspca_dev->fr_q, | ||
1912 | gspca_dev->fr_i, | ||
1913 | gspca_dev->fr_o); | ||
1914 | 1796 | ||
1915 | if (gspca_dev->sd_desc->dq_callback) { | 1797 | if (gspca_dev->sd_desc->dq_callback) { |
1916 | mutex_lock(&gspca_dev->usb_lock); | 1798 | mutex_lock(&gspca_dev->usb_lock); |
@@ -1919,7 +1801,7 @@ static int frame_wait(struct gspca_dev *gspca_dev, | |||
1919 | gspca_dev->sd_desc->dq_callback(gspca_dev); | 1801 | gspca_dev->sd_desc->dq_callback(gspca_dev); |
1920 | mutex_unlock(&gspca_dev->usb_lock); | 1802 | mutex_unlock(&gspca_dev->usb_lock); |
1921 | } | 1803 | } |
1922 | return j; | 1804 | return gspca_dev->fr_queue[i]; |
1923 | } | 1805 | } |
1924 | 1806 | ||
1925 | /* | 1807 | /* |
@@ -2024,15 +1906,9 @@ static int vidioc_qbuf(struct file *file, void *priv, | |||
2024 | } | 1906 | } |
2025 | 1907 | ||
2026 | /* put the buffer in the 'queued' queue */ | 1908 | /* put the buffer in the 'queued' queue */ |
2027 | i = gspca_dev->fr_q; | 1909 | i = atomic_read(&gspca_dev->fr_q); |
2028 | gspca_dev->fr_queue[i] = index; | 1910 | gspca_dev->fr_queue[i] = index; |
2029 | if (gspca_dev->fr_i == i) | 1911 | atomic_set(&gspca_dev->fr_q, (i + 1) % GSPCA_MAX_FRAMES); |
2030 | gspca_dev->cur_frame = frame; | ||
2031 | gspca_dev->fr_q = (i + 1) % gspca_dev->nframes; | ||
2032 | PDEBUG(D_FRAM, "qbuf q:%d i:%d o:%d", | ||
2033 | gspca_dev->fr_q, | ||
2034 | gspca_dev->fr_i, | ||
2035 | gspca_dev->fr_o); | ||
2036 | 1912 | ||
2037 | v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED; | 1913 | v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED; |
2038 | v4l2_buf->flags &= ~V4L2_BUF_FLAG_DONE; | 1914 | v4l2_buf->flags &= ~V4L2_BUF_FLAG_DONE; |
@@ -2088,7 +1964,7 @@ static int read_alloc(struct gspca_dev *gspca_dev, | |||
2088 | static unsigned int dev_poll(struct file *file, poll_table *wait) | 1964 | static unsigned int dev_poll(struct file *file, poll_table *wait) |
2089 | { | 1965 | { |
2090 | struct gspca_dev *gspca_dev = file->private_data; | 1966 | struct gspca_dev *gspca_dev = file->private_data; |
2091 | int i, ret; | 1967 | int ret; |
2092 | 1968 | ||
2093 | PDEBUG(D_FRAM, "poll"); | 1969 | PDEBUG(D_FRAM, "poll"); |
2094 | 1970 | ||
@@ -2106,11 +1982,9 @@ static unsigned int dev_poll(struct file *file, poll_table *wait) | |||
2106 | if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0) | 1982 | if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0) |
2107 | return POLLERR; | 1983 | return POLLERR; |
2108 | 1984 | ||
2109 | /* check the next incoming buffer */ | 1985 | /* check if an image has been received */ |
2110 | i = gspca_dev->fr_o; | 1986 | if (gspca_dev->fr_o != atomic_read(&gspca_dev->fr_i)) |
2111 | i = gspca_dev->fr_queue[i]; | 1987 | ret = POLLIN | POLLRDNORM; /* yes */ |
2112 | if (gspca_dev->frame[i].v4l2_buf.flags & V4L2_BUF_FLAG_DONE) | ||
2113 | ret = POLLIN | POLLRDNORM; /* something to read */ | ||
2114 | else | 1988 | else |
2115 | ret = 0; | 1989 | ret = 0; |
2116 | mutex_unlock(&gspca_dev->queue_lock); | 1990 | mutex_unlock(&gspca_dev->queue_lock); |
@@ -2214,9 +2088,6 @@ static const struct v4l2_ioctl_ops dev_ioctl_ops = { | |||
2214 | .vidioc_queryctrl = vidioc_queryctrl, | 2088 | .vidioc_queryctrl = vidioc_queryctrl, |
2215 | .vidioc_g_ctrl = vidioc_g_ctrl, | 2089 | .vidioc_g_ctrl = vidioc_g_ctrl, |
2216 | .vidioc_s_ctrl = vidioc_s_ctrl, | 2090 | .vidioc_s_ctrl = vidioc_s_ctrl, |
2217 | .vidioc_g_audio = vidioc_g_audio, | ||
2218 | .vidioc_s_audio = vidioc_s_audio, | ||
2219 | .vidioc_enumaudio = vidioc_enumaudio, | ||
2220 | .vidioc_querymenu = vidioc_querymenu, | 2091 | .vidioc_querymenu = vidioc_querymenu, |
2221 | .vidioc_enum_input = vidioc_enum_input, | 2092 | .vidioc_enum_input = vidioc_enum_input, |
2222 | .vidioc_g_input = vidioc_g_input, | 2093 | .vidioc_g_input = vidioc_g_input, |
@@ -2235,9 +2106,6 @@ static const struct v4l2_ioctl_ops dev_ioctl_ops = { | |||
2235 | .vidioc_s_register = vidioc_s_register, | 2106 | .vidioc_s_register = vidioc_s_register, |
2236 | #endif | 2107 | #endif |
2237 | .vidioc_g_chip_ident = vidioc_g_chip_ident, | 2108 | .vidioc_g_chip_ident = vidioc_g_chip_ident, |
2238 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
2239 | .vidiocgmbuf = vidiocgmbuf, | ||
2240 | #endif | ||
2241 | }; | 2109 | }; |
2242 | 2110 | ||
2243 | static struct video_device gspca_template = { | 2111 | static struct video_device gspca_template = { |
@@ -2253,31 +2121,18 @@ static struct video_device gspca_template = { | |||
2253 | * This function must be called by the sub-driver when it is | 2121 | * This function must be called by the sub-driver when it is |
2254 | * called for probing a new device. | 2122 | * called for probing a new device. |
2255 | */ | 2123 | */ |
2256 | int gspca_dev_probe(struct usb_interface *intf, | 2124 | int gspca_dev_probe2(struct usb_interface *intf, |
2257 | const struct usb_device_id *id, | 2125 | const struct usb_device_id *id, |
2258 | const struct sd_desc *sd_desc, | 2126 | const struct sd_desc *sd_desc, |
2259 | int dev_size, | 2127 | int dev_size, |
2260 | struct module *module) | 2128 | struct module *module) |
2261 | { | 2129 | { |
2262 | struct usb_interface_descriptor *interface; | ||
2263 | struct gspca_dev *gspca_dev; | 2130 | struct gspca_dev *gspca_dev; |
2264 | struct usb_device *dev = interface_to_usbdev(intf); | 2131 | struct usb_device *dev = interface_to_usbdev(intf); |
2265 | int ret; | 2132 | int ret; |
2266 | 2133 | ||
2267 | PDEBUG(D_PROBE, "probing %04x:%04x", id->idVendor, id->idProduct); | 2134 | PDEBUG(D_PROBE, "probing %04x:%04x", id->idVendor, id->idProduct); |
2268 | 2135 | ||
2269 | /* we don't handle multi-config cameras */ | ||
2270 | if (dev->descriptor.bNumConfigurations != 1) { | ||
2271 | PDEBUG(D_ERR, "Too many config"); | ||
2272 | return -ENODEV; | ||
2273 | } | ||
2274 | |||
2275 | /* the USB video interface must be the first one */ | ||
2276 | interface = &intf->cur_altsetting->desc; | ||
2277 | if (dev->config->desc.bNumInterfaces != 1 && | ||
2278 | interface->bInterfaceNumber != 0) | ||
2279 | return -ENODEV; | ||
2280 | |||
2281 | /* create the device */ | 2136 | /* create the device */ |
2282 | if (dev_size < sizeof *gspca_dev) | 2137 | if (dev_size < sizeof *gspca_dev) |
2283 | dev_size = sizeof *gspca_dev; | 2138 | dev_size = sizeof *gspca_dev; |
@@ -2293,8 +2148,26 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
2293 | goto out; | 2148 | goto out; |
2294 | } | 2149 | } |
2295 | gspca_dev->dev = dev; | 2150 | gspca_dev->dev = dev; |
2296 | gspca_dev->iface = interface->bInterfaceNumber; | 2151 | gspca_dev->iface = intf->cur_altsetting->desc.bInterfaceNumber; |
2297 | gspca_dev->nbalt = intf->num_altsetting; | 2152 | gspca_dev->nbalt = intf->num_altsetting; |
2153 | |||
2154 | /* check if any audio device */ | ||
2155 | if (dev->config->desc.bNumInterfaces != 1) { | ||
2156 | int i; | ||
2157 | struct usb_interface *intf2; | ||
2158 | |||
2159 | for (i = 0; i < dev->config->desc.bNumInterfaces; i++) { | ||
2160 | intf2 = dev->config->interface[i]; | ||
2161 | if (intf2 != NULL | ||
2162 | && intf2->altsetting != NULL | ||
2163 | && intf2->altsetting->desc.bInterfaceClass == | ||
2164 | USB_CLASS_AUDIO) { | ||
2165 | gspca_dev->audio = 1; | ||
2166 | break; | ||
2167 | } | ||
2168 | } | ||
2169 | } | ||
2170 | |||
2298 | gspca_dev->sd_desc = sd_desc; | 2171 | gspca_dev->sd_desc = sd_desc; |
2299 | gspca_dev->nbufread = 2; | 2172 | gspca_dev->nbufread = 2; |
2300 | gspca_dev->empty_packet = -1; /* don't check the empty packets */ | 2173 | gspca_dev->empty_packet = -1; /* don't check the empty packets */ |
@@ -2345,6 +2218,31 @@ out: | |||
2345 | kfree(gspca_dev); | 2218 | kfree(gspca_dev); |
2346 | return ret; | 2219 | return ret; |
2347 | } | 2220 | } |
2221 | EXPORT_SYMBOL(gspca_dev_probe2); | ||
2222 | |||
2223 | /* same function as the previous one, but check the interface */ | ||
2224 | int gspca_dev_probe(struct usb_interface *intf, | ||
2225 | const struct usb_device_id *id, | ||
2226 | const struct sd_desc *sd_desc, | ||
2227 | int dev_size, | ||
2228 | struct module *module) | ||
2229 | { | ||
2230 | struct usb_device *dev = interface_to_usbdev(intf); | ||
2231 | |||
2232 | /* we don't handle multi-config cameras */ | ||
2233 | if (dev->descriptor.bNumConfigurations != 1) { | ||
2234 | PDEBUG(D_ERR, "%04x:%04x too many config", | ||
2235 | id->idVendor, id->idProduct); | ||
2236 | return -ENODEV; | ||
2237 | } | ||
2238 | |||
2239 | /* the USB video interface must be the first one */ | ||
2240 | if (dev->config->desc.bNumInterfaces != 1 | ||
2241 | && intf->cur_altsetting->desc.bInterfaceNumber != 0) | ||
2242 | return -ENODEV; | ||
2243 | |||
2244 | return gspca_dev_probe2(intf, id, sd_desc, dev_size, module); | ||
2245 | } | ||
2348 | EXPORT_SYMBOL(gspca_dev_probe); | 2246 | EXPORT_SYMBOL(gspca_dev_probe); |
2349 | 2247 | ||
2350 | /* | 2248 | /* |
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 8b963dfae861..b749c36d9f7e 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h | |||
@@ -7,7 +7,6 @@ | |||
7 | #include <linux/videodev2.h> | 7 | #include <linux/videodev2.h> |
8 | #include <media/v4l2-common.h> | 8 | #include <media/v4l2-common.h> |
9 | #include <linux/mutex.h> | 9 | #include <linux/mutex.h> |
10 | #include <linux/slab.h> | ||
11 | 10 | ||
12 | /* compilation option */ | 11 | /* compilation option */ |
13 | #define GSPCA_DEBUG 1 | 12 | #define GSPCA_DEBUG 1 |
@@ -148,7 +147,6 @@ enum gspca_packet_type { | |||
148 | 147 | ||
149 | struct gspca_frame { | 148 | struct gspca_frame { |
150 | __u8 *data; /* frame buffer */ | 149 | __u8 *data; /* frame buffer */ |
151 | __u8 *data_end; /* end of frame while filling */ | ||
152 | int vma_use_count; | 150 | int vma_use_count; |
153 | struct v4l2_buffer v4l2_buf; | 151 | struct v4l2_buffer v4l2_buf; |
154 | }; | 152 | }; |
@@ -177,13 +175,14 @@ struct gspca_dev { | |||
177 | 175 | ||
178 | __u8 *frbuf; /* buffer for nframes */ | 176 | __u8 *frbuf; /* buffer for nframes */ |
179 | struct gspca_frame frame[GSPCA_MAX_FRAMES]; | 177 | struct gspca_frame frame[GSPCA_MAX_FRAMES]; |
180 | struct gspca_frame *cur_frame; /* frame beeing filled */ | 178 | u8 *image; /* image beeing filled */ |
181 | __u32 frsz; /* frame size */ | 179 | __u32 frsz; /* frame size */ |
182 | char nframes; /* number of frames */ | 180 | u32 image_len; /* current length of image */ |
183 | char fr_i; /* frame being filled */ | 181 | atomic_t fr_q; /* next frame to queue */ |
184 | char fr_q; /* next frame to queue */ | 182 | atomic_t fr_i; /* frame being filled */ |
185 | char fr_o; /* next frame to dequeue */ | ||
186 | signed char fr_queue[GSPCA_MAX_FRAMES]; /* frame queue */ | 183 | signed char fr_queue[GSPCA_MAX_FRAMES]; /* frame queue */ |
184 | char nframes; /* number of frames */ | ||
185 | u8 fr_o; /* next frame to dequeue */ | ||
187 | __u8 last_packet_type; | 186 | __u8 last_packet_type; |
188 | __s8 empty_packet; /* if (-1) don't check empty packets */ | 187 | __s8 empty_packet; /* if (-1) don't check empty packets */ |
189 | __u8 streaming; | 188 | __u8 streaming; |
@@ -199,6 +198,7 @@ struct gspca_dev { | |||
199 | struct mutex read_lock; /* read protection */ | 198 | struct mutex read_lock; /* read protection */ |
200 | struct mutex queue_lock; /* ISOC queue protection */ | 199 | struct mutex queue_lock; /* ISOC queue protection */ |
201 | int usb_err; /* USB error - protected by usb_lock */ | 200 | int usb_err; /* USB error - protected by usb_lock */ |
201 | u16 pkt_size; /* ISOC packet size */ | ||
202 | #ifdef CONFIG_PM | 202 | #ifdef CONFIG_PM |
203 | char frozen; /* suspend - resume */ | 203 | char frozen; /* suspend - resume */ |
204 | #endif | 204 | #endif |
@@ -209,7 +209,7 @@ struct gspca_dev { | |||
209 | __u8 iface; /* USB interface number */ | 209 | __u8 iface; /* USB interface number */ |
210 | __u8 alt; /* USB alternate setting */ | 210 | __u8 alt; /* USB alternate setting */ |
211 | __u8 nbalt; /* number of USB alternate settings */ | 211 | __u8 nbalt; /* number of USB alternate settings */ |
212 | u16 pkt_size; /* ISOC packet size */ | 212 | u8 audio; /* presence of audio device */ |
213 | }; | 213 | }; |
214 | 214 | ||
215 | int gspca_dev_probe(struct usb_interface *intf, | 215 | int gspca_dev_probe(struct usb_interface *intf, |
@@ -217,12 +217,16 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
217 | const struct sd_desc *sd_desc, | 217 | const struct sd_desc *sd_desc, |
218 | int dev_size, | 218 | int dev_size, |
219 | struct module *module); | 219 | struct module *module); |
220 | int gspca_dev_probe2(struct usb_interface *intf, | ||
221 | const struct usb_device_id *id, | ||
222 | const struct sd_desc *sd_desc, | ||
223 | int dev_size, | ||
224 | struct module *module); | ||
220 | void gspca_disconnect(struct usb_interface *intf); | 225 | void gspca_disconnect(struct usb_interface *intf); |
221 | void gspca_frame_add(struct gspca_dev *gspca_dev, | 226 | void gspca_frame_add(struct gspca_dev *gspca_dev, |
222 | enum gspca_packet_type packet_type, | 227 | enum gspca_packet_type packet_type, |
223 | const u8 *data, | 228 | const u8 *data, |
224 | int len); | 229 | int len); |
225 | struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev); | ||
226 | #ifdef CONFIG_PM | 230 | #ifdef CONFIG_PM |
227 | int gspca_suspend(struct usb_interface *intf, pm_message_t message); | 231 | int gspca_suspend(struct usb_interface *intf, pm_message_t message); |
228 | int gspca_resume(struct usb_interface *intf); | 232 | int gspca_resume(struct usb_interface *intf); |
diff --git a/drivers/media/video/gspca/jeilinj.c b/drivers/media/video/gspca/jeilinj.c index 84ecd56c6470..12d9cf4caba2 100644 --- a/drivers/media/video/gspca/jeilinj.c +++ b/drivers/media/video/gspca/jeilinj.c | |||
@@ -50,7 +50,7 @@ struct sd { | |||
50 | struct workqueue_struct *work_thread; | 50 | struct workqueue_struct *work_thread; |
51 | u8 quality; /* image quality */ | 51 | u8 quality; /* image quality */ |
52 | u8 jpegqual; /* webcam quality */ | 52 | u8 jpegqual; /* webcam quality */ |
53 | u8 *jpeg_hdr; | 53 | u8 jpeg_hdr[JPEG_HDR_SZ]; |
54 | }; | 54 | }; |
55 | 55 | ||
56 | struct jlj_command { | 56 | struct jlj_command { |
@@ -282,7 +282,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
282 | destroy_workqueue(dev->work_thread); | 282 | destroy_workqueue(dev->work_thread); |
283 | dev->work_thread = NULL; | 283 | dev->work_thread = NULL; |
284 | mutex_lock(&gspca_dev->usb_lock); | 284 | mutex_lock(&gspca_dev->usb_lock); |
285 | kfree(dev->jpeg_hdr); | ||
286 | } | 285 | } |
287 | 286 | ||
288 | /* this function is called at probe and resume time */ | 287 | /* this function is called at probe and resume time */ |
@@ -298,9 +297,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
298 | int ret; | 297 | int ret; |
299 | 298 | ||
300 | /* create the JPEG header */ | 299 | /* create the JPEG header */ |
301 | dev->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); | ||
302 | if (dev->jpeg_hdr == NULL) | ||
303 | return -ENOMEM; | ||
304 | jpeg_define(dev->jpeg_hdr, gspca_dev->height, gspca_dev->width, | 300 | jpeg_define(dev->jpeg_hdr, gspca_dev->height, gspca_dev->width, |
305 | 0x21); /* JPEG 422 */ | 301 | 0x21); /* JPEG 422 */ |
306 | jpeg_set_qual(dev->jpeg_hdr, dev->quality); | 302 | jpeg_set_qual(dev->jpeg_hdr, dev->quality); |
diff --git a/drivers/media/video/gspca/m5602/m5602_bridge.h b/drivers/media/video/gspca/m5602/m5602_bridge.h index 1127a405c9b2..51af3ee3ab85 100644 --- a/drivers/media/video/gspca/m5602/m5602_bridge.h +++ b/drivers/media/video/gspca/m5602/m5602_bridge.h | |||
@@ -19,6 +19,7 @@ | |||
19 | #ifndef M5602_BRIDGE_H_ | 19 | #ifndef M5602_BRIDGE_H_ |
20 | #define M5602_BRIDGE_H_ | 20 | #define M5602_BRIDGE_H_ |
21 | 21 | ||
22 | #include <linux/slab.h> | ||
22 | #include "gspca.h" | 23 | #include "gspca.h" |
23 | 24 | ||
24 | #define MODULE_NAME "ALi m5602" | 25 | #define MODULE_NAME "ALi m5602" |
diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c index 4294c75e3b11..b073d66acd04 100644 --- a/drivers/media/video/gspca/m5602/m5602_core.c +++ b/drivers/media/video/gspca/m5602/m5602_core.c | |||
@@ -305,30 +305,23 @@ static void m5602_urb_complete(struct gspca_dev *gspca_dev, | |||
305 | sd->frame_count); | 305 | sd->frame_count); |
306 | 306 | ||
307 | } else { | 307 | } else { |
308 | struct gspca_frame *frame; | ||
309 | int cur_frame_len; | 308 | int cur_frame_len; |
310 | 309 | ||
311 | frame = gspca_get_i_frame(gspca_dev); | 310 | cur_frame_len = gspca_dev->image_len; |
312 | if (frame == NULL) { | ||
313 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
314 | return; | ||
315 | } | ||
316 | |||
317 | cur_frame_len = frame->data_end - frame->data; | ||
318 | /* Remove urb header */ | 311 | /* Remove urb header */ |
319 | data += 4; | 312 | data += 4; |
320 | len -= 4; | 313 | len -= 4; |
321 | 314 | ||
322 | if (cur_frame_len + len <= frame->v4l2_buf.length) { | 315 | if (cur_frame_len + len <= gspca_dev->frsz) { |
323 | PDEBUG(D_FRAM, "Continuing frame %d copying %d bytes", | 316 | PDEBUG(D_FRAM, "Continuing frame %d copying %d bytes", |
324 | sd->frame_count, len); | 317 | sd->frame_count, len); |
325 | 318 | ||
326 | gspca_frame_add(gspca_dev, INTER_PACKET, | 319 | gspca_frame_add(gspca_dev, INTER_PACKET, |
327 | data, len); | 320 | data, len); |
328 | } else if (frame->v4l2_buf.length - cur_frame_len > 0) { | 321 | } else { |
329 | /* Add the remaining data up to frame size */ | 322 | /* Add the remaining data up to frame size */ |
330 | gspca_frame_add(gspca_dev, INTER_PACKET, data, | 323 | gspca_frame_add(gspca_dev, INTER_PACKET, data, |
331 | frame->v4l2_buf.length - cur_frame_len); | 324 | gspca_dev->frsz - cur_frame_len); |
332 | } | 325 | } |
333 | } | 326 | } |
334 | } | 327 | } |
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/drivers/media/video/gspca/m5602/m5602_s5k83a.c index 6b3be4fa2c06..fbd91545497a 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.c | |||
@@ -17,7 +17,6 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/kthread.h> | 19 | #include <linux/kthread.h> |
20 | #include <linux/slab.h> | ||
21 | #include "m5602_s5k83a.h" | 20 | #include "m5602_s5k83a.h" |
22 | 21 | ||
23 | static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val); | 22 | static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val); |
diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index 3d9229e22b25..031f7195ce0d 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c | |||
@@ -41,7 +41,7 @@ struct sd { | |||
41 | #define QUALITY_MAX 70 | 41 | #define QUALITY_MAX 70 |
42 | #define QUALITY_DEF 50 | 42 | #define QUALITY_DEF 50 |
43 | 43 | ||
44 | u8 *jpeg_hdr; | 44 | u8 jpeg_hdr[JPEG_HDR_SZ]; |
45 | }; | 45 | }; |
46 | 46 | ||
47 | /* V4L2 controls supported by the driver */ | 47 | /* V4L2 controls supported by the driver */ |
@@ -200,9 +200,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
200 | int i; | 200 | int i; |
201 | 201 | ||
202 | /* create the JPEG header */ | 202 | /* create the JPEG header */ |
203 | sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); | ||
204 | if (!sd->jpeg_hdr) | ||
205 | return -ENOMEM; | ||
206 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, | 203 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, |
207 | 0x21); /* JPEG 422 */ | 204 | 0x21); /* JPEG 422 */ |
208 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | 205 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); |
@@ -317,13 +314,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
317 | PDEBUG(D_ERR, "Camera Stop failed"); | 314 | PDEBUG(D_ERR, "Camera Stop failed"); |
318 | } | 315 | } |
319 | 316 | ||
320 | static void sd_stop0(struct gspca_dev *gspca_dev) | ||
321 | { | ||
322 | struct sd *sd = (struct sd *) gspca_dev; | ||
323 | |||
324 | kfree(sd->jpeg_hdr); | ||
325 | } | ||
326 | |||
327 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 317 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
328 | u8 *data, /* isoc packet */ | 318 | u8 *data, /* isoc packet */ |
329 | int len) /* iso packet length */ | 319 | int len) /* iso packet length */ |
@@ -486,7 +476,6 @@ static const struct sd_desc sd_desc = { | |||
486 | .init = sd_init, | 476 | .init = sd_init, |
487 | .start = sd_start, | 477 | .start = sd_start, |
488 | .stopN = sd_stopN, | 478 | .stopN = sd_stopN, |
489 | .stop0 = sd_stop0, | ||
490 | .pkt_scan = sd_pkt_scan, | 479 | .pkt_scan = sd_pkt_scan, |
491 | .get_jcomp = sd_get_jcomp, | 480 | .get_jcomp = sd_get_jcomp, |
492 | .set_jcomp = sd_set_jcomp, | 481 | .set_jcomp = sd_set_jcomp, |
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index f36e11a0458d..2b2cbdbf03fe 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c | |||
@@ -41,6 +41,11 @@ | |||
41 | #include <linux/input.h> | 41 | #include <linux/input.h> |
42 | #include "gspca.h" | 42 | #include "gspca.h" |
43 | 43 | ||
44 | /* The jpeg_hdr is used by w996Xcf only */ | ||
45 | /* The CONEX_CAM define for jpeg.h needs renaming, now its used here too */ | ||
46 | #define CONEX_CAM | ||
47 | #include "jpeg.h" | ||
48 | |||
44 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | 49 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); |
45 | MODULE_DESCRIPTION("OV519 USB Camera Driver"); | 50 | MODULE_DESCRIPTION("OV519 USB Camera Driver"); |
46 | MODULE_LICENSE("GPL"); | 51 | MODULE_LICENSE("GPL"); |
@@ -90,6 +95,7 @@ struct sd { | |||
90 | #define QUALITY_DEF 50 | 95 | #define QUALITY_DEF 50 |
91 | 96 | ||
92 | __u8 stopped; /* Streaming is temporarily paused */ | 97 | __u8 stopped; /* Streaming is temporarily paused */ |
98 | __u8 first_frame; | ||
93 | 99 | ||
94 | __u8 frame_rate; /* current Framerate */ | 100 | __u8 frame_rate; /* current Framerate */ |
95 | __u8 clockdiv; /* clockdiv override */ | 101 | __u8 clockdiv; /* clockdiv override */ |
@@ -115,7 +121,7 @@ struct sd { | |||
115 | int sensor_height; | 121 | int sensor_height; |
116 | int sensor_reg_cache[256]; | 122 | int sensor_reg_cache[256]; |
117 | 123 | ||
118 | u8 *jpeg_hdr; | 124 | u8 jpeg_hdr[JPEG_HDR_SZ]; |
119 | }; | 125 | }; |
120 | 126 | ||
121 | /* Note this is a bit of a hack, but the w9968cf driver needs the code for all | 127 | /* Note this is a bit of a hack, but the w9968cf driver needs the code for all |
@@ -3147,7 +3153,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
3147 | sd->autobrightness = AUTOBRIGHT_DEF; | 3153 | sd->autobrightness = AUTOBRIGHT_DEF; |
3148 | if (sd->sensor == SEN_OV7670) { | 3154 | if (sd->sensor == SEN_OV7670) { |
3149 | sd->freq = OV7670_FREQ_DEF; | 3155 | sd->freq = OV7670_FREQ_DEF; |
3150 | gspca_dev->ctrl_dis = 1 << FREQ_IDX; | 3156 | gspca_dev->ctrl_dis = (1 << FREQ_IDX) | (1 << COLOR_IDX); |
3151 | } else { | 3157 | } else { |
3152 | sd->freq = FREQ_DEF; | 3158 | sd->freq = FREQ_DEF; |
3153 | gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | | 3159 | gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | |
@@ -3961,6 +3967,8 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
3961 | sd_reset_snapshot(gspca_dev); | 3967 | sd_reset_snapshot(gspca_dev); |
3962 | sd->snapshot_pressed = 0; | 3968 | sd->snapshot_pressed = 0; |
3963 | 3969 | ||
3970 | sd->first_frame = 3; | ||
3971 | |||
3964 | ret = ov51x_restart(sd); | 3972 | ret = ov51x_restart(sd); |
3965 | if (ret < 0) | 3973 | if (ret < 0) |
3966 | goto out; | 3974 | goto out; |
@@ -4153,13 +4161,23 @@ static void ovfx2_pkt_scan(struct gspca_dev *gspca_dev, | |||
4153 | u8 *data, /* isoc packet */ | 4161 | u8 *data, /* isoc packet */ |
4154 | int len) /* iso packet length */ | 4162 | int len) /* iso packet length */ |
4155 | { | 4163 | { |
4164 | struct sd *sd = (struct sd *) gspca_dev; | ||
4165 | |||
4166 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | ||
4167 | |||
4156 | /* A short read signals EOF */ | 4168 | /* A short read signals EOF */ |
4157 | if (len < OVFX2_BULK_SIZE) { | 4169 | if (len < OVFX2_BULK_SIZE) { |
4158 | gspca_frame_add(gspca_dev, LAST_PACKET, data, len); | 4170 | /* If the frame is short, and it is one of the first ones |
4171 | the sensor and bridge are still syncing, so drop it. */ | ||
4172 | if (sd->first_frame) { | ||
4173 | sd->first_frame--; | ||
4174 | if (gspca_dev->image_len < | ||
4175 | sd->gspca_dev.width * sd->gspca_dev.height) | ||
4176 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
4177 | } | ||
4178 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); | ||
4159 | gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); | 4179 | gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); |
4160 | return; | ||
4161 | } | 4180 | } |
4162 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | ||
4163 | } | 4181 | } |
4164 | 4182 | ||
4165 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 4183 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index dc1e4efe30fb..96cb3a976581 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c | |||
@@ -987,13 +987,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
987 | data + 12, len - 12); | 987 | data + 12, len - 12); |
988 | /* If this packet is marked as EOF, end the frame */ | 988 | /* If this packet is marked as EOF, end the frame */ |
989 | } else if (data[1] & UVC_STREAM_EOF) { | 989 | } else if (data[1] & UVC_STREAM_EOF) { |
990 | struct gspca_frame *frame; | ||
991 | |||
992 | sd->last_pts = 0; | 990 | sd->last_pts = 0; |
993 | frame = gspca_get_i_frame(gspca_dev); | 991 | if (gspca_dev->image_len + len - 12 != |
994 | if (frame == NULL) | ||
995 | goto discard; | ||
996 | if (frame->data_end - frame->data + (len - 12) != | ||
997 | gspca_dev->width * gspca_dev->height * 2) { | 992 | gspca_dev->width * gspca_dev->height * 2) { |
998 | PDEBUG(D_PACK, "wrong sized frame"); | 993 | PDEBUG(D_PACK, "wrong sized frame"); |
999 | goto discard; | 994 | goto discard; |
diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index 2a68220d1ada..a66df07d7625 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c | |||
@@ -402,7 +402,7 @@ static void reg_w_buf(struct gspca_dev *gspca_dev, | |||
402 | memcpy(gspca_dev->usb_buf, buffer, len); | 402 | memcpy(gspca_dev->usb_buf, buffer, len); |
403 | ret = usb_control_msg(gspca_dev->dev, | 403 | ret = usb_control_msg(gspca_dev->dev, |
404 | usb_sndctrlpipe(gspca_dev->dev, 0), | 404 | usb_sndctrlpipe(gspca_dev->dev, 0), |
405 | 1, /* request */ | 405 | 0, /* request */ |
406 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 406 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
407 | 0, /* value */ | 407 | 0, /* value */ |
408 | index, gspca_dev->usb_buf, len, | 408 | index, gspca_dev->usb_buf, len, |
@@ -804,7 +804,6 @@ static const unsigned char pac_jpeg_header2[] = { | |||
804 | }; | 804 | }; |
805 | 805 | ||
806 | static void pac_start_frame(struct gspca_dev *gspca_dev, | 806 | static void pac_start_frame(struct gspca_dev *gspca_dev, |
807 | struct gspca_frame *frame, | ||
808 | __u16 lines, __u16 samples_per_line) | 807 | __u16 lines, __u16 samples_per_line) |
809 | { | 808 | { |
810 | unsigned char tmpbuf[4]; | 809 | unsigned char tmpbuf[4]; |
@@ -829,19 +828,13 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
829 | int len) /* iso packet length */ | 828 | int len) /* iso packet length */ |
830 | { | 829 | { |
831 | struct sd *sd = (struct sd *) gspca_dev; | 830 | struct sd *sd = (struct sd *) gspca_dev; |
832 | struct gspca_frame *frame; | 831 | u8 *image; |
833 | unsigned char *sof; | 832 | unsigned char *sof; |
834 | 833 | ||
835 | sof = pac_find_sof(&sd->sof_read, data, len); | 834 | sof = pac_find_sof(&sd->sof_read, data, len); |
836 | if (sof) { | 835 | if (sof) { |
837 | int n, lum_offset, footer_length; | 836 | int n, lum_offset, footer_length; |
838 | 837 | ||
839 | frame = gspca_get_i_frame(gspca_dev); | ||
840 | if (frame == NULL) { | ||
841 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
842 | return; | ||
843 | } | ||
844 | |||
845 | /* 6 bytes after the FF D9 EOF marker a number of lumination | 838 | /* 6 bytes after the FF D9 EOF marker a number of lumination |
846 | bytes are send corresponding to different parts of the | 839 | bytes are send corresponding to different parts of the |
847 | image, the 14th and 15th byte after the EOF seem to | 840 | image, the 14th and 15th byte after the EOF seem to |
@@ -852,16 +845,17 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
852 | /* Finish decoding current frame */ | 845 | /* Finish decoding current frame */ |
853 | n = (sof - data) - (footer_length + sizeof pac_sof_marker); | 846 | n = (sof - data) - (footer_length + sizeof pac_sof_marker); |
854 | if (n < 0) { | 847 | if (n < 0) { |
855 | frame->data_end += n; | 848 | gspca_dev->image_len += n; |
856 | n = 0; | 849 | n = 0; |
850 | } else { | ||
851 | gspca_frame_add(gspca_dev, INTER_PACKET, data, n); | ||
857 | } | 852 | } |
858 | gspca_frame_add(gspca_dev, INTER_PACKET, | 853 | |
859 | data, n); | 854 | image = gspca_dev->image; |
860 | if (gspca_dev->last_packet_type != DISCARD_PACKET && | 855 | if (image != NULL |
861 | frame->data_end[-2] == 0xff && | 856 | && image[gspca_dev->image_len - 2] == 0xff |
862 | frame->data_end[-1] == 0xd9) | 857 | && image[gspca_dev->image_len - 1] == 0xd9) |
863 | gspca_frame_add(gspca_dev, LAST_PACKET, | 858 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); |
864 | NULL, 0); | ||
865 | 859 | ||
866 | n = sof - data; | 860 | n = sof - data; |
867 | len -= n; | 861 | len -= n; |
@@ -877,7 +871,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
877 | 871 | ||
878 | /* Start the new frame with the jpeg header */ | 872 | /* Start the new frame with the jpeg header */ |
879 | /* The PAC7302 has the image rotated 90 degrees */ | 873 | /* The PAC7302 has the image rotated 90 degrees */ |
880 | pac_start_frame(gspca_dev, frame, | 874 | pac_start_frame(gspca_dev, |
881 | gspca_dev->width, gspca_dev->height); | 875 | gspca_dev->width, gspca_dev->height); |
882 | } | 876 | } |
883 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | 877 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
@@ -1200,6 +1194,7 @@ static const struct usb_device_id device_table[] __devinitconst = { | |||
1200 | {USB_DEVICE(0x093a, 0x2621)}, | 1194 | {USB_DEVICE(0x093a, 0x2621)}, |
1201 | {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP}, | 1195 | {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP}, |
1202 | {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP}, | 1196 | {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP}, |
1197 | {USB_DEVICE(0x093a, 0x2625)}, | ||
1203 | {USB_DEVICE(0x093a, 0x2626)}, | 1198 | {USB_DEVICE(0x093a, 0x2626)}, |
1204 | {USB_DEVICE(0x093a, 0x2628)}, | 1199 | {USB_DEVICE(0x093a, 0x2628)}, |
1205 | {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP}, | 1200 | {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP}, |
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 44fed9686729..1cb7e99e92bd 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c | |||
@@ -270,7 +270,7 @@ static void reg_w_buf(struct gspca_dev *gspca_dev, | |||
270 | memcpy(gspca_dev->usb_buf, buffer, len); | 270 | memcpy(gspca_dev->usb_buf, buffer, len); |
271 | ret = usb_control_msg(gspca_dev->dev, | 271 | ret = usb_control_msg(gspca_dev->dev, |
272 | usb_sndctrlpipe(gspca_dev->dev, 0), | 272 | usb_sndctrlpipe(gspca_dev->dev, 0), |
273 | 1, /* request */ | 273 | 0, /* request */ |
274 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 274 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
275 | 0, /* value */ | 275 | 0, /* value */ |
276 | index, gspca_dev->usb_buf, len, | 276 | index, gspca_dev->usb_buf, len, |
@@ -599,7 +599,6 @@ static const unsigned char pac_jpeg_header2[] = { | |||
599 | }; | 599 | }; |
600 | 600 | ||
601 | static void pac_start_frame(struct gspca_dev *gspca_dev, | 601 | static void pac_start_frame(struct gspca_dev *gspca_dev, |
602 | struct gspca_frame *frame, | ||
603 | __u16 lines, __u16 samples_per_line) | 602 | __u16 lines, __u16 samples_per_line) |
604 | { | 603 | { |
605 | unsigned char tmpbuf[4]; | 604 | unsigned char tmpbuf[4]; |
@@ -624,19 +623,13 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
624 | int len) /* iso packet length */ | 623 | int len) /* iso packet length */ |
625 | { | 624 | { |
626 | struct sd *sd = (struct sd *) gspca_dev; | 625 | struct sd *sd = (struct sd *) gspca_dev; |
626 | u8 *image; | ||
627 | unsigned char *sof; | 627 | unsigned char *sof; |
628 | struct gspca_frame *frame; | ||
629 | 628 | ||
630 | sof = pac_find_sof(&sd->sof_read, data, len); | 629 | sof = pac_find_sof(&sd->sof_read, data, len); |
631 | if (sof) { | 630 | if (sof) { |
632 | int n, lum_offset, footer_length; | 631 | int n, lum_offset, footer_length; |
633 | 632 | ||
634 | frame = gspca_get_i_frame(gspca_dev); | ||
635 | if (frame == NULL) { | ||
636 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
637 | return; | ||
638 | } | ||
639 | |||
640 | /* 6 bytes after the FF D9 EOF marker a number of lumination | 633 | /* 6 bytes after the FF D9 EOF marker a number of lumination |
641 | bytes are send corresponding to different parts of the | 634 | bytes are send corresponding to different parts of the |
642 | image, the 14th and 15th byte after the EOF seem to | 635 | image, the 14th and 15th byte after the EOF seem to |
@@ -647,16 +640,16 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
647 | /* Finish decoding current frame */ | 640 | /* Finish decoding current frame */ |
648 | n = (sof - data) - (footer_length + sizeof pac_sof_marker); | 641 | n = (sof - data) - (footer_length + sizeof pac_sof_marker); |
649 | if (n < 0) { | 642 | if (n < 0) { |
650 | frame->data_end += n; | 643 | gspca_dev->image_len += n; |
651 | n = 0; | 644 | n = 0; |
645 | } else { | ||
646 | gspca_frame_add(gspca_dev, INTER_PACKET, data, n); | ||
652 | } | 647 | } |
653 | gspca_frame_add(gspca_dev, INTER_PACKET, | 648 | image = gspca_dev->image; |
654 | data, n); | 649 | if (image != NULL |
655 | if (gspca_dev->last_packet_type != DISCARD_PACKET && | 650 | && image[gspca_dev->image_len - 2] == 0xff |
656 | frame->data_end[-2] == 0xff && | 651 | && image[gspca_dev->image_len - 1] == 0xd9) |
657 | frame->data_end[-1] == 0xd9) | 652 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); |
658 | gspca_frame_add(gspca_dev, LAST_PACKET, | ||
659 | NULL, 0); | ||
660 | 653 | ||
661 | n = sof - data; | 654 | n = sof - data; |
662 | len -= n; | 655 | len -= n; |
@@ -671,7 +664,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
671 | atomic_set(&sd->avg_lum, -1); | 664 | atomic_set(&sd->avg_lum, -1); |
672 | 665 | ||
673 | /* Start the new frame with the jpeg header */ | 666 | /* Start the new frame with the jpeg header */ |
674 | pac_start_frame(gspca_dev, frame, | 667 | pac_start_frame(gspca_dev, |
675 | gspca_dev->height, gspca_dev->width); | 668 | gspca_dev->height, gspca_dev->width); |
676 | } | 669 | } |
677 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | 670 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 644a7fd4701a..83a718f0f3f9 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c | |||
@@ -20,7 +20,6 @@ | |||
20 | 20 | ||
21 | #ifdef CONFIG_INPUT | 21 | #ifdef CONFIG_INPUT |
22 | #include <linux/input.h> | 22 | #include <linux/input.h> |
23 | #include <linux/slab.h> | ||
24 | #endif | 23 | #endif |
25 | 24 | ||
26 | #include "gspca.h" | 25 | #include "gspca.h" |
@@ -89,7 +88,7 @@ struct sd { | |||
89 | u8 hstart; | 88 | u8 hstart; |
90 | u8 vstart; | 89 | u8 vstart; |
91 | 90 | ||
92 | u8 *jpeg_hdr; | 91 | u8 jpeg_hdr[JPEG_HDR_SZ]; |
93 | u8 quality; | 92 | u8 quality; |
94 | 93 | ||
95 | u8 flags; | 94 | u8 flags; |
@@ -2162,10 +2161,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2162 | int height = gspca_dev->height; | 2161 | int height = gspca_dev->height; |
2163 | u8 fmt, scale = 0; | 2162 | u8 fmt, scale = 0; |
2164 | 2163 | ||
2165 | sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); | ||
2166 | if (sd->jpeg_hdr == NULL) | ||
2167 | return -ENOMEM; | ||
2168 | |||
2169 | jpeg_define(sd->jpeg_hdr, height, width, | 2164 | jpeg_define(sd->jpeg_hdr, height, width, |
2170 | 0x21); | 2165 | 0x21); |
2171 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | 2166 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); |
@@ -2197,8 +2192,8 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2197 | } | 2192 | } |
2198 | 2193 | ||
2199 | configure_sensor_output(gspca_dev, mode); | 2194 | configure_sensor_output(gspca_dev, mode); |
2200 | reg_w(gspca_dev, 0x1100, sd->jpeg_hdr + JPEG_QT0_OFFSET, 64); | 2195 | reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64); |
2201 | reg_w(gspca_dev, 0x1140, sd->jpeg_hdr + JPEG_QT1_OFFSET, 64); | 2196 | reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64); |
2202 | reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5); | 2197 | reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5); |
2203 | reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6); | 2198 | reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6); |
2204 | reg_w1(gspca_dev, 0x1189, scale); | 2199 | reg_w1(gspca_dev, 0x1189, scale); |
@@ -2226,12 +2221,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
2226 | reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02); | 2221 | reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02); |
2227 | } | 2222 | } |
2228 | 2223 | ||
2229 | static void sd_stop0(struct gspca_dev *gspca_dev) | ||
2230 | { | ||
2231 | struct sd *sd = (struct sd *) gspca_dev; | ||
2232 | kfree(sd->jpeg_hdr); | ||
2233 | } | ||
2234 | |||
2235 | static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum) | 2224 | static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum) |
2236 | { | 2225 | { |
2237 | struct sd *sd = (struct sd *) gspca_dev; | 2226 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -2397,7 +2386,6 @@ static const struct sd_desc sd_desc = { | |||
2397 | .init = sd_init, | 2386 | .init = sd_init, |
2398 | .start = sd_start, | 2387 | .start = sd_start, |
2399 | .stopN = sd_stopN, | 2388 | .stopN = sd_stopN, |
2400 | .stop0 = sd_stop0, | ||
2401 | .pkt_scan = sd_pkt_scan, | 2389 | .pkt_scan = sd_pkt_scan, |
2402 | #ifdef CONFIG_INPUT | 2390 | #ifdef CONFIG_INPUT |
2403 | .int_pkt_scan = sd_int_pkt_scan, | 2391 | .int_pkt_scan = sd_int_pkt_scan, |
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 95354a339e3d..204bb3af4559 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c | |||
@@ -1251,16 +1251,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1251 | if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) { | 1251 | if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) { |
1252 | /* In raw mode we sometimes get some garbage after the frame | 1252 | /* In raw mode we sometimes get some garbage after the frame |
1253 | ignore this */ | 1253 | ignore this */ |
1254 | struct gspca_frame *frame; | ||
1255 | int used; | 1254 | int used; |
1256 | int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage; | 1255 | int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage; |
1257 | 1256 | ||
1258 | frame = gspca_get_i_frame(gspca_dev); | 1257 | used = gspca_dev->image_len; |
1259 | if (frame == NULL) { | ||
1260 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
1261 | return; | ||
1262 | } | ||
1263 | used = frame->data_end - frame->data; | ||
1264 | if (used + len > size) | 1258 | if (used + len > size) |
1265 | len = size - used; | 1259 | len = size - used; |
1266 | } | 1260 | } |
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 176c5b3d5e6f..ee17b034bf6b 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #define MODULE_NAME "sonixj" | 22 | #define MODULE_NAME "sonixj" |
23 | 23 | ||
24 | #include <linux/input.h> | 24 | #include <linux/input.h> |
25 | #include <linux/slab.h> | ||
26 | #include "gspca.h" | 25 | #include "gspca.h" |
27 | #include "jpeg.h" | 26 | #include "jpeg.h" |
28 | 27 | ||
@@ -392,7 +391,7 @@ static const u8 sn_gc0307[0x1c] = { | |||
392 | 391 | ||
393 | static const u8 sn_hv7131[0x1c] = { | 392 | static const u8 sn_hv7131[0x1c] = { |
394 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ | 393 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ |
395 | 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20, | 394 | 0x00, 0x03, 0x60, 0x00, 0x1a, 0x20, 0x20, 0x20, |
396 | /* reg8 reg9 rega regb regc regd rege regf */ | 395 | /* reg8 reg9 rega regb regc regd rege regf */ |
397 | 0x81, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 396 | 0x81, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
398 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ | 397 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ |
@@ -403,7 +402,7 @@ static const u8 sn_hv7131[0x1c] = { | |||
403 | 402 | ||
404 | static const u8 sn_mi0360[0x1c] = { | 403 | static const u8 sn_mi0360[0x1c] = { |
405 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ | 404 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ |
406 | 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, | 405 | 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20, |
407 | /* reg8 reg9 rega regb regc regd rege regf */ | 406 | /* reg8 reg9 rega regb regc regd rege regf */ |
408 | 0x81, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 407 | 0x81, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
409 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ | 408 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ |
@@ -1644,6 +1643,7 @@ static void bridge_init(struct gspca_dev *gspca_dev, | |||
1644 | const u8 *sn9c1xx) | 1643 | const u8 *sn9c1xx) |
1645 | { | 1644 | { |
1646 | struct sd *sd = (struct sd *) gspca_dev; | 1645 | struct sd *sd = (struct sd *) gspca_dev; |
1646 | u8 reg0102[2]; | ||
1647 | const u8 *reg9a; | 1647 | const u8 *reg9a; |
1648 | static const u8 reg9a_def[] = | 1648 | static const u8 reg9a_def[] = |
1649 | {0x00, 0x40, 0x20, 0x00, 0x00, 0x00}; | 1649 | {0x00, 0x40, 0x20, 0x00, 0x00, 0x00}; |
@@ -1656,7 +1656,11 @@ static void bridge_init(struct gspca_dev *gspca_dev, | |||
1656 | reg_w1(gspca_dev, 0x01, sn9c1xx[1]); | 1656 | reg_w1(gspca_dev, 0x01, sn9c1xx[1]); |
1657 | 1657 | ||
1658 | /* configure gpio */ | 1658 | /* configure gpio */ |
1659 | reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2); | 1659 | reg0102[0] = sn9c1xx[1]; |
1660 | reg0102[1] = sn9c1xx[2]; | ||
1661 | if (gspca_dev->audio) | ||
1662 | reg0102[1] |= 0x04; /* keep the audio connection */ | ||
1663 | reg_w(gspca_dev, 0x01, reg0102, 2); | ||
1660 | reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2); | 1664 | reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2); |
1661 | reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); | 1665 | reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); |
1662 | switch (sd->sensor) { | 1666 | switch (sd->sensor) { |
@@ -1737,13 +1741,12 @@ static void bridge_init(struct gspca_dev *gspca_dev, | |||
1737 | reg_w1(gspca_dev, 0x01, 0x40); | 1741 | reg_w1(gspca_dev, 0x01, 0x40); |
1738 | break; | 1742 | break; |
1739 | case SENSOR_PO2030N: | 1743 | case SENSOR_PO2030N: |
1744 | case SENSOR_OV7660: | ||
1740 | reg_w1(gspca_dev, 0x01, 0x63); | 1745 | reg_w1(gspca_dev, 0x01, 0x63); |
1741 | reg_w1(gspca_dev, 0x17, 0x20); | 1746 | reg_w1(gspca_dev, 0x17, 0x20); |
1742 | reg_w1(gspca_dev, 0x01, 0x62); | 1747 | reg_w1(gspca_dev, 0x01, 0x62); |
1743 | reg_w1(gspca_dev, 0x01, 0x42); | 1748 | reg_w1(gspca_dev, 0x01, 0x42); |
1744 | break; | 1749 | break; |
1745 | case SENSOR_OV7660: | ||
1746 | /* fall thru */ | ||
1747 | case SENSOR_SP80708: | 1750 | case SENSOR_SP80708: |
1748 | reg_w1(gspca_dev, 0x01, 0x63); | 1751 | reg_w1(gspca_dev, 0x01, 0x63); |
1749 | reg_w1(gspca_dev, 0x17, 0x20); | 1752 | reg_w1(gspca_dev, 0x17, 0x20); |
@@ -1816,7 +1819,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1816 | { | 1819 | { |
1817 | struct sd *sd = (struct sd *) gspca_dev; | 1820 | struct sd *sd = (struct sd *) gspca_dev; |
1818 | const u8 *sn9c1xx; | 1821 | const u8 *sn9c1xx; |
1819 | u8 regGpio[] = { 0x29, 0x74 }; | 1822 | u8 regGpio[] = { 0x29, 0x74 }; /* with audio */ |
1820 | u8 regF1; | 1823 | u8 regF1; |
1821 | 1824 | ||
1822 | /* setup a selector by bridge */ | 1825 | /* setup a selector by bridge */ |
@@ -1856,7 +1859,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1856 | po2030n_probe(gspca_dev); | 1859 | po2030n_probe(gspca_dev); |
1857 | break; | 1860 | break; |
1858 | } | 1861 | } |
1859 | regGpio[1] = 0x70; | 1862 | regGpio[1] = 0x70; /* no audio */ |
1860 | reg_w(gspca_dev, 0x01, regGpio, 2); | 1863 | reg_w(gspca_dev, 0x01, regGpio, 2); |
1861 | break; | 1864 | break; |
1862 | default: | 1865 | default: |
@@ -2274,7 +2277,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2274 | { | 2277 | { |
2275 | struct sd *sd = (struct sd *) gspca_dev; | 2278 | struct sd *sd = (struct sd *) gspca_dev; |
2276 | int i; | 2279 | int i; |
2277 | u8 reg1, reg2, reg17; | 2280 | u8 reg1, reg17; |
2278 | const u8 *sn9c1xx; | 2281 | const u8 *sn9c1xx; |
2279 | const u8 (*init)[8]; | 2282 | const u8 (*init)[8]; |
2280 | int mode; | 2283 | int mode; |
@@ -2304,23 +2307,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2304 | /* initialize the sensor */ | 2307 | /* initialize the sensor */ |
2305 | i2c_w_seq(gspca_dev, sensor_init[sd->sensor]); | 2308 | i2c_w_seq(gspca_dev, sensor_init[sd->sensor]); |
2306 | 2309 | ||
2307 | switch (sd->sensor) { | ||
2308 | case SENSOR_ADCM1700: | ||
2309 | reg2 = 0x60; | ||
2310 | break; | ||
2311 | case SENSOR_OM6802: | ||
2312 | reg2 = 0x71; | ||
2313 | break; | ||
2314 | case SENSOR_SP80708: | ||
2315 | reg2 = 0x62; | ||
2316 | break; | ||
2317 | default: | ||
2318 | reg2 = 0x40; | ||
2319 | break; | ||
2320 | } | ||
2321 | reg_w1(gspca_dev, 0x02, reg2); | ||
2322 | reg_w1(gspca_dev, 0x02, reg2); | ||
2323 | |||
2324 | reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]); | 2310 | reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]); |
2325 | reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]); | 2311 | reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]); |
2326 | reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]); | 2312 | reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]); |
diff --git a/drivers/media/video/gspca/spca1528.c b/drivers/media/video/gspca/spca1528.c new file mode 100644 index 000000000000..3f514eb1d99d --- /dev/null +++ b/drivers/media/video/gspca/spca1528.c | |||
@@ -0,0 +1,605 @@ | |||
1 | /* | ||
2 | * spca1528 subdriver | ||
3 | * | ||
4 | * Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #define MODULE_NAME "spca1528" | ||
22 | |||
23 | #include "gspca.h" | ||
24 | #include "jpeg.h" | ||
25 | |||
26 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | ||
27 | MODULE_DESCRIPTION("SPCA1528 USB Camera Driver"); | ||
28 | MODULE_LICENSE("GPL"); | ||
29 | |||
30 | /* specific webcam descriptor */ | ||
31 | struct sd { | ||
32 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
33 | |||
34 | u8 brightness; | ||
35 | u8 contrast; | ||
36 | u8 hue; | ||
37 | u8 color; | ||
38 | u8 sharpness; | ||
39 | |||
40 | u8 pkt_seq; | ||
41 | |||
42 | u8 jpeg_hdr[JPEG_HDR_SZ]; | ||
43 | }; | ||
44 | |||
45 | /* V4L2 controls supported by the driver */ | ||
46 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
47 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
48 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
49 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
50 | static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val); | ||
51 | static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val); | ||
52 | static int sd_setcolor(struct gspca_dev *gspca_dev, __s32 val); | ||
53 | static int sd_getcolor(struct gspca_dev *gspca_dev, __s32 *val); | ||
54 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | ||
55 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | ||
56 | |||
57 | static const struct ctrl sd_ctrls[] = { | ||
58 | { | ||
59 | { | ||
60 | .id = V4L2_CID_BRIGHTNESS, | ||
61 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
62 | .name = "Brightness", | ||
63 | .minimum = 0, | ||
64 | .maximum = 255, | ||
65 | .step = 1, | ||
66 | #define BRIGHTNESS_DEF 128 | ||
67 | .default_value = BRIGHTNESS_DEF, | ||
68 | }, | ||
69 | .set = sd_setbrightness, | ||
70 | .get = sd_getbrightness, | ||
71 | }, | ||
72 | { | ||
73 | { | ||
74 | .id = V4L2_CID_CONTRAST, | ||
75 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
76 | .name = "Contrast", | ||
77 | .minimum = 0, | ||
78 | .maximum = 8, | ||
79 | .step = 1, | ||
80 | #define CONTRAST_DEF 1 | ||
81 | .default_value = CONTRAST_DEF, | ||
82 | }, | ||
83 | .set = sd_setcontrast, | ||
84 | .get = sd_getcontrast, | ||
85 | }, | ||
86 | { | ||
87 | { | ||
88 | .id = V4L2_CID_HUE, | ||
89 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
90 | .name = "Hue", | ||
91 | .minimum = 0, | ||
92 | .maximum = 255, | ||
93 | .step = 1, | ||
94 | #define HUE_DEF 0 | ||
95 | .default_value = HUE_DEF, | ||
96 | }, | ||
97 | .set = sd_sethue, | ||
98 | .get = sd_gethue, | ||
99 | }, | ||
100 | { | ||
101 | { | ||
102 | .id = V4L2_CID_SATURATION, | ||
103 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
104 | .name = "Saturation", | ||
105 | .minimum = 0, | ||
106 | .maximum = 8, | ||
107 | .step = 1, | ||
108 | #define COLOR_DEF 1 | ||
109 | .default_value = COLOR_DEF, | ||
110 | }, | ||
111 | .set = sd_setcolor, | ||
112 | .get = sd_getcolor, | ||
113 | }, | ||
114 | { | ||
115 | { | ||
116 | .id = V4L2_CID_SHARPNESS, | ||
117 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
118 | .name = "Sharpness", | ||
119 | .minimum = 0, | ||
120 | .maximum = 255, | ||
121 | .step = 1, | ||
122 | #define SHARPNESS_DEF 0 | ||
123 | .default_value = SHARPNESS_DEF, | ||
124 | }, | ||
125 | .set = sd_setsharpness, | ||
126 | .get = sd_getsharpness, | ||
127 | }, | ||
128 | }; | ||
129 | |||
130 | static const struct v4l2_pix_format vga_mode[] = { | ||
131 | /* (does not work correctly) | ||
132 | {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
133 | .bytesperline = 176, | ||
134 | .sizeimage = 176 * 144 * 5 / 8 + 590, | ||
135 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
136 | .priv = 3}, | ||
137 | */ | ||
138 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
139 | .bytesperline = 320, | ||
140 | .sizeimage = 320 * 240 * 4 / 8 + 590, | ||
141 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
142 | .priv = 2}, | ||
143 | {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
144 | .bytesperline = 640, | ||
145 | .sizeimage = 640 * 480 * 3 / 8 + 590, | ||
146 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
147 | .priv = 1}, | ||
148 | }; | ||
149 | |||
150 | /* read <len> bytes to gspca usb_buf */ | ||
151 | static void reg_r(struct gspca_dev *gspca_dev, | ||
152 | u8 req, | ||
153 | u16 index, | ||
154 | int len) | ||
155 | { | ||
156 | #if USB_BUF_SZ < 64 | ||
157 | #error "USB buffer too small" | ||
158 | #endif | ||
159 | struct usb_device *dev = gspca_dev->dev; | ||
160 | int ret; | ||
161 | |||
162 | if (gspca_dev->usb_err < 0) | ||
163 | return; | ||
164 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
165 | req, | ||
166 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
167 | 0x0000, /* value */ | ||
168 | index, | ||
169 | gspca_dev->usb_buf, len, | ||
170 | 500); | ||
171 | PDEBUG(D_USBI, "GET %02x 0000 %04x %02x", req, index, | ||
172 | gspca_dev->usb_buf[0]); | ||
173 | if (ret < 0) { | ||
174 | PDEBUG(D_ERR, "reg_r err %d", ret); | ||
175 | gspca_dev->usb_err = ret; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | static void reg_w(struct gspca_dev *gspca_dev, | ||
180 | u8 req, | ||
181 | u16 value, | ||
182 | u16 index) | ||
183 | { | ||
184 | struct usb_device *dev = gspca_dev->dev; | ||
185 | int ret; | ||
186 | |||
187 | if (gspca_dev->usb_err < 0) | ||
188 | return; | ||
189 | PDEBUG(D_USBO, "SET %02x %04x %04x", req, value, index); | ||
190 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
191 | req, | ||
192 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
193 | value, index, | ||
194 | NULL, 0, 500); | ||
195 | if (ret < 0) { | ||
196 | PDEBUG(D_ERR, "reg_w err %d", ret); | ||
197 | gspca_dev->usb_err = ret; | ||
198 | } | ||
199 | } | ||
200 | |||
201 | static void reg_wb(struct gspca_dev *gspca_dev, | ||
202 | u8 req, | ||
203 | u16 value, | ||
204 | u16 index, | ||
205 | u8 byte) | ||
206 | { | ||
207 | struct usb_device *dev = gspca_dev->dev; | ||
208 | int ret; | ||
209 | |||
210 | if (gspca_dev->usb_err < 0) | ||
211 | return; | ||
212 | PDEBUG(D_USBO, "SET %02x %04x %04x %02x", req, value, index, byte); | ||
213 | gspca_dev->usb_buf[0] = byte; | ||
214 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
215 | req, | ||
216 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
217 | value, index, | ||
218 | gspca_dev->usb_buf, 1, 500); | ||
219 | if (ret < 0) { | ||
220 | PDEBUG(D_ERR, "reg_w err %d", ret); | ||
221 | gspca_dev->usb_err = ret; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | static void wait_status_0(struct gspca_dev *gspca_dev) | ||
226 | { | ||
227 | int i; | ||
228 | |||
229 | i = 20; | ||
230 | do { | ||
231 | reg_r(gspca_dev, 0x21, 0x0000, 1); | ||
232 | if (gspca_dev->usb_buf[0] == 0) | ||
233 | return; | ||
234 | msleep(30); | ||
235 | } while (--i > 0); | ||
236 | PDEBUG(D_ERR, "wait_status_0 timeout"); | ||
237 | gspca_dev->usb_err = -ETIME; | ||
238 | } | ||
239 | |||
240 | static void wait_status_1(struct gspca_dev *gspca_dev) | ||
241 | { | ||
242 | int i; | ||
243 | |||
244 | i = 10; | ||
245 | do { | ||
246 | reg_r(gspca_dev, 0x21, 0x0001, 1); | ||
247 | msleep(10); | ||
248 | if (gspca_dev->usb_buf[0] == 1) { | ||
249 | reg_wb(gspca_dev, 0x21, 0x0000, 0x0001, 0x00); | ||
250 | reg_r(gspca_dev, 0x21, 0x0001, 1); | ||
251 | return; | ||
252 | } | ||
253 | } while (--i > 0); | ||
254 | PDEBUG(D_ERR, "wait_status_1 timeout"); | ||
255 | gspca_dev->usb_err = -ETIME; | ||
256 | } | ||
257 | |||
258 | static void setbrightness(struct gspca_dev *gspca_dev) | ||
259 | { | ||
260 | struct sd *sd = (struct sd *) gspca_dev; | ||
261 | |||
262 | reg_wb(gspca_dev, 0xc0, 0x0000, 0x00c0, sd->brightness); | ||
263 | } | ||
264 | |||
265 | static void setcontrast(struct gspca_dev *gspca_dev) | ||
266 | { | ||
267 | struct sd *sd = (struct sd *) gspca_dev; | ||
268 | |||
269 | reg_wb(gspca_dev, 0xc1, 0x0000, 0x00c1, sd->contrast); | ||
270 | } | ||
271 | |||
272 | static void sethue(struct gspca_dev *gspca_dev) | ||
273 | { | ||
274 | struct sd *sd = (struct sd *) gspca_dev; | ||
275 | |||
276 | reg_wb(gspca_dev, 0xc2, 0x0000, 0x0000, sd->hue); | ||
277 | } | ||
278 | |||
279 | static void setcolor(struct gspca_dev *gspca_dev) | ||
280 | { | ||
281 | struct sd *sd = (struct sd *) gspca_dev; | ||
282 | |||
283 | reg_wb(gspca_dev, 0xc3, 0x0000, 0x00c3, sd->color); | ||
284 | } | ||
285 | |||
286 | static void setsharpness(struct gspca_dev *gspca_dev) | ||
287 | { | ||
288 | struct sd *sd = (struct sd *) gspca_dev; | ||
289 | |||
290 | reg_wb(gspca_dev, 0xc4, 0x0000, 0x00c4, sd->sharpness); | ||
291 | } | ||
292 | |||
293 | /* this function is called at probe time */ | ||
294 | static int sd_config(struct gspca_dev *gspca_dev, | ||
295 | const struct usb_device_id *id) | ||
296 | { | ||
297 | struct sd *sd = (struct sd *) gspca_dev; | ||
298 | |||
299 | gspca_dev->cam.cam_mode = vga_mode; | ||
300 | gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); | ||
301 | gspca_dev->cam.npkt = 128; /* number of packets per ISOC message */ | ||
302 | /*fixme: 256 in ms-win traces*/ | ||
303 | |||
304 | sd->brightness = BRIGHTNESS_DEF; | ||
305 | sd->contrast = CONTRAST_DEF; | ||
306 | sd->hue = HUE_DEF; | ||
307 | sd->color = COLOR_DEF; | ||
308 | sd->sharpness = SHARPNESS_DEF; | ||
309 | |||
310 | gspca_dev->nbalt = 4; /* use alternate setting 3 */ | ||
311 | |||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | /* this function is called at probe and resume time */ | ||
316 | static int sd_init(struct gspca_dev *gspca_dev) | ||
317 | { | ||
318 | reg_w(gspca_dev, 0x00, 0x0001, 0x2067); | ||
319 | reg_w(gspca_dev, 0x00, 0x00d0, 0x206b); | ||
320 | reg_w(gspca_dev, 0x00, 0x0000, 0x206c); | ||
321 | reg_w(gspca_dev, 0x00, 0x0001, 0x2069); | ||
322 | msleep(8); | ||
323 | reg_w(gspca_dev, 0x00, 0x00c0, 0x206b); | ||
324 | reg_w(gspca_dev, 0x00, 0x0000, 0x206c); | ||
325 | reg_w(gspca_dev, 0x00, 0x0001, 0x2069); | ||
326 | |||
327 | reg_r(gspca_dev, 0x20, 0x0000, 1); | ||
328 | reg_r(gspca_dev, 0x20, 0x0000, 5); | ||
329 | reg_r(gspca_dev, 0x23, 0x0000, 64); | ||
330 | PDEBUG(D_PROBE, "%s%s", &gspca_dev->usb_buf[0x1c], | ||
331 | &gspca_dev->usb_buf[0x30]); | ||
332 | reg_r(gspca_dev, 0x23, 0x0001, 64); | ||
333 | return gspca_dev->usb_err; | ||
334 | } | ||
335 | |||
336 | /* function called at start time before URB creation */ | ||
337 | static int sd_isoc_init(struct gspca_dev *gspca_dev) | ||
338 | { | ||
339 | u8 mode; | ||
340 | |||
341 | reg_r(gspca_dev, 0x00, 0x2520, 1); | ||
342 | wait_status_0(gspca_dev); | ||
343 | reg_w(gspca_dev, 0xc5, 0x0003, 0x0000); | ||
344 | wait_status_1(gspca_dev); | ||
345 | |||
346 | wait_status_0(gspca_dev); | ||
347 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; | ||
348 | reg_wb(gspca_dev, 0x25, 0x0000, 0x0004, mode); | ||
349 | reg_r(gspca_dev, 0x25, 0x0004, 1); | ||
350 | reg_wb(gspca_dev, 0x27, 0x0000, 0x0000, 0x06); | ||
351 | reg_r(gspca_dev, 0x27, 0x0000, 1); | ||
352 | return gspca_dev->usb_err; | ||
353 | } | ||
354 | |||
355 | /* -- start the camera -- */ | ||
356 | static int sd_start(struct gspca_dev *gspca_dev) | ||
357 | { | ||
358 | struct sd *sd = (struct sd *) gspca_dev; | ||
359 | |||
360 | /* initialize the JPEG header */ | ||
361 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, | ||
362 | 0x22); /* JPEG 411 */ | ||
363 | |||
364 | /* the JPEG quality seems to be 82% */ | ||
365 | jpeg_set_qual(sd->jpeg_hdr, 82); | ||
366 | |||
367 | /* set the controls */ | ||
368 | setbrightness(gspca_dev); | ||
369 | setcontrast(gspca_dev); | ||
370 | sethue(gspca_dev); | ||
371 | setcolor(gspca_dev); | ||
372 | setsharpness(gspca_dev); | ||
373 | |||
374 | msleep(5); | ||
375 | reg_r(gspca_dev, 0x00, 0x2520, 1); | ||
376 | msleep(8); | ||
377 | |||
378 | /* start the capture */ | ||
379 | wait_status_0(gspca_dev); | ||
380 | reg_w(gspca_dev, 0x31, 0x0000, 0x0004); | ||
381 | wait_status_1(gspca_dev); | ||
382 | wait_status_0(gspca_dev); | ||
383 | msleep(200); | ||
384 | |||
385 | sd->pkt_seq = 0; | ||
386 | return gspca_dev->usb_err; | ||
387 | } | ||
388 | |||
389 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
390 | { | ||
391 | /* stop the capture */ | ||
392 | wait_status_0(gspca_dev); | ||
393 | reg_w(gspca_dev, 0x31, 0x0000, 0x0000); | ||
394 | wait_status_1(gspca_dev); | ||
395 | wait_status_0(gspca_dev); | ||
396 | } | ||
397 | |||
398 | /* move a packet adding 0x00 after 0xff */ | ||
399 | static void add_packet(struct gspca_dev *gspca_dev, | ||
400 | u8 *data, | ||
401 | int len) | ||
402 | { | ||
403 | int i; | ||
404 | |||
405 | i = 0; | ||
406 | do { | ||
407 | if (data[i] == 0xff) { | ||
408 | gspca_frame_add(gspca_dev, INTER_PACKET, | ||
409 | data, i + 1); | ||
410 | len -= i; | ||
411 | data += i; | ||
412 | *data = 0x00; | ||
413 | i = 0; | ||
414 | } | ||
415 | } while (++i < len); | ||
416 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | ||
417 | } | ||
418 | |||
419 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
420 | u8 *data, /* isoc packet */ | ||
421 | int len) /* iso packet length */ | ||
422 | { | ||
423 | struct sd *sd = (struct sd *) gspca_dev; | ||
424 | static const u8 ffd9[] = {0xff, 0xd9}; | ||
425 | |||
426 | /* image packets start with: | ||
427 | * 02 8n | ||
428 | * with <n> bit: | ||
429 | * 0x01: even (0) / odd (1) image | ||
430 | * 0x02: end of image when set | ||
431 | */ | ||
432 | if (len < 3) | ||
433 | return; /* empty packet */ | ||
434 | if (*data == 0x02) { | ||
435 | if (data[1] & 0x02) { | ||
436 | sd->pkt_seq = !(data[1] & 1); | ||
437 | add_packet(gspca_dev, data + 2, len - 2); | ||
438 | gspca_frame_add(gspca_dev, LAST_PACKET, | ||
439 | ffd9, 2); | ||
440 | return; | ||
441 | } | ||
442 | if ((data[1] & 1) != sd->pkt_seq) | ||
443 | goto err; | ||
444 | if (gspca_dev->last_packet_type == LAST_PACKET) | ||
445 | gspca_frame_add(gspca_dev, FIRST_PACKET, | ||
446 | sd->jpeg_hdr, JPEG_HDR_SZ); | ||
447 | add_packet(gspca_dev, data + 2, len - 2); | ||
448 | return; | ||
449 | } | ||
450 | err: | ||
451 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
452 | } | ||
453 | |||
454 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | ||
455 | { | ||
456 | struct sd *sd = (struct sd *) gspca_dev; | ||
457 | |||
458 | sd->brightness = val; | ||
459 | if (gspca_dev->streaming) | ||
460 | setbrightness(gspca_dev); | ||
461 | return gspca_dev->usb_err; | ||
462 | } | ||
463 | |||
464 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
465 | { | ||
466 | struct sd *sd = (struct sd *) gspca_dev; | ||
467 | |||
468 | *val = sd->brightness; | ||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | ||
473 | { | ||
474 | struct sd *sd = (struct sd *) gspca_dev; | ||
475 | |||
476 | sd->contrast = val; | ||
477 | if (gspca_dev->streaming) | ||
478 | setcontrast(gspca_dev); | ||
479 | return gspca_dev->usb_err; | ||
480 | } | ||
481 | |||
482 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | ||
483 | { | ||
484 | struct sd *sd = (struct sd *) gspca_dev; | ||
485 | |||
486 | *val = sd->contrast; | ||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val) | ||
491 | { | ||
492 | struct sd *sd = (struct sd *) gspca_dev; | ||
493 | |||
494 | sd->hue = val; | ||
495 | if (gspca_dev->streaming) | ||
496 | sethue(gspca_dev); | ||
497 | return gspca_dev->usb_err; | ||
498 | } | ||
499 | |||
500 | static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val) | ||
501 | { | ||
502 | struct sd *sd = (struct sd *) gspca_dev; | ||
503 | |||
504 | *val = sd->hue; | ||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | static int sd_setcolor(struct gspca_dev *gspca_dev, __s32 val) | ||
509 | { | ||
510 | struct sd *sd = (struct sd *) gspca_dev; | ||
511 | |||
512 | sd->color = val; | ||
513 | if (gspca_dev->streaming) | ||
514 | setcolor(gspca_dev); | ||
515 | return gspca_dev->usb_err; | ||
516 | } | ||
517 | |||
518 | static int sd_getcolor(struct gspca_dev *gspca_dev, __s32 *val) | ||
519 | { | ||
520 | struct sd *sd = (struct sd *) gspca_dev; | ||
521 | |||
522 | *val = sd->color; | ||
523 | return 0; | ||
524 | } | ||
525 | |||
526 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) | ||
527 | { | ||
528 | struct sd *sd = (struct sd *) gspca_dev; | ||
529 | |||
530 | sd->sharpness = val; | ||
531 | if (gspca_dev->streaming) | ||
532 | setsharpness(gspca_dev); | ||
533 | return gspca_dev->usb_err; | ||
534 | } | ||
535 | |||
536 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val) | ||
537 | { | ||
538 | struct sd *sd = (struct sd *) gspca_dev; | ||
539 | |||
540 | *val = sd->sharpness; | ||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | /* sub-driver description */ | ||
545 | static const struct sd_desc sd_desc = { | ||
546 | .name = MODULE_NAME, | ||
547 | .ctrls = sd_ctrls, | ||
548 | .nctrls = ARRAY_SIZE(sd_ctrls), | ||
549 | .config = sd_config, | ||
550 | .init = sd_init, | ||
551 | .isoc_init = sd_isoc_init, | ||
552 | .start = sd_start, | ||
553 | .stopN = sd_stopN, | ||
554 | .pkt_scan = sd_pkt_scan, | ||
555 | }; | ||
556 | |||
557 | /* -- module initialisation -- */ | ||
558 | static const __devinitdata struct usb_device_id device_table[] = { | ||
559 | {USB_DEVICE(0x04fc, 0x1528)}, | ||
560 | {} | ||
561 | }; | ||
562 | MODULE_DEVICE_TABLE(usb, device_table); | ||
563 | |||
564 | /* -- device connect -- */ | ||
565 | static int sd_probe(struct usb_interface *intf, | ||
566 | const struct usb_device_id *id) | ||
567 | { | ||
568 | /* the video interface for isochronous transfer is 1 */ | ||
569 | if (intf->cur_altsetting->desc.bInterfaceNumber != 1) | ||
570 | return -ENODEV; | ||
571 | |||
572 | return gspca_dev_probe2(intf, id, &sd_desc, sizeof(struct sd), | ||
573 | THIS_MODULE); | ||
574 | } | ||
575 | |||
576 | static struct usb_driver sd_driver = { | ||
577 | .name = MODULE_NAME, | ||
578 | .id_table = device_table, | ||
579 | .probe = sd_probe, | ||
580 | .disconnect = gspca_disconnect, | ||
581 | #ifdef CONFIG_PM | ||
582 | .suspend = gspca_suspend, | ||
583 | .resume = gspca_resume, | ||
584 | #endif | ||
585 | }; | ||
586 | |||
587 | /* -- module insert / remove -- */ | ||
588 | static int __init sd_mod_init(void) | ||
589 | { | ||
590 | int ret; | ||
591 | |||
592 | ret = usb_register(&sd_driver); | ||
593 | if (ret < 0) | ||
594 | return ret; | ||
595 | info("registered"); | ||
596 | return 0; | ||
597 | } | ||
598 | static void __exit sd_mod_exit(void) | ||
599 | { | ||
600 | usb_deregister(&sd_driver); | ||
601 | info("deregistered"); | ||
602 | } | ||
603 | |||
604 | module_init(sd_mod_init); | ||
605 | module_exit(sd_mod_exit); | ||
diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c index b866c73c97db..c02beb6c1e93 100644 --- a/drivers/media/video/gspca/spca500.c +++ b/drivers/media/video/gspca/spca500.c | |||
@@ -57,7 +57,7 @@ struct sd { | |||
57 | #define PalmPixDC85 13 | 57 | #define PalmPixDC85 13 |
58 | #define ToptroIndus 14 | 58 | #define ToptroIndus 14 |
59 | 59 | ||
60 | u8 *jpeg_hdr; | 60 | u8 jpeg_hdr[JPEG_HDR_SZ]; |
61 | }; | 61 | }; |
62 | 62 | ||
63 | /* V4L2 controls supported by the driver */ | 63 | /* V4L2 controls supported by the driver */ |
@@ -669,9 +669,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
669 | __u8 xmult, ymult; | 669 | __u8 xmult, ymult; |
670 | 670 | ||
671 | /* create the JPEG header */ | 671 | /* create the JPEG header */ |
672 | sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); | ||
673 | if (!sd->jpeg_hdr) | ||
674 | return -ENOMEM; | ||
675 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, | 672 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, |
676 | 0x22); /* JPEG 411 */ | 673 | 0x22); /* JPEG 411 */ |
677 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | 674 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); |
@@ -891,13 +888,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
891 | gspca_dev->usb_buf[0]); | 888 | gspca_dev->usb_buf[0]); |
892 | } | 889 | } |
893 | 890 | ||
894 | static void sd_stop0(struct gspca_dev *gspca_dev) | ||
895 | { | ||
896 | struct sd *sd = (struct sd *) gspca_dev; | ||
897 | |||
898 | kfree(sd->jpeg_hdr); | ||
899 | } | ||
900 | |||
901 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 891 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
902 | u8 *data, /* isoc packet */ | 892 | u8 *data, /* isoc packet */ |
903 | int len) /* iso packet length */ | 893 | int len) /* iso packet length */ |
@@ -1055,7 +1045,6 @@ static const struct sd_desc sd_desc = { | |||
1055 | .init = sd_init, | 1045 | .init = sd_init, |
1056 | .start = sd_start, | 1046 | .start = sd_start, |
1057 | .stopN = sd_stopN, | 1047 | .stopN = sd_stopN, |
1058 | .stop0 = sd_stop0, | ||
1059 | .pkt_scan = sd_pkt_scan, | 1048 | .pkt_scan = sd_pkt_scan, |
1060 | .get_jcomp = sd_get_jcomp, | 1049 | .get_jcomp = sd_get_jcomp, |
1061 | .set_jcomp = sd_set_jcomp, | 1050 | .set_jcomp = sd_set_jcomp, |
diff --git a/drivers/media/video/gspca/sq930x.c b/drivers/media/video/gspca/sq930x.c new file mode 100644 index 000000000000..37cee5e063cf --- /dev/null +++ b/drivers/media/video/gspca/sq930x.c | |||
@@ -0,0 +1,1402 @@ | |||
1 | /* | ||
2 | * SQ930x subdriver | ||
3 | * | ||
4 | * Copyright (C) 2010 Jean-François Moine <http://moinejf.free.fr> | ||
5 | * Copyright (C) 2006 -2008 Gerard Klaver <gerard at gkall dot hobby dot nl> | ||
6 | * Copyright (C) 2007 Sam Revitch <samr7@cs.washington.edu> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #define MODULE_NAME "sq930x" | ||
24 | |||
25 | #include "gspca.h" | ||
26 | #include "jpeg.h" | ||
27 | |||
28 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>\n" | ||
29 | "Gerard Klaver <gerard at gkall dot hobby dot nl\n" | ||
30 | "Sam Revitch <samr7@cs.washington.edu>"); | ||
31 | MODULE_DESCRIPTION("GSPCA/SQ930x USB Camera Driver"); | ||
32 | MODULE_LICENSE("GPL"); | ||
33 | |||
34 | #define BULK_TRANSFER_LEN 5128 | ||
35 | |||
36 | /* Structure to hold all of our device specific stuff */ | ||
37 | struct sd { | ||
38 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
39 | |||
40 | u16 expo; | ||
41 | u8 gain; | ||
42 | |||
43 | u8 quality; /* webcam quality 0..3 */ | ||
44 | #define QUALITY_DEF 1 | ||
45 | |||
46 | u8 gpio[2]; | ||
47 | |||
48 | u8 eof_len; | ||
49 | u8 do_ctrl; | ||
50 | |||
51 | u8 sensor; | ||
52 | enum { | ||
53 | SENSOR_ICX098BQ, | ||
54 | SENSOR_LZ24BP, | ||
55 | SENSOR_MI0360, | ||
56 | SENSOR_MT9V111, | ||
57 | SENSOR_OV7660, | ||
58 | SENSOR_OV9630, | ||
59 | } sensors; | ||
60 | u8 type; | ||
61 | #define Generic 0 | ||
62 | #define Creative_live_motion 1 | ||
63 | |||
64 | u8 jpeg_hdr[JPEG_HDR_SZ]; | ||
65 | }; | ||
66 | |||
67 | static int sd_setexpo(struct gspca_dev *gspca_dev, __s32 val); | ||
68 | static int sd_getexpo(struct gspca_dev *gspca_dev, __s32 *val); | ||
69 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | ||
70 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | ||
71 | |||
72 | static const struct ctrl sd_ctrls[] = { | ||
73 | { | ||
74 | { | ||
75 | .id = V4L2_CID_EXPOSURE, | ||
76 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
77 | .name = "Exposure", | ||
78 | .minimum = 0x0001, | ||
79 | .maximum = 0x0fff, | ||
80 | .step = 1, | ||
81 | #define EXPO_DEF 0x027d | ||
82 | .default_value = EXPO_DEF, | ||
83 | }, | ||
84 | .set = sd_setexpo, | ||
85 | .get = sd_getexpo, | ||
86 | }, | ||
87 | { | ||
88 | { | ||
89 | .id = V4L2_CID_GAIN, | ||
90 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
91 | .name = "Gain", | ||
92 | .minimum = 0x01, | ||
93 | .maximum = 0xff, | ||
94 | .step = 1, | ||
95 | #define GAIN_DEF 0x61 | ||
96 | .default_value = GAIN_DEF, | ||
97 | }, | ||
98 | .set = sd_setgain, | ||
99 | .get = sd_getgain, | ||
100 | }, | ||
101 | }; | ||
102 | |||
103 | static struct v4l2_pix_format vga_mode[] = { | ||
104 | {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
105 | .bytesperline = 160, | ||
106 | .sizeimage = 160 * 120 * 5 / 8 + 590, | ||
107 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
108 | .priv = 0}, | ||
109 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
110 | .bytesperline = 320, | ||
111 | .sizeimage = 320 * 240 * 4 / 8 + 590, | ||
112 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
113 | .priv = 1}, | ||
114 | {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
115 | .bytesperline = 640, | ||
116 | .sizeimage = 640 * 480 * 3 / 8 + 590, | ||
117 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
118 | .priv = 2}, | ||
119 | }; | ||
120 | |||
121 | /* JPEG quality indexed by webcam quality */ | ||
122 | #define QUAL_0 90 | ||
123 | #define QUAL_1 85 | ||
124 | #define QUAL_2 75 | ||
125 | #define QUAL_3 70 | ||
126 | static const u8 quality_tb[4] = { QUAL_0, QUAL_1, QUAL_2, QUAL_3 }; | ||
127 | |||
128 | /* sq930x registers */ | ||
129 | #define SQ930_CTRL_UCBUS_IO 0x0001 | ||
130 | #define SQ930_CTRL_I2C_IO 0x0002 | ||
131 | #define SQ930_CTRL_GPIO 0x0005 | ||
132 | #define SQ930_CTRL_CAP_START 0x0010 | ||
133 | #define SQ930_CTRL_CAP_STOP 0x0011 | ||
134 | #define SQ930_CTRL_SET_EXPOSURE 0x001d | ||
135 | #define SQ930_CTRL_RESET 0x001e | ||
136 | #define SQ930_CTRL_GET_DEV_INFO 0x001f | ||
137 | |||
138 | /* gpio 1 (8..15) */ | ||
139 | #define SQ930_GPIO_DFL_I2C_SDA 0x0001 | ||
140 | #define SQ930_GPIO_DFL_I2C_SCL 0x0002 | ||
141 | #define SQ930_GPIO_RSTBAR 0x0004 | ||
142 | #define SQ930_GPIO_EXTRA1 0x0040 | ||
143 | #define SQ930_GPIO_EXTRA2 0x0080 | ||
144 | /* gpio 3 (24..31) */ | ||
145 | #define SQ930_GPIO_POWER 0x0200 | ||
146 | #define SQ930_GPIO_DFL_LED 0x1000 | ||
147 | |||
148 | struct ucbus_write_cmd { | ||
149 | u16 bw_addr; | ||
150 | u8 bw_data; | ||
151 | }; | ||
152 | struct i2c_write_cmd { | ||
153 | u8 reg; | ||
154 | u16 val; | ||
155 | }; | ||
156 | |||
157 | static const struct ucbus_write_cmd icx098bq_start_0[] = { | ||
158 | {0x0354, 0x00}, {0x03fa, 0x00}, {0xf800, 0x02}, {0xf801, 0xce}, | ||
159 | {0xf802, 0xc1}, {0xf804, 0x00}, {0xf808, 0x00}, {0xf809, 0x0e}, | ||
160 | {0xf80a, 0x01}, {0xf80b, 0xee}, {0xf807, 0x60}, {0xf80c, 0x02}, | ||
161 | {0xf80d, 0xf0}, {0xf80e, 0x03}, {0xf80f, 0x0a}, {0xf81c, 0x02}, | ||
162 | {0xf81d, 0xf0}, {0xf81e, 0x03}, {0xf81f, 0x0a}, {0xf83a, 0x00}, | ||
163 | {0xf83b, 0x10}, {0xf83c, 0x00}, {0xf83d, 0x4e}, {0xf810, 0x04}, | ||
164 | {0xf811, 0x00}, {0xf812, 0x02}, {0xf813, 0x10}, {0xf803, 0x00}, | ||
165 | {0xf814, 0x01}, {0xf815, 0x18}, {0xf816, 0x00}, {0xf817, 0x48}, | ||
166 | {0xf818, 0x00}, {0xf819, 0x25}, {0xf81a, 0x00}, {0xf81b, 0x3c}, | ||
167 | {0xf82f, 0x03}, {0xf820, 0xff}, {0xf821, 0x0d}, {0xf822, 0xff}, | ||
168 | {0xf823, 0x07}, {0xf824, 0xff}, {0xf825, 0x03}, {0xf826, 0xff}, | ||
169 | {0xf827, 0x06}, {0xf828, 0xff}, {0xf829, 0x03}, {0xf82a, 0xff}, | ||
170 | {0xf82b, 0x0c}, {0xf82c, 0xfd}, {0xf82d, 0x01}, {0xf82e, 0x00}, | ||
171 | {0xf830, 0x00}, {0xf831, 0x47}, {0xf832, 0x00}, {0xf833, 0x00}, | ||
172 | {0xf850, 0x00}, {0xf851, 0x00}, {0xf852, 0x00}, {0xf853, 0x24}, | ||
173 | {0xf854, 0x00}, {0xf855, 0x18}, {0xf856, 0x00}, {0xf857, 0x3c}, | ||
174 | {0xf858, 0x00}, {0xf859, 0x0c}, {0xf85a, 0x00}, {0xf85b, 0x30}, | ||
175 | {0xf85c, 0x00}, {0xf85d, 0x0c}, {0xf85e, 0x00}, {0xf85f, 0x30}, | ||
176 | {0xf860, 0x00}, {0xf861, 0x48}, {0xf862, 0x01}, {0xf863, 0xdc}, | ||
177 | {0xf864, 0xff}, {0xf865, 0x98}, {0xf866, 0xff}, {0xf867, 0xc0}, | ||
178 | {0xf868, 0xff}, {0xf869, 0x70}, {0xf86c, 0xff}, {0xf86d, 0x00}, | ||
179 | {0xf86a, 0xff}, {0xf86b, 0x48}, {0xf86e, 0xff}, {0xf86f, 0x00}, | ||
180 | {0xf870, 0x01}, {0xf871, 0xdb}, {0xf872, 0x01}, {0xf873, 0xfa}, | ||
181 | {0xf874, 0x01}, {0xf875, 0xdb}, {0xf876, 0x01}, {0xf877, 0xfa}, | ||
182 | {0xf878, 0x0f}, {0xf879, 0x0f}, {0xf87a, 0xff}, {0xf87b, 0xff}, | ||
183 | {0xf800, 0x03} | ||
184 | }; | ||
185 | static const struct ucbus_write_cmd icx098bq_start_1[] = { | ||
186 | {0xf5f0, 0x00}, {0xf5f1, 0xcd}, {0xf5f2, 0x80}, {0xf5f3, 0x80}, | ||
187 | {0xf5f4, 0xc0}, | ||
188 | {0xf5f0, 0x49}, {0xf5f1, 0xcd}, {0xf5f2, 0x80}, {0xf5f3, 0x80}, | ||
189 | {0xf5f4, 0xc0}, | ||
190 | {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00}, | ||
191 | {0xf5f9, 0x00} | ||
192 | }; | ||
193 | |||
194 | static const struct ucbus_write_cmd icx098bq_start_2[] = { | ||
195 | {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x82}, {0xf806, 0x00}, | ||
196 | {0xf807, 0x7f}, {0xf800, 0x03}, | ||
197 | {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x40}, {0xf806, 0x00}, | ||
198 | {0xf807, 0x7f}, {0xf800, 0x03}, | ||
199 | {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0xcf}, {0xf806, 0xd0}, | ||
200 | {0xf807, 0x7f}, {0xf800, 0x03}, | ||
201 | {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x00}, {0xf806, 0x00}, | ||
202 | {0xf807, 0x7f}, {0xf800, 0x03} | ||
203 | }; | ||
204 | |||
205 | static const struct ucbus_write_cmd lz24bp_start_0[] = { | ||
206 | {0x0354, 0x00}, {0x03fa, 0x00}, {0xf800, 0x02}, {0xf801, 0xbe}, | ||
207 | {0xf802, 0xc6}, {0xf804, 0x00}, {0xf808, 0x00}, {0xf809, 0x06}, | ||
208 | {0xf80a, 0x01}, {0xf80b, 0xfe}, {0xf807, 0x84}, {0xf80c, 0x02}, | ||
209 | {0xf80d, 0xf7}, {0xf80e, 0x03}, {0xf80f, 0x0b}, {0xf81c, 0x00}, | ||
210 | {0xf81d, 0x49}, {0xf81e, 0x03}, {0xf81f, 0x0b}, {0xf83a, 0x00}, | ||
211 | {0xf83b, 0x01}, {0xf83c, 0x00}, {0xf83d, 0x6b}, {0xf810, 0x03}, | ||
212 | {0xf811, 0x10}, {0xf812, 0x02}, {0xf813, 0x6f}, {0xf803, 0x00}, | ||
213 | {0xf814, 0x00}, {0xf815, 0x44}, {0xf816, 0x00}, {0xf817, 0x48}, | ||
214 | {0xf818, 0x00}, {0xf819, 0x25}, {0xf81a, 0x00}, {0xf81b, 0x3c}, | ||
215 | {0xf82f, 0x03}, {0xf820, 0xff}, {0xf821, 0x0d}, {0xf822, 0xff}, | ||
216 | {0xf823, 0x07}, {0xf824, 0xfd}, {0xf825, 0x07}, {0xf826, 0xf0}, | ||
217 | {0xf827, 0x0c}, {0xf828, 0xff}, {0xf829, 0x03}, {0xf82a, 0xff}, | ||
218 | {0xf82b, 0x0c}, {0xf82c, 0xfc}, {0xf82d, 0x01}, {0xf82e, 0x00}, | ||
219 | {0xf830, 0x00}, {0xf831, 0x47}, {0xf832, 0x00}, {0xf833, 0x00}, | ||
220 | {0xf850, 0x00}, {0xf851, 0x00}, {0xf852, 0x00}, {0xf853, 0x24}, | ||
221 | {0xf854, 0x00}, {0xf855, 0x0c}, {0xf856, 0x00}, {0xf857, 0x30}, | ||
222 | {0xf858, 0x00}, {0xf859, 0x18}, {0xf85a, 0x00}, {0xf85b, 0x3c}, | ||
223 | {0xf85c, 0x00}, {0xf85d, 0x18}, {0xf85e, 0x00}, {0xf85f, 0x3c}, | ||
224 | {0xf860, 0xff}, {0xf861, 0x37}, {0xf862, 0xff}, {0xf863, 0x1d}, | ||
225 | {0xf864, 0xff}, {0xf865, 0x98}, {0xf866, 0xff}, {0xf867, 0xc0}, | ||
226 | {0xf868, 0x00}, {0xf869, 0x37}, {0xf86c, 0x02}, {0xf86d, 0x1d}, | ||
227 | {0xf86a, 0x00}, {0xf86b, 0x37}, {0xf86e, 0x02}, {0xf86f, 0x1d}, | ||
228 | {0xf870, 0x01}, {0xf871, 0xc6}, {0xf872, 0x02}, {0xf873, 0x04}, | ||
229 | {0xf874, 0x01}, {0xf875, 0xc6}, {0xf876, 0x02}, {0xf877, 0x04}, | ||
230 | {0xf878, 0x0f}, {0xf879, 0x0f}, {0xf87a, 0xff}, {0xf87b, 0xff}, | ||
231 | {0xf800, 0x03} | ||
232 | }; | ||
233 | static const struct ucbus_write_cmd lz24bp_start_1_gen[] = { | ||
234 | {0xf5f0, 0x00}, {0xf5f1, 0xff}, {0xf5f2, 0x80}, {0xf5f3, 0x80}, | ||
235 | {0xf5f4, 0xb3}, | ||
236 | {0xf5f0, 0x40}, {0xf5f1, 0xff}, {0xf5f2, 0x80}, {0xf5f3, 0x80}, | ||
237 | {0xf5f4, 0xb3}, | ||
238 | {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00}, | ||
239 | {0xf5f9, 0x00} | ||
240 | }; | ||
241 | |||
242 | static const struct ucbus_write_cmd lz24bp_start_1_clm[] = { | ||
243 | {0xf5f0, 0x00}, {0xf5f1, 0xff}, {0xf5f2, 0x88}, {0xf5f3, 0x88}, | ||
244 | {0xf5f4, 0xc0}, | ||
245 | {0xf5f0, 0x40}, {0xf5f1, 0xff}, {0xf5f2, 0x88}, {0xf5f3, 0x88}, | ||
246 | {0xf5f4, 0xc0}, | ||
247 | {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00}, | ||
248 | {0xf5f9, 0x00} | ||
249 | }; | ||
250 | |||
251 | static const struct ucbus_write_cmd lz24bp_start_2[] = { | ||
252 | {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x80}, {0xf806, 0x00}, | ||
253 | {0xf807, 0x7f}, {0xf800, 0x03}, | ||
254 | {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x4e}, {0xf806, 0x00}, | ||
255 | {0xf807, 0x7f}, {0xf800, 0x03}, | ||
256 | {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0xc0}, {0xf806, 0x48}, | ||
257 | {0xf807, 0x7f}, {0xf800, 0x03}, | ||
258 | {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x00}, {0xf806, 0x00}, | ||
259 | {0xf807, 0x7f}, {0xf800, 0x03} | ||
260 | }; | ||
261 | |||
262 | static const struct ucbus_write_cmd mi0360_start_0[] = { | ||
263 | {0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0xcc}, {0xf333, 0xcc}, | ||
264 | {0xf334, 0xcc}, {0xf335, 0xcc}, {0xf33f, 0x00} | ||
265 | }; | ||
266 | static const struct i2c_write_cmd mi0360_init_23[] = { | ||
267 | {0x30, 0x0040}, /* reserved - def 0x0005 */ | ||
268 | {0x31, 0x0000}, /* reserved - def 0x002a */ | ||
269 | {0x34, 0x0100}, /* reserved - def 0x0100 */ | ||
270 | {0x3d, 0x068f}, /* reserved - def 0x068f */ | ||
271 | }; | ||
272 | static const struct i2c_write_cmd mi0360_init_24[] = { | ||
273 | {0x03, 0x01e5}, /* window height */ | ||
274 | {0x04, 0x0285}, /* window width */ | ||
275 | }; | ||
276 | static const struct i2c_write_cmd mi0360_init_25[] = { | ||
277 | {0x35, 0x0020}, /* global gain */ | ||
278 | {0x2b, 0x0020}, /* green1 gain */ | ||
279 | {0x2c, 0x002a}, /* blue gain */ | ||
280 | {0x2d, 0x0028}, /* red gain */ | ||
281 | {0x2e, 0x0020}, /* green2 gain */ | ||
282 | }; | ||
283 | static const struct ucbus_write_cmd mi0360_start_1[] = { | ||
284 | {0xf5f0, 0x11}, {0xf5f1, 0x99}, {0xf5f2, 0x80}, {0xf5f3, 0x80}, | ||
285 | {0xf5f4, 0xa6}, | ||
286 | {0xf5f0, 0x51}, {0xf5f1, 0x99}, {0xf5f2, 0x80}, {0xf5f3, 0x80}, | ||
287 | {0xf5f4, 0xa6}, | ||
288 | {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00}, | ||
289 | {0xf5f9, 0x00} | ||
290 | }; | ||
291 | static const struct i2c_write_cmd mi0360_start_2[] = { | ||
292 | {0x62, 0x041d}, /* reserved - def 0x0418 */ | ||
293 | }; | ||
294 | static const struct i2c_write_cmd mi0360_start_3[] = { | ||
295 | {0x05, 0x007b}, /* horiz blanking */ | ||
296 | }; | ||
297 | static const struct i2c_write_cmd mi0360_start_4[] = { | ||
298 | {0x05, 0x03f5}, /* horiz blanking */ | ||
299 | }; | ||
300 | |||
301 | static const struct i2c_write_cmd mt9v111_init_0[] = { | ||
302 | {0x01, 0x0001}, /* select IFP/SOC registers */ | ||
303 | {0x06, 0x300c}, /* operating mode control */ | ||
304 | {0x08, 0xcc00}, /* output format control (RGB) */ | ||
305 | {0x01, 0x0004}, /* select core registers */ | ||
306 | }; | ||
307 | static const struct i2c_write_cmd mt9v111_init_1[] = { | ||
308 | {0x03, 0x01e5}, /* window height */ | ||
309 | {0x04, 0x0285}, /* window width */ | ||
310 | }; | ||
311 | static const struct i2c_write_cmd mt9v111_init_2[] = { | ||
312 | {0x30, 0x7800}, | ||
313 | {0x31, 0x0000}, | ||
314 | {0x07, 0x3002}, /* output control */ | ||
315 | {0x35, 0x0020}, /* global gain */ | ||
316 | {0x2b, 0x0020}, /* green1 gain */ | ||
317 | {0x2c, 0x0020}, /* blue gain */ | ||
318 | {0x2d, 0x0020}, /* red gain */ | ||
319 | {0x2e, 0x0020}, /* green2 gain */ | ||
320 | }; | ||
321 | static const struct ucbus_write_cmd mt9v111_start_1[] = { | ||
322 | {0xf5f0, 0x11}, {0xf5f1, 0x96}, {0xf5f2, 0x80}, {0xf5f3, 0x80}, | ||
323 | {0xf5f4, 0xaa}, | ||
324 | {0xf5f0, 0x51}, {0xf5f1, 0x96}, {0xf5f2, 0x80}, {0xf5f3, 0x80}, | ||
325 | {0xf5f4, 0xaa}, | ||
326 | {0xf5fa, 0x00}, {0xf5f6, 0x0a}, {0xf5f7, 0x0a}, {0xf5f8, 0x0a}, | ||
327 | {0xf5f9, 0x0a} | ||
328 | }; | ||
329 | static const struct i2c_write_cmd mt9v111_init_3[] = { | ||
330 | {0x62, 0x0405}, | ||
331 | }; | ||
332 | static const struct i2c_write_cmd mt9v111_init_4[] = { | ||
333 | {0x05, 0x00ce}, /* horizontal blanking */ | ||
334 | }; | ||
335 | |||
336 | static const struct ucbus_write_cmd ov7660_start_0[] = { | ||
337 | {0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0x00}, {0xf333, 0xc0}, | ||
338 | {0xf334, 0x39}, {0xf335, 0xe7}, {0xf33f, 0x03} | ||
339 | }; | ||
340 | |||
341 | static const struct ucbus_write_cmd ov9630_start_0[] = { | ||
342 | {0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0x00}, {0xf333, 0x00}, | ||
343 | {0xf334, 0x3e}, {0xf335, 0xf8}, {0xf33f, 0x03} | ||
344 | }; | ||
345 | |||
346 | static const struct cap_s { | ||
347 | u8 cc_sizeid; | ||
348 | u8 cc_bytes[32]; | ||
349 | } capconfig[4][3] = { | ||
350 | [SENSOR_ICX098BQ] = { | ||
351 | {0, /* JPEG, 160x120 */ | ||
352 | {0x01, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee, | ||
353 | 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, | ||
354 | 0x02, 0x8b, 0x00, 0x8b, 0x00, 0x41, 0x01, 0x41, | ||
355 | 0x01, 0x41, 0x01, 0x05, 0x40, 0x01, 0xf0, 0x00} }, | ||
356 | {2, /* JPEG, 320x240 */ | ||
357 | {0x01, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee, | ||
358 | 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, | ||
359 | 0x02, 0xdf, 0x01, 0x00, 0x00, 0x3f, 0x01, 0x3f, | ||
360 | 0x01, 0x00, 0x00, 0x05, 0x40, 0x01, 0xf0, 0x00} }, | ||
361 | {4, /* JPEG, 640x480 */ | ||
362 | {0x01, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xf0, | ||
363 | 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, | ||
364 | 0x07, 0xe1, 0x01, 0xe1, 0x01, 0x3f, 0x01, 0x3f, | ||
365 | 0x01, 0x3f, 0x01, 0x05, 0x80, 0x02, 0xe0, 0x01} }, | ||
366 | }, | ||
367 | [SENSOR_LZ24BP] = { | ||
368 | {0, /* JPEG, 160x120 */ | ||
369 | {0x01, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee, | ||
370 | 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, | ||
371 | 0x02, 0x8b, 0x00, 0x8b, 0x00, 0x41, 0x01, 0x41, | ||
372 | 0x01, 0x41, 0x01, 0x05, 0x40, 0x01, 0xf0, 0x00} }, | ||
373 | {2, /* JPEG, 320x240 */ | ||
374 | {0x01, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xee, | ||
375 | 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, | ||
376 | 0x02, 0xdf, 0x01, 0x00, 0x00, 0x3f, 0x01, 0x3f, | ||
377 | 0x01, 0x00, 0x00, 0x05, 0x40, 0x01, 0xf0, 0x00} }, | ||
378 | {4, /* JPEG, 640x480 */ | ||
379 | {0x01, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xf0, | ||
380 | 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, | ||
381 | 0x07, 0xe1, 0x01, 0xe1, 0x01, 0x3f, 0x01, 0x3f, | ||
382 | 0x01, 0x3f, 0x01, 0x05, 0x80, 0x02, 0xe0, 0x01} }, | ||
383 | }, | ||
384 | [SENSOR_MI0360] = { | ||
385 | {0, /* JPEG, 160x120 */ | ||
386 | {0x05, 0x3d, 0x20, 0x0b, 0x00, 0xbd, 0x02, 0x0b, | ||
387 | 0x02, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, | ||
388 | 0x02, 0x01, 0x01, 0x01, 0x01, 0x9f, 0x00, 0x9f, | ||
389 | 0x00, 0x9f, 0x01, 0x05, 0xa0, 0x00, 0x80, 0x00} }, | ||
390 | {2, /* JPEG, 320x240 */ | ||
391 | {0x01, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1, | ||
392 | /*fixme 03 e3 */ | ||
393 | 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, | ||
394 | 0x02, 0xdf, 0x01, 0x00, 0x00, 0x3f, 0x01, 0x3f, | ||
395 | 0x01, 0x00, 0x00, 0x05, 0x40, 0x01, 0xf0, 0x00} }, | ||
396 | {4, /* JPEG, 640x480 */ | ||
397 | {0x01, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe3, | ||
398 | 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, | ||
399 | 0x07, 0xe1, 0x01, 0xe1, 0x01, 0x3f, 0x01, 0x3f, | ||
400 | 0x01, 0x3f, 0x01, 0x05, 0x80, 0x02, 0xe0, 0x01} }, | ||
401 | }, | ||
402 | [SENSOR_MT9V111] = { | ||
403 | {0, /* JPEG, 160x120 */ | ||
404 | {0x05, 0x3d, 0x20, 0x0b, 0x00, 0xbd, 0x02, 0x0b, | ||
405 | 0x02, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, | ||
406 | 0x02, 0x01, 0x01, 0x01, 0x01, 0x9f, 0x00, 0x9f, | ||
407 | 0x00, 0x9f, 0x01, 0x05, 0xa0, 0x00, 0x80, 0x00} }, | ||
408 | {2, /* JPEG, 320x240 */ | ||
409 | {0x01, 0x02, 0x20, 0x03, 0x20, 0x82, 0x02, 0xe3, | ||
410 | 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, | ||
411 | 0x02, 0xdf, 0x01, 0x00, 0x00, 0x3f, 0x01, 0x3f, | ||
412 | 0x01, 0x00, 0x00, 0x05, 0x40, 0x01, 0xf0, 0x00} }, | ||
413 | {4, /* JPEG, 640x480 */ | ||
414 | {0x01, 0x02, 0x20, 0x03, 0x20, 0x82, 0x02, 0xe3, | ||
415 | 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, | ||
416 | 0x07, 0xe1, 0x01, 0xe1, 0x01, 0x3f, 0x01, 0x3f, | ||
417 | 0x01, 0x3f, 0x01, 0x05, 0x80, 0x02, 0xe0, 0x01} }, | ||
418 | }, | ||
419 | }; | ||
420 | |||
421 | struct sensor_s { | ||
422 | const char *name; | ||
423 | u8 i2c_addr; | ||
424 | u8 i2c_dum; | ||
425 | u8 gpio[5]; | ||
426 | u8 cmd_len; | ||
427 | const struct ucbus_write_cmd *cmd; | ||
428 | }; | ||
429 | |||
430 | static const struct sensor_s sensor_tb[] = { | ||
431 | [SENSOR_ICX098BQ] = { | ||
432 | "icx098bp", | ||
433 | 0x00, 0x00, | ||
434 | {0, | ||
435 | SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL, | ||
436 | SQ930_GPIO_DFL_I2C_SDA, | ||
437 | 0, | ||
438 | SQ930_GPIO_RSTBAR | ||
439 | }, | ||
440 | 8, icx098bq_start_0 | ||
441 | }, | ||
442 | [SENSOR_LZ24BP] = { | ||
443 | "lz24bp", | ||
444 | 0x00, 0x00, | ||
445 | {0, | ||
446 | SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL, | ||
447 | SQ930_GPIO_DFL_I2C_SDA, | ||
448 | 0, | ||
449 | SQ930_GPIO_RSTBAR | ||
450 | }, | ||
451 | 8, lz24bp_start_0 | ||
452 | }, | ||
453 | [SENSOR_MI0360] = { | ||
454 | "mi0360", | ||
455 | 0x5d, 0x80, | ||
456 | {SQ930_GPIO_RSTBAR, | ||
457 | SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL, | ||
458 | SQ930_GPIO_DFL_I2C_SDA, | ||
459 | 0, | ||
460 | 0 | ||
461 | }, | ||
462 | 7, mi0360_start_0 | ||
463 | }, | ||
464 | [SENSOR_MT9V111] = { | ||
465 | "mt9v111", | ||
466 | 0x5c, 0x7f, | ||
467 | {SQ930_GPIO_RSTBAR, | ||
468 | SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL, | ||
469 | SQ930_GPIO_DFL_I2C_SDA, | ||
470 | 0, | ||
471 | 0 | ||
472 | }, | ||
473 | 7, mi0360_start_0 | ||
474 | }, | ||
475 | [SENSOR_OV7660] = { | ||
476 | "ov7660", | ||
477 | 0x21, 0x00, | ||
478 | {0, | ||
479 | SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL, | ||
480 | SQ930_GPIO_DFL_I2C_SDA, | ||
481 | 0, | ||
482 | SQ930_GPIO_RSTBAR | ||
483 | }, | ||
484 | 7, ov7660_start_0 | ||
485 | }, | ||
486 | [SENSOR_OV9630] = { | ||
487 | "ov9630", | ||
488 | 0x30, 0x00, | ||
489 | {0, | ||
490 | SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL, | ||
491 | SQ930_GPIO_DFL_I2C_SDA, | ||
492 | 0, | ||
493 | SQ930_GPIO_RSTBAR | ||
494 | }, | ||
495 | 7, ov9630_start_0 | ||
496 | }, | ||
497 | }; | ||
498 | |||
499 | static void reg_r(struct gspca_dev *gspca_dev, | ||
500 | u16 value, int len) | ||
501 | { | ||
502 | int ret; | ||
503 | |||
504 | if (gspca_dev->usb_err < 0) | ||
505 | return; | ||
506 | ret = usb_control_msg(gspca_dev->dev, | ||
507 | usb_rcvctrlpipe(gspca_dev->dev, 0), | ||
508 | 0x0c, | ||
509 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
510 | value, 0, gspca_dev->usb_buf, len, | ||
511 | 500); | ||
512 | if (ret < 0) { | ||
513 | PDEBUG(D_ERR, "reg_r %04x failed %d", value, ret); | ||
514 | gspca_dev->usb_err = ret; | ||
515 | } | ||
516 | } | ||
517 | |||
518 | static void reg_w(struct gspca_dev *gspca_dev, u16 value, u16 index) | ||
519 | { | ||
520 | int ret; | ||
521 | |||
522 | if (gspca_dev->usb_err < 0) | ||
523 | return; | ||
524 | PDEBUG(D_USBO, "reg_w v: %04x i: %04x", value, index); | ||
525 | ret = usb_control_msg(gspca_dev->dev, | ||
526 | usb_sndctrlpipe(gspca_dev->dev, 0), | ||
527 | 0x0c, /* request */ | ||
528 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
529 | value, index, NULL, 0, | ||
530 | 500); | ||
531 | msleep(30); | ||
532 | if (ret < 0) { | ||
533 | PDEBUG(D_ERR, "reg_w %04x %04x failed %d", value, index, ret); | ||
534 | gspca_dev->usb_err = ret; | ||
535 | } | ||
536 | } | ||
537 | |||
538 | static void reg_wb(struct gspca_dev *gspca_dev, u16 value, u16 index, | ||
539 | const u8 *data, int len) | ||
540 | { | ||
541 | int ret; | ||
542 | |||
543 | if (gspca_dev->usb_err < 0) | ||
544 | return; | ||
545 | PDEBUG(D_USBO, "reg_wb v: %04x i: %04x %02x...%02x", | ||
546 | value, index, *data, data[len - 1]); | ||
547 | memcpy(gspca_dev->usb_buf, data, len); | ||
548 | ret = usb_control_msg(gspca_dev->dev, | ||
549 | usb_sndctrlpipe(gspca_dev->dev, 0), | ||
550 | 0x0c, /* request */ | ||
551 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
552 | value, index, gspca_dev->usb_buf, len, | ||
553 | 1000); | ||
554 | msleep(30); | ||
555 | if (ret < 0) { | ||
556 | PDEBUG(D_ERR, "reg_wb %04x %04x failed %d", value, index, ret); | ||
557 | gspca_dev->usb_err = ret; | ||
558 | } | ||
559 | } | ||
560 | |||
561 | static void i2c_write(struct sd *sd, | ||
562 | const struct i2c_write_cmd *cmd, | ||
563 | int ncmds) | ||
564 | { | ||
565 | struct gspca_dev *gspca_dev = &sd->gspca_dev; | ||
566 | const struct sensor_s *sensor; | ||
567 | u16 val, idx; | ||
568 | u8 *buf; | ||
569 | int ret; | ||
570 | |||
571 | if (gspca_dev->usb_err < 0) | ||
572 | return; | ||
573 | |||
574 | sensor = &sensor_tb[sd->sensor]; | ||
575 | |||
576 | val = (sensor->i2c_addr << 8) | SQ930_CTRL_I2C_IO; | ||
577 | idx = (cmd->val & 0xff00) | cmd->reg; | ||
578 | |||
579 | buf = gspca_dev->usb_buf; | ||
580 | *buf++ = sensor->i2c_dum; | ||
581 | *buf++ = cmd->val; | ||
582 | |||
583 | while (--ncmds > 0) { | ||
584 | cmd++; | ||
585 | *buf++ = cmd->reg; | ||
586 | *buf++ = cmd->val >> 8; | ||
587 | *buf++ = sensor->i2c_dum; | ||
588 | *buf++ = cmd->val; | ||
589 | } | ||
590 | |||
591 | PDEBUG(D_USBO, "i2c_w v: %04x i: %04x %02x...%02x", | ||
592 | val, idx, gspca_dev->usb_buf[0], buf[-1]); | ||
593 | ret = usb_control_msg(gspca_dev->dev, | ||
594 | usb_sndctrlpipe(gspca_dev->dev, 0), | ||
595 | 0x0c, /* request */ | ||
596 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
597 | val, idx, | ||
598 | gspca_dev->usb_buf, buf - gspca_dev->usb_buf, | ||
599 | 500); | ||
600 | if (ret < 0) { | ||
601 | PDEBUG(D_ERR, "i2c_write failed %d", ret); | ||
602 | gspca_dev->usb_err = ret; | ||
603 | } | ||
604 | } | ||
605 | |||
606 | static void ucbus_write(struct gspca_dev *gspca_dev, | ||
607 | const struct ucbus_write_cmd *cmd, | ||
608 | int ncmds, | ||
609 | int batchsize) | ||
610 | { | ||
611 | u8 *buf; | ||
612 | u16 val, idx; | ||
613 | int len, ret; | ||
614 | |||
615 | if (gspca_dev->usb_err < 0) | ||
616 | return; | ||
617 | |||
618 | #ifdef GSPCA_DEBUG | ||
619 | if ((batchsize - 1) * 3 > USB_BUF_SZ) { | ||
620 | err("Bug: usb_buf overflow"); | ||
621 | gspca_dev->usb_err = -ENOMEM; | ||
622 | return; | ||
623 | } | ||
624 | #endif | ||
625 | |||
626 | for (;;) { | ||
627 | len = ncmds; | ||
628 | if (len > batchsize) | ||
629 | len = batchsize; | ||
630 | ncmds -= len; | ||
631 | |||
632 | val = (cmd->bw_addr << 8) | SQ930_CTRL_UCBUS_IO; | ||
633 | idx = (cmd->bw_data << 8) | (cmd->bw_addr >> 8); | ||
634 | |||
635 | buf = gspca_dev->usb_buf; | ||
636 | while (--len > 0) { | ||
637 | cmd++; | ||
638 | *buf++ = cmd->bw_addr; | ||
639 | *buf++ = cmd->bw_addr >> 8; | ||
640 | *buf++ = cmd->bw_data; | ||
641 | } | ||
642 | if (buf != gspca_dev->usb_buf) | ||
643 | PDEBUG(D_USBO, "ucbus v: %04x i: %04x %02x...%02x", | ||
644 | val, idx, | ||
645 | gspca_dev->usb_buf[0], buf[-1]); | ||
646 | else | ||
647 | PDEBUG(D_USBO, "ucbus v: %04x i: %04x", | ||
648 | val, idx); | ||
649 | ret = usb_control_msg(gspca_dev->dev, | ||
650 | usb_sndctrlpipe(gspca_dev->dev, 0), | ||
651 | 0x0c, /* request */ | ||
652 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
653 | val, idx, | ||
654 | gspca_dev->usb_buf, buf - gspca_dev->usb_buf, | ||
655 | 500); | ||
656 | if (ret < 0) { | ||
657 | PDEBUG(D_ERR, "ucbus_write failed %d", ret); | ||
658 | gspca_dev->usb_err = ret; | ||
659 | return; | ||
660 | } | ||
661 | msleep(30); | ||
662 | if (ncmds <= 0) | ||
663 | break; | ||
664 | cmd++; | ||
665 | } | ||
666 | } | ||
667 | |||
668 | static void gpio_set(struct sd *sd, u16 val, u16 mask) | ||
669 | { | ||
670 | struct gspca_dev *gspca_dev = &sd->gspca_dev; | ||
671 | |||
672 | if (mask & 0x00ff) { | ||
673 | sd->gpio[0] &= ~mask; | ||
674 | sd->gpio[0] |= val; | ||
675 | reg_w(gspca_dev, 0x0100 | SQ930_CTRL_GPIO, | ||
676 | ~sd->gpio[0] << 8); | ||
677 | } | ||
678 | mask >>= 8; | ||
679 | val >>= 8; | ||
680 | if (mask) { | ||
681 | sd->gpio[1] &= ~mask; | ||
682 | sd->gpio[1] |= val; | ||
683 | reg_w(gspca_dev, 0x0300 | SQ930_CTRL_GPIO, | ||
684 | ~sd->gpio[1] << 8); | ||
685 | } | ||
686 | } | ||
687 | |||
688 | static void gpio_init(struct sd *sd, | ||
689 | const u8 *gpio) | ||
690 | { | ||
691 | gpio_set(sd, *gpio++, 0x000f); | ||
692 | gpio_set(sd, *gpio++, 0x000f); | ||
693 | gpio_set(sd, *gpio++, 0x000f); | ||
694 | gpio_set(sd, *gpio++, 0x000f); | ||
695 | gpio_set(sd, *gpio, 0x000f); | ||
696 | } | ||
697 | |||
698 | static void bridge_init(struct sd *sd) | ||
699 | { | ||
700 | static const struct ucbus_write_cmd clkfreq_cmd = { | ||
701 | 0xf031, 0 /* SQ930_CLKFREQ_60MHZ */ | ||
702 | }; | ||
703 | |||
704 | ucbus_write(&sd->gspca_dev, &clkfreq_cmd, 1, 1); | ||
705 | |||
706 | gpio_set(sd, SQ930_GPIO_POWER, 0xff00); | ||
707 | } | ||
708 | |||
709 | static void cmos_probe(struct gspca_dev *gspca_dev) | ||
710 | { | ||
711 | struct sd *sd = (struct sd *) gspca_dev; | ||
712 | int i; | ||
713 | const struct sensor_s *sensor; | ||
714 | static const u8 probe_order[] = { | ||
715 | /* SENSOR_LZ24BP, (tested as ccd) */ | ||
716 | SENSOR_OV9630, | ||
717 | SENSOR_MI0360, | ||
718 | SENSOR_OV7660, | ||
719 | SENSOR_MT9V111, | ||
720 | }; | ||
721 | |||
722 | for (i = 0; i < ARRAY_SIZE(probe_order); i++) { | ||
723 | sensor = &sensor_tb[probe_order[i]]; | ||
724 | ucbus_write(&sd->gspca_dev, sensor->cmd, sensor->cmd_len, 8); | ||
725 | gpio_init(sd, sensor->gpio); | ||
726 | msleep(100); | ||
727 | reg_r(gspca_dev, (sensor->i2c_addr << 8) | 0x001c, 1); | ||
728 | msleep(100); | ||
729 | if (gspca_dev->usb_buf[0] != 0) | ||
730 | break; | ||
731 | } | ||
732 | if (i >= ARRAY_SIZE(probe_order)) | ||
733 | PDEBUG(D_PROBE, "Unknown sensor"); | ||
734 | else | ||
735 | sd->sensor = probe_order[i]; | ||
736 | } | ||
737 | |||
738 | static void mt9v111_init(struct gspca_dev *gspca_dev) | ||
739 | { | ||
740 | int i, nwait; | ||
741 | static const u8 cmd_001b[] = { | ||
742 | 0x00, 0x3b, 0xf6, 0x01, 0x03, 0x02, 0x00, 0x00, | ||
743 | 0x00, 0x00, 0x00 | ||
744 | }; | ||
745 | static const u8 cmd_011b[][7] = { | ||
746 | {0x10, 0x01, 0x66, 0x08, 0x00, 0x00, 0x00}, | ||
747 | {0x01, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x00}, | ||
748 | {0x20, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00}, | ||
749 | {0x02, 0x01, 0xae, 0x01, 0x00, 0x00, 0x00}, | ||
750 | }; | ||
751 | |||
752 | reg_wb(gspca_dev, 0x001b, 0x0000, cmd_001b, sizeof cmd_001b); | ||
753 | for (i = 0; i < ARRAY_SIZE(cmd_011b); i++) { | ||
754 | reg_wb(gspca_dev, 0x001b, 0x0000, cmd_011b[i], | ||
755 | ARRAY_SIZE(cmd_011b[0])); | ||
756 | msleep(400); | ||
757 | nwait = 20; | ||
758 | for (;;) { | ||
759 | reg_r(gspca_dev, 0x031b, 1); | ||
760 | if (gspca_dev->usb_buf[0] == 0 | ||
761 | || gspca_dev->usb_err != 0) | ||
762 | break; | ||
763 | if (--nwait < 0) { | ||
764 | PDEBUG(D_PROBE, "mt9v111_init timeout"); | ||
765 | gspca_dev->usb_err = -ETIME; | ||
766 | return; | ||
767 | } | ||
768 | msleep(50); | ||
769 | } | ||
770 | } | ||
771 | } | ||
772 | |||
773 | static void global_init(struct sd *sd, int first_time) | ||
774 | { | ||
775 | switch (sd->sensor) { | ||
776 | case SENSOR_ICX098BQ: | ||
777 | if (first_time) | ||
778 | ucbus_write(&sd->gspca_dev, | ||
779 | icx098bq_start_0, | ||
780 | 8, 8); | ||
781 | gpio_init(sd, sensor_tb[sd->sensor].gpio); | ||
782 | break; | ||
783 | case SENSOR_LZ24BP: | ||
784 | if (sd->type != Creative_live_motion) | ||
785 | gpio_set(sd, SQ930_GPIO_EXTRA1, 0x00ff); | ||
786 | else | ||
787 | gpio_set(sd, 0, 0x00ff); | ||
788 | msleep(50); | ||
789 | if (first_time) | ||
790 | ucbus_write(&sd->gspca_dev, | ||
791 | lz24bp_start_0, | ||
792 | 8, 8); | ||
793 | gpio_init(sd, sensor_tb[sd->sensor].gpio); | ||
794 | break; | ||
795 | case SENSOR_MI0360: | ||
796 | if (first_time) | ||
797 | ucbus_write(&sd->gspca_dev, | ||
798 | mi0360_start_0, | ||
799 | ARRAY_SIZE(mi0360_start_0), | ||
800 | 8); | ||
801 | gpio_init(sd, sensor_tb[sd->sensor].gpio); | ||
802 | gpio_set(sd, SQ930_GPIO_EXTRA2, SQ930_GPIO_EXTRA2); | ||
803 | break; | ||
804 | default: | ||
805 | /* case SENSOR_MT9V111: */ | ||
806 | if (first_time) | ||
807 | mt9v111_init(&sd->gspca_dev); | ||
808 | else | ||
809 | gpio_init(sd, sensor_tb[sd->sensor].gpio); | ||
810 | break; | ||
811 | } | ||
812 | } | ||
813 | |||
814 | static void lz24bp_ppl(struct sd *sd, u16 ppl) | ||
815 | { | ||
816 | struct ucbus_write_cmd cmds[2] = { | ||
817 | {0xf810, ppl >> 8}, | ||
818 | {0xf811, ppl} | ||
819 | }; | ||
820 | |||
821 | ucbus_write(&sd->gspca_dev, cmds, ARRAY_SIZE(cmds), 2); | ||
822 | } | ||
823 | |||
824 | static void setexposure(struct gspca_dev *gspca_dev) | ||
825 | { | ||
826 | struct sd *sd = (struct sd *) gspca_dev; | ||
827 | int i, integclks, intstartclk, frameclks, min_frclk; | ||
828 | const struct sensor_s *sensor; | ||
829 | u16 cmd; | ||
830 | u8 buf[15]; | ||
831 | |||
832 | integclks = sd->expo; | ||
833 | i = 0; | ||
834 | cmd = SQ930_CTRL_SET_EXPOSURE; | ||
835 | |||
836 | switch (sd->sensor) { | ||
837 | case SENSOR_ICX098BQ: /* ccd */ | ||
838 | case SENSOR_LZ24BP: | ||
839 | min_frclk = sd->sensor == SENSOR_ICX098BQ ? 0x210 : 0x26f; | ||
840 | if (integclks >= min_frclk) { | ||
841 | intstartclk = 0; | ||
842 | frameclks = integclks; | ||
843 | } else { | ||
844 | intstartclk = min_frclk - integclks; | ||
845 | frameclks = min_frclk; | ||
846 | } | ||
847 | buf[i++] = intstartclk >> 8; | ||
848 | buf[i++] = intstartclk; | ||
849 | buf[i++] = frameclks >> 8; | ||
850 | buf[i++] = frameclks; | ||
851 | buf[i++] = sd->gain; | ||
852 | break; | ||
853 | default: /* cmos */ | ||
854 | /* case SENSOR_MI0360: */ | ||
855 | /* case SENSOR_MT9V111: */ | ||
856 | cmd |= 0x0100; | ||
857 | sensor = &sensor_tb[sd->sensor]; | ||
858 | buf[i++] = sensor->i2c_addr; /* i2c_slave_addr */ | ||
859 | buf[i++] = 0x08; /* 2 * ni2c */ | ||
860 | buf[i++] = 0x09; /* reg = shutter width */ | ||
861 | buf[i++] = integclks >> 8; /* val H */ | ||
862 | buf[i++] = sensor->i2c_dum; | ||
863 | buf[i++] = integclks; /* val L */ | ||
864 | buf[i++] = 0x35; /* reg = global gain */ | ||
865 | buf[i++] = 0x00; /* val H */ | ||
866 | buf[i++] = sensor->i2c_dum; | ||
867 | buf[i++] = sd->gain; /* val L */ | ||
868 | buf[i++] = 0x00; | ||
869 | buf[i++] = 0x00; | ||
870 | buf[i++] = 0x00; | ||
871 | buf[i++] = 0x00; | ||
872 | buf[i++] = 0x83; | ||
873 | break; | ||
874 | } | ||
875 | reg_wb(gspca_dev, cmd, 0, buf, i); | ||
876 | } | ||
877 | |||
878 | /* This function is called at probe time just before sd_init */ | ||
879 | static int sd_config(struct gspca_dev *gspca_dev, | ||
880 | const struct usb_device_id *id) | ||
881 | { | ||
882 | struct sd *sd = (struct sd *) gspca_dev; | ||
883 | struct cam *cam = &gspca_dev->cam; | ||
884 | |||
885 | sd->sensor = id->driver_info >> 8; | ||
886 | sd->type = id->driver_info; | ||
887 | |||
888 | cam->cam_mode = vga_mode; | ||
889 | cam->nmodes = ARRAY_SIZE(vga_mode); | ||
890 | |||
891 | cam->bulk = 1; | ||
892 | cam->bulk_size = BULK_TRANSFER_LEN; | ||
893 | /* cam->bulk_nurbs = 2; fixme: if no setexpo sync */ | ||
894 | |||
895 | sd->quality = QUALITY_DEF; | ||
896 | sd->gain = GAIN_DEF; | ||
897 | sd->expo = EXPO_DEF; | ||
898 | |||
899 | return 0; | ||
900 | } | ||
901 | |||
902 | /* this function is called at probe and resume time */ | ||
903 | static int sd_init(struct gspca_dev *gspca_dev) | ||
904 | { | ||
905 | struct sd *sd = (struct sd *) gspca_dev; | ||
906 | |||
907 | sd->gpio[0] = sd->gpio[1] = 0xff; /* force gpio rewrite */ | ||
908 | |||
909 | /*fixme: is this needed for icx098bp and mi0360? | ||
910 | if (sd->sensor != SENSOR_LZ24BP) | ||
911 | reg_w(gspca_dev, SQ930_CTRL_RESET, 0x0000); | ||
912 | */ | ||
913 | |||
914 | reg_r(gspca_dev, SQ930_CTRL_GET_DEV_INFO, 8); | ||
915 | /* it returns: | ||
916 | * 03 00 12 93 0b f6 c9 00 live! ultra | ||
917 | * 03 00 07 93 0b f6 ca 00 live! ultra for notebook | ||
918 | * 03 00 12 93 0b fe c8 00 Trust WB-3500T | ||
919 | * 02 00 06 93 0b fe c8 00 Joy-IT 318S | ||
920 | * 03 00 12 93 0b f6 cf 00 icam tracer - sensor icx098bq | ||
921 | * 02 00 12 93 0b fe cf 00 ProQ Motion Webcam | ||
922 | * | ||
923 | * byte | ||
924 | * 0: 02 = usb 1.0 (12Mbit) / 03 = usb2.0 (480Mbit) | ||
925 | * 1: 00 | ||
926 | * 2: 06 / 07 / 12 = mode webcam? firmware?? | ||
927 | * 3: 93 chip = 930b (930b or 930c) | ||
928 | * 4: 0b | ||
929 | * 5: f6 = cdd (icx098bq, lz24bp) / fe or de = cmos (i2c) (other sensors) | ||
930 | * 6: c8 / c9 / ca / cf = mode webcam?, sensor? webcam? | ||
931 | * 7: 00 | ||
932 | */ | ||
933 | PDEBUG(D_PROBE, "info: %02x %02x %02x %02x %02x %02x %02x %02x", | ||
934 | gspca_dev->usb_buf[0], | ||
935 | gspca_dev->usb_buf[1], | ||
936 | gspca_dev->usb_buf[2], | ||
937 | gspca_dev->usb_buf[3], | ||
938 | gspca_dev->usb_buf[4], | ||
939 | gspca_dev->usb_buf[5], | ||
940 | gspca_dev->usb_buf[6], | ||
941 | gspca_dev->usb_buf[7]); | ||
942 | |||
943 | bridge_init(sd); | ||
944 | |||
945 | if (sd->sensor == SENSOR_MI0360) { | ||
946 | |||
947 | /* no sensor probe for icam tracer */ | ||
948 | if (gspca_dev->usb_buf[5] == 0xf6) { /* if CMOS */ | ||
949 | sd->sensor = SENSOR_ICX098BQ; | ||
950 | gspca_dev->cam.cam_mode = &vga_mode[1]; | ||
951 | gspca_dev->cam.nmodes = 1; /* only 320x240 */ | ||
952 | } else { | ||
953 | cmos_probe(gspca_dev); | ||
954 | } | ||
955 | } | ||
956 | |||
957 | PDEBUG(D_PROBE, "Sensor %s", sensor_tb[sd->sensor].name); | ||
958 | |||
959 | global_init(sd, 1); | ||
960 | return gspca_dev->usb_err; | ||
961 | } | ||
962 | |||
963 | /* special function to create the quantization tables of the JPEG header */ | ||
964 | static void sd_jpeg_set_qual(u8 *jpeg_hdr, | ||
965 | int quality) | ||
966 | { | ||
967 | int i, sc1, sc2; | ||
968 | |||
969 | quality = quality_tb[quality]; /* convert to JPEG quality */ | ||
970 | /* | ||
971 | * approximative qualities for Y and U/V: | ||
972 | * quant = 0:94%/91% 1:91%/87% 2:82%/73% 3:69%/56% | ||
973 | * should have: | ||
974 | * quant = 0:94%/91% 1:91%/87.5% 2:81.5%/72% 3:69%/54.5% | ||
975 | */ | ||
976 | sc1 = 200 - quality * 2; | ||
977 | quality = quality * 7 / 5 - 40; /* UV quality */ | ||
978 | sc2 = 200 - quality * 2; | ||
979 | for (i = 0; i < 64; i++) { | ||
980 | jpeg_hdr[JPEG_QT0_OFFSET + i] = | ||
981 | (jpeg_head[JPEG_QT0_OFFSET + i] * sc1 + 50) / 100; | ||
982 | jpeg_hdr[JPEG_QT1_OFFSET + i] = | ||
983 | (jpeg_head[JPEG_QT1_OFFSET + i] * sc2 + 50) / 100; | ||
984 | } | ||
985 | } | ||
986 | |||
987 | /* send the start/stop commands to the webcam */ | ||
988 | static void send_start(struct gspca_dev *gspca_dev) | ||
989 | { | ||
990 | struct sd *sd = (struct sd *) gspca_dev; | ||
991 | const struct cap_s *cap; | ||
992 | int mode, quality; | ||
993 | |||
994 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; | ||
995 | cap = &capconfig[sd->sensor][mode]; | ||
996 | quality = sd->quality; | ||
997 | reg_wb(gspca_dev, (quality << 12) | ||
998 | | 0x0a00 /* 900 for Bayer */ | ||
999 | | SQ930_CTRL_CAP_START, | ||
1000 | 0x0500 /* a00 for Bayer */ | ||
1001 | | cap->cc_sizeid, | ||
1002 | cap->cc_bytes, 32); | ||
1003 | }; | ||
1004 | static void send_stop(struct gspca_dev *gspca_dev) | ||
1005 | { | ||
1006 | reg_w(gspca_dev, SQ930_CTRL_CAP_STOP, 0); | ||
1007 | }; | ||
1008 | |||
1009 | /* function called at start time before URB creation */ | ||
1010 | static int sd_isoc_init(struct gspca_dev *gspca_dev) | ||
1011 | { | ||
1012 | struct sd *sd = (struct sd *) gspca_dev; | ||
1013 | |||
1014 | gspca_dev->cam.bulk_nurbs = 1; /* there must be one URB only */ | ||
1015 | sd->do_ctrl = 0; | ||
1016 | return 0; | ||
1017 | } | ||
1018 | |||
1019 | /* start the capture */ | ||
1020 | static int sd_start(struct gspca_dev *gspca_dev) | ||
1021 | { | ||
1022 | struct sd *sd = (struct sd *) gspca_dev; | ||
1023 | int mode; | ||
1024 | |||
1025 | /* initialize the JPEG header */ | ||
1026 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, | ||
1027 | 0x21); /* JPEG 422 */ | ||
1028 | sd_jpeg_set_qual(sd->jpeg_hdr, sd->quality); | ||
1029 | |||
1030 | bridge_init(sd); | ||
1031 | global_init(sd, 0); | ||
1032 | msleep(100); | ||
1033 | |||
1034 | switch (sd->sensor) { | ||
1035 | case SENSOR_ICX098BQ: | ||
1036 | ucbus_write(gspca_dev, icx098bq_start_0, | ||
1037 | ARRAY_SIZE(icx098bq_start_0), | ||
1038 | 8); | ||
1039 | ucbus_write(gspca_dev, icx098bq_start_1, | ||
1040 | ARRAY_SIZE(icx098bq_start_1), | ||
1041 | 5); | ||
1042 | ucbus_write(gspca_dev, icx098bq_start_2, | ||
1043 | ARRAY_SIZE(icx098bq_start_2), | ||
1044 | 6); | ||
1045 | msleep(50); | ||
1046 | |||
1047 | /* 1st start */ | ||
1048 | send_start(gspca_dev); | ||
1049 | gpio_set(sd, SQ930_GPIO_EXTRA2 | SQ930_GPIO_RSTBAR, 0x00ff); | ||
1050 | msleep(70); | ||
1051 | reg_w(gspca_dev, SQ930_CTRL_CAP_STOP, 0x0000); | ||
1052 | gpio_set(sd, 0x7f, 0x00ff); | ||
1053 | |||
1054 | /* 2nd start */ | ||
1055 | send_start(gspca_dev); | ||
1056 | gpio_set(sd, SQ930_GPIO_EXTRA2 | SQ930_GPIO_RSTBAR, 0x00ff); | ||
1057 | goto out; | ||
1058 | case SENSOR_LZ24BP: | ||
1059 | ucbus_write(gspca_dev, lz24bp_start_0, | ||
1060 | ARRAY_SIZE(lz24bp_start_0), | ||
1061 | 8); | ||
1062 | if (sd->type != Creative_live_motion) | ||
1063 | ucbus_write(gspca_dev, lz24bp_start_1_gen, | ||
1064 | ARRAY_SIZE(lz24bp_start_1_gen), | ||
1065 | 5); | ||
1066 | else | ||
1067 | ucbus_write(gspca_dev, lz24bp_start_1_clm, | ||
1068 | ARRAY_SIZE(lz24bp_start_1_clm), | ||
1069 | 5); | ||
1070 | ucbus_write(gspca_dev, lz24bp_start_2, | ||
1071 | ARRAY_SIZE(lz24bp_start_2), | ||
1072 | 6); | ||
1073 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; | ||
1074 | lz24bp_ppl(sd, mode == 2 ? 0x0564 : 0x0310); | ||
1075 | msleep(10); | ||
1076 | break; | ||
1077 | case SENSOR_MI0360: | ||
1078 | ucbus_write(gspca_dev, mi0360_start_0, | ||
1079 | ARRAY_SIZE(mi0360_start_0), | ||
1080 | 8); | ||
1081 | i2c_write(sd, mi0360_init_23, | ||
1082 | ARRAY_SIZE(mi0360_init_23)); | ||
1083 | i2c_write(sd, mi0360_init_24, | ||
1084 | ARRAY_SIZE(mi0360_init_24)); | ||
1085 | i2c_write(sd, mi0360_init_25, | ||
1086 | ARRAY_SIZE(mi0360_init_25)); | ||
1087 | ucbus_write(gspca_dev, mi0360_start_1, | ||
1088 | ARRAY_SIZE(mi0360_start_1), | ||
1089 | 5); | ||
1090 | i2c_write(sd, mi0360_start_2, | ||
1091 | ARRAY_SIZE(mi0360_start_2)); | ||
1092 | i2c_write(sd, mi0360_start_3, | ||
1093 | ARRAY_SIZE(mi0360_start_3)); | ||
1094 | |||
1095 | /* 1st start */ | ||
1096 | send_start(gspca_dev); | ||
1097 | msleep(60); | ||
1098 | reg_w(gspca_dev, SQ930_CTRL_CAP_STOP, 0x0000); | ||
1099 | |||
1100 | i2c_write(sd, | ||
1101 | mi0360_start_4, ARRAY_SIZE(mi0360_start_4)); | ||
1102 | break; | ||
1103 | default: | ||
1104 | /* case SENSOR_MT9V111: */ | ||
1105 | ucbus_write(gspca_dev, mi0360_start_0, | ||
1106 | ARRAY_SIZE(mi0360_start_0), | ||
1107 | 8); | ||
1108 | i2c_write(sd, mt9v111_init_0, | ||
1109 | ARRAY_SIZE(mt9v111_init_0)); | ||
1110 | i2c_write(sd, mt9v111_init_1, | ||
1111 | ARRAY_SIZE(mt9v111_init_1)); | ||
1112 | i2c_write(sd, mt9v111_init_2, | ||
1113 | ARRAY_SIZE(mt9v111_init_2)); | ||
1114 | ucbus_write(gspca_dev, mt9v111_start_1, | ||
1115 | ARRAY_SIZE(mt9v111_start_1), | ||
1116 | 8); | ||
1117 | i2c_write(sd, mt9v111_init_3, | ||
1118 | ARRAY_SIZE(mt9v111_init_3)); | ||
1119 | i2c_write(sd, mt9v111_init_4, | ||
1120 | ARRAY_SIZE(mt9v111_init_4)); | ||
1121 | break; | ||
1122 | } | ||
1123 | |||
1124 | send_start(gspca_dev); | ||
1125 | out: | ||
1126 | msleep(1000); | ||
1127 | |||
1128 | sd->eof_len = 0; /* init packet scan */ | ||
1129 | |||
1130 | if (sd->sensor == SENSOR_MT9V111) | ||
1131 | gpio_set(sd, SQ930_GPIO_DFL_LED, SQ930_GPIO_DFL_LED); | ||
1132 | |||
1133 | sd->do_ctrl = 1; /* set the exposure */ | ||
1134 | |||
1135 | return gspca_dev->usb_err; | ||
1136 | } | ||
1137 | |||
1138 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
1139 | { | ||
1140 | struct sd *sd = (struct sd *) gspca_dev; | ||
1141 | |||
1142 | if (sd->sensor == SENSOR_MT9V111) | ||
1143 | gpio_set(sd, 0, SQ930_GPIO_DFL_LED); | ||
1144 | send_stop(gspca_dev); | ||
1145 | } | ||
1146 | |||
1147 | /* function called when the application gets a new frame */ | ||
1148 | /* It sets the exposure if required and restart the bulk transfer. */ | ||
1149 | static void sd_dq_callback(struct gspca_dev *gspca_dev) | ||
1150 | { | ||
1151 | struct sd *sd = (struct sd *) gspca_dev; | ||
1152 | int ret; | ||
1153 | |||
1154 | if (!sd->do_ctrl || gspca_dev->cam.bulk_nurbs != 0) | ||
1155 | return; | ||
1156 | sd->do_ctrl = 0; | ||
1157 | |||
1158 | setexposure(gspca_dev); | ||
1159 | |||
1160 | gspca_dev->cam.bulk_nurbs = 1; | ||
1161 | ret = usb_submit_urb(gspca_dev->urb[0], GFP_ATOMIC); | ||
1162 | if (ret < 0) | ||
1163 | PDEBUG(D_ERR|D_PACK, "sd_dq_callback() err %d", ret); | ||
1164 | |||
1165 | /* wait a little time, otherwise the webcam crashes */ | ||
1166 | msleep(100); | ||
1167 | } | ||
1168 | |||
1169 | /* move a packet adding 0x00 after 0xff */ | ||
1170 | static void add_packet(struct gspca_dev *gspca_dev, | ||
1171 | u8 *data, | ||
1172 | int len) | ||
1173 | { | ||
1174 | int i; | ||
1175 | |||
1176 | i = 0; | ||
1177 | do { | ||
1178 | if (data[i] == 0xff) { | ||
1179 | gspca_frame_add(gspca_dev, INTER_PACKET, | ||
1180 | data, i + 1); | ||
1181 | len -= i; | ||
1182 | data += i; | ||
1183 | *data = 0x00; | ||
1184 | i = 0; | ||
1185 | } | ||
1186 | } while (++i < len); | ||
1187 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | ||
1188 | } | ||
1189 | |||
1190 | /* end a frame and start a new one */ | ||
1191 | static void eof_sof(struct gspca_dev *gspca_dev) | ||
1192 | { | ||
1193 | struct sd *sd = (struct sd *) gspca_dev; | ||
1194 | static const u8 ffd9[] = {0xff, 0xd9}; | ||
1195 | |||
1196 | /* if control set, stop bulk transfer */ | ||
1197 | if (sd->do_ctrl | ||
1198 | && gspca_dev->last_packet_type == INTER_PACKET) | ||
1199 | gspca_dev->cam.bulk_nurbs = 0; | ||
1200 | gspca_frame_add(gspca_dev, LAST_PACKET, | ||
1201 | ffd9, 2); | ||
1202 | gspca_frame_add(gspca_dev, FIRST_PACKET, | ||
1203 | sd->jpeg_hdr, JPEG_HDR_SZ); | ||
1204 | } | ||
1205 | |||
1206 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
1207 | u8 *data, /* isoc packet */ | ||
1208 | int len) /* iso packet length */ | ||
1209 | { | ||
1210 | struct sd *sd = (struct sd *) gspca_dev; | ||
1211 | u8 *p; | ||
1212 | int l; | ||
1213 | |||
1214 | len -= 8; /* ignore last 8 bytes (00 00 55 aa 55 aa 00 00) */ | ||
1215 | |||
1216 | /* | ||
1217 | * the end/start of frame is indicated by | ||
1218 | * 0x00 * 16 - 0xab * 8 | ||
1219 | * aligned on 8 bytes boundary | ||
1220 | */ | ||
1221 | if (sd->eof_len != 0) { /* if 'abababab' in previous pkt */ | ||
1222 | if (*((u32 *) data) == 0xabababab) { | ||
1223 | /*fixme: should remove previous 0000ababab*/ | ||
1224 | eof_sof(gspca_dev); | ||
1225 | data += 4; | ||
1226 | len -= 4; | ||
1227 | } | ||
1228 | sd->eof_len = 0; | ||
1229 | } | ||
1230 | p = data; | ||
1231 | l = len; | ||
1232 | for (;;) { | ||
1233 | if (*((u32 *) p) == 0xabababab) { | ||
1234 | if (l < 8) { /* (may be 4 only) */ | ||
1235 | sd->eof_len = 1; | ||
1236 | break; | ||
1237 | } | ||
1238 | if (*((u32 *) p + 1) == 0xabababab) { | ||
1239 | add_packet(gspca_dev, data, p - data - 16); | ||
1240 | /* remove previous zeros */ | ||
1241 | eof_sof(gspca_dev); | ||
1242 | p += 8; | ||
1243 | l -= 8; | ||
1244 | if (l <= 0) | ||
1245 | return; | ||
1246 | len = l; | ||
1247 | data = p; | ||
1248 | continue; | ||
1249 | } | ||
1250 | } | ||
1251 | p += 4; | ||
1252 | l -= 4; | ||
1253 | if (l <= 0) | ||
1254 | break; | ||
1255 | } | ||
1256 | add_packet(gspca_dev, data, len); | ||
1257 | } | ||
1258 | |||
1259 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) | ||
1260 | { | ||
1261 | struct sd *sd = (struct sd *) gspca_dev; | ||
1262 | |||
1263 | sd->gain = val; | ||
1264 | if (gspca_dev->streaming) | ||
1265 | sd->do_ctrl = 1; | ||
1266 | return 0; | ||
1267 | } | ||
1268 | |||
1269 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) | ||
1270 | { | ||
1271 | struct sd *sd = (struct sd *) gspca_dev; | ||
1272 | |||
1273 | *val = sd->gain; | ||
1274 | return 0; | ||
1275 | } | ||
1276 | static int sd_setexpo(struct gspca_dev *gspca_dev, __s32 val) | ||
1277 | { | ||
1278 | struct sd *sd = (struct sd *) gspca_dev; | ||
1279 | |||
1280 | sd->expo = val; | ||
1281 | if (gspca_dev->streaming) | ||
1282 | sd->do_ctrl = 1; | ||
1283 | return 0; | ||
1284 | } | ||
1285 | |||
1286 | static int sd_getexpo(struct gspca_dev *gspca_dev, __s32 *val) | ||
1287 | { | ||
1288 | struct sd *sd = (struct sd *) gspca_dev; | ||
1289 | |||
1290 | *val = sd->expo; | ||
1291 | return 0; | ||
1292 | } | ||
1293 | |||
1294 | static int sd_set_jcomp(struct gspca_dev *gspca_dev, | ||
1295 | struct v4l2_jpegcompression *jcomp) | ||
1296 | { | ||
1297 | struct sd *sd = (struct sd *) gspca_dev; | ||
1298 | int quality; | ||
1299 | |||
1300 | if (jcomp->quality >= (QUAL_0 + QUAL_1) / 2) | ||
1301 | quality = 0; | ||
1302 | else if (jcomp->quality >= (QUAL_1 + QUAL_2) / 2) | ||
1303 | quality = 1; | ||
1304 | else if (jcomp->quality >= (QUAL_2 + QUAL_3) / 2) | ||
1305 | quality = 2; | ||
1306 | else | ||
1307 | quality = 3; | ||
1308 | |||
1309 | if (quality != sd->quality) { | ||
1310 | sd->quality = quality; | ||
1311 | if (gspca_dev->streaming) { | ||
1312 | send_stop(gspca_dev); | ||
1313 | sd_jpeg_set_qual(sd->jpeg_hdr, sd->quality); | ||
1314 | msleep(70); | ||
1315 | send_start(gspca_dev); | ||
1316 | } | ||
1317 | } | ||
1318 | return gspca_dev->usb_err; | ||
1319 | } | ||
1320 | |||
1321 | static int sd_get_jcomp(struct gspca_dev *gspca_dev, | ||
1322 | struct v4l2_jpegcompression *jcomp) | ||
1323 | { | ||
1324 | struct sd *sd = (struct sd *) gspca_dev; | ||
1325 | |||
1326 | memset(jcomp, 0, sizeof *jcomp); | ||
1327 | jcomp->quality = quality_tb[sd->quality]; | ||
1328 | jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | ||
1329 | | V4L2_JPEG_MARKER_DQT; | ||
1330 | return 0; | ||
1331 | } | ||
1332 | |||
1333 | /* sub-driver description */ | ||
1334 | static const struct sd_desc sd_desc = { | ||
1335 | .name = MODULE_NAME, | ||
1336 | .ctrls = sd_ctrls, | ||
1337 | .nctrls = ARRAY_SIZE(sd_ctrls), | ||
1338 | .config = sd_config, | ||
1339 | .init = sd_init, | ||
1340 | .isoc_init = sd_isoc_init, | ||
1341 | .start = sd_start, | ||
1342 | .stopN = sd_stopN, | ||
1343 | .pkt_scan = sd_pkt_scan, | ||
1344 | .dq_callback = sd_dq_callback, | ||
1345 | .get_jcomp = sd_get_jcomp, | ||
1346 | .set_jcomp = sd_set_jcomp, | ||
1347 | }; | ||
1348 | |||
1349 | /* Table of supported USB devices */ | ||
1350 | #define ST(sensor, type) \ | ||
1351 | .driver_info = (SENSOR_ ## sensor << 8) \ | ||
1352 | | (type) | ||
1353 | static const __devinitdata struct usb_device_id device_table[] = { | ||
1354 | {USB_DEVICE(0x041e, 0x4038), ST(MI0360, 0)}, | ||
1355 | {USB_DEVICE(0x041e, 0x403c), ST(LZ24BP, 0)}, | ||
1356 | {USB_DEVICE(0x041e, 0x403d), ST(LZ24BP, 0)}, | ||
1357 | {USB_DEVICE(0x041e, 0x4041), ST(LZ24BP, Creative_live_motion)}, | ||
1358 | {USB_DEVICE(0x2770, 0x930b), ST(MI0360, 0)}, | ||
1359 | {USB_DEVICE(0x2770, 0x930c), ST(MI0360, 0)}, | ||
1360 | {} | ||
1361 | }; | ||
1362 | MODULE_DEVICE_TABLE(usb, device_table); | ||
1363 | |||
1364 | |||
1365 | /* -- device connect -- */ | ||
1366 | static int sd_probe(struct usb_interface *intf, | ||
1367 | const struct usb_device_id *id) | ||
1368 | { | ||
1369 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | ||
1370 | THIS_MODULE); | ||
1371 | } | ||
1372 | |||
1373 | static struct usb_driver sd_driver = { | ||
1374 | .name = MODULE_NAME, | ||
1375 | .id_table = device_table, | ||
1376 | .probe = sd_probe, | ||
1377 | .disconnect = gspca_disconnect, | ||
1378 | #ifdef CONFIG_PM | ||
1379 | .suspend = gspca_suspend, | ||
1380 | .resume = gspca_resume, | ||
1381 | #endif | ||
1382 | }; | ||
1383 | |||
1384 | /* -- module insert / remove -- */ | ||
1385 | static int __init sd_mod_init(void) | ||
1386 | { | ||
1387 | int ret; | ||
1388 | |||
1389 | ret = usb_register(&sd_driver); | ||
1390 | if (ret < 0) | ||
1391 | return ret; | ||
1392 | info("registered"); | ||
1393 | return 0; | ||
1394 | } | ||
1395 | static void __exit sd_mod_exit(void) | ||
1396 | { | ||
1397 | usb_deregister(&sd_driver); | ||
1398 | info("deregistered"); | ||
1399 | } | ||
1400 | |||
1401 | module_init(sd_mod_init); | ||
1402 | module_exit(sd_mod_exit); | ||
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index 0fb534210a2c..2aedf4b1bfa3 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c | |||
@@ -36,11 +36,11 @@ struct sd { | |||
36 | unsigned char colors; | 36 | unsigned char colors; |
37 | unsigned char lightfreq; | 37 | unsigned char lightfreq; |
38 | u8 quality; | 38 | u8 quality; |
39 | #define QUALITY_MIN 60 | 39 | #define QUALITY_MIN 70 |
40 | #define QUALITY_MAX 95 | 40 | #define QUALITY_MAX 95 |
41 | #define QUALITY_DEF 80 | 41 | #define QUALITY_DEF 88 |
42 | 42 | ||
43 | u8 *jpeg_hdr; | 43 | u8 jpeg_hdr[JPEG_HDR_SZ]; |
44 | }; | 44 | }; |
45 | 45 | ||
46 | /* V4L2 controls supported by the driver */ | 46 | /* V4L2 controls supported by the driver */ |
@@ -337,9 +337,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
337 | int ret, value; | 337 | int ret, value; |
338 | 338 | ||
339 | /* create the JPEG header */ | 339 | /* create the JPEG header */ |
340 | sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); | ||
341 | if (!sd->jpeg_hdr) | ||
342 | return -ENOMEM; | ||
343 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, | 340 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, |
344 | 0x22); /* JPEG 411 */ | 341 | 0x22); /* JPEG 411 */ |
345 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | 342 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); |
@@ -412,13 +409,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
412 | PDEBUG(D_STREAM, "camera stopped"); | 409 | PDEBUG(D_STREAM, "camera stopped"); |
413 | } | 410 | } |
414 | 411 | ||
415 | static void sd_stop0(struct gspca_dev *gspca_dev) | ||
416 | { | ||
417 | struct sd *sd = (struct sd *) gspca_dev; | ||
418 | |||
419 | kfree(sd->jpeg_hdr); | ||
420 | } | ||
421 | |||
422 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 412 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
423 | u8 *data, /* isoc packet */ | 413 | u8 *data, /* isoc packet */ |
424 | int len) /* iso packet length */ | 414 | int len) /* iso packet length */ |
@@ -578,7 +568,6 @@ static const struct sd_desc sd_desc = { | |||
578 | .init = sd_init, | 568 | .init = sd_init, |
579 | .start = sd_start, | 569 | .start = sd_start, |
580 | .stopN = sd_stopN, | 570 | .stopN = sd_stopN, |
581 | .stop0 = sd_stop0, | ||
582 | .pkt_scan = sd_pkt_scan, | 571 | .pkt_scan = sd_pkt_scan, |
583 | .querymenu = sd_querymenu, | 572 | .querymenu = sd_querymenu, |
584 | .get_jcomp = sd_get_jcomp, | 573 | .get_jcomp = sd_get_jcomp, |
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.h b/drivers/media/video/gspca/stv06xx/stv06xx.h index 992ce530f138..053a27e3a400 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #ifndef STV06XX_H_ | 30 | #ifndef STV06XX_H_ |
31 | #define STV06XX_H_ | 31 | #define STV06XX_H_ |
32 | 32 | ||
33 | #include <linux/slab.h> | ||
33 | #include "gspca.h" | 34 | #include "gspca.h" |
34 | 35 | ||
35 | #define MODULE_NAME "STV06xx" | 36 | #define MODULE_NAME "STV06xx" |
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index 0c786e00ebcf..21d82bab0c2e 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c | |||
@@ -54,7 +54,7 @@ struct sd { | |||
54 | #define MegapixV4 4 | 54 | #define MegapixV4 4 |
55 | #define MegaImageVI 5 | 55 | #define MegaImageVI 5 |
56 | 56 | ||
57 | u8 *jpeg_hdr; | 57 | u8 jpeg_hdr[JPEG_HDR_SZ]; |
58 | }; | 58 | }; |
59 | 59 | ||
60 | /* V4L2 controls supported by the driver */ | 60 | /* V4L2 controls supported by the driver */ |
@@ -842,9 +842,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
842 | int enable; | 842 | int enable; |
843 | 843 | ||
844 | /* create the JPEG header */ | 844 | /* create the JPEG header */ |
845 | sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); | ||
846 | if (!sd->jpeg_hdr) | ||
847 | return -ENOMEM; | ||
848 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, | 845 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, |
849 | 0x22); /* JPEG 411 */ | 846 | 0x22); /* JPEG 411 */ |
850 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | 847 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); |
@@ -954,13 +951,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
954 | } | 951 | } |
955 | } | 952 | } |
956 | 953 | ||
957 | static void sd_stop0(struct gspca_dev *gspca_dev) | ||
958 | { | ||
959 | struct sd *sd = (struct sd *) gspca_dev; | ||
960 | |||
961 | kfree(sd->jpeg_hdr); | ||
962 | } | ||
963 | |||
964 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 954 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
965 | u8 *data, /* isoc packet */ | 955 | u8 *data, /* isoc packet */ |
966 | int len) /* iso packet length */ | 956 | int len) /* iso packet length */ |
@@ -1162,7 +1152,6 @@ static const struct sd_desc sd_desc = { | |||
1162 | .init = sd_init, | 1152 | .init = sd_init, |
1163 | .start = sd_start, | 1153 | .start = sd_start, |
1164 | .stopN = sd_stopN, | 1154 | .stopN = sd_stopN, |
1165 | .stop0 = sd_stop0, | ||
1166 | .pkt_scan = sd_pkt_scan, | 1155 | .pkt_scan = sd_pkt_scan, |
1167 | .get_jcomp = sd_get_jcomp, | 1156 | .get_jcomp = sd_get_jcomp, |
1168 | .set_jcomp = sd_set_jcomp, | 1157 | .set_jcomp = sd_set_jcomp, |
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 63014372adbc..2a0f12d55e48 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c | |||
@@ -1,5 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> | 2 | * T613 subdriver |
3 | * | ||
4 | * Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr) | ||
3 | * | 5 | * |
4 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -26,6 +28,7 @@ | |||
26 | 28 | ||
27 | #define MODULE_NAME "t613" | 29 | #define MODULE_NAME "t613" |
28 | 30 | ||
31 | #include <linux/slab.h> | ||
29 | #include "gspca.h" | 32 | #include "gspca.h" |
30 | 33 | ||
31 | #define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0) | 34 | #define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0) |
@@ -44,18 +47,20 @@ struct sd { | |||
44 | u8 gamma; | 47 | u8 gamma; |
45 | u8 sharpness; | 48 | u8 sharpness; |
46 | u8 freq; | 49 | u8 freq; |
47 | u8 red_balance; /* split balance */ | 50 | u8 red_gain; |
48 | u8 blue_balance; | 51 | u8 blue_gain; |
49 | u8 global_gain; /* aka gain */ | 52 | u8 green_gain; |
50 | u8 whitebalance; /* set default r/g/b and activate */ | 53 | u8 awb; /* set default r/g/b and activate */ |
51 | u8 mirror; | 54 | u8 mirror; |
52 | u8 effect; | 55 | u8 effect; |
53 | 56 | ||
54 | u8 sensor; | 57 | u8 sensor; |
55 | #define SENSOR_OM6802 0 | 58 | enum { |
56 | #define SENSOR_OTHER 1 | 59 | SENSOR_OM6802, |
57 | #define SENSOR_TAS5130A 2 | 60 | SENSOR_OTHER, |
58 | #define SENSOR_LT168G 3 /* must verify if this is the actual model */ | 61 | SENSOR_TAS5130A, |
62 | SENSOR_LT168G, /* must verify if this is the actual model */ | ||
63 | } sensors; | ||
59 | }; | 64 | }; |
60 | 65 | ||
61 | /* V4L2 controls supported by the driver */ | 66 | /* V4L2 controls supported by the driver */ |
@@ -74,24 +79,22 @@ static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | |||
74 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | 79 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); |
75 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | 80 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); |
76 | 81 | ||
77 | 82 | static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val); | |
78 | static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val); | 83 | static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val); |
79 | static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val); | 84 | static int sd_setblue_gain(struct gspca_dev *gspca_dev, __s32 val); |
80 | static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val); | 85 | static int sd_getblue_gain(struct gspca_dev *gspca_dev, __s32 *val); |
81 | static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val); | 86 | static int sd_setred_gain(struct gspca_dev *gspca_dev, __s32 val); |
82 | static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val); | 87 | static int sd_getred_gain(struct gspca_dev *gspca_dev, __s32 *val); |
83 | static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val); | 88 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); |
84 | static int sd_setglobal_gain(struct gspca_dev *gspca_dev, __s32 val); | 89 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); |
85 | static int sd_getglobal_gain(struct gspca_dev *gspca_dev, __s32 *val); | 90 | |
86 | 91 | static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val); | |
87 | static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val); | 92 | static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val); |
88 | static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
89 | static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val); | 93 | static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val); |
90 | static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val); | 94 | static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val); |
91 | static int sd_querymenu(struct gspca_dev *gspca_dev, | 95 | static int sd_querymenu(struct gspca_dev *gspca_dev, |
92 | struct v4l2_querymenu *menu); | 96 | struct v4l2_querymenu *menu); |
93 | 97 | ||
94 | |||
95 | static const struct ctrl sd_ctrls[] = { | 98 | static const struct ctrl sd_ctrls[] = { |
96 | { | 99 | { |
97 | { | 100 | { |
@@ -177,8 +180,8 @@ static const struct ctrl sd_ctrls[] = { | |||
177 | #define MIRROR_DEF 0 | 180 | #define MIRROR_DEF 0 |
178 | .default_value = MIRROR_DEF, | 181 | .default_value = MIRROR_DEF, |
179 | }, | 182 | }, |
180 | .set = sd_setflip, | 183 | .set = sd_setmirror, |
181 | .get = sd_getflip | 184 | .get = sd_getmirror |
182 | }, | 185 | }, |
183 | { | 186 | { |
184 | { | 187 | { |
@@ -198,15 +201,15 @@ static const struct ctrl sd_ctrls[] = { | |||
198 | { | 201 | { |
199 | .id = V4L2_CID_AUTO_WHITE_BALANCE, | 202 | .id = V4L2_CID_AUTO_WHITE_BALANCE, |
200 | .type = V4L2_CTRL_TYPE_INTEGER, | 203 | .type = V4L2_CTRL_TYPE_INTEGER, |
201 | .name = "White Balance", | 204 | .name = "Auto White Balance", |
202 | .minimum = 0, | 205 | .minimum = 0, |
203 | .maximum = 1, | 206 | .maximum = 1, |
204 | .step = 1, | 207 | .step = 1, |
205 | #define WHITE_BALANCE_DEF 0 | 208 | #define AWB_DEF 0 |
206 | .default_value = WHITE_BALANCE_DEF, | 209 | .default_value = AWB_DEF, |
207 | }, | 210 | }, |
208 | .set = sd_setwhitebalance, | 211 | .set = sd_setawb, |
209 | .get = sd_getwhitebalance | 212 | .get = sd_getawb |
210 | }, | 213 | }, |
211 | { | 214 | { |
212 | { | 215 | { |
@@ -244,11 +247,11 @@ static const struct ctrl sd_ctrls[] = { | |||
244 | .minimum = 0x10, | 247 | .minimum = 0x10, |
245 | .maximum = 0x40, | 248 | .maximum = 0x40, |
246 | .step = 1, | 249 | .step = 1, |
247 | #define BLUE_BALANCE_DEF 0x20 | 250 | #define BLUE_GAIN_DEF 0x20 |
248 | .default_value = BLUE_BALANCE_DEF, | 251 | .default_value = BLUE_GAIN_DEF, |
249 | }, | 252 | }, |
250 | .set = sd_setblue_balance, | 253 | .set = sd_setblue_gain, |
251 | .get = sd_getblue_balance, | 254 | .get = sd_getblue_gain, |
252 | }, | 255 | }, |
253 | { | 256 | { |
254 | { | 257 | { |
@@ -258,11 +261,11 @@ static const struct ctrl sd_ctrls[] = { | |||
258 | .minimum = 0x10, | 261 | .minimum = 0x10, |
259 | .maximum = 0x40, | 262 | .maximum = 0x40, |
260 | .step = 1, | 263 | .step = 1, |
261 | #define RED_BALANCE_DEF 0x20 | 264 | #define RED_GAIN_DEF 0x20 |
262 | .default_value = RED_BALANCE_DEF, | 265 | .default_value = RED_GAIN_DEF, |
263 | }, | 266 | }, |
264 | .set = sd_setred_balance, | 267 | .set = sd_setred_gain, |
265 | .get = sd_getred_balance, | 268 | .get = sd_getred_gain, |
266 | }, | 269 | }, |
267 | { | 270 | { |
268 | { | 271 | { |
@@ -272,24 +275,14 @@ static const struct ctrl sd_ctrls[] = { | |||
272 | .minimum = 0x10, | 275 | .minimum = 0x10, |
273 | .maximum = 0x40, | 276 | .maximum = 0x40, |
274 | .step = 1, | 277 | .step = 1, |
275 | #define global_gain_DEF 0x20 | 278 | #define GAIN_DEF 0x20 |
276 | .default_value = global_gain_DEF, | 279 | .default_value = GAIN_DEF, |
277 | }, | 280 | }, |
278 | .set = sd_setglobal_gain, | 281 | .set = sd_setgain, |
279 | .get = sd_getglobal_gain, | 282 | .get = sd_getgain, |
280 | }, | 283 | }, |
281 | }; | 284 | }; |
282 | 285 | ||
283 | static char *effects_control[] = { | ||
284 | "Normal", | ||
285 | "Emboss", /* disabled */ | ||
286 | "Monochrome", | ||
287 | "Sepia", | ||
288 | "Sketch", | ||
289 | "Sun Effect", /* disabled */ | ||
290 | "Negative", | ||
291 | }; | ||
292 | |||
293 | static const struct v4l2_pix_format vga_mode_t16[] = { | 286 | static const struct v4l2_pix_format vga_mode_t16[] = { |
294 | {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 287 | {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
295 | .bytesperline = 160, | 288 | .bytesperline = 160, |
@@ -327,7 +320,6 @@ struct additional_sensor_data { | |||
327 | const u8 data1[10]; | 320 | const u8 data1[10]; |
328 | const u8 data2[9]; | 321 | const u8 data2[9]; |
329 | const u8 data3[9]; | 322 | const u8 data3[9]; |
330 | const u8 data4[4]; | ||
331 | const u8 data5[6]; | 323 | const u8 data5[6]; |
332 | const u8 stream[4]; | 324 | const u8 stream[4]; |
333 | }; | 325 | }; |
@@ -375,7 +367,7 @@ static const u8 n4_lt168g[] = { | |||
375 | }; | 367 | }; |
376 | 368 | ||
377 | static const struct additional_sensor_data sensor_data[] = { | 369 | static const struct additional_sensor_data sensor_data[] = { |
378 | { /* 0: OM6802 */ | 370 | [SENSOR_OM6802] = { |
379 | .n3 = | 371 | .n3 = |
380 | {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04}, | 372 | {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04}, |
381 | .n4 = n4_om6802, | 373 | .n4 = n4_om6802, |
@@ -392,14 +384,12 @@ static const struct additional_sensor_data sensor_data[] = { | |||
392 | .data3 = | 384 | .data3 = |
393 | {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, | 385 | {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, |
394 | 0xff}, | 386 | 0xff}, |
395 | .data4 = /*Freq (50/60Hz). Splitted for test purpose */ | ||
396 | {0x66, 0xca, 0xa8, 0xf0}, | ||
397 | .data5 = /* this could be removed later */ | 387 | .data5 = /* this could be removed later */ |
398 | {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23}, | 388 | {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23}, |
399 | .stream = | 389 | .stream = |
400 | {0x0b, 0x04, 0x0a, 0x78}, | 390 | {0x0b, 0x04, 0x0a, 0x78}, |
401 | }, | 391 | }, |
402 | { /* 1: OTHER */ | 392 | [SENSOR_OTHER] = { |
403 | .n3 = | 393 | .n3 = |
404 | {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00}, | 394 | {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00}, |
405 | .n4 = n4_other, | 395 | .n4 = n4_other, |
@@ -416,14 +406,12 @@ static const struct additional_sensor_data sensor_data[] = { | |||
416 | .data3 = | 406 | .data3 = |
417 | {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96, | 407 | {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96, |
418 | 0xd9}, | 408 | 0xd9}, |
419 | .data4 = | ||
420 | {0x66, 0x00, 0xa8, 0xa8}, | ||
421 | .data5 = | 409 | .data5 = |
422 | {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69}, | 410 | {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69}, |
423 | .stream = | 411 | .stream = |
424 | {0x0b, 0x04, 0x0a, 0x00}, | 412 | {0x0b, 0x04, 0x0a, 0x00}, |
425 | }, | 413 | }, |
426 | { /* 2: TAS5130A */ | 414 | [SENSOR_TAS5130A] = { |
427 | .n3 = | 415 | .n3 = |
428 | {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08}, | 416 | {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08}, |
429 | .n4 = n4_tas5130a, | 417 | .n4 = n4_tas5130a, |
@@ -440,14 +428,12 @@ static const struct additional_sensor_data sensor_data[] = { | |||
440 | .data3 = | 428 | .data3 = |
441 | {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8, | 429 | {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8, |
442 | 0xe0}, | 430 | 0xe0}, |
443 | .data4 = /* Freq (50/60Hz). Splitted for test purpose */ | ||
444 | {0x66, 0x00, 0xa8, 0xe8}, | ||
445 | .data5 = | 431 | .data5 = |
446 | {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20}, | 432 | {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20}, |
447 | .stream = | 433 | .stream = |
448 | {0x0b, 0x04, 0x0a, 0x40}, | 434 | {0x0b, 0x04, 0x0a, 0x40}, |
449 | }, | 435 | }, |
450 | { /* 3: LT168G */ | 436 | [SENSOR_LT168G] = { |
451 | .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00}, | 437 | .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00}, |
452 | .n4 = n4_lt168g, | 438 | .n4 = n4_lt168g, |
453 | .n4sz = sizeof n4_lt168g, | 439 | .n4sz = sizeof n4_lt168g, |
@@ -460,7 +446,6 @@ static const struct additional_sensor_data sensor_data[] = { | |||
460 | 0xff}, | 446 | 0xff}, |
461 | .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6, | 447 | .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6, |
462 | 0xff}, | 448 | 0xff}, |
463 | .data4 = {0x66, 0x41, 0xa8, 0xf0}, | ||
464 | .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b}, | 449 | .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b}, |
465 | .stream = {0x0b, 0x04, 0x0a, 0x28}, | 450 | .stream = {0x0b, 0x04, 0x0a, 0x28}, |
466 | }, | 451 | }, |
@@ -469,6 +454,15 @@ static const struct additional_sensor_data sensor_data[] = { | |||
469 | #define MAX_EFFECTS 7 | 454 | #define MAX_EFFECTS 7 |
470 | /* easily done by soft, this table could be removed, | 455 | /* easily done by soft, this table could be removed, |
471 | * i keep it here just in case */ | 456 | * i keep it here just in case */ |
457 | static char *effects_control[MAX_EFFECTS] = { | ||
458 | "Normal", | ||
459 | "Emboss", /* disabled */ | ||
460 | "Monochrome", | ||
461 | "Sepia", | ||
462 | "Sketch", | ||
463 | "Sun Effect", /* disabled */ | ||
464 | "Negative", | ||
465 | }; | ||
472 | static const u8 effects_table[MAX_EFFECTS][6] = { | 466 | static const u8 effects_table[MAX_EFFECTS][6] = { |
473 | {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */ | 467 | {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */ |
474 | {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */ | 468 | {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */ |
@@ -480,40 +474,41 @@ static const u8 effects_table[MAX_EFFECTS][6] = { | |||
480 | }; | 474 | }; |
481 | 475 | ||
482 | static const u8 gamma_table[GAMMA_MAX][17] = { | 476 | static const u8 gamma_table[GAMMA_MAX][17] = { |
483 | {0x00, 0x3e, 0x69, 0x85, 0x95, 0xa1, 0xae, 0xb9, /* 0 */ | 477 | /* gamma table from cam1690.ini */ |
484 | 0xc2, 0xcb, 0xd4, 0xdb, 0xe3, 0xea, 0xf1, 0xf8, | 478 | {0x00, 0x00, 0x01, 0x04, 0x08, 0x0e, 0x16, 0x21, /* 0 */ |
479 | 0x2e, 0x3d, 0x50, 0x65, 0x7d, 0x99, 0xb8, 0xdb, | ||
485 | 0xff}, | 480 | 0xff}, |
486 | {0x00, 0x33, 0x5a, 0x75, 0x85, 0x93, 0xa1, 0xad, /* 1 */ | 481 | {0x00, 0x01, 0x03, 0x08, 0x0e, 0x16, 0x21, 0x2d, /* 1 */ |
487 | 0xb7, 0xc2, 0xcb, 0xd4, 0xde, 0xe7, 0xf0, 0xf7, | 482 | 0x3c, 0x4d, 0x60, 0x75, 0x8d, 0xa6, 0xc2, 0xe1, |
488 | 0xff}, | 483 | 0xff}, |
489 | {0x00, 0x2f, 0x51, 0x6b, 0x7c, 0x8a, 0x99, 0xa6, /* 2 */ | 484 | {0x00, 0x01, 0x05, 0x0b, 0x12, 0x1c, 0x28, 0x35, /* 2 */ |
490 | 0xb1, 0xbc, 0xc6, 0xd0, 0xdb, 0xe4, 0xed, 0xf6, | 485 | 0x45, 0x56, 0x69, 0x7e, 0x95, 0xad, 0xc7, 0xe3, |
491 | 0xff}, | 486 | 0xff}, |
492 | {0x00, 0x29, 0x48, 0x60, 0x72, 0x81, 0x90, 0x9e, /* 3 */ | 487 | {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f, /* 3 */ |
493 | 0xaa, 0xb5, 0xbf, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5, | 488 | 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6, |
494 | 0xff}, | 489 | 0xff}, |
495 | {0x00, 0x23, 0x3f, 0x55, 0x68, 0x77, 0x86, 0x95, /* 4 */ | 490 | {0x00, 0x04, 0x0B, 0x15, 0x20, 0x2d, 0x3b, 0x4a, /* 4 */ |
496 | 0xa2, 0xad, 0xb9, 0xc6, 0xd2, 0xde, 0xe9, 0xf4, | 491 | 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9, |
497 | 0xff}, | 492 | 0xff}, |
498 | {0x00, 0x1b, 0x33, 0x48, 0x59, 0x69, 0x79, 0x87, /* 5 */ | 493 | {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58, /* 5 */ |
499 | 0x96, 0xa3, 0xb1, 0xbe, 0xcc, 0xda, 0xe7, 0xf3, | 494 | 0x68, 0x79, 0x8b, 0x9d, 0xb0, 0xc4, 0xd7, 0xec, |
500 | 0xff}, | 495 | 0xff}, |
501 | {0x00, 0x02, 0x10, 0x20, 0x32, 0x40, 0x57, 0x67, /* 6 */ | 496 | {0x00, 0x0c, 0x1a, 0x29, 0x38, 0x47, 0x57, 0x67, /* 6 */ |
502 | 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, | 497 | 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, |
503 | 0xff}, | 498 | 0xff}, |
504 | {0x00, 0x02, 0x14, 0x26, 0x38, 0x4a, 0x60, 0x70, /* 7 */ | 499 | {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, /* 7 */ |
505 | 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, | 500 | 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, |
506 | 0xff}, | 501 | 0xff}, |
507 | {0x00, 0x10, 0x22, 0x35, 0x47, 0x5a, 0x69, 0x79, /* 8 */ | 502 | {0x00, 0x15, 0x27, 0x38, 0x49, 0x59, 0x69, 0x79, /* 8 */ |
508 | 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe0, 0xf0, | 503 | 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe2, 0xf0, |
509 | 0xff}, | 504 | 0xff}, |
510 | {0x00, 0x10, 0x26, 0x40, 0x54, 0x65, 0x75, 0x84, /* 9 */ | 505 | {0x00, 0x1c, 0x30, 0x43, 0x54, 0x65, 0x75, 0x84, /* 9 */ |
511 | 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd6, 0xe0, 0xf0, | 506 | 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd8, 0xe5, 0xf2, |
512 | 0xff}, | 507 | 0xff}, |
513 | {0x00, 0x18, 0x2b, 0x44, 0x60, 0x70, 0x80, 0x8e, /* 10 */ | 508 | {0x00, 0x24, 0x3b, 0x4f, 0x60, 0x70, 0x80, 0x8e, /* 10 */ |
514 | 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xd8, 0xe2, 0xf0, | 509 | 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xdc, 0xe8, 0xf3, |
515 | 0xff}, | 510 | 0xff}, |
516 | {0x00, 0x1a, 0x34, 0x52, 0x66, 0x7e, 0x8d, 0x9b, /* 11 */ | 511 | {0x00, 0x2a, 0x3c, 0x5d, 0x6e, 0x7e, 0x8d, 0x9b, /* 11 */ |
517 | 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5, | 512 | 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5, |
518 | 0xff}, | 513 | 0xff}, |
519 | {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */ | 514 | {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */ |
@@ -577,12 +572,11 @@ static void reg_w_buf(struct gspca_dev *gspca_dev, | |||
577 | } else { | 572 | } else { |
578 | u8 *tmpbuf; | 573 | u8 *tmpbuf; |
579 | 574 | ||
580 | tmpbuf = kmalloc(len, GFP_KERNEL); | 575 | tmpbuf = kmemdup(buffer, len, GFP_KERNEL); |
581 | if (!tmpbuf) { | 576 | if (!tmpbuf) { |
582 | err("Out of memory"); | 577 | err("Out of memory"); |
583 | return; | 578 | return; |
584 | } | 579 | } |
585 | memcpy(tmpbuf, buffer, len); | ||
586 | usb_control_msg(gspca_dev->dev, | 580 | usb_control_msg(gspca_dev->dev, |
587 | usb_sndctrlpipe(gspca_dev->dev, 0), | 581 | usb_sndctrlpipe(gspca_dev->dev, 0), |
588 | 0, | 582 | 0, |
@@ -625,7 +619,6 @@ static void reg_w_ixbuf(struct gspca_dev *gspca_dev, | |||
625 | kfree(tmpbuf); | 619 | kfree(tmpbuf); |
626 | } | 620 | } |
627 | 621 | ||
628 | /* Reported as OM6802*/ | ||
629 | static void om6802_sensor_init(struct gspca_dev *gspca_dev) | 622 | static void om6802_sensor_init(struct gspca_dev *gspca_dev) |
630 | { | 623 | { |
631 | int i; | 624 | int i; |
@@ -703,12 +696,12 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
703 | sd->autogain = AUTOGAIN_DEF; | 696 | sd->autogain = AUTOGAIN_DEF; |
704 | sd->mirror = MIRROR_DEF; | 697 | sd->mirror = MIRROR_DEF; |
705 | sd->freq = FREQ_DEF; | 698 | sd->freq = FREQ_DEF; |
706 | sd->whitebalance = WHITE_BALANCE_DEF; | 699 | sd->awb = AWB_DEF; |
707 | sd->sharpness = SHARPNESS_DEF; | 700 | sd->sharpness = SHARPNESS_DEF; |
708 | sd->effect = EFFECTS_DEF; | 701 | sd->effect = EFFECTS_DEF; |
709 | sd->red_balance = RED_BALANCE_DEF; | 702 | sd->red_gain = RED_GAIN_DEF; |
710 | sd->blue_balance = BLUE_BALANCE_DEF; | 703 | sd->blue_gain = BLUE_GAIN_DEF; |
711 | sd->global_gain = global_gain_DEF; | 704 | sd->green_gain = GAIN_DEF * 3 - RED_GAIN_DEF - BLUE_GAIN_DEF; |
712 | 705 | ||
713 | return 0; | 706 | return 0; |
714 | } | 707 | } |
@@ -761,40 +754,59 @@ static void setgamma(struct gspca_dev *gspca_dev) | |||
761 | reg_w_ixbuf(gspca_dev, 0x90, | 754 | reg_w_ixbuf(gspca_dev, 0x90, |
762 | gamma_table[sd->gamma], sizeof gamma_table[0]); | 755 | gamma_table[sd->gamma], sizeof gamma_table[0]); |
763 | } | 756 | } |
764 | static void setglobalgain(struct gspca_dev *gspca_dev) | ||
765 | { | ||
766 | 757 | ||
758 | static void setRGB(struct gspca_dev *gspca_dev) | ||
759 | { | ||
767 | struct sd *sd = (struct sd *) gspca_dev; | 760 | struct sd *sd = (struct sd *) gspca_dev; |
768 | reg_w(gspca_dev, (sd->red_balance << 8) + 0x87); | 761 | u8 all_gain_reg[6] = |
769 | reg_w(gspca_dev, (sd->blue_balance << 8) + 0x88); | 762 | {0x87, 0x00, 0x88, 0x00, 0x89, 0x00}; |
770 | reg_w(gspca_dev, (sd->global_gain << 8) + 0x89); | 763 | |
764 | all_gain_reg[1] = sd->red_gain; | ||
765 | all_gain_reg[3] = sd->blue_gain; | ||
766 | all_gain_reg[5] = sd->green_gain; | ||
767 | reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg); | ||
771 | } | 768 | } |
772 | 769 | ||
773 | /* Generic fnc for r/b balance, exposure and whitebalance */ | 770 | /* Generic fnc for r/b balance, exposure and awb */ |
774 | static void setbalance(struct gspca_dev *gspca_dev) | 771 | static void setawb(struct gspca_dev *gspca_dev) |
775 | { | 772 | { |
776 | struct sd *sd = (struct sd *) gspca_dev; | 773 | struct sd *sd = (struct sd *) gspca_dev; |
774 | u16 reg80; | ||
777 | 775 | ||
778 | /* on whitebalance leave defaults values */ | 776 | reg80 = (sensor_data[sd->sensor].reg80 << 8) | 0x80; |
779 | if (sd->whitebalance) { | 777 | |
780 | reg_w(gspca_dev, 0x3c80); | 778 | /* on awb leave defaults values */ |
781 | } else { | 779 | if (!sd->awb) { |
782 | reg_w(gspca_dev, 0x3880); | ||
783 | /* shoud we wait here.. */ | 780 | /* shoud we wait here.. */ |
784 | /* update and reset 'global gain' with webcam parameters */ | 781 | /* update and reset RGB gains with webcam values */ |
785 | sd->red_balance = reg_r(gspca_dev, 0x0087); | 782 | sd->red_gain = reg_r(gspca_dev, 0x0087); |
786 | sd->blue_balance = reg_r(gspca_dev, 0x0088); | 783 | sd->blue_gain = reg_r(gspca_dev, 0x0088); |
787 | sd->global_gain = reg_r(gspca_dev, 0x0089); | 784 | sd->green_gain = reg_r(gspca_dev, 0x0089); |
788 | setglobalgain(gspca_dev); | 785 | reg80 &= ~0x0400; /* AWB off */ |
789 | } | 786 | } |
790 | 787 | reg_w(gspca_dev, reg80); | |
788 | reg_w(gspca_dev, reg80); | ||
791 | } | 789 | } |
792 | 790 | ||
793 | 791 | static void init_gains(struct gspca_dev *gspca_dev) | |
794 | |||
795 | static void setwhitebalance(struct gspca_dev *gspca_dev) | ||
796 | { | 792 | { |
797 | setbalance(gspca_dev); | 793 | struct sd *sd = (struct sd *) gspca_dev; |
794 | u16 reg80; | ||
795 | u8 all_gain_reg[8] = | ||
796 | {0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x80, 0x00}; | ||
797 | |||
798 | all_gain_reg[1] = sd->red_gain; | ||
799 | all_gain_reg[3] = sd->blue_gain; | ||
800 | all_gain_reg[5] = sd->green_gain; | ||
801 | reg80 = sensor_data[sd->sensor].reg80; | ||
802 | if (!sd->awb) | ||
803 | reg80 &= ~0x04; | ||
804 | all_gain_reg[7] = reg80; | ||
805 | reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg); | ||
806 | |||
807 | reg_w(gspca_dev, (sd->red_gain << 8) + 0x87); | ||
808 | reg_w(gspca_dev, (sd->blue_gain << 8) + 0x88); | ||
809 | reg_w(gspca_dev, (sd->green_gain << 8) + 0x89); | ||
798 | } | 810 | } |
799 | 811 | ||
800 | static void setsharpness(struct gspca_dev *gspca_dev) | 812 | static void setsharpness(struct gspca_dev *gspca_dev) |
@@ -807,6 +819,38 @@ static void setsharpness(struct gspca_dev *gspca_dev) | |||
807 | reg_w(gspca_dev, reg_to_write); | 819 | reg_w(gspca_dev, reg_to_write); |
808 | } | 820 | } |
809 | 821 | ||
822 | static void setfreq(struct gspca_dev *gspca_dev) | ||
823 | { | ||
824 | struct sd *sd = (struct sd *) gspca_dev; | ||
825 | u8 reg66; | ||
826 | u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 }; | ||
827 | |||
828 | switch (sd->sensor) { | ||
829 | case SENSOR_LT168G: | ||
830 | if (sd->freq != 0) | ||
831 | freq[3] = 0xa8; | ||
832 | reg66 = 0x41; | ||
833 | break; | ||
834 | case SENSOR_OM6802: | ||
835 | reg66 = 0xca; | ||
836 | break; | ||
837 | default: | ||
838 | reg66 = 0x40; | ||
839 | break; | ||
840 | } | ||
841 | switch (sd->freq) { | ||
842 | case 0: /* no flicker */ | ||
843 | freq[3] = 0xf0; | ||
844 | break; | ||
845 | case 2: /* 60Hz */ | ||
846 | reg66 &= ~0x40; | ||
847 | break; | ||
848 | } | ||
849 | freq[1] = reg66; | ||
850 | |||
851 | reg_w_buf(gspca_dev, freq, sizeof freq); | ||
852 | } | ||
853 | |||
810 | /* this function is called at probe and resume time */ | 854 | /* this function is called at probe and resume time */ |
811 | static int sd_init(struct gspca_dev *gspca_dev) | 855 | static int sd_init(struct gspca_dev *gspca_dev) |
812 | { | 856 | { |
@@ -901,13 +945,9 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
901 | setgamma(gspca_dev); | 945 | setgamma(gspca_dev); |
902 | setcolors(gspca_dev); | 946 | setcolors(gspca_dev); |
903 | setsharpness(gspca_dev); | 947 | setsharpness(gspca_dev); |
904 | setwhitebalance(gspca_dev); | 948 | init_gains(gspca_dev); |
905 | 949 | setfreq(gspca_dev); | |
906 | reg_w(gspca_dev, 0x2087); /* tied to white balance? */ | ||
907 | reg_w(gspca_dev, 0x2088); | ||
908 | reg_w(gspca_dev, 0x2089); | ||
909 | 950 | ||
910 | reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4); | ||
911 | reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5); | 951 | reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5); |
912 | reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8); | 952 | reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8); |
913 | reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream); | 953 | reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream); |
@@ -926,16 +966,16 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
926 | return 0; | 966 | return 0; |
927 | } | 967 | } |
928 | 968 | ||
929 | static void setflip(struct gspca_dev *gspca_dev) | 969 | static void setmirror(struct gspca_dev *gspca_dev) |
930 | { | 970 | { |
931 | struct sd *sd = (struct sd *) gspca_dev; | 971 | struct sd *sd = (struct sd *) gspca_dev; |
932 | u8 flipcmd[8] = | 972 | u8 hflipcmd[8] = |
933 | {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09}; | 973 | {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09}; |
934 | 974 | ||
935 | if (sd->mirror) | 975 | if (sd->mirror) |
936 | flipcmd[3] = 0x01; | 976 | hflipcmd[3] = 0x01; |
937 | 977 | ||
938 | reg_w_buf(gspca_dev, flipcmd, sizeof flipcmd); | 978 | reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd); |
939 | } | 979 | } |
940 | 980 | ||
941 | static void seteffect(struct gspca_dev *gspca_dev) | 981 | static void seteffect(struct gspca_dev *gspca_dev) |
@@ -956,17 +996,6 @@ static void seteffect(struct gspca_dev *gspca_dev) | |||
956 | reg_w(gspca_dev, 0xfaa6); | 996 | reg_w(gspca_dev, 0xfaa6); |
957 | } | 997 | } |
958 | 998 | ||
959 | static void setlightfreq(struct gspca_dev *gspca_dev) | ||
960 | { | ||
961 | struct sd *sd = (struct sd *) gspca_dev; | ||
962 | u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 }; | ||
963 | |||
964 | if (sd->freq == 2) /* 60hz */ | ||
965 | freq[1] = 0x00; | ||
966 | |||
967 | reg_w_buf(gspca_dev, freq, sizeof freq); | ||
968 | } | ||
969 | |||
970 | /* Is this really needed? | 999 | /* Is this really needed? |
971 | * i added some module parameters for test with some users */ | 1000 | * i added some module parameters for test with some users */ |
972 | static void poll_sensor(struct gspca_dev *gspca_dev) | 1001 | static void poll_sensor(struct gspca_dev *gspca_dev) |
@@ -979,9 +1008,7 @@ static void poll_sensor(struct gspca_dev *gspca_dev) | |||
979 | static const u8 poll2[] = | 1008 | static const u8 poll2[] = |
980 | {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9, | 1009 | {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9, |
981 | 0x73, 0x02, 0x73, 0x02, 0x60, 0x14}; | 1010 | 0x73, 0x02, 0x73, 0x02, 0x60, 0x14}; |
982 | static const u8 poll3[] = | 1011 | static const u8 noise03[] = /* (some differences / ms-drv) */ |
983 | {0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d}; | ||
984 | static const u8 poll4[] = | ||
985 | {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f, | 1012 | {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f, |
986 | 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c, | 1013 | 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c, |
987 | 0xc2, 0x80, 0xc3, 0x10}; | 1014 | 0xc2, 0x80, 0xc3, 0x10}; |
@@ -989,8 +1016,7 @@ static void poll_sensor(struct gspca_dev *gspca_dev) | |||
989 | PDEBUG(D_STREAM, "[Sensor requires polling]"); | 1016 | PDEBUG(D_STREAM, "[Sensor requires polling]"); |
990 | reg_w_buf(gspca_dev, poll1, sizeof poll1); | 1017 | reg_w_buf(gspca_dev, poll1, sizeof poll1); |
991 | reg_w_buf(gspca_dev, poll2, sizeof poll2); | 1018 | reg_w_buf(gspca_dev, poll2, sizeof poll2); |
992 | reg_w_buf(gspca_dev, poll3, sizeof poll3); | 1019 | reg_w_buf(gspca_dev, noise03, sizeof noise03); |
993 | reg_w_buf(gspca_dev, poll4, sizeof poll4); | ||
994 | } | 1020 | } |
995 | 1021 | ||
996 | static int sd_start(struct gspca_dev *gspca_dev) | 1022 | static int sd_start(struct gspca_dev *gspca_dev) |
@@ -1025,12 +1051,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1025 | case SENSOR_OM6802: | 1051 | case SENSOR_OM6802: |
1026 | om6802_sensor_init(gspca_dev); | 1052 | om6802_sensor_init(gspca_dev); |
1027 | break; | 1053 | break; |
1028 | case SENSOR_LT168G: | 1054 | case SENSOR_TAS5130A: |
1029 | break; | ||
1030 | case SENSOR_OTHER: | ||
1031 | break; | ||
1032 | default: | ||
1033 | /* case SENSOR_TAS5130A: */ | ||
1034 | i = 0; | 1055 | i = 0; |
1035 | for (;;) { | 1056 | for (;;) { |
1036 | reg_w_buf(gspca_dev, tas5130a_sensor_init[i], | 1057 | reg_w_buf(gspca_dev, tas5130a_sensor_init[i], |
@@ -1047,7 +1068,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1047 | break; | 1068 | break; |
1048 | } | 1069 | } |
1049 | sensor = &sensor_data[sd->sensor]; | 1070 | sensor = &sensor_data[sd->sensor]; |
1050 | reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4); | 1071 | setfreq(gspca_dev); |
1051 | reg_r(gspca_dev, 0x0012); | 1072 | reg_r(gspca_dev, 0x0012); |
1052 | reg_w_buf(gspca_dev, t2, sizeof t2); | 1073 | reg_w_buf(gspca_dev, t2, sizeof t2); |
1053 | reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3); | 1074 | reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3); |
@@ -1080,7 +1101,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1080 | u8 *data, /* isoc packet */ | 1101 | u8 *data, /* isoc packet */ |
1081 | int len) /* iso packet length */ | 1102 | int len) /* iso packet length */ |
1082 | { | 1103 | { |
1083 | static u8 ffd9[] = { 0xff, 0xd9 }; | 1104 | int pkt_type; |
1084 | 1105 | ||
1085 | if (data[0] == 0x5a) { | 1106 | if (data[0] == 0x5a) { |
1086 | /* Control Packet, after this came the header again, | 1107 | /* Control Packet, after this came the header again, |
@@ -1090,84 +1111,88 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1090 | } | 1111 | } |
1091 | data += 2; | 1112 | data += 2; |
1092 | len -= 2; | 1113 | len -= 2; |
1093 | if (data[0] == 0xff && data[1] == 0xd8) { | 1114 | if (data[0] == 0xff && data[1] == 0xd8) |
1094 | /* extra bytes....., could be processed too but would be | 1115 | pkt_type = FIRST_PACKET; |
1095 | * a waste of time, right now leave the application and | 1116 | else if (data[len - 2] == 0xff && data[len - 1] == 0xd9) |
1096 | * libjpeg do it for ourserlves.. */ | 1117 | pkt_type = LAST_PACKET; |
1097 | gspca_frame_add(gspca_dev, LAST_PACKET, | 1118 | else |
1098 | ffd9, 2); | 1119 | pkt_type = INTER_PACKET; |
1099 | gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); | 1120 | gspca_frame_add(gspca_dev, pkt_type, data, len); |
1100 | return; | ||
1101 | } | ||
1102 | |||
1103 | if (data[len - 2] == 0xff && data[len - 1] == 0xd9) { | ||
1104 | /* Just in case, i have seen packets with the marker, | ||
1105 | * other's do not include it... */ | ||
1106 | len -= 2; | ||
1107 | } | ||
1108 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | ||
1109 | } | 1121 | } |
1110 | 1122 | ||
1111 | 1123 | static int sd_setblue_gain(struct gspca_dev *gspca_dev, __s32 val) | |
1112 | static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val) | ||
1113 | { | 1124 | { |
1114 | struct sd *sd = (struct sd *) gspca_dev; | 1125 | struct sd *sd = (struct sd *) gspca_dev; |
1115 | 1126 | ||
1116 | sd->blue_balance = val; | 1127 | sd->blue_gain = val; |
1117 | if (gspca_dev->streaming) | 1128 | if (gspca_dev->streaming) |
1118 | reg_w(gspca_dev, (val << 8) + 0x88); | 1129 | reg_w(gspca_dev, (val << 8) + 0x88); |
1119 | return 0; | 1130 | return 0; |
1120 | } | 1131 | } |
1121 | 1132 | ||
1122 | static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val) | 1133 | static int sd_getblue_gain(struct gspca_dev *gspca_dev, __s32 *val) |
1123 | { | 1134 | { |
1124 | struct sd *sd = (struct sd *) gspca_dev; | 1135 | struct sd *sd = (struct sd *) gspca_dev; |
1125 | 1136 | ||
1126 | *val = sd->blue_balance; | 1137 | *val = sd->blue_gain; |
1127 | return 0; | 1138 | return 0; |
1128 | } | 1139 | } |
1129 | 1140 | ||
1130 | static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val) | 1141 | static int sd_setred_gain(struct gspca_dev *gspca_dev, __s32 val) |
1131 | { | 1142 | { |
1132 | struct sd *sd = (struct sd *) gspca_dev; | 1143 | struct sd *sd = (struct sd *) gspca_dev; |
1133 | 1144 | ||
1134 | sd->red_balance = val; | 1145 | sd->red_gain = val; |
1135 | if (gspca_dev->streaming) | 1146 | if (gspca_dev->streaming) |
1136 | reg_w(gspca_dev, (val << 8) + 0x87); | 1147 | reg_w(gspca_dev, (val << 8) + 0x87); |
1137 | 1148 | ||
1138 | return 0; | 1149 | return 0; |
1139 | } | 1150 | } |
1140 | 1151 | ||
1141 | static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val) | 1152 | static int sd_getred_gain(struct gspca_dev *gspca_dev, __s32 *val) |
1142 | { | 1153 | { |
1143 | struct sd *sd = (struct sd *) gspca_dev; | 1154 | struct sd *sd = (struct sd *) gspca_dev; |
1144 | 1155 | ||
1145 | *val = sd->red_balance; | 1156 | *val = sd->red_gain; |
1146 | return 0; | 1157 | return 0; |
1147 | } | 1158 | } |
1148 | 1159 | ||
1149 | 1160 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) | |
1150 | |||
1151 | static int sd_setglobal_gain(struct gspca_dev *gspca_dev, __s32 val) | ||
1152 | { | 1161 | { |
1153 | struct sd *sd = (struct sd *) gspca_dev; | 1162 | struct sd *sd = (struct sd *) gspca_dev; |
1163 | u16 psg, nsg; | ||
1164 | |||
1165 | psg = sd->red_gain + sd->blue_gain + sd->green_gain; | ||
1166 | nsg = val * 3; | ||
1167 | sd->red_gain = sd->red_gain * nsg / psg; | ||
1168 | if (sd->red_gain > 0x40) | ||
1169 | sd->red_gain = 0x40; | ||
1170 | else if (sd->red_gain < 0x10) | ||
1171 | sd->red_gain = 0x10; | ||
1172 | sd->blue_gain = sd->blue_gain * nsg / psg; | ||
1173 | if (sd->blue_gain > 0x40) | ||
1174 | sd->blue_gain = 0x40; | ||
1175 | else if (sd->blue_gain < 0x10) | ||
1176 | sd->blue_gain = 0x10; | ||
1177 | sd->green_gain = sd->green_gain * nsg / psg; | ||
1178 | if (sd->green_gain > 0x40) | ||
1179 | sd->green_gain = 0x40; | ||
1180 | else if (sd->green_gain < 0x10) | ||
1181 | sd->green_gain = 0x10; | ||
1154 | 1182 | ||
1155 | sd->global_gain = val; | ||
1156 | if (gspca_dev->streaming) | 1183 | if (gspca_dev->streaming) |
1157 | setglobalgain(gspca_dev); | 1184 | setRGB(gspca_dev); |
1158 | |||
1159 | return 0; | 1185 | return 0; |
1160 | } | 1186 | } |
1161 | 1187 | ||
1162 | static int sd_getglobal_gain(struct gspca_dev *gspca_dev, __s32 *val) | 1188 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) |
1163 | { | 1189 | { |
1164 | struct sd *sd = (struct sd *) gspca_dev; | 1190 | struct sd *sd = (struct sd *) gspca_dev; |
1165 | 1191 | ||
1166 | *val = sd->global_gain; | 1192 | *val = (sd->red_gain + sd->blue_gain + sd->green_gain) / 3; |
1167 | return 0; | 1193 | return 0; |
1168 | } | 1194 | } |
1169 | 1195 | ||
1170 | |||
1171 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 1196 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) |
1172 | { | 1197 | { |
1173 | struct sd *sd = (struct sd *) gspca_dev; | 1198 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -1186,35 +1211,35 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | |||
1186 | return *val; | 1211 | return *val; |
1187 | } | 1212 | } |
1188 | 1213 | ||
1189 | static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val) | 1214 | static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val) |
1190 | { | 1215 | { |
1191 | struct sd *sd = (struct sd *) gspca_dev; | 1216 | struct sd *sd = (struct sd *) gspca_dev; |
1192 | 1217 | ||
1193 | sd->whitebalance = val; | 1218 | sd->awb = val; |
1194 | if (gspca_dev->streaming) | 1219 | if (gspca_dev->streaming) |
1195 | setwhitebalance(gspca_dev); | 1220 | setawb(gspca_dev); |
1196 | return 0; | 1221 | return 0; |
1197 | } | 1222 | } |
1198 | 1223 | ||
1199 | static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val) | 1224 | static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val) |
1200 | { | 1225 | { |
1201 | struct sd *sd = (struct sd *) gspca_dev; | 1226 | struct sd *sd = (struct sd *) gspca_dev; |
1202 | 1227 | ||
1203 | *val = sd->whitebalance; | 1228 | *val = sd->awb; |
1204 | return *val; | 1229 | return *val; |
1205 | } | 1230 | } |
1206 | 1231 | ||
1207 | static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val) | 1232 | static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val) |
1208 | { | 1233 | { |
1209 | struct sd *sd = (struct sd *) gspca_dev; | 1234 | struct sd *sd = (struct sd *) gspca_dev; |
1210 | 1235 | ||
1211 | sd->mirror = val; | 1236 | sd->mirror = val; |
1212 | if (gspca_dev->streaming) | 1237 | if (gspca_dev->streaming) |
1213 | setflip(gspca_dev); | 1238 | setmirror(gspca_dev); |
1214 | return 0; | 1239 | return 0; |
1215 | } | 1240 | } |
1216 | 1241 | ||
1217 | static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val) | 1242 | static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val) |
1218 | { | 1243 | { |
1219 | struct sd *sd = (struct sd *) gspca_dev; | 1244 | struct sd *sd = (struct sd *) gspca_dev; |
1220 | 1245 | ||
@@ -1300,7 +1325,7 @@ static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) | |||
1300 | 1325 | ||
1301 | sd->freq = val; | 1326 | sd->freq = val; |
1302 | if (gspca_dev->streaming) | 1327 | if (gspca_dev->streaming) |
1303 | setlightfreq(gspca_dev); | 1328 | setfreq(gspca_dev); |
1304 | return 0; | 1329 | return 0; |
1305 | } | 1330 | } |
1306 | 1331 | ||
@@ -1368,7 +1393,8 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, | |||
1368 | case V4L2_CID_EFFECTS: | 1393 | case V4L2_CID_EFFECTS: |
1369 | if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) { | 1394 | if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) { |
1370 | strncpy((char *) menu->name, | 1395 | strncpy((char *) menu->name, |
1371 | effects_control[menu->index], 32); | 1396 | effects_control[menu->index], |
1397 | sizeof menu->name); | ||
1372 | return 0; | 1398 | return 0; |
1373 | } | 1399 | } |
1374 | break; | 1400 | break; |
diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c index c7b6eb1e04d5..d9c5bf3449d4 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/video/gspca/tv8532.c | |||
@@ -30,29 +30,46 @@ MODULE_LICENSE("GPL"); | |||
30 | struct sd { | 30 | struct sd { |
31 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 31 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
32 | 32 | ||
33 | __u16 brightness; | 33 | __u16 exposure; |
34 | __u16 gain; | ||
34 | 35 | ||
35 | __u8 packet; | 36 | __u8 packet; |
36 | }; | 37 | }; |
37 | 38 | ||
38 | /* V4L2 controls supported by the driver */ | 39 | /* V4L2 controls supported by the driver */ |
39 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | 40 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); |
40 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | 41 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); |
42 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | ||
43 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | ||
41 | 44 | ||
42 | static const struct ctrl sd_ctrls[] = { | 45 | static const struct ctrl sd_ctrls[] = { |
43 | { | 46 | { |
44 | { | 47 | { |
45 | .id = V4L2_CID_BRIGHTNESS, | 48 | .id = V4L2_CID_EXPOSURE, |
46 | .type = V4L2_CTRL_TYPE_INTEGER, | 49 | .type = V4L2_CTRL_TYPE_INTEGER, |
47 | .name = "Brightness", | 50 | .name = "Exposure", |
48 | .minimum = 1, | 51 | .minimum = 1, |
49 | .maximum = 0x15f, /* = 352 - 1 */ | 52 | .maximum = 0x18f, |
50 | .step = 1, | 53 | .step = 1, |
51 | #define BRIGHTNESS_DEF 0x14c | 54 | #define EXPOSURE_DEF 0x18f |
52 | .default_value = BRIGHTNESS_DEF, | 55 | .default_value = EXPOSURE_DEF, |
53 | }, | 56 | }, |
54 | .set = sd_setbrightness, | 57 | .set = sd_setexposure, |
55 | .get = sd_getbrightness, | 58 | .get = sd_getexposure, |
59 | }, | ||
60 | { | ||
61 | { | ||
62 | .id = V4L2_CID_GAIN, | ||
63 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
64 | .name = "Gain", | ||
65 | .minimum = 0, | ||
66 | .maximum = 0x7ff, | ||
67 | .step = 1, | ||
68 | #define GAIN_DEF 0x100 | ||
69 | .default_value = GAIN_DEF, | ||
70 | }, | ||
71 | .set = sd_setgain, | ||
72 | .get = sd_getgain, | ||
56 | }, | 73 | }, |
57 | }; | 74 | }; |
58 | 75 | ||
@@ -92,6 +109,14 @@ static const struct v4l2_pix_format sif_mode[] = { | |||
92 | #define R14_AD_ROW_BEGINL 0x14 | 109 | #define R14_AD_ROW_BEGINL 0x14 |
93 | #define R15_AD_ROWBEGINH 0x15 | 110 | #define R15_AD_ROWBEGINH 0x15 |
94 | #define R1C_AD_EXPOSE_TIMEL 0x1c | 111 | #define R1C_AD_EXPOSE_TIMEL 0x1c |
112 | #define R20_GAIN_G1L 0x20 | ||
113 | #define R21_GAIN_G1H 0x21 | ||
114 | #define R22_GAIN_RL 0x22 | ||
115 | #define R23_GAIN_RH 0x23 | ||
116 | #define R24_GAIN_BL 0x24 | ||
117 | #define R25_GAIN_BH 0x25 | ||
118 | #define R26_GAIN_G2L 0x26 | ||
119 | #define R27_GAIN_G2H 0x27 | ||
95 | #define R28_QUANT 0x28 | 120 | #define R28_QUANT 0x28 |
96 | #define R29_LINE 0x29 | 121 | #define R29_LINE 0x29 |
97 | #define R2C_POLARITY 0x2c | 122 | #define R2C_POLARITY 0x2c |
@@ -129,18 +154,6 @@ static const u8 eeprom_data[][3] = { | |||
129 | {0x05, 0x09, 0xf1}, | 154 | {0x05, 0x09, 0xf1}, |
130 | }; | 155 | }; |
131 | 156 | ||
132 | static int reg_r(struct gspca_dev *gspca_dev, | ||
133 | __u16 index) | ||
134 | { | ||
135 | usb_control_msg(gspca_dev->dev, | ||
136 | usb_rcvctrlpipe(gspca_dev->dev, 0), | ||
137 | 0x03, | ||
138 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
139 | 0, /* value */ | ||
140 | index, gspca_dev->usb_buf, 1, | ||
141 | 500); | ||
142 | return gspca_dev->usb_buf[0]; | ||
143 | } | ||
144 | 157 | ||
145 | /* write 1 byte */ | 158 | /* write 1 byte */ |
146 | static void reg_w1(struct gspca_dev *gspca_dev, | 159 | static void reg_w1(struct gspca_dev *gspca_dev, |
@@ -183,7 +196,6 @@ static void tv_8532WriteEEprom(struct gspca_dev *gspca_dev) | |||
183 | } | 196 | } |
184 | reg_w1(gspca_dev, R07_TABLE_LEN, i); | 197 | reg_w1(gspca_dev, R07_TABLE_LEN, i); |
185 | reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Close); | 198 | reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Close); |
186 | msleep(10); | ||
187 | } | 199 | } |
188 | 200 | ||
189 | /* this function is called at probe time */ | 201 | /* this function is called at probe time */ |
@@ -197,53 +209,13 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
197 | cam->cam_mode = sif_mode; | 209 | cam->cam_mode = sif_mode; |
198 | cam->nmodes = ARRAY_SIZE(sif_mode); | 210 | cam->nmodes = ARRAY_SIZE(sif_mode); |
199 | 211 | ||
200 | sd->brightness = BRIGHTNESS_DEF; | 212 | sd->exposure = EXPOSURE_DEF; |
213 | sd->gain = GAIN_DEF; | ||
201 | return 0; | 214 | return 0; |
202 | } | 215 | } |
203 | 216 | ||
204 | static void tv_8532ReadRegisters(struct gspca_dev *gspca_dev) | ||
205 | { | ||
206 | int i; | ||
207 | static u8 reg_tb[] = { | ||
208 | R0C_AD_WIDTHL, | ||
209 | R0D_AD_WIDTHH, | ||
210 | R28_QUANT, | ||
211 | R29_LINE, | ||
212 | R2C_POLARITY, | ||
213 | R2D_POINT, | ||
214 | R2E_POINTH, | ||
215 | R2F_POINTB, | ||
216 | R30_POINTBH, | ||
217 | R2A_HIGH_BUDGET, | ||
218 | R2B_LOW_BUDGET, | ||
219 | R34_VID, | ||
220 | R35_VIDH, | ||
221 | R36_PID, | ||
222 | R37_PIDH, | ||
223 | R83_AD_IDH, | ||
224 | R10_AD_COL_BEGINL, | ||
225 | R11_AD_COL_BEGINH, | ||
226 | R14_AD_ROW_BEGINL, | ||
227 | R15_AD_ROWBEGINH, | ||
228 | 0 | ||
229 | }; | ||
230 | |||
231 | i = 0; | ||
232 | do { | ||
233 | reg_r(gspca_dev, reg_tb[i]); | ||
234 | i++; | ||
235 | } while (reg_tb[i] != 0); | ||
236 | } | ||
237 | |||
238 | static void tv_8532_setReg(struct gspca_dev *gspca_dev) | 217 | static void tv_8532_setReg(struct gspca_dev *gspca_dev) |
239 | { | 218 | { |
240 | reg_w1(gspca_dev, R10_AD_COL_BEGINL, 0x44); | ||
241 | /* begin active line */ | ||
242 | reg_w1(gspca_dev, R11_AD_COL_BEGINH, 0x00); | ||
243 | /* mirror and digital gain */ | ||
244 | reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); | ||
245 | /* = 0x84 */ | ||
246 | |||
247 | reg_w1(gspca_dev, R3B_Test3, 0x0a); /* Test0Sel = 10 */ | 219 | reg_w1(gspca_dev, R3B_Test3, 0x0a); /* Test0Sel = 10 */ |
248 | /******************************************************/ | 220 | /******************************************************/ |
249 | reg_w1(gspca_dev, R0E_AD_HEIGHTL, 0x90); | 221 | reg_w1(gspca_dev, R0E_AD_HEIGHTL, 0x90); |
@@ -255,100 +227,43 @@ static void tv_8532_setReg(struct gspca_dev *gspca_dev) | |||
255 | /* mirror and digital gain */ | 227 | /* mirror and digital gain */ |
256 | reg_w1(gspca_dev, R14_AD_ROW_BEGINL, 0x0a); | 228 | reg_w1(gspca_dev, R14_AD_ROW_BEGINL, 0x0a); |
257 | 229 | ||
258 | reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x00); | ||
259 | reg_w1(gspca_dev, R94_AD_BITCONTROL, 0x02); | 230 | reg_w1(gspca_dev, R94_AD_BITCONTROL, 0x02); |
260 | |||
261 | reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Close); | ||
262 | |||
263 | reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x00); | 231 | reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x00); |
264 | reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); | 232 | reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); |
265 | /* = 0x84 */ | 233 | /* = 0x84 */ |
266 | } | 234 | } |
267 | 235 | ||
268 | static void tv_8532_PollReg(struct gspca_dev *gspca_dev) | ||
269 | { | ||
270 | int i; | ||
271 | |||
272 | /* strange polling from tgc */ | ||
273 | for (i = 0; i < 10; i++) { | ||
274 | reg_w1(gspca_dev, R2C_POLARITY, 0x10); | ||
275 | reg_w1(gspca_dev, R00_PART_CONTROL, | ||
276 | LATENT_CHANGE | EXPO_CHANGE); | ||
277 | reg_w1(gspca_dev, R31_UPD, 0x01); | ||
278 | } | ||
279 | } | ||
280 | |||
281 | /* this function is called at probe and resume time */ | 236 | /* this function is called at probe and resume time */ |
282 | static int sd_init(struct gspca_dev *gspca_dev) | 237 | static int sd_init(struct gspca_dev *gspca_dev) |
283 | { | 238 | { |
284 | tv_8532WriteEEprom(gspca_dev); | 239 | tv_8532WriteEEprom(gspca_dev); |
285 | 240 | ||
286 | reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x32); /* slope begin 1,7V, | ||
287 | * slope rate 2 */ | ||
288 | reg_w1(gspca_dev, R94_AD_BITCONTROL, 0x00); | ||
289 | tv_8532ReadRegisters(gspca_dev); | ||
290 | reg_w1(gspca_dev, R3B_Test3, 0x0b); | ||
291 | reg_w2(gspca_dev, R0E_AD_HEIGHTL, 0x0190); | ||
292 | reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, 0x018f); | ||
293 | reg_w1(gspca_dev, R0C_AD_WIDTHL, 0xe8); | ||
294 | reg_w1(gspca_dev, R0D_AD_WIDTHH, 0x03); | ||
295 | |||
296 | /*******************************************************************/ | ||
297 | reg_w1(gspca_dev, R28_QUANT, 0x90); | ||
298 | /* no compress - fixed Q - quant 0 */ | ||
299 | reg_w1(gspca_dev, R29_LINE, 0x81); | ||
300 | /* 0x84; // CIF | 4 packet 0x29 */ | ||
301 | |||
302 | /************************************************/ | ||
303 | reg_w1(gspca_dev, R2C_POLARITY, 0x10); | ||
304 | /* 0x48; //0x08; 0x2c */ | ||
305 | reg_w1(gspca_dev, R2D_POINT, 0x14); | ||
306 | /* 0x38; 0x2d */ | ||
307 | reg_w1(gspca_dev, R2E_POINTH, 0x01); | ||
308 | /* 0x04; 0x2e */ | ||
309 | reg_w1(gspca_dev, R2F_POINTB, 0x12); | ||
310 | /* 0x04; 0x2f */ | ||
311 | reg_w1(gspca_dev, R30_POINTBH, 0x01); | ||
312 | /* 0x04; 0x30 */ | ||
313 | reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); | ||
314 | /* 0x00<-0x84 */ | ||
315 | /*************************************************/ | ||
316 | reg_w1(gspca_dev, R31_UPD, 0x01); /* update registers */ | ||
317 | msleep(200); | ||
318 | reg_w1(gspca_dev, R31_UPD, 0x00); /* end update */ | ||
319 | /*************************************************/ | ||
320 | tv_8532_setReg(gspca_dev); | ||
321 | /*************************************************/ | ||
322 | reg_w1(gspca_dev, R3B_Test3, 0x0b); /* Test0Sel = 11 = GPIO */ | ||
323 | /*************************************************/ | ||
324 | tv_8532_setReg(gspca_dev); | ||
325 | /*************************************************/ | ||
326 | tv_8532_PollReg(gspca_dev); | ||
327 | return 0; | 241 | return 0; |
328 | } | 242 | } |
329 | 243 | ||
330 | static void setbrightness(struct gspca_dev *gspca_dev) | 244 | static void setexposure(struct gspca_dev *gspca_dev) |
331 | { | 245 | { |
332 | struct sd *sd = (struct sd *) gspca_dev; | 246 | struct sd *sd = (struct sd *) gspca_dev; |
333 | 247 | ||
334 | reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, sd->brightness); | 248 | reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, sd->exposure); |
335 | reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); | 249 | reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); |
336 | /* 0x84 */ | 250 | /* 0x84 */ |
337 | } | 251 | } |
338 | 252 | ||
339 | /* -- start the camera -- */ | 253 | static void setgain(struct gspca_dev *gspca_dev) |
340 | static int sd_start(struct gspca_dev *gspca_dev) | ||
341 | { | 254 | { |
342 | struct sd *sd = (struct sd *) gspca_dev; | 255 | struct sd *sd = (struct sd *) gspca_dev; |
343 | 256 | ||
344 | reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x32); /* slope begin 1,7V, | 257 | reg_w2(gspca_dev, R20_GAIN_G1L, sd->gain); |
345 | * slope rate 2 */ | 258 | reg_w2(gspca_dev, R22_GAIN_RL, sd->gain); |
346 | reg_w1(gspca_dev, R94_AD_BITCONTROL, 0x00); | 259 | reg_w2(gspca_dev, R24_GAIN_BL, sd->gain); |
347 | tv_8532ReadRegisters(gspca_dev); | 260 | reg_w2(gspca_dev, R26_GAIN_G2L, sd->gain); |
348 | reg_w1(gspca_dev, R3B_Test3, 0x0b); | 261 | } |
349 | 262 | ||
350 | reg_w2(gspca_dev, R0E_AD_HEIGHTL, 0x0190); | 263 | /* -- start the camera -- */ |
351 | setbrightness(gspca_dev); | 264 | static int sd_start(struct gspca_dev *gspca_dev) |
265 | { | ||
266 | struct sd *sd = (struct sd *) gspca_dev; | ||
352 | 267 | ||
353 | reg_w1(gspca_dev, R0C_AD_WIDTHL, 0xe8); /* 0x20; 0x0c */ | 268 | reg_w1(gspca_dev, R0C_AD_WIDTHL, 0xe8); /* 0x20; 0x0c */ |
354 | reg_w1(gspca_dev, R0D_AD_WIDTHH, 0x03); | 269 | reg_w1(gspca_dev, R0D_AD_WIDTHH, 0x03); |
@@ -371,19 +286,15 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
371 | reg_w1(gspca_dev, R2E_POINTH, 0x01); | 286 | reg_w1(gspca_dev, R2E_POINTH, 0x01); |
372 | reg_w1(gspca_dev, R2F_POINTB, 0x12); | 287 | reg_w1(gspca_dev, R2F_POINTB, 0x12); |
373 | reg_w1(gspca_dev, R30_POINTBH, 0x01); | 288 | reg_w1(gspca_dev, R30_POINTBH, 0x01); |
374 | reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); | 289 | |
290 | tv_8532_setReg(gspca_dev); | ||
291 | |||
292 | setexposure(gspca_dev); | ||
293 | setgain(gspca_dev); | ||
294 | |||
375 | /************************************************/ | 295 | /************************************************/ |
376 | reg_w1(gspca_dev, R31_UPD, 0x01); /* update registers */ | 296 | reg_w1(gspca_dev, R31_UPD, 0x01); /* update registers */ |
377 | msleep(200); | 297 | msleep(200); |
378 | reg_w1(gspca_dev, R31_UPD, 0x00); /* end update */ | ||
379 | /************************************************/ | ||
380 | tv_8532_setReg(gspca_dev); | ||
381 | /************************************************/ | ||
382 | reg_w1(gspca_dev, R3B_Test3, 0x0b); /* Test0Sel = 11 = GPIO */ | ||
383 | /************************************************/ | ||
384 | tv_8532_setReg(gspca_dev); | ||
385 | /************************************************/ | ||
386 | tv_8532_PollReg(gspca_dev); | ||
387 | reg_w1(gspca_dev, R31_UPD, 0x00); /* end update */ | 298 | reg_w1(gspca_dev, R31_UPD, 0x00); /* end update */ |
388 | 299 | ||
389 | gspca_dev->empty_packet = 0; /* check the empty packets */ | 300 | gspca_dev->empty_packet = 0; /* check the empty packets */ |
@@ -428,21 +339,39 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
428 | data + gspca_dev->width + 5, gspca_dev->width); | 339 | data + gspca_dev->width + 5, gspca_dev->width); |
429 | } | 340 | } |
430 | 341 | ||
431 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 342 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) |
343 | { | ||
344 | struct sd *sd = (struct sd *) gspca_dev; | ||
345 | |||
346 | sd->exposure = val; | ||
347 | if (gspca_dev->streaming) | ||
348 | setexposure(gspca_dev); | ||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) | ||
353 | { | ||
354 | struct sd *sd = (struct sd *) gspca_dev; | ||
355 | |||
356 | *val = sd->exposure; | ||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) | ||
432 | { | 361 | { |
433 | struct sd *sd = (struct sd *) gspca_dev; | 362 | struct sd *sd = (struct sd *) gspca_dev; |
434 | 363 | ||
435 | sd->brightness = val; | 364 | sd->gain = val; |
436 | if (gspca_dev->streaming) | 365 | if (gspca_dev->streaming) |
437 | setbrightness(gspca_dev); | 366 | setgain(gspca_dev); |
438 | return 0; | 367 | return 0; |
439 | } | 368 | } |
440 | 369 | ||
441 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | 370 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) |
442 | { | 371 | { |
443 | struct sd *sd = (struct sd *) gspca_dev; | 372 | struct sd *sd = (struct sd *) gspca_dev; |
444 | 373 | ||
445 | *val = sd->brightness; | 374 | *val = sd->gain; |
446 | return 0; | 375 | return 0; |
447 | } | 376 | } |
448 | 377 | ||
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 732c3dfe46ff..031266a4081b 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c | |||
@@ -2748,11 +2748,11 @@ static const u8 poxxxx_init_common[][4] = { | |||
2748 | {0xb3, 0x04, 0x15, 0xcc}, | 2748 | {0xb3, 0x04, 0x15, 0xcc}, |
2749 | {0xb3, 0x20, 0x00, 0xcc}, | 2749 | {0xb3, 0x20, 0x00, 0xcc}, |
2750 | {0xb3, 0x21, 0x00, 0xcc}, | 2750 | {0xb3, 0x21, 0x00, 0xcc}, |
2751 | {0xb3, 0x22, 0x04, 0xcc}, | 2751 | {0xb3, 0x22, 0x04, 0xcc}, /* sensor height = 1024 */ |
2752 | {0xb3, 0x23, 0x00, 0xcc}, | 2752 | {0xb3, 0x23, 0x00, 0xcc}, |
2753 | {0xb3, 0x14, 0x00, 0xcc}, | 2753 | {0xb3, 0x14, 0x00, 0xcc}, |
2754 | {0xb3, 0x15, 0x00, 0xcc}, | 2754 | {0xb3, 0x15, 0x00, 0xcc}, |
2755 | {0xb3, 0x16, 0x04, 0xcc}, | 2755 | {0xb3, 0x16, 0x04, 0xcc}, /* sensor width = 1280 */ |
2756 | {0xb3, 0x17, 0xff, 0xcc}, | 2756 | {0xb3, 0x17, 0xff, 0xcc}, |
2757 | {0xb3, 0x2c, 0x03, 0xcc}, | 2757 | {0xb3, 0x2c, 0x03, 0xcc}, |
2758 | {0xb3, 0x2d, 0x56, 0xcc}, | 2758 | {0xb3, 0x2d, 0x56, 0xcc}, |
@@ -2919,7 +2919,7 @@ static const u8 poxxxx_initVGA[][4] = { | |||
2919 | {0x00, 0x20, 0x11, 0xaa}, | 2919 | {0x00, 0x20, 0x11, 0xaa}, |
2920 | {0x00, 0x33, 0x38, 0xaa}, | 2920 | {0x00, 0x33, 0x38, 0xaa}, |
2921 | {0x00, 0xbb, 0x0d, 0xaa}, | 2921 | {0x00, 0xbb, 0x0d, 0xaa}, |
2922 | {0xb3, 0x22, 0x01, 0xcc}, | 2922 | {0xb3, 0x22, 0x01, 0xcc}, /* change to 640x480 */ |
2923 | {0xb3, 0x23, 0xe0, 0xcc}, | 2923 | {0xb3, 0x23, 0xe0, 0xcc}, |
2924 | {0xb3, 0x16, 0x02, 0xcc}, | 2924 | {0xb3, 0x16, 0x02, 0xcc}, |
2925 | {0xb3, 0x17, 0x7f, 0xcc}, | 2925 | {0xb3, 0x17, 0x7f, 0xcc}, |
@@ -2935,7 +2935,7 @@ static const u8 poxxxx_initQVGA[][4] = { | |||
2935 | {0x00, 0x20, 0x33, 0xaa}, | 2935 | {0x00, 0x20, 0x33, 0xaa}, |
2936 | {0x00, 0x33, 0x38, 0xaa}, | 2936 | {0x00, 0x33, 0x38, 0xaa}, |
2937 | {0x00, 0xbb, 0x0d, 0xaa}, | 2937 | {0x00, 0xbb, 0x0d, 0xaa}, |
2938 | {0xb3, 0x22, 0x00, 0xcc}, | 2938 | {0xb3, 0x22, 0x00, 0xcc}, /* change to 320x240 */ |
2939 | {0xb3, 0x23, 0xf0, 0xcc}, | 2939 | {0xb3, 0x23, 0xf0, 0xcc}, |
2940 | {0xb3, 0x16, 0x01, 0xcc}, | 2940 | {0xb3, 0x16, 0x01, 0xcc}, |
2941 | {0xb3, 0x17, 0x3f, 0xcc}, | 2941 | {0xb3, 0x17, 0x3f, 0xcc}, |
@@ -3068,37 +3068,84 @@ static const struct sensor_info vc0323_probe_data[] = { | |||
3068 | }; | 3068 | }; |
3069 | 3069 | ||
3070 | /* read 'len' bytes in gspca_dev->usb_buf */ | 3070 | /* read 'len' bytes in gspca_dev->usb_buf */ |
3071 | static void reg_r(struct gspca_dev *gspca_dev, | 3071 | static void reg_r_i(struct gspca_dev *gspca_dev, |
3072 | u16 req, | 3072 | u16 req, |
3073 | u16 index, | 3073 | u16 index, |
3074 | u16 len) | 3074 | u16 len) |
3075 | { | 3075 | { |
3076 | usb_control_msg(gspca_dev->dev, | 3076 | int ret; |
3077 | |||
3078 | if (gspca_dev->usb_err < 0) | ||
3079 | return; | ||
3080 | ret = usb_control_msg(gspca_dev->dev, | ||
3077 | usb_rcvctrlpipe(gspca_dev->dev, 0), | 3081 | usb_rcvctrlpipe(gspca_dev->dev, 0), |
3078 | req, | 3082 | req, |
3079 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 3083 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
3080 | 1, /* value */ | 3084 | 1, /* value */ |
3081 | index, gspca_dev->usb_buf, len, | 3085 | index, gspca_dev->usb_buf, len, |
3082 | 500); | 3086 | 500); |
3087 | if (ret < 0) { | ||
3088 | PDEBUG(D_ERR, "reg_r err %d", ret); | ||
3089 | gspca_dev->usb_err = ret; | ||
3090 | } | ||
3091 | } | ||
3092 | static void reg_r(struct gspca_dev *gspca_dev, | ||
3093 | u16 req, | ||
3094 | u16 index, | ||
3095 | u16 len) | ||
3096 | { | ||
3097 | reg_r_i(gspca_dev, req, index, len); | ||
3098 | #ifdef GSPCA_DEBUG | ||
3099 | if (gspca_dev->usb_err < 0) | ||
3100 | return; | ||
3101 | if (len == 1) | ||
3102 | PDEBUG(D_USBI, "GET %02x 0001 %04x %02x", req, index, | ||
3103 | gspca_dev->usb_buf[0]); | ||
3104 | else | ||
3105 | PDEBUG(D_USBI, "GET %02x 0001 %04x %02x %02x %02x", | ||
3106 | req, index, | ||
3107 | gspca_dev->usb_buf[0], | ||
3108 | gspca_dev->usb_buf[1], | ||
3109 | gspca_dev->usb_buf[2]); | ||
3110 | #endif | ||
3083 | } | 3111 | } |
3084 | 3112 | ||
3085 | static void reg_w(struct usb_device *dev, | 3113 | static void reg_w_i(struct gspca_dev *gspca_dev, |
3086 | u16 req, | 3114 | u16 req, |
3087 | u16 value, | 3115 | u16 value, |
3088 | u16 index) | 3116 | u16 index) |
3089 | { | 3117 | { |
3090 | usb_control_msg(dev, | 3118 | int ret; |
3091 | usb_sndctrlpipe(dev, 0), | 3119 | |
3120 | if (gspca_dev->usb_err < 0) | ||
3121 | return; | ||
3122 | ret = usb_control_msg(gspca_dev->dev, | ||
3123 | usb_sndctrlpipe(gspca_dev->dev, 0), | ||
3092 | req, | 3124 | req, |
3093 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 3125 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
3094 | value, index, NULL, 0, | 3126 | value, index, NULL, 0, |
3095 | 500); | 3127 | 500); |
3128 | if (ret < 0) { | ||
3129 | PDEBUG(D_ERR, "reg_w err %d", ret); | ||
3130 | gspca_dev->usb_err = ret; | ||
3131 | } | ||
3132 | } | ||
3133 | static void reg_w(struct gspca_dev *gspca_dev, | ||
3134 | u16 req, | ||
3135 | u16 value, | ||
3136 | u16 index) | ||
3137 | { | ||
3138 | #ifdef GSPCA_DEBUG | ||
3139 | if (gspca_dev->usb_err < 0) | ||
3140 | return; | ||
3141 | PDEBUG(D_USBO, "SET %02x %04x %04x", req, value, index); | ||
3142 | #endif | ||
3143 | reg_w_i(gspca_dev, req, value, index); | ||
3096 | } | 3144 | } |
3097 | 3145 | ||
3098 | static u16 read_sensor_register(struct gspca_dev *gspca_dev, | 3146 | static u16 read_sensor_register(struct gspca_dev *gspca_dev, |
3099 | u16 address) | 3147 | u16 address) |
3100 | { | 3148 | { |
3101 | struct usb_device *dev = gspca_dev->dev; | ||
3102 | u8 ldata, mdata, hdata; | 3149 | u8 ldata, mdata, hdata; |
3103 | int retry = 50; | 3150 | int retry = 50; |
3104 | 3151 | ||
@@ -3108,8 +3155,8 @@ static u16 read_sensor_register(struct gspca_dev *gspca_dev, | |||
3108 | gspca_dev->usb_buf[0]); | 3155 | gspca_dev->usb_buf[0]); |
3109 | return 0; | 3156 | return 0; |
3110 | } | 3157 | } |
3111 | reg_w(dev, 0xa0, address, 0xb33a); | 3158 | reg_w(gspca_dev, 0xa0, address, 0xb33a); |
3112 | reg_w(dev, 0xa0, 0x02, 0xb339); | 3159 | reg_w(gspca_dev, 0xa0, 0x02, 0xb339); |
3113 | 3160 | ||
3114 | do { | 3161 | do { |
3115 | reg_r(gspca_dev, 0xa1, 0xb33b, 1); | 3162 | reg_r(gspca_dev, 0xa1, 0xb33b, 1); |
@@ -3136,15 +3183,15 @@ static u16 read_sensor_register(struct gspca_dev *gspca_dev, | |||
3136 | static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) | 3183 | static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) |
3137 | { | 3184 | { |
3138 | struct sd *sd = (struct sd *) gspca_dev; | 3185 | struct sd *sd = (struct sd *) gspca_dev; |
3139 | struct usb_device *dev = gspca_dev->dev; | ||
3140 | int i, n; | 3186 | int i, n; |
3141 | u16 value; | 3187 | u16 value; |
3142 | const struct sensor_info *ptsensor_info; | 3188 | const struct sensor_info *ptsensor_info; |
3143 | 3189 | ||
3144 | /*fixme: should also check the other sensor (back mi1320_soc, front mc501cb)*/ | 3190 | /*fixme: should also check the other sensor (back mi1320_soc, front mc501cb)*/ |
3145 | if (sd->flags & FL_SAMSUNG) { | 3191 | if (sd->flags & FL_SAMSUNG) { |
3146 | reg_w(dev, 0xa0, 0x01, 0xb301); | 3192 | reg_w(gspca_dev, 0xa0, 0x01, 0xb301); |
3147 | reg_w(dev, 0x89, 0xf0ff, 0xffff); /* select the back sensor */ | 3193 | reg_w(gspca_dev, 0x89, 0xf0ff, 0xffff); |
3194 | /* select the back sensor */ | ||
3148 | } | 3195 | } |
3149 | 3196 | ||
3150 | reg_r(gspca_dev, 0xa1, 0xbfcf, 1); | 3197 | reg_r(gspca_dev, 0xa1, 0xbfcf, 1); |
@@ -3158,13 +3205,13 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) | |||
3158 | n = ARRAY_SIZE(vc0323_probe_data); | 3205 | n = ARRAY_SIZE(vc0323_probe_data); |
3159 | } | 3206 | } |
3160 | for (i = 0; i < n; i++) { | 3207 | for (i = 0; i < n; i++) { |
3161 | reg_w(dev, 0xa0, 0x02, 0xb334); | 3208 | reg_w(gspca_dev, 0xa0, 0x02, 0xb334); |
3162 | reg_w(dev, 0xa0, ptsensor_info->m1, 0xb300); | 3209 | reg_w(gspca_dev, 0xa0, ptsensor_info->m1, 0xb300); |
3163 | reg_w(dev, 0xa0, ptsensor_info->m2, 0xb300); | 3210 | reg_w(gspca_dev, 0xa0, ptsensor_info->m2, 0xb300); |
3164 | reg_w(dev, 0xa0, 0x01, 0xb308); | 3211 | reg_w(gspca_dev, 0xa0, 0x01, 0xb308); |
3165 | reg_w(dev, 0xa0, 0x0c, 0xb309); | 3212 | reg_w(gspca_dev, 0xa0, 0x0c, 0xb309); |
3166 | reg_w(dev, 0xa0, ptsensor_info->I2cAdd, 0xb335); | 3213 | reg_w(gspca_dev, 0xa0, ptsensor_info->I2cAdd, 0xb335); |
3167 | reg_w(dev, 0xa0, ptsensor_info->op, 0xb301); | 3214 | reg_w(gspca_dev, 0xa0, ptsensor_info->op, 0xb301); |
3168 | value = read_sensor_register(gspca_dev, ptsensor_info->IdAdd); | 3215 | value = read_sensor_register(gspca_dev, ptsensor_info->IdAdd); |
3169 | if (value == 0 && ptsensor_info->IdAdd == 0x82) | 3216 | if (value == 0 && ptsensor_info->IdAdd == 0x82) |
3170 | value = read_sensor_register(gspca_dev, 0x83); | 3217 | value = read_sensor_register(gspca_dev, 0x83); |
@@ -3192,26 +3239,33 @@ static void i2c_write(struct gspca_dev *gspca_dev, | |||
3192 | u8 reg, const u8 *val, | 3239 | u8 reg, const u8 *val, |
3193 | u8 size) /* 1 or 2 */ | 3240 | u8 size) /* 1 or 2 */ |
3194 | { | 3241 | { |
3195 | struct usb_device *dev = gspca_dev->dev; | ||
3196 | int retry; | 3242 | int retry; |
3197 | 3243 | ||
3198 | reg_r(gspca_dev, 0xa1, 0xb33f, 1); | 3244 | #ifdef GSPCA_DEBUG |
3245 | if (gspca_dev->usb_err < 0) | ||
3246 | return; | ||
3247 | if (size == 1) | ||
3248 | PDEBUG(D_USBO, "i2c_w %02x %02x", reg, *val); | ||
3249 | else | ||
3250 | PDEBUG(D_USBO, "i2c_w %02x %02x%02x", reg, *val, val[1]); | ||
3251 | #endif | ||
3252 | reg_r_i(gspca_dev, 0xa1, 0xb33f, 1); | ||
3199 | /*fixme:should check if (!(gspca_dev->usb_buf[0] & 0x02)) error*/ | 3253 | /*fixme:should check if (!(gspca_dev->usb_buf[0] & 0x02)) error*/ |
3200 | reg_w(dev, 0xa0, size, 0xb334); | 3254 | reg_w_i(gspca_dev, 0xa0, size, 0xb334); |
3201 | reg_w(dev, 0xa0, reg, 0xb33a); | 3255 | reg_w_i(gspca_dev, 0xa0, reg, 0xb33a); |
3202 | reg_w(dev, 0xa0, val[0], 0xb336); | 3256 | reg_w_i(gspca_dev, 0xa0, val[0], 0xb336); |
3203 | if (size > 1) | 3257 | if (size > 1) |
3204 | reg_w(dev, 0xa0, val[1], 0xb337); | 3258 | reg_w_i(gspca_dev, 0xa0, val[1], 0xb337); |
3205 | reg_w(dev, 0xa0, 0x01, 0xb339); | 3259 | reg_w_i(gspca_dev, 0xa0, 0x01, 0xb339); |
3206 | retry = 4; | 3260 | retry = 4; |
3207 | do { | 3261 | do { |
3208 | reg_r(gspca_dev, 0xa1, 0xb33b, 1); | 3262 | reg_r_i(gspca_dev, 0xa1, 0xb33b, 1); |
3209 | if (gspca_dev->usb_buf[0] == 0) | 3263 | if (gspca_dev->usb_buf[0] == 0) |
3210 | break; | 3264 | break; |
3211 | msleep(20); | 3265 | msleep(20); |
3212 | } while (--retry > 0); | 3266 | } while (--retry > 0); |
3213 | if (retry <= 0) | 3267 | if (retry <= 0) |
3214 | PDEBUG(D_ERR, "i2c_write failed"); | 3268 | PDEBUG(D_ERR, "i2c_write timeout"); |
3215 | } | 3269 | } |
3216 | 3270 | ||
3217 | static void put_tab_to_reg(struct gspca_dev *gspca_dev, | 3271 | static void put_tab_to_reg(struct gspca_dev *gspca_dev, |
@@ -3221,13 +3275,12 @@ static void put_tab_to_reg(struct gspca_dev *gspca_dev, | |||
3221 | u16 ad = addr; | 3275 | u16 ad = addr; |
3222 | 3276 | ||
3223 | for (j = 0; j < tabsize; j++) | 3277 | for (j = 0; j < tabsize; j++) |
3224 | reg_w(gspca_dev->dev, 0xa0, tab[j], ad++); | 3278 | reg_w(gspca_dev, 0xa0, tab[j], ad++); |
3225 | } | 3279 | } |
3226 | 3280 | ||
3227 | static void usb_exchange(struct gspca_dev *gspca_dev, | 3281 | static void usb_exchange(struct gspca_dev *gspca_dev, |
3228 | const u8 data[][4]) | 3282 | const u8 data[][4]) |
3229 | { | 3283 | { |
3230 | struct usb_device *dev = gspca_dev->dev; | ||
3231 | int i = 0; | 3284 | int i = 0; |
3232 | 3285 | ||
3233 | for (;;) { | 3286 | for (;;) { |
@@ -3235,7 +3288,7 @@ static void usb_exchange(struct gspca_dev *gspca_dev, | |||
3235 | default: | 3288 | default: |
3236 | return; | 3289 | return; |
3237 | case 0xcc: /* normal write */ | 3290 | case 0xcc: /* normal write */ |
3238 | reg_w(dev, 0xa0, data[i][2], | 3291 | reg_w(gspca_dev, 0xa0, data[i][2], |
3239 | (data[i][0]) << 8 | data[i][1]); | 3292 | (data[i][0]) << 8 | data[i][1]); |
3240 | break; | 3293 | break; |
3241 | case 0xaa: /* i2c op */ | 3294 | case 0xaa: /* i2c op */ |
@@ -3259,7 +3312,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
3259 | const struct usb_device_id *id) | 3312 | const struct usb_device_id *id) |
3260 | { | 3313 | { |
3261 | struct sd *sd = (struct sd *) gspca_dev; | 3314 | struct sd *sd = (struct sd *) gspca_dev; |
3262 | struct usb_device *dev = gspca_dev->dev; | ||
3263 | struct cam *cam; | 3315 | struct cam *cam; |
3264 | int sensor; | 3316 | int sensor; |
3265 | static u8 npkt[] = { /* number of packets per ISOC message */ | 3317 | static u8 npkt[] = { /* number of packets per ISOC message */ |
@@ -3363,13 +3415,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
3363 | if (sd->sensor == SENSOR_OV7670) | 3415 | if (sd->sensor == SENSOR_OV7670) |
3364 | sd->flags |= FL_HFLIP | FL_VFLIP; | 3416 | sd->flags |= FL_HFLIP | FL_VFLIP; |
3365 | 3417 | ||
3366 | if (sd->bridge == BRIDGE_VC0321) { | ||
3367 | reg_r(gspca_dev, 0x8a, 0, 3); | ||
3368 | reg_w(dev, 0x87, 0x00, 0x0f0f); | ||
3369 | |||
3370 | reg_r(gspca_dev, 0x8b, 0, 3); | ||
3371 | reg_w(dev, 0x88, 0x00, 0x0202); | ||
3372 | } | ||
3373 | return 0; | 3418 | return 0; |
3374 | } | 3419 | } |
3375 | 3420 | ||
@@ -3378,15 +3423,21 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
3378 | { | 3423 | { |
3379 | struct sd *sd = (struct sd *) gspca_dev; | 3424 | struct sd *sd = (struct sd *) gspca_dev; |
3380 | 3425 | ||
3381 | if (sd->sensor == SENSOR_POxxxx) { | 3426 | if (sd->bridge == BRIDGE_VC0321) { |
3382 | reg_r(gspca_dev, 0xa1, 0xb300, 1); | 3427 | reg_r(gspca_dev, 0x8a, 0, 3); |
3383 | if (gspca_dev->usb_buf[0] != 0) { | 3428 | reg_w(gspca_dev, 0x87, 0x00, 0x0f0f); |
3384 | reg_w(gspca_dev->dev, 0xa0, 0x26, 0xb300); | 3429 | reg_r(gspca_dev, 0x8b, 0, 3); |
3385 | reg_w(gspca_dev->dev, 0xa0, 0x04, 0xb300); | 3430 | reg_w(gspca_dev, 0x88, 0x00, 0x0202); |
3386 | reg_w(gspca_dev->dev, 0xa0, 0x00, 0xb300); | 3431 | if (sd->sensor == SENSOR_POxxxx) { |
3432 | reg_r(gspca_dev, 0xa1, 0xb300, 1); | ||
3433 | if (gspca_dev->usb_buf[0] != 0) { | ||
3434 | reg_w(gspca_dev, 0xa0, 0x26, 0xb300); | ||
3435 | reg_w(gspca_dev, 0xa0, 0x04, 0xb300); | ||
3436 | reg_w(gspca_dev, 0xa0, 0x00, 0xb300); | ||
3437 | } | ||
3387 | } | 3438 | } |
3388 | } | 3439 | } |
3389 | return 0; | 3440 | return gspca_dev->usb_err; |
3390 | } | 3441 | } |
3391 | 3442 | ||
3392 | static void setbrightness(struct gspca_dev *gspca_dev) | 3443 | static void setbrightness(struct gspca_dev *gspca_dev) |
@@ -3516,17 +3567,17 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
3516 | 3567 | ||
3517 | /*fixme: back sensor only*/ | 3568 | /*fixme: back sensor only*/ |
3518 | if (sd->flags & FL_SAMSUNG) { | 3569 | if (sd->flags & FL_SAMSUNG) { |
3519 | reg_w(gspca_dev->dev, 0x89, 0xf0ff, 0xffff); | 3570 | reg_w(gspca_dev, 0x89, 0xf0ff, 0xffff); |
3520 | reg_w(gspca_dev->dev, 0xa9, 0x8348, 0x000e); | 3571 | reg_w(gspca_dev, 0xa9, 0x8348, 0x000e); |
3521 | reg_w(gspca_dev->dev, 0xa9, 0x0000, 0x001a); | 3572 | reg_w(gspca_dev, 0xa9, 0x0000, 0x001a); |
3522 | } | 3573 | } |
3523 | 3574 | ||
3524 | /* Assume start use the good resolution from gspca_dev->mode */ | 3575 | /* Assume start use the good resolution from gspca_dev->mode */ |
3525 | if (sd->bridge == BRIDGE_VC0321) { | 3576 | if (sd->bridge == BRIDGE_VC0321) { |
3526 | reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfec); | 3577 | reg_w(gspca_dev, 0xa0, 0xff, 0xbfec); |
3527 | reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfed); | 3578 | reg_w(gspca_dev, 0xa0, 0xff, 0xbfed); |
3528 | reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfee); | 3579 | reg_w(gspca_dev, 0xa0, 0xff, 0xbfee); |
3529 | reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfef); | 3580 | reg_w(gspca_dev, 0xa0, 0xff, 0xbfef); |
3530 | sd->image_offset = 46; | 3581 | sd->image_offset = 46; |
3531 | } else { | 3582 | } else { |
3532 | if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].pixelformat | 3583 | if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].pixelformat |
@@ -3617,7 +3668,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
3617 | init = poxxxx_initVGA; | 3668 | init = poxxxx_initVGA; |
3618 | usb_exchange(gspca_dev, init); | 3669 | usb_exchange(gspca_dev, init); |
3619 | reg_r(gspca_dev, 0x8c, 0x0000, 3); | 3670 | reg_r(gspca_dev, 0x8c, 0x0000, 3); |
3620 | reg_w(gspca_dev->dev, 0xa0, | 3671 | reg_w(gspca_dev, 0xa0, |
3621 | gspca_dev->usb_buf[2] & 1 ? 0 : 1, | 3672 | gspca_dev->usb_buf[2] & 1 ? 0 : 1, |
3622 | 0xb35c); | 3673 | 0xb35c); |
3623 | msleep(300); | 3674 | msleep(300); |
@@ -3635,10 +3686,10 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
3635 | switch (sd->sensor) { | 3686 | switch (sd->sensor) { |
3636 | case SENSOR_PO1200: | 3687 | case SENSOR_PO1200: |
3637 | case SENSOR_HV7131R: | 3688 | case SENSOR_HV7131R: |
3638 | reg_w(gspca_dev->dev, 0x89, 0x0400, 0x1415); | 3689 | reg_w(gspca_dev, 0x89, 0x0400, 0x1415); |
3639 | break; | 3690 | break; |
3640 | case SENSOR_MI1310_SOC: | 3691 | case SENSOR_MI1310_SOC: |
3641 | reg_w(gspca_dev->dev, 0x89, 0x058c, 0x0000); | 3692 | reg_w(gspca_dev, 0x89, 0x058c, 0x0000); |
3642 | break; | 3693 | break; |
3643 | } | 3694 | } |
3644 | msleep(100); | 3695 | msleep(100); |
@@ -3648,9 +3699,9 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
3648 | } | 3699 | } |
3649 | switch (sd->sensor) { | 3700 | switch (sd->sensor) { |
3650 | case SENSOR_OV7670: | 3701 | case SENSOR_OV7670: |
3651 | reg_w(gspca_dev->dev, 0x87, 0xffff, 0xffff); | 3702 | reg_w(gspca_dev, 0x87, 0xffff, 0xffff); |
3652 | reg_w(gspca_dev->dev, 0x88, 0xff00, 0xf0f1); | 3703 | reg_w(gspca_dev, 0x88, 0xff00, 0xf0f1); |
3653 | reg_w(gspca_dev->dev, 0xa0, 0x0000, 0xbfff); | 3704 | reg_w(gspca_dev, 0xa0, 0x0000, 0xbfff); |
3654 | break; | 3705 | break; |
3655 | case SENSOR_POxxxx: | 3706 | case SENSOR_POxxxx: |
3656 | setcolors(gspca_dev); | 3707 | setcolors(gspca_dev); |
@@ -3659,51 +3710,49 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
3659 | 3710 | ||
3660 | /* led on */ | 3711 | /* led on */ |
3661 | msleep(80); | 3712 | msleep(80); |
3662 | reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff); | 3713 | reg_w(gspca_dev, 0x89, 0xffff, 0xfdff); |
3663 | usb_exchange(gspca_dev, poxxxx_init_end_2); | 3714 | usb_exchange(gspca_dev, poxxxx_init_end_2); |
3664 | break; | 3715 | break; |
3665 | } | 3716 | } |
3666 | return 0; | 3717 | return gspca_dev->usb_err; |
3667 | } | 3718 | } |
3668 | 3719 | ||
3669 | static void sd_stopN(struct gspca_dev *gspca_dev) | 3720 | static void sd_stopN(struct gspca_dev *gspca_dev) |
3670 | { | 3721 | { |
3671 | struct usb_device *dev = gspca_dev->dev; | ||
3672 | struct sd *sd = (struct sd *) gspca_dev; | 3722 | struct sd *sd = (struct sd *) gspca_dev; |
3673 | 3723 | ||
3674 | switch (sd->sensor) { | 3724 | switch (sd->sensor) { |
3675 | case SENSOR_MI1310_SOC: | 3725 | case SENSOR_MI1310_SOC: |
3676 | reg_w(dev, 0x89, 0x058c, 0x00ff); | 3726 | reg_w(gspca_dev, 0x89, 0x058c, 0x00ff); |
3677 | break; | 3727 | break; |
3678 | case SENSOR_POxxxx: | 3728 | case SENSOR_POxxxx: |
3679 | return; | 3729 | return; |
3680 | default: | 3730 | default: |
3681 | if (!(sd->flags & FL_SAMSUNG)) | 3731 | if (!(sd->flags & FL_SAMSUNG)) |
3682 | reg_w(dev, 0x89, 0xffff, 0xffff); | 3732 | reg_w(gspca_dev, 0x89, 0xffff, 0xffff); |
3683 | break; | 3733 | break; |
3684 | } | 3734 | } |
3685 | reg_w(dev, 0xa0, 0x01, 0xb301); | 3735 | reg_w(gspca_dev, 0xa0, 0x01, 0xb301); |
3686 | reg_w(dev, 0xa0, 0x09, 0xb003); | 3736 | reg_w(gspca_dev, 0xa0, 0x09, 0xb003); |
3687 | } | 3737 | } |
3688 | 3738 | ||
3689 | /* called on streamoff with alt 0 and on disconnect */ | 3739 | /* called on streamoff with alt 0 and on disconnect */ |
3690 | static void sd_stop0(struct gspca_dev *gspca_dev) | 3740 | static void sd_stop0(struct gspca_dev *gspca_dev) |
3691 | { | 3741 | { |
3692 | struct usb_device *dev = gspca_dev->dev; | ||
3693 | struct sd *sd = (struct sd *) gspca_dev; | 3742 | struct sd *sd = (struct sd *) gspca_dev; |
3694 | 3743 | ||
3695 | if (!gspca_dev->present) | 3744 | if (!gspca_dev->present) |
3696 | return; | 3745 | return; |
3697 | /*fixme: is this useful?*/ | 3746 | /*fixme: is this useful?*/ |
3698 | if (sd->sensor == SENSOR_MI1310_SOC) | 3747 | if (sd->sensor == SENSOR_MI1310_SOC) |
3699 | reg_w(dev, 0x89, 0x058c, 0x00ff); | 3748 | reg_w(gspca_dev, 0x89, 0x058c, 0x00ff); |
3700 | else if (!(sd->flags & FL_SAMSUNG)) | 3749 | else if (!(sd->flags & FL_SAMSUNG)) |
3701 | reg_w(dev, 0x89, 0xffff, 0xffff); | 3750 | reg_w(gspca_dev, 0x89, 0xffff, 0xffff); |
3702 | 3751 | ||
3703 | if (sd->sensor == SENSOR_POxxxx) { | 3752 | if (sd->sensor == SENSOR_POxxxx) { |
3704 | reg_w(dev, 0xa0, 0x26, 0xb300); | 3753 | reg_w(gspca_dev, 0xa0, 0x26, 0xb300); |
3705 | reg_w(dev, 0xa0, 0x04, 0xb300); | 3754 | reg_w(gspca_dev, 0xa0, 0x04, 0xb300); |
3706 | reg_w(dev, 0xa0, 0x00, 0xb300); | 3755 | reg_w(gspca_dev, 0xa0, 0x00, 0xb300); |
3707 | } | 3756 | } |
3708 | } | 3757 | } |
3709 | 3758 | ||
@@ -3726,17 +3775,12 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
3726 | /* The vc0321 sends some additional data after sending the complete | 3775 | /* The vc0321 sends some additional data after sending the complete |
3727 | * frame, we ignore this. */ | 3776 | * frame, we ignore this. */ |
3728 | if (sd->bridge == BRIDGE_VC0321) { | 3777 | if (sd->bridge == BRIDGE_VC0321) { |
3729 | struct gspca_frame *frame; | 3778 | int size, l; |
3730 | int l; | ||
3731 | 3779 | ||
3732 | frame = gspca_get_i_frame(gspca_dev); | 3780 | l = gspca_dev->image_len; |
3733 | if (frame == NULL) { | 3781 | size = gspca_dev->frsz; |
3734 | gspca_dev->last_packet_type = DISCARD_PACKET; | 3782 | if (len > size - l) |
3735 | return; | 3783 | len = size - l; |
3736 | } | ||
3737 | l = frame->data_end - frame->data; | ||
3738 | if (len > frame->v4l2_buf.length - l) | ||
3739 | len = frame->v4l2_buf.length - l; | ||
3740 | } | 3784 | } |
3741 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | 3785 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
3742 | } | 3786 | } |
@@ -3748,7 +3792,7 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | |||
3748 | sd->brightness = val; | 3792 | sd->brightness = val; |
3749 | if (gspca_dev->streaming) | 3793 | if (gspca_dev->streaming) |
3750 | setbrightness(gspca_dev); | 3794 | setbrightness(gspca_dev); |
3751 | return 0; | 3795 | return gspca_dev->usb_err; |
3752 | } | 3796 | } |
3753 | 3797 | ||
3754 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | 3798 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -3766,7 +3810,7 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | |||
3766 | sd->contrast = val; | 3810 | sd->contrast = val; |
3767 | if (gspca_dev->streaming) | 3811 | if (gspca_dev->streaming) |
3768 | setcontrast(gspca_dev); | 3812 | setcontrast(gspca_dev); |
3769 | return 0; | 3813 | return gspca_dev->usb_err; |
3770 | } | 3814 | } |
3771 | 3815 | ||
3772 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | 3816 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -3784,7 +3828,7 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) | |||
3784 | sd->colors = val; | 3828 | sd->colors = val; |
3785 | if (gspca_dev->streaming) | 3829 | if (gspca_dev->streaming) |
3786 | setcolors(gspca_dev); | 3830 | setcolors(gspca_dev); |
3787 | return 0; | 3831 | return gspca_dev->usb_err; |
3788 | } | 3832 | } |
3789 | 3833 | ||
3790 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) | 3834 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -3802,7 +3846,7 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) | |||
3802 | sd->hflip = val; | 3846 | sd->hflip = val; |
3803 | if (gspca_dev->streaming) | 3847 | if (gspca_dev->streaming) |
3804 | sethvflip(gspca_dev); | 3848 | sethvflip(gspca_dev); |
3805 | return 0; | 3849 | return gspca_dev->usb_err; |
3806 | } | 3850 | } |
3807 | 3851 | ||
3808 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) | 3852 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -3820,7 +3864,7 @@ static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) | |||
3820 | sd->vflip = val; | 3864 | sd->vflip = val; |
3821 | if (gspca_dev->streaming) | 3865 | if (gspca_dev->streaming) |
3822 | sethvflip(gspca_dev); | 3866 | sethvflip(gspca_dev); |
3823 | return 0; | 3867 | return gspca_dev->usb_err; |
3824 | } | 3868 | } |
3825 | 3869 | ||
3826 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | 3870 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -3838,7 +3882,7 @@ static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) | |||
3838 | sd->lightfreq = val; | 3882 | sd->lightfreq = val; |
3839 | if (gspca_dev->streaming) | 3883 | if (gspca_dev->streaming) |
3840 | setlightfreq(gspca_dev); | 3884 | setlightfreq(gspca_dev); |
3841 | return 0; | 3885 | return gspca_dev->usb_err; |
3842 | } | 3886 | } |
3843 | 3887 | ||
3844 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) | 3888 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -3856,7 +3900,7 @@ static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) | |||
3856 | sd->sharpness = val; | 3900 | sd->sharpness = val; |
3857 | if (gspca_dev->streaming) | 3901 | if (gspca_dev->streaming) |
3858 | setsharpness(gspca_dev); | 3902 | setsharpness(gspca_dev); |
3859 | return 0; | 3903 | return gspca_dev->usb_err; |
3860 | } | 3904 | } |
3861 | 3905 | ||
3862 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val) | 3906 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val) |
diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/video/gspca/w996Xcf.c index 2fffe203bed8..38a68591ce48 100644 --- a/drivers/media/video/gspca/w996Xcf.c +++ b/drivers/media/video/gspca/w996Xcf.c | |||
@@ -31,14 +31,10 @@ | |||
31 | the sensor drivers to v4l2 sub drivers, and properly split of this | 31 | the sensor drivers to v4l2 sub drivers, and properly split of this |
32 | driver from ov519.c */ | 32 | driver from ov519.c */ |
33 | 33 | ||
34 | /* The CONEX_CAM define for jpeg.h needs renaming, now its used here too */ | ||
35 | #define CONEX_CAM | ||
36 | #include "jpeg.h" | ||
37 | |||
38 | #define W9968CF_I2C_BUS_DELAY 4 /* delay in us for I2C bit r/w operations */ | 34 | #define W9968CF_I2C_BUS_DELAY 4 /* delay in us for I2C bit r/w operations */ |
39 | 35 | ||
40 | #define Y_QUANTABLE (sd->jpeg_hdr + JPEG_QT0_OFFSET) | 36 | #define Y_QUANTABLE (&sd->jpeg_hdr[JPEG_QT0_OFFSET]) |
41 | #define UV_QUANTABLE (sd->jpeg_hdr + JPEG_QT1_OFFSET) | 37 | #define UV_QUANTABLE (&sd->jpeg_hdr[JPEG_QT1_OFFSET]) |
42 | 38 | ||
43 | static const struct v4l2_pix_format w9968cf_vga_mode[] = { | 39 | static const struct v4l2_pix_format w9968cf_vga_mode[] = { |
44 | {160, 120, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, | 40 | {160, 120, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, |
@@ -509,11 +505,6 @@ static int w9968cf_mode_init_regs(struct sd *sd) | |||
509 | if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == | 505 | if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == |
510 | V4L2_PIX_FMT_JPEG) { | 506 | V4L2_PIX_FMT_JPEG) { |
511 | /* We may get called multiple times (usb isoc bw negotiat.) */ | 507 | /* We may get called multiple times (usb isoc bw negotiat.) */ |
512 | if (!sd->jpeg_hdr) | ||
513 | sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); | ||
514 | if (!sd->jpeg_hdr) | ||
515 | return -ENOMEM; | ||
516 | |||
517 | jpeg_define(sd->jpeg_hdr, sd->gspca_dev.height, | 508 | jpeg_define(sd->jpeg_hdr, sd->gspca_dev.height, |
518 | sd->gspca_dev.width, 0x22); /* JPEG 420 */ | 509 | sd->gspca_dev.width, 0x22); /* JPEG 420 */ |
519 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | 510 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); |
@@ -562,9 +553,6 @@ static void w9968cf_stop0(struct sd *sd) | |||
562 | reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */ | 553 | reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */ |
563 | reg_w(sd, 0x16, 0x0000); /* stop video capture */ | 554 | reg_w(sd, 0x16, 0x0000); /* stop video capture */ |
564 | } | 555 | } |
565 | |||
566 | kfree(sd->jpeg_hdr); | ||
567 | sd->jpeg_hdr = NULL; | ||
568 | } | 556 | } |
569 | 557 | ||
570 | /* The w9968cf docs say that a 0 sized packet means EOF (and also SOF | 558 | /* The w9968cf docs say that a 0 sized packet means EOF (and also SOF |
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index d02aa5c8472a..4473f0fb8b73 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #define MODULE_NAME "zc3xx" | 22 | #define MODULE_NAME "zc3xx" |
23 | 23 | ||
24 | #include <linux/input.h> | 24 | #include <linux/input.h> |
25 | #include <linux/slab.h> | ||
26 | #include "gspca.h" | 25 | #include "gspca.h" |
27 | #include "jpeg.h" | 26 | #include "jpeg.h" |
28 | 27 | ||
@@ -40,15 +39,16 @@ static int force_sensor = -1; | |||
40 | struct sd { | 39 | struct sd { |
41 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 40 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
42 | 41 | ||
42 | u8 brightness; | ||
43 | u8 contrast; | 43 | u8 contrast; |
44 | u8 gamma; | 44 | u8 gamma; |
45 | u8 autogain; | 45 | u8 autogain; |
46 | u8 lightfreq; | 46 | u8 lightfreq; |
47 | u8 sharpness; | 47 | u8 sharpness; |
48 | u8 quality; /* image quality */ | 48 | u8 quality; /* image quality */ |
49 | #define QUALITY_MIN 40 | 49 | #define QUALITY_MIN 50 |
50 | #define QUALITY_MAX 60 | 50 | #define QUALITY_MAX 80 |
51 | #define QUALITY_DEF 50 | 51 | #define QUALITY_DEF 70 |
52 | 52 | ||
53 | u8 sensor; /* Type of image sensor chip */ | 53 | u8 sensor; /* Type of image sensor chip */ |
54 | /* !! values used in different tables */ | 54 | /* !! values used in different tables */ |
@@ -75,10 +75,12 @@ struct sd { | |||
75 | #define SENSOR_MAX 19 | 75 | #define SENSOR_MAX 19 |
76 | unsigned short chip_revision; | 76 | unsigned short chip_revision; |
77 | 77 | ||
78 | u8 *jpeg_hdr; | 78 | u8 jpeg_hdr[JPEG_HDR_SZ]; |
79 | }; | 79 | }; |
80 | 80 | ||
81 | /* V4L2 controls supported by the driver */ | 81 | /* V4L2 controls supported by the driver */ |
82 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
83 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
82 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | 84 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); |
83 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | 85 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); |
84 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | 86 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); |
@@ -93,6 +95,20 @@ static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | |||
93 | static const struct ctrl sd_ctrls[] = { | 95 | static const struct ctrl sd_ctrls[] = { |
94 | { | 96 | { |
95 | { | 97 | { |
98 | .id = V4L2_CID_BRIGHTNESS, | ||
99 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
100 | .name = "Brightness", | ||
101 | .minimum = 0, | ||
102 | .maximum = 255, | ||
103 | .step = 1, | ||
104 | #define BRIGHTNESS_DEF 128 | ||
105 | .default_value = BRIGHTNESS_DEF, | ||
106 | }, | ||
107 | .set = sd_setbrightness, | ||
108 | .get = sd_getbrightness, | ||
109 | }, | ||
110 | { | ||
111 | { | ||
96 | .id = V4L2_CID_CONTRAST, | 112 | .id = V4L2_CID_CONTRAST, |
97 | .type = V4L2_CTRL_TYPE_INTEGER, | 113 | .type = V4L2_CTRL_TYPE_INTEGER, |
98 | .name = "Contrast", | 114 | .name = "Contrast", |
@@ -132,7 +148,7 @@ static const struct ctrl sd_ctrls[] = { | |||
132 | .set = sd_setautogain, | 148 | .set = sd_setautogain, |
133 | .get = sd_getautogain, | 149 | .get = sd_getautogain, |
134 | }, | 150 | }, |
135 | #define LIGHTFREQ_IDX 3 | 151 | #define LIGHTFREQ_IDX 4 |
136 | { | 152 | { |
137 | { | 153 | { |
138 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | 154 | .id = V4L2_CID_POWER_LINE_FREQUENCY, |
@@ -6011,9 +6027,12 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
6011 | struct sd *sd = (struct sd *) gspca_dev; | 6027 | struct sd *sd = (struct sd *) gspca_dev; |
6012 | struct usb_device *dev = gspca_dev->dev; | 6028 | struct usb_device *dev = gspca_dev->dev; |
6013 | const u8 *Tgamma; | 6029 | const u8 *Tgamma; |
6014 | int g, i, k, adj, gp; | 6030 | int g, i, brightness, contrast, adj, gp1, gp2; |
6015 | u8 gr[16]; | 6031 | u8 gr[16]; |
6016 | static const u8 delta_tb[16] = /* delta for contrast */ | 6032 | static const u8 delta_b[16] = /* delta for brightness */ |
6033 | {0x50, 0x38, 0x2d, 0x28, 0x24, 0x21, 0x1e, 0x1d, | ||
6034 | 0x1d, 0x1b, 0x1b, 0x1b, 0x19, 0x18, 0x18, 0x18}; | ||
6035 | static const u8 delta_c[16] = /* delta for contrast */ | ||
6017 | {0x2c, 0x1a, 0x12, 0x0c, 0x0a, 0x06, 0x06, 0x06, | 6036 | {0x2c, 0x1a, 0x12, 0x0c, 0x0a, 0x06, 0x06, 0x06, |
6018 | 0x04, 0x06, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02}; | 6037 | 0x04, 0x06, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02}; |
6019 | static const u8 gamma_tb[6][16] = { | 6038 | static const u8 gamma_tb[6][16] = { |
@@ -6033,30 +6052,30 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
6033 | 6052 | ||
6034 | Tgamma = gamma_tb[sd->gamma - 1]; | 6053 | Tgamma = gamma_tb[sd->gamma - 1]; |
6035 | 6054 | ||
6036 | k = ((int) sd->contrast - 128); /* -128 / 128 */ | 6055 | contrast = ((int) sd->contrast - 128); /* -128 / 127 */ |
6056 | brightness = ((int) sd->brightness - 128); /* -128 / 92 */ | ||
6037 | adj = 0; | 6057 | adj = 0; |
6038 | gp = 0; | 6058 | gp1 = gp2 = 0; |
6039 | for (i = 0; i < 16; i++) { | 6059 | for (i = 0; i < 16; i++) { |
6040 | g = Tgamma[i] - delta_tb[i] * k / 256 - adj / 2; | 6060 | g = Tgamma[i] + delta_b[i] * brightness / 256 |
6061 | - delta_c[i] * contrast / 256 - adj / 2; | ||
6041 | if (g > 0xff) | 6062 | if (g > 0xff) |
6042 | g = 0xff; | 6063 | g = 0xff; |
6043 | else if (g < 0) | 6064 | else if (g < 0) |
6044 | g = 0; | 6065 | g = 0; |
6045 | reg_w(dev, g, 0x0120 + i); /* gamma */ | 6066 | reg_w(dev, g, 0x0120 + i); /* gamma */ |
6046 | if (k > 0) | 6067 | if (contrast > 0) |
6047 | adj--; | 6068 | adj--; |
6048 | else | 6069 | else if (contrast < 0) |
6049 | adj++; | 6070 | adj++; |
6050 | 6071 | if (i > 1) | |
6051 | if (i != 0) { | 6072 | gr[i - 1] = (g - gp2) / 2; |
6052 | if (gp == 0) | 6073 | else if (i != 0) |
6053 | gr[i - 1] = 0; | 6074 | gr[0] = gp1 == 0 ? 0 : (g - gp1); |
6054 | else | 6075 | gp2 = gp1; |
6055 | gr[i - 1] = g - gp; | 6076 | gp1 = g; |
6056 | } | ||
6057 | gp = g; | ||
6058 | } | 6077 | } |
6059 | gr[15] = gr[14] / 2; | 6078 | gr[15] = (0xff - gp2) / 2; |
6060 | for (i = 0; i < 16; i++) | 6079 | for (i = 0; i < 16; i++) |
6061 | reg_w(dev, gr[i], 0x0130 + i); /* gradient */ | 6080 | reg_w(dev, gr[i], 0x0130 + i); /* gradient */ |
6062 | } | 6081 | } |
@@ -6744,6 +6763,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6744 | cam->nmodes = ARRAY_SIZE(broken_vga_mode); | 6763 | cam->nmodes = ARRAY_SIZE(broken_vga_mode); |
6745 | break; | 6764 | break; |
6746 | } | 6765 | } |
6766 | sd->brightness = BRIGHTNESS_DEF; | ||
6747 | sd->contrast = CONTRAST_DEF; | 6767 | sd->contrast = CONTRAST_DEF; |
6748 | sd->gamma = gamma[sd->sensor]; | 6768 | sd->gamma = gamma[sd->sensor]; |
6749 | sd->autogain = AUTOGAIN_DEF; | 6769 | sd->autogain = AUTOGAIN_DEF; |
@@ -6798,9 +6818,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6798 | }; | 6818 | }; |
6799 | 6819 | ||
6800 | /* create the JPEG header */ | 6820 | /* create the JPEG header */ |
6801 | sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); | ||
6802 | if (!sd->jpeg_hdr) | ||
6803 | return -ENOMEM; | ||
6804 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, | 6821 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, |
6805 | 0x21); /* JPEG 422 */ | 6822 | 0x21); /* JPEG 422 */ |
6806 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | 6823 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); |
@@ -6918,10 +6935,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6918 | reg_w(dev, 0x00, 0x0007); /* (from win traces) */ | 6935 | reg_w(dev, 0x00, 0x0007); /* (from win traces) */ |
6919 | reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING); | 6936 | reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING); |
6920 | break; | 6937 | break; |
6921 | case SENSOR_PAS202B: | ||
6922 | reg_w(dev, 0x32, 0x0007); /* (from win traces) */ | ||
6923 | reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING); | ||
6924 | break; | ||
6925 | } | 6938 | } |
6926 | return 0; | 6939 | return 0; |
6927 | } | 6940 | } |
@@ -6931,7 +6944,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
6931 | { | 6944 | { |
6932 | struct sd *sd = (struct sd *) gspca_dev; | 6945 | struct sd *sd = (struct sd *) gspca_dev; |
6933 | 6946 | ||
6934 | kfree(sd->jpeg_hdr); | ||
6935 | if (!gspca_dev->present) | 6947 | if (!gspca_dev->present) |
6936 | return; | 6948 | return; |
6937 | send_unknown(gspca_dev->dev, sd->sensor); | 6949 | send_unknown(gspca_dev->dev, sd->sensor); |
@@ -6962,6 +6974,24 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
6962 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | 6974 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
6963 | } | 6975 | } |
6964 | 6976 | ||
6977 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | ||
6978 | { | ||
6979 | struct sd *sd = (struct sd *) gspca_dev; | ||
6980 | |||
6981 | sd->brightness = val; | ||
6982 | if (gspca_dev->streaming) | ||
6983 | setcontrast(gspca_dev); | ||
6984 | return 0; | ||
6985 | } | ||
6986 | |||
6987 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
6988 | { | ||
6989 | struct sd *sd = (struct sd *) gspca_dev; | ||
6990 | |||
6991 | *val = sd->brightness; | ||
6992 | return 0; | ||
6993 | } | ||
6994 | |||
6965 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | 6995 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) |
6966 | { | 6996 | { |
6967 | struct sd *sd = (struct sd *) gspca_dev; | 6997 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -7163,9 +7193,7 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
7163 | {USB_DEVICE(0x046d, 0x08aa)}, | 7193 | {USB_DEVICE(0x046d, 0x08aa)}, |
7164 | {USB_DEVICE(0x046d, 0x08ac)}, | 7194 | {USB_DEVICE(0x046d, 0x08ac)}, |
7165 | {USB_DEVICE(0x046d, 0x08ad)}, | 7195 | {USB_DEVICE(0x046d, 0x08ad)}, |
7166 | #if !defined CONFIG_USB_ZC0301 && !defined CONFIG_USB_ZC0301_MODULE | ||
7167 | {USB_DEVICE(0x046d, 0x08ae)}, | 7196 | {USB_DEVICE(0x046d, 0x08ae)}, |
7168 | #endif | ||
7169 | {USB_DEVICE(0x046d, 0x08af)}, | 7197 | {USB_DEVICE(0x046d, 0x08af)}, |
7170 | {USB_DEVICE(0x046d, 0x08b9)}, | 7198 | {USB_DEVICE(0x046d, 0x08b9)}, |
7171 | {USB_DEVICE(0x046d, 0x08d7)}, | 7199 | {USB_DEVICE(0x046d, 0x08d7)}, |
diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c index 830d47b05e1d..0cae5b82e1a2 100644 --- a/drivers/media/video/hdpvr/hdpvr-core.c +++ b/drivers/media/video/hdpvr/hdpvr-core.c | |||
@@ -286,6 +286,8 @@ static int hdpvr_probe(struct usb_interface *interface, | |||
286 | goto error; | 286 | goto error; |
287 | } | 287 | } |
288 | 288 | ||
289 | dev->workqueue = 0; | ||
290 | |||
289 | /* register v4l2_device early so it can be used for printks */ | 291 | /* register v4l2_device early so it can be used for printks */ |
290 | if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) { | 292 | if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) { |
291 | err("v4l2_device_register failed"); | 293 | err("v4l2_device_register failed"); |
@@ -380,6 +382,9 @@ static int hdpvr_probe(struct usb_interface *interface, | |||
380 | 382 | ||
381 | error: | 383 | error: |
382 | if (dev) { | 384 | if (dev) { |
385 | /* Destroy single thread */ | ||
386 | if (dev->workqueue) | ||
387 | destroy_workqueue(dev->workqueue); | ||
383 | /* this frees allocated memory */ | 388 | /* this frees allocated memory */ |
384 | hdpvr_delete(dev); | 389 | hdpvr_delete(dev); |
385 | } | 390 | } |
diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index c338f3f62e77..4863a21b1f24 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c | |||
@@ -394,7 +394,7 @@ err: | |||
394 | 394 | ||
395 | static int hdpvr_release(struct file *file) | 395 | static int hdpvr_release(struct file *file) |
396 | { | 396 | { |
397 | struct hdpvr_fh *fh = (struct hdpvr_fh *)file->private_data; | 397 | struct hdpvr_fh *fh = file->private_data; |
398 | struct hdpvr_device *dev = fh->dev; | 398 | struct hdpvr_device *dev = fh->dev; |
399 | 399 | ||
400 | if (!dev) | 400 | if (!dev) |
@@ -518,7 +518,7 @@ err: | |||
518 | static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) | 518 | static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) |
519 | { | 519 | { |
520 | struct hdpvr_buffer *buf = NULL; | 520 | struct hdpvr_buffer *buf = NULL; |
521 | struct hdpvr_fh *fh = (struct hdpvr_fh *)filp->private_data; | 521 | struct hdpvr_fh *fh = filp->private_data; |
522 | struct hdpvr_device *dev = fh->dev; | 522 | struct hdpvr_device *dev = fh->dev; |
523 | unsigned int mask = 0; | 523 | unsigned int mask = 0; |
524 | 524 | ||
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 29d439742653..27ae8bbfb477 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c | |||
@@ -47,7 +47,7 @@ | |||
47 | #include <linux/i2c-id.h> | 47 | #include <linux/i2c-id.h> |
48 | #include <linux/workqueue.h> | 48 | #include <linux/workqueue.h> |
49 | 49 | ||
50 | #include <media/ir-common.h> | 50 | #include <media/ir-core.h> |
51 | #include <media/ir-kbd-i2c.h> | 51 | #include <media/ir-kbd-i2c.h> |
52 | 52 | ||
53 | /* ----------------------------------------------------------------------- */ | 53 | /* ----------------------------------------------------------------------- */ |
@@ -272,11 +272,8 @@ static void ir_key_poll(struct IR_i2c *ir) | |||
272 | return; | 272 | return; |
273 | } | 273 | } |
274 | 274 | ||
275 | if (0 == rc) { | 275 | if (rc) |
276 | ir_input_nokey(ir->input, &ir->ir); | 276 | ir_keydown(ir->input, ir_key, 0); |
277 | } else { | ||
278 | ir_input_keydown(ir->input, &ir->ir, ir_key); | ||
279 | } | ||
280 | } | 277 | } |
281 | 278 | ||
282 | static void ir_work(struct work_struct *work) | 279 | static void ir_work(struct work_struct *work) |
@@ -439,10 +436,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
439 | dev_name(&client->dev)); | 436 | dev_name(&client->dev)); |
440 | 437 | ||
441 | /* init + register input device */ | 438 | /* init + register input device */ |
442 | err = ir_input_init(input_dev, &ir->ir, ir_type); | 439 | ir->ir_type = ir_type; |
443 | if (err < 0) | ||
444 | goto err_out_free; | ||
445 | |||
446 | input_dev->id.bustype = BUS_I2C; | 440 | input_dev->id.bustype = BUS_I2C; |
447 | input_dev->name = ir->name; | 441 | input_dev->name = ir->name; |
448 | input_dev->phys = ir->phys; | 442 | input_dev->phys = ir->phys; |
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 1b79475ca134..90daa6e751d8 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c | |||
@@ -130,6 +130,9 @@ static int ivtv_yuv_threshold = -1; | |||
130 | static int ivtv_pci_latency = 1; | 130 | static int ivtv_pci_latency = 1; |
131 | 131 | ||
132 | int ivtv_debug; | 132 | int ivtv_debug; |
133 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
134 | int ivtv_fw_debug; | ||
135 | #endif | ||
133 | 136 | ||
134 | static int tunertype = -1; | 137 | static int tunertype = -1; |
135 | static int newi2c = -1; | 138 | static int newi2c = -1; |
@@ -141,6 +144,9 @@ module_param_string(pal, pal, sizeof(pal), 0644); | |||
141 | module_param_string(secam, secam, sizeof(secam), 0644); | 144 | module_param_string(secam, secam, sizeof(secam), 0644); |
142 | module_param_string(ntsc, ntsc, sizeof(ntsc), 0644); | 145 | module_param_string(ntsc, ntsc, sizeof(ntsc), 0644); |
143 | module_param_named(debug,ivtv_debug, int, 0644); | 146 | module_param_named(debug,ivtv_debug, int, 0644); |
147 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
148 | module_param_named(fw_debug, ivtv_fw_debug, int, 0644); | ||
149 | #endif | ||
144 | module_param(ivtv_pci_latency, int, 0644); | 150 | module_param(ivtv_pci_latency, int, 0644); |
145 | module_param(ivtv_yuv_mode, int, 0644); | 151 | module_param(ivtv_yuv_mode, int, 0644); |
146 | module_param(ivtv_yuv_threshold, int, 0644); | 152 | module_param(ivtv_yuv_threshold, int, 0644); |
@@ -217,6 +223,10 @@ MODULE_PARM_DESC(debug, | |||
217 | "\t\t\t 256/0x0100: yuv\n" | 223 | "\t\t\t 256/0x0100: yuv\n" |
218 | "\t\t\t 512/0x0200: i2c\n" | 224 | "\t\t\t 512/0x0200: i2c\n" |
219 | "\t\t\t1024/0x0400: high volume\n"); | 225 | "\t\t\t1024/0x0400: high volume\n"); |
226 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
227 | MODULE_PARM_DESC(fw_debug, | ||
228 | "Enable code for debugging firmware problems. Default: 0\n"); | ||
229 | #endif | ||
220 | MODULE_PARM_DESC(ivtv_pci_latency, | 230 | MODULE_PARM_DESC(ivtv_pci_latency, |
221 | "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n" | 231 | "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n" |
222 | "\t\t\tDefault: Yes"); | 232 | "\t\t\tDefault: Yes"); |
@@ -1425,12 +1435,16 @@ EXPORT_SYMBOL(ivtv_vapi); | |||
1425 | EXPORT_SYMBOL(ivtv_vapi_result); | 1435 | EXPORT_SYMBOL(ivtv_vapi_result); |
1426 | EXPORT_SYMBOL(ivtv_clear_irq_mask); | 1436 | EXPORT_SYMBOL(ivtv_clear_irq_mask); |
1427 | EXPORT_SYMBOL(ivtv_debug); | 1437 | EXPORT_SYMBOL(ivtv_debug); |
1438 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1439 | EXPORT_SYMBOL(ivtv_fw_debug); | ||
1440 | #endif | ||
1428 | EXPORT_SYMBOL(ivtv_reset_ir_gpio); | 1441 | EXPORT_SYMBOL(ivtv_reset_ir_gpio); |
1429 | EXPORT_SYMBOL(ivtv_udma_setup); | 1442 | EXPORT_SYMBOL(ivtv_udma_setup); |
1430 | EXPORT_SYMBOL(ivtv_udma_unmap); | 1443 | EXPORT_SYMBOL(ivtv_udma_unmap); |
1431 | EXPORT_SYMBOL(ivtv_udma_alloc); | 1444 | EXPORT_SYMBOL(ivtv_udma_alloc); |
1432 | EXPORT_SYMBOL(ivtv_udma_prepare); | 1445 | EXPORT_SYMBOL(ivtv_udma_prepare); |
1433 | EXPORT_SYMBOL(ivtv_init_on_first_open); | 1446 | EXPORT_SYMBOL(ivtv_init_on_first_open); |
1447 | EXPORT_SYMBOL(ivtv_firmware_check); | ||
1434 | 1448 | ||
1435 | module_init(module_start); | 1449 | module_init(module_start); |
1436 | module_exit(module_cleanup); | 1450 | module_exit(module_cleanup); |
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 5b45fd2b2645..bd084df4448a 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h | |||
@@ -122,6 +122,9 @@ | |||
122 | 122 | ||
123 | /* debugging */ | 123 | /* debugging */ |
124 | extern int ivtv_debug; | 124 | extern int ivtv_debug; |
125 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
126 | extern int ivtv_fw_debug; | ||
127 | #endif | ||
125 | 128 | ||
126 | #define IVTV_DBGFLG_WARN (1 << 0) | 129 | #define IVTV_DBGFLG_WARN (1 << 0) |
127 | #define IVTV_DBGFLG_INFO (1 << 1) | 130 | #define IVTV_DBGFLG_INFO (1 << 1) |
@@ -734,6 +737,7 @@ struct ivtv { | |||
734 | struct v4l2_rect osd_rect; /* current OSD position and size */ | 737 | struct v4l2_rect osd_rect; /* current OSD position and size */ |
735 | struct v4l2_rect main_rect; /* current Main window position and size */ | 738 | struct v4l2_rect main_rect; /* current Main window position and size */ |
736 | struct osd_info *osd_info; /* ivtvfb private OSD info */ | 739 | struct osd_info *osd_info; /* ivtvfb private OSD info */ |
740 | void (*ivtvfb_restore)(struct ivtv *itv); /* Used for a warm start */ | ||
737 | }; | 741 | }; |
738 | 742 | ||
739 | static inline struct ivtv *to_ivtv(struct v4l2_device *v4l2_dev) | 743 | static inline struct ivtv *to_ivtv(struct v4l2_device *v4l2_dev) |
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 3c2cc270ccd5..a6a2cdb81566 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "ivtv-yuv.h" | 32 | #include "ivtv-yuv.h" |
33 | #include "ivtv-ioctl.h" | 33 | #include "ivtv-ioctl.h" |
34 | #include "ivtv-cards.h" | 34 | #include "ivtv-cards.h" |
35 | #include "ivtv-firmware.h" | ||
35 | #include <media/v4l2-event.h> | 36 | #include <media/v4l2-event.h> |
36 | #include <media/saa7115.h> | 37 | #include <media/saa7115.h> |
37 | 38 | ||
@@ -526,6 +527,7 @@ int ivtv_start_decoding(struct ivtv_open_id *id, int speed) | |||
526 | { | 527 | { |
527 | struct ivtv *itv = id->itv; | 528 | struct ivtv *itv = id->itv; |
528 | struct ivtv_stream *s = &itv->streams[id->type]; | 529 | struct ivtv_stream *s = &itv->streams[id->type]; |
530 | int rc; | ||
529 | 531 | ||
530 | if (atomic_read(&itv->decoding) == 0) { | 532 | if (atomic_read(&itv->decoding) == 0) { |
531 | if (ivtv_claim_stream(id, s->type)) { | 533 | if (ivtv_claim_stream(id, s->type)) { |
@@ -533,7 +535,13 @@ int ivtv_start_decoding(struct ivtv_open_id *id, int speed) | |||
533 | IVTV_DEBUG_WARN("start decode, stream already claimed\n"); | 535 | IVTV_DEBUG_WARN("start decode, stream already claimed\n"); |
534 | return -EBUSY; | 536 | return -EBUSY; |
535 | } | 537 | } |
536 | ivtv_start_v4l2_decode_stream(s, 0); | 538 | rc = ivtv_start_v4l2_decode_stream(s, 0); |
539 | if (rc < 0) { | ||
540 | if (rc == -EAGAIN) | ||
541 | rc = ivtv_start_v4l2_decode_stream(s, 0); | ||
542 | if (rc < 0) | ||
543 | return rc; | ||
544 | } | ||
537 | } | 545 | } |
538 | if (s->type == IVTV_DEC_STREAM_TYPE_MPG) | 546 | if (s->type == IVTV_DEC_STREAM_TYPE_MPG) |
539 | return ivtv_set_speed(itv, speed); | 547 | return ivtv_set_speed(itv, speed); |
@@ -912,12 +920,32 @@ int ivtv_v4l2_close(struct file *filp) | |||
912 | 920 | ||
913 | static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) | 921 | static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) |
914 | { | 922 | { |
923 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
924 | struct video_device *vdev = video_devdata(filp); | ||
925 | #endif | ||
915 | struct ivtv *itv = s->itv; | 926 | struct ivtv *itv = s->itv; |
916 | struct ivtv_open_id *item; | 927 | struct ivtv_open_id *item; |
917 | int res = 0; | 928 | int res = 0; |
918 | 929 | ||
919 | IVTV_DEBUG_FILE("open %s\n", s->name); | 930 | IVTV_DEBUG_FILE("open %s\n", s->name); |
920 | 931 | ||
932 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
933 | /* Unless ivtv_fw_debug is set, error out if firmware dead. */ | ||
934 | if (ivtv_fw_debug) { | ||
935 | IVTV_WARN("Opening %s with dead firmware lockout disabled\n", | ||
936 | video_device_node_name(vdev)); | ||
937 | IVTV_WARN("Selected firmware errors will be ignored\n"); | ||
938 | } else { | ||
939 | #else | ||
940 | if (1) { | ||
941 | #endif | ||
942 | res = ivtv_firmware_check(itv, "ivtv_serialized_open"); | ||
943 | if (res == -EAGAIN) | ||
944 | res = ivtv_firmware_check(itv, "ivtv_serialized_open"); | ||
945 | if (res < 0) | ||
946 | return -EIO; | ||
947 | } | ||
948 | |||
921 | if (s->type == IVTV_DEC_STREAM_TYPE_MPG && | 949 | if (s->type == IVTV_DEC_STREAM_TYPE_MPG && |
922 | test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags)) | 950 | test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags)) |
923 | return -EBUSY; | 951 | return -EBUSY; |
diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/video/ivtv/ivtv-firmware.c index a71e8ba306b0..d8bf2b01729d 100644 --- a/drivers/media/video/ivtv/ivtv-firmware.c +++ b/drivers/media/video/ivtv/ivtv-firmware.c | |||
@@ -23,7 +23,10 @@ | |||
23 | #include "ivtv-mailbox.h" | 23 | #include "ivtv-mailbox.h" |
24 | #include "ivtv-firmware.h" | 24 | #include "ivtv-firmware.h" |
25 | #include "ivtv-yuv.h" | 25 | #include "ivtv-yuv.h" |
26 | #include "ivtv-ioctl.h" | ||
27 | #include "ivtv-cards.h" | ||
26 | #include <linux/firmware.h> | 28 | #include <linux/firmware.h> |
29 | #include <media/saa7127.h> | ||
27 | 30 | ||
28 | #define IVTV_MASK_SPU_ENABLE 0xFFFFFFFE | 31 | #define IVTV_MASK_SPU_ENABLE 0xFFFFFFFE |
29 | #define IVTV_MASK_VPU_ENABLE15 0xFFFFFFF6 | 32 | #define IVTV_MASK_VPU_ENABLE15 0xFFFFFFF6 |
@@ -271,3 +274,122 @@ void ivtv_init_mpeg_decoder(struct ivtv *itv) | |||
271 | } | 274 | } |
272 | ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 4, 0, 0, 0, 1); | 275 | ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 4, 0, 0, 0, 1); |
273 | } | 276 | } |
277 | |||
278 | /* Try to restart the card & restore previous settings */ | ||
279 | int ivtv_firmware_restart(struct ivtv *itv) | ||
280 | { | ||
281 | int rc = 0; | ||
282 | v4l2_std_id std; | ||
283 | struct ivtv_open_id fh; | ||
284 | fh.itv = itv; | ||
285 | |||
286 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) | ||
287 | /* Display test image during restart */ | ||
288 | ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing, | ||
289 | SAA7127_INPUT_TYPE_TEST_IMAGE, | ||
290 | itv->card->video_outputs[itv->active_output].video_output, | ||
291 | 0); | ||
292 | |||
293 | mutex_lock(&itv->udma.lock); | ||
294 | |||
295 | rc = ivtv_firmware_init(itv); | ||
296 | if (rc) { | ||
297 | mutex_unlock(&itv->udma.lock); | ||
298 | return rc; | ||
299 | } | ||
300 | |||
301 | /* Allow settings to reload */ | ||
302 | ivtv_mailbox_cache_invalidate(itv); | ||
303 | |||
304 | /* Restore video standard */ | ||
305 | std = itv->std; | ||
306 | itv->std = 0; | ||
307 | ivtv_s_std(NULL, &fh, &std); | ||
308 | |||
309 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { | ||
310 | ivtv_init_mpeg_decoder(itv); | ||
311 | |||
312 | /* Restore framebuffer if active */ | ||
313 | if (itv->ivtvfb_restore) | ||
314 | itv->ivtvfb_restore(itv); | ||
315 | |||
316 | /* Restore alpha settings */ | ||
317 | ivtv_set_osd_alpha(itv); | ||
318 | |||
319 | /* Restore normal output */ | ||
320 | ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing, | ||
321 | SAA7127_INPUT_TYPE_NORMAL, | ||
322 | itv->card->video_outputs[itv->active_output].video_output, | ||
323 | 0); | ||
324 | } | ||
325 | |||
326 | mutex_unlock(&itv->udma.lock); | ||
327 | return rc; | ||
328 | } | ||
329 | |||
330 | /* Check firmware running state. The checks fall through | ||
331 | allowing multiple failures to be logged. */ | ||
332 | int ivtv_firmware_check(struct ivtv *itv, char *where) | ||
333 | { | ||
334 | int res = 0; | ||
335 | |||
336 | /* Check encoder is still running */ | ||
337 | if (ivtv_vapi(itv, CX2341X_ENC_PING_FW, 0) < 0) { | ||
338 | IVTV_WARN("Encoder has died : %s\n", where); | ||
339 | res = -1; | ||
340 | } | ||
341 | |||
342 | /* Also check audio. Only check if not in use & encoder is okay */ | ||
343 | if (!res && !atomic_read(&itv->capturing) && | ||
344 | (!atomic_read(&itv->decoding) || | ||
345 | (atomic_read(&itv->decoding) < 2 && test_bit(IVTV_F_I_DEC_YUV, | ||
346 | &itv->i_flags)))) { | ||
347 | |||
348 | if (ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12) < 0) { | ||
349 | IVTV_WARN("Audio has died (Encoder OK) : %s\n", where); | ||
350 | res = -2; | ||
351 | } | ||
352 | } | ||
353 | |||
354 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { | ||
355 | /* Second audio check. Skip if audio already failed */ | ||
356 | if (res != -2 && read_dec(0x100) != read_dec(0x104)) { | ||
357 | /* Wait & try again to be certain. */ | ||
358 | ivtv_msleep_timeout(14, 0); | ||
359 | if (read_dec(0x100) != read_dec(0x104)) { | ||
360 | IVTV_WARN("Audio has died (Decoder) : %s\n", | ||
361 | where); | ||
362 | res = -1; | ||
363 | } | ||
364 | } | ||
365 | |||
366 | /* Check decoder is still running */ | ||
367 | if (ivtv_vapi(itv, CX2341X_DEC_PING_FW, 0) < 0) { | ||
368 | IVTV_WARN("Decoder has died : %s\n", where); | ||
369 | res = -1; | ||
370 | } | ||
371 | } | ||
372 | |||
373 | /* If something failed & currently idle, try to reload */ | ||
374 | if (res && !atomic_read(&itv->capturing) && | ||
375 | !atomic_read(&itv->decoding)) { | ||
376 | IVTV_INFO("Detected in %s that firmware had failed - " | ||
377 | "Reloading\n", where); | ||
378 | res = ivtv_firmware_restart(itv); | ||
379 | /* | ||
380 | * Even if restarted ok, still signal a problem had occured. | ||
381 | * The caller can come through this function again to check | ||
382 | * if things are really ok after the restart. | ||
383 | */ | ||
384 | if (!res) { | ||
385 | IVTV_INFO("Firmware restart okay\n"); | ||
386 | res = -EAGAIN; | ||
387 | } else { | ||
388 | IVTV_INFO("Firmware restart failed\n"); | ||
389 | } | ||
390 | } else if (res) { | ||
391 | res = -EIO; | ||
392 | } | ||
393 | |||
394 | return res; | ||
395 | } | ||
diff --git a/drivers/media/video/ivtv/ivtv-firmware.h b/drivers/media/video/ivtv/ivtv-firmware.h index 041ba94e65bc..52bb4e5598fd 100644 --- a/drivers/media/video/ivtv/ivtv-firmware.h +++ b/drivers/media/video/ivtv/ivtv-firmware.h | |||
@@ -26,5 +26,6 @@ int ivtv_firmware_init(struct ivtv *itv); | |||
26 | void ivtv_firmware_versions(struct ivtv *itv); | 26 | void ivtv_firmware_versions(struct ivtv *itv); |
27 | void ivtv_halt_firmware(struct ivtv *itv); | 27 | void ivtv_halt_firmware(struct ivtv *itv); |
28 | void ivtv_init_mpeg_decoder(struct ivtv *itv); | 28 | void ivtv_init_mpeg_decoder(struct ivtv *itv); |
29 | int ivtv_firmware_check(struct ivtv *itv, char *where); | ||
29 | 30 | ||
30 | #endif | 31 | #endif |
diff --git a/drivers/media/video/ivtv/ivtv-mailbox.c b/drivers/media/video/ivtv/ivtv-mailbox.c index 84577f6f41a2..e3ce96763785 100644 --- a/drivers/media/video/ivtv/ivtv-mailbox.c +++ b/drivers/media/video/ivtv/ivtv-mailbox.c | |||
@@ -377,3 +377,11 @@ void ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb, | |||
377 | for (i = 0; i < argc; i++, p++) | 377 | for (i = 0; i < argc; i++, p++) |
378 | data[i] = readl(p); | 378 | data[i] = readl(p); |
379 | } | 379 | } |
380 | |||
381 | /* Wipe api cache */ | ||
382 | void ivtv_mailbox_cache_invalidate(struct ivtv *itv) | ||
383 | { | ||
384 | int i; | ||
385 | for (i = 0; i < 256; i++) | ||
386 | itv->api_cache[i].last_jiffies = 0; | ||
387 | } | ||
diff --git a/drivers/media/video/ivtv/ivtv-mailbox.h b/drivers/media/video/ivtv/ivtv-mailbox.h index 8247662c928e..2c834d2cb56f 100644 --- a/drivers/media/video/ivtv/ivtv-mailbox.h +++ b/drivers/media/video/ivtv/ivtv-mailbox.h | |||
@@ -30,5 +30,6 @@ int ivtv_api(struct ivtv *itv, int cmd, int args, u32 data[]); | |||
30 | int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...); | 30 | int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...); |
31 | int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...); | 31 | int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...); |
32 | int ivtv_api_func(void *priv, u32 cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]); | 32 | int ivtv_api_func(void *priv, u32 cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]); |
33 | void ivtv_mailbox_cache_invalidate(struct ivtv *itv); | ||
33 | 34 | ||
34 | #endif | 35 | #endif |
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index a937e2ff9b6e..55df4190c28d 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include "ivtv-yuv.h" | 42 | #include "ivtv-yuv.h" |
43 | #include "ivtv-cards.h" | 43 | #include "ivtv-cards.h" |
44 | #include "ivtv-streams.h" | 44 | #include "ivtv-streams.h" |
45 | #include "ivtv-firmware.h" | ||
45 | #include <media/v4l2-event.h> | 46 | #include <media/v4l2-event.h> |
46 | 47 | ||
47 | static const struct v4l2_file_operations ivtv_v4l2_enc_fops = { | 48 | static const struct v4l2_file_operations ivtv_v4l2_enc_fops = { |
@@ -674,12 +675,14 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s) | |||
674 | /* Decoder sometimes dies here, so wait a moment */ | 675 | /* Decoder sometimes dies here, so wait a moment */ |
675 | ivtv_msleep_timeout(10, 0); | 676 | ivtv_msleep_timeout(10, 0); |
676 | 677 | ||
677 | return 0; | 678 | /* Known failure point for firmware, so check */ |
679 | return ivtv_firmware_check(itv, "ivtv_setup_v4l2_decode_stream"); | ||
678 | } | 680 | } |
679 | 681 | ||
680 | int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset) | 682 | int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset) |
681 | { | 683 | { |
682 | struct ivtv *itv = s->itv; | 684 | struct ivtv *itv = s->itv; |
685 | int rc; | ||
683 | 686 | ||
684 | if (s->vdev == NULL) | 687 | if (s->vdev == NULL) |
685 | return -EINVAL; | 688 | return -EINVAL; |
@@ -689,7 +692,11 @@ int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset) | |||
689 | 692 | ||
690 | IVTV_DEBUG_INFO("Starting decode stream %s (gop_offset %d)\n", s->name, gop_offset); | 693 | IVTV_DEBUG_INFO("Starting decode stream %s (gop_offset %d)\n", s->name, gop_offset); |
691 | 694 | ||
692 | ivtv_setup_v4l2_decode_stream(s); | 695 | rc = ivtv_setup_v4l2_decode_stream(s); |
696 | if (rc < 0) { | ||
697 | clear_bit(IVTV_F_S_STREAMING, &s->s_flags); | ||
698 | return rc; | ||
699 | } | ||
693 | 700 | ||
694 | /* set dma size to 65536 bytes */ | 701 | /* set dma size to 65536 bytes */ |
695 | ivtv_vapi(itv, CX2341X_DEC_SET_DMA_BLOCK_SIZE, 1, 65536); | 702 | ivtv_vapi(itv, CX2341X_DEC_SET_DMA_BLOCK_SIZE, 1, 65536); |
diff --git a/drivers/media/video/ivtv/ivtv-version.h b/drivers/media/video/ivtv/ivtv-version.h index b530dec399d3..b67a4048f5aa 100644 --- a/drivers/media/video/ivtv/ivtv-version.h +++ b/drivers/media/video/ivtv/ivtv-version.h | |||
@@ -23,7 +23,7 @@ | |||
23 | #define IVTV_DRIVER_NAME "ivtv" | 23 | #define IVTV_DRIVER_NAME "ivtv" |
24 | #define IVTV_DRIVER_VERSION_MAJOR 1 | 24 | #define IVTV_DRIVER_VERSION_MAJOR 1 |
25 | #define IVTV_DRIVER_VERSION_MINOR 4 | 25 | #define IVTV_DRIVER_VERSION_MINOR 4 |
26 | #define IVTV_DRIVER_VERSION_PATCHLEVEL 1 | 26 | #define IVTV_DRIVER_VERSION_PATCHLEVEL 2 |
27 | 27 | ||
28 | #define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL) | 28 | #define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL) |
29 | #define IVTV_DRIVER_VERSION KERNEL_VERSION(IVTV_DRIVER_VERSION_MAJOR,IVTV_DRIVER_VERSION_MINOR,IVTV_DRIVER_VERSION_PATCHLEVEL) | 29 | #define IVTV_DRIVER_VERSION KERNEL_VERSION(IVTV_DRIVER_VERSION_MAJOR,IVTV_DRIVER_VERSION_MINOR,IVTV_DRIVER_VERSION_PATCHLEVEL) |
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index 9ff3425891ed..be03a712731c 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include "ivtv-i2c.h" | 53 | #include "ivtv-i2c.h" |
54 | #include "ivtv-udma.h" | 54 | #include "ivtv-udma.h" |
55 | #include "ivtv-mailbox.h" | 55 | #include "ivtv-mailbox.h" |
56 | #include "ivtv-firmware.h" | ||
56 | 57 | ||
57 | /* card parameters */ | 58 | /* card parameters */ |
58 | static int ivtvfb_card_id = -1; | 59 | static int ivtvfb_card_id = -1; |
@@ -178,6 +179,12 @@ struct osd_info { | |||
178 | struct fb_info ivtvfb_info; | 179 | struct fb_info ivtvfb_info; |
179 | struct fb_var_screeninfo ivtvfb_defined; | 180 | struct fb_var_screeninfo ivtvfb_defined; |
180 | struct fb_fix_screeninfo ivtvfb_fix; | 181 | struct fb_fix_screeninfo ivtvfb_fix; |
182 | |||
183 | /* Used for a warm start */ | ||
184 | struct fb_var_screeninfo fbvar_cur; | ||
185 | int blank_cur; | ||
186 | u32 palette_cur[256]; | ||
187 | u32 pan_cur; | ||
181 | }; | 188 | }; |
182 | 189 | ||
183 | struct ivtv_osd_coords { | 190 | struct ivtv_osd_coords { |
@@ -199,6 +206,7 @@ static int ivtvfb_get_framebuffer(struct ivtv *itv, u32 *fbbase, | |||
199 | u32 data[CX2341X_MBOX_MAX_DATA]; | 206 | u32 data[CX2341X_MBOX_MAX_DATA]; |
200 | int rc; | 207 | int rc; |
201 | 208 | ||
209 | ivtv_firmware_check(itv, "ivtvfb_get_framebuffer"); | ||
202 | rc = ivtv_vapi_result(itv, data, CX2341X_OSD_GET_FRAMEBUFFER, 0); | 210 | rc = ivtv_vapi_result(itv, data, CX2341X_OSD_GET_FRAMEBUFFER, 0); |
203 | *fbbase = data[0]; | 211 | *fbbase = data[0]; |
204 | *fblength = data[1]; | 212 | *fblength = data[1]; |
@@ -581,8 +589,10 @@ static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var) | |||
581 | ivtv_window.height = var->yres; | 589 | ivtv_window.height = var->yres; |
582 | 590 | ||
583 | /* Minimum margin cannot be 0, as X won't allow such a mode */ | 591 | /* Minimum margin cannot be 0, as X won't allow such a mode */ |
584 | if (!var->upper_margin) var->upper_margin++; | 592 | if (!var->upper_margin) |
585 | if (!var->left_margin) var->left_margin++; | 593 | var->upper_margin++; |
594 | if (!var->left_margin) | ||
595 | var->left_margin++; | ||
586 | ivtv_window.top = var->upper_margin - 1; | 596 | ivtv_window.top = var->upper_margin - 1; |
587 | ivtv_window.left = var->left_margin - 1; | 597 | ivtv_window.left = var->left_margin - 1; |
588 | 598 | ||
@@ -595,6 +605,9 @@ static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var) | |||
595 | /* Force update of yuv registers */ | 605 | /* Force update of yuv registers */ |
596 | itv->yuv_info.yuv_forced_update = 1; | 606 | itv->yuv_info.yuv_forced_update = 1; |
597 | 607 | ||
608 | /* Keep a copy of these settings */ | ||
609 | memcpy(&oi->fbvar_cur, var, sizeof(oi->fbvar_cur)); | ||
610 | |||
598 | IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n", | 611 | IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n", |
599 | var->xres, var->yres, | 612 | var->xres, var->yres, |
600 | var->xres_virtual, var->yres_virtual, | 613 | var->xres_virtual, var->yres_virtual, |
@@ -829,6 +842,8 @@ static int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *inf | |||
829 | itv->yuv_info.osd_y_pan = var->yoffset; | 842 | itv->yuv_info.osd_y_pan = var->yoffset; |
830 | /* Force update of yuv registers */ | 843 | /* Force update of yuv registers */ |
831 | itv->yuv_info.yuv_forced_update = 1; | 844 | itv->yuv_info.yuv_forced_update = 1; |
845 | /* Remember this value */ | ||
846 | itv->osd_info->pan_cur = osd_pan_index; | ||
832 | return 0; | 847 | return 0; |
833 | } | 848 | } |
834 | 849 | ||
@@ -842,6 +857,7 @@ static int ivtvfb_set_par(struct fb_info *info) | |||
842 | rc = ivtvfb_set_var(itv, &info->var); | 857 | rc = ivtvfb_set_var(itv, &info->var); |
843 | ivtvfb_pan_display(&info->var, info); | 858 | ivtvfb_pan_display(&info->var, info); |
844 | ivtvfb_get_fix(itv, &info->fix); | 859 | ivtvfb_get_fix(itv, &info->fix); |
860 | ivtv_firmware_check(itv, "ivtvfb_set_par"); | ||
845 | return rc; | 861 | return rc; |
846 | } | 862 | } |
847 | 863 | ||
@@ -859,6 +875,7 @@ static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
859 | if (info->var.bits_per_pixel <= 8) { | 875 | if (info->var.bits_per_pixel <= 8) { |
860 | write_reg(regno, 0x02a30); | 876 | write_reg(regno, 0x02a30); |
861 | write_reg(color, 0x02a34); | 877 | write_reg(color, 0x02a34); |
878 | itv->osd_info->palette_cur[regno] = color; | ||
862 | return 0; | 879 | return 0; |
863 | } | 880 | } |
864 | if (regno >= 16) | 881 | if (regno >= 16) |
@@ -911,6 +928,7 @@ static int ivtvfb_blank(int blank_mode, struct fb_info *info) | |||
911 | ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0); | 928 | ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0); |
912 | break; | 929 | break; |
913 | } | 930 | } |
931 | itv->osd_info->blank_cur = blank_mode; | ||
914 | return 0; | 932 | return 0; |
915 | } | 933 | } |
916 | 934 | ||
@@ -929,6 +947,21 @@ static struct fb_ops ivtvfb_ops = { | |||
929 | .fb_blank = ivtvfb_blank, | 947 | .fb_blank = ivtvfb_blank, |
930 | }; | 948 | }; |
931 | 949 | ||
950 | /* Restore hardware after firmware restart */ | ||
951 | static void ivtvfb_restore(struct ivtv *itv) | ||
952 | { | ||
953 | struct osd_info *oi = itv->osd_info; | ||
954 | int i; | ||
955 | |||
956 | ivtvfb_set_var(itv, &oi->fbvar_cur); | ||
957 | ivtvfb_blank(oi->blank_cur, &oi->ivtvfb_info); | ||
958 | for (i = 0; i < 256; i++) { | ||
959 | write_reg(i, 0x02a30); | ||
960 | write_reg(oi->palette_cur[i], 0x02a34); | ||
961 | } | ||
962 | write_reg(oi->pan_cur, 0x02a0c); | ||
963 | } | ||
964 | |||
932 | /* Initialization */ | 965 | /* Initialization */ |
933 | 966 | ||
934 | 967 | ||
@@ -1192,6 +1225,9 @@ static int ivtvfb_init_card(struct ivtv *itv) | |||
1192 | /* Enable the osd */ | 1225 | /* Enable the osd */ |
1193 | ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info); | 1226 | ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info); |
1194 | 1227 | ||
1228 | /* Enable restart */ | ||
1229 | itv->ivtvfb_restore = ivtvfb_restore; | ||
1230 | |||
1195 | /* Allocate DMA */ | 1231 | /* Allocate DMA */ |
1196 | ivtv_udma_alloc(itv); | 1232 | ivtv_udma_alloc(itv); |
1197 | return 0; | 1233 | return 0; |
@@ -1203,7 +1239,7 @@ static int __init ivtvfb_callback_init(struct device *dev, void *p) | |||
1203 | struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); | 1239 | struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); |
1204 | struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev); | 1240 | struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev); |
1205 | 1241 | ||
1206 | if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { | 1242 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { |
1207 | if (ivtvfb_init_card(itv) == 0) { | 1243 | if (ivtvfb_init_card(itv) == 0) { |
1208 | IVTVFB_INFO("Framebuffer registered on %s\n", | 1244 | IVTVFB_INFO("Framebuffer registered on %s\n", |
1209 | itv->v4l2_dev.name); | 1245 | itv->v4l2_dev.name); |
@@ -1219,13 +1255,14 @@ static int ivtvfb_callback_cleanup(struct device *dev, void *p) | |||
1219 | struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev); | 1255 | struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev); |
1220 | struct osd_info *oi = itv->osd_info; | 1256 | struct osd_info *oi = itv->osd_info; |
1221 | 1257 | ||
1222 | if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { | 1258 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { |
1223 | if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) { | 1259 | if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) { |
1224 | IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n", | 1260 | IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n", |
1225 | itv->instance); | 1261 | itv->instance); |
1226 | return 0; | 1262 | return 0; |
1227 | } | 1263 | } |
1228 | IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance); | 1264 | IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance); |
1265 | itv->ivtvfb_restore = NULL; | ||
1229 | ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info); | 1266 | ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info); |
1230 | ivtvfb_release_buffers(itv); | 1267 | ivtvfb_release_buffers(itv); |
1231 | itv->osd_video_pbase = 0; | 1268 | itv->osd_video_pbase = 0; |
diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c index 10ddeccc70eb..4525335f9bd4 100644 --- a/drivers/media/video/mem2mem_testdev.c +++ b/drivers/media/video/mem2mem_testdev.c | |||
@@ -903,14 +903,14 @@ static int m2mtest_release(struct file *file) | |||
903 | static unsigned int m2mtest_poll(struct file *file, | 903 | static unsigned int m2mtest_poll(struct file *file, |
904 | struct poll_table_struct *wait) | 904 | struct poll_table_struct *wait) |
905 | { | 905 | { |
906 | struct m2mtest_ctx *ctx = (struct m2mtest_ctx *)file->private_data; | 906 | struct m2mtest_ctx *ctx = file->private_data; |
907 | 907 | ||
908 | return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); | 908 | return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); |
909 | } | 909 | } |
910 | 910 | ||
911 | static int m2mtest_mmap(struct file *file, struct vm_area_struct *vma) | 911 | static int m2mtest_mmap(struct file *file, struct vm_area_struct *vma) |
912 | { | 912 | { |
913 | struct m2mtest_ctx *ctx = (struct m2mtest_ctx *)file->private_data; | 913 | struct m2mtest_ctx *ctx = file->private_data; |
914 | 914 | ||
915 | return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); | 915 | return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); |
916 | } | 916 | } |
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index fbd0fc794720..31cc3d04bcc4 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c | |||
@@ -143,10 +143,10 @@ static const struct mt9m111_datafmt *mt9m111_find_datafmt( | |||
143 | } | 143 | } |
144 | 144 | ||
145 | static const struct mt9m111_datafmt mt9m111_colour_fmts[] = { | 145 | static const struct mt9m111_datafmt mt9m111_colour_fmts[] = { |
146 | {V4L2_MBUS_FMT_YUYV8_2X8_LE, V4L2_COLORSPACE_JPEG}, | 146 | {V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG}, |
147 | {V4L2_MBUS_FMT_YVYU8_2X8_LE, V4L2_COLORSPACE_JPEG}, | 147 | {V4L2_MBUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG}, |
148 | {V4L2_MBUS_FMT_YUYV8_2X8_BE, V4L2_COLORSPACE_JPEG}, | 148 | {V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG}, |
149 | {V4L2_MBUS_FMT_YVYU8_2X8_BE, V4L2_COLORSPACE_JPEG}, | 149 | {V4L2_MBUS_FMT_VYUY8_2X8, V4L2_COLORSPACE_JPEG}, |
150 | {V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB}, | 150 | {V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB}, |
151 | {V4L2_MBUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB}, | 151 | {V4L2_MBUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB}, |
152 | {V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB}, | 152 | {V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB}, |
@@ -505,22 +505,22 @@ static int mt9m111_set_pixfmt(struct i2c_client *client, | |||
505 | case V4L2_MBUS_FMT_RGB565_2X8_LE: | 505 | case V4L2_MBUS_FMT_RGB565_2X8_LE: |
506 | ret = mt9m111_setfmt_rgb565(client); | 506 | ret = mt9m111_setfmt_rgb565(client); |
507 | break; | 507 | break; |
508 | case V4L2_MBUS_FMT_YUYV8_2X8_BE: | 508 | case V4L2_MBUS_FMT_UYVY8_2X8: |
509 | mt9m111->swap_yuv_y_chromas = 0; | 509 | mt9m111->swap_yuv_y_chromas = 0; |
510 | mt9m111->swap_yuv_cb_cr = 0; | 510 | mt9m111->swap_yuv_cb_cr = 0; |
511 | ret = mt9m111_setfmt_yuv(client); | 511 | ret = mt9m111_setfmt_yuv(client); |
512 | break; | 512 | break; |
513 | case V4L2_MBUS_FMT_YVYU8_2X8_BE: | 513 | case V4L2_MBUS_FMT_VYUY8_2X8: |
514 | mt9m111->swap_yuv_y_chromas = 0; | 514 | mt9m111->swap_yuv_y_chromas = 0; |
515 | mt9m111->swap_yuv_cb_cr = 1; | 515 | mt9m111->swap_yuv_cb_cr = 1; |
516 | ret = mt9m111_setfmt_yuv(client); | 516 | ret = mt9m111_setfmt_yuv(client); |
517 | break; | 517 | break; |
518 | case V4L2_MBUS_FMT_YUYV8_2X8_LE: | 518 | case V4L2_MBUS_FMT_YUYV8_2X8: |
519 | mt9m111->swap_yuv_y_chromas = 1; | 519 | mt9m111->swap_yuv_y_chromas = 1; |
520 | mt9m111->swap_yuv_cb_cr = 0; | 520 | mt9m111->swap_yuv_cb_cr = 0; |
521 | ret = mt9m111_setfmt_yuv(client); | 521 | ret = mt9m111_setfmt_yuv(client); |
522 | break; | 522 | break; |
523 | case V4L2_MBUS_FMT_YVYU8_2X8_LE: | 523 | case V4L2_MBUS_FMT_YVYU8_2X8: |
524 | mt9m111->swap_yuv_y_chromas = 1; | 524 | mt9m111->swap_yuv_y_chromas = 1; |
525 | mt9m111->swap_yuv_cb_cr = 1; | 525 | mt9m111->swap_yuv_cb_cr = 1; |
526 | ret = mt9m111_setfmt_yuv(client); | 526 | ret = mt9m111_setfmt_yuv(client); |
diff --git a/drivers/media/video/mt9t112.c b/drivers/media/video/mt9t112.c index e4bf1db9a87b..8ec47e42d4d0 100644 --- a/drivers/media/video/mt9t112.c +++ b/drivers/media/video/mt9t112.c | |||
@@ -121,22 +121,22 @@ struct mt9t112_priv { | |||
121 | 121 | ||
122 | static const struct mt9t112_format mt9t112_cfmts[] = { | 122 | static const struct mt9t112_format mt9t112_cfmts[] = { |
123 | { | 123 | { |
124 | .code = V4L2_MBUS_FMT_YUYV8_2X8_BE, | 124 | .code = V4L2_MBUS_FMT_UYVY8_2X8, |
125 | .colorspace = V4L2_COLORSPACE_JPEG, | 125 | .colorspace = V4L2_COLORSPACE_JPEG, |
126 | .fmt = 1, | 126 | .fmt = 1, |
127 | .order = 0, | 127 | .order = 0, |
128 | }, { | 128 | }, { |
129 | .code = V4L2_MBUS_FMT_YVYU8_2X8_BE, | 129 | .code = V4L2_MBUS_FMT_VYUY8_2X8, |
130 | .colorspace = V4L2_COLORSPACE_JPEG, | 130 | .colorspace = V4L2_COLORSPACE_JPEG, |
131 | .fmt = 1, | 131 | .fmt = 1, |
132 | .order = 1, | 132 | .order = 1, |
133 | }, { | 133 | }, { |
134 | .code = V4L2_MBUS_FMT_YUYV8_2X8_LE, | 134 | .code = V4L2_MBUS_FMT_YUYV8_2X8, |
135 | .colorspace = V4L2_COLORSPACE_JPEG, | 135 | .colorspace = V4L2_COLORSPACE_JPEG, |
136 | .fmt = 1, | 136 | .fmt = 1, |
137 | .order = 2, | 137 | .order = 2, |
138 | }, { | 138 | }, { |
139 | .code = V4L2_MBUS_FMT_YVYU8_2X8_LE, | 139 | .code = V4L2_MBUS_FMT_YVYU8_2X8, |
140 | .colorspace = V4L2_COLORSPACE_JPEG, | 140 | .colorspace = V4L2_COLORSPACE_JPEG, |
141 | .fmt = 1, | 141 | .fmt = 1, |
142 | .order = 3, | 142 | .order = 3, |
@@ -972,7 +972,7 @@ static int mt9t112_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | |||
972 | struct v4l2_rect *rect = &a->c; | 972 | struct v4l2_rect *rect = &a->c; |
973 | 973 | ||
974 | return mt9t112_set_params(client, rect->width, rect->height, | 974 | return mt9t112_set_params(client, rect->width, rect->height, |
975 | V4L2_MBUS_FMT_YUYV8_2X8_BE); | 975 | V4L2_MBUS_FMT_UYVY8_2X8); |
976 | } | 976 | } |
977 | 977 | ||
978 | static int mt9t112_g_fmt(struct v4l2_subdev *sd, | 978 | static int mt9t112_g_fmt(struct v4l2_subdev *sd, |
@@ -983,7 +983,7 @@ static int mt9t112_g_fmt(struct v4l2_subdev *sd, | |||
983 | 983 | ||
984 | if (!priv->format) { | 984 | if (!priv->format) { |
985 | int ret = mt9t112_set_params(client, VGA_WIDTH, VGA_HEIGHT, | 985 | int ret = mt9t112_set_params(client, VGA_WIDTH, VGA_HEIGHT, |
986 | V4L2_MBUS_FMT_YUYV8_2X8_BE); | 986 | V4L2_MBUS_FMT_UYVY8_2X8); |
987 | if (ret < 0) | 987 | if (ret < 0) |
988 | return ret; | 988 | return ret; |
989 | } | 989 | } |
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index 929073e792c9..4ed51b1552e1 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c | |||
@@ -2545,19 +2545,11 @@ static int __init omap_vout_probe(struct platform_device *pdev) | |||
2545 | /* set the update mode */ | 2545 | /* set the update mode */ |
2546 | if (def_display->caps & | 2546 | if (def_display->caps & |
2547 | OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { | 2547 | OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { |
2548 | #ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE | ||
2549 | if (dssdrv->enable_te) | ||
2550 | dssdrv->enable_te(def_display, 1); | ||
2551 | if (dssdrv->set_update_mode) | ||
2552 | dssdrv->set_update_mode(def_display, | ||
2553 | OMAP_DSS_UPDATE_AUTO); | ||
2554 | #else /* MANUAL_UPDATE */ | ||
2555 | if (dssdrv->enable_te) | 2548 | if (dssdrv->enable_te) |
2556 | dssdrv->enable_te(def_display, 0); | 2549 | dssdrv->enable_te(def_display, 0); |
2557 | if (dssdrv->set_update_mode) | 2550 | if (dssdrv->set_update_mode) |
2558 | dssdrv->set_update_mode(def_display, | 2551 | dssdrv->set_update_mode(def_display, |
2559 | OMAP_DSS_UPDATE_MANUAL); | 2552 | OMAP_DSS_UPDATE_MANUAL); |
2560 | #endif | ||
2561 | } else { | 2553 | } else { |
2562 | if (dssdrv->set_update_mode) | 2554 | if (dssdrv->set_update_mode) |
2563 | dssdrv->set_update_mode(def_display, | 2555 | dssdrv->set_update_mode(def_display, |
diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c index f85b2ed8a2d8..926a5aa6f7f8 100644 --- a/drivers/media/video/omap24xxcam.c +++ b/drivers/media/video/omap24xxcam.c | |||
@@ -426,7 +426,7 @@ static void omap24xxcam_vbq_release(struct videobuf_queue *vbq, | |||
426 | dma->direction); | 426 | dma->direction); |
427 | dma->direction = DMA_NONE; | 427 | dma->direction = DMA_NONE; |
428 | } else { | 428 | } else { |
429 | videobuf_dma_unmap(vbq, videobuf_to_dma(vb)); | 429 | videobuf_dma_unmap(vbq->dev, videobuf_to_dma(vb)); |
430 | videobuf_dma_free(videobuf_to_dma(vb)); | 430 | videobuf_dma_free(videobuf_to_dma(vb)); |
431 | } | 431 | } |
432 | 432 | ||
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c deleted file mode 100644 index a10912097b7a..000000000000 --- a/drivers/media/video/ov511.c +++ /dev/null | |||
@@ -1,5995 +0,0 @@ | |||
1 | /* | ||
2 | * OmniVision OV511 Camera-to-USB Bridge Driver | ||
3 | * | ||
4 | * Copyright (c) 1999-2003 Mark W. McClelland | ||
5 | * Original decompression code Copyright 1998-2000 OmniVision Technologies | ||
6 | * Many improvements by Bret Wallach <bwallac1@san.rr.com> | ||
7 | * Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000) | ||
8 | * Snapshot code by Kevin Moore | ||
9 | * OV7620 fixes by Charl P. Botha <cpbotha@ieee.org> | ||
10 | * Changes by Claudio Matsuoka <claudio@conectiva.com> | ||
11 | * Original SAA7111A code by Dave Perks <dperks@ibm.net> | ||
12 | * URB error messages from pwc driver by Nemosoft | ||
13 | * generic_ioctl() code from videodev.c by Gerd Knorr and Alan Cox | ||
14 | * Memory management (rvmalloc) code from bttv driver, by Gerd Knorr and others | ||
15 | * | ||
16 | * Based on the Linux CPiA driver written by Peter Pregler, | ||
17 | * Scott J. Bertin and Johannes Erdfelt. | ||
18 | * | ||
19 | * Please see the file: Documentation/usb/ov511.txt | ||
20 | * and the website at: http://alpha.dyndns.org/ov511 | ||
21 | * for more info. | ||
22 | * | ||
23 | * This program is free software; you can redistribute it and/or modify it | ||
24 | * under the terms of the GNU General Public License as published by the | ||
25 | * Free Software Foundation; either version 2 of the License, or (at your | ||
26 | * option) any later version. | ||
27 | * | ||
28 | * This program is distributed in the hope that it will be useful, but | ||
29 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
30 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
31 | * for more details. | ||
32 | * | ||
33 | * You should have received a copy of the GNU General Public License | ||
34 | * along with this program; if not, write to the Free Software Foundation, | ||
35 | * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
36 | */ | ||
37 | |||
38 | #include <linux/module.h> | ||
39 | #include <linux/init.h> | ||
40 | #include <linux/vmalloc.h> | ||
41 | #include <linux/slab.h> | ||
42 | #include <linux/ctype.h> | ||
43 | #include <linux/pagemap.h> | ||
44 | #include <asm/processor.h> | ||
45 | #include <linux/mm.h> | ||
46 | #include <linux/device.h> | ||
47 | |||
48 | #if defined (__i386__) | ||
49 | #include <asm/cpufeature.h> | ||
50 | #endif | ||
51 | |||
52 | #include "ov511.h" | ||
53 | |||
54 | /* | ||
55 | * Version Information | ||
56 | */ | ||
57 | #define DRIVER_VERSION "v1.64 for Linux 2.5" | ||
58 | #define EMAIL "mark@alpha.dyndns.org" | ||
59 | #define DRIVER_AUTHOR "Mark McClelland <mark@alpha.dyndns.org> & Bret Wallach \ | ||
60 | & Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha \ | ||
61 | <cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>" | ||
62 | #define DRIVER_DESC "ov511 USB Camera Driver" | ||
63 | |||
64 | #define OV511_I2C_RETRIES 3 | ||
65 | #define ENABLE_Y_QUANTABLE 1 | ||
66 | #define ENABLE_UV_QUANTABLE 1 | ||
67 | |||
68 | #define OV511_MAX_UNIT_VIDEO 16 | ||
69 | |||
70 | /* Pixel count * bytes per YUV420 pixel (1.5) */ | ||
71 | #define MAX_FRAME_SIZE(w, h) ((w) * (h) * 3 / 2) | ||
72 | |||
73 | #define MAX_DATA_SIZE(w, h) (MAX_FRAME_SIZE(w, h) + sizeof(struct timeval)) | ||
74 | |||
75 | /* Max size * bytes per YUV420 pixel (1.5) + one extra isoc frame for safety */ | ||
76 | #define MAX_RAW_DATA_SIZE(w, h) ((w) * (h) * 3 / 2 + 1024) | ||
77 | |||
78 | #define FATAL_ERROR(rc) ((rc) < 0 && (rc) != -EPERM) | ||
79 | |||
80 | /********************************************************************** | ||
81 | * Module Parameters | ||
82 | * (See ov511.txt for detailed descriptions of these) | ||
83 | **********************************************************************/ | ||
84 | |||
85 | /* These variables (and all static globals) default to zero */ | ||
86 | static int autobright = 1; | ||
87 | static int autogain = 1; | ||
88 | static int autoexp = 1; | ||
89 | static int debug; | ||
90 | static int snapshot; | ||
91 | static int cams = 1; | ||
92 | static int compress; | ||
93 | static int testpat; | ||
94 | static int dumppix; | ||
95 | static int led = 1; | ||
96 | static int dump_bridge; | ||
97 | static int dump_sensor; | ||
98 | static int printph; | ||
99 | static int phy = 0x1f; | ||
100 | static int phuv = 0x05; | ||
101 | static int pvy = 0x06; | ||
102 | static int pvuv = 0x06; | ||
103 | static int qhy = 0x14; | ||
104 | static int qhuv = 0x03; | ||
105 | static int qvy = 0x04; | ||
106 | static int qvuv = 0x04; | ||
107 | static int lightfreq; | ||
108 | static int bandingfilter; | ||
109 | static int clockdiv = -1; | ||
110 | static int packetsize = -1; | ||
111 | static int framedrop = -1; | ||
112 | static int fastset; | ||
113 | static int force_palette; | ||
114 | static int backlight; | ||
115 | /* Bitmask marking allocated devices from 0 to OV511_MAX_UNIT_VIDEO */ | ||
116 | static unsigned long ov511_devused; | ||
117 | static int unit_video[OV511_MAX_UNIT_VIDEO]; | ||
118 | static int remove_zeros; | ||
119 | static int mirror; | ||
120 | static int ov518_color; | ||
121 | |||
122 | module_param(autobright, int, 0); | ||
123 | MODULE_PARM_DESC(autobright, "Sensor automatically changes brightness"); | ||
124 | module_param(autogain, int, 0); | ||
125 | MODULE_PARM_DESC(autogain, "Sensor automatically changes gain"); | ||
126 | module_param(autoexp, int, 0); | ||
127 | MODULE_PARM_DESC(autoexp, "Sensor automatically changes exposure"); | ||
128 | module_param(debug, int, 0); | ||
129 | MODULE_PARM_DESC(debug, | ||
130 | "Debug level: 0=none, 1=inits, 2=warning, 3=config, 4=functions, 5=max"); | ||
131 | module_param(snapshot, int, 0); | ||
132 | MODULE_PARM_DESC(snapshot, "Enable snapshot mode"); | ||
133 | module_param(cams, int, 0); | ||
134 | MODULE_PARM_DESC(cams, "Number of simultaneous cameras"); | ||
135 | module_param(compress, int, 0); | ||
136 | MODULE_PARM_DESC(compress, "Turn on compression"); | ||
137 | module_param(testpat, int, 0); | ||
138 | MODULE_PARM_DESC(testpat, | ||
139 | "Replace image with vertical bar testpattern (only partially working)"); | ||
140 | module_param(dumppix, int, 0); | ||
141 | MODULE_PARM_DESC(dumppix, "Dump raw pixel data"); | ||
142 | module_param(led, int, 0); | ||
143 | MODULE_PARM_DESC(led, | ||
144 | "LED policy (OV511+ or later). 0=off, 1=on (default), 2=auto (on when open)"); | ||
145 | module_param(dump_bridge, int, 0); | ||
146 | MODULE_PARM_DESC(dump_bridge, "Dump the bridge registers"); | ||
147 | module_param(dump_sensor, int, 0); | ||
148 | MODULE_PARM_DESC(dump_sensor, "Dump the sensor registers"); | ||
149 | module_param(printph, int, 0); | ||
150 | MODULE_PARM_DESC(printph, "Print frame start/end headers"); | ||
151 | module_param(phy, int, 0); | ||
152 | MODULE_PARM_DESC(phy, "Prediction range (horiz. Y)"); | ||
153 | module_param(phuv, int, 0); | ||
154 | MODULE_PARM_DESC(phuv, "Prediction range (horiz. UV)"); | ||
155 | module_param(pvy, int, 0); | ||
156 | MODULE_PARM_DESC(pvy, "Prediction range (vert. Y)"); | ||
157 | module_param(pvuv, int, 0); | ||
158 | MODULE_PARM_DESC(pvuv, "Prediction range (vert. UV)"); | ||
159 | module_param(qhy, int, 0); | ||
160 | MODULE_PARM_DESC(qhy, "Quantization threshold (horiz. Y)"); | ||
161 | module_param(qhuv, int, 0); | ||
162 | MODULE_PARM_DESC(qhuv, "Quantization threshold (horiz. UV)"); | ||
163 | module_param(qvy, int, 0); | ||
164 | MODULE_PARM_DESC(qvy, "Quantization threshold (vert. Y)"); | ||
165 | module_param(qvuv, int, 0); | ||
166 | MODULE_PARM_DESC(qvuv, "Quantization threshold (vert. UV)"); | ||
167 | module_param(lightfreq, int, 0); | ||
168 | MODULE_PARM_DESC(lightfreq, | ||
169 | "Light frequency. Set to 50 or 60 Hz, or zero for default settings"); | ||
170 | module_param(bandingfilter, int, 0); | ||
171 | MODULE_PARM_DESC(bandingfilter, | ||
172 | "Enable banding filter (to reduce effects of fluorescent lighting)"); | ||
173 | module_param(clockdiv, int, 0); | ||
174 | MODULE_PARM_DESC(clockdiv, "Force pixel clock divisor to a specific value"); | ||
175 | module_param(packetsize, int, 0); | ||
176 | MODULE_PARM_DESC(packetsize, "Force a specific isoc packet size"); | ||
177 | module_param(framedrop, int, 0); | ||
178 | MODULE_PARM_DESC(framedrop, "Force a specific frame drop register setting"); | ||
179 | module_param(fastset, int, 0); | ||
180 | MODULE_PARM_DESC(fastset, "Allows picture settings to take effect immediately"); | ||
181 | module_param(force_palette, int, 0); | ||
182 | MODULE_PARM_DESC(force_palette, "Force the palette to a specific value"); | ||
183 | module_param(backlight, int, 0); | ||
184 | MODULE_PARM_DESC(backlight, "For objects that are lit from behind"); | ||
185 | static unsigned int num_uv; | ||
186 | module_param_array(unit_video, int, &num_uv, 0); | ||
187 | MODULE_PARM_DESC(unit_video, | ||
188 | "Force use of specific minor number(s). 0 is not allowed."); | ||
189 | module_param(remove_zeros, int, 0); | ||
190 | MODULE_PARM_DESC(remove_zeros, | ||
191 | "Remove zero-padding from uncompressed incoming data"); | ||
192 | module_param(mirror, int, 0); | ||
193 | MODULE_PARM_DESC(mirror, "Reverse image horizontally"); | ||
194 | module_param(ov518_color, int, 0); | ||
195 | MODULE_PARM_DESC(ov518_color, "Enable OV518 color (experimental)"); | ||
196 | |||
197 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
198 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
199 | MODULE_LICENSE("GPL"); | ||
200 | |||
201 | /********************************************************************** | ||
202 | * Miscellaneous Globals | ||
203 | **********************************************************************/ | ||
204 | |||
205 | static struct usb_driver ov511_driver; | ||
206 | |||
207 | /* Number of times to retry a failed I2C transaction. Increase this if you | ||
208 | * are getting "Failed to read sensor ID..." */ | ||
209 | static const int i2c_detect_tries = 5; | ||
210 | |||
211 | static struct usb_device_id device_table [] = { | ||
212 | { USB_DEVICE(VEND_OMNIVISION, PROD_OV511) }, | ||
213 | { USB_DEVICE(VEND_OMNIVISION, PROD_OV511PLUS) }, | ||
214 | { USB_DEVICE(VEND_MATTEL, PROD_ME2CAM) }, | ||
215 | { } /* Terminating entry */ | ||
216 | }; | ||
217 | |||
218 | MODULE_DEVICE_TABLE (usb, device_table); | ||
219 | |||
220 | static unsigned char yQuanTable511[] = OV511_YQUANTABLE; | ||
221 | static unsigned char uvQuanTable511[] = OV511_UVQUANTABLE; | ||
222 | static unsigned char yQuanTable518[] = OV518_YQUANTABLE; | ||
223 | static unsigned char uvQuanTable518[] = OV518_UVQUANTABLE; | ||
224 | |||
225 | /********************************************************************** | ||
226 | * Symbolic Names | ||
227 | **********************************************************************/ | ||
228 | |||
229 | /* Known OV511-based cameras */ | ||
230 | static struct symbolic_list camlist[] = { | ||
231 | { 0, "Generic Camera (no ID)" }, | ||
232 | { 1, "Mustek WCam 3X" }, | ||
233 | { 3, "D-Link DSB-C300" }, | ||
234 | { 4, "Generic OV511/OV7610" }, | ||
235 | { 5, "Puretek PT-6007" }, | ||
236 | { 6, "Lifeview USB Life TV (NTSC)" }, | ||
237 | { 21, "Creative Labs WebCam 3" }, | ||
238 | { 22, "Lifeview USB Life TV (PAL D/K+B/G)" }, | ||
239 | { 36, "Koala-Cam" }, | ||
240 | { 38, "Lifeview USB Life TV (PAL)" }, | ||
241 | { 41, "Samsung Anycam MPC-M10" }, | ||
242 | { 43, "Mtekvision Zeca MV402" }, | ||
243 | { 46, "Suma eON" }, | ||
244 | { 70, "Lifeview USB Life TV (PAL/SECAM)" }, | ||
245 | { 100, "Lifeview RoboCam" }, | ||
246 | { 102, "AverMedia InterCam Elite" }, | ||
247 | { 112, "MediaForte MV300" }, /* or OV7110 evaluation kit */ | ||
248 | { 134, "Ezonics EZCam II" }, | ||
249 | { 192, "Webeye 2000B" }, | ||
250 | { 253, "Alpha Vision Tech. AlphaCam SE" }, | ||
251 | { -1, NULL } | ||
252 | }; | ||
253 | |||
254 | /* Video4Linux1 Palettes */ | ||
255 | static struct symbolic_list v4l1_plist[] = { | ||
256 | { VIDEO_PALETTE_GREY, "GREY" }, | ||
257 | { VIDEO_PALETTE_HI240, "HI240" }, | ||
258 | { VIDEO_PALETTE_RGB565, "RGB565" }, | ||
259 | { VIDEO_PALETTE_RGB24, "RGB24" }, | ||
260 | { VIDEO_PALETTE_RGB32, "RGB32" }, | ||
261 | { VIDEO_PALETTE_RGB555, "RGB555" }, | ||
262 | { VIDEO_PALETTE_YUV422, "YUV422" }, | ||
263 | { VIDEO_PALETTE_YUYV, "YUYV" }, | ||
264 | { VIDEO_PALETTE_UYVY, "UYVY" }, | ||
265 | { VIDEO_PALETTE_YUV420, "YUV420" }, | ||
266 | { VIDEO_PALETTE_YUV411, "YUV411" }, | ||
267 | { VIDEO_PALETTE_RAW, "RAW" }, | ||
268 | { VIDEO_PALETTE_YUV422P,"YUV422P" }, | ||
269 | { VIDEO_PALETTE_YUV411P,"YUV411P" }, | ||
270 | { VIDEO_PALETTE_YUV420P,"YUV420P" }, | ||
271 | { VIDEO_PALETTE_YUV410P,"YUV410P" }, | ||
272 | { -1, NULL } | ||
273 | }; | ||
274 | |||
275 | static struct symbolic_list brglist[] = { | ||
276 | { BRG_OV511, "OV511" }, | ||
277 | { BRG_OV511PLUS, "OV511+" }, | ||
278 | { BRG_OV518, "OV518" }, | ||
279 | { BRG_OV518PLUS, "OV518+" }, | ||
280 | { -1, NULL } | ||
281 | }; | ||
282 | |||
283 | static struct symbolic_list senlist[] = { | ||
284 | { SEN_OV76BE, "OV76BE" }, | ||
285 | { SEN_OV7610, "OV7610" }, | ||
286 | { SEN_OV7620, "OV7620" }, | ||
287 | { SEN_OV7620AE, "OV7620AE" }, | ||
288 | { SEN_OV6620, "OV6620" }, | ||
289 | { SEN_OV6630, "OV6630" }, | ||
290 | { SEN_OV6630AE, "OV6630AE" }, | ||
291 | { SEN_OV6630AF, "OV6630AF" }, | ||
292 | { SEN_OV8600, "OV8600" }, | ||
293 | { SEN_KS0127, "KS0127" }, | ||
294 | { SEN_KS0127B, "KS0127B" }, | ||
295 | { SEN_SAA7111A, "SAA7111A" }, | ||
296 | { -1, NULL } | ||
297 | }; | ||
298 | |||
299 | /* URB error codes: */ | ||
300 | static struct symbolic_list urb_errlist[] = { | ||
301 | { -ENOSR, "Buffer error (overrun)" }, | ||
302 | { -EPIPE, "Stalled (device not responding)" }, | ||
303 | { -EOVERFLOW, "Babble (device sends too much data)" }, | ||
304 | { -EPROTO, "Bit-stuff error (bad cable?)" }, | ||
305 | { -EILSEQ, "CRC/Timeout (bad cable?)" }, | ||
306 | { -ETIME, "Device does not respond to token" }, | ||
307 | { -ETIMEDOUT, "Device does not respond to command" }, | ||
308 | { -1, NULL } | ||
309 | }; | ||
310 | |||
311 | /********************************************************************** | ||
312 | * Memory management | ||
313 | **********************************************************************/ | ||
314 | static void * | ||
315 | rvmalloc(unsigned long size) | ||
316 | { | ||
317 | void *mem; | ||
318 | unsigned long adr; | ||
319 | |||
320 | size = PAGE_ALIGN(size); | ||
321 | mem = vmalloc_32(size); | ||
322 | if (!mem) | ||
323 | return NULL; | ||
324 | |||
325 | memset(mem, 0, size); /* Clear the ram out, no junk to the user */ | ||
326 | adr = (unsigned long) mem; | ||
327 | while (size > 0) { | ||
328 | SetPageReserved(vmalloc_to_page((void *)adr)); | ||
329 | adr += PAGE_SIZE; | ||
330 | size -= PAGE_SIZE; | ||
331 | } | ||
332 | |||
333 | return mem; | ||
334 | } | ||
335 | |||
336 | static void | ||
337 | rvfree(void *mem, unsigned long size) | ||
338 | { | ||
339 | unsigned long adr; | ||
340 | |||
341 | if (!mem) | ||
342 | return; | ||
343 | |||
344 | adr = (unsigned long) mem; | ||
345 | while ((long) size > 0) { | ||
346 | ClearPageReserved(vmalloc_to_page((void *)adr)); | ||
347 | adr += PAGE_SIZE; | ||
348 | size -= PAGE_SIZE; | ||
349 | } | ||
350 | vfree(mem); | ||
351 | } | ||
352 | |||
353 | /********************************************************************** | ||
354 | * | ||
355 | * Register I/O | ||
356 | * | ||
357 | **********************************************************************/ | ||
358 | |||
359 | /* Write an OV51x register */ | ||
360 | static int | ||
361 | reg_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value) | ||
362 | { | ||
363 | int rc; | ||
364 | |||
365 | PDEBUG(5, "0x%02X:0x%02X", reg, value); | ||
366 | |||
367 | mutex_lock(&ov->cbuf_lock); | ||
368 | ov->cbuf[0] = value; | ||
369 | rc = usb_control_msg(ov->dev, | ||
370 | usb_sndctrlpipe(ov->dev, 0), | ||
371 | (ov->bclass == BCL_OV518)?1:2 /* REG_IO */, | ||
372 | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
373 | 0, (__u16)reg, &ov->cbuf[0], 1, 1000); | ||
374 | mutex_unlock(&ov->cbuf_lock); | ||
375 | |||
376 | if (rc < 0) | ||
377 | err("reg write: error %d: %s", rc, symbolic(urb_errlist, rc)); | ||
378 | |||
379 | return rc; | ||
380 | } | ||
381 | |||
382 | /* Read from an OV51x register */ | ||
383 | /* returns: negative is error, pos or zero is data */ | ||
384 | static int | ||
385 | reg_r(struct usb_ov511 *ov, unsigned char reg) | ||
386 | { | ||
387 | int rc; | ||
388 | |||
389 | mutex_lock(&ov->cbuf_lock); | ||
390 | rc = usb_control_msg(ov->dev, | ||
391 | usb_rcvctrlpipe(ov->dev, 0), | ||
392 | (ov->bclass == BCL_OV518)?1:3 /* REG_IO */, | ||
393 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
394 | 0, (__u16)reg, &ov->cbuf[0], 1, 1000); | ||
395 | |||
396 | if (rc < 0) { | ||
397 | err("reg read: error %d: %s", rc, symbolic(urb_errlist, rc)); | ||
398 | } else { | ||
399 | rc = ov->cbuf[0]; | ||
400 | PDEBUG(5, "0x%02X:0x%02X", reg, ov->cbuf[0]); | ||
401 | } | ||
402 | |||
403 | mutex_unlock(&ov->cbuf_lock); | ||
404 | |||
405 | return rc; | ||
406 | } | ||
407 | |||
408 | /* | ||
409 | * Writes bits at positions specified by mask to an OV51x reg. Bits that are in | ||
410 | * the same position as 1's in "mask" are cleared and set to "value". Bits | ||
411 | * that are in the same position as 0's in "mask" are preserved, regardless | ||
412 | * of their respective state in "value". | ||
413 | */ | ||
414 | static int | ||
415 | reg_w_mask(struct usb_ov511 *ov, | ||
416 | unsigned char reg, | ||
417 | unsigned char value, | ||
418 | unsigned char mask) | ||
419 | { | ||
420 | int ret; | ||
421 | unsigned char oldval, newval; | ||
422 | |||
423 | ret = reg_r(ov, reg); | ||
424 | if (ret < 0) | ||
425 | return ret; | ||
426 | |||
427 | oldval = (unsigned char) ret; | ||
428 | oldval &= (~mask); /* Clear the masked bits */ | ||
429 | value &= mask; /* Enforce mask on value */ | ||
430 | newval = oldval | value; /* Set the desired bits */ | ||
431 | |||
432 | return (reg_w(ov, reg, newval)); | ||
433 | } | ||
434 | |||
435 | /* | ||
436 | * Writes multiple (n) byte value to a single register. Only valid with certain | ||
437 | * registers (0x30 and 0xc4 - 0xce). | ||
438 | */ | ||
439 | static int | ||
440 | ov518_reg_w32(struct usb_ov511 *ov, unsigned char reg, u32 val, int n) | ||
441 | { | ||
442 | int rc; | ||
443 | |||
444 | PDEBUG(5, "0x%02X:%7d, n=%d", reg, val, n); | ||
445 | |||
446 | mutex_lock(&ov->cbuf_lock); | ||
447 | |||
448 | *((__le32 *)ov->cbuf) = __cpu_to_le32(val); | ||
449 | |||
450 | rc = usb_control_msg(ov->dev, | ||
451 | usb_sndctrlpipe(ov->dev, 0), | ||
452 | 1 /* REG_IO */, | ||
453 | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
454 | 0, (__u16)reg, ov->cbuf, n, 1000); | ||
455 | mutex_unlock(&ov->cbuf_lock); | ||
456 | |||
457 | if (rc < 0) | ||
458 | err("reg write multiple: error %d: %s", rc, | ||
459 | symbolic(urb_errlist, rc)); | ||
460 | |||
461 | return rc; | ||
462 | } | ||
463 | |||
464 | static int | ||
465 | ov511_upload_quan_tables(struct usb_ov511 *ov) | ||
466 | { | ||
467 | unsigned char *pYTable = yQuanTable511; | ||
468 | unsigned char *pUVTable = uvQuanTable511; | ||
469 | unsigned char val0, val1; | ||
470 | int i, rc, reg = R511_COMP_LUT_BEGIN; | ||
471 | |||
472 | PDEBUG(4, "Uploading quantization tables"); | ||
473 | |||
474 | for (i = 0; i < OV511_QUANTABLESIZE / 2; i++) { | ||
475 | if (ENABLE_Y_QUANTABLE) { | ||
476 | val0 = *pYTable++; | ||
477 | val1 = *pYTable++; | ||
478 | val0 &= 0x0f; | ||
479 | val1 &= 0x0f; | ||
480 | val0 |= val1 << 4; | ||
481 | rc = reg_w(ov, reg, val0); | ||
482 | if (rc < 0) | ||
483 | return rc; | ||
484 | } | ||
485 | |||
486 | if (ENABLE_UV_QUANTABLE) { | ||
487 | val0 = *pUVTable++; | ||
488 | val1 = *pUVTable++; | ||
489 | val0 &= 0x0f; | ||
490 | val1 &= 0x0f; | ||
491 | val0 |= val1 << 4; | ||
492 | rc = reg_w(ov, reg + OV511_QUANTABLESIZE/2, val0); | ||
493 | if (rc < 0) | ||
494 | return rc; | ||
495 | } | ||
496 | |||
497 | reg++; | ||
498 | } | ||
499 | |||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | /* OV518 quantization tables are 8x4 (instead of 8x8) */ | ||
504 | static int | ||
505 | ov518_upload_quan_tables(struct usb_ov511 *ov) | ||
506 | { | ||
507 | unsigned char *pYTable = yQuanTable518; | ||
508 | unsigned char *pUVTable = uvQuanTable518; | ||
509 | unsigned char val0, val1; | ||
510 | int i, rc, reg = R511_COMP_LUT_BEGIN; | ||
511 | |||
512 | PDEBUG(4, "Uploading quantization tables"); | ||
513 | |||
514 | for (i = 0; i < OV518_QUANTABLESIZE / 2; i++) { | ||
515 | if (ENABLE_Y_QUANTABLE) { | ||
516 | val0 = *pYTable++; | ||
517 | val1 = *pYTable++; | ||
518 | val0 &= 0x0f; | ||
519 | val1 &= 0x0f; | ||
520 | val0 |= val1 << 4; | ||
521 | rc = reg_w(ov, reg, val0); | ||
522 | if (rc < 0) | ||
523 | return rc; | ||
524 | } | ||
525 | |||
526 | if (ENABLE_UV_QUANTABLE) { | ||
527 | val0 = *pUVTable++; | ||
528 | val1 = *pUVTable++; | ||
529 | val0 &= 0x0f; | ||
530 | val1 &= 0x0f; | ||
531 | val0 |= val1 << 4; | ||
532 | rc = reg_w(ov, reg + OV518_QUANTABLESIZE/2, val0); | ||
533 | if (rc < 0) | ||
534 | return rc; | ||
535 | } | ||
536 | |||
537 | reg++; | ||
538 | } | ||
539 | |||
540 | return 0; | ||
541 | } | ||
542 | |||
543 | static int | ||
544 | ov51x_reset(struct usb_ov511 *ov, unsigned char reset_type) | ||
545 | { | ||
546 | int rc; | ||
547 | |||
548 | /* Setting bit 0 not allowed on 518/518Plus */ | ||
549 | if (ov->bclass == BCL_OV518) | ||
550 | reset_type &= 0xfe; | ||
551 | |||
552 | PDEBUG(4, "Reset: type=0x%02X", reset_type); | ||
553 | |||
554 | rc = reg_w(ov, R51x_SYS_RESET, reset_type); | ||
555 | rc = reg_w(ov, R51x_SYS_RESET, 0); | ||
556 | |||
557 | if (rc < 0) | ||
558 | err("reset: command failed"); | ||
559 | |||
560 | return rc; | ||
561 | } | ||
562 | |||
563 | /********************************************************************** | ||
564 | * | ||
565 | * Low-level I2C I/O functions | ||
566 | * | ||
567 | **********************************************************************/ | ||
568 | |||
569 | /* NOTE: Do not call this function directly! | ||
570 | * The OV518 I2C I/O procedure is different, hence, this function. | ||
571 | * This is normally only called from i2c_w(). Note that this function | ||
572 | * always succeeds regardless of whether the sensor is present and working. | ||
573 | */ | ||
574 | static int | ||
575 | ov518_i2c_write_internal(struct usb_ov511 *ov, | ||
576 | unsigned char reg, | ||
577 | unsigned char value) | ||
578 | { | ||
579 | int rc; | ||
580 | |||
581 | PDEBUG(5, "0x%02X:0x%02X", reg, value); | ||
582 | |||
583 | /* Select camera register */ | ||
584 | rc = reg_w(ov, R51x_I2C_SADDR_3, reg); | ||
585 | if (rc < 0) | ||
586 | return rc; | ||
587 | |||
588 | /* Write "value" to I2C data port of OV511 */ | ||
589 | rc = reg_w(ov, R51x_I2C_DATA, value); | ||
590 | if (rc < 0) | ||
591 | return rc; | ||
592 | |||
593 | /* Initiate 3-byte write cycle */ | ||
594 | rc = reg_w(ov, R518_I2C_CTL, 0x01); | ||
595 | if (rc < 0) | ||
596 | return rc; | ||
597 | |||
598 | return 0; | ||
599 | } | ||
600 | |||
601 | /* NOTE: Do not call this function directly! */ | ||
602 | static int | ||
603 | ov511_i2c_write_internal(struct usb_ov511 *ov, | ||
604 | unsigned char reg, | ||
605 | unsigned char value) | ||
606 | { | ||
607 | int rc, retries; | ||
608 | |||
609 | PDEBUG(5, "0x%02X:0x%02X", reg, value); | ||
610 | |||
611 | /* Three byte write cycle */ | ||
612 | for (retries = OV511_I2C_RETRIES; ; ) { | ||
613 | /* Select camera register */ | ||
614 | rc = reg_w(ov, R51x_I2C_SADDR_3, reg); | ||
615 | if (rc < 0) | ||
616 | break; | ||
617 | |||
618 | /* Write "value" to I2C data port of OV511 */ | ||
619 | rc = reg_w(ov, R51x_I2C_DATA, value); | ||
620 | if (rc < 0) | ||
621 | break; | ||
622 | |||
623 | /* Initiate 3-byte write cycle */ | ||
624 | rc = reg_w(ov, R511_I2C_CTL, 0x01); | ||
625 | if (rc < 0) | ||
626 | break; | ||
627 | |||
628 | /* Retry until idle */ | ||
629 | do { | ||
630 | rc = reg_r(ov, R511_I2C_CTL); | ||
631 | } while (rc > 0 && ((rc&1) == 0)); | ||
632 | if (rc < 0) | ||
633 | break; | ||
634 | |||
635 | /* Ack? */ | ||
636 | if ((rc&2) == 0) { | ||
637 | rc = 0; | ||
638 | break; | ||
639 | } | ||
640 | #if 0 | ||
641 | /* I2C abort */ | ||
642 | reg_w(ov, R511_I2C_CTL, 0x10); | ||
643 | #endif | ||
644 | if (--retries < 0) { | ||
645 | err("i2c write retries exhausted"); | ||
646 | rc = -1; | ||
647 | break; | ||
648 | } | ||
649 | } | ||
650 | |||
651 | return rc; | ||
652 | } | ||
653 | |||
654 | /* NOTE: Do not call this function directly! | ||
655 | * The OV518 I2C I/O procedure is different, hence, this function. | ||
656 | * This is normally only called from i2c_r(). Note that this function | ||
657 | * always succeeds regardless of whether the sensor is present and working. | ||
658 | */ | ||
659 | static int | ||
660 | ov518_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg) | ||
661 | { | ||
662 | int rc, value; | ||
663 | |||
664 | /* Select camera register */ | ||
665 | rc = reg_w(ov, R51x_I2C_SADDR_2, reg); | ||
666 | if (rc < 0) | ||
667 | return rc; | ||
668 | |||
669 | /* Initiate 2-byte write cycle */ | ||
670 | rc = reg_w(ov, R518_I2C_CTL, 0x03); | ||
671 | if (rc < 0) | ||
672 | return rc; | ||
673 | |||
674 | /* Initiate 2-byte read cycle */ | ||
675 | rc = reg_w(ov, R518_I2C_CTL, 0x05); | ||
676 | if (rc < 0) | ||
677 | return rc; | ||
678 | |||
679 | value = reg_r(ov, R51x_I2C_DATA); | ||
680 | |||
681 | PDEBUG(5, "0x%02X:0x%02X", reg, value); | ||
682 | |||
683 | return value; | ||
684 | } | ||
685 | |||
686 | /* NOTE: Do not call this function directly! | ||
687 | * returns: negative is error, pos or zero is data */ | ||
688 | static int | ||
689 | ov511_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg) | ||
690 | { | ||
691 | int rc, value, retries; | ||
692 | |||
693 | /* Two byte write cycle */ | ||
694 | for (retries = OV511_I2C_RETRIES; ; ) { | ||
695 | /* Select camera register */ | ||
696 | rc = reg_w(ov, R51x_I2C_SADDR_2, reg); | ||
697 | if (rc < 0) | ||
698 | return rc; | ||
699 | |||
700 | /* Initiate 2-byte write cycle */ | ||
701 | rc = reg_w(ov, R511_I2C_CTL, 0x03); | ||
702 | if (rc < 0) | ||
703 | return rc; | ||
704 | |||
705 | /* Retry until idle */ | ||
706 | do { | ||
707 | rc = reg_r(ov, R511_I2C_CTL); | ||
708 | } while (rc > 0 && ((rc & 1) == 0)); | ||
709 | if (rc < 0) | ||
710 | return rc; | ||
711 | |||
712 | if ((rc&2) == 0) /* Ack? */ | ||
713 | break; | ||
714 | |||
715 | /* I2C abort */ | ||
716 | reg_w(ov, R511_I2C_CTL, 0x10); | ||
717 | |||
718 | if (--retries < 0) { | ||
719 | err("i2c write retries exhausted"); | ||
720 | return -1; | ||
721 | } | ||
722 | } | ||
723 | |||
724 | /* Two byte read cycle */ | ||
725 | for (retries = OV511_I2C_RETRIES; ; ) { | ||
726 | /* Initiate 2-byte read cycle */ | ||
727 | rc = reg_w(ov, R511_I2C_CTL, 0x05); | ||
728 | if (rc < 0) | ||
729 | return rc; | ||
730 | |||
731 | /* Retry until idle */ | ||
732 | do { | ||
733 | rc = reg_r(ov, R511_I2C_CTL); | ||
734 | } while (rc > 0 && ((rc&1) == 0)); | ||
735 | if (rc < 0) | ||
736 | return rc; | ||
737 | |||
738 | if ((rc&2) == 0) /* Ack? */ | ||
739 | break; | ||
740 | |||
741 | /* I2C abort */ | ||
742 | rc = reg_w(ov, R511_I2C_CTL, 0x10); | ||
743 | if (rc < 0) | ||
744 | return rc; | ||
745 | |||
746 | if (--retries < 0) { | ||
747 | err("i2c read retries exhausted"); | ||
748 | return -1; | ||
749 | } | ||
750 | } | ||
751 | |||
752 | value = reg_r(ov, R51x_I2C_DATA); | ||
753 | |||
754 | PDEBUG(5, "0x%02X:0x%02X", reg, value); | ||
755 | |||
756 | /* This is needed to make i2c_w() work */ | ||
757 | rc = reg_w(ov, R511_I2C_CTL, 0x05); | ||
758 | if (rc < 0) | ||
759 | return rc; | ||
760 | |||
761 | return value; | ||
762 | } | ||
763 | |||
764 | /* returns: negative is error, pos or zero is data */ | ||
765 | static int | ||
766 | i2c_r(struct usb_ov511 *ov, unsigned char reg) | ||
767 | { | ||
768 | int rc; | ||
769 | |||
770 | mutex_lock(&ov->i2c_lock); | ||
771 | |||
772 | if (ov->bclass == BCL_OV518) | ||
773 | rc = ov518_i2c_read_internal(ov, reg); | ||
774 | else | ||
775 | rc = ov511_i2c_read_internal(ov, reg); | ||
776 | |||
777 | mutex_unlock(&ov->i2c_lock); | ||
778 | |||
779 | return rc; | ||
780 | } | ||
781 | |||
782 | static int | ||
783 | i2c_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value) | ||
784 | { | ||
785 | int rc; | ||
786 | |||
787 | mutex_lock(&ov->i2c_lock); | ||
788 | |||
789 | if (ov->bclass == BCL_OV518) | ||
790 | rc = ov518_i2c_write_internal(ov, reg, value); | ||
791 | else | ||
792 | rc = ov511_i2c_write_internal(ov, reg, value); | ||
793 | |||
794 | mutex_unlock(&ov->i2c_lock); | ||
795 | |||
796 | return rc; | ||
797 | } | ||
798 | |||
799 | /* Do not call this function directly! */ | ||
800 | static int | ||
801 | ov51x_i2c_write_mask_internal(struct usb_ov511 *ov, | ||
802 | unsigned char reg, | ||
803 | unsigned char value, | ||
804 | unsigned char mask) | ||
805 | { | ||
806 | int rc; | ||
807 | unsigned char oldval, newval; | ||
808 | |||
809 | if (mask == 0xff) { | ||
810 | newval = value; | ||
811 | } else { | ||
812 | if (ov->bclass == BCL_OV518) | ||
813 | rc = ov518_i2c_read_internal(ov, reg); | ||
814 | else | ||
815 | rc = ov511_i2c_read_internal(ov, reg); | ||
816 | if (rc < 0) | ||
817 | return rc; | ||
818 | |||
819 | oldval = (unsigned char) rc; | ||
820 | oldval &= (~mask); /* Clear the masked bits */ | ||
821 | value &= mask; /* Enforce mask on value */ | ||
822 | newval = oldval | value; /* Set the desired bits */ | ||
823 | } | ||
824 | |||
825 | if (ov->bclass == BCL_OV518) | ||
826 | return (ov518_i2c_write_internal(ov, reg, newval)); | ||
827 | else | ||
828 | return (ov511_i2c_write_internal(ov, reg, newval)); | ||
829 | } | ||
830 | |||
831 | /* Writes bits at positions specified by mask to an I2C reg. Bits that are in | ||
832 | * the same position as 1's in "mask" are cleared and set to "value". Bits | ||
833 | * that are in the same position as 0's in "mask" are preserved, regardless | ||
834 | * of their respective state in "value". | ||
835 | */ | ||
836 | static int | ||
837 | i2c_w_mask(struct usb_ov511 *ov, | ||
838 | unsigned char reg, | ||
839 | unsigned char value, | ||
840 | unsigned char mask) | ||
841 | { | ||
842 | int rc; | ||
843 | |||
844 | mutex_lock(&ov->i2c_lock); | ||
845 | rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask); | ||
846 | mutex_unlock(&ov->i2c_lock); | ||
847 | |||
848 | return rc; | ||
849 | } | ||
850 | |||
851 | /* Set the read and write slave IDs. The "slave" argument is the write slave, | ||
852 | * and the read slave will be set to (slave + 1). ov->i2c_lock should be held | ||
853 | * when calling this. This should not be called from outside the i2c I/O | ||
854 | * functions. | ||
855 | */ | ||
856 | static int | ||
857 | i2c_set_slave_internal(struct usb_ov511 *ov, unsigned char slave) | ||
858 | { | ||
859 | int rc; | ||
860 | |||
861 | rc = reg_w(ov, R51x_I2C_W_SID, slave); | ||
862 | if (rc < 0) | ||
863 | return rc; | ||
864 | |||
865 | rc = reg_w(ov, R51x_I2C_R_SID, slave + 1); | ||
866 | if (rc < 0) | ||
867 | return rc; | ||
868 | |||
869 | return 0; | ||
870 | } | ||
871 | |||
872 | /* Write to a specific I2C slave ID and register, using the specified mask */ | ||
873 | static int | ||
874 | i2c_w_slave(struct usb_ov511 *ov, | ||
875 | unsigned char slave, | ||
876 | unsigned char reg, | ||
877 | unsigned char value, | ||
878 | unsigned char mask) | ||
879 | { | ||
880 | int rc = 0; | ||
881 | |||
882 | mutex_lock(&ov->i2c_lock); | ||
883 | |||
884 | /* Set new slave IDs */ | ||
885 | rc = i2c_set_slave_internal(ov, slave); | ||
886 | if (rc < 0) | ||
887 | goto out; | ||
888 | |||
889 | rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask); | ||
890 | |||
891 | out: | ||
892 | /* Restore primary IDs */ | ||
893 | if (i2c_set_slave_internal(ov, ov->primary_i2c_slave) < 0) | ||
894 | err("Couldn't restore primary I2C slave"); | ||
895 | |||
896 | mutex_unlock(&ov->i2c_lock); | ||
897 | return rc; | ||
898 | } | ||
899 | |||
900 | /* Read from a specific I2C slave ID and register */ | ||
901 | static int | ||
902 | i2c_r_slave(struct usb_ov511 *ov, | ||
903 | unsigned char slave, | ||
904 | unsigned char reg) | ||
905 | { | ||
906 | int rc; | ||
907 | |||
908 | mutex_lock(&ov->i2c_lock); | ||
909 | |||
910 | /* Set new slave IDs */ | ||
911 | rc = i2c_set_slave_internal(ov, slave); | ||
912 | if (rc < 0) | ||
913 | goto out; | ||
914 | |||
915 | if (ov->bclass == BCL_OV518) | ||
916 | rc = ov518_i2c_read_internal(ov, reg); | ||
917 | else | ||
918 | rc = ov511_i2c_read_internal(ov, reg); | ||
919 | |||
920 | out: | ||
921 | /* Restore primary IDs */ | ||
922 | if (i2c_set_slave_internal(ov, ov->primary_i2c_slave) < 0) | ||
923 | err("Couldn't restore primary I2C slave"); | ||
924 | |||
925 | mutex_unlock(&ov->i2c_lock); | ||
926 | return rc; | ||
927 | } | ||
928 | |||
929 | /* Sets I2C read and write slave IDs. Returns <0 for error */ | ||
930 | static int | ||
931 | ov51x_set_slave_ids(struct usb_ov511 *ov, unsigned char sid) | ||
932 | { | ||
933 | int rc; | ||
934 | |||
935 | mutex_lock(&ov->i2c_lock); | ||
936 | |||
937 | rc = i2c_set_slave_internal(ov, sid); | ||
938 | if (rc < 0) | ||
939 | goto out; | ||
940 | |||
941 | // FIXME: Is this actually necessary? | ||
942 | rc = ov51x_reset(ov, OV511_RESET_NOREGS); | ||
943 | out: | ||
944 | mutex_unlock(&ov->i2c_lock); | ||
945 | return rc; | ||
946 | } | ||
947 | |||
948 | static int | ||
949 | write_regvals(struct usb_ov511 *ov, struct ov511_regvals * pRegvals) | ||
950 | { | ||
951 | int rc; | ||
952 | |||
953 | while (pRegvals->bus != OV511_DONE_BUS) { | ||
954 | if (pRegvals->bus == OV511_REG_BUS) { | ||
955 | if ((rc = reg_w(ov, pRegvals->reg, pRegvals->val)) < 0) | ||
956 | return rc; | ||
957 | } else if (pRegvals->bus == OV511_I2C_BUS) { | ||
958 | if ((rc = i2c_w(ov, pRegvals->reg, pRegvals->val)) < 0) | ||
959 | return rc; | ||
960 | } else { | ||
961 | err("Bad regval array"); | ||
962 | return -1; | ||
963 | } | ||
964 | pRegvals++; | ||
965 | } | ||
966 | return 0; | ||
967 | } | ||
968 | |||
969 | #ifdef OV511_DEBUG | ||
970 | static void | ||
971 | dump_i2c_range(struct usb_ov511 *ov, int reg1, int regn) | ||
972 | { | ||
973 | int i, rc; | ||
974 | |||
975 | for (i = reg1; i <= regn; i++) { | ||
976 | rc = i2c_r(ov, i); | ||
977 | dev_info(&ov->dev->dev, "Sensor[0x%02X] = 0x%02X\n", i, rc); | ||
978 | } | ||
979 | } | ||
980 | |||
981 | static void | ||
982 | dump_i2c_regs(struct usb_ov511 *ov) | ||
983 | { | ||
984 | dev_info(&ov->dev->dev, "I2C REGS\n"); | ||
985 | dump_i2c_range(ov, 0x00, 0x7C); | ||
986 | } | ||
987 | |||
988 | static void | ||
989 | dump_reg_range(struct usb_ov511 *ov, int reg1, int regn) | ||
990 | { | ||
991 | int i, rc; | ||
992 | |||
993 | for (i = reg1; i <= regn; i++) { | ||
994 | rc = reg_r(ov, i); | ||
995 | dev_info(&ov->dev->dev, "OV511[0x%02X] = 0x%02X\n", i, rc); | ||
996 | } | ||
997 | } | ||
998 | |||
999 | static void | ||
1000 | ov511_dump_regs(struct usb_ov511 *ov) | ||
1001 | { | ||
1002 | dev_info(&ov->dev->dev, "CAMERA INTERFACE REGS\n"); | ||
1003 | dump_reg_range(ov, 0x10, 0x1f); | ||
1004 | dev_info(&ov->dev->dev, "DRAM INTERFACE REGS\n"); | ||
1005 | dump_reg_range(ov, 0x20, 0x23); | ||
1006 | dev_info(&ov->dev->dev, "ISO FIFO REGS\n"); | ||
1007 | dump_reg_range(ov, 0x30, 0x31); | ||
1008 | dev_info(&ov->dev->dev, "PIO REGS\n"); | ||
1009 | dump_reg_range(ov, 0x38, 0x39); | ||
1010 | dump_reg_range(ov, 0x3e, 0x3e); | ||
1011 | dev_info(&ov->dev->dev, "I2C REGS\n"); | ||
1012 | dump_reg_range(ov, 0x40, 0x49); | ||
1013 | dev_info(&ov->dev->dev, "SYSTEM CONTROL REGS\n"); | ||
1014 | dump_reg_range(ov, 0x50, 0x55); | ||
1015 | dump_reg_range(ov, 0x5e, 0x5f); | ||
1016 | dev_info(&ov->dev->dev, "OmniCE REGS\n"); | ||
1017 | dump_reg_range(ov, 0x70, 0x79); | ||
1018 | /* NOTE: Quantization tables are not readable. You will get the value | ||
1019 | * in reg. 0x79 for every table register */ | ||
1020 | dump_reg_range(ov, 0x80, 0x9f); | ||
1021 | dump_reg_range(ov, 0xa0, 0xbf); | ||
1022 | |||
1023 | } | ||
1024 | |||
1025 | static void | ||
1026 | ov518_dump_regs(struct usb_ov511 *ov) | ||
1027 | { | ||
1028 | dev_info(&ov->dev->dev, "VIDEO MODE REGS\n"); | ||
1029 | dump_reg_range(ov, 0x20, 0x2f); | ||
1030 | dev_info(&ov->dev->dev, "DATA PUMP AND SNAPSHOT REGS\n"); | ||
1031 | dump_reg_range(ov, 0x30, 0x3f); | ||
1032 | dev_info(&ov->dev->dev, "I2C REGS\n"); | ||
1033 | dump_reg_range(ov, 0x40, 0x4f); | ||
1034 | dev_info(&ov->dev->dev, "SYSTEM CONTROL AND VENDOR REGS\n"); | ||
1035 | dump_reg_range(ov, 0x50, 0x5f); | ||
1036 | dev_info(&ov->dev->dev, "60 - 6F\n"); | ||
1037 | dump_reg_range(ov, 0x60, 0x6f); | ||
1038 | dev_info(&ov->dev->dev, "70 - 7F\n"); | ||
1039 | dump_reg_range(ov, 0x70, 0x7f); | ||
1040 | dev_info(&ov->dev->dev, "Y QUANTIZATION TABLE\n"); | ||
1041 | dump_reg_range(ov, 0x80, 0x8f); | ||
1042 | dev_info(&ov->dev->dev, "UV QUANTIZATION TABLE\n"); | ||
1043 | dump_reg_range(ov, 0x90, 0x9f); | ||
1044 | dev_info(&ov->dev->dev, "A0 - BF\n"); | ||
1045 | dump_reg_range(ov, 0xa0, 0xbf); | ||
1046 | dev_info(&ov->dev->dev, "CBR\n"); | ||
1047 | dump_reg_range(ov, 0xc0, 0xcf); | ||
1048 | } | ||
1049 | #endif | ||
1050 | |||
1051 | /*****************************************************************************/ | ||
1052 | |||
1053 | /* Temporarily stops OV511 from functioning. Must do this before changing | ||
1054 | * registers while the camera is streaming */ | ||
1055 | static inline int | ||
1056 | ov51x_stop(struct usb_ov511 *ov) | ||
1057 | { | ||
1058 | PDEBUG(4, "stopping"); | ||
1059 | ov->stopped = 1; | ||
1060 | if (ov->bclass == BCL_OV518) | ||
1061 | return (reg_w_mask(ov, R51x_SYS_RESET, 0x3a, 0x3a)); | ||
1062 | else | ||
1063 | return (reg_w(ov, R51x_SYS_RESET, 0x3d)); | ||
1064 | } | ||
1065 | |||
1066 | /* Restarts OV511 after ov511_stop() is called. Has no effect if it is not | ||
1067 | * actually stopped (for performance). */ | ||
1068 | static inline int | ||
1069 | ov51x_restart(struct usb_ov511 *ov) | ||
1070 | { | ||
1071 | if (ov->stopped) { | ||
1072 | PDEBUG(4, "restarting"); | ||
1073 | ov->stopped = 0; | ||
1074 | |||
1075 | /* Reinitialize the stream */ | ||
1076 | if (ov->bclass == BCL_OV518) | ||
1077 | reg_w(ov, 0x2f, 0x80); | ||
1078 | |||
1079 | return (reg_w(ov, R51x_SYS_RESET, 0x00)); | ||
1080 | } | ||
1081 | |||
1082 | return 0; | ||
1083 | } | ||
1084 | |||
1085 | /* Sleeps until no frames are active. Returns !0 if got signal */ | ||
1086 | static int | ||
1087 | ov51x_wait_frames_inactive(struct usb_ov511 *ov) | ||
1088 | { | ||
1089 | return wait_event_interruptible(ov->wq, ov->curframe < 0); | ||
1090 | } | ||
1091 | |||
1092 | /* Resets the hardware snapshot button */ | ||
1093 | static void | ||
1094 | ov51x_clear_snapshot(struct usb_ov511 *ov) | ||
1095 | { | ||
1096 | if (ov->bclass == BCL_OV511) { | ||
1097 | reg_w(ov, R51x_SYS_SNAP, 0x00); | ||
1098 | reg_w(ov, R51x_SYS_SNAP, 0x02); | ||
1099 | reg_w(ov, R51x_SYS_SNAP, 0x00); | ||
1100 | } else if (ov->bclass == BCL_OV518) { | ||
1101 | dev_warn(&ov->dev->dev, | ||
1102 | "snapshot reset not supported yet on OV518(+)\n"); | ||
1103 | } else { | ||
1104 | dev_err(&ov->dev->dev, "clear snap: invalid bridge type\n"); | ||
1105 | } | ||
1106 | } | ||
1107 | |||
1108 | #if 0 | ||
1109 | /* Checks the status of the snapshot button. Returns 1 if it was pressed since | ||
1110 | * it was last cleared, and zero in all other cases (including errors) */ | ||
1111 | static int | ||
1112 | ov51x_check_snapshot(struct usb_ov511 *ov) | ||
1113 | { | ||
1114 | int ret, status = 0; | ||
1115 | |||
1116 | if (ov->bclass == BCL_OV511) { | ||
1117 | ret = reg_r(ov, R51x_SYS_SNAP); | ||
1118 | if (ret < 0) { | ||
1119 | dev_err(&ov->dev->dev, | ||
1120 | "Error checking snspshot status (%d)\n", ret); | ||
1121 | } else if (ret & 0x08) { | ||
1122 | status = 1; | ||
1123 | } | ||
1124 | } else if (ov->bclass == BCL_OV518) { | ||
1125 | dev_warn(&ov->dev->dev, | ||
1126 | "snapshot check not supported yet on OV518(+)\n"); | ||
1127 | } else { | ||
1128 | dev_err(&ov->dev->dev, "clear snap: invalid bridge type\n"); | ||
1129 | } | ||
1130 | |||
1131 | return status; | ||
1132 | } | ||
1133 | #endif | ||
1134 | |||
1135 | /* This does an initial reset of an OmniVision sensor and ensures that I2C | ||
1136 | * is synchronized. Returns <0 for failure. | ||
1137 | */ | ||
1138 | static int | ||
1139 | init_ov_sensor(struct usb_ov511 *ov) | ||
1140 | { | ||
1141 | int i, success; | ||
1142 | |||
1143 | /* Reset the sensor */ | ||
1144 | if (i2c_w(ov, 0x12, 0x80) < 0) | ||
1145 | return -EIO; | ||
1146 | |||
1147 | /* Wait for it to initialize */ | ||
1148 | msleep(150); | ||
1149 | |||
1150 | for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) { | ||
1151 | if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) && | ||
1152 | (i2c_r(ov, OV7610_REG_ID_LOW) == 0xA2)) { | ||
1153 | success = 1; | ||
1154 | continue; | ||
1155 | } | ||
1156 | |||
1157 | /* Reset the sensor */ | ||
1158 | if (i2c_w(ov, 0x12, 0x80) < 0) | ||
1159 | return -EIO; | ||
1160 | /* Wait for it to initialize */ | ||
1161 | msleep(150); | ||
1162 | /* Dummy read to sync I2C */ | ||
1163 | if (i2c_r(ov, 0x00) < 0) | ||
1164 | return -EIO; | ||
1165 | } | ||
1166 | |||
1167 | if (!success) | ||
1168 | return -EIO; | ||
1169 | |||
1170 | PDEBUG(1, "I2C synced in %d attempt(s)", i); | ||
1171 | |||
1172 | return 0; | ||
1173 | } | ||
1174 | |||
1175 | static int | ||
1176 | ov511_set_packet_size(struct usb_ov511 *ov, int size) | ||
1177 | { | ||
1178 | int alt, mult; | ||
1179 | |||
1180 | if (ov51x_stop(ov) < 0) | ||
1181 | return -EIO; | ||
1182 | |||
1183 | mult = size >> 5; | ||
1184 | |||
1185 | if (ov->bridge == BRG_OV511) { | ||
1186 | if (size == 0) | ||
1187 | alt = OV511_ALT_SIZE_0; | ||
1188 | else if (size == 257) | ||
1189 | alt = OV511_ALT_SIZE_257; | ||
1190 | else if (size == 513) | ||
1191 | alt = OV511_ALT_SIZE_513; | ||
1192 | else if (size == 769) | ||
1193 | alt = OV511_ALT_SIZE_769; | ||
1194 | else if (size == 993) | ||
1195 | alt = OV511_ALT_SIZE_993; | ||
1196 | else { | ||
1197 | err("Set packet size: invalid size (%d)", size); | ||
1198 | return -EINVAL; | ||
1199 | } | ||
1200 | } else if (ov->bridge == BRG_OV511PLUS) { | ||
1201 | if (size == 0) | ||
1202 | alt = OV511PLUS_ALT_SIZE_0; | ||
1203 | else if (size == 33) | ||
1204 | alt = OV511PLUS_ALT_SIZE_33; | ||
1205 | else if (size == 129) | ||
1206 | alt = OV511PLUS_ALT_SIZE_129; | ||
1207 | else if (size == 257) | ||
1208 | alt = OV511PLUS_ALT_SIZE_257; | ||
1209 | else if (size == 385) | ||
1210 | alt = OV511PLUS_ALT_SIZE_385; | ||
1211 | else if (size == 513) | ||
1212 | alt = OV511PLUS_ALT_SIZE_513; | ||
1213 | else if (size == 769) | ||
1214 | alt = OV511PLUS_ALT_SIZE_769; | ||
1215 | else if (size == 961) | ||
1216 | alt = OV511PLUS_ALT_SIZE_961; | ||
1217 | else { | ||
1218 | err("Set packet size: invalid size (%d)", size); | ||
1219 | return -EINVAL; | ||
1220 | } | ||
1221 | } else { | ||
1222 | err("Set packet size: Invalid bridge type"); | ||
1223 | return -EINVAL; | ||
1224 | } | ||
1225 | |||
1226 | PDEBUG(3, "%d, mult=%d, alt=%d", size, mult, alt); | ||
1227 | |||
1228 | if (reg_w(ov, R51x_FIFO_PSIZE, mult) < 0) | ||
1229 | return -EIO; | ||
1230 | |||
1231 | if (usb_set_interface(ov->dev, ov->iface, alt) < 0) { | ||
1232 | err("Set packet size: set interface error"); | ||
1233 | return -EBUSY; | ||
1234 | } | ||
1235 | |||
1236 | if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0) | ||
1237 | return -EIO; | ||
1238 | |||
1239 | ov->packet_size = size; | ||
1240 | |||
1241 | if (ov51x_restart(ov) < 0) | ||
1242 | return -EIO; | ||
1243 | |||
1244 | return 0; | ||
1245 | } | ||
1246 | |||
1247 | /* Note: Unlike the OV511/OV511+, the size argument does NOT include the | ||
1248 | * optional packet number byte. The actual size *is* stored in ov->packet_size, | ||
1249 | * though. */ | ||
1250 | static int | ||
1251 | ov518_set_packet_size(struct usb_ov511 *ov, int size) | ||
1252 | { | ||
1253 | int alt; | ||
1254 | |||
1255 | if (ov51x_stop(ov) < 0) | ||
1256 | return -EIO; | ||
1257 | |||
1258 | if (ov->bclass == BCL_OV518) { | ||
1259 | if (size == 0) | ||
1260 | alt = OV518_ALT_SIZE_0; | ||
1261 | else if (size == 128) | ||
1262 | alt = OV518_ALT_SIZE_128; | ||
1263 | else if (size == 256) | ||
1264 | alt = OV518_ALT_SIZE_256; | ||
1265 | else if (size == 384) | ||
1266 | alt = OV518_ALT_SIZE_384; | ||
1267 | else if (size == 512) | ||
1268 | alt = OV518_ALT_SIZE_512; | ||
1269 | else if (size == 640) | ||
1270 | alt = OV518_ALT_SIZE_640; | ||
1271 | else if (size == 768) | ||
1272 | alt = OV518_ALT_SIZE_768; | ||
1273 | else if (size == 896) | ||
1274 | alt = OV518_ALT_SIZE_896; | ||
1275 | else { | ||
1276 | err("Set packet size: invalid size (%d)", size); | ||
1277 | return -EINVAL; | ||
1278 | } | ||
1279 | } else { | ||
1280 | err("Set packet size: Invalid bridge type"); | ||
1281 | return -EINVAL; | ||
1282 | } | ||
1283 | |||
1284 | PDEBUG(3, "%d, alt=%d", size, alt); | ||
1285 | |||
1286 | ov->packet_size = size; | ||
1287 | if (size > 0) { | ||
1288 | /* Program ISO FIFO size reg (packet number isn't included) */ | ||
1289 | ov518_reg_w32(ov, 0x30, size, 2); | ||
1290 | |||
1291 | if (ov->packet_numbering) | ||
1292 | ++ov->packet_size; | ||
1293 | } | ||
1294 | |||
1295 | if (usb_set_interface(ov->dev, ov->iface, alt) < 0) { | ||
1296 | err("Set packet size: set interface error"); | ||
1297 | return -EBUSY; | ||
1298 | } | ||
1299 | |||
1300 | /* Initialize the stream */ | ||
1301 | if (reg_w(ov, 0x2f, 0x80) < 0) | ||
1302 | return -EIO; | ||
1303 | |||
1304 | if (ov51x_restart(ov) < 0) | ||
1305 | return -EIO; | ||
1306 | |||
1307 | if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0) | ||
1308 | return -EIO; | ||
1309 | |||
1310 | return 0; | ||
1311 | } | ||
1312 | |||
1313 | /* Upload compression params and quantization tables. Returns 0 for success. */ | ||
1314 | static int | ||
1315 | ov511_init_compression(struct usb_ov511 *ov) | ||
1316 | { | ||
1317 | int rc = 0; | ||
1318 | |||
1319 | if (!ov->compress_inited) { | ||
1320 | reg_w(ov, 0x70, phy); | ||
1321 | reg_w(ov, 0x71, phuv); | ||
1322 | reg_w(ov, 0x72, pvy); | ||
1323 | reg_w(ov, 0x73, pvuv); | ||
1324 | reg_w(ov, 0x74, qhy); | ||
1325 | reg_w(ov, 0x75, qhuv); | ||
1326 | reg_w(ov, 0x76, qvy); | ||
1327 | reg_w(ov, 0x77, qvuv); | ||
1328 | |||
1329 | if (ov511_upload_quan_tables(ov) < 0) { | ||
1330 | err("Error uploading quantization tables"); | ||
1331 | rc = -EIO; | ||
1332 | goto out; | ||
1333 | } | ||
1334 | } | ||
1335 | |||
1336 | ov->compress_inited = 1; | ||
1337 | out: | ||
1338 | return rc; | ||
1339 | } | ||
1340 | |||
1341 | /* Upload compression params and quantization tables. Returns 0 for success. */ | ||
1342 | static int | ||
1343 | ov518_init_compression(struct usb_ov511 *ov) | ||
1344 | { | ||
1345 | int rc = 0; | ||
1346 | |||
1347 | if (!ov->compress_inited) { | ||
1348 | if (ov518_upload_quan_tables(ov) < 0) { | ||
1349 | err("Error uploading quantization tables"); | ||
1350 | rc = -EIO; | ||
1351 | goto out; | ||
1352 | } | ||
1353 | } | ||
1354 | |||
1355 | ov->compress_inited = 1; | ||
1356 | out: | ||
1357 | return rc; | ||
1358 | } | ||
1359 | |||
1360 | /* -------------------------------------------------------------------------- */ | ||
1361 | |||
1362 | /* Sets sensor's contrast setting to "val" */ | ||
1363 | static int | ||
1364 | sensor_set_contrast(struct usb_ov511 *ov, unsigned short val) | ||
1365 | { | ||
1366 | int rc; | ||
1367 | |||
1368 | PDEBUG(3, "%d", val); | ||
1369 | |||
1370 | if (ov->stop_during_set) | ||
1371 | if (ov51x_stop(ov) < 0) | ||
1372 | return -EIO; | ||
1373 | |||
1374 | switch (ov->sensor) { | ||
1375 | case SEN_OV7610: | ||
1376 | case SEN_OV6620: | ||
1377 | { | ||
1378 | rc = i2c_w(ov, OV7610_REG_CNT, val >> 8); | ||
1379 | if (rc < 0) | ||
1380 | goto out; | ||
1381 | break; | ||
1382 | } | ||
1383 | case SEN_OV6630: | ||
1384 | { | ||
1385 | rc = i2c_w_mask(ov, OV7610_REG_CNT, val >> 12, 0x0f); | ||
1386 | if (rc < 0) | ||
1387 | goto out; | ||
1388 | break; | ||
1389 | } | ||
1390 | case SEN_OV7620: | ||
1391 | { | ||
1392 | unsigned char ctab[] = { | ||
1393 | 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57, | ||
1394 | 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff | ||
1395 | }; | ||
1396 | |||
1397 | /* Use Y gamma control instead. Bit 0 enables it. */ | ||
1398 | rc = i2c_w(ov, 0x64, ctab[val>>12]); | ||
1399 | if (rc < 0) | ||
1400 | goto out; | ||
1401 | break; | ||
1402 | } | ||
1403 | case SEN_SAA7111A: | ||
1404 | { | ||
1405 | rc = i2c_w(ov, 0x0b, val >> 9); | ||
1406 | if (rc < 0) | ||
1407 | goto out; | ||
1408 | break; | ||
1409 | } | ||
1410 | default: | ||
1411 | { | ||
1412 | PDEBUG(3, "Unsupported with this sensor"); | ||
1413 | rc = -EPERM; | ||
1414 | goto out; | ||
1415 | } | ||
1416 | } | ||
1417 | |||
1418 | rc = 0; /* Success */ | ||
1419 | ov->contrast = val; | ||
1420 | out: | ||
1421 | if (ov51x_restart(ov) < 0) | ||
1422 | return -EIO; | ||
1423 | |||
1424 | return rc; | ||
1425 | } | ||
1426 | |||
1427 | /* Gets sensor's contrast setting */ | ||
1428 | static int | ||
1429 | sensor_get_contrast(struct usb_ov511 *ov, unsigned short *val) | ||
1430 | { | ||
1431 | int rc; | ||
1432 | |||
1433 | switch (ov->sensor) { | ||
1434 | case SEN_OV7610: | ||
1435 | case SEN_OV6620: | ||
1436 | rc = i2c_r(ov, OV7610_REG_CNT); | ||
1437 | if (rc < 0) | ||
1438 | return rc; | ||
1439 | else | ||
1440 | *val = rc << 8; | ||
1441 | break; | ||
1442 | case SEN_OV6630: | ||
1443 | rc = i2c_r(ov, OV7610_REG_CNT); | ||
1444 | if (rc < 0) | ||
1445 | return rc; | ||
1446 | else | ||
1447 | *val = rc << 12; | ||
1448 | break; | ||
1449 | case SEN_OV7620: | ||
1450 | /* Use Y gamma reg instead. Bit 0 is the enable bit. */ | ||
1451 | rc = i2c_r(ov, 0x64); | ||
1452 | if (rc < 0) | ||
1453 | return rc; | ||
1454 | else | ||
1455 | *val = (rc & 0xfe) << 8; | ||
1456 | break; | ||
1457 | case SEN_SAA7111A: | ||
1458 | *val = ov->contrast; | ||
1459 | break; | ||
1460 | default: | ||
1461 | PDEBUG(3, "Unsupported with this sensor"); | ||
1462 | return -EPERM; | ||
1463 | } | ||
1464 | |||
1465 | PDEBUG(3, "%d", *val); | ||
1466 | ov->contrast = *val; | ||
1467 | |||
1468 | return 0; | ||
1469 | } | ||
1470 | |||
1471 | /* -------------------------------------------------------------------------- */ | ||
1472 | |||
1473 | /* Sets sensor's brightness setting to "val" */ | ||
1474 | static int | ||
1475 | sensor_set_brightness(struct usb_ov511 *ov, unsigned short val) | ||
1476 | { | ||
1477 | int rc; | ||
1478 | |||
1479 | PDEBUG(4, "%d", val); | ||
1480 | |||
1481 | if (ov->stop_during_set) | ||
1482 | if (ov51x_stop(ov) < 0) | ||
1483 | return -EIO; | ||
1484 | |||
1485 | switch (ov->sensor) { | ||
1486 | case SEN_OV7610: | ||
1487 | case SEN_OV76BE: | ||
1488 | case SEN_OV6620: | ||
1489 | case SEN_OV6630: | ||
1490 | rc = i2c_w(ov, OV7610_REG_BRT, val >> 8); | ||
1491 | if (rc < 0) | ||
1492 | goto out; | ||
1493 | break; | ||
1494 | case SEN_OV7620: | ||
1495 | /* 7620 doesn't like manual changes when in auto mode */ | ||
1496 | if (!ov->auto_brt) { | ||
1497 | rc = i2c_w(ov, OV7610_REG_BRT, val >> 8); | ||
1498 | if (rc < 0) | ||
1499 | goto out; | ||
1500 | } | ||
1501 | break; | ||
1502 | case SEN_SAA7111A: | ||
1503 | rc = i2c_w(ov, 0x0a, val >> 8); | ||
1504 | if (rc < 0) | ||
1505 | goto out; | ||
1506 | break; | ||
1507 | default: | ||
1508 | PDEBUG(3, "Unsupported with this sensor"); | ||
1509 | rc = -EPERM; | ||
1510 | goto out; | ||
1511 | } | ||
1512 | |||
1513 | rc = 0; /* Success */ | ||
1514 | ov->brightness = val; | ||
1515 | out: | ||
1516 | if (ov51x_restart(ov) < 0) | ||
1517 | return -EIO; | ||
1518 | |||
1519 | return rc; | ||
1520 | } | ||
1521 | |||
1522 | /* Gets sensor's brightness setting */ | ||
1523 | static int | ||
1524 | sensor_get_brightness(struct usb_ov511 *ov, unsigned short *val) | ||
1525 | { | ||
1526 | int rc; | ||
1527 | |||
1528 | switch (ov->sensor) { | ||
1529 | case SEN_OV7610: | ||
1530 | case SEN_OV76BE: | ||
1531 | case SEN_OV7620: | ||
1532 | case SEN_OV6620: | ||
1533 | case SEN_OV6630: | ||
1534 | rc = i2c_r(ov, OV7610_REG_BRT); | ||
1535 | if (rc < 0) | ||
1536 | return rc; | ||
1537 | else | ||
1538 | *val = rc << 8; | ||
1539 | break; | ||
1540 | case SEN_SAA7111A: | ||
1541 | *val = ov->brightness; | ||
1542 | break; | ||
1543 | default: | ||
1544 | PDEBUG(3, "Unsupported with this sensor"); | ||
1545 | return -EPERM; | ||
1546 | } | ||
1547 | |||
1548 | PDEBUG(3, "%d", *val); | ||
1549 | ov->brightness = *val; | ||
1550 | |||
1551 | return 0; | ||
1552 | } | ||
1553 | |||
1554 | /* -------------------------------------------------------------------------- */ | ||
1555 | |||
1556 | /* Sets sensor's saturation (color intensity) setting to "val" */ | ||
1557 | static int | ||
1558 | sensor_set_saturation(struct usb_ov511 *ov, unsigned short val) | ||
1559 | { | ||
1560 | int rc; | ||
1561 | |||
1562 | PDEBUG(3, "%d", val); | ||
1563 | |||
1564 | if (ov->stop_during_set) | ||
1565 | if (ov51x_stop(ov) < 0) | ||
1566 | return -EIO; | ||
1567 | |||
1568 | switch (ov->sensor) { | ||
1569 | case SEN_OV7610: | ||
1570 | case SEN_OV76BE: | ||
1571 | case SEN_OV6620: | ||
1572 | case SEN_OV6630: | ||
1573 | rc = i2c_w(ov, OV7610_REG_SAT, val >> 8); | ||
1574 | if (rc < 0) | ||
1575 | goto out; | ||
1576 | break; | ||
1577 | case SEN_OV7620: | ||
1578 | // /* Use UV gamma control instead. Bits 0 & 7 are reserved. */ | ||
1579 | // rc = ov_i2c_write(ov->dev, 0x62, (val >> 9) & 0x7e); | ||
1580 | // if (rc < 0) | ||
1581 | // goto out; | ||
1582 | rc = i2c_w(ov, OV7610_REG_SAT, val >> 8); | ||
1583 | if (rc < 0) | ||
1584 | goto out; | ||
1585 | break; | ||
1586 | case SEN_SAA7111A: | ||
1587 | rc = i2c_w(ov, 0x0c, val >> 9); | ||
1588 | if (rc < 0) | ||
1589 | goto out; | ||
1590 | break; | ||
1591 | default: | ||
1592 | PDEBUG(3, "Unsupported with this sensor"); | ||
1593 | rc = -EPERM; | ||
1594 | goto out; | ||
1595 | } | ||
1596 | |||
1597 | rc = 0; /* Success */ | ||
1598 | ov->colour = val; | ||
1599 | out: | ||
1600 | if (ov51x_restart(ov) < 0) | ||
1601 | return -EIO; | ||
1602 | |||
1603 | return rc; | ||
1604 | } | ||
1605 | |||
1606 | /* Gets sensor's saturation (color intensity) setting */ | ||
1607 | static int | ||
1608 | sensor_get_saturation(struct usb_ov511 *ov, unsigned short *val) | ||
1609 | { | ||
1610 | int rc; | ||
1611 | |||
1612 | switch (ov->sensor) { | ||
1613 | case SEN_OV7610: | ||
1614 | case SEN_OV76BE: | ||
1615 | case SEN_OV6620: | ||
1616 | case SEN_OV6630: | ||
1617 | rc = i2c_r(ov, OV7610_REG_SAT); | ||
1618 | if (rc < 0) | ||
1619 | return rc; | ||
1620 | else | ||
1621 | *val = rc << 8; | ||
1622 | break; | ||
1623 | case SEN_OV7620: | ||
1624 | // /* Use UV gamma reg instead. Bits 0 & 7 are reserved. */ | ||
1625 | // rc = i2c_r(ov, 0x62); | ||
1626 | // if (rc < 0) | ||
1627 | // return rc; | ||
1628 | // else | ||
1629 | // *val = (rc & 0x7e) << 9; | ||
1630 | rc = i2c_r(ov, OV7610_REG_SAT); | ||
1631 | if (rc < 0) | ||
1632 | return rc; | ||
1633 | else | ||
1634 | *val = rc << 8; | ||
1635 | break; | ||
1636 | case SEN_SAA7111A: | ||
1637 | *val = ov->colour; | ||
1638 | break; | ||
1639 | default: | ||
1640 | PDEBUG(3, "Unsupported with this sensor"); | ||
1641 | return -EPERM; | ||
1642 | } | ||
1643 | |||
1644 | PDEBUG(3, "%d", *val); | ||
1645 | ov->colour = *val; | ||
1646 | |||
1647 | return 0; | ||
1648 | } | ||
1649 | |||
1650 | /* -------------------------------------------------------------------------- */ | ||
1651 | |||
1652 | /* Sets sensor's hue (red/blue balance) setting to "val" */ | ||
1653 | static int | ||
1654 | sensor_set_hue(struct usb_ov511 *ov, unsigned short val) | ||
1655 | { | ||
1656 | int rc; | ||
1657 | |||
1658 | PDEBUG(3, "%d", val); | ||
1659 | |||
1660 | if (ov->stop_during_set) | ||
1661 | if (ov51x_stop(ov) < 0) | ||
1662 | return -EIO; | ||
1663 | |||
1664 | switch (ov->sensor) { | ||
1665 | case SEN_OV7610: | ||
1666 | case SEN_OV6620: | ||
1667 | case SEN_OV6630: | ||
1668 | rc = i2c_w(ov, OV7610_REG_RED, 0xFF - (val >> 8)); | ||
1669 | if (rc < 0) | ||
1670 | goto out; | ||
1671 | |||
1672 | rc = i2c_w(ov, OV7610_REG_BLUE, val >> 8); | ||
1673 | if (rc < 0) | ||
1674 | goto out; | ||
1675 | break; | ||
1676 | case SEN_OV7620: | ||
1677 | // Hue control is causing problems. I will enable it once it's fixed. | ||
1678 | #if 0 | ||
1679 | rc = i2c_w(ov, 0x7a, (unsigned char)(val >> 8) + 0xb); | ||
1680 | if (rc < 0) | ||
1681 | goto out; | ||
1682 | |||
1683 | rc = i2c_w(ov, 0x79, (unsigned char)(val >> 8) + 0xb); | ||
1684 | if (rc < 0) | ||
1685 | goto out; | ||
1686 | #endif | ||
1687 | break; | ||
1688 | case SEN_SAA7111A: | ||
1689 | rc = i2c_w(ov, 0x0d, (val + 32768) >> 8); | ||
1690 | if (rc < 0) | ||
1691 | goto out; | ||
1692 | break; | ||
1693 | default: | ||
1694 | PDEBUG(3, "Unsupported with this sensor"); | ||
1695 | rc = -EPERM; | ||
1696 | goto out; | ||
1697 | } | ||
1698 | |||
1699 | rc = 0; /* Success */ | ||
1700 | ov->hue = val; | ||
1701 | out: | ||
1702 | if (ov51x_restart(ov) < 0) | ||
1703 | return -EIO; | ||
1704 | |||
1705 | return rc; | ||
1706 | } | ||
1707 | |||
1708 | /* Gets sensor's hue (red/blue balance) setting */ | ||
1709 | static int | ||
1710 | sensor_get_hue(struct usb_ov511 *ov, unsigned short *val) | ||
1711 | { | ||
1712 | int rc; | ||
1713 | |||
1714 | switch (ov->sensor) { | ||
1715 | case SEN_OV7610: | ||
1716 | case SEN_OV6620: | ||
1717 | case SEN_OV6630: | ||
1718 | rc = i2c_r(ov, OV7610_REG_BLUE); | ||
1719 | if (rc < 0) | ||
1720 | return rc; | ||
1721 | else | ||
1722 | *val = rc << 8; | ||
1723 | break; | ||
1724 | case SEN_OV7620: | ||
1725 | rc = i2c_r(ov, 0x7a); | ||
1726 | if (rc < 0) | ||
1727 | return rc; | ||
1728 | else | ||
1729 | *val = rc << 8; | ||
1730 | break; | ||
1731 | case SEN_SAA7111A: | ||
1732 | *val = ov->hue; | ||
1733 | break; | ||
1734 | default: | ||
1735 | PDEBUG(3, "Unsupported with this sensor"); | ||
1736 | return -EPERM; | ||
1737 | } | ||
1738 | |||
1739 | PDEBUG(3, "%d", *val); | ||
1740 | ov->hue = *val; | ||
1741 | |||
1742 | return 0; | ||
1743 | } | ||
1744 | |||
1745 | /* -------------------------------------------------------------------------- */ | ||
1746 | |||
1747 | static int | ||
1748 | sensor_set_picture(struct usb_ov511 *ov, struct video_picture *p) | ||
1749 | { | ||
1750 | int rc; | ||
1751 | |||
1752 | PDEBUG(4, "sensor_set_picture"); | ||
1753 | |||
1754 | ov->whiteness = p->whiteness; | ||
1755 | |||
1756 | /* Don't return error if a setting is unsupported, or rest of settings | ||
1757 | * will not be performed */ | ||
1758 | |||
1759 | rc = sensor_set_contrast(ov, p->contrast); | ||
1760 | if (FATAL_ERROR(rc)) | ||
1761 | return rc; | ||
1762 | |||
1763 | rc = sensor_set_brightness(ov, p->brightness); | ||
1764 | if (FATAL_ERROR(rc)) | ||
1765 | return rc; | ||
1766 | |||
1767 | rc = sensor_set_saturation(ov, p->colour); | ||
1768 | if (FATAL_ERROR(rc)) | ||
1769 | return rc; | ||
1770 | |||
1771 | rc = sensor_set_hue(ov, p->hue); | ||
1772 | if (FATAL_ERROR(rc)) | ||
1773 | return rc; | ||
1774 | |||
1775 | return 0; | ||
1776 | } | ||
1777 | |||
1778 | static int | ||
1779 | sensor_get_picture(struct usb_ov511 *ov, struct video_picture *p) | ||
1780 | { | ||
1781 | int rc; | ||
1782 | |||
1783 | PDEBUG(4, "sensor_get_picture"); | ||
1784 | |||
1785 | /* Don't return error if a setting is unsupported, or rest of settings | ||
1786 | * will not be performed */ | ||
1787 | |||
1788 | rc = sensor_get_contrast(ov, &(p->contrast)); | ||
1789 | if (FATAL_ERROR(rc)) | ||
1790 | return rc; | ||
1791 | |||
1792 | rc = sensor_get_brightness(ov, &(p->brightness)); | ||
1793 | if (FATAL_ERROR(rc)) | ||
1794 | return rc; | ||
1795 | |||
1796 | rc = sensor_get_saturation(ov, &(p->colour)); | ||
1797 | if (FATAL_ERROR(rc)) | ||
1798 | return rc; | ||
1799 | |||
1800 | rc = sensor_get_hue(ov, &(p->hue)); | ||
1801 | if (FATAL_ERROR(rc)) | ||
1802 | return rc; | ||
1803 | |||
1804 | p->whiteness = 105 << 8; | ||
1805 | |||
1806 | return 0; | ||
1807 | } | ||
1808 | |||
1809 | #if 0 | ||
1810 | // FIXME: Exposure range is only 0x00-0x7f in interlace mode | ||
1811 | /* Sets current exposure for sensor. This only has an effect if auto-exposure | ||
1812 | * is off */ | ||
1813 | static inline int | ||
1814 | sensor_set_exposure(struct usb_ov511 *ov, unsigned char val) | ||
1815 | { | ||
1816 | int rc; | ||
1817 | |||
1818 | PDEBUG(3, "%d", val); | ||
1819 | |||
1820 | if (ov->stop_during_set) | ||
1821 | if (ov51x_stop(ov) < 0) | ||
1822 | return -EIO; | ||
1823 | |||
1824 | switch (ov->sensor) { | ||
1825 | case SEN_OV6620: | ||
1826 | case SEN_OV6630: | ||
1827 | case SEN_OV7610: | ||
1828 | case SEN_OV7620: | ||
1829 | case SEN_OV76BE: | ||
1830 | case SEN_OV8600: | ||
1831 | rc = i2c_w(ov, 0x10, val); | ||
1832 | if (rc < 0) | ||
1833 | goto out; | ||
1834 | |||
1835 | break; | ||
1836 | case SEN_KS0127: | ||
1837 | case SEN_KS0127B: | ||
1838 | case SEN_SAA7111A: | ||
1839 | PDEBUG(3, "Unsupported with this sensor"); | ||
1840 | return -EPERM; | ||
1841 | default: | ||
1842 | err("Sensor not supported for set_exposure"); | ||
1843 | return -EINVAL; | ||
1844 | } | ||
1845 | |||
1846 | rc = 0; /* Success */ | ||
1847 | ov->exposure = val; | ||
1848 | out: | ||
1849 | if (ov51x_restart(ov) < 0) | ||
1850 | return -EIO; | ||
1851 | |||
1852 | return rc; | ||
1853 | } | ||
1854 | #endif | ||
1855 | |||
1856 | /* Gets current exposure level from sensor, regardless of whether it is under | ||
1857 | * manual control. */ | ||
1858 | static int | ||
1859 | sensor_get_exposure(struct usb_ov511 *ov, unsigned char *val) | ||
1860 | { | ||
1861 | int rc; | ||
1862 | |||
1863 | switch (ov->sensor) { | ||
1864 | case SEN_OV7610: | ||
1865 | case SEN_OV6620: | ||
1866 | case SEN_OV6630: | ||
1867 | case SEN_OV7620: | ||
1868 | case SEN_OV76BE: | ||
1869 | case SEN_OV8600: | ||
1870 | rc = i2c_r(ov, 0x10); | ||
1871 | if (rc < 0) | ||
1872 | return rc; | ||
1873 | else | ||
1874 | *val = rc; | ||
1875 | break; | ||
1876 | case SEN_KS0127: | ||
1877 | case SEN_KS0127B: | ||
1878 | case SEN_SAA7111A: | ||
1879 | val = NULL; | ||
1880 | PDEBUG(3, "Unsupported with this sensor"); | ||
1881 | return -EPERM; | ||
1882 | default: | ||
1883 | err("Sensor not supported for get_exposure"); | ||
1884 | return -EINVAL; | ||
1885 | } | ||
1886 | |||
1887 | PDEBUG(3, "%d", *val); | ||
1888 | ov->exposure = *val; | ||
1889 | |||
1890 | return 0; | ||
1891 | } | ||
1892 | |||
1893 | /* Turns on or off the LED. Only has an effect with OV511+/OV518(+) */ | ||
1894 | static void | ||
1895 | ov51x_led_control(struct usb_ov511 *ov, int enable) | ||
1896 | { | ||
1897 | PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); | ||
1898 | |||
1899 | if (ov->bridge == BRG_OV511PLUS) | ||
1900 | reg_w(ov, R511_SYS_LED_CTL, enable ? 1 : 0); | ||
1901 | else if (ov->bclass == BCL_OV518) | ||
1902 | reg_w_mask(ov, R518_GPIO_OUT, enable ? 0x02 : 0x00, 0x02); | ||
1903 | |||
1904 | return; | ||
1905 | } | ||
1906 | |||
1907 | /* Matches the sensor's internal frame rate to the lighting frequency. | ||
1908 | * Valid frequencies are: | ||
1909 | * 50 - 50Hz, for European and Asian lighting | ||
1910 | * 60 - 60Hz, for American lighting | ||
1911 | * | ||
1912 | * Tested with: OV7610, OV7620, OV76BE, OV6620 | ||
1913 | * Unsupported: KS0127, KS0127B, SAA7111A | ||
1914 | * Returns: 0 for success | ||
1915 | */ | ||
1916 | static int | ||
1917 | sensor_set_light_freq(struct usb_ov511 *ov, int freq) | ||
1918 | { | ||
1919 | int sixty; | ||
1920 | |||
1921 | PDEBUG(4, "%d Hz", freq); | ||
1922 | |||
1923 | if (freq == 60) | ||
1924 | sixty = 1; | ||
1925 | else if (freq == 50) | ||
1926 | sixty = 0; | ||
1927 | else { | ||
1928 | err("Invalid light freq (%d Hz)", freq); | ||
1929 | return -EINVAL; | ||
1930 | } | ||
1931 | |||
1932 | switch (ov->sensor) { | ||
1933 | case SEN_OV7610: | ||
1934 | i2c_w_mask(ov, 0x2a, sixty?0x00:0x80, 0x80); | ||
1935 | i2c_w(ov, 0x2b, sixty?0x00:0xac); | ||
1936 | i2c_w_mask(ov, 0x13, 0x10, 0x10); | ||
1937 | i2c_w_mask(ov, 0x13, 0x00, 0x10); | ||
1938 | break; | ||
1939 | case SEN_OV7620: | ||
1940 | case SEN_OV76BE: | ||
1941 | case SEN_OV8600: | ||
1942 | i2c_w_mask(ov, 0x2a, sixty?0x00:0x80, 0x80); | ||
1943 | i2c_w(ov, 0x2b, sixty?0x00:0xac); | ||
1944 | i2c_w_mask(ov, 0x76, 0x01, 0x01); | ||
1945 | break; | ||
1946 | case SEN_OV6620: | ||
1947 | case SEN_OV6630: | ||
1948 | i2c_w(ov, 0x2b, sixty?0xa8:0x28); | ||
1949 | i2c_w(ov, 0x2a, sixty?0x84:0xa4); | ||
1950 | break; | ||
1951 | case SEN_KS0127: | ||
1952 | case SEN_KS0127B: | ||
1953 | case SEN_SAA7111A: | ||
1954 | PDEBUG(5, "Unsupported with this sensor"); | ||
1955 | return -EPERM; | ||
1956 | default: | ||
1957 | err("Sensor not supported for set_light_freq"); | ||
1958 | return -EINVAL; | ||
1959 | } | ||
1960 | |||
1961 | ov->lightfreq = freq; | ||
1962 | |||
1963 | return 0; | ||
1964 | } | ||
1965 | |||
1966 | /* If enable is true, turn on the sensor's banding filter, otherwise turn it | ||
1967 | * off. This filter tries to reduce the pattern of horizontal light/dark bands | ||
1968 | * caused by some (usually fluorescent) lighting. The light frequency must be | ||
1969 | * set either before or after enabling it with ov51x_set_light_freq(). | ||
1970 | * | ||
1971 | * Tested with: OV7610, OV7620, OV76BE, OV6620. | ||
1972 | * Unsupported: KS0127, KS0127B, SAA7111A | ||
1973 | * Returns: 0 for success | ||
1974 | */ | ||
1975 | static int | ||
1976 | sensor_set_banding_filter(struct usb_ov511 *ov, int enable) | ||
1977 | { | ||
1978 | int rc; | ||
1979 | |||
1980 | PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); | ||
1981 | |||
1982 | if (ov->sensor == SEN_KS0127 || ov->sensor == SEN_KS0127B | ||
1983 | || ov->sensor == SEN_SAA7111A) { | ||
1984 | PDEBUG(5, "Unsupported with this sensor"); | ||
1985 | return -EPERM; | ||
1986 | } | ||
1987 | |||
1988 | rc = i2c_w_mask(ov, 0x2d, enable?0x04:0x00, 0x04); | ||
1989 | if (rc < 0) | ||
1990 | return rc; | ||
1991 | |||
1992 | ov->bandfilt = enable; | ||
1993 | |||
1994 | return 0; | ||
1995 | } | ||
1996 | |||
1997 | /* If enable is true, turn on the sensor's auto brightness control, otherwise | ||
1998 | * turn it off. | ||
1999 | * | ||
2000 | * Unsupported: KS0127, KS0127B, SAA7111A | ||
2001 | * Returns: 0 for success | ||
2002 | */ | ||
2003 | static int | ||
2004 | sensor_set_auto_brightness(struct usb_ov511 *ov, int enable) | ||
2005 | { | ||
2006 | int rc; | ||
2007 | |||
2008 | PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); | ||
2009 | |||
2010 | if (ov->sensor == SEN_KS0127 || ov->sensor == SEN_KS0127B | ||
2011 | || ov->sensor == SEN_SAA7111A) { | ||
2012 | PDEBUG(5, "Unsupported with this sensor"); | ||
2013 | return -EPERM; | ||
2014 | } | ||
2015 | |||
2016 | rc = i2c_w_mask(ov, 0x2d, enable?0x10:0x00, 0x10); | ||
2017 | if (rc < 0) | ||
2018 | return rc; | ||
2019 | |||
2020 | ov->auto_brt = enable; | ||
2021 | |||
2022 | return 0; | ||
2023 | } | ||
2024 | |||
2025 | /* If enable is true, turn on the sensor's auto exposure control, otherwise | ||
2026 | * turn it off. | ||
2027 | * | ||
2028 | * Unsupported: KS0127, KS0127B, SAA7111A | ||
2029 | * Returns: 0 for success | ||
2030 | */ | ||
2031 | static int | ||
2032 | sensor_set_auto_exposure(struct usb_ov511 *ov, int enable) | ||
2033 | { | ||
2034 | PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); | ||
2035 | |||
2036 | switch (ov->sensor) { | ||
2037 | case SEN_OV7610: | ||
2038 | i2c_w_mask(ov, 0x29, enable?0x00:0x80, 0x80); | ||
2039 | break; | ||
2040 | case SEN_OV6620: | ||
2041 | case SEN_OV7620: | ||
2042 | case SEN_OV76BE: | ||
2043 | case SEN_OV8600: | ||
2044 | i2c_w_mask(ov, 0x13, enable?0x01:0x00, 0x01); | ||
2045 | break; | ||
2046 | case SEN_OV6630: | ||
2047 | i2c_w_mask(ov, 0x28, enable?0x00:0x10, 0x10); | ||
2048 | break; | ||
2049 | case SEN_KS0127: | ||
2050 | case SEN_KS0127B: | ||
2051 | case SEN_SAA7111A: | ||
2052 | PDEBUG(5, "Unsupported with this sensor"); | ||
2053 | return -EPERM; | ||
2054 | default: | ||
2055 | err("Sensor not supported for set_auto_exposure"); | ||
2056 | return -EINVAL; | ||
2057 | } | ||
2058 | |||
2059 | ov->auto_exp = enable; | ||
2060 | |||
2061 | return 0; | ||
2062 | } | ||
2063 | |||
2064 | /* Modifies the sensor's exposure algorithm to allow proper exposure of objects | ||
2065 | * that are illuminated from behind. | ||
2066 | * | ||
2067 | * Tested with: OV6620, OV7620 | ||
2068 | * Unsupported: OV7610, OV76BE, KS0127, KS0127B, SAA7111A | ||
2069 | * Returns: 0 for success | ||
2070 | */ | ||
2071 | static int | ||
2072 | sensor_set_backlight(struct usb_ov511 *ov, int enable) | ||
2073 | { | ||
2074 | PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); | ||
2075 | |||
2076 | switch (ov->sensor) { | ||
2077 | case SEN_OV7620: | ||
2078 | case SEN_OV8600: | ||
2079 | i2c_w_mask(ov, 0x68, enable?0xe0:0xc0, 0xe0); | ||
2080 | i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08); | ||
2081 | i2c_w_mask(ov, 0x28, enable?0x02:0x00, 0x02); | ||
2082 | break; | ||
2083 | case SEN_OV6620: | ||
2084 | i2c_w_mask(ov, 0x4e, enable?0xe0:0xc0, 0xe0); | ||
2085 | i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08); | ||
2086 | i2c_w_mask(ov, 0x0e, enable?0x80:0x00, 0x80); | ||
2087 | break; | ||
2088 | case SEN_OV6630: | ||
2089 | i2c_w_mask(ov, 0x4e, enable?0x80:0x60, 0xe0); | ||
2090 | i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08); | ||
2091 | i2c_w_mask(ov, 0x28, enable?0x02:0x00, 0x02); | ||
2092 | break; | ||
2093 | case SEN_OV7610: | ||
2094 | case SEN_OV76BE: | ||
2095 | case SEN_KS0127: | ||
2096 | case SEN_KS0127B: | ||
2097 | case SEN_SAA7111A: | ||
2098 | PDEBUG(5, "Unsupported with this sensor"); | ||
2099 | return -EPERM; | ||
2100 | default: | ||
2101 | err("Sensor not supported for set_backlight"); | ||
2102 | return -EINVAL; | ||
2103 | } | ||
2104 | |||
2105 | ov->backlight = enable; | ||
2106 | |||
2107 | return 0; | ||
2108 | } | ||
2109 | |||
2110 | static int | ||
2111 | sensor_set_mirror(struct usb_ov511 *ov, int enable) | ||
2112 | { | ||
2113 | PDEBUG(4, " (%s)", enable ? "turn on" : "turn off"); | ||
2114 | |||
2115 | switch (ov->sensor) { | ||
2116 | case SEN_OV6620: | ||
2117 | case SEN_OV6630: | ||
2118 | case SEN_OV7610: | ||
2119 | case SEN_OV7620: | ||
2120 | case SEN_OV76BE: | ||
2121 | case SEN_OV8600: | ||
2122 | i2c_w_mask(ov, 0x12, enable?0x40:0x00, 0x40); | ||
2123 | break; | ||
2124 | case SEN_KS0127: | ||
2125 | case SEN_KS0127B: | ||
2126 | case SEN_SAA7111A: | ||
2127 | PDEBUG(5, "Unsupported with this sensor"); | ||
2128 | return -EPERM; | ||
2129 | default: | ||
2130 | err("Sensor not supported for set_mirror"); | ||
2131 | return -EINVAL; | ||
2132 | } | ||
2133 | |||
2134 | ov->mirror = enable; | ||
2135 | |||
2136 | return 0; | ||
2137 | } | ||
2138 | |||
2139 | /* Returns number of bits per pixel (regardless of where they are located; | ||
2140 | * planar or not), or zero for unsupported format. | ||
2141 | */ | ||
2142 | static inline int | ||
2143 | get_depth(int palette) | ||
2144 | { | ||
2145 | switch (palette) { | ||
2146 | case VIDEO_PALETTE_GREY: return 8; | ||
2147 | case VIDEO_PALETTE_YUV420: return 12; | ||
2148 | case VIDEO_PALETTE_YUV420P: return 12; /* Planar */ | ||
2149 | default: return 0; /* Invalid format */ | ||
2150 | } | ||
2151 | } | ||
2152 | |||
2153 | /* Bytes per frame. Used by read(). Return of 0 indicates error */ | ||
2154 | static inline long int | ||
2155 | get_frame_length(struct ov511_frame *frame) | ||
2156 | { | ||
2157 | if (!frame) | ||
2158 | return 0; | ||
2159 | else | ||
2160 | return ((frame->width * frame->height | ||
2161 | * get_depth(frame->format)) >> 3); | ||
2162 | } | ||
2163 | |||
2164 | static int | ||
2165 | mode_init_ov_sensor_regs(struct usb_ov511 *ov, int width, int height, | ||
2166 | int mode, int sub_flag, int qvga) | ||
2167 | { | ||
2168 | int clock; | ||
2169 | |||
2170 | /******** Mode (VGA/QVGA) and sensor specific regs ********/ | ||
2171 | |||
2172 | switch (ov->sensor) { | ||
2173 | case SEN_OV7610: | ||
2174 | i2c_w(ov, 0x14, qvga?0x24:0x04); | ||
2175 | // FIXME: Does this improve the image quality or frame rate? | ||
2176 | #if 0 | ||
2177 | i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20); | ||
2178 | i2c_w(ov, 0x24, 0x10); | ||
2179 | i2c_w(ov, 0x25, qvga?0x40:0x8a); | ||
2180 | i2c_w(ov, 0x2f, qvga?0x30:0xb0); | ||
2181 | i2c_w(ov, 0x35, qvga?0x1c:0x9c); | ||
2182 | #endif | ||
2183 | break; | ||
2184 | case SEN_OV7620: | ||
2185 | // i2c_w(ov, 0x2b, 0x00); | ||
2186 | i2c_w(ov, 0x14, qvga?0xa4:0x84); | ||
2187 | i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20); | ||
2188 | i2c_w(ov, 0x24, qvga?0x20:0x3a); | ||
2189 | i2c_w(ov, 0x25, qvga?0x30:0x60); | ||
2190 | i2c_w_mask(ov, 0x2d, qvga?0x40:0x00, 0x40); | ||
2191 | i2c_w_mask(ov, 0x67, qvga?0xf0:0x90, 0xf0); | ||
2192 | i2c_w_mask(ov, 0x74, qvga?0x20:0x00, 0x20); | ||
2193 | break; | ||
2194 | case SEN_OV76BE: | ||
2195 | // i2c_w(ov, 0x2b, 0x00); | ||
2196 | i2c_w(ov, 0x14, qvga?0xa4:0x84); | ||
2197 | // FIXME: Enable this once 7620AE uses 7620 initial settings | ||
2198 | #if 0 | ||
2199 | i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20); | ||
2200 | i2c_w(ov, 0x24, qvga?0x20:0x3a); | ||
2201 | i2c_w(ov, 0x25, qvga?0x30:0x60); | ||
2202 | i2c_w_mask(ov, 0x2d, qvga?0x40:0x00, 0x40); | ||
2203 | i2c_w_mask(ov, 0x67, qvga?0xb0:0x90, 0xf0); | ||
2204 | i2c_w_mask(ov, 0x74, qvga?0x20:0x00, 0x20); | ||
2205 | #endif | ||
2206 | break; | ||
2207 | case SEN_OV6620: | ||
2208 | i2c_w(ov, 0x14, qvga?0x24:0x04); | ||
2209 | break; | ||
2210 | case SEN_OV6630: | ||
2211 | i2c_w(ov, 0x14, qvga?0xa0:0x80); | ||
2212 | break; | ||
2213 | default: | ||
2214 | err("Invalid sensor"); | ||
2215 | return -EINVAL; | ||
2216 | } | ||
2217 | |||
2218 | /******** Palette-specific regs ********/ | ||
2219 | |||
2220 | if (mode == VIDEO_PALETTE_GREY) { | ||
2221 | if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV76BE) { | ||
2222 | /* these aren't valid on the OV6620/OV7620/6630? */ | ||
2223 | i2c_w_mask(ov, 0x0e, 0x40, 0x40); | ||
2224 | } | ||
2225 | |||
2226 | if (ov->sensor == SEN_OV6630 && ov->bridge == BRG_OV518 | ||
2227 | && ov518_color) { | ||
2228 | i2c_w_mask(ov, 0x12, 0x00, 0x10); | ||
2229 | i2c_w_mask(ov, 0x13, 0x00, 0x20); | ||
2230 | } else { | ||
2231 | i2c_w_mask(ov, 0x13, 0x20, 0x20); | ||
2232 | } | ||
2233 | } else { | ||
2234 | if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV76BE) { | ||
2235 | /* not valid on the OV6620/OV7620/6630? */ | ||
2236 | i2c_w_mask(ov, 0x0e, 0x00, 0x40); | ||
2237 | } | ||
2238 | |||
2239 | /* The OV518 needs special treatment. Although both the OV518 | ||
2240 | * and the OV6630 support a 16-bit video bus, only the 8 bit Y | ||
2241 | * bus is actually used. The UV bus is tied to ground. | ||
2242 | * Therefore, the OV6630 needs to be in 8-bit multiplexed | ||
2243 | * output mode */ | ||
2244 | |||
2245 | if (ov->sensor == SEN_OV6630 && ov->bridge == BRG_OV518 | ||
2246 | && ov518_color) { | ||
2247 | i2c_w_mask(ov, 0x12, 0x10, 0x10); | ||
2248 | i2c_w_mask(ov, 0x13, 0x20, 0x20); | ||
2249 | } else { | ||
2250 | i2c_w_mask(ov, 0x13, 0x00, 0x20); | ||
2251 | } | ||
2252 | } | ||
2253 | |||
2254 | /******** Clock programming ********/ | ||
2255 | |||
2256 | /* The OV6620 needs special handling. This prevents the | ||
2257 | * severe banding that normally occurs */ | ||
2258 | if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630) | ||
2259 | { | ||
2260 | /* Clock down */ | ||
2261 | |||
2262 | i2c_w(ov, 0x2a, 0x04); | ||
2263 | |||
2264 | if (ov->compress) { | ||
2265 | // clock = 0; /* This ensures the highest frame rate */ | ||
2266 | clock = 3; | ||
2267 | } else if (clockdiv == -1) { /* If user didn't override it */ | ||
2268 | clock = 3; /* Gives better exposure time */ | ||
2269 | } else { | ||
2270 | clock = clockdiv; | ||
2271 | } | ||
2272 | |||
2273 | PDEBUG(4, "Setting clock divisor to %d", clock); | ||
2274 | |||
2275 | i2c_w(ov, 0x11, clock); | ||
2276 | |||
2277 | i2c_w(ov, 0x2a, 0x84); | ||
2278 | /* This next setting is critical. It seems to improve | ||
2279 | * the gain or the contrast. The "reserved" bits seem | ||
2280 | * to have some effect in this case. */ | ||
2281 | i2c_w(ov, 0x2d, 0x85); | ||
2282 | } | ||
2283 | else | ||
2284 | { | ||
2285 | if (ov->compress) { | ||
2286 | clock = 1; /* This ensures the highest frame rate */ | ||
2287 | } else if (clockdiv == -1) { /* If user didn't override it */ | ||
2288 | /* Calculate and set the clock divisor */ | ||
2289 | clock = ((sub_flag ? ov->subw * ov->subh | ||
2290 | : width * height) | ||
2291 | * (mode == VIDEO_PALETTE_GREY ? 2 : 3) / 2) | ||
2292 | / 66000; | ||
2293 | } else { | ||
2294 | clock = clockdiv; | ||
2295 | } | ||
2296 | |||
2297 | PDEBUG(4, "Setting clock divisor to %d", clock); | ||
2298 | |||
2299 | i2c_w(ov, 0x11, clock); | ||
2300 | } | ||
2301 | |||
2302 | /******** Special Features ********/ | ||
2303 | |||
2304 | if (framedrop >= 0) | ||
2305 | i2c_w(ov, 0x16, framedrop); | ||
2306 | |||
2307 | /* Test Pattern */ | ||
2308 | i2c_w_mask(ov, 0x12, (testpat?0x02:0x00), 0x02); | ||
2309 | |||
2310 | /* Enable auto white balance */ | ||
2311 | i2c_w_mask(ov, 0x12, 0x04, 0x04); | ||
2312 | |||
2313 | // This will go away as soon as ov51x_mode_init_sensor_regs() | ||
2314 | // is fully tested. | ||
2315 | /* 7620/6620/6630? don't have register 0x35, so play it safe */ | ||
2316 | if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV76BE) { | ||
2317 | if (width == 640 && height == 480) | ||
2318 | i2c_w(ov, 0x35, 0x9e); | ||
2319 | else | ||
2320 | i2c_w(ov, 0x35, 0x1e); | ||
2321 | } | ||
2322 | |||
2323 | return 0; | ||
2324 | } | ||
2325 | |||
2326 | static int | ||
2327 | set_ov_sensor_window(struct usb_ov511 *ov, int width, int height, int mode, | ||
2328 | int sub_flag) | ||
2329 | { | ||
2330 | int ret; | ||
2331 | int hwsbase, hwebase, vwsbase, vwebase, hwsize, vwsize; | ||
2332 | int hoffset, voffset, hwscale = 0, vwscale = 0; | ||
2333 | |||
2334 | /* The different sensor ICs handle setting up of window differently. | ||
2335 | * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!!! */ | ||
2336 | switch (ov->sensor) { | ||
2337 | case SEN_OV7610: | ||
2338 | case SEN_OV76BE: | ||
2339 | hwsbase = 0x38; | ||
2340 | hwebase = 0x3a; | ||
2341 | vwsbase = vwebase = 0x05; | ||
2342 | break; | ||
2343 | case SEN_OV6620: | ||
2344 | case SEN_OV6630: | ||
2345 | hwsbase = 0x38; | ||
2346 | hwebase = 0x3a; | ||
2347 | vwsbase = 0x05; | ||
2348 | vwebase = 0x06; | ||
2349 | break; | ||
2350 | case SEN_OV7620: | ||
2351 | hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */ | ||
2352 | hwebase = 0x2f; | ||
2353 | vwsbase = vwebase = 0x05; | ||
2354 | break; | ||
2355 | default: | ||
2356 | err("Invalid sensor"); | ||
2357 | return -EINVAL; | ||
2358 | } | ||
2359 | |||
2360 | if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630) { | ||
2361 | /* Note: OV518(+) does downsample on its own) */ | ||
2362 | if ((width > 176 && height > 144) | ||
2363 | || ov->bclass == BCL_OV518) { /* CIF */ | ||
2364 | ret = mode_init_ov_sensor_regs(ov, width, height, | ||
2365 | mode, sub_flag, 0); | ||
2366 | if (ret < 0) | ||
2367 | return ret; | ||
2368 | hwscale = 1; | ||
2369 | vwscale = 1; /* The datasheet says 0; it's wrong */ | ||
2370 | hwsize = 352; | ||
2371 | vwsize = 288; | ||
2372 | } else if (width > 176 || height > 144) { | ||
2373 | err("Illegal dimensions"); | ||
2374 | return -EINVAL; | ||
2375 | } else { /* QCIF */ | ||
2376 | ret = mode_init_ov_sensor_regs(ov, width, height, | ||
2377 | mode, sub_flag, 1); | ||
2378 | if (ret < 0) | ||
2379 | return ret; | ||
2380 | hwsize = 176; | ||
2381 | vwsize = 144; | ||
2382 | } | ||
2383 | } else { | ||
2384 | if (width > 320 && height > 240) { /* VGA */ | ||
2385 | ret = mode_init_ov_sensor_regs(ov, width, height, | ||
2386 | mode, sub_flag, 0); | ||
2387 | if (ret < 0) | ||
2388 | return ret; | ||
2389 | hwscale = 2; | ||
2390 | vwscale = 1; | ||
2391 | hwsize = 640; | ||
2392 | vwsize = 480; | ||
2393 | } else if (width > 320 || height > 240) { | ||
2394 | err("Illegal dimensions"); | ||
2395 | return -EINVAL; | ||
2396 | } else { /* QVGA */ | ||
2397 | ret = mode_init_ov_sensor_regs(ov, width, height, | ||
2398 | mode, sub_flag, 1); | ||
2399 | if (ret < 0) | ||
2400 | return ret; | ||
2401 | hwscale = 1; | ||
2402 | hwsize = 320; | ||
2403 | vwsize = 240; | ||
2404 | } | ||
2405 | } | ||
2406 | |||
2407 | /* Center the window */ | ||
2408 | hoffset = ((hwsize - width) / 2) >> hwscale; | ||
2409 | voffset = ((vwsize - height) / 2) >> vwscale; | ||
2410 | |||
2411 | /* FIXME! - This needs to be changed to support 160x120 and 6620!!! */ | ||
2412 | if (sub_flag) { | ||
2413 | i2c_w(ov, 0x17, hwsbase+(ov->subx>>hwscale)); | ||
2414 | i2c_w(ov, 0x18, hwebase+((ov->subx+ov->subw)>>hwscale)); | ||
2415 | i2c_w(ov, 0x19, vwsbase+(ov->suby>>vwscale)); | ||
2416 | i2c_w(ov, 0x1a, vwebase+((ov->suby+ov->subh)>>vwscale)); | ||
2417 | } else { | ||
2418 | i2c_w(ov, 0x17, hwsbase + hoffset); | ||
2419 | i2c_w(ov, 0x18, hwebase + hoffset + (hwsize>>hwscale)); | ||
2420 | i2c_w(ov, 0x19, vwsbase + voffset); | ||
2421 | i2c_w(ov, 0x1a, vwebase + voffset + (vwsize>>vwscale)); | ||
2422 | } | ||
2423 | |||
2424 | #ifdef OV511_DEBUG | ||
2425 | if (dump_sensor) | ||
2426 | dump_i2c_regs(ov); | ||
2427 | #endif | ||
2428 | |||
2429 | return 0; | ||
2430 | } | ||
2431 | |||
2432 | /* Set up the OV511/OV511+ with the given image parameters. | ||
2433 | * | ||
2434 | * Do not put any sensor-specific code in here (including I2C I/O functions) | ||
2435 | */ | ||
2436 | static int | ||
2437 | ov511_mode_init_regs(struct usb_ov511 *ov, | ||
2438 | int width, int height, int mode, int sub_flag) | ||
2439 | { | ||
2440 | int hsegs, vsegs; | ||
2441 | |||
2442 | if (sub_flag) { | ||
2443 | width = ov->subw; | ||
2444 | height = ov->subh; | ||
2445 | } | ||
2446 | |||
2447 | PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d", | ||
2448 | width, height, mode, sub_flag); | ||
2449 | |||
2450 | // FIXME: This should be moved to a 7111a-specific function once | ||
2451 | // subcapture is dealt with properly | ||
2452 | if (ov->sensor == SEN_SAA7111A) { | ||
2453 | if (width == 320 && height == 240) { | ||
2454 | /* No need to do anything special */ | ||
2455 | } else if (width == 640 && height == 480) { | ||
2456 | /* Set the OV511 up as 320x480, but keep the | ||
2457 | * V4L resolution as 640x480 */ | ||
2458 | width = 320; | ||
2459 | } else { | ||
2460 | err("SAA7111A only allows 320x240 or 640x480"); | ||
2461 | return -EINVAL; | ||
2462 | } | ||
2463 | } | ||
2464 | |||
2465 | /* Make sure width and height are a multiple of 8 */ | ||
2466 | if (width % 8 || height % 8) { | ||
2467 | err("Invalid size (%d, %d) (mode = %d)", width, height, mode); | ||
2468 | return -EINVAL; | ||
2469 | } | ||
2470 | |||
2471 | if (width < ov->minwidth || height < ov->minheight) { | ||
2472 | err("Requested dimensions are too small"); | ||
2473 | return -EINVAL; | ||
2474 | } | ||
2475 | |||
2476 | if (ov51x_stop(ov) < 0) | ||
2477 | return -EIO; | ||
2478 | |||
2479 | if (mode == VIDEO_PALETTE_GREY) { | ||
2480 | reg_w(ov, R511_CAM_UV_EN, 0x00); | ||
2481 | reg_w(ov, R511_SNAP_UV_EN, 0x00); | ||
2482 | reg_w(ov, R511_SNAP_OPTS, 0x01); | ||
2483 | } else { | ||
2484 | reg_w(ov, R511_CAM_UV_EN, 0x01); | ||
2485 | reg_w(ov, R511_SNAP_UV_EN, 0x01); | ||
2486 | reg_w(ov, R511_SNAP_OPTS, 0x03); | ||
2487 | } | ||
2488 | |||
2489 | /* Here I'm assuming that snapshot size == image size. | ||
2490 | * I hope that's always true. --claudio | ||
2491 | */ | ||
2492 | hsegs = (width >> 3) - 1; | ||
2493 | vsegs = (height >> 3) - 1; | ||
2494 | |||
2495 | reg_w(ov, R511_CAM_PXCNT, hsegs); | ||
2496 | reg_w(ov, R511_CAM_LNCNT, vsegs); | ||
2497 | reg_w(ov, R511_CAM_PXDIV, 0x00); | ||
2498 | reg_w(ov, R511_CAM_LNDIV, 0x00); | ||
2499 | |||
2500 | /* YUV420, low pass filter on */ | ||
2501 | reg_w(ov, R511_CAM_OPTS, 0x03); | ||
2502 | |||
2503 | /* Snapshot additions */ | ||
2504 | reg_w(ov, R511_SNAP_PXCNT, hsegs); | ||
2505 | reg_w(ov, R511_SNAP_LNCNT, vsegs); | ||
2506 | reg_w(ov, R511_SNAP_PXDIV, 0x00); | ||
2507 | reg_w(ov, R511_SNAP_LNDIV, 0x00); | ||
2508 | |||
2509 | if (ov->compress) { | ||
2510 | /* Enable Y and UV quantization and compression */ | ||
2511 | reg_w(ov, R511_COMP_EN, 0x07); | ||
2512 | reg_w(ov, R511_COMP_LUT_EN, 0x03); | ||
2513 | ov51x_reset(ov, OV511_RESET_OMNICE); | ||
2514 | } | ||
2515 | |||
2516 | if (ov51x_restart(ov) < 0) | ||
2517 | return -EIO; | ||
2518 | |||
2519 | return 0; | ||
2520 | } | ||
2521 | |||
2522 | /* Sets up the OV518/OV518+ with the given image parameters | ||
2523 | * | ||
2524 | * OV518 needs a completely different approach, until we can figure out what | ||
2525 | * the individual registers do. Also, only 15 FPS is supported now. | ||
2526 | * | ||
2527 | * Do not put any sensor-specific code in here (including I2C I/O functions) | ||
2528 | */ | ||
2529 | static int | ||
2530 | ov518_mode_init_regs(struct usb_ov511 *ov, | ||
2531 | int width, int height, int mode, int sub_flag) | ||
2532 | { | ||
2533 | int hsegs, vsegs, hi_res; | ||
2534 | |||
2535 | if (sub_flag) { | ||
2536 | width = ov->subw; | ||
2537 | height = ov->subh; | ||
2538 | } | ||
2539 | |||
2540 | PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d", | ||
2541 | width, height, mode, sub_flag); | ||
2542 | |||
2543 | if (width % 16 || height % 8) { | ||
2544 | err("Invalid size (%d, %d)", width, height); | ||
2545 | return -EINVAL; | ||
2546 | } | ||
2547 | |||
2548 | if (width < ov->minwidth || height < ov->minheight) { | ||
2549 | err("Requested dimensions are too small"); | ||
2550 | return -EINVAL; | ||
2551 | } | ||
2552 | |||
2553 | if (width >= 320 && height >= 240) { | ||
2554 | hi_res = 1; | ||
2555 | } else if (width >= 320 || height >= 240) { | ||
2556 | err("Invalid width/height combination (%d, %d)", width, height); | ||
2557 | return -EINVAL; | ||
2558 | } else { | ||
2559 | hi_res = 0; | ||
2560 | } | ||
2561 | |||
2562 | if (ov51x_stop(ov) < 0) | ||
2563 | return -EIO; | ||
2564 | |||
2565 | /******** Set the mode ********/ | ||
2566 | |||
2567 | reg_w(ov, 0x2b, 0); | ||
2568 | reg_w(ov, 0x2c, 0); | ||
2569 | reg_w(ov, 0x2d, 0); | ||
2570 | reg_w(ov, 0x2e, 0); | ||
2571 | reg_w(ov, 0x3b, 0); | ||
2572 | reg_w(ov, 0x3c, 0); | ||
2573 | reg_w(ov, 0x3d, 0); | ||
2574 | reg_w(ov, 0x3e, 0); | ||
2575 | |||
2576 | if (ov->bridge == BRG_OV518 && ov518_color) { | ||
2577 | /* OV518 needs U and V swapped */ | ||
2578 | i2c_w_mask(ov, 0x15, 0x00, 0x01); | ||
2579 | |||
2580 | if (mode == VIDEO_PALETTE_GREY) { | ||
2581 | /* Set 16-bit input format (UV data are ignored) */ | ||
2582 | reg_w_mask(ov, 0x20, 0x00, 0x08); | ||
2583 | |||
2584 | /* Set 8-bit (4:0:0) output format */ | ||
2585 | reg_w_mask(ov, 0x28, 0x00, 0xf0); | ||
2586 | reg_w_mask(ov, 0x38, 0x00, 0xf0); | ||
2587 | } else { | ||
2588 | /* Set 8-bit (YVYU) input format */ | ||
2589 | reg_w_mask(ov, 0x20, 0x08, 0x08); | ||
2590 | |||
2591 | /* Set 12-bit (4:2:0) output format */ | ||
2592 | reg_w_mask(ov, 0x28, 0x80, 0xf0); | ||
2593 | reg_w_mask(ov, 0x38, 0x80, 0xf0); | ||
2594 | } | ||
2595 | } else { | ||
2596 | reg_w(ov, 0x28, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80); | ||
2597 | reg_w(ov, 0x38, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80); | ||
2598 | } | ||
2599 | |||
2600 | hsegs = width / 16; | ||
2601 | vsegs = height / 4; | ||
2602 | |||
2603 | reg_w(ov, 0x29, hsegs); | ||
2604 | reg_w(ov, 0x2a, vsegs); | ||
2605 | |||
2606 | reg_w(ov, 0x39, hsegs); | ||
2607 | reg_w(ov, 0x3a, vsegs); | ||
2608 | |||
2609 | /* Windows driver does this here; who knows why */ | ||
2610 | reg_w(ov, 0x2f, 0x80); | ||
2611 | |||
2612 | /******** Set the framerate (to 15 FPS) ********/ | ||
2613 | |||
2614 | /* Mode independent, but framerate dependent, regs */ | ||
2615 | reg_w(ov, 0x51, 0x02); /* Clock divider; lower==faster */ | ||
2616 | reg_w(ov, 0x22, 0x18); | ||
2617 | reg_w(ov, 0x23, 0xff); | ||
2618 | |||
2619 | if (ov->bridge == BRG_OV518PLUS) | ||
2620 | reg_w(ov, 0x21, 0x19); | ||
2621 | else | ||
2622 | reg_w(ov, 0x71, 0x19); /* Compression-related? */ | ||
2623 | |||
2624 | // FIXME: Sensor-specific | ||
2625 | /* Bit 5 is what matters here. Of course, it is "reserved" */ | ||
2626 | i2c_w(ov, 0x54, 0x23); | ||
2627 | |||
2628 | reg_w(ov, 0x2f, 0x80); | ||
2629 | |||
2630 | if (ov->bridge == BRG_OV518PLUS) { | ||
2631 | reg_w(ov, 0x24, 0x94); | ||
2632 | reg_w(ov, 0x25, 0x90); | ||
2633 | ov518_reg_w32(ov, 0xc4, 400, 2); /* 190h */ | ||
2634 | ov518_reg_w32(ov, 0xc6, 540, 2); /* 21ch */ | ||
2635 | ov518_reg_w32(ov, 0xc7, 540, 2); /* 21ch */ | ||
2636 | ov518_reg_w32(ov, 0xc8, 108, 2); /* 6ch */ | ||
2637 | ov518_reg_w32(ov, 0xca, 131098, 3); /* 2001ah */ | ||
2638 | ov518_reg_w32(ov, 0xcb, 532, 2); /* 214h */ | ||
2639 | ov518_reg_w32(ov, 0xcc, 2400, 2); /* 960h */ | ||
2640 | ov518_reg_w32(ov, 0xcd, 32, 2); /* 20h */ | ||
2641 | ov518_reg_w32(ov, 0xce, 608, 2); /* 260h */ | ||
2642 | } else { | ||
2643 | reg_w(ov, 0x24, 0x9f); | ||
2644 | reg_w(ov, 0x25, 0x90); | ||
2645 | ov518_reg_w32(ov, 0xc4, 400, 2); /* 190h */ | ||
2646 | ov518_reg_w32(ov, 0xc6, 500, 2); /* 1f4h */ | ||
2647 | ov518_reg_w32(ov, 0xc7, 500, 2); /* 1f4h */ | ||
2648 | ov518_reg_w32(ov, 0xc8, 142, 2); /* 8eh */ | ||
2649 | ov518_reg_w32(ov, 0xca, 131098, 3); /* 2001ah */ | ||
2650 | ov518_reg_w32(ov, 0xcb, 532, 2); /* 214h */ | ||
2651 | ov518_reg_w32(ov, 0xcc, 2000, 2); /* 7d0h */ | ||
2652 | ov518_reg_w32(ov, 0xcd, 32, 2); /* 20h */ | ||
2653 | ov518_reg_w32(ov, 0xce, 608, 2); /* 260h */ | ||
2654 | } | ||
2655 | |||
2656 | reg_w(ov, 0x2f, 0x80); | ||
2657 | |||
2658 | if (ov51x_restart(ov) < 0) | ||
2659 | return -EIO; | ||
2660 | |||
2661 | /* Reset it just for good measure */ | ||
2662 | if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0) | ||
2663 | return -EIO; | ||
2664 | |||
2665 | return 0; | ||
2666 | } | ||
2667 | |||
2668 | /* This is a wrapper around the OV511, OV518, and sensor specific functions */ | ||
2669 | static int | ||
2670 | mode_init_regs(struct usb_ov511 *ov, | ||
2671 | int width, int height, int mode, int sub_flag) | ||
2672 | { | ||
2673 | int rc = 0; | ||
2674 | |||
2675 | if (!ov || !ov->dev) | ||
2676 | return -EFAULT; | ||
2677 | |||
2678 | if (ov->bclass == BCL_OV518) { | ||
2679 | rc = ov518_mode_init_regs(ov, width, height, mode, sub_flag); | ||
2680 | } else { | ||
2681 | rc = ov511_mode_init_regs(ov, width, height, mode, sub_flag); | ||
2682 | } | ||
2683 | |||
2684 | if (FATAL_ERROR(rc)) | ||
2685 | return rc; | ||
2686 | |||
2687 | switch (ov->sensor) { | ||
2688 | case SEN_OV7610: | ||
2689 | case SEN_OV7620: | ||
2690 | case SEN_OV76BE: | ||
2691 | case SEN_OV8600: | ||
2692 | case SEN_OV6620: | ||
2693 | case SEN_OV6630: | ||
2694 | rc = set_ov_sensor_window(ov, width, height, mode, sub_flag); | ||
2695 | break; | ||
2696 | case SEN_KS0127: | ||
2697 | case SEN_KS0127B: | ||
2698 | err("KS0127-series decoders not supported yet"); | ||
2699 | rc = -EINVAL; | ||
2700 | break; | ||
2701 | case SEN_SAA7111A: | ||
2702 | // rc = mode_init_saa_sensor_regs(ov, width, height, mode, | ||
2703 | // sub_flag); | ||
2704 | |||
2705 | PDEBUG(1, "SAA status = 0x%02X", i2c_r(ov, 0x1f)); | ||
2706 | break; | ||
2707 | default: | ||
2708 | err("Unknown sensor"); | ||
2709 | rc = -EINVAL; | ||
2710 | } | ||
2711 | |||
2712 | if (FATAL_ERROR(rc)) | ||
2713 | return rc; | ||
2714 | |||
2715 | /* Sensor-independent settings */ | ||
2716 | rc = sensor_set_auto_brightness(ov, ov->auto_brt); | ||
2717 | if (FATAL_ERROR(rc)) | ||
2718 | return rc; | ||
2719 | |||
2720 | rc = sensor_set_auto_exposure(ov, ov->auto_exp); | ||
2721 | if (FATAL_ERROR(rc)) | ||
2722 | return rc; | ||
2723 | |||
2724 | rc = sensor_set_banding_filter(ov, bandingfilter); | ||
2725 | if (FATAL_ERROR(rc)) | ||
2726 | return rc; | ||
2727 | |||
2728 | if (ov->lightfreq) { | ||
2729 | rc = sensor_set_light_freq(ov, lightfreq); | ||
2730 | if (FATAL_ERROR(rc)) | ||
2731 | return rc; | ||
2732 | } | ||
2733 | |||
2734 | rc = sensor_set_backlight(ov, ov->backlight); | ||
2735 | if (FATAL_ERROR(rc)) | ||
2736 | return rc; | ||
2737 | |||
2738 | rc = sensor_set_mirror(ov, ov->mirror); | ||
2739 | if (FATAL_ERROR(rc)) | ||
2740 | return rc; | ||
2741 | |||
2742 | return 0; | ||
2743 | } | ||
2744 | |||
2745 | /* This sets the default image parameters. This is useful for apps that use | ||
2746 | * read() and do not set these. | ||
2747 | */ | ||
2748 | static int | ||
2749 | ov51x_set_default_params(struct usb_ov511 *ov) | ||
2750 | { | ||
2751 | int i; | ||
2752 | |||
2753 | /* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used | ||
2754 | * (using read() instead). */ | ||
2755 | for (i = 0; i < OV511_NUMFRAMES; i++) { | ||
2756 | ov->frame[i].width = ov->maxwidth; | ||
2757 | ov->frame[i].height = ov->maxheight; | ||
2758 | ov->frame[i].bytes_read = 0; | ||
2759 | if (force_palette) | ||
2760 | ov->frame[i].format = force_palette; | ||
2761 | else | ||
2762 | ov->frame[i].format = VIDEO_PALETTE_YUV420; | ||
2763 | |||
2764 | ov->frame[i].depth = get_depth(ov->frame[i].format); | ||
2765 | } | ||
2766 | |||
2767 | PDEBUG(3, "%dx%d, %s", ov->maxwidth, ov->maxheight, | ||
2768 | symbolic(v4l1_plist, ov->frame[0].format)); | ||
2769 | |||
2770 | /* Initialize to max width/height, YUV420 or RGB24 (if supported) */ | ||
2771 | if (mode_init_regs(ov, ov->maxwidth, ov->maxheight, | ||
2772 | ov->frame[0].format, 0) < 0) | ||
2773 | return -EINVAL; | ||
2774 | |||
2775 | return 0; | ||
2776 | } | ||
2777 | |||
2778 | /********************************************************************** | ||
2779 | * | ||
2780 | * Video decoder stuff | ||
2781 | * | ||
2782 | **********************************************************************/ | ||
2783 | |||
2784 | /* Set analog input port of decoder */ | ||
2785 | static int | ||
2786 | decoder_set_input(struct usb_ov511 *ov, int input) | ||
2787 | { | ||
2788 | PDEBUG(4, "port %d", input); | ||
2789 | |||
2790 | switch (ov->sensor) { | ||
2791 | case SEN_SAA7111A: | ||
2792 | { | ||
2793 | /* Select mode */ | ||
2794 | i2c_w_mask(ov, 0x02, input, 0x07); | ||
2795 | /* Bypass chrominance trap for modes 4..7 */ | ||
2796 | i2c_w_mask(ov, 0x09, (input > 3) ? 0x80:0x00, 0x80); | ||
2797 | break; | ||
2798 | } | ||
2799 | default: | ||
2800 | return -EINVAL; | ||
2801 | } | ||
2802 | |||
2803 | return 0; | ||
2804 | } | ||
2805 | |||
2806 | /* Get ASCII name of video input */ | ||
2807 | static int | ||
2808 | decoder_get_input_name(struct usb_ov511 *ov, int input, char *name) | ||
2809 | { | ||
2810 | switch (ov->sensor) { | ||
2811 | case SEN_SAA7111A: | ||
2812 | { | ||
2813 | if (input < 0 || input > 7) | ||
2814 | return -EINVAL; | ||
2815 | else if (input < 4) | ||
2816 | sprintf(name, "CVBS-%d", input); | ||
2817 | else // if (input < 8) | ||
2818 | sprintf(name, "S-Video-%d", input - 4); | ||
2819 | break; | ||
2820 | } | ||
2821 | default: | ||
2822 | sprintf(name, "%s", "Camera"); | ||
2823 | } | ||
2824 | |||
2825 | return 0; | ||
2826 | } | ||
2827 | |||
2828 | /* Set norm (NTSC, PAL, SECAM, AUTO) */ | ||
2829 | static int | ||
2830 | decoder_set_norm(struct usb_ov511 *ov, int norm) | ||
2831 | { | ||
2832 | PDEBUG(4, "%d", norm); | ||
2833 | |||
2834 | switch (ov->sensor) { | ||
2835 | case SEN_SAA7111A: | ||
2836 | { | ||
2837 | int reg_8, reg_e; | ||
2838 | |||
2839 | if (norm == VIDEO_MODE_NTSC) { | ||
2840 | reg_8 = 0x40; /* 60 Hz */ | ||
2841 | reg_e = 0x00; /* NTSC M / PAL BGHI */ | ||
2842 | } else if (norm == VIDEO_MODE_PAL) { | ||
2843 | reg_8 = 0x00; /* 50 Hz */ | ||
2844 | reg_e = 0x00; /* NTSC M / PAL BGHI */ | ||
2845 | } else if (norm == VIDEO_MODE_AUTO) { | ||
2846 | reg_8 = 0x80; /* Auto field detect */ | ||
2847 | reg_e = 0x00; /* NTSC M / PAL BGHI */ | ||
2848 | } else if (norm == VIDEO_MODE_SECAM) { | ||
2849 | reg_8 = 0x00; /* 50 Hz */ | ||
2850 | reg_e = 0x50; /* SECAM / PAL 4.43 */ | ||
2851 | } else { | ||
2852 | return -EINVAL; | ||
2853 | } | ||
2854 | |||
2855 | i2c_w_mask(ov, 0x08, reg_8, 0xc0); | ||
2856 | i2c_w_mask(ov, 0x0e, reg_e, 0x70); | ||
2857 | break; | ||
2858 | } | ||
2859 | default: | ||
2860 | return -EINVAL; | ||
2861 | } | ||
2862 | |||
2863 | return 0; | ||
2864 | } | ||
2865 | |||
2866 | /********************************************************************** | ||
2867 | * | ||
2868 | * Raw data parsing | ||
2869 | * | ||
2870 | **********************************************************************/ | ||
2871 | |||
2872 | /* Copies a 64-byte segment at pIn to an 8x8 block at pOut. The width of the | ||
2873 | * image at pOut is specified by w. | ||
2874 | */ | ||
2875 | static inline void | ||
2876 | make_8x8(unsigned char *pIn, unsigned char *pOut, int w) | ||
2877 | { | ||
2878 | unsigned char *pOut1 = pOut; | ||
2879 | int x, y; | ||
2880 | |||
2881 | for (y = 0; y < 8; y++) { | ||
2882 | pOut1 = pOut; | ||
2883 | for (x = 0; x < 8; x++) { | ||
2884 | *pOut1++ = *pIn++; | ||
2885 | } | ||
2886 | pOut += w; | ||
2887 | } | ||
2888 | } | ||
2889 | |||
2890 | /* | ||
2891 | * For RAW BW (YUV 4:0:0) images, data show up in 256 byte segments. | ||
2892 | * The segments represent 4 squares of 8x8 pixels as follows: | ||
2893 | * | ||
2894 | * 0 1 ... 7 64 65 ... 71 ... 192 193 ... 199 | ||
2895 | * 8 9 ... 15 72 73 ... 79 200 201 ... 207 | ||
2896 | * ... ... ... | ||
2897 | * 56 57 ... 63 120 121 ... 127 248 249 ... 255 | ||
2898 | * | ||
2899 | */ | ||
2900 | static void | ||
2901 | yuv400raw_to_yuv400p(struct ov511_frame *frame, | ||
2902 | unsigned char *pIn0, unsigned char *pOut0) | ||
2903 | { | ||
2904 | int x, y; | ||
2905 | unsigned char *pIn, *pOut, *pOutLine; | ||
2906 | |||
2907 | /* Copy Y */ | ||
2908 | pIn = pIn0; | ||
2909 | pOutLine = pOut0; | ||
2910 | for (y = 0; y < frame->rawheight - 1; y += 8) { | ||
2911 | pOut = pOutLine; | ||
2912 | for (x = 0; x < frame->rawwidth - 1; x += 8) { | ||
2913 | make_8x8(pIn, pOut, frame->rawwidth); | ||
2914 | pIn += 64; | ||
2915 | pOut += 8; | ||
2916 | } | ||
2917 | pOutLine += 8 * frame->rawwidth; | ||
2918 | } | ||
2919 | } | ||
2920 | |||
2921 | /* | ||
2922 | * For YUV 4:2:0 images, the data show up in 384 byte segments. | ||
2923 | * The first 64 bytes of each segment are U, the next 64 are V. The U and | ||
2924 | * V are arranged as follows: | ||
2925 | * | ||
2926 | * 0 1 ... 7 | ||
2927 | * 8 9 ... 15 | ||
2928 | * ... | ||
2929 | * 56 57 ... 63 | ||
2930 | * | ||
2931 | * U and V are shipped at half resolution (1 U,V sample -> one 2x2 block). | ||
2932 | * | ||
2933 | * The next 256 bytes are full resolution Y data and represent 4 squares | ||
2934 | * of 8x8 pixels as follows: | ||
2935 | * | ||
2936 | * 0 1 ... 7 64 65 ... 71 ... 192 193 ... 199 | ||
2937 | * 8 9 ... 15 72 73 ... 79 200 201 ... 207 | ||
2938 | * ... ... ... | ||
2939 | * 56 57 ... 63 120 121 ... 127 ... 248 249 ... 255 | ||
2940 | * | ||
2941 | * Note that the U and V data in one segment represent a 16 x 16 pixel | ||
2942 | * area, but the Y data represent a 32 x 8 pixel area. If the width is not an | ||
2943 | * even multiple of 32, the extra 8x8 blocks within a 32x8 block belong to the | ||
2944 | * next horizontal stripe. | ||
2945 | * | ||
2946 | * If dumppix module param is set, _parse_data just dumps the incoming segments, | ||
2947 | * verbatim, in order, into the frame. When used with vidcat -f ppm -s 640x480 | ||
2948 | * this puts the data on the standard output and can be analyzed with the | ||
2949 | * parseppm.c utility I wrote. That's a much faster way for figuring out how | ||
2950 | * these data are scrambled. | ||
2951 | */ | ||
2952 | |||
2953 | /* Converts from raw, uncompressed segments at pIn0 to a YUV420P frame at pOut0. | ||
2954 | * | ||
2955 | * FIXME: Currently only handles width and height that are multiples of 16 | ||
2956 | */ | ||
2957 | static void | ||
2958 | yuv420raw_to_yuv420p(struct ov511_frame *frame, | ||
2959 | unsigned char *pIn0, unsigned char *pOut0) | ||
2960 | { | ||
2961 | int k, x, y; | ||
2962 | unsigned char *pIn, *pOut, *pOutLine; | ||
2963 | const unsigned int a = frame->rawwidth * frame->rawheight; | ||
2964 | const unsigned int w = frame->rawwidth / 2; | ||
2965 | |||
2966 | /* Copy U and V */ | ||
2967 | pIn = pIn0; | ||
2968 | pOutLine = pOut0 + a; | ||
2969 | for (y = 0; y < frame->rawheight - 1; y += 16) { | ||
2970 | pOut = pOutLine; | ||
2971 | for (x = 0; x < frame->rawwidth - 1; x += 16) { | ||
2972 | make_8x8(pIn, pOut, w); | ||
2973 | make_8x8(pIn + 64, pOut + a/4, w); | ||
2974 | pIn += 384; | ||
2975 | pOut += 8; | ||
2976 | } | ||
2977 | pOutLine += 8 * w; | ||
2978 | } | ||
2979 | |||
2980 | /* Copy Y */ | ||
2981 | pIn = pIn0 + 128; | ||
2982 | pOutLine = pOut0; | ||
2983 | k = 0; | ||
2984 | for (y = 0; y < frame->rawheight - 1; y += 8) { | ||
2985 | pOut = pOutLine; | ||
2986 | for (x = 0; x < frame->rawwidth - 1; x += 8) { | ||
2987 | make_8x8(pIn, pOut, frame->rawwidth); | ||
2988 | pIn += 64; | ||
2989 | pOut += 8; | ||
2990 | if ((++k) > 3) { | ||
2991 | k = 0; | ||
2992 | pIn += 128; | ||
2993 | } | ||
2994 | } | ||
2995 | pOutLine += 8 * frame->rawwidth; | ||
2996 | } | ||
2997 | } | ||
2998 | |||
2999 | /********************************************************************** | ||
3000 | * | ||
3001 | * Decompression | ||
3002 | * | ||
3003 | **********************************************************************/ | ||
3004 | |||
3005 | static int | ||
3006 | request_decompressor(struct usb_ov511 *ov) | ||
3007 | { | ||
3008 | if (ov->bclass == BCL_OV511 || ov->bclass == BCL_OV518) { | ||
3009 | err("No decompressor available"); | ||
3010 | } else { | ||
3011 | err("Unknown bridge"); | ||
3012 | } | ||
3013 | |||
3014 | return -ENOSYS; | ||
3015 | } | ||
3016 | |||
3017 | static void | ||
3018 | decompress(struct usb_ov511 *ov, struct ov511_frame *frame, | ||
3019 | unsigned char *pIn0, unsigned char *pOut0) | ||
3020 | { | ||
3021 | if (!ov->decomp_ops) | ||
3022 | if (request_decompressor(ov)) | ||
3023 | return; | ||
3024 | |||
3025 | } | ||
3026 | |||
3027 | /********************************************************************** | ||
3028 | * | ||
3029 | * Format conversion | ||
3030 | * | ||
3031 | **********************************************************************/ | ||
3032 | |||
3033 | /* Fuses even and odd fields together, and doubles width. | ||
3034 | * INPUT: an odd field followed by an even field at pIn0, in YUV planar format | ||
3035 | * OUTPUT: a normal YUV planar image, with correct aspect ratio | ||
3036 | */ | ||
3037 | static void | ||
3038 | deinterlace(struct ov511_frame *frame, int rawformat, | ||
3039 | unsigned char *pIn0, unsigned char *pOut0) | ||
3040 | { | ||
3041 | const int fieldheight = frame->rawheight / 2; | ||
3042 | const int fieldpix = fieldheight * frame->rawwidth; | ||
3043 | const int w = frame->width; | ||
3044 | int x, y; | ||
3045 | unsigned char *pInEven, *pInOdd, *pOut; | ||
3046 | |||
3047 | PDEBUG(5, "fieldheight=%d", fieldheight); | ||
3048 | |||
3049 | if (frame->rawheight != frame->height) { | ||
3050 | err("invalid height"); | ||
3051 | return; | ||
3052 | } | ||
3053 | |||
3054 | if ((frame->rawwidth * 2) != frame->width) { | ||
3055 | err("invalid width"); | ||
3056 | return; | ||
3057 | } | ||
3058 | |||
3059 | /* Y */ | ||
3060 | pInOdd = pIn0; | ||
3061 | pInEven = pInOdd + fieldpix; | ||
3062 | pOut = pOut0; | ||
3063 | for (y = 0; y < fieldheight; y++) { | ||
3064 | for (x = 0; x < frame->rawwidth; x++) { | ||
3065 | *pOut = *pInEven; | ||
3066 | *(pOut+1) = *pInEven++; | ||
3067 | *(pOut+w) = *pInOdd; | ||
3068 | *(pOut+w+1) = *pInOdd++; | ||
3069 | pOut += 2; | ||
3070 | } | ||
3071 | pOut += w; | ||
3072 | } | ||
3073 | |||
3074 | if (rawformat == RAWFMT_YUV420) { | ||
3075 | /* U */ | ||
3076 | pInOdd = pIn0 + fieldpix * 2; | ||
3077 | pInEven = pInOdd + fieldpix / 4; | ||
3078 | for (y = 0; y < fieldheight / 2; y++) { | ||
3079 | for (x = 0; x < frame->rawwidth / 2; x++) { | ||
3080 | *pOut = *pInEven; | ||
3081 | *(pOut+1) = *pInEven++; | ||
3082 | *(pOut+w/2) = *pInOdd; | ||
3083 | *(pOut+w/2+1) = *pInOdd++; | ||
3084 | pOut += 2; | ||
3085 | } | ||
3086 | pOut += w/2; | ||
3087 | } | ||
3088 | /* V */ | ||
3089 | pInOdd = pIn0 + fieldpix * 2 + fieldpix / 2; | ||
3090 | pInEven = pInOdd + fieldpix / 4; | ||
3091 | for (y = 0; y < fieldheight / 2; y++) { | ||
3092 | for (x = 0; x < frame->rawwidth / 2; x++) { | ||
3093 | *pOut = *pInEven; | ||
3094 | *(pOut+1) = *pInEven++; | ||
3095 | *(pOut+w/2) = *pInOdd; | ||
3096 | *(pOut+w/2+1) = *pInOdd++; | ||
3097 | pOut += 2; | ||
3098 | } | ||
3099 | pOut += w/2; | ||
3100 | } | ||
3101 | } | ||
3102 | } | ||
3103 | |||
3104 | static void | ||
3105 | ov51x_postprocess_grey(struct usb_ov511 *ov, struct ov511_frame *frame) | ||
3106 | { | ||
3107 | /* Deinterlace frame, if necessary */ | ||
3108 | if (ov->sensor == SEN_SAA7111A && frame->rawheight >= 480) { | ||
3109 | if (frame->compressed) | ||
3110 | decompress(ov, frame, frame->rawdata, | ||
3111 | frame->tempdata); | ||
3112 | else | ||
3113 | yuv400raw_to_yuv400p(frame, frame->rawdata, | ||
3114 | frame->tempdata); | ||
3115 | |||
3116 | deinterlace(frame, RAWFMT_YUV400, frame->tempdata, | ||
3117 | frame->data); | ||
3118 | } else { | ||
3119 | if (frame->compressed) | ||
3120 | decompress(ov, frame, frame->rawdata, | ||
3121 | frame->data); | ||
3122 | else | ||
3123 | yuv400raw_to_yuv400p(frame, frame->rawdata, | ||
3124 | frame->data); | ||
3125 | } | ||
3126 | } | ||
3127 | |||
3128 | /* Process raw YUV420 data into standard YUV420P */ | ||
3129 | static void | ||
3130 | ov51x_postprocess_yuv420(struct usb_ov511 *ov, struct ov511_frame *frame) | ||
3131 | { | ||
3132 | /* Deinterlace frame, if necessary */ | ||
3133 | if (ov->sensor == SEN_SAA7111A && frame->rawheight >= 480) { | ||
3134 | if (frame->compressed) | ||
3135 | decompress(ov, frame, frame->rawdata, frame->tempdata); | ||
3136 | else | ||
3137 | yuv420raw_to_yuv420p(frame, frame->rawdata, | ||
3138 | frame->tempdata); | ||
3139 | |||
3140 | deinterlace(frame, RAWFMT_YUV420, frame->tempdata, | ||
3141 | frame->data); | ||
3142 | } else { | ||
3143 | if (frame->compressed) | ||
3144 | decompress(ov, frame, frame->rawdata, frame->data); | ||
3145 | else | ||
3146 | yuv420raw_to_yuv420p(frame, frame->rawdata, | ||
3147 | frame->data); | ||
3148 | } | ||
3149 | } | ||
3150 | |||
3151 | /* Post-processes the specified frame. This consists of: | ||
3152 | * 1. Decompress frame, if necessary | ||
3153 | * 2. Deinterlace frame and scale to proper size, if necessary | ||
3154 | * 3. Convert from YUV planar to destination format, if necessary | ||
3155 | * 4. Fix the RGB offset, if necessary | ||
3156 | */ | ||
3157 | static void | ||
3158 | ov51x_postprocess(struct usb_ov511 *ov, struct ov511_frame *frame) | ||
3159 | { | ||
3160 | if (dumppix) { | ||
3161 | memset(frame->data, 0, | ||
3162 | MAX_DATA_SIZE(ov->maxwidth, ov->maxheight)); | ||
3163 | PDEBUG(4, "Dumping %d bytes", frame->bytes_recvd); | ||
3164 | memcpy(frame->data, frame->rawdata, frame->bytes_recvd); | ||
3165 | } else { | ||
3166 | switch (frame->format) { | ||
3167 | case VIDEO_PALETTE_GREY: | ||
3168 | ov51x_postprocess_grey(ov, frame); | ||
3169 | break; | ||
3170 | case VIDEO_PALETTE_YUV420: | ||
3171 | case VIDEO_PALETTE_YUV420P: | ||
3172 | ov51x_postprocess_yuv420(ov, frame); | ||
3173 | break; | ||
3174 | default: | ||
3175 | err("Cannot convert data to %s", | ||
3176 | symbolic(v4l1_plist, frame->format)); | ||
3177 | } | ||
3178 | } | ||
3179 | } | ||
3180 | |||
3181 | /********************************************************************** | ||
3182 | * | ||
3183 | * OV51x data transfer, IRQ handler | ||
3184 | * | ||
3185 | **********************************************************************/ | ||
3186 | |||
3187 | static inline void | ||
3188 | ov511_move_data(struct usb_ov511 *ov, unsigned char *in, int n) | ||
3189 | { | ||
3190 | int num, offset; | ||
3191 | int pnum = in[ov->packet_size - 1]; /* Get packet number */ | ||
3192 | int max_raw = MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight); | ||
3193 | struct ov511_frame *frame = &ov->frame[ov->curframe]; | ||
3194 | struct timeval *ts; | ||
3195 | |||
3196 | /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th | ||
3197 | * byte non-zero. The EOF packet has image width/height in the | ||
3198 | * 10th and 11th bytes. The 9th byte is given as follows: | ||
3199 | * | ||
3200 | * bit 7: EOF | ||
3201 | * 6: compression enabled | ||
3202 | * 5: 422/420/400 modes | ||
3203 | * 4: 422/420/400 modes | ||
3204 | * 3: 1 | ||
3205 | * 2: snapshot button on | ||
3206 | * 1: snapshot frame | ||
3207 | * 0: even/odd field | ||
3208 | */ | ||
3209 | |||
3210 | if (printph) { | ||
3211 | dev_info(&ov->dev->dev, | ||
3212 | "ph(%3d): %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x\n", | ||
3213 | pnum, in[0], in[1], in[2], in[3], in[4], in[5], in[6], | ||
3214 | in[7], in[8], in[9], in[10], in[11]); | ||
3215 | } | ||
3216 | |||
3217 | /* Check for SOF/EOF packet */ | ||
3218 | if ((in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) || | ||
3219 | (~in[8] & 0x08)) | ||
3220 | goto check_middle; | ||
3221 | |||
3222 | /* Frame end */ | ||
3223 | if (in[8] & 0x80) { | ||
3224 | ts = (struct timeval *)(frame->data | ||
3225 | + MAX_FRAME_SIZE(ov->maxwidth, ov->maxheight)); | ||
3226 | do_gettimeofday(ts); | ||
3227 | |||
3228 | /* Get the actual frame size from the EOF header */ | ||
3229 | frame->rawwidth = ((int)(in[9]) + 1) * 8; | ||
3230 | frame->rawheight = ((int)(in[10]) + 1) * 8; | ||
3231 | |||
3232 | PDEBUG(4, "Frame end, frame=%d, pnum=%d, w=%d, h=%d, recvd=%d", | ||
3233 | ov->curframe, pnum, frame->rawwidth, frame->rawheight, | ||
3234 | frame->bytes_recvd); | ||
3235 | |||
3236 | /* Validate the header data */ | ||
3237 | RESTRICT_TO_RANGE(frame->rawwidth, ov->minwidth, ov->maxwidth); | ||
3238 | RESTRICT_TO_RANGE(frame->rawheight, ov->minheight, | ||
3239 | ov->maxheight); | ||
3240 | |||
3241 | /* Don't allow byte count to exceed buffer size */ | ||
3242 | RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw); | ||
3243 | |||
3244 | if (frame->scanstate == STATE_LINES) { | ||
3245 | int nextf; | ||
3246 | |||
3247 | frame->grabstate = FRAME_DONE; | ||
3248 | wake_up_interruptible(&frame->wq); | ||
3249 | |||
3250 | /* If next frame is ready or grabbing, | ||
3251 | * point to it */ | ||
3252 | nextf = (ov->curframe + 1) % OV511_NUMFRAMES; | ||
3253 | if (ov->frame[nextf].grabstate == FRAME_READY | ||
3254 | || ov->frame[nextf].grabstate == FRAME_GRABBING) { | ||
3255 | ov->curframe = nextf; | ||
3256 | ov->frame[nextf].scanstate = STATE_SCANNING; | ||
3257 | } else { | ||
3258 | if (frame->grabstate == FRAME_DONE) { | ||
3259 | PDEBUG(4, "** Frame done **"); | ||
3260 | } else { | ||
3261 | PDEBUG(4, "Frame not ready? state = %d", | ||
3262 | ov->frame[nextf].grabstate); | ||
3263 | } | ||
3264 | |||
3265 | ov->curframe = -1; | ||
3266 | } | ||
3267 | } else { | ||
3268 | PDEBUG(5, "Frame done, but not scanning"); | ||
3269 | } | ||
3270 | /* Image corruption caused by misplaced frame->segment = 0 | ||
3271 | * fixed by carlosf@conectiva.com.br | ||
3272 | */ | ||
3273 | } else { | ||
3274 | /* Frame start */ | ||
3275 | PDEBUG(4, "Frame start, framenum = %d", ov->curframe); | ||
3276 | |||
3277 | /* Check to see if it's a snapshot frame */ | ||
3278 | /* FIXME?? Should the snapshot reset go here? Performance? */ | ||
3279 | if (in[8] & 0x02) { | ||
3280 | frame->snapshot = 1; | ||
3281 | PDEBUG(3, "snapshot detected"); | ||
3282 | } | ||
3283 | |||
3284 | frame->scanstate = STATE_LINES; | ||
3285 | frame->bytes_recvd = 0; | ||
3286 | frame->compressed = in[8] & 0x40; | ||
3287 | } | ||
3288 | |||
3289 | check_middle: | ||
3290 | /* Are we in a frame? */ | ||
3291 | if (frame->scanstate != STATE_LINES) { | ||
3292 | PDEBUG(5, "Not in a frame; packet skipped"); | ||
3293 | return; | ||
3294 | } | ||
3295 | |||
3296 | /* If frame start, skip header */ | ||
3297 | if (frame->bytes_recvd == 0) | ||
3298 | offset = 9; | ||
3299 | else | ||
3300 | offset = 0; | ||
3301 | |||
3302 | num = n - offset - 1; | ||
3303 | |||
3304 | /* Dump all data exactly as received */ | ||
3305 | if (dumppix == 2) { | ||
3306 | frame->bytes_recvd += n - 1; | ||
3307 | if (frame->bytes_recvd <= max_raw) | ||
3308 | memcpy(frame->rawdata + frame->bytes_recvd - (n - 1), | ||
3309 | in, n - 1); | ||
3310 | else | ||
3311 | PDEBUG(3, "Raw data buffer overrun!! (%d)", | ||
3312 | frame->bytes_recvd - max_raw); | ||
3313 | } else if (!frame->compressed && !remove_zeros) { | ||
3314 | frame->bytes_recvd += num; | ||
3315 | if (frame->bytes_recvd <= max_raw) | ||
3316 | memcpy(frame->rawdata + frame->bytes_recvd - num, | ||
3317 | in + offset, num); | ||
3318 | else | ||
3319 | PDEBUG(3, "Raw data buffer overrun!! (%d)", | ||
3320 | frame->bytes_recvd - max_raw); | ||
3321 | } else { /* Remove all-zero FIFO lines (aligned 32-byte blocks) */ | ||
3322 | int b, read = 0, allzero, copied = 0; | ||
3323 | if (offset) { | ||
3324 | frame->bytes_recvd += 32 - offset; // Bytes out | ||
3325 | memcpy(frame->rawdata, in + offset, 32 - offset); | ||
3326 | read += 32; | ||
3327 | } | ||
3328 | |||
3329 | while (read < n - 1) { | ||
3330 | allzero = 1; | ||
3331 | for (b = 0; b < 32; b++) { | ||
3332 | if (in[read + b]) { | ||
3333 | allzero = 0; | ||
3334 | break; | ||
3335 | } | ||
3336 | } | ||
3337 | |||
3338 | if (allzero) { | ||
3339 | /* Don't copy it */ | ||
3340 | } else { | ||
3341 | if (frame->bytes_recvd + copied + 32 <= max_raw) | ||
3342 | { | ||
3343 | memcpy(frame->rawdata | ||
3344 | + frame->bytes_recvd + copied, | ||
3345 | in + read, 32); | ||
3346 | copied += 32; | ||
3347 | } else { | ||
3348 | PDEBUG(3, "Raw data buffer overrun!!"); | ||
3349 | } | ||
3350 | } | ||
3351 | read += 32; | ||
3352 | } | ||
3353 | |||
3354 | frame->bytes_recvd += copied; | ||
3355 | } | ||
3356 | } | ||
3357 | |||
3358 | static inline void | ||
3359 | ov518_move_data(struct usb_ov511 *ov, unsigned char *in, int n) | ||
3360 | { | ||
3361 | int max_raw = MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight); | ||
3362 | struct ov511_frame *frame = &ov->frame[ov->curframe]; | ||
3363 | struct timeval *ts; | ||
3364 | |||
3365 | /* Don't copy the packet number byte */ | ||
3366 | if (ov->packet_numbering) | ||
3367 | --n; | ||
3368 | |||
3369 | /* A false positive here is likely, until OVT gives me | ||
3370 | * the definitive SOF/EOF format */ | ||
3371 | if ((!(in[0] | in[1] | in[2] | in[3] | in[5])) && in[6]) { | ||
3372 | if (printph) { | ||
3373 | dev_info(&ov->dev->dev, | ||
3374 | "ph: %2x %2x %2x %2x %2x %2x %2x %2x\n", | ||
3375 | in[0], in[1], in[2], in[3], in[4], in[5], | ||
3376 | in[6], in[7]); | ||
3377 | } | ||
3378 | |||
3379 | if (frame->scanstate == STATE_LINES) { | ||
3380 | PDEBUG(4, "Detected frame end/start"); | ||
3381 | goto eof; | ||
3382 | } else { //scanstate == STATE_SCANNING | ||
3383 | /* Frame start */ | ||
3384 | PDEBUG(4, "Frame start, framenum = %d", ov->curframe); | ||
3385 | goto sof; | ||
3386 | } | ||
3387 | } else { | ||
3388 | goto check_middle; | ||
3389 | } | ||
3390 | |||
3391 | eof: | ||
3392 | ts = (struct timeval *)(frame->data | ||
3393 | + MAX_FRAME_SIZE(ov->maxwidth, ov->maxheight)); | ||
3394 | do_gettimeofday(ts); | ||
3395 | |||
3396 | PDEBUG(4, "Frame end, curframe = %d, hw=%d, vw=%d, recvd=%d", | ||
3397 | ov->curframe, | ||
3398 | (int)(in[9]), (int)(in[10]), frame->bytes_recvd); | ||
3399 | |||
3400 | // FIXME: Since we don't know the header formats yet, | ||
3401 | // there is no way to know what the actual image size is | ||
3402 | frame->rawwidth = frame->width; | ||
3403 | frame->rawheight = frame->height; | ||
3404 | |||
3405 | /* Validate the header data */ | ||
3406 | RESTRICT_TO_RANGE(frame->rawwidth, ov->minwidth, ov->maxwidth); | ||
3407 | RESTRICT_TO_RANGE(frame->rawheight, ov->minheight, ov->maxheight); | ||
3408 | |||
3409 | /* Don't allow byte count to exceed buffer size */ | ||
3410 | RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw); | ||
3411 | |||
3412 | if (frame->scanstate == STATE_LINES) { | ||
3413 | int nextf; | ||
3414 | |||
3415 | frame->grabstate = FRAME_DONE; | ||
3416 | wake_up_interruptible(&frame->wq); | ||
3417 | |||
3418 | /* If next frame is ready or grabbing, | ||
3419 | * point to it */ | ||
3420 | nextf = (ov->curframe + 1) % OV511_NUMFRAMES; | ||
3421 | if (ov->frame[nextf].grabstate == FRAME_READY | ||
3422 | || ov->frame[nextf].grabstate == FRAME_GRABBING) { | ||
3423 | ov->curframe = nextf; | ||
3424 | ov->frame[nextf].scanstate = STATE_SCANNING; | ||
3425 | frame = &ov->frame[nextf]; | ||
3426 | } else { | ||
3427 | if (frame->grabstate == FRAME_DONE) { | ||
3428 | PDEBUG(4, "** Frame done **"); | ||
3429 | } else { | ||
3430 | PDEBUG(4, "Frame not ready? state = %d", | ||
3431 | ov->frame[nextf].grabstate); | ||
3432 | } | ||
3433 | |||
3434 | ov->curframe = -1; | ||
3435 | PDEBUG(4, "SOF dropped (no active frame)"); | ||
3436 | return; /* Nowhere to store this frame */ | ||
3437 | } | ||
3438 | } | ||
3439 | sof: | ||
3440 | PDEBUG(4, "Starting capture on frame %d", frame->framenum); | ||
3441 | |||
3442 | // Snapshot not reverse-engineered yet. | ||
3443 | #if 0 | ||
3444 | /* Check to see if it's a snapshot frame */ | ||
3445 | /* FIXME?? Should the snapshot reset go here? Performance? */ | ||
3446 | if (in[8] & 0x02) { | ||
3447 | frame->snapshot = 1; | ||
3448 | PDEBUG(3, "snapshot detected"); | ||
3449 | } | ||
3450 | #endif | ||
3451 | frame->scanstate = STATE_LINES; | ||
3452 | frame->bytes_recvd = 0; | ||
3453 | frame->compressed = 1; | ||
3454 | |||
3455 | check_middle: | ||
3456 | /* Are we in a frame? */ | ||
3457 | if (frame->scanstate != STATE_LINES) { | ||
3458 | PDEBUG(4, "scanstate: no SOF yet"); | ||
3459 | return; | ||
3460 | } | ||
3461 | |||
3462 | /* Dump all data exactly as received */ | ||
3463 | if (dumppix == 2) { | ||
3464 | frame->bytes_recvd += n; | ||
3465 | if (frame->bytes_recvd <= max_raw) | ||
3466 | memcpy(frame->rawdata + frame->bytes_recvd - n, in, n); | ||
3467 | else | ||
3468 | PDEBUG(3, "Raw data buffer overrun!! (%d)", | ||
3469 | frame->bytes_recvd - max_raw); | ||
3470 | } else { | ||
3471 | /* All incoming data are divided into 8-byte segments. If the | ||
3472 | * segment contains all zero bytes, it must be skipped. These | ||
3473 | * zero-segments allow the OV518 to mainain a constant data rate | ||
3474 | * regardless of the effectiveness of the compression. Segments | ||
3475 | * are aligned relative to the beginning of each isochronous | ||
3476 | * packet. The first segment in each image is a header (the | ||
3477 | * decompressor skips it later). | ||
3478 | */ | ||
3479 | |||
3480 | int b, read = 0, allzero, copied = 0; | ||
3481 | |||
3482 | while (read < n) { | ||
3483 | allzero = 1; | ||
3484 | for (b = 0; b < 8; b++) { | ||
3485 | if (in[read + b]) { | ||
3486 | allzero = 0; | ||
3487 | break; | ||
3488 | } | ||
3489 | } | ||
3490 | |||
3491 | if (allzero) { | ||
3492 | /* Don't copy it */ | ||
3493 | } else { | ||
3494 | if (frame->bytes_recvd + copied + 8 <= max_raw) | ||
3495 | { | ||
3496 | memcpy(frame->rawdata | ||
3497 | + frame->bytes_recvd + copied, | ||
3498 | in + read, 8); | ||
3499 | copied += 8; | ||
3500 | } else { | ||
3501 | PDEBUG(3, "Raw data buffer overrun!!"); | ||
3502 | } | ||
3503 | } | ||
3504 | read += 8; | ||
3505 | } | ||
3506 | frame->bytes_recvd += copied; | ||
3507 | } | ||
3508 | } | ||
3509 | |||
3510 | static void | ||
3511 | ov51x_isoc_irq(struct urb *urb) | ||
3512 | { | ||
3513 | int i; | ||
3514 | struct usb_ov511 *ov; | ||
3515 | struct ov511_sbuf *sbuf; | ||
3516 | |||
3517 | if (!urb->context) { | ||
3518 | PDEBUG(4, "no context"); | ||
3519 | return; | ||
3520 | } | ||
3521 | |||
3522 | sbuf = urb->context; | ||
3523 | ov = sbuf->ov; | ||
3524 | |||
3525 | if (!ov || !ov->dev || !ov->user) { | ||
3526 | PDEBUG(4, "no device, or not open"); | ||
3527 | return; | ||
3528 | } | ||
3529 | |||
3530 | if (!ov->streaming) { | ||
3531 | PDEBUG(4, "hmmm... not streaming, but got interrupt"); | ||
3532 | return; | ||
3533 | } | ||
3534 | |||
3535 | if (urb->status == -ENOENT || urb->status == -ECONNRESET) { | ||
3536 | PDEBUG(4, "URB unlinked"); | ||
3537 | return; | ||
3538 | } | ||
3539 | |||
3540 | if (urb->status != -EINPROGRESS && urb->status != 0) { | ||
3541 | err("ERROR: urb->status=%d: %s", urb->status, | ||
3542 | symbolic(urb_errlist, urb->status)); | ||
3543 | } | ||
3544 | |||
3545 | /* Copy the data received into our frame buffer */ | ||
3546 | PDEBUG(5, "sbuf[%d]: Moving %d packets", sbuf->n, | ||
3547 | urb->number_of_packets); | ||
3548 | for (i = 0; i < urb->number_of_packets; i++) { | ||
3549 | /* Warning: Don't call *_move_data() if no frame active! */ | ||
3550 | if (ov->curframe >= 0) { | ||
3551 | int n = urb->iso_frame_desc[i].actual_length; | ||
3552 | int st = urb->iso_frame_desc[i].status; | ||
3553 | unsigned char *cdata; | ||
3554 | |||
3555 | urb->iso_frame_desc[i].actual_length = 0; | ||
3556 | urb->iso_frame_desc[i].status = 0; | ||
3557 | |||
3558 | cdata = urb->transfer_buffer | ||
3559 | + urb->iso_frame_desc[i].offset; | ||
3560 | |||
3561 | if (!n) { | ||
3562 | PDEBUG(4, "Zero-length packet"); | ||
3563 | continue; | ||
3564 | } | ||
3565 | |||
3566 | if (st) | ||
3567 | PDEBUG(2, "data error: [%d] len=%d, status=%d", | ||
3568 | i, n, st); | ||
3569 | |||
3570 | if (ov->bclass == BCL_OV511) | ||
3571 | ov511_move_data(ov, cdata, n); | ||
3572 | else if (ov->bclass == BCL_OV518) | ||
3573 | ov518_move_data(ov, cdata, n); | ||
3574 | else | ||
3575 | err("Unknown bridge device (%d)", ov->bridge); | ||
3576 | |||
3577 | } else if (waitqueue_active(&ov->wq)) { | ||
3578 | wake_up_interruptible(&ov->wq); | ||
3579 | } | ||
3580 | } | ||
3581 | |||
3582 | /* Resubmit this URB */ | ||
3583 | urb->dev = ov->dev; | ||
3584 | if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0) | ||
3585 | err("usb_submit_urb() ret %d", i); | ||
3586 | |||
3587 | return; | ||
3588 | } | ||
3589 | |||
3590 | /**************************************************************************** | ||
3591 | * | ||
3592 | * Stream initialization and termination | ||
3593 | * | ||
3594 | ***************************************************************************/ | ||
3595 | |||
3596 | static int | ||
3597 | ov51x_init_isoc(struct usb_ov511 *ov) | ||
3598 | { | ||
3599 | struct urb *urb; | ||
3600 | int fx, err, n, i, size; | ||
3601 | |||
3602 | PDEBUG(3, "*** Initializing capture ***"); | ||
3603 | |||
3604 | ov->curframe = -1; | ||
3605 | |||
3606 | if (ov->bridge == BRG_OV511) { | ||
3607 | if (cams == 1) | ||
3608 | size = 993; | ||
3609 | else if (cams == 2) | ||
3610 | size = 513; | ||
3611 | else if (cams == 3 || cams == 4) | ||
3612 | size = 257; | ||
3613 | else { | ||
3614 | err("\"cams\" parameter too high!"); | ||
3615 | return -1; | ||
3616 | } | ||
3617 | } else if (ov->bridge == BRG_OV511PLUS) { | ||
3618 | if (cams == 1) | ||
3619 | size = 961; | ||
3620 | else if (cams == 2) | ||
3621 | size = 513; | ||
3622 | else if (cams == 3 || cams == 4) | ||
3623 | size = 257; | ||
3624 | else if (cams >= 5 && cams <= 8) | ||
3625 | size = 129; | ||
3626 | else if (cams >= 9 && cams <= 31) | ||
3627 | size = 33; | ||
3628 | else { | ||
3629 | err("\"cams\" parameter too high!"); | ||
3630 | return -1; | ||
3631 | } | ||
3632 | } else if (ov->bclass == BCL_OV518) { | ||
3633 | if (cams == 1) | ||
3634 | size = 896; | ||
3635 | else if (cams == 2) | ||
3636 | size = 512; | ||
3637 | else if (cams == 3 || cams == 4) | ||
3638 | size = 256; | ||
3639 | else if (cams >= 5 && cams <= 8) | ||
3640 | size = 128; | ||
3641 | else { | ||
3642 | err("\"cams\" parameter too high!"); | ||
3643 | return -1; | ||
3644 | } | ||
3645 | } else { | ||
3646 | err("invalid bridge type"); | ||
3647 | return -1; | ||
3648 | } | ||
3649 | |||
3650 | // FIXME: OV518 is hardcoded to 15 FPS (alternate 5) for now | ||
3651 | if (ov->bclass == BCL_OV518) { | ||
3652 | if (packetsize == -1) { | ||
3653 | ov518_set_packet_size(ov, 640); | ||
3654 | } else { | ||
3655 | dev_info(&ov->dev->dev, "Forcing packet size to %d\n", | ||
3656 | packetsize); | ||
3657 | ov518_set_packet_size(ov, packetsize); | ||
3658 | } | ||
3659 | } else { | ||
3660 | if (packetsize == -1) { | ||
3661 | ov511_set_packet_size(ov, size); | ||
3662 | } else { | ||
3663 | dev_info(&ov->dev->dev, "Forcing packet size to %d\n", | ||
3664 | packetsize); | ||
3665 | ov511_set_packet_size(ov, packetsize); | ||
3666 | } | ||
3667 | } | ||
3668 | |||
3669 | for (n = 0; n < OV511_NUMSBUF; n++) { | ||
3670 | urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); | ||
3671 | if (!urb) { | ||
3672 | err("init isoc: usb_alloc_urb ret. NULL"); | ||
3673 | for (i = 0; i < n; i++) | ||
3674 | usb_free_urb(ov->sbuf[i].urb); | ||
3675 | return -ENOMEM; | ||
3676 | } | ||
3677 | ov->sbuf[n].urb = urb; | ||
3678 | urb->dev = ov->dev; | ||
3679 | urb->context = &ov->sbuf[n]; | ||
3680 | urb->pipe = usb_rcvisocpipe(ov->dev, OV511_ENDPOINT_ADDRESS); | ||
3681 | urb->transfer_flags = URB_ISO_ASAP; | ||
3682 | urb->transfer_buffer = ov->sbuf[n].data; | ||
3683 | urb->complete = ov51x_isoc_irq; | ||
3684 | urb->number_of_packets = FRAMES_PER_DESC; | ||
3685 | urb->transfer_buffer_length = ov->packet_size * FRAMES_PER_DESC; | ||
3686 | urb->interval = 1; | ||
3687 | for (fx = 0; fx < FRAMES_PER_DESC; fx++) { | ||
3688 | urb->iso_frame_desc[fx].offset = ov->packet_size * fx; | ||
3689 | urb->iso_frame_desc[fx].length = ov->packet_size; | ||
3690 | } | ||
3691 | } | ||
3692 | |||
3693 | ov->streaming = 1; | ||
3694 | |||
3695 | for (n = 0; n < OV511_NUMSBUF; n++) { | ||
3696 | ov->sbuf[n].urb->dev = ov->dev; | ||
3697 | err = usb_submit_urb(ov->sbuf[n].urb, GFP_KERNEL); | ||
3698 | if (err) { | ||
3699 | err("init isoc: usb_submit_urb(%d) ret %d", n, err); | ||
3700 | return err; | ||
3701 | } | ||
3702 | } | ||
3703 | |||
3704 | return 0; | ||
3705 | } | ||
3706 | |||
3707 | static void | ||
3708 | ov51x_unlink_isoc(struct usb_ov511 *ov) | ||
3709 | { | ||
3710 | int n; | ||
3711 | |||
3712 | /* Unschedule all of the iso td's */ | ||
3713 | for (n = OV511_NUMSBUF - 1; n >= 0; n--) { | ||
3714 | if (ov->sbuf[n].urb) { | ||
3715 | usb_kill_urb(ov->sbuf[n].urb); | ||
3716 | usb_free_urb(ov->sbuf[n].urb); | ||
3717 | ov->sbuf[n].urb = NULL; | ||
3718 | } | ||
3719 | } | ||
3720 | } | ||
3721 | |||
3722 | static void | ||
3723 | ov51x_stop_isoc(struct usb_ov511 *ov) | ||
3724 | { | ||
3725 | if (!ov->streaming || !ov->dev) | ||
3726 | return; | ||
3727 | |||
3728 | PDEBUG(3, "*** Stopping capture ***"); | ||
3729 | |||
3730 | if (ov->bclass == BCL_OV518) | ||
3731 | ov518_set_packet_size(ov, 0); | ||
3732 | else | ||
3733 | ov511_set_packet_size(ov, 0); | ||
3734 | |||
3735 | ov->streaming = 0; | ||
3736 | |||
3737 | ov51x_unlink_isoc(ov); | ||
3738 | } | ||
3739 | |||
3740 | static int | ||
3741 | ov51x_new_frame(struct usb_ov511 *ov, int framenum) | ||
3742 | { | ||
3743 | struct ov511_frame *frame; | ||
3744 | int newnum; | ||
3745 | |||
3746 | PDEBUG(4, "ov->curframe = %d, framenum = %d", ov->curframe, framenum); | ||
3747 | |||
3748 | if (!ov->dev) | ||
3749 | return -1; | ||
3750 | |||
3751 | /* If we're not grabbing a frame right now and the other frame is */ | ||
3752 | /* ready to be grabbed into, then use it instead */ | ||
3753 | if (ov->curframe == -1) { | ||
3754 | newnum = (framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES; | ||
3755 | if (ov->frame[newnum].grabstate == FRAME_READY) | ||
3756 | framenum = newnum; | ||
3757 | } else | ||
3758 | return 0; | ||
3759 | |||
3760 | frame = &ov->frame[framenum]; | ||
3761 | |||
3762 | PDEBUG(4, "framenum = %d, width = %d, height = %d", framenum, | ||
3763 | frame->width, frame->height); | ||
3764 | |||
3765 | frame->grabstate = FRAME_GRABBING; | ||
3766 | frame->scanstate = STATE_SCANNING; | ||
3767 | frame->snapshot = 0; | ||
3768 | |||
3769 | ov->curframe = framenum; | ||
3770 | |||
3771 | /* Make sure it's not too big */ | ||
3772 | if (frame->width > ov->maxwidth) | ||
3773 | frame->width = ov->maxwidth; | ||
3774 | |||
3775 | frame->width &= ~7L; /* Multiple of 8 */ | ||
3776 | |||
3777 | if (frame->height > ov->maxheight) | ||
3778 | frame->height = ov->maxheight; | ||
3779 | |||
3780 | frame->height &= ~3L; /* Multiple of 4 */ | ||
3781 | |||
3782 | return 0; | ||
3783 | } | ||
3784 | |||
3785 | /**************************************************************************** | ||
3786 | * | ||
3787 | * Buffer management | ||
3788 | * | ||
3789 | ***************************************************************************/ | ||
3790 | |||
3791 | /* | ||
3792 | * - You must acquire buf_lock before entering this function. | ||
3793 | * - Because this code will free any non-null pointer, you must be sure to null | ||
3794 | * them if you explicitly free them somewhere else! | ||
3795 | */ | ||
3796 | static void | ||
3797 | ov51x_do_dealloc(struct usb_ov511 *ov) | ||
3798 | { | ||
3799 | int i; | ||
3800 | PDEBUG(4, "entered"); | ||
3801 | |||
3802 | if (ov->fbuf) { | ||
3803 | rvfree(ov->fbuf, OV511_NUMFRAMES | ||
3804 | * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight)); | ||
3805 | ov->fbuf = NULL; | ||
3806 | } | ||
3807 | |||
3808 | vfree(ov->rawfbuf); | ||
3809 | ov->rawfbuf = NULL; | ||
3810 | |||
3811 | vfree(ov->tempfbuf); | ||
3812 | ov->tempfbuf = NULL; | ||
3813 | |||
3814 | for (i = 0; i < OV511_NUMSBUF; i++) { | ||
3815 | kfree(ov->sbuf[i].data); | ||
3816 | ov->sbuf[i].data = NULL; | ||
3817 | } | ||
3818 | |||
3819 | for (i = 0; i < OV511_NUMFRAMES; i++) { | ||
3820 | ov->frame[i].data = NULL; | ||
3821 | ov->frame[i].rawdata = NULL; | ||
3822 | ov->frame[i].tempdata = NULL; | ||
3823 | if (ov->frame[i].compbuf) { | ||
3824 | free_page((unsigned long) ov->frame[i].compbuf); | ||
3825 | ov->frame[i].compbuf = NULL; | ||
3826 | } | ||
3827 | } | ||
3828 | |||
3829 | PDEBUG(4, "buffer memory deallocated"); | ||
3830 | ov->buf_state = BUF_NOT_ALLOCATED; | ||
3831 | PDEBUG(4, "leaving"); | ||
3832 | } | ||
3833 | |||
3834 | static int | ||
3835 | ov51x_alloc(struct usb_ov511 *ov) | ||
3836 | { | ||
3837 | int i; | ||
3838 | const int w = ov->maxwidth; | ||
3839 | const int h = ov->maxheight; | ||
3840 | const int data_bufsize = OV511_NUMFRAMES * MAX_DATA_SIZE(w, h); | ||
3841 | const int raw_bufsize = OV511_NUMFRAMES * MAX_RAW_DATA_SIZE(w, h); | ||
3842 | |||
3843 | PDEBUG(4, "entered"); | ||
3844 | mutex_lock(&ov->buf_lock); | ||
3845 | |||
3846 | if (ov->buf_state == BUF_ALLOCATED) | ||
3847 | goto out; | ||
3848 | |||
3849 | ov->fbuf = rvmalloc(data_bufsize); | ||
3850 | if (!ov->fbuf) | ||
3851 | goto error; | ||
3852 | |||
3853 | ov->rawfbuf = vmalloc(raw_bufsize); | ||
3854 | if (!ov->rawfbuf) | ||
3855 | goto error; | ||
3856 | |||
3857 | memset(ov->rawfbuf, 0, raw_bufsize); | ||
3858 | |||
3859 | ov->tempfbuf = vmalloc(raw_bufsize); | ||
3860 | if (!ov->tempfbuf) | ||
3861 | goto error; | ||
3862 | |||
3863 | memset(ov->tempfbuf, 0, raw_bufsize); | ||
3864 | |||
3865 | for (i = 0; i < OV511_NUMSBUF; i++) { | ||
3866 | ov->sbuf[i].data = kmalloc(FRAMES_PER_DESC * | ||
3867 | MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL); | ||
3868 | if (!ov->sbuf[i].data) | ||
3869 | goto error; | ||
3870 | |||
3871 | PDEBUG(4, "sbuf[%d] @ %p", i, ov->sbuf[i].data); | ||
3872 | } | ||
3873 | |||
3874 | for (i = 0; i < OV511_NUMFRAMES; i++) { | ||
3875 | ov->frame[i].data = ov->fbuf + i * MAX_DATA_SIZE(w, h); | ||
3876 | ov->frame[i].rawdata = ov->rawfbuf | ||
3877 | + i * MAX_RAW_DATA_SIZE(w, h); | ||
3878 | ov->frame[i].tempdata = ov->tempfbuf | ||
3879 | + i * MAX_RAW_DATA_SIZE(w, h); | ||
3880 | |||
3881 | ov->frame[i].compbuf = | ||
3882 | (unsigned char *) __get_free_page(GFP_KERNEL); | ||
3883 | if (!ov->frame[i].compbuf) | ||
3884 | goto error; | ||
3885 | |||
3886 | PDEBUG(4, "frame[%d] @ %p", i, ov->frame[i].data); | ||
3887 | } | ||
3888 | |||
3889 | ov->buf_state = BUF_ALLOCATED; | ||
3890 | out: | ||
3891 | mutex_unlock(&ov->buf_lock); | ||
3892 | PDEBUG(4, "leaving"); | ||
3893 | return 0; | ||
3894 | error: | ||
3895 | ov51x_do_dealloc(ov); | ||
3896 | mutex_unlock(&ov->buf_lock); | ||
3897 | PDEBUG(4, "errored"); | ||
3898 | return -ENOMEM; | ||
3899 | } | ||
3900 | |||
3901 | static void | ||
3902 | ov51x_dealloc(struct usb_ov511 *ov) | ||
3903 | { | ||
3904 | PDEBUG(4, "entered"); | ||
3905 | mutex_lock(&ov->buf_lock); | ||
3906 | ov51x_do_dealloc(ov); | ||
3907 | mutex_unlock(&ov->buf_lock); | ||
3908 | PDEBUG(4, "leaving"); | ||
3909 | } | ||
3910 | |||
3911 | /**************************************************************************** | ||
3912 | * | ||
3913 | * V4L 1 API | ||
3914 | * | ||
3915 | ***************************************************************************/ | ||
3916 | |||
3917 | static int | ||
3918 | ov51x_v4l1_open(struct file *file) | ||
3919 | { | ||
3920 | struct video_device *vdev = video_devdata(file); | ||
3921 | struct usb_ov511 *ov = video_get_drvdata(vdev); | ||
3922 | int err, i; | ||
3923 | |||
3924 | PDEBUG(4, "opening"); | ||
3925 | |||
3926 | mutex_lock(&ov->lock); | ||
3927 | |||
3928 | err = -EBUSY; | ||
3929 | if (ov->user) | ||
3930 | goto out; | ||
3931 | |||
3932 | ov->sub_flag = 0; | ||
3933 | |||
3934 | /* In case app doesn't set them... */ | ||
3935 | err = ov51x_set_default_params(ov); | ||
3936 | if (err < 0) | ||
3937 | goto out; | ||
3938 | |||
3939 | /* Make sure frames are reset */ | ||
3940 | for (i = 0; i < OV511_NUMFRAMES; i++) { | ||
3941 | ov->frame[i].grabstate = FRAME_UNUSED; | ||
3942 | ov->frame[i].bytes_read = 0; | ||
3943 | } | ||
3944 | |||
3945 | /* If compression is on, make sure now that a | ||
3946 | * decompressor can be loaded */ | ||
3947 | if (ov->compress && !ov->decomp_ops) { | ||
3948 | err = request_decompressor(ov); | ||
3949 | if (err && !dumppix) | ||
3950 | goto out; | ||
3951 | } | ||
3952 | |||
3953 | err = ov51x_alloc(ov); | ||
3954 | if (err < 0) | ||
3955 | goto out; | ||
3956 | |||
3957 | err = ov51x_init_isoc(ov); | ||
3958 | if (err) { | ||
3959 | ov51x_dealloc(ov); | ||
3960 | goto out; | ||
3961 | } | ||
3962 | |||
3963 | ov->user++; | ||
3964 | file->private_data = vdev; | ||
3965 | |||
3966 | if (ov->led_policy == LED_AUTO) | ||
3967 | ov51x_led_control(ov, 1); | ||
3968 | |||
3969 | out: | ||
3970 | mutex_unlock(&ov->lock); | ||
3971 | return err; | ||
3972 | } | ||
3973 | |||
3974 | static int | ||
3975 | ov51x_v4l1_close(struct file *file) | ||
3976 | { | ||
3977 | struct video_device *vdev = file->private_data; | ||
3978 | struct usb_ov511 *ov = video_get_drvdata(vdev); | ||
3979 | |||
3980 | PDEBUG(4, "ov511_close"); | ||
3981 | |||
3982 | mutex_lock(&ov->lock); | ||
3983 | |||
3984 | ov->user--; | ||
3985 | ov51x_stop_isoc(ov); | ||
3986 | |||
3987 | if (ov->led_policy == LED_AUTO) | ||
3988 | ov51x_led_control(ov, 0); | ||
3989 | |||
3990 | if (ov->dev) | ||
3991 | ov51x_dealloc(ov); | ||
3992 | |||
3993 | mutex_unlock(&ov->lock); | ||
3994 | |||
3995 | /* Device unplugged while open. Only a minimum of unregistration is done | ||
3996 | * here; the disconnect callback already did the rest. */ | ||
3997 | if (!ov->dev) { | ||
3998 | mutex_lock(&ov->cbuf_lock); | ||
3999 | kfree(ov->cbuf); | ||
4000 | ov->cbuf = NULL; | ||
4001 | mutex_unlock(&ov->cbuf_lock); | ||
4002 | |||
4003 | ov51x_dealloc(ov); | ||
4004 | kfree(ov); | ||
4005 | ov = NULL; | ||
4006 | } | ||
4007 | |||
4008 | file->private_data = NULL; | ||
4009 | return 0; | ||
4010 | } | ||
4011 | |||
4012 | /* Do not call this function directly! */ | ||
4013 | static long | ||
4014 | ov51x_v4l1_ioctl_internal(struct file *file, unsigned int cmd, void *arg) | ||
4015 | { | ||
4016 | struct video_device *vdev = file->private_data; | ||
4017 | struct usb_ov511 *ov = video_get_drvdata(vdev); | ||
4018 | PDEBUG(5, "IOCtl: 0x%X", cmd); | ||
4019 | |||
4020 | if (!ov->dev) | ||
4021 | return -EIO; | ||
4022 | |||
4023 | switch (cmd) { | ||
4024 | case VIDIOCGCAP: | ||
4025 | { | ||
4026 | struct video_capability *b = arg; | ||
4027 | |||
4028 | PDEBUG(4, "VIDIOCGCAP"); | ||
4029 | |||
4030 | memset(b, 0, sizeof(struct video_capability)); | ||
4031 | sprintf(b->name, "%s USB Camera", | ||
4032 | symbolic(brglist, ov->bridge)); | ||
4033 | b->type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE; | ||
4034 | b->channels = ov->num_inputs; | ||
4035 | b->audios = 0; | ||
4036 | b->maxwidth = ov->maxwidth; | ||
4037 | b->maxheight = ov->maxheight; | ||
4038 | b->minwidth = ov->minwidth; | ||
4039 | b->minheight = ov->minheight; | ||
4040 | |||
4041 | return 0; | ||
4042 | } | ||
4043 | case VIDIOCGCHAN: | ||
4044 | { | ||
4045 | struct video_channel *v = arg; | ||
4046 | |||
4047 | PDEBUG(4, "VIDIOCGCHAN"); | ||
4048 | |||
4049 | if ((unsigned)(v->channel) >= ov->num_inputs) { | ||
4050 | err("Invalid channel (%d)", v->channel); | ||
4051 | return -EINVAL; | ||
4052 | } | ||
4053 | |||
4054 | v->norm = ov->norm; | ||
4055 | v->type = VIDEO_TYPE_CAMERA; | ||
4056 | v->flags = 0; | ||
4057 | // v->flags |= (ov->has_decoder) ? VIDEO_VC_NORM : 0; | ||
4058 | v->tuners = 0; | ||
4059 | decoder_get_input_name(ov, v->channel, v->name); | ||
4060 | |||
4061 | return 0; | ||
4062 | } | ||
4063 | case VIDIOCSCHAN: | ||
4064 | { | ||
4065 | struct video_channel *v = arg; | ||
4066 | int err; | ||
4067 | |||
4068 | PDEBUG(4, "VIDIOCSCHAN"); | ||
4069 | |||
4070 | /* Make sure it's not a camera */ | ||
4071 | if (!ov->has_decoder) { | ||
4072 | if (v->channel == 0) | ||
4073 | return 0; | ||
4074 | else | ||
4075 | return -EINVAL; | ||
4076 | } | ||
4077 | |||
4078 | if (v->norm != VIDEO_MODE_PAL && | ||
4079 | v->norm != VIDEO_MODE_NTSC && | ||
4080 | v->norm != VIDEO_MODE_SECAM && | ||
4081 | v->norm != VIDEO_MODE_AUTO) { | ||
4082 | err("Invalid norm (%d)", v->norm); | ||
4083 | return -EINVAL; | ||
4084 | } | ||
4085 | |||
4086 | if ((unsigned)(v->channel) >= ov->num_inputs) { | ||
4087 | err("Invalid channel (%d)", v->channel); | ||
4088 | return -EINVAL; | ||
4089 | } | ||
4090 | |||
4091 | err = decoder_set_input(ov, v->channel); | ||
4092 | if (err) | ||
4093 | return err; | ||
4094 | |||
4095 | err = decoder_set_norm(ov, v->norm); | ||
4096 | if (err) | ||
4097 | return err; | ||
4098 | |||
4099 | return 0; | ||
4100 | } | ||
4101 | case VIDIOCGPICT: | ||
4102 | { | ||
4103 | struct video_picture *p = arg; | ||
4104 | |||
4105 | PDEBUG(4, "VIDIOCGPICT"); | ||
4106 | |||
4107 | memset(p, 0, sizeof(struct video_picture)); | ||
4108 | if (sensor_get_picture(ov, p)) | ||
4109 | return -EIO; | ||
4110 | |||
4111 | /* Can we get these from frame[0]? -claudio? */ | ||
4112 | p->depth = ov->frame[0].depth; | ||
4113 | p->palette = ov->frame[0].format; | ||
4114 | |||
4115 | return 0; | ||
4116 | } | ||
4117 | case VIDIOCSPICT: | ||
4118 | { | ||
4119 | struct video_picture *p = arg; | ||
4120 | int i, rc; | ||
4121 | |||
4122 | PDEBUG(4, "VIDIOCSPICT"); | ||
4123 | |||
4124 | if (!get_depth(p->palette)) | ||
4125 | return -EINVAL; | ||
4126 | |||
4127 | if (sensor_set_picture(ov, p)) | ||
4128 | return -EIO; | ||
4129 | |||
4130 | if (force_palette && p->palette != force_palette) { | ||
4131 | dev_info(&ov->dev->dev, "Palette rejected (%s)\n", | ||
4132 | symbolic(v4l1_plist, p->palette)); | ||
4133 | return -EINVAL; | ||
4134 | } | ||
4135 | |||
4136 | // FIXME: Format should be independent of frames | ||
4137 | if (p->palette != ov->frame[0].format) { | ||
4138 | PDEBUG(4, "Detected format change"); | ||
4139 | |||
4140 | rc = ov51x_wait_frames_inactive(ov); | ||
4141 | if (rc) | ||
4142 | return rc; | ||
4143 | |||
4144 | mode_init_regs(ov, ov->frame[0].width, | ||
4145 | ov->frame[0].height, p->palette, ov->sub_flag); | ||
4146 | } | ||
4147 | |||
4148 | PDEBUG(4, "Setting depth=%d, palette=%s", | ||
4149 | p->depth, symbolic(v4l1_plist, p->palette)); | ||
4150 | |||
4151 | for (i = 0; i < OV511_NUMFRAMES; i++) { | ||
4152 | ov->frame[i].depth = p->depth; | ||
4153 | ov->frame[i].format = p->palette; | ||
4154 | } | ||
4155 | |||
4156 | return 0; | ||
4157 | } | ||
4158 | case VIDIOCGCAPTURE: | ||
4159 | { | ||
4160 | int *vf = arg; | ||
4161 | |||
4162 | PDEBUG(4, "VIDIOCGCAPTURE"); | ||
4163 | |||
4164 | ov->sub_flag = *vf; | ||
4165 | return 0; | ||
4166 | } | ||
4167 | case VIDIOCSCAPTURE: | ||
4168 | { | ||
4169 | struct video_capture *vc = arg; | ||
4170 | |||
4171 | PDEBUG(4, "VIDIOCSCAPTURE"); | ||
4172 | |||
4173 | if (vc->flags) | ||
4174 | return -EINVAL; | ||
4175 | if (vc->decimation) | ||
4176 | return -EINVAL; | ||
4177 | |||
4178 | vc->x &= ~3L; | ||
4179 | vc->y &= ~1L; | ||
4180 | vc->y &= ~31L; | ||
4181 | |||
4182 | if (vc->width == 0) | ||
4183 | vc->width = 32; | ||
4184 | |||
4185 | vc->height /= 16; | ||
4186 | vc->height *= 16; | ||
4187 | if (vc->height == 0) | ||
4188 | vc->height = 16; | ||
4189 | |||
4190 | ov->subx = vc->x; | ||
4191 | ov->suby = vc->y; | ||
4192 | ov->subw = vc->width; | ||
4193 | ov->subh = vc->height; | ||
4194 | |||
4195 | return 0; | ||
4196 | } | ||
4197 | case VIDIOCSWIN: | ||
4198 | { | ||
4199 | struct video_window *vw = arg; | ||
4200 | int i, rc; | ||
4201 | |||
4202 | PDEBUG(4, "VIDIOCSWIN: %dx%d", vw->width, vw->height); | ||
4203 | |||
4204 | #if 0 | ||
4205 | if (vw->flags) | ||
4206 | return -EINVAL; | ||
4207 | if (vw->clipcount) | ||
4208 | return -EINVAL; | ||
4209 | if (vw->height != ov->maxheight) | ||
4210 | return -EINVAL; | ||
4211 | if (vw->width != ov->maxwidth) | ||
4212 | return -EINVAL; | ||
4213 | #endif | ||
4214 | |||
4215 | rc = ov51x_wait_frames_inactive(ov); | ||
4216 | if (rc) | ||
4217 | return rc; | ||
4218 | |||
4219 | rc = mode_init_regs(ov, vw->width, vw->height, | ||
4220 | ov->frame[0].format, ov->sub_flag); | ||
4221 | if (rc < 0) | ||
4222 | return rc; | ||
4223 | |||
4224 | for (i = 0; i < OV511_NUMFRAMES; i++) { | ||
4225 | ov->frame[i].width = vw->width; | ||
4226 | ov->frame[i].height = vw->height; | ||
4227 | } | ||
4228 | |||
4229 | return 0; | ||
4230 | } | ||
4231 | case VIDIOCGWIN: | ||
4232 | { | ||
4233 | struct video_window *vw = arg; | ||
4234 | |||
4235 | memset(vw, 0, sizeof(struct video_window)); | ||
4236 | vw->x = 0; /* FIXME */ | ||
4237 | vw->y = 0; | ||
4238 | vw->width = ov->frame[0].width; | ||
4239 | vw->height = ov->frame[0].height; | ||
4240 | vw->flags = 30; | ||
4241 | |||
4242 | PDEBUG(4, "VIDIOCGWIN: %dx%d", vw->width, vw->height); | ||
4243 | |||
4244 | return 0; | ||
4245 | } | ||
4246 | case VIDIOCGMBUF: | ||
4247 | { | ||
4248 | struct video_mbuf *vm = arg; | ||
4249 | int i; | ||
4250 | |||
4251 | PDEBUG(4, "VIDIOCGMBUF"); | ||
4252 | |||
4253 | memset(vm, 0, sizeof(struct video_mbuf)); | ||
4254 | vm->size = OV511_NUMFRAMES | ||
4255 | * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight); | ||
4256 | vm->frames = OV511_NUMFRAMES; | ||
4257 | |||
4258 | vm->offsets[0] = 0; | ||
4259 | for (i = 1; i < OV511_NUMFRAMES; i++) { | ||
4260 | vm->offsets[i] = vm->offsets[i-1] | ||
4261 | + MAX_DATA_SIZE(ov->maxwidth, ov->maxheight); | ||
4262 | } | ||
4263 | |||
4264 | return 0; | ||
4265 | } | ||
4266 | case VIDIOCMCAPTURE: | ||
4267 | { | ||
4268 | struct video_mmap *vm = arg; | ||
4269 | int rc, depth; | ||
4270 | unsigned int f = vm->frame; | ||
4271 | |||
4272 | PDEBUG(4, "VIDIOCMCAPTURE: frame: %d, %dx%d, %s", f, vm->width, | ||
4273 | vm->height, symbolic(v4l1_plist, vm->format)); | ||
4274 | |||
4275 | depth = get_depth(vm->format); | ||
4276 | if (!depth) { | ||
4277 | PDEBUG(2, "VIDIOCMCAPTURE: invalid format (%s)", | ||
4278 | symbolic(v4l1_plist, vm->format)); | ||
4279 | return -EINVAL; | ||
4280 | } | ||
4281 | |||
4282 | if (f >= OV511_NUMFRAMES) { | ||
4283 | err("VIDIOCMCAPTURE: invalid frame (%d)", f); | ||
4284 | return -EINVAL; | ||
4285 | } | ||
4286 | |||
4287 | if (vm->width > ov->maxwidth | ||
4288 | || vm->height > ov->maxheight) { | ||
4289 | err("VIDIOCMCAPTURE: requested dimensions too big"); | ||
4290 | return -EINVAL; | ||
4291 | } | ||
4292 | |||
4293 | if (ov->frame[f].grabstate == FRAME_GRABBING) { | ||
4294 | PDEBUG(4, "VIDIOCMCAPTURE: already grabbing"); | ||
4295 | return -EBUSY; | ||
4296 | } | ||
4297 | |||
4298 | if (force_palette && (vm->format != force_palette)) { | ||
4299 | PDEBUG(2, "palette rejected (%s)", | ||
4300 | symbolic(v4l1_plist, vm->format)); | ||
4301 | return -EINVAL; | ||
4302 | } | ||
4303 | |||
4304 | if ((ov->frame[f].width != vm->width) || | ||
4305 | (ov->frame[f].height != vm->height) || | ||
4306 | (ov->frame[f].format != vm->format) || | ||
4307 | (ov->frame[f].sub_flag != ov->sub_flag) || | ||
4308 | (ov->frame[f].depth != depth)) { | ||
4309 | PDEBUG(4, "VIDIOCMCAPTURE: change in image parameters"); | ||
4310 | |||
4311 | rc = ov51x_wait_frames_inactive(ov); | ||
4312 | if (rc) | ||
4313 | return rc; | ||
4314 | |||
4315 | rc = mode_init_regs(ov, vm->width, vm->height, | ||
4316 | vm->format, ov->sub_flag); | ||
4317 | #if 0 | ||
4318 | if (rc < 0) { | ||
4319 | PDEBUG(1, "Got error while initializing regs "); | ||
4320 | return ret; | ||
4321 | } | ||
4322 | #endif | ||
4323 | ov->frame[f].width = vm->width; | ||
4324 | ov->frame[f].height = vm->height; | ||
4325 | ov->frame[f].format = vm->format; | ||
4326 | ov->frame[f].sub_flag = ov->sub_flag; | ||
4327 | ov->frame[f].depth = depth; | ||
4328 | } | ||
4329 | |||
4330 | /* Mark it as ready */ | ||
4331 | ov->frame[f].grabstate = FRAME_READY; | ||
4332 | |||
4333 | PDEBUG(4, "VIDIOCMCAPTURE: renewing frame %d", f); | ||
4334 | |||
4335 | return ov51x_new_frame(ov, f); | ||
4336 | } | ||
4337 | case VIDIOCSYNC: | ||
4338 | { | ||
4339 | unsigned int fnum = *((unsigned int *) arg); | ||
4340 | struct ov511_frame *frame; | ||
4341 | int rc; | ||
4342 | |||
4343 | if (fnum >= OV511_NUMFRAMES) { | ||
4344 | err("VIDIOCSYNC: invalid frame (%d)", fnum); | ||
4345 | return -EINVAL; | ||
4346 | } | ||
4347 | |||
4348 | frame = &ov->frame[fnum]; | ||
4349 | |||
4350 | PDEBUG(4, "syncing to frame %d, grabstate = %d", fnum, | ||
4351 | frame->grabstate); | ||
4352 | |||
4353 | switch (frame->grabstate) { | ||
4354 | case FRAME_UNUSED: | ||
4355 | return -EINVAL; | ||
4356 | case FRAME_READY: | ||
4357 | case FRAME_GRABBING: | ||
4358 | case FRAME_ERROR: | ||
4359 | redo: | ||
4360 | if (!ov->dev) | ||
4361 | return -EIO; | ||
4362 | |||
4363 | rc = wait_event_interruptible(frame->wq, | ||
4364 | (frame->grabstate == FRAME_DONE) | ||
4365 | || (frame->grabstate == FRAME_ERROR)); | ||
4366 | |||
4367 | if (rc) | ||
4368 | return rc; | ||
4369 | |||
4370 | if (frame->grabstate == FRAME_ERROR) { | ||
4371 | if ((rc = ov51x_new_frame(ov, fnum)) < 0) | ||
4372 | return rc; | ||
4373 | goto redo; | ||
4374 | } | ||
4375 | /* Fall through */ | ||
4376 | case FRAME_DONE: | ||
4377 | if (ov->snap_enabled && !frame->snapshot) { | ||
4378 | if ((rc = ov51x_new_frame(ov, fnum)) < 0) | ||
4379 | return rc; | ||
4380 | goto redo; | ||
4381 | } | ||
4382 | |||
4383 | frame->grabstate = FRAME_UNUSED; | ||
4384 | |||
4385 | /* Reset the hardware snapshot button */ | ||
4386 | /* FIXME - Is this the best place for this? */ | ||
4387 | if ((ov->snap_enabled) && (frame->snapshot)) { | ||
4388 | frame->snapshot = 0; | ||
4389 | ov51x_clear_snapshot(ov); | ||
4390 | } | ||
4391 | |||
4392 | /* Decompression, format conversion, etc... */ | ||
4393 | ov51x_postprocess(ov, frame); | ||
4394 | |||
4395 | break; | ||
4396 | } /* end switch */ | ||
4397 | |||
4398 | return 0; | ||
4399 | } | ||
4400 | case VIDIOCGFBUF: | ||
4401 | { | ||
4402 | struct video_buffer *vb = arg; | ||
4403 | |||
4404 | PDEBUG(4, "VIDIOCGFBUF"); | ||
4405 | |||
4406 | memset(vb, 0, sizeof(struct video_buffer)); | ||
4407 | |||
4408 | return 0; | ||
4409 | } | ||
4410 | case VIDIOCGUNIT: | ||
4411 | { | ||
4412 | struct video_unit *vu = arg; | ||
4413 | |||
4414 | PDEBUG(4, "VIDIOCGUNIT"); | ||
4415 | |||
4416 | memset(vu, 0, sizeof(struct video_unit)); | ||
4417 | |||
4418 | vu->video = ov->vdev->minor; | ||
4419 | vu->vbi = VIDEO_NO_UNIT; | ||
4420 | vu->radio = VIDEO_NO_UNIT; | ||
4421 | vu->audio = VIDEO_NO_UNIT; | ||
4422 | vu->teletext = VIDEO_NO_UNIT; | ||
4423 | |||
4424 | return 0; | ||
4425 | } | ||
4426 | case OV511IOC_WI2C: | ||
4427 | { | ||
4428 | struct ov511_i2c_struct *w = arg; | ||
4429 | |||
4430 | return i2c_w_slave(ov, w->slave, w->reg, w->value, w->mask); | ||
4431 | } | ||
4432 | case OV511IOC_RI2C: | ||
4433 | { | ||
4434 | struct ov511_i2c_struct *r = arg; | ||
4435 | int rc; | ||
4436 | |||
4437 | rc = i2c_r_slave(ov, r->slave, r->reg); | ||
4438 | if (rc < 0) | ||
4439 | return rc; | ||
4440 | |||
4441 | r->value = rc; | ||
4442 | return 0; | ||
4443 | } | ||
4444 | default: | ||
4445 | PDEBUG(3, "Unsupported IOCtl: 0x%X", cmd); | ||
4446 | return -ENOIOCTLCMD; | ||
4447 | } /* end switch */ | ||
4448 | |||
4449 | return 0; | ||
4450 | } | ||
4451 | |||
4452 | static long | ||
4453 | ov51x_v4l1_ioctl(struct file *file, | ||
4454 | unsigned int cmd, unsigned long arg) | ||
4455 | { | ||
4456 | struct video_device *vdev = file->private_data; | ||
4457 | struct usb_ov511 *ov = video_get_drvdata(vdev); | ||
4458 | int rc; | ||
4459 | |||
4460 | if (mutex_lock_interruptible(&ov->lock)) | ||
4461 | return -EINTR; | ||
4462 | |||
4463 | rc = video_usercopy(file, cmd, arg, ov51x_v4l1_ioctl_internal); | ||
4464 | |||
4465 | mutex_unlock(&ov->lock); | ||
4466 | return rc; | ||
4467 | } | ||
4468 | |||
4469 | static ssize_t | ||
4470 | ov51x_v4l1_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos) | ||
4471 | { | ||
4472 | struct video_device *vdev = file->private_data; | ||
4473 | int noblock = file->f_flags&O_NONBLOCK; | ||
4474 | unsigned long count = cnt; | ||
4475 | struct usb_ov511 *ov = video_get_drvdata(vdev); | ||
4476 | int i, rc = 0, frmx = -1; | ||
4477 | struct ov511_frame *frame; | ||
4478 | |||
4479 | if (mutex_lock_interruptible(&ov->lock)) | ||
4480 | return -EINTR; | ||
4481 | |||
4482 | PDEBUG(4, "%ld bytes, noblock=%d", count, noblock); | ||
4483 | |||
4484 | if (!vdev || !buf) { | ||
4485 | rc = -EFAULT; | ||
4486 | goto error; | ||
4487 | } | ||
4488 | |||
4489 | if (!ov->dev) { | ||
4490 | rc = -EIO; | ||
4491 | goto error; | ||
4492 | } | ||
4493 | |||
4494 | // FIXME: Only supports two frames | ||
4495 | /* See if a frame is completed, then use it. */ | ||
4496 | if (ov->frame[0].grabstate >= FRAME_DONE) /* _DONE or _ERROR */ | ||
4497 | frmx = 0; | ||
4498 | else if (ov->frame[1].grabstate >= FRAME_DONE)/* _DONE or _ERROR */ | ||
4499 | frmx = 1; | ||
4500 | |||
4501 | /* If nonblocking we return immediately */ | ||
4502 | if (noblock && (frmx == -1)) { | ||
4503 | rc = -EAGAIN; | ||
4504 | goto error; | ||
4505 | } | ||
4506 | |||
4507 | /* If no FRAME_DONE, look for a FRAME_GRABBING state. */ | ||
4508 | /* See if a frame is in process (grabbing), then use it. */ | ||
4509 | if (frmx == -1) { | ||
4510 | if (ov->frame[0].grabstate == FRAME_GRABBING) | ||
4511 | frmx = 0; | ||
4512 | else if (ov->frame[1].grabstate == FRAME_GRABBING) | ||
4513 | frmx = 1; | ||
4514 | } | ||
4515 | |||
4516 | /* If no frame is active, start one. */ | ||
4517 | if (frmx == -1) { | ||
4518 | if ((rc = ov51x_new_frame(ov, frmx = 0))) { | ||
4519 | err("read: ov51x_new_frame error"); | ||
4520 | goto error; | ||
4521 | } | ||
4522 | } | ||
4523 | |||
4524 | frame = &ov->frame[frmx]; | ||
4525 | |||
4526 | restart: | ||
4527 | if (!ov->dev) { | ||
4528 | rc = -EIO; | ||
4529 | goto error; | ||
4530 | } | ||
4531 | |||
4532 | /* Wait while we're grabbing the image */ | ||
4533 | PDEBUG(4, "Waiting image grabbing"); | ||
4534 | rc = wait_event_interruptible(frame->wq, | ||
4535 | (frame->grabstate == FRAME_DONE) | ||
4536 | || (frame->grabstate == FRAME_ERROR)); | ||
4537 | |||
4538 | if (rc) | ||
4539 | goto error; | ||
4540 | |||
4541 | PDEBUG(4, "Got image, frame->grabstate = %d", frame->grabstate); | ||
4542 | PDEBUG(4, "bytes_recvd = %d", frame->bytes_recvd); | ||
4543 | |||
4544 | if (frame->grabstate == FRAME_ERROR) { | ||
4545 | frame->bytes_read = 0; | ||
4546 | err("** ick! ** Errored frame %d", ov->curframe); | ||
4547 | if (ov51x_new_frame(ov, frmx)) { | ||
4548 | err("read: ov51x_new_frame error"); | ||
4549 | goto error; | ||
4550 | } | ||
4551 | goto restart; | ||
4552 | } | ||
4553 | |||
4554 | |||
4555 | /* Repeat until we get a snapshot frame */ | ||
4556 | if (ov->snap_enabled) | ||
4557 | PDEBUG(4, "Waiting snapshot frame"); | ||
4558 | if (ov->snap_enabled && !frame->snapshot) { | ||
4559 | frame->bytes_read = 0; | ||
4560 | if ((rc = ov51x_new_frame(ov, frmx))) { | ||
4561 | err("read: ov51x_new_frame error"); | ||
4562 | goto error; | ||
4563 | } | ||
4564 | goto restart; | ||
4565 | } | ||
4566 | |||
4567 | /* Clear the snapshot */ | ||
4568 | if (ov->snap_enabled && frame->snapshot) { | ||
4569 | frame->snapshot = 0; | ||
4570 | ov51x_clear_snapshot(ov); | ||
4571 | } | ||
4572 | |||
4573 | /* Decompression, format conversion, etc... */ | ||
4574 | ov51x_postprocess(ov, frame); | ||
4575 | |||
4576 | PDEBUG(4, "frmx=%d, bytes_read=%ld, length=%ld", frmx, | ||
4577 | frame->bytes_read, | ||
4578 | get_frame_length(frame)); | ||
4579 | |||
4580 | /* copy bytes to user space; we allow for partials reads */ | ||
4581 | // if ((count + frame->bytes_read) | ||
4582 | // > get_frame_length((struct ov511_frame *)frame)) | ||
4583 | // count = frame->scanlength - frame->bytes_read; | ||
4584 | |||
4585 | /* FIXME - count hardwired to be one frame... */ | ||
4586 | count = get_frame_length(frame); | ||
4587 | |||
4588 | PDEBUG(4, "Copy to user space: %ld bytes", count); | ||
4589 | if ((i = copy_to_user(buf, frame->data + frame->bytes_read, count))) { | ||
4590 | PDEBUG(4, "Copy failed! %d bytes not copied", i); | ||
4591 | rc = -EFAULT; | ||
4592 | goto error; | ||
4593 | } | ||
4594 | |||
4595 | frame->bytes_read += count; | ||
4596 | PDEBUG(4, "{copy} count used=%ld, new bytes_read=%ld", | ||
4597 | count, frame->bytes_read); | ||
4598 | |||
4599 | /* If all data have been read... */ | ||
4600 | if (frame->bytes_read | ||
4601 | >= get_frame_length(frame)) { | ||
4602 | frame->bytes_read = 0; | ||
4603 | |||
4604 | // FIXME: Only supports two frames | ||
4605 | /* Mark it as available to be used again. */ | ||
4606 | ov->frame[frmx].grabstate = FRAME_UNUSED; | ||
4607 | if ((rc = ov51x_new_frame(ov, !frmx))) { | ||
4608 | err("ov51x_new_frame returned error"); | ||
4609 | goto error; | ||
4610 | } | ||
4611 | } | ||
4612 | |||
4613 | PDEBUG(4, "read finished, returning %ld (sweet)", count); | ||
4614 | |||
4615 | mutex_unlock(&ov->lock); | ||
4616 | return count; | ||
4617 | |||
4618 | error: | ||
4619 | mutex_unlock(&ov->lock); | ||
4620 | return rc; | ||
4621 | } | ||
4622 | |||
4623 | static int | ||
4624 | ov51x_v4l1_mmap(struct file *file, struct vm_area_struct *vma) | ||
4625 | { | ||
4626 | struct video_device *vdev = file->private_data; | ||
4627 | unsigned long start = vma->vm_start; | ||
4628 | unsigned long size = vma->vm_end - vma->vm_start; | ||
4629 | struct usb_ov511 *ov = video_get_drvdata(vdev); | ||
4630 | unsigned long page, pos; | ||
4631 | |||
4632 | if (ov->dev == NULL) | ||
4633 | return -EIO; | ||
4634 | |||
4635 | PDEBUG(4, "mmap: %ld (%lX) bytes", size, size); | ||
4636 | |||
4637 | if (size > (((OV511_NUMFRAMES | ||
4638 | * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight) | ||
4639 | + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))) | ||
4640 | return -EINVAL; | ||
4641 | |||
4642 | if (mutex_lock_interruptible(&ov->lock)) | ||
4643 | return -EINTR; | ||
4644 | |||
4645 | pos = (unsigned long)ov->fbuf; | ||
4646 | while (size > 0) { | ||
4647 | page = vmalloc_to_pfn((void *)pos); | ||
4648 | if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { | ||
4649 | mutex_unlock(&ov->lock); | ||
4650 | return -EAGAIN; | ||
4651 | } | ||
4652 | start += PAGE_SIZE; | ||
4653 | pos += PAGE_SIZE; | ||
4654 | if (size > PAGE_SIZE) | ||
4655 | size -= PAGE_SIZE; | ||
4656 | else | ||
4657 | size = 0; | ||
4658 | } | ||
4659 | |||
4660 | mutex_unlock(&ov->lock); | ||
4661 | return 0; | ||
4662 | } | ||
4663 | |||
4664 | static const struct v4l2_file_operations ov511_fops = { | ||
4665 | .owner = THIS_MODULE, | ||
4666 | .open = ov51x_v4l1_open, | ||
4667 | .release = ov51x_v4l1_close, | ||
4668 | .read = ov51x_v4l1_read, | ||
4669 | .mmap = ov51x_v4l1_mmap, | ||
4670 | .ioctl = ov51x_v4l1_ioctl, | ||
4671 | }; | ||
4672 | |||
4673 | static struct video_device vdev_template = { | ||
4674 | .name = "OV511 USB Camera", | ||
4675 | .fops = &ov511_fops, | ||
4676 | .release = video_device_release, | ||
4677 | }; | ||
4678 | |||
4679 | /**************************************************************************** | ||
4680 | * | ||
4681 | * OV511 and sensor configuration | ||
4682 | * | ||
4683 | ***************************************************************************/ | ||
4684 | |||
4685 | /* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses | ||
4686 | * the same register settings as the OV7610, since they are very similar. | ||
4687 | */ | ||
4688 | static int | ||
4689 | ov7xx0_configure(struct usb_ov511 *ov) | ||
4690 | { | ||
4691 | int i, success; | ||
4692 | int rc; | ||
4693 | |||
4694 | /* Lawrence Glaister <lg@jfm.bc.ca> reports: | ||
4695 | * | ||
4696 | * Register 0x0f in the 7610 has the following effects: | ||
4697 | * | ||
4698 | * 0x85 (AEC method 1): Best overall, good contrast range | ||
4699 | * 0x45 (AEC method 2): Very overexposed | ||
4700 | * 0xa5 (spec sheet default): Ok, but the black level is | ||
4701 | * shifted resulting in loss of contrast | ||
4702 | * 0x05 (old driver setting): very overexposed, too much | ||
4703 | * contrast | ||
4704 | */ | ||
4705 | static struct ov511_regvals aRegvalsNorm7610[] = { | ||
4706 | { OV511_I2C_BUS, 0x10, 0xff }, | ||
4707 | { OV511_I2C_BUS, 0x16, 0x06 }, | ||
4708 | { OV511_I2C_BUS, 0x28, 0x24 }, | ||
4709 | { OV511_I2C_BUS, 0x2b, 0xac }, | ||
4710 | { OV511_I2C_BUS, 0x12, 0x00 }, | ||
4711 | { OV511_I2C_BUS, 0x38, 0x81 }, | ||
4712 | { OV511_I2C_BUS, 0x28, 0x24 }, /* 0c */ | ||
4713 | { OV511_I2C_BUS, 0x0f, 0x85 }, /* lg's setting */ | ||
4714 | { OV511_I2C_BUS, 0x15, 0x01 }, | ||
4715 | { OV511_I2C_BUS, 0x20, 0x1c }, | ||
4716 | { OV511_I2C_BUS, 0x23, 0x2a }, | ||
4717 | { OV511_I2C_BUS, 0x24, 0x10 }, | ||
4718 | { OV511_I2C_BUS, 0x25, 0x8a }, | ||
4719 | { OV511_I2C_BUS, 0x26, 0xa2 }, | ||
4720 | { OV511_I2C_BUS, 0x27, 0xc2 }, | ||
4721 | { OV511_I2C_BUS, 0x2a, 0x04 }, | ||
4722 | { OV511_I2C_BUS, 0x2c, 0xfe }, | ||
4723 | { OV511_I2C_BUS, 0x2d, 0x93 }, | ||
4724 | { OV511_I2C_BUS, 0x30, 0x71 }, | ||
4725 | { OV511_I2C_BUS, 0x31, 0x60 }, | ||
4726 | { OV511_I2C_BUS, 0x32, 0x26 }, | ||
4727 | { OV511_I2C_BUS, 0x33, 0x20 }, | ||
4728 | { OV511_I2C_BUS, 0x34, 0x48 }, | ||
4729 | { OV511_I2C_BUS, 0x12, 0x24 }, | ||
4730 | { OV511_I2C_BUS, 0x11, 0x01 }, | ||
4731 | { OV511_I2C_BUS, 0x0c, 0x24 }, | ||
4732 | { OV511_I2C_BUS, 0x0d, 0x24 }, | ||
4733 | { OV511_DONE_BUS, 0x0, 0x00 }, | ||
4734 | }; | ||
4735 | |||
4736 | static struct ov511_regvals aRegvalsNorm7620[] = { | ||
4737 | { OV511_I2C_BUS, 0x00, 0x00 }, | ||
4738 | { OV511_I2C_BUS, 0x01, 0x80 }, | ||
4739 | { OV511_I2C_BUS, 0x02, 0x80 }, | ||
4740 | { OV511_I2C_BUS, 0x03, 0xc0 }, | ||
4741 | { OV511_I2C_BUS, 0x06, 0x60 }, | ||
4742 | { OV511_I2C_BUS, 0x07, 0x00 }, | ||
4743 | { OV511_I2C_BUS, 0x0c, 0x24 }, | ||
4744 | { OV511_I2C_BUS, 0x0c, 0x24 }, | ||
4745 | { OV511_I2C_BUS, 0x0d, 0x24 }, | ||
4746 | { OV511_I2C_BUS, 0x11, 0x01 }, | ||
4747 | { OV511_I2C_BUS, 0x12, 0x24 }, | ||
4748 | { OV511_I2C_BUS, 0x13, 0x01 }, | ||
4749 | { OV511_I2C_BUS, 0x14, 0x84 }, | ||
4750 | { OV511_I2C_BUS, 0x15, 0x01 }, | ||
4751 | { OV511_I2C_BUS, 0x16, 0x03 }, | ||
4752 | { OV511_I2C_BUS, 0x17, 0x2f }, | ||
4753 | { OV511_I2C_BUS, 0x18, 0xcf }, | ||
4754 | { OV511_I2C_BUS, 0x19, 0x06 }, | ||
4755 | { OV511_I2C_BUS, 0x1a, 0xf5 }, | ||
4756 | { OV511_I2C_BUS, 0x1b, 0x00 }, | ||
4757 | { OV511_I2C_BUS, 0x20, 0x18 }, | ||
4758 | { OV511_I2C_BUS, 0x21, 0x80 }, | ||
4759 | { OV511_I2C_BUS, 0x22, 0x80 }, | ||
4760 | { OV511_I2C_BUS, 0x23, 0x00 }, | ||
4761 | { OV511_I2C_BUS, 0x26, 0xa2 }, | ||
4762 | { OV511_I2C_BUS, 0x27, 0xea }, | ||
4763 | { OV511_I2C_BUS, 0x28, 0x20 }, | ||
4764 | { OV511_I2C_BUS, 0x29, 0x00 }, | ||
4765 | { OV511_I2C_BUS, 0x2a, 0x10 }, | ||
4766 | { OV511_I2C_BUS, 0x2b, 0x00 }, | ||
4767 | { OV511_I2C_BUS, 0x2c, 0x88 }, | ||
4768 | { OV511_I2C_BUS, 0x2d, 0x91 }, | ||
4769 | { OV511_I2C_BUS, 0x2e, 0x80 }, | ||
4770 | { OV511_I2C_BUS, 0x2f, 0x44 }, | ||
4771 | { OV511_I2C_BUS, 0x60, 0x27 }, | ||
4772 | { OV511_I2C_BUS, 0x61, 0x02 }, | ||
4773 | { OV511_I2C_BUS, 0x62, 0x5f }, | ||
4774 | { OV511_I2C_BUS, 0x63, 0xd5 }, | ||
4775 | { OV511_I2C_BUS, 0x64, 0x57 }, | ||
4776 | { OV511_I2C_BUS, 0x65, 0x83 }, | ||
4777 | { OV511_I2C_BUS, 0x66, 0x55 }, | ||
4778 | { OV511_I2C_BUS, 0x67, 0x92 }, | ||
4779 | { OV511_I2C_BUS, 0x68, 0xcf }, | ||
4780 | { OV511_I2C_BUS, 0x69, 0x76 }, | ||
4781 | { OV511_I2C_BUS, 0x6a, 0x22 }, | ||
4782 | { OV511_I2C_BUS, 0x6b, 0x00 }, | ||
4783 | { OV511_I2C_BUS, 0x6c, 0x02 }, | ||
4784 | { OV511_I2C_BUS, 0x6d, 0x44 }, | ||
4785 | { OV511_I2C_BUS, 0x6e, 0x80 }, | ||
4786 | { OV511_I2C_BUS, 0x6f, 0x1d }, | ||
4787 | { OV511_I2C_BUS, 0x70, 0x8b }, | ||
4788 | { OV511_I2C_BUS, 0x71, 0x00 }, | ||
4789 | { OV511_I2C_BUS, 0x72, 0x14 }, | ||
4790 | { OV511_I2C_BUS, 0x73, 0x54 }, | ||
4791 | { OV511_I2C_BUS, 0x74, 0x00 }, | ||
4792 | { OV511_I2C_BUS, 0x75, 0x8e }, | ||
4793 | { OV511_I2C_BUS, 0x76, 0x00 }, | ||
4794 | { OV511_I2C_BUS, 0x77, 0xff }, | ||
4795 | { OV511_I2C_BUS, 0x78, 0x80 }, | ||
4796 | { OV511_I2C_BUS, 0x79, 0x80 }, | ||
4797 | { OV511_I2C_BUS, 0x7a, 0x80 }, | ||
4798 | { OV511_I2C_BUS, 0x7b, 0xe2 }, | ||
4799 | { OV511_I2C_BUS, 0x7c, 0x00 }, | ||
4800 | { OV511_DONE_BUS, 0x0, 0x00 }, | ||
4801 | }; | ||
4802 | |||
4803 | PDEBUG(4, "starting configuration"); | ||
4804 | |||
4805 | /* This looks redundant, but is necessary for WebCam 3 */ | ||
4806 | ov->primary_i2c_slave = OV7xx0_SID; | ||
4807 | if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0) | ||
4808 | return -1; | ||
4809 | |||
4810 | if (init_ov_sensor(ov) >= 0) { | ||
4811 | PDEBUG(1, "OV7xx0 sensor initalized (method 1)"); | ||
4812 | } else { | ||
4813 | /* Reset the 76xx */ | ||
4814 | if (i2c_w(ov, 0x12, 0x80) < 0) | ||
4815 | return -1; | ||
4816 | |||
4817 | /* Wait for it to initialize */ | ||
4818 | msleep(150); | ||
4819 | |||
4820 | i = 0; | ||
4821 | success = 0; | ||
4822 | while (i <= i2c_detect_tries) { | ||
4823 | if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) && | ||
4824 | (i2c_r(ov, OV7610_REG_ID_LOW) == 0xA2)) { | ||
4825 | success = 1; | ||
4826 | break; | ||
4827 | } else { | ||
4828 | i++; | ||
4829 | } | ||
4830 | } | ||
4831 | |||
4832 | // Was (i == i2c_detect_tries) previously. This obviously used to always report | ||
4833 | // success. Whether anyone actually depended on that bug is unknown | ||
4834 | if ((i >= i2c_detect_tries) && (success == 0)) { | ||
4835 | err("Failed to read sensor ID. You might not have an"); | ||
4836 | err("OV7610/20, or it may be not responding. Report"); | ||
4837 | err("this to " EMAIL); | ||
4838 | err("This is only a warning. You can attempt to use"); | ||
4839 | err("your camera anyway"); | ||
4840 | // Only issue a warning for now | ||
4841 | // return -1; | ||
4842 | } else { | ||
4843 | PDEBUG(1, "OV7xx0 initialized (method 2, %dx)", i+1); | ||
4844 | } | ||
4845 | } | ||
4846 | |||
4847 | /* Detect sensor (sub)type */ | ||
4848 | rc = i2c_r(ov, OV7610_REG_COM_I); | ||
4849 | |||
4850 | if (rc < 0) { | ||
4851 | err("Error detecting sensor type"); | ||
4852 | return -1; | ||
4853 | } else if ((rc & 3) == 3) { | ||
4854 | dev_info(&ov->dev->dev, "Sensor is an OV7610\n"); | ||
4855 | ov->sensor = SEN_OV7610; | ||
4856 | } else if ((rc & 3) == 1) { | ||
4857 | /* I don't know what's different about the 76BE yet. */ | ||
4858 | if (i2c_r(ov, 0x15) & 1) | ||
4859 | dev_info(&ov->dev->dev, "Sensor is an OV7620AE\n"); | ||
4860 | else | ||
4861 | dev_info(&ov->dev->dev, "Sensor is an OV76BE\n"); | ||
4862 | |||
4863 | /* OV511+ will return all zero isoc data unless we | ||
4864 | * configure the sensor as a 7620. Someone needs to | ||
4865 | * find the exact reg. setting that causes this. */ | ||
4866 | if (ov->bridge == BRG_OV511PLUS) { | ||
4867 | dev_info(&ov->dev->dev, | ||
4868 | "Enabling 511+/7620AE workaround\n"); | ||
4869 | ov->sensor = SEN_OV7620; | ||
4870 | } else { | ||
4871 | ov->sensor = SEN_OV76BE; | ||
4872 | } | ||
4873 | } else if ((rc & 3) == 0) { | ||
4874 | dev_info(&ov->dev->dev, "Sensor is an OV7620\n"); | ||
4875 | ov->sensor = SEN_OV7620; | ||
4876 | } else { | ||
4877 | err("Unknown image sensor version: %d", rc & 3); | ||
4878 | return -1; | ||
4879 | } | ||
4880 | |||
4881 | if (ov->sensor == SEN_OV7620) { | ||
4882 | PDEBUG(4, "Writing 7620 registers"); | ||
4883 | if (write_regvals(ov, aRegvalsNorm7620)) | ||
4884 | return -1; | ||
4885 | } else { | ||
4886 | PDEBUG(4, "Writing 7610 registers"); | ||
4887 | if (write_regvals(ov, aRegvalsNorm7610)) | ||
4888 | return -1; | ||
4889 | } | ||
4890 | |||
4891 | /* Set sensor-specific vars */ | ||
4892 | ov->maxwidth = 640; | ||
4893 | ov->maxheight = 480; | ||
4894 | ov->minwidth = 64; | ||
4895 | ov->minheight = 48; | ||
4896 | |||
4897 | // FIXME: These do not match the actual settings yet | ||
4898 | ov->brightness = 0x80 << 8; | ||
4899 | ov->contrast = 0x80 << 8; | ||
4900 | ov->colour = 0x80 << 8; | ||
4901 | ov->hue = 0x80 << 8; | ||
4902 | |||
4903 | return 0; | ||
4904 | } | ||
4905 | |||
4906 | /* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */ | ||
4907 | static int | ||
4908 | ov6xx0_configure(struct usb_ov511 *ov) | ||
4909 | { | ||
4910 | int rc; | ||
4911 | |||
4912 | static struct ov511_regvals aRegvalsNorm6x20[] = { | ||
4913 | { OV511_I2C_BUS, 0x12, 0x80 }, /* reset */ | ||
4914 | { OV511_I2C_BUS, 0x11, 0x01 }, | ||
4915 | { OV511_I2C_BUS, 0x03, 0x60 }, | ||
4916 | { OV511_I2C_BUS, 0x05, 0x7f }, /* For when autoadjust is off */ | ||
4917 | { OV511_I2C_BUS, 0x07, 0xa8 }, | ||
4918 | /* The ratio of 0x0c and 0x0d controls the white point */ | ||
4919 | { OV511_I2C_BUS, 0x0c, 0x24 }, | ||
4920 | { OV511_I2C_BUS, 0x0d, 0x24 }, | ||
4921 | { OV511_I2C_BUS, 0x0f, 0x15 }, /* COMS */ | ||
4922 | { OV511_I2C_BUS, 0x10, 0x75 }, /* AEC Exposure time */ | ||
4923 | { OV511_I2C_BUS, 0x12, 0x24 }, /* Enable AGC */ | ||
4924 | { OV511_I2C_BUS, 0x14, 0x04 }, | ||
4925 | /* 0x16: 0x06 helps frame stability with moving objects */ | ||
4926 | { OV511_I2C_BUS, 0x16, 0x06 }, | ||
4927 | // { OV511_I2C_BUS, 0x20, 0x30 }, /* Aperture correction enable */ | ||
4928 | { OV511_I2C_BUS, 0x26, 0xb2 }, /* BLC enable */ | ||
4929 | /* 0x28: 0x05 Selects RGB format if RGB on */ | ||
4930 | { OV511_I2C_BUS, 0x28, 0x05 }, | ||
4931 | { OV511_I2C_BUS, 0x2a, 0x04 }, /* Disable framerate adjust */ | ||
4932 | // { OV511_I2C_BUS, 0x2b, 0xac }, /* Framerate; Set 2a[7] first */ | ||
4933 | { OV511_I2C_BUS, 0x2d, 0x99 }, | ||
4934 | { OV511_I2C_BUS, 0x33, 0xa0 }, /* Color Processing Parameter */ | ||
4935 | { OV511_I2C_BUS, 0x34, 0xd2 }, /* Max A/D range */ | ||
4936 | { OV511_I2C_BUS, 0x38, 0x8b }, | ||
4937 | { OV511_I2C_BUS, 0x39, 0x40 }, | ||
4938 | |||
4939 | { OV511_I2C_BUS, 0x3c, 0x39 }, /* Enable AEC mode changing */ | ||
4940 | { OV511_I2C_BUS, 0x3c, 0x3c }, /* Change AEC mode */ | ||
4941 | { OV511_I2C_BUS, 0x3c, 0x24 }, /* Disable AEC mode changing */ | ||
4942 | |||
4943 | { OV511_I2C_BUS, 0x3d, 0x80 }, | ||
4944 | /* These next two registers (0x4a, 0x4b) are undocumented. They | ||
4945 | * control the color balance */ | ||
4946 | { OV511_I2C_BUS, 0x4a, 0x80 }, | ||
4947 | { OV511_I2C_BUS, 0x4b, 0x80 }, | ||
4948 | { OV511_I2C_BUS, 0x4d, 0xd2 }, /* This reduces noise a bit */ | ||
4949 | { OV511_I2C_BUS, 0x4e, 0xc1 }, | ||
4950 | { OV511_I2C_BUS, 0x4f, 0x04 }, | ||
4951 | // Do 50-53 have any effect? | ||
4952 | // Toggle 0x12[2] off and on here? | ||
4953 | { OV511_DONE_BUS, 0x0, 0x00 }, /* END MARKER */ | ||
4954 | }; | ||
4955 | |||
4956 | static struct ov511_regvals aRegvalsNorm6x30[] = { | ||
4957 | /*OK*/ { OV511_I2C_BUS, 0x12, 0x80 }, /* reset */ | ||
4958 | { OV511_I2C_BUS, 0x11, 0x00 }, | ||
4959 | /*OK*/ { OV511_I2C_BUS, 0x03, 0x60 }, | ||
4960 | /*0A?*/ { OV511_I2C_BUS, 0x05, 0x7f }, /* For when autoadjust is off */ | ||
4961 | { OV511_I2C_BUS, 0x07, 0xa8 }, | ||
4962 | /* The ratio of 0x0c and 0x0d controls the white point */ | ||
4963 | /*OK*/ { OV511_I2C_BUS, 0x0c, 0x24 }, | ||
4964 | /*OK*/ { OV511_I2C_BUS, 0x0d, 0x24 }, | ||
4965 | /*A*/ { OV511_I2C_BUS, 0x0e, 0x20 }, | ||
4966 | // /*04?*/ { OV511_I2C_BUS, 0x14, 0x80 }, | ||
4967 | { OV511_I2C_BUS, 0x16, 0x03 }, | ||
4968 | // /*OK*/ { OV511_I2C_BUS, 0x20, 0x30 }, /* Aperture correction enable */ | ||
4969 | // 21 & 22? The suggested values look wrong. Go with default | ||
4970 | /*A*/ { OV511_I2C_BUS, 0x23, 0xc0 }, | ||
4971 | /*A*/ { OV511_I2C_BUS, 0x25, 0x9a }, // Check this against default | ||
4972 | // /*OK*/ { OV511_I2C_BUS, 0x26, 0xb2 }, /* BLC enable */ | ||
4973 | |||
4974 | /* 0x28: 0x05 Selects RGB format if RGB on */ | ||
4975 | // /*04?*/ { OV511_I2C_BUS, 0x28, 0x05 }, | ||
4976 | // /*04?*/ { OV511_I2C_BUS, 0x28, 0x45 }, // DEBUG: Tristate UV bus | ||
4977 | |||
4978 | /*OK*/ { OV511_I2C_BUS, 0x2a, 0x04 }, /* Disable framerate adjust */ | ||
4979 | // /*OK*/ { OV511_I2C_BUS, 0x2b, 0xac }, /* Framerate; Set 2a[7] first */ | ||
4980 | { OV511_I2C_BUS, 0x2d, 0x99 }, | ||
4981 | // /*A*/ { OV511_I2C_BUS, 0x33, 0x26 }, // Reserved bits on 6620 | ||
4982 | // /*d2?*/ { OV511_I2C_BUS, 0x34, 0x03 }, /* Max A/D range */ | ||
4983 | // /*8b?*/ { OV511_I2C_BUS, 0x38, 0x83 }, | ||
4984 | // /*40?*/ { OV511_I2C_BUS, 0x39, 0xc0 }, // 6630 adds bit 7 | ||
4985 | // { OV511_I2C_BUS, 0x3c, 0x39 }, /* Enable AEC mode changing */ | ||
4986 | // { OV511_I2C_BUS, 0x3c, 0x3c }, /* Change AEC mode */ | ||
4987 | // { OV511_I2C_BUS, 0x3c, 0x24 }, /* Disable AEC mode changing */ | ||
4988 | { OV511_I2C_BUS, 0x3d, 0x80 }, | ||
4989 | // /*A*/ { OV511_I2C_BUS, 0x3f, 0x0e }, | ||
4990 | |||
4991 | /* These next two registers (0x4a, 0x4b) are undocumented. They | ||
4992 | * control the color balance */ | ||
4993 | // /*OK?*/ { OV511_I2C_BUS, 0x4a, 0x80 }, // Check these | ||
4994 | // /*OK?*/ { OV511_I2C_BUS, 0x4b, 0x80 }, | ||
4995 | { OV511_I2C_BUS, 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */ | ||
4996 | /*c1?*/ { OV511_I2C_BUS, 0x4e, 0x40 }, | ||
4997 | |||
4998 | /* UV average mode, color killer: strongest */ | ||
4999 | { OV511_I2C_BUS, 0x4f, 0x07 }, | ||
5000 | |||
5001 | { OV511_I2C_BUS, 0x54, 0x23 }, /* Max AGC gain: 18dB */ | ||
5002 | { OV511_I2C_BUS, 0x57, 0x81 }, /* (default) */ | ||
5003 | { OV511_I2C_BUS, 0x59, 0x01 }, /* AGC dark current comp: +1 */ | ||
5004 | { OV511_I2C_BUS, 0x5a, 0x2c }, /* (undocumented) */ | ||
5005 | { OV511_I2C_BUS, 0x5b, 0x0f }, /* AWB chrominance levels */ | ||
5006 | // { OV511_I2C_BUS, 0x5c, 0x10 }, | ||
5007 | { OV511_DONE_BUS, 0x0, 0x00 }, /* END MARKER */ | ||
5008 | }; | ||
5009 | |||
5010 | PDEBUG(4, "starting sensor configuration"); | ||
5011 | |||
5012 | if (init_ov_sensor(ov) < 0) { | ||
5013 | err("Failed to read sensor ID. You might not have an OV6xx0,"); | ||
5014 | err("or it may be not responding. Report this to " EMAIL); | ||
5015 | return -1; | ||
5016 | } else { | ||
5017 | PDEBUG(1, "OV6xx0 sensor detected"); | ||
5018 | } | ||
5019 | |||
5020 | /* Detect sensor (sub)type */ | ||
5021 | rc = i2c_r(ov, OV7610_REG_COM_I); | ||
5022 | |||
5023 | if (rc < 0) { | ||
5024 | err("Error detecting sensor type"); | ||
5025 | return -1; | ||
5026 | } | ||
5027 | |||
5028 | if ((rc & 3) == 0) { | ||
5029 | ov->sensor = SEN_OV6630; | ||
5030 | dev_info(&ov->dev->dev, "Sensor is an OV6630\n"); | ||
5031 | } else if ((rc & 3) == 1) { | ||
5032 | ov->sensor = SEN_OV6620; | ||
5033 | dev_info(&ov->dev->dev, "Sensor is an OV6620\n"); | ||
5034 | } else if ((rc & 3) == 2) { | ||
5035 | ov->sensor = SEN_OV6630; | ||
5036 | dev_info(&ov->dev->dev, "Sensor is an OV6630AE\n"); | ||
5037 | } else if ((rc & 3) == 3) { | ||
5038 | ov->sensor = SEN_OV6630; | ||
5039 | dev_info(&ov->dev->dev, "Sensor is an OV6630AF\n"); | ||
5040 | } | ||
5041 | |||
5042 | /* Set sensor-specific vars */ | ||
5043 | ov->maxwidth = 352; | ||
5044 | ov->maxheight = 288; | ||
5045 | ov->minwidth = 64; | ||
5046 | ov->minheight = 48; | ||
5047 | |||
5048 | // FIXME: These do not match the actual settings yet | ||
5049 | ov->brightness = 0x80 << 8; | ||
5050 | ov->contrast = 0x80 << 8; | ||
5051 | ov->colour = 0x80 << 8; | ||
5052 | ov->hue = 0x80 << 8; | ||
5053 | |||
5054 | if (ov->sensor == SEN_OV6620) { | ||
5055 | PDEBUG(4, "Writing 6x20 registers"); | ||
5056 | if (write_regvals(ov, aRegvalsNorm6x20)) | ||
5057 | return -1; | ||
5058 | } else { | ||
5059 | PDEBUG(4, "Writing 6x30 registers"); | ||
5060 | if (write_regvals(ov, aRegvalsNorm6x30)) | ||
5061 | return -1; | ||
5062 | } | ||
5063 | |||
5064 | return 0; | ||
5065 | } | ||
5066 | |||
5067 | /* This initializes the KS0127 and KS0127B video decoders. */ | ||
5068 | static int | ||
5069 | ks0127_configure(struct usb_ov511 *ov) | ||
5070 | { | ||
5071 | int rc; | ||
5072 | |||
5073 | // FIXME: I don't know how to sync or reset it yet | ||
5074 | #if 0 | ||
5075 | if (ov51x_init_ks_sensor(ov) < 0) { | ||
5076 | err("Failed to initialize the KS0127"); | ||
5077 | return -1; | ||
5078 | } else { | ||
5079 | PDEBUG(1, "KS012x(B) sensor detected"); | ||
5080 | } | ||
5081 | #endif | ||
5082 | |||
5083 | /* Detect decoder subtype */ | ||
5084 | rc = i2c_r(ov, 0x00); | ||
5085 | if (rc < 0) { | ||
5086 | err("Error detecting sensor type"); | ||
5087 | return -1; | ||
5088 | } else if (rc & 0x08) { | ||
5089 | rc = i2c_r(ov, 0x3d); | ||
5090 | if (rc < 0) { | ||
5091 | err("Error detecting sensor type"); | ||
5092 | return -1; | ||
5093 | } else if ((rc & 0x0f) == 0) { | ||
5094 | dev_info(&ov->dev->dev, "Sensor is a KS0127\n"); | ||
5095 | ov->sensor = SEN_KS0127; | ||
5096 | } else if ((rc & 0x0f) == 9) { | ||
5097 | dev_info(&ov->dev->dev, "Sensor is a KS0127B Rev. A\n"); | ||
5098 | ov->sensor = SEN_KS0127B; | ||
5099 | } | ||
5100 | } else { | ||
5101 | err("Error: Sensor is an unsupported KS0122"); | ||
5102 | return -1; | ||
5103 | } | ||
5104 | |||
5105 | /* Set sensor-specific vars */ | ||
5106 | ov->maxwidth = 640; | ||
5107 | ov->maxheight = 480; | ||
5108 | ov->minwidth = 64; | ||
5109 | ov->minheight = 48; | ||
5110 | |||
5111 | // FIXME: These do not match the actual settings yet | ||
5112 | ov->brightness = 0x80 << 8; | ||
5113 | ov->contrast = 0x80 << 8; | ||
5114 | ov->colour = 0x80 << 8; | ||
5115 | ov->hue = 0x80 << 8; | ||
5116 | |||
5117 | /* This device is not supported yet. Bail out now... */ | ||
5118 | err("This sensor is not supported yet."); | ||
5119 | return -1; | ||
5120 | |||
5121 | return 0; | ||
5122 | } | ||
5123 | |||
5124 | /* This initializes the SAA7111A video decoder. */ | ||
5125 | static int | ||
5126 | saa7111a_configure(struct usb_ov511 *ov) | ||
5127 | { | ||
5128 | int rc; | ||
5129 | |||
5130 | /* Since there is no register reset command, all registers must be | ||
5131 | * written, otherwise gives erratic results */ | ||
5132 | static struct ov511_regvals aRegvalsNormSAA7111A[] = { | ||
5133 | { OV511_I2C_BUS, 0x06, 0xce }, | ||
5134 | { OV511_I2C_BUS, 0x07, 0x00 }, | ||
5135 | { OV511_I2C_BUS, 0x10, 0x44 }, /* YUV422, 240/286 lines */ | ||
5136 | { OV511_I2C_BUS, 0x0e, 0x01 }, /* NTSC M or PAL BGHI */ | ||
5137 | { OV511_I2C_BUS, 0x00, 0x00 }, | ||
5138 | { OV511_I2C_BUS, 0x01, 0x00 }, | ||
5139 | { OV511_I2C_BUS, 0x03, 0x23 }, | ||
5140 | { OV511_I2C_BUS, 0x04, 0x00 }, | ||
5141 | { OV511_I2C_BUS, 0x05, 0x00 }, | ||
5142 | { OV511_I2C_BUS, 0x08, 0xc8 }, /* Auto field freq */ | ||
5143 | { OV511_I2C_BUS, 0x09, 0x01 }, /* Chrom. trap off, APER=0.25 */ | ||
5144 | { OV511_I2C_BUS, 0x0a, 0x80 }, /* BRIG=128 */ | ||
5145 | { OV511_I2C_BUS, 0x0b, 0x40 }, /* CONT=1.0 */ | ||
5146 | { OV511_I2C_BUS, 0x0c, 0x40 }, /* SATN=1.0 */ | ||
5147 | { OV511_I2C_BUS, 0x0d, 0x00 }, /* HUE=0 */ | ||
5148 | { OV511_I2C_BUS, 0x0f, 0x00 }, | ||
5149 | { OV511_I2C_BUS, 0x11, 0x0c }, | ||
5150 | { OV511_I2C_BUS, 0x12, 0x00 }, | ||
5151 | { OV511_I2C_BUS, 0x13, 0x00 }, | ||
5152 | { OV511_I2C_BUS, 0x14, 0x00 }, | ||
5153 | { OV511_I2C_BUS, 0x15, 0x00 }, | ||
5154 | { OV511_I2C_BUS, 0x16, 0x00 }, | ||
5155 | { OV511_I2C_BUS, 0x17, 0x00 }, | ||
5156 | { OV511_I2C_BUS, 0x02, 0xc0 }, /* Composite input 0 */ | ||
5157 | { OV511_DONE_BUS, 0x0, 0x00 }, | ||
5158 | }; | ||
5159 | |||
5160 | // FIXME: I don't know how to sync or reset it yet | ||
5161 | #if 0 | ||
5162 | if (ov51x_init_saa_sensor(ov) < 0) { | ||
5163 | err("Failed to initialize the SAA7111A"); | ||
5164 | return -1; | ||
5165 | } else { | ||
5166 | PDEBUG(1, "SAA7111A sensor detected"); | ||
5167 | } | ||
5168 | #endif | ||
5169 | |||
5170 | /* 640x480 not supported with PAL */ | ||
5171 | if (ov->pal) { | ||
5172 | ov->maxwidth = 320; | ||
5173 | ov->maxheight = 240; /* Even field only */ | ||
5174 | } else { | ||
5175 | ov->maxwidth = 640; | ||
5176 | ov->maxheight = 480; /* Even/Odd fields */ | ||
5177 | } | ||
5178 | |||
5179 | ov->minwidth = 320; | ||
5180 | ov->minheight = 240; /* Even field only */ | ||
5181 | |||
5182 | ov->has_decoder = 1; | ||
5183 | ov->num_inputs = 8; | ||
5184 | ov->norm = VIDEO_MODE_AUTO; | ||
5185 | ov->stop_during_set = 0; /* Decoder guarantees stable image */ | ||
5186 | |||
5187 | /* Decoder doesn't change these values, so we use these instead of | ||
5188 | * acutally reading the registers (which doesn't work) */ | ||
5189 | ov->brightness = 0x80 << 8; | ||
5190 | ov->contrast = 0x40 << 9; | ||
5191 | ov->colour = 0x40 << 9; | ||
5192 | ov->hue = 32768; | ||
5193 | |||
5194 | PDEBUG(4, "Writing SAA7111A registers"); | ||
5195 | if (write_regvals(ov, aRegvalsNormSAA7111A)) | ||
5196 | return -1; | ||
5197 | |||
5198 | /* Detect version of decoder. This must be done after writing the | ||
5199 | * initial regs or the decoder will lock up. */ | ||
5200 | rc = i2c_r(ov, 0x00); | ||
5201 | |||
5202 | if (rc < 0) { | ||
5203 | err("Error detecting sensor version"); | ||
5204 | return -1; | ||
5205 | } else { | ||
5206 | dev_info(&ov->dev->dev, | ||
5207 | "Sensor is an SAA7111A (version 0x%x)\n", rc); | ||
5208 | ov->sensor = SEN_SAA7111A; | ||
5209 | } | ||
5210 | |||
5211 | // FIXME: Fix this for OV518(+) | ||
5212 | /* Latch to negative edge of clock. Otherwise, we get incorrect | ||
5213 | * colors and jitter in the digital signal. */ | ||
5214 | if (ov->bclass == BCL_OV511) | ||
5215 | reg_w(ov, 0x11, 0x00); | ||
5216 | else | ||
5217 | dev_warn(&ov->dev->dev, | ||
5218 | "SAA7111A not yet supported with OV518/OV518+\n"); | ||
5219 | |||
5220 | return 0; | ||
5221 | } | ||
5222 | |||
5223 | /* This initializes the OV511/OV511+ and the sensor */ | ||
5224 | static int | ||
5225 | ov511_configure(struct usb_ov511 *ov) | ||
5226 | { | ||
5227 | static struct ov511_regvals aRegvalsInit511[] = { | ||
5228 | { OV511_REG_BUS, R51x_SYS_RESET, 0x7f }, | ||
5229 | { OV511_REG_BUS, R51x_SYS_INIT, 0x01 }, | ||
5230 | { OV511_REG_BUS, R51x_SYS_RESET, 0x7f }, | ||
5231 | { OV511_REG_BUS, R51x_SYS_INIT, 0x01 }, | ||
5232 | { OV511_REG_BUS, R51x_SYS_RESET, 0x3f }, | ||
5233 | { OV511_REG_BUS, R51x_SYS_INIT, 0x01 }, | ||
5234 | { OV511_REG_BUS, R51x_SYS_RESET, 0x3d }, | ||
5235 | { OV511_DONE_BUS, 0x0, 0x00}, | ||
5236 | }; | ||
5237 | |||
5238 | static struct ov511_regvals aRegvalsNorm511[] = { | ||
5239 | { OV511_REG_BUS, R511_DRAM_FLOW_CTL, 0x01 }, | ||
5240 | { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, | ||
5241 | { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, | ||
5242 | { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, | ||
5243 | { OV511_REG_BUS, R511_FIFO_OPTS, 0x1f }, | ||
5244 | { OV511_REG_BUS, R511_COMP_EN, 0x00 }, | ||
5245 | { OV511_REG_BUS, R511_COMP_LUT_EN, 0x03 }, | ||
5246 | { OV511_DONE_BUS, 0x0, 0x00 }, | ||
5247 | }; | ||
5248 | |||
5249 | static struct ov511_regvals aRegvalsNorm511Plus[] = { | ||
5250 | { OV511_REG_BUS, R511_DRAM_FLOW_CTL, 0xff }, | ||
5251 | { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, | ||
5252 | { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, | ||
5253 | { OV511_REG_BUS, R51x_SYS_SNAP, 0x00 }, | ||
5254 | { OV511_REG_BUS, R511_FIFO_OPTS, 0xff }, | ||
5255 | { OV511_REG_BUS, R511_COMP_EN, 0x00 }, | ||
5256 | { OV511_REG_BUS, R511_COMP_LUT_EN, 0x03 }, | ||
5257 | { OV511_DONE_BUS, 0x0, 0x00 }, | ||
5258 | }; | ||
5259 | |||
5260 | PDEBUG(4, ""); | ||
5261 | |||
5262 | ov->customid = reg_r(ov, R511_SYS_CUST_ID); | ||
5263 | if (ov->customid < 0) { | ||
5264 | err("Unable to read camera bridge registers"); | ||
5265 | goto error; | ||
5266 | } | ||
5267 | |||
5268 | PDEBUG (1, "CustomID = %d", ov->customid); | ||
5269 | ov->desc = symbolic(camlist, ov->customid); | ||
5270 | dev_info(&ov->dev->dev, "model: %s\n", ov->desc); | ||
5271 | |||
5272 | if (0 == strcmp(ov->desc, NOT_DEFINED_STR)) { | ||
5273 | err("Camera type (%d) not recognized", ov->customid); | ||
5274 | err("Please notify " EMAIL " of the name,"); | ||
5275 | err("manufacturer, model, and this number of your camera."); | ||
5276 | err("Also include the output of the detection process."); | ||
5277 | } | ||
5278 | |||
5279 | if (ov->customid == 70) /* USB Life TV (PAL/SECAM) */ | ||
5280 | ov->pal = 1; | ||
5281 | |||
5282 | if (write_regvals(ov, aRegvalsInit511)) | ||
5283 | goto error; | ||
5284 | |||
5285 | if (ov->led_policy == LED_OFF || ov->led_policy == LED_AUTO) | ||
5286 | ov51x_led_control(ov, 0); | ||
5287 | |||
5288 | /* The OV511+ has undocumented bits in the flow control register. | ||
5289 | * Setting it to 0xff fixes the corruption with moving objects. */ | ||
5290 | if (ov->bridge == BRG_OV511) { | ||
5291 | if (write_regvals(ov, aRegvalsNorm511)) | ||
5292 | goto error; | ||
5293 | } else if (ov->bridge == BRG_OV511PLUS) { | ||
5294 | if (write_regvals(ov, aRegvalsNorm511Plus)) | ||
5295 | goto error; | ||
5296 | } else { | ||
5297 | err("Invalid bridge"); | ||
5298 | } | ||
5299 | |||
5300 | if (ov511_init_compression(ov)) | ||
5301 | goto error; | ||
5302 | |||
5303 | ov->packet_numbering = 1; | ||
5304 | ov511_set_packet_size(ov, 0); | ||
5305 | |||
5306 | ov->snap_enabled = snapshot; | ||
5307 | |||
5308 | /* Test for 7xx0 */ | ||
5309 | PDEBUG(3, "Testing for 0V7xx0"); | ||
5310 | ov->primary_i2c_slave = OV7xx0_SID; | ||
5311 | if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0) | ||
5312 | goto error; | ||
5313 | |||
5314 | if (i2c_w(ov, 0x12, 0x80) < 0) { | ||
5315 | /* Test for 6xx0 */ | ||
5316 | PDEBUG(3, "Testing for 0V6xx0"); | ||
5317 | ov->primary_i2c_slave = OV6xx0_SID; | ||
5318 | if (ov51x_set_slave_ids(ov, OV6xx0_SID) < 0) | ||
5319 | goto error; | ||
5320 | |||
5321 | if (i2c_w(ov, 0x12, 0x80) < 0) { | ||
5322 | /* Test for 8xx0 */ | ||
5323 | PDEBUG(3, "Testing for 0V8xx0"); | ||
5324 | ov->primary_i2c_slave = OV8xx0_SID; | ||
5325 | if (ov51x_set_slave_ids(ov, OV8xx0_SID) < 0) | ||
5326 | goto error; | ||
5327 | |||
5328 | if (i2c_w(ov, 0x12, 0x80) < 0) { | ||
5329 | /* Test for SAA7111A */ | ||
5330 | PDEBUG(3, "Testing for SAA7111A"); | ||
5331 | ov->primary_i2c_slave = SAA7111A_SID; | ||
5332 | if (ov51x_set_slave_ids(ov, SAA7111A_SID) < 0) | ||
5333 | goto error; | ||
5334 | |||
5335 | if (i2c_w(ov, 0x0d, 0x00) < 0) { | ||
5336 | /* Test for KS0127 */ | ||
5337 | PDEBUG(3, "Testing for KS0127"); | ||
5338 | ov->primary_i2c_slave = KS0127_SID; | ||
5339 | if (ov51x_set_slave_ids(ov, KS0127_SID) < 0) | ||
5340 | goto error; | ||
5341 | |||
5342 | if (i2c_w(ov, 0x10, 0x00) < 0) { | ||
5343 | err("Can't determine sensor slave IDs"); | ||
5344 | goto error; | ||
5345 | } else { | ||
5346 | if (ks0127_configure(ov) < 0) { | ||
5347 | err("Failed to configure KS0127"); | ||
5348 | goto error; | ||
5349 | } | ||
5350 | } | ||
5351 | } else { | ||
5352 | if (saa7111a_configure(ov) < 0) { | ||
5353 | err("Failed to configure SAA7111A"); | ||
5354 | goto error; | ||
5355 | } | ||
5356 | } | ||
5357 | } else { | ||
5358 | err("Detected unsupported OV8xx0 sensor"); | ||
5359 | goto error; | ||
5360 | } | ||
5361 | } else { | ||
5362 | if (ov6xx0_configure(ov) < 0) { | ||
5363 | err("Failed to configure OV6xx0"); | ||
5364 | goto error; | ||
5365 | } | ||
5366 | } | ||
5367 | } else { | ||
5368 | if (ov7xx0_configure(ov) < 0) { | ||
5369 | err("Failed to configure OV7xx0"); | ||
5370 | goto error; | ||
5371 | } | ||
5372 | } | ||
5373 | |||
5374 | return 0; | ||
5375 | |||
5376 | error: | ||
5377 | err("OV511 Config failed"); | ||
5378 | |||
5379 | return -EBUSY; | ||
5380 | } | ||
5381 | |||
5382 | /* This initializes the OV518/OV518+ and the sensor */ | ||
5383 | static int | ||
5384 | ov518_configure(struct usb_ov511 *ov) | ||
5385 | { | ||
5386 | /* For 518 and 518+ */ | ||
5387 | static struct ov511_regvals aRegvalsInit518[] = { | ||
5388 | { OV511_REG_BUS, R51x_SYS_RESET, 0x40 }, | ||
5389 | { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 }, | ||
5390 | { OV511_REG_BUS, R51x_SYS_RESET, 0x3e }, | ||
5391 | { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 }, | ||
5392 | { OV511_REG_BUS, R51x_SYS_RESET, 0x00 }, | ||
5393 | { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 }, | ||
5394 | { OV511_REG_BUS, 0x46, 0x00 }, | ||
5395 | { OV511_REG_BUS, 0x5d, 0x03 }, | ||
5396 | { OV511_DONE_BUS, 0x0, 0x00}, | ||
5397 | }; | ||
5398 | |||
5399 | static struct ov511_regvals aRegvalsNorm518[] = { | ||
5400 | { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, /* Reset */ | ||
5401 | { OV511_REG_BUS, R51x_SYS_SNAP, 0x01 }, /* Enable */ | ||
5402 | { OV511_REG_BUS, 0x31, 0x0f }, | ||
5403 | { OV511_REG_BUS, 0x5d, 0x03 }, | ||
5404 | { OV511_REG_BUS, 0x24, 0x9f }, | ||
5405 | { OV511_REG_BUS, 0x25, 0x90 }, | ||
5406 | { OV511_REG_BUS, 0x20, 0x00 }, | ||
5407 | { OV511_REG_BUS, 0x51, 0x04 }, | ||
5408 | { OV511_REG_BUS, 0x71, 0x19 }, | ||
5409 | { OV511_DONE_BUS, 0x0, 0x00 }, | ||
5410 | }; | ||
5411 | |||
5412 | static struct ov511_regvals aRegvalsNorm518Plus[] = { | ||
5413 | { OV511_REG_BUS, R51x_SYS_SNAP, 0x02 }, /* Reset */ | ||
5414 | { OV511_REG_BUS, R51x_SYS_SNAP, 0x01 }, /* Enable */ | ||
5415 | { OV511_REG_BUS, 0x31, 0x0f }, | ||
5416 | { OV511_REG_BUS, 0x5d, 0x03 }, | ||
5417 | { OV511_REG_BUS, 0x24, 0x9f }, | ||
5418 | { OV511_REG_BUS, 0x25, 0x90 }, | ||
5419 | { OV511_REG_BUS, 0x20, 0x60 }, | ||
5420 | { OV511_REG_BUS, 0x51, 0x02 }, | ||
5421 | { OV511_REG_BUS, 0x71, 0x19 }, | ||
5422 | { OV511_REG_BUS, 0x40, 0xff }, | ||
5423 | { OV511_REG_BUS, 0x41, 0x42 }, | ||
5424 | { OV511_REG_BUS, 0x46, 0x00 }, | ||
5425 | { OV511_REG_BUS, 0x33, 0x04 }, | ||
5426 | { OV511_REG_BUS, 0x21, 0x19 }, | ||
5427 | { OV511_REG_BUS, 0x3f, 0x10 }, | ||
5428 | { OV511_DONE_BUS, 0x0, 0x00 }, | ||
5429 | }; | ||
5430 | |||
5431 | PDEBUG(4, ""); | ||
5432 | |||
5433 | /* First 5 bits of custom ID reg are a revision ID on OV518 */ | ||
5434 | dev_info(&ov->dev->dev, "Device revision %d\n", | ||
5435 | 0x1F & reg_r(ov, R511_SYS_CUST_ID)); | ||
5436 | |||
5437 | /* Give it the default description */ | ||
5438 | ov->desc = symbolic(camlist, 0); | ||
5439 | |||
5440 | if (write_regvals(ov, aRegvalsInit518)) | ||
5441 | goto error; | ||
5442 | |||
5443 | /* Set LED GPIO pin to output mode */ | ||
5444 | if (reg_w_mask(ov, 0x57, 0x00, 0x02) < 0) | ||
5445 | goto error; | ||
5446 | |||
5447 | /* LED is off by default with OV518; have to explicitly turn it on */ | ||
5448 | if (ov->led_policy == LED_OFF || ov->led_policy == LED_AUTO) | ||
5449 | ov51x_led_control(ov, 0); | ||
5450 | else | ||
5451 | ov51x_led_control(ov, 1); | ||
5452 | |||
5453 | /* Don't require compression if dumppix is enabled; otherwise it's | ||
5454 | * required. OV518 has no uncompressed mode, to save RAM. */ | ||
5455 | if (!dumppix && !ov->compress) { | ||
5456 | ov->compress = 1; | ||
5457 | dev_warn(&ov->dev->dev, | ||
5458 | "Compression required with OV518...enabling\n"); | ||
5459 | } | ||
5460 | |||
5461 | if (ov->bridge == BRG_OV518) { | ||
5462 | if (write_regvals(ov, aRegvalsNorm518)) | ||
5463 | goto error; | ||
5464 | } else if (ov->bridge == BRG_OV518PLUS) { | ||
5465 | if (write_regvals(ov, aRegvalsNorm518Plus)) | ||
5466 | goto error; | ||
5467 | } else { | ||
5468 | err("Invalid bridge"); | ||
5469 | } | ||
5470 | |||
5471 | if (reg_w(ov, 0x2f, 0x80) < 0) | ||
5472 | goto error; | ||
5473 | |||
5474 | if (ov518_init_compression(ov)) | ||
5475 | goto error; | ||
5476 | |||
5477 | if (ov->bridge == BRG_OV518) | ||
5478 | { | ||
5479 | struct usb_interface *ifp; | ||
5480 | struct usb_host_interface *alt; | ||
5481 | __u16 mxps = 0; | ||
5482 | |||
5483 | ifp = usb_ifnum_to_if(ov->dev, 0); | ||
5484 | if (ifp) { | ||
5485 | alt = usb_altnum_to_altsetting(ifp, 7); | ||
5486 | if (alt) | ||
5487 | mxps = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); | ||
5488 | } | ||
5489 | |||
5490 | /* Some OV518s have packet numbering by default, some don't */ | ||
5491 | if (mxps == 897) | ||
5492 | ov->packet_numbering = 1; | ||
5493 | else | ||
5494 | ov->packet_numbering = 0; | ||
5495 | } else { | ||
5496 | /* OV518+ has packet numbering turned on by default */ | ||
5497 | ov->packet_numbering = 1; | ||
5498 | } | ||
5499 | |||
5500 | ov518_set_packet_size(ov, 0); | ||
5501 | |||
5502 | ov->snap_enabled = snapshot; | ||
5503 | |||
5504 | /* Test for 76xx */ | ||
5505 | ov->primary_i2c_slave = OV7xx0_SID; | ||
5506 | if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0) | ||
5507 | goto error; | ||
5508 | |||
5509 | /* The OV518 must be more aggressive about sensor detection since | ||
5510 | * I2C write will never fail if the sensor is not present. We have | ||
5511 | * to try to initialize the sensor to detect its presence */ | ||
5512 | |||
5513 | if (init_ov_sensor(ov) < 0) { | ||
5514 | /* Test for 6xx0 */ | ||
5515 | ov->primary_i2c_slave = OV6xx0_SID; | ||
5516 | if (ov51x_set_slave_ids(ov, OV6xx0_SID) < 0) | ||
5517 | goto error; | ||
5518 | |||
5519 | if (init_ov_sensor(ov) < 0) { | ||
5520 | /* Test for 8xx0 */ | ||
5521 | ov->primary_i2c_slave = OV8xx0_SID; | ||
5522 | if (ov51x_set_slave_ids(ov, OV8xx0_SID) < 0) | ||
5523 | goto error; | ||
5524 | |||
5525 | if (init_ov_sensor(ov) < 0) { | ||
5526 | err("Can't determine sensor slave IDs"); | ||
5527 | goto error; | ||
5528 | } else { | ||
5529 | err("Detected unsupported OV8xx0 sensor"); | ||
5530 | goto error; | ||
5531 | } | ||
5532 | } else { | ||
5533 | if (ov6xx0_configure(ov) < 0) { | ||
5534 | err("Failed to configure OV6xx0"); | ||
5535 | goto error; | ||
5536 | } | ||
5537 | } | ||
5538 | } else { | ||
5539 | if (ov7xx0_configure(ov) < 0) { | ||
5540 | err("Failed to configure OV7xx0"); | ||
5541 | goto error; | ||
5542 | } | ||
5543 | } | ||
5544 | |||
5545 | ov->maxwidth = 352; | ||
5546 | ov->maxheight = 288; | ||
5547 | |||
5548 | // The OV518 cannot go as low as the sensor can | ||
5549 | ov->minwidth = 160; | ||
5550 | ov->minheight = 120; | ||
5551 | |||
5552 | return 0; | ||
5553 | |||
5554 | error: | ||
5555 | err("OV518 Config failed"); | ||
5556 | |||
5557 | return -EBUSY; | ||
5558 | } | ||
5559 | |||
5560 | /**************************************************************************** | ||
5561 | * sysfs | ||
5562 | ***************************************************************************/ | ||
5563 | |||
5564 | static inline struct usb_ov511 *cd_to_ov(struct device *cd) | ||
5565 | { | ||
5566 | struct video_device *vdev = to_video_device(cd); | ||
5567 | return video_get_drvdata(vdev); | ||
5568 | } | ||
5569 | |||
5570 | static ssize_t show_custom_id(struct device *cd, | ||
5571 | struct device_attribute *attr, char *buf) | ||
5572 | { | ||
5573 | struct usb_ov511 *ov = cd_to_ov(cd); | ||
5574 | return sprintf(buf, "%d\n", ov->customid); | ||
5575 | } | ||
5576 | static DEVICE_ATTR(custom_id, S_IRUGO, show_custom_id, NULL); | ||
5577 | |||
5578 | static ssize_t show_model(struct device *cd, | ||
5579 | struct device_attribute *attr, char *buf) | ||
5580 | { | ||
5581 | struct usb_ov511 *ov = cd_to_ov(cd); | ||
5582 | return sprintf(buf, "%s\n", ov->desc); | ||
5583 | } | ||
5584 | static DEVICE_ATTR(model, S_IRUGO, show_model, NULL); | ||
5585 | |||
5586 | static ssize_t show_bridge(struct device *cd, | ||
5587 | struct device_attribute *attr, char *buf) | ||
5588 | { | ||
5589 | struct usb_ov511 *ov = cd_to_ov(cd); | ||
5590 | return sprintf(buf, "%s\n", symbolic(brglist, ov->bridge)); | ||
5591 | } | ||
5592 | static DEVICE_ATTR(bridge, S_IRUGO, show_bridge, NULL); | ||
5593 | |||
5594 | static ssize_t show_sensor(struct device *cd, | ||
5595 | struct device_attribute *attr, char *buf) | ||
5596 | { | ||
5597 | struct usb_ov511 *ov = cd_to_ov(cd); | ||
5598 | return sprintf(buf, "%s\n", symbolic(senlist, ov->sensor)); | ||
5599 | } | ||
5600 | static DEVICE_ATTR(sensor, S_IRUGO, show_sensor, NULL); | ||
5601 | |||
5602 | static ssize_t show_brightness(struct device *cd, | ||
5603 | struct device_attribute *attr, char *buf) | ||
5604 | { | ||
5605 | struct usb_ov511 *ov = cd_to_ov(cd); | ||
5606 | unsigned short x; | ||
5607 | |||
5608 | if (!ov->dev) | ||
5609 | return -ENODEV; | ||
5610 | sensor_get_brightness(ov, &x); | ||
5611 | return sprintf(buf, "%d\n", x >> 8); | ||
5612 | } | ||
5613 | static DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); | ||
5614 | |||
5615 | static ssize_t show_saturation(struct device *cd, | ||
5616 | struct device_attribute *attr, char *buf) | ||
5617 | { | ||
5618 | struct usb_ov511 *ov = cd_to_ov(cd); | ||
5619 | unsigned short x; | ||
5620 | |||
5621 | if (!ov->dev) | ||
5622 | return -ENODEV; | ||
5623 | sensor_get_saturation(ov, &x); | ||
5624 | return sprintf(buf, "%d\n", x >> 8); | ||
5625 | } | ||
5626 | static DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); | ||
5627 | |||
5628 | static ssize_t show_contrast(struct device *cd, | ||
5629 | struct device_attribute *attr, char *buf) | ||
5630 | { | ||
5631 | struct usb_ov511 *ov = cd_to_ov(cd); | ||
5632 | unsigned short x; | ||
5633 | |||
5634 | if (!ov->dev) | ||
5635 | return -ENODEV; | ||
5636 | sensor_get_contrast(ov, &x); | ||
5637 | return sprintf(buf, "%d\n", x >> 8); | ||
5638 | } | ||
5639 | static DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); | ||
5640 | |||
5641 | static ssize_t show_hue(struct device *cd, | ||
5642 | struct device_attribute *attr, char *buf) | ||
5643 | { | ||
5644 | struct usb_ov511 *ov = cd_to_ov(cd); | ||
5645 | unsigned short x; | ||
5646 | |||
5647 | if (!ov->dev) | ||
5648 | return -ENODEV; | ||
5649 | sensor_get_hue(ov, &x); | ||
5650 | return sprintf(buf, "%d\n", x >> 8); | ||
5651 | } | ||
5652 | static DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); | ||
5653 | |||
5654 | static ssize_t show_exposure(struct device *cd, | ||
5655 | struct device_attribute *attr, char *buf) | ||
5656 | { | ||
5657 | struct usb_ov511 *ov = cd_to_ov(cd); | ||
5658 | unsigned char exp = 0; | ||
5659 | |||
5660 | if (!ov->dev) | ||
5661 | return -ENODEV; | ||
5662 | sensor_get_exposure(ov, &exp); | ||
5663 | return sprintf(buf, "%d\n", exp); | ||
5664 | } | ||
5665 | static DEVICE_ATTR(exposure, S_IRUGO, show_exposure, NULL); | ||
5666 | |||
5667 | static int ov_create_sysfs(struct video_device *vdev) | ||
5668 | { | ||
5669 | int rc; | ||
5670 | |||
5671 | rc = device_create_file(&vdev->dev, &dev_attr_custom_id); | ||
5672 | if (rc) goto err; | ||
5673 | rc = device_create_file(&vdev->dev, &dev_attr_model); | ||
5674 | if (rc) goto err_id; | ||
5675 | rc = device_create_file(&vdev->dev, &dev_attr_bridge); | ||
5676 | if (rc) goto err_model; | ||
5677 | rc = device_create_file(&vdev->dev, &dev_attr_sensor); | ||
5678 | if (rc) goto err_bridge; | ||
5679 | rc = device_create_file(&vdev->dev, &dev_attr_brightness); | ||
5680 | if (rc) goto err_sensor; | ||
5681 | rc = device_create_file(&vdev->dev, &dev_attr_saturation); | ||
5682 | if (rc) goto err_bright; | ||
5683 | rc = device_create_file(&vdev->dev, &dev_attr_contrast); | ||
5684 | if (rc) goto err_sat; | ||
5685 | rc = device_create_file(&vdev->dev, &dev_attr_hue); | ||
5686 | if (rc) goto err_contrast; | ||
5687 | rc = device_create_file(&vdev->dev, &dev_attr_exposure); | ||
5688 | if (rc) goto err_hue; | ||
5689 | |||
5690 | return 0; | ||
5691 | |||
5692 | err_hue: | ||
5693 | device_remove_file(&vdev->dev, &dev_attr_hue); | ||
5694 | err_contrast: | ||
5695 | device_remove_file(&vdev->dev, &dev_attr_contrast); | ||
5696 | err_sat: | ||
5697 | device_remove_file(&vdev->dev, &dev_attr_saturation); | ||
5698 | err_bright: | ||
5699 | device_remove_file(&vdev->dev, &dev_attr_brightness); | ||
5700 | err_sensor: | ||
5701 | device_remove_file(&vdev->dev, &dev_attr_sensor); | ||
5702 | err_bridge: | ||
5703 | device_remove_file(&vdev->dev, &dev_attr_bridge); | ||
5704 | err_model: | ||
5705 | device_remove_file(&vdev->dev, &dev_attr_model); | ||
5706 | err_id: | ||
5707 | device_remove_file(&vdev->dev, &dev_attr_custom_id); | ||
5708 | err: | ||
5709 | return rc; | ||
5710 | } | ||
5711 | |||
5712 | /**************************************************************************** | ||
5713 | * USB routines | ||
5714 | ***************************************************************************/ | ||
5715 | |||
5716 | static int | ||
5717 | ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
5718 | { | ||
5719 | struct usb_device *dev = interface_to_usbdev(intf); | ||
5720 | struct usb_interface_descriptor *idesc; | ||
5721 | struct usb_ov511 *ov; | ||
5722 | int i, rc, nr; | ||
5723 | |||
5724 | PDEBUG(1, "probing for device..."); | ||
5725 | |||
5726 | /* We don't handle multi-config cameras */ | ||
5727 | if (dev->descriptor.bNumConfigurations != 1) | ||
5728 | return -ENODEV; | ||
5729 | |||
5730 | idesc = &intf->cur_altsetting->desc; | ||
5731 | |||
5732 | if (idesc->bInterfaceClass != 0xFF) | ||
5733 | return -ENODEV; | ||
5734 | if (idesc->bInterfaceSubClass != 0x00) | ||
5735 | return -ENODEV; | ||
5736 | |||
5737 | if ((ov = kzalloc(sizeof(*ov), GFP_KERNEL)) == NULL) { | ||
5738 | err("couldn't kmalloc ov struct"); | ||
5739 | goto error_out; | ||
5740 | } | ||
5741 | |||
5742 | ov->dev = dev; | ||
5743 | ov->iface = idesc->bInterfaceNumber; | ||
5744 | ov->led_policy = led; | ||
5745 | ov->compress = compress; | ||
5746 | ov->lightfreq = lightfreq; | ||
5747 | ov->num_inputs = 1; /* Video decoder init functs. change this */ | ||
5748 | ov->stop_during_set = !fastset; | ||
5749 | ov->backlight = backlight; | ||
5750 | ov->mirror = mirror; | ||
5751 | ov->auto_brt = autobright; | ||
5752 | ov->auto_gain = autogain; | ||
5753 | ov->auto_exp = autoexp; | ||
5754 | |||
5755 | switch (le16_to_cpu(dev->descriptor.idProduct)) { | ||
5756 | case PROD_OV511: | ||
5757 | ov->bridge = BRG_OV511; | ||
5758 | ov->bclass = BCL_OV511; | ||
5759 | break; | ||
5760 | case PROD_OV511PLUS: | ||
5761 | ov->bridge = BRG_OV511PLUS; | ||
5762 | ov->bclass = BCL_OV511; | ||
5763 | break; | ||
5764 | case PROD_OV518: | ||
5765 | ov->bridge = BRG_OV518; | ||
5766 | ov->bclass = BCL_OV518; | ||
5767 | break; | ||
5768 | case PROD_OV518PLUS: | ||
5769 | ov->bridge = BRG_OV518PLUS; | ||
5770 | ov->bclass = BCL_OV518; | ||
5771 | break; | ||
5772 | case PROD_ME2CAM: | ||
5773 | if (le16_to_cpu(dev->descriptor.idVendor) != VEND_MATTEL) | ||
5774 | goto error; | ||
5775 | ov->bridge = BRG_OV511PLUS; | ||
5776 | ov->bclass = BCL_OV511; | ||
5777 | break; | ||
5778 | default: | ||
5779 | err("Unknown product ID 0x%04x", le16_to_cpu(dev->descriptor.idProduct)); | ||
5780 | goto error; | ||
5781 | } | ||
5782 | |||
5783 | dev_info(&intf->dev, "USB %s video device found\n", | ||
5784 | symbolic(brglist, ov->bridge)); | ||
5785 | |||
5786 | init_waitqueue_head(&ov->wq); | ||
5787 | |||
5788 | mutex_init(&ov->lock); /* to 1 == available */ | ||
5789 | mutex_init(&ov->buf_lock); | ||
5790 | mutex_init(&ov->i2c_lock); | ||
5791 | mutex_init(&ov->cbuf_lock); | ||
5792 | |||
5793 | ov->buf_state = BUF_NOT_ALLOCATED; | ||
5794 | |||
5795 | if (usb_make_path(dev, ov->usb_path, OV511_USB_PATH_LEN) < 0) { | ||
5796 | err("usb_make_path error"); | ||
5797 | goto error; | ||
5798 | } | ||
5799 | |||
5800 | /* Allocate control transfer buffer. */ | ||
5801 | /* Must be kmalloc()'ed, for DMA compatibility */ | ||
5802 | ov->cbuf = kmalloc(OV511_CBUF_SIZE, GFP_KERNEL); | ||
5803 | if (!ov->cbuf) | ||
5804 | goto error; | ||
5805 | |||
5806 | if (ov->bclass == BCL_OV518) { | ||
5807 | if (ov518_configure(ov) < 0) | ||
5808 | goto error; | ||
5809 | } else { | ||
5810 | if (ov511_configure(ov) < 0) | ||
5811 | goto error; | ||
5812 | } | ||
5813 | |||
5814 | for (i = 0; i < OV511_NUMFRAMES; i++) { | ||
5815 | ov->frame[i].framenum = i; | ||
5816 | init_waitqueue_head(&ov->frame[i].wq); | ||
5817 | } | ||
5818 | |||
5819 | for (i = 0; i < OV511_NUMSBUF; i++) { | ||
5820 | ov->sbuf[i].ov = ov; | ||
5821 | spin_lock_init(&ov->sbuf[i].lock); | ||
5822 | ov->sbuf[i].n = i; | ||
5823 | } | ||
5824 | |||
5825 | /* Unnecessary? (This is done on open(). Need to make sure variables | ||
5826 | * are properly initialized without this before removing it, though). */ | ||
5827 | if (ov51x_set_default_params(ov) < 0) | ||
5828 | goto error; | ||
5829 | |||
5830 | #ifdef OV511_DEBUG | ||
5831 | if (dump_bridge) { | ||
5832 | if (ov->bclass == BCL_OV511) | ||
5833 | ov511_dump_regs(ov); | ||
5834 | else | ||
5835 | ov518_dump_regs(ov); | ||
5836 | } | ||
5837 | #endif | ||
5838 | |||
5839 | ov->vdev = video_device_alloc(); | ||
5840 | if (!ov->vdev) | ||
5841 | goto error; | ||
5842 | |||
5843 | memcpy(ov->vdev, &vdev_template, sizeof(*ov->vdev)); | ||
5844 | ov->vdev->parent = &intf->dev; | ||
5845 | video_set_drvdata(ov->vdev, ov); | ||
5846 | |||
5847 | mutex_lock(&ov->lock); | ||
5848 | |||
5849 | /* Check to see next free device and mark as used */ | ||
5850 | nr = find_first_zero_bit(&ov511_devused, OV511_MAX_UNIT_VIDEO); | ||
5851 | |||
5852 | /* Registers device */ | ||
5853 | if (unit_video[nr] != 0) | ||
5854 | rc = video_register_device(ov->vdev, VFL_TYPE_GRABBER, | ||
5855 | unit_video[nr]); | ||
5856 | else | ||
5857 | rc = video_register_device(ov->vdev, VFL_TYPE_GRABBER, -1); | ||
5858 | |||
5859 | if (rc < 0) { | ||
5860 | err("video_register_device failed"); | ||
5861 | mutex_unlock(&ov->lock); | ||
5862 | goto error; | ||
5863 | } | ||
5864 | |||
5865 | /* Mark device as used */ | ||
5866 | ov511_devused |= 1 << nr; | ||
5867 | ov->nr = nr; | ||
5868 | |||
5869 | dev_info(&intf->dev, "Device at %s registered to %s\n", | ||
5870 | ov->usb_path, video_device_node_name(ov->vdev)); | ||
5871 | |||
5872 | usb_set_intfdata(intf, ov); | ||
5873 | if (ov_create_sysfs(ov->vdev)) { | ||
5874 | err("ov_create_sysfs failed"); | ||
5875 | ov511_devused &= ~(1 << nr); | ||
5876 | mutex_unlock(&ov->lock); | ||
5877 | goto error; | ||
5878 | } | ||
5879 | |||
5880 | mutex_unlock(&ov->lock); | ||
5881 | |||
5882 | return 0; | ||
5883 | |||
5884 | error: | ||
5885 | if (ov->vdev) { | ||
5886 | if (!video_is_registered(ov->vdev)) | ||
5887 | video_device_release(ov->vdev); | ||
5888 | else | ||
5889 | video_unregister_device(ov->vdev); | ||
5890 | ov->vdev = NULL; | ||
5891 | } | ||
5892 | |||
5893 | if (ov->cbuf) { | ||
5894 | mutex_lock(&ov->cbuf_lock); | ||
5895 | kfree(ov->cbuf); | ||
5896 | ov->cbuf = NULL; | ||
5897 | mutex_unlock(&ov->cbuf_lock); | ||
5898 | } | ||
5899 | |||
5900 | kfree(ov); | ||
5901 | ov = NULL; | ||
5902 | |||
5903 | error_out: | ||
5904 | err("Camera initialization failed"); | ||
5905 | return -EIO; | ||
5906 | } | ||
5907 | |||
5908 | static void | ||
5909 | ov51x_disconnect(struct usb_interface *intf) | ||
5910 | { | ||
5911 | struct usb_ov511 *ov = usb_get_intfdata(intf); | ||
5912 | int n; | ||
5913 | |||
5914 | PDEBUG(3, ""); | ||
5915 | |||
5916 | mutex_lock(&ov->lock); | ||
5917 | usb_set_intfdata (intf, NULL); | ||
5918 | |||
5919 | /* Free device number */ | ||
5920 | ov511_devused &= ~(1 << ov->nr); | ||
5921 | |||
5922 | if (ov->vdev) | ||
5923 | video_unregister_device(ov->vdev); | ||
5924 | |||
5925 | for (n = 0; n < OV511_NUMFRAMES; n++) | ||
5926 | ov->frame[n].grabstate = FRAME_ERROR; | ||
5927 | |||
5928 | ov->curframe = -1; | ||
5929 | |||
5930 | /* This will cause the process to request another frame */ | ||
5931 | for (n = 0; n < OV511_NUMFRAMES; n++) | ||
5932 | wake_up_interruptible(&ov->frame[n].wq); | ||
5933 | |||
5934 | wake_up_interruptible(&ov->wq); | ||
5935 | |||
5936 | ov->streaming = 0; | ||
5937 | ov51x_unlink_isoc(ov); | ||
5938 | mutex_unlock(&ov->lock); | ||
5939 | |||
5940 | ov->dev = NULL; | ||
5941 | |||
5942 | /* Free the memory */ | ||
5943 | if (!ov->user) { | ||
5944 | mutex_lock(&ov->cbuf_lock); | ||
5945 | kfree(ov->cbuf); | ||
5946 | ov->cbuf = NULL; | ||
5947 | mutex_unlock(&ov->cbuf_lock); | ||
5948 | |||
5949 | ov51x_dealloc(ov); | ||
5950 | kfree(ov); | ||
5951 | ov = NULL; | ||
5952 | } | ||
5953 | |||
5954 | PDEBUG(3, "Disconnect complete"); | ||
5955 | } | ||
5956 | |||
5957 | static struct usb_driver ov511_driver = { | ||
5958 | .name = "ov511", | ||
5959 | .id_table = device_table, | ||
5960 | .probe = ov51x_probe, | ||
5961 | .disconnect = ov51x_disconnect | ||
5962 | }; | ||
5963 | |||
5964 | /**************************************************************************** | ||
5965 | * | ||
5966 | * Module routines | ||
5967 | * | ||
5968 | ***************************************************************************/ | ||
5969 | |||
5970 | static int __init | ||
5971 | usb_ov511_init(void) | ||
5972 | { | ||
5973 | int retval; | ||
5974 | |||
5975 | retval = usb_register(&ov511_driver); | ||
5976 | if (retval) | ||
5977 | goto out; | ||
5978 | |||
5979 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" | ||
5980 | DRIVER_DESC "\n"); | ||
5981 | |||
5982 | out: | ||
5983 | return retval; | ||
5984 | } | ||
5985 | |||
5986 | static void __exit | ||
5987 | usb_ov511_exit(void) | ||
5988 | { | ||
5989 | usb_deregister(&ov511_driver); | ||
5990 | printk(KERN_INFO KBUILD_MODNAME ": driver deregistered\n"); | ||
5991 | } | ||
5992 | |||
5993 | module_init(usb_ov511_init); | ||
5994 | module_exit(usb_ov511_exit); | ||
5995 | |||
diff --git a/drivers/media/video/ov511.h b/drivers/media/video/ov511.h deleted file mode 100644 index c450c92468da..000000000000 --- a/drivers/media/video/ov511.h +++ /dev/null | |||
@@ -1,573 +0,0 @@ | |||
1 | #ifndef __LINUX_OV511_H | ||
2 | #define __LINUX_OV511_H | ||
3 | |||
4 | #include <asm/uaccess.h> | ||
5 | #include <linux/videodev.h> | ||
6 | #include <media/v4l2-common.h> | ||
7 | #include <media/v4l2-ioctl.h> | ||
8 | #include <linux/usb.h> | ||
9 | #include <linux/mutex.h> | ||
10 | |||
11 | #define OV511_DEBUG /* Turn on debug messages */ | ||
12 | |||
13 | #ifdef OV511_DEBUG | ||
14 | #define PDEBUG(level, fmt, args...) \ | ||
15 | if (debug >= (level)) \ | ||
16 | printk(KERN_INFO KBUILD_MODNAME "[%s:%d] \n" fmt, \ | ||
17 | __func__, __LINE__ , ## args) | ||
18 | #else | ||
19 | #define PDEBUG(level, fmt, args...) do {} while(0) | ||
20 | #endif | ||
21 | |||
22 | /* This macro restricts an int variable to an inclusive range */ | ||
23 | #define RESTRICT_TO_RANGE(v,mi,ma) { \ | ||
24 | if ((v) < (mi)) (v) = (mi); \ | ||
25 | else if ((v) > (ma)) (v) = (ma); \ | ||
26 | } | ||
27 | |||
28 | /* --------------------------------- */ | ||
29 | /* DEFINES FOR OV511 AND OTHER CHIPS */ | ||
30 | /* --------------------------------- */ | ||
31 | |||
32 | /* USB IDs */ | ||
33 | #define VEND_OMNIVISION 0x05A9 | ||
34 | #define PROD_OV511 0x0511 | ||
35 | #define PROD_OV511PLUS 0xA511 | ||
36 | #define PROD_OV518 0x0518 | ||
37 | #define PROD_OV518PLUS 0xA518 | ||
38 | |||
39 | #define VEND_MATTEL 0x0813 | ||
40 | #define PROD_ME2CAM 0x0002 | ||
41 | |||
42 | /* --------------------------------- */ | ||
43 | /* OV51x REGISTER MNEMONICS */ | ||
44 | /* --------------------------------- */ | ||
45 | |||
46 | /* Camera interface register numbers */ | ||
47 | #define R511_CAM_DELAY 0x10 | ||
48 | #define R511_CAM_EDGE 0x11 | ||
49 | #define R511_CAM_PXCNT 0x12 | ||
50 | #define R511_CAM_LNCNT 0x13 | ||
51 | #define R511_CAM_PXDIV 0x14 | ||
52 | #define R511_CAM_LNDIV 0x15 | ||
53 | #define R511_CAM_UV_EN 0x16 | ||
54 | #define R511_CAM_LINE_MODE 0x17 | ||
55 | #define R511_CAM_OPTS 0x18 | ||
56 | |||
57 | /* Snapshot mode camera interface register numbers */ | ||
58 | #define R511_SNAP_FRAME 0x19 | ||
59 | #define R511_SNAP_PXCNT 0x1A | ||
60 | #define R511_SNAP_LNCNT 0x1B | ||
61 | #define R511_SNAP_PXDIV 0x1C | ||
62 | #define R511_SNAP_LNDIV 0x1D | ||
63 | #define R511_SNAP_UV_EN 0x1E | ||
64 | #define R511_SNAP_OPTS 0x1F | ||
65 | |||
66 | /* DRAM register numbers */ | ||
67 | #define R511_DRAM_FLOW_CTL 0x20 | ||
68 | #define R511_DRAM_ARCP 0x21 | ||
69 | #define R511_DRAM_MRC 0x22 | ||
70 | #define R511_DRAM_RFC 0x23 | ||
71 | |||
72 | /* ISO FIFO register numbers */ | ||
73 | #define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */ | ||
74 | #define R511_FIFO_OPTS 0x31 | ||
75 | |||
76 | /* Parallel IO register numbers */ | ||
77 | #define R511_PIO_OPTS 0x38 | ||
78 | #define R511_PIO_DATA 0x39 | ||
79 | #define R511_PIO_BIST 0x3E | ||
80 | #define R518_GPIO_IN 0x55 /* OV518(+) only */ | ||
81 | #define R518_GPIO_OUT 0x56 /* OV518(+) only */ | ||
82 | #define R518_GPIO_CTL 0x57 /* OV518(+) only */ | ||
83 | #define R518_GPIO_PULSE_IN 0x58 /* OV518(+) only */ | ||
84 | #define R518_GPIO_PULSE_CLEAR 0x59 /* OV518(+) only */ | ||
85 | #define R518_GPIO_PULSE_POL 0x5a /* OV518(+) only */ | ||
86 | #define R518_GPIO_PULSE_EN 0x5b /* OV518(+) only */ | ||
87 | #define R518_GPIO_RESET 0x5c /* OV518(+) only */ | ||
88 | |||
89 | /* I2C registers */ | ||
90 | #define R511_I2C_CTL 0x40 | ||
91 | #define R518_I2C_CTL 0x47 /* OV518(+) only */ | ||
92 | #define R51x_I2C_W_SID 0x41 | ||
93 | #define R51x_I2C_SADDR_3 0x42 | ||
94 | #define R51x_I2C_SADDR_2 0x43 | ||
95 | #define R51x_I2C_R_SID 0x44 | ||
96 | #define R51x_I2C_DATA 0x45 | ||
97 | #define R51x_I2C_CLOCK 0x46 | ||
98 | #define R51x_I2C_TIMEOUT 0x47 | ||
99 | |||
100 | /* I2C snapshot registers */ | ||
101 | #define R511_SI2C_SADDR_3 0x48 | ||
102 | #define R511_SI2C_DATA 0x49 | ||
103 | |||
104 | /* System control registers */ | ||
105 | #define R51x_SYS_RESET 0x50 | ||
106 | /* Reset type definitions */ | ||
107 | #define OV511_RESET_UDC 0x01 | ||
108 | #define OV511_RESET_I2C 0x02 | ||
109 | #define OV511_RESET_FIFO 0x04 | ||
110 | #define OV511_RESET_OMNICE 0x08 | ||
111 | #define OV511_RESET_DRAM 0x10 | ||
112 | #define OV511_RESET_CAM_INT 0x20 | ||
113 | #define OV511_RESET_OV511 0x40 | ||
114 | #define OV511_RESET_NOREGS 0x3F /* All but OV511 & regs */ | ||
115 | #define OV511_RESET_ALL 0x7F | ||
116 | |||
117 | #define R511_SYS_CLOCK_DIV 0x51 | ||
118 | #define R51x_SYS_SNAP 0x52 | ||
119 | #define R51x_SYS_INIT 0x53 | ||
120 | #define R511_SYS_PWR_CLK 0x54 /* OV511+/OV518(+) only */ | ||
121 | #define R511_SYS_LED_CTL 0x55 /* OV511+ only */ | ||
122 | #define R511_SYS_USER 0x5E | ||
123 | #define R511_SYS_CUST_ID 0x5F | ||
124 | |||
125 | /* OmniCE (compression) registers */ | ||
126 | #define R511_COMP_PHY 0x70 | ||
127 | #define R511_COMP_PHUV 0x71 | ||
128 | #define R511_COMP_PVY 0x72 | ||
129 | #define R511_COMP_PVUV 0x73 | ||
130 | #define R511_COMP_QHY 0x74 | ||
131 | #define R511_COMP_QHUV 0x75 | ||
132 | #define R511_COMP_QVY 0x76 | ||
133 | #define R511_COMP_QVUV 0x77 | ||
134 | #define R511_COMP_EN 0x78 | ||
135 | #define R511_COMP_LUT_EN 0x79 | ||
136 | #define R511_COMP_LUT_BEGIN 0x80 | ||
137 | |||
138 | /* --------------------------------- */ | ||
139 | /* ALTERNATE NUMBERS */ | ||
140 | /* --------------------------------- */ | ||
141 | |||
142 | /* Alternate numbers for various max packet sizes (OV511 only) */ | ||
143 | #define OV511_ALT_SIZE_992 0 | ||
144 | #define OV511_ALT_SIZE_993 1 | ||
145 | #define OV511_ALT_SIZE_768 2 | ||
146 | #define OV511_ALT_SIZE_769 3 | ||
147 | #define OV511_ALT_SIZE_512 4 | ||
148 | #define OV511_ALT_SIZE_513 5 | ||
149 | #define OV511_ALT_SIZE_257 6 | ||
150 | #define OV511_ALT_SIZE_0 7 | ||
151 | |||
152 | /* Alternate numbers for various max packet sizes (OV511+ only) */ | ||
153 | #define OV511PLUS_ALT_SIZE_0 0 | ||
154 | #define OV511PLUS_ALT_SIZE_33 1 | ||
155 | #define OV511PLUS_ALT_SIZE_129 2 | ||
156 | #define OV511PLUS_ALT_SIZE_257 3 | ||
157 | #define OV511PLUS_ALT_SIZE_385 4 | ||
158 | #define OV511PLUS_ALT_SIZE_513 5 | ||
159 | #define OV511PLUS_ALT_SIZE_769 6 | ||
160 | #define OV511PLUS_ALT_SIZE_961 7 | ||
161 | |||
162 | /* Alternate numbers for various max packet sizes (OV518(+) only) */ | ||
163 | #define OV518_ALT_SIZE_0 0 | ||
164 | #define OV518_ALT_SIZE_128 1 | ||
165 | #define OV518_ALT_SIZE_256 2 | ||
166 | #define OV518_ALT_SIZE_384 3 | ||
167 | #define OV518_ALT_SIZE_512 4 | ||
168 | #define OV518_ALT_SIZE_640 5 | ||
169 | #define OV518_ALT_SIZE_768 6 | ||
170 | #define OV518_ALT_SIZE_896 7 | ||
171 | |||
172 | /* --------------------------------- */ | ||
173 | /* OV7610 REGISTER MNEMONICS */ | ||
174 | /* --------------------------------- */ | ||
175 | |||
176 | /* OV7610 registers */ | ||
177 | #define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */ | ||
178 | #define OV7610_REG_BLUE 0x01 /* blue channel balance */ | ||
179 | #define OV7610_REG_RED 0x02 /* red channel balance */ | ||
180 | #define OV7610_REG_SAT 0x03 /* saturation */ | ||
181 | /* 04 reserved */ | ||
182 | #define OV7610_REG_CNT 0x05 /* Y contrast */ | ||
183 | #define OV7610_REG_BRT 0x06 /* Y brightness */ | ||
184 | /* 08-0b reserved */ | ||
185 | #define OV7610_REG_BLUE_BIAS 0x0C /* blue channel bias (5:0) */ | ||
186 | #define OV7610_REG_RED_BIAS 0x0D /* read channel bias (5:0) */ | ||
187 | #define OV7610_REG_GAMMA_COEFF 0x0E /* gamma settings */ | ||
188 | #define OV7610_REG_WB_RANGE 0x0F /* AEC/ALC/S-AWB settings */ | ||
189 | #define OV7610_REG_EXP 0x10 /* manual exposure setting */ | ||
190 | #define OV7610_REG_CLOCK 0x11 /* polarity/clock prescaler */ | ||
191 | #define OV7610_REG_COM_A 0x12 /* misc common regs */ | ||
192 | #define OV7610_REG_COM_B 0x13 /* misc common regs */ | ||
193 | #define OV7610_REG_COM_C 0x14 /* misc common regs */ | ||
194 | #define OV7610_REG_COM_D 0x15 /* misc common regs */ | ||
195 | #define OV7610_REG_FIELD_DIVIDE 0x16 /* field interval/mode settings */ | ||
196 | #define OV7610_REG_HWIN_START 0x17 /* horizontal window start */ | ||
197 | #define OV7610_REG_HWIN_END 0x18 /* horizontal window end */ | ||
198 | #define OV7610_REG_VWIN_START 0x19 /* vertical window start */ | ||
199 | #define OV7610_REG_VWIN_END 0x1A /* vertical window end */ | ||
200 | #define OV7610_REG_PIXEL_SHIFT 0x1B /* pixel shift */ | ||
201 | #define OV7610_REG_ID_HIGH 0x1C /* manufacturer ID MSB */ | ||
202 | #define OV7610_REG_ID_LOW 0x1D /* manufacturer ID LSB */ | ||
203 | /* 0e-0f reserved */ | ||
204 | #define OV7610_REG_COM_E 0x20 /* misc common regs */ | ||
205 | #define OV7610_REG_YOFFSET 0x21 /* Y channel offset */ | ||
206 | #define OV7610_REG_UOFFSET 0x22 /* U channel offset */ | ||
207 | /* 23 reserved */ | ||
208 | #define OV7610_REG_ECW 0x24 /* Exposure white level for AEC */ | ||
209 | #define OV7610_REG_ECB 0x25 /* Exposure black level for AEC */ | ||
210 | #define OV7610_REG_COM_F 0x26 /* misc settings */ | ||
211 | #define OV7610_REG_COM_G 0x27 /* misc settings */ | ||
212 | #define OV7610_REG_COM_H 0x28 /* misc settings */ | ||
213 | #define OV7610_REG_COM_I 0x29 /* misc settings */ | ||
214 | #define OV7610_REG_FRAMERATE_H 0x2A /* frame rate MSB + misc */ | ||
215 | #define OV7610_REG_FRAMERATE_L 0x2B /* frame rate LSB */ | ||
216 | #define OV7610_REG_ALC 0x2C /* Auto Level Control settings */ | ||
217 | #define OV7610_REG_COM_J 0x2D /* misc settings */ | ||
218 | #define OV7610_REG_VOFFSET 0x2E /* V channel offset adjustment */ | ||
219 | #define OV7610_REG_ARRAY_BIAS 0x2F /* Array bias -- don't change */ | ||
220 | /* 30-32 reserved */ | ||
221 | #define OV7610_REG_YGAMMA 0x33 /* misc gamma settings (7:6) */ | ||
222 | #define OV7610_REG_BIAS_ADJUST 0x34 /* misc bias settings */ | ||
223 | #define OV7610_REG_COM_L 0x35 /* misc settings */ | ||
224 | /* 36-37 reserved */ | ||
225 | #define OV7610_REG_COM_K 0x38 /* misc registers */ | ||
226 | |||
227 | /* --------------------------------- */ | ||
228 | /* I2C ADDRESSES */ | ||
229 | /* --------------------------------- */ | ||
230 | |||
231 | #define OV7xx0_SID 0x42 | ||
232 | #define OV6xx0_SID 0xC0 | ||
233 | #define OV8xx0_SID 0xA0 | ||
234 | #define KS0127_SID 0xD8 | ||
235 | #define SAA7111A_SID 0x48 | ||
236 | |||
237 | /* --------------------------------- */ | ||
238 | /* MISCELLANEOUS DEFINES */ | ||
239 | /* --------------------------------- */ | ||
240 | |||
241 | #define I2C_CLOCK_PRESCALER 0x03 | ||
242 | |||
243 | #define FRAMES_PER_DESC 10 /* FIXME - What should this be? */ | ||
244 | #define MAX_FRAME_SIZE_PER_DESC 993 /* For statically allocated stuff */ | ||
245 | #define PIXELS_PER_SEG 256 /* Pixels per segment */ | ||
246 | |||
247 | #define OV511_ENDPOINT_ADDRESS 1 /* Isoc endpoint number */ | ||
248 | |||
249 | #define OV511_NUMFRAMES 2 | ||
250 | #if OV511_NUMFRAMES > VIDEO_MAX_FRAME | ||
251 | #error "OV511_NUMFRAMES is too high" | ||
252 | #endif | ||
253 | |||
254 | #define OV511_NUMSBUF 2 | ||
255 | |||
256 | /* Control transfers use up to 4 bytes */ | ||
257 | #define OV511_CBUF_SIZE 4 | ||
258 | |||
259 | /* Size of usb_make_path() buffer */ | ||
260 | #define OV511_USB_PATH_LEN 64 | ||
261 | |||
262 | /* Bridge types */ | ||
263 | enum { | ||
264 | BRG_UNKNOWN, | ||
265 | BRG_OV511, | ||
266 | BRG_OV511PLUS, | ||
267 | BRG_OV518, | ||
268 | BRG_OV518PLUS, | ||
269 | }; | ||
270 | |||
271 | /* Bridge classes */ | ||
272 | enum { | ||
273 | BCL_UNKNOWN, | ||
274 | BCL_OV511, | ||
275 | BCL_OV518, | ||
276 | }; | ||
277 | |||
278 | /* Sensor types */ | ||
279 | enum { | ||
280 | SEN_UNKNOWN, | ||
281 | SEN_OV76BE, | ||
282 | SEN_OV7610, | ||
283 | SEN_OV7620, | ||
284 | SEN_OV7620AE, | ||
285 | SEN_OV6620, | ||
286 | SEN_OV6630, | ||
287 | SEN_OV6630AE, | ||
288 | SEN_OV6630AF, | ||
289 | SEN_OV8600, | ||
290 | SEN_KS0127, | ||
291 | SEN_KS0127B, | ||
292 | SEN_SAA7111A, | ||
293 | }; | ||
294 | |||
295 | enum { | ||
296 | STATE_SCANNING, /* Scanning for start */ | ||
297 | STATE_HEADER, /* Parsing header */ | ||
298 | STATE_LINES, /* Parsing lines */ | ||
299 | }; | ||
300 | |||
301 | /* Buffer states */ | ||
302 | enum { | ||
303 | BUF_NOT_ALLOCATED, | ||
304 | BUF_ALLOCATED, | ||
305 | }; | ||
306 | |||
307 | /* --------- Definition of ioctl interface --------- */ | ||
308 | |||
309 | #define OV511_INTERFACE_VER 101 | ||
310 | |||
311 | /* LED options */ | ||
312 | enum { | ||
313 | LED_OFF, | ||
314 | LED_ON, | ||
315 | LED_AUTO, | ||
316 | }; | ||
317 | |||
318 | /* Raw frame formats */ | ||
319 | enum { | ||
320 | RAWFMT_INVALID, | ||
321 | RAWFMT_YUV400, | ||
322 | RAWFMT_YUV420, | ||
323 | RAWFMT_YUV422, | ||
324 | RAWFMT_GBR422, | ||
325 | }; | ||
326 | |||
327 | struct ov511_i2c_struct { | ||
328 | unsigned char slave; /* Write slave ID (read ID - 1) */ | ||
329 | unsigned char reg; /* Index of register */ | ||
330 | unsigned char value; /* User sets this w/ write, driver does w/ read */ | ||
331 | unsigned char mask; /* Bits to be changed. Not used with read ops */ | ||
332 | }; | ||
333 | |||
334 | /* ioctls */ | ||
335 | #define OV511IOC_WI2C _IOW('v', BASE_VIDIOCPRIVATE + 5, \ | ||
336 | struct ov511_i2c_struct) | ||
337 | #define OV511IOC_RI2C _IOWR('v', BASE_VIDIOCPRIVATE + 6, \ | ||
338 | struct ov511_i2c_struct) | ||
339 | /* ------------- End IOCTL interface -------------- */ | ||
340 | |||
341 | struct usb_ov511; /* Forward declaration */ | ||
342 | |||
343 | struct ov511_sbuf { | ||
344 | struct usb_ov511 *ov; | ||
345 | unsigned char *data; | ||
346 | struct urb *urb; | ||
347 | spinlock_t lock; | ||
348 | int n; | ||
349 | }; | ||
350 | |||
351 | enum { | ||
352 | FRAME_UNUSED, /* Unused (no MCAPTURE) */ | ||
353 | FRAME_READY, /* Ready to start grabbing */ | ||
354 | FRAME_GRABBING, /* In the process of being grabbed into */ | ||
355 | FRAME_DONE, /* Finished grabbing, but not been synced yet */ | ||
356 | FRAME_ERROR, /* Something bad happened while processing */ | ||
357 | }; | ||
358 | |||
359 | struct ov511_regvals { | ||
360 | enum { | ||
361 | OV511_DONE_BUS, | ||
362 | OV511_REG_BUS, | ||
363 | OV511_I2C_BUS, | ||
364 | } bus; | ||
365 | unsigned char reg; | ||
366 | unsigned char val; | ||
367 | }; | ||
368 | |||
369 | struct ov511_frame { | ||
370 | int framenum; /* Index of this frame */ | ||
371 | unsigned char *data; /* Frame buffer */ | ||
372 | unsigned char *tempdata; /* Temp buffer for multi-stage conversions */ | ||
373 | unsigned char *rawdata; /* Raw camera data buffer */ | ||
374 | unsigned char *compbuf; /* Temp buffer for decompressor */ | ||
375 | |||
376 | int depth; /* Bytes per pixel */ | ||
377 | int width; /* Width application is expecting */ | ||
378 | int height; /* Height application is expecting */ | ||
379 | |||
380 | int rawwidth; /* Actual width of frame sent from camera */ | ||
381 | int rawheight; /* Actual height of frame sent from camera */ | ||
382 | |||
383 | int sub_flag; /* Sub-capture mode for this frame? */ | ||
384 | unsigned int format; /* Format for this frame */ | ||
385 | int compressed; /* Is frame compressed? */ | ||
386 | |||
387 | volatile int grabstate; /* State of grabbing */ | ||
388 | int scanstate; /* State of scanning */ | ||
389 | |||
390 | int bytes_recvd; /* Number of image bytes received from camera */ | ||
391 | |||
392 | long bytes_read; /* Amount that has been read() */ | ||
393 | |||
394 | wait_queue_head_t wq; /* Processes waiting */ | ||
395 | |||
396 | int snapshot; /* True if frame was a snapshot */ | ||
397 | }; | ||
398 | |||
399 | #define DECOMP_INTERFACE_VER 4 | ||
400 | |||
401 | /* Compression module operations */ | ||
402 | struct ov51x_decomp_ops { | ||
403 | int (*decomp_400)(unsigned char *, unsigned char *, unsigned char *, | ||
404 | int, int, int); | ||
405 | int (*decomp_420)(unsigned char *, unsigned char *, unsigned char *, | ||
406 | int, int, int); | ||
407 | int (*decomp_422)(unsigned char *, unsigned char *, unsigned char *, | ||
408 | int, int, int); | ||
409 | struct module *owner; | ||
410 | }; | ||
411 | |||
412 | struct usb_ov511 { | ||
413 | struct video_device *vdev; | ||
414 | struct usb_device *dev; | ||
415 | |||
416 | int customid; | ||
417 | char *desc; | ||
418 | unsigned char iface; | ||
419 | char usb_path[OV511_USB_PATH_LEN]; | ||
420 | |||
421 | /* Determined by sensor type */ | ||
422 | int maxwidth; | ||
423 | int maxheight; | ||
424 | int minwidth; | ||
425 | int minheight; | ||
426 | |||
427 | int brightness; | ||
428 | int colour; | ||
429 | int contrast; | ||
430 | int hue; | ||
431 | int whiteness; | ||
432 | int exposure; | ||
433 | int auto_brt; /* Auto brightness enabled flag */ | ||
434 | int auto_gain; /* Auto gain control enabled flag */ | ||
435 | int auto_exp; /* Auto exposure enabled flag */ | ||
436 | int backlight; /* Backlight exposure algorithm flag */ | ||
437 | int mirror; /* Image is reversed horizontally */ | ||
438 | |||
439 | int led_policy; /* LED: off|on|auto; OV511+ only */ | ||
440 | |||
441 | struct mutex lock; /* Serializes user-accessible operations */ | ||
442 | int user; /* user count for exclusive use */ | ||
443 | |||
444 | int streaming; /* Are we streaming Isochronous? */ | ||
445 | int grabbing; /* Are we grabbing? */ | ||
446 | |||
447 | int compress; /* Should the next frame be compressed? */ | ||
448 | int compress_inited; /* Are compression params uploaded? */ | ||
449 | |||
450 | int lightfreq; /* Power (lighting) frequency */ | ||
451 | int bandfilt; /* Banding filter enabled flag */ | ||
452 | |||
453 | unsigned char *fbuf; /* Videodev buffer area */ | ||
454 | unsigned char *tempfbuf; /* Temporary (intermediate) buffer area */ | ||
455 | unsigned char *rawfbuf; /* Raw camera data buffer area */ | ||
456 | |||
457 | int sub_flag; /* Pix Array subcapture on flag */ | ||
458 | int subx; /* Pix Array subcapture x offset */ | ||
459 | int suby; /* Pix Array subcapture y offset */ | ||
460 | int subw; /* Pix Array subcapture width */ | ||
461 | int subh; /* Pix Array subcapture height */ | ||
462 | |||
463 | int curframe; /* Current receiving sbuf */ | ||
464 | struct ov511_frame frame[OV511_NUMFRAMES]; | ||
465 | |||
466 | struct ov511_sbuf sbuf[OV511_NUMSBUF]; | ||
467 | |||
468 | wait_queue_head_t wq; /* Processes waiting */ | ||
469 | |||
470 | int snap_enabled; /* Snapshot mode enabled */ | ||
471 | |||
472 | int bridge; /* Type of bridge (BRG_*) */ | ||
473 | int bclass; /* Class of bridge (BCL_*) */ | ||
474 | int sensor; /* Type of image sensor chip (SEN_*) */ | ||
475 | |||
476 | int packet_size; /* Frame size per isoc desc */ | ||
477 | int packet_numbering; /* Is ISO frame numbering enabled? */ | ||
478 | |||
479 | /* Framebuffer/sbuf management */ | ||
480 | int buf_state; | ||
481 | struct mutex buf_lock; | ||
482 | |||
483 | struct ov51x_decomp_ops *decomp_ops; | ||
484 | |||
485 | /* Stop streaming while changing picture settings */ | ||
486 | int stop_during_set; | ||
487 | |||
488 | int stopped; /* Streaming is temporarily paused */ | ||
489 | |||
490 | /* Video decoder stuff */ | ||
491 | int input; /* Composite, S-VIDEO, etc... */ | ||
492 | int num_inputs; /* Number of inputs */ | ||
493 | int norm; /* NTSC / PAL / SECAM */ | ||
494 | int has_decoder; /* Device has a video decoder */ | ||
495 | int pal; /* Device is designed for PAL resolution */ | ||
496 | |||
497 | /* ov511 device number ID */ | ||
498 | int nr; /* Stores a device number */ | ||
499 | |||
500 | /* I2C interface */ | ||
501 | struct mutex i2c_lock; /* Protect I2C controller regs */ | ||
502 | unsigned char primary_i2c_slave; /* I2C write id of sensor */ | ||
503 | |||
504 | /* Control transaction stuff */ | ||
505 | unsigned char *cbuf; /* Buffer for payload */ | ||
506 | struct mutex cbuf_lock; | ||
507 | }; | ||
508 | |||
509 | /* Used to represent a list of values and their respective symbolic names */ | ||
510 | struct symbolic_list { | ||
511 | int num; | ||
512 | char *name; | ||
513 | }; | ||
514 | |||
515 | #define NOT_DEFINED_STR "Unknown" | ||
516 | |||
517 | /* Returns the name of the matching element in the symbolic_list array. The | ||
518 | * end of the list must be marked with an element that has a NULL name. | ||
519 | */ | ||
520 | static inline char * | ||
521 | symbolic(struct symbolic_list list[], int num) | ||
522 | { | ||
523 | int i; | ||
524 | |||
525 | for (i = 0; list[i].name != NULL; i++) | ||
526 | if (list[i].num == num) | ||
527 | return (list[i].name); | ||
528 | |||
529 | return (NOT_DEFINED_STR); | ||
530 | } | ||
531 | |||
532 | /* Compression stuff */ | ||
533 | |||
534 | #define OV511_QUANTABLESIZE 64 | ||
535 | #define OV518_QUANTABLESIZE 32 | ||
536 | |||
537 | #define OV511_YQUANTABLE { \ | ||
538 | 0, 1, 1, 2, 2, 3, 3, 4, \ | ||
539 | 1, 1, 1, 2, 2, 3, 4, 4, \ | ||
540 | 1, 1, 2, 2, 3, 4, 4, 4, \ | ||
541 | 2, 2, 2, 3, 4, 4, 4, 4, \ | ||
542 | 2, 2, 3, 4, 4, 5, 5, 5, \ | ||
543 | 3, 3, 4, 4, 5, 5, 5, 5, \ | ||
544 | 3, 4, 4, 4, 5, 5, 5, 5, \ | ||
545 | 4, 4, 4, 4, 5, 5, 5, 5 \ | ||
546 | } | ||
547 | |||
548 | #define OV511_UVQUANTABLE { \ | ||
549 | 0, 2, 2, 3, 4, 4, 4, 4, \ | ||
550 | 2, 2, 2, 4, 4, 4, 4, 4, \ | ||
551 | 2, 2, 3, 4, 4, 4, 4, 4, \ | ||
552 | 3, 4, 4, 4, 4, 4, 4, 4, \ | ||
553 | 4, 4, 4, 4, 4, 4, 4, 4, \ | ||
554 | 4, 4, 4, 4, 4, 4, 4, 4, \ | ||
555 | 4, 4, 4, 4, 4, 4, 4, 4, \ | ||
556 | 4, 4, 4, 4, 4, 4, 4, 4 \ | ||
557 | } | ||
558 | |||
559 | #define OV518_YQUANTABLE { \ | ||
560 | 5, 4, 5, 6, 6, 7, 7, 7, \ | ||
561 | 5, 5, 5, 5, 6, 7, 7, 7, \ | ||
562 | 6, 6, 6, 6, 7, 7, 7, 8, \ | ||
563 | 7, 7, 6, 7, 7, 7, 8, 8 \ | ||
564 | } | ||
565 | |||
566 | #define OV518_UVQUANTABLE { \ | ||
567 | 6, 6, 6, 7, 7, 7, 7, 7, \ | ||
568 | 6, 6, 6, 7, 7, 7, 7, 7, \ | ||
569 | 6, 6, 6, 7, 7, 7, 7, 8, \ | ||
570 | 7, 7, 7, 7, 7, 7, 8, 8 \ | ||
571 | } | ||
572 | |||
573 | #endif | ||
diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index 34034a710214..25eb5d637eea 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c | |||
@@ -440,21 +440,21 @@ static const struct regval_list ov772x_vga_regs[] = { | |||
440 | */ | 440 | */ |
441 | static const struct ov772x_color_format ov772x_cfmts[] = { | 441 | static const struct ov772x_color_format ov772x_cfmts[] = { |
442 | { | 442 | { |
443 | .code = V4L2_MBUS_FMT_YUYV8_2X8_LE, | 443 | .code = V4L2_MBUS_FMT_YUYV8_2X8, |
444 | .colorspace = V4L2_COLORSPACE_JPEG, | 444 | .colorspace = V4L2_COLORSPACE_JPEG, |
445 | .dsp3 = 0x0, | 445 | .dsp3 = 0x0, |
446 | .com3 = SWAP_YUV, | 446 | .com3 = SWAP_YUV, |
447 | .com7 = OFMT_YUV, | 447 | .com7 = OFMT_YUV, |
448 | }, | 448 | }, |
449 | { | 449 | { |
450 | .code = V4L2_MBUS_FMT_YVYU8_2X8_LE, | 450 | .code = V4L2_MBUS_FMT_YVYU8_2X8, |
451 | .colorspace = V4L2_COLORSPACE_JPEG, | 451 | .colorspace = V4L2_COLORSPACE_JPEG, |
452 | .dsp3 = UV_ON, | 452 | .dsp3 = UV_ON, |
453 | .com3 = SWAP_YUV, | 453 | .com3 = SWAP_YUV, |
454 | .com7 = OFMT_YUV, | 454 | .com7 = OFMT_YUV, |
455 | }, | 455 | }, |
456 | { | 456 | { |
457 | .code = V4L2_MBUS_FMT_YUYV8_2X8_BE, | 457 | .code = V4L2_MBUS_FMT_UYVY8_2X8, |
458 | .colorspace = V4L2_COLORSPACE_JPEG, | 458 | .colorspace = V4L2_COLORSPACE_JPEG, |
459 | .dsp3 = 0x0, | 459 | .dsp3 = 0x0, |
460 | .com3 = 0x0, | 460 | .com3 = 0x0, |
@@ -960,7 +960,7 @@ static int ov772x_g_fmt(struct v4l2_subdev *sd, | |||
960 | if (!priv->win || !priv->cfmt) { | 960 | if (!priv->win || !priv->cfmt) { |
961 | u32 width = VGA_WIDTH, height = VGA_HEIGHT; | 961 | u32 width = VGA_WIDTH, height = VGA_HEIGHT; |
962 | int ret = ov772x_set_params(client, &width, &height, | 962 | int ret = ov772x_set_params(client, &width, &height, |
963 | V4L2_MBUS_FMT_YUYV8_2X8_LE); | 963 | V4L2_MBUS_FMT_YUYV8_2X8); |
964 | if (ret < 0) | 964 | if (ret < 0) |
965 | return ret; | 965 | return ret; |
966 | } | 966 | } |
diff --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c index 7ce9e05b4781..40cdfab74ccc 100644 --- a/drivers/media/video/ov9640.c +++ b/drivers/media/video/ov9640.c | |||
@@ -155,7 +155,7 @@ static const struct ov9640_reg ov9640_regs_rgb[] = { | |||
155 | }; | 155 | }; |
156 | 156 | ||
157 | static enum v4l2_mbus_pixelcode ov9640_codes[] = { | 157 | static enum v4l2_mbus_pixelcode ov9640_codes[] = { |
158 | V4L2_MBUS_FMT_YUYV8_2X8_BE, | 158 | V4L2_MBUS_FMT_UYVY8_2X8, |
159 | V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, | 159 | V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, |
160 | V4L2_MBUS_FMT_RGB565_2X8_LE, | 160 | V4L2_MBUS_FMT_RGB565_2X8_LE, |
161 | }; | 161 | }; |
@@ -430,7 +430,7 @@ static void ov9640_alter_regs(enum v4l2_mbus_pixelcode code, | |||
430 | { | 430 | { |
431 | switch (code) { | 431 | switch (code) { |
432 | default: | 432 | default: |
433 | case V4L2_MBUS_FMT_YUYV8_2X8_BE: | 433 | case V4L2_MBUS_FMT_UYVY8_2X8: |
434 | alt->com12 = OV9640_COM12_YUV_AVG; | 434 | alt->com12 = OV9640_COM12_YUV_AVG; |
435 | alt->com13 = OV9640_COM13_Y_DELAY_EN | | 435 | alt->com13 = OV9640_COM13_Y_DELAY_EN | |
436 | OV9640_COM13_YUV_DLY(0x01); | 436 | OV9640_COM13_YUV_DLY(0x01); |
@@ -493,7 +493,7 @@ static int ov9640_write_regs(struct i2c_client *client, u32 width, | |||
493 | } | 493 | } |
494 | 494 | ||
495 | /* select color matrix configuration for given color encoding */ | 495 | /* select color matrix configuration for given color encoding */ |
496 | if (code == V4L2_MBUS_FMT_YUYV8_2X8_BE) { | 496 | if (code == V4L2_MBUS_FMT_UYVY8_2X8) { |
497 | matrix_regs = ov9640_regs_yuv; | 497 | matrix_regs = ov9640_regs_yuv; |
498 | matrix_regs_len = ARRAY_SIZE(ov9640_regs_yuv); | 498 | matrix_regs_len = ARRAY_SIZE(ov9640_regs_yuv); |
499 | } else { | 499 | } else { |
@@ -579,8 +579,8 @@ static int ov9640_s_fmt(struct v4l2_subdev *sd, | |||
579 | cspace = V4L2_COLORSPACE_SRGB; | 579 | cspace = V4L2_COLORSPACE_SRGB; |
580 | break; | 580 | break; |
581 | default: | 581 | default: |
582 | code = V4L2_MBUS_FMT_YUYV8_2X8_BE; | 582 | code = V4L2_MBUS_FMT_UYVY8_2X8; |
583 | case V4L2_MBUS_FMT_YUYV8_2X8_BE: | 583 | case V4L2_MBUS_FMT_UYVY8_2X8: |
584 | cspace = V4L2_COLORSPACE_JPEG; | 584 | cspace = V4L2_COLORSPACE_JPEG; |
585 | } | 585 | } |
586 | 586 | ||
@@ -606,8 +606,8 @@ static int ov9640_try_fmt(struct v4l2_subdev *sd, | |||
606 | mf->colorspace = V4L2_COLORSPACE_SRGB; | 606 | mf->colorspace = V4L2_COLORSPACE_SRGB; |
607 | break; | 607 | break; |
608 | default: | 608 | default: |
609 | mf->code = V4L2_MBUS_FMT_YUYV8_2X8_BE; | 609 | mf->code = V4L2_MBUS_FMT_UYVY8_2X8; |
610 | case V4L2_MBUS_FMT_YUYV8_2X8_BE: | 610 | case V4L2_MBUS_FMT_UYVY8_2X8: |
611 | mf->colorspace = V4L2_COLORSPACE_JPEG; | 611 | mf->colorspace = V4L2_COLORSPACE_JPEG; |
612 | } | 612 | } |
613 | 613 | ||
diff --git a/drivers/media/video/ovcamchip/Makefile b/drivers/media/video/ovcamchip/Makefile deleted file mode 100644 index cba4cdf20f49..000000000000 --- a/drivers/media/video/ovcamchip/Makefile +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | ovcamchip-objs := ovcamchip_core.o ov6x20.o ov6x30.o ov7x10.o ov7x20.o \ | ||
2 | ov76be.o | ||
3 | |||
4 | obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip.o | ||
diff --git a/drivers/media/video/ovcamchip/ov6x20.c b/drivers/media/video/ovcamchip/ov6x20.c deleted file mode 100644 index c04130dab127..000000000000 --- a/drivers/media/video/ovcamchip/ov6x20.c +++ /dev/null | |||
@@ -1,414 +0,0 @@ | |||
1 | /* OmniVision OV6620/OV6120 Camera Chip Support Code | ||
2 | * | ||
3 | * Copyright (c) 1999-2004 Mark McClelland <mark@alpha.dyndns.org> | ||
4 | * http://alpha.dyndns.org/ov511/ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied. | ||
10 | */ | ||
11 | |||
12 | #define DEBUG | ||
13 | |||
14 | #include <linux/slab.h> | ||
15 | #include "ovcamchip_priv.h" | ||
16 | |||
17 | /* Registers */ | ||
18 | #define REG_GAIN 0x00 /* gain [5:0] */ | ||
19 | #define REG_BLUE 0x01 /* blue gain */ | ||
20 | #define REG_RED 0x02 /* red gain */ | ||
21 | #define REG_SAT 0x03 /* saturation */ | ||
22 | #define REG_CNT 0x05 /* Y contrast */ | ||
23 | #define REG_BRT 0x06 /* Y brightness */ | ||
24 | #define REG_WB_BLUE 0x0C /* WB blue ratio [5:0] */ | ||
25 | #define REG_WB_RED 0x0D /* WB red ratio [5:0] */ | ||
26 | #define REG_EXP 0x10 /* exposure */ | ||
27 | |||
28 | /* Window parameters */ | ||
29 | #define HWSBASE 0x38 | ||
30 | #define HWEBASE 0x3A | ||
31 | #define VWSBASE 0x05 | ||
32 | #define VWEBASE 0x06 | ||
33 | |||
34 | struct ov6x20 { | ||
35 | int auto_brt; | ||
36 | int auto_exp; | ||
37 | int backlight; | ||
38 | int bandfilt; | ||
39 | int mirror; | ||
40 | }; | ||
41 | |||
42 | /* Initial values for use with OV511/OV511+ cameras */ | ||
43 | static struct ovcamchip_regvals regvals_init_6x20_511[] = { | ||
44 | { 0x12, 0x80 }, /* reset */ | ||
45 | { 0x11, 0x01 }, | ||
46 | { 0x03, 0x60 }, | ||
47 | { 0x05, 0x7f }, /* For when autoadjust is off */ | ||
48 | { 0x07, 0xa8 }, | ||
49 | { 0x0c, 0x24 }, | ||
50 | { 0x0d, 0x24 }, | ||
51 | { 0x0f, 0x15 }, /* COMS */ | ||
52 | { 0x10, 0x75 }, /* AEC Exposure time */ | ||
53 | { 0x12, 0x24 }, /* Enable AGC and AWB */ | ||
54 | { 0x14, 0x04 }, | ||
55 | { 0x16, 0x03 }, | ||
56 | { 0x26, 0xb2 }, /* BLC enable */ | ||
57 | /* 0x28: 0x05 Selects RGB format if RGB on */ | ||
58 | { 0x28, 0x05 }, | ||
59 | { 0x2a, 0x04 }, /* Disable framerate adjust */ | ||
60 | { 0x2d, 0x99 }, | ||
61 | { 0x33, 0xa0 }, /* Color Processing Parameter */ | ||
62 | { 0x34, 0xd2 }, /* Max A/D range */ | ||
63 | { 0x38, 0x8b }, | ||
64 | { 0x39, 0x40 }, | ||
65 | |||
66 | { 0x3c, 0x39 }, /* Enable AEC mode changing */ | ||
67 | { 0x3c, 0x3c }, /* Change AEC mode */ | ||
68 | { 0x3c, 0x24 }, /* Disable AEC mode changing */ | ||
69 | |||
70 | { 0x3d, 0x80 }, | ||
71 | /* These next two registers (0x4a, 0x4b) are undocumented. They | ||
72 | * control the color balance */ | ||
73 | { 0x4a, 0x80 }, | ||
74 | { 0x4b, 0x80 }, | ||
75 | { 0x4d, 0xd2 }, /* This reduces noise a bit */ | ||
76 | { 0x4e, 0xc1 }, | ||
77 | { 0x4f, 0x04 }, | ||
78 | { 0xff, 0xff }, /* END MARKER */ | ||
79 | }; | ||
80 | |||
81 | /* Initial values for use with OV518 cameras */ | ||
82 | static struct ovcamchip_regvals regvals_init_6x20_518[] = { | ||
83 | { 0x12, 0x80 }, /* Do a reset */ | ||
84 | { 0x03, 0xc0 }, /* Saturation */ | ||
85 | { 0x05, 0x8a }, /* Contrast */ | ||
86 | { 0x0c, 0x24 }, /* AWB blue */ | ||
87 | { 0x0d, 0x24 }, /* AWB red */ | ||
88 | { 0x0e, 0x8d }, /* Additional 2x gain */ | ||
89 | { 0x0f, 0x25 }, /* Black expanding level = 1.3V */ | ||
90 | { 0x11, 0x01 }, /* Clock div. */ | ||
91 | { 0x12, 0x24 }, /* Enable AGC and AWB */ | ||
92 | { 0x13, 0x01 }, /* (default) */ | ||
93 | { 0x14, 0x80 }, /* Set reserved bit 7 */ | ||
94 | { 0x15, 0x01 }, /* (default) */ | ||
95 | { 0x16, 0x03 }, /* (default) */ | ||
96 | { 0x17, 0x38 }, /* (default) */ | ||
97 | { 0x18, 0xea }, /* (default) */ | ||
98 | { 0x19, 0x04 }, | ||
99 | { 0x1a, 0x93 }, | ||
100 | { 0x1b, 0x00 }, /* (default) */ | ||
101 | { 0x1e, 0xc4 }, /* (default) */ | ||
102 | { 0x1f, 0x04 }, /* (default) */ | ||
103 | { 0x20, 0x20 }, /* Enable 1st stage aperture correction */ | ||
104 | { 0x21, 0x10 }, /* Y offset */ | ||
105 | { 0x22, 0x88 }, /* U offset */ | ||
106 | { 0x23, 0xc0 }, /* Set XTAL power level */ | ||
107 | { 0x24, 0x53 }, /* AEC bright ratio */ | ||
108 | { 0x25, 0x7a }, /* AEC black ratio */ | ||
109 | { 0x26, 0xb2 }, /* BLC enable */ | ||
110 | { 0x27, 0xa2 }, /* Full output range */ | ||
111 | { 0x28, 0x01 }, /* (default) */ | ||
112 | { 0x29, 0x00 }, /* (default) */ | ||
113 | { 0x2a, 0x84 }, /* (default) */ | ||
114 | { 0x2b, 0xa8 }, /* Set custom frame rate */ | ||
115 | { 0x2c, 0xa0 }, /* (reserved) */ | ||
116 | { 0x2d, 0x95 }, /* Enable banding filter */ | ||
117 | { 0x2e, 0x88 }, /* V offset */ | ||
118 | { 0x33, 0x22 }, /* Luminance gamma on */ | ||
119 | { 0x34, 0xc7 }, /* A/D bias */ | ||
120 | { 0x36, 0x12 }, /* (reserved) */ | ||
121 | { 0x37, 0x63 }, /* (reserved) */ | ||
122 | { 0x38, 0x8b }, /* Quick AEC/AEB */ | ||
123 | { 0x39, 0x00 }, /* (default) */ | ||
124 | { 0x3a, 0x0f }, /* (default) */ | ||
125 | { 0x3b, 0x3c }, /* (default) */ | ||
126 | { 0x3c, 0x5c }, /* AEC controls */ | ||
127 | { 0x3d, 0x80 }, /* Drop 1 (bad) frame when AEC change */ | ||
128 | { 0x3e, 0x80 }, /* (default) */ | ||
129 | { 0x3f, 0x02 }, /* (default) */ | ||
130 | { 0x40, 0x10 }, /* (reserved) */ | ||
131 | { 0x41, 0x10 }, /* (reserved) */ | ||
132 | { 0x42, 0x00 }, /* (reserved) */ | ||
133 | { 0x43, 0x7f }, /* (reserved) */ | ||
134 | { 0x44, 0x80 }, /* (reserved) */ | ||
135 | { 0x45, 0x1c }, /* (reserved) */ | ||
136 | { 0x46, 0x1c }, /* (reserved) */ | ||
137 | { 0x47, 0x80 }, /* (reserved) */ | ||
138 | { 0x48, 0x5f }, /* (reserved) */ | ||
139 | { 0x49, 0x00 }, /* (reserved) */ | ||
140 | { 0x4a, 0x00 }, /* Color balance (undocumented) */ | ||
141 | { 0x4b, 0x80 }, /* Color balance (undocumented) */ | ||
142 | { 0x4c, 0x58 }, /* (reserved) */ | ||
143 | { 0x4d, 0xd2 }, /* U *= .938, V *= .838 */ | ||
144 | { 0x4e, 0xa0 }, /* (default) */ | ||
145 | { 0x4f, 0x04 }, /* UV 3-point average */ | ||
146 | { 0x50, 0xff }, /* (reserved) */ | ||
147 | { 0x51, 0x58 }, /* (reserved) */ | ||
148 | { 0x52, 0xc0 }, /* (reserved) */ | ||
149 | { 0x53, 0x42 }, /* (reserved) */ | ||
150 | { 0x27, 0xa6 }, /* Enable manual offset adj. (reg 21 & 22) */ | ||
151 | { 0x12, 0x20 }, | ||
152 | { 0x12, 0x24 }, | ||
153 | |||
154 | { 0xff, 0xff }, /* END MARKER */ | ||
155 | }; | ||
156 | |||
157 | /* This initializes the OV6x20 camera chip and relevant variables. */ | ||
158 | static int ov6x20_init(struct i2c_client *c) | ||
159 | { | ||
160 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
161 | struct ov6x20 *s; | ||
162 | int rc; | ||
163 | |||
164 | DDEBUG(4, &c->dev, "entered"); | ||
165 | |||
166 | switch (c->adapter->id) { | ||
167 | case I2C_HW_SMBUS_OV511: | ||
168 | rc = ov_write_regvals(c, regvals_init_6x20_511); | ||
169 | break; | ||
170 | case I2C_HW_SMBUS_OV518: | ||
171 | rc = ov_write_regvals(c, regvals_init_6x20_518); | ||
172 | break; | ||
173 | default: | ||
174 | dev_err(&c->dev, "ov6x20: Unsupported adapter\n"); | ||
175 | rc = -ENODEV; | ||
176 | } | ||
177 | |||
178 | if (rc < 0) | ||
179 | return rc; | ||
180 | |||
181 | ov->spriv = s = kzalloc(sizeof *s, GFP_KERNEL); | ||
182 | if (!s) | ||
183 | return -ENOMEM; | ||
184 | |||
185 | s->auto_brt = 1; | ||
186 | s->auto_exp = 1; | ||
187 | |||
188 | return rc; | ||
189 | } | ||
190 | |||
191 | static int ov6x20_free(struct i2c_client *c) | ||
192 | { | ||
193 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
194 | |||
195 | kfree(ov->spriv); | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static int ov6x20_set_control(struct i2c_client *c, | ||
200 | struct ovcamchip_control *ctl) | ||
201 | { | ||
202 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
203 | struct ov6x20 *s = ov->spriv; | ||
204 | int rc; | ||
205 | int v = ctl->value; | ||
206 | |||
207 | switch (ctl->id) { | ||
208 | case OVCAMCHIP_CID_CONT: | ||
209 | rc = ov_write(c, REG_CNT, v >> 8); | ||
210 | break; | ||
211 | case OVCAMCHIP_CID_BRIGHT: | ||
212 | rc = ov_write(c, REG_BRT, v >> 8); | ||
213 | break; | ||
214 | case OVCAMCHIP_CID_SAT: | ||
215 | rc = ov_write(c, REG_SAT, v >> 8); | ||
216 | break; | ||
217 | case OVCAMCHIP_CID_HUE: | ||
218 | rc = ov_write(c, REG_RED, 0xFF - (v >> 8)); | ||
219 | if (rc < 0) | ||
220 | goto out; | ||
221 | |||
222 | rc = ov_write(c, REG_BLUE, v >> 8); | ||
223 | break; | ||
224 | case OVCAMCHIP_CID_EXP: | ||
225 | rc = ov_write(c, REG_EXP, v); | ||
226 | break; | ||
227 | case OVCAMCHIP_CID_FREQ: | ||
228 | { | ||
229 | int sixty = (v == 60); | ||
230 | |||
231 | rc = ov_write(c, 0x2b, sixty?0xa8:0x28); | ||
232 | if (rc < 0) | ||
233 | goto out; | ||
234 | |||
235 | rc = ov_write(c, 0x2a, sixty?0x84:0xa4); | ||
236 | break; | ||
237 | } | ||
238 | case OVCAMCHIP_CID_BANDFILT: | ||
239 | rc = ov_write_mask(c, 0x2d, v?0x04:0x00, 0x04); | ||
240 | s->bandfilt = v; | ||
241 | break; | ||
242 | case OVCAMCHIP_CID_AUTOBRIGHT: | ||
243 | rc = ov_write_mask(c, 0x2d, v?0x10:0x00, 0x10); | ||
244 | s->auto_brt = v; | ||
245 | break; | ||
246 | case OVCAMCHIP_CID_AUTOEXP: | ||
247 | rc = ov_write_mask(c, 0x13, v?0x01:0x00, 0x01); | ||
248 | s->auto_exp = v; | ||
249 | break; | ||
250 | case OVCAMCHIP_CID_BACKLIGHT: | ||
251 | { | ||
252 | rc = ov_write_mask(c, 0x4e, v?0xe0:0xc0, 0xe0); | ||
253 | if (rc < 0) | ||
254 | goto out; | ||
255 | |||
256 | rc = ov_write_mask(c, 0x29, v?0x08:0x00, 0x08); | ||
257 | if (rc < 0) | ||
258 | goto out; | ||
259 | |||
260 | rc = ov_write_mask(c, 0x0e, v?0x80:0x00, 0x80); | ||
261 | s->backlight = v; | ||
262 | break; | ||
263 | } | ||
264 | case OVCAMCHIP_CID_MIRROR: | ||
265 | rc = ov_write_mask(c, 0x12, v?0x40:0x00, 0x40); | ||
266 | s->mirror = v; | ||
267 | break; | ||
268 | default: | ||
269 | DDEBUG(2, &c->dev, "control not supported: %d", ctl->id); | ||
270 | return -EPERM; | ||
271 | } | ||
272 | |||
273 | out: | ||
274 | DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, v, rc); | ||
275 | return rc; | ||
276 | } | ||
277 | |||
278 | static int ov6x20_get_control(struct i2c_client *c, | ||
279 | struct ovcamchip_control *ctl) | ||
280 | { | ||
281 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
282 | struct ov6x20 *s = ov->spriv; | ||
283 | int rc = 0; | ||
284 | unsigned char val = 0; | ||
285 | |||
286 | switch (ctl->id) { | ||
287 | case OVCAMCHIP_CID_CONT: | ||
288 | rc = ov_read(c, REG_CNT, &val); | ||
289 | ctl->value = val << 8; | ||
290 | break; | ||
291 | case OVCAMCHIP_CID_BRIGHT: | ||
292 | rc = ov_read(c, REG_BRT, &val); | ||
293 | ctl->value = val << 8; | ||
294 | break; | ||
295 | case OVCAMCHIP_CID_SAT: | ||
296 | rc = ov_read(c, REG_SAT, &val); | ||
297 | ctl->value = val << 8; | ||
298 | break; | ||
299 | case OVCAMCHIP_CID_HUE: | ||
300 | rc = ov_read(c, REG_BLUE, &val); | ||
301 | ctl->value = val << 8; | ||
302 | break; | ||
303 | case OVCAMCHIP_CID_EXP: | ||
304 | rc = ov_read(c, REG_EXP, &val); | ||
305 | ctl->value = val; | ||
306 | break; | ||
307 | case OVCAMCHIP_CID_BANDFILT: | ||
308 | ctl->value = s->bandfilt; | ||
309 | break; | ||
310 | case OVCAMCHIP_CID_AUTOBRIGHT: | ||
311 | ctl->value = s->auto_brt; | ||
312 | break; | ||
313 | case OVCAMCHIP_CID_AUTOEXP: | ||
314 | ctl->value = s->auto_exp; | ||
315 | break; | ||
316 | case OVCAMCHIP_CID_BACKLIGHT: | ||
317 | ctl->value = s->backlight; | ||
318 | break; | ||
319 | case OVCAMCHIP_CID_MIRROR: | ||
320 | ctl->value = s->mirror; | ||
321 | break; | ||
322 | default: | ||
323 | DDEBUG(2, &c->dev, "control not supported: %d", ctl->id); | ||
324 | return -EPERM; | ||
325 | } | ||
326 | |||
327 | DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, ctl->value, rc); | ||
328 | return rc; | ||
329 | } | ||
330 | |||
331 | static int ov6x20_mode_init(struct i2c_client *c, struct ovcamchip_window *win) | ||
332 | { | ||
333 | /******** QCIF-specific regs ********/ | ||
334 | |||
335 | ov_write(c, 0x14, win->quarter?0x24:0x04); | ||
336 | |||
337 | /******** Palette-specific regs ********/ | ||
338 | |||
339 | /* OV518 needs 8 bit multiplexed in color mode, and 16 bit in B&W */ | ||
340 | if (c->adapter->id == I2C_HW_SMBUS_OV518) { | ||
341 | if (win->format == VIDEO_PALETTE_GREY) | ||
342 | ov_write_mask(c, 0x13, 0x00, 0x20); | ||
343 | else | ||
344 | ov_write_mask(c, 0x13, 0x20, 0x20); | ||
345 | } else { | ||
346 | if (win->format == VIDEO_PALETTE_GREY) | ||
347 | ov_write_mask(c, 0x13, 0x20, 0x20); | ||
348 | else | ||
349 | ov_write_mask(c, 0x13, 0x00, 0x20); | ||
350 | } | ||
351 | |||
352 | /******** Clock programming ********/ | ||
353 | |||
354 | /* The OV6620 needs special handling. This prevents the | ||
355 | * severe banding that normally occurs */ | ||
356 | |||
357 | /* Clock down */ | ||
358 | ov_write(c, 0x2a, 0x04); | ||
359 | |||
360 | ov_write(c, 0x11, win->clockdiv); | ||
361 | |||
362 | ov_write(c, 0x2a, 0x84); | ||
363 | /* This next setting is critical. It seems to improve | ||
364 | * the gain or the contrast. The "reserved" bits seem | ||
365 | * to have some effect in this case. */ | ||
366 | ov_write(c, 0x2d, 0x85); /* FIXME: This messes up banding filter */ | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static int ov6x20_set_window(struct i2c_client *c, struct ovcamchip_window *win) | ||
372 | { | ||
373 | int ret, hwscale, vwscale; | ||
374 | |||
375 | ret = ov6x20_mode_init(c, win); | ||
376 | if (ret < 0) | ||
377 | return ret; | ||
378 | |||
379 | if (win->quarter) { | ||
380 | hwscale = 0; | ||
381 | vwscale = 0; | ||
382 | } else { | ||
383 | hwscale = 1; | ||
384 | vwscale = 1; /* The datasheet says 0; it's wrong */ | ||
385 | } | ||
386 | |||
387 | ov_write(c, 0x17, HWSBASE + (win->x >> hwscale)); | ||
388 | ov_write(c, 0x18, HWEBASE + ((win->x + win->width) >> hwscale)); | ||
389 | ov_write(c, 0x19, VWSBASE + (win->y >> vwscale)); | ||
390 | ov_write(c, 0x1a, VWEBASE + ((win->y + win->height) >> vwscale)); | ||
391 | |||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | static int ov6x20_command(struct i2c_client *c, unsigned int cmd, void *arg) | ||
396 | { | ||
397 | switch (cmd) { | ||
398 | case OVCAMCHIP_CMD_S_CTRL: | ||
399 | return ov6x20_set_control(c, arg); | ||
400 | case OVCAMCHIP_CMD_G_CTRL: | ||
401 | return ov6x20_get_control(c, arg); | ||
402 | case OVCAMCHIP_CMD_S_MODE: | ||
403 | return ov6x20_set_window(c, arg); | ||
404 | default: | ||
405 | DDEBUG(2, &c->dev, "command not supported: %d", cmd); | ||
406 | return -ENOIOCTLCMD; | ||
407 | } | ||
408 | } | ||
409 | |||
410 | struct ovcamchip_ops ov6x20_ops = { | ||
411 | .init = ov6x20_init, | ||
412 | .free = ov6x20_free, | ||
413 | .command = ov6x20_command, | ||
414 | }; | ||
diff --git a/drivers/media/video/ovcamchip/ov6x30.c b/drivers/media/video/ovcamchip/ov6x30.c deleted file mode 100644 index 73b94f51a85a..000000000000 --- a/drivers/media/video/ovcamchip/ov6x30.c +++ /dev/null | |||
@@ -1,373 +0,0 @@ | |||
1 | /* OmniVision OV6630/OV6130 Camera Chip Support Code | ||
2 | * | ||
3 | * Copyright (c) 1999-2004 Mark McClelland <mark@alpha.dyndns.org> | ||
4 | * http://alpha.dyndns.org/ov511/ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied. | ||
10 | */ | ||
11 | |||
12 | #define DEBUG | ||
13 | |||
14 | #include <linux/slab.h> | ||
15 | #include "ovcamchip_priv.h" | ||
16 | |||
17 | /* Registers */ | ||
18 | #define REG_GAIN 0x00 /* gain [5:0] */ | ||
19 | #define REG_BLUE 0x01 /* blue gain */ | ||
20 | #define REG_RED 0x02 /* red gain */ | ||
21 | #define REG_SAT 0x03 /* saturation [7:3] */ | ||
22 | #define REG_CNT 0x05 /* Y contrast [3:0] */ | ||
23 | #define REG_BRT 0x06 /* Y brightness */ | ||
24 | #define REG_SHARP 0x07 /* sharpness */ | ||
25 | #define REG_WB_BLUE 0x0C /* WB blue ratio [5:0] */ | ||
26 | #define REG_WB_RED 0x0D /* WB red ratio [5:0] */ | ||
27 | #define REG_EXP 0x10 /* exposure */ | ||
28 | |||
29 | /* Window parameters */ | ||
30 | #define HWSBASE 0x38 | ||
31 | #define HWEBASE 0x3A | ||
32 | #define VWSBASE 0x05 | ||
33 | #define VWEBASE 0x06 | ||
34 | |||
35 | struct ov6x30 { | ||
36 | int auto_brt; | ||
37 | int auto_exp; | ||
38 | int backlight; | ||
39 | int bandfilt; | ||
40 | int mirror; | ||
41 | }; | ||
42 | |||
43 | static struct ovcamchip_regvals regvals_init_6x30[] = { | ||
44 | { 0x12, 0x80 }, /* reset */ | ||
45 | { 0x00, 0x1f }, /* Gain */ | ||
46 | { 0x01, 0x99 }, /* Blue gain */ | ||
47 | { 0x02, 0x7c }, /* Red gain */ | ||
48 | { 0x03, 0xc0 }, /* Saturation */ | ||
49 | { 0x05, 0x0a }, /* Contrast */ | ||
50 | { 0x06, 0x95 }, /* Brightness */ | ||
51 | { 0x07, 0x2d }, /* Sharpness */ | ||
52 | { 0x0c, 0x20 }, | ||
53 | { 0x0d, 0x20 }, | ||
54 | { 0x0e, 0x20 }, | ||
55 | { 0x0f, 0x05 }, | ||
56 | { 0x10, 0x9a }, /* "exposure check" */ | ||
57 | { 0x11, 0x00 }, /* Pixel clock = fastest */ | ||
58 | { 0x12, 0x24 }, /* Enable AGC and AWB */ | ||
59 | { 0x13, 0x21 }, | ||
60 | { 0x14, 0x80 }, | ||
61 | { 0x15, 0x01 }, | ||
62 | { 0x16, 0x03 }, | ||
63 | { 0x17, 0x38 }, | ||
64 | { 0x18, 0xea }, | ||
65 | { 0x19, 0x04 }, | ||
66 | { 0x1a, 0x93 }, | ||
67 | { 0x1b, 0x00 }, | ||
68 | { 0x1e, 0xc4 }, | ||
69 | { 0x1f, 0x04 }, | ||
70 | { 0x20, 0x20 }, | ||
71 | { 0x21, 0x10 }, | ||
72 | { 0x22, 0x88 }, | ||
73 | { 0x23, 0xc0 }, /* Crystal circuit power level */ | ||
74 | { 0x25, 0x9a }, /* Increase AEC black pixel ratio */ | ||
75 | { 0x26, 0xb2 }, /* BLC enable */ | ||
76 | { 0x27, 0xa2 }, | ||
77 | { 0x28, 0x00 }, | ||
78 | { 0x29, 0x00 }, | ||
79 | { 0x2a, 0x84 }, /* (keep) */ | ||
80 | { 0x2b, 0xa8 }, /* (keep) */ | ||
81 | { 0x2c, 0xa0 }, | ||
82 | { 0x2d, 0x95 }, /* Enable auto-brightness */ | ||
83 | { 0x2e, 0x88 }, | ||
84 | { 0x33, 0x26 }, | ||
85 | { 0x34, 0x03 }, | ||
86 | { 0x36, 0x8f }, | ||
87 | { 0x37, 0x80 }, | ||
88 | { 0x38, 0x83 }, | ||
89 | { 0x39, 0x80 }, | ||
90 | { 0x3a, 0x0f }, | ||
91 | { 0x3b, 0x3c }, | ||
92 | { 0x3c, 0x1a }, | ||
93 | { 0x3d, 0x80 }, | ||
94 | { 0x3e, 0x80 }, | ||
95 | { 0x3f, 0x0e }, | ||
96 | { 0x40, 0x00 }, /* White bal */ | ||
97 | { 0x41, 0x00 }, /* White bal */ | ||
98 | { 0x42, 0x80 }, | ||
99 | { 0x43, 0x3f }, /* White bal */ | ||
100 | { 0x44, 0x80 }, | ||
101 | { 0x45, 0x20 }, | ||
102 | { 0x46, 0x20 }, | ||
103 | { 0x47, 0x80 }, | ||
104 | { 0x48, 0x7f }, | ||
105 | { 0x49, 0x00 }, | ||
106 | { 0x4a, 0x00 }, | ||
107 | { 0x4b, 0x80 }, | ||
108 | { 0x4c, 0xd0 }, | ||
109 | { 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */ | ||
110 | { 0x4e, 0x40 }, | ||
111 | { 0x4f, 0x07 }, /* UV average mode, color killer: strongest */ | ||
112 | { 0x50, 0xff }, | ||
113 | { 0x54, 0x23 }, /* Max AGC gain: 18dB */ | ||
114 | { 0x55, 0xff }, | ||
115 | { 0x56, 0x12 }, | ||
116 | { 0x57, 0x81 }, /* (default) */ | ||
117 | { 0x58, 0x75 }, | ||
118 | { 0x59, 0x01 }, /* AGC dark current compensation: +1 */ | ||
119 | { 0x5a, 0x2c }, | ||
120 | { 0x5b, 0x0f }, /* AWB chrominance levels */ | ||
121 | { 0x5c, 0x10 }, | ||
122 | { 0x3d, 0x80 }, | ||
123 | { 0x27, 0xa6 }, | ||
124 | /* Toggle AWB off and on */ | ||
125 | { 0x12, 0x20 }, | ||
126 | { 0x12, 0x24 }, | ||
127 | |||
128 | { 0xff, 0xff }, /* END MARKER */ | ||
129 | }; | ||
130 | |||
131 | /* This initializes the OV6x30 camera chip and relevant variables. */ | ||
132 | static int ov6x30_init(struct i2c_client *c) | ||
133 | { | ||
134 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
135 | struct ov6x30 *s; | ||
136 | int rc; | ||
137 | |||
138 | DDEBUG(4, &c->dev, "entered"); | ||
139 | |||
140 | rc = ov_write_regvals(c, regvals_init_6x30); | ||
141 | if (rc < 0) | ||
142 | return rc; | ||
143 | |||
144 | ov->spriv = s = kzalloc(sizeof *s, GFP_KERNEL); | ||
145 | if (!s) | ||
146 | return -ENOMEM; | ||
147 | |||
148 | s->auto_brt = 1; | ||
149 | s->auto_exp = 1; | ||
150 | |||
151 | return rc; | ||
152 | } | ||
153 | |||
154 | static int ov6x30_free(struct i2c_client *c) | ||
155 | { | ||
156 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
157 | |||
158 | kfree(ov->spriv); | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static int ov6x30_set_control(struct i2c_client *c, | ||
163 | struct ovcamchip_control *ctl) | ||
164 | { | ||
165 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
166 | struct ov6x30 *s = ov->spriv; | ||
167 | int rc; | ||
168 | int v = ctl->value; | ||
169 | |||
170 | switch (ctl->id) { | ||
171 | case OVCAMCHIP_CID_CONT: | ||
172 | rc = ov_write_mask(c, REG_CNT, v >> 12, 0x0f); | ||
173 | break; | ||
174 | case OVCAMCHIP_CID_BRIGHT: | ||
175 | rc = ov_write(c, REG_BRT, v >> 8); | ||
176 | break; | ||
177 | case OVCAMCHIP_CID_SAT: | ||
178 | rc = ov_write(c, REG_SAT, v >> 8); | ||
179 | break; | ||
180 | case OVCAMCHIP_CID_HUE: | ||
181 | rc = ov_write(c, REG_RED, 0xFF - (v >> 8)); | ||
182 | if (rc < 0) | ||
183 | goto out; | ||
184 | |||
185 | rc = ov_write(c, REG_BLUE, v >> 8); | ||
186 | break; | ||
187 | case OVCAMCHIP_CID_EXP: | ||
188 | rc = ov_write(c, REG_EXP, v); | ||
189 | break; | ||
190 | case OVCAMCHIP_CID_FREQ: | ||
191 | { | ||
192 | int sixty = (v == 60); | ||
193 | |||
194 | rc = ov_write(c, 0x2b, sixty?0xa8:0x28); | ||
195 | if (rc < 0) | ||
196 | goto out; | ||
197 | |||
198 | rc = ov_write(c, 0x2a, sixty?0x84:0xa4); | ||
199 | break; | ||
200 | } | ||
201 | case OVCAMCHIP_CID_BANDFILT: | ||
202 | rc = ov_write_mask(c, 0x2d, v?0x04:0x00, 0x04); | ||
203 | s->bandfilt = v; | ||
204 | break; | ||
205 | case OVCAMCHIP_CID_AUTOBRIGHT: | ||
206 | rc = ov_write_mask(c, 0x2d, v?0x10:0x00, 0x10); | ||
207 | s->auto_brt = v; | ||
208 | break; | ||
209 | case OVCAMCHIP_CID_AUTOEXP: | ||
210 | rc = ov_write_mask(c, 0x28, v?0x00:0x10, 0x10); | ||
211 | s->auto_exp = v; | ||
212 | break; | ||
213 | case OVCAMCHIP_CID_BACKLIGHT: | ||
214 | { | ||
215 | rc = ov_write_mask(c, 0x4e, v?0x80:0x60, 0xe0); | ||
216 | if (rc < 0) | ||
217 | goto out; | ||
218 | |||
219 | rc = ov_write_mask(c, 0x29, v?0x08:0x00, 0x08); | ||
220 | if (rc < 0) | ||
221 | goto out; | ||
222 | |||
223 | rc = ov_write_mask(c, 0x28, v?0x02:0x00, 0x02); | ||
224 | s->backlight = v; | ||
225 | break; | ||
226 | } | ||
227 | case OVCAMCHIP_CID_MIRROR: | ||
228 | rc = ov_write_mask(c, 0x12, v?0x40:0x00, 0x40); | ||
229 | s->mirror = v; | ||
230 | break; | ||
231 | default: | ||
232 | DDEBUG(2, &c->dev, "control not supported: %d", ctl->id); | ||
233 | return -EPERM; | ||
234 | } | ||
235 | |||
236 | out: | ||
237 | DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, v, rc); | ||
238 | return rc; | ||
239 | } | ||
240 | |||
241 | static int ov6x30_get_control(struct i2c_client *c, | ||
242 | struct ovcamchip_control *ctl) | ||
243 | { | ||
244 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
245 | struct ov6x30 *s = ov->spriv; | ||
246 | int rc = 0; | ||
247 | unsigned char val = 0; | ||
248 | |||
249 | switch (ctl->id) { | ||
250 | case OVCAMCHIP_CID_CONT: | ||
251 | rc = ov_read(c, REG_CNT, &val); | ||
252 | ctl->value = (val & 0x0f) << 12; | ||
253 | break; | ||
254 | case OVCAMCHIP_CID_BRIGHT: | ||
255 | rc = ov_read(c, REG_BRT, &val); | ||
256 | ctl->value = val << 8; | ||
257 | break; | ||
258 | case OVCAMCHIP_CID_SAT: | ||
259 | rc = ov_read(c, REG_SAT, &val); | ||
260 | ctl->value = val << 8; | ||
261 | break; | ||
262 | case OVCAMCHIP_CID_HUE: | ||
263 | rc = ov_read(c, REG_BLUE, &val); | ||
264 | ctl->value = val << 8; | ||
265 | break; | ||
266 | case OVCAMCHIP_CID_EXP: | ||
267 | rc = ov_read(c, REG_EXP, &val); | ||
268 | ctl->value = val; | ||
269 | break; | ||
270 | case OVCAMCHIP_CID_BANDFILT: | ||
271 | ctl->value = s->bandfilt; | ||
272 | break; | ||
273 | case OVCAMCHIP_CID_AUTOBRIGHT: | ||
274 | ctl->value = s->auto_brt; | ||
275 | break; | ||
276 | case OVCAMCHIP_CID_AUTOEXP: | ||
277 | ctl->value = s->auto_exp; | ||
278 | break; | ||
279 | case OVCAMCHIP_CID_BACKLIGHT: | ||
280 | ctl->value = s->backlight; | ||
281 | break; | ||
282 | case OVCAMCHIP_CID_MIRROR: | ||
283 | ctl->value = s->mirror; | ||
284 | break; | ||
285 | default: | ||
286 | DDEBUG(2, &c->dev, "control not supported: %d", ctl->id); | ||
287 | return -EPERM; | ||
288 | } | ||
289 | |||
290 | DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, ctl->value, rc); | ||
291 | return rc; | ||
292 | } | ||
293 | |||
294 | static int ov6x30_mode_init(struct i2c_client *c, struct ovcamchip_window *win) | ||
295 | { | ||
296 | /******** QCIF-specific regs ********/ | ||
297 | |||
298 | ov_write_mask(c, 0x14, win->quarter?0x20:0x00, 0x20); | ||
299 | |||
300 | /******** Palette-specific regs ********/ | ||
301 | |||
302 | if (win->format == VIDEO_PALETTE_GREY) { | ||
303 | if (c->adapter->id == I2C_HW_SMBUS_OV518) { | ||
304 | /* Do nothing - we're already in 8-bit mode */ | ||
305 | } else { | ||
306 | ov_write_mask(c, 0x13, 0x20, 0x20); | ||
307 | } | ||
308 | } else { | ||
309 | /* The OV518 needs special treatment. Although both the OV518 | ||
310 | * and the OV6630 support a 16-bit video bus, only the 8 bit Y | ||
311 | * bus is actually used. The UV bus is tied to ground. | ||
312 | * Therefore, the OV6630 needs to be in 8-bit multiplexed | ||
313 | * output mode */ | ||
314 | |||
315 | if (c->adapter->id == I2C_HW_SMBUS_OV518) { | ||
316 | /* Do nothing - we want to stay in 8-bit mode */ | ||
317 | /* Warning: Messing with reg 0x13 breaks OV518 color */ | ||
318 | } else { | ||
319 | ov_write_mask(c, 0x13, 0x00, 0x20); | ||
320 | } | ||
321 | } | ||
322 | |||
323 | /******** Clock programming ********/ | ||
324 | |||
325 | ov_write(c, 0x11, win->clockdiv); | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | static int ov6x30_set_window(struct i2c_client *c, struct ovcamchip_window *win) | ||
331 | { | ||
332 | int ret, hwscale, vwscale; | ||
333 | |||
334 | ret = ov6x30_mode_init(c, win); | ||
335 | if (ret < 0) | ||
336 | return ret; | ||
337 | |||
338 | if (win->quarter) { | ||
339 | hwscale = 0; | ||
340 | vwscale = 0; | ||
341 | } else { | ||
342 | hwscale = 1; | ||
343 | vwscale = 1; /* The datasheet says 0; it's wrong */ | ||
344 | } | ||
345 | |||
346 | ov_write(c, 0x17, HWSBASE + (win->x >> hwscale)); | ||
347 | ov_write(c, 0x18, HWEBASE + ((win->x + win->width) >> hwscale)); | ||
348 | ov_write(c, 0x19, VWSBASE + (win->y >> vwscale)); | ||
349 | ov_write(c, 0x1a, VWEBASE + ((win->y + win->height) >> vwscale)); | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | static int ov6x30_command(struct i2c_client *c, unsigned int cmd, void *arg) | ||
355 | { | ||
356 | switch (cmd) { | ||
357 | case OVCAMCHIP_CMD_S_CTRL: | ||
358 | return ov6x30_set_control(c, arg); | ||
359 | case OVCAMCHIP_CMD_G_CTRL: | ||
360 | return ov6x30_get_control(c, arg); | ||
361 | case OVCAMCHIP_CMD_S_MODE: | ||
362 | return ov6x30_set_window(c, arg); | ||
363 | default: | ||
364 | DDEBUG(2, &c->dev, "command not supported: %d", cmd); | ||
365 | return -ENOIOCTLCMD; | ||
366 | } | ||
367 | } | ||
368 | |||
369 | struct ovcamchip_ops ov6x30_ops = { | ||
370 | .init = ov6x30_init, | ||
371 | .free = ov6x30_free, | ||
372 | .command = ov6x30_command, | ||
373 | }; | ||
diff --git a/drivers/media/video/ovcamchip/ov76be.c b/drivers/media/video/ovcamchip/ov76be.c deleted file mode 100644 index 11f6be924d8b..000000000000 --- a/drivers/media/video/ovcamchip/ov76be.c +++ /dev/null | |||
@@ -1,302 +0,0 @@ | |||
1 | /* OmniVision OV76BE Camera Chip Support Code | ||
2 | * | ||
3 | * Copyright (c) 1999-2004 Mark McClelland <mark@alpha.dyndns.org> | ||
4 | * http://alpha.dyndns.org/ov511/ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied. | ||
10 | */ | ||
11 | |||
12 | #define DEBUG | ||
13 | |||
14 | #include <linux/slab.h> | ||
15 | #include "ovcamchip_priv.h" | ||
16 | |||
17 | /* OV7610 registers: Since the OV76BE is undocumented, we'll settle for these | ||
18 | * for now. */ | ||
19 | #define REG_GAIN 0x00 /* gain [5:0] */ | ||
20 | #define REG_BLUE 0x01 /* blue channel balance */ | ||
21 | #define REG_RED 0x02 /* red channel balance */ | ||
22 | #define REG_SAT 0x03 /* saturation */ | ||
23 | #define REG_CNT 0x05 /* Y contrast */ | ||
24 | #define REG_BRT 0x06 /* Y brightness */ | ||
25 | #define REG_BLUE_BIAS 0x0C /* blue channel bias [5:0] */ | ||
26 | #define REG_RED_BIAS 0x0D /* red channel bias [5:0] */ | ||
27 | #define REG_GAMMA_COEFF 0x0E /* gamma settings */ | ||
28 | #define REG_WB_RANGE 0x0F /* AEC/ALC/S-AWB settings */ | ||
29 | #define REG_EXP 0x10 /* manual exposure setting */ | ||
30 | #define REG_CLOCK 0x11 /* polarity/clock prescaler */ | ||
31 | #define REG_FIELD_DIVIDE 0x16 /* field interval/mode settings */ | ||
32 | #define REG_HWIN_START 0x17 /* horizontal window start */ | ||
33 | #define REG_HWIN_END 0x18 /* horizontal window end */ | ||
34 | #define REG_VWIN_START 0x19 /* vertical window start */ | ||
35 | #define REG_VWIN_END 0x1A /* vertical window end */ | ||
36 | #define REG_PIXEL_SHIFT 0x1B /* pixel shift */ | ||
37 | #define REG_YOFFSET 0x21 /* Y channel offset */ | ||
38 | #define REG_UOFFSET 0x22 /* U channel offset */ | ||
39 | #define REG_ECW 0x24 /* exposure white level for AEC */ | ||
40 | #define REG_ECB 0x25 /* exposure black level for AEC */ | ||
41 | #define REG_FRAMERATE_H 0x2A /* frame rate MSB + misc */ | ||
42 | #define REG_FRAMERATE_L 0x2B /* frame rate LSB */ | ||
43 | #define REG_ALC 0x2C /* Auto Level Control settings */ | ||
44 | #define REG_VOFFSET 0x2E /* V channel offset adjustment */ | ||
45 | #define REG_ARRAY_BIAS 0x2F /* array bias -- don't change */ | ||
46 | #define REG_YGAMMA 0x33 /* misc gamma settings [7:6] */ | ||
47 | #define REG_BIAS_ADJUST 0x34 /* misc bias settings */ | ||
48 | |||
49 | /* Window parameters */ | ||
50 | #define HWSBASE 0x38 | ||
51 | #define HWEBASE 0x3a | ||
52 | #define VWSBASE 0x05 | ||
53 | #define VWEBASE 0x05 | ||
54 | |||
55 | struct ov76be { | ||
56 | int auto_brt; | ||
57 | int auto_exp; | ||
58 | int bandfilt; | ||
59 | int mirror; | ||
60 | }; | ||
61 | |||
62 | /* NOTE: These are the same as the 7x10 settings, but should eventually be | ||
63 | * optimized for the OV76BE */ | ||
64 | static struct ovcamchip_regvals regvals_init_76be[] = { | ||
65 | { 0x10, 0xff }, | ||
66 | { 0x16, 0x03 }, | ||
67 | { 0x28, 0x24 }, | ||
68 | { 0x2b, 0xac }, | ||
69 | { 0x12, 0x00 }, | ||
70 | { 0x38, 0x81 }, | ||
71 | { 0x28, 0x24 }, /* 0c */ | ||
72 | { 0x0f, 0x85 }, /* lg's setting */ | ||
73 | { 0x15, 0x01 }, | ||
74 | { 0x20, 0x1c }, | ||
75 | { 0x23, 0x2a }, | ||
76 | { 0x24, 0x10 }, | ||
77 | { 0x25, 0x8a }, | ||
78 | { 0x26, 0xa2 }, | ||
79 | { 0x27, 0xc2 }, | ||
80 | { 0x2a, 0x04 }, | ||
81 | { 0x2c, 0xfe }, | ||
82 | { 0x2d, 0x93 }, | ||
83 | { 0x30, 0x71 }, | ||
84 | { 0x31, 0x60 }, | ||
85 | { 0x32, 0x26 }, | ||
86 | { 0x33, 0x20 }, | ||
87 | { 0x34, 0x48 }, | ||
88 | { 0x12, 0x24 }, | ||
89 | { 0x11, 0x01 }, | ||
90 | { 0x0c, 0x24 }, | ||
91 | { 0x0d, 0x24 }, | ||
92 | { 0xff, 0xff }, /* END MARKER */ | ||
93 | }; | ||
94 | |||
95 | /* This initializes the OV76be camera chip and relevant variables. */ | ||
96 | static int ov76be_init(struct i2c_client *c) | ||
97 | { | ||
98 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
99 | struct ov76be *s; | ||
100 | int rc; | ||
101 | |||
102 | DDEBUG(4, &c->dev, "entered"); | ||
103 | |||
104 | rc = ov_write_regvals(c, regvals_init_76be); | ||
105 | if (rc < 0) | ||
106 | return rc; | ||
107 | |||
108 | ov->spriv = s = kzalloc(sizeof *s, GFP_KERNEL); | ||
109 | if (!s) | ||
110 | return -ENOMEM; | ||
111 | |||
112 | s->auto_brt = 1; | ||
113 | s->auto_exp = 1; | ||
114 | |||
115 | return rc; | ||
116 | } | ||
117 | |||
118 | static int ov76be_free(struct i2c_client *c) | ||
119 | { | ||
120 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
121 | |||
122 | kfree(ov->spriv); | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static int ov76be_set_control(struct i2c_client *c, | ||
127 | struct ovcamchip_control *ctl) | ||
128 | { | ||
129 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
130 | struct ov76be *s = ov->spriv; | ||
131 | int rc; | ||
132 | int v = ctl->value; | ||
133 | |||
134 | switch (ctl->id) { | ||
135 | case OVCAMCHIP_CID_BRIGHT: | ||
136 | rc = ov_write(c, REG_BRT, v >> 8); | ||
137 | break; | ||
138 | case OVCAMCHIP_CID_SAT: | ||
139 | rc = ov_write(c, REG_SAT, v >> 8); | ||
140 | break; | ||
141 | case OVCAMCHIP_CID_EXP: | ||
142 | rc = ov_write(c, REG_EXP, v); | ||
143 | break; | ||
144 | case OVCAMCHIP_CID_FREQ: | ||
145 | { | ||
146 | int sixty = (v == 60); | ||
147 | |||
148 | rc = ov_write_mask(c, 0x2a, sixty?0x00:0x80, 0x80); | ||
149 | if (rc < 0) | ||
150 | goto out; | ||
151 | |||
152 | rc = ov_write(c, 0x2b, sixty?0x00:0xac); | ||
153 | if (rc < 0) | ||
154 | goto out; | ||
155 | |||
156 | rc = ov_write_mask(c, 0x76, 0x01, 0x01); | ||
157 | break; | ||
158 | } | ||
159 | case OVCAMCHIP_CID_BANDFILT: | ||
160 | rc = ov_write_mask(c, 0x2d, v?0x04:0x00, 0x04); | ||
161 | s->bandfilt = v; | ||
162 | break; | ||
163 | case OVCAMCHIP_CID_AUTOBRIGHT: | ||
164 | rc = ov_write_mask(c, 0x2d, v?0x10:0x00, 0x10); | ||
165 | s->auto_brt = v; | ||
166 | break; | ||
167 | case OVCAMCHIP_CID_AUTOEXP: | ||
168 | rc = ov_write_mask(c, 0x13, v?0x01:0x00, 0x01); | ||
169 | s->auto_exp = v; | ||
170 | break; | ||
171 | case OVCAMCHIP_CID_MIRROR: | ||
172 | rc = ov_write_mask(c, 0x12, v?0x40:0x00, 0x40); | ||
173 | s->mirror = v; | ||
174 | break; | ||
175 | default: | ||
176 | DDEBUG(2, &c->dev, "control not supported: %d", ctl->id); | ||
177 | return -EPERM; | ||
178 | } | ||
179 | |||
180 | out: | ||
181 | DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, v, rc); | ||
182 | return rc; | ||
183 | } | ||
184 | |||
185 | static int ov76be_get_control(struct i2c_client *c, | ||
186 | struct ovcamchip_control *ctl) | ||
187 | { | ||
188 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
189 | struct ov76be *s = ov->spriv; | ||
190 | int rc = 0; | ||
191 | unsigned char val = 0; | ||
192 | |||
193 | switch (ctl->id) { | ||
194 | case OVCAMCHIP_CID_BRIGHT: | ||
195 | rc = ov_read(c, REG_BRT, &val); | ||
196 | ctl->value = val << 8; | ||
197 | break; | ||
198 | case OVCAMCHIP_CID_SAT: | ||
199 | rc = ov_read(c, REG_SAT, &val); | ||
200 | ctl->value = val << 8; | ||
201 | break; | ||
202 | case OVCAMCHIP_CID_EXP: | ||
203 | rc = ov_read(c, REG_EXP, &val); | ||
204 | ctl->value = val; | ||
205 | break; | ||
206 | case OVCAMCHIP_CID_BANDFILT: | ||
207 | ctl->value = s->bandfilt; | ||
208 | break; | ||
209 | case OVCAMCHIP_CID_AUTOBRIGHT: | ||
210 | ctl->value = s->auto_brt; | ||
211 | break; | ||
212 | case OVCAMCHIP_CID_AUTOEXP: | ||
213 | ctl->value = s->auto_exp; | ||
214 | break; | ||
215 | case OVCAMCHIP_CID_MIRROR: | ||
216 | ctl->value = s->mirror; | ||
217 | break; | ||
218 | default: | ||
219 | DDEBUG(2, &c->dev, "control not supported: %d", ctl->id); | ||
220 | return -EPERM; | ||
221 | } | ||
222 | |||
223 | DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, ctl->value, rc); | ||
224 | return rc; | ||
225 | } | ||
226 | |||
227 | static int ov76be_mode_init(struct i2c_client *c, struct ovcamchip_window *win) | ||
228 | { | ||
229 | int qvga = win->quarter; | ||
230 | |||
231 | /******** QVGA-specific regs ********/ | ||
232 | |||
233 | ov_write(c, 0x14, qvga?0xa4:0x84); | ||
234 | |||
235 | /******** Palette-specific regs ********/ | ||
236 | |||
237 | if (win->format == VIDEO_PALETTE_GREY) { | ||
238 | ov_write_mask(c, 0x0e, 0x40, 0x40); | ||
239 | ov_write_mask(c, 0x13, 0x20, 0x20); | ||
240 | } else { | ||
241 | ov_write_mask(c, 0x0e, 0x00, 0x40); | ||
242 | ov_write_mask(c, 0x13, 0x00, 0x20); | ||
243 | } | ||
244 | |||
245 | /******** Clock programming ********/ | ||
246 | |||
247 | ov_write(c, 0x11, win->clockdiv); | ||
248 | |||
249 | /******** Resolution-specific ********/ | ||
250 | |||
251 | if (win->width == 640 && win->height == 480) | ||
252 | ov_write(c, 0x35, 0x9e); | ||
253 | else | ||
254 | ov_write(c, 0x35, 0x1e); | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static int ov76be_set_window(struct i2c_client *c, struct ovcamchip_window *win) | ||
260 | { | ||
261 | int ret, hwscale, vwscale; | ||
262 | |||
263 | ret = ov76be_mode_init(c, win); | ||
264 | if (ret < 0) | ||
265 | return ret; | ||
266 | |||
267 | if (win->quarter) { | ||
268 | hwscale = 1; | ||
269 | vwscale = 0; | ||
270 | } else { | ||
271 | hwscale = 2; | ||
272 | vwscale = 1; | ||
273 | } | ||
274 | |||
275 | ov_write(c, 0x17, HWSBASE + (win->x >> hwscale)); | ||
276 | ov_write(c, 0x18, HWEBASE + ((win->x + win->width) >> hwscale)); | ||
277 | ov_write(c, 0x19, VWSBASE + (win->y >> vwscale)); | ||
278 | ov_write(c, 0x1a, VWEBASE + ((win->y + win->height) >> vwscale)); | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static int ov76be_command(struct i2c_client *c, unsigned int cmd, void *arg) | ||
284 | { | ||
285 | switch (cmd) { | ||
286 | case OVCAMCHIP_CMD_S_CTRL: | ||
287 | return ov76be_set_control(c, arg); | ||
288 | case OVCAMCHIP_CMD_G_CTRL: | ||
289 | return ov76be_get_control(c, arg); | ||
290 | case OVCAMCHIP_CMD_S_MODE: | ||
291 | return ov76be_set_window(c, arg); | ||
292 | default: | ||
293 | DDEBUG(2, &c->dev, "command not supported: %d", cmd); | ||
294 | return -ENOIOCTLCMD; | ||
295 | } | ||
296 | } | ||
297 | |||
298 | struct ovcamchip_ops ov76be_ops = { | ||
299 | .init = ov76be_init, | ||
300 | .free = ov76be_free, | ||
301 | .command = ov76be_command, | ||
302 | }; | ||
diff --git a/drivers/media/video/ovcamchip/ov7x10.c b/drivers/media/video/ovcamchip/ov7x10.c deleted file mode 100644 index 5206e7913924..000000000000 --- a/drivers/media/video/ovcamchip/ov7x10.c +++ /dev/null | |||
@@ -1,334 +0,0 @@ | |||
1 | /* OmniVision OV7610/OV7110 Camera Chip Support Code | ||
2 | * | ||
3 | * Copyright (c) 1999-2004 Mark McClelland <mark@alpha.dyndns.org> | ||
4 | * http://alpha.dyndns.org/ov511/ | ||
5 | * | ||
6 | * Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied. | ||
12 | */ | ||
13 | |||
14 | #define DEBUG | ||
15 | |||
16 | #include <linux/slab.h> | ||
17 | #include "ovcamchip_priv.h" | ||
18 | |||
19 | /* Registers */ | ||
20 | #define REG_GAIN 0x00 /* gain [5:0] */ | ||
21 | #define REG_BLUE 0x01 /* blue channel balance */ | ||
22 | #define REG_RED 0x02 /* red channel balance */ | ||
23 | #define REG_SAT 0x03 /* saturation */ | ||
24 | #define REG_CNT 0x05 /* Y contrast */ | ||
25 | #define REG_BRT 0x06 /* Y brightness */ | ||
26 | #define REG_BLUE_BIAS 0x0C /* blue channel bias [5:0] */ | ||
27 | #define REG_RED_BIAS 0x0D /* red channel bias [5:0] */ | ||
28 | #define REG_GAMMA_COEFF 0x0E /* gamma settings */ | ||
29 | #define REG_WB_RANGE 0x0F /* AEC/ALC/S-AWB settings */ | ||
30 | #define REG_EXP 0x10 /* manual exposure setting */ | ||
31 | #define REG_CLOCK 0x11 /* polarity/clock prescaler */ | ||
32 | #define REG_FIELD_DIVIDE 0x16 /* field interval/mode settings */ | ||
33 | #define REG_HWIN_START 0x17 /* horizontal window start */ | ||
34 | #define REG_HWIN_END 0x18 /* horizontal window end */ | ||
35 | #define REG_VWIN_START 0x19 /* vertical window start */ | ||
36 | #define REG_VWIN_END 0x1A /* vertical window end */ | ||
37 | #define REG_PIXEL_SHIFT 0x1B /* pixel shift */ | ||
38 | #define REG_YOFFSET 0x21 /* Y channel offset */ | ||
39 | #define REG_UOFFSET 0x22 /* U channel offset */ | ||
40 | #define REG_ECW 0x24 /* exposure white level for AEC */ | ||
41 | #define REG_ECB 0x25 /* exposure black level for AEC */ | ||
42 | #define REG_FRAMERATE_H 0x2A /* frame rate MSB + misc */ | ||
43 | #define REG_FRAMERATE_L 0x2B /* frame rate LSB */ | ||
44 | #define REG_ALC 0x2C /* Auto Level Control settings */ | ||
45 | #define REG_VOFFSET 0x2E /* V channel offset adjustment */ | ||
46 | #define REG_ARRAY_BIAS 0x2F /* array bias -- don't change */ | ||
47 | #define REG_YGAMMA 0x33 /* misc gamma settings [7:6] */ | ||
48 | #define REG_BIAS_ADJUST 0x34 /* misc bias settings */ | ||
49 | |||
50 | /* Window parameters */ | ||
51 | #define HWSBASE 0x38 | ||
52 | #define HWEBASE 0x3a | ||
53 | #define VWSBASE 0x05 | ||
54 | #define VWEBASE 0x05 | ||
55 | |||
56 | struct ov7x10 { | ||
57 | int auto_brt; | ||
58 | int auto_exp; | ||
59 | int bandfilt; | ||
60 | int mirror; | ||
61 | }; | ||
62 | |||
63 | /* Lawrence Glaister <lg@jfm.bc.ca> reports: | ||
64 | * | ||
65 | * Register 0x0f in the 7610 has the following effects: | ||
66 | * | ||
67 | * 0x85 (AEC method 1): Best overall, good contrast range | ||
68 | * 0x45 (AEC method 2): Very overexposed | ||
69 | * 0xa5 (spec sheet default): Ok, but the black level is | ||
70 | * shifted resulting in loss of contrast | ||
71 | * 0x05 (old driver setting): very overexposed, too much | ||
72 | * contrast | ||
73 | */ | ||
74 | static struct ovcamchip_regvals regvals_init_7x10[] = { | ||
75 | { 0x10, 0xff }, | ||
76 | { 0x16, 0x03 }, | ||
77 | { 0x28, 0x24 }, | ||
78 | { 0x2b, 0xac }, | ||
79 | { 0x12, 0x00 }, | ||
80 | { 0x38, 0x81 }, | ||
81 | { 0x28, 0x24 }, /* 0c */ | ||
82 | { 0x0f, 0x85 }, /* lg's setting */ | ||
83 | { 0x15, 0x01 }, | ||
84 | { 0x20, 0x1c }, | ||
85 | { 0x23, 0x2a }, | ||
86 | { 0x24, 0x10 }, | ||
87 | { 0x25, 0x8a }, | ||
88 | { 0x26, 0xa2 }, | ||
89 | { 0x27, 0xc2 }, | ||
90 | { 0x2a, 0x04 }, | ||
91 | { 0x2c, 0xfe }, | ||
92 | { 0x2d, 0x93 }, | ||
93 | { 0x30, 0x71 }, | ||
94 | { 0x31, 0x60 }, | ||
95 | { 0x32, 0x26 }, | ||
96 | { 0x33, 0x20 }, | ||
97 | { 0x34, 0x48 }, | ||
98 | { 0x12, 0x24 }, | ||
99 | { 0x11, 0x01 }, | ||
100 | { 0x0c, 0x24 }, | ||
101 | { 0x0d, 0x24 }, | ||
102 | { 0xff, 0xff }, /* END MARKER */ | ||
103 | }; | ||
104 | |||
105 | /* This initializes the OV7x10 camera chip and relevant variables. */ | ||
106 | static int ov7x10_init(struct i2c_client *c) | ||
107 | { | ||
108 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
109 | struct ov7x10 *s; | ||
110 | int rc; | ||
111 | |||
112 | DDEBUG(4, &c->dev, "entered"); | ||
113 | |||
114 | rc = ov_write_regvals(c, regvals_init_7x10); | ||
115 | if (rc < 0) | ||
116 | return rc; | ||
117 | |||
118 | ov->spriv = s = kzalloc(sizeof *s, GFP_KERNEL); | ||
119 | if (!s) | ||
120 | return -ENOMEM; | ||
121 | |||
122 | s->auto_brt = 1; | ||
123 | s->auto_exp = 1; | ||
124 | |||
125 | return rc; | ||
126 | } | ||
127 | |||
128 | static int ov7x10_free(struct i2c_client *c) | ||
129 | { | ||
130 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
131 | |||
132 | kfree(ov->spriv); | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static int ov7x10_set_control(struct i2c_client *c, | ||
137 | struct ovcamchip_control *ctl) | ||
138 | { | ||
139 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
140 | struct ov7x10 *s = ov->spriv; | ||
141 | int rc; | ||
142 | int v = ctl->value; | ||
143 | |||
144 | switch (ctl->id) { | ||
145 | case OVCAMCHIP_CID_CONT: | ||
146 | rc = ov_write(c, REG_CNT, v >> 8); | ||
147 | break; | ||
148 | case OVCAMCHIP_CID_BRIGHT: | ||
149 | rc = ov_write(c, REG_BRT, v >> 8); | ||
150 | break; | ||
151 | case OVCAMCHIP_CID_SAT: | ||
152 | rc = ov_write(c, REG_SAT, v >> 8); | ||
153 | break; | ||
154 | case OVCAMCHIP_CID_HUE: | ||
155 | rc = ov_write(c, REG_RED, 0xFF - (v >> 8)); | ||
156 | if (rc < 0) | ||
157 | goto out; | ||
158 | |||
159 | rc = ov_write(c, REG_BLUE, v >> 8); | ||
160 | break; | ||
161 | case OVCAMCHIP_CID_EXP: | ||
162 | rc = ov_write(c, REG_EXP, v); | ||
163 | break; | ||
164 | case OVCAMCHIP_CID_FREQ: | ||
165 | { | ||
166 | int sixty = (v == 60); | ||
167 | |||
168 | rc = ov_write_mask(c, 0x2a, sixty?0x00:0x80, 0x80); | ||
169 | if (rc < 0) | ||
170 | goto out; | ||
171 | |||
172 | rc = ov_write(c, 0x2b, sixty?0x00:0xac); | ||
173 | if (rc < 0) | ||
174 | goto out; | ||
175 | |||
176 | rc = ov_write_mask(c, 0x13, 0x10, 0x10); | ||
177 | if (rc < 0) | ||
178 | goto out; | ||
179 | |||
180 | rc = ov_write_mask(c, 0x13, 0x00, 0x10); | ||
181 | break; | ||
182 | } | ||
183 | case OVCAMCHIP_CID_BANDFILT: | ||
184 | rc = ov_write_mask(c, 0x2d, v?0x04:0x00, 0x04); | ||
185 | s->bandfilt = v; | ||
186 | break; | ||
187 | case OVCAMCHIP_CID_AUTOBRIGHT: | ||
188 | rc = ov_write_mask(c, 0x2d, v?0x10:0x00, 0x10); | ||
189 | s->auto_brt = v; | ||
190 | break; | ||
191 | case OVCAMCHIP_CID_AUTOEXP: | ||
192 | rc = ov_write_mask(c, 0x29, v?0x00:0x80, 0x80); | ||
193 | s->auto_exp = v; | ||
194 | break; | ||
195 | case OVCAMCHIP_CID_MIRROR: | ||
196 | rc = ov_write_mask(c, 0x12, v?0x40:0x00, 0x40); | ||
197 | s->mirror = v; | ||
198 | break; | ||
199 | default: | ||
200 | DDEBUG(2, &c->dev, "control not supported: %d", ctl->id); | ||
201 | return -EPERM; | ||
202 | } | ||
203 | |||
204 | out: | ||
205 | DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, v, rc); | ||
206 | return rc; | ||
207 | } | ||
208 | |||
209 | static int ov7x10_get_control(struct i2c_client *c, | ||
210 | struct ovcamchip_control *ctl) | ||
211 | { | ||
212 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
213 | struct ov7x10 *s = ov->spriv; | ||
214 | int rc = 0; | ||
215 | unsigned char val = 0; | ||
216 | |||
217 | switch (ctl->id) { | ||
218 | case OVCAMCHIP_CID_CONT: | ||
219 | rc = ov_read(c, REG_CNT, &val); | ||
220 | ctl->value = val << 8; | ||
221 | break; | ||
222 | case OVCAMCHIP_CID_BRIGHT: | ||
223 | rc = ov_read(c, REG_BRT, &val); | ||
224 | ctl->value = val << 8; | ||
225 | break; | ||
226 | case OVCAMCHIP_CID_SAT: | ||
227 | rc = ov_read(c, REG_SAT, &val); | ||
228 | ctl->value = val << 8; | ||
229 | break; | ||
230 | case OVCAMCHIP_CID_HUE: | ||
231 | rc = ov_read(c, REG_BLUE, &val); | ||
232 | ctl->value = val << 8; | ||
233 | break; | ||
234 | case OVCAMCHIP_CID_EXP: | ||
235 | rc = ov_read(c, REG_EXP, &val); | ||
236 | ctl->value = val; | ||
237 | break; | ||
238 | case OVCAMCHIP_CID_BANDFILT: | ||
239 | ctl->value = s->bandfilt; | ||
240 | break; | ||
241 | case OVCAMCHIP_CID_AUTOBRIGHT: | ||
242 | ctl->value = s->auto_brt; | ||
243 | break; | ||
244 | case OVCAMCHIP_CID_AUTOEXP: | ||
245 | ctl->value = s->auto_exp; | ||
246 | break; | ||
247 | case OVCAMCHIP_CID_MIRROR: | ||
248 | ctl->value = s->mirror; | ||
249 | break; | ||
250 | default: | ||
251 | DDEBUG(2, &c->dev, "control not supported: %d", ctl->id); | ||
252 | return -EPERM; | ||
253 | } | ||
254 | |||
255 | DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, ctl->value, rc); | ||
256 | return rc; | ||
257 | } | ||
258 | |||
259 | static int ov7x10_mode_init(struct i2c_client *c, struct ovcamchip_window *win) | ||
260 | { | ||
261 | int qvga = win->quarter; | ||
262 | |||
263 | /******** QVGA-specific regs ********/ | ||
264 | |||
265 | ov_write(c, 0x14, qvga?0x24:0x04); | ||
266 | |||
267 | /******** Palette-specific regs ********/ | ||
268 | |||
269 | if (win->format == VIDEO_PALETTE_GREY) { | ||
270 | ov_write_mask(c, 0x0e, 0x40, 0x40); | ||
271 | ov_write_mask(c, 0x13, 0x20, 0x20); | ||
272 | } else { | ||
273 | ov_write_mask(c, 0x0e, 0x00, 0x40); | ||
274 | ov_write_mask(c, 0x13, 0x00, 0x20); | ||
275 | } | ||
276 | |||
277 | /******** Clock programming ********/ | ||
278 | |||
279 | ov_write(c, 0x11, win->clockdiv); | ||
280 | |||
281 | /******** Resolution-specific ********/ | ||
282 | |||
283 | if (win->width == 640 && win->height == 480) | ||
284 | ov_write(c, 0x35, 0x9e); | ||
285 | else | ||
286 | ov_write(c, 0x35, 0x1e); | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static int ov7x10_set_window(struct i2c_client *c, struct ovcamchip_window *win) | ||
292 | { | ||
293 | int ret, hwscale, vwscale; | ||
294 | |||
295 | ret = ov7x10_mode_init(c, win); | ||
296 | if (ret < 0) | ||
297 | return ret; | ||
298 | |||
299 | if (win->quarter) { | ||
300 | hwscale = 1; | ||
301 | vwscale = 0; | ||
302 | } else { | ||
303 | hwscale = 2; | ||
304 | vwscale = 1; | ||
305 | } | ||
306 | |||
307 | ov_write(c, 0x17, HWSBASE + (win->x >> hwscale)); | ||
308 | ov_write(c, 0x18, HWEBASE + ((win->x + win->width) >> hwscale)); | ||
309 | ov_write(c, 0x19, VWSBASE + (win->y >> vwscale)); | ||
310 | ov_write(c, 0x1a, VWEBASE + ((win->y + win->height) >> vwscale)); | ||
311 | |||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | static int ov7x10_command(struct i2c_client *c, unsigned int cmd, void *arg) | ||
316 | { | ||
317 | switch (cmd) { | ||
318 | case OVCAMCHIP_CMD_S_CTRL: | ||
319 | return ov7x10_set_control(c, arg); | ||
320 | case OVCAMCHIP_CMD_G_CTRL: | ||
321 | return ov7x10_get_control(c, arg); | ||
322 | case OVCAMCHIP_CMD_S_MODE: | ||
323 | return ov7x10_set_window(c, arg); | ||
324 | default: | ||
325 | DDEBUG(2, &c->dev, "command not supported: %d", cmd); | ||
326 | return -ENOIOCTLCMD; | ||
327 | } | ||
328 | } | ||
329 | |||
330 | struct ovcamchip_ops ov7x10_ops = { | ||
331 | .init = ov7x10_init, | ||
332 | .free = ov7x10_free, | ||
333 | .command = ov7x10_command, | ||
334 | }; | ||
diff --git a/drivers/media/video/ovcamchip/ov7x20.c b/drivers/media/video/ovcamchip/ov7x20.c deleted file mode 100644 index 8e26ae338f31..000000000000 --- a/drivers/media/video/ovcamchip/ov7x20.c +++ /dev/null | |||
@@ -1,454 +0,0 @@ | |||
1 | /* OmniVision OV7620/OV7120 Camera Chip Support Code | ||
2 | * | ||
3 | * Copyright (c) 1999-2004 Mark McClelland <mark@alpha.dyndns.org> | ||
4 | * http://alpha.dyndns.org/ov511/ | ||
5 | * | ||
6 | * OV7620 fixes by Charl P. Botha <cpbotha@ieee.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied. | ||
12 | */ | ||
13 | |||
14 | #define DEBUG | ||
15 | |||
16 | #include <linux/slab.h> | ||
17 | #include "ovcamchip_priv.h" | ||
18 | |||
19 | /* Registers */ | ||
20 | #define REG_GAIN 0x00 /* gain [5:0] */ | ||
21 | #define REG_BLUE 0x01 /* blue gain */ | ||
22 | #define REG_RED 0x02 /* red gain */ | ||
23 | #define REG_SAT 0x03 /* saturation */ | ||
24 | #define REG_BRT 0x06 /* Y brightness */ | ||
25 | #define REG_SHARP 0x07 /* analog sharpness */ | ||
26 | #define REG_BLUE_BIAS 0x0C /* WB blue ratio [5:0] */ | ||
27 | #define REG_RED_BIAS 0x0D /* WB red ratio [5:0] */ | ||
28 | #define REG_EXP 0x10 /* exposure */ | ||
29 | |||
30 | /* Default control settings. Values are in terms of V4L2 controls. */ | ||
31 | #define OV7120_DFL_BRIGHT 0x60 | ||
32 | #define OV7620_DFL_BRIGHT 0x60 | ||
33 | #define OV7120_DFL_SAT 0xb0 | ||
34 | #define OV7620_DFL_SAT 0xc0 | ||
35 | #define DFL_AUTO_EXP 1 | ||
36 | #define DFL_AUTO_GAIN 1 | ||
37 | #define OV7120_DFL_GAIN 0x00 | ||
38 | #define OV7620_DFL_GAIN 0x00 | ||
39 | /* NOTE: Since autoexposure is the default, these aren't programmed into the | ||
40 | * OV7x20 chip. They are just here because V4L2 expects a default */ | ||
41 | #define OV7120_DFL_EXP 0x7f | ||
42 | #define OV7620_DFL_EXP 0x7f | ||
43 | |||
44 | /* Window parameters */ | ||
45 | #define HWSBASE 0x2F /* From 7620.SET (spec is wrong) */ | ||
46 | #define HWEBASE 0x2F | ||
47 | #define VWSBASE 0x05 | ||
48 | #define VWEBASE 0x05 | ||
49 | |||
50 | struct ov7x20 { | ||
51 | int auto_brt; | ||
52 | int auto_exp; | ||
53 | int auto_gain; | ||
54 | int backlight; | ||
55 | int bandfilt; | ||
56 | int mirror; | ||
57 | }; | ||
58 | |||
59 | /* Contrast look-up table */ | ||
60 | static unsigned char ctab[] = { | ||
61 | 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57, | ||
62 | 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff | ||
63 | }; | ||
64 | |||
65 | /* Settings for (Black & White) OV7120 camera chip */ | ||
66 | static struct ovcamchip_regvals regvals_init_7120[] = { | ||
67 | { 0x12, 0x80 }, /* reset */ | ||
68 | { 0x13, 0x00 }, /* Autoadjust off */ | ||
69 | { 0x12, 0x20 }, /* Disable AWB */ | ||
70 | { 0x13, DFL_AUTO_GAIN?0x01:0x00 }, /* Autoadjust on (if desired) */ | ||
71 | { 0x00, OV7120_DFL_GAIN }, | ||
72 | { 0x01, 0x80 }, | ||
73 | { 0x02, 0x80 }, | ||
74 | { 0x03, OV7120_DFL_SAT }, | ||
75 | { 0x06, OV7120_DFL_BRIGHT }, | ||
76 | { 0x07, 0x00 }, | ||
77 | { 0x0c, 0x20 }, | ||
78 | { 0x0d, 0x20 }, | ||
79 | { 0x11, 0x01 }, | ||
80 | { 0x14, 0x84 }, | ||
81 | { 0x15, 0x01 }, | ||
82 | { 0x16, 0x03 }, | ||
83 | { 0x17, 0x2f }, | ||
84 | { 0x18, 0xcf }, | ||
85 | { 0x19, 0x06 }, | ||
86 | { 0x1a, 0xf5 }, | ||
87 | { 0x1b, 0x00 }, | ||
88 | { 0x20, 0x08 }, | ||
89 | { 0x21, 0x80 }, | ||
90 | { 0x22, 0x80 }, | ||
91 | { 0x23, 0x00 }, | ||
92 | { 0x26, 0xa0 }, | ||
93 | { 0x27, 0xfa }, | ||
94 | { 0x28, 0x20 }, /* DON'T set bit 6. It is for the OV7620 only */ | ||
95 | { 0x29, DFL_AUTO_EXP?0x00:0x80 }, | ||
96 | { 0x2a, 0x10 }, | ||
97 | { 0x2b, 0x00 }, | ||
98 | { 0x2c, 0x88 }, | ||
99 | { 0x2d, 0x95 }, | ||
100 | { 0x2e, 0x80 }, | ||
101 | { 0x2f, 0x44 }, | ||
102 | { 0x60, 0x20 }, | ||
103 | { 0x61, 0x02 }, | ||
104 | { 0x62, 0x5f }, | ||
105 | { 0x63, 0xd5 }, | ||
106 | { 0x64, 0x57 }, | ||
107 | { 0x65, 0x83 }, /* OV says "don't change this value" */ | ||
108 | { 0x66, 0x55 }, | ||
109 | { 0x67, 0x92 }, | ||
110 | { 0x68, 0xcf }, | ||
111 | { 0x69, 0x76 }, | ||
112 | { 0x6a, 0x22 }, | ||
113 | { 0x6b, 0xe2 }, | ||
114 | { 0x6c, 0x40 }, | ||
115 | { 0x6d, 0x48 }, | ||
116 | { 0x6e, 0x80 }, | ||
117 | { 0x6f, 0x0d }, | ||
118 | { 0x70, 0x89 }, | ||
119 | { 0x71, 0x00 }, | ||
120 | { 0x72, 0x14 }, | ||
121 | { 0x73, 0x54 }, | ||
122 | { 0x74, 0xa0 }, | ||
123 | { 0x75, 0x8e }, | ||
124 | { 0x76, 0x00 }, | ||
125 | { 0x77, 0xff }, | ||
126 | { 0x78, 0x80 }, | ||
127 | { 0x79, 0x80 }, | ||
128 | { 0x7a, 0x80 }, | ||
129 | { 0x7b, 0xe6 }, | ||
130 | { 0x7c, 0x00 }, | ||
131 | { 0x24, 0x3a }, | ||
132 | { 0x25, 0x60 }, | ||
133 | { 0xff, 0xff }, /* END MARKER */ | ||
134 | }; | ||
135 | |||
136 | /* Settings for (color) OV7620 camera chip */ | ||
137 | static struct ovcamchip_regvals regvals_init_7620[] = { | ||
138 | { 0x12, 0x80 }, /* reset */ | ||
139 | { 0x00, OV7620_DFL_GAIN }, | ||
140 | { 0x01, 0x80 }, | ||
141 | { 0x02, 0x80 }, | ||
142 | { 0x03, OV7620_DFL_SAT }, | ||
143 | { 0x06, OV7620_DFL_BRIGHT }, | ||
144 | { 0x07, 0x00 }, | ||
145 | { 0x0c, 0x24 }, | ||
146 | { 0x0c, 0x24 }, | ||
147 | { 0x0d, 0x24 }, | ||
148 | { 0x11, 0x01 }, | ||
149 | { 0x12, 0x24 }, | ||
150 | { 0x13, DFL_AUTO_GAIN?0x01:0x00 }, | ||
151 | { 0x14, 0x84 }, | ||
152 | { 0x15, 0x01 }, | ||
153 | { 0x16, 0x03 }, | ||
154 | { 0x17, 0x2f }, | ||
155 | { 0x18, 0xcf }, | ||
156 | { 0x19, 0x06 }, | ||
157 | { 0x1a, 0xf5 }, | ||
158 | { 0x1b, 0x00 }, | ||
159 | { 0x20, 0x18 }, | ||
160 | { 0x21, 0x80 }, | ||
161 | { 0x22, 0x80 }, | ||
162 | { 0x23, 0x00 }, | ||
163 | { 0x26, 0xa2 }, | ||
164 | { 0x27, 0xea }, | ||
165 | { 0x28, 0x20 }, | ||
166 | { 0x29, DFL_AUTO_EXP?0x00:0x80 }, | ||
167 | { 0x2a, 0x10 }, | ||
168 | { 0x2b, 0x00 }, | ||
169 | { 0x2c, 0x88 }, | ||
170 | { 0x2d, 0x91 }, | ||
171 | { 0x2e, 0x80 }, | ||
172 | { 0x2f, 0x44 }, | ||
173 | { 0x60, 0x27 }, | ||
174 | { 0x61, 0x02 }, | ||
175 | { 0x62, 0x5f }, | ||
176 | { 0x63, 0xd5 }, | ||
177 | { 0x64, 0x57 }, | ||
178 | { 0x65, 0x83 }, | ||
179 | { 0x66, 0x55 }, | ||
180 | { 0x67, 0x92 }, | ||
181 | { 0x68, 0xcf }, | ||
182 | { 0x69, 0x76 }, | ||
183 | { 0x6a, 0x22 }, | ||
184 | { 0x6b, 0x00 }, | ||
185 | { 0x6c, 0x02 }, | ||
186 | { 0x6d, 0x44 }, | ||
187 | { 0x6e, 0x80 }, | ||
188 | { 0x6f, 0x1d }, | ||
189 | { 0x70, 0x8b }, | ||
190 | { 0x71, 0x00 }, | ||
191 | { 0x72, 0x14 }, | ||
192 | { 0x73, 0x54 }, | ||
193 | { 0x74, 0x00 }, | ||
194 | { 0x75, 0x8e }, | ||
195 | { 0x76, 0x00 }, | ||
196 | { 0x77, 0xff }, | ||
197 | { 0x78, 0x80 }, | ||
198 | { 0x79, 0x80 }, | ||
199 | { 0x7a, 0x80 }, | ||
200 | { 0x7b, 0xe2 }, | ||
201 | { 0x7c, 0x00 }, | ||
202 | { 0xff, 0xff }, /* END MARKER */ | ||
203 | }; | ||
204 | |||
205 | /* Returns index into the specified look-up table, with 'n' elements, for which | ||
206 | * the value is greater than or equal to "val". If a match isn't found, (n-1) | ||
207 | * is returned. The entries in the table must be in ascending order. */ | ||
208 | static inline int ov7x20_lut_find(unsigned char lut[], int n, unsigned char val) | ||
209 | { | ||
210 | int i = 0; | ||
211 | |||
212 | while (lut[i] < val && i < n) | ||
213 | i++; | ||
214 | |||
215 | return i; | ||
216 | } | ||
217 | |||
218 | /* This initializes the OV7x20 camera chip and relevant variables. */ | ||
219 | static int ov7x20_init(struct i2c_client *c) | ||
220 | { | ||
221 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
222 | struct ov7x20 *s; | ||
223 | int rc; | ||
224 | |||
225 | DDEBUG(4, &c->dev, "entered"); | ||
226 | |||
227 | if (ov->mono) | ||
228 | rc = ov_write_regvals(c, regvals_init_7120); | ||
229 | else | ||
230 | rc = ov_write_regvals(c, regvals_init_7620); | ||
231 | |||
232 | if (rc < 0) | ||
233 | return rc; | ||
234 | |||
235 | ov->spriv = s = kzalloc(sizeof *s, GFP_KERNEL); | ||
236 | if (!s) | ||
237 | return -ENOMEM; | ||
238 | |||
239 | s->auto_brt = 1; | ||
240 | s->auto_exp = DFL_AUTO_EXP; | ||
241 | s->auto_gain = DFL_AUTO_GAIN; | ||
242 | |||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static int ov7x20_free(struct i2c_client *c) | ||
247 | { | ||
248 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
249 | |||
250 | kfree(ov->spriv); | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static int ov7x20_set_v4l1_control(struct i2c_client *c, | ||
255 | struct ovcamchip_control *ctl) | ||
256 | { | ||
257 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
258 | struct ov7x20 *s = ov->spriv; | ||
259 | int rc; | ||
260 | int v = ctl->value; | ||
261 | |||
262 | switch (ctl->id) { | ||
263 | case OVCAMCHIP_CID_CONT: | ||
264 | { | ||
265 | /* Use Y gamma control instead. Bit 0 enables it. */ | ||
266 | rc = ov_write(c, 0x64, ctab[v >> 12]); | ||
267 | break; | ||
268 | } | ||
269 | case OVCAMCHIP_CID_BRIGHT: | ||
270 | /* 7620 doesn't like manual changes when in auto mode */ | ||
271 | if (!s->auto_brt) | ||
272 | rc = ov_write(c, REG_BRT, v >> 8); | ||
273 | else | ||
274 | rc = 0; | ||
275 | break; | ||
276 | case OVCAMCHIP_CID_SAT: | ||
277 | rc = ov_write(c, REG_SAT, v >> 8); | ||
278 | break; | ||
279 | case OVCAMCHIP_CID_EXP: | ||
280 | if (!s->auto_exp) | ||
281 | rc = ov_write(c, REG_EXP, v); | ||
282 | else | ||
283 | rc = -EBUSY; | ||
284 | break; | ||
285 | case OVCAMCHIP_CID_FREQ: | ||
286 | { | ||
287 | int sixty = (v == 60); | ||
288 | |||
289 | rc = ov_write_mask(c, 0x2a, sixty?0x00:0x80, 0x80); | ||
290 | if (rc < 0) | ||
291 | goto out; | ||
292 | |||
293 | rc = ov_write(c, 0x2b, sixty?0x00:0xac); | ||
294 | if (rc < 0) | ||
295 | goto out; | ||
296 | |||
297 | rc = ov_write_mask(c, 0x76, 0x01, 0x01); | ||
298 | break; | ||
299 | } | ||
300 | case OVCAMCHIP_CID_BANDFILT: | ||
301 | rc = ov_write_mask(c, 0x2d, v?0x04:0x00, 0x04); | ||
302 | s->bandfilt = v; | ||
303 | break; | ||
304 | case OVCAMCHIP_CID_AUTOBRIGHT: | ||
305 | rc = ov_write_mask(c, 0x2d, v?0x10:0x00, 0x10); | ||
306 | s->auto_brt = v; | ||
307 | break; | ||
308 | case OVCAMCHIP_CID_AUTOEXP: | ||
309 | rc = ov_write_mask(c, 0x13, v?0x01:0x00, 0x01); | ||
310 | s->auto_exp = v; | ||
311 | break; | ||
312 | case OVCAMCHIP_CID_BACKLIGHT: | ||
313 | { | ||
314 | rc = ov_write_mask(c, 0x68, v?0xe0:0xc0, 0xe0); | ||
315 | if (rc < 0) | ||
316 | goto out; | ||
317 | |||
318 | rc = ov_write_mask(c, 0x29, v?0x08:0x00, 0x08); | ||
319 | if (rc < 0) | ||
320 | goto out; | ||
321 | |||
322 | rc = ov_write_mask(c, 0x28, v?0x02:0x00, 0x02); | ||
323 | s->backlight = v; | ||
324 | break; | ||
325 | } | ||
326 | case OVCAMCHIP_CID_MIRROR: | ||
327 | rc = ov_write_mask(c, 0x12, v?0x40:0x00, 0x40); | ||
328 | s->mirror = v; | ||
329 | break; | ||
330 | default: | ||
331 | DDEBUG(2, &c->dev, "control not supported: %d", ctl->id); | ||
332 | return -EPERM; | ||
333 | } | ||
334 | |||
335 | out: | ||
336 | DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, v, rc); | ||
337 | return rc; | ||
338 | } | ||
339 | |||
340 | static int ov7x20_get_v4l1_control(struct i2c_client *c, | ||
341 | struct ovcamchip_control *ctl) | ||
342 | { | ||
343 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
344 | struct ov7x20 *s = ov->spriv; | ||
345 | int rc = 0; | ||
346 | unsigned char val = 0; | ||
347 | |||
348 | switch (ctl->id) { | ||
349 | case OVCAMCHIP_CID_CONT: | ||
350 | rc = ov_read(c, 0x64, &val); | ||
351 | ctl->value = ov7x20_lut_find(ctab, 16, val) << 12; | ||
352 | break; | ||
353 | case OVCAMCHIP_CID_BRIGHT: | ||
354 | rc = ov_read(c, REG_BRT, &val); | ||
355 | ctl->value = val << 8; | ||
356 | break; | ||
357 | case OVCAMCHIP_CID_SAT: | ||
358 | rc = ov_read(c, REG_SAT, &val); | ||
359 | ctl->value = val << 8; | ||
360 | break; | ||
361 | case OVCAMCHIP_CID_EXP: | ||
362 | rc = ov_read(c, REG_EXP, &val); | ||
363 | ctl->value = val; | ||
364 | break; | ||
365 | case OVCAMCHIP_CID_BANDFILT: | ||
366 | ctl->value = s->bandfilt; | ||
367 | break; | ||
368 | case OVCAMCHIP_CID_AUTOBRIGHT: | ||
369 | ctl->value = s->auto_brt; | ||
370 | break; | ||
371 | case OVCAMCHIP_CID_AUTOEXP: | ||
372 | ctl->value = s->auto_exp; | ||
373 | break; | ||
374 | case OVCAMCHIP_CID_BACKLIGHT: | ||
375 | ctl->value = s->backlight; | ||
376 | break; | ||
377 | case OVCAMCHIP_CID_MIRROR: | ||
378 | ctl->value = s->mirror; | ||
379 | break; | ||
380 | default: | ||
381 | DDEBUG(2, &c->dev, "control not supported: %d", ctl->id); | ||
382 | return -EPERM; | ||
383 | } | ||
384 | |||
385 | DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, ctl->value, rc); | ||
386 | return rc; | ||
387 | } | ||
388 | |||
389 | static int ov7x20_mode_init(struct i2c_client *c, struct ovcamchip_window *win) | ||
390 | { | ||
391 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
392 | int qvga = win->quarter; | ||
393 | |||
394 | /******** QVGA-specific regs ********/ | ||
395 | ov_write_mask(c, 0x14, qvga?0x20:0x00, 0x20); | ||
396 | ov_write_mask(c, 0x28, qvga?0x00:0x20, 0x20); | ||
397 | ov_write(c, 0x24, qvga?0x20:0x3a); | ||
398 | ov_write(c, 0x25, qvga?0x30:0x60); | ||
399 | ov_write_mask(c, 0x2d, qvga?0x40:0x00, 0x40); | ||
400 | if (!ov->mono) | ||
401 | ov_write_mask(c, 0x67, qvga?0xf0:0x90, 0xf0); | ||
402 | ov_write_mask(c, 0x74, qvga?0x20:0x00, 0x20); | ||
403 | |||
404 | /******** Clock programming ********/ | ||
405 | |||
406 | ov_write(c, 0x11, win->clockdiv); | ||
407 | |||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | static int ov7x20_set_window(struct i2c_client *c, struct ovcamchip_window *win) | ||
412 | { | ||
413 | int ret, hwscale, vwscale; | ||
414 | |||
415 | ret = ov7x20_mode_init(c, win); | ||
416 | if (ret < 0) | ||
417 | return ret; | ||
418 | |||
419 | if (win->quarter) { | ||
420 | hwscale = 1; | ||
421 | vwscale = 0; | ||
422 | } else { | ||
423 | hwscale = 2; | ||
424 | vwscale = 1; | ||
425 | } | ||
426 | |||
427 | ov_write(c, 0x17, HWSBASE + (win->x >> hwscale)); | ||
428 | ov_write(c, 0x18, HWEBASE + ((win->x + win->width) >> hwscale)); | ||
429 | ov_write(c, 0x19, VWSBASE + (win->y >> vwscale)); | ||
430 | ov_write(c, 0x1a, VWEBASE + ((win->y + win->height) >> vwscale)); | ||
431 | |||
432 | return 0; | ||
433 | } | ||
434 | |||
435 | static int ov7x20_command(struct i2c_client *c, unsigned int cmd, void *arg) | ||
436 | { | ||
437 | switch (cmd) { | ||
438 | case OVCAMCHIP_CMD_S_CTRL: | ||
439 | return ov7x20_set_v4l1_control(c, arg); | ||
440 | case OVCAMCHIP_CMD_G_CTRL: | ||
441 | return ov7x20_get_v4l1_control(c, arg); | ||
442 | case OVCAMCHIP_CMD_S_MODE: | ||
443 | return ov7x20_set_window(c, arg); | ||
444 | default: | ||
445 | DDEBUG(2, &c->dev, "command not supported: %d", cmd); | ||
446 | return -ENOIOCTLCMD; | ||
447 | } | ||
448 | } | ||
449 | |||
450 | struct ovcamchip_ops ov7x20_ops = { | ||
451 | .init = ov7x20_init, | ||
452 | .free = ov7x20_free, | ||
453 | .command = ov7x20_command, | ||
454 | }; | ||
diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c deleted file mode 100644 index d573d8428998..000000000000 --- a/drivers/media/video/ovcamchip/ovcamchip_core.c +++ /dev/null | |||
@@ -1,395 +0,0 @@ | |||
1 | /* Shared Code for OmniVision Camera Chip Drivers | ||
2 | * | ||
3 | * Copyright (c) 2004 Mark McClelland <mark@alpha.dyndns.org> | ||
4 | * http://alpha.dyndns.org/ov511/ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied. | ||
10 | */ | ||
11 | |||
12 | #define DEBUG | ||
13 | |||
14 | #include <linux/init.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <media/v4l2-device.h> | ||
20 | #include <media/v4l2-i2c-drv.h> | ||
21 | #include "ovcamchip_priv.h" | ||
22 | |||
23 | #define DRIVER_VERSION "v2.27 for Linux 2.6" | ||
24 | #define DRIVER_AUTHOR "Mark McClelland <mark@alpha.dyndns.org>" | ||
25 | #define DRIVER_DESC "OV camera chip I2C driver" | ||
26 | |||
27 | #define PINFO(fmt, args...) printk(KERN_INFO "ovcamchip: " fmt "\n" , ## args); | ||
28 | #define PERROR(fmt, args...) printk(KERN_ERR "ovcamchip: " fmt "\n" , ## args); | ||
29 | |||
30 | #ifdef DEBUG | ||
31 | int ovcamchip_debug = 0; | ||
32 | static int debug; | ||
33 | module_param(debug, int, 0); | ||
34 | MODULE_PARM_DESC(debug, | ||
35 | "Debug level: 0=none, 1=inits, 2=warning, 3=config, 4=functions, 5=all"); | ||
36 | #endif | ||
37 | |||
38 | /* By default, let bridge driver tell us if chip is monochrome. mono=0 | ||
39 | * will ignore that and always treat chips as color. mono=1 will force | ||
40 | * monochrome mode for all chips. */ | ||
41 | static int mono = -1; | ||
42 | module_param(mono, int, 0); | ||
43 | MODULE_PARM_DESC(mono, | ||
44 | "1=chips are monochrome (OVx1xx), 0=force color, -1=autodetect (default)"); | ||
45 | |||
46 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
47 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
48 | MODULE_LICENSE("GPL"); | ||
49 | |||
50 | |||
51 | /* Registers common to all chips, that are needed for detection */ | ||
52 | #define GENERIC_REG_ID_HIGH 0x1C /* manufacturer ID MSB */ | ||
53 | #define GENERIC_REG_ID_LOW 0x1D /* manufacturer ID LSB */ | ||
54 | #define GENERIC_REG_COM_I 0x29 /* misc ID bits */ | ||
55 | |||
56 | static char *chip_names[NUM_CC_TYPES] = { | ||
57 | [CC_UNKNOWN] = "Unknown chip", | ||
58 | [CC_OV76BE] = "OV76BE", | ||
59 | [CC_OV7610] = "OV7610", | ||
60 | [CC_OV7620] = "OV7620", | ||
61 | [CC_OV7620AE] = "OV7620AE", | ||
62 | [CC_OV6620] = "OV6620", | ||
63 | [CC_OV6630] = "OV6630", | ||
64 | [CC_OV6630AE] = "OV6630AE", | ||
65 | [CC_OV6630AF] = "OV6630AF", | ||
66 | }; | ||
67 | |||
68 | /* ----------------------------------------------------------------------- */ | ||
69 | |||
70 | int ov_write_regvals(struct i2c_client *c, struct ovcamchip_regvals *rvals) | ||
71 | { | ||
72 | int rc; | ||
73 | |||
74 | while (rvals->reg != 0xff) { | ||
75 | rc = ov_write(c, rvals->reg, rvals->val); | ||
76 | if (rc < 0) | ||
77 | return rc; | ||
78 | rvals++; | ||
79 | } | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | /* Writes bits at positions specified by mask to an I2C reg. Bits that are in | ||
85 | * the same position as 1's in "mask" are cleared and set to "value". Bits | ||
86 | * that are in the same position as 0's in "mask" are preserved, regardless | ||
87 | * of their respective state in "value". | ||
88 | */ | ||
89 | int ov_write_mask(struct i2c_client *c, | ||
90 | unsigned char reg, | ||
91 | unsigned char value, | ||
92 | unsigned char mask) | ||
93 | { | ||
94 | int rc; | ||
95 | unsigned char oldval, newval; | ||
96 | |||
97 | if (mask == 0xff) { | ||
98 | newval = value; | ||
99 | } else { | ||
100 | rc = ov_read(c, reg, &oldval); | ||
101 | if (rc < 0) | ||
102 | return rc; | ||
103 | |||
104 | oldval &= (~mask); /* Clear the masked bits */ | ||
105 | value &= mask; /* Enforce mask on value */ | ||
106 | newval = oldval | value; /* Set the desired bits */ | ||
107 | } | ||
108 | |||
109 | return ov_write(c, reg, newval); | ||
110 | } | ||
111 | |||
112 | /* ----------------------------------------------------------------------- */ | ||
113 | |||
114 | /* Reset the chip and ensure that I2C is synchronized. Returns <0 if failure. | ||
115 | */ | ||
116 | static int init_camchip(struct i2c_client *c) | ||
117 | { | ||
118 | int i, success; | ||
119 | unsigned char high, low; | ||
120 | |||
121 | /* Reset the chip */ | ||
122 | ov_write(c, 0x12, 0x80); | ||
123 | |||
124 | /* Wait for it to initialize */ | ||
125 | msleep(150); | ||
126 | |||
127 | for (i = 0, success = 0; i < I2C_DETECT_RETRIES && !success; i++) { | ||
128 | if (ov_read(c, GENERIC_REG_ID_HIGH, &high) >= 0) { | ||
129 | if (ov_read(c, GENERIC_REG_ID_LOW, &low) >= 0) { | ||
130 | if (high == 0x7F && low == 0xA2) { | ||
131 | success = 1; | ||
132 | continue; | ||
133 | } | ||
134 | } | ||
135 | } | ||
136 | |||
137 | /* Reset the chip */ | ||
138 | ov_write(c, 0x12, 0x80); | ||
139 | |||
140 | /* Wait for it to initialize */ | ||
141 | msleep(150); | ||
142 | |||
143 | /* Dummy read to sync I2C */ | ||
144 | ov_read(c, 0x00, &low); | ||
145 | } | ||
146 | |||
147 | if (!success) | ||
148 | return -EIO; | ||
149 | |||
150 | PDEBUG(1, "I2C synced in %d attempt(s)", i); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | /* This detects the OV7610, OV7620, or OV76BE chip. */ | ||
156 | static int ov7xx0_detect(struct i2c_client *c) | ||
157 | { | ||
158 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
159 | int rc; | ||
160 | unsigned char val; | ||
161 | |||
162 | PDEBUG(4, ""); | ||
163 | |||
164 | /* Detect chip (sub)type */ | ||
165 | rc = ov_read(c, GENERIC_REG_COM_I, &val); | ||
166 | if (rc < 0) { | ||
167 | PERROR("Error detecting ov7xx0 type"); | ||
168 | return rc; | ||
169 | } | ||
170 | |||
171 | if ((val & 3) == 3) { | ||
172 | PINFO("Camera chip is an OV7610"); | ||
173 | ov->subtype = CC_OV7610; | ||
174 | } else if ((val & 3) == 1) { | ||
175 | rc = ov_read(c, 0x15, &val); | ||
176 | if (rc < 0) { | ||
177 | PERROR("Error detecting ov7xx0 type"); | ||
178 | return rc; | ||
179 | } | ||
180 | |||
181 | if (val & 1) { | ||
182 | PINFO("Camera chip is an OV7620AE"); | ||
183 | /* OV7620 is a close enough match for now. There are | ||
184 | * some definite differences though, so this should be | ||
185 | * fixed */ | ||
186 | ov->subtype = CC_OV7620; | ||
187 | } else { | ||
188 | PINFO("Camera chip is an OV76BE"); | ||
189 | ov->subtype = CC_OV76BE; | ||
190 | } | ||
191 | } else if ((val & 3) == 0) { | ||
192 | PINFO("Camera chip is an OV7620"); | ||
193 | ov->subtype = CC_OV7620; | ||
194 | } else { | ||
195 | PERROR("Unknown camera chip version: %d", val & 3); | ||
196 | return -ENOSYS; | ||
197 | } | ||
198 | |||
199 | if (ov->subtype == CC_OV76BE) | ||
200 | ov->sops = &ov76be_ops; | ||
201 | else if (ov->subtype == CC_OV7620) | ||
202 | ov->sops = &ov7x20_ops; | ||
203 | else | ||
204 | ov->sops = &ov7x10_ops; | ||
205 | |||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | /* This detects the OV6620, OV6630, OV6630AE, or OV6630AF chip. */ | ||
210 | static int ov6xx0_detect(struct i2c_client *c) | ||
211 | { | ||
212 | struct ovcamchip *ov = i2c_get_clientdata(c); | ||
213 | int rc; | ||
214 | unsigned char val; | ||
215 | |||
216 | PDEBUG(4, ""); | ||
217 | |||
218 | /* Detect chip (sub)type */ | ||
219 | rc = ov_read(c, GENERIC_REG_COM_I, &val); | ||
220 | if (rc < 0) { | ||
221 | PERROR("Error detecting ov6xx0 type"); | ||
222 | return -1; | ||
223 | } | ||
224 | |||
225 | if ((val & 3) == 0) { | ||
226 | ov->subtype = CC_OV6630; | ||
227 | PINFO("Camera chip is an OV6630"); | ||
228 | } else if ((val & 3) == 1) { | ||
229 | ov->subtype = CC_OV6620; | ||
230 | PINFO("Camera chip is an OV6620"); | ||
231 | } else if ((val & 3) == 2) { | ||
232 | ov->subtype = CC_OV6630; | ||
233 | PINFO("Camera chip is an OV6630AE"); | ||
234 | } else if ((val & 3) == 3) { | ||
235 | ov->subtype = CC_OV6630; | ||
236 | PINFO("Camera chip is an OV6630AF"); | ||
237 | } | ||
238 | |||
239 | if (ov->subtype == CC_OV6620) | ||
240 | ov->sops = &ov6x20_ops; | ||
241 | else | ||
242 | ov->sops = &ov6x30_ops; | ||
243 | |||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | static int ovcamchip_detect(struct i2c_client *c) | ||
248 | { | ||
249 | /* Ideally we would just try a single register write and see if it NAKs. | ||
250 | * That isn't possible since the OV518 can't report I2C transaction | ||
251 | * failures. So, we have to try to initialize the chip (i.e. reset it | ||
252 | * and check the ID registers) to detect its presence. */ | ||
253 | |||
254 | /* Test for 7xx0 */ | ||
255 | PDEBUG(3, "Testing for 0V7xx0"); | ||
256 | if (init_camchip(c) < 0) | ||
257 | return -ENODEV; | ||
258 | /* 7-bit addresses with bit 0 set are for the OV7xx0 */ | ||
259 | if (c->addr & 1) { | ||
260 | if (ov7xx0_detect(c) < 0) { | ||
261 | PERROR("Failed to init OV7xx0"); | ||
262 | return -EIO; | ||
263 | } | ||
264 | return 0; | ||
265 | } | ||
266 | /* Test for 6xx0 */ | ||
267 | PDEBUG(3, "Testing for 0V6xx0"); | ||
268 | if (ov6xx0_detect(c) < 0) { | ||
269 | PERROR("Failed to init OV6xx0"); | ||
270 | return -EIO; | ||
271 | } | ||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | /* ----------------------------------------------------------------------- */ | ||
276 | |||
277 | static long ovcamchip_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) | ||
278 | { | ||
279 | struct ovcamchip *ov = to_ovcamchip(sd); | ||
280 | struct i2c_client *c = v4l2_get_subdevdata(sd); | ||
281 | |||
282 | if (!ov->initialized && | ||
283 | cmd != OVCAMCHIP_CMD_Q_SUBTYPE && | ||
284 | cmd != OVCAMCHIP_CMD_INITIALIZE) { | ||
285 | v4l2_err(sd, "Camera chip not initialized yet!\n"); | ||
286 | return -EPERM; | ||
287 | } | ||
288 | |||
289 | switch (cmd) { | ||
290 | case OVCAMCHIP_CMD_Q_SUBTYPE: | ||
291 | { | ||
292 | *(int *)arg = ov->subtype; | ||
293 | return 0; | ||
294 | } | ||
295 | case OVCAMCHIP_CMD_INITIALIZE: | ||
296 | { | ||
297 | int rc; | ||
298 | |||
299 | if (mono == -1) | ||
300 | ov->mono = *(int *)arg; | ||
301 | else | ||
302 | ov->mono = mono; | ||
303 | |||
304 | if (ov->mono) { | ||
305 | if (ov->subtype != CC_OV7620) | ||
306 | v4l2_warn(sd, "Monochrome not " | ||
307 | "implemented for this chip\n"); | ||
308 | else | ||
309 | v4l2_info(sd, "Initializing chip as " | ||
310 | "monochrome\n"); | ||
311 | } | ||
312 | |||
313 | rc = ov->sops->init(c); | ||
314 | if (rc < 0) | ||
315 | return rc; | ||
316 | |||
317 | ov->initialized = 1; | ||
318 | return 0; | ||
319 | } | ||
320 | default: | ||
321 | return ov->sops->command(c, cmd, arg); | ||
322 | } | ||
323 | } | ||
324 | |||
325 | /* ----------------------------------------------------------------------- */ | ||
326 | |||
327 | static const struct v4l2_subdev_core_ops ovcamchip_core_ops = { | ||
328 | .ioctl = ovcamchip_ioctl, | ||
329 | }; | ||
330 | |||
331 | static const struct v4l2_subdev_ops ovcamchip_ops = { | ||
332 | .core = &ovcamchip_core_ops, | ||
333 | }; | ||
334 | |||
335 | static int ovcamchip_probe(struct i2c_client *client, | ||
336 | const struct i2c_device_id *id) | ||
337 | { | ||
338 | struct ovcamchip *ov; | ||
339 | struct v4l2_subdev *sd; | ||
340 | int rc = 0; | ||
341 | |||
342 | ov = kzalloc(sizeof *ov, GFP_KERNEL); | ||
343 | if (!ov) { | ||
344 | rc = -ENOMEM; | ||
345 | goto no_ov; | ||
346 | } | ||
347 | sd = &ov->sd; | ||
348 | v4l2_i2c_subdev_init(sd, client, &ovcamchip_ops); | ||
349 | |||
350 | rc = ovcamchip_detect(client); | ||
351 | if (rc < 0) | ||
352 | goto error; | ||
353 | |||
354 | v4l_info(client, "%s found @ 0x%02x (%s)\n", | ||
355 | chip_names[ov->subtype], client->addr << 1, client->adapter->name); | ||
356 | |||
357 | PDEBUG(1, "Camera chip detection complete"); | ||
358 | |||
359 | return rc; | ||
360 | error: | ||
361 | kfree(ov); | ||
362 | no_ov: | ||
363 | PDEBUG(1, "returning %d", rc); | ||
364 | return rc; | ||
365 | } | ||
366 | |||
367 | static int ovcamchip_remove(struct i2c_client *client) | ||
368 | { | ||
369 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
370 | struct ovcamchip *ov = to_ovcamchip(sd); | ||
371 | int rc; | ||
372 | |||
373 | v4l2_device_unregister_subdev(sd); | ||
374 | rc = ov->sops->free(client); | ||
375 | if (rc < 0) | ||
376 | return rc; | ||
377 | |||
378 | kfree(ov); | ||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | /* ----------------------------------------------------------------------- */ | ||
383 | |||
384 | static const struct i2c_device_id ovcamchip_id[] = { | ||
385 | { "ovcamchip", 0 }, | ||
386 | { } | ||
387 | }; | ||
388 | MODULE_DEVICE_TABLE(i2c, ovcamchip_id); | ||
389 | |||
390 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | ||
391 | .name = "ovcamchip", | ||
392 | .probe = ovcamchip_probe, | ||
393 | .remove = ovcamchip_remove, | ||
394 | .id_table = ovcamchip_id, | ||
395 | }; | ||
diff --git a/drivers/media/video/ovcamchip/ovcamchip_priv.h b/drivers/media/video/ovcamchip/ovcamchip_priv.h deleted file mode 100644 index 4f07b78c88bc..000000000000 --- a/drivers/media/video/ovcamchip/ovcamchip_priv.h +++ /dev/null | |||
@@ -1,101 +0,0 @@ | |||
1 | /* OmniVision* camera chip driver private definitions for core code and | ||
2 | * chip-specific code | ||
3 | * | ||
4 | * Copyright (c) 1999-2004 Mark McClelland | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied. | ||
10 | * | ||
11 | * * OmniVision is a trademark of OmniVision Technologies, Inc. This driver | ||
12 | * is not sponsored or developed by them. | ||
13 | */ | ||
14 | |||
15 | #ifndef __LINUX_OVCAMCHIP_PRIV_H | ||
16 | #define __LINUX_OVCAMCHIP_PRIV_H | ||
17 | |||
18 | #include <linux/i2c.h> | ||
19 | #include <media/v4l2-subdev.h> | ||
20 | #include <media/ovcamchip.h> | ||
21 | |||
22 | #ifdef DEBUG | ||
23 | extern int ovcamchip_debug; | ||
24 | #endif | ||
25 | |||
26 | #define PDEBUG(level, fmt, args...) \ | ||
27 | if (ovcamchip_debug >= (level)) pr_debug("[%s:%d] " fmt "\n", \ | ||
28 | __func__, __LINE__ , ## args) | ||
29 | |||
30 | #define DDEBUG(level, dev, fmt, args...) \ | ||
31 | if (ovcamchip_debug >= (level)) dev_dbg(dev, "[%s:%d] " fmt "\n", \ | ||
32 | __func__, __LINE__ , ## args) | ||
33 | |||
34 | /* Number of times to retry chip detection. Increase this if you are getting | ||
35 | * "Failed to init camera chip" */ | ||
36 | #define I2C_DETECT_RETRIES 10 | ||
37 | |||
38 | struct ovcamchip_regvals { | ||
39 | unsigned char reg; | ||
40 | unsigned char val; | ||
41 | }; | ||
42 | |||
43 | struct ovcamchip_ops { | ||
44 | int (*init)(struct i2c_client *); | ||
45 | int (*free)(struct i2c_client *); | ||
46 | int (*command)(struct i2c_client *, unsigned int, void *); | ||
47 | }; | ||
48 | |||
49 | struct ovcamchip { | ||
50 | struct v4l2_subdev sd; | ||
51 | struct ovcamchip_ops *sops; | ||
52 | void *spriv; /* Private data for OV7x10.c etc... */ | ||
53 | int subtype; /* = SEN_OV7610 etc... */ | ||
54 | int mono; /* Monochrome chip? (invalid until init) */ | ||
55 | int initialized; /* OVCAMCHIP_CMD_INITIALIZE was successful */ | ||
56 | }; | ||
57 | |||
58 | static inline struct ovcamchip *to_ovcamchip(struct v4l2_subdev *sd) | ||
59 | { | ||
60 | return container_of(sd, struct ovcamchip, sd); | ||
61 | } | ||
62 | |||
63 | extern struct ovcamchip_ops ov6x20_ops; | ||
64 | extern struct ovcamchip_ops ov6x30_ops; | ||
65 | extern struct ovcamchip_ops ov7x10_ops; | ||
66 | extern struct ovcamchip_ops ov7x20_ops; | ||
67 | extern struct ovcamchip_ops ov76be_ops; | ||
68 | |||
69 | /* --------------------------------- */ | ||
70 | /* I2C I/O */ | ||
71 | /* --------------------------------- */ | ||
72 | |||
73 | static inline int ov_read(struct i2c_client *c, unsigned char reg, | ||
74 | unsigned char *value) | ||
75 | { | ||
76 | int rc; | ||
77 | |||
78 | rc = i2c_smbus_read_byte_data(c, reg); | ||
79 | *value = (unsigned char) rc; | ||
80 | return rc; | ||
81 | } | ||
82 | |||
83 | static inline int ov_write(struct i2c_client *c, unsigned char reg, | ||
84 | unsigned char value ) | ||
85 | { | ||
86 | return i2c_smbus_write_byte_data(c, reg, value); | ||
87 | } | ||
88 | |||
89 | /* --------------------------------- */ | ||
90 | /* FUNCTION PROTOTYPES */ | ||
91 | /* --------------------------------- */ | ||
92 | |||
93 | /* Functions in ovcamchip_core.c */ | ||
94 | |||
95 | extern int ov_write_regvals(struct i2c_client *c, | ||
96 | struct ovcamchip_regvals *rvals); | ||
97 | |||
98 | extern int ov_write_mask(struct i2c_client *c, unsigned char reg, | ||
99 | unsigned char value, unsigned char mask); | ||
100 | |||
101 | #endif | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.c b/drivers/media/video/pvrusb2/pvrusb2-ioread.c index b4824782d858..bba6115c9ae8 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-ioread.c +++ b/drivers/media/video/pvrusb2/pvrusb2-ioread.c | |||
@@ -223,7 +223,10 @@ int pvr2_ioread_setup(struct pvr2_ioread *cp,struct pvr2_stream *sp) | |||
223 | " pvr2_ioread_setup (setup) id=%p",cp); | 223 | " pvr2_ioread_setup (setup) id=%p",cp); |
224 | pvr2_stream_kill(sp); | 224 | pvr2_stream_kill(sp); |
225 | ret = pvr2_stream_set_buffer_count(sp,BUFFER_COUNT); | 225 | ret = pvr2_stream_set_buffer_count(sp,BUFFER_COUNT); |
226 | if (ret < 0) return ret; | 226 | if (ret < 0) { |
227 | mutex_unlock(&cp->mutex); | ||
228 | return ret; | ||
229 | } | ||
227 | for (idx = 0; idx < BUFFER_COUNT; idx++) { | 230 | for (idx = 0; idx < BUFFER_COUNT; idx++) { |
228 | bp = pvr2_stream_get_buffer(sp,idx); | 231 | bp = pvr2_stream_get_buffer(sp,idx); |
229 | pvr2_buffer_set_buffer(bp, | 232 | pvr2_buffer_set_buffer(bp, |
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index fb242f6cfb1f..9de7d59916bd 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
@@ -276,7 +276,7 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) | |||
276 | * longer in STATE_QUEUED or STATE_ACTIVE | 276 | * longer in STATE_QUEUED or STATE_ACTIVE |
277 | */ | 277 | */ |
278 | videobuf_waiton(&buf->vb, 0, 0); | 278 | videobuf_waiton(&buf->vb, 0, 0); |
279 | videobuf_dma_unmap(vq, dma); | 279 | videobuf_dma_unmap(vq->dev, dma); |
280 | videobuf_dma_free(dma); | 280 | videobuf_dma_free(dma); |
281 | 281 | ||
282 | for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) { | 282 | for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) { |
@@ -1284,7 +1284,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, unsigned int id | |||
1284 | } | 1284 | } |
1285 | 1285 | ||
1286 | switch (code) { | 1286 | switch (code) { |
1287 | case V4L2_MBUS_FMT_YUYV8_2X8_BE: | 1287 | case V4L2_MBUS_FMT_UYVY8_2X8: |
1288 | formats++; | 1288 | formats++; |
1289 | if (xlate) { | 1289 | if (xlate) { |
1290 | xlate->host_fmt = &pxa_camera_formats[0]; | 1290 | xlate->host_fmt = &pxa_camera_formats[0]; |
@@ -1293,9 +1293,9 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, unsigned int id | |||
1293 | dev_dbg(dev, "Providing format %s using code %d\n", | 1293 | dev_dbg(dev, "Providing format %s using code %d\n", |
1294 | pxa_camera_formats[0].name, code); | 1294 | pxa_camera_formats[0].name, code); |
1295 | } | 1295 | } |
1296 | case V4L2_MBUS_FMT_YVYU8_2X8_BE: | 1296 | case V4L2_MBUS_FMT_VYUY8_2X8: |
1297 | case V4L2_MBUS_FMT_YUYV8_2X8_LE: | 1297 | case V4L2_MBUS_FMT_YUYV8_2X8: |
1298 | case V4L2_MBUS_FMT_YVYU8_2X8_LE: | 1298 | case V4L2_MBUS_FMT_YVYU8_2X8: |
1299 | case V4L2_MBUS_FMT_RGB565_2X8_LE: | 1299 | case V4L2_MBUS_FMT_RGB565_2X8_LE: |
1300 | case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE: | 1300 | case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE: |
1301 | if (xlate) | 1301 | if (xlate) |
diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c index 47fd207ba3b1..ce78fff23425 100644 --- a/drivers/media/video/rj54n1cb0c.c +++ b/drivers/media/video/rj54n1cb0c.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for RJ54N1CB0C CMOS Image Sensor from Micron | 2 | * Driver for RJ54N1CB0C CMOS Image Sensor from Sharp |
3 | * | 3 | * |
4 | * Copyright (C) 2009, Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 4 | * Copyright (C) 2009, Guennadi Liakhovetski <g.liakhovetski@gmx.de> |
5 | * | 5 | * |
@@ -127,8 +127,8 @@ static const struct rj54n1_datafmt *rj54n1_find_datafmt( | |||
127 | } | 127 | } |
128 | 128 | ||
129 | static const struct rj54n1_datafmt rj54n1_colour_fmts[] = { | 129 | static const struct rj54n1_datafmt rj54n1_colour_fmts[] = { |
130 | {V4L2_MBUS_FMT_YUYV8_2X8_LE, V4L2_COLORSPACE_JPEG}, | 130 | {V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG}, |
131 | {V4L2_MBUS_FMT_YVYU8_2X8_LE, V4L2_COLORSPACE_JPEG}, | 131 | {V4L2_MBUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG}, |
132 | {V4L2_MBUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB}, | 132 | {V4L2_MBUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB}, |
133 | {V4L2_MBUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB}, | 133 | {V4L2_MBUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB}, |
134 | {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB}, | 134 | {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB}, |
@@ -1046,12 +1046,12 @@ static int rj54n1_s_fmt(struct v4l2_subdev *sd, | |||
1046 | 1046 | ||
1047 | /* RA_SEL_UL is only relevant for raw modes, ignored otherwise. */ | 1047 | /* RA_SEL_UL is only relevant for raw modes, ignored otherwise. */ |
1048 | switch (mf->code) { | 1048 | switch (mf->code) { |
1049 | case V4L2_MBUS_FMT_YUYV8_2X8_LE: | 1049 | case V4L2_MBUS_FMT_YUYV8_2X8: |
1050 | ret = reg_write(client, RJ54N1_OUT_SEL, 0); | 1050 | ret = reg_write(client, RJ54N1_OUT_SEL, 0); |
1051 | if (!ret) | 1051 | if (!ret) |
1052 | ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8); | 1052 | ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8); |
1053 | break; | 1053 | break; |
1054 | case V4L2_MBUS_FMT_YVYU8_2X8_LE: | 1054 | case V4L2_MBUS_FMT_YVYU8_2X8: |
1055 | ret = reg_write(client, RJ54N1_OUT_SEL, 0); | 1055 | ret = reg_write(client, RJ54N1_OUT_SEL, 0); |
1056 | if (!ret) | 1056 | if (!ret) |
1057 | ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8); | 1057 | ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8); |
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 3c7a79f3812a..8ec7c9a45a17 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c | |||
@@ -191,7 +191,6 @@ struct s2255_bufferi { | |||
191 | struct s2255_dmaqueue { | 191 | struct s2255_dmaqueue { |
192 | struct list_head active; | 192 | struct list_head active; |
193 | struct s2255_dev *dev; | 193 | struct s2255_dev *dev; |
194 | int channel; | ||
195 | }; | 194 | }; |
196 | 195 | ||
197 | /* for firmware loading, fw_state */ | 196 | /* for firmware loading, fw_state */ |
@@ -226,51 +225,60 @@ struct s2255_pipeinfo { | |||
226 | }; | 225 | }; |
227 | 226 | ||
228 | struct s2255_fmt; /*forward declaration */ | 227 | struct s2255_fmt; /*forward declaration */ |
228 | struct s2255_dev; | ||
229 | |||
230 | struct s2255_channel { | ||
231 | struct video_device vdev; | ||
232 | int resources; | ||
233 | struct s2255_dmaqueue vidq; | ||
234 | struct s2255_bufferi buffer; | ||
235 | struct s2255_mode mode; | ||
236 | /* jpeg compression */ | ||
237 | struct v4l2_jpegcompression jc; | ||
238 | /* capture parameters (for high quality mode full size) */ | ||
239 | struct v4l2_captureparm cap_parm; | ||
240 | int cur_frame; | ||
241 | int last_frame; | ||
242 | |||
243 | int b_acquire; | ||
244 | /* allocated image size */ | ||
245 | unsigned long req_image_size; | ||
246 | /* received packet size */ | ||
247 | unsigned long pkt_size; | ||
248 | int bad_payload; | ||
249 | unsigned long frame_count; | ||
250 | /* if JPEG image */ | ||
251 | int jpg_size; | ||
252 | /* if channel configured to default state */ | ||
253 | int configured; | ||
254 | wait_queue_head_t wait_setmode; | ||
255 | int setmode_ready; | ||
256 | /* video status items */ | ||
257 | int vidstatus; | ||
258 | wait_queue_head_t wait_vidstatus; | ||
259 | int vidstatus_ready; | ||
260 | unsigned int width; | ||
261 | unsigned int height; | ||
262 | const struct s2255_fmt *fmt; | ||
263 | int idx; /* channel number on device, 0-3 */ | ||
264 | }; | ||
265 | |||
229 | 266 | ||
230 | struct s2255_dev { | 267 | struct s2255_dev { |
231 | struct video_device vdev[MAX_CHANNELS]; | 268 | struct s2255_channel channel[MAX_CHANNELS]; |
232 | struct v4l2_device v4l2_dev; | 269 | struct v4l2_device v4l2_dev; |
233 | atomic_t channels; /* number of channels registered */ | 270 | atomic_t num_channels; |
234 | int frames; | 271 | int frames; |
235 | struct mutex lock; | 272 | struct mutex lock; |
236 | struct mutex open_lock; | 273 | struct mutex open_lock; |
237 | int resources[MAX_CHANNELS]; | ||
238 | struct usb_device *udev; | 274 | struct usb_device *udev; |
239 | struct usb_interface *interface; | 275 | struct usb_interface *interface; |
240 | u8 read_endpoint; | 276 | u8 read_endpoint; |
241 | |||
242 | struct s2255_dmaqueue vidq[MAX_CHANNELS]; | ||
243 | struct timer_list timer; | 277 | struct timer_list timer; |
244 | struct s2255_fw *fw_data; | 278 | struct s2255_fw *fw_data; |
245 | struct s2255_pipeinfo pipe; | 279 | struct s2255_pipeinfo pipe; |
246 | struct s2255_bufferi buffer[MAX_CHANNELS]; | ||
247 | struct s2255_mode mode[MAX_CHANNELS]; | ||
248 | /* jpeg compression */ | ||
249 | struct v4l2_jpegcompression jc[MAX_CHANNELS]; | ||
250 | /* capture parameters (for high quality mode full size) */ | ||
251 | struct v4l2_captureparm cap_parm[MAX_CHANNELS]; | ||
252 | const struct s2255_fmt *cur_fmt[MAX_CHANNELS]; | ||
253 | int cur_frame[MAX_CHANNELS]; | ||
254 | int last_frame[MAX_CHANNELS]; | ||
255 | u32 cc; /* current channel */ | 280 | u32 cc; /* current channel */ |
256 | int b_acquire[MAX_CHANNELS]; | ||
257 | /* allocated image size */ | ||
258 | unsigned long req_image_size[MAX_CHANNELS]; | ||
259 | /* received packet size */ | ||
260 | unsigned long pkt_size[MAX_CHANNELS]; | ||
261 | int bad_payload[MAX_CHANNELS]; | ||
262 | unsigned long frame_count[MAX_CHANNELS]; | ||
263 | int frame_ready; | 281 | int frame_ready; |
264 | /* if JPEG image */ | ||
265 | int jpg_size[MAX_CHANNELS]; | ||
266 | /* if channel configured to default state */ | ||
267 | int chn_configured[MAX_CHANNELS]; | ||
268 | wait_queue_head_t wait_setmode[MAX_CHANNELS]; | ||
269 | int setmode_ready[MAX_CHANNELS]; | ||
270 | /* video status items */ | ||
271 | int vidstatus[MAX_CHANNELS]; | ||
272 | wait_queue_head_t wait_vidstatus[MAX_CHANNELS]; | ||
273 | int vidstatus_ready[MAX_CHANNELS]; | ||
274 | int chn_ready; | 282 | int chn_ready; |
275 | spinlock_t slock; | 283 | spinlock_t slock; |
276 | /* dsp firmware version (f2255usb.bin) */ | 284 | /* dsp firmware version (f2255usb.bin) */ |
@@ -298,16 +306,10 @@ struct s2255_buffer { | |||
298 | 306 | ||
299 | struct s2255_fh { | 307 | struct s2255_fh { |
300 | struct s2255_dev *dev; | 308 | struct s2255_dev *dev; |
301 | const struct s2255_fmt *fmt; | ||
302 | unsigned int width; | ||
303 | unsigned int height; | ||
304 | struct videobuf_queue vb_vidq; | 309 | struct videobuf_queue vb_vidq; |
305 | enum v4l2_buf_type type; | 310 | enum v4l2_buf_type type; |
306 | int channel; | 311 | struct s2255_channel *channel; |
307 | /* mode below is the desired mode. | 312 | int resources; |
308 | mode in s2255_dev is the current mode that was last set */ | ||
309 | struct s2255_mode mode; | ||
310 | int resources[MAX_CHANNELS]; | ||
311 | }; | 313 | }; |
312 | 314 | ||
313 | /* current cypress EEPROM firmware version */ | 315 | /* current cypress EEPROM firmware version */ |
@@ -360,12 +362,11 @@ static int *s2255_debug = &debug; | |||
360 | 362 | ||
361 | static int s2255_start_readpipe(struct s2255_dev *dev); | 363 | static int s2255_start_readpipe(struct s2255_dev *dev); |
362 | static void s2255_stop_readpipe(struct s2255_dev *dev); | 364 | static void s2255_stop_readpipe(struct s2255_dev *dev); |
363 | static int s2255_start_acquire(struct s2255_dev *dev, unsigned long chn); | 365 | static int s2255_start_acquire(struct s2255_channel *channel); |
364 | static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn); | 366 | static int s2255_stop_acquire(struct s2255_channel *channel); |
365 | static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, | 367 | static void s2255_fillbuff(struct s2255_channel *chn, struct s2255_buffer *buf, |
366 | int chn, int jpgsize); | 368 | int jpgsize); |
367 | static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, | 369 | static int s2255_set_mode(struct s2255_channel *chan, struct s2255_mode *mode); |
368 | struct s2255_mode *mode); | ||
369 | static int s2255_board_shutdown(struct s2255_dev *dev); | 370 | static int s2255_board_shutdown(struct s2255_dev *dev); |
370 | static void s2255_fwload_start(struct s2255_dev *dev, int reset); | 371 | static void s2255_fwload_start(struct s2255_dev *dev, int reset); |
371 | static void s2255_destroy(struct s2255_dev *dev); | 372 | static void s2255_destroy(struct s2255_dev *dev); |
@@ -577,10 +578,11 @@ static void s2255_fwchunk_complete(struct urb *urb) | |||
577 | 578 | ||
578 | } | 579 | } |
579 | 580 | ||
580 | static int s2255_got_frame(struct s2255_dev *dev, int chn, int jpgsize) | 581 | static int s2255_got_frame(struct s2255_channel *channel, int jpgsize) |
581 | { | 582 | { |
582 | struct s2255_dmaqueue *dma_q = &dev->vidq[chn]; | 583 | struct s2255_dmaqueue *dma_q = &channel->vidq; |
583 | struct s2255_buffer *buf; | 584 | struct s2255_buffer *buf; |
585 | struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev); | ||
584 | unsigned long flags = 0; | 586 | unsigned long flags = 0; |
585 | int rc = 0; | 587 | int rc = 0; |
586 | spin_lock_irqsave(&dev->slock, flags); | 588 | spin_lock_irqsave(&dev->slock, flags); |
@@ -593,7 +595,7 @@ static int s2255_got_frame(struct s2255_dev *dev, int chn, int jpgsize) | |||
593 | struct s2255_buffer, vb.queue); | 595 | struct s2255_buffer, vb.queue); |
594 | list_del(&buf->vb.queue); | 596 | list_del(&buf->vb.queue); |
595 | do_gettimeofday(&buf->vb.ts); | 597 | do_gettimeofday(&buf->vb.ts); |
596 | s2255_fillbuff(dev, buf, dma_q->channel, jpgsize); | 598 | s2255_fillbuff(channel, buf, jpgsize); |
597 | wake_up(&buf->vb.done); | 599 | wake_up(&buf->vb.done); |
598 | dprintk(2, "%s: [buf/i] [%p/%d]\n", __func__, buf, buf->vb.i); | 600 | dprintk(2, "%s: [buf/i] [%p/%d]\n", __func__, buf, buf->vb.i); |
599 | unlock: | 601 | unlock: |
@@ -621,8 +623,8 @@ static const struct s2255_fmt *format_by_fourcc(int fourcc) | |||
621 | * http://v4l.videotechnology.com/ | 623 | * http://v4l.videotechnology.com/ |
622 | * | 624 | * |
623 | */ | 625 | */ |
624 | static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, | 626 | static void s2255_fillbuff(struct s2255_channel *channel, |
625 | int chn, int jpgsize) | 627 | struct s2255_buffer *buf, int jpgsize) |
626 | { | 628 | { |
627 | int pos = 0; | 629 | int pos = 0; |
628 | struct timeval ts; | 630 | struct timeval ts; |
@@ -633,12 +635,11 @@ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, | |||
633 | 635 | ||
634 | if (!vbuf) | 636 | if (!vbuf) |
635 | return; | 637 | return; |
636 | 638 | last_frame = channel->last_frame; | |
637 | last_frame = dev->last_frame[chn]; | ||
638 | if (last_frame != -1) { | 639 | if (last_frame != -1) { |
639 | frm = &dev->buffer[chn].frame[last_frame]; | 640 | frm = &channel->buffer.frame[last_frame]; |
640 | tmpbuf = | 641 | tmpbuf = |
641 | (const char *)dev->buffer[chn].frame[last_frame].lpvbits; | 642 | (const char *)channel->buffer.frame[last_frame].lpvbits; |
642 | switch (buf->fmt->fourcc) { | 643 | switch (buf->fmt->fourcc) { |
643 | case V4L2_PIX_FMT_YUYV: | 644 | case V4L2_PIX_FMT_YUYV: |
644 | case V4L2_PIX_FMT_UYVY: | 645 | case V4L2_PIX_FMT_UYVY: |
@@ -661,7 +662,7 @@ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, | |||
661 | default: | 662 | default: |
662 | printk(KERN_DEBUG "s2255: unknown format?\n"); | 663 | printk(KERN_DEBUG "s2255: unknown format?\n"); |
663 | } | 664 | } |
664 | dev->last_frame[chn] = -1; | 665 | channel->last_frame = -1; |
665 | } else { | 666 | } else { |
666 | printk(KERN_ERR "s2255: =======no frame\n"); | 667 | printk(KERN_ERR "s2255: =======no frame\n"); |
667 | return; | 668 | return; |
@@ -671,7 +672,7 @@ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, | |||
671 | (unsigned long)vbuf, pos); | 672 | (unsigned long)vbuf, pos); |
672 | /* tell v4l buffer was filled */ | 673 | /* tell v4l buffer was filled */ |
673 | 674 | ||
674 | buf->vb.field_count = dev->frame_count[chn] * 2; | 675 | buf->vb.field_count = channel->frame_count * 2; |
675 | do_gettimeofday(&ts); | 676 | do_gettimeofday(&ts); |
676 | buf->vb.ts = ts; | 677 | buf->vb.ts = ts; |
677 | buf->vb.state = VIDEOBUF_DONE; | 678 | buf->vb.state = VIDEOBUF_DONE; |
@@ -686,8 +687,8 @@ static int buffer_setup(struct videobuf_queue *vq, unsigned int *count, | |||
686 | unsigned int *size) | 687 | unsigned int *size) |
687 | { | 688 | { |
688 | struct s2255_fh *fh = vq->priv_data; | 689 | struct s2255_fh *fh = vq->priv_data; |
689 | 690 | struct s2255_channel *channel = fh->channel; | |
690 | *size = fh->width * fh->height * (fh->fmt->depth >> 3); | 691 | *size = channel->width * channel->height * (channel->fmt->depth >> 3); |
691 | 692 | ||
692 | if (0 == *count) | 693 | if (0 == *count) |
693 | *count = S2255_DEF_BUFS; | 694 | *count = S2255_DEF_BUFS; |
@@ -710,30 +711,31 @@ static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, | |||
710 | enum v4l2_field field) | 711 | enum v4l2_field field) |
711 | { | 712 | { |
712 | struct s2255_fh *fh = vq->priv_data; | 713 | struct s2255_fh *fh = vq->priv_data; |
714 | struct s2255_channel *channel = fh->channel; | ||
713 | struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb); | 715 | struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb); |
714 | int rc; | 716 | int rc; |
717 | int w = channel->width; | ||
718 | int h = channel->height; | ||
715 | dprintk(4, "%s, field=%d\n", __func__, field); | 719 | dprintk(4, "%s, field=%d\n", __func__, field); |
716 | if (fh->fmt == NULL) | 720 | if (channel->fmt == NULL) |
717 | return -EINVAL; | 721 | return -EINVAL; |
718 | 722 | ||
719 | if ((fh->width < norm_minw(&fh->dev->vdev[fh->channel])) || | 723 | if ((w < norm_minw(&channel->vdev)) || |
720 | (fh->width > norm_maxw(&fh->dev->vdev[fh->channel])) || | 724 | (w > norm_maxw(&channel->vdev)) || |
721 | (fh->height < norm_minh(&fh->dev->vdev[fh->channel])) || | 725 | (h < norm_minh(&channel->vdev)) || |
722 | (fh->height > norm_maxh(&fh->dev->vdev[fh->channel]))) { | 726 | (h > norm_maxh(&channel->vdev))) { |
723 | dprintk(4, "invalid buffer prepare\n"); | 727 | dprintk(4, "invalid buffer prepare\n"); |
724 | return -EINVAL; | 728 | return -EINVAL; |
725 | } | 729 | } |
726 | 730 | buf->vb.size = w * h * (channel->fmt->depth >> 3); | |
727 | buf->vb.size = fh->width * fh->height * (fh->fmt->depth >> 3); | ||
728 | |||
729 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) { | 731 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) { |
730 | dprintk(4, "invalid buffer prepare\n"); | 732 | dprintk(4, "invalid buffer prepare\n"); |
731 | return -EINVAL; | 733 | return -EINVAL; |
732 | } | 734 | } |
733 | 735 | ||
734 | buf->fmt = fh->fmt; | 736 | buf->fmt = channel->fmt; |
735 | buf->vb.width = fh->width; | 737 | buf->vb.width = w; |
736 | buf->vb.height = fh->height; | 738 | buf->vb.height = h; |
737 | buf->vb.field = field; | 739 | buf->vb.field = field; |
738 | 740 | ||
739 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | 741 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { |
@@ -753,8 +755,8 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | |||
753 | { | 755 | { |
754 | struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb); | 756 | struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb); |
755 | struct s2255_fh *fh = vq->priv_data; | 757 | struct s2255_fh *fh = vq->priv_data; |
756 | struct s2255_dev *dev = fh->dev; | 758 | struct s2255_channel *channel = fh->channel; |
757 | struct s2255_dmaqueue *vidq = &dev->vidq[fh->channel]; | 759 | struct s2255_dmaqueue *vidq = &channel->vidq; |
758 | dprintk(1, "%s\n", __func__); | 760 | dprintk(1, "%s\n", __func__); |
759 | buf->vb.state = VIDEOBUF_QUEUED; | 761 | buf->vb.state = VIDEOBUF_QUEUED; |
760 | list_add_tail(&buf->vb.queue, &vidq->active); | 762 | list_add_tail(&buf->vb.queue, &vidq->active); |
@@ -765,7 +767,7 @@ static void buffer_release(struct videobuf_queue *vq, | |||
765 | { | 767 | { |
766 | struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb); | 768 | struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb); |
767 | struct s2255_fh *fh = vq->priv_data; | 769 | struct s2255_fh *fh = vq->priv_data; |
768 | dprintk(4, "%s %d\n", __func__, fh->channel); | 770 | dprintk(4, "%s %d\n", __func__, fh->channel->idx); |
769 | free_buffer(vq, buf); | 771 | free_buffer(vq, buf); |
770 | } | 772 | } |
771 | 773 | ||
@@ -777,39 +779,43 @@ static struct videobuf_queue_ops s2255_video_qops = { | |||
777 | }; | 779 | }; |
778 | 780 | ||
779 | 781 | ||
780 | static int res_get(struct s2255_dev *dev, struct s2255_fh *fh) | 782 | static int res_get(struct s2255_fh *fh) |
781 | { | 783 | { |
784 | struct s2255_dev *dev = fh->dev; | ||
782 | /* is it free? */ | 785 | /* is it free? */ |
786 | struct s2255_channel *channel = fh->channel; | ||
783 | mutex_lock(&dev->lock); | 787 | mutex_lock(&dev->lock); |
784 | if (dev->resources[fh->channel]) { | 788 | if (channel->resources) { |
785 | /* no, someone else uses it */ | 789 | /* no, someone else uses it */ |
786 | mutex_unlock(&dev->lock); | 790 | mutex_unlock(&dev->lock); |
787 | return 0; | 791 | return 0; |
788 | } | 792 | } |
789 | /* it's free, grab it */ | 793 | /* it's free, grab it */ |
790 | dev->resources[fh->channel] = 1; | 794 | channel->resources = 1; |
791 | fh->resources[fh->channel] = 1; | 795 | fh->resources = 1; |
792 | dprintk(1, "s2255: res: get\n"); | 796 | dprintk(1, "s2255: res: get\n"); |
793 | mutex_unlock(&dev->lock); | 797 | mutex_unlock(&dev->lock); |
794 | return 1; | 798 | return 1; |
795 | } | 799 | } |
796 | 800 | ||
797 | static int res_locked(struct s2255_dev *dev, struct s2255_fh *fh) | 801 | static int res_locked(struct s2255_fh *fh) |
798 | { | 802 | { |
799 | return dev->resources[fh->channel]; | 803 | return fh->channel->resources; |
800 | } | 804 | } |
801 | 805 | ||
802 | static int res_check(struct s2255_fh *fh) | 806 | static int res_check(struct s2255_fh *fh) |
803 | { | 807 | { |
804 | return fh->resources[fh->channel]; | 808 | return fh->resources; |
805 | } | 809 | } |
806 | 810 | ||
807 | 811 | ||
808 | static void res_free(struct s2255_dev *dev, struct s2255_fh *fh) | 812 | static void res_free(struct s2255_fh *fh) |
809 | { | 813 | { |
814 | struct s2255_channel *channel = fh->channel; | ||
815 | struct s2255_dev *dev = fh->dev; | ||
810 | mutex_lock(&dev->lock); | 816 | mutex_lock(&dev->lock); |
811 | dev->resources[fh->channel] = 0; | 817 | channel->resources = 0; |
812 | fh->resources[fh->channel] = 0; | 818 | fh->resources = 0; |
813 | mutex_unlock(&dev->lock); | 819 | mutex_unlock(&dev->lock); |
814 | dprintk(1, "res: put\n"); | 820 | dprintk(1, "res: put\n"); |
815 | } | 821 | } |
@@ -869,12 +875,13 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | |||
869 | struct v4l2_format *f) | 875 | struct v4l2_format *f) |
870 | { | 876 | { |
871 | struct s2255_fh *fh = priv; | 877 | struct s2255_fh *fh = priv; |
878 | struct s2255_channel *channel = fh->channel; | ||
872 | 879 | ||
873 | f->fmt.pix.width = fh->width; | 880 | f->fmt.pix.width = channel->width; |
874 | f->fmt.pix.height = fh->height; | 881 | f->fmt.pix.height = channel->height; |
875 | f->fmt.pix.field = fh->vb_vidq.field; | 882 | f->fmt.pix.field = fh->vb_vidq.field; |
876 | f->fmt.pix.pixelformat = fh->fmt->fourcc; | 883 | f->fmt.pix.pixelformat = channel->fmt->fourcc; |
877 | f->fmt.pix.bytesperline = f->fmt.pix.width * (fh->fmt->depth >> 3); | 884 | f->fmt.pix.bytesperline = f->fmt.pix.width * (channel->fmt->depth >> 3); |
878 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | 885 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; |
879 | return 0; | 886 | return 0; |
880 | } | 887 | } |
@@ -886,11 +893,10 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
886 | enum v4l2_field field; | 893 | enum v4l2_field field; |
887 | int b_any_field = 0; | 894 | int b_any_field = 0; |
888 | struct s2255_fh *fh = priv; | 895 | struct s2255_fh *fh = priv; |
889 | struct s2255_dev *dev = fh->dev; | 896 | struct s2255_channel *channel = fh->channel; |
890 | int is_ntsc; | 897 | int is_ntsc; |
891 | |||
892 | is_ntsc = | 898 | is_ntsc = |
893 | (dev->vdev[fh->channel].current_norm & V4L2_STD_NTSC) ? 1 : 0; | 899 | (channel->vdev.current_norm & V4L2_STD_NTSC) ? 1 : 0; |
894 | 900 | ||
895 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); | 901 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); |
896 | 902 | ||
@@ -982,8 +988,10 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
982 | struct v4l2_format *f) | 988 | struct v4l2_format *f) |
983 | { | 989 | { |
984 | struct s2255_fh *fh = priv; | 990 | struct s2255_fh *fh = priv; |
991 | struct s2255_channel *channel = fh->channel; | ||
985 | const struct s2255_fmt *fmt; | 992 | const struct s2255_fmt *fmt; |
986 | struct videobuf_queue *q = &fh->vb_vidq; | 993 | struct videobuf_queue *q = &fh->vb_vidq; |
994 | struct s2255_mode mode; | ||
987 | int ret; | 995 | int ret; |
988 | int norm; | 996 | int norm; |
989 | 997 | ||
@@ -1005,54 +1013,61 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
1005 | goto out_s_fmt; | 1013 | goto out_s_fmt; |
1006 | } | 1014 | } |
1007 | 1015 | ||
1008 | if (res_locked(fh->dev, fh)) { | 1016 | if (res_locked(fh)) { |
1009 | dprintk(1, "%s: channel busy\n", __func__); | 1017 | dprintk(1, "%s: channel busy\n", __func__); |
1010 | ret = -EBUSY; | 1018 | ret = -EBUSY; |
1011 | goto out_s_fmt; | 1019 | goto out_s_fmt; |
1012 | } | 1020 | } |
1013 | 1021 | mode = channel->mode; | |
1014 | fh->fmt = fmt; | 1022 | channel->fmt = fmt; |
1015 | fh->width = f->fmt.pix.width; | 1023 | channel->width = f->fmt.pix.width; |
1016 | fh->height = f->fmt.pix.height; | 1024 | channel->height = f->fmt.pix.height; |
1017 | fh->vb_vidq.field = f->fmt.pix.field; | 1025 | fh->vb_vidq.field = f->fmt.pix.field; |
1018 | fh->type = f->type; | 1026 | fh->type = f->type; |
1019 | norm = norm_minw(&fh->dev->vdev[fh->channel]); | 1027 | norm = norm_minw(&channel->vdev); |
1020 | if (fh->width > norm_minw(&fh->dev->vdev[fh->channel])) { | 1028 | if (channel->width > norm_minw(&channel->vdev)) { |
1021 | if (fh->height > norm_minh(&fh->dev->vdev[fh->channel])) { | 1029 | if (channel->height > norm_minh(&channel->vdev)) { |
1022 | if (fh->dev->cap_parm[fh->channel].capturemode & | 1030 | if (channel->cap_parm.capturemode & |
1023 | V4L2_MODE_HIGHQUALITY) | 1031 | V4L2_MODE_HIGHQUALITY) |
1024 | fh->mode.scale = SCALE_4CIFSI; | 1032 | mode.scale = SCALE_4CIFSI; |
1025 | else | 1033 | else |
1026 | fh->mode.scale = SCALE_4CIFS; | 1034 | mode.scale = SCALE_4CIFS; |
1027 | } else | 1035 | } else |
1028 | fh->mode.scale = SCALE_2CIFS; | 1036 | mode.scale = SCALE_2CIFS; |
1029 | 1037 | ||
1030 | } else { | 1038 | } else { |
1031 | fh->mode.scale = SCALE_1CIFS; | 1039 | mode.scale = SCALE_1CIFS; |
1032 | } | 1040 | } |
1033 | |||
1034 | /* color mode */ | 1041 | /* color mode */ |
1035 | switch (fh->fmt->fourcc) { | 1042 | switch (channel->fmt->fourcc) { |
1036 | case V4L2_PIX_FMT_GREY: | 1043 | case V4L2_PIX_FMT_GREY: |
1037 | fh->mode.color &= ~MASK_COLOR; | 1044 | mode.color &= ~MASK_COLOR; |
1038 | fh->mode.color |= COLOR_Y8; | 1045 | mode.color |= COLOR_Y8; |
1039 | break; | 1046 | break; |
1040 | case V4L2_PIX_FMT_JPEG: | 1047 | case V4L2_PIX_FMT_JPEG: |
1041 | fh->mode.color &= ~MASK_COLOR; | 1048 | mode.color &= ~MASK_COLOR; |
1042 | fh->mode.color |= COLOR_JPG; | 1049 | mode.color |= COLOR_JPG; |
1043 | fh->mode.color |= (fh->dev->jc[fh->channel].quality << 8); | 1050 | mode.color |= (channel->jc.quality << 8); |
1044 | break; | 1051 | break; |
1045 | case V4L2_PIX_FMT_YUV422P: | 1052 | case V4L2_PIX_FMT_YUV422P: |
1046 | fh->mode.color &= ~MASK_COLOR; | 1053 | mode.color &= ~MASK_COLOR; |
1047 | fh->mode.color |= COLOR_YUVPL; | 1054 | mode.color |= COLOR_YUVPL; |
1048 | break; | 1055 | break; |
1049 | case V4L2_PIX_FMT_YUYV: | 1056 | case V4L2_PIX_FMT_YUYV: |
1050 | case V4L2_PIX_FMT_UYVY: | 1057 | case V4L2_PIX_FMT_UYVY: |
1051 | default: | 1058 | default: |
1052 | fh->mode.color &= ~MASK_COLOR; | 1059 | mode.color &= ~MASK_COLOR; |
1053 | fh->mode.color |= COLOR_YUVPK; | 1060 | mode.color |= COLOR_YUVPK; |
1054 | break; | 1061 | break; |
1055 | } | 1062 | } |
1063 | if ((mode.color & MASK_COLOR) != (channel->mode.color & MASK_COLOR)) | ||
1064 | mode.restart = 1; | ||
1065 | else if (mode.scale != channel->mode.scale) | ||
1066 | mode.restart = 1; | ||
1067 | else if (mode.format != channel->mode.format) | ||
1068 | mode.restart = 1; | ||
1069 | channel->mode = mode; | ||
1070 | (void) s2255_set_mode(channel, &mode); | ||
1056 | ret = 0; | 1071 | ret = 0; |
1057 | out_s_fmt: | 1072 | out_s_fmt: |
1058 | mutex_unlock(&q->vb_lock); | 1073 | mutex_unlock(&q->vb_lock); |
@@ -1197,26 +1212,27 @@ static void s2255_print_cfg(struct s2255_dev *sdev, struct s2255_mode *mode) | |||
1197 | * When the restart parameter is set, we sleep for ONE frame to allow the | 1212 | * When the restart parameter is set, we sleep for ONE frame to allow the |
1198 | * DSP time to get the new frame | 1213 | * DSP time to get the new frame |
1199 | */ | 1214 | */ |
1200 | static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, | 1215 | static int s2255_set_mode(struct s2255_channel *channel, |
1201 | struct s2255_mode *mode) | 1216 | struct s2255_mode *mode) |
1202 | { | 1217 | { |
1203 | int res; | 1218 | int res; |
1204 | __le32 *buffer; | 1219 | __le32 *buffer; |
1205 | unsigned long chn_rev; | 1220 | unsigned long chn_rev; |
1221 | struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev); | ||
1206 | mutex_lock(&dev->lock); | 1222 | mutex_lock(&dev->lock); |
1207 | chn_rev = G_chnmap[chn]; | 1223 | chn_rev = G_chnmap[channel->idx]; |
1208 | dprintk(3, "%s channel %lu\n", __func__, chn); | 1224 | dprintk(3, "%s channel: %d\n", __func__, channel->idx); |
1209 | /* if JPEG, set the quality */ | 1225 | /* if JPEG, set the quality */ |
1210 | if ((mode->color & MASK_COLOR) == COLOR_JPG) { | 1226 | if ((mode->color & MASK_COLOR) == COLOR_JPG) { |
1211 | mode->color &= ~MASK_COLOR; | 1227 | mode->color &= ~MASK_COLOR; |
1212 | mode->color |= COLOR_JPG; | 1228 | mode->color |= COLOR_JPG; |
1213 | mode->color &= ~MASK_JPG_QUALITY; | 1229 | mode->color &= ~MASK_JPG_QUALITY; |
1214 | mode->color |= (dev->jc[chn].quality << 8); | 1230 | mode->color |= (channel->jc.quality << 8); |
1215 | } | 1231 | } |
1216 | /* save the mode */ | 1232 | /* save the mode */ |
1217 | dev->mode[chn] = *mode; | 1233 | channel->mode = *mode; |
1218 | dev->req_image_size[chn] = get_transfer_size(mode); | 1234 | channel->req_image_size = get_transfer_size(mode); |
1219 | dprintk(1, "%s: reqsize %ld\n", __func__, dev->req_image_size[chn]); | 1235 | dprintk(1, "%s: reqsize %ld\n", __func__, channel->req_image_size); |
1220 | buffer = kzalloc(512, GFP_KERNEL); | 1236 | buffer = kzalloc(512, GFP_KERNEL); |
1221 | if (buffer == NULL) { | 1237 | if (buffer == NULL) { |
1222 | dev_err(&dev->udev->dev, "out of mem\n"); | 1238 | dev_err(&dev->udev->dev, "out of mem\n"); |
@@ -1227,38 +1243,38 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, | |||
1227 | buffer[0] = IN_DATA_TOKEN; | 1243 | buffer[0] = IN_DATA_TOKEN; |
1228 | buffer[1] = (__le32) cpu_to_le32(chn_rev); | 1244 | buffer[1] = (__le32) cpu_to_le32(chn_rev); |
1229 | buffer[2] = CMD_SET_MODE; | 1245 | buffer[2] = CMD_SET_MODE; |
1230 | memcpy(&buffer[3], &dev->mode[chn], sizeof(struct s2255_mode)); | 1246 | memcpy(&buffer[3], &channel->mode, sizeof(struct s2255_mode)); |
1231 | dev->setmode_ready[chn] = 0; | 1247 | channel->setmode_ready = 0; |
1232 | res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); | 1248 | res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); |
1233 | if (debug) | 1249 | if (debug) |
1234 | s2255_print_cfg(dev, mode); | 1250 | s2255_print_cfg(dev, mode); |
1235 | kfree(buffer); | 1251 | kfree(buffer); |
1236 | /* wait at least 3 frames before continuing */ | 1252 | /* wait at least 3 frames before continuing */ |
1237 | if (mode->restart) { | 1253 | if (mode->restart) { |
1238 | wait_event_timeout(dev->wait_setmode[chn], | 1254 | wait_event_timeout(channel->wait_setmode, |
1239 | (dev->setmode_ready[chn] != 0), | 1255 | (channel->setmode_ready != 0), |
1240 | msecs_to_jiffies(S2255_SETMODE_TIMEOUT)); | 1256 | msecs_to_jiffies(S2255_SETMODE_TIMEOUT)); |
1241 | if (dev->setmode_ready[chn] != 1) { | 1257 | if (channel->setmode_ready != 1) { |
1242 | printk(KERN_DEBUG "s2255: no set mode response\n"); | 1258 | printk(KERN_DEBUG "s2255: no set mode response\n"); |
1243 | res = -EFAULT; | 1259 | res = -EFAULT; |
1244 | } | 1260 | } |
1245 | } | 1261 | } |
1246 | /* clear the restart flag */ | 1262 | /* clear the restart flag */ |
1247 | dev->mode[chn].restart = 0; | 1263 | channel->mode.restart = 0; |
1248 | mutex_unlock(&dev->lock); | 1264 | mutex_unlock(&dev->lock); |
1249 | dprintk(1, "%s chn %lu, result: %d\n", __func__, chn, res); | 1265 | dprintk(1, "%s chn %d, result: %d\n", __func__, channel->idx, res); |
1250 | return res; | 1266 | return res; |
1251 | } | 1267 | } |
1252 | 1268 | ||
1253 | static int s2255_cmd_status(struct s2255_dev *dev, unsigned long chn, | 1269 | static int s2255_cmd_status(struct s2255_channel *channel, u32 *pstatus) |
1254 | u32 *pstatus) | ||
1255 | { | 1270 | { |
1256 | int res; | 1271 | int res; |
1257 | __le32 *buffer; | 1272 | __le32 *buffer; |
1258 | u32 chn_rev; | 1273 | u32 chn_rev; |
1274 | struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev); | ||
1259 | mutex_lock(&dev->lock); | 1275 | mutex_lock(&dev->lock); |
1260 | chn_rev = G_chnmap[chn]; | 1276 | chn_rev = G_chnmap[channel->idx]; |
1261 | dprintk(4, "%s chan %lu\n", __func__, chn); | 1277 | dprintk(4, "%s chan %d\n", __func__, channel->idx); |
1262 | buffer = kzalloc(512, GFP_KERNEL); | 1278 | buffer = kzalloc(512, GFP_KERNEL); |
1263 | if (buffer == NULL) { | 1279 | if (buffer == NULL) { |
1264 | dev_err(&dev->udev->dev, "out of mem\n"); | 1280 | dev_err(&dev->udev->dev, "out of mem\n"); |
@@ -1270,17 +1286,17 @@ static int s2255_cmd_status(struct s2255_dev *dev, unsigned long chn, | |||
1270 | buffer[1] = (__le32) cpu_to_le32(chn_rev); | 1286 | buffer[1] = (__le32) cpu_to_le32(chn_rev); |
1271 | buffer[2] = CMD_STATUS; | 1287 | buffer[2] = CMD_STATUS; |
1272 | *pstatus = 0; | 1288 | *pstatus = 0; |
1273 | dev->vidstatus_ready[chn] = 0; | 1289 | channel->vidstatus_ready = 0; |
1274 | res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); | 1290 | res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); |
1275 | kfree(buffer); | 1291 | kfree(buffer); |
1276 | wait_event_timeout(dev->wait_vidstatus[chn], | 1292 | wait_event_timeout(channel->wait_vidstatus, |
1277 | (dev->vidstatus_ready[chn] != 0), | 1293 | (channel->vidstatus_ready != 0), |
1278 | msecs_to_jiffies(S2255_VIDSTATUS_TIMEOUT)); | 1294 | msecs_to_jiffies(S2255_VIDSTATUS_TIMEOUT)); |
1279 | if (dev->vidstatus_ready[chn] != 1) { | 1295 | if (channel->vidstatus_ready != 1) { |
1280 | printk(KERN_DEBUG "s2255: no vidstatus response\n"); | 1296 | printk(KERN_DEBUG "s2255: no vidstatus response\n"); |
1281 | res = -EFAULT; | 1297 | res = -EFAULT; |
1282 | } | 1298 | } |
1283 | *pstatus = dev->vidstatus[chn]; | 1299 | *pstatus = channel->vidstatus; |
1284 | dprintk(4, "%s, vid status %d\n", __func__, *pstatus); | 1300 | dprintk(4, "%s, vid status %d\n", __func__, *pstatus); |
1285 | mutex_unlock(&dev->lock); | 1301 | mutex_unlock(&dev->lock); |
1286 | return res; | 1302 | return res; |
@@ -1291,9 +1307,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
1291 | int res; | 1307 | int res; |
1292 | struct s2255_fh *fh = priv; | 1308 | struct s2255_fh *fh = priv; |
1293 | struct s2255_dev *dev = fh->dev; | 1309 | struct s2255_dev *dev = fh->dev; |
1294 | struct s2255_mode *new_mode; | 1310 | struct s2255_channel *channel = fh->channel; |
1295 | struct s2255_mode *old_mode; | ||
1296 | int chn; | ||
1297 | int j; | 1311 | int j; |
1298 | dprintk(4, "%s\n", __func__); | 1312 | dprintk(4, "%s\n", __func__); |
1299 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1313 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
@@ -1305,51 +1319,32 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
1305 | return -EINVAL; | 1319 | return -EINVAL; |
1306 | } | 1320 | } |
1307 | 1321 | ||
1308 | if (!res_get(dev, fh)) { | 1322 | if (!res_get(fh)) { |
1309 | s2255_dev_err(&dev->udev->dev, "stream busy\n"); | 1323 | s2255_dev_err(&dev->udev->dev, "stream busy\n"); |
1310 | return -EBUSY; | 1324 | return -EBUSY; |
1311 | } | 1325 | } |
1312 | 1326 | channel->last_frame = -1; | |
1313 | /* send a set mode command everytime with restart. | 1327 | channel->bad_payload = 0; |
1314 | in case we switch resolutions or other parameters */ | 1328 | channel->cur_frame = 0; |
1315 | chn = fh->channel; | 1329 | channel->frame_count = 0; |
1316 | new_mode = &fh->mode; | ||
1317 | old_mode = &fh->dev->mode[chn]; | ||
1318 | |||
1319 | if ((new_mode->color & MASK_COLOR) != (old_mode->color & MASK_COLOR)) | ||
1320 | new_mode->restart = 1; | ||
1321 | else if (new_mode->scale != old_mode->scale) | ||
1322 | new_mode->restart = 1; | ||
1323 | else if (new_mode->format != old_mode->format) | ||
1324 | new_mode->restart = 1; | ||
1325 | |||
1326 | s2255_set_mode(dev, chn, new_mode); | ||
1327 | new_mode->restart = 0; | ||
1328 | *old_mode = *new_mode; | ||
1329 | dev->cur_fmt[chn] = fh->fmt; | ||
1330 | dev->last_frame[chn] = -1; | ||
1331 | dev->bad_payload[chn] = 0; | ||
1332 | dev->cur_frame[chn] = 0; | ||
1333 | dev->frame_count[chn] = 0; | ||
1334 | for (j = 0; j < SYS_FRAMES; j++) { | 1330 | for (j = 0; j < SYS_FRAMES; j++) { |
1335 | dev->buffer[chn].frame[j].ulState = S2255_READ_IDLE; | 1331 | channel->buffer.frame[j].ulState = S2255_READ_IDLE; |
1336 | dev->buffer[chn].frame[j].cur_size = 0; | 1332 | channel->buffer.frame[j].cur_size = 0; |
1337 | } | 1333 | } |
1338 | res = videobuf_streamon(&fh->vb_vidq); | 1334 | res = videobuf_streamon(&fh->vb_vidq); |
1339 | if (res == 0) { | 1335 | if (res == 0) { |
1340 | s2255_start_acquire(dev, chn); | 1336 | s2255_start_acquire(channel); |
1341 | dev->b_acquire[chn] = 1; | 1337 | channel->b_acquire = 1; |
1342 | } else { | 1338 | } else |
1343 | res_free(dev, fh); | 1339 | res_free(fh); |
1344 | } | 1340 | |
1345 | return res; | 1341 | return res; |
1346 | } | 1342 | } |
1347 | 1343 | ||
1348 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | 1344 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) |
1349 | { | 1345 | { |
1350 | struct s2255_fh *fh = priv; | 1346 | struct s2255_fh *fh = priv; |
1351 | struct s2255_dev *dev = fh->dev; | 1347 | dprintk(4, "%s\n, channel: %d", __func__, fh->channel->idx); |
1352 | dprintk(4, "%s\n, channel: %d", __func__, fh->channel); | ||
1353 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1348 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
1354 | printk(KERN_ERR "invalid fh type0\n"); | 1349 | printk(KERN_ERR "invalid fh type0\n"); |
1355 | return -EINVAL; | 1350 | return -EINVAL; |
@@ -1358,16 +1353,16 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
1358 | printk(KERN_ERR "invalid type i\n"); | 1353 | printk(KERN_ERR "invalid type i\n"); |
1359 | return -EINVAL; | 1354 | return -EINVAL; |
1360 | } | 1355 | } |
1361 | s2255_stop_acquire(dev, fh->channel); | 1356 | s2255_stop_acquire(fh->channel); |
1362 | videobuf_streamoff(&fh->vb_vidq); | 1357 | videobuf_streamoff(&fh->vb_vidq); |
1363 | res_free(dev, fh); | 1358 | res_free(fh); |
1364 | return 0; | 1359 | return 0; |
1365 | } | 1360 | } |
1366 | 1361 | ||
1367 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) | 1362 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) |
1368 | { | 1363 | { |
1369 | struct s2255_fh *fh = priv; | 1364 | struct s2255_fh *fh = priv; |
1370 | struct s2255_mode *mode; | 1365 | struct s2255_mode mode; |
1371 | struct videobuf_queue *q = &fh->vb_vidq; | 1366 | struct videobuf_queue *q = &fh->vb_vidq; |
1372 | int ret = 0; | 1367 | int ret = 0; |
1373 | mutex_lock(&q->vb_lock); | 1368 | mutex_lock(&q->vb_lock); |
@@ -1376,29 +1371,32 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) | |||
1376 | ret = -EBUSY; | 1371 | ret = -EBUSY; |
1377 | goto out_s_std; | 1372 | goto out_s_std; |
1378 | } | 1373 | } |
1379 | if (res_locked(fh->dev, fh)) { | 1374 | if (res_locked(fh)) { |
1380 | dprintk(1, "can't change standard after started\n"); | 1375 | dprintk(1, "can't change standard after started\n"); |
1381 | ret = -EBUSY; | 1376 | ret = -EBUSY; |
1382 | goto out_s_std; | 1377 | goto out_s_std; |
1383 | } | 1378 | } |
1384 | mode = &fh->mode; | 1379 | mode = fh->channel->mode; |
1385 | if (*i & V4L2_STD_NTSC) { | 1380 | if (*i & V4L2_STD_NTSC) { |
1386 | dprintk(4, "%s NTSC\n", __func__); | 1381 | dprintk(4, "%s NTSC\n", __func__); |
1387 | /* if changing format, reset frame decimation/intervals */ | 1382 | /* if changing format, reset frame decimation/intervals */ |
1388 | if (mode->format != FORMAT_NTSC) { | 1383 | if (mode.format != FORMAT_NTSC) { |
1389 | mode->format = FORMAT_NTSC; | 1384 | mode.restart = 1; |
1390 | mode->fdec = FDEC_1; | 1385 | mode.format = FORMAT_NTSC; |
1386 | mode.fdec = FDEC_1; | ||
1391 | } | 1387 | } |
1392 | } else if (*i & V4L2_STD_PAL) { | 1388 | } else if (*i & V4L2_STD_PAL) { |
1393 | dprintk(4, "%s PAL\n", __func__); | 1389 | dprintk(4, "%s PAL\n", __func__); |
1394 | mode->format = FORMAT_PAL; | 1390 | if (mode.format != FORMAT_PAL) { |
1395 | if (mode->format != FORMAT_PAL) { | 1391 | mode.restart = 1; |
1396 | mode->format = FORMAT_PAL; | 1392 | mode.format = FORMAT_PAL; |
1397 | mode->fdec = FDEC_1; | 1393 | mode.fdec = FDEC_1; |
1398 | } | 1394 | } |
1399 | } else { | 1395 | } else { |
1400 | ret = -EINVAL; | 1396 | ret = -EINVAL; |
1401 | } | 1397 | } |
1398 | if (mode.restart) | ||
1399 | s2255_set_mode(fh->channel, &mode); | ||
1402 | out_s_std: | 1400 | out_s_std: |
1403 | mutex_unlock(&q->vb_lock); | 1401 | mutex_unlock(&q->vb_lock); |
1404 | return ret; | 1402 | return ret; |
@@ -1416,6 +1414,7 @@ static int vidioc_enum_input(struct file *file, void *priv, | |||
1416 | { | 1414 | { |
1417 | struct s2255_fh *fh = priv; | 1415 | struct s2255_fh *fh = priv; |
1418 | struct s2255_dev *dev = fh->dev; | 1416 | struct s2255_dev *dev = fh->dev; |
1417 | struct s2255_channel *channel = fh->channel; | ||
1419 | u32 status = 0; | 1418 | u32 status = 0; |
1420 | if (inp->index != 0) | 1419 | if (inp->index != 0) |
1421 | return -EINVAL; | 1420 | return -EINVAL; |
@@ -1424,7 +1423,7 @@ static int vidioc_enum_input(struct file *file, void *priv, | |||
1424 | inp->status = 0; | 1423 | inp->status = 0; |
1425 | if (dev->dsp_fw_ver >= S2255_MIN_DSP_STATUS) { | 1424 | if (dev->dsp_fw_ver >= S2255_MIN_DSP_STATUS) { |
1426 | int rc; | 1425 | int rc; |
1427 | rc = s2255_cmd_status(dev, fh->channel, &status); | 1426 | rc = s2255_cmd_status(fh->channel, &status); |
1428 | dprintk(4, "s2255_cmd_status rc: %d status %x\n", rc, status); | 1427 | dprintk(4, "s2255_cmd_status rc: %d status %x\n", rc, status); |
1429 | if (rc == 0) | 1428 | if (rc == 0) |
1430 | inp->status = (status & 0x01) ? 0 | 1429 | inp->status = (status & 0x01) ? 0 |
@@ -1436,7 +1435,7 @@ static int vidioc_enum_input(struct file *file, void *priv, | |||
1436 | strlcpy(inp->name, "Composite", sizeof(inp->name)); | 1435 | strlcpy(inp->name, "Composite", sizeof(inp->name)); |
1437 | break; | 1436 | break; |
1438 | case 0x2257: | 1437 | case 0x2257: |
1439 | strlcpy(inp->name, (fh->channel < 2) ? "Composite" : "S-Video", | 1438 | strlcpy(inp->name, (channel->idx < 2) ? "Composite" : "S-Video", |
1440 | sizeof(inp->name)); | 1439 | sizeof(inp->name)); |
1441 | break; | 1440 | break; |
1442 | } | 1441 | } |
@@ -1460,6 +1459,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
1460 | struct v4l2_queryctrl *qc) | 1459 | struct v4l2_queryctrl *qc) |
1461 | { | 1460 | { |
1462 | struct s2255_fh *fh = priv; | 1461 | struct s2255_fh *fh = priv; |
1462 | struct s2255_channel *channel = fh->channel; | ||
1463 | struct s2255_dev *dev = fh->dev; | 1463 | struct s2255_dev *dev = fh->dev; |
1464 | switch (qc->id) { | 1464 | switch (qc->id) { |
1465 | case V4L2_CID_BRIGHTNESS: | 1465 | case V4L2_CID_BRIGHTNESS: |
@@ -1477,7 +1477,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
1477 | case V4L2_CID_PRIVATE_COLORFILTER: | 1477 | case V4L2_CID_PRIVATE_COLORFILTER: |
1478 | if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER) | 1478 | if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER) |
1479 | return -EINVAL; | 1479 | return -EINVAL; |
1480 | if ((dev->pid == 0x2257) && (fh->channel > 1)) | 1480 | if ((dev->pid == 0x2257) && (channel->idx > 1)) |
1481 | return -EINVAL; | 1481 | return -EINVAL; |
1482 | strlcpy(qc->name, "Color Filter", sizeof(qc->name)); | 1482 | strlcpy(qc->name, "Color Filter", sizeof(qc->name)); |
1483 | qc->type = V4L2_CTRL_TYPE_MENU; | 1483 | qc->type = V4L2_CTRL_TYPE_MENU; |
@@ -1499,25 +1499,26 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
1499 | { | 1499 | { |
1500 | struct s2255_fh *fh = priv; | 1500 | struct s2255_fh *fh = priv; |
1501 | struct s2255_dev *dev = fh->dev; | 1501 | struct s2255_dev *dev = fh->dev; |
1502 | struct s2255_channel *channel = fh->channel; | ||
1502 | switch (ctrl->id) { | 1503 | switch (ctrl->id) { |
1503 | case V4L2_CID_BRIGHTNESS: | 1504 | case V4L2_CID_BRIGHTNESS: |
1504 | ctrl->value = fh->mode.bright; | 1505 | ctrl->value = channel->mode.bright; |
1505 | break; | 1506 | break; |
1506 | case V4L2_CID_CONTRAST: | 1507 | case V4L2_CID_CONTRAST: |
1507 | ctrl->value = fh->mode.contrast; | 1508 | ctrl->value = channel->mode.contrast; |
1508 | break; | 1509 | break; |
1509 | case V4L2_CID_SATURATION: | 1510 | case V4L2_CID_SATURATION: |
1510 | ctrl->value = fh->mode.saturation; | 1511 | ctrl->value = channel->mode.saturation; |
1511 | break; | 1512 | break; |
1512 | case V4L2_CID_HUE: | 1513 | case V4L2_CID_HUE: |
1513 | ctrl->value = fh->mode.hue; | 1514 | ctrl->value = channel->mode.hue; |
1514 | break; | 1515 | break; |
1515 | case V4L2_CID_PRIVATE_COLORFILTER: | 1516 | case V4L2_CID_PRIVATE_COLORFILTER: |
1516 | if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER) | 1517 | if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER) |
1517 | return -EINVAL; | 1518 | return -EINVAL; |
1518 | if ((dev->pid == 0x2257) && (fh->channel > 1)) | 1519 | if ((dev->pid == 0x2257) && (channel->idx > 1)) |
1519 | return -EINVAL; | 1520 | return -EINVAL; |
1520 | ctrl->value = !((fh->mode.color & MASK_INPUT_TYPE) >> 16); | 1521 | ctrl->value = !((channel->mode.color & MASK_INPUT_TYPE) >> 16); |
1521 | break; | 1522 | break; |
1522 | default: | 1523 | default: |
1523 | return -EINVAL; | 1524 | return -EINVAL; |
@@ -1530,41 +1531,42 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
1530 | struct v4l2_control *ctrl) | 1531 | struct v4l2_control *ctrl) |
1531 | { | 1532 | { |
1532 | struct s2255_fh *fh = priv; | 1533 | struct s2255_fh *fh = priv; |
1533 | struct s2255_dev *dev = fh->dev; | 1534 | struct s2255_channel *channel = fh->channel; |
1534 | struct s2255_mode *mode; | 1535 | struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev); |
1535 | mode = &fh->mode; | 1536 | struct s2255_mode mode; |
1537 | mode = channel->mode; | ||
1536 | dprintk(4, "%s\n", __func__); | 1538 | dprintk(4, "%s\n", __func__); |
1537 | /* update the mode to the corresponding value */ | 1539 | /* update the mode to the corresponding value */ |
1538 | switch (ctrl->id) { | 1540 | switch (ctrl->id) { |
1539 | case V4L2_CID_BRIGHTNESS: | 1541 | case V4L2_CID_BRIGHTNESS: |
1540 | mode->bright = ctrl->value; | 1542 | mode.bright = ctrl->value; |
1541 | break; | 1543 | break; |
1542 | case V4L2_CID_CONTRAST: | 1544 | case V4L2_CID_CONTRAST: |
1543 | mode->contrast = ctrl->value; | 1545 | mode.contrast = ctrl->value; |
1544 | break; | 1546 | break; |
1545 | case V4L2_CID_HUE: | 1547 | case V4L2_CID_HUE: |
1546 | mode->hue = ctrl->value; | 1548 | mode.hue = ctrl->value; |
1547 | break; | 1549 | break; |
1548 | case V4L2_CID_SATURATION: | 1550 | case V4L2_CID_SATURATION: |
1549 | mode->saturation = ctrl->value; | 1551 | mode.saturation = ctrl->value; |
1550 | break; | 1552 | break; |
1551 | case V4L2_CID_PRIVATE_COLORFILTER: | 1553 | case V4L2_CID_PRIVATE_COLORFILTER: |
1552 | if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER) | 1554 | if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER) |
1553 | return -EINVAL; | 1555 | return -EINVAL; |
1554 | if ((dev->pid == 0x2257) && (fh->channel > 1)) | 1556 | if ((dev->pid == 0x2257) && (channel->idx > 1)) |
1555 | return -EINVAL; | 1557 | return -EINVAL; |
1556 | mode->color &= ~MASK_INPUT_TYPE; | 1558 | mode.color &= ~MASK_INPUT_TYPE; |
1557 | mode->color |= ((ctrl->value ? 0 : 1) << 16); | 1559 | mode.color |= ((ctrl->value ? 0 : 1) << 16); |
1558 | break; | 1560 | break; |
1559 | default: | 1561 | default: |
1560 | return -EINVAL; | 1562 | return -EINVAL; |
1561 | } | 1563 | } |
1562 | mode->restart = 0; | 1564 | mode.restart = 0; |
1563 | /* set mode here. Note: stream does not need restarted. | 1565 | /* set mode here. Note: stream does not need restarted. |
1564 | some V4L programs restart stream unnecessarily | 1566 | some V4L programs restart stream unnecessarily |
1565 | after a s_crtl. | 1567 | after a s_crtl. |
1566 | */ | 1568 | */ |
1567 | s2255_set_mode(dev, fh->channel, mode); | 1569 | s2255_set_mode(fh->channel, &mode); |
1568 | return 0; | 1570 | return 0; |
1569 | } | 1571 | } |
1570 | 1572 | ||
@@ -1572,8 +1574,8 @@ static int vidioc_g_jpegcomp(struct file *file, void *priv, | |||
1572 | struct v4l2_jpegcompression *jc) | 1574 | struct v4l2_jpegcompression *jc) |
1573 | { | 1575 | { |
1574 | struct s2255_fh *fh = priv; | 1576 | struct s2255_fh *fh = priv; |
1575 | struct s2255_dev *dev = fh->dev; | 1577 | struct s2255_channel *channel = fh->channel; |
1576 | *jc = dev->jc[fh->channel]; | 1578 | *jc = channel->jc; |
1577 | dprintk(2, "%s: quality %d\n", __func__, jc->quality); | 1579 | dprintk(2, "%s: quality %d\n", __func__, jc->quality); |
1578 | return 0; | 1580 | return 0; |
1579 | } | 1581 | } |
@@ -1582,10 +1584,10 @@ static int vidioc_s_jpegcomp(struct file *file, void *priv, | |||
1582 | struct v4l2_jpegcompression *jc) | 1584 | struct v4l2_jpegcompression *jc) |
1583 | { | 1585 | { |
1584 | struct s2255_fh *fh = priv; | 1586 | struct s2255_fh *fh = priv; |
1585 | struct s2255_dev *dev = fh->dev; | 1587 | struct s2255_channel *channel = fh->channel; |
1586 | if (jc->quality < 0 || jc->quality > 100) | 1588 | if (jc->quality < 0 || jc->quality > 100) |
1587 | return -EINVAL; | 1589 | return -EINVAL; |
1588 | dev->jc[fh->channel].quality = jc->quality; | 1590 | channel->jc.quality = jc->quality; |
1589 | dprintk(2, "%s: quality %d\n", __func__, jc->quality); | 1591 | dprintk(2, "%s: quality %d\n", __func__, jc->quality); |
1590 | return 0; | 1592 | return 0; |
1591 | } | 1593 | } |
@@ -1594,17 +1596,17 @@ static int vidioc_g_parm(struct file *file, void *priv, | |||
1594 | struct v4l2_streamparm *sp) | 1596 | struct v4l2_streamparm *sp) |
1595 | { | 1597 | { |
1596 | struct s2255_fh *fh = priv; | 1598 | struct s2255_fh *fh = priv; |
1597 | struct s2255_dev *dev = fh->dev; | ||
1598 | __u32 def_num, def_dem; | 1599 | __u32 def_num, def_dem; |
1600 | struct s2255_channel *channel = fh->channel; | ||
1599 | if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1601 | if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1600 | return -EINVAL; | 1602 | return -EINVAL; |
1601 | memset(sp, 0, sizeof(struct v4l2_streamparm)); | 1603 | memset(sp, 0, sizeof(struct v4l2_streamparm)); |
1602 | sp->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; | 1604 | sp->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; |
1603 | sp->parm.capture.capturemode = dev->cap_parm[fh->channel].capturemode; | 1605 | sp->parm.capture.capturemode = channel->cap_parm.capturemode; |
1604 | def_num = (fh->mode.format == FORMAT_NTSC) ? 1001 : 1000; | 1606 | def_num = (channel->mode.format == FORMAT_NTSC) ? 1001 : 1000; |
1605 | def_dem = (fh->mode.format == FORMAT_NTSC) ? 30000 : 25000; | 1607 | def_dem = (channel->mode.format == FORMAT_NTSC) ? 30000 : 25000; |
1606 | sp->parm.capture.timeperframe.denominator = def_dem; | 1608 | sp->parm.capture.timeperframe.denominator = def_dem; |
1607 | switch (fh->mode.fdec) { | 1609 | switch (channel->mode.fdec) { |
1608 | default: | 1610 | default: |
1609 | case FDEC_1: | 1611 | case FDEC_1: |
1610 | sp->parm.capture.timeperframe.numerator = def_num; | 1612 | sp->parm.capture.timeperframe.numerator = def_num; |
@@ -1630,17 +1632,19 @@ static int vidioc_s_parm(struct file *file, void *priv, | |||
1630 | struct v4l2_streamparm *sp) | 1632 | struct v4l2_streamparm *sp) |
1631 | { | 1633 | { |
1632 | struct s2255_fh *fh = priv; | 1634 | struct s2255_fh *fh = priv; |
1633 | struct s2255_dev *dev = fh->dev; | 1635 | struct s2255_channel *channel = fh->channel; |
1636 | struct s2255_mode mode; | ||
1634 | int fdec = FDEC_1; | 1637 | int fdec = FDEC_1; |
1635 | __u32 def_num, def_dem; | 1638 | __u32 def_num, def_dem; |
1636 | if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1639 | if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1637 | return -EINVAL; | 1640 | return -EINVAL; |
1641 | mode = channel->mode; | ||
1638 | /* high quality capture mode requires a stream restart */ | 1642 | /* high quality capture mode requires a stream restart */ |
1639 | if (dev->cap_parm[fh->channel].capturemode | 1643 | if (channel->cap_parm.capturemode |
1640 | != sp->parm.capture.capturemode && res_locked(fh->dev, fh)) | 1644 | != sp->parm.capture.capturemode && res_locked(fh)) |
1641 | return -EBUSY; | 1645 | return -EBUSY; |
1642 | def_num = (fh->mode.format == FORMAT_NTSC) ? 1001 : 1000; | 1646 | def_num = (mode.format == FORMAT_NTSC) ? 1001 : 1000; |
1643 | def_dem = (fh->mode.format == FORMAT_NTSC) ? 30000 : 25000; | 1647 | def_dem = (mode.format == FORMAT_NTSC) ? 30000 : 25000; |
1644 | if (def_dem != sp->parm.capture.timeperframe.denominator) | 1648 | if (def_dem != sp->parm.capture.timeperframe.denominator) |
1645 | sp->parm.capture.timeperframe.numerator = def_num; | 1649 | sp->parm.capture.timeperframe.numerator = def_num; |
1646 | else if (sp->parm.capture.timeperframe.numerator <= def_num) | 1650 | else if (sp->parm.capture.timeperframe.numerator <= def_num) |
@@ -1655,9 +1659,9 @@ static int vidioc_s_parm(struct file *file, void *priv, | |||
1655 | sp->parm.capture.timeperframe.numerator = def_num * 5; | 1659 | sp->parm.capture.timeperframe.numerator = def_num * 5; |
1656 | fdec = FDEC_5; | 1660 | fdec = FDEC_5; |
1657 | } | 1661 | } |
1658 | fh->mode.fdec = fdec; | 1662 | mode.fdec = fdec; |
1659 | sp->parm.capture.timeperframe.denominator = def_dem; | 1663 | sp->parm.capture.timeperframe.denominator = def_dem; |
1660 | s2255_set_mode(dev, fh->channel, &fh->mode); | 1664 | s2255_set_mode(channel, &mode); |
1661 | dprintk(4, "%s capture mode, %d timeperframe %d/%d, fdec %d\n", | 1665 | dprintk(4, "%s capture mode, %d timeperframe %d/%d, fdec %d\n", |
1662 | __func__, | 1666 | __func__, |
1663 | sp->parm.capture.capturemode, | 1667 | sp->parm.capture.capturemode, |
@@ -1707,24 +1711,13 @@ static int vidioc_enum_frameintervals(struct file *file, void *priv, | |||
1707 | static int s2255_open(struct file *file) | 1711 | static int s2255_open(struct file *file) |
1708 | { | 1712 | { |
1709 | struct video_device *vdev = video_devdata(file); | 1713 | struct video_device *vdev = video_devdata(file); |
1710 | struct s2255_dev *dev = video_drvdata(file); | 1714 | struct s2255_channel *channel = video_drvdata(file); |
1715 | struct s2255_dev *dev = to_s2255_dev(vdev->v4l2_dev); | ||
1711 | struct s2255_fh *fh; | 1716 | struct s2255_fh *fh; |
1712 | enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1717 | enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1713 | int i = 0; | ||
1714 | int cur_channel = -1; | ||
1715 | int state; | 1718 | int state; |
1716 | dprintk(1, "s2255: open called (dev=%s)\n", | 1719 | dprintk(1, "s2255: open called (dev=%s)\n", |
1717 | video_device_node_name(vdev)); | 1720 | video_device_node_name(vdev)); |
1718 | |||
1719 | for (i = 0; i < MAX_CHANNELS; i++) { | ||
1720 | if (&dev->vdev[i] == vdev) { | ||
1721 | cur_channel = i; | ||
1722 | break; | ||
1723 | } | ||
1724 | } | ||
1725 | if (i == MAX_CHANNELS) | ||
1726 | return -ENODEV; | ||
1727 | |||
1728 | /* | 1721 | /* |
1729 | * open lock necessary to prevent multiple instances | 1722 | * open lock necessary to prevent multiple instances |
1730 | * of v4l-conf (or other programs) from simultaneously | 1723 | * of v4l-conf (or other programs) from simultaneously |
@@ -1806,24 +1799,20 @@ static int s2255_open(struct file *file) | |||
1806 | file->private_data = fh; | 1799 | file->private_data = fh; |
1807 | fh->dev = dev; | 1800 | fh->dev = dev; |
1808 | fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1801 | fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1809 | fh->mode = dev->mode[cur_channel]; | 1802 | fh->channel = channel; |
1810 | fh->fmt = dev->cur_fmt[cur_channel]; | 1803 | if (!channel->configured) { |
1811 | /* default 4CIF NTSC */ | 1804 | /* configure channel to default state */ |
1812 | fh->width = LINE_SZ_4CIFS_NTSC; | 1805 | channel->fmt = &formats[0]; |
1813 | fh->height = NUM_LINES_4CIFS_NTSC * 2; | 1806 | s2255_set_mode(channel, &channel->mode); |
1814 | fh->channel = cur_channel; | 1807 | channel->configured = 1; |
1815 | /* configure channel to default state */ | ||
1816 | if (!dev->chn_configured[cur_channel]) { | ||
1817 | s2255_set_mode(dev, cur_channel, &fh->mode); | ||
1818 | dev->chn_configured[cur_channel] = 1; | ||
1819 | } | 1808 | } |
1820 | dprintk(1, "%s: dev=%s type=%s\n", __func__, | 1809 | dprintk(1, "%s: dev=%s type=%s\n", __func__, |
1821 | video_device_node_name(vdev), v4l2_type_names[type]); | 1810 | video_device_node_name(vdev), v4l2_type_names[type]); |
1822 | dprintk(2, "%s: fh=0x%08lx, dev=0x%08lx, vidq=0x%08lx\n", __func__, | 1811 | dprintk(2, "%s: fh=0x%08lx, dev=0x%08lx, vidq=0x%08lx\n", __func__, |
1823 | (unsigned long)fh, (unsigned long)dev, | 1812 | (unsigned long)fh, (unsigned long)dev, |
1824 | (unsigned long)&dev->vidq[cur_channel]); | 1813 | (unsigned long)&channel->vidq); |
1825 | dprintk(4, "%s: list_empty active=%d\n", __func__, | 1814 | dprintk(4, "%s: list_empty active=%d\n", __func__, |
1826 | list_empty(&dev->vidq[cur_channel].active)); | 1815 | list_empty(&channel->vidq.active)); |
1827 | videobuf_queue_vmalloc_init(&fh->vb_vidq, &s2255_video_qops, | 1816 | videobuf_queue_vmalloc_init(&fh->vb_vidq, &s2255_video_qops, |
1828 | NULL, &dev->slock, | 1817 | NULL, &dev->slock, |
1829 | fh->type, | 1818 | fh->type, |
@@ -1865,6 +1854,7 @@ static void s2255_destroy(struct s2255_dev *dev) | |||
1865 | mutex_destroy(&dev->open_lock); | 1854 | mutex_destroy(&dev->open_lock); |
1866 | mutex_destroy(&dev->lock); | 1855 | mutex_destroy(&dev->lock); |
1867 | usb_put_dev(dev->udev); | 1856 | usb_put_dev(dev->udev); |
1857 | v4l2_device_unregister(&dev->v4l2_dev); | ||
1868 | dprintk(1, "%s", __func__); | 1858 | dprintk(1, "%s", __func__); |
1869 | kfree(dev); | 1859 | kfree(dev); |
1870 | } | 1860 | } |
@@ -1874,14 +1864,15 @@ static int s2255_release(struct file *file) | |||
1874 | struct s2255_fh *fh = file->private_data; | 1864 | struct s2255_fh *fh = file->private_data; |
1875 | struct s2255_dev *dev = fh->dev; | 1865 | struct s2255_dev *dev = fh->dev; |
1876 | struct video_device *vdev = video_devdata(file); | 1866 | struct video_device *vdev = video_devdata(file); |
1867 | struct s2255_channel *channel = fh->channel; | ||
1877 | if (!dev) | 1868 | if (!dev) |
1878 | return -ENODEV; | 1869 | return -ENODEV; |
1879 | /* turn off stream */ | 1870 | /* turn off stream */ |
1880 | if (res_check(fh)) { | 1871 | if (res_check(fh)) { |
1881 | if (dev->b_acquire[fh->channel]) | 1872 | if (channel->b_acquire) |
1882 | s2255_stop_acquire(dev, fh->channel); | 1873 | s2255_stop_acquire(fh->channel); |
1883 | videobuf_streamoff(&fh->vb_vidq); | 1874 | videobuf_streamoff(&fh->vb_vidq); |
1884 | res_free(dev, fh); | 1875 | res_free(fh); |
1885 | } | 1876 | } |
1886 | videobuf_mmap_free(&fh->vb_vidq); | 1877 | videobuf_mmap_free(&fh->vb_vidq); |
1887 | dprintk(1, "%s (dev=%s)\n", __func__, video_device_node_name(vdev)); | 1878 | dprintk(1, "%s (dev=%s)\n", __func__, video_device_node_name(vdev)); |
@@ -1945,9 +1936,10 @@ static const struct v4l2_ioctl_ops s2255_ioctl_ops = { | |||
1945 | 1936 | ||
1946 | static void s2255_video_device_release(struct video_device *vdev) | 1937 | static void s2255_video_device_release(struct video_device *vdev) |
1947 | { | 1938 | { |
1948 | struct s2255_dev *dev = video_get_drvdata(vdev); | 1939 | struct s2255_dev *dev = to_s2255_dev(vdev->v4l2_dev); |
1949 | dprintk(4, "%s, chnls: %d \n", __func__, atomic_read(&dev->channels)); | 1940 | dprintk(4, "%s, chnls: %d \n", __func__, |
1950 | if (atomic_dec_and_test(&dev->channels)) | 1941 | atomic_read(&dev->num_channels)); |
1942 | if (atomic_dec_and_test(&dev->num_channels)) | ||
1951 | s2255_destroy(dev); | 1943 | s2255_destroy(dev); |
1952 | return; | 1944 | return; |
1953 | } | 1945 | } |
@@ -1966,47 +1958,48 @@ static int s2255_probe_v4l(struct s2255_dev *dev) | |||
1966 | int ret; | 1958 | int ret; |
1967 | int i; | 1959 | int i; |
1968 | int cur_nr = video_nr; | 1960 | int cur_nr = video_nr; |
1961 | struct s2255_channel *channel; | ||
1969 | ret = v4l2_device_register(&dev->interface->dev, &dev->v4l2_dev); | 1962 | ret = v4l2_device_register(&dev->interface->dev, &dev->v4l2_dev); |
1970 | if (ret) | 1963 | if (ret) |
1971 | return ret; | 1964 | return ret; |
1972 | /* initialize all video 4 linux */ | 1965 | /* initialize all video 4 linux */ |
1973 | /* register 4 video devices */ | 1966 | /* register 4 video devices */ |
1974 | for (i = 0; i < MAX_CHANNELS; i++) { | 1967 | for (i = 0; i < MAX_CHANNELS; i++) { |
1975 | INIT_LIST_HEAD(&dev->vidq[i].active); | 1968 | channel = &dev->channel[i]; |
1976 | dev->vidq[i].dev = dev; | 1969 | INIT_LIST_HEAD(&channel->vidq.active); |
1977 | dev->vidq[i].channel = i; | 1970 | channel->vidq.dev = dev; |
1978 | /* register 4 video devices */ | 1971 | /* register 4 video devices */ |
1979 | memcpy(&dev->vdev[i], &template, sizeof(struct video_device)); | 1972 | channel->vdev = template; |
1980 | dev->vdev[i].v4l2_dev = &dev->v4l2_dev; | 1973 | channel->vdev.v4l2_dev = &dev->v4l2_dev; |
1981 | video_set_drvdata(&dev->vdev[i], dev); | 1974 | video_set_drvdata(&channel->vdev, channel); |
1982 | if (video_nr == -1) | 1975 | if (video_nr == -1) |
1983 | ret = video_register_device(&dev->vdev[i], | 1976 | ret = video_register_device(&channel->vdev, |
1984 | VFL_TYPE_GRABBER, | 1977 | VFL_TYPE_GRABBER, |
1985 | video_nr); | 1978 | video_nr); |
1986 | else | 1979 | else |
1987 | ret = video_register_device(&dev->vdev[i], | 1980 | ret = video_register_device(&channel->vdev, |
1988 | VFL_TYPE_GRABBER, | 1981 | VFL_TYPE_GRABBER, |
1989 | cur_nr + i); | 1982 | cur_nr + i); |
1983 | |||
1990 | if (ret) { | 1984 | if (ret) { |
1991 | dev_err(&dev->udev->dev, | 1985 | dev_err(&dev->udev->dev, |
1992 | "failed to register video device!\n"); | 1986 | "failed to register video device!\n"); |
1993 | break; | 1987 | break; |
1994 | } | 1988 | } |
1995 | atomic_inc(&dev->channels); | 1989 | atomic_inc(&dev->num_channels); |
1996 | v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n", | 1990 | v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n", |
1997 | video_device_node_name(&dev->vdev[i])); | 1991 | video_device_node_name(&channel->vdev)); |
1998 | 1992 | ||
1999 | } | 1993 | } |
2000 | |||
2001 | printk(KERN_INFO "Sensoray 2255 V4L driver Revision: %d.%d\n", | 1994 | printk(KERN_INFO "Sensoray 2255 V4L driver Revision: %d.%d\n", |
2002 | S2255_MAJOR_VERSION, | 1995 | S2255_MAJOR_VERSION, |
2003 | S2255_MINOR_VERSION); | 1996 | S2255_MINOR_VERSION); |
2004 | /* if no channels registered, return error and probe will fail*/ | 1997 | /* if no channels registered, return error and probe will fail*/ |
2005 | if (atomic_read(&dev->channels) == 0) { | 1998 | if (atomic_read(&dev->num_channels) == 0) { |
2006 | v4l2_device_unregister(&dev->v4l2_dev); | 1999 | v4l2_device_unregister(&dev->v4l2_dev); |
2007 | return ret; | 2000 | return ret; |
2008 | } | 2001 | } |
2009 | if (atomic_read(&dev->channels) != MAX_CHANNELS) | 2002 | if (atomic_read(&dev->num_channels) != MAX_CHANNELS) |
2010 | printk(KERN_WARNING "s2255: Not all channels available.\n"); | 2003 | printk(KERN_WARNING "s2255: Not all channels available.\n"); |
2011 | return 0; | 2004 | return 0; |
2012 | } | 2005 | } |
@@ -2033,12 +2026,11 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) | |||
2033 | s32 idx = -1; | 2026 | s32 idx = -1; |
2034 | struct s2255_framei *frm; | 2027 | struct s2255_framei *frm; |
2035 | unsigned char *pdata; | 2028 | unsigned char *pdata; |
2036 | 2029 | struct s2255_channel *channel; | |
2037 | dprintk(100, "buffer to user\n"); | 2030 | dprintk(100, "buffer to user\n"); |
2038 | 2031 | channel = &dev->channel[dev->cc]; | |
2039 | idx = dev->cur_frame[dev->cc]; | 2032 | idx = channel->cur_frame; |
2040 | frm = &dev->buffer[dev->cc].frame[idx]; | 2033 | frm = &channel->buffer.frame[idx]; |
2041 | |||
2042 | if (frm->ulState == S2255_READ_IDLE) { | 2034 | if (frm->ulState == S2255_READ_IDLE) { |
2043 | int jj; | 2035 | int jj; |
2044 | unsigned int cc; | 2036 | unsigned int cc; |
@@ -2063,16 +2055,18 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) | |||
2063 | } | 2055 | } |
2064 | /* reverse it */ | 2056 | /* reverse it */ |
2065 | dev->cc = G_chnmap[cc]; | 2057 | dev->cc = G_chnmap[cc]; |
2058 | channel = &dev->channel[dev->cc]; | ||
2066 | payload = pdword[3]; | 2059 | payload = pdword[3]; |
2067 | if (payload > dev->req_image_size[dev->cc]) { | 2060 | if (payload > channel->req_image_size) { |
2068 | dev->bad_payload[dev->cc]++; | 2061 | channel->bad_payload++; |
2069 | /* discard the bad frame */ | 2062 | /* discard the bad frame */ |
2070 | return -EINVAL; | 2063 | return -EINVAL; |
2071 | } | 2064 | } |
2072 | dev->pkt_size[dev->cc] = payload; | 2065 | channel->pkt_size = payload; |
2073 | dev->jpg_size[dev->cc] = pdword[4]; | 2066 | channel->jpg_size = pdword[4]; |
2074 | break; | 2067 | break; |
2075 | case S2255_MARKER_RESPONSE: | 2068 | case S2255_MARKER_RESPONSE: |
2069 | |||
2076 | pdata += DEF_USB_BLOCK; | 2070 | pdata += DEF_USB_BLOCK; |
2077 | jj += DEF_USB_BLOCK; | 2071 | jj += DEF_USB_BLOCK; |
2078 | if (pdword[1] >= MAX_CHANNELS) | 2072 | if (pdword[1] >= MAX_CHANNELS) |
@@ -2080,12 +2074,13 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) | |||
2080 | cc = G_chnmap[pdword[1]]; | 2074 | cc = G_chnmap[pdword[1]]; |
2081 | if (cc >= MAX_CHANNELS) | 2075 | if (cc >= MAX_CHANNELS) |
2082 | break; | 2076 | break; |
2077 | channel = &dev->channel[cc]; | ||
2083 | switch (pdword[2]) { | 2078 | switch (pdword[2]) { |
2084 | case S2255_RESPONSE_SETMODE: | 2079 | case S2255_RESPONSE_SETMODE: |
2085 | /* check if channel valid */ | 2080 | /* check if channel valid */ |
2086 | /* set mode ready */ | 2081 | /* set mode ready */ |
2087 | dev->setmode_ready[cc] = 1; | 2082 | channel->setmode_ready = 1; |
2088 | wake_up(&dev->wait_setmode[cc]); | 2083 | wake_up(&channel->wait_setmode); |
2089 | dprintk(5, "setmode ready %d\n", cc); | 2084 | dprintk(5, "setmode ready %d\n", cc); |
2090 | break; | 2085 | break; |
2091 | case S2255_RESPONSE_FW: | 2086 | case S2255_RESPONSE_FW: |
@@ -2099,9 +2094,9 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) | |||
2099 | wake_up(&dev->fw_data->wait_fw); | 2094 | wake_up(&dev->fw_data->wait_fw); |
2100 | break; | 2095 | break; |
2101 | case S2255_RESPONSE_STATUS: | 2096 | case S2255_RESPONSE_STATUS: |
2102 | dev->vidstatus[cc] = pdword[3]; | 2097 | channel->vidstatus = pdword[3]; |
2103 | dev->vidstatus_ready[cc] = 1; | 2098 | channel->vidstatus_ready = 1; |
2104 | wake_up(&dev->wait_vidstatus[cc]); | 2099 | wake_up(&channel->wait_vidstatus); |
2105 | dprintk(5, "got vidstatus %x chan %d\n", | 2100 | dprintk(5, "got vidstatus %x chan %d\n", |
2106 | pdword[3], cc); | 2101 | pdword[3], cc); |
2107 | break; | 2102 | break; |
@@ -2118,13 +2113,11 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) | |||
2118 | if (!bframe) | 2113 | if (!bframe) |
2119 | return -EINVAL; | 2114 | return -EINVAL; |
2120 | } | 2115 | } |
2121 | 2116 | channel = &dev->channel[dev->cc]; | |
2122 | 2117 | idx = channel->cur_frame; | |
2123 | idx = dev->cur_frame[dev->cc]; | 2118 | frm = &channel->buffer.frame[idx]; |
2124 | frm = &dev->buffer[dev->cc].frame[idx]; | ||
2125 | |||
2126 | /* search done. now find out if should be acquiring on this channel */ | 2119 | /* search done. now find out if should be acquiring on this channel */ |
2127 | if (!dev->b_acquire[dev->cc]) { | 2120 | if (!channel->b_acquire) { |
2128 | /* we found a frame, but this channel is turned off */ | 2121 | /* we found a frame, but this channel is turned off */ |
2129 | frm->ulState = S2255_READ_IDLE; | 2122 | frm->ulState = S2255_READ_IDLE; |
2130 | return -EINVAL; | 2123 | return -EINVAL; |
@@ -2149,30 +2142,28 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) | |||
2149 | 2142 | ||
2150 | copy_size = (pipe_info->cur_transfer_size - offset); | 2143 | copy_size = (pipe_info->cur_transfer_size - offset); |
2151 | 2144 | ||
2152 | size = dev->pkt_size[dev->cc] - PREFIX_SIZE; | 2145 | size = channel->pkt_size - PREFIX_SIZE; |
2153 | 2146 | ||
2154 | /* sanity check on pdest */ | 2147 | /* sanity check on pdest */ |
2155 | if ((copy_size + frm->cur_size) < dev->req_image_size[dev->cc]) | 2148 | if ((copy_size + frm->cur_size) < channel->req_image_size) |
2156 | memcpy(pdest, psrc, copy_size); | 2149 | memcpy(pdest, psrc, copy_size); |
2157 | 2150 | ||
2158 | frm->cur_size += copy_size; | 2151 | frm->cur_size += copy_size; |
2159 | dprintk(4, "cur_size size %lu size %lu \n", frm->cur_size, size); | 2152 | dprintk(4, "cur_size size %lu size %lu \n", frm->cur_size, size); |
2160 | 2153 | ||
2161 | if (frm->cur_size >= size) { | 2154 | if (frm->cur_size >= size) { |
2162 | |||
2163 | u32 cc = dev->cc; | ||
2164 | dprintk(2, "****************[%d]Buffer[%d]full*************\n", | 2155 | dprintk(2, "****************[%d]Buffer[%d]full*************\n", |
2165 | cc, idx); | 2156 | dev->cc, idx); |
2166 | dev->last_frame[cc] = dev->cur_frame[cc]; | 2157 | channel->last_frame = channel->cur_frame; |
2167 | dev->cur_frame[cc]++; | 2158 | channel->cur_frame++; |
2168 | /* end of system frame ring buffer, start at zero */ | 2159 | /* end of system frame ring buffer, start at zero */ |
2169 | if ((dev->cur_frame[cc] == SYS_FRAMES) || | 2160 | if ((channel->cur_frame == SYS_FRAMES) || |
2170 | (dev->cur_frame[cc] == dev->buffer[cc].dwFrames)) | 2161 | (channel->cur_frame == channel->buffer.dwFrames)) |
2171 | dev->cur_frame[cc] = 0; | 2162 | channel->cur_frame = 0; |
2172 | /* frame ready */ | 2163 | /* frame ready */ |
2173 | if (dev->b_acquire[cc]) | 2164 | if (channel->b_acquire) |
2174 | s2255_got_frame(dev, cc, dev->jpg_size[cc]); | 2165 | s2255_got_frame(channel, channel->jpg_size); |
2175 | dev->frame_count[cc]++; | 2166 | channel->frame_count++; |
2176 | frm->ulState = S2255_READ_IDLE; | 2167 | frm->ulState = S2255_READ_IDLE; |
2177 | frm->cur_size = 0; | 2168 | frm->cur_size = 0; |
2178 | 2169 | ||
@@ -2245,16 +2236,12 @@ static int s2255_get_fx2fw(struct s2255_dev *dev) | |||
2245 | * Create the system ring buffer to copy frames into from the | 2236 | * Create the system ring buffer to copy frames into from the |
2246 | * usb read pipe. | 2237 | * usb read pipe. |
2247 | */ | 2238 | */ |
2248 | static int s2255_create_sys_buffers(struct s2255_dev *dev, unsigned long chn) | 2239 | static int s2255_create_sys_buffers(struct s2255_channel *channel) |
2249 | { | 2240 | { |
2250 | unsigned long i; | 2241 | unsigned long i; |
2251 | unsigned long reqsize; | 2242 | unsigned long reqsize; |
2252 | dprintk(1, "create sys buffers\n"); | 2243 | dprintk(1, "create sys buffers\n"); |
2253 | if (chn >= MAX_CHANNELS) | 2244 | channel->buffer.dwFrames = SYS_FRAMES; |
2254 | return -1; | ||
2255 | |||
2256 | dev->buffer[chn].dwFrames = SYS_FRAMES; | ||
2257 | |||
2258 | /* always allocate maximum size(PAL) for system buffers */ | 2245 | /* always allocate maximum size(PAL) for system buffers */ |
2259 | reqsize = SYS_FRAMES_MAXSIZE; | 2246 | reqsize = SYS_FRAMES_MAXSIZE; |
2260 | 2247 | ||
@@ -2263,42 +2250,40 @@ static int s2255_create_sys_buffers(struct s2255_dev *dev, unsigned long chn) | |||
2263 | 2250 | ||
2264 | for (i = 0; i < SYS_FRAMES; i++) { | 2251 | for (i = 0; i < SYS_FRAMES; i++) { |
2265 | /* allocate the frames */ | 2252 | /* allocate the frames */ |
2266 | dev->buffer[chn].frame[i].lpvbits = vmalloc(reqsize); | 2253 | channel->buffer.frame[i].lpvbits = vmalloc(reqsize); |
2267 | 2254 | dprintk(1, "valloc %p chan %d, idx %lu, pdata %p\n", | |
2268 | dprintk(1, "valloc %p chan %lu, idx %lu, pdata %p\n", | 2255 | &channel->buffer.frame[i], channel->idx, i, |
2269 | &dev->buffer[chn].frame[i], chn, i, | 2256 | channel->buffer.frame[i].lpvbits); |
2270 | dev->buffer[chn].frame[i].lpvbits); | 2257 | channel->buffer.frame[i].size = reqsize; |
2271 | dev->buffer[chn].frame[i].size = reqsize; | 2258 | if (channel->buffer.frame[i].lpvbits == NULL) { |
2272 | if (dev->buffer[chn].frame[i].lpvbits == NULL) { | ||
2273 | printk(KERN_INFO "out of memory. using less frames\n"); | 2259 | printk(KERN_INFO "out of memory. using less frames\n"); |
2274 | dev->buffer[chn].dwFrames = i; | 2260 | channel->buffer.dwFrames = i; |
2275 | break; | 2261 | break; |
2276 | } | 2262 | } |
2277 | } | 2263 | } |
2278 | 2264 | ||
2279 | /* make sure internal states are set */ | 2265 | /* make sure internal states are set */ |
2280 | for (i = 0; i < SYS_FRAMES; i++) { | 2266 | for (i = 0; i < SYS_FRAMES; i++) { |
2281 | dev->buffer[chn].frame[i].ulState = 0; | 2267 | channel->buffer.frame[i].ulState = 0; |
2282 | dev->buffer[chn].frame[i].cur_size = 0; | 2268 | channel->buffer.frame[i].cur_size = 0; |
2283 | } | 2269 | } |
2284 | 2270 | ||
2285 | dev->cur_frame[chn] = 0; | 2271 | channel->cur_frame = 0; |
2286 | dev->last_frame[chn] = -1; | 2272 | channel->last_frame = -1; |
2287 | return 0; | 2273 | return 0; |
2288 | } | 2274 | } |
2289 | 2275 | ||
2290 | static int s2255_release_sys_buffers(struct s2255_dev *dev, | 2276 | static int s2255_release_sys_buffers(struct s2255_channel *channel) |
2291 | unsigned long channel) | ||
2292 | { | 2277 | { |
2293 | unsigned long i; | 2278 | unsigned long i; |
2294 | dprintk(1, "release sys buffers\n"); | 2279 | dprintk(1, "release sys buffers\n"); |
2295 | for (i = 0; i < SYS_FRAMES; i++) { | 2280 | for (i = 0; i < SYS_FRAMES; i++) { |
2296 | if (dev->buffer[channel].frame[i].lpvbits) { | 2281 | if (channel->buffer.frame[i].lpvbits) { |
2297 | dprintk(1, "vfree %p\n", | 2282 | dprintk(1, "vfree %p\n", |
2298 | dev->buffer[channel].frame[i].lpvbits); | 2283 | channel->buffer.frame[i].lpvbits); |
2299 | vfree(dev->buffer[channel].frame[i].lpvbits); | 2284 | vfree(channel->buffer.frame[i].lpvbits); |
2300 | } | 2285 | } |
2301 | dev->buffer[channel].frame[i].lpvbits = NULL; | 2286 | channel->buffer.frame[i].lpvbits = NULL; |
2302 | } | 2287 | } |
2303 | return 0; | 2288 | return 0; |
2304 | } | 2289 | } |
@@ -2335,17 +2320,20 @@ static int s2255_board_init(struct s2255_dev *dev) | |||
2335 | fw_ver & 0xff); | 2320 | fw_ver & 0xff); |
2336 | 2321 | ||
2337 | for (j = 0; j < MAX_CHANNELS; j++) { | 2322 | for (j = 0; j < MAX_CHANNELS; j++) { |
2338 | dev->b_acquire[j] = 0; | 2323 | struct s2255_channel *channel = &dev->channel[j]; |
2339 | dev->mode[j] = mode_def; | 2324 | channel->b_acquire = 0; |
2325 | channel->mode = mode_def; | ||
2340 | if (dev->pid == 0x2257 && j > 1) | 2326 | if (dev->pid == 0x2257 && j > 1) |
2341 | dev->mode[j].color |= (1 << 16); | 2327 | channel->mode.color |= (1 << 16); |
2342 | dev->jc[j].quality = S2255_DEF_JPEG_QUAL; | 2328 | channel->jc.quality = S2255_DEF_JPEG_QUAL; |
2343 | dev->cur_fmt[j] = &formats[0]; | 2329 | channel->width = LINE_SZ_4CIFS_NTSC; |
2344 | dev->mode[j].restart = 1; | 2330 | channel->height = NUM_LINES_4CIFS_NTSC * 2; |
2345 | dev->req_image_size[j] = get_transfer_size(&mode_def); | 2331 | channel->fmt = &formats[0]; |
2346 | dev->frame_count[j] = 0; | 2332 | channel->mode.restart = 1; |
2333 | channel->req_image_size = get_transfer_size(&mode_def); | ||
2334 | channel->frame_count = 0; | ||
2347 | /* create the system buffers */ | 2335 | /* create the system buffers */ |
2348 | s2255_create_sys_buffers(dev, j); | 2336 | s2255_create_sys_buffers(channel); |
2349 | } | 2337 | } |
2350 | /* start read pipe */ | 2338 | /* start read pipe */ |
2351 | s2255_start_readpipe(dev); | 2339 | s2255_start_readpipe(dev); |
@@ -2359,14 +2347,12 @@ static int s2255_board_shutdown(struct s2255_dev *dev) | |||
2359 | dprintk(1, "%s: dev: %p", __func__, dev); | 2347 | dprintk(1, "%s: dev: %p", __func__, dev); |
2360 | 2348 | ||
2361 | for (i = 0; i < MAX_CHANNELS; i++) { | 2349 | for (i = 0; i < MAX_CHANNELS; i++) { |
2362 | if (dev->b_acquire[i]) | 2350 | if (dev->channel[i].b_acquire) |
2363 | s2255_stop_acquire(dev, i); | 2351 | s2255_stop_acquire(&dev->channel[i]); |
2364 | } | 2352 | } |
2365 | |||
2366 | s2255_stop_readpipe(dev); | 2353 | s2255_stop_readpipe(dev); |
2367 | |||
2368 | for (i = 0; i < MAX_CHANNELS; i++) | 2354 | for (i = 0; i < MAX_CHANNELS; i++) |
2369 | s2255_release_sys_buffers(dev, i); | 2355 | s2255_release_sys_buffers(&dev->channel[i]); |
2370 | /* release transfer buffer */ | 2356 | /* release transfer buffer */ |
2371 | kfree(dev->pipe.transfer_buffer); | 2357 | kfree(dev->pipe.transfer_buffer); |
2372 | return 0; | 2358 | return 0; |
@@ -2459,29 +2445,26 @@ static int s2255_start_readpipe(struct s2255_dev *dev) | |||
2459 | } | 2445 | } |
2460 | 2446 | ||
2461 | /* starts acquisition process */ | 2447 | /* starts acquisition process */ |
2462 | static int s2255_start_acquire(struct s2255_dev *dev, unsigned long chn) | 2448 | static int s2255_start_acquire(struct s2255_channel *channel) |
2463 | { | 2449 | { |
2464 | unsigned char *buffer; | 2450 | unsigned char *buffer; |
2465 | int res; | 2451 | int res; |
2466 | unsigned long chn_rev; | 2452 | unsigned long chn_rev; |
2467 | int j; | 2453 | int j; |
2468 | if (chn >= MAX_CHANNELS) { | 2454 | struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev); |
2469 | dprintk(2, "start acquire failed, bad channel %lu\n", chn); | 2455 | chn_rev = G_chnmap[channel->idx]; |
2470 | return -1; | ||
2471 | } | ||
2472 | chn_rev = G_chnmap[chn]; | ||
2473 | buffer = kzalloc(512, GFP_KERNEL); | 2456 | buffer = kzalloc(512, GFP_KERNEL); |
2474 | if (buffer == NULL) { | 2457 | if (buffer == NULL) { |
2475 | dev_err(&dev->udev->dev, "out of mem\n"); | 2458 | dev_err(&dev->udev->dev, "out of mem\n"); |
2476 | return -ENOMEM; | 2459 | return -ENOMEM; |
2477 | } | 2460 | } |
2478 | 2461 | ||
2479 | dev->last_frame[chn] = -1; | 2462 | channel->last_frame = -1; |
2480 | dev->bad_payload[chn] = 0; | 2463 | channel->bad_payload = 0; |
2481 | dev->cur_frame[chn] = 0; | 2464 | channel->cur_frame = 0; |
2482 | for (j = 0; j < SYS_FRAMES; j++) { | 2465 | for (j = 0; j < SYS_FRAMES; j++) { |
2483 | dev->buffer[chn].frame[j].ulState = 0; | 2466 | channel->buffer.frame[j].ulState = 0; |
2484 | dev->buffer[chn].frame[j].cur_size = 0; | 2467 | channel->buffer.frame[j].cur_size = 0; |
2485 | } | 2468 | } |
2486 | 2469 | ||
2487 | /* send the start command */ | 2470 | /* send the start command */ |
@@ -2492,21 +2475,18 @@ static int s2255_start_acquire(struct s2255_dev *dev, unsigned long chn) | |||
2492 | if (res != 0) | 2475 | if (res != 0) |
2493 | dev_err(&dev->udev->dev, "CMD_START error\n"); | 2476 | dev_err(&dev->udev->dev, "CMD_START error\n"); |
2494 | 2477 | ||
2495 | dprintk(2, "start acquire exit[%lu] %d \n", chn, res); | 2478 | dprintk(2, "start acquire exit[%d] %d \n", channel->idx, res); |
2496 | kfree(buffer); | 2479 | kfree(buffer); |
2497 | return 0; | 2480 | return 0; |
2498 | } | 2481 | } |
2499 | 2482 | ||
2500 | static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn) | 2483 | static int s2255_stop_acquire(struct s2255_channel *channel) |
2501 | { | 2484 | { |
2502 | unsigned char *buffer; | 2485 | unsigned char *buffer; |
2503 | int res; | 2486 | int res; |
2504 | unsigned long chn_rev; | 2487 | unsigned long chn_rev; |
2505 | if (chn >= MAX_CHANNELS) { | 2488 | struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev); |
2506 | dprintk(2, "stop acquire failed, bad channel %lu\n", chn); | 2489 | chn_rev = G_chnmap[channel->idx]; |
2507 | return -1; | ||
2508 | } | ||
2509 | chn_rev = G_chnmap[chn]; | ||
2510 | buffer = kzalloc(512, GFP_KERNEL); | 2490 | buffer = kzalloc(512, GFP_KERNEL); |
2511 | if (buffer == NULL) { | 2491 | if (buffer == NULL) { |
2512 | dev_err(&dev->udev->dev, "out of mem\n"); | 2492 | dev_err(&dev->udev->dev, "out of mem\n"); |
@@ -2520,8 +2500,8 @@ static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn) | |||
2520 | if (res != 0) | 2500 | if (res != 0) |
2521 | dev_err(&dev->udev->dev, "CMD_STOP error\n"); | 2501 | dev_err(&dev->udev->dev, "CMD_STOP error\n"); |
2522 | kfree(buffer); | 2502 | kfree(buffer); |
2523 | dev->b_acquire[chn] = 0; | 2503 | channel->b_acquire = 0; |
2524 | dprintk(4, "%s: chn %lu, res %d\n", __func__, chn, res); | 2504 | dprintk(4, "%s: chn %d, res %d\n", __func__, channel->idx, res); |
2525 | return res; | 2505 | return res; |
2526 | } | 2506 | } |
2527 | 2507 | ||
@@ -2575,7 +2555,7 @@ static int s2255_probe(struct usb_interface *interface, | |||
2575 | s2255_dev_err(&interface->dev, "out of memory\n"); | 2555 | s2255_dev_err(&interface->dev, "out of memory\n"); |
2576 | return -ENOMEM; | 2556 | return -ENOMEM; |
2577 | } | 2557 | } |
2578 | atomic_set(&dev->channels, 0); | 2558 | atomic_set(&dev->num_channels, 0); |
2579 | dev->pid = id->idProduct; | 2559 | dev->pid = id->idProduct; |
2580 | dev->fw_data = kzalloc(sizeof(struct s2255_fw), GFP_KERNEL); | 2560 | dev->fw_data = kzalloc(sizeof(struct s2255_fw), GFP_KERNEL); |
2581 | if (!dev->fw_data) | 2561 | if (!dev->fw_data) |
@@ -2612,8 +2592,10 @@ static int s2255_probe(struct usb_interface *interface, | |||
2612 | dev->timer.data = (unsigned long)dev->fw_data; | 2592 | dev->timer.data = (unsigned long)dev->fw_data; |
2613 | init_waitqueue_head(&dev->fw_data->wait_fw); | 2593 | init_waitqueue_head(&dev->fw_data->wait_fw); |
2614 | for (i = 0; i < MAX_CHANNELS; i++) { | 2594 | for (i = 0; i < MAX_CHANNELS; i++) { |
2615 | init_waitqueue_head(&dev->wait_setmode[i]); | 2595 | struct s2255_channel *channel = &dev->channel[i]; |
2616 | init_waitqueue_head(&dev->wait_vidstatus[i]); | 2596 | dev->channel[i].idx = i; |
2597 | init_waitqueue_head(&channel->wait_setmode); | ||
2598 | init_waitqueue_head(&channel->wait_vidstatus); | ||
2617 | } | 2599 | } |
2618 | 2600 | ||
2619 | dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL); | 2601 | dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL); |
@@ -2651,7 +2633,7 @@ static int s2255_probe(struct usb_interface *interface, | |||
2651 | printk(KERN_INFO "s2255: f2255usb.bin out of date.\n"); | 2633 | printk(KERN_INFO "s2255: f2255usb.bin out of date.\n"); |
2652 | if (dev->pid == 0x2257 && *pRel < S2255_MIN_DSP_COLORFILTER) | 2634 | if (dev->pid == 0x2257 && *pRel < S2255_MIN_DSP_COLORFILTER) |
2653 | printk(KERN_WARNING "s2255: 2257 requires firmware %d" | 2635 | printk(KERN_WARNING "s2255: 2257 requires firmware %d" |
2654 | "or above.\n", S2255_MIN_DSP_COLORFILTER); | 2636 | " or above.\n", S2255_MIN_DSP_COLORFILTER); |
2655 | } | 2637 | } |
2656 | usb_reset_device(dev->udev); | 2638 | usb_reset_device(dev->udev); |
2657 | /* load 2255 board specific */ | 2639 | /* load 2255 board specific */ |
@@ -2693,25 +2675,23 @@ static void s2255_disconnect(struct usb_interface *interface) | |||
2693 | { | 2675 | { |
2694 | struct s2255_dev *dev = to_s2255_dev(usb_get_intfdata(interface)); | 2676 | struct s2255_dev *dev = to_s2255_dev(usb_get_intfdata(interface)); |
2695 | int i; | 2677 | int i; |
2696 | int channels = atomic_read(&dev->channels); | 2678 | int channels = atomic_read(&dev->num_channels); |
2697 | v4l2_device_unregister(&dev->v4l2_dev); | 2679 | v4l2_device_disconnect(&dev->v4l2_dev); |
2698 | /*see comments in the uvc_driver.c usb disconnect function */ | 2680 | /*see comments in the uvc_driver.c usb disconnect function */ |
2699 | atomic_inc(&dev->channels); | 2681 | atomic_inc(&dev->num_channels); |
2700 | /* unregister each video device. */ | 2682 | /* unregister each video device. */ |
2701 | for (i = 0; i < channels; i++) { | 2683 | for (i = 0; i < channels; i++) |
2702 | if (video_is_registered(&dev->vdev[i])) | 2684 | video_unregister_device(&dev->channel[i].vdev); |
2703 | video_unregister_device(&dev->vdev[i]); | ||
2704 | } | ||
2705 | /* wake up any of our timers */ | 2685 | /* wake up any of our timers */ |
2706 | atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING); | 2686 | atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING); |
2707 | wake_up(&dev->fw_data->wait_fw); | 2687 | wake_up(&dev->fw_data->wait_fw); |
2708 | for (i = 0; i < MAX_CHANNELS; i++) { | 2688 | for (i = 0; i < MAX_CHANNELS; i++) { |
2709 | dev->setmode_ready[i] = 1; | 2689 | dev->channel[i].setmode_ready = 1; |
2710 | wake_up(&dev->wait_setmode[i]); | 2690 | wake_up(&dev->channel[i].wait_setmode); |
2711 | dev->vidstatus_ready[i] = 1; | 2691 | dev->channel[i].vidstatus_ready = 1; |
2712 | wake_up(&dev->wait_vidstatus[i]); | 2692 | wake_up(&dev->channel[i].wait_vidstatus); |
2713 | } | 2693 | } |
2714 | if (atomic_dec_and_test(&dev->channels)) | 2694 | if (atomic_dec_and_test(&dev->num_channels)) |
2715 | s2255_destroy(dev); | 2695 | s2255_destroy(dev); |
2716 | dev_info(&interface->dev, "%s\n", __func__); | 2696 | dev_info(&interface->dev, "%s\n", __func__); |
2717 | } | 2697 | } |
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index d3bd82ad010a..10460fd3ce39 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c | |||
@@ -630,7 +630,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, | |||
630 | /* release the old buffer */ | 630 | /* release the old buffer */ |
631 | if (substream->runtime->dma_area) { | 631 | if (substream->runtime->dma_area) { |
632 | saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); | 632 | saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); |
633 | videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); | 633 | videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); |
634 | dsp_buffer_free(dev); | 634 | dsp_buffer_free(dev); |
635 | substream->runtime->dma_area = NULL; | 635 | substream->runtime->dma_area = NULL; |
636 | } | 636 | } |
@@ -646,12 +646,12 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, | |||
646 | return err; | 646 | return err; |
647 | } | 647 | } |
648 | 648 | ||
649 | if (0 != (err = videobuf_sg_dma_map(&dev->pci->dev, &dev->dmasound.dma))) { | 649 | if (0 != (err = videobuf_dma_map(&dev->pci->dev, &dev->dmasound.dma))) { |
650 | dsp_buffer_free(dev); | 650 | dsp_buffer_free(dev); |
651 | return err; | 651 | return err; |
652 | } | 652 | } |
653 | if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) { | 653 | if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) { |
654 | videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); | 654 | videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); |
655 | dsp_buffer_free(dev); | 655 | dsp_buffer_free(dev); |
656 | return err; | 656 | return err; |
657 | } | 657 | } |
@@ -660,7 +660,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, | |||
660 | dev->dmasound.dma.sglen, | 660 | dev->dmasound.dma.sglen, |
661 | 0))) { | 661 | 0))) { |
662 | saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); | 662 | saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); |
663 | videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); | 663 | videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); |
664 | dsp_buffer_free(dev); | 664 | dsp_buffer_free(dev); |
665 | return err; | 665 | return err; |
666 | } | 666 | } |
@@ -669,7 +669,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream, | |||
669 | byte, but it doesn't work. So I allocate the DMA using the | 669 | byte, but it doesn't work. So I allocate the DMA using the |
670 | V4L functions, and force ALSA to use that as the DMA area */ | 670 | V4L functions, and force ALSA to use that as the DMA area */ |
671 | 671 | ||
672 | substream->runtime->dma_area = dev->dmasound.dma.vmalloc; | 672 | substream->runtime->dma_area = dev->dmasound.dma.vaddr; |
673 | substream->runtime->dma_bytes = dev->dmasound.bufsize; | 673 | substream->runtime->dma_bytes = dev->dmasound.bufsize; |
674 | substream->runtime->dma_addr = 0; | 674 | substream->runtime->dma_addr = 0; |
675 | 675 | ||
@@ -696,7 +696,7 @@ static int snd_card_saa7134_hw_free(struct snd_pcm_substream * substream) | |||
696 | 696 | ||
697 | if (substream->runtime->dma_area) { | 697 | if (substream->runtime->dma_area) { |
698 | saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); | 698 | saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); |
699 | videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); | 699 | videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma); |
700 | dsp_buffer_free(dev); | 700 | dsp_buffer_free(dev); |
701 | substream->runtime->dma_area = NULL; | 701 | substream->runtime->dma_area = NULL; |
702 | } | 702 | } |
@@ -1080,7 +1080,7 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum) | |||
1080 | /* Card "creation" */ | 1080 | /* Card "creation" */ |
1081 | 1081 | ||
1082 | card->private_free = snd_saa7134_free; | 1082 | card->private_free = snd_saa7134_free; |
1083 | chip = (snd_card_saa7134_t *) card->private_data; | 1083 | chip = card->private_data; |
1084 | 1084 | ||
1085 | spin_lock_init(&chip->lock); | 1085 | spin_lock_init(&chip->lock); |
1086 | spin_lock_init(&chip->mixer_lock); | 1086 | spin_lock_init(&chip->mixer_lock); |
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 07f6bb8ef9d9..ec697fcd406e 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -5462,6 +5462,30 @@ struct saa7134_board saa7134_boards[] = { | |||
5462 | .amux = TV, | 5462 | .amux = TV, |
5463 | }, | 5463 | }, |
5464 | }, | 5464 | }, |
5465 | [SAA7134_BOARD_TECHNOTREND_BUDGET_T3000] = { | ||
5466 | .name = "TechoTrend TT-budget T-3000", | ||
5467 | .tuner_type = TUNER_PHILIPS_TD1316, | ||
5468 | .audio_clock = 0x00187de7, | ||
5469 | .radio_type = UNSET, | ||
5470 | .tuner_addr = 0x63, | ||
5471 | .radio_addr = ADDR_UNSET, | ||
5472 | .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, | ||
5473 | .mpeg = SAA7134_MPEG_DVB, | ||
5474 | .inputs = {{ | ||
5475 | .name = name_tv, | ||
5476 | .vmux = 3, | ||
5477 | .amux = TV, | ||
5478 | .tv = 1, | ||
5479 | }, { | ||
5480 | .name = name_comp1, | ||
5481 | .vmux = 0, | ||
5482 | .amux = LINE2, | ||
5483 | }, { | ||
5484 | .name = name_svideo, | ||
5485 | .vmux = 8, | ||
5486 | .amux = LINE2, | ||
5487 | } }, | ||
5488 | }, | ||
5465 | 5489 | ||
5466 | }; | 5490 | }; |
5467 | 5491 | ||
@@ -6631,6 +6655,12 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
6631 | .subdevice = 0x6655, | 6655 | .subdevice = 0x6655, |
6632 | .driver_data = SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S, | 6656 | .driver_data = SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S, |
6633 | }, { | 6657 | }, { |
6658 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
6659 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
6660 | .subvendor = 0x13c2, | ||
6661 | .subdevice = 0x2804, | ||
6662 | .driver_data = SAA7134_BOARD_TECHNOTREND_BUDGET_T3000, | ||
6663 | }, { | ||
6634 | /* --- boards without eeprom + subsystem ID --- */ | 6664 | /* --- boards without eeprom + subsystem ID --- */ |
6635 | .vendor = PCI_VENDOR_ID_PHILIPS, | 6665 | .vendor = PCI_VENDOR_ID_PHILIPS, |
6636 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | 6666 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, |
@@ -7320,6 +7350,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
7320 | case SAA7134_BOARD_VIDEOMATE_DVBT_300: | 7350 | case SAA7134_BOARD_VIDEOMATE_DVBT_300: |
7321 | case SAA7134_BOARD_ASUS_EUROPA2_HYBRID: | 7351 | case SAA7134_BOARD_ASUS_EUROPA2_HYBRID: |
7322 | case SAA7134_BOARD_ASUS_EUROPA_HYBRID: | 7352 | case SAA7134_BOARD_ASUS_EUROPA_HYBRID: |
7353 | case SAA7134_BOARD_TECHNOTREND_BUDGET_T3000: | ||
7323 | { | 7354 | { |
7324 | 7355 | ||
7325 | /* The Philips EUROPA based hybrid boards have the tuner | 7356 | /* The Philips EUROPA based hybrid boards have the tuner |
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 90f231881297..40bc635e8a3f 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c | |||
@@ -256,7 +256,7 @@ void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf) | |||
256 | BUG_ON(in_interrupt()); | 256 | BUG_ON(in_interrupt()); |
257 | 257 | ||
258 | videobuf_waiton(&buf->vb,0,0); | 258 | videobuf_waiton(&buf->vb,0,0); |
259 | videobuf_dma_unmap(q, dma); | 259 | videobuf_dma_unmap(q->dev, dma); |
260 | videobuf_dma_free(dma); | 260 | videobuf_dma_free(dma); |
261 | buf->vb.state = VIDEOBUF_NEEDS_INIT; | 261 | buf->vb.state = VIDEOBUF_NEEDS_INIT; |
262 | } | 262 | } |
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 31e82be1b7e7..f26fe7661a1d 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c | |||
@@ -481,6 +481,17 @@ static struct tda1004x_config medion_cardbus = { | |||
481 | .request_firmware = philips_tda1004x_request_firmware | 481 | .request_firmware = philips_tda1004x_request_firmware |
482 | }; | 482 | }; |
483 | 483 | ||
484 | static struct tda1004x_config technotrend_budget_t3000_config = { | ||
485 | .demod_address = 0x8, | ||
486 | .invert = 1, | ||
487 | .invert_oclk = 0, | ||
488 | .xtal_freq = TDA10046_XTAL_4M, | ||
489 | .agc_config = TDA10046_AGC_DEFAULT, | ||
490 | .if_freq = TDA10046_FREQ_3617, | ||
491 | .tuner_address = 0x63, | ||
492 | .request_firmware = philips_tda1004x_request_firmware | ||
493 | }; | ||
494 | |||
484 | /* ------------------------------------------------------------------ | 495 | /* ------------------------------------------------------------------ |
485 | * tda 1004x based cards with philips silicon tuner | 496 | * tda 1004x based cards with philips silicon tuner |
486 | */ | 497 | */ |
@@ -1168,6 +1179,18 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1168 | fe0->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params; | 1179 | fe0->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params; |
1169 | } | 1180 | } |
1170 | break; | 1181 | break; |
1182 | case SAA7134_BOARD_TECHNOTREND_BUDGET_T3000: | ||
1183 | fe0->dvb.frontend = dvb_attach(tda10046_attach, | ||
1184 | &technotrend_budget_t3000_config, | ||
1185 | &dev->i2c_adap); | ||
1186 | if (fe0->dvb.frontend) { | ||
1187 | dev->original_demod_sleep = fe0->dvb.frontend->ops.sleep; | ||
1188 | fe0->dvb.frontend->ops.sleep = philips_europa_demod_sleep; | ||
1189 | fe0->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init; | ||
1190 | fe0->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep; | ||
1191 | fe0->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params; | ||
1192 | } | ||
1193 | break; | ||
1171 | case SAA7134_BOARD_VIDEOMATE_DVBT_200: | 1194 | case SAA7134_BOARD_VIDEOMATE_DVBT_200: |
1172 | fe0->dvb.frontend = dvb_attach(tda10046_attach, | 1195 | fe0->dvb.frontend = dvb_attach(tda10046_attach, |
1173 | &philips_tu1216_61_config, | 1196 | &philips_tu1216_61_config, |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 756a1ca8833d..c040a1808542 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -304,6 +304,7 @@ struct saa7134_format { | |||
304 | #define SAA7134_BOARD_BEHOLD_H7 178 | 304 | #define SAA7134_BOARD_BEHOLD_H7 178 |
305 | #define SAA7134_BOARD_BEHOLD_A7 179 | 305 | #define SAA7134_BOARD_BEHOLD_A7 179 |
306 | #define SAA7134_BOARD_AVERMEDIA_M733A 180 | 306 | #define SAA7134_BOARD_AVERMEDIA_M733A 180 |
307 | #define SAA7134_BOARD_TECHNOTREND_BUDGET_T3000 181 | ||
307 | 308 | ||
308 | #define SAA7134_MAXBOARDS 32 | 309 | #define SAA7134_MAXBOARDS 32 |
309 | #define SAA7134_INPUT_MAX 8 | 310 | #define SAA7134_INPUT_MAX 8 |
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 961bfa2fea97..2b24bd0de3ad 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
@@ -633,6 +633,12 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd) | |||
633 | cdwdr_width *= 2; | 633 | cdwdr_width *= 2; |
634 | } | 634 | } |
635 | 635 | ||
636 | /* CSI2 special configuration */ | ||
637 | if (pcdev->pdata->csi2_dev) { | ||
638 | in_width = ((in_width - 2) * 2); | ||
639 | left_offset *= 2; | ||
640 | } | ||
641 | |||
636 | /* Set CAMOR, CAPWR, CFSZR, take care of CDWDR */ | 642 | /* Set CAMOR, CAPWR, CFSZR, take care of CDWDR */ |
637 | camor = left_offset | (top_offset << 16); | 643 | camor = left_offset | (top_offset << 16); |
638 | 644 | ||
@@ -743,16 +749,16 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, | |||
743 | case V4L2_PIX_FMT_NV16: | 749 | case V4L2_PIX_FMT_NV16: |
744 | case V4L2_PIX_FMT_NV61: | 750 | case V4L2_PIX_FMT_NV61: |
745 | switch (cam->code) { | 751 | switch (cam->code) { |
746 | case V4L2_MBUS_FMT_YUYV8_2X8_BE: | 752 | case V4L2_MBUS_FMT_UYVY8_2X8: |
747 | value = 0x00000000; /* Cb0, Y0, Cr0, Y1 */ | 753 | value = 0x00000000; /* Cb0, Y0, Cr0, Y1 */ |
748 | break; | 754 | break; |
749 | case V4L2_MBUS_FMT_YVYU8_2X8_BE: | 755 | case V4L2_MBUS_FMT_VYUY8_2X8: |
750 | value = 0x00000100; /* Cr0, Y0, Cb0, Y1 */ | 756 | value = 0x00000100; /* Cr0, Y0, Cb0, Y1 */ |
751 | break; | 757 | break; |
752 | case V4L2_MBUS_FMT_YUYV8_2X8_LE: | 758 | case V4L2_MBUS_FMT_YUYV8_2X8: |
753 | value = 0x00000200; /* Y0, Cb0, Y1, Cr0 */ | 759 | value = 0x00000200; /* Y0, Cb0, Y1, Cr0 */ |
754 | break; | 760 | break; |
755 | case V4L2_MBUS_FMT_YVYU8_2X8_LE: | 761 | case V4L2_MBUS_FMT_YVYU8_2X8: |
756 | value = 0x00000300; /* Y0, Cr0, Y1, Cb0 */ | 762 | value = 0x00000300; /* Y0, Cr0, Y1, Cb0 */ |
757 | break; | 763 | break; |
758 | default: | 764 | default: |
@@ -767,6 +773,11 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, | |||
767 | value |= common_flags & SOCAM_VSYNC_ACTIVE_LOW ? 1 << 1 : 0; | 773 | value |= common_flags & SOCAM_VSYNC_ACTIVE_LOW ? 1 << 1 : 0; |
768 | value |= common_flags & SOCAM_HSYNC_ACTIVE_LOW ? 1 << 0 : 0; | 774 | value |= common_flags & SOCAM_HSYNC_ACTIVE_LOW ? 1 << 0 : 0; |
769 | value |= pcdev->is_16bit ? 1 << 12 : 0; | 775 | value |= pcdev->is_16bit ? 1 << 12 : 0; |
776 | |||
777 | /* CSI2 mode */ | ||
778 | if (pcdev->pdata->csi2_dev) | ||
779 | value |= 3 << 12; | ||
780 | |||
770 | ceu_write(pcdev, CAMCR, value); | 781 | ceu_write(pcdev, CAMCR, value); |
771 | 782 | ||
772 | ceu_write(pcdev, CAPCR, 0x00300000); | 783 | ceu_write(pcdev, CAPCR, 0x00300000); |
@@ -883,6 +894,8 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int | |||
883 | { | 894 | { |
884 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 895 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
885 | struct device *dev = icd->dev.parent; | 896 | struct device *dev = icd->dev.parent; |
897 | struct soc_camera_host *ici = to_soc_camera_host(dev); | ||
898 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | ||
886 | int ret, k, n; | 899 | int ret, k, n; |
887 | int formats = 0; | 900 | int formats = 0; |
888 | struct sh_mobile_ceu_cam *cam; | 901 | struct sh_mobile_ceu_cam *cam; |
@@ -896,19 +909,19 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int | |||
896 | 909 | ||
897 | fmt = soc_mbus_get_fmtdesc(code); | 910 | fmt = soc_mbus_get_fmtdesc(code); |
898 | if (!fmt) { | 911 | if (!fmt) { |
899 | dev_err(icd->dev.parent, | 912 | dev_err(dev, "Invalid format code #%u: %d\n", idx, code); |
900 | "Invalid format code #%u: %d\n", idx, code); | ||
901 | return -EINVAL; | 913 | return -EINVAL; |
902 | } | 914 | } |
903 | 915 | ||
904 | ret = sh_mobile_ceu_try_bus_param(icd, fmt->bits_per_sample); | 916 | if (!pcdev->pdata->csi2_dev) { |
905 | if (ret < 0) | 917 | ret = sh_mobile_ceu_try_bus_param(icd, fmt->bits_per_sample); |
906 | return 0; | 918 | if (ret < 0) |
919 | return 0; | ||
920 | } | ||
907 | 921 | ||
908 | if (!icd->host_priv) { | 922 | if (!icd->host_priv) { |
909 | struct v4l2_mbus_framefmt mf; | 923 | struct v4l2_mbus_framefmt mf; |
910 | struct v4l2_rect rect; | 924 | struct v4l2_rect rect; |
911 | struct device *dev = icd->dev.parent; | ||
912 | int shift = 0; | 925 | int shift = 0; |
913 | 926 | ||
914 | /* FIXME: subwindow is lost between close / open */ | 927 | /* FIXME: subwindow is lost between close / open */ |
@@ -927,7 +940,8 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int | |||
927 | /* Try 2560x1920, 1280x960, 640x480, 320x240 */ | 940 | /* Try 2560x1920, 1280x960, 640x480, 320x240 */ |
928 | mf.width = 2560 >> shift; | 941 | mf.width = 2560 >> shift; |
929 | mf.height = 1920 >> shift; | 942 | mf.height = 1920 >> shift; |
930 | ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); | 943 | ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video, |
944 | s_mbus_fmt, &mf); | ||
931 | if (ret < 0) | 945 | if (ret < 0) |
932 | return ret; | 946 | return ret; |
933 | shift++; | 947 | shift++; |
@@ -965,10 +979,10 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int | |||
965 | cam->extra_fmt = NULL; | 979 | cam->extra_fmt = NULL; |
966 | 980 | ||
967 | switch (code) { | 981 | switch (code) { |
968 | case V4L2_MBUS_FMT_YUYV8_2X8_BE: | 982 | case V4L2_MBUS_FMT_UYVY8_2X8: |
969 | case V4L2_MBUS_FMT_YVYU8_2X8_BE: | 983 | case V4L2_MBUS_FMT_VYUY8_2X8: |
970 | case V4L2_MBUS_FMT_YUYV8_2X8_LE: | 984 | case V4L2_MBUS_FMT_YUYV8_2X8: |
971 | case V4L2_MBUS_FMT_YVYU8_2X8_LE: | 985 | case V4L2_MBUS_FMT_YVYU8_2X8: |
972 | if (cam->extra_fmt) | 986 | if (cam->extra_fmt) |
973 | break; | 987 | break; |
974 | 988 | ||
@@ -1005,7 +1019,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int | |||
1005 | xlate->code = code; | 1019 | xlate->code = code; |
1006 | xlate++; | 1020 | xlate++; |
1007 | dev_dbg(dev, "Providing format %s in pass-through mode\n", | 1021 | dev_dbg(dev, "Providing format %s in pass-through mode\n", |
1008 | xlate->host_fmt->name); | 1022 | fmt->name); |
1009 | } | 1023 | } |
1010 | 1024 | ||
1011 | return formats; | 1025 | return formats; |
@@ -1228,7 +1242,8 @@ static int client_s_fmt(struct soc_camera_device *icd, | |||
1228 | struct v4l2_cropcap cap; | 1242 | struct v4l2_cropcap cap; |
1229 | int ret; | 1243 | int ret; |
1230 | 1244 | ||
1231 | ret = v4l2_subdev_call(sd, video, s_mbus_fmt, mf); | 1245 | ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video, |
1246 | s_mbus_fmt, mf); | ||
1232 | if (ret < 0) | 1247 | if (ret < 0) |
1233 | return ret; | 1248 | return ret; |
1234 | 1249 | ||
@@ -1257,7 +1272,8 @@ static int client_s_fmt(struct soc_camera_device *icd, | |||
1257 | tmp_h = min(2 * tmp_h, max_height); | 1272 | tmp_h = min(2 * tmp_h, max_height); |
1258 | mf->width = tmp_w; | 1273 | mf->width = tmp_w; |
1259 | mf->height = tmp_h; | 1274 | mf->height = tmp_h; |
1260 | ret = v4l2_subdev_call(sd, video, s_mbus_fmt, mf); | 1275 | ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video, |
1276 | s_mbus_fmt, mf); | ||
1261 | dev_geo(dev, "Camera scaled to %ux%u\n", | 1277 | dev_geo(dev, "Camera scaled to %ux%u\n", |
1262 | mf->width, mf->height); | 1278 | mf->width, mf->height); |
1263 | if (ret < 0) { | 1279 | if (ret < 0) { |
@@ -1514,7 +1530,8 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, | |||
1514 | struct device *dev = icd->dev.parent; | 1530 | struct device *dev = icd->dev.parent; |
1515 | __u32 pixfmt = pix->pixelformat; | 1531 | __u32 pixfmt = pix->pixelformat; |
1516 | const struct soc_camera_format_xlate *xlate; | 1532 | const struct soc_camera_format_xlate *xlate; |
1517 | unsigned int ceu_sub_width, ceu_sub_height; | 1533 | /* Keep Compiler Happy */ |
1534 | unsigned int ceu_sub_width = 0, ceu_sub_height = 0; | ||
1518 | u16 scale_v, scale_h; | 1535 | u16 scale_v, scale_h; |
1519 | int ret; | 1536 | int ret; |
1520 | bool image_mode; | 1537 | bool image_mode; |
@@ -1569,8 +1586,8 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, | |||
1569 | 1586 | ||
1570 | /* Done with the camera. Now see if we can improve the result */ | 1587 | /* Done with the camera. Now see if we can improve the result */ |
1571 | 1588 | ||
1572 | dev_geo(dev, "Camera %d fmt %ux%u, requested %ux%u\n", | 1589 | dev_geo(dev, "fmt %ux%u, requested %ux%u\n", |
1573 | ret, mf.width, mf.height, pix->width, pix->height); | 1590 | mf.width, mf.height, pix->width, pix->height); |
1574 | if (ret < 0) | 1591 | if (ret < 0) |
1575 | return ret; | 1592 | return ret; |
1576 | 1593 | ||
@@ -1634,6 +1651,9 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, | |||
1634 | int width, height; | 1651 | int width, height; |
1635 | int ret; | 1652 | int ret; |
1636 | 1653 | ||
1654 | dev_geo(icd->dev.parent, "TRY_FMT(pix=0x%x, %ux%u)\n", | ||
1655 | pixfmt, pix->width, pix->height); | ||
1656 | |||
1637 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); | 1657 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); |
1638 | if (!xlate) { | 1658 | if (!xlate) { |
1639 | dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt); | 1659 | dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt); |
@@ -1660,7 +1680,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, | |||
1660 | mf.code = xlate->code; | 1680 | mf.code = xlate->code; |
1661 | mf.colorspace = pix->colorspace; | 1681 | mf.colorspace = pix->colorspace; |
1662 | 1682 | ||
1663 | ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf); | 1683 | ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video, try_mbus_fmt, &mf); |
1664 | if (ret < 0) | 1684 | if (ret < 0) |
1665 | return ret; | 1685 | return ret; |
1666 | 1686 | ||
@@ -1684,7 +1704,8 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, | |||
1684 | */ | 1704 | */ |
1685 | mf.width = 2560; | 1705 | mf.width = 2560; |
1686 | mf.height = 1920; | 1706 | mf.height = 1920; |
1687 | ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf); | 1707 | ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video, |
1708 | try_mbus_fmt, &mf); | ||
1688 | if (ret < 0) { | 1709 | if (ret < 0) { |
1689 | /* Shouldn't actually happen... */ | 1710 | /* Shouldn't actually happen... */ |
1690 | dev_err(icd->dev.parent, | 1711 | dev_err(icd->dev.parent, |
@@ -1699,6 +1720,9 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, | |||
1699 | pix->height = height; | 1720 | pix->height = height; |
1700 | } | 1721 | } |
1701 | 1722 | ||
1723 | dev_geo(icd->dev.parent, "%s(): return %d, fmt 0x%x, %ux%u\n", | ||
1724 | __func__, ret, pix->pixelformat, pix->width, pix->height); | ||
1725 | |||
1702 | return ret; | 1726 | return ret; |
1703 | } | 1727 | } |
1704 | 1728 | ||
@@ -1853,6 +1877,30 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { | |||
1853 | .num_controls = ARRAY_SIZE(sh_mobile_ceu_controls), | 1877 | .num_controls = ARRAY_SIZE(sh_mobile_ceu_controls), |
1854 | }; | 1878 | }; |
1855 | 1879 | ||
1880 | struct bus_wait { | ||
1881 | struct notifier_block notifier; | ||
1882 | struct completion completion; | ||
1883 | struct device *dev; | ||
1884 | }; | ||
1885 | |||
1886 | static int bus_notify(struct notifier_block *nb, | ||
1887 | unsigned long action, void *data) | ||
1888 | { | ||
1889 | struct device *dev = data; | ||
1890 | struct bus_wait *wait = container_of(nb, struct bus_wait, notifier); | ||
1891 | |||
1892 | if (wait->dev != dev) | ||
1893 | return NOTIFY_DONE; | ||
1894 | |||
1895 | switch (action) { | ||
1896 | case BUS_NOTIFY_UNBOUND_DRIVER: | ||
1897 | /* Protect from module unloading */ | ||
1898 | wait_for_completion(&wait->completion); | ||
1899 | return NOTIFY_OK; | ||
1900 | } | ||
1901 | return NOTIFY_DONE; | ||
1902 | } | ||
1903 | |||
1856 | static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev) | 1904 | static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev) |
1857 | { | 1905 | { |
1858 | struct sh_mobile_ceu_dev *pcdev; | 1906 | struct sh_mobile_ceu_dev *pcdev; |
@@ -1860,6 +1908,11 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev) | |||
1860 | void __iomem *base; | 1908 | void __iomem *base; |
1861 | unsigned int irq; | 1909 | unsigned int irq; |
1862 | int err = 0; | 1910 | int err = 0; |
1911 | struct bus_wait wait = { | ||
1912 | .completion = COMPLETION_INITIALIZER_ONSTACK(wait.completion), | ||
1913 | .notifier.notifier_call = bus_notify, | ||
1914 | }; | ||
1915 | struct device *csi2; | ||
1863 | 1916 | ||
1864 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1917 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1865 | irq = platform_get_irq(pdev, 0); | 1918 | irq = platform_get_irq(pdev, 0); |
@@ -1931,12 +1984,54 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev) | |||
1931 | pcdev->ici.drv_name = dev_name(&pdev->dev); | 1984 | pcdev->ici.drv_name = dev_name(&pdev->dev); |
1932 | pcdev->ici.ops = &sh_mobile_ceu_host_ops; | 1985 | pcdev->ici.ops = &sh_mobile_ceu_host_ops; |
1933 | 1986 | ||
1987 | /* CSI2 interfacing */ | ||
1988 | csi2 = pcdev->pdata->csi2_dev; | ||
1989 | if (csi2) { | ||
1990 | wait.dev = csi2; | ||
1991 | |||
1992 | err = bus_register_notifier(&platform_bus_type, &wait.notifier); | ||
1993 | if (err < 0) | ||
1994 | goto exit_free_clk; | ||
1995 | |||
1996 | /* | ||
1997 | * From this point the driver module will not unload, until | ||
1998 | * we complete the completion. | ||
1999 | */ | ||
2000 | |||
2001 | if (!csi2->driver || !csi2->driver->owner) { | ||
2002 | complete(&wait.completion); | ||
2003 | /* Either too late, or probing failed */ | ||
2004 | bus_unregister_notifier(&platform_bus_type, &wait.notifier); | ||
2005 | err = -ENXIO; | ||
2006 | goto exit_free_clk; | ||
2007 | } | ||
2008 | |||
2009 | /* | ||
2010 | * The module is still loaded, in the worst case it is hanging | ||
2011 | * in device release on our completion. So, _now_ dereferencing | ||
2012 | * the "owner" is safe! | ||
2013 | */ | ||
2014 | |||
2015 | err = try_module_get(csi2->driver->owner); | ||
2016 | |||
2017 | /* Let notifier complete, if it has been locked */ | ||
2018 | complete(&wait.completion); | ||
2019 | bus_unregister_notifier(&platform_bus_type, &wait.notifier); | ||
2020 | if (!err) { | ||
2021 | err = -ENODEV; | ||
2022 | goto exit_free_clk; | ||
2023 | } | ||
2024 | } | ||
2025 | |||
1934 | err = soc_camera_host_register(&pcdev->ici); | 2026 | err = soc_camera_host_register(&pcdev->ici); |
1935 | if (err) | 2027 | if (err) |
1936 | goto exit_free_clk; | 2028 | goto exit_module_put; |
1937 | 2029 | ||
1938 | return 0; | 2030 | return 0; |
1939 | 2031 | ||
2032 | exit_module_put: | ||
2033 | if (csi2 && csi2->driver) | ||
2034 | module_put(csi2->driver->owner); | ||
1940 | exit_free_clk: | 2035 | exit_free_clk: |
1941 | pm_runtime_disable(&pdev->dev); | 2036 | pm_runtime_disable(&pdev->dev); |
1942 | free_irq(pcdev->irq, pcdev); | 2037 | free_irq(pcdev->irq, pcdev); |
@@ -1956,6 +2051,7 @@ static int __devexit sh_mobile_ceu_remove(struct platform_device *pdev) | |||
1956 | struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); | 2051 | struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); |
1957 | struct sh_mobile_ceu_dev *pcdev = container_of(soc_host, | 2052 | struct sh_mobile_ceu_dev *pcdev = container_of(soc_host, |
1958 | struct sh_mobile_ceu_dev, ici); | 2053 | struct sh_mobile_ceu_dev, ici); |
2054 | struct device *csi2 = pcdev->pdata->csi2_dev; | ||
1959 | 2055 | ||
1960 | soc_camera_host_unregister(soc_host); | 2056 | soc_camera_host_unregister(soc_host); |
1961 | pm_runtime_disable(&pdev->dev); | 2057 | pm_runtime_disable(&pdev->dev); |
@@ -1963,7 +2059,10 @@ static int __devexit sh_mobile_ceu_remove(struct platform_device *pdev) | |||
1963 | if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) | 2059 | if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) |
1964 | dma_release_declared_memory(&pdev->dev); | 2060 | dma_release_declared_memory(&pdev->dev); |
1965 | iounmap(pcdev->base); | 2061 | iounmap(pcdev->base); |
2062 | if (csi2 && csi2->driver) | ||
2063 | module_put(csi2->driver->owner); | ||
1966 | kfree(pcdev); | 2064 | kfree(pcdev); |
2065 | |||
1967 | return 0; | 2066 | return 0; |
1968 | } | 2067 | } |
1969 | 2068 | ||
@@ -1995,6 +2094,8 @@ static struct platform_driver sh_mobile_ceu_driver = { | |||
1995 | 2094 | ||
1996 | static int __init sh_mobile_ceu_init(void) | 2095 | static int __init sh_mobile_ceu_init(void) |
1997 | { | 2096 | { |
2097 | /* Whatever return code */ | ||
2098 | request_module("sh_mobile_csi2"); | ||
1998 | return platform_driver_register(&sh_mobile_ceu_driver); | 2099 | return platform_driver_register(&sh_mobile_ceu_driver); |
1999 | } | 2100 | } |
2000 | 2101 | ||
diff --git a/drivers/media/video/sh_mobile_csi2.c b/drivers/media/video/sh_mobile_csi2.c new file mode 100644 index 000000000000..84a646819318 --- /dev/null +++ b/drivers/media/video/sh_mobile_csi2.c | |||
@@ -0,0 +1,354 @@ | |||
1 | /* | ||
2 | * Driver for the SH-Mobile MIPI CSI-2 unit | ||
3 | * | ||
4 | * Copyright (C) 2010, 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/delay.h> | ||
12 | #include <linux/i2c.h> | ||
13 | #include <linux/io.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/pm_runtime.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/videodev2.h> | ||
18 | |||
19 | #include <media/sh_mobile_csi2.h> | ||
20 | #include <media/soc_camera.h> | ||
21 | #include <media/v4l2-common.h> | ||
22 | #include <media/v4l2-dev.h> | ||
23 | #include <media/v4l2-device.h> | ||
24 | #include <media/v4l2-mediabus.h> | ||
25 | #include <media/v4l2-subdev.h> | ||
26 | |||
27 | #define SH_CSI2_TREF 0x00 | ||
28 | #define SH_CSI2_SRST 0x04 | ||
29 | #define SH_CSI2_PHYCNT 0x08 | ||
30 | #define SH_CSI2_CHKSUM 0x0C | ||
31 | #define SH_CSI2_VCDT 0x10 | ||
32 | |||
33 | struct sh_csi2 { | ||
34 | struct v4l2_subdev subdev; | ||
35 | struct list_head list; | ||
36 | struct notifier_block notifier; | ||
37 | unsigned int irq; | ||
38 | void __iomem *base; | ||
39 | struct platform_device *pdev; | ||
40 | struct sh_csi2_client_config *client; | ||
41 | }; | ||
42 | |||
43 | static int sh_csi2_try_fmt(struct v4l2_subdev *sd, | ||
44 | struct v4l2_mbus_framefmt *mf) | ||
45 | { | ||
46 | struct sh_csi2 *priv = container_of(sd, struct sh_csi2, subdev); | ||
47 | struct sh_csi2_pdata *pdata = priv->pdev->dev.platform_data; | ||
48 | |||
49 | if (mf->width > 8188) | ||
50 | mf->width = 8188; | ||
51 | else if (mf->width & 1) | ||
52 | mf->width &= ~1; | ||
53 | |||
54 | switch (pdata->type) { | ||
55 | case SH_CSI2C: | ||
56 | switch (mf->code) { | ||
57 | case V4L2_MBUS_FMT_UYVY8_2X8: /* YUV422 */ | ||
58 | case V4L2_MBUS_FMT_YUYV8_1_5X8: /* YUV420 */ | ||
59 | case V4L2_MBUS_FMT_GREY8_1X8: /* RAW8 */ | ||
60 | case V4L2_MBUS_FMT_SBGGR8_1X8: | ||
61 | case V4L2_MBUS_FMT_SGRBG8_1X8: | ||
62 | break; | ||
63 | default: | ||
64 | /* All MIPI CSI-2 devices must support one of primary formats */ | ||
65 | mf->code = V4L2_MBUS_FMT_YUYV8_2X8; | ||
66 | } | ||
67 | break; | ||
68 | case SH_CSI2I: | ||
69 | switch (mf->code) { | ||
70 | case V4L2_MBUS_FMT_GREY8_1X8: /* RAW8 */ | ||
71 | case V4L2_MBUS_FMT_SBGGR8_1X8: | ||
72 | case V4L2_MBUS_FMT_SGRBG8_1X8: | ||
73 | case V4L2_MBUS_FMT_SBGGR10_1X10: /* RAW10 */ | ||
74 | case V4L2_MBUS_FMT_SBGGR12_1X12: /* RAW12 */ | ||
75 | break; | ||
76 | default: | ||
77 | /* All MIPI CSI-2 devices must support one of primary formats */ | ||
78 | mf->code = V4L2_MBUS_FMT_SBGGR8_1X8; | ||
79 | } | ||
80 | break; | ||
81 | } | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | /* | ||
87 | * We have done our best in try_fmt to try and tell the sensor, which formats | ||
88 | * we support. If now the configuration is unsuitable for us we can only | ||
89 | * error out. | ||
90 | */ | ||
91 | static int sh_csi2_s_fmt(struct v4l2_subdev *sd, | ||
92 | struct v4l2_mbus_framefmt *mf) | ||
93 | { | ||
94 | struct sh_csi2 *priv = container_of(sd, struct sh_csi2, subdev); | ||
95 | u32 tmp = (priv->client->channel & 3) << 8; | ||
96 | |||
97 | dev_dbg(sd->v4l2_dev->dev, "%s(%u)\n", __func__, mf->code); | ||
98 | if (mf->width > 8188 || mf->width & 1) | ||
99 | return -EINVAL; | ||
100 | |||
101 | switch (mf->code) { | ||
102 | case V4L2_MBUS_FMT_UYVY8_2X8: | ||
103 | tmp |= 0x1e; /* YUV422 8 bit */ | ||
104 | break; | ||
105 | case V4L2_MBUS_FMT_YUYV8_1_5X8: | ||
106 | tmp |= 0x18; /* YUV420 8 bit */ | ||
107 | break; | ||
108 | case V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE: | ||
109 | tmp |= 0x21; /* RGB555 */ | ||
110 | break; | ||
111 | case V4L2_MBUS_FMT_RGB565_2X8_BE: | ||
112 | tmp |= 0x22; /* RGB565 */ | ||
113 | break; | ||
114 | case V4L2_MBUS_FMT_GREY8_1X8: | ||
115 | case V4L2_MBUS_FMT_SBGGR8_1X8: | ||
116 | case V4L2_MBUS_FMT_SGRBG8_1X8: | ||
117 | tmp |= 0x2a; /* RAW8 */ | ||
118 | break; | ||
119 | default: | ||
120 | return -EINVAL; | ||
121 | } | ||
122 | |||
123 | iowrite32(tmp, priv->base + SH_CSI2_VCDT); | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static struct v4l2_subdev_video_ops sh_csi2_subdev_video_ops = { | ||
129 | .s_mbus_fmt = sh_csi2_s_fmt, | ||
130 | .try_mbus_fmt = sh_csi2_try_fmt, | ||
131 | }; | ||
132 | |||
133 | static struct v4l2_subdev_core_ops sh_csi2_subdev_core_ops; | ||
134 | |||
135 | static struct v4l2_subdev_ops sh_csi2_subdev_ops = { | ||
136 | .core = &sh_csi2_subdev_core_ops, | ||
137 | .video = &sh_csi2_subdev_video_ops, | ||
138 | }; | ||
139 | |||
140 | static void sh_csi2_hwinit(struct sh_csi2 *priv) | ||
141 | { | ||
142 | struct sh_csi2_pdata *pdata = priv->pdev->dev.platform_data; | ||
143 | __u32 tmp = 0x10; /* Enable MIPI CSI clock lane */ | ||
144 | |||
145 | /* Reflect registers immediately */ | ||
146 | iowrite32(0x00000001, priv->base + SH_CSI2_TREF); | ||
147 | /* reset CSI2 harware */ | ||
148 | iowrite32(0x00000001, priv->base + SH_CSI2_SRST); | ||
149 | udelay(5); | ||
150 | iowrite32(0x00000000, priv->base + SH_CSI2_SRST); | ||
151 | |||
152 | if (priv->client->lanes & 3) | ||
153 | tmp |= priv->client->lanes & 3; | ||
154 | else | ||
155 | /* Default - both lanes */ | ||
156 | tmp |= 3; | ||
157 | |||
158 | if (priv->client->phy == SH_CSI2_PHY_MAIN) | ||
159 | tmp |= 0x8000; | ||
160 | |||
161 | iowrite32(tmp, priv->base + SH_CSI2_PHYCNT); | ||
162 | |||
163 | tmp = 0; | ||
164 | if (pdata->flags & SH_CSI2_ECC) | ||
165 | tmp |= 2; | ||
166 | if (pdata->flags & SH_CSI2_CRC) | ||
167 | tmp |= 1; | ||
168 | iowrite32(tmp, priv->base + SH_CSI2_CHKSUM); | ||
169 | } | ||
170 | |||
171 | static int sh_csi2_set_bus_param(struct soc_camera_device *icd, | ||
172 | unsigned long flags) | ||
173 | { | ||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | static unsigned long sh_csi2_query_bus_param(struct soc_camera_device *icd) | ||
178 | { | ||
179 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
180 | const unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | | ||
181 | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | | ||
182 | SOCAM_MASTER | SOCAM_DATAWIDTH_8 | SOCAM_DATA_ACTIVE_HIGH; | ||
183 | |||
184 | return soc_camera_apply_sensor_flags(icl, flags); | ||
185 | } | ||
186 | |||
187 | static int sh_csi2_notify(struct notifier_block *nb, | ||
188 | unsigned long action, void *data) | ||
189 | { | ||
190 | struct device *dev = data; | ||
191 | struct soc_camera_device *icd = to_soc_camera_dev(dev); | ||
192 | struct v4l2_device *v4l2_dev = dev_get_drvdata(dev->parent); | ||
193 | struct sh_csi2 *priv = | ||
194 | container_of(nb, struct sh_csi2, notifier); | ||
195 | struct sh_csi2_pdata *pdata = priv->pdev->dev.platform_data; | ||
196 | int ret, i; | ||
197 | |||
198 | for (i = 0; i < pdata->num_clients; i++) | ||
199 | if (&pdata->clients[i].pdev->dev == icd->pdev) | ||
200 | break; | ||
201 | |||
202 | dev_dbg(dev, "%s(%p): action = %lu, found #%d\n", __func__, dev, action, i); | ||
203 | |||
204 | if (i == pdata->num_clients) | ||
205 | return NOTIFY_DONE; | ||
206 | |||
207 | switch (action) { | ||
208 | case BUS_NOTIFY_BOUND_DRIVER: | ||
209 | snprintf(priv->subdev.name, V4L2_SUBDEV_NAME_SIZE, "%s%s", | ||
210 | dev_name(v4l2_dev->dev), ".mipi-csi"); | ||
211 | ret = v4l2_device_register_subdev(v4l2_dev, &priv->subdev); | ||
212 | dev_dbg(dev, "%s(%p): ret(register_subdev) = %d\n", __func__, priv, ret); | ||
213 | if (ret < 0) | ||
214 | return NOTIFY_DONE; | ||
215 | |||
216 | priv->client = pdata->clients + i; | ||
217 | |||
218 | icd->ops->set_bus_param = sh_csi2_set_bus_param; | ||
219 | icd->ops->query_bus_param = sh_csi2_query_bus_param; | ||
220 | |||
221 | pm_runtime_get_sync(v4l2_get_subdevdata(&priv->subdev)); | ||
222 | |||
223 | sh_csi2_hwinit(priv); | ||
224 | break; | ||
225 | case BUS_NOTIFY_UNBIND_DRIVER: | ||
226 | priv->client = NULL; | ||
227 | |||
228 | /* Driver is about to be unbound */ | ||
229 | icd->ops->set_bus_param = NULL; | ||
230 | icd->ops->query_bus_param = NULL; | ||
231 | |||
232 | v4l2_device_unregister_subdev(&priv->subdev); | ||
233 | |||
234 | pm_runtime_put(v4l2_get_subdevdata(&priv->subdev)); | ||
235 | break; | ||
236 | } | ||
237 | |||
238 | return NOTIFY_OK; | ||
239 | } | ||
240 | |||
241 | static __devinit int sh_csi2_probe(struct platform_device *pdev) | ||
242 | { | ||
243 | struct resource *res; | ||
244 | unsigned int irq; | ||
245 | int ret; | ||
246 | struct sh_csi2 *priv; | ||
247 | /* Platform data specify the PHY, lanes, ECC, CRC */ | ||
248 | struct sh_csi2_pdata *pdata = pdev->dev.platform_data; | ||
249 | |||
250 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
251 | /* Interrupt unused so far */ | ||
252 | irq = platform_get_irq(pdev, 0); | ||
253 | |||
254 | if (!res || (int)irq <= 0 || !pdata) { | ||
255 | dev_err(&pdev->dev, "Not enough CSI2 platform resources.\n"); | ||
256 | return -ENODEV; | ||
257 | } | ||
258 | |||
259 | /* TODO: Add support for CSI2I. Careful: different register layout! */ | ||
260 | if (pdata->type != SH_CSI2C) { | ||
261 | dev_err(&pdev->dev, "Only CSI2C supported ATM.\n"); | ||
262 | return -EINVAL; | ||
263 | } | ||
264 | |||
265 | priv = kzalloc(sizeof(struct sh_csi2), GFP_KERNEL); | ||
266 | if (!priv) | ||
267 | return -ENOMEM; | ||
268 | |||
269 | priv->irq = irq; | ||
270 | priv->notifier.notifier_call = sh_csi2_notify; | ||
271 | |||
272 | /* We MUST attach after the MIPI sensor */ | ||
273 | ret = bus_register_notifier(&soc_camera_bus_type, &priv->notifier); | ||
274 | if (ret < 0) { | ||
275 | dev_err(&pdev->dev, "CSI2 cannot register notifier\n"); | ||
276 | goto ernotify; | ||
277 | } | ||
278 | |||
279 | if (!request_mem_region(res->start, resource_size(res), pdev->name)) { | ||
280 | dev_err(&pdev->dev, "CSI2 register region already claimed\n"); | ||
281 | ret = -EBUSY; | ||
282 | goto ereqreg; | ||
283 | } | ||
284 | |||
285 | priv->base = ioremap(res->start, resource_size(res)); | ||
286 | if (!priv->base) { | ||
287 | ret = -ENXIO; | ||
288 | dev_err(&pdev->dev, "Unable to ioremap CSI2 registers.\n"); | ||
289 | goto eremap; | ||
290 | } | ||
291 | |||
292 | priv->pdev = pdev; | ||
293 | |||
294 | v4l2_subdev_init(&priv->subdev, &sh_csi2_subdev_ops); | ||
295 | v4l2_set_subdevdata(&priv->subdev, &pdev->dev); | ||
296 | |||
297 | platform_set_drvdata(pdev, priv); | ||
298 | |||
299 | pm_runtime_enable(&pdev->dev); | ||
300 | |||
301 | dev_dbg(&pdev->dev, "CSI2 probed.\n"); | ||
302 | |||
303 | return 0; | ||
304 | |||
305 | eremap: | ||
306 | release_mem_region(res->start, resource_size(res)); | ||
307 | ereqreg: | ||
308 | bus_unregister_notifier(&soc_camera_bus_type, &priv->notifier); | ||
309 | ernotify: | ||
310 | kfree(priv); | ||
311 | |||
312 | return ret; | ||
313 | } | ||
314 | |||
315 | static __devexit int sh_csi2_remove(struct platform_device *pdev) | ||
316 | { | ||
317 | struct sh_csi2 *priv = platform_get_drvdata(pdev); | ||
318 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
319 | |||
320 | bus_unregister_notifier(&soc_camera_bus_type, &priv->notifier); | ||
321 | pm_runtime_disable(&pdev->dev); | ||
322 | iounmap(priv->base); | ||
323 | release_mem_region(res->start, resource_size(res)); | ||
324 | platform_set_drvdata(pdev, NULL); | ||
325 | kfree(priv); | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | static struct platform_driver __refdata sh_csi2_pdrv = { | ||
331 | .remove = __devexit_p(sh_csi2_remove), | ||
332 | .driver = { | ||
333 | .name = "sh-mobile-csi2", | ||
334 | .owner = THIS_MODULE, | ||
335 | }, | ||
336 | }; | ||
337 | |||
338 | static int __init sh_csi2_init(void) | ||
339 | { | ||
340 | return platform_driver_probe(&sh_csi2_pdrv, sh_csi2_probe); | ||
341 | } | ||
342 | |||
343 | static void __exit sh_csi2_exit(void) | ||
344 | { | ||
345 | platform_driver_unregister(&sh_csi2_pdrv); | ||
346 | } | ||
347 | |||
348 | module_init(sh_csi2_init); | ||
349 | module_exit(sh_csi2_exit); | ||
350 | |||
351 | MODULE_DESCRIPTION("SH-Mobile MIPI CSI-2 driver"); | ||
352 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); | ||
353 | MODULE_LICENSE("GPL v2"); | ||
354 | MODULE_ALIAS("platform:sh-mobile-csi2"); | ||
diff --git a/drivers/media/video/sh_vou.c b/drivers/media/video/sh_vou.c index f5b892a2a8ee..d394187eb701 100644 --- a/drivers/media/video/sh_vou.c +++ b/drivers/media/video/sh_vou.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/pm_runtime.h> | 20 | #include <linux/pm_runtime.h> |
21 | #include <linux/slab.h> | ||
21 | #include <linux/version.h> | 22 | #include <linux/version.h> |
22 | #include <linux/videodev2.h> | 23 | #include <linux/videodev2.h> |
23 | 24 | ||
@@ -57,7 +58,7 @@ enum sh_vou_status { | |||
57 | }; | 58 | }; |
58 | 59 | ||
59 | #define VOU_MAX_IMAGE_WIDTH 720 | 60 | #define VOU_MAX_IMAGE_WIDTH 720 |
60 | #define VOU_MAX_IMAGE_HEIGHT 480 | 61 | #define VOU_MAX_IMAGE_HEIGHT 576 |
61 | 62 | ||
62 | struct sh_vou_device { | 63 | struct sh_vou_device { |
63 | struct v4l2_device v4l2_dev; | 64 | struct v4l2_device v4l2_dev; |
@@ -527,20 +528,17 @@ struct sh_vou_geometry { | |||
527 | static void vou_adjust_input(struct sh_vou_geometry *geo, v4l2_std_id std) | 528 | static void vou_adjust_input(struct sh_vou_geometry *geo, v4l2_std_id std) |
528 | { | 529 | { |
529 | /* The compiler cannot know, that best and idx will indeed be set */ | 530 | /* The compiler cannot know, that best and idx will indeed be set */ |
530 | unsigned int best_err = UINT_MAX, best = 0, width_max, height_max; | 531 | unsigned int best_err = UINT_MAX, best = 0, img_height_max; |
531 | int i, idx = 0; | 532 | int i, idx = 0; |
532 | 533 | ||
533 | if (std & V4L2_STD_525_60) { | 534 | if (std & V4L2_STD_525_60) |
534 | width_max = 858; | 535 | img_height_max = 480; |
535 | height_max = 262; | 536 | else |
536 | } else { | 537 | img_height_max = 576; |
537 | width_max = 864; | ||
538 | height_max = 312; | ||
539 | } | ||
540 | 538 | ||
541 | /* Image width must be a multiple of 4 */ | 539 | /* Image width must be a multiple of 4 */ |
542 | v4l_bound_align_image(&geo->in_width, 0, VOU_MAX_IMAGE_WIDTH, 2, | 540 | v4l_bound_align_image(&geo->in_width, 0, VOU_MAX_IMAGE_WIDTH, 2, |
543 | &geo->in_height, 0, VOU_MAX_IMAGE_HEIGHT, 1, 0); | 541 | &geo->in_height, 0, img_height_max, 1, 0); |
544 | 542 | ||
545 | /* Select scales to come as close as possible to the output image */ | 543 | /* Select scales to come as close as possible to the output image */ |
546 | for (i = ARRAY_SIZE(vou_scale_h_num) - 1; i >= 0; i--) { | 544 | for (i = ARRAY_SIZE(vou_scale_h_num) - 1; i >= 0; i--) { |
@@ -573,7 +571,7 @@ static void vou_adjust_input(struct sh_vou_geometry *geo, v4l2_std_id std) | |||
573 | unsigned int found = geo->output.height * vou_scale_v_den[i] / | 571 | unsigned int found = geo->output.height * vou_scale_v_den[i] / |
574 | vou_scale_v_num[i]; | 572 | vou_scale_v_num[i]; |
575 | 573 | ||
576 | if (found > VOU_MAX_IMAGE_HEIGHT) | 574 | if (found > img_height_max) |
577 | /* scales increase */ | 575 | /* scales increase */ |
578 | break; | 576 | break; |
579 | 577 | ||
@@ -597,15 +595,18 @@ static void vou_adjust_input(struct sh_vou_geometry *geo, v4l2_std_id std) | |||
597 | */ | 595 | */ |
598 | static void vou_adjust_output(struct sh_vou_geometry *geo, v4l2_std_id std) | 596 | static void vou_adjust_output(struct sh_vou_geometry *geo, v4l2_std_id std) |
599 | { | 597 | { |
600 | unsigned int best_err = UINT_MAX, best, width_max, height_max; | 598 | unsigned int best_err = UINT_MAX, best, width_max, height_max, |
599 | img_height_max; | ||
601 | int i, idx; | 600 | int i, idx; |
602 | 601 | ||
603 | if (std & V4L2_STD_525_60) { | 602 | if (std & V4L2_STD_525_60) { |
604 | width_max = 858; | 603 | width_max = 858; |
605 | height_max = 262 * 2; | 604 | height_max = 262 * 2; |
605 | img_height_max = 480; | ||
606 | } else { | 606 | } else { |
607 | width_max = 864; | 607 | width_max = 864; |
608 | height_max = 312 * 2; | 608 | height_max = 312 * 2; |
609 | img_height_max = 576; | ||
609 | } | 610 | } |
610 | 611 | ||
611 | /* Select scales to come as close as possible to the output image */ | 612 | /* Select scales to come as close as possible to the output image */ |
@@ -644,7 +645,7 @@ static void vou_adjust_output(struct sh_vou_geometry *geo, v4l2_std_id std) | |||
644 | unsigned int found = geo->in_height * vou_scale_v_num[i] / | 645 | unsigned int found = geo->in_height * vou_scale_v_num[i] / |
645 | vou_scale_v_den[i]; | 646 | vou_scale_v_den[i]; |
646 | 647 | ||
647 | if (found > VOU_MAX_IMAGE_HEIGHT) | 648 | if (found > img_height_max) |
648 | /* scales increase */ | 649 | /* scales increase */ |
649 | break; | 650 | break; |
650 | 651 | ||
@@ -673,11 +674,12 @@ static int sh_vou_s_fmt_vid_out(struct file *file, void *priv, | |||
673 | struct video_device *vdev = video_devdata(file); | 674 | struct video_device *vdev = video_devdata(file); |
674 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); | 675 | struct sh_vou_device *vou_dev = video_get_drvdata(vdev); |
675 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | 676 | struct v4l2_pix_format *pix = &fmt->fmt.pix; |
677 | unsigned int img_height_max; | ||
676 | int pix_idx; | 678 | int pix_idx; |
677 | struct sh_vou_geometry geo; | 679 | struct sh_vou_geometry geo; |
678 | struct v4l2_mbus_framefmt mbfmt = { | 680 | struct v4l2_mbus_framefmt mbfmt = { |
679 | /* Revisit: is this the correct code? */ | 681 | /* Revisit: is this the correct code? */ |
680 | .code = V4L2_MBUS_FMT_YUYV8_2X8_LE, | 682 | .code = V4L2_MBUS_FMT_YUYV8_2X8, |
681 | .field = V4L2_FIELD_INTERLACED, | 683 | .field = V4L2_FIELD_INTERLACED, |
682 | .colorspace = V4L2_COLORSPACE_SMPTE170M, | 684 | .colorspace = V4L2_COLORSPACE_SMPTE170M, |
683 | }; | 685 | }; |
@@ -701,9 +703,14 @@ static int sh_vou_s_fmt_vid_out(struct file *file, void *priv, | |||
701 | if (pix_idx == ARRAY_SIZE(vou_fmt)) | 703 | if (pix_idx == ARRAY_SIZE(vou_fmt)) |
702 | return -EINVAL; | 704 | return -EINVAL; |
703 | 705 | ||
706 | if (vou_dev->std & V4L2_STD_525_60) | ||
707 | img_height_max = 480; | ||
708 | else | ||
709 | img_height_max = 576; | ||
710 | |||
704 | /* Image width must be a multiple of 4 */ | 711 | /* Image width must be a multiple of 4 */ |
705 | v4l_bound_align_image(&pix->width, 0, VOU_MAX_IMAGE_WIDTH, 2, | 712 | v4l_bound_align_image(&pix->width, 0, VOU_MAX_IMAGE_WIDTH, 2, |
706 | &pix->height, 0, VOU_MAX_IMAGE_HEIGHT, 1, 0); | 713 | &pix->height, 0, img_height_max, 1, 0); |
707 | 714 | ||
708 | geo.in_width = pix->width; | 715 | geo.in_width = pix->width; |
709 | geo.in_height = pix->height; | 716 | geo.in_height = pix->height; |
@@ -724,8 +731,8 @@ static int sh_vou_s_fmt_vid_out(struct file *file, void *priv, | |||
724 | 731 | ||
725 | /* Sanity checks */ | 732 | /* Sanity checks */ |
726 | if ((unsigned)mbfmt.width > VOU_MAX_IMAGE_WIDTH || | 733 | if ((unsigned)mbfmt.width > VOU_MAX_IMAGE_WIDTH || |
727 | (unsigned)mbfmt.height > VOU_MAX_IMAGE_HEIGHT || | 734 | (unsigned)mbfmt.height > img_height_max || |
728 | mbfmt.code != V4L2_MBUS_FMT_YUYV8_2X8_LE) | 735 | mbfmt.code != V4L2_MBUS_FMT_YUYV8_2X8) |
729 | return -EIO; | 736 | return -EIO; |
730 | 737 | ||
731 | if (mbfmt.width != geo.output.width || | 738 | if (mbfmt.width != geo.output.width || |
@@ -936,10 +943,11 @@ static int sh_vou_s_crop(struct file *file, void *fh, struct v4l2_crop *a) | |||
936 | struct sh_vou_geometry geo; | 943 | struct sh_vou_geometry geo; |
937 | struct v4l2_mbus_framefmt mbfmt = { | 944 | struct v4l2_mbus_framefmt mbfmt = { |
938 | /* Revisit: is this the correct code? */ | 945 | /* Revisit: is this the correct code? */ |
939 | .code = V4L2_MBUS_FMT_YUYV8_2X8_LE, | 946 | .code = V4L2_MBUS_FMT_YUYV8_2X8, |
940 | .field = V4L2_FIELD_INTERLACED, | 947 | .field = V4L2_FIELD_INTERLACED, |
941 | .colorspace = V4L2_COLORSPACE_SMPTE170M, | 948 | .colorspace = V4L2_COLORSPACE_SMPTE170M, |
942 | }; | 949 | }; |
950 | unsigned int img_height_max; | ||
943 | int ret; | 951 | int ret; |
944 | 952 | ||
945 | dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u@%u:%u\n", __func__, | 953 | dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u@%u:%u\n", __func__, |
@@ -948,14 +956,19 @@ static int sh_vou_s_crop(struct file *file, void *fh, struct v4l2_crop *a) | |||
948 | if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) | 956 | if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) |
949 | return -EINVAL; | 957 | return -EINVAL; |
950 | 958 | ||
959 | if (vou_dev->std & V4L2_STD_525_60) | ||
960 | img_height_max = 480; | ||
961 | else | ||
962 | img_height_max = 576; | ||
963 | |||
951 | v4l_bound_align_image(&rect->width, 0, VOU_MAX_IMAGE_WIDTH, 1, | 964 | v4l_bound_align_image(&rect->width, 0, VOU_MAX_IMAGE_WIDTH, 1, |
952 | &rect->height, 0, VOU_MAX_IMAGE_HEIGHT, 1, 0); | 965 | &rect->height, 0, img_height_max, 1, 0); |
953 | 966 | ||
954 | if (rect->width + rect->left > VOU_MAX_IMAGE_WIDTH) | 967 | if (rect->width + rect->left > VOU_MAX_IMAGE_WIDTH) |
955 | rect->left = VOU_MAX_IMAGE_WIDTH - rect->width; | 968 | rect->left = VOU_MAX_IMAGE_WIDTH - rect->width; |
956 | 969 | ||
957 | if (rect->height + rect->top > VOU_MAX_IMAGE_HEIGHT) | 970 | if (rect->height + rect->top > img_height_max) |
958 | rect->top = VOU_MAX_IMAGE_HEIGHT - rect->height; | 971 | rect->top = img_height_max - rect->height; |
959 | 972 | ||
960 | geo.output = *rect; | 973 | geo.output = *rect; |
961 | geo.in_width = pix->width; | 974 | geo.in_width = pix->width; |
@@ -980,8 +993,8 @@ static int sh_vou_s_crop(struct file *file, void *fh, struct v4l2_crop *a) | |||
980 | 993 | ||
981 | /* Sanity checks */ | 994 | /* Sanity checks */ |
982 | if ((unsigned)mbfmt.width > VOU_MAX_IMAGE_WIDTH || | 995 | if ((unsigned)mbfmt.width > VOU_MAX_IMAGE_WIDTH || |
983 | (unsigned)mbfmt.height > VOU_MAX_IMAGE_HEIGHT || | 996 | (unsigned)mbfmt.height > img_height_max || |
984 | mbfmt.code != V4L2_MBUS_FMT_YUYV8_2X8_LE) | 997 | mbfmt.code != V4L2_MBUS_FMT_YUYV8_2X8) |
985 | return -EIO; | 998 | return -EIO; |
986 | 999 | ||
987 | geo.output.width = mbfmt.width; | 1000 | geo.output.width = mbfmt.width; |
@@ -1329,13 +1342,13 @@ static int __devinit sh_vou_probe(struct platform_device *pdev) | |||
1329 | rect->left = 0; | 1342 | rect->left = 0; |
1330 | rect->top = 0; | 1343 | rect->top = 0; |
1331 | rect->width = VOU_MAX_IMAGE_WIDTH; | 1344 | rect->width = VOU_MAX_IMAGE_WIDTH; |
1332 | rect->height = VOU_MAX_IMAGE_HEIGHT; | 1345 | rect->height = 480; |
1333 | pix->width = VOU_MAX_IMAGE_WIDTH; | 1346 | pix->width = VOU_MAX_IMAGE_WIDTH; |
1334 | pix->height = VOU_MAX_IMAGE_HEIGHT; | 1347 | pix->height = 480; |
1335 | pix->pixelformat = V4L2_PIX_FMT_YVYU; | 1348 | pix->pixelformat = V4L2_PIX_FMT_YVYU; |
1336 | pix->field = V4L2_FIELD_NONE; | 1349 | pix->field = V4L2_FIELD_NONE; |
1337 | pix->bytesperline = VOU_MAX_IMAGE_WIDTH * 2; | 1350 | pix->bytesperline = VOU_MAX_IMAGE_WIDTH * 2; |
1338 | pix->sizeimage = VOU_MAX_IMAGE_WIDTH * 2 * VOU_MAX_IMAGE_HEIGHT; | 1351 | pix->sizeimage = VOU_MAX_IMAGE_WIDTH * 2 * 480; |
1339 | pix->colorspace = V4L2_COLORSPACE_SMPTE170M; | 1352 | pix->colorspace = V4L2_COLORSPACE_SMPTE170M; |
1340 | 1353 | ||
1341 | region = request_mem_region(reg_res->start, resource_size(reg_res), | 1354 | region = request_mem_region(reg_res->start, resource_size(reg_res), |
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 475757bfd7ba..f2032939fd4b 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
@@ -1107,13 +1107,14 @@ static int soc_camera_resume(struct device *dev) | |||
1107 | return ret; | 1107 | return ret; |
1108 | } | 1108 | } |
1109 | 1109 | ||
1110 | static struct bus_type soc_camera_bus_type = { | 1110 | struct bus_type soc_camera_bus_type = { |
1111 | .name = "soc-camera", | 1111 | .name = "soc-camera", |
1112 | .probe = soc_camera_probe, | 1112 | .probe = soc_camera_probe, |
1113 | .remove = soc_camera_remove, | 1113 | .remove = soc_camera_remove, |
1114 | .suspend = soc_camera_suspend, | 1114 | .suspend = soc_camera_suspend, |
1115 | .resume = soc_camera_resume, | 1115 | .resume = soc_camera_resume, |
1116 | }; | 1116 | }; |
1117 | EXPORT_SYMBOL_GPL(soc_camera_bus_type); | ||
1117 | 1118 | ||
1118 | static struct device_driver ic_drv = { | 1119 | static struct device_driver ic_drv = { |
1119 | .name = "camera", | 1120 | .name = "camera", |
diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c index 248c986f0989..bf406e89c992 100644 --- a/drivers/media/video/soc_camera_platform.c +++ b/drivers/media/video/soc_camera_platform.c | |||
@@ -56,8 +56,8 @@ soc_camera_platform_query_bus_param(struct soc_camera_device *icd) | |||
56 | return p->bus_param; | 56 | return p->bus_param; |
57 | } | 57 | } |
58 | 58 | ||
59 | static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd, | 59 | static int soc_camera_platform_fill_fmt(struct v4l2_subdev *sd, |
60 | struct v4l2_mbus_framefmt *mf) | 60 | struct v4l2_mbus_framefmt *mf) |
61 | { | 61 | { |
62 | struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); | 62 | struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); |
63 | 63 | ||
@@ -65,6 +65,7 @@ static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd, | |||
65 | mf->height = p->format.height; | 65 | mf->height = p->format.height; |
66 | mf->code = p->format.code; | 66 | mf->code = p->format.code; |
67 | mf->colorspace = p->format.colorspace; | 67 | mf->colorspace = p->format.colorspace; |
68 | mf->field = p->format.field; | ||
68 | 69 | ||
69 | return 0; | 70 | return 0; |
70 | } | 71 | } |
@@ -83,10 +84,45 @@ static int soc_camera_platform_enum_fmt(struct v4l2_subdev *sd, unsigned int ind | |||
83 | return 0; | 84 | return 0; |
84 | } | 85 | } |
85 | 86 | ||
87 | static int soc_camera_platform_g_crop(struct v4l2_subdev *sd, | ||
88 | struct v4l2_crop *a) | ||
89 | { | ||
90 | struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); | ||
91 | |||
92 | a->c.left = 0; | ||
93 | a->c.top = 0; | ||
94 | a->c.width = p->format.width; | ||
95 | a->c.height = p->format.height; | ||
96 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static int soc_camera_platform_cropcap(struct v4l2_subdev *sd, | ||
102 | struct v4l2_cropcap *a) | ||
103 | { | ||
104 | struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); | ||
105 | |||
106 | a->bounds.left = 0; | ||
107 | a->bounds.top = 0; | ||
108 | a->bounds.width = p->format.width; | ||
109 | a->bounds.height = p->format.height; | ||
110 | a->defrect = a->bounds; | ||
111 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
112 | a->pixelaspect.numerator = 1; | ||
113 | a->pixelaspect.denominator = 1; | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
86 | static struct v4l2_subdev_video_ops platform_subdev_video_ops = { | 118 | static struct v4l2_subdev_video_ops platform_subdev_video_ops = { |
87 | .s_stream = soc_camera_platform_s_stream, | 119 | .s_stream = soc_camera_platform_s_stream, |
88 | .try_mbus_fmt = soc_camera_platform_try_fmt, | ||
89 | .enum_mbus_fmt = soc_camera_platform_enum_fmt, | 120 | .enum_mbus_fmt = soc_camera_platform_enum_fmt, |
121 | .cropcap = soc_camera_platform_cropcap, | ||
122 | .g_crop = soc_camera_platform_g_crop, | ||
123 | .try_mbus_fmt = soc_camera_platform_fill_fmt, | ||
124 | .g_mbus_fmt = soc_camera_platform_fill_fmt, | ||
125 | .s_mbus_fmt = soc_camera_platform_fill_fmt, | ||
90 | }; | 126 | }; |
91 | 127 | ||
92 | static struct v4l2_subdev_ops platform_subdev_ops = { | 128 | static struct v4l2_subdev_ops platform_subdev_ops = { |
diff --git a/drivers/media/video/soc_mediabus.c b/drivers/media/video/soc_mediabus.c index 8b63b6545e76..91391214c682 100644 --- a/drivers/media/video/soc_mediabus.c +++ b/drivers/media/video/soc_mediabus.c | |||
@@ -18,28 +18,28 @@ | |||
18 | #define MBUS_IDX(f) (V4L2_MBUS_FMT_ ## f - V4L2_MBUS_FMT_FIXED - 1) | 18 | #define MBUS_IDX(f) (V4L2_MBUS_FMT_ ## f - V4L2_MBUS_FMT_FIXED - 1) |
19 | 19 | ||
20 | static const struct soc_mbus_pixelfmt mbus_fmt[] = { | 20 | static const struct soc_mbus_pixelfmt mbus_fmt[] = { |
21 | [MBUS_IDX(YUYV8_2X8_LE)] = { | 21 | [MBUS_IDX(YUYV8_2X8)] = { |
22 | .fourcc = V4L2_PIX_FMT_YUYV, | 22 | .fourcc = V4L2_PIX_FMT_YUYV, |
23 | .name = "YUYV", | 23 | .name = "YUYV", |
24 | .bits_per_sample = 8, | 24 | .bits_per_sample = 8, |
25 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 25 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
26 | .order = SOC_MBUS_ORDER_LE, | 26 | .order = SOC_MBUS_ORDER_LE, |
27 | }, | 27 | }, |
28 | [MBUS_IDX(YVYU8_2X8_LE)] = { | 28 | [MBUS_IDX(YVYU8_2X8)] = { |
29 | .fourcc = V4L2_PIX_FMT_YVYU, | 29 | .fourcc = V4L2_PIX_FMT_YVYU, |
30 | .name = "YVYU", | 30 | .name = "YVYU", |
31 | .bits_per_sample = 8, | 31 | .bits_per_sample = 8, |
32 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 32 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
33 | .order = SOC_MBUS_ORDER_LE, | 33 | .order = SOC_MBUS_ORDER_LE, |
34 | }, | 34 | }, |
35 | [MBUS_IDX(YUYV8_2X8_BE)] = { | 35 | [MBUS_IDX(UYVY8_2X8)] = { |
36 | .fourcc = V4L2_PIX_FMT_UYVY, | 36 | .fourcc = V4L2_PIX_FMT_UYVY, |
37 | .name = "UYVY", | 37 | .name = "UYVY", |
38 | .bits_per_sample = 8, | 38 | .bits_per_sample = 8, |
39 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 39 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
40 | .order = SOC_MBUS_ORDER_LE, | 40 | .order = SOC_MBUS_ORDER_LE, |
41 | }, | 41 | }, |
42 | [MBUS_IDX(YVYU8_2X8_BE)] = { | 42 | [MBUS_IDX(VYUY8_2X8)] = { |
43 | .fourcc = V4L2_PIX_FMT_VYUY, | 43 | .fourcc = V4L2_PIX_FMT_VYUY, |
44 | .name = "VYUY", | 44 | .name = "VYUY", |
45 | .bits_per_sample = 8, | 45 | .bits_per_sample = 8, |
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c deleted file mode 100644 index 5938ad8702ef..000000000000 --- a/drivers/media/video/stv680.c +++ /dev/null | |||
@@ -1,1565 +0,0 @@ | |||
1 | /* | ||
2 | * STV0680 USB Camera Driver, by Kevin Sisson (kjsisson@bellsouth.net) | ||
3 | * | ||
4 | * Thanks to STMicroelectronics for information on the usb commands, and | ||
5 | * to Steve Miller at STM for his help and encouragement while I was | ||
6 | * writing this driver. | ||
7 | * | ||
8 | * This driver is based heavily on the | ||
9 | * Endpoints (formerly known as AOX) se401 USB Camera Driver | ||
10 | * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org) | ||
11 | * | ||
12 | * Still somewhat based on the Linux ov511 driver. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify it | ||
15 | * under the terms of the GNU General Public License as published by the | ||
16 | * Free Software Foundation; either version 2 of the License, or (at your | ||
17 | * option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, but | ||
20 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
21 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
22 | * for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software Foundation, | ||
26 | * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
27 | * | ||
28 | * History: | ||
29 | * ver 0.1 October, 2001. Initial attempt. | ||
30 | * | ||
31 | * ver 0.2 November, 2001. Fixed asbility to resize, added brightness | ||
32 | * function, made more stable (?) | ||
33 | * | ||
34 | * ver 0.21 Nov, 2001. Added gamma correction and white balance, | ||
35 | * due to Alexander Schwartz. Still trying to | ||
36 | * improve stablility. Moved stuff into stv680.h | ||
37 | * | ||
38 | * ver 0.22 Nov, 2001. Added sharpen function (by Michael Sweet, | ||
39 | * mike@easysw.com) from GIMP, also used in pencam. | ||
40 | * Simple, fast, good integer math routine. | ||
41 | * | ||
42 | * ver 0.23 Dec, 2001 (gkh) | ||
43 | * Took out sharpen function, ran code through | ||
44 | * Lindent, and did other minor tweaks to get | ||
45 | * things to work properly with 2.5.1 | ||
46 | * | ||
47 | * ver 0.24 Jan, 2002 (kjs) | ||
48 | * Fixed the problem with webcam crashing after | ||
49 | * two pictures. Changed the way pic is halved to | ||
50 | * improve quality. Got rid of green line around | ||
51 | * frame. Fix brightness reset when changing size | ||
52 | * bug. Adjusted gamma filters slightly. | ||
53 | * | ||
54 | * ver 0.25 Jan, 2002 (kjs) | ||
55 | * Fixed a bug in which the driver sometimes attempted | ||
56 | * to set to a non-supported size. This allowed | ||
57 | * gnomemeeting to work. | ||
58 | * Fixed proc entry removal bug. | ||
59 | */ | ||
60 | |||
61 | #include <linux/module.h> | ||
62 | #include <linux/init.h> | ||
63 | #include <linux/vmalloc.h> | ||
64 | #include <linux/slab.h> | ||
65 | #include <linux/smp_lock.h> | ||
66 | #include <linux/pagemap.h> | ||
67 | #include <linux/errno.h> | ||
68 | #include <linux/videodev.h> | ||
69 | #include <media/v4l2-common.h> | ||
70 | #include <media/v4l2-ioctl.h> | ||
71 | #include <linux/usb.h> | ||
72 | #include <linux/mutex.h> | ||
73 | |||
74 | #include "stv680.h" | ||
75 | |||
76 | static int video_nr = -1; | ||
77 | |||
78 | static int swapRGB; /* 0 = default for auto select */ | ||
79 | |||
80 | /* 0 = default to allow auto select; -1 = swap never, +1 = swap always */ | ||
81 | static int swapRGB_on; | ||
82 | |||
83 | static unsigned int debug; | ||
84 | |||
85 | #define PDEBUG(level, fmt, args...) \ | ||
86 | do { \ | ||
87 | if (debug >= level) \ | ||
88 | printk(KERN_INFO KBUILD_MODNAME " [%s:%d] \n" fmt, \ | ||
89 | __func__, __LINE__ , ## args); \ | ||
90 | } while (0) | ||
91 | |||
92 | |||
93 | /* | ||
94 | * Version Information | ||
95 | */ | ||
96 | #define DRIVER_VERSION "v0.25" | ||
97 | #define DRIVER_AUTHOR "Kevin Sisson <kjsisson@bellsouth.net>" | ||
98 | #define DRIVER_DESC "STV0680 USB Camera Driver" | ||
99 | |||
100 | MODULE_AUTHOR (DRIVER_AUTHOR); | ||
101 | MODULE_DESCRIPTION (DRIVER_DESC); | ||
102 | MODULE_LICENSE ("GPL"); | ||
103 | module_param(debug, int, S_IRUGO | S_IWUSR); | ||
104 | MODULE_PARM_DESC (debug, "Debug enabled or not"); | ||
105 | module_param(swapRGB_on, int, 0); | ||
106 | MODULE_PARM_DESC (swapRGB_on, "Red/blue swap: 1=always, 0=auto, -1=never"); | ||
107 | module_param(video_nr, int, 0); | ||
108 | |||
109 | /******************************************************************** | ||
110 | * | ||
111 | * Memory management | ||
112 | * | ||
113 | * This is a shameless copy from the USB-cpia driver (linux kernel | ||
114 | * version 2.3.29 or so, I have no idea what this code actually does ;). | ||
115 | * Actually it seems to be a copy of a shameless copy of the bttv-driver. | ||
116 | * Or that is a copy of a shameless copy of ... (To the powers: is there | ||
117 | * no generic kernel-function to do this sort of stuff?) | ||
118 | * | ||
119 | * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says | ||
120 | * there will be one, but apparentely not yet -jerdfelt | ||
121 | * | ||
122 | * So I copied it again for the ov511 driver -claudio | ||
123 | * | ||
124 | * Same for the se401 driver -Jeroen | ||
125 | * | ||
126 | * And the STV0680 driver - Kevin | ||
127 | ********************************************************************/ | ||
128 | static void *rvmalloc (unsigned long size) | ||
129 | { | ||
130 | void *mem; | ||
131 | unsigned long adr; | ||
132 | |||
133 | size = PAGE_ALIGN(size); | ||
134 | mem = vmalloc_32 (size); | ||
135 | if (!mem) | ||
136 | return NULL; | ||
137 | |||
138 | memset (mem, 0, size); /* Clear the ram out, no junk to the user */ | ||
139 | adr = (unsigned long) mem; | ||
140 | while (size > 0) { | ||
141 | SetPageReserved(vmalloc_to_page((void *)adr)); | ||
142 | adr += PAGE_SIZE; | ||
143 | size -= PAGE_SIZE; | ||
144 | } | ||
145 | return mem; | ||
146 | } | ||
147 | |||
148 | static void rvfree (void *mem, unsigned long size) | ||
149 | { | ||
150 | unsigned long adr; | ||
151 | |||
152 | if (!mem) | ||
153 | return; | ||
154 | |||
155 | adr = (unsigned long) mem; | ||
156 | while ((long) size > 0) { | ||
157 | ClearPageReserved(vmalloc_to_page((void *)adr)); | ||
158 | adr += PAGE_SIZE; | ||
159 | size -= PAGE_SIZE; | ||
160 | } | ||
161 | vfree (mem); | ||
162 | } | ||
163 | |||
164 | |||
165 | /********************************************************************* | ||
166 | * pencam read/write functions | ||
167 | ********************************************************************/ | ||
168 | |||
169 | static int stv_sndctrl (int set, struct usb_stv *stv680, unsigned short req, unsigned short value, unsigned char *buffer, int size) | ||
170 | { | ||
171 | int ret = -1; | ||
172 | |||
173 | switch (set) { | ||
174 | case 0: /* 0xc1 */ | ||
175 | ret = usb_control_msg (stv680->udev, | ||
176 | usb_rcvctrlpipe (stv680->udev, 0), | ||
177 | req, | ||
178 | (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT), | ||
179 | value, 0, buffer, size, PENCAM_TIMEOUT); | ||
180 | break; | ||
181 | |||
182 | case 1: /* 0x41 */ | ||
183 | ret = usb_control_msg (stv680->udev, | ||
184 | usb_sndctrlpipe (stv680->udev, 0), | ||
185 | req, | ||
186 | (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT), | ||
187 | value, 0, buffer, size, PENCAM_TIMEOUT); | ||
188 | break; | ||
189 | |||
190 | case 2: /* 0x80 */ | ||
191 | ret = usb_control_msg (stv680->udev, | ||
192 | usb_rcvctrlpipe (stv680->udev, 0), | ||
193 | req, | ||
194 | (USB_DIR_IN | USB_RECIP_DEVICE), | ||
195 | value, 0, buffer, size, PENCAM_TIMEOUT); | ||
196 | break; | ||
197 | |||
198 | case 3: /* 0x40 */ | ||
199 | ret = usb_control_msg (stv680->udev, | ||
200 | usb_sndctrlpipe (stv680->udev, 0), | ||
201 | req, | ||
202 | (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE), | ||
203 | value, 0, buffer, size, PENCAM_TIMEOUT); | ||
204 | break; | ||
205 | |||
206 | } | ||
207 | if ((ret < 0) && (req != 0x0a)) { | ||
208 | PDEBUG (1, "STV(e): usb_control_msg error %i, request = 0x%x, error = %i", set, req, ret); | ||
209 | } | ||
210 | return ret; | ||
211 | } | ||
212 | |||
213 | static int stv_set_config (struct usb_stv *dev, int configuration, int interface, int alternate) | ||
214 | { | ||
215 | |||
216 | if (configuration != dev->udev->actconfig->desc.bConfigurationValue | ||
217 | || usb_reset_configuration (dev->udev) < 0) { | ||
218 | PDEBUG (1, "STV(e): FAILED to reset configuration %i", configuration); | ||
219 | return -1; | ||
220 | } | ||
221 | if (usb_set_interface (dev->udev, interface, alternate) < 0) { | ||
222 | PDEBUG (1, "STV(e): FAILED to set alternate interface %i", alternate); | ||
223 | return -1; | ||
224 | } | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static int stv_stop_video (struct usb_stv *dev) | ||
229 | { | ||
230 | int i; | ||
231 | unsigned char *buf; | ||
232 | |||
233 | buf = kmalloc (40, GFP_KERNEL); | ||
234 | if (buf == NULL) { | ||
235 | PDEBUG (0, "STV(e): Out of (small buf) memory"); | ||
236 | return -1; | ||
237 | } | ||
238 | |||
239 | /* this is a high priority command; it stops all lower order commands */ | ||
240 | if ((i = stv_sndctrl (1, dev, 0x04, 0x0000, buf, 0x0)) < 0) { | ||
241 | i = stv_sndctrl (0, dev, 0x80, 0, buf, 0x02); /* Get Last Error; 2 = busy */ | ||
242 | PDEBUG (1, "STV(i): last error: %i, command = 0x%x", buf[0], buf[1]); | ||
243 | } else { | ||
244 | PDEBUG (1, "STV(i): Camera reset to idle mode."); | ||
245 | } | ||
246 | |||
247 | if ((i = stv_set_config (dev, 1, 0, 0)) < 0) | ||
248 | PDEBUG (1, "STV(e): Reset config during exit failed"); | ||
249 | |||
250 | /* get current mode */ | ||
251 | buf[0] = 0xf0; | ||
252 | if ((i = stv_sndctrl (0, dev, 0x87, 0, buf, 0x08)) != 0x08) /* get mode */ | ||
253 | PDEBUG (0, "STV(e): Stop_video: problem setting original mode"); | ||
254 | if (dev->origMode != buf[0]) { | ||
255 | memset (buf, 0, 8); | ||
256 | buf[0] = (unsigned char) dev->origMode; | ||
257 | if ((i = stv_sndctrl (3, dev, 0x07, 0x0100, buf, 0x08)) != 0x08) { | ||
258 | PDEBUG (0, "STV(e): Stop_video: Set_Camera_Mode failed"); | ||
259 | i = -1; | ||
260 | } | ||
261 | buf[0] = 0xf0; | ||
262 | i = stv_sndctrl (0, dev, 0x87, 0, buf, 0x08); | ||
263 | if ((i != 0x08) || (buf[0] != dev->origMode)) { | ||
264 | PDEBUG (0, "STV(e): camera NOT set to original resolution."); | ||
265 | i = -1; | ||
266 | } else | ||
267 | PDEBUG (0, "STV(i): Camera set to original resolution"); | ||
268 | } | ||
269 | /* origMode */ | ||
270 | kfree(buf); | ||
271 | return i; | ||
272 | } | ||
273 | |||
274 | static int stv_set_video_mode (struct usb_stv *dev) | ||
275 | { | ||
276 | int i, stop_video = 1; | ||
277 | unsigned char *buf; | ||
278 | |||
279 | buf = kmalloc (40, GFP_KERNEL); | ||
280 | if (buf == NULL) { | ||
281 | PDEBUG (0, "STV(e): Out of (small buf) memory"); | ||
282 | return -1; | ||
283 | } | ||
284 | |||
285 | if ((i = stv_set_config (dev, 1, 0, 0)) < 0) { | ||
286 | kfree(buf); | ||
287 | return i; | ||
288 | } | ||
289 | |||
290 | i = stv_sndctrl (2, dev, 0x06, 0x0100, buf, 0x12); | ||
291 | if (!(i > 0) && (buf[8] == 0x53) && (buf[9] == 0x05)) { | ||
292 | PDEBUG (1, "STV(e): Could not get descriptor 0100."); | ||
293 | goto error; | ||
294 | } | ||
295 | |||
296 | /* set alternate interface 1 */ | ||
297 | if ((i = stv_set_config (dev, 1, 0, 1)) < 0) | ||
298 | goto error; | ||
299 | |||
300 | if ((i = stv_sndctrl (0, dev, 0x85, 0, buf, 0x10)) != 0x10) | ||
301 | goto error; | ||
302 | PDEBUG (1, "STV(i): Setting video mode."); | ||
303 | /* Switch to Video mode: 0x0100 = VGA (640x480), 0x0000 = CIF (352x288) 0x0300 = QVGA (320x240) */ | ||
304 | if ((i = stv_sndctrl (1, dev, 0x09, dev->VideoMode, buf, 0x0)) < 0) { | ||
305 | stop_video = 0; | ||
306 | goto error; | ||
307 | } | ||
308 | goto exit; | ||
309 | |||
310 | error: | ||
311 | kfree(buf); | ||
312 | if (stop_video == 1) | ||
313 | stv_stop_video (dev); | ||
314 | return -1; | ||
315 | |||
316 | exit: | ||
317 | kfree(buf); | ||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static int stv_init (struct usb_stv *stv680) | ||
322 | { | ||
323 | int i = 0; | ||
324 | unsigned char *buffer; | ||
325 | unsigned long int bufsize; | ||
326 | |||
327 | buffer = kzalloc (40, GFP_KERNEL); | ||
328 | if (buffer == NULL) { | ||
329 | PDEBUG (0, "STV(e): Out of (small buf) memory"); | ||
330 | return -1; | ||
331 | } | ||
332 | udelay (100); | ||
333 | |||
334 | /* set config 1, interface 0, alternate 0 */ | ||
335 | if ((i = stv_set_config (stv680, 1, 0, 0)) < 0) { | ||
336 | kfree(buffer); | ||
337 | PDEBUG (0, "STV(e): set config 1,0,0 failed"); | ||
338 | return -1; | ||
339 | } | ||
340 | /* ping camera to be sure STV0680 is present */ | ||
341 | if ((i = stv_sndctrl (0, stv680, 0x88, 0x5678, buffer, 0x02)) != 0x02) | ||
342 | goto error; | ||
343 | if ((buffer[0] != 0x56) || (buffer[1] != 0x78)) { | ||
344 | PDEBUG (1, "STV(e): camera ping failed!!"); | ||
345 | goto error; | ||
346 | } | ||
347 | |||
348 | /* get camera descriptor */ | ||
349 | if ((i = stv_sndctrl (2, stv680, 0x06, 0x0200, buffer, 0x09)) != 0x09) | ||
350 | goto error; | ||
351 | i = stv_sndctrl (2, stv680, 0x06, 0x0200, buffer, 0x22); | ||
352 | if (!(i >= 0) && (buffer[7] == 0xa0) && (buffer[8] == 0x23)) { | ||
353 | PDEBUG (1, "STV(e): Could not get descriptor 0200."); | ||
354 | goto error; | ||
355 | } | ||
356 | if ((i = stv_sndctrl (0, stv680, 0x8a, 0, buffer, 0x02)) != 0x02) | ||
357 | goto error; | ||
358 | if ((i = stv_sndctrl (0, stv680, 0x8b, 0, buffer, 0x24)) != 0x24) | ||
359 | goto error; | ||
360 | if ((i = stv_sndctrl (0, stv680, 0x85, 0, buffer, 0x10)) != 0x10) | ||
361 | goto error; | ||
362 | |||
363 | stv680->SupportedModes = buffer[7]; | ||
364 | i = stv680->SupportedModes; | ||
365 | stv680->CIF = 0; | ||
366 | stv680->VGA = 0; | ||
367 | stv680->QVGA = 0; | ||
368 | if (i & 1) | ||
369 | stv680->CIF = 1; | ||
370 | if (i & 2) | ||
371 | stv680->VGA = 1; | ||
372 | if (i & 8) | ||
373 | stv680->QVGA = 1; | ||
374 | if (stv680->SupportedModes == 0) { | ||
375 | PDEBUG (0, "STV(e): There are NO supported STV680 modes!!"); | ||
376 | i = -1; | ||
377 | goto error; | ||
378 | } else { | ||
379 | if (stv680->CIF) | ||
380 | PDEBUG (0, "STV(i): CIF is supported"); | ||
381 | if (stv680->QVGA) | ||
382 | PDEBUG (0, "STV(i): QVGA is supported"); | ||
383 | } | ||
384 | /* FW rev, ASIC rev, sensor ID */ | ||
385 | PDEBUG (1, "STV(i): Firmware rev is %i.%i", buffer[0], buffer[1]); | ||
386 | PDEBUG (1, "STV(i): ASIC rev is %i.%i", buffer[2], buffer[3]); | ||
387 | PDEBUG (1, "STV(i): Sensor ID is %i", (buffer[4]*16) + (buffer[5]>>4)); | ||
388 | |||
389 | /* set alternate interface 1 */ | ||
390 | if ((i = stv_set_config (stv680, 1, 0, 1)) < 0) | ||
391 | goto error; | ||
392 | |||
393 | if ((i = stv_sndctrl (0, stv680, 0x85, 0, buffer, 0x10)) != 0x10) | ||
394 | goto error; | ||
395 | if ((i = stv_sndctrl (0, stv680, 0x8d, 0, buffer, 0x08)) != 0x08) | ||
396 | goto error; | ||
397 | i = buffer[3]; | ||
398 | PDEBUG (0, "STV(i): Camera has %i pictures.", i); | ||
399 | |||
400 | /* get current mode */ | ||
401 | if ((i = stv_sndctrl (0, stv680, 0x87, 0, buffer, 0x08)) != 0x08) | ||
402 | goto error; | ||
403 | stv680->origMode = buffer[0]; /* 01 = VGA, 03 = QVGA, 00 = CIF */ | ||
404 | |||
405 | /* This will attemp CIF mode, if supported. If not, set to QVGA */ | ||
406 | memset (buffer, 0, 8); | ||
407 | if (stv680->CIF) | ||
408 | buffer[0] = 0x00; | ||
409 | else if (stv680->QVGA) | ||
410 | buffer[0] = 0x03; | ||
411 | if ((i = stv_sndctrl (3, stv680, 0x07, 0x0100, buffer, 0x08)) != 0x08) { | ||
412 | PDEBUG (0, "STV(i): Set_Camera_Mode failed"); | ||
413 | i = -1; | ||
414 | goto error; | ||
415 | } | ||
416 | buffer[0] = 0xf0; | ||
417 | stv_sndctrl (0, stv680, 0x87, 0, buffer, 0x08); | ||
418 | if (((stv680->CIF == 1) && (buffer[0] != 0x00)) || ((stv680->QVGA == 1) && (buffer[0] != 0x03))) { | ||
419 | PDEBUG (0, "STV(e): Error setting camera video mode!"); | ||
420 | i = -1; | ||
421 | goto error; | ||
422 | } else { | ||
423 | if (buffer[0] == 0) { | ||
424 | stv680->VideoMode = 0x0000; | ||
425 | PDEBUG (0, "STV(i): Video Mode set to CIF"); | ||
426 | } | ||
427 | if (buffer[0] == 0x03) { | ||
428 | stv680->VideoMode = 0x0300; | ||
429 | PDEBUG (0, "STV(i): Video Mode set to QVGA"); | ||
430 | } | ||
431 | } | ||
432 | if ((i = stv_sndctrl (0, stv680, 0x8f, 0, buffer, 0x10)) != 0x10) | ||
433 | goto error; | ||
434 | bufsize = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | (buffer[3]); | ||
435 | stv680->cwidth = (buffer[4] << 8) | (buffer[5]); /* ->camera = 322, 356, 644 */ | ||
436 | stv680->cheight = (buffer[6] << 8) | (buffer[7]); /* ->camera = 242, 292, 484 */ | ||
437 | stv680->origGain = buffer[12]; | ||
438 | |||
439 | goto exit; | ||
440 | |||
441 | error: | ||
442 | i = stv_sndctrl (0, stv680, 0x80, 0, buffer, 0x02); /* Get Last Error */ | ||
443 | PDEBUG (1, "STV(i): last error: %i, command = 0x%x", buffer[0], buffer[1]); | ||
444 | kfree(buffer); | ||
445 | return -1; | ||
446 | |||
447 | exit: | ||
448 | kfree(buffer); | ||
449 | |||
450 | /* video = 320x240, 352x288 */ | ||
451 | if (stv680->CIF == 1) { | ||
452 | stv680->maxwidth = 352; | ||
453 | stv680->maxheight = 288; | ||
454 | stv680->vwidth = 352; | ||
455 | stv680->vheight = 288; | ||
456 | } | ||
457 | if (stv680->QVGA == 1) { | ||
458 | stv680->maxwidth = 320; | ||
459 | stv680->maxheight = 240; | ||
460 | stv680->vwidth = 320; | ||
461 | stv680->vheight = 240; | ||
462 | } | ||
463 | |||
464 | stv680->rawbufsize = bufsize; /* must be ./. by 8 */ | ||
465 | stv680->maxframesize = bufsize * 3; /* RGB size */ | ||
466 | PDEBUG (2, "STV(i): cwidth = %i, cheight = %i", stv680->cwidth, stv680->cheight); | ||
467 | PDEBUG (1, "STV(i): width = %i, height = %i, rawbufsize = %li", stv680->vwidth, stv680->vheight, stv680->rawbufsize); | ||
468 | |||
469 | /* some default values */ | ||
470 | stv680->bulk_in_endpointAddr = 0x82; | ||
471 | stv680->dropped = 0; | ||
472 | stv680->error = 0; | ||
473 | stv680->framecount = 0; | ||
474 | stv680->readcount = 0; | ||
475 | stv680->streaming = 0; | ||
476 | /* bright, white, colour, hue, contrast are set by software, not in stv0680 */ | ||
477 | stv680->brightness = 32767; | ||
478 | stv680->chgbright = 0; | ||
479 | stv680->whiteness = 0; /* only for greyscale */ | ||
480 | stv680->colour = 32767; | ||
481 | stv680->contrast = 32767; | ||
482 | stv680->hue = 32767; | ||
483 | stv680->palette = STV_VIDEO_PALETTE; | ||
484 | stv680->depth = 24; /* rgb24 bits */ | ||
485 | if ((swapRGB_on == 0) && (swapRGB == 0)) | ||
486 | PDEBUG (1, "STV(i): swapRGB is (auto) OFF"); | ||
487 | else if ((swapRGB_on == 0) && (swapRGB == 1)) | ||
488 | PDEBUG (1, "STV(i): swapRGB is (auto) ON"); | ||
489 | else if (swapRGB_on == 1) | ||
490 | PDEBUG (1, "STV(i): swapRGB is (forced) ON"); | ||
491 | else if (swapRGB_on == -1) | ||
492 | PDEBUG (1, "STV(i): swapRGB is (forced) OFF"); | ||
493 | |||
494 | if (stv_set_video_mode (stv680) < 0) { | ||
495 | PDEBUG (0, "STV(e): Could not set video mode in stv_init"); | ||
496 | return -1; | ||
497 | } | ||
498 | |||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | /***************** last of pencam routines *******************/ | ||
503 | |||
504 | /**************************************************************************** | ||
505 | * sysfs | ||
506 | ***************************************************************************/ | ||
507 | #define stv680_file(name, variable, field) \ | ||
508 | static ssize_t show_##name(struct device *class_dev, \ | ||
509 | struct device_attribute *attr, char *buf) \ | ||
510 | { \ | ||
511 | struct video_device *vdev = to_video_device(class_dev); \ | ||
512 | struct usb_stv *stv = video_get_drvdata(vdev); \ | ||
513 | return sprintf(buf, field, stv->variable); \ | ||
514 | } \ | ||
515 | static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); | ||
516 | |||
517 | stv680_file(model, camera_name, "%s\n"); | ||
518 | stv680_file(in_use, user, "%d\n"); | ||
519 | stv680_file(streaming, streaming, "%d\n"); | ||
520 | stv680_file(palette, palette, "%i\n"); | ||
521 | stv680_file(frames_total, readcount, "%d\n"); | ||
522 | stv680_file(frames_read, framecount, "%d\n"); | ||
523 | stv680_file(packets_dropped, dropped, "%d\n"); | ||
524 | stv680_file(decoding_errors, error, "%d\n"); | ||
525 | |||
526 | static int stv680_create_sysfs_files(struct video_device *vdev) | ||
527 | { | ||
528 | int rc; | ||
529 | |||
530 | rc = device_create_file(&vdev->dev, &dev_attr_model); | ||
531 | if (rc) goto err; | ||
532 | rc = device_create_file(&vdev->dev, &dev_attr_in_use); | ||
533 | if (rc) goto err_model; | ||
534 | rc = device_create_file(&vdev->dev, &dev_attr_streaming); | ||
535 | if (rc) goto err_inuse; | ||
536 | rc = device_create_file(&vdev->dev, &dev_attr_palette); | ||
537 | if (rc) goto err_stream; | ||
538 | rc = device_create_file(&vdev->dev, &dev_attr_frames_total); | ||
539 | if (rc) goto err_pal; | ||
540 | rc = device_create_file(&vdev->dev, &dev_attr_frames_read); | ||
541 | if (rc) goto err_framtot; | ||
542 | rc = device_create_file(&vdev->dev, &dev_attr_packets_dropped); | ||
543 | if (rc) goto err_framread; | ||
544 | rc = device_create_file(&vdev->dev, &dev_attr_decoding_errors); | ||
545 | if (rc) goto err_dropped; | ||
546 | |||
547 | return 0; | ||
548 | |||
549 | err_dropped: | ||
550 | device_remove_file(&vdev->dev, &dev_attr_packets_dropped); | ||
551 | err_framread: | ||
552 | device_remove_file(&vdev->dev, &dev_attr_frames_read); | ||
553 | err_framtot: | ||
554 | device_remove_file(&vdev->dev, &dev_attr_frames_total); | ||
555 | err_pal: | ||
556 | device_remove_file(&vdev->dev, &dev_attr_palette); | ||
557 | err_stream: | ||
558 | device_remove_file(&vdev->dev, &dev_attr_streaming); | ||
559 | err_inuse: | ||
560 | device_remove_file(&vdev->dev, &dev_attr_in_use); | ||
561 | err_model: | ||
562 | device_remove_file(&vdev->dev, &dev_attr_model); | ||
563 | err: | ||
564 | PDEBUG(0, "STV(e): Could not create sysfs files"); | ||
565 | return rc; | ||
566 | } | ||
567 | |||
568 | static void stv680_remove_sysfs_files(struct video_device *vdev) | ||
569 | { | ||
570 | device_remove_file(&vdev->dev, &dev_attr_model); | ||
571 | device_remove_file(&vdev->dev, &dev_attr_in_use); | ||
572 | device_remove_file(&vdev->dev, &dev_attr_streaming); | ||
573 | device_remove_file(&vdev->dev, &dev_attr_palette); | ||
574 | device_remove_file(&vdev->dev, &dev_attr_frames_total); | ||
575 | device_remove_file(&vdev->dev, &dev_attr_frames_read); | ||
576 | device_remove_file(&vdev->dev, &dev_attr_packets_dropped); | ||
577 | device_remove_file(&vdev->dev, &dev_attr_decoding_errors); | ||
578 | } | ||
579 | |||
580 | /******************************************************************** | ||
581 | * Camera control | ||
582 | *******************************************************************/ | ||
583 | |||
584 | static int stv680_get_pict (struct usb_stv *stv680, struct video_picture *p) | ||
585 | { | ||
586 | /* This sets values for v4l interface. max/min = 65535/0 */ | ||
587 | |||
588 | p->brightness = stv680->brightness; | ||
589 | p->whiteness = stv680->whiteness; /* greyscale */ | ||
590 | p->colour = stv680->colour; | ||
591 | p->contrast = stv680->contrast; | ||
592 | p->hue = stv680->hue; | ||
593 | p->palette = stv680->palette; | ||
594 | p->depth = stv680->depth; | ||
595 | return 0; | ||
596 | } | ||
597 | |||
598 | static int stv680_set_pict (struct usb_stv *stv680, struct video_picture *p) | ||
599 | { | ||
600 | /* See above stv680_get_pict */ | ||
601 | |||
602 | if (p->palette != STV_VIDEO_PALETTE) { | ||
603 | PDEBUG (2, "STV(e): Palette set error in _set_pic"); | ||
604 | return 1; | ||
605 | } | ||
606 | |||
607 | if (stv680->brightness != p->brightness) { | ||
608 | stv680->chgbright = 1; | ||
609 | stv680->brightness = p->brightness; | ||
610 | } | ||
611 | |||
612 | stv680->whiteness = p->whiteness; /* greyscale */ | ||
613 | stv680->colour = p->colour; | ||
614 | stv680->contrast = p->contrast; | ||
615 | stv680->hue = p->hue; | ||
616 | stv680->palette = p->palette; | ||
617 | stv680->depth = p->depth; | ||
618 | |||
619 | return 0; | ||
620 | } | ||
621 | |||
622 | static void stv680_video_irq (struct urb *urb) | ||
623 | { | ||
624 | struct usb_stv *stv680 = urb->context; | ||
625 | int length = urb->actual_length; | ||
626 | |||
627 | if (length < stv680->rawbufsize) | ||
628 | PDEBUG (2, "STV(i): Lost data in transfer: exp %li, got %i", stv680->rawbufsize, length); | ||
629 | |||
630 | /* ohoh... */ | ||
631 | if (!stv680->streaming) | ||
632 | return; | ||
633 | |||
634 | if (!stv680->udev) { | ||
635 | PDEBUG (0, "STV(e): device vapourished in video_irq"); | ||
636 | return; | ||
637 | } | ||
638 | |||
639 | /* 0 sized packets happen if we are to fast, but sometimes the camera | ||
640 | keeps sending them forever... | ||
641 | */ | ||
642 | if (length && !urb->status) { | ||
643 | stv680->nullpackets = 0; | ||
644 | switch (stv680->scratch[stv680->scratch_next].state) { | ||
645 | case BUFFER_READY: | ||
646 | case BUFFER_BUSY: | ||
647 | stv680->dropped++; | ||
648 | break; | ||
649 | |||
650 | case BUFFER_UNUSED: | ||
651 | memcpy (stv680->scratch[stv680->scratch_next].data, | ||
652 | (unsigned char *) urb->transfer_buffer, length); | ||
653 | stv680->scratch[stv680->scratch_next].state = BUFFER_READY; | ||
654 | stv680->scratch[stv680->scratch_next].length = length; | ||
655 | if (waitqueue_active (&stv680->wq)) { | ||
656 | wake_up_interruptible (&stv680->wq); | ||
657 | } | ||
658 | stv680->scratch_overflow = 0; | ||
659 | stv680->scratch_next++; | ||
660 | if (stv680->scratch_next >= STV680_NUMSCRATCH) | ||
661 | stv680->scratch_next = 0; | ||
662 | break; | ||
663 | } /* switch */ | ||
664 | } else { | ||
665 | stv680->nullpackets++; | ||
666 | if (stv680->nullpackets > STV680_MAX_NULLPACKETS) { | ||
667 | if (waitqueue_active (&stv680->wq)) { | ||
668 | wake_up_interruptible (&stv680->wq); | ||
669 | } | ||
670 | } | ||
671 | } /* if - else */ | ||
672 | |||
673 | /* Resubmit urb for new data */ | ||
674 | urb->status = 0; | ||
675 | urb->dev = stv680->udev; | ||
676 | if (usb_submit_urb (urb, GFP_ATOMIC)) | ||
677 | PDEBUG (0, "STV(e): urb burned down in video irq"); | ||
678 | return; | ||
679 | } /* _video_irq */ | ||
680 | |||
681 | static int stv680_start_stream (struct usb_stv *stv680) | ||
682 | { | ||
683 | struct urb *urb; | ||
684 | int err = 0, i; | ||
685 | |||
686 | stv680->streaming = 1; | ||
687 | |||
688 | /* Do some memory allocation */ | ||
689 | for (i = 0; i < STV680_NUMFRAMES; i++) { | ||
690 | stv680->frame[i].data = stv680->fbuf + i * stv680->maxframesize; | ||
691 | stv680->frame[i].curpix = 0; | ||
692 | } | ||
693 | /* packet size = 4096 */ | ||
694 | for (i = 0; i < STV680_NUMSBUF; i++) { | ||
695 | stv680->sbuf[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); | ||
696 | if (stv680->sbuf[i].data == NULL) { | ||
697 | PDEBUG (0, "STV(e): Could not kmalloc raw data buffer %i", i); | ||
698 | goto nomem_err; | ||
699 | } | ||
700 | } | ||
701 | |||
702 | stv680->scratch_next = 0; | ||
703 | stv680->scratch_use = 0; | ||
704 | stv680->scratch_overflow = 0; | ||
705 | for (i = 0; i < STV680_NUMSCRATCH; i++) { | ||
706 | stv680->scratch[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); | ||
707 | if (stv680->scratch[i].data == NULL) { | ||
708 | PDEBUG (0, "STV(e): Could not kmalloc raw scratch buffer %i", i); | ||
709 | goto nomem_err; | ||
710 | } | ||
711 | stv680->scratch[i].state = BUFFER_UNUSED; | ||
712 | } | ||
713 | |||
714 | for (i = 0; i < STV680_NUMSBUF; i++) { | ||
715 | urb = usb_alloc_urb (0, GFP_KERNEL); | ||
716 | if (!urb) | ||
717 | goto nomem_err; | ||
718 | |||
719 | /* sbuf is urb->transfer_buffer, later gets memcpyed to scratch */ | ||
720 | usb_fill_bulk_urb (urb, stv680->udev, | ||
721 | usb_rcvbulkpipe (stv680->udev, stv680->bulk_in_endpointAddr), | ||
722 | stv680->sbuf[i].data, stv680->rawbufsize, | ||
723 | stv680_video_irq, stv680); | ||
724 | stv680->urb[i] = urb; | ||
725 | err = usb_submit_urb (stv680->urb[i], GFP_KERNEL); | ||
726 | if (err) { | ||
727 | PDEBUG (0, "STV(e): urb burned down with err " | ||
728 | "%d in start stream %d", err, i); | ||
729 | goto nomem_err; | ||
730 | } | ||
731 | } /* i STV680_NUMSBUF */ | ||
732 | |||
733 | stv680->framecount = 0; | ||
734 | return 0; | ||
735 | |||
736 | nomem_err: | ||
737 | for (i = 0; i < STV680_NUMSBUF; i++) { | ||
738 | usb_kill_urb(stv680->urb[i]); | ||
739 | usb_free_urb(stv680->urb[i]); | ||
740 | stv680->urb[i] = NULL; | ||
741 | kfree(stv680->sbuf[i].data); | ||
742 | stv680->sbuf[i].data = NULL; | ||
743 | } | ||
744 | /* used in irq, free only as all URBs are dead */ | ||
745 | for (i = 0; i < STV680_NUMSCRATCH; i++) { | ||
746 | kfree(stv680->scratch[i].data); | ||
747 | stv680->scratch[i].data = NULL; | ||
748 | } | ||
749 | return -ENOMEM; | ||
750 | |||
751 | } | ||
752 | |||
753 | static int stv680_stop_stream (struct usb_stv *stv680) | ||
754 | { | ||
755 | int i; | ||
756 | |||
757 | if (!stv680->streaming || !stv680->udev) | ||
758 | return 1; | ||
759 | |||
760 | stv680->streaming = 0; | ||
761 | |||
762 | for (i = 0; i < STV680_NUMSBUF; i++) | ||
763 | if (stv680->urb[i]) { | ||
764 | usb_kill_urb (stv680->urb[i]); | ||
765 | usb_free_urb (stv680->urb[i]); | ||
766 | stv680->urb[i] = NULL; | ||
767 | kfree(stv680->sbuf[i].data); | ||
768 | } | ||
769 | for (i = 0; i < STV680_NUMSCRATCH; i++) { | ||
770 | kfree(stv680->scratch[i].data); | ||
771 | stv680->scratch[i].data = NULL; | ||
772 | } | ||
773 | |||
774 | return 0; | ||
775 | } | ||
776 | |||
777 | static int stv680_set_size (struct usb_stv *stv680, int width, int height) | ||
778 | { | ||
779 | int wasstreaming = stv680->streaming; | ||
780 | |||
781 | /* Check to see if we need to change */ | ||
782 | if ((stv680->vwidth == width) && (stv680->vheight == height)) | ||
783 | return 0; | ||
784 | |||
785 | PDEBUG (1, "STV(i): size request for %i x %i", width, height); | ||
786 | /* Check for a valid mode */ | ||
787 | if ((!width || !height) || ((width & 1) || (height & 1))) { | ||
788 | PDEBUG (1, "STV(e): set_size error: request: v.width = %i, v.height = %i actual: stv.width = %i, stv.height = %i", width, height, stv680->vwidth, stv680->vheight); | ||
789 | return 1; | ||
790 | } | ||
791 | |||
792 | if ((width < (stv680->maxwidth / 2)) || (height < (stv680->maxheight / 2))) { | ||
793 | width = stv680->maxwidth / 2; | ||
794 | height = stv680->maxheight / 2; | ||
795 | } else if ((width >= 158) && (width <= 166) && (stv680->QVGA == 1)) { | ||
796 | width = 160; | ||
797 | height = 120; | ||
798 | } else if ((width >= 172) && (width <= 180) && (stv680->CIF == 1)) { | ||
799 | width = 176; | ||
800 | height = 144; | ||
801 | } else if ((width >= 318) && (width <= 350) && (stv680->QVGA == 1)) { | ||
802 | width = 320; | ||
803 | height = 240; | ||
804 | } else if ((width >= 350) && (width <= 358) && (stv680->CIF == 1)) { | ||
805 | width = 352; | ||
806 | height = 288; | ||
807 | } else { | ||
808 | PDEBUG (1, "STV(e): request for non-supported size: request: v.width = %i, v.height = %i actual: stv.width = %i, stv.height = %i", width, height, stv680->vwidth, stv680->vheight); | ||
809 | return 1; | ||
810 | } | ||
811 | |||
812 | /* Stop a current stream and start it again at the new size */ | ||
813 | if (wasstreaming) | ||
814 | stv680_stop_stream (stv680); | ||
815 | stv680->vwidth = width; | ||
816 | stv680->vheight = height; | ||
817 | PDEBUG (1, "STV(i): size set to %i x %i", stv680->vwidth, stv680->vheight); | ||
818 | if (wasstreaming) | ||
819 | stv680_start_stream (stv680); | ||
820 | |||
821 | return 0; | ||
822 | } | ||
823 | |||
824 | /********************************************************************** | ||
825 | * Video Decoding | ||
826 | **********************************************************************/ | ||
827 | |||
828 | /******* routines from the pencam program; hey, they work! ********/ | ||
829 | |||
830 | /* | ||
831 | * STV0680 Vision Camera Chipset Driver | ||
832 | * Copyright (C) 2000 Adam Harrison <adam@antispin.org> | ||
833 | */ | ||
834 | |||
835 | #define RED 0 | ||
836 | #define GREEN 1 | ||
837 | #define BLUE 2 | ||
838 | #define AD(x, y, w) (((y)*(w)+(x))*3) | ||
839 | |||
840 | static void bayer_unshuffle (struct usb_stv *stv680, struct stv680_scratch *buffer) | ||
841 | { | ||
842 | int x, y, i; | ||
843 | int w = stv680->cwidth; | ||
844 | int vw = stv680->cwidth, vh = stv680->cheight; | ||
845 | unsigned int p = 0; | ||
846 | int colour = 0, bayer = 0; | ||
847 | unsigned char *raw = buffer->data; | ||
848 | struct stv680_frame *frame = &stv680->frame[stv680->curframe]; | ||
849 | unsigned char *output = frame->data; | ||
850 | unsigned char *temp = frame->data; | ||
851 | int offset = buffer->offset; | ||
852 | |||
853 | if (frame->curpix == 0) { | ||
854 | if (frame->grabstate == FRAME_READY) { | ||
855 | frame->grabstate = FRAME_GRABBING; | ||
856 | } | ||
857 | } | ||
858 | if (offset != frame->curpix) { /* Regard frame as lost :( */ | ||
859 | frame->curpix = 0; | ||
860 | stv680->error++; | ||
861 | return; | ||
862 | } | ||
863 | |||
864 | if ((stv680->vwidth == 320) || (stv680->vwidth == 160)) { | ||
865 | vw = 320; | ||
866 | vh = 240; | ||
867 | } | ||
868 | if ((stv680->vwidth == 352) || (stv680->vwidth == 176)) { | ||
869 | vw = 352; | ||
870 | vh = 288; | ||
871 | } | ||
872 | |||
873 | memset (output, 0, 3 * vw * vh); /* clear output matrix. */ | ||
874 | |||
875 | for (y = 0; y < vh; y++) { | ||
876 | for (x = 0; x < vw; x++) { | ||
877 | if (x & 1) | ||
878 | p = *(raw + y * w + (x >> 1)); | ||
879 | else | ||
880 | p = *(raw + y * w + (x >> 1) + (w >> 1)); | ||
881 | |||
882 | if (y & 1) | ||
883 | bayer = 2; | ||
884 | else | ||
885 | bayer = 0; | ||
886 | if (x & 1) | ||
887 | bayer++; | ||
888 | |||
889 | switch (bayer) { | ||
890 | case 0: | ||
891 | case 3: | ||
892 | colour = 1; | ||
893 | break; | ||
894 | case 1: | ||
895 | colour = 0; | ||
896 | break; | ||
897 | case 2: | ||
898 | colour = 2; | ||
899 | break; | ||
900 | } | ||
901 | i = (y * vw + x) * 3; | ||
902 | *(output + i + colour) = (unsigned char) p; | ||
903 | } /* for x */ | ||
904 | |||
905 | } /* for y */ | ||
906 | |||
907 | /****** gamma correction plus hardcoded white balance */ | ||
908 | /* Thanks to Alexander Schwartx <alexander.schwartx@gmx.net> for this code. | ||
909 | Correction values red[], green[], blue[], are generated by | ||
910 | (pow(i/256.0, GAMMA)*255.0)*white balanceRGB where GAMMA=0.55, 1<i<255. | ||
911 | White balance (RGB)= 1.0, 1.17, 1.48. Values are calculated as double float and | ||
912 | converted to unsigned char. Values are in stv680.h */ | ||
913 | |||
914 | for (y = 0; y < vh; y++) { | ||
915 | for (x = 0; x < vw; x++) { | ||
916 | i = (y * vw + x) * 3; | ||
917 | *(output + i) = red[*(output + i)]; | ||
918 | *(output + i + 1) = green[*(output + i + 1)]; | ||
919 | *(output + i + 2) = blue[*(output + i + 2)]; | ||
920 | } | ||
921 | } | ||
922 | |||
923 | /****** bayer demosaic ******/ | ||
924 | for (y = 1; y < (vh - 1); y++) { | ||
925 | for (x = 1; x < (vw - 1); x++) { /* work out pixel type */ | ||
926 | if (y & 1) | ||
927 | bayer = 0; | ||
928 | else | ||
929 | bayer = 2; | ||
930 | if (!(x & 1)) | ||
931 | bayer++; | ||
932 | |||
933 | switch (bayer) { | ||
934 | case 0: /* green. blue lr, red tb */ | ||
935 | *(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x - 1, y, vw) + BLUE) + (int) *(output + AD (x + 1, y, vw) + BLUE)) >> 1; | ||
936 | *(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x, y - 1, vw) + RED) + (int) *(output + AD (x, y + 1, vw) + RED)) >> 1; | ||
937 | break; | ||
938 | |||
939 | case 1: /* blue. green lrtb, red diagonals */ | ||
940 | *(output + AD (x, y, vw) + GREEN) = ((int) *(output + AD (x - 1, y, vw) + GREEN) + (int) *(output + AD (x + 1, y, vw) + GREEN) + (int) *(output + AD (x, y - 1, vw) + GREEN) + (int) *(output + AD (x, y + 1, vw) + GREEN)) >> 2; | ||
941 | *(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x - 1, y - 1, vw) + RED) + (int) *(output + AD (x - 1, y + 1, vw) + RED) + (int) *(output + AD (x + 1, y - 1, vw) + RED) + (int) *(output + AD (x + 1, y + 1, vw) + RED)) >> 2; | ||
942 | break; | ||
943 | |||
944 | case 2: /* red. green lrtb, blue diagonals */ | ||
945 | *(output + AD (x, y, vw) + GREEN) = ((int) *(output + AD (x - 1, y, vw) + GREEN) + (int) *(output + AD (x + 1, y, vw) + GREEN) + (int) *(output + AD (x, y - 1, vw) + GREEN) + (int) *(output + AD (x, y + 1, vw) + GREEN)) >> 2; | ||
946 | *(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x - 1, y - 1, vw) + BLUE) + (int) *(output + AD (x + 1, y - 1, vw) + BLUE) + (int) *(output + AD (x - 1, y + 1, vw) + BLUE) + (int) *(output + AD (x + 1, y + 1, vw) + BLUE)) >> 2; | ||
947 | break; | ||
948 | |||
949 | case 3: /* green. red lr, blue tb */ | ||
950 | *(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x - 1, y, vw) + RED) + (int) *(output + AD (x + 1, y, vw) + RED)) >> 1; | ||
951 | *(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x, y - 1, vw) + BLUE) + (int) *(output + AD (x, y + 1, vw) + BLUE)) >> 1; | ||
952 | break; | ||
953 | } /* switch */ | ||
954 | } /* for x */ | ||
955 | } /* for y - end demosaic */ | ||
956 | |||
957 | /* fix top and bottom row, left and right side */ | ||
958 | i = vw * 3; | ||
959 | memcpy (output, (output + i), i); | ||
960 | memcpy ((output + (vh * i)), (output + ((vh - 1) * i)), i); | ||
961 | for (y = 0; y < vh; y++) { | ||
962 | i = y * vw * 3; | ||
963 | memcpy ((output + i), (output + i + 3), 3); | ||
964 | memcpy ((output + i + (vw * 3)), (output + i + (vw - 1) * 3), 3); | ||
965 | } | ||
966 | |||
967 | /* process all raw data, then trim to size if necessary */ | ||
968 | if ((stv680->vwidth == 160) || (stv680->vwidth == 176)) { | ||
969 | i = 0; | ||
970 | for (y = 0; y < vh; y++) { | ||
971 | if (!(y & 1)) { | ||
972 | for (x = 0; x < vw; x++) { | ||
973 | p = (y * vw + x) * 3; | ||
974 | if (!(x & 1)) { | ||
975 | *(output + i) = *(output + p); | ||
976 | *(output + i + 1) = *(output + p + 1); | ||
977 | *(output + i + 2) = *(output + p + 2); | ||
978 | i += 3; | ||
979 | } | ||
980 | } /* for x */ | ||
981 | } | ||
982 | } /* for y */ | ||
983 | } | ||
984 | /* reset to proper width */ | ||
985 | if ((stv680->vwidth == 160)) { | ||
986 | vw = 160; | ||
987 | vh = 120; | ||
988 | } | ||
989 | if ((stv680->vwidth == 176)) { | ||
990 | vw = 176; | ||
991 | vh = 144; | ||
992 | } | ||
993 | |||
994 | /* output is RGB; some programs want BGR */ | ||
995 | /* swapRGB_on=0 -> program decides; swapRGB_on=1, always swap */ | ||
996 | /* swapRGB_on=-1, never swap */ | ||
997 | if (((swapRGB == 1) && (swapRGB_on != -1)) || (swapRGB_on == 1)) { | ||
998 | for (y = 0; y < vh; y++) { | ||
999 | for (x = 0; x < vw; x++) { | ||
1000 | i = (y * vw + x) * 3; | ||
1001 | *(temp) = *(output + i); | ||
1002 | *(output + i) = *(output + i + 2); | ||
1003 | *(output + i + 2) = *(temp); | ||
1004 | } | ||
1005 | } | ||
1006 | } | ||
1007 | /* brightness */ | ||
1008 | if (stv680->chgbright == 1) { | ||
1009 | if (stv680->brightness >= 32767) { | ||
1010 | p = (stv680->brightness - 32767) / 256; | ||
1011 | for (x = 0; x < (vw * vh * 3); x++) { | ||
1012 | if ((*(output + x) + (unsigned char) p) > 255) | ||
1013 | *(output + x) = 255; | ||
1014 | else | ||
1015 | *(output + x) += (unsigned char) p; | ||
1016 | } /* for */ | ||
1017 | } else { | ||
1018 | p = (32767 - stv680->brightness) / 256; | ||
1019 | for (x = 0; x < (vw * vh * 3); x++) { | ||
1020 | if ((unsigned char) p > *(output + x)) | ||
1021 | *(output + x) = 0; | ||
1022 | else | ||
1023 | *(output + x) -= (unsigned char) p; | ||
1024 | } /* for */ | ||
1025 | } /* else */ | ||
1026 | } | ||
1027 | /* if */ | ||
1028 | frame->curpix = 0; | ||
1029 | frame->curlinepix = 0; | ||
1030 | frame->grabstate = FRAME_DONE; | ||
1031 | stv680->framecount++; | ||
1032 | stv680->readcount++; | ||
1033 | if (stv680->frame[(stv680->curframe + 1) & (STV680_NUMFRAMES - 1)].grabstate == FRAME_READY) { | ||
1034 | stv680->curframe = (stv680->curframe + 1) & (STV680_NUMFRAMES - 1); | ||
1035 | } | ||
1036 | |||
1037 | } /* bayer_unshuffle */ | ||
1038 | |||
1039 | /******* end routines from the pencam program *********/ | ||
1040 | |||
1041 | static int stv680_newframe (struct usb_stv *stv680, int framenr) | ||
1042 | { | ||
1043 | int errors = 0; | ||
1044 | |||
1045 | while (stv680->streaming && (stv680->frame[framenr].grabstate == FRAME_READY || stv680->frame[framenr].grabstate == FRAME_GRABBING)) { | ||
1046 | if (!stv680->frame[framenr].curpix) { | ||
1047 | errors++; | ||
1048 | } | ||
1049 | wait_event_interruptible (stv680->wq, (stv680->scratch[stv680->scratch_use].state == BUFFER_READY)); | ||
1050 | |||
1051 | if (stv680->nullpackets > STV680_MAX_NULLPACKETS) { | ||
1052 | stv680->nullpackets = 0; | ||
1053 | PDEBUG (2, "STV(i): too many null length packets, restarting capture"); | ||
1054 | stv680_stop_stream (stv680); | ||
1055 | stv680_start_stream (stv680); | ||
1056 | } else { | ||
1057 | if (stv680->scratch[stv680->scratch_use].state != BUFFER_READY) { | ||
1058 | stv680->frame[framenr].grabstate = FRAME_ERROR; | ||
1059 | PDEBUG (2, "STV(e): FRAME_ERROR in _newframe"); | ||
1060 | return -EIO; | ||
1061 | } | ||
1062 | stv680->scratch[stv680->scratch_use].state = BUFFER_BUSY; | ||
1063 | |||
1064 | bayer_unshuffle (stv680, &stv680->scratch[stv680->scratch_use]); | ||
1065 | |||
1066 | stv680->scratch[stv680->scratch_use].state = BUFFER_UNUSED; | ||
1067 | stv680->scratch_use++; | ||
1068 | if (stv680->scratch_use >= STV680_NUMSCRATCH) | ||
1069 | stv680->scratch_use = 0; | ||
1070 | if (errors > STV680_MAX_ERRORS) { | ||
1071 | errors = 0; | ||
1072 | PDEBUG (2, "STV(i): too many errors, restarting capture"); | ||
1073 | stv680_stop_stream (stv680); | ||
1074 | stv680_start_stream (stv680); | ||
1075 | } | ||
1076 | } /* else */ | ||
1077 | } /* while */ | ||
1078 | return 0; | ||
1079 | } | ||
1080 | |||
1081 | /********************************************************************* | ||
1082 | * Video4Linux | ||
1083 | *********************************************************************/ | ||
1084 | |||
1085 | static int stv_open(struct file *file) | ||
1086 | { | ||
1087 | struct video_device *dev = video_devdata(file); | ||
1088 | struct usb_stv *stv680 = video_get_drvdata(dev); | ||
1089 | int err = 0; | ||
1090 | |||
1091 | /* we are called with the BKL held */ | ||
1092 | lock_kernel(); | ||
1093 | stv680->user = 1; | ||
1094 | err = stv_init (stv680); /* main initialization routine for camera */ | ||
1095 | |||
1096 | if (err >= 0) { | ||
1097 | stv680->fbuf = rvmalloc (stv680->maxframesize * STV680_NUMFRAMES); | ||
1098 | if (!stv680->fbuf) { | ||
1099 | PDEBUG (0, "STV(e): Could not rvmalloc frame bufer"); | ||
1100 | err = -ENOMEM; | ||
1101 | } | ||
1102 | file->private_data = dev; | ||
1103 | } | ||
1104 | if (err) | ||
1105 | stv680->user = 0; | ||
1106 | unlock_kernel(); | ||
1107 | |||
1108 | return err; | ||
1109 | } | ||
1110 | |||
1111 | static int stv_close(struct file *file) | ||
1112 | { | ||
1113 | struct video_device *dev = file->private_data; | ||
1114 | struct usb_stv *stv680 = video_get_drvdata(dev); | ||
1115 | int i; | ||
1116 | |||
1117 | for (i = 0; i < STV680_NUMFRAMES; i++) | ||
1118 | stv680->frame[i].grabstate = FRAME_UNUSED; | ||
1119 | if (stv680->streaming) | ||
1120 | stv680_stop_stream (stv680); | ||
1121 | |||
1122 | if ((i = stv_stop_video (stv680)) < 0) | ||
1123 | PDEBUG (1, "STV(e): stop_video failed in stv_close"); | ||
1124 | |||
1125 | rvfree (stv680->fbuf, stv680->maxframesize * STV680_NUMFRAMES); | ||
1126 | stv680->user = 0; | ||
1127 | |||
1128 | if (stv680->removed) { | ||
1129 | kfree(stv680); | ||
1130 | stv680 = NULL; | ||
1131 | PDEBUG (0, "STV(i): device unregistered"); | ||
1132 | } | ||
1133 | file->private_data = NULL; | ||
1134 | return 0; | ||
1135 | } | ||
1136 | |||
1137 | static long stv680_do_ioctl(struct file *file, unsigned int cmd, void *arg) | ||
1138 | { | ||
1139 | struct video_device *vdev = file->private_data; | ||
1140 | struct usb_stv *stv680 = video_get_drvdata(vdev); | ||
1141 | |||
1142 | if (!stv680->udev) | ||
1143 | return -EIO; | ||
1144 | |||
1145 | switch (cmd) { | ||
1146 | case VIDIOCGCAP:{ | ||
1147 | struct video_capability *b = arg; | ||
1148 | |||
1149 | strcpy (b->name, stv680->camera_name); | ||
1150 | b->type = VID_TYPE_CAPTURE; | ||
1151 | b->channels = 1; | ||
1152 | b->audios = 0; | ||
1153 | b->maxwidth = stv680->maxwidth; | ||
1154 | b->maxheight = stv680->maxheight; | ||
1155 | b->minwidth = stv680->maxwidth / 2; | ||
1156 | b->minheight = stv680->maxheight / 2; | ||
1157 | return 0; | ||
1158 | } | ||
1159 | case VIDIOCGCHAN:{ | ||
1160 | struct video_channel *v = arg; | ||
1161 | |||
1162 | if (v->channel != 0) | ||
1163 | return -EINVAL; | ||
1164 | v->flags = 0; | ||
1165 | v->tuners = 0; | ||
1166 | v->type = VIDEO_TYPE_CAMERA; | ||
1167 | strcpy (v->name, "STV Camera"); | ||
1168 | return 0; | ||
1169 | } | ||
1170 | case VIDIOCSCHAN:{ | ||
1171 | struct video_channel *v = arg; | ||
1172 | if (v->channel != 0) | ||
1173 | return -EINVAL; | ||
1174 | return 0; | ||
1175 | } | ||
1176 | case VIDIOCGPICT:{ | ||
1177 | struct video_picture *p = arg; | ||
1178 | |||
1179 | stv680_get_pict (stv680, p); | ||
1180 | return 0; | ||
1181 | } | ||
1182 | case VIDIOCSPICT:{ | ||
1183 | struct video_picture *p = arg; | ||
1184 | |||
1185 | if (stv680_set_pict (stv680, p)) | ||
1186 | return -EINVAL; | ||
1187 | return 0; | ||
1188 | } | ||
1189 | case VIDIOCSWIN:{ | ||
1190 | struct video_window *vw = arg; | ||
1191 | |||
1192 | if (vw->flags) | ||
1193 | return -EINVAL; | ||
1194 | if (vw->clipcount) | ||
1195 | return -EINVAL; | ||
1196 | if (vw->width != stv680->vwidth) { | ||
1197 | if (stv680_set_size (stv680, vw->width, vw->height)) { | ||
1198 | PDEBUG (2, "STV(e): failed (from user) set size in VIDIOCSWIN"); | ||
1199 | return -EINVAL; | ||
1200 | } | ||
1201 | } | ||
1202 | return 0; | ||
1203 | } | ||
1204 | case VIDIOCGWIN:{ | ||
1205 | struct video_window *vw = arg; | ||
1206 | |||
1207 | vw->x = 0; /* FIXME */ | ||
1208 | vw->y = 0; | ||
1209 | vw->chromakey = 0; | ||
1210 | vw->flags = 0; | ||
1211 | vw->clipcount = 0; | ||
1212 | vw->width = stv680->vwidth; | ||
1213 | vw->height = stv680->vheight; | ||
1214 | return 0; | ||
1215 | } | ||
1216 | case VIDIOCGMBUF:{ | ||
1217 | struct video_mbuf *vm = arg; | ||
1218 | int i; | ||
1219 | |||
1220 | memset (vm, 0, sizeof (*vm)); | ||
1221 | vm->size = STV680_NUMFRAMES * stv680->maxframesize; | ||
1222 | vm->frames = STV680_NUMFRAMES; | ||
1223 | for (i = 0; i < STV680_NUMFRAMES; i++) | ||
1224 | vm->offsets[i] = stv680->maxframesize * i; | ||
1225 | return 0; | ||
1226 | } | ||
1227 | case VIDIOCMCAPTURE:{ | ||
1228 | struct video_mmap *vm = arg; | ||
1229 | |||
1230 | if (vm->format != STV_VIDEO_PALETTE) { | ||
1231 | PDEBUG (2, "STV(i): VIDIOCMCAPTURE vm.format (%i) != VIDEO_PALETTE (%i)", | ||
1232 | vm->format, STV_VIDEO_PALETTE); | ||
1233 | if ((vm->format == 3) && (swapRGB_on == 0)) { | ||
1234 | PDEBUG (2, "STV(i): VIDIOCMCAPTURE swapRGB is (auto) ON"); | ||
1235 | /* this may fix those apps (e.g., xawtv) that want BGR */ | ||
1236 | swapRGB = 1; | ||
1237 | } | ||
1238 | return -EINVAL; | ||
1239 | } | ||
1240 | if (vm->frame >= STV680_NUMFRAMES) { | ||
1241 | PDEBUG (2, "STV(e): VIDIOCMCAPTURE vm.frame > NUMFRAMES"); | ||
1242 | return -EINVAL; | ||
1243 | } | ||
1244 | if ((stv680->frame[vm->frame].grabstate == FRAME_ERROR) | ||
1245 | || (stv680->frame[vm->frame].grabstate == FRAME_GRABBING)) { | ||
1246 | PDEBUG (2, "STV(e): VIDIOCMCAPTURE grabstate (%i) error", | ||
1247 | stv680->frame[vm->frame].grabstate); | ||
1248 | return -EBUSY; | ||
1249 | } | ||
1250 | /* Is this according to the v4l spec??? */ | ||
1251 | if (stv680->vwidth != vm->width) { | ||
1252 | if (stv680_set_size (stv680, vm->width, vm->height)) { | ||
1253 | PDEBUG (2, "STV(e): VIDIOCMCAPTURE set_size failed"); | ||
1254 | return -EINVAL; | ||
1255 | } | ||
1256 | } | ||
1257 | stv680->frame[vm->frame].grabstate = FRAME_READY; | ||
1258 | |||
1259 | if (!stv680->streaming) | ||
1260 | stv680_start_stream (stv680); | ||
1261 | |||
1262 | return 0; | ||
1263 | } | ||
1264 | case VIDIOCSYNC:{ | ||
1265 | int *frame = arg; | ||
1266 | int ret = 0; | ||
1267 | |||
1268 | if (*frame < 0 || *frame >= STV680_NUMFRAMES) { | ||
1269 | PDEBUG (2, "STV(e): Bad frame # in VIDIOCSYNC"); | ||
1270 | return -EINVAL; | ||
1271 | } | ||
1272 | ret = stv680_newframe (stv680, *frame); | ||
1273 | stv680->frame[*frame].grabstate = FRAME_UNUSED; | ||
1274 | return ret; | ||
1275 | } | ||
1276 | case VIDIOCGFBUF:{ | ||
1277 | struct video_buffer *vb = arg; | ||
1278 | |||
1279 | memset (vb, 0, sizeof (*vb)); | ||
1280 | return 0; | ||
1281 | } | ||
1282 | case VIDIOCKEY: | ||
1283 | return 0; | ||
1284 | case VIDIOCCAPTURE: | ||
1285 | { | ||
1286 | PDEBUG (2, "STV(e): VIDIOCCAPTURE failed"); | ||
1287 | return -EINVAL; | ||
1288 | } | ||
1289 | case VIDIOCSFBUF: | ||
1290 | case VIDIOCGTUNER: | ||
1291 | case VIDIOCSTUNER: | ||
1292 | case VIDIOCGFREQ: | ||
1293 | case VIDIOCSFREQ: | ||
1294 | case VIDIOCGAUDIO: | ||
1295 | case VIDIOCSAUDIO: | ||
1296 | return -EINVAL; | ||
1297 | default: | ||
1298 | return -ENOIOCTLCMD; | ||
1299 | } /* end switch */ | ||
1300 | |||
1301 | return 0; | ||
1302 | } | ||
1303 | |||
1304 | static long stv680_ioctl(struct file *file, | ||
1305 | unsigned int cmd, unsigned long arg) | ||
1306 | { | ||
1307 | return video_usercopy(file, cmd, arg, stv680_do_ioctl); | ||
1308 | } | ||
1309 | |||
1310 | static int stv680_mmap (struct file *file, struct vm_area_struct *vma) | ||
1311 | { | ||
1312 | struct video_device *dev = file->private_data; | ||
1313 | struct usb_stv *stv680 = video_get_drvdata(dev); | ||
1314 | unsigned long start = vma->vm_start; | ||
1315 | unsigned long size = vma->vm_end-vma->vm_start; | ||
1316 | unsigned long page, pos; | ||
1317 | |||
1318 | mutex_lock(&stv680->lock); | ||
1319 | |||
1320 | if (stv680->udev == NULL) { | ||
1321 | mutex_unlock(&stv680->lock); | ||
1322 | return -EIO; | ||
1323 | } | ||
1324 | if (size > (((STV680_NUMFRAMES * stv680->maxframesize) + PAGE_SIZE - 1) | ||
1325 | & ~(PAGE_SIZE - 1))) { | ||
1326 | mutex_unlock(&stv680->lock); | ||
1327 | return -EINVAL; | ||
1328 | } | ||
1329 | pos = (unsigned long) stv680->fbuf; | ||
1330 | while (size > 0) { | ||
1331 | page = vmalloc_to_pfn((void *)pos); | ||
1332 | if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { | ||
1333 | mutex_unlock(&stv680->lock); | ||
1334 | return -EAGAIN; | ||
1335 | } | ||
1336 | start += PAGE_SIZE; | ||
1337 | pos += PAGE_SIZE; | ||
1338 | if (size > PAGE_SIZE) | ||
1339 | size -= PAGE_SIZE; | ||
1340 | else | ||
1341 | size = 0; | ||
1342 | } | ||
1343 | mutex_unlock(&stv680->lock); | ||
1344 | |||
1345 | return 0; | ||
1346 | } | ||
1347 | |||
1348 | static ssize_t stv680_read (struct file *file, char __user *buf, | ||
1349 | size_t count, loff_t *ppos) | ||
1350 | { | ||
1351 | struct video_device *dev = file->private_data; | ||
1352 | unsigned long int realcount = count; | ||
1353 | int ret = 0; | ||
1354 | struct usb_stv *stv680 = video_get_drvdata(dev); | ||
1355 | unsigned long int i; | ||
1356 | |||
1357 | if (STV680_NUMFRAMES != 2) { | ||
1358 | PDEBUG (0, "STV(e): STV680_NUMFRAMES needs to be 2!"); | ||
1359 | return -1; | ||
1360 | } | ||
1361 | if (stv680->udev == NULL) | ||
1362 | return -EIO; | ||
1363 | if (realcount > (stv680->vwidth * stv680->vheight * 3)) | ||
1364 | realcount = stv680->vwidth * stv680->vheight * 3; | ||
1365 | |||
1366 | /* Shouldn't happen: */ | ||
1367 | if (stv680->frame[0].grabstate == FRAME_GRABBING) { | ||
1368 | PDEBUG (2, "STV(e): FRAME_GRABBING in stv680_read"); | ||
1369 | return -EBUSY; | ||
1370 | } | ||
1371 | stv680->frame[0].grabstate = FRAME_READY; | ||
1372 | stv680->frame[1].grabstate = FRAME_UNUSED; | ||
1373 | stv680->curframe = 0; | ||
1374 | |||
1375 | if (!stv680->streaming) | ||
1376 | stv680_start_stream (stv680); | ||
1377 | |||
1378 | if (!stv680->streaming) { | ||
1379 | ret = stv680_newframe (stv680, 0); /* ret should = 0 */ | ||
1380 | } | ||
1381 | |||
1382 | ret = stv680_newframe (stv680, 0); | ||
1383 | |||
1384 | if (!ret) { | ||
1385 | if ((i = copy_to_user (buf, stv680->frame[0].data, realcount)) != 0) { | ||
1386 | PDEBUG (2, "STV(e): copy_to_user frame 0 failed, ret count = %li", i); | ||
1387 | return -EFAULT; | ||
1388 | } | ||
1389 | } else { | ||
1390 | realcount = ret; | ||
1391 | } | ||
1392 | stv680->frame[0].grabstate = FRAME_UNUSED; | ||
1393 | return realcount; | ||
1394 | } /* stv680_read */ | ||
1395 | |||
1396 | static const struct v4l2_file_operations stv680_fops = { | ||
1397 | .owner = THIS_MODULE, | ||
1398 | .open = stv_open, | ||
1399 | .release = stv_close, | ||
1400 | .read = stv680_read, | ||
1401 | .mmap = stv680_mmap, | ||
1402 | .ioctl = stv680_ioctl, | ||
1403 | }; | ||
1404 | static struct video_device stv680_template = { | ||
1405 | .name = "STV0680 USB camera", | ||
1406 | .fops = &stv680_fops, | ||
1407 | .release = video_device_release, | ||
1408 | }; | ||
1409 | |||
1410 | static int stv680_probe (struct usb_interface *intf, const struct usb_device_id *id) | ||
1411 | { | ||
1412 | struct usb_device *dev = interface_to_usbdev(intf); | ||
1413 | struct usb_host_interface *interface; | ||
1414 | struct usb_stv *stv680 = NULL; | ||
1415 | char *camera_name = NULL; | ||
1416 | int retval = 0; | ||
1417 | |||
1418 | /* We don't handle multi-config cameras */ | ||
1419 | if (dev->descriptor.bNumConfigurations != 1) { | ||
1420 | PDEBUG (0, "STV(e): Number of Configurations != 1"); | ||
1421 | return -ENODEV; | ||
1422 | } | ||
1423 | |||
1424 | interface = &intf->altsetting[0]; | ||
1425 | /* Is it a STV680? */ | ||
1426 | if ((le16_to_cpu(dev->descriptor.idVendor) == USB_PENCAM_VENDOR_ID) && | ||
1427 | (le16_to_cpu(dev->descriptor.idProduct) == USB_PENCAM_PRODUCT_ID)) { | ||
1428 | camera_name = "STV0680"; | ||
1429 | PDEBUG (0, "STV(i): STV0680 camera found."); | ||
1430 | } else if ((le16_to_cpu(dev->descriptor.idVendor) == USB_CREATIVEGOMINI_VENDOR_ID) && | ||
1431 | (le16_to_cpu(dev->descriptor.idProduct) == USB_CREATIVEGOMINI_PRODUCT_ID)) { | ||
1432 | camera_name = "Creative WebCam Go Mini"; | ||
1433 | PDEBUG (0, "STV(i): Creative WebCam Go Mini found."); | ||
1434 | } else { | ||
1435 | PDEBUG (0, "STV(e): Vendor/Product ID do not match STV0680 or Creative WebCam Go Mini values."); | ||
1436 | PDEBUG (0, "STV(e): Check that the STV0680 or Creative WebCam Go Mini camera is connected to the computer."); | ||
1437 | retval = -ENODEV; | ||
1438 | goto error; | ||
1439 | } | ||
1440 | /* We found one */ | ||
1441 | if ((stv680 = kzalloc (sizeof (*stv680), GFP_KERNEL)) == NULL) { | ||
1442 | PDEBUG (0, "STV(e): couldn't kmalloc stv680 struct."); | ||
1443 | retval = -ENOMEM; | ||
1444 | goto error; | ||
1445 | } | ||
1446 | |||
1447 | stv680->udev = dev; | ||
1448 | stv680->camera_name = camera_name; | ||
1449 | |||
1450 | stv680->vdev = video_device_alloc(); | ||
1451 | if (!stv680->vdev) { | ||
1452 | retval = -ENOMEM; | ||
1453 | goto error; | ||
1454 | } | ||
1455 | memcpy(stv680->vdev, &stv680_template, sizeof(stv680_template)); | ||
1456 | stv680->vdev->parent = &intf->dev; | ||
1457 | video_set_drvdata(stv680->vdev, stv680); | ||
1458 | |||
1459 | memcpy (stv680->vdev->name, stv680->camera_name, strlen (stv680->camera_name)); | ||
1460 | init_waitqueue_head (&stv680->wq); | ||
1461 | mutex_init (&stv680->lock); | ||
1462 | wmb (); | ||
1463 | |||
1464 | if (video_register_device(stv680->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { | ||
1465 | PDEBUG (0, "STV(e): video_register_device failed"); | ||
1466 | retval = -EIO; | ||
1467 | goto error_vdev; | ||
1468 | } | ||
1469 | PDEBUG(0, "STV(i): registered new video device: %s", | ||
1470 | video_device_node_name(stv680->vdev)); | ||
1471 | |||
1472 | usb_set_intfdata (intf, stv680); | ||
1473 | retval = stv680_create_sysfs_files(stv680->vdev); | ||
1474 | if (retval) | ||
1475 | goto error_unreg; | ||
1476 | return 0; | ||
1477 | |||
1478 | error_unreg: | ||
1479 | video_unregister_device(stv680->vdev); | ||
1480 | error_vdev: | ||
1481 | video_device_release(stv680->vdev); | ||
1482 | error: | ||
1483 | kfree(stv680); | ||
1484 | return retval; | ||
1485 | } | ||
1486 | |||
1487 | static inline void usb_stv680_remove_disconnected (struct usb_stv *stv680) | ||
1488 | { | ||
1489 | int i; | ||
1490 | |||
1491 | stv680->udev = NULL; | ||
1492 | stv680->frame[0].grabstate = FRAME_ERROR; | ||
1493 | stv680->frame[1].grabstate = FRAME_ERROR; | ||
1494 | stv680->streaming = 0; | ||
1495 | |||
1496 | wake_up_interruptible (&stv680->wq); | ||
1497 | |||
1498 | for (i = 0; i < STV680_NUMSBUF; i++) | ||
1499 | if (stv680->urb[i]) { | ||
1500 | usb_kill_urb (stv680->urb[i]); | ||
1501 | usb_free_urb (stv680->urb[i]); | ||
1502 | stv680->urb[i] = NULL; | ||
1503 | kfree(stv680->sbuf[i].data); | ||
1504 | } | ||
1505 | for (i = 0; i < STV680_NUMSCRATCH; i++) | ||
1506 | kfree(stv680->scratch[i].data); | ||
1507 | PDEBUG (0, "STV(i): %s disconnected", stv680->camera_name); | ||
1508 | |||
1509 | /* Free the memory */ | ||
1510 | kfree(stv680); | ||
1511 | } | ||
1512 | |||
1513 | static void stv680_disconnect (struct usb_interface *intf) | ||
1514 | { | ||
1515 | struct usb_stv *stv680 = usb_get_intfdata (intf); | ||
1516 | |||
1517 | usb_set_intfdata (intf, NULL); | ||
1518 | |||
1519 | if (stv680) { | ||
1520 | /* We don't want people trying to open up the device */ | ||
1521 | if (stv680->vdev) { | ||
1522 | stv680_remove_sysfs_files(stv680->vdev); | ||
1523 | video_unregister_device(stv680->vdev); | ||
1524 | stv680->vdev = NULL; | ||
1525 | } | ||
1526 | if (!stv680->user) { | ||
1527 | usb_stv680_remove_disconnected (stv680); | ||
1528 | } else { | ||
1529 | stv680->removed = 1; | ||
1530 | } | ||
1531 | } | ||
1532 | } | ||
1533 | |||
1534 | static struct usb_driver stv680_driver = { | ||
1535 | .name = "stv680", | ||
1536 | .probe = stv680_probe, | ||
1537 | .disconnect = stv680_disconnect, | ||
1538 | .id_table = device_table | ||
1539 | }; | ||
1540 | |||
1541 | /******************************************************************** | ||
1542 | * Module routines | ||
1543 | ********************************************************************/ | ||
1544 | |||
1545 | static int __init usb_stv680_init (void) | ||
1546 | { | ||
1547 | if (usb_register (&stv680_driver) < 0) { | ||
1548 | PDEBUG (0, "STV(e): Could not setup STV0680 driver"); | ||
1549 | return -1; | ||
1550 | } | ||
1551 | PDEBUG (0, "STV(i): usb camera driver version %s registering", DRIVER_VERSION); | ||
1552 | |||
1553 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" | ||
1554 | DRIVER_DESC "\n"); | ||
1555 | return 0; | ||
1556 | } | ||
1557 | |||
1558 | static void __exit usb_stv680_exit (void) | ||
1559 | { | ||
1560 | usb_deregister (&stv680_driver); | ||
1561 | PDEBUG (0, "STV(i): driver deregistered"); | ||
1562 | } | ||
1563 | |||
1564 | module_init (usb_stv680_init); | ||
1565 | module_exit (usb_stv680_exit); | ||
diff --git a/drivers/media/video/stv680.h b/drivers/media/video/stv680.h deleted file mode 100644 index a08f1b08a4b0..000000000000 --- a/drivers/media/video/stv680.h +++ /dev/null | |||
@@ -1,227 +0,0 @@ | |||
1 | /**************************************************************************** | ||
2 | * | ||
3 | * Filename: stv680.h | ||
4 | * | ||
5 | * Description: | ||
6 | * This is a USB driver for STV0680 based usb video cameras. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | * | ||
22 | ****************************************************************************/ | ||
23 | |||
24 | /* size of usb transfers */ | ||
25 | #define STV680_PACKETSIZE 4096 | ||
26 | |||
27 | /* number of queued bulk transfers to use, may have problems if > 1 */ | ||
28 | #define STV680_NUMSBUF 1 | ||
29 | |||
30 | /* number of frames supported by the v4l part */ | ||
31 | #define STV680_NUMFRAMES 2 | ||
32 | |||
33 | /* scratch buffers for passing data to the decoders: 2 or 4 are good */ | ||
34 | #define STV680_NUMSCRATCH 2 | ||
35 | |||
36 | /* number of nul sized packets to receive before kicking the camera */ | ||
37 | #define STV680_MAX_NULLPACKETS 200 | ||
38 | |||
39 | /* number of decoding errors before kicking the camera */ | ||
40 | #define STV680_MAX_ERRORS 100 | ||
41 | |||
42 | #define USB_PENCAM_VENDOR_ID 0x0553 | ||
43 | #define USB_PENCAM_PRODUCT_ID 0x0202 | ||
44 | |||
45 | #define USB_CREATIVEGOMINI_VENDOR_ID 0x041e | ||
46 | #define USB_CREATIVEGOMINI_PRODUCT_ID 0x4007 | ||
47 | |||
48 | #define PENCAM_TIMEOUT 1000 | ||
49 | /* fmt 4 */ | ||
50 | #define STV_VIDEO_PALETTE VIDEO_PALETTE_RGB24 | ||
51 | |||
52 | static struct usb_device_id device_table[] = { | ||
53 | {USB_DEVICE (USB_PENCAM_VENDOR_ID, USB_PENCAM_PRODUCT_ID)}, | ||
54 | {USB_DEVICE (USB_CREATIVEGOMINI_VENDOR_ID, USB_CREATIVEGOMINI_PRODUCT_ID)}, | ||
55 | {} | ||
56 | }; | ||
57 | MODULE_DEVICE_TABLE (usb, device_table); | ||
58 | |||
59 | struct stv680_sbuf { | ||
60 | unsigned char *data; | ||
61 | }; | ||
62 | |||
63 | enum { | ||
64 | FRAME_UNUSED, /* Unused (no MCAPTURE) */ | ||
65 | FRAME_READY, /* Ready to start grabbing */ | ||
66 | FRAME_GRABBING, /* In the process of being grabbed into */ | ||
67 | FRAME_DONE, /* Finished grabbing, but not been synced yet */ | ||
68 | FRAME_ERROR, /* Something bad happened while processing */ | ||
69 | }; | ||
70 | |||
71 | enum { | ||
72 | BUFFER_UNUSED, | ||
73 | BUFFER_READY, | ||
74 | BUFFER_BUSY, | ||
75 | BUFFER_DONE, | ||
76 | }; | ||
77 | |||
78 | /* raw camera data <- sbuf (urb transfer buf) */ | ||
79 | struct stv680_scratch { | ||
80 | unsigned char *data; | ||
81 | volatile int state; | ||
82 | int offset; | ||
83 | int length; | ||
84 | }; | ||
85 | |||
86 | /* processed data for display ends up here, after bayer */ | ||
87 | struct stv680_frame { | ||
88 | unsigned char *data; /* Frame buffer */ | ||
89 | volatile int grabstate; /* State of grabbing */ | ||
90 | unsigned char *curline; | ||
91 | int curlinepix; | ||
92 | int curpix; | ||
93 | }; | ||
94 | |||
95 | /* this is almost the video structure uvd_t, with extra parameters for stv */ | ||
96 | struct usb_stv { | ||
97 | struct video_device *vdev; | ||
98 | |||
99 | struct usb_device *udev; | ||
100 | |||
101 | unsigned char bulk_in_endpointAddr; /* __u8 the address of the bulk in endpoint */ | ||
102 | char *camera_name; | ||
103 | |||
104 | unsigned int VideoMode; /* 0x0100 = VGA, 0x0000 = CIF, 0x0300 = QVGA */ | ||
105 | int SupportedModes; | ||
106 | int CIF; | ||
107 | int VGA; | ||
108 | int QVGA; | ||
109 | int cwidth; /* camera width */ | ||
110 | int cheight; /* camera height */ | ||
111 | int maxwidth; /* max video width */ | ||
112 | int maxheight; /* max video height */ | ||
113 | int vwidth; /* current width for video window */ | ||
114 | int vheight; /* current height for video window */ | ||
115 | unsigned long int rawbufsize; | ||
116 | unsigned long int maxframesize; /* rawbufsize * 3 for RGB */ | ||
117 | |||
118 | int origGain; | ||
119 | int origMode; /* original camera mode */ | ||
120 | |||
121 | struct mutex lock; /* to lock the structure */ | ||
122 | int user; /* user count for exclusive use */ | ||
123 | int removed; /* device disconnected */ | ||
124 | int streaming; /* Are we streaming video? */ | ||
125 | char *fbuf; /* Videodev buffer area */ | ||
126 | struct urb *urb[STV680_NUMSBUF]; /* # of queued bulk transfers */ | ||
127 | int curframe; /* Current receiving frame */ | ||
128 | struct stv680_frame frame[STV680_NUMFRAMES]; /* # frames supported by v4l part */ | ||
129 | int readcount; | ||
130 | int framecount; | ||
131 | int error; | ||
132 | int dropped; | ||
133 | int scratch_next; | ||
134 | int scratch_use; | ||
135 | int scratch_overflow; | ||
136 | struct stv680_scratch scratch[STV680_NUMSCRATCH]; /* for decoders */ | ||
137 | struct stv680_sbuf sbuf[STV680_NUMSBUF]; | ||
138 | |||
139 | unsigned int brightness; | ||
140 | unsigned int chgbright; | ||
141 | unsigned int whiteness; | ||
142 | unsigned int colour; | ||
143 | unsigned int contrast; | ||
144 | unsigned int hue; | ||
145 | unsigned int palette; | ||
146 | unsigned int depth; /* rgb24 in bits */ | ||
147 | |||
148 | wait_queue_head_t wq; /* Processes waiting */ | ||
149 | |||
150 | int nullpackets; | ||
151 | }; | ||
152 | |||
153 | |||
154 | static const unsigned char red[256] = { | ||
155 | 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, | ||
156 | 18, 18, 18, 18, 18, 18, 18, 25, 30, 35, 38, 42, | ||
157 | 44, 47, 50, 53, 54, 57, 59, 61, 63, 65, 67, 69, | ||
158 | 71, 71, 73, 75, 77, 78, 80, 81, 82, 84, 85, 87, | ||
159 | 88, 89, 90, 91, 93, 94, 95, 97, 98, 98, 99, 101, | ||
160 | 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, | ||
161 | 114, 115, 116, 116, 117, 118, 119, 120, 121, 122, 123, 124, | ||
162 | 125, 125, 126, 127, 128, 129, 129, 130, 131, 132, 133, 134, | ||
163 | 134, 135, 135, 136, 137, 138, 139, 140, 140, 141, 142, 143, | ||
164 | 143, 143, 144, 145, 146, 147, 147, 148, 149, 150, 150, 151, | ||
165 | 152, 152, 152, 153, 154, 154, 155, 156, 157, 157, 158, 159, | ||
166 | 159, 160, 161, 161, 161, 162, 163, 163, 164, 165, 165, 166, | ||
167 | 167, 167, 168, 168, 169, 170, 170, 170, 171, 171, 172, 173, | ||
168 | 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 179, 179, | ||
169 | 180, 180, 181, 181, 182, 183, 183, 184, 184, 185, 185, 186, | ||
170 | 187, 187, 188, 188, 188, 188, 189, 190, 190, 191, 191, 192, | ||
171 | 192, 193, 193, 194, 195, 195, 196, 196, 197, 197, 197, 197, | ||
172 | 198, 198, 199, 199, 200, 201, 201, 202, 202, 203, 203, 204, | ||
173 | 204, 205, 205, 206, 206, 206, 206, 207, 207, 208, 208, 209, | ||
174 | 209, 210, 210, 211, 211, 212, 212, 213, 213, 214, 214, 215, | ||
175 | 215, 215, 215, 216, 216, 217, 217, 218, 218, 218, 219, 219, | ||
176 | 220, 220, 221, 221 | ||
177 | }; | ||
178 | |||
179 | static const unsigned char green[256] = { | ||
180 | 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, | ||
181 | 21, 21, 21, 21, 21, 21, 21, 28, 34, 39, 43, 47, | ||
182 | 50, 53, 56, 59, 61, 64, 66, 68, 71, 73, 75, 77, | ||
183 | 79, 80, 82, 84, 86, 87, 89, 91, 92, 94, 95, 97, | ||
184 | 98, 100, 101, 102, 104, 105, 106, 108, 109, 110, 111, 113, | ||
185 | 114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126, | ||
186 | 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, | ||
187 | 139, 140, 141, 142, 143, 144, 144, 145, 146, 147, 148, 149, | ||
188 | 150, 151, 151, 152, 153, 154, 155, 156, 156, 157, 158, 159, | ||
189 | 160, 160, 161, 162, 163, 164, 164, 165, 166, 167, 167, 168, | ||
190 | 169, 170, 170, 171, 172, 172, 173, 174, 175, 175, 176, 177, | ||
191 | 177, 178, 179, 179, 180, 181, 182, 182, 183, 184, 184, 185, | ||
192 | 186, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193, | ||
193 | 193, 194, 194, 195, 196, 196, 197, 198, 198, 199, 199, 200, | ||
194 | 201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207, | ||
195 | 208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, | ||
196 | 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220, | ||
197 | 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, | ||
198 | 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, | ||
199 | 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239, | ||
200 | 239, 240, 240, 241, 241, 242, 242, 243, 243, 243, 244, 244, | ||
201 | 245, 245, 246, 246 | ||
202 | }; | ||
203 | |||
204 | static const unsigned char blue[256] = { | ||
205 | 0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, | ||
206 | 23, 23, 23, 23, 23, 23, 23, 30, 37, 42, 47, 51, | ||
207 | 55, 58, 61, 64, 67, 70, 72, 74, 78, 80, 82, 84, | ||
208 | 86, 88, 90, 92, 94, 95, 97, 100, 101, 103, 104, 106, | ||
209 | 107, 110, 111, 112, 114, 115, 116, 118, 119, 121, 122, 124, | ||
210 | 125, 126, 127, 128, 129, 132, 133, 134, 135, 136, 137, 138, | ||
211 | 139, 140, 141, 143, 144, 145, 146, 147, 148, 149, 150, 151, | ||
212 | 152, 154, 155, 156, 157, 158, 158, 159, 160, 161, 162, 163, | ||
213 | 165, 166, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, | ||
214 | 176, 176, 177, 178, 179, 180, 180, 181, 182, 183, 183, 184, | ||
215 | 185, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 194, | ||
216 | 194, 195, 196, 196, 198, 199, 200, 200, 201, 202, 202, 203, | ||
217 | 204, 204, 205, 205, 206, 207, 207, 209, 210, 210, 211, 212, | ||
218 | 212, 213, 213, 214, 215, 215, 216, 217, 217, 218, 218, 220, | ||
219 | 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, | ||
220 | 228, 228, 229, 229, 231, 231, 232, 233, 233, 234, 234, 235, | ||
221 | 235, 236, 236, 237, 238, 238, 239, 239, 240, 240, 242, 242, | ||
222 | 243, 243, 244, 244, 245, 246, 246, 247, 247, 248, 248, 249, | ||
223 | 249, 250, 250, 251, 251, 253, 253, 254, 254, 255, 255, 255, | ||
224 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
225 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
226 | 255, 255, 255, 255 | ||
227 | }; | ||
diff --git a/drivers/media/video/tlg2300/pd-main.c b/drivers/media/video/tlg2300/pd-main.c index 256cc558ba13..4555f4a5f4c8 100644 --- a/drivers/media/video/tlg2300/pd-main.c +++ b/drivers/media/video/tlg2300/pd-main.c | |||
@@ -227,12 +227,11 @@ static int firmware_download(struct usb_device *udev) | |||
227 | 227 | ||
228 | fwlength = fw->size; | 228 | fwlength = fw->size; |
229 | 229 | ||
230 | fwbuf = kzalloc(fwlength, GFP_KERNEL); | 230 | fwbuf = kmemdup(fw->data, fwlength, GFP_KERNEL); |
231 | if (!fwbuf) { | 231 | if (!fwbuf) { |
232 | ret = -ENOMEM; | 232 | ret = -ENOMEM; |
233 | goto out; | 233 | goto out; |
234 | } | 234 | } |
235 | memcpy(fwbuf, fw->data, fwlength); | ||
236 | 235 | ||
237 | max_packet_size = udev->ep_out[0x1]->desc.wMaxPacketSize; | 236 | max_packet_size = udev->ep_out[0x1]->desc.wMaxPacketSize; |
238 | log("\t\t download size : %d", (int)max_packet_size); | 237 | log("\t\t download size : %d", (int)max_packet_size); |
diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index 445dc93413e3..a727962781a3 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c | |||
@@ -768,7 +768,7 @@ static int tw9910_g_fmt(struct v4l2_subdev *sd, | |||
768 | 768 | ||
769 | mf->width = priv->scale->width; | 769 | mf->width = priv->scale->width; |
770 | mf->height = priv->scale->height; | 770 | mf->height = priv->scale->height; |
771 | mf->code = V4L2_MBUS_FMT_YUYV8_2X8_BE; | 771 | mf->code = V4L2_MBUS_FMT_UYVY8_2X8; |
772 | mf->colorspace = V4L2_COLORSPACE_JPEG; | 772 | mf->colorspace = V4L2_COLORSPACE_JPEG; |
773 | mf->field = V4L2_FIELD_INTERLACED_BT; | 773 | mf->field = V4L2_FIELD_INTERLACED_BT; |
774 | 774 | ||
@@ -797,7 +797,7 @@ static int tw9910_s_fmt(struct v4l2_subdev *sd, | |||
797 | /* | 797 | /* |
798 | * check color format | 798 | * check color format |
799 | */ | 799 | */ |
800 | if (mf->code != V4L2_MBUS_FMT_YUYV8_2X8_BE) | 800 | if (mf->code != V4L2_MBUS_FMT_UYVY8_2X8) |
801 | return -EINVAL; | 801 | return -EINVAL; |
802 | 802 | ||
803 | mf->colorspace = V4L2_COLORSPACE_JPEG; | 803 | mf->colorspace = V4L2_COLORSPACE_JPEG; |
@@ -824,7 +824,7 @@ static int tw9910_try_fmt(struct v4l2_subdev *sd, | |||
824 | return -EINVAL; | 824 | return -EINVAL; |
825 | } | 825 | } |
826 | 826 | ||
827 | mf->code = V4L2_MBUS_FMT_YUYV8_2X8_BE; | 827 | mf->code = V4L2_MBUS_FMT_UYVY8_2X8; |
828 | mf->colorspace = V4L2_COLORSPACE_JPEG; | 828 | mf->colorspace = V4L2_COLORSPACE_JPEG; |
829 | 829 | ||
830 | /* | 830 | /* |
@@ -909,7 +909,7 @@ static int tw9910_enum_fmt(struct v4l2_subdev *sd, unsigned int index, | |||
909 | if (index) | 909 | if (index) |
910 | return -EINVAL; | 910 | return -EINVAL; |
911 | 911 | ||
912 | *code = V4L2_MBUS_FMT_YUYV8_2X8_BE; | 912 | *code = V4L2_MBUS_FMT_UYVY8_2X8; |
913 | return 0; | 913 | return 0; |
914 | } | 914 | } |
915 | 915 | ||
diff --git a/drivers/media/video/usbvideo/Kconfig b/drivers/media/video/usbvideo/Kconfig index adb1c044ad7d..d6e16959f78b 100644 --- a/drivers/media/video/usbvideo/Kconfig +++ b/drivers/media/video/usbvideo/Kconfig | |||
@@ -37,17 +37,3 @@ config USB_KONICAWC | |||
37 | To compile this driver as a module, choose M here: the | 37 | To compile this driver as a module, choose M here: the |
38 | module will be called konicawc. | 38 | module will be called konicawc. |
39 | 39 | ||
40 | config USB_QUICKCAM_MESSENGER | ||
41 | tristate "USB Logitech Quickcam Messenger (DEPRECATED)" | ||
42 | depends on VIDEO_V4L1 | ||
43 | select VIDEO_USBVIDEO | ||
44 | ---help--- | ||
45 | This driver is DEPRECATED please use the gspca stv06xx module | ||
46 | instead. | ||
47 | |||
48 | Say Y or M here to enable support for the USB Logitech Quickcam | ||
49 | Messenger webcam. | ||
50 | |||
51 | To compile this driver as a module, choose M here: the | ||
52 | module will be called quickcam_messenger. | ||
53 | |||
diff --git a/drivers/media/video/usbvideo/Makefile b/drivers/media/video/usbvideo/Makefile index 4a1b144bee4d..bb52eb8dc2f9 100644 --- a/drivers/media/video/usbvideo/Makefile +++ b/drivers/media/video/usbvideo/Makefile | |||
@@ -2,4 +2,3 @@ obj-$(CONFIG_VIDEO_USBVIDEO) += usbvideo.o | |||
2 | obj-$(CONFIG_USB_IBMCAM) += ibmcam.o ultracam.o | 2 | obj-$(CONFIG_USB_IBMCAM) += ibmcam.o ultracam.o |
3 | obj-$(CONFIG_USB_KONICAWC) += konicawc.o | 3 | obj-$(CONFIG_USB_KONICAWC) += konicawc.o |
4 | obj-$(CONFIG_USB_VICAM) += vicam.o | 4 | obj-$(CONFIG_USB_VICAM) += vicam.o |
5 | obj-$(CONFIG_USB_QUICKCAM_MESSENGER) += quickcam_messenger.o | ||
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c deleted file mode 100644 index fbd665fa1979..000000000000 --- a/drivers/media/video/usbvideo/quickcam_messenger.c +++ /dev/null | |||
@@ -1,1126 +0,0 @@ | |||
1 | /* | ||
2 | * Driver for Logitech Quickcam Messenger usb video camera | ||
3 | * Copyright (C) Jaya Kumar | ||
4 | * | ||
5 | * This work was sponsored by CIS(M) Sdn Bhd. | ||
6 | * History: | ||
7 | * 05/08/2006 - Jaya Kumar | ||
8 | * I wrote this based on the konicawc by Simon Evans. | ||
9 | * - | ||
10 | * Full credit for reverse engineering and creating an initial | ||
11 | * working linux driver for the VV6422 goes to the qce-ga project by | ||
12 | * Tuukka Toivonen, Jochen Hoenicke, Peter McConnell, | ||
13 | * Cristiano De Michele, Georg Acher, Jean-Frederic Clere as well as | ||
14 | * others. | ||
15 | * --- | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License as published by | ||
18 | * the Free Software Foundation; either version 2 of the License, or | ||
19 | * (at your option) any later version. | ||
20 | * | ||
21 | * This program is distributed in the hope that it will be useful, | ||
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
24 | * GNU General Public License for more details. | ||
25 | * | ||
26 | * You should have received a copy of the GNU General Public License | ||
27 | * along with this program; if not, write to the Free Software | ||
28 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
29 | * | ||
30 | */ | ||
31 | |||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/init.h> | ||
35 | #include <linux/input.h> | ||
36 | #include <linux/usb/input.h> | ||
37 | #include <linux/slab.h> | ||
38 | |||
39 | #include "usbvideo.h" | ||
40 | #include "quickcam_messenger.h" | ||
41 | |||
42 | /* | ||
43 | * Version Information | ||
44 | */ | ||
45 | |||
46 | #ifdef CONFIG_USB_DEBUG | ||
47 | static int debug; | ||
48 | #define DEBUG(n, format, arg...) \ | ||
49 | if (n <= debug) { \ | ||
50 | printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \ | ||
51 | } | ||
52 | #else | ||
53 | #define DEBUG(n, arg...) | ||
54 | static const int debug; | ||
55 | #endif | ||
56 | |||
57 | #define DRIVER_VERSION "v0.01" | ||
58 | #define DRIVER_DESC "Logitech Quickcam Messenger USB" | ||
59 | |||
60 | #define USB_LOGITECH_VENDOR_ID 0x046D | ||
61 | #define USB_QCM_PRODUCT_ID 0x08F0 | ||
62 | |||
63 | #define MAX_CAMERAS 1 | ||
64 | |||
65 | #define MAX_COLOUR 32768 | ||
66 | #define MAX_HUE 32768 | ||
67 | #define MAX_BRIGHTNESS 32768 | ||
68 | #define MAX_CONTRAST 32768 | ||
69 | #define MAX_WHITENESS 32768 | ||
70 | |||
71 | static int size = SIZE_320X240; | ||
72 | static int colour = MAX_COLOUR; | ||
73 | static int hue = MAX_HUE; | ||
74 | static int brightness = MAX_BRIGHTNESS; | ||
75 | static int contrast = MAX_CONTRAST; | ||
76 | static int whiteness = MAX_WHITENESS; | ||
77 | |||
78 | static struct usbvideo *cams; | ||
79 | |||
80 | static struct usb_device_id qcm_table [] = { | ||
81 | { USB_DEVICE(USB_LOGITECH_VENDOR_ID, USB_QCM_PRODUCT_ID) }, | ||
82 | { } | ||
83 | }; | ||
84 | MODULE_DEVICE_TABLE(usb, qcm_table); | ||
85 | |||
86 | #ifdef CONFIG_INPUT | ||
87 | static void qcm_register_input(struct qcm *cam, struct usb_device *dev) | ||
88 | { | ||
89 | struct input_dev *input_dev; | ||
90 | int error; | ||
91 | |||
92 | usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); | ||
93 | strlcat(cam->input_physname, "/input0", sizeof(cam->input_physname)); | ||
94 | |||
95 | cam->input = input_dev = input_allocate_device(); | ||
96 | if (!input_dev) { | ||
97 | dev_warn(&dev->dev, "insufficient mem for cam input device\n"); | ||
98 | return; | ||
99 | } | ||
100 | |||
101 | input_dev->name = "QCM button"; | ||
102 | input_dev->phys = cam->input_physname; | ||
103 | usb_to_input_id(dev, &input_dev->id); | ||
104 | input_dev->dev.parent = &dev->dev; | ||
105 | |||
106 | input_dev->evbit[0] = BIT_MASK(EV_KEY); | ||
107 | input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA); | ||
108 | |||
109 | error = input_register_device(cam->input); | ||
110 | if (error) { | ||
111 | dev_warn(&dev->dev, | ||
112 | "Failed to register camera's input device, err: %d\n", | ||
113 | error); | ||
114 | input_free_device(cam->input); | ||
115 | cam->input = NULL; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | static void qcm_unregister_input(struct qcm *cam) | ||
120 | { | ||
121 | if (cam->input) { | ||
122 | input_unregister_device(cam->input); | ||
123 | cam->input = NULL; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | static void qcm_report_buttonstat(struct qcm *cam) | ||
128 | { | ||
129 | if (cam->input) { | ||
130 | input_report_key(cam->input, KEY_CAMERA, cam->button_sts); | ||
131 | input_sync(cam->input); | ||
132 | } | ||
133 | } | ||
134 | |||
135 | static void qcm_int_irq(struct urb *urb) | ||
136 | { | ||
137 | int ret; | ||
138 | struct uvd *uvd = urb->context; | ||
139 | struct qcm *cam; | ||
140 | |||
141 | if (!CAMERA_IS_OPERATIONAL(uvd)) | ||
142 | return; | ||
143 | |||
144 | if (!uvd->streaming) | ||
145 | return; | ||
146 | |||
147 | uvd->stats.urb_count++; | ||
148 | |||
149 | if (urb->status < 0) | ||
150 | uvd->stats.iso_err_count++; | ||
151 | else { | ||
152 | if (urb->actual_length > 0 ) { | ||
153 | cam = (struct qcm *) uvd->user_data; | ||
154 | if (cam->button_sts_buf == 0x88) | ||
155 | cam->button_sts = 0x0; | ||
156 | else if (cam->button_sts_buf == 0x80) | ||
157 | cam->button_sts = 0x1; | ||
158 | qcm_report_buttonstat(cam); | ||
159 | } | ||
160 | } | ||
161 | |||
162 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
163 | if (ret < 0) | ||
164 | err("usb_submit_urb error (%d)", ret); | ||
165 | } | ||
166 | |||
167 | static int qcm_setup_input_int(struct qcm *cam, struct uvd *uvd) | ||
168 | { | ||
169 | int errflag; | ||
170 | usb_fill_int_urb(cam->button_urb, uvd->dev, | ||
171 | usb_rcvintpipe(uvd->dev, uvd->video_endp + 1), | ||
172 | &cam->button_sts_buf, | ||
173 | 1, | ||
174 | qcm_int_irq, | ||
175 | uvd, 16); | ||
176 | |||
177 | errflag = usb_submit_urb(cam->button_urb, GFP_KERNEL); | ||
178 | if (errflag) | ||
179 | err ("usb_submit_int ret %d", errflag); | ||
180 | return errflag; | ||
181 | } | ||
182 | |||
183 | static void qcm_stop_int_data(struct qcm *cam) | ||
184 | { | ||
185 | usb_kill_urb(cam->button_urb); | ||
186 | } | ||
187 | |||
188 | static int qcm_alloc_int_urb(struct qcm *cam) | ||
189 | { | ||
190 | cam->button_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
191 | |||
192 | if (!cam->button_urb) | ||
193 | return -ENOMEM; | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | static void qcm_free_int(struct qcm *cam) | ||
199 | { | ||
200 | usb_free_urb(cam->button_urb); | ||
201 | } | ||
202 | #endif /* CONFIG_INPUT */ | ||
203 | |||
204 | static int qcm_stv_setb(struct usb_device *dev, u16 reg, u8 val) | ||
205 | { | ||
206 | int ret; | ||
207 | |||
208 | /* we'll wait up to 3 slices but no more */ | ||
209 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
210 | 0x04, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, | ||
211 | reg, 0, &val, 1, 3*HZ); | ||
212 | return ret; | ||
213 | } | ||
214 | |||
215 | static int qcm_stv_setw(struct usb_device *dev, u16 reg, __le16 val) | ||
216 | { | ||
217 | int ret; | ||
218 | |||
219 | /* we'll wait up to 3 slices but no more */ | ||
220 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
221 | 0x04, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, | ||
222 | reg, 0, &val, 2, 3*HZ); | ||
223 | return ret; | ||
224 | } | ||
225 | |||
226 | static int qcm_stv_getw(struct usb_device *dev, unsigned short reg, | ||
227 | __le16 *val) | ||
228 | { | ||
229 | int ret; | ||
230 | |||
231 | /* we'll wait up to 3 slices but no more */ | ||
232 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
233 | 0x04, USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, | ||
234 | reg, 0, val, 2, 3*HZ); | ||
235 | return ret; | ||
236 | } | ||
237 | |||
238 | static int qcm_camera_on(struct uvd *uvd) | ||
239 | { | ||
240 | int ret; | ||
241 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x01)); | ||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static int qcm_camera_off(struct uvd *uvd) | ||
246 | { | ||
247 | int ret; | ||
248 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x00)); | ||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static void qcm_hsv2rgb(u16 hue, u16 sat, u16 val, u16 *r, u16 *g, u16 *b) | ||
253 | { | ||
254 | unsigned int segment, valsat; | ||
255 | signed int h = (signed int) hue; | ||
256 | unsigned int s = (sat - 32768) * 2; /* rescale */ | ||
257 | unsigned int v = val; | ||
258 | unsigned int p; | ||
259 | |||
260 | /* | ||
261 | the registers controlling gain are 8 bit of which | ||
262 | we affect only the last 4 bits with our gain. | ||
263 | we know that if saturation is 0, (unsaturated) then | ||
264 | we're grayscale (center axis of the colour cone) so | ||
265 | we set rgb=value. we use a formula obtained from | ||
266 | wikipedia to map the cone to the RGB plane. it's | ||
267 | as follows for the human value case of h=0..360, | ||
268 | s=0..1, v=0..1 | ||
269 | h_i = h/60 % 6 , f = h/60 - h_i , p = v(1-s) | ||
270 | q = v(1 - f*s) , t = v(1 - (1-f)s) | ||
271 | h_i==0 => r=v , g=t, b=p | ||
272 | h_i==1 => r=q , g=v, b=p | ||
273 | h_i==2 => r=p , g=v, b=t | ||
274 | h_i==3 => r=p , g=q, b=v | ||
275 | h_i==4 => r=t , g=p, b=v | ||
276 | h_i==5 => r=v , g=p, b=q | ||
277 | the bottom side (the point) and the stuff just up | ||
278 | of that is black so we simplify those two cases. | ||
279 | */ | ||
280 | if (sat < 32768) { | ||
281 | /* anything less than this is unsaturated */ | ||
282 | *r = val; | ||
283 | *g = val; | ||
284 | *b = val; | ||
285 | return; | ||
286 | } | ||
287 | if (val <= (0xFFFF/8)) { | ||
288 | /* anything less than this is black */ | ||
289 | *r = 0; | ||
290 | *g = 0; | ||
291 | *b = 0; | ||
292 | return; | ||
293 | } | ||
294 | |||
295 | /* the rest of this code is copying tukkat's | ||
296 | implementation of the hsv2rgb conversion as taken | ||
297 | from qc-usb-messenger code. the 10923 is 0xFFFF/6 | ||
298 | to divide the cone into 6 sectors. */ | ||
299 | |||
300 | segment = (h + 10923) & 0xFFFF; | ||
301 | segment = segment*3 >> 16; /* 0..2: 0=R, 1=G, 2=B */ | ||
302 | hue -= segment * 21845; /* -10923..10923 */ | ||
303 | h = hue; | ||
304 | h *= 3; | ||
305 | valsat = v*s >> 16; /* 0..65534 */ | ||
306 | p = v - valsat; | ||
307 | if (h >= 0) { | ||
308 | unsigned int t = v - (valsat * (32769 - h) >> 15); | ||
309 | switch (segment) { | ||
310 | case 0: /* R-> */ | ||
311 | *r = v; | ||
312 | *g = t; | ||
313 | *b = p; | ||
314 | break; | ||
315 | case 1: /* G-> */ | ||
316 | *r = p; | ||
317 | *g = v; | ||
318 | *b = t; | ||
319 | break; | ||
320 | case 2: /* B-> */ | ||
321 | *r = t; | ||
322 | *g = p; | ||
323 | *b = v; | ||
324 | break; | ||
325 | } | ||
326 | } else { | ||
327 | unsigned int q = v - (valsat * (32769 + h) >> 15); | ||
328 | switch (segment) { | ||
329 | case 0: /* ->R */ | ||
330 | *r = v; | ||
331 | *g = p; | ||
332 | *b = q; | ||
333 | break; | ||
334 | case 1: /* ->G */ | ||
335 | *r = q; | ||
336 | *g = v; | ||
337 | *b = p; | ||
338 | break; | ||
339 | case 2: /* ->B */ | ||
340 | *r = p; | ||
341 | *g = q; | ||
342 | *b = v; | ||
343 | break; | ||
344 | } | ||
345 | } | ||
346 | } | ||
347 | |||
348 | static int qcm_sensor_set_gains(struct uvd *uvd, u16 hue, | ||
349 | u16 saturation, u16 value) | ||
350 | { | ||
351 | int ret; | ||
352 | u16 r=0,g=0,b=0; | ||
353 | |||
354 | /* this code is based on qc-usb-messenger */ | ||
355 | qcm_hsv2rgb(hue, saturation, value, &r, &g, &b); | ||
356 | |||
357 | r >>= 12; | ||
358 | g >>= 12; | ||
359 | b >>= 12; | ||
360 | |||
361 | /* min val is 8 */ | ||
362 | r = max((u16) 8, r); | ||
363 | g = max((u16) 8, g); | ||
364 | b = max((u16) 8, b); | ||
365 | |||
366 | r |= 0x30; | ||
367 | g |= 0x30; | ||
368 | b |= 0x30; | ||
369 | |||
370 | /* set the r,g,b gain registers */ | ||
371 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x0509, r)); | ||
372 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050A, g)); | ||
373 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050B, b)); | ||
374 | |||
375 | /* doing as qc-usb did */ | ||
376 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050C, 0x2A)); | ||
377 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050D, 0x01)); | ||
378 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01)); | ||
379 | |||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | static int qcm_sensor_set_exposure(struct uvd *uvd, int exposure) | ||
384 | { | ||
385 | int ret; | ||
386 | int formedval; | ||
387 | |||
388 | /* calculation was from qc-usb-messenger driver */ | ||
389 | formedval = ( exposure >> 12 ); | ||
390 | |||
391 | /* max value for formedval is 14 */ | ||
392 | formedval = min(formedval, 14); | ||
393 | |||
394 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, | ||
395 | 0x143A, 0xF0 | formedval)); | ||
396 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01)); | ||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | static int qcm_sensor_setlevels(struct uvd *uvd, int brightness, int contrast, | ||
401 | int hue, int colour) | ||
402 | { | ||
403 | int ret; | ||
404 | /* brightness is exposure, contrast is gain, colour is saturation */ | ||
405 | CHECK_RET(ret, | ||
406 | qcm_sensor_set_exposure(uvd, brightness)); | ||
407 | CHECK_RET(ret, qcm_sensor_set_gains(uvd, hue, colour, contrast)); | ||
408 | |||
409 | return 0; | ||
410 | } | ||
411 | |||
412 | static int qcm_sensor_setsize(struct uvd *uvd, u8 size) | ||
413 | { | ||
414 | int ret; | ||
415 | |||
416 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x1505, size)); | ||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | static int qcm_sensor_set_shutter(struct uvd *uvd, int whiteness) | ||
421 | { | ||
422 | int ret; | ||
423 | /* some rescaling as done by the qc-usb-messenger code */ | ||
424 | if (whiteness > 0xC000) | ||
425 | whiteness = 0xC000 + (whiteness & 0x3FFF)*8; | ||
426 | |||
427 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143D, | ||
428 | (whiteness >> 8) & 0xFF)); | ||
429 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143E, | ||
430 | (whiteness >> 16) & 0x03)); | ||
431 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01)); | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | static int qcm_sensor_init(struct uvd *uvd) | ||
437 | { | ||
438 | struct qcm *cam = (struct qcm *) uvd->user_data; | ||
439 | int ret; | ||
440 | int i; | ||
441 | |||
442 | for (i=0; i < ARRAY_SIZE(regval_table) ; i++) { | ||
443 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, | ||
444 | regval_table[i].reg, | ||
445 | regval_table[i].val)); | ||
446 | } | ||
447 | |||
448 | CHECK_RET(ret, qcm_stv_setw(uvd->dev, 0x15c1, | ||
449 | cpu_to_le16(ISOC_PACKET_SIZE))); | ||
450 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x15c3, 0x08)); | ||
451 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143f, 0x01)); | ||
452 | |||
453 | CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x00)); | ||
454 | |||
455 | CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd)); | ||
456 | |||
457 | CHECK_RET(ret, qcm_sensor_setlevels(uvd, uvd->vpic.brightness, | ||
458 | uvd->vpic.contrast, uvd->vpic.hue, uvd->vpic.colour)); | ||
459 | |||
460 | CHECK_RET(ret, qcm_sensor_set_shutter(uvd, uvd->vpic.whiteness)); | ||
461 | CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd)); | ||
462 | |||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | static int qcm_set_camera_size(struct uvd *uvd) | ||
467 | { | ||
468 | int ret; | ||
469 | struct qcm *cam = (struct qcm *) uvd->user_data; | ||
470 | |||
471 | CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd)); | ||
472 | cam->width = camera_sizes[cam->size].width; | ||
473 | cam->height = camera_sizes[cam->size].height; | ||
474 | uvd->videosize = VIDEOSIZE(cam->width, cam->height); | ||
475 | |||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | static int qcm_setup_on_open(struct uvd *uvd) | ||
480 | { | ||
481 | int ret; | ||
482 | |||
483 | CHECK_RET(ret, qcm_sensor_set_gains(uvd, uvd->vpic.hue, | ||
484 | uvd->vpic.colour, uvd->vpic.contrast)); | ||
485 | CHECK_RET(ret, qcm_sensor_set_exposure(uvd, uvd->vpic.brightness)); | ||
486 | CHECK_RET(ret, qcm_sensor_set_shutter(uvd, uvd->vpic.whiteness)); | ||
487 | CHECK_RET(ret, qcm_set_camera_size(uvd)); | ||
488 | CHECK_RET(ret, qcm_camera_on(uvd)); | ||
489 | return 0; | ||
490 | } | ||
491 | |||
492 | static void qcm_adjust_picture(struct uvd *uvd) | ||
493 | { | ||
494 | int ret; | ||
495 | struct qcm *cam = (struct qcm *) uvd->user_data; | ||
496 | |||
497 | ret = qcm_camera_off(uvd); | ||
498 | if (ret) { | ||
499 | err("can't turn camera off. abandoning pic adjustment"); | ||
500 | return; | ||
501 | } | ||
502 | |||
503 | /* if there's been a change in contrast, hue, or | ||
504 | colour then we need to recalculate hsv in order | ||
505 | to update gains */ | ||
506 | if ((cam->contrast != uvd->vpic.contrast) || | ||
507 | (cam->hue != uvd->vpic.hue) || | ||
508 | (cam->colour != uvd->vpic.colour)) { | ||
509 | cam->contrast = uvd->vpic.contrast; | ||
510 | cam->hue = uvd->vpic.hue; | ||
511 | cam->colour = uvd->vpic.colour; | ||
512 | ret = qcm_sensor_set_gains(uvd, cam->hue, cam->colour, | ||
513 | cam->contrast); | ||
514 | if (ret) { | ||
515 | err("can't set gains. abandoning pic adjustment"); | ||
516 | return; | ||
517 | } | ||
518 | } | ||
519 | |||
520 | if (cam->brightness != uvd->vpic.brightness) { | ||
521 | cam->brightness = uvd->vpic.brightness; | ||
522 | ret = qcm_sensor_set_exposure(uvd, cam->brightness); | ||
523 | if (ret) { | ||
524 | err("can't set exposure. abandoning pic adjustment"); | ||
525 | return; | ||
526 | } | ||
527 | } | ||
528 | |||
529 | if (cam->whiteness != uvd->vpic.whiteness) { | ||
530 | cam->whiteness = uvd->vpic.whiteness; | ||
531 | qcm_sensor_set_shutter(uvd, cam->whiteness); | ||
532 | if (ret) { | ||
533 | err("can't set shutter. abandoning pic adjustment"); | ||
534 | return; | ||
535 | } | ||
536 | } | ||
537 | |||
538 | ret = qcm_camera_on(uvd); | ||
539 | if (ret) { | ||
540 | err("can't reenable camera. pic adjustment failed"); | ||
541 | return; | ||
542 | } | ||
543 | } | ||
544 | |||
545 | static int qcm_process_frame(struct uvd *uvd, u8 *cdata, int framelen) | ||
546 | { | ||
547 | int datalen; | ||
548 | int totaldata; | ||
549 | struct framehdr { | ||
550 | __be16 id; | ||
551 | __be16 len; | ||
552 | }; | ||
553 | struct framehdr *fhdr; | ||
554 | |||
555 | totaldata = 0; | ||
556 | while (framelen) { | ||
557 | fhdr = (struct framehdr *) cdata; | ||
558 | datalen = be16_to_cpu(fhdr->len); | ||
559 | framelen -= 4; | ||
560 | cdata += 4; | ||
561 | |||
562 | if ((fhdr->id) == cpu_to_be16(0x8001)) { | ||
563 | RingQueue_Enqueue(&uvd->dp, marker, 4); | ||
564 | totaldata += 4; | ||
565 | continue; | ||
566 | } | ||
567 | if ((fhdr->id & cpu_to_be16(0xFF00)) == cpu_to_be16(0x0200)) { | ||
568 | RingQueue_Enqueue(&uvd->dp, cdata, datalen); | ||
569 | totaldata += datalen; | ||
570 | } | ||
571 | framelen -= datalen; | ||
572 | cdata += datalen; | ||
573 | } | ||
574 | return totaldata; | ||
575 | } | ||
576 | |||
577 | static int qcm_compress_iso(struct uvd *uvd, struct urb *dataurb) | ||
578 | { | ||
579 | int totlen; | ||
580 | int i; | ||
581 | unsigned char *cdata; | ||
582 | |||
583 | totlen=0; | ||
584 | for (i = 0; i < dataurb->number_of_packets; i++) { | ||
585 | int n = dataurb->iso_frame_desc[i].actual_length; | ||
586 | int st = dataurb->iso_frame_desc[i].status; | ||
587 | |||
588 | cdata = dataurb->transfer_buffer + | ||
589 | dataurb->iso_frame_desc[i].offset; | ||
590 | |||
591 | if (st < 0) { | ||
592 | dev_warn(&uvd->dev->dev, | ||
593 | "Data error: packet=%d. len=%d. status=%d.\n", | ||
594 | i, n, st); | ||
595 | uvd->stats.iso_err_count++; | ||
596 | continue; | ||
597 | } | ||
598 | if (!n) | ||
599 | continue; | ||
600 | |||
601 | totlen += qcm_process_frame(uvd, cdata, n); | ||
602 | } | ||
603 | return totlen; | ||
604 | } | ||
605 | |||
606 | static void resubmit_urb(struct uvd *uvd, struct urb *urb) | ||
607 | { | ||
608 | int ret; | ||
609 | |||
610 | urb->dev = uvd->dev; | ||
611 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
612 | if (ret) | ||
613 | err("usb_submit_urb error (%d)", ret); | ||
614 | } | ||
615 | |||
616 | static void qcm_isoc_irq(struct urb *urb) | ||
617 | { | ||
618 | int len; | ||
619 | struct uvd *uvd = urb->context; | ||
620 | |||
621 | if (!CAMERA_IS_OPERATIONAL(uvd)) | ||
622 | return; | ||
623 | |||
624 | if (!uvd->streaming) | ||
625 | return; | ||
626 | |||
627 | uvd->stats.urb_count++; | ||
628 | |||
629 | if (!urb->actual_length) { | ||
630 | resubmit_urb(uvd, urb); | ||
631 | return; | ||
632 | } | ||
633 | |||
634 | len = qcm_compress_iso(uvd, urb); | ||
635 | resubmit_urb(uvd, urb); | ||
636 | uvd->stats.urb_length = len; | ||
637 | uvd->stats.data_count += len; | ||
638 | if (len) | ||
639 | RingQueue_WakeUpInterruptible(&uvd->dp); | ||
640 | } | ||
641 | |||
642 | static int qcm_start_data(struct uvd *uvd) | ||
643 | { | ||
644 | struct qcm *cam = (struct qcm *) uvd->user_data; | ||
645 | int i; | ||
646 | int errflag; | ||
647 | int pktsz; | ||
648 | int err; | ||
649 | |||
650 | pktsz = uvd->iso_packet_len; | ||
651 | if (!CAMERA_IS_OPERATIONAL(uvd)) { | ||
652 | err("Camera is not operational"); | ||
653 | return -EFAULT; | ||
654 | } | ||
655 | |||
656 | err = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltActive); | ||
657 | if (err < 0) { | ||
658 | err("usb_set_interface error"); | ||
659 | uvd->last_error = err; | ||
660 | return -EBUSY; | ||
661 | } | ||
662 | |||
663 | for (i=0; i < USBVIDEO_NUMSBUF; i++) { | ||
664 | int j, k; | ||
665 | struct urb *urb = uvd->sbuf[i].urb; | ||
666 | urb->dev = uvd->dev; | ||
667 | urb->context = uvd; | ||
668 | urb->pipe = usb_rcvisocpipe(uvd->dev, uvd->video_endp); | ||
669 | urb->interval = 1; | ||
670 | urb->transfer_flags = URB_ISO_ASAP; | ||
671 | urb->transfer_buffer = uvd->sbuf[i].data; | ||
672 | urb->complete = qcm_isoc_irq; | ||
673 | urb->number_of_packets = FRAMES_PER_DESC; | ||
674 | urb->transfer_buffer_length = pktsz * FRAMES_PER_DESC; | ||
675 | for (j=k=0; j < FRAMES_PER_DESC; j++, k += pktsz) { | ||
676 | urb->iso_frame_desc[j].offset = k; | ||
677 | urb->iso_frame_desc[j].length = pktsz; | ||
678 | } | ||
679 | } | ||
680 | |||
681 | uvd->streaming = 1; | ||
682 | uvd->curframe = -1; | ||
683 | for (i=0; i < USBVIDEO_NUMSBUF; i++) { | ||
684 | errflag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL); | ||
685 | if (errflag) | ||
686 | err ("usb_submit_isoc(%d) ret %d", i, errflag); | ||
687 | } | ||
688 | |||
689 | CHECK_RET(err, qcm_setup_input_int(cam, uvd)); | ||
690 | CHECK_RET(err, qcm_camera_on(uvd)); | ||
691 | return 0; | ||
692 | } | ||
693 | |||
694 | static void qcm_stop_data(struct uvd *uvd) | ||
695 | { | ||
696 | struct qcm *cam; | ||
697 | int i, j; | ||
698 | int ret; | ||
699 | |||
700 | if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL)) | ||
701 | return; | ||
702 | cam = (struct qcm *) uvd->user_data; | ||
703 | |||
704 | ret = qcm_camera_off(uvd); | ||
705 | if (ret) | ||
706 | dev_warn(&uvd->dev->dev, "couldn't turn the cam off.\n"); | ||
707 | |||
708 | uvd->streaming = 0; | ||
709 | |||
710 | /* Unschedule all of the iso td's */ | ||
711 | for (i=0; i < USBVIDEO_NUMSBUF; i++) | ||
712 | usb_kill_urb(uvd->sbuf[i].urb); | ||
713 | |||
714 | qcm_stop_int_data(cam); | ||
715 | |||
716 | if (!uvd->remove_pending) { | ||
717 | /* Set packet size to 0 */ | ||
718 | j = usb_set_interface(uvd->dev, uvd->iface, | ||
719 | uvd->ifaceAltInactive); | ||
720 | if (j < 0) { | ||
721 | err("usb_set_interface() error %d.", j); | ||
722 | uvd->last_error = j; | ||
723 | } | ||
724 | } | ||
725 | } | ||
726 | |||
727 | static void qcm_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame) | ||
728 | { | ||
729 | struct qcm *cam = (struct qcm *) uvd->user_data; | ||
730 | int x; | ||
731 | struct rgb *rgbL0; | ||
732 | struct rgb *rgbL1; | ||
733 | struct bayL0 *bayL0; | ||
734 | struct bayL1 *bayL1; | ||
735 | int hor,ver,hordel,verdel; | ||
736 | assert(frame != NULL); | ||
737 | |||
738 | switch (cam->size) { | ||
739 | case SIZE_160X120: | ||
740 | hor = 162; ver = 124; hordel = 1; verdel = 2; | ||
741 | break; | ||
742 | case SIZE_320X240: | ||
743 | default: | ||
744 | hor = 324; ver = 248; hordel = 2; verdel = 4; | ||
745 | break; | ||
746 | } | ||
747 | |||
748 | if (frame->scanstate == ScanState_Scanning) { | ||
749 | while (RingQueue_GetLength(&uvd->dp) >= | ||
750 | 4 + (hor*verdel + hordel)) { | ||
751 | if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && | ||
752 | (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) && | ||
753 | (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) && | ||
754 | (RING_QUEUE_PEEK(&uvd->dp, 3) == 0xff)) { | ||
755 | frame->curline = 0; | ||
756 | frame->scanstate = ScanState_Lines; | ||
757 | frame->frameState = FrameState_Grabbing; | ||
758 | RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4); | ||
759 | /* | ||
760 | * if we're starting, we need to discard the first | ||
761 | * 4 lines of y bayer data | ||
762 | * and the first 2 gr elements of x bayer data | ||
763 | */ | ||
764 | RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, | ||
765 | (hor*verdel + hordel)); | ||
766 | break; | ||
767 | } | ||
768 | RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); | ||
769 | } | ||
770 | } | ||
771 | |||
772 | if (frame->scanstate == ScanState_Scanning) | ||
773 | return; | ||
774 | |||
775 | /* now we can start processing bayer data so long as we have at least | ||
776 | * 2 lines worth of data. this is the simplest demosaicing method that | ||
777 | * I could think of. I use each 2x2 bayer element without interpolation | ||
778 | * to generate 4 rgb pixels. | ||
779 | */ | ||
780 | while ( frame->curline < cam->height && | ||
781 | (RingQueue_GetLength(&uvd->dp) >= hor*2)) { | ||
782 | /* get 2 lines of bayer for demosaicing | ||
783 | * into 2 lines of RGB */ | ||
784 | RingQueue_Dequeue(&uvd->dp, cam->scratch, hor*2); | ||
785 | bayL0 = (struct bayL0 *) cam->scratch; | ||
786 | bayL1 = (struct bayL1 *) (cam->scratch + hor); | ||
787 | /* frame->curline is the rgb y line */ | ||
788 | rgbL0 = (struct rgb *) | ||
789 | ( frame->data + (cam->width*3*frame->curline)); | ||
790 | /* w/2 because we're already doing 2 pixels */ | ||
791 | rgbL1 = rgbL0 + (cam->width/2); | ||
792 | |||
793 | for (x=0; x < cam->width; x+=2) { | ||
794 | rgbL0->r = bayL0->r; | ||
795 | rgbL0->g = bayL0->g; | ||
796 | rgbL0->b = bayL1->b; | ||
797 | |||
798 | rgbL0->r2 = bayL0->r; | ||
799 | rgbL0->g2 = bayL1->g; | ||
800 | rgbL0->b2 = bayL1->b; | ||
801 | |||
802 | rgbL1->r = bayL0->r; | ||
803 | rgbL1->g = bayL1->g; | ||
804 | rgbL1->b = bayL1->b; | ||
805 | |||
806 | rgbL1->r2 = bayL0->r; | ||
807 | rgbL1->g2 = bayL1->g; | ||
808 | rgbL1->b2 = bayL1->b; | ||
809 | |||
810 | rgbL0++; | ||
811 | rgbL1++; | ||
812 | |||
813 | bayL0++; | ||
814 | bayL1++; | ||
815 | } | ||
816 | |||
817 | frame->seqRead_Length += cam->width*3*2; | ||
818 | frame->curline += 2; | ||
819 | } | ||
820 | /* See if we filled the frame */ | ||
821 | if (frame->curline == cam->height) { | ||
822 | frame->frameState = FrameState_Done_Hold; | ||
823 | frame->curline = 0; | ||
824 | uvd->curframe = -1; | ||
825 | uvd->stats.frame_num++; | ||
826 | } | ||
827 | } | ||
828 | |||
829 | /* taken from konicawc */ | ||
830 | static int qcm_set_video_mode(struct uvd *uvd, struct video_window *vw) | ||
831 | { | ||
832 | int ret; | ||
833 | int newsize; | ||
834 | int oldsize; | ||
835 | int x = vw->width; | ||
836 | int y = vw->height; | ||
837 | struct qcm *cam = (struct qcm *) uvd->user_data; | ||
838 | |||
839 | if (x > 0 && y > 0) { | ||
840 | DEBUG(2, "trying to find size %d,%d", x, y); | ||
841 | for (newsize = 0; newsize <= MAX_FRAME_SIZE; newsize++) { | ||
842 | if ((camera_sizes[newsize].width == x) && | ||
843 | (camera_sizes[newsize].height == y)) | ||
844 | break; | ||
845 | } | ||
846 | } else | ||
847 | newsize = cam->size; | ||
848 | |||
849 | if (newsize > MAX_FRAME_SIZE) { | ||
850 | DEBUG(1, "couldn't find size %d,%d", x, y); | ||
851 | return -EINVAL; | ||
852 | } | ||
853 | |||
854 | if (newsize == cam->size) { | ||
855 | DEBUG(1, "Nothing to do"); | ||
856 | return 0; | ||
857 | } | ||
858 | |||
859 | qcm_stop_data(uvd); | ||
860 | |||
861 | if (cam->size != newsize) { | ||
862 | oldsize = cam->size; | ||
863 | cam->size = newsize; | ||
864 | ret = qcm_set_camera_size(uvd); | ||
865 | if (ret) { | ||
866 | err("Couldn't set camera size, err=%d",ret); | ||
867 | /* restore the original size */ | ||
868 | cam->size = oldsize; | ||
869 | return ret; | ||
870 | } | ||
871 | } | ||
872 | |||
873 | /* Flush the input queue and clear any current frame in progress */ | ||
874 | |||
875 | RingQueue_Flush(&uvd->dp); | ||
876 | if (uvd->curframe != -1) { | ||
877 | uvd->frame[uvd->curframe].curline = 0; | ||
878 | uvd->frame[uvd->curframe].seqRead_Length = 0; | ||
879 | uvd->frame[uvd->curframe].seqRead_Index = 0; | ||
880 | } | ||
881 | |||
882 | CHECK_RET(ret, qcm_start_data(uvd)); | ||
883 | return 0; | ||
884 | } | ||
885 | |||
886 | static int qcm_configure_video(struct uvd *uvd) | ||
887 | { | ||
888 | int ret; | ||
889 | memset(&uvd->vpic, 0, sizeof(uvd->vpic)); | ||
890 | memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old)); | ||
891 | |||
892 | uvd->vpic.colour = colour; | ||
893 | uvd->vpic.hue = hue; | ||
894 | uvd->vpic.brightness = brightness; | ||
895 | uvd->vpic.contrast = contrast; | ||
896 | uvd->vpic.whiteness = whiteness; | ||
897 | uvd->vpic.depth = 24; | ||
898 | uvd->vpic.palette = VIDEO_PALETTE_RGB24; | ||
899 | |||
900 | memset(&uvd->vcap, 0, sizeof(uvd->vcap)); | ||
901 | strcpy(uvd->vcap.name, "QCM USB Camera"); | ||
902 | uvd->vcap.type = VID_TYPE_CAPTURE; | ||
903 | uvd->vcap.channels = 1; | ||
904 | uvd->vcap.audios = 0; | ||
905 | |||
906 | uvd->vcap.minwidth = camera_sizes[SIZE_160X120].width; | ||
907 | uvd->vcap.minheight = camera_sizes[SIZE_160X120].height; | ||
908 | uvd->vcap.maxwidth = camera_sizes[SIZE_320X240].width; | ||
909 | uvd->vcap.maxheight = camera_sizes[SIZE_320X240].height; | ||
910 | |||
911 | memset(&uvd->vchan, 0, sizeof(uvd->vchan)); | ||
912 | uvd->vchan.flags = 0 ; | ||
913 | uvd->vchan.tuners = 0; | ||
914 | uvd->vchan.channel = 0; | ||
915 | uvd->vchan.type = VIDEO_TYPE_CAMERA; | ||
916 | strcpy(uvd->vchan.name, "Camera"); | ||
917 | |||
918 | CHECK_RET(ret, qcm_sensor_init(uvd)); | ||
919 | return 0; | ||
920 | } | ||
921 | |||
922 | static int qcm_probe(struct usb_interface *intf, | ||
923 | const struct usb_device_id *devid) | ||
924 | { | ||
925 | int err; | ||
926 | struct uvd *uvd; | ||
927 | struct usb_device *dev = interface_to_usbdev(intf); | ||
928 | struct qcm *cam; | ||
929 | size_t buffer_size; | ||
930 | unsigned char video_ep; | ||
931 | struct usb_host_interface *interface; | ||
932 | struct usb_endpoint_descriptor *endpoint; | ||
933 | int i,j; | ||
934 | unsigned int ifacenum, ifacenum_inact=0; | ||
935 | __le16 sensor_id; | ||
936 | |||
937 | /* we don't support multiconfig cams */ | ||
938 | if (dev->descriptor.bNumConfigurations != 1) | ||
939 | return -ENODEV; | ||
940 | |||
941 | /* first check for the video interface and not | ||
942 | * the audio interface */ | ||
943 | interface = &intf->cur_altsetting[0]; | ||
944 | if ((interface->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC) | ||
945 | || (interface->desc.bInterfaceSubClass != | ||
946 | USB_CLASS_VENDOR_SPEC)) | ||
947 | return -ENODEV; | ||
948 | |||
949 | /* | ||
950 | walk through each endpoint in each setting in the interface | ||
951 | stop when we find the one that's an isochronous IN endpoint. | ||
952 | */ | ||
953 | for (i=0; i < intf->num_altsetting; i++) { | ||
954 | interface = &intf->cur_altsetting[i]; | ||
955 | ifacenum = interface->desc.bAlternateSetting; | ||
956 | /* walk the end points */ | ||
957 | for (j=0; j < interface->desc.bNumEndpoints; j++) { | ||
958 | endpoint = &interface->endpoint[j].desc; | ||
959 | |||
960 | if (usb_endpoint_dir_out(endpoint)) | ||
961 | continue; /* not input then not good */ | ||
962 | |||
963 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); | ||
964 | if (!buffer_size) { | ||
965 | ifacenum_inact = ifacenum; | ||
966 | continue; /* 0 pkt size is not what we want */ | ||
967 | } | ||
968 | |||
969 | if (usb_endpoint_xfer_isoc(endpoint)) { | ||
970 | video_ep = endpoint->bEndpointAddress; | ||
971 | /* break out of the search */ | ||
972 | goto good_videoep; | ||
973 | } | ||
974 | } | ||
975 | } | ||
976 | /* failed out since nothing useful was found */ | ||
977 | err("No suitable endpoint was found\n"); | ||
978 | return -ENODEV; | ||
979 | |||
980 | good_videoep: | ||
981 | /* disable isochronous stream before doing anything else */ | ||
982 | err = qcm_stv_setb(dev, STV_ISO_ENABLE, 0); | ||
983 | if (err < 0) { | ||
984 | err("Failed to disable sensor stream"); | ||
985 | return -EIO; | ||
986 | } | ||
987 | |||
988 | /* | ||
989 | Check that this is the same unknown sensor that is known to work. This | ||
990 | sensor is suspected to be the ST VV6422C001. I'll check the same value | ||
991 | that the qc-usb driver checks. This value is probably not even the | ||
992 | sensor ID since it matches the USB dev ID. Oh well. If it doesn't | ||
993 | match, it's probably a diff sensor so exit and apologize. | ||
994 | */ | ||
995 | err = qcm_stv_getw(dev, CMOS_SENSOR_IDREV, &sensor_id); | ||
996 | if (err < 0) { | ||
997 | err("Couldn't read sensor values. Err %d\n",err); | ||
998 | return err; | ||
999 | } | ||
1000 | if (sensor_id != cpu_to_le16(0x08F0)) { | ||
1001 | err("Sensor ID %x != %x. Unsupported. Sorry\n", | ||
1002 | le16_to_cpu(sensor_id), (0x08F0)); | ||
1003 | return -ENODEV; | ||
1004 | } | ||
1005 | |||
1006 | uvd = usbvideo_AllocateDevice(cams); | ||
1007 | if (!uvd) | ||
1008 | return -ENOMEM; | ||
1009 | |||
1010 | cam = (struct qcm *) uvd->user_data; | ||
1011 | |||
1012 | /* buf for doing demosaicing */ | ||
1013 | cam->scratch = kmalloc(324*2, GFP_KERNEL); | ||
1014 | if (!cam->scratch) /* uvd freed in dereg */ | ||
1015 | return -ENOMEM; | ||
1016 | |||
1017 | /* yes, if we fail after here, cam->scratch gets freed | ||
1018 | by qcm_free_uvd */ | ||
1019 | |||
1020 | err = qcm_alloc_int_urb(cam); | ||
1021 | if (err < 0) | ||
1022 | return err; | ||
1023 | |||
1024 | /* yes, if we fail after here, int urb gets freed | ||
1025 | by qcm_free_uvd */ | ||
1026 | |||
1027 | RESTRICT_TO_RANGE(size, SIZE_160X120, SIZE_320X240); | ||
1028 | cam->width = camera_sizes[size].width; | ||
1029 | cam->height = camera_sizes[size].height; | ||
1030 | cam->size = size; | ||
1031 | |||
1032 | uvd->debug = debug; | ||
1033 | uvd->flags = 0; | ||
1034 | uvd->dev = dev; | ||
1035 | uvd->iface = intf->altsetting->desc.bInterfaceNumber; | ||
1036 | uvd->ifaceAltActive = ifacenum; | ||
1037 | uvd->ifaceAltInactive = ifacenum_inact; | ||
1038 | uvd->video_endp = video_ep; | ||
1039 | uvd->iso_packet_len = buffer_size; | ||
1040 | uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24; | ||
1041 | uvd->defaultPalette = VIDEO_PALETTE_RGB24; | ||
1042 | uvd->canvas = VIDEOSIZE(320, 240); | ||
1043 | uvd->videosize = VIDEOSIZE(cam->width, cam->height); | ||
1044 | err = qcm_configure_video(uvd); | ||
1045 | if (err) { | ||
1046 | err("failed to configure video settings"); | ||
1047 | return err; | ||
1048 | } | ||
1049 | |||
1050 | err = usbvideo_RegisterVideoDevice(uvd); | ||
1051 | if (err) { /* the uvd gets freed in Deregister */ | ||
1052 | err("usbvideo_RegisterVideoDevice() failed."); | ||
1053 | return err; | ||
1054 | } | ||
1055 | |||
1056 | uvd->max_frame_size = (320 * 240 * 3); | ||
1057 | qcm_register_input(cam, dev); | ||
1058 | usb_set_intfdata(intf, uvd); | ||
1059 | return 0; | ||
1060 | } | ||
1061 | |||
1062 | static void qcm_free_uvd(struct uvd *uvd) | ||
1063 | { | ||
1064 | struct qcm *cam = (struct qcm *) uvd->user_data; | ||
1065 | |||
1066 | kfree(cam->scratch); | ||
1067 | qcm_unregister_input(cam); | ||
1068 | qcm_free_int(cam); | ||
1069 | } | ||
1070 | |||
1071 | static struct usbvideo_cb qcm_driver = { | ||
1072 | .probe = qcm_probe, | ||
1073 | .setupOnOpen = qcm_setup_on_open, | ||
1074 | .processData = qcm_process_isoc, | ||
1075 | .setVideoMode = qcm_set_video_mode, | ||
1076 | .startDataPump = qcm_start_data, | ||
1077 | .stopDataPump = qcm_stop_data, | ||
1078 | .adjustPicture = qcm_adjust_picture, | ||
1079 | .userFree = qcm_free_uvd | ||
1080 | }; | ||
1081 | |||
1082 | static int __init qcm_init(void) | ||
1083 | { | ||
1084 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" | ||
1085 | DRIVER_DESC "\n"); | ||
1086 | |||
1087 | return usbvideo_register( | ||
1088 | &cams, | ||
1089 | MAX_CAMERAS, | ||
1090 | sizeof(struct qcm), | ||
1091 | "QCM", | ||
1092 | &qcm_driver, | ||
1093 | THIS_MODULE, | ||
1094 | qcm_table); | ||
1095 | } | ||
1096 | |||
1097 | static void __exit qcm_exit(void) | ||
1098 | { | ||
1099 | usbvideo_Deregister(&cams); | ||
1100 | } | ||
1101 | |||
1102 | module_param(size, int, 0); | ||
1103 | MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 320x240"); | ||
1104 | module_param(colour, int, 0); | ||
1105 | MODULE_PARM_DESC(colour, "Initial colour"); | ||
1106 | module_param(hue, int, 0); | ||
1107 | MODULE_PARM_DESC(hue, "Initial hue"); | ||
1108 | module_param(brightness, int, 0); | ||
1109 | MODULE_PARM_DESC(brightness, "Initial brightness"); | ||
1110 | module_param(contrast, int, 0); | ||
1111 | MODULE_PARM_DESC(contrast, "Initial contrast"); | ||
1112 | module_param(whiteness, int, 0); | ||
1113 | MODULE_PARM_DESC(whiteness, "Initial whiteness"); | ||
1114 | |||
1115 | #ifdef CONFIG_USB_DEBUG | ||
1116 | module_param(debug, int, S_IRUGO | S_IWUSR); | ||
1117 | MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); | ||
1118 | #endif | ||
1119 | |||
1120 | module_init(qcm_init); | ||
1121 | module_exit(qcm_exit); | ||
1122 | |||
1123 | MODULE_LICENSE("GPL"); | ||
1124 | MODULE_AUTHOR("Jaya Kumar"); | ||
1125 | MODULE_DESCRIPTION("QCM USB Camera"); | ||
1126 | MODULE_SUPPORTED_DEVICE("QCM USB Camera"); | ||
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.h b/drivers/media/video/usbvideo/quickcam_messenger.h deleted file mode 100644 index 17ace394d981..000000000000 --- a/drivers/media/video/usbvideo/quickcam_messenger.h +++ /dev/null | |||
@@ -1,112 +0,0 @@ | |||
1 | #ifndef quickcam_messenger_h | ||
2 | #define quickcam_messenger_h | ||
3 | |||
4 | #ifndef CONFIG_INPUT | ||
5 | /* if we're not using input we dummy out these functions */ | ||
6 | #define qcm_register_input(...) | ||
7 | #define qcm_unregister_input(...) | ||
8 | #define qcm_report_buttonstat(...) | ||
9 | #define qcm_setup_input_int(...) 0 | ||
10 | #define qcm_stop_int_data(...) | ||
11 | #define qcm_alloc_int_urb(...) 0 | ||
12 | #define qcm_free_int(...) | ||
13 | #endif | ||
14 | |||
15 | |||
16 | #define CHECK_RET(ret, expr) \ | ||
17 | if ((ret = expr) < 0) return ret | ||
18 | |||
19 | /* Control Registers for the STVV6422 ASIC | ||
20 | * - this define is taken from the qc-usb-messenger code | ||
21 | */ | ||
22 | #define STV_ISO_ENABLE 0x1440 | ||
23 | #define ISOC_PACKET_SIZE 1023 | ||
24 | |||
25 | /* Chip identification number including revision indicator */ | ||
26 | #define CMOS_SENSOR_IDREV 0xE00A | ||
27 | |||
28 | struct rgb { | ||
29 | u8 b; | ||
30 | u8 g; | ||
31 | u8 r; | ||
32 | u8 b2; | ||
33 | u8 g2; | ||
34 | u8 r2; | ||
35 | }; | ||
36 | |||
37 | struct bayL0 { | ||
38 | u8 g; | ||
39 | u8 r; | ||
40 | }; | ||
41 | |||
42 | struct bayL1 { | ||
43 | u8 b; | ||
44 | u8 g; | ||
45 | }; | ||
46 | |||
47 | struct cam_size { | ||
48 | u16 width; | ||
49 | u16 height; | ||
50 | u8 cmd; | ||
51 | }; | ||
52 | |||
53 | static const struct cam_size camera_sizes[] = { | ||
54 | { 160, 120, 0xf }, | ||
55 | { 320, 240, 0x2 }, | ||
56 | }; | ||
57 | |||
58 | enum frame_sizes { | ||
59 | SIZE_160X120 = 0, | ||
60 | SIZE_320X240 = 1, | ||
61 | }; | ||
62 | |||
63 | #define MAX_FRAME_SIZE SIZE_320X240 | ||
64 | |||
65 | struct qcm { | ||
66 | u16 colour; | ||
67 | u16 hue; | ||
68 | u16 brightness; | ||
69 | u16 contrast; | ||
70 | u16 whiteness; | ||
71 | |||
72 | u8 size; | ||
73 | int height; | ||
74 | int width; | ||
75 | u8 *scratch; | ||
76 | struct urb *button_urb; | ||
77 | u8 button_sts; | ||
78 | u8 button_sts_buf; | ||
79 | |||
80 | #ifdef CONFIG_INPUT | ||
81 | struct input_dev *input; | ||
82 | char input_physname[64]; | ||
83 | #endif | ||
84 | }; | ||
85 | |||
86 | struct regval { | ||
87 | u16 reg; | ||
88 | u8 val; | ||
89 | }; | ||
90 | /* this table is derived from the | ||
91 | qc-usb-messenger code */ | ||
92 | static const struct regval regval_table[] = { | ||
93 | { STV_ISO_ENABLE, 0x00 }, | ||
94 | { 0x1436, 0x00 }, { 0x1432, 0x03 }, | ||
95 | { 0x143a, 0xF9 }, { 0x0509, 0x38 }, | ||
96 | { 0x050a, 0x38 }, { 0x050b, 0x38 }, | ||
97 | { 0x050c, 0x2A }, { 0x050d, 0x01 }, | ||
98 | { 0x1431, 0x00 }, { 0x1433, 0x34 }, | ||
99 | { 0x1438, 0x18 }, { 0x1439, 0x00 }, | ||
100 | { 0x143b, 0x05 }, { 0x143c, 0x00 }, | ||
101 | { 0x143e, 0x01 }, { 0x143d, 0x00 }, | ||
102 | { 0x1442, 0xe2 }, { 0x1500, 0xd0 }, | ||
103 | { 0x1500, 0xd0 }, { 0x1500, 0x50 }, | ||
104 | { 0x1501, 0xaf }, { 0x1502, 0xc2 }, | ||
105 | { 0x1503, 0x45 }, { 0x1505, 0x02 }, | ||
106 | { 0x150e, 0x8e }, { 0x150f, 0x37 }, | ||
107 | { 0x15c0, 0x00 }, | ||
108 | }; | ||
109 | |||
110 | static const unsigned char marker[] = { 0x00, 0xff, 0x00, 0xFF }; | ||
111 | |||
112 | #endif /* quickcam_messenger_h */ | ||
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index 27a79f087b15..a350fad0db43 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c | |||
@@ -606,6 +606,26 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { | |||
606 | .set = uvc_ctrl_set_zoom, | 606 | .set = uvc_ctrl_set_zoom, |
607 | }, | 607 | }, |
608 | { | 608 | { |
609 | .id = V4L2_CID_PAN_ABSOLUTE, | ||
610 | .name = "Pan (Absolute)", | ||
611 | .entity = UVC_GUID_UVC_CAMERA, | ||
612 | .selector = UVC_CT_PANTILT_ABSOLUTE_CONTROL, | ||
613 | .size = 32, | ||
614 | .offset = 0, | ||
615 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
616 | .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, | ||
617 | }, | ||
618 | { | ||
619 | .id = V4L2_CID_TILT_ABSOLUTE, | ||
620 | .name = "Tilt (Absolute)", | ||
621 | .entity = UVC_GUID_UVC_CAMERA, | ||
622 | .selector = UVC_CT_PANTILT_ABSOLUTE_CONTROL, | ||
623 | .size = 32, | ||
624 | .offset = 32, | ||
625 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
626 | .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, | ||
627 | }, | ||
628 | { | ||
609 | .id = V4L2_CID_PRIVACY, | 629 | .id = V4L2_CID_PRIVACY, |
610 | .name = "Privacy", | 630 | .name = "Privacy", |
611 | .entity = UVC_GUID_UVC_CAMERA, | 631 | .entity = UVC_GUID_UVC_CAMERA, |
@@ -623,7 +643,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { | |||
623 | 643 | ||
624 | static inline __u8 *uvc_ctrl_data(struct uvc_control *ctrl, int id) | 644 | static inline __u8 *uvc_ctrl_data(struct uvc_control *ctrl, int id) |
625 | { | 645 | { |
626 | return ctrl->data + id * ctrl->info->size; | 646 | return ctrl->uvc_data + id * ctrl->info->size; |
627 | } | 647 | } |
628 | 648 | ||
629 | static inline int uvc_test_bit(const __u8 *data, int bit) | 649 | static inline int uvc_test_bit(const __u8 *data, int bit) |
@@ -678,6 +698,14 @@ static void uvc_set_le_value(struct uvc_control_mapping *mapping, | |||
678 | int offset = mapping->offset; | 698 | int offset = mapping->offset; |
679 | __u8 mask; | 699 | __u8 mask; |
680 | 700 | ||
701 | /* According to the v4l2 spec, writing any value to a button control | ||
702 | * should result in the action belonging to the button control being | ||
703 | * triggered. UVC devices however want to see a 1 written -> override | ||
704 | * value. | ||
705 | */ | ||
706 | if (mapping->v4l2_type == V4L2_CTRL_TYPE_BUTTON) | ||
707 | value = -1; | ||
708 | |||
681 | data += offset / 8; | 709 | data += offset / 8; |
682 | offset &= 7; | 710 | offset &= 7; |
683 | 711 | ||
@@ -1265,13 +1293,15 @@ int uvc_ctrl_resume_device(struct uvc_device *dev) | |||
1265 | * Control and mapping handling | 1293 | * Control and mapping handling |
1266 | */ | 1294 | */ |
1267 | 1295 | ||
1268 | static void uvc_ctrl_add_ctrl(struct uvc_device *dev, | 1296 | static int uvc_ctrl_add_ctrl(struct uvc_device *dev, |
1269 | struct uvc_control_info *info) | 1297 | struct uvc_control_info *info) |
1270 | { | 1298 | { |
1271 | struct uvc_entity *entity; | 1299 | struct uvc_entity *entity; |
1272 | struct uvc_control *ctrl = NULL; | 1300 | struct uvc_control *ctrl = NULL; |
1273 | int ret, found = 0; | 1301 | int ret = 0, found = 0; |
1274 | unsigned int i; | 1302 | unsigned int i; |
1303 | u8 *uvc_info; | ||
1304 | u8 *uvc_data; | ||
1275 | 1305 | ||
1276 | list_for_each_entry(entity, &dev->entities, list) { | 1306 | list_for_each_entry(entity, &dev->entities, list) { |
1277 | if (!uvc_entity_match_guid(entity, info->entity)) | 1307 | if (!uvc_entity_match_guid(entity, info->entity)) |
@@ -1290,56 +1320,69 @@ static void uvc_ctrl_add_ctrl(struct uvc_device *dev, | |||
1290 | } | 1320 | } |
1291 | 1321 | ||
1292 | if (!found) | 1322 | if (!found) |
1293 | return; | 1323 | return 0; |
1324 | |||
1325 | uvc_data = kmalloc(info->size * UVC_CTRL_DATA_LAST + 1, GFP_KERNEL); | ||
1326 | if (uvc_data == NULL) | ||
1327 | return -ENOMEM; | ||
1328 | |||
1329 | uvc_info = uvc_data + info->size * UVC_CTRL_DATA_LAST; | ||
1294 | 1330 | ||
1295 | if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT) { | 1331 | if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT) { |
1296 | /* Check if the device control information and length match | 1332 | /* Check if the device control information and length match |
1297 | * the user supplied information. | 1333 | * the user supplied information. |
1298 | */ | 1334 | */ |
1299 | __u32 flags; | ||
1300 | __le16 size; | ||
1301 | __u8 inf; | ||
1302 | |||
1303 | ret = uvc_query_ctrl(dev, UVC_GET_LEN, ctrl->entity->id, | 1335 | ret = uvc_query_ctrl(dev, UVC_GET_LEN, ctrl->entity->id, |
1304 | dev->intfnum, info->selector, (__u8 *)&size, 2); | 1336 | dev->intfnum, info->selector, uvc_data, 2); |
1305 | if (ret < 0) { | 1337 | if (ret < 0) { |
1306 | uvc_trace(UVC_TRACE_CONTROL, | 1338 | uvc_trace(UVC_TRACE_CONTROL, |
1307 | "GET_LEN failed on control %pUl/%u (%d).\n", | 1339 | "GET_LEN failed on control %pUl/%u (%d).\n", |
1308 | info->entity, info->selector, ret); | 1340 | info->entity, info->selector, ret); |
1309 | return; | 1341 | goto done; |
1310 | } | 1342 | } |
1311 | 1343 | ||
1312 | if (info->size != le16_to_cpu(size)) { | 1344 | if (info->size != le16_to_cpu(*(__le16 *)uvc_data)) { |
1313 | uvc_trace(UVC_TRACE_CONTROL, "Control %pUl/%u size " | 1345 | uvc_trace(UVC_TRACE_CONTROL, "Control %pUl/%u size " |
1314 | "doesn't match user supplied value.\n", | 1346 | "doesn't match user supplied value.\n", |
1315 | info->entity, info->selector); | 1347 | info->entity, info->selector); |
1316 | return; | 1348 | ret = -EINVAL; |
1349 | goto done; | ||
1317 | } | 1350 | } |
1318 | 1351 | ||
1319 | ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, | 1352 | ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, |
1320 | dev->intfnum, info->selector, &inf, 1); | 1353 | dev->intfnum, info->selector, uvc_info, 1); |
1321 | if (ret < 0) { | 1354 | if (ret < 0) { |
1322 | uvc_trace(UVC_TRACE_CONTROL, | 1355 | uvc_trace(UVC_TRACE_CONTROL, |
1323 | "GET_INFO failed on control %pUl/%u (%d).\n", | 1356 | "GET_INFO failed on control %pUl/%u (%d).\n", |
1324 | info->entity, info->selector, ret); | 1357 | info->entity, info->selector, ret); |
1325 | return; | 1358 | goto done; |
1326 | } | 1359 | } |
1327 | 1360 | ||
1328 | flags = info->flags; | 1361 | if (((info->flags & UVC_CONTROL_GET_CUR) && |
1329 | if (((flags & UVC_CONTROL_GET_CUR) && !(inf & (1 << 0))) || | 1362 | !(*uvc_info & UVC_CONTROL_CAP_GET)) || |
1330 | ((flags & UVC_CONTROL_SET_CUR) && !(inf & (1 << 1)))) { | 1363 | ((info->flags & UVC_CONTROL_SET_CUR) && |
1364 | !(*uvc_info & UVC_CONTROL_CAP_SET))) { | ||
1331 | uvc_trace(UVC_TRACE_CONTROL, "Control %pUl/%u flags " | 1365 | uvc_trace(UVC_TRACE_CONTROL, "Control %pUl/%u flags " |
1332 | "don't match supported operations.\n", | 1366 | "don't match supported operations.\n", |
1333 | info->entity, info->selector); | 1367 | info->entity, info->selector); |
1334 | return; | 1368 | ret = -EINVAL; |
1369 | goto done; | ||
1335 | } | 1370 | } |
1336 | } | 1371 | } |
1337 | 1372 | ||
1338 | ctrl->info = info; | 1373 | ctrl->info = info; |
1339 | ctrl->data = kmalloc(ctrl->info->size * UVC_CTRL_DATA_LAST, GFP_KERNEL); | 1374 | ctrl->uvc_data = uvc_data; |
1375 | ctrl->uvc_info = uvc_info; | ||
1376 | |||
1340 | uvc_trace(UVC_TRACE_CONTROL, "Added control %pUl/%u to device %s " | 1377 | uvc_trace(UVC_TRACE_CONTROL, "Added control %pUl/%u to device %s " |
1341 | "entity %u\n", ctrl->info->entity, ctrl->info->selector, | 1378 | "entity %u\n", ctrl->info->entity, ctrl->info->selector, |
1342 | dev->udev->devpath, entity->id); | 1379 | dev->udev->devpath, entity->id); |
1380 | |||
1381 | done: | ||
1382 | if (ret < 0) | ||
1383 | kfree(uvc_data); | ||
1384 | |||
1385 | return ret; | ||
1343 | } | 1386 | } |
1344 | 1387 | ||
1345 | /* | 1388 | /* |
@@ -1572,12 +1615,34 @@ void uvc_ctrl_cleanup_device(struct uvc_device *dev) | |||
1572 | 1615 | ||
1573 | list_for_each_entry(entity, &dev->entities, list) { | 1616 | list_for_each_entry(entity, &dev->entities, list) { |
1574 | for (i = 0; i < entity->ncontrols; ++i) | 1617 | for (i = 0; i < entity->ncontrols; ++i) |
1575 | kfree(entity->controls[i].data); | 1618 | kfree(entity->controls[i].uvc_data); |
1576 | 1619 | ||
1577 | kfree(entity->controls); | 1620 | kfree(entity->controls); |
1578 | } | 1621 | } |
1579 | } | 1622 | } |
1580 | 1623 | ||
1624 | void uvc_ctrl_cleanup(void) | ||
1625 | { | ||
1626 | struct uvc_control_info *info; | ||
1627 | struct uvc_control_info *ni; | ||
1628 | struct uvc_control_mapping *mapping; | ||
1629 | struct uvc_control_mapping *nm; | ||
1630 | |||
1631 | list_for_each_entry_safe(info, ni, &uvc_driver.controls, list) { | ||
1632 | if (!(info->flags & UVC_CONTROL_EXTENSION)) | ||
1633 | continue; | ||
1634 | |||
1635 | list_for_each_entry_safe(mapping, nm, &info->mappings, list) { | ||
1636 | list_del(&mapping->list); | ||
1637 | kfree(mapping->menu_info); | ||
1638 | kfree(mapping); | ||
1639 | } | ||
1640 | |||
1641 | list_del(&info->list); | ||
1642 | kfree(info); | ||
1643 | } | ||
1644 | } | ||
1645 | |||
1581 | void uvc_ctrl_init(void) | 1646 | void uvc_ctrl_init(void) |
1582 | { | 1647 | { |
1583 | struct uvc_control_info *ctrl = uvc_ctrls; | 1648 | struct uvc_control_info *ctrl = uvc_ctrls; |
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 838b56f097cf..7eaf99b22a48 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c | |||
@@ -637,14 +637,13 @@ static int uvc_parse_streaming(struct uvc_device *dev, | |||
637 | } | 637 | } |
638 | streaming->header.bControlSize = n; | 638 | streaming->header.bControlSize = n; |
639 | 639 | ||
640 | streaming->header.bmaControls = kmalloc(p*n, GFP_KERNEL); | 640 | streaming->header.bmaControls = kmemdup(&buffer[size], p * n, |
641 | GFP_KERNEL); | ||
641 | if (streaming->header.bmaControls == NULL) { | 642 | if (streaming->header.bmaControls == NULL) { |
642 | ret = -ENOMEM; | 643 | ret = -ENOMEM; |
643 | goto error; | 644 | goto error; |
644 | } | 645 | } |
645 | 646 | ||
646 | memcpy(streaming->header.bmaControls, &buffer[size], p*n); | ||
647 | |||
648 | buflen -= buffer[0]; | 647 | buflen -= buffer[0]; |
649 | buffer += buffer[0]; | 648 | buffer += buffer[0]; |
650 | 649 | ||
@@ -2174,6 +2173,15 @@ static struct usb_device_id uvc_ids[] = { | |||
2174 | .bInterfaceSubClass = 1, | 2173 | .bInterfaceSubClass = 1, |
2175 | .bInterfaceProtocol = 0, | 2174 | .bInterfaceProtocol = 0, |
2176 | .driver_info = UVC_QUIRK_PROBE_EXTRAFIELDS }, | 2175 | .driver_info = UVC_QUIRK_PROBE_EXTRAFIELDS }, |
2176 | /* Manta MM-353 Plako */ | ||
2177 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
2178 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
2179 | .idVendor = 0x18ec, | ||
2180 | .idProduct = 0x3188, | ||
2181 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
2182 | .bInterfaceSubClass = 1, | ||
2183 | .bInterfaceProtocol = 0, | ||
2184 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
2177 | /* FSC WebCam V30S */ | 2185 | /* FSC WebCam V30S */ |
2178 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 2186 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
2179 | | USB_DEVICE_ID_MATCH_INT_INFO, | 2187 | | USB_DEVICE_ID_MATCH_INT_INFO, |
@@ -2261,6 +2269,7 @@ static int __init uvc_init(void) | |||
2261 | static void __exit uvc_cleanup(void) | 2269 | static void __exit uvc_cleanup(void) |
2262 | { | 2270 | { |
2263 | usb_deregister(&uvc_driver.driver); | 2271 | usb_deregister(&uvc_driver.driver); |
2272 | uvc_ctrl_cleanup(); | ||
2264 | } | 2273 | } |
2265 | 2274 | ||
2266 | module_init(uvc_init); | 2275 | module_init(uvc_init); |
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 7c9ab2933496..86db32697b80 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c | |||
@@ -29,6 +29,71 @@ | |||
29 | #include "uvcvideo.h" | 29 | #include "uvcvideo.h" |
30 | 30 | ||
31 | /* ------------------------------------------------------------------------ | 31 | /* ------------------------------------------------------------------------ |
32 | * UVC ioctls | ||
33 | */ | ||
34 | static int uvc_ioctl_ctrl_map(struct uvc_xu_control_mapping *xmap, int old) | ||
35 | { | ||
36 | struct uvc_control_mapping *map; | ||
37 | unsigned int size; | ||
38 | int ret; | ||
39 | |||
40 | map = kzalloc(sizeof *map, GFP_KERNEL); | ||
41 | if (map == NULL) | ||
42 | return -ENOMEM; | ||
43 | |||
44 | map->id = xmap->id; | ||
45 | memcpy(map->name, xmap->name, sizeof map->name); | ||
46 | memcpy(map->entity, xmap->entity, sizeof map->entity); | ||
47 | map->selector = xmap->selector; | ||
48 | map->size = xmap->size; | ||
49 | map->offset = xmap->offset; | ||
50 | map->v4l2_type = xmap->v4l2_type; | ||
51 | map->data_type = xmap->data_type; | ||
52 | |||
53 | switch (xmap->v4l2_type) { | ||
54 | case V4L2_CTRL_TYPE_INTEGER: | ||
55 | case V4L2_CTRL_TYPE_BOOLEAN: | ||
56 | case V4L2_CTRL_TYPE_BUTTON: | ||
57 | break; | ||
58 | |||
59 | case V4L2_CTRL_TYPE_MENU: | ||
60 | if (old) { | ||
61 | ret = -EINVAL; | ||
62 | goto done; | ||
63 | } | ||
64 | |||
65 | size = xmap->menu_count * sizeof(*map->menu_info); | ||
66 | map->menu_info = kmalloc(size, GFP_KERNEL); | ||
67 | if (map->menu_info == NULL) { | ||
68 | ret = -ENOMEM; | ||
69 | goto done; | ||
70 | } | ||
71 | |||
72 | if (copy_from_user(map->menu_info, xmap->menu_info, size)) { | ||
73 | ret = -EFAULT; | ||
74 | goto done; | ||
75 | } | ||
76 | |||
77 | map->menu_count = xmap->menu_count; | ||
78 | break; | ||
79 | |||
80 | default: | ||
81 | ret = -EINVAL; | ||
82 | goto done; | ||
83 | } | ||
84 | |||
85 | ret = uvc_ctrl_add_mapping(map); | ||
86 | |||
87 | done: | ||
88 | if (ret < 0) { | ||
89 | kfree(map->menu_info); | ||
90 | kfree(map); | ||
91 | } | ||
92 | |||
93 | return ret; | ||
94 | } | ||
95 | |||
96 | /* ------------------------------------------------------------------------ | ||
32 | * V4L2 interface | 97 | * V4L2 interface |
33 | */ | 98 | */ |
34 | 99 | ||
@@ -451,7 +516,7 @@ static int uvc_v4l2_open(struct file *file) | |||
451 | 516 | ||
452 | static int uvc_v4l2_release(struct file *file) | 517 | static int uvc_v4l2_release(struct file *file) |
453 | { | 518 | { |
454 | struct uvc_fh *handle = (struct uvc_fh *)file->private_data; | 519 | struct uvc_fh *handle = file->private_data; |
455 | struct uvc_streaming *stream = handle->stream; | 520 | struct uvc_streaming *stream = handle->stream; |
456 | 521 | ||
457 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n"); | 522 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n"); |
@@ -482,7 +547,7 @@ static int uvc_v4l2_release(struct file *file) | |||
482 | static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | 547 | static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) |
483 | { | 548 | { |
484 | struct video_device *vdev = video_devdata(file); | 549 | struct video_device *vdev = video_devdata(file); |
485 | struct uvc_fh *handle = (struct uvc_fh *)file->private_data; | 550 | struct uvc_fh *handle = file->private_data; |
486 | struct uvc_video_chain *chain = handle->chain; | 551 | struct uvc_video_chain *chain = handle->chain; |
487 | struct uvc_streaming *stream = handle->stream; | 552 | struct uvc_streaming *stream = handle->stream; |
488 | long ret = 0; | 553 | long ret = 0; |
@@ -963,6 +1028,9 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
963 | if (!capable(CAP_SYS_ADMIN)) | 1028 | if (!capable(CAP_SYS_ADMIN)) |
964 | return -EPERM; | 1029 | return -EPERM; |
965 | 1030 | ||
1031 | if (xinfo->size == 0) | ||
1032 | return -EINVAL; | ||
1033 | |||
966 | info = kzalloc(sizeof *info, GFP_KERNEL); | 1034 | info = kzalloc(sizeof *info, GFP_KERNEL); |
967 | if (info == NULL) | 1035 | if (info == NULL) |
968 | return -ENOMEM; | 1036 | return -ENOMEM; |
@@ -974,7 +1042,8 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
974 | info->flags = xinfo->flags; | 1042 | info->flags = xinfo->flags; |
975 | 1043 | ||
976 | info->flags |= UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | | 1044 | info->flags |= UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | |
977 | UVC_CONTROL_GET_RES | UVC_CONTROL_GET_DEF; | 1045 | UVC_CONTROL_GET_RES | UVC_CONTROL_GET_DEF | |
1046 | UVC_CONTROL_EXTENSION; | ||
978 | 1047 | ||
979 | ret = uvc_ctrl_add_info(info); | 1048 | ret = uvc_ctrl_add_info(info); |
980 | if (ret < 0) | 1049 | if (ret < 0) |
@@ -982,32 +1051,12 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
982 | break; | 1051 | break; |
983 | } | 1052 | } |
984 | 1053 | ||
1054 | case UVCIOC_CTRL_MAP_OLD: | ||
985 | case UVCIOC_CTRL_MAP: | 1055 | case UVCIOC_CTRL_MAP: |
986 | { | ||
987 | struct uvc_xu_control_mapping *xmap = arg; | ||
988 | struct uvc_control_mapping *map; | ||
989 | |||
990 | if (!capable(CAP_SYS_ADMIN)) | 1056 | if (!capable(CAP_SYS_ADMIN)) |
991 | return -EPERM; | 1057 | return -EPERM; |
992 | 1058 | ||
993 | map = kzalloc(sizeof *map, GFP_KERNEL); | 1059 | return uvc_ioctl_ctrl_map(arg, cmd == UVCIOC_CTRL_MAP_OLD); |
994 | if (map == NULL) | ||
995 | return -ENOMEM; | ||
996 | |||
997 | map->id = xmap->id; | ||
998 | memcpy(map->name, xmap->name, sizeof map->name); | ||
999 | memcpy(map->entity, xmap->entity, sizeof map->entity); | ||
1000 | map->selector = xmap->selector; | ||
1001 | map->size = xmap->size; | ||
1002 | map->offset = xmap->offset; | ||
1003 | map->v4l2_type = xmap->v4l2_type; | ||
1004 | map->data_type = xmap->data_type; | ||
1005 | |||
1006 | ret = uvc_ctrl_add_mapping(map); | ||
1007 | if (ret < 0) | ||
1008 | kfree(map); | ||
1009 | break; | ||
1010 | } | ||
1011 | 1060 | ||
1012 | case UVCIOC_CTRL_GET: | 1061 | case UVCIOC_CTRL_GET: |
1013 | return uvc_xu_ctrl_query(chain, arg, 0); | 1062 | return uvc_xu_ctrl_query(chain, arg, 0); |
@@ -1067,7 +1116,7 @@ static const struct vm_operations_struct uvc_vm_ops = { | |||
1067 | 1116 | ||
1068 | static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | 1117 | static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) |
1069 | { | 1118 | { |
1070 | struct uvc_fh *handle = (struct uvc_fh *)file->private_data; | 1119 | struct uvc_fh *handle = file->private_data; |
1071 | struct uvc_streaming *stream = handle->stream; | 1120 | struct uvc_streaming *stream = handle->stream; |
1072 | struct uvc_video_queue *queue = &stream->queue; | 1121 | struct uvc_video_queue *queue = &stream->queue; |
1073 | struct uvc_buffer *uninitialized_var(buffer); | 1122 | struct uvc_buffer *uninitialized_var(buffer); |
@@ -1122,7 +1171,7 @@ done: | |||
1122 | 1171 | ||
1123 | static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) | 1172 | static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) |
1124 | { | 1173 | { |
1125 | struct uvc_fh *handle = (struct uvc_fh *)file->private_data; | 1174 | struct uvc_fh *handle = file->private_data; |
1126 | struct uvc_streaming *stream = handle->stream; | 1175 | struct uvc_streaming *stream = handle->stream; |
1127 | 1176 | ||
1128 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n"); | 1177 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n"); |
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index d1f88406a5e7..ac272456fbfd 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h | |||
@@ -27,6 +27,8 @@ | |||
27 | #define UVC_CONTROL_RESTORE (1 << 6) | 27 | #define UVC_CONTROL_RESTORE (1 << 6) |
28 | /* Control can be updated by the camera. */ | 28 | /* Control can be updated by the camera. */ |
29 | #define UVC_CONTROL_AUTO_UPDATE (1 << 7) | 29 | #define UVC_CONTROL_AUTO_UPDATE (1 << 7) |
30 | /* Control is an extension unit control. */ | ||
31 | #define UVC_CONTROL_EXTENSION (1 << 8) | ||
30 | 32 | ||
31 | #define UVC_CONTROL_GET_RANGE (UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_MIN | \ | 33 | #define UVC_CONTROL_GET_RANGE (UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_MIN | \ |
32 | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | \ | 34 | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | \ |
@@ -40,6 +42,15 @@ struct uvc_xu_control_info { | |||
40 | __u32 flags; | 42 | __u32 flags; |
41 | }; | 43 | }; |
42 | 44 | ||
45 | struct uvc_menu_info { | ||
46 | __u32 value; | ||
47 | __u8 name[32]; | ||
48 | }; | ||
49 | |||
50 | struct uvc_xu_control_mapping_old { | ||
51 | __u8 reserved[64]; | ||
52 | }; | ||
53 | |||
43 | struct uvc_xu_control_mapping { | 54 | struct uvc_xu_control_mapping { |
44 | __u32 id; | 55 | __u32 id; |
45 | __u8 name[32]; | 56 | __u8 name[32]; |
@@ -50,6 +61,11 @@ struct uvc_xu_control_mapping { | |||
50 | __u8 offset; | 61 | __u8 offset; |
51 | enum v4l2_ctrl_type v4l2_type; | 62 | enum v4l2_ctrl_type v4l2_type; |
52 | __u32 data_type; | 63 | __u32 data_type; |
64 | |||
65 | struct uvc_menu_info __user *menu_info; | ||
66 | __u32 menu_count; | ||
67 | |||
68 | __u32 reserved[4]; | ||
53 | }; | 69 | }; |
54 | 70 | ||
55 | struct uvc_xu_control { | 71 | struct uvc_xu_control { |
@@ -60,6 +76,7 @@ struct uvc_xu_control { | |||
60 | }; | 76 | }; |
61 | 77 | ||
62 | #define UVCIOC_CTRL_ADD _IOW('U', 1, struct uvc_xu_control_info) | 78 | #define UVCIOC_CTRL_ADD _IOW('U', 1, struct uvc_xu_control_info) |
79 | #define UVCIOC_CTRL_MAP_OLD _IOWR('U', 2, struct uvc_xu_control_mapping_old) | ||
63 | #define UVCIOC_CTRL_MAP _IOWR('U', 2, struct uvc_xu_control_mapping) | 80 | #define UVCIOC_CTRL_MAP _IOWR('U', 2, struct uvc_xu_control_mapping) |
64 | #define UVCIOC_CTRL_GET _IOWR('U', 3, struct uvc_xu_control) | 81 | #define UVCIOC_CTRL_GET _IOWR('U', 3, struct uvc_xu_control) |
65 | #define UVCIOC_CTRL_SET _IOW('U', 4, struct uvc_xu_control) | 82 | #define UVCIOC_CTRL_SET _IOW('U', 4, struct uvc_xu_control) |
@@ -179,30 +196,6 @@ struct uvc_device; | |||
179 | /* TODO: Put the most frequently accessed fields at the beginning of | 196 | /* TODO: Put the most frequently accessed fields at the beginning of |
180 | * structures to maximize cache efficiency. | 197 | * structures to maximize cache efficiency. |
181 | */ | 198 | */ |
182 | struct uvc_streaming_control { | ||
183 | __u16 bmHint; | ||
184 | __u8 bFormatIndex; | ||
185 | __u8 bFrameIndex; | ||
186 | __u32 dwFrameInterval; | ||
187 | __u16 wKeyFrameRate; | ||
188 | __u16 wPFrameRate; | ||
189 | __u16 wCompQuality; | ||
190 | __u16 wCompWindowSize; | ||
191 | __u16 wDelay; | ||
192 | __u32 dwMaxVideoFrameSize; | ||
193 | __u32 dwMaxPayloadTransferSize; | ||
194 | __u32 dwClockFrequency; | ||
195 | __u8 bmFramingInfo; | ||
196 | __u8 bPreferedVersion; | ||
197 | __u8 bMinVersion; | ||
198 | __u8 bMaxVersion; | ||
199 | }; | ||
200 | |||
201 | struct uvc_menu_info { | ||
202 | __u32 value; | ||
203 | __u8 name[32]; | ||
204 | }; | ||
205 | |||
206 | struct uvc_control_info { | 199 | struct uvc_control_info { |
207 | struct list_head list; | 200 | struct list_head list; |
208 | struct list_head mappings; | 201 | struct list_head mappings; |
@@ -250,7 +243,8 @@ struct uvc_control { | |||
250 | modified : 1, | 243 | modified : 1, |
251 | cached : 1; | 244 | cached : 1; |
252 | 245 | ||
253 | __u8 *data; | 246 | __u8 *uvc_data; |
247 | __u8 *uvc_info; | ||
254 | }; | 248 | }; |
255 | 249 | ||
256 | struct uvc_format_desc { | 250 | struct uvc_format_desc { |
@@ -625,6 +619,7 @@ extern int uvc_ctrl_init_device(struct uvc_device *dev); | |||
625 | extern void uvc_ctrl_cleanup_device(struct uvc_device *dev); | 619 | extern void uvc_ctrl_cleanup_device(struct uvc_device *dev); |
626 | extern int uvc_ctrl_resume_device(struct uvc_device *dev); | 620 | extern int uvc_ctrl_resume_device(struct uvc_device *dev); |
627 | extern void uvc_ctrl_init(void); | 621 | extern void uvc_ctrl_init(void); |
622 | extern void uvc_ctrl_cleanup(void); | ||
628 | 623 | ||
629 | extern int uvc_ctrl_begin(struct uvc_video_chain *chain); | 624 | extern int uvc_ctrl_begin(struct uvc_video_chain *chain); |
630 | extern int __uvc_ctrl_commit(struct uvc_video_chain *chain, int rollback); | 625 | extern int __uvc_ctrl_commit(struct uvc_video_chain *chain, int rollback); |
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 0ca7ec9ca902..9e89bf617790 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c | |||
@@ -410,7 +410,7 @@ static int __video_register_device(struct video_device *vdev, int type, int nr, | |||
410 | int minor_offset = 0; | 410 | int minor_offset = 0; |
411 | int minor_cnt = VIDEO_NUM_DEVICES; | 411 | int minor_cnt = VIDEO_NUM_DEVICES; |
412 | const char *name_base; | 412 | const char *name_base; |
413 | void *priv = video_get_drvdata(vdev); | 413 | void *priv = vdev->dev.p; |
414 | 414 | ||
415 | /* A minor value of -1 marks this video device as never | 415 | /* A minor value of -1 marks this video device as never |
416 | having been registered */ | 416 | having been registered */ |
@@ -536,9 +536,9 @@ static int __video_register_device(struct video_device *vdev, int type, int nr, | |||
536 | 536 | ||
537 | /* Part 4: register the device with sysfs */ | 537 | /* Part 4: register the device with sysfs */ |
538 | memset(&vdev->dev, 0, sizeof(vdev->dev)); | 538 | memset(&vdev->dev, 0, sizeof(vdev->dev)); |
539 | /* The memset above cleared the device's drvdata, so | 539 | /* The memset above cleared the device's device_private, so |
540 | put back the copy we made earlier. */ | 540 | put back the copy we made earlier. */ |
541 | video_set_drvdata(vdev, priv); | 541 | vdev->dev.p = priv; |
542 | vdev->dev.class = &video_class; | 542 | vdev->dev.class = &video_class; |
543 | vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor); | 543 | vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor); |
544 | if (vdev->parent) | 544 | if (vdev->parent) |
diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 7d3378437ded..ce1595bef629 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c | |||
@@ -52,18 +52,18 @@ MODULE_LICENSE("GPL"); | |||
52 | #define CALL(q, f, arg...) \ | 52 | #define CALL(q, f, arg...) \ |
53 | ((q->int_ops->f) ? q->int_ops->f(arg) : 0) | 53 | ((q->int_ops->f) ? q->int_ops->f(arg) : 0) |
54 | 54 | ||
55 | struct videobuf_buffer *videobuf_alloc(struct videobuf_queue *q) | 55 | struct videobuf_buffer *videobuf_alloc_vb(struct videobuf_queue *q) |
56 | { | 56 | { |
57 | struct videobuf_buffer *vb; | 57 | struct videobuf_buffer *vb; |
58 | 58 | ||
59 | BUG_ON(q->msize < sizeof(*vb)); | 59 | BUG_ON(q->msize < sizeof(*vb)); |
60 | 60 | ||
61 | if (!q->int_ops || !q->int_ops->alloc) { | 61 | if (!q->int_ops || !q->int_ops->alloc_vb) { |
62 | printk(KERN_ERR "No specific ops defined!\n"); | 62 | printk(KERN_ERR "No specific ops defined!\n"); |
63 | BUG(); | 63 | BUG(); |
64 | } | 64 | } |
65 | 65 | ||
66 | vb = q->int_ops->alloc(q->msize); | 66 | vb = q->int_ops->alloc_vb(q->msize); |
67 | if (NULL != vb) { | 67 | if (NULL != vb) { |
68 | init_waitqueue_head(&vb->done); | 68 | init_waitqueue_head(&vb->done); |
69 | vb->magic = MAGIC_BUFFER; | 69 | vb->magic = MAGIC_BUFFER; |
@@ -71,7 +71,7 @@ struct videobuf_buffer *videobuf_alloc(struct videobuf_queue *q) | |||
71 | 71 | ||
72 | return vb; | 72 | return vb; |
73 | } | 73 | } |
74 | EXPORT_SYMBOL_GPL(videobuf_alloc); | 74 | EXPORT_SYMBOL_GPL(videobuf_alloc_vb); |
75 | 75 | ||
76 | #define WAITON_CONDITION (vb->state != VIDEOBUF_ACTIVE &&\ | 76 | #define WAITON_CONDITION (vb->state != VIDEOBUF_ACTIVE &&\ |
77 | vb->state != VIDEOBUF_QUEUED) | 77 | vb->state != VIDEOBUF_QUEUED) |
@@ -195,6 +195,45 @@ int videobuf_queue_is_busy(struct videobuf_queue *q) | |||
195 | } | 195 | } |
196 | EXPORT_SYMBOL_GPL(videobuf_queue_is_busy); | 196 | EXPORT_SYMBOL_GPL(videobuf_queue_is_busy); |
197 | 197 | ||
198 | /** | ||
199 | * __videobuf_free() - free all the buffers and their control structures | ||
200 | * | ||
201 | * This function can only be called if streaming/reading is off, i.e. no buffers | ||
202 | * are under control of the driver. | ||
203 | */ | ||
204 | /* Locking: Caller holds q->vb_lock */ | ||
205 | static int __videobuf_free(struct videobuf_queue *q) | ||
206 | { | ||
207 | int i; | ||
208 | |||
209 | dprintk(1, "%s\n", __func__); | ||
210 | if (!q) | ||
211 | return 0; | ||
212 | |||
213 | if (q->streaming || q->reading) { | ||
214 | dprintk(1, "Cannot free buffers when streaming or reading\n"); | ||
215 | return -EBUSY; | ||
216 | } | ||
217 | |||
218 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); | ||
219 | |||
220 | for (i = 0; i < VIDEO_MAX_FRAME; i++) | ||
221 | if (q->bufs[i] && q->bufs[i]->map) { | ||
222 | dprintk(1, "Cannot free mmapped buffers\n"); | ||
223 | return -EBUSY; | ||
224 | } | ||
225 | |||
226 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | ||
227 | if (NULL == q->bufs[i]) | ||
228 | continue; | ||
229 | q->ops->buf_release(q, q->bufs[i]); | ||
230 | kfree(q->bufs[i]); | ||
231 | q->bufs[i] = NULL; | ||
232 | } | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | |||
198 | /* Locking: Caller holds q->vb_lock */ | 237 | /* Locking: Caller holds q->vb_lock */ |
199 | void videobuf_queue_cancel(struct videobuf_queue *q) | 238 | void videobuf_queue_cancel(struct videobuf_queue *q) |
200 | { | 239 | { |
@@ -308,36 +347,11 @@ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, | |||
308 | b->sequence = vb->field_count >> 1; | 347 | b->sequence = vb->field_count >> 1; |
309 | } | 348 | } |
310 | 349 | ||
311 | /* Locking: Caller holds q->vb_lock */ | ||
312 | static int __videobuf_mmap_free(struct videobuf_queue *q) | ||
313 | { | ||
314 | int i; | ||
315 | |||
316 | if (!q) | ||
317 | return 0; | ||
318 | |||
319 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); | ||
320 | |||
321 | for (i = 0; i < VIDEO_MAX_FRAME; i++) | ||
322 | if (q->bufs[i] && q->bufs[i]->map) | ||
323 | return -EBUSY; | ||
324 | |||
325 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | ||
326 | if (NULL == q->bufs[i]) | ||
327 | continue; | ||
328 | q->ops->buf_release(q, q->bufs[i]); | ||
329 | kfree(q->bufs[i]); | ||
330 | q->bufs[i] = NULL; | ||
331 | } | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | int videobuf_mmap_free(struct videobuf_queue *q) | 350 | int videobuf_mmap_free(struct videobuf_queue *q) |
337 | { | 351 | { |
338 | int ret; | 352 | int ret; |
339 | mutex_lock(&q->vb_lock); | 353 | mutex_lock(&q->vb_lock); |
340 | ret = __videobuf_mmap_free(q); | 354 | ret = __videobuf_free(q); |
341 | mutex_unlock(&q->vb_lock); | 355 | mutex_unlock(&q->vb_lock); |
342 | return ret; | 356 | return ret; |
343 | } | 357 | } |
@@ -353,13 +367,13 @@ int __videobuf_mmap_setup(struct videobuf_queue *q, | |||
353 | 367 | ||
354 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); | 368 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); |
355 | 369 | ||
356 | err = __videobuf_mmap_free(q); | 370 | err = __videobuf_free(q); |
357 | if (0 != err) | 371 | if (0 != err) |
358 | return err; | 372 | return err; |
359 | 373 | ||
360 | /* Allocate and initialize buffers */ | 374 | /* Allocate and initialize buffers */ |
361 | for (i = 0; i < bcount; i++) { | 375 | for (i = 0; i < bcount; i++) { |
362 | q->bufs[i] = videobuf_alloc(q); | 376 | q->bufs[i] = videobuf_alloc_vb(q); |
363 | 377 | ||
364 | if (NULL == q->bufs[i]) | 378 | if (NULL == q->bufs[i]) |
365 | break; | 379 | break; |
@@ -766,7 +780,7 @@ static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q, | |||
766 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); | 780 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); |
767 | 781 | ||
768 | /* setup stuff */ | 782 | /* setup stuff */ |
769 | q->read_buf = videobuf_alloc(q); | 783 | q->read_buf = videobuf_alloc_vb(q); |
770 | if (NULL == q->read_buf) | 784 | if (NULL == q->read_buf) |
771 | return -ENOMEM; | 785 | return -ENOMEM; |
772 | 786 | ||
@@ -871,7 +885,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, | |||
871 | if (NULL == q->read_buf) { | 885 | if (NULL == q->read_buf) { |
872 | /* need to capture a new frame */ | 886 | /* need to capture a new frame */ |
873 | retval = -ENOMEM; | 887 | retval = -ENOMEM; |
874 | q->read_buf = videobuf_alloc(q); | 888 | q->read_buf = videobuf_alloc_vb(q); |
875 | 889 | ||
876 | dprintk(1, "video alloc=0x%p\n", q->read_buf); | 890 | dprintk(1, "video alloc=0x%p\n", q->read_buf); |
877 | if (NULL == q->read_buf) | 891 | if (NULL == q->read_buf) |
@@ -970,7 +984,7 @@ static void __videobuf_read_stop(struct videobuf_queue *q) | |||
970 | int i; | 984 | int i; |
971 | 985 | ||
972 | videobuf_queue_cancel(q); | 986 | videobuf_queue_cancel(q); |
973 | __videobuf_mmap_free(q); | 987 | __videobuf_free(q); |
974 | INIT_LIST_HEAD(&q->stream); | 988 | INIT_LIST_HEAD(&q->stream); |
975 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | 989 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { |
976 | if (NULL == q->bufs[i]) | 990 | if (NULL == q->bufs[i]) |
diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c index 74730c624cfc..372b87efcd05 100644 --- a/drivers/media/video/videobuf-dma-contig.c +++ b/drivers/media/video/videobuf-dma-contig.c | |||
@@ -190,7 +190,7 @@ static int videobuf_dma_contig_user_get(struct videobuf_dma_contig_memory *mem, | |||
190 | return ret; | 190 | return ret; |
191 | } | 191 | } |
192 | 192 | ||
193 | static struct videobuf_buffer *__videobuf_alloc(size_t size) | 193 | static struct videobuf_buffer *__videobuf_alloc_vb(size_t size) |
194 | { | 194 | { |
195 | struct videobuf_dma_contig_memory *mem; | 195 | struct videobuf_dma_contig_memory *mem; |
196 | struct videobuf_buffer *vb; | 196 | struct videobuf_buffer *vb; |
@@ -280,8 +280,6 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, | |||
280 | return -ENOMEM; | 280 | return -ENOMEM; |
281 | 281 | ||
282 | buf->map = map; | 282 | buf->map = map; |
283 | map->start = vma->vm_start; | ||
284 | map->end = vma->vm_end; | ||
285 | map->q = q; | 283 | map->q = q; |
286 | 284 | ||
287 | buf->baddr = vma->vm_start; | 285 | buf->baddr = vma->vm_start; |
@@ -338,7 +336,7 @@ error: | |||
338 | static struct videobuf_qtype_ops qops = { | 336 | static struct videobuf_qtype_ops qops = { |
339 | .magic = MAGIC_QTYPE_OPS, | 337 | .magic = MAGIC_QTYPE_OPS, |
340 | 338 | ||
341 | .alloc = __videobuf_alloc, | 339 | .alloc_vb = __videobuf_alloc_vb, |
342 | .iolock = __videobuf_iolock, | 340 | .iolock = __videobuf_iolock, |
343 | .mmap_mapper = __videobuf_mmap_mapper, | 341 | .mmap_mapper = __videobuf_mmap_mapper, |
344 | .vaddr = __videobuf_to_vaddr, | 342 | .vaddr = __videobuf_to_vaddr, |
diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 8359e6badd36..06f9a9c2a39a 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c | |||
@@ -57,7 +57,13 @@ MODULE_LICENSE("GPL"); | |||
57 | 57 | ||
58 | /* --------------------------------------------------------------------- */ | 58 | /* --------------------------------------------------------------------- */ |
59 | 59 | ||
60 | struct scatterlist *videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages) | 60 | /* |
61 | * Return a scatterlist for some page-aligned vmalloc()'ed memory | ||
62 | * block (NULL on errors). Memory for the scatterlist is allocated | ||
63 | * using kmalloc. The caller must free the memory. | ||
64 | */ | ||
65 | static struct scatterlist *videobuf_vmalloc_to_sg(unsigned char *virt, | ||
66 | int nr_pages) | ||
61 | { | 67 | { |
62 | struct scatterlist *sglist; | 68 | struct scatterlist *sglist; |
63 | struct page *pg; | 69 | struct page *pg; |
@@ -81,10 +87,14 @@ err: | |||
81 | vfree(sglist); | 87 | vfree(sglist); |
82 | return NULL; | 88 | return NULL; |
83 | } | 89 | } |
84 | EXPORT_SYMBOL_GPL(videobuf_vmalloc_to_sg); | ||
85 | 90 | ||
86 | struct scatterlist *videobuf_pages_to_sg(struct page **pages, int nr_pages, | 91 | /* |
87 | int offset) | 92 | * Return a scatterlist for a an array of userpages (NULL on errors). |
93 | * Memory for the scatterlist is allocated using kmalloc. The caller | ||
94 | * must free the memory. | ||
95 | */ | ||
96 | static struct scatterlist *videobuf_pages_to_sg(struct page **pages, | ||
97 | int nr_pages, int offset) | ||
88 | { | 98 | { |
89 | struct scatterlist *sglist; | 99 | struct scatterlist *sglist; |
90 | int i; | 100 | int i; |
@@ -201,17 +211,17 @@ int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, | |||
201 | dprintk(1, "init kernel [%d pages]\n", nr_pages); | 211 | dprintk(1, "init kernel [%d pages]\n", nr_pages); |
202 | 212 | ||
203 | dma->direction = direction; | 213 | dma->direction = direction; |
204 | dma->vmalloc = vmalloc_32(nr_pages << PAGE_SHIFT); | 214 | dma->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT); |
205 | if (NULL == dma->vmalloc) { | 215 | if (NULL == dma->vaddr) { |
206 | dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages); | 216 | dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages); |
207 | return -ENOMEM; | 217 | return -ENOMEM; |
208 | } | 218 | } |
209 | 219 | ||
210 | dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n", | 220 | dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n", |
211 | (unsigned long)dma->vmalloc, | 221 | (unsigned long)dma->vaddr, |
212 | nr_pages << PAGE_SHIFT); | 222 | nr_pages << PAGE_SHIFT); |
213 | 223 | ||
214 | memset(dma->vmalloc, 0, nr_pages << PAGE_SHIFT); | 224 | memset(dma->vaddr, 0, nr_pages << PAGE_SHIFT); |
215 | dma->nr_pages = nr_pages; | 225 | dma->nr_pages = nr_pages; |
216 | 226 | ||
217 | return 0; | 227 | return 0; |
@@ -235,7 +245,7 @@ int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, | |||
235 | } | 245 | } |
236 | EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay); | 246 | EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay); |
237 | 247 | ||
238 | int videobuf_dma_map(struct videobuf_queue *q, struct videobuf_dmabuf *dma) | 248 | int videobuf_dma_map(struct device *dev, struct videobuf_dmabuf *dma) |
239 | { | 249 | { |
240 | MAGIC_CHECK(dma->magic, MAGIC_DMABUF); | 250 | MAGIC_CHECK(dma->magic, MAGIC_DMABUF); |
241 | BUG_ON(0 == dma->nr_pages); | 251 | BUG_ON(0 == dma->nr_pages); |
@@ -244,8 +254,8 @@ int videobuf_dma_map(struct videobuf_queue *q, struct videobuf_dmabuf *dma) | |||
244 | dma->sglist = videobuf_pages_to_sg(dma->pages, dma->nr_pages, | 254 | dma->sglist = videobuf_pages_to_sg(dma->pages, dma->nr_pages, |
245 | dma->offset); | 255 | dma->offset); |
246 | } | 256 | } |
247 | if (dma->vmalloc) { | 257 | if (dma->vaddr) { |
248 | dma->sglist = videobuf_vmalloc_to_sg(dma->vmalloc, | 258 | dma->sglist = videobuf_vmalloc_to_sg(dma->vaddr, |
249 | dma->nr_pages); | 259 | dma->nr_pages); |
250 | } | 260 | } |
251 | if (dma->bus_addr) { | 261 | if (dma->bus_addr) { |
@@ -263,7 +273,7 @@ int videobuf_dma_map(struct videobuf_queue *q, struct videobuf_dmabuf *dma) | |||
263 | return -ENOMEM; | 273 | return -ENOMEM; |
264 | } | 274 | } |
265 | if (!dma->bus_addr) { | 275 | if (!dma->bus_addr) { |
266 | dma->sglen = dma_map_sg(q->dev, dma->sglist, | 276 | dma->sglen = dma_map_sg(dev, dma->sglist, |
267 | dma->nr_pages, dma->direction); | 277 | dma->nr_pages, dma->direction); |
268 | if (0 == dma->sglen) { | 278 | if (0 == dma->sglen) { |
269 | printk(KERN_WARNING | 279 | printk(KERN_WARNING |
@@ -279,14 +289,14 @@ int videobuf_dma_map(struct videobuf_queue *q, struct videobuf_dmabuf *dma) | |||
279 | } | 289 | } |
280 | EXPORT_SYMBOL_GPL(videobuf_dma_map); | 290 | EXPORT_SYMBOL_GPL(videobuf_dma_map); |
281 | 291 | ||
282 | int videobuf_dma_unmap(struct videobuf_queue *q, struct videobuf_dmabuf *dma) | 292 | int videobuf_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma) |
283 | { | 293 | { |
284 | MAGIC_CHECK(dma->magic, MAGIC_DMABUF); | 294 | MAGIC_CHECK(dma->magic, MAGIC_DMABUF); |
285 | 295 | ||
286 | if (!dma->sglen) | 296 | if (!dma->sglen) |
287 | return 0; | 297 | return 0; |
288 | 298 | ||
289 | dma_unmap_sg(q->dev, dma->sglist, dma->sglen, dma->direction); | 299 | dma_unmap_sg(dev, dma->sglist, dma->sglen, dma->direction); |
290 | 300 | ||
291 | vfree(dma->sglist); | 301 | vfree(dma->sglist); |
292 | dma->sglist = NULL; | 302 | dma->sglist = NULL; |
@@ -309,8 +319,8 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma) | |||
309 | dma->pages = NULL; | 319 | dma->pages = NULL; |
310 | } | 320 | } |
311 | 321 | ||
312 | vfree(dma->vmalloc); | 322 | vfree(dma->vaddr); |
313 | dma->vmalloc = NULL; | 323 | dma->vaddr = NULL; |
314 | 324 | ||
315 | if (dma->bus_addr) | 325 | if (dma->bus_addr) |
316 | dma->bus_addr = 0; | 326 | dma->bus_addr = 0; |
@@ -322,28 +332,6 @@ EXPORT_SYMBOL_GPL(videobuf_dma_free); | |||
322 | 332 | ||
323 | /* --------------------------------------------------------------------- */ | 333 | /* --------------------------------------------------------------------- */ |
324 | 334 | ||
325 | int videobuf_sg_dma_map(struct device *dev, struct videobuf_dmabuf *dma) | ||
326 | { | ||
327 | struct videobuf_queue q; | ||
328 | |||
329 | q.dev = dev; | ||
330 | |||
331 | return videobuf_dma_map(&q, dma); | ||
332 | } | ||
333 | EXPORT_SYMBOL_GPL(videobuf_sg_dma_map); | ||
334 | |||
335 | int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma) | ||
336 | { | ||
337 | struct videobuf_queue q; | ||
338 | |||
339 | q.dev = dev; | ||
340 | |||
341 | return videobuf_dma_unmap(&q, dma); | ||
342 | } | ||
343 | EXPORT_SYMBOL_GPL(videobuf_sg_dma_unmap); | ||
344 | |||
345 | /* --------------------------------------------------------------------- */ | ||
346 | |||
347 | static void videobuf_vm_open(struct vm_area_struct *vma) | 335 | static void videobuf_vm_open(struct vm_area_struct *vma) |
348 | { | 336 | { |
349 | struct videobuf_mapping *map = vma->vm_private_data; | 337 | struct videobuf_mapping *map = vma->vm_private_data; |
@@ -428,7 +416,7 @@ static const struct vm_operations_struct videobuf_vm_ops = { | |||
428 | struct videobuf_dma_sg_memory | 416 | struct videobuf_dma_sg_memory |
429 | */ | 417 | */ |
430 | 418 | ||
431 | static struct videobuf_buffer *__videobuf_alloc(size_t size) | 419 | static struct videobuf_buffer *__videobuf_alloc_vb(size_t size) |
432 | { | 420 | { |
433 | struct videobuf_dma_sg_memory *mem; | 421 | struct videobuf_dma_sg_memory *mem; |
434 | struct videobuf_buffer *vb; | 422 | struct videobuf_buffer *vb; |
@@ -456,7 +444,7 @@ static void *__videobuf_to_vaddr(struct videobuf_buffer *buf) | |||
456 | 444 | ||
457 | MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); | 445 | MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); |
458 | 446 | ||
459 | return mem->dma.vmalloc; | 447 | return mem->dma.vaddr; |
460 | } | 448 | } |
461 | 449 | ||
462 | static int __videobuf_iolock(struct videobuf_queue *q, | 450 | static int __videobuf_iolock(struct videobuf_queue *q, |
@@ -520,7 +508,7 @@ static int __videobuf_iolock(struct videobuf_queue *q, | |||
520 | default: | 508 | default: |
521 | BUG(); | 509 | BUG(); |
522 | } | 510 | } |
523 | err = videobuf_dma_map(q, &mem->dma); | 511 | err = videobuf_dma_map(q->dev, &mem->dma); |
524 | if (0 != err) | 512 | if (0 != err) |
525 | return err; | 513 | return err; |
526 | 514 | ||
@@ -620,8 +608,6 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, | |||
620 | } | 608 | } |
621 | 609 | ||
622 | map->count = 1; | 610 | map->count = 1; |
623 | map->start = vma->vm_start; | ||
624 | map->end = vma->vm_end; | ||
625 | map->q = q; | 611 | map->q = q; |
626 | vma->vm_ops = &videobuf_vm_ops; | 612 | vma->vm_ops = &videobuf_vm_ops; |
627 | vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; | 613 | vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; |
@@ -638,7 +624,7 @@ done: | |||
638 | static struct videobuf_qtype_ops sg_ops = { | 624 | static struct videobuf_qtype_ops sg_ops = { |
639 | .magic = MAGIC_QTYPE_OPS, | 625 | .magic = MAGIC_QTYPE_OPS, |
640 | 626 | ||
641 | .alloc = __videobuf_alloc, | 627 | .alloc_vb = __videobuf_alloc_vb, |
642 | .iolock = __videobuf_iolock, | 628 | .iolock = __videobuf_iolock, |
643 | .sync = __videobuf_sync, | 629 | .sync = __videobuf_sync, |
644 | .mmap_mapper = __videobuf_mmap_mapper, | 630 | .mmap_mapper = __videobuf_mmap_mapper, |
@@ -654,7 +640,7 @@ void *videobuf_sg_alloc(size_t size) | |||
654 | 640 | ||
655 | q.msize = size; | 641 | q.msize = size; |
656 | 642 | ||
657 | return videobuf_alloc(&q); | 643 | return videobuf_alloc_vb(&q); |
658 | } | 644 | } |
659 | EXPORT_SYMBOL_GPL(videobuf_sg_alloc); | 645 | EXPORT_SYMBOL_GPL(videobuf_sg_alloc); |
660 | 646 | ||
diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index 583728f4c221..e7fe31d54f07 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c | |||
@@ -102,10 +102,10 @@ static void videobuf_vm_close(struct vm_area_struct *vma) | |||
102 | called with IRQ's disabled | 102 | called with IRQ's disabled |
103 | */ | 103 | */ |
104 | dprintk(1, "%s: buf[%d] freeing (%p)\n", | 104 | dprintk(1, "%s: buf[%d] freeing (%p)\n", |
105 | __func__, i, mem->vmalloc); | 105 | __func__, i, mem->vaddr); |
106 | 106 | ||
107 | vfree(mem->vmalloc); | 107 | vfree(mem->vaddr); |
108 | mem->vmalloc = NULL; | 108 | mem->vaddr = NULL; |
109 | } | 109 | } |
110 | 110 | ||
111 | q->bufs[i]->map = NULL; | 111 | q->bufs[i]->map = NULL; |
@@ -135,7 +135,7 @@ static const struct vm_operations_struct videobuf_vm_ops = { | |||
135 | struct videobuf_dma_sg_memory | 135 | struct videobuf_dma_sg_memory |
136 | */ | 136 | */ |
137 | 137 | ||
138 | static struct videobuf_buffer *__videobuf_alloc(size_t size) | 138 | static struct videobuf_buffer *__videobuf_alloc_vb(size_t size) |
139 | { | 139 | { |
140 | struct videobuf_vmalloc_memory *mem; | 140 | struct videobuf_vmalloc_memory *mem; |
141 | struct videobuf_buffer *vb; | 141 | struct videobuf_buffer *vb; |
@@ -170,7 +170,7 @@ static int __videobuf_iolock(struct videobuf_queue *q, | |||
170 | dprintk(1, "%s memory method MMAP\n", __func__); | 170 | dprintk(1, "%s memory method MMAP\n", __func__); |
171 | 171 | ||
172 | /* All handling should be done by __videobuf_mmap_mapper() */ | 172 | /* All handling should be done by __videobuf_mmap_mapper() */ |
173 | if (!mem->vmalloc) { | 173 | if (!mem->vaddr) { |
174 | printk(KERN_ERR "memory is not alloced/mmapped.\n"); | 174 | printk(KERN_ERR "memory is not alloced/mmapped.\n"); |
175 | return -EINVAL; | 175 | return -EINVAL; |
176 | } | 176 | } |
@@ -189,13 +189,13 @@ static int __videobuf_iolock(struct videobuf_queue *q, | |||
189 | * read() method. | 189 | * read() method. |
190 | */ | 190 | */ |
191 | 191 | ||
192 | mem->vmalloc = vmalloc_user(pages); | 192 | mem->vaddr = vmalloc_user(pages); |
193 | if (!mem->vmalloc) { | 193 | if (!mem->vaddr) { |
194 | printk(KERN_ERR "vmalloc (%d pages) failed\n", pages); | 194 | printk(KERN_ERR "vmalloc (%d pages) failed\n", pages); |
195 | return -ENOMEM; | 195 | return -ENOMEM; |
196 | } | 196 | } |
197 | dprintk(1, "vmalloc is at addr %p (%d pages)\n", | 197 | dprintk(1, "vmalloc is at addr %p (%d pages)\n", |
198 | mem->vmalloc, pages); | 198 | mem->vaddr, pages); |
199 | 199 | ||
200 | #if 0 | 200 | #if 0 |
201 | int rc; | 201 | int rc; |
@@ -245,8 +245,6 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, | |||
245 | return -ENOMEM; | 245 | return -ENOMEM; |
246 | 246 | ||
247 | buf->map = map; | 247 | buf->map = map; |
248 | map->start = vma->vm_start; | ||
249 | map->end = vma->vm_end; | ||
250 | map->q = q; | 248 | map->q = q; |
251 | 249 | ||
252 | buf->baddr = vma->vm_start; | 250 | buf->baddr = vma->vm_start; |
@@ -256,18 +254,18 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, | |||
256 | MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); | 254 | MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); |
257 | 255 | ||
258 | pages = PAGE_ALIGN(vma->vm_end - vma->vm_start); | 256 | pages = PAGE_ALIGN(vma->vm_end - vma->vm_start); |
259 | mem->vmalloc = vmalloc_user(pages); | 257 | mem->vaddr = vmalloc_user(pages); |
260 | if (!mem->vmalloc) { | 258 | if (!mem->vaddr) { |
261 | printk(KERN_ERR "vmalloc (%d pages) failed\n", pages); | 259 | printk(KERN_ERR "vmalloc (%d pages) failed\n", pages); |
262 | goto error; | 260 | goto error; |
263 | } | 261 | } |
264 | dprintk(1, "vmalloc is at addr %p (%d pages)\n", mem->vmalloc, pages); | 262 | dprintk(1, "vmalloc is at addr %p (%d pages)\n", mem->vaddr, pages); |
265 | 263 | ||
266 | /* Try to remap memory */ | 264 | /* Try to remap memory */ |
267 | retval = remap_vmalloc_range(vma, mem->vmalloc, 0); | 265 | retval = remap_vmalloc_range(vma, mem->vaddr, 0); |
268 | if (retval < 0) { | 266 | if (retval < 0) { |
269 | printk(KERN_ERR "mmap: remap failed with error %d. ", retval); | 267 | printk(KERN_ERR "mmap: remap failed with error %d. ", retval); |
270 | vfree(mem->vmalloc); | 268 | vfree(mem->vaddr); |
271 | goto error; | 269 | goto error; |
272 | } | 270 | } |
273 | 271 | ||
@@ -293,7 +291,7 @@ error: | |||
293 | static struct videobuf_qtype_ops qops = { | 291 | static struct videobuf_qtype_ops qops = { |
294 | .magic = MAGIC_QTYPE_OPS, | 292 | .magic = MAGIC_QTYPE_OPS, |
295 | 293 | ||
296 | .alloc = __videobuf_alloc, | 294 | .alloc_vb = __videobuf_alloc_vb, |
297 | .iolock = __videobuf_iolock, | 295 | .iolock = __videobuf_iolock, |
298 | .mmap_mapper = __videobuf_mmap_mapper, | 296 | .mmap_mapper = __videobuf_mmap_mapper, |
299 | .vaddr = videobuf_to_vmalloc, | 297 | .vaddr = videobuf_to_vmalloc, |
@@ -319,7 +317,7 @@ void *videobuf_to_vmalloc(struct videobuf_buffer *buf) | |||
319 | BUG_ON(!mem); | 317 | BUG_ON(!mem); |
320 | MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); | 318 | MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); |
321 | 319 | ||
322 | return mem->vmalloc; | 320 | return mem->vaddr; |
323 | } | 321 | } |
324 | EXPORT_SYMBOL_GPL(videobuf_to_vmalloc); | 322 | EXPORT_SYMBOL_GPL(videobuf_to_vmalloc); |
325 | 323 | ||
@@ -341,8 +339,8 @@ void videobuf_vmalloc_free(struct videobuf_buffer *buf) | |||
341 | 339 | ||
342 | MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); | 340 | MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); |
343 | 341 | ||
344 | vfree(mem->vmalloc); | 342 | vfree(mem->vaddr); |
345 | mem->vmalloc = NULL; | 343 | mem->vaddr = NULL; |
346 | 344 | ||
347 | return; | 345 | return; |
348 | } | 346 | } |
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c deleted file mode 100644 index d807eea91757..000000000000 --- a/drivers/media/video/w9968cf.c +++ /dev/null | |||
@@ -1,3620 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * Video4Linux driver for W996[87]CF JPEG USB Dual Mode Camera Chip. * | ||
3 | * * | ||
4 | * Copyright (C) 2002-2004 by Luca Risolia <luca.risolia@studio.unibo.it> * | ||
5 | * * | ||
6 | * - Memory management code from bttv driver by Ralph Metzler, * | ||
7 | * Marcus Metzler and Gerd Knorr. * | ||
8 | * - I2C interface to kernel, high-level image sensor control routines and * | ||
9 | * some symbolic names from OV511 driver by Mark W. McClelland. * | ||
10 | * - Low-level I2C fast write function by Piotr Czerczak. * | ||
11 | * - Low-level I2C read function by Frederic Jouault. * | ||
12 | * * | ||
13 | * This program is free software; you can redistribute it and/or modify * | ||
14 | * it under the terms of the GNU General Public License as published by * | ||
15 | * the Free Software Foundation; either version 2 of the License, or * | ||
16 | * (at your option) any later version. * | ||
17 | * * | ||
18 | * This program is distributed in the hope that it will be useful, * | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
21 | * GNU General Public License for more details. * | ||
22 | * * | ||
23 | * You should have received a copy of the GNU General Public License * | ||
24 | * along with this program; if not, write to the Free Software * | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * | ||
26 | ***************************************************************************/ | ||
27 | |||
28 | #include <linux/module.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/kmod.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/fs.h> | ||
33 | #include <linux/vmalloc.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/mm.h> | ||
36 | #include <linux/string.h> | ||
37 | #include <linux/errno.h> | ||
38 | #include <linux/sched.h> | ||
39 | #include <linux/ioctl.h> | ||
40 | #include <linux/delay.h> | ||
41 | #include <linux/stddef.h> | ||
42 | #include <asm/page.h> | ||
43 | #include <asm/uaccess.h> | ||
44 | #include <linux/page-flags.h> | ||
45 | #include <linux/videodev.h> | ||
46 | #include <media/v4l2-ioctl.h> | ||
47 | |||
48 | #include "w9968cf.h" | ||
49 | #include "w9968cf_decoder.h" | ||
50 | |||
51 | static struct w9968cf_vpp_t* w9968cf_vpp; | ||
52 | static DECLARE_WAIT_QUEUE_HEAD(w9968cf_vppmod_wait); | ||
53 | |||
54 | static LIST_HEAD(w9968cf_dev_list); /* head of V4L registered cameras list */ | ||
55 | static DEFINE_MUTEX(w9968cf_devlist_mutex); /* semaphore for list traversal */ | ||
56 | |||
57 | static DECLARE_RWSEM(w9968cf_disconnect); /* prevent races with open() */ | ||
58 | |||
59 | |||
60 | /**************************************************************************** | ||
61 | * Module macros and parameters * | ||
62 | ****************************************************************************/ | ||
63 | |||
64 | MODULE_DEVICE_TABLE(usb, winbond_id_table); | ||
65 | |||
66 | MODULE_AUTHOR(W9968CF_MODULE_AUTHOR" "W9968CF_AUTHOR_EMAIL); | ||
67 | MODULE_DESCRIPTION(W9968CF_MODULE_NAME); | ||
68 | MODULE_VERSION(W9968CF_MODULE_VERSION); | ||
69 | MODULE_LICENSE(W9968CF_MODULE_LICENSE); | ||
70 | MODULE_SUPPORTED_DEVICE("Video"); | ||
71 | |||
72 | static unsigned short simcams = W9968CF_SIMCAMS; | ||
73 | static short video_nr[]={[0 ... W9968CF_MAX_DEVICES-1] = -1}; /*-1=first free*/ | ||
74 | static unsigned int packet_size[] = {[0 ... W9968CF_MAX_DEVICES-1] = | ||
75 | W9968CF_PACKET_SIZE}; | ||
76 | static unsigned short max_buffers[] = {[0 ... W9968CF_MAX_DEVICES-1] = | ||
77 | W9968CF_BUFFERS}; | ||
78 | static int double_buffer[] = {[0 ... W9968CF_MAX_DEVICES-1] = | ||
79 | W9968CF_DOUBLE_BUFFER}; | ||
80 | static int clamping[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_CLAMPING}; | ||
81 | static unsigned short filter_type[]= {[0 ... W9968CF_MAX_DEVICES-1] = | ||
82 | W9968CF_FILTER_TYPE}; | ||
83 | static int largeview[]= {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_LARGEVIEW}; | ||
84 | static unsigned short decompression[] = {[0 ... W9968CF_MAX_DEVICES-1] = | ||
85 | W9968CF_DECOMPRESSION}; | ||
86 | static int upscaling[]= {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_UPSCALING}; | ||
87 | static unsigned short force_palette[] = {[0 ... W9968CF_MAX_DEVICES-1] = 0}; | ||
88 | static int force_rgb[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_FORCE_RGB}; | ||
89 | static int autobright[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_AUTOBRIGHT}; | ||
90 | static int autoexp[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_AUTOEXP}; | ||
91 | static unsigned short lightfreq[] = {[0 ... W9968CF_MAX_DEVICES-1] = | ||
92 | W9968CF_LIGHTFREQ}; | ||
93 | static int bandingfilter[] = {[0 ... W9968CF_MAX_DEVICES-1]= | ||
94 | W9968CF_BANDINGFILTER}; | ||
95 | static short clockdiv[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_CLOCKDIV}; | ||
96 | static int backlight[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_BACKLIGHT}; | ||
97 | static int mirror[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_MIRROR}; | ||
98 | static int monochrome[] = {[0 ... W9968CF_MAX_DEVICES-1]=W9968CF_MONOCHROME}; | ||
99 | static unsigned int brightness[] = {[0 ... W9968CF_MAX_DEVICES-1] = | ||
100 | W9968CF_BRIGHTNESS}; | ||
101 | static unsigned int hue[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_HUE}; | ||
102 | static unsigned int colour[]={[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_COLOUR}; | ||
103 | static unsigned int contrast[] = {[0 ... W9968CF_MAX_DEVICES-1] = | ||
104 | W9968CF_CONTRAST}; | ||
105 | static unsigned int whiteness[] = {[0 ... W9968CF_MAX_DEVICES-1] = | ||
106 | W9968CF_WHITENESS}; | ||
107 | #ifdef W9968CF_DEBUG | ||
108 | static unsigned short debug = W9968CF_DEBUG_LEVEL; | ||
109 | static int specific_debug = W9968CF_SPECIFIC_DEBUG; | ||
110 | #endif | ||
111 | |||
112 | static unsigned int param_nv[24]; /* number of values per parameter */ | ||
113 | |||
114 | module_param(simcams, ushort, 0644); | ||
115 | module_param_array(video_nr, short, ¶m_nv[0], 0444); | ||
116 | module_param_array(packet_size, uint, ¶m_nv[1], 0444); | ||
117 | module_param_array(max_buffers, ushort, ¶m_nv[2], 0444); | ||
118 | module_param_array(double_buffer, bool, ¶m_nv[3], 0444); | ||
119 | module_param_array(clamping, bool, ¶m_nv[4], 0444); | ||
120 | module_param_array(filter_type, ushort, ¶m_nv[5], 0444); | ||
121 | module_param_array(largeview, bool, ¶m_nv[6], 0444); | ||
122 | module_param_array(decompression, ushort, ¶m_nv[7], 0444); | ||
123 | module_param_array(upscaling, bool, ¶m_nv[8], 0444); | ||
124 | module_param_array(force_palette, ushort, ¶m_nv[9], 0444); | ||
125 | module_param_array(force_rgb, ushort, ¶m_nv[10], 0444); | ||
126 | module_param_array(autobright, bool, ¶m_nv[11], 0444); | ||
127 | module_param_array(autoexp, bool, ¶m_nv[12], 0444); | ||
128 | module_param_array(lightfreq, ushort, ¶m_nv[13], 0444); | ||
129 | module_param_array(bandingfilter, bool, ¶m_nv[14], 0444); | ||
130 | module_param_array(clockdiv, short, ¶m_nv[15], 0444); | ||
131 | module_param_array(backlight, bool, ¶m_nv[16], 0444); | ||
132 | module_param_array(mirror, bool, ¶m_nv[17], 0444); | ||
133 | module_param_array(monochrome, bool, ¶m_nv[18], 0444); | ||
134 | module_param_array(brightness, uint, ¶m_nv[19], 0444); | ||
135 | module_param_array(hue, uint, ¶m_nv[20], 0444); | ||
136 | module_param_array(colour, uint, ¶m_nv[21], 0444); | ||
137 | module_param_array(contrast, uint, ¶m_nv[22], 0444); | ||
138 | module_param_array(whiteness, uint, ¶m_nv[23], 0444); | ||
139 | #ifdef W9968CF_DEBUG | ||
140 | module_param(debug, ushort, 0644); | ||
141 | module_param(specific_debug, bool, 0644); | ||
142 | #endif | ||
143 | |||
144 | MODULE_PARM_DESC(simcams, | ||
145 | "\n<n> Number of cameras allowed to stream simultaneously." | ||
146 | "\nn may vary from 0 to " | ||
147 | __MODULE_STRING(W9968CF_MAX_DEVICES)"." | ||
148 | "\nDefault value is "__MODULE_STRING(W9968CF_SIMCAMS)"." | ||
149 | "\n"); | ||
150 | MODULE_PARM_DESC(video_nr, | ||
151 | "\n<-1|n[,...]> Specify V4L minor mode number." | ||
152 | "\n -1 = use next available (default)" | ||
153 | "\n n = use minor number n (integer >= 0)" | ||
154 | "\nYou can specify up to "__MODULE_STRING(W9968CF_MAX_DEVICES) | ||
155 | " cameras this way." | ||
156 | "\nFor example:" | ||
157 | "\nvideo_nr=-1,2,-1 would assign minor number 2 to" | ||
158 | "\nthe second camera and use auto for the first" | ||
159 | "\none and for every other camera." | ||
160 | "\n"); | ||
161 | MODULE_PARM_DESC(packet_size, | ||
162 | "\n<n[,...]> Specify the maximum data payload" | ||
163 | "\nsize in bytes for alternate settings, for each device." | ||
164 | "\nn is scaled between 63 and 1023 " | ||
165 | "(default is "__MODULE_STRING(W9968CF_PACKET_SIZE)")." | ||
166 | "\n"); | ||
167 | MODULE_PARM_DESC(max_buffers, | ||
168 | "\n<n[,...]> For advanced users." | ||
169 | "\nSpecify the maximum number of video frame buffers" | ||
170 | "\nto allocate for each device, from 2 to " | ||
171 | __MODULE_STRING(W9968CF_MAX_BUFFERS) | ||
172 | ". (default is "__MODULE_STRING(W9968CF_BUFFERS)")." | ||
173 | "\n"); | ||
174 | MODULE_PARM_DESC(double_buffer, | ||
175 | "\n<0|1[,...]> " | ||
176 | "Hardware double buffering: 0 disabled, 1 enabled." | ||
177 | "\nIt should be enabled if you want smooth video output: if" | ||
178 | "\nyou obtain out of sync. video, disable it, or try to" | ||
179 | "\ndecrease the 'clockdiv' module parameter value." | ||
180 | "\nDefault value is "__MODULE_STRING(W9968CF_DOUBLE_BUFFER) | ||
181 | " for every device." | ||
182 | "\n"); | ||
183 | MODULE_PARM_DESC(clamping, | ||
184 | "\n<0|1[,...]> Video data clamping: 0 disabled, 1 enabled." | ||
185 | "\nDefault value is "__MODULE_STRING(W9968CF_CLAMPING) | ||
186 | " for every device." | ||
187 | "\n"); | ||
188 | MODULE_PARM_DESC(filter_type, | ||
189 | "\n<0|1|2[,...]> Video filter type." | ||
190 | "\n0 none, 1 (1-2-1) 3-tap filter, " | ||
191 | "2 (2-3-6-3-2) 5-tap filter." | ||
192 | "\nDefault value is "__MODULE_STRING(W9968CF_FILTER_TYPE) | ||
193 | " for every device." | ||
194 | "\nThe filter is used to reduce noise and aliasing artifacts" | ||
195 | "\nproduced by the CCD or CMOS image sensor, and the scaling" | ||
196 | " process." | ||
197 | "\n"); | ||
198 | MODULE_PARM_DESC(largeview, | ||
199 | "\n<0|1[,...]> Large view: 0 disabled, 1 enabled." | ||
200 | "\nDefault value is "__MODULE_STRING(W9968CF_LARGEVIEW) | ||
201 | " for every device." | ||
202 | "\n"); | ||
203 | MODULE_PARM_DESC(upscaling, | ||
204 | "\n<0|1[,...]> Software scaling (for non-compressed video):" | ||
205 | "\n0 disabled, 1 enabled." | ||
206 | "\nDisable it if you have a slow CPU or you don't have" | ||
207 | " enough memory." | ||
208 | "\nDefault value is "__MODULE_STRING(W9968CF_UPSCALING) | ||
209 | " for every device." | ||
210 | "\nIf 'w9968cf-vpp' is not present, this parameter is" | ||
211 | " set to 0." | ||
212 | "\n"); | ||
213 | MODULE_PARM_DESC(decompression, | ||
214 | "\n<0|1|2[,...]> Software video decompression:" | ||
215 | "\n- 0 disables decompression (doesn't allow formats needing" | ||
216 | " decompression)" | ||
217 | "\n- 1 forces decompression (allows formats needing" | ||
218 | " decompression only);" | ||
219 | "\n- 2 allows any permitted formats." | ||
220 | "\nFormats supporting compressed video are YUV422P and" | ||
221 | " YUV420P/YUV420 " | ||
222 | "\nin any resolutions where both width and height are " | ||
223 | "a multiple of 16." | ||
224 | "\nDefault value is "__MODULE_STRING(W9968CF_DECOMPRESSION) | ||
225 | " for every device." | ||
226 | "\nIf 'w9968cf-vpp' is not present, forcing decompression is " | ||
227 | "\nnot allowed; in this case this parameter is set to 2." | ||
228 | "\n"); | ||
229 | MODULE_PARM_DESC(force_palette, | ||
230 | "\n<0" | ||
231 | "|" __MODULE_STRING(VIDEO_PALETTE_UYVY) | ||
232 | "|" __MODULE_STRING(VIDEO_PALETTE_YUV420) | ||
233 | "|" __MODULE_STRING(VIDEO_PALETTE_YUV422P) | ||
234 | "|" __MODULE_STRING(VIDEO_PALETTE_YUV420P) | ||
235 | "|" __MODULE_STRING(VIDEO_PALETTE_YUYV) | ||
236 | "|" __MODULE_STRING(VIDEO_PALETTE_YUV422) | ||
237 | "|" __MODULE_STRING(VIDEO_PALETTE_GREY) | ||
238 | "|" __MODULE_STRING(VIDEO_PALETTE_RGB555) | ||
239 | "|" __MODULE_STRING(VIDEO_PALETTE_RGB565) | ||
240 | "|" __MODULE_STRING(VIDEO_PALETTE_RGB24) | ||
241 | "|" __MODULE_STRING(VIDEO_PALETTE_RGB32) | ||
242 | "[,...]>" | ||
243 | " Force picture palette." | ||
244 | "\nIn order:" | ||
245 | "\n- 0 allows any of the following formats:" | ||
246 | "\n- UYVY 16 bpp - Original video, compression disabled" | ||
247 | "\n- YUV420 12 bpp - Original video, compression enabled" | ||
248 | "\n- YUV422P 16 bpp - Original video, compression enabled" | ||
249 | "\n- YUV420P 12 bpp - Original video, compression enabled" | ||
250 | "\n- YUVY 16 bpp - Software conversion from UYVY" | ||
251 | "\n- YUV422 16 bpp - Software conversion from UYVY" | ||
252 | "\n- GREY 8 bpp - Software conversion from UYVY" | ||
253 | "\n- RGB555 16 bpp - Software conversion from UYVY" | ||
254 | "\n- RGB565 16 bpp - Software conversion from UYVY" | ||
255 | "\n- RGB24 24 bpp - Software conversion from UYVY" | ||
256 | "\n- RGB32 32 bpp - Software conversion from UYVY" | ||
257 | "\nWhen not 0, this parameter will override 'decompression'." | ||
258 | "\nDefault value is 0 for every device." | ||
259 | "\nInitial palette is " | ||
260 | __MODULE_STRING(W9968CF_PALETTE_DECOMP_ON)"." | ||
261 | "\nIf 'w9968cf-vpp' is not present, this parameter is" | ||
262 | " set to 9 (UYVY)." | ||
263 | "\n"); | ||
264 | MODULE_PARM_DESC(force_rgb, | ||
265 | "\n<0|1[,...]> Read RGB video data instead of BGR:" | ||
266 | "\n 1 = use RGB component ordering." | ||
267 | "\n 0 = use BGR component ordering." | ||
268 | "\nThis parameter has effect when using RGBX palettes only." | ||
269 | "\nDefault value is "__MODULE_STRING(W9968CF_FORCE_RGB) | ||
270 | " for every device." | ||
271 | "\n"); | ||
272 | MODULE_PARM_DESC(autobright, | ||
273 | "\n<0|1[,...]> Image sensor automatically changes brightness:" | ||
274 | "\n 0 = no, 1 = yes" | ||
275 | "\nDefault value is "__MODULE_STRING(W9968CF_AUTOBRIGHT) | ||
276 | " for every device." | ||
277 | "\n"); | ||
278 | MODULE_PARM_DESC(autoexp, | ||
279 | "\n<0|1[,...]> Image sensor automatically changes exposure:" | ||
280 | "\n 0 = no, 1 = yes" | ||
281 | "\nDefault value is "__MODULE_STRING(W9968CF_AUTOEXP) | ||
282 | " for every device." | ||
283 | "\n"); | ||
284 | MODULE_PARM_DESC(lightfreq, | ||
285 | "\n<50|60[,...]> Light frequency in Hz:" | ||
286 | "\n 50 for European and Asian lighting," | ||
287 | " 60 for American lighting." | ||
288 | "\nDefault value is "__MODULE_STRING(W9968CF_LIGHTFREQ) | ||
289 | " for every device." | ||
290 | "\n"); | ||
291 | MODULE_PARM_DESC(bandingfilter, | ||
292 | "\n<0|1[,...]> Banding filter to reduce effects of" | ||
293 | " fluorescent lighting:" | ||
294 | "\n 0 disabled, 1 enabled." | ||
295 | "\nThis filter tries to reduce the pattern of horizontal" | ||
296 | "\nlight/dark bands caused by some (usually fluorescent)" | ||
297 | " lighting." | ||
298 | "\nDefault value is "__MODULE_STRING(W9968CF_BANDINGFILTER) | ||
299 | " for every device." | ||
300 | "\n"); | ||
301 | MODULE_PARM_DESC(clockdiv, | ||
302 | "\n<-1|n[,...]> " | ||
303 | "Force pixel clock divisor to a specific value (for experts):" | ||
304 | "\n n may vary from 0 to 127." | ||
305 | "\n -1 for automatic value." | ||
306 | "\nSee also the 'double_buffer' module parameter." | ||
307 | "\nDefault value is "__MODULE_STRING(W9968CF_CLOCKDIV) | ||
308 | " for every device." | ||
309 | "\n"); | ||
310 | MODULE_PARM_DESC(backlight, | ||
311 | "\n<0|1[,...]> Objects are lit from behind:" | ||
312 | "\n 0 = no, 1 = yes" | ||
313 | "\nDefault value is "__MODULE_STRING(W9968CF_BACKLIGHT) | ||
314 | " for every device." | ||
315 | "\n"); | ||
316 | MODULE_PARM_DESC(mirror, | ||
317 | "\n<0|1[,...]> Reverse image horizontally:" | ||
318 | "\n 0 = no, 1 = yes" | ||
319 | "\nDefault value is "__MODULE_STRING(W9968CF_MIRROR) | ||
320 | " for every device." | ||
321 | "\n"); | ||
322 | MODULE_PARM_DESC(monochrome, | ||
323 | "\n<0|1[,...]> Use image sensor as monochrome sensor:" | ||
324 | "\n 0 = no, 1 = yes" | ||
325 | "\nNot all the sensors support monochrome color." | ||
326 | "\nDefault value is "__MODULE_STRING(W9968CF_MONOCHROME) | ||
327 | " for every device." | ||
328 | "\n"); | ||
329 | MODULE_PARM_DESC(brightness, | ||
330 | "\n<n[,...]> Set picture brightness (0-65535)." | ||
331 | "\nDefault value is "__MODULE_STRING(W9968CF_BRIGHTNESS) | ||
332 | " for every device." | ||
333 | "\nThis parameter has no effect if 'autobright' is enabled." | ||
334 | "\n"); | ||
335 | MODULE_PARM_DESC(hue, | ||
336 | "\n<n[,...]> Set picture hue (0-65535)." | ||
337 | "\nDefault value is "__MODULE_STRING(W9968CF_HUE) | ||
338 | " for every device." | ||
339 | "\n"); | ||
340 | MODULE_PARM_DESC(colour, | ||
341 | "\n<n[,...]> Set picture saturation (0-65535)." | ||
342 | "\nDefault value is "__MODULE_STRING(W9968CF_COLOUR) | ||
343 | " for every device." | ||
344 | "\n"); | ||
345 | MODULE_PARM_DESC(contrast, | ||
346 | "\n<n[,...]> Set picture contrast (0-65535)." | ||
347 | "\nDefault value is "__MODULE_STRING(W9968CF_CONTRAST) | ||
348 | " for every device." | ||
349 | "\n"); | ||
350 | MODULE_PARM_DESC(whiteness, | ||
351 | "\n<n[,...]> Set picture whiteness (0-65535)." | ||
352 | "\nDefault value is "__MODULE_STRING(W9968CF_WHITENESS) | ||
353 | " for every device." | ||
354 | "\n"); | ||
355 | #ifdef W9968CF_DEBUG | ||
356 | MODULE_PARM_DESC(debug, | ||
357 | "\n<n> Debugging information level, from 0 to 6:" | ||
358 | "\n0 = none (use carefully)" | ||
359 | "\n1 = critical errors" | ||
360 | "\n2 = significant informations" | ||
361 | "\n3 = configuration or general messages" | ||
362 | "\n4 = warnings" | ||
363 | "\n5 = called functions" | ||
364 | "\n6 = function internals" | ||
365 | "\nLevel 5 and 6 are useful for testing only, when only " | ||
366 | "one device is used." | ||
367 | "\nDefault value is "__MODULE_STRING(W9968CF_DEBUG_LEVEL)"." | ||
368 | "\n"); | ||
369 | MODULE_PARM_DESC(specific_debug, | ||
370 | "\n<0|1> Enable or disable specific debugging messages:" | ||
371 | "\n0 = print messages concerning every level" | ||
372 | " <= 'debug' level." | ||
373 | "\n1 = print messages concerning the level" | ||
374 | " indicated by 'debug'." | ||
375 | "\nDefault value is " | ||
376 | __MODULE_STRING(W9968CF_SPECIFIC_DEBUG)"." | ||
377 | "\n"); | ||
378 | #endif /* W9968CF_DEBUG */ | ||
379 | |||
380 | |||
381 | |||
382 | /**************************************************************************** | ||
383 | * Some prototypes * | ||
384 | ****************************************************************************/ | ||
385 | |||
386 | /* Video4linux interface */ | ||
387 | static const struct v4l2_file_operations w9968cf_fops; | ||
388 | static int w9968cf_open(struct file *); | ||
389 | static int w9968cf_release(struct file *); | ||
390 | static int w9968cf_mmap(struct file *, struct vm_area_struct *); | ||
391 | static long w9968cf_ioctl(struct file *, unsigned, unsigned long); | ||
392 | static ssize_t w9968cf_read(struct file *, char __user *, size_t, loff_t *); | ||
393 | static long w9968cf_v4l_ioctl(struct file *, unsigned int, | ||
394 | void __user *); | ||
395 | |||
396 | /* USB-specific */ | ||
397 | static int w9968cf_start_transfer(struct w9968cf_device*); | ||
398 | static int w9968cf_stop_transfer(struct w9968cf_device*); | ||
399 | static int w9968cf_write_reg(struct w9968cf_device*, u16 value, u16 index); | ||
400 | static int w9968cf_read_reg(struct w9968cf_device*, u16 index); | ||
401 | static int w9968cf_write_fsb(struct w9968cf_device*, u16* data); | ||
402 | static int w9968cf_write_sb(struct w9968cf_device*, u16 value); | ||
403 | static int w9968cf_read_sb(struct w9968cf_device*); | ||
404 | static int w9968cf_upload_quantizationtables(struct w9968cf_device*); | ||
405 | static void w9968cf_urb_complete(struct urb *urb); | ||
406 | |||
407 | /* Low-level I2C (SMBus) I/O */ | ||
408 | static int w9968cf_smbus_start(struct w9968cf_device*); | ||
409 | static int w9968cf_smbus_stop(struct w9968cf_device*); | ||
410 | static int w9968cf_smbus_write_byte(struct w9968cf_device*, u8 v); | ||
411 | static int w9968cf_smbus_read_byte(struct w9968cf_device*, u8* v); | ||
412 | static int w9968cf_smbus_write_ack(struct w9968cf_device*); | ||
413 | static int w9968cf_smbus_read_ack(struct w9968cf_device*); | ||
414 | static int w9968cf_smbus_refresh_bus(struct w9968cf_device*); | ||
415 | static int w9968cf_i2c_adap_read_byte(struct w9968cf_device* cam, | ||
416 | u16 address, u8* value); | ||
417 | static int w9968cf_i2c_adap_read_byte_data(struct w9968cf_device*, u16 address, | ||
418 | u8 subaddress, u8* value); | ||
419 | static int w9968cf_i2c_adap_write_byte(struct w9968cf_device*, | ||
420 | u16 address, u8 subaddress); | ||
421 | static int w9968cf_i2c_adap_fastwrite_byte_data(struct w9968cf_device*, | ||
422 | u16 address, u8 subaddress, | ||
423 | u8 value); | ||
424 | |||
425 | /* I2C interface to kernel */ | ||
426 | static int w9968cf_i2c_init(struct w9968cf_device*); | ||
427 | static int w9968cf_i2c_smbus_xfer(struct i2c_adapter*, u16 addr, | ||
428 | unsigned short flags, char read_write, | ||
429 | u8 command, int size, union i2c_smbus_data*); | ||
430 | static u32 w9968cf_i2c_func(struct i2c_adapter*); | ||
431 | |||
432 | /* Memory management */ | ||
433 | static void* rvmalloc(unsigned long size); | ||
434 | static void rvfree(void *mem, unsigned long size); | ||
435 | static void w9968cf_deallocate_memory(struct w9968cf_device*); | ||
436 | static int w9968cf_allocate_memory(struct w9968cf_device*); | ||
437 | |||
438 | /* High-level image sensor control functions */ | ||
439 | static int w9968cf_sensor_set_control(struct w9968cf_device*,int cid,int val); | ||
440 | static int w9968cf_sensor_get_control(struct w9968cf_device*,int cid,int *val); | ||
441 | static int w9968cf_sensor_cmd(struct w9968cf_device*, | ||
442 | unsigned int cmd, void *arg); | ||
443 | static int w9968cf_sensor_init(struct w9968cf_device*); | ||
444 | static int w9968cf_sensor_update_settings(struct w9968cf_device*); | ||
445 | static int w9968cf_sensor_get_picture(struct w9968cf_device*); | ||
446 | static int w9968cf_sensor_update_picture(struct w9968cf_device*, | ||
447 | struct video_picture pict); | ||
448 | |||
449 | /* Other helper functions */ | ||
450 | static void w9968cf_configure_camera(struct w9968cf_device*,struct usb_device*, | ||
451 | enum w9968cf_model_id, | ||
452 | const unsigned short dev_nr); | ||
453 | static void w9968cf_adjust_configuration(struct w9968cf_device*); | ||
454 | static int w9968cf_turn_on_led(struct w9968cf_device*); | ||
455 | static int w9968cf_init_chip(struct w9968cf_device*); | ||
456 | static inline u16 w9968cf_valid_palette(u16 palette); | ||
457 | static inline u16 w9968cf_valid_depth(u16 palette); | ||
458 | static inline u8 w9968cf_need_decompression(u16 palette); | ||
459 | static int w9968cf_set_picture(struct w9968cf_device*, struct video_picture); | ||
460 | static int w9968cf_set_window(struct w9968cf_device*, struct video_window); | ||
461 | static int w9968cf_postprocess_frame(struct w9968cf_device*, | ||
462 | struct w9968cf_frame_t*); | ||
463 | static int w9968cf_adjust_window_size(struct w9968cf_device*, u32 *w, u32 *h); | ||
464 | static void w9968cf_init_framelist(struct w9968cf_device*); | ||
465 | static void w9968cf_push_frame(struct w9968cf_device*, u8 f_num); | ||
466 | static void w9968cf_pop_frame(struct w9968cf_device*,struct w9968cf_frame_t**); | ||
467 | static void w9968cf_release_resources(struct w9968cf_device*); | ||
468 | |||
469 | |||
470 | |||
471 | /**************************************************************************** | ||
472 | * Symbolic names * | ||
473 | ****************************************************************************/ | ||
474 | |||
475 | /* Used to represent a list of values and their respective symbolic names */ | ||
476 | struct w9968cf_symbolic_list { | ||
477 | const int num; | ||
478 | const char *name; | ||
479 | }; | ||
480 | |||
481 | /*-------------------------------------------------------------------------- | ||
482 | Returns the name of the matching element in the symbolic_list array. The | ||
483 | end of the list must be marked with an element that has a NULL name. | ||
484 | --------------------------------------------------------------------------*/ | ||
485 | static inline const char * | ||
486 | symbolic(struct w9968cf_symbolic_list list[], const int num) | ||
487 | { | ||
488 | int i; | ||
489 | |||
490 | for (i = 0; list[i].name != NULL; i++) | ||
491 | if (list[i].num == num) | ||
492 | return (list[i].name); | ||
493 | |||
494 | return "Unknown"; | ||
495 | } | ||
496 | |||
497 | static struct w9968cf_symbolic_list camlist[] = { | ||
498 | { W9968CF_MOD_GENERIC, "W996[87]CF JPEG USB Dual Mode Camera" }, | ||
499 | { W9968CF_MOD_CLVBWGP, "Creative Labs Video Blaster WebCam Go Plus" }, | ||
500 | |||
501 | /* Other cameras (having the same descriptors as Generic W996[87]CF) */ | ||
502 | { W9968CF_MOD_ADPVDMA, "Aroma Digi Pen VGA Dual Mode ADG-5000" }, | ||
503 | { W9986CF_MOD_AAU, "AVerMedia AVerTV USB" }, | ||
504 | { W9968CF_MOD_CLVBWG, "Creative Labs Video Blaster WebCam Go" }, | ||
505 | { W9968CF_MOD_LL, "Lebon LDC-035A" }, | ||
506 | { W9968CF_MOD_EEEMC, "Ezonics EZ-802 EZMega Cam" }, | ||
507 | { W9968CF_MOD_OOE, "OmniVision OV8610-EDE" }, | ||
508 | { W9968CF_MOD_ODPVDMPC, "OPCOM Digi Pen VGA Dual Mode Pen Camera" }, | ||
509 | { W9968CF_MOD_PDPII, "Pretec Digi Pen-II" }, | ||
510 | { W9968CF_MOD_PDP480, "Pretec DigiPen-480" }, | ||
511 | |||
512 | { -1, NULL } | ||
513 | }; | ||
514 | |||
515 | static struct w9968cf_symbolic_list senlist[] = { | ||
516 | { CC_OV76BE, "OV76BE" }, | ||
517 | { CC_OV7610, "OV7610" }, | ||
518 | { CC_OV7620, "OV7620" }, | ||
519 | { CC_OV7620AE, "OV7620AE" }, | ||
520 | { CC_OV6620, "OV6620" }, | ||
521 | { CC_OV6630, "OV6630" }, | ||
522 | { CC_OV6630AE, "OV6630AE" }, | ||
523 | { CC_OV6630AF, "OV6630AF" }, | ||
524 | { -1, NULL } | ||
525 | }; | ||
526 | |||
527 | /* Video4Linux1 palettes */ | ||
528 | static struct w9968cf_symbolic_list v4l1_plist[] = { | ||
529 | { VIDEO_PALETTE_GREY, "GREY" }, | ||
530 | { VIDEO_PALETTE_HI240, "HI240" }, | ||
531 | { VIDEO_PALETTE_RGB565, "RGB565" }, | ||
532 | { VIDEO_PALETTE_RGB24, "RGB24" }, | ||
533 | { VIDEO_PALETTE_RGB32, "RGB32" }, | ||
534 | { VIDEO_PALETTE_RGB555, "RGB555" }, | ||
535 | { VIDEO_PALETTE_YUV422, "YUV422" }, | ||
536 | { VIDEO_PALETTE_YUYV, "YUYV" }, | ||
537 | { VIDEO_PALETTE_UYVY, "UYVY" }, | ||
538 | { VIDEO_PALETTE_YUV420, "YUV420" }, | ||
539 | { VIDEO_PALETTE_YUV411, "YUV411" }, | ||
540 | { VIDEO_PALETTE_RAW, "RAW" }, | ||
541 | { VIDEO_PALETTE_YUV422P, "YUV422P" }, | ||
542 | { VIDEO_PALETTE_YUV411P, "YUV411P" }, | ||
543 | { VIDEO_PALETTE_YUV420P, "YUV420P" }, | ||
544 | { VIDEO_PALETTE_YUV410P, "YUV410P" }, | ||
545 | { -1, NULL } | ||
546 | }; | ||
547 | |||
548 | /* Decoder error codes: */ | ||
549 | static struct w9968cf_symbolic_list decoder_errlist[] = { | ||
550 | { W9968CF_DEC_ERR_CORRUPTED_DATA, "Corrupted data" }, | ||
551 | { W9968CF_DEC_ERR_BUF_OVERFLOW, "Buffer overflow" }, | ||
552 | { W9968CF_DEC_ERR_NO_SOI, "SOI marker not found" }, | ||
553 | { W9968CF_DEC_ERR_NO_SOF0, "SOF0 marker not found" }, | ||
554 | { W9968CF_DEC_ERR_NO_SOS, "SOS marker not found" }, | ||
555 | { W9968CF_DEC_ERR_NO_EOI, "EOI marker not found" }, | ||
556 | { -1, NULL } | ||
557 | }; | ||
558 | |||
559 | /* URB error codes: */ | ||
560 | static struct w9968cf_symbolic_list urb_errlist[] = { | ||
561 | { -ENOMEM, "No memory for allocation of internal structures" }, | ||
562 | { -ENOSPC, "The host controller's bandwidth is already consumed" }, | ||
563 | { -ENOENT, "URB was canceled by unlink_urb" }, | ||
564 | { -EXDEV, "ISO transfer only partially completed" }, | ||
565 | { -EAGAIN, "Too match scheduled for the future" }, | ||
566 | { -ENXIO, "URB already queued" }, | ||
567 | { -EFBIG, "Too much ISO frames requested" }, | ||
568 | { -ENOSR, "Buffer error (overrun)" }, | ||
569 | { -EPIPE, "Specified endpoint is stalled (device not responding)"}, | ||
570 | { -EOVERFLOW, "Babble (too much data)" }, | ||
571 | { -EPROTO, "Bit-stuff error (bad cable?)" }, | ||
572 | { -EILSEQ, "CRC/Timeout" }, | ||
573 | { -ETIME, "Device does not respond to token" }, | ||
574 | { -ETIMEDOUT, "Device does not respond to command" }, | ||
575 | { -1, NULL } | ||
576 | }; | ||
577 | |||
578 | /**************************************************************************** | ||
579 | * Memory management functions * | ||
580 | ****************************************************************************/ | ||
581 | static void* rvmalloc(unsigned long size) | ||
582 | { | ||
583 | void* mem; | ||
584 | unsigned long adr; | ||
585 | |||
586 | size = PAGE_ALIGN(size); | ||
587 | mem = vmalloc_32(size); | ||
588 | if (!mem) | ||
589 | return NULL; | ||
590 | |||
591 | memset(mem, 0, size); /* Clear the ram out, no junk to the user */ | ||
592 | adr = (unsigned long) mem; | ||
593 | while (size > 0) { | ||
594 | SetPageReserved(vmalloc_to_page((void *)adr)); | ||
595 | adr += PAGE_SIZE; | ||
596 | size -= PAGE_SIZE; | ||
597 | } | ||
598 | |||
599 | return mem; | ||
600 | } | ||
601 | |||
602 | |||
603 | static void rvfree(void* mem, unsigned long size) | ||
604 | { | ||
605 | unsigned long adr; | ||
606 | |||
607 | if (!mem) | ||
608 | return; | ||
609 | |||
610 | adr = (unsigned long) mem; | ||
611 | while ((long) size > 0) { | ||
612 | ClearPageReserved(vmalloc_to_page((void *)adr)); | ||
613 | adr += PAGE_SIZE; | ||
614 | size -= PAGE_SIZE; | ||
615 | } | ||
616 | vfree(mem); | ||
617 | } | ||
618 | |||
619 | |||
620 | /*-------------------------------------------------------------------------- | ||
621 | Deallocate previously allocated memory. | ||
622 | --------------------------------------------------------------------------*/ | ||
623 | static void w9968cf_deallocate_memory(struct w9968cf_device* cam) | ||
624 | { | ||
625 | u8 i; | ||
626 | |||
627 | /* Free the isochronous transfer buffers */ | ||
628 | for (i = 0; i < W9968CF_URBS; i++) { | ||
629 | kfree(cam->transfer_buffer[i]); | ||
630 | cam->transfer_buffer[i] = NULL; | ||
631 | } | ||
632 | |||
633 | /* Free temporary frame buffer */ | ||
634 | if (cam->frame_tmp.buffer) { | ||
635 | rvfree(cam->frame_tmp.buffer, cam->frame_tmp.size); | ||
636 | cam->frame_tmp.buffer = NULL; | ||
637 | } | ||
638 | |||
639 | /* Free helper buffer */ | ||
640 | if (cam->frame_vpp.buffer) { | ||
641 | rvfree(cam->frame_vpp.buffer, cam->frame_vpp.size); | ||
642 | cam->frame_vpp.buffer = NULL; | ||
643 | } | ||
644 | |||
645 | /* Free video frame buffers */ | ||
646 | if (cam->frame[0].buffer) { | ||
647 | rvfree(cam->frame[0].buffer, cam->nbuffers*cam->frame[0].size); | ||
648 | cam->frame[0].buffer = NULL; | ||
649 | } | ||
650 | |||
651 | cam->nbuffers = 0; | ||
652 | |||
653 | DBG(5, "Memory successfully deallocated") | ||
654 | } | ||
655 | |||
656 | |||
657 | /*-------------------------------------------------------------------------- | ||
658 | Allocate memory buffers for USB transfers and video frames. | ||
659 | This function is called by open() only. | ||
660 | Return 0 on success, a negative number otherwise. | ||
661 | --------------------------------------------------------------------------*/ | ||
662 | static int w9968cf_allocate_memory(struct w9968cf_device* cam) | ||
663 | { | ||
664 | const u16 p_size = wMaxPacketSize[cam->altsetting-1]; | ||
665 | void* buff = NULL; | ||
666 | unsigned long hw_bufsize, vpp_bufsize; | ||
667 | u8 i, bpp; | ||
668 | |||
669 | /* NOTE: Deallocation is done elsewhere in case of error */ | ||
670 | |||
671 | /* Calculate the max amount of raw data per frame from the device */ | ||
672 | hw_bufsize = cam->maxwidth*cam->maxheight*2; | ||
673 | |||
674 | /* Calculate the max buf. size needed for post-processing routines */ | ||
675 | bpp = (w9968cf_vpp) ? 4 : 2; | ||
676 | if (cam->upscaling) | ||
677 | vpp_bufsize = max(W9968CF_MAX_WIDTH*W9968CF_MAX_HEIGHT*bpp, | ||
678 | cam->maxwidth*cam->maxheight*bpp); | ||
679 | else | ||
680 | vpp_bufsize = cam->maxwidth*cam->maxheight*bpp; | ||
681 | |||
682 | /* Allocate memory for the isochronous transfer buffers */ | ||
683 | for (i = 0; i < W9968CF_URBS; i++) { | ||
684 | if (!(cam->transfer_buffer[i] = | ||
685 | kzalloc(W9968CF_ISO_PACKETS*p_size, GFP_KERNEL))) { | ||
686 | DBG(1, "Couldn't allocate memory for the isochronous " | ||
687 | "transfer buffers (%u bytes)", | ||
688 | p_size * W9968CF_ISO_PACKETS) | ||
689 | return -ENOMEM; | ||
690 | } | ||
691 | } | ||
692 | |||
693 | /* Allocate memory for the temporary frame buffer */ | ||
694 | if (!(cam->frame_tmp.buffer = rvmalloc(hw_bufsize))) { | ||
695 | DBG(1, "Couldn't allocate memory for the temporary " | ||
696 | "video frame buffer (%lu bytes)", hw_bufsize) | ||
697 | return -ENOMEM; | ||
698 | } | ||
699 | cam->frame_tmp.size = hw_bufsize; | ||
700 | cam->frame_tmp.number = -1; | ||
701 | |||
702 | /* Allocate memory for the helper buffer */ | ||
703 | if (w9968cf_vpp) { | ||
704 | if (!(cam->frame_vpp.buffer = rvmalloc(vpp_bufsize))) { | ||
705 | DBG(1, "Couldn't allocate memory for the helper buffer" | ||
706 | " (%lu bytes)", vpp_bufsize) | ||
707 | return -ENOMEM; | ||
708 | } | ||
709 | cam->frame_vpp.size = vpp_bufsize; | ||
710 | } else | ||
711 | cam->frame_vpp.buffer = NULL; | ||
712 | |||
713 | /* Allocate memory for video frame buffers */ | ||
714 | cam->nbuffers = cam->max_buffers; | ||
715 | while (cam->nbuffers >= 2) { | ||
716 | if ((buff = rvmalloc(cam->nbuffers * vpp_bufsize))) | ||
717 | break; | ||
718 | else | ||
719 | cam->nbuffers--; | ||
720 | } | ||
721 | |||
722 | if (!buff) { | ||
723 | DBG(1, "Couldn't allocate memory for the video frame buffers") | ||
724 | cam->nbuffers = 0; | ||
725 | return -ENOMEM; | ||
726 | } | ||
727 | |||
728 | if (cam->nbuffers != cam->max_buffers) | ||
729 | DBG(2, "Couldn't allocate memory for %u video frame buffers. " | ||
730 | "Only memory for %u buffers has been allocated", | ||
731 | cam->max_buffers, cam->nbuffers) | ||
732 | |||
733 | for (i = 0; i < cam->nbuffers; i++) { | ||
734 | cam->frame[i].buffer = buff + i*vpp_bufsize; | ||
735 | cam->frame[i].size = vpp_bufsize; | ||
736 | cam->frame[i].number = i; | ||
737 | /* Circular list */ | ||
738 | if (i != cam->nbuffers-1) | ||
739 | cam->frame[i].next = &cam->frame[i+1]; | ||
740 | else | ||
741 | cam->frame[i].next = &cam->frame[0]; | ||
742 | cam->frame[i].status = F_UNUSED; | ||
743 | } | ||
744 | |||
745 | DBG(5, "Memory successfully allocated") | ||
746 | return 0; | ||
747 | } | ||
748 | |||
749 | |||
750 | |||
751 | /**************************************************************************** | ||
752 | * USB-specific functions * | ||
753 | ****************************************************************************/ | ||
754 | |||
755 | /*-------------------------------------------------------------------------- | ||
756 | This is an handler function which is called after the URBs are completed. | ||
757 | It collects multiple data packets coming from the camera by putting them | ||
758 | into frame buffers: one or more zero data length data packets are used to | ||
759 | mark the end of a video frame; the first non-zero data packet is the start | ||
760 | of the next video frame; if an error is encountered in a packet, the entire | ||
761 | video frame is discarded and grabbed again. | ||
762 | If there are no requested frames in the FIFO list, packets are collected into | ||
763 | a temporary buffer. | ||
764 | --------------------------------------------------------------------------*/ | ||
765 | static void w9968cf_urb_complete(struct urb *urb) | ||
766 | { | ||
767 | struct w9968cf_device* cam = (struct w9968cf_device*)urb->context; | ||
768 | struct w9968cf_frame_t** f; | ||
769 | unsigned int len, status; | ||
770 | void* pos; | ||
771 | u8 i; | ||
772 | int err = 0; | ||
773 | |||
774 | if ((!cam->streaming) || cam->disconnected) { | ||
775 | DBG(4, "Got interrupt, but not streaming") | ||
776 | return; | ||
777 | } | ||
778 | |||
779 | /* "(*f)" will be used instead of "cam->frame_current" */ | ||
780 | f = &cam->frame_current; | ||
781 | |||
782 | /* If a frame has been requested and we are grabbing into | ||
783 | the temporary frame, we'll switch to that requested frame */ | ||
784 | if ((*f) == &cam->frame_tmp && *cam->requested_frame) { | ||
785 | if (cam->frame_tmp.status == F_GRABBING) { | ||
786 | w9968cf_pop_frame(cam, &cam->frame_current); | ||
787 | (*f)->status = F_GRABBING; | ||
788 | (*f)->length = cam->frame_tmp.length; | ||
789 | memcpy((*f)->buffer, cam->frame_tmp.buffer, | ||
790 | (*f)->length); | ||
791 | DBG(6, "Switched from temp. frame to frame #%d", | ||
792 | (*f)->number) | ||
793 | } | ||
794 | } | ||
795 | |||
796 | for (i = 0; i < urb->number_of_packets; i++) { | ||
797 | len = urb->iso_frame_desc[i].actual_length; | ||
798 | status = urb->iso_frame_desc[i].status; | ||
799 | pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer; | ||
800 | |||
801 | if (status && len != 0) { | ||
802 | DBG(4, "URB failed, error in data packet " | ||
803 | "(error #%u, %s)", | ||
804 | status, symbolic(urb_errlist, status)) | ||
805 | (*f)->status = F_ERROR; | ||
806 | continue; | ||
807 | } | ||
808 | |||
809 | if (len) { /* start of frame */ | ||
810 | |||
811 | if ((*f)->status == F_UNUSED) { | ||
812 | (*f)->status = F_GRABBING; | ||
813 | (*f)->length = 0; | ||
814 | } | ||
815 | |||
816 | /* Buffer overflows shouldn't happen, however...*/ | ||
817 | if ((*f)->length + len > (*f)->size) { | ||
818 | DBG(4, "Buffer overflow: bad data packets") | ||
819 | (*f)->status = F_ERROR; | ||
820 | } | ||
821 | |||
822 | if ((*f)->status == F_GRABBING) { | ||
823 | memcpy((*f)->buffer + (*f)->length, pos, len); | ||
824 | (*f)->length += len; | ||
825 | } | ||
826 | |||
827 | } else if ((*f)->status == F_GRABBING) { /* end of frame */ | ||
828 | |||
829 | DBG(6, "Frame #%d successfully grabbed", (*f)->number) | ||
830 | |||
831 | if (cam->vpp_flag & VPP_DECOMPRESSION) { | ||
832 | err = w9968cf_vpp->check_headers((*f)->buffer, | ||
833 | (*f)->length); | ||
834 | if (err) { | ||
835 | DBG(4, "Skip corrupted frame: %s", | ||
836 | symbolic(decoder_errlist, err)) | ||
837 | (*f)->status = F_UNUSED; | ||
838 | continue; /* grab this frame again */ | ||
839 | } | ||
840 | } | ||
841 | |||
842 | (*f)->status = F_READY; | ||
843 | (*f)->queued = 0; | ||
844 | |||
845 | /* Take a pointer to the new frame from the FIFO list. | ||
846 | If the list is empty,we'll use the temporary frame*/ | ||
847 | if (*cam->requested_frame) | ||
848 | w9968cf_pop_frame(cam, &cam->frame_current); | ||
849 | else { | ||
850 | cam->frame_current = &cam->frame_tmp; | ||
851 | (*f)->status = F_UNUSED; | ||
852 | } | ||
853 | |||
854 | } else if ((*f)->status == F_ERROR) | ||
855 | (*f)->status = F_UNUSED; /* grab it again */ | ||
856 | |||
857 | PDBGG("Frame length %lu | pack.#%u | pack.len. %u | state %d", | ||
858 | (unsigned long)(*f)->length, i, len, (*f)->status) | ||
859 | |||
860 | } /* end for */ | ||
861 | |||
862 | /* Resubmit this URB */ | ||
863 | urb->dev = cam->usbdev; | ||
864 | urb->status = 0; | ||
865 | spin_lock(&cam->urb_lock); | ||
866 | if (cam->streaming) | ||
867 | if ((err = usb_submit_urb(urb, GFP_ATOMIC))) { | ||
868 | cam->misconfigured = 1; | ||
869 | DBG(1, "Couldn't resubmit the URB: error %d, %s", | ||
870 | err, symbolic(urb_errlist, err)) | ||
871 | } | ||
872 | spin_unlock(&cam->urb_lock); | ||
873 | |||
874 | /* Wake up the user process */ | ||
875 | wake_up_interruptible(&cam->wait_queue); | ||
876 | } | ||
877 | |||
878 | |||
879 | /*--------------------------------------------------------------------------- | ||
880 | Setup the URB structures for the isochronous transfer. | ||
881 | Submit the URBs so that the data transfer begins. | ||
882 | Return 0 on success, a negative number otherwise. | ||
883 | ---------------------------------------------------------------------------*/ | ||
884 | static int w9968cf_start_transfer(struct w9968cf_device* cam) | ||
885 | { | ||
886 | struct usb_device *udev = cam->usbdev; | ||
887 | struct urb* urb; | ||
888 | const u16 p_size = wMaxPacketSize[cam->altsetting-1]; | ||
889 | u16 w, h, d; | ||
890 | int vidcapt; | ||
891 | u32 t_size; | ||
892 | int err = 0; | ||
893 | s8 i, j; | ||
894 | |||
895 | for (i = 0; i < W9968CF_URBS; i++) { | ||
896 | urb = usb_alloc_urb(W9968CF_ISO_PACKETS, GFP_KERNEL); | ||
897 | if (!urb) { | ||
898 | for (j = 0; j < i; j++) | ||
899 | usb_free_urb(cam->urb[j]); | ||
900 | DBG(1, "Couldn't allocate the URB structures") | ||
901 | return -ENOMEM; | ||
902 | } | ||
903 | |||
904 | cam->urb[i] = urb; | ||
905 | urb->dev = udev; | ||
906 | urb->context = (void*)cam; | ||
907 | urb->pipe = usb_rcvisocpipe(udev, 1); | ||
908 | urb->transfer_flags = URB_ISO_ASAP; | ||
909 | urb->number_of_packets = W9968CF_ISO_PACKETS; | ||
910 | urb->complete = w9968cf_urb_complete; | ||
911 | urb->transfer_buffer = cam->transfer_buffer[i]; | ||
912 | urb->transfer_buffer_length = p_size*W9968CF_ISO_PACKETS; | ||
913 | urb->interval = 1; | ||
914 | for (j = 0; j < W9968CF_ISO_PACKETS; j++) { | ||
915 | urb->iso_frame_desc[j].offset = p_size*j; | ||
916 | urb->iso_frame_desc[j].length = p_size; | ||
917 | } | ||
918 | } | ||
919 | |||
920 | /* Transfer size per frame, in WORD ! */ | ||
921 | d = cam->hw_depth; | ||
922 | w = cam->hw_width; | ||
923 | h = cam->hw_height; | ||
924 | |||
925 | t_size = (w*h*d)/16; | ||
926 | |||
927 | err = w9968cf_write_reg(cam, 0xbf17, 0x00); /* reset everything */ | ||
928 | err += w9968cf_write_reg(cam, 0xbf10, 0x00); /* normal operation */ | ||
929 | |||
930 | /* Transfer size */ | ||
931 | err += w9968cf_write_reg(cam, t_size & 0xffff, 0x3d); /* low bits */ | ||
932 | err += w9968cf_write_reg(cam, t_size >> 16, 0x3e); /* high bits */ | ||
933 | |||
934 | if (cam->vpp_flag & VPP_DECOMPRESSION) | ||
935 | err += w9968cf_upload_quantizationtables(cam); | ||
936 | |||
937 | vidcapt = w9968cf_read_reg(cam, 0x16); /* read picture settings */ | ||
938 | err += w9968cf_write_reg(cam, vidcapt|0x8000, 0x16); /* capt. enable */ | ||
939 | |||
940 | err += usb_set_interface(udev, 0, cam->altsetting); | ||
941 | err += w9968cf_write_reg(cam, 0x8a05, 0x3c); /* USB FIFO enable */ | ||
942 | |||
943 | if (err || (vidcapt < 0)) { | ||
944 | for (i = 0; i < W9968CF_URBS; i++) | ||
945 | usb_free_urb(cam->urb[i]); | ||
946 | DBG(1, "Couldn't tell the camera to start the data transfer") | ||
947 | return err; | ||
948 | } | ||
949 | |||
950 | w9968cf_init_framelist(cam); | ||
951 | |||
952 | /* Begin to grab into the temporary buffer */ | ||
953 | cam->frame_tmp.status = F_UNUSED; | ||
954 | cam->frame_tmp.queued = 0; | ||
955 | cam->frame_current = &cam->frame_tmp; | ||
956 | |||
957 | if (!(cam->vpp_flag & VPP_DECOMPRESSION)) | ||
958 | DBG(5, "Isochronous transfer size: %lu bytes/frame", | ||
959 | (unsigned long)t_size*2) | ||
960 | |||
961 | DBG(5, "Starting the isochronous transfer...") | ||
962 | |||
963 | cam->streaming = 1; | ||
964 | |||
965 | /* Submit the URBs */ | ||
966 | for (i = 0; i < W9968CF_URBS; i++) { | ||
967 | err = usb_submit_urb(cam->urb[i], GFP_KERNEL); | ||
968 | if (err) { | ||
969 | cam->streaming = 0; | ||
970 | for (j = i-1; j >= 0; j--) { | ||
971 | usb_kill_urb(cam->urb[j]); | ||
972 | usb_free_urb(cam->urb[j]); | ||
973 | } | ||
974 | DBG(1, "Couldn't send a transfer request to the " | ||
975 | "USB core (error #%d, %s)", err, | ||
976 | symbolic(urb_errlist, err)) | ||
977 | return err; | ||
978 | } | ||
979 | } | ||
980 | |||
981 | return 0; | ||
982 | } | ||
983 | |||
984 | |||
985 | /*-------------------------------------------------------------------------- | ||
986 | Stop the isochronous transfer and set alternate setting to 0 (0Mb/s). | ||
987 | Return 0 on success, a negative number otherwise. | ||
988 | --------------------------------------------------------------------------*/ | ||
989 | static int w9968cf_stop_transfer(struct w9968cf_device* cam) | ||
990 | { | ||
991 | struct usb_device *udev = cam->usbdev; | ||
992 | unsigned long lock_flags; | ||
993 | int err = 0; | ||
994 | s8 i; | ||
995 | |||
996 | if (!cam->streaming) | ||
997 | return 0; | ||
998 | |||
999 | /* This avoids race conditions with usb_submit_urb() | ||
1000 | in the URB completition handler */ | ||
1001 | spin_lock_irqsave(&cam->urb_lock, lock_flags); | ||
1002 | cam->streaming = 0; | ||
1003 | spin_unlock_irqrestore(&cam->urb_lock, lock_flags); | ||
1004 | |||
1005 | for (i = W9968CF_URBS-1; i >= 0; i--) | ||
1006 | if (cam->urb[i]) { | ||
1007 | usb_kill_urb(cam->urb[i]); | ||
1008 | usb_free_urb(cam->urb[i]); | ||
1009 | cam->urb[i] = NULL; | ||
1010 | } | ||
1011 | |||
1012 | if (cam->disconnected) | ||
1013 | goto exit; | ||
1014 | |||
1015 | err = w9968cf_write_reg(cam, 0x0a05, 0x3c); /* stop USB transfer */ | ||
1016 | err += usb_set_interface(udev, 0, 0); /* 0 Mb/s */ | ||
1017 | err += w9968cf_write_reg(cam, 0x0000, 0x39); /* disable JPEG encoder */ | ||
1018 | err += w9968cf_write_reg(cam, 0x0000, 0x16); /* stop video capture */ | ||
1019 | |||
1020 | if (err) { | ||
1021 | DBG(2, "Failed to tell the camera to stop the isochronous " | ||
1022 | "transfer. However this is not a critical error.") | ||
1023 | return -EIO; | ||
1024 | } | ||
1025 | |||
1026 | exit: | ||
1027 | DBG(5, "Isochronous transfer stopped") | ||
1028 | return 0; | ||
1029 | } | ||
1030 | |||
1031 | |||
1032 | /*-------------------------------------------------------------------------- | ||
1033 | Write a W9968CF register. | ||
1034 | Return 0 on success, -1 otherwise. | ||
1035 | --------------------------------------------------------------------------*/ | ||
1036 | static int w9968cf_write_reg(struct w9968cf_device* cam, u16 value, u16 index) | ||
1037 | { | ||
1038 | struct usb_device* udev = cam->usbdev; | ||
1039 | int res; | ||
1040 | |||
1041 | res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, | ||
1042 | USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, | ||
1043 | value, index, NULL, 0, W9968CF_USB_CTRL_TIMEOUT); | ||
1044 | |||
1045 | if (res < 0) | ||
1046 | DBG(4, "Failed to write a register " | ||
1047 | "(value 0x%04X, index 0x%02X, error #%d, %s)", | ||
1048 | value, index, res, symbolic(urb_errlist, res)) | ||
1049 | |||
1050 | return (res >= 0) ? 0 : -1; | ||
1051 | } | ||
1052 | |||
1053 | |||
1054 | /*-------------------------------------------------------------------------- | ||
1055 | Read a W9968CF register. | ||
1056 | Return the register value on success, -1 otherwise. | ||
1057 | --------------------------------------------------------------------------*/ | ||
1058 | static int w9968cf_read_reg(struct w9968cf_device* cam, u16 index) | ||
1059 | { | ||
1060 | struct usb_device* udev = cam->usbdev; | ||
1061 | u16* buff = cam->control_buffer; | ||
1062 | int res; | ||
1063 | |||
1064 | res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 1, | ||
1065 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
1066 | 0, index, buff, 2, W9968CF_USB_CTRL_TIMEOUT); | ||
1067 | |||
1068 | if (res < 0) | ||
1069 | DBG(4, "Failed to read a register " | ||
1070 | "(index 0x%02X, error #%d, %s)", | ||
1071 | index, res, symbolic(urb_errlist, res)) | ||
1072 | |||
1073 | return (res >= 0) ? (int)(*buff) : -1; | ||
1074 | } | ||
1075 | |||
1076 | |||
1077 | /*-------------------------------------------------------------------------- | ||
1078 | Write 64-bit data to the fast serial bus registers. | ||
1079 | Return 0 on success, -1 otherwise. | ||
1080 | --------------------------------------------------------------------------*/ | ||
1081 | static int w9968cf_write_fsb(struct w9968cf_device* cam, u16* data) | ||
1082 | { | ||
1083 | struct usb_device* udev = cam->usbdev; | ||
1084 | u16 value; | ||
1085 | int res; | ||
1086 | |||
1087 | value = *data++; | ||
1088 | |||
1089 | res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, | ||
1090 | USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, | ||
1091 | value, 0x06, data, 6, W9968CF_USB_CTRL_TIMEOUT); | ||
1092 | |||
1093 | if (res < 0) | ||
1094 | DBG(4, "Failed to write the FSB registers " | ||
1095 | "(error #%d, %s)", res, symbolic(urb_errlist, res)) | ||
1096 | |||
1097 | return (res >= 0) ? 0 : -1; | ||
1098 | } | ||
1099 | |||
1100 | |||
1101 | /*-------------------------------------------------------------------------- | ||
1102 | Write data to the serial bus control register. | ||
1103 | Return 0 on success, a negative number otherwise. | ||
1104 | --------------------------------------------------------------------------*/ | ||
1105 | static int w9968cf_write_sb(struct w9968cf_device* cam, u16 value) | ||
1106 | { | ||
1107 | int err = 0; | ||
1108 | |||
1109 | err = w9968cf_write_reg(cam, value, 0x01); | ||
1110 | udelay(W9968CF_I2C_BUS_DELAY); | ||
1111 | |||
1112 | return err; | ||
1113 | } | ||
1114 | |||
1115 | |||
1116 | /*-------------------------------------------------------------------------- | ||
1117 | Read data from the serial bus control register. | ||
1118 | Return 0 on success, a negative number otherwise. | ||
1119 | --------------------------------------------------------------------------*/ | ||
1120 | static int w9968cf_read_sb(struct w9968cf_device* cam) | ||
1121 | { | ||
1122 | int v = 0; | ||
1123 | |||
1124 | v = w9968cf_read_reg(cam, 0x01); | ||
1125 | udelay(W9968CF_I2C_BUS_DELAY); | ||
1126 | |||
1127 | return v; | ||
1128 | } | ||
1129 | |||
1130 | |||
1131 | /*-------------------------------------------------------------------------- | ||
1132 | Upload quantization tables for the JPEG compression. | ||
1133 | This function is called by w9968cf_start_transfer(). | ||
1134 | Return 0 on success, a negative number otherwise. | ||
1135 | --------------------------------------------------------------------------*/ | ||
1136 | static int w9968cf_upload_quantizationtables(struct w9968cf_device* cam) | ||
1137 | { | ||
1138 | u16 a, b; | ||
1139 | int err = 0, i, j; | ||
1140 | |||
1141 | err += w9968cf_write_reg(cam, 0x0010, 0x39); /* JPEG clock enable */ | ||
1142 | |||
1143 | for (i = 0, j = 0; i < 32; i++, j += 2) { | ||
1144 | a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j+1]) << 8); | ||
1145 | b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j+1]) << 8); | ||
1146 | err += w9968cf_write_reg(cam, a, 0x40+i); | ||
1147 | err += w9968cf_write_reg(cam, b, 0x60+i); | ||
1148 | } | ||
1149 | err += w9968cf_write_reg(cam, 0x0012, 0x39); /* JPEG encoder enable */ | ||
1150 | |||
1151 | return err; | ||
1152 | } | ||
1153 | |||
1154 | |||
1155 | |||
1156 | /**************************************************************************** | ||
1157 | * Low-level I2C I/O functions. * | ||
1158 | * The adapter supports the following I2C transfer functions: * | ||
1159 | * i2c_adap_fastwrite_byte_data() (at 400 kHz bit frequency only) * | ||
1160 | * i2c_adap_read_byte_data() * | ||
1161 | * i2c_adap_read_byte() * | ||
1162 | ****************************************************************************/ | ||
1163 | |||
1164 | static int w9968cf_smbus_start(struct w9968cf_device* cam) | ||
1165 | { | ||
1166 | int err = 0; | ||
1167 | |||
1168 | err += w9968cf_write_sb(cam, 0x0011); /* SDE=1, SDA=0, SCL=1 */ | ||
1169 | err += w9968cf_write_sb(cam, 0x0010); /* SDE=1, SDA=0, SCL=0 */ | ||
1170 | |||
1171 | return err; | ||
1172 | } | ||
1173 | |||
1174 | |||
1175 | static int w9968cf_smbus_stop(struct w9968cf_device* cam) | ||
1176 | { | ||
1177 | int err = 0; | ||
1178 | |||
1179 | err += w9968cf_write_sb(cam, 0x0011); /* SDE=1, SDA=0, SCL=1 */ | ||
1180 | err += w9968cf_write_sb(cam, 0x0013); /* SDE=1, SDA=1, SCL=1 */ | ||
1181 | |||
1182 | return err; | ||
1183 | } | ||
1184 | |||
1185 | |||
1186 | static int w9968cf_smbus_write_byte(struct w9968cf_device* cam, u8 v) | ||
1187 | { | ||
1188 | u8 bit; | ||
1189 | int err = 0, sda; | ||
1190 | |||
1191 | for (bit = 0 ; bit < 8 ; bit++) { | ||
1192 | sda = (v & 0x80) ? 2 : 0; | ||
1193 | v <<= 1; | ||
1194 | /* SDE=1, SDA=sda, SCL=0 */ | ||
1195 | err += w9968cf_write_sb(cam, 0x10 | sda); | ||
1196 | /* SDE=1, SDA=sda, SCL=1 */ | ||
1197 | err += w9968cf_write_sb(cam, 0x11 | sda); | ||
1198 | /* SDE=1, SDA=sda, SCL=0 */ | ||
1199 | err += w9968cf_write_sb(cam, 0x10 | sda); | ||
1200 | } | ||
1201 | |||
1202 | return err; | ||
1203 | } | ||
1204 | |||
1205 | |||
1206 | static int w9968cf_smbus_read_byte(struct w9968cf_device* cam, u8* v) | ||
1207 | { | ||
1208 | u8 bit; | ||
1209 | int err = 0; | ||
1210 | |||
1211 | *v = 0; | ||
1212 | for (bit = 0 ; bit < 8 ; bit++) { | ||
1213 | *v <<= 1; | ||
1214 | err += w9968cf_write_sb(cam, 0x0013); | ||
1215 | *v |= (w9968cf_read_sb(cam) & 0x0008) ? 1 : 0; | ||
1216 | err += w9968cf_write_sb(cam, 0x0012); | ||
1217 | } | ||
1218 | |||
1219 | return err; | ||
1220 | } | ||
1221 | |||
1222 | |||
1223 | static int w9968cf_smbus_write_ack(struct w9968cf_device* cam) | ||
1224 | { | ||
1225 | int err = 0; | ||
1226 | |||
1227 | err += w9968cf_write_sb(cam, 0x0010); /* SDE=1, SDA=0, SCL=0 */ | ||
1228 | err += w9968cf_write_sb(cam, 0x0011); /* SDE=1, SDA=0, SCL=1 */ | ||
1229 | err += w9968cf_write_sb(cam, 0x0010); /* SDE=1, SDA=0, SCL=0 */ | ||
1230 | |||
1231 | return err; | ||
1232 | } | ||
1233 | |||
1234 | |||
1235 | static int w9968cf_smbus_read_ack(struct w9968cf_device* cam) | ||
1236 | { | ||
1237 | int err = 0, sda; | ||
1238 | |||
1239 | err += w9968cf_write_sb(cam, 0x0013); /* SDE=1, SDA=1, SCL=1 */ | ||
1240 | sda = (w9968cf_read_sb(cam) & 0x08) ? 1 : 0; /* sda = SDA */ | ||
1241 | err += w9968cf_write_sb(cam, 0x0012); /* SDE=1, SDA=1, SCL=0 */ | ||
1242 | if (sda < 0) | ||
1243 | err += sda; | ||
1244 | if (sda == 1) { | ||
1245 | DBG(6, "Couldn't receive the ACK") | ||
1246 | err += -1; | ||
1247 | } | ||
1248 | |||
1249 | return err; | ||
1250 | } | ||
1251 | |||
1252 | |||
1253 | /* This seems to refresh the communication through the serial bus */ | ||
1254 | static int w9968cf_smbus_refresh_bus(struct w9968cf_device* cam) | ||
1255 | { | ||
1256 | int err = 0, j; | ||
1257 | |||
1258 | for (j = 1; j <= 10; j++) { | ||
1259 | err = w9968cf_write_reg(cam, 0x0020, 0x01); | ||
1260 | err += w9968cf_write_reg(cam, 0x0000, 0x01); | ||
1261 | if (err) | ||
1262 | break; | ||
1263 | } | ||
1264 | |||
1265 | return err; | ||
1266 | } | ||
1267 | |||
1268 | |||
1269 | /* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */ | ||
1270 | static int | ||
1271 | w9968cf_i2c_adap_fastwrite_byte_data(struct w9968cf_device* cam, | ||
1272 | u16 address, u8 subaddress,u8 value) | ||
1273 | { | ||
1274 | u16* data = cam->data_buffer; | ||
1275 | int err = 0; | ||
1276 | |||
1277 | err += w9968cf_smbus_refresh_bus(cam); | ||
1278 | |||
1279 | /* Enable SBUS outputs */ | ||
1280 | err += w9968cf_write_sb(cam, 0x0020); | ||
1281 | |||
1282 | data[0] = 0x082f | ((address & 0x80) ? 0x1500 : 0x0); | ||
1283 | data[0] |= (address & 0x40) ? 0x4000 : 0x0; | ||
1284 | data[1] = 0x2082 | ((address & 0x40) ? 0x0005 : 0x0); | ||
1285 | data[1] |= (address & 0x20) ? 0x0150 : 0x0; | ||
1286 | data[1] |= (address & 0x10) ? 0x5400 : 0x0; | ||
1287 | data[2] = 0x8208 | ((address & 0x08) ? 0x0015 : 0x0); | ||
1288 | data[2] |= (address & 0x04) ? 0x0540 : 0x0; | ||
1289 | data[2] |= (address & 0x02) ? 0x5000 : 0x0; | ||
1290 | data[3] = 0x1d20 | ((address & 0x02) ? 0x0001 : 0x0); | ||
1291 | data[3] |= (address & 0x01) ? 0x0054 : 0x0; | ||
1292 | |||
1293 | err += w9968cf_write_fsb(cam, data); | ||
1294 | |||
1295 | data[0] = 0x8208 | ((subaddress & 0x80) ? 0x0015 : 0x0); | ||
1296 | data[0] |= (subaddress & 0x40) ? 0x0540 : 0x0; | ||
1297 | data[0] |= (subaddress & 0x20) ? 0x5000 : 0x0; | ||
1298 | data[1] = 0x0820 | ((subaddress & 0x20) ? 0x0001 : 0x0); | ||
1299 | data[1] |= (subaddress & 0x10) ? 0x0054 : 0x0; | ||
1300 | data[1] |= (subaddress & 0x08) ? 0x1500 : 0x0; | ||
1301 | data[1] |= (subaddress & 0x04) ? 0x4000 : 0x0; | ||
1302 | data[2] = 0x2082 | ((subaddress & 0x04) ? 0x0005 : 0x0); | ||
1303 | data[2] |= (subaddress & 0x02) ? 0x0150 : 0x0; | ||
1304 | data[2] |= (subaddress & 0x01) ? 0x5400 : 0x0; | ||
1305 | data[3] = 0x001d; | ||
1306 | |||
1307 | err += w9968cf_write_fsb(cam, data); | ||
1308 | |||
1309 | data[0] = 0x8208 | ((value & 0x80) ? 0x0015 : 0x0); | ||
1310 | data[0] |= (value & 0x40) ? 0x0540 : 0x0; | ||
1311 | data[0] |= (value & 0x20) ? 0x5000 : 0x0; | ||
1312 | data[1] = 0x0820 | ((value & 0x20) ? 0x0001 : 0x0); | ||
1313 | data[1] |= (value & 0x10) ? 0x0054 : 0x0; | ||
1314 | data[1] |= (value & 0x08) ? 0x1500 : 0x0; | ||
1315 | data[1] |= (value & 0x04) ? 0x4000 : 0x0; | ||
1316 | data[2] = 0x2082 | ((value & 0x04) ? 0x0005 : 0x0); | ||
1317 | data[2] |= (value & 0x02) ? 0x0150 : 0x0; | ||
1318 | data[2] |= (value & 0x01) ? 0x5400 : 0x0; | ||
1319 | data[3] = 0xfe1d; | ||
1320 | |||
1321 | err += w9968cf_write_fsb(cam, data); | ||
1322 | |||
1323 | /* Disable SBUS outputs */ | ||
1324 | err += w9968cf_write_sb(cam, 0x0000); | ||
1325 | |||
1326 | if (!err) | ||
1327 | DBG(5, "I2C write byte data done, addr.0x%04X, subaddr.0x%02X " | ||
1328 | "value 0x%02X", address, subaddress, value) | ||
1329 | else | ||
1330 | DBG(5, "I2C write byte data failed, addr.0x%04X, " | ||
1331 | "subaddr.0x%02X, value 0x%02X", | ||
1332 | address, subaddress, value) | ||
1333 | |||
1334 | return err; | ||
1335 | } | ||
1336 | |||
1337 | |||
1338 | /* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */ | ||
1339 | static int | ||
1340 | w9968cf_i2c_adap_read_byte_data(struct w9968cf_device* cam, | ||
1341 | u16 address, u8 subaddress, | ||
1342 | u8* value) | ||
1343 | { | ||
1344 | int err = 0; | ||
1345 | |||
1346 | /* Serial data enable */ | ||
1347 | err += w9968cf_write_sb(cam, 0x0013); /* don't change ! */ | ||
1348 | |||
1349 | err += w9968cf_smbus_start(cam); | ||
1350 | err += w9968cf_smbus_write_byte(cam, address); | ||
1351 | err += w9968cf_smbus_read_ack(cam); | ||
1352 | err += w9968cf_smbus_write_byte(cam, subaddress); | ||
1353 | err += w9968cf_smbus_read_ack(cam); | ||
1354 | err += w9968cf_smbus_stop(cam); | ||
1355 | err += w9968cf_smbus_start(cam); | ||
1356 | err += w9968cf_smbus_write_byte(cam, address + 1); | ||
1357 | err += w9968cf_smbus_read_ack(cam); | ||
1358 | err += w9968cf_smbus_read_byte(cam, value); | ||
1359 | err += w9968cf_smbus_write_ack(cam); | ||
1360 | err += w9968cf_smbus_stop(cam); | ||
1361 | |||
1362 | /* Serial data disable */ | ||
1363 | err += w9968cf_write_sb(cam, 0x0000); | ||
1364 | |||
1365 | if (!err) | ||
1366 | DBG(5, "I2C read byte data done, addr.0x%04X, " | ||
1367 | "subaddr.0x%02X, value 0x%02X", | ||
1368 | address, subaddress, *value) | ||
1369 | else | ||
1370 | DBG(5, "I2C read byte data failed, addr.0x%04X, " | ||
1371 | "subaddr.0x%02X, wrong value 0x%02X", | ||
1372 | address, subaddress, *value) | ||
1373 | |||
1374 | return err; | ||
1375 | } | ||
1376 | |||
1377 | |||
1378 | /* SMBus protocol: S Addr+1 Rd [A] [Value] NA P */ | ||
1379 | static int | ||
1380 | w9968cf_i2c_adap_read_byte(struct w9968cf_device* cam, | ||
1381 | u16 address, u8* value) | ||
1382 | { | ||
1383 | int err = 0; | ||
1384 | |||
1385 | /* Serial data enable */ | ||
1386 | err += w9968cf_write_sb(cam, 0x0013); | ||
1387 | |||
1388 | err += w9968cf_smbus_start(cam); | ||
1389 | err += w9968cf_smbus_write_byte(cam, address + 1); | ||
1390 | err += w9968cf_smbus_read_ack(cam); | ||
1391 | err += w9968cf_smbus_read_byte(cam, value); | ||
1392 | err += w9968cf_smbus_write_ack(cam); | ||
1393 | err += w9968cf_smbus_stop(cam); | ||
1394 | |||
1395 | /* Serial data disable */ | ||
1396 | err += w9968cf_write_sb(cam, 0x0000); | ||
1397 | |||
1398 | if (!err) | ||
1399 | DBG(5, "I2C read byte done, addr.0x%04X, " | ||
1400 | "value 0x%02X", address, *value) | ||
1401 | else | ||
1402 | DBG(5, "I2C read byte failed, addr.0x%04X, " | ||
1403 | "wrong value 0x%02X", address, *value) | ||
1404 | |||
1405 | return err; | ||
1406 | } | ||
1407 | |||
1408 | |||
1409 | /* SMBus protocol: S Addr Wr [A] Value [A] P */ | ||
1410 | static int | ||
1411 | w9968cf_i2c_adap_write_byte(struct w9968cf_device* cam, | ||
1412 | u16 address, u8 value) | ||
1413 | { | ||
1414 | DBG(4, "i2c_write_byte() is an unsupported transfer mode") | ||
1415 | return -EINVAL; | ||
1416 | } | ||
1417 | |||
1418 | |||
1419 | |||
1420 | /**************************************************************************** | ||
1421 | * I2C interface to kernel * | ||
1422 | ****************************************************************************/ | ||
1423 | |||
1424 | static int | ||
1425 | w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, | ||
1426 | unsigned short flags, char read_write, u8 command, | ||
1427 | int size, union i2c_smbus_data *data) | ||
1428 | { | ||
1429 | struct v4l2_device *v4l2_dev = i2c_get_adapdata(adapter); | ||
1430 | struct w9968cf_device *cam = to_cam(v4l2_dev); | ||
1431 | u8 i; | ||
1432 | int err = 0; | ||
1433 | |||
1434 | if (size == I2C_SMBUS_BYTE) { | ||
1435 | /* Why addr <<= 1? See OVXXX0_SID defines in ovcamchip.h */ | ||
1436 | addr <<= 1; | ||
1437 | |||
1438 | if (read_write == I2C_SMBUS_WRITE) | ||
1439 | err = w9968cf_i2c_adap_write_byte(cam, addr, command); | ||
1440 | else if (read_write == I2C_SMBUS_READ) | ||
1441 | for (i = 1; i <= W9968CF_I2C_RW_RETRIES; i++) { | ||
1442 | err = w9968cf_i2c_adap_read_byte(cam, addr, | ||
1443 | &data->byte); | ||
1444 | if (err) { | ||
1445 | if (w9968cf_smbus_refresh_bus(cam)) { | ||
1446 | err = -EIO; | ||
1447 | break; | ||
1448 | } | ||
1449 | } else | ||
1450 | break; | ||
1451 | } | ||
1452 | } else if (size == I2C_SMBUS_BYTE_DATA) { | ||
1453 | addr <<= 1; | ||
1454 | |||
1455 | if (read_write == I2C_SMBUS_WRITE) | ||
1456 | err = w9968cf_i2c_adap_fastwrite_byte_data(cam, addr, | ||
1457 | command, data->byte); | ||
1458 | else if (read_write == I2C_SMBUS_READ) { | ||
1459 | for (i = 1; i <= W9968CF_I2C_RW_RETRIES; i++) { | ||
1460 | err = w9968cf_i2c_adap_read_byte_data(cam,addr, | ||
1461 | command, &data->byte); | ||
1462 | if (err) { | ||
1463 | if (w9968cf_smbus_refresh_bus(cam)) { | ||
1464 | err = -EIO; | ||
1465 | break; | ||
1466 | } | ||
1467 | } else | ||
1468 | break; | ||
1469 | } | ||
1470 | |||
1471 | } else | ||
1472 | return -EINVAL; | ||
1473 | |||
1474 | } else { | ||
1475 | DBG(4, "Unsupported I2C transfer mode (%d)", size) | ||
1476 | return -EINVAL; | ||
1477 | } | ||
1478 | return err; | ||
1479 | } | ||
1480 | |||
1481 | |||
1482 | static u32 w9968cf_i2c_func(struct i2c_adapter* adap) | ||
1483 | { | ||
1484 | return I2C_FUNC_SMBUS_READ_BYTE | | ||
1485 | I2C_FUNC_SMBUS_READ_BYTE_DATA | | ||
1486 | I2C_FUNC_SMBUS_WRITE_BYTE_DATA; | ||
1487 | } | ||
1488 | |||
1489 | |||
1490 | static int w9968cf_i2c_init(struct w9968cf_device* cam) | ||
1491 | { | ||
1492 | int err = 0; | ||
1493 | |||
1494 | static struct i2c_algorithm algo = { | ||
1495 | .smbus_xfer = w9968cf_i2c_smbus_xfer, | ||
1496 | .functionality = w9968cf_i2c_func, | ||
1497 | }; | ||
1498 | |||
1499 | static struct i2c_adapter adap = { | ||
1500 | .owner = THIS_MODULE, | ||
1501 | .algo = &algo, | ||
1502 | }; | ||
1503 | |||
1504 | memcpy(&cam->i2c_adapter, &adap, sizeof(struct i2c_adapter)); | ||
1505 | strcpy(cam->i2c_adapter.name, "w9968cf"); | ||
1506 | cam->i2c_adapter.dev.parent = &cam->usbdev->dev; | ||
1507 | i2c_set_adapdata(&cam->i2c_adapter, &cam->v4l2_dev); | ||
1508 | |||
1509 | DBG(6, "Registering I2C adapter with kernel...") | ||
1510 | |||
1511 | err = i2c_add_adapter(&cam->i2c_adapter); | ||
1512 | if (err) | ||
1513 | DBG(1, "Failed to register the I2C adapter") | ||
1514 | else | ||
1515 | DBG(5, "I2C adapter registered") | ||
1516 | |||
1517 | return err; | ||
1518 | } | ||
1519 | |||
1520 | |||
1521 | |||
1522 | /**************************************************************************** | ||
1523 | * Helper functions * | ||
1524 | ****************************************************************************/ | ||
1525 | |||
1526 | /*-------------------------------------------------------------------------- | ||
1527 | Turn on the LED on some webcams. A beep should be heard too. | ||
1528 | Return 0 on success, a negative number otherwise. | ||
1529 | --------------------------------------------------------------------------*/ | ||
1530 | static int w9968cf_turn_on_led(struct w9968cf_device* cam) | ||
1531 | { | ||
1532 | int err = 0; | ||
1533 | |||
1534 | err += w9968cf_write_reg(cam, 0xff00, 0x00); /* power-down */ | ||
1535 | err += w9968cf_write_reg(cam, 0xbf17, 0x00); /* reset everything */ | ||
1536 | err += w9968cf_write_reg(cam, 0xbf10, 0x00); /* normal operation */ | ||
1537 | err += w9968cf_write_reg(cam, 0x0010, 0x01); /* serial bus, SDS high */ | ||
1538 | err += w9968cf_write_reg(cam, 0x0000, 0x01); /* serial bus, SDS low */ | ||
1539 | err += w9968cf_write_reg(cam, 0x0010, 0x01); /* ..high 'beep-beep' */ | ||
1540 | |||
1541 | if (err) | ||
1542 | DBG(2, "Couldn't turn on the LED") | ||
1543 | |||
1544 | DBG(5, "LED turned on") | ||
1545 | |||
1546 | return err; | ||
1547 | } | ||
1548 | |||
1549 | |||
1550 | /*-------------------------------------------------------------------------- | ||
1551 | Write some registers for the device initialization. | ||
1552 | This function is called once on open(). | ||
1553 | Return 0 on success, a negative number otherwise. | ||
1554 | --------------------------------------------------------------------------*/ | ||
1555 | static int w9968cf_init_chip(struct w9968cf_device* cam) | ||
1556 | { | ||
1557 | unsigned long hw_bufsize = cam->maxwidth*cam->maxheight*2, | ||
1558 | y0 = 0x0000, | ||
1559 | u0 = y0 + hw_bufsize/2, | ||
1560 | v0 = u0 + hw_bufsize/4, | ||
1561 | y1 = v0 + hw_bufsize/4, | ||
1562 | u1 = y1 + hw_bufsize/2, | ||
1563 | v1 = u1 + hw_bufsize/4; | ||
1564 | int err = 0; | ||
1565 | |||
1566 | err += w9968cf_write_reg(cam, 0xff00, 0x00); /* power off */ | ||
1567 | err += w9968cf_write_reg(cam, 0xbf10, 0x00); /* power on */ | ||
1568 | |||
1569 | err += w9968cf_write_reg(cam, 0x405d, 0x03); /* DRAM timings */ | ||
1570 | err += w9968cf_write_reg(cam, 0x0030, 0x04); /* SDRAM timings */ | ||
1571 | |||
1572 | err += w9968cf_write_reg(cam, y0 & 0xffff, 0x20); /* Y buf.0, low */ | ||
1573 | err += w9968cf_write_reg(cam, y0 >> 16, 0x21); /* Y buf.0, high */ | ||
1574 | err += w9968cf_write_reg(cam, u0 & 0xffff, 0x24); /* U buf.0, low */ | ||
1575 | err += w9968cf_write_reg(cam, u0 >> 16, 0x25); /* U buf.0, high */ | ||
1576 | err += w9968cf_write_reg(cam, v0 & 0xffff, 0x28); /* V buf.0, low */ | ||
1577 | err += w9968cf_write_reg(cam, v0 >> 16, 0x29); /* V buf.0, high */ | ||
1578 | |||
1579 | err += w9968cf_write_reg(cam, y1 & 0xffff, 0x22); /* Y buf.1, low */ | ||
1580 | err += w9968cf_write_reg(cam, y1 >> 16, 0x23); /* Y buf.1, high */ | ||
1581 | err += w9968cf_write_reg(cam, u1 & 0xffff, 0x26); /* U buf.1, low */ | ||
1582 | err += w9968cf_write_reg(cam, u1 >> 16, 0x27); /* U buf.1, high */ | ||
1583 | err += w9968cf_write_reg(cam, v1 & 0xffff, 0x2a); /* V buf.1, low */ | ||
1584 | err += w9968cf_write_reg(cam, v1 >> 16, 0x2b); /* V buf.1, high */ | ||
1585 | |||
1586 | err += w9968cf_write_reg(cam, y1 & 0xffff, 0x32); /* JPEG buf 0 low */ | ||
1587 | err += w9968cf_write_reg(cam, y1 >> 16, 0x33); /* JPEG buf 0 high */ | ||
1588 | |||
1589 | err += w9968cf_write_reg(cam, y1 & 0xffff, 0x34); /* JPEG buf 1 low */ | ||
1590 | err += w9968cf_write_reg(cam, y1 >> 16, 0x35); /* JPEG bug 1 high */ | ||
1591 | |||
1592 | err += w9968cf_write_reg(cam, 0x0000, 0x36);/* JPEG restart interval */ | ||
1593 | err += w9968cf_write_reg(cam, 0x0804, 0x37);/*JPEG VLE FIFO threshold*/ | ||
1594 | err += w9968cf_write_reg(cam, 0x0000, 0x38);/* disable hw up-scaling */ | ||
1595 | err += w9968cf_write_reg(cam, 0x0000, 0x3f); /* JPEG/MCTL test data */ | ||
1596 | |||
1597 | err += w9968cf_set_picture(cam, cam->picture); /* this before */ | ||
1598 | err += w9968cf_set_window(cam, cam->window); | ||
1599 | |||
1600 | if (err) | ||
1601 | DBG(1, "Chip initialization failed") | ||
1602 | else | ||
1603 | DBG(5, "Chip successfully initialized") | ||
1604 | |||
1605 | return err; | ||
1606 | } | ||
1607 | |||
1608 | |||
1609 | /*-------------------------------------------------------------------------- | ||
1610 | Return non-zero if the palette is supported, 0 otherwise. | ||
1611 | --------------------------------------------------------------------------*/ | ||
1612 | static inline u16 w9968cf_valid_palette(u16 palette) | ||
1613 | { | ||
1614 | u8 i = 0; | ||
1615 | while (w9968cf_formatlist[i].palette != 0) { | ||
1616 | if (palette == w9968cf_formatlist[i].palette) | ||
1617 | return palette; | ||
1618 | i++; | ||
1619 | } | ||
1620 | return 0; | ||
1621 | } | ||
1622 | |||
1623 | |||
1624 | /*-------------------------------------------------------------------------- | ||
1625 | Return the depth corresponding to the given palette. | ||
1626 | Palette _must_ be supported ! | ||
1627 | --------------------------------------------------------------------------*/ | ||
1628 | static inline u16 w9968cf_valid_depth(u16 palette) | ||
1629 | { | ||
1630 | u8 i=0; | ||
1631 | while (w9968cf_formatlist[i].palette != palette) | ||
1632 | i++; | ||
1633 | |||
1634 | return w9968cf_formatlist[i].depth; | ||
1635 | } | ||
1636 | |||
1637 | |||
1638 | /*-------------------------------------------------------------------------- | ||
1639 | Return non-zero if the format requires decompression, 0 otherwise. | ||
1640 | --------------------------------------------------------------------------*/ | ||
1641 | static inline u8 w9968cf_need_decompression(u16 palette) | ||
1642 | { | ||
1643 | u8 i = 0; | ||
1644 | while (w9968cf_formatlist[i].palette != 0) { | ||
1645 | if (palette == w9968cf_formatlist[i].palette) | ||
1646 | return w9968cf_formatlist[i].compression; | ||
1647 | i++; | ||
1648 | } | ||
1649 | return 0; | ||
1650 | } | ||
1651 | |||
1652 | |||
1653 | /*-------------------------------------------------------------------------- | ||
1654 | Change the picture settings of the camera. | ||
1655 | Return 0 on success, a negative number otherwise. | ||
1656 | --------------------------------------------------------------------------*/ | ||
1657 | static int | ||
1658 | w9968cf_set_picture(struct w9968cf_device* cam, struct video_picture pict) | ||
1659 | { | ||
1660 | u16 fmt, hw_depth, hw_palette, reg_v = 0x0000; | ||
1661 | int err = 0; | ||
1662 | |||
1663 | /* Make sure we are using a valid depth */ | ||
1664 | pict.depth = w9968cf_valid_depth(pict.palette); | ||
1665 | |||
1666 | fmt = pict.palette; | ||
1667 | |||
1668 | hw_depth = pict.depth; /* depth used by the winbond chip */ | ||
1669 | hw_palette = pict.palette; /* palette used by the winbond chip */ | ||
1670 | |||
1671 | /* VS & HS polarities */ | ||
1672 | reg_v = (cam->vs_polarity << 12) | (cam->hs_polarity << 11); | ||
1673 | |||
1674 | switch (fmt) | ||
1675 | { | ||
1676 | case VIDEO_PALETTE_UYVY: | ||
1677 | reg_v |= 0x0000; | ||
1678 | cam->vpp_flag = VPP_NONE; | ||
1679 | break; | ||
1680 | case VIDEO_PALETTE_YUV422P: | ||
1681 | reg_v |= 0x0002; | ||
1682 | cam->vpp_flag = VPP_DECOMPRESSION; | ||
1683 | break; | ||
1684 | case VIDEO_PALETTE_YUV420: | ||
1685 | case VIDEO_PALETTE_YUV420P: | ||
1686 | reg_v |= 0x0003; | ||
1687 | cam->vpp_flag = VPP_DECOMPRESSION; | ||
1688 | break; | ||
1689 | case VIDEO_PALETTE_YUYV: | ||
1690 | case VIDEO_PALETTE_YUV422: | ||
1691 | reg_v |= 0x0000; | ||
1692 | cam->vpp_flag = VPP_SWAP_YUV_BYTES; | ||
1693 | hw_palette = VIDEO_PALETTE_UYVY; | ||
1694 | break; | ||
1695 | /* Original video is used instead of RGBX palettes. | ||
1696 | Software conversion later. */ | ||
1697 | case VIDEO_PALETTE_GREY: | ||
1698 | case VIDEO_PALETTE_RGB555: | ||
1699 | case VIDEO_PALETTE_RGB565: | ||
1700 | case VIDEO_PALETTE_RGB24: | ||
1701 | case VIDEO_PALETTE_RGB32: | ||
1702 | reg_v |= 0x0000; /* UYVY 16 bit is used */ | ||
1703 | hw_depth = 16; | ||
1704 | hw_palette = VIDEO_PALETTE_UYVY; | ||
1705 | cam->vpp_flag = VPP_UYVY_TO_RGBX; | ||
1706 | break; | ||
1707 | } | ||
1708 | |||
1709 | /* NOTE: due to memory issues, it is better to disable the hardware | ||
1710 | double buffering during compression */ | ||
1711 | if (cam->double_buffer && !(cam->vpp_flag & VPP_DECOMPRESSION)) | ||
1712 | reg_v |= 0x0080; | ||
1713 | |||
1714 | if (cam->clamping) | ||
1715 | reg_v |= 0x0020; | ||
1716 | |||
1717 | if (cam->filter_type == 1) | ||
1718 | reg_v |= 0x0008; | ||
1719 | else if (cam->filter_type == 2) | ||
1720 | reg_v |= 0x000c; | ||
1721 | |||
1722 | if ((err = w9968cf_write_reg(cam, reg_v, 0x16))) | ||
1723 | goto error; | ||
1724 | |||
1725 | if ((err = w9968cf_sensor_update_picture(cam, pict))) | ||
1726 | goto error; | ||
1727 | |||
1728 | /* If all went well, update the device data structure */ | ||
1729 | memcpy(&cam->picture, &pict, sizeof(pict)); | ||
1730 | cam->hw_depth = hw_depth; | ||
1731 | cam->hw_palette = hw_palette; | ||
1732 | |||
1733 | /* Settings changed, so we clear the frame buffers */ | ||
1734 | memset(cam->frame[0].buffer, 0, cam->nbuffers*cam->frame[0].size); | ||
1735 | |||
1736 | DBG(4, "Palette is %s, depth is %u bpp", | ||
1737 | symbolic(v4l1_plist, pict.palette), pict.depth) | ||
1738 | |||
1739 | return 0; | ||
1740 | |||
1741 | error: | ||
1742 | DBG(1, "Failed to change picture settings") | ||
1743 | return err; | ||
1744 | } | ||
1745 | |||
1746 | |||
1747 | /*-------------------------------------------------------------------------- | ||
1748 | Change the capture area size of the camera. | ||
1749 | This function _must_ be called _after_ w9968cf_set_picture(). | ||
1750 | Return 0 on success, a negative number otherwise. | ||
1751 | --------------------------------------------------------------------------*/ | ||
1752 | static int | ||
1753 | w9968cf_set_window(struct w9968cf_device* cam, struct video_window win) | ||
1754 | { | ||
1755 | u16 x, y, w, h, scx, scy, cw, ch, ax, ay; | ||
1756 | unsigned long fw, fh; | ||
1757 | struct ovcamchip_window s_win; | ||
1758 | int err = 0; | ||
1759 | |||
1760 | /* Work around to avoid FP arithmetics */ | ||
1761 | #define SC(x) ((x) << 10) | ||
1762 | #define UNSC(x) ((x) >> 10) | ||
1763 | |||
1764 | /* Make sure we are using a supported resolution */ | ||
1765 | if ((err = w9968cf_adjust_window_size(cam, &win.width, &win.height))) | ||
1766 | goto error; | ||
1767 | |||
1768 | /* Scaling factors */ | ||
1769 | fw = SC(win.width) / cam->maxwidth; | ||
1770 | fh = SC(win.height) / cam->maxheight; | ||
1771 | |||
1772 | /* Set up the width and height values used by the chip */ | ||
1773 | if ((win.width > cam->maxwidth) || (win.height > cam->maxheight)) { | ||
1774 | cam->vpp_flag |= VPP_UPSCALE; | ||
1775 | /* Calculate largest w,h mantaining the same w/h ratio */ | ||
1776 | w = (fw >= fh) ? cam->maxwidth : SC(win.width)/fh; | ||
1777 | h = (fw >= fh) ? SC(win.height)/fw : cam->maxheight; | ||
1778 | if (w < cam->minwidth) /* just in case */ | ||
1779 | w = cam->minwidth; | ||
1780 | if (h < cam->minheight) /* just in case */ | ||
1781 | h = cam->minheight; | ||
1782 | } else { | ||
1783 | cam->vpp_flag &= ~VPP_UPSCALE; | ||
1784 | w = win.width; | ||
1785 | h = win.height; | ||
1786 | } | ||
1787 | |||
1788 | /* x,y offsets of the cropped area */ | ||
1789 | scx = cam->start_cropx; | ||
1790 | scy = cam->start_cropy; | ||
1791 | |||
1792 | /* Calculate cropped area manteining the right w/h ratio */ | ||
1793 | if (cam->largeview && !(cam->vpp_flag & VPP_UPSCALE)) { | ||
1794 | cw = (fw >= fh) ? cam->maxwidth : SC(win.width)/fh; | ||
1795 | ch = (fw >= fh) ? SC(win.height)/fw : cam->maxheight; | ||
1796 | } else { | ||
1797 | cw = w; | ||
1798 | ch = h; | ||
1799 | } | ||
1800 | |||
1801 | /* Setup the window of the sensor */ | ||
1802 | s_win.format = VIDEO_PALETTE_UYVY; | ||
1803 | s_win.width = cam->maxwidth; | ||
1804 | s_win.height = cam->maxheight; | ||
1805 | s_win.quarter = 0; /* full progressive video */ | ||
1806 | |||
1807 | /* Center it */ | ||
1808 | s_win.x = (s_win.width - cw) / 2; | ||
1809 | s_win.y = (s_win.height - ch) / 2; | ||
1810 | |||
1811 | /* Clock divisor */ | ||
1812 | if (cam->clockdiv >= 0) | ||
1813 | s_win.clockdiv = cam->clockdiv; /* manual override */ | ||
1814 | else | ||
1815 | switch (cam->sensor) { | ||
1816 | case CC_OV6620: | ||
1817 | s_win.clockdiv = 0; | ||
1818 | break; | ||
1819 | case CC_OV6630: | ||
1820 | s_win.clockdiv = 0; | ||
1821 | break; | ||
1822 | case CC_OV76BE: | ||
1823 | case CC_OV7610: | ||
1824 | case CC_OV7620: | ||
1825 | s_win.clockdiv = 0; | ||
1826 | break; | ||
1827 | default: | ||
1828 | s_win.clockdiv = W9968CF_DEF_CLOCKDIVISOR; | ||
1829 | } | ||
1830 | |||
1831 | /* We have to scale win.x and win.y offsets */ | ||
1832 | if ( (cam->largeview && !(cam->vpp_flag & VPP_UPSCALE)) | ||
1833 | || (cam->vpp_flag & VPP_UPSCALE) ) { | ||
1834 | ax = SC(win.x)/fw; | ||
1835 | ay = SC(win.y)/fh; | ||
1836 | } else { | ||
1837 | ax = win.x; | ||
1838 | ay = win.y; | ||
1839 | } | ||
1840 | |||
1841 | if ((ax + cw) > cam->maxwidth) | ||
1842 | ax = cam->maxwidth - cw; | ||
1843 | |||
1844 | if ((ay + ch) > cam->maxheight) | ||
1845 | ay = cam->maxheight - ch; | ||
1846 | |||
1847 | /* Adjust win.x, win.y */ | ||
1848 | if ( (cam->largeview && !(cam->vpp_flag & VPP_UPSCALE)) | ||
1849 | || (cam->vpp_flag & VPP_UPSCALE) ) { | ||
1850 | win.x = UNSC(ax*fw); | ||
1851 | win.y = UNSC(ay*fh); | ||
1852 | } else { | ||
1853 | win.x = ax; | ||
1854 | win.y = ay; | ||
1855 | } | ||
1856 | |||
1857 | /* Offsets used by the chip */ | ||
1858 | x = ax + s_win.x; | ||
1859 | y = ay + s_win.y; | ||
1860 | |||
1861 | /* Go ! */ | ||
1862 | if ((err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_S_MODE, &s_win))) | ||
1863 | goto error; | ||
1864 | |||
1865 | err += w9968cf_write_reg(cam, scx + x, 0x10); | ||
1866 | err += w9968cf_write_reg(cam, scy + y, 0x11); | ||
1867 | err += w9968cf_write_reg(cam, scx + x + cw, 0x12); | ||
1868 | err += w9968cf_write_reg(cam, scy + y + ch, 0x13); | ||
1869 | err += w9968cf_write_reg(cam, w, 0x14); | ||
1870 | err += w9968cf_write_reg(cam, h, 0x15); | ||
1871 | |||
1872 | /* JPEG width & height */ | ||
1873 | err += w9968cf_write_reg(cam, w, 0x30); | ||
1874 | err += w9968cf_write_reg(cam, h, 0x31); | ||
1875 | |||
1876 | /* Y & UV frame buffer strides (in WORD) */ | ||
1877 | if (cam->vpp_flag & VPP_DECOMPRESSION) { | ||
1878 | err += w9968cf_write_reg(cam, w/2, 0x2c); | ||
1879 | err += w9968cf_write_reg(cam, w/4, 0x2d); | ||
1880 | } else | ||
1881 | err += w9968cf_write_reg(cam, w, 0x2c); | ||
1882 | |||
1883 | if (err) | ||
1884 | goto error; | ||
1885 | |||
1886 | /* If all went well, update the device data structure */ | ||
1887 | memcpy(&cam->window, &win, sizeof(win)); | ||
1888 | cam->hw_width = w; | ||
1889 | cam->hw_height = h; | ||
1890 | |||
1891 | /* Settings changed, so we clear the frame buffers */ | ||
1892 | memset(cam->frame[0].buffer, 0, cam->nbuffers*cam->frame[0].size); | ||
1893 | |||
1894 | DBG(4, "The capture area is %dx%d, Offset (x,y)=(%u,%u)", | ||
1895 | win.width, win.height, win.x, win.y) | ||
1896 | |||
1897 | PDBGG("x=%u ,y=%u, w=%u, h=%u, ax=%u, ay=%u, s_win.x=%u, s_win.y=%u, " | ||
1898 | "cw=%u, ch=%u, win.x=%u, win.y=%u, win.width=%u, win.height=%u", | ||
1899 | x, y, w, h, ax, ay, s_win.x, s_win.y, cw, ch, win.x, win.y, | ||
1900 | win.width, win.height) | ||
1901 | |||
1902 | return 0; | ||
1903 | |||
1904 | error: | ||
1905 | DBG(1, "Failed to change the capture area size") | ||
1906 | return err; | ||
1907 | } | ||
1908 | |||
1909 | |||
1910 | /*-------------------------------------------------------------------------- | ||
1911 | Adjust the asked values for window width and height. | ||
1912 | Return 0 on success, -1 otherwise. | ||
1913 | --------------------------------------------------------------------------*/ | ||
1914 | static int | ||
1915 | w9968cf_adjust_window_size(struct w9968cf_device *cam, u32 *width, u32 *height) | ||
1916 | { | ||
1917 | unsigned int maxw, maxh, align; | ||
1918 | |||
1919 | maxw = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) && | ||
1920 | w9968cf_vpp ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth) | ||
1921 | : cam->maxwidth; | ||
1922 | maxh = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) && | ||
1923 | w9968cf_vpp ? max((u16)W9968CF_MAX_HEIGHT, cam->maxheight) | ||
1924 | : cam->maxheight; | ||
1925 | align = (cam->vpp_flag & VPP_DECOMPRESSION) ? 4 : 0; | ||
1926 | |||
1927 | v4l_bound_align_image(width, cam->minwidth, maxw, align, | ||
1928 | height, cam->minheight, maxh, align, 0); | ||
1929 | |||
1930 | PDBGG("Window size adjusted w=%u, h=%u ", *width, *height) | ||
1931 | |||
1932 | return 0; | ||
1933 | } | ||
1934 | |||
1935 | |||
1936 | /*-------------------------------------------------------------------------- | ||
1937 | Initialize the FIFO list of requested frames. | ||
1938 | --------------------------------------------------------------------------*/ | ||
1939 | static void w9968cf_init_framelist(struct w9968cf_device* cam) | ||
1940 | { | ||
1941 | u8 i; | ||
1942 | |||
1943 | for (i = 0; i < cam->nbuffers; i++) { | ||
1944 | cam->requested_frame[i] = NULL; | ||
1945 | cam->frame[i].queued = 0; | ||
1946 | cam->frame[i].status = F_UNUSED; | ||
1947 | } | ||
1948 | } | ||
1949 | |||
1950 | |||
1951 | /*-------------------------------------------------------------------------- | ||
1952 | Add a frame in the FIFO list of requested frames. | ||
1953 | This function is called in process context. | ||
1954 | --------------------------------------------------------------------------*/ | ||
1955 | static void w9968cf_push_frame(struct w9968cf_device* cam, u8 f_num) | ||
1956 | { | ||
1957 | u8 f; | ||
1958 | unsigned long lock_flags; | ||
1959 | |||
1960 | spin_lock_irqsave(&cam->flist_lock, lock_flags); | ||
1961 | |||
1962 | for (f=0; cam->requested_frame[f] != NULL; f++); | ||
1963 | cam->requested_frame[f] = &cam->frame[f_num]; | ||
1964 | cam->frame[f_num].queued = 1; | ||
1965 | cam->frame[f_num].status = F_UNUSED; /* clear the status */ | ||
1966 | |||
1967 | spin_unlock_irqrestore(&cam->flist_lock, lock_flags); | ||
1968 | |||
1969 | DBG(6, "Frame #%u pushed into the FIFO list. Position %u", f_num, f) | ||
1970 | } | ||
1971 | |||
1972 | |||
1973 | /*-------------------------------------------------------------------------- | ||
1974 | Read, store and remove the first pointer in the FIFO list of requested | ||
1975 | frames. This function is called in interrupt context. | ||
1976 | --------------------------------------------------------------------------*/ | ||
1977 | static void | ||
1978 | w9968cf_pop_frame(struct w9968cf_device* cam, struct w9968cf_frame_t** framep) | ||
1979 | { | ||
1980 | u8 i; | ||
1981 | |||
1982 | spin_lock(&cam->flist_lock); | ||
1983 | |||
1984 | *framep = cam->requested_frame[0]; | ||
1985 | |||
1986 | /* Shift the list of pointers */ | ||
1987 | for (i = 0; i < cam->nbuffers-1; i++) | ||
1988 | cam->requested_frame[i] = cam->requested_frame[i+1]; | ||
1989 | cam->requested_frame[i] = NULL; | ||
1990 | |||
1991 | spin_unlock(&cam->flist_lock); | ||
1992 | |||
1993 | DBG(6,"Popped frame #%d from the list", (*framep)->number) | ||
1994 | } | ||
1995 | |||
1996 | |||
1997 | /*-------------------------------------------------------------------------- | ||
1998 | High-level video post-processing routine on grabbed frames. | ||
1999 | Return 0 on success, a negative number otherwise. | ||
2000 | --------------------------------------------------------------------------*/ | ||
2001 | static int | ||
2002 | w9968cf_postprocess_frame(struct w9968cf_device* cam, | ||
2003 | struct w9968cf_frame_t* fr) | ||
2004 | { | ||
2005 | void *pIn = fr->buffer, *pOut = cam->frame_vpp.buffer, *tmp; | ||
2006 | u16 w = cam->window.width, | ||
2007 | h = cam->window.height, | ||
2008 | d = cam->picture.depth, | ||
2009 | fmt = cam->picture.palette, | ||
2010 | rgb = cam->force_rgb, | ||
2011 | hw_w = cam->hw_width, | ||
2012 | hw_h = cam->hw_height, | ||
2013 | hw_d = cam->hw_depth; | ||
2014 | int err = 0; | ||
2015 | |||
2016 | #define _PSWAP(pIn, pOut) {tmp = (pIn); (pIn) = (pOut); (pOut) = tmp;} | ||
2017 | |||
2018 | if (cam->vpp_flag & VPP_DECOMPRESSION) { | ||
2019 | memcpy(pOut, pIn, fr->length); | ||
2020 | _PSWAP(pIn, pOut) | ||
2021 | err = w9968cf_vpp->decode(pIn, fr->length, hw_w, hw_h, pOut); | ||
2022 | PDBGG("Compressed frame length: %lu",(unsigned long)fr->length) | ||
2023 | fr->length = (hw_w*hw_h*hw_d)/8; | ||
2024 | _PSWAP(pIn, pOut) | ||
2025 | if (err) { | ||
2026 | DBG(4, "An error occurred while decoding the frame: " | ||
2027 | "%s", symbolic(decoder_errlist, err)) | ||
2028 | return err; | ||
2029 | } else | ||
2030 | DBG(6, "Frame decoded") | ||
2031 | } | ||
2032 | |||
2033 | if (cam->vpp_flag & VPP_SWAP_YUV_BYTES) { | ||
2034 | w9968cf_vpp->swap_yuvbytes(pIn, fr->length); | ||
2035 | DBG(6, "Original UYVY component ordering changed") | ||
2036 | } | ||
2037 | |||
2038 | if (cam->vpp_flag & VPP_UPSCALE) { | ||
2039 | w9968cf_vpp->scale_up(pIn, pOut, hw_w, hw_h, hw_d, w, h); | ||
2040 | fr->length = (w*h*hw_d)/8; | ||
2041 | _PSWAP(pIn, pOut) | ||
2042 | DBG(6, "Vertical up-scaling done: %u,%u,%ubpp->%u,%u", | ||
2043 | hw_w, hw_h, hw_d, w, h) | ||
2044 | } | ||
2045 | |||
2046 | if (cam->vpp_flag & VPP_UYVY_TO_RGBX) { | ||
2047 | w9968cf_vpp->uyvy_to_rgbx(pIn, fr->length, pOut, fmt, rgb); | ||
2048 | fr->length = (w*h*d)/8; | ||
2049 | _PSWAP(pIn, pOut) | ||
2050 | DBG(6, "UYVY-16bit to %s conversion done", | ||
2051 | symbolic(v4l1_plist, fmt)) | ||
2052 | } | ||
2053 | |||
2054 | if (pOut == fr->buffer) | ||
2055 | memcpy(fr->buffer, cam->frame_vpp.buffer, fr->length); | ||
2056 | |||
2057 | return 0; | ||
2058 | } | ||
2059 | |||
2060 | |||
2061 | |||
2062 | /**************************************************************************** | ||
2063 | * Image sensor control routines * | ||
2064 | ****************************************************************************/ | ||
2065 | |||
2066 | static int | ||
2067 | w9968cf_sensor_set_control(struct w9968cf_device* cam, int cid, int val) | ||
2068 | { | ||
2069 | struct ovcamchip_control ctl; | ||
2070 | int err; | ||
2071 | |||
2072 | ctl.id = cid; | ||
2073 | ctl.value = val; | ||
2074 | |||
2075 | err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_S_CTRL, &ctl); | ||
2076 | |||
2077 | return err; | ||
2078 | } | ||
2079 | |||
2080 | |||
2081 | static int | ||
2082 | w9968cf_sensor_get_control(struct w9968cf_device* cam, int cid, int* val) | ||
2083 | { | ||
2084 | struct ovcamchip_control ctl; | ||
2085 | int err; | ||
2086 | |||
2087 | ctl.id = cid; | ||
2088 | |||
2089 | err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_G_CTRL, &ctl); | ||
2090 | if (!err) | ||
2091 | *val = ctl.value; | ||
2092 | |||
2093 | return err; | ||
2094 | } | ||
2095 | |||
2096 | |||
2097 | static int | ||
2098 | w9968cf_sensor_cmd(struct w9968cf_device* cam, unsigned int cmd, void* arg) | ||
2099 | { | ||
2100 | int rc; | ||
2101 | |||
2102 | rc = v4l2_subdev_call(cam->sensor_sd, core, ioctl, cmd, arg); | ||
2103 | /* The I2C driver returns -EPERM on non-supported controls */ | ||
2104 | return (rc < 0 && rc != -EPERM) ? rc : 0; | ||
2105 | } | ||
2106 | |||
2107 | |||
2108 | /*-------------------------------------------------------------------------- | ||
2109 | Update some settings of the image sensor. | ||
2110 | Returns: 0 on success, a negative number otherwise. | ||
2111 | --------------------------------------------------------------------------*/ | ||
2112 | static int w9968cf_sensor_update_settings(struct w9968cf_device* cam) | ||
2113 | { | ||
2114 | int err = 0; | ||
2115 | |||
2116 | /* Auto brightness */ | ||
2117 | err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_AUTOBRIGHT, | ||
2118 | cam->auto_brt); | ||
2119 | if (err) | ||
2120 | return err; | ||
2121 | |||
2122 | /* Auto exposure */ | ||
2123 | err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_AUTOEXP, | ||
2124 | cam->auto_exp); | ||
2125 | if (err) | ||
2126 | return err; | ||
2127 | |||
2128 | /* Banding filter */ | ||
2129 | err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BANDFILT, | ||
2130 | cam->bandfilt); | ||
2131 | if (err) | ||
2132 | return err; | ||
2133 | |||
2134 | /* Light frequency */ | ||
2135 | err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_FREQ, | ||
2136 | cam->lightfreq); | ||
2137 | if (err) | ||
2138 | return err; | ||
2139 | |||
2140 | /* Back light */ | ||
2141 | err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BACKLIGHT, | ||
2142 | cam->backlight); | ||
2143 | if (err) | ||
2144 | return err; | ||
2145 | |||
2146 | /* Mirror */ | ||
2147 | err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_MIRROR, | ||
2148 | cam->mirror); | ||
2149 | if (err) | ||
2150 | return err; | ||
2151 | |||
2152 | return 0; | ||
2153 | } | ||
2154 | |||
2155 | |||
2156 | /*-------------------------------------------------------------------------- | ||
2157 | Get some current picture settings from the image sensor and update the | ||
2158 | internal 'picture' structure of the camera. | ||
2159 | Returns: 0 on success, a negative number otherwise. | ||
2160 | --------------------------------------------------------------------------*/ | ||
2161 | static int w9968cf_sensor_get_picture(struct w9968cf_device* cam) | ||
2162 | { | ||
2163 | int err, v; | ||
2164 | |||
2165 | err = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_CONT, &v); | ||
2166 | if (err) | ||
2167 | return err; | ||
2168 | cam->picture.contrast = v; | ||
2169 | |||
2170 | err = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_BRIGHT, &v); | ||
2171 | if (err) | ||
2172 | return err; | ||
2173 | cam->picture.brightness = v; | ||
2174 | |||
2175 | err = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_SAT, &v); | ||
2176 | if (err) | ||
2177 | return err; | ||
2178 | cam->picture.colour = v; | ||
2179 | |||
2180 | err = w9968cf_sensor_get_control(cam, OVCAMCHIP_CID_HUE, &v); | ||
2181 | if (err) | ||
2182 | return err; | ||
2183 | cam->picture.hue = v; | ||
2184 | |||
2185 | DBG(5, "Got picture settings from the image sensor") | ||
2186 | |||
2187 | PDBGG("Brightness, contrast, hue, colour, whiteness are " | ||
2188 | "%u,%u,%u,%u,%u", cam->picture.brightness,cam->picture.contrast, | ||
2189 | cam->picture.hue, cam->picture.colour, cam->picture.whiteness) | ||
2190 | |||
2191 | return 0; | ||
2192 | } | ||
2193 | |||
2194 | |||
2195 | /*-------------------------------------------------------------------------- | ||
2196 | Update picture settings of the image sensor. | ||
2197 | Returns: 0 on success, a negative number otherwise. | ||
2198 | --------------------------------------------------------------------------*/ | ||
2199 | static int | ||
2200 | w9968cf_sensor_update_picture(struct w9968cf_device* cam, | ||
2201 | struct video_picture pict) | ||
2202 | { | ||
2203 | int err = 0; | ||
2204 | |||
2205 | if ((!cam->sensor_initialized) | ||
2206 | || pict.contrast != cam->picture.contrast) { | ||
2207 | err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_CONT, | ||
2208 | pict.contrast); | ||
2209 | if (err) | ||
2210 | goto fail; | ||
2211 | DBG(4, "Contrast changed from %u to %u", | ||
2212 | cam->picture.contrast, pict.contrast) | ||
2213 | cam->picture.contrast = pict.contrast; | ||
2214 | } | ||
2215 | |||
2216 | if (((!cam->sensor_initialized) || | ||
2217 | pict.brightness != cam->picture.brightness) && (!cam->auto_brt)) { | ||
2218 | err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BRIGHT, | ||
2219 | pict.brightness); | ||
2220 | if (err) | ||
2221 | goto fail; | ||
2222 | DBG(4, "Brightness changed from %u to %u", | ||
2223 | cam->picture.brightness, pict.brightness) | ||
2224 | cam->picture.brightness = pict.brightness; | ||
2225 | } | ||
2226 | |||
2227 | if ((!cam->sensor_initialized) || pict.colour != cam->picture.colour) { | ||
2228 | err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_SAT, | ||
2229 | pict.colour); | ||
2230 | if (err) | ||
2231 | goto fail; | ||
2232 | DBG(4, "Colour changed from %u to %u", | ||
2233 | cam->picture.colour, pict.colour) | ||
2234 | cam->picture.colour = pict.colour; | ||
2235 | } | ||
2236 | |||
2237 | if ((!cam->sensor_initialized) || pict.hue != cam->picture.hue) { | ||
2238 | err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_HUE, | ||
2239 | pict.hue); | ||
2240 | if (err) | ||
2241 | goto fail; | ||
2242 | DBG(4, "Hue changed from %u to %u", | ||
2243 | cam->picture.hue, pict.hue) | ||
2244 | cam->picture.hue = pict.hue; | ||
2245 | } | ||
2246 | |||
2247 | return 0; | ||
2248 | |||
2249 | fail: | ||
2250 | DBG(4, "Failed to change sensor picture setting") | ||
2251 | return err; | ||
2252 | } | ||
2253 | |||
2254 | |||
2255 | |||
2256 | /**************************************************************************** | ||
2257 | * Camera configuration * | ||
2258 | ****************************************************************************/ | ||
2259 | |||
2260 | /*-------------------------------------------------------------------------- | ||
2261 | This function is called when a supported image sensor is detected. | ||
2262 | Return 0 if the initialization succeeds, a negative number otherwise. | ||
2263 | --------------------------------------------------------------------------*/ | ||
2264 | static int w9968cf_sensor_init(struct w9968cf_device* cam) | ||
2265 | { | ||
2266 | int err = 0; | ||
2267 | |||
2268 | if ((err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_INITIALIZE, | ||
2269 | &cam->monochrome))) | ||
2270 | goto error; | ||
2271 | |||
2272 | if ((err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_Q_SUBTYPE, | ||
2273 | &cam->sensor))) | ||
2274 | goto error; | ||
2275 | |||
2276 | /* NOTE: Make sure width and height are a multiple of 16 */ | ||
2277 | switch (v4l2_i2c_subdev_addr(cam->sensor_sd)) { | ||
2278 | case OV6xx0_SID: | ||
2279 | cam->maxwidth = 352; | ||
2280 | cam->maxheight = 288; | ||
2281 | cam->minwidth = 64; | ||
2282 | cam->minheight = 48; | ||
2283 | break; | ||
2284 | case OV7xx0_SID: | ||
2285 | cam->maxwidth = 640; | ||
2286 | cam->maxheight = 480; | ||
2287 | cam->minwidth = 64; | ||
2288 | cam->minheight = 48; | ||
2289 | break; | ||
2290 | default: | ||
2291 | DBG(1, "Not supported image sensor detected for %s", | ||
2292 | symbolic(camlist, cam->id)) | ||
2293 | return -EINVAL; | ||
2294 | } | ||
2295 | |||
2296 | /* These values depend on the ones in the ovxxx0.c sources */ | ||
2297 | switch (cam->sensor) { | ||
2298 | case CC_OV7620: | ||
2299 | cam->start_cropx = 287; | ||
2300 | cam->start_cropy = 35; | ||
2301 | /* Seems to work around a bug in the image sensor */ | ||
2302 | cam->vs_polarity = 1; | ||
2303 | cam->hs_polarity = 1; | ||
2304 | break; | ||
2305 | default: | ||
2306 | cam->start_cropx = 320; | ||
2307 | cam->start_cropy = 35; | ||
2308 | cam->vs_polarity = 1; | ||
2309 | cam->hs_polarity = 0; | ||
2310 | } | ||
2311 | |||
2312 | if ((err = w9968cf_sensor_update_settings(cam))) | ||
2313 | goto error; | ||
2314 | |||
2315 | if ((err = w9968cf_sensor_update_picture(cam, cam->picture))) | ||
2316 | goto error; | ||
2317 | |||
2318 | cam->sensor_initialized = 1; | ||
2319 | |||
2320 | DBG(2, "%s image sensor initialized", symbolic(senlist, cam->sensor)) | ||
2321 | return 0; | ||
2322 | |||
2323 | error: | ||
2324 | cam->sensor_initialized = 0; | ||
2325 | cam->sensor = CC_UNKNOWN; | ||
2326 | DBG(1, "Image sensor initialization failed for %s (%s). " | ||
2327 | "Try to detach and attach this device again", | ||
2328 | symbolic(camlist, cam->id), video_device_node_name(cam->v4ldev)) | ||
2329 | return err; | ||
2330 | } | ||
2331 | |||
2332 | |||
2333 | /*-------------------------------------------------------------------------- | ||
2334 | Fill some basic fields in the main device data structure. | ||
2335 | This function is called once on w9968cf_usb_probe() for each recognized | ||
2336 | camera. | ||
2337 | --------------------------------------------------------------------------*/ | ||
2338 | static void | ||
2339 | w9968cf_configure_camera(struct w9968cf_device* cam, | ||
2340 | struct usb_device* udev, | ||
2341 | enum w9968cf_model_id mod_id, | ||
2342 | const unsigned short dev_nr) | ||
2343 | { | ||
2344 | mutex_init(&cam->fileop_mutex); | ||
2345 | init_waitqueue_head(&cam->open); | ||
2346 | spin_lock_init(&cam->urb_lock); | ||
2347 | spin_lock_init(&cam->flist_lock); | ||
2348 | |||
2349 | cam->users = 0; | ||
2350 | cam->disconnected = 0; | ||
2351 | cam->id = mod_id; | ||
2352 | cam->sensor = CC_UNKNOWN; | ||
2353 | cam->sensor_initialized = 0; | ||
2354 | |||
2355 | /* Calculate the alternate setting number (from 1 to 16) | ||
2356 | according to the 'packet_size' module parameter */ | ||
2357 | if (packet_size[dev_nr] < W9968CF_MIN_PACKET_SIZE) | ||
2358 | packet_size[dev_nr] = W9968CF_MIN_PACKET_SIZE; | ||
2359 | for (cam->altsetting = 1; | ||
2360 | packet_size[dev_nr] < wMaxPacketSize[cam->altsetting-1]; | ||
2361 | cam->altsetting++); | ||
2362 | |||
2363 | cam->max_buffers = (max_buffers[dev_nr] < 2 || | ||
2364 | max_buffers[dev_nr] > W9968CF_MAX_BUFFERS) | ||
2365 | ? W9968CF_BUFFERS : (u8)max_buffers[dev_nr]; | ||
2366 | |||
2367 | cam->double_buffer = (double_buffer[dev_nr] == 0 || | ||
2368 | double_buffer[dev_nr] == 1) | ||
2369 | ? (u8)double_buffer[dev_nr]:W9968CF_DOUBLE_BUFFER; | ||
2370 | |||
2371 | cam->clamping = (clamping[dev_nr] == 0 || clamping[dev_nr] == 1) | ||
2372 | ? (u8)clamping[dev_nr] : W9968CF_CLAMPING; | ||
2373 | |||
2374 | cam->filter_type = (filter_type[dev_nr] == 0 || | ||
2375 | filter_type[dev_nr] == 1 || | ||
2376 | filter_type[dev_nr] == 2) | ||
2377 | ? (u8)filter_type[dev_nr] : W9968CF_FILTER_TYPE; | ||
2378 | |||
2379 | cam->capture = 1; | ||
2380 | |||
2381 | cam->largeview = (largeview[dev_nr] == 0 || largeview[dev_nr] == 1) | ||
2382 | ? (u8)largeview[dev_nr] : W9968CF_LARGEVIEW; | ||
2383 | |||
2384 | cam->decompression = (decompression[dev_nr] == 0 || | ||
2385 | decompression[dev_nr] == 1 || | ||
2386 | decompression[dev_nr] == 2) | ||
2387 | ? (u8)decompression[dev_nr]:W9968CF_DECOMPRESSION; | ||
2388 | |||
2389 | cam->upscaling = (upscaling[dev_nr] == 0 || | ||
2390 | upscaling[dev_nr] == 1) | ||
2391 | ? (u8)upscaling[dev_nr] : W9968CF_UPSCALING; | ||
2392 | |||
2393 | cam->auto_brt = (autobright[dev_nr] == 0 || autobright[dev_nr] == 1) | ||
2394 | ? (u8)autobright[dev_nr] : W9968CF_AUTOBRIGHT; | ||
2395 | |||
2396 | cam->auto_exp = (autoexp[dev_nr] == 0 || autoexp[dev_nr] == 1) | ||
2397 | ? (u8)autoexp[dev_nr] : W9968CF_AUTOEXP; | ||
2398 | |||
2399 | cam->lightfreq = (lightfreq[dev_nr] == 50 || lightfreq[dev_nr] == 60) | ||
2400 | ? (u8)lightfreq[dev_nr] : W9968CF_LIGHTFREQ; | ||
2401 | |||
2402 | cam->bandfilt = (bandingfilter[dev_nr] == 0 || | ||
2403 | bandingfilter[dev_nr] == 1) | ||
2404 | ? (u8)bandingfilter[dev_nr] : W9968CF_BANDINGFILTER; | ||
2405 | |||
2406 | cam->backlight = (backlight[dev_nr] == 0 || backlight[dev_nr] == 1) | ||
2407 | ? (u8)backlight[dev_nr] : W9968CF_BACKLIGHT; | ||
2408 | |||
2409 | cam->clockdiv = (clockdiv[dev_nr] == -1 || clockdiv[dev_nr] >= 0) | ||
2410 | ? (s8)clockdiv[dev_nr] : W9968CF_CLOCKDIV; | ||
2411 | |||
2412 | cam->mirror = (mirror[dev_nr] == 0 || mirror[dev_nr] == 1) | ||
2413 | ? (u8)mirror[dev_nr] : W9968CF_MIRROR; | ||
2414 | |||
2415 | cam->monochrome = (monochrome[dev_nr] == 0 || monochrome[dev_nr] == 1) | ||
2416 | ? monochrome[dev_nr] : W9968CF_MONOCHROME; | ||
2417 | |||
2418 | cam->picture.brightness = (u16)brightness[dev_nr]; | ||
2419 | cam->picture.hue = (u16)hue[dev_nr]; | ||
2420 | cam->picture.colour = (u16)colour[dev_nr]; | ||
2421 | cam->picture.contrast = (u16)contrast[dev_nr]; | ||
2422 | cam->picture.whiteness = (u16)whiteness[dev_nr]; | ||
2423 | if (w9968cf_valid_palette((u16)force_palette[dev_nr])) { | ||
2424 | cam->picture.palette = (u16)force_palette[dev_nr]; | ||
2425 | cam->force_palette = 1; | ||
2426 | } else { | ||
2427 | cam->force_palette = 0; | ||
2428 | if (cam->decompression == 0) | ||
2429 | cam->picture.palette = W9968CF_PALETTE_DECOMP_OFF; | ||
2430 | else if (cam->decompression == 1) | ||
2431 | cam->picture.palette = W9968CF_PALETTE_DECOMP_FORCE; | ||
2432 | else | ||
2433 | cam->picture.palette = W9968CF_PALETTE_DECOMP_ON; | ||
2434 | } | ||
2435 | cam->picture.depth = w9968cf_valid_depth(cam->picture.palette); | ||
2436 | |||
2437 | cam->force_rgb = (force_rgb[dev_nr] == 0 || force_rgb[dev_nr] == 1) | ||
2438 | ? (u8)force_rgb[dev_nr] : W9968CF_FORCE_RGB; | ||
2439 | |||
2440 | cam->window.x = 0; | ||
2441 | cam->window.y = 0; | ||
2442 | cam->window.width = W9968CF_WIDTH; | ||
2443 | cam->window.height = W9968CF_HEIGHT; | ||
2444 | cam->window.chromakey = 0; | ||
2445 | cam->window.clipcount = 0; | ||
2446 | cam->window.flags = 0; | ||
2447 | |||
2448 | DBG(3, "%s configured with settings #%u:", | ||
2449 | symbolic(camlist, cam->id), dev_nr) | ||
2450 | |||
2451 | DBG(3, "- Data packet size for USB isochrnous transfer: %u bytes", | ||
2452 | wMaxPacketSize[cam->altsetting-1]) | ||
2453 | |||
2454 | DBG(3, "- Number of requested video frame buffers: %u", | ||
2455 | cam->max_buffers) | ||
2456 | |||
2457 | if (cam->double_buffer) | ||
2458 | DBG(3, "- Hardware double buffering enabled") | ||
2459 | else | ||
2460 | DBG(3, "- Hardware double buffering disabled") | ||
2461 | |||
2462 | if (cam->filter_type == 0) | ||
2463 | DBG(3, "- Video filtering disabled") | ||
2464 | else if (cam->filter_type == 1) | ||
2465 | DBG(3, "- Video filtering enabled: type 1-2-1") | ||
2466 | else if (cam->filter_type == 2) | ||
2467 | DBG(3, "- Video filtering enabled: type 2-3-6-3-2") | ||
2468 | |||
2469 | if (cam->clamping) | ||
2470 | DBG(3, "- Video data clamping (CCIR-601 format) enabled") | ||
2471 | else | ||
2472 | DBG(3, "- Video data clamping (CCIR-601 format) disabled") | ||
2473 | |||
2474 | if (cam->largeview) | ||
2475 | DBG(3, "- Large view enabled") | ||
2476 | else | ||
2477 | DBG(3, "- Large view disabled") | ||
2478 | |||
2479 | if ((cam->decompression) == 0 && (!cam->force_palette)) | ||
2480 | DBG(3, "- Decompression disabled") | ||
2481 | else if ((cam->decompression) == 1 && (!cam->force_palette)) | ||
2482 | DBG(3, "- Decompression forced") | ||
2483 | else if ((cam->decompression) == 2 && (!cam->force_palette)) | ||
2484 | DBG(3, "- Decompression allowed") | ||
2485 | |||
2486 | if (cam->upscaling) | ||
2487 | DBG(3, "- Software image scaling enabled") | ||
2488 | else | ||
2489 | DBG(3, "- Software image scaling disabled") | ||
2490 | |||
2491 | if (cam->force_palette) | ||
2492 | DBG(3, "- Image palette forced to %s", | ||
2493 | symbolic(v4l1_plist, cam->picture.palette)) | ||
2494 | |||
2495 | if (cam->force_rgb) | ||
2496 | DBG(3, "- RGB component ordering will be used instead of BGR") | ||
2497 | |||
2498 | if (cam->auto_brt) | ||
2499 | DBG(3, "- Auto brightness enabled") | ||
2500 | else | ||
2501 | DBG(3, "- Auto brightness disabled") | ||
2502 | |||
2503 | if (cam->auto_exp) | ||
2504 | DBG(3, "- Auto exposure enabled") | ||
2505 | else | ||
2506 | DBG(3, "- Auto exposure disabled") | ||
2507 | |||
2508 | if (cam->backlight) | ||
2509 | DBG(3, "- Backlight exposure algorithm enabled") | ||
2510 | else | ||
2511 | DBG(3, "- Backlight exposure algorithm disabled") | ||
2512 | |||
2513 | if (cam->mirror) | ||
2514 | DBG(3, "- Mirror enabled") | ||
2515 | else | ||
2516 | DBG(3, "- Mirror disabled") | ||
2517 | |||
2518 | if (cam->bandfilt) | ||
2519 | DBG(3, "- Banding filter enabled") | ||
2520 | else | ||
2521 | DBG(3, "- Banding filter disabled") | ||
2522 | |||
2523 | DBG(3, "- Power lighting frequency: %u", cam->lightfreq) | ||
2524 | |||
2525 | if (cam->clockdiv == -1) | ||
2526 | DBG(3, "- Automatic clock divisor enabled") | ||
2527 | else | ||
2528 | DBG(3, "- Clock divisor: %d", cam->clockdiv) | ||
2529 | |||
2530 | if (cam->monochrome) | ||
2531 | DBG(3, "- Image sensor used as monochrome") | ||
2532 | else | ||
2533 | DBG(3, "- Image sensor not used as monochrome") | ||
2534 | } | ||
2535 | |||
2536 | |||
2537 | /*-------------------------------------------------------------------------- | ||
2538 | If the video post-processing module is not loaded, some parameters | ||
2539 | must be overridden. | ||
2540 | --------------------------------------------------------------------------*/ | ||
2541 | static void w9968cf_adjust_configuration(struct w9968cf_device* cam) | ||
2542 | { | ||
2543 | if (!w9968cf_vpp) { | ||
2544 | if (cam->decompression == 1) { | ||
2545 | cam->decompression = 2; | ||
2546 | DBG(2, "Video post-processing module not found: " | ||
2547 | "'decompression' parameter forced to 2") | ||
2548 | } | ||
2549 | if (cam->upscaling) { | ||
2550 | cam->upscaling = 0; | ||
2551 | DBG(2, "Video post-processing module not found: " | ||
2552 | "'upscaling' parameter forced to 0") | ||
2553 | } | ||
2554 | if (cam->picture.palette != VIDEO_PALETTE_UYVY) { | ||
2555 | cam->force_palette = 0; | ||
2556 | DBG(2, "Video post-processing module not found: " | ||
2557 | "'force_palette' parameter forced to 0") | ||
2558 | } | ||
2559 | cam->picture.palette = VIDEO_PALETTE_UYVY; | ||
2560 | cam->picture.depth = w9968cf_valid_depth(cam->picture.palette); | ||
2561 | } | ||
2562 | } | ||
2563 | |||
2564 | |||
2565 | /*-------------------------------------------------------------------------- | ||
2566 | Release the resources used by the driver. | ||
2567 | This function is called on disconnect | ||
2568 | (or on close if deallocation has been deferred) | ||
2569 | --------------------------------------------------------------------------*/ | ||
2570 | static void w9968cf_release_resources(struct w9968cf_device* cam) | ||
2571 | { | ||
2572 | mutex_lock(&w9968cf_devlist_mutex); | ||
2573 | |||
2574 | DBG(2, "V4L device deregistered: %s", | ||
2575 | video_device_node_name(cam->v4ldev)) | ||
2576 | |||
2577 | video_unregister_device(cam->v4ldev); | ||
2578 | list_del(&cam->v4llist); | ||
2579 | i2c_del_adapter(&cam->i2c_adapter); | ||
2580 | w9968cf_deallocate_memory(cam); | ||
2581 | kfree(cam->control_buffer); | ||
2582 | kfree(cam->data_buffer); | ||
2583 | v4l2_device_unregister(&cam->v4l2_dev); | ||
2584 | |||
2585 | mutex_unlock(&w9968cf_devlist_mutex); | ||
2586 | } | ||
2587 | |||
2588 | |||
2589 | |||
2590 | /**************************************************************************** | ||
2591 | * Video4Linux interface * | ||
2592 | ****************************************************************************/ | ||
2593 | |||
2594 | static int w9968cf_open(struct file *filp) | ||
2595 | { | ||
2596 | struct w9968cf_device* cam; | ||
2597 | int err; | ||
2598 | |||
2599 | /* This the only safe way to prevent race conditions with disconnect */ | ||
2600 | if (!down_read_trylock(&w9968cf_disconnect)) | ||
2601 | return -EAGAIN; | ||
2602 | |||
2603 | cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); | ||
2604 | |||
2605 | mutex_lock(&cam->dev_mutex); | ||
2606 | |||
2607 | if (cam->sensor == CC_UNKNOWN) { | ||
2608 | DBG(2, "No supported image sensor has been detected by the " | ||
2609 | "'ovcamchip' module for the %s (%s). Make sure " | ||
2610 | "it is loaded *before* (re)connecting the camera.", | ||
2611 | symbolic(camlist, cam->id), | ||
2612 | video_device_node_name(cam->v4ldev)) | ||
2613 | mutex_unlock(&cam->dev_mutex); | ||
2614 | up_read(&w9968cf_disconnect); | ||
2615 | return -ENODEV; | ||
2616 | } | ||
2617 | |||
2618 | if (cam->users) { | ||
2619 | DBG(2, "%s (%s) has been already occupied by '%s'", | ||
2620 | symbolic(camlist, cam->id), | ||
2621 | video_device_node_name(cam->v4ldev), cam->command) | ||
2622 | if ((filp->f_flags & O_NONBLOCK)||(filp->f_flags & O_NDELAY)) { | ||
2623 | mutex_unlock(&cam->dev_mutex); | ||
2624 | up_read(&w9968cf_disconnect); | ||
2625 | return -EWOULDBLOCK; | ||
2626 | } | ||
2627 | mutex_unlock(&cam->dev_mutex); | ||
2628 | err = wait_event_interruptible_exclusive(cam->open, | ||
2629 | cam->disconnected || | ||
2630 | !cam->users); | ||
2631 | if (err) { | ||
2632 | up_read(&w9968cf_disconnect); | ||
2633 | return err; | ||
2634 | } | ||
2635 | if (cam->disconnected) { | ||
2636 | up_read(&w9968cf_disconnect); | ||
2637 | return -ENODEV; | ||
2638 | } | ||
2639 | mutex_lock(&cam->dev_mutex); | ||
2640 | } | ||
2641 | |||
2642 | DBG(5, "Opening '%s', %s ...", | ||
2643 | symbolic(camlist, cam->id), video_device_node_name(cam->v4ldev)) | ||
2644 | |||
2645 | cam->streaming = 0; | ||
2646 | cam->misconfigured = 0; | ||
2647 | |||
2648 | w9968cf_adjust_configuration(cam); | ||
2649 | |||
2650 | if ((err = w9968cf_allocate_memory(cam))) | ||
2651 | goto deallocate_memory; | ||
2652 | |||
2653 | if ((err = w9968cf_init_chip(cam))) | ||
2654 | goto deallocate_memory; | ||
2655 | |||
2656 | if ((err = w9968cf_start_transfer(cam))) | ||
2657 | goto deallocate_memory; | ||
2658 | |||
2659 | filp->private_data = cam; | ||
2660 | |||
2661 | cam->users++; | ||
2662 | strcpy(cam->command, current->comm); | ||
2663 | |||
2664 | init_waitqueue_head(&cam->wait_queue); | ||
2665 | |||
2666 | DBG(5, "Video device is open") | ||
2667 | |||
2668 | mutex_unlock(&cam->dev_mutex); | ||
2669 | up_read(&w9968cf_disconnect); | ||
2670 | |||
2671 | return 0; | ||
2672 | |||
2673 | deallocate_memory: | ||
2674 | w9968cf_deallocate_memory(cam); | ||
2675 | DBG(2, "Failed to open the video device") | ||
2676 | mutex_unlock(&cam->dev_mutex); | ||
2677 | up_read(&w9968cf_disconnect); | ||
2678 | return err; | ||
2679 | } | ||
2680 | |||
2681 | |||
2682 | static int w9968cf_release(struct file *filp) | ||
2683 | { | ||
2684 | struct w9968cf_device* cam; | ||
2685 | |||
2686 | cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); | ||
2687 | |||
2688 | mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ | ||
2689 | |||
2690 | w9968cf_stop_transfer(cam); | ||
2691 | |||
2692 | if (cam->disconnected) { | ||
2693 | w9968cf_release_resources(cam); | ||
2694 | mutex_unlock(&cam->dev_mutex); | ||
2695 | kfree(cam); | ||
2696 | return 0; | ||
2697 | } | ||
2698 | |||
2699 | cam->users--; | ||
2700 | w9968cf_deallocate_memory(cam); | ||
2701 | wake_up_interruptible_nr(&cam->open, 1); | ||
2702 | |||
2703 | DBG(5, "Video device closed") | ||
2704 | mutex_unlock(&cam->dev_mutex); | ||
2705 | return 0; | ||
2706 | } | ||
2707 | |||
2708 | |||
2709 | static ssize_t | ||
2710 | w9968cf_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) | ||
2711 | { | ||
2712 | struct w9968cf_device* cam; | ||
2713 | struct w9968cf_frame_t* fr; | ||
2714 | int err = 0; | ||
2715 | |||
2716 | cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); | ||
2717 | |||
2718 | if (filp->f_flags & O_NONBLOCK) | ||
2719 | return -EWOULDBLOCK; | ||
2720 | |||
2721 | if (mutex_lock_interruptible(&cam->fileop_mutex)) | ||
2722 | return -ERESTARTSYS; | ||
2723 | |||
2724 | if (cam->disconnected) { | ||
2725 | DBG(2, "Device not present") | ||
2726 | mutex_unlock(&cam->fileop_mutex); | ||
2727 | return -ENODEV; | ||
2728 | } | ||
2729 | |||
2730 | if (cam->misconfigured) { | ||
2731 | DBG(2, "The camera is misconfigured. Close and open it again.") | ||
2732 | mutex_unlock(&cam->fileop_mutex); | ||
2733 | return -EIO; | ||
2734 | } | ||
2735 | |||
2736 | if (!cam->frame[0].queued) | ||
2737 | w9968cf_push_frame(cam, 0); | ||
2738 | |||
2739 | if (!cam->frame[1].queued) | ||
2740 | w9968cf_push_frame(cam, 1); | ||
2741 | |||
2742 | err = wait_event_interruptible(cam->wait_queue, | ||
2743 | cam->frame[0].status == F_READY || | ||
2744 | cam->frame[1].status == F_READY || | ||
2745 | cam->disconnected); | ||
2746 | if (err) { | ||
2747 | mutex_unlock(&cam->fileop_mutex); | ||
2748 | return err; | ||
2749 | } | ||
2750 | if (cam->disconnected) { | ||
2751 | mutex_unlock(&cam->fileop_mutex); | ||
2752 | return -ENODEV; | ||
2753 | } | ||
2754 | |||
2755 | fr = (cam->frame[0].status == F_READY) ? &cam->frame[0]:&cam->frame[1]; | ||
2756 | |||
2757 | if (w9968cf_vpp) | ||
2758 | w9968cf_postprocess_frame(cam, fr); | ||
2759 | |||
2760 | if (count > fr->length) | ||
2761 | count = fr->length; | ||
2762 | |||
2763 | if (copy_to_user(buf, fr->buffer, count)) { | ||
2764 | fr->status = F_UNUSED; | ||
2765 | mutex_unlock(&cam->fileop_mutex); | ||
2766 | return -EFAULT; | ||
2767 | } | ||
2768 | *f_pos += count; | ||
2769 | |||
2770 | fr->status = F_UNUSED; | ||
2771 | |||
2772 | DBG(5, "%zu bytes read", count) | ||
2773 | |||
2774 | mutex_unlock(&cam->fileop_mutex); | ||
2775 | return count; | ||
2776 | } | ||
2777 | |||
2778 | |||
2779 | static int w9968cf_mmap(struct file* filp, struct vm_area_struct *vma) | ||
2780 | { | ||
2781 | struct w9968cf_device* cam = (struct w9968cf_device*) | ||
2782 | video_get_drvdata(video_devdata(filp)); | ||
2783 | unsigned long vsize = vma->vm_end - vma->vm_start, | ||
2784 | psize = cam->nbuffers * cam->frame[0].size, | ||
2785 | start = vma->vm_start, | ||
2786 | pos = (unsigned long)cam->frame[0].buffer, | ||
2787 | page; | ||
2788 | |||
2789 | if (cam->disconnected) { | ||
2790 | DBG(2, "Device not present") | ||
2791 | return -ENODEV; | ||
2792 | } | ||
2793 | |||
2794 | if (cam->misconfigured) { | ||
2795 | DBG(2, "The camera is misconfigured. Close and open it again") | ||
2796 | return -EIO; | ||
2797 | } | ||
2798 | |||
2799 | PDBGG("mmapping %lu bytes...", vsize) | ||
2800 | |||
2801 | if (vsize > psize - (vma->vm_pgoff << PAGE_SHIFT)) | ||
2802 | return -EINVAL; | ||
2803 | |||
2804 | while (vsize > 0) { | ||
2805 | page = vmalloc_to_pfn((void *)pos); | ||
2806 | if (remap_pfn_range(vma, start, page + vma->vm_pgoff, | ||
2807 | PAGE_SIZE, vma->vm_page_prot)) | ||
2808 | return -EAGAIN; | ||
2809 | start += PAGE_SIZE; | ||
2810 | pos += PAGE_SIZE; | ||
2811 | vsize -= PAGE_SIZE; | ||
2812 | } | ||
2813 | |||
2814 | DBG(5, "mmap method successfully called") | ||
2815 | return 0; | ||
2816 | } | ||
2817 | |||
2818 | |||
2819 | static long | ||
2820 | w9968cf_ioctl(struct file *filp, | ||
2821 | unsigned int cmd, unsigned long arg) | ||
2822 | { | ||
2823 | struct w9968cf_device* cam; | ||
2824 | long err; | ||
2825 | |||
2826 | cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); | ||
2827 | |||
2828 | if (mutex_lock_interruptible(&cam->fileop_mutex)) | ||
2829 | return -ERESTARTSYS; | ||
2830 | |||
2831 | if (cam->disconnected) { | ||
2832 | DBG(2, "Device not present") | ||
2833 | mutex_unlock(&cam->fileop_mutex); | ||
2834 | return -ENODEV; | ||
2835 | } | ||
2836 | |||
2837 | if (cam->misconfigured) { | ||
2838 | DBG(2, "The camera is misconfigured. Close and open it again.") | ||
2839 | mutex_unlock(&cam->fileop_mutex); | ||
2840 | return -EIO; | ||
2841 | } | ||
2842 | |||
2843 | err = w9968cf_v4l_ioctl(filp, cmd, (void __user *)arg); | ||
2844 | |||
2845 | mutex_unlock(&cam->fileop_mutex); | ||
2846 | return err; | ||
2847 | } | ||
2848 | |||
2849 | |||
2850 | static long w9968cf_v4l_ioctl(struct file *filp, | ||
2851 | unsigned int cmd, void __user *arg) | ||
2852 | { | ||
2853 | struct w9968cf_device* cam; | ||
2854 | const char* v4l1_ioctls[] = { | ||
2855 | "?", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", | ||
2856 | "GPICT", "SPICT", "CCAPTURE", "GWIN", "SWIN", "GFBUF", | ||
2857 | "SFBUF", "KEY", "GFREQ", "SFREQ", "GAUDIO", "SAUDIO", | ||
2858 | "SYNC", "MCAPTURE", "GMBUF", "GUNIT", "GCAPTURE", "SCAPTURE", | ||
2859 | "SPLAYMODE", "SWRITEMODE", "GPLAYINFO", "SMICROCODE", | ||
2860 | "GVBIFMT", "SVBIFMT" | ||
2861 | }; | ||
2862 | |||
2863 | #define V4L1_IOCTL(cmd) \ | ||
2864 | ((_IOC_NR((cmd)) < ARRAY_SIZE(v4l1_ioctls)) ? \ | ||
2865 | v4l1_ioctls[_IOC_NR((cmd))] : "?") | ||
2866 | |||
2867 | cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); | ||
2868 | |||
2869 | switch (cmd) { | ||
2870 | |||
2871 | case VIDIOCGCAP: /* get video capability */ | ||
2872 | { | ||
2873 | struct video_capability cap = { | ||
2874 | .type = VID_TYPE_CAPTURE | VID_TYPE_SCALES, | ||
2875 | .channels = 1, | ||
2876 | .audios = 0, | ||
2877 | .minwidth = cam->minwidth, | ||
2878 | .minheight = cam->minheight, | ||
2879 | }; | ||
2880 | sprintf(cap.name, "W996[87]CF USB Camera"); | ||
2881 | cap.maxwidth = (cam->upscaling && w9968cf_vpp) | ||
2882 | ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth) | ||
2883 | : cam->maxwidth; | ||
2884 | cap.maxheight = (cam->upscaling && w9968cf_vpp) | ||
2885 | ? max((u16)W9968CF_MAX_HEIGHT, cam->maxheight) | ||
2886 | : cam->maxheight; | ||
2887 | |||
2888 | if (copy_to_user(arg, &cap, sizeof(cap))) | ||
2889 | return -EFAULT; | ||
2890 | |||
2891 | DBG(5, "VIDIOCGCAP successfully called") | ||
2892 | return 0; | ||
2893 | } | ||
2894 | |||
2895 | case VIDIOCGCHAN: /* get video channel informations */ | ||
2896 | { | ||
2897 | struct video_channel chan; | ||
2898 | if (copy_from_user(&chan, arg, sizeof(chan))) | ||
2899 | return -EFAULT; | ||
2900 | |||
2901 | if (chan.channel != 0) | ||
2902 | return -EINVAL; | ||
2903 | |||
2904 | strcpy(chan.name, "Camera"); | ||
2905 | chan.tuners = 0; | ||
2906 | chan.flags = 0; | ||
2907 | chan.type = VIDEO_TYPE_CAMERA; | ||
2908 | chan.norm = VIDEO_MODE_AUTO; | ||
2909 | |||
2910 | if (copy_to_user(arg, &chan, sizeof(chan))) | ||
2911 | return -EFAULT; | ||
2912 | |||
2913 | DBG(5, "VIDIOCGCHAN successfully called") | ||
2914 | return 0; | ||
2915 | } | ||
2916 | |||
2917 | case VIDIOCSCHAN: /* set active channel */ | ||
2918 | { | ||
2919 | struct video_channel chan; | ||
2920 | |||
2921 | if (copy_from_user(&chan, arg, sizeof(chan))) | ||
2922 | return -EFAULT; | ||
2923 | |||
2924 | if (chan.channel != 0) | ||
2925 | return -EINVAL; | ||
2926 | |||
2927 | DBG(5, "VIDIOCSCHAN successfully called") | ||
2928 | return 0; | ||
2929 | } | ||
2930 | |||
2931 | case VIDIOCGPICT: /* get image properties of the picture */ | ||
2932 | { | ||
2933 | if (w9968cf_sensor_get_picture(cam)) | ||
2934 | return -EIO; | ||
2935 | |||
2936 | if (copy_to_user(arg, &cam->picture, sizeof(cam->picture))) | ||
2937 | return -EFAULT; | ||
2938 | |||
2939 | DBG(5, "VIDIOCGPICT successfully called") | ||
2940 | return 0; | ||
2941 | } | ||
2942 | |||
2943 | case VIDIOCSPICT: /* change picture settings */ | ||
2944 | { | ||
2945 | struct video_picture pict; | ||
2946 | int err = 0; | ||
2947 | |||
2948 | if (copy_from_user(&pict, arg, sizeof(pict))) | ||
2949 | return -EFAULT; | ||
2950 | |||
2951 | if ( (cam->force_palette || !w9968cf_vpp) | ||
2952 | && pict.palette != cam->picture.palette ) { | ||
2953 | DBG(4, "Palette %s rejected: only %s is allowed", | ||
2954 | symbolic(v4l1_plist, pict.palette), | ||
2955 | symbolic(v4l1_plist, cam->picture.palette)) | ||
2956 | return -EINVAL; | ||
2957 | } | ||
2958 | |||
2959 | if (!w9968cf_valid_palette(pict.palette)) { | ||
2960 | DBG(4, "Palette %s not supported. VIDIOCSPICT failed", | ||
2961 | symbolic(v4l1_plist, pict.palette)) | ||
2962 | return -EINVAL; | ||
2963 | } | ||
2964 | |||
2965 | if (!cam->force_palette) { | ||
2966 | if (cam->decompression == 0) { | ||
2967 | if (w9968cf_need_decompression(pict.palette)) { | ||
2968 | DBG(4, "Decompression disabled: palette %s is not " | ||
2969 | "allowed. VIDIOCSPICT failed", | ||
2970 | symbolic(v4l1_plist, pict.palette)) | ||
2971 | return -EINVAL; | ||
2972 | } | ||
2973 | } else if (cam->decompression == 1) { | ||
2974 | if (!w9968cf_need_decompression(pict.palette)) { | ||
2975 | DBG(4, "Decompression forced: palette %s is not " | ||
2976 | "allowed. VIDIOCSPICT failed", | ||
2977 | symbolic(v4l1_plist, pict.palette)) | ||
2978 | return -EINVAL; | ||
2979 | } | ||
2980 | } | ||
2981 | } | ||
2982 | |||
2983 | if (pict.depth != w9968cf_valid_depth(pict.palette)) { | ||
2984 | DBG(4, "Requested depth %u bpp is not valid for %s " | ||
2985 | "palette: ignored and changed to %u bpp", | ||
2986 | pict.depth, symbolic(v4l1_plist, pict.palette), | ||
2987 | w9968cf_valid_depth(pict.palette)) | ||
2988 | pict.depth = w9968cf_valid_depth(pict.palette); | ||
2989 | } | ||
2990 | |||
2991 | if (pict.palette != cam->picture.palette) { | ||
2992 | if(*cam->requested_frame | ||
2993 | || cam->frame_current->queued) { | ||
2994 | err = wait_event_interruptible | ||
2995 | ( cam->wait_queue, | ||
2996 | cam->disconnected || | ||
2997 | (!*cam->requested_frame && | ||
2998 | !cam->frame_current->queued) ); | ||
2999 | if (err) | ||
3000 | return err; | ||
3001 | if (cam->disconnected) | ||
3002 | return -ENODEV; | ||
3003 | } | ||
3004 | |||
3005 | if (w9968cf_stop_transfer(cam)) | ||
3006 | goto ioctl_fail; | ||
3007 | |||
3008 | if (w9968cf_set_picture(cam, pict)) | ||
3009 | goto ioctl_fail; | ||
3010 | |||
3011 | if (w9968cf_start_transfer(cam)) | ||
3012 | goto ioctl_fail; | ||
3013 | |||
3014 | } else if (w9968cf_sensor_update_picture(cam, pict)) | ||
3015 | return -EIO; | ||
3016 | |||
3017 | |||
3018 | DBG(5, "VIDIOCSPICT successfully called") | ||
3019 | return 0; | ||
3020 | } | ||
3021 | |||
3022 | case VIDIOCSWIN: /* set capture area */ | ||
3023 | { | ||
3024 | struct video_window win; | ||
3025 | int err = 0; | ||
3026 | |||
3027 | if (copy_from_user(&win, arg, sizeof(win))) | ||
3028 | return -EFAULT; | ||
3029 | |||
3030 | DBG(6, "VIDIOCSWIN called: clipcount=%d, flags=%u, " | ||
3031 | "x=%u, y=%u, %ux%u", win.clipcount, win.flags, | ||
3032 | win.x, win.y, win.width, win.height) | ||
3033 | |||
3034 | if (win.clipcount != 0 || win.flags != 0) | ||
3035 | return -EINVAL; | ||
3036 | |||
3037 | if ((err = w9968cf_adjust_window_size(cam, &win.width, | ||
3038 | &win.height))) { | ||
3039 | DBG(4, "Resolution not supported (%ux%u). " | ||
3040 | "VIDIOCSWIN failed", win.width, win.height) | ||
3041 | return err; | ||
3042 | } | ||
3043 | |||
3044 | if (win.x != cam->window.x || | ||
3045 | win.y != cam->window.y || | ||
3046 | win.width != cam->window.width || | ||
3047 | win.height != cam->window.height) { | ||
3048 | if(*cam->requested_frame | ||
3049 | || cam->frame_current->queued) { | ||
3050 | err = wait_event_interruptible | ||
3051 | ( cam->wait_queue, | ||
3052 | cam->disconnected || | ||
3053 | (!*cam->requested_frame && | ||
3054 | !cam->frame_current->queued) ); | ||
3055 | if (err) | ||
3056 | return err; | ||
3057 | if (cam->disconnected) | ||
3058 | return -ENODEV; | ||
3059 | } | ||
3060 | |||
3061 | if (w9968cf_stop_transfer(cam)) | ||
3062 | goto ioctl_fail; | ||
3063 | |||
3064 | /* This _must_ be called before set_window() */ | ||
3065 | if (w9968cf_set_picture(cam, cam->picture)) | ||
3066 | goto ioctl_fail; | ||
3067 | |||
3068 | if (w9968cf_set_window(cam, win)) | ||
3069 | goto ioctl_fail; | ||
3070 | |||
3071 | if (w9968cf_start_transfer(cam)) | ||
3072 | goto ioctl_fail; | ||
3073 | } | ||
3074 | |||
3075 | DBG(5, "VIDIOCSWIN successfully called. ") | ||
3076 | return 0; | ||
3077 | } | ||
3078 | |||
3079 | case VIDIOCGWIN: /* get current window properties */ | ||
3080 | { | ||
3081 | if (copy_to_user(arg,&cam->window,sizeof(struct video_window))) | ||
3082 | return -EFAULT; | ||
3083 | |||
3084 | DBG(5, "VIDIOCGWIN successfully called") | ||
3085 | return 0; | ||
3086 | } | ||
3087 | |||
3088 | case VIDIOCGMBUF: /* request for memory (mapped) buffer */ | ||
3089 | { | ||
3090 | struct video_mbuf mbuf; | ||
3091 | u8 i; | ||
3092 | |||
3093 | mbuf.size = cam->nbuffers * cam->frame[0].size; | ||
3094 | mbuf.frames = cam->nbuffers; | ||
3095 | for (i = 0; i < cam->nbuffers; i++) | ||
3096 | mbuf.offsets[i] = (unsigned long)cam->frame[i].buffer - | ||
3097 | (unsigned long)cam->frame[0].buffer; | ||
3098 | |||
3099 | if (copy_to_user(arg, &mbuf, sizeof(mbuf))) | ||
3100 | return -EFAULT; | ||
3101 | |||
3102 | DBG(5, "VIDIOCGMBUF successfully called") | ||
3103 | return 0; | ||
3104 | } | ||
3105 | |||
3106 | case VIDIOCMCAPTURE: /* start the capture to a frame */ | ||
3107 | { | ||
3108 | struct video_mmap mmap; | ||
3109 | struct w9968cf_frame_t* fr; | ||
3110 | u32 w, h; | ||
3111 | int err = 0; | ||
3112 | |||
3113 | if (copy_from_user(&mmap, arg, sizeof(mmap))) | ||
3114 | return -EFAULT; | ||
3115 | |||
3116 | DBG(6, "VIDIOCMCAPTURE called: frame #%u, format=%s, %dx%d", | ||
3117 | mmap.frame, symbolic(v4l1_plist, mmap.format), | ||
3118 | mmap.width, mmap.height) | ||
3119 | |||
3120 | if (mmap.frame >= cam->nbuffers) { | ||
3121 | DBG(4, "Invalid frame number (%u). " | ||
3122 | "VIDIOCMCAPTURE failed", mmap.frame) | ||
3123 | return -EINVAL; | ||
3124 | } | ||
3125 | |||
3126 | if (mmap.format!=cam->picture.palette && | ||
3127 | (cam->force_palette || !w9968cf_vpp)) { | ||
3128 | DBG(4, "Palette %s rejected: only %s is allowed", | ||
3129 | symbolic(v4l1_plist, mmap.format), | ||
3130 | symbolic(v4l1_plist, cam->picture.palette)) | ||
3131 | return -EINVAL; | ||
3132 | } | ||
3133 | |||
3134 | if (!w9968cf_valid_palette(mmap.format)) { | ||
3135 | DBG(4, "Palette %s not supported. " | ||
3136 | "VIDIOCMCAPTURE failed", | ||
3137 | symbolic(v4l1_plist, mmap.format)) | ||
3138 | return -EINVAL; | ||
3139 | } | ||
3140 | |||
3141 | if (!cam->force_palette) { | ||
3142 | if (cam->decompression == 0) { | ||
3143 | if (w9968cf_need_decompression(mmap.format)) { | ||
3144 | DBG(4, "Decompression disabled: palette %s is not " | ||
3145 | "allowed. VIDIOCSPICT failed", | ||
3146 | symbolic(v4l1_plist, mmap.format)) | ||
3147 | return -EINVAL; | ||
3148 | } | ||
3149 | } else if (cam->decompression == 1) { | ||
3150 | if (!w9968cf_need_decompression(mmap.format)) { | ||
3151 | DBG(4, "Decompression forced: palette %s is not " | ||
3152 | "allowed. VIDIOCSPICT failed", | ||
3153 | symbolic(v4l1_plist, mmap.format)) | ||
3154 | return -EINVAL; | ||
3155 | } | ||
3156 | } | ||
3157 | } | ||
3158 | |||
3159 | w = mmap.width; h = mmap.height; | ||
3160 | err = w9968cf_adjust_window_size(cam, &w, &h); | ||
3161 | mmap.width = w; mmap.height = h; | ||
3162 | if (err) { | ||
3163 | DBG(4, "Resolution not supported (%dx%d). " | ||
3164 | "VIDIOCMCAPTURE failed", | ||
3165 | mmap.width, mmap.height) | ||
3166 | return err; | ||
3167 | } | ||
3168 | |||
3169 | fr = &cam->frame[mmap.frame]; | ||
3170 | |||
3171 | if (mmap.width != cam->window.width || | ||
3172 | mmap.height != cam->window.height || | ||
3173 | mmap.format != cam->picture.palette) { | ||
3174 | |||
3175 | struct video_window win; | ||
3176 | struct video_picture pict; | ||
3177 | |||
3178 | if(*cam->requested_frame | ||
3179 | || cam->frame_current->queued) { | ||
3180 | DBG(6, "VIDIOCMCAPTURE. Change settings for " | ||
3181 | "frame #%u: %dx%d, format %s. Wait...", | ||
3182 | mmap.frame, mmap.width, mmap.height, | ||
3183 | symbolic(v4l1_plist, mmap.format)) | ||
3184 | err = wait_event_interruptible | ||
3185 | ( cam->wait_queue, | ||
3186 | cam->disconnected || | ||
3187 | (!*cam->requested_frame && | ||
3188 | !cam->frame_current->queued) ); | ||
3189 | if (err) | ||
3190 | return err; | ||
3191 | if (cam->disconnected) | ||
3192 | return -ENODEV; | ||
3193 | } | ||
3194 | |||
3195 | memcpy(&win, &cam->window, sizeof(win)); | ||
3196 | memcpy(&pict, &cam->picture, sizeof(pict)); | ||
3197 | win.width = mmap.width; | ||
3198 | win.height = mmap.height; | ||
3199 | pict.palette = mmap.format; | ||
3200 | |||
3201 | if (w9968cf_stop_transfer(cam)) | ||
3202 | goto ioctl_fail; | ||
3203 | |||
3204 | /* This before set_window */ | ||
3205 | if (w9968cf_set_picture(cam, pict)) | ||
3206 | goto ioctl_fail; | ||
3207 | |||
3208 | if (w9968cf_set_window(cam, win)) | ||
3209 | goto ioctl_fail; | ||
3210 | |||
3211 | if (w9968cf_start_transfer(cam)) | ||
3212 | goto ioctl_fail; | ||
3213 | |||
3214 | } else if (fr->queued) { | ||
3215 | |||
3216 | DBG(6, "Wait until frame #%u is free", mmap.frame) | ||
3217 | |||
3218 | err = wait_event_interruptible(cam->wait_queue, | ||
3219 | cam->disconnected || | ||
3220 | (!fr->queued)); | ||
3221 | if (err) | ||
3222 | return err; | ||
3223 | if (cam->disconnected) | ||
3224 | return -ENODEV; | ||
3225 | } | ||
3226 | |||
3227 | w9968cf_push_frame(cam, mmap.frame); | ||
3228 | DBG(5, "VIDIOCMCAPTURE(%u): successfully called", mmap.frame) | ||
3229 | return 0; | ||
3230 | } | ||
3231 | |||
3232 | case VIDIOCSYNC: /* wait until the capture of a frame is finished */ | ||
3233 | { | ||
3234 | unsigned int f_num; | ||
3235 | struct w9968cf_frame_t* fr; | ||
3236 | int err = 0; | ||
3237 | |||
3238 | if (copy_from_user(&f_num, arg, sizeof(f_num))) | ||
3239 | return -EFAULT; | ||
3240 | |||
3241 | if (f_num >= cam->nbuffers) { | ||
3242 | DBG(4, "Invalid frame number (%u). " | ||
3243 | "VIDIOCMCAPTURE failed", f_num) | ||
3244 | return -EINVAL; | ||
3245 | } | ||
3246 | |||
3247 | DBG(6, "VIDIOCSYNC called for frame #%u", f_num) | ||
3248 | |||
3249 | fr = &cam->frame[f_num]; | ||
3250 | |||
3251 | switch (fr->status) { | ||
3252 | case F_UNUSED: | ||
3253 | if (!fr->queued) { | ||
3254 | DBG(4, "VIDIOSYNC: Frame #%u not requested!", | ||
3255 | f_num) | ||
3256 | return -EFAULT; | ||
3257 | } | ||
3258 | case F_ERROR: | ||
3259 | case F_GRABBING: | ||
3260 | err = wait_event_interruptible(cam->wait_queue, | ||
3261 | (fr->status == F_READY) | ||
3262 | || cam->disconnected); | ||
3263 | if (err) | ||
3264 | return err; | ||
3265 | if (cam->disconnected) | ||
3266 | return -ENODEV; | ||
3267 | break; | ||
3268 | case F_READY: | ||
3269 | break; | ||
3270 | } | ||
3271 | |||
3272 | if (w9968cf_vpp) | ||
3273 | w9968cf_postprocess_frame(cam, fr); | ||
3274 | |||
3275 | fr->status = F_UNUSED; | ||
3276 | |||
3277 | DBG(5, "VIDIOCSYNC(%u) successfully called", f_num) | ||
3278 | return 0; | ||
3279 | } | ||
3280 | |||
3281 | case VIDIOCGUNIT:/* report the unit numbers of the associated devices*/ | ||
3282 | { | ||
3283 | struct video_unit unit = { | ||
3284 | .video = cam->v4ldev->minor, | ||
3285 | .vbi = VIDEO_NO_UNIT, | ||
3286 | .radio = VIDEO_NO_UNIT, | ||
3287 | .audio = VIDEO_NO_UNIT, | ||
3288 | .teletext = VIDEO_NO_UNIT, | ||
3289 | }; | ||
3290 | |||
3291 | if (copy_to_user(arg, &unit, sizeof(unit))) | ||
3292 | return -EFAULT; | ||
3293 | |||
3294 | DBG(5, "VIDIOCGUNIT successfully called") | ||
3295 | return 0; | ||
3296 | } | ||
3297 | |||
3298 | case VIDIOCKEY: | ||
3299 | return 0; | ||
3300 | |||
3301 | case VIDIOCGFBUF: | ||
3302 | { | ||
3303 | if (clear_user(arg, sizeof(struct video_buffer))) | ||
3304 | return -EFAULT; | ||
3305 | |||
3306 | DBG(5, "VIDIOCGFBUF successfully called") | ||
3307 | return 0; | ||
3308 | } | ||
3309 | |||
3310 | case VIDIOCGTUNER: | ||
3311 | { | ||
3312 | struct video_tuner tuner; | ||
3313 | if (copy_from_user(&tuner, arg, sizeof(tuner))) | ||
3314 | return -EFAULT; | ||
3315 | |||
3316 | if (tuner.tuner != 0) | ||
3317 | return -EINVAL; | ||
3318 | |||
3319 | strcpy(tuner.name, "no_tuner"); | ||
3320 | tuner.rangelow = 0; | ||
3321 | tuner.rangehigh = 0; | ||
3322 | tuner.flags = VIDEO_TUNER_NORM; | ||
3323 | tuner.mode = VIDEO_MODE_AUTO; | ||
3324 | tuner.signal = 0xffff; | ||
3325 | |||
3326 | if (copy_to_user(arg, &tuner, sizeof(tuner))) | ||
3327 | return -EFAULT; | ||
3328 | |||
3329 | DBG(5, "VIDIOCGTUNER successfully called") | ||
3330 | return 0; | ||
3331 | } | ||
3332 | |||
3333 | case VIDIOCSTUNER: | ||
3334 | { | ||
3335 | struct video_tuner tuner; | ||
3336 | if (copy_from_user(&tuner, arg, sizeof(tuner))) | ||
3337 | return -EFAULT; | ||
3338 | |||
3339 | if (tuner.tuner != 0) | ||
3340 | return -EINVAL; | ||
3341 | |||
3342 | if (tuner.mode != VIDEO_MODE_AUTO) | ||
3343 | return -EINVAL; | ||
3344 | |||
3345 | DBG(5, "VIDIOCSTUNER successfully called") | ||
3346 | return 0; | ||
3347 | } | ||
3348 | |||
3349 | case VIDIOCSFBUF: | ||
3350 | case VIDIOCCAPTURE: | ||
3351 | case VIDIOCGFREQ: | ||
3352 | case VIDIOCSFREQ: | ||
3353 | case VIDIOCGAUDIO: | ||
3354 | case VIDIOCSAUDIO: | ||
3355 | case VIDIOCSPLAYMODE: | ||
3356 | case VIDIOCSWRITEMODE: | ||
3357 | case VIDIOCGPLAYINFO: | ||
3358 | case VIDIOCSMICROCODE: | ||
3359 | case VIDIOCGVBIFMT: | ||
3360 | case VIDIOCSVBIFMT: | ||
3361 | DBG(4, "Unsupported V4L1 IOCtl: VIDIOC%s " | ||
3362 | "(type 0x%01X, " | ||
3363 | "n. 0x%01X, " | ||
3364 | "dir. 0x%01X, " | ||
3365 | "size 0x%02X)", | ||
3366 | V4L1_IOCTL(cmd), | ||
3367 | _IOC_TYPE(cmd),_IOC_NR(cmd),_IOC_DIR(cmd),_IOC_SIZE(cmd)) | ||
3368 | |||
3369 | return -EINVAL; | ||
3370 | |||
3371 | default: | ||
3372 | DBG(4, "Invalid V4L1 IOCtl: VIDIOC%s " | ||
3373 | "type 0x%01X, " | ||
3374 | "n. 0x%01X, " | ||
3375 | "dir. 0x%01X, " | ||
3376 | "size 0x%02X", | ||
3377 | V4L1_IOCTL(cmd), | ||
3378 | _IOC_TYPE(cmd),_IOC_NR(cmd),_IOC_DIR(cmd),_IOC_SIZE(cmd)) | ||
3379 | |||
3380 | return -ENOIOCTLCMD; | ||
3381 | |||
3382 | } /* end of switch */ | ||
3383 | |||
3384 | ioctl_fail: | ||
3385 | cam->misconfigured = 1; | ||
3386 | DBG(1, "VIDIOC%s failed because of hardware problems. " | ||
3387 | "To use the camera, close and open it again.", V4L1_IOCTL(cmd)) | ||
3388 | return -EFAULT; | ||
3389 | } | ||
3390 | |||
3391 | |||
3392 | static const struct v4l2_file_operations w9968cf_fops = { | ||
3393 | .owner = THIS_MODULE, | ||
3394 | .open = w9968cf_open, | ||
3395 | .release = w9968cf_release, | ||
3396 | .read = w9968cf_read, | ||
3397 | .ioctl = w9968cf_ioctl, | ||
3398 | .mmap = w9968cf_mmap, | ||
3399 | }; | ||
3400 | |||
3401 | |||
3402 | |||
3403 | /**************************************************************************** | ||
3404 | * USB probe and V4L registration, disconnect and id_table[] definition * | ||
3405 | ****************************************************************************/ | ||
3406 | |||
3407 | static int | ||
3408 | w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | ||
3409 | { | ||
3410 | struct usb_device *udev = interface_to_usbdev(intf); | ||
3411 | struct w9968cf_device* cam; | ||
3412 | int err = 0; | ||
3413 | enum w9968cf_model_id mod_id; | ||
3414 | struct list_head* ptr; | ||
3415 | u8 sc = 0; /* number of simultaneous cameras */ | ||
3416 | static unsigned short dev_nr; /* 0 - we are handling device number n */ | ||
3417 | static unsigned short addrs[] = { | ||
3418 | OV7xx0_SID, | ||
3419 | OV6xx0_SID, | ||
3420 | I2C_CLIENT_END | ||
3421 | }; | ||
3422 | |||
3423 | if (le16_to_cpu(udev->descriptor.idVendor) == winbond_id_table[0].idVendor && | ||
3424 | le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[0].idProduct) | ||
3425 | mod_id = W9968CF_MOD_CLVBWGP; /* see camlist[] table */ | ||
3426 | else if (le16_to_cpu(udev->descriptor.idVendor) == winbond_id_table[1].idVendor && | ||
3427 | le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[1].idProduct) | ||
3428 | mod_id = W9968CF_MOD_GENERIC; /* see camlist[] table */ | ||
3429 | else | ||
3430 | return -ENODEV; | ||
3431 | |||
3432 | cam = (struct w9968cf_device*) | ||
3433 | kzalloc(sizeof(struct w9968cf_device), GFP_KERNEL); | ||
3434 | if (!cam) | ||
3435 | return -ENOMEM; | ||
3436 | |||
3437 | err = v4l2_device_register(&intf->dev, &cam->v4l2_dev); | ||
3438 | if (err) | ||
3439 | goto fail0; | ||
3440 | |||
3441 | mutex_init(&cam->dev_mutex); | ||
3442 | mutex_lock(&cam->dev_mutex); | ||
3443 | |||
3444 | cam->usbdev = udev; | ||
3445 | |||
3446 | DBG(2, "%s detected", symbolic(camlist, mod_id)) | ||
3447 | |||
3448 | if (simcams > W9968CF_MAX_DEVICES) | ||
3449 | simcams = W9968CF_SIMCAMS; | ||
3450 | |||
3451 | /* How many cameras are connected ? */ | ||
3452 | mutex_lock(&w9968cf_devlist_mutex); | ||
3453 | list_for_each(ptr, &w9968cf_dev_list) | ||
3454 | sc++; | ||
3455 | mutex_unlock(&w9968cf_devlist_mutex); | ||
3456 | |||
3457 | if (sc >= simcams) { | ||
3458 | DBG(2, "Device rejected: too many connected cameras " | ||
3459 | "(max. %u)", simcams) | ||
3460 | err = -EPERM; | ||
3461 | goto fail; | ||
3462 | } | ||
3463 | |||
3464 | |||
3465 | /* Allocate 2 bytes of memory for camera control USB transfers */ | ||
3466 | if (!(cam->control_buffer = kzalloc(2, GFP_KERNEL))) { | ||
3467 | DBG(1,"Couldn't allocate memory for camera control transfers") | ||
3468 | err = -ENOMEM; | ||
3469 | goto fail; | ||
3470 | } | ||
3471 | |||
3472 | /* Allocate 8 bytes of memory for USB data transfers to the FSB */ | ||
3473 | if (!(cam->data_buffer = kzalloc(8, GFP_KERNEL))) { | ||
3474 | DBG(1, "Couldn't allocate memory for data " | ||
3475 | "transfers to the FSB") | ||
3476 | err = -ENOMEM; | ||
3477 | goto fail; | ||
3478 | } | ||
3479 | |||
3480 | /* Register the V4L device */ | ||
3481 | cam->v4ldev = video_device_alloc(); | ||
3482 | if (!cam->v4ldev) { | ||
3483 | DBG(1, "Could not allocate memory for a V4L structure") | ||
3484 | err = -ENOMEM; | ||
3485 | goto fail; | ||
3486 | } | ||
3487 | |||
3488 | strcpy(cam->v4ldev->name, symbolic(camlist, mod_id)); | ||
3489 | cam->v4ldev->fops = &w9968cf_fops; | ||
3490 | cam->v4ldev->release = video_device_release; | ||
3491 | video_set_drvdata(cam->v4ldev, cam); | ||
3492 | cam->v4ldev->v4l2_dev = &cam->v4l2_dev; | ||
3493 | |||
3494 | err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, | ||
3495 | video_nr[dev_nr]); | ||
3496 | if (err) { | ||
3497 | DBG(1, "V4L device registration failed") | ||
3498 | if (err == -ENFILE && video_nr[dev_nr] == -1) | ||
3499 | DBG(2, "Couldn't find a free /dev/videoX node") | ||
3500 | video_nr[dev_nr] = -1; | ||
3501 | dev_nr = (dev_nr < W9968CF_MAX_DEVICES-1) ? dev_nr+1 : 0; | ||
3502 | goto fail; | ||
3503 | } | ||
3504 | |||
3505 | DBG(2, "V4L device registered as %s", | ||
3506 | video_device_node_name(cam->v4ldev)) | ||
3507 | |||
3508 | /* Set some basic constants */ | ||
3509 | w9968cf_configure_camera(cam, udev, mod_id, dev_nr); | ||
3510 | |||
3511 | /* Add a new entry into the list of V4L registered devices */ | ||
3512 | mutex_lock(&w9968cf_devlist_mutex); | ||
3513 | list_add(&cam->v4llist, &w9968cf_dev_list); | ||
3514 | mutex_unlock(&w9968cf_devlist_mutex); | ||
3515 | dev_nr = (dev_nr < W9968CF_MAX_DEVICES-1) ? dev_nr+1 : 0; | ||
3516 | |||
3517 | w9968cf_turn_on_led(cam); | ||
3518 | |||
3519 | w9968cf_i2c_init(cam); | ||
3520 | cam->sensor_sd = v4l2_i2c_new_subdev(&cam->v4l2_dev, | ||
3521 | &cam->i2c_adapter, | ||
3522 | "ovcamchip", "ovcamchip", 0, addrs); | ||
3523 | |||
3524 | usb_set_intfdata(intf, cam); | ||
3525 | mutex_unlock(&cam->dev_mutex); | ||
3526 | |||
3527 | err = w9968cf_sensor_init(cam); | ||
3528 | return 0; | ||
3529 | |||
3530 | fail: /* Free unused memory */ | ||
3531 | kfree(cam->control_buffer); | ||
3532 | kfree(cam->data_buffer); | ||
3533 | if (cam->v4ldev) | ||
3534 | video_device_release(cam->v4ldev); | ||
3535 | mutex_unlock(&cam->dev_mutex); | ||
3536 | v4l2_device_unregister(&cam->v4l2_dev); | ||
3537 | fail0: | ||
3538 | kfree(cam); | ||
3539 | return err; | ||
3540 | } | ||
3541 | |||
3542 | |||
3543 | static void w9968cf_usb_disconnect(struct usb_interface* intf) | ||
3544 | { | ||
3545 | struct w9968cf_device* cam = | ||
3546 | (struct w9968cf_device*)usb_get_intfdata(intf); | ||
3547 | |||
3548 | if (cam) { | ||
3549 | down_write(&w9968cf_disconnect); | ||
3550 | /* Prevent concurrent accesses to data */ | ||
3551 | mutex_lock(&cam->dev_mutex); | ||
3552 | |||
3553 | cam->disconnected = 1; | ||
3554 | |||
3555 | DBG(2, "Disconnecting %s...", symbolic(camlist, cam->id)); | ||
3556 | |||
3557 | v4l2_device_disconnect(&cam->v4l2_dev); | ||
3558 | |||
3559 | wake_up_interruptible_all(&cam->open); | ||
3560 | |||
3561 | if (cam->users) { | ||
3562 | DBG(2, "The device is open (%s)! " | ||
3563 | "Process name: %s. Deregistration and memory " | ||
3564 | "deallocation are deferred on close.", | ||
3565 | video_device_node_name(cam->v4ldev), cam->command) | ||
3566 | cam->misconfigured = 1; | ||
3567 | w9968cf_stop_transfer(cam); | ||
3568 | wake_up_interruptible(&cam->wait_queue); | ||
3569 | } else | ||
3570 | w9968cf_release_resources(cam); | ||
3571 | |||
3572 | mutex_unlock(&cam->dev_mutex); | ||
3573 | up_write(&w9968cf_disconnect); | ||
3574 | |||
3575 | if (!cam->users) { | ||
3576 | kfree(cam); | ||
3577 | } | ||
3578 | } | ||
3579 | } | ||
3580 | |||
3581 | |||
3582 | static struct usb_driver w9968cf_usb_driver = { | ||
3583 | .name = "w9968cf", | ||
3584 | .id_table = winbond_id_table, | ||
3585 | .probe = w9968cf_usb_probe, | ||
3586 | .disconnect = w9968cf_usb_disconnect, | ||
3587 | }; | ||
3588 | |||
3589 | |||
3590 | |||
3591 | /**************************************************************************** | ||
3592 | * Module init, exit and intermodule communication * | ||
3593 | ****************************************************************************/ | ||
3594 | |||
3595 | static int __init w9968cf_module_init(void) | ||
3596 | { | ||
3597 | int err; | ||
3598 | |||
3599 | KDBG(2, W9968CF_MODULE_NAME" "W9968CF_MODULE_VERSION) | ||
3600 | KDBG(3, W9968CF_MODULE_AUTHOR) | ||
3601 | |||
3602 | if ((err = usb_register(&w9968cf_usb_driver))) | ||
3603 | return err; | ||
3604 | |||
3605 | return 0; | ||
3606 | } | ||
3607 | |||
3608 | |||
3609 | static void __exit w9968cf_module_exit(void) | ||
3610 | { | ||
3611 | /* w9968cf_usb_disconnect() will be called */ | ||
3612 | usb_deregister(&w9968cf_usb_driver); | ||
3613 | |||
3614 | KDBG(2, W9968CF_MODULE_NAME" deregistered") | ||
3615 | } | ||
3616 | |||
3617 | |||
3618 | module_init(w9968cf_module_init); | ||
3619 | module_exit(w9968cf_module_exit); | ||
3620 | |||
diff --git a/drivers/media/video/w9968cf.h b/drivers/media/video/w9968cf.h deleted file mode 100644 index 73ad864b4842..000000000000 --- a/drivers/media/video/w9968cf.h +++ /dev/null | |||
@@ -1,333 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * Video4Linux driver for W996[87]CF JPEG USB Dual Mode Camera Chip. * | ||
3 | * * | ||
4 | * Copyright (C) 2002-2004 by Luca Risolia <luca.risolia@studio.unibo.it> * | ||
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 _W9968CF_H_ | ||
22 | #define _W9968CF_H_ | ||
23 | |||
24 | #include <linux/videodev2.h> | ||
25 | #include <linux/usb.h> | ||
26 | #include <linux/i2c.h> | ||
27 | #include <linux/device.h> | ||
28 | #include <linux/spinlock.h> | ||
29 | #include <linux/list.h> | ||
30 | #include <linux/wait.h> | ||
31 | #include <linux/param.h> | ||
32 | #include <linux/types.h> | ||
33 | #include <linux/rwsem.h> | ||
34 | #include <linux/mutex.h> | ||
35 | |||
36 | #include <media/v4l2-device.h> | ||
37 | #include <media/ovcamchip.h> | ||
38 | |||
39 | #include "w9968cf_vpp.h" | ||
40 | |||
41 | |||
42 | /**************************************************************************** | ||
43 | * Default values * | ||
44 | ****************************************************************************/ | ||
45 | |||
46 | #define W9968CF_VPPMOD_LOAD 1 /* automatic 'w9968cf-vpp' module loading */ | ||
47 | |||
48 | /* Comment/uncomment the following line to enable/disable debugging messages */ | ||
49 | #define W9968CF_DEBUG | ||
50 | |||
51 | /* These have effect only if W9968CF_DEBUG is defined */ | ||
52 | #define W9968CF_DEBUG_LEVEL 2 /* from 0 to 6. 0 for no debug informations */ | ||
53 | #define W9968CF_SPECIFIC_DEBUG 0 /* 0 or 1 */ | ||
54 | |||
55 | #define W9968CF_MAX_DEVICES 32 | ||
56 | #define W9968CF_SIMCAMS W9968CF_MAX_DEVICES /* simultaneous cameras */ | ||
57 | |||
58 | #define W9968CF_MAX_BUFFERS 32 | ||
59 | #define W9968CF_BUFFERS 2 /* n. of frame buffers from 2 to MAX_BUFFERS */ | ||
60 | |||
61 | /* Maximum data payload sizes in bytes for alternate settings */ | ||
62 | static const u16 wMaxPacketSize[] = {1023, 959, 895, 831, 767, 703, 639, 575, | ||
63 | 511, 447, 383, 319, 255, 191, 127, 63}; | ||
64 | #define W9968CF_PACKET_SIZE 1023 /* according to wMaxPacketSizes[] */ | ||
65 | #define W9968CF_MIN_PACKET_SIZE 63 /* minimum value */ | ||
66 | #define W9968CF_ISO_PACKETS 5 /* n.of packets for isochronous transfers */ | ||
67 | #define W9968CF_USB_CTRL_TIMEOUT 1000 /* timeout (ms) for usb control commands */ | ||
68 | #define W9968CF_URBS 2 /* n. of scheduled URBs for ISO transfer */ | ||
69 | |||
70 | #define W9968CF_I2C_BUS_DELAY 4 /* delay in us for I2C bit r/w operations */ | ||
71 | #define W9968CF_I2C_RW_RETRIES 15 /* number of max I2C r/w retries */ | ||
72 | |||
73 | /* Available video formats */ | ||
74 | struct w9968cf_format { | ||
75 | const u16 palette; | ||
76 | const u16 depth; | ||
77 | const u8 compression; | ||
78 | }; | ||
79 | |||
80 | static const struct w9968cf_format w9968cf_formatlist[] = { | ||
81 | { VIDEO_PALETTE_UYVY, 16, 0 }, /* original video */ | ||
82 | { VIDEO_PALETTE_YUV422P, 16, 1 }, /* with JPEG compression */ | ||
83 | { VIDEO_PALETTE_YUV420P, 12, 1 }, /* with JPEG compression */ | ||
84 | { VIDEO_PALETTE_YUV420, 12, 1 }, /* same as YUV420P */ | ||
85 | { VIDEO_PALETTE_YUYV, 16, 0 }, /* software conversion */ | ||
86 | { VIDEO_PALETTE_YUV422, 16, 0 }, /* software conversion */ | ||
87 | { VIDEO_PALETTE_GREY, 8, 0 }, /* software conversion */ | ||
88 | { VIDEO_PALETTE_RGB555, 16, 0 }, /* software conversion */ | ||
89 | { VIDEO_PALETTE_RGB565, 16, 0 }, /* software conversion */ | ||
90 | { VIDEO_PALETTE_RGB24, 24, 0 }, /* software conversion */ | ||
91 | { VIDEO_PALETTE_RGB32, 32, 0 }, /* software conversion */ | ||
92 | { 0, 0, 0 } /* 0 is a terminating entry */ | ||
93 | }; | ||
94 | |||
95 | #define W9968CF_DECOMPRESSION 2 /* decomp:0=disable,1=force,2=any formats */ | ||
96 | #define W9968CF_PALETTE_DECOMP_OFF VIDEO_PALETTE_UYVY /* when decomp=0 */ | ||
97 | #define W9968CF_PALETTE_DECOMP_FORCE VIDEO_PALETTE_YUV420P /* when decomp=1 */ | ||
98 | #define W9968CF_PALETTE_DECOMP_ON VIDEO_PALETTE_UYVY /* when decomp=2 */ | ||
99 | |||
100 | #define W9968CF_FORCE_RGB 0 /* read RGB instead of BGR, yes=1/no=0 */ | ||
101 | |||
102 | #define W9968CF_MAX_WIDTH 800 /* Has effect if up-scaling is on */ | ||
103 | #define W9968CF_MAX_HEIGHT 600 /* Has effect if up-scaling is on */ | ||
104 | #define W9968CF_WIDTH 320 /* from 128 to 352, multiple of 16 */ | ||
105 | #define W9968CF_HEIGHT 240 /* from 96 to 288, multiple of 16 */ | ||
106 | |||
107 | #define W9968CF_CLAMPING 0 /* 0 disable, 1 enable video data clamping */ | ||
108 | #define W9968CF_FILTER_TYPE 0 /* 0 disable 1 (1-2-1), 2 (2-3-6-3-2) */ | ||
109 | #define W9968CF_DOUBLE_BUFFER 1 /* 0 disable, 1 enable double buffer */ | ||
110 | #define W9968CF_LARGEVIEW 1 /* 0 disable, 1 enable */ | ||
111 | #define W9968CF_UPSCALING 0 /* 0 disable, 1 enable */ | ||
112 | |||
113 | #define W9968CF_MONOCHROME 0 /* 0 not monochrome, 1 monochrome sensor */ | ||
114 | #define W9968CF_BRIGHTNESS 31000 /* from 0 to 65535 */ | ||
115 | #define W9968CF_HUE 32768 /* from 0 to 65535 */ | ||
116 | #define W9968CF_COLOUR 32768 /* from 0 to 65535 */ | ||
117 | #define W9968CF_CONTRAST 50000 /* from 0 to 65535 */ | ||
118 | #define W9968CF_WHITENESS 32768 /* from 0 to 65535 */ | ||
119 | |||
120 | #define W9968CF_AUTOBRIGHT 0 /* 0 disable, 1 enable automatic brightness */ | ||
121 | #define W9968CF_AUTOEXP 1 /* 0 disable, 1 enable automatic exposure */ | ||
122 | #define W9968CF_LIGHTFREQ 50 /* light frequency. 50Hz (Europe) or 60Hz */ | ||
123 | #define W9968CF_BANDINGFILTER 0 /* 0 disable, 1 enable banding filter */ | ||
124 | #define W9968CF_BACKLIGHT 0 /* 0 or 1, 1=object is lit from behind */ | ||
125 | #define W9968CF_MIRROR 0 /* 0 or 1 [don't] reverse image horizontally*/ | ||
126 | |||
127 | #define W9968CF_CLOCKDIV -1 /* -1 = automatic clock divisor */ | ||
128 | #define W9968CF_DEF_CLOCKDIVISOR 0 /* default sensor clock divisor value */ | ||
129 | |||
130 | |||
131 | /**************************************************************************** | ||
132 | * Globals * | ||
133 | ****************************************************************************/ | ||
134 | |||
135 | #define W9968CF_MODULE_NAME "V4L driver for W996[87]CF JPEG USB " \ | ||
136 | "Dual Mode Camera Chip" | ||
137 | #define W9968CF_MODULE_VERSION "1:1.34-basic" | ||
138 | #define W9968CF_MODULE_AUTHOR "(C) 2002-2004 Luca Risolia" | ||
139 | #define W9968CF_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" | ||
140 | #define W9968CF_MODULE_LICENSE "GPL" | ||
141 | |||
142 | static const struct usb_device_id winbond_id_table[] = { | ||
143 | { | ||
144 | /* Creative Labs Video Blaster WebCam Go Plus */ | ||
145 | USB_DEVICE(0x041e, 0x4003), | ||
146 | .driver_info = (unsigned long)"w9968cf", | ||
147 | }, | ||
148 | { | ||
149 | /* Generic W996[87]CF JPEG USB Dual Mode Camera */ | ||
150 | USB_DEVICE(0x1046, 0x9967), | ||
151 | .driver_info = (unsigned long)"w9968cf", | ||
152 | }, | ||
153 | { } /* terminating entry */ | ||
154 | }; | ||
155 | |||
156 | /* W996[87]CF camera models, internal ids: */ | ||
157 | enum w9968cf_model_id { | ||
158 | W9968CF_MOD_GENERIC = 1, /* Generic W996[87]CF based device */ | ||
159 | W9968CF_MOD_CLVBWGP = 11,/*Creative Labs Video Blaster WebCam Go Plus*/ | ||
160 | W9968CF_MOD_ADPVDMA = 21, /* Aroma Digi Pen VGA Dual Mode ADG-5000 */ | ||
161 | W9986CF_MOD_AAU = 31, /* AVerMedia AVerTV USB */ | ||
162 | W9968CF_MOD_CLVBWG = 34, /* Creative Labs Video Blaster WebCam Go */ | ||
163 | W9968CF_MOD_LL = 37, /* Lebon LDC-035A */ | ||
164 | W9968CF_MOD_EEEMC = 40, /* Ezonics EZ-802 EZMega Cam */ | ||
165 | W9968CF_MOD_OOE = 42, /* OmniVision OV8610-EDE */ | ||
166 | W9968CF_MOD_ODPVDMPC = 43,/* OPCOM Digi Pen VGA Dual Mode Pen Camera */ | ||
167 | W9968CF_MOD_PDPII = 46, /* Pretec Digi Pen-II */ | ||
168 | W9968CF_MOD_PDP480 = 49, /* Pretec DigiPen-480 */ | ||
169 | }; | ||
170 | |||
171 | enum w9968cf_frame_status { | ||
172 | F_READY, /* finished grabbing & ready to be read/synced */ | ||
173 | F_GRABBING, /* in the process of being grabbed into */ | ||
174 | F_ERROR, /* something bad happened while processing */ | ||
175 | F_UNUSED /* unused (no VIDIOCMCAPTURE) */ | ||
176 | }; | ||
177 | |||
178 | struct w9968cf_frame_t { | ||
179 | void* buffer; | ||
180 | unsigned long size; | ||
181 | u32 length; | ||
182 | int number; | ||
183 | enum w9968cf_frame_status status; | ||
184 | struct w9968cf_frame_t* next; | ||
185 | u8 queued; | ||
186 | }; | ||
187 | |||
188 | enum w9968cf_vpp_flag { | ||
189 | VPP_NONE = 0x00, | ||
190 | VPP_UPSCALE = 0x01, | ||
191 | VPP_SWAP_YUV_BYTES = 0x02, | ||
192 | VPP_DECOMPRESSION = 0x04, | ||
193 | VPP_UYVY_TO_RGBX = 0x08, | ||
194 | }; | ||
195 | |||
196 | /* Main device driver structure */ | ||
197 | struct w9968cf_device { | ||
198 | enum w9968cf_model_id id; /* private device identifier */ | ||
199 | |||
200 | struct v4l2_device v4l2_dev; | ||
201 | struct video_device* v4ldev; /* -> V4L structure */ | ||
202 | struct list_head v4llist; /* entry of the list of V4L cameras */ | ||
203 | |||
204 | struct usb_device* usbdev; /* -> main USB structure */ | ||
205 | struct urb* urb[W9968CF_URBS]; /* -> USB request block structs */ | ||
206 | void* transfer_buffer[W9968CF_URBS]; /* -> ISO transfer buffers */ | ||
207 | u16* control_buffer; /* -> buffer for control req.*/ | ||
208 | u16* data_buffer; /* -> data to send to the FSB */ | ||
209 | |||
210 | struct w9968cf_frame_t frame[W9968CF_MAX_BUFFERS]; | ||
211 | struct w9968cf_frame_t frame_tmp; /* temporary frame */ | ||
212 | struct w9968cf_frame_t frame_vpp; /* helper frame.*/ | ||
213 | struct w9968cf_frame_t* frame_current; /* -> frame being grabbed */ | ||
214 | struct w9968cf_frame_t* requested_frame[W9968CF_MAX_BUFFERS]; | ||
215 | |||
216 | u8 max_buffers, /* number of requested buffers */ | ||
217 | force_palette, /* yes=1/no=0 */ | ||
218 | force_rgb, /* read RGB instead of BGR, yes=1, no=0 */ | ||
219 | double_buffer, /* hardware double buffering yes=1/no=0 */ | ||
220 | clamping, /* video data clamping yes=1/no=0 */ | ||
221 | filter_type, /* 0=disabled, 1=3 tap, 2=5 tap filter */ | ||
222 | capture, /* 0=disabled, 1=enabled */ | ||
223 | largeview, /* 0=disabled, 1=enabled */ | ||
224 | decompression, /* 0=disabled, 1=forced, 2=allowed */ | ||
225 | upscaling; /* software image scaling, 0=enabled, 1=disabled */ | ||
226 | |||
227 | struct video_picture picture; /* current picture settings */ | ||
228 | struct video_window window; /* current window settings */ | ||
229 | |||
230 | u16 hw_depth, /* depth (used by the chip) */ | ||
231 | hw_palette, /* palette (used by the chip) */ | ||
232 | hw_width, /* width (used by the chip) */ | ||
233 | hw_height, /* height (used by the chip) */ | ||
234 | hs_polarity, /* 0=negative sync pulse, 1=positive sync pulse */ | ||
235 | vs_polarity, /* 0=negative sync pulse, 1=positive sync pulse */ | ||
236 | start_cropx, /* pixels from HS inactive edge to 1st cropped pixel*/ | ||
237 | start_cropy; /* pixels from VS inactive edge to 1st cropped pixel*/ | ||
238 | |||
239 | enum w9968cf_vpp_flag vpp_flag; /* post-processing routines in use */ | ||
240 | |||
241 | u8 nbuffers, /* number of allocated frame buffers */ | ||
242 | altsetting, /* camera alternate setting */ | ||
243 | disconnected, /* flag: yes=1, no=0 */ | ||
244 | misconfigured, /* flag: yes=1, no=0 */ | ||
245 | users, /* flag: number of users holding the device */ | ||
246 | streaming; /* flag: yes=1, no=0 */ | ||
247 | |||
248 | u8 sensor_initialized; /* flag: yes=1, no=0 */ | ||
249 | |||
250 | /* Determined by the image sensor type: */ | ||
251 | int sensor, /* type of image sensor chip (CC_*) */ | ||
252 | monochrome; /* image sensor is (probably) monochrome */ | ||
253 | u16 maxwidth, /* maximum width supported by the image sensor */ | ||
254 | maxheight, /* maximum height supported by the image sensor */ | ||
255 | minwidth, /* minimum width supported by the image sensor */ | ||
256 | minheight; /* minimum height supported by the image sensor */ | ||
257 | u8 auto_brt, /* auto brightness enabled flag */ | ||
258 | auto_exp, /* auto exposure enabled flag */ | ||
259 | backlight, /* backlight exposure algorithm flag */ | ||
260 | mirror, /* image is reversed horizontally */ | ||
261 | lightfreq, /* power (lighting) frequency */ | ||
262 | bandfilt; /* banding filter enabled flag */ | ||
263 | s8 clockdiv; /* clock divisor */ | ||
264 | |||
265 | /* I2C interface to kernel */ | ||
266 | struct i2c_adapter i2c_adapter; | ||
267 | struct v4l2_subdev *sensor_sd; | ||
268 | |||
269 | /* Locks */ | ||
270 | struct mutex dev_mutex, /* for probe, disconnect,open and close */ | ||
271 | fileop_mutex; /* for read and ioctl */ | ||
272 | spinlock_t urb_lock, /* for submit_urb() and unlink_urb() */ | ||
273 | flist_lock; /* for requested frame list accesses */ | ||
274 | wait_queue_head_t open, wait_queue; | ||
275 | |||
276 | char command[16]; /* name of the program holding the device */ | ||
277 | }; | ||
278 | |||
279 | static inline struct w9968cf_device *to_cam(struct v4l2_device *v4l2_dev) | ||
280 | { | ||
281 | return container_of(v4l2_dev, struct w9968cf_device, v4l2_dev); | ||
282 | } | ||
283 | |||
284 | |||
285 | /**************************************************************************** | ||
286 | * Macros for debugging * | ||
287 | ****************************************************************************/ | ||
288 | |||
289 | #undef DBG | ||
290 | #undef KDBG | ||
291 | #ifdef W9968CF_DEBUG | ||
292 | /* For device specific debugging messages */ | ||
293 | # define DBG(level, fmt, args...) \ | ||
294 | { \ | ||
295 | if ( ((specific_debug) && (debug == (level))) || \ | ||
296 | ((!specific_debug) && (debug >= (level))) ) { \ | ||
297 | if ((level) == 1) \ | ||
298 | v4l2_err(&cam->v4l2_dev, fmt "\n", ## args); \ | ||
299 | else if ((level) == 2 || (level) == 3) \ | ||
300 | v4l2_info(&cam->v4l2_dev, fmt "\n", ## args); \ | ||
301 | else if ((level) == 4) \ | ||
302 | v4l2_warn(&cam->v4l2_dev, fmt "\n", ## args); \ | ||
303 | else if ((level) >= 5) \ | ||
304 | v4l2_info(&cam->v4l2_dev, "[%s:%d] " fmt "\n", \ | ||
305 | __func__, __LINE__ , ## args); \ | ||
306 | } \ | ||
307 | } | ||
308 | /* For generic kernel (not device specific) messages */ | ||
309 | # define KDBG(level, fmt, args...) \ | ||
310 | { \ | ||
311 | if ( ((specific_debug) && (debug == (level))) || \ | ||
312 | ((!specific_debug) && (debug >= (level))) ) { \ | ||
313 | if ((level) >= 1 && (level) <= 4) \ | ||
314 | pr_info("w9968cf: " fmt "\n", ## args); \ | ||
315 | else if ((level) >= 5) \ | ||
316 | pr_debug("w9968cf: [%s:%d] " fmt "\n", __func__, \ | ||
317 | __LINE__ , ## args); \ | ||
318 | } \ | ||
319 | } | ||
320 | #else | ||
321 | /* Not debugging: nothing */ | ||
322 | # define DBG(level, fmt, args...) do {;} while(0); | ||
323 | # define KDBG(level, fmt, args...) do {;} while(0); | ||
324 | #endif | ||
325 | |||
326 | #undef PDBG | ||
327 | #define PDBG(fmt, args...) \ | ||
328 | v4l2_info(&cam->v4l2_dev, "[%s:%d] " fmt "\n", __func__, __LINE__ , ## args); | ||
329 | |||
330 | #undef PDBGG | ||
331 | #define PDBGG(fmt, args...) do {;} while(0); /* nothing: it's a placeholder */ | ||
332 | |||
333 | #endif /* _W9968CF_H_ */ | ||
diff --git a/drivers/media/video/w9968cf_decoder.h b/drivers/media/video/w9968cf_decoder.h deleted file mode 100644 index 59decbfc540a..000000000000 --- a/drivers/media/video/w9968cf_decoder.h +++ /dev/null | |||
@@ -1,86 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * Video decoder for the W996[87]CF driver for Linux. * | ||
3 | * * | ||
4 | * Copyright (C) 2003 2004 by Luca Risolia <luca.risolia@studio.unibo.it> * | ||
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 _W9968CF_DECODER_H_ | ||
22 | #define _W9968CF_DECODER_H_ | ||
23 | |||
24 | /* Comment/uncomment this for high/low quality of compressed video */ | ||
25 | #define W9968CF_DEC_FAST_LOWQUALITY_VIDEO | ||
26 | |||
27 | #ifdef W9968CF_DEC_FAST_LOWQUALITY_VIDEO | ||
28 | static const unsigned char Y_QUANTABLE[64] = { | ||
29 | 16, 11, 10, 16, 24, 40, 51, 61, | ||
30 | 12, 12, 14, 19, 26, 58, 60, 55, | ||
31 | 14, 13, 16, 24, 40, 57, 69, 56, | ||
32 | 14, 17, 22, 29, 51, 87, 80, 62, | ||
33 | 18, 22, 37, 56, 68, 109, 103, 77, | ||
34 | 24, 35, 55, 64, 81, 104, 113, 92, | ||
35 | 49, 64, 78, 87, 103, 121, 120, 101, | ||
36 | 72, 92, 95, 98, 112, 100, 103, 99 | ||
37 | }; | ||
38 | |||
39 | static const unsigned char UV_QUANTABLE[64] = { | ||
40 | 17, 18, 24, 47, 99, 99, 99, 99, | ||
41 | 18, 21, 26, 66, 99, 99, 99, 99, | ||
42 | 24, 26, 56, 99, 99, 99, 99, 99, | ||
43 | 47, 66, 99, 99, 99, 99, 99, 99, | ||
44 | 99, 99, 99, 99, 99, 99, 99, 99, | ||
45 | 99, 99, 99, 99, 99, 99, 99, 99, | ||
46 | 99, 99, 99, 99, 99, 99, 99, 99, | ||
47 | 99, 99, 99, 99, 99, 99, 99, 99 | ||
48 | }; | ||
49 | #else | ||
50 | static const unsigned char Y_QUANTABLE[64] = { | ||
51 | 8, 5, 5, 8, 12, 20, 25, 30, | ||
52 | 6, 6, 7, 9, 13, 29, 30, 27, | ||
53 | 7, 6, 8, 12, 20, 28, 34, 28, | ||
54 | 7, 8, 11, 14, 25, 43, 40, 31, | ||
55 | 9, 11, 18, 28, 34, 54, 51, 38, | ||
56 | 12, 17, 27, 32, 40, 52, 56, 46, | ||
57 | 24, 32, 39, 43, 51, 60, 60, 50, | ||
58 | 36, 46, 47, 49, 56, 50, 51, 49 | ||
59 | }; | ||
60 | |||
61 | static const unsigned char UV_QUANTABLE[64] = { | ||
62 | 8, 9, 12, 23, 49, 49, 49, 49, | ||
63 | 9, 10, 13, 33, 49, 49, 49, 49, | ||
64 | 12, 13, 28, 49, 49, 49, 49, 49, | ||
65 | 23, 33, 49, 49, 49, 49, 49, 49, | ||
66 | 49, 49, 49, 49, 49, 49, 49, 49, | ||
67 | 49, 49, 49, 49, 49, 49, 49, 49, | ||
68 | 49, 49, 49, 49, 49, 49, 49, 49, | ||
69 | 49, 49, 49, 49, 49, 49, 49, 49 | ||
70 | }; | ||
71 | #endif | ||
72 | |||
73 | #define W9968CF_DEC_ERR_CORRUPTED_DATA -1 | ||
74 | #define W9968CF_DEC_ERR_BUF_OVERFLOW -2 | ||
75 | #define W9968CF_DEC_ERR_NO_SOI -3 | ||
76 | #define W9968CF_DEC_ERR_NO_SOF0 -4 | ||
77 | #define W9968CF_DEC_ERR_NO_SOS -5 | ||
78 | #define W9968CF_DEC_ERR_NO_EOI -6 | ||
79 | |||
80 | extern void w9968cf_init_decoder(void); | ||
81 | extern int w9968cf_check_headers(const unsigned char* Pin, | ||
82 | const unsigned long BUF_SIZE); | ||
83 | extern int w9968cf_decode(const char* Pin, const unsigned long BUF_SIZE, | ||
84 | const unsigned W, const unsigned H, char* Pout); | ||
85 | |||
86 | #endif /* _W9968CF_DECODER_H_ */ | ||
diff --git a/drivers/media/video/w9968cf_vpp.h b/drivers/media/video/w9968cf_vpp.h deleted file mode 100644 index 88c9b6c0cc36..000000000000 --- a/drivers/media/video/w9968cf_vpp.h +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * Interface for video post-processing functions for the W996[87]CF driver * | ||
3 | * for Linux. * | ||
4 | * * | ||
5 | * Copyright (C) 2002-2004 by Luca Risolia <luca.risolia@studio.unibo.it> * | ||
6 | * * | ||
7 | * This program is free software; you can redistribute it and/or modify * | ||
8 | * it under the terms of the GNU General Public License as published by * | ||
9 | * the Free Software Foundation; either version 2 of the License, or * | ||
10 | * (at your option) any later version. * | ||
11 | * * | ||
12 | * This program is distributed in the hope that it will be useful, * | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
15 | * GNU General Public License for more details. * | ||
16 | * * | ||
17 | * You should have received a copy of the GNU General Public License * | ||
18 | * along with this program; if not, write to the Free Software * | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * | ||
20 | ***************************************************************************/ | ||
21 | |||
22 | #ifndef _W9968CF_VPP_H_ | ||
23 | #define _W9968CF_VPP_H_ | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <asm/types.h> | ||
27 | |||
28 | struct w9968cf_vpp_t { | ||
29 | struct module* owner; | ||
30 | int (*check_headers)(const unsigned char*, const unsigned long); | ||
31 | int (*decode)(const char*, const unsigned long, const unsigned, | ||
32 | const unsigned, char*); | ||
33 | void (*swap_yuvbytes)(void*, unsigned long); | ||
34 | void (*uyvy_to_rgbx)(u8*, unsigned long, u8*, u16, u8); | ||
35 | void (*scale_up)(u8*, u8*, u16, u16, u16, u16, u16); | ||
36 | |||
37 | u8 busy; /* read-only flag: module is/is not in use */ | ||
38 | }; | ||
39 | |||
40 | #endif /* _W9968CF_VPP_H_ */ | ||
diff --git a/drivers/media/video/zc0301/Kconfig b/drivers/media/video/zc0301/Kconfig deleted file mode 100644 index a7e610e0be9e..000000000000 --- a/drivers/media/video/zc0301/Kconfig +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | config USB_ZC0301 | ||
2 | tristate "USB ZC0301[P] webcam support (DEPRECATED)" | ||
3 | depends on VIDEO_V4L2 | ||
4 | default n | ||
5 | ---help--- | ||
6 | This driver is DEPRECATED please use the gspca zc3xx module | ||
7 | instead. | ||
8 | |||
9 | Say Y here if you want support for cameras based on the ZC0301 or | ||
10 | ZC0301P Image Processors and Control Chips. | ||
11 | |||
12 | See <file:Documentation/video4linux/zc0301.txt> for more info. | ||
13 | |||
14 | To compile this driver as a module, choose M here: the | ||
15 | module will be called zc0301. | ||
diff --git a/drivers/media/video/zc0301/Makefile b/drivers/media/video/zc0301/Makefile deleted file mode 100644 index d9e6d97fade6..000000000000 --- a/drivers/media/video/zc0301/Makefile +++ /dev/null | |||
@@ -1,3 +0,0 @@ | |||
1 | zc0301-objs := zc0301_core.o zc0301_pb0330.o zc0301_pas202bcb.o | ||
2 | |||
3 | obj-$(CONFIG_USB_ZC0301) += zc0301.o | ||
diff --git a/drivers/media/video/zc0301/zc0301.h b/drivers/media/video/zc0301/zc0301.h deleted file mode 100644 index b1b5cceb4baa..000000000000 --- a/drivers/media/video/zc0301/zc0301.h +++ /dev/null | |||
@@ -1,196 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * V4L2 driver for ZC0301[P] Image Processor and Control Chip * | ||
3 | * * | ||
4 | * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * | ||
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 _ZC0301_H_ | ||
22 | #define _ZC0301_H_ | ||
23 | |||
24 | #include <linux/version.h> | ||
25 | #include <linux/usb.h> | ||
26 | #include <linux/videodev2.h> | ||
27 | #include <media/v4l2-common.h> | ||
28 | #include <media/v4l2-ioctl.h> | ||
29 | #include <linux/device.h> | ||
30 | #include <linux/list.h> | ||
31 | #include <linux/spinlock.h> | ||
32 | #include <linux/time.h> | ||
33 | #include <linux/wait.h> | ||
34 | #include <linux/types.h> | ||
35 | #include <linux/param.h> | ||
36 | #include <linux/mutex.h> | ||
37 | #include <linux/rwsem.h> | ||
38 | #include <linux/stddef.h> | ||
39 | #include <linux/string.h> | ||
40 | #include <linux/kref.h> | ||
41 | |||
42 | #include "zc0301_sensor.h" | ||
43 | |||
44 | /*****************************************************************************/ | ||
45 | |||
46 | #define ZC0301_DEBUG | ||
47 | #define ZC0301_DEBUG_LEVEL 2 | ||
48 | #define ZC0301_MAX_DEVICES 64 | ||
49 | #define ZC0301_FORCE_MUNMAP 0 | ||
50 | #define ZC0301_MAX_FRAMES 32 | ||
51 | #define ZC0301_COMPRESSION_QUALITY 0 | ||
52 | #define ZC0301_URBS 2 | ||
53 | #define ZC0301_ISO_PACKETS 7 | ||
54 | #define ZC0301_ALTERNATE_SETTING 7 | ||
55 | #define ZC0301_URB_TIMEOUT msecs_to_jiffies(2 * ZC0301_ISO_PACKETS) | ||
56 | #define ZC0301_CTRL_TIMEOUT 100 | ||
57 | #define ZC0301_FRAME_TIMEOUT 2 | ||
58 | |||
59 | /*****************************************************************************/ | ||
60 | |||
61 | ZC0301_ID_TABLE | ||
62 | ZC0301_SENSOR_TABLE | ||
63 | |||
64 | enum zc0301_frame_state { | ||
65 | F_UNUSED, | ||
66 | F_QUEUED, | ||
67 | F_GRABBING, | ||
68 | F_DONE, | ||
69 | F_ERROR, | ||
70 | }; | ||
71 | |||
72 | struct zc0301_frame_t { | ||
73 | void* bufmem; | ||
74 | struct v4l2_buffer buf; | ||
75 | enum zc0301_frame_state state; | ||
76 | struct list_head frame; | ||
77 | unsigned long vma_use_count; | ||
78 | }; | ||
79 | |||
80 | enum zc0301_dev_state { | ||
81 | DEV_INITIALIZED = 0x01, | ||
82 | DEV_DISCONNECTED = 0x02, | ||
83 | DEV_MISCONFIGURED = 0x04, | ||
84 | }; | ||
85 | |||
86 | enum zc0301_io_method { | ||
87 | IO_NONE, | ||
88 | IO_READ, | ||
89 | IO_MMAP, | ||
90 | }; | ||
91 | |||
92 | enum zc0301_stream_state { | ||
93 | STREAM_OFF, | ||
94 | STREAM_INTERRUPT, | ||
95 | STREAM_ON, | ||
96 | }; | ||
97 | |||
98 | struct zc0301_module_param { | ||
99 | u8 force_munmap; | ||
100 | u16 frame_timeout; | ||
101 | }; | ||
102 | |||
103 | static DECLARE_RWSEM(zc0301_dev_lock); | ||
104 | |||
105 | struct zc0301_device { | ||
106 | struct video_device* v4ldev; | ||
107 | |||
108 | struct zc0301_sensor sensor; | ||
109 | |||
110 | struct usb_device* usbdev; | ||
111 | struct urb* urb[ZC0301_URBS]; | ||
112 | void* transfer_buffer[ZC0301_URBS]; | ||
113 | u8* control_buffer; | ||
114 | |||
115 | struct zc0301_frame_t *frame_current, frame[ZC0301_MAX_FRAMES]; | ||
116 | struct list_head inqueue, outqueue; | ||
117 | u32 frame_count, nbuffers, nreadbuffers; | ||
118 | |||
119 | enum zc0301_io_method io; | ||
120 | enum zc0301_stream_state stream; | ||
121 | |||
122 | struct v4l2_jpegcompression compression; | ||
123 | |||
124 | struct zc0301_module_param module_param; | ||
125 | |||
126 | struct kref kref; | ||
127 | enum zc0301_dev_state state; | ||
128 | u8 users; | ||
129 | |||
130 | struct completion probe; | ||
131 | struct mutex open_mutex, fileop_mutex; | ||
132 | spinlock_t queue_lock; | ||
133 | wait_queue_head_t wait_open, wait_frame, wait_stream; | ||
134 | }; | ||
135 | |||
136 | /*****************************************************************************/ | ||
137 | |||
138 | struct zc0301_device* | ||
139 | zc0301_match_id(struct zc0301_device* cam, const struct usb_device_id *id) | ||
140 | { | ||
141 | return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL; | ||
142 | } | ||
143 | |||
144 | void | ||
145 | zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor) | ||
146 | { | ||
147 | memcpy(&cam->sensor, sensor, sizeof(struct zc0301_sensor)); | ||
148 | } | ||
149 | |||
150 | /*****************************************************************************/ | ||
151 | |||
152 | #undef DBG | ||
153 | #undef KDBG | ||
154 | #ifdef ZC0301_DEBUG | ||
155 | # define DBG(level, fmt, args...) \ | ||
156 | do { \ | ||
157 | if (debug >= (level)) { \ | ||
158 | if ((level) == 1) \ | ||
159 | dev_err(&cam->usbdev->dev, fmt "\n", ## args); \ | ||
160 | else if ((level) == 2) \ | ||
161 | dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ | ||
162 | else if ((level) >= 3) \ | ||
163 | dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", \ | ||
164 | __FILE__, __func__, __LINE__ , ## args); \ | ||
165 | } \ | ||
166 | } while (0) | ||
167 | # define KDBG(level, fmt, args...) \ | ||
168 | do { \ | ||
169 | if (debug >= (level)) { \ | ||
170 | if ((level) == 1 || (level) == 2) \ | ||
171 | pr_info("zc0301: " fmt "\n", ## args); \ | ||
172 | else if ((level) == 3) \ | ||
173 | pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__, \ | ||
174 | __func__, __LINE__ , ## args); \ | ||
175 | } \ | ||
176 | } while (0) | ||
177 | # define V4LDBG(level, name, cmd) \ | ||
178 | do { \ | ||
179 | if (debug >= (level)) \ | ||
180 | v4l_print_ioctl(name, cmd); \ | ||
181 | } while (0) | ||
182 | #else | ||
183 | # define DBG(level, fmt, args...) do {;} while(0) | ||
184 | # define KDBG(level, fmt, args...) do {;} while(0) | ||
185 | # define V4LDBG(level, name, cmd) do {;} while(0) | ||
186 | #endif | ||
187 | |||
188 | #undef PDBG | ||
189 | #define PDBG(fmt, args...) \ | ||
190 | dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__, \ | ||
191 | __LINE__ , ## args) | ||
192 | |||
193 | #undef PDBGG | ||
194 | #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ | ||
195 | |||
196 | #endif /* _ZC0301_H_ */ | ||
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c deleted file mode 100644 index bb51cfb0c647..000000000000 --- a/drivers/media/video/zc0301/zc0301_core.c +++ /dev/null | |||
@@ -1,2098 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * Video4Linux2 driver for ZC0301[P] Image Processor and Control Chip * | ||
3 | * * | ||
4 | * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * | ||
5 | * * | ||
6 | * Informations about the chip internals needed to enable the I2C protocol * | ||
7 | * have been taken from the documentation of the ZC030x Video4Linux1 * | ||
8 | * driver written by Andrew Birkett <andy@nobugs.org> * | ||
9 | * * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the Free Software * | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * | ||
23 | ***************************************************************************/ | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/param.h> | ||
29 | #include <linux/errno.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/device.h> | ||
32 | #include <linux/fs.h> | ||
33 | #include <linux/delay.h> | ||
34 | #include <linux/compiler.h> | ||
35 | #include <linux/ioctl.h> | ||
36 | #include <linux/poll.h> | ||
37 | #include <linux/stat.h> | ||
38 | #include <linux/mm.h> | ||
39 | #include <linux/vmalloc.h> | ||
40 | #include <linux/page-flags.h> | ||
41 | #include <asm/byteorder.h> | ||
42 | #include <asm/page.h> | ||
43 | #include <asm/uaccess.h> | ||
44 | |||
45 | #include "zc0301.h" | ||
46 | |||
47 | /*****************************************************************************/ | ||
48 | |||
49 | #define ZC0301_MODULE_NAME "V4L2 driver for ZC0301[P] " \ | ||
50 | "Image Processor and Control Chip" | ||
51 | #define ZC0301_MODULE_AUTHOR "(C) 2006-2007 Luca Risolia" | ||
52 | #define ZC0301_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" | ||
53 | #define ZC0301_MODULE_LICENSE "GPL" | ||
54 | #define ZC0301_MODULE_VERSION "1:1.10" | ||
55 | #define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 10) | ||
56 | |||
57 | /*****************************************************************************/ | ||
58 | |||
59 | MODULE_DEVICE_TABLE(usb, zc0301_id_table); | ||
60 | |||
61 | MODULE_AUTHOR(ZC0301_MODULE_AUTHOR " " ZC0301_AUTHOR_EMAIL); | ||
62 | MODULE_DESCRIPTION(ZC0301_MODULE_NAME); | ||
63 | MODULE_VERSION(ZC0301_MODULE_VERSION); | ||
64 | MODULE_LICENSE(ZC0301_MODULE_LICENSE); | ||
65 | |||
66 | static short video_nr[] = {[0 ... ZC0301_MAX_DEVICES-1] = -1}; | ||
67 | module_param_array(video_nr, short, NULL, 0444); | ||
68 | MODULE_PARM_DESC(video_nr, | ||
69 | "\n<-1|n[,...]> Specify V4L2 minor mode number." | ||
70 | "\n -1 = use next available (default)" | ||
71 | "\n n = use minor number n (integer >= 0)" | ||
72 | "\nYou can specify up to " | ||
73 | __MODULE_STRING(ZC0301_MAX_DEVICES) " cameras this way." | ||
74 | "\nFor example:" | ||
75 | "\nvideo_nr=-1,2,-1 would assign minor number 2 to" | ||
76 | "\nthe second registered camera and use auto for the first" | ||
77 | "\none and for every other camera." | ||
78 | "\n"); | ||
79 | |||
80 | static short force_munmap[] = {[0 ... ZC0301_MAX_DEVICES-1] = | ||
81 | ZC0301_FORCE_MUNMAP}; | ||
82 | module_param_array(force_munmap, bool, NULL, 0444); | ||
83 | MODULE_PARM_DESC(force_munmap, | ||
84 | "\n<0|1[,...]> Force the application to unmap previously" | ||
85 | "\nmapped buffer memory before calling any VIDIOC_S_CROP or" | ||
86 | "\nVIDIOC_S_FMT ioctl's. Not all the applications support" | ||
87 | "\nthis feature. This parameter is specific for each" | ||
88 | "\ndetected camera." | ||
89 | "\n 0 = do not force memory unmapping" | ||
90 | "\n 1 = force memory unmapping (save memory)" | ||
91 | "\nDefault value is "__MODULE_STRING(ZC0301_FORCE_MUNMAP)"." | ||
92 | "\n"); | ||
93 | |||
94 | static unsigned int frame_timeout[] = {[0 ... ZC0301_MAX_DEVICES-1] = | ||
95 | ZC0301_FRAME_TIMEOUT}; | ||
96 | module_param_array(frame_timeout, uint, NULL, 0644); | ||
97 | MODULE_PARM_DESC(frame_timeout, | ||
98 | "\n<n[,...]> Timeout for a video frame in seconds." | ||
99 | "\nThis parameter is specific for each detected camera." | ||
100 | "\nDefault value is "__MODULE_STRING(ZC0301_FRAME_TIMEOUT)"." | ||
101 | "\n"); | ||
102 | |||
103 | #ifdef ZC0301_DEBUG | ||
104 | static unsigned short debug = ZC0301_DEBUG_LEVEL; | ||
105 | module_param(debug, ushort, 0644); | ||
106 | MODULE_PARM_DESC(debug, | ||
107 | "\n<n> Debugging information level, from 0 to 3:" | ||
108 | "\n0 = none (use carefully)" | ||
109 | "\n1 = critical errors" | ||
110 | "\n2 = significant informations" | ||
111 | "\n3 = more verbose messages" | ||
112 | "\nLevel 3 is useful for testing only, when only " | ||
113 | "one device is used." | ||
114 | "\nDefault value is "__MODULE_STRING(ZC0301_DEBUG_LEVEL)"." | ||
115 | "\n"); | ||
116 | #endif | ||
117 | |||
118 | /*****************************************************************************/ | ||
119 | |||
120 | static u32 | ||
121 | zc0301_request_buffers(struct zc0301_device* cam, u32 count, | ||
122 | enum zc0301_io_method io) | ||
123 | { | ||
124 | struct v4l2_pix_format* p = &(cam->sensor.pix_format); | ||
125 | struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); | ||
126 | const size_t imagesize = cam->module_param.force_munmap || | ||
127 | io == IO_READ ? | ||
128 | (p->width * p->height * p->priv) / 8 : | ||
129 | (r->width * r->height * p->priv) / 8; | ||
130 | void* buff = NULL; | ||
131 | u32 i; | ||
132 | |||
133 | if (count > ZC0301_MAX_FRAMES) | ||
134 | count = ZC0301_MAX_FRAMES; | ||
135 | |||
136 | cam->nbuffers = count; | ||
137 | while (cam->nbuffers > 0) { | ||
138 | if ((buff = vmalloc_32_user(cam->nbuffers * | ||
139 | PAGE_ALIGN(imagesize)))) | ||
140 | break; | ||
141 | cam->nbuffers--; | ||
142 | } | ||
143 | |||
144 | for (i = 0; i < cam->nbuffers; i++) { | ||
145 | cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize); | ||
146 | cam->frame[i].buf.index = i; | ||
147 | cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize); | ||
148 | cam->frame[i].buf.length = imagesize; | ||
149 | cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
150 | cam->frame[i].buf.sequence = 0; | ||
151 | cam->frame[i].buf.field = V4L2_FIELD_NONE; | ||
152 | cam->frame[i].buf.memory = V4L2_MEMORY_MMAP; | ||
153 | cam->frame[i].buf.flags = 0; | ||
154 | } | ||
155 | |||
156 | return cam->nbuffers; | ||
157 | } | ||
158 | |||
159 | |||
160 | static void zc0301_release_buffers(struct zc0301_device* cam) | ||
161 | { | ||
162 | if (cam->nbuffers) { | ||
163 | vfree(cam->frame[0].bufmem); | ||
164 | cam->nbuffers = 0; | ||
165 | } | ||
166 | cam->frame_current = NULL; | ||
167 | } | ||
168 | |||
169 | |||
170 | static void zc0301_empty_framequeues(struct zc0301_device* cam) | ||
171 | { | ||
172 | u32 i; | ||
173 | |||
174 | INIT_LIST_HEAD(&cam->inqueue); | ||
175 | INIT_LIST_HEAD(&cam->outqueue); | ||
176 | |||
177 | for (i = 0; i < ZC0301_MAX_FRAMES; i++) { | ||
178 | cam->frame[i].state = F_UNUSED; | ||
179 | cam->frame[i].buf.bytesused = 0; | ||
180 | } | ||
181 | } | ||
182 | |||
183 | |||
184 | static void zc0301_requeue_outqueue(struct zc0301_device* cam) | ||
185 | { | ||
186 | struct zc0301_frame_t *i; | ||
187 | |||
188 | list_for_each_entry(i, &cam->outqueue, frame) { | ||
189 | i->state = F_QUEUED; | ||
190 | list_add(&i->frame, &cam->inqueue); | ||
191 | } | ||
192 | |||
193 | INIT_LIST_HEAD(&cam->outqueue); | ||
194 | } | ||
195 | |||
196 | |||
197 | static void zc0301_queue_unusedframes(struct zc0301_device* cam) | ||
198 | { | ||
199 | unsigned long lock_flags; | ||
200 | u32 i; | ||
201 | |||
202 | for (i = 0; i < cam->nbuffers; i++) | ||
203 | if (cam->frame[i].state == F_UNUSED) { | ||
204 | cam->frame[i].state = F_QUEUED; | ||
205 | spin_lock_irqsave(&cam->queue_lock, lock_flags); | ||
206 | list_add_tail(&cam->frame[i].frame, &cam->inqueue); | ||
207 | spin_unlock_irqrestore(&cam->queue_lock, lock_flags); | ||
208 | } | ||
209 | } | ||
210 | |||
211 | /*****************************************************************************/ | ||
212 | |||
213 | int zc0301_write_reg(struct zc0301_device* cam, u16 index, u16 value) | ||
214 | { | ||
215 | struct usb_device* udev = cam->usbdev; | ||
216 | int res; | ||
217 | |||
218 | res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0xa0, 0x40, | ||
219 | value, index, NULL, 0, ZC0301_CTRL_TIMEOUT); | ||
220 | if (res < 0) { | ||
221 | DBG(3, "Failed to write a register (index 0x%04X, " | ||
222 | "value 0x%02X, error %d)",index, value, res); | ||
223 | return -1; | ||
224 | } | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | |||
230 | int zc0301_read_reg(struct zc0301_device* cam, u16 index) | ||
231 | { | ||
232 | struct usb_device* udev = cam->usbdev; | ||
233 | u8* buff = cam->control_buffer; | ||
234 | int res; | ||
235 | |||
236 | res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0xa1, 0xc0, | ||
237 | 0x0001, index, buff, 1, ZC0301_CTRL_TIMEOUT); | ||
238 | if (res < 0) | ||
239 | DBG(3, "Failed to read a register (index 0x%04X, error %d)", | ||
240 | index, res); | ||
241 | |||
242 | PDBGG("Read: index 0x%04X, value: 0x%04X", index, (int)(*buff)); | ||
243 | |||
244 | return (res >= 0) ? (int)(*buff) : -1; | ||
245 | } | ||
246 | |||
247 | |||
248 | int zc0301_i2c_read(struct zc0301_device* cam, u16 address, u8 length) | ||
249 | { | ||
250 | int err = 0, res, r0, r1; | ||
251 | |||
252 | err += zc0301_write_reg(cam, 0x0092, address); | ||
253 | err += zc0301_write_reg(cam, 0x0090, 0x02); | ||
254 | |||
255 | msleep(1); | ||
256 | |||
257 | res = zc0301_read_reg(cam, 0x0091); | ||
258 | if (res < 0) | ||
259 | err += res; | ||
260 | r0 = zc0301_read_reg(cam, 0x0095); | ||
261 | if (r0 < 0) | ||
262 | err += r0; | ||
263 | r1 = zc0301_read_reg(cam, 0x0096); | ||
264 | if (r1 < 0) | ||
265 | err += r1; | ||
266 | |||
267 | res = (length <= 1) ? r0 : r0 | (r1 << 8); | ||
268 | |||
269 | if (err) | ||
270 | DBG(3, "I2C read failed at address 0x%04X, value: 0x%04X", | ||
271 | address, res); | ||
272 | |||
273 | |||
274 | PDBGG("I2C read: address 0x%04X, value: 0x%04X", address, res); | ||
275 | |||
276 | return err ? -1 : res; | ||
277 | } | ||
278 | |||
279 | |||
280 | int zc0301_i2c_write(struct zc0301_device* cam, u16 address, u16 value) | ||
281 | { | ||
282 | int err = 0, res; | ||
283 | |||
284 | err += zc0301_write_reg(cam, 0x0092, address); | ||
285 | err += zc0301_write_reg(cam, 0x0093, value & 0xff); | ||
286 | err += zc0301_write_reg(cam, 0x0094, value >> 8); | ||
287 | err += zc0301_write_reg(cam, 0x0090, 0x01); | ||
288 | |||
289 | msleep(1); | ||
290 | |||
291 | res = zc0301_read_reg(cam, 0x0091); | ||
292 | if (res < 0) | ||
293 | err += res; | ||
294 | |||
295 | if (err) | ||
296 | DBG(3, "I2C write failed at address 0x%04X, value: 0x%04X", | ||
297 | address, value); | ||
298 | |||
299 | PDBGG("I2C write: address 0x%04X, value: 0x%04X", address, value); | ||
300 | |||
301 | return err ? -1 : 0; | ||
302 | } | ||
303 | |||
304 | /*****************************************************************************/ | ||
305 | |||
306 | static void zc0301_urb_complete(struct urb *urb) | ||
307 | { | ||
308 | struct zc0301_device* cam = urb->context; | ||
309 | struct zc0301_frame_t** f; | ||
310 | size_t imagesize; | ||
311 | u8 i; | ||
312 | int err = 0; | ||
313 | |||
314 | if (urb->status == -ENOENT) | ||
315 | return; | ||
316 | |||
317 | f = &cam->frame_current; | ||
318 | |||
319 | if (cam->stream == STREAM_INTERRUPT) { | ||
320 | cam->stream = STREAM_OFF; | ||
321 | if ((*f)) | ||
322 | (*f)->state = F_QUEUED; | ||
323 | DBG(3, "Stream interrupted"); | ||
324 | wake_up(&cam->wait_stream); | ||
325 | } | ||
326 | |||
327 | if (cam->state & DEV_DISCONNECTED) | ||
328 | return; | ||
329 | |||
330 | if (cam->state & DEV_MISCONFIGURED) { | ||
331 | wake_up_interruptible(&cam->wait_frame); | ||
332 | return; | ||
333 | } | ||
334 | |||
335 | if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue)) | ||
336 | goto resubmit_urb; | ||
337 | |||
338 | if (!(*f)) | ||
339 | (*f) = list_entry(cam->inqueue.next, struct zc0301_frame_t, | ||
340 | frame); | ||
341 | |||
342 | imagesize = (cam->sensor.pix_format.width * | ||
343 | cam->sensor.pix_format.height * | ||
344 | cam->sensor.pix_format.priv) / 8; | ||
345 | |||
346 | for (i = 0; i < urb->number_of_packets; i++) { | ||
347 | unsigned int len, status; | ||
348 | void *pos; | ||
349 | u16* soi; | ||
350 | u8 sof; | ||
351 | |||
352 | len = urb->iso_frame_desc[i].actual_length; | ||
353 | status = urb->iso_frame_desc[i].status; | ||
354 | pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer; | ||
355 | |||
356 | if (status) { | ||
357 | DBG(3, "Error in isochronous frame"); | ||
358 | (*f)->state = F_ERROR; | ||
359 | continue; | ||
360 | } | ||
361 | |||
362 | sof = (*(soi = pos) == 0xd8ff); | ||
363 | |||
364 | PDBGG("Isochrnous frame: length %u, #%u i,", len, i); | ||
365 | |||
366 | if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR) | ||
367 | start_of_frame: | ||
368 | if (sof) { | ||
369 | (*f)->state = F_GRABBING; | ||
370 | (*f)->buf.bytesused = 0; | ||
371 | do_gettimeofday(&(*f)->buf.timestamp); | ||
372 | DBG(3, "SOF detected: new video frame"); | ||
373 | } | ||
374 | |||
375 | if ((*f)->state == F_GRABBING) { | ||
376 | if (sof && (*f)->buf.bytesused) | ||
377 | goto end_of_frame; | ||
378 | |||
379 | if ((*f)->buf.bytesused + len > imagesize) { | ||
380 | DBG(3, "Video frame size exceeded"); | ||
381 | (*f)->state = F_ERROR; | ||
382 | continue; | ||
383 | } | ||
384 | |||
385 | memcpy((*f)->bufmem+(*f)->buf.bytesused, pos, len); | ||
386 | (*f)->buf.bytesused += len; | ||
387 | |||
388 | if ((*f)->buf.bytesused == imagesize) { | ||
389 | u32 b; | ||
390 | end_of_frame: | ||
391 | b = (*f)->buf.bytesused; | ||
392 | (*f)->state = F_DONE; | ||
393 | (*f)->buf.sequence= ++cam->frame_count; | ||
394 | spin_lock(&cam->queue_lock); | ||
395 | list_move_tail(&(*f)->frame, &cam->outqueue); | ||
396 | if (!list_empty(&cam->inqueue)) | ||
397 | (*f) = list_entry(cam->inqueue.next, | ||
398 | struct zc0301_frame_t, | ||
399 | frame); | ||
400 | else | ||
401 | (*f) = NULL; | ||
402 | spin_unlock(&cam->queue_lock); | ||
403 | DBG(3, "Video frame captured: : %lu bytes", | ||
404 | (unsigned long)(b)); | ||
405 | |||
406 | if (!(*f)) | ||
407 | goto resubmit_urb; | ||
408 | |||
409 | if (sof) | ||
410 | goto start_of_frame; | ||
411 | } | ||
412 | } | ||
413 | } | ||
414 | |||
415 | resubmit_urb: | ||
416 | urb->dev = cam->usbdev; | ||
417 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
418 | if (err < 0 && err != -EPERM) { | ||
419 | cam->state |= DEV_MISCONFIGURED; | ||
420 | DBG(1, "usb_submit_urb() failed"); | ||
421 | } | ||
422 | |||
423 | wake_up_interruptible(&cam->wait_frame); | ||
424 | } | ||
425 | |||
426 | |||
427 | static int zc0301_start_transfer(struct zc0301_device* cam) | ||
428 | { | ||
429 | struct usb_device *udev = cam->usbdev; | ||
430 | struct usb_host_interface* altsetting = usb_altnum_to_altsetting( | ||
431 | usb_ifnum_to_if(udev, 0), | ||
432 | ZC0301_ALTERNATE_SETTING); | ||
433 | const unsigned int psz = le16_to_cpu(altsetting-> | ||
434 | endpoint[0].desc.wMaxPacketSize); | ||
435 | struct urb* urb; | ||
436 | s8 i, j; | ||
437 | int err = 0; | ||
438 | |||
439 | for (i = 0; i < ZC0301_URBS; i++) { | ||
440 | cam->transfer_buffer[i] = kzalloc(ZC0301_ISO_PACKETS * psz, | ||
441 | GFP_KERNEL); | ||
442 | if (!cam->transfer_buffer[i]) { | ||
443 | err = -ENOMEM; | ||
444 | DBG(1, "Not enough memory"); | ||
445 | goto free_buffers; | ||
446 | } | ||
447 | } | ||
448 | |||
449 | for (i = 0; i < ZC0301_URBS; i++) { | ||
450 | urb = usb_alloc_urb(ZC0301_ISO_PACKETS, GFP_KERNEL); | ||
451 | cam->urb[i] = urb; | ||
452 | if (!urb) { | ||
453 | err = -ENOMEM; | ||
454 | DBG(1, "usb_alloc_urb() failed"); | ||
455 | goto free_urbs; | ||
456 | } | ||
457 | urb->dev = udev; | ||
458 | urb->context = cam; | ||
459 | urb->pipe = usb_rcvisocpipe(udev, 1); | ||
460 | urb->transfer_flags = URB_ISO_ASAP; | ||
461 | urb->number_of_packets = ZC0301_ISO_PACKETS; | ||
462 | urb->complete = zc0301_urb_complete; | ||
463 | urb->transfer_buffer = cam->transfer_buffer[i]; | ||
464 | urb->transfer_buffer_length = psz * ZC0301_ISO_PACKETS; | ||
465 | urb->interval = 1; | ||
466 | for (j = 0; j < ZC0301_ISO_PACKETS; j++) { | ||
467 | urb->iso_frame_desc[j].offset = psz * j; | ||
468 | urb->iso_frame_desc[j].length = psz; | ||
469 | } | ||
470 | } | ||
471 | |||
472 | err = usb_set_interface(udev, 0, ZC0301_ALTERNATE_SETTING); | ||
473 | if (err) { | ||
474 | DBG(1, "usb_set_interface() failed"); | ||
475 | goto free_urbs; | ||
476 | } | ||
477 | |||
478 | cam->frame_current = NULL; | ||
479 | |||
480 | for (i = 0; i < ZC0301_URBS; i++) { | ||
481 | err = usb_submit_urb(cam->urb[i], GFP_KERNEL); | ||
482 | if (err) { | ||
483 | for (j = i-1; j >= 0; j--) | ||
484 | usb_kill_urb(cam->urb[j]); | ||
485 | DBG(1, "usb_submit_urb() failed, error %d", err); | ||
486 | goto free_urbs; | ||
487 | } | ||
488 | } | ||
489 | |||
490 | return 0; | ||
491 | |||
492 | free_urbs: | ||
493 | for (i = 0; (i < ZC0301_URBS) && cam->urb[i]; i++) | ||
494 | usb_free_urb(cam->urb[i]); | ||
495 | |||
496 | free_buffers: | ||
497 | for (i = 0; (i < ZC0301_URBS) && cam->transfer_buffer[i]; i++) | ||
498 | kfree(cam->transfer_buffer[i]); | ||
499 | |||
500 | return err; | ||
501 | } | ||
502 | |||
503 | |||
504 | static int zc0301_stop_transfer(struct zc0301_device* cam) | ||
505 | { | ||
506 | struct usb_device *udev = cam->usbdev; | ||
507 | s8 i; | ||
508 | int err = 0; | ||
509 | |||
510 | if (cam->state & DEV_DISCONNECTED) | ||
511 | return 0; | ||
512 | |||
513 | for (i = ZC0301_URBS-1; i >= 0; i--) { | ||
514 | usb_kill_urb(cam->urb[i]); | ||
515 | usb_free_urb(cam->urb[i]); | ||
516 | kfree(cam->transfer_buffer[i]); | ||
517 | } | ||
518 | |||
519 | err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */ | ||
520 | if (err) | ||
521 | DBG(3, "usb_set_interface() failed"); | ||
522 | |||
523 | return err; | ||
524 | } | ||
525 | |||
526 | |||
527 | static int zc0301_stream_interrupt(struct zc0301_device* cam) | ||
528 | { | ||
529 | long timeout; | ||
530 | |||
531 | cam->stream = STREAM_INTERRUPT; | ||
532 | timeout = wait_event_timeout(cam->wait_stream, | ||
533 | (cam->stream == STREAM_OFF) || | ||
534 | (cam->state & DEV_DISCONNECTED), | ||
535 | ZC0301_URB_TIMEOUT); | ||
536 | if (cam->state & DEV_DISCONNECTED) | ||
537 | return -ENODEV; | ||
538 | else if (cam->stream != STREAM_OFF) { | ||
539 | cam->state |= DEV_MISCONFIGURED; | ||
540 | DBG(1, "URB timeout reached. The camera is misconfigured. To " | ||
541 | "use it, close and open %s again.", | ||
542 | video_device_node_name(cam->v4ldev)); | ||
543 | return -EIO; | ||
544 | } | ||
545 | |||
546 | return 0; | ||
547 | } | ||
548 | |||
549 | /*****************************************************************************/ | ||
550 | |||
551 | static int | ||
552 | zc0301_set_compression(struct zc0301_device* cam, | ||
553 | struct v4l2_jpegcompression* compression) | ||
554 | { | ||
555 | int r, err = 0; | ||
556 | |||
557 | if ((r = zc0301_read_reg(cam, 0x0008)) < 0) | ||
558 | err += r; | ||
559 | err += zc0301_write_reg(cam, 0x0008, r | 0x11 | compression->quality); | ||
560 | |||
561 | return err ? -EIO : 0; | ||
562 | } | ||
563 | |||
564 | |||
565 | static int zc0301_init(struct zc0301_device* cam) | ||
566 | { | ||
567 | struct zc0301_sensor* s = &cam->sensor; | ||
568 | struct v4l2_control ctrl; | ||
569 | struct v4l2_queryctrl *qctrl; | ||
570 | struct v4l2_rect* rect; | ||
571 | u8 i = 0; | ||
572 | int err = 0; | ||
573 | |||
574 | if (!(cam->state & DEV_INITIALIZED)) { | ||
575 | mutex_init(&cam->open_mutex); | ||
576 | init_waitqueue_head(&cam->wait_open); | ||
577 | qctrl = s->qctrl; | ||
578 | rect = &(s->cropcap.defrect); | ||
579 | cam->compression.quality = ZC0301_COMPRESSION_QUALITY; | ||
580 | } else { /* use current values */ | ||
581 | qctrl = s->_qctrl; | ||
582 | rect = &(s->_rect); | ||
583 | } | ||
584 | |||
585 | if (s->init) { | ||
586 | err = s->init(cam); | ||
587 | if (err) { | ||
588 | DBG(3, "Sensor initialization failed"); | ||
589 | return err; | ||
590 | } | ||
591 | } | ||
592 | |||
593 | if ((err = zc0301_set_compression(cam, &cam->compression))) { | ||
594 | DBG(3, "set_compression() failed"); | ||
595 | return err; | ||
596 | } | ||
597 | |||
598 | if (s->set_crop) | ||
599 | if ((err = s->set_crop(cam, rect))) { | ||
600 | DBG(3, "set_crop() failed"); | ||
601 | return err; | ||
602 | } | ||
603 | |||
604 | if (s->set_ctrl) { | ||
605 | for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) | ||
606 | if (s->qctrl[i].id != 0 && | ||
607 | !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) { | ||
608 | ctrl.id = s->qctrl[i].id; | ||
609 | ctrl.value = qctrl[i].default_value; | ||
610 | err = s->set_ctrl(cam, &ctrl); | ||
611 | if (err) { | ||
612 | DBG(3, "Set %s control failed", | ||
613 | s->qctrl[i].name); | ||
614 | return err; | ||
615 | } | ||
616 | DBG(3, "Image sensor supports '%s' control", | ||
617 | s->qctrl[i].name); | ||
618 | } | ||
619 | } | ||
620 | |||
621 | if (!(cam->state & DEV_INITIALIZED)) { | ||
622 | mutex_init(&cam->fileop_mutex); | ||
623 | spin_lock_init(&cam->queue_lock); | ||
624 | init_waitqueue_head(&cam->wait_frame); | ||
625 | init_waitqueue_head(&cam->wait_stream); | ||
626 | cam->nreadbuffers = 2; | ||
627 | memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl)); | ||
628 | memcpy(&(s->_rect), &(s->cropcap.defrect), | ||
629 | sizeof(struct v4l2_rect)); | ||
630 | cam->state |= DEV_INITIALIZED; | ||
631 | } | ||
632 | |||
633 | DBG(2, "Initialization succeeded"); | ||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | /*****************************************************************************/ | ||
638 | |||
639 | static void zc0301_release_resources(struct kref *kref) | ||
640 | { | ||
641 | struct zc0301_device *cam = container_of(kref, struct zc0301_device, | ||
642 | kref); | ||
643 | DBG(2, "V4L2 device %s deregistered", | ||
644 | video_device_node_name(cam->v4ldev)); | ||
645 | video_set_drvdata(cam->v4ldev, NULL); | ||
646 | video_unregister_device(cam->v4ldev); | ||
647 | usb_put_dev(cam->usbdev); | ||
648 | kfree(cam->control_buffer); | ||
649 | kfree(cam); | ||
650 | } | ||
651 | |||
652 | |||
653 | static int zc0301_open(struct file *filp) | ||
654 | { | ||
655 | struct zc0301_device* cam; | ||
656 | int err = 0; | ||
657 | |||
658 | if (!down_read_trylock(&zc0301_dev_lock)) | ||
659 | return -EAGAIN; | ||
660 | |||
661 | cam = video_drvdata(filp); | ||
662 | |||
663 | if (wait_for_completion_interruptible(&cam->probe)) { | ||
664 | up_read(&zc0301_dev_lock); | ||
665 | return -ERESTARTSYS; | ||
666 | } | ||
667 | |||
668 | kref_get(&cam->kref); | ||
669 | |||
670 | if (mutex_lock_interruptible(&cam->open_mutex)) { | ||
671 | kref_put(&cam->kref, zc0301_release_resources); | ||
672 | up_read(&zc0301_dev_lock); | ||
673 | return -ERESTARTSYS; | ||
674 | } | ||
675 | |||
676 | if (cam->state & DEV_DISCONNECTED) { | ||
677 | DBG(1, "Device not present"); | ||
678 | err = -ENODEV; | ||
679 | goto out; | ||
680 | } | ||
681 | |||
682 | if (cam->users) { | ||
683 | DBG(2, "Device %s is busy...", | ||
684 | video_device_node_name(cam->v4ldev)); | ||
685 | DBG(3, "Simultaneous opens are not supported"); | ||
686 | if ((filp->f_flags & O_NONBLOCK) || | ||
687 | (filp->f_flags & O_NDELAY)) { | ||
688 | err = -EWOULDBLOCK; | ||
689 | goto out; | ||
690 | } | ||
691 | DBG(2, "A blocking open() has been requested. Wait for the " | ||
692 | "device to be released..."); | ||
693 | up_read(&zc0301_dev_lock); | ||
694 | err = wait_event_interruptible_exclusive(cam->wait_open, | ||
695 | (cam->state & DEV_DISCONNECTED) | ||
696 | || !cam->users); | ||
697 | down_read(&zc0301_dev_lock); | ||
698 | if (err) | ||
699 | goto out; | ||
700 | if (cam->state & DEV_DISCONNECTED) { | ||
701 | err = -ENODEV; | ||
702 | goto out; | ||
703 | } | ||
704 | } | ||
705 | |||
706 | if (cam->state & DEV_MISCONFIGURED) { | ||
707 | err = zc0301_init(cam); | ||
708 | if (err) { | ||
709 | DBG(1, "Initialization failed again. " | ||
710 | "I will retry on next open()."); | ||
711 | goto out; | ||
712 | } | ||
713 | cam->state &= ~DEV_MISCONFIGURED; | ||
714 | } | ||
715 | |||
716 | if ((err = zc0301_start_transfer(cam))) | ||
717 | goto out; | ||
718 | |||
719 | filp->private_data = cam; | ||
720 | cam->users++; | ||
721 | cam->io = IO_NONE; | ||
722 | cam->stream = STREAM_OFF; | ||
723 | cam->nbuffers = 0; | ||
724 | cam->frame_count = 0; | ||
725 | zc0301_empty_framequeues(cam); | ||
726 | |||
727 | DBG(3, "Video device %s is open", | ||
728 | video_device_node_name(cam->v4ldev)); | ||
729 | |||
730 | out: | ||
731 | mutex_unlock(&cam->open_mutex); | ||
732 | if (err) | ||
733 | kref_put(&cam->kref, zc0301_release_resources); | ||
734 | up_read(&zc0301_dev_lock); | ||
735 | return err; | ||
736 | } | ||
737 | |||
738 | |||
739 | static int zc0301_release(struct file *filp) | ||
740 | { | ||
741 | struct zc0301_device* cam; | ||
742 | |||
743 | down_write(&zc0301_dev_lock); | ||
744 | |||
745 | cam = video_drvdata(filp); | ||
746 | |||
747 | zc0301_stop_transfer(cam); | ||
748 | zc0301_release_buffers(cam); | ||
749 | cam->users--; | ||
750 | wake_up_interruptible_nr(&cam->wait_open, 1); | ||
751 | |||
752 | DBG(3, "Video device %s closed", | ||
753 | video_device_node_name(cam->v4ldev)); | ||
754 | |||
755 | kref_put(&cam->kref, zc0301_release_resources); | ||
756 | |||
757 | up_write(&zc0301_dev_lock); | ||
758 | |||
759 | return 0; | ||
760 | } | ||
761 | |||
762 | |||
763 | static ssize_t | ||
764 | zc0301_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) | ||
765 | { | ||
766 | struct zc0301_device *cam = video_drvdata(filp); | ||
767 | struct zc0301_frame_t* f, * i; | ||
768 | unsigned long lock_flags; | ||
769 | long timeout; | ||
770 | int err = 0; | ||
771 | |||
772 | if (mutex_lock_interruptible(&cam->fileop_mutex)) | ||
773 | return -ERESTARTSYS; | ||
774 | |||
775 | if (cam->state & DEV_DISCONNECTED) { | ||
776 | DBG(1, "Device not present"); | ||
777 | mutex_unlock(&cam->fileop_mutex); | ||
778 | return -ENODEV; | ||
779 | } | ||
780 | |||
781 | if (cam->state & DEV_MISCONFIGURED) { | ||
782 | DBG(1, "The camera is misconfigured. Close and open it " | ||
783 | "again."); | ||
784 | mutex_unlock(&cam->fileop_mutex); | ||
785 | return -EIO; | ||
786 | } | ||
787 | |||
788 | if (cam->io == IO_MMAP) { | ||
789 | DBG(3, "Close and open the device again to choose the read " | ||
790 | "method"); | ||
791 | mutex_unlock(&cam->fileop_mutex); | ||
792 | return -EBUSY; | ||
793 | } | ||
794 | |||
795 | if (cam->io == IO_NONE) { | ||
796 | if (!zc0301_request_buffers(cam, cam->nreadbuffers, IO_READ)) { | ||
797 | DBG(1, "read() failed, not enough memory"); | ||
798 | mutex_unlock(&cam->fileop_mutex); | ||
799 | return -ENOMEM; | ||
800 | } | ||
801 | cam->io = IO_READ; | ||
802 | cam->stream = STREAM_ON; | ||
803 | } | ||
804 | |||
805 | if (list_empty(&cam->inqueue)) { | ||
806 | if (!list_empty(&cam->outqueue)) | ||
807 | zc0301_empty_framequeues(cam); | ||
808 | zc0301_queue_unusedframes(cam); | ||
809 | } | ||
810 | |||
811 | if (!count) { | ||
812 | mutex_unlock(&cam->fileop_mutex); | ||
813 | return 0; | ||
814 | } | ||
815 | |||
816 | if (list_empty(&cam->outqueue)) { | ||
817 | if (filp->f_flags & O_NONBLOCK) { | ||
818 | mutex_unlock(&cam->fileop_mutex); | ||
819 | return -EAGAIN; | ||
820 | } | ||
821 | timeout = wait_event_interruptible_timeout | ||
822 | ( cam->wait_frame, | ||
823 | (!list_empty(&cam->outqueue)) || | ||
824 | (cam->state & DEV_DISCONNECTED) || | ||
825 | (cam->state & DEV_MISCONFIGURED), | ||
826 | msecs_to_jiffies( | ||
827 | cam->module_param.frame_timeout * 1000 | ||
828 | ) | ||
829 | ); | ||
830 | if (timeout < 0) { | ||
831 | mutex_unlock(&cam->fileop_mutex); | ||
832 | return timeout; | ||
833 | } | ||
834 | if (cam->state & DEV_DISCONNECTED) { | ||
835 | mutex_unlock(&cam->fileop_mutex); | ||
836 | return -ENODEV; | ||
837 | } | ||
838 | if (!timeout || (cam->state & DEV_MISCONFIGURED)) { | ||
839 | mutex_unlock(&cam->fileop_mutex); | ||
840 | return -EIO; | ||
841 | } | ||
842 | } | ||
843 | |||
844 | f = list_entry(cam->outqueue.prev, struct zc0301_frame_t, frame); | ||
845 | |||
846 | if (count > f->buf.bytesused) | ||
847 | count = f->buf.bytesused; | ||
848 | |||
849 | if (copy_to_user(buf, f->bufmem, count)) { | ||
850 | err = -EFAULT; | ||
851 | goto exit; | ||
852 | } | ||
853 | *f_pos += count; | ||
854 | |||
855 | exit: | ||
856 | spin_lock_irqsave(&cam->queue_lock, lock_flags); | ||
857 | list_for_each_entry(i, &cam->outqueue, frame) | ||
858 | i->state = F_UNUSED; | ||
859 | INIT_LIST_HEAD(&cam->outqueue); | ||
860 | spin_unlock_irqrestore(&cam->queue_lock, lock_flags); | ||
861 | |||
862 | zc0301_queue_unusedframes(cam); | ||
863 | |||
864 | PDBGG("Frame #%lu, bytes read: %zu", | ||
865 | (unsigned long)f->buf.index, count); | ||
866 | |||
867 | mutex_unlock(&cam->fileop_mutex); | ||
868 | |||
869 | return err ? err : count; | ||
870 | } | ||
871 | |||
872 | |||
873 | static unsigned int zc0301_poll(struct file *filp, poll_table *wait) | ||
874 | { | ||
875 | struct zc0301_device *cam = video_drvdata(filp); | ||
876 | struct zc0301_frame_t* f; | ||
877 | unsigned long lock_flags; | ||
878 | unsigned int mask = 0; | ||
879 | |||
880 | if (mutex_lock_interruptible(&cam->fileop_mutex)) | ||
881 | return POLLERR; | ||
882 | |||
883 | if (cam->state & DEV_DISCONNECTED) { | ||
884 | DBG(1, "Device not present"); | ||
885 | goto error; | ||
886 | } | ||
887 | |||
888 | if (cam->state & DEV_MISCONFIGURED) { | ||
889 | DBG(1, "The camera is misconfigured. Close and open it " | ||
890 | "again."); | ||
891 | goto error; | ||
892 | } | ||
893 | |||
894 | if (cam->io == IO_NONE) { | ||
895 | if (!zc0301_request_buffers(cam, cam->nreadbuffers, IO_READ)) { | ||
896 | DBG(1, "poll() failed, not enough memory"); | ||
897 | goto error; | ||
898 | } | ||
899 | cam->io = IO_READ; | ||
900 | cam->stream = STREAM_ON; | ||
901 | } | ||
902 | |||
903 | if (cam->io == IO_READ) { | ||
904 | spin_lock_irqsave(&cam->queue_lock, lock_flags); | ||
905 | list_for_each_entry(f, &cam->outqueue, frame) | ||
906 | f->state = F_UNUSED; | ||
907 | INIT_LIST_HEAD(&cam->outqueue); | ||
908 | spin_unlock_irqrestore(&cam->queue_lock, lock_flags); | ||
909 | zc0301_queue_unusedframes(cam); | ||
910 | } | ||
911 | |||
912 | poll_wait(filp, &cam->wait_frame, wait); | ||
913 | |||
914 | if (!list_empty(&cam->outqueue)) | ||
915 | mask |= POLLIN | POLLRDNORM; | ||
916 | |||
917 | mutex_unlock(&cam->fileop_mutex); | ||
918 | |||
919 | return mask; | ||
920 | |||
921 | error: | ||
922 | mutex_unlock(&cam->fileop_mutex); | ||
923 | return POLLERR; | ||
924 | } | ||
925 | |||
926 | |||
927 | static void zc0301_vm_open(struct vm_area_struct* vma) | ||
928 | { | ||
929 | struct zc0301_frame_t* f = vma->vm_private_data; | ||
930 | f->vma_use_count++; | ||
931 | } | ||
932 | |||
933 | |||
934 | static void zc0301_vm_close(struct vm_area_struct* vma) | ||
935 | { | ||
936 | /* NOTE: buffers are not freed here */ | ||
937 | struct zc0301_frame_t* f = vma->vm_private_data; | ||
938 | f->vma_use_count--; | ||
939 | } | ||
940 | |||
941 | |||
942 | static const struct vm_operations_struct zc0301_vm_ops = { | ||
943 | .open = zc0301_vm_open, | ||
944 | .close = zc0301_vm_close, | ||
945 | }; | ||
946 | |||
947 | |||
948 | static int zc0301_mmap(struct file* filp, struct vm_area_struct *vma) | ||
949 | { | ||
950 | struct zc0301_device *cam = video_drvdata(filp); | ||
951 | unsigned long size = vma->vm_end - vma->vm_start, | ||
952 | start = vma->vm_start; | ||
953 | void *pos; | ||
954 | u32 i; | ||
955 | |||
956 | if (mutex_lock_interruptible(&cam->fileop_mutex)) | ||
957 | return -ERESTARTSYS; | ||
958 | |||
959 | if (cam->state & DEV_DISCONNECTED) { | ||
960 | DBG(1, "Device not present"); | ||
961 | mutex_unlock(&cam->fileop_mutex); | ||
962 | return -ENODEV; | ||
963 | } | ||
964 | |||
965 | if (cam->state & DEV_MISCONFIGURED) { | ||
966 | DBG(1, "The camera is misconfigured. Close and open it " | ||
967 | "again."); | ||
968 | mutex_unlock(&cam->fileop_mutex); | ||
969 | return -EIO; | ||
970 | } | ||
971 | |||
972 | if (!(vma->vm_flags & (VM_WRITE | VM_READ))) { | ||
973 | mutex_unlock(&cam->fileop_mutex); | ||
974 | return -EACCES; | ||
975 | } | ||
976 | |||
977 | if (cam->io != IO_MMAP || | ||
978 | size != PAGE_ALIGN(cam->frame[0].buf.length)) { | ||
979 | mutex_unlock(&cam->fileop_mutex); | ||
980 | return -EINVAL; | ||
981 | } | ||
982 | |||
983 | for (i = 0; i < cam->nbuffers; i++) { | ||
984 | if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff) | ||
985 | break; | ||
986 | } | ||
987 | if (i == cam->nbuffers) { | ||
988 | mutex_unlock(&cam->fileop_mutex); | ||
989 | return -EINVAL; | ||
990 | } | ||
991 | |||
992 | vma->vm_flags |= VM_IO; | ||
993 | vma->vm_flags |= VM_RESERVED; | ||
994 | |||
995 | pos = cam->frame[i].bufmem; | ||
996 | while (size > 0) { /* size is page-aligned */ | ||
997 | if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { | ||
998 | mutex_unlock(&cam->fileop_mutex); | ||
999 | return -EAGAIN; | ||
1000 | } | ||
1001 | start += PAGE_SIZE; | ||
1002 | pos += PAGE_SIZE; | ||
1003 | size -= PAGE_SIZE; | ||
1004 | } | ||
1005 | |||
1006 | vma->vm_ops = &zc0301_vm_ops; | ||
1007 | vma->vm_private_data = &cam->frame[i]; | ||
1008 | zc0301_vm_open(vma); | ||
1009 | |||
1010 | mutex_unlock(&cam->fileop_mutex); | ||
1011 | |||
1012 | return 0; | ||
1013 | } | ||
1014 | |||
1015 | /*****************************************************************************/ | ||
1016 | |||
1017 | static int | ||
1018 | zc0301_vidioc_querycap(struct zc0301_device* cam, void __user * arg) | ||
1019 | { | ||
1020 | struct v4l2_capability cap = { | ||
1021 | .driver = "zc0301", | ||
1022 | .version = ZC0301_MODULE_VERSION_CODE, | ||
1023 | .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | | ||
1024 | V4L2_CAP_STREAMING, | ||
1025 | }; | ||
1026 | |||
1027 | strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card)); | ||
1028 | if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0) | ||
1029 | strlcpy(cap.bus_info, dev_name(&cam->usbdev->dev), | ||
1030 | sizeof(cap.bus_info)); | ||
1031 | |||
1032 | if (copy_to_user(arg, &cap, sizeof(cap))) | ||
1033 | return -EFAULT; | ||
1034 | |||
1035 | return 0; | ||
1036 | } | ||
1037 | |||
1038 | |||
1039 | static int | ||
1040 | zc0301_vidioc_enuminput(struct zc0301_device* cam, void __user * arg) | ||
1041 | { | ||
1042 | struct v4l2_input i; | ||
1043 | |||
1044 | if (copy_from_user(&i, arg, sizeof(i))) | ||
1045 | return -EFAULT; | ||
1046 | |||
1047 | if (i.index) | ||
1048 | return -EINVAL; | ||
1049 | |||
1050 | memset(&i, 0, sizeof(i)); | ||
1051 | strcpy(i.name, "Camera"); | ||
1052 | i.type = V4L2_INPUT_TYPE_CAMERA; | ||
1053 | |||
1054 | if (copy_to_user(arg, &i, sizeof(i))) | ||
1055 | return -EFAULT; | ||
1056 | |||
1057 | return 0; | ||
1058 | } | ||
1059 | |||
1060 | |||
1061 | static int | ||
1062 | zc0301_vidioc_g_input(struct zc0301_device* cam, void __user * arg) | ||
1063 | { | ||
1064 | int index = 0; | ||
1065 | |||
1066 | if (copy_to_user(arg, &index, sizeof(index))) | ||
1067 | return -EFAULT; | ||
1068 | |||
1069 | return 0; | ||
1070 | } | ||
1071 | |||
1072 | |||
1073 | static int | ||
1074 | zc0301_vidioc_s_input(struct zc0301_device* cam, void __user * arg) | ||
1075 | { | ||
1076 | int index; | ||
1077 | |||
1078 | if (copy_from_user(&index, arg, sizeof(index))) | ||
1079 | return -EFAULT; | ||
1080 | |||
1081 | if (index != 0) | ||
1082 | return -EINVAL; | ||
1083 | |||
1084 | return 0; | ||
1085 | } | ||
1086 | |||
1087 | |||
1088 | static int | ||
1089 | zc0301_vidioc_query_ctrl(struct zc0301_device* cam, void __user * arg) | ||
1090 | { | ||
1091 | struct zc0301_sensor* s = &cam->sensor; | ||
1092 | struct v4l2_queryctrl qc; | ||
1093 | u8 i; | ||
1094 | |||
1095 | if (copy_from_user(&qc, arg, sizeof(qc))) | ||
1096 | return -EFAULT; | ||
1097 | |||
1098 | for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) | ||
1099 | if (qc.id && qc.id == s->qctrl[i].id) { | ||
1100 | memcpy(&qc, &(s->qctrl[i]), sizeof(qc)); | ||
1101 | if (copy_to_user(arg, &qc, sizeof(qc))) | ||
1102 | return -EFAULT; | ||
1103 | return 0; | ||
1104 | } | ||
1105 | |||
1106 | return -EINVAL; | ||
1107 | } | ||
1108 | |||
1109 | |||
1110 | static int | ||
1111 | zc0301_vidioc_g_ctrl(struct zc0301_device* cam, void __user * arg) | ||
1112 | { | ||
1113 | struct zc0301_sensor* s = &cam->sensor; | ||
1114 | struct v4l2_control ctrl; | ||
1115 | int err = 0; | ||
1116 | u8 i; | ||
1117 | |||
1118 | if (!s->get_ctrl && !s->set_ctrl) | ||
1119 | return -EINVAL; | ||
1120 | |||
1121 | if (copy_from_user(&ctrl, arg, sizeof(ctrl))) | ||
1122 | return -EFAULT; | ||
1123 | |||
1124 | if (!s->get_ctrl) { | ||
1125 | for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) | ||
1126 | if (ctrl.id == s->qctrl[i].id) { | ||
1127 | ctrl.value = s->_qctrl[i].default_value; | ||
1128 | goto exit; | ||
1129 | } | ||
1130 | return -EINVAL; | ||
1131 | } else | ||
1132 | err = s->get_ctrl(cam, &ctrl); | ||
1133 | |||
1134 | exit: | ||
1135 | if (copy_to_user(arg, &ctrl, sizeof(ctrl))) | ||
1136 | return -EFAULT; | ||
1137 | |||
1138 | return err; | ||
1139 | } | ||
1140 | |||
1141 | |||
1142 | static int | ||
1143 | zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg) | ||
1144 | { | ||
1145 | struct zc0301_sensor* s = &cam->sensor; | ||
1146 | struct v4l2_control ctrl; | ||
1147 | u8 i; | ||
1148 | int err = 0; | ||
1149 | |||
1150 | if (!s->set_ctrl) | ||
1151 | return -EINVAL; | ||
1152 | |||
1153 | if (copy_from_user(&ctrl, arg, sizeof(ctrl))) | ||
1154 | return -EFAULT; | ||
1155 | |||
1156 | for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) { | ||
1157 | if (ctrl.id == s->qctrl[i].id) { | ||
1158 | if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) | ||
1159 | return -EINVAL; | ||
1160 | if (ctrl.value < s->qctrl[i].minimum || | ||
1161 | ctrl.value > s->qctrl[i].maximum) | ||
1162 | return -ERANGE; | ||
1163 | ctrl.value -= ctrl.value % s->qctrl[i].step; | ||
1164 | break; | ||
1165 | } | ||
1166 | } | ||
1167 | if (i == ARRAY_SIZE(s->qctrl)) | ||
1168 | return -EINVAL; | ||
1169 | if ((err = s->set_ctrl(cam, &ctrl))) | ||
1170 | return err; | ||
1171 | |||
1172 | s->_qctrl[i].default_value = ctrl.value; | ||
1173 | |||
1174 | return 0; | ||
1175 | } | ||
1176 | |||
1177 | |||
1178 | static int | ||
1179 | zc0301_vidioc_cropcap(struct zc0301_device* cam, void __user * arg) | ||
1180 | { | ||
1181 | struct v4l2_cropcap* cc = &(cam->sensor.cropcap); | ||
1182 | |||
1183 | cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1184 | cc->pixelaspect.numerator = 1; | ||
1185 | cc->pixelaspect.denominator = 1; | ||
1186 | |||
1187 | if (copy_to_user(arg, cc, sizeof(*cc))) | ||
1188 | return -EFAULT; | ||
1189 | |||
1190 | return 0; | ||
1191 | } | ||
1192 | |||
1193 | |||
1194 | static int | ||
1195 | zc0301_vidioc_g_crop(struct zc0301_device* cam, void __user * arg) | ||
1196 | { | ||
1197 | struct zc0301_sensor* s = &cam->sensor; | ||
1198 | struct v4l2_crop crop = { | ||
1199 | .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
1200 | }; | ||
1201 | |||
1202 | memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect)); | ||
1203 | |||
1204 | if (copy_to_user(arg, &crop, sizeof(crop))) | ||
1205 | return -EFAULT; | ||
1206 | |||
1207 | return 0; | ||
1208 | } | ||
1209 | |||
1210 | |||
1211 | static int | ||
1212 | zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg) | ||
1213 | { | ||
1214 | struct zc0301_sensor* s = &cam->sensor; | ||
1215 | struct v4l2_crop crop; | ||
1216 | struct v4l2_rect* rect; | ||
1217 | struct v4l2_rect* bounds = &(s->cropcap.bounds); | ||
1218 | const enum zc0301_stream_state stream = cam->stream; | ||
1219 | const u32 nbuffers = cam->nbuffers; | ||
1220 | u32 i; | ||
1221 | int err = 0; | ||
1222 | |||
1223 | if (copy_from_user(&crop, arg, sizeof(crop))) | ||
1224 | return -EFAULT; | ||
1225 | |||
1226 | rect = &(crop.c); | ||
1227 | |||
1228 | if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1229 | return -EINVAL; | ||
1230 | |||
1231 | if (cam->module_param.force_munmap) | ||
1232 | for (i = 0; i < cam->nbuffers; i++) | ||
1233 | if (cam->frame[i].vma_use_count) { | ||
1234 | DBG(3, "VIDIOC_S_CROP failed. " | ||
1235 | "Unmap the buffers first."); | ||
1236 | return -EBUSY; | ||
1237 | } | ||
1238 | |||
1239 | if (!s->set_crop) { | ||
1240 | memcpy(rect, &(s->_rect), sizeof(*rect)); | ||
1241 | if (copy_to_user(arg, &crop, sizeof(crop))) | ||
1242 | return -EFAULT; | ||
1243 | return 0; | ||
1244 | } | ||
1245 | |||
1246 | rect->left &= ~7L; | ||
1247 | rect->top &= ~7L; | ||
1248 | if (rect->width < 8) | ||
1249 | rect->width = 8; | ||
1250 | if (rect->height < 8) | ||
1251 | rect->height = 8; | ||
1252 | if (rect->width > bounds->width) | ||
1253 | rect->width = bounds->width; | ||
1254 | if (rect->height > bounds->height) | ||
1255 | rect->height = bounds->height; | ||
1256 | if (rect->left < bounds->left) | ||
1257 | rect->left = bounds->left; | ||
1258 | if (rect->top < bounds->top) | ||
1259 | rect->top = bounds->top; | ||
1260 | if (rect->left + rect->width > bounds->left + bounds->width) | ||
1261 | rect->left = bounds->left+bounds->width - rect->width; | ||
1262 | if (rect->top + rect->height > bounds->top + bounds->height) | ||
1263 | rect->top = bounds->top+bounds->height - rect->height; | ||
1264 | rect->width &= ~7L; | ||
1265 | rect->height &= ~7L; | ||
1266 | |||
1267 | if (cam->stream == STREAM_ON) | ||
1268 | if ((err = zc0301_stream_interrupt(cam))) | ||
1269 | return err; | ||
1270 | |||
1271 | if (copy_to_user(arg, &crop, sizeof(crop))) { | ||
1272 | cam->stream = stream; | ||
1273 | return -EFAULT; | ||
1274 | } | ||
1275 | |||
1276 | if (cam->module_param.force_munmap || cam->io == IO_READ) | ||
1277 | zc0301_release_buffers(cam); | ||
1278 | |||
1279 | if (s->set_crop) | ||
1280 | err += s->set_crop(cam, rect); | ||
1281 | |||
1282 | if (err) { /* atomic, no rollback in ioctl() */ | ||
1283 | cam->state |= DEV_MISCONFIGURED; | ||
1284 | DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " | ||
1285 | "use the camera, close and open %s again.", | ||
1286 | video_device_node_name(cam->v4ldev)); | ||
1287 | return -EIO; | ||
1288 | } | ||
1289 | |||
1290 | s->pix_format.width = rect->width; | ||
1291 | s->pix_format.height = rect->height; | ||
1292 | memcpy(&(s->_rect), rect, sizeof(*rect)); | ||
1293 | |||
1294 | if ((cam->module_param.force_munmap || cam->io == IO_READ) && | ||
1295 | nbuffers != zc0301_request_buffers(cam, nbuffers, cam->io)) { | ||
1296 | cam->state |= DEV_MISCONFIGURED; | ||
1297 | DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " | ||
1298 | "use the camera, close and open %s again.", | ||
1299 | video_device_node_name(cam->v4ldev)); | ||
1300 | return -ENOMEM; | ||
1301 | } | ||
1302 | |||
1303 | if (cam->io == IO_READ) | ||
1304 | zc0301_empty_framequeues(cam); | ||
1305 | else if (cam->module_param.force_munmap) | ||
1306 | zc0301_requeue_outqueue(cam); | ||
1307 | |||
1308 | cam->stream = stream; | ||
1309 | |||
1310 | return 0; | ||
1311 | } | ||
1312 | |||
1313 | |||
1314 | static int | ||
1315 | zc0301_vidioc_enum_framesizes(struct zc0301_device* cam, void __user * arg) | ||
1316 | { | ||
1317 | struct v4l2_frmsizeenum frmsize; | ||
1318 | |||
1319 | if (copy_from_user(&frmsize, arg, sizeof(frmsize))) | ||
1320 | return -EFAULT; | ||
1321 | |||
1322 | if (frmsize.index != 0 && frmsize.index != 1) | ||
1323 | return -EINVAL; | ||
1324 | |||
1325 | if (frmsize.pixel_format != V4L2_PIX_FMT_JPEG) | ||
1326 | return -EINVAL; | ||
1327 | |||
1328 | frmsize.type = V4L2_FRMSIZE_TYPE_DISCRETE; | ||
1329 | |||
1330 | if (frmsize.index == 1) { | ||
1331 | frmsize.discrete.width = cam->sensor.cropcap.defrect.width; | ||
1332 | frmsize.discrete.height = cam->sensor.cropcap.defrect.height; | ||
1333 | } | ||
1334 | memset(&frmsize.reserved, 0, sizeof(frmsize.reserved)); | ||
1335 | |||
1336 | if (copy_to_user(arg, &frmsize, sizeof(frmsize))) | ||
1337 | return -EFAULT; | ||
1338 | |||
1339 | return 0; | ||
1340 | } | ||
1341 | |||
1342 | |||
1343 | static int | ||
1344 | zc0301_vidioc_enum_fmt(struct zc0301_device* cam, void __user * arg) | ||
1345 | { | ||
1346 | struct v4l2_fmtdesc fmtd; | ||
1347 | |||
1348 | if (copy_from_user(&fmtd, arg, sizeof(fmtd))) | ||
1349 | return -EFAULT; | ||
1350 | |||
1351 | if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1352 | return -EINVAL; | ||
1353 | |||
1354 | if (fmtd.index == 0) { | ||
1355 | strcpy(fmtd.description, "JPEG"); | ||
1356 | fmtd.pixelformat = V4L2_PIX_FMT_JPEG; | ||
1357 | fmtd.flags = V4L2_FMT_FLAG_COMPRESSED; | ||
1358 | } else | ||
1359 | return -EINVAL; | ||
1360 | |||
1361 | fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1362 | memset(&fmtd.reserved, 0, sizeof(fmtd.reserved)); | ||
1363 | |||
1364 | if (copy_to_user(arg, &fmtd, sizeof(fmtd))) | ||
1365 | return -EFAULT; | ||
1366 | |||
1367 | return 0; | ||
1368 | } | ||
1369 | |||
1370 | |||
1371 | static int | ||
1372 | zc0301_vidioc_g_fmt(struct zc0301_device* cam, void __user * arg) | ||
1373 | { | ||
1374 | struct v4l2_format format; | ||
1375 | struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format); | ||
1376 | |||
1377 | if (copy_from_user(&format, arg, sizeof(format))) | ||
1378 | return -EFAULT; | ||
1379 | |||
1380 | if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1381 | return -EINVAL; | ||
1382 | |||
1383 | pfmt->bytesperline = 0; | ||
1384 | pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); | ||
1385 | pfmt->field = V4L2_FIELD_NONE; | ||
1386 | memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt)); | ||
1387 | |||
1388 | if (copy_to_user(arg, &format, sizeof(format))) | ||
1389 | return -EFAULT; | ||
1390 | |||
1391 | return 0; | ||
1392 | } | ||
1393 | |||
1394 | |||
1395 | static int | ||
1396 | zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd, | ||
1397 | void __user * arg) | ||
1398 | { | ||
1399 | struct zc0301_sensor* s = &cam->sensor; | ||
1400 | struct v4l2_format format; | ||
1401 | struct v4l2_pix_format* pix; | ||
1402 | struct v4l2_pix_format* pfmt = &(s->pix_format); | ||
1403 | struct v4l2_rect* bounds = &(s->cropcap.bounds); | ||
1404 | struct v4l2_rect rect; | ||
1405 | const enum zc0301_stream_state stream = cam->stream; | ||
1406 | const u32 nbuffers = cam->nbuffers; | ||
1407 | u32 i; | ||
1408 | int err = 0; | ||
1409 | |||
1410 | if (copy_from_user(&format, arg, sizeof(format))) | ||
1411 | return -EFAULT; | ||
1412 | |||
1413 | pix = &(format.fmt.pix); | ||
1414 | |||
1415 | if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1416 | return -EINVAL; | ||
1417 | |||
1418 | memcpy(&rect, &(s->_rect), sizeof(rect)); | ||
1419 | |||
1420 | if (!s->set_crop) { | ||
1421 | pix->width = rect.width; | ||
1422 | pix->height = rect.height; | ||
1423 | } else { | ||
1424 | rect.width = pix->width; | ||
1425 | rect.height = pix->height; | ||
1426 | } | ||
1427 | |||
1428 | if (rect.width < 8) | ||
1429 | rect.width = 8; | ||
1430 | if (rect.height < 8) | ||
1431 | rect.height = 8; | ||
1432 | if (rect.width > bounds->left + bounds->width - rect.left) | ||
1433 | rect.width = bounds->left + bounds->width - rect.left; | ||
1434 | if (rect.height > bounds->top + bounds->height - rect.top) | ||
1435 | rect.height = bounds->top + bounds->height - rect.top; | ||
1436 | rect.width &= ~7L; | ||
1437 | rect.height &= ~7L; | ||
1438 | |||
1439 | pix->width = rect.width; | ||
1440 | pix->height = rect.height; | ||
1441 | pix->pixelformat = pfmt->pixelformat; | ||
1442 | pix->priv = pfmt->priv; | ||
1443 | pix->colorspace = pfmt->colorspace; | ||
1444 | pix->bytesperline = 0; | ||
1445 | pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); | ||
1446 | pix->field = V4L2_FIELD_NONE; | ||
1447 | |||
1448 | if (cmd == VIDIOC_TRY_FMT) { | ||
1449 | if (copy_to_user(arg, &format, sizeof(format))) | ||
1450 | return -EFAULT; | ||
1451 | return 0; | ||
1452 | } | ||
1453 | |||
1454 | if (cam->module_param.force_munmap) | ||
1455 | for (i = 0; i < cam->nbuffers; i++) | ||
1456 | if (cam->frame[i].vma_use_count) { | ||
1457 | DBG(3, "VIDIOC_S_FMT failed. " | ||
1458 | "Unmap the buffers first."); | ||
1459 | return -EBUSY; | ||
1460 | } | ||
1461 | |||
1462 | if (cam->stream == STREAM_ON) | ||
1463 | if ((err = zc0301_stream_interrupt(cam))) | ||
1464 | return err; | ||
1465 | |||
1466 | if (copy_to_user(arg, &format, sizeof(format))) { | ||
1467 | cam->stream = stream; | ||
1468 | return -EFAULT; | ||
1469 | } | ||
1470 | |||
1471 | if (cam->module_param.force_munmap || cam->io == IO_READ) | ||
1472 | zc0301_release_buffers(cam); | ||
1473 | |||
1474 | if (s->set_crop) | ||
1475 | err += s->set_crop(cam, &rect); | ||
1476 | |||
1477 | if (err) { /* atomic, no rollback in ioctl() */ | ||
1478 | cam->state |= DEV_MISCONFIGURED; | ||
1479 | DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " | ||
1480 | "use the camera, close and open %s again.", | ||
1481 | video_device_node_name(cam->v4ldev)); | ||
1482 | return -EIO; | ||
1483 | } | ||
1484 | |||
1485 | memcpy(pfmt, pix, sizeof(*pix)); | ||
1486 | memcpy(&(s->_rect), &rect, sizeof(rect)); | ||
1487 | |||
1488 | if ((cam->module_param.force_munmap || cam->io == IO_READ) && | ||
1489 | nbuffers != zc0301_request_buffers(cam, nbuffers, cam->io)) { | ||
1490 | cam->state |= DEV_MISCONFIGURED; | ||
1491 | DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " | ||
1492 | "use the camera, close and open %s again.", | ||
1493 | video_device_node_name(cam->v4ldev)); | ||
1494 | return -ENOMEM; | ||
1495 | } | ||
1496 | |||
1497 | if (cam->io == IO_READ) | ||
1498 | zc0301_empty_framequeues(cam); | ||
1499 | else if (cam->module_param.force_munmap) | ||
1500 | zc0301_requeue_outqueue(cam); | ||
1501 | |||
1502 | cam->stream = stream; | ||
1503 | |||
1504 | return 0; | ||
1505 | } | ||
1506 | |||
1507 | |||
1508 | static int | ||
1509 | zc0301_vidioc_g_jpegcomp(struct zc0301_device* cam, void __user * arg) | ||
1510 | { | ||
1511 | if (copy_to_user(arg, &cam->compression, sizeof(cam->compression))) | ||
1512 | return -EFAULT; | ||
1513 | |||
1514 | return 0; | ||
1515 | } | ||
1516 | |||
1517 | |||
1518 | static int | ||
1519 | zc0301_vidioc_s_jpegcomp(struct zc0301_device* cam, void __user * arg) | ||
1520 | { | ||
1521 | struct v4l2_jpegcompression jc; | ||
1522 | const enum zc0301_stream_state stream = cam->stream; | ||
1523 | int err = 0; | ||
1524 | |||
1525 | if (copy_from_user(&jc, arg, sizeof(jc))) | ||
1526 | return -EFAULT; | ||
1527 | |||
1528 | if (jc.quality != 0) | ||
1529 | return -EINVAL; | ||
1530 | |||
1531 | if (cam->stream == STREAM_ON) | ||
1532 | if ((err = zc0301_stream_interrupt(cam))) | ||
1533 | return err; | ||
1534 | |||
1535 | err += zc0301_set_compression(cam, &jc); | ||
1536 | if (err) { /* atomic, no rollback in ioctl() */ | ||
1537 | cam->state |= DEV_MISCONFIGURED; | ||
1538 | DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " | ||
1539 | "problems. To use the camera, close and open %s again.", | ||
1540 | video_device_node_name(cam->v4ldev)); | ||
1541 | return -EIO; | ||
1542 | } | ||
1543 | |||
1544 | cam->compression.quality = jc.quality; | ||
1545 | |||
1546 | cam->stream = stream; | ||
1547 | |||
1548 | return 0; | ||
1549 | } | ||
1550 | |||
1551 | |||
1552 | static int | ||
1553 | zc0301_vidioc_reqbufs(struct zc0301_device* cam, void __user * arg) | ||
1554 | { | ||
1555 | struct v4l2_requestbuffers rb; | ||
1556 | u32 i; | ||
1557 | int err; | ||
1558 | |||
1559 | if (copy_from_user(&rb, arg, sizeof(rb))) | ||
1560 | return -EFAULT; | ||
1561 | |||
1562 | if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || | ||
1563 | rb.memory != V4L2_MEMORY_MMAP) | ||
1564 | return -EINVAL; | ||
1565 | |||
1566 | if (cam->io == IO_READ) { | ||
1567 | DBG(3, "Close and open the device again to choose the mmap " | ||
1568 | "I/O method"); | ||
1569 | return -EBUSY; | ||
1570 | } | ||
1571 | |||
1572 | for (i = 0; i < cam->nbuffers; i++) | ||
1573 | if (cam->frame[i].vma_use_count) { | ||
1574 | DBG(3, "VIDIOC_REQBUFS failed. " | ||
1575 | "Previous buffers are still mapped."); | ||
1576 | return -EBUSY; | ||
1577 | } | ||
1578 | |||
1579 | if (cam->stream == STREAM_ON) | ||
1580 | if ((err = zc0301_stream_interrupt(cam))) | ||
1581 | return err; | ||
1582 | |||
1583 | zc0301_empty_framequeues(cam); | ||
1584 | |||
1585 | zc0301_release_buffers(cam); | ||
1586 | if (rb.count) | ||
1587 | rb.count = zc0301_request_buffers(cam, rb.count, IO_MMAP); | ||
1588 | |||
1589 | if (copy_to_user(arg, &rb, sizeof(rb))) { | ||
1590 | zc0301_release_buffers(cam); | ||
1591 | cam->io = IO_NONE; | ||
1592 | return -EFAULT; | ||
1593 | } | ||
1594 | |||
1595 | cam->io = rb.count ? IO_MMAP : IO_NONE; | ||
1596 | |||
1597 | return 0; | ||
1598 | } | ||
1599 | |||
1600 | |||
1601 | static int | ||
1602 | zc0301_vidioc_querybuf(struct zc0301_device* cam, void __user * arg) | ||
1603 | { | ||
1604 | struct v4l2_buffer b; | ||
1605 | |||
1606 | if (copy_from_user(&b, arg, sizeof(b))) | ||
1607 | return -EFAULT; | ||
1608 | |||
1609 | if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || | ||
1610 | b.index >= cam->nbuffers || cam->io != IO_MMAP) | ||
1611 | return -EINVAL; | ||
1612 | |||
1613 | memcpy(&b, &cam->frame[b.index].buf, sizeof(b)); | ||
1614 | |||
1615 | if (cam->frame[b.index].vma_use_count) | ||
1616 | b.flags |= V4L2_BUF_FLAG_MAPPED; | ||
1617 | |||
1618 | if (cam->frame[b.index].state == F_DONE) | ||
1619 | b.flags |= V4L2_BUF_FLAG_DONE; | ||
1620 | else if (cam->frame[b.index].state != F_UNUSED) | ||
1621 | b.flags |= V4L2_BUF_FLAG_QUEUED; | ||
1622 | |||
1623 | if (copy_to_user(arg, &b, sizeof(b))) | ||
1624 | return -EFAULT; | ||
1625 | |||
1626 | return 0; | ||
1627 | } | ||
1628 | |||
1629 | |||
1630 | static int | ||
1631 | zc0301_vidioc_qbuf(struct zc0301_device* cam, void __user * arg) | ||
1632 | { | ||
1633 | struct v4l2_buffer b; | ||
1634 | unsigned long lock_flags; | ||
1635 | |||
1636 | if (copy_from_user(&b, arg, sizeof(b))) | ||
1637 | return -EFAULT; | ||
1638 | |||
1639 | if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || | ||
1640 | b.index >= cam->nbuffers || cam->io != IO_MMAP) | ||
1641 | return -EINVAL; | ||
1642 | |||
1643 | if (cam->frame[b.index].state != F_UNUSED) | ||
1644 | return -EINVAL; | ||
1645 | |||
1646 | cam->frame[b.index].state = F_QUEUED; | ||
1647 | |||
1648 | spin_lock_irqsave(&cam->queue_lock, lock_flags); | ||
1649 | list_add_tail(&cam->frame[b.index].frame, &cam->inqueue); | ||
1650 | spin_unlock_irqrestore(&cam->queue_lock, lock_flags); | ||
1651 | |||
1652 | PDBGG("Frame #%lu queued", (unsigned long)b.index); | ||
1653 | |||
1654 | return 0; | ||
1655 | } | ||
1656 | |||
1657 | |||
1658 | static int | ||
1659 | zc0301_vidioc_dqbuf(struct zc0301_device* cam, struct file* filp, | ||
1660 | void __user * arg) | ||
1661 | { | ||
1662 | struct v4l2_buffer b; | ||
1663 | struct zc0301_frame_t *f; | ||
1664 | unsigned long lock_flags; | ||
1665 | long timeout; | ||
1666 | |||
1667 | if (copy_from_user(&b, arg, sizeof(b))) | ||
1668 | return -EFAULT; | ||
1669 | |||
1670 | if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io!= IO_MMAP) | ||
1671 | return -EINVAL; | ||
1672 | |||
1673 | if (list_empty(&cam->outqueue)) { | ||
1674 | if (cam->stream == STREAM_OFF) | ||
1675 | return -EINVAL; | ||
1676 | if (filp->f_flags & O_NONBLOCK) | ||
1677 | return -EAGAIN; | ||
1678 | timeout = wait_event_interruptible_timeout | ||
1679 | ( cam->wait_frame, | ||
1680 | (!list_empty(&cam->outqueue)) || | ||
1681 | (cam->state & DEV_DISCONNECTED) || | ||
1682 | (cam->state & DEV_MISCONFIGURED), | ||
1683 | cam->module_param.frame_timeout * | ||
1684 | 1000 * msecs_to_jiffies(1) ); | ||
1685 | if (timeout < 0) | ||
1686 | return timeout; | ||
1687 | if (cam->state & DEV_DISCONNECTED) | ||
1688 | return -ENODEV; | ||
1689 | if (!timeout || (cam->state & DEV_MISCONFIGURED)) | ||
1690 | return -EIO; | ||
1691 | } | ||
1692 | |||
1693 | spin_lock_irqsave(&cam->queue_lock, lock_flags); | ||
1694 | f = list_entry(cam->outqueue.next, struct zc0301_frame_t, frame); | ||
1695 | list_del(cam->outqueue.next); | ||
1696 | spin_unlock_irqrestore(&cam->queue_lock, lock_flags); | ||
1697 | |||
1698 | f->state = F_UNUSED; | ||
1699 | |||
1700 | memcpy(&b, &f->buf, sizeof(b)); | ||
1701 | if (f->vma_use_count) | ||
1702 | b.flags |= V4L2_BUF_FLAG_MAPPED; | ||
1703 | |||
1704 | if (copy_to_user(arg, &b, sizeof(b))) | ||
1705 | return -EFAULT; | ||
1706 | |||
1707 | PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index); | ||
1708 | |||
1709 | return 0; | ||
1710 | } | ||
1711 | |||
1712 | |||
1713 | static int | ||
1714 | zc0301_vidioc_streamon(struct zc0301_device* cam, void __user * arg) | ||
1715 | { | ||
1716 | int type; | ||
1717 | |||
1718 | if (copy_from_user(&type, arg, sizeof(type))) | ||
1719 | return -EFAULT; | ||
1720 | |||
1721 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) | ||
1722 | return -EINVAL; | ||
1723 | |||
1724 | cam->stream = STREAM_ON; | ||
1725 | |||
1726 | DBG(3, "Stream on"); | ||
1727 | |||
1728 | return 0; | ||
1729 | } | ||
1730 | |||
1731 | |||
1732 | static int | ||
1733 | zc0301_vidioc_streamoff(struct zc0301_device* cam, void __user * arg) | ||
1734 | { | ||
1735 | int type, err; | ||
1736 | |||
1737 | if (copy_from_user(&type, arg, sizeof(type))) | ||
1738 | return -EFAULT; | ||
1739 | |||
1740 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) | ||
1741 | return -EINVAL; | ||
1742 | |||
1743 | if (cam->stream == STREAM_ON) | ||
1744 | if ((err = zc0301_stream_interrupt(cam))) | ||
1745 | return err; | ||
1746 | |||
1747 | zc0301_empty_framequeues(cam); | ||
1748 | |||
1749 | DBG(3, "Stream off"); | ||
1750 | |||
1751 | return 0; | ||
1752 | } | ||
1753 | |||
1754 | |||
1755 | static int | ||
1756 | zc0301_vidioc_g_parm(struct zc0301_device* cam, void __user * arg) | ||
1757 | { | ||
1758 | struct v4l2_streamparm sp; | ||
1759 | |||
1760 | if (copy_from_user(&sp, arg, sizeof(sp))) | ||
1761 | return -EFAULT; | ||
1762 | |||
1763 | if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1764 | return -EINVAL; | ||
1765 | |||
1766 | sp.parm.capture.extendedmode = 0; | ||
1767 | sp.parm.capture.readbuffers = cam->nreadbuffers; | ||
1768 | |||
1769 | if (copy_to_user(arg, &sp, sizeof(sp))) | ||
1770 | return -EFAULT; | ||
1771 | |||
1772 | return 0; | ||
1773 | } | ||
1774 | |||
1775 | |||
1776 | static int | ||
1777 | zc0301_vidioc_s_parm(struct zc0301_device* cam, void __user * arg) | ||
1778 | { | ||
1779 | struct v4l2_streamparm sp; | ||
1780 | |||
1781 | if (copy_from_user(&sp, arg, sizeof(sp))) | ||
1782 | return -EFAULT; | ||
1783 | |||
1784 | if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1785 | return -EINVAL; | ||
1786 | |||
1787 | sp.parm.capture.extendedmode = 0; | ||
1788 | |||
1789 | if (sp.parm.capture.readbuffers == 0) | ||
1790 | sp.parm.capture.readbuffers = cam->nreadbuffers; | ||
1791 | |||
1792 | if (sp.parm.capture.readbuffers > ZC0301_MAX_FRAMES) | ||
1793 | sp.parm.capture.readbuffers = ZC0301_MAX_FRAMES; | ||
1794 | |||
1795 | if (copy_to_user(arg, &sp, sizeof(sp))) | ||
1796 | return -EFAULT; | ||
1797 | |||
1798 | cam->nreadbuffers = sp.parm.capture.readbuffers; | ||
1799 | |||
1800 | return 0; | ||
1801 | } | ||
1802 | |||
1803 | |||
1804 | static long zc0301_ioctl_v4l2(struct file *filp, | ||
1805 | unsigned int cmd, void __user *arg) | ||
1806 | { | ||
1807 | struct zc0301_device *cam = video_drvdata(filp); | ||
1808 | |||
1809 | switch (cmd) { | ||
1810 | |||
1811 | case VIDIOC_QUERYCAP: | ||
1812 | return zc0301_vidioc_querycap(cam, arg); | ||
1813 | |||
1814 | case VIDIOC_ENUMINPUT: | ||
1815 | return zc0301_vidioc_enuminput(cam, arg); | ||
1816 | |||
1817 | case VIDIOC_G_INPUT: | ||
1818 | return zc0301_vidioc_g_input(cam, arg); | ||
1819 | |||
1820 | case VIDIOC_S_INPUT: | ||
1821 | return zc0301_vidioc_s_input(cam, arg); | ||
1822 | |||
1823 | case VIDIOC_QUERYCTRL: | ||
1824 | return zc0301_vidioc_query_ctrl(cam, arg); | ||
1825 | |||
1826 | case VIDIOC_G_CTRL: | ||
1827 | return zc0301_vidioc_g_ctrl(cam, arg); | ||
1828 | |||
1829 | case VIDIOC_S_CTRL: | ||
1830 | return zc0301_vidioc_s_ctrl(cam, arg); | ||
1831 | |||
1832 | case VIDIOC_CROPCAP: | ||
1833 | return zc0301_vidioc_cropcap(cam, arg); | ||
1834 | |||
1835 | case VIDIOC_G_CROP: | ||
1836 | return zc0301_vidioc_g_crop(cam, arg); | ||
1837 | |||
1838 | case VIDIOC_S_CROP: | ||
1839 | return zc0301_vidioc_s_crop(cam, arg); | ||
1840 | |||
1841 | case VIDIOC_ENUM_FMT: | ||
1842 | return zc0301_vidioc_enum_fmt(cam, arg); | ||
1843 | |||
1844 | case VIDIOC_G_FMT: | ||
1845 | return zc0301_vidioc_g_fmt(cam, arg); | ||
1846 | |||
1847 | case VIDIOC_TRY_FMT: | ||
1848 | case VIDIOC_S_FMT: | ||
1849 | return zc0301_vidioc_try_s_fmt(cam, cmd, arg); | ||
1850 | |||
1851 | case VIDIOC_ENUM_FRAMESIZES: | ||
1852 | return zc0301_vidioc_enum_framesizes(cam, arg); | ||
1853 | |||
1854 | case VIDIOC_G_JPEGCOMP: | ||
1855 | return zc0301_vidioc_g_jpegcomp(cam, arg); | ||
1856 | |||
1857 | case VIDIOC_S_JPEGCOMP: | ||
1858 | return zc0301_vidioc_s_jpegcomp(cam, arg); | ||
1859 | |||
1860 | case VIDIOC_REQBUFS: | ||
1861 | return zc0301_vidioc_reqbufs(cam, arg); | ||
1862 | |||
1863 | case VIDIOC_QUERYBUF: | ||
1864 | return zc0301_vidioc_querybuf(cam, arg); | ||
1865 | |||
1866 | case VIDIOC_QBUF: | ||
1867 | return zc0301_vidioc_qbuf(cam, arg); | ||
1868 | |||
1869 | case VIDIOC_DQBUF: | ||
1870 | return zc0301_vidioc_dqbuf(cam, filp, arg); | ||
1871 | |||
1872 | case VIDIOC_STREAMON: | ||
1873 | return zc0301_vidioc_streamon(cam, arg); | ||
1874 | |||
1875 | case VIDIOC_STREAMOFF: | ||
1876 | return zc0301_vidioc_streamoff(cam, arg); | ||
1877 | |||
1878 | case VIDIOC_G_PARM: | ||
1879 | return zc0301_vidioc_g_parm(cam, arg); | ||
1880 | |||
1881 | case VIDIOC_S_PARM: | ||
1882 | return zc0301_vidioc_s_parm(cam, arg); | ||
1883 | |||
1884 | case VIDIOC_G_STD: | ||
1885 | case VIDIOC_S_STD: | ||
1886 | case VIDIOC_QUERYSTD: | ||
1887 | case VIDIOC_ENUMSTD: | ||
1888 | case VIDIOC_QUERYMENU: | ||
1889 | case VIDIOC_ENUM_FRAMEINTERVALS: | ||
1890 | return -EINVAL; | ||
1891 | |||
1892 | default: | ||
1893 | return -EINVAL; | ||
1894 | |||
1895 | } | ||
1896 | } | ||
1897 | |||
1898 | |||
1899 | static long zc0301_ioctl(struct file *filp, | ||
1900 | unsigned int cmd, unsigned long arg) | ||
1901 | { | ||
1902 | struct zc0301_device *cam = video_drvdata(filp); | ||
1903 | int err = 0; | ||
1904 | |||
1905 | if (mutex_lock_interruptible(&cam->fileop_mutex)) | ||
1906 | return -ERESTARTSYS; | ||
1907 | |||
1908 | if (cam->state & DEV_DISCONNECTED) { | ||
1909 | DBG(1, "Device not present"); | ||
1910 | mutex_unlock(&cam->fileop_mutex); | ||
1911 | return -ENODEV; | ||
1912 | } | ||
1913 | |||
1914 | if (cam->state & DEV_MISCONFIGURED) { | ||
1915 | DBG(1, "The camera is misconfigured. Close and open it " | ||
1916 | "again."); | ||
1917 | mutex_unlock(&cam->fileop_mutex); | ||
1918 | return -EIO; | ||
1919 | } | ||
1920 | |||
1921 | V4LDBG(3, "zc0301", cmd); | ||
1922 | |||
1923 | err = zc0301_ioctl_v4l2(filp, cmd, (void __user *)arg); | ||
1924 | |||
1925 | mutex_unlock(&cam->fileop_mutex); | ||
1926 | |||
1927 | return err; | ||
1928 | } | ||
1929 | |||
1930 | |||
1931 | static const struct v4l2_file_operations zc0301_fops = { | ||
1932 | .owner = THIS_MODULE, | ||
1933 | .open = zc0301_open, | ||
1934 | .release = zc0301_release, | ||
1935 | .ioctl = zc0301_ioctl, | ||
1936 | .read = zc0301_read, | ||
1937 | .poll = zc0301_poll, | ||
1938 | .mmap = zc0301_mmap, | ||
1939 | }; | ||
1940 | |||
1941 | /*****************************************************************************/ | ||
1942 | |||
1943 | static int | ||
1944 | zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | ||
1945 | { | ||
1946 | struct usb_device *udev = interface_to_usbdev(intf); | ||
1947 | struct zc0301_device* cam; | ||
1948 | static unsigned int dev_nr; | ||
1949 | unsigned int i; | ||
1950 | int err = 0; | ||
1951 | |||
1952 | if (!(cam = kzalloc(sizeof(struct zc0301_device), GFP_KERNEL))) | ||
1953 | return -ENOMEM; | ||
1954 | |||
1955 | cam->usbdev = udev; | ||
1956 | |||
1957 | if (!(cam->control_buffer = kzalloc(4, GFP_KERNEL))) { | ||
1958 | DBG(1, "kmalloc() failed"); | ||
1959 | err = -ENOMEM; | ||
1960 | goto fail; | ||
1961 | } | ||
1962 | |||
1963 | if (!(cam->v4ldev = video_device_alloc())) { | ||
1964 | DBG(1, "video_device_alloc() failed"); | ||
1965 | err = -ENOMEM; | ||
1966 | goto fail; | ||
1967 | } | ||
1968 | |||
1969 | DBG(2, "ZC0301[P] Image Processor and Control Chip detected " | ||
1970 | "(vid/pid 0x%04X:0x%04X)",id->idVendor, id->idProduct); | ||
1971 | |||
1972 | for (i = 0; zc0301_sensor_table[i]; i++) { | ||
1973 | err = zc0301_sensor_table[i](cam); | ||
1974 | if (!err) | ||
1975 | break; | ||
1976 | } | ||
1977 | |||
1978 | if (!err) | ||
1979 | DBG(2, "%s image sensor detected", cam->sensor.name); | ||
1980 | else { | ||
1981 | DBG(1, "No supported image sensor detected"); | ||
1982 | err = -ENODEV; | ||
1983 | goto fail; | ||
1984 | } | ||
1985 | |||
1986 | if (zc0301_init(cam)) { | ||
1987 | DBG(1, "Initialization failed. I will retry on open()."); | ||
1988 | cam->state |= DEV_MISCONFIGURED; | ||
1989 | } | ||
1990 | |||
1991 | strcpy(cam->v4ldev->name, "ZC0301[P] PC Camera"); | ||
1992 | cam->v4ldev->fops = &zc0301_fops; | ||
1993 | cam->v4ldev->release = video_device_release; | ||
1994 | cam->v4ldev->parent = &udev->dev; | ||
1995 | video_set_drvdata(cam->v4ldev, cam); | ||
1996 | |||
1997 | init_completion(&cam->probe); | ||
1998 | |||
1999 | err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, | ||
2000 | video_nr[dev_nr]); | ||
2001 | if (err) { | ||
2002 | DBG(1, "V4L2 device registration failed"); | ||
2003 | if (err == -ENFILE && video_nr[dev_nr] == -1) | ||
2004 | DBG(1, "Free /dev/videoX node not found"); | ||
2005 | video_nr[dev_nr] = -1; | ||
2006 | dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0; | ||
2007 | complete_all(&cam->probe); | ||
2008 | goto fail; | ||
2009 | } | ||
2010 | |||
2011 | DBG(2, "V4L2 device registered as %s", | ||
2012 | video_device_node_name(cam->v4ldev)); | ||
2013 | |||
2014 | cam->module_param.force_munmap = force_munmap[dev_nr]; | ||
2015 | cam->module_param.frame_timeout = frame_timeout[dev_nr]; | ||
2016 | |||
2017 | dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0; | ||
2018 | |||
2019 | usb_set_intfdata(intf, cam); | ||
2020 | kref_init(&cam->kref); | ||
2021 | usb_get_dev(cam->usbdev); | ||
2022 | |||
2023 | complete_all(&cam->probe); | ||
2024 | |||
2025 | return 0; | ||
2026 | |||
2027 | fail: | ||
2028 | if (cam) { | ||
2029 | kfree(cam->control_buffer); | ||
2030 | if (cam->v4ldev) | ||
2031 | video_device_release(cam->v4ldev); | ||
2032 | kfree(cam); | ||
2033 | } | ||
2034 | return err; | ||
2035 | } | ||
2036 | |||
2037 | |||
2038 | static void zc0301_usb_disconnect(struct usb_interface* intf) | ||
2039 | { | ||
2040 | struct zc0301_device* cam; | ||
2041 | |||
2042 | down_write(&zc0301_dev_lock); | ||
2043 | |||
2044 | cam = usb_get_intfdata(intf); | ||
2045 | |||
2046 | DBG(2, "Disconnecting %s...", cam->v4ldev->name); | ||
2047 | |||
2048 | if (cam->users) { | ||
2049 | DBG(2, "Device %s is open! Deregistration and " | ||
2050 | "memory deallocation are deferred.", | ||
2051 | video_device_node_name(cam->v4ldev)); | ||
2052 | cam->state |= DEV_MISCONFIGURED; | ||
2053 | zc0301_stop_transfer(cam); | ||
2054 | cam->state |= DEV_DISCONNECTED; | ||
2055 | wake_up_interruptible(&cam->wait_frame); | ||
2056 | wake_up(&cam->wait_stream); | ||
2057 | } else | ||
2058 | cam->state |= DEV_DISCONNECTED; | ||
2059 | |||
2060 | wake_up_interruptible_all(&cam->wait_open); | ||
2061 | |||
2062 | kref_put(&cam->kref, zc0301_release_resources); | ||
2063 | |||
2064 | up_write(&zc0301_dev_lock); | ||
2065 | } | ||
2066 | |||
2067 | |||
2068 | static struct usb_driver zc0301_usb_driver = { | ||
2069 | .name = "zc0301", | ||
2070 | .id_table = zc0301_id_table, | ||
2071 | .probe = zc0301_usb_probe, | ||
2072 | .disconnect = zc0301_usb_disconnect, | ||
2073 | }; | ||
2074 | |||
2075 | /*****************************************************************************/ | ||
2076 | |||
2077 | static int __init zc0301_module_init(void) | ||
2078 | { | ||
2079 | int err = 0; | ||
2080 | |||
2081 | KDBG(2, ZC0301_MODULE_NAME " v" ZC0301_MODULE_VERSION); | ||
2082 | KDBG(3, ZC0301_MODULE_AUTHOR); | ||
2083 | |||
2084 | if ((err = usb_register(&zc0301_usb_driver))) | ||
2085 | KDBG(1, "usb_register() failed"); | ||
2086 | |||
2087 | return err; | ||
2088 | } | ||
2089 | |||
2090 | |||
2091 | static void __exit zc0301_module_exit(void) | ||
2092 | { | ||
2093 | usb_deregister(&zc0301_usb_driver); | ||
2094 | } | ||
2095 | |||
2096 | |||
2097 | module_init(zc0301_module_init); | ||
2098 | module_exit(zc0301_module_exit); | ||
diff --git a/drivers/media/video/zc0301/zc0301_pas202bcb.c b/drivers/media/video/zc0301/zc0301_pas202bcb.c deleted file mode 100644 index 24b0dfba357e..000000000000 --- a/drivers/media/video/zc0301/zc0301_pas202bcb.c +++ /dev/null | |||
@@ -1,362 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * Plug-in for PAS202BCB image sensor connected to the ZC0301 Image * | ||
3 | * Processor and Control Chip * | ||
4 | * * | ||
5 | * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * | ||
6 | * * | ||
7 | * Initialization values of the ZC0301[P] have been taken from the SPCA5XX * | ||
8 | * driver maintained by Michel Xhaard <mxhaard@magic.fr> * | ||
9 | * * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the Free Software * | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * | ||
23 | ***************************************************************************/ | ||
24 | |||
25 | /* | ||
26 | NOTE: Sensor controls are disabled for now, becouse changing them while | ||
27 | streaming sometimes results in out-of-sync video frames. We'll use | ||
28 | the default initialization, until we know how to stop and start video | ||
29 | in the chip. However, the image quality still looks good under various | ||
30 | light conditions. | ||
31 | */ | ||
32 | |||
33 | #include <linux/delay.h> | ||
34 | #include "zc0301_sensor.h" | ||
35 | |||
36 | |||
37 | static struct zc0301_sensor pas202bcb; | ||
38 | |||
39 | |||
40 | static int pas202bcb_init(struct zc0301_device* cam) | ||
41 | { | ||
42 | int err = 0; | ||
43 | |||
44 | err += zc0301_write_reg(cam, 0x0002, 0x00); | ||
45 | err += zc0301_write_reg(cam, 0x0003, 0x02); | ||
46 | err += zc0301_write_reg(cam, 0x0004, 0x80); | ||
47 | err += zc0301_write_reg(cam, 0x0005, 0x01); | ||
48 | err += zc0301_write_reg(cam, 0x0006, 0xE0); | ||
49 | err += zc0301_write_reg(cam, 0x0098, 0x00); | ||
50 | err += zc0301_write_reg(cam, 0x009A, 0x03); | ||
51 | err += zc0301_write_reg(cam, 0x011A, 0x00); | ||
52 | err += zc0301_write_reg(cam, 0x011C, 0x03); | ||
53 | err += zc0301_write_reg(cam, 0x009B, 0x01); | ||
54 | err += zc0301_write_reg(cam, 0x009C, 0xE6); | ||
55 | err += zc0301_write_reg(cam, 0x009D, 0x02); | ||
56 | err += zc0301_write_reg(cam, 0x009E, 0x86); | ||
57 | |||
58 | err += zc0301_i2c_write(cam, 0x02, 0x02); | ||
59 | err += zc0301_i2c_write(cam, 0x0A, 0x01); | ||
60 | err += zc0301_i2c_write(cam, 0x0B, 0x01); | ||
61 | err += zc0301_i2c_write(cam, 0x0D, 0x00); | ||
62 | err += zc0301_i2c_write(cam, 0x12, 0x05); | ||
63 | err += zc0301_i2c_write(cam, 0x13, 0x63); | ||
64 | err += zc0301_i2c_write(cam, 0x15, 0x70); | ||
65 | |||
66 | err += zc0301_write_reg(cam, 0x0101, 0xB7); | ||
67 | err += zc0301_write_reg(cam, 0x0100, 0x0D); | ||
68 | err += zc0301_write_reg(cam, 0x0189, 0x06); | ||
69 | err += zc0301_write_reg(cam, 0x01AD, 0x00); | ||
70 | err += zc0301_write_reg(cam, 0x01C5, 0x03); | ||
71 | err += zc0301_write_reg(cam, 0x01CB, 0x13); | ||
72 | err += zc0301_write_reg(cam, 0x0250, 0x08); | ||
73 | err += zc0301_write_reg(cam, 0x0301, 0x08); | ||
74 | err += zc0301_write_reg(cam, 0x018D, 0x70); | ||
75 | err += zc0301_write_reg(cam, 0x0008, 0x03); | ||
76 | err += zc0301_write_reg(cam, 0x01C6, 0x04); | ||
77 | err += zc0301_write_reg(cam, 0x01CB, 0x07); | ||
78 | err += zc0301_write_reg(cam, 0x0120, 0x11); | ||
79 | err += zc0301_write_reg(cam, 0x0121, 0x37); | ||
80 | err += zc0301_write_reg(cam, 0x0122, 0x58); | ||
81 | err += zc0301_write_reg(cam, 0x0123, 0x79); | ||
82 | err += zc0301_write_reg(cam, 0x0124, 0x91); | ||
83 | err += zc0301_write_reg(cam, 0x0125, 0xA6); | ||
84 | err += zc0301_write_reg(cam, 0x0126, 0xB8); | ||
85 | err += zc0301_write_reg(cam, 0x0127, 0xC7); | ||
86 | err += zc0301_write_reg(cam, 0x0128, 0xD3); | ||
87 | err += zc0301_write_reg(cam, 0x0129, 0xDE); | ||
88 | err += zc0301_write_reg(cam, 0x012A, 0xE6); | ||
89 | err += zc0301_write_reg(cam, 0x012B, 0xED); | ||
90 | err += zc0301_write_reg(cam, 0x012C, 0xF3); | ||
91 | err += zc0301_write_reg(cam, 0x012D, 0xF8); | ||
92 | err += zc0301_write_reg(cam, 0x012E, 0xFB); | ||
93 | err += zc0301_write_reg(cam, 0x012F, 0xFF); | ||
94 | err += zc0301_write_reg(cam, 0x0130, 0x26); | ||
95 | err += zc0301_write_reg(cam, 0x0131, 0x23); | ||
96 | err += zc0301_write_reg(cam, 0x0132, 0x20); | ||
97 | err += zc0301_write_reg(cam, 0x0133, 0x1C); | ||
98 | err += zc0301_write_reg(cam, 0x0134, 0x16); | ||
99 | err += zc0301_write_reg(cam, 0x0135, 0x13); | ||
100 | err += zc0301_write_reg(cam, 0x0136, 0x10); | ||
101 | err += zc0301_write_reg(cam, 0x0137, 0x0D); | ||
102 | err += zc0301_write_reg(cam, 0x0138, 0x0B); | ||
103 | err += zc0301_write_reg(cam, 0x0139, 0x09); | ||
104 | err += zc0301_write_reg(cam, 0x013A, 0x07); | ||
105 | err += zc0301_write_reg(cam, 0x013B, 0x06); | ||
106 | err += zc0301_write_reg(cam, 0x013C, 0x05); | ||
107 | err += zc0301_write_reg(cam, 0x013D, 0x04); | ||
108 | err += zc0301_write_reg(cam, 0x013E, 0x03); | ||
109 | err += zc0301_write_reg(cam, 0x013F, 0x02); | ||
110 | err += zc0301_write_reg(cam, 0x010A, 0x4C); | ||
111 | err += zc0301_write_reg(cam, 0x010B, 0xF5); | ||
112 | err += zc0301_write_reg(cam, 0x010C, 0xFF); | ||
113 | err += zc0301_write_reg(cam, 0x010D, 0xF9); | ||
114 | err += zc0301_write_reg(cam, 0x010E, 0x51); | ||
115 | err += zc0301_write_reg(cam, 0x010F, 0xF5); | ||
116 | err += zc0301_write_reg(cam, 0x0110, 0xFB); | ||
117 | err += zc0301_write_reg(cam, 0x0111, 0xED); | ||
118 | err += zc0301_write_reg(cam, 0x0112, 0x5F); | ||
119 | err += zc0301_write_reg(cam, 0x0180, 0x00); | ||
120 | err += zc0301_write_reg(cam, 0x0019, 0x00); | ||
121 | err += zc0301_write_reg(cam, 0x0087, 0x20); | ||
122 | err += zc0301_write_reg(cam, 0x0088, 0x21); | ||
123 | |||
124 | err += zc0301_i2c_write(cam, 0x20, 0x02); | ||
125 | err += zc0301_i2c_write(cam, 0x21, 0x1B); | ||
126 | err += zc0301_i2c_write(cam, 0x03, 0x44); | ||
127 | err += zc0301_i2c_write(cam, 0x0E, 0x01); | ||
128 | err += zc0301_i2c_write(cam, 0x0F, 0x00); | ||
129 | |||
130 | err += zc0301_write_reg(cam, 0x01A9, 0x14); | ||
131 | err += zc0301_write_reg(cam, 0x01AA, 0x24); | ||
132 | err += zc0301_write_reg(cam, 0x0190, 0x00); | ||
133 | err += zc0301_write_reg(cam, 0x0191, 0x02); | ||
134 | err += zc0301_write_reg(cam, 0x0192, 0x1B); | ||
135 | err += zc0301_write_reg(cam, 0x0195, 0x00); | ||
136 | err += zc0301_write_reg(cam, 0x0196, 0x00); | ||
137 | err += zc0301_write_reg(cam, 0x0197, 0x4D); | ||
138 | err += zc0301_write_reg(cam, 0x018C, 0x10); | ||
139 | err += zc0301_write_reg(cam, 0x018F, 0x20); | ||
140 | err += zc0301_write_reg(cam, 0x001D, 0x44); | ||
141 | err += zc0301_write_reg(cam, 0x001E, 0x6F); | ||
142 | err += zc0301_write_reg(cam, 0x001F, 0xAD); | ||
143 | err += zc0301_write_reg(cam, 0x0020, 0xEB); | ||
144 | err += zc0301_write_reg(cam, 0x0087, 0x0F); | ||
145 | err += zc0301_write_reg(cam, 0x0088, 0x0E); | ||
146 | err += zc0301_write_reg(cam, 0x0180, 0x40); | ||
147 | err += zc0301_write_reg(cam, 0x0192, 0x1B); | ||
148 | err += zc0301_write_reg(cam, 0x0191, 0x02); | ||
149 | err += zc0301_write_reg(cam, 0x0190, 0x00); | ||
150 | err += zc0301_write_reg(cam, 0x0116, 0x1D); | ||
151 | err += zc0301_write_reg(cam, 0x0117, 0x40); | ||
152 | err += zc0301_write_reg(cam, 0x0118, 0x99); | ||
153 | err += zc0301_write_reg(cam, 0x0180, 0x42); | ||
154 | err += zc0301_write_reg(cam, 0x0116, 0x1D); | ||
155 | err += zc0301_write_reg(cam, 0x0117, 0x40); | ||
156 | err += zc0301_write_reg(cam, 0x0118, 0x99); | ||
157 | err += zc0301_write_reg(cam, 0x0007, 0x00); | ||
158 | |||
159 | err += zc0301_i2c_write(cam, 0x11, 0x01); | ||
160 | |||
161 | msleep(100); | ||
162 | |||
163 | return err; | ||
164 | } | ||
165 | |||
166 | |||
167 | static int pas202bcb_get_ctrl(struct zc0301_device* cam, | ||
168 | struct v4l2_control* ctrl) | ||
169 | { | ||
170 | switch (ctrl->id) { | ||
171 | case V4L2_CID_EXPOSURE: | ||
172 | { | ||
173 | int r1 = zc0301_i2c_read(cam, 0x04, 1), | ||
174 | r2 = zc0301_i2c_read(cam, 0x05, 1); | ||
175 | if (r1 < 0 || r2 < 0) | ||
176 | return -EIO; | ||
177 | ctrl->value = (r1 << 6) | (r2 & 0x3f); | ||
178 | } | ||
179 | return 0; | ||
180 | case V4L2_CID_RED_BALANCE: | ||
181 | if ((ctrl->value = zc0301_i2c_read(cam, 0x09, 1)) < 0) | ||
182 | return -EIO; | ||
183 | ctrl->value &= 0x0f; | ||
184 | return 0; | ||
185 | case V4L2_CID_BLUE_BALANCE: | ||
186 | if ((ctrl->value = zc0301_i2c_read(cam, 0x07, 1)) < 0) | ||
187 | return -EIO; | ||
188 | ctrl->value &= 0x0f; | ||
189 | return 0; | ||
190 | case V4L2_CID_GAIN: | ||
191 | if ((ctrl->value = zc0301_i2c_read(cam, 0x10, 1)) < 0) | ||
192 | return -EIO; | ||
193 | ctrl->value &= 0x1f; | ||
194 | return 0; | ||
195 | case ZC0301_V4L2_CID_GREEN_BALANCE: | ||
196 | if ((ctrl->value = zc0301_i2c_read(cam, 0x08, 1)) < 0) | ||
197 | return -EIO; | ||
198 | ctrl->value &= 0x0f; | ||
199 | return 0; | ||
200 | case ZC0301_V4L2_CID_DAC_MAGNITUDE: | ||
201 | if ((ctrl->value = zc0301_i2c_read(cam, 0x0c, 1)) < 0) | ||
202 | return -EIO; | ||
203 | return 0; | ||
204 | default: | ||
205 | return -EINVAL; | ||
206 | } | ||
207 | } | ||
208 | |||
209 | |||
210 | static int pas202bcb_set_ctrl(struct zc0301_device* cam, | ||
211 | const struct v4l2_control* ctrl) | ||
212 | { | ||
213 | int err = 0; | ||
214 | |||
215 | switch (ctrl->id) { | ||
216 | case V4L2_CID_EXPOSURE: | ||
217 | err += zc0301_i2c_write(cam, 0x04, ctrl->value >> 6); | ||
218 | err += zc0301_i2c_write(cam, 0x05, ctrl->value & 0x3f); | ||
219 | break; | ||
220 | case V4L2_CID_RED_BALANCE: | ||
221 | err += zc0301_i2c_write(cam, 0x09, ctrl->value); | ||
222 | break; | ||
223 | case V4L2_CID_BLUE_BALANCE: | ||
224 | err += zc0301_i2c_write(cam, 0x07, ctrl->value); | ||
225 | break; | ||
226 | case V4L2_CID_GAIN: | ||
227 | err += zc0301_i2c_write(cam, 0x10, ctrl->value); | ||
228 | break; | ||
229 | case ZC0301_V4L2_CID_GREEN_BALANCE: | ||
230 | err += zc0301_i2c_write(cam, 0x08, ctrl->value); | ||
231 | break; | ||
232 | case ZC0301_V4L2_CID_DAC_MAGNITUDE: | ||
233 | err += zc0301_i2c_write(cam, 0x0c, ctrl->value); | ||
234 | break; | ||
235 | default: | ||
236 | return -EINVAL; | ||
237 | } | ||
238 | err += zc0301_i2c_write(cam, 0x11, 0x01); | ||
239 | |||
240 | return err ? -EIO : 0; | ||
241 | } | ||
242 | |||
243 | |||
244 | static struct zc0301_sensor pas202bcb = { | ||
245 | .name = "PAS202BCB", | ||
246 | .init = &pas202bcb_init, | ||
247 | .qctrl = { | ||
248 | { | ||
249 | .id = V4L2_CID_EXPOSURE, | ||
250 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
251 | .name = "exposure", | ||
252 | .minimum = 0x01e5, | ||
253 | .maximum = 0x3fff, | ||
254 | .step = 0x0001, | ||
255 | .default_value = 0x01e5, | ||
256 | .flags = V4L2_CTRL_FLAG_DISABLED, | ||
257 | }, | ||
258 | { | ||
259 | .id = V4L2_CID_GAIN, | ||
260 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
261 | .name = "global gain", | ||
262 | .minimum = 0x00, | ||
263 | .maximum = 0x1f, | ||
264 | .step = 0x01, | ||
265 | .default_value = 0x0c, | ||
266 | .flags = V4L2_CTRL_FLAG_DISABLED, | ||
267 | }, | ||
268 | { | ||
269 | .id = ZC0301_V4L2_CID_DAC_MAGNITUDE, | ||
270 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
271 | .name = "DAC magnitude", | ||
272 | .minimum = 0x00, | ||
273 | .maximum = 0xff, | ||
274 | .step = 0x01, | ||
275 | .default_value = 0x00, | ||
276 | .flags = V4L2_CTRL_FLAG_DISABLED, | ||
277 | }, | ||
278 | { | ||
279 | .id = V4L2_CID_RED_BALANCE, | ||
280 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
281 | .name = "red balance", | ||
282 | .minimum = 0x00, | ||
283 | .maximum = 0x0f, | ||
284 | .step = 0x01, | ||
285 | .default_value = 0x01, | ||
286 | .flags = V4L2_CTRL_FLAG_DISABLED, | ||
287 | }, | ||
288 | { | ||
289 | .id = V4L2_CID_BLUE_BALANCE, | ||
290 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
291 | .name = "blue balance", | ||
292 | .minimum = 0x00, | ||
293 | .maximum = 0x0f, | ||
294 | .step = 0x01, | ||
295 | .default_value = 0x05, | ||
296 | .flags = V4L2_CTRL_FLAG_DISABLED, | ||
297 | }, | ||
298 | { | ||
299 | .id = ZC0301_V4L2_CID_GREEN_BALANCE, | ||
300 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
301 | .name = "green balance", | ||
302 | .minimum = 0x00, | ||
303 | .maximum = 0x0f, | ||
304 | .step = 0x01, | ||
305 | .default_value = 0x00, | ||
306 | .flags = V4L2_CTRL_FLAG_DISABLED, | ||
307 | }, | ||
308 | }, | ||
309 | .get_ctrl = &pas202bcb_get_ctrl, | ||
310 | .set_ctrl = &pas202bcb_set_ctrl, | ||
311 | .cropcap = { | ||
312 | .bounds = { | ||
313 | .left = 0, | ||
314 | .top = 0, | ||
315 | .width = 640, | ||
316 | .height = 480, | ||
317 | }, | ||
318 | .defrect = { | ||
319 | .left = 0, | ||
320 | .top = 0, | ||
321 | .width = 640, | ||
322 | .height = 480, | ||
323 | }, | ||
324 | }, | ||
325 | .pix_format = { | ||
326 | .width = 640, | ||
327 | .height = 480, | ||
328 | .pixelformat = V4L2_PIX_FMT_JPEG, | ||
329 | .priv = 8, | ||
330 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
331 | }, | ||
332 | }; | ||
333 | |||
334 | |||
335 | int zc0301_probe_pas202bcb(struct zc0301_device* cam) | ||
336 | { | ||
337 | int r0 = 0, r1 = 0, err = 0; | ||
338 | unsigned int pid = 0; | ||
339 | |||
340 | err += zc0301_write_reg(cam, 0x0000, 0x01); | ||
341 | err += zc0301_write_reg(cam, 0x0010, 0x0e); | ||
342 | err += zc0301_write_reg(cam, 0x0001, 0x01); | ||
343 | err += zc0301_write_reg(cam, 0x0012, 0x03); | ||
344 | err += zc0301_write_reg(cam, 0x0012, 0x01); | ||
345 | err += zc0301_write_reg(cam, 0x008d, 0x08); | ||
346 | |||
347 | msleep(10); | ||
348 | |||
349 | r0 = zc0301_i2c_read(cam, 0x00, 1); | ||
350 | r1 = zc0301_i2c_read(cam, 0x01, 1); | ||
351 | |||
352 | if (r0 < 0 || r1 < 0 || err) | ||
353 | return -EIO; | ||
354 | |||
355 | pid = (r0 << 4) | ((r1 & 0xf0) >> 4); | ||
356 | if (pid != 0x017) | ||
357 | return -ENODEV; | ||
358 | |||
359 | zc0301_attach_sensor(cam, &pas202bcb); | ||
360 | |||
361 | return 0; | ||
362 | } | ||
diff --git a/drivers/media/video/zc0301/zc0301_pb0330.c b/drivers/media/video/zc0301/zc0301_pb0330.c deleted file mode 100644 index 9519aba3612e..000000000000 --- a/drivers/media/video/zc0301/zc0301_pb0330.c +++ /dev/null | |||
@@ -1,188 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * Plug-in for PB-0330 image sensor connected to the ZC0301P Image * | ||
3 | * Processor and Control Chip * | ||
4 | * * | ||
5 | * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * | ||
6 | * * | ||
7 | * Initialization values of the ZC0301[P] have been taken from the SPCA5XX * | ||
8 | * driver maintained by Michel Xhaard <mxhaard@magic.fr> * | ||
9 | * * | ||
10 | * This program is free software; you can redistribute it and/or modify * | ||
11 | * it under the terms of the GNU General Public License as published by * | ||
12 | * the Free Software Foundation; either version 2 of the License, or * | ||
13 | * (at your option) any later version. * | ||
14 | * * | ||
15 | * This program is distributed in the hope that it will be useful, * | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
18 | * GNU General Public License for more details. * | ||
19 | * * | ||
20 | * You should have received a copy of the GNU General Public License * | ||
21 | * along with this program; if not, write to the Free Software * | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * | ||
23 | ***************************************************************************/ | ||
24 | |||
25 | #include <linux/delay.h> | ||
26 | #include "zc0301_sensor.h" | ||
27 | |||
28 | |||
29 | static struct zc0301_sensor pb0330; | ||
30 | |||
31 | |||
32 | static int pb0330_init(struct zc0301_device* cam) | ||
33 | { | ||
34 | int err = 0; | ||
35 | |||
36 | err += zc0301_write_reg(cam, 0x0000, 0x01); | ||
37 | err += zc0301_write_reg(cam, 0x0008, 0x03); | ||
38 | err += zc0301_write_reg(cam, 0x0010, 0x0A); | ||
39 | err += zc0301_write_reg(cam, 0x0002, 0x00); | ||
40 | err += zc0301_write_reg(cam, 0x0003, 0x02); | ||
41 | err += zc0301_write_reg(cam, 0x0004, 0x80); | ||
42 | err += zc0301_write_reg(cam, 0x0005, 0x01); | ||
43 | err += zc0301_write_reg(cam, 0x0006, 0xE0); | ||
44 | err += zc0301_write_reg(cam, 0x0001, 0x01); | ||
45 | err += zc0301_write_reg(cam, 0x0012, 0x05); | ||
46 | err += zc0301_write_reg(cam, 0x0012, 0x07); | ||
47 | err += zc0301_write_reg(cam, 0x0098, 0x00); | ||
48 | err += zc0301_write_reg(cam, 0x009A, 0x00); | ||
49 | err += zc0301_write_reg(cam, 0x011A, 0x00); | ||
50 | err += zc0301_write_reg(cam, 0x011C, 0x00); | ||
51 | err += zc0301_write_reg(cam, 0x0012, 0x05); | ||
52 | |||
53 | err += zc0301_i2c_write(cam, 0x01, 0x0006); | ||
54 | err += zc0301_i2c_write(cam, 0x02, 0x0011); | ||
55 | err += zc0301_i2c_write(cam, 0x03, 0x01E7); | ||
56 | err += zc0301_i2c_write(cam, 0x04, 0x0287); | ||
57 | err += zc0301_i2c_write(cam, 0x06, 0x0003); | ||
58 | err += zc0301_i2c_write(cam, 0x07, 0x3002); | ||
59 | err += zc0301_i2c_write(cam, 0x20, 0x1100); | ||
60 | err += zc0301_i2c_write(cam, 0x2F, 0xF7B0); | ||
61 | err += zc0301_i2c_write(cam, 0x30, 0x0005); | ||
62 | err += zc0301_i2c_write(cam, 0x31, 0x0000); | ||
63 | err += zc0301_i2c_write(cam, 0x34, 0x0100); | ||
64 | err += zc0301_i2c_write(cam, 0x35, 0x0060); | ||
65 | err += zc0301_i2c_write(cam, 0x3D, 0x068F); | ||
66 | err += zc0301_i2c_write(cam, 0x40, 0x01E0); | ||
67 | err += zc0301_i2c_write(cam, 0x58, 0x0078); | ||
68 | err += zc0301_i2c_write(cam, 0x62, 0x0411); | ||
69 | |||
70 | err += zc0301_write_reg(cam, 0x0087, 0x10); | ||
71 | err += zc0301_write_reg(cam, 0x0101, 0x37); | ||
72 | err += zc0301_write_reg(cam, 0x0012, 0x05); | ||
73 | err += zc0301_write_reg(cam, 0x0100, 0x0D); | ||
74 | err += zc0301_write_reg(cam, 0x0189, 0x06); | ||
75 | err += zc0301_write_reg(cam, 0x01AD, 0x00); | ||
76 | err += zc0301_write_reg(cam, 0x01C5, 0x03); | ||
77 | err += zc0301_write_reg(cam, 0x01CB, 0x13); | ||
78 | err += zc0301_write_reg(cam, 0x0250, 0x08); | ||
79 | err += zc0301_write_reg(cam, 0x0301, 0x08); | ||
80 | err += zc0301_write_reg(cam, 0x01A8, 0x60); | ||
81 | err += zc0301_write_reg(cam, 0x018D, 0x6C); | ||
82 | err += zc0301_write_reg(cam, 0x01AD, 0x09); | ||
83 | err += zc0301_write_reg(cam, 0x01AE, 0x15); | ||
84 | err += zc0301_write_reg(cam, 0x010A, 0x50); | ||
85 | err += zc0301_write_reg(cam, 0x010B, 0xF8); | ||
86 | err += zc0301_write_reg(cam, 0x010C, 0xF8); | ||
87 | err += zc0301_write_reg(cam, 0x010D, 0xF8); | ||
88 | err += zc0301_write_reg(cam, 0x010E, 0x50); | ||
89 | err += zc0301_write_reg(cam, 0x010F, 0xF8); | ||
90 | err += zc0301_write_reg(cam, 0x0110, 0xF8); | ||
91 | err += zc0301_write_reg(cam, 0x0111, 0xF8); | ||
92 | err += zc0301_write_reg(cam, 0x0112, 0x50); | ||
93 | err += zc0301_write_reg(cam, 0x0008, 0x03); | ||
94 | err += zc0301_write_reg(cam, 0x01C6, 0x08); | ||
95 | err += zc0301_write_reg(cam, 0x01CB, 0x0F); | ||
96 | err += zc0301_write_reg(cam, 0x010A, 0x50); | ||
97 | err += zc0301_write_reg(cam, 0x010B, 0xF8); | ||
98 | err += zc0301_write_reg(cam, 0x010C, 0xF8); | ||
99 | err += zc0301_write_reg(cam, 0x010D, 0xF8); | ||
100 | err += zc0301_write_reg(cam, 0x010E, 0x50); | ||
101 | err += zc0301_write_reg(cam, 0x010F, 0xF8); | ||
102 | err += zc0301_write_reg(cam, 0x0110, 0xF8); | ||
103 | err += zc0301_write_reg(cam, 0x0111, 0xF8); | ||
104 | err += zc0301_write_reg(cam, 0x0112, 0x50); | ||
105 | err += zc0301_write_reg(cam, 0x0180, 0x00); | ||
106 | err += zc0301_write_reg(cam, 0x0019, 0x00); | ||
107 | |||
108 | err += zc0301_i2c_write(cam, 0x05, 0x0066); | ||
109 | err += zc0301_i2c_write(cam, 0x09, 0x02B2); | ||
110 | err += zc0301_i2c_write(cam, 0x10, 0x0002); | ||
111 | |||
112 | err += zc0301_write_reg(cam, 0x011D, 0x60); | ||
113 | err += zc0301_write_reg(cam, 0x0190, 0x00); | ||
114 | err += zc0301_write_reg(cam, 0x0191, 0x07); | ||
115 | err += zc0301_write_reg(cam, 0x0192, 0x8C); | ||
116 | err += zc0301_write_reg(cam, 0x0195, 0x00); | ||
117 | err += zc0301_write_reg(cam, 0x0196, 0x00); | ||
118 | err += zc0301_write_reg(cam, 0x0197, 0x8A); | ||
119 | err += zc0301_write_reg(cam, 0x018C, 0x10); | ||
120 | err += zc0301_write_reg(cam, 0x018F, 0x20); | ||
121 | err += zc0301_write_reg(cam, 0x01A9, 0x14); | ||
122 | err += zc0301_write_reg(cam, 0x01AA, 0x24); | ||
123 | err += zc0301_write_reg(cam, 0x001D, 0xD7); | ||
124 | err += zc0301_write_reg(cam, 0x001E, 0xF0); | ||
125 | err += zc0301_write_reg(cam, 0x001F, 0xF8); | ||
126 | err += zc0301_write_reg(cam, 0x0020, 0xFF); | ||
127 | err += zc0301_write_reg(cam, 0x01AD, 0x09); | ||
128 | err += zc0301_write_reg(cam, 0x01AE, 0x15); | ||
129 | err += zc0301_write_reg(cam, 0x0180, 0x40); | ||
130 | err += zc0301_write_reg(cam, 0x0180, 0x42); | ||
131 | |||
132 | msleep(100); | ||
133 | |||
134 | return err; | ||
135 | } | ||
136 | |||
137 | |||
138 | static struct zc0301_sensor pb0330 = { | ||
139 | .name = "PB-0330", | ||
140 | .init = &pb0330_init, | ||
141 | .cropcap = { | ||
142 | .bounds = { | ||
143 | .left = 0, | ||
144 | .top = 0, | ||
145 | .width = 640, | ||
146 | .height = 480, | ||
147 | }, | ||
148 | .defrect = { | ||
149 | .left = 0, | ||
150 | .top = 0, | ||
151 | .width = 640, | ||
152 | .height = 480, | ||
153 | }, | ||
154 | }, | ||
155 | .pix_format = { | ||
156 | .width = 640, | ||
157 | .height = 480, | ||
158 | .pixelformat = V4L2_PIX_FMT_JPEG, | ||
159 | .priv = 8, | ||
160 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
161 | }, | ||
162 | }; | ||
163 | |||
164 | |||
165 | int zc0301_probe_pb0330(struct zc0301_device* cam) | ||
166 | { | ||
167 | int r0, err = 0; | ||
168 | |||
169 | err += zc0301_write_reg(cam, 0x0000, 0x01); | ||
170 | err += zc0301_write_reg(cam, 0x0010, 0x0a); | ||
171 | err += zc0301_write_reg(cam, 0x0001, 0x01); | ||
172 | err += zc0301_write_reg(cam, 0x0012, 0x03); | ||
173 | err += zc0301_write_reg(cam, 0x0012, 0x01); | ||
174 | |||
175 | msleep(10); | ||
176 | |||
177 | r0 = zc0301_i2c_read(cam, 0x00, 2); | ||
178 | |||
179 | if (r0 < 0 || err) | ||
180 | return -EIO; | ||
181 | |||
182 | if (r0 != 0x8243) | ||
183 | return -ENODEV; | ||
184 | |||
185 | zc0301_attach_sensor(cam, &pb0330); | ||
186 | |||
187 | return 0; | ||
188 | } | ||
diff --git a/drivers/media/video/zc0301/zc0301_sensor.h b/drivers/media/video/zc0301/zc0301_sensor.h deleted file mode 100644 index 0be783c203f7..000000000000 --- a/drivers/media/video/zc0301/zc0301_sensor.h +++ /dev/null | |||
@@ -1,107 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * API for image sensors connected to the ZC0301[P] Image Processor and * | ||
3 | * Control Chip * | ||
4 | * * | ||
5 | * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * | ||
6 | * * | ||
7 | * This program is free software; you can redistribute it and/or modify * | ||
8 | * it under the terms of the GNU General Public License as published by * | ||
9 | * the Free Software Foundation; either version 2 of the License, or * | ||
10 | * (at your option) any later version. * | ||
11 | * * | ||
12 | * This program is distributed in the hope that it will be useful, * | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
15 | * GNU General Public License for more details. * | ||
16 | * * | ||
17 | * You should have received a copy of the GNU General Public License * | ||
18 | * along with this program; if not, write to the Free Software * | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * | ||
20 | ***************************************************************************/ | ||
21 | |||
22 | #ifndef _ZC0301_SENSOR_H_ | ||
23 | #define _ZC0301_SENSOR_H_ | ||
24 | |||
25 | #include <linux/usb.h> | ||
26 | #include <linux/videodev2.h> | ||
27 | #include <linux/device.h> | ||
28 | #include <linux/stddef.h> | ||
29 | #include <linux/errno.h> | ||
30 | #include <asm/types.h> | ||
31 | |||
32 | struct zc0301_device; | ||
33 | struct zc0301_sensor; | ||
34 | |||
35 | /*****************************************************************************/ | ||
36 | |||
37 | extern int zc0301_probe_pas202bcb(struct zc0301_device* cam); | ||
38 | extern int zc0301_probe_pb0330(struct zc0301_device* cam); | ||
39 | |||
40 | #define ZC0301_SENSOR_TABLE \ | ||
41 | /* Weak detections must go at the end of the list */ \ | ||
42 | static int (*zc0301_sensor_table[])(struct zc0301_device*) = { \ | ||
43 | &zc0301_probe_pas202bcb, \ | ||
44 | &zc0301_probe_pb0330, \ | ||
45 | NULL, \ | ||
46 | }; | ||
47 | |||
48 | extern struct zc0301_device* | ||
49 | zc0301_match_id(struct zc0301_device* cam, const struct usb_device_id *id); | ||
50 | |||
51 | extern void | ||
52 | zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor); | ||
53 | |||
54 | #define ZC0301_USB_DEVICE(vend, prod, intclass) \ | ||
55 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ | ||
56 | USB_DEVICE_ID_MATCH_INT_CLASS, \ | ||
57 | .idVendor = (vend), \ | ||
58 | .idProduct = (prod), \ | ||
59 | .bInterfaceClass = (intclass) | ||
60 | |||
61 | #if !defined CONFIG_USB_GSPCA_ZC3XX && !defined CONFIG_USB_GSPCA_ZC3XX_MODULE | ||
62 | #define ZC0301_ID_TABLE \ | ||
63 | static const struct usb_device_id zc0301_id_table[] = { \ | ||
64 | { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */ \ | ||
65 | { ZC0301_USB_DEVICE(0x0ac8, 0x303b, 0xff), }, /* PB-0330 */ \ | ||
66 | { } \ | ||
67 | }; | ||
68 | #else | ||
69 | #define ZC0301_ID_TABLE \ | ||
70 | static const struct usb_device_id zc0301_id_table[] = { \ | ||
71 | { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */ \ | ||
72 | { } \ | ||
73 | }; | ||
74 | #endif | ||
75 | |||
76 | /*****************************************************************************/ | ||
77 | |||
78 | extern int zc0301_write_reg(struct zc0301_device*, u16 index, u16 value); | ||
79 | extern int zc0301_read_reg(struct zc0301_device*, u16 index); | ||
80 | extern int zc0301_i2c_write(struct zc0301_device*, u16 address, u16 value); | ||
81 | extern int zc0301_i2c_read(struct zc0301_device*, u16 address, u8 length); | ||
82 | |||
83 | /*****************************************************************************/ | ||
84 | |||
85 | #define ZC0301_MAX_CTRLS (V4L2_CID_LASTP1 - V4L2_CID_BASE + 10) | ||
86 | #define ZC0301_V4L2_CID_DAC_MAGNITUDE (V4L2_CID_PRIVATE_BASE + 0) | ||
87 | #define ZC0301_V4L2_CID_GREEN_BALANCE (V4L2_CID_PRIVATE_BASE + 1) | ||
88 | |||
89 | struct zc0301_sensor { | ||
90 | char name[32]; | ||
91 | |||
92 | struct v4l2_queryctrl qctrl[ZC0301_MAX_CTRLS]; | ||
93 | struct v4l2_cropcap cropcap; | ||
94 | struct v4l2_pix_format pix_format; | ||
95 | |||
96 | int (*init)(struct zc0301_device*); | ||
97 | int (*get_ctrl)(struct zc0301_device*, struct v4l2_control* ctrl); | ||
98 | int (*set_ctrl)(struct zc0301_device*, | ||
99 | const struct v4l2_control* ctrl); | ||
100 | int (*set_crop)(struct zc0301_device*, const struct v4l2_rect* rect); | ||
101 | |||
102 | /* Private */ | ||
103 | struct v4l2_queryctrl _qctrl[ZC0301_MAX_CTRLS]; | ||
104 | struct v4l2_rect _rect; | ||
105 | }; | ||
106 | |||
107 | #endif /* _ZC0301_SENSOR_H_ */ | ||
diff --git a/drivers/media/video/zoran/videocodec.c b/drivers/media/video/zoran/videocodec.c index cf24956f3204..c01071635290 100644 --- a/drivers/media/video/zoran/videocodec.c +++ b/drivers/media/video/zoran/videocodec.c | |||
@@ -107,15 +107,14 @@ videocodec_attach (struct videocodec_master *master) | |||
107 | if (!try_module_get(h->codec->owner)) | 107 | if (!try_module_get(h->codec->owner)) |
108 | return NULL; | 108 | return NULL; |
109 | 109 | ||
110 | codec = | 110 | codec = kmemdup(h->codec, sizeof(struct videocodec), |
111 | kmalloc(sizeof(struct videocodec), GFP_KERNEL); | 111 | GFP_KERNEL); |
112 | if (!codec) { | 112 | if (!codec) { |
113 | dprintk(1, | 113 | dprintk(1, |
114 | KERN_ERR | 114 | KERN_ERR |
115 | "videocodec_attach: no mem\n"); | 115 | "videocodec_attach: no mem\n"); |
116 | goto out_module_put; | 116 | goto out_module_put; |
117 | } | 117 | } |
118 | memcpy(codec, h->codec, sizeof(struct videocodec)); | ||
119 | 118 | ||
120 | snprintf(codec->name, sizeof(codec->name), | 119 | snprintf(codec->name, sizeof(codec->name), |
121 | "%s[%d]", codec->name, h->attached); | 120 | "%s[%d]", codec->name, h->attached); |