diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-09 22:50:49 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-09 22:50:49 -0500 |
commit | 3e7468313758913c5e4d372f35b271b96bad1298 (patch) | |
tree | eb612d252a9e2349a1173451cd779beebd18a33e /drivers/media/video | |
parent | 6825fbc4cb219f2c98bb7d157915d797cf5cb823 (diff) | |
parent | e97f4677961f68e29bd906022ebf60a6df7f530a (diff) |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (345 commits)
V4L/DVB (13542): ir-keytable: Allow dynamic table change
V4L/DVB (13541): atbm8830: replace 64-bit division and floating point usage
V4L/DVB (13540): ir-common: Cleanup get key evdev code
V4L/DVB (13539): ir-common: add __func__ for debug messages
V4L/DVB (13538): ir-common: Use a dynamic keycode table
V4L/DVB (13537): ir: Prepare the code for dynamic keycode table allocation
V4L/DVB (13536): em28xx: Use the full RC5 code on HVR-950 Remote Controller
V4L/DVB (13535): ir-common: Add a hauppauge new table with the complete RC5 code
V4L/DVB (13534): ir-common: Remove some unused fields/structs
V4L/DVB (13533): ir: use dynamic tables, instead of static ones
V4L/DVB (13532): ir-common: Add infrastructure to use a dynamic keycode table
V4L/DVB (13531): ir-common: rename the debug routine to allow exporting it
V4L/DVB (13458): go7007: subdev conversion
V4L/DVB (13457): s2250: subdev conversion
V4L/DVB (13456): s2250: Change module structure
V4L/DVB (13528): em28xx: add support for em2800 VC211A card
em28xx: don't reduce scale to half size for em2800
em28xx: don't load audio modules when AC97 is mis-detected
em28xx: em2800 chips support max width of 640
V4L/DVB (13523): dvb-bt8xx: fix compile warning
...
Fix up trivial conflicts due to spelling fixes from the trivial tree in
Documentation/video4linux/gspca.txt
drivers/media/video/cx18/cx18-mailbox.h
Diffstat (limited to 'drivers/media/video')
164 files changed, 15481 insertions, 4544 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index e6186b338a12..9dc74c93bf24 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -600,7 +600,7 @@ source "drivers/media/video/bt8xx/Kconfig" | |||
600 | 600 | ||
601 | config VIDEO_PMS | 601 | config VIDEO_PMS |
602 | tristate "Mediavision Pro Movie Studio Video For Linux" | 602 | tristate "Mediavision Pro Movie Studio Video For Linux" |
603 | depends on ISA && VIDEO_V4L1 | 603 | depends on ISA && VIDEO_V4L2 |
604 | help | 604 | help |
605 | Say Y if you have such a thing. | 605 | Say Y if you have such a thing. |
606 | 606 | ||
@@ -847,6 +847,12 @@ config SOC_CAMERA_MT9V022 | |||
847 | help | 847 | help |
848 | This driver supports MT9V022 cameras from Micron | 848 | This driver supports MT9V022 cameras from Micron |
849 | 849 | ||
850 | config SOC_CAMERA_RJ54N1 | ||
851 | tristate "rj54n1cb0c support" | ||
852 | depends on SOC_CAMERA && I2C | ||
853 | help | ||
854 | This is a rj54n1cb0c video driver | ||
855 | |||
850 | config SOC_CAMERA_TW9910 | 856 | config SOC_CAMERA_TW9910 |
851 | tristate "tw9910 support" | 857 | tristate "tw9910 support" |
852 | depends on SOC_CAMERA && I2C | 858 | depends on SOC_CAMERA && I2C |
@@ -865,6 +871,12 @@ config SOC_CAMERA_OV772X | |||
865 | help | 871 | help |
866 | This is a ov772x camera driver | 872 | This is a ov772x camera driver |
867 | 873 | ||
874 | config SOC_CAMERA_OV9640 | ||
875 | tristate "ov9640 camera support" | ||
876 | depends on SOC_CAMERA && I2C | ||
877 | help | ||
878 | This is a ov9640 camera driver | ||
879 | |||
868 | config MX1_VIDEO | 880 | config MX1_VIDEO |
869 | bool | 881 | bool |
870 | 882 | ||
@@ -939,9 +951,14 @@ source "drivers/media/video/usbvideo/Kconfig" | |||
939 | source "drivers/media/video/et61x251/Kconfig" | 951 | source "drivers/media/video/et61x251/Kconfig" |
940 | 952 | ||
941 | config VIDEO_OVCAMCHIP | 953 | config VIDEO_OVCAMCHIP |
942 | tristate "OmniVision Camera Chip support" | 954 | tristate "OmniVision Camera Chip support (DEPRECATED)" |
943 | depends on I2C && VIDEO_V4L1 | 955 | depends on I2C && VIDEO_V4L1 |
944 | ---help--- | 956 | ---help--- |
957 | This driver is DEPRECATED please use the gspca ov519 module | ||
958 | instead. Note that for the ov511 / ov518 support of the gspca module | ||
959 | you need atleast version 0.6.0 of libv4l and for the w9968cf | ||
960 | atleast version 0.6.3 of libv4l. | ||
961 | |||
945 | Support for the OmniVision OV6xxx and OV7xxx series of camera chips. | 962 | Support for the OmniVision OV6xxx and OV7xxx series of camera chips. |
946 | This driver is intended to be used with the ov511 and w9968cf USB | 963 | This driver is intended to be used with the ov511 and w9968cf USB |
947 | camera drivers. | 964 | camera drivers. |
@@ -950,9 +967,13 @@ config VIDEO_OVCAMCHIP | |||
950 | module will be called ovcamchip. | 967 | module will be called ovcamchip. |
951 | 968 | ||
952 | config USB_W9968CF | 969 | config USB_W9968CF |
953 | tristate "USB W996[87]CF JPEG Dual Mode Camera support" | 970 | tristate "USB W996[87]CF JPEG Dual Mode Camera support (DEPRECATED)" |
954 | depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP | 971 | depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP |
955 | ---help--- | 972 | ---help--- |
973 | This driver is DEPRECATED please use the gspca ov519 module | ||
974 | instead. Note that for the w9968cf support of the gspca module | ||
975 | you need atleast version 0.6.3 of libv4l. | ||
976 | |||
956 | Say Y here if you want support for cameras based on OV681 or | 977 | Say Y here if you want support for cameras based on OV681 or |
957 | Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. | 978 | Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. |
958 | 979 | ||
@@ -995,9 +1016,13 @@ config USB_SE401 | |||
995 | source "drivers/media/video/sn9c102/Kconfig" | 1016 | source "drivers/media/video/sn9c102/Kconfig" |
996 | 1017 | ||
997 | config USB_STV680 | 1018 | config USB_STV680 |
998 | tristate "USB STV680 (Pencam) Camera support" | 1019 | tristate "USB STV680 (Pencam) Camera support (DEPRECATED)" |
999 | depends on VIDEO_V4L1 | 1020 | depends on VIDEO_V4L1 |
1000 | ---help--- | 1021 | ---help--- |
1022 | This driver is DEPRECATED please use the gspca stv0680 module | ||
1023 | instead. Note that for the gspca stv0680 module you need | ||
1024 | atleast version 0.6.3 of libv4l. | ||
1025 | |||
1001 | Say Y here if you want to connect this type of camera to your | 1026 | Say Y here if you want to connect this type of camera to your |
1002 | computer's USB port. This includes the Pencam line of cameras. | 1027 | computer's USB port. This includes the Pencam line of cameras. |
1003 | See <file:Documentation/video4linux/stv680.txt> for more information | 1028 | See <file:Documentation/video4linux/stv680.txt> for more information |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index e541932a789b..7a2dcc34111c 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -77,6 +77,8 @@ obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o | |||
77 | obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o | 77 | obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o |
78 | obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o | 78 | obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o |
79 | obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o | 79 | obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o |
80 | obj-$(CONFIG_SOC_CAMERA_OV9640) += ov9640.o | ||
81 | obj-$(CONFIG_SOC_CAMERA_RJ54N1) += rj54n1cb0c.o | ||
80 | obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o | 82 | obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o |
81 | 83 | ||
82 | # And now the v4l2 drivers: | 84 | # And now the v4l2 drivers: |
diff --git a/drivers/media/video/adv7180.c b/drivers/media/video/adv7180.c index 1b3cbd02a7fd..0826f0dabc17 100644 --- a/drivers/media/video/adv7180.c +++ b/drivers/media/video/adv7180.c | |||
@@ -27,17 +27,40 @@ | |||
27 | #include <linux/videodev2.h> | 27 | #include <linux/videodev2.h> |
28 | #include <media/v4l2-device.h> | 28 | #include <media/v4l2-device.h> |
29 | #include <media/v4l2-chip-ident.h> | 29 | #include <media/v4l2-chip-ident.h> |
30 | #include <linux/mutex.h> | ||
30 | 31 | ||
31 | #define DRIVER_NAME "adv7180" | 32 | #define DRIVER_NAME "adv7180" |
32 | 33 | ||
33 | #define ADV7180_INPUT_CONTROL_REG 0x00 | 34 | #define ADV7180_INPUT_CONTROL_REG 0x00 |
34 | #define ADV7180_INPUT_CONTROL_PAL_BG_NTSC_J_SECAM 0x00 | 35 | #define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM 0x00 |
35 | #define ADV7180_AUTODETECT_ENABLE_REG 0x07 | 36 | #define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM_PED 0x10 |
36 | #define ADV7180_AUTODETECT_DEFAULT 0x7f | 37 | #define ADV7180_INPUT_CONTROL_AD_PAL_N_NTSC_J_SECAM 0x20 |
37 | 38 | #define ADV7180_INPUT_CONTROL_AD_PAL_N_NTSC_M_SECAM 0x30 | |
38 | 39 | #define ADV7180_INPUT_CONTROL_NTSC_J 0x40 | |
39 | #define ADV7180_STATUS1_REG 0x10 | 40 | #define ADV7180_INPUT_CONTROL_NTSC_M 0x50 |
40 | #define ADV7180_STATUS1_AUTOD_MASK 0x70 | 41 | #define ADV7180_INPUT_CONTROL_PAL60 0x60 |
42 | #define ADV7180_INPUT_CONTROL_NTSC_443 0x70 | ||
43 | #define ADV7180_INPUT_CONTROL_PAL_BG 0x80 | ||
44 | #define ADV7180_INPUT_CONTROL_PAL_N 0x90 | ||
45 | #define ADV7180_INPUT_CONTROL_PAL_M 0xa0 | ||
46 | #define ADV7180_INPUT_CONTROL_PAL_M_PED 0xb0 | ||
47 | #define ADV7180_INPUT_CONTROL_PAL_COMB_N 0xc0 | ||
48 | #define ADV7180_INPUT_CONTROL_PAL_COMB_N_PED 0xd0 | ||
49 | #define ADV7180_INPUT_CONTROL_PAL_SECAM 0xe0 | ||
50 | #define ADV7180_INPUT_CONTROL_PAL_SECAM_PED 0xf0 | ||
51 | |||
52 | #define ADV7180_EXTENDED_OUTPUT_CONTROL_REG 0x04 | ||
53 | #define ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS 0xC5 | ||
54 | |||
55 | #define ADV7180_AUTODETECT_ENABLE_REG 0x07 | ||
56 | #define ADV7180_AUTODETECT_DEFAULT 0x7f | ||
57 | |||
58 | #define ADV7180_ADI_CTRL_REG 0x0e | ||
59 | #define ADV7180_ADI_CTRL_IRQ_SPACE 0x20 | ||
60 | |||
61 | #define ADV7180_STATUS1_REG 0x10 | ||
62 | #define ADV7180_STATUS1_IN_LOCK 0x01 | ||
63 | #define ADV7180_STATUS1_AUTOD_MASK 0x70 | ||
41 | #define ADV7180_STATUS1_AUTOD_NTSM_M_J 0x00 | 64 | #define ADV7180_STATUS1_AUTOD_NTSM_M_J 0x00 |
42 | #define ADV7180_STATUS1_AUTOD_NTSC_4_43 0x10 | 65 | #define ADV7180_STATUS1_AUTOD_NTSC_4_43 0x10 |
43 | #define ADV7180_STATUS1_AUTOD_PAL_M 0x20 | 66 | #define ADV7180_STATUS1_AUTOD_PAL_M 0x20 |
@@ -50,18 +73,37 @@ | |||
50 | #define ADV7180_IDENT_REG 0x11 | 73 | #define ADV7180_IDENT_REG 0x11 |
51 | #define ADV7180_ID_7180 0x18 | 74 | #define ADV7180_ID_7180 0x18 |
52 | 75 | ||
76 | #define ADV7180_ICONF1_ADI 0x40 | ||
77 | #define ADV7180_ICONF1_ACTIVE_LOW 0x01 | ||
78 | #define ADV7180_ICONF1_PSYNC_ONLY 0x10 | ||
79 | #define ADV7180_ICONF1_ACTIVE_TO_CLR 0xC0 | ||
80 | |||
81 | #define ADV7180_IRQ1_LOCK 0x01 | ||
82 | #define ADV7180_IRQ1_UNLOCK 0x02 | ||
83 | #define ADV7180_ISR1_ADI 0x42 | ||
84 | #define ADV7180_ICR1_ADI 0x43 | ||
85 | #define ADV7180_IMR1_ADI 0x44 | ||
86 | #define ADV7180_IMR2_ADI 0x48 | ||
87 | #define ADV7180_IRQ3_AD_CHANGE 0x08 | ||
88 | #define ADV7180_ISR3_ADI 0x4A | ||
89 | #define ADV7180_ICR3_ADI 0x4B | ||
90 | #define ADV7180_IMR3_ADI 0x4C | ||
91 | #define ADV7180_IMR4_ADI 0x50 | ||
53 | 92 | ||
54 | struct adv7180_state { | 93 | struct adv7180_state { |
55 | struct v4l2_subdev sd; | 94 | struct v4l2_subdev sd; |
95 | struct work_struct work; | ||
96 | struct mutex mutex; /* mutual excl. when accessing chip */ | ||
97 | int irq; | ||
98 | v4l2_std_id curr_norm; | ||
99 | bool autodetect; | ||
56 | }; | 100 | }; |
57 | 101 | ||
58 | static v4l2_std_id determine_norm(struct i2c_client *client) | 102 | static v4l2_std_id adv7180_std_to_v4l2(u8 status1) |
59 | { | 103 | { |
60 | u8 status1 = i2c_smbus_read_byte_data(client, ADV7180_STATUS1_REG); | ||
61 | |||
62 | switch (status1 & ADV7180_STATUS1_AUTOD_MASK) { | 104 | switch (status1 & ADV7180_STATUS1_AUTOD_MASK) { |
63 | case ADV7180_STATUS1_AUTOD_NTSM_M_J: | 105 | case ADV7180_STATUS1_AUTOD_NTSM_M_J: |
64 | return V4L2_STD_NTSC_M_JP; | 106 | return V4L2_STD_NTSC; |
65 | case ADV7180_STATUS1_AUTOD_NTSC_4_43: | 107 | case ADV7180_STATUS1_AUTOD_NTSC_4_43: |
66 | return V4L2_STD_NTSC_443; | 108 | return V4L2_STD_NTSC_443; |
67 | case ADV7180_STATUS1_AUTOD_PAL_M: | 109 | case ADV7180_STATUS1_AUTOD_PAL_M: |
@@ -81,6 +123,53 @@ static v4l2_std_id determine_norm(struct i2c_client *client) | |||
81 | } | 123 | } |
82 | } | 124 | } |
83 | 125 | ||
126 | static int v4l2_std_to_adv7180(v4l2_std_id std) | ||
127 | { | ||
128 | if (std == V4L2_STD_PAL_60) | ||
129 | return ADV7180_INPUT_CONTROL_PAL60; | ||
130 | if (std == V4L2_STD_NTSC_443) | ||
131 | return ADV7180_INPUT_CONTROL_NTSC_443; | ||
132 | if (std == V4L2_STD_PAL_N) | ||
133 | return ADV7180_INPUT_CONTROL_PAL_N; | ||
134 | if (std == V4L2_STD_PAL_M) | ||
135 | return ADV7180_INPUT_CONTROL_PAL_M; | ||
136 | if (std == V4L2_STD_PAL_Nc) | ||
137 | return ADV7180_INPUT_CONTROL_PAL_COMB_N; | ||
138 | |||
139 | if (std & V4L2_STD_PAL) | ||
140 | return ADV7180_INPUT_CONTROL_PAL_BG; | ||
141 | if (std & V4L2_STD_NTSC) | ||
142 | return ADV7180_INPUT_CONTROL_NTSC_M; | ||
143 | if (std & V4L2_STD_SECAM) | ||
144 | return ADV7180_INPUT_CONTROL_PAL_SECAM; | ||
145 | |||
146 | return -EINVAL; | ||
147 | } | ||
148 | |||
149 | static u32 adv7180_status_to_v4l2(u8 status1) | ||
150 | { | ||
151 | if (!(status1 & ADV7180_STATUS1_IN_LOCK)) | ||
152 | return V4L2_IN_ST_NO_SIGNAL; | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static int __adv7180_status(struct i2c_client *client, u32 *status, | ||
158 | v4l2_std_id *std) | ||
159 | { | ||
160 | int status1 = i2c_smbus_read_byte_data(client, ADV7180_STATUS1_REG); | ||
161 | |||
162 | if (status1 < 0) | ||
163 | return status1; | ||
164 | |||
165 | if (status) | ||
166 | *status = adv7180_status_to_v4l2(status1); | ||
167 | if (std) | ||
168 | *std = adv7180_std_to_v4l2(status1); | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
84 | static inline struct adv7180_state *to_state(struct v4l2_subdev *sd) | 173 | static inline struct adv7180_state *to_state(struct v4l2_subdev *sd) |
85 | { | 174 | { |
86 | return container_of(sd, struct adv7180_state, sd); | 175 | return container_of(sd, struct adv7180_state, sd); |
@@ -88,10 +177,31 @@ static inline struct adv7180_state *to_state(struct v4l2_subdev *sd) | |||
88 | 177 | ||
89 | static int adv7180_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) | 178 | static int adv7180_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) |
90 | { | 179 | { |
91 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 180 | struct adv7180_state *state = to_state(sd); |
181 | int err = mutex_lock_interruptible(&state->mutex); | ||
182 | if (err) | ||
183 | return err; | ||
184 | |||
185 | /* when we are interrupt driven we know the state */ | ||
186 | if (!state->autodetect || state->irq > 0) | ||
187 | *std = state->curr_norm; | ||
188 | else | ||
189 | err = __adv7180_status(v4l2_get_subdevdata(sd), NULL, std); | ||
190 | |||
191 | mutex_unlock(&state->mutex); | ||
192 | return err; | ||
193 | } | ||
92 | 194 | ||
93 | *std = determine_norm(client); | 195 | static int adv7180_g_input_status(struct v4l2_subdev *sd, u32 *status) |
94 | return 0; | 196 | { |
197 | struct adv7180_state *state = to_state(sd); | ||
198 | int ret = mutex_lock_interruptible(&state->mutex); | ||
199 | if (ret) | ||
200 | return ret; | ||
201 | |||
202 | ret = __adv7180_status(v4l2_get_subdevdata(sd), status, NULL); | ||
203 | mutex_unlock(&state->mutex); | ||
204 | return ret; | ||
95 | } | 205 | } |
96 | 206 | ||
97 | static int adv7180_g_chip_ident(struct v4l2_subdev *sd, | 207 | static int adv7180_g_chip_ident(struct v4l2_subdev *sd, |
@@ -102,12 +212,51 @@ static int adv7180_g_chip_ident(struct v4l2_subdev *sd, | |||
102 | return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7180, 0); | 212 | return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7180, 0); |
103 | } | 213 | } |
104 | 214 | ||
215 | static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std) | ||
216 | { | ||
217 | struct adv7180_state *state = to_state(sd); | ||
218 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
219 | int ret = mutex_lock_interruptible(&state->mutex); | ||
220 | if (ret) | ||
221 | return ret; | ||
222 | |||
223 | /* all standards -> autodetect */ | ||
224 | if (std == V4L2_STD_ALL) { | ||
225 | ret = i2c_smbus_write_byte_data(client, | ||
226 | ADV7180_INPUT_CONTROL_REG, | ||
227 | ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM); | ||
228 | if (ret < 0) | ||
229 | goto out; | ||
230 | |||
231 | __adv7180_status(client, NULL, &state->curr_norm); | ||
232 | state->autodetect = true; | ||
233 | } else { | ||
234 | ret = v4l2_std_to_adv7180(std); | ||
235 | if (ret < 0) | ||
236 | goto out; | ||
237 | |||
238 | ret = i2c_smbus_write_byte_data(client, | ||
239 | ADV7180_INPUT_CONTROL_REG, ret); | ||
240 | if (ret < 0) | ||
241 | goto out; | ||
242 | |||
243 | state->curr_norm = std; | ||
244 | state->autodetect = false; | ||
245 | } | ||
246 | ret = 0; | ||
247 | out: | ||
248 | mutex_unlock(&state->mutex); | ||
249 | return ret; | ||
250 | } | ||
251 | |||
105 | static const struct v4l2_subdev_video_ops adv7180_video_ops = { | 252 | static const struct v4l2_subdev_video_ops adv7180_video_ops = { |
106 | .querystd = adv7180_querystd, | 253 | .querystd = adv7180_querystd, |
254 | .g_input_status = adv7180_g_input_status, | ||
107 | }; | 255 | }; |
108 | 256 | ||
109 | static const struct v4l2_subdev_core_ops adv7180_core_ops = { | 257 | static const struct v4l2_subdev_core_ops adv7180_core_ops = { |
110 | .g_chip_ident = adv7180_g_chip_ident, | 258 | .g_chip_ident = adv7180_g_chip_ident, |
259 | .s_std = adv7180_s_std, | ||
111 | }; | 260 | }; |
112 | 261 | ||
113 | static const struct v4l2_subdev_ops adv7180_ops = { | 262 | static const struct v4l2_subdev_ops adv7180_ops = { |
@@ -115,12 +264,45 @@ static const struct v4l2_subdev_ops adv7180_ops = { | |||
115 | .video = &adv7180_video_ops, | 264 | .video = &adv7180_video_ops, |
116 | }; | 265 | }; |
117 | 266 | ||
267 | static void adv7180_work(struct work_struct *work) | ||
268 | { | ||
269 | struct adv7180_state *state = container_of(work, struct adv7180_state, | ||
270 | work); | ||
271 | struct i2c_client *client = v4l2_get_subdevdata(&state->sd); | ||
272 | u8 isr3; | ||
273 | |||
274 | mutex_lock(&state->mutex); | ||
275 | i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG, | ||
276 | ADV7180_ADI_CTRL_IRQ_SPACE); | ||
277 | isr3 = i2c_smbus_read_byte_data(client, ADV7180_ISR3_ADI); | ||
278 | /* clear */ | ||
279 | i2c_smbus_write_byte_data(client, ADV7180_ICR3_ADI, isr3); | ||
280 | i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG, 0); | ||
281 | |||
282 | if (isr3 & ADV7180_IRQ3_AD_CHANGE && state->autodetect) | ||
283 | __adv7180_status(client, NULL, &state->curr_norm); | ||
284 | mutex_unlock(&state->mutex); | ||
285 | |||
286 | enable_irq(state->irq); | ||
287 | } | ||
288 | |||
289 | static irqreturn_t adv7180_irq(int irq, void *devid) | ||
290 | { | ||
291 | struct adv7180_state *state = devid; | ||
292 | |||
293 | schedule_work(&state->work); | ||
294 | |||
295 | disable_irq_nosync(state->irq); | ||
296 | |||
297 | return IRQ_HANDLED; | ||
298 | } | ||
299 | |||
118 | /* | 300 | /* |
119 | * Generic i2c probe | 301 | * Generic i2c probe |
120 | * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' | 302 | * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' |
121 | */ | 303 | */ |
122 | 304 | ||
123 | static int adv7180_probe(struct i2c_client *client, | 305 | static __devinit int adv7180_probe(struct i2c_client *client, |
124 | const struct i2c_device_id *id) | 306 | const struct i2c_device_id *id) |
125 | { | 307 | { |
126 | struct adv7180_state *state; | 308 | struct adv7180_state *state; |
@@ -135,32 +317,111 @@ static int adv7180_probe(struct i2c_client *client, | |||
135 | client->addr << 1, client->adapter->name); | 317 | client->addr << 1, client->adapter->name); |
136 | 318 | ||
137 | state = kzalloc(sizeof(struct adv7180_state), GFP_KERNEL); | 319 | state = kzalloc(sizeof(struct adv7180_state), GFP_KERNEL); |
138 | if (state == NULL) | 320 | if (state == NULL) { |
139 | return -ENOMEM; | 321 | ret = -ENOMEM; |
322 | goto err; | ||
323 | } | ||
324 | |||
325 | state->irq = client->irq; | ||
326 | INIT_WORK(&state->work, adv7180_work); | ||
327 | mutex_init(&state->mutex); | ||
328 | state->autodetect = true; | ||
140 | sd = &state->sd; | 329 | sd = &state->sd; |
141 | v4l2_i2c_subdev_init(sd, client, &adv7180_ops); | 330 | v4l2_i2c_subdev_init(sd, client, &adv7180_ops); |
142 | 331 | ||
143 | /* Initialize adv7180 */ | 332 | /* Initialize adv7180 */ |
144 | /* enable autodetection */ | 333 | /* Enable autodetection */ |
145 | ret = i2c_smbus_write_byte_data(client, ADV7180_INPUT_CONTROL_REG, | 334 | ret = i2c_smbus_write_byte_data(client, ADV7180_INPUT_CONTROL_REG, |
146 | ADV7180_INPUT_CONTROL_PAL_BG_NTSC_J_SECAM); | 335 | ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM); |
147 | if (ret > 0) | 336 | if (ret < 0) |
148 | ret = i2c_smbus_write_byte_data(client, | 337 | goto err_unreg_subdev; |
149 | ADV7180_AUTODETECT_ENABLE_REG, | 338 | |
150 | ADV7180_AUTODETECT_DEFAULT); | 339 | ret = i2c_smbus_write_byte_data(client, ADV7180_AUTODETECT_ENABLE_REG, |
151 | if (ret < 0) { | 340 | ADV7180_AUTODETECT_DEFAULT); |
152 | printk(KERN_ERR DRIVER_NAME | 341 | if (ret < 0) |
153 | ": Failed to communicate to chip: %d\n", ret); | 342 | goto err_unreg_subdev; |
154 | return ret; | 343 | |
344 | /* ITU-R BT.656-4 compatible */ | ||
345 | ret = i2c_smbus_write_byte_data(client, | ||
346 | ADV7180_EXTENDED_OUTPUT_CONTROL_REG, | ||
347 | ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS); | ||
348 | if (ret < 0) | ||
349 | goto err_unreg_subdev; | ||
350 | |||
351 | /* read current norm */ | ||
352 | __adv7180_status(client, NULL, &state->curr_norm); | ||
353 | |||
354 | /* register for interrupts */ | ||
355 | if (state->irq > 0) { | ||
356 | ret = request_irq(state->irq, adv7180_irq, 0, DRIVER_NAME, | ||
357 | state); | ||
358 | if (ret) | ||
359 | goto err_unreg_subdev; | ||
360 | |||
361 | ret = i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG, | ||
362 | ADV7180_ADI_CTRL_IRQ_SPACE); | ||
363 | if (ret < 0) | ||
364 | goto err_unreg_subdev; | ||
365 | |||
366 | /* config the Interrupt pin to be active low */ | ||
367 | ret = i2c_smbus_write_byte_data(client, ADV7180_ICONF1_ADI, | ||
368 | ADV7180_ICONF1_ACTIVE_LOW | ADV7180_ICONF1_PSYNC_ONLY); | ||
369 | if (ret < 0) | ||
370 | goto err_unreg_subdev; | ||
371 | |||
372 | ret = i2c_smbus_write_byte_data(client, ADV7180_IMR1_ADI, 0); | ||
373 | if (ret < 0) | ||
374 | goto err_unreg_subdev; | ||
375 | |||
376 | ret = i2c_smbus_write_byte_data(client, ADV7180_IMR2_ADI, 0); | ||
377 | if (ret < 0) | ||
378 | goto err_unreg_subdev; | ||
379 | |||
380 | /* enable AD change interrupts interrupts */ | ||
381 | ret = i2c_smbus_write_byte_data(client, ADV7180_IMR3_ADI, | ||
382 | ADV7180_IRQ3_AD_CHANGE); | ||
383 | if (ret < 0) | ||
384 | goto err_unreg_subdev; | ||
385 | |||
386 | ret = i2c_smbus_write_byte_data(client, ADV7180_IMR4_ADI, 0); | ||
387 | if (ret < 0) | ||
388 | goto err_unreg_subdev; | ||
389 | |||
390 | ret = i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG, | ||
391 | 0); | ||
392 | if (ret < 0) | ||
393 | goto err_unreg_subdev; | ||
155 | } | 394 | } |
156 | 395 | ||
157 | return 0; | 396 | return 0; |
397 | |||
398 | err_unreg_subdev: | ||
399 | mutex_destroy(&state->mutex); | ||
400 | v4l2_device_unregister_subdev(sd); | ||
401 | kfree(state); | ||
402 | err: | ||
403 | printk(KERN_ERR DRIVER_NAME ": Failed to probe: %d\n", ret); | ||
404 | return ret; | ||
158 | } | 405 | } |
159 | 406 | ||
160 | static int adv7180_remove(struct i2c_client *client) | 407 | static __devexit int adv7180_remove(struct i2c_client *client) |
161 | { | 408 | { |
162 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | 409 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
410 | struct adv7180_state *state = to_state(sd); | ||
411 | |||
412 | if (state->irq > 0) { | ||
413 | free_irq(client->irq, state); | ||
414 | if (cancel_work_sync(&state->work)) { | ||
415 | /* | ||
416 | * Work was pending, therefore we need to enable | ||
417 | * IRQ here to balance the disable_irq() done in the | ||
418 | * interrupt handler. | ||
419 | */ | ||
420 | enable_irq(state->irq); | ||
421 | } | ||
422 | } | ||
163 | 423 | ||
424 | mutex_destroy(&state->mutex); | ||
164 | v4l2_device_unregister_subdev(sd); | 425 | v4l2_device_unregister_subdev(sd); |
165 | kfree(to_state(sd)); | 426 | kfree(to_state(sd)); |
166 | return 0; | 427 | return 0; |
@@ -179,7 +440,7 @@ static struct i2c_driver adv7180_driver = { | |||
179 | .name = DRIVER_NAME, | 440 | .name = DRIVER_NAME, |
180 | }, | 441 | }, |
181 | .probe = adv7180_probe, | 442 | .probe = adv7180_probe, |
182 | .remove = adv7180_remove, | 443 | .remove = __devexit_p(adv7180_remove), |
183 | .id_table = adv7180_id, | 444 | .id_table = adv7180_id, |
184 | }; | 445 | }; |
185 | 446 | ||
diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 51527d7b55a7..1485aee18d58 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c | |||
@@ -830,7 +830,7 @@ static int au0828_v4l2_close(struct file *filp) | |||
830 | au0828_uninit_isoc(dev); | 830 | au0828_uninit_isoc(dev); |
831 | 831 | ||
832 | /* Save some power by putting tuner to sleep */ | 832 | /* Save some power by putting tuner to sleep */ |
833 | v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_standby); | 833 | v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); |
834 | 834 | ||
835 | /* When close the device, set the usb intf0 into alt0 to free | 835 | /* When close the device, set the usb intf0 into alt0 to free |
836 | USB bandwidth */ | 836 | USB bandwidth */ |
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index f9330e3529c3..5bb0f9e71583 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c | |||
@@ -299,7 +299,7 @@ static int bt819_s_routing(struct v4l2_subdev *sd, | |||
299 | 299 | ||
300 | v4l2_dbg(1, debug, sd, "set input %x\n", input); | 300 | v4l2_dbg(1, debug, sd, "set input %x\n", input); |
301 | 301 | ||
302 | if (input < 0 || input > 7) | 302 | if (input > 7) |
303 | return -EINVAL; | 303 | return -EINVAL; |
304 | 304 | ||
305 | if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL) | 305 | if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL) |
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index ebd51afe8761..84a957e52c4b 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c | |||
@@ -73,12 +73,12 @@ static void ir_handle_key(struct bttv *btv) | |||
73 | 73 | ||
74 | if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || | 74 | if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || |
75 | (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { | 75 | (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { |
76 | ir_input_keydown(ir->dev,&ir->ir,data,data); | 76 | ir_input_keydown(ir->dev, &ir->ir, data); |
77 | } else { | 77 | } else { |
78 | /* HACK: Probably, ir->mask_keydown is missing | 78 | /* HACK: Probably, ir->mask_keydown is missing |
79 | for this board */ | 79 | for this board */ |
80 | if (btv->c.type == BTTV_BOARD_WINFAST2000) | 80 | if (btv->c.type == BTTV_BOARD_WINFAST2000) |
81 | ir_input_keydown(ir->dev, &ir->ir, data, data); | 81 | ir_input_keydown(ir->dev, &ir->ir, data); |
82 | 82 | ||
83 | ir_input_nokey(ir->dev,&ir->ir); | 83 | ir_input_nokey(ir->dev,&ir->ir); |
84 | } | 84 | } |
@@ -104,7 +104,7 @@ static void ir_enltv_handle_key(struct bttv *btv) | |||
104 | gpio, data, | 104 | gpio, data, |
105 | (gpio & ir->mask_keyup) ? " up" : "up/down"); | 105 | (gpio & ir->mask_keyup) ? " up" : "up/down"); |
106 | 106 | ||
107 | ir_input_keydown(ir->dev, &ir->ir, data, data); | 107 | ir_input_keydown(ir->dev, &ir->ir, data); |
108 | if (keyup) | 108 | if (keyup) |
109 | ir_input_nokey(ir->dev, &ir->ir); | 109 | ir_input_nokey(ir->dev, &ir->ir); |
110 | } else { | 110 | } else { |
@@ -118,7 +118,7 @@ static void ir_enltv_handle_key(struct bttv *btv) | |||
118 | if (keyup) | 118 | if (keyup) |
119 | ir_input_nokey(ir->dev, &ir->ir); | 119 | ir_input_nokey(ir->dev, &ir->ir); |
120 | else | 120 | else |
121 | ir_input_keydown(ir->dev, &ir->ir, data, data); | 121 | ir_input_keydown(ir->dev, &ir->ir, data); |
122 | } | 122 | } |
123 | 123 | ||
124 | ir->last_gpio = data | keyup; | 124 | ir->last_gpio = data | keyup; |
@@ -368,7 +368,10 @@ int bttv_input_init(struct bttv *btv) | |||
368 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", | 368 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", |
369 | pci_name(btv->c.pci)); | 369 | pci_name(btv->c.pci)); |
370 | 370 | ||
371 | ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); | 371 | err = ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); |
372 | if (err < 0) | ||
373 | goto err_out_free; | ||
374 | |||
372 | input_dev->name = ir->name; | 375 | input_dev->name = ir->name; |
373 | input_dev->phys = ir->phys; | 376 | input_dev->phys = ir->phys; |
374 | input_dev->id.bustype = BUS_PCI; | 377 | input_dev->id.bustype = BUS_PCI; |
@@ -400,6 +403,7 @@ int bttv_input_init(struct bttv *btv) | |||
400 | bttv_ir_stop(btv); | 403 | bttv_ir_stop(btv); |
401 | btv->remote = NULL; | 404 | btv->remote = NULL; |
402 | err_out_free: | 405 | err_out_free: |
406 | ir_input_free(input_dev); | ||
403 | input_free_device(input_dev); | 407 | input_free_device(input_dev); |
404 | kfree(ir); | 408 | kfree(ir); |
405 | return err; | 409 | return err; |
@@ -411,6 +415,7 @@ void bttv_input_fini(struct bttv *btv) | |||
411 | return; | 415 | return; |
412 | 416 | ||
413 | bttv_ir_stop(btv); | 417 | bttv_ir_stop(btv); |
418 | ir_input_free(btv->remote->dev); | ||
414 | input_unregister_device(btv->remote->dev); | 419 | input_unregister_device(btv->remote->dev); |
415 | kfree(btv->remote); | 420 | kfree(btv->remote); |
416 | btv->remote = NULL; | 421 | btv->remote = NULL; |
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 536dedb23ba3..4392c76af5df 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c | |||
@@ -99,10 +99,8 @@ int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 and_mask, | |||
99 | or_value); | 99 | or_value); |
100 | } | 100 | } |
101 | 101 | ||
102 | static int cx18_av_init(struct v4l2_subdev *sd, u32 val) | 102 | static void cx18_av_init(struct cx18 *cx) |
103 | { | 103 | { |
104 | struct cx18 *cx = v4l2_get_subdevdata(sd); | ||
105 | |||
106 | /* | 104 | /* |
107 | * The crystal freq used in calculations in this driver will be | 105 | * The crystal freq used in calculations in this driver will be |
108 | * 28.636360 MHz. | 106 | * 28.636360 MHz. |
@@ -125,7 +123,6 @@ static int cx18_av_init(struct v4l2_subdev *sd, u32 val) | |||
125 | 123 | ||
126 | /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */ | 124 | /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */ |
127 | cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56); | 125 | cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56); |
128 | return 0; | ||
129 | } | 126 | } |
130 | 127 | ||
131 | static void cx18_av_initialize(struct v4l2_subdev *sd) | 128 | static void cx18_av_initialize(struct v4l2_subdev *sd) |
@@ -198,7 +195,7 @@ static void cx18_av_initialize(struct v4l2_subdev *sd) | |||
198 | cx18_av_and_or4(cx, CXADEC_CHIP_CTRL, 0xFFFBFFFF, 0x00120000); | 195 | cx18_av_and_or4(cx, CXADEC_CHIP_CTRL, 0xFFFBFFFF, 0x00120000); |
199 | 196 | ||
200 | /* Setup the Video and and Aux/Audio PLLs */ | 197 | /* Setup the Video and and Aux/Audio PLLs */ |
201 | cx18_av_init(sd, 0); | 198 | cx18_av_init(cx); |
202 | 199 | ||
203 | /* set video to auto-detect */ | 200 | /* set video to auto-detect */ |
204 | /* Clear bits 11-12 to enable slow locking mode. Set autodetect mode */ | 201 | /* Clear bits 11-12 to enable slow locking mode. Set autodetect mode */ |
@@ -1355,7 +1352,6 @@ static int cx18_av_s_register(struct v4l2_subdev *sd, | |||
1355 | static const struct v4l2_subdev_core_ops cx18_av_general_ops = { | 1352 | static const struct v4l2_subdev_core_ops cx18_av_general_ops = { |
1356 | .g_chip_ident = cx18_av_g_chip_ident, | 1353 | .g_chip_ident = cx18_av_g_chip_ident, |
1357 | .log_status = cx18_av_log_status, | 1354 | .log_status = cx18_av_log_status, |
1358 | .init = cx18_av_init, | ||
1359 | .load_fw = cx18_av_load_fw, | 1355 | .load_fw = cx18_av_load_fw, |
1360 | .reset = cx18_av_reset, | 1356 | .reset = cx18_av_reset, |
1361 | .queryctrl = cx18_av_queryctrl, | 1357 | .queryctrl = cx18_av_queryctrl, |
@@ -1399,6 +1395,7 @@ int cx18_av_probe(struct cx18 *cx) | |||
1399 | { | 1395 | { |
1400 | struct cx18_av_state *state = &cx->av_state; | 1396 | struct cx18_av_state *state = &cx->av_state; |
1401 | struct v4l2_subdev *sd; | 1397 | struct v4l2_subdev *sd; |
1398 | int err; | ||
1402 | 1399 | ||
1403 | state->rev = cx18_av_read4(cx, CXADEC_CHIP_CTRL) & 0xffff; | 1400 | state->rev = cx18_av_read4(cx, CXADEC_CHIP_CTRL) & 0xffff; |
1404 | state->id = ((state->rev >> 4) == CXADEC_CHIP_TYPE_MAKO) | 1401 | state->id = ((state->rev >> 4) == CXADEC_CHIP_TYPE_MAKO) |
@@ -1417,5 +1414,8 @@ int cx18_av_probe(struct cx18 *cx) | |||
1417 | snprintf(sd->name, sizeof(sd->name), | 1414 | snprintf(sd->name, sizeof(sd->name), |
1418 | "%s %03x", cx->v4l2_dev.name, (state->rev >> 4)); | 1415 | "%s %03x", cx->v4l2_dev.name, (state->rev >> 4)); |
1419 | sd->grp_id = CX18_HW_418_AV; | 1416 | sd->grp_id = CX18_HW_418_AV; |
1420 | return v4l2_device_register_subdev(&cx->v4l2_dev, sd); | 1417 | err = v4l2_device_register_subdev(&cx->v4l2_dev, sd); |
1418 | if (!err) | ||
1419 | cx18_av_init(cx); | ||
1420 | return err; | ||
1421 | } | 1421 | } |
diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h index 444e3c7c563e..af3d71607dc9 100644 --- a/drivers/media/video/cx18/cx18-cards.h +++ b/drivers/media/video/cx18/cx18-cards.h | |||
@@ -34,6 +34,9 @@ | |||
34 | #define CX18_HW_Z8F0811_IR_HAUP (CX18_HW_Z8F0811_IR_RX_HAUP | \ | 34 | #define CX18_HW_Z8F0811_IR_HAUP (CX18_HW_Z8F0811_IR_RX_HAUP | \ |
35 | CX18_HW_Z8F0811_IR_TX_HAUP) | 35 | CX18_HW_Z8F0811_IR_TX_HAUP) |
36 | 36 | ||
37 | #define CX18_HW_IR_ANY (CX18_HW_Z8F0811_IR_RX_HAUP | \ | ||
38 | CX18_HW_Z8F0811_IR_TX_HAUP) | ||
39 | |||
37 | /* video inputs */ | 40 | /* video inputs */ |
38 | #define CX18_CARD_INPUT_VID_TUNER 1 | 41 | #define CX18_CARD_INPUT_VID_TUNER 1 |
39 | #define CX18_CARD_INPUT_SVIDEO1 2 | 42 | #define CX18_CARD_INPUT_SVIDEO1 2 |
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index e12082b8a08d..7f65a47f12e1 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c | |||
@@ -87,7 +87,6 @@ static int enc_ts_bufsize = CX18_DEFAULT_ENC_TS_BUFSIZE; | |||
87 | static int enc_mpg_bufsize = CX18_DEFAULT_ENC_MPG_BUFSIZE; | 87 | static int enc_mpg_bufsize = CX18_DEFAULT_ENC_MPG_BUFSIZE; |
88 | static int enc_idx_bufsize = CX18_DEFAULT_ENC_IDX_BUFSIZE; | 88 | static int enc_idx_bufsize = CX18_DEFAULT_ENC_IDX_BUFSIZE; |
89 | static int enc_yuv_bufsize = CX18_DEFAULT_ENC_YUV_BUFSIZE; | 89 | static int enc_yuv_bufsize = CX18_DEFAULT_ENC_YUV_BUFSIZE; |
90 | /* VBI bufsize based on standards supported by card tuner for now */ | ||
91 | static int enc_pcm_bufsize = CX18_DEFAULT_ENC_PCM_BUFSIZE; | 90 | static int enc_pcm_bufsize = CX18_DEFAULT_ENC_PCM_BUFSIZE; |
92 | 91 | ||
93 | static int enc_ts_bufs = -1; | 92 | static int enc_ts_bufs = -1; |
@@ -128,7 +127,6 @@ module_param(enc_ts_bufsize, int, 0644); | |||
128 | module_param(enc_mpg_bufsize, int, 0644); | 127 | module_param(enc_mpg_bufsize, int, 0644); |
129 | module_param(enc_idx_bufsize, int, 0644); | 128 | module_param(enc_idx_bufsize, int, 0644); |
130 | module_param(enc_yuv_bufsize, int, 0644); | 129 | module_param(enc_yuv_bufsize, int, 0644); |
131 | /* VBI bufsize based on standards supported by card tuner for now */ | ||
132 | module_param(enc_pcm_bufsize, int, 0644); | 130 | module_param(enc_pcm_bufsize, int, 0644); |
133 | 131 | ||
134 | module_param(enc_ts_bufs, int, 0644); | 132 | module_param(enc_ts_bufs, int, 0644); |
@@ -211,7 +209,9 @@ MODULE_PARM_DESC(enc_yuv_buffers, | |||
211 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS)); | 209 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS)); |
212 | MODULE_PARM_DESC(enc_yuv_bufsize, | 210 | MODULE_PARM_DESC(enc_yuv_bufsize, |
213 | "Size of an encoder YUV buffer (kB)\n" | 211 | "Size of an encoder YUV buffer (kB)\n" |
214 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFSIZE)); | 212 | "\t\t\tAllowed values are multiples of 33.75 kB rounded up\n" |
213 | "\t\t\t(multiples of size required for 32 screen lines)\n" | ||
214 | "\t\t\tDefault: 102"); | ||
215 | MODULE_PARM_DESC(enc_yuv_bufs, | 215 | MODULE_PARM_DESC(enc_yuv_bufs, |
216 | "Number of encoder YUV buffers\n" | 216 | "Number of encoder YUV buffers\n" |
217 | "\t\t\tDefault is computed from other enc_yuv_* parameters"); | 217 | "\t\t\tDefault is computed from other enc_yuv_* parameters"); |
@@ -220,7 +220,7 @@ MODULE_PARM_DESC(enc_vbi_buffers, | |||
220 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_VBI_BUFFERS)); | 220 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_VBI_BUFFERS)); |
221 | MODULE_PARM_DESC(enc_vbi_bufs, | 221 | MODULE_PARM_DESC(enc_vbi_bufs, |
222 | "Number of encoder VBI buffers\n" | 222 | "Number of encoder VBI buffers\n" |
223 | "\t\t\tDefault is computed from enc_vbi_buffers & tuner std"); | 223 | "\t\t\tDefault is computed from enc_vbi_buffers"); |
224 | MODULE_PARM_DESC(enc_pcm_buffers, | 224 | MODULE_PARM_DESC(enc_pcm_buffers, |
225 | "Encoder PCM buffer memory (MB). (enc_pcm_bufs can override)\n" | 225 | "Encoder PCM buffer memory (MB). (enc_pcm_bufs can override)\n" |
226 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS)); | 226 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS)); |
@@ -499,10 +499,27 @@ static void cx18_process_options(struct cx18 *cx) | |||
499 | continue; | 499 | continue; |
500 | } | 500 | } |
501 | /* | 501 | /* |
502 | * YUV is a special case where the stream_buf_size needs to be | ||
503 | * an integral multiple of 33.75 kB (storage for 32 screens | ||
504 | * lines to maintain alignment in case of lost buffers | ||
505 | */ | ||
506 | if (i == CX18_ENC_STREAM_TYPE_YUV) { | ||
507 | cx->stream_buf_size[i] *= 1024; | ||
508 | cx->stream_buf_size[i] -= | ||
509 | (cx->stream_buf_size[i] % CX18_UNIT_ENC_YUV_BUFSIZE); | ||
510 | |||
511 | if (cx->stream_buf_size[i] < CX18_UNIT_ENC_YUV_BUFSIZE) | ||
512 | cx->stream_buf_size[i] = | ||
513 | CX18_UNIT_ENC_YUV_BUFSIZE; | ||
514 | } | ||
515 | /* | ||
516 | * YUV is a special case where the stream_buf_size is | ||
517 | * now in bytes. | ||
502 | * VBI is a special case where the stream_buf_size is fixed | 518 | * VBI is a special case where the stream_buf_size is fixed |
503 | * and already in bytes | 519 | * and already in bytes |
504 | */ | 520 | */ |
505 | if (i == CX18_ENC_STREAM_TYPE_VBI) { | 521 | if (i == CX18_ENC_STREAM_TYPE_VBI || |
522 | i == CX18_ENC_STREAM_TYPE_YUV) { | ||
506 | if (cx->stream_buffers[i] < 0) { | 523 | if (cx->stream_buffers[i] < 0) { |
507 | cx->stream_buffers[i] = | 524 | cx->stream_buffers[i] = |
508 | cx->options.megabytes[i] * 1024 * 1024 | 525 | cx->options.megabytes[i] * 1024 * 1024 |
@@ -513,18 +530,24 @@ static void cx18_process_options(struct cx18 *cx) | |||
513 | cx->stream_buffers[i] | 530 | cx->stream_buffers[i] |
514 | * cx->stream_buf_size[i]/(1024 * 1024); | 531 | * cx->stream_buf_size[i]/(1024 * 1024); |
515 | } | 532 | } |
516 | continue; | ||
517 | } | ||
518 | /* All other streams have stream_buf_size in kB at this point */ | ||
519 | if (cx->stream_buffers[i] < 0) { | ||
520 | cx->stream_buffers[i] = cx->options.megabytes[i] * 1024 | ||
521 | / cx->stream_buf_size[i]; | ||
522 | } else { | 533 | } else { |
523 | /* N.B. This might round down to 0 */ | 534 | /* All other streams have stream_buf_size in kB here */ |
524 | cx->options.megabytes[i] = | 535 | if (cx->stream_buffers[i] < 0) { |
525 | cx->stream_buffers[i] * cx->stream_buf_size[i] / 1024; | 536 | cx->stream_buffers[i] = |
537 | cx->options.megabytes[i] * 1024 | ||
538 | / cx->stream_buf_size[i]; | ||
539 | } else { | ||
540 | /* N.B. This might round down to 0 */ | ||
541 | cx->options.megabytes[i] = | ||
542 | cx->stream_buffers[i] | ||
543 | * cx->stream_buf_size[i] / 1024; | ||
544 | } | ||
545 | /* convert from kB to bytes */ | ||
546 | cx->stream_buf_size[i] *= 1024; | ||
526 | } | 547 | } |
527 | cx->stream_buf_size[i] *= 1024; /* convert from kB to bytes */ | 548 | CX18_DEBUG_INFO("Stream type %d options: %d MB, %d buffers, " |
549 | "%d bytes\n", i, cx->options.megabytes[i], | ||
550 | cx->stream_buffers[i], cx->stream_buf_size[i]); | ||
528 | } | 551 | } |
529 | 552 | ||
530 | cx->options.cardtype = cardtype[cx->instance]; | 553 | cx->options.cardtype = cardtype[cx->instance]; |
@@ -669,6 +692,12 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) | |||
669 | cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; | 692 | cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; |
670 | cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced; | 693 | cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced; |
671 | 694 | ||
695 | /* IVTV style VBI insertion into MPEG streams */ | ||
696 | INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_buf.list); | ||
697 | INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_mdl.list); | ||
698 | INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_mdl.buf_list); | ||
699 | list_add(&cx->vbi.sliced_mpeg_buf.list, | ||
700 | &cx->vbi.sliced_mpeg_mdl.buf_list); | ||
672 | return 0; | 701 | return 0; |
673 | } | 702 | } |
674 | 703 | ||
@@ -883,7 +912,6 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, | |||
883 | CX18_ERR("Could not register A/V decoder subdevice\n"); | 912 | CX18_ERR("Could not register A/V decoder subdevice\n"); |
884 | goto free_map; | 913 | goto free_map; |
885 | } | 914 | } |
886 | cx18_call_hw(cx, CX18_HW_418_AV, core, init, 0); | ||
887 | 915 | ||
888 | /* Initialize GPIO Reset Controller to do chip resets during i2c init */ | 916 | /* Initialize GPIO Reset Controller to do chip resets during i2c init */ |
889 | if (cx->card->hw_all & CX18_HW_GPIO_RESET_CTRL) { | 917 | if (cx->card->hw_all & CX18_HW_GPIO_RESET_CTRL) { |
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index c6a1e907f63a..e3f7911a7385 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <media/v4l2-ioctl.h> | 50 | #include <media/v4l2-ioctl.h> |
51 | #include <media/v4l2-device.h> | 51 | #include <media/v4l2-device.h> |
52 | #include <media/tuner.h> | 52 | #include <media/tuner.h> |
53 | #include <media/ir-kbd-i2c.h> | ||
53 | #include "cx18-mailbox.h" | 54 | #include "cx18-mailbox.h" |
54 | #include "cx18-av-core.h" | 55 | #include "cx18-av-core.h" |
55 | #include "cx23418.h" | 56 | #include "cx23418.h" |
@@ -120,12 +121,16 @@ | |||
120 | /* Maximum firmware DMA buffers per stream */ | 121 | /* Maximum firmware DMA buffers per stream */ |
121 | #define CX18_MAX_FW_MDLS_PER_STREAM 63 | 122 | #define CX18_MAX_FW_MDLS_PER_STREAM 63 |
122 | 123 | ||
124 | /* YUV buffer sizes in bytes to ensure integer # of frames per buffer */ | ||
125 | #define CX18_UNIT_ENC_YUV_BUFSIZE (720 * 32 * 3 / 2) /* bytes */ | ||
126 | #define CX18_625_LINE_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 576/32) | ||
127 | #define CX18_525_LINE_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 480/32) | ||
128 | |||
123 | /* DMA buffer, default size in kB allocated */ | 129 | /* DMA buffer, default size in kB allocated */ |
124 | #define CX18_DEFAULT_ENC_TS_BUFSIZE 32 | 130 | #define CX18_DEFAULT_ENC_TS_BUFSIZE 32 |
125 | #define CX18_DEFAULT_ENC_MPG_BUFSIZE 32 | 131 | #define CX18_DEFAULT_ENC_MPG_BUFSIZE 32 |
126 | #define CX18_DEFAULT_ENC_IDX_BUFSIZE 32 | 132 | #define CX18_DEFAULT_ENC_IDX_BUFSIZE 32 |
127 | #define CX18_DEFAULT_ENC_YUV_BUFSIZE 128 | 133 | #define CX18_DEFAULT_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 3 / 1024 + 1) |
128 | /* Default VBI bufsize based on standards supported by card tuner for now */ | ||
129 | #define CX18_DEFAULT_ENC_PCM_BUFSIZE 4 | 134 | #define CX18_DEFAULT_ENC_PCM_BUFSIZE 4 |
130 | 135 | ||
131 | /* i2c stuff */ | 136 | /* i2c stuff */ |
@@ -246,8 +251,8 @@ struct cx18_options { | |||
246 | int radio; /* enable/disable radio */ | 251 | int radio; /* enable/disable radio */ |
247 | }; | 252 | }; |
248 | 253 | ||
249 | /* per-buffer bit flags */ | 254 | /* per-mdl bit flags */ |
250 | #define CX18_F_B_NEED_BUF_SWAP 0 /* this buffer should be byte swapped */ | 255 | #define CX18_F_M_NEED_SWAP 0 /* mdl buffer data must be endianess swapped */ |
251 | 256 | ||
252 | /* per-stream, s_flags */ | 257 | /* per-stream, s_flags */ |
253 | #define CX18_F_S_CLAIMED 3 /* this stream is claimed */ | 258 | #define CX18_F_S_CLAIMED 3 /* this stream is claimed */ |
@@ -274,18 +279,29 @@ struct cx18_options { | |||
274 | struct cx18_buffer { | 279 | struct cx18_buffer { |
275 | struct list_head list; | 280 | struct list_head list; |
276 | dma_addr_t dma_handle; | 281 | dma_addr_t dma_handle; |
277 | u32 id; | ||
278 | unsigned long b_flags; | ||
279 | unsigned skipped; | ||
280 | char *buf; | 282 | char *buf; |
281 | 283 | ||
282 | u32 bytesused; | 284 | u32 bytesused; |
283 | u32 readpos; | 285 | u32 readpos; |
284 | }; | 286 | }; |
285 | 287 | ||
288 | struct cx18_mdl { | ||
289 | struct list_head list; | ||
290 | u32 id; /* index into cx->scb->cpu_mdl[] of 1st cx18_mdl_ent */ | ||
291 | |||
292 | unsigned int skipped; | ||
293 | unsigned long m_flags; | ||
294 | |||
295 | struct list_head buf_list; | ||
296 | struct cx18_buffer *curr_buf; /* current buffer in list for reading */ | ||
297 | |||
298 | u32 bytesused; | ||
299 | u32 readpos; | ||
300 | }; | ||
301 | |||
286 | struct cx18_queue { | 302 | struct cx18_queue { |
287 | struct list_head list; | 303 | struct list_head list; |
288 | atomic_t buffers; | 304 | atomic_t depth; |
289 | u32 bytesused; | 305 | u32 bytesused; |
290 | spinlock_t lock; | 306 | spinlock_t lock; |
291 | }; | 307 | }; |
@@ -337,7 +353,7 @@ struct cx18_stream { | |||
337 | const char *name; /* name of the stream */ | 353 | const char *name; /* name of the stream */ |
338 | int type; /* stream type */ | 354 | int type; /* stream type */ |
339 | u32 handle; /* task handle */ | 355 | u32 handle; /* task handle */ |
340 | unsigned mdl_offset; | 356 | unsigned int mdl_base_idx; |
341 | 357 | ||
342 | u32 id; | 358 | u32 id; |
343 | unsigned long s_flags; /* status flags, see above */ | 359 | unsigned long s_flags; /* status flags, see above */ |
@@ -346,14 +362,20 @@ struct cx18_stream { | |||
346 | PCI_DMA_NONE */ | 362 | PCI_DMA_NONE */ |
347 | wait_queue_head_t waitq; | 363 | wait_queue_head_t waitq; |
348 | 364 | ||
349 | /* Buffer Stats */ | 365 | /* Buffers */ |
350 | u32 buffers; | 366 | struct list_head buf_pool; /* buffers not attached to an MDL */ |
351 | u32 buf_size; | 367 | u32 buffers; /* total buffers owned by this stream */ |
368 | u32 buf_size; /* size in bytes of a single buffer */ | ||
369 | |||
370 | /* MDL sizes - all stream MDLs are the same size */ | ||
371 | u32 bufs_per_mdl; | ||
372 | u32 mdl_size; /* total bytes in all buffers in a mdl */ | ||
352 | 373 | ||
353 | /* Buffer Queues */ | 374 | /* MDL Queues */ |
354 | struct cx18_queue q_free; /* free buffers */ | 375 | struct cx18_queue q_free; /* free - in rotation, not committed */ |
355 | struct cx18_queue q_busy; /* busy buffers - in use by firmware */ | 376 | struct cx18_queue q_busy; /* busy - in use by firmware */ |
356 | struct cx18_queue q_full; /* full buffers - data for user apps */ | 377 | struct cx18_queue q_full; /* full - data for user apps */ |
378 | struct cx18_queue q_idle; /* idle - not in rotation */ | ||
357 | 379 | ||
358 | struct work_struct out_work_order; | 380 | struct work_struct out_work_order; |
359 | 381 | ||
@@ -481,10 +503,11 @@ struct vbi_info { | |||
481 | u32 inserted_frame; | 503 | u32 inserted_frame; |
482 | 504 | ||
483 | /* | 505 | /* |
484 | * A dummy driver stream transfer buffer with a copy of the next | 506 | * A dummy driver stream transfer mdl & buffer with a copy of the next |
485 | * sliced_mpeg_data[] buffer for output to userland apps. | 507 | * sliced_mpeg_data[] buffer for output to userland apps. |
486 | * Only used in cx18-fileops.c, but its state needs to persist at times. | 508 | * Only used in cx18-fileops.c, but its state needs to persist at times. |
487 | */ | 509 | */ |
510 | struct cx18_mdl sliced_mpeg_mdl; | ||
488 | struct cx18_buffer sliced_mpeg_buf; | 511 | struct cx18_buffer sliced_mpeg_buf; |
489 | }; | 512 | }; |
490 | 513 | ||
@@ -511,10 +534,9 @@ struct cx18 { | |||
511 | u8 is_60hz; | 534 | u8 is_60hz; |
512 | u8 nof_inputs; /* number of video inputs */ | 535 | u8 nof_inputs; /* number of video inputs */ |
513 | u8 nof_audio_inputs; /* number of audio inputs */ | 536 | u8 nof_audio_inputs; /* number of audio inputs */ |
514 | u16 buffer_id; /* buffer ID counter */ | ||
515 | u32 v4l2_cap; /* V4L2 capabilities of card */ | 537 | u32 v4l2_cap; /* V4L2 capabilities of card */ |
516 | u32 hw_flags; /* Hardware description of the board */ | 538 | u32 hw_flags; /* Hardware description of the board */ |
517 | unsigned mdl_offset; | 539 | unsigned int free_mdl_idx; |
518 | struct cx18_scb __iomem *scb; /* pointer to SCB */ | 540 | struct cx18_scb __iomem *scb; /* pointer to SCB */ |
519 | struct mutex epu2apu_mb_lock; /* protect driver to chip mailbox in SCB*/ | 541 | struct mutex epu2apu_mb_lock; /* protect driver to chip mailbox in SCB*/ |
520 | struct mutex epu2cpu_mb_lock; /* protect driver to chip mailbox in SCB*/ | 542 | struct mutex epu2cpu_mb_lock; /* protect driver to chip mailbox in SCB*/ |
@@ -585,6 +607,8 @@ struct cx18 { | |||
585 | struct i2c_algo_bit_data i2c_algo[2]; | 607 | struct i2c_algo_bit_data i2c_algo[2]; |
586 | struct cx18_i2c_algo_callback_data i2c_algo_cb_data[2]; | 608 | struct cx18_i2c_algo_callback_data i2c_algo_cb_data[2]; |
587 | 609 | ||
610 | struct IR_i2c_init_data ir_i2c_init_data; | ||
611 | |||
588 | /* gpio */ | 612 | /* gpio */ |
589 | u32 gpio_dir; | 613 | u32 gpio_dir; |
590 | u32 gpio_val; | 614 | u32 gpio_val; |
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index 51a0c33b25b7..71ad2d1b4c2c 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c | |||
@@ -61,6 +61,7 @@ static struct mxl5005s_config hauppauge_hvr1600_tuner = { | |||
61 | .top = MXL5005S_TOP_25P2, | 61 | .top = MXL5005S_TOP_25P2, |
62 | .mod_mode = MXL_DIGITAL_MODE, | 62 | .mod_mode = MXL_DIGITAL_MODE, |
63 | .if_mode = MXL_ZERO_IF, | 63 | .if_mode = MXL_ZERO_IF, |
64 | .qam_gain = 0x02, | ||
64 | .AgcMasterByte = 0x00, | 65 | .AgcMasterByte = 0x00, |
65 | }; | 66 | }; |
66 | 67 | ||
@@ -71,7 +72,8 @@ static struct s5h1409_config hauppauge_hvr1600_config = { | |||
71 | .qam_if = 44000, | 72 | .qam_if = 44000, |
72 | .inversion = S5H1409_INVERSION_OFF, | 73 | .inversion = S5H1409_INVERSION_OFF, |
73 | .status_mode = S5H1409_DEMODLOCKING, | 74 | .status_mode = S5H1409_DEMODLOCKING, |
74 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK | 75 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, |
76 | .hvr1600_opt = S5H1409_HVR1600_OPTIMIZE | ||
75 | }; | 77 | }; |
76 | 78 | ||
77 | /* | 79 | /* |
@@ -360,9 +362,10 @@ int cx18_dvb_register(struct cx18_stream *stream) | |||
360 | dvb_net_init(dvb_adapter, &dvb->dvbnet, dmx); | 362 | dvb_net_init(dvb_adapter, &dvb->dvbnet, dmx); |
361 | 363 | ||
362 | CX18_INFO("DVB Frontend registered\n"); | 364 | CX18_INFO("DVB Frontend registered\n"); |
363 | CX18_INFO("Registered DVB adapter%d for %s (%d x %d kB)\n", | 365 | CX18_INFO("Registered DVB adapter%d for %s (%d x %d.%02d kB)\n", |
364 | stream->dvb.dvb_adapter.num, stream->name, | 366 | stream->dvb.dvb_adapter.num, stream->name, |
365 | stream->buffers, stream->buf_size/1024); | 367 | stream->buffers, stream->buf_size/1024, |
368 | (stream->buf_size * 100 / 1024) % 100); | ||
366 | 369 | ||
367 | mutex_init(&dvb->feedlock); | 370 | mutex_init(&dvb->feedlock); |
368 | dvb->enabled = 1; | 371 | dvb->enabled = 1; |
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 04d9c2508b86..4e278db31cc9 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c | |||
@@ -166,11 +166,12 @@ static void cx18_dualwatch(struct cx18 *cx) | |||
166 | } | 166 | } |
167 | 167 | ||
168 | 168 | ||
169 | static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, int *err) | 169 | static struct cx18_mdl *cx18_get_mdl(struct cx18_stream *s, int non_block, |
170 | int *err) | ||
170 | { | 171 | { |
171 | struct cx18 *cx = s->cx; | 172 | struct cx18 *cx = s->cx; |
172 | struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; | 173 | struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; |
173 | struct cx18_buffer *buf; | 174 | struct cx18_mdl *mdl; |
174 | DEFINE_WAIT(wait); | 175 | DEFINE_WAIT(wait); |
175 | 176 | ||
176 | *err = 0; | 177 | *err = 0; |
@@ -185,32 +186,33 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, | |||
185 | } | 186 | } |
186 | if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) && | 187 | if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) && |
187 | !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) { | 188 | !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) { |
188 | while ((buf = cx18_dequeue(s_vbi, &s_vbi->q_full))) { | 189 | while ((mdl = cx18_dequeue(s_vbi, |
190 | &s_vbi->q_full))) { | ||
189 | /* byteswap and process VBI data */ | 191 | /* byteswap and process VBI data */ |
190 | cx18_process_vbi_data(cx, buf, | 192 | cx18_process_vbi_data(cx, mdl, |
191 | s_vbi->type); | 193 | s_vbi->type); |
192 | cx18_stream_put_buf_fw(s_vbi, buf); | 194 | cx18_stream_put_mdl_fw(s_vbi, mdl); |
193 | } | 195 | } |
194 | } | 196 | } |
195 | buf = &cx->vbi.sliced_mpeg_buf; | 197 | mdl = &cx->vbi.sliced_mpeg_mdl; |
196 | if (buf->readpos != buf->bytesused) | 198 | if (mdl->readpos != mdl->bytesused) |
197 | return buf; | 199 | return mdl; |
198 | } | 200 | } |
199 | 201 | ||
200 | /* do we have new data? */ | 202 | /* do we have new data? */ |
201 | buf = cx18_dequeue(s, &s->q_full); | 203 | mdl = cx18_dequeue(s, &s->q_full); |
202 | if (buf) { | 204 | if (mdl) { |
203 | if (!test_and_clear_bit(CX18_F_B_NEED_BUF_SWAP, | 205 | if (!test_and_clear_bit(CX18_F_M_NEED_SWAP, |
204 | &buf->b_flags)) | 206 | &mdl->m_flags)) |
205 | return buf; | 207 | return mdl; |
206 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) | 208 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) |
207 | /* byteswap MPG data */ | 209 | /* byteswap MPG data */ |
208 | cx18_buf_swap(buf); | 210 | cx18_mdl_swap(mdl); |
209 | else { | 211 | else { |
210 | /* byteswap and process VBI data */ | 212 | /* byteswap and process VBI data */ |
211 | cx18_process_vbi_data(cx, buf, s->type); | 213 | cx18_process_vbi_data(cx, mdl, s->type); |
212 | } | 214 | } |
213 | return buf; | 215 | return mdl; |
214 | } | 216 | } |
215 | 217 | ||
216 | /* return if end of stream */ | 218 | /* return if end of stream */ |
@@ -229,7 +231,7 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, | |||
229 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); | 231 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); |
230 | /* New buffers might have become available before we were added | 232 | /* New buffers might have become available before we were added |
231 | to the waitqueue */ | 233 | to the waitqueue */ |
232 | if (!atomic_read(&s->q_full.buffers)) | 234 | if (!atomic_read(&s->q_full.depth)) |
233 | schedule(); | 235 | schedule(); |
234 | finish_wait(&s->waitq, &wait); | 236 | finish_wait(&s->waitq, &wait); |
235 | if (signal_pending(current)) { | 237 | if (signal_pending(current)) { |
@@ -241,21 +243,28 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, | |||
241 | } | 243 | } |
242 | } | 244 | } |
243 | 245 | ||
244 | static void cx18_setup_sliced_vbi_buf(struct cx18 *cx) | 246 | static void cx18_setup_sliced_vbi_mdl(struct cx18 *cx) |
245 | { | 247 | { |
248 | struct cx18_mdl *mdl = &cx->vbi.sliced_mpeg_mdl; | ||
249 | struct cx18_buffer *buf = &cx->vbi.sliced_mpeg_buf; | ||
246 | int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES; | 250 | int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES; |
247 | 251 | ||
248 | cx->vbi.sliced_mpeg_buf.buf = cx->vbi.sliced_mpeg_data[idx]; | 252 | buf->buf = cx->vbi.sliced_mpeg_data[idx]; |
249 | cx->vbi.sliced_mpeg_buf.bytesused = cx->vbi.sliced_mpeg_size[idx]; | 253 | buf->bytesused = cx->vbi.sliced_mpeg_size[idx]; |
250 | cx->vbi.sliced_mpeg_buf.readpos = 0; | 254 | buf->readpos = 0; |
255 | |||
256 | mdl->curr_buf = NULL; | ||
257 | mdl->bytesused = cx->vbi.sliced_mpeg_size[idx]; | ||
258 | mdl->readpos = 0; | ||
251 | } | 259 | } |
252 | 260 | ||
253 | static size_t cx18_copy_buf_to_user(struct cx18_stream *s, | 261 | static size_t cx18_copy_buf_to_user(struct cx18_stream *s, |
254 | struct cx18_buffer *buf, char __user *ubuf, size_t ucount) | 262 | struct cx18_buffer *buf, char __user *ubuf, size_t ucount, bool *stop) |
255 | { | 263 | { |
256 | struct cx18 *cx = s->cx; | 264 | struct cx18 *cx = s->cx; |
257 | size_t len = buf->bytesused - buf->readpos; | 265 | size_t len = buf->bytesused - buf->readpos; |
258 | 266 | ||
267 | *stop = false; | ||
259 | if (len > ucount) | 268 | if (len > ucount) |
260 | len = ucount; | 269 | len = ucount; |
261 | if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG && | 270 | if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG && |
@@ -335,7 +344,8 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s, | |||
335 | /* We declare we actually found a Program Pack*/ | 344 | /* We declare we actually found a Program Pack*/ |
336 | cx->search_pack_header = 0; /* expect vid PES */ | 345 | cx->search_pack_header = 0; /* expect vid PES */ |
337 | len = (char *)q - start; | 346 | len = (char *)q - start; |
338 | cx18_setup_sliced_vbi_buf(cx); | 347 | cx18_setup_sliced_vbi_mdl(cx); |
348 | *stop = true; | ||
339 | break; | 349 | break; |
340 | } | 350 | } |
341 | } | 351 | } |
@@ -352,6 +362,60 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s, | |||
352 | return len; | 362 | return len; |
353 | } | 363 | } |
354 | 364 | ||
365 | /** | ||
366 | * list_entry_is_past_end - check if a previous loop cursor is off list end | ||
367 | * @pos: the type * previously used as a loop cursor. | ||
368 | * @head: the head for your list. | ||
369 | * @member: the name of the list_struct within the struct. | ||
370 | * | ||
371 | * Check if the entry's list_head is the head of the list, thus it's not a | ||
372 | * real entry but was the loop cursor that walked past the end | ||
373 | */ | ||
374 | #define list_entry_is_past_end(pos, head, member) \ | ||
375 | (&pos->member == (head)) | ||
376 | |||
377 | static size_t cx18_copy_mdl_to_user(struct cx18_stream *s, | ||
378 | struct cx18_mdl *mdl, char __user *ubuf, size_t ucount) | ||
379 | { | ||
380 | size_t tot_written = 0; | ||
381 | int rc; | ||
382 | bool stop = false; | ||
383 | |||
384 | if (mdl->curr_buf == NULL) | ||
385 | mdl->curr_buf = list_first_entry(&mdl->buf_list, | ||
386 | struct cx18_buffer, list); | ||
387 | |||
388 | if (list_entry_is_past_end(mdl->curr_buf, &mdl->buf_list, list)) { | ||
389 | /* | ||
390 | * For some reason we've exhausted the buffers, but the MDL | ||
391 | * object still said some data was unread. | ||
392 | * Fix that and bail out. | ||
393 | */ | ||
394 | mdl->readpos = mdl->bytesused; | ||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | list_for_each_entry_from(mdl->curr_buf, &mdl->buf_list, list) { | ||
399 | |||
400 | if (mdl->curr_buf->readpos >= mdl->curr_buf->bytesused) | ||
401 | continue; | ||
402 | |||
403 | rc = cx18_copy_buf_to_user(s, mdl->curr_buf, ubuf + tot_written, | ||
404 | ucount - tot_written, &stop); | ||
405 | if (rc < 0) | ||
406 | return rc; | ||
407 | mdl->readpos += rc; | ||
408 | tot_written += rc; | ||
409 | |||
410 | if (stop || /* Forced stopping point for VBI insertion */ | ||
411 | tot_written >= ucount || /* Reader request statisfied */ | ||
412 | mdl->curr_buf->readpos < mdl->curr_buf->bytesused || | ||
413 | mdl->readpos >= mdl->bytesused) /* MDL buffers drained */ | ||
414 | break; | ||
415 | } | ||
416 | return tot_written; | ||
417 | } | ||
418 | |||
355 | static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf, | 419 | static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf, |
356 | size_t tot_count, int non_block) | 420 | size_t tot_count, int non_block) |
357 | { | 421 | { |
@@ -373,12 +437,12 @@ static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf, | |||
373 | single_frame = 1; | 437 | single_frame = 1; |
374 | 438 | ||
375 | for (;;) { | 439 | for (;;) { |
376 | struct cx18_buffer *buf; | 440 | struct cx18_mdl *mdl; |
377 | int rc; | 441 | int rc; |
378 | 442 | ||
379 | buf = cx18_get_buffer(s, non_block, &rc); | 443 | mdl = cx18_get_mdl(s, non_block, &rc); |
380 | /* if there is no data available... */ | 444 | /* if there is no data available... */ |
381 | if (buf == NULL) { | 445 | if (mdl == NULL) { |
382 | /* if we got data, then return that regardless */ | 446 | /* if we got data, then return that regardless */ |
383 | if (tot_written) | 447 | if (tot_written) |
384 | break; | 448 | break; |
@@ -392,20 +456,20 @@ static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf, | |||
392 | return rc; | 456 | return rc; |
393 | } | 457 | } |
394 | 458 | ||
395 | rc = cx18_copy_buf_to_user(s, buf, ubuf + tot_written, | 459 | rc = cx18_copy_mdl_to_user(s, mdl, ubuf + tot_written, |
396 | tot_count - tot_written); | 460 | tot_count - tot_written); |
397 | 461 | ||
398 | if (buf != &cx->vbi.sliced_mpeg_buf) { | 462 | if (mdl != &cx->vbi.sliced_mpeg_mdl) { |
399 | if (buf->readpos == buf->bytesused) | 463 | if (mdl->readpos == mdl->bytesused) |
400 | cx18_stream_put_buf_fw(s, buf); | 464 | cx18_stream_put_mdl_fw(s, mdl); |
401 | else | 465 | else |
402 | cx18_push(s, buf, &s->q_full); | 466 | cx18_push(s, mdl, &s->q_full); |
403 | } else if (buf->readpos == buf->bytesused) { | 467 | } else if (mdl->readpos == mdl->bytesused) { |
404 | int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES; | 468 | int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES; |
405 | 469 | ||
406 | cx->vbi.sliced_mpeg_size[idx] = 0; | 470 | cx->vbi.sliced_mpeg_size[idx] = 0; |
407 | cx->vbi.inserted_frame++; | 471 | cx->vbi.inserted_frame++; |
408 | cx->vbi_data_inserted += buf->bytesused; | 472 | cx->vbi_data_inserted += mdl->bytesused; |
409 | } | 473 | } |
410 | if (rc < 0) | 474 | if (rc < 0) |
411 | return rc; | 475 | return rc; |
@@ -543,7 +607,7 @@ unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait) | |||
543 | CX18_DEBUG_HI_FILE("Encoder poll\n"); | 607 | CX18_DEBUG_HI_FILE("Encoder poll\n"); |
544 | poll_wait(filp, &s->waitq, wait); | 608 | poll_wait(filp, &s->waitq, wait); |
545 | 609 | ||
546 | if (atomic_read(&s->q_full.buffers)) | 610 | if (atomic_read(&s->q_full.depth)) |
547 | return POLLIN | POLLRDNORM; | 611 | return POLLIN | POLLRDNORM; |
548 | if (eof) | 612 | if (eof) |
549 | return POLLHUP; | 613 | return POLLHUP; |
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index 2477461e84d7..eecf29af916c 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include "cx18-gpio.h" | 28 | #include "cx18-gpio.h" |
29 | #include "cx18-i2c.h" | 29 | #include "cx18-i2c.h" |
30 | #include "cx18-irq.h" | 30 | #include "cx18-irq.h" |
31 | #include <media/ir-kbd-i2c.h> | ||
32 | 31 | ||
33 | #define CX18_REG_I2C_1_WR 0xf15000 | 32 | #define CX18_REG_I2C_1_WR 0xf15000 |
34 | #define CX18_REG_I2C_1_RD 0xf15008 | 33 | #define CX18_REG_I2C_1_RD 0xf15008 |
@@ -97,17 +96,11 @@ static const char * const hw_devicenames[] = { | |||
97 | "ir_rx_z8f0811_haup", | 96 | "ir_rx_z8f0811_haup", |
98 | }; | 97 | }; |
99 | 98 | ||
100 | static const struct IR_i2c_init_data z8f0811_ir_init_data = { | 99 | static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw, |
101 | .ir_codes = &ir_codes_hauppauge_new_table, | 100 | const char *type, u8 addr) |
102 | .internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR, | ||
103 | .type = IR_TYPE_RC5, | ||
104 | .name = "CX23418 Z8F0811 Hauppauge", | ||
105 | }; | ||
106 | |||
107 | static int cx18_i2c_new_ir(struct i2c_adapter *adap, u32 hw, const char *type, | ||
108 | u8 addr) | ||
109 | { | 101 | { |
110 | struct i2c_board_info info; | 102 | struct i2c_board_info info; |
103 | struct IR_i2c_init_data *init_data = &cx->ir_i2c_init_data; | ||
111 | unsigned short addr_list[2] = { addr, I2C_CLIENT_END }; | 104 | unsigned short addr_list[2] = { addr, I2C_CLIENT_END }; |
112 | 105 | ||
113 | memset(&info, 0, sizeof(struct i2c_board_info)); | 106 | memset(&info, 0, sizeof(struct i2c_board_info)); |
@@ -116,9 +109,11 @@ static int cx18_i2c_new_ir(struct i2c_adapter *adap, u32 hw, const char *type, | |||
116 | /* Our default information for ir-kbd-i2c.c to use */ | 109 | /* Our default information for ir-kbd-i2c.c to use */ |
117 | switch (hw) { | 110 | switch (hw) { |
118 | case CX18_HW_Z8F0811_IR_RX_HAUP: | 111 | case CX18_HW_Z8F0811_IR_RX_HAUP: |
119 | info.platform_data = (void *) &z8f0811_ir_init_data; | 112 | init_data->ir_codes = &ir_codes_hauppauge_new_table; |
120 | break; | 113 | init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; |
121 | default: | 114 | init_data->type = IR_TYPE_RC5; |
115 | init_data->name = cx->card_name; | ||
116 | info.platform_data = init_data; | ||
122 | break; | 117 | break; |
123 | } | 118 | } |
124 | 119 | ||
@@ -154,8 +149,8 @@ int cx18_i2c_register(struct cx18 *cx, unsigned idx) | |||
154 | return sd != NULL ? 0 : -1; | 149 | return sd != NULL ? 0 : -1; |
155 | } | 150 | } |
156 | 151 | ||
157 | if (hw & CX18_HW_Z8F0811_IR_HAUP) | 152 | if (hw & CX18_HW_IR_ANY) |
158 | return cx18_i2c_new_ir(adap, hw, type, hw_addrs[idx]); | 153 | return cx18_i2c_new_ir(cx, adap, hw, type, hw_addrs[idx]); |
159 | 154 | ||
160 | /* Is it not an I2C device or one we do not wish to register? */ | 155 | /* Is it not an I2C device or one we do not wish to register? */ |
161 | if (!hw_addrs[idx]) | 156 | if (!hw_addrs[idx]) |
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index fc76e4d6ffa7..3e4fc192fdec 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c | |||
@@ -910,7 +910,8 @@ static int cx18_log_status(struct file *file, void *fh) | |||
910 | continue; | 910 | continue; |
911 | CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", | 911 | CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", |
912 | s->name, s->s_flags, | 912 | s->name, s->s_flags, |
913 | atomic_read(&s->q_full.buffers) * 100 / s->buffers, | 913 | atomic_read(&s->q_full.depth) * s->bufs_per_mdl * 100 |
914 | / s->buffers, | ||
914 | (s->buffers * s->buf_size) / 1024, s->buffers); | 915 | (s->buffers * s->buf_size) / 1024, s->buffers); |
915 | } | 916 | } |
916 | CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", | 917 | CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", |
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index afe46c3d4057..f231dd09c720 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c | |||
@@ -131,13 +131,39 @@ static void dump_mb(struct cx18 *cx, struct cx18_mailbox *mb, char *name) | |||
131 | * Functions that run in a work_queue work handling context | 131 | * Functions that run in a work_queue work handling context |
132 | */ | 132 | */ |
133 | 133 | ||
134 | static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl) | ||
135 | { | ||
136 | struct cx18_buffer *buf; | ||
137 | |||
138 | if (!s->dvb.enabled || mdl->bytesused == 0) | ||
139 | return; | ||
140 | |||
141 | /* We ignore mdl and buf readpos accounting here - it doesn't matter */ | ||
142 | |||
143 | /* The likely case */ | ||
144 | if (list_is_singular(&mdl->buf_list)) { | ||
145 | buf = list_first_entry(&mdl->buf_list, struct cx18_buffer, | ||
146 | list); | ||
147 | if (buf->bytesused) | ||
148 | dvb_dmx_swfilter(&s->dvb.demux, | ||
149 | buf->buf, buf->bytesused); | ||
150 | return; | ||
151 | } | ||
152 | |||
153 | list_for_each_entry(buf, &mdl->buf_list, list) { | ||
154 | if (buf->bytesused == 0) | ||
155 | break; | ||
156 | dvb_dmx_swfilter(&s->dvb.demux, buf->buf, buf->bytesused); | ||
157 | } | ||
158 | } | ||
159 | |||
134 | static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order) | 160 | static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order) |
135 | { | 161 | { |
136 | u32 handle, mdl_ack_count, id; | 162 | u32 handle, mdl_ack_count, id; |
137 | struct cx18_mailbox *mb; | 163 | struct cx18_mailbox *mb; |
138 | struct cx18_mdl_ack *mdl_ack; | 164 | struct cx18_mdl_ack *mdl_ack; |
139 | struct cx18_stream *s; | 165 | struct cx18_stream *s; |
140 | struct cx18_buffer *buf; | 166 | struct cx18_mdl *mdl; |
141 | int i; | 167 | int i; |
142 | 168 | ||
143 | mb = &order->mb; | 169 | mb = &order->mb; |
@@ -158,7 +184,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order) | |||
158 | id = mdl_ack->id; | 184 | id = mdl_ack->id; |
159 | /* | 185 | /* |
160 | * Simple integrity check for processing a stale (and possibly | 186 | * Simple integrity check for processing a stale (and possibly |
161 | * inconsistent mailbox): make sure the buffer id is in the | 187 | * inconsistent mailbox): make sure the MDL id is in the |
162 | * valid range for the stream. | 188 | * valid range for the stream. |
163 | * | 189 | * |
164 | * We go through the trouble of dealing with stale mailboxes | 190 | * We go through the trouble of dealing with stale mailboxes |
@@ -169,44 +195,42 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order) | |||
169 | * There are occasions when we get a half changed mailbox, | 195 | * There are occasions when we get a half changed mailbox, |
170 | * which this check catches for a handle & id mismatch. If the | 196 | * which this check catches for a handle & id mismatch. If the |
171 | * handle and id do correspond, the worst case is that we | 197 | * handle and id do correspond, the worst case is that we |
172 | * completely lost the old buffer, but pick up the new buffer | 198 | * completely lost the old MDL, but pick up the new MDL |
173 | * early (but the new mdl_ack is guaranteed to be good in this | 199 | * early (but the new mdl_ack is guaranteed to be good in this |
174 | * case as the firmware wouldn't point us to a new mdl_ack until | 200 | * case as the firmware wouldn't point us to a new mdl_ack until |
175 | * it's filled in). | 201 | * it's filled in). |
176 | * | 202 | * |
177 | * cx18_queue_get buf() will detect the lost buffers | 203 | * cx18_queue_get_mdl() will detect the lost MDLs |
178 | * and send them back to q_free for fw rotation eventually. | 204 | * and send them back to q_free for fw rotation eventually. |
179 | */ | 205 | */ |
180 | if ((order->flags & CX18_F_EWO_MB_STALE_UPON_RECEIPT) && | 206 | if ((order->flags & CX18_F_EWO_MB_STALE_UPON_RECEIPT) && |
181 | !(id >= s->mdl_offset && | 207 | !(id >= s->mdl_base_idx && |
182 | id < (s->mdl_offset + s->buffers))) { | 208 | id < (s->mdl_base_idx + s->buffers))) { |
183 | CX18_WARN("Fell behind! Ignoring stale mailbox with " | 209 | CX18_WARN("Fell behind! Ignoring stale mailbox with " |
184 | " inconsistent data. Lost buffer for mailbox " | 210 | " inconsistent data. Lost MDL for mailbox " |
185 | "seq no %d\n", mb->request); | 211 | "seq no %d\n", mb->request); |
186 | break; | 212 | break; |
187 | } | 213 | } |
188 | buf = cx18_queue_get_buf(s, id, mdl_ack->data_used); | 214 | mdl = cx18_queue_get_mdl(s, id, mdl_ack->data_used); |
189 | 215 | ||
190 | CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id); | 216 | CX18_DEBUG_HI_DMA("DMA DONE for %s (MDL %d)\n", s->name, id); |
191 | if (buf == NULL) { | 217 | if (mdl == NULL) { |
192 | CX18_WARN("Could not find buf %d for stream %s\n", | 218 | CX18_WARN("Could not find MDL %d for stream %s\n", |
193 | id, s->name); | 219 | id, s->name); |
194 | continue; | 220 | continue; |
195 | } | 221 | } |
196 | 222 | ||
197 | CX18_DEBUG_HI_DMA("%s recv bytesused = %d\n", | 223 | CX18_DEBUG_HI_DMA("%s recv bytesused = %d\n", |
198 | s->name, buf->bytesused); | 224 | s->name, mdl->bytesused); |
199 | 225 | ||
200 | if (s->type != CX18_ENC_STREAM_TYPE_TS) | 226 | if (s->type != CX18_ENC_STREAM_TYPE_TS) |
201 | cx18_enqueue(s, buf, &s->q_full); | 227 | cx18_enqueue(s, mdl, &s->q_full); |
202 | else { | 228 | else { |
203 | if (s->dvb.enabled) | 229 | cx18_mdl_send_to_dvb(s, mdl); |
204 | dvb_dmx_swfilter(&s->dvb.demux, buf->buf, | 230 | cx18_enqueue(s, mdl, &s->q_free); |
205 | buf->bytesused); | ||
206 | cx18_enqueue(s, buf, &s->q_free); | ||
207 | } | 231 | } |
208 | } | 232 | } |
209 | /* Put as many buffers as possible back into fw use */ | 233 | /* Put as many MDLs as possible back into fw use */ |
210 | cx18_stream_load_fw_queue(s); | 234 | cx18_stream_load_fw_queue(s); |
211 | 235 | ||
212 | wake_up(&cx->dma_waitq); | 236 | wake_up(&cx->dma_waitq); |
@@ -616,7 +640,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) | |||
616 | 640 | ||
617 | /* | 641 | /* |
618 | * Wait for XPU to perform extra actions for the caller in some cases. | 642 | * Wait for XPU to perform extra actions for the caller in some cases. |
619 | * e.g. CX18_CPU_DE_RELEASE_MDL will cause the CPU to send all buffers | 643 | * e.g. CX18_CPU_DE_RELEASE_MDL will cause the CPU to send all MDLs |
620 | * back in a burst shortly thereafter | 644 | * back in a burst shortly thereafter |
621 | */ | 645 | */ |
622 | if (info->flags & API_SLOW) | 646 | if (info->flags & API_SLOW) |
diff --git a/drivers/media/video/cx18/cx18-mailbox.h b/drivers/media/video/cx18/cx18-mailbox.h index 522ad534034c..33a3491c4537 100644 --- a/drivers/media/video/cx18/cx18-mailbox.h +++ b/drivers/media/video/cx18/cx18-mailbox.h | |||
@@ -39,14 +39,14 @@ | |||
39 | struct cx18; | 39 | struct cx18; |
40 | 40 | ||
41 | /* | 41 | /* |
42 | * This structure is used by CPU to provide completed buffers information | 42 | * This structure is used by CPU to provide completed MDL & buffers information. |
43 | * Its structure is dictrated by the layout of the SCB, required by the | 43 | * Its structure is dictated by the layout of the SCB, required by the |
44 | * firmware, but its definition needs to be here, instead of in cx18-scb.h, | 44 | * firmware, but its definition needs to be here, instead of in cx18-scb.h, |
45 | * for mailbox work order scheduling | 45 | * for mailbox work order scheduling |
46 | */ | 46 | */ |
47 | struct cx18_mdl_ack { | 47 | struct cx18_mdl_ack { |
48 | u32 id; /* ID of a completed MDL */ | 48 | u32 id; /* ID of a completed MDL */ |
49 | u32 data_used; /* Total data filled in the MDL for buffer 'id' */ | 49 | u32 data_used; /* Total data filled in the MDL with 'id' */ |
50 | }; | 50 | }; |
51 | 51 | ||
52 | /* The cx18_mailbox struct is the mailbox structure which is used for passing | 52 | /* The cx18_mailbox struct is the mailbox structure which is used for passing |
diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index fa1ed7897d97..63304823cef5 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "cx18-queue.h" | 26 | #include "cx18-queue.h" |
27 | #include "cx18-streams.h" | 27 | #include "cx18-streams.h" |
28 | #include "cx18-scb.h" | 28 | #include "cx18-scb.h" |
29 | #include "cx18-io.h" | ||
29 | 30 | ||
30 | void cx18_buf_swap(struct cx18_buffer *buf) | 31 | void cx18_buf_swap(struct cx18_buffer *buf) |
31 | { | 32 | { |
@@ -35,151 +36,312 @@ void cx18_buf_swap(struct cx18_buffer *buf) | |||
35 | swab32s((u32 *)(buf->buf + i)); | 36 | swab32s((u32 *)(buf->buf + i)); |
36 | } | 37 | } |
37 | 38 | ||
39 | void _cx18_mdl_swap(struct cx18_mdl *mdl) | ||
40 | { | ||
41 | struct cx18_buffer *buf; | ||
42 | |||
43 | list_for_each_entry(buf, &mdl->buf_list, list) { | ||
44 | if (buf->bytesused == 0) | ||
45 | break; | ||
46 | cx18_buf_swap(buf); | ||
47 | } | ||
48 | } | ||
49 | |||
38 | void cx18_queue_init(struct cx18_queue *q) | 50 | void cx18_queue_init(struct cx18_queue *q) |
39 | { | 51 | { |
40 | INIT_LIST_HEAD(&q->list); | 52 | INIT_LIST_HEAD(&q->list); |
41 | atomic_set(&q->buffers, 0); | 53 | atomic_set(&q->depth, 0); |
42 | q->bytesused = 0; | 54 | q->bytesused = 0; |
43 | } | 55 | } |
44 | 56 | ||
45 | struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, | 57 | struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_mdl *mdl, |
46 | struct cx18_queue *q, int to_front) | 58 | struct cx18_queue *q, int to_front) |
47 | { | 59 | { |
48 | /* clear the buffer if it is not to be enqueued to the full queue */ | 60 | /* clear the mdl if it is not to be enqueued to the full queue */ |
49 | if (q != &s->q_full) { | 61 | if (q != &s->q_full) { |
50 | buf->bytesused = 0; | 62 | mdl->bytesused = 0; |
51 | buf->readpos = 0; | 63 | mdl->readpos = 0; |
52 | buf->b_flags = 0; | 64 | mdl->m_flags = 0; |
53 | buf->skipped = 0; | 65 | mdl->skipped = 0; |
66 | mdl->curr_buf = NULL; | ||
54 | } | 67 | } |
55 | 68 | ||
56 | /* q_busy is restricted to a max buffer count imposed by firmware */ | 69 | /* q_busy is restricted to a max buffer count imposed by firmware */ |
57 | if (q == &s->q_busy && | 70 | if (q == &s->q_busy && |
58 | atomic_read(&q->buffers) >= CX18_MAX_FW_MDLS_PER_STREAM) | 71 | atomic_read(&q->depth) >= CX18_MAX_FW_MDLS_PER_STREAM) |
59 | q = &s->q_free; | 72 | q = &s->q_free; |
60 | 73 | ||
61 | spin_lock(&q->lock); | 74 | spin_lock(&q->lock); |
62 | 75 | ||
63 | if (to_front) | 76 | if (to_front) |
64 | list_add(&buf->list, &q->list); /* LIFO */ | 77 | list_add(&mdl->list, &q->list); /* LIFO */ |
65 | else | 78 | else |
66 | list_add_tail(&buf->list, &q->list); /* FIFO */ | 79 | list_add_tail(&mdl->list, &q->list); /* FIFO */ |
67 | q->bytesused += buf->bytesused - buf->readpos; | 80 | q->bytesused += mdl->bytesused - mdl->readpos; |
68 | atomic_inc(&q->buffers); | 81 | atomic_inc(&q->depth); |
69 | 82 | ||
70 | spin_unlock(&q->lock); | 83 | spin_unlock(&q->lock); |
71 | return q; | 84 | return q; |
72 | } | 85 | } |
73 | 86 | ||
74 | struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) | 87 | struct cx18_mdl *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) |
75 | { | 88 | { |
76 | struct cx18_buffer *buf = NULL; | 89 | struct cx18_mdl *mdl = NULL; |
77 | 90 | ||
78 | spin_lock(&q->lock); | 91 | spin_lock(&q->lock); |
79 | if (!list_empty(&q->list)) { | 92 | if (!list_empty(&q->list)) { |
80 | buf = list_first_entry(&q->list, struct cx18_buffer, list); | 93 | mdl = list_first_entry(&q->list, struct cx18_mdl, list); |
81 | list_del_init(&buf->list); | 94 | list_del_init(&mdl->list); |
82 | q->bytesused -= buf->bytesused - buf->readpos; | 95 | q->bytesused -= mdl->bytesused - mdl->readpos; |
83 | buf->skipped = 0; | 96 | mdl->skipped = 0; |
84 | atomic_dec(&q->buffers); | 97 | atomic_dec(&q->depth); |
85 | } | 98 | } |
86 | spin_unlock(&q->lock); | 99 | spin_unlock(&q->lock); |
87 | return buf; | 100 | return mdl; |
101 | } | ||
102 | |||
103 | static void _cx18_mdl_update_bufs_for_cpu(struct cx18_stream *s, | ||
104 | struct cx18_mdl *mdl) | ||
105 | { | ||
106 | struct cx18_buffer *buf; | ||
107 | u32 buf_size = s->buf_size; | ||
108 | u32 bytesused = mdl->bytesused; | ||
109 | |||
110 | list_for_each_entry(buf, &mdl->buf_list, list) { | ||
111 | buf->readpos = 0; | ||
112 | if (bytesused >= buf_size) { | ||
113 | buf->bytesused = buf_size; | ||
114 | bytesused -= buf_size; | ||
115 | } else { | ||
116 | buf->bytesused = bytesused; | ||
117 | bytesused = 0; | ||
118 | } | ||
119 | cx18_buf_sync_for_cpu(s, buf); | ||
120 | } | ||
121 | } | ||
122 | |||
123 | static inline void cx18_mdl_update_bufs_for_cpu(struct cx18_stream *s, | ||
124 | struct cx18_mdl *mdl) | ||
125 | { | ||
126 | struct cx18_buffer *buf; | ||
127 | |||
128 | if (list_is_singular(&mdl->buf_list)) { | ||
129 | buf = list_first_entry(&mdl->buf_list, struct cx18_buffer, | ||
130 | list); | ||
131 | buf->bytesused = mdl->bytesused; | ||
132 | buf->readpos = 0; | ||
133 | cx18_buf_sync_for_cpu(s, buf); | ||
134 | } else { | ||
135 | _cx18_mdl_update_bufs_for_cpu(s, mdl); | ||
136 | } | ||
88 | } | 137 | } |
89 | 138 | ||
90 | struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, | 139 | struct cx18_mdl *cx18_queue_get_mdl(struct cx18_stream *s, u32 id, |
91 | u32 bytesused) | 140 | u32 bytesused) |
92 | { | 141 | { |
93 | struct cx18 *cx = s->cx; | 142 | struct cx18 *cx = s->cx; |
94 | struct cx18_buffer *buf; | 143 | struct cx18_mdl *mdl; |
95 | struct cx18_buffer *tmp; | 144 | struct cx18_mdl *tmp; |
96 | struct cx18_buffer *ret = NULL; | 145 | struct cx18_mdl *ret = NULL; |
97 | LIST_HEAD(sweep_up); | 146 | LIST_HEAD(sweep_up); |
98 | 147 | ||
99 | /* | 148 | /* |
100 | * We don't have to acquire multiple q locks here, because we are | 149 | * We don't have to acquire multiple q locks here, because we are |
101 | * serialized by the single threaded work handler. | 150 | * serialized by the single threaded work handler. |
102 | * Buffers from the firmware will thus remain in order as | 151 | * MDLs from the firmware will thus remain in order as |
103 | * they are moved from q_busy to q_full or to the dvb ring buffer. | 152 | * they are moved from q_busy to q_full or to the dvb ring buffer. |
104 | */ | 153 | */ |
105 | spin_lock(&s->q_busy.lock); | 154 | spin_lock(&s->q_busy.lock); |
106 | list_for_each_entry_safe(buf, tmp, &s->q_busy.list, list) { | 155 | list_for_each_entry_safe(mdl, tmp, &s->q_busy.list, list) { |
107 | /* | 156 | /* |
108 | * We should find what the firmware told us is done, | 157 | * We should find what the firmware told us is done, |
109 | * right at the front of the queue. If we don't, we likely have | 158 | * right at the front of the queue. If we don't, we likely have |
110 | * missed a buffer done message from the firmware. | 159 | * missed an mdl done message from the firmware. |
111 | * Once we skip a buffer repeatedly, relative to the size of | 160 | * Once we skip an mdl repeatedly, relative to the size of |
112 | * q_busy, we have high confidence we've missed it. | 161 | * q_busy, we have high confidence we've missed it. |
113 | */ | 162 | */ |
114 | if (buf->id != id) { | 163 | if (mdl->id != id) { |
115 | buf->skipped++; | 164 | mdl->skipped++; |
116 | if (buf->skipped >= atomic_read(&s->q_busy.buffers)-1) { | 165 | if (mdl->skipped >= atomic_read(&s->q_busy.depth)-1) { |
117 | /* buffer must have fallen out of rotation */ | 166 | /* mdl must have fallen out of rotation */ |
118 | CX18_WARN("Skipped %s, buffer %d, %d " | 167 | CX18_WARN("Skipped %s, MDL %d, %d " |
119 | "times - it must have dropped out of " | 168 | "times - it must have dropped out of " |
120 | "rotation\n", s->name, buf->id, | 169 | "rotation\n", s->name, mdl->id, |
121 | buf->skipped); | 170 | mdl->skipped); |
122 | /* Sweep it up to put it back into rotation */ | 171 | /* Sweep it up to put it back into rotation */ |
123 | list_move_tail(&buf->list, &sweep_up); | 172 | list_move_tail(&mdl->list, &sweep_up); |
124 | atomic_dec(&s->q_busy.buffers); | 173 | atomic_dec(&s->q_busy.depth); |
125 | } | 174 | } |
126 | continue; | 175 | continue; |
127 | } | 176 | } |
128 | /* | 177 | /* |
129 | * We pull the desired buffer off of the queue here. Something | 178 | * We pull the desired mdl off of the queue here. Something |
130 | * will have to put it back on a queue later. | 179 | * will have to put it back on a queue later. |
131 | */ | 180 | */ |
132 | list_del_init(&buf->list); | 181 | list_del_init(&mdl->list); |
133 | atomic_dec(&s->q_busy.buffers); | 182 | atomic_dec(&s->q_busy.depth); |
134 | ret = buf; | 183 | ret = mdl; |
135 | break; | 184 | break; |
136 | } | 185 | } |
137 | spin_unlock(&s->q_busy.lock); | 186 | spin_unlock(&s->q_busy.lock); |
138 | 187 | ||
139 | /* | 188 | /* |
140 | * We found the buffer for which we were looking. Get it ready for | 189 | * We found the mdl for which we were looking. Get it ready for |
141 | * the caller to put on q_full or in the dvb ring buffer. | 190 | * the caller to put on q_full or in the dvb ring buffer. |
142 | */ | 191 | */ |
143 | if (ret != NULL) { | 192 | if (ret != NULL) { |
144 | ret->bytesused = bytesused; | 193 | ret->bytesused = bytesused; |
145 | ret->skipped = 0; | 194 | ret->skipped = 0; |
146 | /* readpos and b_flags were 0'ed when the buf went on q_busy */ | 195 | /* 0'ed readpos, m_flags & curr_buf when mdl went on q_busy */ |
147 | cx18_buf_sync_for_cpu(s, ret); | 196 | cx18_mdl_update_bufs_for_cpu(s, ret); |
148 | if (s->type != CX18_ENC_STREAM_TYPE_TS) | 197 | if (s->type != CX18_ENC_STREAM_TYPE_TS) |
149 | set_bit(CX18_F_B_NEED_BUF_SWAP, &ret->b_flags); | 198 | set_bit(CX18_F_M_NEED_SWAP, &ret->m_flags); |
150 | } | 199 | } |
151 | 200 | ||
152 | /* Put any buffers the firmware is ignoring back into normal rotation */ | 201 | /* Put any mdls the firmware is ignoring back into normal rotation */ |
153 | list_for_each_entry_safe(buf, tmp, &sweep_up, list) { | 202 | list_for_each_entry_safe(mdl, tmp, &sweep_up, list) { |
154 | list_del_init(&buf->list); | 203 | list_del_init(&mdl->list); |
155 | cx18_enqueue(s, buf, &s->q_free); | 204 | cx18_enqueue(s, mdl, &s->q_free); |
156 | } | 205 | } |
157 | return ret; | 206 | return ret; |
158 | } | 207 | } |
159 | 208 | ||
160 | /* Move all buffers of a queue to q_free, while flushing the buffers */ | 209 | /* Move all mdls of a queue, while flushing the mdl */ |
161 | static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q) | 210 | static void cx18_queue_flush(struct cx18_stream *s, |
211 | struct cx18_queue *q_src, struct cx18_queue *q_dst) | ||
162 | { | 212 | { |
163 | struct cx18_buffer *buf; | 213 | struct cx18_mdl *mdl; |
164 | 214 | ||
165 | if (q == &s->q_free) | 215 | /* It only makes sense to flush to q_free or q_idle */ |
216 | if (q_src == q_dst || q_dst == &s->q_full || q_dst == &s->q_busy) | ||
166 | return; | 217 | return; |
167 | 218 | ||
168 | spin_lock(&q->lock); | 219 | spin_lock(&q_src->lock); |
169 | while (!list_empty(&q->list)) { | 220 | spin_lock(&q_dst->lock); |
170 | buf = list_first_entry(&q->list, struct cx18_buffer, list); | 221 | while (!list_empty(&q_src->list)) { |
171 | list_move_tail(&buf->list, &s->q_free.list); | 222 | mdl = list_first_entry(&q_src->list, struct cx18_mdl, list); |
172 | buf->bytesused = buf->readpos = buf->b_flags = buf->skipped = 0; | 223 | list_move_tail(&mdl->list, &q_dst->list); |
173 | atomic_inc(&s->q_free.buffers); | 224 | mdl->bytesused = 0; |
225 | mdl->readpos = 0; | ||
226 | mdl->m_flags = 0; | ||
227 | mdl->skipped = 0; | ||
228 | mdl->curr_buf = NULL; | ||
229 | atomic_inc(&q_dst->depth); | ||
174 | } | 230 | } |
175 | cx18_queue_init(q); | 231 | cx18_queue_init(q_src); |
176 | spin_unlock(&q->lock); | 232 | spin_unlock(&q_src->lock); |
233 | spin_unlock(&q_dst->lock); | ||
177 | } | 234 | } |
178 | 235 | ||
179 | void cx18_flush_queues(struct cx18_stream *s) | 236 | void cx18_flush_queues(struct cx18_stream *s) |
180 | { | 237 | { |
181 | cx18_queue_flush(s, &s->q_busy); | 238 | cx18_queue_flush(s, &s->q_busy, &s->q_free); |
182 | cx18_queue_flush(s, &s->q_full); | 239 | cx18_queue_flush(s, &s->q_full, &s->q_free); |
240 | } | ||
241 | |||
242 | /* | ||
243 | * Note, s->buf_pool is not protected by a lock, | ||
244 | * the stream better not have *anything* going on when calling this | ||
245 | */ | ||
246 | void cx18_unload_queues(struct cx18_stream *s) | ||
247 | { | ||
248 | struct cx18_queue *q_idle = &s->q_idle; | ||
249 | struct cx18_mdl *mdl; | ||
250 | struct cx18_buffer *buf; | ||
251 | |||
252 | /* Move all MDLS to q_idle */ | ||
253 | cx18_queue_flush(s, &s->q_busy, q_idle); | ||
254 | cx18_queue_flush(s, &s->q_full, q_idle); | ||
255 | cx18_queue_flush(s, &s->q_free, q_idle); | ||
256 | |||
257 | /* Reset MDL id's and move all buffers back to the stream's buf_pool */ | ||
258 | spin_lock(&q_idle->lock); | ||
259 | list_for_each_entry(mdl, &q_idle->list, list) { | ||
260 | while (!list_empty(&mdl->buf_list)) { | ||
261 | buf = list_first_entry(&mdl->buf_list, | ||
262 | struct cx18_buffer, list); | ||
263 | list_move_tail(&buf->list, &s->buf_pool); | ||
264 | buf->bytesused = 0; | ||
265 | buf->readpos = 0; | ||
266 | } | ||
267 | mdl->id = s->mdl_base_idx; /* reset id to a "safe" value */ | ||
268 | /* all other mdl fields were cleared by cx18_queue_flush() */ | ||
269 | } | ||
270 | spin_unlock(&q_idle->lock); | ||
271 | } | ||
272 | |||
273 | /* | ||
274 | * Note, s->buf_pool is not protected by a lock, | ||
275 | * the stream better not have *anything* going on when calling this | ||
276 | */ | ||
277 | void cx18_load_queues(struct cx18_stream *s) | ||
278 | { | ||
279 | struct cx18 *cx = s->cx; | ||
280 | struct cx18_mdl *mdl; | ||
281 | struct cx18_buffer *buf; | ||
282 | int mdl_id; | ||
283 | int i; | ||
284 | u32 partial_buf_size; | ||
285 | |||
286 | /* | ||
287 | * Attach buffers to MDLs, give the MDLs ids, and add MDLs to q_free | ||
288 | * Excess MDLs are left on q_idle | ||
289 | * Excess buffers are left in buf_pool and/or on an MDL in q_idle | ||
290 | */ | ||
291 | mdl_id = s->mdl_base_idx; | ||
292 | for (mdl = cx18_dequeue(s, &s->q_idle), i = s->bufs_per_mdl; | ||
293 | mdl != NULL && i == s->bufs_per_mdl; | ||
294 | mdl = cx18_dequeue(s, &s->q_idle)) { | ||
295 | |||
296 | mdl->id = mdl_id; | ||
297 | |||
298 | for (i = 0; i < s->bufs_per_mdl; i++) { | ||
299 | if (list_empty(&s->buf_pool)) | ||
300 | break; | ||
301 | |||
302 | buf = list_first_entry(&s->buf_pool, struct cx18_buffer, | ||
303 | list); | ||
304 | list_move_tail(&buf->list, &mdl->buf_list); | ||
305 | |||
306 | /* update the firmware's MDL array with this buffer */ | ||
307 | cx18_writel(cx, buf->dma_handle, | ||
308 | &cx->scb->cpu_mdl[mdl_id + i].paddr); | ||
309 | cx18_writel(cx, s->buf_size, | ||
310 | &cx->scb->cpu_mdl[mdl_id + i].length); | ||
311 | } | ||
312 | |||
313 | if (i == s->bufs_per_mdl) { | ||
314 | /* | ||
315 | * The encoder doesn't honor s->mdl_size. So in the | ||
316 | * case of a non-integral number of buffers to meet | ||
317 | * mdl_size, we lie about the size of the last buffer | ||
318 | * in the MDL to get the encoder to really only send | ||
319 | * us mdl_size bytes per MDL transfer. | ||
320 | */ | ||
321 | partial_buf_size = s->mdl_size % s->buf_size; | ||
322 | if (partial_buf_size) { | ||
323 | cx18_writel(cx, partial_buf_size, | ||
324 | &cx->scb->cpu_mdl[mdl_id + i - 1].length); | ||
325 | } | ||
326 | cx18_enqueue(s, mdl, &s->q_free); | ||
327 | } else { | ||
328 | /* Not enough buffers for this MDL; we won't use it */ | ||
329 | cx18_push(s, mdl, &s->q_idle); | ||
330 | } | ||
331 | mdl_id += i; | ||
332 | } | ||
333 | } | ||
334 | |||
335 | void _cx18_mdl_sync_for_device(struct cx18_stream *s, struct cx18_mdl *mdl) | ||
336 | { | ||
337 | int dma = s->dma; | ||
338 | u32 buf_size = s->buf_size; | ||
339 | struct pci_dev *pci_dev = s->cx->pci_dev; | ||
340 | struct cx18_buffer *buf; | ||
341 | |||
342 | list_for_each_entry(buf, &mdl->buf_list, list) | ||
343 | pci_dma_sync_single_for_device(pci_dev, buf->dma_handle, | ||
344 | buf_size, dma); | ||
183 | } | 345 | } |
184 | 346 | ||
185 | int cx18_stream_alloc(struct cx18_stream *s) | 347 | int cx18_stream_alloc(struct cx18_stream *s) |
@@ -190,44 +352,62 @@ int cx18_stream_alloc(struct cx18_stream *s) | |||
190 | if (s->buffers == 0) | 352 | if (s->buffers == 0) |
191 | return 0; | 353 | return 0; |
192 | 354 | ||
193 | CX18_DEBUG_INFO("Allocate %s stream: %d x %d buffers (%dkB total)\n", | 355 | CX18_DEBUG_INFO("Allocate %s stream: %d x %d buffers " |
356 | "(%d.%02d kB total)\n", | ||
194 | s->name, s->buffers, s->buf_size, | 357 | s->name, s->buffers, s->buf_size, |
195 | s->buffers * s->buf_size / 1024); | 358 | s->buffers * s->buf_size / 1024, |
359 | (s->buffers * s->buf_size * 100 / 1024) % 100); | ||
196 | 360 | ||
197 | if (((char __iomem *)&cx->scb->cpu_mdl[cx->mdl_offset + s->buffers] - | 361 | if (((char __iomem *)&cx->scb->cpu_mdl[cx->free_mdl_idx + s->buffers] - |
198 | (char __iomem *)cx->scb) > SCB_RESERVED_SIZE) { | 362 | (char __iomem *)cx->scb) > SCB_RESERVED_SIZE) { |
199 | unsigned bufsz = (((char __iomem *)cx->scb) + SCB_RESERVED_SIZE - | 363 | unsigned bufsz = (((char __iomem *)cx->scb) + SCB_RESERVED_SIZE - |
200 | ((char __iomem *)cx->scb->cpu_mdl)); | 364 | ((char __iomem *)cx->scb->cpu_mdl)); |
201 | 365 | ||
202 | CX18_ERR("Too many buffers, cannot fit in SCB area\n"); | 366 | CX18_ERR("Too many buffers, cannot fit in SCB area\n"); |
203 | CX18_ERR("Max buffers = %zd\n", | 367 | CX18_ERR("Max buffers = %zd\n", |
204 | bufsz / sizeof(struct cx18_mdl)); | 368 | bufsz / sizeof(struct cx18_mdl_ent)); |
205 | return -ENOMEM; | 369 | return -ENOMEM; |
206 | } | 370 | } |
207 | 371 | ||
208 | s->mdl_offset = cx->mdl_offset; | 372 | s->mdl_base_idx = cx->free_mdl_idx; |
209 | 373 | ||
210 | /* allocate stream buffers. Initially all buffers are in q_free. */ | 374 | /* allocate stream buffers and MDLs */ |
211 | for (i = 0; i < s->buffers; i++) { | 375 | for (i = 0; i < s->buffers; i++) { |
212 | struct cx18_buffer *buf = kzalloc(sizeof(struct cx18_buffer), | 376 | struct cx18_mdl *mdl; |
213 | GFP_KERNEL|__GFP_NOWARN); | 377 | struct cx18_buffer *buf; |
214 | 378 | ||
215 | if (buf == NULL) | 379 | /* 1 MDL per buffer to handle the worst & also default case */ |
380 | mdl = kzalloc(sizeof(struct cx18_mdl), GFP_KERNEL|__GFP_NOWARN); | ||
381 | if (mdl == NULL) | ||
216 | break; | 382 | break; |
383 | |||
384 | buf = kzalloc(sizeof(struct cx18_buffer), | ||
385 | GFP_KERNEL|__GFP_NOWARN); | ||
386 | if (buf == NULL) { | ||
387 | kfree(mdl); | ||
388 | break; | ||
389 | } | ||
390 | |||
217 | buf->buf = kmalloc(s->buf_size, GFP_KERNEL|__GFP_NOWARN); | 391 | buf->buf = kmalloc(s->buf_size, GFP_KERNEL|__GFP_NOWARN); |
218 | if (buf->buf == NULL) { | 392 | if (buf->buf == NULL) { |
393 | kfree(mdl); | ||
219 | kfree(buf); | 394 | kfree(buf); |
220 | break; | 395 | break; |
221 | } | 396 | } |
222 | buf->id = cx->buffer_id++; | 397 | |
398 | INIT_LIST_HEAD(&mdl->list); | ||
399 | INIT_LIST_HEAD(&mdl->buf_list); | ||
400 | mdl->id = s->mdl_base_idx; /* a somewhat safe value */ | ||
401 | cx18_enqueue(s, mdl, &s->q_idle); | ||
402 | |||
223 | INIT_LIST_HEAD(&buf->list); | 403 | INIT_LIST_HEAD(&buf->list); |
224 | buf->dma_handle = pci_map_single(s->cx->pci_dev, | 404 | buf->dma_handle = pci_map_single(s->cx->pci_dev, |
225 | buf->buf, s->buf_size, s->dma); | 405 | buf->buf, s->buf_size, s->dma); |
226 | cx18_buf_sync_for_cpu(s, buf); | 406 | cx18_buf_sync_for_cpu(s, buf); |
227 | cx18_enqueue(s, buf, &s->q_free); | 407 | list_add_tail(&buf->list, &s->buf_pool); |
228 | } | 408 | } |
229 | if (i == s->buffers) { | 409 | if (i == s->buffers) { |
230 | cx->mdl_offset += s->buffers; | 410 | cx->free_mdl_idx += s->buffers; |
231 | return 0; | 411 | return 0; |
232 | } | 412 | } |
233 | CX18_ERR("Couldn't allocate buffers for %s stream\n", s->name); | 413 | CX18_ERR("Couldn't allocate buffers for %s stream\n", s->name); |
@@ -237,13 +417,21 @@ int cx18_stream_alloc(struct cx18_stream *s) | |||
237 | 417 | ||
238 | void cx18_stream_free(struct cx18_stream *s) | 418 | void cx18_stream_free(struct cx18_stream *s) |
239 | { | 419 | { |
420 | struct cx18_mdl *mdl; | ||
240 | struct cx18_buffer *buf; | 421 | struct cx18_buffer *buf; |
241 | 422 | ||
242 | /* move all buffers to q_free */ | 423 | /* move all buffers to buf_pool and all MDLs to q_idle */ |
243 | cx18_flush_queues(s); | 424 | cx18_unload_queues(s); |
425 | |||
426 | /* empty q_idle */ | ||
427 | while ((mdl = cx18_dequeue(s, &s->q_idle))) | ||
428 | kfree(mdl); | ||
429 | |||
430 | /* empty buf_pool */ | ||
431 | while (!list_empty(&s->buf_pool)) { | ||
432 | buf = list_first_entry(&s->buf_pool, struct cx18_buffer, list); | ||
433 | list_del_init(&buf->list); | ||
244 | 434 | ||
245 | /* empty q_free */ | ||
246 | while ((buf = cx18_dequeue(s, &s->q_free))) { | ||
247 | pci_unmap_single(s->cx->pci_dev, buf->dma_handle, | 435 | pci_unmap_single(s->cx->pci_dev, buf->dma_handle, |
248 | s->buf_size, s->dma); | 436 | s->buf_size, s->dma); |
249 | kfree(buf->buf); | 437 | kfree(buf->buf); |
diff --git a/drivers/media/video/cx18/cx18-queue.h b/drivers/media/video/cx18/cx18-queue.h index 4de06269d88f..88a6d34ad3bb 100644 --- a/drivers/media/video/cx18/cx18-queue.h +++ b/drivers/media/video/cx18/cx18-queue.h | |||
@@ -40,32 +40,59 @@ static inline void cx18_buf_sync_for_device(struct cx18_stream *s, | |||
40 | s->buf_size, s->dma); | 40 | s->buf_size, s->dma); |
41 | } | 41 | } |
42 | 42 | ||
43 | void _cx18_mdl_sync_for_device(struct cx18_stream *s, struct cx18_mdl *mdl); | ||
44 | |||
45 | static inline void cx18_mdl_sync_for_device(struct cx18_stream *s, | ||
46 | struct cx18_mdl *mdl) | ||
47 | { | ||
48 | if (list_is_singular(&mdl->buf_list)) | ||
49 | cx18_buf_sync_for_device(s, list_first_entry(&mdl->buf_list, | ||
50 | struct cx18_buffer, | ||
51 | list)); | ||
52 | else | ||
53 | _cx18_mdl_sync_for_device(s, mdl); | ||
54 | } | ||
55 | |||
43 | void cx18_buf_swap(struct cx18_buffer *buf); | 56 | void cx18_buf_swap(struct cx18_buffer *buf); |
57 | void _cx18_mdl_swap(struct cx18_mdl *mdl); | ||
58 | |||
59 | static inline void cx18_mdl_swap(struct cx18_mdl *mdl) | ||
60 | { | ||
61 | if (list_is_singular(&mdl->buf_list)) | ||
62 | cx18_buf_swap(list_first_entry(&mdl->buf_list, | ||
63 | struct cx18_buffer, list)); | ||
64 | else | ||
65 | _cx18_mdl_swap(mdl); | ||
66 | } | ||
44 | 67 | ||
45 | /* cx18_queue utility functions */ | 68 | /* cx18_queue utility functions */ |
46 | struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, | 69 | struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_mdl *mdl, |
47 | struct cx18_queue *q, int to_front); | 70 | struct cx18_queue *q, int to_front); |
48 | 71 | ||
49 | static inline | 72 | static inline |
50 | struct cx18_queue *cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, | 73 | struct cx18_queue *cx18_enqueue(struct cx18_stream *s, struct cx18_mdl *mdl, |
51 | struct cx18_queue *q) | 74 | struct cx18_queue *q) |
52 | { | 75 | { |
53 | return _cx18_enqueue(s, buf, q, 0); /* FIFO */ | 76 | return _cx18_enqueue(s, mdl, q, 0); /* FIFO */ |
54 | } | 77 | } |
55 | 78 | ||
56 | static inline | 79 | static inline |
57 | struct cx18_queue *cx18_push(struct cx18_stream *s, struct cx18_buffer *buf, | 80 | struct cx18_queue *cx18_push(struct cx18_stream *s, struct cx18_mdl *mdl, |
58 | struct cx18_queue *q) | 81 | struct cx18_queue *q) |
59 | { | 82 | { |
60 | return _cx18_enqueue(s, buf, q, 1); /* LIFO */ | 83 | return _cx18_enqueue(s, mdl, q, 1); /* LIFO */ |
61 | } | 84 | } |
62 | 85 | ||
63 | void cx18_queue_init(struct cx18_queue *q); | 86 | void cx18_queue_init(struct cx18_queue *q); |
64 | struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q); | 87 | struct cx18_mdl *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q); |
65 | struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, | 88 | struct cx18_mdl *cx18_queue_get_mdl(struct cx18_stream *s, u32 id, |
66 | u32 bytesused); | 89 | u32 bytesused); |
67 | void cx18_flush_queues(struct cx18_stream *s); | 90 | void cx18_flush_queues(struct cx18_stream *s); |
68 | 91 | ||
92 | /* queue MDL reconfiguration helpers */ | ||
93 | void cx18_unload_queues(struct cx18_stream *s); | ||
94 | void cx18_load_queues(struct cx18_stream *s); | ||
95 | |||
69 | /* cx18_stream utility functions */ | 96 | /* cx18_stream utility functions */ |
70 | int cx18_stream_alloc(struct cx18_stream *s); | 97 | int cx18_stream_alloc(struct cx18_stream *s); |
71 | void cx18_stream_free(struct cx18_stream *s); | 98 | void cx18_stream_free(struct cx18_stream *s); |
diff --git a/drivers/media/video/cx18/cx18-scb.h b/drivers/media/video/cx18/cx18-scb.h index 1dc1c431f5a1..368f23d08709 100644 --- a/drivers/media/video/cx18/cx18-scb.h +++ b/drivers/media/video/cx18/cx18-scb.h | |||
@@ -81,7 +81,7 @@ | |||
81 | 81 | ||
82 | 82 | ||
83 | /* This structure is used by EPU to provide memory descriptors in its memory */ | 83 | /* This structure is used by EPU to provide memory descriptors in its memory */ |
84 | struct cx18_mdl { | 84 | struct cx18_mdl_ent { |
85 | u32 paddr; /* Physical address of a buffer segment */ | 85 | u32 paddr; /* Physical address of a buffer segment */ |
86 | u32 length; /* Length of the buffer segment */ | 86 | u32 length; /* Length of the buffer segment */ |
87 | }; | 87 | }; |
@@ -272,7 +272,7 @@ struct cx18_scb { | |||
272 | struct cx18_mailbox ppu2epu_mb; | 272 | struct cx18_mailbox ppu2epu_mb; |
273 | 273 | ||
274 | struct cx18_mdl_ack cpu_mdl_ack[CX18_MAX_STREAMS][CX18_MAX_MDL_ACKS]; | 274 | struct cx18_mdl_ack cpu_mdl_ack[CX18_MAX_STREAMS][CX18_MAX_MDL_ACKS]; |
275 | struct cx18_mdl cpu_mdl[1]; | 275 | struct cx18_mdl_ent cpu_mdl[1]; |
276 | }; | 276 | }; |
277 | 277 | ||
278 | void cx18_init_scb(struct cx18 *cx); | 278 | void cx18_init_scb(struct cx18 *cx); |
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 7df513a2dba8..c398651dd74c 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c | |||
@@ -115,6 +115,9 @@ static void cx18_stream_init(struct cx18 *cx, int type) | |||
115 | s->dma = cx18_stream_info[type].dma; | 115 | s->dma = cx18_stream_info[type].dma; |
116 | s->buffers = cx->stream_buffers[type]; | 116 | s->buffers = cx->stream_buffers[type]; |
117 | s->buf_size = cx->stream_buf_size[type]; | 117 | s->buf_size = cx->stream_buf_size[type]; |
118 | INIT_LIST_HEAD(&s->buf_pool); | ||
119 | s->bufs_per_mdl = 1; | ||
120 | s->mdl_size = s->buf_size * s->bufs_per_mdl; | ||
118 | 121 | ||
119 | init_waitqueue_head(&s->waitq); | 122 | init_waitqueue_head(&s->waitq); |
120 | s->id = -1; | 123 | s->id = -1; |
@@ -124,6 +127,8 @@ static void cx18_stream_init(struct cx18 *cx, int type) | |||
124 | cx18_queue_init(&s->q_busy); | 127 | cx18_queue_init(&s->q_busy); |
125 | spin_lock_init(&s->q_full.lock); | 128 | spin_lock_init(&s->q_full.lock); |
126 | cx18_queue_init(&s->q_full); | 129 | cx18_queue_init(&s->q_full); |
130 | spin_lock_init(&s->q_idle.lock); | ||
131 | cx18_queue_init(&s->q_idle); | ||
127 | 132 | ||
128 | INIT_WORK(&s->out_work_order, cx18_out_work_handler); | 133 | INIT_WORK(&s->out_work_order, cx18_out_work_handler); |
129 | } | 134 | } |
@@ -257,9 +262,11 @@ static int cx18_reg_dev(struct cx18 *cx, int type) | |||
257 | 262 | ||
258 | switch (vfl_type) { | 263 | switch (vfl_type) { |
259 | case VFL_TYPE_GRABBER: | 264 | case VFL_TYPE_GRABBER: |
260 | CX18_INFO("Registered device video%d for %s (%d x %d kB)\n", | 265 | CX18_INFO("Registered device video%d for %s " |
266 | "(%d x %d.%02d kB)\n", | ||
261 | num, s->name, cx->stream_buffers[type], | 267 | num, s->name, cx->stream_buffers[type], |
262 | cx->stream_buf_size[type]/1024); | 268 | cx->stream_buf_size[type] / 1024, |
269 | (cx->stream_buf_size[type] * 100 / 1024) % 100); | ||
263 | break; | 270 | break; |
264 | 271 | ||
265 | case VFL_TYPE_RADIO: | 272 | case VFL_TYPE_RADIO: |
@@ -441,8 +448,8 @@ static void cx18_vbi_setup(struct cx18_stream *s) | |||
441 | } | 448 | } |
442 | 449 | ||
443 | static | 450 | static |
444 | struct cx18_queue *_cx18_stream_put_buf_fw(struct cx18_stream *s, | 451 | struct cx18_queue *_cx18_stream_put_mdl_fw(struct cx18_stream *s, |
445 | struct cx18_buffer *buf) | 452 | struct cx18_mdl *mdl) |
446 | { | 453 | { |
447 | struct cx18 *cx = s->cx; | 454 | struct cx18 *cx = s->cx; |
448 | struct cx18_queue *q; | 455 | struct cx18_queue *q; |
@@ -451,16 +458,16 @@ struct cx18_queue *_cx18_stream_put_buf_fw(struct cx18_stream *s, | |||
451 | if (s->handle == CX18_INVALID_TASK_HANDLE || | 458 | if (s->handle == CX18_INVALID_TASK_HANDLE || |
452 | test_bit(CX18_F_S_STOPPING, &s->s_flags) || | 459 | test_bit(CX18_F_S_STOPPING, &s->s_flags) || |
453 | !test_bit(CX18_F_S_STREAMING, &s->s_flags)) | 460 | !test_bit(CX18_F_S_STREAMING, &s->s_flags)) |
454 | return cx18_enqueue(s, buf, &s->q_free); | 461 | return cx18_enqueue(s, mdl, &s->q_free); |
455 | 462 | ||
456 | q = cx18_enqueue(s, buf, &s->q_busy); | 463 | q = cx18_enqueue(s, mdl, &s->q_busy); |
457 | if (q != &s->q_busy) | 464 | if (q != &s->q_busy) |
458 | return q; /* The firmware has the max buffers it can handle */ | 465 | return q; /* The firmware has the max MDLs it can handle */ |
459 | 466 | ||
460 | cx18_buf_sync_for_device(s, buf); | 467 | cx18_mdl_sync_for_device(s, mdl); |
461 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, | 468 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, |
462 | (void __iomem *) &cx->scb->cpu_mdl[buf->id] - cx->enc_mem, | 469 | (void __iomem *) &cx->scb->cpu_mdl[mdl->id] - cx->enc_mem, |
463 | 1, buf->id, s->buf_size); | 470 | s->bufs_per_mdl, mdl->id, s->mdl_size); |
464 | return q; | 471 | return q; |
465 | } | 472 | } |
466 | 473 | ||
@@ -468,19 +475,19 @@ static | |||
468 | void _cx18_stream_load_fw_queue(struct cx18_stream *s) | 475 | void _cx18_stream_load_fw_queue(struct cx18_stream *s) |
469 | { | 476 | { |
470 | struct cx18_queue *q; | 477 | struct cx18_queue *q; |
471 | struct cx18_buffer *buf; | 478 | struct cx18_mdl *mdl; |
472 | 479 | ||
473 | if (atomic_read(&s->q_free.buffers) == 0 || | 480 | if (atomic_read(&s->q_free.depth) == 0 || |
474 | atomic_read(&s->q_busy.buffers) >= CX18_MAX_FW_MDLS_PER_STREAM) | 481 | atomic_read(&s->q_busy.depth) >= CX18_MAX_FW_MDLS_PER_STREAM) |
475 | return; | 482 | return; |
476 | 483 | ||
477 | /* Move from q_free to q_busy notifying the firmware, until the limit */ | 484 | /* Move from q_free to q_busy notifying the firmware, until the limit */ |
478 | do { | 485 | do { |
479 | buf = cx18_dequeue(s, &s->q_free); | 486 | mdl = cx18_dequeue(s, &s->q_free); |
480 | if (buf == NULL) | 487 | if (mdl == NULL) |
481 | break; | 488 | break; |
482 | q = _cx18_stream_put_buf_fw(s, buf); | 489 | q = _cx18_stream_put_mdl_fw(s, mdl); |
483 | } while (atomic_read(&s->q_busy.buffers) < CX18_MAX_FW_MDLS_PER_STREAM | 490 | } while (atomic_read(&s->q_busy.depth) < CX18_MAX_FW_MDLS_PER_STREAM |
484 | && q == &s->q_busy); | 491 | && q == &s->q_busy); |
485 | } | 492 | } |
486 | 493 | ||
@@ -492,11 +499,51 @@ void cx18_out_work_handler(struct work_struct *work) | |||
492 | _cx18_stream_load_fw_queue(s); | 499 | _cx18_stream_load_fw_queue(s); |
493 | } | 500 | } |
494 | 501 | ||
502 | static void cx18_stream_configure_mdls(struct cx18_stream *s) | ||
503 | { | ||
504 | cx18_unload_queues(s); | ||
505 | |||
506 | switch (s->type) { | ||
507 | case CX18_ENC_STREAM_TYPE_YUV: | ||
508 | /* | ||
509 | * Height should be a multiple of 32 lines. | ||
510 | * Set the MDL size to the exact size needed for one frame. | ||
511 | * Use enough buffers per MDL to cover the MDL size | ||
512 | */ | ||
513 | s->mdl_size = 720 * s->cx->params.height * 3 / 2; | ||
514 | s->bufs_per_mdl = s->mdl_size / s->buf_size; | ||
515 | if (s->mdl_size % s->buf_size) | ||
516 | s->bufs_per_mdl++; | ||
517 | break; | ||
518 | case CX18_ENC_STREAM_TYPE_VBI: | ||
519 | s->bufs_per_mdl = 1; | ||
520 | if (cx18_raw_vbi(s->cx)) { | ||
521 | s->mdl_size = (s->cx->is_60hz ? 12 : 18) | ||
522 | * 2 * vbi_active_samples; | ||
523 | } else { | ||
524 | /* | ||
525 | * See comment in cx18_vbi_setup() below about the | ||
526 | * extra lines we capture in sliced VBI mode due to | ||
527 | * the lines on which EAV RP codes toggle. | ||
528 | */ | ||
529 | s->mdl_size = s->cx->is_60hz | ||
530 | ? (21 - 4 + 1) * 2 * vbi_hblank_samples_60Hz | ||
531 | : (23 - 2 + 1) * 2 * vbi_hblank_samples_50Hz; | ||
532 | } | ||
533 | break; | ||
534 | default: | ||
535 | s->bufs_per_mdl = 1; | ||
536 | s->mdl_size = s->buf_size * s->bufs_per_mdl; | ||
537 | break; | ||
538 | } | ||
539 | |||
540 | cx18_load_queues(s); | ||
541 | } | ||
542 | |||
495 | int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | 543 | int cx18_start_v4l2_encode_stream(struct cx18_stream *s) |
496 | { | 544 | { |
497 | u32 data[MAX_MB_ARGUMENTS]; | 545 | u32 data[MAX_MB_ARGUMENTS]; |
498 | struct cx18 *cx = s->cx; | 546 | struct cx18 *cx = s->cx; |
499 | struct cx18_buffer *buf; | ||
500 | int captype = 0; | 547 | int captype = 0; |
501 | struct cx18_api_func_private priv; | 548 | struct cx18_api_func_private priv; |
502 | 549 | ||
@@ -619,14 +666,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
619 | (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem); | 666 | (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem); |
620 | 667 | ||
621 | /* Init all the cpu_mdls for this stream */ | 668 | /* Init all the cpu_mdls for this stream */ |
622 | cx18_flush_queues(s); | 669 | cx18_stream_configure_mdls(s); |
623 | spin_lock(&s->q_free.lock); | ||
624 | list_for_each_entry(buf, &s->q_free.list, list) { | ||
625 | cx18_writel(cx, buf->dma_handle, | ||
626 | &cx->scb->cpu_mdl[buf->id].paddr); | ||
627 | cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length); | ||
628 | } | ||
629 | spin_unlock(&s->q_free.lock); | ||
630 | _cx18_stream_load_fw_queue(s); | 670 | _cx18_stream_load_fw_queue(s); |
631 | 671 | ||
632 | /* begin_capture */ | 672 | /* begin_capture */ |
diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h index 1afc3fd9d822..4a01db5e5a35 100644 --- a/drivers/media/video/cx18/cx18-streams.h +++ b/drivers/media/video/cx18/cx18-streams.h | |||
@@ -28,18 +28,18 @@ int cx18_streams_setup(struct cx18 *cx); | |||
28 | int cx18_streams_register(struct cx18 *cx); | 28 | int cx18_streams_register(struct cx18 *cx); |
29 | void cx18_streams_cleanup(struct cx18 *cx, int unregister); | 29 | void cx18_streams_cleanup(struct cx18 *cx, int unregister); |
30 | 30 | ||
31 | /* Related to submission of buffers to firmware */ | 31 | /* Related to submission of mdls to firmware */ |
32 | static inline void cx18_stream_load_fw_queue(struct cx18_stream *s) | 32 | static inline void cx18_stream_load_fw_queue(struct cx18_stream *s) |
33 | { | 33 | { |
34 | struct cx18 *cx = s->cx; | 34 | struct cx18 *cx = s->cx; |
35 | queue_work(cx->out_work_queue, &s->out_work_order); | 35 | queue_work(cx->out_work_queue, &s->out_work_order); |
36 | } | 36 | } |
37 | 37 | ||
38 | static inline void cx18_stream_put_buf_fw(struct cx18_stream *s, | 38 | static inline void cx18_stream_put_mdl_fw(struct cx18_stream *s, |
39 | struct cx18_buffer *buf) | 39 | struct cx18_mdl *mdl) |
40 | { | 40 | { |
41 | /* Put buf on q_free; the out work handler will move buf(s) to q_busy */ | 41 | /* Put mdl on q_free; the out work handler will move mdl(s) to q_busy */ |
42 | cx18_enqueue(s, buf, &s->q_free); | 42 | cx18_enqueue(s, mdl, &s->q_free); |
43 | cx18_stream_load_fw_queue(s); | 43 | cx18_stream_load_fw_queue(s); |
44 | } | 44 | } |
45 | 45 | ||
diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c index c2aef4add31d..574c1c6974f8 100644 --- a/drivers/media/video/cx18/cx18-vbi.c +++ b/drivers/media/video/cx18/cx18-vbi.c | |||
@@ -105,6 +105,7 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) | |||
105 | 105 | ||
106 | /* Compress raw VBI format, removes leading SAV codes and surplus space | 106 | /* Compress raw VBI format, removes leading SAV codes and surplus space |
107 | after the frame. Returns new compressed size. */ | 107 | after the frame. Returns new compressed size. */ |
108 | /* FIXME - this function ignores the input size. */ | ||
108 | static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size, u32 hdr_size) | 109 | static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size, u32 hdr_size) |
109 | { | 110 | { |
110 | u32 line_size = vbi_active_samples; | 111 | u32 line_size = vbi_active_samples; |
@@ -185,8 +186,7 @@ static u32 compress_sliced_buf(struct cx18 *cx, u8 *buf, u32 size, | |||
185 | return line; | 186 | return line; |
186 | } | 187 | } |
187 | 188 | ||
188 | void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, | 189 | static void _cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf) |
189 | int streamtype) | ||
190 | { | 190 | { |
191 | /* | 191 | /* |
192 | * The CX23418 provides a 12 byte header in its raw VBI buffers to us: | 192 | * The CX23418 provides a 12 byte header in its raw VBI buffers to us: |
@@ -203,9 +203,6 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, | |||
203 | u32 pts; | 203 | u32 pts; |
204 | int lines; | 204 | int lines; |
205 | 205 | ||
206 | if (streamtype != CX18_ENC_STREAM_TYPE_VBI) | ||
207 | return; | ||
208 | |||
209 | /* | 206 | /* |
210 | * The CX23418 sends us data that is 32 bit little-endian swapped, | 207 | * The CX23418 sends us data that is 32 bit little-endian swapped, |
211 | * but we want the raw VBI bytes in the order they were in the raster | 208 | * but we want the raw VBI bytes in the order they were in the raster |
@@ -250,3 +247,31 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, | |||
250 | copy_vbi_data(cx, lines, pts); | 247 | copy_vbi_data(cx, lines, pts); |
251 | cx->vbi.frame++; | 248 | cx->vbi.frame++; |
252 | } | 249 | } |
250 | |||
251 | void cx18_process_vbi_data(struct cx18 *cx, struct cx18_mdl *mdl, | ||
252 | int streamtype) | ||
253 | { | ||
254 | struct cx18_buffer *buf; | ||
255 | u32 orig_used; | ||
256 | |||
257 | if (streamtype != CX18_ENC_STREAM_TYPE_VBI) | ||
258 | return; | ||
259 | |||
260 | /* | ||
261 | * Big assumption here: | ||
262 | * Every buffer hooked to the MDL's buf_list is a complete VBI frame | ||
263 | * that ends at the end of the buffer. | ||
264 | * | ||
265 | * To assume anything else would make the code in this file | ||
266 | * more complex, or require extra memcpy()'s to make the | ||
267 | * buffers satisfy the above assumption. It's just simpler to set | ||
268 | * up the encoder buffer transfers to make the assumption true. | ||
269 | */ | ||
270 | list_for_each_entry(buf, &mdl->buf_list, list) { | ||
271 | orig_used = buf->bytesused; | ||
272 | if (orig_used == 0) | ||
273 | break; | ||
274 | _cx18_process_vbi_data(cx, buf); | ||
275 | mdl->bytesused -= (orig_used - buf->bytesused); | ||
276 | } | ||
277 | } | ||
diff --git a/drivers/media/video/cx18/cx18-vbi.h b/drivers/media/video/cx18/cx18-vbi.h index e7e1ae427f34..b365cf4b4668 100644 --- a/drivers/media/video/cx18/cx18-vbi.h +++ b/drivers/media/video/cx18/cx18-vbi.h | |||
@@ -21,6 +21,6 @@ | |||
21 | * 02111-1307 USA | 21 | * 02111-1307 USA |
22 | */ | 22 | */ |
23 | 23 | ||
24 | void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, | 24 | void cx18_process_vbi_data(struct cx18 *cx, struct cx18_mdl *mdl, |
25 | int streamtype); | 25 | int streamtype); |
26 | int cx18_used_line(struct cx18 *cx, int line, int field); | 26 | int cx18_used_line(struct cx18 *cx, int line, int field); |
diff --git a/drivers/media/video/cx18/cx18-version.h b/drivers/media/video/cx18/cx18-version.h index 45494b094e7f..9c0b5bb1b019 100644 --- a/drivers/media/video/cx18/cx18-version.h +++ b/drivers/media/video/cx18/cx18-version.h | |||
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | #define CX18_DRIVER_NAME "cx18" | 25 | #define CX18_DRIVER_NAME "cx18" |
26 | #define CX18_DRIVER_VERSION_MAJOR 1 | 26 | #define CX18_DRIVER_VERSION_MAJOR 1 |
27 | #define CX18_DRIVER_VERSION_MINOR 2 | 27 | #define CX18_DRIVER_VERSION_MINOR 3 |
28 | #define CX18_DRIVER_VERSION_PATCHLEVEL 0 | 28 | #define CX18_DRIVER_VERSION_PATCHLEVEL 0 |
29 | 29 | ||
30 | #define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL) | 30 | #define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL) |
diff --git a/drivers/media/video/cx18/cx23418.h b/drivers/media/video/cx18/cx23418.h index 9956abf576c5..868806effdcf 100644 --- a/drivers/media/video/cx18/cx23418.h +++ b/drivers/media/video/cx18/cx23418.h | |||
@@ -363,7 +363,7 @@ | |||
363 | /* Description: This command provides the offset to a Memory Descriptor List | 363 | /* Description: This command provides the offset to a Memory Descriptor List |
364 | IN[0] - Task handle. Handle of the task to start | 364 | IN[0] - Task handle. Handle of the task to start |
365 | IN[1] - Offset of the MDL from the beginning of the local DDR. | 365 | IN[1] - Offset of the MDL from the beginning of the local DDR. |
366 | IN[2] - Number of cx18_mdl structures in the array pointed to by IN[1] | 366 | IN[2] - Number of cx18_mdl_ent structures in the array pointed to by IN[1] |
367 | IN[3] - Buffer ID | 367 | IN[3] - Buffer ID |
368 | IN[4] - Total buffer length | 368 | IN[4] - Total buffer length |
369 | ReturnCode - One of the ERR_DE_... */ | 369 | ReturnCode - One of the ERR_DE_... */ |
diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c index 48f22fa38e6c..cd135f01b9c1 100644 --- a/drivers/media/video/cx231xx/cx231xx-input.c +++ b/drivers/media/video/cx231xx/cx231xx-input.c | |||
@@ -126,8 +126,7 @@ static void cx231xx_ir_handle_key(struct cx231xx_IR *ir) | |||
126 | 126 | ||
127 | if (do_sendkey) { | 127 | if (do_sendkey) { |
128 | dprintk("sending keypress\n"); | 128 | dprintk("sending keypress\n"); |
129 | ir_input_keydown(ir->input, &ir->ir, poll_result.rc_data[0], | 129 | ir_input_keydown(ir->input, &ir->ir, poll_result.rc_data[0]); |
130 | poll_result.rc_data[0]); | ||
131 | ir_input_nokey(ir->input, &ir->ir); | 130 | ir_input_nokey(ir->input, &ir->ir); |
132 | } | 131 | } |
133 | 132 | ||
@@ -198,7 +197,11 @@ int cx231xx_ir_init(struct cx231xx *dev) | |||
198 | usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); | 197 | usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); |
199 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); | 198 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); |
200 | 199 | ||
201 | ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER, dev->board.ir_codes); | 200 | err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER, |
201 | dev->board.ir_codes); | ||
202 | if (err < 0) | ||
203 | goto err_out_free; | ||
204 | |||
202 | input_dev->name = ir->name; | 205 | input_dev->name = ir->name; |
203 | input_dev->phys = ir->phys; | 206 | input_dev->phys = ir->phys; |
204 | input_dev->id.bustype = BUS_USB; | 207 | input_dev->id.bustype = BUS_USB; |
@@ -223,6 +226,7 @@ err_out_stop: | |||
223 | cx231xx_ir_stop(ir); | 226 | cx231xx_ir_stop(ir); |
224 | dev->ir = NULL; | 227 | dev->ir = NULL; |
225 | err_out_free: | 228 | err_out_free: |
229 | ir_input_free(input_dev); | ||
226 | input_free_device(input_dev); | 230 | input_free_device(input_dev); |
227 | kfree(ir); | 231 | kfree(ir); |
228 | return err; | 232 | return err; |
@@ -237,6 +241,7 @@ int cx231xx_ir_fini(struct cx231xx *dev) | |||
237 | return 0; | 241 | return 0; |
238 | 242 | ||
239 | cx231xx_ir_stop(ir); | 243 | cx231xx_ir_stop(ir); |
244 | ir_input_free(ir->input); | ||
240 | input_unregister_device(ir->input); | 245 | input_unregister_device(ir->input); |
241 | kfree(ir); | 246 | kfree(ir); |
242 | 247 | ||
diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c index 36503725d973..d095aa0d6d19 100644 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ b/drivers/media/video/cx231xx/cx231xx-video.c | |||
@@ -2106,7 +2106,7 @@ static int cx231xx_v4l2_close(struct file *filp) | |||
2106 | } | 2106 | } |
2107 | 2107 | ||
2108 | /* Save some power by putting tuner to sleep */ | 2108 | /* Save some power by putting tuner to sleep */ |
2109 | call_all(dev, tuner, s_standby); | 2109 | call_all(dev, core, s_power, 0); |
2110 | 2110 | ||
2111 | /* do this before setting alternate! */ | 2111 | /* do this before setting alternate! */ |
2112 | cx231xx_uninit_isoc(dev); | 2112 | cx231xx_uninit_isoc(dev); |
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index fd3fc3e3198a..bcdda9a9aa96 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig | |||
@@ -18,7 +18,9 @@ config VIDEO_CX23885 | |||
18 | select DVB_TDA10048 if !DVB_FE_CUSTOMISE | 18 | select DVB_TDA10048 if !DVB_FE_CUSTOMISE |
19 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE | 19 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE |
20 | select DVB_STV6110 if !DVB_FE_CUSTOMISE | 20 | select DVB_STV6110 if !DVB_FE_CUSTOMISE |
21 | select DVB_CX24116 if !DVB_FE_CUSTOMISE | ||
21 | select DVB_STV0900 if !DVB_FE_CUSTOMISE | 22 | select DVB_STV0900 if !DVB_FE_CUSTOMISE |
23 | select DVB_DS3000 if !DVB_FE_CUSTOMISE | ||
22 | select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE | 24 | select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE |
23 | select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE | 25 | select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE |
24 | select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE | 26 | select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE |
diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile index ab8ea35c9bfb..5787ae243631 100644 --- a/drivers/media/video/cx23885/Makefile +++ b/drivers/media/video/cx23885/Makefile | |||
@@ -1,6 +1,7 @@ | |||
1 | cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \ | 1 | cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \ |
2 | cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \ | 2 | cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \ |
3 | netup-init.o cimax2.o netup-eeprom.o | 3 | cx23885-ioctl.o cx23885-ir.o cx23885-input.o cx23888-ir.o \ |
4 | netup-init.o cimax2.o netup-eeprom.o cx23885-f300.o | ||
4 | 5 | ||
5 | obj-$(CONFIG_VIDEO_CX23885) += cx23885.o | 6 | obj-$(CONFIG_VIDEO_CX23885) += cx23885.o |
6 | 7 | ||
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index 6c3b51ce3372..0eed852c61e9 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <media/cx2341x.h> | 37 | #include <media/cx2341x.h> |
38 | 38 | ||
39 | #include "cx23885.h" | 39 | #include "cx23885.h" |
40 | #include "cx23885-ioctl.h" | ||
40 | 41 | ||
41 | #define CX23885_FIRM_IMAGE_SIZE 376836 | 42 | #define CX23885_FIRM_IMAGE_SIZE 376836 |
42 | #define CX23885_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw" | 43 | #define CX23885_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw" |
@@ -318,7 +319,7 @@ static int mc417_wait_ready(struct cx23885_dev *dev) | |||
318 | } | 319 | } |
319 | } | 320 | } |
320 | 321 | ||
321 | static int mc417_register_write(struct cx23885_dev *dev, u16 address, u32 value) | 322 | int mc417_register_write(struct cx23885_dev *dev, u16 address, u32 value) |
322 | { | 323 | { |
323 | u32 regval; | 324 | u32 regval; |
324 | 325 | ||
@@ -382,7 +383,7 @@ static int mc417_register_write(struct cx23885_dev *dev, u16 address, u32 value) | |||
382 | return mc417_wait_ready(dev); | 383 | return mc417_wait_ready(dev); |
383 | } | 384 | } |
384 | 385 | ||
385 | static int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value) | 386 | int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value) |
386 | { | 387 | { |
387 | int retval; | 388 | int retval; |
388 | u32 regval; | 389 | u32 regval; |
@@ -1724,6 +1725,11 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { | |||
1724 | .vidioc_log_status = vidioc_log_status, | 1725 | .vidioc_log_status = vidioc_log_status, |
1725 | .vidioc_querymenu = vidioc_querymenu, | 1726 | .vidioc_querymenu = vidioc_querymenu, |
1726 | .vidioc_queryctrl = vidioc_queryctrl, | 1727 | .vidioc_queryctrl = vidioc_queryctrl, |
1728 | .vidioc_g_chip_ident = cx23885_g_chip_ident, | ||
1729 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1730 | .vidioc_g_register = cx23885_g_register, | ||
1731 | .vidioc_s_register = cx23885_s_register, | ||
1732 | #endif | ||
1727 | }; | 1733 | }; |
1728 | 1734 | ||
1729 | static struct video_device cx23885_mpeg_template = { | 1735 | static struct video_device cx23885_mpeg_template = { |
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index bfdf79f1033c..1ec48169277d 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "cx23885.h" | 28 | #include "cx23885.h" |
29 | #include "tuner-xc2028.h" | 29 | #include "tuner-xc2028.h" |
30 | #include "netup-init.h" | 30 | #include "netup-init.h" |
31 | #include "cx23888-ir.h" | ||
31 | 32 | ||
32 | /* ------------------------------------------------------------------ */ | 33 | /* ------------------------------------------------------------------ */ |
33 | /* board config info */ | 34 | /* board config info */ |
@@ -199,11 +200,61 @@ struct cx23885_board cx23885_boards[] = { | |||
199 | }, | 200 | }, |
200 | [CX23885_BOARD_MYGICA_X8506] = { | 201 | [CX23885_BOARD_MYGICA_X8506] = { |
201 | .name = "Mygica X8506 DMB-TH", | 202 | .name = "Mygica X8506 DMB-TH", |
203 | .tuner_type = TUNER_XC5000, | ||
204 | .tuner_addr = 0x61, | ||
205 | .porta = CX23885_ANALOG_VIDEO, | ||
202 | .portb = CX23885_MPEG_DVB, | 206 | .portb = CX23885_MPEG_DVB, |
207 | .input = { | ||
208 | { | ||
209 | .type = CX23885_VMUX_TELEVISION, | ||
210 | .vmux = CX25840_COMPOSITE2, | ||
211 | }, | ||
212 | { | ||
213 | .type = CX23885_VMUX_COMPOSITE1, | ||
214 | .vmux = CX25840_COMPOSITE8, | ||
215 | }, | ||
216 | { | ||
217 | .type = CX23885_VMUX_SVIDEO, | ||
218 | .vmux = CX25840_SVIDEO_LUMA3 | | ||
219 | CX25840_SVIDEO_CHROMA4, | ||
220 | }, | ||
221 | { | ||
222 | .type = CX23885_VMUX_COMPONENT, | ||
223 | .vmux = CX25840_COMPONENT_ON | | ||
224 | CX25840_VIN1_CH1 | | ||
225 | CX25840_VIN6_CH2 | | ||
226 | CX25840_VIN7_CH3, | ||
227 | }, | ||
228 | }, | ||
203 | }, | 229 | }, |
204 | [CX23885_BOARD_MAGICPRO_PROHDTVE2] = { | 230 | [CX23885_BOARD_MAGICPRO_PROHDTVE2] = { |
205 | .name = "Magic-Pro ProHDTV Extreme 2", | 231 | .name = "Magic-Pro ProHDTV Extreme 2", |
232 | .tuner_type = TUNER_XC5000, | ||
233 | .tuner_addr = 0x61, | ||
234 | .porta = CX23885_ANALOG_VIDEO, | ||
206 | .portb = CX23885_MPEG_DVB, | 235 | .portb = CX23885_MPEG_DVB, |
236 | .input = { | ||
237 | { | ||
238 | .type = CX23885_VMUX_TELEVISION, | ||
239 | .vmux = CX25840_COMPOSITE2, | ||
240 | }, | ||
241 | { | ||
242 | .type = CX23885_VMUX_COMPOSITE1, | ||
243 | .vmux = CX25840_COMPOSITE8, | ||
244 | }, | ||
245 | { | ||
246 | .type = CX23885_VMUX_SVIDEO, | ||
247 | .vmux = CX25840_SVIDEO_LUMA3 | | ||
248 | CX25840_SVIDEO_CHROMA4, | ||
249 | }, | ||
250 | { | ||
251 | .type = CX23885_VMUX_COMPONENT, | ||
252 | .vmux = CX25840_COMPONENT_ON | | ||
253 | CX25840_VIN1_CH1 | | ||
254 | CX25840_VIN6_CH2 | | ||
255 | CX25840_VIN7_CH3, | ||
256 | }, | ||
257 | }, | ||
207 | }, | 258 | }, |
208 | [CX23885_BOARD_HAUPPAUGE_HVR1850] = { | 259 | [CX23885_BOARD_HAUPPAUGE_HVR1850] = { |
209 | .name = "Hauppauge WinTV-HVR1850", | 260 | .name = "Hauppauge WinTV-HVR1850", |
@@ -214,6 +265,15 @@ struct cx23885_board cx23885_boards[] = { | |||
214 | .name = "Compro VideoMate E800", | 265 | .name = "Compro VideoMate E800", |
215 | .portc = CX23885_MPEG_DVB, | 266 | .portc = CX23885_MPEG_DVB, |
216 | }, | 267 | }, |
268 | [CX23885_BOARD_HAUPPAUGE_HVR1290] = { | ||
269 | .name = "Hauppauge WinTV-HVR1290", | ||
270 | .portc = CX23885_MPEG_DVB, | ||
271 | }, | ||
272 | [CX23885_BOARD_MYGICA_X8558PRO] = { | ||
273 | .name = "Mygica X8558 PRO DMB-TH", | ||
274 | .portb = CX23885_MPEG_DVB, | ||
275 | .portc = CX23885_MPEG_DVB, | ||
276 | }, | ||
217 | }; | 277 | }; |
218 | const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); | 278 | const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); |
219 | 279 | ||
@@ -349,6 +409,14 @@ struct cx23885_subid cx23885_subids[] = { | |||
349 | .subvendor = 0x1858, | 409 | .subvendor = 0x1858, |
350 | .subdevice = 0xe800, | 410 | .subdevice = 0xe800, |
351 | .card = CX23885_BOARD_COMPRO_VIDEOMATE_E800, | 411 | .card = CX23885_BOARD_COMPRO_VIDEOMATE_E800, |
412 | }, { | ||
413 | .subvendor = 0x0070, | ||
414 | .subdevice = 0x8551, | ||
415 | .card = CX23885_BOARD_HAUPPAUGE_HVR1290, | ||
416 | }, { | ||
417 | .subvendor = 0x14f1, | ||
418 | .subdevice = 0x8578, | ||
419 | .card = CX23885_BOARD_MYGICA_X8558PRO, | ||
352 | }, | 420 | }, |
353 | }; | 421 | }; |
354 | const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); | 422 | const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); |
@@ -509,9 +577,13 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) | |||
509 | * DVB-T and MPEG2 HW Encoder */ | 577 | * DVB-T and MPEG2 HW Encoder */ |
510 | break; | 578 | break; |
511 | case 85021: | 579 | case 85021: |
512 | /* WinTV-HVR1850 (PCIe, OEM, RCA in, IR, FM, | 580 | /* WinTV-HVR1850 (PCIe, Retail, 3.5mm in, IR, FM, |
513 | Dual channel ATSC and MPEG2 HW Encoder */ | 581 | Dual channel ATSC and MPEG2 HW Encoder */ |
514 | break; | 582 | break; |
583 | case 85721: | ||
584 | /* WinTV-HVR1290 (PCIe, OEM, RCA in, IR, | ||
585 | Dual channel ATSC and Basic analog */ | ||
586 | break; | ||
515 | default: | 587 | default: |
516 | printk(KERN_WARNING "%s: warning: " | 588 | printk(KERN_WARNING "%s: warning: " |
517 | "unknown hauppauge model #%d\n", | 589 | "unknown hauppauge model #%d\n", |
@@ -710,10 +782,14 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) | |||
710 | cx_set(GP0_IO, 0x00040004); | 782 | cx_set(GP0_IO, 0x00040004); |
711 | break; | 783 | break; |
712 | case CX23885_BOARD_TBS_6920: | 784 | case CX23885_BOARD_TBS_6920: |
713 | case CX23885_BOARD_TEVII_S470: | ||
714 | cx_write(MC417_CTL, 0x00000036); | 785 | cx_write(MC417_CTL, 0x00000036); |
715 | cx_write(MC417_OEN, 0x00001000); | 786 | cx_write(MC417_OEN, 0x00001000); |
716 | cx_write(MC417_RWD, 0x00001800); | 787 | cx_set(MC417_RWD, 0x00000002); |
788 | mdelay(200); | ||
789 | cx_clear(MC417_RWD, 0x00000800); | ||
790 | mdelay(200); | ||
791 | cx_set(MC417_RWD, 0x00000800); | ||
792 | mdelay(200); | ||
717 | break; | 793 | break; |
718 | case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: | 794 | case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: |
719 | /* GPIO-0 INTA from CiMax1 | 795 | /* GPIO-0 INTA from CiMax1 |
@@ -758,15 +834,26 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) | |||
758 | break; | 834 | break; |
759 | case CX23885_BOARD_MYGICA_X8506: | 835 | case CX23885_BOARD_MYGICA_X8506: |
760 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: | 836 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: |
837 | /* GPIO-0 (0)Analog / (1)Digital TV */ | ||
761 | /* GPIO-1 reset XC5000 */ | 838 | /* GPIO-1 reset XC5000 */ |
762 | /* GPIO-2 reset LGS8GL5 / LGS8G75 */ | 839 | /* GPIO-2 reset LGS8GL5 / LGS8G75 */ |
763 | cx_set(GP0_IO, 0x00060000); | 840 | cx23885_gpio_enable(dev, GPIO_0 | GPIO_1 | GPIO_2, 1); |
764 | cx_clear(GP0_IO, 0x00000006); | 841 | cx23885_gpio_clear(dev, GPIO_1 | GPIO_2); |
765 | mdelay(100); | 842 | mdelay(100); |
766 | cx_set(GP0_IO, 0x00060006); | 843 | cx23885_gpio_set(dev, GPIO_0 | GPIO_1 | GPIO_2); |
844 | mdelay(100); | ||
845 | break; | ||
846 | case CX23885_BOARD_MYGICA_X8558PRO: | ||
847 | /* GPIO-0 reset first ATBM8830 */ | ||
848 | /* GPIO-1 reset second ATBM8830 */ | ||
849 | cx23885_gpio_enable(dev, GPIO_0 | GPIO_1, 1); | ||
850 | cx23885_gpio_clear(dev, GPIO_0 | GPIO_1); | ||
851 | mdelay(100); | ||
852 | cx23885_gpio_set(dev, GPIO_0 | GPIO_1); | ||
767 | mdelay(100); | 853 | mdelay(100); |
768 | break; | 854 | break; |
769 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | 855 | case CX23885_BOARD_HAUPPAUGE_HVR1850: |
856 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | ||
770 | /* GPIO-0 656_CLK */ | 857 | /* GPIO-0 656_CLK */ |
771 | /* GPIO-1 656_D0 */ | 858 | /* GPIO-1 656_D0 */ |
772 | /* GPIO-2 Wake# */ | 859 | /* GPIO-2 Wake# */ |
@@ -801,6 +888,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) | |||
801 | 888 | ||
802 | int cx23885_ir_init(struct cx23885_dev *dev) | 889 | int cx23885_ir_init(struct cx23885_dev *dev) |
803 | { | 890 | { |
891 | int ret = 0; | ||
804 | switch (dev->board) { | 892 | switch (dev->board) { |
805 | case CX23885_BOARD_HAUPPAUGE_HVR1250: | 893 | case CX23885_BOARD_HAUPPAUGE_HVR1250: |
806 | case CX23885_BOARD_HAUPPAUGE_HVR1500: | 894 | case CX23885_BOARD_HAUPPAUGE_HVR1500: |
@@ -812,15 +900,46 @@ int cx23885_ir_init(struct cx23885_dev *dev) | |||
812 | case CX23885_BOARD_HAUPPAUGE_HVR1275: | 900 | case CX23885_BOARD_HAUPPAUGE_HVR1275: |
813 | case CX23885_BOARD_HAUPPAUGE_HVR1255: | 901 | case CX23885_BOARD_HAUPPAUGE_HVR1255: |
814 | case CX23885_BOARD_HAUPPAUGE_HVR1210: | 902 | case CX23885_BOARD_HAUPPAUGE_HVR1210: |
815 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | ||
816 | /* FIXME: Implement me */ | 903 | /* FIXME: Implement me */ |
817 | break; | 904 | break; |
905 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | ||
906 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | ||
907 | ret = cx23888_ir_probe(dev); | ||
908 | if (ret) | ||
909 | break; | ||
910 | dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR); | ||
911 | dev->pci_irqmask |= PCI_MSK_IR; | ||
912 | break; | ||
818 | case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: | 913 | case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: |
819 | request_module("ir-kbd-i2c"); | 914 | request_module("ir-kbd-i2c"); |
820 | break; | 915 | break; |
821 | } | 916 | } |
822 | 917 | ||
823 | return 0; | 918 | return ret; |
919 | } | ||
920 | |||
921 | void cx23885_ir_fini(struct cx23885_dev *dev) | ||
922 | { | ||
923 | switch (dev->board) { | ||
924 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | ||
925 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | ||
926 | dev->pci_irqmask &= ~PCI_MSK_IR; | ||
927 | cx_clear(PCI_INT_MSK, PCI_MSK_IR); | ||
928 | cx23888_ir_remove(dev); | ||
929 | dev->sd_ir = NULL; | ||
930 | break; | ||
931 | } | ||
932 | } | ||
933 | |||
934 | void cx23885_ir_pci_int_enable(struct cx23885_dev *dev) | ||
935 | { | ||
936 | switch (dev->board) { | ||
937 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | ||
938 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | ||
939 | if (dev->sd_ir && (dev->pci_irqmask & PCI_MSK_IR)) | ||
940 | cx_set(PCI_INT_MSK, PCI_MSK_IR); | ||
941 | break; | ||
942 | } | ||
824 | } | 943 | } |
825 | 944 | ||
826 | void cx23885_card_setup(struct cx23885_dev *dev) | 945 | void cx23885_card_setup(struct cx23885_dev *dev) |
@@ -853,6 +972,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
853 | case CX23885_BOARD_HAUPPAUGE_HVR1255: | 972 | case CX23885_BOARD_HAUPPAUGE_HVR1255: |
854 | case CX23885_BOARD_HAUPPAUGE_HVR1210: | 973 | case CX23885_BOARD_HAUPPAUGE_HVR1210: |
855 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | 974 | case CX23885_BOARD_HAUPPAUGE_HVR1850: |
975 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | ||
856 | if (dev->i2c_bus[0].i2c_rc == 0) | 976 | if (dev->i2c_bus[0].i2c_rc == 0) |
857 | hauppauge_eeprom(dev, eeprom+0xc0); | 977 | hauppauge_eeprom(dev, eeprom+0xc0); |
858 | break; | 978 | break; |
@@ -886,8 +1006,12 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
886 | ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ | 1006 | ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ |
887 | ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; | 1007 | ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; |
888 | break; | 1008 | break; |
889 | case CX23885_BOARD_TEVII_S470: | ||
890 | case CX23885_BOARD_TBS_6920: | 1009 | case CX23885_BOARD_TBS_6920: |
1010 | ts1->gen_ctrl_val = 0x4; /* Parallel */ | ||
1011 | ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ | ||
1012 | ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; | ||
1013 | break; | ||
1014 | case CX23885_BOARD_TEVII_S470: | ||
891 | case CX23885_BOARD_DVBWORLD_2005: | 1015 | case CX23885_BOARD_DVBWORLD_2005: |
892 | ts1->gen_ctrl_val = 0x5; /* Parallel */ | 1016 | ts1->gen_ctrl_val = 0x5; /* Parallel */ |
893 | ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ | 1017 | ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ |
@@ -907,6 +1031,14 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
907 | ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ | 1031 | ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ |
908 | ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; | 1032 | ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; |
909 | break; | 1033 | break; |
1034 | case CX23885_BOARD_MYGICA_X8558PRO: | ||
1035 | ts1->gen_ctrl_val = 0x5; /* Parallel */ | ||
1036 | ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ | ||
1037 | ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; | ||
1038 | ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ | ||
1039 | ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ | ||
1040 | ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; | ||
1041 | break; | ||
910 | case CX23885_BOARD_HAUPPAUGE_HVR1250: | 1042 | case CX23885_BOARD_HAUPPAUGE_HVR1250: |
911 | case CX23885_BOARD_HAUPPAUGE_HVR1500: | 1043 | case CX23885_BOARD_HAUPPAUGE_HVR1500: |
912 | case CX23885_BOARD_HAUPPAUGE_HVR1500Q: | 1044 | case CX23885_BOARD_HAUPPAUGE_HVR1500Q: |
@@ -922,6 +1054,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
922 | case CX23885_BOARD_HAUPPAUGE_HVR1210: | 1054 | case CX23885_BOARD_HAUPPAUGE_HVR1210: |
923 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | 1055 | case CX23885_BOARD_HAUPPAUGE_HVR1850: |
924 | case CX23885_BOARD_COMPRO_VIDEOMATE_E800: | 1056 | case CX23885_BOARD_COMPRO_VIDEOMATE_E800: |
1057 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | ||
925 | default: | 1058 | default: |
926 | ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ | 1059 | ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ |
927 | ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ | 1060 | ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ |
@@ -939,6 +1072,10 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
939 | case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: | 1072 | case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: |
940 | case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: | 1073 | case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: |
941 | case CX23885_BOARD_COMPRO_VIDEOMATE_E800: | 1074 | case CX23885_BOARD_COMPRO_VIDEOMATE_E800: |
1075 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | ||
1076 | case CX23885_BOARD_MYGICA_X8506: | ||
1077 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: | ||
1078 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | ||
942 | dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, | 1079 | dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, |
943 | &dev->i2c_bus[2].i2c_adap, | 1080 | &dev->i2c_bus[2].i2c_adap, |
944 | "cx25840", "cx25840", 0x88 >> 1, NULL); | 1081 | "cx25840", "cx25840", 0x88 >> 1, NULL); |
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index fa2d350e20fd..04b12d27bc13 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c | |||
@@ -32,6 +32,9 @@ | |||
32 | 32 | ||
33 | #include "cx23885.h" | 33 | #include "cx23885.h" |
34 | #include "cimax2.h" | 34 | #include "cimax2.h" |
35 | #include "cx23888-ir.h" | ||
36 | #include "cx23885-ir.h" | ||
37 | #include "cx23885-input.h" | ||
35 | 38 | ||
36 | MODULE_DESCRIPTION("Driver for cx23885 based TV cards"); | 39 | MODULE_DESCRIPTION("Driver for cx23885 based TV cards"); |
37 | MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); | 40 | MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); |
@@ -753,6 +756,23 @@ static void cx23885_dev_checkrevision(struct cx23885_dev *dev) | |||
753 | __func__, dev->hwrevision); | 756 | __func__, dev->hwrevision); |
754 | } | 757 | } |
755 | 758 | ||
759 | /* Find the first v4l2_subdev member of the group id in hw */ | ||
760 | struct v4l2_subdev *cx23885_find_hw(struct cx23885_dev *dev, u32 hw) | ||
761 | { | ||
762 | struct v4l2_subdev *result = NULL; | ||
763 | struct v4l2_subdev *sd; | ||
764 | |||
765 | spin_lock(&dev->v4l2_dev.lock); | ||
766 | v4l2_device_for_each_subdev(sd, &dev->v4l2_dev) { | ||
767 | if (sd->grp_id == hw) { | ||
768 | result = sd; | ||
769 | break; | ||
770 | } | ||
771 | } | ||
772 | spin_unlock(&dev->v4l2_dev.lock); | ||
773 | return result; | ||
774 | } | ||
775 | |||
756 | static int cx23885_dev_setup(struct cx23885_dev *dev) | 776 | static int cx23885_dev_setup(struct cx23885_dev *dev) |
757 | { | 777 | { |
758 | int i; | 778 | int i; |
@@ -899,7 +919,7 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) | |||
899 | cx23885_i2c_register(&dev->i2c_bus[1]); | 919 | cx23885_i2c_register(&dev->i2c_bus[1]); |
900 | cx23885_i2c_register(&dev->i2c_bus[2]); | 920 | cx23885_i2c_register(&dev->i2c_bus[2]); |
901 | cx23885_card_setup(dev); | 921 | cx23885_card_setup(dev); |
902 | call_all(dev, tuner, s_standby); | 922 | call_all(dev, core, s_power, 0); |
903 | cx23885_ir_init(dev); | 923 | cx23885_ir_init(dev); |
904 | 924 | ||
905 | if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) { | 925 | if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) { |
@@ -1637,6 +1657,7 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) | |||
1637 | u32 ts1_status, ts1_mask; | 1657 | u32 ts1_status, ts1_mask; |
1638 | u32 ts2_status, ts2_mask; | 1658 | u32 ts2_status, ts2_mask; |
1639 | int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0; | 1659 | int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0; |
1660 | bool ir_handled = false; | ||
1640 | 1661 | ||
1641 | pci_status = cx_read(PCI_INT_STAT); | 1662 | pci_status = cx_read(PCI_INT_STAT); |
1642 | pci_mask = cx_read(PCI_INT_MSK); | 1663 | pci_mask = cx_read(PCI_INT_MSK); |
@@ -1662,18 +1683,12 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) | |||
1662 | dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n", | 1683 | dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n", |
1663 | ts2_status, ts2_mask, ts2_count); | 1684 | ts2_status, ts2_mask, ts2_count); |
1664 | 1685 | ||
1665 | if ((pci_status & PCI_MSK_RISC_RD) || | 1686 | if (pci_status & (PCI_MSK_RISC_RD | PCI_MSK_RISC_WR | |
1666 | (pci_status & PCI_MSK_RISC_WR) || | 1687 | PCI_MSK_AL_RD | PCI_MSK_AL_WR | PCI_MSK_APB_DMA | |
1667 | (pci_status & PCI_MSK_AL_RD) || | 1688 | PCI_MSK_VID_C | PCI_MSK_VID_B | PCI_MSK_VID_A | |
1668 | (pci_status & PCI_MSK_AL_WR) || | 1689 | PCI_MSK_AUD_INT | PCI_MSK_AUD_EXT | |
1669 | (pci_status & PCI_MSK_APB_DMA) || | 1690 | PCI_MSK_GPIO0 | PCI_MSK_GPIO1 | |
1670 | (pci_status & PCI_MSK_VID_C) || | 1691 | PCI_MSK_IR)) { |
1671 | (pci_status & PCI_MSK_VID_B) || | ||
1672 | (pci_status & PCI_MSK_VID_A) || | ||
1673 | (pci_status & PCI_MSK_AUD_INT) || | ||
1674 | (pci_status & PCI_MSK_AUD_EXT) || | ||
1675 | (pci_status & PCI_MSK_GPIO0) || | ||
1676 | (pci_status & PCI_MSK_GPIO1)) { | ||
1677 | 1692 | ||
1678 | if (pci_status & PCI_MSK_RISC_RD) | 1693 | if (pci_status & PCI_MSK_RISC_RD) |
1679 | dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n", | 1694 | dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n", |
@@ -1722,6 +1737,10 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) | |||
1722 | if (pci_status & PCI_MSK_GPIO1) | 1737 | if (pci_status & PCI_MSK_GPIO1) |
1723 | dprintk(7, " (PCI_MSK_GPIO1 0x%08x)\n", | 1738 | dprintk(7, " (PCI_MSK_GPIO1 0x%08x)\n", |
1724 | PCI_MSK_GPIO1); | 1739 | PCI_MSK_GPIO1); |
1740 | |||
1741 | if (pci_status & PCI_MSK_IR) | ||
1742 | dprintk(7, " (PCI_MSK_IR 0x%08x)\n", | ||
1743 | PCI_MSK_IR); | ||
1725 | } | 1744 | } |
1726 | 1745 | ||
1727 | if (cx23885_boards[dev->board].cimax > 0 && | 1746 | if (cx23885_boards[dev->board].cimax > 0 && |
@@ -1752,12 +1771,48 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) | |||
1752 | if (vida_status) | 1771 | if (vida_status) |
1753 | handled += cx23885_video_irq(dev, vida_status); | 1772 | handled += cx23885_video_irq(dev, vida_status); |
1754 | 1773 | ||
1774 | if (pci_status & PCI_MSK_IR) { | ||
1775 | v4l2_subdev_call(dev->sd_ir, ir, interrupt_service_routine, | ||
1776 | pci_status, &ir_handled); | ||
1777 | if (ir_handled) | ||
1778 | handled++; | ||
1779 | } | ||
1780 | |||
1755 | if (handled) | 1781 | if (handled) |
1756 | cx_write(PCI_INT_STAT, pci_status); | 1782 | cx_write(PCI_INT_STAT, pci_status); |
1757 | out: | 1783 | out: |
1758 | return IRQ_RETVAL(handled); | 1784 | return IRQ_RETVAL(handled); |
1759 | } | 1785 | } |
1760 | 1786 | ||
1787 | static void cx23885_v4l2_dev_notify(struct v4l2_subdev *sd, | ||
1788 | unsigned int notification, void *arg) | ||
1789 | { | ||
1790 | struct cx23885_dev *dev; | ||
1791 | |||
1792 | if (sd == NULL) | ||
1793 | return; | ||
1794 | |||
1795 | dev = to_cx23885(sd->v4l2_dev); | ||
1796 | |||
1797 | switch (notification) { | ||
1798 | case V4L2_SUBDEV_IR_RX_NOTIFY: /* Called in an IRQ context */ | ||
1799 | if (sd == dev->sd_ir) | ||
1800 | cx23885_ir_rx_v4l2_dev_notify(sd, *(u32 *)arg); | ||
1801 | break; | ||
1802 | case V4L2_SUBDEV_IR_TX_NOTIFY: /* Called in an IRQ context */ | ||
1803 | if (sd == dev->sd_ir) | ||
1804 | cx23885_ir_tx_v4l2_dev_notify(sd, *(u32 *)arg); | ||
1805 | break; | ||
1806 | } | ||
1807 | } | ||
1808 | |||
1809 | static void cx23885_v4l2_dev_notify_init(struct cx23885_dev *dev) | ||
1810 | { | ||
1811 | INIT_WORK(&dev->ir_rx_work, cx23885_ir_rx_work_handler); | ||
1812 | INIT_WORK(&dev->ir_tx_work, cx23885_ir_tx_work_handler); | ||
1813 | dev->v4l2_dev.notify = cx23885_v4l2_dev_notify; | ||
1814 | } | ||
1815 | |||
1761 | static inline int encoder_on_portb(struct cx23885_dev *dev) | 1816 | static inline int encoder_on_portb(struct cx23885_dev *dev) |
1762 | { | 1817 | { |
1763 | return cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER; | 1818 | return cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER; |
@@ -1816,6 +1871,26 @@ void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask) | |||
1816 | printk(KERN_INFO "%s: Unsupported\n", dev->name); | 1871 | printk(KERN_INFO "%s: Unsupported\n", dev->name); |
1817 | } | 1872 | } |
1818 | 1873 | ||
1874 | u32 cx23885_gpio_get(struct cx23885_dev *dev, u32 mask) | ||
1875 | { | ||
1876 | if (mask & 0x00000007) | ||
1877 | return (cx_read(GP0_IO) >> 8) & mask & 0x7; | ||
1878 | |||
1879 | if (mask & 0x0007fff8) { | ||
1880 | if (encoder_on_portb(dev) || encoder_on_portc(dev)) | ||
1881 | printk(KERN_ERR | ||
1882 | "%s: Reading GPIO moving on encoder ports\n", | ||
1883 | dev->name); | ||
1884 | return (cx_read(MC417_RWD) & ((mask & 0x7fff8) >> 3)) << 3; | ||
1885 | } | ||
1886 | |||
1887 | /* TODO: 23-19 */ | ||
1888 | if (mask & 0x00f80000) | ||
1889 | printk(KERN_INFO "%s: Unsupported\n", dev->name); | ||
1890 | |||
1891 | return 0; | ||
1892 | } | ||
1893 | |||
1819 | void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput) | 1894 | void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput) |
1820 | { | 1895 | { |
1821 | if ((mask & 0x00000007) && asoutput) | 1896 | if ((mask & 0x00000007) && asoutput) |
@@ -1854,6 +1929,9 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, | |||
1854 | if (err < 0) | 1929 | if (err < 0) |
1855 | goto fail_free; | 1930 | goto fail_free; |
1856 | 1931 | ||
1932 | /* Prepare to handle notifications from subdevices */ | ||
1933 | cx23885_v4l2_dev_notify_init(dev); | ||
1934 | |||
1857 | /* pci init */ | 1935 | /* pci init */ |
1858 | dev->pci = pci_dev; | 1936 | dev->pci = pci_dev; |
1859 | if (pci_enable_device(pci_dev)) { | 1937 | if (pci_enable_device(pci_dev)) { |
@@ -1896,6 +1974,14 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, | |||
1896 | break; | 1974 | break; |
1897 | } | 1975 | } |
1898 | 1976 | ||
1977 | /* | ||
1978 | * The CX2388[58] IR controller can start firing interrupts when | ||
1979 | * enabled, so these have to take place after the cx23885_irq() handler | ||
1980 | * is hooked up by the call to request_irq() above. | ||
1981 | */ | ||
1982 | cx23885_ir_pci_int_enable(dev); | ||
1983 | cx23885_input_init(dev); | ||
1984 | |||
1899 | return 0; | 1985 | return 0; |
1900 | 1986 | ||
1901 | fail_irq: | 1987 | fail_irq: |
@@ -1912,6 +1998,9 @@ static void __devexit cx23885_finidev(struct pci_dev *pci_dev) | |||
1912 | struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); | 1998 | struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); |
1913 | struct cx23885_dev *dev = to_cx23885(v4l2_dev); | 1999 | struct cx23885_dev *dev = to_cx23885(v4l2_dev); |
1914 | 2000 | ||
2001 | cx23885_input_fini(dev); | ||
2002 | cx23885_ir_fini(dev); | ||
2003 | |||
1915 | cx23885_shutdown(dev); | 2004 | cx23885_shutdown(dev); |
1916 | 2005 | ||
1917 | pci_disable_device(pci_dev); | 2006 | pci_disable_device(pci_dev); |
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 16c6a921f40b..e45d2df08138 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include "tda18271.h" | 38 | #include "tda18271.h" |
39 | #include "lgdt330x.h" | 39 | #include "lgdt330x.h" |
40 | #include "xc5000.h" | 40 | #include "xc5000.h" |
41 | #include "max2165.h" | ||
41 | #include "tda10048.h" | 42 | #include "tda10048.h" |
42 | #include "tuner-xc2028.h" | 43 | #include "tuner-xc2028.h" |
43 | #include "tuner-simple.h" | 44 | #include "tuner-simple.h" |
@@ -54,6 +55,9 @@ | |||
54 | #include "netup-eeprom.h" | 55 | #include "netup-eeprom.h" |
55 | #include "netup-init.h" | 56 | #include "netup-init.h" |
56 | #include "lgdt3305.h" | 57 | #include "lgdt3305.h" |
58 | #include "atbm8830.h" | ||
59 | #include "ds3000.h" | ||
60 | #include "cx23885-f300.h" | ||
57 | 61 | ||
58 | static unsigned int debug; | 62 | static unsigned int debug; |
59 | 63 | ||
@@ -400,6 +404,7 @@ static struct stv0900_reg stv0900_ts_regs[] = { | |||
400 | 404 | ||
401 | static struct stv0900_config netup_stv0900_config = { | 405 | static struct stv0900_config netup_stv0900_config = { |
402 | .demod_address = 0x68, | 406 | .demod_address = 0x68, |
407 | .demod_mode = 1, /* dual */ | ||
403 | .xtal = 8000000, | 408 | .xtal = 8000000, |
404 | .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ | 409 | .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ |
405 | .diseqc_mode = 2,/* 2/3 PWM */ | 410 | .diseqc_mode = 2,/* 2/3 PWM */ |
@@ -414,34 +419,22 @@ static struct stv6110_config netup_stv6110_tunerconfig_a = { | |||
414 | .i2c_address = 0x60, | 419 | .i2c_address = 0x60, |
415 | .mclk = 16000000, | 420 | .mclk = 16000000, |
416 | .clk_div = 1, | 421 | .clk_div = 1, |
422 | .gain = 8, /* +16 dB - maximum gain */ | ||
417 | }; | 423 | }; |
418 | 424 | ||
419 | static struct stv6110_config netup_stv6110_tunerconfig_b = { | 425 | static struct stv6110_config netup_stv6110_tunerconfig_b = { |
420 | .i2c_address = 0x63, | 426 | .i2c_address = 0x63, |
421 | .mclk = 16000000, | 427 | .mclk = 16000000, |
422 | .clk_div = 1, | 428 | .clk_div = 1, |
429 | .gain = 8, /* +16 dB - maximum gain */ | ||
423 | }; | 430 | }; |
424 | 431 | ||
425 | static int tbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | ||
426 | { | ||
427 | struct cx23885_tsport *port = fe->dvb->priv; | ||
428 | struct cx23885_dev *dev = port->dev; | ||
429 | |||
430 | if (voltage == SEC_VOLTAGE_18) | ||
431 | cx_write(MC417_RWD, 0x00001e00);/* GPIO-13 high */ | ||
432 | else if (voltage == SEC_VOLTAGE_13) | ||
433 | cx_write(MC417_RWD, 0x00001a00);/* GPIO-13 low */ | ||
434 | else | ||
435 | cx_write(MC417_RWD, 0x00001800);/* GPIO-12 low */ | ||
436 | return 0; | ||
437 | } | ||
438 | |||
439 | static struct cx24116_config tbs_cx24116_config = { | 432 | static struct cx24116_config tbs_cx24116_config = { |
440 | .demod_address = 0x05, | 433 | .demod_address = 0x55, |
441 | }; | 434 | }; |
442 | 435 | ||
443 | static struct cx24116_config tevii_cx24116_config = { | 436 | static struct ds3000_config tevii_ds3000_config = { |
444 | .demod_address = 0x55, | 437 | .demod_address = 0x68, |
445 | }; | 438 | }; |
446 | 439 | ||
447 | static struct cx24116_config dvbworld_cx24116_config = { | 440 | static struct cx24116_config dvbworld_cx24116_config = { |
@@ -486,11 +479,40 @@ static int cx23885_dvb_set_frontend(struct dvb_frontend *fe, | |||
486 | break; | 479 | break; |
487 | } | 480 | } |
488 | break; | 481 | break; |
482 | case CX23885_BOARD_MYGICA_X8506: | ||
483 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: | ||
484 | /* Select Digital TV */ | ||
485 | cx23885_gpio_set(dev, GPIO_0); | ||
486 | break; | ||
489 | } | 487 | } |
490 | return (port->set_frontend_save) ? | 488 | return 0; |
491 | port->set_frontend_save(fe, param) : -ENODEV; | ||
492 | } | 489 | } |
493 | 490 | ||
491 | static int cx23885_dvb_fe_ioctl_override(struct dvb_frontend *fe, | ||
492 | unsigned int cmd, void *parg, | ||
493 | unsigned int stage) | ||
494 | { | ||
495 | int err = 0; | ||
496 | |||
497 | switch (stage) { | ||
498 | case DVB_FE_IOCTL_PRE: | ||
499 | |||
500 | switch (cmd) { | ||
501 | case FE_SET_FRONTEND: | ||
502 | err = cx23885_dvb_set_frontend(fe, | ||
503 | (struct dvb_frontend_parameters *) parg); | ||
504 | break; | ||
505 | } | ||
506 | break; | ||
507 | |||
508 | case DVB_FE_IOCTL_POST: | ||
509 | /* no post-ioctl handling required */ | ||
510 | break; | ||
511 | } | ||
512 | return err; | ||
513 | }; | ||
514 | |||
515 | |||
494 | static struct lgs8gxx_config magicpro_prohdtve2_lgs8g75_config = { | 516 | static struct lgs8gxx_config magicpro_prohdtve2_lgs8g75_config = { |
495 | .prod = LGS8GXX_PROD_LGS8G75, | 517 | .prod = LGS8GXX_PROD_LGS8G75, |
496 | .demod_address = 0x19, | 518 | .demod_address = 0x19, |
@@ -511,6 +533,38 @@ static struct xc5000_config magicpro_prohdtve2_xc5000_config = { | |||
511 | .if_khz = 6500, | 533 | .if_khz = 6500, |
512 | }; | 534 | }; |
513 | 535 | ||
536 | static struct atbm8830_config mygica_x8558pro_atbm8830_cfg1 = { | ||
537 | .prod = ATBM8830_PROD_8830, | ||
538 | .demod_address = 0x44, | ||
539 | .serial_ts = 0, | ||
540 | .ts_sampling_edge = 1, | ||
541 | .ts_clk_gated = 0, | ||
542 | .osc_clk_freq = 30400, /* in kHz */ | ||
543 | .if_freq = 0, /* zero IF */ | ||
544 | .zif_swap_iq = 1, | ||
545 | }; | ||
546 | |||
547 | static struct max2165_config mygic_x8558pro_max2165_cfg1 = { | ||
548 | .i2c_address = 0x60, | ||
549 | .osc_clk = 20 | ||
550 | }; | ||
551 | |||
552 | static struct atbm8830_config mygica_x8558pro_atbm8830_cfg2 = { | ||
553 | .prod = ATBM8830_PROD_8830, | ||
554 | .demod_address = 0x44, | ||
555 | .serial_ts = 1, | ||
556 | .ts_sampling_edge = 1, | ||
557 | .ts_clk_gated = 0, | ||
558 | .osc_clk_freq = 30400, /* in kHz */ | ||
559 | .if_freq = 0, /* zero IF */ | ||
560 | .zif_swap_iq = 1, | ||
561 | }; | ||
562 | |||
563 | static struct max2165_config mygic_x8558pro_max2165_cfg2 = { | ||
564 | .i2c_address = 0x60, | ||
565 | .osc_clk = 20 | ||
566 | }; | ||
567 | |||
514 | static int dvb_register(struct cx23885_tsport *port) | 568 | static int dvb_register(struct cx23885_tsport *port) |
515 | { | 569 | { |
516 | struct cx23885_dev *dev = port->dev; | 570 | struct cx23885_dev *dev = port->dev; |
@@ -550,12 +604,6 @@ static int dvb_register(struct cx23885_tsport *port) | |||
550 | 0x60, &dev->i2c_bus[1].i2c_adap, | 604 | 0x60, &dev->i2c_bus[1].i2c_adap, |
551 | &hauppauge_hvr127x_config); | 605 | &hauppauge_hvr127x_config); |
552 | } | 606 | } |
553 | |||
554 | /* FIXME: temporary hack */ | ||
555 | /* define bridge override to set_frontend */ | ||
556 | port->set_frontend_save = fe0->dvb.frontend->ops.set_frontend; | ||
557 | fe0->dvb.frontend->ops.set_frontend = cx23885_dvb_set_frontend; | ||
558 | |||
559 | break; | 607 | break; |
560 | case CX23885_BOARD_HAUPPAUGE_HVR1255: | 608 | case CX23885_BOARD_HAUPPAUGE_HVR1255: |
561 | i2c_bus = &dev->i2c_bus[0]; | 609 | i2c_bus = &dev->i2c_bus[0]; |
@@ -772,23 +820,23 @@ static int dvb_register(struct cx23885_tsport *port) | |||
772 | } | 820 | } |
773 | break; | 821 | break; |
774 | case CX23885_BOARD_TBS_6920: | 822 | case CX23885_BOARD_TBS_6920: |
775 | i2c_bus = &dev->i2c_bus[0]; | 823 | i2c_bus = &dev->i2c_bus[1]; |
776 | 824 | ||
777 | fe0->dvb.frontend = dvb_attach(cx24116_attach, | 825 | fe0->dvb.frontend = dvb_attach(cx24116_attach, |
778 | &tbs_cx24116_config, | 826 | &tbs_cx24116_config, |
779 | &i2c_bus->i2c_adap); | 827 | &i2c_bus->i2c_adap); |
780 | if (fe0->dvb.frontend != NULL) | 828 | if (fe0->dvb.frontend != NULL) |
781 | fe0->dvb.frontend->ops.set_voltage = tbs_set_voltage; | 829 | fe0->dvb.frontend->ops.set_voltage = f300_set_voltage; |
782 | 830 | ||
783 | break; | 831 | break; |
784 | case CX23885_BOARD_TEVII_S470: | 832 | case CX23885_BOARD_TEVII_S470: |
785 | i2c_bus = &dev->i2c_bus[1]; | 833 | i2c_bus = &dev->i2c_bus[1]; |
786 | 834 | ||
787 | fe0->dvb.frontend = dvb_attach(cx24116_attach, | 835 | fe0->dvb.frontend = dvb_attach(ds3000_attach, |
788 | &tevii_cx24116_config, | 836 | &tevii_ds3000_config, |
789 | &i2c_bus->i2c_adap); | 837 | &i2c_bus->i2c_adap); |
790 | if (fe0->dvb.frontend != NULL) | 838 | if (fe0->dvb.frontend != NULL) |
791 | fe0->dvb.frontend->ops.set_voltage = tbs_set_voltage; | 839 | fe0->dvb.frontend->ops.set_voltage = f300_set_voltage; |
792 | 840 | ||
793 | break; | 841 | break; |
794 | case CX23885_BOARD_DVBWORLD_2005: | 842 | case CX23885_BOARD_DVBWORLD_2005: |
@@ -814,8 +862,8 @@ static int dvb_register(struct cx23885_tsport *port) | |||
814 | if (!dvb_attach(lnbh24_attach, | 862 | if (!dvb_attach(lnbh24_attach, |
815 | fe0->dvb.frontend, | 863 | fe0->dvb.frontend, |
816 | &i2c_bus->i2c_adap, | 864 | &i2c_bus->i2c_adap, |
817 | LNBH24_PCL, | 865 | LNBH24_PCL | LNBH24_TTX, |
818 | LNBH24_TTX, 0x09)) | 866 | LNBH24_TEN, 0x09)) |
819 | printk(KERN_ERR | 867 | printk(KERN_ERR |
820 | "No LNBH24 found!\n"); | 868 | "No LNBH24 found!\n"); |
821 | 869 | ||
@@ -835,8 +883,8 @@ static int dvb_register(struct cx23885_tsport *port) | |||
835 | if (!dvb_attach(lnbh24_attach, | 883 | if (!dvb_attach(lnbh24_attach, |
836 | fe0->dvb.frontend, | 884 | fe0->dvb.frontend, |
837 | &i2c_bus->i2c_adap, | 885 | &i2c_bus->i2c_adap, |
838 | LNBH24_PCL, | 886 | LNBH24_PCL | LNBH24_TTX, |
839 | LNBH24_TTX, 0x0a)) | 887 | LNBH24_TEN, 0x0a)) |
840 | printk(KERN_ERR | 888 | printk(KERN_ERR |
841 | "No LNBH24 found!\n"); | 889 | "No LNBH24 found!\n"); |
842 | 890 | ||
@@ -872,6 +920,7 @@ static int dvb_register(struct cx23885_tsport *port) | |||
872 | } | 920 | } |
873 | break; | 921 | break; |
874 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | 922 | case CX23885_BOARD_HAUPPAUGE_HVR1850: |
923 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | ||
875 | i2c_bus = &dev->i2c_bus[0]; | 924 | i2c_bus = &dev->i2c_bus[0]; |
876 | fe0->dvb.frontend = dvb_attach(s5h1411_attach, | 925 | fe0->dvb.frontend = dvb_attach(s5h1411_attach, |
877 | &hcw_s5h1411_config, | 926 | &hcw_s5h1411_config, |
@@ -881,6 +930,36 @@ static int dvb_register(struct cx23885_tsport *port) | |||
881 | 0x60, &dev->i2c_bus[0].i2c_adap, | 930 | 0x60, &dev->i2c_bus[0].i2c_adap, |
882 | &hauppauge_tda18271_config); | 931 | &hauppauge_tda18271_config); |
883 | break; | 932 | break; |
933 | case CX23885_BOARD_MYGICA_X8558PRO: | ||
934 | switch (port->nr) { | ||
935 | /* port B */ | ||
936 | case 1: | ||
937 | i2c_bus = &dev->i2c_bus[0]; | ||
938 | fe0->dvb.frontend = dvb_attach(atbm8830_attach, | ||
939 | &mygica_x8558pro_atbm8830_cfg1, | ||
940 | &i2c_bus->i2c_adap); | ||
941 | if (fe0->dvb.frontend != NULL) { | ||
942 | dvb_attach(max2165_attach, | ||
943 | fe0->dvb.frontend, | ||
944 | &i2c_bus->i2c_adap, | ||
945 | &mygic_x8558pro_max2165_cfg1); | ||
946 | } | ||
947 | break; | ||
948 | /* port C */ | ||
949 | case 2: | ||
950 | i2c_bus = &dev->i2c_bus[1]; | ||
951 | fe0->dvb.frontend = dvb_attach(atbm8830_attach, | ||
952 | &mygica_x8558pro_atbm8830_cfg2, | ||
953 | &i2c_bus->i2c_adap); | ||
954 | if (fe0->dvb.frontend != NULL) { | ||
955 | dvb_attach(max2165_attach, | ||
956 | fe0->dvb.frontend, | ||
957 | &i2c_bus->i2c_adap, | ||
958 | &mygic_x8558pro_max2165_cfg2); | ||
959 | } | ||
960 | break; | ||
961 | } | ||
962 | break; | ||
884 | 963 | ||
885 | default: | 964 | default: |
886 | printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " | 965 | printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " |
@@ -897,14 +976,15 @@ static int dvb_register(struct cx23885_tsport *port) | |||
897 | fe0->dvb.frontend->callback = cx23885_tuner_callback; | 976 | fe0->dvb.frontend->callback = cx23885_tuner_callback; |
898 | 977 | ||
899 | /* Put the analog decoder in standby to keep it quiet */ | 978 | /* Put the analog decoder in standby to keep it quiet */ |
900 | call_all(dev, tuner, s_standby); | 979 | call_all(dev, core, s_power, 0); |
901 | 980 | ||
902 | if (fe0->dvb.frontend->ops.analog_ops.standby) | 981 | if (fe0->dvb.frontend->ops.analog_ops.standby) |
903 | fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend); | 982 | fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend); |
904 | 983 | ||
905 | /* register everything */ | 984 | /* register everything */ |
906 | ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, | 985 | ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, |
907 | &dev->pci->dev, adapter_nr, 0); | 986 | &dev->pci->dev, adapter_nr, 0, |
987 | cx23885_dvb_fe_ioctl_override); | ||
908 | 988 | ||
909 | /* init CI & MAC */ | 989 | /* init CI & MAC */ |
910 | switch (dev->board) { | 990 | switch (dev->board) { |
diff --git a/drivers/media/video/cx23885/cx23885-f300.c b/drivers/media/video/cx23885/cx23885-f300.c new file mode 100644 index 000000000000..93998f220986 --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-f300.c | |||
@@ -0,0 +1,177 @@ | |||
1 | /* | ||
2 | * Driver for Silicon Labs C8051F300 microcontroller. | ||
3 | * | ||
4 | * It is used for LNB power control in TeVii S470, | ||
5 | * TBS 6920 PCIe DVB-S2 cards. | ||
6 | * | ||
7 | * Microcontroller connected to cx23885 GPIO pins: | ||
8 | * GPIO0 - data - P0.3 F300 | ||
9 | * GPIO1 - reset - P0.2 F300 | ||
10 | * GPIO2 - clk - P0.1 F300 | ||
11 | * GPIO3 - busy - P0.0 F300 | ||
12 | * | ||
13 | * Copyright (C) 2009 Igor M. Liplianin <liplianin@me.by> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * | ||
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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
29 | */ | ||
30 | |||
31 | #include "cx23885.h" | ||
32 | |||
33 | #define F300_DATA GPIO_0 | ||
34 | #define F300_RESET GPIO_1 | ||
35 | #define F300_CLK GPIO_2 | ||
36 | #define F300_BUSY GPIO_3 | ||
37 | |||
38 | static void f300_set_line(struct cx23885_dev *dev, u32 line, u8 lvl) | ||
39 | { | ||
40 | cx23885_gpio_enable(dev, line, 1); | ||
41 | if (lvl == 1) | ||
42 | cx23885_gpio_set(dev, line); | ||
43 | else | ||
44 | cx23885_gpio_clear(dev, line); | ||
45 | } | ||
46 | |||
47 | static u8 f300_get_line(struct cx23885_dev *dev, u32 line) | ||
48 | { | ||
49 | cx23885_gpio_enable(dev, line, 0); | ||
50 | |||
51 | return cx23885_gpio_get(dev, line); | ||
52 | } | ||
53 | |||
54 | static void f300_send_byte(struct cx23885_dev *dev, u8 dta) | ||
55 | { | ||
56 | u8 i; | ||
57 | |||
58 | for (i = 0; i < 8; i++) { | ||
59 | f300_set_line(dev, F300_CLK, 0); | ||
60 | udelay(30); | ||
61 | f300_set_line(dev, F300_DATA, (dta & 0x80) >> 7);/* msb first */ | ||
62 | udelay(30); | ||
63 | dta <<= 1; | ||
64 | f300_set_line(dev, F300_CLK, 1); | ||
65 | udelay(30); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | static u8 f300_get_byte(struct cx23885_dev *dev) | ||
70 | { | ||
71 | u8 i, dta = 0; | ||
72 | |||
73 | for (i = 0; i < 8; i++) { | ||
74 | f300_set_line(dev, F300_CLK, 0); | ||
75 | udelay(30); | ||
76 | dta <<= 1; | ||
77 | f300_set_line(dev, F300_CLK, 1); | ||
78 | udelay(30); | ||
79 | dta |= f300_get_line(dev, F300_DATA);/* msb first */ | ||
80 | |||
81 | } | ||
82 | |||
83 | return dta; | ||
84 | } | ||
85 | |||
86 | static u8 f300_xfer(struct dvb_frontend *fe, u8 *buf) | ||
87 | { | ||
88 | struct cx23885_tsport *port = fe->dvb->priv; | ||
89 | struct cx23885_dev *dev = port->dev; | ||
90 | u8 i, temp, ret = 0; | ||
91 | |||
92 | temp = buf[0]; | ||
93 | for (i = 0; i < buf[0]; i++) | ||
94 | temp += buf[i + 1]; | ||
95 | temp = (~temp + 1);/* get check sum */ | ||
96 | buf[1 + buf[0]] = temp; | ||
97 | |||
98 | f300_set_line(dev, F300_RESET, 1); | ||
99 | f300_set_line(dev, F300_CLK, 1); | ||
100 | udelay(30); | ||
101 | f300_set_line(dev, F300_DATA, 1); | ||
102 | msleep(1); | ||
103 | |||
104 | /* question: */ | ||
105 | f300_set_line(dev, F300_RESET, 0);/* begin to send data */ | ||
106 | msleep(1); | ||
107 | |||
108 | f300_send_byte(dev, 0xe0);/* the slave address is 0xe0, write */ | ||
109 | msleep(1); | ||
110 | |||
111 | temp = buf[0]; | ||
112 | temp += 2; | ||
113 | for (i = 0; i < temp; i++) | ||
114 | f300_send_byte(dev, buf[i]); | ||
115 | |||
116 | f300_set_line(dev, F300_RESET, 1);/* sent data over */ | ||
117 | f300_set_line(dev, F300_DATA, 1); | ||
118 | |||
119 | /* answer: */ | ||
120 | temp = 0; | ||
121 | for (i = 0; ((i < 8) & (temp == 0)); i++) { | ||
122 | msleep(1); | ||
123 | if (f300_get_line(dev, F300_BUSY) == 0) | ||
124 | temp = 1; | ||
125 | } | ||
126 | |||
127 | if (i > 7) { | ||
128 | printk(KERN_ERR "%s: timeout, the slave no response\n", | ||
129 | __func__); | ||
130 | ret = 1; /* timeout, the slave no response */ | ||
131 | } else { /* the slave not busy, prepare for getting data */ | ||
132 | f300_set_line(dev, F300_RESET, 0);/*ready...*/ | ||
133 | msleep(1); | ||
134 | f300_send_byte(dev, 0xe1);/* 0xe1 is Read */ | ||
135 | msleep(1); | ||
136 | temp = f300_get_byte(dev);/*get the data length */ | ||
137 | if (temp > 14) | ||
138 | temp = 14; | ||
139 | |||
140 | for (i = 0; i < (temp + 1); i++) | ||
141 | f300_get_byte(dev);/* get data to empty buffer */ | ||
142 | |||
143 | f300_set_line(dev, F300_RESET, 1);/* received data over */ | ||
144 | f300_set_line(dev, F300_DATA, 1); | ||
145 | } | ||
146 | |||
147 | return ret; | ||
148 | } | ||
149 | |||
150 | int f300_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | ||
151 | { | ||
152 | u8 buf[16]; | ||
153 | |||
154 | buf[0] = 0x05; | ||
155 | buf[1] = 0x38;/* write port */ | ||
156 | buf[2] = 0x01;/* A port, lnb power */ | ||
157 | |||
158 | switch (voltage) { | ||
159 | case SEC_VOLTAGE_13: | ||
160 | buf[3] = 0x01;/* power on */ | ||
161 | buf[4] = 0x02;/* B port, H/V */ | ||
162 | buf[5] = 0x00;/*13V v*/ | ||
163 | break; | ||
164 | case SEC_VOLTAGE_18: | ||
165 | buf[3] = 0x01; | ||
166 | buf[4] = 0x02; | ||
167 | buf[5] = 0x01;/* 18V h*/ | ||
168 | break; | ||
169 | case SEC_VOLTAGE_OFF: | ||
170 | buf[3] = 0x00;/* power off */ | ||
171 | buf[4] = 0x00; | ||
172 | buf[5] = 0x00; | ||
173 | break; | ||
174 | } | ||
175 | |||
176 | return f300_xfer(fe, buf); | ||
177 | } | ||
diff --git a/drivers/media/video/cx23885/cx23885-f300.h b/drivers/media/video/cx23885/cx23885-f300.h new file mode 100644 index 000000000000..e73344c94963 --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-f300.h | |||
@@ -0,0 +1,2 @@ | |||
1 | extern int f300_set_voltage(struct dvb_frontend *fe, | ||
2 | fe_sec_voltage_t voltage); | ||
diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c new file mode 100644 index 000000000000..469e083dd5f8 --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-input.c | |||
@@ -0,0 +1,427 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX23885/7/8 PCIe bridge | ||
3 | * | ||
4 | * Infrared remote control input device | ||
5 | * | ||
6 | * Most of this file is | ||
7 | * | ||
8 | * Copyright (C) 2009 Andy Walls <awalls@radix.net> | ||
9 | * | ||
10 | * However, the cx23885_input_{init,fini} functions contained herein are | ||
11 | * derived from Linux kernel files linux/media/video/.../...-input.c marked as: | ||
12 | * | ||
13 | * Copyright (C) 2008 <srinivasa.deevi at conexant dot com> | ||
14 | * Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> | ||
15 | * Markus Rechberger <mrechberger@gmail.com> | ||
16 | * Mauro Carvalho Chehab <mchehab@infradead.org> | ||
17 | * Sascha Sommer <saschasommer@freenet.de> | ||
18 | * Copyright (C) 2004, 2005 Chris Pascoe | ||
19 | * Copyright (C) 2003, 2004 Gerd Knorr | ||
20 | * Copyright (C) 2003 Pavel Machek | ||
21 | * | ||
22 | * This program is free software; you can redistribute it and/or | ||
23 | * modify it under the terms of the GNU General Public License | ||
24 | * as published by the Free Software Foundation; either version 2 | ||
25 | * of the License, or (at your option) any later version. | ||
26 | * | ||
27 | * This program is distributed in the hope that it will be useful, | ||
28 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
29 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
30 | * GNU General Public License for more details. | ||
31 | * | ||
32 | * You should have received a copy of the GNU General Public License | ||
33 | * along with this program; if not, write to the Free Software | ||
34 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
35 | * 02110-1301, USA. | ||
36 | */ | ||
37 | |||
38 | #include <linux/input.h> | ||
39 | #include <media/ir-common.h> | ||
40 | #include <media/v4l2-subdev.h> | ||
41 | |||
42 | #include "cx23885.h" | ||
43 | |||
44 | #define RC5_BITS 14 | ||
45 | #define RC5_HALF_BITS (2*RC5_BITS) | ||
46 | #define RC5_HALF_BITS_MASK ((1 << RC5_HALF_BITS) - 1) | ||
47 | |||
48 | #define RC5_START_BITS_NORMAL 0x3 /* Command range 0 - 63 */ | ||
49 | #define RC5_START_BITS_EXTENDED 0x2 /* Command range 64 - 127 */ | ||
50 | |||
51 | #define RC5_EXTENDED_COMMAND_OFFSET 64 | ||
52 | |||
53 | static inline unsigned int rc5_command(u32 rc5_baseband) | ||
54 | { | ||
55 | return RC5_INSTR(rc5_baseband) + | ||
56 | ((RC5_START(rc5_baseband) == RC5_START_BITS_EXTENDED) | ||
57 | ? RC5_EXTENDED_COMMAND_OFFSET : 0); | ||
58 | } | ||
59 | |||
60 | static void cx23885_input_process_raw_rc5(struct cx23885_dev *dev) | ||
61 | { | ||
62 | struct card_ir *ir_input = dev->ir_input; | ||
63 | unsigned int code, command; | ||
64 | u32 rc5; | ||
65 | |||
66 | /* Ignore codes that are too short to be valid RC-5 */ | ||
67 | if (ir_input->last_bit < (RC5_HALF_BITS - 1)) | ||
68 | return; | ||
69 | |||
70 | /* The library has the manchester coding backwards; XOR to adapt. */ | ||
71 | code = (ir_input->code & RC5_HALF_BITS_MASK) ^ RC5_HALF_BITS_MASK; | ||
72 | rc5 = ir_rc5_decode(code); | ||
73 | |||
74 | switch (RC5_START(rc5)) { | ||
75 | case RC5_START_BITS_NORMAL: | ||
76 | break; | ||
77 | case RC5_START_BITS_EXTENDED: | ||
78 | /* Don't allow if the remote only emits standard commands */ | ||
79 | if (ir_input->start == RC5_START_BITS_NORMAL) | ||
80 | return; | ||
81 | break; | ||
82 | default: | ||
83 | return; | ||
84 | } | ||
85 | |||
86 | if (ir_input->addr != RC5_ADDR(rc5)) | ||
87 | return; | ||
88 | |||
89 | /* Don't generate a keypress for RC-5 auto-repeated keypresses */ | ||
90 | command = rc5_command(rc5); | ||
91 | if (RC5_TOGGLE(rc5) != RC5_TOGGLE(ir_input->last_rc5) || | ||
92 | command != rc5_command(ir_input->last_rc5) || | ||
93 | /* Catch T == 0, CMD == 0 (e.g. '0') as first keypress after init */ | ||
94 | RC5_START(ir_input->last_rc5) == 0) { | ||
95 | /* This keypress is differnet: not an auto repeat */ | ||
96 | ir_input_nokey(ir_input->dev, &ir_input->ir); | ||
97 | ir_input_keydown(ir_input->dev, &ir_input->ir, command); | ||
98 | } | ||
99 | ir_input->last_rc5 = rc5; | ||
100 | |||
101 | /* Schedule when we should do the key up event: ir_input_nokey() */ | ||
102 | mod_timer(&ir_input->timer_keyup, | ||
103 | jiffies + msecs_to_jiffies(ir_input->rc5_key_timeout)); | ||
104 | } | ||
105 | |||
106 | static void cx23885_input_next_pulse_width_rc5(struct cx23885_dev *dev, | ||
107 | u32 ns_pulse) | ||
108 | { | ||
109 | const int rc5_quarterbit_ns = 444444; /* 32 cycles/36 kHz/2 = 444 us */ | ||
110 | struct card_ir *ir_input = dev->ir_input; | ||
111 | int i, level, quarterbits, halfbits; | ||
112 | |||
113 | if (!ir_input->active) { | ||
114 | ir_input->active = 1; | ||
115 | /* assume an initial space that we may not detect or measure */ | ||
116 | ir_input->code = 0; | ||
117 | ir_input->last_bit = 0; | ||
118 | } | ||
119 | |||
120 | if (ns_pulse == V4L2_SUBDEV_IR_PULSE_RX_SEQ_END) { | ||
121 | ir_input->last_bit++; /* Account for the final space */ | ||
122 | ir_input->active = 0; | ||
123 | cx23885_input_process_raw_rc5(dev); | ||
124 | return; | ||
125 | } | ||
126 | |||
127 | level = (ns_pulse & V4L2_SUBDEV_IR_PULSE_LEVEL_MASK) ? 1 : 0; | ||
128 | |||
129 | /* Skip any leading space to sync to the start bit */ | ||
130 | if (ir_input->last_bit == 0 && level == 0) | ||
131 | return; | ||
132 | |||
133 | /* | ||
134 | * With valid RC-5 we can get up to two consecutive half-bits in a | ||
135 | * single pulse measurment. Experiments have shown that the duration | ||
136 | * of a half-bit can vary. Make sure we always end up with an even | ||
137 | * number of quarter bits at the same level (mark or space). | ||
138 | */ | ||
139 | ns_pulse &= V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS; | ||
140 | quarterbits = ns_pulse / rc5_quarterbit_ns; | ||
141 | if (quarterbits & 1) | ||
142 | quarterbits++; | ||
143 | halfbits = quarterbits / 2; | ||
144 | |||
145 | for (i = 0; i < halfbits; i++) { | ||
146 | ir_input->last_bit++; | ||
147 | ir_input->code |= (level << ir_input->last_bit); | ||
148 | |||
149 | if (ir_input->last_bit >= RC5_HALF_BITS-1) { | ||
150 | ir_input->active = 0; | ||
151 | cx23885_input_process_raw_rc5(dev); | ||
152 | /* | ||
153 | * If level is 1, a leading mark is invalid for RC5. | ||
154 | * If level is 0, we scan past extra intial space. | ||
155 | * Either way we don't want to reactivate collecting | ||
156 | * marks or spaces here with any left over half-bits. | ||
157 | */ | ||
158 | break; | ||
159 | } | ||
160 | } | ||
161 | } | ||
162 | |||
163 | static void cx23885_input_process_pulse_widths_rc5(struct cx23885_dev *dev, | ||
164 | bool add_eom) | ||
165 | { | ||
166 | struct card_ir *ir_input = dev->ir_input; | ||
167 | struct ir_input_state *ir_input_state = &ir_input->ir; | ||
168 | |||
169 | u32 ns_pulse[RC5_HALF_BITS+1]; | ||
170 | ssize_t num = 0; | ||
171 | int count, i; | ||
172 | |||
173 | do { | ||
174 | v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) ns_pulse, | ||
175 | sizeof(ns_pulse), &num); | ||
176 | |||
177 | count = num / sizeof(u32); | ||
178 | |||
179 | /* Append an end of Rx seq, if the caller requested */ | ||
180 | if (add_eom && count < ARRAY_SIZE(ns_pulse)) { | ||
181 | ns_pulse[count] = V4L2_SUBDEV_IR_PULSE_RX_SEQ_END; | ||
182 | count++; | ||
183 | } | ||
184 | |||
185 | /* Just drain the Rx FIFO, if we're called, but not RC-5 */ | ||
186 | if (ir_input_state->ir_type != IR_TYPE_RC5) | ||
187 | continue; | ||
188 | |||
189 | for (i = 0; i < count; i++) | ||
190 | cx23885_input_next_pulse_width_rc5(dev, ns_pulse[i]); | ||
191 | } while (num != 0); | ||
192 | } | ||
193 | |||
194 | void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events) | ||
195 | { | ||
196 | struct v4l2_subdev_ir_parameters params; | ||
197 | int overrun, data_available; | ||
198 | |||
199 | if (dev->sd_ir == NULL || events == 0) | ||
200 | return; | ||
201 | |||
202 | switch (dev->board) { | ||
203 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | ||
204 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | ||
205 | /* | ||
206 | * The only board we handle right now. However other boards | ||
207 | * using the CX2388x integrated IR controller should be similar | ||
208 | */ | ||
209 | break; | ||
210 | default: | ||
211 | return; | ||
212 | } | ||
213 | |||
214 | overrun = events & (V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN | | ||
215 | V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN); | ||
216 | |||
217 | data_available = events & (V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED | | ||
218 | V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ); | ||
219 | |||
220 | if (overrun) { | ||
221 | /* If there was a FIFO overrun, stop the device */ | ||
222 | v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, ¶ms); | ||
223 | params.enable = false; | ||
224 | /* Mitigate race with cx23885_input_ir_stop() */ | ||
225 | params.shutdown = atomic_read(&dev->ir_input_stopping); | ||
226 | v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, ¶ms); | ||
227 | } | ||
228 | |||
229 | if (data_available) | ||
230 | cx23885_input_process_pulse_widths_rc5(dev, overrun); | ||
231 | |||
232 | if (overrun) { | ||
233 | /* If there was a FIFO overrun, clear & restart the device */ | ||
234 | params.enable = true; | ||
235 | /* Mitigate race with cx23885_input_ir_stop() */ | ||
236 | params.shutdown = atomic_read(&dev->ir_input_stopping); | ||
237 | v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, ¶ms); | ||
238 | } | ||
239 | } | ||
240 | |||
241 | static void cx23885_input_ir_start(struct cx23885_dev *dev) | ||
242 | { | ||
243 | struct card_ir *ir_input = dev->ir_input; | ||
244 | struct ir_input_state *ir_input_state = &ir_input->ir; | ||
245 | struct v4l2_subdev_ir_parameters params; | ||
246 | |||
247 | if (dev->sd_ir == NULL) | ||
248 | return; | ||
249 | |||
250 | atomic_set(&dev->ir_input_stopping, 0); | ||
251 | |||
252 | /* keyup timer set up, if needed */ | ||
253 | switch (dev->board) { | ||
254 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | ||
255 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | ||
256 | setup_timer(&ir_input->timer_keyup, | ||
257 | ir_rc5_timer_keyup, /* Not actually RC-5 specific */ | ||
258 | (unsigned long) ir_input); | ||
259 | if (ir_input_state->ir_type == IR_TYPE_RC5) { | ||
260 | /* | ||
261 | * RC-5 repeats a held key every | ||
262 | * 64 bits * (2 * 32/36000) sec/bit = 113.778 ms | ||
263 | */ | ||
264 | ir_input->rc5_key_timeout = 115; | ||
265 | } | ||
266 | break; | ||
267 | } | ||
268 | |||
269 | v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, ¶ms); | ||
270 | switch (dev->board) { | ||
271 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | ||
272 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | ||
273 | /* | ||
274 | * The IR controller on this board only returns pulse widths. | ||
275 | * Any other mode setting will fail to set up the device. | ||
276 | */ | ||
277 | params.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH; | ||
278 | params.enable = true; | ||
279 | params.interrupt_enable = true; | ||
280 | params.shutdown = false; | ||
281 | |||
282 | /* Setup for baseband compatible with both RC-5 and RC-6A */ | ||
283 | params.modulation = false; | ||
284 | /* RC-5: 2,222,222 ns = 1/36 kHz * 32 cycles * 2 marks * 1.25*/ | ||
285 | /* RC-6A: 3,333,333 ns = 1/36 kHz * 16 cycles * 6 marks * 1.25*/ | ||
286 | params.max_pulse_width = 3333333; /* ns */ | ||
287 | /* RC-5: 666,667 ns = 1/36 kHz * 32 cycles * 1 mark * 0.75 */ | ||
288 | /* RC-6A: 333,333 ns = 1/36 kHz * 16 cycles * 1 mark * 0.75 */ | ||
289 | params.noise_filter_min_width = 333333; /* ns */ | ||
290 | /* | ||
291 | * This board has inverted receive sense: | ||
292 | * mark is received as low logic level; | ||
293 | * falling edges are detected as rising edges; etc. | ||
294 | */ | ||
295 | params.invert = true; | ||
296 | break; | ||
297 | } | ||
298 | v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, ¶ms); | ||
299 | } | ||
300 | |||
301 | static void cx23885_input_ir_stop(struct cx23885_dev *dev) | ||
302 | { | ||
303 | struct card_ir *ir_input = dev->ir_input; | ||
304 | struct v4l2_subdev_ir_parameters params; | ||
305 | |||
306 | if (dev->sd_ir == NULL) | ||
307 | return; | ||
308 | |||
309 | /* | ||
310 | * Stop the sd_ir subdevice from generating notifications and | ||
311 | * scheduling work. | ||
312 | * It is shutdown this way in order to mitigate a race with | ||
313 | * cx23885_input_rx_work_handler() in the overrun case, which could | ||
314 | * re-enable the subdevice. | ||
315 | */ | ||
316 | atomic_set(&dev->ir_input_stopping, 1); | ||
317 | v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, ¶ms); | ||
318 | while (params.shutdown == false) { | ||
319 | params.enable = false; | ||
320 | params.interrupt_enable = false; | ||
321 | params.shutdown = true; | ||
322 | v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, ¶ms); | ||
323 | v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, ¶ms); | ||
324 | } | ||
325 | |||
326 | flush_scheduled_work(); | ||
327 | |||
328 | switch (dev->board) { | ||
329 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | ||
330 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | ||
331 | del_timer_sync(&ir_input->timer_keyup); | ||
332 | break; | ||
333 | } | ||
334 | } | ||
335 | |||
336 | int cx23885_input_init(struct cx23885_dev *dev) | ||
337 | { | ||
338 | struct card_ir *ir; | ||
339 | struct input_dev *input_dev; | ||
340 | struct ir_scancode_table *ir_codes = NULL; | ||
341 | int ir_type, ir_addr, ir_start; | ||
342 | int ret; | ||
343 | |||
344 | /* | ||
345 | * If the IR device (hardware registers, chip, GPIO lines, etc.) isn't | ||
346 | * encapsulated in a v4l2_subdev, then I'm not going to deal with it. | ||
347 | */ | ||
348 | if (dev->sd_ir == NULL) | ||
349 | return -ENODEV; | ||
350 | |||
351 | switch (dev->board) { | ||
352 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | ||
353 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | ||
354 | /* Parameters for the grey Hauppauge remote for the HVR-1850 */ | ||
355 | ir_codes = &ir_codes_hauppauge_new_table; | ||
356 | ir_type = IR_TYPE_RC5; | ||
357 | ir_addr = 0x1e; /* RC-5 system bits emitted by the remote */ | ||
358 | ir_start = RC5_START_BITS_NORMAL; /* A basic RC-5 remote */ | ||
359 | break; | ||
360 | } | ||
361 | if (ir_codes == NULL) | ||
362 | return -ENODEV; | ||
363 | |||
364 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | ||
365 | input_dev = input_allocate_device(); | ||
366 | if (!ir || !input_dev) { | ||
367 | ret = -ENOMEM; | ||
368 | goto err_out_free; | ||
369 | } | ||
370 | |||
371 | ir->dev = input_dev; | ||
372 | ir->addr = ir_addr; | ||
373 | ir->start = ir_start; | ||
374 | |||
375 | /* init input device */ | ||
376 | snprintf(ir->name, sizeof(ir->name), "cx23885 IR (%s)", | ||
377 | cx23885_boards[dev->board].name); | ||
378 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(dev->pci)); | ||
379 | |||
380 | ret = ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); | ||
381 | if (ret < 0) | ||
382 | goto err_out_free; | ||
383 | |||
384 | input_dev->name = ir->name; | ||
385 | input_dev->phys = ir->phys; | ||
386 | input_dev->id.bustype = BUS_PCI; | ||
387 | input_dev->id.version = 1; | ||
388 | if (dev->pci->subsystem_vendor) { | ||
389 | input_dev->id.vendor = dev->pci->subsystem_vendor; | ||
390 | input_dev->id.product = dev->pci->subsystem_device; | ||
391 | } else { | ||
392 | input_dev->id.vendor = dev->pci->vendor; | ||
393 | input_dev->id.product = dev->pci->device; | ||
394 | } | ||
395 | input_dev->dev.parent = &dev->pci->dev; | ||
396 | |||
397 | dev->ir_input = ir; | ||
398 | cx23885_input_ir_start(dev); | ||
399 | |||
400 | ret = input_register_device(ir->dev); | ||
401 | if (ret) | ||
402 | goto err_out_stop; | ||
403 | |||
404 | return 0; | ||
405 | |||
406 | err_out_stop: | ||
407 | cx23885_input_ir_stop(dev); | ||
408 | dev->ir_input = NULL; | ||
409 | err_out_free: | ||
410 | ir_input_free(input_dev); | ||
411 | input_free_device(input_dev); | ||
412 | kfree(ir); | ||
413 | return ret; | ||
414 | } | ||
415 | |||
416 | void cx23885_input_fini(struct cx23885_dev *dev) | ||
417 | { | ||
418 | /* Always stop the IR hardware from generating interrupts */ | ||
419 | cx23885_input_ir_stop(dev); | ||
420 | |||
421 | if (dev->ir_input == NULL) | ||
422 | return; | ||
423 | ir_input_free(dev->ir_input->dev); | ||
424 | input_unregister_device(dev->ir_input->dev); | ||
425 | kfree(dev->ir_input); | ||
426 | dev->ir_input = NULL; | ||
427 | } | ||
diff --git a/drivers/media/video/cx23885/cx23885-input.h b/drivers/media/video/cx23885/cx23885-input.h new file mode 100644 index 000000000000..3572cb1ecfc2 --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-input.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX23885/7/8 PCIe bridge | ||
3 | * | ||
4 | * Infrared remote control input device | ||
5 | * | ||
6 | * Copyright (C) 2009 Andy Walls <awalls@radix.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version 2 | ||
11 | * of the License, or (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 | #ifndef _CX23885_INPUT_H_ | ||
25 | #define _CX23885_INPUT_H_ | ||
26 | int cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events); | ||
27 | |||
28 | int cx23885_input_init(struct cx23885_dev *dev); | ||
29 | void cx23885_input_fini(struct cx23885_dev *dev); | ||
30 | #endif | ||
diff --git a/drivers/media/video/cx23885/cx23885-ioctl.c b/drivers/media/video/cx23885/cx23885-ioctl.c new file mode 100644 index 000000000000..dfb4627fb340 --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-ioctl.c | |||
@@ -0,0 +1,208 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX23885/7/8 PCIe bridge | ||
3 | * | ||
4 | * Various common ioctl() support functions | ||
5 | * | ||
6 | * Copyright (c) 2009 Andy Walls <awalls@radix.net> | ||
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 | * | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #include "cx23885.h" | ||
25 | #include <media/v4l2-chip-ident.h> | ||
26 | |||
27 | int cx23885_g_chip_ident(struct file *file, void *fh, | ||
28 | struct v4l2_dbg_chip_ident *chip) | ||
29 | { | ||
30 | struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; | ||
31 | int err = 0; | ||
32 | u8 rev; | ||
33 | |||
34 | chip->ident = V4L2_IDENT_NONE; | ||
35 | chip->revision = 0; | ||
36 | switch (chip->match.type) { | ||
37 | case V4L2_CHIP_MATCH_HOST: | ||
38 | switch (chip->match.addr) { | ||
39 | case 0: | ||
40 | rev = cx_read(RDR_CFG2) & 0xff; | ||
41 | switch (dev->pci->device) { | ||
42 | case 0x8852: | ||
43 | /* rev 0x04 could be '885 or '888. Pick '888. */ | ||
44 | if (rev == 0x04) | ||
45 | chip->ident = V4L2_IDENT_CX23888; | ||
46 | else | ||
47 | chip->ident = V4L2_IDENT_CX23885; | ||
48 | break; | ||
49 | case 0x8880: | ||
50 | if (rev == 0x0e || rev == 0x0f) | ||
51 | chip->ident = V4L2_IDENT_CX23887; | ||
52 | else | ||
53 | chip->ident = V4L2_IDENT_CX23888; | ||
54 | break; | ||
55 | default: | ||
56 | chip->ident = V4L2_IDENT_UNKNOWN; | ||
57 | break; | ||
58 | } | ||
59 | chip->revision = (dev->pci->device << 16) | (rev << 8) | | ||
60 | (dev->hwrevision & 0xff); | ||
61 | break; | ||
62 | case 1: | ||
63 | if (dev->v4l_device != NULL) { | ||
64 | chip->ident = V4L2_IDENT_CX23417; | ||
65 | chip->revision = 0; | ||
66 | } | ||
67 | break; | ||
68 | case 2: | ||
69 | /* | ||
70 | * The integrated IR controller on the CX23888 is | ||
71 | * host chip 2. It may not be used/initialized or sd_ir | ||
72 | * may be pointing at the cx25840 subdevice for the | ||
73 | * IR controller on the CX23885. Thus we find it | ||
74 | * without using the dev->sd_ir pointer. | ||
75 | */ | ||
76 | call_hw(dev, CX23885_HW_888_IR, core, g_chip_ident, | ||
77 | chip); | ||
78 | break; | ||
79 | default: | ||
80 | err = -EINVAL; /* per V4L2 spec */ | ||
81 | break; | ||
82 | } | ||
83 | break; | ||
84 | case V4L2_CHIP_MATCH_I2C_DRIVER: | ||
85 | /* If needed, returns V4L2_IDENT_AMBIGUOUS without extra work */ | ||
86 | call_all(dev, core, g_chip_ident, chip); | ||
87 | break; | ||
88 | case V4L2_CHIP_MATCH_I2C_ADDR: | ||
89 | /* | ||
90 | * We could return V4L2_IDENT_UNKNOWN, but we don't do the work | ||
91 | * to look if a chip is at the address with no driver. That's a | ||
92 | * dangerous thing to do with EEPROMs anyway. | ||
93 | */ | ||
94 | call_all(dev, core, g_chip_ident, chip); | ||
95 | break; | ||
96 | default: | ||
97 | err = -EINVAL; | ||
98 | break; | ||
99 | } | ||
100 | return err; | ||
101 | } | ||
102 | |||
103 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
104 | static int cx23885_g_host_register(struct cx23885_dev *dev, | ||
105 | struct v4l2_dbg_register *reg) | ||
106 | { | ||
107 | if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0)) | ||
108 | return -EINVAL; | ||
109 | |||
110 | reg->size = 4; | ||
111 | reg->val = cx_read(reg->reg); | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static int cx23417_g_register(struct cx23885_dev *dev, | ||
116 | struct v4l2_dbg_register *reg) | ||
117 | { | ||
118 | u32 value; | ||
119 | |||
120 | if (dev->v4l_device == NULL) | ||
121 | return -EINVAL; | ||
122 | |||
123 | if ((reg->reg & 0x3) != 0 || reg->reg >= 0x10000) | ||
124 | return -EINVAL; | ||
125 | |||
126 | if (mc417_register_read(dev, (u16) reg->reg, &value)) | ||
127 | return -EINVAL; /* V4L2 spec, but -EREMOTEIO really */ | ||
128 | |||
129 | reg->size = 4; | ||
130 | reg->val = value; | ||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | int cx23885_g_register(struct file *file, void *fh, | ||
135 | struct v4l2_dbg_register *reg) | ||
136 | { | ||
137 | struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; | ||
138 | |||
139 | if (!capable(CAP_SYS_ADMIN)) | ||
140 | return -EPERM; | ||
141 | |||
142 | if (reg->match.type == V4L2_CHIP_MATCH_HOST) { | ||
143 | switch (reg->match.addr) { | ||
144 | case 0: | ||
145 | return cx23885_g_host_register(dev, reg); | ||
146 | case 1: | ||
147 | return cx23417_g_register(dev, reg); | ||
148 | default: | ||
149 | break; | ||
150 | } | ||
151 | } | ||
152 | |||
153 | /* FIXME - any error returns should not be ignored */ | ||
154 | call_all(dev, core, g_register, reg); | ||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static int cx23885_s_host_register(struct cx23885_dev *dev, | ||
159 | struct v4l2_dbg_register *reg) | ||
160 | { | ||
161 | if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0)) | ||
162 | return -EINVAL; | ||
163 | |||
164 | reg->size = 4; | ||
165 | cx_write(reg->reg, reg->val); | ||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static int cx23417_s_register(struct cx23885_dev *dev, | ||
170 | struct v4l2_dbg_register *reg) | ||
171 | { | ||
172 | if (dev->v4l_device == NULL) | ||
173 | return -EINVAL; | ||
174 | |||
175 | if ((reg->reg & 0x3) != 0 || reg->reg >= 0x10000) | ||
176 | return -EINVAL; | ||
177 | |||
178 | if (mc417_register_write(dev, (u16) reg->reg, (u32) reg->val)) | ||
179 | return -EINVAL; /* V4L2 spec, but -EREMOTEIO really */ | ||
180 | |||
181 | reg->size = 4; | ||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | int cx23885_s_register(struct file *file, void *fh, | ||
186 | struct v4l2_dbg_register *reg) | ||
187 | { | ||
188 | struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; | ||
189 | |||
190 | if (!capable(CAP_SYS_ADMIN)) | ||
191 | return -EPERM; | ||
192 | |||
193 | if (reg->match.type == V4L2_CHIP_MATCH_HOST) { | ||
194 | switch (reg->match.addr) { | ||
195 | case 0: | ||
196 | return cx23885_s_host_register(dev, reg); | ||
197 | case 1: | ||
198 | return cx23417_s_register(dev, reg); | ||
199 | default: | ||
200 | break; | ||
201 | } | ||
202 | } | ||
203 | |||
204 | /* FIXME - any error returns should not be ignored */ | ||
205 | call_all(dev, core, s_register, reg); | ||
206 | return 0; | ||
207 | } | ||
208 | #endif | ||
diff --git a/drivers/media/video/cx23885/cx23885-ioctl.h b/drivers/media/video/cx23885/cx23885-ioctl.h new file mode 100644 index 000000000000..80b0f4923c6a --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-ioctl.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX23885/7/8 PCIe bridge | ||
3 | * | ||
4 | * Various common ioctl() support functions | ||
5 | * | ||
6 | * Copyright (c) 2009 Andy Walls <awalls@radix.net> | ||
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 | * | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #ifndef _CX23885_IOCTL_H_ | ||
25 | #define _CX23885_IOCTL_H_ | ||
26 | |||
27 | int cx23885_g_chip_ident(struct file *file, void *fh, | ||
28 | struct v4l2_dbg_chip_ident *chip); | ||
29 | |||
30 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
31 | int cx23885_g_register(struct file *file, void *fh, | ||
32 | struct v4l2_dbg_register *reg); | ||
33 | |||
34 | |||
35 | int cx23885_s_register(struct file *file, void *fh, | ||
36 | struct v4l2_dbg_register *reg); | ||
37 | |||
38 | #endif | ||
39 | #endif | ||
diff --git a/drivers/media/video/cx23885/cx23885-ir.c b/drivers/media/video/cx23885/cx23885-ir.c new file mode 100644 index 000000000000..6ae982cc9856 --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-ir.c | |||
@@ -0,0 +1,101 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX23885/7/8 PCIe bridge | ||
3 | * | ||
4 | * Infrared device support routines - non-input, non-vl42_subdev routines | ||
5 | * | ||
6 | * Copyright (C) 2009 Andy Walls <awalls@radix.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version 2 | ||
11 | * of the License, or (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 <media/v4l2-device.h> | ||
25 | |||
26 | #include "cx23885.h" | ||
27 | #include "cx23885-input.h" | ||
28 | |||
29 | #define CX23885_IR_RX_FIFO_SERVICE_REQ 0 | ||
30 | #define CX23885_IR_RX_END_OF_RX_DETECTED 1 | ||
31 | #define CX23885_IR_RX_HW_FIFO_OVERRUN 2 | ||
32 | #define CX23885_IR_RX_SW_FIFO_OVERRUN 3 | ||
33 | |||
34 | #define CX23885_IR_TX_FIFO_SERVICE_REQ 0 | ||
35 | |||
36 | |||
37 | void cx23885_ir_rx_work_handler(struct work_struct *work) | ||
38 | { | ||
39 | struct cx23885_dev *dev = | ||
40 | container_of(work, struct cx23885_dev, ir_rx_work); | ||
41 | u32 events = 0; | ||
42 | unsigned long *notifications = &dev->ir_rx_notifications; | ||
43 | |||
44 | if (test_and_clear_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications)) | ||
45 | events |= V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN; | ||
46 | if (test_and_clear_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications)) | ||
47 | events |= V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN; | ||
48 | if (test_and_clear_bit(CX23885_IR_RX_END_OF_RX_DETECTED, notifications)) | ||
49 | events |= V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED; | ||
50 | if (test_and_clear_bit(CX23885_IR_RX_FIFO_SERVICE_REQ, notifications)) | ||
51 | events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ; | ||
52 | |||
53 | if (events == 0) | ||
54 | return; | ||
55 | |||
56 | if (dev->ir_input) | ||
57 | cx23885_input_rx_work_handler(dev, events); | ||
58 | } | ||
59 | |||
60 | void cx23885_ir_tx_work_handler(struct work_struct *work) | ||
61 | { | ||
62 | struct cx23885_dev *dev = | ||
63 | container_of(work, struct cx23885_dev, ir_tx_work); | ||
64 | u32 events = 0; | ||
65 | unsigned long *notifications = &dev->ir_tx_notifications; | ||
66 | |||
67 | if (test_and_clear_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications)) | ||
68 | events |= V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ; | ||
69 | |||
70 | if (events == 0) | ||
71 | return; | ||
72 | |||
73 | } | ||
74 | |||
75 | /* Called in an IRQ context */ | ||
76 | void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events) | ||
77 | { | ||
78 | struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev); | ||
79 | unsigned long *notifications = &dev->ir_rx_notifications; | ||
80 | |||
81 | if (events & V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ) | ||
82 | set_bit(CX23885_IR_RX_FIFO_SERVICE_REQ, notifications); | ||
83 | if (events & V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED) | ||
84 | set_bit(CX23885_IR_RX_END_OF_RX_DETECTED, notifications); | ||
85 | if (events & V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN) | ||
86 | set_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications); | ||
87 | if (events & V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN) | ||
88 | set_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications); | ||
89 | schedule_work(&dev->ir_rx_work); | ||
90 | } | ||
91 | |||
92 | /* Called in an IRQ context */ | ||
93 | void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events) | ||
94 | { | ||
95 | struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev); | ||
96 | unsigned long *notifications = &dev->ir_tx_notifications; | ||
97 | |||
98 | if (events & V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ) | ||
99 | set_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications); | ||
100 | schedule_work(&dev->ir_tx_work); | ||
101 | } | ||
diff --git a/drivers/media/video/cx23885/cx23885-ir.h b/drivers/media/video/cx23885/cx23885-ir.h new file mode 100644 index 000000000000..9b8a6d5d1ef6 --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-ir.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX23885/7/8 PCIe bridge | ||
3 | * | ||
4 | * Infrared device support routines - non-input, non-vl42_subdev routines | ||
5 | * | ||
6 | * Copyright (C) 2009 Andy Walls <awalls@radix.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version 2 | ||
11 | * of the License, or (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 | #ifndef _CX23885_IR_H_ | ||
25 | #define _CX23885_IR_H_ | ||
26 | void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events); | ||
27 | void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events); | ||
28 | |||
29 | void cx23885_ir_rx_work_handler(struct work_struct *work); | ||
30 | void cx23885_ir_tx_work_handler(struct work_struct *work); | ||
31 | #endif | ||
diff --git a/drivers/media/video/cx23885/cx23885-reg.h b/drivers/media/video/cx23885/cx23885-reg.h index eafbe5226bae..c0bc9a068954 100644 --- a/drivers/media/video/cx23885/cx23885-reg.h +++ b/drivers/media/video/cx23885/cx23885-reg.h | |||
@@ -212,8 +212,9 @@ Channel manager Data Structure entry = 20 DWORD | |||
212 | 212 | ||
213 | #define DEV_CNTRL2 0x00040000 | 213 | #define DEV_CNTRL2 0x00040000 |
214 | 214 | ||
215 | #define PCI_MSK_GPIO1 (1 << 24) | 215 | #define PCI_MSK_IR (1 << 28) |
216 | #define PCI_MSK_GPIO0 (1 << 23) | 216 | #define PCI_MSK_GPIO1 (1 << 24) |
217 | #define PCI_MSK_GPIO0 (1 << 23) | ||
217 | #define PCI_MSK_APB_DMA (1 << 12) | 218 | #define PCI_MSK_APB_DMA (1 << 12) |
218 | #define PCI_MSK_AL_WR (1 << 11) | 219 | #define PCI_MSK_AL_WR (1 << 11) |
219 | #define PCI_MSK_AL_RD (1 << 10) | 220 | #define PCI_MSK_AL_RD (1 << 10) |
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 654cc253cd50..8b372b4f0de2 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include "cx23885.h" | 35 | #include "cx23885.h" |
36 | #include <media/v4l2-common.h> | 36 | #include <media/v4l2-common.h> |
37 | #include <media/v4l2-ioctl.h> | 37 | #include <media/v4l2-ioctl.h> |
38 | #include "cx23885-ioctl.h" | ||
38 | 39 | ||
39 | MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards"); | 40 | MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards"); |
40 | MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); | 41 | MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); |
@@ -401,6 +402,13 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) | |||
401 | INPUT(input)->gpio2, INPUT(input)->gpio3); | 402 | INPUT(input)->gpio2, INPUT(input)->gpio3); |
402 | dev->input = input; | 403 | dev->input = input; |
403 | 404 | ||
405 | if (dev->board == CX23885_BOARD_MYGICA_X8506 || | ||
406 | dev->board == CX23885_BOARD_MAGICPRO_PROHDTVE2) { | ||
407 | /* Select Analog TV */ | ||
408 | if (INPUT(input)->type == CX23885_VMUX_TELEVISION) | ||
409 | cx23885_gpio_clear(dev, GPIO_0); | ||
410 | } | ||
411 | |||
404 | /* Tell the internal A/V decoder */ | 412 | /* Tell the internal A/V decoder */ |
405 | v4l2_subdev_call(dev->sd_cx25840, video, s_routing, | 413 | v4l2_subdev_call(dev->sd_cx25840, video, s_routing, |
406 | INPUT(input)->vmux, 0, 0); | 414 | INPUT(input)->vmux, 0, 0); |
@@ -1144,6 +1152,7 @@ static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) | |||
1144 | [CX23885_VMUX_COMPOSITE3] = "Composite3", | 1152 | [CX23885_VMUX_COMPOSITE3] = "Composite3", |
1145 | [CX23885_VMUX_COMPOSITE4] = "Composite4", | 1153 | [CX23885_VMUX_COMPOSITE4] = "Composite4", |
1146 | [CX23885_VMUX_SVIDEO] = "S-Video", | 1154 | [CX23885_VMUX_SVIDEO] = "S-Video", |
1155 | [CX23885_VMUX_COMPONENT] = "Component", | ||
1147 | [CX23885_VMUX_TELEVISION] = "Television", | 1156 | [CX23885_VMUX_TELEVISION] = "Television", |
1148 | [CX23885_VMUX_CABLE] = "Cable TV", | 1157 | [CX23885_VMUX_CABLE] = "Cable TV", |
1149 | [CX23885_VMUX_DVB] = "DVB", | 1158 | [CX23885_VMUX_DVB] = "DVB", |
@@ -1312,34 +1321,6 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
1312 | cx23885_set_freq(dev, f); | 1321 | cx23885_set_freq(dev, f); |
1313 | } | 1322 | } |
1314 | 1323 | ||
1315 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1316 | static int vidioc_g_register(struct file *file, void *fh, | ||
1317 | struct v4l2_dbg_register *reg) | ||
1318 | { | ||
1319 | struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; | ||
1320 | |||
1321 | if (!v4l2_chip_match_host(®->match)) | ||
1322 | return -EINVAL; | ||
1323 | |||
1324 | call_all(dev, core, g_register, reg); | ||
1325 | |||
1326 | return 0; | ||
1327 | } | ||
1328 | |||
1329 | static int vidioc_s_register(struct file *file, void *fh, | ||
1330 | struct v4l2_dbg_register *reg) | ||
1331 | { | ||
1332 | struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; | ||
1333 | |||
1334 | if (!v4l2_chip_match_host(®->match)) | ||
1335 | return -EINVAL; | ||
1336 | |||
1337 | call_all(dev, core, s_register, reg); | ||
1338 | |||
1339 | return 0; | ||
1340 | } | ||
1341 | #endif | ||
1342 | |||
1343 | /* ----------------------------------------------------------- */ | 1324 | /* ----------------------------------------------------------- */ |
1344 | 1325 | ||
1345 | static void cx23885_vid_timeout(unsigned long data) | 1326 | static void cx23885_vid_timeout(unsigned long data) |
@@ -1449,9 +1430,10 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { | |||
1449 | .vidioc_s_tuner = vidioc_s_tuner, | 1430 | .vidioc_s_tuner = vidioc_s_tuner, |
1450 | .vidioc_g_frequency = vidioc_g_frequency, | 1431 | .vidioc_g_frequency = vidioc_g_frequency, |
1451 | .vidioc_s_frequency = vidioc_s_frequency, | 1432 | .vidioc_s_frequency = vidioc_s_frequency, |
1433 | .vidioc_g_chip_ident = cx23885_g_chip_ident, | ||
1452 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 1434 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
1453 | .vidioc_g_register = vidioc_g_register, | 1435 | .vidioc_g_register = cx23885_g_register, |
1454 | .vidioc_s_register = vidioc_s_register, | 1436 | .vidioc_s_register = cx23885_s_register, |
1455 | #endif | 1437 | #endif |
1456 | }; | 1438 | }; |
1457 | 1439 | ||
@@ -1529,9 +1511,11 @@ int cx23885_video_register(struct cx23885_dev *dev) | |||
1529 | if (sd) { | 1511 | if (sd) { |
1530 | struct tuner_setup tun_setup; | 1512 | struct tuner_setup tun_setup; |
1531 | 1513 | ||
1514 | memset(&tun_setup, 0, sizeof(tun_setup)); | ||
1532 | tun_setup.mode_mask = T_ANALOG_TV; | 1515 | tun_setup.mode_mask = T_ANALOG_TV; |
1533 | tun_setup.type = dev->tuner_type; | 1516 | tun_setup.type = dev->tuner_type; |
1534 | tun_setup.addr = v4l2_i2c_subdev_addr(sd); | 1517 | tun_setup.addr = v4l2_i2c_subdev_addr(sd); |
1518 | tun_setup.tuner_callback = cx23885_tuner_callback; | ||
1535 | 1519 | ||
1536 | v4l2_subdev_call(sd, tuner, s_type_addr, &tun_setup); | 1520 | v4l2_subdev_call(sd, tuner, s_type_addr, &tun_setup); |
1537 | } | 1521 | } |
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index cc7a165561ff..fa744764dc8b 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h | |||
@@ -79,6 +79,8 @@ | |||
79 | #define CX23885_BOARD_MAGICPRO_PROHDTVE2 23 | 79 | #define CX23885_BOARD_MAGICPRO_PROHDTVE2 23 |
80 | #define CX23885_BOARD_HAUPPAUGE_HVR1850 24 | 80 | #define CX23885_BOARD_HAUPPAUGE_HVR1850 24 |
81 | #define CX23885_BOARD_COMPRO_VIDEOMATE_E800 25 | 81 | #define CX23885_BOARD_COMPRO_VIDEOMATE_E800 25 |
82 | #define CX23885_BOARD_HAUPPAUGE_HVR1290 26 | ||
83 | #define CX23885_BOARD_MYGICA_X8558PRO 27 | ||
82 | 84 | ||
83 | #define GPIO_0 0x00000001 | 85 | #define GPIO_0 0x00000001 |
84 | #define GPIO_1 0x00000002 | 86 | #define GPIO_1 0x00000002 |
@@ -157,6 +159,7 @@ enum cx23885_itype { | |||
157 | CX23885_VMUX_COMPOSITE3, | 159 | CX23885_VMUX_COMPOSITE3, |
158 | CX23885_VMUX_COMPOSITE4, | 160 | CX23885_VMUX_COMPOSITE4, |
159 | CX23885_VMUX_SVIDEO, | 161 | CX23885_VMUX_SVIDEO, |
162 | CX23885_VMUX_COMPONENT, | ||
160 | CX23885_VMUX_TELEVISION, | 163 | CX23885_VMUX_TELEVISION, |
161 | CX23885_VMUX_CABLE, | 164 | CX23885_VMUX_CABLE, |
162 | CX23885_VMUX_DVB, | 165 | CX23885_VMUX_DVB, |
@@ -297,10 +300,6 @@ struct cx23885_tsport { | |||
297 | /* Allow a single tsport to have multiple frontends */ | 300 | /* Allow a single tsport to have multiple frontends */ |
298 | u32 num_frontends; | 301 | u32 num_frontends; |
299 | void *port_priv; | 302 | void *port_priv; |
300 | |||
301 | /* FIXME: temporary hack */ | ||
302 | int (*set_frontend_save) (struct dvb_frontend *, | ||
303 | struct dvb_frontend_parameters *); | ||
304 | }; | 303 | }; |
305 | 304 | ||
306 | struct cx23885_dev { | 305 | struct cx23885_dev { |
@@ -356,6 +355,16 @@ struct cx23885_dev { | |||
356 | unsigned int has_radio; | 355 | unsigned int has_radio; |
357 | struct v4l2_subdev *sd_cx25840; | 356 | struct v4l2_subdev *sd_cx25840; |
358 | 357 | ||
358 | /* Infrared */ | ||
359 | struct v4l2_subdev *sd_ir; | ||
360 | struct work_struct ir_rx_work; | ||
361 | unsigned long ir_rx_notifications; | ||
362 | struct work_struct ir_tx_work; | ||
363 | unsigned long ir_tx_notifications; | ||
364 | |||
365 | struct card_ir *ir_input; | ||
366 | atomic_t ir_input_stopping; | ||
367 | |||
359 | /* V4l */ | 368 | /* V4l */ |
360 | u32 freq; | 369 | u32 freq; |
361 | struct video_device *video_dev; | 370 | struct video_device *video_dev; |
@@ -383,6 +392,13 @@ static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev) | |||
383 | #define call_all(dev, o, f, args...) \ | 392 | #define call_all(dev, o, f, args...) \ |
384 | v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args) | 393 | v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args) |
385 | 394 | ||
395 | #define CX23885_HW_888_IR (1 << 0) | ||
396 | |||
397 | #define call_hw(dev, grpid, o, f, args...) \ | ||
398 | v4l2_device_call_all(&dev->v4l2_dev, grpid, o, f, ##args) | ||
399 | |||
400 | extern struct v4l2_subdev *cx23885_find_hw(struct cx23885_dev *dev, u32 hw); | ||
401 | |||
386 | extern struct list_head cx23885_devlist; | 402 | extern struct list_head cx23885_devlist; |
387 | 403 | ||
388 | #define SRAM_CH01 0 /* Video A */ | 404 | #define SRAM_CH01 0 /* Video A */ |
@@ -455,6 +471,7 @@ extern void cx23885_wakeup(struct cx23885_tsport *port, | |||
455 | 471 | ||
456 | extern void cx23885_gpio_set(struct cx23885_dev *dev, u32 mask); | 472 | extern void cx23885_gpio_set(struct cx23885_dev *dev, u32 mask); |
457 | extern void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask); | 473 | extern void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask); |
474 | extern u32 cx23885_gpio_get(struct cx23885_dev *dev, u32 mask); | ||
458 | extern void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, | 475 | extern void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, |
459 | int asoutput); | 476 | int asoutput); |
460 | 477 | ||
@@ -471,6 +488,8 @@ extern int cx23885_tuner_callback(void *priv, int component, | |||
471 | int command, int arg); | 488 | int command, int arg); |
472 | extern void cx23885_card_list(struct cx23885_dev *dev); | 489 | extern void cx23885_card_list(struct cx23885_dev *dev); |
473 | extern int cx23885_ir_init(struct cx23885_dev *dev); | 490 | extern int cx23885_ir_init(struct cx23885_dev *dev); |
491 | extern void cx23885_ir_pci_int_enable(struct cx23885_dev *dev); | ||
492 | extern void cx23885_ir_fini(struct cx23885_dev *dev); | ||
474 | extern void cx23885_gpio_setup(struct cx23885_dev *dev); | 493 | extern void cx23885_gpio_setup(struct cx23885_dev *dev); |
475 | extern void cx23885_card_setup(struct cx23885_dev *dev); | 494 | extern void cx23885_card_setup(struct cx23885_dev *dev); |
476 | extern void cx23885_card_setup_pre_i2c(struct cx23885_dev *dev); | 495 | extern void cx23885_card_setup_pre_i2c(struct cx23885_dev *dev); |
@@ -515,6 +534,10 @@ extern void cx23885_417_check_encoder(struct cx23885_dev *dev); | |||
515 | extern void cx23885_mc417_init(struct cx23885_dev *dev); | 534 | extern void cx23885_mc417_init(struct cx23885_dev *dev); |
516 | extern int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value); | 535 | extern int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value); |
517 | extern int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value); | 536 | extern int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value); |
537 | extern int mc417_register_read(struct cx23885_dev *dev, | ||
538 | u16 address, u32 *value); | ||
539 | extern int mc417_register_write(struct cx23885_dev *dev, | ||
540 | u16 address, u32 value); | ||
518 | extern void mc417_gpio_set(struct cx23885_dev *dev, u32 mask); | 541 | extern void mc417_gpio_set(struct cx23885_dev *dev, u32 mask); |
519 | extern void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask); | 542 | extern void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask); |
520 | extern void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput); | 543 | extern void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput); |
diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c new file mode 100644 index 000000000000..3ccc8afeccf3 --- /dev/null +++ b/drivers/media/video/cx23885/cx23888-ir.c | |||
@@ -0,0 +1,1239 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX23885/7/8 PCIe bridge | ||
3 | * | ||
4 | * CX23888 Integrated Consumer Infrared Controller | ||
5 | * | ||
6 | * Copyright (C) 2009 Andy Walls <awalls@radix.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version 2 | ||
11 | * of the License, or (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/kfifo.h> | ||
25 | |||
26 | #include <media/v4l2-device.h> | ||
27 | #include <media/v4l2-chip-ident.h> | ||
28 | |||
29 | #include "cx23885.h" | ||
30 | |||
31 | static unsigned int ir_888_debug; | ||
32 | module_param(ir_888_debug, int, 0644); | ||
33 | MODULE_PARM_DESC(ir_888_debug, "enable debug messages [CX23888 IR controller]"); | ||
34 | |||
35 | #define CX23888_IR_REG_BASE 0x170000 | ||
36 | /* | ||
37 | * These CX23888 register offsets have a straightforward one to one mapping | ||
38 | * to the CX23885 register offsets of 0x200 through 0x218 | ||
39 | */ | ||
40 | #define CX23888_IR_CNTRL_REG 0x170000 | ||
41 | #define CNTRL_WIN_3_3 0x00000000 | ||
42 | #define CNTRL_WIN_4_3 0x00000001 | ||
43 | #define CNTRL_WIN_3_4 0x00000002 | ||
44 | #define CNTRL_WIN_4_4 0x00000003 | ||
45 | #define CNTRL_WIN 0x00000003 | ||
46 | #define CNTRL_EDG_NONE 0x00000000 | ||
47 | #define CNTRL_EDG_FALL 0x00000004 | ||
48 | #define CNTRL_EDG_RISE 0x00000008 | ||
49 | #define CNTRL_EDG_BOTH 0x0000000C | ||
50 | #define CNTRL_EDG 0x0000000C | ||
51 | #define CNTRL_DMD 0x00000010 | ||
52 | #define CNTRL_MOD 0x00000020 | ||
53 | #define CNTRL_RFE 0x00000040 | ||
54 | #define CNTRL_TFE 0x00000080 | ||
55 | #define CNTRL_RXE 0x00000100 | ||
56 | #define CNTRL_TXE 0x00000200 | ||
57 | #define CNTRL_RIC 0x00000400 | ||
58 | #define CNTRL_TIC 0x00000800 | ||
59 | #define CNTRL_CPL 0x00001000 | ||
60 | #define CNTRL_LBM 0x00002000 | ||
61 | #define CNTRL_R 0x00004000 | ||
62 | |||
63 | #define CX23888_IR_TXCLK_REG 0x170004 | ||
64 | #define TXCLK_TCD 0x0000FFFF | ||
65 | |||
66 | #define CX23888_IR_RXCLK_REG 0x170008 | ||
67 | #define RXCLK_RCD 0x0000FFFF | ||
68 | |||
69 | #define CX23888_IR_CDUTY_REG 0x17000C | ||
70 | #define CDUTY_CDC 0x0000000F | ||
71 | |||
72 | #define CX23888_IR_STATS_REG 0x170010 | ||
73 | #define STATS_RTO 0x00000001 | ||
74 | #define STATS_ROR 0x00000002 | ||
75 | #define STATS_RBY 0x00000004 | ||
76 | #define STATS_TBY 0x00000008 | ||
77 | #define STATS_RSR 0x00000010 | ||
78 | #define STATS_TSR 0x00000020 | ||
79 | |||
80 | #define CX23888_IR_IRQEN_REG 0x170014 | ||
81 | #define IRQEN_RTE 0x00000001 | ||
82 | #define IRQEN_ROE 0x00000002 | ||
83 | #define IRQEN_RSE 0x00000010 | ||
84 | #define IRQEN_TSE 0x00000020 | ||
85 | |||
86 | #define CX23888_IR_FILTR_REG 0x170018 | ||
87 | #define FILTR_LPF 0x0000FFFF | ||
88 | |||
89 | /* This register doesn't follow the pattern; it's 0x23C on a CX23885 */ | ||
90 | #define CX23888_IR_FIFO_REG 0x170040 | ||
91 | #define FIFO_RXTX 0x0000FFFF | ||
92 | #define FIFO_RXTX_LVL 0x00010000 | ||
93 | #define FIFO_RXTX_RTO 0x0001FFFF | ||
94 | #define FIFO_RX_NDV 0x00020000 | ||
95 | #define FIFO_RX_DEPTH 8 | ||
96 | #define FIFO_TX_DEPTH 8 | ||
97 | |||
98 | /* CX23888 unique registers */ | ||
99 | #define CX23888_IR_SEEDP_REG 0x17001C | ||
100 | #define CX23888_IR_TIMOL_REG 0x170020 | ||
101 | #define CX23888_IR_WAKE0_REG 0x170024 | ||
102 | #define CX23888_IR_WAKE1_REG 0x170028 | ||
103 | #define CX23888_IR_WAKE2_REG 0x17002C | ||
104 | #define CX23888_IR_MASK0_REG 0x170030 | ||
105 | #define CX23888_IR_MASK1_REG 0x170034 | ||
106 | #define CX23888_IR_MAKS2_REG 0x170038 | ||
107 | #define CX23888_IR_DPIPG_REG 0x17003C | ||
108 | #define CX23888_IR_LEARN_REG 0x170044 | ||
109 | |||
110 | #define CX23888_VIDCLK_FREQ 108000000 /* 108 MHz, BT.656 */ | ||
111 | #define CX23888_IR_REFCLK_FREQ (CX23888_VIDCLK_FREQ / 2) | ||
112 | |||
113 | #define CX23888_IR_RX_KFIFO_SIZE (512 * sizeof(u32)) | ||
114 | #define CX23888_IR_TX_KFIFO_SIZE (512 * sizeof(u32)) | ||
115 | |||
116 | struct cx23888_ir_state { | ||
117 | struct v4l2_subdev sd; | ||
118 | struct cx23885_dev *dev; | ||
119 | u32 id; | ||
120 | u32 rev; | ||
121 | |||
122 | struct v4l2_subdev_ir_parameters rx_params; | ||
123 | struct mutex rx_params_lock; | ||
124 | atomic_t rxclk_divider; | ||
125 | atomic_t rx_invert; | ||
126 | |||
127 | struct kfifo *rx_kfifo; | ||
128 | spinlock_t rx_kfifo_lock; | ||
129 | |||
130 | struct v4l2_subdev_ir_parameters tx_params; | ||
131 | struct mutex tx_params_lock; | ||
132 | atomic_t txclk_divider; | ||
133 | |||
134 | struct kfifo *tx_kfifo; | ||
135 | spinlock_t tx_kfifo_lock; | ||
136 | }; | ||
137 | |||
138 | static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd) | ||
139 | { | ||
140 | return v4l2_get_subdevdata(sd); | ||
141 | } | ||
142 | |||
143 | /* | ||
144 | * IR register block read and write functions | ||
145 | */ | ||
146 | static | ||
147 | inline int cx23888_ir_write4(struct cx23885_dev *dev, u32 addr, u32 value) | ||
148 | { | ||
149 | cx_write(addr, value); | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static inline u32 cx23888_ir_read4(struct cx23885_dev *dev, u32 addr) | ||
154 | { | ||
155 | return cx_read(addr); | ||
156 | } | ||
157 | |||
158 | static inline int cx23888_ir_and_or4(struct cx23885_dev *dev, u32 addr, | ||
159 | u32 and_mask, u32 or_value) | ||
160 | { | ||
161 | cx_andor(addr, ~and_mask, or_value); | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * Rx and Tx Clock Divider register computations | ||
167 | * | ||
168 | * Note the largest clock divider value of 0xffff corresponds to: | ||
169 | * (0xffff + 1) * 1000 / 108/2 MHz = 1,213,629.629... ns | ||
170 | * which fits in 21 bits, so we'll use unsigned int for time arguments. | ||
171 | */ | ||
172 | static inline u16 count_to_clock_divider(unsigned int d) | ||
173 | { | ||
174 | if (d > RXCLK_RCD + 1) | ||
175 | d = RXCLK_RCD; | ||
176 | else if (d < 2) | ||
177 | d = 1; | ||
178 | else | ||
179 | d--; | ||
180 | return (u16) d; | ||
181 | } | ||
182 | |||
183 | static inline u16 ns_to_clock_divider(unsigned int ns) | ||
184 | { | ||
185 | return count_to_clock_divider( | ||
186 | DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ / 1000000 * ns, 1000)); | ||
187 | } | ||
188 | |||
189 | static inline unsigned int clock_divider_to_ns(unsigned int divider) | ||
190 | { | ||
191 | /* Period of the Rx or Tx clock in ns */ | ||
192 | return DIV_ROUND_CLOSEST((divider + 1) * 1000, | ||
193 | CX23888_IR_REFCLK_FREQ / 1000000); | ||
194 | } | ||
195 | |||
196 | static inline u16 carrier_freq_to_clock_divider(unsigned int freq) | ||
197 | { | ||
198 | return count_to_clock_divider( | ||
199 | DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, freq * 16)); | ||
200 | } | ||
201 | |||
202 | static inline unsigned int clock_divider_to_carrier_freq(unsigned int divider) | ||
203 | { | ||
204 | return DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, (divider + 1) * 16); | ||
205 | } | ||
206 | |||
207 | static inline u16 freq_to_clock_divider(unsigned int freq, | ||
208 | unsigned int rollovers) | ||
209 | { | ||
210 | return count_to_clock_divider( | ||
211 | DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, freq * rollovers)); | ||
212 | } | ||
213 | |||
214 | static inline unsigned int clock_divider_to_freq(unsigned int divider, | ||
215 | unsigned int rollovers) | ||
216 | { | ||
217 | return DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, | ||
218 | (divider + 1) * rollovers); | ||
219 | } | ||
220 | |||
221 | /* | ||
222 | * Low Pass Filter register calculations | ||
223 | * | ||
224 | * Note the largest count value of 0xffff corresponds to: | ||
225 | * 0xffff * 1000 / 108/2 MHz = 1,213,611.11... ns | ||
226 | * which fits in 21 bits, so we'll use unsigned int for time arguments. | ||
227 | */ | ||
228 | static inline u16 count_to_lpf_count(unsigned int d) | ||
229 | { | ||
230 | if (d > FILTR_LPF) | ||
231 | d = FILTR_LPF; | ||
232 | else if (d < 4) | ||
233 | d = 0; | ||
234 | return (u16) d; | ||
235 | } | ||
236 | |||
237 | static inline u16 ns_to_lpf_count(unsigned int ns) | ||
238 | { | ||
239 | return count_to_lpf_count( | ||
240 | DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ / 1000000 * ns, 1000)); | ||
241 | } | ||
242 | |||
243 | static inline unsigned int lpf_count_to_ns(unsigned int count) | ||
244 | { | ||
245 | /* Duration of the Low Pass Filter rejection window in ns */ | ||
246 | return DIV_ROUND_CLOSEST(count * 1000, | ||
247 | CX23888_IR_REFCLK_FREQ / 1000000); | ||
248 | } | ||
249 | |||
250 | static inline unsigned int lpf_count_to_us(unsigned int count) | ||
251 | { | ||
252 | /* Duration of the Low Pass Filter rejection window in us */ | ||
253 | return DIV_ROUND_CLOSEST(count, CX23888_IR_REFCLK_FREQ / 1000000); | ||
254 | } | ||
255 | |||
256 | /* | ||
257 | * FIFO register pulse width count compuations | ||
258 | */ | ||
259 | static u32 clock_divider_to_resolution(u16 divider) | ||
260 | { | ||
261 | /* | ||
262 | * Resolution is the duration of 1 tick of the readable portion of | ||
263 | * of the pulse width counter as read from the FIFO. The two lsb's are | ||
264 | * not readable, hence the << 2. This function returns ns. | ||
265 | */ | ||
266 | return DIV_ROUND_CLOSEST((1 << 2) * ((u32) divider + 1) * 1000, | ||
267 | CX23888_IR_REFCLK_FREQ / 1000000); | ||
268 | } | ||
269 | |||
270 | static u64 pulse_width_count_to_ns(u16 count, u16 divider) | ||
271 | { | ||
272 | u64 n; | ||
273 | u32 rem; | ||
274 | |||
275 | /* | ||
276 | * The 2 lsb's of the pulse width timer count are not readable, hence | ||
277 | * the (count << 2) | 0x3 | ||
278 | */ | ||
279 | n = (((u64) count << 2) | 0x3) * (divider + 1) * 1000; /* millicycles */ | ||
280 | rem = do_div(n, CX23888_IR_REFCLK_FREQ / 1000000); /* / MHz => ns */ | ||
281 | if (rem >= CX23888_IR_REFCLK_FREQ / 1000000 / 2) | ||
282 | n++; | ||
283 | return n; | ||
284 | } | ||
285 | |||
286 | static unsigned int pulse_width_count_to_us(u16 count, u16 divider) | ||
287 | { | ||
288 | u64 n; | ||
289 | u32 rem; | ||
290 | |||
291 | /* | ||
292 | * The 2 lsb's of the pulse width timer count are not readable, hence | ||
293 | * the (count << 2) | 0x3 | ||
294 | */ | ||
295 | n = (((u64) count << 2) | 0x3) * (divider + 1); /* cycles */ | ||
296 | rem = do_div(n, CX23888_IR_REFCLK_FREQ / 1000000); /* / MHz => us */ | ||
297 | if (rem >= CX23888_IR_REFCLK_FREQ / 1000000 / 2) | ||
298 | n++; | ||
299 | return (unsigned int) n; | ||
300 | } | ||
301 | |||
302 | /* | ||
303 | * Pulse Clocks computations: Combined Pulse Width Count & Rx Clock Counts | ||
304 | * | ||
305 | * The total pulse clock count is an 18 bit pulse width timer count as the most | ||
306 | * significant part and (up to) 16 bit clock divider count as a modulus. | ||
307 | * When the Rx clock divider ticks down to 0, it increments the 18 bit pulse | ||
308 | * width timer count's least significant bit. | ||
309 | */ | ||
310 | static u64 ns_to_pulse_clocks(u32 ns) | ||
311 | { | ||
312 | u64 clocks; | ||
313 | u32 rem; | ||
314 | clocks = CX23888_IR_REFCLK_FREQ / 1000000 * (u64) ns; /* millicycles */ | ||
315 | rem = do_div(clocks, 1000); /* /1000 = cycles */ | ||
316 | if (rem >= 1000 / 2) | ||
317 | clocks++; | ||
318 | return clocks; | ||
319 | } | ||
320 | |||
321 | static u16 pulse_clocks_to_clock_divider(u64 count) | ||
322 | { | ||
323 | u32 rem; | ||
324 | |||
325 | rem = do_div(count, (FIFO_RXTX << 2) | 0x3); | ||
326 | |||
327 | /* net result needs to be rounded down and decremented by 1 */ | ||
328 | if (count > RXCLK_RCD + 1) | ||
329 | count = RXCLK_RCD; | ||
330 | else if (count < 2) | ||
331 | count = 1; | ||
332 | else | ||
333 | count--; | ||
334 | return (u16) count; | ||
335 | } | ||
336 | |||
337 | /* | ||
338 | * IR Control Register helpers | ||
339 | */ | ||
340 | enum tx_fifo_watermark { | ||
341 | TX_FIFO_HALF_EMPTY = 0, | ||
342 | TX_FIFO_EMPTY = CNTRL_TIC, | ||
343 | }; | ||
344 | |||
345 | enum rx_fifo_watermark { | ||
346 | RX_FIFO_HALF_FULL = 0, | ||
347 | RX_FIFO_NOT_EMPTY = CNTRL_RIC, | ||
348 | }; | ||
349 | |||
350 | static inline void control_tx_irq_watermark(struct cx23885_dev *dev, | ||
351 | enum tx_fifo_watermark level) | ||
352 | { | ||
353 | cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_TIC, level); | ||
354 | } | ||
355 | |||
356 | static inline void control_rx_irq_watermark(struct cx23885_dev *dev, | ||
357 | enum rx_fifo_watermark level) | ||
358 | { | ||
359 | cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_RIC, level); | ||
360 | } | ||
361 | |||
362 | static inline void control_tx_enable(struct cx23885_dev *dev, bool enable) | ||
363 | { | ||
364 | cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~(CNTRL_TXE | CNTRL_TFE), | ||
365 | enable ? (CNTRL_TXE | CNTRL_TFE) : 0); | ||
366 | } | ||
367 | |||
368 | static inline void control_rx_enable(struct cx23885_dev *dev, bool enable) | ||
369 | { | ||
370 | cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~(CNTRL_RXE | CNTRL_RFE), | ||
371 | enable ? (CNTRL_RXE | CNTRL_RFE) : 0); | ||
372 | } | ||
373 | |||
374 | static inline void control_tx_modulation_enable(struct cx23885_dev *dev, | ||
375 | bool enable) | ||
376 | { | ||
377 | cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_MOD, | ||
378 | enable ? CNTRL_MOD : 0); | ||
379 | } | ||
380 | |||
381 | static inline void control_rx_demodulation_enable(struct cx23885_dev *dev, | ||
382 | bool enable) | ||
383 | { | ||
384 | cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_DMD, | ||
385 | enable ? CNTRL_DMD : 0); | ||
386 | } | ||
387 | |||
388 | static inline void control_rx_s_edge_detection(struct cx23885_dev *dev, | ||
389 | u32 edge_types) | ||
390 | { | ||
391 | cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_EDG_BOTH, | ||
392 | edge_types & CNTRL_EDG_BOTH); | ||
393 | } | ||
394 | |||
395 | static void control_rx_s_carrier_window(struct cx23885_dev *dev, | ||
396 | unsigned int carrier, | ||
397 | unsigned int *carrier_range_low, | ||
398 | unsigned int *carrier_range_high) | ||
399 | { | ||
400 | u32 v; | ||
401 | unsigned int c16 = carrier * 16; | ||
402 | |||
403 | if (*carrier_range_low < DIV_ROUND_CLOSEST(c16, 16 + 3)) { | ||
404 | v = CNTRL_WIN_3_4; | ||
405 | *carrier_range_low = DIV_ROUND_CLOSEST(c16, 16 + 4); | ||
406 | } else { | ||
407 | v = CNTRL_WIN_3_3; | ||
408 | *carrier_range_low = DIV_ROUND_CLOSEST(c16, 16 + 3); | ||
409 | } | ||
410 | |||
411 | if (*carrier_range_high > DIV_ROUND_CLOSEST(c16, 16 - 3)) { | ||
412 | v |= CNTRL_WIN_4_3; | ||
413 | *carrier_range_high = DIV_ROUND_CLOSEST(c16, 16 - 4); | ||
414 | } else { | ||
415 | v |= CNTRL_WIN_3_3; | ||
416 | *carrier_range_high = DIV_ROUND_CLOSEST(c16, 16 - 3); | ||
417 | } | ||
418 | cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_WIN, v); | ||
419 | } | ||
420 | |||
421 | static inline void control_tx_polarity_invert(struct cx23885_dev *dev, | ||
422 | bool invert) | ||
423 | { | ||
424 | cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_CPL, | ||
425 | invert ? CNTRL_CPL : 0); | ||
426 | } | ||
427 | |||
428 | /* | ||
429 | * IR Rx & Tx Clock Register helpers | ||
430 | */ | ||
431 | static unsigned int txclk_tx_s_carrier(struct cx23885_dev *dev, | ||
432 | unsigned int freq, | ||
433 | u16 *divider) | ||
434 | { | ||
435 | *divider = carrier_freq_to_clock_divider(freq); | ||
436 | cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider); | ||
437 | return clock_divider_to_carrier_freq(*divider); | ||
438 | } | ||
439 | |||
440 | static unsigned int rxclk_rx_s_carrier(struct cx23885_dev *dev, | ||
441 | unsigned int freq, | ||
442 | u16 *divider) | ||
443 | { | ||
444 | *divider = carrier_freq_to_clock_divider(freq); | ||
445 | cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider); | ||
446 | return clock_divider_to_carrier_freq(*divider); | ||
447 | } | ||
448 | |||
449 | static u32 txclk_tx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns, | ||
450 | u16 *divider) | ||
451 | { | ||
452 | u64 pulse_clocks; | ||
453 | |||
454 | if (ns > V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS) | ||
455 | ns = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS; | ||
456 | pulse_clocks = ns_to_pulse_clocks(ns); | ||
457 | *divider = pulse_clocks_to_clock_divider(pulse_clocks); | ||
458 | cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider); | ||
459 | return (u32) pulse_width_count_to_ns(FIFO_RXTX, *divider); | ||
460 | } | ||
461 | |||
462 | static u32 rxclk_rx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns, | ||
463 | u16 *divider) | ||
464 | { | ||
465 | u64 pulse_clocks; | ||
466 | |||
467 | if (ns > V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS) | ||
468 | ns = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS; | ||
469 | pulse_clocks = ns_to_pulse_clocks(ns); | ||
470 | *divider = pulse_clocks_to_clock_divider(pulse_clocks); | ||
471 | cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider); | ||
472 | return (u32) pulse_width_count_to_ns(FIFO_RXTX, *divider); | ||
473 | } | ||
474 | |||
475 | /* | ||
476 | * IR Tx Carrier Duty Cycle register helpers | ||
477 | */ | ||
478 | static unsigned int cduty_tx_s_duty_cycle(struct cx23885_dev *dev, | ||
479 | unsigned int duty_cycle) | ||
480 | { | ||
481 | u32 n; | ||
482 | n = DIV_ROUND_CLOSEST(duty_cycle * 100, 625); /* 16ths of 100% */ | ||
483 | if (n != 0) | ||
484 | n--; | ||
485 | if (n > 15) | ||
486 | n = 15; | ||
487 | cx23888_ir_write4(dev, CX23888_IR_CDUTY_REG, n); | ||
488 | return DIV_ROUND_CLOSEST((n + 1) * 100, 16); | ||
489 | } | ||
490 | |||
491 | /* | ||
492 | * IR Filter Register helpers | ||
493 | */ | ||
494 | static u32 filter_rx_s_min_width(struct cx23885_dev *dev, u32 min_width_ns) | ||
495 | { | ||
496 | u32 count = ns_to_lpf_count(min_width_ns); | ||
497 | cx23888_ir_write4(dev, CX23888_IR_FILTR_REG, count); | ||
498 | return lpf_count_to_ns(count); | ||
499 | } | ||
500 | |||
501 | /* | ||
502 | * IR IRQ Enable Register helpers | ||
503 | */ | ||
504 | static inline void irqenable_rx(struct cx23885_dev *dev, u32 mask) | ||
505 | { | ||
506 | mask &= (IRQEN_RTE | IRQEN_ROE | IRQEN_RSE); | ||
507 | cx23888_ir_and_or4(dev, CX23888_IR_IRQEN_REG, | ||
508 | ~(IRQEN_RTE | IRQEN_ROE | IRQEN_RSE), mask); | ||
509 | } | ||
510 | |||
511 | static inline void irqenable_tx(struct cx23885_dev *dev, u32 mask) | ||
512 | { | ||
513 | mask &= IRQEN_TSE; | ||
514 | cx23888_ir_and_or4(dev, CX23888_IR_IRQEN_REG, ~IRQEN_TSE, mask); | ||
515 | } | ||
516 | |||
517 | /* | ||
518 | * V4L2 Subdevice IR Ops | ||
519 | */ | ||
520 | static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status, | ||
521 | bool *handled) | ||
522 | { | ||
523 | struct cx23888_ir_state *state = to_state(sd); | ||
524 | struct cx23885_dev *dev = state->dev; | ||
525 | |||
526 | u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG); | ||
527 | u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG); | ||
528 | u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG); | ||
529 | |||
530 | u32 rx_data[FIFO_RX_DEPTH]; | ||
531 | int i, j, k; | ||
532 | u32 events, v; | ||
533 | int tsr, rsr, rto, ror, tse, rse, rte, roe, kror; | ||
534 | |||
535 | tsr = stats & STATS_TSR; /* Tx FIFO Service Request */ | ||
536 | rsr = stats & STATS_RSR; /* Rx FIFO Service Request */ | ||
537 | rto = stats & STATS_RTO; /* Rx Pulse Width Timer Time Out */ | ||
538 | ror = stats & STATS_ROR; /* Rx FIFO Over Run */ | ||
539 | |||
540 | tse = irqen & IRQEN_TSE; /* Tx FIFO Service Request IRQ Enable */ | ||
541 | rse = irqen & IRQEN_RSE; /* Rx FIFO Service Reuqest IRQ Enable */ | ||
542 | rte = irqen & IRQEN_RTE; /* Rx Pulse Width Timer Time Out IRQ Enable */ | ||
543 | roe = irqen & IRQEN_ROE; /* Rx FIFO Over Run IRQ Enable */ | ||
544 | |||
545 | *handled = false; | ||
546 | v4l2_dbg(2, ir_888_debug, sd, "IRQ Status: %s %s %s %s %s %s\n", | ||
547 | tsr ? "tsr" : " ", rsr ? "rsr" : " ", | ||
548 | rto ? "rto" : " ", ror ? "ror" : " ", | ||
549 | stats & STATS_TBY ? "tby" : " ", | ||
550 | stats & STATS_RBY ? "rby" : " "); | ||
551 | |||
552 | v4l2_dbg(2, ir_888_debug, sd, "IRQ Enables: %s %s %s %s\n", | ||
553 | tse ? "tse" : " ", rse ? "rse" : " ", | ||
554 | rte ? "rte" : " ", roe ? "roe" : " "); | ||
555 | |||
556 | /* | ||
557 | * Transmitter interrupt service | ||
558 | */ | ||
559 | if (tse && tsr) { | ||
560 | /* | ||
561 | * TODO: | ||
562 | * Check the watermark threshold setting | ||
563 | * Pull FIFO_TX_DEPTH or FIFO_TX_DEPTH/2 entries from tx_kfifo | ||
564 | * Push the data to the hardware FIFO. | ||
565 | * If there was nothing more to send in the tx_kfifo, disable | ||
566 | * the TSR IRQ and notify the v4l2_device. | ||
567 | * If there was something in the tx_kfifo, check the tx_kfifo | ||
568 | * level and notify the v4l2_device, if it is low. | ||
569 | */ | ||
570 | /* For now, inhibit TSR interrupt until Tx is implemented */ | ||
571 | irqenable_tx(dev, 0); | ||
572 | events = V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ; | ||
573 | v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_TX_NOTIFY, &events); | ||
574 | *handled = true; | ||
575 | } | ||
576 | |||
577 | /* | ||
578 | * Receiver interrupt service | ||
579 | */ | ||
580 | kror = 0; | ||
581 | if ((rse && rsr) || (rte && rto)) { | ||
582 | /* | ||
583 | * Receive data on RSR to clear the STATS_RSR. | ||
584 | * Receive data on RTO, since we may not have yet hit the RSR | ||
585 | * watermark when we receive the RTO. | ||
586 | */ | ||
587 | for (i = 0, v = FIFO_RX_NDV; | ||
588 | (v & FIFO_RX_NDV) && !kror; i = 0) { | ||
589 | for (j = 0; | ||
590 | (v & FIFO_RX_NDV) && j < FIFO_RX_DEPTH; j++) { | ||
591 | v = cx23888_ir_read4(dev, CX23888_IR_FIFO_REG); | ||
592 | rx_data[i++] = v & ~FIFO_RX_NDV; | ||
593 | } | ||
594 | if (i == 0) | ||
595 | break; | ||
596 | j = i * sizeof(u32); | ||
597 | k = kfifo_put(state->rx_kfifo, | ||
598 | (unsigned char *) rx_data, j); | ||
599 | if (k != j) | ||
600 | kror++; /* rx_kfifo over run */ | ||
601 | } | ||
602 | *handled = true; | ||
603 | } | ||
604 | |||
605 | events = 0; | ||
606 | v = 0; | ||
607 | if (kror) { | ||
608 | events |= V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN; | ||
609 | v4l2_err(sd, "IR receiver software FIFO overrun\n"); | ||
610 | } | ||
611 | if (roe && ror) { | ||
612 | /* | ||
613 | * The RX FIFO Enable (CNTRL_RFE) must be toggled to clear | ||
614 | * the Rx FIFO Over Run status (STATS_ROR) | ||
615 | */ | ||
616 | v |= CNTRL_RFE; | ||
617 | events |= V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN; | ||
618 | v4l2_err(sd, "IR receiver hardware FIFO overrun\n"); | ||
619 | } | ||
620 | if (rte && rto) { | ||
621 | /* | ||
622 | * The IR Receiver Enable (CNTRL_RXE) must be toggled to clear | ||
623 | * the Rx Pulse Width Timer Time Out (STATS_RTO) | ||
624 | */ | ||
625 | v |= CNTRL_RXE; | ||
626 | events |= V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED; | ||
627 | } | ||
628 | if (v) { | ||
629 | /* Clear STATS_ROR & STATS_RTO as needed by reseting hardware */ | ||
630 | cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl & ~v); | ||
631 | cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl); | ||
632 | *handled = true; | ||
633 | } | ||
634 | if (kfifo_len(state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE / 2) | ||
635 | events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ; | ||
636 | |||
637 | if (events) | ||
638 | v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_RX_NOTIFY, &events); | ||
639 | return 0; | ||
640 | } | ||
641 | |||
642 | /* Receiver */ | ||
643 | static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count, | ||
644 | ssize_t *num) | ||
645 | { | ||
646 | struct cx23888_ir_state *state = to_state(sd); | ||
647 | bool invert = (bool) atomic_read(&state->rx_invert); | ||
648 | u16 divider = (u16) atomic_read(&state->rxclk_divider); | ||
649 | |||
650 | unsigned int i, n; | ||
651 | u32 *p; | ||
652 | u32 u, v; | ||
653 | |||
654 | n = count / sizeof(u32) * sizeof(u32); | ||
655 | if (n == 0) { | ||
656 | *num = 0; | ||
657 | return 0; | ||
658 | } | ||
659 | |||
660 | n = kfifo_get(state->rx_kfifo, buf, n); | ||
661 | |||
662 | n /= sizeof(u32); | ||
663 | *num = n * sizeof(u32); | ||
664 | |||
665 | for (p = (u32 *) buf, i = 0; i < n; p++, i++) { | ||
666 | if ((*p & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) { | ||
667 | *p = V4L2_SUBDEV_IR_PULSE_RX_SEQ_END; | ||
668 | v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n"); | ||
669 | continue; | ||
670 | } | ||
671 | |||
672 | u = (*p & FIFO_RXTX_LVL) ? V4L2_SUBDEV_IR_PULSE_LEVEL_MASK : 0; | ||
673 | if (invert) | ||
674 | u = u ? 0 : V4L2_SUBDEV_IR_PULSE_LEVEL_MASK; | ||
675 | |||
676 | v = (u32) pulse_width_count_to_ns((u16) (*p & FIFO_RXTX), | ||
677 | divider); | ||
678 | if (v >= V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS) | ||
679 | v = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS - 1; | ||
680 | |||
681 | *p = u | v; | ||
682 | |||
683 | v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns %s\n", | ||
684 | v, u ? "mark" : "space"); | ||
685 | } | ||
686 | return 0; | ||
687 | } | ||
688 | |||
689 | static int cx23888_ir_rx_g_parameters(struct v4l2_subdev *sd, | ||
690 | struct v4l2_subdev_ir_parameters *p) | ||
691 | { | ||
692 | struct cx23888_ir_state *state = to_state(sd); | ||
693 | mutex_lock(&state->rx_params_lock); | ||
694 | memcpy(p, &state->rx_params, sizeof(struct v4l2_subdev_ir_parameters)); | ||
695 | mutex_unlock(&state->rx_params_lock); | ||
696 | return 0; | ||
697 | } | ||
698 | |||
699 | static int cx23888_ir_rx_shutdown(struct v4l2_subdev *sd) | ||
700 | { | ||
701 | struct cx23888_ir_state *state = to_state(sd); | ||
702 | struct cx23885_dev *dev = state->dev; | ||
703 | |||
704 | mutex_lock(&state->rx_params_lock); | ||
705 | |||
706 | /* Disable or slow down all IR Rx circuits and counters */ | ||
707 | irqenable_rx(dev, 0); | ||
708 | control_rx_enable(dev, false); | ||
709 | control_rx_demodulation_enable(dev, false); | ||
710 | control_rx_s_edge_detection(dev, CNTRL_EDG_NONE); | ||
711 | filter_rx_s_min_width(dev, 0); | ||
712 | cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, RXCLK_RCD); | ||
713 | |||
714 | state->rx_params.shutdown = true; | ||
715 | |||
716 | mutex_unlock(&state->rx_params_lock); | ||
717 | return 0; | ||
718 | } | ||
719 | |||
720 | static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd, | ||
721 | struct v4l2_subdev_ir_parameters *p) | ||
722 | { | ||
723 | struct cx23888_ir_state *state = to_state(sd); | ||
724 | struct cx23885_dev *dev = state->dev; | ||
725 | struct v4l2_subdev_ir_parameters *o = &state->rx_params; | ||
726 | u16 rxclk_divider; | ||
727 | |||
728 | if (p->shutdown) | ||
729 | return cx23888_ir_rx_shutdown(sd); | ||
730 | |||
731 | if (p->mode != V4L2_SUBDEV_IR_MODE_PULSE_WIDTH) | ||
732 | return -ENOSYS; | ||
733 | |||
734 | mutex_lock(&state->rx_params_lock); | ||
735 | |||
736 | o->shutdown = p->shutdown; | ||
737 | |||
738 | o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH; | ||
739 | |||
740 | o->bytes_per_data_element = p->bytes_per_data_element = sizeof(u32); | ||
741 | |||
742 | /* Before we tweak the hardware, we have to disable the receiver */ | ||
743 | irqenable_rx(dev, 0); | ||
744 | control_rx_enable(dev, false); | ||
745 | |||
746 | control_rx_demodulation_enable(dev, p->modulation); | ||
747 | o->modulation = p->modulation; | ||
748 | |||
749 | if (p->modulation) { | ||
750 | p->carrier_freq = rxclk_rx_s_carrier(dev, p->carrier_freq, | ||
751 | &rxclk_divider); | ||
752 | |||
753 | o->carrier_freq = p->carrier_freq; | ||
754 | |||
755 | o->duty_cycle = p->duty_cycle = 50; | ||
756 | |||
757 | control_rx_s_carrier_window(dev, p->carrier_freq, | ||
758 | &p->carrier_range_lower, | ||
759 | &p->carrier_range_upper); | ||
760 | o->carrier_range_lower = p->carrier_range_lower; | ||
761 | o->carrier_range_upper = p->carrier_range_upper; | ||
762 | } else { | ||
763 | p->max_pulse_width = | ||
764 | rxclk_rx_s_max_pulse_width(dev, p->max_pulse_width, | ||
765 | &rxclk_divider); | ||
766 | o->max_pulse_width = p->max_pulse_width; | ||
767 | } | ||
768 | atomic_set(&state->rxclk_divider, rxclk_divider); | ||
769 | |||
770 | p->noise_filter_min_width = | ||
771 | filter_rx_s_min_width(dev, p->noise_filter_min_width); | ||
772 | o->noise_filter_min_width = p->noise_filter_min_width; | ||
773 | |||
774 | p->resolution = clock_divider_to_resolution(rxclk_divider); | ||
775 | o->resolution = p->resolution; | ||
776 | |||
777 | /* FIXME - make this dependent on resolution for better performance */ | ||
778 | control_rx_irq_watermark(dev, RX_FIFO_HALF_FULL); | ||
779 | |||
780 | control_rx_s_edge_detection(dev, CNTRL_EDG_BOTH); | ||
781 | |||
782 | o->invert = p->invert; | ||
783 | atomic_set(&state->rx_invert, p->invert); | ||
784 | |||
785 | o->interrupt_enable = p->interrupt_enable; | ||
786 | o->enable = p->enable; | ||
787 | if (p->enable) { | ||
788 | kfifo_reset(state->rx_kfifo); | ||
789 | if (p->interrupt_enable) | ||
790 | irqenable_rx(dev, IRQEN_RSE | IRQEN_RTE | IRQEN_ROE); | ||
791 | control_rx_enable(dev, p->enable); | ||
792 | } | ||
793 | |||
794 | mutex_unlock(&state->rx_params_lock); | ||
795 | return 0; | ||
796 | } | ||
797 | |||
798 | /* Transmitter */ | ||
799 | static int cx23888_ir_tx_write(struct v4l2_subdev *sd, u8 *buf, size_t count, | ||
800 | ssize_t *num) | ||
801 | { | ||
802 | struct cx23888_ir_state *state = to_state(sd); | ||
803 | struct cx23885_dev *dev = state->dev; | ||
804 | /* For now enable the Tx FIFO Service interrupt & pretend we did work */ | ||
805 | irqenable_tx(dev, IRQEN_TSE); | ||
806 | *num = count; | ||
807 | return 0; | ||
808 | } | ||
809 | |||
810 | static int cx23888_ir_tx_g_parameters(struct v4l2_subdev *sd, | ||
811 | struct v4l2_subdev_ir_parameters *p) | ||
812 | { | ||
813 | struct cx23888_ir_state *state = to_state(sd); | ||
814 | mutex_lock(&state->tx_params_lock); | ||
815 | memcpy(p, &state->tx_params, sizeof(struct v4l2_subdev_ir_parameters)); | ||
816 | mutex_unlock(&state->tx_params_lock); | ||
817 | return 0; | ||
818 | } | ||
819 | |||
820 | static int cx23888_ir_tx_shutdown(struct v4l2_subdev *sd) | ||
821 | { | ||
822 | struct cx23888_ir_state *state = to_state(sd); | ||
823 | struct cx23885_dev *dev = state->dev; | ||
824 | |||
825 | mutex_lock(&state->tx_params_lock); | ||
826 | |||
827 | /* Disable or slow down all IR Tx circuits and counters */ | ||
828 | irqenable_tx(dev, 0); | ||
829 | control_tx_enable(dev, false); | ||
830 | control_tx_modulation_enable(dev, false); | ||
831 | cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, TXCLK_TCD); | ||
832 | |||
833 | state->tx_params.shutdown = true; | ||
834 | |||
835 | mutex_unlock(&state->tx_params_lock); | ||
836 | return 0; | ||
837 | } | ||
838 | |||
839 | static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd, | ||
840 | struct v4l2_subdev_ir_parameters *p) | ||
841 | { | ||
842 | struct cx23888_ir_state *state = to_state(sd); | ||
843 | struct cx23885_dev *dev = state->dev; | ||
844 | struct v4l2_subdev_ir_parameters *o = &state->tx_params; | ||
845 | u16 txclk_divider; | ||
846 | |||
847 | if (p->shutdown) | ||
848 | return cx23888_ir_tx_shutdown(sd); | ||
849 | |||
850 | if (p->mode != V4L2_SUBDEV_IR_MODE_PULSE_WIDTH) | ||
851 | return -ENOSYS; | ||
852 | |||
853 | mutex_lock(&state->tx_params_lock); | ||
854 | |||
855 | o->shutdown = p->shutdown; | ||
856 | |||
857 | o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH; | ||
858 | |||
859 | o->bytes_per_data_element = p->bytes_per_data_element = sizeof(u32); | ||
860 | |||
861 | /* Before we tweak the hardware, we have to disable the transmitter */ | ||
862 | irqenable_tx(dev, 0); | ||
863 | control_tx_enable(dev, false); | ||
864 | |||
865 | control_tx_modulation_enable(dev, p->modulation); | ||
866 | o->modulation = p->modulation; | ||
867 | |||
868 | if (p->modulation) { | ||
869 | p->carrier_freq = txclk_tx_s_carrier(dev, p->carrier_freq, | ||
870 | &txclk_divider); | ||
871 | o->carrier_freq = p->carrier_freq; | ||
872 | |||
873 | p->duty_cycle = cduty_tx_s_duty_cycle(dev, p->duty_cycle); | ||
874 | o->duty_cycle = p->duty_cycle; | ||
875 | } else { | ||
876 | p->max_pulse_width = | ||
877 | txclk_tx_s_max_pulse_width(dev, p->max_pulse_width, | ||
878 | &txclk_divider); | ||
879 | o->max_pulse_width = p->max_pulse_width; | ||
880 | } | ||
881 | atomic_set(&state->txclk_divider, txclk_divider); | ||
882 | |||
883 | p->resolution = clock_divider_to_resolution(txclk_divider); | ||
884 | o->resolution = p->resolution; | ||
885 | |||
886 | /* FIXME - make this dependent on resolution for better performance */ | ||
887 | control_tx_irq_watermark(dev, TX_FIFO_HALF_EMPTY); | ||
888 | |||
889 | control_tx_polarity_invert(dev, p->invert); | ||
890 | o->invert = p->invert; | ||
891 | |||
892 | o->interrupt_enable = p->interrupt_enable; | ||
893 | o->enable = p->enable; | ||
894 | if (p->enable) { | ||
895 | kfifo_reset(state->tx_kfifo); | ||
896 | if (p->interrupt_enable) | ||
897 | irqenable_tx(dev, IRQEN_TSE); | ||
898 | control_tx_enable(dev, p->enable); | ||
899 | } | ||
900 | |||
901 | mutex_unlock(&state->tx_params_lock); | ||
902 | return 0; | ||
903 | } | ||
904 | |||
905 | |||
906 | /* | ||
907 | * V4L2 Subdevice Core Ops | ||
908 | */ | ||
909 | static int cx23888_ir_log_status(struct v4l2_subdev *sd) | ||
910 | { | ||
911 | struct cx23888_ir_state *state = to_state(sd); | ||
912 | struct cx23885_dev *dev = state->dev; | ||
913 | char *s; | ||
914 | int i, j; | ||
915 | |||
916 | u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG); | ||
917 | u32 txclk = cx23888_ir_read4(dev, CX23888_IR_TXCLK_REG) & TXCLK_TCD; | ||
918 | u32 rxclk = cx23888_ir_read4(dev, CX23888_IR_RXCLK_REG) & RXCLK_RCD; | ||
919 | u32 cduty = cx23888_ir_read4(dev, CX23888_IR_CDUTY_REG) & CDUTY_CDC; | ||
920 | u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG); | ||
921 | u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG); | ||
922 | u32 filtr = cx23888_ir_read4(dev, CX23888_IR_FILTR_REG) & FILTR_LPF; | ||
923 | |||
924 | v4l2_info(sd, "IR Receiver:\n"); | ||
925 | v4l2_info(sd, "\tEnabled: %s\n", | ||
926 | cntrl & CNTRL_RXE ? "yes" : "no"); | ||
927 | v4l2_info(sd, "\tDemodulation from a carrier: %s\n", | ||
928 | cntrl & CNTRL_DMD ? "enabled" : "disabled"); | ||
929 | v4l2_info(sd, "\tFIFO: %s\n", | ||
930 | cntrl & CNTRL_RFE ? "enabled" : "disabled"); | ||
931 | switch (cntrl & CNTRL_EDG) { | ||
932 | case CNTRL_EDG_NONE: | ||
933 | s = "disabled"; | ||
934 | break; | ||
935 | case CNTRL_EDG_FALL: | ||
936 | s = "falling edge"; | ||
937 | break; | ||
938 | case CNTRL_EDG_RISE: | ||
939 | s = "rising edge"; | ||
940 | break; | ||
941 | case CNTRL_EDG_BOTH: | ||
942 | s = "rising & falling edges"; | ||
943 | break; | ||
944 | default: | ||
945 | s = "??? edge"; | ||
946 | break; | ||
947 | } | ||
948 | v4l2_info(sd, "\tPulse timers' start/stop trigger: %s\n", s); | ||
949 | v4l2_info(sd, "\tFIFO data on pulse timer overflow: %s\n", | ||
950 | cntrl & CNTRL_R ? "not loaded" : "overflow marker"); | ||
951 | v4l2_info(sd, "\tFIFO interrupt watermark: %s\n", | ||
952 | cntrl & CNTRL_RIC ? "not empty" : "half full or greater"); | ||
953 | v4l2_info(sd, "\tLoopback mode: %s\n", | ||
954 | cntrl & CNTRL_LBM ? "loopback active" : "normal receive"); | ||
955 | if (cntrl & CNTRL_DMD) { | ||
956 | v4l2_info(sd, "\tExpected carrier (16 clocks): %u Hz\n", | ||
957 | clock_divider_to_carrier_freq(rxclk)); | ||
958 | switch (cntrl & CNTRL_WIN) { | ||
959 | case CNTRL_WIN_3_3: | ||
960 | i = 3; | ||
961 | j = 3; | ||
962 | break; | ||
963 | case CNTRL_WIN_4_3: | ||
964 | i = 4; | ||
965 | j = 3; | ||
966 | break; | ||
967 | case CNTRL_WIN_3_4: | ||
968 | i = 3; | ||
969 | j = 4; | ||
970 | break; | ||
971 | case CNTRL_WIN_4_4: | ||
972 | i = 4; | ||
973 | j = 4; | ||
974 | break; | ||
975 | default: | ||
976 | i = 0; | ||
977 | j = 0; | ||
978 | break; | ||
979 | } | ||
980 | v4l2_info(sd, "\tNext carrier edge window: 16 clocks " | ||
981 | "-%1d/+%1d, %u to %u Hz\n", i, j, | ||
982 | clock_divider_to_freq(rxclk, 16 + j), | ||
983 | clock_divider_to_freq(rxclk, 16 - i)); | ||
984 | } else { | ||
985 | v4l2_info(sd, "\tMax measurable pulse width: %u us, " | ||
986 | "%llu ns\n", | ||
987 | pulse_width_count_to_us(FIFO_RXTX, rxclk), | ||
988 | pulse_width_count_to_ns(FIFO_RXTX, rxclk)); | ||
989 | } | ||
990 | v4l2_info(sd, "\tLow pass filter: %s\n", | ||
991 | filtr ? "enabled" : "disabled"); | ||
992 | if (filtr) | ||
993 | v4l2_info(sd, "\tMin acceptable pulse width (LPF): %u us, " | ||
994 | "%u ns\n", | ||
995 | lpf_count_to_us(filtr), | ||
996 | lpf_count_to_ns(filtr)); | ||
997 | v4l2_info(sd, "\tPulse width timer timed-out: %s\n", | ||
998 | stats & STATS_RTO ? "yes" : "no"); | ||
999 | v4l2_info(sd, "\tPulse width timer time-out intr: %s\n", | ||
1000 | irqen & IRQEN_RTE ? "enabled" : "disabled"); | ||
1001 | v4l2_info(sd, "\tFIFO overrun: %s\n", | ||
1002 | stats & STATS_ROR ? "yes" : "no"); | ||
1003 | v4l2_info(sd, "\tFIFO overrun interrupt: %s\n", | ||
1004 | irqen & IRQEN_ROE ? "enabled" : "disabled"); | ||
1005 | v4l2_info(sd, "\tBusy: %s\n", | ||
1006 | stats & STATS_RBY ? "yes" : "no"); | ||
1007 | v4l2_info(sd, "\tFIFO service requested: %s\n", | ||
1008 | stats & STATS_RSR ? "yes" : "no"); | ||
1009 | v4l2_info(sd, "\tFIFO service request interrupt: %s\n", | ||
1010 | irqen & IRQEN_RSE ? "enabled" : "disabled"); | ||
1011 | |||
1012 | v4l2_info(sd, "IR Transmitter:\n"); | ||
1013 | v4l2_info(sd, "\tEnabled: %s\n", | ||
1014 | cntrl & CNTRL_TXE ? "yes" : "no"); | ||
1015 | v4l2_info(sd, "\tModulation onto a carrier: %s\n", | ||
1016 | cntrl & CNTRL_MOD ? "enabled" : "disabled"); | ||
1017 | v4l2_info(sd, "\tFIFO: %s\n", | ||
1018 | cntrl & CNTRL_TFE ? "enabled" : "disabled"); | ||
1019 | v4l2_info(sd, "\tFIFO interrupt watermark: %s\n", | ||
1020 | cntrl & CNTRL_TIC ? "not empty" : "half full or less"); | ||
1021 | v4l2_info(sd, "\tSignal polarity: %s\n", | ||
1022 | cntrl & CNTRL_CPL ? "0:mark 1:space" : "0:space 1:mark"); | ||
1023 | if (cntrl & CNTRL_MOD) { | ||
1024 | v4l2_info(sd, "\tCarrier (16 clocks): %u Hz\n", | ||
1025 | clock_divider_to_carrier_freq(txclk)); | ||
1026 | v4l2_info(sd, "\tCarrier duty cycle: %2u/16\n", | ||
1027 | cduty + 1); | ||
1028 | } else { | ||
1029 | v4l2_info(sd, "\tMax pulse width: %u us, " | ||
1030 | "%llu ns\n", | ||
1031 | pulse_width_count_to_us(FIFO_RXTX, txclk), | ||
1032 | pulse_width_count_to_ns(FIFO_RXTX, txclk)); | ||
1033 | } | ||
1034 | v4l2_info(sd, "\tBusy: %s\n", | ||
1035 | stats & STATS_TBY ? "yes" : "no"); | ||
1036 | v4l2_info(sd, "\tFIFO service requested: %s\n", | ||
1037 | stats & STATS_TSR ? "yes" : "no"); | ||
1038 | v4l2_info(sd, "\tFIFO service request interrupt: %s\n", | ||
1039 | irqen & IRQEN_TSE ? "enabled" : "disabled"); | ||
1040 | |||
1041 | return 0; | ||
1042 | } | ||
1043 | |||
1044 | static inline int cx23888_ir_dbg_match(const struct v4l2_dbg_match *match) | ||
1045 | { | ||
1046 | return match->type == V4L2_CHIP_MATCH_HOST && match->addr == 2; | ||
1047 | } | ||
1048 | |||
1049 | static int cx23888_ir_g_chip_ident(struct v4l2_subdev *sd, | ||
1050 | struct v4l2_dbg_chip_ident *chip) | ||
1051 | { | ||
1052 | struct cx23888_ir_state *state = to_state(sd); | ||
1053 | |||
1054 | if (cx23888_ir_dbg_match(&chip->match)) { | ||
1055 | chip->ident = state->id; | ||
1056 | chip->revision = state->rev; | ||
1057 | } | ||
1058 | return 0; | ||
1059 | } | ||
1060 | |||
1061 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1062 | static int cx23888_ir_g_register(struct v4l2_subdev *sd, | ||
1063 | struct v4l2_dbg_register *reg) | ||
1064 | { | ||
1065 | struct cx23888_ir_state *state = to_state(sd); | ||
1066 | u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg; | ||
1067 | |||
1068 | if (!cx23888_ir_dbg_match(®->match)) | ||
1069 | return -EINVAL; | ||
1070 | if ((addr & 0x3) != 0) | ||
1071 | return -EINVAL; | ||
1072 | if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG) | ||
1073 | return -EINVAL; | ||
1074 | if (!capable(CAP_SYS_ADMIN)) | ||
1075 | return -EPERM; | ||
1076 | reg->size = 4; | ||
1077 | reg->val = cx23888_ir_read4(state->dev, addr); | ||
1078 | return 0; | ||
1079 | } | ||
1080 | |||
1081 | static int cx23888_ir_s_register(struct v4l2_subdev *sd, | ||
1082 | struct v4l2_dbg_register *reg) | ||
1083 | { | ||
1084 | struct cx23888_ir_state *state = to_state(sd); | ||
1085 | u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg; | ||
1086 | |||
1087 | if (!cx23888_ir_dbg_match(®->match)) | ||
1088 | return -EINVAL; | ||
1089 | if ((addr & 0x3) != 0) | ||
1090 | return -EINVAL; | ||
1091 | if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG) | ||
1092 | return -EINVAL; | ||
1093 | if (!capable(CAP_SYS_ADMIN)) | ||
1094 | return -EPERM; | ||
1095 | cx23888_ir_write4(state->dev, addr, reg->val); | ||
1096 | return 0; | ||
1097 | } | ||
1098 | #endif | ||
1099 | |||
1100 | static const struct v4l2_subdev_core_ops cx23888_ir_core_ops = { | ||
1101 | .g_chip_ident = cx23888_ir_g_chip_ident, | ||
1102 | .log_status = cx23888_ir_log_status, | ||
1103 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1104 | .g_register = cx23888_ir_g_register, | ||
1105 | .s_register = cx23888_ir_s_register, | ||
1106 | #endif | ||
1107 | }; | ||
1108 | |||
1109 | static const struct v4l2_subdev_ir_ops cx23888_ir_ir_ops = { | ||
1110 | .interrupt_service_routine = cx23888_ir_irq_handler, | ||
1111 | |||
1112 | .rx_read = cx23888_ir_rx_read, | ||
1113 | .rx_g_parameters = cx23888_ir_rx_g_parameters, | ||
1114 | .rx_s_parameters = cx23888_ir_rx_s_parameters, | ||
1115 | |||
1116 | .tx_write = cx23888_ir_tx_write, | ||
1117 | .tx_g_parameters = cx23888_ir_tx_g_parameters, | ||
1118 | .tx_s_parameters = cx23888_ir_tx_s_parameters, | ||
1119 | }; | ||
1120 | |||
1121 | static const struct v4l2_subdev_ops cx23888_ir_controller_ops = { | ||
1122 | .core = &cx23888_ir_core_ops, | ||
1123 | .ir = &cx23888_ir_ir_ops, | ||
1124 | }; | ||
1125 | |||
1126 | static const struct v4l2_subdev_ir_parameters default_rx_params = { | ||
1127 | .bytes_per_data_element = sizeof(u32), | ||
1128 | .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH, | ||
1129 | |||
1130 | .enable = false, | ||
1131 | .interrupt_enable = false, | ||
1132 | .shutdown = true, | ||
1133 | |||
1134 | .modulation = true, | ||
1135 | .carrier_freq = 36000, /* 36 kHz - RC-5, RC-6, and RC-6A carrier */ | ||
1136 | |||
1137 | /* RC-5: 666,667 ns = 1/36 kHz * 32 cycles * 1 mark * 0.75 */ | ||
1138 | /* RC-6A: 333,333 ns = 1/36 kHz * 16 cycles * 1 mark * 0.75 */ | ||
1139 | .noise_filter_min_width = 333333, /* ns */ | ||
1140 | .carrier_range_lower = 35000, | ||
1141 | .carrier_range_upper = 37000, | ||
1142 | .invert = false, | ||
1143 | }; | ||
1144 | |||
1145 | static const struct v4l2_subdev_ir_parameters default_tx_params = { | ||
1146 | .bytes_per_data_element = sizeof(u32), | ||
1147 | .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH, | ||
1148 | |||
1149 | .enable = false, | ||
1150 | .interrupt_enable = false, | ||
1151 | .shutdown = true, | ||
1152 | |||
1153 | .modulation = true, | ||
1154 | .carrier_freq = 36000, /* 36 kHz - RC-5 carrier */ | ||
1155 | .duty_cycle = 25, /* 25 % - RC-5 carrier */ | ||
1156 | .invert = false, | ||
1157 | }; | ||
1158 | |||
1159 | int cx23888_ir_probe(struct cx23885_dev *dev) | ||
1160 | { | ||
1161 | struct cx23888_ir_state *state; | ||
1162 | struct v4l2_subdev *sd; | ||
1163 | struct v4l2_subdev_ir_parameters default_params; | ||
1164 | int ret; | ||
1165 | |||
1166 | state = kzalloc(sizeof(struct cx23888_ir_state), GFP_KERNEL); | ||
1167 | if (state == NULL) | ||
1168 | return -ENOMEM; | ||
1169 | |||
1170 | spin_lock_init(&state->rx_kfifo_lock); | ||
1171 | state->rx_kfifo = kfifo_alloc(CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL, | ||
1172 | &state->rx_kfifo_lock); | ||
1173 | if (state->rx_kfifo == NULL) | ||
1174 | return -ENOMEM; | ||
1175 | |||
1176 | spin_lock_init(&state->tx_kfifo_lock); | ||
1177 | state->tx_kfifo = kfifo_alloc(CX23888_IR_TX_KFIFO_SIZE, GFP_KERNEL, | ||
1178 | &state->tx_kfifo_lock); | ||
1179 | if (state->tx_kfifo == NULL) { | ||
1180 | kfifo_free(state->rx_kfifo); | ||
1181 | return -ENOMEM; | ||
1182 | } | ||
1183 | |||
1184 | state->dev = dev; | ||
1185 | state->id = V4L2_IDENT_CX23888_IR; | ||
1186 | state->rev = 0; | ||
1187 | sd = &state->sd; | ||
1188 | |||
1189 | v4l2_subdev_init(sd, &cx23888_ir_controller_ops); | ||
1190 | v4l2_set_subdevdata(sd, state); | ||
1191 | /* FIXME - fix the formatting of dev->v4l2_dev.name and use it */ | ||
1192 | snprintf(sd->name, sizeof(sd->name), "%s/888-ir", dev->name); | ||
1193 | sd->grp_id = CX23885_HW_888_IR; | ||
1194 | |||
1195 | ret = v4l2_device_register_subdev(&dev->v4l2_dev, sd); | ||
1196 | if (ret == 0) { | ||
1197 | /* | ||
1198 | * Ensure no interrupts arrive from '888 specific conditions, | ||
1199 | * since we ignore them in this driver to have commonality with | ||
1200 | * similar IR controller cores. | ||
1201 | */ | ||
1202 | cx23888_ir_write4(dev, CX23888_IR_IRQEN_REG, 0); | ||
1203 | |||
1204 | mutex_init(&state->rx_params_lock); | ||
1205 | memcpy(&default_params, &default_rx_params, | ||
1206 | sizeof(struct v4l2_subdev_ir_parameters)); | ||
1207 | v4l2_subdev_call(sd, ir, rx_s_parameters, &default_params); | ||
1208 | |||
1209 | mutex_init(&state->tx_params_lock); | ||
1210 | memcpy(&default_params, &default_tx_params, | ||
1211 | sizeof(struct v4l2_subdev_ir_parameters)); | ||
1212 | v4l2_subdev_call(sd, ir, tx_s_parameters, &default_params); | ||
1213 | } else { | ||
1214 | kfifo_free(state->rx_kfifo); | ||
1215 | kfifo_free(state->tx_kfifo); | ||
1216 | } | ||
1217 | return ret; | ||
1218 | } | ||
1219 | |||
1220 | int cx23888_ir_remove(struct cx23885_dev *dev) | ||
1221 | { | ||
1222 | struct v4l2_subdev *sd; | ||
1223 | struct cx23888_ir_state *state; | ||
1224 | |||
1225 | sd = cx23885_find_hw(dev, CX23885_HW_888_IR); | ||
1226 | if (sd == NULL) | ||
1227 | return -ENODEV; | ||
1228 | |||
1229 | cx23888_ir_rx_shutdown(sd); | ||
1230 | cx23888_ir_tx_shutdown(sd); | ||
1231 | |||
1232 | state = to_state(sd); | ||
1233 | v4l2_device_unregister_subdev(sd); | ||
1234 | kfifo_free(state->rx_kfifo); | ||
1235 | kfifo_free(state->tx_kfifo); | ||
1236 | kfree(state); | ||
1237 | /* Nothing more to free() as state held the actual v4l2_subdev object */ | ||
1238 | return 0; | ||
1239 | } | ||
diff --git a/drivers/media/video/cx23885/cx23888-ir.h b/drivers/media/video/cx23885/cx23888-ir.h new file mode 100644 index 000000000000..3d446f9eb94b --- /dev/null +++ b/drivers/media/video/cx23885/cx23888-ir.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX23885/7/8 PCIe bridge | ||
3 | * | ||
4 | * CX23888 Integrated Consumer Infrared Controller | ||
5 | * | ||
6 | * Copyright (C) 2009 Andy Walls <awalls@radix.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version 2 | ||
11 | * of the License, or (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 | #ifndef _CX23888_IR_H_ | ||
25 | #define _CX23888_IR_H_ | ||
26 | int cx23888_ir_probe(struct cx23885_dev *dev); | ||
27 | int cx23888_ir_remove(struct cx23885_dev *dev); | ||
28 | #endif | ||
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c index 2f846f5e0f9f..45608d50529c 100644 --- a/drivers/media/video/cx25840/cx25840-audio.c +++ b/drivers/media/video/cx25840/cx25840-audio.c | |||
@@ -23,87 +23,137 @@ | |||
23 | 23 | ||
24 | #include "cx25840-core.h" | 24 | #include "cx25840-core.h" |
25 | 25 | ||
26 | static int set_audclk_freq(struct i2c_client *client, u32 freq) | 26 | /* |
27 | * Note: The PLL and SRC parameters are based on a reference frequency that | ||
28 | * would ideally be: | ||
29 | * | ||
30 | * NTSC Color subcarrier freq * 8 = 4.5 MHz/286 * 455/2 * 8 = 28.63636363... MHz | ||
31 | * | ||
32 | * However, it's not the exact reference frequency that matters, only that the | ||
33 | * firmware and modules that comprise the driver for a particular board all | ||
34 | * use the same value (close to the ideal value). | ||
35 | * | ||
36 | * Comments below will note which reference frequency is assumed for various | ||
37 | * parameters. They will usually be one of | ||
38 | * | ||
39 | * ref_freq = 28.636360 MHz | ||
40 | * or | ||
41 | * ref_freq = 28.636363 MHz | ||
42 | */ | ||
43 | |||
44 | static int cx25840_set_audclk_freq(struct i2c_client *client, u32 freq) | ||
27 | { | 45 | { |
28 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); | 46 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
29 | 47 | ||
30 | if (freq != 32000 && freq != 44100 && freq != 48000) | ||
31 | return -EINVAL; | ||
32 | |||
33 | /* common for all inputs and rates */ | ||
34 | /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */ | ||
35 | if (!state->is_cx23885 && !state->is_cx231xx) | ||
36 | cx25840_write(client, 0x127, 0x50); | ||
37 | |||
38 | if (state->aud_input != CX25840_AUDIO_SERIAL) { | 48 | if (state->aud_input != CX25840_AUDIO_SERIAL) { |
39 | switch (freq) { | 49 | switch (freq) { |
40 | case 32000: | 50 | case 32000: |
41 | if (state->is_cx23885) { | 51 | /* |
42 | /* We don't have register values | 52 | * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04 |
43 | * so avoid destroying registers. */ | 53 | * AUX_PLL Integer = 0x06, AUX PLL Post Divider = 0x10 |
44 | break; | 54 | */ |
45 | } | 55 | cx25840_write4(client, 0x108, 0x1006040f); |
46 | 56 | ||
47 | if (!state->is_cx231xx) { | 57 | /* |
48 | /* VID_PLL and AUX_PLL */ | 58 | * VID_PLL Fraction (register 0x10c) = 0x2be2fe |
49 | cx25840_write4(client, 0x108, 0x1006040f); | 59 | * 28636360 * 0xf.15f17f0/4 = 108 MHz |
50 | 60 | * 432 MHz pre-postdivide | |
51 | /* AUX_PLL_FRAC */ | 61 | */ |
52 | cx25840_write4(client, 0x110, 0x01bb39ee); | 62 | |
53 | } | 63 | /* |
54 | 64 | * AUX_PLL Fraction = 0x1bb39ee | |
55 | if (state->is_cx25836) | 65 | * 28636363 * 0x6.dd9cf70/0x10 = 32000 * 384 |
66 | * 196.6 MHz pre-postdivide | ||
67 | * FIXME < 200 MHz is out of specified valid range | ||
68 | * FIXME 28636363 ref_freq doesn't match VID PLL ref | ||
69 | */ | ||
70 | cx25840_write4(client, 0x110, 0x01bb39ee); | ||
71 | |||
72 | /* | ||
73 | * SA_MCLK_SEL = 1 | ||
74 | * SA_MCLK_DIV = 0x10 = 384/384 * AUX_PLL post dvivider | ||
75 | */ | ||
76 | cx25840_write(client, 0x127, 0x50); | ||
77 | |||
78 | if (is_cx2583x(state)) | ||
56 | break; | 79 | break; |
57 | 80 | ||
58 | /* src3/4/6_ctl = 0x0801f77f */ | 81 | /* src3/4/6_ctl */ |
82 | /* 0x1.f77f = (4 * 28636360/8 * 2/455) / 32000 */ | ||
59 | cx25840_write4(client, 0x900, 0x0801f77f); | 83 | cx25840_write4(client, 0x900, 0x0801f77f); |
60 | cx25840_write4(client, 0x904, 0x0801f77f); | 84 | cx25840_write4(client, 0x904, 0x0801f77f); |
61 | cx25840_write4(client, 0x90c, 0x0801f77f); | 85 | cx25840_write4(client, 0x90c, 0x0801f77f); |
62 | break; | 86 | break; |
63 | 87 | ||
64 | case 44100: | 88 | case 44100: |
65 | if (state->is_cx23885) { | 89 | /* |
66 | /* We don't have register values | 90 | * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04 |
67 | * so avoid destroying registers. */ | 91 | * AUX_PLL Integer = 0x09, AUX PLL Post Divider = 0x10 |
92 | */ | ||
93 | cx25840_write4(client, 0x108, 0x1009040f); | ||
94 | |||
95 | /* | ||
96 | * VID_PLL Fraction (register 0x10c) = 0x2be2fe | ||
97 | * 28636360 * 0xf.15f17f0/4 = 108 MHz | ||
98 | * 432 MHz pre-postdivide | ||
99 | */ | ||
100 | |||
101 | /* | ||
102 | * AUX_PLL Fraction = 0x0ec6bd6 | ||
103 | * 28636363 * 0x9.7635eb0/0x10 = 44100 * 384 | ||
104 | * 271 MHz pre-postdivide | ||
105 | * FIXME 28636363 ref_freq doesn't match VID PLL ref | ||
106 | */ | ||
107 | cx25840_write4(client, 0x110, 0x00ec6bd6); | ||
108 | |||
109 | /* | ||
110 | * SA_MCLK_SEL = 1 | ||
111 | * SA_MCLK_DIV = 0x10 = 384/384 * AUX_PLL post dvivider | ||
112 | */ | ||
113 | cx25840_write(client, 0x127, 0x50); | ||
114 | |||
115 | if (is_cx2583x(state)) | ||
68 | break; | 116 | break; |
69 | } | ||
70 | |||
71 | if (!state->is_cx231xx) { | ||
72 | /* VID_PLL and AUX_PLL */ | ||
73 | cx25840_write4(client, 0x108, 0x1009040f); | ||
74 | |||
75 | /* AUX_PLL_FRAC */ | ||
76 | cx25840_write4(client, 0x110, 0x00ec6bd6); | ||
77 | } | ||
78 | 117 | ||
79 | if (state->is_cx25836) | 118 | /* src3/4/6_ctl */ |
80 | break; | 119 | /* 0x1.6d59 = (4 * 28636360/8 * 2/455) / 44100 */ |
81 | |||
82 | /* src3/4/6_ctl = 0x08016d59 */ | ||
83 | cx25840_write4(client, 0x900, 0x08016d59); | 120 | cx25840_write4(client, 0x900, 0x08016d59); |
84 | cx25840_write4(client, 0x904, 0x08016d59); | 121 | cx25840_write4(client, 0x904, 0x08016d59); |
85 | cx25840_write4(client, 0x90c, 0x08016d59); | 122 | cx25840_write4(client, 0x90c, 0x08016d59); |
86 | break; | 123 | break; |
87 | 124 | ||
88 | case 48000: | 125 | case 48000: |
89 | if (state->is_cx23885) { | 126 | /* |
90 | /* We don't have register values | 127 | * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04 |
91 | * so avoid destroying registers. */ | 128 | * AUX_PLL Integer = 0x0a, AUX PLL Post Divider = 0x10 |
92 | break; | 129 | */ |
93 | } | 130 | cx25840_write4(client, 0x108, 0x100a040f); |
94 | 131 | ||
95 | if (!state->is_cx231xx) { | 132 | /* |
96 | /* VID_PLL and AUX_PLL */ | 133 | * VID_PLL Fraction (register 0x10c) = 0x2be2fe |
97 | cx25840_write4(client, 0x108, 0x100a040f); | 134 | * 28636360 * 0xf.15f17f0/4 = 108 MHz |
98 | 135 | * 432 MHz pre-postdivide | |
99 | /* AUX_PLL_FRAC */ | 136 | */ |
100 | cx25840_write4(client, 0x110, 0x0098d6e5); | 137 | |
101 | } | 138 | /* |
102 | 139 | * AUX_PLL Fraction = 0x098d6e5 | |
103 | if (state->is_cx25836) | 140 | * 28636363 * 0xa.4c6b728/0x10 = 48000 * 384 |
141 | * 295 MHz pre-postdivide | ||
142 | * FIXME 28636363 ref_freq doesn't match VID PLL ref | ||
143 | */ | ||
144 | cx25840_write4(client, 0x110, 0x0098d6e5); | ||
145 | |||
146 | /* | ||
147 | * SA_MCLK_SEL = 1 | ||
148 | * SA_MCLK_DIV = 0x10 = 384/384 * AUX_PLL post dvivider | ||
149 | */ | ||
150 | cx25840_write(client, 0x127, 0x50); | ||
151 | |||
152 | if (is_cx2583x(state)) | ||
104 | break; | 153 | break; |
105 | 154 | ||
106 | /* src3/4/6_ctl = 0x08014faa */ | 155 | /* src3/4/6_ctl */ |
156 | /* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */ | ||
107 | cx25840_write4(client, 0x900, 0x08014faa); | 157 | cx25840_write4(client, 0x900, 0x08014faa); |
108 | cx25840_write4(client, 0x904, 0x08014faa); | 158 | cx25840_write4(client, 0x904, 0x08014faa); |
109 | cx25840_write4(client, 0x90c, 0x08014faa); | 159 | cx25840_write4(client, 0x90c, 0x08014faa); |
@@ -112,91 +162,249 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) | |||
112 | } else { | 162 | } else { |
113 | switch (freq) { | 163 | switch (freq) { |
114 | case 32000: | 164 | case 32000: |
115 | if (state->is_cx23885) { | 165 | /* |
116 | /* We don't have register values | 166 | * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04 |
117 | * so avoid destroying registers. */ | 167 | * AUX_PLL Integer = 0x08, AUX PLL Post Divider = 0x1e |
118 | break; | 168 | */ |
119 | } | 169 | cx25840_write4(client, 0x108, 0x1e08040f); |
120 | 170 | ||
121 | if (!state->is_cx231xx) { | 171 | /* |
122 | /* VID_PLL and AUX_PLL */ | 172 | * VID_PLL Fraction (register 0x10c) = 0x2be2fe |
123 | cx25840_write4(client, 0x108, 0x1e08040f); | 173 | * 28636360 * 0xf.15f17f0/4 = 108 MHz |
124 | 174 | * 432 MHz pre-postdivide | |
125 | /* AUX_PLL_FRAC */ | 175 | */ |
126 | cx25840_write4(client, 0x110, 0x012a0869); | 176 | |
127 | } | 177 | /* |
178 | * AUX_PLL Fraction = 0x12a0869 | ||
179 | * 28636363 * 0x8.9504348/0x1e = 32000 * 256 | ||
180 | * 246 MHz pre-postdivide | ||
181 | * FIXME 28636363 ref_freq doesn't match VID PLL ref | ||
182 | */ | ||
183 | cx25840_write4(client, 0x110, 0x012a0869); | ||
184 | |||
185 | /* | ||
186 | * SA_MCLK_SEL = 1 | ||
187 | * SA_MCLK_DIV = 0x14 = 256/384 * AUX_PLL post dvivider | ||
188 | */ | ||
189 | cx25840_write(client, 0x127, 0x54); | ||
128 | 190 | ||
129 | if (state->is_cx25836) | 191 | if (is_cx2583x(state)) |
130 | break; | 192 | break; |
131 | 193 | ||
132 | /* src1_ctl = 0x08010000 */ | 194 | /* src1_ctl */ |
195 | /* 0x1.0000 = 32000/32000 */ | ||
133 | cx25840_write4(client, 0x8f8, 0x08010000); | 196 | cx25840_write4(client, 0x8f8, 0x08010000); |
134 | 197 | ||
135 | /* src3/4/6_ctl = 0x08020000 */ | 198 | /* src3/4/6_ctl */ |
199 | /* 0x2.0000 = 2 * (32000/32000) */ | ||
136 | cx25840_write4(client, 0x900, 0x08020000); | 200 | cx25840_write4(client, 0x900, 0x08020000); |
137 | cx25840_write4(client, 0x904, 0x08020000); | 201 | cx25840_write4(client, 0x904, 0x08020000); |
138 | cx25840_write4(client, 0x90c, 0x08020000); | 202 | cx25840_write4(client, 0x90c, 0x08020000); |
139 | |||
140 | /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */ | ||
141 | cx25840_write(client, 0x127, 0x54); | ||
142 | break; | 203 | break; |
143 | 204 | ||
144 | case 44100: | 205 | case 44100: |
145 | if (state->is_cx23885) { | 206 | /* |
146 | /* We don't have register values | 207 | * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04 |
147 | * so avoid destroying registers. */ | 208 | * AUX_PLL Integer = 0x09, AUX PLL Post Divider = 0x18 |
148 | break; | 209 | */ |
149 | } | 210 | cx25840_write4(client, 0x108, 0x1809040f); |
150 | 211 | ||
151 | 212 | /* | |
152 | if (!state->is_cx231xx) { | 213 | * VID_PLL Fraction (register 0x10c) = 0x2be2fe |
153 | /* VID_PLL and AUX_PLL */ | 214 | * 28636360 * 0xf.15f17f0/4 = 108 MHz |
154 | cx25840_write4(client, 0x108, 0x1809040f); | 215 | * 432 MHz pre-postdivide |
155 | 216 | */ | |
156 | /* AUX_PLL_FRAC */ | 217 | |
157 | cx25840_write4(client, 0x110, 0x00ec6bd6); | 218 | /* |
158 | } | 219 | * AUX_PLL Fraction = 0x0ec6bd6 |
159 | 220 | * 28636363 * 0x9.7635eb0/0x18 = 44100 * 256 | |
160 | if (state->is_cx25836) | 221 | * 271 MHz pre-postdivide |
222 | * FIXME 28636363 ref_freq doesn't match VID PLL ref | ||
223 | */ | ||
224 | cx25840_write4(client, 0x110, 0x00ec6bd6); | ||
225 | |||
226 | /* | ||
227 | * SA_MCLK_SEL = 1 | ||
228 | * SA_MCLK_DIV = 0x10 = 256/384 * AUX_PLL post dvivider | ||
229 | */ | ||
230 | cx25840_write(client, 0x127, 0x50); | ||
231 | |||
232 | if (is_cx2583x(state)) | ||
161 | break; | 233 | break; |
162 | 234 | ||
163 | /* src1_ctl = 0x08010000 */ | 235 | /* src1_ctl */ |
236 | /* 0x1.60cd = 44100/32000 */ | ||
164 | cx25840_write4(client, 0x8f8, 0x080160cd); | 237 | cx25840_write4(client, 0x8f8, 0x080160cd); |
165 | 238 | ||
166 | /* src3/4/6_ctl = 0x08020000 */ | 239 | /* src3/4/6_ctl */ |
240 | /* 0x1.7385 = 2 * (32000/44100) */ | ||
167 | cx25840_write4(client, 0x900, 0x08017385); | 241 | cx25840_write4(client, 0x900, 0x08017385); |
168 | cx25840_write4(client, 0x904, 0x08017385); | 242 | cx25840_write4(client, 0x904, 0x08017385); |
169 | cx25840_write4(client, 0x90c, 0x08017385); | 243 | cx25840_write4(client, 0x90c, 0x08017385); |
170 | break; | 244 | break; |
171 | 245 | ||
172 | case 48000: | 246 | case 48000: |
173 | if (!state->is_cx23885 && !state->is_cx231xx) { | 247 | /* |
174 | /* VID_PLL and AUX_PLL */ | 248 | * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04 |
175 | cx25840_write4(client, 0x108, 0x180a040f); | 249 | * AUX_PLL Integer = 0x0a, AUX PLL Post Divider = 0x18 |
250 | */ | ||
251 | cx25840_write4(client, 0x108, 0x180a040f); | ||
252 | |||
253 | /* | ||
254 | * VID_PLL Fraction (register 0x10c) = 0x2be2fe | ||
255 | * 28636360 * 0xf.15f17f0/4 = 108 MHz | ||
256 | * 432 MHz pre-postdivide | ||
257 | */ | ||
258 | |||
259 | /* | ||
260 | * AUX_PLL Fraction = 0x098d6e5 | ||
261 | * 28636363 * 0xa.4c6b728/0x18 = 48000 * 256 | ||
262 | * 295 MHz pre-postdivide | ||
263 | * FIXME 28636363 ref_freq doesn't match VID PLL ref | ||
264 | */ | ||
265 | cx25840_write4(client, 0x110, 0x0098d6e5); | ||
266 | |||
267 | /* | ||
268 | * SA_MCLK_SEL = 1 | ||
269 | * SA_MCLK_DIV = 0x10 = 256/384 * AUX_PLL post dvivider | ||
270 | */ | ||
271 | cx25840_write(client, 0x127, 0x50); | ||
272 | |||
273 | if (is_cx2583x(state)) | ||
274 | break; | ||
176 | 275 | ||
177 | /* AUX_PLL_FRAC */ | 276 | /* src1_ctl */ |
178 | cx25840_write4(client, 0x110, 0x0098d6e5); | 277 | /* 0x1.8000 = 48000/32000 */ |
179 | } | 278 | cx25840_write4(client, 0x8f8, 0x08018000); |
180 | 279 | ||
181 | if (state->is_cx25836) | 280 | /* src3/4/6_ctl */ |
182 | break; | 281 | /* 0x1.5555 = 2 * (32000/48000) */ |
282 | cx25840_write4(client, 0x900, 0x08015555); | ||
283 | cx25840_write4(client, 0x904, 0x08015555); | ||
284 | cx25840_write4(client, 0x90c, 0x08015555); | ||
285 | break; | ||
286 | } | ||
287 | } | ||
288 | |||
289 | state->audclk_freq = freq; | ||
290 | |||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | static inline int cx25836_set_audclk_freq(struct i2c_client *client, u32 freq) | ||
295 | { | ||
296 | return cx25840_set_audclk_freq(client, freq); | ||
297 | } | ||
298 | |||
299 | static int cx23885_set_audclk_freq(struct i2c_client *client, u32 freq) | ||
300 | { | ||
301 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); | ||
302 | |||
303 | if (state->aud_input != CX25840_AUDIO_SERIAL) { | ||
304 | switch (freq) { | ||
305 | case 32000: | ||
306 | case 44100: | ||
307 | case 48000: | ||
308 | /* We don't have register values | ||
309 | * so avoid destroying registers. */ | ||
310 | /* FIXME return -EINVAL; */ | ||
311 | break; | ||
312 | } | ||
313 | } else { | ||
314 | switch (freq) { | ||
315 | case 32000: | ||
316 | case 44100: | ||
317 | /* We don't have register values | ||
318 | * so avoid destroying registers. */ | ||
319 | /* FIXME return -EINVAL; */ | ||
320 | break; | ||
321 | |||
322 | case 48000: | ||
323 | /* src1_ctl */ | ||
324 | /* 0x1.867c = 48000 / (2 * 28636360/8 * 2/455) */ | ||
325 | cx25840_write4(client, 0x8f8, 0x0801867c); | ||
326 | |||
327 | /* src3/4/6_ctl */ | ||
328 | /* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */ | ||
329 | cx25840_write4(client, 0x900, 0x08014faa); | ||
330 | cx25840_write4(client, 0x904, 0x08014faa); | ||
331 | cx25840_write4(client, 0x90c, 0x08014faa); | ||
332 | break; | ||
333 | } | ||
334 | } | ||
335 | |||
336 | state->audclk_freq = freq; | ||
337 | |||
338 | return 0; | ||
339 | } | ||
340 | |||
341 | static int cx231xx_set_audclk_freq(struct i2c_client *client, u32 freq) | ||
342 | { | ||
343 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); | ||
344 | |||
345 | if (state->aud_input != CX25840_AUDIO_SERIAL) { | ||
346 | switch (freq) { | ||
347 | case 32000: | ||
348 | /* src3/4/6_ctl */ | ||
349 | /* 0x1.f77f = (4 * 28636360/8 * 2/455) / 32000 */ | ||
350 | cx25840_write4(client, 0x900, 0x0801f77f); | ||
351 | cx25840_write4(client, 0x904, 0x0801f77f); | ||
352 | cx25840_write4(client, 0x90c, 0x0801f77f); | ||
353 | break; | ||
354 | |||
355 | case 44100: | ||
356 | /* src3/4/6_ctl */ | ||
357 | /* 0x1.6d59 = (4 * 28636360/8 * 2/455) / 44100 */ | ||
358 | cx25840_write4(client, 0x900, 0x08016d59); | ||
359 | cx25840_write4(client, 0x904, 0x08016d59); | ||
360 | cx25840_write4(client, 0x90c, 0x08016d59); | ||
361 | break; | ||
362 | |||
363 | case 48000: | ||
364 | /* src3/4/6_ctl */ | ||
365 | /* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */ | ||
366 | cx25840_write4(client, 0x900, 0x08014faa); | ||
367 | cx25840_write4(client, 0x904, 0x08014faa); | ||
368 | cx25840_write4(client, 0x90c, 0x08014faa); | ||
369 | break; | ||
370 | } | ||
371 | } else { | ||
372 | switch (freq) { | ||
373 | /* FIXME These cases make different assumptions about audclk */ | ||
374 | case 32000: | ||
375 | /* src1_ctl */ | ||
376 | /* 0x1.0000 = 32000/32000 */ | ||
377 | cx25840_write4(client, 0x8f8, 0x08010000); | ||
183 | 378 | ||
184 | if (!state->is_cx23885 && !state->is_cx231xx) { | 379 | /* src3/4/6_ctl */ |
185 | /* src1_ctl */ | 380 | /* 0x2.0000 = 2 * (32000/32000) */ |
186 | cx25840_write4(client, 0x8f8, 0x08018000); | 381 | cx25840_write4(client, 0x900, 0x08020000); |
382 | cx25840_write4(client, 0x904, 0x08020000); | ||
383 | cx25840_write4(client, 0x90c, 0x08020000); | ||
384 | break; | ||
187 | 385 | ||
188 | /* src3/4/6_ctl */ | 386 | case 44100: |
189 | cx25840_write4(client, 0x900, 0x08015555); | 387 | /* src1_ctl */ |
190 | cx25840_write4(client, 0x904, 0x08015555); | 388 | /* 0x1.60cd = 44100/32000 */ |
191 | cx25840_write4(client, 0x90c, 0x08015555); | 389 | cx25840_write4(client, 0x8f8, 0x080160cd); |
192 | } else { | ||
193 | 390 | ||
194 | cx25840_write4(client, 0x8f8, 0x0801867c); | 391 | /* src3/4/6_ctl */ |
392 | /* 0x1.7385 = 2 * (32000/44100) */ | ||
393 | cx25840_write4(client, 0x900, 0x08017385); | ||
394 | cx25840_write4(client, 0x904, 0x08017385); | ||
395 | cx25840_write4(client, 0x90c, 0x08017385); | ||
396 | break; | ||
195 | 397 | ||
196 | cx25840_write4(client, 0x900, 0x08014faa); | 398 | case 48000: |
197 | cx25840_write4(client, 0x904, 0x08014faa); | 399 | /* src1_ctl */ |
198 | cx25840_write4(client, 0x90c, 0x08014faa); | 400 | /* 0x1.867c = 48000 / (2 * 28636360/8 * 2/455) */ |
199 | } | 401 | cx25840_write4(client, 0x8f8, 0x0801867c); |
402 | |||
403 | /* src3/4/6_ctl */ | ||
404 | /* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */ | ||
405 | cx25840_write4(client, 0x900, 0x08014faa); | ||
406 | cx25840_write4(client, 0x904, 0x08014faa); | ||
407 | cx25840_write4(client, 0x90c, 0x08014faa); | ||
200 | break; | 408 | break; |
201 | } | 409 | } |
202 | } | 410 | } |
@@ -206,6 +414,25 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) | |||
206 | return 0; | 414 | return 0; |
207 | } | 415 | } |
208 | 416 | ||
417 | static int set_audclk_freq(struct i2c_client *client, u32 freq) | ||
418 | { | ||
419 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); | ||
420 | |||
421 | if (freq != 32000 && freq != 44100 && freq != 48000) | ||
422 | return -EINVAL; | ||
423 | |||
424 | if (is_cx231xx(state)) | ||
425 | return cx231xx_set_audclk_freq(client, freq); | ||
426 | |||
427 | if (is_cx2388x(state)) | ||
428 | return cx23885_set_audclk_freq(client, freq); | ||
429 | |||
430 | if (is_cx2583x(state)) | ||
431 | return cx25836_set_audclk_freq(client, freq); | ||
432 | |||
433 | return cx25840_set_audclk_freq(client, freq); | ||
434 | } | ||
435 | |||
209 | void cx25840_audio_set_path(struct i2c_client *client) | 436 | void cx25840_audio_set_path(struct i2c_client *client) |
210 | { | 437 | { |
211 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); | 438 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
@@ -243,7 +470,7 @@ void cx25840_audio_set_path(struct i2c_client *client) | |||
243 | cx25840_and_or(client, 0x810, ~0x1, 0x00); | 470 | cx25840_and_or(client, 0x810, ~0x1, 0x00); |
244 | 471 | ||
245 | /* Ensure the controller is running when we exit */ | 472 | /* Ensure the controller is running when we exit */ |
246 | if (state->is_cx23885 || state->is_cx231xx) | 473 | if (is_cx2388x(state) || is_cx231xx(state)) |
247 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | 474 | cx25840_and_or(client, 0x803, ~0x10, 0x10); |
248 | } | 475 | } |
249 | 476 | ||
@@ -383,7 +610,7 @@ int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq) | |||
383 | struct cx25840_state *state = to_state(sd); | 610 | struct cx25840_state *state = to_state(sd); |
384 | int retval; | 611 | int retval; |
385 | 612 | ||
386 | if (!state->is_cx25836) | 613 | if (!is_cx2583x(state)) |
387 | cx25840_and_or(client, 0x810, ~0x1, 1); | 614 | cx25840_and_or(client, 0x810, ~0x1, 1); |
388 | if (state->aud_input != CX25840_AUDIO_SERIAL) { | 615 | if (state->aud_input != CX25840_AUDIO_SERIAL) { |
389 | cx25840_and_or(client, 0x803, ~0x10, 0); | 616 | cx25840_and_or(client, 0x803, ~0x10, 0); |
@@ -392,7 +619,7 @@ int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq) | |||
392 | retval = set_audclk_freq(client, freq); | 619 | retval = set_audclk_freq(client, freq); |
393 | if (state->aud_input != CX25840_AUDIO_SERIAL) | 620 | if (state->aud_input != CX25840_AUDIO_SERIAL) |
394 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | 621 | cx25840_and_or(client, 0x803, ~0x10, 0x10); |
395 | if (!state->is_cx25836) | 622 | if (!is_cx2583x(state)) |
396 | cx25840_and_or(client, 0x810, ~0x1, 0); | 623 | cx25840_and_or(client, 0x810, ~0x1, 0); |
397 | return retval; | 624 | return retval; |
398 | } | 625 | } |
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 1aeaf18a9bea..385ecd58f1c0 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c | |||
@@ -259,6 +259,13 @@ static void cx23885_initialize(struct i2c_client *client) | |||
259 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); | 259 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
260 | struct workqueue_struct *q; | 260 | struct workqueue_struct *q; |
261 | 261 | ||
262 | /* | ||
263 | * Come out of digital power down | ||
264 | * The CX23888, at least, needs this, otherwise registers aside from | ||
265 | * 0x0-0x2 can't be read or written. | ||
266 | */ | ||
267 | cx25840_write(client, 0x000, 0); | ||
268 | |||
262 | /* Internal Reset */ | 269 | /* Internal Reset */ |
263 | cx25840_and_or(client, 0x102, ~0x01, 0x01); | 270 | cx25840_and_or(client, 0x102, ~0x01, 0x01); |
264 | cx25840_and_or(client, 0x102, ~0x01, 0x00); | 271 | cx25840_and_or(client, 0x102, ~0x01, 0x00); |
@@ -269,18 +276,45 @@ static void cx23885_initialize(struct i2c_client *client) | |||
269 | /* DIF in reset? */ | 276 | /* DIF in reset? */ |
270 | cx25840_write(client, 0x398, 0); | 277 | cx25840_write(client, 0x398, 0); |
271 | 278 | ||
272 | /* Trust the default xtal, no division */ | 279 | /* |
273 | /* This changes for the cx23888 products */ | 280 | * Trust the default xtal, no division |
281 | * '885: 28.636363... MHz | ||
282 | * '887: 25.000000 MHz | ||
283 | * '888: 50.000000 MHz | ||
284 | */ | ||
274 | cx25840_write(client, 0x2, 0x76); | 285 | cx25840_write(client, 0x2, 0x76); |
275 | 286 | ||
276 | /* Bring down the regulator for AUX clk */ | 287 | /* Power up all the PLL's and DLL */ |
277 | cx25840_write(client, 0x1, 0x40); | 288 | cx25840_write(client, 0x1, 0x40); |
278 | 289 | ||
279 | /* Sys PLL frac */ | 290 | /* Sys PLL */ |
280 | cx25840_write4(client, 0x11c, 0x01d1744c); | 291 | switch (state->id) { |
281 | 292 | case V4L2_IDENT_CX23888_AV: | |
282 | /* Sys PLL int */ | 293 | /* |
283 | cx25840_write4(client, 0x118, 0x00000416); | 294 | * 50.0 MHz * (0xb + 0xe8ba26/0x2000000)/4 = 5 * 28.636363 MHz |
295 | * 572.73 MHz before post divide | ||
296 | */ | ||
297 | cx25840_write4(client, 0x11c, 0x00e8ba26); | ||
298 | cx25840_write4(client, 0x118, 0x0000040b); | ||
299 | break; | ||
300 | case V4L2_IDENT_CX23887_AV: | ||
301 | /* | ||
302 | * 25.0 MHz * (0x16 + 0x1d1744c/0x2000000)/4 = 5 * 28.636363 MHz | ||
303 | * 572.73 MHz before post divide | ||
304 | */ | ||
305 | cx25840_write4(client, 0x11c, 0x01d1744c); | ||
306 | cx25840_write4(client, 0x118, 0x00000416); | ||
307 | break; | ||
308 | case V4L2_IDENT_CX23885_AV: | ||
309 | default: | ||
310 | /* | ||
311 | * 28.636363 MHz * (0x14 + 0x0/0x2000000)/4 = 5 * 28.636363 MHz | ||
312 | * 572.73 MHz before post divide | ||
313 | */ | ||
314 | cx25840_write4(client, 0x11c, 0x00000000); | ||
315 | cx25840_write4(client, 0x118, 0x00000414); | ||
316 | break; | ||
317 | } | ||
284 | 318 | ||
285 | /* Disable DIF bypass */ | 319 | /* Disable DIF bypass */ |
286 | cx25840_write4(client, 0x33c, 0x00000001); | 320 | cx25840_write4(client, 0x33c, 0x00000001); |
@@ -288,11 +322,15 @@ static void cx23885_initialize(struct i2c_client *client) | |||
288 | /* DIF Src phase inc */ | 322 | /* DIF Src phase inc */ |
289 | cx25840_write4(client, 0x340, 0x0df7df83); | 323 | cx25840_write4(client, 0x340, 0x0df7df83); |
290 | 324 | ||
291 | /* Vid PLL frac */ | 325 | /* |
292 | cx25840_write4(client, 0x10c, 0x01b6db7b); | 326 | * Vid PLL |
293 | 327 | * Setup for a BT.656 pixel clock of 13.5 Mpixels/second | |
294 | /* Vid PLL int */ | 328 | * |
295 | cx25840_write4(client, 0x108, 0x00000512); | 329 | * 28.636363 MHz * (0xf + 0x02be2c9/0x2000000)/4 = 8 * 13.5 MHz |
330 | * 432.0 MHz before post divide | ||
331 | */ | ||
332 | cx25840_write4(client, 0x10c, 0x002be2c9); | ||
333 | cx25840_write4(client, 0x108, 0x0000040f); | ||
296 | 334 | ||
297 | /* Luma */ | 335 | /* Luma */ |
298 | cx25840_write4(client, 0x414, 0x00107d12); | 336 | cx25840_write4(client, 0x414, 0x00107d12); |
@@ -300,11 +338,43 @@ static void cx23885_initialize(struct i2c_client *client) | |||
300 | /* Chroma */ | 338 | /* Chroma */ |
301 | cx25840_write4(client, 0x420, 0x3d008282); | 339 | cx25840_write4(client, 0x420, 0x3d008282); |
302 | 340 | ||
303 | /* Aux PLL frac */ | 341 | /* |
304 | cx25840_write4(client, 0x114, 0x017dbf48); | 342 | * Aux PLL |
305 | 343 | * Initial setup for audio sample clock: | |
306 | /* Aux PLL int */ | 344 | * 48 ksps, 16 bits/sample, x160 multiplier = 122.88 MHz |
307 | cx25840_write4(client, 0x110, 0x000a030e); | 345 | * Intial I2S output/master clock(?): |
346 | * 48 ksps, 16 bits/sample, x16 multiplier = 12.288 MHz | ||
347 | */ | ||
348 | switch (state->id) { | ||
349 | case V4L2_IDENT_CX23888_AV: | ||
350 | /* | ||
351 | * 50.0 MHz * (0x7 + 0x0bedfa4/0x2000000)/3 = 122.88 MHz | ||
352 | * 368.64 MHz before post divide | ||
353 | * 122.88 MHz / 0xa = 12.288 MHz | ||
354 | */ | ||
355 | cx25840_write4(client, 0x114, 0x00bedfa4); | ||
356 | cx25840_write4(client, 0x110, 0x000a0307); | ||
357 | break; | ||
358 | case V4L2_IDENT_CX23887_AV: | ||
359 | /* | ||
360 | * 25.0 MHz * (0xe + 0x17dbf48/0x2000000)/3 = 122.88 MHz | ||
361 | * 368.64 MHz before post divide | ||
362 | * 122.88 MHz / 0xa = 12.288 MHz | ||
363 | */ | ||
364 | cx25840_write4(client, 0x114, 0x017dbf48); | ||
365 | cx25840_write4(client, 0x110, 0x000a030e); | ||
366 | break; | ||
367 | case V4L2_IDENT_CX23885_AV: | ||
368 | default: | ||
369 | /* | ||
370 | * 28.636363 MHz * (0xc + 0x1bf0c9e/0x2000000)/3 = 122.88 MHz | ||
371 | * 368.64 MHz before post divide | ||
372 | * 122.88 MHz / 0xa = 12.288 MHz | ||
373 | */ | ||
374 | cx25840_write4(client, 0x114, 0x01bf0c9e); | ||
375 | cx25840_write4(client, 0x110, 0x000a030c); | ||
376 | break; | ||
377 | }; | ||
308 | 378 | ||
309 | /* ADC2 input select */ | 379 | /* ADC2 input select */ |
310 | cx25840_write(client, 0x102, 0x10); | 380 | cx25840_write(client, 0x102, 0x10); |
@@ -494,7 +564,7 @@ void cx25840_std_setup(struct i2c_client *client) | |||
494 | } | 564 | } |
495 | 565 | ||
496 | /* DEBUG: Displays configured PLL frequency */ | 566 | /* DEBUG: Displays configured PLL frequency */ |
497 | if (!state->is_cx231xx) { | 567 | if (!is_cx231xx(state)) { |
498 | pll_int = cx25840_read(client, 0x108); | 568 | pll_int = cx25840_read(client, 0x108); |
499 | pll_frac = cx25840_read4(client, 0x10c) & 0x1ffffff; | 569 | pll_frac = cx25840_read4(client, 0x10c) & 0x1ffffff; |
500 | pll_post = cx25840_read(client, 0x109); | 570 | pll_post = cx25840_read(client, 0x109); |
@@ -615,13 +685,30 @@ static void input_change(struct i2c_client *client) | |||
615 | } | 685 | } |
616 | cx25840_write(client, 0x80b, 0x00); | 686 | cx25840_write(client, 0x80b, 0x00); |
617 | } else if (std & V4L2_STD_PAL) { | 687 | } else if (std & V4L2_STD_PAL) { |
618 | /* Follow tuner change procedure for PAL */ | 688 | /* Autodetect audio standard and audio system */ |
619 | cx25840_write(client, 0x808, 0xff); | 689 | cx25840_write(client, 0x808, 0xff); |
620 | cx25840_write(client, 0x80b, 0x10); | 690 | /* Since system PAL-L is pretty much non-existant and |
691 | not used by any public broadcast network, force | ||
692 | 6.5 MHz carrier to be interpreted as System DK, | ||
693 | this avoids DK audio detection instability */ | ||
694 | cx25840_write(client, 0x80b, 0x00); | ||
621 | } else if (std & V4L2_STD_SECAM) { | 695 | } else if (std & V4L2_STD_SECAM) { |
622 | /* Select autodetect for SECAM */ | 696 | /* Autodetect audio standard and audio system */ |
623 | cx25840_write(client, 0x808, 0xff); | 697 | cx25840_write(client, 0x808, 0xff); |
624 | cx25840_write(client, 0x80b, 0x10); | 698 | /* If only one of SECAM-DK / SECAM-L is required, then force |
699 | 6.5MHz carrier, else autodetect it */ | ||
700 | if ((std & V4L2_STD_SECAM_DK) && | ||
701 | !(std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC))) { | ||
702 | /* 6.5 MHz carrier to be interpreted as System DK */ | ||
703 | cx25840_write(client, 0x80b, 0x00); | ||
704 | } else if (!(std & V4L2_STD_SECAM_DK) && | ||
705 | (std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC))) { | ||
706 | /* 6.5 MHz carrier to be interpreted as System L */ | ||
707 | cx25840_write(client, 0x80b, 0x08); | ||
708 | } else { | ||
709 | /* 6.5 MHz carrier to be autodetected */ | ||
710 | cx25840_write(client, 0x80b, 0x10); | ||
711 | } | ||
625 | } | 712 | } |
626 | 713 | ||
627 | cx25840_and_or(client, 0x810, ~0x01, 0); | 714 | cx25840_and_or(client, 0x810, ~0x01, 0); |
@@ -633,6 +720,10 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp | |||
633 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); | 720 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
634 | u8 is_composite = (vid_input >= CX25840_COMPOSITE1 && | 721 | u8 is_composite = (vid_input >= CX25840_COMPOSITE1 && |
635 | vid_input <= CX25840_COMPOSITE8); | 722 | vid_input <= CX25840_COMPOSITE8); |
723 | u8 is_component = (vid_input & CX25840_COMPONENT_ON) == | ||
724 | CX25840_COMPONENT_ON; | ||
725 | int luma = vid_input & 0xf0; | ||
726 | int chroma = vid_input & 0xf00; | ||
636 | u8 reg; | 727 | u8 reg; |
637 | 728 | ||
638 | v4l_dbg(1, cx25840_debug, client, | 729 | v4l_dbg(1, cx25840_debug, client, |
@@ -645,18 +736,14 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp | |||
645 | reg = vid_input & 0xff; | 736 | reg = vid_input & 0xff; |
646 | if ((vid_input & CX25840_SVIDEO_ON) == CX25840_SVIDEO_ON) | 737 | if ((vid_input & CX25840_SVIDEO_ON) == CX25840_SVIDEO_ON) |
647 | is_composite = 0; | 738 | is_composite = 0; |
648 | else | 739 | else if ((vid_input & CX25840_COMPONENT_ON) == 0) |
649 | is_composite = 1; | 740 | is_composite = 1; |
650 | 741 | ||
651 | v4l_dbg(1, cx25840_debug, client, "mux cfg 0x%x comp=%d\n", | 742 | v4l_dbg(1, cx25840_debug, client, "mux cfg 0x%x comp=%d\n", |
652 | reg, is_composite); | 743 | reg, is_composite); |
653 | } else | 744 | } else if (is_composite) { |
654 | if (is_composite) { | ||
655 | reg = 0xf0 + (vid_input - CX25840_COMPOSITE1); | 745 | reg = 0xf0 + (vid_input - CX25840_COMPOSITE1); |
656 | } else { | 746 | } else { |
657 | int luma = vid_input & 0xf0; | ||
658 | int chroma = vid_input & 0xf00; | ||
659 | |||
660 | if ((vid_input & ~0xff0) || | 747 | if ((vid_input & ~0xff0) || |
661 | luma < CX25840_SVIDEO_LUMA1 || luma > CX25840_SVIDEO_LUMA8 || | 748 | luma < CX25840_SVIDEO_LUMA1 || luma > CX25840_SVIDEO_LUMA8 || |
662 | chroma < CX25840_SVIDEO_CHROMA4 || chroma > CX25840_SVIDEO_CHROMA8) { | 749 | chroma < CX25840_SVIDEO_CHROMA4 || chroma > CX25840_SVIDEO_CHROMA8) { |
@@ -678,7 +765,7 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp | |||
678 | * configuration in reg (for the cx23885) so we have no | 765 | * configuration in reg (for the cx23885) so we have no |
679 | * need to attempt to flip bits for earlier av decoders. | 766 | * need to attempt to flip bits for earlier av decoders. |
680 | */ | 767 | */ |
681 | if (!state->is_cx23885 && !state->is_cx231xx) { | 768 | if (!is_cx2388x(state) && !is_cx231xx(state)) { |
682 | switch (aud_input) { | 769 | switch (aud_input) { |
683 | case CX25840_AUDIO_SERIAL: | 770 | case CX25840_AUDIO_SERIAL: |
684 | /* do nothing, use serial audio input */ | 771 | /* do nothing, use serial audio input */ |
@@ -698,10 +785,13 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp | |||
698 | 785 | ||
699 | cx25840_write(client, 0x103, reg); | 786 | cx25840_write(client, 0x103, reg); |
700 | 787 | ||
701 | /* Set INPUT_MODE to Composite (0) or S-Video (1) */ | 788 | /* Set INPUT_MODE to Composite, S-Video or Component */ |
702 | cx25840_and_or(client, 0x401, ~0x6, is_composite ? 0 : 0x02); | 789 | if (is_component) |
790 | cx25840_and_or(client, 0x401, ~0x6, 0x6); | ||
791 | else | ||
792 | cx25840_and_or(client, 0x401, ~0x6, is_composite ? 0 : 0x02); | ||
703 | 793 | ||
704 | if (!state->is_cx23885 && !state->is_cx231xx) { | 794 | if (!is_cx2388x(state) && !is_cx231xx(state)) { |
705 | /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ | 795 | /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ |
706 | cx25840_and_or(client, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0); | 796 | cx25840_and_or(client, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0); |
707 | /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2&CH3 */ | 797 | /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2&CH3 */ |
@@ -710,22 +800,31 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp | |||
710 | else | 800 | else |
711 | cx25840_and_or(client, 0x102, ~0x4, 0); | 801 | cx25840_and_or(client, 0x102, ~0x4, 0); |
712 | } else { | 802 | } else { |
713 | if (is_composite) | 803 | /* Set DUAL_MODE_ADC2 to 1 if component*/ |
804 | cx25840_and_or(client, 0x102, ~0x4, is_component ? 0x4 : 0x0); | ||
805 | if (is_composite) { | ||
714 | /* ADC2 input select channel 2 */ | 806 | /* ADC2 input select channel 2 */ |
715 | cx25840_and_or(client, 0x102, ~0x2, 0); | 807 | cx25840_and_or(client, 0x102, ~0x2, 0); |
716 | else | 808 | } else if (!is_component) { |
717 | /* ADC2 input select channel 3 */ | 809 | /* S-Video */ |
718 | cx25840_and_or(client, 0x102, ~0x2, 2); | 810 | if (chroma >= CX25840_SVIDEO_CHROMA7) { |
811 | /* ADC2 input select channel 3 */ | ||
812 | cx25840_and_or(client, 0x102, ~0x2, 2); | ||
813 | } else { | ||
814 | /* ADC2 input select channel 2 */ | ||
815 | cx25840_and_or(client, 0x102, ~0x2, 0); | ||
816 | } | ||
817 | } | ||
719 | } | 818 | } |
720 | 819 | ||
721 | state->vid_input = vid_input; | 820 | state->vid_input = vid_input; |
722 | state->aud_input = aud_input; | 821 | state->aud_input = aud_input; |
723 | if (!state->is_cx25836) { | 822 | if (!is_cx2583x(state)) { |
724 | cx25840_audio_set_path(client); | 823 | cx25840_audio_set_path(client); |
725 | input_change(client); | 824 | input_change(client); |
726 | } | 825 | } |
727 | 826 | ||
728 | if (state->is_cx23885) { | 827 | if (is_cx2388x(state)) { |
729 | /* Audio channel 1 src : Parallel 1 */ | 828 | /* Audio channel 1 src : Parallel 1 */ |
730 | cx25840_write(client, 0x124, 0x03); | 829 | cx25840_write(client, 0x124, 0x03); |
731 | 830 | ||
@@ -741,7 +840,7 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp | |||
741 | */ | 840 | */ |
742 | cx25840_write(client, 0x918, 0xa0); | 841 | cx25840_write(client, 0x918, 0xa0); |
743 | cx25840_write(client, 0x919, 0x01); | 842 | cx25840_write(client, 0x919, 0x01); |
744 | } else if (state->is_cx231xx) { | 843 | } else if (is_cx231xx(state)) { |
745 | /* Audio channel 1 src : Parallel 1 */ | 844 | /* Audio channel 1 src : Parallel 1 */ |
746 | cx25840_write(client, 0x124, 0x03); | 845 | cx25840_write(client, 0x124, 0x03); |
747 | 846 | ||
@@ -805,7 +904,7 @@ static int set_v4lstd(struct i2c_client *client) | |||
805 | cx25840_and_or(client, 0x400, ~0xf, fmt); | 904 | cx25840_and_or(client, 0x400, ~0xf, fmt); |
806 | cx25840_and_or(client, 0x403, ~0x3, pal_m); | 905 | cx25840_and_or(client, 0x403, ~0x3, pal_m); |
807 | cx25840_std_setup(client); | 906 | cx25840_std_setup(client); |
808 | if (!state->is_cx25836) | 907 | if (!is_cx2583x(state)) |
809 | input_change(client); | 908 | input_change(client); |
810 | return 0; | 909 | return 0; |
811 | } | 910 | } |
@@ -868,7 +967,7 @@ static int cx25840_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
868 | case V4L2_CID_AUDIO_TREBLE: | 967 | case V4L2_CID_AUDIO_TREBLE: |
869 | case V4L2_CID_AUDIO_BALANCE: | 968 | case V4L2_CID_AUDIO_BALANCE: |
870 | case V4L2_CID_AUDIO_MUTE: | 969 | case V4L2_CID_AUDIO_MUTE: |
871 | if (state->is_cx25836) | 970 | if (is_cx2583x(state)) |
872 | return -EINVAL; | 971 | return -EINVAL; |
873 | return cx25840_audio_s_ctrl(sd, ctrl); | 972 | return cx25840_audio_s_ctrl(sd, ctrl); |
874 | 973 | ||
@@ -905,7 +1004,7 @@ static int cx25840_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
905 | case V4L2_CID_AUDIO_TREBLE: | 1004 | case V4L2_CID_AUDIO_TREBLE: |
906 | case V4L2_CID_AUDIO_BALANCE: | 1005 | case V4L2_CID_AUDIO_BALANCE: |
907 | case V4L2_CID_AUDIO_MUTE: | 1006 | case V4L2_CID_AUDIO_MUTE: |
908 | if (state->is_cx25836) | 1007 | if (is_cx2583x(state)) |
909 | return -EINVAL; | 1008 | return -EINVAL; |
910 | return cx25840_audio_g_ctrl(sd, ctrl); | 1009 | return cx25840_audio_g_ctrl(sd, ctrl); |
911 | default: | 1010 | default: |
@@ -1209,11 +1308,11 @@ static int cx25840_load_fw(struct v4l2_subdev *sd) | |||
1209 | if (!state->is_initialized) { | 1308 | if (!state->is_initialized) { |
1210 | /* initialize and load firmware */ | 1309 | /* initialize and load firmware */ |
1211 | state->is_initialized = 1; | 1310 | state->is_initialized = 1; |
1212 | if (state->is_cx25836) | 1311 | if (is_cx2583x(state)) |
1213 | cx25836_initialize(client); | 1312 | cx25836_initialize(client); |
1214 | else if (state->is_cx23885) | 1313 | else if (is_cx2388x(state)) |
1215 | cx23885_initialize(client); | 1314 | cx23885_initialize(client); |
1216 | else if (state->is_cx231xx) | 1315 | else if (is_cx231xx(state)) |
1217 | cx231xx_initialize(client); | 1316 | cx231xx_initialize(client); |
1218 | else | 1317 | else |
1219 | cx25840_initialize(client); | 1318 | cx25840_initialize(client); |
@@ -1256,17 +1355,17 @@ static int cx25840_s_stream(struct v4l2_subdev *sd, int enable) | |||
1256 | v4l_dbg(1, cx25840_debug, client, "%s output\n", | 1355 | v4l_dbg(1, cx25840_debug, client, "%s output\n", |
1257 | enable ? "enable" : "disable"); | 1356 | enable ? "enable" : "disable"); |
1258 | if (enable) { | 1357 | if (enable) { |
1259 | if (state->is_cx23885 || state->is_cx231xx) { | 1358 | if (is_cx2388x(state) || is_cx231xx(state)) { |
1260 | u8 v = (cx25840_read(client, 0x421) | 0x0b); | 1359 | u8 v = (cx25840_read(client, 0x421) | 0x0b); |
1261 | cx25840_write(client, 0x421, v); | 1360 | cx25840_write(client, 0x421, v); |
1262 | } else { | 1361 | } else { |
1263 | cx25840_write(client, 0x115, | 1362 | cx25840_write(client, 0x115, |
1264 | state->is_cx25836 ? 0x0c : 0x8c); | 1363 | is_cx2583x(state) ? 0x0c : 0x8c); |
1265 | cx25840_write(client, 0x116, | 1364 | cx25840_write(client, 0x116, |
1266 | state->is_cx25836 ? 0x04 : 0x07); | 1365 | is_cx2583x(state) ? 0x04 : 0x07); |
1267 | } | 1366 | } |
1268 | } else { | 1367 | } else { |
1269 | if (state->is_cx23885 || state->is_cx231xx) { | 1368 | if (is_cx2388x(state) || is_cx231xx(state)) { |
1270 | u8 v = cx25840_read(client, 0x421) & ~(0x0b); | 1369 | u8 v = cx25840_read(client, 0x421) & ~(0x0b); |
1271 | cx25840_write(client, 0x421, v); | 1370 | cx25840_write(client, 0x421, v); |
1272 | } else { | 1371 | } else { |
@@ -1292,7 +1391,7 @@ static int cx25840_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) | |||
1292 | default: | 1391 | default: |
1293 | break; | 1392 | break; |
1294 | } | 1393 | } |
1295 | if (state->is_cx25836) | 1394 | if (is_cx2583x(state)) |
1296 | return -EINVAL; | 1395 | return -EINVAL; |
1297 | 1396 | ||
1298 | switch (qc->id) { | 1397 | switch (qc->id) { |
@@ -1346,7 +1445,7 @@ static int cx25840_s_audio_routing(struct v4l2_subdev *sd, | |||
1346 | struct cx25840_state *state = to_state(sd); | 1445 | struct cx25840_state *state = to_state(sd); |
1347 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 1446 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1348 | 1447 | ||
1349 | if (state->is_cx25836) | 1448 | if (is_cx2583x(state)) |
1350 | return -EINVAL; | 1449 | return -EINVAL; |
1351 | return set_input(client, state->vid_input, input); | 1450 | return set_input(client, state->vid_input, input); |
1352 | } | 1451 | } |
@@ -1356,7 +1455,7 @@ static int cx25840_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *fr | |||
1356 | struct cx25840_state *state = to_state(sd); | 1455 | struct cx25840_state *state = to_state(sd); |
1357 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 1456 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1358 | 1457 | ||
1359 | if (!state->is_cx25836) | 1458 | if (!is_cx2583x(state)) |
1360 | input_change(client); | 1459 | input_change(client); |
1361 | return 0; | 1460 | return 0; |
1362 | } | 1461 | } |
@@ -1373,7 +1472,7 @@ static int cx25840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) | |||
1373 | return 0; | 1472 | return 0; |
1374 | 1473 | ||
1375 | vt->signal = vpres ? 0xffff : 0x0; | 1474 | vt->signal = vpres ? 0xffff : 0x0; |
1376 | if (state->is_cx25836) | 1475 | if (is_cx2583x(state)) |
1377 | return 0; | 1476 | return 0; |
1378 | 1477 | ||
1379 | vt->capability |= | 1478 | vt->capability |= |
@@ -1404,7 +1503,7 @@ static int cx25840_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) | |||
1404 | struct cx25840_state *state = to_state(sd); | 1503 | struct cx25840_state *state = to_state(sd); |
1405 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 1504 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1406 | 1505 | ||
1407 | if (state->radio || state->is_cx25836) | 1506 | if (state->radio || is_cx2583x(state)) |
1408 | return 0; | 1507 | return 0; |
1409 | 1508 | ||
1410 | switch (vt->audmode) { | 1509 | switch (vt->audmode) { |
@@ -1445,11 +1544,11 @@ static int cx25840_reset(struct v4l2_subdev *sd, u32 val) | |||
1445 | struct cx25840_state *state = to_state(sd); | 1544 | struct cx25840_state *state = to_state(sd); |
1446 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 1545 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1447 | 1546 | ||
1448 | if (state->is_cx25836) | 1547 | if (is_cx2583x(state)) |
1449 | cx25836_initialize(client); | 1548 | cx25836_initialize(client); |
1450 | else if (state->is_cx23885) | 1549 | else if (is_cx2388x(state)) |
1451 | cx23885_initialize(client); | 1550 | cx23885_initialize(client); |
1452 | else if (state->is_cx231xx) | 1551 | else if (is_cx231xx(state)) |
1453 | cx231xx_initialize(client); | 1552 | cx231xx_initialize(client); |
1454 | else | 1553 | else |
1455 | cx25840_initialize(client); | 1554 | cx25840_initialize(client); |
@@ -1470,7 +1569,7 @@ static int cx25840_log_status(struct v4l2_subdev *sd) | |||
1470 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 1569 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1471 | 1570 | ||
1472 | log_video_status(client); | 1571 | log_video_status(client); |
1473 | if (!state->is_cx25836) | 1572 | if (!is_cx2583x(state)) |
1474 | log_audio_status(client); | 1573 | log_audio_status(client); |
1475 | return 0; | 1574 | return 0; |
1476 | } | 1575 | } |
@@ -1521,12 +1620,50 @@ static const struct v4l2_subdev_ops cx25840_ops = { | |||
1521 | 1620 | ||
1522 | /* ----------------------------------------------------------------------- */ | 1621 | /* ----------------------------------------------------------------------- */ |
1523 | 1622 | ||
1623 | static u32 get_cx2388x_ident(struct i2c_client *client) | ||
1624 | { | ||
1625 | u32 ret; | ||
1626 | |||
1627 | /* Come out of digital power down */ | ||
1628 | cx25840_write(client, 0x000, 0); | ||
1629 | |||
1630 | /* Detecting whether the part is cx23885/7/8 is more | ||
1631 | * difficult than it needs to be. No ID register. Instead we | ||
1632 | * probe certain registers indicated in the datasheets to look | ||
1633 | * for specific defaults that differ between the silicon designs. */ | ||
1634 | |||
1635 | /* It's either 885/7 if the IR Tx Clk Divider register exists */ | ||
1636 | if (cx25840_read4(client, 0x204) & 0xffff) { | ||
1637 | /* CX23885 returns bogus repetitive byte values for the DIF, | ||
1638 | * which doesn't exist for it. (Ex. 8a8a8a8a or 31313131) */ | ||
1639 | ret = cx25840_read4(client, 0x300); | ||
1640 | if (((ret & 0xffff0000) >> 16) == (ret & 0xffff)) { | ||
1641 | /* No DIF */ | ||
1642 | ret = V4L2_IDENT_CX23885_AV; | ||
1643 | } else { | ||
1644 | /* CX23887 has a broken DIF, but the registers | ||
1645 | * appear valid (but unsed), good enough to detect. */ | ||
1646 | ret = V4L2_IDENT_CX23887_AV; | ||
1647 | } | ||
1648 | } else if (cx25840_read4(client, 0x300) & 0x0fffffff) { | ||
1649 | /* DIF PLL Freq Word reg exists; chip must be a CX23888 */ | ||
1650 | ret = V4L2_IDENT_CX23888_AV; | ||
1651 | } else { | ||
1652 | v4l_err(client, "Unable to detect h/w, assuming cx23887\n"); | ||
1653 | ret = V4L2_IDENT_CX23887_AV; | ||
1654 | } | ||
1655 | |||
1656 | /* Back into digital power down */ | ||
1657 | cx25840_write(client, 0x000, 2); | ||
1658 | return ret; | ||
1659 | } | ||
1660 | |||
1524 | static int cx25840_probe(struct i2c_client *client, | 1661 | static int cx25840_probe(struct i2c_client *client, |
1525 | const struct i2c_device_id *did) | 1662 | const struct i2c_device_id *did) |
1526 | { | 1663 | { |
1527 | struct cx25840_state *state; | 1664 | struct cx25840_state *state; |
1528 | struct v4l2_subdev *sd; | 1665 | struct v4l2_subdev *sd; |
1529 | u32 id; | 1666 | u32 id = V4L2_IDENT_NONE; |
1530 | u16 device_id; | 1667 | u16 device_id; |
1531 | 1668 | ||
1532 | /* Check if the adapter supports the needed features */ | 1669 | /* Check if the adapter supports the needed features */ |
@@ -1543,17 +1680,22 @@ static int cx25840_probe(struct i2c_client *client, | |||
1543 | * 0x83 for the cx2583x and 0x84 for the cx2584x */ | 1680 | * 0x83 for the cx2583x and 0x84 for the cx2584x */ |
1544 | if ((device_id & 0xff00) == 0x8300) { | 1681 | if ((device_id & 0xff00) == 0x8300) { |
1545 | id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; | 1682 | id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; |
1546 | } | 1683 | } else if ((device_id & 0xff00) == 0x8400) { |
1547 | else if ((device_id & 0xff00) == 0x8400) { | ||
1548 | id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf); | 1684 | id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf); |
1549 | } else if (device_id == 0x0000) { | 1685 | } else if (device_id == 0x0000) { |
1550 | id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; | 1686 | id = get_cx2388x_ident(client); |
1551 | } else if (device_id == 0x1313) { | ||
1552 | id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; | ||
1553 | } else if ((device_id & 0xfff0) == 0x5A30) { | 1687 | } else if ((device_id & 0xfff0) == 0x5A30) { |
1554 | id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf); | 1688 | /* The CX23100 (0x5A3C = 23100) doesn't have an A/V decoder */ |
1555 | } | 1689 | id = V4L2_IDENT_CX2310X_AV; |
1556 | else { | 1690 | } else if ((device_id & 0xff) == (device_id >> 8)) { |
1691 | v4l_err(client, | ||
1692 | "likely a confused/unresponsive cx2388[578] A/V decoder" | ||
1693 | " found @ 0x%x (%s)\n", | ||
1694 | client->addr << 1, client->adapter->name); | ||
1695 | v4l_err(client, "A method to reset it from the cx25840 driver" | ||
1696 | " software is not known at this time\n"); | ||
1697 | return -ENODEV; | ||
1698 | } else { | ||
1557 | v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n"); | 1699 | v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n"); |
1558 | return -ENODEV; | 1700 | return -ENODEV; |
1559 | } | 1701 | } |
@@ -1564,17 +1706,45 @@ static int cx25840_probe(struct i2c_client *client, | |||
1564 | 1706 | ||
1565 | sd = &state->sd; | 1707 | sd = &state->sd; |
1566 | v4l2_i2c_subdev_init(sd, client, &cx25840_ops); | 1708 | v4l2_i2c_subdev_init(sd, client, &cx25840_ops); |
1567 | /* Note: revision '(device_id & 0x0f) == 2' was never built. The | 1709 | switch (id) { |
1568 | marking skips from 0x1 == 22 to 0x3 == 23. */ | 1710 | case V4L2_IDENT_CX23885_AV: |
1569 | v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n", | 1711 | v4l_info(client, "cx23885 A/V decoder found @ 0x%x (%s)\n", |
1570 | (device_id & 0xfff0) >> 4, | 1712 | client->addr << 1, client->adapter->name); |
1571 | (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : (device_id & 0x0f), | 1713 | break; |
1572 | client->addr << 1, client->adapter->name); | 1714 | case V4L2_IDENT_CX23887_AV: |
1715 | v4l_info(client, "cx23887 A/V decoder found @ 0x%x (%s)\n", | ||
1716 | client->addr << 1, client->adapter->name); | ||
1717 | break; | ||
1718 | case V4L2_IDENT_CX23888_AV: | ||
1719 | v4l_info(client, "cx23888 A/V decoder found @ 0x%x (%s)\n", | ||
1720 | client->addr << 1, client->adapter->name); | ||
1721 | break; | ||
1722 | case V4L2_IDENT_CX2310X_AV: | ||
1723 | v4l_info(client, "cx%d A/V decoder found @ 0x%x (%s)\n", | ||
1724 | device_id, client->addr << 1, client->adapter->name); | ||
1725 | break; | ||
1726 | case V4L2_IDENT_CX25840: | ||
1727 | case V4L2_IDENT_CX25841: | ||
1728 | case V4L2_IDENT_CX25842: | ||
1729 | case V4L2_IDENT_CX25843: | ||
1730 | /* Note: revision '(device_id & 0x0f) == 2' was never built. The | ||
1731 | marking skips from 0x1 == 22 to 0x3 == 23. */ | ||
1732 | v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n", | ||
1733 | (device_id & 0xfff0) >> 4, | ||
1734 | (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 | ||
1735 | : (device_id & 0x0f), | ||
1736 | client->addr << 1, client->adapter->name); | ||
1737 | break; | ||
1738 | case V4L2_IDENT_CX25836: | ||
1739 | case V4L2_IDENT_CX25837: | ||
1740 | default: | ||
1741 | v4l_info(client, "cx25%3x-%x found @ 0x%x (%s)\n", | ||
1742 | (device_id & 0xfff0) >> 4, device_id & 0x0f, | ||
1743 | client->addr << 1, client->adapter->name); | ||
1744 | break; | ||
1745 | } | ||
1573 | 1746 | ||
1574 | state->c = client; | 1747 | state->c = client; |
1575 | state->is_cx25836 = ((device_id & 0xff00) == 0x8300); | ||
1576 | state->is_cx23885 = (device_id == 0x0000) || (device_id == 0x1313); | ||
1577 | state->is_cx231xx = (device_id == 0x5a3e); | ||
1578 | state->vid_input = CX25840_COMPOSITE7; | 1748 | state->vid_input = CX25840_COMPOSITE7; |
1579 | state->aud_input = CX25840_AUDIO8; | 1749 | state->aud_input = CX25840_AUDIO8; |
1580 | state->audclk_freq = 48000; | 1750 | state->audclk_freq = 48000; |
diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h index 814b56536994..55345444417f 100644 --- a/drivers/media/video/cx25840/cx25840-core.h +++ b/drivers/media/video/cx25840/cx25840-core.h | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | #include <linux/videodev2.h> | 24 | #include <linux/videodev2.h> |
25 | #include <media/v4l2-device.h> | 25 | #include <media/v4l2-device.h> |
26 | #include <media/v4l2-chip-ident.h> | ||
26 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
27 | 28 | ||
28 | /* ENABLE_PVR150_WORKAROUND activates a workaround for a hardware bug that is | 29 | /* ENABLE_PVR150_WORKAROUND activates a workaround for a hardware bug that is |
@@ -48,9 +49,6 @@ struct cx25840_state { | |||
48 | int vbi_line_offset; | 49 | int vbi_line_offset; |
49 | u32 id; | 50 | u32 id; |
50 | u32 rev; | 51 | u32 rev; |
51 | int is_cx25836; | ||
52 | int is_cx23885; | ||
53 | int is_cx231xx; | ||
54 | int is_initialized; | 52 | int is_initialized; |
55 | wait_queue_head_t fw_wait; /* wake up when the fw load is finished */ | 53 | wait_queue_head_t fw_wait; /* wake up when the fw load is finished */ |
56 | struct work_struct fw_work; /* work entry for fw load */ | 54 | struct work_struct fw_work; /* work entry for fw load */ |
@@ -61,6 +59,24 @@ static inline struct cx25840_state *to_state(struct v4l2_subdev *sd) | |||
61 | return container_of(sd, struct cx25840_state, sd); | 59 | return container_of(sd, struct cx25840_state, sd); |
62 | } | 60 | } |
63 | 61 | ||
62 | static inline bool is_cx2583x(struct cx25840_state *state) | ||
63 | { | ||
64 | return state->id == V4L2_IDENT_CX25836 || | ||
65 | state->id == V4L2_IDENT_CX25837; | ||
66 | } | ||
67 | |||
68 | static inline bool is_cx231xx(struct cx25840_state *state) | ||
69 | { | ||
70 | return state->id == V4L2_IDENT_CX2310X_AV; | ||
71 | } | ||
72 | |||
73 | static inline bool is_cx2388x(struct cx25840_state *state) | ||
74 | { | ||
75 | return state->id == V4L2_IDENT_CX23885_AV || | ||
76 | state->id == V4L2_IDENT_CX23887_AV || | ||
77 | state->id == V4L2_IDENT_CX23888_AV; | ||
78 | } | ||
79 | |||
64 | /* ----------------------------------------------------------------------- */ | 80 | /* ----------------------------------------------------------------------- */ |
65 | /* cx25850-core.c */ | 81 | /* cx25850-core.c */ |
66 | int cx25840_write(struct i2c_client *client, u16 addr, u8 value); | 82 | int cx25840_write(struct i2c_client *client, u16 addr, u8 value); |
diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c index 1f483c1d0dbe..8150200511da 100644 --- a/drivers/media/video/cx25840/cx25840-firmware.c +++ b/drivers/media/video/cx25840/cx25840-firmware.c | |||
@@ -67,9 +67,9 @@ static const char *get_fw_name(struct i2c_client *client) | |||
67 | 67 | ||
68 | if (firmware[0]) | 68 | if (firmware[0]) |
69 | return firmware; | 69 | return firmware; |
70 | if (state->is_cx23885) | 70 | if (is_cx2388x(state)) |
71 | return "v4l-cx23885-avcore-01.fw"; | 71 | return "v4l-cx23885-avcore-01.fw"; |
72 | if (state->is_cx231xx) | 72 | if (is_cx231xx(state)) |
73 | return "v4l-cx231xx-avcore-01.fw"; | 73 | return "v4l-cx231xx-avcore-01.fw"; |
74 | return "v4l-cx25840.fw"; | 74 | return "v4l-cx25840.fw"; |
75 | } | 75 | } |
@@ -112,13 +112,13 @@ int cx25840_loadfw(struct i2c_client *client) | |||
112 | int MAX_BUF_SIZE = FWSEND; | 112 | int MAX_BUF_SIZE = FWSEND; |
113 | u32 gpio_oe = 0, gpio_da = 0; | 113 | u32 gpio_oe = 0, gpio_da = 0; |
114 | 114 | ||
115 | if (state->is_cx23885) { | 115 | if (is_cx2388x(state)) { |
116 | /* Preserve the GPIO OE and output bits */ | 116 | /* Preserve the GPIO OE and output bits */ |
117 | gpio_oe = cx25840_read(client, 0x160); | 117 | gpio_oe = cx25840_read(client, 0x160); |
118 | gpio_da = cx25840_read(client, 0x164); | 118 | gpio_da = cx25840_read(client, 0x164); |
119 | } | 119 | } |
120 | 120 | ||
121 | if ((state->is_cx231xx) && MAX_BUF_SIZE > 16) { | 121 | if (is_cx231xx(state) && MAX_BUF_SIZE > 16) { |
122 | v4l_err(client, " Firmware download size changed to 16 bytes max length\n"); | 122 | v4l_err(client, " Firmware download size changed to 16 bytes max length\n"); |
123 | MAX_BUF_SIZE = 16; /* cx231xx cannot accept more than 16 bytes at a time */ | 123 | MAX_BUF_SIZE = 16; /* cx231xx cannot accept more than 16 bytes at a time */ |
124 | } | 124 | } |
@@ -156,7 +156,7 @@ int cx25840_loadfw(struct i2c_client *client) | |||
156 | size = fw->size; | 156 | size = fw->size; |
157 | release_firmware(fw); | 157 | release_firmware(fw); |
158 | 158 | ||
159 | if (state->is_cx23885) { | 159 | if (is_cx2388x(state)) { |
160 | /* Restore GPIO configuration after f/w load */ | 160 | /* Restore GPIO configuration after f/w load */ |
161 | cx25840_write(client, 0x160, gpio_oe); | 161 | cx25840_write(client, 0x160, gpio_oe); |
162 | cx25840_write(client, 0x164, gpio_da); | 162 | cx25840_write(client, 0x164, gpio_da); |
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 49952980dab3..c7e5851d3486 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig | |||
@@ -61,6 +61,8 @@ config VIDEO_CX88_DVB | |||
61 | select DVB_STV0299 if !DVB_FE_CUSTOMISE | 61 | select DVB_STV0299 if !DVB_FE_CUSTOMISE |
62 | select DVB_STV0288 if !DVB_FE_CUSTOMISE | 62 | select DVB_STV0288 if !DVB_FE_CUSTOMISE |
63 | select DVB_STB6000 if !DVB_FE_CUSTOMISE | 63 | select DVB_STB6000 if !DVB_FE_CUSTOMISE |
64 | select DVB_STV0900 if !DVB_FE_CUSTOMISE | ||
65 | select DVB_STB6100 if !DVB_FE_CUSTOMISE | ||
64 | select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE | 66 | select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE |
65 | ---help--- | 67 | ---help--- |
66 | This adds support for DVB/ATSC cards based on the | 68 | This adds support for DVB/ATSC cards based on the |
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 33be6369871a..d844f2aaa01d 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
@@ -2075,6 +2075,18 @@ static const struct cx88_board cx88_boards[] = { | |||
2075 | }, | 2075 | }, |
2076 | .mpeg = CX88_MPEG_DVB, | 2076 | .mpeg = CX88_MPEG_DVB, |
2077 | }, | 2077 | }, |
2078 | [CX88_BOARD_PROF_7301] = { | ||
2079 | .name = "Prof 7301 DVB-S/S2", | ||
2080 | .tuner_type = UNSET, | ||
2081 | .radio_type = UNSET, | ||
2082 | .tuner_addr = ADDR_UNSET, | ||
2083 | .radio_addr = ADDR_UNSET, | ||
2084 | .input = { { | ||
2085 | .type = CX88_VMUX_DVB, | ||
2086 | .vmux = 0, | ||
2087 | } }, | ||
2088 | .mpeg = CX88_MPEG_DVB, | ||
2089 | }, | ||
2078 | }; | 2090 | }; |
2079 | 2091 | ||
2080 | /* ------------------------------------------------------------------ */ | 2092 | /* ------------------------------------------------------------------ */ |
@@ -2535,6 +2547,10 @@ static const struct cx88_subid cx88_subids[] = { | |||
2535 | .subvendor = 0x107d, | 2547 | .subvendor = 0x107d, |
2536 | .subdevice = 0x6618, | 2548 | .subdevice = 0x6618, |
2537 | .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL, | 2549 | .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL, |
2550 | }, { | ||
2551 | .subvendor = 0xb034, | ||
2552 | .subdevice = 0x3034, | ||
2553 | .card = CX88_BOARD_PROF_7301, | ||
2538 | }, | 2554 | }, |
2539 | }; | 2555 | }; |
2540 | 2556 | ||
@@ -3211,6 +3227,7 @@ static void cx88_card_setup(struct cx88_core *core) | |||
3211 | case CX88_BOARD_TBS_8920: | 3227 | case CX88_BOARD_TBS_8920: |
3212 | case CX88_BOARD_PROF_6200: | 3228 | case CX88_BOARD_PROF_6200: |
3213 | case CX88_BOARD_PROF_7300: | 3229 | case CX88_BOARD_PROF_7300: |
3230 | case CX88_BOARD_PROF_7301: | ||
3214 | case CX88_BOARD_SATTRADE_ST4200: | 3231 | case CX88_BOARD_SATTRADE_ST4200: |
3215 | cx_write(MO_GP0_IO, 0x8000); | 3232 | cx_write(MO_GP0_IO, 0x8000); |
3216 | msleep(100); | 3233 | msleep(100); |
@@ -3267,7 +3284,7 @@ static void cx88_card_setup(struct cx88_core *core) | |||
3267 | ctl.fname); | 3284 | ctl.fname); |
3268 | call_all(core, tuner, s_config, &xc2028_cfg); | 3285 | call_all(core, tuner, s_config, &xc2028_cfg); |
3269 | } | 3286 | } |
3270 | call_all(core, tuner, s_standby); | 3287 | call_all(core, core, s_power, 0); |
3271 | } | 3288 | } |
3272 | 3289 | ||
3273 | /* ------------------------------------------------------------------ */ | 3290 | /* ------------------------------------------------------------------ */ |
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 518bcfe18bcb..b14296923250 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -53,6 +53,9 @@ | |||
53 | #include "stv0288.h" | 53 | #include "stv0288.h" |
54 | #include "stb6000.h" | 54 | #include "stb6000.h" |
55 | #include "cx24116.h" | 55 | #include "cx24116.h" |
56 | #include "stv0900.h" | ||
57 | #include "stb6100.h" | ||
58 | #include "stb6100_proc.h" | ||
56 | 59 | ||
57 | MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); | 60 | MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); |
58 | MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); | 61 | MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); |
@@ -573,6 +576,15 @@ static int cx24116_set_ts_param(struct dvb_frontend *fe, | |||
573 | return 0; | 576 | return 0; |
574 | } | 577 | } |
575 | 578 | ||
579 | static int stv0900_set_ts_param(struct dvb_frontend *fe, | ||
580 | int is_punctured) | ||
581 | { | ||
582 | struct cx8802_dev *dev = fe->dvb->priv; | ||
583 | dev->ts_gen_cntrl = 0; | ||
584 | |||
585 | return 0; | ||
586 | } | ||
587 | |||
576 | static int cx24116_reset_device(struct dvb_frontend *fe) | 588 | static int cx24116_reset_device(struct dvb_frontend *fe) |
577 | { | 589 | { |
578 | struct cx8802_dev *dev = fe->dvb->priv; | 590 | struct cx8802_dev *dev = fe->dvb->priv; |
@@ -601,6 +613,23 @@ static struct cx24116_config tevii_s460_config = { | |||
601 | .reset_device = cx24116_reset_device, | 613 | .reset_device = cx24116_reset_device, |
602 | }; | 614 | }; |
603 | 615 | ||
616 | static struct stv0900_config prof_7301_stv0900_config = { | ||
617 | .demod_address = 0x6a, | ||
618 | /* demod_mode = 0,*/ | ||
619 | .xtal = 27000000, | ||
620 | .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ | ||
621 | .diseqc_mode = 2,/* 2/3 PWM */ | ||
622 | .tun1_maddress = 0,/* 0x60 */ | ||
623 | .tun1_adc = 0,/* 2 Vpp */ | ||
624 | .path1_mode = 3, | ||
625 | .set_ts_params = stv0900_set_ts_param, | ||
626 | }; | ||
627 | |||
628 | static struct stb6100_config prof_7301_stb6100_config = { | ||
629 | .tuner_address = 0x60, | ||
630 | .refclock = 27000000, | ||
631 | }; | ||
632 | |||
604 | static struct stv0299_config tevii_tuner_sharp_config = { | 633 | static struct stv0299_config tevii_tuner_sharp_config = { |
605 | .demod_address = 0x68, | 634 | .demod_address = 0x68, |
606 | .inittab = sharp_z0194a_inittab, | 635 | .inittab = sharp_z0194a_inittab, |
@@ -1149,6 +1178,31 @@ static int dvb_register(struct cx8802_dev *dev) | |||
1149 | goto frontend_detach; | 1178 | goto frontend_detach; |
1150 | } | 1179 | } |
1151 | break; | 1180 | break; |
1181 | case CX88_BOARD_PROF_7301:{ | ||
1182 | struct dvb_tuner_ops *tuner_ops = NULL; | ||
1183 | |||
1184 | fe0->dvb.frontend = dvb_attach(stv0900_attach, | ||
1185 | &prof_7301_stv0900_config, | ||
1186 | &core->i2c_adap, 0); | ||
1187 | if (fe0->dvb.frontend != NULL) { | ||
1188 | if (!dvb_attach(stb6100_attach, fe0->dvb.frontend, | ||
1189 | &prof_7301_stb6100_config, | ||
1190 | &core->i2c_adap)) | ||
1191 | goto frontend_detach; | ||
1192 | |||
1193 | tuner_ops = &fe0->dvb.frontend->ops.tuner_ops; | ||
1194 | tuner_ops->set_frequency = stb6100_set_freq; | ||
1195 | tuner_ops->get_frequency = stb6100_get_freq; | ||
1196 | tuner_ops->set_bandwidth = stb6100_set_bandw; | ||
1197 | tuner_ops->get_bandwidth = stb6100_get_bandw; | ||
1198 | |||
1199 | core->prev_set_voltage = | ||
1200 | fe0->dvb.frontend->ops.set_voltage; | ||
1201 | fe0->dvb.frontend->ops.set_voltage = | ||
1202 | tevii_dvbs_set_voltage; | ||
1203 | } | ||
1204 | break; | ||
1205 | } | ||
1152 | default: | 1206 | default: |
1153 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", | 1207 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", |
1154 | core->name); | 1208 | core->name); |
@@ -1170,11 +1224,11 @@ static int dvb_register(struct cx8802_dev *dev) | |||
1170 | fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; | 1224 | fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; |
1171 | 1225 | ||
1172 | /* Put the analog decoder in standby to keep it quiet */ | 1226 | /* Put the analog decoder in standby to keep it quiet */ |
1173 | call_all(core, tuner, s_standby); | 1227 | call_all(core, core, s_power, 0); |
1174 | 1228 | ||
1175 | /* register everything */ | 1229 | /* register everything */ |
1176 | return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, | 1230 | return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, |
1177 | &dev->pci->dev, adapter_nr, mfe_shared); | 1231 | &dev->pci->dev, adapter_nr, mfe_shared, NULL); |
1178 | 1232 | ||
1179 | frontend_detach: | 1233 | frontend_detach: |
1180 | core->gate_ctrl = NULL; | 1234 | core->gate_ctrl = NULL; |
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 78b3635178af..92b8cdf9fb81 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c | |||
@@ -118,13 +118,13 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) | |||
118 | 118 | ||
119 | data = (data << 4) | ((gpio_key & 0xf0) >> 4); | 119 | data = (data << 4) | ((gpio_key & 0xf0) >> 4); |
120 | 120 | ||
121 | ir_input_keydown(ir->input, &ir->ir, data, data); | 121 | ir_input_keydown(ir->input, &ir->ir, data); |
122 | ir_input_nokey(ir->input, &ir->ir); | 122 | ir_input_nokey(ir->input, &ir->ir); |
123 | 123 | ||
124 | } else if (ir->mask_keydown) { | 124 | } else if (ir->mask_keydown) { |
125 | /* bit set on keydown */ | 125 | /* bit set on keydown */ |
126 | if (gpio & ir->mask_keydown) { | 126 | if (gpio & ir->mask_keydown) { |
127 | ir_input_keydown(ir->input, &ir->ir, data, data); | 127 | ir_input_keydown(ir->input, &ir->ir, data); |
128 | } else { | 128 | } else { |
129 | ir_input_nokey(ir->input, &ir->ir); | 129 | ir_input_nokey(ir->input, &ir->ir); |
130 | } | 130 | } |
@@ -132,14 +132,14 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) | |||
132 | } else if (ir->mask_keyup) { | 132 | } else if (ir->mask_keyup) { |
133 | /* bit cleared on keydown */ | 133 | /* bit cleared on keydown */ |
134 | if (0 == (gpio & ir->mask_keyup)) { | 134 | if (0 == (gpio & ir->mask_keyup)) { |
135 | ir_input_keydown(ir->input, &ir->ir, data, data); | 135 | ir_input_keydown(ir->input, &ir->ir, data); |
136 | } else { | 136 | } else { |
137 | ir_input_nokey(ir->input, &ir->ir); | 137 | ir_input_nokey(ir->input, &ir->ir); |
138 | } | 138 | } |
139 | 139 | ||
140 | } else { | 140 | } else { |
141 | /* can't distinguish keydown/up :-/ */ | 141 | /* can't distinguish keydown/up :-/ */ |
142 | ir_input_keydown(ir->input, &ir->ir, data, data); | 142 | ir_input_keydown(ir->input, &ir->ir, data); |
143 | ir_input_nokey(ir->input, &ir->ir); | 143 | ir_input_nokey(ir->input, &ir->ir); |
144 | } | 144 | } |
145 | } | 145 | } |
@@ -303,6 +303,23 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
303 | ir->mask_keydown = 0x02; | 303 | ir->mask_keydown = 0x02; |
304 | ir->polling = 50; /* ms */ | 304 | ir->polling = 50; /* ms */ |
305 | break; | 305 | break; |
306 | case CX88_BOARD_OMICOM_SS4_PCI: | ||
307 | case CX88_BOARD_SATTRADE_ST4200: | ||
308 | case CX88_BOARD_TBS_8920: | ||
309 | case CX88_BOARD_TBS_8910: | ||
310 | case CX88_BOARD_PROF_7300: | ||
311 | case CX88_BOARD_PROF_7301: | ||
312 | case CX88_BOARD_PROF_6200: | ||
313 | ir_codes = &ir_codes_tbs_nec_table; | ||
314 | ir_type = IR_TYPE_PD; | ||
315 | ir->sampling = 0xff00; /* address */ | ||
316 | break; | ||
317 | case CX88_BOARD_TEVII_S460: | ||
318 | case CX88_BOARD_TEVII_S420: | ||
319 | ir_codes = &ir_codes_tevii_nec_table; | ||
320 | ir_type = IR_TYPE_PD; | ||
321 | ir->sampling = 0xff00; /* address */ | ||
322 | break; | ||
306 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: | 323 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: |
307 | ir_codes = &ir_codes_dntv_live_dvbt_pro_table; | 324 | ir_codes = &ir_codes_dntv_live_dvbt_pro_table; |
308 | ir_type = IR_TYPE_PD; | 325 | ir_type = IR_TYPE_PD; |
@@ -343,7 +360,10 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
343 | snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name); | 360 | snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name); |
344 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci)); | 361 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci)); |
345 | 362 | ||
346 | ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); | 363 | err = ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); |
364 | if (err < 0) | ||
365 | goto err_out_free; | ||
366 | |||
347 | input_dev->name = ir->name; | 367 | input_dev->name = ir->name; |
348 | input_dev->phys = ir->phys; | 368 | input_dev->phys = ir->phys; |
349 | input_dev->id.bustype = BUS_PCI; | 369 | input_dev->id.bustype = BUS_PCI; |
@@ -373,6 +393,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
373 | cx88_ir_stop(core, ir); | 393 | cx88_ir_stop(core, ir); |
374 | core->ir = NULL; | 394 | core->ir = NULL; |
375 | err_out_free: | 395 | err_out_free: |
396 | ir_input_free(input_dev); | ||
376 | input_free_device(input_dev); | 397 | input_free_device(input_dev); |
377 | kfree(ir); | 398 | kfree(ir); |
378 | return err; | 399 | return err; |
@@ -387,6 +408,7 @@ int cx88_ir_fini(struct cx88_core *core) | |||
387 | return 0; | 408 | return 0; |
388 | 409 | ||
389 | cx88_ir_stop(core, ir); | 410 | cx88_ir_stop(core, ir); |
411 | ir_input_free(ir->input); | ||
390 | input_unregister_device(ir->input); | 412 | input_unregister_device(ir->input); |
391 | kfree(ir); | 413 | kfree(ir); |
392 | 414 | ||
@@ -432,8 +454,17 @@ void cx88_ir_irq(struct cx88_core *core) | |||
432 | 454 | ||
433 | /* decode it */ | 455 | /* decode it */ |
434 | switch (core->boardnr) { | 456 | switch (core->boardnr) { |
457 | case CX88_BOARD_TEVII_S460: | ||
458 | case CX88_BOARD_TEVII_S420: | ||
435 | case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: | 459 | case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: |
436 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: | 460 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: |
461 | case CX88_BOARD_OMICOM_SS4_PCI: | ||
462 | case CX88_BOARD_SATTRADE_ST4200: | ||
463 | case CX88_BOARD_TBS_8920: | ||
464 | case CX88_BOARD_TBS_8910: | ||
465 | case CX88_BOARD_PROF_7300: | ||
466 | case CX88_BOARD_PROF_7301: | ||
467 | case CX88_BOARD_PROF_6200: | ||
437 | ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4); | 468 | ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4); |
438 | 469 | ||
439 | if (ircode == 0xffffffff) { /* decoding error */ | 470 | if (ircode == 0xffffffff) { /* decoding error */ |
@@ -461,7 +492,7 @@ void cx88_ir_irq(struct cx88_core *core) | |||
461 | 492 | ||
462 | ir_dprintk("Key Code: %x\n", (ircode >> 16) & 0x7f); | 493 | ir_dprintk("Key Code: %x\n", (ircode >> 16) & 0x7f); |
463 | 494 | ||
464 | ir_input_keydown(ir->input, &ir->ir, (ircode >> 16) & 0x7f, (ircode >> 16) & 0xff); | 495 | ir_input_keydown(ir->input, &ir->ir, (ircode >> 16) & 0x7f); |
465 | ir->release = jiffies + msecs_to_jiffies(120); | 496 | ir->release = jiffies + msecs_to_jiffies(120); |
466 | break; | 497 | break; |
467 | case CX88_BOARD_HAUPPAUGE: | 498 | case CX88_BOARD_HAUPPAUGE: |
@@ -498,7 +529,7 @@ void cx88_ir_irq(struct cx88_core *core) | |||
498 | if ( dev != 0x1e && dev != 0x1f ) | 529 | if ( dev != 0x1e && dev != 0x1f ) |
499 | /* not a hauppauge remote */ | 530 | /* not a hauppauge remote */ |
500 | break; | 531 | break; |
501 | ir_input_keydown(ir->input, &ir->ir, code, ircode); | 532 | ir_input_keydown(ir->input, &ir->ir, code); |
502 | ir->release = jiffies + msecs_to_jiffies(120); | 533 | ir->release = jiffies + msecs_to_jiffies(120); |
503 | break; | 534 | break; |
504 | case CX88_BOARD_PINNACLE_PCTV_HD_800i: | 535 | case CX88_BOARD_PINNACLE_PCTV_HD_800i: |
@@ -506,7 +537,7 @@ void cx88_ir_irq(struct cx88_core *core) | |||
506 | ir_dprintk("biphase decoded: %x\n", ircode); | 537 | ir_dprintk("biphase decoded: %x\n", ircode); |
507 | if ((ircode & 0xfffff000) != 0x3000) | 538 | if ((ircode & 0xfffff000) != 0x3000) |
508 | break; | 539 | break; |
509 | ir_input_keydown(ir->input, &ir->ir, ircode & 0x3f, ircode); | 540 | ir_input_keydown(ir->input, &ir->ir, ircode & 0x3f); |
510 | ir->release = jiffies + msecs_to_jiffies(120); | 541 | ir->release = jiffies + msecs_to_jiffies(120); |
511 | break; | 542 | break; |
512 | } | 543 | } |
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 57e6b1241090..d7e8fcee559c 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c | |||
@@ -935,7 +935,7 @@ static int video_release(struct file *file) | |||
935 | 935 | ||
936 | mutex_lock(&dev->core->lock); | 936 | mutex_lock(&dev->core->lock); |
937 | if(atomic_dec_and_test(&dev->core->users)) | 937 | if(atomic_dec_and_test(&dev->core->users)) |
938 | call_all(dev->core, tuner, s_standby); | 938 | call_all(dev->core, core, s_power, 0); |
939 | mutex_unlock(&dev->core->lock); | 939 | mutex_unlock(&dev->core->lock); |
940 | 940 | ||
941 | return 0; | 941 | return 0; |
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index d5cea41f4207..e1c521710103 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
@@ -238,6 +238,7 @@ extern struct sram_channel cx88_sram_channels[]; | |||
238 | #define CX88_BOARD_HAUPPAUGE_IRONLY 80 | 238 | #define CX88_BOARD_HAUPPAUGE_IRONLY 80 |
239 | #define CX88_BOARD_WINFAST_DTV1800H 81 | 239 | #define CX88_BOARD_WINFAST_DTV1800H 81 |
240 | #define CX88_BOARD_WINFAST_DTV2000H_J 82 | 240 | #define CX88_BOARD_WINFAST_DTV2000H_J 82 |
241 | #define CX88_BOARD_PROF_7301 83 | ||
241 | 242 | ||
242 | enum cx88_itype { | 243 | enum cx88_itype { |
243 | CX88_VMUX_COMPOSITE1 = 1, | 244 | CX88_VMUX_COMPOSITE1 = 1, |
diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index 402ce43ef38e..12a1b3d7132d 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c | |||
@@ -660,7 +660,7 @@ static void vpfe_detach_irq(struct vpfe_device *vpfe_dev) | |||
660 | 660 | ||
661 | frame_format = ccdc_dev->hw_ops.get_frame_format(); | 661 | frame_format = ccdc_dev->hw_ops.get_frame_format(); |
662 | if (frame_format == CCDC_FRMFMT_PROGRESSIVE) | 662 | if (frame_format == CCDC_FRMFMT_PROGRESSIVE) |
663 | free_irq(IRQ_VDINT1, vpfe_dev); | 663 | free_irq(vpfe_dev->ccdc_irq1, vpfe_dev); |
664 | } | 664 | } |
665 | 665 | ||
666 | static int vpfe_attach_irq(struct vpfe_device *vpfe_dev) | 666 | static int vpfe_attach_irq(struct vpfe_device *vpfe_dev) |
@@ -1338,7 +1338,7 @@ static int vpfe_reqbufs(struct file *file, void *priv, | |||
1338 | vpfe_dev->memory = req_buf->memory; | 1338 | vpfe_dev->memory = req_buf->memory; |
1339 | videobuf_queue_dma_contig_init(&vpfe_dev->buffer_queue, | 1339 | videobuf_queue_dma_contig_init(&vpfe_dev->buffer_queue, |
1340 | &vpfe_videobuf_qops, | 1340 | &vpfe_videobuf_qops, |
1341 | NULL, | 1341 | vpfe_dev->pdev, |
1342 | &vpfe_dev->irqlock, | 1342 | &vpfe_dev->irqlock, |
1343 | req_buf->type, | 1343 | req_buf->type, |
1344 | vpfe_dev->fmt.fmt.pix.field, | 1344 | vpfe_dev->fmt.fmt.pix.field, |
@@ -1413,6 +1413,41 @@ static int vpfe_dqbuf(struct file *file, void *priv, | |||
1413 | buf, file->f_flags & O_NONBLOCK); | 1413 | buf, file->f_flags & O_NONBLOCK); |
1414 | } | 1414 | } |
1415 | 1415 | ||
1416 | static int vpfe_queryctrl(struct file *file, void *priv, | ||
1417 | struct v4l2_queryctrl *qctrl) | ||
1418 | { | ||
1419 | struct vpfe_device *vpfe_dev = video_drvdata(file); | ||
1420 | struct vpfe_subdev_info *sdinfo; | ||
1421 | |||
1422 | sdinfo = vpfe_dev->current_subdev; | ||
1423 | |||
1424 | return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, | ||
1425 | core, queryctrl, qctrl); | ||
1426 | |||
1427 | } | ||
1428 | |||
1429 | static int vpfe_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) | ||
1430 | { | ||
1431 | struct vpfe_device *vpfe_dev = video_drvdata(file); | ||
1432 | struct vpfe_subdev_info *sdinfo; | ||
1433 | |||
1434 | sdinfo = vpfe_dev->current_subdev; | ||
1435 | |||
1436 | return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, | ||
1437 | core, g_ctrl, ctrl); | ||
1438 | } | ||
1439 | |||
1440 | static int vpfe_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) | ||
1441 | { | ||
1442 | struct vpfe_device *vpfe_dev = video_drvdata(file); | ||
1443 | struct vpfe_subdev_info *sdinfo; | ||
1444 | |||
1445 | sdinfo = vpfe_dev->current_subdev; | ||
1446 | |||
1447 | return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, | ||
1448 | core, s_ctrl, ctrl); | ||
1449 | } | ||
1450 | |||
1416 | /* | 1451 | /* |
1417 | * vpfe_calculate_offsets : This function calculates buffers offset | 1452 | * vpfe_calculate_offsets : This function calculates buffers offset |
1418 | * for top and bottom field | 1453 | * for top and bottom field |
@@ -1577,7 +1612,7 @@ static int vpfe_cropcap(struct file *file, void *priv, | |||
1577 | 1612 | ||
1578 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_cropcap\n"); | 1613 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_cropcap\n"); |
1579 | 1614 | ||
1580 | if (vpfe_dev->std_index > ARRAY_SIZE(vpfe_standards)) | 1615 | if (vpfe_dev->std_index >= ARRAY_SIZE(vpfe_standards)) |
1581 | return -EINVAL; | 1616 | return -EINVAL; |
1582 | 1617 | ||
1583 | memset(crop, 0, sizeof(struct v4l2_cropcap)); | 1618 | memset(crop, 0, sizeof(struct v4l2_cropcap)); |
@@ -1710,6 +1745,9 @@ static const struct v4l2_ioctl_ops vpfe_ioctl_ops = { | |||
1710 | .vidioc_querystd = vpfe_querystd, | 1745 | .vidioc_querystd = vpfe_querystd, |
1711 | .vidioc_s_std = vpfe_s_std, | 1746 | .vidioc_s_std = vpfe_s_std, |
1712 | .vidioc_g_std = vpfe_g_std, | 1747 | .vidioc_g_std = vpfe_g_std, |
1748 | .vidioc_queryctrl = vpfe_queryctrl, | ||
1749 | .vidioc_g_ctrl = vpfe_g_ctrl, | ||
1750 | .vidioc_s_ctrl = vpfe_s_ctrl, | ||
1713 | .vidioc_reqbufs = vpfe_reqbufs, | 1751 | .vidioc_reqbufs = vpfe_reqbufs, |
1714 | .vidioc_querybuf = vpfe_querybuf, | 1752 | .vidioc_querybuf = vpfe_querybuf, |
1715 | .vidioc_qbuf = vpfe_qbuf, | 1753 | .vidioc_qbuf = vpfe_qbuf, |
@@ -1978,8 +2016,7 @@ static __init int vpfe_probe(struct platform_device *pdev) | |||
1978 | platform_set_drvdata(pdev, vpfe_dev); | 2016 | platform_set_drvdata(pdev, vpfe_dev); |
1979 | /* set driver private data */ | 2017 | /* set driver private data */ |
1980 | video_set_drvdata(vpfe_dev->video_dev, vpfe_dev); | 2018 | video_set_drvdata(vpfe_dev->video_dev, vpfe_dev); |
1981 | i2c_adap = i2c_get_adapter(1); | 2019 | i2c_adap = i2c_get_adapter(vpfe_cfg->i2c_adapter_id); |
1982 | vpfe_cfg = pdev->dev.platform_data; | ||
1983 | num_subdevs = vpfe_cfg->num_subdevs; | 2020 | num_subdevs = vpfe_cfg->num_subdevs; |
1984 | vpfe_dev->sd = kmalloc(sizeof(struct v4l2_subdev *) * num_subdevs, | 2021 | vpfe_dev->sd = kmalloc(sizeof(struct v4l2_subdev *) * num_subdevs, |
1985 | GFP_KERNEL); | 2022 | GFP_KERNEL); |
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index ac947aecb9c3..bd783387b37d 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c | |||
@@ -293,7 +293,7 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) | |||
293 | dprintk("opening device and trying to acquire exclusive lock\n"); | 293 | dprintk("opening device and trying to acquire exclusive lock\n"); |
294 | 294 | ||
295 | if (!dev) { | 295 | if (!dev) { |
296 | printk(KERN_ERR "BUG: em28xx can't find device struct." | 296 | em28xx_err("BUG: em28xx can't find device struct." |
297 | " Can't proceed with open\n"); | 297 | " Can't proceed with open\n"); |
298 | return -ENODEV; | 298 | return -ENODEV; |
299 | } | 299 | } |
@@ -325,7 +325,7 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) | |||
325 | 325 | ||
326 | return 0; | 326 | return 0; |
327 | err: | 327 | err: |
328 | printk(KERN_ERR "Error while configuring em28xx mixer\n"); | 328 | em28xx_err("Error while configuring em28xx mixer\n"); |
329 | return ret; | 329 | return ret; |
330 | } | 330 | } |
331 | 331 | ||
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index c0fd5c6feeac..82da205047be 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -225,6 +225,14 @@ static struct em28xx_reg_seq silvercrest_reg_seq[] = { | |||
225 | { -1, -1, -1, -1}, | 225 | { -1, -1, -1, -1}, |
226 | }; | 226 | }; |
227 | 227 | ||
228 | static struct em28xx_reg_seq vc211a_enable[] = { | ||
229 | {EM28XX_R08_GPIO, 0xff, 0x07, 10}, | ||
230 | {EM28XX_R08_GPIO, 0xff, 0x0f, 10}, | ||
231 | {EM28XX_R08_GPIO, 0xff, 0x0b, 10}, | ||
232 | { -1, -1, -1, -1}, | ||
233 | }; | ||
234 | |||
235 | |||
228 | /* | 236 | /* |
229 | * Board definitions | 237 | * Board definitions |
230 | */ | 238 | */ |
@@ -829,7 +837,7 @@ struct em28xx_board em28xx_boards[] = { | |||
829 | .mts_firmware = 1, | 837 | .mts_firmware = 1, |
830 | .has_dvb = 1, | 838 | .has_dvb = 1, |
831 | .dvb_gpio = hauppauge_wintv_hvr_900_digital, | 839 | .dvb_gpio = hauppauge_wintv_hvr_900_digital, |
832 | .ir_codes = &ir_codes_hauppauge_new_table, | 840 | .ir_codes = &ir_codes_rc5_hauppauge_new_table, |
833 | .decoder = EM28XX_TVP5150, | 841 | .decoder = EM28XX_TVP5150, |
834 | .input = { { | 842 | .input = { { |
835 | .type = EM28XX_VMUX_TELEVISION, | 843 | .type = EM28XX_VMUX_TELEVISION, |
@@ -1009,6 +1017,23 @@ struct em28xx_board em28xx_boards[] = { | |||
1009 | .amux = EM28XX_AMUX_LINE_IN, | 1017 | .amux = EM28XX_AMUX_LINE_IN, |
1010 | } }, | 1018 | } }, |
1011 | }, | 1019 | }, |
1020 | [EM2800_BOARD_VC211A] = { | ||
1021 | .name = "Actionmaster/LinXcel/Digitus VC211A", | ||
1022 | .is_em2800 = 1, | ||
1023 | .tuner_type = TUNER_ABSENT, /* Capture-only board */ | ||
1024 | .decoder = EM28XX_SAA711X, | ||
1025 | .input = { { | ||
1026 | .type = EM28XX_VMUX_COMPOSITE1, | ||
1027 | .vmux = SAA7115_COMPOSITE0, | ||
1028 | .amux = EM28XX_AMUX_LINE_IN, | ||
1029 | .gpio = vc211a_enable, | ||
1030 | }, { | ||
1031 | .type = EM28XX_VMUX_SVIDEO, | ||
1032 | .vmux = SAA7115_SVIDEO3, | ||
1033 | .amux = EM28XX_AMUX_LINE_IN, | ||
1034 | .gpio = vc211a_enable, | ||
1035 | } }, | ||
1036 | }, | ||
1012 | [EM2800_BOARD_LEADTEK_WINFAST_USBII] = { | 1037 | [EM2800_BOARD_LEADTEK_WINFAST_USBII] = { |
1013 | .name = "Leadtek Winfast USB II", | 1038 | .name = "Leadtek Winfast USB II", |
1014 | .is_em2800 = 1, | 1039 | .is_em2800 = 1, |
@@ -1381,10 +1406,14 @@ struct em28xx_board em28xx_boards[] = { | |||
1381 | }, | 1406 | }, |
1382 | [EM2882_BOARD_TERRATEC_HYBRID_XS] = { | 1407 | [EM2882_BOARD_TERRATEC_HYBRID_XS] = { |
1383 | .name = "Terratec Hybrid XS (em2882)", | 1408 | .name = "Terratec Hybrid XS (em2882)", |
1384 | .valid = EM28XX_BOARD_NOT_VALIDATED, | ||
1385 | .tuner_type = TUNER_XC2028, | 1409 | .tuner_type = TUNER_XC2028, |
1386 | .tuner_gpio = default_tuner_gpio, | 1410 | .tuner_gpio = default_tuner_gpio, |
1411 | .mts_firmware = 1, | ||
1387 | .decoder = EM28XX_TVP5150, | 1412 | .decoder = EM28XX_TVP5150, |
1413 | .has_dvb = 1, | ||
1414 | .dvb_gpio = hauppauge_wintv_hvr_900_digital, | ||
1415 | .ir_codes = &ir_codes_terratec_cinergy_xs_table, | ||
1416 | .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, | ||
1388 | .input = { { | 1417 | .input = { { |
1389 | .type = EM28XX_VMUX_TELEVISION, | 1418 | .type = EM28XX_VMUX_TELEVISION, |
1390 | .vmux = TVP5150_COMPOSITE0, | 1419 | .vmux = TVP5150_COMPOSITE0, |
@@ -1608,6 +1637,8 @@ struct usb_device_id em28xx_id_table[] = { | |||
1608 | .driver_info = EM2820_BOARD_UNKNOWN }, | 1637 | .driver_info = EM2820_BOARD_UNKNOWN }, |
1609 | { USB_DEVICE(0xeb1a, 0x2861), | 1638 | { USB_DEVICE(0xeb1a, 0x2861), |
1610 | .driver_info = EM2820_BOARD_UNKNOWN }, | 1639 | .driver_info = EM2820_BOARD_UNKNOWN }, |
1640 | { USB_DEVICE(0xeb1a, 0x2862), | ||
1641 | .driver_info = EM2820_BOARD_UNKNOWN }, | ||
1611 | { USB_DEVICE(0xeb1a, 0x2870), | 1642 | { USB_DEVICE(0xeb1a, 0x2870), |
1612 | .driver_info = EM2820_BOARD_UNKNOWN }, | 1643 | .driver_info = EM2820_BOARD_UNKNOWN }, |
1613 | { USB_DEVICE(0xeb1a, 0x2881), | 1644 | { USB_DEVICE(0xeb1a, 0x2881), |
@@ -2050,6 +2081,7 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) | |||
2050 | switch (dev->model) { | 2081 | switch (dev->model) { |
2051 | case EM2880_BOARD_EMPIRE_DUAL_TV: | 2082 | case EM2880_BOARD_EMPIRE_DUAL_TV: |
2052 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: | 2083 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: |
2084 | case EM2882_BOARD_TERRATEC_HYBRID_XS: | ||
2053 | ctl->demod = XC3028_FE_ZARLINK456; | 2085 | ctl->demod = XC3028_FE_ZARLINK456; |
2054 | break; | 2086 | break; |
2055 | case EM2880_BOARD_TERRATEC_HYBRID_XS: | 2087 | case EM2880_BOARD_TERRATEC_HYBRID_XS: |
@@ -2227,6 +2259,7 @@ static int em28xx_hint_board(struct em28xx *dev) | |||
2227 | /* ----------------------------------------------------------------------- */ | 2259 | /* ----------------------------------------------------------------------- */ |
2228 | void em28xx_register_i2c_ir(struct em28xx *dev) | 2260 | void em28xx_register_i2c_ir(struct em28xx *dev) |
2229 | { | 2261 | { |
2262 | struct i2c_board_info info; | ||
2230 | const unsigned short addr_list[] = { | 2263 | const unsigned short addr_list[] = { |
2231 | 0x30, 0x47, I2C_CLIENT_END | 2264 | 0x30, 0x47, I2C_CLIENT_END |
2232 | }; | 2265 | }; |
@@ -2234,9 +2267,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev) | |||
2234 | if (disable_ir) | 2267 | if (disable_ir) |
2235 | return; | 2268 | return; |
2236 | 2269 | ||
2237 | memset(&dev->info, 0, sizeof(&dev->info)); | 2270 | memset(&info, 0, sizeof(struct i2c_board_info)); |
2238 | memset(&dev->init_data, 0, sizeof(dev->init_data)); | 2271 | memset(&dev->init_data, 0, sizeof(dev->init_data)); |
2239 | strlcpy(dev->info.type, "ir_video", I2C_NAME_SIZE); | 2272 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); |
2240 | 2273 | ||
2241 | /* detect & configure */ | 2274 | /* detect & configure */ |
2242 | switch (dev->model) { | 2275 | switch (dev->model) { |
@@ -2259,8 +2292,8 @@ void em28xx_register_i2c_ir(struct em28xx *dev) | |||
2259 | } | 2292 | } |
2260 | 2293 | ||
2261 | if (dev->init_data.name) | 2294 | if (dev->init_data.name) |
2262 | dev->info.platform_data = &dev->init_data; | 2295 | info.platform_data = &dev->init_data; |
2263 | i2c_new_probed_device(&dev->i2c_adap, &dev->info, addr_list); | 2296 | i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); |
2264 | } | 2297 | } |
2265 | 2298 | ||
2266 | void em28xx_card_setup(struct em28xx *dev) | 2299 | void em28xx_card_setup(struct em28xx *dev) |
@@ -2524,6 +2557,9 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
2524 | dev->chip_id = retval; | 2557 | dev->chip_id = retval; |
2525 | 2558 | ||
2526 | switch (dev->chip_id) { | 2559 | switch (dev->chip_id) { |
2560 | case CHIP_ID_EM2800: | ||
2561 | em28xx_info("chip ID is em2800\n"); | ||
2562 | break; | ||
2527 | case CHIP_ID_EM2710: | 2563 | case CHIP_ID_EM2710: |
2528 | em28xx_info("chip ID is em2710\n"); | 2564 | em28xx_info("chip ID is em2710\n"); |
2529 | break; | 2565 | break; |
@@ -2650,7 +2686,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
2650 | em28xx_init_extension(dev); | 2686 | em28xx_init_extension(dev); |
2651 | 2687 | ||
2652 | /* Save some power by putting tuner to sleep */ | 2688 | /* Save some power by putting tuner to sleep */ |
2653 | v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_standby); | 2689 | v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); |
2654 | 2690 | ||
2655 | return 0; | 2691 | return 0; |
2656 | 2692 | ||
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index a88257a7d94f..3f86d36dff2b 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -50,7 +50,7 @@ MODULE_PARM_DESC(reg_debug, "enable debug messages [URB reg]"); | |||
50 | printk(KERN_INFO "%s %s :"fmt, \ | 50 | printk(KERN_INFO "%s %s :"fmt, \ |
51 | dev->name, __func__ , ##arg); } while (0) | 51 | dev->name, __func__ , ##arg); } while (0) |
52 | 52 | ||
53 | static int alt = EM28XX_PINOUT; | 53 | static int alt; |
54 | module_param(alt, int, 0644); | 54 | module_param(alt, int, 0644); |
55 | MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); | 55 | MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); |
56 | 56 | ||
@@ -533,8 +533,15 @@ int em28xx_audio_setup(struct em28xx *dev) | |||
533 | 533 | ||
534 | vid1 = em28xx_read_ac97(dev, AC97_VENDOR_ID1); | 534 | vid1 = em28xx_read_ac97(dev, AC97_VENDOR_ID1); |
535 | if (vid1 < 0) { | 535 | if (vid1 < 0) { |
536 | /* Device likely doesn't support AC97 */ | 536 | /* |
537 | * Device likely doesn't support AC97 | ||
538 | * Note: (some) em2800 devices without eeprom reports 0x91 on | ||
539 | * CHIPCFG register, even not having an AC97 chip | ||
540 | */ | ||
537 | em28xx_warn("AC97 chip type couldn't be determined\n"); | 541 | em28xx_warn("AC97 chip type couldn't be determined\n"); |
542 | dev->audio_mode.ac97 = EM28XX_NO_AC97; | ||
543 | dev->has_alsa_audio = 0; | ||
544 | dev->audio_mode.has_audio = 0; | ||
538 | goto init_audio; | 545 | goto init_audio; |
539 | } | 546 | } |
540 | 547 | ||
@@ -778,6 +785,16 @@ int em28xx_set_alternate(struct em28xx *dev) | |||
778 | int i; | 785 | int i; |
779 | unsigned int min_pkt_size = dev->width * 2 + 4; | 786 | unsigned int min_pkt_size = dev->width * 2 + 4; |
780 | 787 | ||
788 | /* | ||
789 | * alt = 0 is used only for control messages, so, only values | ||
790 | * greater than 0 can be used for streaming. | ||
791 | */ | ||
792 | if (alt && alt < dev->num_alt) { | ||
793 | em28xx_coredbg("alternate forced to %d\n", dev->alt); | ||
794 | dev->alt = alt; | ||
795 | goto set_alt; | ||
796 | } | ||
797 | |||
781 | /* When image size is bigger than a certain value, | 798 | /* When image size is bigger than a certain value, |
782 | the frame size should be increased, otherwise, only | 799 | the frame size should be increased, otherwise, only |
783 | green screen will be received. | 800 | green screen will be received. |
@@ -798,6 +815,7 @@ int em28xx_set_alternate(struct em28xx *dev) | |||
798 | dev->alt = i; | 815 | dev->alt = i; |
799 | } | 816 | } |
800 | 817 | ||
818 | set_alt: | ||
801 | if (dev->alt != prev_alt) { | 819 | if (dev->alt != prev_alt) { |
802 | em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n", | 820 | em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n", |
803 | min_pkt_size, dev->alt); | 821 | min_pkt_size, dev->alt); |
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index db749461e5c6..cc0505eb900f 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c | |||
@@ -313,22 +313,20 @@ static int attach_xc3028(u8 addr, struct em28xx *dev) | |||
313 | cfg.i2c_addr = addr; | 313 | cfg.i2c_addr = addr; |
314 | 314 | ||
315 | if (!dev->dvb->frontend) { | 315 | if (!dev->dvb->frontend) { |
316 | printk(KERN_ERR "%s/2: dvb frontend not attached. " | 316 | em28xx_errdev("/2: dvb frontend not attached. " |
317 | "Can't attach xc3028\n", | 317 | "Can't attach xc3028\n"); |
318 | dev->name); | ||
319 | return -EINVAL; | 318 | return -EINVAL; |
320 | } | 319 | } |
321 | 320 | ||
322 | fe = dvb_attach(xc2028_attach, dev->dvb->frontend, &cfg); | 321 | fe = dvb_attach(xc2028_attach, dev->dvb->frontend, &cfg); |
323 | if (!fe) { | 322 | if (!fe) { |
324 | printk(KERN_ERR "%s/2: xc3028 attach failed\n", | 323 | em28xx_errdev("/2: xc3028 attach failed\n"); |
325 | dev->name); | ||
326 | dvb_frontend_detach(dev->dvb->frontend); | 324 | dvb_frontend_detach(dev->dvb->frontend); |
327 | dev->dvb->frontend = NULL; | 325 | dev->dvb->frontend = NULL; |
328 | return -EINVAL; | 326 | return -EINVAL; |
329 | } | 327 | } |
330 | 328 | ||
331 | printk(KERN_INFO "%s/2: xc3028 attached\n", dev->name); | 329 | em28xx_info("%s/2: xc3028 attached\n", dev->name); |
332 | 330 | ||
333 | return 0; | 331 | return 0; |
334 | } | 332 | } |
@@ -463,7 +461,7 @@ static int dvb_init(struct em28xx *dev) | |||
463 | dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL); | 461 | dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL); |
464 | 462 | ||
465 | if (dvb == NULL) { | 463 | if (dvb == NULL) { |
466 | printk(KERN_INFO "em28xx_dvb: memory allocation failed\n"); | 464 | em28xx_info("em28xx_dvb: memory allocation failed\n"); |
467 | return -ENOMEM; | 465 | return -ENOMEM; |
468 | } | 466 | } |
469 | dev->dvb = dvb; | 467 | dev->dvb = dvb; |
@@ -493,6 +491,7 @@ static int dvb_init(struct em28xx *dev) | |||
493 | } | 491 | } |
494 | break; | 492 | break; |
495 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: | 493 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: |
494 | case EM2882_BOARD_TERRATEC_HYBRID_XS: | ||
496 | case EM2880_BOARD_EMPIRE_DUAL_TV: | 495 | case EM2880_BOARD_EMPIRE_DUAL_TV: |
497 | dvb->frontend = dvb_attach(zl10353_attach, | 496 | dvb->frontend = dvb_attach(zl10353_attach, |
498 | &em28xx_zl10353_xc3028_no_i2c_gate, | 497 | &em28xx_zl10353_xc3028_no_i2c_gate, |
@@ -569,15 +568,12 @@ static int dvb_init(struct em28xx *dev) | |||
569 | } | 568 | } |
570 | break; | 569 | break; |
571 | default: | 570 | default: |
572 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card" | 571 | em28xx_errdev("/2: The frontend of your DVB/ATSC card" |
573 | " isn't supported yet\n", | 572 | " isn't supported yet\n"); |
574 | dev->name); | ||
575 | break; | 573 | break; |
576 | } | 574 | } |
577 | if (NULL == dvb->frontend) { | 575 | if (NULL == dvb->frontend) { |
578 | printk(KERN_ERR | 576 | em28xx_errdev("/2: frontend initialization failed\n"); |
579 | "%s/2: frontend initialization failed\n", | ||
580 | dev->name); | ||
581 | result = -EINVAL; | 577 | result = -EINVAL; |
582 | goto out_free; | 578 | goto out_free; |
583 | } | 579 | } |
@@ -591,7 +587,7 @@ static int dvb_init(struct em28xx *dev) | |||
591 | goto out_free; | 587 | goto out_free; |
592 | 588 | ||
593 | em28xx_set_mode(dev, EM28XX_SUSPEND); | 589 | em28xx_set_mode(dev, EM28XX_SUSPEND); |
594 | printk(KERN_INFO "Successfully loaded em28xx-dvb\n"); | 590 | em28xx_info("Successfully loaded em28xx-dvb\n"); |
595 | return 0; | 591 | return 0; |
596 | 592 | ||
597 | out_free: | 593 | out_free: |
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 7a0fe3816e3d..d96ec7c09dca 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c | |||
@@ -70,6 +70,7 @@ struct em28xx_IR { | |||
70 | int polling; | 70 | int polling; |
71 | struct delayed_work work; | 71 | struct delayed_work work; |
72 | unsigned int last_toggle:1; | 72 | unsigned int last_toggle:1; |
73 | unsigned int full_code:1; | ||
73 | unsigned int last_readcount; | 74 | unsigned int last_readcount; |
74 | unsigned int repeat_interval; | 75 | unsigned int repeat_interval; |
75 | 76 | ||
@@ -246,9 +247,10 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir) | |||
246 | return; | 247 | return; |
247 | } | 248 | } |
248 | 249 | ||
249 | dprintk("ir->get_key result tb=%02x rc=%02x lr=%02x data=%02x\n", | 250 | dprintk("ir->get_key result tb=%02x rc=%02x lr=%02x data=%02x%02x\n", |
250 | poll_result.toggle_bit, poll_result.read_count, | 251 | poll_result.toggle_bit, poll_result.read_count, |
251 | ir->last_readcount, poll_result.rc_data[0]); | 252 | ir->last_readcount, poll_result.rc_address, |
253 | poll_result.rc_data[0]); | ||
252 | 254 | ||
253 | if (ir->dev->chip_id == CHIP_ID_EM2874) { | 255 | if (ir->dev->chip_id == CHIP_ID_EM2874) { |
254 | /* The em2874 clears the readcount field every time the | 256 | /* The em2874 clears the readcount field every time the |
@@ -282,8 +284,15 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir) | |||
282 | 284 | ||
283 | if (do_sendkey) { | 285 | if (do_sendkey) { |
284 | dprintk("sending keypress\n"); | 286 | dprintk("sending keypress\n"); |
285 | ir_input_keydown(ir->input, &ir->ir, poll_result.rc_data[0], | 287 | |
286 | poll_result.rc_data[0]); | 288 | if (ir->full_code) |
289 | ir_input_keydown(ir->input, &ir->ir, | ||
290 | poll_result.rc_address << 8 | | ||
291 | poll_result.rc_data[0]); | ||
292 | else | ||
293 | ir_input_keydown(ir->input, &ir->ir, | ||
294 | poll_result.rc_data[0]); | ||
295 | |||
287 | ir_input_nokey(ir->input, &ir->ir); | 296 | ir_input_nokey(ir->input, &ir->ir); |
288 | } | 297 | } |
289 | 298 | ||
@@ -333,6 +342,8 @@ int em28xx_ir_init(struct em28xx *dev) | |||
333 | switch (dev->chip_id) { | 342 | switch (dev->chip_id) { |
334 | case CHIP_ID_EM2860: | 343 | case CHIP_ID_EM2860: |
335 | case CHIP_ID_EM2883: | 344 | case CHIP_ID_EM2883: |
345 | if (dev->model == EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950) | ||
346 | ir->full_code = 1; | ||
336 | ir->get_key = default_polling_getkey; | 347 | ir->get_key = default_polling_getkey; |
337 | break; | 348 | break; |
338 | case CHIP_ID_EM2874: | 349 | case CHIP_ID_EM2874: |
@@ -356,7 +367,11 @@ int em28xx_ir_init(struct em28xx *dev) | |||
356 | usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); | 367 | usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); |
357 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); | 368 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); |
358 | 369 | ||
359 | ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER, dev->board.ir_codes); | 370 | err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER, |
371 | dev->board.ir_codes); | ||
372 | if (err < 0) | ||
373 | goto err_out_free; | ||
374 | |||
360 | input_dev->name = ir->name; | 375 | input_dev->name = ir->name; |
361 | input_dev->phys = ir->phys; | 376 | input_dev->phys = ir->phys; |
362 | input_dev->id.bustype = BUS_USB; | 377 | input_dev->id.bustype = BUS_USB; |
@@ -381,6 +396,7 @@ int em28xx_ir_init(struct em28xx *dev) | |||
381 | em28xx_ir_stop(ir); | 396 | em28xx_ir_stop(ir); |
382 | dev->ir = NULL; | 397 | dev->ir = NULL; |
383 | err_out_free: | 398 | err_out_free: |
399 | ir_input_free(input_dev); | ||
384 | input_free_device(input_dev); | 400 | input_free_device(input_dev); |
385 | kfree(ir); | 401 | kfree(ir); |
386 | return err; | 402 | return err; |
@@ -395,6 +411,7 @@ int em28xx_ir_fini(struct em28xx *dev) | |||
395 | return 0; | 411 | return 0; |
396 | 412 | ||
397 | em28xx_ir_stop(ir); | 413 | em28xx_ir_stop(ir); |
414 | ir_input_free(ir->input); | ||
398 | input_unregister_device(ir->input); | 415 | input_unregister_device(ir->input); |
399 | kfree(ir); | 416 | kfree(ir); |
400 | 417 | ||
diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h index ed12e7ffcbd0..058ac87639ce 100644 --- a/drivers/media/video/em28xx/em28xx-reg.h +++ b/drivers/media/video/em28xx/em28xx-reg.h | |||
@@ -192,6 +192,7 @@ | |||
192 | 192 | ||
193 | /* FIXME: Need to be populated with the other chip ID's */ | 193 | /* FIXME: Need to be populated with the other chip ID's */ |
194 | enum em28xx_chip_id { | 194 | enum em28xx_chip_id { |
195 | CHIP_ID_EM2800 = 7, | ||
195 | CHIP_ID_EM2710 = 17, | 196 | CHIP_ID_EM2710 = 17, |
196 | CHIP_ID_EM2820 = 18, /* Also used by some em2710 */ | 197 | CHIP_ID_EM2820 = 18, /* Also used by some em2710 */ |
197 | CHIP_ID_EM2840 = 20, | 198 | CHIP_ID_EM2840 = 20, |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 3a1dfb7726f8..7ad65370f274 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -1060,12 +1060,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
1060 | /* the em2800 can only scale down to 50% */ | 1060 | /* the em2800 can only scale down to 50% */ |
1061 | height = height > (3 * maxh / 4) ? maxh : maxh / 2; | 1061 | height = height > (3 * maxh / 4) ? maxh : maxh / 2; |
1062 | width = width > (3 * maxw / 4) ? maxw : maxw / 2; | 1062 | width = width > (3 * maxw / 4) ? maxw : maxw / 2; |
1063 | /* According to empiatech support the MaxPacketSize is too small | ||
1064 | * to support framesizes larger than 640x480 @ 30 fps or 640x576 | ||
1065 | * @ 25 fps. As this would cut of a part of the image we prefer | ||
1066 | * 360x576 or 360x480 for now */ | ||
1067 | if (width == maxw && height == maxh) | ||
1068 | width /= 2; | ||
1069 | } else { | 1063 | } else { |
1070 | /* width must even because of the YUYV format | 1064 | /* width must even because of the YUYV format |
1071 | height must be even because of interlacing */ | 1065 | height must be even because of interlacing */ |
@@ -2225,7 +2219,7 @@ static int em28xx_v4l2_close(struct file *filp) | |||
2225 | } | 2219 | } |
2226 | 2220 | ||
2227 | /* Save some power by putting tuner to sleep */ | 2221 | /* Save some power by putting tuner to sleep */ |
2228 | v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_standby); | 2222 | v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); |
2229 | 2223 | ||
2230 | /* do this before setting alternate! */ | 2224 | /* do this before setting alternate! */ |
2231 | em28xx_uninit_isoc(dev); | 2225 | em28xx_uninit_isoc(dev); |
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 0a73e8bf0d6e..441df644ddbe 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -110,6 +110,7 @@ | |||
110 | #define EM2820_BOARD_SILVERCREST_WEBCAM 71 | 110 | #define EM2820_BOARD_SILVERCREST_WEBCAM 71 |
111 | #define EM2861_BOARD_GADMEI_UTV330PLUS 72 | 111 | #define EM2861_BOARD_GADMEI_UTV330PLUS 72 |
112 | #define EM2870_BOARD_REDDO_DVB_C_USB_BOX 73 | 112 | #define EM2870_BOARD_REDDO_DVB_C_USB_BOX 73 |
113 | #define EM2800_BOARD_VC211A 74 | ||
113 | 114 | ||
114 | /* Limits minimum and default number of buffers */ | 115 | /* Limits minimum and default number of buffers */ |
115 | #define EM28XX_MIN_BUF 4 | 116 | #define EM28XX_MIN_BUF 4 |
@@ -143,9 +144,6 @@ | |||
143 | */ | 144 | */ |
144 | #define EM28XX_NUM_PACKETS 40 | 145 | #define EM28XX_NUM_PACKETS 40 |
145 | 146 | ||
146 | /* default alternate; 0 means choose the best */ | ||
147 | #define EM28XX_PINOUT 0 | ||
148 | |||
149 | #define EM28XX_INTERLACED_DEFAULT 1 | 147 | #define EM28XX_INTERLACED_DEFAULT 1 |
150 | 148 | ||
151 | /* | 149 | /* |
@@ -615,7 +613,6 @@ struct em28xx { | |||
615 | struct em28xx_dvb *dvb; | 613 | struct em28xx_dvb *dvb; |
616 | 614 | ||
617 | /* I2C keyboard data */ | 615 | /* I2C keyboard data */ |
618 | struct i2c_board_info info; | ||
619 | struct IR_i2c_init_data init_data; | 616 | struct IR_i2c_init_data init_data; |
620 | }; | 617 | }; |
621 | 618 | ||
@@ -800,7 +797,7 @@ static inline unsigned int norm_maxw(struct em28xx *dev) | |||
800 | if (dev->board.is_webcam) | 797 | if (dev->board.is_webcam) |
801 | return dev->sensor_xres; | 798 | return dev->sensor_xres; |
802 | 799 | ||
803 | if (dev->board.max_range_640_480) | 800 | if (dev->board.max_range_640_480 || dev->board.is_em2800) |
804 | return 640; | 801 | return 640; |
805 | 802 | ||
806 | return 720; | 803 | return 720; |
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index fe2e490ebc52..609d65b0b10d 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig | |||
@@ -76,10 +76,11 @@ config USB_GSPCA_MR97310A | |||
76 | module will be called gspca_mr97310a. | 76 | module will be called gspca_mr97310a. |
77 | 77 | ||
78 | config USB_GSPCA_OV519 | 78 | config USB_GSPCA_OV519 |
79 | tristate "OV519 USB Camera Driver" | 79 | tristate "OV51x / OVFX2 / W996xCF USB Camera Driver" |
80 | depends on VIDEO_V4L2 && USB_GSPCA | 80 | depends on VIDEO_V4L2 && USB_GSPCA |
81 | help | 81 | help |
82 | Say Y here if you want support for cameras based on the OV519 chip. | 82 | Say Y here if you want support for cameras based on one of these: |
83 | OV511(+), OV518(+), OV519, OVFX2, W9967CF, W9968CF | ||
83 | 84 | ||
84 | To compile this driver as a module, choose M here: the | 85 | To compile this driver as a module, choose M here: the |
85 | module will be called gspca_ov519. | 86 | module will be called gspca_ov519. |
@@ -103,6 +104,15 @@ config USB_GSPCA_PAC207 | |||
103 | To compile this driver as a module, choose M here: the | 104 | To compile this driver as a module, choose M here: the |
104 | module will be called gspca_pac207. | 105 | module will be called gspca_pac207. |
105 | 106 | ||
107 | config USB_GSPCA_PAC7302 | ||
108 | tristate "Pixart PAC7302 USB Camera Driver" | ||
109 | depends on VIDEO_V4L2 && USB_GSPCA | ||
110 | help | ||
111 | Say Y here if you want support for cameras based on the PAC7302 chip. | ||
112 | |||
113 | To compile this driver as a module, choose M here: the | ||
114 | module will be called gspca_pac7302. | ||
115 | |||
106 | config USB_GSPCA_PAC7311 | 116 | config USB_GSPCA_PAC7311 |
107 | tristate "Pixart PAC7311 USB Camera Driver" | 117 | tristate "Pixart PAC7311 USB Camera Driver" |
108 | depends on VIDEO_V4L2 && USB_GSPCA | 118 | depends on VIDEO_V4L2 && USB_GSPCA |
@@ -229,6 +239,15 @@ config USB_GSPCA_STK014 | |||
229 | To compile this driver as a module, choose M here: the | 239 | To compile this driver as a module, choose M here: the |
230 | module will be called gspca_stk014. | 240 | module will be called gspca_stk014. |
231 | 241 | ||
242 | config USB_GSPCA_STV0680 | ||
243 | tristate "STV0680 USB Camera Driver" | ||
244 | depends on VIDEO_V4L2 && USB_GSPCA | ||
245 | help | ||
246 | Say Y here if you want support for cameras based on the STV0680 chip. | ||
247 | |||
248 | To compile this driver as a module, choose M here: the | ||
249 | module will be called gspca_stv0680. | ||
250 | |||
232 | config USB_GSPCA_SUNPLUS | 251 | config USB_GSPCA_SUNPLUS |
233 | tristate "SUNPLUS USB Camera Driver" | 252 | tristate "SUNPLUS USB Camera Driver" |
234 | depends on VIDEO_V4L2 && USB_GSPCA | 253 | depends on VIDEO_V4L2 && USB_GSPCA |
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index b7420818037e..ff2c7279d82e 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile | |||
@@ -8,6 +8,7 @@ obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o | |||
8 | obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o | 8 | obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o |
9 | obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o | 9 | obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o |
10 | obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o | 10 | obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o |
11 | obj-$(CONFIG_USB_GSPCA_PAC7302) += gspca_pac7302.o | ||
11 | obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o | 12 | obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o |
12 | obj-$(CONFIG_USB_GSPCA_SN9C20X) += gspca_sn9c20x.o | 13 | obj-$(CONFIG_USB_GSPCA_SN9C20X) += gspca_sn9c20x.o |
13 | obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o | 14 | obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o |
@@ -22,6 +23,7 @@ obj-$(CONFIG_USB_GSPCA_SQ905) += gspca_sq905.o | |||
22 | obj-$(CONFIG_USB_GSPCA_SQ905C) += gspca_sq905c.o | 23 | obj-$(CONFIG_USB_GSPCA_SQ905C) += gspca_sq905c.o |
23 | obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o | 24 | obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o |
24 | obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o | 25 | obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o |
26 | obj-$(CONFIG_USB_GSPCA_STV0680) += gspca_stv0680.o | ||
25 | obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o | 27 | obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o |
26 | obj-$(CONFIG_USB_GSPCA_TV8532) += gspca_tv8532.o | 28 | obj-$(CONFIG_USB_GSPCA_TV8532) += gspca_tv8532.o |
27 | obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o | 29 | obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o |
@@ -37,6 +39,7 @@ gspca_mr97310a-objs := mr97310a.o | |||
37 | gspca_ov519-objs := ov519.o | 39 | gspca_ov519-objs := ov519.o |
38 | gspca_ov534-objs := ov534.o | 40 | gspca_ov534-objs := ov534.o |
39 | gspca_pac207-objs := pac207.o | 41 | gspca_pac207-objs := pac207.o |
42 | gspca_pac7302-objs := pac7302.o | ||
40 | gspca_pac7311-objs := pac7311.o | 43 | gspca_pac7311-objs := pac7311.o |
41 | gspca_sn9c20x-objs := sn9c20x.o | 44 | gspca_sn9c20x-objs := sn9c20x.o |
42 | gspca_sonixb-objs := sonixb.o | 45 | gspca_sonixb-objs := sonixb.o |
@@ -50,6 +53,7 @@ gspca_spca561-objs := spca561.o | |||
50 | gspca_sq905-objs := sq905.o | 53 | gspca_sq905-objs := sq905.o |
51 | gspca_sq905c-objs := sq905c.o | 54 | gspca_sq905c-objs := sq905c.o |
52 | gspca_stk014-objs := stk014.o | 55 | gspca_stk014-objs := stk014.o |
56 | gspca_stv0680-objs := stv0680.o | ||
53 | gspca_sunplus-objs := sunplus.o | 57 | gspca_sunplus-objs := sunplus.o |
54 | gspca_t613-objs := t613.o | 58 | gspca_t613-objs := t613.o |
55 | gspca_tv8532-objs := tv8532.o | 59 | gspca_tv8532-objs := tv8532.o |
diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index eca003566ae3..2f0b8d621e00 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c | |||
@@ -888,8 +888,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
888 | } | 888 | } |
889 | 889 | ||
890 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 890 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
891 | struct gspca_frame *frame, /* target */ | 891 | u8 *data, /* isoc packet */ |
892 | __u8 *data, /* isoc packet */ | ||
893 | int len) /* iso packet length */ | 892 | int len) /* iso packet length */ |
894 | { | 893 | { |
895 | struct sd *sd = (struct sd *) gspca_dev; | 894 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -897,16 +896,15 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
897 | if (data[0] == 0xff && data[1] == 0xd8) { | 896 | if (data[0] == 0xff && data[1] == 0xd8) { |
898 | 897 | ||
899 | /* start of frame */ | 898 | /* start of frame */ |
900 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | 899 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); |
901 | data, 0); | ||
902 | 900 | ||
903 | /* put the JPEG header in the new frame */ | 901 | /* put the JPEG header in the new frame */ |
904 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | 902 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
905 | sd->jpeg_hdr, JPEG_HDR_SZ); | 903 | sd->jpeg_hdr, JPEG_HDR_SZ); |
906 | data += 2; | 904 | data += 2; |
907 | len -= 2; | 905 | len -= 2; |
908 | } | 906 | } |
909 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | 907 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
910 | } | 908 | } |
911 | 909 | ||
912 | static void setbrightness(struct gspca_dev*gspca_dev) | 910 | static void setbrightness(struct gspca_dev*gspca_dev) |
diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c index c1461e63647f..9de86419ae1e 100644 --- a/drivers/media/video/gspca/etoms.c +++ b/drivers/media/video/gspca/etoms.c | |||
@@ -752,8 +752,7 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
752 | #undef LIMIT | 752 | #undef LIMIT |
753 | 753 | ||
754 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 754 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
755 | struct gspca_frame *frame, /* target */ | 755 | u8 *data, /* isoc packet */ |
756 | __u8 *data, /* isoc packet */ | ||
757 | int len) /* iso packet length */ | 756 | int len) /* iso packet length */ |
758 | { | 757 | { |
759 | int seqframe; | 758 | int seqframe; |
@@ -767,14 +766,13 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
767 | data[2], data[3], data[4], data[5]); | 766 | data[2], data[3], data[4], data[5]); |
768 | data += 30; | 767 | data += 30; |
769 | /* don't change datalength as the chips provided it */ | 768 | /* don't change datalength as the chips provided it */ |
770 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | 769 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); |
771 | data, 0); | 770 | gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); |
772 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); | ||
773 | return; | 771 | return; |
774 | } | 772 | } |
775 | if (len) { | 773 | if (len) { |
776 | data += 8; | 774 | data += 8; |
777 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | 775 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
778 | } else { /* Drop Packet */ | 776 | } else { /* Drop Packet */ |
779 | gspca_dev->last_packet_type = DISCARD_PACKET; | 777 | gspca_dev->last_packet_type = DISCARD_PACKET; |
780 | } | 778 | } |
diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c index 480ec5c87d0e..5d90e7448579 100644 --- a/drivers/media/video/gspca/finepix.c +++ b/drivers/media/video/gspca/finepix.c | |||
@@ -82,7 +82,6 @@ static void dostream(struct work_struct *work) | |||
82 | struct gspca_dev *gspca_dev = &dev->gspca_dev; | 82 | struct gspca_dev *gspca_dev = &dev->gspca_dev; |
83 | struct urb *urb = gspca_dev->urb[0]; | 83 | struct urb *urb = gspca_dev->urb[0]; |
84 | u8 *data = urb->transfer_buffer; | 84 | u8 *data = urb->transfer_buffer; |
85 | struct gspca_frame *frame; | ||
86 | int ret = 0; | 85 | int ret = 0; |
87 | int len; | 86 | int len; |
88 | 87 | ||
@@ -118,10 +117,6 @@ again: | |||
118 | } | 117 | } |
119 | if (!gspca_dev->present || !gspca_dev->streaming) | 118 | if (!gspca_dev->present || !gspca_dev->streaming) |
120 | goto out; | 119 | goto out; |
121 | frame = gspca_get_i_frame(&dev->gspca_dev); | ||
122 | if (frame == NULL) | ||
123 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
124 | |||
125 | if (len < FPIX_MAX_TRANSFER || | 120 | if (len < FPIX_MAX_TRANSFER || |
126 | (data[len - 2] == 0xff && | 121 | (data[len - 2] == 0xff && |
127 | data[len - 1] == 0xd9)) { | 122 | data[len - 1] == 0xd9)) { |
@@ -132,21 +127,17 @@ again: | |||
132 | * but there's nothing we can do. We also end | 127 | * but there's nothing we can do. We also end |
133 | * here if the the jpeg ends right at the end | 128 | * here if the the jpeg ends right at the end |
134 | * of the frame. */ | 129 | * of the frame. */ |
135 | if (frame) | 130 | gspca_frame_add(gspca_dev, LAST_PACKET, |
136 | frame = gspca_frame_add(gspca_dev, | 131 | data, len); |
137 | LAST_PACKET, | ||
138 | frame, | ||
139 | data, len); | ||
140 | break; | 132 | break; |
141 | } | 133 | } |
142 | 134 | ||
143 | /* got a partial image */ | 135 | /* got a partial image */ |
144 | if (frame) | 136 | gspca_frame_add(gspca_dev, |
145 | gspca_frame_add(gspca_dev, | 137 | gspca_dev->last_packet_type |
146 | gspca_dev->last_packet_type | 138 | == LAST_PACKET |
147 | == LAST_PACKET | 139 | ? FIRST_PACKET : INTER_PACKET, |
148 | ? FIRST_PACKET : INTER_PACKET, | 140 | data, len); |
149 | frame, data, len); | ||
150 | } | 141 | } |
151 | 142 | ||
152 | /* We must wait before trying reading the next | 143 | /* We must wait before trying reading the next |
diff --git a/drivers/media/video/gspca/gl860/gl860-mi1320.c b/drivers/media/video/gspca/gl860/gl860-mi1320.c index 39f6261c1a0c..1355e526ee84 100644 --- a/drivers/media/video/gspca/gl860/gl860-mi1320.c +++ b/drivers/media/video/gspca/gl860/gl860-mi1320.c | |||
@@ -1,6 +1,5 @@ | |||
1 | /* @file gl860-mi1320.c | 1 | /* Subdriver for the GL860 chip with the MI1320 sensor |
2 | * @author Olivier LORIN from my logs | 2 | * Author Olivier LORIN from own logs |
3 | * @date 2009-08-27 | ||
4 | * | 3 | * |
5 | * This program is free software; you can redistribute it and/or modify | 4 | * 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 | 5 | * it under the terms of the GNU General Public License as published by |
@@ -127,49 +126,49 @@ static u8 dat_wbalBL[] = | |||
127 | 126 | ||
128 | static u8 dat_hvflip1[] = {0xf0, 0x00, 0xf1, 0x00}; | 127 | static u8 dat_hvflip1[] = {0xf0, 0x00, 0xf1, 0x00}; |
129 | 128 | ||
130 | static u8 s000[] = | 129 | static u8 dat_common00[] = |
131 | "\x00\x01\x07\x6a\x06\x63\x0d\x6a" "\xc0\x00\x10\x10\xc1\x03\xc2\x42" | 130 | "\x00\x01\x07\x6a\x06\x63\x0d\x6a" "\xc0\x00\x10\x10\xc1\x03\xc2\x42" |
132 | "\xd8\x04\x58\x00\x04\x02"; | 131 | "\xd8\x04\x58\x00\x04\x02"; |
133 | static u8 s001[] = | 132 | static u8 dat_common01[] = |
134 | "\x0d\x00\xf1\x0b\x0d\x00\xf1\x08" "\x35\x00\xf1\x22\x68\x00\xf1\x5d" | 133 | "\x0d\x00\xf1\x0b\x0d\x00\xf1\x08" "\x35\x00\xf1\x22\x68\x00\xf1\x5d" |
135 | "\xf0\x00\xf1\x01\x06\x70\xf1\x0e" "\xf0\x00\xf1\x02\xdd\x18\xf1\xe0"; | 134 | "\xf0\x00\xf1\x01\x06\x70\xf1\x0e" "\xf0\x00\xf1\x02\xdd\x18\xf1\xe0"; |
136 | static u8 s002[] = | 135 | static u8 dat_common02[] = |
137 | "\x05\x01\xf1\x84\x06\x00\xf1\x44" "\x07\x00\xf1\xbe\x08\x00\xf1\x1e" | 136 | "\x05\x01\xf1\x84\x06\x00\xf1\x44" "\x07\x00\xf1\xbe\x08\x00\xf1\x1e" |
138 | "\x20\x01\xf1\x03\x21\x84\xf1\x00" "\x22\x0d\xf1\x0f\x24\x80\xf1\x00" | 137 | "\x20\x01\xf1\x03\x21\x84\xf1\x00" "\x22\x0d\xf1\x0f\x24\x80\xf1\x00" |
139 | "\x34\x18\xf1\x2d\x35\x00\xf1\x22" "\x43\x83\xf1\x83\x59\x00\xf1\xff"; | 138 | "\x34\x18\xf1\x2d\x35\x00\xf1\x22" "\x43\x83\xf1\x83\x59\x00\xf1\xff"; |
140 | static u8 s003[] = | 139 | static u8 dat_common03[] = |
141 | "\xf0\x00\xf1\x02\x39\x06\xf1\x8c" "\x3a\x06\xf1\x8c\x3b\x03\xf1\xda" | 140 | "\xf0\x00\xf1\x02\x39\x06\xf1\x8c" "\x3a\x06\xf1\x8c\x3b\x03\xf1\xda" |
142 | "\x3c\x05\xf1\x30\x57\x01\xf1\x0c" "\x58\x01\xf1\x42\x59\x01\xf1\x0c" | 141 | "\x3c\x05\xf1\x30\x57\x01\xf1\x0c" "\x58\x01\xf1\x42\x59\x01\xf1\x0c" |
143 | "\x5a\x01\xf1\x42\x5c\x13\xf1\x0e" "\x5d\x17\xf1\x12\x64\x1e\xf1\x1c"; | 142 | "\x5a\x01\xf1\x42\x5c\x13\xf1\x0e" "\x5d\x17\xf1\x12\x64\x1e\xf1\x1c"; |
144 | static u8 s004[] = | 143 | static u8 dat_common04[] = |
145 | "\xf0\x00\xf1\x02\x24\x5f\xf1\x20" "\x28\xea\xf1\x02\x5f\x41\xf1\x43"; | 144 | "\xf0\x00\xf1\x02\x24\x5f\xf1\x20" "\x28\xea\xf1\x02\x5f\x41\xf1\x43"; |
146 | static u8 s005[] = | 145 | static u8 dat_common05[] = |
147 | "\x02\x00\xf1\xee\x03\x29\xf1\x1a" "\x04\x02\xf1\xa4\x09\x00\xf1\x68" | 146 | "\x02\x00\xf1\xee\x03\x29\xf1\x1a" "\x04\x02\xf1\xa4\x09\x00\xf1\x68" |
148 | "\x0a\x00\xf1\x2a\x0b\x00\xf1\x04" "\x0c\x00\xf1\x93\x0d\x00\xf1\x82" | 147 | "\x0a\x00\xf1\x2a\x0b\x00\xf1\x04" "\x0c\x00\xf1\x93\x0d\x00\xf1\x82" |
149 | "\x0e\x00\xf1\x40\x0f\x00\xf1\x5f" "\x10\x00\xf1\x4e\x11\x00\xf1\x5b"; | 148 | "\x0e\x00\xf1\x40\x0f\x00\xf1\x5f" "\x10\x00\xf1\x4e\x11\x00\xf1\x5b"; |
150 | static u8 s006[] = | 149 | static u8 dat_common06[] = |
151 | "\x15\x00\xf1\xc9\x16\x00\xf1\x5e" "\x17\x00\xf1\x9d\x18\x00\xf1\x06" | 150 | "\x15\x00\xf1\xc9\x16\x00\xf1\x5e" "\x17\x00\xf1\x9d\x18\x00\xf1\x06" |
152 | "\x19\x00\xf1\x89\x1a\x00\xf1\x12" "\x1b\x00\xf1\xa1\x1c\x00\xf1\xe4" | 151 | "\x19\x00\xf1\x89\x1a\x00\xf1\x12" "\x1b\x00\xf1\xa1\x1c\x00\xf1\xe4" |
153 | "\x1d\x00\xf1\x7a\x1e\x00\xf1\x64" "\xf6\x00\xf1\x5f"; | 152 | "\x1d\x00\xf1\x7a\x1e\x00\xf1\x64" "\xf6\x00\xf1\x5f"; |
154 | static u8 s007[] = | 153 | static u8 dat_common07[] = |
155 | "\xf0\x00\xf1\x01\x53\x09\xf1\x03" "\x54\x3d\xf1\x1c\x55\x99\xf1\x72" | 154 | "\xf0\x00\xf1\x01\x53\x09\xf1\x03" "\x54\x3d\xf1\x1c\x55\x99\xf1\x72" |
156 | "\x56\xc1\xf1\xb1\x57\xd8\xf1\xce" "\x58\xe0\xf1\x00\xdc\x0a\xf1\x03" | 155 | "\x56\xc1\xf1\xb1\x57\xd8\xf1\xce" "\x58\xe0\xf1\x00\xdc\x0a\xf1\x03" |
157 | "\xdd\x45\xf1\x20\xde\xae\xf1\x82" "\xdf\xdc\xf1\xc9\xe0\xf6\xf1\xea" | 156 | "\xdd\x45\xf1\x20\xde\xae\xf1\x82" "\xdf\xdc\xf1\xc9\xe0\xf6\xf1\xea" |
158 | "\xe1\xff\xf1\x00"; | 157 | "\xe1\xff\xf1\x00"; |
159 | static u8 s008[] = | 158 | static u8 dat_common08[] = |
160 | "\xf0\x00\xf1\x01\x80\x00\xf1\x06" "\x81\xf6\xf1\x08\x82\xfb\xf1\xf7" | 159 | "\xf0\x00\xf1\x01\x80\x00\xf1\x06" "\x81\xf6\xf1\x08\x82\xfb\xf1\xf7" |
161 | "\x83\x00\xf1\xfe\xb6\x07\xf1\x03" "\xb7\x18\xf1\x0c\x84\xfb\xf1\x06" | 160 | "\x83\x00\xf1\xfe\xb6\x07\xf1\x03" "\xb7\x18\xf1\x0c\x84\xfb\xf1\x06" |
162 | "\x85\xfb\xf1\xf9\x86\x00\xf1\xff" "\xb8\x07\xf1\x04\xb9\x16\xf1\x0a"; | 161 | "\x85\xfb\xf1\xf9\x86\x00\xf1\xff" "\xb8\x07\xf1\x04\xb9\x16\xf1\x0a"; |
163 | static u8 s009[] = | 162 | static u8 dat_common09[] = |
164 | "\x87\xfa\xf1\x05\x88\xfc\xf1\xf9" "\x89\x00\xf1\xff\xba\x06\xf1\x03" | 163 | "\x87\xfa\xf1\x05\x88\xfc\xf1\xf9" "\x89\x00\xf1\xff\xba\x06\xf1\x03" |
165 | "\xbb\x17\xf1\x09\x8a\xe8\xf1\x14" "\x8b\xf7\xf1\xf0\x8c\xfd\xf1\xfa" | 164 | "\xbb\x17\xf1\x09\x8a\xe8\xf1\x14" "\x8b\xf7\xf1\xf0\x8c\xfd\xf1\xfa" |
166 | "\x8d\x00\xf1\x00\xbc\x05\xf1\x01" "\xbd\x0c\xf1\x08\xbe\x00\xf1\x14"; | 165 | "\x8d\x00\xf1\x00\xbc\x05\xf1\x01" "\xbd\x0c\xf1\x08\xbe\x00\xf1\x14"; |
167 | static u8 s010[] = | 166 | static u8 dat_common10[] = |
168 | "\x8e\xea\xf1\x13\x8f\xf7\xf1\xf2" "\x90\xfd\xf1\xfa\x91\x00\xf1\x00" | 167 | "\x8e\xea\xf1\x13\x8f\xf7\xf1\xf2" "\x90\xfd\xf1\xfa\x91\x00\xf1\x00" |
169 | "\xbf\x05\xf1\x01\xc0\x0a\xf1\x08" "\xc1\x00\xf1\x0c\x92\xed\xf1\x0f" | 168 | "\xbf\x05\xf1\x01\xc0\x0a\xf1\x08" "\xc1\x00\xf1\x0c\x92\xed\xf1\x0f" |
170 | "\x93\xf9\xf1\xf4\x94\xfe\xf1\xfb" "\x95\x00\xf1\x00\xc2\x04\xf1\x01" | 169 | "\x93\xf9\xf1\xf4\x94\xfe\xf1\xfb" "\x95\x00\xf1\x00\xc2\x04\xf1\x01" |
171 | "\xc3\x0a\xf1\x07\xc4\x00\xf1\x10"; | 170 | "\xc3\x0a\xf1\x07\xc4\x00\xf1\x10"; |
172 | static u8 s011[] = | 171 | static u8 dat_common11[] = |
173 | "\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x25\x00\xf1\x55\x34\x10\xf1\x10" | 172 | "\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x25\x00\xf1\x55\x34\x10\xf1\x10" |
174 | "\x35\xf0\xf1\x10\x3a\x02\xf1\x03" "\x3b\x04\xf1\x2a\x9b\x43\xf1\x00" | 173 | "\x35\xf0\xf1\x10\x3a\x02\xf1\x03" "\x3b\x04\xf1\x2a\x9b\x43\xf1\x00" |
175 | "\xa4\x03\xf1\xc0\xa7\x02\xf1\x81"; | 174 | "\xa4\x03\xf1\xc0\xa7\x02\xf1\x81"; |
@@ -222,26 +221,26 @@ void mi1320_init_settings(struct gspca_dev *gspca_dev) | |||
222 | 221 | ||
223 | static void common(struct gspca_dev *gspca_dev) | 222 | static void common(struct gspca_dev *gspca_dev) |
224 | { | 223 | { |
225 | s32 n; /* reserved for FETCH macros */ | 224 | s32 n; /* reserved for FETCH functions */ |
226 | 225 | ||
227 | ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 22, s000); | 226 | ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 22, dat_common00); |
228 | ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x0000, 0, NULL); | 227 | ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x0000, 0, NULL); |
229 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 32, s001); | 228 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 32, dat_common01); |
230 | n = fetch_validx(gspca_dev, tbl_common, ARRAY_SIZE(tbl_common)); | 229 | n = fetch_validx(gspca_dev, tbl_common, ARRAY_SIZE(tbl_common)); |
231 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, s002); | 230 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common02); |
232 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, s003); | 231 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common03); |
233 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 16, s004); | 232 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 16, dat_common04); |
234 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, s005); | 233 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common05); |
235 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 44, s006); | 234 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 44, dat_common06); |
236 | keep_on_fetching_validx(gspca_dev, tbl_common, | 235 | keep_on_fetching_validx(gspca_dev, tbl_common, |
237 | ARRAY_SIZE(tbl_common), n); | 236 | ARRAY_SIZE(tbl_common), n); |
238 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 52, s007); | 237 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 52, dat_common07); |
239 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, s008); | 238 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common08); |
240 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, s009); | 239 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common09); |
241 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 56, s010); | 240 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 56, dat_common10); |
242 | keep_on_fetching_validx(gspca_dev, tbl_common, | 241 | keep_on_fetching_validx(gspca_dev, tbl_common, |
243 | ARRAY_SIZE(tbl_common), n); | 242 | ARRAY_SIZE(tbl_common), n); |
244 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, s011); | 243 | ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, dat_common11); |
245 | keep_on_fetching_validx(gspca_dev, tbl_common, | 244 | keep_on_fetching_validx(gspca_dev, tbl_common, |
246 | ARRAY_SIZE(tbl_common), n); | 245 | ARRAY_SIZE(tbl_common), n); |
247 | } | 246 | } |
diff --git a/drivers/media/video/gspca/gl860/gl860-mi2020.c b/drivers/media/video/gspca/gl860/gl860-mi2020.c index ffb09fed3e8c..80cb3f1b36f7 100644 --- a/drivers/media/video/gspca/gl860/gl860-mi2020.c +++ b/drivers/media/video/gspca/gl860/gl860-mi2020.c | |||
@@ -1,7 +1,6 @@ | |||
1 | /* @file gl860-mi2020.c | 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 Ice/Soro2005's logs(A), Fret_saw/Hulkie's |
3 | * logs(B) and Tricid"s logs(C). With the help of Kytrix/BUGabundo/Blazercist. | 3 | * logs(B) and Tricid"s logs(C). With the help of Kytrix/BUGabundo/Blazercist. |
4 | * @date 2009-08-27 | ||
5 | * | 4 | * |
6 | * This program is free software; you can redistribute it and/or modify | 5 | * 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 | 6 | * it under the terms of the GNU General Public License as published by |
@@ -41,7 +40,7 @@ static u8 dat_freq1[] = { 0x8c, 0xa4, 0x04 }; | |||
41 | static u8 dat_multi5[] = { 0x8c, 0xa1, 0x03 }; | 40 | static u8 dat_multi5[] = { 0x8c, 0xa1, 0x03 }; |
42 | static u8 dat_multi6[] = { 0x90, 0x00, 0x05 }; | 41 | static u8 dat_multi6[] = { 0x90, 0x00, 0x05 }; |
43 | 42 | ||
44 | static struct validx tbl_common_a[] = { | 43 | static struct validx tbl_common1[] = { |
45 | {0x0000, 0x0000}, | 44 | {0x0000, 0x0000}, |
46 | {1, 0xffff}, /* msleep(35); */ | 45 | {1, 0xffff}, /* msleep(35); */ |
47 | {0x006a, 0x0007}, {0x0063, 0x0006}, {0x006a, 0x000d}, {0x0000, 0x00c0}, | 46 | {0x006a, 0x0007}, {0x0063, 0x0006}, {0x006a, 0x000d}, {0x0000, 0x00c0}, |
@@ -49,7 +48,7 @@ static struct validx tbl_common_a[] = { | |||
49 | {0x0000, 0x0058}, {0x0002, 0x0004}, {0x0041, 0x0000}, | 48 | {0x0000, 0x0058}, {0x0002, 0x0004}, {0x0041, 0x0000}, |
50 | }; | 49 | }; |
51 | 50 | ||
52 | static struct validx tbl_common_b[] = { | 51 | static struct validx tbl_common2[] = { |
53 | {0x006a, 0x0007}, | 52 | {0x006a, 0x0007}, |
54 | {35, 0xffff}, | 53 | {35, 0xffff}, |
55 | {0x00ef, 0x0006}, | 54 | {0x00ef, 0x0006}, |
@@ -60,7 +59,7 @@ static struct validx tbl_common_b[] = { | |||
60 | {0x0004, 0x00d8}, {0x0000, 0x0058}, {0x0041, 0x0000}, | 59 | {0x0004, 0x00d8}, {0x0000, 0x0058}, {0x0041, 0x0000}, |
61 | }; | 60 | }; |
62 | 61 | ||
63 | static struct idxdata tbl_common_c[] = { | 62 | static struct idxdata tbl_common3[] = { |
64 | {0x32, "\x02\x00\x08"}, {0x33, "\xf4\x03\x1d"}, | 63 | {0x32, "\x02\x00\x08"}, {0x33, "\xf4\x03\x1d"}, |
65 | {6, "\xff\xff\xff"}, /* 12 */ | 64 | {6, "\xff\xff\xff"}, /* 12 */ |
66 | {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"}, | 65 | {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"}, |
@@ -109,7 +108,7 @@ static struct idxdata tbl_common_c[] = { | |||
109 | {0x33, "\x8c\xa2\x03"}, {0x33, "\x90\x00\xbb"}, | 108 | {0x33, "\x8c\xa2\x03"}, {0x33, "\x90\x00\xbb"}, |
110 | }; | 109 | }; |
111 | 110 | ||
112 | static struct idxdata tbl_common_d[] = { | 111 | static struct idxdata tbl_common4[] = { |
113 | {0x33, "\x8c\x22\x2e"}, {0x33, "\x90\x00\xa0"}, {0x33, "\x8c\xa4\x08"}, | 112 | {0x33, "\x8c\x22\x2e"}, {0x33, "\x90\x00\xa0"}, {0x33, "\x8c\xa4\x08"}, |
114 | {0x33, "\x90\x00\x1f"}, {0x33, "\x8c\xa4\x09"}, {0x33, "\x90\x00\x21"}, | 113 | {0x33, "\x90\x00\x1f"}, {0x33, "\x8c\xa4\x09"}, {0x33, "\x90\x00\x21"}, |
115 | {0x33, "\x8c\xa4\x0a"}, {0x33, "\x90\x00\x25"}, {0x33, "\x8c\xa4\x0b"}, | 114 | {0x33, "\x8c\xa4\x0a"}, {0x33, "\x90\x00\x25"}, {0x33, "\x8c\xa4\x0b"}, |
@@ -118,7 +117,7 @@ static struct idxdata tbl_common_d[] = { | |||
118 | {0x33, "\x90\x00\xa0"}, {0x33, "\x8c\x24\x17"}, {0x33, "\x90\x00\xc0"}, | 117 | {0x33, "\x90\x00\xa0"}, {0x33, "\x8c\x24\x17"}, {0x33, "\x90\x00\xc0"}, |
119 | }; | 118 | }; |
120 | 119 | ||
121 | static struct idxdata tbl_common_e[] = { | 120 | static struct idxdata tbl_common5[] = { |
122 | {0x33, "\x8c\xa4\x04"}, {0x33, "\x90\x00\x80"}, {0x33, "\x8c\xa7\x9d"}, | 121 | {0x33, "\x8c\xa4\x04"}, {0x33, "\x90\x00\x80"}, {0x33, "\x8c\xa7\x9d"}, |
123 | {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa7\x9e"}, {0x33, "\x90\x00\x00"}, | 122 | {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa7\x9e"}, {0x33, "\x90\x00\x00"}, |
124 | {0x33, "\x8c\xa2\x0c"}, {0x33, "\x90\x00\x17"}, {0x33, "\x8c\xa2\x15"}, | 123 | {0x33, "\x8c\xa2\x0c"}, {0x33, "\x90\x00\x17"}, {0x33, "\x8c\xa2\x15"}, |
@@ -180,7 +179,7 @@ static struct validx tbl_init_at_startup[] = { | |||
180 | {53, 0xffff}, | 179 | {53, 0xffff}, |
181 | }; | 180 | }; |
182 | 181 | ||
183 | static struct idxdata tbl_init_post_alt_low_a[] = { | 182 | static struct idxdata tbl_init_post_alt_low1[] = { |
184 | {0x33, "\x8c\x27\x15"}, {0x33, "\x90\x00\x25"}, {0x33, "\x8c\x22\x2e"}, | 183 | {0x33, "\x8c\x27\x15"}, {0x33, "\x90\x00\x25"}, {0x33, "\x8c\x22\x2e"}, |
185 | {0x33, "\x90\x00\x81"}, {0x33, "\x8c\xa4\x08"}, {0x33, "\x90\x00\x17"}, | 184 | {0x33, "\x90\x00\x81"}, {0x33, "\x8c\xa4\x08"}, {0x33, "\x90\x00\x17"}, |
186 | {0x33, "\x8c\xa4\x09"}, {0x33, "\x90\x00\x1a"}, {0x33, "\x8c\xa4\x0a"}, | 185 | {0x33, "\x8c\xa4\x09"}, {0x33, "\x90\x00\x1a"}, {0x33, "\x8c\xa4\x0a"}, |
@@ -189,7 +188,7 @@ static struct idxdata tbl_init_post_alt_low_a[] = { | |||
189 | {0x33, "\x90\x00\x9b"}, | 188 | {0x33, "\x90\x00\x9b"}, |
190 | }; | 189 | }; |
191 | 190 | ||
192 | static struct idxdata tbl_init_post_alt_low_b[] = { | 191 | static struct idxdata tbl_init_post_alt_low2[] = { |
193 | {0x33, "\x8c\x27\x03"}, {0x33, "\x90\x03\x24"}, {0x33, "\x8c\x27\x05"}, | 192 | {0x33, "\x8c\x27\x03"}, {0x33, "\x90\x03\x24"}, {0x33, "\x8c\x27\x05"}, |
194 | {0x33, "\x90\x02\x58"}, {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"}, | 193 | {0x33, "\x90\x02\x58"}, {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"}, |
195 | {2, "\xff\xff\xff"}, | 194 | {2, "\xff\xff\xff"}, |
@@ -197,7 +196,7 @@ static struct idxdata tbl_init_post_alt_low_b[] = { | |||
197 | {2, "\xff\xff\xff"}, | 196 | {2, "\xff\xff\xff"}, |
198 | }; | 197 | }; |
199 | 198 | ||
200 | static struct idxdata tbl_init_post_alt_low_c[] = { | 199 | static struct idxdata tbl_init_post_alt_low3[] = { |
201 | {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"}, | 200 | {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"}, |
202 | {2, "\xff\xff\xff"}, | 201 | {2, "\xff\xff\xff"}, |
203 | {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\xa1\x20"}, | 202 | {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\xa1\x20"}, |
@@ -221,7 +220,7 @@ static struct idxdata tbl_init_post_alt_low_c[] = { | |||
221 | {1, "\xff\xff\xff"}, | 220 | {1, "\xff\xff\xff"}, |
222 | }; | 221 | }; |
223 | 222 | ||
224 | static struct idxdata tbl_init_post_alt_low_d[] = { | 223 | static struct idxdata tbl_init_post_alt_low4[] = { |
225 | {0x32, "\x10\x01\xf8"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"}, | 224 | {0x32, "\x10\x01\xf8"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"}, |
226 | {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"}, | 225 | {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"}, |
227 | {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"}, | 226 | {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"}, |
@@ -267,7 +266,7 @@ static struct idxdata tbl_init_post_alt_low_d[] = { | |||
267 | {0x32, "\x6c\x14\x08"}, | 266 | {0x32, "\x6c\x14\x08"}, |
268 | }; | 267 | }; |
269 | 268 | ||
270 | static struct idxdata tbl_init_post_alt_big_a[] = { | 269 | static struct idxdata tbl_init_post_alt_big1[] = { |
271 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"}, | 270 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"}, |
272 | {2, "\xff\xff\xff"}, | 271 | {2, "\xff\xff\xff"}, |
273 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, | 272 | {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, |
@@ -288,7 +287,7 @@ static struct idxdata tbl_init_post_alt_big_a[] = { | |||
288 | {0x34, "\x04\x00\x2a"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"}, | 287 | {0x34, "\x04\x00\x2a"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"}, |
289 | }; | 288 | }; |
290 | 289 | ||
291 | static struct idxdata tbl_init_post_alt_big_b[] = { | 290 | static struct idxdata tbl_init_post_alt_big2[] = { |
292 | {0x32, "\x10\x01\xf8"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"}, | 291 | {0x32, "\x10\x01\xf8"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"}, |
293 | {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"}, | 292 | {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"}, |
294 | {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"}, | 293 | {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"}, |
@@ -317,7 +316,7 @@ static struct idxdata tbl_init_post_alt_big_b[] = { | |||
317 | {0x32, "\x10\x01\xfc"}, {0x33, "\x8c\xa1\x18"}, {0x33, "\x90\x00\x3c"}, | 316 | {0x32, "\x10\x01\xfc"}, {0x33, "\x8c\xa1\x18"}, {0x33, "\x90\x00\x3c"}, |
318 | }; | 317 | }; |
319 | 318 | ||
320 | static struct idxdata tbl_init_post_alt_big_c[] = { | 319 | static struct idxdata tbl_init_post_alt_big3[] = { |
321 | {0x33, "\x8c\xa1\x02"}, | 320 | {0x33, "\x8c\xa1\x02"}, |
322 | {0x33, "\x90\x00\x1f"}, | 321 | {0x33, "\x90\x00\x1f"}, |
323 | {0x33, "\x8c\xa1\x02"}, | 322 | {0x33, "\x8c\xa1\x02"}, |
@@ -388,14 +387,14 @@ static void common(struct gspca_dev *gspca_dev) | |||
388 | s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; | 387 | s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; |
389 | 388 | ||
390 | if (_MI2020b_) { | 389 | if (_MI2020b_) { |
391 | fetch_validx(gspca_dev, tbl_common_a, ARRAY_SIZE(tbl_common_a)); | 390 | fetch_validx(gspca_dev, tbl_common1, ARRAY_SIZE(tbl_common1)); |
392 | } else { | 391 | } else { |
393 | if (_MI2020_) | 392 | if (_MI2020_) |
394 | ctrl_out(gspca_dev, 0x40, 1, 0x0008, 0x0004, 0, NULL); | 393 | ctrl_out(gspca_dev, 0x40, 1, 0x0008, 0x0004, 0, NULL); |
395 | else | 394 | else |
396 | ctrl_out(gspca_dev, 0x40, 1, 0x0002, 0x0004, 0, NULL); | 395 | ctrl_out(gspca_dev, 0x40, 1, 0x0002, 0x0004, 0, NULL); |
397 | msleep(35); | 396 | msleep(35); |
398 | fetch_validx(gspca_dev, tbl_common_b, ARRAY_SIZE(tbl_common_b)); | 397 | fetch_validx(gspca_dev, tbl_common2, ARRAY_SIZE(tbl_common2)); |
399 | } | 398 | } |
400 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x86\x25\x01"); | 399 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x86\x25\x01"); |
401 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x86\x25\x00"); | 400 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x86\x25\x00"); |
@@ -403,13 +402,13 @@ static void common(struct gspca_dev *gspca_dev) | |||
403 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0030, 3, "\x1a\x0a\xcc"); | 402 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0030, 3, "\x1a\x0a\xcc"); |
404 | if (reso == IMAGE_1600) | 403 | if (reso == IMAGE_1600) |
405 | msleep(2); /* 1600 */ | 404 | msleep(2); /* 1600 */ |
406 | fetch_idxdata(gspca_dev, tbl_common_c, ARRAY_SIZE(tbl_common_c)); | 405 | fetch_idxdata(gspca_dev, tbl_common3, ARRAY_SIZE(tbl_common3)); |
407 | 406 | ||
408 | if (_MI2020b_ || _MI2020_) | 407 | if (_MI2020b_ || _MI2020_) |
409 | fetch_idxdata(gspca_dev, tbl_common_d, | 408 | fetch_idxdata(gspca_dev, tbl_common4, |
410 | ARRAY_SIZE(tbl_common_d)); | 409 | ARRAY_SIZE(tbl_common4)); |
411 | 410 | ||
412 | fetch_idxdata(gspca_dev, tbl_common_e, ARRAY_SIZE(tbl_common_e)); | 411 | fetch_idxdata(gspca_dev, tbl_common5, ARRAY_SIZE(tbl_common5)); |
413 | if (_MI2020b_ || _MI2020_) { | 412 | if (_MI2020b_ || _MI2020_) { |
414 | /* Different from fret */ | 413 | /* Different from fret */ |
415 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x78"); | 414 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x78"); |
@@ -525,15 +524,15 @@ static int mi2020_init_post_alt(struct gspca_dev *gspca_dev) | |||
525 | 12, dat_800); | 524 | 12, dat_800); |
526 | 525 | ||
527 | if (_MI2020c_) | 526 | if (_MI2020c_) |
528 | fetch_idxdata(gspca_dev, tbl_init_post_alt_low_a, | 527 | fetch_idxdata(gspca_dev, tbl_init_post_alt_low1, |
529 | ARRAY_SIZE(tbl_init_post_alt_low_a)); | 528 | ARRAY_SIZE(tbl_init_post_alt_low1)); |
530 | 529 | ||
531 | if (reso == IMAGE_800) | 530 | if (reso == IMAGE_800) |
532 | fetch_idxdata(gspca_dev, tbl_init_post_alt_low_b, | 531 | fetch_idxdata(gspca_dev, tbl_init_post_alt_low2, |
533 | ARRAY_SIZE(tbl_init_post_alt_low_b)); | 532 | ARRAY_SIZE(tbl_init_post_alt_low2)); |
534 | 533 | ||
535 | fetch_idxdata(gspca_dev, tbl_init_post_alt_low_c, | 534 | fetch_idxdata(gspca_dev, tbl_init_post_alt_low3, |
536 | ARRAY_SIZE(tbl_init_post_alt_low_c)); | 535 | ARRAY_SIZE(tbl_init_post_alt_low3)); |
537 | 536 | ||
538 | if (_MI2020b_) { | 537 | if (_MI2020b_) { |
539 | ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0010, 0, NULL); | 538 | ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0010, 0, NULL); |
@@ -574,8 +573,8 @@ static int mi2020_init_post_alt(struct gspca_dev *gspca_dev) | |||
574 | msleep(5);/* " */ | 573 | msleep(5);/* " */ |
575 | 574 | ||
576 | if (_MI2020c_) { | 575 | if (_MI2020c_) { |
577 | fetch_idxdata(gspca_dev, tbl_init_post_alt_low_d, | 576 | fetch_idxdata(gspca_dev, tbl_init_post_alt_low4, |
578 | ARRAY_SIZE(tbl_init_post_alt_low_d)); | 577 | ARRAY_SIZE(tbl_init_post_alt_low4)); |
579 | } else { | 578 | } else { |
580 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, &c); | 579 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, &c); |
581 | msleep(14); /* 0xd8 */ | 580 | msleep(14); /* 0xd8 */ |
@@ -644,8 +643,8 @@ static int mi2020_init_post_alt(struct gspca_dev *gspca_dev) | |||
644 | 3, "\x90\x04\xb0"); | 643 | 3, "\x90\x04\xb0"); |
645 | } | 644 | } |
646 | 645 | ||
647 | fetch_idxdata(gspca_dev, tbl_init_post_alt_big_a, | 646 | fetch_idxdata(gspca_dev, tbl_init_post_alt_big1, |
648 | ARRAY_SIZE(tbl_init_post_alt_big_a)); | 647 | ARRAY_SIZE(tbl_init_post_alt_big1)); |
649 | 648 | ||
650 | if (reso == IMAGE_1600) | 649 | if (reso == IMAGE_1600) |
651 | msleep(13); /* 1600 */ | 650 | msleep(13); /* 1600 */ |
@@ -708,8 +707,8 @@ static int mi2020_init_post_alt(struct gspca_dev *gspca_dev) | |||
708 | msleep(14); | 707 | msleep(14); |
709 | 708 | ||
710 | if (_MI2020c_) | 709 | if (_MI2020c_) |
711 | fetch_idxdata(gspca_dev, tbl_init_post_alt_big_b, | 710 | fetch_idxdata(gspca_dev, tbl_init_post_alt_big2, |
712 | ARRAY_SIZE(tbl_init_post_alt_big_b)); | 711 | ARRAY_SIZE(tbl_init_post_alt_big2)); |
713 | 712 | ||
714 | /* flip/mirror */ | 713 | /* flip/mirror */ |
715 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1); | 714 | ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1); |
@@ -738,8 +737,8 @@ static int mi2020_init_post_alt(struct gspca_dev *gspca_dev) | |||
738 | sd->nbIm = 0; | 737 | sd->nbIm = 0; |
739 | 738 | ||
740 | if (_MI2020c_) | 739 | if (_MI2020c_) |
741 | fetch_idxdata(gspca_dev, tbl_init_post_alt_big_c, | 740 | fetch_idxdata(gspca_dev, tbl_init_post_alt_big3, |
742 | ARRAY_SIZE(tbl_init_post_alt_big_c)); | 741 | ARRAY_SIZE(tbl_init_post_alt_big3)); |
743 | } | 742 | } |
744 | 743 | ||
745 | sd->vold.mirror = mirror; | 744 | sd->vold.mirror = mirror; |
diff --git a/drivers/media/video/gspca/gl860/gl860-ov2640.c b/drivers/media/video/gspca/gl860/gl860-ov2640.c index 14b9c373f9f7..768cac5cd72b 100644 --- a/drivers/media/video/gspca/gl860/gl860-ov2640.c +++ b/drivers/media/video/gspca/gl860/gl860-ov2640.c | |||
@@ -1,6 +1,5 @@ | |||
1 | /* @file gl860-ov2640.c | 1 | /* Subdriver for the GL860 chip with the OV2640 sensor |
2 | * @author Olivier LORIN, from Malmostoso's logs | 2 | * Author Olivier LORIN, from Malmostoso's logs |
3 | * @date 2009-08-27 | ||
4 | * | 3 | * |
5 | * This program is free software; you can redistribute it and/or modify | 4 | * 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 | 5 | * it under the terms of the GNU General Public License as published by |
@@ -21,8 +20,12 @@ | |||
21 | #include "gl860.h" | 20 | #include "gl860.h" |
22 | 21 | ||
23 | static u8 dat_init1[] = "\x00\x41\x07\x6a\x06\x61\x0d\x6a" "\x10\x10\xc1\x01"; | 22 | static u8 dat_init1[] = "\x00\x41\x07\x6a\x06\x61\x0d\x6a" "\x10\x10\xc1\x01"; |
24 | static u8 dat_init2[] = {0x61}; /* expected */ | 23 | |
25 | static u8 dat_init3[] = {0x51}; /* expected */ | 24 | static u8 c61[] = {0x61}; /* expected */ |
25 | static u8 c51[] = {0x51}; /* expected */ | ||
26 | static u8 c50[] = {0x50}; /* expected */ | ||
27 | static u8 c28[] = {0x28}; /* expected */ | ||
28 | static u8 ca8[] = {0xa8}; /* expected */ | ||
26 | 29 | ||
27 | static u8 dat_post[] = | 30 | static u8 dat_post[] = |
28 | "\x00\x41\x07\x6a\x06\xef\x0d\x6a" "\x10\x10\xc1\x01"; | 31 | "\x00\x41\x07\x6a\x06\xef\x0d\x6a" "\x10\x10\xc1\x01"; |
@@ -32,10 +35,6 @@ static u8 dat_800[] = "\xd0\x01\xd1\x10\xd2\x58\xd3\x02\xd4\x18\xd5\x21"; | |||
32 | static u8 dat_1280[] = "\xd0\x01\xd1\x18\xd2\xc0\xd3\x02\xd4\x28\xd5\x01"; | 35 | static u8 dat_1280[] = "\xd0\x01\xd1\x18\xd2\xc0\xd3\x02\xd4\x28\xd5\x01"; |
33 | static u8 dat_1600[] = "\xd0\x01\xd1\x20\xd2\xb0\xd3\x02\xd4\x30\xd5\x41"; | 36 | static u8 dat_1600[] = "\xd0\x01\xd1\x20\xd2\xb0\xd3\x02\xd4\x30\xd5\x41"; |
34 | 37 | ||
35 | static u8 c50[] = {0x50}; /* expected */ | ||
36 | static u8 c28[] = {0x28}; /* expected */ | ||
37 | static u8 ca8[] = {0xa8}; /* expected */ | ||
38 | |||
39 | static struct validx tbl_init_at_startup[] = { | 38 | static struct validx tbl_init_at_startup[] = { |
40 | {0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001, 0x00c1}, | 39 | {0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001, 0x00c1}, |
41 | {0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d}, | 40 | {0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d}, |
@@ -92,7 +91,7 @@ static struct validx tbl_common[] = { | |||
92 | {0x6000, 0x0010}, | 91 | {0x6000, 0x0010}, |
93 | }; | 92 | }; |
94 | 93 | ||
95 | static struct validx tbl_sensor_settings_common_a[] = { | 94 | static struct validx tbl_sensor_settings_common1[] = { |
96 | {0x0041, 0x0000}, {0x006a, 0x0007}, {0x00ef, 0x0006}, {0x006a, 0x000d}, | 95 | {0x0041, 0x0000}, {0x006a, 0x0007}, {0x00ef, 0x0006}, {0x006a, 0x000d}, |
97 | {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0001, 0x00c1}, {0x0041, 0x00c2}, | 96 | {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0001, 0x00c1}, {0x0041, 0x00c2}, |
98 | {0x0004, 0x00d8}, {0x0012, 0x0004}, {0x0000, 0x0058}, {0x0041, 0x0000}, | 97 | {0x0004, 0x00d8}, {0x0012, 0x0004}, {0x0000, 0x0058}, {0x0041, 0x0000}, |
@@ -104,40 +103,10 @@ static struct validx tbl_sensor_settings_common_a[] = { | |||
104 | {0x0040, 0x0000}, | 103 | {0x0040, 0x0000}, |
105 | }; | 104 | }; |
106 | 105 | ||
107 | static struct validx tbl_sensor_settings_common_b[] = { | 106 | static struct validx tbl_sensor_settings_common2[] = { |
108 | {0x6001, 0x00ff}, {0x6038, 0x000c}, | 107 | {0x6001, 0x00ff}, {0x6038, 0x000c}, |
109 | {10, 0xffff}, | 108 | {10, 0xffff}, |
110 | {0x6000, 0x0011}, | 109 | {0x6000, 0x0011}, |
111 | /* backlight=31/64 */ | ||
112 | {0x6001, 0x00ff}, {0x603e, 0x0024}, {0x6034, 0x0025}, | ||
113 | /* bright=0/256 */ | ||
114 | {0x6000, 0x00ff}, {0x6009, 0x007c}, {0x6000, 0x007d}, | ||
115 | /* wbal=64/128 */ | ||
116 | {0x6000, 0x00ff}, {0x6003, 0x007c}, {0x6040, 0x007d}, | ||
117 | /* cntr=0/256 */ | ||
118 | {0x6000, 0x00ff}, {0x6007, 0x007c}, {0x6000, 0x007d}, | ||
119 | /* sat=128/256 */ | ||
120 | {0x6000, 0x00ff}, {0x6001, 0x007c}, {0x6080, 0x007d}, | ||
121 | /* sharpness=0/32 */ | ||
122 | {0x6000, 0x00ff}, {0x6001, 0x0092}, {0x60c0, 0x0093}, | ||
123 | /* hue=0/256 */ | ||
124 | {0x6000, 0x00ff}, {0x6002, 0x007c}, {0x6000, 0x007d}, | ||
125 | /* gam=32/64 */ | ||
126 | {0x6000, 0x00ff}, {0x6008, 0x007c}, {0x6020, 0x007d}, | ||
127 | /* image right up */ | ||
128 | {0xffff, 0xffff}, | ||
129 | {15, 0xffff}, | ||
130 | {0x6001, 0x00ff}, {0x6000, 0x8004}, | ||
131 | {0xffff, 0xffff}, | ||
132 | {0x60a8, 0x0004}, | ||
133 | {15, 0xffff}, | ||
134 | {0x6001, 0x00ff}, {0x6000, 0x8004}, | ||
135 | {0xffff, 0xffff}, | ||
136 | {0x60f8, 0x0004}, | ||
137 | /* image right up */ | ||
138 | {0xffff, 0xffff}, | ||
139 | /* backlight=31/64 */ | ||
140 | {0x6001, 0x00ff}, {0x603e, 0x0024}, {0x6034, 0x0025}, | ||
141 | }; | 110 | }; |
142 | 111 | ||
143 | static struct validx tbl_640[] = { | 112 | static struct validx tbl_640[] = { |
@@ -166,7 +135,7 @@ static struct validx tbl_800[] = { | |||
166 | {0x60ff, 0x00dd}, {0x6020, 0x008c}, {0x6001, 0x00ff}, {0x6044, 0x0018}, | 135 | {0x60ff, 0x00dd}, {0x6020, 0x008c}, {0x6001, 0x00ff}, {0x6044, 0x0018}, |
167 | }; | 136 | }; |
168 | 137 | ||
169 | static struct validx tbl_big_a[] = { | 138 | static struct validx tbl_big1[] = { |
170 | {0x0002, 0x00c1}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, | 139 | {0x0002, 0x00c1}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, |
171 | {0x6001, 0x00ff}, {0x6000, 0x0012}, {0x6000, 0x0000}, {0x6000, 0x0045}, | 140 | {0x6001, 0x00ff}, {0x6000, 0x0012}, {0x6000, 0x0000}, {0x6000, 0x0045}, |
172 | {0x6000, 0x0010}, {0x6000, 0x0011}, {0x6011, 0x0017}, {0x6075, 0x0018}, | 141 | {0x6000, 0x0010}, {0x6000, 0x0011}, {0x6011, 0x0017}, {0x6075, 0x0018}, |
@@ -176,14 +145,14 @@ static struct validx tbl_big_a[] = { | |||
176 | {0x60c8, 0x00c0}, {0x6096, 0x00c1}, {0x6000, 0x008c}, | 145 | {0x60c8, 0x00c0}, {0x6096, 0x00c1}, {0x6000, 0x008c}, |
177 | }; | 146 | }; |
178 | 147 | ||
179 | static struct validx tbl_big_b[] = { | 148 | static struct validx tbl_big2[] = { |
180 | {0x603d, 0x0086}, {0x6000, 0x0050}, {0x6090, 0x0051}, {0x602c, 0x0052}, | 149 | {0x603d, 0x0086}, {0x6000, 0x0050}, {0x6090, 0x0051}, {0x602c, 0x0052}, |
181 | {0x6000, 0x0053}, {0x6000, 0x0054}, {0x6088, 0x0055}, {0x6000, 0x0057}, | 150 | {0x6000, 0x0053}, {0x6000, 0x0054}, {0x6088, 0x0055}, {0x6000, 0x0057}, |
182 | {0x6040, 0x005a}, {0x60f0, 0x005b}, {0x6001, 0x005c}, {0x6082, 0x00d3}, | 151 | {0x6040, 0x005a}, {0x60f0, 0x005b}, {0x6001, 0x005c}, {0x6082, 0x00d3}, |
183 | {0x6000, 0x008e}, | 152 | {0x6000, 0x008e}, |
184 | }; | 153 | }; |
185 | 154 | ||
186 | static struct validx tbl_big_c[] = { | 155 | static struct validx tbl_big3[] = { |
187 | {0x6004, 0x00da}, {0x6000, 0x00e0}, {0x6067, 0x00e1}, {0x60ff, 0x00dd}, | 156 | {0x6004, 0x00da}, {0x6000, 0x00e0}, {0x6067, 0x00e1}, {0x60ff, 0x00dd}, |
188 | {0x6001, 0x00ff}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, | 157 | {0x6001, 0x00ff}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, |
189 | {0x6001, 0x00ff}, {0x6000, 0x0011}, {0x6000, 0x00ff}, {0x6010, 0x00c7}, | 158 | {0x6001, 0x00ff}, {0x6000, 0x0011}, {0x6000, 0x00ff}, {0x6010, 0x00c7}, |
@@ -223,17 +192,19 @@ void ov2640_init_settings(struct gspca_dev *gspca_dev) | |||
223 | sd->vcur.hue = 0; | 192 | sd->vcur.hue = 0; |
224 | sd->vcur.saturation = 128; | 193 | sd->vcur.saturation = 128; |
225 | sd->vcur.whitebal = 64; | 194 | sd->vcur.whitebal = 64; |
195 | sd->vcur.mirror = 0; | ||
196 | sd->vcur.flip = 0; | ||
226 | 197 | ||
227 | sd->vmax.backlight = 64; | 198 | sd->vmax.backlight = 64; |
228 | sd->vmax.brightness = 255; | 199 | sd->vmax.brightness = 255; |
229 | sd->vmax.sharpness = 31; | 200 | sd->vmax.sharpness = 31; |
230 | sd->vmax.contrast = 255; | 201 | sd->vmax.contrast = 255; |
231 | sd->vmax.gamma = 64; | 202 | sd->vmax.gamma = 64; |
232 | sd->vmax.hue = 255 + 1; | 203 | sd->vmax.hue = 254 + 2; |
233 | sd->vmax.saturation = 255; | 204 | sd->vmax.saturation = 255; |
234 | sd->vmax.whitebal = 128; | 205 | sd->vmax.whitebal = 128; |
235 | sd->vmax.mirror = 0; | 206 | sd->vmax.mirror = 1; |
236 | sd->vmax.flip = 0; | 207 | sd->vmax.flip = 1; |
237 | sd->vmax.AC50Hz = 0; | 208 | sd->vmax.AC50Hz = 0; |
238 | 209 | ||
239 | sd->dev_camera_settings = ov2640_camera_settings; | 210 | sd->dev_camera_settings = ov2640_camera_settings; |
@@ -259,11 +230,11 @@ static int ov2640_init_at_startup(struct gspca_dev *gspca_dev) | |||
259 | 230 | ||
260 | common(gspca_dev); | 231 | common(gspca_dev); |
261 | 232 | ||
262 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0006, 1, dat_init2); | 233 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0006, 1, c61); |
263 | 234 | ||
264 | ctrl_out(gspca_dev, 0x40, 1, 0x00ef, 0x0006, 0, NULL); | 235 | ctrl_out(gspca_dev, 0x40, 1, 0x00ef, 0x0006, 0, NULL); |
265 | 236 | ||
266 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, dat_init3); | 237 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c51); |
267 | 238 | ||
268 | ctrl_out(gspca_dev, 0x40, 1, 0x0051, 0x0000, 0, NULL); | 239 | ctrl_out(gspca_dev, 0x40, 1, 0x0051, 0x0000, 0, NULL); |
269 | /* ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL); */ | 240 | /* ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL); */ |
@@ -275,6 +246,8 @@ static int ov2640_init_pre_alt(struct gspca_dev *gspca_dev) | |||
275 | { | 246 | { |
276 | struct sd *sd = (struct sd *) gspca_dev; | 247 | struct sd *sd = (struct sd *) gspca_dev; |
277 | 248 | ||
249 | sd->mirrorMask = 0; | ||
250 | |||
278 | sd->vold.backlight = -1; | 251 | sd->vold.backlight = -1; |
279 | sd->vold.brightness = -1; | 252 | sd->vold.brightness = -1; |
280 | sd->vold.sharpness = -1; | 253 | sd->vold.sharpness = -1; |
@@ -283,6 +256,8 @@ static int ov2640_init_pre_alt(struct gspca_dev *gspca_dev) | |||
283 | sd->vold.gamma = -1; | 256 | sd->vold.gamma = -1; |
284 | sd->vold.hue = -1; | 257 | sd->vold.hue = -1; |
285 | sd->vold.whitebal = -1; | 258 | sd->vold.whitebal = -1; |
259 | sd->vold.mirror = -1; | ||
260 | sd->vold.flip = -1; | ||
286 | 261 | ||
287 | ov2640_init_post_alt(gspca_dev); | 262 | ov2640_init_post_alt(gspca_dev); |
288 | 263 | ||
@@ -292,16 +267,16 @@ static int ov2640_init_pre_alt(struct gspca_dev *gspca_dev) | |||
292 | static int ov2640_init_post_alt(struct gspca_dev *gspca_dev) | 267 | static int ov2640_init_post_alt(struct gspca_dev *gspca_dev) |
293 | { | 268 | { |
294 | s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; | 269 | s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; |
295 | s32 n; /* reserved for FETCH macros */ | 270 | s32 n; /* reserved for FETCH functions */ |
296 | 271 | ||
297 | ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL); | 272 | ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL); |
298 | 273 | ||
299 | n = fetch_validx(gspca_dev, tbl_sensor_settings_common_a, | 274 | n = fetch_validx(gspca_dev, tbl_sensor_settings_common1, |
300 | ARRAY_SIZE(tbl_sensor_settings_common_a)); | 275 | ARRAY_SIZE(tbl_sensor_settings_common1)); |
301 | ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_post); | 276 | ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_post); |
302 | common(gspca_dev); | 277 | common(gspca_dev); |
303 | keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common_a, | 278 | keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common1, |
304 | ARRAY_SIZE(tbl_sensor_settings_common_a), n); | 279 | ARRAY_SIZE(tbl_sensor_settings_common1), n); |
305 | 280 | ||
306 | switch (reso) { | 281 | switch (reso) { |
307 | case IMAGE_640: | 282 | case IMAGE_640: |
@@ -316,18 +291,18 @@ static int ov2640_init_post_alt(struct gspca_dev *gspca_dev) | |||
316 | 291 | ||
317 | case IMAGE_1600: | 292 | case IMAGE_1600: |
318 | case IMAGE_1280: | 293 | case IMAGE_1280: |
319 | n = fetch_validx(gspca_dev, tbl_big_a, ARRAY_SIZE(tbl_big_a)); | 294 | n = fetch_validx(gspca_dev, tbl_big1, ARRAY_SIZE(tbl_big1)); |
320 | 295 | ||
321 | if (reso == IMAGE_1280) { | 296 | if (reso == IMAGE_1280) { |
322 | n = fetch_validx(gspca_dev, tbl_big_b, | 297 | n = fetch_validx(gspca_dev, tbl_big2, |
323 | ARRAY_SIZE(tbl_big_b)); | 298 | ARRAY_SIZE(tbl_big2)); |
324 | } else { | 299 | } else { |
325 | ctrl_out(gspca_dev, 0x40, 1, 0x601d, 0x0086, 0, NULL); | 300 | ctrl_out(gspca_dev, 0x40, 1, 0x601d, 0x0086, 0, NULL); |
326 | ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00d7, 0, NULL); | 301 | ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00d7, 0, NULL); |
327 | ctrl_out(gspca_dev, 0x40, 1, 0x6082, 0x00d3, 0, NULL); | 302 | ctrl_out(gspca_dev, 0x40, 1, 0x6082, 0x00d3, 0, NULL); |
328 | } | 303 | } |
329 | 304 | ||
330 | n = fetch_validx(gspca_dev, tbl_big_c, ARRAY_SIZE(tbl_big_c)); | 305 | n = fetch_validx(gspca_dev, tbl_big3, ARRAY_SIZE(tbl_big3)); |
331 | 306 | ||
332 | if (reso == IMAGE_1280) { | 307 | if (reso == IMAGE_1280) { |
333 | ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL); | 308 | ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL); |
@@ -343,20 +318,8 @@ static int ov2640_init_post_alt(struct gspca_dev *gspca_dev) | |||
343 | break; | 318 | break; |
344 | } | 319 | } |
345 | 320 | ||
346 | n = fetch_validx(gspca_dev, tbl_sensor_settings_common_b, | 321 | n = fetch_validx(gspca_dev, tbl_sensor_settings_common2, |
347 | ARRAY_SIZE(tbl_sensor_settings_common_b)); | 322 | ARRAY_SIZE(tbl_sensor_settings_common2)); |
348 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c50); | ||
349 | keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common_b, | ||
350 | ARRAY_SIZE(tbl_sensor_settings_common_b), n); | ||
351 | ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, c28); | ||
352 | keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common_b, | ||
353 | ARRAY_SIZE(tbl_sensor_settings_common_b), n); | ||
354 | ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, ca8); | ||
355 | keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common_b, | ||
356 | ARRAY_SIZE(tbl_sensor_settings_common_b), n); | ||
357 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c50); | ||
358 | keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common_b, | ||
359 | ARRAY_SIZE(tbl_sensor_settings_common_b), n); | ||
360 | 323 | ||
361 | ov2640_camera_settings(gspca_dev); | 324 | ov2640_camera_settings(gspca_dev); |
362 | 325 | ||
@@ -393,18 +356,20 @@ static int ov2640_camera_settings(struct gspca_dev *gspca_dev) | |||
393 | s32 sat = sd->vcur.saturation; | 356 | s32 sat = sd->vcur.saturation; |
394 | s32 hue = sd->vcur.hue; | 357 | s32 hue = sd->vcur.hue; |
395 | s32 wbal = sd->vcur.whitebal; | 358 | s32 wbal = sd->vcur.whitebal; |
359 | s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) == 0); | ||
360 | s32 flip = (((sd->vcur.flip > 0) ^ sd->mirrorMask) == 0); | ||
396 | 361 | ||
397 | if (backlight != sd->vold.backlight) { | 362 | if (backlight != sd->vold.backlight) { |
363 | /* No sd->vold.backlight=backlight; (to be done again later) */ | ||
398 | if (backlight < 0 || backlight > sd->vmax.backlight) | 364 | if (backlight < 0 || backlight > sd->vmax.backlight) |
399 | backlight = 0; | 365 | backlight = 0; |
400 | 366 | ||
401 | ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x00ff, | 367 | ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x00ff, |
402 | 0, NULL); | 368 | 0, NULL); |
403 | ctrl_out(gspca_dev, 0x40, 1, 0x601f + backlight , 0x0024, | 369 | ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight , 0x0024, |
404 | 0, NULL); | 370 | 0, NULL); |
405 | ctrl_out(gspca_dev, 0x40, 1, 0x601f + backlight - 10, 0x0025, | 371 | ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight - 10, 0x0025, |
406 | 0, NULL); | 372 | 0, NULL); |
407 | /* No sd->vold.backlight=backlight; (to be done again later) */ | ||
408 | } | 373 | } |
409 | 374 | ||
410 | if (bright != sd->vold.brightness) { | 375 | if (bright != sd->vold.brightness) { |
@@ -466,7 +431,7 @@ static int ov2640_camera_settings(struct gspca_dev *gspca_dev) | |||
466 | ctrl_out(gspca_dev, 0x40, 1, 0x6002 , 0x007c, 0, NULL); | 431 | ctrl_out(gspca_dev, 0x40, 1, 0x6002 , 0x007c, 0, NULL); |
467 | ctrl_out(gspca_dev, 0x40, 1, 0x6000 + hue * (hue < 255), 0x007d, | 432 | ctrl_out(gspca_dev, 0x40, 1, 0x6000 + hue * (hue < 255), 0x007d, |
468 | 0, NULL); | 433 | 0, NULL); |
469 | if (hue >= sd->vmax.hue) | 434 | if (hue >= 255) |
470 | sd->swapRB = 1; | 435 | sd->swapRB = 1; |
471 | else | 436 | else |
472 | sd->swapRB = 0; | 437 | sd->swapRB = 0; |
@@ -482,14 +447,33 @@ static int ov2640_camera_settings(struct gspca_dev *gspca_dev) | |||
482 | ctrl_out(gspca_dev, 0x40, 1, 0x6000 + gam, 0x007d, 0, NULL); | 447 | ctrl_out(gspca_dev, 0x40, 1, 0x6000 + gam, 0x007d, 0, NULL); |
483 | } | 448 | } |
484 | 449 | ||
450 | if (mirror != sd->vold.mirror || flip != sd->vold.flip) { | ||
451 | sd->vold.mirror = mirror; | ||
452 | sd->vold.flip = flip; | ||
453 | |||
454 | mirror = 0x80 * mirror; | ||
455 | ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL); | ||
456 | ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x8004, 0, NULL); | ||
457 | ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, c28); | ||
458 | ctrl_out(gspca_dev, 0x40, 1, 0x6028 + mirror, 0x0004, 0, NULL); | ||
459 | |||
460 | flip = 0x50 * flip + mirror; | ||
461 | ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL); | ||
462 | ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x8004, 0, NULL); | ||
463 | ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, ca8); | ||
464 | ctrl_out(gspca_dev, 0x40, 1, 0x6028 + flip, 0x0004, 0, NULL); | ||
465 | |||
466 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c50); | ||
467 | } | ||
468 | |||
485 | if (backlight != sd->vold.backlight) { | 469 | if (backlight != sd->vold.backlight) { |
486 | sd->vold.backlight = backlight; | 470 | sd->vold.backlight = backlight; |
487 | 471 | ||
488 | ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x00ff, | 472 | ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x00ff, |
489 | 0, NULL); | 473 | 0, NULL); |
490 | ctrl_out(gspca_dev, 0x40, 1, 0x601f + backlight , 0x0024, | 474 | ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight , 0x0024, |
491 | 0, NULL); | 475 | 0, NULL); |
492 | ctrl_out(gspca_dev, 0x40, 1, 0x601f + backlight - 10, 0x0025, | 476 | ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight - 10, 0x0025, |
493 | 0, NULL); | 477 | 0, NULL); |
494 | } | 478 | } |
495 | 479 | ||
diff --git a/drivers/media/video/gspca/gl860/gl860-ov9655.c b/drivers/media/video/gspca/gl860/gl860-ov9655.c index eda3346f939c..d412694c50af 100644 --- a/drivers/media/video/gspca/gl860/gl860-ov9655.c +++ b/drivers/media/video/gspca/gl860/gl860-ov9655.c | |||
@@ -1,7 +1,6 @@ | |||
1 | /* @file gl860-ov9655.c | 1 | /* Subdriver for the GL860 chip with the OV9655 sensor |
2 | * @author Olivier LORIN, from logs done by Simon (Sur3) and Almighurt | 2 | * Author Olivier LORIN, from logs done by Simon (Sur3) and Almighurt |
3 | * on dsd's weblog | 3 | * on dsd's weblog |
4 | * @date 2009-08-27 | ||
5 | * | 4 | * |
6 | * This program is free software; you can redistribute it and/or modify | 5 | * 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 | 6 | * it under the terms of the GNU General Public License as published by |
@@ -104,14 +103,14 @@ static u8 *tbl_800[] = { | |||
104 | }; | 103 | }; |
105 | 104 | ||
106 | static u8 c04[] = {0x04}; | 105 | static u8 c04[] = {0x04}; |
107 | static u8 dat_post_1[] = "\x04\x00\x10\x20\xa1\x00\x00\x02"; | 106 | static u8 dat_post1[] = "\x04\x00\x10\x20\xa1\x00\x00\x02"; |
108 | static u8 dat_post_2[] = "\x10\x10\xc1\x02"; | 107 | static u8 dat_post2[] = "\x10\x10\xc1\x02"; |
109 | static u8 dat_post_3[] = "\x04\x00\x10\x7c\xa1\x00\x00\x04"; | 108 | static u8 dat_post3[] = "\x04\x00\x10\x7c\xa1\x00\x00\x04"; |
110 | static u8 dat_post_4[] = "\x10\x02\xc1\x06"; | 109 | static u8 dat_post4[] = "\x10\x02\xc1\x06"; |
111 | static u8 dat_post_5[] = "\x04\x00\x10\x7b\xa1\x00\x00\x08"; | 110 | static u8 dat_post5[] = "\x04\x00\x10\x7b\xa1\x00\x00\x08"; |
112 | static u8 dat_post_6[] = "\x10\x10\xc1\x05"; | 111 | static u8 dat_post6[] = "\x10\x10\xc1\x05"; |
113 | static u8 dat_post_7[] = "\x04\x00\x10\x7c\xa1\x00\x00\x08"; | 112 | static u8 dat_post7[] = "\x04\x00\x10\x7c\xa1\x00\x00\x08"; |
114 | static u8 dat_post_8[] = "\x04\x00\x10\x7c\xa1\x00\x00\x09"; | 113 | static u8 dat_post8[] = "\x04\x00\x10\x7c\xa1\x00\x00\x09"; |
115 | 114 | ||
116 | static struct validx tbl_init_post_alt[] = { | 115 | static struct validx tbl_init_post_alt[] = { |
117 | {0x6032, 0x00ff}, {0x6032, 0x00ff}, {0x6032, 0x00ff}, {0x603c, 0x00ff}, | 116 | {0x6032, 0x00ff}, {0x6032, 0x00ff}, {0x6032, 0x00ff}, {0x603c, 0x00ff}, |
@@ -212,7 +211,7 @@ static int ov9655_init_pre_alt(struct gspca_dev *gspca_dev) | |||
212 | static int ov9655_init_post_alt(struct gspca_dev *gspca_dev) | 211 | static int ov9655_init_post_alt(struct gspca_dev *gspca_dev) |
213 | { | 212 | { |
214 | s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; | 213 | s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; |
215 | s32 n; /* reserved for FETCH macros */ | 214 | s32 n; /* reserved for FETCH functions */ |
216 | s32 i; | 215 | s32 i; |
217 | u8 **tbl; | 216 | u8 **tbl; |
218 | 217 | ||
@@ -243,7 +242,7 @@ static int ov9655_init_post_alt(struct gspca_dev *gspca_dev) | |||
243 | ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04); | 242 | ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04); |
244 | keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, | 243 | keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, |
245 | ARRAY_SIZE(tbl_init_post_alt), n); | 244 | ARRAY_SIZE(tbl_init_post_alt), n); |
246 | ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post_1); | 245 | ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post1); |
247 | keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, | 246 | keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, |
248 | ARRAY_SIZE(tbl_init_post_alt), n); | 247 | ARRAY_SIZE(tbl_init_post_alt), n); |
249 | 248 | ||
@@ -259,7 +258,7 @@ static int ov9655_init_post_alt(struct gspca_dev *gspca_dev) | |||
259 | ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04); | 258 | ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04); |
260 | keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, | 259 | keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, |
261 | ARRAY_SIZE(tbl_init_post_alt), n); | 260 | ARRAY_SIZE(tbl_init_post_alt), n); |
262 | ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post_1); | 261 | ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post1); |
263 | keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, | 262 | keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, |
264 | ARRAY_SIZE(tbl_init_post_alt), n); | 263 | ARRAY_SIZE(tbl_init_post_alt), n); |
265 | 264 | ||
@@ -270,18 +269,18 @@ static int ov9655_init_post_alt(struct gspca_dev *gspca_dev) | |||
270 | keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, | 269 | keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, |
271 | ARRAY_SIZE(tbl_init_post_alt), n); | 270 | ARRAY_SIZE(tbl_init_post_alt), n); |
272 | 271 | ||
273 | ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post_1); | 272 | ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post1); |
274 | 273 | ||
275 | ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post_2); | 274 | ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post2); |
276 | ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post_3); | 275 | ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post3); |
277 | 276 | ||
278 | ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post_4); | 277 | ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post4); |
279 | ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post_5); | 278 | ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post5); |
280 | 279 | ||
281 | ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post_6); | 280 | ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post6); |
282 | ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post_7); | 281 | ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post7); |
283 | 282 | ||
284 | ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post_8); | 283 | ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post8); |
285 | 284 | ||
286 | ov9655_camera_settings(gspca_dev); | 285 | ov9655_camera_settings(gspca_dev); |
287 | 286 | ||
diff --git a/drivers/media/video/gspca/gl860/gl860.c b/drivers/media/video/gspca/gl860/gl860.c index 6ef59ac7f502..a695e0ae13c2 100644 --- a/drivers/media/video/gspca/gl860/gl860.c +++ b/drivers/media/video/gspca/gl860/gl860.c | |||
@@ -1,9 +1,7 @@ | |||
1 | /* @file gl860.c | 1 | /* GSPCA subdrivers for Genesys Logic webcams with the GL860 chip |
2 | * @date 2009-08-27 | 2 | * Subdriver core |
3 | * | 3 | * |
4 | * Genesys Logic webcam with gl860 subdrivers | 4 | * 2009/09/24 Olivier Lorin <o.lorin@laposte.net> |
5 | * | ||
6 | * Driver by Olivier Lorin <o.lorin@laposte.net> | ||
7 | * GSPCA by Jean-Francois Moine <http://moinejf.free.fr> | 5 | * GSPCA by Jean-Francois Moine <http://moinejf.free.fr> |
8 | * Thanks BUGabundo and Malmostoso for your amazing help! | 6 | * Thanks BUGabundo and Malmostoso for your amazing help! |
9 | * | 7 | * |
@@ -23,8 +21,8 @@ | |||
23 | #include "gspca.h" | 21 | #include "gspca.h" |
24 | #include "gl860.h" | 22 | #include "gl860.h" |
25 | 23 | ||
26 | MODULE_AUTHOR("Olivier Lorin <lorin@laposte.net>"); | 24 | MODULE_AUTHOR("Olivier Lorin <o.lorin@laposte.net>"); |
27 | MODULE_DESCRIPTION("GSPCA/Genesys Logic GL860 USB Camera Driver"); | 25 | MODULE_DESCRIPTION("Genesys Logic USB PC Camera Driver"); |
28 | MODULE_LICENSE("GPL"); | 26 | MODULE_LICENSE("GPL"); |
29 | 27 | ||
30 | /*======================== static function declarations ====================*/ | 28 | /*======================== static function declarations ====================*/ |
@@ -38,7 +36,7 @@ static int sd_isoc_init(struct gspca_dev *gspca_dev); | |||
38 | static int sd_start(struct gspca_dev *gspca_dev); | 36 | static int sd_start(struct gspca_dev *gspca_dev); |
39 | static void sd_stop0(struct gspca_dev *gspca_dev); | 37 | static void sd_stop0(struct gspca_dev *gspca_dev); |
40 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 38 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
41 | struct gspca_frame *frame, u8 *data, s32 len); | 39 | u8 *data, int len); |
42 | static void sd_callback(struct gspca_dev *gspca_dev); | 40 | static void sd_callback(struct gspca_dev *gspca_dev); |
43 | 41 | ||
44 | static int gl860_guess_sensor(struct gspca_dev *gspca_dev, | 42 | static int gl860_guess_sensor(struct gspca_dev *gspca_dev, |
@@ -53,7 +51,7 @@ MODULE_PARM_DESC(AC50Hz, " Does AC power frequency is 50Hz? (0/1)"); | |||
53 | static char sensor[7]; | 51 | static char sensor[7]; |
54 | module_param_string(sensor, sensor, sizeof(sensor), 0644); | 52 | module_param_string(sensor, sensor, sizeof(sensor), 0644); |
55 | MODULE_PARM_DESC(sensor, | 53 | MODULE_PARM_DESC(sensor, |
56 | " Driver sensor ('MI1320'/'MI2020'/'OV9655'/'OV2640'/'')"); | 54 | " Driver sensor ('MI1320'/'MI2020'/'OV9655'/'OV2640')"); |
57 | 55 | ||
58 | /*============================ webcam controls =============================*/ | 56 | /*============================ webcam controls =============================*/ |
59 | 57 | ||
@@ -156,7 +154,7 @@ static int gl860_build_control_table(struct gspca_dev *gspca_dev) | |||
156 | SET_MY_CTRL(V4L2_CID_VFLIP, | 154 | SET_MY_CTRL(V4L2_CID_VFLIP, |
157 | V4L2_CTRL_TYPE_BOOLEAN, "Flip", flip) | 155 | V4L2_CTRL_TYPE_BOOLEAN, "Flip", flip) |
158 | SET_MY_CTRL(V4L2_CID_POWER_LINE_FREQUENCY, | 156 | SET_MY_CTRL(V4L2_CID_POWER_LINE_FREQUENCY, |
159 | V4L2_CTRL_TYPE_BOOLEAN, "50Hz", AC50Hz) | 157 | V4L2_CTRL_TYPE_BOOLEAN, "AC power 50Hz", AC50Hz) |
160 | 158 | ||
161 | return nCtrls; | 159 | return nCtrls; |
162 | } | 160 | } |
@@ -435,7 +433,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
435 | 433 | ||
436 | /* This function is called when an image is being received */ | 434 | /* This function is called when an image is being received */ |
437 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 435 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
438 | struct gspca_frame *frame, u8 *data, s32 len) | 436 | u8 *data, int len) |
439 | { | 437 | { |
440 | struct sd *sd = (struct sd *) gspca_dev; | 438 | struct sd *sd = (struct sd *) gspca_dev; |
441 | static s32 nSkipped; | 439 | static s32 nSkipped; |
@@ -447,11 +445,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
447 | /* Test only against 0202h, so endianess does not matter */ | 445 | /* Test only against 0202h, so endianess does not matter */ |
448 | switch (*(s16 *) data) { | 446 | switch (*(s16 *) data) { |
449 | case 0x0202: /* End of frame, start a new one */ | 447 | case 0x0202: /* End of frame, start a new one */ |
450 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); | 448 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); |
451 | nSkipped = 0; | 449 | nSkipped = 0; |
452 | if (sd->nbIm >= 0 && sd->nbIm < 10) | 450 | if (sd->nbIm >= 0 && sd->nbIm < 10) |
453 | sd->nbIm++; | 451 | sd->nbIm++; |
454 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, 0); | 452 | gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); |
455 | break; | 453 | break; |
456 | 454 | ||
457 | default: | 455 | default: |
@@ -466,7 +464,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
466 | nSkipped = nToSkip + 1; | 464 | nSkipped = nToSkip + 1; |
467 | } | 465 | } |
468 | gspca_frame_add(gspca_dev, | 466 | gspca_frame_add(gspca_dev, |
469 | INTER_PACKET, frame, data, len); | 467 | INTER_PACKET, data, len); |
470 | } | 468 | } |
471 | break; | 469 | break; |
472 | } | 470 | } |
@@ -702,6 +700,7 @@ static int gl860_guess_sensor(struct gspca_dev *gspca_dev, | |||
702 | ctrl_out(gspca_dev, 0x40, 1, 0x006a, 0x000d, 0, NULL); | 700 | ctrl_out(gspca_dev, 0x40, 1, 0x006a, 0x000d, 0, NULL); |
703 | msleep(56); | 701 | msleep(56); |
704 | 702 | ||
703 | PDEBUG(D_PROBE, "probing for sensor MI2020 or OVXXXX"); | ||
705 | nOV = 0; | 704 | nOV = 0; |
706 | for (ntry = 0; ntry < 4; ntry++) { | 705 | for (ntry = 0; ntry < 4; ntry++) { |
707 | ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL); | 706 | ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL); |
@@ -711,14 +710,14 @@ static int gl860_guess_sensor(struct gspca_dev *gspca_dev, | |||
711 | ctrl_out(gspca_dev, 0x40, 1, 0x7a00, 0x8030, 0, NULL); | 710 | ctrl_out(gspca_dev, 0x40, 1, 0x7a00, 0x8030, 0, NULL); |
712 | msleep(10); | 711 | msleep(10); |
713 | ctrl_in(gspca_dev, 0xc0, 2, 0x7a00, 0x8030, 1, &probe); | 712 | ctrl_in(gspca_dev, 0xc0, 2, 0x7a00, 0x8030, 1, &probe); |
714 | PDEBUG(D_PROBE, "1st probe=%02x", probe); | 713 | PDEBUG(D_PROBE, "probe=0x%02x", probe); |
715 | if (probe == 0xff) | 714 | if (probe == 0xff) |
716 | nOV++; | 715 | nOV++; |
717 | } | 716 | } |
718 | 717 | ||
719 | if (nOV) { | 718 | if (nOV) { |
720 | PDEBUG(D_PROBE, "0xff -> sensor OVXXXX"); | 719 | PDEBUG(D_PROBE, "0xff -> OVXXXX"); |
721 | PDEBUG(D_PROBE, "Probing for sensor OV2640 or OV9655"); | 720 | PDEBUG(D_PROBE, "probing for sensor OV2640 or OV9655"); |
722 | 721 | ||
723 | nb26 = nb96 = 0; | 722 | nb26 = nb96 = 0; |
724 | for (ntry = 0; ntry < 4; ntry++) { | 723 | for (ntry = 0; ntry < 4; ntry++) { |
@@ -728,40 +727,38 @@ static int gl860_guess_sensor(struct gspca_dev *gspca_dev, | |||
728 | ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x800a, | 727 | ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x800a, |
729 | 0, NULL); | 728 | 0, NULL); |
730 | msleep(10); | 729 | msleep(10); |
730 | |||
731 | /* Wait for 26(OV2640) or 96(OV9655) */ | 731 | /* Wait for 26(OV2640) or 96(OV9655) */ |
732 | ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x800a, | 732 | ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x800a, |
733 | 1, &probe); | 733 | 1, &probe); |
734 | 734 | ||
735 | PDEBUG(D_PROBE, "2nd probe=%02x", probe); | ||
736 | if (probe == 0x00) | ||
737 | nb26++; | ||
738 | if (probe == 0x26 || probe == 0x40) { | 735 | if (probe == 0x26 || probe == 0x40) { |
736 | PDEBUG(D_PROBE, | ||
737 | "probe=0x%02x -> OV2640", | ||
738 | probe); | ||
739 | sd->sensor = ID_OV2640; | 739 | sd->sensor = ID_OV2640; |
740 | nb26 += 4; | 740 | nb26 += 4; |
741 | break; | 741 | break; |
742 | } | 742 | } |
743 | if (probe == 0x96 || probe == 0x55) { | 743 | if (probe == 0x96 || probe == 0x55) { |
744 | PDEBUG(D_PROBE, | ||
745 | "probe=0x%02x -> OV9655", | ||
746 | probe); | ||
744 | sd->sensor = ID_OV9655; | 747 | sd->sensor = ID_OV9655; |
745 | nb96 += 4; | 748 | nb96 += 4; |
746 | break; | 749 | break; |
747 | } | 750 | } |
751 | PDEBUG(D_PROBE, "probe=0x%02x", probe); | ||
752 | if (probe == 0x00) | ||
753 | nb26++; | ||
748 | if (probe == 0xff) | 754 | if (probe == 0xff) |
749 | nb96++; | 755 | nb96++; |
750 | msleep(3); | 756 | msleep(3); |
751 | } | 757 | } |
752 | if (nb26 < 4 && nb96 < 4) { | 758 | if (nb26 < 4 && nb96 < 4) |
753 | PDEBUG(D_PROBE, "No relevant answer "); | ||
754 | PDEBUG(D_PROBE, "* 1.3Mpixels -> use OV9655"); | ||
755 | PDEBUG(D_PROBE, "* 2.0Mpixels -> use OV2640"); | ||
756 | PDEBUG(D_PROBE, | ||
757 | "To force a sensor, add that line to " | ||
758 | "/etc/modprobe.d/options.conf:"); | ||
759 | PDEBUG(D_PROBE, "options gspca_gl860 " | ||
760 | "sensor=\"OV2640\" or \"OV9655\""); | ||
761 | return -1; | 759 | return -1; |
762 | } | 760 | } else { |
763 | } else { /* probe = 0 */ | 761 | PDEBUG(D_PROBE, "Not any 0xff -> MI2020"); |
764 | PDEBUG(D_PROBE, "No 0xff -> sensor MI2020"); | ||
765 | sd->sensor = ID_MI2020; | 762 | sd->sensor = ID_MI2020; |
766 | } | 763 | } |
767 | } | 764 | } |
diff --git a/drivers/media/video/gspca/gl860/gl860.h b/drivers/media/video/gspca/gl860/gl860.h index cef4e24c1e61..305061ff8387 100644 --- a/drivers/media/video/gspca/gl860/gl860.h +++ b/drivers/media/video/gspca/gl860/gl860.h | |||
@@ -1,6 +1,7 @@ | |||
1 | /* @file gl860.h | 1 | /* GSPCA subdrivers for Genesys Logic webcams with the GL860 chip |
2 | * @author Olivier LORIN, tiré du pilote Syntek par Nicolas VIVIEN | 2 | * Subdriver declarations |
3 | * @date 2009-08-27 | 3 | * |
4 | * 2009/10/14 Olivier LORIN <o.lorin@laposte.net> | ||
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 |
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 23d3fb776918..4076f8e5a6fc 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -47,7 +47,7 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | |||
47 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); | 47 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); |
48 | MODULE_LICENSE("GPL"); | 48 | MODULE_LICENSE("GPL"); |
49 | 49 | ||
50 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 7, 0) | 50 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 8, 0) |
51 | 51 | ||
52 | #ifdef GSPCA_DEBUG | 52 | #ifdef GSPCA_DEBUG |
53 | int gspca_debug = D_ERR | D_PROBE; | 53 | int gspca_debug = D_ERR | D_PROBE; |
@@ -74,7 +74,7 @@ static void PDEBUG_MODE(char *txt, __u32 pixfmt, int w, int h) | |||
74 | #define PDEBUG_MODE(txt, pixfmt, w, h) | 74 | #define PDEBUG_MODE(txt, pixfmt, w, h) |
75 | #endif | 75 | #endif |
76 | 76 | ||
77 | /* specific memory types - !! should different from V4L2_MEMORY_xxx */ | 77 | /* specific memory types - !! should be different from V4L2_MEMORY_xxx */ |
78 | #define GSPCA_MEMORY_NO 0 /* V4L2_MEMORY_xxx starts from 1 */ | 78 | #define GSPCA_MEMORY_NO 0 /* V4L2_MEMORY_xxx starts from 1 */ |
79 | #define GSPCA_MEMORY_READ 7 | 79 | #define GSPCA_MEMORY_READ 7 |
80 | 80 | ||
@@ -126,7 +126,6 @@ EXPORT_SYMBOL(gspca_get_i_frame); | |||
126 | static void fill_frame(struct gspca_dev *gspca_dev, | 126 | static void fill_frame(struct gspca_dev *gspca_dev, |
127 | struct urb *urb) | 127 | struct urb *urb) |
128 | { | 128 | { |
129 | struct gspca_frame *frame; | ||
130 | u8 *data; /* address of data in the iso message */ | 129 | u8 *data; /* address of data in the iso message */ |
131 | int i, len, st; | 130 | int i, len, st; |
132 | cam_pkt_op pkt_scan; | 131 | cam_pkt_op pkt_scan; |
@@ -135,21 +134,16 @@ static void fill_frame(struct gspca_dev *gspca_dev, | |||
135 | if (urb->status == -ESHUTDOWN) | 134 | if (urb->status == -ESHUTDOWN) |
136 | return; /* disconnection */ | 135 | return; /* disconnection */ |
137 | #ifdef CONFIG_PM | 136 | #ifdef CONFIG_PM |
138 | if (!gspca_dev->frozen) | 137 | if (gspca_dev->frozen) |
138 | return; | ||
139 | #endif | 139 | #endif |
140 | PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); | 140 | PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); |
141 | return; | 141 | urb->status = 0; |
142 | goto resubmit; | ||
142 | } | 143 | } |
143 | pkt_scan = gspca_dev->sd_desc->pkt_scan; | 144 | pkt_scan = gspca_dev->sd_desc->pkt_scan; |
144 | for (i = 0; i < urb->number_of_packets; i++) { | 145 | for (i = 0; i < urb->number_of_packets; i++) { |
145 | 146 | ||
146 | /* check the availability of the frame buffer */ | ||
147 | frame = gspca_get_i_frame(gspca_dev); | ||
148 | if (!frame) { | ||
149 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
150 | break; | ||
151 | } | ||
152 | |||
153 | /* check the packet status and length */ | 147 | /* check the packet status and length */ |
154 | len = urb->iso_frame_desc[i].actual_length; | 148 | len = urb->iso_frame_desc[i].actual_length; |
155 | if (len == 0) { | 149 | if (len == 0) { |
@@ -171,9 +165,10 @@ static void fill_frame(struct gspca_dev *gspca_dev, | |||
171 | i, urb->iso_frame_desc[i].offset, len); | 165 | i, urb->iso_frame_desc[i].offset, len); |
172 | data = (u8 *) urb->transfer_buffer | 166 | data = (u8 *) urb->transfer_buffer |
173 | + urb->iso_frame_desc[i].offset; | 167 | + urb->iso_frame_desc[i].offset; |
174 | pkt_scan(gspca_dev, frame, data, len); | 168 | pkt_scan(gspca_dev, data, len); |
175 | } | 169 | } |
176 | 170 | ||
171 | resubmit: | ||
177 | /* resubmit the URB */ | 172 | /* resubmit the URB */ |
178 | st = usb_submit_urb(urb, GFP_ATOMIC); | 173 | st = usb_submit_urb(urb, GFP_ATOMIC); |
179 | if (st < 0) | 174 | if (st < 0) |
@@ -201,7 +196,6 @@ static void isoc_irq(struct urb *urb) | |||
201 | static void bulk_irq(struct urb *urb) | 196 | static void bulk_irq(struct urb *urb) |
202 | { | 197 | { |
203 | struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; | 198 | struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; |
204 | struct gspca_frame *frame; | ||
205 | int st; | 199 | int st; |
206 | 200 | ||
207 | PDEBUG(D_PACK, "bulk irq"); | 201 | PDEBUG(D_PACK, "bulk irq"); |
@@ -212,29 +206,22 @@ static void bulk_irq(struct urb *urb) | |||
212 | break; | 206 | break; |
213 | case -ESHUTDOWN: | 207 | case -ESHUTDOWN: |
214 | return; /* disconnection */ | 208 | return; /* disconnection */ |
215 | case -ECONNRESET: | ||
216 | urb->status = 0; | ||
217 | break; | ||
218 | default: | 209 | default: |
219 | #ifdef CONFIG_PM | 210 | #ifdef CONFIG_PM |
220 | if (!gspca_dev->frozen) | 211 | if (gspca_dev->frozen) |
212 | return; | ||
221 | #endif | 213 | #endif |
222 | PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); | 214 | PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); |
223 | return; | 215 | urb->status = 0; |
216 | goto resubmit; | ||
224 | } | 217 | } |
225 | 218 | ||
226 | /* check the availability of the frame buffer */ | 219 | PDEBUG(D_PACK, "packet l:%d", urb->actual_length); |
227 | frame = gspca_get_i_frame(gspca_dev); | 220 | gspca_dev->sd_desc->pkt_scan(gspca_dev, |
228 | if (!frame) { | 221 | urb->transfer_buffer, |
229 | gspca_dev->last_packet_type = DISCARD_PACKET; | 222 | urb->actual_length); |
230 | } else { | ||
231 | PDEBUG(D_PACK, "packet l:%d", urb->actual_length); | ||
232 | gspca_dev->sd_desc->pkt_scan(gspca_dev, | ||
233 | frame, | ||
234 | urb->transfer_buffer, | ||
235 | urb->actual_length); | ||
236 | } | ||
237 | 223 | ||
224 | resubmit: | ||
238 | /* resubmit the URB */ | 225 | /* resubmit the URB */ |
239 | if (gspca_dev->cam.bulk_nurbs != 0) { | 226 | if (gspca_dev->cam.bulk_nurbs != 0) { |
240 | st = usb_submit_urb(urb, GFP_ATOMIC); | 227 | st = usb_submit_urb(urb, GFP_ATOMIC); |
@@ -255,24 +242,27 @@ static void bulk_irq(struct urb *urb) | |||
255 | * DISCARD_PACKET invalidates the whole frame. | 242 | * DISCARD_PACKET invalidates the whole frame. |
256 | * On LAST_PACKET, a new frame is returned. | 243 | * On LAST_PACKET, a new frame is returned. |
257 | */ | 244 | */ |
258 | struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, | 245 | void gspca_frame_add(struct gspca_dev *gspca_dev, |
259 | enum gspca_packet_type packet_type, | 246 | enum gspca_packet_type packet_type, |
260 | struct gspca_frame *frame, | 247 | const u8 *data, |
261 | const __u8 *data, | 248 | int len) |
262 | int len) | ||
263 | { | 249 | { |
250 | struct gspca_frame *frame; | ||
264 | int i, j; | 251 | int i, j; |
265 | 252 | ||
266 | PDEBUG(D_PACK, "add t:%d l:%d", packet_type, len); | 253 | PDEBUG(D_PACK, "add t:%d l:%d", packet_type, len); |
267 | 254 | ||
255 | /* check the availability of the frame buffer */ | ||
256 | frame = gspca_dev->cur_frame; | ||
257 | if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) | ||
258 | != V4L2_BUF_FLAG_QUEUED) { | ||
259 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
260 | return; | ||
261 | } | ||
262 | |||
268 | /* when start of a new frame, if the current frame buffer | 263 | /* when start of a new frame, if the current frame buffer |
269 | * is not queued, discard the whole frame */ | 264 | * is not queued, discard the whole frame */ |
270 | if (packet_type == FIRST_PACKET) { | 265 | if (packet_type == FIRST_PACKET) { |
271 | if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) | ||
272 | != V4L2_BUF_FLAG_QUEUED) { | ||
273 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
274 | return frame; | ||
275 | } | ||
276 | frame->data_end = frame->data; | 266 | frame->data_end = frame->data; |
277 | jiffies_to_timeval(get_jiffies_64(), | 267 | jiffies_to_timeval(get_jiffies_64(), |
278 | &frame->v4l2_buf.timestamp); | 268 | &frame->v4l2_buf.timestamp); |
@@ -280,7 +270,7 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, | |||
280 | } else if (gspca_dev->last_packet_type == DISCARD_PACKET) { | 270 | } else if (gspca_dev->last_packet_type == DISCARD_PACKET) { |
281 | if (packet_type == LAST_PACKET) | 271 | if (packet_type == LAST_PACKET) |
282 | gspca_dev->last_packet_type = packet_type; | 272 | gspca_dev->last_packet_type = packet_type; |
283 | return frame; | 273 | return; |
284 | } | 274 | } |
285 | 275 | ||
286 | /* append the packet to the frame buffer */ | 276 | /* append the packet to the frame buffer */ |
@@ -312,9 +302,9 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, | |||
312 | i, | 302 | i, |
313 | gspca_dev->fr_o); | 303 | gspca_dev->fr_o); |
314 | j = gspca_dev->fr_queue[i]; | 304 | j = gspca_dev->fr_queue[i]; |
315 | frame = &gspca_dev->frame[j]; | 305 | gspca_dev->cur_frame = &gspca_dev->frame[j]; |
316 | } | 306 | } |
317 | return frame; | 307 | return; |
318 | } | 308 | } |
319 | EXPORT_SYMBOL(gspca_frame_add); | 309 | EXPORT_SYMBOL(gspca_frame_add); |
320 | 310 | ||
@@ -395,6 +385,7 @@ static int frame_alloc(struct gspca_dev *gspca_dev, | |||
395 | frame->v4l2_buf.m.offset = i * frsz; | 385 | frame->v4l2_buf.m.offset = i * frsz; |
396 | } | 386 | } |
397 | gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0; | 387 | gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0; |
388 | gspca_dev->cur_frame = &gspca_dev->frame[0]; | ||
398 | gspca_dev->last_packet_type = DISCARD_PACKET; | 389 | gspca_dev->last_packet_type = DISCARD_PACKET; |
399 | gspca_dev->sequence = 0; | 390 | gspca_dev->sequence = 0; |
400 | return 0; | 391 | return 0; |
@@ -475,10 +466,18 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) | |||
475 | xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK | 466 | xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK |
476 | : USB_ENDPOINT_XFER_ISOC; | 467 | : USB_ENDPOINT_XFER_ISOC; |
477 | i = gspca_dev->alt; /* previous alt setting */ | 468 | i = gspca_dev->alt; /* previous alt setting */ |
478 | while (--i >= 0) { | 469 | if (gspca_dev->cam.reverse_alts) { |
479 | ep = alt_xfer(&intf->altsetting[i], xfer); | 470 | while (++i < gspca_dev->nbalt) { |
480 | if (ep) | 471 | ep = alt_xfer(&intf->altsetting[i], xfer); |
481 | break; | 472 | if (ep) |
473 | break; | ||
474 | } | ||
475 | } else { | ||
476 | while (--i >= 0) { | ||
477 | ep = alt_xfer(&intf->altsetting[i], xfer); | ||
478 | if (ep) | ||
479 | break; | ||
480 | } | ||
482 | } | 481 | } |
483 | if (ep == NULL) { | 482 | if (ep == NULL) { |
484 | err("no transfer endpoint found"); | 483 | err("no transfer endpoint found"); |
@@ -599,7 +598,11 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
599 | 598 | ||
600 | /* set the higher alternate setting and | 599 | /* set the higher alternate setting and |
601 | * loop until urb submit succeeds */ | 600 | * loop until urb submit succeeds */ |
602 | gspca_dev->alt = gspca_dev->nbalt; | 601 | if (gspca_dev->cam.reverse_alts) |
602 | gspca_dev->alt = 0; | ||
603 | else | ||
604 | gspca_dev->alt = gspca_dev->nbalt; | ||
605 | |||
603 | if (gspca_dev->sd_desc->isoc_init) { | 606 | if (gspca_dev->sd_desc->isoc_init) { |
604 | ret = gspca_dev->sd_desc->isoc_init(gspca_dev); | 607 | ret = gspca_dev->sd_desc->isoc_init(gspca_dev); |
605 | if (ret < 0) | 608 | if (ret < 0) |
@@ -641,15 +644,19 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
641 | } | 644 | } |
642 | if (ret >= 0) | 645 | if (ret >= 0) |
643 | break; | 646 | break; |
644 | PDEBUG(D_ERR|D_STREAM, | ||
645 | "usb_submit_urb alt %d err %d", gspca_dev->alt, ret); | ||
646 | gspca_dev->streaming = 0; | 647 | gspca_dev->streaming = 0; |
647 | destroy_urbs(gspca_dev); | 648 | destroy_urbs(gspca_dev); |
648 | if (ret != -ENOSPC) | 649 | if (ret != -ENOSPC) { |
650 | PDEBUG(D_ERR|D_STREAM, | ||
651 | "usb_submit_urb alt %d err %d", | ||
652 | gspca_dev->alt, ret); | ||
649 | goto out; | 653 | goto out; |
654 | } | ||
650 | 655 | ||
651 | /* the bandwidth is not wide enough | 656 | /* the bandwidth is not wide enough |
652 | * negociate or try a lower alternate setting */ | 657 | * negociate or try a lower alternate setting */ |
658 | PDEBUG(D_ERR|D_STREAM, | ||
659 | "bandwidth not wide enough - trying again"); | ||
653 | msleep(20); /* wait for kill complete */ | 660 | msleep(20); /* wait for kill complete */ |
654 | if (gspca_dev->sd_desc->isoc_nego) { | 661 | if (gspca_dev->sd_desc->isoc_nego) { |
655 | ret = gspca_dev->sd_desc->isoc_nego(gspca_dev); | 662 | ret = gspca_dev->sd_desc->isoc_nego(gspca_dev); |
@@ -980,7 +987,7 @@ static void gspca_release(struct video_device *vfd) | |||
980 | { | 987 | { |
981 | struct gspca_dev *gspca_dev = container_of(vfd, struct gspca_dev, vdev); | 988 | struct gspca_dev *gspca_dev = container_of(vfd, struct gspca_dev, vdev); |
982 | 989 | ||
983 | PDEBUG(D_STREAM, "device released"); | 990 | PDEBUG(D_PROBE, "/dev/video%d released", gspca_dev->vdev.num); |
984 | 991 | ||
985 | kfree(gspca_dev->usb_buf); | 992 | kfree(gspca_dev->usb_buf); |
986 | kfree(gspca_dev); | 993 | kfree(gspca_dev); |
@@ -991,7 +998,7 @@ static int dev_open(struct file *file) | |||
991 | struct gspca_dev *gspca_dev; | 998 | struct gspca_dev *gspca_dev; |
992 | int ret; | 999 | int ret; |
993 | 1000 | ||
994 | PDEBUG(D_STREAM, "%s open", current->comm); | 1001 | PDEBUG(D_STREAM, "[%s] open", current->comm); |
995 | gspca_dev = (struct gspca_dev *) video_devdata(file); | 1002 | gspca_dev = (struct gspca_dev *) video_devdata(file); |
996 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | 1003 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) |
997 | return -ERESTARTSYS; | 1004 | return -ERESTARTSYS; |
@@ -1037,7 +1044,7 @@ static int dev_close(struct file *file) | |||
1037 | { | 1044 | { |
1038 | struct gspca_dev *gspca_dev = file->private_data; | 1045 | struct gspca_dev *gspca_dev = file->private_data; |
1039 | 1046 | ||
1040 | PDEBUG(D_STREAM, "%s close", current->comm); | 1047 | PDEBUG(D_STREAM, "[%s] close", current->comm); |
1041 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | 1048 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) |
1042 | return -ERESTARTSYS; | 1049 | return -ERESTARTSYS; |
1043 | gspca_dev->users--; | 1050 | gspca_dev->users--; |
@@ -1138,10 +1145,13 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
1138 | } | 1145 | } |
1139 | } else { | 1146 | } else { |
1140 | ctrls = get_ctrl(gspca_dev, id); | 1147 | ctrls = get_ctrl(gspca_dev, id); |
1148 | i = ctrls - gspca_dev->sd_desc->ctrls; | ||
1141 | } | 1149 | } |
1142 | if (ctrls == NULL) | 1150 | if (ctrls == NULL) |
1143 | return -EINVAL; | 1151 | return -EINVAL; |
1144 | memcpy(q_ctrl, ctrls, sizeof *q_ctrl); | 1152 | memcpy(q_ctrl, ctrls, sizeof *q_ctrl); |
1153 | if (gspca_dev->ctrl_inac & (1 << i)) | ||
1154 | q_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; | ||
1145 | return 0; | 1155 | return 0; |
1146 | } | 1156 | } |
1147 | 1157 | ||
@@ -1603,7 +1613,7 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma) | |||
1603 | size -= PAGE_SIZE; | 1613 | size -= PAGE_SIZE; |
1604 | } | 1614 | } |
1605 | 1615 | ||
1606 | vma->vm_ops = &gspca_vm_ops; | 1616 | vma->vm_ops = (struct vm_operations_struct *) &gspca_vm_ops; |
1607 | vma->vm_private_data = frame; | 1617 | vma->vm_private_data = frame; |
1608 | gspca_vm_open(vma); | 1618 | gspca_vm_open(vma); |
1609 | ret = 0; | 1619 | ret = 0; |
@@ -2001,11 +2011,15 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
2001 | PDEBUG(D_PROBE, "probing %04x:%04x", id->idVendor, id->idProduct); | 2011 | PDEBUG(D_PROBE, "probing %04x:%04x", id->idVendor, id->idProduct); |
2002 | 2012 | ||
2003 | /* we don't handle multi-config cameras */ | 2013 | /* we don't handle multi-config cameras */ |
2004 | if (dev->descriptor.bNumConfigurations != 1) | 2014 | if (dev->descriptor.bNumConfigurations != 1) { |
2015 | PDEBUG(D_ERR, "Too many config"); | ||
2005 | return -ENODEV; | 2016 | return -ENODEV; |
2017 | } | ||
2006 | interface = &intf->cur_altsetting->desc; | 2018 | interface = &intf->cur_altsetting->desc; |
2007 | if (interface->bInterfaceNumber > 0) | 2019 | if (interface->bInterfaceNumber > 0) { |
2020 | PDEBUG(D_ERR, "intf != 0"); | ||
2008 | return -ENODEV; | 2021 | return -ENODEV; |
2022 | } | ||
2009 | 2023 | ||
2010 | /* create the device */ | 2024 | /* create the device */ |
2011 | if (dev_size < sizeof *gspca_dev) | 2025 | if (dev_size < sizeof *gspca_dev) |
@@ -2059,7 +2073,7 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
2059 | } | 2073 | } |
2060 | 2074 | ||
2061 | usb_set_intfdata(intf, gspca_dev); | 2075 | usb_set_intfdata(intf, gspca_dev); |
2062 | PDEBUG(D_PROBE, "probe ok"); | 2076 | PDEBUG(D_PROBE, "/dev/video%d created", gspca_dev->vdev.num); |
2063 | return 0; | 2077 | return 0; |
2064 | out: | 2078 | out: |
2065 | kfree(gspca_dev->usb_buf); | 2079 | kfree(gspca_dev->usb_buf); |
@@ -2078,6 +2092,7 @@ void gspca_disconnect(struct usb_interface *intf) | |||
2078 | { | 2092 | { |
2079 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); | 2093 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); |
2080 | 2094 | ||
2095 | PDEBUG(D_PROBE, "/dev/video%d disconnect", gspca_dev->vdev.num); | ||
2081 | mutex_lock(&gspca_dev->usb_lock); | 2096 | mutex_lock(&gspca_dev->usb_lock); |
2082 | gspca_dev->present = 0; | 2097 | gspca_dev->present = 0; |
2083 | 2098 | ||
@@ -2096,7 +2111,7 @@ void gspca_disconnect(struct usb_interface *intf) | |||
2096 | /* (this will call gspca_release() immediatly or on last close) */ | 2111 | /* (this will call gspca_release() immediatly or on last close) */ |
2097 | video_unregister_device(&gspca_dev->vdev); | 2112 | video_unregister_device(&gspca_dev->vdev); |
2098 | 2113 | ||
2099 | PDEBUG(D_PROBE, "disconnect complete"); | 2114 | /* PDEBUG(D_PROBE, "disconnect complete"); */ |
2100 | } | 2115 | } |
2101 | EXPORT_SYMBOL(gspca_disconnect); | 2116 | EXPORT_SYMBOL(gspca_disconnect); |
2102 | 2117 | ||
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 70b1fd830876..181617355ec3 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h | |||
@@ -58,6 +58,7 @@ struct cam { | |||
58 | u8 npkt; /* number of packets in an ISOC message | 58 | u8 npkt; /* number of packets in an ISOC message |
59 | * 0 is the default value: 32 packets */ | 59 | * 0 is the default value: 32 packets */ |
60 | u32 input_flags; /* value for ENUM_INPUT status flags */ | 60 | u32 input_flags; /* value for ENUM_INPUT status flags */ |
61 | char reverse_alts; /* Alt settings are in high to low order */ | ||
61 | }; | 62 | }; |
62 | 63 | ||
63 | struct gspca_dev; | 64 | struct gspca_dev; |
@@ -78,8 +79,7 @@ typedef int (*cam_streamparm_op) (struct gspca_dev *, | |||
78 | typedef int (*cam_qmnu_op) (struct gspca_dev *, | 79 | typedef int (*cam_qmnu_op) (struct gspca_dev *, |
79 | struct v4l2_querymenu *); | 80 | struct v4l2_querymenu *); |
80 | typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev, | 81 | typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev, |
81 | struct gspca_frame *frame, | 82 | u8 *data, |
82 | __u8 *data, | ||
83 | int len); | 83 | int len); |
84 | 84 | ||
85 | struct ctrl { | 85 | struct ctrl { |
@@ -142,6 +142,7 @@ struct gspca_dev { | |||
142 | struct cam cam; /* device information */ | 142 | struct cam cam; /* device information */ |
143 | const struct sd_desc *sd_desc; /* subdriver description */ | 143 | const struct sd_desc *sd_desc; /* subdriver description */ |
144 | unsigned ctrl_dis; /* disabled controls (bit map) */ | 144 | unsigned ctrl_dis; /* disabled controls (bit map) */ |
145 | unsigned ctrl_inac; /* inactive controls (bit map) */ | ||
145 | 146 | ||
146 | #define USB_BUF_SZ 64 | 147 | #define USB_BUF_SZ 64 |
147 | __u8 *usb_buf; /* buffer for USB exchanges */ | 148 | __u8 *usb_buf; /* buffer for USB exchanges */ |
@@ -149,6 +150,7 @@ struct gspca_dev { | |||
149 | 150 | ||
150 | __u8 *frbuf; /* buffer for nframes */ | 151 | __u8 *frbuf; /* buffer for nframes */ |
151 | struct gspca_frame frame[GSPCA_MAX_FRAMES]; | 152 | struct gspca_frame frame[GSPCA_MAX_FRAMES]; |
153 | struct gspca_frame *cur_frame; /* frame beeing filled */ | ||
152 | __u32 frsz; /* frame size */ | 154 | __u32 frsz; /* frame size */ |
153 | char nframes; /* number of frames */ | 155 | char nframes; /* number of frames */ |
154 | char fr_i; /* frame being filled */ | 156 | char fr_i; /* frame being filled */ |
@@ -189,11 +191,10 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
189 | int dev_size, | 191 | int dev_size, |
190 | struct module *module); | 192 | struct module *module); |
191 | void gspca_disconnect(struct usb_interface *intf); | 193 | void gspca_disconnect(struct usb_interface *intf); |
192 | struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, | 194 | void gspca_frame_add(struct gspca_dev *gspca_dev, |
193 | enum gspca_packet_type packet_type, | 195 | enum gspca_packet_type packet_type, |
194 | struct gspca_frame *frame, | 196 | const u8 *data, |
195 | const __u8 *data, | 197 | int len); |
196 | int len); | ||
197 | struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev); | 198 | struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev); |
198 | #ifdef CONFIG_PM | 199 | #ifdef CONFIG_PM |
199 | int gspca_suspend(struct usb_interface *intf, pm_message_t message); | 200 | int gspca_suspend(struct usb_interface *intf, pm_message_t message); |
diff --git a/drivers/media/video/gspca/jeilinj.c b/drivers/media/video/gspca/jeilinj.c index a11c97ebeb0f..2019b04f9235 100644 --- a/drivers/media/video/gspca/jeilinj.c +++ b/drivers/media/video/gspca/jeilinj.c | |||
@@ -181,11 +181,9 @@ static void jlj_dostream(struct work_struct *work) | |||
181 | { | 181 | { |
182 | struct sd *dev = container_of(work, struct sd, work_struct); | 182 | struct sd *dev = container_of(work, struct sd, work_struct); |
183 | struct gspca_dev *gspca_dev = &dev->gspca_dev; | 183 | struct gspca_dev *gspca_dev = &dev->gspca_dev; |
184 | struct gspca_frame *frame; | ||
185 | int blocks_left; /* 0x200-sized blocks remaining in current frame. */ | 184 | int blocks_left; /* 0x200-sized blocks remaining in current frame. */ |
186 | int size_in_blocks; | 185 | int size_in_blocks; |
187 | int act_len; | 186 | int act_len; |
188 | int discarding = 0; /* true if we failed to get space for frame. */ | ||
189 | int packet_type; | 187 | int packet_type; |
190 | int ret; | 188 | int ret; |
191 | u8 *buffer; | 189 | u8 *buffer; |
@@ -196,15 +194,6 @@ static void jlj_dostream(struct work_struct *work) | |||
196 | goto quit_stream; | 194 | goto quit_stream; |
197 | } | 195 | } |
198 | while (gspca_dev->present && gspca_dev->streaming) { | 196 | while (gspca_dev->present && gspca_dev->streaming) { |
199 | if (!gspca_dev->present) | ||
200 | goto quit_stream; | ||
201 | /* Start a new frame, and add the JPEG header, first thing */ | ||
202 | frame = gspca_get_i_frame(gspca_dev); | ||
203 | if (frame && !discarding) | ||
204 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | ||
205 | dev->jpeg_hdr, JPEG_HDR_SZ); | ||
206 | else | ||
207 | discarding = 1; | ||
208 | /* | 197 | /* |
209 | * Now request data block 0. Line 0 reports the size | 198 | * Now request data block 0. Line 0 reports the size |
210 | * to download, in blocks of size 0x200, and also tells the | 199 | * to download, in blocks of size 0x200, and also tells the |
@@ -222,14 +211,15 @@ static void jlj_dostream(struct work_struct *work) | |||
222 | size_in_blocks = buffer[0x0a]; | 211 | size_in_blocks = buffer[0x0a]; |
223 | blocks_left = buffer[0x0a] - 1; | 212 | blocks_left = buffer[0x0a] - 1; |
224 | PDEBUG(D_STREAM, "blocks_left = 0x%x", blocks_left); | 213 | PDEBUG(D_STREAM, "blocks_left = 0x%x", blocks_left); |
225 | packet_type = INTER_PACKET; | 214 | |
226 | if (frame && !discarding) | 215 | /* Start a new frame, and add the JPEG header, first thing */ |
227 | /* Toss line 0 of data block 0, keep the rest. */ | 216 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
228 | gspca_frame_add(gspca_dev, packet_type, | 217 | dev->jpeg_hdr, JPEG_HDR_SZ); |
229 | frame, buffer + FRAME_HEADER_LEN, | 218 | /* Toss line 0 of data block 0, keep the rest. */ |
219 | gspca_frame_add(gspca_dev, INTER_PACKET, | ||
220 | buffer + FRAME_HEADER_LEN, | ||
230 | JEILINJ_MAX_TRANSFER - FRAME_HEADER_LEN); | 221 | JEILINJ_MAX_TRANSFER - FRAME_HEADER_LEN); |
231 | else | 222 | |
232 | discarding = 1; | ||
233 | while (blocks_left > 0) { | 223 | while (blocks_left > 0) { |
234 | if (!gspca_dev->present) | 224 | if (!gspca_dev->present) |
235 | goto quit_stream; | 225 | goto quit_stream; |
@@ -246,12 +236,8 @@ static void jlj_dostream(struct work_struct *work) | |||
246 | packet_type = LAST_PACKET; | 236 | packet_type = LAST_PACKET; |
247 | else | 237 | else |
248 | packet_type = INTER_PACKET; | 238 | packet_type = INTER_PACKET; |
249 | if (frame && !discarding) | 239 | gspca_frame_add(gspca_dev, packet_type, |
250 | gspca_frame_add(gspca_dev, packet_type, | 240 | buffer, JEILINJ_MAX_TRANSFER); |
251 | frame, buffer, | ||
252 | JEILINJ_MAX_TRANSFER); | ||
253 | else | ||
254 | discarding = 1; | ||
255 | } | 241 | } |
256 | } | 242 | } |
257 | quit_stream: | 243 | quit_stream: |
diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c index 7f1e5415850b..844fc1d886d1 100644 --- a/drivers/media/video/gspca/m5602/m5602_core.c +++ b/drivers/media/video/gspca/m5602/m5602_core.c | |||
@@ -274,8 +274,7 @@ static int m5602_start_transfer(struct gspca_dev *gspca_dev) | |||
274 | } | 274 | } |
275 | 275 | ||
276 | static void m5602_urb_complete(struct gspca_dev *gspca_dev, | 276 | static void m5602_urb_complete(struct gspca_dev *gspca_dev, |
277 | struct gspca_frame *frame, | 277 | u8 *data, int len) |
278 | __u8 *data, int len) | ||
279 | { | 278 | { |
280 | struct sd *sd = (struct sd *) gspca_dev; | 279 | struct sd *sd = (struct sd *) gspca_dev; |
281 | 280 | ||
@@ -295,19 +294,27 @@ static void m5602_urb_complete(struct gspca_dev *gspca_dev, | |||
295 | len -= 6; | 294 | len -= 6; |
296 | 295 | ||
297 | /* Complete the last frame (if any) */ | 296 | /* Complete the last frame (if any) */ |
298 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, | 297 | gspca_frame_add(gspca_dev, LAST_PACKET, |
299 | frame, data, 0); | 298 | NULL, 0); |
300 | sd->frame_count++; | 299 | sd->frame_count++; |
301 | 300 | ||
302 | /* Create a new frame */ | 301 | /* Create a new frame */ |
303 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); | 302 | gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); |
304 | 303 | ||
305 | PDEBUG(D_FRAM, "Starting new frame %d", | 304 | PDEBUG(D_FRAM, "Starting new frame %d", |
306 | sd->frame_count); | 305 | sd->frame_count); |
307 | 306 | ||
308 | } else { | 307 | } else { |
309 | int cur_frame_len = frame->data_end - frame->data; | 308 | struct gspca_frame *frame; |
309 | int cur_frame_len; | ||
310 | 310 | ||
311 | frame = gspca_get_i_frame(gspca_dev); | ||
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; | ||
311 | /* Remove urb header */ | 318 | /* Remove urb header */ |
312 | data += 4; | 319 | data += 4; |
313 | len -= 4; | 320 | len -= 4; |
@@ -316,12 +323,12 @@ static void m5602_urb_complete(struct gspca_dev *gspca_dev, | |||
316 | PDEBUG(D_FRAM, "Continuing frame %d copying %d bytes", | 323 | PDEBUG(D_FRAM, "Continuing frame %d copying %d bytes", |
317 | sd->frame_count, len); | 324 | sd->frame_count, len); |
318 | 325 | ||
319 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | 326 | gspca_frame_add(gspca_dev, INTER_PACKET, |
320 | data, len); | 327 | data, len); |
321 | } else if (frame->v4l2_buf.length - cur_frame_len > 0) { | 328 | } else if (frame->v4l2_buf.length - cur_frame_len > 0) { |
322 | /* Add the remaining data up to frame size */ | 329 | /* Add the remaining data up to frame size */ |
323 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, | 330 | gspca_frame_add(gspca_dev, INTER_PACKET, data, |
324 | frame->v4l2_buf.length - cur_frame_len); | 331 | frame->v4l2_buf.length - cur_frame_len); |
325 | } | 332 | } |
326 | } | 333 | } |
327 | } | 334 | } |
diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index de769caf013d..9cf8d68c71bf 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c | |||
@@ -325,8 +325,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
325 | } | 325 | } |
326 | 326 | ||
327 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 327 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
328 | struct gspca_frame *frame, /* target */ | 328 | u8 *data, /* isoc packet */ |
329 | __u8 *data, /* isoc packet */ | ||
330 | int len) /* iso packet length */ | 329 | int len) /* iso packet length */ |
331 | { | 330 | { |
332 | struct sd *sd = (struct sd *) gspca_dev; | 331 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -348,11 +347,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
348 | || data[5 + p] == 0x67) { | 347 | || data[5 + p] == 0x67) { |
349 | PDEBUG(D_PACK, "sof offset: %d len: %d", | 348 | PDEBUG(D_PACK, "sof offset: %d len: %d", |
350 | p, len); | 349 | p, len); |
351 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, | 350 | gspca_frame_add(gspca_dev, LAST_PACKET, |
352 | frame, data, p); | 351 | data, p); |
353 | 352 | ||
354 | /* put the JPEG header */ | 353 | /* put the JPEG header */ |
355 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | 354 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
356 | sd->jpeg_hdr, JPEG_HDR_SZ); | 355 | sd->jpeg_hdr, JPEG_HDR_SZ); |
357 | data += p + 16; | 356 | data += p + 16; |
358 | len -= p + 16; | 357 | len -= p + 16; |
@@ -360,7 +359,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
360 | } | 359 | } |
361 | } | 360 | } |
362 | } | 361 | } |
363 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | 362 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
364 | } | 363 | } |
365 | 364 | ||
366 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 365 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) |
diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index f8328b9efae5..126d968dd9e0 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c | |||
@@ -1,23 +1,30 @@ | |||
1 | /* | 1 | /* |
2 | * Mars MR97310A library | 2 | * Mars MR97310A library |
3 | * | 3 | * |
4 | * The original mr97310a driver, which supported the Aiptek Pencam VGA+, is | ||
4 | * Copyright (C) 2009 Kyle Guinn <elyk03@gmail.com> | 5 | * Copyright (C) 2009 Kyle Guinn <elyk03@gmail.com> |
5 | * | 6 | * |
6 | * Support for the MR97310A cameras in addition to the Aiptek Pencam VGA+ | 7 | * Support for the MR97310A cameras in addition to the Aiptek Pencam VGA+ |
7 | * and for the routines for detecting and classifying these various cameras, | 8 | * and for the routines for detecting and classifying these various cameras, |
9 | * is Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu> | ||
8 | * | 10 | * |
11 | * Support for the control settings for the CIF cameras is | ||
12 | * Copyright (C) 2009 Hans de Goede <hdgoede@redhat.com> and | ||
13 | * Thomas Kaiser <thomas@kaiser-linux.li> | ||
14 | * | ||
15 | * Support for the control settings for the VGA cameras is | ||
9 | * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu> | 16 | * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu> |
10 | * | 17 | * |
11 | * Acknowledgements: | 18 | * Several previously unsupported cameras are owned and have been tested by |
19 | * Hans de Goede <hdgoede@redhat.com> and | ||
20 | * Thomas Kaiser <thomas@kaiser-linux.li> and | ||
21 | * Theodore Kilgore <kilgota@auburn.edu> and | ||
22 | * Edmond Rodriguez <erodrig_97@yahoo.com> and | ||
23 | * Aurelien Jacobs <aurel@gnuage.org> | ||
12 | * | 24 | * |
13 | * The MR97311A support in gspca/mars.c has been helpful in understanding some | 25 | * The MR97311A support in gspca/mars.c has been helpful in understanding some |
14 | * of the registers in these cameras. | 26 | * of the registers in these cameras. |
15 | * | 27 | * |
16 | * Hans de Goede <hdgoede@redhat.com> and | ||
17 | * Thomas Kaiser <thomas@kaiser-linux.li> | ||
18 | * have assisted with their experience. Each of them has also helped by | ||
19 | * testing a previously unsupported camera. | ||
20 | * | ||
21 | * This program is free software; you can redistribute it and/or modify | 28 | * This program is free software; you can redistribute it and/or modify |
22 | * it under the terms of the GNU General Public License as published by | 29 | * it under the terms of the GNU General Public License as published by |
23 | * the Free Software Foundation; either version 2 of the License, or | 30 | * the Free Software Foundation; either version 2 of the License, or |
@@ -40,11 +47,9 @@ | |||
40 | #define CAM_TYPE_CIF 0 | 47 | #define CAM_TYPE_CIF 0 |
41 | #define CAM_TYPE_VGA 1 | 48 | #define CAM_TYPE_VGA 1 |
42 | 49 | ||
43 | #define MR97310A_BRIGHTNESS_MIN -254 | ||
44 | #define MR97310A_BRIGHTNESS_MAX 255 | ||
45 | #define MR97310A_BRIGHTNESS_DEFAULT 0 | 50 | #define MR97310A_BRIGHTNESS_DEFAULT 0 |
46 | 51 | ||
47 | #define MR97310A_EXPOSURE_MIN 300 | 52 | #define MR97310A_EXPOSURE_MIN 0 |
48 | #define MR97310A_EXPOSURE_MAX 4095 | 53 | #define MR97310A_EXPOSURE_MAX 4095 |
49 | #define MR97310A_EXPOSURE_DEFAULT 1000 | 54 | #define MR97310A_EXPOSURE_DEFAULT 1000 |
50 | 55 | ||
@@ -52,6 +57,10 @@ | |||
52 | #define MR97310A_GAIN_MAX 31 | 57 | #define MR97310A_GAIN_MAX 31 |
53 | #define MR97310A_GAIN_DEFAULT 25 | 58 | #define MR97310A_GAIN_DEFAULT 25 |
54 | 59 | ||
60 | #define MR97310A_MIN_CLOCKDIV_MIN 3 | ||
61 | #define MR97310A_MIN_CLOCKDIV_MAX 8 | ||
62 | #define MR97310A_MIN_CLOCKDIV_DEFAULT 3 | ||
63 | |||
55 | MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>," | 64 | MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>," |
56 | "Theodore Kilgore <kilgota@auburn.edu>"); | 65 | "Theodore Kilgore <kilgota@auburn.edu>"); |
57 | MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver"); | 66 | MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver"); |
@@ -69,10 +78,12 @@ struct sd { | |||
69 | u8 cam_type; /* 0 is CIF and 1 is VGA */ | 78 | u8 cam_type; /* 0 is CIF and 1 is VGA */ |
70 | u8 sensor_type; /* We use 0 and 1 here, too. */ | 79 | u8 sensor_type; /* We use 0 and 1 here, too. */ |
71 | u8 do_lcd_stop; | 80 | u8 do_lcd_stop; |
81 | u8 adj_colors; | ||
72 | 82 | ||
73 | int brightness; | 83 | int brightness; |
74 | u16 exposure; | 84 | u16 exposure; |
75 | u8 gain; | 85 | u8 gain; |
86 | u8 min_clockdiv; | ||
76 | }; | 87 | }; |
77 | 88 | ||
78 | struct sensor_w_data { | 89 | struct sensor_w_data { |
@@ -82,26 +93,31 @@ struct sensor_w_data { | |||
82 | int len; | 93 | int len; |
83 | }; | 94 | }; |
84 | 95 | ||
96 | static void sd_stopN(struct gspca_dev *gspca_dev); | ||
85 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | 97 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); |
86 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | 98 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); |
87 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | 99 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); |
88 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | 100 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); |
89 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | 101 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); |
90 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | 102 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); |
103 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val); | ||
104 | static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val); | ||
91 | static void setbrightness(struct gspca_dev *gspca_dev); | 105 | static void setbrightness(struct gspca_dev *gspca_dev); |
92 | static void setexposure(struct gspca_dev *gspca_dev); | 106 | static void setexposure(struct gspca_dev *gspca_dev); |
93 | static void setgain(struct gspca_dev *gspca_dev); | 107 | static void setgain(struct gspca_dev *gspca_dev); |
94 | 108 | ||
95 | /* V4L2 controls supported by the driver */ | 109 | /* V4L2 controls supported by the driver */ |
96 | static struct ctrl sd_ctrls[] = { | 110 | static struct ctrl sd_ctrls[] = { |
111 | /* Separate brightness control description for Argus QuickClix as it has | ||
112 | different limits from the other mr97310a cameras */ | ||
97 | { | 113 | { |
98 | #define BRIGHTNESS_IDX 0 | 114 | #define NORM_BRIGHTNESS_IDX 0 |
99 | { | 115 | { |
100 | .id = V4L2_CID_BRIGHTNESS, | 116 | .id = V4L2_CID_BRIGHTNESS, |
101 | .type = V4L2_CTRL_TYPE_INTEGER, | 117 | .type = V4L2_CTRL_TYPE_INTEGER, |
102 | .name = "Brightness", | 118 | .name = "Brightness", |
103 | .minimum = MR97310A_BRIGHTNESS_MIN, | 119 | .minimum = -254, |
104 | .maximum = MR97310A_BRIGHTNESS_MAX, | 120 | .maximum = 255, |
105 | .step = 1, | 121 | .step = 1, |
106 | .default_value = MR97310A_BRIGHTNESS_DEFAULT, | 122 | .default_value = MR97310A_BRIGHTNESS_DEFAULT, |
107 | .flags = 0, | 123 | .flags = 0, |
@@ -110,7 +126,22 @@ static struct ctrl sd_ctrls[] = { | |||
110 | .get = sd_getbrightness, | 126 | .get = sd_getbrightness, |
111 | }, | 127 | }, |
112 | { | 128 | { |
113 | #define EXPOSURE_IDX 1 | 129 | #define ARGUS_QC_BRIGHTNESS_IDX 1 |
130 | { | ||
131 | .id = V4L2_CID_BRIGHTNESS, | ||
132 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
133 | .name = "Brightness", | ||
134 | .minimum = 0, | ||
135 | .maximum = 15, | ||
136 | .step = 1, | ||
137 | .default_value = MR97310A_BRIGHTNESS_DEFAULT, | ||
138 | .flags = 0, | ||
139 | }, | ||
140 | .set = sd_setbrightness, | ||
141 | .get = sd_getbrightness, | ||
142 | }, | ||
143 | { | ||
144 | #define EXPOSURE_IDX 2 | ||
114 | { | 145 | { |
115 | .id = V4L2_CID_EXPOSURE, | 146 | .id = V4L2_CID_EXPOSURE, |
116 | .type = V4L2_CTRL_TYPE_INTEGER, | 147 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -125,7 +156,7 @@ static struct ctrl sd_ctrls[] = { | |||
125 | .get = sd_getexposure, | 156 | .get = sd_getexposure, |
126 | }, | 157 | }, |
127 | { | 158 | { |
128 | #define GAIN_IDX 2 | 159 | #define GAIN_IDX 3 |
129 | { | 160 | { |
130 | .id = V4L2_CID_GAIN, | 161 | .id = V4L2_CID_GAIN, |
131 | .type = V4L2_CTRL_TYPE_INTEGER, | 162 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -139,6 +170,21 @@ static struct ctrl sd_ctrls[] = { | |||
139 | .set = sd_setgain, | 170 | .set = sd_setgain, |
140 | .get = sd_getgain, | 171 | .get = sd_getgain, |
141 | }, | 172 | }, |
173 | { | ||
174 | #define MIN_CLOCKDIV_IDX 4 | ||
175 | { | ||
176 | .id = V4L2_CID_PRIVATE_BASE, | ||
177 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
178 | .name = "Minimum Clock Divider", | ||
179 | .minimum = MR97310A_MIN_CLOCKDIV_MIN, | ||
180 | .maximum = MR97310A_MIN_CLOCKDIV_MAX, | ||
181 | .step = 1, | ||
182 | .default_value = MR97310A_MIN_CLOCKDIV_DEFAULT, | ||
183 | .flags = 0, | ||
184 | }, | ||
185 | .set = sd_setmin_clockdiv, | ||
186 | .get = sd_getmin_clockdiv, | ||
187 | }, | ||
142 | }; | 188 | }; |
143 | 189 | ||
144 | static const struct v4l2_pix_format vga_mode[] = { | 190 | static const struct v4l2_pix_format vga_mode[] = { |
@@ -230,12 +276,17 @@ static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data) | |||
230 | int rc; | 276 | int rc; |
231 | 277 | ||
232 | buf = data; | 278 | buf = data; |
233 | rc = sensor_write_reg(gspca_dev, reg, 0x01, &buf, 1); | 279 | if (sd->cam_type == CAM_TYPE_CIF) { |
280 | rc = sensor_write_reg(gspca_dev, reg, 0x01, &buf, 1); | ||
281 | confirm_reg = sd->sensor_type ? 0x13 : 0x11; | ||
282 | } else { | ||
283 | rc = sensor_write_reg(gspca_dev, reg, 0x00, &buf, 1); | ||
284 | confirm_reg = 0x11; | ||
285 | } | ||
234 | if (rc < 0) | 286 | if (rc < 0) |
235 | return rc; | 287 | return rc; |
236 | 288 | ||
237 | buf = 0x01; | 289 | buf = 0x01; |
238 | confirm_reg = sd->sensor_type ? 0x13 : 0x11; | ||
239 | rc = sensor_write_reg(gspca_dev, confirm_reg, 0x00, &buf, 1); | 290 | rc = sensor_write_reg(gspca_dev, confirm_reg, 0x00, &buf, 1); |
240 | if (rc < 0) | 291 | if (rc < 0) |
241 | return rc; | 292 | return rc; |
@@ -243,18 +294,26 @@ static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data) | |||
243 | return 0; | 294 | return 0; |
244 | } | 295 | } |
245 | 296 | ||
246 | static int cam_get_response16(struct gspca_dev *gspca_dev) | 297 | static int cam_get_response16(struct gspca_dev *gspca_dev, u8 reg, int verbose) |
247 | { | 298 | { |
248 | __u8 *data = gspca_dev->usb_buf; | ||
249 | int err_code; | 299 | int err_code; |
250 | 300 | ||
251 | data[0] = 0x21; | 301 | gspca_dev->usb_buf[0] = reg; |
252 | err_code = mr_write(gspca_dev, 1); | 302 | err_code = mr_write(gspca_dev, 1); |
253 | if (err_code < 0) | 303 | if (err_code < 0) |
254 | return err_code; | 304 | return err_code; |
255 | 305 | ||
256 | err_code = mr_read(gspca_dev, 16); | 306 | err_code = mr_read(gspca_dev, 16); |
257 | return err_code; | 307 | if (err_code < 0) |
308 | return err_code; | ||
309 | |||
310 | if (verbose) | ||
311 | PDEBUG(D_PROBE, "Register: %02x reads %02x%02x%02x", reg, | ||
312 | gspca_dev->usb_buf[0], | ||
313 | gspca_dev->usb_buf[1], | ||
314 | gspca_dev->usb_buf[2]); | ||
315 | |||
316 | return 0; | ||
258 | } | 317 | } |
259 | 318 | ||
260 | static int zero_the_pointer(struct gspca_dev *gspca_dev) | 319 | static int zero_the_pointer(struct gspca_dev *gspca_dev) |
@@ -264,7 +323,7 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev) | |||
264 | u8 status = 0; | 323 | u8 status = 0; |
265 | int tries = 0; | 324 | int tries = 0; |
266 | 325 | ||
267 | err_code = cam_get_response16(gspca_dev); | 326 | err_code = cam_get_response16(gspca_dev, 0x21, 0); |
268 | if (err_code < 0) | 327 | if (err_code < 0) |
269 | return err_code; | 328 | return err_code; |
270 | 329 | ||
@@ -275,7 +334,7 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev) | |||
275 | if (err_code < 0) | 334 | if (err_code < 0) |
276 | return err_code; | 335 | return err_code; |
277 | 336 | ||
278 | err_code = cam_get_response16(gspca_dev); | 337 | err_code = cam_get_response16(gspca_dev, 0x21, 0); |
279 | if (err_code < 0) | 338 | if (err_code < 0) |
280 | return err_code; | 339 | return err_code; |
281 | 340 | ||
@@ -285,7 +344,7 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev) | |||
285 | if (err_code < 0) | 344 | if (err_code < 0) |
286 | return err_code; | 345 | return err_code; |
287 | 346 | ||
288 | err_code = cam_get_response16(gspca_dev); | 347 | err_code = cam_get_response16(gspca_dev, 0x21, 0); |
289 | if (err_code < 0) | 348 | if (err_code < 0) |
290 | return err_code; | 349 | return err_code; |
291 | 350 | ||
@@ -295,7 +354,7 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev) | |||
295 | if (err_code < 0) | 354 | if (err_code < 0) |
296 | return err_code; | 355 | return err_code; |
297 | 356 | ||
298 | err_code = cam_get_response16(gspca_dev); | 357 | err_code = cam_get_response16(gspca_dev, 0x21, 0); |
299 | if (err_code < 0) | 358 | if (err_code < 0) |
300 | return err_code; | 359 | return err_code; |
301 | 360 | ||
@@ -306,7 +365,7 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev) | |||
306 | return err_code; | 365 | return err_code; |
307 | 366 | ||
308 | while (status != 0x0a && tries < 256) { | 367 | while (status != 0x0a && tries < 256) { |
309 | err_code = cam_get_response16(gspca_dev); | 368 | err_code = cam_get_response16(gspca_dev, 0x21, 0); |
310 | status = data[0]; | 369 | status = data[0]; |
311 | tries++; | 370 | tries++; |
312 | if (err_code < 0) | 371 | if (err_code < 0) |
@@ -323,7 +382,7 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev) | |||
323 | if (err_code < 0) | 382 | if (err_code < 0) |
324 | return err_code; | 383 | return err_code; |
325 | 384 | ||
326 | err_code = cam_get_response16(gspca_dev); | 385 | err_code = cam_get_response16(gspca_dev, 0x21, 0); |
327 | status = data[0]; | 386 | status = data[0]; |
328 | tries++; | 387 | tries++; |
329 | if (err_code < 0) | 388 | if (err_code < 0) |
@@ -342,89 +401,202 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev) | |||
342 | return 0; | 401 | return 0; |
343 | } | 402 | } |
344 | 403 | ||
345 | static u8 get_sensor_id(struct gspca_dev *gspca_dev) | 404 | static int stream_start(struct gspca_dev *gspca_dev) |
346 | { | 405 | { |
347 | int err_code; | 406 | gspca_dev->usb_buf[0] = 0x01; |
348 | 407 | gspca_dev->usb_buf[1] = 0x01; | |
349 | gspca_dev->usb_buf[0] = 0x1e; | 408 | return mr_write(gspca_dev, 2); |
350 | err_code = mr_write(gspca_dev, 1); | 409 | } |
351 | if (err_code < 0) | ||
352 | return err_code; | ||
353 | 410 | ||
354 | err_code = mr_read(gspca_dev, 16); | 411 | static void stream_stop(struct gspca_dev *gspca_dev) |
355 | if (err_code < 0) | 412 | { |
356 | return err_code; | 413 | gspca_dev->usb_buf[0] = 0x01; |
414 | gspca_dev->usb_buf[1] = 0x00; | ||
415 | if (mr_write(gspca_dev, 2) < 0) | ||
416 | PDEBUG(D_ERR, "Stream Stop failed"); | ||
417 | } | ||
357 | 418 | ||
358 | PDEBUG(D_PROBE, "Byte zero reported is %01x", gspca_dev->usb_buf[0]); | 419 | static void lcd_stop(struct gspca_dev *gspca_dev) |
420 | { | ||
421 | gspca_dev->usb_buf[0] = 0x19; | ||
422 | gspca_dev->usb_buf[1] = 0x54; | ||
423 | if (mr_write(gspca_dev, 2) < 0) | ||
424 | PDEBUG(D_ERR, "LCD Stop failed"); | ||
425 | } | ||
359 | 426 | ||
360 | return gspca_dev->usb_buf[0]; | 427 | static int isoc_enable(struct gspca_dev *gspca_dev) |
428 | { | ||
429 | gspca_dev->usb_buf[0] = 0x00; | ||
430 | gspca_dev->usb_buf[1] = 0x4d; /* ISOC transfering enable... */ | ||
431 | return mr_write(gspca_dev, 2); | ||
361 | } | 432 | } |
362 | 433 | ||
363 | /* this function is called at probe time */ | 434 | /* This function is called at probe time */ |
364 | static int sd_config(struct gspca_dev *gspca_dev, | 435 | static int sd_config(struct gspca_dev *gspca_dev, |
365 | const struct usb_device_id *id) | 436 | const struct usb_device_id *id) |
366 | { | 437 | { |
367 | struct sd *sd = (struct sd *) gspca_dev; | 438 | struct sd *sd = (struct sd *) gspca_dev; |
368 | struct cam *cam; | 439 | struct cam *cam; |
369 | __u8 *data = gspca_dev->usb_buf; | ||
370 | int err_code; | 440 | int err_code; |
371 | 441 | ||
372 | cam = &gspca_dev->cam; | 442 | cam = &gspca_dev->cam; |
373 | cam->cam_mode = vga_mode; | 443 | cam->cam_mode = vga_mode; |
374 | cam->nmodes = ARRAY_SIZE(vga_mode); | 444 | cam->nmodes = ARRAY_SIZE(vga_mode); |
445 | sd->do_lcd_stop = 0; | ||
446 | |||
447 | /* Several of the supported CIF cameras share the same USB ID but | ||
448 | * require different initializations and different control settings. | ||
449 | * The same is true of the VGA cameras. Therefore, we are forced | ||
450 | * to start the initialization process in order to determine which | ||
451 | * camera is present. Some of the supported cameras require the | ||
452 | * memory pointer to be set to 0 as the very first item of business | ||
453 | * or else they will not stream. So we do that immediately. | ||
454 | */ | ||
455 | err_code = zero_the_pointer(gspca_dev); | ||
456 | if (err_code < 0) | ||
457 | return err_code; | ||
458 | |||
459 | err_code = stream_start(gspca_dev); | ||
460 | if (err_code < 0) | ||
461 | return err_code; | ||
375 | 462 | ||
376 | if (id->idProduct == 0x010e) { | 463 | if (id->idProduct == 0x0110 || id->idProduct == 0x010e) { |
377 | sd->cam_type = CAM_TYPE_CIF; | 464 | sd->cam_type = CAM_TYPE_CIF; |
378 | cam->nmodes--; | 465 | cam->nmodes--; |
379 | 466 | err_code = cam_get_response16(gspca_dev, 0x06, 1); | |
380 | data[0] = 0x01; | ||
381 | data[1] = 0x01; | ||
382 | err_code = mr_write(gspca_dev, 2); | ||
383 | if (err_code < 0) | 467 | if (err_code < 0) |
384 | return err_code; | 468 | return err_code; |
385 | |||
386 | msleep(200); | ||
387 | data[0] = get_sensor_id(gspca_dev); | ||
388 | /* | 469 | /* |
389 | * Known CIF cameras. If you have another to report, please do | 470 | * All but one of the known CIF cameras share the same USB ID, |
471 | * but two different init routines are in use, and the control | ||
472 | * settings are different, too. We need to detect which camera | ||
473 | * of the two known varieties is connected! | ||
390 | * | 474 | * |
391 | * Name byte just read sd->sensor_type | 475 | * A list of known CIF cameras follows. They all report either |
392 | * reported by | 476 | * 0002 for type 0 or 0003 for type 1. |
393 | * Sakar Spy-shot 0x28 T. Kilgore 0 | 477 | * If you have another to report, please do |
394 | * Innovage 0xf5 (unstable) T. Kilgore 0 | 478 | * |
395 | * Vivitar Mini 0x53 H. De Goede 0 | 479 | * Name sd->sensor_type reported by |
396 | * Vivitar Mini 0x04 / 0x24 E. Rodriguez 0 | 480 | * |
397 | * Vivitar Mini 0x08 T. Kilgore 1 | 481 | * Sakar Spy-shot 0 T. Kilgore |
398 | * Elta-Media 8212dc 0x23 T. Kaiser 1 | 482 | * Innovage 0 T. Kilgore |
399 | * Philips dig. keych. 0x37 T. Kilgore 1 | 483 | * Vivitar Mini 0 H. De Goede |
484 | * Vivitar Mini 0 E. Rodriguez | ||
485 | * Vivitar Mini 1 T. Kilgore | ||
486 | * Elta-Media 8212dc 1 T. Kaiser | ||
487 | * Philips dig. keych. 1 T. Kilgore | ||
488 | * Trust Spyc@m 100 1 A. Jacobs | ||
400 | */ | 489 | */ |
401 | if ((data[0] & 0x78) == 8 || | 490 | switch (gspca_dev->usb_buf[1]) { |
402 | ((data[0] & 0x2) == 0x2 && data[0] != 0x53)) | 491 | case 2: |
403 | sd->sensor_type = 1; | ||
404 | else | ||
405 | sd->sensor_type = 0; | 492 | sd->sensor_type = 0; |
406 | 493 | break; | |
494 | case 3: | ||
495 | sd->sensor_type = 1; | ||
496 | break; | ||
497 | default: | ||
498 | PDEBUG(D_ERR, "Unknown CIF Sensor id : %02x", | ||
499 | gspca_dev->usb_buf[1]); | ||
500 | return -ENODEV; | ||
501 | } | ||
407 | PDEBUG(D_PROBE, "MR97310A CIF camera detected, sensor: %d", | 502 | PDEBUG(D_PROBE, "MR97310A CIF camera detected, sensor: %d", |
408 | sd->sensor_type); | 503 | sd->sensor_type); |
504 | } else { | ||
505 | sd->cam_type = CAM_TYPE_VGA; | ||
409 | 506 | ||
410 | if (force_sensor_type != -1) { | 507 | err_code = cam_get_response16(gspca_dev, 0x07, 1); |
411 | sd->sensor_type = !! force_sensor_type; | 508 | if (err_code < 0) |
412 | PDEBUG(D_PROBE, "Forcing sensor type to: %d", | 509 | return err_code; |
413 | sd->sensor_type); | 510 | |
511 | /* | ||
512 | * Here is a table of the responses to the previous command | ||
513 | * from the known MR97310A VGA cameras. | ||
514 | * | ||
515 | * Name gspca_dev->usb_buf[] sd->sensor_type | ||
516 | * sd->do_lcd_stop | ||
517 | * Aiptek Pencam VGA+ 0300 0 1 | ||
518 | * ION digital 0350 0 1 | ||
519 | * Argus DC-1620 0450 1 0 | ||
520 | * Argus QuickClix 0420 1 1 | ||
521 | * | ||
522 | * Based upon these results, we assume default settings | ||
523 | * and then correct as necessary, as follows. | ||
524 | * | ||
525 | */ | ||
526 | |||
527 | sd->sensor_type = 1; | ||
528 | sd->do_lcd_stop = 0; | ||
529 | sd->adj_colors = 0; | ||
530 | if ((gspca_dev->usb_buf[0] != 0x03) && | ||
531 | (gspca_dev->usb_buf[0] != 0x04)) { | ||
532 | PDEBUG(D_ERR, "Unknown VGA Sensor id Byte 0: %02x", | ||
533 | gspca_dev->usb_buf[1]); | ||
534 | PDEBUG(D_ERR, "Defaults assumed, may not work"); | ||
535 | PDEBUG(D_ERR, "Please report this"); | ||
536 | } | ||
537 | /* Sakar Digital color needs to be adjusted. */ | ||
538 | if ((gspca_dev->usb_buf[0] == 0x03) && | ||
539 | (gspca_dev->usb_buf[1] == 0x50)) | ||
540 | sd->adj_colors = 1; | ||
541 | if (gspca_dev->usb_buf[0] == 0x04) { | ||
542 | sd->do_lcd_stop = 1; | ||
543 | switch (gspca_dev->usb_buf[1]) { | ||
544 | case 0x50: | ||
545 | sd->sensor_type = 0; | ||
546 | PDEBUG(D_PROBE, "sensor_type corrected to 0"); | ||
547 | break; | ||
548 | case 0x20: | ||
549 | /* Nothing to do here. */ | ||
550 | break; | ||
551 | default: | ||
552 | PDEBUG(D_ERR, | ||
553 | "Unknown VGA Sensor id Byte 1: %02x", | ||
554 | gspca_dev->usb_buf[1]); | ||
555 | PDEBUG(D_ERR, | ||
556 | "Defaults assumed, may not work"); | ||
557 | PDEBUG(D_ERR, "Please report this"); | ||
558 | } | ||
414 | } | 559 | } |
560 | PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d", | ||
561 | sd->sensor_type); | ||
562 | } | ||
563 | /* Stop streaming as we've started it to probe the sensor type. */ | ||
564 | sd_stopN(gspca_dev); | ||
565 | |||
566 | if (force_sensor_type != -1) { | ||
567 | sd->sensor_type = !!force_sensor_type; | ||
568 | PDEBUG(D_PROBE, "Forcing sensor type to: %d", | ||
569 | sd->sensor_type); | ||
570 | } | ||
415 | 571 | ||
572 | /* Setup controls depending on camera type */ | ||
573 | if (sd->cam_type == CAM_TYPE_CIF) { | ||
574 | /* No brightness for sensor_type 0 */ | ||
416 | if (sd->sensor_type == 0) | 575 | if (sd->sensor_type == 0) |
417 | gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX); | 576 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | |
577 | (1 << ARGUS_QC_BRIGHTNESS_IDX); | ||
578 | else | ||
579 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) | | ||
580 | (1 << MIN_CLOCKDIV_IDX); | ||
418 | } else { | 581 | } else { |
419 | sd->cam_type = CAM_TYPE_VGA; | 582 | /* All controls need to be disabled if VGA sensor_type is 0 */ |
420 | PDEBUG(D_PROBE, "MR97310A VGA camera detected"); | 583 | if (sd->sensor_type == 0) |
421 | gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) | | 584 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | |
422 | (1 << EXPOSURE_IDX) | (1 << GAIN_IDX); | 585 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | |
586 | (1 << EXPOSURE_IDX) | | ||
587 | (1 << GAIN_IDX) | | ||
588 | (1 << MIN_CLOCKDIV_IDX); | ||
589 | else if (sd->do_lcd_stop) | ||
590 | /* Argus QuickClix has different brightness limits */ | ||
591 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX); | ||
592 | else | ||
593 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX); | ||
423 | } | 594 | } |
424 | 595 | ||
425 | sd->brightness = MR97310A_BRIGHTNESS_DEFAULT; | 596 | sd->brightness = MR97310A_BRIGHTNESS_DEFAULT; |
426 | sd->exposure = MR97310A_EXPOSURE_DEFAULT; | 597 | sd->exposure = MR97310A_EXPOSURE_DEFAULT; |
427 | sd->gain = MR97310A_GAIN_DEFAULT; | 598 | sd->gain = MR97310A_GAIN_DEFAULT; |
599 | sd->min_clockdiv = MR97310A_MIN_CLOCKDIV_DEFAULT; | ||
428 | 600 | ||
429 | return 0; | 601 | return 0; |
430 | } | 602 | } |
@@ -455,11 +627,6 @@ static int start_cif_cam(struct gspca_dev *gspca_dev) | |||
455 | }; | 627 | }; |
456 | 628 | ||
457 | /* Note: Some of the above descriptions guessed from MR97113A driver */ | 629 | /* Note: Some of the above descriptions guessed from MR97113A driver */ |
458 | data[0] = 0x01; | ||
459 | data[1] = 0x01; | ||
460 | err_code = mr_write(gspca_dev, 2); | ||
461 | if (err_code < 0) | ||
462 | return err_code; | ||
463 | 630 | ||
464 | memcpy(data, startup_string, 11); | 631 | memcpy(data, startup_string, 11); |
465 | if (sd->sensor_type) | 632 | if (sd->sensor_type) |
@@ -533,22 +700,7 @@ static int start_cif_cam(struct gspca_dev *gspca_dev) | |||
533 | err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data, | 700 | err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data, |
534 | ARRAY_SIZE(cif_sensor1_init_data)); | 701 | ARRAY_SIZE(cif_sensor1_init_data)); |
535 | } | 702 | } |
536 | if (err_code < 0) | 703 | return err_code; |
537 | return err_code; | ||
538 | |||
539 | setbrightness(gspca_dev); | ||
540 | setexposure(gspca_dev); | ||
541 | setgain(gspca_dev); | ||
542 | |||
543 | msleep(200); | ||
544 | |||
545 | data[0] = 0x00; | ||
546 | data[1] = 0x4d; /* ISOC transfering enable... */ | ||
547 | err_code = mr_write(gspca_dev, 2); | ||
548 | if (err_code < 0) | ||
549 | return err_code; | ||
550 | |||
551 | return 0; | ||
552 | } | 704 | } |
553 | 705 | ||
554 | static int start_vga_cam(struct gspca_dev *gspca_dev) | 706 | static int start_vga_cam(struct gspca_dev *gspca_dev) |
@@ -558,84 +710,8 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
558 | int err_code; | 710 | int err_code; |
559 | const __u8 startup_string[] = {0x00, 0x0d, 0x01, 0x00, 0x00, 0x2b, | 711 | const __u8 startup_string[] = {0x00, 0x0d, 0x01, 0x00, 0x00, 0x2b, |
560 | 0x00, 0x00, 0x00, 0x50, 0xc0}; | 712 | 0x00, 0x00, 0x00, 0x50, 0xc0}; |
561 | |||
562 | /* What some of these mean is explained in start_cif_cam(), above */ | 713 | /* What some of these mean is explained in start_cif_cam(), above */ |
563 | sd->sof_read = 0; | ||
564 | |||
565 | /* | ||
566 | * We have to know which camera we have, because the register writes | ||
567 | * depend upon the camera. This test, run before we actually enter | ||
568 | * the initialization routine, distinguishes most of the cameras, If | ||
569 | * needed, another routine is done later, too. | ||
570 | */ | ||
571 | memset(data, 0, 16); | ||
572 | data[0] = 0x20; | ||
573 | err_code = mr_write(gspca_dev, 1); | ||
574 | if (err_code < 0) | ||
575 | return err_code; | ||
576 | |||
577 | err_code = mr_read(gspca_dev, 16); | ||
578 | if (err_code < 0) | ||
579 | return err_code; | ||
580 | |||
581 | PDEBUG(D_PROBE, "Byte reported is %02x", data[0]); | ||
582 | |||
583 | msleep(200); | ||
584 | /* | ||
585 | * Known VGA cameras. If you have another to report, please do | ||
586 | * | ||
587 | * Name byte just read sd->sensor_type | ||
588 | * sd->do_lcd_stop | ||
589 | * Aiptek Pencam VGA+ 0x31 0 1 | ||
590 | * ION digital 0x31 0 1 | ||
591 | * Argus DC-1620 0x30 1 0 | ||
592 | * Argus QuickClix 0x30 1 1 (not caught here) | ||
593 | */ | ||
594 | sd->sensor_type = data[0] & 1; | ||
595 | sd->do_lcd_stop = (~data[0]) & 1; | ||
596 | |||
597 | |||
598 | |||
599 | /* Streaming setup begins here. */ | ||
600 | |||
601 | |||
602 | data[0] = 0x01; | ||
603 | data[1] = 0x01; | ||
604 | err_code = mr_write(gspca_dev, 2); | ||
605 | if (err_code < 0) | ||
606 | return err_code; | ||
607 | 714 | ||
608 | /* | ||
609 | * A second test can now resolve any remaining ambiguity in the | ||
610 | * identification of the camera type, | ||
611 | */ | ||
612 | if (!sd->sensor_type) { | ||
613 | data[0] = get_sensor_id(gspca_dev); | ||
614 | if (data[0] == 0x7f) { | ||
615 | sd->sensor_type = 1; | ||
616 | PDEBUG(D_PROBE, "sensor_type corrected to 1"); | ||
617 | } | ||
618 | msleep(200); | ||
619 | } | ||
620 | |||
621 | if (force_sensor_type != -1) { | ||
622 | sd->sensor_type = !! force_sensor_type; | ||
623 | PDEBUG(D_PROBE, "Forcing sensor type to: %d", | ||
624 | sd->sensor_type); | ||
625 | } | ||
626 | |||
627 | /* | ||
628 | * Known VGA cameras. | ||
629 | * This test is only run if the previous test returned 0x30, but | ||
630 | * here is the information for all others, too, just for reference. | ||
631 | * | ||
632 | * Name byte just read sd->sensor_type | ||
633 | * | ||
634 | * Aiptek Pencam VGA+ 0xfb (this test not run) 1 | ||
635 | * ION digital 0xbd (this test not run) 1 | ||
636 | * Argus DC-1620 0xe5 (no change) 0 | ||
637 | * Argus QuickClix 0x7f (reclassified) 1 | ||
638 | */ | ||
639 | memcpy(data, startup_string, 11); | 715 | memcpy(data, startup_string, 11); |
640 | if (!sd->sensor_type) { | 716 | if (!sd->sensor_type) { |
641 | data[5] = 0x00; | 717 | data[5] = 0x00; |
@@ -689,29 +765,44 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
689 | err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data, | 765 | err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data, |
690 | ARRAY_SIZE(vga_sensor0_init_data)); | 766 | ARRAY_SIZE(vga_sensor0_init_data)); |
691 | } else { /* sd->sensor_type = 1 */ | 767 | } else { /* sd->sensor_type = 1 */ |
692 | const struct sensor_w_data vga_sensor1_init_data[] = { | 768 | const struct sensor_w_data color_adj[] = { |
693 | {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, | 769 | {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, |
694 | 0x07, 0x00, 0x01}, 8}, | 770 | /* adjusted blue, green, red gain correct |
771 | too much blue from the Sakar Digital */ | ||
772 | 0x05, 0x01, 0x04}, 8} | ||
773 | }; | ||
774 | |||
775 | const struct sensor_w_data color_no_adj[] = { | ||
776 | {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, | ||
777 | /* default blue, green, red gain settings */ | ||
778 | 0x07, 0x00, 0x01}, 8} | ||
779 | }; | ||
780 | |||
781 | const struct sensor_w_data vga_sensor1_init_data[] = { | ||
695 | {0x11, 0x04, {0x01}, 1}, | 782 | {0x11, 0x04, {0x01}, 1}, |
696 | /*{0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01, */ | 783 | {0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01, |
697 | {0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01, | 784 | /* These settings may be better for some cameras */ |
785 | /* {0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01, */ | ||
698 | 0x00, 0x0a}, 7}, | 786 | 0x00, 0x0a}, 7}, |
699 | {0x11, 0x04, {0x01}, 1}, | 787 | {0x11, 0x04, {0x01}, 1}, |
700 | {0x12, 0x00, {0x00, 0x63, 0x00, 0x70, 0x00, 0x00}, 6}, | 788 | {0x12, 0x00, {0x00, 0x63, 0x00, 0x70, 0x00, 0x00}, 6}, |
701 | {0x11, 0x04, {0x01}, 1}, | 789 | {0x11, 0x04, {0x01}, 1}, |
702 | {0, 0, {0}, 0} | 790 | {0, 0, {0}, 0} |
703 | }; | 791 | }; |
792 | |||
793 | if (sd->adj_colors) | ||
794 | err_code = sensor_write_regs(gspca_dev, color_adj, | ||
795 | ARRAY_SIZE(color_adj)); | ||
796 | else | ||
797 | err_code = sensor_write_regs(gspca_dev, color_no_adj, | ||
798 | ARRAY_SIZE(color_no_adj)); | ||
799 | |||
800 | if (err_code < 0) | ||
801 | return err_code; | ||
802 | |||
704 | err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data, | 803 | err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data, |
705 | ARRAY_SIZE(vga_sensor1_init_data)); | 804 | ARRAY_SIZE(vga_sensor1_init_data)); |
706 | } | 805 | } |
707 | if (err_code < 0) | ||
708 | return err_code; | ||
709 | |||
710 | msleep(200); | ||
711 | data[0] = 0x00; | ||
712 | data[1] = 0x4d; /* ISOC transfering enable... */ | ||
713 | err_code = mr_write(gspca_dev, 2); | ||
714 | |||
715 | return err_code; | 806 | return err_code; |
716 | } | 807 | } |
717 | 808 | ||
@@ -719,97 +810,120 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
719 | { | 810 | { |
720 | struct sd *sd = (struct sd *) gspca_dev; | 811 | struct sd *sd = (struct sd *) gspca_dev; |
721 | int err_code; | 812 | int err_code; |
722 | struct cam *cam; | ||
723 | 813 | ||
724 | cam = &gspca_dev->cam; | ||
725 | sd->sof_read = 0; | 814 | sd->sof_read = 0; |
726 | /* | 815 | |
727 | * Some of the supported cameras require the memory pointer to be | 816 | /* Some of the VGA cameras require the memory pointer |
728 | * set to 0, or else they will not stream. | 817 | * to be set to 0 again. We have been forced to start the |
729 | */ | 818 | * stream in sd_config() to detect the hardware, and closed it. |
730 | zero_the_pointer(gspca_dev); | 819 | * Thus, we need here to do a completely fresh and clean start. */ |
731 | msleep(200); | 820 | err_code = zero_the_pointer(gspca_dev); |
821 | if (err_code < 0) | ||
822 | return err_code; | ||
823 | |||
824 | err_code = stream_start(gspca_dev); | ||
825 | if (err_code < 0) | ||
826 | return err_code; | ||
827 | |||
732 | if (sd->cam_type == CAM_TYPE_CIF) { | 828 | if (sd->cam_type == CAM_TYPE_CIF) { |
733 | err_code = start_cif_cam(gspca_dev); | 829 | err_code = start_cif_cam(gspca_dev); |
734 | } else { | 830 | } else { |
735 | err_code = start_vga_cam(gspca_dev); | 831 | err_code = start_vga_cam(gspca_dev); |
736 | } | 832 | } |
737 | return err_code; | 833 | if (err_code < 0) |
834 | return err_code; | ||
835 | |||
836 | setbrightness(gspca_dev); | ||
837 | setexposure(gspca_dev); | ||
838 | setgain(gspca_dev); | ||
839 | |||
840 | return isoc_enable(gspca_dev); | ||
738 | } | 841 | } |
739 | 842 | ||
740 | static void sd_stopN(struct gspca_dev *gspca_dev) | 843 | static void sd_stopN(struct gspca_dev *gspca_dev) |
741 | { | 844 | { |
742 | struct sd *sd = (struct sd *) gspca_dev; | 845 | struct sd *sd = (struct sd *) gspca_dev; |
743 | int result; | ||
744 | |||
745 | gspca_dev->usb_buf[0] = 1; | ||
746 | gspca_dev->usb_buf[1] = 0; | ||
747 | result = mr_write(gspca_dev, 2); | ||
748 | if (result < 0) | ||
749 | PDEBUG(D_ERR, "Camera Stop failed"); | ||
750 | 846 | ||
847 | stream_stop(gspca_dev); | ||
751 | /* Not all the cams need this, but even if not, probably a good idea */ | 848 | /* Not all the cams need this, but even if not, probably a good idea */ |
752 | zero_the_pointer(gspca_dev); | 849 | zero_the_pointer(gspca_dev); |
753 | if (sd->do_lcd_stop) { | 850 | if (sd->do_lcd_stop) |
754 | gspca_dev->usb_buf[0] = 0x19; | 851 | lcd_stop(gspca_dev); |
755 | gspca_dev->usb_buf[1] = 0x54; | ||
756 | result = mr_write(gspca_dev, 2); | ||
757 | if (result < 0) | ||
758 | PDEBUG(D_ERR, "Camera Stop failed"); | ||
759 | } | ||
760 | } | 852 | } |
761 | 853 | ||
762 | static void setbrightness(struct gspca_dev *gspca_dev) | 854 | static void setbrightness(struct gspca_dev *gspca_dev) |
763 | { | 855 | { |
764 | struct sd *sd = (struct sd *) gspca_dev; | 856 | struct sd *sd = (struct sd *) gspca_dev; |
765 | u8 val; | 857 | u8 val; |
766 | 858 | u8 sign_reg = 7; /* This reg and the next one used on CIF cams. */ | |
767 | if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS_IDX)) | 859 | u8 value_reg = 8; /* VGA cams seem to use regs 0x0b and 0x0c */ |
860 | const u8 quick_clix_table[] = | ||
861 | /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ | ||
862 | { 0, 4, 8, 12, 1, 2, 3, 5, 6, 9, 7, 10, 13, 11, 14, 15}; | ||
863 | /* | ||
864 | * This control is disabled for CIF type 1 and VGA type 0 cameras. | ||
865 | * It does not quite act linearly for the Argus QuickClix camera, | ||
866 | * but it does control brightness. The values are 0 - 15 only, and | ||
867 | * the table above makes them act consecutively. | ||
868 | */ | ||
869 | if ((gspca_dev->ctrl_dis & (1 << NORM_BRIGHTNESS_IDX)) && | ||
870 | (gspca_dev->ctrl_dis & (1 << ARGUS_QC_BRIGHTNESS_IDX))) | ||
768 | return; | 871 | return; |
769 | 872 | ||
770 | /* Note register 7 is also seen as 0x8x or 0xCx in dumps */ | 873 | if (sd->cam_type == CAM_TYPE_VGA) { |
874 | sign_reg += 4; | ||
875 | value_reg += 4; | ||
876 | } | ||
877 | |||
878 | /* Note register 7 is also seen as 0x8x or 0xCx in some dumps */ | ||
771 | if (sd->brightness > 0) { | 879 | if (sd->brightness > 0) { |
772 | sensor_write1(gspca_dev, 7, 0x00); | 880 | sensor_write1(gspca_dev, sign_reg, 0x00); |
773 | val = sd->brightness; | 881 | val = sd->brightness; |
774 | } else { | 882 | } else { |
775 | sensor_write1(gspca_dev, 7, 0x01); | 883 | sensor_write1(gspca_dev, sign_reg, 0x01); |
776 | val = 257 - sd->brightness; | 884 | val = (257 - sd->brightness); |
777 | } | 885 | } |
778 | sensor_write1(gspca_dev, 8, val); | 886 | /* Use lookup table for funky Argus QuickClix brightness */ |
887 | if (sd->do_lcd_stop) | ||
888 | val = quick_clix_table[val]; | ||
889 | |||
890 | sensor_write1(gspca_dev, value_reg, val); | ||
779 | } | 891 | } |
780 | 892 | ||
781 | static void setexposure(struct gspca_dev *gspca_dev) | 893 | static void setexposure(struct gspca_dev *gspca_dev) |
782 | { | 894 | { |
783 | struct sd *sd = (struct sd *) gspca_dev; | 895 | struct sd *sd = (struct sd *) gspca_dev; |
784 | u8 val; | 896 | int exposure; |
897 | u8 buf[2]; | ||
785 | 898 | ||
786 | if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) | 899 | if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) |
787 | return; | 900 | return; |
788 | 901 | ||
789 | if (sd->sensor_type) { | 902 | if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) { |
790 | val = sd->exposure >> 4; | 903 | /* This cam does not like exposure settings < 300, |
791 | sensor_write1(gspca_dev, 3, val); | 904 | so scale 0 - 4095 to 300 - 4095 */ |
792 | val = sd->exposure & 0xf; | 905 | exposure = (sd->exposure * 9267) / 10000 + 300; |
793 | sensor_write1(gspca_dev, 4, val); | 906 | sensor_write1(gspca_dev, 3, exposure >> 4); |
907 | sensor_write1(gspca_dev, 4, exposure & 0x0f); | ||
794 | } else { | 908 | } else { |
795 | u8 clockdiv; | ||
796 | int exposure; | ||
797 | |||
798 | /* We have both a clock divider and an exposure register. | 909 | /* We have both a clock divider and an exposure register. |
799 | We first calculate the clock divider, as that determines | 910 | We first calculate the clock divider, as that determines |
800 | the maximum exposure and then we calculayte the exposure | 911 | the maximum exposure and then we calculate the exposure |
801 | register setting (which goes from 0 - 511). | 912 | register setting (which goes from 0 - 511). |
802 | 913 | ||
803 | Note our 0 - 4095 exposure is mapped to 0 - 511 | 914 | Note our 0 - 4095 exposure is mapped to 0 - 511 |
804 | milliseconds exposure time */ | 915 | milliseconds exposure time */ |
805 | clockdiv = (60 * sd->exposure + 7999) / 8000; | 916 | u8 clockdiv = (60 * sd->exposure + 7999) / 8000; |
806 | 917 | ||
807 | /* Limit framerate to not exceed usb bandwidth */ | 918 | /* Limit framerate to not exceed usb bandwidth */ |
808 | if (clockdiv < 3 && gspca_dev->width >= 320) | 919 | if (clockdiv < sd->min_clockdiv && gspca_dev->width >= 320) |
809 | clockdiv = 3; | 920 | clockdiv = sd->min_clockdiv; |
810 | else if (clockdiv < 2) | 921 | else if (clockdiv < 2) |
811 | clockdiv = 2; | 922 | clockdiv = 2; |
812 | 923 | ||
924 | if (sd->cam_type == CAM_TYPE_VGA && clockdiv < 4) | ||
925 | clockdiv = 4; | ||
926 | |||
813 | /* Frame exposure time in ms = 1000 * clockdiv / 60 -> | 927 | /* Frame exposure time in ms = 1000 * clockdiv / 60 -> |
814 | exposure = (sd->exposure / 8) * 511 / (1000 * clockdiv / 60) */ | 928 | exposure = (sd->exposure / 8) * 511 / (1000 * clockdiv / 60) */ |
815 | exposure = (60 * 511 * sd->exposure) / (8000 * clockdiv); | 929 | exposure = (60 * 511 * sd->exposure) / (8000 * clockdiv); |
@@ -819,9 +933,10 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
819 | /* exposure register value is reversed! */ | 933 | /* exposure register value is reversed! */ |
820 | exposure = 511 - exposure; | 934 | exposure = 511 - exposure; |
821 | 935 | ||
936 | buf[0] = exposure & 0xff; | ||
937 | buf[1] = exposure >> 8; | ||
938 | sensor_write_reg(gspca_dev, 0x0e, 0, buf, 2); | ||
822 | sensor_write1(gspca_dev, 0x02, clockdiv); | 939 | sensor_write1(gspca_dev, 0x02, clockdiv); |
823 | sensor_write1(gspca_dev, 0x0e, exposure & 0xff); | ||
824 | sensor_write1(gspca_dev, 0x0f, exposure >> 8); | ||
825 | } | 940 | } |
826 | } | 941 | } |
827 | 942 | ||
@@ -832,7 +947,7 @@ static void setgain(struct gspca_dev *gspca_dev) | |||
832 | if (gspca_dev->ctrl_dis & (1 << GAIN_IDX)) | 947 | if (gspca_dev->ctrl_dis & (1 << GAIN_IDX)) |
833 | return; | 948 | return; |
834 | 949 | ||
835 | if (sd->sensor_type) { | 950 | if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) { |
836 | sensor_write1(gspca_dev, 0x0e, sd->gain); | 951 | sensor_write1(gspca_dev, 0x0e, sd->gain); |
837 | } else { | 952 | } else { |
838 | sensor_write1(gspca_dev, 0x10, sd->gain); | 953 | sensor_write1(gspca_dev, 0x10, sd->gain); |
@@ -893,17 +1008,35 @@ static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) | |||
893 | return 0; | 1008 | return 0; |
894 | } | 1009 | } |
895 | 1010 | ||
1011 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val) | ||
1012 | { | ||
1013 | struct sd *sd = (struct sd *) gspca_dev; | ||
1014 | |||
1015 | sd->min_clockdiv = val; | ||
1016 | if (gspca_dev->streaming) | ||
1017 | setexposure(gspca_dev); | ||
1018 | return 0; | ||
1019 | } | ||
1020 | |||
1021 | static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val) | ||
1022 | { | ||
1023 | struct sd *sd = (struct sd *) gspca_dev; | ||
1024 | |||
1025 | *val = sd->min_clockdiv; | ||
1026 | return 0; | ||
1027 | } | ||
1028 | |||
896 | /* Include pac common sof detection functions */ | 1029 | /* Include pac common sof detection functions */ |
897 | #include "pac_common.h" | 1030 | #include "pac_common.h" |
898 | 1031 | ||
899 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 1032 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
900 | struct gspca_frame *frame, /* target */ | 1033 | u8 *data, /* isoc packet */ |
901 | __u8 *data, /* isoc packet */ | 1034 | int len) /* iso packet length */ |
902 | int len) /* iso packet length */ | ||
903 | { | 1035 | { |
1036 | struct sd *sd = (struct sd *) gspca_dev; | ||
904 | unsigned char *sof; | 1037 | unsigned char *sof; |
905 | 1038 | ||
906 | sof = pac_find_sof(gspca_dev, data, len); | 1039 | sof = pac_find_sof(&sd->sof_read, data, len); |
907 | if (sof) { | 1040 | if (sof) { |
908 | int n; | 1041 | int n; |
909 | 1042 | ||
@@ -913,15 +1046,15 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
913 | n -= sizeof pac_sof_marker; | 1046 | n -= sizeof pac_sof_marker; |
914 | else | 1047 | else |
915 | n = 0; | 1048 | n = 0; |
916 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | 1049 | gspca_frame_add(gspca_dev, LAST_PACKET, |
917 | data, n); | 1050 | data, n); |
918 | /* Start next frame. */ | 1051 | /* Start next frame. */ |
919 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | 1052 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
920 | pac_sof_marker, sizeof pac_sof_marker); | 1053 | pac_sof_marker, sizeof pac_sof_marker); |
921 | len -= sof - data; | 1054 | len -= sof - data; |
922 | data = sof; | 1055 | data = sof; |
923 | } | 1056 | } |
924 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | 1057 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
925 | } | 1058 | } |
926 | 1059 | ||
927 | /* sub-driver description */ | 1060 | /* sub-driver description */ |
@@ -938,6 +1071,7 @@ static const struct sd_desc sd_desc = { | |||
938 | 1071 | ||
939 | /* -- module initialisation -- */ | 1072 | /* -- module initialisation -- */ |
940 | static const __devinitdata struct usb_device_id device_table[] = { | 1073 | static const __devinitdata struct usb_device_id device_table[] = { |
1074 | {USB_DEVICE(0x08ca, 0x0110)}, /* Trust Spyc@m 100 */ | ||
941 | {USB_DEVICE(0x08ca, 0x0111)}, /* Aiptek Pencam VGA+ */ | 1075 | {USB_DEVICE(0x08ca, 0x0111)}, /* Aiptek Pencam VGA+ */ |
942 | {USB_DEVICE(0x093a, 0x010f)}, /* All other known MR97310A VGA cams */ | 1076 | {USB_DEVICE(0x093a, 0x010f)}, /* All other known MR97310A VGA cams */ |
943 | {USB_DEVICE(0x093a, 0x010e)}, /* All known MR97310A CIF cams */ | 1077 | {USB_DEVICE(0x093a, 0x010e)}, /* All known MR97310A CIF cams */ |
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index a5c190e93799..ad9ec339981d 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c | |||
@@ -2,14 +2,19 @@ | |||
2 | * OV519 driver | 2 | * OV519 driver |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr) | 4 | * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr) |
5 | * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> | ||
5 | * | 6 | * |
6 | * This module is adapted from the ov51x-jpeg package, which itself | 7 | * This module is adapted from the ov51x-jpeg package, which itself |
7 | * was adapted from the ov511 driver. | 8 | * was adapted from the ov511 driver. |
8 | * | 9 | * |
9 | * Original copyright for the ov511 driver is: | 10 | * Original copyright for the ov511 driver is: |
10 | * | 11 | * |
11 | * Copyright (c) 1999-2004 Mark W. McClelland | 12 | * Copyright (c) 1999-2006 Mark W. McClelland |
12 | * Support for OV519, OV8610 Copyright (c) 2003 Joerg Heckenbach | 13 | * Support for OV519, OV8610 Copyright (c) 2003 Joerg Heckenbach |
14 | * Many improvements by Bret Wallach <bwallac1@san.rr.com> | ||
15 | * Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000) | ||
16 | * OV7620 fixes by Charl P. Botha <cpbotha@ieee.org> | ||
17 | * Changes by Claudio Matsuoka <claudio@conectiva.com> | ||
13 | * | 18 | * |
14 | * ov51x-jpeg original copyright is: | 19 | * ov51x-jpeg original copyright is: |
15 | * | 20 | * |
@@ -58,6 +63,8 @@ struct sd { | |||
58 | #define BRIDGE_OV518 2 | 63 | #define BRIDGE_OV518 2 |
59 | #define BRIDGE_OV518PLUS 3 | 64 | #define BRIDGE_OV518PLUS 3 |
60 | #define BRIDGE_OV519 4 | 65 | #define BRIDGE_OV519 4 |
66 | #define BRIDGE_OVFX2 5 | ||
67 | #define BRIDGE_W9968CF 6 | ||
61 | #define BRIDGE_MASK 7 | 68 | #define BRIDGE_MASK 7 |
62 | 69 | ||
63 | char invert_led; | 70 | char invert_led; |
@@ -73,6 +80,10 @@ struct sd { | |||
73 | __u8 vflip; | 80 | __u8 vflip; |
74 | __u8 autobrightness; | 81 | __u8 autobrightness; |
75 | __u8 freq; | 82 | __u8 freq; |
83 | __u8 quality; | ||
84 | #define QUALITY_MIN 50 | ||
85 | #define QUALITY_MAX 70 | ||
86 | #define QUALITY_DEF 50 | ||
76 | 87 | ||
77 | __u8 stopped; /* Streaming is temporarily paused */ | 88 | __u8 stopped; /* Streaming is temporarily paused */ |
78 | 89 | ||
@@ -81,17 +92,31 @@ struct sd { | |||
81 | 92 | ||
82 | char sensor; /* Type of image sensor chip (SEN_*) */ | 93 | char sensor; /* Type of image sensor chip (SEN_*) */ |
83 | #define SEN_UNKNOWN 0 | 94 | #define SEN_UNKNOWN 0 |
84 | #define SEN_OV6620 1 | 95 | #define SEN_OV2610 1 |
85 | #define SEN_OV6630 2 | 96 | #define SEN_OV3610 2 |
86 | #define SEN_OV66308AF 3 | 97 | #define SEN_OV6620 3 |
87 | #define SEN_OV7610 4 | 98 | #define SEN_OV6630 4 |
88 | #define SEN_OV7620 5 | 99 | #define SEN_OV66308AF 5 |
89 | #define SEN_OV7640 6 | 100 | #define SEN_OV7610 6 |
90 | #define SEN_OV7670 7 | 101 | #define SEN_OV7620 7 |
91 | #define SEN_OV76BE 8 | 102 | #define SEN_OV7640 8 |
92 | #define SEN_OV8610 9 | 103 | #define SEN_OV7670 9 |
104 | #define SEN_OV76BE 10 | ||
105 | #define SEN_OV8610 11 | ||
106 | |||
107 | u8 sensor_addr; | ||
108 | int sensor_width; | ||
109 | int sensor_height; | ||
110 | int sensor_reg_cache[256]; | ||
111 | |||
112 | u8 *jpeg_hdr; | ||
93 | }; | 113 | }; |
94 | 114 | ||
115 | /* Note this is a bit of a hack, but the w9968cf driver needs the code for all | ||
116 | the ov sensors which is already present here. When we have the time we | ||
117 | really should move the sensor drivers to v4l2 sub drivers. */ | ||
118 | #include "w996Xcf.c" | ||
119 | |||
95 | /* V4L2 controls supported by the driver */ | 120 | /* V4L2 controls supported by the driver */ |
96 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | 121 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); |
97 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | 122 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); |
@@ -345,6 +370,75 @@ static const struct v4l2_pix_format ov511_sif_mode[] = { | |||
345 | .priv = 0}, | 370 | .priv = 0}, |
346 | }; | 371 | }; |
347 | 372 | ||
373 | static const struct v4l2_pix_format ovfx2_vga_mode[] = { | ||
374 | {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
375 | .bytesperline = 320, | ||
376 | .sizeimage = 320 * 240, | ||
377 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
378 | .priv = 1}, | ||
379 | {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
380 | .bytesperline = 640, | ||
381 | .sizeimage = 640 * 480, | ||
382 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
383 | .priv = 0}, | ||
384 | }; | ||
385 | static const struct v4l2_pix_format ovfx2_cif_mode[] = { | ||
386 | {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
387 | .bytesperline = 160, | ||
388 | .sizeimage = 160 * 120, | ||
389 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
390 | .priv = 3}, | ||
391 | {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
392 | .bytesperline = 176, | ||
393 | .sizeimage = 176 * 144, | ||
394 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
395 | .priv = 1}, | ||
396 | {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
397 | .bytesperline = 320, | ||
398 | .sizeimage = 320 * 240, | ||
399 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
400 | .priv = 2}, | ||
401 | {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
402 | .bytesperline = 352, | ||
403 | .sizeimage = 352 * 288, | ||
404 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
405 | .priv = 0}, | ||
406 | }; | ||
407 | static const struct v4l2_pix_format ovfx2_ov2610_mode[] = { | ||
408 | {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
409 | .bytesperline = 1600, | ||
410 | .sizeimage = 1600 * 1200, | ||
411 | .colorspace = V4L2_COLORSPACE_SRGB}, | ||
412 | }; | ||
413 | static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { | ||
414 | {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
415 | .bytesperline = 640, | ||
416 | .sizeimage = 640 * 480, | ||
417 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
418 | .priv = 1}, | ||
419 | {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
420 | .bytesperline = 800, | ||
421 | .sizeimage = 800 * 600, | ||
422 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
423 | .priv = 1}, | ||
424 | {1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
425 | .bytesperline = 1024, | ||
426 | .sizeimage = 1024 * 768, | ||
427 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
428 | .priv = 1}, | ||
429 | {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
430 | .bytesperline = 1600, | ||
431 | .sizeimage = 1600 * 1200, | ||
432 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
433 | .priv = 0}, | ||
434 | {2048, 1536, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
435 | .bytesperline = 2048, | ||
436 | .sizeimage = 2048 * 1536, | ||
437 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
438 | .priv = 0}, | ||
439 | }; | ||
440 | |||
441 | |||
348 | /* Registers common to OV511 / OV518 */ | 442 | /* Registers common to OV511 / OV518 */ |
349 | #define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */ | 443 | #define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */ |
350 | #define R51x_SYS_RESET 0x50 | 444 | #define R51x_SYS_RESET 0x50 |
@@ -406,6 +500,30 @@ static const struct v4l2_pix_format ov511_sif_mode[] = { | |||
406 | 500 | ||
407 | #define OV511_ENDPOINT_ADDRESS 1 /* Isoc endpoint number */ | 501 | #define OV511_ENDPOINT_ADDRESS 1 /* Isoc endpoint number */ |
408 | 502 | ||
503 | /* | ||
504 | * The FX2 chip does not give us a zero length read at end of frame. | ||
505 | * It does, however, give a short read at the end of a frame, if | ||
506 | * neccessary, rather than run two frames together. | ||
507 | * | ||
508 | * By choosing the right bulk transfer size, we are guaranteed to always | ||
509 | * get a short read for the last read of each frame. Frame sizes are | ||
510 | * always a composite number (width * height, or a multiple) so if we | ||
511 | * choose a prime number, we are guaranteed that the last read of a | ||
512 | * frame will be short. | ||
513 | * | ||
514 | * But it isn't that easy: the 2.6 kernel requires a multiple of 4KB, | ||
515 | * otherwise EOVERFLOW "babbling" errors occur. I have not been able | ||
516 | * to figure out why. [PMiller] | ||
517 | * | ||
518 | * The constant (13 * 4096) is the largest "prime enough" number less than 64KB. | ||
519 | * | ||
520 | * It isn't enough to know the number of bytes per frame, in case we | ||
521 | * have data dropouts or buffer overruns (even though the FX2 double | ||
522 | * buffers, there are some pretty strict real time constraints for | ||
523 | * isochronous transfer for larger frame sizes). | ||
524 | */ | ||
525 | #define OVFX2_BULK_SIZE (13 * 4096) | ||
526 | |||
409 | /* I2C registers */ | 527 | /* I2C registers */ |
410 | #define R51x_I2C_W_SID 0x41 | 528 | #define R51x_I2C_W_SID 0x41 |
411 | #define R51x_I2C_SADDR_3 0x42 | 529 | #define R51x_I2C_SADDR_3 0x42 |
@@ -413,9 +531,11 @@ static const struct v4l2_pix_format ov511_sif_mode[] = { | |||
413 | #define R51x_I2C_R_SID 0x44 | 531 | #define R51x_I2C_R_SID 0x44 |
414 | #define R51x_I2C_DATA 0x45 | 532 | #define R51x_I2C_DATA 0x45 |
415 | #define R518_I2C_CTL 0x47 /* OV518(+) only */ | 533 | #define R518_I2C_CTL 0x47 /* OV518(+) only */ |
534 | #define OVFX2_I2C_ADDR 0x00 | ||
416 | 535 | ||
417 | /* I2C ADDRESSES */ | 536 | /* I2C ADDRESSES */ |
418 | #define OV7xx0_SID 0x42 | 537 | #define OV7xx0_SID 0x42 |
538 | #define OV_HIRES_SID 0x60 /* OV9xxx / OV2xxx / OV3xxx */ | ||
419 | #define OV8xx0_SID 0xa0 | 539 | #define OV8xx0_SID 0xa0 |
420 | #define OV6xx0_SID 0xc0 | 540 | #define OV6xx0_SID 0xc0 |
421 | 541 | ||
@@ -508,6 +628,696 @@ struct ov_i2c_regvals { | |||
508 | __u8 val; | 628 | __u8 val; |
509 | }; | 629 | }; |
510 | 630 | ||
631 | /* Settings for OV2610 camera chip */ | ||
632 | static const struct ov_i2c_regvals norm_2610[] = | ||
633 | { | ||
634 | { 0x12, 0x80 }, /* reset */ | ||
635 | }; | ||
636 | |||
637 | static const struct ov_i2c_regvals norm_3620b[] = | ||
638 | { | ||
639 | /* | ||
640 | * From the datasheet: "Note that after writing to register COMH | ||
641 | * (0x12) to change the sensor mode, registers related to the | ||
642 | * sensor’s cropping window will be reset back to their default | ||
643 | * values." | ||
644 | * | ||
645 | * "wait 4096 external clock ... to make sure the sensor is | ||
646 | * stable and ready to access registers" i.e. 160us at 24MHz | ||
647 | */ | ||
648 | |||
649 | { 0x12, 0x80 }, /* COMH reset */ | ||
650 | { 0x12, 0x00 }, /* QXGA, master */ | ||
651 | |||
652 | /* | ||
653 | * 11 CLKRC "Clock Rate Control" | ||
654 | * [7] internal frequency doublers: on | ||
655 | * [6] video port mode: master | ||
656 | * [5:0] clock divider: 1 | ||
657 | */ | ||
658 | { 0x11, 0x80 }, | ||
659 | |||
660 | /* | ||
661 | * 13 COMI "Common Control I" | ||
662 | * = 192 (0xC0) 11000000 | ||
663 | * COMI[7] "AEC speed selection" | ||
664 | * = 1 (0x01) 1....... "Faster AEC correction" | ||
665 | * COMI[6] "AEC speed step selection" | ||
666 | * = 1 (0x01) .1...... "Big steps, fast" | ||
667 | * COMI[5] "Banding filter on off" | ||
668 | * = 0 (0x00) ..0..... "Off" | ||
669 | * COMI[4] "Banding filter option" | ||
670 | * = 0 (0x00) ...0.... "Main clock is 48 MHz and | ||
671 | * the PLL is ON" | ||
672 | * COMI[3] "Reserved" | ||
673 | * = 0 (0x00) ....0... | ||
674 | * COMI[2] "AGC auto manual control selection" | ||
675 | * = 0 (0x00) .....0.. "Manual" | ||
676 | * COMI[1] "AWB auto manual control selection" | ||
677 | * = 0 (0x00) ......0. "Manual" | ||
678 | * COMI[0] "Exposure control" | ||
679 | * = 0 (0x00) .......0 "Manual" | ||
680 | */ | ||
681 | { 0x13, 0xC0 }, | ||
682 | |||
683 | /* | ||
684 | * 09 COMC "Common Control C" | ||
685 | * = 8 (0x08) 00001000 | ||
686 | * COMC[7:5] "Reserved" | ||
687 | * = 0 (0x00) 000..... | ||
688 | * COMC[4] "Sleep Mode Enable" | ||
689 | * = 0 (0x00) ...0.... "Normal mode" | ||
690 | * COMC[3:2] "Sensor sampling reset timing selection" | ||
691 | * = 2 (0x02) ....10.. "Longer reset time" | ||
692 | * COMC[1:0] "Output drive current select" | ||
693 | * = 0 (0x00) ......00 "Weakest" | ||
694 | */ | ||
695 | { 0x09, 0x08 }, | ||
696 | |||
697 | /* | ||
698 | * 0C COMD "Common Control D" | ||
699 | * = 8 (0x08) 00001000 | ||
700 | * COMD[7] "Reserved" | ||
701 | * = 0 (0x00) 0....... | ||
702 | * COMD[6] "Swap MSB and LSB at the output port" | ||
703 | * = 0 (0x00) .0...... "False" | ||
704 | * COMD[5:3] "Reserved" | ||
705 | * = 1 (0x01) ..001... | ||
706 | * COMD[2] "Output Average On Off" | ||
707 | * = 0 (0x00) .....0.. "Output Normal" | ||
708 | * COMD[1] "Sensor precharge voltage selection" | ||
709 | * = 0 (0x00) ......0. "Selects internal | ||
710 | * reference precharge | ||
711 | * voltage" | ||
712 | * COMD[0] "Snapshot option" | ||
713 | * = 0 (0x00) .......0 "Enable live video output | ||
714 | * after snapshot sequence" | ||
715 | */ | ||
716 | { 0x0c, 0x08 }, | ||
717 | |||
718 | /* | ||
719 | * 0D COME "Common Control E" | ||
720 | * = 161 (0xA1) 10100001 | ||
721 | * COME[7] "Output average option" | ||
722 | * = 1 (0x01) 1....... "Output average of 4 pixels" | ||
723 | * COME[6] "Anti-blooming control" | ||
724 | * = 0 (0x00) .0...... "Off" | ||
725 | * COME[5:3] "Reserved" | ||
726 | * = 4 (0x04) ..100... | ||
727 | * COME[2] "Clock output power down pin status" | ||
728 | * = 0 (0x00) .....0.. "Tri-state data output pin | ||
729 | * on power down" | ||
730 | * COME[1] "Data output pin status selection at power down" | ||
731 | * = 0 (0x00) ......0. "Tri-state VSYNC, PCLK, | ||
732 | * HREF, and CHSYNC pins on | ||
733 | * power down" | ||
734 | * COME[0] "Auto zero circuit select" | ||
735 | * = 1 (0x01) .......1 "On" | ||
736 | */ | ||
737 | { 0x0d, 0xA1 }, | ||
738 | |||
739 | /* | ||
740 | * 0E COMF "Common Control F" | ||
741 | * = 112 (0x70) 01110000 | ||
742 | * COMF[7] "System clock selection" | ||
743 | * = 0 (0x00) 0....... "Use 24 MHz system clock" | ||
744 | * COMF[6:4] "Reserved" | ||
745 | * = 7 (0x07) .111.... | ||
746 | * COMF[3] "Manual auto negative offset canceling selection" | ||
747 | * = 0 (0x00) ....0... "Auto detect negative | ||
748 | * offset and cancel it" | ||
749 | * COMF[2:0] "Reserved" | ||
750 | * = 0 (0x00) .....000 | ||
751 | */ | ||
752 | { 0x0e, 0x70 }, | ||
753 | |||
754 | /* | ||
755 | * 0F COMG "Common Control G" | ||
756 | * = 66 (0x42) 01000010 | ||
757 | * COMG[7] "Optical black output selection" | ||
758 | * = 0 (0x00) 0....... "Disable" | ||
759 | * COMG[6] "Black level calibrate selection" | ||
760 | * = 1 (0x01) .1...... "Use optical black pixels | ||
761 | * to calibrate" | ||
762 | * COMG[5:4] "Reserved" | ||
763 | * = 0 (0x00) ..00.... | ||
764 | * COMG[3] "Channel offset adjustment" | ||
765 | * = 0 (0x00) ....0... "Disable offset adjustment" | ||
766 | * COMG[2] "ADC black level calibration option" | ||
767 | * = 0 (0x00) .....0.. "Use B/G line and G/R | ||
768 | * line to calibrate each | ||
769 | * channel's black level" | ||
770 | * COMG[1] "Reserved" | ||
771 | * = 1 (0x01) ......1. | ||
772 | * COMG[0] "ADC black level calibration enable" | ||
773 | * = 0 (0x00) .......0 "Disable" | ||
774 | */ | ||
775 | { 0x0f, 0x42 }, | ||
776 | |||
777 | /* | ||
778 | * 14 COMJ "Common Control J" | ||
779 | * = 198 (0xC6) 11000110 | ||
780 | * COMJ[7:6] "AGC gain ceiling" | ||
781 | * = 3 (0x03) 11...... "8x" | ||
782 | * COMJ[5:4] "Reserved" | ||
783 | * = 0 (0x00) ..00.... | ||
784 | * COMJ[3] "Auto banding filter" | ||
785 | * = 0 (0x00) ....0... "Banding filter is always | ||
786 | * on off depending on | ||
787 | * COMI[5] setting" | ||
788 | * COMJ[2] "VSYNC drop option" | ||
789 | * = 1 (0x01) .....1.. "SYNC is dropped if frame | ||
790 | * data is dropped" | ||
791 | * COMJ[1] "Frame data drop" | ||
792 | * = 1 (0x01) ......1. "Drop frame data if | ||
793 | * exposure is not within | ||
794 | * tolerance. In AEC mode, | ||
795 | * data is normally dropped | ||
796 | * when data is out of | ||
797 | * range." | ||
798 | * COMJ[0] "Reserved" | ||
799 | * = 0 (0x00) .......0 | ||
800 | */ | ||
801 | { 0x14, 0xC6 }, | ||
802 | |||
803 | /* | ||
804 | * 15 COMK "Common Control K" | ||
805 | * = 2 (0x02) 00000010 | ||
806 | * COMK[7] "CHSYNC pin output swap" | ||
807 | * = 0 (0x00) 0....... "CHSYNC" | ||
808 | * COMK[6] "HREF pin output swap" | ||
809 | * = 0 (0x00) .0...... "HREF" | ||
810 | * COMK[5] "PCLK output selection" | ||
811 | * = 0 (0x00) ..0..... "PCLK always output" | ||
812 | * COMK[4] "PCLK edge selection" | ||
813 | * = 0 (0x00) ...0.... "Data valid on falling edge" | ||
814 | * COMK[3] "HREF output polarity" | ||
815 | * = 0 (0x00) ....0... "positive" | ||
816 | * COMK[2] "Reserved" | ||
817 | * = 0 (0x00) .....0.. | ||
818 | * COMK[1] "VSYNC polarity" | ||
819 | * = 1 (0x01) ......1. "negative" | ||
820 | * COMK[0] "HSYNC polarity" | ||
821 | * = 0 (0x00) .......0 "positive" | ||
822 | */ | ||
823 | { 0x15, 0x02 }, | ||
824 | |||
825 | /* | ||
826 | * 33 CHLF "Current Control" | ||
827 | * = 9 (0x09) 00001001 | ||
828 | * CHLF[7:6] "Sensor current control" | ||
829 | * = 0 (0x00) 00...... | ||
830 | * CHLF[5] "Sensor current range control" | ||
831 | * = 0 (0x00) ..0..... "normal range" | ||
832 | * CHLF[4] "Sensor current" | ||
833 | * = 0 (0x00) ...0.... "normal current" | ||
834 | * CHLF[3] "Sensor buffer current control" | ||
835 | * = 1 (0x01) ....1... "half current" | ||
836 | * CHLF[2] "Column buffer current control" | ||
837 | * = 0 (0x00) .....0.. "normal current" | ||
838 | * CHLF[1] "Analog DSP current control" | ||
839 | * = 0 (0x00) ......0. "normal current" | ||
840 | * CHLF[1] "ADC current control" | ||
841 | * = 0 (0x00) ......0. "normal current" | ||
842 | */ | ||
843 | { 0x33, 0x09 }, | ||
844 | |||
845 | /* | ||
846 | * 34 VBLM "Blooming Control" | ||
847 | * = 80 (0x50) 01010000 | ||
848 | * VBLM[7] "Hard soft reset switch" | ||
849 | * = 0 (0x00) 0....... "Hard reset" | ||
850 | * VBLM[6:4] "Blooming voltage selection" | ||
851 | * = 5 (0x05) .101.... | ||
852 | * VBLM[3:0] "Sensor current control" | ||
853 | * = 0 (0x00) ....0000 | ||
854 | */ | ||
855 | { 0x34, 0x50 }, | ||
856 | |||
857 | /* | ||
858 | * 36 VCHG "Sensor Precharge Voltage Control" | ||
859 | * = 0 (0x00) 00000000 | ||
860 | * VCHG[7] "Reserved" | ||
861 | * = 0 (0x00) 0....... | ||
862 | * VCHG[6:4] "Sensor precharge voltage control" | ||
863 | * = 0 (0x00) .000.... | ||
864 | * VCHG[3:0] "Sensor array common reference" | ||
865 | * = 0 (0x00) ....0000 | ||
866 | */ | ||
867 | { 0x36, 0x00 }, | ||
868 | |||
869 | /* | ||
870 | * 37 ADC "ADC Reference Control" | ||
871 | * = 4 (0x04) 00000100 | ||
872 | * ADC[7:4] "Reserved" | ||
873 | * = 0 (0x00) 0000.... | ||
874 | * ADC[3] "ADC input signal range" | ||
875 | * = 0 (0x00) ....0... "Input signal 1.0x" | ||
876 | * ADC[2:0] "ADC range control" | ||
877 | * = 4 (0x04) .....100 | ||
878 | */ | ||
879 | { 0x37, 0x04 }, | ||
880 | |||
881 | /* | ||
882 | * 38 ACOM "Analog Common Ground" | ||
883 | * = 82 (0x52) 01010010 | ||
884 | * ACOM[7] "Analog gain control" | ||
885 | * = 0 (0x00) 0....... "Gain 1x" | ||
886 | * ACOM[6] "Analog black level calibration" | ||
887 | * = 1 (0x01) .1...... "On" | ||
888 | * ACOM[5:0] "Reserved" | ||
889 | * = 18 (0x12) ..010010 | ||
890 | */ | ||
891 | { 0x38, 0x52 }, | ||
892 | |||
893 | /* | ||
894 | * 3A FREFA "Internal Reference Adjustment" | ||
895 | * = 0 (0x00) 00000000 | ||
896 | * FREFA[7:0] "Range" | ||
897 | * = 0 (0x00) 00000000 | ||
898 | */ | ||
899 | { 0x3a, 0x00 }, | ||
900 | |||
901 | /* | ||
902 | * 3C FVOPT "Internal Reference Adjustment" | ||
903 | * = 31 (0x1F) 00011111 | ||
904 | * FVOPT[7:0] "Range" | ||
905 | * = 31 (0x1F) 00011111 | ||
906 | */ | ||
907 | { 0x3c, 0x1F }, | ||
908 | |||
909 | /* | ||
910 | * 44 Undocumented = 0 (0x00) 00000000 | ||
911 | * 44[7:0] "It's a secret" | ||
912 | * = 0 (0x00) 00000000 | ||
913 | */ | ||
914 | { 0x44, 0x00 }, | ||
915 | |||
916 | /* | ||
917 | * 40 Undocumented = 0 (0x00) 00000000 | ||
918 | * 40[7:0] "It's a secret" | ||
919 | * = 0 (0x00) 00000000 | ||
920 | */ | ||
921 | { 0x40, 0x00 }, | ||
922 | |||
923 | /* | ||
924 | * 41 Undocumented = 0 (0x00) 00000000 | ||
925 | * 41[7:0] "It's a secret" | ||
926 | * = 0 (0x00) 00000000 | ||
927 | */ | ||
928 | { 0x41, 0x00 }, | ||
929 | |||
930 | /* | ||
931 | * 42 Undocumented = 0 (0x00) 00000000 | ||
932 | * 42[7:0] "It's a secret" | ||
933 | * = 0 (0x00) 00000000 | ||
934 | */ | ||
935 | { 0x42, 0x00 }, | ||
936 | |||
937 | /* | ||
938 | * 43 Undocumented = 0 (0x00) 00000000 | ||
939 | * 43[7:0] "It's a secret" | ||
940 | * = 0 (0x00) 00000000 | ||
941 | */ | ||
942 | { 0x43, 0x00 }, | ||
943 | |||
944 | /* | ||
945 | * 45 Undocumented = 128 (0x80) 10000000 | ||
946 | * 45[7:0] "It's a secret" | ||
947 | * = 128 (0x80) 10000000 | ||
948 | */ | ||
949 | { 0x45, 0x80 }, | ||
950 | |||
951 | /* | ||
952 | * 48 Undocumented = 192 (0xC0) 11000000 | ||
953 | * 48[7:0] "It's a secret" | ||
954 | * = 192 (0xC0) 11000000 | ||
955 | */ | ||
956 | { 0x48, 0xC0 }, | ||
957 | |||
958 | /* | ||
959 | * 49 Undocumented = 25 (0x19) 00011001 | ||
960 | * 49[7:0] "It's a secret" | ||
961 | * = 25 (0x19) 00011001 | ||
962 | */ | ||
963 | { 0x49, 0x19 }, | ||
964 | |||
965 | /* | ||
966 | * 4B Undocumented = 128 (0x80) 10000000 | ||
967 | * 4B[7:0] "It's a secret" | ||
968 | * = 128 (0x80) 10000000 | ||
969 | */ | ||
970 | { 0x4B, 0x80 }, | ||
971 | |||
972 | /* | ||
973 | * 4D Undocumented = 196 (0xC4) 11000100 | ||
974 | * 4D[7:0] "It's a secret" | ||
975 | * = 196 (0xC4) 11000100 | ||
976 | */ | ||
977 | { 0x4D, 0xC4 }, | ||
978 | |||
979 | /* | ||
980 | * 35 VREF "Reference Voltage Control" | ||
981 | * = 76 (0x4C) 01001100 | ||
982 | * VREF[7:5] "Column high reference control" | ||
983 | * = 2 (0x02) 010..... "higher voltage" | ||
984 | * VREF[4:2] "Column low reference control" | ||
985 | * = 3 (0x03) ...011.. "Highest voltage" | ||
986 | * VREF[1:0] "Reserved" | ||
987 | * = 0 (0x00) ......00 | ||
988 | */ | ||
989 | { 0x35, 0x4C }, | ||
990 | |||
991 | /* | ||
992 | * 3D Undocumented = 0 (0x00) 00000000 | ||
993 | * 3D[7:0] "It's a secret" | ||
994 | * = 0 (0x00) 00000000 | ||
995 | */ | ||
996 | { 0x3D, 0x00 }, | ||
997 | |||
998 | /* | ||
999 | * 3E Undocumented = 0 (0x00) 00000000 | ||
1000 | * 3E[7:0] "It's a secret" | ||
1001 | * = 0 (0x00) 00000000 | ||
1002 | */ | ||
1003 | { 0x3E, 0x00 }, | ||
1004 | |||
1005 | /* | ||
1006 | * 3B FREFB "Internal Reference Adjustment" | ||
1007 | * = 24 (0x18) 00011000 | ||
1008 | * FREFB[7:0] "Range" | ||
1009 | * = 24 (0x18) 00011000 | ||
1010 | */ | ||
1011 | { 0x3b, 0x18 }, | ||
1012 | |||
1013 | /* | ||
1014 | * 33 CHLF "Current Control" | ||
1015 | * = 25 (0x19) 00011001 | ||
1016 | * CHLF[7:6] "Sensor current control" | ||
1017 | * = 0 (0x00) 00...... | ||
1018 | * CHLF[5] "Sensor current range control" | ||
1019 | * = 0 (0x00) ..0..... "normal range" | ||
1020 | * CHLF[4] "Sensor current" | ||
1021 | * = 1 (0x01) ...1.... "double current" | ||
1022 | * CHLF[3] "Sensor buffer current control" | ||
1023 | * = 1 (0x01) ....1... "half current" | ||
1024 | * CHLF[2] "Column buffer current control" | ||
1025 | * = 0 (0x00) .....0.. "normal current" | ||
1026 | * CHLF[1] "Analog DSP current control" | ||
1027 | * = 0 (0x00) ......0. "normal current" | ||
1028 | * CHLF[1] "ADC current control" | ||
1029 | * = 0 (0x00) ......0. "normal current" | ||
1030 | */ | ||
1031 | { 0x33, 0x19 }, | ||
1032 | |||
1033 | /* | ||
1034 | * 34 VBLM "Blooming Control" | ||
1035 | * = 90 (0x5A) 01011010 | ||
1036 | * VBLM[7] "Hard soft reset switch" | ||
1037 | * = 0 (0x00) 0....... "Hard reset" | ||
1038 | * VBLM[6:4] "Blooming voltage selection" | ||
1039 | * = 5 (0x05) .101.... | ||
1040 | * VBLM[3:0] "Sensor current control" | ||
1041 | * = 10 (0x0A) ....1010 | ||
1042 | */ | ||
1043 | { 0x34, 0x5A }, | ||
1044 | |||
1045 | /* | ||
1046 | * 3B FREFB "Internal Reference Adjustment" | ||
1047 | * = 0 (0x00) 00000000 | ||
1048 | * FREFB[7:0] "Range" | ||
1049 | * = 0 (0x00) 00000000 | ||
1050 | */ | ||
1051 | { 0x3b, 0x00 }, | ||
1052 | |||
1053 | /* | ||
1054 | * 33 CHLF "Current Control" | ||
1055 | * = 9 (0x09) 00001001 | ||
1056 | * CHLF[7:6] "Sensor current control" | ||
1057 | * = 0 (0x00) 00...... | ||
1058 | * CHLF[5] "Sensor current range control" | ||
1059 | * = 0 (0x00) ..0..... "normal range" | ||
1060 | * CHLF[4] "Sensor current" | ||
1061 | * = 0 (0x00) ...0.... "normal current" | ||
1062 | * CHLF[3] "Sensor buffer current control" | ||
1063 | * = 1 (0x01) ....1... "half current" | ||
1064 | * CHLF[2] "Column buffer current control" | ||
1065 | * = 0 (0x00) .....0.. "normal current" | ||
1066 | * CHLF[1] "Analog DSP current control" | ||
1067 | * = 0 (0x00) ......0. "normal current" | ||
1068 | * CHLF[1] "ADC current control" | ||
1069 | * = 0 (0x00) ......0. "normal current" | ||
1070 | */ | ||
1071 | { 0x33, 0x09 }, | ||
1072 | |||
1073 | /* | ||
1074 | * 34 VBLM "Blooming Control" | ||
1075 | * = 80 (0x50) 01010000 | ||
1076 | * VBLM[7] "Hard soft reset switch" | ||
1077 | * = 0 (0x00) 0....... "Hard reset" | ||
1078 | * VBLM[6:4] "Blooming voltage selection" | ||
1079 | * = 5 (0x05) .101.... | ||
1080 | * VBLM[3:0] "Sensor current control" | ||
1081 | * = 0 (0x00) ....0000 | ||
1082 | */ | ||
1083 | { 0x34, 0x50 }, | ||
1084 | |||
1085 | /* | ||
1086 | * 12 COMH "Common Control H" | ||
1087 | * = 64 (0x40) 01000000 | ||
1088 | * COMH[7] "SRST" | ||
1089 | * = 0 (0x00) 0....... "No-op" | ||
1090 | * COMH[6:4] "Resolution selection" | ||
1091 | * = 4 (0x04) .100.... "XGA" | ||
1092 | * COMH[3] "Master slave selection" | ||
1093 | * = 0 (0x00) ....0... "Master mode" | ||
1094 | * COMH[2] "Internal B/R channel option" | ||
1095 | * = 0 (0x00) .....0.. "B/R use same channel" | ||
1096 | * COMH[1] "Color bar test pattern" | ||
1097 | * = 0 (0x00) ......0. "Off" | ||
1098 | * COMH[0] "Reserved" | ||
1099 | * = 0 (0x00) .......0 | ||
1100 | */ | ||
1101 | { 0x12, 0x40 }, | ||
1102 | |||
1103 | /* | ||
1104 | * 17 HREFST "Horizontal window start" | ||
1105 | * = 31 (0x1F) 00011111 | ||
1106 | * HREFST[7:0] "Horizontal window start, 8 MSBs" | ||
1107 | * = 31 (0x1F) 00011111 | ||
1108 | */ | ||
1109 | { 0x17, 0x1F }, | ||
1110 | |||
1111 | /* | ||
1112 | * 18 HREFEND "Horizontal window end" | ||
1113 | * = 95 (0x5F) 01011111 | ||
1114 | * HREFEND[7:0] "Horizontal Window End, 8 MSBs" | ||
1115 | * = 95 (0x5F) 01011111 | ||
1116 | */ | ||
1117 | { 0x18, 0x5F }, | ||
1118 | |||
1119 | /* | ||
1120 | * 19 VSTRT "Vertical window start" | ||
1121 | * = 0 (0x00) 00000000 | ||
1122 | * VSTRT[7:0] "Vertical Window Start, 8 MSBs" | ||
1123 | * = 0 (0x00) 00000000 | ||
1124 | */ | ||
1125 | { 0x19, 0x00 }, | ||
1126 | |||
1127 | /* | ||
1128 | * 1A VEND "Vertical window end" | ||
1129 | * = 96 (0x60) 01100000 | ||
1130 | * VEND[7:0] "Vertical Window End, 8 MSBs" | ||
1131 | * = 96 (0x60) 01100000 | ||
1132 | */ | ||
1133 | { 0x1a, 0x60 }, | ||
1134 | |||
1135 | /* | ||
1136 | * 32 COMM "Common Control M" | ||
1137 | * = 18 (0x12) 00010010 | ||
1138 | * COMM[7:6] "Pixel clock divide option" | ||
1139 | * = 0 (0x00) 00...... "/1" | ||
1140 | * COMM[5:3] "Horizontal window end position, 3 LSBs" | ||
1141 | * = 2 (0x02) ..010... | ||
1142 | * COMM[2:0] "Horizontal window start position, 3 LSBs" | ||
1143 | * = 2 (0x02) .....010 | ||
1144 | */ | ||
1145 | { 0x32, 0x12 }, | ||
1146 | |||
1147 | /* | ||
1148 | * 03 COMA "Common Control A" | ||
1149 | * = 74 (0x4A) 01001010 | ||
1150 | * COMA[7:4] "AWB Update Threshold" | ||
1151 | * = 4 (0x04) 0100.... | ||
1152 | * COMA[3:2] "Vertical window end line control 2 LSBs" | ||
1153 | * = 2 (0x02) ....10.. | ||
1154 | * COMA[1:0] "Vertical window start line control 2 LSBs" | ||
1155 | * = 2 (0x02) ......10 | ||
1156 | */ | ||
1157 | { 0x03, 0x4A }, | ||
1158 | |||
1159 | /* | ||
1160 | * 11 CLKRC "Clock Rate Control" | ||
1161 | * = 128 (0x80) 10000000 | ||
1162 | * CLKRC[7] "Internal frequency doublers on off seclection" | ||
1163 | * = 1 (0x01) 1....... "On" | ||
1164 | * CLKRC[6] "Digital video master slave selection" | ||
1165 | * = 0 (0x00) .0...... "Master mode, sensor | ||
1166 | * provides PCLK" | ||
1167 | * CLKRC[5:0] "Clock divider { CLK = PCLK/(1+CLKRC[5:0]) }" | ||
1168 | * = 0 (0x00) ..000000 | ||
1169 | */ | ||
1170 | { 0x11, 0x80 }, | ||
1171 | |||
1172 | /* | ||
1173 | * 12 COMH "Common Control H" | ||
1174 | * = 0 (0x00) 00000000 | ||
1175 | * COMH[7] "SRST" | ||
1176 | * = 0 (0x00) 0....... "No-op" | ||
1177 | * COMH[6:4] "Resolution selection" | ||
1178 | * = 0 (0x00) .000.... "QXGA" | ||
1179 | * COMH[3] "Master slave selection" | ||
1180 | * = 0 (0x00) ....0... "Master mode" | ||
1181 | * COMH[2] "Internal B/R channel option" | ||
1182 | * = 0 (0x00) .....0.. "B/R use same channel" | ||
1183 | * COMH[1] "Color bar test pattern" | ||
1184 | * = 0 (0x00) ......0. "Off" | ||
1185 | * COMH[0] "Reserved" | ||
1186 | * = 0 (0x00) .......0 | ||
1187 | */ | ||
1188 | { 0x12, 0x00 }, | ||
1189 | |||
1190 | /* | ||
1191 | * 12 COMH "Common Control H" | ||
1192 | * = 64 (0x40) 01000000 | ||
1193 | * COMH[7] "SRST" | ||
1194 | * = 0 (0x00) 0....... "No-op" | ||
1195 | * COMH[6:4] "Resolution selection" | ||
1196 | * = 4 (0x04) .100.... "XGA" | ||
1197 | * COMH[3] "Master slave selection" | ||
1198 | * = 0 (0x00) ....0... "Master mode" | ||
1199 | * COMH[2] "Internal B/R channel option" | ||
1200 | * = 0 (0x00) .....0.. "B/R use same channel" | ||
1201 | * COMH[1] "Color bar test pattern" | ||
1202 | * = 0 (0x00) ......0. "Off" | ||
1203 | * COMH[0] "Reserved" | ||
1204 | * = 0 (0x00) .......0 | ||
1205 | */ | ||
1206 | { 0x12, 0x40 }, | ||
1207 | |||
1208 | /* | ||
1209 | * 17 HREFST "Horizontal window start" | ||
1210 | * = 31 (0x1F) 00011111 | ||
1211 | * HREFST[7:0] "Horizontal window start, 8 MSBs" | ||
1212 | * = 31 (0x1F) 00011111 | ||
1213 | */ | ||
1214 | { 0x17, 0x1F }, | ||
1215 | |||
1216 | /* | ||
1217 | * 18 HREFEND "Horizontal window end" | ||
1218 | * = 95 (0x5F) 01011111 | ||
1219 | * HREFEND[7:0] "Horizontal Window End, 8 MSBs" | ||
1220 | * = 95 (0x5F) 01011111 | ||
1221 | */ | ||
1222 | { 0x18, 0x5F }, | ||
1223 | |||
1224 | /* | ||
1225 | * 19 VSTRT "Vertical window start" | ||
1226 | * = 0 (0x00) 00000000 | ||
1227 | * VSTRT[7:0] "Vertical Window Start, 8 MSBs" | ||
1228 | * = 0 (0x00) 00000000 | ||
1229 | */ | ||
1230 | { 0x19, 0x00 }, | ||
1231 | |||
1232 | /* | ||
1233 | * 1A VEND "Vertical window end" | ||
1234 | * = 96 (0x60) 01100000 | ||
1235 | * VEND[7:0] "Vertical Window End, 8 MSBs" | ||
1236 | * = 96 (0x60) 01100000 | ||
1237 | */ | ||
1238 | { 0x1a, 0x60 }, | ||
1239 | |||
1240 | /* | ||
1241 | * 32 COMM "Common Control M" | ||
1242 | * = 18 (0x12) 00010010 | ||
1243 | * COMM[7:6] "Pixel clock divide option" | ||
1244 | * = 0 (0x00) 00...... "/1" | ||
1245 | * COMM[5:3] "Horizontal window end position, 3 LSBs" | ||
1246 | * = 2 (0x02) ..010... | ||
1247 | * COMM[2:0] "Horizontal window start position, 3 LSBs" | ||
1248 | * = 2 (0x02) .....010 | ||
1249 | */ | ||
1250 | { 0x32, 0x12 }, | ||
1251 | |||
1252 | /* | ||
1253 | * 03 COMA "Common Control A" | ||
1254 | * = 74 (0x4A) 01001010 | ||
1255 | * COMA[7:4] "AWB Update Threshold" | ||
1256 | * = 4 (0x04) 0100.... | ||
1257 | * COMA[3:2] "Vertical window end line control 2 LSBs" | ||
1258 | * = 2 (0x02) ....10.. | ||
1259 | * COMA[1:0] "Vertical window start line control 2 LSBs" | ||
1260 | * = 2 (0x02) ......10 | ||
1261 | */ | ||
1262 | { 0x03, 0x4A }, | ||
1263 | |||
1264 | /* | ||
1265 | * 02 RED "Red Gain Control" | ||
1266 | * = 175 (0xAF) 10101111 | ||
1267 | * RED[7] "Action" | ||
1268 | * = 1 (0x01) 1....... "gain = 1/(1+bitrev([6:0]))" | ||
1269 | * RED[6:0] "Value" | ||
1270 | * = 47 (0x2F) .0101111 | ||
1271 | */ | ||
1272 | { 0x02, 0xAF }, | ||
1273 | |||
1274 | /* | ||
1275 | * 2D ADDVSL "VSYNC Pulse Width" | ||
1276 | * = 210 (0xD2) 11010010 | ||
1277 | * ADDVSL[7:0] "VSYNC pulse width, LSB" | ||
1278 | * = 210 (0xD2) 11010010 | ||
1279 | */ | ||
1280 | { 0x2d, 0xD2 }, | ||
1281 | |||
1282 | /* | ||
1283 | * 00 GAIN = 24 (0x18) 00011000 | ||
1284 | * GAIN[7:6] "Reserved" | ||
1285 | * = 0 (0x00) 00...... | ||
1286 | * GAIN[5] "Double" | ||
1287 | * = 0 (0x00) ..0..... "False" | ||
1288 | * GAIN[4] "Double" | ||
1289 | * = 1 (0x01) ...1.... "True" | ||
1290 | * GAIN[3:0] "Range" | ||
1291 | * = 8 (0x08) ....1000 | ||
1292 | */ | ||
1293 | { 0x00, 0x18 }, | ||
1294 | |||
1295 | /* | ||
1296 | * 01 BLUE "Blue Gain Control" | ||
1297 | * = 240 (0xF0) 11110000 | ||
1298 | * BLUE[7] "Action" | ||
1299 | * = 1 (0x01) 1....... "gain = 1/(1+bitrev([6:0]))" | ||
1300 | * BLUE[6:0] "Value" | ||
1301 | * = 112 (0x70) .1110000 | ||
1302 | */ | ||
1303 | { 0x01, 0xF0 }, | ||
1304 | |||
1305 | /* | ||
1306 | * 10 AEC "Automatic Exposure Control" | ||
1307 | * = 10 (0x0A) 00001010 | ||
1308 | * AEC[7:0] "Automatic Exposure Control, 8 MSBs" | ||
1309 | * = 10 (0x0A) 00001010 | ||
1310 | */ | ||
1311 | { 0x10, 0x0A }, | ||
1312 | |||
1313 | { 0xE1, 0x67 }, | ||
1314 | { 0xE3, 0x03 }, | ||
1315 | { 0xE4, 0x26 }, | ||
1316 | { 0xE5, 0x3E }, | ||
1317 | { 0xF8, 0x01 }, | ||
1318 | { 0xFF, 0x01 }, | ||
1319 | }; | ||
1320 | |||
511 | static const struct ov_i2c_regvals norm_6x20[] = { | 1321 | static const struct ov_i2c_regvals norm_6x20[] = { |
512 | { 0x12, 0x80 }, /* reset */ | 1322 | { 0x12, 0x80 }, /* reset */ |
513 | { 0x11, 0x01 }, | 1323 | { 0x11, 0x01 }, |
@@ -678,6 +1488,7 @@ static const struct ov_i2c_regvals norm_7610[] = { | |||
678 | }; | 1488 | }; |
679 | 1489 | ||
680 | static const struct ov_i2c_regvals norm_7620[] = { | 1490 | static const struct ov_i2c_regvals norm_7620[] = { |
1491 | { 0x12, 0x80 }, /* reset */ | ||
681 | { 0x00, 0x00 }, /* gain */ | 1492 | { 0x00, 0x00 }, /* gain */ |
682 | { 0x01, 0x80 }, /* blue gain */ | 1493 | { 0x01, 0x80 }, /* blue gain */ |
683 | { 0x02, 0x80 }, /* red gain */ | 1494 | { 0x02, 0x80 }, /* red gain */ |
@@ -1042,10 +1853,28 @@ static unsigned char ov7670_abs_to_sm(unsigned char v) | |||
1042 | } | 1853 | } |
1043 | 1854 | ||
1044 | /* Write a OV519 register */ | 1855 | /* Write a OV519 register */ |
1045 | static int reg_w(struct sd *sd, __u16 index, __u8 value) | 1856 | static int reg_w(struct sd *sd, __u16 index, __u16 value) |
1046 | { | 1857 | { |
1047 | int ret; | 1858 | int ret, req = 0; |
1048 | int req = (sd->bridge <= BRIDGE_OV511PLUS) ? 2 : 1; | 1859 | |
1860 | switch (sd->bridge) { | ||
1861 | case BRIDGE_OV511: | ||
1862 | case BRIDGE_OV511PLUS: | ||
1863 | req = 2; | ||
1864 | break; | ||
1865 | case BRIDGE_OVFX2: | ||
1866 | req = 0x0a; | ||
1867 | /* fall through */ | ||
1868 | case BRIDGE_W9968CF: | ||
1869 | ret = usb_control_msg(sd->gspca_dev.dev, | ||
1870 | usb_sndctrlpipe(sd->gspca_dev.dev, 0), | ||
1871 | req, | ||
1872 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
1873 | value, index, NULL, 0, 500); | ||
1874 | goto leave; | ||
1875 | default: | ||
1876 | req = 1; | ||
1877 | } | ||
1049 | 1878 | ||
1050 | sd->gspca_dev.usb_buf[0] = value; | 1879 | sd->gspca_dev.usb_buf[0] = value; |
1051 | ret = usb_control_msg(sd->gspca_dev.dev, | 1880 | ret = usb_control_msg(sd->gspca_dev.dev, |
@@ -1054,17 +1883,35 @@ static int reg_w(struct sd *sd, __u16 index, __u8 value) | |||
1054 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 1883 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
1055 | 0, index, | 1884 | 0, index, |
1056 | sd->gspca_dev.usb_buf, 1, 500); | 1885 | sd->gspca_dev.usb_buf, 1, 500); |
1057 | if (ret < 0) | 1886 | leave: |
1058 | PDEBUG(D_ERR, "Write reg [%02x] %02x failed", index, value); | 1887 | if (ret < 0) { |
1059 | return ret; | 1888 | PDEBUG(D_ERR, "Write reg 0x%04x -> [0x%02x] failed", |
1889 | value, index); | ||
1890 | return ret; | ||
1891 | } | ||
1892 | |||
1893 | PDEBUG(D_USBO, "Write reg 0x%04x -> [0x%02x]", value, index); | ||
1894 | return 0; | ||
1060 | } | 1895 | } |
1061 | 1896 | ||
1062 | /* Read from a OV519 register */ | 1897 | /* Read from a OV519 register, note not valid for the w9968cf!! */ |
1063 | /* returns: negative is error, pos or zero is data */ | 1898 | /* returns: negative is error, pos or zero is data */ |
1064 | static int reg_r(struct sd *sd, __u16 index) | 1899 | static int reg_r(struct sd *sd, __u16 index) |
1065 | { | 1900 | { |
1066 | int ret; | 1901 | int ret; |
1067 | int req = (sd->bridge <= BRIDGE_OV511PLUS) ? 3 : 1; | 1902 | int req; |
1903 | |||
1904 | switch (sd->bridge) { | ||
1905 | case BRIDGE_OV511: | ||
1906 | case BRIDGE_OV511PLUS: | ||
1907 | req = 3; | ||
1908 | break; | ||
1909 | case BRIDGE_OVFX2: | ||
1910 | req = 0x0b; | ||
1911 | break; | ||
1912 | default: | ||
1913 | req = 1; | ||
1914 | } | ||
1068 | 1915 | ||
1069 | ret = usb_control_msg(sd->gspca_dev.dev, | 1916 | ret = usb_control_msg(sd->gspca_dev.dev, |
1070 | usb_rcvctrlpipe(sd->gspca_dev.dev, 0), | 1917 | usb_rcvctrlpipe(sd->gspca_dev.dev, 0), |
@@ -1072,10 +1919,12 @@ static int reg_r(struct sd *sd, __u16 index) | |||
1072 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 1919 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
1073 | 0, index, sd->gspca_dev.usb_buf, 1, 500); | 1920 | 0, index, sd->gspca_dev.usb_buf, 1, 500); |
1074 | 1921 | ||
1075 | if (ret >= 0) | 1922 | if (ret >= 0) { |
1076 | ret = sd->gspca_dev.usb_buf[0]; | 1923 | ret = sd->gspca_dev.usb_buf[0]; |
1077 | else | 1924 | PDEBUG(D_USBI, "Read reg [0x%02X] -> 0x%04X", index, ret); |
1925 | } else | ||
1078 | PDEBUG(D_ERR, "Read reg [0x%02x] failed", index); | 1926 | PDEBUG(D_ERR, "Read reg [0x%02x] failed", index); |
1927 | |||
1079 | return ret; | 1928 | return ret; |
1080 | } | 1929 | } |
1081 | 1930 | ||
@@ -1095,6 +1944,7 @@ static int reg_r8(struct sd *sd, | |||
1095 | ret = sd->gspca_dev.usb_buf[0]; | 1944 | ret = sd->gspca_dev.usb_buf[0]; |
1096 | else | 1945 | else |
1097 | PDEBUG(D_ERR, "Read reg 8 [0x%02x] failed", index); | 1946 | PDEBUG(D_ERR, "Read reg 8 [0x%02x] failed", index); |
1947 | |||
1098 | return ret; | 1948 | return ret; |
1099 | } | 1949 | } |
1100 | 1950 | ||
@@ -1140,9 +1990,12 @@ static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n) | |||
1140 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 1990 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
1141 | 0, index, | 1991 | 0, index, |
1142 | sd->gspca_dev.usb_buf, n, 500); | 1992 | sd->gspca_dev.usb_buf, n, 500); |
1143 | if (ret < 0) | 1993 | if (ret < 0) { |
1144 | PDEBUG(D_ERR, "Write reg32 [%02x] %08x failed", index, value); | 1994 | PDEBUG(D_ERR, "Write reg32 [%02x] %08x failed", index, value); |
1145 | return ret; | 1995 | return ret; |
1996 | } | ||
1997 | |||
1998 | return 0; | ||
1146 | } | 1999 | } |
1147 | 2000 | ||
1148 | static int ov511_i2c_w(struct sd *sd, __u8 reg, __u8 value) | 2001 | static int ov511_i2c_w(struct sd *sd, __u8 reg, __u8 value) |
@@ -1324,32 +2177,110 @@ static int ov518_i2c_r(struct sd *sd, __u8 reg) | |||
1324 | return value; | 2177 | return value; |
1325 | } | 2178 | } |
1326 | 2179 | ||
2180 | static int ovfx2_i2c_w(struct sd *sd, __u8 reg, __u8 value) | ||
2181 | { | ||
2182 | int ret; | ||
2183 | |||
2184 | ret = usb_control_msg(sd->gspca_dev.dev, | ||
2185 | usb_sndctrlpipe(sd->gspca_dev.dev, 0), | ||
2186 | 0x02, | ||
2187 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
2188 | (__u16)value, (__u16)reg, NULL, 0, 500); | ||
2189 | |||
2190 | if (ret < 0) { | ||
2191 | PDEBUG(D_ERR, "i2c 0x%02x -> [0x%02x] failed", value, reg); | ||
2192 | return ret; | ||
2193 | } | ||
2194 | |||
2195 | PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); | ||
2196 | return 0; | ||
2197 | } | ||
2198 | |||
2199 | static int ovfx2_i2c_r(struct sd *sd, __u8 reg) | ||
2200 | { | ||
2201 | int ret; | ||
2202 | |||
2203 | ret = usb_control_msg(sd->gspca_dev.dev, | ||
2204 | usb_rcvctrlpipe(sd->gspca_dev.dev, 0), | ||
2205 | 0x03, | ||
2206 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
2207 | 0, (__u16)reg, sd->gspca_dev.usb_buf, 1, 500); | ||
2208 | |||
2209 | if (ret >= 0) { | ||
2210 | ret = sd->gspca_dev.usb_buf[0]; | ||
2211 | PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, ret); | ||
2212 | } else | ||
2213 | PDEBUG(D_ERR, "i2c read [0x%02x] failed", reg); | ||
2214 | |||
2215 | return ret; | ||
2216 | } | ||
2217 | |||
1327 | static int i2c_w(struct sd *sd, __u8 reg, __u8 value) | 2218 | static int i2c_w(struct sd *sd, __u8 reg, __u8 value) |
1328 | { | 2219 | { |
2220 | int ret = -1; | ||
2221 | |||
2222 | if (sd->sensor_reg_cache[reg] == value) | ||
2223 | return 0; | ||
2224 | |||
1329 | switch (sd->bridge) { | 2225 | switch (sd->bridge) { |
1330 | case BRIDGE_OV511: | 2226 | case BRIDGE_OV511: |
1331 | case BRIDGE_OV511PLUS: | 2227 | case BRIDGE_OV511PLUS: |
1332 | return ov511_i2c_w(sd, reg, value); | 2228 | ret = ov511_i2c_w(sd, reg, value); |
2229 | break; | ||
1333 | case BRIDGE_OV518: | 2230 | case BRIDGE_OV518: |
1334 | case BRIDGE_OV518PLUS: | 2231 | case BRIDGE_OV518PLUS: |
1335 | case BRIDGE_OV519: | 2232 | case BRIDGE_OV519: |
1336 | return ov518_i2c_w(sd, reg, value); | 2233 | ret = ov518_i2c_w(sd, reg, value); |
2234 | break; | ||
2235 | case BRIDGE_OVFX2: | ||
2236 | ret = ovfx2_i2c_w(sd, reg, value); | ||
2237 | break; | ||
2238 | case BRIDGE_W9968CF: | ||
2239 | ret = w9968cf_i2c_w(sd, reg, value); | ||
2240 | break; | ||
1337 | } | 2241 | } |
1338 | return -1; /* Should never happen */ | 2242 | |
2243 | if (ret >= 0) { | ||
2244 | /* Up on sensor reset empty the register cache */ | ||
2245 | if (reg == 0x12 && (value & 0x80)) | ||
2246 | memset(sd->sensor_reg_cache, -1, | ||
2247 | sizeof(sd->sensor_reg_cache)); | ||
2248 | else | ||
2249 | sd->sensor_reg_cache[reg] = value; | ||
2250 | } | ||
2251 | |||
2252 | return ret; | ||
1339 | } | 2253 | } |
1340 | 2254 | ||
1341 | static int i2c_r(struct sd *sd, __u8 reg) | 2255 | static int i2c_r(struct sd *sd, __u8 reg) |
1342 | { | 2256 | { |
2257 | int ret = -1; | ||
2258 | |||
2259 | if (sd->sensor_reg_cache[reg] != -1) | ||
2260 | return sd->sensor_reg_cache[reg]; | ||
2261 | |||
1343 | switch (sd->bridge) { | 2262 | switch (sd->bridge) { |
1344 | case BRIDGE_OV511: | 2263 | case BRIDGE_OV511: |
1345 | case BRIDGE_OV511PLUS: | 2264 | case BRIDGE_OV511PLUS: |
1346 | return ov511_i2c_r(sd, reg); | 2265 | ret = ov511_i2c_r(sd, reg); |
2266 | break; | ||
1347 | case BRIDGE_OV518: | 2267 | case BRIDGE_OV518: |
1348 | case BRIDGE_OV518PLUS: | 2268 | case BRIDGE_OV518PLUS: |
1349 | case BRIDGE_OV519: | 2269 | case BRIDGE_OV519: |
1350 | return ov518_i2c_r(sd, reg); | 2270 | ret = ov518_i2c_r(sd, reg); |
2271 | break; | ||
2272 | case BRIDGE_OVFX2: | ||
2273 | ret = ovfx2_i2c_r(sd, reg); | ||
2274 | break; | ||
2275 | case BRIDGE_W9968CF: | ||
2276 | ret = w9968cf_i2c_r(sd, reg); | ||
2277 | break; | ||
1351 | } | 2278 | } |
1352 | return -1; /* Should never happen */ | 2279 | |
2280 | if (ret >= 0) | ||
2281 | sd->sensor_reg_cache[reg] = ret; | ||
2282 | |||
2283 | return ret; | ||
1353 | } | 2284 | } |
1354 | 2285 | ||
1355 | /* Writes bits at positions specified by mask to an I2C reg. Bits that are in | 2286 | /* Writes bits at positions specified by mask to an I2C reg. Bits that are in |
@@ -1389,6 +2320,10 @@ static inline int ov51x_stop(struct sd *sd) | |||
1389 | return reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a); | 2320 | return reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a); |
1390 | case BRIDGE_OV519: | 2321 | case BRIDGE_OV519: |
1391 | return reg_w(sd, OV519_SYS_RESET1, 0x0f); | 2322 | return reg_w(sd, OV519_SYS_RESET1, 0x0f); |
2323 | case BRIDGE_OVFX2: | ||
2324 | return reg_w_mask(sd, 0x0f, 0x00, 0x02); | ||
2325 | case BRIDGE_W9968CF: | ||
2326 | return reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */ | ||
1392 | } | 2327 | } |
1393 | 2328 | ||
1394 | return 0; | 2329 | return 0; |
@@ -1418,18 +2353,27 @@ static inline int ov51x_restart(struct sd *sd) | |||
1418 | return reg_w(sd, R51x_SYS_RESET, 0x00); | 2353 | return reg_w(sd, R51x_SYS_RESET, 0x00); |
1419 | case BRIDGE_OV519: | 2354 | case BRIDGE_OV519: |
1420 | return reg_w(sd, OV519_SYS_RESET1, 0x00); | 2355 | return reg_w(sd, OV519_SYS_RESET1, 0x00); |
2356 | case BRIDGE_OVFX2: | ||
2357 | return reg_w_mask(sd, 0x0f, 0x02, 0x02); | ||
2358 | case BRIDGE_W9968CF: | ||
2359 | return reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */ | ||
1421 | } | 2360 | } |
1422 | 2361 | ||
1423 | return 0; | 2362 | return 0; |
1424 | } | 2363 | } |
1425 | 2364 | ||
2365 | static int ov51x_set_slave_ids(struct sd *sd, __u8 slave); | ||
2366 | |||
1426 | /* This does an initial reset of an OmniVision sensor and ensures that I2C | 2367 | /* This does an initial reset of an OmniVision sensor and ensures that I2C |
1427 | * is synchronized. Returns <0 on failure. | 2368 | * is synchronized. Returns <0 on failure. |
1428 | */ | 2369 | */ |
1429 | static int init_ov_sensor(struct sd *sd) | 2370 | static int init_ov_sensor(struct sd *sd, __u8 slave) |
1430 | { | 2371 | { |
1431 | int i; | 2372 | int i; |
1432 | 2373 | ||
2374 | if (ov51x_set_slave_ids(sd, slave) < 0) | ||
2375 | return -EIO; | ||
2376 | |||
1433 | /* Reset the sensor */ | 2377 | /* Reset the sensor */ |
1434 | if (i2c_w(sd, 0x12, 0x80) < 0) | 2378 | if (i2c_w(sd, 0x12, 0x80) < 0) |
1435 | return -EIO; | 2379 | return -EIO; |
@@ -1466,6 +2410,14 @@ static int ov51x_set_slave_ids(struct sd *sd, | |||
1466 | { | 2410 | { |
1467 | int rc; | 2411 | int rc; |
1468 | 2412 | ||
2413 | switch (sd->bridge) { | ||
2414 | case BRIDGE_OVFX2: | ||
2415 | return reg_w(sd, OVFX2_I2C_ADDR, slave); | ||
2416 | case BRIDGE_W9968CF: | ||
2417 | sd->sensor_addr = slave; | ||
2418 | return 0; | ||
2419 | } | ||
2420 | |||
1469 | rc = reg_w(sd, R51x_I2C_W_SID, slave); | 2421 | rc = reg_w(sd, R51x_I2C_W_SID, slave); |
1470 | if (rc < 0) | 2422 | if (rc < 0) |
1471 | return rc; | 2423 | return rc; |
@@ -1508,6 +2460,39 @@ static int write_i2c_regvals(struct sd *sd, | |||
1508 | * | 2460 | * |
1509 | ***************************************************************************/ | 2461 | ***************************************************************************/ |
1510 | 2462 | ||
2463 | /* This initializes the OV2x10 / OV3610 / OV3620 */ | ||
2464 | static int ov_hires_configure(struct sd *sd) | ||
2465 | { | ||
2466 | int high, low; | ||
2467 | |||
2468 | if (sd->bridge != BRIDGE_OVFX2) { | ||
2469 | PDEBUG(D_ERR, "error hires sensors only supported with ovfx2"); | ||
2470 | return -1; | ||
2471 | } | ||
2472 | |||
2473 | PDEBUG(D_PROBE, "starting ov hires configuration"); | ||
2474 | |||
2475 | /* Detect sensor (sub)type */ | ||
2476 | high = i2c_r(sd, 0x0a); | ||
2477 | low = i2c_r(sd, 0x0b); | ||
2478 | /* info("%x, %x", high, low); */ | ||
2479 | if (high == 0x96 && low == 0x40) { | ||
2480 | PDEBUG(D_PROBE, "Sensor is an OV2610"); | ||
2481 | sd->sensor = SEN_OV2610; | ||
2482 | } else if (high == 0x36 && (low & 0x0f) == 0x00) { | ||
2483 | PDEBUG(D_PROBE, "Sensor is an OV3610"); | ||
2484 | sd->sensor = SEN_OV3610; | ||
2485 | } else { | ||
2486 | PDEBUG(D_ERR, "Error unknown sensor type: 0x%02x%02x", | ||
2487 | high, low); | ||
2488 | return -1; | ||
2489 | } | ||
2490 | |||
2491 | /* Set sensor-specific vars */ | ||
2492 | return 0; | ||
2493 | } | ||
2494 | |||
2495 | |||
1511 | /* This initializes the OV8110, OV8610 sensor. The OV8110 uses | 2496 | /* This initializes the OV8110, OV8610 sensor. The OV8110 uses |
1512 | * the same register settings as the OV8610, since they are very similar. | 2497 | * the same register settings as the OV8610, since they are very similar. |
1513 | */ | 2498 | */ |
@@ -1966,12 +2951,29 @@ static int ov519_configure(struct sd *sd) | |||
1966 | return write_regvals(sd, init_519, ARRAY_SIZE(init_519)); | 2951 | return write_regvals(sd, init_519, ARRAY_SIZE(init_519)); |
1967 | } | 2952 | } |
1968 | 2953 | ||
2954 | static int ovfx2_configure(struct sd *sd) | ||
2955 | { | ||
2956 | static const struct ov_regvals init_fx2[] = { | ||
2957 | { 0x00, 0x60 }, | ||
2958 | { 0x02, 0x01 }, | ||
2959 | { 0x0f, 0x1d }, | ||
2960 | { 0xe9, 0x82 }, | ||
2961 | { 0xea, 0xc7 }, | ||
2962 | { 0xeb, 0x10 }, | ||
2963 | { 0xec, 0xf6 }, | ||
2964 | }; | ||
2965 | |||
2966 | sd->stopped = 1; | ||
2967 | |||
2968 | return write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2)); | ||
2969 | } | ||
2970 | |||
1969 | /* this function is called at probe time */ | 2971 | /* this function is called at probe time */ |
1970 | static int sd_config(struct gspca_dev *gspca_dev, | 2972 | static int sd_config(struct gspca_dev *gspca_dev, |
1971 | const struct usb_device_id *id) | 2973 | const struct usb_device_id *id) |
1972 | { | 2974 | { |
1973 | struct sd *sd = (struct sd *) gspca_dev; | 2975 | struct sd *sd = (struct sd *) gspca_dev; |
1974 | struct cam *cam; | 2976 | struct cam *cam = &gspca_dev->cam; |
1975 | int ret = 0; | 2977 | int ret = 0; |
1976 | 2978 | ||
1977 | sd->bridge = id->driver_info & BRIDGE_MASK; | 2979 | sd->bridge = id->driver_info & BRIDGE_MASK; |
@@ -1989,6 +2991,16 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1989 | case BRIDGE_OV519: | 2991 | case BRIDGE_OV519: |
1990 | ret = ov519_configure(sd); | 2992 | ret = ov519_configure(sd); |
1991 | break; | 2993 | break; |
2994 | case BRIDGE_OVFX2: | ||
2995 | ret = ovfx2_configure(sd); | ||
2996 | cam->bulk_size = OVFX2_BULK_SIZE; | ||
2997 | cam->bulk_nurbs = MAX_NURBS; | ||
2998 | cam->bulk = 1; | ||
2999 | break; | ||
3000 | case BRIDGE_W9968CF: | ||
3001 | ret = w9968cf_configure(sd); | ||
3002 | cam->reverse_alts = 1; | ||
3003 | break; | ||
1992 | } | 3004 | } |
1993 | 3005 | ||
1994 | if (ret) | 3006 | if (ret) |
@@ -1996,49 +3008,39 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1996 | 3008 | ||
1997 | ov51x_led_control(sd, 0); /* turn LED off */ | 3009 | ov51x_led_control(sd, 0); /* turn LED off */ |
1998 | 3010 | ||
1999 | /* Test for 76xx */ | ||
2000 | if (ov51x_set_slave_ids(sd, OV7xx0_SID) < 0) | ||
2001 | goto error; | ||
2002 | |||
2003 | /* The OV519 must be more aggressive about sensor detection since | 3011 | /* The OV519 must be more aggressive about sensor detection since |
2004 | * I2C write will never fail if the sensor is not present. We have | 3012 | * I2C write will never fail if the sensor is not present. We have |
2005 | * to try to initialize the sensor to detect its presence */ | 3013 | * to try to initialize the sensor to detect its presence */ |
2006 | if (init_ov_sensor(sd) >= 0) { | 3014 | |
3015 | /* Test for 76xx */ | ||
3016 | if (init_ov_sensor(sd, OV7xx0_SID) >= 0) { | ||
2007 | if (ov7xx0_configure(sd) < 0) { | 3017 | if (ov7xx0_configure(sd) < 0) { |
2008 | PDEBUG(D_ERR, "Failed to configure OV7xx0"); | 3018 | PDEBUG(D_ERR, "Failed to configure OV7xx0"); |
2009 | goto error; | 3019 | goto error; |
2010 | } | 3020 | } |
2011 | } else { | 3021 | /* Test for 6xx0 */ |
2012 | 3022 | } else if (init_ov_sensor(sd, OV6xx0_SID) >= 0) { | |
2013 | /* Test for 6xx0 */ | 3023 | if (ov6xx0_configure(sd) < 0) { |
2014 | if (ov51x_set_slave_ids(sd, OV6xx0_SID) < 0) | 3024 | PDEBUG(D_ERR, "Failed to configure OV6xx0"); |
3025 | goto error; | ||
3026 | } | ||
3027 | /* Test for 8xx0 */ | ||
3028 | } else if (init_ov_sensor(sd, OV8xx0_SID) >= 0) { | ||
3029 | if (ov8xx0_configure(sd) < 0) { | ||
3030 | PDEBUG(D_ERR, "Failed to configure OV8xx0"); | ||
2015 | goto error; | 3031 | goto error; |
2016 | |||
2017 | if (init_ov_sensor(sd) >= 0) { | ||
2018 | if (ov6xx0_configure(sd) < 0) { | ||
2019 | PDEBUG(D_ERR, "Failed to configure OV6xx0"); | ||
2020 | goto error; | ||
2021 | } | ||
2022 | } else { | ||
2023 | |||
2024 | /* Test for 8xx0 */ | ||
2025 | if (ov51x_set_slave_ids(sd, OV8xx0_SID) < 0) | ||
2026 | goto error; | ||
2027 | |||
2028 | if (init_ov_sensor(sd) < 0) { | ||
2029 | PDEBUG(D_ERR, | ||
2030 | "Can't determine sensor slave IDs"); | ||
2031 | goto error; | ||
2032 | } | ||
2033 | if (ov8xx0_configure(sd) < 0) { | ||
2034 | PDEBUG(D_ERR, | ||
2035 | "Failed to configure OV8xx0 sensor"); | ||
2036 | goto error; | ||
2037 | } | ||
2038 | } | 3032 | } |
3033 | /* Test for 3xxx / 2xxx */ | ||
3034 | } else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) { | ||
3035 | if (ov_hires_configure(sd) < 0) { | ||
3036 | PDEBUG(D_ERR, "Failed to configure high res OV"); | ||
3037 | goto error; | ||
3038 | } | ||
3039 | } else { | ||
3040 | PDEBUG(D_ERR, "Can't determine sensor slave IDs"); | ||
3041 | goto error; | ||
2039 | } | 3042 | } |
2040 | 3043 | ||
2041 | cam = &gspca_dev->cam; | ||
2042 | switch (sd->bridge) { | 3044 | switch (sd->bridge) { |
2043 | case BRIDGE_OV511: | 3045 | case BRIDGE_OV511: |
2044 | case BRIDGE_OV511PLUS: | 3046 | case BRIDGE_OV511PLUS: |
@@ -2069,6 +3071,31 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
2069 | cam->nmodes = ARRAY_SIZE(ov519_sif_mode); | 3071 | cam->nmodes = ARRAY_SIZE(ov519_sif_mode); |
2070 | } | 3072 | } |
2071 | break; | 3073 | break; |
3074 | case BRIDGE_OVFX2: | ||
3075 | if (sd->sensor == SEN_OV2610) { | ||
3076 | cam->cam_mode = ovfx2_ov2610_mode; | ||
3077 | cam->nmodes = ARRAY_SIZE(ovfx2_ov2610_mode); | ||
3078 | } else if (sd->sensor == SEN_OV3610) { | ||
3079 | cam->cam_mode = ovfx2_ov3610_mode; | ||
3080 | cam->nmodes = ARRAY_SIZE(ovfx2_ov3610_mode); | ||
3081 | } else if (!sd->sif) { | ||
3082 | cam->cam_mode = ov519_vga_mode; | ||
3083 | cam->nmodes = ARRAY_SIZE(ov519_vga_mode); | ||
3084 | } else { | ||
3085 | cam->cam_mode = ov519_sif_mode; | ||
3086 | cam->nmodes = ARRAY_SIZE(ov519_sif_mode); | ||
3087 | } | ||
3088 | break; | ||
3089 | case BRIDGE_W9968CF: | ||
3090 | cam->cam_mode = w9968cf_vga_mode; | ||
3091 | cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode); | ||
3092 | if (sd->sif) | ||
3093 | cam->nmodes--; | ||
3094 | |||
3095 | /* w9968cf needs initialisation once the sensor is known */ | ||
3096 | if (w9968cf_init(sd) < 0) | ||
3097 | goto error; | ||
3098 | break; | ||
2072 | } | 3099 | } |
2073 | sd->brightness = BRIGHTNESS_DEF; | 3100 | sd->brightness = BRIGHTNESS_DEF; |
2074 | if (sd->sensor == SEN_OV6630 || sd->sensor == SEN_OV66308AF) | 3101 | if (sd->sensor == SEN_OV6630 || sd->sensor == SEN_OV66308AF) |
@@ -2087,11 +3114,15 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
2087 | gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | | 3114 | gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | |
2088 | (1 << OV7670_FREQ_IDX); | 3115 | (1 << OV7670_FREQ_IDX); |
2089 | } | 3116 | } |
3117 | sd->quality = QUALITY_DEF; | ||
2090 | if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670) | 3118 | if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670) |
2091 | gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT_IDX; | 3119 | gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT_IDX; |
2092 | /* OV8610 Frequency filter control should work but needs testing */ | 3120 | /* OV8610 Frequency filter control should work but needs testing */ |
2093 | if (sd->sensor == SEN_OV8610) | 3121 | if (sd->sensor == SEN_OV8610) |
2094 | gspca_dev->ctrl_dis |= 1 << FREQ_IDX; | 3122 | gspca_dev->ctrl_dis |= 1 << FREQ_IDX; |
3123 | /* No controls for the OV2610/OV3610 */ | ||
3124 | if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) | ||
3125 | gspca_dev->ctrl_dis |= 0xFF; | ||
2095 | 3126 | ||
2096 | return 0; | 3127 | return 0; |
2097 | error: | 3128 | error: |
@@ -2106,6 +3137,20 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
2106 | 3137 | ||
2107 | /* initialize the sensor */ | 3138 | /* initialize the sensor */ |
2108 | switch (sd->sensor) { | 3139 | switch (sd->sensor) { |
3140 | case SEN_OV2610: | ||
3141 | if (write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610))) | ||
3142 | return -EIO; | ||
3143 | /* Enable autogain, autoexpo, awb, bandfilter */ | ||
3144 | if (i2c_w_mask(sd, 0x13, 0x27, 0x27) < 0) | ||
3145 | return -EIO; | ||
3146 | break; | ||
3147 | case SEN_OV3610: | ||
3148 | if (write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b))) | ||
3149 | return -EIO; | ||
3150 | /* Enable autogain, autoexpo, awb, bandfilter */ | ||
3151 | if (i2c_w_mask(sd, 0x13, 0x27, 0x27) < 0) | ||
3152 | return -EIO; | ||
3153 | break; | ||
2109 | case SEN_OV6620: | 3154 | case SEN_OV6620: |
2110 | if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20))) | 3155 | if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20))) |
2111 | return -EIO; | 3156 | return -EIO; |
@@ -2548,19 +3593,60 @@ static int ov519_mode_init_regs(struct sd *sd) | |||
2548 | static int mode_init_ov_sensor_regs(struct sd *sd) | 3593 | static int mode_init_ov_sensor_regs(struct sd *sd) |
2549 | { | 3594 | { |
2550 | struct gspca_dev *gspca_dev; | 3595 | struct gspca_dev *gspca_dev; |
2551 | int qvga; | 3596 | int qvga, xstart, xend, ystart, yend; |
3597 | __u8 v; | ||
2552 | 3598 | ||
2553 | gspca_dev = &sd->gspca_dev; | 3599 | gspca_dev = &sd->gspca_dev; |
2554 | qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1; | 3600 | qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1; |
2555 | 3601 | ||
2556 | /******** Mode (VGA/QVGA) and sensor specific regs ********/ | 3602 | /******** Mode (VGA/QVGA) and sensor specific regs ********/ |
2557 | switch (sd->sensor) { | 3603 | switch (sd->sensor) { |
3604 | case SEN_OV2610: | ||
3605 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); | ||
3606 | i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); | ||
3607 | i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); | ||
3608 | i2c_w(sd, 0x25, qvga ? 0x30 : 0x60); | ||
3609 | i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); | ||
3610 | i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); | ||
3611 | i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); | ||
3612 | return 0; | ||
3613 | case SEN_OV3610: | ||
3614 | if (qvga) { | ||
3615 | xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4); | ||
3616 | ystart = (776 - gspca_dev->height) / 2; | ||
3617 | } else { | ||
3618 | xstart = (2076 - gspca_dev->width) / 2 + (0x10 << 4); | ||
3619 | ystart = (1544 - gspca_dev->height) / 2; | ||
3620 | } | ||
3621 | xend = xstart + gspca_dev->width; | ||
3622 | yend = ystart + gspca_dev->height; | ||
3623 | /* Writing to the COMH register resets the other windowing regs | ||
3624 | to their default values, so we must do this first. */ | ||
3625 | i2c_w_mask(sd, 0x12, qvga ? 0x40 : 0x00, 0xf0); | ||
3626 | i2c_w_mask(sd, 0x32, | ||
3627 | (((xend >> 1) & 7) << 3) | ((xstart >> 1) & 7), | ||
3628 | 0x3f); | ||
3629 | i2c_w_mask(sd, 0x03, | ||
3630 | (((yend >> 1) & 3) << 2) | ((ystart >> 1) & 3), | ||
3631 | 0x0f); | ||
3632 | i2c_w(sd, 0x17, xstart >> 4); | ||
3633 | i2c_w(sd, 0x18, xend >> 4); | ||
3634 | i2c_w(sd, 0x19, ystart >> 3); | ||
3635 | i2c_w(sd, 0x1a, yend >> 3); | ||
3636 | return 0; | ||
2558 | case SEN_OV8610: | 3637 | case SEN_OV8610: |
2559 | /* For OV8610 qvga means qsvga */ | 3638 | /* For OV8610 qvga means qsvga */ |
2560 | i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5); | 3639 | i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5); |
3640 | i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ | ||
3641 | i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ | ||
3642 | i2c_w_mask(sd, 0x2d, 0x00, 0x40); /* from windrv 090403 */ | ||
3643 | i2c_w_mask(sd, 0x28, 0x20, 0x20); /* progressive mode on */ | ||
2561 | break; | 3644 | break; |
2562 | case SEN_OV7610: | 3645 | case SEN_OV7610: |
2563 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); | 3646 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); |
3647 | i2c_w(sd, 0x35, qvga?0x1e:0x9e); | ||
3648 | i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ | ||
3649 | i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ | ||
2564 | break; | 3650 | break; |
2565 | case SEN_OV7620: | 3651 | case SEN_OV7620: |
2566 | case SEN_OV76BE: | 3652 | case SEN_OV76BE: |
@@ -2571,6 +3657,10 @@ static int mode_init_ov_sensor_regs(struct sd *sd) | |||
2571 | i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); | 3657 | i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); |
2572 | i2c_w_mask(sd, 0x67, qvga ? 0xb0 : 0x90, 0xf0); | 3658 | i2c_w_mask(sd, 0x67, qvga ? 0xb0 : 0x90, 0xf0); |
2573 | i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); | 3659 | i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); |
3660 | i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ | ||
3661 | i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ | ||
3662 | if (sd->sensor == SEN_OV76BE) | ||
3663 | i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e); | ||
2574 | break; | 3664 | break; |
2575 | case SEN_OV7640: | 3665 | case SEN_OV7640: |
2576 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); | 3666 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); |
@@ -2580,6 +3670,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) | |||
2580 | /* i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); */ | 3670 | /* i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); */ |
2581 | /* i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); */ | 3671 | /* i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); */ |
2582 | /* i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); */ | 3672 | /* i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); */ |
3673 | i2c_w_mask(sd, 0x12, 0x04, 0x04); /* AWB: 1 */ | ||
2583 | break; | 3674 | break; |
2584 | case SEN_OV7670: | 3675 | case SEN_OV7670: |
2585 | /* set COM7_FMT_VGA or COM7_FMT_QVGA | 3676 | /* set COM7_FMT_VGA or COM7_FMT_QVGA |
@@ -2588,55 +3679,56 @@ static int mode_init_ov_sensor_regs(struct sd *sd) | |||
2588 | i2c_w_mask(sd, OV7670_REG_COM7, | 3679 | i2c_w_mask(sd, OV7670_REG_COM7, |
2589 | qvga ? OV7670_COM7_FMT_QVGA : OV7670_COM7_FMT_VGA, | 3680 | qvga ? OV7670_COM7_FMT_QVGA : OV7670_COM7_FMT_VGA, |
2590 | OV7670_COM7_FMT_MASK); | 3681 | OV7670_COM7_FMT_MASK); |
3682 | i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ | ||
3683 | i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_AWB, | ||
3684 | OV7670_COM8_AWB); | ||
3685 | if (qvga) { /* QVGA from ov7670.c by | ||
3686 | * Jonathan Corbet */ | ||
3687 | xstart = 164; | ||
3688 | xend = 28; | ||
3689 | ystart = 14; | ||
3690 | yend = 494; | ||
3691 | } else { /* VGA */ | ||
3692 | xstart = 158; | ||
3693 | xend = 14; | ||
3694 | ystart = 10; | ||
3695 | yend = 490; | ||
3696 | } | ||
3697 | /* OV7670 hardware window registers are split across | ||
3698 | * multiple locations */ | ||
3699 | i2c_w(sd, OV7670_REG_HSTART, xstart >> 3); | ||
3700 | i2c_w(sd, OV7670_REG_HSTOP, xend >> 3); | ||
3701 | v = i2c_r(sd, OV7670_REG_HREF); | ||
3702 | v = (v & 0xc0) | ((xend & 0x7) << 3) | (xstart & 0x07); | ||
3703 | msleep(10); /* need to sleep between read and write to | ||
3704 | * same reg! */ | ||
3705 | i2c_w(sd, OV7670_REG_HREF, v); | ||
3706 | |||
3707 | i2c_w(sd, OV7670_REG_VSTART, ystart >> 2); | ||
3708 | i2c_w(sd, OV7670_REG_VSTOP, yend >> 2); | ||
3709 | v = i2c_r(sd, OV7670_REG_VREF); | ||
3710 | v = (v & 0xc0) | ((yend & 0x3) << 2) | (ystart & 0x03); | ||
3711 | msleep(10); /* need to sleep between read and write to | ||
3712 | * same reg! */ | ||
3713 | i2c_w(sd, OV7670_REG_VREF, v); | ||
2591 | break; | 3714 | break; |
2592 | case SEN_OV6620: | 3715 | case SEN_OV6620: |
3716 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); | ||
3717 | i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ | ||
3718 | i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ | ||
3719 | break; | ||
2593 | case SEN_OV6630: | 3720 | case SEN_OV6630: |
2594 | case SEN_OV66308AF: | 3721 | case SEN_OV66308AF: |
2595 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); | 3722 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); |
3723 | i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ | ||
2596 | break; | 3724 | break; |
2597 | default: | 3725 | default: |
2598 | return -EINVAL; | 3726 | return -EINVAL; |
2599 | } | 3727 | } |
2600 | 3728 | ||
2601 | /******** Palette-specific regs ********/ | ||
2602 | |||
2603 | /* The OV518 needs special treatment. Although both the OV518 | ||
2604 | * and the OV6630 support a 16-bit video bus, only the 8 bit Y | ||
2605 | * bus is actually used. The UV bus is tied to ground. | ||
2606 | * Therefore, the OV6630 needs to be in 8-bit multiplexed | ||
2607 | * output mode */ | ||
2608 | |||
2609 | /* OV7640 is 8-bit only */ | ||
2610 | |||
2611 | if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV66308AF && | ||
2612 | sd->sensor != SEN_OV7640) | ||
2613 | i2c_w_mask(sd, 0x13, 0x00, 0x20); | ||
2614 | |||
2615 | /******** Clock programming ********/ | 3729 | /******** Clock programming ********/ |
2616 | i2c_w(sd, 0x11, sd->clockdiv); | 3730 | i2c_w(sd, 0x11, sd->clockdiv); |
2617 | 3731 | ||
2618 | /******** Special Features ********/ | ||
2619 | /* no evidence this is possible with OV7670, either */ | ||
2620 | /* Test Pattern */ | ||
2621 | if (sd->sensor != SEN_OV7640 && sd->sensor != SEN_OV7670) | ||
2622 | i2c_w_mask(sd, 0x12, 0x00, 0x02); | ||
2623 | |||
2624 | /* Enable auto white balance */ | ||
2625 | if (sd->sensor == SEN_OV7670) | ||
2626 | i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_AWB, | ||
2627 | OV7670_COM8_AWB); | ||
2628 | else | ||
2629 | i2c_w_mask(sd, 0x12, 0x04, 0x04); | ||
2630 | |||
2631 | /* This will go away as soon as ov51x_mode_init_sensor_regs() */ | ||
2632 | /* is fully tested. */ | ||
2633 | /* 7620/6620/6630? don't have register 0x35, so play it safe */ | ||
2634 | if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) { | ||
2635 | if (!qvga) | ||
2636 | i2c_w(sd, 0x35, 0x9e); | ||
2637 | else | ||
2638 | i2c_w(sd, 0x35, 0x1e); | ||
2639 | } | ||
2640 | return 0; | 3732 | return 0; |
2641 | } | 3733 | } |
2642 | 3734 | ||
@@ -2659,8 +3751,12 @@ static int set_ov_sensor_window(struct sd *sd) | |||
2659 | struct gspca_dev *gspca_dev; | 3751 | struct gspca_dev *gspca_dev; |
2660 | int qvga, crop; | 3752 | int qvga, crop; |
2661 | int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; | 3753 | int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; |
2662 | int ret, hstart, hstop, vstop, vstart; | 3754 | int ret; |
2663 | __u8 v; | 3755 | |
3756 | /* mode setup is fully handled in mode_init_ov_sensor_regs for these */ | ||
3757 | if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610 || | ||
3758 | sd->sensor == SEN_OV7670) | ||
3759 | return mode_init_ov_sensor_regs(sd); | ||
2664 | 3760 | ||
2665 | gspca_dev = &sd->gspca_dev; | 3761 | gspca_dev = &sd->gspca_dev; |
2666 | qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1; | 3762 | qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1; |
@@ -2708,11 +3804,6 @@ static int set_ov_sensor_window(struct sd *sd) | |||
2708 | hwebase = 0x1a; | 3804 | hwebase = 0x1a; |
2709 | vwsbase = vwebase = 0x03; | 3805 | vwsbase = vwebase = 0x03; |
2710 | break; | 3806 | break; |
2711 | case SEN_OV7670: | ||
2712 | /*handling of OV7670 hardware sensor start and stop values | ||
2713 | * is very odd, compared to the other OV sensors */ | ||
2714 | vwsbase = vwebase = hwebase = hwsbase = 0x00; | ||
2715 | break; | ||
2716 | default: | 3807 | default: |
2717 | return -EINVAL; | 3808 | return -EINVAL; |
2718 | } | 3809 | } |
@@ -2753,58 +3844,11 @@ static int set_ov_sensor_window(struct sd *sd) | |||
2753 | if (ret < 0) | 3844 | if (ret < 0) |
2754 | return ret; | 3845 | return ret; |
2755 | 3846 | ||
2756 | if (sd->sensor == SEN_OV8610) { | 3847 | i2c_w(sd, 0x17, hwsbase); |
2757 | i2c_w_mask(sd, 0x2d, 0x05, 0x40); | 3848 | i2c_w(sd, 0x18, hwebase + (sd->sensor_width >> hwscale)); |
2758 | /* old 0x95, new 0x05 from windrv 090403 */ | 3849 | i2c_w(sd, 0x19, vwsbase); |
2759 | /* bits 5-7: reserved */ | 3850 | i2c_w(sd, 0x1a, vwebase + (sd->sensor_height >> vwscale)); |
2760 | i2c_w_mask(sd, 0x28, 0x20, 0x20); | ||
2761 | /* bit 5: progressive mode on */ | ||
2762 | } | ||
2763 | |||
2764 | /* The below is wrong for OV7670s because their window registers | ||
2765 | * only store the high bits in 0x17 to 0x1a */ | ||
2766 | |||
2767 | /* SRH Use sd->max values instead of requested win values */ | ||
2768 | /* SCS Since we're sticking with only the max hardware widths | ||
2769 | * for a given mode */ | ||
2770 | /* I can hard code this for OV7670s */ | ||
2771 | /* Yes, these numbers do look odd, but they're tested and work! */ | ||
2772 | if (sd->sensor == SEN_OV7670) { | ||
2773 | if (qvga) { /* QVGA from ov7670.c by | ||
2774 | * Jonathan Corbet */ | ||
2775 | hstart = 164; | ||
2776 | hstop = 28; | ||
2777 | vstart = 14; | ||
2778 | vstop = 494; | ||
2779 | } else { /* VGA */ | ||
2780 | hstart = 158; | ||
2781 | hstop = 14; | ||
2782 | vstart = 10; | ||
2783 | vstop = 490; | ||
2784 | } | ||
2785 | /* OV7670 hardware window registers are split across | ||
2786 | * multiple locations */ | ||
2787 | i2c_w(sd, OV7670_REG_HSTART, hstart >> 3); | ||
2788 | i2c_w(sd, OV7670_REG_HSTOP, hstop >> 3); | ||
2789 | v = i2c_r(sd, OV7670_REG_HREF); | ||
2790 | v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x07); | ||
2791 | msleep(10); /* need to sleep between read and write to | ||
2792 | * same reg! */ | ||
2793 | i2c_w(sd, OV7670_REG_HREF, v); | ||
2794 | 3851 | ||
2795 | i2c_w(sd, OV7670_REG_VSTART, vstart >> 2); | ||
2796 | i2c_w(sd, OV7670_REG_VSTOP, vstop >> 2); | ||
2797 | v = i2c_r(sd, OV7670_REG_VREF); | ||
2798 | v = (v & 0xc0) | ((vstop & 0x3) << 2) | (vstart & 0x03); | ||
2799 | msleep(10); /* need to sleep between read and write to | ||
2800 | * same reg! */ | ||
2801 | i2c_w(sd, OV7670_REG_VREF, v); | ||
2802 | } else { | ||
2803 | i2c_w(sd, 0x17, hwsbase); | ||
2804 | i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale)); | ||
2805 | i2c_w(sd, 0x19, vwsbase); | ||
2806 | i2c_w(sd, 0x1a, vwebase + (sd->gspca_dev.height >> vwscale)); | ||
2807 | } | ||
2808 | return 0; | 3852 | return 0; |
2809 | } | 3853 | } |
2810 | 3854 | ||
@@ -2814,6 +3858,10 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2814 | struct sd *sd = (struct sd *) gspca_dev; | 3858 | struct sd *sd = (struct sd *) gspca_dev; |
2815 | int ret = 0; | 3859 | int ret = 0; |
2816 | 3860 | ||
3861 | /* Default for most bridges, allow bridge_mode_init_regs to override */ | ||
3862 | sd->sensor_width = sd->gspca_dev.width; | ||
3863 | sd->sensor_height = sd->gspca_dev.height; | ||
3864 | |||
2817 | switch (sd->bridge) { | 3865 | switch (sd->bridge) { |
2818 | case BRIDGE_OV511: | 3866 | case BRIDGE_OV511: |
2819 | case BRIDGE_OV511PLUS: | 3867 | case BRIDGE_OV511PLUS: |
@@ -2826,6 +3874,10 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2826 | case BRIDGE_OV519: | 3874 | case BRIDGE_OV519: |
2827 | ret = ov519_mode_init_regs(sd); | 3875 | ret = ov519_mode_init_regs(sd); |
2828 | break; | 3876 | break; |
3877 | /* case BRIDGE_OVFX2: nothing to do */ | ||
3878 | case BRIDGE_W9968CF: | ||
3879 | ret = w9968cf_mode_init_regs(sd); | ||
3880 | break; | ||
2829 | } | 3881 | } |
2830 | if (ret < 0) | 3882 | if (ret < 0) |
2831 | goto out; | 3883 | goto out; |
@@ -2859,10 +3911,17 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
2859 | ov51x_led_control(sd, 0); | 3911 | ov51x_led_control(sd, 0); |
2860 | } | 3912 | } |
2861 | 3913 | ||
3914 | static void sd_stop0(struct gspca_dev *gspca_dev) | ||
3915 | { | ||
3916 | struct sd *sd = (struct sd *) gspca_dev; | ||
3917 | |||
3918 | if (sd->bridge == BRIDGE_W9968CF) | ||
3919 | w9968cf_stop0(sd); | ||
3920 | } | ||
3921 | |||
2862 | static void ov511_pkt_scan(struct gspca_dev *gspca_dev, | 3922 | static void ov511_pkt_scan(struct gspca_dev *gspca_dev, |
2863 | struct gspca_frame *frame, /* target */ | 3923 | u8 *in, /* isoc packet */ |
2864 | __u8 *in, /* isoc packet */ | 3924 | int len) /* iso packet length */ |
2865 | int len) /* iso packet length */ | ||
2866 | { | 3925 | { |
2867 | struct sd *sd = (struct sd *) gspca_dev; | 3926 | struct sd *sd = (struct sd *) gspca_dev; |
2868 | 3927 | ||
@@ -2893,11 +3952,11 @@ static void ov511_pkt_scan(struct gspca_dev *gspca_dev, | |||
2893 | return; | 3952 | return; |
2894 | } | 3953 | } |
2895 | /* Add 11 byte footer to frame, might be usefull */ | 3954 | /* Add 11 byte footer to frame, might be usefull */ |
2896 | gspca_frame_add(gspca_dev, LAST_PACKET, frame, in, 11); | 3955 | gspca_frame_add(gspca_dev, LAST_PACKET, in, 11); |
2897 | return; | 3956 | return; |
2898 | } else { | 3957 | } else { |
2899 | /* Frame start */ | 3958 | /* Frame start */ |
2900 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, in, 0); | 3959 | gspca_frame_add(gspca_dev, FIRST_PACKET, in, 0); |
2901 | sd->packet_nr = 0; | 3960 | sd->packet_nr = 0; |
2902 | } | 3961 | } |
2903 | } | 3962 | } |
@@ -2906,12 +3965,11 @@ static void ov511_pkt_scan(struct gspca_dev *gspca_dev, | |||
2906 | len--; | 3965 | len--; |
2907 | 3966 | ||
2908 | /* intermediate packet */ | 3967 | /* intermediate packet */ |
2909 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, in, len); | 3968 | gspca_frame_add(gspca_dev, INTER_PACKET, in, len); |
2910 | } | 3969 | } |
2911 | 3970 | ||
2912 | static void ov518_pkt_scan(struct gspca_dev *gspca_dev, | 3971 | static void ov518_pkt_scan(struct gspca_dev *gspca_dev, |
2913 | struct gspca_frame *frame, /* target */ | 3972 | u8 *data, /* isoc packet */ |
2914 | __u8 *data, /* isoc packet */ | ||
2915 | int len) /* iso packet length */ | 3973 | int len) /* iso packet length */ |
2916 | { | 3974 | { |
2917 | struct sd *sd = (struct sd *) gspca_dev; | 3975 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -2919,8 +3977,8 @@ static void ov518_pkt_scan(struct gspca_dev *gspca_dev, | |||
2919 | /* A false positive here is likely, until OVT gives me | 3977 | /* A false positive here is likely, until OVT gives me |
2920 | * the definitive SOF/EOF format */ | 3978 | * the definitive SOF/EOF format */ |
2921 | if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) { | 3979 | if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) { |
2922 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); | 3980 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); |
2923 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, 0); | 3981 | gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); |
2924 | sd->packet_nr = 0; | 3982 | sd->packet_nr = 0; |
2925 | } | 3983 | } |
2926 | 3984 | ||
@@ -2944,12 +4002,11 @@ static void ov518_pkt_scan(struct gspca_dev *gspca_dev, | |||
2944 | } | 4002 | } |
2945 | 4003 | ||
2946 | /* intermediate packet */ | 4004 | /* intermediate packet */ |
2947 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | 4005 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
2948 | } | 4006 | } |
2949 | 4007 | ||
2950 | static void ov519_pkt_scan(struct gspca_dev *gspca_dev, | 4008 | static void ov519_pkt_scan(struct gspca_dev *gspca_dev, |
2951 | struct gspca_frame *frame, /* target */ | 4009 | u8 *data, /* isoc packet */ |
2952 | __u8 *data, /* isoc packet */ | ||
2953 | int len) /* iso packet length */ | 4010 | int len) /* iso packet length */ |
2954 | { | 4011 | { |
2955 | /* Header of ov519 is 16 bytes: | 4012 | /* Header of ov519 is 16 bytes: |
@@ -2972,7 +4029,7 @@ static void ov519_pkt_scan(struct gspca_dev *gspca_dev, | |||
2972 | len -= HDRSZ; | 4029 | len -= HDRSZ; |
2973 | #undef HDRSZ | 4030 | #undef HDRSZ |
2974 | if (data[0] == 0xff || data[1] == 0xd8) | 4031 | if (data[0] == 0xff || data[1] == 0xd8) |
2975 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | 4032 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
2976 | data, len); | 4033 | data, len); |
2977 | else | 4034 | else |
2978 | gspca_dev->last_packet_type = DISCARD_PACKET; | 4035 | gspca_dev->last_packet_type = DISCARD_PACKET; |
@@ -2980,20 +4037,31 @@ static void ov519_pkt_scan(struct gspca_dev *gspca_dev, | |||
2980 | case 0x51: /* end of frame */ | 4037 | case 0x51: /* end of frame */ |
2981 | if (data[9] != 0) | 4038 | if (data[9] != 0) |
2982 | gspca_dev->last_packet_type = DISCARD_PACKET; | 4039 | gspca_dev->last_packet_type = DISCARD_PACKET; |
2983 | gspca_frame_add(gspca_dev, LAST_PACKET, frame, | 4040 | gspca_frame_add(gspca_dev, LAST_PACKET, |
2984 | data, 0); | 4041 | NULL, 0); |
2985 | return; | 4042 | return; |
2986 | } | 4043 | } |
2987 | } | 4044 | } |
2988 | 4045 | ||
2989 | /* intermediate packet */ | 4046 | /* intermediate packet */ |
2990 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | 4047 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
2991 | data, len); | 4048 | } |
4049 | |||
4050 | static void ovfx2_pkt_scan(struct gspca_dev *gspca_dev, | ||
4051 | u8 *data, /* isoc packet */ | ||
4052 | int len) /* iso packet length */ | ||
4053 | { | ||
4054 | /* A short read signals EOF */ | ||
4055 | if (len < OVFX2_BULK_SIZE) { | ||
4056 | gspca_frame_add(gspca_dev, LAST_PACKET, data, len); | ||
4057 | gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); | ||
4058 | return; | ||
4059 | } | ||
4060 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | ||
2992 | } | 4061 | } |
2993 | 4062 | ||
2994 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 4063 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
2995 | struct gspca_frame *frame, /* target */ | 4064 | u8 *data, /* isoc packet */ |
2996 | __u8 *data, /* isoc packet */ | ||
2997 | int len) /* iso packet length */ | 4065 | int len) /* iso packet length */ |
2998 | { | 4066 | { |
2999 | struct sd *sd = (struct sd *) gspca_dev; | 4067 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -3001,14 +4069,20 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
3001 | switch (sd->bridge) { | 4069 | switch (sd->bridge) { |
3002 | case BRIDGE_OV511: | 4070 | case BRIDGE_OV511: |
3003 | case BRIDGE_OV511PLUS: | 4071 | case BRIDGE_OV511PLUS: |
3004 | ov511_pkt_scan(gspca_dev, frame, data, len); | 4072 | ov511_pkt_scan(gspca_dev, data, len); |
3005 | break; | 4073 | break; |
3006 | case BRIDGE_OV518: | 4074 | case BRIDGE_OV518: |
3007 | case BRIDGE_OV518PLUS: | 4075 | case BRIDGE_OV518PLUS: |
3008 | ov518_pkt_scan(gspca_dev, frame, data, len); | 4076 | ov518_pkt_scan(gspca_dev, data, len); |
3009 | break; | 4077 | break; |
3010 | case BRIDGE_OV519: | 4078 | case BRIDGE_OV519: |
3011 | ov519_pkt_scan(gspca_dev, frame, data, len); | 4079 | ov519_pkt_scan(gspca_dev, data, len); |
4080 | break; | ||
4081 | case BRIDGE_OVFX2: | ||
4082 | ovfx2_pkt_scan(gspca_dev, data, len); | ||
4083 | break; | ||
4084 | case BRIDGE_W9968CF: | ||
4085 | w9968cf_pkt_scan(gspca_dev, data, len); | ||
3012 | break; | 4086 | break; |
3013 | } | 4087 | } |
3014 | } | 4088 | } |
@@ -3124,7 +4198,8 @@ static void setcolors(struct gspca_dev *gspca_dev) | |||
3124 | 4198 | ||
3125 | static void setautobrightness(struct sd *sd) | 4199 | static void setautobrightness(struct sd *sd) |
3126 | { | 4200 | { |
3127 | if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670) | 4201 | if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670 || |
4202 | sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) | ||
3128 | return; | 4203 | return; |
3129 | 4204 | ||
3130 | i2c_w_mask(sd, 0x2d, sd->autobrightness ? 0x10 : 0x00, 0x10); | 4205 | i2c_w_mask(sd, 0x2d, sd->autobrightness ? 0x10 : 0x00, 0x10); |
@@ -3132,6 +4207,9 @@ static void setautobrightness(struct sd *sd) | |||
3132 | 4207 | ||
3133 | static void setfreq(struct sd *sd) | 4208 | static void setfreq(struct sd *sd) |
3134 | { | 4209 | { |
4210 | if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) | ||
4211 | return; | ||
4212 | |||
3135 | if (sd->sensor == SEN_OV7670) { | 4213 | if (sd->sensor == SEN_OV7670) { |
3136 | switch (sd->freq) { | 4214 | switch (sd->freq) { |
3137 | case 0: /* Banding filter disabled */ | 4215 | case 0: /* Banding filter disabled */ |
@@ -3301,8 +4379,12 @@ static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) | |||
3301 | struct sd *sd = (struct sd *) gspca_dev; | 4379 | struct sd *sd = (struct sd *) gspca_dev; |
3302 | 4380 | ||
3303 | sd->freq = val; | 4381 | sd->freq = val; |
3304 | if (gspca_dev->streaming) | 4382 | if (gspca_dev->streaming) { |
3305 | setfreq(sd); | 4383 | setfreq(sd); |
4384 | /* Ugly but necessary */ | ||
4385 | if (sd->bridge == BRIDGE_W9968CF) | ||
4386 | w9968cf_set_crop_window(sd); | ||
4387 | } | ||
3306 | return 0; | 4388 | return 0; |
3307 | } | 4389 | } |
3308 | 4390 | ||
@@ -3343,6 +4425,45 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, | |||
3343 | return -EINVAL; | 4425 | return -EINVAL; |
3344 | } | 4426 | } |
3345 | 4427 | ||
4428 | static int sd_get_jcomp(struct gspca_dev *gspca_dev, | ||
4429 | struct v4l2_jpegcompression *jcomp) | ||
4430 | { | ||
4431 | struct sd *sd = (struct sd *) gspca_dev; | ||
4432 | |||
4433 | if (sd->bridge != BRIDGE_W9968CF) | ||
4434 | return -EINVAL; | ||
4435 | |||
4436 | memset(jcomp, 0, sizeof *jcomp); | ||
4437 | jcomp->quality = sd->quality; | ||
4438 | jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | V4L2_JPEG_MARKER_DQT | | ||
4439 | V4L2_JPEG_MARKER_DRI; | ||
4440 | return 0; | ||
4441 | } | ||
4442 | |||
4443 | static int sd_set_jcomp(struct gspca_dev *gspca_dev, | ||
4444 | struct v4l2_jpegcompression *jcomp) | ||
4445 | { | ||
4446 | struct sd *sd = (struct sd *) gspca_dev; | ||
4447 | |||
4448 | if (sd->bridge != BRIDGE_W9968CF) | ||
4449 | return -EINVAL; | ||
4450 | |||
4451 | if (gspca_dev->streaming) | ||
4452 | return -EBUSY; | ||
4453 | |||
4454 | if (jcomp->quality < QUALITY_MIN) | ||
4455 | sd->quality = QUALITY_MIN; | ||
4456 | else if (jcomp->quality > QUALITY_MAX) | ||
4457 | sd->quality = QUALITY_MAX; | ||
4458 | else | ||
4459 | sd->quality = jcomp->quality; | ||
4460 | |||
4461 | /* Return resulting jcomp params to app */ | ||
4462 | sd_get_jcomp(gspca_dev, jcomp); | ||
4463 | |||
4464 | return 0; | ||
4465 | } | ||
4466 | |||
3346 | /* sub-driver description */ | 4467 | /* sub-driver description */ |
3347 | static const struct sd_desc sd_desc = { | 4468 | static const struct sd_desc sd_desc = { |
3348 | .name = MODULE_NAME, | 4469 | .name = MODULE_NAME, |
@@ -3352,18 +4473,23 @@ static const struct sd_desc sd_desc = { | |||
3352 | .init = sd_init, | 4473 | .init = sd_init, |
3353 | .start = sd_start, | 4474 | .start = sd_start, |
3354 | .stopN = sd_stopN, | 4475 | .stopN = sd_stopN, |
4476 | .stop0 = sd_stop0, | ||
3355 | .pkt_scan = sd_pkt_scan, | 4477 | .pkt_scan = sd_pkt_scan, |
3356 | .querymenu = sd_querymenu, | 4478 | .querymenu = sd_querymenu, |
4479 | .get_jcomp = sd_get_jcomp, | ||
4480 | .set_jcomp = sd_set_jcomp, | ||
3357 | }; | 4481 | }; |
3358 | 4482 | ||
3359 | /* -- module initialisation -- */ | 4483 | /* -- module initialisation -- */ |
3360 | static const __devinitdata struct usb_device_id device_table[] = { | 4484 | static const __devinitdata struct usb_device_id device_table[] = { |
4485 | {USB_DEVICE(0x041e, 0x4003), .driver_info = BRIDGE_W9968CF }, | ||
3361 | {USB_DEVICE(0x041e, 0x4052), .driver_info = BRIDGE_OV519 }, | 4486 | {USB_DEVICE(0x041e, 0x4052), .driver_info = BRIDGE_OV519 }, |
3362 | {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 }, | 4487 | {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 }, |
3363 | {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 }, | 4488 | {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 }, |
3364 | {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 }, | 4489 | {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 }, |
3365 | {USB_DEVICE(0x041e, 0x4064), | 4490 | {USB_DEVICE(0x041e, 0x4064), |
3366 | .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, | 4491 | .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, |
4492 | {USB_DEVICE(0x041e, 0x4067), .driver_info = BRIDGE_OV519 }, | ||
3367 | {USB_DEVICE(0x041e, 0x4068), | 4493 | {USB_DEVICE(0x041e, 0x4068), |
3368 | .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, | 4494 | .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, |
3369 | {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 }, | 4495 | {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 }, |
@@ -3373,11 +4499,16 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
3373 | {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, | 4499 | {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, |
3374 | {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 }, | 4500 | {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 }, |
3375 | {USB_DEVICE(0x05a9, 0x0530), .driver_info = BRIDGE_OV519 }, | 4501 | {USB_DEVICE(0x05a9, 0x0530), .driver_info = BRIDGE_OV519 }, |
4502 | {USB_DEVICE(0x05a9, 0x2800), .driver_info = BRIDGE_OVFX2 }, | ||
3376 | {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 }, | 4503 | {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 }, |
3377 | {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 }, | 4504 | {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 }, |
3378 | {USB_DEVICE(0x05a9, 0xa511), .driver_info = BRIDGE_OV511PLUS }, | 4505 | {USB_DEVICE(0x05a9, 0xa511), .driver_info = BRIDGE_OV511PLUS }, |
3379 | {USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS }, | 4506 | {USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS }, |
3380 | {USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS }, | 4507 | {USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS }, |
4508 | {USB_DEVICE(0x0b62, 0x0059), .driver_info = BRIDGE_OVFX2 }, | ||
4509 | {USB_DEVICE(0x0e96, 0xc001), .driver_info = BRIDGE_OVFX2 }, | ||
4510 | {USB_DEVICE(0x1046, 0x9967), .driver_info = BRIDGE_W9968CF }, | ||
4511 | {USB_DEVICE(0x8020, 0xEF04), .driver_info = BRIDGE_OVFX2 }, | ||
3381 | {} | 4512 | {} |
3382 | }; | 4513 | }; |
3383 | 4514 | ||
diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 4b528b372911..4dbb882c83dc 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * ov534 gspca driver | 2 | * ov534 gspca driver |
3 | * | ||
3 | * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it> | 4 | * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it> |
4 | * Copyright (C) 2008 Jim Paris <jim@jtan.com> | 5 | * Copyright (C) 2008 Jim Paris <jim@jtan.com> |
5 | * Copyright (C) 2009 Jean-Francois Moine http://moinejf.free.fr | 6 | * Copyright (C) 2009 Jean-Francois Moine http://moinejf.free.fr |
@@ -8,6 +9,10 @@ | |||
8 | * USB protocol reverse engineered by Jim Paris <jim@jtan.com> | 9 | * USB protocol reverse engineered by Jim Paris <jim@jtan.com> |
9 | * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/ | 10 | * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/ |
10 | * | 11 | * |
12 | * PS3 Eye camera enhanced by Richard Kaswy http://kaswy.free.fr | ||
13 | * PS3 Eye camera, brightness, contrast, hue, AWB control added | ||
14 | * by Max Thrun <bear24rw@gmail.com> | ||
15 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | 16 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License as published by | 17 | * it under the terms of the GNU General Public License as published by |
13 | * the Free Software Foundation; either version 2 of the License, or | 18 | * the Free Software Foundation; either version 2 of the License, or |
@@ -51,16 +56,335 @@ struct sd { | |||
51 | u16 last_fid; | 56 | u16 last_fid; |
52 | u8 frame_rate; | 57 | u8 frame_rate; |
53 | 58 | ||
59 | u8 brightness; | ||
60 | u8 contrast; | ||
61 | u8 gain; | ||
62 | u8 exposure; | ||
63 | u8 redblc; | ||
64 | u8 blueblc; | ||
65 | u8 hue; | ||
66 | u8 autogain; | ||
67 | u8 awb; | ||
68 | s8 sharpness; | ||
69 | u8 hflip; | ||
70 | u8 vflip; | ||
71 | u8 satur; | ||
72 | u8 lightfreq; | ||
73 | |||
54 | u8 sensor; | 74 | u8 sensor; |
55 | #define SENSOR_OV772X 0 | 75 | #define SENSOR_OV772X 0 |
56 | #define SENSOR_OV965X 1 | 76 | #define SENSOR_OV965X 1 |
57 | }; | 77 | }; |
58 | 78 | ||
59 | /* V4L2 controls supported by the driver */ | 79 | /* V4L2 controls supported by the driver */ |
60 | static struct ctrl sd_ctrls[] = { | 80 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); |
81 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | ||
82 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | ||
83 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
84 | static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val); | ||
85 | static int sd_getredblc(struct gspca_dev *gspca_dev, __s32 *val); | ||
86 | static int sd_setblueblc(struct gspca_dev *gspca_dev, __s32 val); | ||
87 | static int sd_getblueblc(struct gspca_dev *gspca_dev, __s32 *val); | ||
88 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
89 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | ||
90 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | ||
91 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | ||
92 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); | ||
93 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
94 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); | ||
95 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
96 | static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val); | ||
97 | static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val); | ||
98 | static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val); | ||
99 | static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val); | ||
100 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
101 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
102 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
103 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
104 | static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val); | ||
105 | static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val); | ||
106 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | ||
107 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | ||
108 | |||
109 | static struct ctrl sd_ctrls_ov772x[] = { | ||
110 | { /* 0 */ | ||
111 | { | ||
112 | .id = V4L2_CID_BRIGHTNESS, | ||
113 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
114 | .name = "Brightness", | ||
115 | .minimum = 0, | ||
116 | .maximum = 255, | ||
117 | .step = 1, | ||
118 | #define BRIGHTNESS_77_DEF 20 | ||
119 | .default_value = BRIGHTNESS_77_DEF, | ||
120 | }, | ||
121 | .set = sd_setbrightness, | ||
122 | .get = sd_getbrightness, | ||
123 | }, | ||
124 | { /* 1 */ | ||
125 | { | ||
126 | .id = V4L2_CID_CONTRAST, | ||
127 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
128 | .name = "Contrast", | ||
129 | .minimum = 0, | ||
130 | .maximum = 255, | ||
131 | .step = 1, | ||
132 | #define CONTRAST_77_DEF 37 | ||
133 | .default_value = CONTRAST_77_DEF, | ||
134 | }, | ||
135 | .set = sd_setcontrast, | ||
136 | .get = sd_getcontrast, | ||
137 | }, | ||
138 | { /* 2 */ | ||
139 | { | ||
140 | .id = V4L2_CID_GAIN, | ||
141 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
142 | .name = "Main Gain", | ||
143 | .minimum = 0, | ||
144 | .maximum = 63, | ||
145 | .step = 1, | ||
146 | #define GAIN_DEF 20 | ||
147 | .default_value = GAIN_DEF, | ||
148 | }, | ||
149 | .set = sd_setgain, | ||
150 | .get = sd_getgain, | ||
151 | }, | ||
152 | { /* 3 */ | ||
153 | { | ||
154 | .id = V4L2_CID_EXPOSURE, | ||
155 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
156 | .name = "Exposure", | ||
157 | .minimum = 0, | ||
158 | .maximum = 255, | ||
159 | .step = 1, | ||
160 | #define EXPO_77_DEF 120 | ||
161 | .default_value = EXPO_77_DEF, | ||
162 | }, | ||
163 | .set = sd_setexposure, | ||
164 | .get = sd_getexposure, | ||
165 | }, | ||
166 | { /* 4 */ | ||
167 | { | ||
168 | .id = V4L2_CID_RED_BALANCE, | ||
169 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
170 | .name = "Red Balance", | ||
171 | .minimum = 0, | ||
172 | .maximum = 255, | ||
173 | .step = 1, | ||
174 | #define RED_BALANCE_DEF 128 | ||
175 | .default_value = RED_BALANCE_DEF, | ||
176 | }, | ||
177 | .set = sd_setredblc, | ||
178 | .get = sd_getredblc, | ||
179 | }, | ||
180 | { /* 5 */ | ||
181 | { | ||
182 | .id = V4L2_CID_BLUE_BALANCE, | ||
183 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
184 | .name = "Blue Balance", | ||
185 | .minimum = 0, | ||
186 | .maximum = 255, | ||
187 | .step = 1, | ||
188 | #define BLUE_BALANCE_DEF 128 | ||
189 | .default_value = BLUE_BALANCE_DEF, | ||
190 | }, | ||
191 | .set = sd_setblueblc, | ||
192 | .get = sd_getblueblc, | ||
193 | }, | ||
194 | { /* 6 */ | ||
195 | { | ||
196 | .id = V4L2_CID_HUE, | ||
197 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
198 | .name = "Hue", | ||
199 | .minimum = 0, | ||
200 | .maximum = 255, | ||
201 | .step = 1, | ||
202 | #define HUE_DEF 143 | ||
203 | .default_value = HUE_DEF, | ||
204 | }, | ||
205 | .set = sd_sethue, | ||
206 | .get = sd_gethue, | ||
207 | }, | ||
208 | { /* 7 */ | ||
209 | { | ||
210 | .id = V4L2_CID_AUTOGAIN, | ||
211 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
212 | .name = "Autogain", | ||
213 | .minimum = 0, | ||
214 | .maximum = 1, | ||
215 | .step = 1, | ||
216 | #define AUTOGAIN_77_DEF 0 | ||
217 | .default_value = AUTOGAIN_77_DEF, | ||
218 | }, | ||
219 | .set = sd_setautogain, | ||
220 | .get = sd_getautogain, | ||
221 | }, | ||
222 | #define AWB_77_IDX 8 | ||
223 | { /* 8 */ | ||
224 | { | ||
225 | .id = V4L2_CID_AUTO_WHITE_BALANCE, | ||
226 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
227 | .name = "Auto White Balance", | ||
228 | .minimum = 0, | ||
229 | .maximum = 1, | ||
230 | .step = 1, | ||
231 | #define AWB_DEF 0 | ||
232 | .default_value = AWB_DEF, | ||
233 | }, | ||
234 | .set = sd_setawb, | ||
235 | .get = sd_getawb, | ||
236 | }, | ||
237 | { /* 9 */ | ||
238 | { | ||
239 | .id = V4L2_CID_SHARPNESS, | ||
240 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
241 | .name = "Sharpness", | ||
242 | .minimum = 0, | ||
243 | .maximum = 63, | ||
244 | .step = 1, | ||
245 | #define SHARPNESS_77_DEF 0 | ||
246 | .default_value = SHARPNESS_77_DEF, | ||
247 | }, | ||
248 | .set = sd_setsharpness, | ||
249 | .get = sd_getsharpness, | ||
250 | }, | ||
251 | { /* 10 */ | ||
252 | { | ||
253 | .id = V4L2_CID_HFLIP, | ||
254 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
255 | .name = "HFlip", | ||
256 | .minimum = 0, | ||
257 | .maximum = 1, | ||
258 | .step = 1, | ||
259 | #define HFLIP_DEF 0 | ||
260 | .default_value = HFLIP_DEF, | ||
261 | }, | ||
262 | .set = sd_sethflip, | ||
263 | .get = sd_gethflip, | ||
264 | }, | ||
265 | { /* 11 */ | ||
266 | { | ||
267 | .id = V4L2_CID_VFLIP, | ||
268 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
269 | .name = "VFlip", | ||
270 | .minimum = 0, | ||
271 | .maximum = 1, | ||
272 | .step = 1, | ||
273 | #define VFLIP_DEF 0 | ||
274 | .default_value = VFLIP_DEF, | ||
275 | }, | ||
276 | .set = sd_setvflip, | ||
277 | .get = sd_getvflip, | ||
278 | }, | ||
279 | }; | ||
280 | static struct ctrl sd_ctrls_ov965x[] = { | ||
281 | { /* 0 */ | ||
282 | { | ||
283 | .id = V4L2_CID_BRIGHTNESS, | ||
284 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
285 | .name = "Brightness", | ||
286 | .minimum = 0, | ||
287 | .maximum = 15, | ||
288 | .step = 1, | ||
289 | #define BRIGHTNESS_96_DEF 7 | ||
290 | .default_value = BRIGHTNESS_96_DEF, | ||
291 | }, | ||
292 | .set = sd_setbrightness, | ||
293 | .get = sd_getbrightness, | ||
294 | }, | ||
295 | { /* 1 */ | ||
296 | { | ||
297 | .id = V4L2_CID_CONTRAST, | ||
298 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
299 | .name = "Contrast", | ||
300 | .minimum = 0, | ||
301 | .maximum = 15, | ||
302 | .step = 1, | ||
303 | #define CONTRAST_96_DEF 3 | ||
304 | .default_value = CONTRAST_96_DEF, | ||
305 | }, | ||
306 | .set = sd_setcontrast, | ||
307 | .get = sd_getcontrast, | ||
308 | }, | ||
309 | { /* 2 */ | ||
310 | { | ||
311 | .id = V4L2_CID_AUTOGAIN, | ||
312 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
313 | .name = "Autogain", | ||
314 | .minimum = 0, | ||
315 | .maximum = 1, | ||
316 | .step = 1, | ||
317 | #define AUTOGAIN_96_DEF 1 | ||
318 | .default_value = AUTOGAIN_96_DEF, | ||
319 | }, | ||
320 | .set = sd_setautogain, | ||
321 | .get = sd_getautogain, | ||
322 | }, | ||
323 | #define EXPO_96_IDX 3 | ||
324 | { /* 3 */ | ||
325 | { | ||
326 | .id = V4L2_CID_EXPOSURE, | ||
327 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
328 | .name = "Exposure", | ||
329 | .minimum = 0, | ||
330 | .maximum = 3, | ||
331 | .step = 1, | ||
332 | #define EXPO_96_DEF 0 | ||
333 | .default_value = EXPO_96_DEF, | ||
334 | }, | ||
335 | .set = sd_setexposure, | ||
336 | .get = sd_getexposure, | ||
337 | }, | ||
338 | { /* 4 */ | ||
339 | { | ||
340 | .id = V4L2_CID_SHARPNESS, | ||
341 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
342 | .name = "Sharpness", | ||
343 | .minimum = -1, /* -1 = auto */ | ||
344 | .maximum = 4, | ||
345 | .step = 1, | ||
346 | #define SHARPNESS_96_DEF -1 | ||
347 | .default_value = SHARPNESS_96_DEF, | ||
348 | }, | ||
349 | .set = sd_setsharpness, | ||
350 | .get = sd_getsharpness, | ||
351 | }, | ||
352 | { /* 5 */ | ||
353 | { | ||
354 | .id = V4L2_CID_SATURATION, | ||
355 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
356 | .name = "Saturation", | ||
357 | .minimum = 0, | ||
358 | .maximum = 4, | ||
359 | .step = 1, | ||
360 | #define SATUR_DEF 2 | ||
361 | .default_value = SATUR_DEF, | ||
362 | }, | ||
363 | .set = sd_setsatur, | ||
364 | .get = sd_getsatur, | ||
365 | }, | ||
366 | { | ||
367 | { | ||
368 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | ||
369 | .type = V4L2_CTRL_TYPE_MENU, | ||
370 | .name = "Light frequency filter", | ||
371 | .minimum = 0, | ||
372 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ | ||
373 | .step = 1, | ||
374 | #define FREQ_DEF 0 | ||
375 | .default_value = FREQ_DEF, | ||
376 | }, | ||
377 | .set = sd_setfreq, | ||
378 | .get = sd_getfreq, | ||
379 | }, | ||
61 | }; | 380 | }; |
62 | 381 | ||
63 | static const struct v4l2_pix_format vga_yuyv_mode[] = { | 382 | static const struct v4l2_pix_format ov772x_mode[] = { |
383 | {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, | ||
384 | .bytesperline = 320 * 2, | ||
385 | .sizeimage = 320 * 240 * 2, | ||
386 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
387 | .priv = 1}, | ||
64 | {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, | 388 | {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, |
65 | .bytesperline = 640 * 2, | 389 | .bytesperline = 640 * 2, |
66 | .sizeimage = 640 * 480 * 2, | 390 | .sizeimage = 640 * 480 * 2, |
@@ -68,20 +392,35 @@ static const struct v4l2_pix_format vga_yuyv_mode[] = { | |||
68 | .priv = 0}, | 392 | .priv = 0}, |
69 | }; | 393 | }; |
70 | 394 | ||
71 | static const struct v4l2_pix_format vga_jpeg_mode[] = { | 395 | static const struct v4l2_pix_format ov965x_mode[] = { |
72 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 396 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
73 | .bytesperline = 320, | 397 | .bytesperline = 320, |
74 | .sizeimage = 320 * 240 * 3 / 8 + 590, | 398 | .sizeimage = 320 * 240 * 3 / 8 + 590, |
75 | .colorspace = V4L2_COLORSPACE_JPEG, | 399 | .colorspace = V4L2_COLORSPACE_JPEG, |
76 | .priv = 1}, | 400 | .priv = 4}, |
77 | {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 401 | {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
78 | .bytesperline = 640, | 402 | .bytesperline = 640, |
79 | .sizeimage = 640 * 480 * 3 / 8 + 590, | 403 | .sizeimage = 640 * 480 * 3 / 8 + 590, |
80 | .colorspace = V4L2_COLORSPACE_JPEG, | 404 | .colorspace = V4L2_COLORSPACE_JPEG, |
405 | .priv = 3}, | ||
406 | {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
407 | .bytesperline = 800, | ||
408 | .sizeimage = 800 * 600 * 3 / 8 + 590, | ||
409 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
410 | .priv = 2}, | ||
411 | {1024, 768, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
412 | .bytesperline = 1024, | ||
413 | .sizeimage = 1024 * 768 * 3 / 8 + 590, | ||
414 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
415 | .priv = 1}, | ||
416 | {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
417 | .bytesperline = 1280, | ||
418 | .sizeimage = 1280 * 1024 * 3 / 8 + 590, | ||
419 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
81 | .priv = 0}, | 420 | .priv = 0}, |
82 | }; | 421 | }; |
83 | 422 | ||
84 | static const u8 bridge_init_ov722x[][2] = { | 423 | static const u8 bridge_init_ov772x[][2] = { |
85 | { 0xc2, 0x0c }, | 424 | { 0xc2, 0x0c }, |
86 | { 0x88, 0xf8 }, | 425 | { 0x88, 0xf8 }, |
87 | { 0xc3, 0x69 }, | 426 | { 0xc3, 0x69 }, |
@@ -122,6 +461,7 @@ static const u8 bridge_init_ov722x[][2] = { | |||
122 | { 0x1d, 0x40 }, | 461 | { 0x1d, 0x40 }, |
123 | { 0x1d, 0x02 }, /* payload size 0x0200 * 4 = 2048 bytes */ | 462 | { 0x1d, 0x02 }, /* payload size 0x0200 * 4 = 2048 bytes */ |
124 | { 0x1d, 0x00 }, /* payload size */ | 463 | { 0x1d, 0x00 }, /* payload size */ |
464 | |||
125 | { 0x1d, 0x02 }, /* frame size 0x025800 * 4 = 614400 */ | 465 | { 0x1d, 0x02 }, /* frame size 0x025800 * 4 = 614400 */ |
126 | { 0x1d, 0x58 }, /* frame size */ | 466 | { 0x1d, 0x58 }, /* frame size */ |
127 | { 0x1d, 0x00 }, /* frame size */ | 467 | { 0x1d, 0x00 }, /* frame size */ |
@@ -138,10 +478,20 @@ static const u8 bridge_init_ov722x[][2] = { | |||
138 | { 0xc1, 0x3c }, | 478 | { 0xc1, 0x3c }, |
139 | { 0xc2, 0x0c }, | 479 | { 0xc2, 0x0c }, |
140 | }; | 480 | }; |
141 | 481 | static const u8 sensor_init_ov772x[][2] = { | |
142 | static const u8 sensor_init_ov722x[][2] = { | ||
143 | { 0x12, 0x80 }, | 482 | { 0x12, 0x80 }, |
144 | { 0x11, 0x01 }, | 483 | { 0x11, 0x01 }, |
484 | /*fixme: better have a delay?*/ | ||
485 | { 0x11, 0x01 }, | ||
486 | { 0x11, 0x01 }, | ||
487 | { 0x11, 0x01 }, | ||
488 | { 0x11, 0x01 }, | ||
489 | { 0x11, 0x01 }, | ||
490 | { 0x11, 0x01 }, | ||
491 | { 0x11, 0x01 }, | ||
492 | { 0x11, 0x01 }, | ||
493 | { 0x11, 0x01 }, | ||
494 | { 0x11, 0x01 }, | ||
145 | 495 | ||
146 | { 0x3d, 0x03 }, | 496 | { 0x3d, 0x03 }, |
147 | { 0x17, 0x26 }, | 497 | { 0x17, 0x26 }, |
@@ -154,10 +504,10 @@ static const u8 sensor_init_ov722x[][2] = { | |||
154 | { 0x65, 0x20 }, | 504 | { 0x65, 0x20 }, |
155 | { 0x11, 0x01 }, | 505 | { 0x11, 0x01 }, |
156 | { 0x42, 0x7f }, | 506 | { 0x42, 0x7f }, |
157 | { 0x63, 0xe0 }, | 507 | { 0x63, 0xaa }, /* AWB - was e0 */ |
158 | { 0x64, 0xff }, | 508 | { 0x64, 0xff }, |
159 | { 0x66, 0x00 }, | 509 | { 0x66, 0x00 }, |
160 | { 0x13, 0xf0 }, | 510 | { 0x13, 0xf0 }, /* com8 */ |
161 | { 0x0d, 0x41 }, | 511 | { 0x0d, 0x41 }, |
162 | { 0x0f, 0xc5 }, | 512 | { 0x0f, 0xc5 }, |
163 | { 0x14, 0x11 }, | 513 | { 0x14, 0x11 }, |
@@ -170,7 +520,7 @@ static const u8 sensor_init_ov722x[][2] = { | |||
170 | { 0x2a, 0x00 }, | 520 | { 0x2a, 0x00 }, |
171 | { 0x2b, 0x00 }, | 521 | { 0x2b, 0x00 }, |
172 | { 0x6b, 0xaa }, | 522 | { 0x6b, 0xaa }, |
173 | { 0x13, 0xff }, | 523 | { 0x13, 0xff }, /* AWB */ |
174 | 524 | ||
175 | { 0x90, 0x05 }, | 525 | { 0x90, 0x05 }, |
176 | { 0x91, 0x01 }, | 526 | { 0x91, 0x01 }, |
@@ -218,9 +568,51 @@ static const u8 sensor_init_ov722x[][2] = { | |||
218 | { 0x14, 0x41 }, | 568 | { 0x14, 0x41 }, |
219 | { 0x0e, 0xcd }, | 569 | { 0x0e, 0xcd }, |
220 | { 0xac, 0xbf }, | 570 | { 0xac, 0xbf }, |
221 | { 0x8e, 0x00 }, | 571 | { 0x8e, 0x00 }, /* De-noise threshold */ |
222 | { 0x0c, 0xd0 } | 572 | { 0x0c, 0xd0 } |
223 | }; | 573 | }; |
574 | static const u8 bridge_start_ov772x_vga[][2] = { | ||
575 | {0x1c, 0x00}, | ||
576 | {0x1d, 0x40}, | ||
577 | {0x1d, 0x02}, | ||
578 | {0x1d, 0x00}, | ||
579 | {0x1d, 0x02}, | ||
580 | {0x1d, 0x58}, | ||
581 | {0x1d, 0x00}, | ||
582 | {0xc0, 0x50}, | ||
583 | {0xc1, 0x3c}, | ||
584 | }; | ||
585 | static const u8 sensor_start_ov772x_vga[][2] = { | ||
586 | {0x12, 0x00}, | ||
587 | {0x17, 0x26}, | ||
588 | {0x18, 0xa0}, | ||
589 | {0x19, 0x07}, | ||
590 | {0x1a, 0xf0}, | ||
591 | {0x29, 0xa0}, | ||
592 | {0x2c, 0xf0}, | ||
593 | {0x65, 0x20}, | ||
594 | }; | ||
595 | static const u8 bridge_start_ov772x_qvga[][2] = { | ||
596 | {0x1c, 0x00}, | ||
597 | {0x1d, 0x40}, | ||
598 | {0x1d, 0x02}, | ||
599 | {0x1d, 0x00}, | ||
600 | {0x1d, 0x01}, | ||
601 | {0x1d, 0x4b}, | ||
602 | {0x1d, 0x00}, | ||
603 | {0xc0, 0x28}, | ||
604 | {0xc1, 0x1e}, | ||
605 | }; | ||
606 | static const u8 sensor_start_ov772x_qvga[][2] = { | ||
607 | {0x12, 0x40}, | ||
608 | {0x17, 0x3f}, | ||
609 | {0x18, 0x50}, | ||
610 | {0x19, 0x03}, | ||
611 | {0x1a, 0x78}, | ||
612 | {0x29, 0x50}, | ||
613 | {0x2c, 0x78}, | ||
614 | {0x65, 0x2f}, | ||
615 | }; | ||
224 | 616 | ||
225 | static const u8 bridge_init_ov965x[][2] = { | 617 | static const u8 bridge_init_ov965x[][2] = { |
226 | {0x88, 0xf8}, | 618 | {0x88, 0xf8}, |
@@ -403,7 +795,7 @@ static const u8 sensor_init_ov965x[][2] = { | |||
403 | {0xcb, 0xf0}, | 795 | {0xcb, 0xf0}, |
404 | {0xcc, 0xd8}, | 796 | {0xcc, 0xd8}, |
405 | {0xcd, 0xf1}, | 797 | {0xcd, 0xf1}, |
406 | {0x4f, 0x98}, | 798 | {0x4f, 0x98}, /* matrix */ |
407 | {0x50, 0x98}, | 799 | {0x50, 0x98}, |
408 | {0x51, 0x00}, | 800 | {0x51, 0x00}, |
409 | {0x52, 0x28}, | 801 | {0x52, 0x28}, |
@@ -412,6 +804,7 @@ static const u8 sensor_init_ov965x[][2] = { | |||
412 | {0x58, 0x1a}, | 804 | {0x58, 0x1a}, |
413 | {0xff, 0x41}, /* read 41, write ff 00 */ | 805 | {0xff, 0x41}, /* read 41, write ff 00 */ |
414 | {0x41, 0x40}, /* com16 */ | 806 | {0x41, 0x40}, /* com16 */ |
807 | |||
415 | {0xc5, 0x03}, /* 60 Hz banding filter */ | 808 | {0xc5, 0x03}, /* 60 Hz banding filter */ |
416 | {0x6a, 0x02}, /* 50 Hz banding filter */ | 809 | {0x6a, 0x02}, /* 50 Hz banding filter */ |
417 | 810 | ||
@@ -455,8 +848,8 @@ static const u8 bridge_init_ov965x_2[][2] = { | |||
455 | {0x52, 0x3c}, | 848 | {0x52, 0x3c}, |
456 | {0x53, 0x00}, | 849 | {0x53, 0x00}, |
457 | {0x54, 0x00}, | 850 | {0x54, 0x00}, |
458 | {0x55, 0x00}, /* brightness */ | 851 | {0x55, 0x00}, |
459 | {0x57, 0x00}, /* contrast 2 */ | 852 | {0x57, 0x00}, |
460 | {0x5c, 0x00}, | 853 | {0x5c, 0x00}, |
461 | {0x5a, 0xa0}, | 854 | {0x5a, 0xa0}, |
462 | {0x5b, 0x78}, | 855 | {0x5b, 0x78}, |
@@ -479,14 +872,16 @@ static const u8 sensor_init_ov965x_2[][2] = { | |||
479 | {0xa3, 0x3e}, | 872 | {0xa3, 0x3e}, |
480 | {0x2d, 0x00}, | 873 | {0x2d, 0x00}, |
481 | {0xff, 0x42}, /* read 42, write ff 00 */ | 874 | {0xff, 0x42}, /* read 42, write ff 00 */ |
482 | {0x42, 0xc0}, | 875 | {0x42, 0xc0}, /* com17 */ |
483 | {0x2d, 0x00}, | 876 | {0x2d, 0x00}, |
484 | {0xff, 0x42}, /* read 42, write ff 00 */ | 877 | {0xff, 0x42}, /* read 42, write ff 00 */ |
485 | {0x42, 0xc1}, | 878 | {0x42, 0xc1}, /* com17 */ |
879 | /* sharpness */ | ||
486 | {0x3f, 0x01}, | 880 | {0x3f, 0x01}, |
487 | {0xff, 0x42}, /* read 42, write ff 00 */ | 881 | {0xff, 0x42}, /* read 42, write ff 00 */ |
488 | {0x42, 0xc1}, | 882 | {0x42, 0xc1}, /* com17 */ |
489 | {0x4f, 0x98}, | 883 | /* saturation */ |
884 | {0x4f, 0x98}, /* matrix */ | ||
490 | {0x50, 0x98}, | 885 | {0x50, 0x98}, |
491 | {0x51, 0x00}, | 886 | {0x51, 0x00}, |
492 | {0x52, 0x28}, | 887 | {0x52, 0x28}, |
@@ -495,14 +890,17 @@ static const u8 sensor_init_ov965x_2[][2] = { | |||
495 | {0x58, 0x1a}, | 890 | {0x58, 0x1a}, |
496 | {0xff, 0x41}, /* read 41, write ff 00 */ | 891 | {0xff, 0x41}, /* read 41, write ff 00 */ |
497 | {0x41, 0x40}, /* com16 */ | 892 | {0x41, 0x40}, /* com16 */ |
893 | /* contrast */ | ||
498 | {0x56, 0x40}, | 894 | {0x56, 0x40}, |
895 | /* brightness */ | ||
499 | {0x55, 0x8f}, | 896 | {0x55, 0x8f}, |
897 | /* expo */ | ||
500 | {0x10, 0x25}, /* aech - exposure high bits */ | 898 | {0x10, 0x25}, /* aech - exposure high bits */ |
501 | {0xff, 0x13}, /* read 13, write ff 00 */ | 899 | {0xff, 0x13}, /* read 13, write ff 00 */ |
502 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | 900 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ |
503 | }; | 901 | }; |
504 | 902 | ||
505 | static const u8 sensor_start_ov965x[][2] = { | 903 | static const u8 sensor_start_ov965x_1_vga[][2] = { /* same for qvga */ |
506 | {0x12, 0x62}, /* com7 - 30fps VGA YUV */ | 904 | {0x12, 0x62}, /* com7 - 30fps VGA YUV */ |
507 | {0x36, 0xfa}, /* aref3 */ | 905 | {0x36, 0xfa}, /* aref3 */ |
508 | {0x69, 0x0a}, /* hv */ | 906 | {0x69, 0x0a}, /* hv */ |
@@ -523,10 +921,77 @@ static const u8 sensor_start_ov965x[][2] = { | |||
523 | {0x1a, 0x3d}, /* vstop */ | 921 | {0x1a, 0x3d}, /* vstop */ |
524 | {0x32, 0xff}, /* href */ | 922 | {0x32, 0xff}, /* href */ |
525 | {0xc0, 0xaa}, | 923 | {0xc0, 0xaa}, |
526 | {} | ||
527 | }; | 924 | }; |
528 | 925 | ||
529 | static const u8 bridge_start_ov965x[][2] = { | 926 | static const u8 sensor_start_ov965x_1_svga[][2] = { |
927 | {0x12, 0x02}, /* com7 - YUYV - VGA 15 full resolution */ | ||
928 | {0x36, 0xf8}, /* aref3 */ | ||
929 | {0x69, 0x02}, /* hv */ | ||
930 | {0x8c, 0x0d}, /* com22 */ | ||
931 | {0x3e, 0x0c}, /* com14 */ | ||
932 | {0x41, 0x40}, /* com16 */ | ||
933 | {0x72, 0x00}, | ||
934 | {0x73, 0x01}, | ||
935 | {0x74, 0x3a}, | ||
936 | {0x75, 0x35}, | ||
937 | {0x76, 0x01}, | ||
938 | {0xc7, 0x80}, /* com24 */ | ||
939 | {0x03, 0x1b}, /* vref */ | ||
940 | {0x17, 0x1d}, /* hstart */ | ||
941 | {0x18, 0xbd}, /* hstop */ | ||
942 | {0x19, 0x01}, /* vstrt */ | ||
943 | {0x1a, 0x81}, /* vstop */ | ||
944 | {0x32, 0xff}, /* href */ | ||
945 | {0xc0, 0xe2}, | ||
946 | }; | ||
947 | |||
948 | static const u8 sensor_start_ov965x_1_xga[][2] = { | ||
949 | {0x12, 0x02}, /* com7 */ | ||
950 | {0x36, 0xf8}, /* aref3 */ | ||
951 | {0x69, 0x02}, /* hv */ | ||
952 | {0x8c, 0x89}, /* com22 */ | ||
953 | {0x14, 0x28}, /* com9 */ | ||
954 | {0x3e, 0x0c}, /* com14 */ | ||
955 | {0x41, 0x40}, /* com16 */ | ||
956 | {0x72, 0x00}, | ||
957 | {0x73, 0x01}, | ||
958 | {0x74, 0x3a}, | ||
959 | {0x75, 0x35}, | ||
960 | {0x76, 0x01}, | ||
961 | {0xc7, 0x80}, /* com24 */ | ||
962 | {0x03, 0x1b}, /* vref */ | ||
963 | {0x17, 0x1d}, /* hstart */ | ||
964 | {0x18, 0xbd}, /* hstop */ | ||
965 | {0x19, 0x01}, /* vstrt */ | ||
966 | {0x1a, 0x81}, /* vstop */ | ||
967 | {0x32, 0xff}, /* href */ | ||
968 | {0xc0, 0xe2}, | ||
969 | }; | ||
970 | |||
971 | static const u8 sensor_start_ov965x_1_sxga[][2] = { | ||
972 | {0x12, 0x02}, /* com7 */ | ||
973 | {0x36, 0xf8}, /* aref3 */ | ||
974 | {0x69, 0x02}, /* hv */ | ||
975 | {0x8c, 0x89}, /* com22 */ | ||
976 | {0x14, 0x28}, /* com9 */ | ||
977 | {0x3e, 0x0c}, /* com14 */ | ||
978 | {0x41, 0x40}, /* com16 */ | ||
979 | {0x72, 0x00}, | ||
980 | {0x73, 0x01}, | ||
981 | {0x74, 0x3a}, | ||
982 | {0x75, 0x35}, | ||
983 | {0x76, 0x01}, | ||
984 | {0xc7, 0x80}, /* com24 */ | ||
985 | {0x03, 0x1b}, /* vref */ | ||
986 | {0x17, 0x1d}, /* hstart */ | ||
987 | {0x18, 0x02}, /* hstop */ | ||
988 | {0x19, 0x01}, /* vstrt */ | ||
989 | {0x1a, 0x81}, /* vstop */ | ||
990 | {0x32, 0xff}, /* href */ | ||
991 | {0xc0, 0xe2}, | ||
992 | }; | ||
993 | |||
994 | static const u8 bridge_start_ov965x_qvga[][2] = { | ||
530 | {0x94, 0xaa}, | 995 | {0x94, 0xaa}, |
531 | {0xf1, 0x60}, | 996 | {0xf1, 0x60}, |
532 | {0xe5, 0x04}, | 997 | {0xe5, 0x04}, |
@@ -535,10 +1000,34 @@ static const u8 bridge_start_ov965x[][2] = { | |||
535 | {0x8c, 0x00}, | 1000 | {0x8c, 0x00}, |
536 | {0x8d, 0x1c}, | 1001 | {0x8d, 0x1c}, |
537 | {0x34, 0x05}, | 1002 | {0x34, 0x05}, |
538 | {} | 1003 | |
1004 | {0xc2, 0x4c}, | ||
1005 | {0xc3, 0xf9}, | ||
1006 | {0xda, 0x00}, | ||
1007 | {0x50, 0x00}, | ||
1008 | {0x51, 0xa0}, | ||
1009 | {0x52, 0x78}, | ||
1010 | {0x53, 0x00}, | ||
1011 | {0x54, 0x00}, | ||
1012 | {0x55, 0x00}, | ||
1013 | {0x57, 0x00}, | ||
1014 | {0x5c, 0x00}, | ||
1015 | {0x5a, 0x50}, | ||
1016 | {0x5b, 0x3c}, | ||
1017 | {0x35, 0x02}, | ||
1018 | {0xd9, 0x10}, | ||
1019 | {0x94, 0x11}, | ||
539 | }; | 1020 | }; |
540 | 1021 | ||
541 | static const u8 bridge_start_ov965x_vga[][2] = { | 1022 | static const u8 bridge_start_ov965x_vga[][2] = { |
1023 | {0x94, 0xaa}, | ||
1024 | {0xf1, 0x60}, | ||
1025 | {0xe5, 0x04}, | ||
1026 | {0xc0, 0x50}, | ||
1027 | {0xc1, 0x3c}, | ||
1028 | {0x8c, 0x00}, | ||
1029 | {0x8d, 0x1c}, | ||
1030 | {0x34, 0x05}, | ||
542 | {0xc2, 0x0c}, | 1031 | {0xc2, 0x0c}, |
543 | {0xc3, 0xf9}, | 1032 | {0xc3, 0xf9}, |
544 | {0xda, 0x01}, | 1033 | {0xda, 0x01}, |
@@ -555,30 +1044,98 @@ static const u8 bridge_start_ov965x_vga[][2] = { | |||
555 | {0x35, 0x02}, | 1044 | {0x35, 0x02}, |
556 | {0xd9, 0x10}, | 1045 | {0xd9, 0x10}, |
557 | {0x94, 0x11}, | 1046 | {0x94, 0x11}, |
558 | {} | ||
559 | }; | 1047 | }; |
560 | 1048 | ||
561 | static const u8 bridge_start_ov965x_cif[][2] = { | 1049 | static const u8 bridge_start_ov965x_svga[][2] = { |
1050 | {0x94, 0xaa}, | ||
1051 | {0xf1, 0x60}, | ||
1052 | {0xe5, 0x04}, | ||
1053 | {0xc0, 0xa0}, | ||
1054 | {0xc1, 0x80}, | ||
1055 | {0x8c, 0x00}, | ||
1056 | {0x8d, 0x1c}, | ||
1057 | {0x34, 0x05}, | ||
562 | {0xc2, 0x4c}, | 1058 | {0xc2, 0x4c}, |
563 | {0xc3, 0xf9}, | 1059 | {0xc3, 0xf9}, |
564 | {0xda, 0x00}, | ||
565 | {0x50, 0x00}, | 1060 | {0x50, 0x00}, |
566 | {0x51, 0xa0}, | 1061 | {0x51, 0x40}, |
567 | {0x52, 0x78}, | 1062 | {0x52, 0x00}, |
568 | {0x53, 0x00}, | 1063 | {0x53, 0x00}, |
569 | {0x54, 0x00}, | 1064 | {0x54, 0x00}, |
570 | {0x55, 0x00}, | 1065 | {0x55, 0x88}, |
571 | {0x57, 0x00}, | 1066 | {0x57, 0x00}, |
572 | {0x5c, 0x00}, | 1067 | {0x5c, 0x00}, |
573 | {0x5a, 0x50}, | 1068 | {0x5a, 0xc8}, |
574 | {0x5b, 0x3c}, | 1069 | {0x5b, 0x96}, |
575 | {0x35, 0x02}, | 1070 | {0x35, 0x02}, |
576 | {0xd9, 0x10}, | 1071 | {0xd9, 0x10}, |
1072 | {0xda, 0x00}, | ||
577 | {0x94, 0x11}, | 1073 | {0x94, 0x11}, |
578 | {} | ||
579 | }; | 1074 | }; |
580 | 1075 | ||
581 | static const u8 sensor_start_ov965x_vga[][2] = { | 1076 | static const u8 bridge_start_ov965x_xga[][2] = { |
1077 | {0x94, 0xaa}, | ||
1078 | {0xf1, 0x60}, | ||
1079 | {0xe5, 0x04}, | ||
1080 | {0xc0, 0xa0}, | ||
1081 | {0xc1, 0x80}, | ||
1082 | {0x8c, 0x00}, | ||
1083 | {0x8d, 0x1c}, | ||
1084 | {0x34, 0x05}, | ||
1085 | {0xc2, 0x4c}, | ||
1086 | {0xc3, 0xf9}, | ||
1087 | {0x50, 0x00}, | ||
1088 | {0x51, 0x40}, | ||
1089 | {0x52, 0x00}, | ||
1090 | {0x53, 0x00}, | ||
1091 | {0x54, 0x00}, | ||
1092 | {0x55, 0x88}, | ||
1093 | {0x57, 0x00}, | ||
1094 | {0x5c, 0x01}, | ||
1095 | {0x5a, 0x00}, | ||
1096 | {0x5b, 0xc0}, | ||
1097 | {0x35, 0x02}, | ||
1098 | {0xd9, 0x10}, | ||
1099 | {0xda, 0x01}, | ||
1100 | {0x94, 0x11}, | ||
1101 | }; | ||
1102 | |||
1103 | static const u8 bridge_start_ov965x_sxga[][2] = { | ||
1104 | {0x94, 0xaa}, | ||
1105 | {0xf1, 0x60}, | ||
1106 | {0xe5, 0x04}, | ||
1107 | {0xc0, 0xa0}, | ||
1108 | {0xc1, 0x80}, | ||
1109 | {0x8c, 0x00}, | ||
1110 | {0x8d, 0x1c}, | ||
1111 | {0x34, 0x05}, | ||
1112 | {0xc2, 0x0c}, | ||
1113 | {0xc3, 0xf9}, | ||
1114 | {0xda, 0x00}, | ||
1115 | {0x35, 0x02}, | ||
1116 | {0xd9, 0x10}, | ||
1117 | {0x94, 0x11}, | ||
1118 | }; | ||
1119 | |||
1120 | static const u8 sensor_start_ov965x_2_qvga[][2] = { | ||
1121 | {0x3b, 0xe4}, /* com11 - night mode 1/4 frame rate */ | ||
1122 | {0x1e, 0x04}, /* mvfp */ | ||
1123 | {0x13, 0xe0}, /* com8 */ | ||
1124 | {0x00, 0x00}, | ||
1125 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
1126 | {0x11, 0x01}, /* clkrc */ | ||
1127 | {0x6b, 0x5a}, /* dblv */ | ||
1128 | {0x6a, 0x02}, /* 50 Hz banding filter */ | ||
1129 | {0xc5, 0x03}, /* 60 Hz banding filter */ | ||
1130 | {0xa2, 0x96}, /* bd50 */ | ||
1131 | {0xa3, 0x7d}, /* bd60 */ | ||
1132 | |||
1133 | {0xff, 0x13}, /* read 13, write ff 00 */ | ||
1134 | {0x13, 0xe7}, | ||
1135 | {0x3a, 0x80}, /* tslb - yuyv */ | ||
1136 | }; | ||
1137 | |||
1138 | static const u8 sensor_start_ov965x_2_vga[][2] = { | ||
582 | {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ | 1139 | {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ |
583 | {0x1e, 0x04}, /* mvfp */ | 1140 | {0x1e, 0x04}, /* mvfp */ |
584 | {0x13, 0xe0}, /* com8 */ | 1141 | {0x13, 0xe0}, /* com8 */ |
@@ -592,35 +1149,36 @@ static const u8 sensor_start_ov965x_vga[][2] = { | |||
592 | {0xa3, 0x3e}, /* bd60 */ | 1149 | {0xa3, 0x3e}, /* bd60 */ |
593 | 1150 | ||
594 | {0x2d, 0x00}, /* advfl */ | 1151 | {0x2d, 0x00}, /* advfl */ |
595 | {} | ||
596 | }; | 1152 | }; |
597 | 1153 | ||
598 | static const u8 sensor_start_ov965x_cif[][2] = { | 1154 | static const u8 sensor_start_ov965x_2_svga[][2] = { /* same for xga */ |
599 | {0x3b, 0xe4}, /* com11 - night mode 1/4 frame rate */ | 1155 | {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ |
600 | {0x1e, 0x04}, /* mvfp */ | 1156 | {0x1e, 0x04}, /* mvfp */ |
601 | {0x13, 0xe0}, /* com8 */ | 1157 | {0x13, 0xe0}, /* com8 */ |
602 | {0x00, 0x00}, | 1158 | {0x00, 0x00}, |
603 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | 1159 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ |
604 | {0x11, 0x01}, /* clkrc */ | 1160 | {0x11, 0x01}, /* clkrc */ |
605 | {0x6b, 0x5a}, /* dblv */ | 1161 | {0x6b, 0x5a}, /* dblv */ |
606 | {0x6a, 0x02}, /* 50 Hz banding filter */ | 1162 | {0x6a, 0x0c}, /* 50 Hz banding filter */ |
607 | {0xc5, 0x03}, /* 60 Hz banding filter */ | 1163 | {0xc5, 0x0f}, /* 60 Hz banding filter */ |
608 | {0xa2, 0x96}, /* bd50 */ | 1164 | {0xa2, 0x4e}, /* bd50 */ |
609 | {0xa3, 0x7d}, /* bd60 */ | 1165 | {0xa3, 0x41}, /* bd60 */ |
610 | |||
611 | {0xff, 0x13}, /* read 13, write ff 00 */ | ||
612 | {0x13, 0xe7}, | ||
613 | {0x3a, 0x80}, /* tslb - yuyv */ | ||
614 | {} | ||
615 | }; | 1166 | }; |
616 | 1167 | ||
617 | static const u8 sensor_start_ov965x_2[][2] = { | 1168 | static const u8 sensor_start_ov965x_2_sxga[][2] = { |
618 | {0xff, 0x42}, /* read 42, write ff 00 */ | 1169 | {0x13, 0xe0}, /* com8 */ |
619 | {0x42, 0xc1}, /* com17 - 50 Hz filter */ | 1170 | {0x00, 0x00}, |
620 | {} | 1171 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ |
1172 | {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ | ||
1173 | {0x1e, 0x04}, /* mvfp */ | ||
1174 | {0x11, 0x01}, /* clkrc */ | ||
1175 | {0x6b, 0x5a}, /* dblv */ | ||
1176 | {0x6a, 0x0c}, /* 50 Hz banding filter */ | ||
1177 | {0xc5, 0x0f}, /* 60 Hz banding filter */ | ||
1178 | {0xa2, 0x4e}, /* bd50 */ | ||
1179 | {0xa3, 0x41}, /* bd60 */ | ||
621 | }; | 1180 | }; |
622 | 1181 | ||
623 | |||
624 | static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val) | 1182 | static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val) |
625 | { | 1183 | { |
626 | struct usb_device *udev = gspca_dev->dev; | 1184 | struct usb_device *udev = gspca_dev->dev; |
@@ -753,39 +1311,310 @@ static void sccb_w_array(struct gspca_dev *gspca_dev, | |||
753 | } | 1311 | } |
754 | } | 1312 | } |
755 | 1313 | ||
756 | /* set framerate */ | 1314 | /* ov772x specific controls */ |
757 | static void ov534_set_frame_rate(struct gspca_dev *gspca_dev) | 1315 | static void set_frame_rate(struct gspca_dev *gspca_dev) |
1316 | { | ||
1317 | struct sd *sd = (struct sd *) gspca_dev; | ||
1318 | int i; | ||
1319 | struct rate_s { | ||
1320 | u8 fps; | ||
1321 | u8 r11; | ||
1322 | u8 r0d; | ||
1323 | u8 re5; | ||
1324 | }; | ||
1325 | const struct rate_s *r; | ||
1326 | static const struct rate_s rate_0[] = { /* 640x480 */ | ||
1327 | {60, 0x01, 0xc1, 0x04}, | ||
1328 | {50, 0x01, 0x41, 0x02}, | ||
1329 | {40, 0x02, 0xc1, 0x04}, | ||
1330 | {30, 0x04, 0x81, 0x02}, | ||
1331 | {15, 0x03, 0x41, 0x04}, | ||
1332 | }; | ||
1333 | static const struct rate_s rate_1[] = { /* 320x240 */ | ||
1334 | {125, 0x02, 0x81, 0x02}, | ||
1335 | {100, 0x02, 0xc1, 0x04}, | ||
1336 | {75, 0x03, 0xc1, 0x04}, | ||
1337 | {60, 0x04, 0xc1, 0x04}, | ||
1338 | {50, 0x02, 0x41, 0x04}, | ||
1339 | {40, 0x03, 0x41, 0x04}, | ||
1340 | {30, 0x04, 0x41, 0x04}, | ||
1341 | }; | ||
1342 | |||
1343 | if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv == 0) { | ||
1344 | r = rate_0; | ||
1345 | i = ARRAY_SIZE(rate_0); | ||
1346 | } else { | ||
1347 | r = rate_1; | ||
1348 | i = ARRAY_SIZE(rate_1); | ||
1349 | } | ||
1350 | while (--i > 0) { | ||
1351 | if (sd->frame_rate >= r->fps) | ||
1352 | break; | ||
1353 | r++; | ||
1354 | } | ||
1355 | |||
1356 | sccb_reg_write(gspca_dev, 0x11, r->r11); | ||
1357 | sccb_reg_write(gspca_dev, 0x0d, r->r0d); | ||
1358 | ov534_reg_write(gspca_dev, 0xe5, r->re5); | ||
1359 | |||
1360 | PDEBUG(D_PROBE, "frame_rate: %d", r->fps); | ||
1361 | } | ||
1362 | |||
1363 | static void setbrightness_77(struct gspca_dev *gspca_dev) | ||
1364 | { | ||
1365 | struct sd *sd = (struct sd *) gspca_dev; | ||
1366 | |||
1367 | sccb_reg_write(gspca_dev, 0x9B, sd->brightness); | ||
1368 | } | ||
1369 | |||
1370 | static void setcontrast_77(struct gspca_dev *gspca_dev) | ||
758 | { | 1371 | { |
759 | struct sd *sd = (struct sd *) gspca_dev; | 1372 | struct sd *sd = (struct sd *) gspca_dev; |
760 | int fr = sd->frame_rate; | ||
761 | 1373 | ||
762 | switch (fr) { | 1374 | sccb_reg_write(gspca_dev, 0x9C, sd->contrast); |
763 | case 50: | 1375 | } |
764 | sccb_reg_write(gspca_dev, 0x11, 0x01); | 1376 | |
765 | sccb_reg_write(gspca_dev, 0x0d, 0x41); | 1377 | static void setgain(struct gspca_dev *gspca_dev) |
766 | ov534_reg_write(gspca_dev, 0xe5, 0x02); | 1378 | { |
1379 | struct sd *sd = (struct sd *) gspca_dev; | ||
1380 | u8 val; | ||
1381 | |||
1382 | val = sd->gain; | ||
1383 | switch (val & 0x30) { | ||
1384 | case 0x00: | ||
1385 | val &= 0x0f; | ||
767 | break; | 1386 | break; |
768 | case 40: | 1387 | case 0x10: |
769 | sccb_reg_write(gspca_dev, 0x11, 0x02); | 1388 | val &= 0x0f; |
770 | sccb_reg_write(gspca_dev, 0x0d, 0xc1); | 1389 | val |= 0x30; |
771 | ov534_reg_write(gspca_dev, 0xe5, 0x04); | ||
772 | break; | 1390 | break; |
773 | /* case 30: */ | 1391 | case 0x20: |
774 | default: | 1392 | val &= 0x0f; |
775 | fr = 30; | 1393 | val |= 0x70; |
776 | sccb_reg_write(gspca_dev, 0x11, 0x04); | ||
777 | sccb_reg_write(gspca_dev, 0x0d, 0x81); | ||
778 | ov534_reg_write(gspca_dev, 0xe5, 0x02); | ||
779 | break; | 1394 | break; |
780 | case 15: | 1395 | default: |
781 | sccb_reg_write(gspca_dev, 0x11, 0x03); | 1396 | /* case 0x30: */ |
782 | sccb_reg_write(gspca_dev, 0x0d, 0x41); | 1397 | val &= 0x0f; |
783 | ov534_reg_write(gspca_dev, 0xe5, 0x04); | 1398 | val |= 0xf0; |
784 | break; | 1399 | break; |
785 | } | 1400 | } |
1401 | sccb_reg_write(gspca_dev, 0x00, val); | ||
1402 | } | ||
1403 | |||
1404 | static void setexposure_77(struct gspca_dev *gspca_dev) | ||
1405 | { | ||
1406 | struct sd *sd = (struct sd *) gspca_dev; | ||
1407 | u8 val; | ||
1408 | |||
1409 | val = sd->exposure; | ||
1410 | sccb_reg_write(gspca_dev, 0x08, val >> 7); | ||
1411 | sccb_reg_write(gspca_dev, 0x10, val << 1); | ||
1412 | } | ||
1413 | |||
1414 | static void setredblc(struct gspca_dev *gspca_dev) | ||
1415 | { | ||
1416 | struct sd *sd = (struct sd *) gspca_dev; | ||
1417 | |||
1418 | sccb_reg_write(gspca_dev, 0x43, sd->redblc); | ||
1419 | } | ||
1420 | |||
1421 | static void setblueblc(struct gspca_dev *gspca_dev) | ||
1422 | { | ||
1423 | struct sd *sd = (struct sd *) gspca_dev; | ||
1424 | |||
1425 | sccb_reg_write(gspca_dev, 0x42, sd->blueblc); | ||
1426 | } | ||
1427 | |||
1428 | static void sethue(struct gspca_dev *gspca_dev) | ||
1429 | { | ||
1430 | struct sd *sd = (struct sd *) gspca_dev; | ||
1431 | |||
1432 | sccb_reg_write(gspca_dev, 0x01, sd->hue); | ||
1433 | } | ||
1434 | |||
1435 | static void setautogain_77(struct gspca_dev *gspca_dev) | ||
1436 | { | ||
1437 | struct sd *sd = (struct sd *) gspca_dev; | ||
1438 | |||
1439 | if (sd->autogain) { | ||
1440 | sccb_reg_write(gspca_dev, 0x13, 0xf7); /* AGC,AEC,AWB ON */ | ||
1441 | sccb_reg_write(gspca_dev, 0x64, | ||
1442 | sccb_reg_read(gspca_dev, 0x64) | 0x03); | ||
1443 | } else { | ||
1444 | sccb_reg_write(gspca_dev, 0x13, 0xf0); /* AGC,AEC,AWB OFF */ | ||
1445 | sccb_reg_write(gspca_dev, 0x64, | ||
1446 | sccb_reg_read(gspca_dev, 0x64) & 0xfc); | ||
1447 | } | ||
1448 | } | ||
1449 | |||
1450 | static void setawb(struct gspca_dev *gspca_dev) | ||
1451 | { | ||
1452 | struct sd *sd = (struct sd *) gspca_dev; | ||
1453 | |||
1454 | if (sd->awb) | ||
1455 | sccb_reg_write(gspca_dev, 0x63, 0xe0); /* AWB on */ | ||
1456 | else | ||
1457 | sccb_reg_write(gspca_dev, 0x63, 0xaa); /* AWB off */ | ||
1458 | } | ||
1459 | |||
1460 | static void setsharpness_77(struct gspca_dev *gspca_dev) | ||
1461 | { | ||
1462 | struct sd *sd = (struct sd *) gspca_dev; | ||
1463 | u8 val; | ||
1464 | |||
1465 | val = sd->sharpness; | ||
1466 | sccb_reg_write(gspca_dev, 0x91, val); /* vga noise */ | ||
1467 | sccb_reg_write(gspca_dev, 0x8e, val); /* qvga noise */ | ||
1468 | } | ||
1469 | |||
1470 | static void sethflip(struct gspca_dev *gspca_dev) | ||
1471 | { | ||
1472 | struct sd *sd = (struct sd *) gspca_dev; | ||
1473 | |||
1474 | if (sd->hflip == 0) | ||
1475 | sccb_reg_write(gspca_dev, 0x0c, | ||
1476 | sccb_reg_read(gspca_dev, 0x0c) | 0x40); | ||
1477 | else | ||
1478 | sccb_reg_write(gspca_dev, 0x0c, | ||
1479 | sccb_reg_read(gspca_dev, 0x0c) & 0xbf); | ||
1480 | } | ||
1481 | |||
1482 | static void setvflip(struct gspca_dev *gspca_dev) | ||
1483 | { | ||
1484 | struct sd *sd = (struct sd *) gspca_dev; | ||
1485 | |||
1486 | if (sd->vflip == 0) | ||
1487 | sccb_reg_write(gspca_dev, 0x0c, | ||
1488 | sccb_reg_read(gspca_dev, 0x0c) | 0x80); | ||
1489 | else | ||
1490 | sccb_reg_write(gspca_dev, 0x0c, | ||
1491 | sccb_reg_read(gspca_dev, 0x0c) & 0x7f); | ||
1492 | } | ||
1493 | |||
1494 | /* ov965x specific controls */ | ||
1495 | static void setbrightness_96(struct gspca_dev *gspca_dev) | ||
1496 | { | ||
1497 | struct sd *sd = (struct sd *) gspca_dev; | ||
1498 | u8 val; | ||
1499 | |||
1500 | val = sd->brightness; | ||
1501 | if (val < 8) | ||
1502 | val = 15 - val; /* f .. 8 */ | ||
1503 | else | ||
1504 | val = val - 8; /* 0 .. 7 */ | ||
1505 | sccb_reg_write(gspca_dev, 0x55, /* brtn - brightness adjustment */ | ||
1506 | 0x0f | (val << 4)); | ||
1507 | } | ||
1508 | |||
1509 | static void setcontrast_96(struct gspca_dev *gspca_dev) | ||
1510 | { | ||
1511 | struct sd *sd = (struct sd *) gspca_dev; | ||
1512 | |||
1513 | sccb_reg_write(gspca_dev, 0x56, /* cnst1 - contrast 1 ctrl coeff */ | ||
1514 | sd->contrast << 4); | ||
1515 | } | ||
1516 | |||
1517 | static void setexposure_96(struct gspca_dev *gspca_dev) | ||
1518 | { | ||
1519 | struct sd *sd = (struct sd *) gspca_dev; | ||
1520 | u8 val; | ||
1521 | static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e}; | ||
1522 | |||
1523 | sccb_reg_write(gspca_dev, 0x10, /* aec[9:2] */ | ||
1524 | expo[sd->exposure]); | ||
1525 | val = sccb_reg_read(gspca_dev, 0x13); /* com8 */ | ||
1526 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1527 | sccb_reg_write(gspca_dev, 0x13, val); | ||
1528 | val = sccb_reg_read(gspca_dev, 0xa1); /* aech */ | ||
1529 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1530 | sccb_reg_write(gspca_dev, 0xa1, val & 0xe0); /* aec[15:10] = 0 */ | ||
1531 | } | ||
1532 | |||
1533 | static void setsharpness_96(struct gspca_dev *gspca_dev) | ||
1534 | { | ||
1535 | struct sd *sd = (struct sd *) gspca_dev; | ||
1536 | u8 val; | ||
1537 | |||
1538 | val = sd->sharpness; | ||
1539 | if (val < 0) { /* auto */ | ||
1540 | val = sccb_reg_read(gspca_dev, 0x42); /* com17 */ | ||
1541 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1542 | sccb_reg_write(gspca_dev, 0x42, val | 0x40); | ||
1543 | /* Edge enhancement strength auto adjust */ | ||
1544 | return; | ||
1545 | } | ||
1546 | if (val != 0) | ||
1547 | val = 1 << (val - 1); | ||
1548 | sccb_reg_write(gspca_dev, 0x3f, /* edge - edge enhance. factor */ | ||
1549 | val); | ||
1550 | val = sccb_reg_read(gspca_dev, 0x42); /* com17 */ | ||
1551 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1552 | sccb_reg_write(gspca_dev, 0x42, val & 0xbf); | ||
1553 | } | ||
1554 | |||
1555 | static void setautogain_96(struct gspca_dev *gspca_dev) | ||
1556 | { | ||
1557 | struct sd *sd = (struct sd *) gspca_dev; | ||
1558 | u8 val; | ||
1559 | |||
1560 | /*fixme: should adjust agc/awb/aec by different controls */ | ||
1561 | val = sd->autogain; | ||
1562 | val = sccb_reg_read(gspca_dev, 0x13); /* com8 */ | ||
1563 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1564 | if (sd->autogain) | ||
1565 | val |= 0x05; /* agc & aec */ | ||
1566 | else | ||
1567 | val &= 0xfa; | ||
1568 | sccb_reg_write(gspca_dev, 0x13, val); | ||
1569 | } | ||
1570 | |||
1571 | static void setsatur(struct gspca_dev *gspca_dev) | ||
1572 | { | ||
1573 | struct sd *sd = (struct sd *) gspca_dev; | ||
1574 | u8 val1, val2, val3; | ||
1575 | static const u8 matrix[5][2] = { | ||
1576 | {0x14, 0x38}, | ||
1577 | {0x1e, 0x54}, | ||
1578 | {0x28, 0x70}, | ||
1579 | {0x32, 0x8c}, | ||
1580 | {0x48, 0x90} | ||
1581 | }; | ||
1582 | |||
1583 | val1 = matrix[sd->satur][0]; | ||
1584 | val2 = matrix[sd->satur][1]; | ||
1585 | val3 = val1 + val2; | ||
1586 | sccb_reg_write(gspca_dev, 0x4f, val3); /* matrix coeff */ | ||
1587 | sccb_reg_write(gspca_dev, 0x50, val3); | ||
1588 | sccb_reg_write(gspca_dev, 0x51, 0x00); | ||
1589 | sccb_reg_write(gspca_dev, 0x52, val1); | ||
1590 | sccb_reg_write(gspca_dev, 0x53, val2); | ||
1591 | sccb_reg_write(gspca_dev, 0x54, val3); | ||
1592 | sccb_reg_write(gspca_dev, 0x58, 0x1a); /* mtxs - coeff signs */ | ||
1593 | val1 = sccb_reg_read(gspca_dev, 0x41); /* com16 */ | ||
1594 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1595 | sccb_reg_write(gspca_dev, 0x41, val1); | ||
1596 | } | ||
1597 | |||
1598 | static void setfreq(struct gspca_dev *gspca_dev) | ||
1599 | { | ||
1600 | struct sd *sd = (struct sd *) gspca_dev; | ||
1601 | u8 val; | ||
1602 | |||
1603 | val = sccb_reg_read(gspca_dev, 0x13); /* com8 */ | ||
1604 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1605 | if (sd->lightfreq == 0) { | ||
1606 | sccb_reg_write(gspca_dev, 0x13, val & 0xdf); | ||
1607 | return; | ||
1608 | } | ||
1609 | sccb_reg_write(gspca_dev, 0x13, val | 0x20); | ||
786 | 1610 | ||
787 | sd->frame_rate = fr; | 1611 | val = sccb_reg_read(gspca_dev, 0x42); /* com17 */ |
788 | PDEBUG(D_PROBE, "frame_rate: %d", fr); | 1612 | sccb_reg_write(gspca_dev, 0xff, 0x00); |
1613 | if (sd->lightfreq == 1) | ||
1614 | val |= 0x01; | ||
1615 | else | ||
1616 | val &= 0xfe; | ||
1617 | sccb_reg_write(gspca_dev, 0x42, val); | ||
789 | } | 1618 | } |
790 | 1619 | ||
791 | /* this function is called at probe time */ | 1620 | /* this function is called at probe time */ |
@@ -800,17 +1629,60 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
800 | cam = &gspca_dev->cam; | 1629 | cam = &gspca_dev->cam; |
801 | 1630 | ||
802 | if (sd->sensor == SENSOR_OV772X) { | 1631 | if (sd->sensor == SENSOR_OV772X) { |
803 | cam->cam_mode = vga_yuyv_mode; | 1632 | cam->cam_mode = ov772x_mode; |
804 | cam->nmodes = ARRAY_SIZE(vga_yuyv_mode); | 1633 | cam->nmodes = ARRAY_SIZE(ov772x_mode); |
805 | 1634 | ||
806 | cam->bulk = 1; | 1635 | cam->bulk = 1; |
807 | cam->bulk_size = 16384; | 1636 | cam->bulk_size = 16384; |
808 | cam->bulk_nurbs = 2; | 1637 | cam->bulk_nurbs = 2; |
809 | } else { /* ov965x */ | 1638 | } else { /* ov965x */ |
810 | cam->cam_mode = vga_jpeg_mode; | 1639 | cam->cam_mode = ov965x_mode; |
811 | cam->nmodes = ARRAY_SIZE(vga_jpeg_mode); | 1640 | cam->nmodes = ARRAY_SIZE(ov965x_mode); |
812 | } | 1641 | } |
813 | 1642 | ||
1643 | sd->frame_rate = 30; | ||
1644 | |||
1645 | if (sd->sensor == SENSOR_OV772X) { | ||
1646 | sd->brightness = BRIGHTNESS_77_DEF; | ||
1647 | sd->contrast = CONTRAST_77_DEF; | ||
1648 | sd->gain = GAIN_DEF; | ||
1649 | sd->exposure = EXPO_77_DEF; | ||
1650 | sd->redblc = RED_BALANCE_DEF; | ||
1651 | sd->blueblc = BLUE_BALANCE_DEF; | ||
1652 | sd->hue = HUE_DEF; | ||
1653 | #if AUTOGAIN_77_DEF != 0 | ||
1654 | sd->autogain = AUTOGAIN_77_DEF; | ||
1655 | #else | ||
1656 | gspca_dev->ctrl_inac |= (1 << AWB_77_IDX); | ||
1657 | #endif | ||
1658 | #if AWB_DEF != 0 | ||
1659 | sd->awb = AWB_DEF | ||
1660 | #endif | ||
1661 | #if SHARPNESS_77_DEF != 0 | ||
1662 | sd->sharpness = SHARPNESS_77_DEF; | ||
1663 | #endif | ||
1664 | #if HFLIP_DEF != 0 | ||
1665 | sd->hflip = HFLIP_DEF; | ||
1666 | #endif | ||
1667 | #if VFLIP_DEF != 0 | ||
1668 | sd->vflip = VFLIP_DEF; | ||
1669 | #endif | ||
1670 | } else { | ||
1671 | sd->brightness = BRIGHTNESS_96_DEF; | ||
1672 | sd->contrast = CONTRAST_96_DEF; | ||
1673 | #if AUTOGAIN_96_DEF != 0 | ||
1674 | sd->autogain = AUTOGAIN_96_DEF; | ||
1675 | gspca_dev->ctrl_inac |= (1 << EXPO_96_IDX); | ||
1676 | #endif | ||
1677 | #if EXPO_96_DEF != 0 | ||
1678 | sd->exposure = EXPO_96_DEF; | ||
1679 | #endif | ||
1680 | #if SHARPNESS_96_DEF != 0 | ||
1681 | sd->sharpness = SHARPNESS_96_DEF; | ||
1682 | #endif | ||
1683 | sd->satur = SATUR_DEF; | ||
1684 | sd->lightfreq = FREQ_DEF; | ||
1685 | } | ||
814 | return 0; | 1686 | return 0; |
815 | } | 1687 | } |
816 | 1688 | ||
@@ -847,14 +1719,14 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
847 | /* initialize */ | 1719 | /* initialize */ |
848 | switch (sd->sensor) { | 1720 | switch (sd->sensor) { |
849 | case SENSOR_OV772X: | 1721 | case SENSOR_OV772X: |
850 | reg_w_array(gspca_dev, bridge_init_ov722x, | 1722 | reg_w_array(gspca_dev, bridge_init_ov772x, |
851 | ARRAY_SIZE(bridge_init_ov722x)); | 1723 | ARRAY_SIZE(bridge_init_ov772x)); |
852 | ov534_set_led(gspca_dev, 1); | 1724 | ov534_set_led(gspca_dev, 1); |
853 | sccb_w_array(gspca_dev, sensor_init_ov722x, | 1725 | sccb_w_array(gspca_dev, sensor_init_ov772x, |
854 | ARRAY_SIZE(sensor_init_ov722x)); | 1726 | ARRAY_SIZE(sensor_init_ov772x)); |
855 | ov534_reg_write(gspca_dev, 0xe0, 0x09); | 1727 | ov534_reg_write(gspca_dev, 0xe0, 0x09); |
856 | ov534_set_led(gspca_dev, 0); | 1728 | ov534_set_led(gspca_dev, 0); |
857 | ov534_set_frame_rate(gspca_dev); | 1729 | set_frame_rate(gspca_dev); |
858 | break; | 1730 | break; |
859 | default: | 1731 | default: |
860 | /* case SENSOR_OV965X: */ | 1732 | /* case SENSOR_OV965X: */ |
@@ -875,60 +1747,115 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
875 | return 0; | 1747 | return 0; |
876 | } | 1748 | } |
877 | 1749 | ||
878 | static int sd_start(struct gspca_dev *gspca_dev) | 1750 | static int sd_start_ov772x(struct gspca_dev *gspca_dev) |
879 | { | 1751 | { |
880 | struct sd *sd = (struct sd *) gspca_dev; | ||
881 | int mode; | 1752 | int mode; |
882 | 1753 | ||
883 | switch (sd->sensor) { | 1754 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; |
884 | case SENSOR_OV772X: | 1755 | if (mode != 0) { /* 320x240 */ |
885 | ov534_set_led(gspca_dev, 1); | 1756 | reg_w_array(gspca_dev, bridge_start_ov772x_qvga, |
886 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | 1757 | ARRAY_SIZE(bridge_start_ov772x_qvga)); |
887 | break; | 1758 | sccb_w_array(gspca_dev, sensor_start_ov772x_qvga, |
888 | default: | 1759 | ARRAY_SIZE(sensor_start_ov772x_qvga)); |
889 | /* case SENSOR_OV965X: */ | 1760 | } else { /* 640x480 */ |
890 | 1761 | reg_w_array(gspca_dev, bridge_start_ov772x_vga, | |
891 | sccb_w_array(gspca_dev, sensor_start_ov965x, | 1762 | ARRAY_SIZE(bridge_start_ov772x_vga)); |
892 | ARRAY_SIZE(sensor_start_ov965x)); | 1763 | sccb_w_array(gspca_dev, sensor_start_ov772x_vga, |
893 | reg_w_array(gspca_dev, bridge_start_ov965x, | 1764 | ARRAY_SIZE(sensor_start_ov772x_vga)); |
894 | ARRAY_SIZE(bridge_start_ov965x)); | ||
895 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; | ||
896 | if (mode != 0) { /* 320x240 */ | ||
897 | reg_w_array(gspca_dev, bridge_start_ov965x_cif, | ||
898 | ARRAY_SIZE(bridge_start_ov965x_cif)); | ||
899 | sccb_w_array(gspca_dev, sensor_start_ov965x_cif, | ||
900 | ARRAY_SIZE(sensor_start_ov965x_cif)); | ||
901 | } else { /* 640x480 */ | ||
902 | reg_w_array(gspca_dev, bridge_start_ov965x_vga, | ||
903 | ARRAY_SIZE(bridge_start_ov965x_vga)); | ||
904 | sccb_w_array(gspca_dev, sensor_start_ov965x_vga, | ||
905 | ARRAY_SIZE(sensor_start_ov965x_vga)); | ||
906 | } | ||
907 | sccb_w_array(gspca_dev, sensor_start_ov965x_2, | ||
908 | ARRAY_SIZE(sensor_start_ov965x_2)); | ||
909 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
910 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
911 | ov534_set_led(gspca_dev, 1); | ||
912 | } | 1765 | } |
1766 | set_frame_rate(gspca_dev); | ||
1767 | |||
1768 | setautogain_77(gspca_dev); | ||
1769 | setawb(gspca_dev); | ||
1770 | setgain(gspca_dev); | ||
1771 | setredblc(gspca_dev); | ||
1772 | setblueblc(gspca_dev); | ||
1773 | sethue(gspca_dev); | ||
1774 | setexposure_77(gspca_dev); | ||
1775 | setbrightness_77(gspca_dev); | ||
1776 | setcontrast_77(gspca_dev); | ||
1777 | setsharpness_77(gspca_dev); | ||
1778 | setvflip(gspca_dev); | ||
1779 | sethflip(gspca_dev); | ||
1780 | |||
1781 | ov534_set_led(gspca_dev, 1); | ||
1782 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
913 | return 0; | 1783 | return 0; |
914 | } | 1784 | } |
915 | 1785 | ||
916 | static void sd_stopN(struct gspca_dev *gspca_dev) | 1786 | static int sd_start_ov965x(struct gspca_dev *gspca_dev) |
917 | { | 1787 | { |
918 | struct sd *sd = (struct sd *) gspca_dev; | 1788 | int mode; |
919 | 1789 | ||
920 | switch (sd->sensor) { | 1790 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; |
921 | case SENSOR_OV772X: | 1791 | switch (mode) { |
922 | ov534_reg_write(gspca_dev, 0xe0, 0x09); | ||
923 | ov534_set_led(gspca_dev, 0); | ||
924 | break; | ||
925 | default: | 1792 | default: |
926 | /* case SENSOR_OV965X: */ | 1793 | /* case 4: * 320x240 */ |
927 | ov534_reg_write(gspca_dev, 0xe0, 0x01); | 1794 | sccb_w_array(gspca_dev, sensor_start_ov965x_1_vga, |
928 | ov534_set_led(gspca_dev, 0); | 1795 | ARRAY_SIZE(sensor_start_ov965x_1_vga)); |
929 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | 1796 | reg_w_array(gspca_dev, bridge_start_ov965x_qvga, |
1797 | ARRAY_SIZE(bridge_start_ov965x_qvga)); | ||
1798 | sccb_w_array(gspca_dev, sensor_start_ov965x_2_qvga, | ||
1799 | ARRAY_SIZE(sensor_start_ov965x_2_qvga)); | ||
1800 | break; | ||
1801 | case 3: /* 640x480 */ | ||
1802 | sccb_w_array(gspca_dev, sensor_start_ov965x_1_vga, | ||
1803 | ARRAY_SIZE(sensor_start_ov965x_1_vga)); | ||
1804 | reg_w_array(gspca_dev, bridge_start_ov965x_vga, | ||
1805 | ARRAY_SIZE(bridge_start_ov965x_vga)); | ||
1806 | sccb_w_array(gspca_dev, sensor_start_ov965x_2_vga, | ||
1807 | ARRAY_SIZE(sensor_start_ov965x_2_vga)); | ||
1808 | break; | ||
1809 | case 2: /* 800x600 */ | ||
1810 | sccb_w_array(gspca_dev, sensor_start_ov965x_1_svga, | ||
1811 | ARRAY_SIZE(sensor_start_ov965x_1_svga)); | ||
1812 | reg_w_array(gspca_dev, bridge_start_ov965x_svga, | ||
1813 | ARRAY_SIZE(bridge_start_ov965x_svga)); | ||
1814 | sccb_w_array(gspca_dev, sensor_start_ov965x_2_svga, | ||
1815 | ARRAY_SIZE(sensor_start_ov965x_2_svga)); | ||
1816 | break; | ||
1817 | case 1: /* 1024x768 */ | ||
1818 | sccb_w_array(gspca_dev, sensor_start_ov965x_1_xga, | ||
1819 | ARRAY_SIZE(sensor_start_ov965x_1_xga)); | ||
1820 | reg_w_array(gspca_dev, bridge_start_ov965x_xga, | ||
1821 | ARRAY_SIZE(bridge_start_ov965x_xga)); | ||
1822 | sccb_w_array(gspca_dev, sensor_start_ov965x_2_svga, | ||
1823 | ARRAY_SIZE(sensor_start_ov965x_2_svga)); | ||
1824 | break; | ||
1825 | case 0: /* 1280x1024 */ | ||
1826 | sccb_w_array(gspca_dev, sensor_start_ov965x_1_sxga, | ||
1827 | ARRAY_SIZE(sensor_start_ov965x_1_sxga)); | ||
1828 | reg_w_array(gspca_dev, bridge_start_ov965x_sxga, | ||
1829 | ARRAY_SIZE(bridge_start_ov965x_sxga)); | ||
1830 | sccb_w_array(gspca_dev, sensor_start_ov965x_2_sxga, | ||
1831 | ARRAY_SIZE(sensor_start_ov965x_2_sxga)); | ||
930 | break; | 1832 | break; |
931 | } | 1833 | } |
1834 | setfreq(gspca_dev); | ||
1835 | setautogain_96(gspca_dev); | ||
1836 | setbrightness_96(gspca_dev); | ||
1837 | setcontrast_96(gspca_dev); | ||
1838 | setexposure_96(gspca_dev); | ||
1839 | setsharpness_96(gspca_dev); | ||
1840 | setsatur(gspca_dev); | ||
1841 | |||
1842 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
1843 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
1844 | ov534_set_led(gspca_dev, 1); | ||
1845 | return 0; | ||
1846 | } | ||
1847 | |||
1848 | static void sd_stopN_ov772x(struct gspca_dev *gspca_dev) | ||
1849 | { | ||
1850 | ov534_reg_write(gspca_dev, 0xe0, 0x09); | ||
1851 | ov534_set_led(gspca_dev, 0); | ||
1852 | } | ||
1853 | |||
1854 | static void sd_stopN_ov965x(struct gspca_dev *gspca_dev) | ||
1855 | { | ||
1856 | ov534_reg_write(gspca_dev, 0xe0, 0x01); | ||
1857 | ov534_set_led(gspca_dev, 0); | ||
1858 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
932 | } | 1859 | } |
933 | 1860 | ||
934 | /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ | 1861 | /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ |
@@ -941,8 +1868,8 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
941 | #define UVC_STREAM_EOF (1 << 1) | 1868 | #define UVC_STREAM_EOF (1 << 1) |
942 | #define UVC_STREAM_FID (1 << 0) | 1869 | #define UVC_STREAM_FID (1 << 0) |
943 | 1870 | ||
944 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, | 1871 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
945 | __u8 *data, int len) | 1872 | u8 *data, int len) |
946 | { | 1873 | { |
947 | struct sd *sd = (struct sd *) gspca_dev; | 1874 | struct sd *sd = (struct sd *) gspca_dev; |
948 | __u32 this_pts; | 1875 | __u32 this_pts; |
@@ -983,32 +1910,30 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, | |||
983 | /* If PTS or FID has changed, start a new frame. */ | 1910 | /* If PTS or FID has changed, start a new frame. */ |
984 | if (this_pts != sd->last_pts || this_fid != sd->last_fid) { | 1911 | if (this_pts != sd->last_pts || this_fid != sd->last_fid) { |
985 | if (gspca_dev->last_packet_type == INTER_PACKET) | 1912 | if (gspca_dev->last_packet_type == INTER_PACKET) |
986 | frame = gspca_frame_add(gspca_dev, | 1913 | gspca_frame_add(gspca_dev, LAST_PACKET, |
987 | LAST_PACKET, frame, | 1914 | NULL, 0); |
988 | NULL, 0); | ||
989 | sd->last_pts = this_pts; | 1915 | sd->last_pts = this_pts; |
990 | sd->last_fid = this_fid; | 1916 | sd->last_fid = this_fid; |
991 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | 1917 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
992 | data + 12, len - 12); | 1918 | data + 12, len - 12); |
993 | /* If this packet is marked as EOF, end the frame */ | 1919 | /* If this packet is marked as EOF, end the frame */ |
994 | } else if (data[1] & UVC_STREAM_EOF) { | 1920 | } else if (data[1] & UVC_STREAM_EOF) { |
995 | sd->last_pts = 0; | 1921 | sd->last_pts = 0; |
996 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | 1922 | gspca_frame_add(gspca_dev, LAST_PACKET, |
997 | data + 12, len - 12); | 1923 | data + 12, len - 12); |
998 | } else { | 1924 | } else { |
999 | 1925 | ||
1000 | /* Add the data from this payload */ | 1926 | /* Add the data from this payload */ |
1001 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | 1927 | gspca_frame_add(gspca_dev, INTER_PACKET, |
1002 | data + 12, len - 12); | 1928 | data + 12, len - 12); |
1003 | } | 1929 | } |
1004 | 1930 | ||
1005 | |||
1006 | /* Done this payload */ | 1931 | /* Done this payload */ |
1007 | goto scan_next; | 1932 | goto scan_next; |
1008 | 1933 | ||
1009 | discard: | 1934 | discard: |
1010 | /* Discard data until a new frame starts. */ | 1935 | /* Discard data until a new frame starts. */ |
1011 | gspca_frame_add(gspca_dev, DISCARD_PACKET, frame, NULL, 0); | 1936 | gspca_dev->last_packet_type = DISCARD_PACKET; |
1012 | 1937 | ||
1013 | scan_next: | 1938 | scan_next: |
1014 | remaining_len -= len; | 1939 | remaining_len -= len; |
@@ -1016,6 +1941,291 @@ scan_next: | |||
1016 | } while (remaining_len > 0); | 1941 | } while (remaining_len > 0); |
1017 | } | 1942 | } |
1018 | 1943 | ||
1944 | /* controls */ | ||
1945 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) | ||
1946 | { | ||
1947 | struct sd *sd = (struct sd *) gspca_dev; | ||
1948 | |||
1949 | sd->gain = val; | ||
1950 | if (gspca_dev->streaming) | ||
1951 | setgain(gspca_dev); | ||
1952 | return 0; | ||
1953 | } | ||
1954 | |||
1955 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) | ||
1956 | { | ||
1957 | struct sd *sd = (struct sd *) gspca_dev; | ||
1958 | |||
1959 | *val = sd->gain; | ||
1960 | return 0; | ||
1961 | } | ||
1962 | |||
1963 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) | ||
1964 | { | ||
1965 | struct sd *sd = (struct sd *) gspca_dev; | ||
1966 | |||
1967 | sd->exposure = val; | ||
1968 | if (gspca_dev->streaming) { | ||
1969 | if (sd->sensor == SENSOR_OV772X) | ||
1970 | setexposure_77(gspca_dev); | ||
1971 | else | ||
1972 | setexposure_96(gspca_dev); | ||
1973 | } | ||
1974 | return 0; | ||
1975 | } | ||
1976 | |||
1977 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) | ||
1978 | { | ||
1979 | struct sd *sd = (struct sd *) gspca_dev; | ||
1980 | |||
1981 | *val = sd->exposure; | ||
1982 | return 0; | ||
1983 | } | ||
1984 | |||
1985 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | ||
1986 | { | ||
1987 | struct sd *sd = (struct sd *) gspca_dev; | ||
1988 | |||
1989 | sd->brightness = val; | ||
1990 | if (gspca_dev->streaming) { | ||
1991 | if (sd->sensor == SENSOR_OV772X) | ||
1992 | setbrightness_77(gspca_dev); | ||
1993 | else | ||
1994 | setbrightness_96(gspca_dev); | ||
1995 | } | ||
1996 | return 0; | ||
1997 | } | ||
1998 | |||
1999 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
2000 | { | ||
2001 | struct sd *sd = (struct sd *) gspca_dev; | ||
2002 | |||
2003 | *val = sd->brightness; | ||
2004 | return 0; | ||
2005 | } | ||
2006 | |||
2007 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | ||
2008 | { | ||
2009 | struct sd *sd = (struct sd *) gspca_dev; | ||
2010 | |||
2011 | sd->contrast = val; | ||
2012 | if (gspca_dev->streaming) { | ||
2013 | if (sd->sensor == SENSOR_OV772X) | ||
2014 | setcontrast_77(gspca_dev); | ||
2015 | else | ||
2016 | setcontrast_96(gspca_dev); | ||
2017 | } | ||
2018 | return 0; | ||
2019 | } | ||
2020 | |||
2021 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | ||
2022 | { | ||
2023 | struct sd *sd = (struct sd *) gspca_dev; | ||
2024 | |||
2025 | *val = sd->contrast; | ||
2026 | return 0; | ||
2027 | } | ||
2028 | |||
2029 | static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val) | ||
2030 | { | ||
2031 | struct sd *sd = (struct sd *) gspca_dev; | ||
2032 | |||
2033 | sd->satur = val; | ||
2034 | if (gspca_dev->streaming) | ||
2035 | setsatur(gspca_dev); | ||
2036 | return 0; | ||
2037 | } | ||
2038 | |||
2039 | static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val) | ||
2040 | { | ||
2041 | struct sd *sd = (struct sd *) gspca_dev; | ||
2042 | |||
2043 | *val = sd->satur; | ||
2044 | return 0; | ||
2045 | } | ||
2046 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) | ||
2047 | { | ||
2048 | struct sd *sd = (struct sd *) gspca_dev; | ||
2049 | |||
2050 | sd->lightfreq = val; | ||
2051 | if (gspca_dev->streaming) | ||
2052 | setfreq(gspca_dev); | ||
2053 | return 0; | ||
2054 | } | ||
2055 | |||
2056 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) | ||
2057 | { | ||
2058 | struct sd *sd = (struct sd *) gspca_dev; | ||
2059 | |||
2060 | *val = sd->lightfreq; | ||
2061 | return 0; | ||
2062 | } | ||
2063 | |||
2064 | static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val) | ||
2065 | { | ||
2066 | struct sd *sd = (struct sd *) gspca_dev; | ||
2067 | |||
2068 | sd->redblc = val; | ||
2069 | if (gspca_dev->streaming) | ||
2070 | setredblc(gspca_dev); | ||
2071 | return 0; | ||
2072 | } | ||
2073 | |||
2074 | static int sd_getredblc(struct gspca_dev *gspca_dev, __s32 *val) | ||
2075 | { | ||
2076 | struct sd *sd = (struct sd *) gspca_dev; | ||
2077 | |||
2078 | *val = sd->redblc; | ||
2079 | return 0; | ||
2080 | } | ||
2081 | |||
2082 | static int sd_setblueblc(struct gspca_dev *gspca_dev, __s32 val) | ||
2083 | { | ||
2084 | struct sd *sd = (struct sd *) gspca_dev; | ||
2085 | |||
2086 | sd->blueblc = val; | ||
2087 | if (gspca_dev->streaming) | ||
2088 | setblueblc(gspca_dev); | ||
2089 | return 0; | ||
2090 | } | ||
2091 | |||
2092 | static int sd_getblueblc(struct gspca_dev *gspca_dev, __s32 *val) | ||
2093 | { | ||
2094 | struct sd *sd = (struct sd *) gspca_dev; | ||
2095 | |||
2096 | *val = sd->blueblc; | ||
2097 | return 0; | ||
2098 | } | ||
2099 | |||
2100 | static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val) | ||
2101 | { | ||
2102 | struct sd *sd = (struct sd *) gspca_dev; | ||
2103 | |||
2104 | sd->hue = val; | ||
2105 | if (gspca_dev->streaming) | ||
2106 | sethue(gspca_dev); | ||
2107 | return 0; | ||
2108 | } | ||
2109 | |||
2110 | static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val) | ||
2111 | { | ||
2112 | struct sd *sd = (struct sd *) gspca_dev; | ||
2113 | |||
2114 | *val = sd->hue; | ||
2115 | return 0; | ||
2116 | } | ||
2117 | |||
2118 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | ||
2119 | { | ||
2120 | struct sd *sd = (struct sd *) gspca_dev; | ||
2121 | |||
2122 | sd->autogain = val; | ||
2123 | |||
2124 | if (gspca_dev->streaming) { | ||
2125 | if (sd->sensor == SENSOR_OV772X) { | ||
2126 | |||
2127 | /* the auto white balance control works only | ||
2128 | * when auto gain is set */ | ||
2129 | if (val) | ||
2130 | gspca_dev->ctrl_inac &= ~(1 << AWB_77_IDX); | ||
2131 | else | ||
2132 | gspca_dev->ctrl_inac |= (1 << AWB_77_IDX); | ||
2133 | setautogain_77(gspca_dev); | ||
2134 | } else { | ||
2135 | if (val) | ||
2136 | gspca_dev->ctrl_inac |= (1 << EXPO_96_IDX); | ||
2137 | else | ||
2138 | gspca_dev->ctrl_inac &= ~(1 << EXPO_96_IDX); | ||
2139 | setautogain_96(gspca_dev); | ||
2140 | } | ||
2141 | } | ||
2142 | return 0; | ||
2143 | } | ||
2144 | |||
2145 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | ||
2146 | { | ||
2147 | struct sd *sd = (struct sd *) gspca_dev; | ||
2148 | |||
2149 | *val = sd->autogain; | ||
2150 | return 0; | ||
2151 | } | ||
2152 | |||
2153 | static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val) | ||
2154 | { | ||
2155 | struct sd *sd = (struct sd *) gspca_dev; | ||
2156 | |||
2157 | sd->awb = val; | ||
2158 | if (gspca_dev->streaming) | ||
2159 | setawb(gspca_dev); | ||
2160 | return 0; | ||
2161 | } | ||
2162 | |||
2163 | static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val) | ||
2164 | { | ||
2165 | struct sd *sd = (struct sd *) gspca_dev; | ||
2166 | |||
2167 | *val = sd->awb; | ||
2168 | return 0; | ||
2169 | } | ||
2170 | |||
2171 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) | ||
2172 | { | ||
2173 | struct sd *sd = (struct sd *) gspca_dev; | ||
2174 | |||
2175 | sd->sharpness = val; | ||
2176 | if (gspca_dev->streaming) { | ||
2177 | if (sd->sensor == SENSOR_OV772X) | ||
2178 | setsharpness_77(gspca_dev); | ||
2179 | else | ||
2180 | setsharpness_96(gspca_dev); | ||
2181 | } | ||
2182 | return 0; | ||
2183 | } | ||
2184 | |||
2185 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val) | ||
2186 | { | ||
2187 | struct sd *sd = (struct sd *) gspca_dev; | ||
2188 | |||
2189 | *val = sd->sharpness; | ||
2190 | return 0; | ||
2191 | } | ||
2192 | |||
2193 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) | ||
2194 | { | ||
2195 | struct sd *sd = (struct sd *) gspca_dev; | ||
2196 | |||
2197 | sd->hflip = val; | ||
2198 | if (gspca_dev->streaming) | ||
2199 | sethflip(gspca_dev); | ||
2200 | return 0; | ||
2201 | } | ||
2202 | |||
2203 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
2204 | { | ||
2205 | struct sd *sd = (struct sd *) gspca_dev; | ||
2206 | |||
2207 | *val = sd->hflip; | ||
2208 | return 0; | ||
2209 | } | ||
2210 | |||
2211 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) | ||
2212 | { | ||
2213 | struct sd *sd = (struct sd *) gspca_dev; | ||
2214 | |||
2215 | sd->vflip = val; | ||
2216 | if (gspca_dev->streaming) | ||
2217 | setvflip(gspca_dev); | ||
2218 | return 0; | ||
2219 | } | ||
2220 | |||
2221 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
2222 | { | ||
2223 | struct sd *sd = (struct sd *) gspca_dev; | ||
2224 | |||
2225 | *val = sd->vflip; | ||
2226 | return 0; | ||
2227 | } | ||
2228 | |||
1019 | /* get stream parameters (framerate) */ | 2229 | /* get stream parameters (framerate) */ |
1020 | static int sd_get_streamparm(struct gspca_dev *gspca_dev, | 2230 | static int sd_get_streamparm(struct gspca_dev *gspca_dev, |
1021 | struct v4l2_streamparm *parm) | 2231 | struct v4l2_streamparm *parm) |
@@ -1047,7 +2257,8 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev, | |||
1047 | 2257 | ||
1048 | /* Set requested framerate */ | 2258 | /* Set requested framerate */ |
1049 | sd->frame_rate = tpf->denominator / tpf->numerator; | 2259 | sd->frame_rate = tpf->denominator / tpf->numerator; |
1050 | ov534_set_frame_rate(gspca_dev); | 2260 | if (gspca_dev->streaming && sd->sensor == SENSOR_OV772X) |
2261 | set_frame_rate(gspca_dev); | ||
1051 | 2262 | ||
1052 | /* Return the actual framerate */ | 2263 | /* Return the actual framerate */ |
1053 | tpf->numerator = 1; | 2264 | tpf->numerator = 1; |
@@ -1056,20 +2267,53 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev, | |||
1056 | return 0; | 2267 | return 0; |
1057 | } | 2268 | } |
1058 | 2269 | ||
2270 | static int sd_querymenu(struct gspca_dev *gspca_dev, | ||
2271 | struct v4l2_querymenu *menu) | ||
2272 | { | ||
2273 | switch (menu->id) { | ||
2274 | case V4L2_CID_POWER_LINE_FREQUENCY: | ||
2275 | switch (menu->index) { | ||
2276 | case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ | ||
2277 | strcpy((char *) menu->name, "NoFliker"); | ||
2278 | return 0; | ||
2279 | case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ | ||
2280 | strcpy((char *) menu->name, "50 Hz"); | ||
2281 | return 0; | ||
2282 | case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ | ||
2283 | strcpy((char *) menu->name, "60 Hz"); | ||
2284 | return 0; | ||
2285 | } | ||
2286 | break; | ||
2287 | } | ||
2288 | return -EINVAL; | ||
2289 | } | ||
2290 | |||
1059 | /* sub-driver description */ | 2291 | /* sub-driver description */ |
1060 | static const struct sd_desc sd_desc = { | 2292 | static const struct sd_desc sd_desc_ov772x = { |
1061 | .name = MODULE_NAME, | 2293 | .name = MODULE_NAME, |
1062 | .ctrls = sd_ctrls, | 2294 | .ctrls = sd_ctrls_ov772x, |
1063 | .nctrls = ARRAY_SIZE(sd_ctrls), | 2295 | .nctrls = ARRAY_SIZE(sd_ctrls_ov772x), |
1064 | .config = sd_config, | 2296 | .config = sd_config, |
1065 | .init = sd_init, | 2297 | .init = sd_init, |
1066 | .start = sd_start, | 2298 | .start = sd_start_ov772x, |
1067 | .stopN = sd_stopN, | 2299 | .stopN = sd_stopN_ov772x, |
1068 | .pkt_scan = sd_pkt_scan, | 2300 | .pkt_scan = sd_pkt_scan, |
1069 | .get_streamparm = sd_get_streamparm, | 2301 | .get_streamparm = sd_get_streamparm, |
1070 | .set_streamparm = sd_set_streamparm, | 2302 | .set_streamparm = sd_set_streamparm, |
1071 | }; | 2303 | }; |
1072 | 2304 | ||
2305 | static const struct sd_desc sd_desc_ov965x = { | ||
2306 | .name = MODULE_NAME, | ||
2307 | .ctrls = sd_ctrls_ov965x, | ||
2308 | .nctrls = ARRAY_SIZE(sd_ctrls_ov965x), | ||
2309 | .config = sd_config, | ||
2310 | .init = sd_init, | ||
2311 | .start = sd_start_ov965x, | ||
2312 | .stopN = sd_stopN_ov965x, | ||
2313 | .pkt_scan = sd_pkt_scan, | ||
2314 | .querymenu = sd_querymenu, | ||
2315 | }; | ||
2316 | |||
1073 | /* -- module initialisation -- */ | 2317 | /* -- module initialisation -- */ |
1074 | static const __devinitdata struct usb_device_id device_table[] = { | 2318 | static const __devinitdata struct usb_device_id device_table[] = { |
1075 | {USB_DEVICE(0x06f8, 0x3003), .driver_info = SENSOR_OV965X}, | 2319 | {USB_DEVICE(0x06f8, 0x3003), .driver_info = SENSOR_OV965X}, |
@@ -1082,8 +2326,12 @@ MODULE_DEVICE_TABLE(usb, device_table); | |||
1082 | /* -- device connect -- */ | 2326 | /* -- device connect -- */ |
1083 | static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) | 2327 | static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) |
1084 | { | 2328 | { |
1085 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | 2329 | return gspca_dev_probe(intf, id, |
1086 | THIS_MODULE); | 2330 | id->driver_info == SENSOR_OV772X |
2331 | ? &sd_desc_ov772x | ||
2332 | : &sd_desc_ov965x, | ||
2333 | sizeof(struct sd), | ||
2334 | THIS_MODULE); | ||
1087 | } | 2335 | } |
1088 | 2336 | ||
1089 | static struct usb_driver sd_driver = { | 2337 | static struct usb_driver sd_driver = { |
@@ -1101,6 +2349,7 @@ static struct usb_driver sd_driver = { | |||
1101 | static int __init sd_mod_init(void) | 2349 | static int __init sd_mod_init(void) |
1102 | { | 2350 | { |
1103 | int ret; | 2351 | int ret; |
2352 | |||
1104 | ret = usb_register(&sd_driver); | 2353 | ret = usb_register(&sd_driver); |
1105 | if (ret < 0) | 2354 | if (ret < 0) |
1106 | return ret; | 2355 | return ret; |
diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index 96659433d248..4706a823add0 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c | |||
@@ -337,14 +337,13 @@ static void pac207_do_auto_gain(struct gspca_dev *gspca_dev) | |||
337 | } | 337 | } |
338 | 338 | ||
339 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 339 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
340 | struct gspca_frame *frame, | 340 | u8 *data, |
341 | __u8 *data, | ||
342 | int len) | 341 | int len) |
343 | { | 342 | { |
344 | struct sd *sd = (struct sd *) gspca_dev; | 343 | struct sd *sd = (struct sd *) gspca_dev; |
345 | unsigned char *sof; | 344 | unsigned char *sof; |
346 | 345 | ||
347 | sof = pac_find_sof(gspca_dev, data, len); | 346 | sof = pac_find_sof(&sd->sof_read, data, len); |
348 | if (sof) { | 347 | if (sof) { |
349 | int n; | 348 | int n; |
350 | 349 | ||
@@ -354,10 +353,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
354 | n -= sizeof pac_sof_marker; | 353 | n -= sizeof pac_sof_marker; |
355 | else | 354 | else |
356 | n = 0; | 355 | n = 0; |
357 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | 356 | gspca_frame_add(gspca_dev, LAST_PACKET, |
358 | data, n); | 357 | data, n); |
359 | sd->header_read = 0; | 358 | sd->header_read = 0; |
360 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0); | 359 | gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); |
361 | len -= sof - data; | 360 | len -= sof - data; |
362 | data = sof; | 361 | data = sof; |
363 | } | 362 | } |
@@ -381,7 +380,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
381 | sd->header_read = 11; | 380 | sd->header_read = 11; |
382 | } | 381 | } |
383 | 382 | ||
384 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | 383 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
385 | } | 384 | } |
386 | 385 | ||
387 | static void setbrightness(struct gspca_dev *gspca_dev) | 386 | static void setbrightness(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c new file mode 100644 index 000000000000..74acceea8094 --- /dev/null +++ b/drivers/media/video/gspca/pac7302.c | |||
@@ -0,0 +1,1272 @@ | |||
1 | /* | ||
2 | * Pixart PAC7302 library | ||
3 | * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li | ||
4 | * | ||
5 | * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> | ||
6 | * | ||
7 | * Separated from Pixart PAC7311 library by Márton Németh <nm127@freemail.hu> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | */ | ||
23 | |||
24 | /* Some documentation about various registers as determined by trial and error. | ||
25 | When the register addresses differ between the 7202 and the 7311 the 2 | ||
26 | different addresses are written as 7302addr/7311addr, when one of the 2 | ||
27 | addresses is a - sign that register description is not valid for the | ||
28 | matching IC. | ||
29 | |||
30 | Register page 1: | ||
31 | |||
32 | Address Description | ||
33 | -/0x08 Unknown compressor related, must always be 8 except when not | ||
34 | in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 ! | ||
35 | -/0x1b Auto white balance related, bit 0 is AWB enable (inverted) | ||
36 | bits 345 seem to toggle per color gains on/off (inverted) | ||
37 | 0x78 Global control, bit 6 controls the LED (inverted) | ||
38 | -/0x80 JPEG compression ratio ? Best not touched | ||
39 | |||
40 | Register page 3/4: | ||
41 | |||
42 | Address Description | ||
43 | 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on | ||
44 | the 7302, so one of 3, 6, 9, ..., except when between 6 and 12? | ||
45 | -/0x0f Master gain 1-245, low value = high gain | ||
46 | 0x10/- Master gain 0-31 | ||
47 | -/0x10 Another gain 0-15, limited influence (1-2x gain I guess) | ||
48 | 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused | ||
49 | -/0x27 Seems to toggle various gains on / off, Setting bit 7 seems to | ||
50 | completely disable the analog amplification block. Set to 0x68 | ||
51 | for max gain, 0x14 for minimal gain. | ||
52 | |||
53 | The registers are accessed in the following functions: | ||
54 | |||
55 | Page | Register | Function | ||
56 | -----+------------+--------------------------------------------------- | ||
57 | 0 | 0x0f..0x20 | setcolors() | ||
58 | 0 | 0xa2..0xab | setbrightcont() | ||
59 | 0 | 0xc5 | setredbalance() | ||
60 | 0 | 0xc6 | setwhitebalance() | ||
61 | 0 | 0xc7 | setbluebalance() | ||
62 | 0 | 0xdc | setbrightcont(), setcolors() | ||
63 | 3 | 0x02 | setexposure() | ||
64 | 3 | 0x10 | setgain() | ||
65 | 3 | 0x11 | setcolors(), setgain(), setexposure(), sethvflip() | ||
66 | 3 | 0x21 | sethvflip() | ||
67 | */ | ||
68 | |||
69 | #define MODULE_NAME "pac7302" | ||
70 | |||
71 | #include <media/v4l2-chip-ident.h> | ||
72 | #include "gspca.h" | ||
73 | |||
74 | MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); | ||
75 | MODULE_DESCRIPTION("Pixart PAC7302"); | ||
76 | MODULE_LICENSE("GPL"); | ||
77 | |||
78 | /* specific webcam descriptor for pac7302 */ | ||
79 | struct sd { | ||
80 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
81 | |||
82 | unsigned char brightness; | ||
83 | unsigned char contrast; | ||
84 | unsigned char colors; | ||
85 | unsigned char white_balance; | ||
86 | unsigned char red_balance; | ||
87 | unsigned char blue_balance; | ||
88 | unsigned char gain; | ||
89 | unsigned char exposure; | ||
90 | unsigned char autogain; | ||
91 | __u8 hflip; | ||
92 | __u8 vflip; | ||
93 | |||
94 | u8 sof_read; | ||
95 | u8 autogain_ignore_frames; | ||
96 | |||
97 | atomic_t avg_lum; | ||
98 | }; | ||
99 | |||
100 | /* V4L2 controls supported by the driver */ | ||
101 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
102 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
103 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
104 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
105 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | ||
106 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | ||
107 | static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val); | ||
108 | static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val); | ||
109 | static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val); | ||
110 | static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val); | ||
111 | static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val); | ||
112 | static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val); | ||
113 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
114 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | ||
115 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); | ||
116 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
117 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); | ||
118 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
119 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | ||
120 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | ||
121 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | ||
122 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
123 | |||
124 | static struct ctrl sd_ctrls[] = { | ||
125 | /* This control is pac7302 only */ | ||
126 | { | ||
127 | { | ||
128 | .id = V4L2_CID_BRIGHTNESS, | ||
129 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
130 | .name = "Brightness", | ||
131 | .minimum = 0, | ||
132 | #define BRIGHTNESS_MAX 0x20 | ||
133 | .maximum = BRIGHTNESS_MAX, | ||
134 | .step = 1, | ||
135 | #define BRIGHTNESS_DEF 0x10 | ||
136 | .default_value = BRIGHTNESS_DEF, | ||
137 | }, | ||
138 | .set = sd_setbrightness, | ||
139 | .get = sd_getbrightness, | ||
140 | }, | ||
141 | /* This control is for both the 7302 and the 7311 */ | ||
142 | { | ||
143 | { | ||
144 | .id = V4L2_CID_CONTRAST, | ||
145 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
146 | .name = "Contrast", | ||
147 | .minimum = 0, | ||
148 | #define CONTRAST_MAX 255 | ||
149 | .maximum = CONTRAST_MAX, | ||
150 | .step = 1, | ||
151 | #define CONTRAST_DEF 127 | ||
152 | .default_value = CONTRAST_DEF, | ||
153 | }, | ||
154 | .set = sd_setcontrast, | ||
155 | .get = sd_getcontrast, | ||
156 | }, | ||
157 | /* This control is pac7302 only */ | ||
158 | { | ||
159 | { | ||
160 | .id = V4L2_CID_SATURATION, | ||
161 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
162 | .name = "Saturation", | ||
163 | .minimum = 0, | ||
164 | #define COLOR_MAX 255 | ||
165 | .maximum = COLOR_MAX, | ||
166 | .step = 1, | ||
167 | #define COLOR_DEF 127 | ||
168 | .default_value = COLOR_DEF, | ||
169 | }, | ||
170 | .set = sd_setcolors, | ||
171 | .get = sd_getcolors, | ||
172 | }, | ||
173 | { | ||
174 | { | ||
175 | .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE, | ||
176 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
177 | .name = "White Balance", | ||
178 | .minimum = 0, | ||
179 | .maximum = 255, | ||
180 | .step = 1, | ||
181 | #define WHITEBALANCE_DEF 4 | ||
182 | .default_value = WHITEBALANCE_DEF, | ||
183 | }, | ||
184 | .set = sd_setwhitebalance, | ||
185 | .get = sd_getwhitebalance, | ||
186 | }, | ||
187 | { | ||
188 | { | ||
189 | .id = V4L2_CID_RED_BALANCE, | ||
190 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
191 | .name = "Red", | ||
192 | .minimum = 0, | ||
193 | .maximum = 3, | ||
194 | .step = 1, | ||
195 | #define REDBALANCE_DEF 1 | ||
196 | .default_value = REDBALANCE_DEF, | ||
197 | }, | ||
198 | .set = sd_setredbalance, | ||
199 | .get = sd_getredbalance, | ||
200 | }, | ||
201 | { | ||
202 | { | ||
203 | .id = V4L2_CID_BLUE_BALANCE, | ||
204 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
205 | .name = "Blue", | ||
206 | .minimum = 0, | ||
207 | .maximum = 3, | ||
208 | .step = 1, | ||
209 | #define BLUEBALANCE_DEF 1 | ||
210 | .default_value = BLUEBALANCE_DEF, | ||
211 | }, | ||
212 | .set = sd_setbluebalance, | ||
213 | .get = sd_getbluebalance, | ||
214 | }, | ||
215 | /* All controls below are for both the 7302 and the 7311 */ | ||
216 | { | ||
217 | { | ||
218 | .id = V4L2_CID_GAIN, | ||
219 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
220 | .name = "Gain", | ||
221 | .minimum = 0, | ||
222 | #define GAIN_MAX 255 | ||
223 | .maximum = GAIN_MAX, | ||
224 | .step = 1, | ||
225 | #define GAIN_DEF 127 | ||
226 | #define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */ | ||
227 | .default_value = GAIN_DEF, | ||
228 | }, | ||
229 | .set = sd_setgain, | ||
230 | .get = sd_getgain, | ||
231 | }, | ||
232 | { | ||
233 | { | ||
234 | .id = V4L2_CID_EXPOSURE, | ||
235 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
236 | .name = "Exposure", | ||
237 | .minimum = 0, | ||
238 | #define EXPOSURE_MAX 255 | ||
239 | .maximum = EXPOSURE_MAX, | ||
240 | .step = 1, | ||
241 | #define EXPOSURE_DEF 16 /* 32 ms / 30 fps */ | ||
242 | #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */ | ||
243 | .default_value = EXPOSURE_DEF, | ||
244 | }, | ||
245 | .set = sd_setexposure, | ||
246 | .get = sd_getexposure, | ||
247 | }, | ||
248 | { | ||
249 | { | ||
250 | .id = V4L2_CID_AUTOGAIN, | ||
251 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
252 | .name = "Auto Gain", | ||
253 | .minimum = 0, | ||
254 | .maximum = 1, | ||
255 | .step = 1, | ||
256 | #define AUTOGAIN_DEF 1 | ||
257 | .default_value = AUTOGAIN_DEF, | ||
258 | }, | ||
259 | .set = sd_setautogain, | ||
260 | .get = sd_getautogain, | ||
261 | }, | ||
262 | { | ||
263 | { | ||
264 | .id = V4L2_CID_HFLIP, | ||
265 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
266 | .name = "Mirror", | ||
267 | .minimum = 0, | ||
268 | .maximum = 1, | ||
269 | .step = 1, | ||
270 | #define HFLIP_DEF 0 | ||
271 | .default_value = HFLIP_DEF, | ||
272 | }, | ||
273 | .set = sd_sethflip, | ||
274 | .get = sd_gethflip, | ||
275 | }, | ||
276 | { | ||
277 | { | ||
278 | .id = V4L2_CID_VFLIP, | ||
279 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
280 | .name = "Vflip", | ||
281 | .minimum = 0, | ||
282 | .maximum = 1, | ||
283 | .step = 1, | ||
284 | #define VFLIP_DEF 0 | ||
285 | .default_value = VFLIP_DEF, | ||
286 | }, | ||
287 | .set = sd_setvflip, | ||
288 | .get = sd_getvflip, | ||
289 | }, | ||
290 | }; | ||
291 | |||
292 | static const struct v4l2_pix_format vga_mode[] = { | ||
293 | {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE, | ||
294 | .bytesperline = 640, | ||
295 | .sizeimage = 640 * 480 * 3 / 8 + 590, | ||
296 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
297 | .priv = 0}, | ||
298 | }; | ||
299 | |||
300 | #define LOAD_PAGE3 255 | ||
301 | #define LOAD_PAGE4 254 | ||
302 | #define END_OF_SEQUENCE 0 | ||
303 | |||
304 | /* pac 7302 */ | ||
305 | static const __u8 init_7302[] = { | ||
306 | /* index,value */ | ||
307 | 0xff, 0x01, /* page 1 */ | ||
308 | 0x78, 0x00, /* deactivate */ | ||
309 | 0xff, 0x01, | ||
310 | 0x78, 0x40, /* led off */ | ||
311 | }; | ||
312 | static const __u8 start_7302[] = { | ||
313 | /* index, len, [value]* */ | ||
314 | 0xff, 1, 0x00, /* page 0 */ | ||
315 | 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80, | ||
316 | 0x00, 0x00, 0x00, 0x00, | ||
317 | 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00, | ||
318 | 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7, | ||
319 | 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11, | ||
320 | 0x26, 2, 0xaa, 0xaa, | ||
321 | 0x2e, 1, 0x31, | ||
322 | 0x38, 1, 0x01, | ||
323 | 0x3a, 3, 0x14, 0xff, 0x5a, | ||
324 | 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11, | ||
325 | 0x00, 0x54, 0x11, | ||
326 | 0x55, 1, 0x00, | ||
327 | 0x62, 4, 0x10, 0x1e, 0x1e, 0x18, | ||
328 | 0x6b, 1, 0x00, | ||
329 | 0x6e, 3, 0x08, 0x06, 0x00, | ||
330 | 0x72, 3, 0x00, 0xff, 0x00, | ||
331 | 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c, | ||
332 | 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50, | ||
333 | 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00, | ||
334 | 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9, | ||
335 | 0xd2, 0xeb, | ||
336 | 0xaf, 1, 0x02, | ||
337 | 0xb5, 2, 0x08, 0x08, | ||
338 | 0xb8, 2, 0x08, 0x88, | ||
339 | 0xc4, 4, 0xae, 0x01, 0x04, 0x01, | ||
340 | 0xcc, 1, 0x00, | ||
341 | 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9, | ||
342 | 0xc1, 0xd7, 0xec, | ||
343 | 0xdc, 1, 0x01, | ||
344 | 0xff, 1, 0x01, /* page 1 */ | ||
345 | 0x12, 3, 0x02, 0x00, 0x01, | ||
346 | 0x3e, 2, 0x00, 0x00, | ||
347 | 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2, | ||
348 | 0x7c, 1, 0x00, | ||
349 | 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20, | ||
350 | 0x02, 0x00, | ||
351 | 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04, | ||
352 | 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, | ||
353 | 0x07, 0x00, 0x01, 0x07, 0x04, 0x01, | ||
354 | 0xd8, 1, 0x01, | ||
355 | 0xdb, 2, 0x00, 0x01, | ||
356 | 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00, | ||
357 | 0xe6, 4, 0x00, 0x00, 0x00, 0x01, | ||
358 | 0xeb, 1, 0x00, | ||
359 | 0xff, 1, 0x02, /* page 2 */ | ||
360 | 0x22, 1, 0x00, | ||
361 | 0xff, 1, 0x03, /* page 3 */ | ||
362 | 0, LOAD_PAGE3, /* load the page 3 */ | ||
363 | 0x11, 1, 0x01, | ||
364 | 0xff, 1, 0x02, /* page 2 */ | ||
365 | 0x13, 1, 0x00, | ||
366 | 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96, | ||
367 | 0x27, 2, 0x14, 0x0c, | ||
368 | 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22, | ||
369 | 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44, | ||
370 | 0x6e, 1, 0x08, | ||
371 | 0xff, 1, 0x01, /* page 1 */ | ||
372 | 0x78, 1, 0x00, | ||
373 | 0, END_OF_SEQUENCE /* end of sequence */ | ||
374 | }; | ||
375 | |||
376 | #define SKIP 0xaa | ||
377 | /* page 3 - the value SKIP says skip the index - see reg_w_page() */ | ||
378 | static const __u8 page3_7302[] = { | ||
379 | 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16, | ||
380 | 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00, | ||
381 | 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
382 | 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00, | ||
383 | 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21, | ||
384 | 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54, | ||
385 | 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00, | ||
386 | 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
387 | 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00, | ||
388 | 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00, | ||
389 | 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
390 | 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00, | ||
391 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
392 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8, | ||
393 | 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, | ||
394 | 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, | ||
395 | 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00, | ||
396 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
397 | 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00, | ||
398 | 0x00 | ||
399 | }; | ||
400 | |||
401 | static int reg_w_buf(struct gspca_dev *gspca_dev, | ||
402 | __u8 index, | ||
403 | const char *buffer, int len) | ||
404 | { | ||
405 | int ret; | ||
406 | |||
407 | memcpy(gspca_dev->usb_buf, buffer, len); | ||
408 | ret = usb_control_msg(gspca_dev->dev, | ||
409 | usb_sndctrlpipe(gspca_dev->dev, 0), | ||
410 | 1, /* request */ | ||
411 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
412 | 0, /* value */ | ||
413 | index, gspca_dev->usb_buf, len, | ||
414 | 500); | ||
415 | if (ret < 0) | ||
416 | PDEBUG(D_ERR, "reg_w_buf(): " | ||
417 | "Failed to write registers to index 0x%x, error %i", | ||
418 | index, ret); | ||
419 | return ret; | ||
420 | } | ||
421 | |||
422 | |||
423 | static int reg_w(struct gspca_dev *gspca_dev, | ||
424 | __u8 index, | ||
425 | __u8 value) | ||
426 | { | ||
427 | int ret; | ||
428 | |||
429 | gspca_dev->usb_buf[0] = value; | ||
430 | ret = usb_control_msg(gspca_dev->dev, | ||
431 | usb_sndctrlpipe(gspca_dev->dev, 0), | ||
432 | 0, /* request */ | ||
433 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
434 | 0, index, gspca_dev->usb_buf, 1, | ||
435 | 500); | ||
436 | if (ret < 0) | ||
437 | PDEBUG(D_ERR, "reg_w(): " | ||
438 | "Failed to write register to index 0x%x, value 0x%x, error %i", | ||
439 | index, value, ret); | ||
440 | return ret; | ||
441 | } | ||
442 | |||
443 | static int reg_w_seq(struct gspca_dev *gspca_dev, | ||
444 | const __u8 *seq, int len) | ||
445 | { | ||
446 | int ret = 0; | ||
447 | while (--len >= 0) { | ||
448 | if (0 <= ret) | ||
449 | ret = reg_w(gspca_dev, seq[0], seq[1]); | ||
450 | seq += 2; | ||
451 | } | ||
452 | return ret; | ||
453 | } | ||
454 | |||
455 | /* load the beginning of a page */ | ||
456 | static int reg_w_page(struct gspca_dev *gspca_dev, | ||
457 | const __u8 *page, int len) | ||
458 | { | ||
459 | int index; | ||
460 | int ret = 0; | ||
461 | |||
462 | for (index = 0; index < len; index++) { | ||
463 | if (page[index] == SKIP) /* skip this index */ | ||
464 | continue; | ||
465 | gspca_dev->usb_buf[0] = page[index]; | ||
466 | ret = usb_control_msg(gspca_dev->dev, | ||
467 | usb_sndctrlpipe(gspca_dev->dev, 0), | ||
468 | 0, /* request */ | ||
469 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
470 | 0, index, gspca_dev->usb_buf, 1, | ||
471 | 500); | ||
472 | if (ret < 0) { | ||
473 | PDEBUG(D_ERR, "reg_w_page(): " | ||
474 | "Failed to write register to index 0x%x, " | ||
475 | "value 0x%x, error %i", | ||
476 | index, page[index], ret); | ||
477 | break; | ||
478 | } | ||
479 | } | ||
480 | return ret; | ||
481 | } | ||
482 | |||
483 | /* output a variable sequence */ | ||
484 | static int reg_w_var(struct gspca_dev *gspca_dev, | ||
485 | const __u8 *seq, | ||
486 | const __u8 *page3, unsigned int page3_len, | ||
487 | const __u8 *page4, unsigned int page4_len) | ||
488 | { | ||
489 | int index, len; | ||
490 | int ret = 0; | ||
491 | |||
492 | for (;;) { | ||
493 | index = *seq++; | ||
494 | len = *seq++; | ||
495 | switch (len) { | ||
496 | case END_OF_SEQUENCE: | ||
497 | return ret; | ||
498 | case LOAD_PAGE4: | ||
499 | ret = reg_w_page(gspca_dev, page4, page4_len); | ||
500 | break; | ||
501 | case LOAD_PAGE3: | ||
502 | ret = reg_w_page(gspca_dev, page3, page3_len); | ||
503 | break; | ||
504 | default: | ||
505 | if (len > USB_BUF_SZ) { | ||
506 | PDEBUG(D_ERR|D_STREAM, | ||
507 | "Incorrect variable sequence"); | ||
508 | return -EINVAL; | ||
509 | } | ||
510 | while (len > 0) { | ||
511 | if (len < 8) { | ||
512 | ret = reg_w_buf(gspca_dev, | ||
513 | index, seq, len); | ||
514 | if (ret < 0) | ||
515 | return ret; | ||
516 | seq += len; | ||
517 | break; | ||
518 | } | ||
519 | ret = reg_w_buf(gspca_dev, index, seq, 8); | ||
520 | seq += 8; | ||
521 | index += 8; | ||
522 | len -= 8; | ||
523 | } | ||
524 | } | ||
525 | if (ret < 0) | ||
526 | return ret; | ||
527 | } | ||
528 | /* not reached */ | ||
529 | } | ||
530 | |||
531 | /* this function is called at probe time for pac7302 */ | ||
532 | static int sd_config(struct gspca_dev *gspca_dev, | ||
533 | const struct usb_device_id *id) | ||
534 | { | ||
535 | struct sd *sd = (struct sd *) gspca_dev; | ||
536 | struct cam *cam; | ||
537 | |||
538 | cam = &gspca_dev->cam; | ||
539 | |||
540 | PDEBUG(D_CONF, "Find Sensor PAC7302"); | ||
541 | cam->cam_mode = vga_mode; /* only 640x480 */ | ||
542 | cam->nmodes = ARRAY_SIZE(vga_mode); | ||
543 | |||
544 | sd->brightness = BRIGHTNESS_DEF; | ||
545 | sd->contrast = CONTRAST_DEF; | ||
546 | sd->colors = COLOR_DEF; | ||
547 | sd->white_balance = WHITEBALANCE_DEF; | ||
548 | sd->red_balance = REDBALANCE_DEF; | ||
549 | sd->blue_balance = BLUEBALANCE_DEF; | ||
550 | sd->gain = GAIN_DEF; | ||
551 | sd->exposure = EXPOSURE_DEF; | ||
552 | sd->autogain = AUTOGAIN_DEF; | ||
553 | sd->hflip = HFLIP_DEF; | ||
554 | sd->vflip = VFLIP_DEF; | ||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | /* This function is used by pac7302 only */ | ||
559 | static int setbrightcont(struct gspca_dev *gspca_dev) | ||
560 | { | ||
561 | struct sd *sd = (struct sd *) gspca_dev; | ||
562 | int i, v; | ||
563 | int ret; | ||
564 | static const __u8 max[10] = | ||
565 | {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb, | ||
566 | 0xd4, 0xec}; | ||
567 | static const __u8 delta[10] = | ||
568 | {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17, | ||
569 | 0x11, 0x0b}; | ||
570 | |||
571 | ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | ||
572 | for (i = 0; i < 10; i++) { | ||
573 | v = max[i]; | ||
574 | v += (sd->brightness - BRIGHTNESS_MAX) | ||
575 | * 150 / BRIGHTNESS_MAX; /* 200 ? */ | ||
576 | v -= delta[i] * sd->contrast / CONTRAST_MAX; | ||
577 | if (v < 0) | ||
578 | v = 0; | ||
579 | else if (v > 0xff) | ||
580 | v = 0xff; | ||
581 | if (0 <= ret) | ||
582 | ret = reg_w(gspca_dev, 0xa2 + i, v); | ||
583 | } | ||
584 | if (0 <= ret) | ||
585 | ret = reg_w(gspca_dev, 0xdc, 0x01); | ||
586 | return ret; | ||
587 | } | ||
588 | |||
589 | /* This function is used by pac7302 only */ | ||
590 | static int setcolors(struct gspca_dev *gspca_dev) | ||
591 | { | ||
592 | struct sd *sd = (struct sd *) gspca_dev; | ||
593 | int i, v; | ||
594 | int ret; | ||
595 | static const int a[9] = | ||
596 | {217, -212, 0, -101, 170, -67, -38, -315, 355}; | ||
597 | static const int b[9] = | ||
598 | {19, 106, 0, 19, 106, 1, 19, 106, 1}; | ||
599 | |||
600 | ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | ||
601 | if (0 <= ret) | ||
602 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
603 | if (0 <= ret) | ||
604 | ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | ||
605 | for (i = 0; i < 9; i++) { | ||
606 | v = a[i] * sd->colors / COLOR_MAX + b[i]; | ||
607 | if (0 <= ret) | ||
608 | ret = reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); | ||
609 | if (0 <= ret) | ||
610 | ret = reg_w(gspca_dev, 0x0f + 2 * i + 1, v); | ||
611 | } | ||
612 | if (0 <= ret) | ||
613 | ret = reg_w(gspca_dev, 0xdc, 0x01); | ||
614 | PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); | ||
615 | return ret; | ||
616 | } | ||
617 | |||
618 | static int setwhitebalance(struct gspca_dev *gspca_dev) | ||
619 | { | ||
620 | struct sd *sd = (struct sd *) gspca_dev; | ||
621 | int ret; | ||
622 | |||
623 | ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | ||
624 | if (0 <= ret) | ||
625 | ret = reg_w(gspca_dev, 0xc6, sd->white_balance); | ||
626 | |||
627 | if (0 <= ret) | ||
628 | ret = reg_w(gspca_dev, 0xdc, 0x01); | ||
629 | PDEBUG(D_CONF|D_STREAM, "white_balance: %i", sd->white_balance); | ||
630 | return ret; | ||
631 | } | ||
632 | |||
633 | static int setredbalance(struct gspca_dev *gspca_dev) | ||
634 | { | ||
635 | struct sd *sd = (struct sd *) gspca_dev; | ||
636 | int ret; | ||
637 | |||
638 | ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | ||
639 | if (0 <= ret) | ||
640 | ret = reg_w(gspca_dev, 0xc5, sd->red_balance); | ||
641 | |||
642 | if (0 <= ret) | ||
643 | ret = reg_w(gspca_dev, 0xdc, 0x01); | ||
644 | PDEBUG(D_CONF|D_STREAM, "red_balance: %i", sd->red_balance); | ||
645 | return ret; | ||
646 | } | ||
647 | |||
648 | static int setbluebalance(struct gspca_dev *gspca_dev) | ||
649 | { | ||
650 | struct sd *sd = (struct sd *) gspca_dev; | ||
651 | int ret; | ||
652 | |||
653 | ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | ||
654 | if (0 <= ret) | ||
655 | ret = reg_w(gspca_dev, 0xc7, sd->blue_balance); | ||
656 | |||
657 | if (0 <= ret) | ||
658 | ret = reg_w(gspca_dev, 0xdc, 0x01); | ||
659 | PDEBUG(D_CONF|D_STREAM, "blue_balance: %i", sd->blue_balance); | ||
660 | return ret; | ||
661 | } | ||
662 | |||
663 | static int setgain(struct gspca_dev *gspca_dev) | ||
664 | { | ||
665 | struct sd *sd = (struct sd *) gspca_dev; | ||
666 | int ret; | ||
667 | |||
668 | ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | ||
669 | if (0 <= ret) | ||
670 | ret = reg_w(gspca_dev, 0x10, sd->gain >> 3); | ||
671 | |||
672 | /* load registers to sensor (Bit 0, auto clear) */ | ||
673 | if (0 <= ret) | ||
674 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
675 | return ret; | ||
676 | } | ||
677 | |||
678 | static int setexposure(struct gspca_dev *gspca_dev) | ||
679 | { | ||
680 | struct sd *sd = (struct sd *) gspca_dev; | ||
681 | int ret; | ||
682 | __u8 reg; | ||
683 | |||
684 | /* register 2 of frame 3/4 contains the clock divider configuring the | ||
685 | no fps according to the formula: 60 / reg. sd->exposure is the | ||
686 | desired exposure time in ms. */ | ||
687 | reg = 120 * sd->exposure / 1000; | ||
688 | if (reg < 2) | ||
689 | reg = 2; | ||
690 | else if (reg > 63) | ||
691 | reg = 63; | ||
692 | |||
693 | /* On the pac7302 reg2 MUST be a multiple of 3, so round it to | ||
694 | the nearest multiple of 3, except when between 6 and 12? */ | ||
695 | if (reg < 6 || reg > 12) | ||
696 | reg = ((reg + 1) / 3) * 3; | ||
697 | ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | ||
698 | if (0 <= ret) | ||
699 | ret = reg_w(gspca_dev, 0x02, reg); | ||
700 | |||
701 | /* load registers to sensor (Bit 0, auto clear) */ | ||
702 | if (0 <= ret) | ||
703 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
704 | return ret; | ||
705 | } | ||
706 | |||
707 | static int sethvflip(struct gspca_dev *gspca_dev) | ||
708 | { | ||
709 | struct sd *sd = (struct sd *) gspca_dev; | ||
710 | int ret; | ||
711 | __u8 data; | ||
712 | |||
713 | ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | ||
714 | data = (sd->hflip ? 0x08 : 0x00) | (sd->vflip ? 0x04 : 0x00); | ||
715 | if (0 <= ret) | ||
716 | ret = reg_w(gspca_dev, 0x21, data); | ||
717 | /* load registers to sensor (Bit 0, auto clear) */ | ||
718 | if (0 <= ret) | ||
719 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
720 | return ret; | ||
721 | } | ||
722 | |||
723 | /* this function is called at probe and resume time for pac7302 */ | ||
724 | static int sd_init(struct gspca_dev *gspca_dev) | ||
725 | { | ||
726 | return reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2); | ||
727 | } | ||
728 | |||
729 | static int sd_start(struct gspca_dev *gspca_dev) | ||
730 | { | ||
731 | struct sd *sd = (struct sd *) gspca_dev; | ||
732 | int ret = 0; | ||
733 | |||
734 | sd->sof_read = 0; | ||
735 | |||
736 | ret = reg_w_var(gspca_dev, start_7302, | ||
737 | page3_7302, sizeof(page3_7302), | ||
738 | NULL, 0); | ||
739 | if (0 <= ret) | ||
740 | ret = setbrightcont(gspca_dev); | ||
741 | if (0 <= ret) | ||
742 | ret = setcolors(gspca_dev); | ||
743 | if (0 <= ret) | ||
744 | ret = setwhitebalance(gspca_dev); | ||
745 | if (0 <= ret) | ||
746 | ret = setredbalance(gspca_dev); | ||
747 | if (0 <= ret) | ||
748 | ret = setbluebalance(gspca_dev); | ||
749 | if (0 <= ret) | ||
750 | ret = setgain(gspca_dev); | ||
751 | if (0 <= ret) | ||
752 | ret = setexposure(gspca_dev); | ||
753 | if (0 <= ret) | ||
754 | ret = sethvflip(gspca_dev); | ||
755 | |||
756 | /* only resolution 640x480 is supported for pac7302 */ | ||
757 | |||
758 | sd->sof_read = 0; | ||
759 | sd->autogain_ignore_frames = 0; | ||
760 | atomic_set(&sd->avg_lum, -1); | ||
761 | |||
762 | /* start stream */ | ||
763 | if (0 <= ret) | ||
764 | ret = reg_w(gspca_dev, 0xff, 0x01); | ||
765 | if (0 <= ret) | ||
766 | ret = reg_w(gspca_dev, 0x78, 0x01); | ||
767 | |||
768 | return ret; | ||
769 | } | ||
770 | |||
771 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
772 | { | ||
773 | int ret; | ||
774 | |||
775 | /* stop stream */ | ||
776 | ret = reg_w(gspca_dev, 0xff, 0x01); | ||
777 | if (0 <= ret) | ||
778 | ret = reg_w(gspca_dev, 0x78, 0x00); | ||
779 | } | ||
780 | |||
781 | /* called on streamoff with alt 0 and on disconnect for pac7302 */ | ||
782 | static void sd_stop0(struct gspca_dev *gspca_dev) | ||
783 | { | ||
784 | int ret; | ||
785 | |||
786 | if (!gspca_dev->present) | ||
787 | return; | ||
788 | ret = reg_w(gspca_dev, 0xff, 0x01); | ||
789 | if (0 <= ret) | ||
790 | ret = reg_w(gspca_dev, 0x78, 0x40); | ||
791 | } | ||
792 | |||
793 | /* Include pac common sof detection functions */ | ||
794 | #include "pac_common.h" | ||
795 | |||
796 | static void do_autogain(struct gspca_dev *gspca_dev) | ||
797 | { | ||
798 | struct sd *sd = (struct sd *) gspca_dev; | ||
799 | int avg_lum = atomic_read(&sd->avg_lum); | ||
800 | int desired_lum, deadzone; | ||
801 | |||
802 | if (avg_lum == -1) | ||
803 | return; | ||
804 | |||
805 | desired_lum = 270 + sd->brightness * 4; | ||
806 | /* Hack hack, with the 7202 the first exposure step is | ||
807 | pretty large, so if we're about to make the first | ||
808 | exposure increase make the deadzone large to avoid | ||
809 | oscilating */ | ||
810 | if (desired_lum > avg_lum && sd->gain == GAIN_DEF && | ||
811 | sd->exposure > EXPOSURE_DEF && | ||
812 | sd->exposure < 42) | ||
813 | deadzone = 90; | ||
814 | else | ||
815 | deadzone = 30; | ||
816 | |||
817 | if (sd->autogain_ignore_frames > 0) | ||
818 | sd->autogain_ignore_frames--; | ||
819 | else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum, | ||
820 | deadzone, GAIN_KNEE, EXPOSURE_KNEE)) | ||
821 | sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; | ||
822 | } | ||
823 | |||
824 | /* JPEG header, part 1 */ | ||
825 | static const unsigned char pac_jpeg_header1[] = { | ||
826 | 0xff, 0xd8, /* SOI: Start of Image */ | ||
827 | |||
828 | 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */ | ||
829 | 0x00, 0x11, /* length = 17 bytes (including this length field) */ | ||
830 | 0x08 /* Precision: 8 */ | ||
831 | /* 2 bytes is placed here: number of image lines */ | ||
832 | /* 2 bytes is placed here: samples per line */ | ||
833 | }; | ||
834 | |||
835 | /* JPEG header, continued */ | ||
836 | static const unsigned char pac_jpeg_header2[] = { | ||
837 | 0x03, /* Number of image components: 3 */ | ||
838 | 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */ | ||
839 | 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */ | ||
840 | 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */ | ||
841 | |||
842 | 0xff, 0xda, /* SOS: Start Of Scan */ | ||
843 | 0x00, 0x0c, /* length = 12 bytes (including this length field) */ | ||
844 | 0x03, /* number of components: 3 */ | ||
845 | 0x01, 0x00, /* selector 1, table 0x00 */ | ||
846 | 0x02, 0x11, /* selector 2, table 0x11 */ | ||
847 | 0x03, 0x11, /* selector 3, table 0x11 */ | ||
848 | 0x00, 0x3f, /* Spectral selection: 0 .. 63 */ | ||
849 | 0x00 /* Successive approximation: 0 */ | ||
850 | }; | ||
851 | |||
852 | static void pac_start_frame(struct gspca_dev *gspca_dev, | ||
853 | struct gspca_frame *frame, | ||
854 | __u16 lines, __u16 samples_per_line) | ||
855 | { | ||
856 | unsigned char tmpbuf[4]; | ||
857 | |||
858 | gspca_frame_add(gspca_dev, FIRST_PACKET, | ||
859 | pac_jpeg_header1, sizeof(pac_jpeg_header1)); | ||
860 | |||
861 | tmpbuf[0] = lines >> 8; | ||
862 | tmpbuf[1] = lines & 0xff; | ||
863 | tmpbuf[2] = samples_per_line >> 8; | ||
864 | tmpbuf[3] = samples_per_line & 0xff; | ||
865 | |||
866 | gspca_frame_add(gspca_dev, INTER_PACKET, | ||
867 | tmpbuf, sizeof(tmpbuf)); | ||
868 | gspca_frame_add(gspca_dev, INTER_PACKET, | ||
869 | pac_jpeg_header2, sizeof(pac_jpeg_header2)); | ||
870 | } | ||
871 | |||
872 | /* this function is run at interrupt level */ | ||
873 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
874 | u8 *data, /* isoc packet */ | ||
875 | int len) /* iso packet length */ | ||
876 | { | ||
877 | struct sd *sd = (struct sd *) gspca_dev; | ||
878 | struct gspca_frame *frame; | ||
879 | unsigned char *sof; | ||
880 | |||
881 | sof = pac_find_sof(&sd->sof_read, data, len); | ||
882 | if (sof) { | ||
883 | int n, lum_offset, footer_length; | ||
884 | |||
885 | frame = gspca_get_i_frame(gspca_dev); | ||
886 | if (frame == NULL) { | ||
887 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
888 | return; | ||
889 | } | ||
890 | |||
891 | /* 6 bytes after the FF D9 EOF marker a number of lumination | ||
892 | bytes are send corresponding to different parts of the | ||
893 | image, the 14th and 15th byte after the EOF seem to | ||
894 | correspond to the center of the image */ | ||
895 | lum_offset = 61 + sizeof pac_sof_marker; | ||
896 | footer_length = 74; | ||
897 | |||
898 | /* Finish decoding current frame */ | ||
899 | n = (sof - data) - (footer_length + sizeof pac_sof_marker); | ||
900 | if (n < 0) { | ||
901 | frame->data_end += n; | ||
902 | n = 0; | ||
903 | } | ||
904 | gspca_frame_add(gspca_dev, INTER_PACKET, | ||
905 | data, n); | ||
906 | if (gspca_dev->last_packet_type != DISCARD_PACKET && | ||
907 | frame->data_end[-2] == 0xff && | ||
908 | frame->data_end[-1] == 0xd9) | ||
909 | gspca_frame_add(gspca_dev, LAST_PACKET, | ||
910 | NULL, 0); | ||
911 | |||
912 | n = sof - data; | ||
913 | len -= n; | ||
914 | data = sof; | ||
915 | |||
916 | /* Get average lumination */ | ||
917 | if (gspca_dev->last_packet_type == LAST_PACKET && | ||
918 | n >= lum_offset) | ||
919 | atomic_set(&sd->avg_lum, data[-lum_offset] + | ||
920 | data[-lum_offset + 1]); | ||
921 | else | ||
922 | atomic_set(&sd->avg_lum, -1); | ||
923 | |||
924 | /* Start the new frame with the jpeg header */ | ||
925 | /* The PAC7302 has the image rotated 90 degrees */ | ||
926 | pac_start_frame(gspca_dev, frame, | ||
927 | gspca_dev->width, gspca_dev->height); | ||
928 | } | ||
929 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | ||
930 | } | ||
931 | |||
932 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | ||
933 | { | ||
934 | struct sd *sd = (struct sd *) gspca_dev; | ||
935 | |||
936 | sd->brightness = val; | ||
937 | if (gspca_dev->streaming) | ||
938 | setbrightcont(gspca_dev); | ||
939 | return 0; | ||
940 | } | ||
941 | |||
942 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
943 | { | ||
944 | struct sd *sd = (struct sd *) gspca_dev; | ||
945 | |||
946 | *val = sd->brightness; | ||
947 | return 0; | ||
948 | } | ||
949 | |||
950 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | ||
951 | { | ||
952 | struct sd *sd = (struct sd *) gspca_dev; | ||
953 | |||
954 | sd->contrast = val; | ||
955 | if (gspca_dev->streaming) { | ||
956 | setbrightcont(gspca_dev); | ||
957 | } | ||
958 | return 0; | ||
959 | } | ||
960 | |||
961 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | ||
962 | { | ||
963 | struct sd *sd = (struct sd *) gspca_dev; | ||
964 | |||
965 | *val = sd->contrast; | ||
966 | return 0; | ||
967 | } | ||
968 | |||
969 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) | ||
970 | { | ||
971 | struct sd *sd = (struct sd *) gspca_dev; | ||
972 | |||
973 | sd->colors = val; | ||
974 | if (gspca_dev->streaming) | ||
975 | setcolors(gspca_dev); | ||
976 | return 0; | ||
977 | } | ||
978 | |||
979 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) | ||
980 | { | ||
981 | struct sd *sd = (struct sd *) gspca_dev; | ||
982 | |||
983 | *val = sd->colors; | ||
984 | return 0; | ||
985 | } | ||
986 | |||
987 | static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val) | ||
988 | { | ||
989 | struct sd *sd = (struct sd *) gspca_dev; | ||
990 | int ret = 0; | ||
991 | |||
992 | sd->white_balance = val; | ||
993 | if (gspca_dev->streaming) | ||
994 | ret = setwhitebalance(gspca_dev); | ||
995 | if (0 <= ret) | ||
996 | ret = 0; | ||
997 | return ret; | ||
998 | } | ||
999 | |||
1000 | static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val) | ||
1001 | { | ||
1002 | struct sd *sd = (struct sd *) gspca_dev; | ||
1003 | |||
1004 | *val = sd->white_balance; | ||
1005 | return 0; | ||
1006 | } | ||
1007 | |||
1008 | static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val) | ||
1009 | { | ||
1010 | struct sd *sd = (struct sd *) gspca_dev; | ||
1011 | int ret = 0; | ||
1012 | |||
1013 | sd->red_balance = val; | ||
1014 | if (gspca_dev->streaming) | ||
1015 | ret = setredbalance(gspca_dev); | ||
1016 | if (0 <= ret) | ||
1017 | ret = 0; | ||
1018 | return ret; | ||
1019 | } | ||
1020 | |||
1021 | static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val) | ||
1022 | { | ||
1023 | struct sd *sd = (struct sd *) gspca_dev; | ||
1024 | |||
1025 | *val = sd->red_balance; | ||
1026 | return 0; | ||
1027 | } | ||
1028 | |||
1029 | static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val) | ||
1030 | { | ||
1031 | struct sd *sd = (struct sd *) gspca_dev; | ||
1032 | int ret = 0; | ||
1033 | |||
1034 | sd->blue_balance = val; | ||
1035 | if (gspca_dev->streaming) | ||
1036 | ret = setbluebalance(gspca_dev); | ||
1037 | if (0 <= ret) | ||
1038 | ret = 0; | ||
1039 | return ret; | ||
1040 | } | ||
1041 | |||
1042 | static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val) | ||
1043 | { | ||
1044 | struct sd *sd = (struct sd *) gspca_dev; | ||
1045 | |||
1046 | *val = sd->blue_balance; | ||
1047 | return 0; | ||
1048 | } | ||
1049 | |||
1050 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) | ||
1051 | { | ||
1052 | struct sd *sd = (struct sd *) gspca_dev; | ||
1053 | |||
1054 | sd->gain = val; | ||
1055 | if (gspca_dev->streaming) | ||
1056 | setgain(gspca_dev); | ||
1057 | return 0; | ||
1058 | } | ||
1059 | |||
1060 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) | ||
1061 | { | ||
1062 | struct sd *sd = (struct sd *) gspca_dev; | ||
1063 | |||
1064 | *val = sd->gain; | ||
1065 | return 0; | ||
1066 | } | ||
1067 | |||
1068 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) | ||
1069 | { | ||
1070 | struct sd *sd = (struct sd *) gspca_dev; | ||
1071 | |||
1072 | sd->exposure = val; | ||
1073 | if (gspca_dev->streaming) | ||
1074 | setexposure(gspca_dev); | ||
1075 | return 0; | ||
1076 | } | ||
1077 | |||
1078 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) | ||
1079 | { | ||
1080 | struct sd *sd = (struct sd *) gspca_dev; | ||
1081 | |||
1082 | *val = sd->exposure; | ||
1083 | return 0; | ||
1084 | } | ||
1085 | |||
1086 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | ||
1087 | { | ||
1088 | struct sd *sd = (struct sd *) gspca_dev; | ||
1089 | |||
1090 | sd->autogain = val; | ||
1091 | /* when switching to autogain set defaults to make sure | ||
1092 | we are on a valid point of the autogain gain / | ||
1093 | exposure knee graph, and give this change time to | ||
1094 | take effect before doing autogain. */ | ||
1095 | if (sd->autogain) { | ||
1096 | sd->exposure = EXPOSURE_DEF; | ||
1097 | sd->gain = GAIN_DEF; | ||
1098 | if (gspca_dev->streaming) { | ||
1099 | sd->autogain_ignore_frames = | ||
1100 | PAC_AUTOGAIN_IGNORE_FRAMES; | ||
1101 | setexposure(gspca_dev); | ||
1102 | setgain(gspca_dev); | ||
1103 | } | ||
1104 | } | ||
1105 | |||
1106 | return 0; | ||
1107 | } | ||
1108 | |||
1109 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | ||
1110 | { | ||
1111 | struct sd *sd = (struct sd *) gspca_dev; | ||
1112 | |||
1113 | *val = sd->autogain; | ||
1114 | return 0; | ||
1115 | } | ||
1116 | |||
1117 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) | ||
1118 | { | ||
1119 | struct sd *sd = (struct sd *) gspca_dev; | ||
1120 | |||
1121 | sd->hflip = val; | ||
1122 | if (gspca_dev->streaming) | ||
1123 | sethvflip(gspca_dev); | ||
1124 | return 0; | ||
1125 | } | ||
1126 | |||
1127 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
1128 | { | ||
1129 | struct sd *sd = (struct sd *) gspca_dev; | ||
1130 | |||
1131 | *val = sd->hflip; | ||
1132 | return 0; | ||
1133 | } | ||
1134 | |||
1135 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) | ||
1136 | { | ||
1137 | struct sd *sd = (struct sd *) gspca_dev; | ||
1138 | |||
1139 | sd->vflip = val; | ||
1140 | if (gspca_dev->streaming) | ||
1141 | sethvflip(gspca_dev); | ||
1142 | return 0; | ||
1143 | } | ||
1144 | |||
1145 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
1146 | { | ||
1147 | struct sd *sd = (struct sd *) gspca_dev; | ||
1148 | |||
1149 | *val = sd->vflip; | ||
1150 | return 0; | ||
1151 | } | ||
1152 | |||
1153 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1154 | static int sd_dbg_s_register(struct gspca_dev *gspca_dev, | ||
1155 | struct v4l2_dbg_register *reg) | ||
1156 | { | ||
1157 | int ret = -EINVAL; | ||
1158 | __u8 index; | ||
1159 | __u8 value; | ||
1160 | |||
1161 | /* reg->reg: bit0..15: reserved for register index (wIndex is 16bit | ||
1162 | long on the USB bus) | ||
1163 | */ | ||
1164 | if (reg->match.type == V4L2_CHIP_MATCH_HOST && | ||
1165 | reg->match.addr == 0 && | ||
1166 | (reg->reg < 0x000000ff) && | ||
1167 | (reg->val <= 0x000000ff) | ||
1168 | ) { | ||
1169 | /* Currently writing to page 0 is only supported. */ | ||
1170 | /* reg_w() only supports 8bit index */ | ||
1171 | index = reg->reg & 0x000000ff; | ||
1172 | value = reg->val & 0x000000ff; | ||
1173 | |||
1174 | /* Note that there shall be no access to other page | ||
1175 | by any other function between the page swith and | ||
1176 | the actual register write */ | ||
1177 | ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | ||
1178 | if (0 <= ret) | ||
1179 | ret = reg_w(gspca_dev, index, value); | ||
1180 | |||
1181 | if (0 <= ret) | ||
1182 | ret = reg_w(gspca_dev, 0xdc, 0x01); | ||
1183 | } | ||
1184 | return ret; | ||
1185 | } | ||
1186 | |||
1187 | static int sd_chip_ident(struct gspca_dev *gspca_dev, | ||
1188 | struct v4l2_dbg_chip_ident *chip) | ||
1189 | { | ||
1190 | int ret = -EINVAL; | ||
1191 | |||
1192 | if (chip->match.type == V4L2_CHIP_MATCH_HOST && | ||
1193 | chip->match.addr == 0) { | ||
1194 | chip->revision = 0; | ||
1195 | chip->ident = V4L2_IDENT_UNKNOWN; | ||
1196 | ret = 0; | ||
1197 | } | ||
1198 | return ret; | ||
1199 | } | ||
1200 | #endif | ||
1201 | |||
1202 | /* sub-driver description for pac7302 */ | ||
1203 | static struct sd_desc sd_desc = { | ||
1204 | .name = MODULE_NAME, | ||
1205 | .ctrls = sd_ctrls, | ||
1206 | .nctrls = ARRAY_SIZE(sd_ctrls), | ||
1207 | .config = sd_config, | ||
1208 | .init = sd_init, | ||
1209 | .start = sd_start, | ||
1210 | .stopN = sd_stopN, | ||
1211 | .stop0 = sd_stop0, | ||
1212 | .pkt_scan = sd_pkt_scan, | ||
1213 | .dq_callback = do_autogain, | ||
1214 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1215 | .set_register = sd_dbg_s_register, | ||
1216 | .get_chip_ident = sd_chip_ident, | ||
1217 | #endif | ||
1218 | }; | ||
1219 | |||
1220 | /* -- module initialisation -- */ | ||
1221 | static __devinitdata struct usb_device_id device_table[] = { | ||
1222 | {USB_DEVICE(0x06f8, 0x3009)}, | ||
1223 | {USB_DEVICE(0x093a, 0x2620)}, | ||
1224 | {USB_DEVICE(0x093a, 0x2621)}, | ||
1225 | {USB_DEVICE(0x093a, 0x2622)}, | ||
1226 | {USB_DEVICE(0x093a, 0x2624)}, | ||
1227 | {USB_DEVICE(0x093a, 0x2626)}, | ||
1228 | {USB_DEVICE(0x093a, 0x2628)}, | ||
1229 | {USB_DEVICE(0x093a, 0x2629)}, | ||
1230 | {USB_DEVICE(0x093a, 0x262a)}, | ||
1231 | {USB_DEVICE(0x093a, 0x262c)}, | ||
1232 | {} | ||
1233 | }; | ||
1234 | MODULE_DEVICE_TABLE(usb, device_table); | ||
1235 | |||
1236 | /* -- device connect -- */ | ||
1237 | static int sd_probe(struct usb_interface *intf, | ||
1238 | const struct usb_device_id *id) | ||
1239 | { | ||
1240 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | ||
1241 | THIS_MODULE); | ||
1242 | } | ||
1243 | |||
1244 | static struct usb_driver sd_driver = { | ||
1245 | .name = MODULE_NAME, | ||
1246 | .id_table = device_table, | ||
1247 | .probe = sd_probe, | ||
1248 | .disconnect = gspca_disconnect, | ||
1249 | #ifdef CONFIG_PM | ||
1250 | .suspend = gspca_suspend, | ||
1251 | .resume = gspca_resume, | ||
1252 | #endif | ||
1253 | }; | ||
1254 | |||
1255 | /* -- module insert / remove -- */ | ||
1256 | static int __init sd_mod_init(void) | ||
1257 | { | ||
1258 | int ret; | ||
1259 | ret = usb_register(&sd_driver); | ||
1260 | if (ret < 0) | ||
1261 | return ret; | ||
1262 | PDEBUG(D_PROBE, "registered"); | ||
1263 | return 0; | ||
1264 | } | ||
1265 | static void __exit sd_mod_exit(void) | ||
1266 | { | ||
1267 | usb_deregister(&sd_driver); | ||
1268 | PDEBUG(D_PROBE, "deregistered"); | ||
1269 | } | ||
1270 | |||
1271 | module_init(sd_mod_init); | ||
1272 | module_exit(sd_mod_exit); | ||
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 052714484e83..e5697a6345e8 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c | |||
@@ -57,23 +57,17 @@ MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); | |||
57 | MODULE_DESCRIPTION("Pixart PAC7311"); | 57 | MODULE_DESCRIPTION("Pixart PAC7311"); |
58 | MODULE_LICENSE("GPL"); | 58 | MODULE_LICENSE("GPL"); |
59 | 59 | ||
60 | /* specific webcam descriptor */ | 60 | /* specific webcam descriptor for pac7311 */ |
61 | struct sd { | 61 | struct sd { |
62 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 62 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
63 | 63 | ||
64 | unsigned char brightness; | ||
65 | unsigned char contrast; | 64 | unsigned char contrast; |
66 | unsigned char colors; | ||
67 | unsigned char gain; | 65 | unsigned char gain; |
68 | unsigned char exposure; | 66 | unsigned char exposure; |
69 | unsigned char autogain; | 67 | unsigned char autogain; |
70 | __u8 hflip; | 68 | __u8 hflip; |
71 | __u8 vflip; | 69 | __u8 vflip; |
72 | 70 | ||
73 | __u8 sensor; | ||
74 | #define SENSOR_PAC7302 0 | ||
75 | #define SENSOR_PAC7311 1 | ||
76 | |||
77 | u8 sof_read; | 71 | u8 sof_read; |
78 | u8 autogain_ignore_frames; | 72 | u8 autogain_ignore_frames; |
79 | 73 | ||
@@ -81,12 +75,8 @@ struct sd { | |||
81 | }; | 75 | }; |
82 | 76 | ||
83 | /* V4L2 controls supported by the driver */ | 77 | /* V4L2 controls supported by the driver */ |
84 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
85 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
86 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | 78 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); |
87 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | 79 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); |
88 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | ||
89 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | ||
90 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | 80 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); |
91 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | 81 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); |
92 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); | 82 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); |
@@ -99,23 +89,6 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | |||
99 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | 89 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); |
100 | 90 | ||
101 | static struct ctrl sd_ctrls[] = { | 91 | static struct ctrl sd_ctrls[] = { |
102 | /* This control is pac7302 only */ | ||
103 | #define BRIGHTNESS_IDX 0 | ||
104 | { | ||
105 | { | ||
106 | .id = V4L2_CID_BRIGHTNESS, | ||
107 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
108 | .name = "Brightness", | ||
109 | .minimum = 0, | ||
110 | #define BRIGHTNESS_MAX 0x20 | ||
111 | .maximum = BRIGHTNESS_MAX, | ||
112 | .step = 1, | ||
113 | #define BRIGHTNESS_DEF 0x10 | ||
114 | .default_value = BRIGHTNESS_DEF, | ||
115 | }, | ||
116 | .set = sd_setbrightness, | ||
117 | .get = sd_getbrightness, | ||
118 | }, | ||
119 | /* This control is for both the 7302 and the 7311 */ | 92 | /* This control is for both the 7302 and the 7311 */ |
120 | { | 93 | { |
121 | { | 94 | { |
@@ -132,23 +105,6 @@ static struct ctrl sd_ctrls[] = { | |||
132 | .set = sd_setcontrast, | 105 | .set = sd_setcontrast, |
133 | .get = sd_getcontrast, | 106 | .get = sd_getcontrast, |
134 | }, | 107 | }, |
135 | /* This control is pac7302 only */ | ||
136 | #define SATURATION_IDX 2 | ||
137 | { | ||
138 | { | ||
139 | .id = V4L2_CID_SATURATION, | ||
140 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
141 | .name = "Saturation", | ||
142 | .minimum = 0, | ||
143 | #define COLOR_MAX 255 | ||
144 | .maximum = COLOR_MAX, | ||
145 | .step = 1, | ||
146 | #define COLOR_DEF 127 | ||
147 | .default_value = COLOR_DEF, | ||
148 | }, | ||
149 | .set = sd_setcolors, | ||
150 | .get = sd_getcolors, | ||
151 | }, | ||
152 | /* All controls below are for both the 7302 and the 7311 */ | 108 | /* All controls below are for both the 7302 and the 7311 */ |
153 | { | 109 | { |
154 | { | 110 | { |
@@ -244,101 +200,9 @@ static const struct v4l2_pix_format vga_mode[] = { | |||
244 | .priv = 0}, | 200 | .priv = 0}, |
245 | }; | 201 | }; |
246 | 202 | ||
247 | /* pac 7302 */ | 203 | #define LOAD_PAGE3 255 |
248 | static const __u8 init_7302[] = { | 204 | #define LOAD_PAGE4 254 |
249 | /* index,value */ | 205 | #define END_OF_SEQUENCE 0 |
250 | 0xff, 0x01, /* page 1 */ | ||
251 | 0x78, 0x00, /* deactivate */ | ||
252 | 0xff, 0x01, | ||
253 | 0x78, 0x40, /* led off */ | ||
254 | }; | ||
255 | static const __u8 start_7302[] = { | ||
256 | /* index, len, [value]* */ | ||
257 | 0xff, 1, 0x00, /* page 0 */ | ||
258 | 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80, | ||
259 | 0x00, 0x00, 0x00, 0x00, | ||
260 | 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00, | ||
261 | 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7, | ||
262 | 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11, | ||
263 | 0x26, 2, 0xaa, 0xaa, | ||
264 | 0x2e, 1, 0x31, | ||
265 | 0x38, 1, 0x01, | ||
266 | 0x3a, 3, 0x14, 0xff, 0x5a, | ||
267 | 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11, | ||
268 | 0x00, 0x54, 0x11, | ||
269 | 0x55, 1, 0x00, | ||
270 | 0x62, 4, 0x10, 0x1e, 0x1e, 0x18, | ||
271 | 0x6b, 1, 0x00, | ||
272 | 0x6e, 3, 0x08, 0x06, 0x00, | ||
273 | 0x72, 3, 0x00, 0xff, 0x00, | ||
274 | 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c, | ||
275 | 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50, | ||
276 | 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00, | ||
277 | 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9, | ||
278 | 0xd2, 0xeb, | ||
279 | 0xaf, 1, 0x02, | ||
280 | 0xb5, 2, 0x08, 0x08, | ||
281 | 0xb8, 2, 0x08, 0x88, | ||
282 | 0xc4, 4, 0xae, 0x01, 0x04, 0x01, | ||
283 | 0xcc, 1, 0x00, | ||
284 | 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9, | ||
285 | 0xc1, 0xd7, 0xec, | ||
286 | 0xdc, 1, 0x01, | ||
287 | 0xff, 1, 0x01, /* page 1 */ | ||
288 | 0x12, 3, 0x02, 0x00, 0x01, | ||
289 | 0x3e, 2, 0x00, 0x00, | ||
290 | 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2, | ||
291 | 0x7c, 1, 0x00, | ||
292 | 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20, | ||
293 | 0x02, 0x00, | ||
294 | 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04, | ||
295 | 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, | ||
296 | 0x07, 0x00, 0x01, 0x07, 0x04, 0x01, | ||
297 | 0xd8, 1, 0x01, | ||
298 | 0xdb, 2, 0x00, 0x01, | ||
299 | 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00, | ||
300 | 0xe6, 4, 0x00, 0x00, 0x00, 0x01, | ||
301 | 0xeb, 1, 0x00, | ||
302 | 0xff, 1, 0x02, /* page 2 */ | ||
303 | 0x22, 1, 0x00, | ||
304 | 0xff, 1, 0x03, /* page 3 */ | ||
305 | 0x00, 255, /* load the page 3 */ | ||
306 | 0x11, 1, 0x01, | ||
307 | 0xff, 1, 0x02, /* page 2 */ | ||
308 | 0x13, 1, 0x00, | ||
309 | 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96, | ||
310 | 0x27, 2, 0x14, 0x0c, | ||
311 | 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22, | ||
312 | 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44, | ||
313 | 0x6e, 1, 0x08, | ||
314 | 0xff, 1, 0x01, /* page 1 */ | ||
315 | 0x78, 1, 0x00, | ||
316 | 0, 0 /* end of sequence */ | ||
317 | }; | ||
318 | |||
319 | /* page 3 - the value 0xaa says skip the index - see reg_w_page() */ | ||
320 | static const __u8 page3_7302[] = { | ||
321 | 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16, | ||
322 | 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00, | ||
323 | 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
324 | 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00, | ||
325 | 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21, | ||
326 | 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54, | ||
327 | 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00, | ||
328 | 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
329 | 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00, | ||
330 | 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00, | ||
331 | 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
332 | 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00, | ||
333 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
334 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8, | ||
335 | 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, | ||
336 | 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, | ||
337 | 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00, | ||
338 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
339 | 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00, | ||
340 | 0x00 | ||
341 | }; | ||
342 | 206 | ||
343 | /* pac 7311 */ | 207 | /* pac 7311 */ |
344 | static const __u8 init_7311[] = { | 208 | static const __u8 init_7311[] = { |
@@ -378,119 +242,154 @@ static const __u8 start_7311[] = { | |||
378 | 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00, | 242 | 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00, |
379 | 0x3f, 0x00, 0x0a, 0x01, 0x00, | 243 | 0x3f, 0x00, 0x0a, 0x01, 0x00, |
380 | 0xff, 1, 0x04, /* page 4 */ | 244 | 0xff, 1, 0x04, /* page 4 */ |
381 | 0x00, 254, /* load the page 4 */ | 245 | 0, LOAD_PAGE4, /* load the page 4 */ |
382 | 0x11, 1, 0x01, | 246 | 0x11, 1, 0x01, |
383 | 0, 0 /* end of sequence */ | 247 | 0, END_OF_SEQUENCE /* end of sequence */ |
384 | }; | 248 | }; |
385 | 249 | ||
386 | /* page 4 - the value 0xaa says skip the index - see reg_w_page() */ | 250 | #define SKIP 0xaa |
251 | /* page 4 - the value SKIP says skip the index - see reg_w_page() */ | ||
387 | static const __u8 page4_7311[] = { | 252 | static const __u8 page4_7311[] = { |
388 | 0xaa, 0xaa, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f, | 253 | SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f, |
389 | 0x09, 0x00, 0xaa, 0xaa, 0x07, 0x00, 0x00, 0x62, | 254 | 0x09, 0x00, SKIP, SKIP, 0x07, 0x00, 0x00, 0x62, |
390 | 0x08, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, | 255 | 0x08, SKIP, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, |
391 | 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, 0xaa, | 256 | 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP, |
392 | 0xaa, 0x00, 0x08, 0xaa, 0x03, 0xaa, 0x00, 0x68, | 257 | SKIP, 0x00, 0x08, SKIP, 0x03, SKIP, 0x00, 0x68, |
393 | 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00, | 258 | 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00, |
394 | 0x23, 0x28, 0x04, 0x11, 0x00, 0x00 | 259 | 0x23, 0x28, 0x04, 0x11, 0x00, 0x00 |
395 | }; | 260 | }; |
396 | 261 | ||
397 | static void reg_w_buf(struct gspca_dev *gspca_dev, | 262 | static int reg_w_buf(struct gspca_dev *gspca_dev, |
398 | __u8 index, | 263 | __u8 index, |
399 | const char *buffer, int len) | 264 | const char *buffer, int len) |
400 | { | 265 | { |
266 | int ret; | ||
267 | |||
401 | memcpy(gspca_dev->usb_buf, buffer, len); | 268 | memcpy(gspca_dev->usb_buf, buffer, len); |
402 | usb_control_msg(gspca_dev->dev, | 269 | ret = usb_control_msg(gspca_dev->dev, |
403 | usb_sndctrlpipe(gspca_dev->dev, 0), | 270 | usb_sndctrlpipe(gspca_dev->dev, 0), |
404 | 1, /* request */ | 271 | 1, /* request */ |
405 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 272 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
406 | 0, /* value */ | 273 | 0, /* value */ |
407 | index, gspca_dev->usb_buf, len, | 274 | index, gspca_dev->usb_buf, len, |
408 | 500); | 275 | 500); |
276 | if (ret < 0) | ||
277 | PDEBUG(D_ERR, "reg_w_buf(): " | ||
278 | "Failed to write registers to index 0x%x, error %i", | ||
279 | index, ret); | ||
280 | return ret; | ||
409 | } | 281 | } |
410 | 282 | ||
411 | 283 | ||
412 | static void reg_w(struct gspca_dev *gspca_dev, | 284 | static int reg_w(struct gspca_dev *gspca_dev, |
413 | __u8 index, | 285 | __u8 index, |
414 | __u8 value) | 286 | __u8 value) |
415 | { | 287 | { |
288 | int ret; | ||
289 | |||
416 | gspca_dev->usb_buf[0] = value; | 290 | gspca_dev->usb_buf[0] = value; |
417 | usb_control_msg(gspca_dev->dev, | 291 | ret = usb_control_msg(gspca_dev->dev, |
418 | usb_sndctrlpipe(gspca_dev->dev, 0), | 292 | usb_sndctrlpipe(gspca_dev->dev, 0), |
419 | 0, /* request */ | 293 | 0, /* request */ |
420 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 294 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
421 | 0, index, gspca_dev->usb_buf, 1, | 295 | 0, index, gspca_dev->usb_buf, 1, |
422 | 500); | 296 | 500); |
297 | if (ret < 0) | ||
298 | PDEBUG(D_ERR, "reg_w(): " | ||
299 | "Failed to write register to index 0x%x, value 0x%x, error %i", | ||
300 | index, value, ret); | ||
301 | return ret; | ||
423 | } | 302 | } |
424 | 303 | ||
425 | static void reg_w_seq(struct gspca_dev *gspca_dev, | 304 | static int reg_w_seq(struct gspca_dev *gspca_dev, |
426 | const __u8 *seq, int len) | 305 | const __u8 *seq, int len) |
427 | { | 306 | { |
307 | int ret = 0; | ||
428 | while (--len >= 0) { | 308 | while (--len >= 0) { |
429 | reg_w(gspca_dev, seq[0], seq[1]); | 309 | if (0 <= ret) |
310 | ret = reg_w(gspca_dev, seq[0], seq[1]); | ||
430 | seq += 2; | 311 | seq += 2; |
431 | } | 312 | } |
313 | return ret; | ||
432 | } | 314 | } |
433 | 315 | ||
434 | /* load the beginning of a page */ | 316 | /* load the beginning of a page */ |
435 | static void reg_w_page(struct gspca_dev *gspca_dev, | 317 | static int reg_w_page(struct gspca_dev *gspca_dev, |
436 | const __u8 *page, int len) | 318 | const __u8 *page, int len) |
437 | { | 319 | { |
438 | int index; | 320 | int index; |
321 | int ret = 0; | ||
439 | 322 | ||
440 | for (index = 0; index < len; index++) { | 323 | for (index = 0; index < len; index++) { |
441 | if (page[index] == 0xaa) /* skip this index */ | 324 | if (page[index] == SKIP) /* skip this index */ |
442 | continue; | 325 | continue; |
443 | gspca_dev->usb_buf[0] = page[index]; | 326 | gspca_dev->usb_buf[0] = page[index]; |
444 | usb_control_msg(gspca_dev->dev, | 327 | ret = usb_control_msg(gspca_dev->dev, |
445 | usb_sndctrlpipe(gspca_dev->dev, 0), | 328 | usb_sndctrlpipe(gspca_dev->dev, 0), |
446 | 0, /* request */ | 329 | 0, /* request */ |
447 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 330 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
448 | 0, index, gspca_dev->usb_buf, 1, | 331 | 0, index, gspca_dev->usb_buf, 1, |
449 | 500); | 332 | 500); |
333 | if (ret < 0) { | ||
334 | PDEBUG(D_ERR, "reg_w_page(): " | ||
335 | "Failed to write register to index 0x%x, " | ||
336 | "value 0x%x, error %i", | ||
337 | index, page[index], ret); | ||
338 | break; | ||
339 | } | ||
450 | } | 340 | } |
341 | return ret; | ||
451 | } | 342 | } |
452 | 343 | ||
453 | /* output a variable sequence */ | 344 | /* output a variable sequence */ |
454 | static void reg_w_var(struct gspca_dev *gspca_dev, | 345 | static int reg_w_var(struct gspca_dev *gspca_dev, |
455 | const __u8 *seq) | 346 | const __u8 *seq, |
347 | const __u8 *page3, unsigned int page3_len, | ||
348 | const __u8 *page4, unsigned int page4_len) | ||
456 | { | 349 | { |
457 | int index, len; | 350 | int index, len; |
351 | int ret = 0; | ||
458 | 352 | ||
459 | for (;;) { | 353 | for (;;) { |
460 | index = *seq++; | 354 | index = *seq++; |
461 | len = *seq++; | 355 | len = *seq++; |
462 | switch (len) { | 356 | switch (len) { |
463 | case 0: | 357 | case END_OF_SEQUENCE: |
464 | return; | 358 | return ret; |
465 | case 254: | 359 | case LOAD_PAGE4: |
466 | reg_w_page(gspca_dev, page4_7311, sizeof page4_7311); | 360 | ret = reg_w_page(gspca_dev, page4, page4_len); |
467 | break; | 361 | break; |
468 | case 255: | 362 | case LOAD_PAGE3: |
469 | reg_w_page(gspca_dev, page3_7302, sizeof page3_7302); | 363 | ret = reg_w_page(gspca_dev, page3, page3_len); |
470 | break; | 364 | break; |
471 | default: | 365 | default: |
472 | if (len > 64) { | 366 | if (len > USB_BUF_SZ) { |
473 | PDEBUG(D_ERR|D_STREAM, | 367 | PDEBUG(D_ERR|D_STREAM, |
474 | "Incorrect variable sequence"); | 368 | "Incorrect variable sequence"); |
475 | return; | 369 | return -EINVAL; |
476 | } | 370 | } |
477 | while (len > 0) { | 371 | while (len > 0) { |
478 | if (len < 8) { | 372 | if (len < 8) { |
479 | reg_w_buf(gspca_dev, index, seq, len); | 373 | ret = reg_w_buf(gspca_dev, |
374 | index, seq, len); | ||
375 | if (ret < 0) | ||
376 | return ret; | ||
480 | seq += len; | 377 | seq += len; |
481 | break; | 378 | break; |
482 | } | 379 | } |
483 | reg_w_buf(gspca_dev, index, seq, 8); | 380 | ret = reg_w_buf(gspca_dev, index, seq, 8); |
484 | seq += 8; | 381 | seq += 8; |
485 | index += 8; | 382 | index += 8; |
486 | len -= 8; | 383 | len -= 8; |
487 | } | 384 | } |
488 | } | 385 | } |
386 | if (ret < 0) | ||
387 | return ret; | ||
489 | } | 388 | } |
490 | /* not reached */ | 389 | /* not reached */ |
491 | } | 390 | } |
492 | 391 | ||
493 | /* this function is called at probe time */ | 392 | /* this function is called at probe time for pac7311 */ |
494 | static int sd_config(struct gspca_dev *gspca_dev, | 393 | static int sd_config(struct gspca_dev *gspca_dev, |
495 | const struct usb_device_id *id) | 394 | const struct usb_device_id *id) |
496 | { | 395 | { |
@@ -499,22 +398,11 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
499 | 398 | ||
500 | cam = &gspca_dev->cam; | 399 | cam = &gspca_dev->cam; |
501 | 400 | ||
502 | sd->sensor = id->driver_info; | 401 | PDEBUG(D_CONF, "Find Sensor PAC7311"); |
503 | if (sd->sensor == SENSOR_PAC7302) { | 402 | cam->cam_mode = vga_mode; |
504 | PDEBUG(D_CONF, "Find Sensor PAC7302"); | 403 | cam->nmodes = ARRAY_SIZE(vga_mode); |
505 | cam->cam_mode = &vga_mode[2]; /* only 640x480 */ | ||
506 | cam->nmodes = 1; | ||
507 | } else { | ||
508 | PDEBUG(D_CONF, "Find Sensor PAC7311"); | ||
509 | cam->cam_mode = vga_mode; | ||
510 | cam->nmodes = ARRAY_SIZE(vga_mode); | ||
511 | gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) | ||
512 | | (1 << SATURATION_IDX); | ||
513 | } | ||
514 | 404 | ||
515 | sd->brightness = BRIGHTNESS_DEF; | ||
516 | sd->contrast = CONTRAST_DEF; | 405 | sd->contrast = CONTRAST_DEF; |
517 | sd->colors = COLOR_DEF; | ||
518 | sd->gain = GAIN_DEF; | 406 | sd->gain = GAIN_DEF; |
519 | sd->exposure = EXPOSURE_DEF; | 407 | sd->exposure = EXPOSURE_DEF; |
520 | sd->autogain = AUTOGAIN_DEF; | 408 | sd->autogain = AUTOGAIN_DEF; |
@@ -523,91 +411,47 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
523 | return 0; | 411 | return 0; |
524 | } | 412 | } |
525 | 413 | ||
526 | /* This function is used by pac7302 only */ | ||
527 | static void setbrightcont(struct gspca_dev *gspca_dev) | ||
528 | { | ||
529 | struct sd *sd = (struct sd *) gspca_dev; | ||
530 | int i, v; | ||
531 | static const __u8 max[10] = | ||
532 | {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb, | ||
533 | 0xd4, 0xec}; | ||
534 | static const __u8 delta[10] = | ||
535 | {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17, | ||
536 | 0x11, 0x0b}; | ||
537 | |||
538 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | ||
539 | for (i = 0; i < 10; i++) { | ||
540 | v = max[i]; | ||
541 | v += (sd->brightness - BRIGHTNESS_MAX) | ||
542 | * 150 / BRIGHTNESS_MAX; /* 200 ? */ | ||
543 | v -= delta[i] * sd->contrast / CONTRAST_MAX; | ||
544 | if (v < 0) | ||
545 | v = 0; | ||
546 | else if (v > 0xff) | ||
547 | v = 0xff; | ||
548 | reg_w(gspca_dev, 0xa2 + i, v); | ||
549 | } | ||
550 | reg_w(gspca_dev, 0xdc, 0x01); | ||
551 | } | ||
552 | |||
553 | /* This function is used by pac7311 only */ | 414 | /* This function is used by pac7311 only */ |
554 | static void setcontrast(struct gspca_dev *gspca_dev) | 415 | static int setcontrast(struct gspca_dev *gspca_dev) |
555 | { | 416 | { |
556 | struct sd *sd = (struct sd *) gspca_dev; | 417 | struct sd *sd = (struct sd *) gspca_dev; |
418 | int ret; | ||
557 | 419 | ||
558 | reg_w(gspca_dev, 0xff, 0x04); | 420 | ret = reg_w(gspca_dev, 0xff, 0x04); |
559 | reg_w(gspca_dev, 0x10, sd->contrast >> 4); | 421 | if (0 <= ret) |
422 | ret = reg_w(gspca_dev, 0x10, sd->contrast >> 4); | ||
560 | /* load registers to sensor (Bit 0, auto clear) */ | 423 | /* load registers to sensor (Bit 0, auto clear) */ |
561 | reg_w(gspca_dev, 0x11, 0x01); | 424 | if (0 <= ret) |
425 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
426 | return ret; | ||
562 | } | 427 | } |
563 | 428 | ||
564 | /* This function is used by pac7302 only */ | 429 | static int setgain(struct gspca_dev *gspca_dev) |
565 | static void setcolors(struct gspca_dev *gspca_dev) | ||
566 | { | 430 | { |
567 | struct sd *sd = (struct sd *) gspca_dev; | 431 | struct sd *sd = (struct sd *) gspca_dev; |
568 | int i, v; | 432 | int gain = GAIN_MAX - sd->gain; |
569 | static const int a[9] = | 433 | int ret; |
570 | {217, -212, 0, -101, 170, -67, -38, -315, 355}; | ||
571 | static const int b[9] = | ||
572 | {19, 106, 0, 19, 106, 1, 19, 106, 1}; | ||
573 | |||
574 | reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | ||
575 | reg_w(gspca_dev, 0x11, 0x01); | ||
576 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | ||
577 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | ||
578 | for (i = 0; i < 9; i++) { | ||
579 | v = a[i] * sd->colors / COLOR_MAX + b[i]; | ||
580 | reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); | ||
581 | reg_w(gspca_dev, 0x0f + 2 * i + 1, v); | ||
582 | } | ||
583 | reg_w(gspca_dev, 0xdc, 0x01); | ||
584 | PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); | ||
585 | } | ||
586 | 434 | ||
587 | static void setgain(struct gspca_dev *gspca_dev) | 435 | if (gain < 1) |
588 | { | 436 | gain = 1; |
589 | struct sd *sd = (struct sd *) gspca_dev; | 437 | else if (gain > 245) |
438 | gain = 245; | ||
439 | ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ | ||
440 | if (0 <= ret) | ||
441 | ret = reg_w(gspca_dev, 0x0e, 0x00); | ||
442 | if (0 <= ret) | ||
443 | ret = reg_w(gspca_dev, 0x0f, gain); | ||
590 | 444 | ||
591 | if (sd->sensor == SENSOR_PAC7302) { | ||
592 | reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | ||
593 | reg_w(gspca_dev, 0x10, sd->gain >> 3); | ||
594 | } else { | ||
595 | int gain = GAIN_MAX - sd->gain; | ||
596 | if (gain < 1) | ||
597 | gain = 1; | ||
598 | else if (gain > 245) | ||
599 | gain = 245; | ||
600 | reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ | ||
601 | reg_w(gspca_dev, 0x0e, 0x00); | ||
602 | reg_w(gspca_dev, 0x0f, gain); | ||
603 | } | ||
604 | /* load registers to sensor (Bit 0, auto clear) */ | 445 | /* load registers to sensor (Bit 0, auto clear) */ |
605 | reg_w(gspca_dev, 0x11, 0x01); | 446 | if (0 <= ret) |
447 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
448 | return ret; | ||
606 | } | 449 | } |
607 | 450 | ||
608 | static void setexposure(struct gspca_dev *gspca_dev) | 451 | static int setexposure(struct gspca_dev *gspca_dev) |
609 | { | 452 | { |
610 | struct sd *sd = (struct sd *) gspca_dev; | 453 | struct sd *sd = (struct sd *) gspca_dev; |
454 | int ret; | ||
611 | __u8 reg; | 455 | __u8 reg; |
612 | 456 | ||
613 | /* register 2 of frame 3/4 contains the clock divider configuring the | 457 | /* register 2 of frame 3/4 contains the clock divider configuring the |
@@ -619,97 +463,94 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
619 | else if (reg > 63) | 463 | else if (reg > 63) |
620 | reg = 63; | 464 | reg = 63; |
621 | 465 | ||
622 | if (sd->sensor == SENSOR_PAC7302) { | 466 | ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ |
623 | /* On the pac7302 reg2 MUST be a multiple of 3, so round it to | 467 | if (0 <= ret) |
624 | the nearest multiple of 3, except when between 6 and 12? */ | 468 | ret = reg_w(gspca_dev, 0x02, reg); |
625 | if (reg < 6 || reg > 12) | 469 | /* Page 1 register 8 must always be 0x08 except when not in |
626 | reg = ((reg + 1) / 3) * 3; | 470 | 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */ |
627 | reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | 471 | if (0 <= ret) |
628 | reg_w(gspca_dev, 0x02, reg); | 472 | ret = reg_w(gspca_dev, 0xff, 0x01); |
473 | if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv && | ||
474 | reg <= 3) { | ||
475 | if (0 <= ret) | ||
476 | ret = reg_w(gspca_dev, 0x08, 0x09); | ||
629 | } else { | 477 | } else { |
630 | reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ | 478 | if (0 <= ret) |
631 | reg_w(gspca_dev, 0x02, reg); | 479 | ret = reg_w(gspca_dev, 0x08, 0x08); |
632 | /* Page 1 register 8 must always be 0x08 except when not in | ||
633 | 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */ | ||
634 | reg_w(gspca_dev, 0xff, 0x01); | ||
635 | if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv && | ||
636 | reg <= 3) | ||
637 | reg_w(gspca_dev, 0x08, 0x09); | ||
638 | else | ||
639 | reg_w(gspca_dev, 0x08, 0x08); | ||
640 | } | 480 | } |
481 | |||
641 | /* load registers to sensor (Bit 0, auto clear) */ | 482 | /* load registers to sensor (Bit 0, auto clear) */ |
642 | reg_w(gspca_dev, 0x11, 0x01); | 483 | if (0 <= ret) |
484 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
485 | return ret; | ||
643 | } | 486 | } |
644 | 487 | ||
645 | static void sethvflip(struct gspca_dev *gspca_dev) | 488 | static int sethvflip(struct gspca_dev *gspca_dev) |
646 | { | 489 | { |
647 | struct sd *sd = (struct sd *) gspca_dev; | 490 | struct sd *sd = (struct sd *) gspca_dev; |
491 | int ret; | ||
648 | __u8 data; | 492 | __u8 data; |
649 | 493 | ||
650 | if (sd->sensor == SENSOR_PAC7302) { | 494 | ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ |
651 | reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | 495 | data = (sd->hflip ? 0x04 : 0x00) | (sd->vflip ? 0x08 : 0x00); |
652 | data = (sd->hflip ? 0x08 : 0x00) | 496 | if (0 <= ret) |
653 | | (sd->vflip ? 0x04 : 0x00); | 497 | ret = reg_w(gspca_dev, 0x21, data); |
654 | } else { | ||
655 | reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ | ||
656 | data = (sd->hflip ? 0x04 : 0x00) | ||
657 | | (sd->vflip ? 0x08 : 0x00); | ||
658 | } | ||
659 | reg_w(gspca_dev, 0x21, data); | ||
660 | /* load registers to sensor (Bit 0, auto clear) */ | 498 | /* load registers to sensor (Bit 0, auto clear) */ |
661 | reg_w(gspca_dev, 0x11, 0x01); | 499 | if (0 <= ret) |
500 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
501 | return ret; | ||
662 | } | 502 | } |
663 | 503 | ||
664 | /* this function is called at probe and resume time */ | 504 | /* this function is called at probe and resume time for pac7311 */ |
665 | static int sd_init(struct gspca_dev *gspca_dev) | 505 | static int sd_init(struct gspca_dev *gspca_dev) |
666 | { | 506 | { |
667 | struct sd *sd = (struct sd *) gspca_dev; | 507 | return reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2); |
668 | |||
669 | if (sd->sensor == SENSOR_PAC7302) | ||
670 | reg_w_seq(gspca_dev, init_7302, sizeof init_7302); | ||
671 | else | ||
672 | reg_w_seq(gspca_dev, init_7311, sizeof init_7311); | ||
673 | |||
674 | return 0; | ||
675 | } | 508 | } |
676 | 509 | ||
677 | static int sd_start(struct gspca_dev *gspca_dev) | 510 | static int sd_start(struct gspca_dev *gspca_dev) |
678 | { | 511 | { |
679 | struct sd *sd = (struct sd *) gspca_dev; | 512 | struct sd *sd = (struct sd *) gspca_dev; |
513 | int ret; | ||
680 | 514 | ||
681 | sd->sof_read = 0; | 515 | sd->sof_read = 0; |
682 | 516 | ||
683 | if (sd->sensor == SENSOR_PAC7302) { | 517 | ret = reg_w_var(gspca_dev, start_7311, |
684 | reg_w_var(gspca_dev, start_7302); | 518 | NULL, 0, |
685 | setbrightcont(gspca_dev); | 519 | page4_7311, sizeof(page4_7311)); |
686 | setcolors(gspca_dev); | 520 | if (0 <= ret) |
687 | } else { | 521 | ret = setcontrast(gspca_dev); |
688 | reg_w_var(gspca_dev, start_7311); | 522 | if (0 <= ret) |
689 | setcontrast(gspca_dev); | 523 | ret = setgain(gspca_dev); |
690 | } | 524 | if (0 <= ret) |
691 | setgain(gspca_dev); | 525 | ret = setexposure(gspca_dev); |
692 | setexposure(gspca_dev); | 526 | if (0 <= ret) |
693 | sethvflip(gspca_dev); | 527 | ret = sethvflip(gspca_dev); |
694 | 528 | ||
695 | /* set correct resolution */ | 529 | /* set correct resolution */ |
696 | switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { | 530 | switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { |
697 | case 2: /* 160x120 pac7311 */ | 531 | case 2: /* 160x120 pac7311 */ |
698 | reg_w(gspca_dev, 0xff, 0x01); | 532 | if (0 <= ret) |
699 | reg_w(gspca_dev, 0x17, 0x20); | 533 | ret = reg_w(gspca_dev, 0xff, 0x01); |
700 | reg_w(gspca_dev, 0x87, 0x10); | 534 | if (0 <= ret) |
535 | ret = reg_w(gspca_dev, 0x17, 0x20); | ||
536 | if (0 <= ret) | ||
537 | ret = reg_w(gspca_dev, 0x87, 0x10); | ||
701 | break; | 538 | break; |
702 | case 1: /* 320x240 pac7311 */ | 539 | case 1: /* 320x240 pac7311 */ |
703 | reg_w(gspca_dev, 0xff, 0x01); | 540 | if (0 <= ret) |
704 | reg_w(gspca_dev, 0x17, 0x30); | 541 | ret = reg_w(gspca_dev, 0xff, 0x01); |
705 | reg_w(gspca_dev, 0x87, 0x11); | 542 | if (0 <= ret) |
543 | ret = reg_w(gspca_dev, 0x17, 0x30); | ||
544 | if (0 <= ret) | ||
545 | ret = reg_w(gspca_dev, 0x87, 0x11); | ||
706 | break; | 546 | break; |
707 | case 0: /* 640x480 */ | 547 | case 0: /* 640x480 */ |
708 | if (sd->sensor == SENSOR_PAC7302) | 548 | if (0 <= ret) |
709 | break; | 549 | ret = reg_w(gspca_dev, 0xff, 0x01); |
710 | reg_w(gspca_dev, 0xff, 0x01); | 550 | if (0 <= ret) |
711 | reg_w(gspca_dev, 0x17, 0x00); | 551 | ret = reg_w(gspca_dev, 0x17, 0x00); |
712 | reg_w(gspca_dev, 0x87, 0x12); | 552 | if (0 <= ret) |
553 | ret = reg_w(gspca_dev, 0x87, 0x12); | ||
713 | break; | 554 | break; |
714 | } | 555 | } |
715 | 556 | ||
@@ -718,47 +559,42 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
718 | atomic_set(&sd->avg_lum, -1); | 559 | atomic_set(&sd->avg_lum, -1); |
719 | 560 | ||
720 | /* start stream */ | 561 | /* start stream */ |
721 | reg_w(gspca_dev, 0xff, 0x01); | 562 | if (0 <= ret) |
722 | if (sd->sensor == SENSOR_PAC7302) | 563 | ret = reg_w(gspca_dev, 0xff, 0x01); |
723 | reg_w(gspca_dev, 0x78, 0x01); | 564 | if (0 <= ret) |
724 | else | 565 | ret = reg_w(gspca_dev, 0x78, 0x05); |
725 | reg_w(gspca_dev, 0x78, 0x05); | 566 | |
726 | return 0; | 567 | return ret; |
727 | } | 568 | } |
728 | 569 | ||
729 | static void sd_stopN(struct gspca_dev *gspca_dev) | 570 | static void sd_stopN(struct gspca_dev *gspca_dev) |
730 | { | 571 | { |
731 | struct sd *sd = (struct sd *) gspca_dev; | 572 | int ret; |
732 | |||
733 | if (sd->sensor == SENSOR_PAC7302) { | ||
734 | reg_w(gspca_dev, 0xff, 0x01); | ||
735 | reg_w(gspca_dev, 0x78, 0x00); | ||
736 | reg_w(gspca_dev, 0x78, 0x00); | ||
737 | return; | ||
738 | } | ||
739 | reg_w(gspca_dev, 0xff, 0x04); | ||
740 | reg_w(gspca_dev, 0x27, 0x80); | ||
741 | reg_w(gspca_dev, 0x28, 0xca); | ||
742 | reg_w(gspca_dev, 0x29, 0x53); | ||
743 | reg_w(gspca_dev, 0x2a, 0x0e); | ||
744 | reg_w(gspca_dev, 0xff, 0x01); | ||
745 | reg_w(gspca_dev, 0x3e, 0x20); | ||
746 | reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ | ||
747 | reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ | ||
748 | reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ | ||
749 | } | ||
750 | 573 | ||
751 | /* called on streamoff with alt 0 and on disconnect */ | 574 | ret = reg_w(gspca_dev, 0xff, 0x04); |
575 | if (0 <= ret) | ||
576 | ret = reg_w(gspca_dev, 0x27, 0x80); | ||
577 | if (0 <= ret) | ||
578 | ret = reg_w(gspca_dev, 0x28, 0xca); | ||
579 | if (0 <= ret) | ||
580 | ret = reg_w(gspca_dev, 0x29, 0x53); | ||
581 | if (0 <= ret) | ||
582 | ret = reg_w(gspca_dev, 0x2a, 0x0e); | ||
583 | if (0 <= ret) | ||
584 | ret = reg_w(gspca_dev, 0xff, 0x01); | ||
585 | if (0 <= ret) | ||
586 | ret = reg_w(gspca_dev, 0x3e, 0x20); | ||
587 | if (0 <= ret) | ||
588 | ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ | ||
589 | if (0 <= ret) | ||
590 | ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ | ||
591 | if (0 <= ret) | ||
592 | ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ | ||
593 | } | ||
594 | |||
595 | /* called on streamoff with alt 0 and on disconnect for 7311 */ | ||
752 | static void sd_stop0(struct gspca_dev *gspca_dev) | 596 | static void sd_stop0(struct gspca_dev *gspca_dev) |
753 | { | 597 | { |
754 | struct sd *sd = (struct sd *) gspca_dev; | ||
755 | |||
756 | if (!gspca_dev->present) | ||
757 | return; | ||
758 | if (sd->sensor == SENSOR_PAC7302) { | ||
759 | reg_w(gspca_dev, 0xff, 0x01); | ||
760 | reg_w(gspca_dev, 0x78, 0x40); | ||
761 | } | ||
762 | } | 598 | } |
763 | 599 | ||
764 | /* Include pac common sof detection functions */ | 600 | /* Include pac common sof detection functions */ |
@@ -773,22 +609,8 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
773 | if (avg_lum == -1) | 609 | if (avg_lum == -1) |
774 | return; | 610 | return; |
775 | 611 | ||
776 | if (sd->sensor == SENSOR_PAC7302) { | 612 | desired_lum = 200; |
777 | desired_lum = 270 + sd->brightness * 4; | 613 | deadzone = 20; |
778 | /* Hack hack, with the 7202 the first exposure step is | ||
779 | pretty large, so if we're about to make the first | ||
780 | exposure increase make the deadzone large to avoid | ||
781 | oscilating */ | ||
782 | if (desired_lum > avg_lum && sd->gain == GAIN_DEF && | ||
783 | sd->exposure > EXPOSURE_DEF && | ||
784 | sd->exposure < 42) | ||
785 | deadzone = 90; | ||
786 | else | ||
787 | deadzone = 30; | ||
788 | } else { | ||
789 | desired_lum = 200; | ||
790 | deadzone = 20; | ||
791 | } | ||
792 | 614 | ||
793 | if (sd->autogain_ignore_frames > 0) | 615 | if (sd->autogain_ignore_frames > 0) |
794 | sd->autogain_ignore_frames--; | 616 | sd->autogain_ignore_frames--; |
@@ -797,53 +619,92 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
797 | sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; | 619 | sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; |
798 | } | 620 | } |
799 | 621 | ||
800 | static const unsigned char pac7311_jpeg_header1[] = { | 622 | /* JPEG header, part 1 */ |
801 | 0xff, 0xd8, 0xff, 0xc0, 0x00, 0x11, 0x08 | 623 | static const unsigned char pac_jpeg_header1[] = { |
624 | 0xff, 0xd8, /* SOI: Start of Image */ | ||
625 | |||
626 | 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */ | ||
627 | 0x00, 0x11, /* length = 17 bytes (including this length field) */ | ||
628 | 0x08 /* Precision: 8 */ | ||
629 | /* 2 bytes is placed here: number of image lines */ | ||
630 | /* 2 bytes is placed here: samples per line */ | ||
802 | }; | 631 | }; |
803 | 632 | ||
804 | static const unsigned char pac7311_jpeg_header2[] = { | 633 | /* JPEG header, continued */ |
805 | 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda, | 634 | static const unsigned char pac_jpeg_header2[] = { |
806 | 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00 | 635 | 0x03, /* Number of image components: 3 */ |
636 | 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */ | ||
637 | 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */ | ||
638 | 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */ | ||
639 | |||
640 | 0xff, 0xda, /* SOS: Start Of Scan */ | ||
641 | 0x00, 0x0c, /* length = 12 bytes (including this length field) */ | ||
642 | 0x03, /* number of components: 3 */ | ||
643 | 0x01, 0x00, /* selector 1, table 0x00 */ | ||
644 | 0x02, 0x11, /* selector 2, table 0x11 */ | ||
645 | 0x03, 0x11, /* selector 3, table 0x11 */ | ||
646 | 0x00, 0x3f, /* Spectral selection: 0 .. 63 */ | ||
647 | 0x00 /* Successive approximation: 0 */ | ||
807 | }; | 648 | }; |
808 | 649 | ||
650 | static void pac_start_frame(struct gspca_dev *gspca_dev, | ||
651 | struct gspca_frame *frame, | ||
652 | __u16 lines, __u16 samples_per_line) | ||
653 | { | ||
654 | unsigned char tmpbuf[4]; | ||
655 | |||
656 | gspca_frame_add(gspca_dev, FIRST_PACKET, | ||
657 | pac_jpeg_header1, sizeof(pac_jpeg_header1)); | ||
658 | |||
659 | tmpbuf[0] = lines >> 8; | ||
660 | tmpbuf[1] = lines & 0xff; | ||
661 | tmpbuf[2] = samples_per_line >> 8; | ||
662 | tmpbuf[3] = samples_per_line & 0xff; | ||
663 | |||
664 | gspca_frame_add(gspca_dev, INTER_PACKET, | ||
665 | tmpbuf, sizeof(tmpbuf)); | ||
666 | gspca_frame_add(gspca_dev, INTER_PACKET, | ||
667 | pac_jpeg_header2, sizeof(pac_jpeg_header2)); | ||
668 | } | ||
669 | |||
809 | /* this function is run at interrupt level */ | 670 | /* this function is run at interrupt level */ |
810 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 671 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
811 | struct gspca_frame *frame, /* target */ | 672 | u8 *data, /* isoc packet */ |
812 | __u8 *data, /* isoc packet */ | ||
813 | int len) /* iso packet length */ | 673 | int len) /* iso packet length */ |
814 | { | 674 | { |
815 | struct sd *sd = (struct sd *) gspca_dev; | 675 | struct sd *sd = (struct sd *) gspca_dev; |
816 | unsigned char *sof; | 676 | unsigned char *sof; |
677 | struct gspca_frame *frame; | ||
817 | 678 | ||
818 | sof = pac_find_sof(gspca_dev, data, len); | 679 | sof = pac_find_sof(&sd->sof_read, data, len); |
819 | if (sof) { | 680 | if (sof) { |
820 | unsigned char tmpbuf[4]; | ||
821 | int n, lum_offset, footer_length; | 681 | int n, lum_offset, footer_length; |
822 | 682 | ||
823 | if (sd->sensor == SENSOR_PAC7302) { | 683 | frame = gspca_get_i_frame(gspca_dev); |
824 | /* 6 bytes after the FF D9 EOF marker a number of lumination | 684 | if (frame == NULL) { |
825 | bytes are send corresponding to different parts of the | 685 | gspca_dev->last_packet_type = DISCARD_PACKET; |
826 | image, the 14th and 15th byte after the EOF seem to | 686 | return; |
827 | correspond to the center of the image */ | ||
828 | lum_offset = 61 + sizeof pac_sof_marker; | ||
829 | footer_length = 74; | ||
830 | } else { | ||
831 | lum_offset = 24 + sizeof pac_sof_marker; | ||
832 | footer_length = 26; | ||
833 | } | 687 | } |
834 | 688 | ||
689 | /* 6 bytes after the FF D9 EOF marker a number of lumination | ||
690 | bytes are send corresponding to different parts of the | ||
691 | image, the 14th and 15th byte after the EOF seem to | ||
692 | correspond to the center of the image */ | ||
693 | lum_offset = 24 + sizeof pac_sof_marker; | ||
694 | footer_length = 26; | ||
695 | |||
835 | /* Finish decoding current frame */ | 696 | /* Finish decoding current frame */ |
836 | n = (sof - data) - (footer_length + sizeof pac_sof_marker); | 697 | n = (sof - data) - (footer_length + sizeof pac_sof_marker); |
837 | if (n < 0) { | 698 | if (n < 0) { |
838 | frame->data_end += n; | 699 | frame->data_end += n; |
839 | n = 0; | 700 | n = 0; |
840 | } | 701 | } |
841 | frame = gspca_frame_add(gspca_dev, INTER_PACKET, frame, | 702 | gspca_frame_add(gspca_dev, INTER_PACKET, |
842 | data, n); | 703 | data, n); |
843 | if (gspca_dev->last_packet_type != DISCARD_PACKET && | 704 | if (gspca_dev->last_packet_type != DISCARD_PACKET && |
844 | frame->data_end[-2] == 0xff && | 705 | frame->data_end[-2] == 0xff && |
845 | frame->data_end[-1] == 0xd9) | 706 | frame->data_end[-1] == 0xd9) |
846 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | 707 | gspca_frame_add(gspca_dev, LAST_PACKET, |
847 | NULL, 0); | 708 | NULL, 0); |
848 | 709 | ||
849 | n = sof - data; | 710 | n = sof - data; |
@@ -859,43 +720,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
859 | atomic_set(&sd->avg_lum, -1); | 720 | atomic_set(&sd->avg_lum, -1); |
860 | 721 | ||
861 | /* Start the new frame with the jpeg header */ | 722 | /* Start the new frame with the jpeg header */ |
862 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | 723 | pac_start_frame(gspca_dev, frame, |
863 | pac7311_jpeg_header1, sizeof(pac7311_jpeg_header1)); | 724 | gspca_dev->height, gspca_dev->width); |
864 | if (sd->sensor == SENSOR_PAC7302) { | ||
865 | /* The PAC7302 has the image rotated 90 degrees */ | ||
866 | tmpbuf[0] = gspca_dev->width >> 8; | ||
867 | tmpbuf[1] = gspca_dev->width & 0xff; | ||
868 | tmpbuf[2] = gspca_dev->height >> 8; | ||
869 | tmpbuf[3] = gspca_dev->height & 0xff; | ||
870 | } else { | ||
871 | tmpbuf[0] = gspca_dev->height >> 8; | ||
872 | tmpbuf[1] = gspca_dev->height & 0xff; | ||
873 | tmpbuf[2] = gspca_dev->width >> 8; | ||
874 | tmpbuf[3] = gspca_dev->width & 0xff; | ||
875 | } | ||
876 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, tmpbuf, 4); | ||
877 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | ||
878 | pac7311_jpeg_header2, sizeof(pac7311_jpeg_header2)); | ||
879 | } | 725 | } |
880 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | 726 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
881 | } | ||
882 | |||
883 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | ||
884 | { | ||
885 | struct sd *sd = (struct sd *) gspca_dev; | ||
886 | |||
887 | sd->brightness = val; | ||
888 | if (gspca_dev->streaming) | ||
889 | setbrightcont(gspca_dev); | ||
890 | return 0; | ||
891 | } | ||
892 | |||
893 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
894 | { | ||
895 | struct sd *sd = (struct sd *) gspca_dev; | ||
896 | |||
897 | *val = sd->brightness; | ||
898 | return 0; | ||
899 | } | 727 | } |
900 | 728 | ||
901 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | 729 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) |
@@ -904,10 +732,7 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | |||
904 | 732 | ||
905 | sd->contrast = val; | 733 | sd->contrast = val; |
906 | if (gspca_dev->streaming) { | 734 | if (gspca_dev->streaming) { |
907 | if (sd->sensor == SENSOR_PAC7302) | 735 | setcontrast(gspca_dev); |
908 | setbrightcont(gspca_dev); | ||
909 | else | ||
910 | setcontrast(gspca_dev); | ||
911 | } | 736 | } |
912 | return 0; | 737 | return 0; |
913 | } | 738 | } |
@@ -920,24 +745,6 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | |||
920 | return 0; | 745 | return 0; |
921 | } | 746 | } |
922 | 747 | ||
923 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) | ||
924 | { | ||
925 | struct sd *sd = (struct sd *) gspca_dev; | ||
926 | |||
927 | sd->colors = val; | ||
928 | if (gspca_dev->streaming) | ||
929 | setcolors(gspca_dev); | ||
930 | return 0; | ||
931 | } | ||
932 | |||
933 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) | ||
934 | { | ||
935 | struct sd *sd = (struct sd *) gspca_dev; | ||
936 | |||
937 | *val = sd->colors; | ||
938 | return 0; | ||
939 | } | ||
940 | |||
941 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) | 748 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) |
942 | { | 749 | { |
943 | struct sd *sd = (struct sd *) gspca_dev; | 750 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -1041,7 +848,7 @@ static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | |||
1041 | return 0; | 848 | return 0; |
1042 | } | 849 | } |
1043 | 850 | ||
1044 | /* sub-driver description */ | 851 | /* sub-driver description for pac7311 */ |
1045 | static struct sd_desc sd_desc = { | 852 | static struct sd_desc sd_desc = { |
1046 | .name = MODULE_NAME, | 853 | .name = MODULE_NAME, |
1047 | .ctrls = sd_ctrls, | 854 | .ctrls = sd_ctrls, |
@@ -1057,21 +864,12 @@ static struct sd_desc sd_desc = { | |||
1057 | 864 | ||
1058 | /* -- module initialisation -- */ | 865 | /* -- module initialisation -- */ |
1059 | static __devinitdata struct usb_device_id device_table[] = { | 866 | static __devinitdata struct usb_device_id device_table[] = { |
1060 | {USB_DEVICE(0x06f8, 0x3009), .driver_info = SENSOR_PAC7302}, | 867 | {USB_DEVICE(0x093a, 0x2600)}, |
1061 | {USB_DEVICE(0x093a, 0x2600), .driver_info = SENSOR_PAC7311}, | 868 | {USB_DEVICE(0x093a, 0x2601)}, |
1062 | {USB_DEVICE(0x093a, 0x2601), .driver_info = SENSOR_PAC7311}, | 869 | {USB_DEVICE(0x093a, 0x2603)}, |
1063 | {USB_DEVICE(0x093a, 0x2603), .driver_info = SENSOR_PAC7311}, | 870 | {USB_DEVICE(0x093a, 0x2608)}, |
1064 | {USB_DEVICE(0x093a, 0x2608), .driver_info = SENSOR_PAC7311}, | 871 | {USB_DEVICE(0x093a, 0x260e)}, |
1065 | {USB_DEVICE(0x093a, 0x260e), .driver_info = SENSOR_PAC7311}, | 872 | {USB_DEVICE(0x093a, 0x260f)}, |
1066 | {USB_DEVICE(0x093a, 0x260f), .driver_info = SENSOR_PAC7311}, | ||
1067 | {USB_DEVICE(0x093a, 0x2620), .driver_info = SENSOR_PAC7302}, | ||
1068 | {USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302}, | ||
1069 | {USB_DEVICE(0x093a, 0x2622), .driver_info = SENSOR_PAC7302}, | ||
1070 | {USB_DEVICE(0x093a, 0x2624), .driver_info = SENSOR_PAC7302}, | ||
1071 | {USB_DEVICE(0x093a, 0x2626), .driver_info = SENSOR_PAC7302}, | ||
1072 | {USB_DEVICE(0x093a, 0x2629), .driver_info = SENSOR_PAC7302}, | ||
1073 | {USB_DEVICE(0x093a, 0x262a), .driver_info = SENSOR_PAC7302}, | ||
1074 | {USB_DEVICE(0x093a, 0x262c), .driver_info = SENSOR_PAC7302}, | ||
1075 | {} | 873 | {} |
1076 | }; | 874 | }; |
1077 | MODULE_DEVICE_TABLE(usb, device_table); | 875 | MODULE_DEVICE_TABLE(usb, device_table); |
diff --git a/drivers/media/video/gspca/pac_common.h b/drivers/media/video/gspca/pac_common.h index 34d4b1494cd5..20f67d9b8c06 100644 --- a/drivers/media/video/gspca/pac_common.h +++ b/drivers/media/video/gspca/pac_common.h | |||
@@ -33,26 +33,101 @@ | |||
33 | static const unsigned char pac_sof_marker[5] = | 33 | static const unsigned char pac_sof_marker[5] = |
34 | { 0xff, 0xff, 0x00, 0xff, 0x96 }; | 34 | { 0xff, 0xff, 0x00, 0xff, 0x96 }; |
35 | 35 | ||
36 | static unsigned char *pac_find_sof(struct gspca_dev *gspca_dev, | 36 | /* |
37 | The following state machine finds the SOF marker sequence | ||
38 | 0xff, 0xff, 0x00, 0xff, 0x96 in a byte stream. | ||
39 | |||
40 | +----------+ | ||
41 | | 0: START |<---------------\ | ||
42 | +----------+<-\ | | ||
43 | | \---/otherwise | | ||
44 | v 0xff | | ||
45 | +----------+ otherwise | | ||
46 | | 1 |--------------->* | ||
47 | | | ^ | ||
48 | +----------+ | | ||
49 | | | | ||
50 | v 0xff | | ||
51 | +----------+<-\0xff | | ||
52 | /->| |--/ | | ||
53 | | | 2 |--------------->* | ||
54 | | | | otherwise ^ | ||
55 | | +----------+ | | ||
56 | | | | | ||
57 | | v 0x00 | | ||
58 | | +----------+ | | ||
59 | | | 3 | | | ||
60 | | | |--------------->* | ||
61 | | +----------+ otherwise ^ | ||
62 | | | | | ||
63 | 0xff | v 0xff | | ||
64 | | +----------+ | | ||
65 | \--| 4 | | | ||
66 | | |----------------/ | ||
67 | +----------+ otherwise | ||
68 | | | ||
69 | v 0x96 | ||
70 | +----------+ | ||
71 | | FOUND | | ||
72 | +----------+ | ||
73 | */ | ||
74 | |||
75 | static unsigned char *pac_find_sof(u8 *sof_read, | ||
37 | unsigned char *m, int len) | 76 | unsigned char *m, int len) |
38 | { | 77 | { |
39 | struct sd *sd = (struct sd *) gspca_dev; | ||
40 | int i; | 78 | int i; |
41 | 79 | ||
42 | /* Search for the SOF marker (fixed part) in the header */ | 80 | /* Search for the SOF marker (fixed part) in the header */ |
43 | for (i = 0; i < len; i++) { | 81 | for (i = 0; i < len; i++) { |
44 | if (m[i] == pac_sof_marker[sd->sof_read]) { | 82 | switch (*sof_read) { |
45 | sd->sof_read++; | 83 | case 0: |
46 | if (sd->sof_read == sizeof(pac_sof_marker)) { | 84 | if (m[i] == 0xff) |
85 | *sof_read = 1; | ||
86 | break; | ||
87 | case 1: | ||
88 | if (m[i] == 0xff) | ||
89 | *sof_read = 2; | ||
90 | else | ||
91 | *sof_read = 0; | ||
92 | break; | ||
93 | case 2: | ||
94 | switch (m[i]) { | ||
95 | case 0x00: | ||
96 | *sof_read = 3; | ||
97 | break; | ||
98 | case 0xff: | ||
99 | /* stay in this state */ | ||
100 | break; | ||
101 | default: | ||
102 | *sof_read = 0; | ||
103 | } | ||
104 | break; | ||
105 | case 3: | ||
106 | if (m[i] == 0xff) | ||
107 | *sof_read = 4; | ||
108 | else | ||
109 | *sof_read = 0; | ||
110 | break; | ||
111 | case 4: | ||
112 | switch (m[i]) { | ||
113 | case 0x96: | ||
114 | /* Pattern found */ | ||
47 | PDEBUG(D_FRAM, | 115 | PDEBUG(D_FRAM, |
48 | "SOF found, bytes to analyze: %u." | 116 | "SOF found, bytes to analyze: %u." |
49 | " Frame starts at byte #%u", | 117 | " Frame starts at byte #%u", |
50 | len, i + 1); | 118 | len, i + 1); |
51 | sd->sof_read = 0; | 119 | *sof_read = 0; |
52 | return m + i + 1; | 120 | return m + i + 1; |
121 | break; | ||
122 | case 0xff: | ||
123 | *sof_read = 2; | ||
124 | break; | ||
125 | default: | ||
126 | *sof_read = 0; | ||
53 | } | 127 | } |
54 | } else { | 128 | break; |
55 | sd->sof_read = 0; | 129 | default: |
130 | *sof_read = 0; | ||
56 | } | 131 | } |
57 | } | 132 | } |
58 | 133 | ||
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index cdad3db33367..b1944a7cbb0f 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c | |||
@@ -2342,7 +2342,6 @@ static void sd_dqcallback(struct gspca_dev *gspca_dev) | |||
2342 | } | 2342 | } |
2343 | 2343 | ||
2344 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 2344 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
2345 | struct gspca_frame *frame, /* target */ | ||
2346 | u8 *data, /* isoc packet */ | 2345 | u8 *data, /* isoc packet */ |
2347 | int len) /* iso packet length */ | 2346 | int len) /* iso packet length */ |
2348 | { | 2347 | { |
@@ -2378,22 +2377,22 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
2378 | avg_lum >>= 9; | 2377 | avg_lum >>= 9; |
2379 | atomic_set(&sd->avg_lum, avg_lum); | 2378 | atomic_set(&sd->avg_lum, avg_lum); |
2380 | gspca_frame_add(gspca_dev, LAST_PACKET, | 2379 | gspca_frame_add(gspca_dev, LAST_PACKET, |
2381 | frame, data, len); | 2380 | data, len); |
2382 | return; | 2381 | return; |
2383 | } | 2382 | } |
2384 | if (gspca_dev->last_packet_type == LAST_PACKET) { | 2383 | if (gspca_dev->last_packet_type == LAST_PACKET) { |
2385 | if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv | 2384 | if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv |
2386 | & MODE_JPEG) { | 2385 | & MODE_JPEG) { |
2387 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | 2386 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
2388 | sd->jpeg_hdr, JPEG_HDR_SZ); | 2387 | sd->jpeg_hdr, JPEG_HDR_SZ); |
2389 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | 2388 | gspca_frame_add(gspca_dev, INTER_PACKET, |
2390 | data, len); | 2389 | data, len); |
2391 | } else { | 2390 | } else { |
2392 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | 2391 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
2393 | data, len); | 2392 | data, len); |
2394 | } | 2393 | } |
2395 | } else { | 2394 | } else { |
2396 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | 2395 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
2397 | } | 2396 | } |
2398 | } | 2397 | } |
2399 | 2398 | ||
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index e39efb45fa1c..5be95bc65138 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c | |||
@@ -995,8 +995,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
995 | } | 995 | } |
996 | 996 | ||
997 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 997 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
998 | struct gspca_frame *frame, /* target */ | 998 | u8 *data, /* isoc packet */ |
999 | unsigned char *data, /* isoc packet */ | ||
1000 | int len) /* iso packet length */ | 999 | int len) /* iso packet length */ |
1001 | { | 1000 | { |
1002 | int i; | 1001 | int i; |
@@ -1054,12 +1053,12 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1054 | pkt_type = DISCARD_PACKET; | 1053 | pkt_type = DISCARD_PACKET; |
1055 | } | 1054 | } |
1056 | 1055 | ||
1057 | frame = gspca_frame_add(gspca_dev, pkt_type, | 1056 | gspca_frame_add(gspca_dev, pkt_type, |
1058 | frame, data, 0); | 1057 | NULL, 0); |
1059 | data += i + fr_h_sz; | 1058 | data += i + fr_h_sz; |
1060 | len -= i + fr_h_sz; | 1059 | len -= i + fr_h_sz; |
1061 | gspca_frame_add(gspca_dev, FIRST_PACKET, | 1060 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
1062 | frame, data, len); | 1061 | data, len); |
1063 | return; | 1062 | return; |
1064 | } | 1063 | } |
1065 | } | 1064 | } |
@@ -1068,15 +1067,21 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1068 | if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) { | 1067 | if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) { |
1069 | /* In raw mode we sometimes get some garbage after the frame | 1068 | /* In raw mode we sometimes get some garbage after the frame |
1070 | ignore this */ | 1069 | ignore this */ |
1071 | int used = frame->data_end - frame->data; | 1070 | struct gspca_frame *frame; |
1071 | int used; | ||
1072 | int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage; | 1072 | int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage; |
1073 | 1073 | ||
1074 | frame = gspca_get_i_frame(gspca_dev); | ||
1075 | if (frame == NULL) { | ||
1076 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
1077 | return; | ||
1078 | } | ||
1079 | used = frame->data_end - frame->data; | ||
1074 | if (used + len > size) | 1080 | if (used + len > size) |
1075 | len = size - used; | 1081 | len = size - used; |
1076 | } | 1082 | } |
1077 | 1083 | ||
1078 | gspca_frame_add(gspca_dev, INTER_PACKET, | 1084 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
1079 | frame, data, len); | ||
1080 | } | 1085 | } |
1081 | 1086 | ||
1082 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 1087 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) |
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 33f4d0a1f6fd..0bd36a00dd2a 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Sonix sn9c102p sn9c105 sn9c120 (jpeg) library | 2 | * Sonix sn9c102p sn9c105 sn9c120 (jpeg) subdriver |
3 | * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr | ||
4 | * | 3 | * |
5 | * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> | 4 | * Copyright (C) 2009 Jean-Francois Moine <http://moinejf.free.fr> |
5 | * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr | ||
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
@@ -72,8 +72,9 @@ struct sd { | |||
72 | #define SENSOR_OV7630 5 | 72 | #define SENSOR_OV7630 5 |
73 | #define SENSOR_OV7648 6 | 73 | #define SENSOR_OV7648 6 |
74 | #define SENSOR_OV7660 7 | 74 | #define SENSOR_OV7660 7 |
75 | #define SENSOR_SP80708 8 | 75 | #define SENSOR_PO1030 8 |
76 | u8 i2c_base; | 76 | #define SENSOR_SP80708 9 |
77 | u8 i2c_addr; | ||
77 | 78 | ||
78 | u8 *jpeg_hdr; | 79 | u8 *jpeg_hdr; |
79 | }; | 80 | }; |
@@ -250,7 +251,7 @@ static struct ctrl sd_ctrls[] = { | |||
250 | .minimum = 0, | 251 | .minimum = 0, |
251 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ | 252 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ |
252 | .step = 1, | 253 | .step = 1, |
253 | #define FREQ_DEF 2 | 254 | #define FREQ_DEF 1 |
254 | .default_value = FREQ_DEF, | 255 | .default_value = FREQ_DEF, |
255 | }, | 256 | }, |
256 | .set = sd_setfreq, | 257 | .set = sd_setfreq, |
@@ -277,7 +278,9 @@ static __u32 ctrl_dis[] = { | |||
277 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), | 278 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), |
278 | /* SENSOR_OV7660 7 */ | 279 | /* SENSOR_OV7660 7 */ |
279 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | | 280 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | |
280 | (1 << FREQ_IDX), /* SENSOR_SP80708 8 */ | 281 | (1 << FREQ_IDX), /* SENSOR_PO1030 8 */ |
282 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | | ||
283 | (1 << FREQ_IDX), /* SENSOR_SP80708 9 */ | ||
281 | }; | 284 | }; |
282 | 285 | ||
283 | static const struct v4l2_pix_format vga_mode[] = { | 286 | static const struct v4l2_pix_format vga_mode[] = { |
@@ -304,7 +307,7 @@ static const u8 sn_hv7131[0x1c] = { | |||
304 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ | 307 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ |
305 | 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20, | 308 | 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20, |
306 | /* reg8 reg9 rega regb regc regd rege regf */ | 309 | /* reg8 reg9 rega regb regc regd rege regf */ |
307 | 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10, | 310 | 0x81, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
308 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ | 311 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ |
309 | 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41, | 312 | 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41, |
310 | /* reg18 reg19 reg1a reg1b */ | 313 | /* reg18 reg19 reg1a reg1b */ |
@@ -315,7 +318,7 @@ static const u8 sn_mi0360[0x1c] = { | |||
315 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ | 318 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ |
316 | 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, | 319 | 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, |
317 | /* reg8 reg9 rega regb regc regd rege regf */ | 320 | /* reg8 reg9 rega regb regc regd rege regf */ |
318 | 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, | 321 | 0x81, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
319 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ | 322 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ |
320 | 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61, | 323 | 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61, |
321 | /* reg18 reg19 reg1a reg1b */ | 324 | /* reg18 reg19 reg1a reg1b */ |
@@ -337,7 +340,7 @@ static const u8 sn_mt9v111[0x1c] = { | |||
337 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ | 340 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ |
338 | 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20, | 341 | 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20, |
339 | /* reg8 reg9 rega regb regc regd rege regf */ | 342 | /* reg8 reg9 rega regb regc regd rege regf */ |
340 | 0x81, 0x5c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, | 343 | 0x81, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
341 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ | 344 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ |
342 | 0x03, 0x00, 0x00, 0x02, 0x1c, 0x28, 0x1e, 0x40, | 345 | 0x03, 0x00, 0x00, 0x02, 0x1c, 0x28, 0x1e, 0x40, |
343 | /* reg18 reg19 reg1a reg1b */ | 346 | /* reg18 reg19 reg1a reg1b */ |
@@ -346,7 +349,7 @@ static const u8 sn_mt9v111[0x1c] = { | |||
346 | 349 | ||
347 | static const u8 sn_om6802[0x1c] = { | 350 | static const u8 sn_om6802[0x1c] = { |
348 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ | 351 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ |
349 | 0x00, 0x23, 0x72, 0x00, 0x1a, 0x34, 0x27, 0x20, | 352 | 0x00, 0x23, 0x72, 0x00, 0x1a, 0x20, 0x20, 0x19, |
350 | /* reg8 reg9 rega regb regc regd rege regf */ | 353 | /* reg8 reg9 rega regb regc regd rege regf */ |
351 | 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 354 | 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
352 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ | 355 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ |
@@ -359,7 +362,7 @@ static const u8 sn_ov7630[0x1c] = { | |||
359 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ | 362 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ |
360 | 0x00, 0x21, 0x40, 0x00, 0x1a, 0x20, 0x1f, 0x20, | 363 | 0x00, 0x21, 0x40, 0x00, 0x1a, 0x20, 0x1f, 0x20, |
361 | /* reg8 reg9 rega regb regc regd rege regf */ | 364 | /* reg8 reg9 rega regb regc regd rege regf */ |
362 | 0xa1, 0x21, 0x76, 0x21, 0x00, 0x00, 0x00, 0x10, | 365 | 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
363 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ | 366 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ |
364 | 0x03, 0x00, 0x04, 0x01, 0x0a, 0x28, 0x1e, 0xc2, | 367 | 0x03, 0x00, 0x04, 0x01, 0x0a, 0x28, 0x1e, 0xc2, |
365 | /* reg18 reg19 reg1a reg1b */ | 368 | /* reg18 reg19 reg1a reg1b */ |
@@ -370,7 +373,7 @@ static const u8 sn_ov7648[0x1c] = { | |||
370 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ | 373 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ |
371 | 0x00, 0x63, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20, | 374 | 0x00, 0x63, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20, |
372 | /* reg8 reg9 rega regb regc regd rege regf */ | 375 | /* reg8 reg9 rega regb regc regd rege regf */ |
373 | 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, | 376 | 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
374 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ | 377 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ |
375 | 0x03, 0x00, 0x00, 0x01, 0x00, 0x28, 0x1e, 0x00, | 378 | 0x03, 0x00, 0x00, 0x01, 0x00, 0x28, 0x1e, 0x00, |
376 | /* reg18 reg19 reg1a reg1b */ | 379 | /* reg18 reg19 reg1a reg1b */ |
@@ -388,11 +391,22 @@ static const u8 sn_ov7660[0x1c] = { | |||
388 | 0x07, 0x00, 0x00, 0x00 | 391 | 0x07, 0x00, 0x00, 0x00 |
389 | }; | 392 | }; |
390 | 393 | ||
394 | static const u8 sn_po1030[0x1c] = { | ||
395 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ | ||
396 | 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20, | ||
397 | /* reg8 reg9 rega regb regc regd rege regf */ | ||
398 | 0x81, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
399 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ | ||
400 | 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1e, 0x00, | ||
401 | /* reg18 reg19 reg1a reg1b */ | ||
402 | 0x07, 0x00, 0x00, 0x00 | ||
403 | }; | ||
404 | |||
391 | static const u8 sn_sp80708[0x1c] = { | 405 | static const u8 sn_sp80708[0x1c] = { |
392 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ | 406 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ |
393 | 0x00, 0x63, 0x60, 0x00, 0x1a, 0x20, 0x20, 0x20, | 407 | 0x00, 0x63, 0x60, 0x00, 0x1a, 0x20, 0x20, 0x20, |
394 | /* reg8 reg9 rega regb regc regd rege regf */ | 408 | /* reg8 reg9 rega regb regc regd rege regf */ |
395 | 0x81, 0x18, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, | 409 | 0x81, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
396 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ | 410 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ |
397 | 0x03, 0x00, 0x00, 0x03, 0x04, 0x28, 0x1e, 0x00, | 411 | 0x03, 0x00, 0x00, 0x03, 0x04, 0x28, 0x1e, 0x00, |
398 | /* reg18 reg19 reg1a reg1b */ | 412 | /* reg18 reg19 reg1a reg1b */ |
@@ -409,6 +423,7 @@ static const u8 *sn_tb[] = { | |||
409 | sn_ov7630, | 423 | sn_ov7630, |
410 | sn_ov7648, | 424 | sn_ov7648, |
411 | sn_ov7660, | 425 | sn_ov7660, |
426 | sn_po1030, | ||
412 | sn_sp80708 | 427 | sn_sp80708 |
413 | }; | 428 | }; |
414 | 429 | ||
@@ -455,7 +470,7 @@ static const u8 hv7131r_sensor_init[][8] = { | |||
455 | 470 | ||
456 | {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10}, | 471 | {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10}, |
457 | {0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, | 472 | {0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, |
458 | {0xa1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10}, | 473 | {0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10}, |
459 | {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10}, | 474 | {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10}, |
460 | {0xa1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10}, | 475 | {0xa1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10}, |
461 | 476 | ||
@@ -464,6 +479,8 @@ static const u8 hv7131r_sensor_init[][8] = { | |||
464 | {0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10}, | 479 | {0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10}, |
465 | {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10}, | 480 | {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10}, |
466 | {0xa1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10}, | 481 | {0xa1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10}, |
482 | {0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10}, | ||
483 | /* set sensor clock */ | ||
467 | {} | 484 | {} |
468 | }; | 485 | }; |
469 | static const u8 mi0360_sensor_init[][8] = { | 486 | static const u8 mi0360_sensor_init[][8] = { |
@@ -545,7 +562,7 @@ static const u8 mo4000_sensor_init[][8] = { | |||
545 | }; | 562 | }; |
546 | static const u8 mt9v111_sensor_init[][8] = { | 563 | static const u8 mt9v111_sensor_init[][8] = { |
547 | {0xb1, 0x5c, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10}, /* reset? */ | 564 | {0xb1, 0x5c, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10}, /* reset? */ |
548 | /* delay 20 ms */ | 565 | {0xdd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */ |
549 | {0xb1, 0x5c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10}, | 566 | {0xb1, 0x5c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10}, |
550 | {0xb1, 0x5c, 0x01, 0x00, 0x01, 0x00, 0x00, 0x10}, /* IFP select */ | 567 | {0xb1, 0x5c, 0x01, 0x00, 0x01, 0x00, 0x00, 0x10}, /* IFP select */ |
551 | {0xb1, 0x5c, 0x08, 0x04, 0x80, 0x00, 0x00, 0x10}, /* output fmt ctrl */ | 568 | {0xb1, 0x5c, 0x08, 0x04, 0x80, 0x00, 0x00, 0x10}, /* output fmt ctrl */ |
@@ -572,7 +589,9 @@ static const u8 mt9v111_sensor_init[][8] = { | |||
572 | {0xb1, 0x5c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* digital zoom */ | 589 | {0xb1, 0x5c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* digital zoom */ |
573 | {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, /* read mode */ | 590 | {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, /* read mode */ |
574 | {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, | 591 | {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, |
575 | /*******/ | 592 | {} |
593 | }; | ||
594 | static const u8 mt9v111_sensor_param1[][8] = { | ||
576 | {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, | 595 | {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, |
577 | {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, | 596 | {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, |
578 | {0xb1, 0x5c, 0x09, 0x01, 0x2c, 0x00, 0x00, 0x10}, | 597 | {0xb1, 0x5c, 0x09, 0x01, 0x2c, 0x00, 0x00, 0x10}, |
@@ -585,14 +604,20 @@ static const u8 mt9v111_sensor_init[][8] = { | |||
585 | {0xb1, 0x5c, 0x35, 0x01, 0xc0, 0x00, 0x00, 0x10}, /* global gain */ | 604 | {0xb1, 0x5c, 0x35, 0x01, 0xc0, 0x00, 0x00, 0x10}, /* global gain */ |
586 | {} | 605 | {} |
587 | }; | 606 | }; |
607 | static const u8 om6802_init0[2][8] = { | ||
608 | /*fixme: variable*/ | ||
609 | {0xa0, 0x34, 0x29, 0x0e, 0x00, 0x00, 0x00, 0x10}, | ||
610 | {0xa0, 0x34, 0x23, 0xb0, 0x00, 0x00, 0x00, 0x10}, | ||
611 | }; | ||
588 | static const u8 om6802_sensor_init[][8] = { | 612 | static const u8 om6802_sensor_init[][8] = { |
589 | {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10}, | 613 | {0xa0, 0x34, 0xdf, 0x6d, 0x00, 0x00, 0x00, 0x10}, |
590 | {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10}, | 614 | /* factory mode */ |
591 | {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10}, | ||
592 | {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10}, | 615 | {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10}, |
616 | /* output raw RGB */ | ||
617 | {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10}, | ||
593 | /* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */ | 618 | /* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */ |
594 | {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10}, | 619 | {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10}, |
595 | /* white balance & auto-exposure */ | 620 | /* auto-exposure speed (0) / white balance mode (auto RGB) */ |
596 | /* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10}, | 621 | /* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10}, |
597 | * set color mode */ | 622 | * set color mode */ |
598 | /* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10}, | 623 | /* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10}, |
@@ -606,26 +631,29 @@ static const u8 om6802_sensor_init[][8] = { | |||
606 | /* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10}, | 631 | /* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10}, |
607 | * preset gamma */ | 632 | * preset gamma */ |
608 | {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10}, | 633 | {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10}, |
609 | /* luminance mode (0x4f = AE) */ | 634 | /* luminance mode (0x4f -> AutoExpo on) */ |
610 | {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10}, | 635 | {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10}, |
611 | /* preset shutter */ | 636 | /* preset shutter */ |
612 | /* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10}, | 637 | /* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10}, |
613 | * auto frame rate */ | 638 | * auto frame rate */ |
614 | /* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */ | 639 | /* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */ |
615 | 640 | {0xa0, 0x34, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10}, | |
616 | /* {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, */ | 641 | {} |
617 | /* {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, */ | 642 | }; |
618 | /* {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, */ | 643 | static const u8 om6802_sensor_param1[][8] = { |
619 | /* {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */ | 644 | {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, |
645 | {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, | ||
646 | {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, | ||
647 | {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, | ||
620 | {} | 648 | {} |
621 | }; | 649 | }; |
622 | static const u8 ov7630_sensor_init[][8] = { | 650 | static const u8 ov7630_sensor_init[][8] = { |
623 | {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10}, | 651 | {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10}, |
624 | {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10}, | 652 | {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10}, |
625 | /* win: delay 20ms */ | 653 | {0xdd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */ |
626 | {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, | 654 | {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, |
627 | {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10}, | 655 | {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10}, |
628 | /* win: delay 20ms */ | 656 | {0xdd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */ |
629 | {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, | 657 | {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, |
630 | /* win: i2c_r from 00 to 80 */ | 658 | /* win: i2c_r from 00 to 80 */ |
631 | {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10}, | 659 | {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10}, |
@@ -677,6 +705,7 @@ static const u8 ov7630_sensor_init[][8] = { | |||
677 | static const u8 ov7648_sensor_init[][8] = { | 705 | static const u8 ov7648_sensor_init[][8] = { |
678 | {0xa1, 0x21, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10}, | 706 | {0xa1, 0x21, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10}, |
679 | {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */ | 707 | {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */ |
708 | {0xdd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */ | ||
680 | {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10}, | 709 | {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10}, |
681 | {0xd1, 0x21, 0x03, 0xa4, 0x30, 0x88, 0x00, 0x10}, | 710 | {0xd1, 0x21, 0x03, 0xa4, 0x30, 0x88, 0x00, 0x10}, |
682 | {0xb1, 0x21, 0x11, 0x80, 0x08, 0x00, 0x00, 0x10}, | 711 | {0xb1, 0x21, 0x11, 0x80, 0x08, 0x00, 0x00, 0x10}, |
@@ -701,7 +730,9 @@ static const u8 ov7648_sensor_init[][8] = { | |||
701 | /* {0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */ | 730 | /* {0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */ |
702 | /* {0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */ | 731 | /* {0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */ |
703 | /* {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10}, set by setfreq */ | 732 | /* {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10}, set by setfreq */ |
704 | /*...*/ | 733 | {} |
734 | }; | ||
735 | static const u8 ov7648_sensor_param1[][8] = { | ||
705 | /* {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */ | 736 | /* {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */ |
706 | /* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, * COMN | 737 | /* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, * COMN |
707 | * set by setvflip */ | 738 | * set by setvflip */ |
@@ -723,7 +754,7 @@ static const u8 ov7648_sensor_init[][8] = { | |||
723 | 754 | ||
724 | static const u8 ov7660_sensor_init[][8] = { | 755 | static const u8 ov7660_sensor_init[][8] = { |
725 | {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */ | 756 | {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */ |
726 | /* (delay 20ms) */ | 757 | {0xdd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */ |
727 | {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10}, | 758 | {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10}, |
728 | /* Outformat = rawRGB */ | 759 | /* Outformat = rawRGB */ |
729 | {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */ | 760 | {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */ |
@@ -783,8 +814,11 @@ static const u8 ov7660_sensor_init[][8] = { | |||
783 | {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */ | 814 | {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */ |
784 | {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */ | 815 | {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */ |
785 | {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */ | 816 | {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */ |
817 | /* not in all ms-win traces*/ | ||
786 | {0xa1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10}, | 818 | {0xa1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10}, |
787 | /****** (some exchanges in the win trace) ******/ | 819 | {} |
820 | }; | ||
821 | static const u8 ov7660_sensor_param1[][8] = { | ||
788 | {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */ | 822 | {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */ |
789 | /* bits[3..0]reserved */ | 823 | /* bits[3..0]reserved */ |
790 | {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, | 824 | {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, |
@@ -797,6 +831,7 @@ static const u8 ov7660_sensor_init[][8] = { | |||
797 | {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */ | 831 | {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */ |
798 | /* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */ | 832 | /* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */ |
799 | /****** (some exchanges in the win trace) ******/ | 833 | /****** (some exchanges in the win trace) ******/ |
834 | /*fixme:param2*/ | ||
800 | {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */ | 835 | {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */ |
801 | {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */ | 836 | {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */ |
802 | {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */ | 837 | {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */ |
@@ -804,6 +839,7 @@ static const u8 ov7660_sensor_init[][8] = { | |||
804 | /* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */ | 839 | /* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */ |
805 | /****** (some exchanges in the win trace) ******/ | 840 | /****** (some exchanges in the win trace) ******/ |
806 | /******!! startsensor KO if changed !!****/ | 841 | /******!! startsensor KO if changed !!****/ |
842 | /*fixme: param3*/ | ||
807 | {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10}, | 843 | {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10}, |
808 | {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10}, | 844 | {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10}, |
809 | {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, | 845 | {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, |
@@ -811,6 +847,60 @@ static const u8 ov7660_sensor_init[][8] = { | |||
811 | {} | 847 | {} |
812 | }; | 848 | }; |
813 | 849 | ||
850 | static const u8 po1030_sensor_init[][8] = { | ||
851 | /* the sensor registers are described in m5602/m5602_po1030.h */ | ||
852 | {0xa1, 0x6e, 0x3f, 0x20, 0x00, 0x00, 0x00, 0x10}, /* sensor reset */ | ||
853 | {0xdd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */ | ||
854 | {0xa1, 0x6e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
855 | {0xa1, 0x6e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
856 | {0xd1, 0x6e, 0x04, 0x02, 0xb1, 0x02, 0x39, 0x10}, | ||
857 | {0xd1, 0x6e, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10}, | ||
858 | {0xd1, 0x6e, 0x0c, 0x02, 0x7f, 0x01, 0xe0, 0x10}, | ||
859 | {0xd1, 0x6e, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10}, | ||
860 | {0xd1, 0x6e, 0x16, 0x85, 0x40, 0x4a, 0x40, 0x10}, /* r/g1/b/g2 gains */ | ||
861 | {0xc1, 0x6e, 0x1a, 0x00, 0x80, 0x00, 0x00, 0x10}, | ||
862 | {0xd1, 0x6e, 0x1d, 0x08, 0x03, 0x00, 0x00, 0x10}, | ||
863 | {0xd1, 0x6e, 0x23, 0x00, 0xb0, 0x00, 0x94, 0x10}, | ||
864 | {0xd1, 0x6e, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10}, | ||
865 | {0xb1, 0x6e, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
866 | {0xd1, 0x6e, 0x2d, 0x14, 0x35, 0x61, 0x84, 0x10}, /* gamma corr */ | ||
867 | {0xd1, 0x6e, 0x31, 0xa2, 0xbd, 0xd8, 0xff, 0x10}, | ||
868 | {0xd1, 0x6e, 0x35, 0x06, 0x1e, 0x12, 0x02, 0x10}, /* color matrix */ | ||
869 | {0xd1, 0x6e, 0x39, 0xaa, 0x53, 0x37, 0xd5, 0x10}, | ||
870 | {0xa1, 0x6e, 0x3d, 0xf2, 0x00, 0x00, 0x00, 0x10}, | ||
871 | {0xd1, 0x6e, 0x3e, 0x00, 0x00, 0x80, 0x03, 0x10}, | ||
872 | {0xd1, 0x6e, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10}, | ||
873 | {0xc1, 0x6e, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10}, | ||
874 | {0xd1, 0x6e, 0x4b, 0x02, 0xef, 0x08, 0xcd, 0x10}, | ||
875 | {0xd1, 0x6e, 0x4f, 0x00, 0xd0, 0x00, 0xa0, 0x10}, | ||
876 | {0xd1, 0x6e, 0x53, 0x01, 0xaa, 0x01, 0x40, 0x10}, | ||
877 | {0xd1, 0x6e, 0x5a, 0x50, 0x04, 0x30, 0x03, 0x10}, /* raw rgb bayer */ | ||
878 | {0xa1, 0x6e, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
879 | {0xd1, 0x6e, 0x5f, 0x10, 0x40, 0xff, 0x00, 0x10}, | ||
880 | |||
881 | {0xd1, 0x6e, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10}, | ||
882 | {0xd1, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
883 | {0xd1, 0x6e, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
884 | {0xd1, 0x6e, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
885 | {0xc1, 0x6e, 0x73, 0x10, 0x80, 0xeb, 0x00, 0x10}, | ||
886 | {} | ||
887 | }; | ||
888 | static const u8 po1030_sensor_param1[][8] = { | ||
889 | /* from ms-win traces - these values change with auto gain/expo/wb.. */ | ||
890 | {0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10}, | ||
891 | {0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10}, | ||
892 | /* mean values */ | ||
893 | {0xc1, 0x6e, 0x1a, 0x02, 0xd4, 0xa4, 0x00, 0x10}, /* integlines */ | ||
894 | {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, /* global gain */ | ||
895 | {0xc1, 0x6e, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10}, /* r/g1/b gains */ | ||
896 | |||
897 | {0xa1, 0x6e, 0x1d, 0x08, 0x00, 0x00, 0x00, 0x10}, /* control1 */ | ||
898 | {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, /* frameheight */ | ||
899 | {0xa1, 0x6e, 0x07, 0xd5, 0x00, 0x00, 0x00, 0x10}, | ||
900 | /* {0xc1, 0x6e, 0x16, 0x49, 0x40, 0x45, 0x00, 0x10}, */ | ||
901 | {} | ||
902 | }; | ||
903 | |||
814 | static const u8 sp80708_sensor_init[][8] = { | 904 | static const u8 sp80708_sensor_init[][8] = { |
815 | {0xa1, 0x18, 0x06, 0xf9, 0x00, 0x00, 0x00, 0x10}, | 905 | {0xa1, 0x18, 0x06, 0xf9, 0x00, 0x00, 0x00, 0x10}, |
816 | {0xa1, 0x18, 0x09, 0x1f, 0x00, 0x00, 0x00, 0x10}, | 906 | {0xa1, 0x18, 0x09, 0x1f, 0x00, 0x00, 0x00, 0x10}, |
@@ -883,7 +973,9 @@ static const u8 sp80708_sensor_init[][8] = { | |||
883 | {0xa1, 0x18, 0x67, 0x24, 0x00, 0x00, 0x00, 0x10}, | 973 | {0xa1, 0x18, 0x67, 0x24, 0x00, 0x00, 0x00, 0x10}, |
884 | {0xa1, 0x18, 0x68, 0x08, 0x00, 0x00, 0x00, 0x10}, | 974 | {0xa1, 0x18, 0x68, 0x08, 0x00, 0x00, 0x00, 0x10}, |
885 | {0xa1, 0x18, 0x2f, 0xc9, 0x00, 0x00, 0x00, 0x10}, | 975 | {0xa1, 0x18, 0x2f, 0xc9, 0x00, 0x00, 0x00, 0x10}, |
886 | /********/ | 976 | {} |
977 | }; | ||
978 | static const u8 sp80708_sensor_param1[][8] = { | ||
887 | {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10}, | 979 | {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10}, |
888 | {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10}, | 980 | {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10}, |
889 | {0xa1, 0x18, 0x03, 0x01, 0x00, 0x00, 0x00, 0x10}, | 981 | {0xa1, 0x18, 0x03, 0x01, 0x00, 0x00, 0x00, 0x10}, |
@@ -894,6 +986,19 @@ static const u8 sp80708_sensor_init[][8] = { | |||
894 | {} | 986 | {} |
895 | }; | 987 | }; |
896 | 988 | ||
989 | static const u8 (*sensor_init[10])[8] = { | ||
990 | hv7131r_sensor_init, /* HV7131R 0 */ | ||
991 | mi0360_sensor_init, /* MI0360 1 */ | ||
992 | mo4000_sensor_init, /* MO4000 2 */ | ||
993 | mt9v111_sensor_init, /* MT9V111 3 */ | ||
994 | om6802_sensor_init, /* OM6802 4 */ | ||
995 | ov7630_sensor_init, /* OV7630 5 */ | ||
996 | ov7648_sensor_init, /* OV7648 6 */ | ||
997 | ov7660_sensor_init, /* OV7660 7 */ | ||
998 | po1030_sensor_init, /* PO1030 8 */ | ||
999 | sp80708_sensor_init, /* SP80708 9 */ | ||
1000 | }; | ||
1001 | |||
897 | /* read <len> bytes to gspca_dev->usb_buf */ | 1002 | /* read <len> bytes to gspca_dev->usb_buf */ |
898 | static void reg_r(struct gspca_dev *gspca_dev, | 1003 | static void reg_r(struct gspca_dev *gspca_dev, |
899 | u16 value, int len) | 1004 | u16 value, int len) |
@@ -958,8 +1063,15 @@ static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) | |||
958 | struct sd *sd = (struct sd *) gspca_dev; | 1063 | struct sd *sd = (struct sd *) gspca_dev; |
959 | 1064 | ||
960 | PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val); | 1065 | PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val); |
961 | gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */ | 1066 | switch (sd->sensor) { |
962 | gspca_dev->usb_buf[1] = sd->i2c_base; | 1067 | case SENSOR_OM6802: /* i2c command = a0 (100 kHz) */ |
1068 | gspca_dev->usb_buf[0] = 0x80 | (2 << 4); | ||
1069 | break; | ||
1070 | default: /* i2c command = a1 (400 kHz) */ | ||
1071 | gspca_dev->usb_buf[0] = 0x81 | (2 << 4); | ||
1072 | break; | ||
1073 | } | ||
1074 | gspca_dev->usb_buf[1] = sd->i2c_addr; | ||
963 | gspca_dev->usb_buf[2] = reg; | 1075 | gspca_dev->usb_buf[2] = reg; |
964 | gspca_dev->usb_buf[3] = val; | 1076 | gspca_dev->usb_buf[3] = val; |
965 | gspca_dev->usb_buf[4] = 0; | 1077 | gspca_dev->usb_buf[4] = 0; |
@@ -991,14 +1103,21 @@ static void i2c_w8(struct gspca_dev *gspca_dev, | |||
991 | msleep(2); | 1103 | msleep(2); |
992 | } | 1104 | } |
993 | 1105 | ||
994 | /* read 5 bytes in gspca_dev->usb_buf */ | 1106 | /* sensor read 'len' (1..5) bytes in gspca_dev->usb_buf */ |
995 | static void i2c_r5(struct gspca_dev *gspca_dev, u8 reg) | 1107 | static void i2c_r(struct gspca_dev *gspca_dev, u8 reg, int len) |
996 | { | 1108 | { |
997 | struct sd *sd = (struct sd *) gspca_dev; | 1109 | struct sd *sd = (struct sd *) gspca_dev; |
998 | u8 mode[8]; | 1110 | u8 mode[8]; |
999 | 1111 | ||
1000 | mode[0] = 0x81 | 0x10; | 1112 | switch (sd->sensor) { |
1001 | mode[1] = sd->i2c_base; | 1113 | case SENSOR_OM6802: /* i2c command = 90 (100 kHz) */ |
1114 | mode[0] = 0x80 | 0x10; | ||
1115 | break; | ||
1116 | default: /* i2c command = 91 (400 kHz) */ | ||
1117 | mode[0] = 0x81 | 0x10; | ||
1118 | break; | ||
1119 | } | ||
1120 | mode[1] = sd->i2c_addr; | ||
1002 | mode[2] = reg; | 1121 | mode[2] = reg; |
1003 | mode[3] = 0; | 1122 | mode[3] = 0; |
1004 | mode[4] = 0; | 1123 | mode[4] = 0; |
@@ -1007,33 +1126,43 @@ static void i2c_r5(struct gspca_dev *gspca_dev, u8 reg) | |||
1007 | mode[7] = 0x10; | 1126 | mode[7] = 0x10; |
1008 | i2c_w8(gspca_dev, mode); | 1127 | i2c_w8(gspca_dev, mode); |
1009 | msleep(2); | 1128 | msleep(2); |
1010 | mode[0] = 0x81 | (5 << 4) | 0x02; | 1129 | mode[0] = (mode[0] & 0x81) | (len << 4) | 0x02; |
1011 | mode[2] = 0; | 1130 | mode[2] = 0; |
1012 | i2c_w8(gspca_dev, mode); | 1131 | i2c_w8(gspca_dev, mode); |
1013 | msleep(2); | 1132 | msleep(2); |
1014 | reg_r(gspca_dev, 0x0a, 5); | 1133 | reg_r(gspca_dev, 0x0a, 5); |
1015 | } | 1134 | } |
1016 | 1135 | ||
1017 | static int hv7131r_probe(struct gspca_dev *gspca_dev) | 1136 | static void i2c_w_seq(struct gspca_dev *gspca_dev, |
1137 | const u8 (*data)[8]) | ||
1138 | { | ||
1139 | while ((*data)[0] != 0) { | ||
1140 | if ((*data)[0] != 0xdd) | ||
1141 | i2c_w8(gspca_dev, *data); | ||
1142 | else | ||
1143 | msleep((*data)[1]); | ||
1144 | data++; | ||
1145 | } | ||
1146 | } | ||
1147 | |||
1148 | static void hv7131r_probe(struct gspca_dev *gspca_dev) | ||
1018 | { | 1149 | { |
1019 | i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */ | 1150 | i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */ |
1020 | msleep(10); | 1151 | msleep(10); |
1021 | reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */ | 1152 | reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */ |
1022 | msleep(10); | 1153 | msleep(10); |
1023 | i2c_r5(gspca_dev, 0); /* read sensor id */ | 1154 | i2c_r(gspca_dev, 0, 5); /* read sensor id */ |
1024 | if (gspca_dev->usb_buf[0] == 0x02 | 1155 | if (gspca_dev->usb_buf[0] == 0x02 |
1025 | && gspca_dev->usb_buf[1] == 0x09 | 1156 | && gspca_dev->usb_buf[1] == 0x09 |
1026 | && gspca_dev->usb_buf[2] == 0x01 | 1157 | && gspca_dev->usb_buf[2] == 0x01 |
1027 | && gspca_dev->usb_buf[3] == 0x00 | 1158 | && gspca_dev->usb_buf[3] == 0x00 |
1028 | && gspca_dev->usb_buf[4] == 0x00) { | 1159 | && gspca_dev->usb_buf[4] == 0x00) { |
1029 | PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R"); | 1160 | PDEBUG(D_PROBE, "Sensor sn9c102P HV7131R found"); |
1030 | return 0; | 1161 | return; |
1031 | } | 1162 | } |
1032 | PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x", | 1163 | PDEBUG(D_PROBE, "Sensor 0x%02x 0x%02x 0x%02x - sn9c102P not found", |
1033 | gspca_dev->usb_buf[0], gspca_dev->usb_buf[1], | 1164 | gspca_dev->usb_buf[0], gspca_dev->usb_buf[1], |
1034 | gspca_dev->usb_buf[2]); | 1165 | gspca_dev->usb_buf[2]); |
1035 | PDEBUG(D_PROBE, "Sensor sn9c102P Not found"); | ||
1036 | return -ENODEV; | ||
1037 | } | 1166 | } |
1038 | 1167 | ||
1039 | static void mi0360_probe(struct gspca_dev *gspca_dev) | 1168 | static void mi0360_probe(struct gspca_dev *gspca_dev) |
@@ -1075,7 +1204,6 @@ static void mi0360_probe(struct gspca_dev *gspca_dev) | |||
1075 | case 0x823a: | 1204 | case 0x823a: |
1076 | PDEBUG(D_PROBE, "Sensor mt9v111"); | 1205 | PDEBUG(D_PROBE, "Sensor mt9v111"); |
1077 | sd->sensor = SENSOR_MT9V111; | 1206 | sd->sensor = SENSOR_MT9V111; |
1078 | sd->i2c_base = 0x5c; | ||
1079 | break; | 1207 | break; |
1080 | case 0x8243: | 1208 | case 0x8243: |
1081 | PDEBUG(D_PROBE, "Sensor mi0360"); | 1209 | PDEBUG(D_PROBE, "Sensor mi0360"); |
@@ -1086,7 +1214,42 @@ static void mi0360_probe(struct gspca_dev *gspca_dev) | |||
1086 | } | 1214 | } |
1087 | } | 1215 | } |
1088 | 1216 | ||
1089 | static int configure_gpio(struct gspca_dev *gspca_dev, | 1217 | static void ov7648_probe(struct gspca_dev *gspca_dev) |
1218 | { | ||
1219 | struct sd *sd = (struct sd *) gspca_dev; | ||
1220 | |||
1221 | /* check ov76xx */ | ||
1222 | reg_w1(gspca_dev, 0x17, 0x62); | ||
1223 | reg_w1(gspca_dev, 0x01, 0x08); | ||
1224 | sd->i2c_addr = 0x21; | ||
1225 | i2c_r(gspca_dev, 0x0a, 2); | ||
1226 | if (gspca_dev->usb_buf[3] == 0x76) { /* ov76xx */ | ||
1227 | PDEBUG(D_PROBE, "Sensor ov%02x%02x", | ||
1228 | gspca_dev->usb_buf[3], gspca_dev->usb_buf[4]); | ||
1229 | return; | ||
1230 | } | ||
1231 | |||
1232 | /* reset */ | ||
1233 | reg_w1(gspca_dev, 0x01, 0x29); | ||
1234 | reg_w1(gspca_dev, 0x17, 0x42); | ||
1235 | |||
1236 | /* check po1030 */ | ||
1237 | reg_w1(gspca_dev, 0x17, 0x62); | ||
1238 | reg_w1(gspca_dev, 0x01, 0x08); | ||
1239 | sd->i2c_addr = 0x6e; | ||
1240 | i2c_r(gspca_dev, 0x00, 2); | ||
1241 | if (gspca_dev->usb_buf[3] == 0x10 /* po1030 */ | ||
1242 | && gspca_dev->usb_buf[4] == 0x30) { | ||
1243 | PDEBUG(D_PROBE, "Sensor po1030"); | ||
1244 | sd->sensor = SENSOR_PO1030; | ||
1245 | return; | ||
1246 | } | ||
1247 | |||
1248 | PDEBUG(D_PROBE, "Unknown sensor %02x%02x", | ||
1249 | gspca_dev->usb_buf[3], gspca_dev->usb_buf[4]); | ||
1250 | } | ||
1251 | |||
1252 | static void bridge_init(struct gspca_dev *gspca_dev, | ||
1090 | const u8 *sn9c1xx) | 1253 | const u8 *sn9c1xx) |
1091 | { | 1254 | { |
1092 | struct sd *sd = (struct sd *) gspca_dev; | 1255 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -1103,9 +1266,10 @@ static int configure_gpio(struct gspca_dev *gspca_dev, | |||
1103 | /* configure gpio */ | 1266 | /* configure gpio */ |
1104 | reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2); | 1267 | reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2); |
1105 | reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2); | 1268 | reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2); |
1106 | reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */ | 1269 | reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); |
1107 | switch (sd->sensor) { | 1270 | switch (sd->sensor) { |
1108 | case SENSOR_OV7660: | 1271 | case SENSOR_OV7660: |
1272 | case SENSOR_PO1030: | ||
1109 | case SENSOR_SP80708: | 1273 | case SENSOR_SP80708: |
1110 | reg9a = reg9a_spec; | 1274 | reg9a = reg9a_spec; |
1111 | break; | 1275 | break; |
@@ -1115,7 +1279,7 @@ static int configure_gpio(struct gspca_dev *gspca_dev, | |||
1115 | } | 1279 | } |
1116 | reg_w(gspca_dev, 0x9a, reg9a, 6); | 1280 | reg_w(gspca_dev, 0x9a, reg9a, 6); |
1117 | 1281 | ||
1118 | reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); /*fixme:jfm was 60 only*/ | 1282 | reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); |
1119 | 1283 | ||
1120 | reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f); | 1284 | reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f); |
1121 | 1285 | ||
@@ -1127,10 +1291,22 @@ static int configure_gpio(struct gspca_dev *gspca_dev, | |||
1127 | reg_w1(gspca_dev, 0x01, 0x40); | 1291 | reg_w1(gspca_dev, 0x01, 0x40); |
1128 | break; | 1292 | break; |
1129 | case SENSOR_OM6802: | 1293 | case SENSOR_OM6802: |
1130 | reg_w1(gspca_dev, 0x02, 0x71); | 1294 | msleep(10); |
1131 | reg_w1(gspca_dev, 0x01, 0x42); | 1295 | reg_w1(gspca_dev, 0x02, 0x73); |
1296 | reg_w1(gspca_dev, 0x17, 0x60); | ||
1297 | reg_w1(gspca_dev, 0x01, 0x22); | ||
1298 | msleep(100); | ||
1299 | reg_w1(gspca_dev, 0x01, 0x62); | ||
1300 | reg_w1(gspca_dev, 0x17, 0x64); | ||
1132 | reg_w1(gspca_dev, 0x17, 0x64); | 1301 | reg_w1(gspca_dev, 0x17, 0x64); |
1133 | reg_w1(gspca_dev, 0x01, 0x42); | 1302 | reg_w1(gspca_dev, 0x01, 0x42); |
1303 | msleep(10); | ||
1304 | reg_w1(gspca_dev, 0x01, 0x42); | ||
1305 | i2c_w8(gspca_dev, om6802_init0[0]); | ||
1306 | i2c_w8(gspca_dev, om6802_init0[1]); | ||
1307 | msleep(15); | ||
1308 | reg_w1(gspca_dev, 0x02, 0x71); | ||
1309 | msleep(150); | ||
1134 | break; | 1310 | break; |
1135 | case SENSOR_OV7630: | 1311 | case SENSOR_OV7630: |
1136 | reg_w1(gspca_dev, 0x01, 0x61); | 1312 | reg_w1(gspca_dev, 0x01, 0x61); |
@@ -1144,7 +1320,14 @@ static int configure_gpio(struct gspca_dev *gspca_dev, | |||
1144 | reg_w1(gspca_dev, 0x01, 0x62); | 1320 | reg_w1(gspca_dev, 0x01, 0x62); |
1145 | reg_w1(gspca_dev, 0x01, 0x42); | 1321 | reg_w1(gspca_dev, 0x01, 0x42); |
1146 | break; | 1322 | break; |
1323 | case SENSOR_PO1030: | ||
1324 | reg_w1(gspca_dev, 0x01, 0x61); | ||
1325 | reg_w1(gspca_dev, 0x17, 0x20); | ||
1326 | reg_w1(gspca_dev, 0x01, 0x60); | ||
1327 | reg_w1(gspca_dev, 0x01, 0x40); | ||
1328 | break; | ||
1147 | case SENSOR_OV7660: | 1329 | case SENSOR_OV7660: |
1330 | /* fall thru */ | ||
1148 | case SENSOR_SP80708: | 1331 | case SENSOR_SP80708: |
1149 | reg_w1(gspca_dev, 0x01, 0x63); | 1332 | reg_w1(gspca_dev, 0x01, 0x63); |
1150 | reg_w1(gspca_dev, 0x17, 0x20); | 1333 | reg_w1(gspca_dev, 0x17, 0x20); |
@@ -1153,143 +1336,18 @@ static int configure_gpio(struct gspca_dev *gspca_dev, | |||
1153 | msleep(100); | 1336 | msleep(100); |
1154 | reg_w1(gspca_dev, 0x02, 0x62); | 1337 | reg_w1(gspca_dev, 0x02, 0x62); |
1155 | break; | 1338 | break; |
1339 | default: | ||
1156 | /* case SENSOR_HV7131R: */ | 1340 | /* case SENSOR_HV7131R: */ |
1157 | /* case SENSOR_MI0360: */ | 1341 | /* case SENSOR_MI0360: */ |
1158 | /* case SENSOR_MO4000: */ | 1342 | /* case SENSOR_MO4000: */ |
1159 | default: | ||
1160 | reg_w1(gspca_dev, 0x01, 0x43); | 1343 | reg_w1(gspca_dev, 0x01, 0x43); |
1161 | reg_w1(gspca_dev, 0x17, 0x61); | 1344 | reg_w1(gspca_dev, 0x17, 0x61); |
1162 | reg_w1(gspca_dev, 0x01, 0x42); | 1345 | reg_w1(gspca_dev, 0x01, 0x42); |
1163 | if (sd->sensor == SENSOR_HV7131R) { | 1346 | if (sd->sensor == SENSOR_HV7131R |
1164 | if (hv7131r_probe(gspca_dev) < 0) | 1347 | && sd->bridge == BRIDGE_SN9C102P) |
1165 | return -ENODEV; | 1348 | hv7131r_probe(gspca_dev); |
1166 | } | ||
1167 | break; | 1349 | break; |
1168 | } | 1350 | } |
1169 | return 0; | ||
1170 | } | ||
1171 | |||
1172 | static void hv7131R_InitSensor(struct gspca_dev *gspca_dev) | ||
1173 | { | ||
1174 | int i = 0; | ||
1175 | static const u8 SetSensorClk[] = /* 0x08 Mclk */ | ||
1176 | { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 }; | ||
1177 | |||
1178 | while (hv7131r_sensor_init[i][0]) { | ||
1179 | i2c_w8(gspca_dev, hv7131r_sensor_init[i]); | ||
1180 | i++; | ||
1181 | } | ||
1182 | i2c_w8(gspca_dev, SetSensorClk); | ||
1183 | } | ||
1184 | |||
1185 | static void mi0360_InitSensor(struct gspca_dev *gspca_dev) | ||
1186 | { | ||
1187 | int i = 0; | ||
1188 | |||
1189 | while (mi0360_sensor_init[i][0]) { | ||
1190 | i2c_w8(gspca_dev, mi0360_sensor_init[i]); | ||
1191 | i++; | ||
1192 | } | ||
1193 | } | ||
1194 | |||
1195 | static void mo4000_InitSensor(struct gspca_dev *gspca_dev) | ||
1196 | { | ||
1197 | int i = 0; | ||
1198 | |||
1199 | while (mo4000_sensor_init[i][0]) { | ||
1200 | i2c_w8(gspca_dev, mo4000_sensor_init[i]); | ||
1201 | i++; | ||
1202 | } | ||
1203 | } | ||
1204 | |||
1205 | static void mt9v111_InitSensor(struct gspca_dev *gspca_dev) | ||
1206 | { | ||
1207 | int i = 0; | ||
1208 | |||
1209 | i2c_w8(gspca_dev, mt9v111_sensor_init[i]); | ||
1210 | i++; | ||
1211 | msleep(20); | ||
1212 | while (mt9v111_sensor_init[i][0]) { | ||
1213 | i2c_w8(gspca_dev, mt9v111_sensor_init[i]); | ||
1214 | i++; | ||
1215 | } | ||
1216 | } | ||
1217 | |||
1218 | static void om6802_InitSensor(struct gspca_dev *gspca_dev) | ||
1219 | { | ||
1220 | int i = 0; | ||
1221 | |||
1222 | while (om6802_sensor_init[i][0]) { | ||
1223 | i2c_w8(gspca_dev, om6802_sensor_init[i]); | ||
1224 | i++; | ||
1225 | } | ||
1226 | } | ||
1227 | |||
1228 | static void ov7630_InitSensor(struct gspca_dev *gspca_dev) | ||
1229 | { | ||
1230 | int i = 0; | ||
1231 | |||
1232 | i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 76 01 */ | ||
1233 | i++; | ||
1234 | i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 (RGB+SRST) */ | ||
1235 | i++; | ||
1236 | msleep(20); | ||
1237 | i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */ | ||
1238 | i++; | ||
1239 | i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 */ | ||
1240 | i++; | ||
1241 | msleep(20); | ||
1242 | i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */ | ||
1243 | i++; | ||
1244 | /*jfm:win i2c_r from 00 to 80*/ | ||
1245 | |||
1246 | while (ov7630_sensor_init[i][0]) { | ||
1247 | i2c_w8(gspca_dev, ov7630_sensor_init[i]); | ||
1248 | i++; | ||
1249 | } | ||
1250 | } | ||
1251 | |||
1252 | static void ov7648_InitSensor(struct gspca_dev *gspca_dev) | ||
1253 | { | ||
1254 | int i = 0; | ||
1255 | |||
1256 | i2c_w8(gspca_dev, ov7648_sensor_init[i]); | ||
1257 | i++; | ||
1258 | /* win: dble reset */ | ||
1259 | i2c_w8(gspca_dev, ov7648_sensor_init[i]); /* reset */ | ||
1260 | i++; | ||
1261 | msleep(20); | ||
1262 | /* win: i2c reg read 00..7f */ | ||
1263 | while (ov7648_sensor_init[i][0]) { | ||
1264 | i2c_w8(gspca_dev, ov7648_sensor_init[i]); | ||
1265 | i++; | ||
1266 | } | ||
1267 | } | ||
1268 | |||
1269 | static void ov7660_InitSensor(struct gspca_dev *gspca_dev) | ||
1270 | { | ||
1271 | int i = 0; | ||
1272 | |||
1273 | i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */ | ||
1274 | i++; | ||
1275 | msleep(20); | ||
1276 | while (ov7660_sensor_init[i][0]) { | ||
1277 | i2c_w8(gspca_dev, ov7660_sensor_init[i]); | ||
1278 | i++; | ||
1279 | } | ||
1280 | } | ||
1281 | |||
1282 | static void sp80708_InitSensor(struct gspca_dev *gspca_dev) | ||
1283 | { | ||
1284 | int i = 0; | ||
1285 | |||
1286 | i2c_w8(gspca_dev, sp80708_sensor_init[i]); /* reset SCCB */ | ||
1287 | i++; | ||
1288 | msleep(20); | ||
1289 | while (sp80708_sensor_init[i][0]) { | ||
1290 | i2c_w8(gspca_dev, sp80708_sensor_init[i]); | ||
1291 | i++; | ||
1292 | } | ||
1293 | } | 1351 | } |
1294 | 1352 | ||
1295 | /* this function is called at probe time */ | 1353 | /* this function is called at probe time */ |
@@ -1305,8 +1363,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1305 | cam->npkt = 24; /* 24 packets per ISOC message */ | 1363 | cam->npkt = 24; /* 24 packets per ISOC message */ |
1306 | 1364 | ||
1307 | sd->bridge = id->driver_info >> 16; | 1365 | sd->bridge = id->driver_info >> 16; |
1308 | sd->sensor = id->driver_info >> 8; | 1366 | sd->sensor = id->driver_info; |
1309 | sd->i2c_base = id->driver_info; | ||
1310 | 1367 | ||
1311 | sd->brightness = BRIGHTNESS_DEF; | 1368 | sd->brightness = BRIGHTNESS_DEF; |
1312 | sd->contrast = CONTRAST_DEF; | 1369 | sd->contrast = CONTRAST_DEF; |
@@ -1322,7 +1379,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1322 | sd->quality = QUALITY_DEF; | 1379 | sd->quality = QUALITY_DEF; |
1323 | sd->jpegqual = 80; | 1380 | sd->jpegqual = 80; |
1324 | 1381 | ||
1325 | gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; | ||
1326 | return 0; | 1382 | return 0; |
1327 | } | 1383 | } |
1328 | 1384 | ||
@@ -1330,6 +1386,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1330 | static int sd_init(struct gspca_dev *gspca_dev) | 1386 | static int sd_init(struct gspca_dev *gspca_dev) |
1331 | { | 1387 | { |
1332 | struct sd *sd = (struct sd *) gspca_dev; | 1388 | struct sd *sd = (struct sd *) gspca_dev; |
1389 | const u8 *sn9c1xx; | ||
1333 | u8 regGpio[] = { 0x29, 0x74 }; | 1390 | u8 regGpio[] = { 0x29, 0x74 }; |
1334 | u8 regF1; | 1391 | u8 regF1; |
1335 | 1392 | ||
@@ -1356,8 +1413,14 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1356 | case BRIDGE_SN9C120: | 1413 | case BRIDGE_SN9C120: |
1357 | if (regF1 != 0x12) | 1414 | if (regF1 != 0x12) |
1358 | return -ENODEV; | 1415 | return -ENODEV; |
1359 | if (sd->sensor == SENSOR_MI0360) | 1416 | switch (sd->sensor) { |
1417 | case SENSOR_MI0360: | ||
1360 | mi0360_probe(gspca_dev); | 1418 | mi0360_probe(gspca_dev); |
1419 | break; | ||
1420 | case SENSOR_OV7648: | ||
1421 | ov7648_probe(gspca_dev); | ||
1422 | break; | ||
1423 | } | ||
1361 | regGpio[1] = 0x70; | 1424 | regGpio[1] = 0x70; |
1362 | reg_w(gspca_dev, 0x01, regGpio, 2); | 1425 | reg_w(gspca_dev, 0x01, regGpio, 2); |
1363 | break; | 1426 | break; |
@@ -1372,6 +1435,12 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1372 | 1435 | ||
1373 | reg_w1(gspca_dev, 0xf1, 0x01); | 1436 | reg_w1(gspca_dev, 0xf1, 0x01); |
1374 | 1437 | ||
1438 | /* set the i2c address */ | ||
1439 | sn9c1xx = sn_tb[sd->sensor]; | ||
1440 | sd->i2c_addr = sn9c1xx[9]; | ||
1441 | |||
1442 | gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; | ||
1443 | |||
1375 | return 0; | 1444 | return 0; |
1376 | } | 1445 | } |
1377 | 1446 | ||
@@ -1383,7 +1452,7 @@ static u32 setexposure(struct gspca_dev *gspca_dev, | |||
1383 | switch (sd->sensor) { | 1452 | switch (sd->sensor) { |
1384 | case SENSOR_HV7131R: { | 1453 | case SENSOR_HV7131R: { |
1385 | u8 Expodoit[] = | 1454 | u8 Expodoit[] = |
1386 | { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 }; | 1455 | { 0xc1, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x16 }; |
1387 | 1456 | ||
1388 | Expodoit[3] = expo >> 16; | 1457 | Expodoit[3] = expo >> 16; |
1389 | Expodoit[4] = expo >> 8; | 1458 | Expodoit[4] = expo >> 8; |
@@ -1393,7 +1462,7 @@ static u32 setexposure(struct gspca_dev *gspca_dev, | |||
1393 | } | 1462 | } |
1394 | case SENSOR_MI0360: { | 1463 | case SENSOR_MI0360: { |
1395 | u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */ | 1464 | u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */ |
1396 | { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 }; | 1465 | { 0xb1, 0x5d, 0x09, 0x00, 0x00, 0x00, 0x00, 0x16 }; |
1397 | static const u8 doit[] = /* update sensor */ | 1466 | static const u8 doit[] = /* update sensor */ |
1398 | { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 }; | 1467 | { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 }; |
1399 | static const u8 sensorgo[] = /* sensor on */ | 1468 | static const u8 sensorgo[] = /* sensor on */ |
@@ -1412,9 +1481,9 @@ static u32 setexposure(struct gspca_dev *gspca_dev, | |||
1412 | } | 1481 | } |
1413 | case SENSOR_MO4000: { | 1482 | case SENSOR_MO4000: { |
1414 | u8 expoMof[] = | 1483 | u8 expoMof[] = |
1415 | { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 }; | 1484 | { 0xa1, 0x21, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x10 }; |
1416 | u8 expoMo10[] = | 1485 | u8 expoMo10[] = |
1417 | { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 }; | 1486 | { 0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10 }; |
1418 | static const u8 gainMo[] = | 1487 | static const u8 gainMo[] = |
1419 | { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d }; | 1488 | { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d }; |
1420 | 1489 | ||
@@ -1450,6 +1519,7 @@ static u32 setexposure(struct gspca_dev *gspca_dev, | |||
1450 | case SENSOR_OM6802: { | 1519 | case SENSOR_OM6802: { |
1451 | u8 gainOm[] = | 1520 | u8 gainOm[] = |
1452 | { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 }; | 1521 | { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 }; |
1522 | /* preset AGC - works when AutoExpo = off */ | ||
1453 | 1523 | ||
1454 | if (expo > 0x03ff) | 1524 | if (expo > 0x03ff) |
1455 | expo = 0x03ff; | 1525 | expo = 0x03ff; |
@@ -1457,7 +1527,7 @@ static u32 setexposure(struct gspca_dev *gspca_dev, | |||
1457 | expo = 0x0001; | 1527 | expo = 0x0001; |
1458 | gainOm[3] = expo >> 2; | 1528 | gainOm[3] = expo >> 2; |
1459 | i2c_w8(gspca_dev, gainOm); | 1529 | i2c_w8(gspca_dev, gainOm); |
1460 | reg_w1(gspca_dev, 0x96, (expo >> 5) & 0x1f); | 1530 | reg_w1(gspca_dev, 0x96, expo >> 5); |
1461 | PDEBUG(D_FRAM, "set exposure %d", gainOm[3]); | 1531 | PDEBUG(D_FRAM, "set exposure %d", gainOm[3]); |
1462 | break; | 1532 | break; |
1463 | } | 1533 | } |
@@ -1489,7 +1559,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
1489 | case SENSOR_MT9V111: | 1559 | case SENSOR_MT9V111: |
1490 | expo = sd->brightness >> 8; | 1560 | expo = sd->brightness >> 8; |
1491 | sd->exposure = setexposure(gspca_dev, expo); | 1561 | sd->exposure = setexposure(gspca_dev, expo); |
1492 | break; | 1562 | return; /* don't set the Y offset */ |
1493 | case SENSOR_OM6802: | 1563 | case SENSOR_OM6802: |
1494 | expo = sd->brightness >> 6; | 1564 | expo = sd->brightness >> 6; |
1495 | sd->exposure = setexposure(gspca_dev, expo); | 1565 | sd->exposure = setexposure(gspca_dev, expo); |
@@ -1497,8 +1567,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
1497 | break; | 1567 | break; |
1498 | } | 1568 | } |
1499 | 1569 | ||
1500 | if (sd->sensor != SENSOR_MT9V111) | 1570 | reg_w1(gspca_dev, 0x96, k2); /* color matrix Y offset */ |
1501 | reg_w1(gspca_dev, 0x96, k2); /* color matrix Y offset */ | ||
1502 | } | 1571 | } |
1503 | 1572 | ||
1504 | static void setcontrast(struct gspca_dev *gspca_dev) | 1573 | static void setcontrast(struct gspca_dev *gspca_dev) |
@@ -1526,6 +1595,7 @@ static void setcolors(struct gspca_dev *gspca_dev) | |||
1526 | -24, -38, 64, /* UR UG UB */ | 1595 | -24, -38, 64, /* UR UG UB */ |
1527 | 62, -51, -9 /* VR VG VB */ | 1596 | 62, -51, -9 /* VR VG VB */ |
1528 | }; | 1597 | }; |
1598 | |||
1529 | for (i = 0; i < 6; i++) { | 1599 | for (i = 0; i < 6; i++) { |
1530 | v = uv[i] * sd->colors / COLOR_DEF; | 1600 | v = uv[i] * sd->colors / COLOR_DEF; |
1531 | reg8a[i * 2] = v; | 1601 | reg8a[i * 2] = v; |
@@ -1605,6 +1675,8 @@ static void setvflip(struct sd *sd) | |||
1605 | { | 1675 | { |
1606 | u8 comn; | 1676 | u8 comn; |
1607 | 1677 | ||
1678 | if (sd->gspca_dev.ctrl_dis & (1 << VFLIP_IDX)) | ||
1679 | return; | ||
1608 | if (sd->sensor == SENSOR_OV7630) { | 1680 | if (sd->sensor == SENSOR_OV7630) { |
1609 | comn = 0x02; | 1681 | comn = 0x02; |
1610 | if (!sd->vflip) | 1682 | if (!sd->vflip) |
@@ -1726,8 +1798,9 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1726 | { | 1798 | { |
1727 | struct sd *sd = (struct sd *) gspca_dev; | 1799 | struct sd *sd = (struct sd *) gspca_dev; |
1728 | int i; | 1800 | int i; |
1729 | u8 reg1, reg17; | 1801 | u8 reg1, reg2, reg17; |
1730 | const u8 *sn9c1xx; | 1802 | const u8 *sn9c1xx; |
1803 | const u8 (*init)[8]; | ||
1731 | int mode; | 1804 | int mode; |
1732 | static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f }; | 1805 | static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f }; |
1733 | static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec }; | 1806 | static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec }; |
@@ -1743,8 +1816,26 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1743 | 0x21); /* JPEG 422 */ | 1816 | 0x21); /* JPEG 422 */ |
1744 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | 1817 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); |
1745 | 1818 | ||
1746 | sn9c1xx = sn_tb[(int) sd->sensor]; | 1819 | /* initialize the bridge */ |
1747 | configure_gpio(gspca_dev, sn9c1xx); | 1820 | sn9c1xx = sn_tb[sd->sensor]; |
1821 | bridge_init(gspca_dev, sn9c1xx); | ||
1822 | |||
1823 | /* initialize the sensor */ | ||
1824 | i2c_w_seq(gspca_dev, sensor_init[sd->sensor]); | ||
1825 | |||
1826 | switch (sd->sensor) { | ||
1827 | case SENSOR_OM6802: | ||
1828 | reg2 = 0x71; | ||
1829 | break; | ||
1830 | case SENSOR_SP80708: | ||
1831 | reg2 = 0x62; | ||
1832 | break; | ||
1833 | default: | ||
1834 | reg2 = 0x40; | ||
1835 | break; | ||
1836 | } | ||
1837 | reg_w1(gspca_dev, 0x02, reg2); | ||
1838 | reg_w1(gspca_dev, 0x02, reg2); | ||
1748 | 1839 | ||
1749 | reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]); | 1840 | reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]); |
1750 | reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]); | 1841 | reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]); |
@@ -1771,6 +1862,9 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1771 | case SENSOR_OV7660: | 1862 | case SENSOR_OV7660: |
1772 | reg17 = 0xa0; | 1863 | reg17 = 0xa0; |
1773 | break; | 1864 | break; |
1865 | case SENSOR_PO1030: | ||
1866 | reg17 = 0xa0; | ||
1867 | break; | ||
1774 | default: | 1868 | default: |
1775 | reg17 = 0x60; | 1869 | reg17 = 0x60; |
1776 | break; | 1870 | break; |
@@ -1791,6 +1885,10 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1791 | reg_w1(gspca_dev, 0x9a, 0x07); | 1885 | reg_w1(gspca_dev, 0x9a, 0x07); |
1792 | reg_w1(gspca_dev, 0x99, 0x59); | 1886 | reg_w1(gspca_dev, 0x99, 0x59); |
1793 | break; | 1887 | break; |
1888 | case SENSOR_OM6802: | ||
1889 | reg_w1(gspca_dev, 0x9a, 0x08); | ||
1890 | reg_w1(gspca_dev, 0x99, 0x10); | ||
1891 | break; | ||
1794 | case SENSOR_OV7648: | 1892 | case SENSOR_OV7648: |
1795 | reg_w1(gspca_dev, 0x9a, 0x0a); | 1893 | reg_w1(gspca_dev, 0x9a, 0x0a); |
1796 | reg_w1(gspca_dev, 0x99, 0x60); | 1894 | reg_w1(gspca_dev, 0x99, 0x60); |
@@ -1806,21 +1904,20 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1806 | break; | 1904 | break; |
1807 | } | 1905 | } |
1808 | 1906 | ||
1809 | mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; | 1907 | reg_w(gspca_dev, 0x84, reg84, sizeof reg84); |
1908 | reg_w1(gspca_dev, 0x05, sn9c1xx[5]); /* red */ | ||
1909 | reg_w1(gspca_dev, 0x07, sn9c1xx[7]); /* green */ | ||
1910 | reg_w1(gspca_dev, 0x06, sn9c1xx[6]); /* blue */ | ||
1911 | |||
1912 | init = NULL; | ||
1913 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; | ||
1810 | if (mode) | 1914 | if (mode) |
1811 | reg1 = 0x46; /* 320x240: clk 48Mhz, video trf enable */ | 1915 | reg1 = 0x46; /* 320x240: clk 48Mhz, video trf enable */ |
1812 | else | 1916 | else |
1813 | reg1 = 0x06; /* 640x480: clk 24Mhz, video trf enable */ | 1917 | reg1 = 0x06; /* 640x480: clk 24Mhz, video trf enable */ |
1814 | reg17 = 0x61; /* 0x:20: enable sensor clock */ | 1918 | reg17 = 0x61; /* 0x:20: enable sensor clock */ |
1815 | switch (sd->sensor) { | 1919 | switch (sd->sensor) { |
1816 | case SENSOR_HV7131R: | ||
1817 | hv7131R_InitSensor(gspca_dev); | ||
1818 | break; | ||
1819 | case SENSOR_MI0360: | ||
1820 | mi0360_InitSensor(gspca_dev); | ||
1821 | break; | ||
1822 | case SENSOR_MO4000: | 1920 | case SENSOR_MO4000: |
1823 | mo4000_InitSensor(gspca_dev); | ||
1824 | if (mode) { | 1921 | if (mode) { |
1825 | /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */ | 1922 | /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */ |
1826 | reg1 = 0x06; /* clk 24Mz */ | 1923 | reg1 = 0x06; /* clk 24Mz */ |
@@ -1830,7 +1927,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1830 | } | 1927 | } |
1831 | break; | 1928 | break; |
1832 | case SENSOR_MT9V111: | 1929 | case SENSOR_MT9V111: |
1833 | mt9v111_InitSensor(gspca_dev); | 1930 | init = mt9v111_sensor_param1; |
1834 | if (mode) { | 1931 | if (mode) { |
1835 | reg1 = 0x04; /* 320 clk 48Mhz */ | 1932 | reg1 = 0x04; /* 320 clk 48Mhz */ |
1836 | } else { | 1933 | } else { |
@@ -1839,22 +1936,21 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1839 | } | 1936 | } |
1840 | break; | 1937 | break; |
1841 | case SENSOR_OM6802: | 1938 | case SENSOR_OM6802: |
1842 | om6802_InitSensor(gspca_dev); | 1939 | init = om6802_sensor_param1; |
1843 | reg17 = 0x64; /* 640 MCKSIZE */ | 1940 | reg17 = 0x64; /* 640 MCKSIZE */ |
1844 | break; | 1941 | break; |
1845 | case SENSOR_OV7630: | 1942 | case SENSOR_OV7630: |
1846 | ov7630_InitSensor(gspca_dev); | ||
1847 | setvflip(sd); | 1943 | setvflip(sd); |
1848 | reg17 = 0xe2; | 1944 | reg17 = 0xe2; |
1849 | reg1 = 0x44; | 1945 | reg1 = 0x44; |
1850 | break; | 1946 | break; |
1851 | case SENSOR_OV7648: | 1947 | case SENSOR_OV7648: |
1852 | ov7648_InitSensor(gspca_dev); | 1948 | init = ov7648_sensor_param1; |
1853 | reg17 = 0x21; | 1949 | reg17 = 0x21; |
1854 | /* reg1 = 0x42; * 42 - 46? */ | 1950 | /* reg1 = 0x42; * 42 - 46? */ |
1855 | break; | 1951 | break; |
1856 | case SENSOR_OV7660: | 1952 | case SENSOR_OV7660: |
1857 | ov7660_InitSensor(gspca_dev); | 1953 | init = ov7660_sensor_param1; |
1858 | if (sd->bridge == BRIDGE_SN9C120) { | 1954 | if (sd->bridge == BRIDGE_SN9C120) { |
1859 | if (mode) { /* 320x240 - 160x120 */ | 1955 | if (mode) { /* 320x240 - 160x120 */ |
1860 | reg17 = 0xa2; | 1956 | reg17 = 0xa2; |
@@ -1866,9 +1962,14 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1866 | * inverse power down */ | 1962 | * inverse power down */ |
1867 | } | 1963 | } |
1868 | break; | 1964 | break; |
1965 | case SENSOR_PO1030: | ||
1966 | init = po1030_sensor_param1; | ||
1967 | reg17 = 0xa2; | ||
1968 | reg1 = 0x44; | ||
1969 | break; | ||
1869 | default: | 1970 | default: |
1870 | /* case SENSOR_SP80708: */ | 1971 | /* case SENSOR_SP80708: */ |
1871 | sp80708_InitSensor(gspca_dev); | 1972 | init = sp80708_sensor_param1; |
1872 | if (mode) { | 1973 | if (mode) { |
1873 | /*?? reg1 = 0x04; * 320 clk 48Mhz */ | 1974 | /*?? reg1 = 0x04; * 320 clk 48Mhz */ |
1874 | } else { | 1975 | } else { |
@@ -1877,6 +1978,13 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1877 | } | 1978 | } |
1878 | break; | 1979 | break; |
1879 | } | 1980 | } |
1981 | |||
1982 | /* more sensor initialization - param1 */ | ||
1983 | if (init != NULL) { | ||
1984 | i2c_w_seq(gspca_dev, init); | ||
1985 | /* init = NULL; */ | ||
1986 | } | ||
1987 | |||
1880 | reg_w(gspca_dev, 0xc0, C0, 6); | 1988 | reg_w(gspca_dev, 0xc0, C0, 6); |
1881 | reg_w(gspca_dev, 0xca, CA, 4); | 1989 | reg_w(gspca_dev, 0xca, CA, 4); |
1882 | switch (sd->sensor) { | 1990 | switch (sd->sensor) { |
@@ -1891,6 +1999,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1891 | break; | 1999 | break; |
1892 | } | 2000 | } |
1893 | 2001 | ||
2002 | |||
1894 | /* here change size mode 0 -> VGA; 1 -> CIF */ | 2003 | /* here change size mode 0 -> VGA; 1 -> CIF */ |
1895 | sd->reg18 = sn9c1xx[0x18] | (mode << 4) | 0x40; | 2004 | sd->reg18 = sn9c1xx[0x18] | (mode << 4) | 0x40; |
1896 | reg_w1(gspca_dev, 0x18, sd->reg18); | 2005 | reg_w1(gspca_dev, 0x18, sd->reg18); |
@@ -1898,6 +2007,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1898 | 2007 | ||
1899 | reg_w1(gspca_dev, 0x17, reg17); | 2008 | reg_w1(gspca_dev, 0x17, reg17); |
1900 | reg_w1(gspca_dev, 0x01, reg1); | 2009 | reg_w1(gspca_dev, 0x01, reg1); |
2010 | |||
1901 | switch (sd->sensor) { | 2011 | switch (sd->sensor) { |
1902 | case SENSOR_OV7630: | 2012 | case SENSOR_OV7630: |
1903 | setvflip(sd); | 2013 | setvflip(sd); |
@@ -1937,14 +2047,11 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
1937 | /* fall thru */ | 2047 | /* fall thru */ |
1938 | case SENSOR_MT9V111: | 2048 | case SENSOR_MT9V111: |
1939 | case SENSOR_OV7630: | 2049 | case SENSOR_OV7630: |
2050 | case SENSOR_PO1030: | ||
1940 | data = 0x29; | 2051 | data = 0x29; |
1941 | break; | 2052 | break; |
1942 | default: | ||
1943 | /* case SENSOR_MO4000: */ | ||
1944 | /* case SENSOR_OV7660: */ | ||
1945 | break; | ||
1946 | } | 2053 | } |
1947 | sn9c1xx = sn_tb[(int) sd->sensor]; | 2054 | sn9c1xx = sn_tb[sd->sensor]; |
1948 | reg_w1(gspca_dev, 0x01, sn9c1xx[1]); | 2055 | reg_w1(gspca_dev, 0x01, sn9c1xx[1]); |
1949 | reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]); | 2056 | reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]); |
1950 | reg_w1(gspca_dev, 0x01, sn9c1xx[1]); | 2057 | reg_w1(gspca_dev, 0x01, sn9c1xx[1]); |
@@ -1987,11 +2094,19 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
1987 | sd->exposure = setexposure(gspca_dev, | 2094 | sd->exposure = setexposure(gspca_dev, |
1988 | (unsigned int) (expotimes << 8)); | 2095 | (unsigned int) (expotimes << 8)); |
1989 | break; | 2096 | break; |
2097 | case SENSOR_OM6802: | ||
2098 | expotimes = sd->exposure; | ||
2099 | expotimes += (luma_mean - delta) >> 2; | ||
2100 | if (expotimes < 0) | ||
2101 | expotimes = 0; | ||
2102 | sd->exposure = setexposure(gspca_dev, | ||
2103 | (unsigned int) expotimes); | ||
2104 | setredblue(gspca_dev); | ||
2105 | break; | ||
1990 | default: | 2106 | default: |
1991 | /* case SENSOR_MO4000: */ | 2107 | /* case SENSOR_MO4000: */ |
1992 | /* case SENSOR_MI0360: */ | 2108 | /* case SENSOR_MI0360: */ |
1993 | /* case SENSOR_MT9V111: */ | 2109 | /* case SENSOR_MT9V111: */ |
1994 | /* case SENSOR_OM6802: */ | ||
1995 | expotimes = sd->exposure; | 2110 | expotimes = sd->exposure; |
1996 | expotimes += (luma_mean - delta) >> 6; | 2111 | expotimes += (luma_mean - delta) >> 6; |
1997 | if (expotimes < 0) | 2112 | if (expotimes < 0) |
@@ -2007,7 +2122,6 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
2007 | /* scan the URB packets */ | 2122 | /* scan the URB packets */ |
2008 | /* This function is run at interrupt level. */ | 2123 | /* This function is run at interrupt level. */ |
2009 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 2124 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
2010 | struct gspca_frame *frame, /* target */ | ||
2011 | u8 *data, /* isoc packet */ | 2125 | u8 *data, /* isoc packet */ |
2012 | int len) /* iso packet length */ | 2126 | int len) /* iso packet length */ |
2013 | { | 2127 | { |
@@ -2019,7 +2133,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
2019 | 2133 | ||
2020 | /* end of frame */ | 2134 | /* end of frame */ |
2021 | gspca_frame_add(gspca_dev, LAST_PACKET, | 2135 | gspca_frame_add(gspca_dev, LAST_PACKET, |
2022 | frame, data, sof + 2); | 2136 | data, sof + 2); |
2023 | if (sd->ag_cnt < 0) | 2137 | if (sd->ag_cnt < 0) |
2024 | return; | 2138 | return; |
2025 | /* w1 w2 w3 */ | 2139 | /* w1 w2 w3 */ |
@@ -2042,10 +2156,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
2042 | if (gspca_dev->last_packet_type == LAST_PACKET) { | 2156 | if (gspca_dev->last_packet_type == LAST_PACKET) { |
2043 | 2157 | ||
2044 | /* put the JPEG 422 header */ | 2158 | /* put the JPEG 422 header */ |
2045 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | 2159 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
2046 | sd->jpeg_hdr, JPEG_HDR_SZ); | 2160 | sd->jpeg_hdr, JPEG_HDR_SZ); |
2047 | } | 2161 | } |
2048 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | 2162 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
2049 | } | 2163 | } |
2050 | 2164 | ||
2051 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 2165 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) |
@@ -2295,69 +2409,69 @@ static const struct sd_desc sd_desc = { | |||
2295 | }; | 2409 | }; |
2296 | 2410 | ||
2297 | /* -- module initialisation -- */ | 2411 | /* -- module initialisation -- */ |
2298 | #define BSI(bridge, sensor, i2c_addr) \ | 2412 | #define BS(bridge, sensor) \ |
2299 | .driver_info = (BRIDGE_ ## bridge << 16) \ | 2413 | .driver_info = (BRIDGE_ ## bridge << 16) \ |
2300 | | (SENSOR_ ## sensor << 8) \ | 2414 | | SENSOR_ ## sensor |
2301 | | (i2c_addr) | ||
2302 | static const __devinitdata struct usb_device_id device_table[] = { | 2415 | static const __devinitdata struct usb_device_id device_table[] = { |
2303 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE | 2416 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE |
2304 | {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)}, | 2417 | {USB_DEVICE(0x0458, 0x7025), BS(SN9C120, MI0360)}, |
2305 | {USB_DEVICE(0x0458, 0x702e), BSI(SN9C120, OV7660, 0x21)}, | 2418 | {USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)}, |
2306 | #endif | 2419 | #endif |
2307 | {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)}, | 2420 | {USB_DEVICE(0x045e, 0x00f5), BS(SN9C105, OV7660)}, |
2308 | {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)}, | 2421 | {USB_DEVICE(0x045e, 0x00f7), BS(SN9C105, OV7660)}, |
2309 | {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)}, | 2422 | {USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)}, |
2310 | {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)}, | 2423 | {USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)}, |
2311 | {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)}, | 2424 | {USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)}, |
2312 | {USB_DEVICE(0x06f8, 0x3004), BSI(SN9C105, OV7660, 0x21)}, | 2425 | {USB_DEVICE(0x06f8, 0x3004), BS(SN9C105, OV7660)}, |
2313 | {USB_DEVICE(0x06f8, 0x3008), BSI(SN9C105, OV7660, 0x21)}, | 2426 | {USB_DEVICE(0x06f8, 0x3008), BS(SN9C105, OV7660)}, |
2314 | {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)}, | 2427 | /* {USB_DEVICE(0x0c45, 0x603a), BS(SN9C102P, OV7648)}, */ |
2315 | /* bw600.inf: | 2428 | {USB_DEVICE(0x0c45, 0x6040), BS(SN9C102P, HV7131R)}, |
2316 | {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */ | 2429 | /* {USB_DEVICE(0x0c45, 0x607a), BS(SN9C102P, OV7648)}, */ |
2317 | /* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */ | 2430 | /* {USB_DEVICE(0x0c45, 0x607b), BS(SN9C102P, OV7660)}, */ |
2318 | /* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */ | 2431 | {USB_DEVICE(0x0c45, 0x607c), BS(SN9C102P, HV7131R)}, |
2319 | {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)}, | 2432 | /* {USB_DEVICE(0x0c45, 0x607e), BS(SN9C102P, OV7630)}, */ |
2320 | /* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */ | 2433 | {USB_DEVICE(0x0c45, 0x60c0), BS(SN9C105, MI0360)}, |
2321 | {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)}, | 2434 | /* {USB_DEVICE(0x0c45, 0x60c2), BS(SN9C105, P1030xC)}, */ |
2322 | /* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6802, 0x??)}, */ | 2435 | /* {USB_DEVICE(0x0c45, 0x60c8), BS(SN9C105, OM6802)}, */ |
2323 | /* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */ | 2436 | /* {USB_DEVICE(0x0c45, 0x60cc), BS(SN9C105, HV7131GP)}, */ |
2324 | {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)}, | 2437 | {USB_DEVICE(0x0c45, 0x60ec), BS(SN9C105, MO4000)}, |
2325 | /* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */ | 2438 | /* {USB_DEVICE(0x0c45, 0x60ef), BS(SN9C105, ICM105C)}, */ |
2326 | /* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */ | 2439 | /* {USB_DEVICE(0x0c45, 0x60fa), BS(SN9C105, OV7648)}, */ |
2327 | {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)}, | 2440 | {USB_DEVICE(0x0c45, 0x60fb), BS(SN9C105, OV7660)}, |
2328 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE | 2441 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE |
2329 | {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)}, | 2442 | {USB_DEVICE(0x0c45, 0x60fc), BS(SN9C105, HV7131R)}, |
2330 | {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)}, | 2443 | {USB_DEVICE(0x0c45, 0x60fe), BS(SN9C105, OV7630)}, |
2331 | #endif | 2444 | #endif |
2332 | {USB_DEVICE(0x0c45, 0x6100), BSI(SN9C120, MI0360, 0x5d)}, /*sn9c128*/ | 2445 | {USB_DEVICE(0x0c45, 0x6100), BS(SN9C120, MI0360)}, /*sn9c128*/ |
2333 | /* {USB_DEVICE(0x0c45, 0x6102), BSI(SN9C120, PO2030N, ??)}, */ | 2446 | /* {USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, P1030xC)}, */ |
2334 | /* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6802, 0x21)}, */ | 2447 | /* {USB_DEVICE(0x0c45, 0x6108), BS(SN9C120, OM6802)}, */ |
2335 | {USB_DEVICE(0x0c45, 0x610a), BSI(SN9C120, OV7648, 0x21)}, /*sn9c128*/ | 2448 | {USB_DEVICE(0x0c45, 0x610a), BS(SN9C120, OV7648)}, /*sn9c128*/ |
2336 | {USB_DEVICE(0x0c45, 0x610b), BSI(SN9C120, OV7660, 0x21)}, /*sn9c128*/ | 2449 | {USB_DEVICE(0x0c45, 0x610b), BS(SN9C120, OV7660)}, /*sn9c128*/ |
2337 | {USB_DEVICE(0x0c45, 0x610c), BSI(SN9C120, HV7131R, 0x11)}, /*sn9c128*/ | 2450 | {USB_DEVICE(0x0c45, 0x610c), BS(SN9C120, HV7131R)}, /*sn9c128*/ |
2338 | {USB_DEVICE(0x0c45, 0x610e), BSI(SN9C120, OV7630, 0x21)}, /*sn9c128*/ | 2451 | {USB_DEVICE(0x0c45, 0x610e), BS(SN9C120, OV7630)}, /*sn9c128*/ |
2339 | /* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */ | 2452 | /* {USB_DEVICE(0x0c45, 0x610f), BS(SN9C120, S5K53BEB)}, */ |
2340 | /* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */ | 2453 | /* {USB_DEVICE(0x0c45, 0x6122), BS(SN9C110, ICM105C)}, */ |
2341 | {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/ | 2454 | /* {USB_DEVICE(0x0c45, 0x6123), BS(SN9C110, SanyoCCD)}, */ |
2455 | {USB_DEVICE(0x0c45, 0x6128), BS(SN9C120, OM6802)}, /*sn9c325?*/ | ||
2342 | /*bw600.inf:*/ | 2456 | /*bw600.inf:*/ |
2343 | {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C120, OV7648, 0x21)}, /*sn9c110?*/ | 2457 | {USB_DEVICE(0x0c45, 0x612a), BS(SN9C120, OV7648)}, /*sn9c325?*/ |
2344 | {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)}, | 2458 | {USB_DEVICE(0x0c45, 0x612c), BS(SN9C110, MO4000)}, |
2345 | {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x21)}, | 2459 | {USB_DEVICE(0x0c45, 0x612e), BS(SN9C110, OV7630)}, |
2346 | /* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */ | 2460 | /* {USB_DEVICE(0x0c45, 0x612f), BS(SN9C110, ICM105C)}, */ |
2347 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE | 2461 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE |
2348 | {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)}, | 2462 | {USB_DEVICE(0x0c45, 0x6130), BS(SN9C120, MI0360)}, |
2349 | #endif | 2463 | #endif |
2350 | /* {USB_DEVICE(0x0c45, 0x6132), BSI(SN9C120, OV7670, 0x21)}, */ | 2464 | /* {USB_DEVICE(0x0c45, 0x6132), BS(SN9C120, OV7670)}, */ |
2351 | {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)}, | 2465 | {USB_DEVICE(0x0c45, 0x6138), BS(SN9C120, MO4000)}, |
2352 | {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x21)}, | 2466 | {USB_DEVICE(0x0c45, 0x613a), BS(SN9C120, OV7648)}, |
2353 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE | 2467 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE |
2354 | {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)}, | 2468 | {USB_DEVICE(0x0c45, 0x613b), BS(SN9C120, OV7660)}, |
2355 | #endif | 2469 | #endif |
2356 | {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)}, | 2470 | {USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)}, |
2357 | {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x21)}, | 2471 | {USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)}, |
2358 | /* {USB_DEVICE(0x0c45, 0x6142), BSI(SN9C120, PO2030N, ??)}, *sn9c120b*/ | 2472 | /* {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, *sn9c120b*/ |
2359 | {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, SP80708, 0x18)}, /*sn9c120b*/ | 2473 | {USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)}, /*sn9c120b*/ |
2360 | {USB_DEVICE(0x0c45, 0x6148), BSI(SN9C120, OM6802, 0x21)}, /*sn9c120b*/ | 2474 | {USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)}, /*sn9c120b*/ |
2361 | {} | 2475 | {} |
2362 | }; | 2476 | }; |
2363 | MODULE_DEVICE_TABLE(usb, device_table); | 2477 | MODULE_DEVICE_TABLE(usb, device_table); |
diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c index 7dbd5eea6cc0..fe46868a87f2 100644 --- a/drivers/media/video/gspca/spca500.c +++ b/drivers/media/video/gspca/spca500.c | |||
@@ -899,8 +899,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
899 | } | 899 | } |
900 | 900 | ||
901 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 901 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
902 | struct gspca_frame *frame, /* target */ | 902 | u8 *data, /* isoc packet */ |
903 | __u8 *data, /* isoc packet */ | ||
904 | int len) /* iso packet length */ | 903 | int len) /* iso packet length */ |
905 | { | 904 | { |
906 | struct sd *sd = (struct sd *) gspca_dev; | 905 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -913,11 +912,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
913 | /* gspca_dev->last_packet_type = DISCARD_PACKET; */ | 912 | /* gspca_dev->last_packet_type = DISCARD_PACKET; */ |
914 | return; | 913 | return; |
915 | } | 914 | } |
916 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | 915 | gspca_frame_add(gspca_dev, LAST_PACKET, |
917 | ffd9, 2); | 916 | ffd9, 2); |
918 | 917 | ||
919 | /* put the JPEG header in the new frame */ | 918 | /* put the JPEG header in the new frame */ |
920 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | 919 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
921 | sd->jpeg_hdr, JPEG_HDR_SZ); | 920 | sd->jpeg_hdr, JPEG_HDR_SZ); |
922 | 921 | ||
923 | data += SPCA500_OFFSET_DATA; | 922 | data += SPCA500_OFFSET_DATA; |
@@ -931,7 +930,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
931 | i = 0; | 930 | i = 0; |
932 | do { | 931 | do { |
933 | if (data[i] == 0xff) { | 932 | if (data[i] == 0xff) { |
934 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | 933 | gspca_frame_add(gspca_dev, INTER_PACKET, |
935 | data, i + 1); | 934 | data, i + 1); |
936 | len -= i; | 935 | len -= i; |
937 | data += i; | 936 | data += i; |
@@ -940,7 +939,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
940 | } | 939 | } |
941 | i++; | 940 | i++; |
942 | } while (i < len); | 941 | } while (i < len); |
943 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | 942 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
944 | } | 943 | } |
945 | 944 | ||
946 | static void setbrightness(struct gspca_dev *gspca_dev) | 945 | static void setbrightness(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c index 66f9f0056146..6761a3048a98 100644 --- a/drivers/media/video/gspca/spca501.c +++ b/drivers/media/video/gspca/spca501.c | |||
@@ -2032,20 +2032,15 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
2032 | } | 2032 | } |
2033 | 2033 | ||
2034 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 2034 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
2035 | struct gspca_frame *frame, /* target */ | 2035 | u8 *data, /* isoc packet */ |
2036 | __u8 *data, /* isoc packet */ | ||
2037 | int len) /* iso packet length */ | 2036 | int len) /* iso packet length */ |
2038 | { | 2037 | { |
2039 | switch (data[0]) { | 2038 | switch (data[0]) { |
2040 | case 0: /* start of frame */ | 2039 | case 0: /* start of frame */ |
2041 | frame = gspca_frame_add(gspca_dev, | 2040 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); |
2042 | LAST_PACKET, | ||
2043 | frame, | ||
2044 | data, 0); | ||
2045 | data += SPCA501_OFFSET_DATA; | 2041 | data += SPCA501_OFFSET_DATA; |
2046 | len -= SPCA501_OFFSET_DATA; | 2042 | len -= SPCA501_OFFSET_DATA; |
2047 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | 2043 | gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); |
2048 | data, len); | ||
2049 | return; | 2044 | return; |
2050 | case 0xff: /* drop */ | 2045 | case 0xff: /* drop */ |
2051 | /* gspca_dev->last_packet_type = DISCARD_PACKET; */ | 2046 | /* gspca_dev->last_packet_type = DISCARD_PACKET; */ |
@@ -2053,8 +2048,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
2053 | } | 2048 | } |
2054 | data++; | 2049 | data++; |
2055 | len--; | 2050 | len--; |
2056 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | 2051 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
2057 | data, len); | ||
2058 | } | 2052 | } |
2059 | 2053 | ||
2060 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 2054 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) |
diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c index ea8c9fe2e961..0f9232ff1281 100644 --- a/drivers/media/video/gspca/spca505.c +++ b/drivers/media/video/gspca/spca505.c | |||
@@ -739,26 +739,22 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
739 | } | 739 | } |
740 | 740 | ||
741 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 741 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
742 | struct gspca_frame *frame, /* target */ | ||
743 | u8 *data, /* isoc packet */ | 742 | u8 *data, /* isoc packet */ |
744 | int len) /* iso packet length */ | 743 | int len) /* iso packet length */ |
745 | { | 744 | { |
746 | switch (data[0]) { | 745 | switch (data[0]) { |
747 | case 0: /* start of frame */ | 746 | case 0: /* start of frame */ |
748 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | 747 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); |
749 | data, 0); | ||
750 | data += SPCA50X_OFFSET_DATA; | 748 | data += SPCA50X_OFFSET_DATA; |
751 | len -= SPCA50X_OFFSET_DATA; | 749 | len -= SPCA50X_OFFSET_DATA; |
752 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | 750 | gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); |
753 | data, len); | ||
754 | break; | 751 | break; |
755 | case 0xff: /* drop */ | 752 | case 0xff: /* drop */ |
756 | break; | 753 | break; |
757 | default: | 754 | default: |
758 | data += 1; | 755 | data += 1; |
759 | len -= 1; | 756 | len -= 1; |
760 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | 757 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
761 | data, len); | ||
762 | break; | 758 | break; |
763 | } | 759 | } |
764 | } | 760 | } |
diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c index a199298a6419..ab28cc23e415 100644 --- a/drivers/media/video/gspca/spca506.c +++ b/drivers/media/video/gspca/spca506.c | |||
@@ -543,18 +543,15 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
543 | } | 543 | } |
544 | 544 | ||
545 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 545 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
546 | struct gspca_frame *frame, /* target */ | 546 | u8 *data, /* isoc packet */ |
547 | __u8 *data, /* isoc packet */ | ||
548 | int len) /* iso packet length */ | 547 | int len) /* iso packet length */ |
549 | { | 548 | { |
550 | switch (data[0]) { | 549 | switch (data[0]) { |
551 | case 0: /* start of frame */ | 550 | case 0: /* start of frame */ |
552 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | 551 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); |
553 | data, 0); | ||
554 | data += SPCA50X_OFFSET_DATA; | 552 | data += SPCA50X_OFFSET_DATA; |
555 | len -= SPCA50X_OFFSET_DATA; | 553 | len -= SPCA50X_OFFSET_DATA; |
556 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | 554 | gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); |
557 | data, len); | ||
558 | break; | 555 | break; |
559 | case 0xff: /* drop */ | 556 | case 0xff: /* drop */ |
560 | /* gspca_dev->last_packet_type = DISCARD_PACKET; */ | 557 | /* gspca_dev->last_packet_type = DISCARD_PACKET; */ |
@@ -562,8 +559,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
562 | default: | 559 | default: |
563 | data += 1; | 560 | data += 1; |
564 | len -= 1; | 561 | len -= 1; |
565 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | 562 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
566 | data, len); | ||
567 | break; | 563 | break; |
568 | } | 564 | } |
569 | } | 565 | } |
diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c index 9696c4caf5c9..4d8e6cf75d55 100644 --- a/drivers/media/video/gspca/spca508.c +++ b/drivers/media/video/gspca/spca508.c | |||
@@ -1447,26 +1447,22 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
1447 | } | 1447 | } |
1448 | 1448 | ||
1449 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 1449 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
1450 | struct gspca_frame *frame, /* target */ | ||
1451 | u8 *data, /* isoc packet */ | 1450 | u8 *data, /* isoc packet */ |
1452 | int len) /* iso packet length */ | 1451 | int len) /* iso packet length */ |
1453 | { | 1452 | { |
1454 | switch (data[0]) { | 1453 | switch (data[0]) { |
1455 | case 0: /* start of frame */ | 1454 | case 0: /* start of frame */ |
1456 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | 1455 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); |
1457 | data, 0); | ||
1458 | data += SPCA508_OFFSET_DATA; | 1456 | data += SPCA508_OFFSET_DATA; |
1459 | len -= SPCA508_OFFSET_DATA; | 1457 | len -= SPCA508_OFFSET_DATA; |
1460 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | 1458 | gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); |
1461 | data, len); | ||
1462 | break; | 1459 | break; |
1463 | case 0xff: /* drop */ | 1460 | case 0xff: /* drop */ |
1464 | break; | 1461 | break; |
1465 | default: | 1462 | default: |
1466 | data += 1; | 1463 | data += 1; |
1467 | len -= 1; | 1464 | len -= 1; |
1468 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | 1465 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
1469 | data, len); | ||
1470 | break; | 1466 | break; |
1471 | } | 1467 | } |
1472 | } | 1468 | } |
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 27e82b35f3e7..58c2f0039af1 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c | |||
@@ -779,8 +779,7 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
779 | } | 779 | } |
780 | 780 | ||
781 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 781 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
782 | struct gspca_frame *frame, /* target */ | 782 | u8 *data, /* isoc packet */ |
783 | __u8 *data, /* isoc packet */ | ||
784 | int len) /* iso packet length */ | 783 | int len) /* iso packet length */ |
785 | { | 784 | { |
786 | struct sd *sd = (struct sd *) gspca_dev; | 785 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -788,12 +787,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
788 | len--; | 787 | len--; |
789 | switch (*data++) { /* sequence number */ | 788 | switch (*data++) { /* sequence number */ |
790 | case 0: /* start of frame */ | 789 | case 0: /* start of frame */ |
791 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | 790 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); |
792 | data, 0); | ||
793 | if (data[1] & 0x10) { | 791 | if (data[1] & 0x10) { |
794 | /* compressed bayer */ | 792 | /* compressed bayer */ |
795 | gspca_frame_add(gspca_dev, FIRST_PACKET, | 793 | gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); |
796 | frame, data, len); | ||
797 | } else { | 794 | } else { |
798 | /* raw bayer (with a header, which we skip) */ | 795 | /* raw bayer (with a header, which we skip) */ |
799 | if (sd->chip_revision == Rev012A) { | 796 | if (sd->chip_revision == Rev012A) { |
@@ -803,14 +800,13 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
803 | data += 16; | 800 | data += 16; |
804 | len -= 16; | 801 | len -= 16; |
805 | } | 802 | } |
806 | gspca_frame_add(gspca_dev, FIRST_PACKET, | 803 | gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); |
807 | frame, data, len); | ||
808 | } | 804 | } |
809 | return; | 805 | return; |
810 | case 0xff: /* drop (empty mpackets) */ | 806 | case 0xff: /* drop (empty mpackets) */ |
811 | return; | 807 | return; |
812 | } | 808 | } |
813 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | 809 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
814 | } | 810 | } |
815 | 811 | ||
816 | /* rev 72a only */ | 812 | /* rev 72a only */ |
diff --git a/drivers/media/video/gspca/sq905.c b/drivers/media/video/gspca/sq905.c index 715a68f0156e..1fcaca6a87f7 100644 --- a/drivers/media/video/gspca/sq905.c +++ b/drivers/media/video/gspca/sq905.c | |||
@@ -168,18 +168,22 @@ static int sq905_ack_frame(struct gspca_dev *gspca_dev) | |||
168 | * request and read a block of data - see warning on sq905_command. | 168 | * request and read a block of data - see warning on sq905_command. |
169 | */ | 169 | */ |
170 | static int | 170 | static int |
171 | sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size) | 171 | sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size, int need_lock) |
172 | { | 172 | { |
173 | int ret; | 173 | int ret; |
174 | int act_len; | 174 | int act_len; |
175 | 175 | ||
176 | gspca_dev->usb_buf[0] = '\0'; | 176 | gspca_dev->usb_buf[0] = '\0'; |
177 | if (need_lock) | ||
178 | mutex_lock(&gspca_dev->usb_lock); | ||
177 | ret = usb_control_msg(gspca_dev->dev, | 179 | ret = usb_control_msg(gspca_dev->dev, |
178 | usb_sndctrlpipe(gspca_dev->dev, 0), | 180 | usb_sndctrlpipe(gspca_dev->dev, 0), |
179 | USB_REQ_SYNCH_FRAME, /* request */ | 181 | USB_REQ_SYNCH_FRAME, /* request */ |
180 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 182 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
181 | SQ905_BULK_READ, size, gspca_dev->usb_buf, | 183 | SQ905_BULK_READ, size, gspca_dev->usb_buf, |
182 | 1, SQ905_CMD_TIMEOUT); | 184 | 1, SQ905_CMD_TIMEOUT); |
185 | if (need_lock) | ||
186 | mutex_unlock(&gspca_dev->usb_lock); | ||
183 | if (ret < 0) { | 187 | if (ret < 0) { |
184 | PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)", __func__, ret); | 188 | PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)", __func__, ret); |
185 | return ret; | 189 | return ret; |
@@ -210,11 +214,9 @@ static void sq905_dostream(struct work_struct *work) | |||
210 | { | 214 | { |
211 | struct sd *dev = container_of(work, struct sd, work_struct); | 215 | struct sd *dev = container_of(work, struct sd, work_struct); |
212 | struct gspca_dev *gspca_dev = &dev->gspca_dev; | 216 | struct gspca_dev *gspca_dev = &dev->gspca_dev; |
213 | struct gspca_frame *frame; | ||
214 | int bytes_left; /* bytes remaining in current frame. */ | 217 | int bytes_left; /* bytes remaining in current frame. */ |
215 | int data_len; /* size to use for the next read. */ | 218 | int data_len; /* size to use for the next read. */ |
216 | int header_read; /* true if we have already read the frame header. */ | 219 | int header_read; /* true if we have already read the frame header. */ |
217 | int discarding; /* true if we failed to get space for frame. */ | ||
218 | int packet_type; | 220 | int packet_type; |
219 | int frame_sz; | 221 | int frame_sz; |
220 | int ret; | 222 | int ret; |
@@ -222,7 +224,6 @@ static void sq905_dostream(struct work_struct *work) | |||
222 | u8 *buffer; | 224 | u8 *buffer; |
223 | 225 | ||
224 | buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL | GFP_DMA); | 226 | buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL | GFP_DMA); |
225 | mutex_lock(&gspca_dev->usb_lock); | ||
226 | if (!buffer) { | 227 | if (!buffer) { |
227 | PDEBUG(D_ERR, "Couldn't allocate USB buffer"); | 228 | PDEBUG(D_ERR, "Couldn't allocate USB buffer"); |
228 | goto quit_stream; | 229 | goto quit_stream; |
@@ -232,28 +233,22 @@ static void sq905_dostream(struct work_struct *work) | |||
232 | + FRAME_HEADER_LEN; | 233 | + FRAME_HEADER_LEN; |
233 | 234 | ||
234 | while (gspca_dev->present && gspca_dev->streaming) { | 235 | while (gspca_dev->present && gspca_dev->streaming) { |
235 | /* Need a short delay to ensure streaming flag was set by | ||
236 | * gspca and to make sure gspca can grab the mutex. */ | ||
237 | mutex_unlock(&gspca_dev->usb_lock); | ||
238 | msleep(1); | ||
239 | |||
240 | /* request some data and then read it until we have | 236 | /* request some data and then read it until we have |
241 | * a complete frame. */ | 237 | * a complete frame. */ |
242 | bytes_left = frame_sz; | 238 | bytes_left = frame_sz; |
243 | header_read = 0; | 239 | header_read = 0; |
244 | discarding = 0; | ||
245 | 240 | ||
246 | while (bytes_left > 0) { | 241 | /* Note we do not check for gspca_dev->streaming here, as |
242 | we must finish reading an entire frame, otherwise the | ||
243 | next time we stream we start reading in the middle of a | ||
244 | frame. */ | ||
245 | while (bytes_left > 0 && gspca_dev->present) { | ||
247 | data_len = bytes_left > SQ905_MAX_TRANSFER ? | 246 | data_len = bytes_left > SQ905_MAX_TRANSFER ? |
248 | SQ905_MAX_TRANSFER : bytes_left; | 247 | SQ905_MAX_TRANSFER : bytes_left; |
249 | mutex_lock(&gspca_dev->usb_lock); | 248 | ret = sq905_read_data(gspca_dev, buffer, data_len, 1); |
250 | if (!gspca_dev->present) | ||
251 | goto quit_stream; | ||
252 | ret = sq905_read_data(gspca_dev, buffer, data_len); | ||
253 | if (ret < 0) | 249 | if (ret < 0) |
254 | goto quit_stream; | 250 | goto quit_stream; |
255 | mutex_unlock(&gspca_dev->usb_lock); | 251 | PDEBUG(D_PACK, |
256 | PDEBUG(D_STREAM, | ||
257 | "Got %d bytes out of %d for frame", | 252 | "Got %d bytes out of %d for frame", |
258 | data_len, bytes_left); | 253 | data_len, bytes_left); |
259 | bytes_left -= data_len; | 254 | bytes_left -= data_len; |
@@ -270,34 +265,30 @@ static void sq905_dostream(struct work_struct *work) | |||
270 | } else { | 265 | } else { |
271 | packet_type = INTER_PACKET; | 266 | packet_type = INTER_PACKET; |
272 | } | 267 | } |
273 | frame = gspca_get_i_frame(gspca_dev); | 268 | gspca_frame_add(gspca_dev, packet_type, |
274 | if (frame && !discarding) { | 269 | data, data_len); |
275 | frame = gspca_frame_add(gspca_dev, packet_type, | 270 | /* If entire frame fits in one packet we still |
276 | frame, data, data_len); | 271 | need to add a LAST_PACKET */ |
277 | /* If entire frame fits in one packet we still | 272 | if (packet_type == FIRST_PACKET && |
278 | need to add a LAST_PACKET */ | 273 | bytes_left == 0) |
279 | if (packet_type == FIRST_PACKET && | 274 | gspca_frame_add(gspca_dev, LAST_PACKET, |
280 | bytes_left == 0) | 275 | NULL, 0); |
281 | frame = gspca_frame_add(gspca_dev, | 276 | } |
282 | LAST_PACKET, | 277 | if (gspca_dev->present) { |
283 | frame, data, 0); | 278 | /* acknowledge the frame */ |
284 | } else { | 279 | mutex_lock(&gspca_dev->usb_lock); |
285 | discarding = 1; | 280 | ret = sq905_ack_frame(gspca_dev); |
286 | } | 281 | mutex_unlock(&gspca_dev->usb_lock); |
282 | if (ret < 0) | ||
283 | goto quit_stream; | ||
287 | } | 284 | } |
288 | /* acknowledge the frame */ | ||
289 | mutex_lock(&gspca_dev->usb_lock); | ||
290 | if (!gspca_dev->present) | ||
291 | goto quit_stream; | ||
292 | ret = sq905_ack_frame(gspca_dev); | ||
293 | if (ret < 0) | ||
294 | goto quit_stream; | ||
295 | } | 285 | } |
296 | quit_stream: | 286 | quit_stream: |
297 | /* the usb_lock is already acquired */ | 287 | if (gspca_dev->present) { |
298 | if (gspca_dev->present) | 288 | mutex_lock(&gspca_dev->usb_lock); |
299 | sq905_command(gspca_dev, SQ905_CLEAR); | 289 | sq905_command(gspca_dev, SQ905_CLEAR); |
300 | mutex_unlock(&gspca_dev->usb_lock); | 290 | mutex_unlock(&gspca_dev->usb_lock); |
291 | } | ||
301 | kfree(buffer); | 292 | kfree(buffer); |
302 | } | 293 | } |
303 | 294 | ||
@@ -346,7 +337,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
346 | ret = sq905_command(gspca_dev, SQ905_ID); | 337 | ret = sq905_command(gspca_dev, SQ905_ID); |
347 | if (ret < 0) | 338 | if (ret < 0) |
348 | return ret; | 339 | return ret; |
349 | ret = sq905_read_data(gspca_dev, gspca_dev->usb_buf, 4); | 340 | ret = sq905_read_data(gspca_dev, gspca_dev->usb_buf, 4, 0); |
350 | if (ret < 0) | 341 | if (ret < 0) |
351 | return ret; | 342 | return ret; |
352 | /* usb_buf is allocated with kmalloc so is aligned. | 343 | /* usb_buf is allocated with kmalloc so is aligned. |
diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c index 916892505432..d70b156872d6 100644 --- a/drivers/media/video/gspca/sq905c.c +++ b/drivers/media/video/gspca/sq905c.c | |||
@@ -115,11 +115,9 @@ static void sq905c_dostream(struct work_struct *work) | |||
115 | { | 115 | { |
116 | struct sd *dev = container_of(work, struct sd, work_struct); | 116 | struct sd *dev = container_of(work, struct sd, work_struct); |
117 | struct gspca_dev *gspca_dev = &dev->gspca_dev; | 117 | struct gspca_dev *gspca_dev = &dev->gspca_dev; |
118 | struct gspca_frame *frame; | ||
119 | int bytes_left; /* bytes remaining in current frame. */ | 118 | int bytes_left; /* bytes remaining in current frame. */ |
120 | int data_len; /* size to use for the next read. */ | 119 | int data_len; /* size to use for the next read. */ |
121 | int act_len; | 120 | int act_len; |
122 | int discarding = 0; /* true if we failed to get space for frame. */ | ||
123 | int packet_type; | 121 | int packet_type; |
124 | int ret; | 122 | int ret; |
125 | u8 *buffer; | 123 | u8 *buffer; |
@@ -131,8 +129,6 @@ static void sq905c_dostream(struct work_struct *work) | |||
131 | } | 129 | } |
132 | 130 | ||
133 | while (gspca_dev->present && gspca_dev->streaming) { | 131 | while (gspca_dev->present && gspca_dev->streaming) { |
134 | if (!gspca_dev->present) | ||
135 | goto quit_stream; | ||
136 | /* Request the header, which tells the size to download */ | 132 | /* Request the header, which tells the size to download */ |
137 | ret = usb_bulk_msg(gspca_dev->dev, | 133 | ret = usb_bulk_msg(gspca_dev->dev, |
138 | usb_rcvbulkpipe(gspca_dev->dev, 0x81), | 134 | usb_rcvbulkpipe(gspca_dev->dev, 0x81), |
@@ -149,17 +145,11 @@ static void sq905c_dostream(struct work_struct *work) | |||
149 | PDEBUG(D_STREAM, "bytes_left = 0x%x", bytes_left); | 145 | PDEBUG(D_STREAM, "bytes_left = 0x%x", bytes_left); |
150 | /* We keep the header. It has other information, too. */ | 146 | /* We keep the header. It has other information, too. */ |
151 | packet_type = FIRST_PACKET; | 147 | packet_type = FIRST_PACKET; |
152 | frame = gspca_get_i_frame(gspca_dev); | 148 | gspca_frame_add(gspca_dev, packet_type, |
153 | if (frame && !discarding) { | 149 | buffer, FRAME_HEADER_LEN); |
154 | gspca_frame_add(gspca_dev, packet_type, | 150 | while (bytes_left > 0 && gspca_dev->present) { |
155 | frame, buffer, FRAME_HEADER_LEN); | ||
156 | } else | ||
157 | discarding = 1; | ||
158 | while (bytes_left > 0) { | ||
159 | data_len = bytes_left > SQ905C_MAX_TRANSFER ? | 151 | data_len = bytes_left > SQ905C_MAX_TRANSFER ? |
160 | SQ905C_MAX_TRANSFER : bytes_left; | 152 | SQ905C_MAX_TRANSFER : bytes_left; |
161 | if (!gspca_dev->present) | ||
162 | goto quit_stream; | ||
163 | ret = usb_bulk_msg(gspca_dev->dev, | 153 | ret = usb_bulk_msg(gspca_dev->dev, |
164 | usb_rcvbulkpipe(gspca_dev->dev, 0x81), | 154 | usb_rcvbulkpipe(gspca_dev->dev, 0x81), |
165 | buffer, data_len, &act_len, | 155 | buffer, data_len, &act_len, |
@@ -174,19 +164,16 @@ static void sq905c_dostream(struct work_struct *work) | |||
174 | packet_type = LAST_PACKET; | 164 | packet_type = LAST_PACKET; |
175 | else | 165 | else |
176 | packet_type = INTER_PACKET; | 166 | packet_type = INTER_PACKET; |
177 | frame = gspca_get_i_frame(gspca_dev); | 167 | gspca_frame_add(gspca_dev, packet_type, |
178 | if (frame && !discarding) | 168 | buffer, data_len); |
179 | gspca_frame_add(gspca_dev, packet_type, | ||
180 | frame, buffer, data_len); | ||
181 | else | ||
182 | discarding = 1; | ||
183 | } | 169 | } |
184 | } | 170 | } |
185 | quit_stream: | 171 | quit_stream: |
186 | mutex_lock(&gspca_dev->usb_lock); | 172 | if (gspca_dev->present) { |
187 | if (gspca_dev->present) | 173 | mutex_lock(&gspca_dev->usb_lock); |
188 | sq905c_command(gspca_dev, SQ905C_CLEAR, 0); | 174 | sq905c_command(gspca_dev, SQ905C_CLEAR, 0); |
189 | mutex_unlock(&gspca_dev->usb_lock); | 175 | mutex_unlock(&gspca_dev->usb_lock); |
176 | } | ||
190 | kfree(buffer); | 177 | kfree(buffer); |
191 | } | 178 | } |
192 | 179 | ||
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index 47628964801e..8e23320d7ab7 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c | |||
@@ -418,8 +418,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
418 | } | 418 | } |
419 | 419 | ||
420 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 420 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
421 | struct gspca_frame *frame, /* target */ | 421 | u8 *data, /* isoc packet */ |
422 | __u8 *data, /* isoc packet */ | ||
423 | int len) /* iso packet length */ | 422 | int len) /* iso packet length */ |
424 | { | 423 | { |
425 | struct sd *sd = (struct sd *) gspca_dev; | 424 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -435,11 +434,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
435 | * (without ending - ff d9) | 434 | * (without ending - ff d9) |
436 | */ | 435 | */ |
437 | if (data[0] == 0xff && data[1] == 0xfe) { | 436 | if (data[0] == 0xff && data[1] == 0xfe) { |
438 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | 437 | gspca_frame_add(gspca_dev, LAST_PACKET, |
439 | ffd9, 2); | 438 | ffd9, 2); |
440 | 439 | ||
441 | /* put the JPEG 411 header */ | 440 | /* put the JPEG 411 header */ |
442 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | 441 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
443 | sd->jpeg_hdr, JPEG_HDR_SZ); | 442 | sd->jpeg_hdr, JPEG_HDR_SZ); |
444 | 443 | ||
445 | /* beginning of the frame */ | 444 | /* beginning of the frame */ |
@@ -447,7 +446,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
447 | data += STKHDRSZ; | 446 | data += STKHDRSZ; |
448 | len -= STKHDRSZ; | 447 | len -= STKHDRSZ; |
449 | } | 448 | } |
450 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | 449 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
451 | } | 450 | } |
452 | 451 | ||
453 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 452 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) |
diff --git a/drivers/media/video/gspca/stv0680.c b/drivers/media/video/gspca/stv0680.c new file mode 100644 index 000000000000..2a69d7ccb50d --- /dev/null +++ b/drivers/media/video/gspca/stv0680.c | |||
@@ -0,0 +1,364 @@ | |||
1 | /* | ||
2 | * STV0680 USB Camera Driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Hans de Goede <hdgoede@redhat.com> | ||
5 | * | ||
6 | * This module is adapted from the in kernel v4l1 stv680 driver: | ||
7 | * | ||
8 | * STV0680 USB Camera Driver, by Kevin Sisson (kjsisson@bellsouth.net) | ||
9 | * | ||
10 | * Thanks to STMicroelectronics for information on the usb commands, and | ||
11 | * to Steve Miller at STM for his help and encouragement while I was | ||
12 | * writing this driver. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License 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 | ||
26 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #define MODULE_NAME "stv0680" | ||
31 | |||
32 | #include "gspca.h" | ||
33 | |||
34 | MODULE_AUTHOR("Hans de Goede <hdgoede@redhat.com>"); | ||
35 | MODULE_DESCRIPTION("STV0680 USB Camera Driver"); | ||
36 | MODULE_LICENSE("GPL"); | ||
37 | |||
38 | /* specific webcam descriptor */ | ||
39 | struct sd { | ||
40 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
41 | struct v4l2_pix_format mode; | ||
42 | u8 orig_mode; | ||
43 | u8 video_mode; | ||
44 | u8 current_mode; | ||
45 | }; | ||
46 | |||
47 | /* V4L2 controls supported by the driver */ | ||
48 | static struct ctrl sd_ctrls[] = { | ||
49 | }; | ||
50 | |||
51 | static int stv_sndctrl(struct gspca_dev *gspca_dev, int set, u8 req, u16 val, | ||
52 | int size) | ||
53 | { | ||
54 | int ret = -1; | ||
55 | u8 req_type = 0; | ||
56 | |||
57 | switch (set) { | ||
58 | case 0: /* 0xc1 */ | ||
59 | req_type = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; | ||
60 | break; | ||
61 | case 1: /* 0x41 */ | ||
62 | req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; | ||
63 | break; | ||
64 | case 2: /* 0x80 */ | ||
65 | req_type = USB_DIR_IN | USB_RECIP_DEVICE; | ||
66 | break; | ||
67 | case 3: /* 0x40 */ | ||
68 | req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; | ||
69 | break; | ||
70 | } | ||
71 | |||
72 | ret = usb_control_msg(gspca_dev->dev, | ||
73 | usb_rcvctrlpipe(gspca_dev->dev, 0), | ||
74 | req, req_type, | ||
75 | val, 0, gspca_dev->usb_buf, size, 500); | ||
76 | |||
77 | if ((ret < 0) && (req != 0x0a)) | ||
78 | PDEBUG(D_ERR, | ||
79 | "usb_control_msg error %i, request = 0x%x, error = %i", | ||
80 | set, req, ret); | ||
81 | |||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | static int stv0680_handle_error(struct gspca_dev *gspca_dev, int ret) | ||
86 | { | ||
87 | stv_sndctrl(gspca_dev, 0, 0x80, 0, 0x02); /* Get Last Error */ | ||
88 | PDEBUG(D_ERR, "last error: %i, command = 0x%x", | ||
89 | gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]); | ||
90 | return ret; | ||
91 | } | ||
92 | |||
93 | static int stv0680_get_video_mode(struct gspca_dev *gspca_dev) | ||
94 | { | ||
95 | /* Note not sure if this init of usb_buf is really necessary */ | ||
96 | memset(gspca_dev->usb_buf, 0, 8); | ||
97 | gspca_dev->usb_buf[0] = 0x0f; | ||
98 | |||
99 | if (stv_sndctrl(gspca_dev, 0, 0x87, 0, 0x08) != 0x08) { | ||
100 | PDEBUG(D_ERR, "Get_Camera_Mode failed"); | ||
101 | return stv0680_handle_error(gspca_dev, -EIO); | ||
102 | } | ||
103 | |||
104 | return gspca_dev->usb_buf[0]; /* 01 = VGA, 03 = QVGA, 00 = CIF */ | ||
105 | } | ||
106 | |||
107 | static int stv0680_set_video_mode(struct gspca_dev *gspca_dev, u8 mode) | ||
108 | { | ||
109 | struct sd *sd = (struct sd *) gspca_dev; | ||
110 | |||
111 | if (sd->current_mode == mode) | ||
112 | return 0; | ||
113 | |||
114 | memset(gspca_dev->usb_buf, 0, 8); | ||
115 | gspca_dev->usb_buf[0] = mode; | ||
116 | |||
117 | if (stv_sndctrl(gspca_dev, 3, 0x07, 0x0100, 0x08) != 0x08) { | ||
118 | PDEBUG(D_ERR, "Set_Camera_Mode failed"); | ||
119 | return stv0680_handle_error(gspca_dev, -EIO); | ||
120 | } | ||
121 | |||
122 | /* Verify we got what we've asked for */ | ||
123 | if (stv0680_get_video_mode(gspca_dev) != mode) { | ||
124 | PDEBUG(D_ERR, "Error setting camera video mode!"); | ||
125 | return -EIO; | ||
126 | } | ||
127 | |||
128 | sd->current_mode = mode; | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | /* this function is called at probe time */ | ||
134 | static int sd_config(struct gspca_dev *gspca_dev, | ||
135 | const struct usb_device_id *id) | ||
136 | { | ||
137 | int ret; | ||
138 | struct sd *sd = (struct sd *) gspca_dev; | ||
139 | struct cam *cam = &gspca_dev->cam; | ||
140 | |||
141 | /* ping camera to be sure STV0680 is present */ | ||
142 | if (stv_sndctrl(gspca_dev, 0, 0x88, 0x5678, 0x02) != 0x02 || | ||
143 | gspca_dev->usb_buf[0] != 0x56 || gspca_dev->usb_buf[1] != 0x78) { | ||
144 | PDEBUG(D_ERR, "STV(e): camera ping failed!!"); | ||
145 | return stv0680_handle_error(gspca_dev, -ENODEV); | ||
146 | } | ||
147 | |||
148 | /* get camera descriptor */ | ||
149 | if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0200, 0x09) != 0x09) | ||
150 | return stv0680_handle_error(gspca_dev, -ENODEV); | ||
151 | |||
152 | if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0200, 0x22) != 0x22 || | ||
153 | gspca_dev->usb_buf[7] != 0xa0 || gspca_dev->usb_buf[8] != 0x23) { | ||
154 | PDEBUG(D_ERR, "Could not get descriptor 0200."); | ||
155 | return stv0680_handle_error(gspca_dev, -ENODEV); | ||
156 | } | ||
157 | if (stv_sndctrl(gspca_dev, 0, 0x8a, 0, 0x02) != 0x02) | ||
158 | return stv0680_handle_error(gspca_dev, -ENODEV); | ||
159 | if (stv_sndctrl(gspca_dev, 0, 0x8b, 0, 0x24) != 0x24) | ||
160 | return stv0680_handle_error(gspca_dev, -ENODEV); | ||
161 | if (stv_sndctrl(gspca_dev, 0, 0x85, 0, 0x10) != 0x10) | ||
162 | return stv0680_handle_error(gspca_dev, -ENODEV); | ||
163 | |||
164 | if (!(gspca_dev->usb_buf[7] & 0x09)) { | ||
165 | PDEBUG(D_ERR, "Camera supports neither CIF nor QVGA mode"); | ||
166 | return -ENODEV; | ||
167 | } | ||
168 | if (gspca_dev->usb_buf[7] & 0x01) | ||
169 | PDEBUG(D_PROBE, "Camera supports CIF mode"); | ||
170 | if (gspca_dev->usb_buf[7] & 0x02) | ||
171 | PDEBUG(D_PROBE, "Camera supports VGA mode"); | ||
172 | if (gspca_dev->usb_buf[7] & 0x08) | ||
173 | PDEBUG(D_PROBE, "Camera supports QVGA mode"); | ||
174 | |||
175 | if (gspca_dev->usb_buf[7] & 0x01) | ||
176 | sd->video_mode = 0x00; /* CIF */ | ||
177 | else | ||
178 | sd->video_mode = 0x03; /* QVGA */ | ||
179 | |||
180 | /* FW rev, ASIC rev, sensor ID */ | ||
181 | PDEBUG(D_PROBE, "Firmware rev is %i.%i", | ||
182 | gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]); | ||
183 | PDEBUG(D_PROBE, "ASIC rev is %i.%i", | ||
184 | gspca_dev->usb_buf[2], gspca_dev->usb_buf[3]); | ||
185 | PDEBUG(D_PROBE, "Sensor ID is %i", | ||
186 | (gspca_dev->usb_buf[4]*16) + (gspca_dev->usb_buf[5]>>4)); | ||
187 | |||
188 | |||
189 | ret = stv0680_get_video_mode(gspca_dev); | ||
190 | if (ret < 0) | ||
191 | return ret; | ||
192 | sd->current_mode = sd->orig_mode = ret; | ||
193 | |||
194 | ret = stv0680_set_video_mode(gspca_dev, sd->video_mode); | ||
195 | if (ret < 0) | ||
196 | return ret; | ||
197 | |||
198 | /* Get mode details */ | ||
199 | if (stv_sndctrl(gspca_dev, 0, 0x8f, 0, 0x10) != 0x10) | ||
200 | return stv0680_handle_error(gspca_dev, -EIO); | ||
201 | |||
202 | cam->bulk = 1; | ||
203 | cam->bulk_nurbs = 1; /* The cam cannot handle more */ | ||
204 | cam->bulk_size = (gspca_dev->usb_buf[0] << 24) | | ||
205 | (gspca_dev->usb_buf[1] << 16) | | ||
206 | (gspca_dev->usb_buf[2] << 8) | | ||
207 | (gspca_dev->usb_buf[3]); | ||
208 | sd->mode.width = (gspca_dev->usb_buf[4] << 8) | | ||
209 | (gspca_dev->usb_buf[5]); /* 322, 356, 644 */ | ||
210 | sd->mode.height = (gspca_dev->usb_buf[6] << 8) | | ||
211 | (gspca_dev->usb_buf[7]); /* 242, 292, 484 */ | ||
212 | sd->mode.pixelformat = V4L2_PIX_FMT_STV0680; | ||
213 | sd->mode.field = V4L2_FIELD_NONE; | ||
214 | sd->mode.bytesperline = sd->mode.width; | ||
215 | sd->mode.sizeimage = cam->bulk_size; | ||
216 | sd->mode.colorspace = V4L2_COLORSPACE_SRGB; | ||
217 | |||
218 | /* origGain = gspca_dev->usb_buf[12]; */ | ||
219 | |||
220 | cam->cam_mode = &sd->mode; | ||
221 | cam->nmodes = 1; | ||
222 | |||
223 | |||
224 | ret = stv0680_set_video_mode(gspca_dev, sd->orig_mode); | ||
225 | if (ret < 0) | ||
226 | return ret; | ||
227 | |||
228 | if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0100, 0x12) != 0x12 || | ||
229 | gspca_dev->usb_buf[8] != 0x53 || gspca_dev->usb_buf[9] != 0x05) { | ||
230 | PDEBUG(D_ERR, "Could not get descriptor 0100."); | ||
231 | return stv0680_handle_error(gspca_dev, -EIO); | ||
232 | } | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | /* this function is called at probe and resume time */ | ||
238 | static int sd_init(struct gspca_dev *gspca_dev) | ||
239 | { | ||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | /* -- start the camera -- */ | ||
244 | static int sd_start(struct gspca_dev *gspca_dev) | ||
245 | { | ||
246 | int ret; | ||
247 | struct sd *sd = (struct sd *) gspca_dev; | ||
248 | |||
249 | ret = stv0680_set_video_mode(gspca_dev, sd->video_mode); | ||
250 | if (ret < 0) | ||
251 | return ret; | ||
252 | |||
253 | if (stv_sndctrl(gspca_dev, 0, 0x85, 0, 0x10) != 0x10) | ||
254 | return stv0680_handle_error(gspca_dev, -EIO); | ||
255 | |||
256 | /* Start stream at: | ||
257 | 0x0000 = CIF (352x288) | ||
258 | 0x0100 = VGA (640x480) | ||
259 | 0x0300 = QVGA (320x240) */ | ||
260 | if (stv_sndctrl(gspca_dev, 1, 0x09, sd->video_mode << 8, 0x0) != 0x0) | ||
261 | return stv0680_handle_error(gspca_dev, -EIO); | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
267 | { | ||
268 | /* This is a high priority command; it stops all lower order cmds */ | ||
269 | if (stv_sndctrl(gspca_dev, 1, 0x04, 0x0000, 0x0) != 0x0) | ||
270 | stv0680_handle_error(gspca_dev, -EIO); | ||
271 | } | ||
272 | |||
273 | static void sd_stop0(struct gspca_dev *gspca_dev) | ||
274 | { | ||
275 | struct sd *sd = (struct sd *) gspca_dev; | ||
276 | |||
277 | if (!sd->gspca_dev.present) | ||
278 | return; | ||
279 | |||
280 | stv0680_set_video_mode(gspca_dev, sd->orig_mode); | ||
281 | } | ||
282 | |||
283 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
284 | u8 *data, | ||
285 | int len) | ||
286 | { | ||
287 | struct sd *sd = (struct sd *) gspca_dev; | ||
288 | |||
289 | /* Every now and then the camera sends a 16 byte packet, no idea | ||
290 | what it contains, but it is not image data, when this | ||
291 | happens the frame received before this packet is corrupt, | ||
292 | so discard it. */ | ||
293 | if (len != sd->mode.sizeimage) { | ||
294 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
295 | return; | ||
296 | } | ||
297 | |||
298 | /* Finish the previous frame, we do this upon reception of the next | ||
299 | packet, even though it is already complete so that the strange 16 | ||
300 | byte packets send after a corrupt frame can discard it. */ | ||
301 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); | ||
302 | |||
303 | /* Store the just received frame */ | ||
304 | gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); | ||
305 | } | ||
306 | |||
307 | /* sub-driver description */ | ||
308 | static const struct sd_desc sd_desc = { | ||
309 | .name = MODULE_NAME, | ||
310 | .ctrls = sd_ctrls, | ||
311 | .nctrls = ARRAY_SIZE(sd_ctrls), | ||
312 | .config = sd_config, | ||
313 | .init = sd_init, | ||
314 | .start = sd_start, | ||
315 | .stopN = sd_stopN, | ||
316 | .stop0 = sd_stop0, | ||
317 | .pkt_scan = sd_pkt_scan, | ||
318 | }; | ||
319 | |||
320 | /* -- module initialisation -- */ | ||
321 | static const __devinitdata struct usb_device_id device_table[] = { | ||
322 | {USB_DEVICE(0x0553, 0x0202)}, | ||
323 | {USB_DEVICE(0x041e, 0x4007)}, | ||
324 | {} | ||
325 | }; | ||
326 | MODULE_DEVICE_TABLE(usb, device_table); | ||
327 | |||
328 | /* -- device connect -- */ | ||
329 | static int sd_probe(struct usb_interface *intf, | ||
330 | const struct usb_device_id *id) | ||
331 | { | ||
332 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | ||
333 | THIS_MODULE); | ||
334 | } | ||
335 | |||
336 | static struct usb_driver sd_driver = { | ||
337 | .name = MODULE_NAME, | ||
338 | .id_table = device_table, | ||
339 | .probe = sd_probe, | ||
340 | .disconnect = gspca_disconnect, | ||
341 | #ifdef CONFIG_PM | ||
342 | .suspend = gspca_suspend, | ||
343 | .resume = gspca_resume, | ||
344 | #endif | ||
345 | }; | ||
346 | |||
347 | /* -- module insert / remove -- */ | ||
348 | static int __init sd_mod_init(void) | ||
349 | { | ||
350 | int ret; | ||
351 | ret = usb_register(&sd_driver); | ||
352 | if (ret < 0) | ||
353 | return ret; | ||
354 | PDEBUG(D_PROBE, "registered"); | ||
355 | return 0; | ||
356 | } | ||
357 | static void __exit sd_mod_exit(void) | ||
358 | { | ||
359 | usb_deregister(&sd_driver); | ||
360 | PDEBUG(D_PROBE, "deregistered"); | ||
361 | } | ||
362 | |||
363 | module_init(sd_mod_init); | ||
364 | module_exit(sd_mod_exit); | ||
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c index bfae63f5584c..5d0241bb1611 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx.c | |||
@@ -312,8 +312,7 @@ out: | |||
312 | * The 0005 and 0100 chunks seem to appear only in compressed stream. | 312 | * The 0005 and 0100 chunks seem to appear only in compressed stream. |
313 | */ | 313 | */ |
314 | static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev, | 314 | static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev, |
315 | struct gspca_frame *frame, /* target */ | 315 | u8 *data, /* isoc packet */ |
316 | __u8 *data, /* isoc packet */ | ||
317 | int len) /* iso packet length */ | 316 | int len) /* iso packet length */ |
318 | { | 317 | { |
319 | struct sd *sd = (struct sd *) gspca_dev; | 318 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -366,7 +365,7 @@ frame_data: | |||
366 | sd->to_skip -= skip; | 365 | sd->to_skip -= skip; |
367 | } | 366 | } |
368 | 367 | ||
369 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | 368 | gspca_frame_add(gspca_dev, INTER_PACKET, |
370 | data, chunk_len); | 369 | data, chunk_len); |
371 | break; | 370 | break; |
372 | 371 | ||
@@ -378,7 +377,7 @@ frame_data: | |||
378 | 377 | ||
379 | /* Create a new frame, chunk length should be zero */ | 378 | /* Create a new frame, chunk length should be zero */ |
380 | gspca_frame_add(gspca_dev, FIRST_PACKET, | 379 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
381 | frame, data, 0); | 380 | NULL, 0); |
382 | 381 | ||
383 | if (sd->bridge == BRIDGE_ST6422) | 382 | if (sd->bridge == BRIDGE_ST6422) |
384 | sd->to_skip = gspca_dev->width * 4; | 383 | sd->to_skip = gspca_dev->width * 4; |
@@ -394,8 +393,8 @@ frame_data: | |||
394 | PDEBUG(D_PACK, "End of frame detected"); | 393 | PDEBUG(D_PACK, "End of frame detected"); |
395 | 394 | ||
396 | /* Complete the last frame (if any) */ | 395 | /* Complete the last frame (if any) */ |
397 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, | 396 | gspca_frame_add(gspca_dev, LAST_PACKET, |
398 | frame, data, 0); | 397 | NULL, 0); |
399 | 398 | ||
400 | if (chunk_len) | 399 | if (chunk_len) |
401 | PDEBUG(D_ERR, "Chunk length is " | 400 | PDEBUG(D_ERR, "Chunk length is " |
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index 1a9af2ebdbef..72bf3b4f0a31 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c | |||
@@ -1116,7 +1116,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
1116 | } | 1116 | } |
1117 | 1117 | ||
1118 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 1118 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
1119 | struct gspca_frame *frame, /* target */ | ||
1120 | u8 *data, /* isoc packet */ | 1119 | u8 *data, /* isoc packet */ |
1121 | int len) /* iso packet length */ | 1120 | int len) /* iso packet length */ |
1122 | { | 1121 | { |
@@ -1186,11 +1185,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1186 | break; | 1185 | break; |
1187 | } | 1186 | } |
1188 | if (sof) { /* start of frame */ | 1187 | if (sof) { /* start of frame */ |
1189 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | 1188 | gspca_frame_add(gspca_dev, LAST_PACKET, |
1190 | ffd9, 2); | 1189 | ffd9, 2); |
1191 | 1190 | ||
1192 | /* put the JPEG header in the new frame */ | 1191 | /* put the JPEG header in the new frame */ |
1193 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | 1192 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
1194 | sd->jpeg_hdr, JPEG_HDR_SZ); | 1193 | sd->jpeg_hdr, JPEG_HDR_SZ); |
1195 | } | 1194 | } |
1196 | 1195 | ||
@@ -1198,7 +1197,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1198 | i = 0; | 1197 | i = 0; |
1199 | do { | 1198 | do { |
1200 | if (data[i] == 0xff) { | 1199 | if (data[i] == 0xff) { |
1201 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | 1200 | gspca_frame_add(gspca_dev, INTER_PACKET, |
1202 | data, i + 1); | 1201 | data, i + 1); |
1203 | len -= i; | 1202 | len -= i; |
1204 | data += i; | 1203 | data += i; |
@@ -1207,7 +1206,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1207 | } | 1206 | } |
1208 | i++; | 1207 | i++; |
1209 | } while (i < len); | 1208 | } while (i < len); |
1210 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | 1209 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
1211 | } | 1210 | } |
1212 | 1211 | ||
1213 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 1212 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) |
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 1d321c30d22f..55ef6a744427 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c | |||
@@ -938,7 +938,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
938 | } | 938 | } |
939 | 939 | ||
940 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 940 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
941 | struct gspca_frame *frame, /* target */ | ||
942 | u8 *data, /* isoc packet */ | 941 | u8 *data, /* isoc packet */ |
943 | int len) /* iso packet length */ | 942 | int len) /* iso packet length */ |
944 | { | 943 | { |
@@ -956,9 +955,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
956 | /* extra bytes....., could be processed too but would be | 955 | /* extra bytes....., could be processed too but would be |
957 | * a waste of time, right now leave the application and | 956 | * a waste of time, right now leave the application and |
958 | * libjpeg do it for ourserlves.. */ | 957 | * libjpeg do it for ourserlves.. */ |
959 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | 958 | gspca_frame_add(gspca_dev, LAST_PACKET, |
960 | ffd9, 2); | 959 | ffd9, 2); |
961 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); | 960 | gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); |
962 | return; | 961 | return; |
963 | } | 962 | } |
964 | 963 | ||
@@ -967,7 +966,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
967 | * other's do not include it... */ | 966 | * other's do not include it... */ |
968 | len -= 2; | 967 | len -= 2; |
969 | } | 968 | } |
970 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | 969 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
971 | } | 970 | } |
972 | 971 | ||
973 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 972 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) |
diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c index 4b44dde9f8b8..b74a3b6489c7 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/video/gspca/tv8532.c | |||
@@ -398,8 +398,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
398 | } | 398 | } |
399 | 399 | ||
400 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 400 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
401 | struct gspca_frame *frame, /* target */ | 401 | u8 *data, /* isoc packet */ |
402 | __u8 *data, /* isoc packet */ | ||
403 | int len) /* iso packet length */ | 402 | int len) /* iso packet length */ |
404 | { | 403 | { |
405 | struct sd *sd = (struct sd *) gspca_dev; | 404 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -424,9 +423,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
424 | * - 4 bytes | 423 | * - 4 bytes |
425 | */ | 424 | */ |
426 | gspca_frame_add(gspca_dev, packet_type0, | 425 | gspca_frame_add(gspca_dev, packet_type0, |
427 | frame, data + 2, gspca_dev->width); | 426 | data + 2, gspca_dev->width); |
428 | gspca_frame_add(gspca_dev, packet_type1, | 427 | gspca_frame_add(gspca_dev, packet_type1, |
429 | frame, data + gspca_dev->width + 5, gspca_dev->width); | 428 | data + gspca_dev->width + 5, gspca_dev->width); |
430 | } | 429 | } |
431 | 430 | ||
432 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 431 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) |
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 589042f6adbe..c090efcd8045 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c | |||
@@ -2987,7 +2987,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
2987 | } | 2987 | } |
2988 | 2988 | ||
2989 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 2989 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
2990 | struct gspca_frame *frame, /* target */ | ||
2991 | u8 *data, /* isoc packet */ | 2990 | u8 *data, /* isoc packet */ |
2992 | int len) /* iso pkt length */ | 2991 | int len) /* iso pkt length */ |
2993 | { | 2992 | { |
@@ -2996,21 +2995,25 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
2996 | if (data[0] == 0xff && data[1] == 0xd8) { | 2995 | if (data[0] == 0xff && data[1] == 0xd8) { |
2997 | PDEBUG(D_PACK, | 2996 | PDEBUG(D_PACK, |
2998 | "vc032x header packet found len %d", len); | 2997 | "vc032x header packet found len %d", len); |
2999 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | 2998 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); |
3000 | data, 0); | ||
3001 | data += sd->image_offset; | 2999 | data += sd->image_offset; |
3002 | len -= sd->image_offset; | 3000 | len -= sd->image_offset; |
3003 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | 3001 | gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); |
3004 | data, len); | ||
3005 | return; | 3002 | return; |
3006 | } | 3003 | } |
3007 | 3004 | ||
3008 | /* The vc0321 sends some additional data after sending the complete | 3005 | /* The vc0321 sends some additional data after sending the complete |
3009 | * frame, we ignore this. */ | 3006 | * frame, we ignore this. */ |
3010 | if (sd->bridge == BRIDGE_VC0321 | 3007 | if (sd->bridge == BRIDGE_VC0321) { |
3011 | && len > frame->v4l2_buf.length - (frame->data_end - frame->data)) | 3008 | struct gspca_frame *frame; |
3012 | len = frame->v4l2_buf.length - (frame->data_end - frame->data); | 3009 | int l; |
3013 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | 3010 | |
3011 | frame = gspca_get_i_frame(gspca_dev); | ||
3012 | l = frame->data_end - frame->data; | ||
3013 | if (len > frame->v4l2_buf.length - l) | ||
3014 | len = frame->v4l2_buf.length - l; | ||
3015 | } | ||
3016 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | ||
3014 | } | 3017 | } |
3015 | 3018 | ||
3016 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) | 3019 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) |
@@ -3092,6 +3095,8 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, | |||
3092 | 3095 | ||
3093 | switch (menu->id) { | 3096 | switch (menu->id) { |
3094 | case V4L2_CID_POWER_LINE_FREQUENCY: | 3097 | case V4L2_CID_POWER_LINE_FREQUENCY: |
3098 | if (menu->index >= ARRAY_SIZE(freq_nm)) | ||
3099 | break; | ||
3095 | strcpy((char *) menu->name, freq_nm[menu->index]); | 3100 | strcpy((char *) menu->name, freq_nm[menu->index]); |
3096 | return 0; | 3101 | return 0; |
3097 | } | 3102 | } |
diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/video/gspca/w996Xcf.c new file mode 100644 index 000000000000..2fffe203bed8 --- /dev/null +++ b/drivers/media/video/gspca/w996Xcf.c | |||
@@ -0,0 +1,609 @@ | |||
1 | /** | ||
2 | * | ||
3 | * GSPCA sub driver for W996[78]CF JPEG USB Dual Mode Camera Chip. | ||
4 | * | ||
5 | * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> | ||
6 | * | ||
7 | * This module is adapted from the in kernel v4l1 w9968cf driver: | ||
8 | * | ||
9 | * Copyright (C) 2002-2004 by Luca Risolia <luca.risolia@studio.unibo.it> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | /* Note this is not a stand alone driver, it gets included in ov519.c, this | ||
28 | is a bit of a hack, but it needs the driver code for a lot of different | ||
29 | ov sensors which is already present in ov519.c (the old v4l1 driver used | ||
30 | the ovchipcam framework). When we have the time we really should move | ||
31 | the sensor drivers to v4l2 sub drivers, and properly split of this | ||
32 | driver from ov519.c */ | ||
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 */ | ||
39 | |||
40 | #define Y_QUANTABLE (sd->jpeg_hdr + JPEG_QT0_OFFSET) | ||
41 | #define UV_QUANTABLE (sd->jpeg_hdr + JPEG_QT1_OFFSET) | ||
42 | |||
43 | static const struct v4l2_pix_format w9968cf_vga_mode[] = { | ||
44 | {160, 120, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, | ||
45 | .bytesperline = 160 * 2, | ||
46 | .sizeimage = 160 * 120 * 2, | ||
47 | .colorspace = V4L2_COLORSPACE_JPEG}, | ||
48 | {176, 144, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, | ||
49 | .bytesperline = 176 * 2, | ||
50 | .sizeimage = 176 * 144 * 2, | ||
51 | .colorspace = V4L2_COLORSPACE_JPEG}, | ||
52 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
53 | .bytesperline = 320 * 2, | ||
54 | .sizeimage = 320 * 240 * 2, | ||
55 | .colorspace = V4L2_COLORSPACE_JPEG}, | ||
56 | {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
57 | .bytesperline = 352 * 2, | ||
58 | .sizeimage = 352 * 288 * 2, | ||
59 | .colorspace = V4L2_COLORSPACE_JPEG}, | ||
60 | {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
61 | .bytesperline = 640 * 2, | ||
62 | .sizeimage = 640 * 480 * 2, | ||
63 | .colorspace = V4L2_COLORSPACE_JPEG}, | ||
64 | }; | ||
65 | |||
66 | static int reg_w(struct sd *sd, __u16 index, __u16 value); | ||
67 | |||
68 | /*-------------------------------------------------------------------------- | ||
69 | Write 64-bit data to the fast serial bus registers. | ||
70 | Return 0 on success, -1 otherwise. | ||
71 | --------------------------------------------------------------------------*/ | ||
72 | static int w9968cf_write_fsb(struct sd *sd, u16* data) | ||
73 | { | ||
74 | struct usb_device* udev = sd->gspca_dev.dev; | ||
75 | u16 value; | ||
76 | int ret; | ||
77 | |||
78 | value = *data++; | ||
79 | memcpy(sd->gspca_dev.usb_buf, data, 6); | ||
80 | |||
81 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, | ||
82 | USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, | ||
83 | value, 0x06, sd->gspca_dev.usb_buf, 6, 500); | ||
84 | if (ret < 0) { | ||
85 | PDEBUG(D_ERR, "Write FSB registers failed (%d)", ret); | ||
86 | return ret; | ||
87 | } | ||
88 | |||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | /*-------------------------------------------------------------------------- | ||
93 | Write data to the serial bus control register. | ||
94 | Return 0 on success, a negative number otherwise. | ||
95 | --------------------------------------------------------------------------*/ | ||
96 | static int w9968cf_write_sb(struct sd *sd, u16 value) | ||
97 | { | ||
98 | int ret; | ||
99 | |||
100 | /* We don't use reg_w here, as that would cause all writes when | ||
101 | bitbanging i2c to be logged, making the logs impossible to read */ | ||
102 | ret = usb_control_msg(sd->gspca_dev.dev, | ||
103 | usb_sndctrlpipe(sd->gspca_dev.dev, 0), | ||
104 | 0, | ||
105 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
106 | value, 0x01, NULL, 0, 500); | ||
107 | |||
108 | udelay(W9968CF_I2C_BUS_DELAY); | ||
109 | |||
110 | if (ret < 0) { | ||
111 | PDEBUG(D_ERR, "Write SB reg [01] %04x failed", value); | ||
112 | return ret; | ||
113 | } | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | /*-------------------------------------------------------------------------- | ||
119 | Read data from the serial bus control register. | ||
120 | Return 0 on success, a negative number otherwise. | ||
121 | --------------------------------------------------------------------------*/ | ||
122 | static int w9968cf_read_sb(struct sd *sd) | ||
123 | { | ||
124 | int ret; | ||
125 | |||
126 | /* We don't use reg_r here, as the w9968cf is special and has 16 | ||
127 | bit registers instead of 8 bit */ | ||
128 | ret = usb_control_msg(sd->gspca_dev.dev, | ||
129 | usb_rcvctrlpipe(sd->gspca_dev.dev, 0), | ||
130 | 1, | ||
131 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
132 | 0, 0x01, sd->gspca_dev.usb_buf, 2, 500); | ||
133 | if (ret >= 0) | ||
134 | ret = sd->gspca_dev.usb_buf[0] | | ||
135 | (sd->gspca_dev.usb_buf[1] << 8); | ||
136 | else | ||
137 | PDEBUG(D_ERR, "Read SB reg [01] failed"); | ||
138 | |||
139 | udelay(W9968CF_I2C_BUS_DELAY); | ||
140 | |||
141 | return ret; | ||
142 | } | ||
143 | |||
144 | /*-------------------------------------------------------------------------- | ||
145 | Upload quantization tables for the JPEG compression. | ||
146 | This function is called by w9968cf_start_transfer(). | ||
147 | Return 0 on success, a negative number otherwise. | ||
148 | --------------------------------------------------------------------------*/ | ||
149 | static int w9968cf_upload_quantizationtables(struct sd *sd) | ||
150 | { | ||
151 | u16 a, b; | ||
152 | int ret = 0, i, j; | ||
153 | |||
154 | ret += reg_w(sd, 0x39, 0x0010); /* JPEG clock enable */ | ||
155 | |||
156 | for (i = 0, j = 0; i < 32; i++, j += 2) { | ||
157 | a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j+1]) << 8); | ||
158 | b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j+1]) << 8); | ||
159 | ret += reg_w(sd, 0x40+i, a); | ||
160 | ret += reg_w(sd, 0x60+i, b); | ||
161 | } | ||
162 | ret += reg_w(sd, 0x39, 0x0012); /* JPEG encoder enable */ | ||
163 | |||
164 | return ret; | ||
165 | } | ||
166 | |||
167 | /**************************************************************************** | ||
168 | * Low-level I2C I/O functions. * | ||
169 | * The adapter supports the following I2C transfer functions: * | ||
170 | * i2c_adap_fastwrite_byte_data() (at 400 kHz bit frequency only) * | ||
171 | * i2c_adap_read_byte_data() * | ||
172 | * i2c_adap_read_byte() * | ||
173 | ****************************************************************************/ | ||
174 | |||
175 | static int w9968cf_smbus_start(struct sd *sd) | ||
176 | { | ||
177 | int ret = 0; | ||
178 | |||
179 | ret += w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ | ||
180 | ret += w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ | ||
181 | |||
182 | return ret; | ||
183 | } | ||
184 | |||
185 | static int w9968cf_smbus_stop(struct sd *sd) | ||
186 | { | ||
187 | int ret = 0; | ||
188 | |||
189 | ret += w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ | ||
190 | ret += w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ | ||
191 | ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ | ||
192 | |||
193 | return ret; | ||
194 | } | ||
195 | |||
196 | static int w9968cf_smbus_write_byte(struct sd *sd, u8 v) | ||
197 | { | ||
198 | u8 bit; | ||
199 | int ret = 0, sda; | ||
200 | |||
201 | for (bit = 0 ; bit < 8 ; bit++) { | ||
202 | sda = (v & 0x80) ? 2 : 0; | ||
203 | v <<= 1; | ||
204 | /* SDE=1, SDA=sda, SCL=0 */ | ||
205 | ret += w9968cf_write_sb(sd, 0x10 | sda); | ||
206 | /* SDE=1, SDA=sda, SCL=1 */ | ||
207 | ret += w9968cf_write_sb(sd, 0x11 | sda); | ||
208 | /* SDE=1, SDA=sda, SCL=0 */ | ||
209 | ret += w9968cf_write_sb(sd, 0x10 | sda); | ||
210 | } | ||
211 | |||
212 | return ret; | ||
213 | } | ||
214 | |||
215 | static int w9968cf_smbus_read_byte(struct sd *sd, u8* v) | ||
216 | { | ||
217 | u8 bit; | ||
218 | int ret = 0; | ||
219 | |||
220 | /* No need to ensure SDA is high as we are always called after | ||
221 | read_ack which ends with SDA high */ | ||
222 | *v = 0; | ||
223 | for (bit = 0 ; bit < 8 ; bit++) { | ||
224 | *v <<= 1; | ||
225 | /* SDE=1, SDA=1, SCL=1 */ | ||
226 | ret += w9968cf_write_sb(sd, 0x0013); | ||
227 | *v |= (w9968cf_read_sb(sd) & 0x0008) ? 1 : 0; | ||
228 | /* SDE=1, SDA=1, SCL=0 */ | ||
229 | ret += w9968cf_write_sb(sd, 0x0012); | ||
230 | } | ||
231 | |||
232 | return ret; | ||
233 | } | ||
234 | |||
235 | static int w9968cf_smbus_write_nack(struct sd *sd) | ||
236 | { | ||
237 | int ret = 0; | ||
238 | |||
239 | /* No need to ensure SDA is high as we are always called after | ||
240 | read_byte which ends with SDA high */ | ||
241 | ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ | ||
242 | ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ | ||
243 | |||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | static int w9968cf_smbus_read_ack(struct sd *sd) | ||
248 | { | ||
249 | int ret = 0, sda; | ||
250 | |||
251 | /* Ensure SDA is high before raising clock to avoid a spurious stop */ | ||
252 | ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ | ||
253 | ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ | ||
254 | sda = w9968cf_read_sb(sd); | ||
255 | ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ | ||
256 | if (sda < 0) | ||
257 | ret += sda; | ||
258 | else if (sda & 0x08) { | ||
259 | PDEBUG(D_USBI, "Did not receive i2c ACK"); | ||
260 | ret += -1; | ||
261 | } | ||
262 | |||
263 | return ret; | ||
264 | } | ||
265 | |||
266 | /* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */ | ||
267 | static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) | ||
268 | { | ||
269 | u16* data = (u16 *)sd->gspca_dev.usb_buf; | ||
270 | int ret = 0; | ||
271 | |||
272 | data[0] = 0x082f | ((sd->sensor_addr & 0x80) ? 0x1500 : 0x0); | ||
273 | data[0] |= (sd->sensor_addr & 0x40) ? 0x4000 : 0x0; | ||
274 | data[1] = 0x2082 | ((sd->sensor_addr & 0x40) ? 0x0005 : 0x0); | ||
275 | data[1] |= (sd->sensor_addr & 0x20) ? 0x0150 : 0x0; | ||
276 | data[1] |= (sd->sensor_addr & 0x10) ? 0x5400 : 0x0; | ||
277 | data[2] = 0x8208 | ((sd->sensor_addr & 0x08) ? 0x0015 : 0x0); | ||
278 | data[2] |= (sd->sensor_addr & 0x04) ? 0x0540 : 0x0; | ||
279 | data[2] |= (sd->sensor_addr & 0x02) ? 0x5000 : 0x0; | ||
280 | data[3] = 0x1d20 | ((sd->sensor_addr & 0x02) ? 0x0001 : 0x0); | ||
281 | data[3] |= (sd->sensor_addr & 0x01) ? 0x0054 : 0x0; | ||
282 | |||
283 | ret += w9968cf_write_fsb(sd, data); | ||
284 | |||
285 | data[0] = 0x8208 | ((reg & 0x80) ? 0x0015 : 0x0); | ||
286 | data[0] |= (reg & 0x40) ? 0x0540 : 0x0; | ||
287 | data[0] |= (reg & 0x20) ? 0x5000 : 0x0; | ||
288 | data[1] = 0x0820 | ((reg & 0x20) ? 0x0001 : 0x0); | ||
289 | data[1] |= (reg & 0x10) ? 0x0054 : 0x0; | ||
290 | data[1] |= (reg & 0x08) ? 0x1500 : 0x0; | ||
291 | data[1] |= (reg & 0x04) ? 0x4000 : 0x0; | ||
292 | data[2] = 0x2082 | ((reg & 0x04) ? 0x0005 : 0x0); | ||
293 | data[2] |= (reg & 0x02) ? 0x0150 : 0x0; | ||
294 | data[2] |= (reg & 0x01) ? 0x5400 : 0x0; | ||
295 | data[3] = 0x001d; | ||
296 | |||
297 | ret += w9968cf_write_fsb(sd, data); | ||
298 | |||
299 | data[0] = 0x8208 | ((value & 0x80) ? 0x0015 : 0x0); | ||
300 | data[0] |= (value & 0x40) ? 0x0540 : 0x0; | ||
301 | data[0] |= (value & 0x20) ? 0x5000 : 0x0; | ||
302 | data[1] = 0x0820 | ((value & 0x20) ? 0x0001 : 0x0); | ||
303 | data[1] |= (value & 0x10) ? 0x0054 : 0x0; | ||
304 | data[1] |= (value & 0x08) ? 0x1500 : 0x0; | ||
305 | data[1] |= (value & 0x04) ? 0x4000 : 0x0; | ||
306 | data[2] = 0x2082 | ((value & 0x04) ? 0x0005 : 0x0); | ||
307 | data[2] |= (value & 0x02) ? 0x0150 : 0x0; | ||
308 | data[2] |= (value & 0x01) ? 0x5400 : 0x0; | ||
309 | data[3] = 0xfe1d; | ||
310 | |||
311 | ret += w9968cf_write_fsb(sd, data); | ||
312 | |||
313 | if (!ret) | ||
314 | PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); | ||
315 | else | ||
316 | PDEBUG(D_ERR, "i2c 0x%02x -> [0x%02x] failed", value, reg); | ||
317 | |||
318 | return ret; | ||
319 | } | ||
320 | |||
321 | /* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */ | ||
322 | static int w9968cf_i2c_r(struct sd *sd, u8 reg) | ||
323 | { | ||
324 | int ret = 0; | ||
325 | u8 value; | ||
326 | |||
327 | /* Fast serial bus data control disable */ | ||
328 | ret += w9968cf_write_sb(sd, 0x0013); /* don't change ! */ | ||
329 | |||
330 | ret += w9968cf_smbus_start(sd); | ||
331 | ret += w9968cf_smbus_write_byte(sd, sd->sensor_addr); | ||
332 | ret += w9968cf_smbus_read_ack(sd); | ||
333 | ret += w9968cf_smbus_write_byte(sd, reg); | ||
334 | ret += w9968cf_smbus_read_ack(sd); | ||
335 | ret += w9968cf_smbus_stop(sd); | ||
336 | ret += w9968cf_smbus_start(sd); | ||
337 | ret += w9968cf_smbus_write_byte(sd, sd->sensor_addr + 1); | ||
338 | ret += w9968cf_smbus_read_ack(sd); | ||
339 | ret += w9968cf_smbus_read_byte(sd, &value); | ||
340 | /* signal we don't want to read anymore, the v4l1 driver used to | ||
341 | send an ack here which is very wrong! (and then fixed | ||
342 | the issues this gave by retrying reads) */ | ||
343 | ret += w9968cf_smbus_write_nack(sd); | ||
344 | ret += w9968cf_smbus_stop(sd); | ||
345 | |||
346 | /* Fast serial bus data control re-enable */ | ||
347 | ret += w9968cf_write_sb(sd, 0x0030); | ||
348 | |||
349 | if (!ret) { | ||
350 | ret = value; | ||
351 | PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); | ||
352 | } else | ||
353 | PDEBUG(D_ERR, "i2c read [0x%02x] failed", reg); | ||
354 | |||
355 | return ret; | ||
356 | } | ||
357 | |||
358 | |||
359 | /*-------------------------------------------------------------------------- | ||
360 | Turn on the LED on some webcams. A beep should be heard too. | ||
361 | Return 0 on success, a negative number otherwise. | ||
362 | --------------------------------------------------------------------------*/ | ||
363 | static int w9968cf_configure(struct sd *sd) | ||
364 | { | ||
365 | int ret = 0; | ||
366 | |||
367 | ret += reg_w(sd, 0x00, 0xff00); /* power-down */ | ||
368 | ret += reg_w(sd, 0x00, 0xbf17); /* reset everything */ | ||
369 | ret += reg_w(sd, 0x00, 0xbf10); /* normal operation */ | ||
370 | ret += reg_w(sd, 0x01, 0x0010); /* serial bus, SDS high */ | ||
371 | ret += reg_w(sd, 0x01, 0x0000); /* serial bus, SDS low */ | ||
372 | ret += reg_w(sd, 0x01, 0x0010); /* ..high 'beep-beep' */ | ||
373 | ret += reg_w(sd, 0x01, 0x0030); /* Set sda scl to FSB mode */ | ||
374 | |||
375 | if (ret) | ||
376 | PDEBUG(D_ERR, "Couldn't turn on the LED"); | ||
377 | |||
378 | sd->stopped = 1; | ||
379 | |||
380 | return ret; | ||
381 | } | ||
382 | |||
383 | static int w9968cf_init(struct sd *sd) | ||
384 | { | ||
385 | int ret = 0; | ||
386 | unsigned long hw_bufsize = sd->sif ? (352 * 288 * 2) : (640 * 480 * 2), | ||
387 | y0 = 0x0000, | ||
388 | u0 = y0 + hw_bufsize/2, | ||
389 | v0 = u0 + hw_bufsize/4, | ||
390 | y1 = v0 + hw_bufsize/4, | ||
391 | u1 = y1 + hw_bufsize/2, | ||
392 | v1 = u1 + hw_bufsize/4; | ||
393 | |||
394 | ret += reg_w(sd, 0x00, 0xff00); /* power off */ | ||
395 | ret += reg_w(sd, 0x00, 0xbf10); /* power on */ | ||
396 | |||
397 | ret += reg_w(sd, 0x03, 0x405d); /* DRAM timings */ | ||
398 | ret += reg_w(sd, 0x04, 0x0030); /* SDRAM timings */ | ||
399 | |||
400 | ret += reg_w(sd, 0x20, y0 & 0xffff); /* Y buf.0, low */ | ||
401 | ret += reg_w(sd, 0x21, y0 >> 16); /* Y buf.0, high */ | ||
402 | ret += reg_w(sd, 0x24, u0 & 0xffff); /* U buf.0, low */ | ||
403 | ret += reg_w(sd, 0x25, u0 >> 16); /* U buf.0, high */ | ||
404 | ret += reg_w(sd, 0x28, v0 & 0xffff); /* V buf.0, low */ | ||
405 | ret += reg_w(sd, 0x29, v0 >> 16); /* V buf.0, high */ | ||
406 | |||
407 | ret += reg_w(sd, 0x22, y1 & 0xffff); /* Y buf.1, low */ | ||
408 | ret += reg_w(sd, 0x23, y1 >> 16); /* Y buf.1, high */ | ||
409 | ret += reg_w(sd, 0x26, u1 & 0xffff); /* U buf.1, low */ | ||
410 | ret += reg_w(sd, 0x27, u1 >> 16); /* U buf.1, high */ | ||
411 | ret += reg_w(sd, 0x2a, v1 & 0xffff); /* V buf.1, low */ | ||
412 | ret += reg_w(sd, 0x2b, v1 >> 16); /* V buf.1, high */ | ||
413 | |||
414 | ret += reg_w(sd, 0x32, y1 & 0xffff); /* JPEG buf 0 low */ | ||
415 | ret += reg_w(sd, 0x33, y1 >> 16); /* JPEG buf 0 high */ | ||
416 | |||
417 | ret += reg_w(sd, 0x34, y1 & 0xffff); /* JPEG buf 1 low */ | ||
418 | ret += reg_w(sd, 0x35, y1 >> 16); /* JPEG bug 1 high */ | ||
419 | |||
420 | ret += reg_w(sd, 0x36, 0x0000);/* JPEG restart interval */ | ||
421 | ret += reg_w(sd, 0x37, 0x0804);/*JPEG VLE FIFO threshold*/ | ||
422 | ret += reg_w(sd, 0x38, 0x0000);/* disable hw up-scaling */ | ||
423 | ret += reg_w(sd, 0x3f, 0x0000); /* JPEG/MCTL test data */ | ||
424 | |||
425 | return ret; | ||
426 | } | ||
427 | |||
428 | static int w9968cf_set_crop_window(struct sd *sd) | ||
429 | { | ||
430 | int ret = 0, start_cropx, start_cropy, x, y, fw, fh, cw, ch, | ||
431 | max_width, max_height; | ||
432 | |||
433 | if (sd->sif) { | ||
434 | max_width = 352; | ||
435 | max_height = 288; | ||
436 | } else { | ||
437 | max_width = 640; | ||
438 | max_height = 480; | ||
439 | } | ||
440 | |||
441 | if (sd->sensor == SEN_OV7620) { | ||
442 | /* Sigh, this is dependend on the clock / framerate changes | ||
443 | made by the frequency control, sick. */ | ||
444 | if (sd->freq == 1) { | ||
445 | start_cropx = 277; | ||
446 | start_cropy = 37; | ||
447 | } else { | ||
448 | start_cropx = 105; | ||
449 | start_cropy = 37; | ||
450 | } | ||
451 | } else { | ||
452 | start_cropx = 320; | ||
453 | start_cropy = 35; | ||
454 | } | ||
455 | |||
456 | /* Work around to avoid FP arithmetics */ | ||
457 | #define SC(x) ((x) << 10) | ||
458 | |||
459 | /* Scaling factors */ | ||
460 | fw = SC(sd->gspca_dev.width) / max_width; | ||
461 | fh = SC(sd->gspca_dev.height) / max_height; | ||
462 | |||
463 | cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.width)/fh; | ||
464 | ch = (fw >= fh) ? SC(sd->gspca_dev.height)/fw : max_height; | ||
465 | |||
466 | sd->sensor_width = max_width; | ||
467 | sd->sensor_height = max_height; | ||
468 | |||
469 | x = (max_width - cw) / 2; | ||
470 | y = (max_height - ch) / 2; | ||
471 | |||
472 | ret += reg_w(sd, 0x10, start_cropx + x); | ||
473 | ret += reg_w(sd, 0x11, start_cropy + y); | ||
474 | ret += reg_w(sd, 0x12, start_cropx + x + cw); | ||
475 | ret += reg_w(sd, 0x13, start_cropy + y + ch); | ||
476 | |||
477 | return ret; | ||
478 | } | ||
479 | |||
480 | static int w9968cf_mode_init_regs(struct sd *sd) | ||
481 | { | ||
482 | int ret = 0, val, vs_polarity, hs_polarity; | ||
483 | |||
484 | ret += w9968cf_set_crop_window(sd); | ||
485 | |||
486 | ret += reg_w(sd, 0x14, sd->gspca_dev.width); | ||
487 | ret += reg_w(sd, 0x15, sd->gspca_dev.height); | ||
488 | |||
489 | /* JPEG width & height */ | ||
490 | ret += reg_w(sd, 0x30, sd->gspca_dev.width); | ||
491 | ret += reg_w(sd, 0x31, sd->gspca_dev.height); | ||
492 | |||
493 | /* Y & UV frame buffer strides (in WORD) */ | ||
494 | if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == | ||
495 | V4L2_PIX_FMT_JPEG) { | ||
496 | ret += reg_w(sd, 0x2c, sd->gspca_dev.width/2); | ||
497 | ret += reg_w(sd, 0x2d, sd->gspca_dev.width/4); | ||
498 | } else | ||
499 | ret += reg_w(sd, 0x2c, sd->gspca_dev.width); | ||
500 | |||
501 | ret += reg_w(sd, 0x00, 0xbf17); /* reset everything */ | ||
502 | ret += reg_w(sd, 0x00, 0xbf10); /* normal operation */ | ||
503 | |||
504 | /* Transfer size in WORDS (for UYVY format only) */ | ||
505 | val = sd->gspca_dev.width * sd->gspca_dev.height; | ||
506 | ret += reg_w(sd, 0x3d, val & 0xffff); /* low bits */ | ||
507 | ret += reg_w(sd, 0x3e, val >> 16); /* high bits */ | ||
508 | |||
509 | if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == | ||
510 | V4L2_PIX_FMT_JPEG) { | ||
511 | /* 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, | ||
518 | sd->gspca_dev.width, 0x22); /* JPEG 420 */ | ||
519 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | ||
520 | ret += w9968cf_upload_quantizationtables(sd); | ||
521 | } | ||
522 | |||
523 | /* Video Capture Control Register */ | ||
524 | if (sd->sensor == SEN_OV7620) { | ||
525 | /* Seems to work around a bug in the image sensor */ | ||
526 | vs_polarity = 1; | ||
527 | hs_polarity = 1; | ||
528 | } else { | ||
529 | vs_polarity = 1; | ||
530 | hs_polarity = 0; | ||
531 | } | ||
532 | |||
533 | val = (vs_polarity << 12) | (hs_polarity << 11); | ||
534 | |||
535 | /* NOTE: We may not have enough memory to do double buffering while | ||
536 | doing compression (amount of memory differs per model cam). | ||
537 | So we use the second image buffer also as jpeg stream buffer | ||
538 | (see w9968cf_init), and disable double buffering. */ | ||
539 | if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == | ||
540 | V4L2_PIX_FMT_JPEG) { | ||
541 | /* val |= 0x0002; YUV422P */ | ||
542 | val |= 0x0003; /* YUV420P */ | ||
543 | } else | ||
544 | val |= 0x0080; /* Enable HW double buffering */ | ||
545 | |||
546 | /* val |= 0x0020; enable clamping */ | ||
547 | /* val |= 0x0008; enable (1-2-1) filter */ | ||
548 | /* val |= 0x000c; enable (2-3-6-3-2) filter */ | ||
549 | |||
550 | val |= 0x8000; /* capt. enable */ | ||
551 | |||
552 | ret += reg_w(sd, 0x16, val); | ||
553 | |||
554 | sd->gspca_dev.empty_packet = 0; | ||
555 | |||
556 | return ret; | ||
557 | } | ||
558 | |||
559 | static void w9968cf_stop0(struct sd *sd) | ||
560 | { | ||
561 | if (sd->gspca_dev.present) { | ||
562 | reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */ | ||
563 | reg_w(sd, 0x16, 0x0000); /* stop video capture */ | ||
564 | } | ||
565 | |||
566 | kfree(sd->jpeg_hdr); | ||
567 | sd->jpeg_hdr = NULL; | ||
568 | } | ||
569 | |||
570 | /* The w9968cf docs say that a 0 sized packet means EOF (and also SOF | ||
571 | for the next frame). This seems to simply not be true when operating | ||
572 | in JPEG mode, in this case there may be empty packets within the | ||
573 | frame. So in JPEG mode use the JPEG SOI marker to detect SOF. | ||
574 | |||
575 | Note to make things even more interesting the w9968cf sends *PLANAR* jpeg, | ||
576 | to be precise it sends: SOI, SOF, DRI, SOS, Y-data, SOS, U-data, SOS, | ||
577 | V-data, EOI. */ | ||
578 | static void w9968cf_pkt_scan(struct gspca_dev *gspca_dev, | ||
579 | u8 *data, /* isoc packet */ | ||
580 | int len) /* iso packet length */ | ||
581 | { | ||
582 | struct sd *sd = (struct sd *) gspca_dev; | ||
583 | |||
584 | if (w9968cf_vga_mode[gspca_dev->curr_mode].pixelformat == | ||
585 | V4L2_PIX_FMT_JPEG) { | ||
586 | if (len >= 2 && | ||
587 | data[0] == 0xff && | ||
588 | data[1] == 0xd8) { | ||
589 | gspca_frame_add(gspca_dev, LAST_PACKET, | ||
590 | NULL, 0); | ||
591 | gspca_frame_add(gspca_dev, FIRST_PACKET, | ||
592 | sd->jpeg_hdr, JPEG_HDR_SZ); | ||
593 | /* Strip the ff d8, our own header (which adds | ||
594 | huffman and quantization tables) already has this */ | ||
595 | len -= 2; | ||
596 | data += 2; | ||
597 | } | ||
598 | } else { | ||
599 | /* In UYVY mode an empty packet signals EOF */ | ||
600 | if (gspca_dev->empty_packet) { | ||
601 | gspca_frame_add(gspca_dev, LAST_PACKET, | ||
602 | NULL, 0); | ||
603 | gspca_frame_add(gspca_dev, FIRST_PACKET, | ||
604 | NULL, 0); | ||
605 | gspca_dev->empty_packet = 0; | ||
606 | } | ||
607 | } | ||
608 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | ||
609 | } | ||
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 49c3c1226e0e..69e5dc4fc9de 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c | |||
@@ -61,17 +61,18 @@ struct sd { | |||
61 | #define SENSOR_HV7131C 6 | 61 | #define SENSOR_HV7131C 6 |
62 | #define SENSOR_ICM105A 7 | 62 | #define SENSOR_ICM105A 7 |
63 | #define SENSOR_MC501CB 8 | 63 | #define SENSOR_MC501CB 8 |
64 | #define SENSOR_OV7620 9 | 64 | #define SENSOR_MI0360SOC 9 |
65 | /*#define SENSOR_OV7648 9 - same values */ | 65 | #define SENSOR_OV7620 10 |
66 | #define SENSOR_OV7630C 10 | 66 | /*#define SENSOR_OV7648 10 - same values */ |
67 | #define SENSOR_PAS106 11 | 67 | #define SENSOR_OV7630C 11 |
68 | #define SENSOR_PAS202B 12 | 68 | #define SENSOR_PAS106 12 |
69 | #define SENSOR_PB0330 13 | 69 | #define SENSOR_PAS202B 13 |
70 | #define SENSOR_PO2030 14 | 70 | #define SENSOR_PB0330 14 /* (MI0360) */ |
71 | #define SENSOR_TAS5130CK 15 | 71 | #define SENSOR_PO2030 15 |
72 | #define SENSOR_TAS5130CXX 16 | 72 | #define SENSOR_TAS5130CK 16 |
73 | #define SENSOR_TAS5130C_VF0250 17 | 73 | #define SENSOR_TAS5130CXX 17 |
74 | #define SENSOR_MAX 18 | 74 | #define SENSOR_TAS5130C_VF0250 18 |
75 | #define SENSOR_MAX 19 | ||
75 | unsigned short chip_revision; | 76 | unsigned short chip_revision; |
76 | 77 | ||
77 | u8 *jpeg_hdr; | 78 | u8 *jpeg_hdr; |
@@ -420,9 +421,7 @@ static const struct usb_action adcm2700_NoFliker[] = { | |||
420 | {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ | 421 | {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ |
421 | {} | 422 | {} |
422 | }; | 423 | }; |
423 | static const struct usb_action cs2102_Initial[] = { | 424 | static const struct usb_action cs2102_Initial[] = { /* 320x240 */ |
424 | {0xa1, 0x01, 0x0008}, | ||
425 | {0xa1, 0x01, 0x0008}, | ||
426 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 425 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
427 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, | 426 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, |
428 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, | 427 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, |
@@ -471,88 +470,10 @@ static const struct usb_action cs2102_Initial[] = { | |||
471 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, | 470 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, |
472 | {0xa0, 0x68, ZC3XX_R18D_YTARGET}, | 471 | {0xa0, 0x68, ZC3XX_R18D_YTARGET}, |
473 | {0xa0, 0x00, 0x01ad}, | 472 | {0xa0, 0x00, 0x01ad}, |
474 | {0xa1, 0x01, 0x0002}, | ||
475 | {0xa1, 0x01, 0x0008}, | ||
476 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */ | ||
477 | {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ | ||
478 | {0xa1, 0x01, 0x01c8}, | ||
479 | {0xa1, 0x01, 0x01c9}, | ||
480 | {0xa1, 0x01, 0x01ca}, | ||
481 | {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ | ||
482 | {0xa0, 0x24, ZC3XX_R120_GAMMA00}, /* gamma 5 */ | ||
483 | {0xa0, 0x44, ZC3XX_R121_GAMMA01}, | ||
484 | {0xa0, 0x64, ZC3XX_R122_GAMMA02}, | ||
485 | {0xa0, 0x84, ZC3XX_R123_GAMMA03}, | ||
486 | {0xa0, 0x9d, ZC3XX_R124_GAMMA04}, | ||
487 | {0xa0, 0xb2, ZC3XX_R125_GAMMA05}, | ||
488 | {0xa0, 0xc4, ZC3XX_R126_GAMMA06}, | ||
489 | {0xa0, 0xd3, ZC3XX_R127_GAMMA07}, | ||
490 | {0xa0, 0xe0, ZC3XX_R128_GAMMA08}, | ||
491 | {0xa0, 0xeb, ZC3XX_R129_GAMMA09}, | ||
492 | {0xa0, 0xf4, ZC3XX_R12A_GAMMA0A}, | ||
493 | {0xa0, 0xfb, ZC3XX_R12B_GAMMA0B}, | ||
494 | {0xa0, 0xff, ZC3XX_R12C_GAMMA0C}, | ||
495 | {0xa0, 0xff, ZC3XX_R12D_GAMMA0D}, | ||
496 | {0xa0, 0xff, ZC3XX_R12E_GAMMA0E}, | ||
497 | {0xa0, 0xff, ZC3XX_R12F_GAMMA0F}, | ||
498 | {0xa0, 0x18, ZC3XX_R130_GAMMA10}, | ||
499 | {0xa0, 0x20, ZC3XX_R131_GAMMA11}, | ||
500 | {0xa0, 0x20, ZC3XX_R132_GAMMA12}, | ||
501 | {0xa0, 0x1c, ZC3XX_R133_GAMMA13}, | ||
502 | {0xa0, 0x16, ZC3XX_R134_GAMMA14}, | ||
503 | {0xa0, 0x13, ZC3XX_R135_GAMMA15}, | ||
504 | {0xa0, 0x10, ZC3XX_R136_GAMMA16}, | ||
505 | {0xa0, 0x0e, ZC3XX_R137_GAMMA17}, | ||
506 | {0xa0, 0x0b, ZC3XX_R138_GAMMA18}, | ||
507 | {0xa0, 0x09, ZC3XX_R139_GAMMA19}, | ||
508 | {0xa0, 0x07, ZC3XX_R13A_GAMMA1A}, | ||
509 | {0xa0, 0x06, ZC3XX_R13B_GAMMA1B}, | ||
510 | {0xa0, 0x00, ZC3XX_R13C_GAMMA1C}, | ||
511 | {0xa0, 0x00, ZC3XX_R13D_GAMMA1D}, | ||
512 | {0xa0, 0x00, ZC3XX_R13E_GAMMA1E}, | ||
513 | {0xa0, 0x01, ZC3XX_R13F_GAMMA1F}, | ||
514 | {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */ | ||
515 | {0xa0, 0xf4, ZC3XX_R10B_RGB01}, | ||
516 | {0xa0, 0xf4, ZC3XX_R10C_RGB02}, | ||
517 | {0xa0, 0xf4, ZC3XX_R10D_RGB10}, | ||
518 | {0xa0, 0x58, ZC3XX_R10E_RGB11}, | ||
519 | {0xa0, 0xf4, ZC3XX_R10F_RGB12}, | ||
520 | {0xa0, 0xf4, ZC3XX_R110_RGB20}, | ||
521 | {0xa0, 0xf4, ZC3XX_R111_RGB21}, | ||
522 | {0xa0, 0x58, ZC3XX_R112_RGB22}, | ||
523 | {0xa1, 0x01, 0x0180}, | ||
524 | {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
525 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | ||
526 | {0xaa, 0x23, 0x0001}, | ||
527 | {0xaa, 0x24, 0x0055}, | ||
528 | {0xaa, 0x25, 0x00cc}, | ||
529 | {0xaa, 0x21, 0x003f}, | ||
530 | {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH}, | ||
531 | {0xa0, 0xab, ZC3XX_R191_EXPOSURELIMITMID}, | ||
532 | {0xa0, 0x98, ZC3XX_R192_EXPOSURELIMITLOW}, | ||
533 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, | ||
534 | {0xa0, 0x30, ZC3XX_R196_ANTIFLICKERMID}, | ||
535 | {0xa0, 0xd4, ZC3XX_R197_ANTIFLICKERLOW}, | ||
536 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, | ||
537 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, | ||
538 | {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, | ||
539 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, | ||
540 | {0xa0, 0x39, ZC3XX_R01D_HSYNC_0}, | ||
541 | {0xa0, 0x70, ZC3XX_R01E_HSYNC_1}, | ||
542 | {0xa0, 0xb0, ZC3XX_R01F_HSYNC_2}, | ||
543 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | ||
544 | {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
545 | {0xa1, 0x01, 0x0180}, | ||
546 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
547 | {0xa0, 0x40, ZC3XX_R116_RGAIN}, | ||
548 | {0xa0, 0x40, ZC3XX_R117_GGAIN}, | ||
549 | {0xa0, 0x40, ZC3XX_R118_BGAIN}, | ||
550 | {} | 473 | {} |
551 | }; | 474 | }; |
552 | 475 | ||
553 | static const struct usb_action cs2102_InitialScale[] = { | 476 | static const struct usb_action cs2102_InitialScale[] = { /* 640x480 */ |
554 | {0xa1, 0x01, 0x0008}, | ||
555 | {0xa1, 0x01, 0x0008}, | ||
556 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 477 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
557 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, | 478 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, |
558 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, | 479 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, |
@@ -601,57 +522,75 @@ static const struct usb_action cs2102_InitialScale[] = { | |||
601 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, | 522 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, |
602 | {0xa0, 0x68, ZC3XX_R18D_YTARGET}, | 523 | {0xa0, 0x68, ZC3XX_R18D_YTARGET}, |
603 | {0xa0, 0x00, 0x01ad}, | 524 | {0xa0, 0x00, 0x01ad}, |
604 | {0xa1, 0x01, 0x0002}, | 525 | {} |
605 | {0xa1, 0x01, 0x0008}, | 526 | }; |
606 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */ | 527 | static const struct usb_action cs2102_50HZ[] = { |
607 | {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ | 528 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
608 | {0xa1, 0x01, 0x01c8}, | 529 | {0xaa, 0x23, 0x0001}, |
609 | {0xa1, 0x01, 0x01c9}, | 530 | {0xaa, 0x24, 0x005f}, |
610 | {0xa1, 0x01, 0x01ca}, | 531 | {0xaa, 0x25, 0x0090}, |
611 | {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ | 532 | {0xaa, 0x21, 0x00dd}, |
612 | {0xa0, 0x24, ZC3XX_R120_GAMMA00}, /* gamma 5 */ | 533 | {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH}, |
613 | {0xa0, 0x44, ZC3XX_R121_GAMMA01}, | 534 | {0xa0, 0xbf, ZC3XX_R191_EXPOSURELIMITMID}, |
614 | {0xa0, 0x64, ZC3XX_R122_GAMMA02}, | 535 | {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, |
615 | {0xa0, 0x84, ZC3XX_R123_GAMMA03}, | 536 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, |
616 | {0xa0, 0x9d, ZC3XX_R124_GAMMA04}, | 537 | {0xa0, 0x3a, ZC3XX_R196_ANTIFLICKERMID}, |
617 | {0xa0, 0xb2, ZC3XX_R125_GAMMA05}, | 538 | {0xa0, 0x98, ZC3XX_R197_ANTIFLICKERLOW}, |
618 | {0xa0, 0xc4, ZC3XX_R126_GAMMA06}, | 539 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, |
619 | {0xa0, 0xd3, ZC3XX_R127_GAMMA07}, | 540 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, |
620 | {0xa0, 0xe0, ZC3XX_R128_GAMMA08}, | 541 | {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
621 | {0xa0, 0xeb, ZC3XX_R129_GAMMA09}, | 542 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, |
622 | {0xa0, 0xf4, ZC3XX_R12A_GAMMA0A}, | 543 | {0xa0, 0xdd, ZC3XX_R01D_HSYNC_0}, |
623 | {0xa0, 0xfb, ZC3XX_R12B_GAMMA0B}, | 544 | {0xa0, 0xe4, ZC3XX_R01E_HSYNC_1}, |
624 | {0xa0, 0xff, ZC3XX_R12C_GAMMA0C}, | 545 | {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2}, |
625 | {0xa0, 0xff, ZC3XX_R12D_GAMMA0D}, | 546 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, |
626 | {0xa0, 0xff, ZC3XX_R12E_GAMMA0E}, | 547 | {} |
627 | {0xa0, 0xff, ZC3XX_R12F_GAMMA0F}, | 548 | }; |
628 | {0xa0, 0x18, ZC3XX_R130_GAMMA10}, | 549 | static const struct usb_action cs2102_50HZScale[] = { |
629 | {0xa0, 0x20, ZC3XX_R131_GAMMA11}, | 550 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
630 | {0xa0, 0x20, ZC3XX_R132_GAMMA12}, | 551 | {0xaa, 0x23, 0x0000}, |
631 | {0xa0, 0x1c, ZC3XX_R133_GAMMA13}, | 552 | {0xaa, 0x24, 0x00af}, |
632 | {0xa0, 0x16, ZC3XX_R134_GAMMA14}, | 553 | {0xaa, 0x25, 0x00c8}, |
633 | {0xa0, 0x13, ZC3XX_R135_GAMMA15}, | 554 | {0xaa, 0x21, 0x0068}, |
634 | {0xa0, 0x10, ZC3XX_R136_GAMMA16}, | 555 | {0xa0, 0x01, ZC3XX_R190_EXPOSURELIMITHIGH}, |
635 | {0xa0, 0x0e, ZC3XX_R137_GAMMA17}, | 556 | {0xa0, 0x5f, ZC3XX_R191_EXPOSURELIMITMID}, |
636 | {0xa0, 0x0b, ZC3XX_R138_GAMMA18}, | 557 | {0xa0, 0x90, ZC3XX_R192_EXPOSURELIMITLOW}, |
637 | {0xa0, 0x09, ZC3XX_R139_GAMMA19}, | 558 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, |
638 | {0xa0, 0x07, ZC3XX_R13A_GAMMA1A}, | 559 | {0xa0, 0x1d, ZC3XX_R196_ANTIFLICKERMID}, |
639 | {0xa0, 0x06, ZC3XX_R13B_GAMMA1B}, | 560 | {0xa0, 0x4c, ZC3XX_R197_ANTIFLICKERLOW}, |
640 | {0xa0, 0x00, ZC3XX_R13C_GAMMA1C}, | 561 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, |
641 | {0xa0, 0x00, ZC3XX_R13D_GAMMA1D}, | 562 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, |
642 | {0xa0, 0x00, ZC3XX_R13E_GAMMA1E}, | 563 | {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
643 | {0xa0, 0x01, ZC3XX_R13F_GAMMA1F}, | 564 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, |
644 | {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */ | 565 | {0xa0, 0x68, ZC3XX_R01D_HSYNC_0}, |
645 | {0xa0, 0xf4, ZC3XX_R10B_RGB01}, | 566 | {0xa0, 0xe3, ZC3XX_R01E_HSYNC_1}, |
646 | {0xa0, 0xf4, ZC3XX_R10C_RGB02}, | 567 | {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2}, |
647 | {0xa0, 0xf4, ZC3XX_R10D_RGB10}, | 568 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, |
648 | {0xa0, 0x58, ZC3XX_R10E_RGB11}, | 569 | {} |
649 | {0xa0, 0xf4, ZC3XX_R10F_RGB12}, | 570 | }; |
650 | {0xa0, 0xf4, ZC3XX_R110_RGB20}, | 571 | static const struct usb_action cs2102_60HZ[] = { |
651 | {0xa0, 0xf4, ZC3XX_R111_RGB21}, | 572 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
652 | {0xa0, 0x58, ZC3XX_R112_RGB22}, | 573 | {0xaa, 0x23, 0x0001}, |
653 | {0xa1, 0x01, 0x0180}, | 574 | {0xaa, 0x24, 0x0055}, |
654 | {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, | 575 | {0xaa, 0x25, 0x00cc}, |
576 | {0xaa, 0x21, 0x003f}, | ||
577 | {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH}, | ||
578 | {0xa0, 0xab, ZC3XX_R191_EXPOSURELIMITMID}, | ||
579 | {0xa0, 0x98, ZC3XX_R192_EXPOSURELIMITLOW}, | ||
580 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, | ||
581 | {0xa0, 0x30, ZC3XX_R196_ANTIFLICKERMID}, | ||
582 | {0xa0, 0xd4, ZC3XX_R197_ANTIFLICKERLOW}, | ||
583 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, | ||
584 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, | ||
585 | {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, | ||
586 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, | ||
587 | {0xa0, 0x39, ZC3XX_R01D_HSYNC_0}, | ||
588 | {0xa0, 0x70, ZC3XX_R01E_HSYNC_1}, | ||
589 | {0xa0, 0xb0, ZC3XX_R01F_HSYNC_2}, | ||
590 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | ||
591 | {} | ||
592 | }; | ||
593 | static const struct usb_action cs2102_60HZScale[] = { | ||
655 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | 594 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
656 | {0xaa, 0x23, 0x0000}, | 595 | {0xaa, 0x23, 0x0000}, |
657 | {0xaa, 0x24, 0x00aa}, | 596 | {0xaa, 0x24, 0x00aa}, |
@@ -671,162 +610,50 @@ static const struct usb_action cs2102_InitialScale[] = { | |||
671 | {0xa0, 0xa5, ZC3XX_R01E_HSYNC_1}, | 610 | {0xa0, 0xa5, ZC3XX_R01E_HSYNC_1}, |
672 | {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2}, | 611 | {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2}, |
673 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | 612 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, |
674 | {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
675 | {0xa1, 0x01, 0x0180}, | ||
676 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
677 | {0xa0, 0x40, ZC3XX_R116_RGAIN}, | ||
678 | {0xa0, 0x40, ZC3XX_R117_GGAIN}, | ||
679 | {0xa0, 0x40, ZC3XX_R118_BGAIN}, | ||
680 | {} | ||
681 | }; | ||
682 | static const struct usb_action cs2102_50HZ[] = { | ||
683 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | ||
684 | {0xaa, 0x0f, 0x008c}, /* 00,0f,8c,aa */ | ||
685 | {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */ | ||
686 | {0xaa, 0x04, 0x00ac}, /* 00,04,ac,aa */ | ||
687 | {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */ | ||
688 | {0xaa, 0x11, 0x00ac}, /* 00,11,ac,aa */ | ||
689 | {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */ | ||
690 | {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */ | ||
691 | {0xaa, 0x1d, 0x00ac}, /* 00,1d,ac,aa */ | ||
692 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | ||
693 | {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,cc */ | ||
694 | {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */ | ||
695 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | ||
696 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | ||
697 | {0xa0, 0x42, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,42,cc */ | ||
698 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | ||
699 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | ||
700 | {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */ | ||
701 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ | ||
702 | {0xa0, 0x8c, ZC3XX_R01D_HSYNC_0}, /* 00,1d,8c,cc */ | ||
703 | {0xa0, 0xb0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,b0,cc */ | ||
704 | {0xa0, 0xd0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,d0,cc */ | ||
705 | {} | ||
706 | }; | ||
707 | static const struct usb_action cs2102_50HZScale[] = { | ||
708 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | ||
709 | {0xaa, 0x0f, 0x0093}, /* 00,0f,93,aa */ | ||
710 | {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */ | ||
711 | {0xaa, 0x04, 0x00a1}, /* 00,04,a1,aa */ | ||
712 | {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */ | ||
713 | {0xaa, 0x11, 0x00a1}, /* 00,11,a1,aa */ | ||
714 | {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */ | ||
715 | {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */ | ||
716 | {0xaa, 0x1d, 0x00a1}, /* 00,1d,a1,aa */ | ||
717 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | ||
718 | {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,cc */ | ||
719 | {0xa0, 0xf7, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f7,cc */ | ||
720 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | ||
721 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | ||
722 | {0xa0, 0x83, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,83,cc */ | ||
723 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | ||
724 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | ||
725 | {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */ | ||
726 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ | ||
727 | {0xa0, 0x93, ZC3XX_R01D_HSYNC_0}, /* 00,1d,93,cc */ | ||
728 | {0xa0, 0xb0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,b0,cc */ | ||
729 | {0xa0, 0xd0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,d0,cc */ | ||
730 | {} | ||
731 | }; | ||
732 | static const struct usb_action cs2102_60HZ[] = { | ||
733 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | ||
734 | {0xaa, 0x0f, 0x005d}, /* 00,0f,5d,aa */ | ||
735 | {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */ | ||
736 | {0xaa, 0x04, 0x00aa}, /* 00,04,aa,aa */ | ||
737 | {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */ | ||
738 | {0xaa, 0x11, 0x00aa}, /* 00,11,aa,aa */ | ||
739 | {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */ | ||
740 | {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */ | ||
741 | {0xaa, 0x1d, 0x00aa}, /* 00,1d,aa,aa */ | ||
742 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | ||
743 | {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,cc */ | ||
744 | {0xa0, 0xe4, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,e4,cc */ | ||
745 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | ||
746 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | ||
747 | {0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3a,cc */ | ||
748 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | ||
749 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | ||
750 | {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */ | ||
751 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ | ||
752 | {0xa0, 0x5d, ZC3XX_R01D_HSYNC_0}, /* 00,1d,5d,cc */ | ||
753 | {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */ | ||
754 | {0xa0, 0xd0, 0x00c8}, /* 00,c8,d0,cc */ | ||
755 | {} | ||
756 | }; | ||
757 | static const struct usb_action cs2102_60HZScale[] = { | ||
758 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | ||
759 | {0xaa, 0x0f, 0x00b7}, /* 00,0f,b7,aa */ | ||
760 | {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */ | ||
761 | {0xaa, 0x04, 0x00be}, /* 00,04,be,aa */ | ||
762 | {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */ | ||
763 | {0xaa, 0x11, 0x00be}, /* 00,11,be,aa */ | ||
764 | {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */ | ||
765 | {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */ | ||
766 | {0xaa, 0x1d, 0x00be}, /* 00,1d,be,aa */ | ||
767 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | ||
768 | {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,cc */ | ||
769 | {0xa0, 0xfc, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,fc,cc */ | ||
770 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | ||
771 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | ||
772 | {0xa0, 0x69, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,69,cc */ | ||
773 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | ||
774 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | ||
775 | {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */ | ||
776 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ | ||
777 | {0xa0, 0xb7, ZC3XX_R01D_HSYNC_0}, /* 00,1d,b7,cc */ | ||
778 | {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */ | ||
779 | {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */ | ||
780 | {} | 613 | {} |
781 | }; | 614 | }; |
782 | static const struct usb_action cs2102_NoFliker[] = { | 615 | static const struct usb_action cs2102_NoFliker[] = { |
783 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 616 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
784 | {0xaa, 0x0f, 0x0059}, /* 00,0f,59,aa */ | 617 | {0xaa, 0x23, 0x0001}, |
785 | {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */ | 618 | {0xaa, 0x24, 0x005f}, |
786 | {0xaa, 0x04, 0x0080}, /* 00,04,80,aa */ | 619 | {0xaa, 0x25, 0x0000}, |
787 | {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */ | 620 | {0xaa, 0x21, 0x0001}, |
788 | {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */ | 621 | {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH}, |
789 | {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */ | 622 | {0xa0, 0xbf, ZC3XX_R191_EXPOSURELIMITMID}, |
790 | {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */ | 623 | {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW}, |
791 | {0xaa, 0x1d, 0x0080}, /* 00,1d,80,aa */ | 624 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, |
792 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 625 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, |
793 | {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,cc */ | 626 | {0xa0, 0x80, ZC3XX_R197_ANTIFLICKERLOW}, |
794 | {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */ | 627 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, |
795 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 628 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, |
796 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 629 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
797 | {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */ | 630 | {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, |
798 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 631 | {0xa0, 0x01, ZC3XX_R01D_HSYNC_0}, |
799 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 632 | {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, |
800 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ | 633 | {0xa0, 0xa0, ZC3XX_R01F_HSYNC_2}, |
801 | {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ | 634 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, |
802 | {0xa0, 0x59, ZC3XX_R01D_HSYNC_0}, /* 00,1d,59,cc */ | ||
803 | {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */ | ||
804 | {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */ | ||
805 | {} | 635 | {} |
806 | }; | 636 | }; |
807 | static const struct usb_action cs2102_NoFlikerScale[] = { | 637 | static const struct usb_action cs2102_NoFlikerScale[] = { |
808 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 638 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
809 | {0xaa, 0x0f, 0x0059}, /* 00,0f,59,aa */ | 639 | {0xaa, 0x23, 0x0000}, |
810 | {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */ | 640 | {0xaa, 0x24, 0x00af}, |
811 | {0xaa, 0x04, 0x0080}, /* 00,04,80,aa */ | 641 | {0xaa, 0x25, 0x0080}, |
812 | {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */ | 642 | {0xaa, 0x21, 0x0001}, |
813 | {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */ | 643 | {0xa0, 0x01, ZC3XX_R190_EXPOSURELIMITHIGH}, |
814 | {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */ | 644 | {0xa0, 0x5f, ZC3XX_R191_EXPOSURELIMITMID}, |
815 | {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */ | 645 | {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW}, |
816 | {0xaa, 0x1d, 0x0080}, /* 00,1d,80,aa */ | 646 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, |
817 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 647 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, |
818 | {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,cc */ | 648 | {0xa0, 0x80, ZC3XX_R197_ANTIFLICKERLOW}, |
819 | {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */ | 649 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, |
820 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 650 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, |
821 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 651 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
822 | {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */ | 652 | {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, |
823 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 653 | {0xa0, 0x01, ZC3XX_R01D_HSYNC_0}, |
824 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 654 | {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, |
825 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ | 655 | {0xa0, 0xa0, ZC3XX_R01F_HSYNC_2}, |
826 | {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ | 656 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, |
827 | {0xa0, 0x59, ZC3XX_R01D_HSYNC_0}, /* 00,1d,59,cc */ | ||
828 | {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */ | ||
829 | {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */ | ||
830 | {} | 657 | {} |
831 | }; | 658 | }; |
832 | 659 | ||
@@ -4409,170 +4236,80 @@ static const struct usb_action pas202b_NoFlikerScale[] = { | |||
4409 | {} | 4236 | {} |
4410 | }; | 4237 | }; |
4411 | 4238 | ||
4412 | static const struct usb_action pb03303x_Initial[] = { | 4239 | /* mi0360soc and pb0330 from vm30x.inf for 0ac8:301b and 0ac8:303b 07/02/13 */ |
4240 | static const struct usb_action mi0360soc_Initial[] = { /* 640x480 */ | ||
4413 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 4241 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
4414 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | 4242 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
4415 | {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, | 4243 | {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, |
4416 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, | 4244 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, |
4417 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, | 4245 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, |
4418 | {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, | 4246 | {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, |
4419 | {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, | 4247 | {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, |
4420 | {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, | 4248 | {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, |
4421 | {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, /* 8b -> dc */ | 4249 | {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, |
4422 | {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, | 4250 | {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, |
4423 | {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, | 4251 | {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC}, /*jfm: was 03*/ |
4424 | {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, | 4252 | /* {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, */ |
4425 | {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, | 4253 | {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, |
4426 | {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, | 4254 | {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, |
4427 | {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, | 4255 | {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, |
4428 | {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, | 4256 | {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, |
4429 | {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, | 4257 | {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, |
4258 | {0xdd, 0x00, 0x0200}, | ||
4430 | {0xaa, 0x01, 0x0001}, | 4259 | {0xaa, 0x01, 0x0001}, |
4431 | {0xaa, 0x06, 0x0000}, | 4260 | {0xaa, 0x06, 0x0000}, |
4432 | {0xaa, 0x08, 0x0483}, | 4261 | {0xaa, 0x08, 0x0483}, |
4433 | {0xaa, 0x01, 0x0004}, | 4262 | {0xaa, 0x01, 0x0004}, |
4434 | {0xaa, 0x08, 0x0006}, | 4263 | {0xaa, 0x08, 0x0006}, |
4435 | {0xaa, 0x02, 0x0011}, | 4264 | {0xaa, 0x02, 0x0011}, |
4436 | {0xaa, 0x03, 0x01e7}, | 4265 | {0xaa, 0x03, 0x01e5}, /*jfm: was 01e7*/ |
4437 | {0xaa, 0x04, 0x0287}, | 4266 | {0xaa, 0x04, 0x0285}, /*jfm: was 0287*/ |
4438 | {0xaa, 0x07, 0x3002}, | 4267 | {0xaa, 0x07, 0x3002}, |
4439 | {0xaa, 0x20, 0x1100}, | 4268 | {0xaa, 0x20, 0x5100}, /*jfm: was 1100*/ |
4440 | {0xaa, 0x35, 0x0050}, | 4269 | {0xaa, 0x35, 0x507f}, /*jfm: was 0050*/ |
4441 | {0xaa, 0x30, 0x0005}, | 4270 | {0xaa, 0x30, 0x0005}, |
4442 | {0xaa, 0x31, 0x0000}, | 4271 | {0xaa, 0x31, 0x0000}, |
4443 | {0xaa, 0x58, 0x0078}, | 4272 | {0xaa, 0x58, 0x0078}, |
4444 | {0xaa, 0x62, 0x0411}, | 4273 | {0xaa, 0x62, 0x0411}, |
4445 | {0xaa, 0x2b, 0x0028}, | 4274 | {0xaa, 0x2b, 0x0028}, |
4446 | {0xaa, 0x2c, 0x0030}, | 4275 | {0xaa, 0x2c, 0x007f}, /*jfm: was 0030*/ |
4447 | {0xaa, 0x2d, 0x0030}, | 4276 | {0xaa, 0x2d, 0x007f}, /*jfm: was 0030*/ |
4448 | {0xaa, 0x2e, 0x0028}, | 4277 | {0xaa, 0x2e, 0x007f}, /*jfm: was 0030*/ |
4449 | {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, | 4278 | {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, |
4450 | {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, | 4279 | {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /*jfm: was 37*/ |
4451 | {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, | 4280 | {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, |
4452 | {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, | 4281 | {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, |
4453 | {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, | 4282 | {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, |
4454 | {0xa0, 0x00, 0x01ad}, | 4283 | {0xa0, 0x09, 0x01ad}, /*jfm: was 00*/ |
4455 | {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, | 4284 | {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, |
4456 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, | 4285 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, |
4457 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, | 4286 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, |
4458 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, | 4287 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, |
4459 | {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, | 4288 | {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, |
4460 | {0xa0, 0x78, ZC3XX_R18D_YTARGET}, | 4289 | {0xa0, 0x6c, ZC3XX_R18D_YTARGET}, /* jfm: was 78 */ |
4461 | {0xa0, 0x61, ZC3XX_R116_RGAIN}, | 4290 | {0xa0, 0x61, ZC3XX_R116_RGAIN}, |
4462 | {0xa0, 0x65, ZC3XX_R118_BGAIN}, | 4291 | {0xa0, 0x65, ZC3XX_R118_BGAIN}, |
4463 | |||
4464 | {0xa1, 0x01, 0x0002}, | ||
4465 | {0xa0, 0x09, 0x01ad}, | ||
4466 | {0xa0, 0x15, 0x01ae}, | ||
4467 | {0xa0, 0x0d, 0x003a}, | ||
4468 | {0xa0, 0x02, 0x003b}, | ||
4469 | {0xa0, 0x00, 0x0038}, | ||
4470 | {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */ | ||
4471 | {0xa0, 0xf8, ZC3XX_R10B_RGB01}, | ||
4472 | {0xa0, 0xf8, ZC3XX_R10C_RGB02}, | ||
4473 | {0xa0, 0xf8, ZC3XX_R10D_RGB10}, | ||
4474 | {0xa0, 0x50, ZC3XX_R10E_RGB11}, | ||
4475 | {0xa0, 0xf8, ZC3XX_R10F_RGB12}, | ||
4476 | {0xa0, 0xf8, ZC3XX_R110_RGB20}, | ||
4477 | {0xa0, 0xf8, ZC3XX_R111_RGB21}, | ||
4478 | {0xa0, 0x50, ZC3XX_R112_RGB22}, | ||
4479 | |||
4480 | {0xa1, 0x01, 0x0008}, | ||
4481 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | ||
4482 | {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, | ||
4483 | {0xa1, 0x01, 0x01c8}, | ||
4484 | {0xa1, 0x01, 0x01c9}, | ||
4485 | {0xa1, 0x01, 0x01ca}, | ||
4486 | {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ | ||
4487 | {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */ | ||
4488 | {0xa0, 0x38, ZC3XX_R121_GAMMA01}, | ||
4489 | {0xa0, 0x59, ZC3XX_R122_GAMMA02}, | ||
4490 | {0xa0, 0x79, ZC3XX_R123_GAMMA03}, | ||
4491 | {0xa0, 0x92, ZC3XX_R124_GAMMA04}, | ||
4492 | {0xa0, 0xa7, ZC3XX_R125_GAMMA05}, | ||
4493 | {0xa0, 0xb9, ZC3XX_R126_GAMMA06}, | ||
4494 | {0xa0, 0xc8, ZC3XX_R127_GAMMA07}, | ||
4495 | {0xa0, 0xd4, ZC3XX_R128_GAMMA08}, | ||
4496 | {0xa0, 0xdf, ZC3XX_R129_GAMMA09}, | ||
4497 | {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A}, | ||
4498 | {0xa0, 0xee, ZC3XX_R12B_GAMMA0B}, | ||
4499 | {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C}, | ||
4500 | {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D}, | ||
4501 | {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E}, | ||
4502 | {0xa0, 0xff, ZC3XX_R12F_GAMMA0F}, | ||
4503 | {0xa0, 0x26, ZC3XX_R130_GAMMA10}, | ||
4504 | {0xa0, 0x22, ZC3XX_R131_GAMMA11}, | ||
4505 | {0xa0, 0x20, ZC3XX_R132_GAMMA12}, | ||
4506 | {0xa0, 0x1c, ZC3XX_R133_GAMMA13}, | ||
4507 | {0xa0, 0x16, ZC3XX_R134_GAMMA14}, | ||
4508 | {0xa0, 0x13, ZC3XX_R135_GAMMA15}, | ||
4509 | {0xa0, 0x10, ZC3XX_R136_GAMMA16}, | ||
4510 | {0xa0, 0x0d, ZC3XX_R137_GAMMA17}, | ||
4511 | {0xa0, 0x0b, ZC3XX_R138_GAMMA18}, | ||
4512 | {0xa0, 0x09, ZC3XX_R139_GAMMA19}, | ||
4513 | {0xa0, 0x07, ZC3XX_R13A_GAMMA1A}, | ||
4514 | {0xa0, 0x06, ZC3XX_R13B_GAMMA1B}, | ||
4515 | {0xa0, 0x05, ZC3XX_R13C_GAMMA1C}, | ||
4516 | {0xa0, 0x04, ZC3XX_R13D_GAMMA1D}, | ||
4517 | {0xa0, 0x03, ZC3XX_R13E_GAMMA1E}, | ||
4518 | {0xa0, 0x02, ZC3XX_R13F_GAMMA1F}, | ||
4519 | {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */ | ||
4520 | {0xa0, 0xf8, ZC3XX_R10B_RGB01}, | ||
4521 | {0xa0, 0xf8, ZC3XX_R10C_RGB02}, | ||
4522 | {0xa0, 0xf8, ZC3XX_R10D_RGB10}, | ||
4523 | {0xa0, 0x50, ZC3XX_R10E_RGB11}, | ||
4524 | {0xa0, 0xf8, ZC3XX_R10F_RGB12}, | ||
4525 | {0xa0, 0xf8, ZC3XX_R110_RGB20}, | ||
4526 | {0xa0, 0xf8, ZC3XX_R111_RGB21}, | ||
4527 | {0xa0, 0x50, ZC3XX_R112_RGB22}, | ||
4528 | |||
4529 | {0xa1, 0x01, 0x0180}, | ||
4530 | {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
4531 | {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
4532 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | ||
4533 | {0xaa, 0x05, 0x0009}, | ||
4534 | {0xaa, 0x09, 0x0134}, | ||
4535 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, | ||
4536 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, | ||
4537 | {0xa0, 0xec, ZC3XX_R192_EXPOSURELIMITLOW}, | ||
4538 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, | ||
4539 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, | ||
4540 | {0xa0, 0x9c, ZC3XX_R197_ANTIFLICKERLOW}, | ||
4541 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, | ||
4542 | {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, | ||
4543 | {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, | ||
4544 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, | ||
4545 | {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0}, | ||
4546 | {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, | ||
4547 | {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2}, | ||
4548 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | ||
4549 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
4550 | {0xa0, 0x09, 0x01ad}, | ||
4551 | {0xa0, 0x15, 0x01ae}, | ||
4552 | {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
4553 | {0xa1, 0x01, 0x0180}, | ||
4554 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
4555 | {} | 4292 | {} |
4556 | }; | 4293 | }; |
4557 | 4294 | static const struct usb_action mi0360soc_InitialScale[] = { /* 320x240 */ | |
4558 | static const struct usb_action pb03303x_InitialScale[] = { | ||
4559 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 4295 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
4560 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | 4296 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
4561 | {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, | 4297 | {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, |
4562 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, | 4298 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, |
4563 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, | 4299 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, |
4564 | {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, | 4300 | {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, |
4565 | {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, | 4301 | {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, |
4566 | {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, | 4302 | {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, |
4567 | {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, /* 8b -> dc */ | 4303 | {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, |
4568 | {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, | 4304 | {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, |
4569 | {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, | 4305 | {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC}, /*jfm: was 03*/ |
4570 | {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, | 4306 | /* {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, */ |
4571 | {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, | 4307 | {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, |
4572 | {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, | 4308 | {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, |
4573 | {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, | 4309 | {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, |
4574 | {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, | 4310 | {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, |
4575 | {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, | 4311 | {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, |
4312 | {0xdd, 0x00, 0x0200}, | ||
4576 | {0xaa, 0x01, 0x0001}, | 4313 | {0xaa, 0x01, 0x0001}, |
4577 | {0xaa, 0x06, 0x0000}, | 4314 | {0xaa, 0x06, 0x0000}, |
4578 | {0xaa, 0x08, 0x0483}, | 4315 | {0xaa, 0x08, 0x0483}, |
@@ -4582,111 +4319,111 @@ static const struct usb_action pb03303x_InitialScale[] = { | |||
4582 | {0xaa, 0x03, 0x01e7}, | 4319 | {0xaa, 0x03, 0x01e7}, |
4583 | {0xaa, 0x04, 0x0287}, | 4320 | {0xaa, 0x04, 0x0287}, |
4584 | {0xaa, 0x07, 0x3002}, | 4321 | {0xaa, 0x07, 0x3002}, |
4585 | {0xaa, 0x20, 0x1100}, | 4322 | {0xaa, 0x20, 0x5100}, /*jfm: was 1100*/ |
4586 | {0xaa, 0x35, 0x0050}, | 4323 | {0xaa, 0x35, 0x007f}, /*jfm: was 0050*/ |
4587 | {0xaa, 0x30, 0x0005}, | 4324 | {0xaa, 0x30, 0x0005}, |
4588 | {0xaa, 0x31, 0x0000}, | 4325 | {0xaa, 0x31, 0x0000}, |
4589 | {0xaa, 0x58, 0x0078}, | 4326 | {0xaa, 0x58, 0x0078}, |
4590 | {0xaa, 0x62, 0x0411}, | 4327 | {0xaa, 0x62, 0x0411}, |
4591 | {0xaa, 0x2b, 0x0028}, | 4328 | {0xaa, 0x2b, 0x007f}, /*jfm: was 28*/ |
4592 | {0xaa, 0x2c, 0x0030}, | 4329 | {0xaa, 0x2c, 0x007f}, /*jfm: was 30*/ |
4593 | {0xaa, 0x2d, 0x0030}, | 4330 | {0xaa, 0x2d, 0x007f}, /*jfm: was 30*/ |
4594 | {0xaa, 0x2e, 0x0028}, | 4331 | {0xaa, 0x2e, 0x007f}, /*jfm: was 28*/ |
4595 | {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, | 4332 | {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, |
4596 | {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, | 4333 | {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /*jfm: was 37*/ |
4597 | {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, | 4334 | {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, |
4598 | {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, | 4335 | {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, |
4599 | {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, | 4336 | {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, |
4600 | {0xa0, 0x00, 0x01ad}, | 4337 | {0xa0, 0x09, 0x01ad}, /*jfm: was 00*/ |
4601 | {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, | 4338 | {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, |
4602 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, | 4339 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, |
4603 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, | 4340 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, |
4604 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, | 4341 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, |
4605 | {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, | 4342 | {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, |
4606 | {0xa0, 0x78, ZC3XX_R18D_YTARGET}, | 4343 | {0xa0, 0x6c, ZC3XX_R18D_YTARGET}, /*jfm: was 78*/ |
4607 | {0xa0, 0x61, ZC3XX_R116_RGAIN}, | 4344 | {0xa0, 0x61, ZC3XX_R116_RGAIN}, |
4608 | {0xa0, 0x65, ZC3XX_R118_BGAIN}, | 4345 | {0xa0, 0x65, ZC3XX_R118_BGAIN}, |
4609 | 4346 | {} | |
4610 | {0xa1, 0x01, 0x0002}, | 4347 | }; |
4611 | 4348 | static const struct usb_action mi360soc_AE50HZ[] = { | |
4612 | {0xa0, 0x09, 0x01ad}, | 4349 | {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, |
4613 | {0xa0, 0x15, 0x01ae}, | 4350 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
4614 | 4351 | {0xbb, 0x00, 0x0562}, | |
4615 | {0xa0, 0x0d, 0x003a}, | 4352 | {0xbb, 0x01, 0x09aa}, |
4616 | {0xa0, 0x02, 0x003b}, | 4353 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, |
4617 | {0xa0, 0x00, 0x0038}, | 4354 | {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, |
4618 | {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */ | 4355 | {0xa0, 0x9b, ZC3XX_R192_EXPOSURELIMITLOW}, |
4619 | {0xa0, 0xf8, ZC3XX_R10B_RGB01}, | 4356 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, |
4620 | {0xa0, 0xf8, ZC3XX_R10C_RGB02}, | 4357 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, |
4621 | {0xa0, 0xf8, ZC3XX_R10D_RGB10}, | 4358 | {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, |
4622 | {0xa0, 0x50, ZC3XX_R10E_RGB11}, | 4359 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, |
4623 | {0xa0, 0xf8, ZC3XX_R10F_RGB12}, | 4360 | {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, |
4624 | {0xa0, 0xf8, ZC3XX_R110_RGB20}, | 4361 | {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
4625 | {0xa0, 0xf8, ZC3XX_R111_RGB21}, | 4362 | {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, |
4626 | {0xa0, 0x50, ZC3XX_R112_RGB22}, | 4363 | {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, |
4627 | 4364 | {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, | |
4628 | {0xa1, 0x01, 0x0008}, | 4365 | {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, |
4629 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */ | 4366 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, |
4630 | {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ | 4367 | {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, |
4631 | {0xa1, 0x01, 0x01c8}, | 4368 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, |
4632 | {0xa1, 0x01, 0x01c9}, | 4369 | {} |
4633 | {0xa1, 0x01, 0x01ca}, | 4370 | }; |
4634 | {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ | 4371 | static const struct usb_action mi360soc_AE50HZScale[] = { |
4635 | |||
4636 | {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */ | ||
4637 | {0xa0, 0x38, ZC3XX_R121_GAMMA01}, | ||
4638 | {0xa0, 0x59, ZC3XX_R122_GAMMA02}, | ||
4639 | {0xa0, 0x79, ZC3XX_R123_GAMMA03}, | ||
4640 | {0xa0, 0x92, ZC3XX_R124_GAMMA04}, | ||
4641 | {0xa0, 0xa7, ZC3XX_R125_GAMMA05}, | ||
4642 | {0xa0, 0xb9, ZC3XX_R126_GAMMA06}, | ||
4643 | {0xa0, 0xc8, ZC3XX_R127_GAMMA07}, | ||
4644 | {0xa0, 0xd4, ZC3XX_R128_GAMMA08}, | ||
4645 | {0xa0, 0xdf, ZC3XX_R129_GAMMA09}, | ||
4646 | {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A}, | ||
4647 | {0xa0, 0xee, ZC3XX_R12B_GAMMA0B}, | ||
4648 | {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C}, | ||
4649 | {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D}, | ||
4650 | {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E}, | ||
4651 | {0xa0, 0xff, ZC3XX_R12F_GAMMA0F}, | ||
4652 | {0xa0, 0x26, ZC3XX_R130_GAMMA10}, | ||
4653 | {0xa0, 0x22, ZC3XX_R131_GAMMA11}, | ||
4654 | {0xa0, 0x20, ZC3XX_R132_GAMMA12}, | ||
4655 | {0xa0, 0x1c, ZC3XX_R133_GAMMA13}, | ||
4656 | {0xa0, 0x16, ZC3XX_R134_GAMMA14}, | ||
4657 | {0xa0, 0x13, ZC3XX_R135_GAMMA15}, | ||
4658 | {0xa0, 0x10, ZC3XX_R136_GAMMA16}, | ||
4659 | {0xa0, 0x0d, ZC3XX_R137_GAMMA17}, | ||
4660 | {0xa0, 0x0b, ZC3XX_R138_GAMMA18}, | ||
4661 | {0xa0, 0x09, ZC3XX_R139_GAMMA19}, | ||
4662 | {0xa0, 0x07, ZC3XX_R13A_GAMMA1A}, | ||
4663 | {0xa0, 0x06, ZC3XX_R13B_GAMMA1B}, | ||
4664 | {0xa0, 0x05, ZC3XX_R13C_GAMMA1C}, | ||
4665 | {0xa0, 0x04, ZC3XX_R13D_GAMMA1D}, | ||
4666 | {0xa0, 0x03, ZC3XX_R13E_GAMMA1E}, | ||
4667 | {0xa0, 0x02, ZC3XX_R13F_GAMMA1F}, | ||
4668 | {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */ | ||
4669 | {0xa0, 0xf8, ZC3XX_R10B_RGB01}, | ||
4670 | {0xa0, 0xf8, ZC3XX_R10C_RGB02}, | ||
4671 | {0xa0, 0xf8, ZC3XX_R10D_RGB10}, | ||
4672 | {0xa0, 0x50, ZC3XX_R10E_RGB11}, | ||
4673 | {0xa0, 0xf8, ZC3XX_R10F_RGB12}, | ||
4674 | {0xa0, 0xf8, ZC3XX_R110_RGB20}, | ||
4675 | {0xa0, 0xf8, ZC3XX_R111_RGB21}, | ||
4676 | {0xa0, 0x50, ZC3XX_R112_RGB22}, | ||
4677 | |||
4678 | {0xa1, 0x01, 0x0180}, | ||
4679 | {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, | 4372 | {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, |
4373 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | ||
4374 | {0xbb, 0x00, 0x0509}, | ||
4375 | {0xbb, 0x01, 0x0934}, | ||
4376 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, | ||
4377 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, | ||
4378 | {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW}, | ||
4379 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, | ||
4380 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, | ||
4381 | {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW}, | ||
4382 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, | ||
4383 | {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, | ||
4384 | {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, | ||
4385 | {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, | ||
4386 | {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0}, | ||
4387 | {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, | ||
4388 | {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2}, | ||
4389 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | ||
4390 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
4391 | {} | ||
4392 | }; | ||
4393 | static const struct usb_action mi360soc_AE60HZ[] = { | ||
4394 | {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
4395 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | ||
4396 | {0xbb, 0x00, 0x053d}, | ||
4397 | {0xbb, 0x01, 0x096e}, | ||
4398 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, | ||
4399 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, | ||
4400 | {0xa0, 0xdd, ZC3XX_R192_EXPOSURELIMITLOW}, | ||
4401 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, | ||
4402 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, | ||
4403 | {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW}, | ||
4404 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, | ||
4405 | {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, | ||
4406 | {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, | ||
4407 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, | ||
4408 | {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, | ||
4409 | {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, | ||
4410 | {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, | ||
4411 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | ||
4412 | {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, | ||
4413 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
4414 | {} | ||
4415 | }; | ||
4416 | static const struct usb_action mi360soc_AE60HZScale[] = { | ||
4680 | {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, | 4417 | {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, |
4681 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | 4418 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
4682 | {0xaa, 0x05, 0x0009}, | 4419 | {0xbb, 0x00, 0x0509}, |
4683 | {0xaa, 0x09, 0x0134}, | 4420 | {0xbb, 0x01, 0x0983}, |
4684 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, | 4421 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, |
4685 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, | 4422 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, |
4686 | {0xa0, 0xec, ZC3XX_R192_EXPOSURELIMITLOW}, | 4423 | {0xa0, 0x8f, ZC3XX_R192_EXPOSURELIMITLOW}, |
4687 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, | 4424 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, |
4688 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, | 4425 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, |
4689 | {0xa0, 0x9c, ZC3XX_R197_ANTIFLICKERLOW}, | 4426 | {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW}, |
4690 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, | 4427 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, |
4691 | {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, | 4428 | {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, |
4692 | {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, | 4429 | {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
@@ -4696,20 +4433,60 @@ static const struct usb_action pb03303x_InitialScale[] = { | |||
4696 | {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2}, | 4433 | {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2}, |
4697 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | 4434 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, |
4698 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, | 4435 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, |
4699 | {0xa0, 0x09, 0x01ad}, | 4436 | {} |
4700 | {0xa0, 0x15, 0x01ae}, | 4437 | }; |
4701 | {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, | 4438 | static const struct usb_action mi360soc_AENoFliker[] = { |
4702 | {0xa1, 0x01, 0x0180}, | 4439 | {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, |
4440 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | ||
4441 | {0xbb, 0x00, 0x0509}, | ||
4442 | {0xbb, 0x01, 0x0960}, | ||
4443 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, | ||
4444 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, | ||
4445 | {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, | ||
4446 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, | ||
4447 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, | ||
4448 | {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW}, | ||
4449 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, | ||
4450 | {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, | ||
4451 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, | ||
4452 | {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, | ||
4453 | {0xa0, 0x09, ZC3XX_R01D_HSYNC_0}, | ||
4454 | {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, | ||
4455 | {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, | ||
4456 | {0xa0, 0xe0, ZC3XX_R020_HSYNC_3}, | ||
4457 | {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, | ||
4703 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, | 4458 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, |
4704 | {} | 4459 | {} |
4705 | }; | 4460 | }; |
4706 | static const struct usb_action pb0330xx_Initial[] = { | 4461 | static const struct usb_action mi360soc_AENoFlikerScale[] = { |
4707 | {0xa1, 0x01, 0x0008}, | 4462 | {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, |
4708 | {0xa1, 0x01, 0x0008}, | 4463 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
4464 | {0xbb, 0x00, 0x0534}, | ||
4465 | {0xbb, 0x02, 0x0960}, | ||
4466 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, | ||
4467 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, | ||
4468 | {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, | ||
4469 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, | ||
4470 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, | ||
4471 | {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW}, | ||
4472 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, | ||
4473 | {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, | ||
4474 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, | ||
4475 | {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, | ||
4476 | {0xa0, 0x34, ZC3XX_R01D_HSYNC_0}, | ||
4477 | {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, | ||
4478 | {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, | ||
4479 | {0xa0, 0xe0, ZC3XX_R020_HSYNC_3}, | ||
4480 | {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, | ||
4481 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
4482 | {} | ||
4483 | }; | ||
4484 | |||
4485 | static const struct usb_action pb0330_Initial[] = { /* 640x480 */ | ||
4709 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 4486 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
4710 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */ | 4487 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */ |
4711 | {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, | 4488 | {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, |
4712 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, | 4489 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, |
4713 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, | 4490 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, |
4714 | {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, | 4491 | {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, |
4715 | {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, | 4492 | {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, |
@@ -4721,11 +4498,12 @@ static const struct usb_action pb0330xx_Initial[] = { | |||
4721 | {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, | 4498 | {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, |
4722 | {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, | 4499 | {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, |
4723 | {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, | 4500 | {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, |
4501 | {0xdd, 0x00, 0x0200}, | ||
4724 | {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, | 4502 | {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, |
4725 | {0xaa, 0x01, 0x0006}, | 4503 | {0xaa, 0x01, 0x0006}, |
4726 | {0xaa, 0x02, 0x0011}, | 4504 | {0xaa, 0x02, 0x0011}, |
4727 | {0xaa, 0x03, 0x01e7}, | 4505 | {0xaa, 0x03, 0x01e5}, /*jfm: was 1e7*/ |
4728 | {0xaa, 0x04, 0x0287}, | 4506 | {0xaa, 0x04, 0x0285}, /*jfm: was 0287*/ |
4729 | {0xaa, 0x06, 0x0003}, | 4507 | {0xaa, 0x06, 0x0003}, |
4730 | {0xaa, 0x07, 0x3002}, | 4508 | {0xaa, 0x07, 0x3002}, |
4731 | {0xaa, 0x20, 0x1100}, | 4509 | {0xaa, 0x20, 0x1100}, |
@@ -4743,88 +4521,21 @@ static const struct usb_action pb0330xx_Initial[] = { | |||
4743 | {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, | 4521 | {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, |
4744 | {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, | 4522 | {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, |
4745 | {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, | 4523 | {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, |
4746 | {0xa0, 0x00, 0x01ad}, | 4524 | {0xa0, 0x09, 0x01ad}, /*jfm: was 00 */ |
4525 | {0xa0, 0x15, 0x01ae}, | ||
4747 | {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, | 4526 | {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, |
4748 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, | 4527 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, |
4749 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, | 4528 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, |
4750 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, | 4529 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, |
4751 | {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, | 4530 | {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, |
4752 | {0xa0, 0x6c, ZC3XX_R18D_YTARGET}, | 4531 | {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /*jfm: was 6c*/ |
4753 | {0xa1, 0x01, 0x0002}, | ||
4754 | {0xa0, 0x09, 0x01ad}, | ||
4755 | {0xa0, 0x15, 0x01ae}, | ||
4756 | {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT}, | ||
4757 | {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND}, | ||
4758 | {0xa1, 0x01, 0x0091}, | ||
4759 | {0xa1, 0x01, 0x0095}, | ||
4760 | {0xa1, 0x01, 0x0096}, | ||
4761 | {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */ | ||
4762 | {0xa0, 0xf8, ZC3XX_R10B_RGB01}, | ||
4763 | {0xa0, 0xf8, ZC3XX_R10C_RGB02}, | ||
4764 | {0xa0, 0xf8, ZC3XX_R10D_RGB10}, | ||
4765 | {0xa0, 0x50, ZC3XX_R10E_RGB11}, | ||
4766 | {0xa0, 0xf8, ZC3XX_R10F_RGB12}, | ||
4767 | {0xa0, 0xf8, ZC3XX_R110_RGB20}, | ||
4768 | {0xa0, 0xf8, ZC3XX_R111_RGB21}, | ||
4769 | {0xa0, 0x50, ZC3XX_R112_RGB22}, | ||
4770 | {0xa1, 0x01, 0x0008}, | ||
4771 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */ | ||
4772 | {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ | ||
4773 | {0xa1, 0x01, 0x01c8}, | ||
4774 | {0xa1, 0x01, 0x01c9}, | ||
4775 | {0xa1, 0x01, 0x01ca}, | ||
4776 | {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ | ||
4777 | |||
4778 | {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */ | ||
4779 | {0xa0, 0xf8, ZC3XX_R10B_RGB01}, | ||
4780 | {0xa0, 0xf8, ZC3XX_R10C_RGB02}, | ||
4781 | {0xa0, 0xf8, ZC3XX_R10D_RGB10}, | ||
4782 | {0xa0, 0x50, ZC3XX_R10E_RGB11}, | ||
4783 | {0xa0, 0xf8, ZC3XX_R10F_RGB12}, | ||
4784 | {0xa0, 0xf8, ZC3XX_R110_RGB20}, | ||
4785 | {0xa0, 0xf8, ZC3XX_R111_RGB21}, | ||
4786 | {0xa0, 0x50, ZC3XX_R112_RGB22}, | ||
4787 | {0xa1, 0x01, 0x0180}, | ||
4788 | {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
4789 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | ||
4790 | {0xaa, 0x05, 0x0066}, | ||
4791 | {0xaa, 0x09, 0x02b2}, | ||
4792 | {0xaa, 0x10, 0x0002}, | ||
4793 | |||
4794 | {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, | ||
4795 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, | ||
4796 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, | ||
4797 | {0xa0, 0x8c, ZC3XX_R192_EXPOSURELIMITLOW}, | ||
4798 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, | ||
4799 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, | ||
4800 | {0xa0, 0x8a, ZC3XX_R197_ANTIFLICKERLOW}, | ||
4801 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, | ||
4802 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, | ||
4803 | {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, | ||
4804 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, | ||
4805 | {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0}, | ||
4806 | {0xa0, 0xf0, ZC3XX_R01E_HSYNC_1}, | ||
4807 | {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, | ||
4808 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | ||
4809 | {0xa0, 0x09, 0x01ad}, | ||
4810 | {0xa0, 0x15, 0x01ae}, | ||
4811 | {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
4812 | {0xa1, 0x01, 0x0180}, | ||
4813 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
4814 | {0xa1, 0x01, 0x0008}, | ||
4815 | {0xa1, 0x01, 0x0007}, | ||
4816 | /* {0xa0, 0x30, 0x0007}, */ | ||
4817 | /* {0xa0, 0x00, 0x0007}, */ | ||
4818 | {} | 4532 | {} |
4819 | }; | 4533 | }; |
4820 | 4534 | static const struct usb_action pb0330_InitialScale[] = { /* 320x240 */ | |
4821 | static const struct usb_action pb0330xx_InitialScale[] = { | ||
4822 | {0xa1, 0x01, 0x0008}, | ||
4823 | {0xa1, 0x01, 0x0008}, | ||
4824 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 4535 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
4825 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */ | 4536 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */ |
4826 | {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, | 4537 | {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, |
4827 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 10 */ | 4538 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, |
4828 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, | 4539 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, |
4829 | {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, | 4540 | {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, |
4830 | {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, | 4541 | {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, |
@@ -4836,6 +4547,7 @@ static const struct usb_action pb0330xx_InitialScale[] = { | |||
4836 | {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, | 4547 | {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, |
4837 | {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, | 4548 | {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, |
4838 | {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, | 4549 | {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, |
4550 | {0xdd, 0x00, 0x0200}, | ||
4839 | {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, | 4551 | {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, |
4840 | {0xaa, 0x01, 0x0006}, | 4552 | {0xaa, 0x01, 0x0006}, |
4841 | {0xaa, 0x02, 0x0011}, | 4553 | {0xaa, 0x02, 0x0011}, |
@@ -4858,53 +4570,43 @@ static const struct usb_action pb0330xx_InitialScale[] = { | |||
4858 | {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, | 4570 | {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, |
4859 | {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, | 4571 | {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, |
4860 | {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, | 4572 | {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, |
4861 | {0xa0, 0x00, 0x01ad}, | 4573 | {0xa0, 0x09, 0x01ad}, |
4574 | {0xa0, 0x15, 0x01ae}, | ||
4862 | {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, | 4575 | {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, |
4863 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, | 4576 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, |
4864 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, | 4577 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, |
4865 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, | 4578 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, |
4866 | {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, | 4579 | {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, |
4867 | {0xa0, 0x6c, ZC3XX_R18D_YTARGET}, | 4580 | {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /*jfm: was 6c*/ |
4868 | {0xa1, 0x01, 0x0002}, | 4581 | {} |
4869 | {0xa0, 0x09, 0x01ad}, | 4582 | }; |
4870 | {0xa0, 0x15, 0x01ae}, | 4583 | static const struct usb_action pb0330_50HZ[] = { |
4871 | {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT}, | ||
4872 | {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND}, | ||
4873 | {0xa1, 0x01, 0x0091}, | ||
4874 | {0xa1, 0x01, 0x0095}, | ||
4875 | {0xa1, 0x01, 0x0096}, | ||
4876 | {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */ | ||
4877 | {0xa0, 0xf8, ZC3XX_R10B_RGB01}, | ||
4878 | {0xa0, 0xf8, ZC3XX_R10C_RGB02}, | ||
4879 | {0xa0, 0xf8, ZC3XX_R10D_RGB10}, | ||
4880 | {0xa0, 0x50, ZC3XX_R10E_RGB11}, | ||
4881 | {0xa0, 0xf8, ZC3XX_R10F_RGB12}, | ||
4882 | {0xa0, 0xf8, ZC3XX_R110_RGB20}, | ||
4883 | {0xa0, 0xf8, ZC3XX_R111_RGB21}, | ||
4884 | {0xa0, 0x50, ZC3XX_R112_RGB22}, | ||
4885 | {0xa1, 0x01, 0x0008}, | ||
4886 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */ | ||
4887 | {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ | ||
4888 | {0xa1, 0x01, 0x01c8}, | ||
4889 | {0xa1, 0x01, 0x01c9}, | ||
4890 | {0xa1, 0x01, 0x01ca}, | ||
4891 | {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ | ||
4892 | |||
4893 | {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */ | ||
4894 | {0xa0, 0xf8, ZC3XX_R10B_RGB01}, | ||
4895 | {0xa0, 0xf8, ZC3XX_R10C_RGB02}, | ||
4896 | {0xa0, 0xf8, ZC3XX_R10D_RGB10}, | ||
4897 | {0xa0, 0x50, ZC3XX_R10E_RGB11}, | ||
4898 | {0xa0, 0xf8, ZC3XX_R10F_RGB12}, | ||
4899 | {0xa0, 0xf8, ZC3XX_R110_RGB20}, | ||
4900 | {0xa0, 0xf8, ZC3XX_R111_RGB21}, | ||
4901 | {0xa0, 0x50, ZC3XX_R112_RGB22}, | ||
4902 | {0xa1, 0x01, 0x0180}, | ||
4903 | {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
4904 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | 4584 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
4905 | {0xaa, 0x05, 0x0066}, | 4585 | {0xbb, 0x00, 0x055c}, |
4906 | {0xaa, 0x09, 0x02b2}, | 4586 | {0xbb, 0x01, 0x09aa}, |
4907 | {0xaa, 0x10, 0x0002}, | 4587 | {0xbb, 0x00, 0x1001}, |
4588 | {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, | ||
4589 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, | ||
4590 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, | ||
4591 | {0xa0, 0xc4, ZC3XX_R192_EXPOSURELIMITLOW}, | ||
4592 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, | ||
4593 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, | ||
4594 | {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, | ||
4595 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, | ||
4596 | {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE}, | ||
4597 | {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, | ||
4598 | {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, | ||
4599 | {0xa0, 0x5c, ZC3XX_R01D_HSYNC_0}, | ||
4600 | {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, | ||
4601 | {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, | ||
4602 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | ||
4603 | {} | ||
4604 | }; | ||
4605 | static const struct usb_action pb0330_50HZScale[] = { | ||
4606 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | ||
4607 | {0xbb, 0x00, 0x0566}, | ||
4608 | {0xbb, 0x02, 0x09b2}, | ||
4609 | {0xbb, 0x00, 0x1002}, | ||
4908 | {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, | 4610 | {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, |
4909 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, | 4611 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, |
4910 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, | 4612 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, |
@@ -4912,124 +4614,102 @@ static const struct usb_action pb0330xx_InitialScale[] = { | |||
4912 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, | 4614 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, |
4913 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, | 4615 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, |
4914 | {0xa0, 0x8a, ZC3XX_R197_ANTIFLICKERLOW}, | 4616 | {0xa0, 0x8a, ZC3XX_R197_ANTIFLICKERLOW}, |
4915 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, | 4617 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, |
4916 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, | 4618 | {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE}, |
4917 | {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, | 4619 | {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
4918 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, | 4620 | {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, |
4919 | {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0}, | 4621 | {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0}, |
4920 | {0xa0, 0xf0, ZC3XX_R01E_HSYNC_1}, | 4622 | {0xa0, 0xf0, ZC3XX_R01E_HSYNC_1}, |
4921 | {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, | 4623 | {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, |
4922 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | 4624 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, |
4923 | {0xa0, 0x09, 0x01ad}, | ||
4924 | {0xa0, 0x15, 0x01ae}, | ||
4925 | {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
4926 | {0xa1, 0x01, 0x0180}, | ||
4927 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
4928 | {0xa1, 0x01, 0x0008}, | ||
4929 | {0xa1, 0x01, 0x0007}, | ||
4930 | /* {0xa0, 0x30, 0x0007}, */ | ||
4931 | /* {0xa0, 0x00, 0x0007}, */ | ||
4932 | {} | ||
4933 | }; | ||
4934 | static const struct usb_action pb0330_50HZ[] = { | ||
4935 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | ||
4936 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */ | ||
4937 | {0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,ee,cc */ | ||
4938 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | ||
4939 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | ||
4940 | {0xa0, 0x46, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,46,cc */ | ||
4941 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | ||
4942 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | ||
4943 | {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */ | ||
4944 | {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */ | ||
4945 | {0xa0, 0x68, ZC3XX_R01D_HSYNC_0}, /* 00,1d,68,cc */ | ||
4946 | {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */ | ||
4947 | {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */ | ||
4948 | {} | ||
4949 | }; | ||
4950 | static const struct usb_action pb0330_50HZScale[] = { | ||
4951 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | ||
4952 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | ||
4953 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */ | ||
4954 | {0xa0, 0xa0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,a0,cc */ | ||
4955 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | ||
4956 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | ||
4957 | {0xa0, 0x7a, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7a,cc */ | ||
4958 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | ||
4959 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | ||
4960 | {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */ | ||
4961 | {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */ | ||
4962 | {0xa0, 0xe5, ZC3XX_R01D_HSYNC_0}, /* 00,1d,e5,cc */ | ||
4963 | {0xa0, 0xf0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,f0,cc */ | ||
4964 | {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,f8,cc */ | ||
4965 | {} | 4625 | {} |
4966 | }; | 4626 | }; |
4967 | static const struct usb_action pb0330_60HZ[] = { | 4627 | static const struct usb_action pb0330_60HZ[] = { |
4968 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 4628 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
4969 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 4629 | {0xbb, 0x00, 0x0535}, |
4970 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */ | 4630 | {0xbb, 0x01, 0x0974}, |
4971 | {0xa0, 0xdd, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,dd,cc */ | 4631 | {0xbb, 0x00, 0x1001}, |
4972 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 4632 | {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, |
4973 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 4633 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, |
4974 | {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3d,cc */ | 4634 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, |
4975 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 4635 | {0xa0, 0xfe, ZC3XX_R192_EXPOSURELIMITLOW}, |
4976 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 4636 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, |
4977 | {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */ | 4637 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, |
4978 | {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */ | 4638 | {0xa0, 0x3e, ZC3XX_R197_ANTIFLICKERLOW}, |
4979 | {0xa0, 0x43, ZC3XX_R01D_HSYNC_0}, /* 00,1d,43,cc */ | 4639 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, |
4980 | {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, /* 00,1e,50,cc */ | 4640 | {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE}, |
4981 | {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */ | 4641 | {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
4642 | {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, | ||
4643 | {0xa0, 0x35, ZC3XX_R01D_HSYNC_0}, | ||
4644 | {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, | ||
4645 | {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, | ||
4646 | {0xa0, 0xd0, ZC3XX_R020_HSYNC_3}, | ||
4982 | {} | 4647 | {} |
4983 | }; | 4648 | }; |
4984 | static const struct usb_action pb0330_60HZScale[] = { | 4649 | static const struct usb_action pb0330_60HZScale[] = { |
4985 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 4650 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
4986 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 4651 | {0xbb, 0x00, 0x0535}, |
4987 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */ | 4652 | {0xbb, 0x02, 0x096c}, |
4988 | {0xa0, 0xa0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,a0,cc */ | 4653 | {0xbb, 0x00, 0x1002}, |
4989 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 4654 | {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, |
4990 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 4655 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, |
4991 | {0xa0, 0x7a, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7a,cc */ | 4656 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, |
4992 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 4657 | {0xa0, 0xc0, ZC3XX_R192_EXPOSURELIMITLOW}, |
4993 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 4658 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, |
4994 | {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */ | 4659 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, |
4995 | {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */ | 4660 | {0xa0, 0x7c, ZC3XX_R197_ANTIFLICKERLOW}, |
4996 | {0xa0, 0x41, ZC3XX_R01D_HSYNC_0}, /* 00,1d,41,cc */ | 4661 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, |
4997 | {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, /* 00,1e,50,cc */ | 4662 | {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE}, |
4998 | {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */ | 4663 | {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
4664 | {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, | ||
4665 | {0xa0, 0x35, ZC3XX_R01D_HSYNC_0}, | ||
4666 | {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, | ||
4667 | {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, | ||
4668 | {0xa0, 0xd0, ZC3XX_R020_HSYNC_3}, | ||
4999 | {} | 4669 | {} |
5000 | }; | 4670 | }; |
5001 | static const struct usb_action pb0330_NoFliker[] = { | 4671 | static const struct usb_action pb0330_NoFliker[] = { |
5002 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 4672 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
5003 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 4673 | {0xbb, 0x00, 0x0509}, |
5004 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */ | 4674 | {0xbb, 0x02, 0x0940}, |
5005 | {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */ | 4675 | {0xbb, 0x00, 0x1002}, |
5006 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 4676 | {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, |
5007 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 4677 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, |
5008 | {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */ | 4678 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, |
5009 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 4679 | {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, |
5010 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 4680 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, |
5011 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ | 4681 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, |
5012 | {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ | 4682 | {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW}, |
5013 | {0xa0, 0x09, ZC3XX_R01D_HSYNC_0}, /* 00,1d,09,cc */ | 4683 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, |
5014 | {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, /* 00,1e,40,cc */ | 4684 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, |
5015 | {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */ | 4685 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
4686 | {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, | ||
4687 | {0xa0, 0x09, ZC3XX_R01D_HSYNC_0}, | ||
4688 | {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, | ||
4689 | {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, | ||
4690 | {0xa0, 0xe0, ZC3XX_R020_HSYNC_3}, | ||
5016 | {} | 4691 | {} |
5017 | }; | 4692 | }; |
5018 | static const struct usb_action pb0330_NoFlikerScale[] = { | 4693 | static const struct usb_action pb0330_NoFlikerScale[] = { |
5019 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 4694 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
5020 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 4695 | {0xbb, 0x00, 0x0535}, |
5021 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */ | 4696 | {0xbb, 0x01, 0x0980}, |
5022 | {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */ | 4697 | {0xbb, 0x00, 0x1001}, |
5023 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 4698 | {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, |
5024 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 4699 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, |
5025 | {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */ | 4700 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, |
5026 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 4701 | {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, |
5027 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 4702 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, |
5028 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ | 4703 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, |
5029 | {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ | 4704 | {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW}, |
5030 | {0xa0, 0x09, ZC3XX_R01D_HSYNC_0}, /* 00,1d,09,cc */ | 4705 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, |
5031 | {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, /* 00,1e,40,cc */ | 4706 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, |
5032 | {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */ | 4707 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
4708 | {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, | ||
4709 | {0xa0, 0x35, ZC3XX_R01D_HSYNC_0}, | ||
4710 | {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, | ||
4711 | {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, | ||
4712 | {0xa0, 0xe0, ZC3XX_R020_HSYNC_3}, | ||
5033 | {} | 4713 | {} |
5034 | }; | 4714 | }; |
5035 | 4715 | ||
@@ -5655,7 +5335,7 @@ static const struct usb_action tas5130CK_InitialScale[] = { | |||
5655 | {} | 5335 | {} |
5656 | }; | 5336 | }; |
5657 | 5337 | ||
5658 | static const struct usb_action tas5130cxx_Initial[] = { | 5338 | static const struct usb_action tas5130cxx_InitialScale[] = { /* 320x240 */ |
5659 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 5339 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
5660 | {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT}, | 5340 | {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT}, |
5661 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | 5341 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
@@ -5684,74 +5364,19 @@ static const struct usb_action tas5130cxx_Initial[] = { | |||
5684 | {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, | 5364 | {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, |
5685 | {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, | 5365 | {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, |
5686 | {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, | 5366 | {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, |
5687 | {0xa0, 0x68, ZC3XX_R18D_YTARGET}, | 5367 | {0xa0, 0x95, ZC3XX_R18D_YTARGET}, |
5688 | {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, | 5368 | {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, |
5689 | {0xa0, 0x00, 0x01ad}, | 5369 | {0xa0, 0x00, 0x01ad}, |
5690 | {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, | 5370 | {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, |
5691 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, | 5371 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, |
5692 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, | 5372 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, |
5693 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, | 5373 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, |
5694 | {0xa1, 0x01, 0x0002}, | ||
5695 | {0xa1, 0x01, 0x0008}, | ||
5696 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */ | ||
5697 | {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ | ||
5698 | {0xa1, 0x01, 0x01c8}, | ||
5699 | {0xa1, 0x01, 0x01c9}, | ||
5700 | {0xa1, 0x01, 0x01ca}, | ||
5701 | {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ | ||
5702 | |||
5703 | {0xa0, 0x68, ZC3XX_R10A_RGB00}, /* matrix */ | ||
5704 | {0xa0, 0xec, ZC3XX_R10B_RGB01}, | ||
5705 | {0xa0, 0xec, ZC3XX_R10C_RGB02}, | ||
5706 | {0xa0, 0xec, ZC3XX_R10D_RGB10}, | ||
5707 | {0xa0, 0x68, ZC3XX_R10E_RGB11}, | ||
5708 | {0xa0, 0xec, ZC3XX_R10F_RGB12}, | ||
5709 | {0xa0, 0xec, ZC3XX_R110_RGB20}, | ||
5710 | {0xa0, 0xec, ZC3XX_R111_RGB21}, | ||
5711 | {0xa0, 0x68, ZC3XX_R112_RGB22}, | ||
5712 | |||
5713 | {0xa1, 0x01, 0x018d}, | ||
5714 | {0xa0, 0x90, ZC3XX_R18D_YTARGET}, /* 90 */ | ||
5715 | {0xa1, 0x01, 0x0180}, | ||
5716 | {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
5717 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | ||
5718 | |||
5719 | {0xaa, 0xa3, 0x0001}, | ||
5720 | {0xaa, 0xa4, 0x0077}, | ||
5721 | {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, | ||
5722 | {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, | ||
5723 | |||
5724 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 00 */ | ||
5725 | {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, /* 03 */ | ||
5726 | {0xa0, 0xe8, ZC3XX_R192_EXPOSURELIMITLOW}, /* e8 */ | ||
5727 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 0 */ | ||
5728 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 0 */ | ||
5729 | {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 7d */ | ||
5730 | |||
5731 | {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, | ||
5732 | {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, | ||
5733 | {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 08 */ | ||
5734 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 24 */ | ||
5735 | {0xa0, 0xf0, ZC3XX_R01D_HSYNC_0}, | ||
5736 | {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, | ||
5737 | {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, | ||
5738 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | ||
5739 | {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, | ||
5740 | {0xa0, 0xc0, ZC3XX_R0A0_MAXXLOW}, | ||
5741 | {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, /* 50 */ | ||
5742 | {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
5743 | {0xa1, 0x01, 0x0180}, | ||
5744 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
5745 | {} | 5374 | {} |
5746 | }; | 5375 | }; |
5747 | static const struct usb_action tas5130cxx_InitialScale[] = { | 5376 | static const struct usb_action tas5130cxx_Initial[] = { /* 640x480 */ |
5748 | /*?? {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, */ | ||
5749 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 5377 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
5750 | {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, | 5378 | {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, |
5751 | |||
5752 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | 5379 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
5753 | {0xa1, 0x01, 0x0008}, | ||
5754 | |||
5755 | {0xa0, 0x02, ZC3XX_R010_CMOSSENSORSELECT}, | 5380 | {0xa0, 0x02, ZC3XX_R010_CMOSSENSORSELECT}, |
5756 | {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, | 5381 | {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, |
5757 | {0xa0, 0x00, ZC3XX_R001_SYSTEMOPERATING}, | 5382 | {0xa0, 0x00, ZC3XX_R001_SYSTEMOPERATING}, |
@@ -5775,63 +5400,13 @@ static const struct usb_action tas5130cxx_InitialScale[] = { | |||
5775 | {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, | 5400 | {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, |
5776 | {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, | 5401 | {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, |
5777 | {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, | 5402 | {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, |
5778 | {0xa0, 0x68, ZC3XX_R18D_YTARGET}, | 5403 | {0xa0, 0x95, ZC3XX_R18D_YTARGET}, |
5779 | {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, | 5404 | {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, |
5780 | {0xa0, 0x00, 0x01ad}, | 5405 | {0xa0, 0x00, 0x01ad}, |
5781 | {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, | 5406 | {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, |
5782 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, | 5407 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, |
5783 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, | 5408 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, |
5784 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, | 5409 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, |
5785 | {0xa1, 0x01, 0x0002}, | ||
5786 | {0xa1, 0x01, 0x0008}, | ||
5787 | |||
5788 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | ||
5789 | {0xa1, 0x01, 0x0008}, /* clock ? */ | ||
5790 | {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ | ||
5791 | {0xa1, 0x01, 0x01c8}, | ||
5792 | {0xa1, 0x01, 0x01c9}, | ||
5793 | {0xa1, 0x01, 0x01ca}, | ||
5794 | {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ | ||
5795 | |||
5796 | {0xa0, 0x68, ZC3XX_R10A_RGB00}, /* matrix */ | ||
5797 | {0xa0, 0xec, ZC3XX_R10B_RGB01}, | ||
5798 | {0xa0, 0xec, ZC3XX_R10C_RGB02}, | ||
5799 | {0xa0, 0xec, ZC3XX_R10D_RGB10}, | ||
5800 | {0xa0, 0x68, ZC3XX_R10E_RGB11}, | ||
5801 | {0xa0, 0xec, ZC3XX_R10F_RGB12}, | ||
5802 | {0xa0, 0xec, ZC3XX_R110_RGB20}, | ||
5803 | {0xa0, 0xec, ZC3XX_R111_RGB21}, | ||
5804 | {0xa0, 0x68, ZC3XX_R112_RGB22}, | ||
5805 | |||
5806 | {0xa1, 0x01, 0x018d}, | ||
5807 | {0xa0, 0x90, ZC3XX_R18D_YTARGET}, | ||
5808 | {0xa1, 0x01, 0x0180}, | ||
5809 | {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
5810 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | ||
5811 | {0xaa, 0xa3, 0x0001}, | ||
5812 | {0xaa, 0xa4, 0x0063}, | ||
5813 | {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, | ||
5814 | {0xa0, 0x63, ZC3XX_R0A4_EXPOSURETIMELOW}, | ||
5815 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, | ||
5816 | {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, | ||
5817 | {0xa0, 0x38, ZC3XX_R192_EXPOSURELIMITLOW}, | ||
5818 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, | ||
5819 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, | ||
5820 | {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, | ||
5821 | {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, | ||
5822 | {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, | ||
5823 | {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF}, | ||
5824 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, | ||
5825 | {0xa0, 0xd3, ZC3XX_R01D_HSYNC_0}, | ||
5826 | {0xa0, 0xda, ZC3XX_R01E_HSYNC_1}, | ||
5827 | {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, | ||
5828 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | ||
5829 | {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, | ||
5830 | {0xa0, 0x4c, ZC3XX_R0A0_MAXXLOW}, | ||
5831 | {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, | ||
5832 | {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
5833 | {0xa1, 0x01, 0x0180}, | ||
5834 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, | ||
5835 | {} | 5410 | {} |
5836 | }; | 5411 | }; |
5837 | static const struct usb_action tas5130cxx_50HZ[] = { | 5412 | static const struct usb_action tas5130cxx_50HZ[] = { |
@@ -5841,20 +5416,22 @@ static const struct usb_action tas5130cxx_50HZ[] = { | |||
5841 | {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ | 5416 | {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ |
5842 | {0xa0, 0x63, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,63,cc */ | 5417 | {0xa0, 0x63, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,63,cc */ |
5843 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 5418 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ |
5844 | {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */ | 5419 | {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, |
5845 | {0xa0, 0x38, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,38,cc */ | 5420 | {0xa0, 0xfe, ZC3XX_R192_EXPOSURELIMITLOW}, |
5846 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 5421 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ |
5847 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 5422 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ |
5848 | {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,47,cc */ | 5423 | {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,47,cc */ |
5849 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 5424 | {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, |
5850 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 5425 | {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, |
5851 | {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */ | 5426 | {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
5852 | {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */ | 5427 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, |
5853 | {0xa0, 0xd3, ZC3XX_R01D_HSYNC_0}, /* 00,1d,d3,cc */ | 5428 | {0xa0, 0xd3, ZC3XX_R01D_HSYNC_0}, /* 00,1d,d3,cc */ |
5854 | {0xa0, 0xda, ZC3XX_R01E_HSYNC_1}, /* 00,1e,da,cc */ | 5429 | {0xa0, 0xda, ZC3XX_R01E_HSYNC_1}, /* 00,1e,da,cc */ |
5855 | {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */ | 5430 | {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */ |
5856 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ | 5431 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ |
5857 | {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */ | 5432 | {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */ |
5433 | {0xa0, 0x4c, ZC3XX_R0A0_MAXXLOW}, | ||
5434 | {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, | ||
5858 | {} | 5435 | {} |
5859 | }; | 5436 | }; |
5860 | static const struct usb_action tas5130cxx_50HZScale[] = { | 5437 | static const struct usb_action tas5130cxx_50HZScale[] = { |
@@ -5864,20 +5441,22 @@ static const struct usb_action tas5130cxx_50HZScale[] = { | |||
5864 | {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ | 5441 | {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ |
5865 | {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,77,cc */ | 5442 | {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,77,cc */ |
5866 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 5443 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ |
5867 | {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,03,cc */ | 5444 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, |
5868 | {0xa0, 0xe8, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,e8,cc */ | 5445 | {0xa0, 0xd0, ZC3XX_R192_EXPOSURELIMITLOW}, |
5869 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 5446 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ |
5870 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 5447 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ |
5871 | {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7d,cc */ | 5448 | {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7d,cc */ |
5872 | {0xa0, 0x14, ZC3XX_R18C_AEFREEZE}, /* 01,8c,14,cc */ | 5449 | {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, |
5873 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 5450 | {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, |
5874 | {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */ | 5451 | {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
5875 | {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */ | 5452 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, |
5876 | {0xa0, 0xf0, ZC3XX_R01D_HSYNC_0}, /* 00,1d,f0,cc */ | 5453 | {0xa0, 0xf0, ZC3XX_R01D_HSYNC_0}, /* 00,1d,f0,cc */ |
5877 | {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,f4,cc */ | 5454 | {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,f4,cc */ |
5878 | {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,f8,cc */ | 5455 | {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,f8,cc */ |
5879 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ | 5456 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ |
5880 | {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */ | 5457 | {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */ |
5458 | {0xa0, 0xc0, ZC3XX_R0A0_MAXXLOW}, | ||
5459 | {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, | ||
5881 | {} | 5460 | {} |
5882 | }; | 5461 | }; |
5883 | static const struct usb_action tas5130cxx_60HZ[] = { | 5462 | static const struct usb_action tas5130cxx_60HZ[] = { |
@@ -5887,20 +5466,22 @@ static const struct usb_action tas5130cxx_60HZ[] = { | |||
5887 | {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ | 5466 | {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ |
5888 | {0xa0, 0x36, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,36,cc */ | 5467 | {0xa0, 0x36, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,36,cc */ |
5889 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 5468 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ |
5890 | {0xa0, 0x01, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,01,cc */ | 5469 | {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID}, |
5891 | {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */ | 5470 | {0xa0, 0x54, ZC3XX_R192_EXPOSURELIMITLOW}, |
5892 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 5471 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ |
5893 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 5472 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ |
5894 | {0xa0, 0x3e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3e,cc */ | 5473 | {0xa0, 0x3e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3e,cc */ |
5895 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 5474 | {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, |
5896 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 5475 | {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, |
5897 | {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */ | 5476 | {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
5898 | {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */ | 5477 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, |
5899 | {0xa0, 0xca, ZC3XX_R01D_HSYNC_0}, /* 00,1d,ca,cc */ | 5478 | {0xa0, 0xca, ZC3XX_R01D_HSYNC_0}, /* 00,1d,ca,cc */ |
5900 | {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */ | 5479 | {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */ |
5901 | {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */ | 5480 | {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */ |
5902 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ | 5481 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ |
5903 | {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */ | 5482 | {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */ |
5483 | {0xa0, 0x28, ZC3XX_R0A0_MAXXLOW}, | ||
5484 | {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, | ||
5904 | {} | 5485 | {} |
5905 | }; | 5486 | }; |
5906 | static const struct usb_action tas5130cxx_60HZScale[] = { | 5487 | static const struct usb_action tas5130cxx_60HZScale[] = { |
@@ -5910,20 +5491,22 @@ static const struct usb_action tas5130cxx_60HZScale[] = { | |||
5910 | {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ | 5491 | {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ |
5911 | {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,77,cc */ | 5492 | {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,77,cc */ |
5912 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 5493 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ |
5913 | {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,03,cc */ | 5494 | {0xa0, 0x09, ZC3XX_R191_EXPOSURELIMITMID}, |
5914 | {0xa0, 0xe8, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,e8,cc */ | 5495 | {0xa0, 0x47, ZC3XX_R192_EXPOSURELIMITLOW}, |
5915 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 5496 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ |
5916 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 5497 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ |
5917 | {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7d,cc */ | 5498 | {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7d,cc */ |
5918 | {0xa0, 0x14, ZC3XX_R18C_AEFREEZE}, /* 01,8c,14,cc */ | 5499 | {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, |
5919 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 5500 | {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, |
5920 | {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */ | 5501 | {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
5921 | {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */ | 5502 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, |
5922 | {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c8,cc */ | 5503 | {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c8,cc */ |
5923 | {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */ | 5504 | {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */ |
5924 | {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */ | 5505 | {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */ |
5925 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ | 5506 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ |
5926 | {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */ | 5507 | {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */ |
5508 | {0xa0, 0x20, ZC3XX_R0A0_MAXXLOW}, | ||
5509 | {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, | ||
5927 | {} | 5510 | {} |
5928 | }; | 5511 | }; |
5929 | static const struct usb_action tas5130cxx_NoFliker[] = { | 5512 | static const struct usb_action tas5130cxx_NoFliker[] = { |
@@ -5933,13 +5516,13 @@ static const struct usb_action tas5130cxx_NoFliker[] = { | |||
5933 | {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ | 5516 | {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ |
5934 | {0xa0, 0x40, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,40,cc */ | 5517 | {0xa0, 0x40, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,40,cc */ |
5935 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 5518 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ |
5936 | {0xa0, 0x01, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,01,cc */ | 5519 | {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID}, |
5937 | {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */ | 5520 | {0xa0, 0xa0, ZC3XX_R192_EXPOSURELIMITLOW}, |
5938 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 5521 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, |
5939 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 5522 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, |
5940 | {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */ | 5523 | {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW}, |
5941 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 5524 | {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, |
5942 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 5525 | {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, |
5943 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ | 5526 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ |
5944 | {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ | 5527 | {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ |
5945 | {0xa0, 0xbc, ZC3XX_R01D_HSYNC_0}, /* 00,1d,bc,cc */ | 5528 | {0xa0, 0xbc, ZC3XX_R01D_HSYNC_0}, /* 00,1d,bc,cc */ |
@@ -5947,6 +5530,8 @@ static const struct usb_action tas5130cxx_NoFliker[] = { | |||
5947 | {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */ | 5530 | {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */ |
5948 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ | 5531 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ |
5949 | {0xa0, 0x02, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,02,cc */ | 5532 | {0xa0, 0x02, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,02,cc */ |
5533 | {0xa0, 0xf0, ZC3XX_R0A0_MAXXLOW}, | ||
5534 | {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, | ||
5950 | {} | 5535 | {} |
5951 | }; | 5536 | }; |
5952 | 5537 | ||
@@ -5957,13 +5542,13 @@ static const struct usb_action tas5130cxx_NoFlikerScale[] = { | |||
5957 | {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ | 5542 | {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ |
5958 | {0xa0, 0x90, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,90,cc */ | 5543 | {0xa0, 0x90, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,90,cc */ |
5959 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 5544 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ |
5960 | {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,03,cc */ | 5545 | {0xa0, 0x0a, ZC3XX_R191_EXPOSURELIMITMID}, |
5961 | {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */ | 5546 | {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW}, |
5962 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 5547 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, |
5963 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 5548 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, |
5964 | {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */ | 5549 | {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW}, |
5965 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 5550 | {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, |
5966 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 5551 | {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, |
5967 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ | 5552 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ |
5968 | {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ | 5553 | {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ |
5969 | {0xa0, 0xbc, ZC3XX_R01D_HSYNC_0}, /* 00,1d,bc,cc */ | 5554 | {0xa0, 0xbc, ZC3XX_R01D_HSYNC_0}, /* 00,1d,bc,cc */ |
@@ -5971,6 +5556,8 @@ static const struct usb_action tas5130cxx_NoFlikerScale[] = { | |||
5971 | {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */ | 5556 | {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */ |
5972 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ | 5557 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ |
5973 | {0xa0, 0x02, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,02,cc */ | 5558 | {0xa0, 0x02, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,02,cc */ |
5559 | {0xa0, 0xf0, ZC3XX_R0A0_MAXXLOW}, | ||
5560 | {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, | ||
5974 | {} | 5561 | {} |
5975 | }; | 5562 | }; |
5976 | 5563 | ||
@@ -6303,8 +5890,10 @@ static __u16 i2c_read(struct gspca_dev *gspca_dev, | |||
6303 | 5890 | ||
6304 | reg_w_i(gspca_dev->dev, reg, 0x0092); | 5891 | reg_w_i(gspca_dev->dev, reg, 0x0092); |
6305 | reg_w_i(gspca_dev->dev, 0x02, 0x0090); /* <- read command */ | 5892 | reg_w_i(gspca_dev->dev, 0x02, 0x0090); /* <- read command */ |
6306 | msleep(25); | 5893 | msleep(20); |
6307 | retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ | 5894 | retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ |
5895 | if (retbyte != 0x00) | ||
5896 | err("i2c_r status error %02x", retbyte); | ||
6308 | retval = reg_r_i(gspca_dev, 0x0095); /* read Lowbyte */ | 5897 | retval = reg_r_i(gspca_dev, 0x0095); /* read Lowbyte */ |
6309 | retval |= reg_r_i(gspca_dev, 0x0096) << 8; /* read Hightbyte */ | 5898 | retval |= reg_r_i(gspca_dev, 0x0096) << 8; /* read Hightbyte */ |
6310 | PDEBUG(D_USBI, "i2c r [%02x] -> %04x (%02x)", | 5899 | PDEBUG(D_USBI, "i2c r [%02x] -> %04x (%02x)", |
@@ -6323,8 +5912,10 @@ static __u8 i2c_write(struct gspca_dev *gspca_dev, | |||
6323 | reg_w_i(gspca_dev->dev, valL, 0x93); | 5912 | reg_w_i(gspca_dev->dev, valL, 0x93); |
6324 | reg_w_i(gspca_dev->dev, valH, 0x94); | 5913 | reg_w_i(gspca_dev->dev, valH, 0x94); |
6325 | reg_w_i(gspca_dev->dev, 0x01, 0x90); /* <- write command */ | 5914 | reg_w_i(gspca_dev->dev, 0x01, 0x90); /* <- write command */ |
6326 | msleep(15); | 5915 | msleep(1); |
6327 | retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ | 5916 | retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ |
5917 | if (retbyte != 0x00) | ||
5918 | err("i2c_w status error %02x", retbyte); | ||
6328 | PDEBUG(D_USBO, "i2c w [%02x] = %02x%02x (%02x)", | 5919 | PDEBUG(D_USBO, "i2c w [%02x] = %02x%02x (%02x)", |
6329 | reg, valH, valL, retbyte); | 5920 | reg, valH, valL, retbyte); |
6330 | return retbyte; | 5921 | return retbyte; |
@@ -6359,7 +5950,7 @@ static void usb_exchange(struct gspca_dev *gspca_dev, | |||
6359 | break; | 5950 | break; |
6360 | } | 5951 | } |
6361 | action++; | 5952 | action++; |
6362 | /* msleep(1); */ | 5953 | msleep(1); |
6363 | } | 5954 | } |
6364 | } | 5955 | } |
6365 | 5956 | ||
@@ -6380,11 +5971,13 @@ static void setmatrix(struct gspca_dev *gspca_dev) | |||
6380 | {0x4c, 0xf5, 0xff, 0xf9, 0x51, 0xf5, 0xfb, 0xed, 0x5f}; | 5971 | {0x4c, 0xf5, 0xff, 0xf9, 0x51, 0xf5, 0xfb, 0xed, 0x5f}; |
6381 | static const __u8 po2030_matrix[9] = | 5972 | static const __u8 po2030_matrix[9] = |
6382 | {0x60, 0xf0, 0xf0, 0xf0, 0x60, 0xf0, 0xf0, 0xf0, 0x60}; | 5973 | {0x60, 0xf0, 0xf0, 0xf0, 0x60, 0xf0, 0xf0, 0xf0, 0x60}; |
5974 | static const u8 tas5130c_matrix[9] = | ||
5975 | {0x68, 0xec, 0xec, 0xec, 0x68, 0xec, 0xec, 0xec, 0x68}; | ||
6383 | static const __u8 vf0250_matrix[9] = | 5976 | static const __u8 vf0250_matrix[9] = |
6384 | {0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b}; | 5977 | {0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b}; |
6385 | static const __u8 *matrix_tb[SENSOR_MAX] = { | 5978 | static const __u8 *matrix_tb[SENSOR_MAX] = { |
6386 | adcm2700_matrix, /* SENSOR_ADCM2700 0 */ | 5979 | adcm2700_matrix, /* SENSOR_ADCM2700 0 */ |
6387 | NULL, /* SENSOR_CS2102 1 */ | 5980 | ov7620_matrix, /* SENSOR_CS2102 1 */ |
6388 | NULL, /* SENSOR_CS2102K 2 */ | 5981 | NULL, /* SENSOR_CS2102K 2 */ |
6389 | gc0305_matrix, /* SENSOR_GC0305 3 */ | 5982 | gc0305_matrix, /* SENSOR_GC0305 3 */ |
6390 | NULL, /* SENSOR_HDCS2020b 4 */ | 5983 | NULL, /* SENSOR_HDCS2020b 4 */ |
@@ -6392,15 +5985,16 @@ static void setmatrix(struct gspca_dev *gspca_dev) | |||
6392 | NULL, /* SENSOR_HV7131C 6 */ | 5985 | NULL, /* SENSOR_HV7131C 6 */ |
6393 | NULL, /* SENSOR_ICM105A 7 */ | 5986 | NULL, /* SENSOR_ICM105A 7 */ |
6394 | NULL, /* SENSOR_MC501CB 8 */ | 5987 | NULL, /* SENSOR_MC501CB 8 */ |
6395 | ov7620_matrix, /* SENSOR_OV7620 9 */ | 5988 | gc0305_matrix, /* SENSOR_MI0360SOC 9 */ |
6396 | NULL, /* SENSOR_OV7630C 10 */ | 5989 | ov7620_matrix, /* SENSOR_OV7620 10 */ |
6397 | NULL, /* SENSOR_PAS106 11 */ | 5990 | NULL, /* SENSOR_OV7630C 11 */ |
6398 | pas202b_matrix, /* SENSOR_PAS202B 12 */ | 5991 | NULL, /* SENSOR_PAS106 12 */ |
6399 | NULL, /* SENSOR_PB0330 13 */ | 5992 | pas202b_matrix, /* SENSOR_PAS202B 13 */ |
6400 | po2030_matrix, /* SENSOR_PO2030 14 */ | 5993 | gc0305_matrix, /* SENSOR_PB0330 14 */ |
6401 | NULL, /* SENSOR_TAS5130CK 15 */ | 5994 | po2030_matrix, /* SENSOR_PO2030 15 */ |
6402 | NULL, /* SENSOR_TAS5130CXX 16 */ | 5995 | NULL, /* SENSOR_TAS5130CK 16 */ |
6403 | vf0250_matrix, /* SENSOR_TAS5130C_VF0250 17 */ | 5996 | tas5130c_matrix, /* SENSOR_TAS5130CXX 17 */ |
5997 | vf0250_matrix, /* SENSOR_TAS5130C_VF0250 18 */ | ||
6404 | }; | 5998 | }; |
6405 | 5999 | ||
6406 | matrix = matrix_tb[sd->sensor]; | 6000 | matrix = matrix_tb[sd->sensor]; |
@@ -6640,39 +6234,43 @@ static int setlightfreq(struct gspca_dev *gspca_dev) | |||
6640 | {MC501CB_NoFliker, MC501CB_NoFlikerScale, | 6234 | {MC501CB_NoFliker, MC501CB_NoFlikerScale, |
6641 | MC501CB_50HZ, MC501CB_50HZScale, | 6235 | MC501CB_50HZ, MC501CB_50HZScale, |
6642 | MC501CB_60HZ, MC501CB_60HZScale}, | 6236 | MC501CB_60HZ, MC501CB_60HZScale}, |
6643 | /* SENSOR_OV7620 9 */ | 6237 | /* SENSOR_MI0360SOC 9 */ |
6238 | {mi360soc_AENoFlikerScale, mi360soc_AENoFliker, | ||
6239 | mi360soc_AE50HZScale, mi360soc_AE50HZ, | ||
6240 | mi360soc_AE60HZScale, mi360soc_AE60HZ}, | ||
6241 | /* SENSOR_OV7620 10 */ | ||
6644 | {OV7620_NoFliker, OV7620_NoFliker, | 6242 | {OV7620_NoFliker, OV7620_NoFliker, |
6645 | OV7620_50HZ, OV7620_50HZ, | 6243 | OV7620_50HZ, OV7620_50HZ, |
6646 | OV7620_60HZ, OV7620_60HZ}, | 6244 | OV7620_60HZ, OV7620_60HZ}, |
6647 | /* SENSOR_OV7630C 10 */ | 6245 | /* SENSOR_OV7630C 11 */ |
6648 | {NULL, NULL, | 6246 | {NULL, NULL, |
6649 | NULL, NULL, | 6247 | NULL, NULL, |
6650 | NULL, NULL}, | 6248 | NULL, NULL}, |
6651 | /* SENSOR_PAS106 11 */ | 6249 | /* SENSOR_PAS106 12 */ |
6652 | {pas106b_NoFliker, pas106b_NoFliker, | 6250 | {pas106b_NoFliker, pas106b_NoFliker, |
6653 | pas106b_50HZ, pas106b_50HZ, | 6251 | pas106b_50HZ, pas106b_50HZ, |
6654 | pas106b_60HZ, pas106b_60HZ}, | 6252 | pas106b_60HZ, pas106b_60HZ}, |
6655 | /* SENSOR_PAS202B 12 */ | 6253 | /* SENSOR_PAS202B 13 */ |
6656 | {pas202b_NoFlikerScale, pas202b_NoFliker, | 6254 | {pas202b_NoFlikerScale, pas202b_NoFliker, |
6657 | pas202b_50HZScale, pas202b_50HZ, | 6255 | pas202b_50HZScale, pas202b_50HZ, |
6658 | pas202b_60HZScale, pas202b_60HZ}, | 6256 | pas202b_60HZScale, pas202b_60HZ}, |
6659 | /* SENSOR_PB0330 13 */ | 6257 | /* SENSOR_PB0330 14 */ |
6660 | {pb0330_NoFliker, pb0330_NoFlikerScale, | 6258 | {pb0330_NoFlikerScale, pb0330_NoFliker, |
6661 | pb0330_50HZ, pb0330_50HZScale, | 6259 | pb0330_50HZScale, pb0330_50HZ, |
6662 | pb0330_60HZ, pb0330_60HZScale}, | 6260 | pb0330_60HZScale, pb0330_60HZ}, |
6663 | /* SENSOR_PO2030 14 */ | 6261 | /* SENSOR_PO2030 15 */ |
6664 | {PO2030_NoFliker, PO2030_NoFliker, | 6262 | {PO2030_NoFliker, PO2030_NoFliker, |
6665 | PO2030_50HZ, PO2030_50HZ, | 6263 | PO2030_50HZ, PO2030_50HZ, |
6666 | PO2030_60HZ, PO2030_60HZ}, | 6264 | PO2030_60HZ, PO2030_60HZ}, |
6667 | /* SENSOR_TAS5130CK 15 */ | 6265 | /* SENSOR_TAS5130CK 16 */ |
6668 | {tas5130cxx_NoFliker, tas5130cxx_NoFlikerScale, | 6266 | {tas5130cxx_NoFlikerScale, tas5130cxx_NoFliker, |
6669 | tas5130cxx_50HZ, tas5130cxx_50HZScale, | 6267 | tas5130cxx_50HZScale, tas5130cxx_50HZ, |
6670 | tas5130cxx_60HZ, tas5130cxx_60HZScale}, | 6268 | tas5130cxx_60HZScale, tas5130cxx_60HZ}, |
6671 | /* SENSOR_TAS5130CXX 16 */ | 6269 | /* SENSOR_TAS5130CXX 17 */ |
6672 | {tas5130cxx_NoFliker, tas5130cxx_NoFlikerScale, | 6270 | {tas5130cxx_NoFlikerScale, tas5130cxx_NoFliker, |
6673 | tas5130cxx_50HZ, tas5130cxx_50HZScale, | 6271 | tas5130cxx_50HZScale, tas5130cxx_50HZ, |
6674 | tas5130cxx_60HZ, tas5130cxx_60HZScale}, | 6272 | tas5130cxx_60HZScale, tas5130cxx_60HZ}, |
6675 | /* SENSOR_TAS5130C_VF0250 17 */ | 6273 | /* SENSOR_TAS5130C_VF0250 18 */ |
6676 | {tas5130c_vf0250_NoFliker, tas5130c_vf0250_NoFlikerScale, | 6274 | {tas5130c_vf0250_NoFliker, tas5130c_vf0250_NoFlikerScale, |
6677 | tas5130c_vf0250_50HZ, tas5130c_vf0250_50HZScale, | 6275 | tas5130c_vf0250_50HZ, tas5130c_vf0250_50HZScale, |
6678 | tas5130c_vf0250_60HZ, tas5130c_vf0250_60HZScale}, | 6276 | tas5130c_vf0250_60HZ, tas5130c_vf0250_60HZScale}, |
@@ -6729,6 +6327,7 @@ static void send_unknown(struct usb_device *dev, int sensor) | |||
6729 | case SENSOR_ADCM2700: | 6327 | case SENSOR_ADCM2700: |
6730 | case SENSOR_GC0305: | 6328 | case SENSOR_GC0305: |
6731 | case SENSOR_OV7620: | 6329 | case SENSOR_OV7620: |
6330 | case SENSOR_MI0360SOC: | ||
6732 | case SENSOR_PB0330: | 6331 | case SENSOR_PB0330: |
6733 | case SENSOR_PO2030: | 6332 | case SENSOR_PO2030: |
6734 | reg_w(dev, 0x0d, 0x003a); | 6333 | reg_w(dev, 0x0d, 0x003a); |
@@ -6820,7 +6419,7 @@ static int vga_2wr_probe(struct gspca_dev *gspca_dev) | |||
6820 | start_2wr_probe(dev, 0x0e); /* PAS202BCB */ | 6419 | start_2wr_probe(dev, 0x0e); /* PAS202BCB */ |
6821 | reg_w(dev, 0x08, 0x008d); | 6420 | reg_w(dev, 0x08, 0x008d); |
6822 | i2c_write(gspca_dev, 0x03, 0xaa, 0x00); | 6421 | i2c_write(gspca_dev, 0x03, 0xaa, 0x00); |
6823 | msleep(500); | 6422 | msleep(50); |
6824 | retword = i2c_read(gspca_dev, 0x03); | 6423 | retword = i2c_read(gspca_dev, 0x03); |
6825 | if (retword != 0) | 6424 | if (retword != 0) |
6826 | return 0x0e; /* PAS202BCB */ | 6425 | return 0x0e; /* PAS202BCB */ |
@@ -6863,7 +6462,8 @@ struct sensor_by_chipset_revision { | |||
6863 | __u8 internal_sensor_id; | 6462 | __u8 internal_sensor_id; |
6864 | }; | 6463 | }; |
6865 | static const struct sensor_by_chipset_revision chipset_revision_sensor[] = { | 6464 | static const struct sensor_by_chipset_revision chipset_revision_sensor[] = { |
6866 | {0xc001, 0x13}, /* MI0360 */ | 6465 | {0xc000, 0x12}, /* TAS5130C */ |
6466 | {0xc001, 0x13}, /* MI0360SOC */ | ||
6867 | {0xe001, 0x13}, | 6467 | {0xe001, 0x13}, |
6868 | {0x8001, 0x13}, | 6468 | {0x8001, 0x13}, |
6869 | {0x8000, 0x14}, /* CS2102K */ | 6469 | {0x8000, 0x14}, /* CS2102K */ |
@@ -6963,7 +6563,6 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) | |||
6963 | reg_w(dev, 0x01, 0x0001); | 6563 | reg_w(dev, 0x01, 0x0001); |
6964 | reg_w(dev, 0xee, 0x008b); | 6564 | reg_w(dev, 0xee, 0x008b); |
6965 | reg_w(dev, 0x03, 0x0012); | 6565 | reg_w(dev, 0x03, 0x0012); |
6966 | /* msleep(150); */ | ||
6967 | reg_w(dev, 0x01, 0x0012); | 6566 | reg_w(dev, 0x01, 0x0012); |
6968 | reg_w(dev, 0x05, 0x0012); | 6567 | reg_w(dev, 0x05, 0x0012); |
6969 | retword = i2c_read(gspca_dev, 0x00) << 8; /* ID 0 */ | 6568 | retword = i2c_read(gspca_dev, 0x00) << 8; /* ID 0 */ |
@@ -7025,7 +6624,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
7025 | int vga = 1; /* 1: vga, 0: sif */ | 6624 | int vga = 1; /* 1: vga, 0: sif */ |
7026 | static const __u8 gamma[SENSOR_MAX] = { | 6625 | static const __u8 gamma[SENSOR_MAX] = { |
7027 | 4, /* SENSOR_ADCM2700 0 */ | 6626 | 4, /* SENSOR_ADCM2700 0 */ |
7028 | 5, /* SENSOR_CS2102 1 */ | 6627 | 4, /* SENSOR_CS2102 1 */ |
7029 | 5, /* SENSOR_CS2102K 2 */ | 6628 | 5, /* SENSOR_CS2102K 2 */ |
7030 | 4, /* SENSOR_GC0305 3 */ | 6629 | 4, /* SENSOR_GC0305 3 */ |
7031 | 4, /* SENSOR_HDCS2020b 4 */ | 6630 | 4, /* SENSOR_HDCS2020b 4 */ |
@@ -7033,15 +6632,16 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
7033 | 4, /* SENSOR_HV7131C 6 */ | 6632 | 4, /* SENSOR_HV7131C 6 */ |
7034 | 4, /* SENSOR_ICM105A 7 */ | 6633 | 4, /* SENSOR_ICM105A 7 */ |
7035 | 4, /* SENSOR_MC501CB 8 */ | 6634 | 4, /* SENSOR_MC501CB 8 */ |
7036 | 3, /* SENSOR_OV7620 9 */ | 6635 | 4, /* SENSOR_MI0360SOC 9 */ |
7037 | 4, /* SENSOR_OV7630C 10 */ | 6636 | 3, /* SENSOR_OV7620 10 */ |
7038 | 4, /* SENSOR_PAS106 11 */ | 6637 | 4, /* SENSOR_OV7630C 11 */ |
7039 | 4, /* SENSOR_PAS202B 12 */ | 6638 | 4, /* SENSOR_PAS106 12 */ |
7040 | 4, /* SENSOR_PB0330 13 */ | 6639 | 4, /* SENSOR_PAS202B 13 */ |
7041 | 4, /* SENSOR_PO2030 14 */ | 6640 | 4, /* SENSOR_PB0330 14 */ |
7042 | 4, /* SENSOR_TAS5130CK 15 */ | 6641 | 4, /* SENSOR_PO2030 15 */ |
7043 | 4, /* SENSOR_TAS5130CXX 16 */ | 6642 | 4, /* SENSOR_TAS5130CK 16 */ |
7044 | 3, /* SENSOR_TAS5130C_VF0250 17 */ | 6643 | 3, /* SENSOR_TAS5130CXX 17 */ |
6644 | 3, /* SENSOR_TAS5130C_VF0250 18 */ | ||
7045 | }; | 6645 | }; |
7046 | 6646 | ||
7047 | /* define some sensors from the vendor/product */ | 6647 | /* define some sensors from the vendor/product */ |
@@ -7103,7 +6703,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
7103 | break; | 6703 | break; |
7104 | case 0x10: | 6704 | case 0x10: |
7105 | case 0x12: | 6705 | case 0x12: |
7106 | PDEBUG(D_PROBE, "Find Sensor TAS5130"); | 6706 | PDEBUG(D_PROBE, "Find Sensor TAS5130C"); |
7107 | sd->sensor = SENSOR_TAS5130CXX; | 6707 | sd->sensor = SENSOR_TAS5130CXX; |
7108 | break; | 6708 | break; |
7109 | case 0x11: | 6709 | case 0x11: |
@@ -7112,9 +6712,9 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
7112 | break; | 6712 | break; |
7113 | case 0x13: | 6713 | case 0x13: |
7114 | PDEBUG(D_PROBE, | 6714 | PDEBUG(D_PROBE, |
7115 | "Find Sensor MI0360. Chip revision %x", | 6715 | "Find Sensor MI0360SOC. Chip revision %x", |
7116 | sd->chip_revision); | 6716 | sd->chip_revision); |
7117 | sd->sensor = SENSOR_PB0330; | 6717 | sd->sensor = SENSOR_MI0360SOC; |
7118 | break; | 6718 | break; |
7119 | case 0x14: | 6719 | case 0x14: |
7120 | PDEBUG(D_PROBE, | 6720 | PDEBUG(D_PROBE, |
@@ -7228,17 +6828,17 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
7228 | {hv7131cxx_InitialScale, hv7131cxx_Initial}, /* 6 */ | 6828 | {hv7131cxx_InitialScale, hv7131cxx_Initial}, /* 6 */ |
7229 | {icm105axx_InitialScale, icm105axx_Initial}, /* 7 */ | 6829 | {icm105axx_InitialScale, icm105axx_Initial}, /* 7 */ |
7230 | {MC501CB_InitialScale, MC501CB_Initial}, /* 8 */ | 6830 | {MC501CB_InitialScale, MC501CB_Initial}, /* 8 */ |
7231 | {OV7620_mode0, OV7620_mode1}, /* 9 */ | 6831 | {mi0360soc_Initial, mi0360soc_InitialScale}, /* 9 */ |
7232 | {ov7630c_InitialScale, ov7630c_Initial}, /* 10 */ | 6832 | {OV7620_mode0, OV7620_mode1}, /* 10 */ |
7233 | {pas106b_InitialScale, pas106b_Initial}, /* 11 */ | 6833 | {ov7630c_InitialScale, ov7630c_Initial}, /* 11 */ |
7234 | {pas202b_Initial, pas202b_InitialScale}, /* 12 */ | 6834 | {pas106b_InitialScale, pas106b_Initial}, /* 12 */ |
7235 | {pb0330xx_InitialScale, pb0330xx_Initial}, /* 13 */ | 6835 | {pas202b_Initial, pas202b_InitialScale}, /* 13 */ |
7236 | /* or {pb03303x_InitialScale, pb03303x_Initial}, */ | 6836 | {pb0330_Initial, pb0330_InitialScale}, /* 14 */ |
7237 | {PO2030_mode0, PO2030_mode1}, /* 14 */ | 6837 | {PO2030_mode0, PO2030_mode1}, /* 15 */ |
7238 | {tas5130CK_InitialScale, tas5130CK_Initial}, /* 15 */ | 6838 | {tas5130CK_InitialScale, tas5130CK_Initial}, /* 16 */ |
7239 | {tas5130cxx_InitialScale, tas5130cxx_Initial}, /* 16 */ | 6839 | {tas5130cxx_Initial, tas5130cxx_InitialScale}, /* 17 */ |
7240 | {tas5130c_vf0250_InitialScale, tas5130c_vf0250_Initial}, | 6840 | {tas5130c_vf0250_InitialScale, tas5130c_vf0250_Initial}, |
7241 | /* 17 */ | 6841 | /* 18 */ |
7242 | }; | 6842 | }; |
7243 | 6843 | ||
7244 | /* create the JPEG header */ | 6844 | /* create the JPEG header */ |
@@ -7258,19 +6858,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
7258 | case SENSOR_PAS106: | 6858 | case SENSOR_PAS106: |
7259 | usb_exchange(gspca_dev, pas106b_Initial_com); | 6859 | usb_exchange(gspca_dev, pas106b_Initial_com); |
7260 | break; | 6860 | break; |
7261 | case SENSOR_PB0330: | ||
7262 | if (mode) { | ||
7263 | if (sd->chip_revision == 0xc001 | ||
7264 | || sd->chip_revision == 0xe001 | ||
7265 | || sd->chip_revision == 0x8001) | ||
7266 | zc3_init = pb03303x_Initial; | ||
7267 | } else { | ||
7268 | if (sd->chip_revision == 0xc001 | ||
7269 | || sd->chip_revision == 0xe001 | ||
7270 | || sd->chip_revision == 0x8001) | ||
7271 | zc3_init = pb03303x_InitialScale; | ||
7272 | } | ||
7273 | break; | ||
7274 | } | 6861 | } |
7275 | usb_exchange(gspca_dev, zc3_init); | 6862 | usb_exchange(gspca_dev, zc3_init); |
7276 | 6863 | ||
@@ -7310,10 +6897,8 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
7310 | 6897 | ||
7311 | /* set the gamma tables when not set */ | 6898 | /* set the gamma tables when not set */ |
7312 | switch (sd->sensor) { | 6899 | switch (sd->sensor) { |
7313 | case SENSOR_CS2102: /* gamma set in xxx_Initial */ | 6900 | case SENSOR_CS2102K: /* gamma set in xxx_Initial */ |
7314 | case SENSOR_CS2102K: | ||
7315 | case SENSOR_HDCS2020b: | 6901 | case SENSOR_HDCS2020b: |
7316 | case SENSOR_PB0330: /* pb with chip_revision - see above */ | ||
7317 | case SENSOR_OV7630C: | 6902 | case SENSOR_OV7630C: |
7318 | case SENSOR_TAS5130CK: | 6903 | case SENSOR_TAS5130CK: |
7319 | break; | 6904 | break; |
@@ -7365,7 +6950,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
7365 | setautogain(gspca_dev); | 6950 | setautogain(gspca_dev); |
7366 | switch (sd->sensor) { | 6951 | switch (sd->sensor) { |
7367 | case SENSOR_PO2030: | 6952 | case SENSOR_PO2030: |
7368 | msleep(500); | 6953 | msleep(50); |
7369 | reg_r(gspca_dev, 0x0008); | 6954 | reg_r(gspca_dev, 0x0008); |
7370 | reg_r(gspca_dev, 0x0007); | 6955 | reg_r(gspca_dev, 0x0007); |
7371 | /*fall thru*/ | 6956 | /*fall thru*/ |
@@ -7389,17 +6974,16 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
7389 | } | 6974 | } |
7390 | 6975 | ||
7391 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 6976 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
7392 | struct gspca_frame *frame, | 6977 | u8 *data, |
7393 | __u8 *data, | ||
7394 | int len) | 6978 | int len) |
7395 | { | 6979 | { |
7396 | struct sd *sd = (struct sd *) gspca_dev; | 6980 | struct sd *sd = (struct sd *) gspca_dev; |
7397 | 6981 | ||
7398 | if (data[0] == 0xff && data[1] == 0xd8) { /* start of frame */ | 6982 | if (data[0] == 0xff && data[1] == 0xd8) { /* start of frame */ |
7399 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | 6983 | gspca_frame_add(gspca_dev, LAST_PACKET, |
7400 | data, 0); | 6984 | NULL, 0); |
7401 | /* put the JPEG header in the new frame */ | 6985 | /* put the JPEG header in the new frame */ |
7402 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | 6986 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
7403 | sd->jpeg_hdr, JPEG_HDR_SZ); | 6987 | sd->jpeg_hdr, JPEG_HDR_SZ); |
7404 | 6988 | ||
7405 | /* remove the webcam's header: | 6989 | /* remove the webcam's header: |
@@ -7411,7 +6995,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
7411 | data += 18; | 6995 | data += 18; |
7412 | len -= 18; | 6996 | len -= 18; |
7413 | } | 6997 | } |
7414 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | 6998 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
7415 | } | 6999 | } |
7416 | 7000 | ||
7417 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 7001 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) |
diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index 2eb9dc2ebe59..b5439cabb381 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c | |||
@@ -139,7 +139,7 @@ int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count) | |||
139 | urb = usb_alloc_urb(0, GFP_KERNEL); | 139 | urb = usb_alloc_urb(0, GFP_KERNEL); |
140 | if (!urb) { | 140 | if (!urb) { |
141 | v4l2_err(&dev->v4l2_dev, "cannot allocate urb\n"); | 141 | v4l2_err(&dev->v4l2_dev, "cannot allocate urb\n"); |
142 | goto exit; | 142 | goto exit_urb; |
143 | } | 143 | } |
144 | buf->urb = urb; | 144 | buf->urb = urb; |
145 | 145 | ||
@@ -148,7 +148,7 @@ int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count) | |||
148 | if (!mem) { | 148 | if (!mem) { |
149 | v4l2_err(&dev->v4l2_dev, | 149 | v4l2_err(&dev->v4l2_dev, |
150 | "cannot allocate usb transfer buffer\n"); | 150 | "cannot allocate usb transfer buffer\n"); |
151 | goto exit; | 151 | goto exit_urb_buffer; |
152 | } | 152 | } |
153 | 153 | ||
154 | usb_fill_bulk_urb(buf->urb, dev->udev, | 154 | usb_fill_bulk_urb(buf->urb, dev->udev, |
@@ -161,6 +161,10 @@ int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count) | |||
161 | list_add_tail(&buf->buff_list, &dev->free_buff_list); | 161 | list_add_tail(&buf->buff_list, &dev->free_buff_list); |
162 | } | 162 | } |
163 | return 0; | 163 | return 0; |
164 | exit_urb_buffer: | ||
165 | usb_free_urb(urb); | ||
166 | exit_urb: | ||
167 | kfree(buf); | ||
164 | exit: | 168 | exit: |
165 | hdpvr_free_buffers(dev); | 169 | hdpvr_free_buffers(dev); |
166 | return retval; | 170 | return retval; |
diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c index 71c211402eb5..60d992ee2589 100644 --- a/drivers/media/video/hexium_gemini.c +++ b/drivers/media/video/hexium_gemini.c | |||
@@ -251,7 +251,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) | |||
251 | 251 | ||
252 | DEB_EE(("VIDIOC_S_INPUT %d.\n", input)); | 252 | DEB_EE(("VIDIOC_S_INPUT %d.\n", input)); |
253 | 253 | ||
254 | if (input < 0 || input >= HEXIUM_INPUTS) | 254 | if (input >= HEXIUM_INPUTS) |
255 | return -EINVAL; | 255 | return -EINVAL; |
256 | 256 | ||
257 | hexium->cur_input = input; | 257 | hexium->cur_input = input; |
diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c index 39d65ca41c62..938a1f8f880a 100644 --- a/drivers/media/video/hexium_orion.c +++ b/drivers/media/video/hexium_orion.c | |||
@@ -350,7 +350,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) | |||
350 | struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; | 350 | struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; |
351 | struct hexium *hexium = (struct hexium *) dev->ext_priv; | 351 | struct hexium *hexium = (struct hexium *) dev->ext_priv; |
352 | 352 | ||
353 | if (input < 0 || input >= HEXIUM_INPUTS) | 353 | if (input >= HEXIUM_INPUTS) |
354 | return -EINVAL; | 354 | return -EINVAL; |
355 | 355 | ||
356 | hexium->cur_input = input; | 356 | hexium->cur_input = input; |
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 247d3115a9b7..64360d26b32d 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c | |||
@@ -275,7 +275,7 @@ static void ir_key_poll(struct IR_i2c *ir) | |||
275 | if (0 == rc) { | 275 | if (0 == rc) { |
276 | ir_input_nokey(ir->input, &ir->ir); | 276 | ir_input_nokey(ir->input, &ir->ir); |
277 | } else { | 277 | } else { |
278 | ir_input_keydown(ir->input, &ir->ir, ir_key, ir_raw); | 278 | ir_input_keydown(ir->input, &ir->ir, ir_key); |
279 | } | 279 | } |
280 | } | 280 | } |
281 | 281 | ||
@@ -299,7 +299,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
299 | { | 299 | { |
300 | struct ir_scancode_table *ir_codes = NULL; | 300 | struct ir_scancode_table *ir_codes = NULL; |
301 | const char *name = NULL; | 301 | const char *name = NULL; |
302 | int ir_type; | 302 | int ir_type = 0; |
303 | struct IR_i2c *ir; | 303 | struct IR_i2c *ir; |
304 | struct input_dev *input_dev; | 304 | struct input_dev *input_dev; |
305 | struct i2c_adapter *adap = client->adapter; | 305 | struct i2c_adapter *adap = client->adapter; |
@@ -353,10 +353,8 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
353 | ir_type = IR_TYPE_RC5; | 353 | ir_type = IR_TYPE_RC5; |
354 | ir_codes = &ir_codes_fusionhdtv_mce_table; | 354 | ir_codes = &ir_codes_fusionhdtv_mce_table; |
355 | break; | 355 | break; |
356 | case 0x7a: | ||
357 | case 0x47: | 356 | case 0x47: |
358 | case 0x71: | 357 | case 0x71: |
359 | case 0x2d: | ||
360 | if (adap->id == I2C_HW_B_CX2388x || | 358 | if (adap->id == I2C_HW_B_CX2388x || |
361 | adap->id == I2C_HW_B_CX2341X) { | 359 | adap->id == I2C_HW_B_CX2341X) { |
362 | /* Handled by cx88-input */ | 360 | /* Handled by cx88-input */ |
@@ -381,10 +379,6 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
381 | ir_type = IR_TYPE_OTHER; | 379 | ir_type = IR_TYPE_OTHER; |
382 | ir_codes = &ir_codes_avermedia_cardbus_table; | 380 | ir_codes = &ir_codes_avermedia_cardbus_table; |
383 | break; | 381 | break; |
384 | default: | ||
385 | dprintk(1, DEVNAME ": Unsupported i2c address 0x%02x\n", addr); | ||
386 | err = -ENODEV; | ||
387 | goto err_out_free; | ||
388 | } | 382 | } |
389 | 383 | ||
390 | /* Let the caller override settings */ | 384 | /* Let the caller override settings */ |
@@ -427,7 +421,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
427 | } | 421 | } |
428 | 422 | ||
429 | /* Make sure we are all setup before going on */ | 423 | /* Make sure we are all setup before going on */ |
430 | if (!name || !ir->get_key || !ir_codes) { | 424 | if (!name || !ir->get_key || !ir_type || !ir_codes) { |
431 | dprintk(1, DEVNAME ": Unsupported device at address 0x%02x\n", | 425 | dprintk(1, DEVNAME ": Unsupported device at address 0x%02x\n", |
432 | addr); | 426 | addr); |
433 | err = -ENODEV; | 427 | err = -ENODEV; |
@@ -443,7 +437,10 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
443 | dev_name(&client->dev)); | 437 | dev_name(&client->dev)); |
444 | 438 | ||
445 | /* init + register input device */ | 439 | /* init + register input device */ |
446 | ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes); | 440 | err = ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes); |
441 | if (err < 0) | ||
442 | goto err_out_free; | ||
443 | |||
447 | input_dev->id.bustype = BUS_I2C; | 444 | input_dev->id.bustype = BUS_I2C; |
448 | input_dev->name = ir->name; | 445 | input_dev->name = ir->name; |
449 | input_dev->phys = ir->phys; | 446 | input_dev->phys = ir->phys; |
@@ -462,6 +459,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
462 | return 0; | 459 | return 0; |
463 | 460 | ||
464 | err_out_free: | 461 | err_out_free: |
462 | ir_input_free(input_dev); | ||
465 | input_free_device(input_dev); | 463 | input_free_device(input_dev); |
466 | kfree(ir); | 464 | kfree(ir); |
467 | return err; | 465 | return err; |
@@ -475,6 +473,7 @@ static int ir_remove(struct i2c_client *client) | |||
475 | cancel_delayed_work_sync(&ir->work); | 473 | cancel_delayed_work_sync(&ir->work); |
476 | 474 | ||
477 | /* unregister device */ | 475 | /* unregister device */ |
476 | ir_input_free(ir->input); | ||
478 | input_unregister_device(ir->input); | 477 | input_unregister_device(ir->input); |
479 | 478 | ||
480 | /* free memory */ | 479 | /* free memory */ |
diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c index 4873b6ca5801..79d0fe4990d6 100644 --- a/drivers/media/video/ivtv/ivtv-cards.c +++ b/drivers/media/video/ivtv/ivtv-cards.c | |||
@@ -136,7 +136,8 @@ static const struct ivtv_card ivtv_card_pvr350 = { | |||
136 | .hw_audio = IVTV_HW_MSP34XX, | 136 | .hw_audio = IVTV_HW_MSP34XX, |
137 | .hw_audio_ctrl = IVTV_HW_MSP34XX, | 137 | .hw_audio_ctrl = IVTV_HW_MSP34XX, |
138 | .hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7115 | | 138 | .hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7115 | |
139 | IVTV_HW_SAA7127 | IVTV_HW_TVEEPROM | IVTV_HW_TUNER, | 139 | IVTV_HW_SAA7127 | IVTV_HW_TVEEPROM | IVTV_HW_TUNER | |
140 | IVTV_HW_I2C_IR_RX_HAUP_EXT | IVTV_HW_I2C_IR_RX_HAUP_INT, | ||
140 | .video_inputs = { | 141 | .video_inputs = { |
141 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, | 142 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, |
142 | { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, | 143 | { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, |
@@ -199,7 +200,9 @@ static const struct ivtv_card ivtv_card_pvr150 = { | |||
199 | .hw_audio_ctrl = IVTV_HW_CX25840, | 200 | .hw_audio_ctrl = IVTV_HW_CX25840, |
200 | .hw_muxer = IVTV_HW_WM8775, | 201 | .hw_muxer = IVTV_HW_WM8775, |
201 | .hw_all = IVTV_HW_WM8775 | IVTV_HW_CX25840 | | 202 | .hw_all = IVTV_HW_WM8775 | IVTV_HW_CX25840 | |
202 | IVTV_HW_TVEEPROM | IVTV_HW_TUNER, | 203 | IVTV_HW_TVEEPROM | IVTV_HW_TUNER | |
204 | IVTV_HW_I2C_IR_RX_HAUP_EXT | IVTV_HW_I2C_IR_RX_HAUP_INT | | ||
205 | IVTV_HW_Z8F0811_IR_HAUP, | ||
203 | .video_inputs = { | 206 | .video_inputs = { |
204 | { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE7 }, | 207 | { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE7 }, |
205 | { IVTV_CARD_INPUT_SVIDEO1, 1, CX25840_SVIDEO1 }, | 208 | { IVTV_CARD_INPUT_SVIDEO1, 1, CX25840_SVIDEO1 }, |
@@ -955,7 +958,8 @@ static const struct ivtv_card ivtv_card_avertv_mce116 = { | |||
955 | .hw_video = IVTV_HW_CX25840, | 958 | .hw_video = IVTV_HW_CX25840, |
956 | .hw_audio = IVTV_HW_CX25840, | 959 | .hw_audio = IVTV_HW_CX25840, |
957 | .hw_audio_ctrl = IVTV_HW_CX25840, | 960 | .hw_audio_ctrl = IVTV_HW_CX25840, |
958 | .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | IVTV_HW_WM8739, | 961 | .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | IVTV_HW_WM8739 | |
962 | IVTV_HW_I2C_IR_RX_AVER, | ||
959 | .video_inputs = { | 963 | .video_inputs = { |
960 | { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 }, | 964 | { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 }, |
961 | { IVTV_CARD_INPUT_SVIDEO1, 1, CX25840_SVIDEO3 }, | 965 | { IVTV_CARD_INPUT_SVIDEO1, 1, CX25840_SVIDEO3 }, |
@@ -965,6 +969,7 @@ static const struct ivtv_card ivtv_card_avertv_mce116 = { | |||
965 | { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 }, | 969 | { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 }, |
966 | { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 }, | 970 | { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 }, |
967 | }, | 971 | }, |
972 | .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 }, | ||
968 | /* enable line-in */ | 973 | /* enable line-in */ |
969 | .gpio_init = { .direction = 0xe000, .initial_value = 0x4000 }, | 974 | .gpio_init = { .direction = 0xe000, .initial_value = 0x4000 }, |
970 | .xceive_pin = 10, | 975 | .xceive_pin = 10, |
@@ -1025,13 +1030,15 @@ static const struct ivtv_card ivtv_card_aver_pvr150 = { | |||
1025 | /* AVerMedia UltraTV 1500 MCE (newer non-cx88 version, M113 variant) card */ | 1030 | /* AVerMedia UltraTV 1500 MCE (newer non-cx88 version, M113 variant) card */ |
1026 | 1031 | ||
1027 | static const struct ivtv_card_pci_info ivtv_pci_aver_ultra1500mce[] = { | 1032 | static const struct ivtv_card_pci_info ivtv_pci_aver_ultra1500mce[] = { |
1028 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc019 }, | 1033 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc019 }, /* NTSC */ |
1034 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc01b }, /* PAL/SECAM */ | ||
1029 | { 0, 0, 0 } | 1035 | { 0, 0, 0 } |
1030 | }; | 1036 | }; |
1031 | 1037 | ||
1032 | static const struct ivtv_card ivtv_card_aver_ultra1500mce = { | 1038 | static const struct ivtv_card ivtv_card_aver_ultra1500mce = { |
1033 | .type = IVTV_CARD_AVER_ULTRA1500MCE, | 1039 | .type = IVTV_CARD_AVER_ULTRA1500MCE, |
1034 | .name = "AVerMedia UltraTV 1500 MCE / AVerTV M113 Philips Tuner", | 1040 | .name = "AVerMedia UltraTV 1500 MCE / AVerTV M113 Philips Tuner", |
1041 | .comment = "For non-NTSC tuners, use the pal= or secam= module options", | ||
1035 | .v4l2_capabilities = IVTV_CAP_ENCODER, | 1042 | .v4l2_capabilities = IVTV_CAP_ENCODER, |
1036 | .hw_video = IVTV_HW_CX25840, | 1043 | .hw_video = IVTV_HW_CX25840, |
1037 | .hw_audio = IVTV_HW_CX25840, | 1044 | .hw_audio = IVTV_HW_CX25840, |
@@ -1058,6 +1065,7 @@ static const struct ivtv_card ivtv_card_aver_ultra1500mce = { | |||
1058 | .tuners = { | 1065 | .tuners = { |
1059 | /* The UltraTV 1500 MCE has a Philips FM1236 MK5 TV/FM tuner */ | 1066 | /* The UltraTV 1500 MCE has a Philips FM1236 MK5 TV/FM tuner */ |
1060 | { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FM1236_MK3 }, | 1067 | { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FM1236_MK3 }, |
1068 | { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216MK5 }, | ||
1061 | }, | 1069 | }, |
1062 | .pci_list = ivtv_pci_aver_ultra1500mce, | 1070 | .pci_list = ivtv_pci_aver_ultra1500mce, |
1063 | .i2c = &ivtv_i2c_std, | 1071 | .i2c = &ivtv_i2c_std, |
diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h index e99a0a255578..6148827ec885 100644 --- a/drivers/media/video/ivtv/ivtv-cards.h +++ b/drivers/media/video/ivtv/ivtv-cards.h | |||
@@ -87,26 +87,43 @@ | |||
87 | #define IVTV_PCI_ID_GOTVIEW1 0xffac | 87 | #define IVTV_PCI_ID_GOTVIEW1 0xffac |
88 | #define IVTV_PCI_ID_GOTVIEW2 0xffad | 88 | #define IVTV_PCI_ID_GOTVIEW2 0xffad |
89 | 89 | ||
90 | /* hardware flags, no gaps allowed, IVTV_HW_GPIO must always be last */ | 90 | /* hardware flags, no gaps allowed */ |
91 | #define IVTV_HW_CX25840 (1 << 0) | 91 | #define IVTV_HW_CX25840 (1 << 0) |
92 | #define IVTV_HW_SAA7115 (1 << 1) | 92 | #define IVTV_HW_SAA7115 (1 << 1) |
93 | #define IVTV_HW_SAA7127 (1 << 2) | 93 | #define IVTV_HW_SAA7127 (1 << 2) |
94 | #define IVTV_HW_MSP34XX (1 << 3) | 94 | #define IVTV_HW_MSP34XX (1 << 3) |
95 | #define IVTV_HW_TUNER (1 << 4) | 95 | #define IVTV_HW_TUNER (1 << 4) |
96 | #define IVTV_HW_WM8775 (1 << 5) | 96 | #define IVTV_HW_WM8775 (1 << 5) |
97 | #define IVTV_HW_CS53L32A (1 << 6) | 97 | #define IVTV_HW_CS53L32A (1 << 6) |
98 | #define IVTV_HW_TVEEPROM (1 << 7) | 98 | #define IVTV_HW_TVEEPROM (1 << 7) |
99 | #define IVTV_HW_SAA7114 (1 << 8) | 99 | #define IVTV_HW_SAA7114 (1 << 8) |
100 | #define IVTV_HW_UPD64031A (1 << 9) | 100 | #define IVTV_HW_UPD64031A (1 << 9) |
101 | #define IVTV_HW_UPD6408X (1 << 10) | 101 | #define IVTV_HW_UPD6408X (1 << 10) |
102 | #define IVTV_HW_SAA717X (1 << 11) | 102 | #define IVTV_HW_SAA717X (1 << 11) |
103 | #define IVTV_HW_WM8739 (1 << 12) | 103 | #define IVTV_HW_WM8739 (1 << 12) |
104 | #define IVTV_HW_VP27SMPX (1 << 13) | 104 | #define IVTV_HW_VP27SMPX (1 << 13) |
105 | #define IVTV_HW_M52790 (1 << 14) | 105 | #define IVTV_HW_M52790 (1 << 14) |
106 | #define IVTV_HW_GPIO (1 << 15) | 106 | #define IVTV_HW_GPIO (1 << 15) |
107 | #define IVTV_HW_I2C_IR_RX_AVER (1 << 16) | ||
108 | #define IVTV_HW_I2C_IR_RX_HAUP_EXT (1 << 17) /* External before internal */ | ||
109 | #define IVTV_HW_I2C_IR_RX_HAUP_INT (1 << 18) | ||
110 | #define IVTV_HW_Z8F0811_IR_TX_HAUP (1 << 19) | ||
111 | #define IVTV_HW_Z8F0811_IR_RX_HAUP (1 << 20) | ||
112 | |||
113 | #define IVTV_HW_Z8F0811_IR_HAUP (IVTV_HW_Z8F0811_IR_RX_HAUP | \ | ||
114 | IVTV_HW_Z8F0811_IR_TX_HAUP) | ||
107 | 115 | ||
108 | #define IVTV_HW_SAA711X (IVTV_HW_SAA7115 | IVTV_HW_SAA7114) | 116 | #define IVTV_HW_SAA711X (IVTV_HW_SAA7115 | IVTV_HW_SAA7114) |
109 | 117 | ||
118 | #define IVTV_HW_IR_RX_ANY (IVTV_HW_I2C_IR_RX_AVER | \ | ||
119 | IVTV_HW_I2C_IR_RX_HAUP_EXT | \ | ||
120 | IVTV_HW_I2C_IR_RX_HAUP_INT | \ | ||
121 | IVTV_HW_Z8F0811_IR_RX_HAUP) | ||
122 | |||
123 | #define IVTV_HW_IR_TX_ANY (IVTV_HW_Z8F0811_IR_TX_HAUP) | ||
124 | |||
125 | #define IVTV_HW_IR_ANY (IVTV_HW_IR_RX_ANY | IVTV_HW_IR_TX_ANY) | ||
126 | |||
110 | /* video inputs */ | 127 | /* video inputs */ |
111 | #define IVTV_CARD_INPUT_VID_TUNER 1 | 128 | #define IVTV_CARD_INPUT_VID_TUNER 1 |
112 | #define IVTV_CARD_INPUT_SVIDEO1 2 | 129 | #define IVTV_CARD_INPUT_SVIDEO1 2 |
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 7cdbc1a8f218..347c3344f56d 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c | |||
@@ -91,10 +91,15 @@ static int radio[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, | |||
91 | -1, -1, -1, -1, -1, -1, -1, -1, | 91 | -1, -1, -1, -1, -1, -1, -1, -1, |
92 | -1, -1, -1, -1, -1, -1, -1, -1, | 92 | -1, -1, -1, -1, -1, -1, -1, -1, |
93 | -1, -1, -1, -1, -1, -1, -1, -1 }; | 93 | -1, -1, -1, -1, -1, -1, -1, -1 }; |
94 | static int i2c_clock_period[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, | ||
95 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
96 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
97 | -1, -1, -1, -1, -1, -1, -1, -1 }; | ||
94 | 98 | ||
95 | static unsigned int cardtype_c = 1; | 99 | static unsigned int cardtype_c = 1; |
96 | static unsigned int tuner_c = 1; | 100 | static unsigned int tuner_c = 1; |
97 | static unsigned int radio_c = 1; | 101 | static unsigned int radio_c = 1; |
102 | static unsigned int i2c_clock_period_c = 1; | ||
98 | static char pal[] = "---"; | 103 | static char pal[] = "---"; |
99 | static char secam[] = "--"; | 104 | static char secam[] = "--"; |
100 | static char ntsc[] = "-"; | 105 | static char ntsc[] = "-"; |
@@ -151,6 +156,7 @@ module_param(dec_vbi_buffers, int, 0644); | |||
151 | 156 | ||
152 | module_param(tunertype, int, 0644); | 157 | module_param(tunertype, int, 0644); |
153 | module_param(newi2c, int, 0644); | 158 | module_param(newi2c, int, 0644); |
159 | module_param_array(i2c_clock_period, int, &i2c_clock_period_c, 0644); | ||
154 | 160 | ||
155 | MODULE_PARM_DESC(tuner, "Tuner type selection,\n" | 161 | MODULE_PARM_DESC(tuner, "Tuner type selection,\n" |
156 | "\t\t\tsee tuner.h for values"); | 162 | "\t\t\tsee tuner.h for values"); |
@@ -245,6 +251,10 @@ MODULE_PARM_DESC(newi2c, | |||
245 | "Use new I2C implementation\n" | 251 | "Use new I2C implementation\n" |
246 | "\t\t\t-1 is autodetect, 0 is off, 1 is on\n" | 252 | "\t\t\t-1 is autodetect, 0 is off, 1 is on\n" |
247 | "\t\t\tDefault is autodetect"); | 253 | "\t\t\tDefault is autodetect"); |
254 | MODULE_PARM_DESC(i2c_clock_period, | ||
255 | "Period of SCL for the I2C bus controlled by the CX23415/6\n" | ||
256 | "\t\t\tMin: 10 usec (100 kHz), Max: 4500 usec (222 Hz)\n" | ||
257 | "\t\t\tDefault: " __stringify(IVTV_DEFAULT_I2C_CLOCK_PERIOD)); | ||
248 | 258 | ||
249 | MODULE_PARM_DESC(ivtv_first_minor, "Set device node number assigned to first card"); | 259 | MODULE_PARM_DESC(ivtv_first_minor, "Set device node number assigned to first card"); |
250 | 260 | ||
@@ -600,6 +610,15 @@ static void ivtv_process_options(struct ivtv *itv) | |||
600 | itv->options.cardtype = cardtype[itv->instance]; | 610 | itv->options.cardtype = cardtype[itv->instance]; |
601 | itv->options.tuner = tuner[itv->instance]; | 611 | itv->options.tuner = tuner[itv->instance]; |
602 | itv->options.radio = radio[itv->instance]; | 612 | itv->options.radio = radio[itv->instance]; |
613 | |||
614 | itv->options.i2c_clock_period = i2c_clock_period[itv->instance]; | ||
615 | if (itv->options.i2c_clock_period == -1) | ||
616 | itv->options.i2c_clock_period = IVTV_DEFAULT_I2C_CLOCK_PERIOD; | ||
617 | else if (itv->options.i2c_clock_period < 10) | ||
618 | itv->options.i2c_clock_period = 10; | ||
619 | else if (itv->options.i2c_clock_period > 4500) | ||
620 | itv->options.i2c_clock_period = 4500; | ||
621 | |||
603 | itv->options.newi2c = newi2c; | 622 | itv->options.newi2c = newi2c; |
604 | if (tunertype < -1 || tunertype > 1) { | 623 | if (tunertype < -1 || tunertype > 1) { |
605 | IVTV_WARN("Invalid tunertype argument, will autodetect instead\n"); | 624 | IVTV_WARN("Invalid tunertype argument, will autodetect instead\n"); |
@@ -865,6 +884,10 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) | |||
865 | itv->hw_flags |= device; | 884 | itv->hw_flags |= device; |
866 | } | 885 | } |
867 | 886 | ||
887 | /* probe for legacy IR controllers that aren't in card definitions */ | ||
888 | if ((itv->hw_flags & IVTV_HW_IR_ANY) == 0) | ||
889 | ivtv_i2c_new_ir_legacy(itv); | ||
890 | |||
868 | if (itv->card->hw_all & IVTV_HW_CX25840) | 891 | if (itv->card->hw_all & IVTV_HW_CX25840) |
869 | itv->sd_video = ivtv_find_hw(itv, IVTV_HW_CX25840); | 892 | itv->sd_video = ivtv_find_hw(itv, IVTV_HW_CX25840); |
870 | else if (itv->card->hw_all & IVTV_HW_SAA717X) | 893 | else if (itv->card->hw_all & IVTV_HW_SAA717X) |
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 440f7328a7ed..e4816da6482b 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h | |||
@@ -64,6 +64,7 @@ | |||
64 | #include <media/v4l2-device.h> | 64 | #include <media/v4l2-device.h> |
65 | #include <media/tuner.h> | 65 | #include <media/tuner.h> |
66 | #include <media/cx2341x.h> | 66 | #include <media/cx2341x.h> |
67 | #include <media/ir-kbd-i2c.h> | ||
67 | 68 | ||
68 | #include <linux/ivtv.h> | 69 | #include <linux/ivtv.h> |
69 | 70 | ||
@@ -176,12 +177,16 @@ extern int ivtv_debug; | |||
176 | 177 | ||
177 | #define IVTV_MAX_PGM_INDEX (400) | 178 | #define IVTV_MAX_PGM_INDEX (400) |
178 | 179 | ||
180 | /* Default I2C SCL period in microseconds */ | ||
181 | #define IVTV_DEFAULT_I2C_CLOCK_PERIOD 20 | ||
182 | |||
179 | struct ivtv_options { | 183 | struct ivtv_options { |
180 | int kilobytes[IVTV_MAX_STREAMS]; /* size in kilobytes of each stream */ | 184 | int kilobytes[IVTV_MAX_STREAMS]; /* size in kilobytes of each stream */ |
181 | int cardtype; /* force card type on load */ | 185 | int cardtype; /* force card type on load */ |
182 | int tuner; /* set tuner on load */ | 186 | int tuner; /* set tuner on load */ |
183 | int radio; /* enable/disable radio */ | 187 | int radio; /* enable/disable radio */ |
184 | int newi2c; /* new I2C algorithm */ | 188 | int newi2c; /* new I2C algorithm */ |
189 | int i2c_clock_period; /* period of SCL for I2C bus */ | ||
185 | }; | 190 | }; |
186 | 191 | ||
187 | /* ivtv-specific mailbox template */ | 192 | /* ivtv-specific mailbox template */ |
@@ -677,6 +682,7 @@ struct ivtv { | |||
677 | int i2c_state; /* i2c bit state */ | 682 | int i2c_state; /* i2c bit state */ |
678 | struct mutex i2c_bus_lock; /* lock i2c bus */ | 683 | struct mutex i2c_bus_lock; /* lock i2c bus */ |
679 | 684 | ||
685 | struct IR_i2c_init_data ir_i2c_init_data; | ||
680 | 686 | ||
681 | /* Program Index information */ | 687 | /* Program Index information */ |
682 | u32 pgm_info_offset; /* start of pgm info in encoder memory */ | 688 | u32 pgm_info_offset; /* start of pgm info in encoder memory */ |
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index b9c71e61f7d6..2ee03c2a1b58 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c | |||
@@ -88,6 +88,11 @@ | |||
88 | #define IVTV_UPD64083_I2C_ADDR 0x5c | 88 | #define IVTV_UPD64083_I2C_ADDR 0x5c |
89 | #define IVTV_VP27SMPX_I2C_ADDR 0x5b | 89 | #define IVTV_VP27SMPX_I2C_ADDR 0x5b |
90 | #define IVTV_M52790_I2C_ADDR 0x48 | 90 | #define IVTV_M52790_I2C_ADDR 0x48 |
91 | #define IVTV_AVERMEDIA_IR_RX_I2C_ADDR 0x40 | ||
92 | #define IVTV_HAUP_EXT_IR_RX_I2C_ADDR 0x1a | ||
93 | #define IVTV_HAUP_INT_IR_RX_I2C_ADDR 0x18 | ||
94 | #define IVTV_Z8F0811_IR_TX_I2C_ADDR 0x70 | ||
95 | #define IVTV_Z8F0811_IR_RX_I2C_ADDR 0x71 | ||
91 | 96 | ||
92 | /* This array should match the IVTV_HW_ defines */ | 97 | /* This array should match the IVTV_HW_ defines */ |
93 | static const u8 hw_addrs[] = { | 98 | static const u8 hw_addrs[] = { |
@@ -106,7 +111,12 @@ static const u8 hw_addrs[] = { | |||
106 | IVTV_WM8739_I2C_ADDR, | 111 | IVTV_WM8739_I2C_ADDR, |
107 | IVTV_VP27SMPX_I2C_ADDR, | 112 | IVTV_VP27SMPX_I2C_ADDR, |
108 | IVTV_M52790_I2C_ADDR, | 113 | IVTV_M52790_I2C_ADDR, |
109 | 0 /* IVTV_HW_GPIO dummy driver ID */ | 114 | 0, /* IVTV_HW_GPIO dummy driver ID */ |
115 | IVTV_AVERMEDIA_IR_RX_I2C_ADDR, /* IVTV_HW_I2C_IR_RX_AVER */ | ||
116 | IVTV_HAUP_EXT_IR_RX_I2C_ADDR, /* IVTV_HW_I2C_IR_RX_HAUP_EXT */ | ||
117 | IVTV_HAUP_INT_IR_RX_I2C_ADDR, /* IVTV_HW_I2C_IR_RX_HAUP_INT */ | ||
118 | IVTV_Z8F0811_IR_TX_I2C_ADDR, /* IVTV_HW_Z8F0811_IR_TX_HAUP */ | ||
119 | IVTV_Z8F0811_IR_RX_I2C_ADDR, /* IVTV_HW_Z8F0811_IR_RX_HAUP */ | ||
110 | }; | 120 | }; |
111 | 121 | ||
112 | /* This array should match the IVTV_HW_ defines */ | 122 | /* This array should match the IVTV_HW_ defines */ |
@@ -126,7 +136,12 @@ static const char *hw_modules[] = { | |||
126 | "wm8739", | 136 | "wm8739", |
127 | "vp27smpx", | 137 | "vp27smpx", |
128 | "m52790", | 138 | "m52790", |
129 | NULL | 139 | NULL, |
140 | NULL, /* IVTV_HW_I2C_IR_RX_AVER */ | ||
141 | NULL, /* IVTV_HW_I2C_IR_RX_HAUP_EXT */ | ||
142 | NULL, /* IVTV_HW_I2C_IR_RX_HAUP_INT */ | ||
143 | NULL, /* IVTV_HW_Z8F0811_IR_TX_HAUP */ | ||
144 | NULL, /* IVTV_HW_Z8F0811_IR_RX_HAUP */ | ||
130 | }; | 145 | }; |
131 | 146 | ||
132 | /* This array should match the IVTV_HW_ defines */ | 147 | /* This array should match the IVTV_HW_ defines */ |
@@ -147,8 +162,95 @@ static const char * const hw_devicenames[] = { | |||
147 | "vp27smpx", | 162 | "vp27smpx", |
148 | "m52790", | 163 | "m52790", |
149 | "gpio", | 164 | "gpio", |
165 | "ir_video", /* IVTV_HW_I2C_IR_RX_AVER */ | ||
166 | "ir_video", /* IVTV_HW_I2C_IR_RX_HAUP_EXT */ | ||
167 | "ir_video", /* IVTV_HW_I2C_IR_RX_HAUP_INT */ | ||
168 | "ir_tx_z8f0811_haup", /* IVTV_HW_Z8F0811_IR_TX_HAUP */ | ||
169 | "ir_rx_z8f0811_haup", /* IVTV_HW_Z8F0811_IR_RX_HAUP */ | ||
150 | }; | 170 | }; |
151 | 171 | ||
172 | static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) | ||
173 | { | ||
174 | struct i2c_board_info info; | ||
175 | struct i2c_adapter *adap = &itv->i2c_adap; | ||
176 | struct IR_i2c_init_data *init_data = &itv->ir_i2c_init_data; | ||
177 | unsigned short addr_list[2] = { addr, I2C_CLIENT_END }; | ||
178 | |||
179 | /* Only allow one IR transmitter to be registered per board */ | ||
180 | if (hw & IVTV_HW_IR_TX_ANY) { | ||
181 | if (itv->hw_flags & IVTV_HW_IR_TX_ANY) | ||
182 | return -1; | ||
183 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
184 | strlcpy(info.type, type, I2C_NAME_SIZE); | ||
185 | return i2c_new_probed_device(adap, &info, addr_list) == NULL | ||
186 | ? -1 : 0; | ||
187 | } | ||
188 | |||
189 | /* Only allow one IR receiver to be registered per board */ | ||
190 | if (itv->hw_flags & IVTV_HW_IR_RX_ANY) | ||
191 | return -1; | ||
192 | |||
193 | /* Our default information for ir-kbd-i2c.c to use */ | ||
194 | switch (hw) { | ||
195 | case IVTV_HW_I2C_IR_RX_AVER: | ||
196 | init_data->ir_codes = &ir_codes_avermedia_cardbus_table; | ||
197 | init_data->internal_get_key_func = | ||
198 | IR_KBD_GET_KEY_AVERMEDIA_CARDBUS; | ||
199 | init_data->type = IR_TYPE_OTHER; | ||
200 | init_data->name = "AVerMedia AVerTV card"; | ||
201 | break; | ||
202 | case IVTV_HW_I2C_IR_RX_HAUP_EXT: | ||
203 | case IVTV_HW_I2C_IR_RX_HAUP_INT: | ||
204 | /* Default to old black remote */ | ||
205 | init_data->ir_codes = &ir_codes_rc5_tv_table; | ||
206 | init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP; | ||
207 | init_data->type = IR_TYPE_RC5; | ||
208 | init_data->name = itv->card_name; | ||
209 | break; | ||
210 | case IVTV_HW_Z8F0811_IR_RX_HAUP: | ||
211 | /* Default to grey remote */ | ||
212 | init_data->ir_codes = &ir_codes_hauppauge_new_table; | ||
213 | init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; | ||
214 | init_data->type = IR_TYPE_RC5; | ||
215 | init_data->name = itv->card_name; | ||
216 | break; | ||
217 | } | ||
218 | |||
219 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
220 | info.platform_data = init_data; | ||
221 | strlcpy(info.type, type, I2C_NAME_SIZE); | ||
222 | |||
223 | return i2c_new_probed_device(adap, &info, addr_list) == NULL ? -1 : 0; | ||
224 | } | ||
225 | |||
226 | /* Instantiate the IR receiver device using probing -- undesirable */ | ||
227 | struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv) | ||
228 | { | ||
229 | struct i2c_board_info info; | ||
230 | /* | ||
231 | * The external IR receiver is at i2c address 0x34. | ||
232 | * The internal IR receiver is at i2c address 0x30. | ||
233 | * | ||
234 | * In theory, both can be fitted, and Hauppauge suggests an external | ||
235 | * overrides an internal. That's why we probe 0x1a (~0x34) first. CB | ||
236 | * | ||
237 | * Some of these addresses we probe may collide with other i2c address | ||
238 | * allocations, so this function must be called after all other i2c | ||
239 | * devices we care about are registered. | ||
240 | */ | ||
241 | const unsigned short addr_list[] = { | ||
242 | 0x1a, /* Hauppauge IR external - collides with WM8739 */ | ||
243 | 0x18, /* Hauppauge IR internal */ | ||
244 | 0x71, /* Hauppauge IR (PVR150) */ | ||
245 | 0x6b, /* Adaptec IR */ | ||
246 | I2C_CLIENT_END | ||
247 | }; | ||
248 | |||
249 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
250 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); | ||
251 | return i2c_new_probed_device(&itv->i2c_adap, &info, addr_list); | ||
252 | } | ||
253 | |||
152 | int ivtv_i2c_register(struct ivtv *itv, unsigned idx) | 254 | int ivtv_i2c_register(struct ivtv *itv, unsigned idx) |
153 | { | 255 | { |
154 | struct v4l2_subdev *sd; | 256 | struct v4l2_subdev *sd; |
@@ -178,8 +280,15 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx) | |||
178 | sd->grp_id = 1 << idx; | 280 | sd->grp_id = 1 << idx; |
179 | return sd ? 0 : -1; | 281 | return sd ? 0 : -1; |
180 | } | 282 | } |
283 | |||
284 | if (hw & IVTV_HW_IR_ANY) | ||
285 | return ivtv_i2c_new_ir(itv, hw, type, hw_addrs[idx]); | ||
286 | |||
287 | /* Is it not an I2C device or one we do not wish to register? */ | ||
181 | if (!hw_addrs[idx]) | 288 | if (!hw_addrs[idx]) |
182 | return -1; | 289 | return -1; |
290 | |||
291 | /* It's an I2C device other than an analog tuner or IR chip */ | ||
183 | if (hw == IVTV_HW_UPD64031A || hw == IVTV_HW_UPD6408X) { | 292 | if (hw == IVTV_HW_UPD64031A || hw == IVTV_HW_UPD6408X) { |
184 | sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, | 293 | sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, |
185 | adap, mod, type, 0, I2C_ADDRS(hw_addrs[idx])); | 294 | adap, mod, type, 0, I2C_ADDRS(hw_addrs[idx])); |
@@ -564,20 +673,22 @@ static struct i2c_adapter ivtv_i2c_adap_template = { | |||
564 | .owner = THIS_MODULE, | 673 | .owner = THIS_MODULE, |
565 | }; | 674 | }; |
566 | 675 | ||
676 | #define IVTV_ALGO_BIT_TIMEOUT (2) /* seconds */ | ||
677 | |||
567 | static const struct i2c_algo_bit_data ivtv_i2c_algo_template = { | 678 | static const struct i2c_algo_bit_data ivtv_i2c_algo_template = { |
568 | .setsda = ivtv_setsda_old, | 679 | .setsda = ivtv_setsda_old, |
569 | .setscl = ivtv_setscl_old, | 680 | .setscl = ivtv_setscl_old, |
570 | .getsda = ivtv_getsda_old, | 681 | .getsda = ivtv_getsda_old, |
571 | .getscl = ivtv_getscl_old, | 682 | .getscl = ivtv_getscl_old, |
572 | .udelay = 10, | 683 | .udelay = IVTV_DEFAULT_I2C_CLOCK_PERIOD / 2, /* microseconds */ |
573 | .timeout = 200, | 684 | .timeout = IVTV_ALGO_BIT_TIMEOUT * HZ, /* jiffies */ |
574 | }; | 685 | }; |
575 | 686 | ||
576 | static struct i2c_client ivtv_i2c_client_template = { | 687 | static struct i2c_client ivtv_i2c_client_template = { |
577 | .name = "ivtv internal", | 688 | .name = "ivtv internal", |
578 | }; | 689 | }; |
579 | 690 | ||
580 | /* init + register i2c adapter + instantiate IR receiver */ | 691 | /* init + register i2c adapter */ |
581 | int init_ivtv_i2c(struct ivtv *itv) | 692 | int init_ivtv_i2c(struct ivtv *itv) |
582 | { | 693 | { |
583 | int retval; | 694 | int retval; |
@@ -585,11 +696,10 @@ int init_ivtv_i2c(struct ivtv *itv) | |||
585 | IVTV_DEBUG_I2C("i2c init\n"); | 696 | IVTV_DEBUG_I2C("i2c init\n"); |
586 | 697 | ||
587 | /* Sanity checks for the I2C hardware arrays. They must be the | 698 | /* Sanity checks for the I2C hardware arrays. They must be the |
588 | * same size and GPIO must be the last entry. | 699 | * same size. |
589 | */ | 700 | */ |
590 | if (ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_addrs) || | 701 | if (ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_addrs) || |
591 | ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_modules) || | 702 | ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_modules)) { |
592 | IVTV_HW_GPIO != (1 << (ARRAY_SIZE(hw_addrs) - 1))) { | ||
593 | IVTV_ERR("Mismatched I2C hardware arrays\n"); | 703 | IVTV_ERR("Mismatched I2C hardware arrays\n"); |
594 | return -ENODEV; | 704 | return -ENODEV; |
595 | } | 705 | } |
@@ -602,6 +712,7 @@ int init_ivtv_i2c(struct ivtv *itv) | |||
602 | memcpy(&itv->i2c_algo, &ivtv_i2c_algo_template, | 712 | memcpy(&itv->i2c_algo, &ivtv_i2c_algo_template, |
603 | sizeof(struct i2c_algo_bit_data)); | 713 | sizeof(struct i2c_algo_bit_data)); |
604 | } | 714 | } |
715 | itv->i2c_algo.udelay = itv->options.i2c_clock_period / 2; | ||
605 | itv->i2c_algo.data = itv; | 716 | itv->i2c_algo.data = itv; |
606 | itv->i2c_adap.algo_data = &itv->i2c_algo; | 717 | itv->i2c_adap.algo_data = &itv->i2c_algo; |
607 | 718 | ||
@@ -623,32 +734,6 @@ int init_ivtv_i2c(struct ivtv *itv) | |||
623 | else | 734 | else |
624 | retval = i2c_bit_add_bus(&itv->i2c_adap); | 735 | retval = i2c_bit_add_bus(&itv->i2c_adap); |
625 | 736 | ||
626 | /* Instantiate the IR receiver device, if present */ | ||
627 | if (retval == 0) { | ||
628 | struct i2c_board_info info; | ||
629 | /* The external IR receiver is at i2c address 0x34 (0x35 for | ||
630 | reads). Future Hauppauge cards will have an internal | ||
631 | receiver at 0x30 (0x31 for reads). In theory, both can be | ||
632 | fitted, and Hauppauge suggest an external overrides an | ||
633 | internal. | ||
634 | |||
635 | That's why we probe 0x1a (~0x34) first. CB | ||
636 | */ | ||
637 | const unsigned short addr_list[] = { | ||
638 | 0x1a, /* Hauppauge IR external */ | ||
639 | 0x18, /* Hauppauge IR internal */ | ||
640 | 0x71, /* Hauppauge IR (PVR150) */ | ||
641 | 0x64, /* Pixelview IR */ | ||
642 | 0x30, /* KNC ONE IR */ | ||
643 | 0x6b, /* Adaptec IR */ | ||
644 | I2C_CLIENT_END | ||
645 | }; | ||
646 | |||
647 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
648 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); | ||
649 | i2c_new_probed_device(&itv->i2c_adap, &info, addr_list); | ||
650 | } | ||
651 | |||
652 | return retval; | 737 | return retval; |
653 | } | 738 | } |
654 | 739 | ||
diff --git a/drivers/media/video/ivtv/ivtv-i2c.h b/drivers/media/video/ivtv/ivtv-i2c.h index 396928a06a54..9332920ca4ff 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.h +++ b/drivers/media/video/ivtv/ivtv-i2c.h | |||
@@ -21,6 +21,7 @@ | |||
21 | #ifndef IVTV_I2C_H | 21 | #ifndef IVTV_I2C_H |
22 | #define IVTV_I2C_H | 22 | #define IVTV_I2C_H |
23 | 23 | ||
24 | struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv); | ||
24 | int ivtv_i2c_register(struct ivtv *itv, unsigned idx); | 25 | int ivtv_i2c_register(struct ivtv *itv, unsigned idx); |
25 | struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw); | 26 | struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw); |
26 | 27 | ||
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 3454070e63f0..c1fc6dc776f5 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c | |||
@@ -478,7 +478,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) | |||
478 | 478 | ||
479 | DEB_EE(("VIDIOC_S_INPUT %d.\n", input)); | 479 | DEB_EE(("VIDIOC_S_INPUT %d.\n", input)); |
480 | 480 | ||
481 | if (input < 0 || input >= MXB_INPUTS) | 481 | if (input >= MXB_INPUTS) |
482 | return -EINVAL; | 482 | return -EINVAL; |
483 | 483 | ||
484 | mxb->cur_input = input; | 484 | mxb->cur_input = input; |
diff --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c new file mode 100644 index 000000000000..c81ae2192887 --- /dev/null +++ b/drivers/media/video/ov9640.c | |||
@@ -0,0 +1,801 @@ | |||
1 | /* | ||
2 | * OmniVision OV96xx Camera Driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Marek Vasut <marek.vasut@gmail.com> | ||
5 | * | ||
6 | * Based on ov772x camera driver: | ||
7 | * | ||
8 | * Copyright (C) 2008 Renesas Solutions Corp. | ||
9 | * Kuninori Morimoto <morimoto.kuninori@renesas.com> | ||
10 | * | ||
11 | * Based on ov7670 and soc_camera_platform driver, | ||
12 | * | ||
13 | * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net> | ||
14 | * Copyright (C) 2008 Magnus Damm | ||
15 | * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de> | ||
16 | * | ||
17 | * This program is free software; you can redistribute it and/or modify | ||
18 | * it under the terms of the GNU General Public License version 2 as | ||
19 | * published by the Free Software Foundation. | ||
20 | */ | ||
21 | |||
22 | #include <linux/init.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/i2c.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/videodev2.h> | ||
28 | #include <media/v4l2-chip-ident.h> | ||
29 | #include <media/v4l2-common.h> | ||
30 | #include <media/soc_camera.h> | ||
31 | |||
32 | #include "ov9640.h" | ||
33 | |||
34 | /* default register setup */ | ||
35 | static const struct ov9640_reg ov9640_regs_dflt[] = { | ||
36 | { OV9640_COM5, OV9640_COM5_SYSCLK | OV9640_COM5_LONGEXP }, | ||
37 | { OV9640_COM6, OV9640_COM6_OPT_BLC | OV9640_COM6_ADBLC_BIAS | | ||
38 | OV9640_COM6_FMT_RST | OV9640_COM6_ADBLC_OPTEN }, | ||
39 | { OV9640_PSHFT, OV9640_PSHFT_VAL(0x01) }, | ||
40 | { OV9640_ACOM, OV9640_ACOM_2X_ANALOG | OV9640_ACOM_RSVD }, | ||
41 | { OV9640_TSLB, OV9640_TSLB_YUYV_UYVY }, | ||
42 | { OV9640_COM16, OV9640_COM16_RB_AVG }, | ||
43 | |||
44 | /* Gamma curve P */ | ||
45 | { 0x6c, 0x40 }, { 0x6d, 0x30 }, { 0x6e, 0x4b }, { 0x6f, 0x60 }, | ||
46 | { 0x70, 0x70 }, { 0x71, 0x70 }, { 0x72, 0x70 }, { 0x73, 0x70 }, | ||
47 | { 0x74, 0x60 }, { 0x75, 0x60 }, { 0x76, 0x50 }, { 0x77, 0x48 }, | ||
48 | { 0x78, 0x3a }, { 0x79, 0x2e }, { 0x7a, 0x28 }, { 0x7b, 0x22 }, | ||
49 | |||
50 | /* Gamma curve T */ | ||
51 | { 0x7c, 0x04 }, { 0x7d, 0x07 }, { 0x7e, 0x10 }, { 0x7f, 0x28 }, | ||
52 | { 0x80, 0x36 }, { 0x81, 0x44 }, { 0x82, 0x52 }, { 0x83, 0x60 }, | ||
53 | { 0x84, 0x6c }, { 0x85, 0x78 }, { 0x86, 0x8c }, { 0x87, 0x9e }, | ||
54 | { 0x88, 0xbb }, { 0x89, 0xd2 }, { 0x8a, 0xe6 }, | ||
55 | }; | ||
56 | |||
57 | /* Configurations | ||
58 | * NOTE: for YUV, alter the following registers: | ||
59 | * COM12 |= OV9640_COM12_YUV_AVG | ||
60 | * | ||
61 | * for RGB, alter the following registers: | ||
62 | * COM7 |= OV9640_COM7_RGB | ||
63 | * COM13 |= OV9640_COM13_RGB_AVG | ||
64 | * COM15 |= proper RGB color encoding mode | ||
65 | */ | ||
66 | static const struct ov9640_reg ov9640_regs_qqcif[] = { | ||
67 | { OV9640_CLKRC, OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x0f) }, | ||
68 | { OV9640_COM1, OV9640_COM1_QQFMT | OV9640_COM1_HREF_2SKIP }, | ||
69 | { OV9640_COM4, OV9640_COM4_QQ_VP | OV9640_COM4_RSVD }, | ||
70 | { OV9640_COM7, OV9640_COM7_QCIF }, | ||
71 | { OV9640_COM12, OV9640_COM12_RSVD }, | ||
72 | { OV9640_COM13, OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN }, | ||
73 | { OV9640_COM15, OV9640_COM15_OR_10F0 }, | ||
74 | }; | ||
75 | |||
76 | static const struct ov9640_reg ov9640_regs_qqvga[] = { | ||
77 | { OV9640_CLKRC, OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x07) }, | ||
78 | { OV9640_COM1, OV9640_COM1_QQFMT | OV9640_COM1_HREF_2SKIP }, | ||
79 | { OV9640_COM4, OV9640_COM4_QQ_VP | OV9640_COM4_RSVD }, | ||
80 | { OV9640_COM7, OV9640_COM7_QVGA }, | ||
81 | { OV9640_COM12, OV9640_COM12_RSVD }, | ||
82 | { OV9640_COM13, OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN }, | ||
83 | { OV9640_COM15, OV9640_COM15_OR_10F0 }, | ||
84 | }; | ||
85 | |||
86 | static const struct ov9640_reg ov9640_regs_qcif[] = { | ||
87 | { OV9640_CLKRC, OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x07) }, | ||
88 | { OV9640_COM4, OV9640_COM4_QQ_VP | OV9640_COM4_RSVD }, | ||
89 | { OV9640_COM7, OV9640_COM7_QCIF }, | ||
90 | { OV9640_COM12, OV9640_COM12_RSVD }, | ||
91 | { OV9640_COM13, OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN }, | ||
92 | { OV9640_COM15, OV9640_COM15_OR_10F0 }, | ||
93 | }; | ||
94 | |||
95 | static const struct ov9640_reg ov9640_regs_qvga[] = { | ||
96 | { OV9640_CLKRC, OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x03) }, | ||
97 | { OV9640_COM4, OV9640_COM4_QQ_VP | OV9640_COM4_RSVD }, | ||
98 | { OV9640_COM7, OV9640_COM7_QVGA }, | ||
99 | { OV9640_COM12, OV9640_COM12_RSVD }, | ||
100 | { OV9640_COM13, OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN }, | ||
101 | { OV9640_COM15, OV9640_COM15_OR_10F0 }, | ||
102 | }; | ||
103 | |||
104 | static const struct ov9640_reg ov9640_regs_cif[] = { | ||
105 | { OV9640_CLKRC, OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x03) }, | ||
106 | { OV9640_COM3, OV9640_COM3_VP }, | ||
107 | { OV9640_COM7, OV9640_COM7_CIF }, | ||
108 | { OV9640_COM12, OV9640_COM12_RSVD }, | ||
109 | { OV9640_COM13, OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN }, | ||
110 | { OV9640_COM15, OV9640_COM15_OR_10F0 }, | ||
111 | }; | ||
112 | |||
113 | static const struct ov9640_reg ov9640_regs_vga[] = { | ||
114 | { OV9640_CLKRC, OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x01) }, | ||
115 | { OV9640_COM3, OV9640_COM3_VP }, | ||
116 | { OV9640_COM7, OV9640_COM7_VGA }, | ||
117 | { OV9640_COM12, OV9640_COM12_RSVD }, | ||
118 | { OV9640_COM13, OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN }, | ||
119 | { OV9640_COM15, OV9640_COM15_OR_10F0 }, | ||
120 | }; | ||
121 | |||
122 | static const struct ov9640_reg ov9640_regs_sxga[] = { | ||
123 | { OV9640_CLKRC, OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x01) }, | ||
124 | { OV9640_COM3, OV9640_COM3_VP }, | ||
125 | { OV9640_COM7, 0 }, | ||
126 | { OV9640_COM12, OV9640_COM12_RSVD }, | ||
127 | { OV9640_COM13, OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN }, | ||
128 | { OV9640_COM15, OV9640_COM15_OR_10F0 }, | ||
129 | }; | ||
130 | |||
131 | static const struct ov9640_reg ov9640_regs_yuv[] = { | ||
132 | { OV9640_MTX1, 0x58 }, | ||
133 | { OV9640_MTX2, 0x48 }, | ||
134 | { OV9640_MTX3, 0x10 }, | ||
135 | { OV9640_MTX4, 0x28 }, | ||
136 | { OV9640_MTX5, 0x48 }, | ||
137 | { OV9640_MTX6, 0x70 }, | ||
138 | { OV9640_MTX7, 0x40 }, | ||
139 | { OV9640_MTX8, 0x40 }, | ||
140 | { OV9640_MTX9, 0x40 }, | ||
141 | { OV9640_MTXS, 0x0f }, | ||
142 | }; | ||
143 | |||
144 | static const struct ov9640_reg ov9640_regs_rgb[] = { | ||
145 | { OV9640_MTX1, 0x71 }, | ||
146 | { OV9640_MTX2, 0x3e }, | ||
147 | { OV9640_MTX3, 0x0c }, | ||
148 | { OV9640_MTX4, 0x33 }, | ||
149 | { OV9640_MTX5, 0x72 }, | ||
150 | { OV9640_MTX6, 0x00 }, | ||
151 | { OV9640_MTX7, 0x2b }, | ||
152 | { OV9640_MTX8, 0x66 }, | ||
153 | { OV9640_MTX9, 0xd2 }, | ||
154 | { OV9640_MTXS, 0x65 }, | ||
155 | }; | ||
156 | |||
157 | /* | ||
158 | * TODO: this sensor also supports RGB555 and RGB565 formats, but support for | ||
159 | * them has not yet been sufficiently tested and so it is not included with | ||
160 | * this version of the driver. To test and debug these formats add two entries | ||
161 | * to the below array, see ov722x.c for an example. | ||
162 | */ | ||
163 | static const struct soc_camera_data_format ov9640_fmt_lists[] = { | ||
164 | { | ||
165 | .name = "UYVY", | ||
166 | .fourcc = V4L2_PIX_FMT_UYVY, | ||
167 | .depth = 16, | ||
168 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
169 | }, | ||
170 | }; | ||
171 | |||
172 | static const struct v4l2_queryctrl ov9640_controls[] = { | ||
173 | { | ||
174 | .id = V4L2_CID_VFLIP, | ||
175 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
176 | .name = "Flip Vertically", | ||
177 | .minimum = 0, | ||
178 | .maximum = 1, | ||
179 | .step = 1, | ||
180 | .default_value = 0, | ||
181 | }, | ||
182 | { | ||
183 | .id = V4L2_CID_HFLIP, | ||
184 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
185 | .name = "Flip Horizontally", | ||
186 | .minimum = 0, | ||
187 | .maximum = 1, | ||
188 | .step = 1, | ||
189 | .default_value = 0, | ||
190 | }, | ||
191 | }; | ||
192 | |||
193 | /* read a register */ | ||
194 | static int ov9640_reg_read(struct i2c_client *client, u8 reg, u8 *val) | ||
195 | { | ||
196 | int ret; | ||
197 | u8 data = reg; | ||
198 | struct i2c_msg msg = { | ||
199 | .addr = client->addr, | ||
200 | .flags = 0, | ||
201 | .len = 1, | ||
202 | .buf = &data, | ||
203 | }; | ||
204 | |||
205 | ret = i2c_transfer(client->adapter, &msg, 1); | ||
206 | if (ret < 0) | ||
207 | goto err; | ||
208 | |||
209 | msg.flags = I2C_M_RD; | ||
210 | ret = i2c_transfer(client->adapter, &msg, 1); | ||
211 | if (ret < 0) | ||
212 | goto err; | ||
213 | |||
214 | *val = data; | ||
215 | return 0; | ||
216 | |||
217 | err: | ||
218 | dev_err(&client->dev, "Failed reading register 0x%02x!\n", reg); | ||
219 | return ret; | ||
220 | } | ||
221 | |||
222 | /* write a register */ | ||
223 | static int ov9640_reg_write(struct i2c_client *client, u8 reg, u8 val) | ||
224 | { | ||
225 | int ret; | ||
226 | u8 _val; | ||
227 | unsigned char data[2] = { reg, val }; | ||
228 | struct i2c_msg msg = { | ||
229 | .addr = client->addr, | ||
230 | .flags = 0, | ||
231 | .len = 2, | ||
232 | .buf = data, | ||
233 | }; | ||
234 | |||
235 | ret = i2c_transfer(client->adapter, &msg, 1); | ||
236 | if (ret < 0) { | ||
237 | dev_err(&client->dev, "Failed writing register 0x%02x!\n", reg); | ||
238 | return ret; | ||
239 | } | ||
240 | |||
241 | /* we have to read the register back ... no idea why, maybe HW bug */ | ||
242 | ret = ov9640_reg_read(client, reg, &_val); | ||
243 | if (ret) | ||
244 | dev_err(&client->dev, | ||
245 | "Failed reading back register 0x%02x!\n", reg); | ||
246 | |||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | |||
251 | /* Read a register, alter its bits, write it back */ | ||
252 | static int ov9640_reg_rmw(struct i2c_client *client, u8 reg, u8 set, u8 unset) | ||
253 | { | ||
254 | u8 val; | ||
255 | int ret; | ||
256 | |||
257 | ret = ov9640_reg_read(client, reg, &val); | ||
258 | if (ret) { | ||
259 | dev_err(&client->dev, | ||
260 | "[Read]-Modify-Write of register %02x failed!\n", reg); | ||
261 | return val; | ||
262 | } | ||
263 | |||
264 | val |= set; | ||
265 | val &= ~unset; | ||
266 | |||
267 | ret = ov9640_reg_write(client, reg, val); | ||
268 | if (ret) | ||
269 | dev_err(&client->dev, | ||
270 | "Read-Modify-[Write] of register %02x failed!\n", reg); | ||
271 | |||
272 | return ret; | ||
273 | } | ||
274 | |||
275 | /* Soft reset the camera. This has nothing to do with the RESET pin! */ | ||
276 | static int ov9640_reset(struct i2c_client *client) | ||
277 | { | ||
278 | int ret; | ||
279 | |||
280 | ret = ov9640_reg_write(client, OV9640_COM7, OV9640_COM7_SCCB_RESET); | ||
281 | if (ret) | ||
282 | dev_err(&client->dev, | ||
283 | "An error occured while entering soft reset!\n"); | ||
284 | |||
285 | return ret; | ||
286 | } | ||
287 | |||
288 | /* Start/Stop streaming from the device */ | ||
289 | static int ov9640_s_stream(struct v4l2_subdev *sd, int enable) | ||
290 | { | ||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | /* Alter bus settings on camera side */ | ||
295 | static int ov9640_set_bus_param(struct soc_camera_device *icd, | ||
296 | unsigned long flags) | ||
297 | { | ||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | /* Request bus settings on camera side */ | ||
302 | static unsigned long ov9640_query_bus_param(struct soc_camera_device *icd) | ||
303 | { | ||
304 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
305 | |||
306 | /* | ||
307 | * REVISIT: the camera probably can do 10 bit transfers, but I don't | ||
308 | * have those pins connected on my hardware. | ||
309 | */ | ||
310 | unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | | ||
311 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | | ||
312 | SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8; | ||
313 | |||
314 | return soc_camera_apply_sensor_flags(icl, flags); | ||
315 | } | ||
316 | |||
317 | /* Get status of additional camera capabilities */ | ||
318 | static int ov9640_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
319 | { | ||
320 | struct i2c_client *client = sd->priv; | ||
321 | struct ov9640_priv *priv = container_of(i2c_get_clientdata(client), | ||
322 | struct ov9640_priv, subdev); | ||
323 | |||
324 | switch (ctrl->id) { | ||
325 | case V4L2_CID_VFLIP: | ||
326 | ctrl->value = priv->flag_vflip; | ||
327 | break; | ||
328 | case V4L2_CID_HFLIP: | ||
329 | ctrl->value = priv->flag_hflip; | ||
330 | break; | ||
331 | } | ||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | /* Set status of additional camera capabilities */ | ||
336 | static int ov9640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
337 | { | ||
338 | struct i2c_client *client = sd->priv; | ||
339 | struct ov9640_priv *priv = container_of(i2c_get_clientdata(client), | ||
340 | struct ov9640_priv, subdev); | ||
341 | |||
342 | int ret = 0; | ||
343 | |||
344 | switch (ctrl->id) { | ||
345 | case V4L2_CID_VFLIP: | ||
346 | priv->flag_vflip = ctrl->value; | ||
347 | if (ctrl->value) | ||
348 | ret = ov9640_reg_rmw(client, OV9640_MVFP, | ||
349 | OV9640_MVFP_V, 0); | ||
350 | else | ||
351 | ret = ov9640_reg_rmw(client, OV9640_MVFP, | ||
352 | 0, OV9640_MVFP_V); | ||
353 | break; | ||
354 | case V4L2_CID_HFLIP: | ||
355 | priv->flag_hflip = ctrl->value; | ||
356 | if (ctrl->value) | ||
357 | ret = ov9640_reg_rmw(client, OV9640_MVFP, | ||
358 | OV9640_MVFP_H, 0); | ||
359 | else | ||
360 | ret = ov9640_reg_rmw(client, OV9640_MVFP, | ||
361 | 0, OV9640_MVFP_H); | ||
362 | break; | ||
363 | } | ||
364 | |||
365 | return ret; | ||
366 | } | ||
367 | |||
368 | /* Get chip identification */ | ||
369 | static int ov9640_g_chip_ident(struct v4l2_subdev *sd, | ||
370 | struct v4l2_dbg_chip_ident *id) | ||
371 | { | ||
372 | struct i2c_client *client = sd->priv; | ||
373 | struct ov9640_priv *priv = container_of(i2c_get_clientdata(client), | ||
374 | struct ov9640_priv, subdev); | ||
375 | |||
376 | id->ident = priv->model; | ||
377 | id->revision = priv->revision; | ||
378 | |||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
383 | static int ov9640_get_register(struct v4l2_subdev *sd, | ||
384 | struct v4l2_dbg_register *reg) | ||
385 | { | ||
386 | struct i2c_client *client = sd->priv; | ||
387 | int ret; | ||
388 | u8 val; | ||
389 | |||
390 | if (reg->reg & ~0xff) | ||
391 | return -EINVAL; | ||
392 | |||
393 | reg->size = 1; | ||
394 | |||
395 | ret = ov9640_reg_read(client, reg->reg, &val); | ||
396 | if (ret) | ||
397 | return ret; | ||
398 | |||
399 | reg->val = (__u64)val; | ||
400 | |||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | static int ov9640_set_register(struct v4l2_subdev *sd, | ||
405 | struct v4l2_dbg_register *reg) | ||
406 | { | ||
407 | struct i2c_client *client = sd->priv; | ||
408 | |||
409 | if (reg->reg & ~0xff || reg->val & ~0xff) | ||
410 | return -EINVAL; | ||
411 | |||
412 | return ov9640_reg_write(client, reg->reg, reg->val); | ||
413 | } | ||
414 | #endif | ||
415 | |||
416 | /* select nearest higher resolution for capture */ | ||
417 | static void ov9640_res_roundup(u32 *width, u32 *height) | ||
418 | { | ||
419 | int i; | ||
420 | enum { QQCIF, QQVGA, QCIF, QVGA, CIF, VGA, SXGA }; | ||
421 | int res_x[] = { 88, 160, 176, 320, 352, 640, 1280 }; | ||
422 | int res_y[] = { 72, 120, 144, 240, 288, 480, 960 }; | ||
423 | |||
424 | for (i = 0; i < ARRAY_SIZE(res_x); i++) { | ||
425 | if (res_x[i] >= *width && res_y[i] >= *height) { | ||
426 | *width = res_x[i]; | ||
427 | *height = res_y[i]; | ||
428 | return; | ||
429 | } | ||
430 | } | ||
431 | |||
432 | *width = res_x[SXGA]; | ||
433 | *height = res_y[SXGA]; | ||
434 | } | ||
435 | |||
436 | /* Prepare necessary register changes depending on color encoding */ | ||
437 | static void ov9640_alter_regs(u32 pixfmt, struct ov9640_reg_alt *alt) | ||
438 | { | ||
439 | switch (pixfmt) { | ||
440 | case V4L2_PIX_FMT_UYVY: | ||
441 | alt->com12 = OV9640_COM12_YUV_AVG; | ||
442 | alt->com13 = OV9640_COM13_Y_DELAY_EN | | ||
443 | OV9640_COM13_YUV_DLY(0x01); | ||
444 | break; | ||
445 | case V4L2_PIX_FMT_RGB555: | ||
446 | alt->com7 = OV9640_COM7_RGB; | ||
447 | alt->com13 = OV9640_COM13_RGB_AVG; | ||
448 | alt->com15 = OV9640_COM15_RGB_555; | ||
449 | break; | ||
450 | case V4L2_PIX_FMT_RGB565: | ||
451 | alt->com7 = OV9640_COM7_RGB; | ||
452 | alt->com13 = OV9640_COM13_RGB_AVG; | ||
453 | alt->com15 = OV9640_COM15_RGB_565; | ||
454 | break; | ||
455 | }; | ||
456 | } | ||
457 | |||
458 | /* Setup registers according to resolution and color encoding */ | ||
459 | static int ov9640_write_regs(struct i2c_client *client, | ||
460 | u32 width, u32 pixfmt, struct ov9640_reg_alt *alts) | ||
461 | { | ||
462 | const struct ov9640_reg *ov9640_regs, *matrix_regs; | ||
463 | int ov9640_regs_len, matrix_regs_len; | ||
464 | int i, ret; | ||
465 | u8 val; | ||
466 | |||
467 | /* select register configuration for given resolution */ | ||
468 | switch (width) { | ||
469 | case W_QQCIF: | ||
470 | ov9640_regs = ov9640_regs_qqcif; | ||
471 | ov9640_regs_len = ARRAY_SIZE(ov9640_regs_qqcif); | ||
472 | break; | ||
473 | case W_QQVGA: | ||
474 | ov9640_regs = ov9640_regs_qqvga; | ||
475 | ov9640_regs_len = ARRAY_SIZE(ov9640_regs_qqvga); | ||
476 | break; | ||
477 | case W_QCIF: | ||
478 | ov9640_regs = ov9640_regs_qcif; | ||
479 | ov9640_regs_len = ARRAY_SIZE(ov9640_regs_qcif); | ||
480 | break; | ||
481 | case W_QVGA: | ||
482 | ov9640_regs = ov9640_regs_qvga; | ||
483 | ov9640_regs_len = ARRAY_SIZE(ov9640_regs_qvga); | ||
484 | break; | ||
485 | case W_CIF: | ||
486 | ov9640_regs = ov9640_regs_cif; | ||
487 | ov9640_regs_len = ARRAY_SIZE(ov9640_regs_cif); | ||
488 | break; | ||
489 | case W_VGA: | ||
490 | ov9640_regs = ov9640_regs_vga; | ||
491 | ov9640_regs_len = ARRAY_SIZE(ov9640_regs_vga); | ||
492 | break; | ||
493 | case W_SXGA: | ||
494 | ov9640_regs = ov9640_regs_sxga; | ||
495 | ov9640_regs_len = ARRAY_SIZE(ov9640_regs_sxga); | ||
496 | break; | ||
497 | default: | ||
498 | dev_err(&client->dev, "Failed to select resolution!\n"); | ||
499 | return -EINVAL; | ||
500 | } | ||
501 | |||
502 | /* select color matrix configuration for given color encoding */ | ||
503 | if (pixfmt == V4L2_PIX_FMT_UYVY) { | ||
504 | matrix_regs = ov9640_regs_yuv; | ||
505 | matrix_regs_len = ARRAY_SIZE(ov9640_regs_yuv); | ||
506 | } else { | ||
507 | matrix_regs = ov9640_regs_rgb; | ||
508 | matrix_regs_len = ARRAY_SIZE(ov9640_regs_rgb); | ||
509 | } | ||
510 | |||
511 | /* write register settings into the module */ | ||
512 | for (i = 0; i < ov9640_regs_len; i++) { | ||
513 | val = ov9640_regs[i].val; | ||
514 | |||
515 | switch (ov9640_regs[i].reg) { | ||
516 | case OV9640_COM7: | ||
517 | val |= alts->com7; | ||
518 | break; | ||
519 | case OV9640_COM12: | ||
520 | val |= alts->com12; | ||
521 | break; | ||
522 | case OV9640_COM13: | ||
523 | val |= alts->com13; | ||
524 | break; | ||
525 | case OV9640_COM15: | ||
526 | val |= alts->com15; | ||
527 | break; | ||
528 | } | ||
529 | |||
530 | ret = ov9640_reg_write(client, ov9640_regs[i].reg, val); | ||
531 | if (ret) | ||
532 | return ret; | ||
533 | } | ||
534 | |||
535 | /* write color matrix configuration into the module */ | ||
536 | for (i = 0; i < matrix_regs_len; i++) { | ||
537 | ret = ov9640_reg_write(client, matrix_regs[i].reg, | ||
538 | matrix_regs[i].val); | ||
539 | if (ret) | ||
540 | return ret; | ||
541 | } | ||
542 | |||
543 | return 0; | ||
544 | } | ||
545 | |||
546 | /* program default register values */ | ||
547 | static int ov9640_prog_dflt(struct i2c_client *client) | ||
548 | { | ||
549 | int i, ret; | ||
550 | |||
551 | for (i = 0; i < ARRAY_SIZE(ov9640_regs_dflt); i++) { | ||
552 | ret = ov9640_reg_write(client, ov9640_regs_dflt[i].reg, | ||
553 | ov9640_regs_dflt[i].val); | ||
554 | if (ret) | ||
555 | return ret; | ||
556 | } | ||
557 | |||
558 | /* wait for the changes to actually happen, 140ms are not enough yet */ | ||
559 | mdelay(150); | ||
560 | |||
561 | return 0; | ||
562 | } | ||
563 | |||
564 | /* set the format we will capture in */ | ||
565 | static int ov9640_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | ||
566 | { | ||
567 | struct i2c_client *client = sd->priv; | ||
568 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
569 | struct ov9640_reg_alt alts = {0}; | ||
570 | int ret; | ||
571 | |||
572 | ov9640_res_roundup(&pix->width, &pix->height); | ||
573 | ov9640_alter_regs(pix->pixelformat, &alts); | ||
574 | |||
575 | ov9640_reset(client); | ||
576 | |||
577 | ret = ov9640_prog_dflt(client); | ||
578 | if (ret) | ||
579 | return ret; | ||
580 | |||
581 | return ov9640_write_regs(client, pix->width, pix->pixelformat, &alts); | ||
582 | } | ||
583 | |||
584 | static int ov9640_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | ||
585 | { | ||
586 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
587 | |||
588 | ov9640_res_roundup(&pix->width, &pix->height); | ||
589 | pix->field = V4L2_FIELD_NONE; | ||
590 | |||
591 | return 0; | ||
592 | } | ||
593 | |||
594 | static int ov9640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | ||
595 | { | ||
596 | a->c.left = 0; | ||
597 | a->c.top = 0; | ||
598 | a->c.width = W_SXGA; | ||
599 | a->c.height = H_SXGA; | ||
600 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
601 | |||
602 | return 0; | ||
603 | } | ||
604 | |||
605 | static int ov9640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) | ||
606 | { | ||
607 | a->bounds.left = 0; | ||
608 | a->bounds.top = 0; | ||
609 | a->bounds.width = W_SXGA; | ||
610 | a->bounds.height = H_SXGA; | ||
611 | a->defrect = a->bounds; | ||
612 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
613 | a->pixelaspect.numerator = 1; | ||
614 | a->pixelaspect.denominator = 1; | ||
615 | |||
616 | return 0; | ||
617 | } | ||
618 | |||
619 | |||
620 | |||
621 | static int ov9640_video_probe(struct soc_camera_device *icd, | ||
622 | struct i2c_client *client) | ||
623 | { | ||
624 | struct ov9640_priv *priv = i2c_get_clientdata(client); | ||
625 | u8 pid, ver, midh, midl; | ||
626 | const char *devname; | ||
627 | int ret = 0; | ||
628 | |||
629 | /* | ||
630 | * We must have a parent by now. And it cannot be a wrong one. | ||
631 | * So this entire test is completely redundant. | ||
632 | */ | ||
633 | if (!icd->dev.parent || | ||
634 | to_soc_camera_host(icd->dev.parent)->nr != icd->iface) { | ||
635 | dev_err(&client->dev, "Parent missing or invalid!\n"); | ||
636 | ret = -ENODEV; | ||
637 | goto err; | ||
638 | } | ||
639 | |||
640 | icd->formats = ov9640_fmt_lists; | ||
641 | icd->num_formats = ARRAY_SIZE(ov9640_fmt_lists); | ||
642 | |||
643 | /* | ||
644 | * check and show product ID and manufacturer ID | ||
645 | */ | ||
646 | |||
647 | ret = ov9640_reg_read(client, OV9640_PID, &pid); | ||
648 | if (ret) | ||
649 | goto err; | ||
650 | |||
651 | ret = ov9640_reg_read(client, OV9640_VER, &ver); | ||
652 | if (ret) | ||
653 | goto err; | ||
654 | |||
655 | ret = ov9640_reg_read(client, OV9640_MIDH, &midh); | ||
656 | if (ret) | ||
657 | goto err; | ||
658 | |||
659 | ret = ov9640_reg_read(client, OV9640_MIDL, &midl); | ||
660 | if (ret) | ||
661 | goto err; | ||
662 | |||
663 | switch (VERSION(pid, ver)) { | ||
664 | case OV9640_V2: | ||
665 | devname = "ov9640"; | ||
666 | priv->model = V4L2_IDENT_OV9640; | ||
667 | priv->revision = 2; | ||
668 | case OV9640_V3: | ||
669 | devname = "ov9640"; | ||
670 | priv->model = V4L2_IDENT_OV9640; | ||
671 | priv->revision = 3; | ||
672 | break; | ||
673 | default: | ||
674 | dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver); | ||
675 | ret = -ENODEV; | ||
676 | goto err; | ||
677 | } | ||
678 | |||
679 | dev_info(&client->dev, "%s Product ID %0x:%0x Manufacturer ID %x:%x\n", | ||
680 | devname, pid, ver, midh, midl); | ||
681 | |||
682 | err: | ||
683 | return ret; | ||
684 | } | ||
685 | |||
686 | static struct soc_camera_ops ov9640_ops = { | ||
687 | .set_bus_param = ov9640_set_bus_param, | ||
688 | .query_bus_param = ov9640_query_bus_param, | ||
689 | .controls = ov9640_controls, | ||
690 | .num_controls = ARRAY_SIZE(ov9640_controls), | ||
691 | }; | ||
692 | |||
693 | static struct v4l2_subdev_core_ops ov9640_core_ops = { | ||
694 | .g_ctrl = ov9640_g_ctrl, | ||
695 | .s_ctrl = ov9640_s_ctrl, | ||
696 | .g_chip_ident = ov9640_g_chip_ident, | ||
697 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
698 | .g_register = ov9640_get_register, | ||
699 | .s_register = ov9640_set_register, | ||
700 | #endif | ||
701 | |||
702 | }; | ||
703 | |||
704 | static struct v4l2_subdev_video_ops ov9640_video_ops = { | ||
705 | .s_stream = ov9640_s_stream, | ||
706 | .s_fmt = ov9640_s_fmt, | ||
707 | .try_fmt = ov9640_try_fmt, | ||
708 | .cropcap = ov9640_cropcap, | ||
709 | .g_crop = ov9640_g_crop, | ||
710 | |||
711 | }; | ||
712 | |||
713 | static struct v4l2_subdev_ops ov9640_subdev_ops = { | ||
714 | .core = &ov9640_core_ops, | ||
715 | .video = &ov9640_video_ops, | ||
716 | }; | ||
717 | |||
718 | /* | ||
719 | * i2c_driver function | ||
720 | */ | ||
721 | static int ov9640_probe(struct i2c_client *client, | ||
722 | const struct i2c_device_id *did) | ||
723 | { | ||
724 | struct ov9640_priv *priv; | ||
725 | struct soc_camera_device *icd = client->dev.platform_data; | ||
726 | struct soc_camera_link *icl; | ||
727 | int ret; | ||
728 | |||
729 | if (!icd) { | ||
730 | dev_err(&client->dev, "Missing soc-camera data!\n"); | ||
731 | return -EINVAL; | ||
732 | } | ||
733 | |||
734 | icl = to_soc_camera_link(icd); | ||
735 | if (!icl) { | ||
736 | dev_err(&client->dev, "Missing platform_data for driver\n"); | ||
737 | return -EINVAL; | ||
738 | } | ||
739 | |||
740 | priv = kzalloc(sizeof(struct ov9640_priv), GFP_KERNEL); | ||
741 | if (!priv) { | ||
742 | dev_err(&client->dev, | ||
743 | "Failed to allocate memory for private data!\n"); | ||
744 | return -ENOMEM; | ||
745 | } | ||
746 | |||
747 | v4l2_i2c_subdev_init(&priv->subdev, client, &ov9640_subdev_ops); | ||
748 | |||
749 | icd->ops = &ov9640_ops; | ||
750 | |||
751 | ret = ov9640_video_probe(icd, client); | ||
752 | |||
753 | if (ret) { | ||
754 | icd->ops = NULL; | ||
755 | i2c_set_clientdata(client, NULL); | ||
756 | kfree(priv); | ||
757 | } | ||
758 | |||
759 | return ret; | ||
760 | } | ||
761 | |||
762 | static int ov9640_remove(struct i2c_client *client) | ||
763 | { | ||
764 | struct ov9640_priv *priv = i2c_get_clientdata(client); | ||
765 | |||
766 | i2c_set_clientdata(client, NULL); | ||
767 | kfree(priv); | ||
768 | return 0; | ||
769 | } | ||
770 | |||
771 | static const struct i2c_device_id ov9640_id[] = { | ||
772 | { "ov9640", 0 }, | ||
773 | { } | ||
774 | }; | ||
775 | MODULE_DEVICE_TABLE(i2c, ov9640_id); | ||
776 | |||
777 | static struct i2c_driver ov9640_i2c_driver = { | ||
778 | .driver = { | ||
779 | .name = "ov9640", | ||
780 | }, | ||
781 | .probe = ov9640_probe, | ||
782 | .remove = ov9640_remove, | ||
783 | .id_table = ov9640_id, | ||
784 | }; | ||
785 | |||
786 | static int __init ov9640_module_init(void) | ||
787 | { | ||
788 | return i2c_add_driver(&ov9640_i2c_driver); | ||
789 | } | ||
790 | |||
791 | static void __exit ov9640_module_exit(void) | ||
792 | { | ||
793 | i2c_del_driver(&ov9640_i2c_driver); | ||
794 | } | ||
795 | |||
796 | module_init(ov9640_module_init); | ||
797 | module_exit(ov9640_module_exit); | ||
798 | |||
799 | MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV96xx"); | ||
800 | MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); | ||
801 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/video/ov9640.h b/drivers/media/video/ov9640.h new file mode 100644 index 000000000000..f8a51b70792e --- /dev/null +++ b/drivers/media/video/ov9640.h | |||
@@ -0,0 +1,209 @@ | |||
1 | /* | ||
2 | * OmniVision OV96xx Camera Header File | ||
3 | * | ||
4 | * Copyright (C) 2009 Marek Vasut <marek.vasut@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef __DRIVERS_MEDIA_VIDEO_OV9640_H__ | ||
12 | #define __DRIVERS_MEDIA_VIDEO_OV9640_H__ | ||
13 | |||
14 | /* Register definitions */ | ||
15 | #define OV9640_GAIN 0x00 | ||
16 | #define OV9640_BLUE 0x01 | ||
17 | #define OV9640_RED 0x02 | ||
18 | #define OV9640_VFER 0x03 | ||
19 | #define OV9640_COM1 0x04 | ||
20 | #define OV9640_BAVE 0x05 | ||
21 | #define OV9640_GEAVE 0x06 | ||
22 | #define OV9640_RSID 0x07 | ||
23 | #define OV9640_RAVE 0x08 | ||
24 | #define OV9640_COM2 0x09 | ||
25 | #define OV9640_PID 0x0a | ||
26 | #define OV9640_VER 0x0b | ||
27 | #define OV9640_COM3 0x0c | ||
28 | #define OV9640_COM4 0x0d | ||
29 | #define OV9640_COM5 0x0e | ||
30 | #define OV9640_COM6 0x0f | ||
31 | #define OV9640_AECH 0x10 | ||
32 | #define OV9640_CLKRC 0x11 | ||
33 | #define OV9640_COM7 0x12 | ||
34 | #define OV9640_COM8 0x13 | ||
35 | #define OV9640_COM9 0x14 | ||
36 | #define OV9640_COM10 0x15 | ||
37 | /* 0x16 - RESERVED */ | ||
38 | #define OV9640_HSTART 0x17 | ||
39 | #define OV9640_HSTOP 0x18 | ||
40 | #define OV9640_VSTART 0x19 | ||
41 | #define OV9640_VSTOP 0x1a | ||
42 | #define OV9640_PSHFT 0x1b | ||
43 | #define OV9640_MIDH 0x1c | ||
44 | #define OV9640_MIDL 0x1d | ||
45 | #define OV9640_MVFP 0x1e | ||
46 | #define OV9640_LAEC 0x1f | ||
47 | #define OV9640_BOS 0x20 | ||
48 | #define OV9640_GBOS 0x21 | ||
49 | #define OV9640_GROS 0x22 | ||
50 | #define OV9640_ROS 0x23 | ||
51 | #define OV9640_AEW 0x24 | ||
52 | #define OV9640_AEB 0x25 | ||
53 | #define OV9640_VPT 0x26 | ||
54 | #define OV9640_BBIAS 0x27 | ||
55 | #define OV9640_GBBIAS 0x28 | ||
56 | /* 0x29 - RESERVED */ | ||
57 | #define OV9640_EXHCH 0x2a | ||
58 | #define OV9640_EXHCL 0x2b | ||
59 | #define OV9640_RBIAS 0x2c | ||
60 | #define OV9640_ADVFL 0x2d | ||
61 | #define OV9640_ADVFH 0x2e | ||
62 | #define OV9640_YAVE 0x2f | ||
63 | #define OV9640_HSYST 0x30 | ||
64 | #define OV9640_HSYEN 0x31 | ||
65 | #define OV9640_HREF 0x32 | ||
66 | #define OV9640_CHLF 0x33 | ||
67 | #define OV9640_ARBLM 0x34 | ||
68 | /* 0x35..0x36 - RESERVED */ | ||
69 | #define OV9640_ADC 0x37 | ||
70 | #define OV9640_ACOM 0x38 | ||
71 | #define OV9640_OFON 0x39 | ||
72 | #define OV9640_TSLB 0x3a | ||
73 | #define OV9640_COM11 0x3b | ||
74 | #define OV9640_COM12 0x3c | ||
75 | #define OV9640_COM13 0x3d | ||
76 | #define OV9640_COM14 0x3e | ||
77 | #define OV9640_EDGE 0x3f | ||
78 | #define OV9640_COM15 0x40 | ||
79 | #define OV9640_COM16 0x41 | ||
80 | #define OV9640_COM17 0x42 | ||
81 | /* 0x43..0x4e - RESERVED */ | ||
82 | #define OV9640_MTX1 0x4f | ||
83 | #define OV9640_MTX2 0x50 | ||
84 | #define OV9640_MTX3 0x51 | ||
85 | #define OV9640_MTX4 0x52 | ||
86 | #define OV9640_MTX5 0x53 | ||
87 | #define OV9640_MTX6 0x54 | ||
88 | #define OV9640_MTX7 0x55 | ||
89 | #define OV9640_MTX8 0x56 | ||
90 | #define OV9640_MTX9 0x57 | ||
91 | #define OV9640_MTXS 0x58 | ||
92 | /* 0x59..0x61 - RESERVED */ | ||
93 | #define OV9640_LCC1 0x62 | ||
94 | #define OV9640_LCC2 0x63 | ||
95 | #define OV9640_LCC3 0x64 | ||
96 | #define OV9640_LCC4 0x65 | ||
97 | #define OV9640_LCC5 0x66 | ||
98 | #define OV9640_MANU 0x67 | ||
99 | #define OV9640_MANV 0x68 | ||
100 | #define OV9640_HV 0x69 | ||
101 | #define OV9640_MBD 0x6a | ||
102 | #define OV9640_DBLV 0x6b | ||
103 | #define OV9640_GSP 0x6c /* ... till 0x7b */ | ||
104 | #define OV9640_GST 0x7c /* ... till 0x8a */ | ||
105 | |||
106 | #define OV9640_CLKRC_DPLL_EN 0x80 | ||
107 | #define OV9640_CLKRC_DIRECT 0x40 | ||
108 | #define OV9640_CLKRC_DIV(x) ((x) & 0x3f) | ||
109 | |||
110 | #define OV9640_PSHFT_VAL(x) ((x) & 0xff) | ||
111 | |||
112 | #define OV9640_ACOM_2X_ANALOG 0x80 | ||
113 | #define OV9640_ACOM_RSVD 0x12 | ||
114 | |||
115 | #define OV9640_MVFP_V 0x10 | ||
116 | #define OV9640_MVFP_H 0x20 | ||
117 | |||
118 | #define OV9640_COM1_HREF_NOSKIP 0x00 | ||
119 | #define OV9640_COM1_HREF_2SKIP 0x04 | ||
120 | #define OV9640_COM1_HREF_3SKIP 0x08 | ||
121 | #define OV9640_COM1_QQFMT 0x20 | ||
122 | |||
123 | #define OV9640_COM2_SSM 0x10 | ||
124 | |||
125 | #define OV9640_COM3_VP 0x04 | ||
126 | |||
127 | #define OV9640_COM4_QQ_VP 0x80 | ||
128 | #define OV9640_COM4_RSVD 0x40 | ||
129 | |||
130 | #define OV9640_COM5_SYSCLK 0x80 | ||
131 | #define OV9640_COM5_LONGEXP 0x01 | ||
132 | |||
133 | #define OV9640_COM6_OPT_BLC 0x40 | ||
134 | #define OV9640_COM6_ADBLC_BIAS 0x08 | ||
135 | #define OV9640_COM6_FMT_RST 0x82 | ||
136 | #define OV9640_COM6_ADBLC_OPTEN 0x01 | ||
137 | |||
138 | #define OV9640_COM7_RAW_RGB 0x01 | ||
139 | #define OV9640_COM7_RGB 0x04 | ||
140 | #define OV9640_COM7_QCIF 0x08 | ||
141 | #define OV9640_COM7_QVGA 0x10 | ||
142 | #define OV9640_COM7_CIF 0x20 | ||
143 | #define OV9640_COM7_VGA 0x40 | ||
144 | #define OV9640_COM7_SCCB_RESET 0x80 | ||
145 | |||
146 | #define OV9640_TSLB_YVYU_YUYV 0x04 | ||
147 | #define OV9640_TSLB_YUYV_UYVY 0x08 | ||
148 | |||
149 | #define OV9640_COM12_YUV_AVG 0x04 | ||
150 | #define OV9640_COM12_RSVD 0x40 | ||
151 | |||
152 | #define OV9640_COM13_GAMMA_NONE 0x00 | ||
153 | #define OV9640_COM13_GAMMA_Y 0x40 | ||
154 | #define OV9640_COM13_GAMMA_RAW 0x80 | ||
155 | #define OV9640_COM13_RGB_AVG 0x20 | ||
156 | #define OV9640_COM13_MATRIX_EN 0x10 | ||
157 | #define OV9640_COM13_Y_DELAY_EN 0x08 | ||
158 | #define OV9640_COM13_YUV_DLY(x) ((x) & 0x07) | ||
159 | |||
160 | #define OV9640_COM15_OR_00FF 0x00 | ||
161 | #define OV9640_COM15_OR_01FE 0x40 | ||
162 | #define OV9640_COM15_OR_10F0 0xc0 | ||
163 | #define OV9640_COM15_RGB_NORM 0x00 | ||
164 | #define OV9640_COM15_RGB_565 0x10 | ||
165 | #define OV9640_COM15_RGB_555 0x30 | ||
166 | |||
167 | #define OV9640_COM16_RB_AVG 0x01 | ||
168 | |||
169 | /* IDs */ | ||
170 | #define OV9640_V2 0x9648 | ||
171 | #define OV9640_V3 0x9649 | ||
172 | #define VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xFF)) | ||
173 | |||
174 | /* supported resolutions */ | ||
175 | enum { | ||
176 | W_QQCIF = 88, | ||
177 | W_QQVGA = 160, | ||
178 | W_QCIF = 176, | ||
179 | W_QVGA = 320, | ||
180 | W_CIF = 352, | ||
181 | W_VGA = 640, | ||
182 | W_SXGA = 1280 | ||
183 | }; | ||
184 | #define H_SXGA 960 | ||
185 | |||
186 | /* Misc. structures */ | ||
187 | struct ov9640_reg_alt { | ||
188 | u8 com7; | ||
189 | u8 com12; | ||
190 | u8 com13; | ||
191 | u8 com15; | ||
192 | }; | ||
193 | |||
194 | struct ov9640_reg { | ||
195 | u8 reg; | ||
196 | u8 val; | ||
197 | }; | ||
198 | |||
199 | struct ov9640_priv { | ||
200 | struct v4l2_subdev subdev; | ||
201 | |||
202 | int model; | ||
203 | int revision; | ||
204 | |||
205 | bool flag_vflip; | ||
206 | bool flag_hflip; | ||
207 | }; | ||
208 | |||
209 | #endif /* __DRIVERS_MEDIA_VIDEO_OV9640_H__ */ | ||
diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index a1ad38fc49c1..73ec970ca5ca 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c | |||
@@ -14,8 +14,10 @@ | |||
14 | * unless the userspace driver also doesn't work for you... | 14 | * unless the userspace driver also doesn't work for you... |
15 | * | 15 | * |
16 | * Changes: | 16 | * Changes: |
17 | * 08/07/2003 Daniele Bellucci <bellucda@tiscali.it> | 17 | * 25-11-2009 Hans Verkuil <hverkuil@xs4all.nl> |
18 | * - pms_capture: report back -EFAULT | 18 | * - converted to version 2 of the V4L API. |
19 | * 08/07/2003 Daniele Bellucci <bellucda@tiscali.it> | ||
20 | * - pms_capture: report back -EFAULT | ||
19 | */ | 21 | */ |
20 | 22 | ||
21 | #include <linux/module.h> | 23 | #include <linux/module.h> |
@@ -27,175 +29,183 @@ | |||
27 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
28 | #include <linux/ioport.h> | 30 | #include <linux/ioport.h> |
29 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/version.h> | ||
33 | #include <linux/mutex.h> | ||
34 | #include <asm/uaccess.h> | ||
30 | #include <asm/io.h> | 35 | #include <asm/io.h> |
31 | #include <linux/videodev.h> | 36 | |
37 | #include <linux/videodev2.h> | ||
32 | #include <media/v4l2-common.h> | 38 | #include <media/v4l2-common.h> |
33 | #include <media/v4l2-ioctl.h> | 39 | #include <media/v4l2-ioctl.h> |
34 | #include <linux/mutex.h> | 40 | #include <media/v4l2-device.h> |
35 | 41 | ||
36 | #include <asm/uaccess.h> | 42 | MODULE_LICENSE("GPL"); |
37 | 43 | ||
38 | 44 | ||
39 | #define MOTOROLA 1 | 45 | #define MOTOROLA 1 |
40 | #define PHILIPS2 2 | 46 | #define PHILIPS2 2 /* SAA7191 */ |
41 | #define PHILIPS1 3 | 47 | #define PHILIPS1 3 |
42 | #define MVVMEMORYWIDTH 0x40 /* 512 bytes */ | 48 | #define MVVMEMORYWIDTH 0x40 /* 512 bytes */ |
43 | 49 | ||
44 | struct pms_device | 50 | struct i2c_info { |
45 | { | ||
46 | struct video_device v; | ||
47 | struct video_picture picture; | ||
48 | int height; | ||
49 | int width; | ||
50 | unsigned long in_use; | ||
51 | struct mutex lock; | ||
52 | }; | ||
53 | |||
54 | struct i2c_info | ||
55 | { | ||
56 | u8 slave; | 51 | u8 slave; |
57 | u8 sub; | 52 | u8 sub; |
58 | u8 data; | 53 | u8 data; |
59 | u8 hits; | 54 | u8 hits; |
60 | }; | 55 | }; |
61 | 56 | ||
62 | static int i2c_count; | 57 | struct pms { |
63 | static struct i2c_info i2cinfo[64]; | 58 | struct v4l2_device v4l2_dev; |
59 | struct video_device vdev; | ||
60 | int height; | ||
61 | int width; | ||
62 | int depth; | ||
63 | int input; | ||
64 | s32 brightness, saturation, hue, contrast; | ||
65 | unsigned long in_use; | ||
66 | struct mutex lock; | ||
67 | int i2c_count; | ||
68 | struct i2c_info i2cinfo[64]; | ||
69 | |||
70 | int decoder; | ||
71 | int standard; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */ | ||
72 | v4l2_std_id std; | ||
73 | int io; | ||
74 | int data; | ||
75 | void __iomem *mem; | ||
76 | }; | ||
64 | 77 | ||
65 | static int decoder = PHILIPS2; | 78 | static struct pms pms_card; |
66 | static int standard; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */ | ||
67 | 79 | ||
68 | /* | 80 | /* |
69 | * I/O ports and Shared Memory | 81 | * I/O ports and Shared Memory |
70 | */ | 82 | */ |
71 | 83 | ||
72 | static int io_port = 0x250; | 84 | static int io_port = 0x250; |
73 | static int data_port = 0x251; | 85 | module_param(io_port, int, 0); |
74 | static int mem_base = 0xC8000; | ||
75 | static void __iomem *mem; | ||
76 | static int video_nr = -1; | ||
77 | 86 | ||
87 | static int mem_base = 0xc8000; | ||
88 | module_param(mem_base, int, 0); | ||
78 | 89 | ||
90 | static int video_nr = -1; | ||
91 | module_param(video_nr, int, 0); | ||
79 | 92 | ||
80 | static inline void mvv_write(u8 index, u8 value) | 93 | |
94 | static inline void mvv_write(struct pms *dev, u8 index, u8 value) | ||
81 | { | 95 | { |
82 | outw(index|(value<<8), io_port); | 96 | outw(index | (value << 8), dev->io); |
83 | } | 97 | } |
84 | 98 | ||
85 | static inline u8 mvv_read(u8 index) | 99 | static inline u8 mvv_read(struct pms *dev, u8 index) |
86 | { | 100 | { |
87 | outb(index, io_port); | 101 | outb(index, dev->io); |
88 | return inb(data_port); | 102 | return inb(dev->data); |
89 | } | 103 | } |
90 | 104 | ||
91 | static int pms_i2c_stat(u8 slave) | 105 | static int pms_i2c_stat(struct pms *dev, u8 slave) |
92 | { | 106 | { |
93 | int counter; | 107 | int counter = 0; |
94 | int i; | 108 | int i; |
95 | 109 | ||
96 | outb(0x28, io_port); | 110 | outb(0x28, dev->io); |
97 | 111 | ||
98 | counter=0; | 112 | while ((inb(dev->data) & 0x01) == 0) |
99 | while((inb(data_port)&0x01)==0) | 113 | if (counter++ == 256) |
100 | if(counter++==256) | ||
101 | break; | 114 | break; |
102 | 115 | ||
103 | while((inb(data_port)&0x01)!=0) | 116 | while ((inb(dev->data) & 0x01) != 0) |
104 | if(counter++==256) | 117 | if (counter++ == 256) |
105 | break; | 118 | break; |
106 | 119 | ||
107 | outb(slave, io_port); | 120 | outb(slave, dev->io); |
108 | 121 | ||
109 | counter=0; | 122 | counter = 0; |
110 | while((inb(data_port)&0x01)==0) | 123 | while ((inb(dev->data) & 0x01) == 0) |
111 | if(counter++==256) | 124 | if (counter++ == 256) |
112 | break; | 125 | break; |
113 | 126 | ||
114 | while((inb(data_port)&0x01)!=0) | 127 | while ((inb(dev->data) & 0x01) != 0) |
115 | if(counter++==256) | 128 | if (counter++ == 256) |
116 | break; | 129 | break; |
117 | 130 | ||
118 | for(i=0;i<12;i++) | 131 | for (i = 0; i < 12; i++) { |
119 | { | 132 | char st = inb(dev->data); |
120 | char st=inb(data_port); | 133 | |
121 | if((st&2)!=0) | 134 | if ((st & 2) != 0) |
122 | return -1; | 135 | return -1; |
123 | if((st&1)==0) | 136 | if ((st & 1) == 0) |
124 | break; | 137 | break; |
125 | } | 138 | } |
126 | outb(0x29, io_port); | 139 | outb(0x29, dev->io); |
127 | return inb(data_port); | 140 | return inb(dev->data); |
128 | } | 141 | } |
129 | 142 | ||
130 | static int pms_i2c_write(u16 slave, u16 sub, u16 data) | 143 | static int pms_i2c_write(struct pms *dev, u16 slave, u16 sub, u16 data) |
131 | { | 144 | { |
132 | int skip=0; | 145 | int skip = 0; |
133 | int count; | 146 | int count; |
134 | int i; | 147 | int i; |
135 | 148 | ||
136 | for(i=0;i<i2c_count;i++) | 149 | for (i = 0; i < dev->i2c_count; i++) { |
137 | { | 150 | if ((dev->i2cinfo[i].slave == slave) && |
138 | if((i2cinfo[i].slave==slave) && | 151 | (dev->i2cinfo[i].sub == sub)) { |
139 | (i2cinfo[i].sub == sub)) | 152 | if (dev->i2cinfo[i].data == data) |
140 | { | 153 | skip = 1; |
141 | if(i2cinfo[i].data==data) | 154 | dev->i2cinfo[i].data = data; |
142 | skip=1; | 155 | i = dev->i2c_count + 1; |
143 | i2cinfo[i].data=data; | ||
144 | i=i2c_count+1; | ||
145 | } | 156 | } |
146 | } | 157 | } |
147 | 158 | ||
148 | if(i==i2c_count && i2c_count<64) | 159 | if (i == dev->i2c_count && dev->i2c_count < 64) { |
149 | { | 160 | dev->i2cinfo[dev->i2c_count].slave = slave; |
150 | i2cinfo[i2c_count].slave=slave; | 161 | dev->i2cinfo[dev->i2c_count].sub = sub; |
151 | i2cinfo[i2c_count].sub=sub; | 162 | dev->i2cinfo[dev->i2c_count].data = data; |
152 | i2cinfo[i2c_count].data=data; | 163 | dev->i2c_count++; |
153 | i2c_count++; | ||
154 | } | 164 | } |
155 | 165 | ||
156 | if(skip) | 166 | if (skip) |
157 | return 0; | 167 | return 0; |
158 | 168 | ||
159 | mvv_write(0x29, sub); | 169 | mvv_write(dev, 0x29, sub); |
160 | mvv_write(0x2A, data); | 170 | mvv_write(dev, 0x2A, data); |
161 | mvv_write(0x28, slave); | 171 | mvv_write(dev, 0x28, slave); |
162 | 172 | ||
163 | outb(0x28, io_port); | 173 | outb(0x28, dev->io); |
164 | 174 | ||
165 | count=0; | 175 | count = 0; |
166 | while((inb(data_port)&1)==0) | 176 | while ((inb(dev->data) & 1) == 0) |
167 | if(count>255) | 177 | if (count > 255) |
168 | break; | 178 | break; |
169 | while((inb(data_port)&1)!=0) | 179 | while ((inb(dev->data) & 1) != 0) |
170 | if(count>255) | 180 | if (count > 255) |
171 | break; | 181 | break; |
172 | 182 | ||
173 | count=inb(data_port); | 183 | count = inb(dev->data); |
174 | 184 | ||
175 | if(count&2) | 185 | if (count & 2) |
176 | return -1; | 186 | return -1; |
177 | return count; | 187 | return count; |
178 | } | 188 | } |
179 | 189 | ||
180 | static int pms_i2c_read(int slave, int sub) | 190 | static int pms_i2c_read(struct pms *dev, int slave, int sub) |
181 | { | 191 | { |
182 | int i=0; | 192 | int i; |
183 | for(i=0;i<i2c_count;i++) | 193 | |
184 | { | 194 | for (i = 0; i < dev->i2c_count; i++) { |
185 | if(i2cinfo[i].slave==slave && i2cinfo[i].sub==sub) | 195 | if (dev->i2cinfo[i].slave == slave && dev->i2cinfo[i].sub == sub) |
186 | return i2cinfo[i].data; | 196 | return dev->i2cinfo[i].data; |
187 | } | 197 | } |
188 | return 0; | 198 | return 0; |
189 | } | 199 | } |
190 | 200 | ||
191 | 201 | ||
192 | static void pms_i2c_andor(int slave, int sub, int and, int or) | 202 | static void pms_i2c_andor(struct pms *dev, int slave, int sub, int and, int or) |
193 | { | 203 | { |
194 | u8 tmp; | 204 | u8 tmp; |
195 | 205 | ||
196 | tmp=pms_i2c_read(slave, sub); | 206 | tmp = pms_i2c_read(dev, slave, sub); |
197 | tmp = (tmp&and)|or; | 207 | tmp = (tmp & and) | or; |
198 | pms_i2c_write(slave, sub, tmp); | 208 | pms_i2c_write(dev, slave, sub, tmp); |
199 | } | 209 | } |
200 | 210 | ||
201 | /* | 211 | /* |
@@ -203,100 +213,108 @@ static void pms_i2c_andor(int slave, int sub, int and, int or) | |||
203 | */ | 213 | */ |
204 | 214 | ||
205 | 215 | ||
206 | static void pms_videosource(short source) | 216 | static void pms_videosource(struct pms *dev, short source) |
207 | { | 217 | { |
208 | mvv_write(0x2E, source?0x31:0x30); | 218 | switch (dev->decoder) { |
219 | case MOTOROLA: | ||
220 | break; | ||
221 | case PHILIPS2: | ||
222 | pms_i2c_andor(dev, 0x8a, 0x06, 0x7f, source ? 0x80 : 0); | ||
223 | break; | ||
224 | case PHILIPS1: | ||
225 | break; | ||
226 | } | ||
227 | mvv_write(dev, 0x2E, 0x31); | ||
228 | /* Was: mvv_write(dev, 0x2E, source ? 0x31 : 0x30); | ||
229 | But could not make this work correctly. Only Composite input | ||
230 | worked for me. */ | ||
209 | } | 231 | } |
210 | 232 | ||
211 | static void pms_hue(short hue) | 233 | static void pms_hue(struct pms *dev, short hue) |
212 | { | 234 | { |
213 | switch(decoder) | 235 | switch (dev->decoder) { |
214 | { | 236 | case MOTOROLA: |
215 | case MOTOROLA: | 237 | pms_i2c_write(dev, 0x8a, 0x00, hue); |
216 | pms_i2c_write(0x8A, 0x00, hue); | 238 | break; |
217 | break; | 239 | case PHILIPS2: |
218 | case PHILIPS2: | 240 | pms_i2c_write(dev, 0x8a, 0x07, hue); |
219 | pms_i2c_write(0x8A, 0x07, hue); | 241 | break; |
220 | break; | 242 | case PHILIPS1: |
221 | case PHILIPS1: | 243 | pms_i2c_write(dev, 0x42, 0x07, hue); |
222 | pms_i2c_write(0x42, 0x07, hue); | 244 | break; |
223 | break; | ||
224 | } | 245 | } |
225 | } | 246 | } |
226 | 247 | ||
227 | static void pms_colour(short colour) | 248 | static void pms_saturation(struct pms *dev, short sat) |
228 | { | 249 | { |
229 | switch(decoder) | 250 | switch (dev->decoder) { |
230 | { | 251 | case MOTOROLA: |
231 | case MOTOROLA: | 252 | pms_i2c_write(dev, 0x8a, 0x00, sat); |
232 | pms_i2c_write(0x8A, 0x00, colour); | 253 | break; |
233 | break; | 254 | case PHILIPS1: |
234 | case PHILIPS1: | 255 | pms_i2c_write(dev, 0x42, 0x12, sat); |
235 | pms_i2c_write(0x42, 0x12, colour); | 256 | break; |
236 | break; | ||
237 | } | 257 | } |
238 | } | 258 | } |
239 | 259 | ||
240 | 260 | ||
241 | static void pms_contrast(short contrast) | 261 | static void pms_contrast(struct pms *dev, short contrast) |
242 | { | 262 | { |
243 | switch(decoder) | 263 | switch (dev->decoder) { |
244 | { | 264 | case MOTOROLA: |
245 | case MOTOROLA: | 265 | pms_i2c_write(dev, 0x8a, 0x00, contrast); |
246 | pms_i2c_write(0x8A, 0x00, contrast); | 266 | break; |
247 | break; | 267 | case PHILIPS1: |
248 | case PHILIPS1: | 268 | pms_i2c_write(dev, 0x42, 0x13, contrast); |
249 | pms_i2c_write(0x42, 0x13, contrast); | 269 | break; |
250 | break; | ||
251 | } | 270 | } |
252 | } | 271 | } |
253 | 272 | ||
254 | static void pms_brightness(short brightness) | 273 | static void pms_brightness(struct pms *dev, short brightness) |
255 | { | 274 | { |
256 | switch(decoder) | 275 | switch (dev->decoder) { |
257 | { | 276 | case MOTOROLA: |
258 | case MOTOROLA: | 277 | pms_i2c_write(dev, 0x8a, 0x00, brightness); |
259 | pms_i2c_write(0x8A, 0x00, brightness); | 278 | pms_i2c_write(dev, 0x8a, 0x00, brightness); |
260 | pms_i2c_write(0x8A, 0x00, brightness); | 279 | pms_i2c_write(dev, 0x8a, 0x00, brightness); |
261 | pms_i2c_write(0x8A, 0x00, brightness); | 280 | break; |
262 | break; | 281 | case PHILIPS1: |
263 | case PHILIPS1: | 282 | pms_i2c_write(dev, 0x42, 0x19, brightness); |
264 | pms_i2c_write(0x42, 0x19, brightness); | 283 | break; |
265 | break; | ||
266 | } | 284 | } |
267 | } | 285 | } |
268 | 286 | ||
269 | 287 | ||
270 | static void pms_format(short format) | 288 | static void pms_format(struct pms *dev, short format) |
271 | { | 289 | { |
272 | int target; | 290 | int target; |
273 | standard = format; | ||
274 | 291 | ||
275 | if(decoder==PHILIPS1) | 292 | dev->standard = format; |
276 | target=0x42; | 293 | |
277 | else if(decoder==PHILIPS2) | 294 | if (dev->decoder == PHILIPS1) |
278 | target=0x8A; | 295 | target = 0x42; |
296 | else if (dev->decoder == PHILIPS2) | ||
297 | target = 0x8a; | ||
279 | else | 298 | else |
280 | return; | 299 | return; |
281 | 300 | ||
282 | switch(format) | 301 | switch (format) { |
283 | { | 302 | case 0: /* Auto */ |
284 | case 0: /* Auto */ | 303 | pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00); |
285 | pms_i2c_andor(target, 0x0D, 0xFE,0x00); | 304 | pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x80); |
286 | pms_i2c_andor(target, 0x0F, 0x3F,0x80); | 305 | break; |
287 | break; | 306 | case 1: /* NTSC */ |
288 | case 1: /* NTSC */ | 307 | pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00); |
289 | pms_i2c_andor(target, 0x0D, 0xFE, 0x00); | 308 | pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x40); |
290 | pms_i2c_andor(target, 0x0F, 0x3F, 0x40); | 309 | break; |
291 | break; | 310 | case 2: /* PAL */ |
292 | case 2: /* PAL */ | 311 | pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00); |
293 | pms_i2c_andor(target, 0x0D, 0xFE, 0x00); | 312 | pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00); |
294 | pms_i2c_andor(target, 0x0F, 0x3F, 0x00); | 313 | break; |
295 | break; | 314 | case 3: /* SECAM */ |
296 | case 3: /* SECAM */ | 315 | pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x01); |
297 | pms_i2c_andor(target, 0x0D, 0xFE, 0x01); | 316 | pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00); |
298 | pms_i2c_andor(target, 0x0F, 0x3F, 0x00); | 317 | break; |
299 | break; | ||
300 | } | 318 | } |
301 | } | 319 | } |
302 | 320 | ||
@@ -308,18 +326,17 @@ static void pms_format(short format) | |||
308 | * people need it. We also don't yet use the PMS interrupt. | 326 | * people need it. We also don't yet use the PMS interrupt. |
309 | */ | 327 | */ |
310 | 328 | ||
311 | static void pms_hstart(short start) | 329 | static void pms_hstart(struct pms *dev, short start) |
312 | { | 330 | { |
313 | switch(decoder) | 331 | switch (dev->decoder) { |
314 | { | 332 | case PHILIPS1: |
315 | case PHILIPS1: | 333 | pms_i2c_write(dev, 0x8a, 0x05, start); |
316 | pms_i2c_write(0x8A, 0x05, start); | 334 | pms_i2c_write(dev, 0x8a, 0x18, start); |
317 | pms_i2c_write(0x8A, 0x18, start); | 335 | break; |
318 | break; | 336 | case PHILIPS2: |
319 | case PHILIPS2: | 337 | pms_i2c_write(dev, 0x42, 0x05, start); |
320 | pms_i2c_write(0x42, 0x05, start); | 338 | pms_i2c_write(dev, 0x42, 0x18, start); |
321 | pms_i2c_write(0x42, 0x18, start); | 339 | break; |
322 | break; | ||
323 | } | 340 | } |
324 | } | 341 | } |
325 | 342 | ||
@@ -327,293 +344,271 @@ static void pms_hstart(short start) | |||
327 | * Bandpass filters | 344 | * Bandpass filters |
328 | */ | 345 | */ |
329 | 346 | ||
330 | static void pms_bandpass(short pass) | 347 | static void pms_bandpass(struct pms *dev, short pass) |
331 | { | 348 | { |
332 | if(decoder==PHILIPS2) | 349 | if (dev->decoder == PHILIPS2) |
333 | pms_i2c_andor(0x8A, 0x06, 0xCF, (pass&0x03)<<4); | 350 | pms_i2c_andor(dev, 0x8a, 0x06, 0xcf, (pass & 0x03) << 4); |
334 | else if(decoder==PHILIPS1) | 351 | else if (dev->decoder == PHILIPS1) |
335 | pms_i2c_andor(0x42, 0x06, 0xCF, (pass&0x03)<<4); | 352 | pms_i2c_andor(dev, 0x42, 0x06, 0xcf, (pass & 0x03) << 4); |
336 | } | 353 | } |
337 | 354 | ||
338 | static void pms_antisnow(short snow) | 355 | static void pms_antisnow(struct pms *dev, short snow) |
339 | { | 356 | { |
340 | if(decoder==PHILIPS2) | 357 | if (dev->decoder == PHILIPS2) |
341 | pms_i2c_andor(0x8A, 0x06, 0xF3, (snow&0x03)<<2); | 358 | pms_i2c_andor(dev, 0x8a, 0x06, 0xf3, (snow & 0x03) << 2); |
342 | else if(decoder==PHILIPS1) | 359 | else if (dev->decoder == PHILIPS1) |
343 | pms_i2c_andor(0x42, 0x06, 0xF3, (snow&0x03)<<2); | 360 | pms_i2c_andor(dev, 0x42, 0x06, 0xf3, (snow & 0x03) << 2); |
344 | } | 361 | } |
345 | 362 | ||
346 | static void pms_sharpness(short sharp) | 363 | static void pms_sharpness(struct pms *dev, short sharp) |
347 | { | 364 | { |
348 | if(decoder==PHILIPS2) | 365 | if (dev->decoder == PHILIPS2) |
349 | pms_i2c_andor(0x8A, 0x06, 0xFC, sharp&0x03); | 366 | pms_i2c_andor(dev, 0x8a, 0x06, 0xfc, sharp & 0x03); |
350 | else if(decoder==PHILIPS1) | 367 | else if (dev->decoder == PHILIPS1) |
351 | pms_i2c_andor(0x42, 0x06, 0xFC, sharp&0x03); | 368 | pms_i2c_andor(dev, 0x42, 0x06, 0xfc, sharp & 0x03); |
352 | } | 369 | } |
353 | 370 | ||
354 | static void pms_chromaagc(short agc) | 371 | static void pms_chromaagc(struct pms *dev, short agc) |
355 | { | 372 | { |
356 | if(decoder==PHILIPS2) | 373 | if (dev->decoder == PHILIPS2) |
357 | pms_i2c_andor(0x8A, 0x0C, 0x9F, (agc&0x03)<<5); | 374 | pms_i2c_andor(dev, 0x8a, 0x0c, 0x9f, (agc & 0x03) << 5); |
358 | else if(decoder==PHILIPS1) | 375 | else if (dev->decoder == PHILIPS1) |
359 | pms_i2c_andor(0x42, 0x0C, 0x9F, (agc&0x03)<<5); | 376 | pms_i2c_andor(dev, 0x42, 0x0c, 0x9f, (agc & 0x03) << 5); |
360 | } | 377 | } |
361 | 378 | ||
362 | static void pms_vertnoise(short noise) | 379 | static void pms_vertnoise(struct pms *dev, short noise) |
363 | { | 380 | { |
364 | if(decoder==PHILIPS2) | 381 | if (dev->decoder == PHILIPS2) |
365 | pms_i2c_andor(0x8A, 0x10, 0xFC, noise&3); | 382 | pms_i2c_andor(dev, 0x8a, 0x10, 0xfc, noise & 3); |
366 | else if(decoder==PHILIPS1) | 383 | else if (dev->decoder == PHILIPS1) |
367 | pms_i2c_andor(0x42, 0x10, 0xFC, noise&3); | 384 | pms_i2c_andor(dev, 0x42, 0x10, 0xfc, noise & 3); |
368 | } | 385 | } |
369 | 386 | ||
370 | static void pms_forcecolour(short colour) | 387 | static void pms_forcecolour(struct pms *dev, short colour) |
371 | { | 388 | { |
372 | if(decoder==PHILIPS2) | 389 | if (dev->decoder == PHILIPS2) |
373 | pms_i2c_andor(0x8A, 0x0C, 0x7F, (colour&1)<<7); | 390 | pms_i2c_andor(dev, 0x8a, 0x0c, 0x7f, (colour & 1) << 7); |
374 | else if(decoder==PHILIPS1) | 391 | else if (dev->decoder == PHILIPS1) |
375 | pms_i2c_andor(0x42, 0x0C, 0x7, (colour&1)<<7); | 392 | pms_i2c_andor(dev, 0x42, 0x0c, 0x7, (colour & 1) << 7); |
376 | } | 393 | } |
377 | 394 | ||
378 | static void pms_antigamma(short gamma) | 395 | static void pms_antigamma(struct pms *dev, short gamma) |
379 | { | 396 | { |
380 | if(decoder==PHILIPS2) | 397 | if (dev->decoder == PHILIPS2) |
381 | pms_i2c_andor(0xB8, 0x00, 0x7F, (gamma&1)<<7); | 398 | pms_i2c_andor(dev, 0xb8, 0x00, 0x7f, (gamma & 1) << 7); |
382 | else if(decoder==PHILIPS1) | 399 | else if (dev->decoder == PHILIPS1) |
383 | pms_i2c_andor(0x42, 0x20, 0x7, (gamma&1)<<7); | 400 | pms_i2c_andor(dev, 0x42, 0x20, 0x7, (gamma & 1) << 7); |
384 | } | 401 | } |
385 | 402 | ||
386 | static void pms_prefilter(short filter) | 403 | static void pms_prefilter(struct pms *dev, short filter) |
387 | { | 404 | { |
388 | if(decoder==PHILIPS2) | 405 | if (dev->decoder == PHILIPS2) |
389 | pms_i2c_andor(0x8A, 0x06, 0xBF, (filter&1)<<6); | 406 | pms_i2c_andor(dev, 0x8a, 0x06, 0xbf, (filter & 1) << 6); |
390 | else if(decoder==PHILIPS1) | 407 | else if (dev->decoder == PHILIPS1) |
391 | pms_i2c_andor(0x42, 0x06, 0xBF, (filter&1)<<6); | 408 | pms_i2c_andor(dev, 0x42, 0x06, 0xbf, (filter & 1) << 6); |
392 | } | 409 | } |
393 | 410 | ||
394 | static void pms_hfilter(short filter) | 411 | static void pms_hfilter(struct pms *dev, short filter) |
395 | { | 412 | { |
396 | if(decoder==PHILIPS2) | 413 | if (dev->decoder == PHILIPS2) |
397 | pms_i2c_andor(0xB8, 0x04, 0x1F, (filter&7)<<5); | 414 | pms_i2c_andor(dev, 0xb8, 0x04, 0x1f, (filter & 7) << 5); |
398 | else if(decoder==PHILIPS1) | 415 | else if (dev->decoder == PHILIPS1) |
399 | pms_i2c_andor(0x42, 0x24, 0x1F, (filter&7)<<5); | 416 | pms_i2c_andor(dev, 0x42, 0x24, 0x1f, (filter & 7) << 5); |
400 | } | 417 | } |
401 | 418 | ||
402 | static void pms_vfilter(short filter) | 419 | static void pms_vfilter(struct pms *dev, short filter) |
403 | { | 420 | { |
404 | if(decoder==PHILIPS2) | 421 | if (dev->decoder == PHILIPS2) |
405 | pms_i2c_andor(0xB8, 0x08, 0x9F, (filter&3)<<5); | 422 | pms_i2c_andor(dev, 0xb8, 0x08, 0x9f, (filter & 3) << 5); |
406 | else if(decoder==PHILIPS1) | 423 | else if (dev->decoder == PHILIPS1) |
407 | pms_i2c_andor(0x42, 0x28, 0x9F, (filter&3)<<5); | 424 | pms_i2c_andor(dev, 0x42, 0x28, 0x9f, (filter & 3) << 5); |
408 | } | 425 | } |
409 | 426 | ||
410 | static void pms_killcolour(short colour) | 427 | static void pms_killcolour(struct pms *dev, short colour) |
411 | { | 428 | { |
412 | if(decoder==PHILIPS2) | 429 | if (dev->decoder == PHILIPS2) { |
413 | { | 430 | pms_i2c_andor(dev, 0x8a, 0x08, 0x07, (colour & 0x1f) << 3); |
414 | pms_i2c_andor(0x8A, 0x08, 0x07, (colour&0x1F)<<3); | 431 | pms_i2c_andor(dev, 0x8a, 0x09, 0x07, (colour & 0x1f) << 3); |
415 | pms_i2c_andor(0x8A, 0x09, 0x07, (colour&0x1F)<<3); | 432 | } else if (dev->decoder == PHILIPS1) { |
416 | } | 433 | pms_i2c_andor(dev, 0x42, 0x08, 0x07, (colour & 0x1f) << 3); |
417 | else if(decoder==PHILIPS1) | 434 | pms_i2c_andor(dev, 0x42, 0x09, 0x07, (colour & 0x1f) << 3); |
418 | { | ||
419 | pms_i2c_andor(0x42, 0x08, 0x07, (colour&0x1F)<<3); | ||
420 | pms_i2c_andor(0x42, 0x09, 0x07, (colour&0x1F)<<3); | ||
421 | } | 435 | } |
422 | } | 436 | } |
423 | 437 | ||
424 | static void pms_chromagain(short chroma) | 438 | static void pms_chromagain(struct pms *dev, short chroma) |
425 | { | 439 | { |
426 | if(decoder==PHILIPS2) | 440 | if (dev->decoder == PHILIPS2) |
427 | { | 441 | pms_i2c_write(dev, 0x8a, 0x11, chroma); |
428 | pms_i2c_write(0x8A, 0x11, chroma); | 442 | else if (dev->decoder == PHILIPS1) |
429 | } | 443 | pms_i2c_write(dev, 0x42, 0x11, chroma); |
430 | else if(decoder==PHILIPS1) | ||
431 | { | ||
432 | pms_i2c_write(0x42, 0x11, chroma); | ||
433 | } | ||
434 | } | 444 | } |
435 | 445 | ||
436 | 446 | ||
437 | static void pms_spacialcompl(short data) | 447 | static void pms_spacialcompl(struct pms *dev, short data) |
438 | { | 448 | { |
439 | mvv_write(0x3B, data); | 449 | mvv_write(dev, 0x3b, data); |
440 | } | 450 | } |
441 | 451 | ||
442 | static void pms_spacialcomph(short data) | 452 | static void pms_spacialcomph(struct pms *dev, short data) |
443 | { | 453 | { |
444 | mvv_write(0x3A, data); | 454 | mvv_write(dev, 0x3a, data); |
445 | } | 455 | } |
446 | 456 | ||
447 | static void pms_vstart(short start) | 457 | static void pms_vstart(struct pms *dev, short start) |
448 | { | 458 | { |
449 | mvv_write(0x16, start); | 459 | mvv_write(dev, 0x16, start); |
450 | mvv_write(0x17, (start>>8)&0x01); | 460 | mvv_write(dev, 0x17, (start >> 8) & 0x01); |
451 | } | 461 | } |
452 | 462 | ||
453 | #endif | 463 | #endif |
454 | 464 | ||
455 | static void pms_secamcross(short cross) | 465 | static void pms_secamcross(struct pms *dev, short cross) |
456 | { | 466 | { |
457 | if(decoder==PHILIPS2) | 467 | if (dev->decoder == PHILIPS2) |
458 | pms_i2c_andor(0x8A, 0x0F, 0xDF, (cross&1)<<5); | 468 | pms_i2c_andor(dev, 0x8a, 0x0f, 0xdf, (cross & 1) << 5); |
459 | else if(decoder==PHILIPS1) | 469 | else if (dev->decoder == PHILIPS1) |
460 | pms_i2c_andor(0x42, 0x0F, 0xDF, (cross&1)<<5); | 470 | pms_i2c_andor(dev, 0x42, 0x0f, 0xdf, (cross & 1) << 5); |
461 | } | 471 | } |
462 | 472 | ||
463 | 473 | ||
464 | static void pms_swsense(short sense) | 474 | static void pms_swsense(struct pms *dev, short sense) |
465 | { | 475 | { |
466 | if(decoder==PHILIPS2) | 476 | if (dev->decoder == PHILIPS2) { |
467 | { | 477 | pms_i2c_write(dev, 0x8a, 0x0a, sense); |
468 | pms_i2c_write(0x8A, 0x0A, sense); | 478 | pms_i2c_write(dev, 0x8a, 0x0b, sense); |
469 | pms_i2c_write(0x8A, 0x0B, sense); | 479 | } else if (dev->decoder == PHILIPS1) { |
470 | } | 480 | pms_i2c_write(dev, 0x42, 0x0a, sense); |
471 | else if(decoder==PHILIPS1) | 481 | pms_i2c_write(dev, 0x42, 0x0b, sense); |
472 | { | ||
473 | pms_i2c_write(0x42, 0x0A, sense); | ||
474 | pms_i2c_write(0x42, 0x0B, sense); | ||
475 | } | 482 | } |
476 | } | 483 | } |
477 | 484 | ||
478 | 485 | ||
479 | static void pms_framerate(short frr) | 486 | static void pms_framerate(struct pms *dev, short frr) |
480 | { | 487 | { |
481 | int fps=(standard==1)?30:25; | 488 | int fps = (dev->std & V4L2_STD_525_60) ? 30 : 25; |
482 | if(frr==0) | 489 | |
490 | if (frr == 0) | ||
483 | return; | 491 | return; |
484 | fps=fps/frr; | 492 | fps = fps/frr; |
485 | mvv_write(0x14,0x80|fps); | 493 | mvv_write(dev, 0x14, 0x80 | fps); |
486 | mvv_write(0x15,1); | 494 | mvv_write(dev, 0x15, 1); |
487 | } | 495 | } |
488 | 496 | ||
489 | static void pms_vert(u8 deciden, u8 decinum) | 497 | static void pms_vert(struct pms *dev, u8 deciden, u8 decinum) |
490 | { | 498 | { |
491 | mvv_write(0x1C, deciden); /* Denominator */ | 499 | mvv_write(dev, 0x1c, deciden); /* Denominator */ |
492 | mvv_write(0x1D, decinum); /* Numerator */ | 500 | mvv_write(dev, 0x1d, decinum); /* Numerator */ |
493 | } | 501 | } |
494 | 502 | ||
495 | /* | 503 | /* |
496 | * Turn 16bit ratios into best small ratio the chipset can grok | 504 | * Turn 16bit ratios into best small ratio the chipset can grok |
497 | */ | 505 | */ |
498 | 506 | ||
499 | static void pms_vertdeci(unsigned short decinum, unsigned short deciden) | 507 | static void pms_vertdeci(struct pms *dev, unsigned short decinum, unsigned short deciden) |
500 | { | 508 | { |
501 | /* Knock it down by /5 once */ | 509 | /* Knock it down by / 5 once */ |
502 | if(decinum%5==0) | 510 | if (decinum % 5 == 0) { |
503 | { | 511 | deciden /= 5; |
504 | deciden/=5; | 512 | decinum /= 5; |
505 | decinum/=5; | ||
506 | } | 513 | } |
507 | /* | 514 | /* |
508 | * 3's | 515 | * 3's |
509 | */ | 516 | */ |
510 | while(decinum%3==0 && deciden%3==0) | 517 | while (decinum % 3 == 0 && deciden % 3 == 0) { |
511 | { | 518 | deciden /= 3; |
512 | deciden/=3; | 519 | decinum /= 3; |
513 | decinum/=3; | ||
514 | } | 520 | } |
515 | /* | 521 | /* |
516 | * 2's | 522 | * 2's |
517 | */ | 523 | */ |
518 | while(decinum%2==0 && deciden%2==0) | 524 | while (decinum % 2 == 0 && deciden % 2 == 0) { |
519 | { | 525 | decinum /= 2; |
520 | decinum/=2; | 526 | deciden /= 2; |
521 | deciden/=2; | ||
522 | } | 527 | } |
523 | /* | 528 | /* |
524 | * Fudgyify | 529 | * Fudgyify |
525 | */ | 530 | */ |
526 | while(deciden>32) | 531 | while (deciden > 32) { |
527 | { | 532 | deciden /= 2; |
528 | deciden/=2; | 533 | decinum = (decinum + 1) / 2; |
529 | decinum=(decinum+1)/2; | ||
530 | } | 534 | } |
531 | if(deciden==32) | 535 | if (deciden == 32) |
532 | deciden--; | 536 | deciden--; |
533 | pms_vert(deciden,decinum); | 537 | pms_vert(dev, deciden, decinum); |
534 | } | 538 | } |
535 | 539 | ||
536 | static void pms_horzdeci(short decinum, short deciden) | 540 | static void pms_horzdeci(struct pms *dev, short decinum, short deciden) |
537 | { | 541 | { |
538 | if(decinum<=512) | 542 | if (decinum <= 512) { |
539 | { | 543 | if (decinum % 5 == 0) { |
540 | if(decinum%5==0) | 544 | decinum /= 5; |
541 | { | 545 | deciden /= 5; |
542 | decinum/=5; | ||
543 | deciden/=5; | ||
544 | } | 546 | } |
545 | } | 547 | } else { |
546 | else | 548 | decinum = 512; |
547 | { | 549 | deciden = 640; /* 768 would be ideal */ |
548 | decinum=512; | ||
549 | deciden=640; /* 768 would be ideal */ | ||
550 | } | 550 | } |
551 | 551 | ||
552 | while(((decinum|deciden)&1)==0) | 552 | while (((decinum | deciden) & 1) == 0) { |
553 | { | 553 | decinum >>= 1; |
554 | decinum>>=1; | 554 | deciden >>= 1; |
555 | deciden>>=1; | ||
556 | } | 555 | } |
557 | while(deciden>32) | 556 | while (deciden > 32) { |
558 | { | 557 | deciden >>= 1; |
559 | deciden>>=1; | 558 | decinum = (decinum + 1) >> 1; |
560 | decinum=(decinum+1)>>1; | ||
561 | } | 559 | } |
562 | if(deciden==32) | 560 | if (deciden == 32) |
563 | deciden--; | 561 | deciden--; |
564 | 562 | ||
565 | mvv_write(0x24, 0x80|deciden); | 563 | mvv_write(dev, 0x24, 0x80 | deciden); |
566 | mvv_write(0x25, decinum); | 564 | mvv_write(dev, 0x25, decinum); |
567 | } | 565 | } |
568 | 566 | ||
569 | static void pms_resolution(short width, short height) | 567 | static void pms_resolution(struct pms *dev, short width, short height) |
570 | { | 568 | { |
571 | int fg_height; | 569 | int fg_height; |
572 | 570 | ||
573 | fg_height=height; | 571 | fg_height = height; |
574 | if(fg_height>280) | 572 | if (fg_height > 280) |
575 | fg_height=280; | 573 | fg_height = 280; |
576 | 574 | ||
577 | mvv_write(0x18, fg_height); | 575 | mvv_write(dev, 0x18, fg_height); |
578 | mvv_write(0x19, fg_height>>8); | 576 | mvv_write(dev, 0x19, fg_height >> 8); |
579 | 577 | ||
580 | if(standard==1) | 578 | if (dev->std & V4L2_STD_525_60) { |
581 | { | 579 | mvv_write(dev, 0x1a, 0xfc); |
582 | mvv_write(0x1A, 0xFC); | 580 | mvv_write(dev, 0x1b, 0x00); |
583 | mvv_write(0x1B, 0x00); | 581 | if (height > fg_height) |
584 | if(height>fg_height) | 582 | pms_vertdeci(dev, 240, 240); |
585 | pms_vertdeci(240,240); | ||
586 | else | 583 | else |
587 | pms_vertdeci(fg_height,240); | 584 | pms_vertdeci(dev, fg_height, 240); |
588 | } | 585 | } else { |
589 | else | 586 | mvv_write(dev, 0x1a, 0x1a); |
590 | { | 587 | mvv_write(dev, 0x1b, 0x01); |
591 | mvv_write(0x1A, 0x1A); | 588 | if (fg_height > 256) |
592 | mvv_write(0x1B, 0x01); | 589 | pms_vertdeci(dev, 270, 270); |
593 | if(fg_height>256) | ||
594 | pms_vertdeci(270,270); | ||
595 | else | 590 | else |
596 | pms_vertdeci(fg_height, 270); | 591 | pms_vertdeci(dev, fg_height, 270); |
597 | } | 592 | } |
598 | mvv_write(0x12,0); | 593 | mvv_write(dev, 0x12, 0); |
599 | mvv_write(0x13, MVVMEMORYWIDTH); | 594 | mvv_write(dev, 0x13, MVVMEMORYWIDTH); |
600 | mvv_write(0x42, 0x00); | 595 | mvv_write(dev, 0x42, 0x00); |
601 | mvv_write(0x43, 0x00); | 596 | mvv_write(dev, 0x43, 0x00); |
602 | mvv_write(0x44, MVVMEMORYWIDTH); | 597 | mvv_write(dev, 0x44, MVVMEMORYWIDTH); |
603 | 598 | ||
604 | mvv_write(0x22, width+8); | 599 | mvv_write(dev, 0x22, width + 8); |
605 | mvv_write(0x23, (width+8)>> 8); | 600 | mvv_write(dev, 0x23, (width + 8) >> 8); |
606 | 601 | ||
607 | if(standard==1) | 602 | if (dev->std & V4L2_STD_525_60) |
608 | pms_horzdeci(width,640); | 603 | pms_horzdeci(dev, width, 640); |
609 | else | 604 | else |
610 | pms_horzdeci(width+8, 768); | 605 | pms_horzdeci(dev, width + 8, 768); |
611 | 606 | ||
612 | mvv_write(0x30, mvv_read(0x30)&0xFE); | 607 | mvv_write(dev, 0x30, mvv_read(dev, 0x30) & 0xfe); |
613 | mvv_write(0x08, mvv_read(0x08)|0x01); | 608 | mvv_write(dev, 0x08, mvv_read(dev, 0x08) | 0x01); |
614 | mvv_write(0x01, mvv_read(0x01)&0xFD); | 609 | mvv_write(dev, 0x01, mvv_read(dev, 0x01) & 0xfd); |
615 | mvv_write(0x32, 0x00); | 610 | mvv_write(dev, 0x32, 0x00); |
616 | mvv_write(0x33, MVVMEMORYWIDTH); | 611 | mvv_write(dev, 0x33, MVVMEMORYWIDTH); |
617 | } | 612 | } |
618 | 613 | ||
619 | 614 | ||
@@ -621,52 +616,49 @@ static void pms_resolution(short width, short height) | |||
621 | * Set Input | 616 | * Set Input |
622 | */ | 617 | */ |
623 | 618 | ||
624 | static void pms_vcrinput(short input) | 619 | static void pms_vcrinput(struct pms *dev, short input) |
625 | { | 620 | { |
626 | if(decoder==PHILIPS2) | 621 | if (dev->decoder == PHILIPS2) |
627 | pms_i2c_andor(0x8A,0x0D,0x7F,(input&1)<<7); | 622 | pms_i2c_andor(dev, 0x8a, 0x0d, 0x7f, (input & 1) << 7); |
628 | else if(decoder==PHILIPS1) | 623 | else if (dev->decoder == PHILIPS1) |
629 | pms_i2c_andor(0x42,0x0D,0x7F,(input&1)<<7); | 624 | pms_i2c_andor(dev, 0x42, 0x0d, 0x7f, (input & 1) << 7); |
630 | } | 625 | } |
631 | 626 | ||
632 | 627 | ||
633 | static int pms_capture(struct pms_device *dev, char __user *buf, int rgb555, int count) | 628 | static int pms_capture(struct pms *dev, char __user *buf, int rgb555, int count) |
634 | { | 629 | { |
635 | int y; | 630 | int y; |
636 | int dw = 2*dev->width; | 631 | int dw = 2 * dev->width; |
637 | 632 | char tmp[dw + 32]; /* using a temp buffer is faster than direct */ | |
638 | char tmp[dw+32]; /* using a temp buffer is faster than direct */ | ||
639 | int cnt = 0; | 633 | int cnt = 0; |
640 | int len=0; | 634 | int len = 0; |
641 | unsigned char r8 = 0x5; /* value for reg8 */ | 635 | unsigned char r8 = 0x5; /* value for reg8 */ |
642 | 636 | ||
643 | if (rgb555) | 637 | if (rgb555) |
644 | r8 |= 0x20; /* else use untranslated rgb = 565 */ | 638 | r8 |= 0x20; /* else use untranslated rgb = 565 */ |
645 | mvv_write(0x08,r8); /* capture rgb555/565, init DRAM, PC enable */ | 639 | mvv_write(dev, 0x08, r8); /* capture rgb555/565, init DRAM, PC enable */ |
646 | 640 | ||
647 | /* printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */ | 641 | /* printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */ |
648 | 642 | ||
649 | for (y = 0; y < dev->height; y++ ) | 643 | for (y = 0; y < dev->height; y++) { |
650 | { | 644 | writeb(0, dev->mem); /* synchronisiert neue Zeile */ |
651 | writeb(0, mem); /* synchronisiert neue Zeile */ | ||
652 | 645 | ||
653 | /* | 646 | /* |
654 | * This is in truth a fifo, be very careful as if you | 647 | * This is in truth a fifo, be very careful as if you |
655 | * forgot this odd things will occur 8) | 648 | * forgot this odd things will occur 8) |
656 | */ | 649 | */ |
657 | 650 | ||
658 | memcpy_fromio(tmp, mem, dw+32); /* discard 16 word */ | 651 | memcpy_fromio(tmp, dev->mem, dw + 32); /* discard 16 word */ |
659 | cnt -= dev->height; | 652 | cnt -= dev->height; |
660 | while (cnt <= 0) | 653 | while (cnt <= 0) { |
661 | { | ||
662 | /* | 654 | /* |
663 | * Don't copy too far | 655 | * Don't copy too far |
664 | */ | 656 | */ |
665 | int dt=dw; | 657 | int dt = dw; |
666 | if(dt+len>count) | 658 | if (dt + len > count) |
667 | dt=count-len; | 659 | dt = count - len; |
668 | cnt += dev->height; | 660 | cnt += dev->height; |
669 | if (copy_to_user(buf, tmp+32, dt)) | 661 | if (copy_to_user(buf, tmp + 32, dt)) |
670 | return len ? len : -EFAULT; | 662 | return len ? len : -EFAULT; |
671 | buf += dt; | 663 | buf += dt; |
672 | len += dt; | 664 | len += dt; |
@@ -680,221 +672,278 @@ static int pms_capture(struct pms_device *dev, char __user *buf, int rgb555, int | |||
680 | * Video4linux interfacing | 672 | * Video4linux interfacing |
681 | */ | 673 | */ |
682 | 674 | ||
683 | static long pms_do_ioctl(struct file *file, unsigned int cmd, void *arg) | 675 | static int pms_querycap(struct file *file, void *priv, |
676 | struct v4l2_capability *vcap) | ||
684 | { | 677 | { |
685 | struct video_device *dev = video_devdata(file); | 678 | struct pms *dev = video_drvdata(file); |
686 | struct pms_device *pd=(struct pms_device *)dev; | ||
687 | |||
688 | switch(cmd) | ||
689 | { | ||
690 | case VIDIOCGCAP: | ||
691 | { | ||
692 | struct video_capability *b = arg; | ||
693 | strcpy(b->name, "Mediavision PMS"); | ||
694 | b->type = VID_TYPE_CAPTURE|VID_TYPE_SCALES; | ||
695 | b->channels = 4; | ||
696 | b->audios = 0; | ||
697 | b->maxwidth = 640; | ||
698 | b->maxheight = 480; | ||
699 | b->minwidth = 16; | ||
700 | b->minheight = 16; | ||
701 | return 0; | ||
702 | } | ||
703 | case VIDIOCGCHAN: | ||
704 | { | ||
705 | struct video_channel *v = arg; | ||
706 | if(v->channel<0 || v->channel>3) | ||
707 | return -EINVAL; | ||
708 | v->flags=0; | ||
709 | v->tuners=1; | ||
710 | /* Good question.. its composite or SVHS so.. */ | ||
711 | v->type = VIDEO_TYPE_CAMERA; | ||
712 | switch(v->channel) | ||
713 | { | ||
714 | case 0: | ||
715 | strcpy(v->name, "Composite");break; | ||
716 | case 1: | ||
717 | strcpy(v->name, "SVideo");break; | ||
718 | case 2: | ||
719 | strcpy(v->name, "Composite(VCR)");break; | ||
720 | case 3: | ||
721 | strcpy(v->name, "SVideo(VCR)");break; | ||
722 | } | ||
723 | return 0; | ||
724 | } | ||
725 | case VIDIOCSCHAN: | ||
726 | { | ||
727 | struct video_channel *v = arg; | ||
728 | if(v->channel<0 || v->channel>3) | ||
729 | return -EINVAL; | ||
730 | mutex_lock(&pd->lock); | ||
731 | pms_videosource(v->channel&1); | ||
732 | pms_vcrinput(v->channel>>1); | ||
733 | mutex_unlock(&pd->lock); | ||
734 | return 0; | ||
735 | } | ||
736 | case VIDIOCGTUNER: | ||
737 | { | ||
738 | struct video_tuner *v = arg; | ||
739 | if(v->tuner) | ||
740 | return -EINVAL; | ||
741 | strcpy(v->name, "Format"); | ||
742 | v->rangelow=0; | ||
743 | v->rangehigh=0; | ||
744 | v->flags= VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM; | ||
745 | switch(standard) | ||
746 | { | ||
747 | case 0: | ||
748 | v->mode = VIDEO_MODE_AUTO; | ||
749 | break; | ||
750 | case 1: | ||
751 | v->mode = VIDEO_MODE_NTSC; | ||
752 | break; | ||
753 | case 2: | ||
754 | v->mode = VIDEO_MODE_PAL; | ||
755 | break; | ||
756 | case 3: | ||
757 | v->mode = VIDEO_MODE_SECAM; | ||
758 | break; | ||
759 | } | ||
760 | return 0; | ||
761 | } | ||
762 | case VIDIOCSTUNER: | ||
763 | { | ||
764 | struct video_tuner *v = arg; | ||
765 | if(v->tuner) | ||
766 | return -EINVAL; | ||
767 | mutex_lock(&pd->lock); | ||
768 | switch(v->mode) | ||
769 | { | ||
770 | case VIDEO_MODE_AUTO: | ||
771 | pms_framerate(25); | ||
772 | pms_secamcross(0); | ||
773 | pms_format(0); | ||
774 | break; | ||
775 | case VIDEO_MODE_NTSC: | ||
776 | pms_framerate(30); | ||
777 | pms_secamcross(0); | ||
778 | pms_format(1); | ||
779 | break; | ||
780 | case VIDEO_MODE_PAL: | ||
781 | pms_framerate(25); | ||
782 | pms_secamcross(0); | ||
783 | pms_format(2); | ||
784 | break; | ||
785 | case VIDEO_MODE_SECAM: | ||
786 | pms_framerate(25); | ||
787 | pms_secamcross(1); | ||
788 | pms_format(2); | ||
789 | break; | ||
790 | default: | ||
791 | mutex_unlock(&pd->lock); | ||
792 | return -EINVAL; | ||
793 | } | ||
794 | mutex_unlock(&pd->lock); | ||
795 | return 0; | ||
796 | } | ||
797 | case VIDIOCGPICT: | ||
798 | { | ||
799 | struct video_picture *p = arg; | ||
800 | *p = pd->picture; | ||
801 | return 0; | ||
802 | } | ||
803 | case VIDIOCSPICT: | ||
804 | { | ||
805 | struct video_picture *p = arg; | ||
806 | if(!((p->palette==VIDEO_PALETTE_RGB565 && p->depth==16) | ||
807 | ||(p->palette==VIDEO_PALETTE_RGB555 && p->depth==15))) | ||
808 | return -EINVAL; | ||
809 | pd->picture= *p; | ||
810 | 679 | ||
811 | /* | 680 | strlcpy(vcap->driver, dev->v4l2_dev.name, sizeof(vcap->driver)); |
812 | * Now load the card. | 681 | strlcpy(vcap->card, "Mediavision PMS", sizeof(vcap->card)); |
813 | */ | 682 | strlcpy(vcap->bus_info, "ISA", sizeof(vcap->bus_info)); |
683 | vcap->version = KERNEL_VERSION(0, 0, 3); | ||
684 | vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; | ||
685 | return 0; | ||
686 | } | ||
814 | 687 | ||
815 | mutex_lock(&pd->lock); | 688 | static int pms_enum_input(struct file *file, void *fh, struct v4l2_input *vin) |
816 | pms_brightness(p->brightness>>8); | 689 | { |
817 | pms_hue(p->hue>>8); | 690 | static const char *inputs[4] = { |
818 | pms_colour(p->colour>>8); | 691 | "Composite", |
819 | pms_contrast(p->contrast>>8); | 692 | "S-Video", |
820 | mutex_unlock(&pd->lock); | 693 | "Composite (VCR)", |
821 | return 0; | 694 | "S-Video (VCR)" |
822 | } | 695 | }; |
823 | case VIDIOCSWIN: | 696 | |
824 | { | 697 | if (vin->index > 3) |
825 | struct video_window *vw = arg; | 698 | return -EINVAL; |
826 | if(vw->flags) | 699 | strlcpy(vin->name, inputs[vin->index], sizeof(vin->name)); |
827 | return -EINVAL; | 700 | vin->type = V4L2_INPUT_TYPE_CAMERA; |
828 | if(vw->clipcount) | 701 | vin->audioset = 0; |
829 | return -EINVAL; | 702 | vin->tuner = 0; |
830 | if(vw->height<16||vw->height>480) | 703 | vin->std = V4L2_STD_ALL; |
831 | return -EINVAL; | 704 | vin->status = 0; |
832 | if(vw->width<16||vw->width>640) | 705 | return 0; |
833 | return -EINVAL; | 706 | } |
834 | pd->width=vw->width; | 707 | |
835 | pd->height=vw->height; | 708 | static int pms_g_input(struct file *file, void *fh, unsigned int *inp) |
836 | mutex_lock(&pd->lock); | 709 | { |
837 | pms_resolution(pd->width, pd->height); | 710 | struct pms *dev = video_drvdata(file); |
838 | mutex_unlock(&pd->lock); /* Ok we figured out what to use from our wide choice */ | 711 | |
839 | return 0; | 712 | *inp = dev->input; |
840 | } | 713 | return 0; |
841 | case VIDIOCGWIN: | 714 | } |
842 | { | 715 | |
843 | struct video_window *vw = arg; | 716 | static int pms_s_input(struct file *file, void *fh, unsigned int inp) |
844 | memset(vw,0,sizeof(*vw)); | 717 | { |
845 | vw->width=pd->width; | 718 | struct pms *dev = video_drvdata(file); |
846 | vw->height=pd->height; | 719 | |
847 | return 0; | 720 | if (inp > 3) |
848 | } | 721 | return -EINVAL; |
849 | case VIDIOCKEY: | 722 | |
850 | return 0; | 723 | mutex_lock(&dev->lock); |
851 | case VIDIOCCAPTURE: | 724 | dev->input = inp; |
852 | case VIDIOCGFBUF: | 725 | pms_videosource(dev, inp & 1); |
853 | case VIDIOCSFBUF: | 726 | pms_vcrinput(dev, inp >> 1); |
854 | case VIDIOCGFREQ: | 727 | mutex_unlock(&dev->lock); |
855 | case VIDIOCSFREQ: | 728 | return 0; |
856 | case VIDIOCGAUDIO: | 729 | } |
857 | case VIDIOCSAUDIO: | 730 | |
858 | return -EINVAL; | 731 | static int pms_g_std(struct file *file, void *fh, v4l2_std_id *std) |
859 | default: | 732 | { |
860 | return -ENOIOCTLCMD; | 733 | struct pms *dev = video_drvdata(file); |
734 | |||
735 | *std = dev->std; | ||
736 | return 0; | ||
737 | } | ||
738 | |||
739 | static int pms_s_std(struct file *file, void *fh, v4l2_std_id *std) | ||
740 | { | ||
741 | struct pms *dev = video_drvdata(file); | ||
742 | int ret = 0; | ||
743 | |||
744 | dev->std = *std; | ||
745 | mutex_lock(&dev->lock); | ||
746 | if (dev->std & V4L2_STD_NTSC) { | ||
747 | pms_framerate(dev, 30); | ||
748 | pms_secamcross(dev, 0); | ||
749 | pms_format(dev, 1); | ||
750 | } else if (dev->std & V4L2_STD_PAL) { | ||
751 | pms_framerate(dev, 25); | ||
752 | pms_secamcross(dev, 0); | ||
753 | pms_format(dev, 2); | ||
754 | } else if (dev->std & V4L2_STD_SECAM) { | ||
755 | pms_framerate(dev, 25); | ||
756 | pms_secamcross(dev, 1); | ||
757 | pms_format(dev, 2); | ||
758 | } else { | ||
759 | ret = -EINVAL; | ||
760 | } | ||
761 | /* | ||
762 | switch (v->mode) { | ||
763 | case VIDEO_MODE_AUTO: | ||
764 | pms_framerate(dev, 25); | ||
765 | pms_secamcross(dev, 0); | ||
766 | pms_format(dev, 0); | ||
767 | break; | ||
768 | }*/ | ||
769 | mutex_unlock(&dev->lock); | ||
770 | return 0; | ||
771 | } | ||
772 | |||
773 | static int pms_queryctrl(struct file *file, void *priv, | ||
774 | struct v4l2_queryctrl *qc) | ||
775 | { | ||
776 | switch (qc->id) { | ||
777 | case V4L2_CID_BRIGHTNESS: | ||
778 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 139); | ||
779 | case V4L2_CID_CONTRAST: | ||
780 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 70); | ||
781 | case V4L2_CID_SATURATION: | ||
782 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 64); | ||
783 | case V4L2_CID_HUE: | ||
784 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 0); | ||
785 | } | ||
786 | return -EINVAL; | ||
787 | } | ||
788 | |||
789 | static int pms_g_ctrl(struct file *file, void *priv, | ||
790 | struct v4l2_control *ctrl) | ||
791 | { | ||
792 | struct pms *dev = video_drvdata(file); | ||
793 | int ret = 0; | ||
794 | |||
795 | switch (ctrl->id) { | ||
796 | case V4L2_CID_BRIGHTNESS: | ||
797 | ctrl->value = dev->brightness; | ||
798 | break; | ||
799 | case V4L2_CID_CONTRAST: | ||
800 | ctrl->value = dev->contrast; | ||
801 | break; | ||
802 | case V4L2_CID_SATURATION: | ||
803 | ctrl->value = dev->saturation; | ||
804 | break; | ||
805 | case V4L2_CID_HUE: | ||
806 | ctrl->value = dev->hue; | ||
807 | break; | ||
808 | default: | ||
809 | ret = -EINVAL; | ||
810 | break; | ||
811 | } | ||
812 | return ret; | ||
813 | } | ||
814 | |||
815 | static int pms_s_ctrl(struct file *file, void *priv, | ||
816 | struct v4l2_control *ctrl) | ||
817 | { | ||
818 | struct pms *dev = video_drvdata(file); | ||
819 | int ret = 0; | ||
820 | |||
821 | mutex_lock(&dev->lock); | ||
822 | switch (ctrl->id) { | ||
823 | case V4L2_CID_BRIGHTNESS: | ||
824 | dev->brightness = ctrl->value; | ||
825 | pms_brightness(dev, dev->brightness); | ||
826 | break; | ||
827 | case V4L2_CID_CONTRAST: | ||
828 | dev->contrast = ctrl->value; | ||
829 | pms_contrast(dev, dev->contrast); | ||
830 | break; | ||
831 | case V4L2_CID_SATURATION: | ||
832 | dev->saturation = ctrl->value; | ||
833 | pms_saturation(dev, dev->saturation); | ||
834 | break; | ||
835 | case V4L2_CID_HUE: | ||
836 | dev->hue = ctrl->value; | ||
837 | pms_hue(dev, dev->hue); | ||
838 | break; | ||
839 | default: | ||
840 | ret = -EINVAL; | ||
841 | break; | ||
861 | } | 842 | } |
843 | mutex_unlock(&dev->lock); | ||
844 | return ret; | ||
845 | } | ||
846 | |||
847 | static int pms_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) | ||
848 | { | ||
849 | struct pms *dev = video_drvdata(file); | ||
850 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
851 | |||
852 | pix->width = dev->width; | ||
853 | pix->height = dev->height; | ||
854 | pix->pixelformat = dev->width == 15 ? | ||
855 | V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB565; | ||
856 | pix->field = V4L2_FIELD_NONE; | ||
857 | pix->bytesperline = 2 * dev->width; | ||
858 | pix->sizeimage = 2 * dev->width * dev->height; | ||
859 | /* Just a guess */ | ||
860 | pix->colorspace = V4L2_COLORSPACE_SRGB; | ||
862 | return 0; | 861 | return 0; |
863 | } | 862 | } |
864 | 863 | ||
865 | static long pms_ioctl(struct file *file, | 864 | static int pms_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) |
866 | unsigned int cmd, unsigned long arg) | ||
867 | { | 865 | { |
868 | return video_usercopy(file, cmd, arg, pms_do_ioctl); | 866 | struct v4l2_pix_format *pix = &fmt->fmt.pix; |
867 | |||
868 | if (pix->height < 16 || pix->height > 480) | ||
869 | return -EINVAL; | ||
870 | if (pix->width < 16 || pix->width > 640) | ||
871 | return -EINVAL; | ||
872 | if (pix->pixelformat != V4L2_PIX_FMT_RGB555 && | ||
873 | pix->pixelformat != V4L2_PIX_FMT_RGB565) | ||
874 | return -EINVAL; | ||
875 | pix->field = V4L2_FIELD_NONE; | ||
876 | pix->bytesperline = 2 * pix->width; | ||
877 | pix->sizeimage = 2 * pix->width * pix->height; | ||
878 | /* Just a guess */ | ||
879 | pix->colorspace = V4L2_COLORSPACE_SRGB; | ||
880 | return 0; | ||
881 | } | ||
882 | |||
883 | static int pms_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) | ||
884 | { | ||
885 | struct pms *dev = video_drvdata(file); | ||
886 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
887 | int ret = pms_try_fmt_vid_cap(file, fh, fmt); | ||
888 | |||
889 | if (ret) | ||
890 | return ret; | ||
891 | mutex_lock(&dev->lock); | ||
892 | dev->width = pix->width; | ||
893 | dev->height = pix->height; | ||
894 | dev->depth = (pix->pixelformat == V4L2_PIX_FMT_RGB555) ? 15 : 16; | ||
895 | pms_resolution(dev, dev->width, dev->height); | ||
896 | /* Ok we figured out what to use from our wide choice */ | ||
897 | mutex_unlock(&dev->lock); | ||
898 | return 0; | ||
899 | } | ||
900 | |||
901 | static int pms_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) | ||
902 | { | ||
903 | static struct v4l2_fmtdesc formats[] = { | ||
904 | { 0, 0, 0, | ||
905 | "RGB 5:5:5", V4L2_PIX_FMT_RGB555, | ||
906 | { 0, 0, 0, 0 } | ||
907 | }, | ||
908 | { 0, 0, 0, | ||
909 | "RGB 5:6:5", V4L2_PIX_FMT_RGB565, | ||
910 | { 0, 0, 0, 0 } | ||
911 | }, | ||
912 | }; | ||
913 | enum v4l2_buf_type type = fmt->type; | ||
914 | |||
915 | if (fmt->index > 1) | ||
916 | return -EINVAL; | ||
917 | |||
918 | *fmt = formats[fmt->index]; | ||
919 | fmt->type = type; | ||
920 | return 0; | ||
869 | } | 921 | } |
870 | 922 | ||
871 | static ssize_t pms_read(struct file *file, char __user *buf, | 923 | static ssize_t pms_read(struct file *file, char __user *buf, |
872 | size_t count, loff_t *ppos) | 924 | size_t count, loff_t *ppos) |
873 | { | 925 | { |
874 | struct video_device *v = video_devdata(file); | 926 | struct pms *dev = video_drvdata(file); |
875 | struct pms_device *pd=(struct pms_device *)v; | ||
876 | int len; | 927 | int len; |
877 | 928 | ||
878 | mutex_lock(&pd->lock); | 929 | mutex_lock(&dev->lock); |
879 | len=pms_capture(pd, buf, (pd->picture.depth==16)?0:1,count); | 930 | len = pms_capture(dev, buf, (dev->depth == 15), count); |
880 | mutex_unlock(&pd->lock); | 931 | mutex_unlock(&dev->lock); |
881 | return len; | 932 | return len; |
882 | } | 933 | } |
883 | 934 | ||
884 | static int pms_exclusive_open(struct file *file) | 935 | static int pms_exclusive_open(struct file *file) |
885 | { | 936 | { |
886 | struct video_device *v = video_devdata(file); | 937 | struct pms *dev = video_drvdata(file); |
887 | struct pms_device *pd = (struct pms_device *)v; | ||
888 | 938 | ||
889 | return test_and_set_bit(0, &pd->in_use) ? -EBUSY : 0; | 939 | return test_and_set_bit(0, &dev->in_use) ? -EBUSY : 0; |
890 | } | 940 | } |
891 | 941 | ||
892 | static int pms_exclusive_release(struct file *file) | 942 | static int pms_exclusive_release(struct file *file) |
893 | { | 943 | { |
894 | struct video_device *v = video_devdata(file); | 944 | struct pms *dev = video_drvdata(file); |
895 | struct pms_device *pd = (struct pms_device *)v; | ||
896 | 945 | ||
897 | clear_bit(0, &pd->in_use); | 946 | clear_bit(0, &dev->in_use); |
898 | return 0; | 947 | return 0; |
899 | } | 948 | } |
900 | 949 | ||
@@ -902,78 +951,81 @@ static const struct v4l2_file_operations pms_fops = { | |||
902 | .owner = THIS_MODULE, | 951 | .owner = THIS_MODULE, |
903 | .open = pms_exclusive_open, | 952 | .open = pms_exclusive_open, |
904 | .release = pms_exclusive_release, | 953 | .release = pms_exclusive_release, |
905 | .ioctl = pms_ioctl, | 954 | .ioctl = video_ioctl2, |
906 | .read = pms_read, | 955 | .read = pms_read, |
907 | }; | 956 | }; |
908 | 957 | ||
909 | static struct video_device pms_template= | 958 | static const struct v4l2_ioctl_ops pms_ioctl_ops = { |
910 | { | 959 | .vidioc_querycap = pms_querycap, |
911 | .name = "Mediavision PMS", | 960 | .vidioc_g_input = pms_g_input, |
912 | .fops = &pms_fops, | 961 | .vidioc_s_input = pms_s_input, |
913 | .release = video_device_release_empty, | 962 | .vidioc_enum_input = pms_enum_input, |
963 | .vidioc_g_std = pms_g_std, | ||
964 | .vidioc_s_std = pms_s_std, | ||
965 | .vidioc_queryctrl = pms_queryctrl, | ||
966 | .vidioc_g_ctrl = pms_g_ctrl, | ||
967 | .vidioc_s_ctrl = pms_s_ctrl, | ||
968 | .vidioc_enum_fmt_vid_cap = pms_enum_fmt_vid_cap, | ||
969 | .vidioc_g_fmt_vid_cap = pms_g_fmt_vid_cap, | ||
970 | .vidioc_s_fmt_vid_cap = pms_s_fmt_vid_cap, | ||
971 | .vidioc_try_fmt_vid_cap = pms_try_fmt_vid_cap, | ||
914 | }; | 972 | }; |
915 | 973 | ||
916 | static struct pms_device pms_device; | ||
917 | |||
918 | |||
919 | /* | 974 | /* |
920 | * Probe for and initialise the Mediavision PMS | 975 | * Probe for and initialise the Mediavision PMS |
921 | */ | 976 | */ |
922 | 977 | ||
923 | static int init_mediavision(void) | 978 | static int init_mediavision(struct pms *dev) |
924 | { | 979 | { |
925 | int id; | 980 | int id; |
926 | int idec, decst; | 981 | int idec, decst; |
927 | int i; | 982 | int i; |
928 | 983 | static const unsigned char i2c_defs[] = { | |
929 | unsigned char i2c_defs[]={ | 984 | 0x4c, 0x30, 0x00, 0xe8, |
930 | 0x4C,0x30,0x00,0xE8, | 985 | 0xb6, 0xe2, 0x00, 0x00, |
931 | 0xB6,0xE2,0x00,0x00, | 986 | 0xff, 0xff, 0x00, 0x00, |
932 | 0xFF,0xFF,0x00,0x00, | 987 | 0x00, 0x00, 0x78, 0x98, |
933 | 0x00,0x00,0x78,0x98, | 988 | 0x00, 0x00, 0x00, 0x00, |
934 | 0x00,0x00,0x00,0x00, | 989 | 0x34, 0x0a, 0xf4, 0xce, |
935 | 0x34,0x0A,0xF4,0xCE, | 990 | 0xe4 |
936 | 0xE4 | ||
937 | }; | 991 | }; |
938 | 992 | ||
939 | mem = ioremap(mem_base, 0x800); | 993 | dev->mem = ioremap(mem_base, 0x800); |
940 | if (!mem) | 994 | if (!dev->mem) |
941 | return -ENOMEM; | 995 | return -ENOMEM; |
942 | 996 | ||
943 | if (!request_region(0x9A01, 1, "Mediavision PMS config")) | 997 | if (!request_region(0x9a01, 1, "Mediavision PMS config")) { |
944 | { | 998 | printk(KERN_WARNING "mediavision: unable to detect: 0x9a01 in use.\n"); |
945 | printk(KERN_WARNING "mediavision: unable to detect: 0x9A01 in use.\n"); | 999 | iounmap(dev->mem); |
946 | iounmap(mem); | ||
947 | return -EBUSY; | 1000 | return -EBUSY; |
948 | } | 1001 | } |
949 | if (!request_region(io_port, 3, "Mediavision PMS")) | 1002 | if (!request_region(dev->io, 3, "Mediavision PMS")) { |
950 | { | 1003 | printk(KERN_WARNING "mediavision: I/O port %d in use.\n", dev->io); |
951 | printk(KERN_WARNING "mediavision: I/O port %d in use.\n", io_port); | 1004 | release_region(0x9a01, 1); |
952 | release_region(0x9A01, 1); | 1005 | iounmap(dev->mem); |
953 | iounmap(mem); | ||
954 | return -EBUSY; | 1006 | return -EBUSY; |
955 | } | 1007 | } |
956 | outb(0xB8, 0x9A01); /* Unlock */ | 1008 | outb(0xb8, 0x9a01); /* Unlock */ |
957 | outb(io_port>>4, 0x9A01); /* Set IO port */ | 1009 | outb(dev->io >> 4, 0x9a01); /* Set IO port */ |
958 | 1010 | ||
959 | 1011 | ||
960 | id=mvv_read(3); | 1012 | id = mvv_read(dev, 3); |
961 | decst=pms_i2c_stat(0x43); | 1013 | decst = pms_i2c_stat(dev, 0x43); |
962 | 1014 | ||
963 | if(decst!=-1) | 1015 | if (decst != -1) |
964 | idec=2; | 1016 | idec = 2; |
965 | else if(pms_i2c_stat(0xb9)!=-1) | 1017 | else if (pms_i2c_stat(dev, 0xb9) != -1) |
966 | idec=3; | 1018 | idec = 3; |
967 | else if(pms_i2c_stat(0x8b)!=-1) | 1019 | else if (pms_i2c_stat(dev, 0x8b) != -1) |
968 | idec=1; | 1020 | idec = 1; |
969 | else | 1021 | else |
970 | idec=0; | 1022 | idec = 0; |
971 | 1023 | ||
972 | printk(KERN_INFO "PMS type is %d\n", idec); | 1024 | printk(KERN_INFO "PMS type is %d\n", idec); |
973 | if(idec == 0) { | 1025 | if (idec == 0) { |
974 | release_region(io_port, 3); | 1026 | release_region(dev->io, 3); |
975 | release_region(0x9A01, 1); | 1027 | release_region(0x9a01, 1); |
976 | iounmap(mem); | 1028 | iounmap(dev->mem); |
977 | return -ENODEV; | 1029 | return -ENODEV; |
978 | } | 1030 | } |
979 | 1031 | ||
@@ -981,51 +1033,50 @@ static int init_mediavision(void) | |||
981 | * Ok we have a PMS of some sort | 1033 | * Ok we have a PMS of some sort |
982 | */ | 1034 | */ |
983 | 1035 | ||
984 | mvv_write(0x04, mem_base>>12); /* Set the memory area */ | 1036 | mvv_write(dev, 0x04, mem_base >> 12); /* Set the memory area */ |
985 | 1037 | ||
986 | /* Ok now load the defaults */ | 1038 | /* Ok now load the defaults */ |
987 | 1039 | ||
988 | for(i=0;i<0x19;i++) | 1040 | for (i = 0; i < 0x19; i++) { |
989 | { | 1041 | if (i2c_defs[i] == 0xff) |
990 | if(i2c_defs[i]==0xFF) | 1042 | pms_i2c_andor(dev, 0x8a, i, 0x07, 0x00); |
991 | pms_i2c_andor(0x8A, i, 0x07,0x00); | ||
992 | else | 1043 | else |
993 | pms_i2c_write(0x8A, i, i2c_defs[i]); | 1044 | pms_i2c_write(dev, 0x8a, i, i2c_defs[i]); |
994 | } | 1045 | } |
995 | 1046 | ||
996 | pms_i2c_write(0xB8,0x00,0x12); | 1047 | pms_i2c_write(dev, 0xb8, 0x00, 0x12); |
997 | pms_i2c_write(0xB8,0x04,0x00); | 1048 | pms_i2c_write(dev, 0xb8, 0x04, 0x00); |
998 | pms_i2c_write(0xB8,0x07,0x00); | 1049 | pms_i2c_write(dev, 0xb8, 0x07, 0x00); |
999 | pms_i2c_write(0xB8,0x08,0x00); | 1050 | pms_i2c_write(dev, 0xb8, 0x08, 0x00); |
1000 | pms_i2c_write(0xB8,0x09,0xFF); | 1051 | pms_i2c_write(dev, 0xb8, 0x09, 0xff); |
1001 | pms_i2c_write(0xB8,0x0A,0x00); | 1052 | pms_i2c_write(dev, 0xb8, 0x0a, 0x00); |
1002 | pms_i2c_write(0xB8,0x0B,0x10); | 1053 | pms_i2c_write(dev, 0xb8, 0x0b, 0x10); |
1003 | pms_i2c_write(0xB8,0x10,0x03); | 1054 | pms_i2c_write(dev, 0xb8, 0x10, 0x03); |
1004 | 1055 | ||
1005 | mvv_write(0x01, 0x00); | 1056 | mvv_write(dev, 0x01, 0x00); |
1006 | mvv_write(0x05, 0xA0); | 1057 | mvv_write(dev, 0x05, 0xa0); |
1007 | mvv_write(0x08, 0x25); | 1058 | mvv_write(dev, 0x08, 0x25); |
1008 | mvv_write(0x09, 0x00); | 1059 | mvv_write(dev, 0x09, 0x00); |
1009 | mvv_write(0x0A, 0x20|MVVMEMORYWIDTH); | 1060 | mvv_write(dev, 0x0a, 0x20 | MVVMEMORYWIDTH); |
1010 | 1061 | ||
1011 | mvv_write(0x10, 0x02); | 1062 | mvv_write(dev, 0x10, 0x02); |
1012 | mvv_write(0x1E, 0x0C); | 1063 | mvv_write(dev, 0x1e, 0x0c); |
1013 | mvv_write(0x1F, 0x03); | 1064 | mvv_write(dev, 0x1f, 0x03); |
1014 | mvv_write(0x26, 0x06); | 1065 | mvv_write(dev, 0x26, 0x06); |
1015 | 1066 | ||
1016 | mvv_write(0x2B, 0x00); | 1067 | mvv_write(dev, 0x2b, 0x00); |
1017 | mvv_write(0x2C, 0x20); | 1068 | mvv_write(dev, 0x2c, 0x20); |
1018 | mvv_write(0x2D, 0x00); | 1069 | mvv_write(dev, 0x2d, 0x00); |
1019 | mvv_write(0x2F, 0x70); | 1070 | mvv_write(dev, 0x2f, 0x70); |
1020 | mvv_write(0x32, 0x00); | 1071 | mvv_write(dev, 0x32, 0x00); |
1021 | mvv_write(0x33, MVVMEMORYWIDTH); | 1072 | mvv_write(dev, 0x33, MVVMEMORYWIDTH); |
1022 | mvv_write(0x34, 0x00); | 1073 | mvv_write(dev, 0x34, 0x00); |
1023 | mvv_write(0x35, 0x00); | 1074 | mvv_write(dev, 0x35, 0x00); |
1024 | mvv_write(0x3A, 0x80); | 1075 | mvv_write(dev, 0x3a, 0x80); |
1025 | mvv_write(0x3B, 0x10); | 1076 | mvv_write(dev, 0x3b, 0x10); |
1026 | mvv_write(0x20, 0x00); | 1077 | mvv_write(dev, 0x20, 0x00); |
1027 | mvv_write(0x21, 0x00); | 1078 | mvv_write(dev, 0x21, 0x00); |
1028 | mvv_write(0x30, 0x22); | 1079 | mvv_write(dev, 0x30, 0x22); |
1029 | return 0; | 1080 | return 0; |
1030 | } | 1081 | } |
1031 | 1082 | ||
@@ -1038,53 +1089,77 @@ static int enable; | |||
1038 | module_param(enable, int, 0); | 1089 | module_param(enable, int, 0); |
1039 | #endif | 1090 | #endif |
1040 | 1091 | ||
1041 | static int __init init_pms_cards(void) | 1092 | static int __init pms_init(void) |
1042 | { | 1093 | { |
1043 | printk(KERN_INFO "Mediavision Pro Movie Studio driver 0.02\n"); | 1094 | struct pms *dev = &pms_card; |
1095 | struct v4l2_device *v4l2_dev = &dev->v4l2_dev; | ||
1096 | int res; | ||
1097 | |||
1098 | strlcpy(v4l2_dev->name, "pms", sizeof(v4l2_dev->name)); | ||
1099 | |||
1100 | v4l2_info(v4l2_dev, "Mediavision Pro Movie Studio driver 0.03\n"); | ||
1044 | 1101 | ||
1045 | #ifndef MODULE | 1102 | #ifndef MODULE |
1046 | if (!enable) { | 1103 | if (!enable) { |
1047 | printk(KERN_INFO "PMS: not enabled, use pms.enable=1 to " | 1104 | v4l2_err(v4l2_dev, |
1048 | "probe\n"); | 1105 | "PMS: not enabled, use pms.enable=1 to probe\n"); |
1049 | return -ENODEV; | 1106 | return -ENODEV; |
1050 | } | 1107 | } |
1051 | #endif | 1108 | #endif |
1052 | 1109 | ||
1053 | data_port = io_port +1; | 1110 | dev->decoder = PHILIPS2; |
1111 | dev->io = io_port; | ||
1112 | dev->data = io_port + 1; | ||
1054 | 1113 | ||
1055 | if(init_mediavision()) | 1114 | if (init_mediavision(dev)) { |
1056 | { | 1115 | v4l2_err(v4l2_dev, "Board not found.\n"); |
1057 | printk(KERN_INFO "Board not found.\n"); | ||
1058 | return -ENODEV; | 1116 | return -ENODEV; |
1059 | } | 1117 | } |
1060 | memcpy(&pms_device, &pms_template, sizeof(pms_template)); | ||
1061 | mutex_init(&pms_device.lock); | ||
1062 | pms_device.height=240; | ||
1063 | pms_device.width=320; | ||
1064 | pms_swsense(75); | ||
1065 | pms_resolution(320,240); | ||
1066 | return video_register_device((struct video_device *)&pms_device, VFL_TYPE_GRABBER, video_nr); | ||
1067 | } | ||
1068 | |||
1069 | module_param(io_port, int, 0); | ||
1070 | module_param(mem_base, int, 0); | ||
1071 | module_param(video_nr, int, 0); | ||
1072 | MODULE_LICENSE("GPL"); | ||
1073 | 1118 | ||
1119 | res = v4l2_device_register(NULL, v4l2_dev); | ||
1120 | if (res < 0) { | ||
1121 | v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); | ||
1122 | return res; | ||
1123 | } | ||
1074 | 1124 | ||
1075 | static void __exit shutdown_mediavision(void) | 1125 | strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); |
1076 | { | 1126 | dev->vdev.v4l2_dev = v4l2_dev; |
1077 | release_region(io_port,3); | 1127 | dev->vdev.fops = &pms_fops; |
1078 | release_region(0x9A01, 1); | 1128 | dev->vdev.ioctl_ops = &pms_ioctl_ops; |
1129 | dev->vdev.release = video_device_release_empty; | ||
1130 | video_set_drvdata(&dev->vdev, dev); | ||
1131 | mutex_init(&dev->lock); | ||
1132 | dev->std = V4L2_STD_NTSC_M; | ||
1133 | dev->height = 240; | ||
1134 | dev->width = 320; | ||
1135 | dev->depth = 15; | ||
1136 | dev->brightness = 139; | ||
1137 | dev->contrast = 70; | ||
1138 | dev->hue = 0; | ||
1139 | dev->saturation = 64; | ||
1140 | pms_swsense(dev, 75); | ||
1141 | pms_resolution(dev, 320, 240); | ||
1142 | pms_videosource(dev, 0); | ||
1143 | pms_vcrinput(dev, 0); | ||
1144 | if (video_register_device(&dev->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { | ||
1145 | v4l2_device_unregister(&dev->v4l2_dev); | ||
1146 | release_region(dev->io, 3); | ||
1147 | release_region(0x9a01, 1); | ||
1148 | iounmap(dev->mem); | ||
1149 | return -EINVAL; | ||
1150 | } | ||
1151 | return 0; | ||
1079 | } | 1152 | } |
1080 | 1153 | ||
1081 | static void __exit cleanup_pms_module(void) | 1154 | static void __exit pms_exit(void) |
1082 | { | 1155 | { |
1083 | shutdown_mediavision(); | 1156 | struct pms *dev = &pms_card; |
1084 | video_unregister_device((struct video_device *)&pms_device); | ||
1085 | iounmap(mem); | ||
1086 | } | ||
1087 | 1157 | ||
1088 | module_init(init_pms_cards); | 1158 | video_unregister_device(&dev->vdev); |
1089 | module_exit(cleanup_pms_module); | 1159 | release_region(dev->io, 3); |
1160 | release_region(0x9a01, 1); | ||
1161 | iounmap(dev->mem); | ||
1162 | } | ||
1090 | 1163 | ||
1164 | module_init(pms_init); | ||
1165 | module_exit(pms_exit); | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c index fbe3856bdca6..ae977668c496 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c +++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c | |||
@@ -142,6 +142,9 @@ int pvr2_debugifc_print_info(struct pvr2_hdw *hdw,char *buf,unsigned int acnt) | |||
142 | { | 142 | { |
143 | int bcnt = 0; | 143 | int bcnt = 0; |
144 | int ccnt; | 144 | int ccnt; |
145 | ccnt = scnprintf(buf, acnt, "Driver hardware description: %s\n", | ||
146 | pvr2_hdw_get_desc(hdw)); | ||
147 | bcnt += ccnt; acnt -= ccnt; buf += ccnt; | ||
145 | ccnt = scnprintf(buf,acnt,"Driver state info:\n"); | 148 | ccnt = scnprintf(buf,acnt,"Driver state info:\n"); |
146 | bcnt += ccnt; acnt -= ccnt; buf += ccnt; | 149 | bcnt += ccnt; acnt -= ccnt; buf += ccnt; |
147 | ccnt = pvr2_hdw_state_report(hdw,buf,acnt); | 150 | ccnt = pvr2_hdw_state_report(hdw,buf,acnt); |
@@ -249,11 +252,15 @@ static int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf, | |||
249 | scnt = debugifc_isolate_word(buf,count,&wptr,&wlen); | 252 | scnt = debugifc_isolate_word(buf,count,&wptr,&wlen); |
250 | if (scnt && wptr) { | 253 | if (scnt && wptr) { |
251 | count -= scnt; buf += scnt; | 254 | count -= scnt; buf += scnt; |
252 | if (debugifc_match_keyword(wptr,wlen,"prom")) { | 255 | if (debugifc_match_keyword(wptr, wlen, |
253 | pvr2_hdw_cpufw_set_enabled(hdw,!0,!0); | 256 | "prom")) { |
254 | } else if (debugifc_match_keyword(wptr,wlen, | 257 | pvr2_hdw_cpufw_set_enabled(hdw, 2, !0); |
255 | "ram")) { | 258 | } else if (debugifc_match_keyword(wptr, wlen, |
256 | pvr2_hdw_cpufw_set_enabled(hdw,0,!0); | 259 | "ram8k")) { |
260 | pvr2_hdw_cpufw_set_enabled(hdw, 0, !0); | ||
261 | } else if (debugifc_match_keyword(wptr, wlen, | ||
262 | "ram16k")) { | ||
263 | pvr2_hdw_cpufw_set_enabled(hdw, 1, !0); | ||
257 | } else { | 264 | } else { |
258 | return -EINVAL; | 265 | return -EINVAL; |
259 | } | 266 | } |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index e4d7c13cab87..6bc16c13ccef 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c | |||
@@ -58,7 +58,7 @@ static const char *pvr2_fw1_names_29xxx[] = { | |||
58 | }; | 58 | }; |
59 | 59 | ||
60 | static const struct pvr2_device_desc pvr2_device_29xxx = { | 60 | static const struct pvr2_device_desc pvr2_device_29xxx = { |
61 | .description = "WinTV PVR USB2 Model Category 29xxx", | 61 | .description = "WinTV PVR USB2 Model 29xxx", |
62 | .shortname = "29xxx", | 62 | .shortname = "29xxx", |
63 | .client_table.lst = pvr2_cli_29xxx, | 63 | .client_table.lst = pvr2_cli_29xxx, |
64 | .client_table.cnt = ARRAY_SIZE(pvr2_cli_29xxx), | 64 | .client_table.cnt = ARRAY_SIZE(pvr2_cli_29xxx), |
@@ -91,7 +91,7 @@ static const char *pvr2_fw1_names_24xxx[] = { | |||
91 | }; | 91 | }; |
92 | 92 | ||
93 | static const struct pvr2_device_desc pvr2_device_24xxx = { | 93 | static const struct pvr2_device_desc pvr2_device_24xxx = { |
94 | .description = "WinTV PVR USB2 Model Category 24xxx", | 94 | .description = "WinTV PVR USB2 Model 24xxx", |
95 | .shortname = "24xxx", | 95 | .shortname = "24xxx", |
96 | .client_table.lst = pvr2_cli_24xxx, | 96 | .client_table.lst = pvr2_cli_24xxx, |
97 | .client_table.cnt = ARRAY_SIZE(pvr2_cli_24xxx), | 97 | .client_table.cnt = ARRAY_SIZE(pvr2_cli_24xxx), |
@@ -340,7 +340,7 @@ static const char *pvr2_fw1_names_73xxx[] = { | |||
340 | }; | 340 | }; |
341 | 341 | ||
342 | static const struct pvr2_device_desc pvr2_device_73xxx = { | 342 | static const struct pvr2_device_desc pvr2_device_73xxx = { |
343 | .description = "WinTV HVR-1900 Model Category 73xxx", | 343 | .description = "WinTV HVR-1900 Model 73xxx", |
344 | .shortname = "73xxx", | 344 | .shortname = "73xxx", |
345 | .client_table.lst = pvr2_cli_73xxx, | 345 | .client_table.lst = pvr2_cli_73xxx, |
346 | .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx), | 346 | .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx), |
@@ -351,6 +351,7 @@ static const struct pvr2_device_desc pvr2_device_73xxx = { | |||
351 | .flag_has_analogtuner = !0, | 351 | .flag_has_analogtuner = !0, |
352 | .flag_has_composite = !0, | 352 | .flag_has_composite = !0, |
353 | .flag_has_svideo = !0, | 353 | .flag_has_svideo = !0, |
354 | .flag_fx2_16kb = !0, | ||
354 | .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, | 355 | .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, |
355 | .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE, | 356 | .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE, |
356 | .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE, | 357 | .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE, |
@@ -445,7 +446,7 @@ static const char *pvr2_fw1_names_75xxx[] = { | |||
445 | }; | 446 | }; |
446 | 447 | ||
447 | static const struct pvr2_device_desc pvr2_device_750xx = { | 448 | static const struct pvr2_device_desc pvr2_device_750xx = { |
448 | .description = "WinTV HVR-1950 Model Category 750xx", | 449 | .description = "WinTV HVR-1950 Model 750xx", |
449 | .shortname = "750xx", | 450 | .shortname = "750xx", |
450 | .client_table.lst = pvr2_cli_73xxx, | 451 | .client_table.lst = pvr2_cli_73xxx, |
451 | .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx), | 452 | .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx), |
@@ -456,6 +457,7 @@ static const struct pvr2_device_desc pvr2_device_750xx = { | |||
456 | .flag_has_analogtuner = !0, | 457 | .flag_has_analogtuner = !0, |
457 | .flag_has_composite = !0, | 458 | .flag_has_composite = !0, |
458 | .flag_has_svideo = !0, | 459 | .flag_has_svideo = !0, |
460 | .flag_fx2_16kb = !0, | ||
459 | .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, | 461 | .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, |
460 | .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE, | 462 | .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE, |
461 | .default_std_mask = V4L2_STD_NTSC_M, | 463 | .default_std_mask = V4L2_STD_NTSC_M, |
@@ -467,7 +469,7 @@ static const struct pvr2_device_desc pvr2_device_750xx = { | |||
467 | }; | 469 | }; |
468 | 470 | ||
469 | static const struct pvr2_device_desc pvr2_device_751xx = { | 471 | static const struct pvr2_device_desc pvr2_device_751xx = { |
470 | .description = "WinTV HVR-1950 Model Category 751xx", | 472 | .description = "WinTV HVR-1950 Model 751xx", |
471 | .shortname = "751xx", | 473 | .shortname = "751xx", |
472 | .client_table.lst = pvr2_cli_73xxx, | 474 | .client_table.lst = pvr2_cli_73xxx, |
473 | .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx), | 475 | .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx), |
@@ -478,6 +480,7 @@ static const struct pvr2_device_desc pvr2_device_751xx = { | |||
478 | .flag_has_analogtuner = !0, | 480 | .flag_has_analogtuner = !0, |
479 | .flag_has_composite = !0, | 481 | .flag_has_composite = !0, |
480 | .flag_has_svideo = !0, | 482 | .flag_has_svideo = !0, |
483 | .flag_fx2_16kb = !0, | ||
481 | .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, | 484 | .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, |
482 | .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE, | 485 | .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE, |
483 | .default_std_mask = V4L2_STD_NTSC_M, | 486 | .default_std_mask = V4L2_STD_NTSC_M, |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h index ea04ecf8aa39..e5b9594eb5f6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h | |||
@@ -176,6 +176,7 @@ struct pvr2_device_desc { | |||
176 | unsigned int flag_has_analogtuner:1; /* Has analog tuner */ | 176 | unsigned int flag_has_analogtuner:1; /* Has analog tuner */ |
177 | unsigned int flag_has_composite:1; /* Has composite input */ | 177 | unsigned int flag_has_composite:1; /* Has composite input */ |
178 | unsigned int flag_has_svideo:1; /* Has s-video input */ | 178 | unsigned int flag_has_svideo:1; /* Has s-video input */ |
179 | unsigned int flag_fx2_16kb:1; /* 16KB FX2 firmware OK here */ | ||
179 | }; | 180 | }; |
180 | 181 | ||
181 | extern struct usb_device_id pvr2_device_table[]; | 182 | extern struct usb_device_id pvr2_device_table[]; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c index 54ac5349dee2..e046fdaec5ae 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c | |||
@@ -294,7 +294,10 @@ static int pvr2_encoder_cmd(void *ctxt, | |||
294 | pvr2_trace( | 294 | pvr2_trace( |
295 | PVR2_TRACE_ERROR_LEGS, | 295 | PVR2_TRACE_ERROR_LEGS, |
296 | "Giving up on command." | 296 | "Giving up on command." |
297 | " This is normally recovered by the driver."); | 297 | " This is normally recovered via a firmware" |
298 | " reload and re-initialization; concern" | ||
299 | " is only warranted if this happens repeatedly" | ||
300 | " and rapidly."); | ||
298 | break; | 301 | break; |
299 | } | 302 | } |
300 | wrData[0] = 0x7; | 303 | wrData[0] = 0x7; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 5fcad28211d2..de5485f506b1 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | |||
@@ -270,6 +270,7 @@ struct pvr2_hdw { | |||
270 | 270 | ||
271 | int force_dirty; /* consider all controls dirty if true */ | 271 | int force_dirty; /* consider all controls dirty if true */ |
272 | int flag_ok; /* device in known good state */ | 272 | int flag_ok; /* device in known good state */ |
273 | int flag_modulefail; /* true if at least one module failed to load */ | ||
273 | int flag_disconnected; /* flag_ok == 0 due to disconnect */ | 274 | int flag_disconnected; /* flag_ok == 0 due to disconnect */ |
274 | int flag_init_ok; /* true if structure is fully initialized */ | 275 | int flag_init_ok; /* true if structure is fully initialized */ |
275 | int fw1_state; /* current situation with fw1 */ | 276 | int fw1_state; /* current situation with fw1 */ |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 13639b302700..1bbdab08fe0e 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
@@ -1447,6 +1447,7 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw) | |||
1447 | const struct firmware *fw_entry = NULL; | 1447 | const struct firmware *fw_entry = NULL; |
1448 | void *fw_ptr; | 1448 | void *fw_ptr; |
1449 | unsigned int pipe; | 1449 | unsigned int pipe; |
1450 | unsigned int fwsize; | ||
1450 | int ret; | 1451 | int ret; |
1451 | u16 address; | 1452 | u16 address; |
1452 | 1453 | ||
@@ -1473,9 +1474,21 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw) | |||
1473 | usb_clear_halt(hdw->usb_dev, usb_sndbulkpipe(hdw->usb_dev, 0 & 0x7f)); | 1474 | usb_clear_halt(hdw->usb_dev, usb_sndbulkpipe(hdw->usb_dev, 0 & 0x7f)); |
1474 | 1475 | ||
1475 | pipe = usb_sndctrlpipe(hdw->usb_dev, 0); | 1476 | pipe = usb_sndctrlpipe(hdw->usb_dev, 0); |
1477 | fwsize = fw_entry->size; | ||
1476 | 1478 | ||
1477 | if (fw_entry->size != 0x2000){ | 1479 | if ((fwsize != 0x2000) && |
1478 | pvr2_trace(PVR2_TRACE_ERROR_LEGS,"wrong fx2 firmware size"); | 1480 | (!(hdw->hdw_desc->flag_fx2_16kb && (fwsize == 0x4000)))) { |
1481 | if (hdw->hdw_desc->flag_fx2_16kb) { | ||
1482 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
1483 | "Wrong fx2 firmware size" | ||
1484 | " (expected 8192 or 16384, got %u)", | ||
1485 | fwsize); | ||
1486 | } else { | ||
1487 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
1488 | "Wrong fx2 firmware size" | ||
1489 | " (expected 8192, got %u)", | ||
1490 | fwsize); | ||
1491 | } | ||
1479 | release_firmware(fw_entry); | 1492 | release_firmware(fw_entry); |
1480 | return -ENOMEM; | 1493 | return -ENOMEM; |
1481 | } | 1494 | } |
@@ -1493,7 +1506,7 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw) | |||
1493 | chunk. */ | 1506 | chunk. */ |
1494 | 1507 | ||
1495 | ret = 0; | 1508 | ret = 0; |
1496 | for(address = 0; address < fw_entry->size; address += 0x800) { | 1509 | for (address = 0; address < fwsize; address += 0x800) { |
1497 | memcpy(fw_ptr, fw_entry->data + address, 0x800); | 1510 | memcpy(fw_ptr, fw_entry->data + address, 0x800); |
1498 | ret += usb_control_msg(hdw->usb_dev, pipe, 0xa0, 0x40, address, | 1511 | ret += usb_control_msg(hdw->usb_dev, pipe, 0xa0, 0x40, address, |
1499 | 0, fw_ptr, 0x800, HZ); | 1512 | 0, fw_ptr, 0x800, HZ); |
@@ -1509,8 +1522,8 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw) | |||
1509 | 1522 | ||
1510 | trace_firmware("Upload done (%d bytes sent)",ret); | 1523 | trace_firmware("Upload done (%d bytes sent)",ret); |
1511 | 1524 | ||
1512 | /* We should have written 8192 bytes */ | 1525 | /* We should have written fwsize bytes */ |
1513 | if (ret == 8192) { | 1526 | if (ret == fwsize) { |
1514 | hdw->fw1_state = FW1_STATE_RELOAD; | 1527 | hdw->fw1_state = FW1_STATE_RELOAD; |
1515 | return 0; | 1528 | return 0; |
1516 | } | 1529 | } |
@@ -2030,7 +2043,8 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, | |||
2030 | fname = (mid < ARRAY_SIZE(module_names)) ? module_names[mid] : NULL; | 2043 | fname = (mid < ARRAY_SIZE(module_names)) ? module_names[mid] : NULL; |
2031 | if (!fname) { | 2044 | if (!fname) { |
2032 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | 2045 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, |
2033 | "Module ID %u for device %s has no name", | 2046 | "Module ID %u for device %s has no name?" |
2047 | " The driver might have a configuration problem.", | ||
2034 | mid, | 2048 | mid, |
2035 | hdw->hdw_desc->description); | 2049 | hdw->hdw_desc->description); |
2036 | return -EINVAL; | 2050 | return -EINVAL; |
@@ -2058,7 +2072,8 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, | |||
2058 | if (!i2ccnt) { | 2072 | if (!i2ccnt) { |
2059 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | 2073 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, |
2060 | "Module ID %u (%s) for device %s:" | 2074 | "Module ID %u (%s) for device %s:" |
2061 | " No i2c addresses", | 2075 | " No i2c addresses." |
2076 | " The driver might have a configuration problem.", | ||
2062 | mid, fname, hdw->hdw_desc->description); | 2077 | mid, fname, hdw->hdw_desc->description); |
2063 | return -EINVAL; | 2078 | return -EINVAL; |
2064 | } | 2079 | } |
@@ -2090,7 +2105,9 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, | |||
2090 | 2105 | ||
2091 | if (!sd) { | 2106 | if (!sd) { |
2092 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | 2107 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, |
2093 | "Module ID %u (%s) for device %s failed to load", | 2108 | "Module ID %u (%s) for device %s failed to load." |
2109 | " Possible missing sub-device kernel module or" | ||
2110 | " initialization failure within module.", | ||
2094 | mid, fname, hdw->hdw_desc->description); | 2111 | mid, fname, hdw->hdw_desc->description); |
2095 | return -EIO; | 2112 | return -EIO; |
2096 | } | 2113 | } |
@@ -2132,7 +2149,10 @@ static void pvr2_hdw_load_modules(struct pvr2_hdw *hdw) | |||
2132 | for (idx = 0; idx < ct->cnt; idx++) { | 2149 | for (idx = 0; idx < ct->cnt; idx++) { |
2133 | if (pvr2_hdw_load_subdev(hdw, &ct->lst[idx]) < 0) okFl = 0; | 2150 | if (pvr2_hdw_load_subdev(hdw, &ct->lst[idx]) < 0) okFl = 0; |
2134 | } | 2151 | } |
2135 | if (!okFl) pvr2_hdw_render_useless(hdw); | 2152 | if (!okFl) { |
2153 | hdw->flag_modulefail = !0; | ||
2154 | pvr2_hdw_render_useless(hdw); | ||
2155 | } | ||
2136 | } | 2156 | } |
2137 | 2157 | ||
2138 | 2158 | ||
@@ -2334,6 +2354,20 @@ static void pvr2_hdw_setup(struct pvr2_hdw *hdw) | |||
2334 | break; | 2354 | break; |
2335 | } | 2355 | } |
2336 | } | 2356 | } |
2357 | if (hdw->flag_modulefail) { | ||
2358 | pvr2_trace( | ||
2359 | PVR2_TRACE_ERROR_LEGS, | ||
2360 | "***WARNING*** pvrusb2 driver initialization" | ||
2361 | " failed due to the failure of one or more" | ||
2362 | " sub-device kernel modules."); | ||
2363 | pvr2_trace( | ||
2364 | PVR2_TRACE_ERROR_LEGS, | ||
2365 | "You need to resolve the failing condition" | ||
2366 | " before this driver can function. There" | ||
2367 | " should be some earlier messages giving more" | ||
2368 | " information about the problem."); | ||
2369 | break; | ||
2370 | } | ||
2337 | if (procreload) { | 2371 | if (procreload) { |
2338 | pvr2_trace( | 2372 | pvr2_trace( |
2339 | PVR2_TRACE_ERROR_LEGS, | 2373 | PVR2_TRACE_ERROR_LEGS, |
@@ -2419,6 +2453,8 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
2419 | hdw = kzalloc(sizeof(*hdw),GFP_KERNEL); | 2453 | hdw = kzalloc(sizeof(*hdw),GFP_KERNEL); |
2420 | pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"", | 2454 | pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"", |
2421 | hdw,hdw_desc->description); | 2455 | hdw,hdw_desc->description); |
2456 | pvr2_trace(PVR2_TRACE_INFO, "Hardware description: %s", | ||
2457 | hdw_desc->description); | ||
2422 | if (!hdw) goto fail; | 2458 | if (!hdw) goto fail; |
2423 | 2459 | ||
2424 | init_timer(&hdw->quiescent_timer); | 2460 | init_timer(&hdw->quiescent_timer); |
@@ -3480,7 +3516,7 @@ static u8 *pvr2_full_eeprom_fetch(struct pvr2_hdw *hdw) | |||
3480 | 3516 | ||
3481 | 3517 | ||
3482 | void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, | 3518 | void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, |
3483 | int prom_flag, | 3519 | int mode, |
3484 | int enable_flag) | 3520 | int enable_flag) |
3485 | { | 3521 | { |
3486 | int ret; | 3522 | int ret; |
@@ -3503,11 +3539,12 @@ void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, | |||
3503 | break; | 3539 | break; |
3504 | } | 3540 | } |
3505 | 3541 | ||
3506 | hdw->fw_cpu_flag = (prom_flag == 0); | 3542 | hdw->fw_cpu_flag = (mode != 2); |
3507 | if (hdw->fw_cpu_flag) { | 3543 | if (hdw->fw_cpu_flag) { |
3544 | hdw->fw_size = (mode == 1) ? 0x4000 : 0x2000; | ||
3508 | pvr2_trace(PVR2_TRACE_FIRMWARE, | 3545 | pvr2_trace(PVR2_TRACE_FIRMWARE, |
3509 | "Preparing to suck out CPU firmware"); | 3546 | "Preparing to suck out CPU firmware" |
3510 | hdw->fw_size = 0x2000; | 3547 | " (size=%u)", hdw->fw_size); |
3511 | hdw->fw_buffer = kzalloc(hdw->fw_size,GFP_KERNEL); | 3548 | hdw->fw_buffer = kzalloc(hdw->fw_size,GFP_KERNEL); |
3512 | if (!hdw->fw_buffer) { | 3549 | if (!hdw->fw_buffer) { |
3513 | hdw->fw_size = 0; | 3550 | hdw->fw_size = 0; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 7b6940554e9a..56e70eae20c1 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h | |||
@@ -219,7 +219,7 @@ int pvr2_hdw_get_stdenum_value(struct pvr2_hdw *hdw,struct v4l2_standard *std, | |||
219 | this may prevent the device from running (and leaving this mode may | 219 | this may prevent the device from running (and leaving this mode may |
220 | imply a device reset). */ | 220 | imply a device reset). */ |
221 | void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *, | 221 | void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *, |
222 | int prom_flag, | 222 | int mode, /* 0=8KB FX2, 1=16KB FX2, 2=PROM */ |
223 | int enable_flag); | 223 | int enable_flag); |
224 | 224 | ||
225 | /* Return true if we're in a mode for retrieval CPU firmware */ | 225 | /* Return true if we're in a mode for retrieval CPU firmware */ |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index a334b1a966a2..7cbe18c4ca95 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | |||
@@ -50,6 +50,7 @@ MODULE_PARM_DESC(disable_autoload_ir_video, | |||
50 | 50 | ||
51 | /* Mapping of IR schemes to known I2C addresses - if any */ | 51 | /* Mapping of IR schemes to known I2C addresses - if any */ |
52 | static const unsigned char ir_video_addresses[] = { | 52 | static const unsigned char ir_video_addresses[] = { |
53 | [PVR2_IR_SCHEME_ZILOG] = 0x71, | ||
53 | [PVR2_IR_SCHEME_29XXX] = 0x18, | 54 | [PVR2_IR_SCHEME_29XXX] = 0x18, |
54 | [PVR2_IR_SCHEME_24XXX] = 0x18, | 55 | [PVR2_IR_SCHEME_24XXX] = 0x18, |
55 | }; | 56 | }; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 2d8825e5b1be..6aa48e0ae731 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | |||
@@ -913,6 +913,15 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) | |||
913 | } | 913 | } |
914 | 914 | ||
915 | 915 | ||
916 | static void pvr2_v4l2_dev_disassociate_parent(struct pvr2_v4l2_dev *dip) | ||
917 | { | ||
918 | if (!dip) return; | ||
919 | if (!dip->devbase.parent) return; | ||
920 | dip->devbase.parent = NULL; | ||
921 | device_move(&dip->devbase.dev, NULL, DPM_ORDER_NONE); | ||
922 | } | ||
923 | |||
924 | |||
916 | static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp) | 925 | static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp) |
917 | { | 926 | { |
918 | if (vp->dev_video) { | 927 | if (vp->dev_video) { |
@@ -943,6 +952,8 @@ static void pvr2_v4l2_internal_check(struct pvr2_channel *chp) | |||
943 | struct pvr2_v4l2 *vp; | 952 | struct pvr2_v4l2 *vp; |
944 | vp = container_of(chp,struct pvr2_v4l2,channel); | 953 | vp = container_of(chp,struct pvr2_v4l2,channel); |
945 | if (!vp->channel.mc_head->disconnect_flag) return; | 954 | if (!vp->channel.mc_head->disconnect_flag) return; |
955 | pvr2_v4l2_dev_disassociate_parent(vp->dev_video); | ||
956 | pvr2_v4l2_dev_disassociate_parent(vp->dev_radio); | ||
946 | if (vp->vfirst) return; | 957 | if (vp->vfirst) return; |
947 | pvr2_v4l2_destroy_no_lock(vp); | 958 | pvr2_v4l2_destroy_no_lock(vp); |
948 | } | 959 | } |
@@ -1250,12 +1261,13 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, | |||
1250 | struct pvr2_v4l2 *vp, | 1261 | struct pvr2_v4l2 *vp, |
1251 | int v4l_type) | 1262 | int v4l_type) |
1252 | { | 1263 | { |
1264 | struct usb_device *usbdev; | ||
1253 | int mindevnum; | 1265 | int mindevnum; |
1254 | int unit_number; | 1266 | int unit_number; |
1255 | int *nr_ptr = NULL; | 1267 | int *nr_ptr = NULL; |
1256 | dip->v4lp = vp; | 1268 | dip->v4lp = vp; |
1257 | 1269 | ||
1258 | 1270 | usbdev = pvr2_hdw_get_dev(vp->channel.mc_head->hdw); | |
1259 | dip->v4l_type = v4l_type; | 1271 | dip->v4l_type = v4l_type; |
1260 | switch (v4l_type) { | 1272 | switch (v4l_type) { |
1261 | case VFL_TYPE_GRABBER: | 1273 | case VFL_TYPE_GRABBER: |
@@ -1296,6 +1308,7 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, | |||
1296 | if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) { | 1308 | if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) { |
1297 | mindevnum = nr_ptr[unit_number]; | 1309 | mindevnum = nr_ptr[unit_number]; |
1298 | } | 1310 | } |
1311 | dip->devbase.parent = &usbdev->dev; | ||
1299 | if ((video_register_device(&dip->devbase, | 1312 | if ((video_register_device(&dip->devbase, |
1300 | dip->v4l_type, mindevnum) < 0) && | 1313 | dip->v4l_type, mindevnum) < 0) && |
1301 | (video_register_device(&dip->devbase, | 1314 | (video_register_device(&dip->devbase, |
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index f976df452a34..89b620f6db7b 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c | |||
@@ -68,6 +68,7 @@ | |||
68 | #endif | 68 | #endif |
69 | #include <linux/vmalloc.h> | 69 | #include <linux/vmalloc.h> |
70 | #include <asm/io.h> | 70 | #include <asm/io.h> |
71 | #include <linux/kernel.h> /* simple_strtol() */ | ||
71 | 72 | ||
72 | #include "pwc.h" | 73 | #include "pwc.h" |
73 | #include "pwc-kiara.h" | 74 | #include "pwc-kiara.h" |
@@ -1916,19 +1917,6 @@ disconnect_out: | |||
1916 | unlock_kernel(); | 1917 | unlock_kernel(); |
1917 | } | 1918 | } |
1918 | 1919 | ||
1919 | /* *grunt* We have to do atoi ourselves :-( */ | ||
1920 | static int pwc_atoi(const char *s) | ||
1921 | { | ||
1922 | int k = 0; | ||
1923 | |||
1924 | k = 0; | ||
1925 | while (*s != '\0' && *s >= '0' && *s <= '9') { | ||
1926 | k = 10 * k + (*s - '0'); | ||
1927 | s++; | ||
1928 | } | ||
1929 | return k; | ||
1930 | } | ||
1931 | |||
1932 | 1920 | ||
1933 | /* | 1921 | /* |
1934 | * Initialization code & module stuff | 1922 | * Initialization code & module stuff |
@@ -2078,13 +2066,16 @@ static int __init usb_pwc_init(void) | |||
2078 | } | 2066 | } |
2079 | else { | 2067 | else { |
2080 | /* No type or serial number specified, just a number. */ | 2068 | /* No type or serial number specified, just a number. */ |
2081 | device_hint[i].device_node = pwc_atoi(s); | 2069 | device_hint[i].device_node = |
2070 | simple_strtol(s, NULL, 10); | ||
2082 | } | 2071 | } |
2083 | } | 2072 | } |
2084 | else { | 2073 | else { |
2085 | /* There's a colon, so we have at least a type and a device node */ | 2074 | /* There's a colon, so we have at least a type and a device node */ |
2086 | device_hint[i].type = pwc_atoi(s); | 2075 | device_hint[i].type = |
2087 | device_hint[i].device_node = pwc_atoi(colon + 1); | 2076 | simple_strtol(s, NULL, 10); |
2077 | device_hint[i].device_node = | ||
2078 | simple_strtol(colon + 1, NULL, 10); | ||
2088 | if (*dot != '\0') { | 2079 | if (*dot != '\0') { |
2089 | /* There's a serial number as well */ | 2080 | /* There's a serial number as well */ |
2090 | int k; | 2081 | int k; |
diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c new file mode 100644 index 000000000000..373f2a30a677 --- /dev/null +++ b/drivers/media/video/rj54n1cb0c.c | |||
@@ -0,0 +1,1219 @@ | |||
1 | /* | ||
2 | * Driver for RJ54N1CB0C CMOS Image Sensor from Micron | ||
3 | * | ||
4 | * Copyright (C) 2009, Guennadi Liakhovetski <g.liakhovetski@gmx.de> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/delay.h> | ||
12 | #include <linux/i2c.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/videodev2.h> | ||
15 | |||
16 | #include <media/v4l2-subdev.h> | ||
17 | #include <media/v4l2-chip-ident.h> | ||
18 | #include <media/soc_camera.h> | ||
19 | |||
20 | #define RJ54N1_DEV_CODE 0x0400 | ||
21 | #define RJ54N1_DEV_CODE2 0x0401 | ||
22 | #define RJ54N1_OUT_SEL 0x0403 | ||
23 | #define RJ54N1_XY_OUTPUT_SIZE_S_H 0x0404 | ||
24 | #define RJ54N1_X_OUTPUT_SIZE_S_L 0x0405 | ||
25 | #define RJ54N1_Y_OUTPUT_SIZE_S_L 0x0406 | ||
26 | #define RJ54N1_XY_OUTPUT_SIZE_P_H 0x0407 | ||
27 | #define RJ54N1_X_OUTPUT_SIZE_P_L 0x0408 | ||
28 | #define RJ54N1_Y_OUTPUT_SIZE_P_L 0x0409 | ||
29 | #define RJ54N1_LINE_LENGTH_PCK_S_H 0x040a | ||
30 | #define RJ54N1_LINE_LENGTH_PCK_S_L 0x040b | ||
31 | #define RJ54N1_LINE_LENGTH_PCK_P_H 0x040c | ||
32 | #define RJ54N1_LINE_LENGTH_PCK_P_L 0x040d | ||
33 | #define RJ54N1_RESIZE_N 0x040e | ||
34 | #define RJ54N1_RESIZE_N_STEP 0x040f | ||
35 | #define RJ54N1_RESIZE_STEP 0x0410 | ||
36 | #define RJ54N1_RESIZE_HOLD_H 0x0411 | ||
37 | #define RJ54N1_RESIZE_HOLD_L 0x0412 | ||
38 | #define RJ54N1_H_OBEN_OFS 0x0413 | ||
39 | #define RJ54N1_V_OBEN_OFS 0x0414 | ||
40 | #define RJ54N1_RESIZE_CONTROL 0x0415 | ||
41 | #define RJ54N1_INC_USE_SEL_H 0x0425 | ||
42 | #define RJ54N1_INC_USE_SEL_L 0x0426 | ||
43 | #define RJ54N1_MIRROR_STILL_MODE 0x0427 | ||
44 | #define RJ54N1_INIT_START 0x0428 | ||
45 | #define RJ54N1_SCALE_1_2_LEV 0x0429 | ||
46 | #define RJ54N1_SCALE_4_LEV 0x042a | ||
47 | #define RJ54N1_Y_GAIN 0x04d8 | ||
48 | #define RJ54N1_APT_GAIN_UP 0x04fa | ||
49 | #define RJ54N1_RA_SEL_UL 0x0530 | ||
50 | #define RJ54N1_BYTE_SWAP 0x0531 | ||
51 | #define RJ54N1_OUT_SIGPO 0x053b | ||
52 | #define RJ54N1_FRAME_LENGTH_S_H 0x0595 | ||
53 | #define RJ54N1_FRAME_LENGTH_S_L 0x0596 | ||
54 | #define RJ54N1_FRAME_LENGTH_P_H 0x0597 | ||
55 | #define RJ54N1_FRAME_LENGTH_P_L 0x0598 | ||
56 | #define RJ54N1_IOC 0x05ef | ||
57 | #define RJ54N1_TG_BYPASS 0x0700 | ||
58 | #define RJ54N1_PLL_L 0x0701 | ||
59 | #define RJ54N1_PLL_N 0x0702 | ||
60 | #define RJ54N1_PLL_EN 0x0704 | ||
61 | #define RJ54N1_RATIO_TG 0x0706 | ||
62 | #define RJ54N1_RATIO_T 0x0707 | ||
63 | #define RJ54N1_RATIO_R 0x0708 | ||
64 | #define RJ54N1_RAMP_TGCLK_EN 0x0709 | ||
65 | #define RJ54N1_OCLK_DSP 0x0710 | ||
66 | #define RJ54N1_RATIO_OP 0x0711 | ||
67 | #define RJ54N1_RATIO_O 0x0712 | ||
68 | #define RJ54N1_OCLK_SEL_EN 0x0713 | ||
69 | #define RJ54N1_CLK_RST 0x0717 | ||
70 | #define RJ54N1_RESET_STANDBY 0x0718 | ||
71 | |||
72 | #define E_EXCLK (1 << 7) | ||
73 | #define SOFT_STDBY (1 << 4) | ||
74 | #define SEN_RSTX (1 << 2) | ||
75 | #define TG_RSTX (1 << 1) | ||
76 | #define DSP_RSTX (1 << 0) | ||
77 | |||
78 | #define RESIZE_HOLD_SEL (1 << 2) | ||
79 | #define RESIZE_GO (1 << 1) | ||
80 | |||
81 | #define RJ54N1_COLUMN_SKIP 0 | ||
82 | #define RJ54N1_ROW_SKIP 0 | ||
83 | #define RJ54N1_MAX_WIDTH 1600 | ||
84 | #define RJ54N1_MAX_HEIGHT 1200 | ||
85 | |||
86 | /* I2C addresses: 0x50, 0x51, 0x60, 0x61 */ | ||
87 | |||
88 | static const struct soc_camera_data_format rj54n1_colour_formats[] = { | ||
89 | { | ||
90 | .name = "YUYV", | ||
91 | .depth = 16, | ||
92 | .fourcc = V4L2_PIX_FMT_YUYV, | ||
93 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
94 | }, { | ||
95 | .name = "RGB565", | ||
96 | .depth = 16, | ||
97 | .fourcc = V4L2_PIX_FMT_RGB565, | ||
98 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
99 | } | ||
100 | }; | ||
101 | |||
102 | struct rj54n1_clock_div { | ||
103 | u8 ratio_tg; | ||
104 | u8 ratio_t; | ||
105 | u8 ratio_r; | ||
106 | u8 ratio_op; | ||
107 | u8 ratio_o; | ||
108 | }; | ||
109 | |||
110 | struct rj54n1 { | ||
111 | struct v4l2_subdev subdev; | ||
112 | struct v4l2_rect rect; /* Sensor window */ | ||
113 | unsigned short width; /* Output window */ | ||
114 | unsigned short height; | ||
115 | unsigned short resize; /* Sensor * 1024 / resize = Output */ | ||
116 | struct rj54n1_clock_div clk_div; | ||
117 | u32 fourcc; | ||
118 | unsigned short scale; | ||
119 | u8 bank; | ||
120 | }; | ||
121 | |||
122 | struct rj54n1_reg_val { | ||
123 | u16 reg; | ||
124 | u8 val; | ||
125 | }; | ||
126 | |||
127 | const static struct rj54n1_reg_val bank_4[] = { | ||
128 | {0x417, 0}, | ||
129 | {0x42c, 0}, | ||
130 | {0x42d, 0xf0}, | ||
131 | {0x42e, 0}, | ||
132 | {0x42f, 0x50}, | ||
133 | {0x430, 0xf5}, | ||
134 | {0x431, 0x16}, | ||
135 | {0x432, 0x20}, | ||
136 | {0x433, 0}, | ||
137 | {0x434, 0xc8}, | ||
138 | {0x43c, 8}, | ||
139 | {0x43e, 0x90}, | ||
140 | {0x445, 0x83}, | ||
141 | {0x4ba, 0x58}, | ||
142 | {0x4bb, 4}, | ||
143 | {0x4bc, 0x20}, | ||
144 | {0x4db, 4}, | ||
145 | {0x4fe, 2}, | ||
146 | }; | ||
147 | |||
148 | const static struct rj54n1_reg_val bank_5[] = { | ||
149 | {0x514, 0}, | ||
150 | {0x516, 0}, | ||
151 | {0x518, 0}, | ||
152 | {0x51a, 0}, | ||
153 | {0x51d, 0xff}, | ||
154 | {0x56f, 0x28}, | ||
155 | {0x575, 0x40}, | ||
156 | {0x5bc, 0x48}, | ||
157 | {0x5c1, 6}, | ||
158 | {0x5e5, 0x11}, | ||
159 | {0x5e6, 0x43}, | ||
160 | {0x5e7, 0x33}, | ||
161 | {0x5e8, 0x21}, | ||
162 | {0x5e9, 0x30}, | ||
163 | {0x5ea, 0x0}, | ||
164 | {0x5eb, 0xa5}, | ||
165 | {0x5ec, 0xff}, | ||
166 | {0x5fe, 2}, | ||
167 | }; | ||
168 | |||
169 | const static struct rj54n1_reg_val bank_7[] = { | ||
170 | {0x70a, 0}, | ||
171 | {0x714, 0xff}, | ||
172 | {0x715, 0xff}, | ||
173 | {0x716, 0x1f}, | ||
174 | {0x7FE, 0x02}, | ||
175 | }; | ||
176 | |||
177 | const static struct rj54n1_reg_val bank_8[] = { | ||
178 | {0x800, 0x00}, | ||
179 | {0x801, 0x01}, | ||
180 | {0x802, 0x61}, | ||
181 | {0x805, 0x00}, | ||
182 | {0x806, 0x00}, | ||
183 | {0x807, 0x00}, | ||
184 | {0x808, 0x00}, | ||
185 | {0x809, 0x01}, | ||
186 | {0x80A, 0x61}, | ||
187 | {0x80B, 0x00}, | ||
188 | {0x80C, 0x01}, | ||
189 | {0x80D, 0x00}, | ||
190 | {0x80E, 0x00}, | ||
191 | {0x80F, 0x00}, | ||
192 | {0x810, 0x00}, | ||
193 | {0x811, 0x01}, | ||
194 | {0x812, 0x61}, | ||
195 | {0x813, 0x00}, | ||
196 | {0x814, 0x11}, | ||
197 | {0x815, 0x00}, | ||
198 | {0x816, 0x41}, | ||
199 | {0x817, 0x00}, | ||
200 | {0x818, 0x51}, | ||
201 | {0x819, 0x01}, | ||
202 | {0x81A, 0x1F}, | ||
203 | {0x81B, 0x00}, | ||
204 | {0x81C, 0x01}, | ||
205 | {0x81D, 0x00}, | ||
206 | {0x81E, 0x11}, | ||
207 | {0x81F, 0x00}, | ||
208 | {0x820, 0x41}, | ||
209 | {0x821, 0x00}, | ||
210 | {0x822, 0x51}, | ||
211 | {0x823, 0x00}, | ||
212 | {0x824, 0x00}, | ||
213 | {0x825, 0x00}, | ||
214 | {0x826, 0x47}, | ||
215 | {0x827, 0x01}, | ||
216 | {0x828, 0x4F}, | ||
217 | {0x829, 0x00}, | ||
218 | {0x82A, 0x00}, | ||
219 | {0x82B, 0x00}, | ||
220 | {0x82C, 0x30}, | ||
221 | {0x82D, 0x00}, | ||
222 | {0x82E, 0x40}, | ||
223 | {0x82F, 0x00}, | ||
224 | {0x830, 0xB3}, | ||
225 | {0x831, 0x00}, | ||
226 | {0x832, 0xE3}, | ||
227 | {0x833, 0x00}, | ||
228 | {0x834, 0x00}, | ||
229 | {0x835, 0x00}, | ||
230 | {0x836, 0x00}, | ||
231 | {0x837, 0x00}, | ||
232 | {0x838, 0x00}, | ||
233 | {0x839, 0x01}, | ||
234 | {0x83A, 0x61}, | ||
235 | {0x83B, 0x00}, | ||
236 | {0x83C, 0x01}, | ||
237 | {0x83D, 0x00}, | ||
238 | {0x83E, 0x00}, | ||
239 | {0x83F, 0x00}, | ||
240 | {0x840, 0x00}, | ||
241 | {0x841, 0x01}, | ||
242 | {0x842, 0x61}, | ||
243 | {0x843, 0x00}, | ||
244 | {0x844, 0x1D}, | ||
245 | {0x845, 0x00}, | ||
246 | {0x846, 0x00}, | ||
247 | {0x847, 0x00}, | ||
248 | {0x848, 0x00}, | ||
249 | {0x849, 0x01}, | ||
250 | {0x84A, 0x1F}, | ||
251 | {0x84B, 0x00}, | ||
252 | {0x84C, 0x05}, | ||
253 | {0x84D, 0x00}, | ||
254 | {0x84E, 0x19}, | ||
255 | {0x84F, 0x01}, | ||
256 | {0x850, 0x21}, | ||
257 | {0x851, 0x01}, | ||
258 | {0x852, 0x5D}, | ||
259 | {0x853, 0x00}, | ||
260 | {0x854, 0x00}, | ||
261 | {0x855, 0x00}, | ||
262 | {0x856, 0x19}, | ||
263 | {0x857, 0x01}, | ||
264 | {0x858, 0x21}, | ||
265 | {0x859, 0x00}, | ||
266 | {0x85A, 0x00}, | ||
267 | {0x85B, 0x00}, | ||
268 | {0x85C, 0x00}, | ||
269 | {0x85D, 0x00}, | ||
270 | {0x85E, 0x00}, | ||
271 | {0x85F, 0x00}, | ||
272 | {0x860, 0xB3}, | ||
273 | {0x861, 0x00}, | ||
274 | {0x862, 0xE3}, | ||
275 | {0x863, 0x00}, | ||
276 | {0x864, 0x00}, | ||
277 | {0x865, 0x00}, | ||
278 | {0x866, 0x00}, | ||
279 | {0x867, 0x00}, | ||
280 | {0x868, 0x00}, | ||
281 | {0x869, 0xE2}, | ||
282 | {0x86A, 0x00}, | ||
283 | {0x86B, 0x01}, | ||
284 | {0x86C, 0x06}, | ||
285 | {0x86D, 0x00}, | ||
286 | {0x86E, 0x00}, | ||
287 | {0x86F, 0x00}, | ||
288 | {0x870, 0x60}, | ||
289 | {0x871, 0x8C}, | ||
290 | {0x872, 0x10}, | ||
291 | {0x873, 0x00}, | ||
292 | {0x874, 0xE0}, | ||
293 | {0x875, 0x00}, | ||
294 | {0x876, 0x27}, | ||
295 | {0x877, 0x01}, | ||
296 | {0x878, 0x00}, | ||
297 | {0x879, 0x00}, | ||
298 | {0x87A, 0x00}, | ||
299 | {0x87B, 0x03}, | ||
300 | {0x87C, 0x00}, | ||
301 | {0x87D, 0x00}, | ||
302 | {0x87E, 0x00}, | ||
303 | {0x87F, 0x00}, | ||
304 | {0x880, 0x00}, | ||
305 | {0x881, 0x00}, | ||
306 | {0x882, 0x00}, | ||
307 | {0x883, 0x00}, | ||
308 | {0x884, 0x00}, | ||
309 | {0x885, 0x00}, | ||
310 | {0x886, 0xF8}, | ||
311 | {0x887, 0x00}, | ||
312 | {0x888, 0x03}, | ||
313 | {0x889, 0x00}, | ||
314 | {0x88A, 0x64}, | ||
315 | {0x88B, 0x00}, | ||
316 | {0x88C, 0x03}, | ||
317 | {0x88D, 0x00}, | ||
318 | {0x88E, 0xB1}, | ||
319 | {0x88F, 0x00}, | ||
320 | {0x890, 0x03}, | ||
321 | {0x891, 0x01}, | ||
322 | {0x892, 0x1D}, | ||
323 | {0x893, 0x00}, | ||
324 | {0x894, 0x03}, | ||
325 | {0x895, 0x01}, | ||
326 | {0x896, 0x4B}, | ||
327 | {0x897, 0x00}, | ||
328 | {0x898, 0xE5}, | ||
329 | {0x899, 0x00}, | ||
330 | {0x89A, 0x01}, | ||
331 | {0x89B, 0x00}, | ||
332 | {0x89C, 0x01}, | ||
333 | {0x89D, 0x04}, | ||
334 | {0x89E, 0xC8}, | ||
335 | {0x89F, 0x00}, | ||
336 | {0x8A0, 0x01}, | ||
337 | {0x8A1, 0x01}, | ||
338 | {0x8A2, 0x61}, | ||
339 | {0x8A3, 0x00}, | ||
340 | {0x8A4, 0x01}, | ||
341 | {0x8A5, 0x00}, | ||
342 | {0x8A6, 0x00}, | ||
343 | {0x8A7, 0x00}, | ||
344 | {0x8A8, 0x00}, | ||
345 | {0x8A9, 0x00}, | ||
346 | {0x8AA, 0x7F}, | ||
347 | {0x8AB, 0x03}, | ||
348 | {0x8AC, 0x00}, | ||
349 | {0x8AD, 0x00}, | ||
350 | {0x8AE, 0x00}, | ||
351 | {0x8AF, 0x00}, | ||
352 | {0x8B0, 0x00}, | ||
353 | {0x8B1, 0x00}, | ||
354 | {0x8B6, 0x00}, | ||
355 | {0x8B7, 0x01}, | ||
356 | {0x8B8, 0x00}, | ||
357 | {0x8B9, 0x00}, | ||
358 | {0x8BA, 0x02}, | ||
359 | {0x8BB, 0x00}, | ||
360 | {0x8BC, 0xFF}, | ||
361 | {0x8BD, 0x00}, | ||
362 | {0x8FE, 0x02}, | ||
363 | }; | ||
364 | |||
365 | const static struct rj54n1_reg_val bank_10[] = { | ||
366 | {0x10bf, 0x69} | ||
367 | }; | ||
368 | |||
369 | /* Clock dividers - these are default register values, divider = register + 1 */ | ||
370 | const static struct rj54n1_clock_div clk_div = { | ||
371 | .ratio_tg = 3 /* default: 5 */, | ||
372 | .ratio_t = 4 /* default: 1 */, | ||
373 | .ratio_r = 4 /* default: 0 */, | ||
374 | .ratio_op = 1 /* default: 5 */, | ||
375 | .ratio_o = 9 /* default: 0 */, | ||
376 | }; | ||
377 | |||
378 | static struct rj54n1 *to_rj54n1(const struct i2c_client *client) | ||
379 | { | ||
380 | return container_of(i2c_get_clientdata(client), struct rj54n1, subdev); | ||
381 | } | ||
382 | |||
383 | static int reg_read(struct i2c_client *client, const u16 reg) | ||
384 | { | ||
385 | struct rj54n1 *rj54n1 = to_rj54n1(client); | ||
386 | int ret; | ||
387 | |||
388 | /* set bank */ | ||
389 | if (rj54n1->bank != reg >> 8) { | ||
390 | dev_dbg(&client->dev, "[0x%x] = 0x%x\n", 0xff, reg >> 8); | ||
391 | ret = i2c_smbus_write_byte_data(client, 0xff, reg >> 8); | ||
392 | if (ret < 0) | ||
393 | return ret; | ||
394 | rj54n1->bank = reg >> 8; | ||
395 | } | ||
396 | return i2c_smbus_read_byte_data(client, reg & 0xff); | ||
397 | } | ||
398 | |||
399 | static int reg_write(struct i2c_client *client, const u16 reg, | ||
400 | const u8 data) | ||
401 | { | ||
402 | struct rj54n1 *rj54n1 = to_rj54n1(client); | ||
403 | int ret; | ||
404 | |||
405 | /* set bank */ | ||
406 | if (rj54n1->bank != reg >> 8) { | ||
407 | dev_dbg(&client->dev, "[0x%x] = 0x%x\n", 0xff, reg >> 8); | ||
408 | ret = i2c_smbus_write_byte_data(client, 0xff, reg >> 8); | ||
409 | if (ret < 0) | ||
410 | return ret; | ||
411 | rj54n1->bank = reg >> 8; | ||
412 | } | ||
413 | dev_dbg(&client->dev, "[0x%x] = 0x%x\n", reg & 0xff, data); | ||
414 | return i2c_smbus_write_byte_data(client, reg & 0xff, data); | ||
415 | } | ||
416 | |||
417 | static int reg_set(struct i2c_client *client, const u16 reg, | ||
418 | const u8 data, const u8 mask) | ||
419 | { | ||
420 | int ret; | ||
421 | |||
422 | ret = reg_read(client, reg); | ||
423 | if (ret < 0) | ||
424 | return ret; | ||
425 | return reg_write(client, reg, (ret & ~mask) | (data & mask)); | ||
426 | } | ||
427 | |||
428 | static int reg_write_multiple(struct i2c_client *client, | ||
429 | const struct rj54n1_reg_val *rv, const int n) | ||
430 | { | ||
431 | int i, ret; | ||
432 | |||
433 | for (i = 0; i < n; i++) { | ||
434 | ret = reg_write(client, rv->reg, rv->val); | ||
435 | if (ret < 0) | ||
436 | return ret; | ||
437 | rv++; | ||
438 | } | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | static int rj54n1_s_stream(struct v4l2_subdev *sd, int enable) | ||
444 | { | ||
445 | /* TODO: start / stop streaming */ | ||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | static int rj54n1_set_bus_param(struct soc_camera_device *icd, | ||
450 | unsigned long flags) | ||
451 | { | ||
452 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
453 | struct i2c_client *client = sd->priv; | ||
454 | /* Figures 2.5-1 to 2.5-3 - default falling pixclk edge */ | ||
455 | |||
456 | if (flags & SOCAM_PCLK_SAMPLE_RISING) | ||
457 | return reg_write(client, RJ54N1_OUT_SIGPO, 1 << 4); | ||
458 | else | ||
459 | return reg_write(client, RJ54N1_OUT_SIGPO, 0); | ||
460 | } | ||
461 | |||
462 | static unsigned long rj54n1_query_bus_param(struct soc_camera_device *icd) | ||
463 | { | ||
464 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
465 | const unsigned long flags = | ||
466 | SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING | | ||
467 | SOCAM_MASTER | SOCAM_DATAWIDTH_8 | | ||
468 | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | | ||
469 | SOCAM_DATA_ACTIVE_HIGH; | ||
470 | |||
471 | return soc_camera_apply_sensor_flags(icl, flags); | ||
472 | } | ||
473 | |||
474 | static int rj54n1_set_rect(struct i2c_client *client, | ||
475 | u16 reg_x, u16 reg_y, u16 reg_xy, | ||
476 | u32 width, u32 height) | ||
477 | { | ||
478 | int ret; | ||
479 | |||
480 | ret = reg_write(client, reg_xy, | ||
481 | ((width >> 4) & 0x70) | | ||
482 | ((height >> 8) & 7)); | ||
483 | |||
484 | if (!ret) | ||
485 | ret = reg_write(client, reg_x, width & 0xff); | ||
486 | if (!ret) | ||
487 | ret = reg_write(client, reg_y, height & 0xff); | ||
488 | |||
489 | return ret; | ||
490 | } | ||
491 | |||
492 | /* | ||
493 | * Some commands, specifically certain initialisation sequences, require | ||
494 | * a commit operation. | ||
495 | */ | ||
496 | static int rj54n1_commit(struct i2c_client *client) | ||
497 | { | ||
498 | int ret = reg_write(client, RJ54N1_INIT_START, 1); | ||
499 | msleep(10); | ||
500 | if (!ret) | ||
501 | ret = reg_write(client, RJ54N1_INIT_START, 0); | ||
502 | return ret; | ||
503 | } | ||
504 | |||
505 | static int rj54n1_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | ||
506 | { | ||
507 | struct i2c_client *client = sd->priv; | ||
508 | struct rj54n1 *rj54n1 = to_rj54n1(client); | ||
509 | |||
510 | a->c = rj54n1->rect; | ||
511 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
512 | |||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | static int rj54n1_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) | ||
517 | { | ||
518 | a->bounds.left = RJ54N1_COLUMN_SKIP; | ||
519 | a->bounds.top = RJ54N1_ROW_SKIP; | ||
520 | a->bounds.width = RJ54N1_MAX_WIDTH; | ||
521 | a->bounds.height = RJ54N1_MAX_HEIGHT; | ||
522 | a->defrect = a->bounds; | ||
523 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
524 | a->pixelaspect.numerator = 1; | ||
525 | a->pixelaspect.denominator = 1; | ||
526 | |||
527 | return 0; | ||
528 | } | ||
529 | |||
530 | static int rj54n1_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | ||
531 | { | ||
532 | struct i2c_client *client = sd->priv; | ||
533 | struct rj54n1 *rj54n1 = to_rj54n1(client); | ||
534 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
535 | |||
536 | pix->pixelformat = rj54n1->fourcc; | ||
537 | pix->field = V4L2_FIELD_NONE; | ||
538 | pix->width = rj54n1->width; | ||
539 | pix->height = rj54n1->height; | ||
540 | |||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | /* | ||
545 | * The actual geometry configuration routine. It scales the input window into | ||
546 | * the output one, updates the window sizes and returns an error or the resize | ||
547 | * coefficient on success. Note: we only use the "Fixed Scaling" on this camera. | ||
548 | */ | ||
549 | static int rj54n1_sensor_scale(struct v4l2_subdev *sd, u32 *in_w, u32 *in_h, | ||
550 | u32 *out_w, u32 *out_h) | ||
551 | { | ||
552 | struct i2c_client *client = sd->priv; | ||
553 | unsigned int skip, resize, input_w = *in_w, input_h = *in_h, | ||
554 | output_w = *out_w, output_h = *out_h; | ||
555 | u16 inc_sel; | ||
556 | int ret; | ||
557 | |||
558 | ret = rj54n1_set_rect(client, RJ54N1_X_OUTPUT_SIZE_S_L, | ||
559 | RJ54N1_Y_OUTPUT_SIZE_S_L, | ||
560 | RJ54N1_XY_OUTPUT_SIZE_S_H, output_w, output_h); | ||
561 | if (!ret) | ||
562 | ret = rj54n1_set_rect(client, RJ54N1_X_OUTPUT_SIZE_P_L, | ||
563 | RJ54N1_Y_OUTPUT_SIZE_P_L, | ||
564 | RJ54N1_XY_OUTPUT_SIZE_P_H, output_w, output_h); | ||
565 | |||
566 | if (ret < 0) | ||
567 | return ret; | ||
568 | |||
569 | if (output_w > input_w || output_h > input_h) { | ||
570 | input_w = output_w; | ||
571 | input_h = output_h; | ||
572 | |||
573 | resize = 1024; | ||
574 | } else { | ||
575 | unsigned int resize_x, resize_y; | ||
576 | resize_x = input_w * 1024 / output_w; | ||
577 | resize_y = input_h * 1024 / output_h; | ||
578 | |||
579 | resize = min(resize_x, resize_y); | ||
580 | |||
581 | /* Prohibited value ranges */ | ||
582 | switch (resize) { | ||
583 | case 2040 ... 2047: | ||
584 | resize = 2039; | ||
585 | break; | ||
586 | case 4080 ... 4095: | ||
587 | resize = 4079; | ||
588 | break; | ||
589 | case 8160 ... 8191: | ||
590 | resize = 8159; | ||
591 | break; | ||
592 | case 16320 ... 16383: | ||
593 | resize = 16319; | ||
594 | } | ||
595 | |||
596 | input_w = output_w * resize / 1024; | ||
597 | input_h = output_h * resize / 1024; | ||
598 | } | ||
599 | |||
600 | /* Set scaling */ | ||
601 | ret = reg_write(client, RJ54N1_RESIZE_HOLD_L, resize & 0xff); | ||
602 | if (!ret) | ||
603 | ret = reg_write(client, RJ54N1_RESIZE_HOLD_H, resize >> 8); | ||
604 | |||
605 | if (ret < 0) | ||
606 | return ret; | ||
607 | |||
608 | /* | ||
609 | * Configure a skipping bitmask. The sensor will select a skipping value | ||
610 | * among set bits automatically. | ||
611 | */ | ||
612 | skip = min(resize / 1024, (unsigned)15); | ||
613 | inc_sel = 1 << skip; | ||
614 | |||
615 | if (inc_sel <= 2) | ||
616 | inc_sel = 0xc; | ||
617 | else if (resize & 1023 && skip < 15) | ||
618 | inc_sel |= 1 << (skip + 1); | ||
619 | |||
620 | ret = reg_write(client, RJ54N1_INC_USE_SEL_L, inc_sel & 0xfc); | ||
621 | if (!ret) | ||
622 | ret = reg_write(client, RJ54N1_INC_USE_SEL_H, inc_sel >> 8); | ||
623 | |||
624 | /* Start resizing */ | ||
625 | if (!ret) | ||
626 | ret = reg_write(client, RJ54N1_RESIZE_CONTROL, | ||
627 | RESIZE_HOLD_SEL | RESIZE_GO | 1); | ||
628 | |||
629 | if (ret < 0) | ||
630 | return ret; | ||
631 | |||
632 | dev_dbg(&client->dev, "resize %u, skip %u\n", resize, skip); | ||
633 | |||
634 | /* Constant taken from manufacturer's example */ | ||
635 | msleep(230); | ||
636 | |||
637 | ret = reg_write(client, RJ54N1_RESIZE_CONTROL, RESIZE_HOLD_SEL | 1); | ||
638 | if (ret < 0) | ||
639 | return ret; | ||
640 | |||
641 | *in_w = input_w; | ||
642 | *in_h = input_h; | ||
643 | *out_w = output_w; | ||
644 | *out_h = output_h; | ||
645 | |||
646 | return resize; | ||
647 | } | ||
648 | |||
649 | static int rj54n1_set_clock(struct i2c_client *client) | ||
650 | { | ||
651 | struct rj54n1 *rj54n1 = to_rj54n1(client); | ||
652 | int ret; | ||
653 | |||
654 | /* Enable external clock */ | ||
655 | ret = reg_write(client, RJ54N1_RESET_STANDBY, E_EXCLK | SOFT_STDBY); | ||
656 | /* Leave stand-by */ | ||
657 | if (!ret) | ||
658 | ret = reg_write(client, RJ54N1_RESET_STANDBY, E_EXCLK); | ||
659 | |||
660 | if (!ret) | ||
661 | ret = reg_write(client, RJ54N1_PLL_L, 2); | ||
662 | if (!ret) | ||
663 | ret = reg_write(client, RJ54N1_PLL_N, 0x31); | ||
664 | |||
665 | /* TGCLK dividers */ | ||
666 | if (!ret) | ||
667 | ret = reg_write(client, RJ54N1_RATIO_TG, | ||
668 | rj54n1->clk_div.ratio_tg); | ||
669 | if (!ret) | ||
670 | ret = reg_write(client, RJ54N1_RATIO_T, | ||
671 | rj54n1->clk_div.ratio_t); | ||
672 | if (!ret) | ||
673 | ret = reg_write(client, RJ54N1_RATIO_R, | ||
674 | rj54n1->clk_div.ratio_r); | ||
675 | |||
676 | /* Enable TGCLK & RAMP */ | ||
677 | if (!ret) | ||
678 | ret = reg_write(client, RJ54N1_RAMP_TGCLK_EN, 3); | ||
679 | |||
680 | /* Disable clock output */ | ||
681 | if (!ret) | ||
682 | ret = reg_write(client, RJ54N1_OCLK_DSP, 0); | ||
683 | |||
684 | /* Set divisors */ | ||
685 | if (!ret) | ||
686 | ret = reg_write(client, RJ54N1_RATIO_OP, | ||
687 | rj54n1->clk_div.ratio_op); | ||
688 | if (!ret) | ||
689 | ret = reg_write(client, RJ54N1_RATIO_O, | ||
690 | rj54n1->clk_div.ratio_o); | ||
691 | |||
692 | /* Enable OCLK */ | ||
693 | if (!ret) | ||
694 | ret = reg_write(client, RJ54N1_OCLK_SEL_EN, 1); | ||
695 | |||
696 | /* Use PLL for Timing Generator, write 2 to reserved bits */ | ||
697 | if (!ret) | ||
698 | ret = reg_write(client, RJ54N1_TG_BYPASS, 2); | ||
699 | |||
700 | /* Take sensor out of reset */ | ||
701 | if (!ret) | ||
702 | ret = reg_write(client, RJ54N1_RESET_STANDBY, | ||
703 | E_EXCLK | SEN_RSTX); | ||
704 | /* Enable PLL */ | ||
705 | if (!ret) | ||
706 | ret = reg_write(client, RJ54N1_PLL_EN, 1); | ||
707 | |||
708 | /* Wait for PLL to stabilise */ | ||
709 | msleep(10); | ||
710 | |||
711 | /* Enable clock to frequency divider */ | ||
712 | if (!ret) | ||
713 | ret = reg_write(client, RJ54N1_CLK_RST, 1); | ||
714 | |||
715 | if (!ret) | ||
716 | ret = reg_read(client, RJ54N1_CLK_RST); | ||
717 | if (ret != 1) { | ||
718 | dev_err(&client->dev, | ||
719 | "Resetting RJ54N1CB0C clock failed: %d!\n", ret); | ||
720 | return -EIO; | ||
721 | } | ||
722 | /* Start the PLL */ | ||
723 | ret = reg_set(client, RJ54N1_OCLK_DSP, 1, 1); | ||
724 | |||
725 | /* Enable OCLK */ | ||
726 | if (!ret) | ||
727 | ret = reg_write(client, RJ54N1_OCLK_SEL_EN, 1); | ||
728 | |||
729 | return ret; | ||
730 | } | ||
731 | |||
732 | static int rj54n1_reg_init(struct i2c_client *client) | ||
733 | { | ||
734 | int ret = rj54n1_set_clock(client); | ||
735 | |||
736 | if (!ret) | ||
737 | ret = reg_write_multiple(client, bank_7, ARRAY_SIZE(bank_7)); | ||
738 | if (!ret) | ||
739 | ret = reg_write_multiple(client, bank_10, ARRAY_SIZE(bank_10)); | ||
740 | |||
741 | /* Set binning divisors */ | ||
742 | if (!ret) | ||
743 | ret = reg_write(client, RJ54N1_SCALE_1_2_LEV, 3 | (7 << 4)); | ||
744 | if (!ret) | ||
745 | ret = reg_write(client, RJ54N1_SCALE_4_LEV, 0xf); | ||
746 | |||
747 | /* Switch to fixed resize mode */ | ||
748 | if (!ret) | ||
749 | ret = reg_write(client, RJ54N1_RESIZE_CONTROL, | ||
750 | RESIZE_HOLD_SEL | 1); | ||
751 | |||
752 | /* Set gain */ | ||
753 | if (!ret) | ||
754 | ret = reg_write(client, RJ54N1_Y_GAIN, 0x84); | ||
755 | |||
756 | /* Mirror the image back: default is upside down and left-to-right... */ | ||
757 | if (!ret) | ||
758 | ret = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 3, 3); | ||
759 | |||
760 | if (!ret) | ||
761 | ret = reg_write_multiple(client, bank_4, ARRAY_SIZE(bank_4)); | ||
762 | if (!ret) | ||
763 | ret = reg_write_multiple(client, bank_5, ARRAY_SIZE(bank_5)); | ||
764 | if (!ret) | ||
765 | ret = reg_write_multiple(client, bank_8, ARRAY_SIZE(bank_8)); | ||
766 | |||
767 | if (!ret) | ||
768 | ret = reg_write(client, RJ54N1_RESET_STANDBY, | ||
769 | E_EXCLK | DSP_RSTX | SEN_RSTX); | ||
770 | |||
771 | /* Commit init */ | ||
772 | if (!ret) | ||
773 | ret = rj54n1_commit(client); | ||
774 | |||
775 | /* Take DSP, TG, sensor out of reset */ | ||
776 | if (!ret) | ||
777 | ret = reg_write(client, RJ54N1_RESET_STANDBY, | ||
778 | E_EXCLK | DSP_RSTX | TG_RSTX | SEN_RSTX); | ||
779 | |||
780 | if (!ret) | ||
781 | ret = reg_write(client, 0x7fe, 2); | ||
782 | |||
783 | /* Constant taken from manufacturer's example */ | ||
784 | msleep(700); | ||
785 | |||
786 | return ret; | ||
787 | } | ||
788 | |||
789 | /* FIXME: streaming output only up to 800x600 is functional */ | ||
790 | static int rj54n1_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | ||
791 | { | ||
792 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
793 | |||
794 | pix->field = V4L2_FIELD_NONE; | ||
795 | |||
796 | if (pix->width > 800) | ||
797 | pix->width = 800; | ||
798 | if (pix->height > 600) | ||
799 | pix->height = 600; | ||
800 | |||
801 | return 0; | ||
802 | } | ||
803 | |||
804 | static int rj54n1_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | ||
805 | { | ||
806 | struct i2c_client *client = sd->priv; | ||
807 | struct rj54n1 *rj54n1 = to_rj54n1(client); | ||
808 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
809 | unsigned int output_w, output_h, | ||
810 | input_w = rj54n1->rect.width, input_h = rj54n1->rect.height; | ||
811 | int ret; | ||
812 | |||
813 | /* | ||
814 | * The host driver can call us without .try_fmt(), so, we have to take | ||
815 | * care ourseleves | ||
816 | */ | ||
817 | ret = rj54n1_try_fmt(sd, f); | ||
818 | |||
819 | /* | ||
820 | * Verify if the sensor has just been powered on. TODO: replace this | ||
821 | * with proper PM, when a suitable API is available. | ||
822 | */ | ||
823 | if (!ret) | ||
824 | ret = reg_read(client, RJ54N1_RESET_STANDBY); | ||
825 | if (ret < 0) | ||
826 | return ret; | ||
827 | |||
828 | if (!(ret & E_EXCLK)) { | ||
829 | ret = rj54n1_reg_init(client); | ||
830 | if (ret < 0) | ||
831 | return ret; | ||
832 | } | ||
833 | |||
834 | /* RA_SEL_UL is only relevant for raw modes, ignored otherwise. */ | ||
835 | switch (pix->pixelformat) { | ||
836 | case V4L2_PIX_FMT_YUYV: | ||
837 | ret = reg_write(client, RJ54N1_OUT_SEL, 0); | ||
838 | if (!ret) | ||
839 | ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8); | ||
840 | break; | ||
841 | case V4L2_PIX_FMT_RGB565: | ||
842 | ret = reg_write(client, RJ54N1_OUT_SEL, 0x11); | ||
843 | if (!ret) | ||
844 | ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8); | ||
845 | break; | ||
846 | default: | ||
847 | ret = -EINVAL; | ||
848 | } | ||
849 | |||
850 | if (ret < 0) | ||
851 | return ret; | ||
852 | |||
853 | /* Supported scales 1:1 - 1:16 */ | ||
854 | if (pix->width < input_w / 16) | ||
855 | pix->width = input_w / 16; | ||
856 | if (pix->height < input_h / 16) | ||
857 | pix->height = input_h / 16; | ||
858 | |||
859 | output_w = pix->width; | ||
860 | output_h = pix->height; | ||
861 | |||
862 | ret = rj54n1_sensor_scale(sd, &input_w, &input_h, &output_w, &output_h); | ||
863 | if (ret < 0) | ||
864 | return ret; | ||
865 | |||
866 | rj54n1->fourcc = pix->pixelformat; | ||
867 | rj54n1->resize = ret; | ||
868 | rj54n1->rect.width = input_w; | ||
869 | rj54n1->rect.height = input_h; | ||
870 | rj54n1->width = output_w; | ||
871 | rj54n1->height = output_h; | ||
872 | |||
873 | pix->width = output_w; | ||
874 | pix->height = output_h; | ||
875 | pix->field = V4L2_FIELD_NONE; | ||
876 | |||
877 | return ret; | ||
878 | } | ||
879 | |||
880 | static int rj54n1_g_chip_ident(struct v4l2_subdev *sd, | ||
881 | struct v4l2_dbg_chip_ident *id) | ||
882 | { | ||
883 | struct i2c_client *client = sd->priv; | ||
884 | |||
885 | if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) | ||
886 | return -EINVAL; | ||
887 | |||
888 | if (id->match.addr != client->addr) | ||
889 | return -ENODEV; | ||
890 | |||
891 | id->ident = V4L2_IDENT_RJ54N1CB0C; | ||
892 | id->revision = 0; | ||
893 | |||
894 | return 0; | ||
895 | } | ||
896 | |||
897 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
898 | static int rj54n1_g_register(struct v4l2_subdev *sd, | ||
899 | struct v4l2_dbg_register *reg) | ||
900 | { | ||
901 | struct i2c_client *client = sd->priv; | ||
902 | |||
903 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || | ||
904 | reg->reg < 0x400 || reg->reg > 0x1fff) | ||
905 | /* Registers > 0x0800 are only available from Sharp support */ | ||
906 | return -EINVAL; | ||
907 | |||
908 | if (reg->match.addr != client->addr) | ||
909 | return -ENODEV; | ||
910 | |||
911 | reg->size = 1; | ||
912 | reg->val = reg_read(client, reg->reg); | ||
913 | |||
914 | if (reg->val > 0xff) | ||
915 | return -EIO; | ||
916 | |||
917 | return 0; | ||
918 | } | ||
919 | |||
920 | static int rj54n1_s_register(struct v4l2_subdev *sd, | ||
921 | struct v4l2_dbg_register *reg) | ||
922 | { | ||
923 | struct i2c_client *client = sd->priv; | ||
924 | |||
925 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || | ||
926 | reg->reg < 0x400 || reg->reg > 0x1fff) | ||
927 | /* Registers >= 0x0800 are only available from Sharp support */ | ||
928 | return -EINVAL; | ||
929 | |||
930 | if (reg->match.addr != client->addr) | ||
931 | return -ENODEV; | ||
932 | |||
933 | if (reg_write(client, reg->reg, reg->val) < 0) | ||
934 | return -EIO; | ||
935 | |||
936 | return 0; | ||
937 | } | ||
938 | #endif | ||
939 | |||
940 | static const struct v4l2_queryctrl rj54n1_controls[] = { | ||
941 | { | ||
942 | .id = V4L2_CID_VFLIP, | ||
943 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
944 | .name = "Flip Vertically", | ||
945 | .minimum = 0, | ||
946 | .maximum = 1, | ||
947 | .step = 1, | ||
948 | .default_value = 0, | ||
949 | }, { | ||
950 | .id = V4L2_CID_HFLIP, | ||
951 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
952 | .name = "Flip Horizontally", | ||
953 | .minimum = 0, | ||
954 | .maximum = 1, | ||
955 | .step = 1, | ||
956 | .default_value = 0, | ||
957 | }, { | ||
958 | .id = V4L2_CID_GAIN, | ||
959 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
960 | .name = "Gain", | ||
961 | .minimum = 0, | ||
962 | .maximum = 127, | ||
963 | .step = 1, | ||
964 | .default_value = 66, | ||
965 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
966 | }, | ||
967 | }; | ||
968 | |||
969 | static struct soc_camera_ops rj54n1_ops = { | ||
970 | .set_bus_param = rj54n1_set_bus_param, | ||
971 | .query_bus_param = rj54n1_query_bus_param, | ||
972 | .controls = rj54n1_controls, | ||
973 | .num_controls = ARRAY_SIZE(rj54n1_controls), | ||
974 | }; | ||
975 | |||
976 | static int rj54n1_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
977 | { | ||
978 | struct i2c_client *client = sd->priv; | ||
979 | int data; | ||
980 | |||
981 | switch (ctrl->id) { | ||
982 | case V4L2_CID_VFLIP: | ||
983 | data = reg_read(client, RJ54N1_MIRROR_STILL_MODE); | ||
984 | if (data < 0) | ||
985 | return -EIO; | ||
986 | ctrl->value = !(data & 1); | ||
987 | break; | ||
988 | case V4L2_CID_HFLIP: | ||
989 | data = reg_read(client, RJ54N1_MIRROR_STILL_MODE); | ||
990 | if (data < 0) | ||
991 | return -EIO; | ||
992 | ctrl->value = !(data & 2); | ||
993 | break; | ||
994 | case V4L2_CID_GAIN: | ||
995 | data = reg_read(client, RJ54N1_Y_GAIN); | ||
996 | if (data < 0) | ||
997 | return -EIO; | ||
998 | |||
999 | ctrl->value = data / 2; | ||
1000 | break; | ||
1001 | } | ||
1002 | |||
1003 | return 0; | ||
1004 | } | ||
1005 | |||
1006 | static int rj54n1_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
1007 | { | ||
1008 | int data; | ||
1009 | struct i2c_client *client = sd->priv; | ||
1010 | const struct v4l2_queryctrl *qctrl; | ||
1011 | |||
1012 | qctrl = soc_camera_find_qctrl(&rj54n1_ops, ctrl->id); | ||
1013 | if (!qctrl) | ||
1014 | return -EINVAL; | ||
1015 | |||
1016 | switch (ctrl->id) { | ||
1017 | case V4L2_CID_VFLIP: | ||
1018 | if (ctrl->value) | ||
1019 | data = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 0, 1); | ||
1020 | else | ||
1021 | data = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 1, 1); | ||
1022 | if (data < 0) | ||
1023 | return -EIO; | ||
1024 | break; | ||
1025 | case V4L2_CID_HFLIP: | ||
1026 | if (ctrl->value) | ||
1027 | data = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 0, 2); | ||
1028 | else | ||
1029 | data = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 2, 2); | ||
1030 | if (data < 0) | ||
1031 | return -EIO; | ||
1032 | break; | ||
1033 | case V4L2_CID_GAIN: | ||
1034 | if (ctrl->value > qctrl->maximum || | ||
1035 | ctrl->value < qctrl->minimum) | ||
1036 | return -EINVAL; | ||
1037 | else if (reg_write(client, RJ54N1_Y_GAIN, ctrl->value * 2) < 0) | ||
1038 | return -EIO; | ||
1039 | break; | ||
1040 | } | ||
1041 | |||
1042 | return 0; | ||
1043 | } | ||
1044 | |||
1045 | static struct v4l2_subdev_core_ops rj54n1_subdev_core_ops = { | ||
1046 | .g_ctrl = rj54n1_g_ctrl, | ||
1047 | .s_ctrl = rj54n1_s_ctrl, | ||
1048 | .g_chip_ident = rj54n1_g_chip_ident, | ||
1049 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1050 | .g_register = rj54n1_g_register, | ||
1051 | .s_register = rj54n1_s_register, | ||
1052 | #endif | ||
1053 | }; | ||
1054 | |||
1055 | static struct v4l2_subdev_video_ops rj54n1_subdev_video_ops = { | ||
1056 | .s_stream = rj54n1_s_stream, | ||
1057 | .s_fmt = rj54n1_s_fmt, | ||
1058 | .g_fmt = rj54n1_g_fmt, | ||
1059 | .try_fmt = rj54n1_try_fmt, | ||
1060 | .g_crop = rj54n1_g_crop, | ||
1061 | .cropcap = rj54n1_cropcap, | ||
1062 | }; | ||
1063 | |||
1064 | static struct v4l2_subdev_ops rj54n1_subdev_ops = { | ||
1065 | .core = &rj54n1_subdev_core_ops, | ||
1066 | .video = &rj54n1_subdev_video_ops, | ||
1067 | }; | ||
1068 | |||
1069 | static int rj54n1_pin_config(struct i2c_client *client) | ||
1070 | { | ||
1071 | /* | ||
1072 | * Experimentally found out IOCTRL wired to 0. TODO: add to platform | ||
1073 | * data: 0 or 1 << 7. | ||
1074 | */ | ||
1075 | return reg_write(client, RJ54N1_IOC, 0); | ||
1076 | } | ||
1077 | |||
1078 | /* | ||
1079 | * Interface active, can use i2c. If it fails, it can indeed mean, that | ||
1080 | * this wasn't our capture interface, so, we wait for the right one | ||
1081 | */ | ||
1082 | static int rj54n1_video_probe(struct soc_camera_device *icd, | ||
1083 | struct i2c_client *client) | ||
1084 | { | ||
1085 | int data1, data2; | ||
1086 | int ret; | ||
1087 | |||
1088 | /* This could be a BUG_ON() or a WARN_ON(), or remove it completely */ | ||
1089 | if (!icd->dev.parent || | ||
1090 | to_soc_camera_host(icd->dev.parent)->nr != icd->iface) | ||
1091 | return -ENODEV; | ||
1092 | |||
1093 | /* Read out the chip version register */ | ||
1094 | data1 = reg_read(client, RJ54N1_DEV_CODE); | ||
1095 | data2 = reg_read(client, RJ54N1_DEV_CODE2); | ||
1096 | |||
1097 | if (data1 != 0x51 || data2 != 0x10) { | ||
1098 | ret = -ENODEV; | ||
1099 | dev_info(&client->dev, "No RJ54N1CB0C found, read 0x%x:0x%x\n", | ||
1100 | data1, data2); | ||
1101 | goto ei2c; | ||
1102 | } | ||
1103 | |||
1104 | ret = rj54n1_pin_config(client); | ||
1105 | if (ret < 0) | ||
1106 | goto ei2c; | ||
1107 | |||
1108 | dev_info(&client->dev, "Detected a RJ54N1CB0C chip ID 0x%x:0x%x\n", | ||
1109 | data1, data2); | ||
1110 | |||
1111 | ei2c: | ||
1112 | return ret; | ||
1113 | } | ||
1114 | |||
1115 | static int rj54n1_probe(struct i2c_client *client, | ||
1116 | const struct i2c_device_id *did) | ||
1117 | { | ||
1118 | struct rj54n1 *rj54n1; | ||
1119 | struct soc_camera_device *icd = client->dev.platform_data; | ||
1120 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | ||
1121 | struct soc_camera_link *icl; | ||
1122 | int ret; | ||
1123 | |||
1124 | if (!icd) { | ||
1125 | dev_err(&client->dev, "RJ54N1CB0C: missing soc-camera data!\n"); | ||
1126 | return -EINVAL; | ||
1127 | } | ||
1128 | |||
1129 | icl = to_soc_camera_link(icd); | ||
1130 | if (!icl) { | ||
1131 | dev_err(&client->dev, "RJ54N1CB0C: missing platform data!\n"); | ||
1132 | return -EINVAL; | ||
1133 | } | ||
1134 | |||
1135 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | ||
1136 | dev_warn(&adapter->dev, | ||
1137 | "I2C-Adapter doesn't support I2C_FUNC_SMBUS_BYTE\n"); | ||
1138 | return -EIO; | ||
1139 | } | ||
1140 | |||
1141 | rj54n1 = kzalloc(sizeof(struct rj54n1), GFP_KERNEL); | ||
1142 | if (!rj54n1) | ||
1143 | return -ENOMEM; | ||
1144 | |||
1145 | v4l2_i2c_subdev_init(&rj54n1->subdev, client, &rj54n1_subdev_ops); | ||
1146 | |||
1147 | icd->ops = &rj54n1_ops; | ||
1148 | |||
1149 | rj54n1->clk_div = clk_div; | ||
1150 | rj54n1->rect.left = RJ54N1_COLUMN_SKIP; | ||
1151 | rj54n1->rect.top = RJ54N1_ROW_SKIP; | ||
1152 | rj54n1->rect.width = RJ54N1_MAX_WIDTH; | ||
1153 | rj54n1->rect.height = RJ54N1_MAX_HEIGHT; | ||
1154 | rj54n1->width = RJ54N1_MAX_WIDTH; | ||
1155 | rj54n1->height = RJ54N1_MAX_HEIGHT; | ||
1156 | rj54n1->fourcc = V4L2_PIX_FMT_YUYV; | ||
1157 | rj54n1->resize = 1024; | ||
1158 | |||
1159 | ret = rj54n1_video_probe(icd, client); | ||
1160 | if (ret < 0) { | ||
1161 | icd->ops = NULL; | ||
1162 | i2c_set_clientdata(client, NULL); | ||
1163 | kfree(rj54n1); | ||
1164 | return ret; | ||
1165 | } | ||
1166 | |||
1167 | icd->formats = rj54n1_colour_formats; | ||
1168 | icd->num_formats = ARRAY_SIZE(rj54n1_colour_formats); | ||
1169 | |||
1170 | return ret; | ||
1171 | } | ||
1172 | |||
1173 | static int rj54n1_remove(struct i2c_client *client) | ||
1174 | { | ||
1175 | struct rj54n1 *rj54n1 = to_rj54n1(client); | ||
1176 | struct soc_camera_device *icd = client->dev.platform_data; | ||
1177 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
1178 | |||
1179 | icd->ops = NULL; | ||
1180 | if (icl->free_bus) | ||
1181 | icl->free_bus(icl); | ||
1182 | i2c_set_clientdata(client, NULL); | ||
1183 | client->driver = NULL; | ||
1184 | kfree(rj54n1); | ||
1185 | |||
1186 | return 0; | ||
1187 | } | ||
1188 | |||
1189 | static const struct i2c_device_id rj54n1_id[] = { | ||
1190 | { "rj54n1cb0c", 0 }, | ||
1191 | { } | ||
1192 | }; | ||
1193 | MODULE_DEVICE_TABLE(i2c, rj54n1_id); | ||
1194 | |||
1195 | static struct i2c_driver rj54n1_i2c_driver = { | ||
1196 | .driver = { | ||
1197 | .name = "rj54n1cb0c", | ||
1198 | }, | ||
1199 | .probe = rj54n1_probe, | ||
1200 | .remove = rj54n1_remove, | ||
1201 | .id_table = rj54n1_id, | ||
1202 | }; | ||
1203 | |||
1204 | static int __init rj54n1_mod_init(void) | ||
1205 | { | ||
1206 | return i2c_add_driver(&rj54n1_i2c_driver); | ||
1207 | } | ||
1208 | |||
1209 | static void __exit rj54n1_mod_exit(void) | ||
1210 | { | ||
1211 | i2c_del_driver(&rj54n1_i2c_driver); | ||
1212 | } | ||
1213 | |||
1214 | module_init(rj54n1_mod_init); | ||
1215 | module_exit(rj54n1_mod_exit); | ||
1216 | |||
1217 | MODULE_DESCRIPTION("Sharp RJ54N1CB0C Camera driver"); | ||
1218 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); | ||
1219 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 03d39266d293..41765f3c7c28 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c | |||
@@ -1958,7 +1958,7 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) | |||
1958 | if (pdword[1] >= MAX_CHANNELS) | 1958 | if (pdword[1] >= MAX_CHANNELS) |
1959 | break; | 1959 | break; |
1960 | cc = G_chnmap[pdword[1]]; | 1960 | cc = G_chnmap[pdword[1]]; |
1961 | if (!(cc >= 0 && cc < MAX_CHANNELS)) | 1961 | if (cc >= MAX_CHANNELS) |
1962 | break; | 1962 | break; |
1963 | switch (pdword[2]) { | 1963 | switch (pdword[2]) { |
1964 | case S2255_RESPONSE_SETMODE: | 1964 | case S2255_RESPONSE_SETMODE: |
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index 5c24c993ac16..3bca744e43af 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c | |||
@@ -304,7 +304,7 @@ static int saa7110_s_routing(struct v4l2_subdev *sd, | |||
304 | { | 304 | { |
305 | struct saa7110 *decoder = to_saa7110(sd); | 305 | struct saa7110 *decoder = to_saa7110(sd); |
306 | 306 | ||
307 | if (input < 0 || input >= SAA7110_MAX_INPUT) { | 307 | if (input >= SAA7110_MAX_INPUT) { |
308 | v4l2_dbg(1, debug, sd, "input=%d not available\n", input); | 308 | v4l2_dbg(1, debug, sd, "input=%d not available\n", input); |
309 | return -EINVAL; | 309 | return -EINVAL; |
310 | } | 310 | } |
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 09013229d4aa..7e40d6d99dd0 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -5239,6 +5239,7 @@ struct saa7134_board saa7134_boards[] = { | |||
5239 | .radio_type = UNSET, | 5239 | .radio_type = UNSET, |
5240 | .tuner_addr = ADDR_UNSET, | 5240 | .tuner_addr = ADDR_UNSET, |
5241 | .radio_addr = ADDR_UNSET, | 5241 | .radio_addr = ADDR_UNSET, |
5242 | .mpeg = SAA7134_MPEG_DVB, | ||
5242 | .inputs = { { | 5243 | .inputs = { { |
5243 | .name = name_tv, | 5244 | .name = name_tv, |
5244 | .vmux = 2, | 5245 | .vmux = 2, |
@@ -5279,6 +5280,46 @@ struct saa7134_board saa7134_boards[] = { | |||
5279 | .amux = TV, | 5280 | .amux = TV, |
5280 | }, | 5281 | }, |
5281 | }, | 5282 | }, |
5283 | [SAA7134_BOARD_ASUS_EUROPA_HYBRID] = { | ||
5284 | .name = "Asus Europa Hybrid OEM", | ||
5285 | .audio_clock = 0x00187de7, | ||
5286 | .tuner_type = TUNER_PHILIPS_TD1316, | ||
5287 | .radio_type = UNSET, | ||
5288 | .tuner_addr = 0x61, | ||
5289 | .radio_addr = ADDR_UNSET, | ||
5290 | .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, | ||
5291 | .mpeg = SAA7134_MPEG_DVB, | ||
5292 | .inputs = { { | ||
5293 | .name = name_tv, | ||
5294 | .vmux = 3, | ||
5295 | .amux = TV, | ||
5296 | .tv = 1, | ||
5297 | }, { | ||
5298 | .name = name_comp1, | ||
5299 | .vmux = 4, | ||
5300 | .amux = LINE2, | ||
5301 | }, { | ||
5302 | .name = name_svideo, | ||
5303 | .vmux = 8, | ||
5304 | .amux = LINE2, | ||
5305 | } }, | ||
5306 | }, | ||
5307 | [SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S] = { | ||
5308 | .name = "Leadtek Winfast DTV1000S", | ||
5309 | .audio_clock = 0x00187de7, | ||
5310 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
5311 | .radio_type = UNSET, | ||
5312 | .tuner_addr = ADDR_UNSET, | ||
5313 | .radio_addr = ADDR_UNSET, | ||
5314 | .mpeg = SAA7134_MPEG_DVB, | ||
5315 | .inputs = { { | ||
5316 | .name = name_comp1, | ||
5317 | .vmux = 3, | ||
5318 | }, { | ||
5319 | .name = name_svideo, | ||
5320 | .vmux = 8, | ||
5321 | } }, | ||
5322 | }, | ||
5282 | 5323 | ||
5283 | }; | 5324 | }; |
5284 | 5325 | ||
@@ -6418,6 +6459,18 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
6418 | .subdevice = 0x2004, | 6459 | .subdevice = 0x2004, |
6419 | .driver_data = SAA7134_BOARD_ZOLID_HYBRID_PCI, | 6460 | .driver_data = SAA7134_BOARD_ZOLID_HYBRID_PCI, |
6420 | }, { | 6461 | }, { |
6462 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
6463 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | ||
6464 | .subvendor = 0x1043, | ||
6465 | .subdevice = 0x4847, | ||
6466 | .driver_data = SAA7134_BOARD_ASUS_EUROPA_HYBRID, | ||
6467 | }, { | ||
6468 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
6469 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, | ||
6470 | .subvendor = 0x107d, | ||
6471 | .subdevice = 0x6655, | ||
6472 | .driver_data = SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S, | ||
6473 | }, { | ||
6421 | /* --- boards without eeprom + subsystem ID --- */ | 6474 | /* --- boards without eeprom + subsystem ID --- */ |
6422 | .vendor = PCI_VENDOR_ID_PHILIPS, | 6475 | .vendor = PCI_VENDOR_ID_PHILIPS, |
6423 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | 6476 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, |
@@ -6748,6 +6801,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
6748 | case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: | 6801 | case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: |
6749 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS: | 6802 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS: |
6750 | case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM: | 6803 | case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM: |
6804 | case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S: | ||
6751 | dev->has_remote = SAA7134_REMOTE_GPIO; | 6805 | dev->has_remote = SAA7134_REMOTE_GPIO; |
6752 | break; | 6806 | break; |
6753 | case SAA7134_BOARD_FLYDVBS_LR300: | 6807 | case SAA7134_BOARD_FLYDVBS_LR300: |
@@ -7079,6 +7133,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
7079 | /* break intentionally omitted */ | 7133 | /* break intentionally omitted */ |
7080 | case SAA7134_BOARD_VIDEOMATE_DVBT_300: | 7134 | case SAA7134_BOARD_VIDEOMATE_DVBT_300: |
7081 | case SAA7134_BOARD_ASUS_EUROPA2_HYBRID: | 7135 | case SAA7134_BOARD_ASUS_EUROPA2_HYBRID: |
7136 | case SAA7134_BOARD_ASUS_EUROPA_HYBRID: | ||
7082 | { | 7137 | { |
7083 | 7138 | ||
7084 | /* The Philips EUROPA based hybrid boards have the tuner | 7139 | /* 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 c673901cb2b5..0ba7f5af0fc3 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c | |||
@@ -1032,7 +1032,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
1032 | saa7134_irq_video_signalchange(dev); | 1032 | saa7134_irq_video_signalchange(dev); |
1033 | 1033 | ||
1034 | if (TUNER_ABSENT != dev->tuner_type) | 1034 | if (TUNER_ABSENT != dev->tuner_type) |
1035 | saa_call_all(dev, tuner, s_standby); | 1035 | saa_call_all(dev, core, s_power, 0); |
1036 | 1036 | ||
1037 | /* register v4l devices */ | 1037 | /* register v4l devices */ |
1038 | if (saa7134_no_overlay > 0) | 1038 | if (saa7134_no_overlay > 0) |
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index a26e997a9ce6..73739d2a63dd 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include "tda1004x.h" | 40 | #include "tda1004x.h" |
41 | #include "nxt200x.h" | 41 | #include "nxt200x.h" |
42 | #include "tuner-xc2028.h" | 42 | #include "tuner-xc2028.h" |
43 | #include "xc5000.h" | ||
43 | 44 | ||
44 | #include "tda10086.h" | 45 | #include "tda10086.h" |
45 | #include "tda826x.h" | 46 | #include "tda826x.h" |
@@ -871,6 +872,20 @@ static struct zl10353_config behold_h6_config = { | |||
871 | .disable_i2c_gate_ctrl = 1, | 872 | .disable_i2c_gate_ctrl = 1, |
872 | }; | 873 | }; |
873 | 874 | ||
875 | static struct xc5000_config behold_x7_tunerconfig = { | ||
876 | .i2c_address = 0xc2>>1, | ||
877 | .if_khz = 4560, | ||
878 | .radio_input = XC5000_RADIO_FM1, | ||
879 | }; | ||
880 | |||
881 | static struct zl10353_config behold_x7_config = { | ||
882 | .demod_address = 0x1e>>1, | ||
883 | .if2 = 45600, | ||
884 | .no_tuner = 1, | ||
885 | .parallel_ts = 1, | ||
886 | .disable_i2c_gate_ctrl = 1, | ||
887 | }; | ||
888 | |||
874 | /* ================================================================== | 889 | /* ================================================================== |
875 | * tda10086 based DVB-S cards, helper functions | 890 | * tda10086 based DVB-S cards, helper functions |
876 | */ | 891 | */ |
@@ -1030,6 +1045,32 @@ static struct tda18271_config zolid_tda18271_config = { | |||
1030 | .gate = TDA18271_GATE_ANALOG, | 1045 | .gate = TDA18271_GATE_ANALOG, |
1031 | }; | 1046 | }; |
1032 | 1047 | ||
1048 | static struct tda10048_config dtv1000s_tda10048_config = { | ||
1049 | .demod_address = 0x10 >> 1, | ||
1050 | .output_mode = TDA10048_PARALLEL_OUTPUT, | ||
1051 | .fwbulkwritelen = TDA10048_BULKWRITE_200, | ||
1052 | .inversion = TDA10048_INVERSION_ON, | ||
1053 | .dtv6_if_freq_khz = TDA10048_IF_3300, | ||
1054 | .dtv7_if_freq_khz = TDA10048_IF_3800, | ||
1055 | .dtv8_if_freq_khz = TDA10048_IF_4300, | ||
1056 | .clk_freq_khz = TDA10048_CLK_16000, | ||
1057 | .disable_gate_access = 1, | ||
1058 | }; | ||
1059 | |||
1060 | static struct tda18271_std_map dtv1000s_tda18271_std_map = { | ||
1061 | .dvbt_6 = { .if_freq = 3300, .agc_mode = 3, .std = 4, | ||
1062 | .if_lvl = 1, .rfagc_top = 0x37, }, | ||
1063 | .dvbt_7 = { .if_freq = 3800, .agc_mode = 3, .std = 5, | ||
1064 | .if_lvl = 1, .rfagc_top = 0x37, }, | ||
1065 | .dvbt_8 = { .if_freq = 4300, .agc_mode = 3, .std = 6, | ||
1066 | .if_lvl = 1, .rfagc_top = 0x37, }, | ||
1067 | }; | ||
1068 | |||
1069 | static struct tda18271_config dtv1000s_tda18271_config = { | ||
1070 | .std_map = &dtv1000s_tda18271_std_map, | ||
1071 | .gate = TDA18271_GATE_ANALOG, | ||
1072 | }; | ||
1073 | |||
1033 | /* ================================================================== | 1074 | /* ================================================================== |
1034 | * Core code | 1075 | * Core code |
1035 | */ | 1076 | */ |
@@ -1116,6 +1157,7 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1116 | break; | 1157 | break; |
1117 | case SAA7134_BOARD_PHILIPS_EUROPA: | 1158 | case SAA7134_BOARD_PHILIPS_EUROPA: |
1118 | case SAA7134_BOARD_VIDEOMATE_DVBT_300: | 1159 | case SAA7134_BOARD_VIDEOMATE_DVBT_300: |
1160 | case SAA7134_BOARD_ASUS_EUROPA_HYBRID: | ||
1119 | fe0->dvb.frontend = dvb_attach(tda10046_attach, | 1161 | fe0->dvb.frontend = dvb_attach(tda10046_attach, |
1120 | &philips_europa_config, | 1162 | &philips_europa_config, |
1121 | &dev->i2c_adap); | 1163 | &dev->i2c_adap); |
@@ -1482,6 +1524,15 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1482 | TUNER_PHILIPS_FMD1216MEX_MK3); | 1524 | TUNER_PHILIPS_FMD1216MEX_MK3); |
1483 | } | 1525 | } |
1484 | break; | 1526 | break; |
1527 | case SAA7134_BOARD_BEHOLD_X7: | ||
1528 | fe0->dvb.frontend = dvb_attach(zl10353_attach, | ||
1529 | &behold_x7_config, | ||
1530 | &dev->i2c_adap); | ||
1531 | if (fe0->dvb.frontend) { | ||
1532 | dvb_attach(xc5000_attach, fe0->dvb.frontend, | ||
1533 | &dev->i2c_adap, &behold_x7_tunerconfig); | ||
1534 | } | ||
1535 | break; | ||
1485 | case SAA7134_BOARD_AVERMEDIA_A700_PRO: | 1536 | case SAA7134_BOARD_AVERMEDIA_A700_PRO: |
1486 | case SAA7134_BOARD_AVERMEDIA_A700_HYBRID: | 1537 | case SAA7134_BOARD_AVERMEDIA_A700_HYBRID: |
1487 | /* Zarlink ZL10313 */ | 1538 | /* Zarlink ZL10313 */ |
@@ -1518,6 +1569,19 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1518 | &zolid_tda18271_config); | 1569 | &zolid_tda18271_config); |
1519 | } | 1570 | } |
1520 | break; | 1571 | break; |
1572 | case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S: | ||
1573 | fe0->dvb.frontend = dvb_attach(tda10048_attach, | ||
1574 | &dtv1000s_tda10048_config, | ||
1575 | &dev->i2c_adap); | ||
1576 | if (fe0->dvb.frontend != NULL) { | ||
1577 | dvb_attach(tda829x_attach, fe0->dvb.frontend, | ||
1578 | &dev->i2c_adap, 0x4b, | ||
1579 | &tda829x_no_probe); | ||
1580 | dvb_attach(tda18271_attach, fe0->dvb.frontend, | ||
1581 | 0x60, &dev->i2c_adap, | ||
1582 | &dtv1000s_tda18271_config); | ||
1583 | } | ||
1584 | break; | ||
1521 | default: | 1585 | default: |
1522 | wprintk("Huh? unknown DVB card?\n"); | 1586 | wprintk("Huh? unknown DVB card?\n"); |
1523 | break; | 1587 | break; |
@@ -1550,7 +1614,7 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1550 | 1614 | ||
1551 | /* register everything else */ | 1615 | /* register everything else */ |
1552 | ret = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, | 1616 | ret = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, |
1553 | &dev->pci->dev, adapter_nr, 0); | 1617 | &dev->pci->dev, adapter_nr, 0, NULL); |
1554 | 1618 | ||
1555 | /* this sequence is necessary to make the tda1004x load its firmware | 1619 | /* this sequence is necessary to make the tda1004x load its firmware |
1556 | * and to enter analog mode of hybrid boards | 1620 | * and to enter analog mode of hybrid boards |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index a0e8c62e6ae1..744918b1cd47 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -102,14 +102,14 @@ static int build_key(struct saa7134_dev *dev) | |||
102 | if (data == ir->mask_keycode) | 102 | if (data == ir->mask_keycode) |
103 | ir_input_nokey(ir->dev, &ir->ir); | 103 | ir_input_nokey(ir->dev, &ir->ir); |
104 | else | 104 | else |
105 | ir_input_keydown(ir->dev, &ir->ir, data, data); | 105 | ir_input_keydown(ir->dev, &ir->ir, data); |
106 | return 0; | 106 | return 0; |
107 | } | 107 | } |
108 | 108 | ||
109 | if (ir->polling) { | 109 | if (ir->polling) { |
110 | if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || | 110 | if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || |
111 | (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { | 111 | (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { |
112 | ir_input_keydown(ir->dev, &ir->ir, data, data); | 112 | ir_input_keydown(ir->dev, &ir->ir, data); |
113 | } else { | 113 | } else { |
114 | ir_input_nokey(ir->dev, &ir->ir); | 114 | ir_input_nokey(ir->dev, &ir->ir); |
115 | } | 115 | } |
@@ -117,7 +117,7 @@ static int build_key(struct saa7134_dev *dev) | |||
117 | else { /* IRQ driven mode - handle key press and release in one go */ | 117 | else { /* IRQ driven mode - handle key press and release in one go */ |
118 | if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || | 118 | if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || |
119 | (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { | 119 | (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { |
120 | ir_input_keydown(ir->dev, &ir->ir, data, data); | 120 | ir_input_keydown(ir->dev, &ir->ir, data); |
121 | ir_input_nokey(ir->dev, &ir->ir); | 121 | ir_input_nokey(ir->dev, &ir->ir); |
122 | } | 122 | } |
123 | } | 123 | } |
@@ -616,6 +616,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
616 | mask_keycode = 0x003f00; | 616 | mask_keycode = 0x003f00; |
617 | mask_keydown = 0x040000; | 617 | mask_keydown = 0x040000; |
618 | break; | 618 | break; |
619 | case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S: | ||
620 | ir_codes = &ir_codes_winfast_table; | ||
621 | mask_keycode = 0x5f00; | ||
622 | mask_keyup = 0x020000; | ||
623 | polling = 50; /* ms */ | ||
624 | break; | ||
619 | } | 625 | } |
620 | if (NULL == ir_codes) { | 626 | if (NULL == ir_codes) { |
621 | printk("%s: Oops: IR config error [card=%d]\n", | 627 | printk("%s: Oops: IR config error [card=%d]\n", |
@@ -646,7 +652,10 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
646 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", | 652 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", |
647 | pci_name(dev->pci)); | 653 | pci_name(dev->pci)); |
648 | 654 | ||
649 | ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); | 655 | err = ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); |
656 | if (err < 0) | ||
657 | goto err_out_free; | ||
658 | |||
650 | input_dev->name = ir->name; | 659 | input_dev->name = ir->name; |
651 | input_dev->phys = ir->phys; | 660 | input_dev->phys = ir->phys; |
652 | input_dev->id.bustype = BUS_PCI; | 661 | input_dev->id.bustype = BUS_PCI; |
@@ -677,6 +686,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
677 | saa7134_ir_stop(dev); | 686 | saa7134_ir_stop(dev); |
678 | dev->remote = NULL; | 687 | dev->remote = NULL; |
679 | err_out_free: | 688 | err_out_free: |
689 | ir_input_free(input_dev); | ||
680 | input_free_device(input_dev); | 690 | input_free_device(input_dev); |
681 | kfree(ir); | 691 | kfree(ir); |
682 | return err; | 692 | return err; |
@@ -688,6 +698,7 @@ void saa7134_input_fini(struct saa7134_dev *dev) | |||
688 | return; | 698 | return; |
689 | 699 | ||
690 | saa7134_ir_stop(dev); | 700 | saa7134_ir_stop(dev); |
701 | ir_input_free(dev->remote->dev); | ||
691 | input_unregister_device(dev->remote->dev); | 702 | input_unregister_device(dev->remote->dev); |
692 | kfree(dev->remote); | 703 | kfree(dev->remote); |
693 | dev->remote = NULL; | 704 | dev->remote = NULL; |
@@ -695,10 +706,7 @@ void saa7134_input_fini(struct saa7134_dev *dev) | |||
695 | 706 | ||
696 | void saa7134_probe_i2c_ir(struct saa7134_dev *dev) | 707 | void saa7134_probe_i2c_ir(struct saa7134_dev *dev) |
697 | { | 708 | { |
698 | const unsigned short addr_list[] = { | 709 | struct i2c_board_info info; |
699 | 0x7a, 0x47, 0x71, 0x2d, | ||
700 | I2C_CLIENT_END | ||
701 | }; | ||
702 | 710 | ||
703 | struct i2c_msg msg_msi = { | 711 | struct i2c_msg msg_msi = { |
704 | .addr = 0x50, | 712 | .addr = 0x50, |
@@ -714,9 +722,9 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) | |||
714 | return; | 722 | return; |
715 | } | 723 | } |
716 | 724 | ||
717 | memset(&dev->info, 0, sizeof(dev->info)); | 725 | memset(&info, 0, sizeof(struct i2c_board_info)); |
718 | memset(&dev->init_data, 0, sizeof(dev->init_data)); | 726 | memset(&dev->init_data, 0, sizeof(dev->init_data)); |
719 | strlcpy(dev->info.type, "ir_video", I2C_NAME_SIZE); | 727 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); |
720 | 728 | ||
721 | switch (dev->board) { | 729 | switch (dev->board) { |
722 | case SAA7134_BOARD_PINNACLE_PCTV_110i: | 730 | case SAA7134_BOARD_PINNACLE_PCTV_110i: |
@@ -725,23 +733,24 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) | |||
725 | if (pinnacle_remote == 0) { | 733 | if (pinnacle_remote == 0) { |
726 | dev->init_data.get_key = get_key_pinnacle_color; | 734 | dev->init_data.get_key = get_key_pinnacle_color; |
727 | dev->init_data.ir_codes = &ir_codes_pinnacle_color_table; | 735 | dev->init_data.ir_codes = &ir_codes_pinnacle_color_table; |
728 | dev->info.addr = 0x47; | 736 | info.addr = 0x47; |
729 | } else { | 737 | } else { |
730 | dev->init_data.get_key = get_key_pinnacle_grey; | 738 | dev->init_data.get_key = get_key_pinnacle_grey; |
731 | dev->init_data.ir_codes = &ir_codes_pinnacle_grey_table; | 739 | dev->init_data.ir_codes = &ir_codes_pinnacle_grey_table; |
732 | dev->info.addr = 0x47; | 740 | info.addr = 0x47; |
733 | } | 741 | } |
734 | break; | 742 | break; |
735 | case SAA7134_BOARD_UPMOST_PURPLE_TV: | 743 | case SAA7134_BOARD_UPMOST_PURPLE_TV: |
736 | dev->init_data.name = "Purple TV"; | 744 | dev->init_data.name = "Purple TV"; |
737 | dev->init_data.get_key = get_key_purpletv; | 745 | dev->init_data.get_key = get_key_purpletv; |
738 | dev->init_data.ir_codes = &ir_codes_purpletv_table; | 746 | dev->init_data.ir_codes = &ir_codes_purpletv_table; |
747 | info.addr = 0x7a; | ||
739 | break; | 748 | break; |
740 | case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: | 749 | case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: |
741 | dev->init_data.name = "MSI TV@nywhere Plus"; | 750 | dev->init_data.name = "MSI TV@nywhere Plus"; |
742 | dev->init_data.get_key = get_key_msi_tvanywhere_plus; | 751 | dev->init_data.get_key = get_key_msi_tvanywhere_plus; |
743 | dev->init_data.ir_codes = &ir_codes_msi_tvanywhere_plus_table; | 752 | dev->init_data.ir_codes = &ir_codes_msi_tvanywhere_plus_table; |
744 | dev->info.addr = 0x30; | 753 | info.addr = 0x30; |
745 | /* MSI TV@nywhere Plus controller doesn't seem to | 754 | /* MSI TV@nywhere Plus controller doesn't seem to |
746 | respond to probes unless we read something from | 755 | respond to probes unless we read something from |
747 | an existing device. Weird... | 756 | an existing device. Weird... |
@@ -755,6 +764,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) | |||
755 | dev->init_data.name = "HVR 1110"; | 764 | dev->init_data.name = "HVR 1110"; |
756 | dev->init_data.get_key = get_key_hvr1110; | 765 | dev->init_data.get_key = get_key_hvr1110; |
757 | dev->init_data.ir_codes = &ir_codes_hauppauge_new_table; | 766 | dev->init_data.ir_codes = &ir_codes_hauppauge_new_table; |
767 | info.addr = 0x71; | ||
758 | break; | 768 | break; |
759 | case SAA7134_BOARD_BEHOLD_607FM_MK3: | 769 | case SAA7134_BOARD_BEHOLD_607FM_MK3: |
760 | case SAA7134_BOARD_BEHOLD_607FM_MK5: | 770 | case SAA7134_BOARD_BEHOLD_607FM_MK5: |
@@ -772,23 +782,20 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) | |||
772 | dev->init_data.name = "BeholdTV"; | 782 | dev->init_data.name = "BeholdTV"; |
773 | dev->init_data.get_key = get_key_beholdm6xx; | 783 | dev->init_data.get_key = get_key_beholdm6xx; |
774 | dev->init_data.ir_codes = &ir_codes_behold_table; | 784 | dev->init_data.ir_codes = &ir_codes_behold_table; |
785 | info.addr = 0x2d; | ||
775 | break; | 786 | break; |
776 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: | 787 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: |
777 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: | 788 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: |
778 | dev->info.addr = 0x40; | 789 | info.addr = 0x40; |
779 | break; | 790 | break; |
780 | } | 791 | default: |
781 | 792 | dprintk("No I2C IR support for board %x\n", dev->board); | |
782 | if (dev->init_data.name) | ||
783 | dev->info.platform_data = &dev->init_data; | ||
784 | /* No need to probe if address is known */ | ||
785 | if (dev->info.addr) { | ||
786 | i2c_new_device(&dev->i2c_adap, &dev->info); | ||
787 | return; | 793 | return; |
788 | } | 794 | } |
789 | 795 | ||
790 | /* Address not known, fallback to probing */ | 796 | if (dev->init_data.name) |
791 | i2c_new_probed_device(&dev->i2c_adap, &dev->info, addr_list); | 797 | info.platform_data = &dev->init_data; |
798 | i2c_new_device(&dev->i2c_adap, &info); | ||
792 | } | 799 | } |
793 | 800 | ||
794 | static int saa7134_rc5_irq(struct saa7134_dev *dev) | 801 | static int saa7134_rc5_irq(struct saa7134_dev *dev) |
@@ -936,7 +943,7 @@ static void nec_task(unsigned long data) | |||
936 | dprintk("scancode = 0x%02x (code = 0x%02x, notcode= 0x%02x)\n", | 943 | dprintk("scancode = 0x%02x (code = 0x%02x, notcode= 0x%02x)\n", |
937 | ir->code, ircode, not_code); | 944 | ir->code, ircode, not_code); |
938 | 945 | ||
939 | ir_input_keydown(ir->dev, &ir->ir, ir->code, ir->code); | 946 | ir_input_keydown(ir->dev, &ir->ir, ir->code); |
940 | } else | 947 | } else |
941 | dprintk("Repeat last key\n"); | 948 | dprintk("Repeat last key\n"); |
942 | 949 | ||
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index da26f476a302..35f8daa3a359 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c | |||
@@ -1499,7 +1499,7 @@ static int video_release(struct file *file) | |||
1499 | saa_andorb(SAA7134_OFMT_DATA_A, 0x1f, 0); | 1499 | saa_andorb(SAA7134_OFMT_DATA_A, 0x1f, 0); |
1500 | saa_andorb(SAA7134_OFMT_DATA_B, 0x1f, 0); | 1500 | saa_andorb(SAA7134_OFMT_DATA_B, 0x1f, 0); |
1501 | 1501 | ||
1502 | saa_call_all(dev, tuner, s_standby); | 1502 | saa_call_all(dev, core, s_power, 0); |
1503 | if (fh->radio) | 1503 | if (fh->radio) |
1504 | saa_call_all(dev, core, ioctl, RDS_CMD_CLOSE, &cmd); | 1504 | saa_call_all(dev, core, ioctl, RDS_CMD_CLOSE, &cmd); |
1505 | 1505 | ||
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index f8697d46ff5f..53b7e0b8a2fb 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -297,6 +297,8 @@ struct saa7134_format { | |||
297 | #define SAA7134_BOARD_BEHOLD_X7 171 | 297 | #define SAA7134_BOARD_BEHOLD_X7 171 |
298 | #define SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM 172 | 298 | #define SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM 172 |
299 | #define SAA7134_BOARD_ZOLID_HYBRID_PCI 173 | 299 | #define SAA7134_BOARD_ZOLID_HYBRID_PCI 173 |
300 | #define SAA7134_BOARD_ASUS_EUROPA_HYBRID 174 | ||
301 | #define SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S 175 | ||
300 | 302 | ||
301 | #define SAA7134_MAXBOARDS 32 | 303 | #define SAA7134_MAXBOARDS 32 |
302 | #define SAA7134_INPUT_MAX 8 | 304 | #define SAA7134_INPUT_MAX 8 |
@@ -592,7 +594,6 @@ struct saa7134_dev { | |||
592 | unsigned int insuspend; | 594 | unsigned int insuspend; |
593 | 595 | ||
594 | /* I2C keyboard data */ | 596 | /* I2C keyboard data */ |
595 | struct i2c_board_info info; | ||
596 | struct IR_i2c_init_data init_data; | 597 | struct IR_i2c_init_data init_data; |
597 | 598 | ||
598 | /* SAA7134_MPEG_* */ | 599 | /* SAA7134_MPEG_* */ |
diff --git a/drivers/media/video/saa7164/saa7164-dvb.c b/drivers/media/video/saa7164/saa7164-dvb.c index 6a2d847d6a88..cf099c59b38e 100644 --- a/drivers/media/video/saa7164/saa7164-dvb.c +++ b/drivers/media/video/saa7164/saa7164-dvb.c | |||
@@ -68,6 +68,7 @@ static struct tda18271_config hauppauge_hvr22x0s_tuner_config = { | |||
68 | .std_map = &hauppauge_tda18271_std_map, | 68 | .std_map = &hauppauge_tda18271_std_map, |
69 | .gate = TDA18271_GATE_ANALOG, | 69 | .gate = TDA18271_GATE_ANALOG, |
70 | .role = TDA18271_SLAVE, | 70 | .role = TDA18271_SLAVE, |
71 | .output_opt = TDA18271_OUTPUT_LT_OFF, | ||
71 | .rf_cal_on_startup = 1 | 72 | .rf_cal_on_startup = 1 |
72 | }; | 73 | }; |
73 | 74 | ||
diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c index b15c40908e84..6818df571168 100644 --- a/drivers/media/video/saa717x.c +++ b/drivers/media/video/saa717x.c | |||
@@ -1115,7 +1115,7 @@ static int saa717x_s_video_routing(struct v4l2_subdev *sd, | |||
1115 | v4l2_dbg(1, debug, sd, "decoder set input (%d)\n", input); | 1115 | v4l2_dbg(1, debug, sd, "decoder set input (%d)\n", input); |
1116 | /* inputs from 0-9 are available*/ | 1116 | /* inputs from 0-9 are available*/ |
1117 | /* saa717x have mode0-mode9 but mode5 is reserved. */ | 1117 | /* saa717x have mode0-mode9 but mode5 is reserved. */ |
1118 | if (input < 0 || input > 9 || input == 5) | 1118 | if (input > 9 || input == 5) |
1119 | return -EINVAL; | 1119 | return -EINVAL; |
1120 | 1120 | ||
1121 | if (decoder->input != input) { | 1121 | if (decoder->input != input) { |
@@ -1312,7 +1312,7 @@ static int saa717x_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) | |||
1312 | "MONO", "STEREO", "LANG1", "LANG2/SAP" | 1312 | "MONO", "STEREO", "LANG1", "LANG2/SAP" |
1313 | }; | 1313 | }; |
1314 | 1314 | ||
1315 | audio_mode = V4L2_TUNER_MODE_STEREO; | 1315 | audio_mode = TUNER_AUDIO_STEREO; |
1316 | 1316 | ||
1317 | switch (vt->audmode) { | 1317 | switch (vt->audmode) { |
1318 | case V4L2_TUNER_MODE_MONO: | 1318 | case V4L2_TUNER_MODE_MONO: |
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 9c8b7c7b89ee..a4f3472d4db8 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
@@ -153,6 +153,40 @@ static u32 ceu_read(struct sh_mobile_ceu_dev *priv, unsigned long reg_offs) | |||
153 | return ioread32(priv->base + reg_offs); | 153 | return ioread32(priv->base + reg_offs); |
154 | } | 154 | } |
155 | 155 | ||
156 | static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev) | ||
157 | { | ||
158 | int i, success = 0; | ||
159 | struct soc_camera_device *icd = pcdev->icd; | ||
160 | |||
161 | ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ | ||
162 | |||
163 | /* wait CSTSR.CPTON bit */ | ||
164 | for (i = 0; i < 1000; i++) { | ||
165 | if (!(ceu_read(pcdev, CSTSR) & 1)) { | ||
166 | success++; | ||
167 | break; | ||
168 | } | ||
169 | udelay(1); | ||
170 | } | ||
171 | |||
172 | /* wait CAPSR.CPKIL bit */ | ||
173 | for (i = 0; i < 1000; i++) { | ||
174 | if (!(ceu_read(pcdev, CAPSR) & (1 << 16))) { | ||
175 | success++; | ||
176 | break; | ||
177 | } | ||
178 | udelay(1); | ||
179 | } | ||
180 | |||
181 | |||
182 | if (2 != success) { | ||
183 | dev_warn(&icd->dev, "soft reset time out\n"); | ||
184 | return -EIO; | ||
185 | } | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
156 | /* | 190 | /* |
157 | * Videobuf operations | 191 | * Videobuf operations |
158 | */ | 192 | */ |
@@ -202,26 +236,45 @@ static void free_buffer(struct videobuf_queue *vq, | |||
202 | #define CEU_CETCR_MAGIC 0x0317f313 /* acknowledge magical interrupt sources */ | 236 | #define CEU_CETCR_MAGIC 0x0317f313 /* acknowledge magical interrupt sources */ |
203 | #define CEU_CETCR_IGRW (1 << 4) /* prohibited register access interrupt bit */ | 237 | #define CEU_CETCR_IGRW (1 << 4) /* prohibited register access interrupt bit */ |
204 | #define CEU_CEIER_CPEIE (1 << 0) /* one-frame capture end interrupt */ | 238 | #define CEU_CEIER_CPEIE (1 << 0) /* one-frame capture end interrupt */ |
239 | #define CEU_CEIER_VBP (1 << 20) /* vbp error */ | ||
205 | #define CEU_CAPCR_CTNCP (1 << 16) /* continuous capture mode (if set) */ | 240 | #define CEU_CAPCR_CTNCP (1 << 16) /* continuous capture mode (if set) */ |
241 | #define CEU_CEIER_MASK (CEU_CEIER_CPEIE | CEU_CEIER_VBP) | ||
206 | 242 | ||
207 | 243 | ||
208 | static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) | 244 | /* |
245 | * return value doesn't reflex the success/failure to queue the new buffer, | ||
246 | * but rather the status of the previous buffer. | ||
247 | */ | ||
248 | static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) | ||
209 | { | 249 | { |
210 | struct soc_camera_device *icd = pcdev->icd; | 250 | struct soc_camera_device *icd = pcdev->icd; |
211 | dma_addr_t phys_addr_top, phys_addr_bottom; | 251 | dma_addr_t phys_addr_top, phys_addr_bottom; |
252 | u32 status; | ||
253 | int ret = 0; | ||
212 | 254 | ||
213 | /* The hardware is _very_ picky about this sequence. Especially | 255 | /* The hardware is _very_ picky about this sequence. Especially |
214 | * the CEU_CETCR_MAGIC value. It seems like we need to acknowledge | 256 | * the CEU_CETCR_MAGIC value. It seems like we need to acknowledge |
215 | * several not-so-well documented interrupt sources in CETCR. | 257 | * several not-so-well documented interrupt sources in CETCR. |
216 | */ | 258 | */ |
217 | ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) & ~CEU_CEIER_CPEIE); | 259 | ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) & ~CEU_CEIER_MASK); |
218 | ceu_write(pcdev, CETCR, ~ceu_read(pcdev, CETCR) & CEU_CETCR_MAGIC); | 260 | status = ceu_read(pcdev, CETCR); |
219 | ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) | CEU_CEIER_CPEIE); | 261 | ceu_write(pcdev, CETCR, ~status & CEU_CETCR_MAGIC); |
262 | ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) | CEU_CEIER_MASK); | ||
220 | ceu_write(pcdev, CAPCR, ceu_read(pcdev, CAPCR) & ~CEU_CAPCR_CTNCP); | 263 | ceu_write(pcdev, CAPCR, ceu_read(pcdev, CAPCR) & ~CEU_CAPCR_CTNCP); |
221 | ceu_write(pcdev, CETCR, CEU_CETCR_MAGIC ^ CEU_CETCR_IGRW); | 264 | ceu_write(pcdev, CETCR, CEU_CETCR_MAGIC ^ CEU_CETCR_IGRW); |
222 | 265 | ||
266 | /* | ||
267 | * When a VBP interrupt occurs, a capture end interrupt does not occur | ||
268 | * and the image of that frame is not captured correctly. So, soft reset | ||
269 | * is needed here. | ||
270 | */ | ||
271 | if (status & CEU_CEIER_VBP) { | ||
272 | sh_mobile_ceu_soft_reset(pcdev); | ||
273 | ret = -EIO; | ||
274 | } | ||
275 | |||
223 | if (!pcdev->active) | 276 | if (!pcdev->active) |
224 | return; | 277 | return ret; |
225 | 278 | ||
226 | phys_addr_top = videobuf_to_dma_contig(pcdev->active); | 279 | phys_addr_top = videobuf_to_dma_contig(pcdev->active); |
227 | ceu_write(pcdev, CDAYR, phys_addr_top); | 280 | ceu_write(pcdev, CDAYR, phys_addr_top); |
@@ -247,6 +300,8 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) | |||
247 | 300 | ||
248 | pcdev->active->state = VIDEOBUF_ACTIVE; | 301 | pcdev->active->state = VIDEOBUF_ACTIVE; |
249 | ceu_write(pcdev, CAPSR, 0x1); /* start capture */ | 302 | ceu_write(pcdev, CAPSR, 0x1); /* start capture */ |
303 | |||
304 | return ret; | ||
250 | } | 305 | } |
251 | 306 | ||
252 | static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq, | 307 | static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq, |
@@ -319,6 +374,11 @@ static void sh_mobile_ceu_videobuf_queue(struct videobuf_queue *vq, | |||
319 | list_add_tail(&vb->queue, &pcdev->capture); | 374 | list_add_tail(&vb->queue, &pcdev->capture); |
320 | 375 | ||
321 | if (!pcdev->active) { | 376 | if (!pcdev->active) { |
377 | /* | ||
378 | * Because there were no active buffer at this moment, | ||
379 | * we are not interested in the return value of | ||
380 | * sh_mobile_ceu_capture here. | ||
381 | */ | ||
322 | pcdev->active = vb; | 382 | pcdev->active = vb; |
323 | sh_mobile_ceu_capture(pcdev); | 383 | sh_mobile_ceu_capture(pcdev); |
324 | } | 384 | } |
@@ -379,9 +439,8 @@ static irqreturn_t sh_mobile_ceu_irq(int irq, void *data) | |||
379 | else | 439 | else |
380 | pcdev->active = NULL; | 440 | pcdev->active = NULL; |
381 | 441 | ||
382 | sh_mobile_ceu_capture(pcdev); | 442 | vb->state = (sh_mobile_ceu_capture(pcdev) < 0) ? |
383 | 443 | VIDEOBUF_ERROR : VIDEOBUF_DONE; | |
384 | vb->state = VIDEOBUF_DONE; | ||
385 | do_gettimeofday(&vb->ts); | 444 | do_gettimeofday(&vb->ts); |
386 | vb->field_count++; | 445 | vb->field_count++; |
387 | wake_up(&vb->done); | 446 | wake_up(&vb->done); |
@@ -407,13 +466,9 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) | |||
407 | 466 | ||
408 | pm_runtime_get_sync(ici->v4l2_dev.dev); | 467 | pm_runtime_get_sync(ici->v4l2_dev.dev); |
409 | 468 | ||
410 | ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ | ||
411 | while (ceu_read(pcdev, CSTSR) & 1) | ||
412 | msleep(1); | ||
413 | |||
414 | pcdev->icd = icd; | 469 | pcdev->icd = icd; |
415 | 470 | ||
416 | return 0; | 471 | return sh_mobile_ceu_soft_reset(pcdev); |
417 | } | 472 | } |
418 | 473 | ||
419 | /* Called with .video_lock held */ | 474 | /* Called with .video_lock held */ |
@@ -427,7 +482,7 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) | |||
427 | 482 | ||
428 | /* disable capture, disable interrupts */ | 483 | /* disable capture, disable interrupts */ |
429 | ceu_write(pcdev, CEIER, 0); | 484 | ceu_write(pcdev, CEIER, 0); |
430 | ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ | 485 | sh_mobile_ceu_soft_reset(pcdev); |
431 | 486 | ||
432 | /* make sure active buffer is canceled */ | 487 | /* make sure active buffer is canceled */ |
433 | spin_lock_irqsave(&pcdev->lock, flags); | 488 | spin_lock_irqsave(&pcdev->lock, flags); |
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index aba92e2313d8..5b3eaa16afd2 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
@@ -320,6 +320,7 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
320 | struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; | 320 | struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; |
321 | struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; | 321 | struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; |
322 | unsigned char buffer[4]; | 322 | unsigned char buffer[4]; |
323 | int tune_now = 1; | ||
323 | 324 | ||
324 | if (type == UNSET || type == TUNER_ABSENT) { | 325 | if (type == UNSET || type == TUNER_ABSENT) { |
325 | tuner_dbg ("tuner 0x%02x: Tuner type absent\n",c->addr); | 326 | tuner_dbg ("tuner 0x%02x: Tuner type absent\n",c->addr); |
@@ -328,7 +329,7 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
328 | 329 | ||
329 | t->type = type; | 330 | t->type = type; |
330 | /* prevent invalid config values */ | 331 | /* prevent invalid config values */ |
331 | t->config = ((new_config >= 0) && (new_config < 256)) ? new_config : 0; | 332 | t->config = new_config < 256 ? new_config : 0; |
332 | if (tuner_callback != NULL) { | 333 | if (tuner_callback != NULL) { |
333 | tuner_dbg("defining GPIO callback\n"); | 334 | tuner_dbg("defining GPIO callback\n"); |
334 | t->fe.callback = tuner_callback; | 335 | t->fe.callback = tuner_callback; |
@@ -404,6 +405,7 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
404 | }; | 405 | }; |
405 | if (!dvb_attach(xc2028_attach, &t->fe, &cfg)) | 406 | if (!dvb_attach(xc2028_attach, &t->fe, &cfg)) |
406 | goto attach_failed; | 407 | goto attach_failed; |
408 | tune_now = 0; | ||
407 | break; | 409 | break; |
408 | } | 410 | } |
409 | case TUNER_TDA9887: | 411 | case TUNER_TDA9887: |
@@ -419,6 +421,7 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
419 | if (!dvb_attach(xc5000_attach, | 421 | if (!dvb_attach(xc5000_attach, |
420 | &t->fe, t->i2c->adapter, &xc5000_cfg)) | 422 | &t->fe, t->i2c->adapter, &xc5000_cfg)) |
421 | goto attach_failed; | 423 | goto attach_failed; |
424 | tune_now = 0; | ||
422 | break; | 425 | break; |
423 | } | 426 | } |
424 | case TUNER_NXP_TDA18271: | 427 | case TUNER_NXP_TDA18271: |
@@ -430,6 +433,7 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
430 | if (!dvb_attach(tda18271_attach, &t->fe, t->i2c->addr, | 433 | if (!dvb_attach(tda18271_attach, &t->fe, t->i2c->addr, |
431 | t->i2c->adapter, &cfg)) | 434 | t->i2c->adapter, &cfg)) |
432 | goto attach_failed; | 435 | goto attach_failed; |
436 | tune_now = 0; | ||
433 | break; | 437 | break; |
434 | } | 438 | } |
435 | default: | 439 | default: |
@@ -458,12 +462,13 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
458 | if (t->mode_mask == T_UNINITIALIZED) | 462 | if (t->mode_mask == T_UNINITIALIZED) |
459 | t->mode_mask = new_mode_mask; | 463 | t->mode_mask = new_mode_mask; |
460 | 464 | ||
461 | /* xc2028/3028 and xc5000 requires a firmware to be set-up later | 465 | /* Some tuners require more initialization setup before use, |
466 | such as firmware download or device calibration. | ||
462 | trying to set a frequency here will just fail | 467 | trying to set a frequency here will just fail |
463 | FIXME: better to move set_freq to the tuner code. This is needed | 468 | FIXME: better to move set_freq to the tuner code. This is needed |
464 | on analog tuners for PLL to properly work | 469 | on analog tuners for PLL to properly work |
465 | */ | 470 | */ |
466 | if (t->type != TUNER_XC2028 && t->type != TUNER_XC5000) | 471 | if (tune_now) |
467 | set_freq(c, (V4L2_TUNER_RADIO == t->mode) ? | 472 | set_freq(c, (V4L2_TUNER_RADIO == t->mode) ? |
468 | t->radio_freq : t->tv_freq); | 473 | t->radio_freq : t->tv_freq); |
469 | 474 | ||
@@ -752,14 +757,17 @@ static int tuner_s_radio(struct v4l2_subdev *sd) | |||
752 | return 0; | 757 | return 0; |
753 | } | 758 | } |
754 | 759 | ||
755 | static int tuner_s_standby(struct v4l2_subdev *sd) | 760 | static int tuner_s_power(struct v4l2_subdev *sd, int on) |
756 | { | 761 | { |
757 | struct tuner *t = to_tuner(sd); | 762 | struct tuner *t = to_tuner(sd); |
758 | struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; | 763 | struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; |
759 | 764 | ||
765 | if (on) | ||
766 | return 0; | ||
767 | |||
760 | tuner_dbg("Putting tuner to sleep\n"); | 768 | tuner_dbg("Putting tuner to sleep\n"); |
761 | 769 | ||
762 | if (check_mode(t, "s_standby") == -EINVAL) | 770 | if (check_mode(t, "s_power") == -EINVAL) |
763 | return 0; | 771 | return 0; |
764 | t->mode = T_STANDBY; | 772 | t->mode = T_STANDBY; |
765 | if (analog_ops->standby) | 773 | if (analog_ops->standby) |
@@ -961,6 +969,7 @@ static int tuner_command(struct i2c_client *client, unsigned cmd, void *arg) | |||
961 | static const struct v4l2_subdev_core_ops tuner_core_ops = { | 969 | static const struct v4l2_subdev_core_ops tuner_core_ops = { |
962 | .log_status = tuner_log_status, | 970 | .log_status = tuner_log_status, |
963 | .s_std = tuner_s_std, | 971 | .s_std = tuner_s_std, |
972 | .s_power = tuner_s_power, | ||
964 | }; | 973 | }; |
965 | 974 | ||
966 | static const struct v4l2_subdev_tuner_ops tuner_tuner_ops = { | 975 | static const struct v4l2_subdev_tuner_ops tuner_tuner_ops = { |
@@ -971,7 +980,6 @@ static const struct v4l2_subdev_tuner_ops tuner_tuner_ops = { | |||
971 | .g_frequency = tuner_g_frequency, | 980 | .g_frequency = tuner_g_frequency, |
972 | .s_type_addr = tuner_s_type_addr, | 981 | .s_type_addr = tuner_s_type_addr, |
973 | .s_config = tuner_s_config, | 982 | .s_config = tuner_s_config, |
974 | .s_standby = tuner_s_standby, | ||
975 | }; | 983 | }; |
976 | 984 | ||
977 | static const struct v4l2_subdev_ops tuner_ops = { | 985 | static const struct v4l2_subdev_ops tuner_ops = { |
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 0869bafc2b56..800fc1b111ef 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c | |||
@@ -1919,7 +1919,7 @@ static const struct v4l2_subdev_tuner_ops tvaudio_tuner_ops = { | |||
1919 | .s_radio = tvaudio_s_radio, | 1919 | .s_radio = tvaudio_s_radio, |
1920 | .s_frequency = tvaudio_s_frequency, | 1920 | .s_frequency = tvaudio_s_frequency, |
1921 | .s_tuner = tvaudio_s_tuner, | 1921 | .s_tuner = tvaudio_s_tuner, |
1922 | .s_tuner = tvaudio_g_tuner, | 1922 | .g_tuner = tvaudio_g_tuner, |
1923 | }; | 1923 | }; |
1924 | 1924 | ||
1925 | static const struct v4l2_subdev_audio_ops tvaudio_audio_ops = { | 1925 | static const struct v4l2_subdev_audio_ops tvaudio_audio_ops = { |
diff --git a/drivers/media/video/tvp514x.c b/drivers/media/video/tvp514x.c index 244372627df2..26b4e718cd6d 100644 --- a/drivers/media/video/tvp514x.c +++ b/drivers/media/video/tvp514x.c | |||
@@ -272,7 +272,7 @@ static int tvp514x_read_reg(struct v4l2_subdev *sd, u8 reg) | |||
272 | read_again: | 272 | read_again: |
273 | 273 | ||
274 | err = i2c_smbus_read_byte_data(client, reg); | 274 | err = i2c_smbus_read_byte_data(client, reg); |
275 | if (err == -1) { | 275 | if (err < 0) { |
276 | if (retry <= I2C_RETRY_COUNT) { | 276 | if (retry <= I2C_RETRY_COUNT) { |
277 | v4l2_warn(sd, "Read: retry ... %d\n", retry); | 277 | v4l2_warn(sd, "Read: retry ... %d\n", retry); |
278 | retry++; | 278 | retry++; |
diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c index 31d57f2d09e1..a0addcb04295 100644 --- a/drivers/media/video/usbvideo/konicawc.c +++ b/drivers/media/video/usbvideo/konicawc.c | |||
@@ -225,7 +225,7 @@ static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev | |||
225 | int error; | 225 | int error; |
226 | 226 | ||
227 | usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); | 227 | usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); |
228 | strncat(cam->input_physname, "/input0", sizeof(cam->input_physname)); | 228 | strlcat(cam->input_physname, "/input0", sizeof(cam->input_physname)); |
229 | 229 | ||
230 | cam->input = input_dev = input_allocate_device(); | 230 | cam->input = input_dev = input_allocate_device(); |
231 | if (!input_dev) { | 231 | if (!input_dev) { |
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c index 803d3e4e29a2..c4d1b96b5cee 100644 --- a/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/drivers/media/video/usbvideo/quickcam_messenger.c | |||
@@ -89,7 +89,7 @@ static void qcm_register_input(struct qcm *cam, struct usb_device *dev) | |||
89 | int error; | 89 | int error; |
90 | 90 | ||
91 | usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); | 91 | usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); |
92 | strncat(cam->input_physname, "/input0", sizeof(cam->input_physname)); | 92 | strlcat(cam->input_physname, "/input0", sizeof(cam->input_physname)); |
93 | 93 | ||
94 | cam->input = input_dev = input_allocate_device(); | 94 | cam->input = input_dev = input_allocate_device(); |
95 | if (!input_dev) { | 95 | if (!input_dev) { |
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index a2a50d608a3f..c07b0ac452ab 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c | |||
@@ -601,7 +601,7 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int input) | |||
601 | { | 601 | { |
602 | struct usb_usbvision *usbvision = video_drvdata(file); | 602 | struct usb_usbvision *usbvision = video_drvdata(file); |
603 | 603 | ||
604 | if ((input >= usbvision->video_inputs) || (input < 0) ) | 604 | if (input >= usbvision->video_inputs) |
605 | return -EINVAL; | 605 | return -EINVAL; |
606 | 606 | ||
607 | mutex_lock(&usbvision->lock); | 607 | mutex_lock(&usbvision->lock); |
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index 1b89735e62fd..0469d7a876a8 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c | |||
@@ -742,17 +742,7 @@ struct uvc_control *uvc_find_control(struct uvc_video_chain *chain, | |||
742 | v4l2_id &= V4L2_CTRL_ID_MASK; | 742 | v4l2_id &= V4L2_CTRL_ID_MASK; |
743 | 743 | ||
744 | /* Find the control. */ | 744 | /* Find the control. */ |
745 | __uvc_find_control(chain->processing, v4l2_id, mapping, &ctrl, next); | 745 | list_for_each_entry(entity, &chain->entities, chain) { |
746 | if (ctrl && !next) | ||
747 | return ctrl; | ||
748 | |||
749 | list_for_each_entry(entity, &chain->iterms, chain) { | ||
750 | __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); | ||
751 | if (ctrl && !next) | ||
752 | return ctrl; | ||
753 | } | ||
754 | |||
755 | list_for_each_entry(entity, &chain->extensions, chain) { | ||
756 | __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); | 746 | __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); |
757 | if (ctrl && !next) | 747 | if (ctrl && !next) |
758 | return ctrl; | 748 | return ctrl; |
@@ -826,6 +816,13 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, | |||
826 | ret = 0; | 816 | ret = 0; |
827 | goto out; | 817 | goto out; |
828 | 818 | ||
819 | case V4L2_CTRL_TYPE_BUTTON: | ||
820 | v4l2_ctrl->minimum = 0; | ||
821 | v4l2_ctrl->maximum = 0; | ||
822 | v4l2_ctrl->step = 0; | ||
823 | ret = 0; | ||
824 | goto out; | ||
825 | |||
829 | default: | 826 | default: |
830 | break; | 827 | break; |
831 | } | 828 | } |
@@ -944,17 +941,7 @@ int __uvc_ctrl_commit(struct uvc_video_chain *chain, int rollback) | |||
944 | int ret = 0; | 941 | int ret = 0; |
945 | 942 | ||
946 | /* Find the control. */ | 943 | /* Find the control. */ |
947 | ret = uvc_ctrl_commit_entity(chain->dev, chain->processing, rollback); | 944 | list_for_each_entry(entity, &chain->entities, chain) { |
948 | if (ret < 0) | ||
949 | goto done; | ||
950 | |||
951 | list_for_each_entry(entity, &chain->iterms, chain) { | ||
952 | ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback); | ||
953 | if (ret < 0) | ||
954 | goto done; | ||
955 | } | ||
956 | |||
957 | list_for_each_entry(entity, &chain->extensions, chain) { | ||
958 | ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback); | 945 | ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback); |
959 | if (ret < 0) | 946 | if (ret < 0) |
960 | goto done; | 947 | goto done; |
@@ -1068,8 +1055,9 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain, | |||
1068 | int ret; | 1055 | int ret; |
1069 | 1056 | ||
1070 | /* Find the extension unit. */ | 1057 | /* Find the extension unit. */ |
1071 | list_for_each_entry(entity, &chain->extensions, chain) { | 1058 | list_for_each_entry(entity, &chain->entities, chain) { |
1072 | if (entity->id == xctrl->unit) | 1059 | if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT && |
1060 | entity->id == xctrl->unit) | ||
1073 | break; | 1061 | break; |
1074 | } | 1062 | } |
1075 | 1063 | ||
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 8756be569154..c31bc50113bc 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c | |||
@@ -46,6 +46,7 @@ | |||
46 | unsigned int uvc_no_drop_param; | 46 | unsigned int uvc_no_drop_param; |
47 | static unsigned int uvc_quirks_param; | 47 | static unsigned int uvc_quirks_param; |
48 | unsigned int uvc_trace_param; | 48 | unsigned int uvc_trace_param; |
49 | unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT; | ||
49 | 50 | ||
50 | /* ------------------------------------------------------------------------ | 51 | /* ------------------------------------------------------------------------ |
51 | * Video formats | 52 | * Video formats |
@@ -248,29 +249,9 @@ static struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev, | |||
248 | entity = list_entry(&dev->entities, struct uvc_entity, list); | 249 | entity = list_entry(&dev->entities, struct uvc_entity, list); |
249 | 250 | ||
250 | list_for_each_entry_continue(entity, &dev->entities, list) { | 251 | list_for_each_entry_continue(entity, &dev->entities, list) { |
251 | switch (UVC_ENTITY_TYPE(entity)) { | 252 | for (i = 0; i < entity->bNrInPins; ++i) |
252 | case UVC_TT_STREAMING: | 253 | if (entity->baSourceID[i] == id) |
253 | if (entity->output.bSourceID == id) | ||
254 | return entity; | ||
255 | break; | ||
256 | |||
257 | case UVC_VC_PROCESSING_UNIT: | ||
258 | if (entity->processing.bSourceID == id) | ||
259 | return entity; | 254 | return entity; |
260 | break; | ||
261 | |||
262 | case UVC_VC_SELECTOR_UNIT: | ||
263 | for (i = 0; i < entity->selector.bNrInPins; ++i) | ||
264 | if (entity->selector.baSourceID[i] == id) | ||
265 | return entity; | ||
266 | break; | ||
267 | |||
268 | case UVC_VC_EXTENSION_UNIT: | ||
269 | for (i = 0; i < entity->extension.bNrInPins; ++i) | ||
270 | if (entity->extension.baSourceID[i] == id) | ||
271 | return entity; | ||
272 | break; | ||
273 | } | ||
274 | } | 255 | } |
275 | 256 | ||
276 | return NULL; | 257 | return NULL; |
@@ -426,7 +407,8 @@ static int uvc_parse_format(struct uvc_device *dev, | |||
426 | /* Parse the frame descriptors. Only uncompressed, MJPEG and frame | 407 | /* Parse the frame descriptors. Only uncompressed, MJPEG and frame |
427 | * based formats have frame descriptors. | 408 | * based formats have frame descriptors. |
428 | */ | 409 | */ |
429 | while (buflen > 2 && buffer[2] == ftype) { | 410 | while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && |
411 | buffer[2] == ftype) { | ||
430 | frame = &format->frame[format->nframes]; | 412 | frame = &format->frame[format->nframes]; |
431 | if (ftype != UVC_VS_FRAME_FRAME_BASED) | 413 | if (ftype != UVC_VS_FRAME_FRAME_BASED) |
432 | n = buflen > 25 ? buffer[25] : 0; | 414 | n = buflen > 25 ? buffer[25] : 0; |
@@ -503,12 +485,14 @@ static int uvc_parse_format(struct uvc_device *dev, | |||
503 | buffer += buffer[0]; | 485 | buffer += buffer[0]; |
504 | } | 486 | } |
505 | 487 | ||
506 | if (buflen > 2 && buffer[2] == UVC_VS_STILL_IMAGE_FRAME) { | 488 | if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && |
489 | buffer[2] == UVC_VS_STILL_IMAGE_FRAME) { | ||
507 | buflen -= buffer[0]; | 490 | buflen -= buffer[0]; |
508 | buffer += buffer[0]; | 491 | buffer += buffer[0]; |
509 | } | 492 | } |
510 | 493 | ||
511 | if (buflen > 2 && buffer[2] == UVC_VS_COLORFORMAT) { | 494 | if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && |
495 | buffer[2] == UVC_VS_COLORFORMAT) { | ||
512 | if (buflen < 6) { | 496 | if (buflen < 6) { |
513 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " | 497 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " |
514 | "interface %d COLORFORMAT error\n", | 498 | "interface %d COLORFORMAT error\n", |
@@ -749,6 +733,11 @@ static int uvc_parse_streaming(struct uvc_device *dev, | |||
749 | buffer += buffer[0]; | 733 | buffer += buffer[0]; |
750 | } | 734 | } |
751 | 735 | ||
736 | if (buflen) | ||
737 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface " | ||
738 | "%d has %u bytes of trailing descriptor garbage.\n", | ||
739 | dev->udev->devnum, alts->desc.bInterfaceNumber, buflen); | ||
740 | |||
752 | /* Parse the alternate settings to find the maximum bandwidth. */ | 741 | /* Parse the alternate settings to find the maximum bandwidth. */ |
753 | for (i = 0; i < intf->num_altsetting; ++i) { | 742 | for (i = 0; i < intf->num_altsetting; ++i) { |
754 | struct usb_host_endpoint *ep; | 743 | struct usb_host_endpoint *ep; |
@@ -776,6 +765,28 @@ error: | |||
776 | return ret; | 765 | return ret; |
777 | } | 766 | } |
778 | 767 | ||
768 | static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id, | ||
769 | unsigned int num_pads, unsigned int extra_size) | ||
770 | { | ||
771 | struct uvc_entity *entity; | ||
772 | unsigned int num_inputs; | ||
773 | unsigned int size; | ||
774 | |||
775 | num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1; | ||
776 | size = sizeof(*entity) + extra_size + num_inputs; | ||
777 | entity = kzalloc(size, GFP_KERNEL); | ||
778 | if (entity == NULL) | ||
779 | return NULL; | ||
780 | |||
781 | entity->id = id; | ||
782 | entity->type = type; | ||
783 | |||
784 | entity->bNrInPins = num_inputs; | ||
785 | entity->baSourceID = ((__u8 *)entity) + sizeof(*entity) + extra_size; | ||
786 | |||
787 | return entity; | ||
788 | } | ||
789 | |||
779 | /* Parse vendor-specific extensions. */ | 790 | /* Parse vendor-specific extensions. */ |
780 | static int uvc_parse_vendor_control(struct uvc_device *dev, | 791 | static int uvc_parse_vendor_control(struct uvc_device *dev, |
781 | const unsigned char *buffer, int buflen) | 792 | const unsigned char *buffer, int buflen) |
@@ -827,21 +838,18 @@ static int uvc_parse_vendor_control(struct uvc_device *dev, | |||
827 | break; | 838 | break; |
828 | } | 839 | } |
829 | 840 | ||
830 | unit = kzalloc(sizeof *unit + p + 2*n, GFP_KERNEL); | 841 | unit = uvc_alloc_entity(UVC_VC_EXTENSION_UNIT, buffer[3], |
842 | p + 1, 2*n); | ||
831 | if (unit == NULL) | 843 | if (unit == NULL) |
832 | return -ENOMEM; | 844 | return -ENOMEM; |
833 | 845 | ||
834 | unit->id = buffer[3]; | ||
835 | unit->type = UVC_VC_EXTENSION_UNIT; | ||
836 | memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); | 846 | memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); |
837 | unit->extension.bNumControls = buffer[20]; | 847 | unit->extension.bNumControls = buffer[20]; |
838 | unit->extension.bNrInPins = get_unaligned_le16(&buffer[21]); | 848 | memcpy(unit->baSourceID, &buffer[22], p); |
839 | unit->extension.baSourceID = (__u8 *)unit + sizeof *unit; | ||
840 | memcpy(unit->extension.baSourceID, &buffer[22], p); | ||
841 | unit->extension.bControlSize = buffer[22+p]; | 849 | unit->extension.bControlSize = buffer[22+p]; |
842 | unit->extension.bmControls = (__u8 *)unit + sizeof *unit + p; | 850 | unit->extension.bmControls = (__u8 *)unit + sizeof(*unit); |
843 | unit->extension.bmControlsType = (__u8 *)unit + sizeof *unit | 851 | unit->extension.bmControlsType = (__u8 *)unit + sizeof(*unit) |
844 | + p + n; | 852 | + n; |
845 | memcpy(unit->extension.bmControls, &buffer[23+p], 2*n); | 853 | memcpy(unit->extension.bmControls, &buffer[23+p], 2*n); |
846 | 854 | ||
847 | if (buffer[24+p+2*n] != 0) | 855 | if (buffer[24+p+2*n] != 0) |
@@ -938,13 +946,11 @@ static int uvc_parse_standard_control(struct uvc_device *dev, | |||
938 | return -EINVAL; | 946 | return -EINVAL; |
939 | } | 947 | } |
940 | 948 | ||
941 | term = kzalloc(sizeof *term + n + p, GFP_KERNEL); | 949 | term = uvc_alloc_entity(type | UVC_TERM_INPUT, buffer[3], |
950 | 1, n + p); | ||
942 | if (term == NULL) | 951 | if (term == NULL) |
943 | return -ENOMEM; | 952 | return -ENOMEM; |
944 | 953 | ||
945 | term->id = buffer[3]; | ||
946 | term->type = type | UVC_TERM_INPUT; | ||
947 | |||
948 | if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) { | 954 | if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) { |
949 | term->camera.bControlSize = n; | 955 | term->camera.bControlSize = n; |
950 | term->camera.bmControls = (__u8 *)term + sizeof *term; | 956 | term->camera.bmControls = (__u8 *)term + sizeof *term; |
@@ -999,13 +1005,12 @@ static int uvc_parse_standard_control(struct uvc_device *dev, | |||
999 | return 0; | 1005 | return 0; |
1000 | } | 1006 | } |
1001 | 1007 | ||
1002 | term = kzalloc(sizeof *term, GFP_KERNEL); | 1008 | term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3], |
1009 | 1, 0); | ||
1003 | if (term == NULL) | 1010 | if (term == NULL) |
1004 | return -ENOMEM; | 1011 | return -ENOMEM; |
1005 | 1012 | ||
1006 | term->id = buffer[3]; | 1013 | memcpy(term->baSourceID, &buffer[7], 1); |
1007 | term->type = type | UVC_TERM_OUTPUT; | ||
1008 | term->output.bSourceID = buffer[7]; | ||
1009 | 1014 | ||
1010 | if (buffer[8] != 0) | 1015 | if (buffer[8] != 0) |
1011 | usb_string(udev, buffer[8], term->name, | 1016 | usb_string(udev, buffer[8], term->name, |
@@ -1026,15 +1031,11 @@ static int uvc_parse_standard_control(struct uvc_device *dev, | |||
1026 | return -EINVAL; | 1031 | return -EINVAL; |
1027 | } | 1032 | } |
1028 | 1033 | ||
1029 | unit = kzalloc(sizeof *unit + p, GFP_KERNEL); | 1034 | unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0); |
1030 | if (unit == NULL) | 1035 | if (unit == NULL) |
1031 | return -ENOMEM; | 1036 | return -ENOMEM; |
1032 | 1037 | ||
1033 | unit->id = buffer[3]; | 1038 | memcpy(unit->baSourceID, &buffer[5], p); |
1034 | unit->type = buffer[2]; | ||
1035 | unit->selector.bNrInPins = buffer[4]; | ||
1036 | unit->selector.baSourceID = (__u8 *)unit + sizeof *unit; | ||
1037 | memcpy(unit->selector.baSourceID, &buffer[5], p); | ||
1038 | 1039 | ||
1039 | if (buffer[5+p] != 0) | 1040 | if (buffer[5+p] != 0) |
1040 | usb_string(udev, buffer[5+p], unit->name, | 1041 | usb_string(udev, buffer[5+p], unit->name, |
@@ -1056,13 +1057,11 @@ static int uvc_parse_standard_control(struct uvc_device *dev, | |||
1056 | return -EINVAL; | 1057 | return -EINVAL; |
1057 | } | 1058 | } |
1058 | 1059 | ||
1059 | unit = kzalloc(sizeof *unit + n, GFP_KERNEL); | 1060 | unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n); |
1060 | if (unit == NULL) | 1061 | if (unit == NULL) |
1061 | return -ENOMEM; | 1062 | return -ENOMEM; |
1062 | 1063 | ||
1063 | unit->id = buffer[3]; | 1064 | memcpy(unit->baSourceID, &buffer[4], 1); |
1064 | unit->type = buffer[2]; | ||
1065 | unit->processing.bSourceID = buffer[4]; | ||
1066 | unit->processing.wMaxMultiplier = | 1065 | unit->processing.wMaxMultiplier = |
1067 | get_unaligned_le16(&buffer[5]); | 1066 | get_unaligned_le16(&buffer[5]); |
1068 | unit->processing.bControlSize = buffer[7]; | 1067 | unit->processing.bControlSize = buffer[7]; |
@@ -1091,19 +1090,15 @@ static int uvc_parse_standard_control(struct uvc_device *dev, | |||
1091 | return -EINVAL; | 1090 | return -EINVAL; |
1092 | } | 1091 | } |
1093 | 1092 | ||
1094 | unit = kzalloc(sizeof *unit + p + n, GFP_KERNEL); | 1093 | unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n); |
1095 | if (unit == NULL) | 1094 | if (unit == NULL) |
1096 | return -ENOMEM; | 1095 | return -ENOMEM; |
1097 | 1096 | ||
1098 | unit->id = buffer[3]; | ||
1099 | unit->type = buffer[2]; | ||
1100 | memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); | 1097 | memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); |
1101 | unit->extension.bNumControls = buffer[20]; | 1098 | unit->extension.bNumControls = buffer[20]; |
1102 | unit->extension.bNrInPins = get_unaligned_le16(&buffer[21]); | 1099 | memcpy(unit->baSourceID, &buffer[22], p); |
1103 | unit->extension.baSourceID = (__u8 *)unit + sizeof *unit; | ||
1104 | memcpy(unit->extension.baSourceID, &buffer[22], p); | ||
1105 | unit->extension.bControlSize = buffer[22+p]; | 1100 | unit->extension.bControlSize = buffer[22+p]; |
1106 | unit->extension.bmControls = (__u8 *)unit + sizeof *unit + p; | 1101 | unit->extension.bmControls = (__u8 *)unit + sizeof *unit; |
1107 | memcpy(unit->extension.bmControls, &buffer[23+p], n); | 1102 | memcpy(unit->extension.bmControls, &buffer[23+p], n); |
1108 | 1103 | ||
1109 | if (buffer[23+p+n] != 0) | 1104 | if (buffer[23+p+n] != 0) |
@@ -1209,13 +1204,12 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain, | |||
1209 | if (uvc_trace_param & UVC_TRACE_PROBE) | 1204 | if (uvc_trace_param & UVC_TRACE_PROBE) |
1210 | printk(" <- XU %d", entity->id); | 1205 | printk(" <- XU %d", entity->id); |
1211 | 1206 | ||
1212 | if (entity->extension.bNrInPins != 1) { | 1207 | if (entity->bNrInPins != 1) { |
1213 | uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more " | 1208 | uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more " |
1214 | "than 1 input pin.\n", entity->id); | 1209 | "than 1 input pin.\n", entity->id); |
1215 | return -1; | 1210 | return -1; |
1216 | } | 1211 | } |
1217 | 1212 | ||
1218 | list_add_tail(&entity->chain, &chain->extensions); | ||
1219 | break; | 1213 | break; |
1220 | 1214 | ||
1221 | case UVC_VC_PROCESSING_UNIT: | 1215 | case UVC_VC_PROCESSING_UNIT: |
@@ -1236,7 +1230,7 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain, | |||
1236 | printk(" <- SU %d", entity->id); | 1230 | printk(" <- SU %d", entity->id); |
1237 | 1231 | ||
1238 | /* Single-input selector units are ignored. */ | 1232 | /* Single-input selector units are ignored. */ |
1239 | if (entity->selector.bNrInPins == 1) | 1233 | if (entity->bNrInPins == 1) |
1240 | break; | 1234 | break; |
1241 | 1235 | ||
1242 | if (chain->selector != NULL) { | 1236 | if (chain->selector != NULL) { |
@@ -1254,20 +1248,17 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain, | |||
1254 | if (uvc_trace_param & UVC_TRACE_PROBE) | 1248 | if (uvc_trace_param & UVC_TRACE_PROBE) |
1255 | printk(" <- IT %d\n", entity->id); | 1249 | printk(" <- IT %d\n", entity->id); |
1256 | 1250 | ||
1257 | list_add_tail(&entity->chain, &chain->iterms); | ||
1258 | break; | 1251 | break; |
1259 | 1252 | ||
1260 | case UVC_TT_STREAMING: | 1253 | case UVC_TT_STREAMING: |
1261 | if (uvc_trace_param & UVC_TRACE_PROBE) | 1254 | if (UVC_ENTITY_IS_ITERM(entity)) { |
1262 | printk(" <- IT %d\n", entity->id); | 1255 | if (uvc_trace_param & UVC_TRACE_PROBE) |
1263 | 1256 | printk(" <- IT %d\n", entity->id); | |
1264 | if (!UVC_ENTITY_IS_ITERM(entity)) { | 1257 | } else { |
1265 | uvc_trace(UVC_TRACE_DESCR, "Unsupported input " | 1258 | if (uvc_trace_param & UVC_TRACE_PROBE) |
1266 | "terminal %u.\n", entity->id); | 1259 | printk(" OT %d", entity->id); |
1267 | return -1; | ||
1268 | } | 1260 | } |
1269 | 1261 | ||
1270 | list_add_tail(&entity->chain, &chain->iterms); | ||
1271 | break; | 1262 | break; |
1272 | 1263 | ||
1273 | default: | 1264 | default: |
@@ -1276,6 +1267,7 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain, | |||
1276 | return -1; | 1267 | return -1; |
1277 | } | 1268 | } |
1278 | 1269 | ||
1270 | list_add_tail(&entity->chain, &chain->entities); | ||
1279 | return 0; | 1271 | return 0; |
1280 | } | 1272 | } |
1281 | 1273 | ||
@@ -1299,14 +1291,14 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain, | |||
1299 | 1291 | ||
1300 | switch (UVC_ENTITY_TYPE(forward)) { | 1292 | switch (UVC_ENTITY_TYPE(forward)) { |
1301 | case UVC_VC_EXTENSION_UNIT: | 1293 | case UVC_VC_EXTENSION_UNIT: |
1302 | if (forward->extension.bNrInPins != 1) { | 1294 | if (forward->bNrInPins != 1) { |
1303 | uvc_trace(UVC_TRACE_DESCR, "Extension unit %d " | 1295 | uvc_trace(UVC_TRACE_DESCR, "Extension unit %d " |
1304 | "has more than 1 input pin.\n", | 1296 | "has more than 1 input pin.\n", |
1305 | entity->id); | 1297 | entity->id); |
1306 | return -EINVAL; | 1298 | return -EINVAL; |
1307 | } | 1299 | } |
1308 | 1300 | ||
1309 | list_add_tail(&forward->chain, &chain->extensions); | 1301 | list_add_tail(&forward->chain, &chain->entities); |
1310 | if (uvc_trace_param & UVC_TRACE_PROBE) { | 1302 | if (uvc_trace_param & UVC_TRACE_PROBE) { |
1311 | if (!found) | 1303 | if (!found) |
1312 | printk(" (->"); | 1304 | printk(" (->"); |
@@ -1326,7 +1318,7 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain, | |||
1326 | return -EINVAL; | 1318 | return -EINVAL; |
1327 | } | 1319 | } |
1328 | 1320 | ||
1329 | list_add_tail(&forward->chain, &chain->oterms); | 1321 | list_add_tail(&forward->chain, &chain->entities); |
1330 | if (uvc_trace_param & UVC_TRACE_PROBE) { | 1322 | if (uvc_trace_param & UVC_TRACE_PROBE) { |
1331 | if (!found) | 1323 | if (!found) |
1332 | printk(" (->"); | 1324 | printk(" (->"); |
@@ -1344,24 +1336,22 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain, | |||
1344 | } | 1336 | } |
1345 | 1337 | ||
1346 | static int uvc_scan_chain_backward(struct uvc_video_chain *chain, | 1338 | static int uvc_scan_chain_backward(struct uvc_video_chain *chain, |
1347 | struct uvc_entity *entity) | 1339 | struct uvc_entity **_entity) |
1348 | { | 1340 | { |
1341 | struct uvc_entity *entity = *_entity; | ||
1349 | struct uvc_entity *term; | 1342 | struct uvc_entity *term; |
1350 | int id = -1, i; | 1343 | int id = -EINVAL, i; |
1351 | 1344 | ||
1352 | switch (UVC_ENTITY_TYPE(entity)) { | 1345 | switch (UVC_ENTITY_TYPE(entity)) { |
1353 | case UVC_VC_EXTENSION_UNIT: | 1346 | case UVC_VC_EXTENSION_UNIT: |
1354 | id = entity->extension.baSourceID[0]; | ||
1355 | break; | ||
1356 | |||
1357 | case UVC_VC_PROCESSING_UNIT: | 1347 | case UVC_VC_PROCESSING_UNIT: |
1358 | id = entity->processing.bSourceID; | 1348 | id = entity->baSourceID[0]; |
1359 | break; | 1349 | break; |
1360 | 1350 | ||
1361 | case UVC_VC_SELECTOR_UNIT: | 1351 | case UVC_VC_SELECTOR_UNIT: |
1362 | /* Single-input selector units are ignored. */ | 1352 | /* Single-input selector units are ignored. */ |
1363 | if (entity->selector.bNrInPins == 1) { | 1353 | if (entity->bNrInPins == 1) { |
1364 | id = entity->selector.baSourceID[0]; | 1354 | id = entity->baSourceID[0]; |
1365 | break; | 1355 | break; |
1366 | } | 1356 | } |
1367 | 1357 | ||
@@ -1369,8 +1359,8 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain, | |||
1369 | printk(" <- IT"); | 1359 | printk(" <- IT"); |
1370 | 1360 | ||
1371 | chain->selector = entity; | 1361 | chain->selector = entity; |
1372 | for (i = 0; i < entity->selector.bNrInPins; ++i) { | 1362 | for (i = 0; i < entity->bNrInPins; ++i) { |
1373 | id = entity->selector.baSourceID[i]; | 1363 | id = entity->baSourceID[i]; |
1374 | term = uvc_entity_by_id(chain->dev, id); | 1364 | term = uvc_entity_by_id(chain->dev, id); |
1375 | if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) { | 1365 | if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) { |
1376 | uvc_trace(UVC_TRACE_DESCR, "Selector unit %d " | 1366 | uvc_trace(UVC_TRACE_DESCR, "Selector unit %d " |
@@ -1382,7 +1372,7 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain, | |||
1382 | if (uvc_trace_param & UVC_TRACE_PROBE) | 1372 | if (uvc_trace_param & UVC_TRACE_PROBE) |
1383 | printk(" %d", term->id); | 1373 | printk(" %d", term->id); |
1384 | 1374 | ||
1385 | list_add_tail(&term->chain, &chain->iterms); | 1375 | list_add_tail(&term->chain, &chain->entities); |
1386 | uvc_scan_chain_forward(chain, term, entity); | 1376 | uvc_scan_chain_forward(chain, term, entity); |
1387 | } | 1377 | } |
1388 | 1378 | ||
@@ -1391,34 +1381,49 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain, | |||
1391 | 1381 | ||
1392 | id = 0; | 1382 | id = 0; |
1393 | break; | 1383 | break; |
1384 | |||
1385 | case UVC_ITT_VENDOR_SPECIFIC: | ||
1386 | case UVC_ITT_CAMERA: | ||
1387 | case UVC_ITT_MEDIA_TRANSPORT_INPUT: | ||
1388 | case UVC_OTT_VENDOR_SPECIFIC: | ||
1389 | case UVC_OTT_DISPLAY: | ||
1390 | case UVC_OTT_MEDIA_TRANSPORT_OUTPUT: | ||
1391 | case UVC_TT_STREAMING: | ||
1392 | id = UVC_ENTITY_IS_OTERM(entity) ? entity->baSourceID[0] : 0; | ||
1393 | break; | ||
1394 | } | ||
1395 | |||
1396 | if (id <= 0) { | ||
1397 | *_entity = NULL; | ||
1398 | return id; | ||
1394 | } | 1399 | } |
1395 | 1400 | ||
1396 | return id; | 1401 | entity = uvc_entity_by_id(chain->dev, id); |
1402 | if (entity == NULL) { | ||
1403 | uvc_trace(UVC_TRACE_DESCR, "Found reference to " | ||
1404 | "unknown entity %d.\n", id); | ||
1405 | return -EINVAL; | ||
1406 | } | ||
1407 | |||
1408 | *_entity = entity; | ||
1409 | return 0; | ||
1397 | } | 1410 | } |
1398 | 1411 | ||
1399 | static int uvc_scan_chain(struct uvc_video_chain *chain, | 1412 | static int uvc_scan_chain(struct uvc_video_chain *chain, |
1400 | struct uvc_entity *oterm) | 1413 | struct uvc_entity *term) |
1401 | { | 1414 | { |
1402 | struct uvc_entity *entity, *prev; | 1415 | struct uvc_entity *entity, *prev; |
1403 | int id; | ||
1404 | 1416 | ||
1405 | entity = oterm; | 1417 | uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain:"); |
1406 | list_add_tail(&entity->chain, &chain->oterms); | ||
1407 | uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain: OT %d", entity->id); | ||
1408 | 1418 | ||
1409 | id = entity->output.bSourceID; | 1419 | entity = term; |
1410 | while (id != 0) { | 1420 | prev = NULL; |
1411 | prev = entity; | ||
1412 | entity = uvc_entity_by_id(chain->dev, id); | ||
1413 | if (entity == NULL) { | ||
1414 | uvc_trace(UVC_TRACE_DESCR, "Found reference to " | ||
1415 | "unknown entity %d.\n", id); | ||
1416 | return -EINVAL; | ||
1417 | } | ||
1418 | 1421 | ||
1422 | while (entity != NULL) { | ||
1423 | /* Entity must not be part of an existing chain */ | ||
1419 | if (entity->chain.next || entity->chain.prev) { | 1424 | if (entity->chain.next || entity->chain.prev) { |
1420 | uvc_trace(UVC_TRACE_DESCR, "Found reference to " | 1425 | uvc_trace(UVC_TRACE_DESCR, "Found reference to " |
1421 | "entity %d already in chain.\n", id); | 1426 | "entity %d already in chain.\n", entity->id); |
1422 | return -EINVAL; | 1427 | return -EINVAL; |
1423 | } | 1428 | } |
1424 | 1429 | ||
@@ -1430,34 +1435,34 @@ static int uvc_scan_chain(struct uvc_video_chain *chain, | |||
1430 | if (uvc_scan_chain_forward(chain, entity, prev) < 0) | 1435 | if (uvc_scan_chain_forward(chain, entity, prev) < 0) |
1431 | return -EINVAL; | 1436 | return -EINVAL; |
1432 | 1437 | ||
1433 | /* Stop when a terminal is found. */ | ||
1434 | if (UVC_ENTITY_IS_TERM(entity)) | ||
1435 | break; | ||
1436 | |||
1437 | /* Backward scan */ | 1438 | /* Backward scan */ |
1438 | id = uvc_scan_chain_backward(chain, entity); | 1439 | prev = entity; |
1439 | if (id < 0) | 1440 | if (uvc_scan_chain_backward(chain, &entity) < 0) |
1440 | return id; | 1441 | return -EINVAL; |
1441 | } | 1442 | } |
1442 | 1443 | ||
1443 | return 0; | 1444 | return 0; |
1444 | } | 1445 | } |
1445 | 1446 | ||
1446 | static unsigned int uvc_print_terms(struct list_head *terms, char *buffer) | 1447 | static unsigned int uvc_print_terms(struct list_head *terms, u16 dir, |
1448 | char *buffer) | ||
1447 | { | 1449 | { |
1448 | struct uvc_entity *term; | 1450 | struct uvc_entity *term; |
1449 | unsigned int nterms = 0; | 1451 | unsigned int nterms = 0; |
1450 | char *p = buffer; | 1452 | char *p = buffer; |
1451 | 1453 | ||
1452 | list_for_each_entry(term, terms, chain) { | 1454 | list_for_each_entry(term, terms, chain) { |
1453 | p += sprintf(p, "%u", term->id); | 1455 | if (!UVC_ENTITY_IS_TERM(term) || |
1454 | if (term->chain.next != terms) { | 1456 | UVC_TERM_DIRECTION(term) != dir) |
1457 | continue; | ||
1458 | |||
1459 | if (nterms) | ||
1455 | p += sprintf(p, ","); | 1460 | p += sprintf(p, ","); |
1456 | if (++nterms >= 4) { | 1461 | if (++nterms >= 4) { |
1457 | p += sprintf(p, "..."); | 1462 | p += sprintf(p, "..."); |
1458 | break; | 1463 | break; |
1459 | } | ||
1460 | } | 1464 | } |
1465 | p += sprintf(p, "%u", term->id); | ||
1461 | } | 1466 | } |
1462 | 1467 | ||
1463 | return p - buffer; | 1468 | return p - buffer; |
@@ -1468,9 +1473,9 @@ static const char *uvc_print_chain(struct uvc_video_chain *chain) | |||
1468 | static char buffer[43]; | 1473 | static char buffer[43]; |
1469 | char *p = buffer; | 1474 | char *p = buffer; |
1470 | 1475 | ||
1471 | p += uvc_print_terms(&chain->iterms, p); | 1476 | p += uvc_print_terms(&chain->entities, UVC_TERM_INPUT, p); |
1472 | p += sprintf(p, " -> "); | 1477 | p += sprintf(p, " -> "); |
1473 | uvc_print_terms(&chain->oterms, p); | 1478 | uvc_print_terms(&chain->entities, UVC_TERM_OUTPUT, p); |
1474 | 1479 | ||
1475 | return buffer; | 1480 | return buffer; |
1476 | } | 1481 | } |
@@ -1501,9 +1506,7 @@ static int uvc_scan_device(struct uvc_device *dev) | |||
1501 | if (chain == NULL) | 1506 | if (chain == NULL) |
1502 | return -ENOMEM; | 1507 | return -ENOMEM; |
1503 | 1508 | ||
1504 | INIT_LIST_HEAD(&chain->iterms); | 1509 | INIT_LIST_HEAD(&chain->entities); |
1505 | INIT_LIST_HEAD(&chain->oterms); | ||
1506 | INIT_LIST_HEAD(&chain->extensions); | ||
1507 | mutex_init(&chain->ctrl_mutex); | 1510 | mutex_init(&chain->ctrl_mutex); |
1508 | chain->dev = dev; | 1511 | chain->dev = dev; |
1509 | 1512 | ||
@@ -1531,22 +1534,92 @@ static int uvc_scan_device(struct uvc_device *dev) | |||
1531 | */ | 1534 | */ |
1532 | 1535 | ||
1533 | /* | 1536 | /* |
1537 | * Delete the UVC device. | ||
1538 | * | ||
1539 | * Called by the kernel when the last reference to the uvc_device structure | ||
1540 | * is released. | ||
1541 | * | ||
1542 | * As this function is called after or during disconnect(), all URBs have | ||
1543 | * already been canceled by the USB core. There is no need to kill the | ||
1544 | * interrupt URB manually. | ||
1545 | */ | ||
1546 | static void uvc_delete(struct uvc_device *dev) | ||
1547 | { | ||
1548 | struct list_head *p, *n; | ||
1549 | |||
1550 | usb_put_intf(dev->intf); | ||
1551 | usb_put_dev(dev->udev); | ||
1552 | |||
1553 | uvc_status_cleanup(dev); | ||
1554 | uvc_ctrl_cleanup_device(dev); | ||
1555 | |||
1556 | list_for_each_safe(p, n, &dev->chains) { | ||
1557 | struct uvc_video_chain *chain; | ||
1558 | chain = list_entry(p, struct uvc_video_chain, list); | ||
1559 | kfree(chain); | ||
1560 | } | ||
1561 | |||
1562 | list_for_each_safe(p, n, &dev->entities) { | ||
1563 | struct uvc_entity *entity; | ||
1564 | entity = list_entry(p, struct uvc_entity, list); | ||
1565 | kfree(entity); | ||
1566 | } | ||
1567 | |||
1568 | list_for_each_safe(p, n, &dev->streams) { | ||
1569 | struct uvc_streaming *streaming; | ||
1570 | streaming = list_entry(p, struct uvc_streaming, list); | ||
1571 | usb_driver_release_interface(&uvc_driver.driver, | ||
1572 | streaming->intf); | ||
1573 | usb_put_intf(streaming->intf); | ||
1574 | kfree(streaming->format); | ||
1575 | kfree(streaming->header.bmaControls); | ||
1576 | kfree(streaming); | ||
1577 | } | ||
1578 | |||
1579 | kfree(dev); | ||
1580 | } | ||
1581 | |||
1582 | static void uvc_release(struct video_device *vdev) | ||
1583 | { | ||
1584 | struct uvc_streaming *stream = video_get_drvdata(vdev); | ||
1585 | struct uvc_device *dev = stream->dev; | ||
1586 | |||
1587 | video_device_release(vdev); | ||
1588 | |||
1589 | /* Decrement the registered streams count and delete the device when it | ||
1590 | * reaches zero. | ||
1591 | */ | ||
1592 | if (atomic_dec_and_test(&dev->nstreams)) | ||
1593 | uvc_delete(dev); | ||
1594 | } | ||
1595 | |||
1596 | /* | ||
1534 | * Unregister the video devices. | 1597 | * Unregister the video devices. |
1535 | */ | 1598 | */ |
1536 | static void uvc_unregister_video(struct uvc_device *dev) | 1599 | static void uvc_unregister_video(struct uvc_device *dev) |
1537 | { | 1600 | { |
1538 | struct uvc_streaming *stream; | 1601 | struct uvc_streaming *stream; |
1539 | 1602 | ||
1603 | /* Unregistering all video devices might result in uvc_delete() being | ||
1604 | * called from inside the loop if there's no open file handle. To avoid | ||
1605 | * that, increment the stream count before iterating over the streams | ||
1606 | * and decrement it when done. | ||
1607 | */ | ||
1608 | atomic_inc(&dev->nstreams); | ||
1609 | |||
1540 | list_for_each_entry(stream, &dev->streams, list) { | 1610 | list_for_each_entry(stream, &dev->streams, list) { |
1541 | if (stream->vdev == NULL) | 1611 | if (stream->vdev == NULL) |
1542 | continue; | 1612 | continue; |
1543 | 1613 | ||
1544 | if (stream->vdev->minor == -1) | 1614 | video_unregister_device(stream->vdev); |
1545 | video_device_release(stream->vdev); | ||
1546 | else | ||
1547 | video_unregister_device(stream->vdev); | ||
1548 | stream->vdev = NULL; | 1615 | stream->vdev = NULL; |
1549 | } | 1616 | } |
1617 | |||
1618 | /* Decrement the stream count and call uvc_delete explicitly if there | ||
1619 | * are no stream left. | ||
1620 | */ | ||
1621 | if (atomic_dec_and_test(&dev->nstreams)) | ||
1622 | uvc_delete(dev); | ||
1550 | } | 1623 | } |
1551 | 1624 | ||
1552 | static int uvc_register_video(struct uvc_device *dev, | 1625 | static int uvc_register_video(struct uvc_device *dev, |
@@ -1580,7 +1653,7 @@ static int uvc_register_video(struct uvc_device *dev, | |||
1580 | vdev->parent = &dev->intf->dev; | 1653 | vdev->parent = &dev->intf->dev; |
1581 | vdev->minor = -1; | 1654 | vdev->minor = -1; |
1582 | vdev->fops = &uvc_fops; | 1655 | vdev->fops = &uvc_fops; |
1583 | vdev->release = video_device_release; | 1656 | vdev->release = uvc_release; |
1584 | strlcpy(vdev->name, dev->name, sizeof vdev->name); | 1657 | strlcpy(vdev->name, dev->name, sizeof vdev->name); |
1585 | 1658 | ||
1586 | /* Set the driver data before calling video_register_device, otherwise | 1659 | /* Set the driver data before calling video_register_device, otherwise |
@@ -1598,6 +1671,7 @@ static int uvc_register_video(struct uvc_device *dev, | |||
1598 | return ret; | 1671 | return ret; |
1599 | } | 1672 | } |
1600 | 1673 | ||
1674 | atomic_inc(&dev->nstreams); | ||
1601 | return 0; | 1675 | return 0; |
1602 | } | 1676 | } |
1603 | 1677 | ||
@@ -1605,13 +1679,13 @@ static int uvc_register_video(struct uvc_device *dev, | |||
1605 | * Register all video devices in all chains. | 1679 | * Register all video devices in all chains. |
1606 | */ | 1680 | */ |
1607 | static int uvc_register_terms(struct uvc_device *dev, | 1681 | static int uvc_register_terms(struct uvc_device *dev, |
1608 | struct uvc_video_chain *chain, struct list_head *terms) | 1682 | struct uvc_video_chain *chain) |
1609 | { | 1683 | { |
1610 | struct uvc_streaming *stream; | 1684 | struct uvc_streaming *stream; |
1611 | struct uvc_entity *term; | 1685 | struct uvc_entity *term; |
1612 | int ret; | 1686 | int ret; |
1613 | 1687 | ||
1614 | list_for_each_entry(term, terms, chain) { | 1688 | list_for_each_entry(term, &chain->entities, chain) { |
1615 | if (UVC_ENTITY_TYPE(term) != UVC_TT_STREAMING) | 1689 | if (UVC_ENTITY_TYPE(term) != UVC_TT_STREAMING) |
1616 | continue; | 1690 | continue; |
1617 | 1691 | ||
@@ -1637,11 +1711,7 @@ static int uvc_register_chains(struct uvc_device *dev) | |||
1637 | int ret; | 1711 | int ret; |
1638 | 1712 | ||
1639 | list_for_each_entry(chain, &dev->chains, list) { | 1713 | list_for_each_entry(chain, &dev->chains, list) { |
1640 | ret = uvc_register_terms(dev, chain, &chain->iterms); | 1714 | ret = uvc_register_terms(dev, chain); |
1641 | if (ret < 0) | ||
1642 | return ret; | ||
1643 | |||
1644 | ret = uvc_register_terms(dev, chain, &chain->oterms); | ||
1645 | if (ret < 0) | 1715 | if (ret < 0) |
1646 | return ret; | 1716 | return ret; |
1647 | } | 1717 | } |
@@ -1653,61 +1723,6 @@ static int uvc_register_chains(struct uvc_device *dev) | |||
1653 | * USB probe, disconnect, suspend and resume | 1723 | * USB probe, disconnect, suspend and resume |
1654 | */ | 1724 | */ |
1655 | 1725 | ||
1656 | /* | ||
1657 | * Delete the UVC device. | ||
1658 | * | ||
1659 | * Called by the kernel when the last reference to the uvc_device structure | ||
1660 | * is released. | ||
1661 | * | ||
1662 | * Unregistering the video devices is done here because every opened instance | ||
1663 | * must be closed before the device can be unregistered. An alternative would | ||
1664 | * have been to use another reference count for uvc_v4l2_open/uvc_release, and | ||
1665 | * unregister the video devices on disconnect when that reference count drops | ||
1666 | * to zero. | ||
1667 | * | ||
1668 | * As this function is called after or during disconnect(), all URBs have | ||
1669 | * already been canceled by the USB core. There is no need to kill the | ||
1670 | * interrupt URB manually. | ||
1671 | */ | ||
1672 | void uvc_delete(struct kref *kref) | ||
1673 | { | ||
1674 | struct uvc_device *dev = container_of(kref, struct uvc_device, kref); | ||
1675 | struct list_head *p, *n; | ||
1676 | |||
1677 | /* Unregister the video devices. */ | ||
1678 | uvc_unregister_video(dev); | ||
1679 | usb_put_intf(dev->intf); | ||
1680 | usb_put_dev(dev->udev); | ||
1681 | |||
1682 | uvc_status_cleanup(dev); | ||
1683 | uvc_ctrl_cleanup_device(dev); | ||
1684 | |||
1685 | list_for_each_safe(p, n, &dev->chains) { | ||
1686 | struct uvc_video_chain *chain; | ||
1687 | chain = list_entry(p, struct uvc_video_chain, list); | ||
1688 | kfree(chain); | ||
1689 | } | ||
1690 | |||
1691 | list_for_each_safe(p, n, &dev->entities) { | ||
1692 | struct uvc_entity *entity; | ||
1693 | entity = list_entry(p, struct uvc_entity, list); | ||
1694 | kfree(entity); | ||
1695 | } | ||
1696 | |||
1697 | list_for_each_safe(p, n, &dev->streams) { | ||
1698 | struct uvc_streaming *streaming; | ||
1699 | streaming = list_entry(p, struct uvc_streaming, list); | ||
1700 | usb_driver_release_interface(&uvc_driver.driver, | ||
1701 | streaming->intf); | ||
1702 | usb_put_intf(streaming->intf); | ||
1703 | kfree(streaming->format); | ||
1704 | kfree(streaming->header.bmaControls); | ||
1705 | kfree(streaming); | ||
1706 | } | ||
1707 | |||
1708 | kfree(dev); | ||
1709 | } | ||
1710 | |||
1711 | static int uvc_probe(struct usb_interface *intf, | 1726 | static int uvc_probe(struct usb_interface *intf, |
1712 | const struct usb_device_id *id) | 1727 | const struct usb_device_id *id) |
1713 | { | 1728 | { |
@@ -1730,7 +1745,7 @@ static int uvc_probe(struct usb_interface *intf, | |||
1730 | INIT_LIST_HEAD(&dev->entities); | 1745 | INIT_LIST_HEAD(&dev->entities); |
1731 | INIT_LIST_HEAD(&dev->chains); | 1746 | INIT_LIST_HEAD(&dev->chains); |
1732 | INIT_LIST_HEAD(&dev->streams); | 1747 | INIT_LIST_HEAD(&dev->streams); |
1733 | kref_init(&dev->kref); | 1748 | atomic_set(&dev->nstreams, 0); |
1734 | atomic_set(&dev->users, 0); | 1749 | atomic_set(&dev->users, 0); |
1735 | 1750 | ||
1736 | dev->udev = usb_get_dev(udev); | 1751 | dev->udev = usb_get_dev(udev); |
@@ -1792,7 +1807,7 @@ static int uvc_probe(struct usb_interface *intf, | |||
1792 | return 0; | 1807 | return 0; |
1793 | 1808 | ||
1794 | error: | 1809 | error: |
1795 | kref_put(&dev->kref, uvc_delete); | 1810 | uvc_unregister_video(dev); |
1796 | return -ENODEV; | 1811 | return -ENODEV; |
1797 | } | 1812 | } |
1798 | 1813 | ||
@@ -1809,21 +1824,9 @@ static void uvc_disconnect(struct usb_interface *intf) | |||
1809 | UVC_SC_VIDEOSTREAMING) | 1824 | UVC_SC_VIDEOSTREAMING) |
1810 | return; | 1825 | return; |
1811 | 1826 | ||
1812 | /* uvc_v4l2_open() might race uvc_disconnect(). A static driver-wide | ||
1813 | * lock is needed to prevent uvc_disconnect from releasing its | ||
1814 | * reference to the uvc_device instance after uvc_v4l2_open() received | ||
1815 | * the pointer to the device (video_devdata) but before it got the | ||
1816 | * chance to increase the reference count (kref_get). | ||
1817 | * | ||
1818 | * Note that the reference can't be released with the lock held, | ||
1819 | * otherwise a AB-BA deadlock can occur with videodev_lock that | ||
1820 | * videodev acquires in videodev_open() and video_unregister_device(). | ||
1821 | */ | ||
1822 | mutex_lock(&uvc_driver.open_mutex); | ||
1823 | dev->state |= UVC_DEV_DISCONNECTED; | 1827 | dev->state |= UVC_DEV_DISCONNECTED; |
1824 | mutex_unlock(&uvc_driver.open_mutex); | ||
1825 | 1828 | ||
1826 | kref_put(&dev->kref, uvc_delete); | 1829 | uvc_unregister_video(dev); |
1827 | } | 1830 | } |
1828 | 1831 | ||
1829 | static int uvc_suspend(struct usb_interface *intf, pm_message_t message) | 1832 | static int uvc_suspend(struct usb_interface *intf, pm_message_t message) |
@@ -1899,6 +1902,15 @@ static int uvc_reset_resume(struct usb_interface *intf) | |||
1899 | * though they are compliant. | 1902 | * though they are compliant. |
1900 | */ | 1903 | */ |
1901 | static struct usb_device_id uvc_ids[] = { | 1904 | static struct usb_device_id uvc_ids[] = { |
1905 | /* Genius eFace 2025 */ | ||
1906 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1907 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1908 | .idVendor = 0x0458, | ||
1909 | .idProduct = 0x706e, | ||
1910 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1911 | .bInterfaceSubClass = 1, | ||
1912 | .bInterfaceProtocol = 0, | ||
1913 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1902 | /* Microsoft Lifecam NX-6000 */ | 1914 | /* Microsoft Lifecam NX-6000 */ |
1903 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 1915 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
1904 | | USB_DEVICE_ID_MATCH_INT_INFO, | 1916 | | USB_DEVICE_ID_MATCH_INT_INFO, |
@@ -2123,6 +2135,15 @@ static struct usb_device_id uvc_ids[] = { | |||
2123 | .bInterfaceSubClass = 1, | 2135 | .bInterfaceSubClass = 1, |
2124 | .bInterfaceProtocol = 0, | 2136 | .bInterfaceProtocol = 0, |
2125 | .driver_info = UVC_QUIRK_STATUS_INTERVAL }, | 2137 | .driver_info = UVC_QUIRK_STATUS_INTERVAL }, |
2138 | /* MSI StarCam 370i */ | ||
2139 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
2140 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
2141 | .idVendor = 0x1b3b, | ||
2142 | .idProduct = 0x2951, | ||
2143 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
2144 | .bInterfaceSubClass = 1, | ||
2145 | .bInterfaceProtocol = 0, | ||
2146 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
2126 | /* SiGma Micro USB Web Camera */ | 2147 | /* SiGma Micro USB Web Camera */ |
2127 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 2148 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
2128 | | USB_DEVICE_ID_MATCH_INT_INFO, | 2149 | | USB_DEVICE_ID_MATCH_INT_INFO, |
@@ -2159,7 +2180,6 @@ static int __init uvc_init(void) | |||
2159 | 2180 | ||
2160 | INIT_LIST_HEAD(&uvc_driver.devices); | 2181 | INIT_LIST_HEAD(&uvc_driver.devices); |
2161 | INIT_LIST_HEAD(&uvc_driver.controls); | 2182 | INIT_LIST_HEAD(&uvc_driver.controls); |
2162 | mutex_init(&uvc_driver.open_mutex); | ||
2163 | mutex_init(&uvc_driver.ctrl_mutex); | 2183 | mutex_init(&uvc_driver.ctrl_mutex); |
2164 | 2184 | ||
2165 | uvc_ctrl_init(); | 2185 | uvc_ctrl_init(); |
@@ -2184,6 +2204,8 @@ module_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR); | |||
2184 | MODULE_PARM_DESC(quirks, "Forced device quirks"); | 2204 | MODULE_PARM_DESC(quirks, "Forced device quirks"); |
2185 | module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR); | 2205 | module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR); |
2186 | MODULE_PARM_DESC(trace, "Trace level bitmask"); | 2206 | MODULE_PARM_DESC(trace, "Trace level bitmask"); |
2207 | module_param_named(timeout, uvc_timeout_param, uint, S_IRUGO|S_IWUSR); | ||
2208 | MODULE_PARM_DESC(timeout, "Streaming control requests timeout"); | ||
2187 | 2209 | ||
2188 | MODULE_AUTHOR(DRIVER_AUTHOR); | 2210 | MODULE_AUTHOR(DRIVER_AUTHOR); |
2189 | MODULE_DESCRIPTION(DRIVER_DESC); | 2211 | MODULE_DESCRIPTION(DRIVER_DESC); |
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index a2bdd806efab..23239a4adefe 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c | |||
@@ -364,37 +364,30 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, | |||
364 | * unprivileged state. Only a single instance can be in a privileged state at | 364 | * unprivileged state. Only a single instance can be in a privileged state at |
365 | * a given time. Trying to perform an operation that requires privileges will | 365 | * a given time. Trying to perform an operation that requires privileges will |
366 | * automatically acquire the required privileges if possible, or return -EBUSY | 366 | * automatically acquire the required privileges if possible, or return -EBUSY |
367 | * otherwise. Privileges are dismissed when closing the instance. | 367 | * otherwise. Privileges are dismissed when closing the instance or when |
368 | * freeing the video buffers using VIDIOC_REQBUFS. | ||
368 | * | 369 | * |
369 | * Operations that require privileges are: | 370 | * Operations that require privileges are: |
370 | * | 371 | * |
371 | * - VIDIOC_S_INPUT | 372 | * - VIDIOC_S_INPUT |
372 | * - VIDIOC_S_PARM | 373 | * - VIDIOC_S_PARM |
373 | * - VIDIOC_S_FMT | 374 | * - VIDIOC_S_FMT |
374 | * - VIDIOC_TRY_FMT | ||
375 | * - VIDIOC_REQBUFS | 375 | * - VIDIOC_REQBUFS |
376 | */ | 376 | */ |
377 | static int uvc_acquire_privileges(struct uvc_fh *handle) | 377 | static int uvc_acquire_privileges(struct uvc_fh *handle) |
378 | { | 378 | { |
379 | int ret = 0; | ||
380 | |||
381 | /* Always succeed if the handle is already privileged. */ | 379 | /* Always succeed if the handle is already privileged. */ |
382 | if (handle->state == UVC_HANDLE_ACTIVE) | 380 | if (handle->state == UVC_HANDLE_ACTIVE) |
383 | return 0; | 381 | return 0; |
384 | 382 | ||
385 | /* Check if the device already has a privileged handle. */ | 383 | /* Check if the device already has a privileged handle. */ |
386 | mutex_lock(&uvc_driver.open_mutex); | ||
387 | if (atomic_inc_return(&handle->stream->active) != 1) { | 384 | if (atomic_inc_return(&handle->stream->active) != 1) { |
388 | atomic_dec(&handle->stream->active); | 385 | atomic_dec(&handle->stream->active); |
389 | ret = -EBUSY; | 386 | return -EBUSY; |
390 | goto done; | ||
391 | } | 387 | } |
392 | 388 | ||
393 | handle->state = UVC_HANDLE_ACTIVE; | 389 | handle->state = UVC_HANDLE_ACTIVE; |
394 | 390 | return 0; | |
395 | done: | ||
396 | mutex_unlock(&uvc_driver.open_mutex); | ||
397 | return ret; | ||
398 | } | 391 | } |
399 | 392 | ||
400 | static void uvc_dismiss_privileges(struct uvc_fh *handle) | 393 | static void uvc_dismiss_privileges(struct uvc_fh *handle) |
@@ -421,24 +414,20 @@ static int uvc_v4l2_open(struct file *file) | |||
421 | int ret = 0; | 414 | int ret = 0; |
422 | 415 | ||
423 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n"); | 416 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n"); |
424 | mutex_lock(&uvc_driver.open_mutex); | ||
425 | stream = video_drvdata(file); | 417 | stream = video_drvdata(file); |
426 | 418 | ||
427 | if (stream->dev->state & UVC_DEV_DISCONNECTED) { | 419 | if (stream->dev->state & UVC_DEV_DISCONNECTED) |
428 | ret = -ENODEV; | 420 | return -ENODEV; |
429 | goto done; | ||
430 | } | ||
431 | 421 | ||
432 | ret = usb_autopm_get_interface(stream->dev->intf); | 422 | ret = usb_autopm_get_interface(stream->dev->intf); |
433 | if (ret < 0) | 423 | if (ret < 0) |
434 | goto done; | 424 | return ret; |
435 | 425 | ||
436 | /* Create the device handle. */ | 426 | /* Create the device handle. */ |
437 | handle = kzalloc(sizeof *handle, GFP_KERNEL); | 427 | handle = kzalloc(sizeof *handle, GFP_KERNEL); |
438 | if (handle == NULL) { | 428 | if (handle == NULL) { |
439 | usb_autopm_put_interface(stream->dev->intf); | 429 | usb_autopm_put_interface(stream->dev->intf); |
440 | ret = -ENOMEM; | 430 | return -ENOMEM; |
441 | goto done; | ||
442 | } | 431 | } |
443 | 432 | ||
444 | if (atomic_inc_return(&stream->dev->users) == 1) { | 433 | if (atomic_inc_return(&stream->dev->users) == 1) { |
@@ -447,7 +436,7 @@ static int uvc_v4l2_open(struct file *file) | |||
447 | usb_autopm_put_interface(stream->dev->intf); | 436 | usb_autopm_put_interface(stream->dev->intf); |
448 | atomic_dec(&stream->dev->users); | 437 | atomic_dec(&stream->dev->users); |
449 | kfree(handle); | 438 | kfree(handle); |
450 | goto done; | 439 | return ret; |
451 | } | 440 | } |
452 | } | 441 | } |
453 | 442 | ||
@@ -456,11 +445,7 @@ static int uvc_v4l2_open(struct file *file) | |||
456 | handle->state = UVC_HANDLE_PASSIVE; | 445 | handle->state = UVC_HANDLE_PASSIVE; |
457 | file->private_data = handle; | 446 | file->private_data = handle; |
458 | 447 | ||
459 | kref_get(&stream->dev->kref); | 448 | return 0; |
460 | |||
461 | done: | ||
462 | mutex_unlock(&uvc_driver.open_mutex); | ||
463 | return ret; | ||
464 | } | 449 | } |
465 | 450 | ||
466 | static int uvc_v4l2_release(struct file *file) | 451 | static int uvc_v4l2_release(struct file *file) |
@@ -490,7 +475,6 @@ static int uvc_v4l2_release(struct file *file) | |||
490 | uvc_status_stop(stream->dev); | 475 | uvc_status_stop(stream->dev); |
491 | 476 | ||
492 | usb_autopm_put_interface(stream->dev->intf); | 477 | usb_autopm_put_interface(stream->dev->intf); |
493 | kref_put(&stream->dev->kref, uvc_delete); | ||
494 | return 0; | 478 | return 0; |
495 | } | 479 | } |
496 | 480 | ||
@@ -636,12 +620,16 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
636 | (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { | 620 | (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { |
637 | if (index != 0) | 621 | if (index != 0) |
638 | return -EINVAL; | 622 | return -EINVAL; |
639 | iterm = list_first_entry(&chain->iterms, | 623 | list_for_each_entry(iterm, &chain->entities, chain) { |
640 | struct uvc_entity, chain); | 624 | if (UVC_ENTITY_IS_ITERM(iterm)) |
625 | break; | ||
626 | } | ||
641 | pin = iterm->id; | 627 | pin = iterm->id; |
642 | } else if (pin < selector->selector.bNrInPins) { | 628 | } else if (pin < selector->bNrInPins) { |
643 | pin = selector->selector.baSourceID[index]; | 629 | pin = selector->baSourceID[index]; |
644 | list_for_each_entry(iterm, chain->iterms.next, chain) { | 630 | list_for_each_entry(iterm, &chain->entities, chain) { |
631 | if (!UVC_ENTITY_IS_ITERM(iterm)) | ||
632 | continue; | ||
645 | if (iterm->id == pin) | 633 | if (iterm->id == pin) |
646 | break; | 634 | break; |
647 | } | 635 | } |
@@ -692,7 +680,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
692 | break; | 680 | break; |
693 | } | 681 | } |
694 | 682 | ||
695 | if (input == 0 || input > chain->selector->selector.bNrInPins) | 683 | if (input == 0 || input > chain->selector->bNrInPins) |
696 | return -EINVAL; | 684 | return -EINVAL; |
697 | 685 | ||
698 | return uvc_query_ctrl(chain->dev, UVC_SET_CUR, | 686 | return uvc_query_ctrl(chain->dev, UVC_SET_CUR, |
@@ -731,9 +719,6 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
731 | { | 719 | { |
732 | struct uvc_streaming_control probe; | 720 | struct uvc_streaming_control probe; |
733 | 721 | ||
734 | if ((ret = uvc_acquire_privileges(handle)) < 0) | ||
735 | return ret; | ||
736 | |||
737 | return uvc_v4l2_try_format(stream, arg, &probe, NULL, NULL); | 722 | return uvc_v4l2_try_format(stream, arg, &probe, NULL, NULL); |
738 | } | 723 | } |
739 | 724 | ||
@@ -888,6 +873,9 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
888 | if (ret < 0) | 873 | if (ret < 0) |
889 | return ret; | 874 | return ret; |
890 | 875 | ||
876 | if (ret == 0) | ||
877 | uvc_dismiss_privileges(handle); | ||
878 | |||
891 | rb->count = ret; | 879 | rb->count = ret; |
892 | ret = 0; | 880 | ret = 0; |
893 | break; | 881 | break; |
@@ -1051,7 +1039,7 @@ static ssize_t uvc_v4l2_read(struct file *file, char __user *data, | |||
1051 | size_t count, loff_t *ppos) | 1039 | size_t count, loff_t *ppos) |
1052 | { | 1040 | { |
1053 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_read: not implemented.\n"); | 1041 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_read: not implemented.\n"); |
1054 | return -ENODEV; | 1042 | return -EINVAL; |
1055 | } | 1043 | } |
1056 | 1044 | ||
1057 | /* | 1045 | /* |
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index a6e41d12b221..05139a4f14f6 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c | |||
@@ -135,7 +135,7 @@ static int uvc_get_video_ctrl(struct uvc_streaming *stream, | |||
135 | 135 | ||
136 | ret = __uvc_query_ctrl(stream->dev, query, 0, stream->intfnum, | 136 | ret = __uvc_query_ctrl(stream->dev, query, 0, stream->intfnum, |
137 | probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data, | 137 | probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data, |
138 | size, UVC_CTRL_STREAMING_TIMEOUT); | 138 | size, uvc_timeout_param); |
139 | 139 | ||
140 | if ((query == UVC_GET_MIN || query == UVC_GET_MAX) && ret == 2) { | 140 | if ((query == UVC_GET_MIN || query == UVC_GET_MAX) && ret == 2) { |
141 | /* Some cameras, mostly based on Bison Electronics chipsets, | 141 | /* Some cameras, mostly based on Bison Electronics chipsets, |
@@ -239,7 +239,7 @@ static int uvc_set_video_ctrl(struct uvc_streaming *stream, | |||
239 | 239 | ||
240 | ret = __uvc_query_ctrl(stream->dev, UVC_SET_CUR, 0, stream->intfnum, | 240 | ret = __uvc_query_ctrl(stream->dev, UVC_SET_CUR, 0, stream->intfnum, |
241 | probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data, | 241 | probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data, |
242 | size, UVC_CTRL_STREAMING_TIMEOUT); | 242 | size, uvc_timeout_param); |
243 | if (ret != size) { | 243 | if (ret != size) { |
244 | uvc_printk(KERN_ERR, "Failed to set UVC %s control : " | 244 | uvc_printk(KERN_ERR, "Failed to set UVC %s control : " |
245 | "%d (exp. %u).\n", probe ? "probe" : "commit", | 245 | "%d (exp. %u).\n", probe ? "probe" : "commit", |
@@ -770,8 +770,9 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream, | |||
770 | /* Retry allocations until one succeed. */ | 770 | /* Retry allocations until one succeed. */ |
771 | for (; npackets > 1; npackets /= 2) { | 771 | for (; npackets > 1; npackets /= 2) { |
772 | for (i = 0; i < UVC_URBS; ++i) { | 772 | for (i = 0; i < UVC_URBS; ++i) { |
773 | stream->urb_size = psize * npackets; | ||
773 | stream->urb_buffer[i] = usb_buffer_alloc( | 774 | stream->urb_buffer[i] = usb_buffer_alloc( |
774 | stream->dev->udev, psize * npackets, | 775 | stream->dev->udev, stream->urb_size, |
775 | gfp_flags | __GFP_NOWARN, &stream->urb_dma[i]); | 776 | gfp_flags | __GFP_NOWARN, &stream->urb_dma[i]); |
776 | if (!stream->urb_buffer[i]) { | 777 | if (!stream->urb_buffer[i]) { |
777 | uvc_free_urb_buffers(stream); | 778 | uvc_free_urb_buffers(stream); |
@@ -780,11 +781,15 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream, | |||
780 | } | 781 | } |
781 | 782 | ||
782 | if (i == UVC_URBS) { | 783 | if (i == UVC_URBS) { |
783 | stream->urb_size = psize * npackets; | 784 | uvc_trace(UVC_TRACE_VIDEO, "Allocated %u URB buffers " |
785 | "of %ux%u bytes each.\n", UVC_URBS, npackets, | ||
786 | psize); | ||
784 | return npackets; | 787 | return npackets; |
785 | } | 788 | } |
786 | } | 789 | } |
787 | 790 | ||
791 | uvc_trace(UVC_TRACE_VIDEO, "Failed to allocate URB buffers (%u bytes " | ||
792 | "per packet).\n", psize); | ||
788 | return 0; | 793 | return 0; |
789 | } | 794 | } |
790 | 795 | ||
@@ -935,10 +940,12 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) | |||
935 | bandwidth = stream->ctrl.dwMaxPayloadTransferSize; | 940 | bandwidth = stream->ctrl.dwMaxPayloadTransferSize; |
936 | 941 | ||
937 | if (bandwidth == 0) { | 942 | if (bandwidth == 0) { |
938 | uvc_printk(KERN_WARNING, "device %s requested null " | 943 | uvc_trace(UVC_TRACE_VIDEO, "Device requested null " |
939 | "bandwidth, defaulting to lowest.\n", | 944 | "bandwidth, defaulting to lowest.\n"); |
940 | stream->dev->name); | ||
941 | bandwidth = 1; | 945 | bandwidth = 1; |
946 | } else { | ||
947 | uvc_trace(UVC_TRACE_VIDEO, "Device requested %u " | ||
948 | "B/frame bandwidth.\n", bandwidth); | ||
942 | } | 949 | } |
943 | 950 | ||
944 | for (i = 0; i < intf->num_altsetting; ++i) { | 951 | for (i = 0; i < intf->num_altsetting; ++i) { |
@@ -955,8 +962,11 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) | |||
955 | break; | 962 | break; |
956 | } | 963 | } |
957 | 964 | ||
958 | if (i >= intf->num_altsetting) | 965 | if (i >= intf->num_altsetting) { |
966 | uvc_trace(UVC_TRACE_VIDEO, "No fast enough alt setting " | ||
967 | "for requested bandwidth.\n"); | ||
959 | return -EIO; | 968 | return -EIO; |
969 | } | ||
960 | 970 | ||
961 | ret = usb_set_interface(stream->dev->udev, intfnum, i); | 971 | ret = usb_set_interface(stream->dev->udev, intfnum, i); |
962 | if (ret < 0) | 972 | if (ret < 0) |
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index e7958aa454ce..7ec9a04ced50 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h | |||
@@ -75,6 +75,7 @@ struct uvc_xu_control { | |||
75 | 75 | ||
76 | #define UVC_TERM_INPUT 0x0000 | 76 | #define UVC_TERM_INPUT 0x0000 |
77 | #define UVC_TERM_OUTPUT 0x8000 | 77 | #define UVC_TERM_OUTPUT 0x8000 |
78 | #define UVC_TERM_DIRECTION(term) ((term)->type & 0x8000) | ||
78 | 79 | ||
79 | #define UVC_ENTITY_TYPE(entity) ((entity)->type & 0x7fff) | 80 | #define UVC_ENTITY_TYPE(entity) ((entity)->type & 0x7fff) |
80 | #define UVC_ENTITY_IS_UNIT(entity) (((entity)->type & 0xff00) == 0) | 81 | #define UVC_ENTITY_IS_UNIT(entity) (((entity)->type & 0xff00) == 0) |
@@ -148,7 +149,7 @@ struct uvc_xu_control { | |||
148 | #define UVC_MAX_STATUS_SIZE 16 | 149 | #define UVC_MAX_STATUS_SIZE 16 |
149 | 150 | ||
150 | #define UVC_CTRL_CONTROL_TIMEOUT 300 | 151 | #define UVC_CTRL_CONTROL_TIMEOUT 300 |
151 | #define UVC_CTRL_STREAMING_TIMEOUT 1000 | 152 | #define UVC_CTRL_STREAMING_TIMEOUT 3000 |
152 | 153 | ||
153 | /* Devices quirks */ | 154 | /* Devices quirks */ |
154 | #define UVC_QUIRK_STATUS_INTERVAL 0x00000001 | 155 | #define UVC_QUIRK_STATUS_INTERVAL 0x00000001 |
@@ -292,11 +293,9 @@ struct uvc_entity { | |||
292 | } media; | 293 | } media; |
293 | 294 | ||
294 | struct { | 295 | struct { |
295 | __u8 bSourceID; | ||
296 | } output; | 296 | } output; |
297 | 297 | ||
298 | struct { | 298 | struct { |
299 | __u8 bSourceID; | ||
300 | __u16 wMaxMultiplier; | 299 | __u16 wMaxMultiplier; |
301 | __u8 bControlSize; | 300 | __u8 bControlSize; |
302 | __u8 *bmControls; | 301 | __u8 *bmControls; |
@@ -304,21 +303,20 @@ struct uvc_entity { | |||
304 | } processing; | 303 | } processing; |
305 | 304 | ||
306 | struct { | 305 | struct { |
307 | __u8 bNrInPins; | ||
308 | __u8 *baSourceID; | ||
309 | } selector; | 306 | } selector; |
310 | 307 | ||
311 | struct { | 308 | struct { |
312 | __u8 guidExtensionCode[16]; | 309 | __u8 guidExtensionCode[16]; |
313 | __u8 bNumControls; | 310 | __u8 bNumControls; |
314 | __u8 bNrInPins; | ||
315 | __u8 *baSourceID; | ||
316 | __u8 bControlSize; | 311 | __u8 bControlSize; |
317 | __u8 *bmControls; | 312 | __u8 *bmControls; |
318 | __u8 *bmControlsType; | 313 | __u8 *bmControlsType; |
319 | } extension; | 314 | } extension; |
320 | }; | 315 | }; |
321 | 316 | ||
317 | __u8 bNrInPins; | ||
318 | __u8 *baSourceID; | ||
319 | |||
322 | unsigned int ncontrols; | 320 | unsigned int ncontrols; |
323 | struct uvc_control *controls; | 321 | struct uvc_control *controls; |
324 | }; | 322 | }; |
@@ -408,11 +406,9 @@ struct uvc_video_chain { | |||
408 | struct uvc_device *dev; | 406 | struct uvc_device *dev; |
409 | struct list_head list; | 407 | struct list_head list; |
410 | 408 | ||
411 | struct list_head iterms; /* Input terminals */ | 409 | struct list_head entities; /* All entities */ |
412 | struct list_head oterms; /* Output terminals */ | ||
413 | struct uvc_entity *processing; /* Processing unit */ | 410 | struct uvc_entity *processing; /* Processing unit */ |
414 | struct uvc_entity *selector; /* Selector unit */ | 411 | struct uvc_entity *selector; /* Selector unit */ |
415 | struct list_head extensions; /* Extension units */ | ||
416 | 412 | ||
417 | struct mutex ctrl_mutex; | 413 | struct mutex ctrl_mutex; |
418 | }; | 414 | }; |
@@ -475,7 +471,6 @@ struct uvc_device { | |||
475 | char name[32]; | 471 | char name[32]; |
476 | 472 | ||
477 | enum uvc_device_state state; | 473 | enum uvc_device_state state; |
478 | struct kref kref; | ||
479 | struct list_head list; | 474 | struct list_head list; |
480 | atomic_t users; | 475 | atomic_t users; |
481 | 476 | ||
@@ -488,6 +483,7 @@ struct uvc_device { | |||
488 | 483 | ||
489 | /* Video Streaming interfaces */ | 484 | /* Video Streaming interfaces */ |
490 | struct list_head streams; | 485 | struct list_head streams; |
486 | atomic_t nstreams; | ||
491 | 487 | ||
492 | /* Status Interrupt Endpoint */ | 488 | /* Status Interrupt Endpoint */ |
493 | struct usb_host_endpoint *int_ep; | 489 | struct usb_host_endpoint *int_ep; |
@@ -511,8 +507,6 @@ struct uvc_fh { | |||
511 | struct uvc_driver { | 507 | struct uvc_driver { |
512 | struct usb_driver driver; | 508 | struct usb_driver driver; |
513 | 509 | ||
514 | struct mutex open_mutex; /* protects from open/disconnect race */ | ||
515 | |||
516 | struct list_head devices; /* struct uvc_device list */ | 510 | struct list_head devices; /* struct uvc_device list */ |
517 | struct list_head controls; /* struct uvc_control_info list */ | 511 | struct list_head controls; /* struct uvc_control_info list */ |
518 | struct mutex ctrl_mutex; /* protects controls and devices | 512 | struct mutex ctrl_mutex; /* protects controls and devices |
@@ -533,12 +527,14 @@ struct uvc_driver { | |||
533 | #define UVC_TRACE_FRAME (1 << 7) | 527 | #define UVC_TRACE_FRAME (1 << 7) |
534 | #define UVC_TRACE_SUSPEND (1 << 8) | 528 | #define UVC_TRACE_SUSPEND (1 << 8) |
535 | #define UVC_TRACE_STATUS (1 << 9) | 529 | #define UVC_TRACE_STATUS (1 << 9) |
530 | #define UVC_TRACE_VIDEO (1 << 10) | ||
536 | 531 | ||
537 | #define UVC_WARN_MINMAX 0 | 532 | #define UVC_WARN_MINMAX 0 |
538 | #define UVC_WARN_PROBE_DEF 1 | 533 | #define UVC_WARN_PROBE_DEF 1 |
539 | 534 | ||
540 | extern unsigned int uvc_no_drop_param; | 535 | extern unsigned int uvc_no_drop_param; |
541 | extern unsigned int uvc_trace_param; | 536 | extern unsigned int uvc_trace_param; |
537 | extern unsigned int uvc_timeout_param; | ||
542 | 538 | ||
543 | #define uvc_trace(flag, msg...) \ | 539 | #define uvc_trace(flag, msg...) \ |
544 | do { \ | 540 | do { \ |
@@ -571,7 +567,6 @@ extern unsigned int uvc_trace_param; | |||
571 | 567 | ||
572 | /* Core driver */ | 568 | /* Core driver */ |
573 | extern struct uvc_driver uvc_driver; | 569 | extern struct uvc_driver uvc_driver; |
574 | extern void uvc_delete(struct kref *kref); | ||
575 | 570 | ||
576 | /* Video buffers queue management. */ | 571 | /* Video buffers queue management. */ |
577 | extern void uvc_queue_init(struct uvc_video_queue *queue, | 572 | extern void uvc_queue_init(struct uvc_video_queue *queue, |
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index f5a93ae3cdf9..e8e5affbabce 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c | |||
@@ -431,6 +431,8 @@ const char *v4l2_ctrl_get_name(u32 id) | |||
431 | case V4L2_CID_CHROMA_AGC: return "Chroma AGC"; | 431 | case V4L2_CID_CHROMA_AGC: return "Chroma AGC"; |
432 | case V4L2_CID_COLOR_KILLER: return "Color Killer"; | 432 | case V4L2_CID_COLOR_KILLER: return "Color Killer"; |
433 | case V4L2_CID_COLORFX: return "Color Effects"; | 433 | case V4L2_CID_COLORFX: return "Color Effects"; |
434 | case V4L2_CID_ROTATE: return "Rotate"; | ||
435 | case V4L2_CID_BG_COLOR: return "Background color"; | ||
434 | 436 | ||
435 | /* MPEG controls */ | 437 | /* MPEG controls */ |
436 | case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls"; | 438 | case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls"; |
@@ -587,6 +589,13 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste | |||
587 | qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; | 589 | qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
588 | min = max = step = def = 0; | 590 | min = max = step = def = 0; |
589 | break; | 591 | break; |
592 | case V4L2_CID_BG_COLOR: | ||
593 | qctrl->type = V4L2_CTRL_TYPE_INTEGER; | ||
594 | step = 1; | ||
595 | min = 0; | ||
596 | /* Max is calculated as RGB888 that is 2^24 */ | ||
597 | max = 0xFFFFFF; | ||
598 | break; | ||
590 | default: | 599 | default: |
591 | qctrl->type = V4L2_CTRL_TYPE_INTEGER; | 600 | qctrl->type = V4L2_CTRL_TYPE_INTEGER; |
592 | break; | 601 | break; |
diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 8e93c6f25c83..bb0a1c8de414 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c | |||
@@ -110,7 +110,7 @@ EXPORT_SYMBOL_GPL(videobuf_queue_to_vmalloc); | |||
110 | 110 | ||
111 | 111 | ||
112 | void videobuf_queue_core_init(struct videobuf_queue *q, | 112 | void videobuf_queue_core_init(struct videobuf_queue *q, |
113 | struct videobuf_queue_ops *ops, | 113 | const struct videobuf_queue_ops *ops, |
114 | struct device *dev, | 114 | struct device *dev, |
115 | spinlock_t *irqlock, | 115 | spinlock_t *irqlock, |
116 | enum v4l2_buf_type type, | 116 | enum v4l2_buf_type type, |
@@ -360,7 +360,7 @@ int __videobuf_mmap_setup(struct videobuf_queue *q, | |||
360 | q->bufs[i]->bsize = bsize; | 360 | q->bufs[i]->bsize = bsize; |
361 | switch (memory) { | 361 | switch (memory) { |
362 | case V4L2_MEMORY_MMAP: | 362 | case V4L2_MEMORY_MMAP: |
363 | q->bufs[i]->boff = bsize * i; | 363 | q->bufs[i]->boff = PAGE_ALIGN(bsize) * i; |
364 | break; | 364 | break; |
365 | case V4L2_MEMORY_USERPTR: | 365 | case V4L2_MEMORY_USERPTR: |
366 | case V4L2_MEMORY_OVERLAY: | 366 | case V4L2_MEMORY_OVERLAY: |
@@ -430,9 +430,9 @@ int videobuf_reqbufs(struct videobuf_queue *q, | |||
430 | count = VIDEO_MAX_FRAME; | 430 | count = VIDEO_MAX_FRAME; |
431 | size = 0; | 431 | size = 0; |
432 | q->ops->buf_setup(q, &count, &size); | 432 | q->ops->buf_setup(q, &count, &size); |
433 | size = PAGE_ALIGN(size); | 433 | dprintk(1, "reqbufs: bufs=%d, size=0x%x [%u pages total]\n", |
434 | dprintk(1, "reqbufs: bufs=%d, size=0x%x [%d pages total]\n", | 434 | count, size, |
435 | count, size, (count*size)>>PAGE_SHIFT); | 435 | (unsigned int)((count*PAGE_ALIGN(size))>>PAGE_SHIFT) ); |
436 | 436 | ||
437 | retval = __videobuf_mmap_setup(q, count, size, req->memory); | 437 | retval = __videobuf_mmap_setup(q, count, size, req->memory); |
438 | if (retval < 0) { | 438 | if (retval < 0) { |
@@ -1099,7 +1099,7 @@ int videobuf_cgmbuf(struct videobuf_queue *q, | |||
1099 | mbuf->size = 0; | 1099 | mbuf->size = 0; |
1100 | for (i = 0; i < mbuf->frames; i++) { | 1100 | for (i = 0; i < mbuf->frames; i++) { |
1101 | mbuf->offsets[i] = q->bufs[i]->boff; | 1101 | mbuf->offsets[i] = q->bufs[i]->boff; |
1102 | mbuf->size += q->bufs[i]->bsize; | 1102 | mbuf->size += PAGE_ALIGN(q->bufs[i]->bsize); |
1103 | } | 1103 | } |
1104 | 1104 | ||
1105 | return 0; | 1105 | return 0; |
diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c index c3065c4bcba9..d25f28461da1 100644 --- a/drivers/media/video/videobuf-dma-contig.c +++ b/drivers/media/video/videobuf-dma-contig.c | |||
@@ -429,7 +429,7 @@ static struct videobuf_qtype_ops qops = { | |||
429 | }; | 429 | }; |
430 | 430 | ||
431 | void videobuf_queue_dma_contig_init(struct videobuf_queue *q, | 431 | void videobuf_queue_dma_contig_init(struct videobuf_queue *q, |
432 | struct videobuf_queue_ops *ops, | 432 | const struct videobuf_queue_ops *ops, |
433 | struct device *dev, | 433 | struct device *dev, |
434 | spinlock_t *irqlock, | 434 | spinlock_t *irqlock, |
435 | enum v4l2_buf_type type, | 435 | enum v4l2_buf_type type, |
diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 032ebae0134a..fa78555b118b 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c | |||
@@ -588,7 +588,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, | |||
588 | retval = -EBUSY; | 588 | retval = -EBUSY; |
589 | goto done; | 589 | goto done; |
590 | } | 590 | } |
591 | size += q->bufs[last]->bsize; | 591 | size += PAGE_ALIGN(q->bufs[last]->bsize); |
592 | if (size == (vma->vm_end - vma->vm_start)) | 592 | if (size == (vma->vm_end - vma->vm_start)) |
593 | break; | 593 | break; |
594 | } | 594 | } |
@@ -610,7 +610,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, | |||
610 | continue; | 610 | continue; |
611 | q->bufs[i]->map = map; | 611 | q->bufs[i]->map = map; |
612 | q->bufs[i]->baddr = vma->vm_start + size; | 612 | q->bufs[i]->baddr = vma->vm_start + size; |
613 | size += q->bufs[i]->bsize; | 613 | size += PAGE_ALIGN(q->bufs[i]->bsize); |
614 | } | 614 | } |
615 | 615 | ||
616 | map->count = 1; | 616 | map->count = 1; |
@@ -702,7 +702,7 @@ void *videobuf_sg_alloc(size_t size) | |||
702 | } | 702 | } |
703 | 703 | ||
704 | void videobuf_queue_sg_init(struct videobuf_queue* q, | 704 | void videobuf_queue_sg_init(struct videobuf_queue* q, |
705 | struct videobuf_queue_ops *ops, | 705 | const struct videobuf_queue_ops *ops, |
706 | struct device *dev, | 706 | struct device *dev, |
707 | spinlock_t *irqlock, | 707 | spinlock_t *irqlock, |
708 | enum v4l2_buf_type type, | 708 | enum v4l2_buf_type type, |
diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c index 0e7dcba8e4ae..a56cf0d3a6d6 100644 --- a/drivers/media/video/videobuf-dvb.c +++ b/drivers/media/video/videobuf-dvb.c | |||
@@ -139,7 +139,9 @@ static int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *fe, | |||
139 | struct device *device, | 139 | struct device *device, |
140 | char *adapter_name, | 140 | char *adapter_name, |
141 | short *adapter_nr, | 141 | short *adapter_nr, |
142 | int mfe_shared) | 142 | int mfe_shared, |
143 | int (*fe_ioctl_override)(struct dvb_frontend *, | ||
144 | unsigned int, void *, unsigned int)) | ||
143 | { | 145 | { |
144 | int result; | 146 | int result; |
145 | 147 | ||
@@ -154,6 +156,7 @@ static int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *fe, | |||
154 | } | 156 | } |
155 | fe->adapter.priv = adapter_priv; | 157 | fe->adapter.priv = adapter_priv; |
156 | fe->adapter.mfe_shared = mfe_shared; | 158 | fe->adapter.mfe_shared = mfe_shared; |
159 | fe->adapter.fe_ioctl_override = fe_ioctl_override; | ||
157 | 160 | ||
158 | return result; | 161 | return result; |
159 | } | 162 | } |
@@ -253,7 +256,9 @@ int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f, | |||
253 | void *adapter_priv, | 256 | void *adapter_priv, |
254 | struct device *device, | 257 | struct device *device, |
255 | short *adapter_nr, | 258 | short *adapter_nr, |
256 | int mfe_shared) | 259 | int mfe_shared, |
260 | int (*fe_ioctl_override)(struct dvb_frontend *, | ||
261 | unsigned int, void *, unsigned int)) | ||
257 | { | 262 | { |
258 | struct list_head *list, *q; | 263 | struct list_head *list, *q; |
259 | struct videobuf_dvb_frontend *fe; | 264 | struct videobuf_dvb_frontend *fe; |
@@ -267,7 +272,7 @@ int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f, | |||
267 | 272 | ||
268 | /* Bring up the adapter */ | 273 | /* Bring up the adapter */ |
269 | res = videobuf_dvb_register_adapter(f, module, adapter_priv, device, | 274 | res = videobuf_dvb_register_adapter(f, module, adapter_priv, device, |
270 | fe->dvb.name, adapter_nr, mfe_shared); | 275 | fe->dvb.name, adapter_nr, mfe_shared, fe_ioctl_override); |
271 | if (res < 0) { | 276 | if (res < 0) { |
272 | printk(KERN_WARNING "videobuf_dvb_register_adapter failed (errno = %d)\n", res); | 277 | printk(KERN_WARNING "videobuf_dvb_register_adapter failed (errno = %d)\n", res); |
273 | return res; | 278 | return res; |
diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index 35f3900c5633..d6e6a28fb6b8 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c | |||
@@ -391,8 +391,8 @@ static struct videobuf_qtype_ops qops = { | |||
391 | }; | 391 | }; |
392 | 392 | ||
393 | void videobuf_queue_vmalloc_init(struct videobuf_queue* q, | 393 | void videobuf_queue_vmalloc_init(struct videobuf_queue* q, |
394 | struct videobuf_queue_ops *ops, | 394 | const struct videobuf_queue_ops *ops, |
395 | void *dev, | 395 | struct device *dev, |
396 | spinlock_t *irqlock, | 396 | spinlock_t *irqlock, |
397 | enum v4l2_buf_type type, | 397 | enum v4l2_buf_type type, |
398 | enum v4l2_field field, | 398 | enum v4l2_field field, |
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index 97e0ce28ff18..33205d7537d8 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c | |||
@@ -391,7 +391,7 @@ static int vpx3220_s_routing(struct v4l2_subdev *sd, | |||
391 | {0x0e, 1} | 391 | {0x0e, 1} |
392 | }; | 392 | }; |
393 | 393 | ||
394 | if (input < 0 || input > 2) | 394 | if (input > 2) |
395 | return -EINVAL; | 395 | return -EINVAL; |
396 | 396 | ||
397 | v4l2_dbg(1, debug, sd, "input switched to %s\n", inputs[input]); | 397 | v4l2_dbg(1, debug, sd, "input switched to %s\n", inputs[input]); |
diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 47137deafcfd..e9f72ca458f1 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c | |||
@@ -2764,7 +2764,7 @@ static int zoran_enum_input(struct file *file, void *__fh, | |||
2764 | struct zoran_fh *fh = __fh; | 2764 | struct zoran_fh *fh = __fh; |
2765 | struct zoran *zr = fh->zr; | 2765 | struct zoran *zr = fh->zr; |
2766 | 2766 | ||
2767 | if (inp->index < 0 || inp->index >= zr->card.inputs) | 2767 | if (inp->index >= zr->card.inputs) |
2768 | return -EINVAL; | 2768 | return -EINVAL; |
2769 | else { | 2769 | else { |
2770 | int id = inp->index; | 2770 | int id = inp->index; |
diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index 9aae011d92ab..2ef110b5221b 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c | |||
@@ -115,6 +115,7 @@ static struct usb_device_id device_table[] = { | |||
115 | {USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 }, | 115 | {USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 }, |
116 | {USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 }, | 116 | {USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 }, |
117 | {USB_DEVICE(0x08ca, 0x2102), .driver_info = METHOD2 }, | 117 | {USB_DEVICE(0x08ca, 0x2102), .driver_info = METHOD2 }, |
118 | {USB_DEVICE(0x06d6, 0x003d), .driver_info = METHOD0 }, | ||
118 | {} /* Terminating entry */ | 119 | {} /* Terminating entry */ |
119 | }; | 120 | }; |
120 | 121 | ||