3 * @author Nicolas VIVIEN
6 * @brief Driver for SN9C20X USB video cameras
8 * @note Copyright (C) Nicolas VIVIEN
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <linux/kernel.h>
28 #include <linux/version.h>
29 #include <linux/usb.h>
30 #include <media/v4l2-common.h>
35 #define DRIVER_NAME "sn9c20x" /**< Name of this driver */
36 #define DRIVER_VERSION "v2009.01" /**< Version of this driver */
37 #define DRIVER_VERSION_NUM 0x200901 /**< Version numerical of this driver */
38 #define DRIVER_DESC "SN9C20x USB 2.0 Webcam Driver" /**< Short description of this driver */
39 #define DRIVER_AUTHOR "Nicolas VIVIEN and microdia project" \
40 " <microdia@googlegroups.com>" /**< Author of this driver */
41 #define PREFIX DRIVER_NAME ": " /**< Prefix use for the SN9C20X "printk" */
43 #define USB_0C45_VID 0x0c45 /**< Vendor ID of MICRODIA */
44 #define USB_045E_VID 0x045e /**< Vendor ID of MICROSOFT */
45 #define USB_04F2_VID 0x04f2 /**< Vendor ID of CHICONY */
46 #define USB_145F_VID 0x145f /**< Vendor ID of TRUST */
47 #define USB_0458_VID 0x0458 /**< Vendor ID of KYE */
50 #define USB_6240_PID 0x6240 /**< SN9C201 + MI1300 */
51 #define USB_6242_PID 0x6242 /**< SN9C201 + MI1310 */
52 #define USB_6243_PID 0x6243 /**< SN9C201 + S5K4AAFX */
53 #define USB_6248_PID 0x6248 /**< SN9C201 + OV9655 */
54 #define USB_624B_PID 0x624b /**< SN9C201 + CX1332 */
55 #define USB_624C_PID 0x624c /**< SN9C201 + MI1320 */
56 #define USB_624E_PID 0x624e /**< SN9C201 + SOI968 */
57 #define USB_624F_PID 0x624f /**< SN9C201 + OV9650 */
58 #define USB_6251_PID 0x6251 /**< SN9C201 + OV9650 */
59 #define USB_6253_PID 0x6253 /**< SN9C201 + OV9650 */
60 #define USB_6260_PID 0x6260 /**< SN9C201 + OV7670ISP */
61 #define USB_6262_PID 0x6262 /**< SN9C201 + OM6802 */
62 #define USB_6270_PID 0x6270 /**< SN9C201 + MI0360/MT9V111 */
63 #define USB_627A_PID 0x627a /**< SN9C201 + S5K53BEB */
64 #define USB_627B_PID 0x627b /**< SN9C201 + OV7660 */
65 #define USB_627C_PID 0x627c /**< SN9C201 + HV7131R */
66 #define USB_627F_PID 0x627f /**< EEPROM */
68 #define USB_6280_PID 0x6280 /**< SN9C202 + MI1300 */
69 #define USB_6282_PID 0x6282 /**< SN9C202 + MI1310 */
70 #define USB_6283_PID 0x6283 /**< SN9C202 + S5K4AAFX */
71 #define USB_6288_PID 0x6288 /**< SN9C202 + OV9655 */
72 #define USB_628A_PID 0x628a /**< SN9C202 + ICM107 */
73 #define USB_628B_PID 0x628b /**< SN9C202 + CX1332 */
74 #define USB_628C_PID 0x628c /**< SN9C202 + MI1320 */
75 #define USB_628E_PID 0x628e /**< SN9C202 + SOI968 */
76 #define USB_628F_PID 0x628f /**< SN9C202 + OV9650 */
77 #define USB_62A0_PID 0x62a0 /**< SN9C202 + OV7670ISP */
78 #define USB_62A2_PID 0x62a2 /**< SN9C202 + OM6802 */
79 #define USB_62B0_PID 0x62b0 /**< SN9C202 + MI0360/MT9V111 */
80 #define USB_62B3_PID 0x62b3 /**< SN9C202 + OV9655 */
81 #define USB_62BA_PID 0x62ba /**< SN9C202 + S5K53BEB */
82 #define USB_62BB_PID 0x62bb /**< SN9C202 + OV7660 */
83 #define USB_62BC_PID 0x62bc /**< SN9C202 + HV7131R */
84 #define USB_62BE_PID 0x62be /**< SN9C202 + OV7663 */
86 /* *** "Clone"-devices ***: */
87 /* Microsoft LifeCam VX-6000: */
88 #define USB_00F4_PID 0x00f4 /**< => 628f (SN9C202 + OV9650) */
90 #define USB_013D_PID 0x013d /**< => 627b (SN9C201 + OV7660) */
91 /* Chicony Panda 7, Trust WB-3450P: */
92 #define USB_A128_PID 0xa128 /**< => 62be (SN9C202 + OV7663) */
93 /* Genius Look 320S (KYE Systems Corp)*/
94 #define USB_7029_PID 0x7029 /**< => 627c (SN9C201 + HV7131R) */
97 #define SN9C20X_USB_DEVICE(vend, prod, sensor, address) \
98 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
99 USB_DEVICE_ID_MATCH_INT_CLASS, \
100 .idVendor = (vend), \
101 .idProduct = (prod), \
102 .bInterfaceClass = 0xff, \
103 .driver_info = ((address << 8) | sensor)
105 /** V4L2-CONTROLS for compatibility with older kernels: */
106 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 25)
107 #define V4L2_CID_SHARPNESS (V4L2_CID_PRIVATE_BASE + 0)
108 #define V4L2_CID_EXPOSURE_AUTO (V4L2_CID_PRIVATE_BASE + 1)
109 enum v4l2_exposure_auto_type
{
110 V4L2_EXPOSURE_AUTO
= 0,
111 V4L2_EXPOSURE_MANUAL
= 1,
112 V4L2_EXPOSURE_SHUTTER_PRIORITY
= 2,
113 V4L2_EXPOSURE_APERTURE_PRIORITY
= 3
117 #ifndef V4L2_PIX_FMT_SN9C20X_I420
118 #define V4L2_PIX_FMT_SN9C20X_I420 v4l2_fourcc('S', '9', '2', '0')
123 * Number maximal of URBS
125 * @def ISO_FRAMES_PER_DESC
126 * Number frames per ISOC descriptor
129 #define ISO_FRAMES_PER_DESC 10
132 * @def hb_multiplier(wMaxPacketSize)
133 * USB endpoint high bandwidth multiplier
135 * @def max_packet_sz(wMaxPacketSize)
136 * USB endpoint maximum packet size
138 * These values are both encoded within the wMaxPacketSize field of the usb_endpoint_descriptor structure.
139 * The 11(10:0) lowest bits hold the MaxPacketSize(according to the usb specs a value over 1024 is undefined),
140 * and the bits 12:11 will give the high bandwidth multiplier(this should be a value of 0-2).
143 #define hb_multiplier(wMaxPacketSize) (((wMaxPacketSize >> 11) & 0x03) + 1)
144 #define max_packet_sz(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
147 * @def DRIVER_SUPPORT
149 * List of supported devices
151 #define DRIVER_SUPPORT "SN9C20X USB Camera"
153 #define SN9C20X_INFO (1 << 0)
154 #define SN9C20X_WARNING (1 << 1)
155 #define SN9C20X_ERROR (1 << 2)
156 #define SN9C20X_DEBUG (1 << 3)
157 #define SN9C20X_STREAM (1 << 4)
160 * @def UDIA_INFO(str, args...)
161 * Print information message.
162 * @a Use this function like the function printf.
164 * @def UDIA_ERROR(str, args...)
165 * Print error message.
166 * @a Use this function like the function printf.
168 * @def UDIA_WARNING(str, args...)
169 * Print warning message.
170 * @a Use this function like the function printf.
172 * @def UDIA_DEBUG(str, args...)
173 * Print debug message.
174 * @a Use this function like the function printf.
176 * @def UDIA_STREAM(str, args...)
177 * Print stream debug message.
178 * @a Use this function like the function printf.
180 extern __u8 log_level
;
182 #define UDIA_INFO(str, args...) \
184 if (log_level & SN9C20X_INFO) \
185 printk(KERN_INFO PREFIX str, ##args); \
188 #define UDIA_WARNING(str, args...) \
190 if (log_level & SN9C20X_WARNING) \
191 printk(KERN_WARNING PREFIX str, ##args); \
194 #define UDIA_ERROR(str, args...) \
196 if (log_level & SN9C20X_ERROR) \
197 printk(KERN_ERR PREFIX str, ##args); \
200 #define UDIA_DEBUG(str, args...) \
202 if (log_level & SN9C20X_DEBUG) \
203 printk(KERN_DEBUG PREFIX str, ##args); \
206 #define UDIA_STREAM(str, args...) \
208 if (log_level & SN9C20X_STREAM) \
209 printk(KERN_DEBUG PREFIX str, ##args); \
213 enum sn9c20x_buffer_state
{
214 SN9C20X_BUF_STATE_IDLE
= 0,
215 SN9C20X_BUF_STATE_QUEUED
= 1,
216 SN9C20X_BUF_STATE_ACTIVE
= 2,
217 SN9C20X_BUF_STATE_DONE
= 3,
218 SN9C20X_BUF_STATE_ERROR
= 4,
222 SN9C20X_MODE_IDLE
= 0,
223 SN9C20X_MODE_READ
= 1,
224 SN9C20X_MODE_STREAM
= 2,
227 struct sn9c20x_buffer
{
228 unsigned long vma_use_count
;
229 struct list_head stream
;
231 /* Touched by interrupt handler. */
232 struct v4l2_buffer buf
;
233 struct list_head queue
;
234 wait_queue_head_t wait
;
235 enum sn9c20x_buffer_state state
;
238 #define SN9C20X_QUEUE_STREAMING (1 << 0)
239 #define SN9C20X_QUEUE_DISCONNECTED (1 << 1)
240 #define SN9C20X_QUEUE_DROP_INCOMPLETE (1 << 2)
242 struct sn9c20x_video_queue
{
248 unsigned int min_buffers
;
249 unsigned int max_buffers
;
250 unsigned int buf_size
;
252 struct sn9c20x_buffer
*buffer
;
253 struct sn9c20x_buffer
*read_buffer
;
254 struct mutex mutex
; /* protects buffers and mainqueue */
255 spinlock_t irqlock
; /* protects irqqueue */
257 struct list_head mainqueue
;
258 struct list_head irqqueue
;
262 * @struct sn9c20x_urb
270 * @struct sn9c20x_video
272 struct sn9c20x_video
{
273 struct v4l2_pix_format format
;
274 int fps
; /**< FPS setting */
275 int brightness
; /**< Brightness setting */
276 int contrast
; /**< Contrast setting */
277 int gamma
; /**< Gamma setting */
278 int colour
; /**< Colour setting */
279 int hue
; /**< Hue setting */
280 int hflip
; /**< Horizontal flip */
281 int vflip
; /**< Vertical flip */
282 int exposure
; /**< Exposure */
283 int gain
; /**< Gain */
284 int sharpness
; /**< Sharpness */
285 int red_gain
; /**< Red Gain Control */
286 int blue_gain
; /**< Blue Gain Control */
287 int auto_exposure
; /**< Automatic exposure */
288 int auto_gain
; /**< Automatic gain */
289 int auto_whitebalance
; /**< Automatic whitebalance */
293 * @struct sn9c20x_debugfs
295 struct sn9c20x_debugfs
{
296 struct dentry
*dent_device
;
297 struct dentry
*dent_bridge_addr
;
298 struct dentry
*dent_bridge_val
;
299 struct dentry
*dent_bridge_dump
;
300 struct dentry
*dent_sensor_addr
;
301 struct dentry
*dent_sensor_val8
;
302 struct dentry
*dent_sensor_val16
;
303 struct dentry
*dent_sensor_val32
;
305 __u16 bridge_addr
; /**< Current bridge register address */
306 __u8 sensor_addr
; /**< Current sensor register address */
309 enum sn9c20x_endpoints
{
310 SN9C20X_VID_ISOC
= 1,
316 enum sn9c20x_sensors
{
335 struct sn9c20x_video_mode
{
342 struct sn9c20x_video_format
{
346 void (*set_format
) (struct usb_sn9c20x
*dev
);
349 struct sn9c20x_i2c_regs
{
354 extern struct sn9c20x_i2c_regs mt9v112_init
[];
355 extern struct sn9c20x_i2c_regs mt9v111_init
[];
356 extern struct sn9c20x_i2c_regs mt9v011_init
[];
357 extern struct sn9c20x_i2c_regs mt9m111_init
[];
358 extern struct sn9c20x_i2c_regs mt9m001_init
[];
359 extern struct sn9c20x_i2c_regs soi968_init
[];
360 extern struct sn9c20x_i2c_regs ov9650_init
[];
361 extern struct sn9c20x_i2c_regs ov9655_init
[];
362 extern struct sn9c20x_i2c_regs ov7660_init
[];
363 extern struct sn9c20x_i2c_regs ov7670_init
[];
364 extern struct sn9c20x_i2c_regs hv7131r_init
[];
366 #define SN9C20X_N_FMTS 3
367 #define SN9C20X_N_MODES 6
369 extern struct sn9c20x_video_format sn9c20x_fmts
[SN9C20X_N_FMTS
];
370 extern struct sn9c20x_video_mode sn9c20x_modes
[SN9C20X_N_MODES
];
372 struct sn9c20x_camera
{
377 /* SCCB/I2C interface */
381 int min_yavg
, max_yavg
, min_stable_yavg
, max_stable_yavg
, old_yavg
;
388 int (*flip_detect
) (struct usb_sn9c20x
*dev
);
389 int (*button_detect
) (struct usb_sn9c20x
*dev
);
390 int (*set_hvflip
) (struct usb_sn9c20x
*dev
);
391 /* image quality functions */
392 int (*set_exposure
) (struct usb_sn9c20x
*dev
);
393 int (*set_gain
) (struct usb_sn9c20x
*dev
);
394 int (*set_auto_exposure
) (struct usb_sn9c20x
*dev
);
395 int (*set_auto_gain
) (struct usb_sn9c20x
*dev
);
396 int (*set_auto_whitebalance
) (struct usb_sn9c20x
*dev
);
397 int (*set_contrast
) (struct usb_sn9c20x
*dev
);
398 int (*set_brightness
) (struct usb_sn9c20x
*dev
);
399 int (*set_gamma
) (struct usb_sn9c20x
*dev
);
400 int (*set_sharpness
) (struct usb_sn9c20x
*dev
);
401 int (*set_red_gain
) (struct usb_sn9c20x
*dev
);
402 int (*set_blue_gain
) (struct usb_sn9c20x
*dev
);
406 * @struct usb_sn9c20x
409 struct video_device
*vdev
; /**< Pointer on a V4L2 video device */
410 struct usb_device
*udev
; /**< Pointer on a USB device */
411 struct usb_interface
*interface
;/**< Pointer on a USB interface */
413 int release
; /**< Release of the device (bcdDevice) */
415 struct sn9c20x_video vsettings
; /**< Video settings (brightness, whiteness...) */
416 struct sn9c20x_debugfs debug
; /**< debugfs information structure */
418 struct kref vopen
; /**< Video status (Opened or Closed) */
419 struct file
*owner
; /**< file handler of stream owner */
420 enum sn9c20x_mode mode
; /**< camera mode */
422 int vframes_overflow
; /**< Buffer overflow frames */
423 int vframes_incomplete
; /**< Incomplete frames */
424 int vframes_dropped
; /**< Dropped frames */
426 struct mutex mutex
; /**< Mutex */
428 struct sn9c20x_urb urbs
[MAX_URBS
];
434 unsigned int frozen
:1;
435 struct sn9c20x_video_queue queue
;
436 struct sn9c20x_camera camera
;
440 * @def SN9C20X_PERCENT
441 * Calculate a value from a percent
443 #define SN9C20X_PERCENT(x, y) (((int)x * (int)y) / 100)
446 extern struct mutex open_lock
;
449 int usb_sn9c20x_control_write(struct usb_sn9c20x
*, __u16
, __u8
*, __u16
);
450 int usb_sn9c20x_control_read(struct usb_sn9c20x
*, __u16
, __u8
*, __u16
);
452 int usb_sn9c20x_isoc_init(struct usb_sn9c20x
*,
453 struct usb_endpoint_descriptor
*);
454 void usb_sn9c20x_completion_handler(struct urb
*);
455 int usb_sn9c20x_init_urbs(struct usb_sn9c20x
*);
456 void usb_sn9c20x_uninit_urbs(struct usb_sn9c20x
*);
457 void usb_sn9c20x_delete(struct kref
*);
459 int sn9c20x_initialize(struct usb_sn9c20x
*dev
);
460 int sn9c20x_initialize_sensor(struct usb_sn9c20x
*dev
);
461 int sn9c20x_enable_video(struct usb_sn9c20x
*dev
, int enable
);
463 int dev_sn9c20x_call_constantly(struct usb_sn9c20x
*dev
);
464 int dev_sn9c20x_flip_detection(struct usb_sn9c20x
*dev
);
465 int dev_sn9c20x_button_detection(struct usb_sn9c20x
*dev
);
466 int dev_sn9c20x_camera_set_exposure(struct usb_sn9c20x
*);
467 int dev_sn9c20x_camera_set_gain(struct usb_sn9c20x
*);
468 int dev_sn9c20x_camera_set_hvflip(struct usb_sn9c20x
*);
469 int dev_sn9c20x_camera_set_auto_exposure(struct usb_sn9c20x
*dev
);
470 int dev_sn9c20x_camera_set_auto_gain(struct usb_sn9c20x
*dev
);
471 int dev_sn9c20x_camera_set_auto_whitebalance(struct usb_sn9c20x
*dev
);
472 int dev_sn9c20x_perform_soft_ae(struct usb_sn9c20x
*dev
);
474 void v4l2_set_control_default(struct usb_sn9c20x
*, __u32
, __u16
);
475 int v4l_sn9c20x_select_video_mode(struct usb_sn9c20x
*, int);
476 int v4l_sn9c20x_register_video_device(struct usb_sn9c20x
*);
477 int v4l_sn9c20x_unregister_video_device(struct usb_sn9c20x
*);
479 int sn9c20x_create_sysfs_files(struct video_device
*);
480 void sn9c20x_remove_sysfs_files(struct video_device
*);
482 #ifdef CONFIG_SN9C20X_DEBUGFS
483 void sn9c20x_init_debugfs(void);
484 void sn9c20x_uninit_debugfs(void);
485 int sn9c20x_create_debugfs_files(struct usb_sn9c20x
*);
486 int sn9c20x_remove_debugfs_files(struct usb_sn9c20x
*);
488 static inline void sn9c20x_init_debugfs(void) {}
489 static inline void sn9c20x_uninit_debugfs(void) {}
490 static inline int sn9c20x_create_debugfs_files(struct usb_sn9c20x
*dev
)
494 static inline int sn9c20x_remove_debugfs_files(struct usb_sn9c20x
*dev
)
500 void sn9c20x_queue_init(struct sn9c20x_video_queue
*);
501 int sn9c20x_alloc_buffers(struct sn9c20x_video_queue
*,
502 unsigned int, unsigned int);
503 int sn9c20x_free_buffers(struct sn9c20x_video_queue
*);
504 int sn9c20x_queue_enable(struct sn9c20x_video_queue
*, int);
505 void sn9c20x_queue_cancel(struct sn9c20x_video_queue
*, int);
506 unsigned int sn9c20x_queue_poll(struct sn9c20x_video_queue
*,
507 struct file
*, poll_table
*);
508 int sn9c20x_query_buffer(struct sn9c20x_video_queue
*, struct v4l2_buffer
*);
509 int sn9c20x_queue_buffer(struct sn9c20x_video_queue
*, struct v4l2_buffer
*);
510 int sn9c20x_dequeue_buffer(struct sn9c20x_video_queue
*,
511 struct v4l2_buffer
*, int);
512 struct sn9c20x_buffer
*sn9c20x_queue_next_buffer(
513 struct sn9c20x_video_queue
*, struct sn9c20x_buffer
*);
515 static inline int sn9c20x_queue_streaming(struct sn9c20x_video_queue
*queue
)
517 return queue
->flags
& SN9C20X_QUEUE_STREAMING
;
520 /* sensor hv7131r has no header-file of its own: */
521 int hv7131r_initialize(struct usb_sn9c20x
*dev
);
522 int hv7131r_set_exposure(struct usb_sn9c20x
*dev
);
523 int hv7131r_set_gain(struct usb_sn9c20x
*dev
);
524 int hv7131r_set_hvflip(struct usb_sn9c20x
*dev
);