summaryrefslogtreecommitdiff
path: root/drivers/media/video/ov511.h
blob: c450c92468da58c4dbb5e403d605d125faaf6054 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
#ifndef __LINUX_OV511_H
#define __LINUX_OV511_H

#include <asm/uaccess.h>
#include <linux/videodev.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <linux/usb.h>
#include <linux/mutex.h>

#define OV511_DEBUG	/* Turn on debug messages */

#ifdef OV511_DEBUG
	#define PDEBUG(level, fmt, args...) \
		if (debug >= (level))	\
			printk(KERN_INFO KBUILD_MODNAME "[%s:%d] \n" fmt, \
		__func__, __LINE__ , ## args)
#else
	#define PDEBUG(level, fmt, args...) do {} while(0)
#endif

/* This macro restricts an int variable to an inclusive range */
#define RESTRICT_TO_RANGE(v,mi,ma) { \
	if ((v) < (mi)) (v) = (mi); \
	else if ((v) > (ma)) (v) = (ma); \
}

/* --------------------------------- */
/* DEFINES FOR OV511 AND OTHER CHIPS */
/* --------------------------------- */

/* USB IDs */
#define VEND_OMNIVISION	0x05A9
#define PROD_OV511	0x0511
#define PROD_OV511PLUS	0xA511
#define PROD_OV518	0x0518
#define PROD_OV518PLUS	0xA518

#define VEND_MATTEL	0x0813
#define PROD_ME2CAM	0x0002

/* --------------------------------- */
/*     OV51x REGISTER MNEMONICS      */
/* --------------------------------- */

/* Camera interface register numbers */
#define R511_CAM_DELAY		0x10
#define R511_CAM_EDGE		0x11
#define R511_CAM_PXCNT		0x12
#define R511_CAM_LNCNT		0x13
#define R511_CAM_PXDIV		0x14
#define R511_CAM_LNDIV		0x15
#define R511_CAM_UV_EN		0x16
#define R511_CAM_LINE_MODE	0x17
#define R511_CAM_OPTS		0x18

/* Snapshot mode camera interface register numbers */
#define R511_SNAP_FRAME		0x19
#define R511_SNAP_PXCNT		0x1A
#define R511_SNAP_LNCNT		0x1B
#define R511_SNAP_PXDIV		0x1C
#define R511_SNAP_LNDIV		0x1D
#define R511_SNAP_UV_EN		0x1E
#define R511_SNAP_OPTS		0x1F

/* DRAM register numbers */
#define R511_DRAM_FLOW_CTL	0x20
#define R511_DRAM_ARCP		0x21
#define R511_DRAM_MRC		0x22
#define R511_DRAM_RFC		0x23

/* ISO FIFO register numbers */
#define R51x_FIFO_PSIZE		0x30	/* 2 bytes wide w/ OV518(+) */
#define R511_FIFO_OPTS		0x31

/* Parallel IO register numbers */
#define R511_PIO_OPTS		0x38
#define R511_PIO_DATA		0x39
#define R511_PIO_BIST		0x3E
#define R518_GPIO_IN		0x55	/* OV518(+) only */
#define R518_GPIO_OUT		0x56	/* OV518(+) only */
#define R518_GPIO_CTL		0x57	/* OV518(+) only */
#define R518_GPIO_PULSE_IN	0x58	/* OV518(+) only */
#define R518_GPIO_PULSE_CLEAR	0x59	/* OV518(+) only */
#define R518_GPIO_PULSE_POL	0x5a	/* OV518(+) only */
#define R518_GPIO_PULSE_EN	0x5b	/* OV518(+) only */
#define R518_GPIO_RESET		0x5c	/* OV518(+) only */

/* I2C registers */
#define R511_I2C_CTL		0x40
#define R518_I2C_CTL		0x47	/* OV518(+) only */
#define R51x_I2C_W_SID		0x41
#define R51x_I2C_SADDR_3	0x42
#define R51x_I2C_SADDR_2	0x43
#define R51x_I2C_R_SID		0x44
#define R51x_I2C_DATA		0x45
#define R51x_I2C_CLOCK		0x46
#define R51x_I2C_TIMEOUT	0x47

/* I2C snapshot registers */
#define R511_SI2C_SADDR_3	0x48
#define R511_SI2C_DATA		0x49

/* System control registers */
#define R51x_SYS_RESET		0x50
		/* Reset type definitions */
