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 #ifdef CONFIG_SN9C20X_EVDEV
31 #include <linux/input.h>
33 #include <media/v4l2-common.h>
38 #define DRIVER_NAME "sn9c20x" /**< Name of this driver */
39 #define DRIVER_VERSION "v2009.01" /**< Version of this driver */
40 #define DRIVER_VERSION_NUM 0x200901 /**< Version numerical of this driver */
41 #define DRIVER_DESC "SN9C20x USB 2.0 Webcam Driver" /**< Short description of this driver */
42 #define DRIVER_AUTHOR "Nicolas VIVIEN and microdia project" \
43 " <microdia@googlegroups.com>" /**< Author of this driver */
44 #define PREFIX DRIVER_NAME ": " /**< Prefix use for the SN9C20X "printk" */
46 #define SN9C20X_USB_DEVICE(vend, prod, sensor, address) \
47 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
48 USB_DEVICE_ID_MATCH_INT_CLASS, \
50 .idProduct = (prod), \
51 .bInterfaceClass = 0xff, \
52 .driver_info = ((address << 8) | sensor)
54 /** V4L2-CONTROLS for compatibility with older kernels: */
55 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 25)
56 #define V4L2_CID_SHARPNESS (V4L2_CID_PRIVATE_BASE + 0)
57 #define V4L2_CID_EXPOSURE_AUTO (V4L2_CID_PRIVATE_BASE + 1)
60 #ifndef V4L2_PIX_FMT_SN9C20X_I420
61 #define V4L2_PIX_FMT_SN9C20X_I420 v4l2_fourcc('S', '9', '2', '0')
66 * Number maximal of URBS
68 * @def ISO_FRAMES_PER_DESC
69 * Number frames per ISOC descriptor
72 #define ISO_FRAMES_PER_DESC 10
75 * @def hb_multiplier(wMaxPacketSize)
76 * USB endpoint high bandwidth multiplier
78 * @def max_packet_sz(wMaxPacketSize)
79 * USB endpoint maximum packet size
81 * These values are both encoded within the wMaxPacketSize field of the usb_endpoint_descriptor structure.
82 * The 11(10:0) lowest bits hold the MaxPacketSize(according to the usb specs a value over 1024 is undefined),
83 * and the bits 12:11 will give the high bandwidth multiplier(this should be a value of 0-2).
86 #define hb_multiplier(wMaxPacketSize) (((wMaxPacketSize >> 11) & 0x03) + 1)
87 #define max_packet_sz(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
92 * List of supported devices
94 #define DRIVER_SUPPORT "SN9C20X USB Camera"
96 #define SN9C20X_INFO (1 << 0)
97 #define SN9C20X_WARNING (1 << 1)
98 #define SN9C20X_ERROR (1 << 2)
99 #define SN9C20X_DEBUG (1 << 3)
100 #define SN9C20X_STREAM (1 << 4)
103 * @def UDIA_INFO(str, args...)
104 * Print information message.
105 * @a Use this function like the function printf.
107 * @def UDIA_ERROR(str, args...)
108 * Print error message.
109 * @a Use this function like the function printf.
111 * @def UDIA_WARNING(str, args...)
112 * Print warning message.
113 * @a Use this function like the function printf.
115 * @def UDIA_DEBUG(str, args...)
116 * Print debug message.
117 * @a Use this function like the function printf.
119 * @def UDIA_STREAM(str, args...)
120 * Print stream debug message.
121 * @a Use this function like the function printf.
123 extern __u8 log_level
;
125 #define UDIA_INFO(str, args...) \
127 if (log_level & SN9C20X_INFO) \
128 printk(KERN_INFO PREFIX str, ##args); \
131 #define UDIA_WARNING(str, args...) \
133 if (log_level & SN9C20X_WARNING) \
134 printk(KERN_WARNING PREFIX str, ##args); \
137 #define UDIA_ERROR(str, args...) \
139 if (log_level & SN9C20X_ERROR) \
140 printk(KERN_ERR PREFIX str, ##args); \
143 #define UDIA_DEBUG(str, args...) \
145 if (log_level & SN9C20X_DEBUG) \
146 printk(KERN_DEBUG PREFIX str, ##args); \
149 #define UDIA_STREAM(str, args...) \
151 if (log_level & SN9C20X_STREAM) \
152 printk(KERN_DEBUG PREFIX str, ##args); \
156 enum sn9c20x_buffer_state
{
157 SN9C20X_BUF_STATE_IDLE
= 0,
158 SN9C20X_BUF_STATE_QUEUED
= 1,
159 SN9C20X_BUF_STATE_ACTIVE
= 2,
160 SN9C20X_BUF_STATE_DONE
= 3,
161 SN9C20X_BUF_STATE_ERROR
= 4,
165 SN9C20X_MODE_IDLE
= 0,
166 SN9C20X_MODE_READ
= 1,
167 SN9C20X_MODE_STREAM
= 2,
170 struct sn9c20x_buffer
{
171 unsigned long vma_use_count
;
172 struct list_head stream
;
174 /* Touched by interrupt handler. */
175 struct v4l2_buffer buf
;
176 struct list_head queue
;
177 wait_queue_head_t wait
;
178 enum sn9c20x_buffer_state state
;
181 #define SN9C20X_QUEUE_STREAMING (1 << 0)
182 #define SN9C20X_QUEUE_DISCONNECTED (1 << 1)
183 #define SN9C20X_QUEUE_DROP_INCOMPLETE (1 << 2)
185 struct sn9c20x_video_queue
{
191 unsigned int min_buffers
;
192 unsigned int max_buffers
;
193 unsigned int buf_size
;
195 struct sn9c20x_buffer
*buffer
;
196 struct sn9c20x_buffer
*read_buffer
;
197 struct mutex mutex
; /* protects buffers and mainqueue */
198 spinlock_t irqlock
; /* protects irqqueue */
200 struct list_head mainqueue
;
201 struct list_head irqqueue
;
205 * @struct sn9c20x_urb
213 * @struct sn9c20x_video
215 struct sn9c20x_video
{
216 struct v4l2_pix_format format
;
217 int fps
; /**< FPS setting */
218 int brightness
; /**< Brightness setting */
219 int contrast
; /**< Contrast setting */
220 int gamma
; /**< Gamma setting */
221 int colour
; /**< Colour setting */
222 int hue
; /**< Hue setting */
223 int hflip
; /**< Horizontal flip */
224 int vflip
; /**< Vertical flip */
225 int exposure
; /**< Exposure */
226 int gain
; /**< Gain */
227 int sharpness
; /**< Sharpness */
228 int red_gain
; /**< Red Gain Control */
229 int blue_gain
; /**< Blue Gain Control */
230 int auto_exposure
; /**< Automatic exposure */
231 int auto_gain
; /**< Automatic gain */
232 int auto_whitebalance
; /**< Automatic whitebalance */
236 * @struct sn9c20x_debugfs
238 struct sn9c20x_debugfs
{
239 struct dentry
*dent_device
;
240 struct dentry
*dent_bridge_addr
;
241 struct dentry
*dent_bridge_val
;
242 struct dentry
*dent_bridge_dump
;
243 struct dentry
*dent_sensor_addr
;
244 struct dentry
*dent_sensor_val8
;
245 struct dentry
*dent_sensor_val16
;
246 struct dentry
*dent_sensor_val32
;
248 __u16 bridge_addr
; /**< Current bridge register address */
249 __u8 sensor_addr
; /**< Current sensor register address */
252 enum sn9c20x_endpoints
{
253 SN9C20X_VID_ISOC
= 1,
259 enum sn9c20x_sensors
{
278 struct sn9c20x_video_mode
{
285 struct sn9c20x_video_format
{
289 void (*set_format
) (struct usb_sn9c20x
*dev
);
292 struct sn9c20x_i2c_regs
{
297 #define SN9C20X_N_FMTS 3
298 #define SN9C20X_N_MODES 6
300 extern struct sn9c20x_video_format sn9c20x_fmts
[SN9C20X_N_FMTS
];
301 extern struct sn9c20x_video_mode sn9c20x_modes
[SN9C20X_N_MODES
];
303 struct sn9c20x_camera
{
308 /* SCCB/I2C interface */
312 int min_yavg
, max_yavg
, old_step
, older_step
;
313 unsigned int exposure_step
;
320 int (*flip_detect
) (struct usb_sn9c20x
*dev
);
321 int (*set_hvflip
) (struct usb_sn9c20x
*dev
);
322 /* image quality functions */
323 int (*set_exposure
) (struct usb_sn9c20x
*dev
);
324 int (*set_gain
) (struct usb_sn9c20x
*dev
);
325 int (*set_auto_exposure
) (struct usb_sn9c20x
*dev
);
326 int (*set_auto_gain
) (struct usb_sn9c20x
*dev
);
327 int (*set_auto_whitebalance
) (struct usb_sn9c20x
*dev
);
328 int (*set_contrast
) (struct usb_sn9c20x
*dev
);
329 int (*set_brightness
) (struct usb_sn9c20x
*dev
);
330 int (*set_gamma
) (struct usb_sn9c20x
*dev
);
331 int (*set_sharpness
) (struct usb_sn9c20x
*dev
);
332 int (*set_red_gain
) (struct usb_sn9c20x
*dev
);
333 int (*set_blue_gain
) (struct usb_sn9c20x
*dev
);
337 * @struct usb_sn9c20x
340 #ifdef CONFIG_SN9C20X_EVDEV
341 struct input_dev
*input_dev
;
343 struct task_struct
*input_task
;
345 struct video_device
*vdev
; /**< Pointer on a V4L2 video device */
346 struct usb_device
*udev
; /**< Pointer on a USB device */
347 struct usb_interface
*interface
;/**< Pointer on a USB interface */
349 int release
; /**< Release of the device (bcdDevice) */
351 struct sn9c20x_video vsettings
; /**< Video settings (brightness, whiteness...) */
352 struct sn9c20x_debugfs debug
; /**< debugfs information structure */
354 struct kref vopen
; /**< Video status (Opened or Closed) */
355 struct file
*owner
; /**< file handler of stream owner */
356 enum sn9c20x_mode mode
; /**< camera mode */
358 int vframes_overflow
; /**< Buffer overflow frames */
359 int vframes_incomplete
; /**< Incomplete frames */
360 int vframes_dropped
; /**< Dropped frames */
362 struct sn9c20x_urb urbs
[MAX_URBS
];
366 unsigned int frozen
:1;
367 struct sn9c20x_video_queue queue
;
368 struct sn9c20x_camera camera
;
372 * @def SN9C20X_PERCENT
373 * Calculate a value from a percent
375 #define SN9C20X_PERCENT(x, y) (((int)x * (int)y) / 100)
378 extern struct mutex open_lock
;
381 int usb_sn9c20x_control_write(struct usb_sn9c20x
*, __u16
, __u8
*, __u16
);
382 int usb_sn9c20x_control_read(struct usb_sn9c20x
*, __u16
, __u8
*, __u16
);
384 int usb_sn9c20x_isoc_init(struct usb_sn9c20x
*,
385 struct usb_endpoint_descriptor
*);
386 void usb_sn9c20x_completion_handler(struct urb
*);
387 int usb_sn9c20x_init_urbs(struct usb_sn9c20x
*);
388 void usb_sn9c20x_uninit_urbs(struct usb_sn9c20x
*, int);
389 void usb_sn9c20x_delete(struct kref
*);
391 int sn9c20x_initialize(struct usb_sn9c20x
*dev
);
392 int sn9c20x_initialize_sensor(struct usb_sn9c20x
*dev
);
393 int sn9c20x_enable_video(struct usb_sn9c20x
*dev
, int enable
);
395 int dev_sn9c20x_call_constantly(struct usb_sn9c20x
*dev
);
396 int dev_sn9c20x_flip_detection(struct usb_sn9c20x
*dev
);
397 int dev_sn9c20x_camera_set_exposure(struct usb_sn9c20x
*);
398 int dev_sn9c20x_camera_set_gain(struct usb_sn9c20x
*);
399 int dev_sn9c20x_camera_set_hvflip(struct usb_sn9c20x
*);
400 int dev_sn9c20x_camera_set_auto_exposure(struct usb_sn9c20x
*dev
);
401 int dev_sn9c20x_camera_set_auto_gain(struct usb_sn9c20x
*dev
);
402 int dev_sn9c20x_camera_set_auto_whitebalance(struct usb_sn9c20x
*dev
);
403 int dev_sn9c20x_perform_soft_ae(struct usb_sn9c20x
*dev
);
405 void v4l2_set_control_default(struct usb_sn9c20x
*, __u32
, __u16
);
406 int v4l_sn9c20x_select_video_mode(struct usb_sn9c20x
*, int);
407 int v4l_sn9c20x_register_video_device(struct usb_sn9c20x
*);
408 int v4l_sn9c20x_unregister_video_device(struct usb_sn9c20x
*);
410 int sn9c20x_create_sysfs_files(struct video_device
*);
411 void sn9c20x_remove_sysfs_files(struct video_device
*);
413 #ifdef CONFIG_SN9C20X_DEBUGFS
414 void sn9c20x_init_debugfs(void);
415 void sn9c20x_uninit_debugfs(void);
416 int sn9c20x_create_debugfs_files(struct usb_sn9c20x
*);
417 int sn9c20x_remove_debugfs_files(struct usb_sn9c20x
*);
419 static inline void sn9c20x_init_debugfs(void) {}
420 static inline void sn9c20x_uninit_debugfs(void) {}
421 static inline int sn9c20x_create_debugfs_files(struct usb_sn9c20x
*dev
)
425 static inline int sn9c20x_remove_debugfs_files(struct usb_sn9c20x
*dev
)
431 void sn9c20x_queue_init(struct sn9c20x_video_queue
*);
432 int sn9c20x_alloc_buffers(struct sn9c20x_video_queue
*,
433 unsigned int, unsigned int);
434 int sn9c20x_free_buffers(struct sn9c20x_video_queue
*);
435 int sn9c20x_queue_enable(struct sn9c20x_video_queue
*, int);
436 void sn9c20x_queue_cancel(struct sn9c20x_video_queue
*, int);
437 unsigned int sn9c20x_queue_poll(struct sn9c20x_video_queue
*,
438 struct file
*, poll_table
*);
439 int sn9c20x_query_buffer(struct sn9c20x_video_queue
*, struct v4l2_buffer
*);
440 int sn9c20x_queue_buffer(struct sn9c20x_video_queue
*, struct v4l2_buffer
*);
441 int sn9c20x_dequeue_buffer(struct sn9c20x_video_queue
*,
442 struct v4l2_buffer
*, int);
443 struct sn9c20x_buffer
*sn9c20x_queue_next_buffer(
444 struct sn9c20x_video_queue
*, struct sn9c20x_buffer
*);
446 static inline int sn9c20x_queue_streaming(struct sn9c20x_video_queue
*queue
)
448 return queue
->flags
& SN9C20X_QUEUE_STREAMING
;
451 /* sensor hv7131r has no header-file of its own: */
452 extern struct sn9c20x_i2c_regs hv7131r_init
[];
453 int hv7131r_initialize(struct usb_sn9c20x
*dev
);
454 int hv7131r_set_exposure(struct usb_sn9c20x
*dev
);
455 int hv7131r_set_gain(struct usb_sn9c20x
*dev
);
456 int hv7131r_set_hvflip(struct usb_sn9c20x
*dev
);