Commit | Line | Data |
---|---|---|
a511ba94 HG |
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 | ||
79b35902 | 34 | #define W9968CF_I2C_BUS_DELAY 4 /* delay in us for I2C bit r/w operations */ |
a511ba94 | 35 | |
9a731a32 JFM |
36 | #define Y_QUANTABLE (&sd->jpeg_hdr[JPEG_QT0_OFFSET]) |
37 | #define UV_QUANTABLE (&sd->jpeg_hdr[JPEG_QT1_OFFSET]) | |
a511ba94 HG |
38 | |
39 | static const struct v4l2_pix_format w9968cf_vga_mode[] = { | |
40 | {160, 120, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, | |
41 | .bytesperline = 160 * 2, | |
42 | .sizeimage = 160 * 120 * 2, | |
43 | .colorspace = V4L2_COLORSPACE_JPEG}, | |
44 | {176, 144, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, | |
45 | .bytesperline = 176 * 2, | |
46 | .sizeimage = 176 * 144 * 2, | |
47 | .colorspace = V4L2_COLORSPACE_JPEG}, | |
79b35902 | 48 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
a511ba94 HG |
49 | .bytesperline = 320 * 2, |
50 | .sizeimage = 320 * 240 * 2, | |
51 | .colorspace = V4L2_COLORSPACE_JPEG}, | |
79b35902 | 52 | {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
a511ba94 HG |
53 | .bytesperline = 352 * 2, |
54 | .sizeimage = 352 * 288 * 2, | |
55 | .colorspace = V4L2_COLORSPACE_JPEG}, | |
79b35902 | 56 | {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
a511ba94 HG |
57 | .bytesperline = 640 * 2, |
58 | .sizeimage = 640 * 480 * 2, | |
79b35902 | 59 | .colorspace = V4L2_COLORSPACE_JPEG}, |
a511ba94 HG |
60 | }; |
61 | ||
f8f20188 | 62 | static void reg_w(struct sd *sd, u16 index, u16 value); |
a511ba94 HG |
63 | |
64 | /*-------------------------------------------------------------------------- | |
65 | Write 64-bit data to the fast serial bus registers. | |
66 | Return 0 on success, -1 otherwise. | |
67 | --------------------------------------------------------------------------*/ | |
f8f20188 | 68 | static void w9968cf_write_fsb(struct sd *sd, u16* data) |
a511ba94 | 69 | { |
780e3121 | 70 | struct usb_device *udev = sd->gspca_dev.dev; |
a511ba94 HG |
71 | u16 value; |
72 | int ret; | |
73 | ||
f8f20188 JFM |
74 | if (sd->gspca_dev.usb_err < 0) |
75 | return; | |
76 | ||
a511ba94 HG |
77 | value = *data++; |
78 | memcpy(sd->gspca_dev.usb_buf, data, 6); | |
79 | ||
80 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, | |
81 | USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, | |
82 | value, 0x06, sd->gspca_dev.usb_buf, 6, 500); | |
83 | if (ret < 0) { | |
0b656321 | 84 | err("Write FSB registers failed (%d)", ret); |
f8f20188 | 85 | sd->gspca_dev.usb_err = ret; |
a511ba94 | 86 | } |
a511ba94 HG |
87 | } |
88 | ||
89 | /*-------------------------------------------------------------------------- | |
90 | Write data to the serial bus control register. | |
91 | Return 0 on success, a negative number otherwise. | |
92 | --------------------------------------------------------------------------*/ | |
f8f20188 | 93 | static void w9968cf_write_sb(struct sd *sd, u16 value) |
a511ba94 HG |
94 | { |
95 | int ret; | |
96 | ||
f8f20188 JFM |
97 | if (sd->gspca_dev.usb_err < 0) |
98 | return; | |
99 | ||
a511ba94 HG |
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) { | |
0b656321 | 111 | err("Write SB reg [01] %04x failed", value); |
f8f20188 | 112 | sd->gspca_dev.usb_err = ret; |
a511ba94 | 113 | } |
a511ba94 HG |
114 | } |
115 | ||
116 | /*-------------------------------------------------------------------------- | |
117 | Read data from the serial bus control register. | |
118 | Return 0 on success, a negative number otherwise. | |
119 | --------------------------------------------------------------------------*/ | |
120 | static int w9968cf_read_sb(struct sd *sd) | |
121 | { | |
122 | int ret; | |
123 | ||
f8f20188 JFM |
124 | if (sd->gspca_dev.usb_err < 0) |
125 | return -1; | |
126 | ||
a511ba94 HG |
127 | /* We don't use reg_r here, as the w9968cf is special and has 16 |
128 | bit registers instead of 8 bit */ | |
129 | ret = usb_control_msg(sd->gspca_dev.dev, | |
130 | usb_rcvctrlpipe(sd->gspca_dev.dev, 0), | |
131 | 1, | |
132 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | |
133 | 0, 0x01, sd->gspca_dev.usb_buf, 2, 500); | |
f8f20188 | 134 | if (ret >= 0) { |
a511ba94 HG |
135 | ret = sd->gspca_dev.usb_buf[0] | |
136 | (sd->gspca_dev.usb_buf[1] << 8); | |
f8f20188 | 137 | } else { |
0b656321 | 138 | err("Read SB reg [01] failed"); |
f8f20188 JFM |
139 | sd->gspca_dev.usb_err = ret; |
140 | } | |
a511ba94 HG |
141 | |
142 | udelay(W9968CF_I2C_BUS_DELAY); | |
143 | ||
144 | return ret; | |
145 | } | |
146 | ||
147 | /*-------------------------------------------------------------------------- | |
148 | Upload quantization tables for the JPEG compression. | |
149 | This function is called by w9968cf_start_transfer(). | |
150 | Return 0 on success, a negative number otherwise. | |
151 | --------------------------------------------------------------------------*/ | |
f8f20188 | 152 | static void w9968cf_upload_quantizationtables(struct sd *sd) |
a511ba94 HG |
153 | { |
154 | u16 a, b; | |
f8f20188 | 155 | int i, j; |
a511ba94 | 156 | |
f8f20188 | 157 | reg_w(sd, 0x39, 0x0010); /* JPEG clock enable */ |
a511ba94 HG |
158 | |
159 | for (i = 0, j = 0; i < 32; i++, j += 2) { | |
87bae740 JFM |
160 | a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j + 1]) << 8); |
161 | b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j + 1]) << 8); | |
162 | reg_w(sd, 0x40 + i, a); | |
163 | reg_w(sd, 0x60 + i, b); | |
a511ba94 | 164 | } |
f8f20188 | 165 | reg_w(sd, 0x39, 0x0012); /* JPEG encoder enable */ |
a511ba94 HG |
166 | } |
167 | ||
168 | /**************************************************************************** | |
169 | * Low-level I2C I/O functions. * | |
170 | * The adapter supports the following I2C transfer functions: * | |
171 | * i2c_adap_fastwrite_byte_data() (at 400 kHz bit frequency only) * | |
172 | * i2c_adap_read_byte_data() * | |
173 | * i2c_adap_read_byte() * | |
174 | ****************************************************************************/ | |
175 | ||
f8f20188 | 176 | static void w9968cf_smbus_start(struct sd *sd) |
a511ba94 | 177 | { |
f8f20188 JFM |
178 | w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ |
179 | w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ | |
a511ba94 HG |
180 | } |
181 | ||
f8f20188 | 182 | static void w9968cf_smbus_stop(struct sd *sd) |
a511ba94 | 183 | { |
f8f20188 JFM |
184 | w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ |
185 | w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ | |
186 | w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ | |
a511ba94 HG |
187 | } |
188 | ||
f8f20188 | 189 | static void w9968cf_smbus_write_byte(struct sd *sd, u8 v) |
a511ba94 HG |
190 | { |
191 | u8 bit; | |
f8f20188 | 192 | int sda; |
a511ba94 HG |
193 | |
194 | for (bit = 0 ; bit < 8 ; bit++) { | |
195 | sda = (v & 0x80) ? 2 : 0; | |
196 | v <<= 1; | |
197 | /* SDE=1, SDA=sda, SCL=0 */ | |
f8f20188 | 198 | w9968cf_write_sb(sd, 0x10 | sda); |
a511ba94 | 199 | /* SDE=1, SDA=sda, SCL=1 */ |
f8f20188 | 200 | w9968cf_write_sb(sd, 0x11 | sda); |
a511ba94 | 201 | /* SDE=1, SDA=sda, SCL=0 */ |
f8f20188 | 202 | w9968cf_write_sb(sd, 0x10 | sda); |
a511ba94 | 203 | } |
a511ba94 HG |
204 | } |
205 | ||
f8f20188 | 206 | static void w9968cf_smbus_read_byte(struct sd *sd, u8 *v) |
a511ba94 HG |
207 | { |
208 | u8 bit; | |
a511ba94 HG |
209 | |
210 | /* No need to ensure SDA is high as we are always called after | |
211 | read_ack which ends with SDA high */ | |
212 | *v = 0; | |
213 | for (bit = 0 ; bit < 8 ; bit++) { | |
214 | *v <<= 1; | |
215 | /* SDE=1, SDA=1, SCL=1 */ | |
f8f20188 | 216 | w9968cf_write_sb(sd, 0x0013); |
a511ba94 HG |
217 | *v |= (w9968cf_read_sb(sd) & 0x0008) ? 1 : 0; |
218 | /* SDE=1, SDA=1, SCL=0 */ | |
f8f20188 | 219 | w9968cf_write_sb(sd, 0x0012); |
a511ba94 | 220 | } |
a511ba94 HG |
221 | } |
222 | ||
f8f20188 | 223 | static void w9968cf_smbus_write_nack(struct sd *sd) |
a511ba94 | 224 | { |
a511ba94 HG |
225 | /* No need to ensure SDA is high as we are always called after |
226 | read_byte which ends with SDA high */ | |
f8f20188 JFM |
227 | w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ |
228 | w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ | |
a511ba94 HG |
229 | } |
230 | ||
f8f20188 | 231 | static void w9968cf_smbus_read_ack(struct sd *sd) |
a511ba94 | 232 | { |
f8f20188 | 233 | int sda; |
a511ba94 HG |
234 | |
235 | /* Ensure SDA is high before raising clock to avoid a spurious stop */ | |
f8f20188 JFM |
236 | w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ |
237 | w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ | |
a511ba94 | 238 | sda = w9968cf_read_sb(sd); |
f8f20188 JFM |
239 | w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ |
240 | if (sda >= 0 && (sda & 0x08)) { | |
a511ba94 | 241 | PDEBUG(D_USBI, "Did not receive i2c ACK"); |
f8f20188 | 242 | sd->gspca_dev.usb_err = -EIO; |
a511ba94 | 243 | } |
a511ba94 HG |
244 | } |
245 | ||
246 | /* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */ | |
f8f20188 | 247 | static void w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) |
a511ba94 HG |
248 | { |
249 | u16* data = (u16 *)sd->gspca_dev.usb_buf; | |
a511ba94 HG |
250 | |
251 | data[0] = 0x082f | ((sd->sensor_addr & 0x80) ? 0x1500 : 0x0); | |
252 | data[0] |= (sd->sensor_addr & 0x40) ? 0x4000 : 0x0; | |
253 | data[1] = 0x2082 | ((sd->sensor_addr & 0x40) ? 0x0005 : 0x0); | |
254 | data[1] |= (sd->sensor_addr & 0x20) ? 0x0150 : 0x0; | |
255 | data[1] |= (sd->sensor_addr & 0x10) ? 0x5400 : 0x0; | |
256 | data[2] = 0x8208 | ((sd->sensor_addr & 0x08) ? 0x0015 : 0x0); | |
257 | data[2] |= (sd->sensor_addr & 0x04) ? 0x0540 : 0x0; | |
258 | data[2] |= (sd->sensor_addr & 0x02) ? 0x5000 : 0x0; | |
259 | data[3] = 0x1d20 | ((sd->sensor_addr & 0x02) ? 0x0001 : 0x0); | |
260 | data[3] |= (sd->sensor_addr & 0x01) ? 0x0054 : 0x0; | |
261 | ||
f8f20188 | 262 | w9968cf_write_fsb(sd, data); |
a511ba94 HG |
263 | |
264 | data[0] = 0x8208 | ((reg & 0x80) ? 0x0015 : 0x0); | |
265 | data[0] |= (reg & 0x40) ? 0x0540 : 0x0; | |
266 | data[0] |= (reg & 0x20) ? 0x5000 : 0x0; | |
267 | data[1] = 0x0820 | ((reg & 0x20) ? 0x0001 : 0x0); | |
268 | data[1] |= (reg & 0x10) ? 0x0054 : 0x0; | |
269 | data[1] |= (reg & 0x08) ? 0x1500 : 0x0; | |
270 | data[1] |= (reg & 0x04) ? 0x4000 : 0x0; | |
271 | data[2] = 0x2082 | ((reg & 0x04) ? 0x0005 : 0x0); | |
272 | data[2] |= (reg & 0x02) ? 0x0150 : 0x0; | |
273 | data[2] |= (reg & 0x01) ? 0x5400 : 0x0; | |
274 | data[3] = 0x001d; | |
275 | ||
f8f20188 | 276 | w9968cf_write_fsb(sd, data); |
a511ba94 HG |
277 | |
278 | data[0] = 0x8208 | ((value & 0x80) ? 0x0015 : 0x0); | |
279 | data[0] |= (value & 0x40) ? 0x0540 : 0x0; | |
280 | data[0] |= (value & 0x20) ? 0x5000 : 0x0; | |
281 | data[1] = 0x0820 | ((value & 0x20) ? 0x0001 : 0x0); | |
282 | data[1] |= (value & 0x10) ? 0x0054 : 0x0; | |
283 | data[1] |= (value & 0x08) ? 0x1500 : 0x0; | |
284 | data[1] |= (value & 0x04) ? 0x4000 : 0x0; | |
285 | data[2] = 0x2082 | ((value & 0x04) ? 0x0005 : 0x0); | |
286 | data[2] |= (value & 0x02) ? 0x0150 : 0x0; | |
287 | data[2] |= (value & 0x01) ? 0x5400 : 0x0; | |
288 | data[3] = 0xfe1d; | |
289 | ||
f8f20188 | 290 | w9968cf_write_fsb(sd, data); |
a511ba94 | 291 | |
f8f20188 | 292 | PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); |
a511ba94 HG |
293 | } |
294 | ||
295 | /* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */ | |
296 | static int w9968cf_i2c_r(struct sd *sd, u8 reg) | |
297 | { | |
298 | int ret = 0; | |
299 | u8 value; | |
300 | ||
301 | /* Fast serial bus data control disable */ | |
f8f20188 JFM |
302 | w9968cf_write_sb(sd, 0x0013); /* don't change ! */ |
303 | ||
304 | w9968cf_smbus_start(sd); | |
305 | w9968cf_smbus_write_byte(sd, sd->sensor_addr); | |
306 | w9968cf_smbus_read_ack(sd); | |
307 | w9968cf_smbus_write_byte(sd, reg); | |
308 | w9968cf_smbus_read_ack(sd); | |
309 | w9968cf_smbus_stop(sd); | |
310 | w9968cf_smbus_start(sd); | |
311 | w9968cf_smbus_write_byte(sd, sd->sensor_addr + 1); | |
312 | w9968cf_smbus_read_ack(sd); | |
313 | w9968cf_smbus_read_byte(sd, &value); | |
a511ba94 HG |
314 | /* signal we don't want to read anymore, the v4l1 driver used to |
315 | send an ack here which is very wrong! (and then fixed | |
316 | the issues this gave by retrying reads) */ | |
f8f20188 JFM |
317 | w9968cf_smbus_write_nack(sd); |
318 | w9968cf_smbus_stop(sd); | |
a511ba94 HG |
319 | |
320 | /* Fast serial bus data control re-enable */ | |
f8f20188 | 321 | w9968cf_write_sb(sd, 0x0030); |
a511ba94 | 322 | |
f8f20188 | 323 | if (sd->gspca_dev.usb_err >= 0) { |
a511ba94 HG |
324 | ret = value; |
325 | PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); | |
326 | } else | |
327 | PDEBUG(D_ERR, "i2c read [0x%02x] failed", reg); | |
328 | ||
329 | return ret; | |
330 | } | |
331 | ||
a511ba94 HG |
332 | /*-------------------------------------------------------------------------- |
333 | Turn on the LED on some webcams. A beep should be heard too. | |
334 | Return 0 on success, a negative number otherwise. | |
335 | --------------------------------------------------------------------------*/ | |
f8f20188 | 336 | static void w9968cf_configure(struct sd *sd) |
a511ba94 | 337 | { |
f8f20188 JFM |
338 | reg_w(sd, 0x00, 0xff00); /* power-down */ |
339 | reg_w(sd, 0x00, 0xbf17); /* reset everything */ | |
340 | reg_w(sd, 0x00, 0xbf10); /* normal operation */ | |
341 | reg_w(sd, 0x01, 0x0010); /* serial bus, SDS high */ | |
342 | reg_w(sd, 0x01, 0x0000); /* serial bus, SDS low */ | |
343 | reg_w(sd, 0x01, 0x0010); /* ..high 'beep-beep' */ | |
344 | reg_w(sd, 0x01, 0x0030); /* Set sda scl to FSB mode */ | |
a511ba94 HG |
345 | |
346 | sd->stopped = 1; | |
a511ba94 HG |
347 | } |
348 | ||
f8f20188 | 349 | static void w9968cf_init(struct sd *sd) |
a511ba94 | 350 | { |
a511ba94 HG |
351 | unsigned long hw_bufsize = sd->sif ? (352 * 288 * 2) : (640 * 480 * 2), |
352 | y0 = 0x0000, | |
87bae740 JFM |
353 | u0 = y0 + hw_bufsize / 2, |
354 | v0 = u0 + hw_bufsize / 4, | |
355 | y1 = v0 + hw_bufsize / 4, | |
356 | u1 = y1 + hw_bufsize / 2, | |
357 | v1 = u1 + hw_bufsize / 4; | |
a511ba94 | 358 | |
f8f20188 JFM |
359 | reg_w(sd, 0x00, 0xff00); /* power off */ |
360 | reg_w(sd, 0x00, 0xbf10); /* power on */ | |
a511ba94 | 361 | |
f8f20188 JFM |
362 | reg_w(sd, 0x03, 0x405d); /* DRAM timings */ |
363 | reg_w(sd, 0x04, 0x0030); /* SDRAM timings */ | |
a511ba94 | 364 | |
f8f20188 JFM |
365 | reg_w(sd, 0x20, y0 & 0xffff); /* Y buf.0, low */ |
366 | reg_w(sd, 0x21, y0 >> 16); /* Y buf.0, high */ | |
367 | reg_w(sd, 0x24, u0 & 0xffff); /* U buf.0, low */ | |
368 | reg_w(sd, 0x25, u0 >> 16); /* U buf.0, high */ | |
369 | reg_w(sd, 0x28, v0 & 0xffff); /* V buf.0, low */ | |
370 | reg_w(sd, 0x29, v0 >> 16); /* V buf.0, high */ | |
a511ba94 | 371 | |
f8f20188 JFM |
372 | reg_w(sd, 0x22, y1 & 0xffff); /* Y buf.1, low */ |
373 | reg_w(sd, 0x23, y1 >> 16); /* Y buf.1, high */ | |
374 | reg_w(sd, 0x26, u1 & 0xffff); /* U buf.1, low */ | |
375 | reg_w(sd, 0x27, u1 >> 16); /* U buf.1, high */ | |
376 | reg_w(sd, 0x2a, v1 & 0xffff); /* V buf.1, low */ | |
377 | reg_w(sd, 0x2b, v1 >> 16); /* V buf.1, high */ | |
a511ba94 | 378 | |
f8f20188 JFM |
379 | reg_w(sd, 0x32, y1 & 0xffff); /* JPEG buf 0 low */ |
380 | reg_w(sd, 0x33, y1 >> 16); /* JPEG buf 0 high */ | |
a511ba94 | 381 | |
f8f20188 JFM |
382 | reg_w(sd, 0x34, y1 & 0xffff); /* JPEG buf 1 low */ |
383 | reg_w(sd, 0x35, y1 >> 16); /* JPEG bug 1 high */ | |
a511ba94 | 384 | |
f8f20188 JFM |
385 | reg_w(sd, 0x36, 0x0000);/* JPEG restart interval */ |
386 | reg_w(sd, 0x37, 0x0804);/*JPEG VLE FIFO threshold*/ | |
387 | reg_w(sd, 0x38, 0x0000);/* disable hw up-scaling */ | |
388 | reg_w(sd, 0x3f, 0x0000); /* JPEG/MCTL test data */ | |
a511ba94 HG |
389 | } |
390 | ||
f8f20188 | 391 | static void w9968cf_set_crop_window(struct sd *sd) |
a511ba94 | 392 | { |
f8f20188 | 393 | int start_cropx, start_cropy, x, y, fw, fh, cw, ch, |
a511ba94 HG |
394 | max_width, max_height; |
395 | ||
396 | if (sd->sif) { | |
397 | max_width = 352; | |
398 | max_height = 288; | |
399 | } else { | |
400 | max_width = 640; | |
401 | max_height = 480; | |
402 | } | |
403 | ||
404 | if (sd->sensor == SEN_OV7620) { | |
405 | /* Sigh, this is dependend on the clock / framerate changes | |
406 | made by the frequency control, sick. */ | |
62833acd | 407 | if (sd->ctrls[FREQ].val == 1) { |
73997870 HG |
408 | start_cropx = 277; |
409 | start_cropy = 37; | |
a511ba94 | 410 | } else { |
73997870 HG |
411 | start_cropx = 105; |
412 | start_cropy = 37; | |
a511ba94 HG |
413 | } |
414 | } else { | |
415 | start_cropx = 320; | |
416 | start_cropy = 35; | |
417 | } | |
418 | ||
419 | /* Work around to avoid FP arithmetics */ | |
420 | #define SC(x) ((x) << 10) | |
421 | ||
422 | /* Scaling factors */ | |
423 | fw = SC(sd->gspca_dev.width) / max_width; | |
424 | fh = SC(sd->gspca_dev.height) / max_height; | |
425 | ||
87bae740 JFM |
426 | cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.width) / fh; |
427 | ch = (fw >= fh) ? SC(sd->gspca_dev.height) / fw : max_height; | |
a511ba94 HG |
428 | |
429 | sd->sensor_width = max_width; | |
430 | sd->sensor_height = max_height; | |
431 | ||
432 | x = (max_width - cw) / 2; | |
433 | y = (max_height - ch) / 2; | |
434 | ||
f8f20188 JFM |
435 | reg_w(sd, 0x10, start_cropx + x); |
436 | reg_w(sd, 0x11, start_cropy + y); | |
437 | reg_w(sd, 0x12, start_cropx + x + cw); | |
438 | reg_w(sd, 0x13, start_cropy + y + ch); | |
a511ba94 HG |
439 | } |
440 | ||
f8f20188 | 441 | static void w9968cf_mode_init_regs(struct sd *sd) |
a511ba94 | 442 | { |
f8f20188 | 443 | int val, vs_polarity, hs_polarity; |
a511ba94 | 444 | |
f8f20188 | 445 | w9968cf_set_crop_window(sd); |
a511ba94 | 446 | |
f8f20188 JFM |
447 | reg_w(sd, 0x14, sd->gspca_dev.width); |
448 | reg_w(sd, 0x15, sd->gspca_dev.height); | |
a511ba94 HG |
449 | |
450 | /* JPEG width & height */ | |
f8f20188 JFM |
451 | reg_w(sd, 0x30, sd->gspca_dev.width); |
452 | reg_w(sd, 0x31, sd->gspca_dev.height); | |
a511ba94 HG |
453 | |
454 | /* Y & UV frame buffer strides (in WORD) */ | |
79b35902 HG |
455 | if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == |
456 | V4L2_PIX_FMT_JPEG) { | |
f8f20188 JFM |
457 | reg_w(sd, 0x2c, sd->gspca_dev.width / 2); |
458 | reg_w(sd, 0x2d, sd->gspca_dev.width / 4); | |
79b35902 | 459 | } else |
f8f20188 | 460 | reg_w(sd, 0x2c, sd->gspca_dev.width); |
a511ba94 | 461 | |
f8f20188 JFM |
462 | reg_w(sd, 0x00, 0xbf17); /* reset everything */ |
463 | reg_w(sd, 0x00, 0xbf10); /* normal operation */ | |
a511ba94 | 464 | |
79b35902 | 465 | /* Transfer size in WORDS (for UYVY format only) */ |
a511ba94 | 466 | val = sd->gspca_dev.width * sd->gspca_dev.height; |
f8f20188 JFM |
467 | reg_w(sd, 0x3d, val & 0xffff); /* low bits */ |
468 | reg_w(sd, 0x3e, val >> 16); /* high bits */ | |
a511ba94 | 469 | |
79b35902 HG |
470 | if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == |
471 | V4L2_PIX_FMT_JPEG) { | |
472 | /* We may get called multiple times (usb isoc bw negotiat.) */ | |
79b35902 HG |
473 | jpeg_define(sd->jpeg_hdr, sd->gspca_dev.height, |
474 | sd->gspca_dev.width, 0x22); /* JPEG 420 */ | |
475 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | |
f8f20188 | 476 | w9968cf_upload_quantizationtables(sd); |
79b35902 HG |
477 | } |
478 | ||
a511ba94 HG |
479 | /* Video Capture Control Register */ |
480 | if (sd->sensor == SEN_OV7620) { | |
481 | /* Seems to work around a bug in the image sensor */ | |
482 | vs_polarity = 1; | |
483 | hs_polarity = 1; | |
484 | } else { | |
485 | vs_polarity = 1; | |
486 | hs_polarity = 0; | |
487 | } | |
488 | ||
489 | val = (vs_polarity << 12) | (hs_polarity << 11); | |
490 | ||
79b35902 HG |
491 | /* NOTE: We may not have enough memory to do double buffering while |
492 | doing compression (amount of memory differs per model cam). | |
493 | So we use the second image buffer also as jpeg stream buffer | |
494 | (see w9968cf_init), and disable double buffering. */ | |
495 | if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == | |
496 | V4L2_PIX_FMT_JPEG) { | |
497 | /* val |= 0x0002; YUV422P */ | |
498 | val |= 0x0003; /* YUV420P */ | |
499 | } else | |
a511ba94 HG |
500 | val |= 0x0080; /* Enable HW double buffering */ |
501 | ||
502 | /* val |= 0x0020; enable clamping */ | |
503 | /* val |= 0x0008; enable (1-2-1) filter */ | |
504 | /* val |= 0x000c; enable (2-3-6-3-2) filter */ | |
505 | ||
506 | val |= 0x8000; /* capt. enable */ | |
507 | ||
f8f20188 | 508 | reg_w(sd, 0x16, val); |
a511ba94 HG |
509 | |
510 | sd->gspca_dev.empty_packet = 0; | |
a511ba94 HG |
511 | } |
512 | ||
79b35902 HG |
513 | static void w9968cf_stop0(struct sd *sd) |
514 | { | |
d65174c0 JFM |
515 | reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */ |
516 | reg_w(sd, 0x16, 0x0000); /* stop video capture */ | |
79b35902 HG |
517 | } |
518 | ||
519 | /* The w9968cf docs say that a 0 sized packet means EOF (and also SOF | |
520 | for the next frame). This seems to simply not be true when operating | |
521 | in JPEG mode, in this case there may be empty packets within the | |
522 | frame. So in JPEG mode use the JPEG SOI marker to detect SOF. | |
523 | ||
524 | Note to make things even more interesting the w9968cf sends *PLANAR* jpeg, | |
525 | to be precise it sends: SOI, SOF, DRI, SOS, Y-data, SOS, U-data, SOS, | |
526 | V-data, EOI. */ | |
a511ba94 | 527 | static void w9968cf_pkt_scan(struct gspca_dev *gspca_dev, |
76dd272b | 528 | u8 *data, /* isoc packet */ |
a511ba94 HG |
529 | int len) /* iso packet length */ |
530 | { | |
79b35902 HG |
531 | struct sd *sd = (struct sd *) gspca_dev; |
532 | ||
533 | if (w9968cf_vga_mode[gspca_dev->curr_mode].pixelformat == | |
534 | V4L2_PIX_FMT_JPEG) { | |
535 | if (len >= 2 && | |
536 | data[0] == 0xff && | |
537 | data[1] == 0xd8) { | |
76dd272b | 538 | gspca_frame_add(gspca_dev, LAST_PACKET, |
8394bcf3 | 539 | NULL, 0); |
76dd272b | 540 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
79b35902 HG |
541 | sd->jpeg_hdr, JPEG_HDR_SZ); |
542 | /* Strip the ff d8, our own header (which adds | |
543 | huffman and quantization tables) already has this */ | |
544 | len -= 2; | |
545 | data += 2; | |
546 | } | |
547 | } else { | |
548 | /* In UYVY mode an empty packet signals EOF */ | |
549 | if (gspca_dev->empty_packet) { | |
76dd272b | 550 | gspca_frame_add(gspca_dev, LAST_PACKET, |
79b35902 | 551 | NULL, 0); |
76dd272b | 552 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
79b35902 HG |
553 | NULL, 0); |
554 | gspca_dev->empty_packet = 0; | |
555 | } | |
a511ba94 | 556 | } |
76dd272b | 557 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
a511ba94 | 558 | } |