#define 	OV511_RESET_UDC		0x01
#define 	OV511_RESET_I2C		0x02
#define 	OV511_RESET_FIFO	0x04
#define 	OV511_RESET_OMNICE	0x08
#define 	OV511_RESET_DRAM	0x10
#define 	OV511_RESET_CAM_INT	0x20
#define 	OV511_RESET_OV511	0x40
#define 	OV511_RESET_NOREGS	0x3F /* All but OV511 & regs */
#define 	OV511_RESET_ALL		0x7F

#define R511_SYS_CLOCK_DIV	0x51
#define R51x_SYS_SNAP		0x52
#define R51x_SYS_INIT         	0x53
#define R511_SYS_PWR_CLK	0x54 /* OV511+/OV518(+) only */
#define R511_SYS_LED_CTL	0x55 /* OV511+ only */
#define R511_SYS_USER		0x5E
#define R511_SYS_CUST_ID	0x5F

/* OmniCE (compression) registers */
#define R511_COMP_PHY		0x70
#define R511_COMP_PHUV		0x71
#define R511_COMP_PVY		0x72
#define R511_COMP_PVUV		0x73
#define R511_COMP_QHY		0x74
#define R511_COMP_QHUV		0x75
#define R511_COMP_QVY		0x76
#define R511_COMP_QVUV		0x77
#define R511_COMP_EN		0x78
#define R511_COMP_LUT_EN	0x79
#define R511_COMP_LUT_BEGIN	0x80

/* --------------------------------- */
/*         ALTERNATE NUMBERS         */
/* --------------------------------- */

/* Alternate numbers for various max packet sizes (OV511 only) */
#define OV511_ALT_SIZE_992	0
#define OV511_ALT_SIZE_993	1
#define OV511_ALT_SIZE_768	2
#define OV511_ALT_SIZE_769	3
#define OV511_ALT_SIZE_512	4
#define OV511_ALT_SIZE_513	5
#define OV511_ALT_SIZE_257	6
#define OV511_ALT_SIZE_0	7

/* Alternate numbers for various max packet sizes (OV511+ only) */
#define OV511PLUS_ALT_SIZE_0	0
#define OV511PLUS_ALT_SIZE_33	1
#define OV511PLUS_ALT_SIZE_129	2
#define OV511PLUS_ALT_SIZE_257	3
#define OV511PLUS_ALT_SIZE_385	4
#define OV511PLUS_ALT_SIZE_513	5
#define OV511PLUS_ALT_SIZE_769	6
#define OV511PLUS_ALT_SIZE_961	7

/* Alternate numbers for various max packet sizes (OV518(+) only) */
#define OV518_ALT_SIZE_0	0
#define OV518_ALT_SIZE_128	1
#define OV518_ALT_SIZE_256	2
#define OV518_ALT_SIZE_384	3
#define OV518_ALT_SIZE_512	4
#define OV518_ALT_SIZE_640	5
#define OV518_ALT_SIZE_768	6
#define OV518_ALT_SIZE_896	7

/* --------------------------------- */
/*     OV7610 REGISTER MNEMONICS     */
/* --------------------------------- */

/* OV7610 registers */
#define OV7610_REG_GAIN          0x00	/* gain setting (5:0) */
#define OV7610_REG_BLUE          0x01	/* blue channel balance */
#define OV7610_REG_RED           0x02	/* red channel balance */
#define OV7610_REG_SAT           0x03	/* saturation */
					/* 04 reserved */
#define OV7610_REG_CNT           0x05	/* Y contrast */
#define OV7610_REG_BRT           0x06	/* Y brightness */
					/* 08-0b reserved */
#define OV7610_REG_BLUE_BIAS     0x0C	/* blue channel bias (5:0) */
#define OV7610_REG_RED_BIAS      0x0D	/* read channel bias (5:0) */
#define OV7610_REG_GAMMA_COEFF   0x0E	/* gamma settings */
#define OV7610_REG_WB_RANGE      0x0F	/* AEC/ALC/S-AWB settings */
#define OV7610_REG_EXP           0x10	/* manual exposure setting */
#define OV7610_REG_CLOCK         0x11	/* polarity/clock prescaler */
#define OV7610_REG_COM_A         0x12	/* misc common regs */
#define OV7610_REG_COM_B         0x13	/* misc common regs */
#define OV7610_REG_COM_C         0x14	/* misc common regs */
#define OV7610_REG_COM_D         0x15	/* misc common regs */
#define OV7610_REG_FIELD_DIVIDE  0x16	/* field interval/mode settings */
#define OV7610_REG_HWIN_START    0x17	/* horizontal window start */
#define OV7610_REG_HWIN_END      0x18	/* horizontal window end */
#define OV7610_REG_VWIN_START    0x19	/* vertical window start */
#define OV7610_REG_VWIN_END      0x1A	/* vertical window end */
#define OV7610_REG_PIXEL_SHIFT   0x1B	/* pixel shift */
#define OV7610_REG_ID_HIGH       0x1C	/* manufacturer ID MSB */
#define OV7610_REG_ID_LOW        0x1D	/* manufacturer ID LSB */
					/* 0e-0f reserved */
#define OV7610_REG_COM_E         0x20	/* misc common regs */
#define OV7610_REG_YOFFSET       0x21	/* Y channel offset */
#define OV7610_REG_UOFFSET       0x22	/* U channel offset */
					/* 23 reserved */
#define OV7610_REG_ECW           0x24	/* Exposure white level for AEC */
#define OV7610_REG_ECB           0x25	/* Exposure black level for AEC */
#define OV7610_REG_COM_F         0x26	/* misc settings */
#define OV7610_REG_COM_G         0x27	/* misc settings */
#define OV7610_REG_COM_H         0x28	/* misc settings */
#define OV7610_REG_COM_I         0x29	/* misc settings */
#define OV7610_REG_FRAMERATE_H   0x2A	/* frame rate MSB + misc */
#define OV7610_REG_FRAMERATE_L   0x2B	/* frame rate LSB */
#define OV7610_REG_ALC           0x2C	/* Auto Level Control settings */
#define OV7610_REG_COM_J         0x2D	/* misc settings */
#define OV7610_REG_VOFFSET       0x2E	/* V channel offset adjustment */
#define OV7610_REG_ARRAY_BIAS	 0x2F	/* Array bias -- don't change */
					/* 30-32 reserved */
#define OV7610_REG_YGAMMA        0x33	/* misc gamma settings (7:6) */
#define OV7610_REG_BIAS_ADJUST   0x34	/* misc bias settings */
#define OV7610_REG_COM_L         0x35	/* misc settings */
					/* 36-37 reserved */
#define OV7610_REG_COM_K         0x38	/* misc registers */

/* --------------------------------- */
/*           I2C ADDRESSES           */
/* --------------------------------- */

#define OV7xx0_SID   0x42
#define OV6xx0_SID   0xC0
#define OV8xx0_SID   0xA0
#define KS0127_SID   0xD8
#define SAA7111A_SID 0x48

/* --------------------------------- */
/*       MISCELLANEOUS DEFINES       */
/* --------------------------------- */

#define I2C_CLOCK_PRESCALER 	0x03

#define FRAMES_PER_DESC		10	/* FIXME - What should this be? */
#define MAX_FRAME_SIZE_PER_DESC	993	/* For statically allocated stuff */
#define PIXELS_PER_SEG		256	/* Pixels per segment */

#define OV511_ENDPOINT_ADDRESS	1	/* Isoc endpoint number */

#define OV511_NUMFRAMES	2
#if OV511_NUMFRAMES > VIDEO_MAX_FRAME
	#error "OV511_NUMFRAMES is too high"
#endif

#define OV511_NUMSBUF		2

/* Control transfers use up to 4 bytes */
#define OV511_CBUF_SIZE		4

/* Size of usb_make_path() buffer */
#define OV511_USB_PATH_LEN	64

/* Bridge types */
enum {
	BRG_UNKNOWN,
	BRG_OV511,
	BRG_OV511PLUS,
	BRG_OV518,
	BRG_OV518PLUS,
};

/* Bridge classes */
enum {
	BCL_UNKNOWN,
	BCL_OV511,
	BCL_OV518,
};

/* Sensor types */
enum {
	SEN_UNKNOWN,
	SEN_OV76BE,
	SEN_OV7610,
	SEN_OV7620,
	SEN_OV7620AE,
	SEN_OV6620,
	SEN_OV6630,
	SEN_OV6630AE,
	SEN_OV6630AF,
	SEN_OV8600,
	SEN_KS0127,
	SEN_KS0127B,
	SEN_SAA7111A,
};

enum {
	STATE_SCANNING,		/* Scanning for start */
	STATE_HEADER,		/* Parsing header */
	STATE_LINES,		/* Parsing lines */
};

/* Buffer states */
enum {
	BUF_NOT_ALLOCATED,
	BUF_ALLOCATED,
};

/* --------- Definition of ioctl interface --------- */

#define OV511_INTERFACE_VER 101

/* LED options */
enum {
	LED_OFF,
	LED_ON,
	LED_AUTO,
};

/* Raw frame formats */
enum {
	RAWFMT_INVALID,
	RAWFMT_YUV400,
	RAWFMT_YUV420,
	RAWFMT_YUV422,
	RAWFMT_GBR422,
};

struct ov511_i2c_struct {
	unsigned char slave; /* Write slave ID (read ID - 1) */
	unsigned char reg;   /* Index of register */
	unsigned char value; /* User sets this w/ write, driver does w/ read */
	unsigned char mask;  /* Bits to be changed. Not used with read ops */
};

/* ioctls */
#define OV511IOC_WI2C     _IOW('v', BASE_VIDIOCPRIVATE + 5, \
			       struct ov511_i2c_struct)
#define OV511IOC_RI2C    _IOWR('v', BASE_VIDIOCPRIVATE + 6, \
			       struct ov511_i2c_struct)
/* ------------- End IOCTL interface -------------- */

struct usb_ov511;		/* Forward declaration */

struct ov511_sbuf {
	struct usb_ov511 *ov;
	unsigned char *data;
	struct urb *urb;
	spinlock_t lock;
	int n;
};

enum {
	FRAME_UNUSED,		/* Unused (no MCAPTURE) */
	FRAME_READY,		/* Ready to start grabbing */
	FRAME_GRABBING,		/* In the process of being grabbed into */
	FRAME_DONE,		/* Finished grabbing, but not been synced yet */
	FRAME_ERROR,		/* Something bad happened while processing */
};

struct ov511_regvals {
	enum {
		OV511_DONE_BUS,
		OV511_REG_BUS,
		OV511_I2C_BUS,
	} bus;
	unsigned char reg;
	unsigned char val;
};

struct ov511_frame {
	int framenum;		/* Index of this frame */
	unsigned char *data;	/* Frame buffer */
	unsigned char *tempdata; /* Temp buffer for multi-stage conversions */
	unsigned char *rawdata;	/* Raw camera data buffer */
	unsigned char *compbuf;	/* Temp buffer for decompressor */

	int depth;		/* Bytes per pixel */
	int width;		/* Width application is expecting */
	int height;		/* Height application is expecting */

	int rawwidth;		/* Actual width of frame sent from camera */
	int rawheight;		/* Actual height of frame sent from camera */

	int sub_flag;		/* Sub-capture mode for this frame? */
	unsigned int format;	/* Format for this frame */
	int compressed;		/* Is frame compressed? */

	volatile int grabstate;	/* State of grabbing */
	int scanstate;		/* State of scanning */

	int bytes_recvd;	/* Number of image bytes received from camera */

	long bytes_read;	/* Amount that has been read() */

	wait_queue_head_t wq;	/* Processes waiting */

	int snapshot;		/* True if frame was a snapshot */
};

#define DECOMP_INTERFACE_VER 4

/* Compression module operations */
struct ov51x_decomp_ops {
	int (*decomp_400)(unsigned char *, unsigned char *, unsigned char *,
			  int, int, int);
	int (*decomp_420)(unsigned char *, unsigned char *, unsigned char *,
			  int, int, int);
	int (*decomp_422)(unsigned char *, unsigned char *, unsigned char *,
			  int, int, int);
	struct module *owner;
};

struct usb_ov511 {
	struct video_device *vdev;
	struct usb_device *dev;

	int customid;
	char *desc;
	unsigned char iface;
	char usb_path[OV511_USB_PATH_LEN];

	/* Determined by sensor type */
	int maxwidth;
	int maxheight;
	int minwidth;
	int minheight;

	int brightness;
	int colour;
	int contrast;
	int hue;
	int whiteness;
	int exposure;
	int auto_brt;		/* Auto brightness enabled flag */
	int auto_gain;		/* Auto gain control enabled flag */
	int auto_exp;		/* Auto exposure enabled flag */
	int backlight;		/* Backlight exposure algorithm flag */
	int mirror;		/* Image is reversed horizontally */

	int led_policy;		/* LED: off|on|auto; OV511+ only */

	struct mutex lock;	/* Serializes user-accessible operations */
	int user;		/* user count for exclusive use */

	int streaming;		/* Are we streaming Isochronous? */
	int grabbing;		/* Are we grabbing? */

	int compress;		/* Should the next frame be compressed? */
	int compress_inited;	/* Are compression params uploaded? */

	int lightfreq;		/* Power (lighting) frequency */
	int bandfilt;		/* Banding filter enabled flag */

	unsigned char *fbuf;	/* Videodev buffer area */
	unsigned char *tempfbuf; /* Temporary (intermediate) buffer area */
	unsigned char *rawfbuf;	/* Raw camera data buffer area */

	int sub_flag;		/* Pix Array subcapture on flag */
	int subx;		/* Pix Array subcapture x offset */
	int suby;		/* Pix Array subcapture y offset */
	int subw;		/* Pix Array subcapture width */
	int subh;		/* Pix Array subcapture height */

	int curframe;		/* Current receiving sbuf */
	struct ov511_frame frame[OV511_NUMFRAMES];

	struct ov511_sbuf sbuf[OV511_NUMSBUF];

	wait_queue_head_t wq;	/* Processes waiting */

	int snap_enabled;	/* Snapshot mode enabled */

	int bridge;		/* Type of bridge (BRG_*) */
	int bclass;		/* Class of bridge (BCL_*) */
	int sensor;		/* Type of image sensor chip (SEN_*) */

	int packet_size;	/* Frame size per isoc desc */
	int packet_numbering;	/* Is ISO frame numbering enabled? */

	/* Framebuffer/sbuf management */
	int buf_state;
	struct mutex buf_lock;

	struct ov51x_decomp_ops *decomp_ops;

	/* Stop streaming while changing picture settings */
	int stop_during_set;

	int stopped;		/* Streaming is temporarily paused */

	/* Video decoder stuff */
	int input;		/* Composite, S-VIDEO, etc... */
	int num_inputs;		/* Number of inputs */
	int norm; 		/* NTSC / PAL / SECAM */
	int has_decoder;	/* Device has a video decoder */
	int pal;		/* Device is designed for PAL resolution */

	/* ov511 device number ID */
	int nr;			/* Stores a device number */

	/* I2C interface */
	struct mutex i2c_lock;	  /* Protect I2C controller regs */
	unsigned char primary_i2c_slave;  /* I2C write id of sensor */

	/* Control transaction stuff */
	unsigned char *cbuf;		/* Buffer for payload */
	struct mutex cbuf_lock;
};

/* Used to represent a list of values and their respective symbolic names */
struct symbolic_list {
	int num;
	char *name;
};

#define NOT_DEFINED_STR "Unknown"

/* Returns the name of the matching element in the symbolic_list array. The
 * end of the list must be marked with an element that has a NULL name.
 */
static inline char *
symbolic(struct symbolic_list list[], int num)
{
	int i;

	for (i = 0; list[i].name != NULL; i++)
			if (list[i].num == num)
				return (list[i].name);

	return (NOT_DEFINED_STR);
}

/* Compression stuff */

#define OV511_QUANTABLESIZE	64
#define OV518_QUANTABLESIZE	32

#define OV511_YQUANTABLE { \
	0, 1, 1, 2, 2, 3, 3, 4, \
	1, 1, 1, 2, 2, 3, 4, 4, \
	1, 1, 2, 2, 3, 4, 4, 4, \
	2, 2, 2, 3, 4, 4, 4, 4, \
	2, 2, 3, 4, 4, 5, 5, 5, \
	3, 3, 4, 4, 5, 5, 5, 5, \
	3, 4, 4, 4, 5, 5, 5, 5, \
	4, 4, 4, 4, 5, 5, 5, 5  \
}

#define OV511_UVQUANTABLE { \
	0, 2, 2, 3, 4, 4, 4, 4, \
	2, 2, 2, 4, 4, 4, 4, 4, \
	2, 2, 3, 4, 4, 4, 4, 4, \
	3, 4, 4, 4, 4, 4, 4, 4, \
	4, 4, 4, 4, 4, 4, 4, 4, \
	4, 4, 4, 4, 4, 4, 4, 4, \
	4, 4, 4, 4, 4, 4, 4, 4, \
	4, 4, 4, 4, 4, 4, 4, 4  \
}

#define OV518_YQUANTABLE { \
	5, 4, 5, 6, 6, 7, 7, 7, \
	5, 5, 5, 5, 6, 7, 7, 7, \
	6, 6, 6, 6, 7, 7, 7, 8, \
	7, 7, 6, 7, 7, 7, 8, 8  \
}

#define OV518_UVQUANTABLE { \
	6, 6, 6, 7, 7, 7, 7, 7, \
	6, 6, 6, 7, 7, 7, 7, 7, \
	6, 6, 6, 7, 7, 7, 7, 8, \
	7, 7, 7, 7, 7, 7, 8, 8  \
}

#endif