* *
* - Memory management code from bttv driver by Ralph Metzler, *
* Marcus Metzler and Gerd Knorr. *
- * - I2C interface to kernel, high-level CMOS sensor control routines and *
+ * - I2C interface to kernel, high-level image sensor control routines and *
* some symbolic names from OV511 driver by Mark W. McClelland. *
* - Low-level I2C fast write function by Piotr Czerczak. *
* - Low-level I2C read function by Frederic Jouault. *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
***************************************************************************/
-#include <linux/version.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/kernel.h>
+#include <linux/kmod.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/string.h>
-#include <linux/ctype.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/ioctl.h>
#include <linux/delay.h>
+#include <linux/stddef.h>
#include <asm/page.h>
#include <asm/uaccess.h>
+#include <linux/page-flags.h>
+#include <linux/moduleparam.h>
#include "w9968cf.h"
#include "w9968cf_decoder.h"
/****************************************************************************
- * Module macros and paramaters *
+ * Module macros and parameters *
****************************************************************************/
+MODULE_DEVICE_TABLE(usb, winbond_id_table);
+
MODULE_AUTHOR(W9968CF_MODULE_AUTHOR" "W9968CF_AUTHOR_EMAIL);
-MODULE_DESCRIPTION(W9968CF_MODULE_NAME" "W9968CF_MODULE_VERSION);
+MODULE_DESCRIPTION(W9968CF_MODULE_NAME);
+MODULE_VERSION(W9968CF_MODULE_VERSION);
MODULE_LICENSE(W9968CF_MODULE_LICENSE);
MODULE_SUPPORTED_DEVICE("Video");
-static int vppmod_load = W9968CF_VPPMOD_LOAD;
+static int ovmod_load = W9968CF_OVMOD_LOAD;
static unsigned short simcams = W9968CF_SIMCAMS;
static short video_nr[]={[0 ... W9968CF_MAX_DEVICES-1] = -1}; /*-1=first free*/
static unsigned int packet_size[] = {[0 ... W9968CF_MAX_DEVICES-1] =
static unsigned int param_nv[24]; /* number of values per parameter */
-module_param(vppmod_load, bool, 0444);
-module_param(simcams, ushort, 0444);
-module_param_array(video_nr, short, param_nv[0], 0444);
-module_param_array(packet_size, uint, param_nv[1], 0444);
-module_param_array(max_buffers, ushort, param_nv[2], 0444);
-module_param_array(double_buffer, bool, param_nv[3], 0444);
-module_param_array(clamping, bool, param_nv[4], 0444);
-module_param_array(filter_type, ushort, param_nv[5], 0444);
-module_param_array(largeview, bool, param_nv[6], 0444);
-module_param_array(decompression, ushort, param_nv[7], 0444);
-module_param_array(upscaling, bool, param_nv[8], 0444);
-module_param_array(force_palette, ushort, param_nv[9], 0444);
-module_param_array(force_rgb, ushort, param_nv[10], 0444);
-module_param_array(autobright, bool, param_nv[11], 0444);
-module_param_array(autoexp, bool, param_nv[12], 0444);
-module_param_array(lightfreq, ushort, param_nv[13], 0444);
-module_param_array(bandingfilter, bool, param_nv[14], 0444);
-module_param_array(clockdiv, short, param_nv[15], 0444);
-module_param_array(backlight, bool, param_nv[16], 0444);
-module_param_array(mirror, bool, param_nv[17], 0444);
-module_param_array(monochrome, bool, param_nv[18], 0444);
-module_param_array(brightness, uint, param_nv[19], 0444);
-module_param_array(hue, uint, param_nv[20], 0444);
-module_param_array(colour, uint, param_nv[21], 0444);
-module_param_array(contrast, uint, param_nv[22], 0444);
-module_param_array(whiteness, uint, param_nv[23], 0444);
+#ifdef CONFIG_KMOD
+module_param(ovmod_load, bool, 0644);
+#endif
+module_param(simcams, ushort, 0644);
+module_param_array(video_nr, short, ¶m_nv[0], 0444);
+module_param_array(packet_size, uint, ¶m_nv[1], 0444);
+module_param_array(max_buffers, ushort, ¶m_nv[2], 0444);
+module_param_array(double_buffer, bool, ¶m_nv[3], 0444);
+module_param_array(clamping, bool, ¶m_nv[4], 0444);
+module_param_array(filter_type, ushort, ¶m_nv[5], 0444);
+module_param_array(largeview, bool, ¶m_nv[6], 0444);
+module_param_array(decompression, ushort, ¶m_nv[7], 0444);
+module_param_array(upscaling, bool, ¶m_nv[8], 0444);
+module_param_array(force_palette, ushort, ¶m_nv[9], 0444);
+module_param_array(force_rgb, ushort, ¶m_nv[10], 0444);
+module_param_array(autobright, bool, ¶m_nv[11], 0444);
+module_param_array(autoexp, bool, ¶m_nv[12], 0444);
+module_param_array(lightfreq, ushort, ¶m_nv[13], 0444);
+module_param_array(bandingfilter, bool, ¶m_nv[14], 0444);
+module_param_array(clockdiv, short, ¶m_nv[15], 0444);
+module_param_array(backlight, bool, ¶m_nv[16], 0444);
+module_param_array(mirror, bool, ¶m_nv[17], 0444);
+module_param_array(monochrome, bool, ¶m_nv[18], 0444);
+module_param_array(brightness, uint, ¶m_nv[19], 0444);
+module_param_array(hue, uint, ¶m_nv[20], 0444);
+module_param_array(colour, uint, ¶m_nv[21], 0444);
+module_param_array(contrast, uint, ¶m_nv[22], 0444);
+module_param_array(whiteness, uint, ¶m_nv[23], 0444);
#ifdef W9968CF_DEBUG
-module_param(debug, ushort, 0444);
-module_param(specific_debug, bool, 0444);
+module_param(debug, ushort, 0644);
+module_param(specific_debug, bool, 0644);
#endif
-MODULE_PARM_DESC(vppmod_load,
- "\n<0|1> Automatic 'w9968cf-vpp' module loading."
- "\n0 disable, 1 enable."
- "\nIf enabled, every time an application attempts to open a"
- "\ncamera, 'insmod' searches for the video post-processing"
- "\nmodule in the system and loads it automatically (if"
- "\npresent). The 'w9968cf-vpp' module adds extra image"
- "\nmanipulation functions to the 'w9968cf' module, like"
- "\nsoftware up-scaling,colour conversions and video decoding."
- "\nDefault value is "__MODULE_STRING(W9968CF_VPPMOD_LOAD)"."
+#ifdef CONFIG_KMOD
+MODULE_PARM_DESC(ovmod_load,
+ "\n<0|1> Automatic 'ovcamchip' module loading."
+ "\n0 disabled, 1 enabled."
+ "\nIf enabled,'insmod' searches for the required 'ovcamchip'"
+ "\nmodule in the system, according to its configuration, and"
+ "\nattempts to load that module automatically. This action is"
+ "\nperformed once as soon as the 'w9968cf' module is loaded"
+ "\ninto memory."
+ "\nDefault value is "__MODULE_STRING(W9968CF_OVMOD_LOAD)"."
"\n");
+#endif
MODULE_PARM_DESC(simcams,
"\n<n> Number of cameras allowed to stream simultaneously."
"\nn may vary from 0 to "
"\n<0|1[,...]> "
"Hardware double buffering: 0 disabled, 1 enabled."
"\nIt should be enabled if you want smooth video output: if"
- "\nyou obtain out of sync. video, disable it at all, or try"
- "\nto decrease the 'clockdiv' module paramater value."
+ "\nyou obtain out of sync. video, disable it, or try to"
+ "\ndecrease the 'clockdiv' module parameter value."
"\nDefault value is "__MODULE_STRING(W9968CF_DOUBLE_BUFFER)
" for every device."
"\n");
"\nDefault value is "__MODULE_STRING(W9968CF_FILTER_TYPE)
" for every device."
"\nThe filter is used to reduce noise and aliasing artifacts"
- "\nproduced by the CCD or CMOS sensor, and the scaling"
+ "\nproduced by the CCD or CMOS image sensor, and the scaling"
" process."
"\n");
MODULE_PARM_DESC(largeview,
" enough memory."
"\nDefault value is "__MODULE_STRING(W9968CF_UPSCALING)
" for every device."
- "\nIf 'w9968cf-vpp' is not loaded, this paramater is"
+ "\nIf 'w9968cf-vpp' is not present, this parameter is"
" set to 0."
"\n");
MODULE_PARM_DESC(decompression,
"a multiple of 16."
"\nDefault value is "__MODULE_STRING(W9968CF_DECOMPRESSION)
" for every device."
- "\nIf 'w9968cf-vpp' is not loaded, forcing decompression is "
- "\nnot allowed; in this case this paramater is set to 2."
+ "\nIf 'w9968cf-vpp' is not present, forcing decompression is "
+ "\nnot allowed; in this case this parameter is set to 2."
"\n");
MODULE_PARM_DESC(force_palette,
"\n<0"
"\n- RGB565 16 bpp - Software conversion from UYVY"
"\n- RGB24 24 bpp - Software conversion from UYVY"
"\n- RGB32 32 bpp - Software conversion from UYVY"
- "\nWhen not 0, this paramater will override 'decompression'."
+ "\nWhen not 0, this parameter will override 'decompression'."
"\nDefault value is 0 for every device."
"\nInitial palette is "
__MODULE_STRING(W9968CF_PALETTE_DECOMP_ON)"."
- "\nIf 'w9968cf-vpp' is not loaded, this paramater is"
+ "\nIf 'w9968cf-vpp' is not present, this parameter is"
" set to 9 (UYVY)."
"\n");
MODULE_PARM_DESC(force_rgb,
" for every device."
"\n");
MODULE_PARM_DESC(autobright,
- "\n<0|1[,...]> CMOS sensor automatically changes brightness:"
+ "\n<0|1[,...]> Image sensor automatically changes brightness:"
"\n 0 = no, 1 = yes"
"\nDefault value is "__MODULE_STRING(W9968CF_AUTOBRIGHT)
" for every device."
"\n");
MODULE_PARM_DESC(autoexp,
- "\n<0|1[,...]> CMOS sensor automatically changes exposure:"
+ "\n<0|1[,...]> Image sensor automatically changes exposure:"
"\n 0 = no, 1 = yes"
"\nDefault value is "__MODULE_STRING(W9968CF_AUTOEXP)
" for every device."
"Force pixel clock divisor to a specific value (for experts):"
"\n n may vary from 0 to 127."
"\n -1 for automatic value."
- "\nSee also the 'double_buffer' module paramater."
+ "\nSee also the 'double_buffer' module parameter."
"\nDefault value is "__MODULE_STRING(W9968CF_CLOCKDIV)
" for every device."
"\n");
" for every device."
"\n");
MODULE_PARM_DESC(monochrome,
- "\n<0|1[,...]> Use OV CMOS sensor as monochrome sensor:"
+ "\n<0|1[,...]> Use image sensor as monochrome sensor:"
"\n 0 = no, 1 = yes"
"\nNot all the sensors support monochrome color."
"\nDefault value is "__MODULE_STRING(W9968CF_MONOCHROME)
"\n4 = warnings"
"\n5 = called functions"
"\n6 = function internals"
- "\nLevel 5 and 6 are useful for testing only, when just "
+ "\nLevel 5 and 6 are useful for testing only, when only "
"one device is used."
"\nDefault value is "__MODULE_STRING(W9968CF_DEBUG_LEVEL)"."
"\n");
static struct file_operations w9968cf_fops;
static int w9968cf_open(struct inode*, struct file*);
static int w9968cf_release(struct inode*, struct file*);
-static ssize_t w9968cf_read(struct file*, char*, size_t, loff_t*);
static int w9968cf_mmap(struct file*, struct vm_area_struct*);
static int w9968cf_ioctl(struct inode*, struct file*, unsigned, unsigned long);
-static int w9968cf_v4l_ioctl(struct inode*, struct file*, unsigned int, void*);
+static ssize_t w9968cf_read(struct file*, char __user *, size_t, loff_t*);
+static int w9968cf_v4l_ioctl(struct inode*, struct file*, unsigned int,
+ void __user *);
/* USB-specific */
static int w9968cf_start_transfer(struct w9968cf_device*);
-static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs);
static int w9968cf_stop_transfer(struct w9968cf_device*);
static int w9968cf_write_reg(struct w9968cf_device*, u16 value, u16 index);
static int w9968cf_read_reg(struct w9968cf_device*, u16 index);
static int w9968cf_write_sb(struct w9968cf_device*, u16 value);
static int w9968cf_read_sb(struct w9968cf_device*);
static int w9968cf_upload_quantizationtables(struct w9968cf_device*);
+static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs);
/* Low-level I2C (SMBus) I/O */
static int w9968cf_smbus_start(struct w9968cf_device*);
unsigned long arg);
/* Memory management */
-static inline unsigned long kvirt_to_pa(unsigned long adr);
static void* rvmalloc(unsigned long size);
static void rvfree(void *mem, unsigned long size);
static void w9968cf_deallocate_memory(struct w9968cf_device*);
static int w9968cf_allocate_memory(struct w9968cf_device*);
-static inline unsigned long w9968cf_get_max_bufsize(struct w9968cf_device*);
-/* High-level CMOS sensor control functions */
+/* High-level image sensor control functions */
static int w9968cf_sensor_set_control(struct w9968cf_device*,int cid,int val);
static int w9968cf_sensor_get_control(struct w9968cf_device*,int cid,int *val);
-static inline int w9968cf_sensor_cmd(struct w9968cf_device*,
- unsigned int cmd, void *arg);
+static int w9968cf_sensor_cmd(struct w9968cf_device*,
+ unsigned int cmd, void *arg);
static int w9968cf_sensor_init(struct w9968cf_device*);
static int w9968cf_sensor_update_settings(struct w9968cf_device*);
static int w9968cf_sensor_get_picture(struct w9968cf_device*);
static void w9968cf_configure_camera(struct w9968cf_device*,struct usb_device*,
enum w9968cf_model_id,
const unsigned short dev_nr);
+static void w9968cf_adjust_configuration(struct w9968cf_device*);
static int w9968cf_turn_on_led(struct w9968cf_device*);
static int w9968cf_init_chip(struct w9968cf_device*);
-static int w9968cf_set_picture(struct w9968cf_device*, struct video_picture);
-static int w9968cf_set_window(struct w9968cf_device*, struct video_window);
static inline u16 w9968cf_valid_palette(u16 palette);
static inline u16 w9968cf_valid_depth(u16 palette);
static inline u8 w9968cf_need_decompression(u16 palette);
+static int w9968cf_set_picture(struct w9968cf_device*, struct video_picture);
+static int w9968cf_set_window(struct w9968cf_device*, struct video_window);
static int w9968cf_postprocess_frame(struct w9968cf_device*,
struct w9968cf_frame_t*);
static int w9968cf_adjust_window_size(struct w9968cf_device*, u16* w, u16* h);
static void w9968cf_pop_frame(struct w9968cf_device*,struct w9968cf_frame_t**);
static void w9968cf_release_resources(struct w9968cf_device*);
-/* Intermodule communication */
-static int w9968cf_vppmod_detect(void);
-static void w9968cf_vppmod_release(void);
-
-/* Pointers to registered video post-processing functions */
-static void (*w9968cf_vpp_init_decoder)(void);
-static int (*w9968cf_vpp_check_headers)(const unsigned char*,
- const unsigned long);
-static int (*w9968cf_vpp_decode)(const char*, const unsigned,
- const unsigned, const unsigned, char*);
-static void (*w9968cf_vpp_swap_yuvbytes)(void*, unsigned long);
-static void (*w9968cf_vpp_uyvy_to_rgbx)(u8*, unsigned long, u8*, u16, u8);
-static void (*w9968cf_vpp_scale_up)(u8*, u8*, u16, u16, u16, u16, u16);
-
/****************************************************************************
{ W9968CF_MOD_CLVBWGP, "Creative Labs Video Blaster WebCam Go Plus" },
/* Other cameras (having the same descriptors as Generic W996[87]CF) */
- { W9968CF_MOD_ADPA5R, "Aroma Digi Pen ADG-5000 Refurbished" },
- { W9986CF_MOD_AU, "AVerTV USB" },
+ { W9968CF_MOD_ADPVDMA, "Aroma Digi Pen VGA Dual Mode ADG-5000" },
+ { W9986CF_MOD_AAU, "AVerMedia AVerTV USB" },
{ W9968CF_MOD_CLVBWG, "Creative Labs Video Blaster WebCam Go" },
- { W9968CF_MOD_DLLDK, "Die Lebon LDC-D35A Digital Kamera" },
+ { W9968CF_MOD_LL, "Lebon LDC-035A" },
{ W9968CF_MOD_EEEMC, "Ezonics EZ-802 EZMega Cam" },
+ { W9968CF_MOD_OOE, "OmniVision OV8610-EDE" },
{ W9968CF_MOD_ODPVDMPC, "OPCOM Digi Pen VGA Dual Mode Pen Camera" },
+ { W9968CF_MOD_PDPII, "Pretec Digi Pen-II" },
+ { W9968CF_MOD_PDP480, "Pretec DigiPen-480" },
{ -1, NULL }
};
/****************************************************************************
* Memory management functions *
****************************************************************************/
-
-/* Here we want the physical address of the memory.
- This is used when initializing the contents of the area. */
-static inline unsigned long kvirt_to_pa(unsigned long adr)
-{
- unsigned long kva, ret;
-
- kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
- kva |= adr & (PAGE_SIZE-1); /* restore the offset */
- ret = __pa(kva);
- return ret;
-}
-
-
static void* rvmalloc(unsigned long size)
{
void* mem;
}
-/*--------------------------------------------------------------------------
- Return the maximum size (in bytes) of a frame buffer.
- --------------------------------------------------------------------------*/
-static inline unsigned long w9968cf_get_max_bufsize(struct w9968cf_device* cam)
-{
- u8 bpp = (w9968cf_vppmod_present) ? 4 : 2;
- return (cam->upscaling) ? W9968CF_MAX_WIDTH*W9968CF_MAX_HEIGHT*bpp :
- cam->maxwidth*cam->maxheight*bpp;
-}
-
-
/*--------------------------------------------------------------------------
Deallocate previously allocated memory.
--------------------------------------------------------------------------*/
/* Free temporary frame buffer */
if (cam->frame_tmp.buffer) {
- rvfree(cam->frame_tmp.buffer, W9968CF_HW_BUF_SIZE);
+ rvfree(cam->frame_tmp.buffer, cam->frame_tmp.size);
cam->frame_tmp.buffer = NULL;
}
/* Free helper buffer */
- if (cam->vpp_buffer) {
- rvfree(cam->vpp_buffer, w9968cf_get_max_bufsize(cam));
- cam->vpp_buffer = NULL;
+ if (cam->frame_vpp.buffer) {
+ rvfree(cam->frame_vpp.buffer, cam->frame_vpp.size);
+ cam->frame_vpp.buffer = NULL;
}
-
+
/* Free video frame buffers */
if (cam->frame[0].buffer) {
- rvfree(cam->frame[0].buffer,
- cam->nbuffers * w9968cf_get_max_bufsize(cam));
+ rvfree(cam->frame[0].buffer, cam->nbuffers*cam->frame[0].size);
cam->frame[0].buffer = NULL;
}
cam->nbuffers = 0;
- DBG(5, "Memory successfully deallocated.")
+ DBG(5, "Memory successfully deallocated")
}
--------------------------------------------------------------------------*/
static int w9968cf_allocate_memory(struct w9968cf_device* cam)
{
- const unsigned long bufsize = w9968cf_get_max_bufsize(cam);
const u16 p_size = wMaxPacketSize[cam->altsetting-1];
void* buff = NULL;
- u8 i;
+ unsigned long hw_bufsize, vpp_bufsize;
+ u8 i, bpp;
/* NOTE: Deallocation is done elsewhere in case of error */
+ /* Calculate the max amount of raw data per frame from the device */
+ hw_bufsize = cam->maxwidth*cam->maxheight*2;
+
+ /* Calculate the max buf. size needed for post-processing routines */
+ bpp = (w9968cf_vpp) ? 4 : 2;
+ if (cam->upscaling)
+ vpp_bufsize = max(W9968CF_MAX_WIDTH*W9968CF_MAX_HEIGHT*bpp,
+ cam->maxwidth*cam->maxheight*bpp);
+ else
+ vpp_bufsize = cam->maxwidth*cam->maxheight*bpp;
+
/* Allocate memory for the isochronous transfer buffers */
for (i = 0; i < W9968CF_URBS; i++) {
if (!(cam->transfer_buffer[i] =
kmalloc(W9968CF_ISO_PACKETS*p_size, GFP_KERNEL))) {
DBG(1, "Couldn't allocate memory for the isochronous "
- "transfer buffers (%d bytes).",
+ "transfer buffers (%u bytes)",
p_size * W9968CF_ISO_PACKETS)
return -ENOMEM;
}
}
/* Allocate memory for the temporary frame buffer */
- if (!(cam->frame_tmp.buffer = rvmalloc(W9968CF_HW_BUF_SIZE))) {
+ if (!(cam->frame_tmp.buffer = rvmalloc(hw_bufsize))) {
DBG(1, "Couldn't allocate memory for the temporary "
- "video frame buffer (%i bytes).", W9968CF_HW_BUF_SIZE)
+ "video frame buffer (%lu bytes)", hw_bufsize)
return -ENOMEM;
}
+ cam->frame_tmp.size = hw_bufsize;
+ cam->frame_tmp.number = -1;
/* Allocate memory for the helper buffer */
- if (w9968cf_vppmod_present) {
- if (!(cam->vpp_buffer = rvmalloc(bufsize))) {
+ if (w9968cf_vpp) {
+ if (!(cam->frame_vpp.buffer = rvmalloc(vpp_bufsize))) {
DBG(1, "Couldn't allocate memory for the helper buffer"
- " (%li bytes).", bufsize)
+ " (%lu bytes)", vpp_bufsize)
return -ENOMEM;
}
+ cam->frame_vpp.size = vpp_bufsize;
} else
- cam->vpp_buffer = NULL;
+ cam->frame_vpp.buffer = NULL;
- /* Allocate memory for video frame buffers */
+ /* Allocate memory for video frame buffers */
cam->nbuffers = cam->max_buffers;
while (cam->nbuffers >= 2) {
- if ((buff = rvmalloc(cam->nbuffers * bufsize)))
+ if ((buff = rvmalloc(cam->nbuffers * vpp_bufsize)))
break;
else
cam->nbuffers--;
}
if (!buff) {
- DBG(1, "Couldn't allocate memory for the video frame buffers.")
+ DBG(1, "Couldn't allocate memory for the video frame buffers")
cam->nbuffers = 0;
return -ENOMEM;
}
if (cam->nbuffers != cam->max_buffers)
- DBG(2, "Couldn't allocate memory for %d video frame buffers. "
- "Only memory for %d buffers has been allocated.",
+ DBG(2, "Couldn't allocate memory for %u video frame buffers. "
+ "Only memory for %u buffers has been allocated",
cam->max_buffers, cam->nbuffers)
for (i = 0; i < cam->nbuffers; i++) {
- cam->frame[i].buffer = buff + i*bufsize;
+ cam->frame[i].buffer = buff + i*vpp_bufsize;
+ cam->frame[i].size = vpp_bufsize;
+ cam->frame[i].number = i;
/* Circular list */
if (i != cam->nbuffers-1)
cam->frame[i].next = &cam->frame[i+1];
cam->frame[i].status = F_UNUSED;
}
- DBG(5, "Memory successfully allocated.")
+ DBG(5, "Memory successfully allocated")
return 0;
}
{
struct w9968cf_device* cam = (struct w9968cf_device*)urb->context;
struct w9968cf_frame_t** f;
- unsigned long maxbufsize;
unsigned int len, status;
void* pos;
u8 i;
int err = 0;
if ((!cam->streaming) || cam->disconnected) {
- DBG(4, "Got interrupt, but not streaming.")
+ DBG(4, "Got interrupt, but not streaming")
return;
}
- maxbufsize = min( (unsigned long)W9968CF_HW_BUF_SIZE,
- w9968cf_get_max_bufsize(cam) );
-
/* "(*f)" will be used instead of "cam->frame_current" */
f = &cam->frame_current;
(*f)->length = cam->frame_tmp.length;
memcpy((*f)->buffer, cam->frame_tmp.buffer,
(*f)->length);
- DBG(6, "Switched from temp. frame to frame #%zd",
- (*f) - &cam->frame[0])
+ DBG(6, "Switched from temp. frame to frame #%d",
+ (*f)->number)
}
}
if (status && len != 0) {
DBG(4, "URB failed, error in data packet "
- "(error #%d, %s).",
+ "(error #%u, %s)",
status, symbolic(urb_errlist, status))
(*f)->status = F_ERROR;
continue;
}
/* Buffer overflows shouldn't happen, however...*/
- if ((*f)->length + len > maxbufsize) {
- DBG(4, "Buffer overflow: bad data packets.")
+ if ((*f)->length + len > (*f)->size) {
+ DBG(4, "Buffer overflow: bad data packets")
(*f)->status = F_ERROR;
}
} else if ((*f)->status == F_GRABBING) { /* end of frame */
- DBG(6, "Frame #%zd successfully grabbed.",
- ((*f)==&cam->frame_tmp ? -1 : (*f)-&cam->frame[0]))
+ DBG(6, "Frame #%d successfully grabbed", (*f)->number)
if (cam->vpp_flag & VPP_DECOMPRESSION) {
- err=(*w9968cf_vpp_check_headers)((*f)->buffer,
+ err = w9968cf_vpp->check_headers((*f)->buffer,
(*f)->length);
if (err) {
DBG(4, "Skip corrupted frame: %s",
} else if ((*f)->status == F_ERROR)
(*f)->status = F_UNUSED; /* grab it again */
- PDBGG("Frame length %li | pack.#%d | pack.len. %d | state %d",
+ PDBGG("Frame length %lu | pack.#%u | pack.len. %u | state %d",
(unsigned long)(*f)->length, i, len, (*f)->status)
} /* end for */
if ((err = usb_submit_urb(urb, GFP_ATOMIC))) {
cam->misconfigured = 1;
DBG(1, "Couldn't resubmit the URB: error %d, %s",
- err, symbolic(urb_errlist, err));
+ err, symbolic(urb_errlist, err))
}
spin_unlock(&cam->urb_lock);
if (!urb) {
for (j = 0; j < i; j++)
usb_free_urb(cam->urb[j]);
- DBG(1, "Couldn't allocate the URB structures.")
+ DBG(1, "Couldn't allocate the URB structures")
return -ENOMEM;
}
if (err || (vidcapt < 0)) {
for (i = 0; i < W9968CF_URBS; i++)
usb_free_urb(cam->urb[i]);
- DBG(1, "Couldn't tell the camera to start the data transfer.")
+ DBG(1, "Couldn't tell the camera to start the data transfer")
return err;
}
cam->frame_current = &cam->frame_tmp;
if (!(cam->vpp_flag & VPP_DECOMPRESSION))
- DBG(5, "Isochronous transfer size: %li bytes/frame.",
+ DBG(5, "Isochronous transfer size: %lu bytes/frame",
(unsigned long)t_size*2)
DBG(5, "Starting the isochronous transfer...")
+ cam->streaming = 1;
+
/* Submit the URBs */
for (i = 0; i < W9968CF_URBS; i++) {
err = usb_submit_urb(cam->urb[i], GFP_KERNEL);
if (err) {
- for (j = i-1; j >= 0; j--)
- if (!usb_unlink_urb(cam->urb[j]))
- usb_free_urb(cam->urb[j]);
+ cam->streaming = 0;
+ for (j = i-1; j >= 0; j--) {
+ usb_kill_urb(cam->urb[j]);
+ usb_free_urb(cam->urb[j]);
+ }
DBG(1, "Couldn't send a transfer request to the "
- "USB core (error #%d, %s).", err,
+ "USB core (error #%d, %s)", err,
symbolic(urb_errlist, err))
+ return err;
}
}
- cam->streaming = 1;
-
return 0;
}
int err = 0;
s8 i;
+ if (!cam->streaming)
+ return 0;
+
/* This avoids race conditions with usb_submit_urb()
in the URB completition handler */
spin_lock_irqsave(&cam->urb_lock, lock_flags);
for (i = W9968CF_URBS-1; i >= 0; i--)
if (cam->urb[i]) {
- if (!usb_unlink_urb(cam->urb[i])) {
- usb_free_urb(cam->urb[i]);
- cam->urb[i] = NULL;
- }
+ usb_kill_urb(cam->urb[i]);
+ usb_free_urb(cam->urb[i]);
+ cam->urb[i] = NULL;
}
if (cam->disconnected)
}
exit:
- DBG(5, "Isochronous transfer stopped.")
+ DBG(5, "Isochronous transfer stopped")
return 0;
}
if (res < 0)
DBG(4, "Failed to write a register "
- "(value 0x%04X, index 0x%02X, error #%d, %s).",
+ "(value 0x%04X, index 0x%02X, error #%d, %s)",
value, index, res, symbolic(urb_errlist, res))
return (res >= 0) ? 0 : -1;
if (res < 0)
DBG(4, "Failed to read a register "
- "(index 0x%02X, error #%d, %s).",
+ "(index 0x%02X, error #%d, %s)",
index, res, symbolic(urb_errlist, res))
return (res >= 0) ? (int)(*buff) : -1;
if (res < 0)
DBG(4, "Failed to write the FSB registers "
- "(error #%d, %s).", res, symbolic(urb_errlist, res))
+ "(error #%d, %s)", res, symbolic(urb_errlist, res))
return (res >= 0) ? 0 : -1;
}
if (sda < 0)
err += sda;
if (sda == 1) {
- DBG(6, "Couldn't receive the ACK.")
+ DBG(6, "Couldn't receive the ACK")
err += -1;
}
if (!err)
DBG(5, "I2C write byte data done, addr.0x%04X, subaddr.0x%02X "
- "value 0x%02X.", address, subaddress, value)
+ "value 0x%02X", address, subaddress, value)
else
DBG(5, "I2C write byte data failed, addr.0x%04X, "
- "subaddr.0x%02X, value 0x%02X.",
- address, subaddress, value)
+ "subaddr.0x%02X, value 0x%02X",
+ address, subaddress, value)
return err;
}
if (!err)
DBG(5, "I2C read byte data done, addr.0x%04X, "
- "subaddr.0x%02X, value 0x%02X.",
+ "subaddr.0x%02X, value 0x%02X",
address, subaddress, *value)
else
DBG(5, "I2C read byte data failed, addr.0x%04X, "
- "subaddr.0x%02X, wrong value 0x%02X.",
+ "subaddr.0x%02X, wrong value 0x%02X",
address, subaddress, *value)
return err;
err += w9968cf_write_sb(cam, 0x0000);
if (!err)
- DBG(5, "I2C read byte done, addr.0x%04X."
- "value 0x%02X.", address, *value)
+ DBG(5, "I2C read byte done, addr.0x%04X, "
+ "value 0x%02X", address, *value)
else
- DBG(5, "I2C read byte failed, addr.0x%04X."
- "wrong value 0x%02X.", address, *value)
+ DBG(5, "I2C read byte failed, addr.0x%04X, "
+ "wrong value 0x%02X", address, *value)
return err;
}
w9968cf_i2c_adap_write_byte(struct w9968cf_device* cam,
u16 address, u8 value)
{
- DBG(4, "i2c_write_byte() is an unsupported transfer mode.")
+ DBG(4, "i2c_write_byte() is an unsupported transfer mode")
return -EINVAL;
}
static int w9968cf_i2c_attach_inform(struct i2c_client* client)
{
struct w9968cf_device* cam = i2c_get_adapdata(client->adapter);
- const char* clientname = i2c_clientname(client);
int id = client->driver->id, err = 0;
if (id == I2C_DRIVERID_OVCAMCHIP) {
}
} else {
DBG(4, "Rejected client [%s] with driver [%s]",
- clientname, client->driver->name)
+ client->name, client->driver->driver.name)
return -EINVAL;
}
DBG(5, "I2C attach client [%s] with driver [%s]",
- clientname, client->driver->name)
+ client->name, client->driver->driver.name)
return 0;
}
static int w9968cf_i2c_detach_inform(struct i2c_client* client)
{
struct w9968cf_device* cam = i2c_get_adapdata(client->adapter);
- const char* clientname = i2c_clientname(client);
- if (cam->sensor_client == client) {
+ if (cam->sensor_client == client)
cam->sensor_client = NULL;
- }
- DBG(5, "I2C detach client [%s]", clientname)
+ DBG(5, "I2C detach client [%s]", client->name)
return 0;
}
int err = 0;
static struct i2c_algorithm algo = {
- .name = "W996[87]CF algorithm",
- .id = I2C_ALGO_SMBUS,
.smbus_xfer = w9968cf_i2c_smbus_xfer,
.algo_control = w9968cf_i2c_control,
.functionality = w9968cf_i2c_func,
};
static struct i2c_adapter adap = {
- .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_W9968CF,
- .class = I2C_ADAP_CLASS_CAM_DIGITAL,
+ .id = I2C_HW_SMBUS_W9968CF,
+ .class = I2C_CLASS_CAM_DIGITAL,
.owner = THIS_MODULE,
.client_register = w9968cf_i2c_attach_inform,
.client_unregister = w9968cf_i2c_detach_inform,
err = i2c_add_adapter(&cam->i2c_adapter);
if (err)
- DBG(1, "Failed to register the I2C adapter.")
+ DBG(1, "Failed to register the I2C adapter")
else
- DBG(5, "I2C adapter registered.")
+ DBG(5, "I2C adapter registered")
return err;
}
err += w9968cf_write_reg(cam, 0x0010, 0x01); /* ..high 'beep-beep' */
if (err)
- DBG(2, "Couldn't turn on the LED.")
+ DBG(2, "Couldn't turn on the LED")
- DBG(5, "LED turned on.")
+ DBG(5, "LED turned on")
return err;
}
--------------------------------------------------------------------------*/
static int w9968cf_init_chip(struct w9968cf_device* cam)
{
+ unsigned long hw_bufsize = cam->maxwidth*cam->maxheight*2,
+ y0 = 0x0000,
+ u0 = y0 + hw_bufsize/2,
+ v0 = u0 + hw_bufsize/4,
+ y1 = v0 + hw_bufsize/4,
+ u1 = y1 + hw_bufsize/2,
+ v1 = u1 + hw_bufsize/4;
int err = 0;
err += w9968cf_write_reg(cam, 0xff00, 0x00); /* power off */
err += w9968cf_write_reg(cam, 0x405d, 0x03); /* DRAM timings */
err += w9968cf_write_reg(cam, 0x0030, 0x04); /* SDRAM timings */
- err += w9968cf_write_reg(cam, 0x0000, 0x20); /* Y frame buf.0, low */
- err += w9968cf_write_reg(cam, 0x0000, 0x21); /* Y frame buf.0, high */
- err += w9968cf_write_reg(cam, 0xb000, 0x22); /* Y frame buf.1, low */
- err += w9968cf_write_reg(cam, 0x0004, 0x23); /* Y frame buf.1, high */
- err += w9968cf_write_reg(cam, 0x5800, 0x24); /* U frame buf.0, low */
- err += w9968cf_write_reg(cam, 0x0002, 0x25); /* U frame buf.0, high */
- err += w9968cf_write_reg(cam, 0x0800, 0x26); /* U frame buf.1, low */
- err += w9968cf_write_reg(cam, 0x0007, 0x27); /* U frame buf.1, high */
- err += w9968cf_write_reg(cam, 0x8400, 0x28); /* V frame buf.0, low */
- err += w9968cf_write_reg(cam, 0x0003, 0x29); /* V frame buf.0, high */
- err += w9968cf_write_reg(cam, 0x3400, 0x2a); /* V frame buf.1, low */
- err += w9968cf_write_reg(cam, 0x0008, 0x2b); /* V frame buf.1, high */
-
- err += w9968cf_write_reg(cam, 0x6000, 0x32); /* JPEG bitstream buf 0 */
- err += w9968cf_write_reg(cam, 0x0009, 0x33); /* JPEG bitstream buf 0 */
- err += w9968cf_write_reg(cam, 0x2000, 0x34); /* JPEG bitstream buf 1 */
- err += w9968cf_write_reg(cam, 0x000d, 0x35); /* JPEG bitstream buf 1 */
+ err += w9968cf_write_reg(cam, y0 & 0xffff, 0x20); /* Y buf.0, low */
+ err += w9968cf_write_reg(cam, y0 >> 16, 0x21); /* Y buf.0, high */
+ err += w9968cf_write_reg(cam, u0 & 0xffff, 0x24); /* U buf.0, low */
+ err += w9968cf_write_reg(cam, u0 >> 16, 0x25); /* U buf.0, high */
+ err += w9968cf_write_reg(cam, v0 & 0xffff, 0x28); /* V buf.0, low */
+ err += w9968cf_write_reg(cam, v0 >> 16, 0x29); /* V buf.0, high */
+
+ err += w9968cf_write_reg(cam, y1 & 0xffff, 0x22); /* Y buf.1, low */
+ err += w9968cf_write_reg(cam, y1 >> 16, 0x23); /* Y buf.1, high */
+ err += w9968cf_write_reg(cam, u1 & 0xffff, 0x26); /* U buf.1, low */
+ err += w9968cf_write_reg(cam, u1 >> 16, 0x27); /* U buf.1, high */
+ err += w9968cf_write_reg(cam, v1 & 0xffff, 0x2a); /* V buf.1, low */
+ err += w9968cf_write_reg(cam, v1 >> 16, 0x2b); /* V buf.1, high */
+
+ err += w9968cf_write_reg(cam, y1 & 0xffff, 0x32); /* JPEG buf 0 low */
+ err += w9968cf_write_reg(cam, y1 >> 16, 0x33); /* JPEG buf 0 high */
+
+ err += w9968cf_write_reg(cam, y1 & 0xffff, 0x34); /* JPEG buf 1 low */
+ err += w9968cf_write_reg(cam, y1 >> 16, 0x35); /* JPEG bug 1 high */
err += w9968cf_write_reg(cam, 0x0000, 0x36);/* JPEG restart interval */
err += w9968cf_write_reg(cam, 0x0804, 0x37);/*JPEG VLE FIFO threshold*/
err += w9968cf_set_window(cam, cam->window);
if (err)
- DBG(1, "Chip initialization failed.")
+ DBG(1, "Chip initialization failed")
else
- DBG(5, "Chip successfully initialized.")
+ DBG(5, "Chip successfully initialized")
return err;
}
+/*--------------------------------------------------------------------------
+ Return non-zero if the palette is supported, 0 otherwise.
+ --------------------------------------------------------------------------*/
+static inline u16 w9968cf_valid_palette(u16 palette)
+{
+ u8 i = 0;
+ while (w9968cf_formatlist[i].palette != 0) {
+ if (palette == w9968cf_formatlist[i].palette)
+ return palette;
+ i++;
+ }
+ return 0;
+}
+
+
+/*--------------------------------------------------------------------------
+ Return the depth corresponding to the given palette.
+ Palette _must_ be supported !
+ --------------------------------------------------------------------------*/
+static inline u16 w9968cf_valid_depth(u16 palette)
+{
+ u8 i=0;
+ while (w9968cf_formatlist[i].palette != palette)
+ i++;
+
+ return w9968cf_formatlist[i].depth;
+}
+
+
+/*--------------------------------------------------------------------------
+ Return non-zero if the format requires decompression, 0 otherwise.
+ --------------------------------------------------------------------------*/
+static inline u8 w9968cf_need_decompression(u16 palette)
+{
+ u8 i = 0;
+ while (w9968cf_formatlist[i].palette != 0) {
+ if (palette == w9968cf_formatlist[i].palette)
+ return w9968cf_formatlist[i].compression;
+ i++;
+ }
+ return 0;
+}
+
+
/*--------------------------------------------------------------------------
Change the picture settings of the camera.
Return 0 on success, a negative number otherwise.
break;
}
- /* FIXME: 'hardware double buffer' doesn't work when compressed video
- is enabled (corrupted frames). */
+ /* NOTE: due to memory issues, it is better to disable the hardware
+ double buffering during compression */
if (cam->double_buffer && !(cam->vpp_flag & VPP_DECOMPRESSION))
reg_v |= 0x0080;
cam->hw_palette = hw_palette;
/* Settings changed, so we clear the frame buffers */
- memset(cam->frame[0].buffer, 0,
- cam->nbuffers*w9968cf_get_max_bufsize(cam));
+ memset(cam->frame[0].buffer, 0, cam->nbuffers*cam->frame[0].size);
- DBG(4, "Palette is %s, depth is %d bpp.",
+ DBG(4, "Palette is %s, depth is %u bpp",
symbolic(v4l1_plist, pict.palette), pict.depth)
return 0;
error:
- DBG(1, "Failed to change picture settings.")
+ DBG(1, "Failed to change picture settings")
return err;
}
cam->hw_height = h;
/* Settings changed, so we clear the frame buffers */
- memset(cam->frame[0].buffer, 0,
- cam->nbuffers*w9968cf_get_max_bufsize(cam));
+ memset(cam->frame[0].buffer, 0, cam->nbuffers*cam->frame[0].size);
- DBG(4, "The capture area is %dx%d, Offset (x,y)=(%d,%d).",
+ DBG(4, "The capture area is %dx%d, Offset (x,y)=(%u,%u)",
win.width, win.height, win.x, win.y)
- PDBGG("x=%d ,y=%d, w=%d, h=%d, ax=%d, ay=%d, s_win.x=%d, s_win.y=%d, "
- "cw=%d, ch=%d, win.x=%d ,win.y=%d, win.width=%d, win.height=%d",
+ PDBGG("x=%u ,y=%u, w=%u, h=%u, ax=%u, ay=%u, s_win.x=%u, s_win.y=%u, "
+ "cw=%u, ch=%u, win.x=%u, win.y=%u, win.width=%u, win.height=%u",
x, y, w, h, ax, ay, s_win.x, s_win.y, cw, ch, win.x, win.y,
win.width, win.height)
return 0;
error:
- DBG(1, "Failed to change the capture area size.")
+ DBG(1, "Failed to change the capture area size")
return err;
}
-/*--------------------------------------------------------------------------
- Return non-zero if the palette is supported, 0 otherwise.
- --------------------------------------------------------------------------*/
-static inline u16 w9968cf_valid_palette(u16 palette)
-{
- u8 i = 0;
- while (w9968cf_formatlist[i].palette != 0) {
- if (palette == w9968cf_formatlist[i].palette)
- return palette;
- i++;
- }
- return 0;
-}
-
-
-/*--------------------------------------------------------------------------
- Return the depth corresponding to the given palette.
- Palette _must_ be supported !
- --------------------------------------------------------------------------*/
-static inline u16 w9968cf_valid_depth(u16 palette)
-{
- u8 i=0;
- while (w9968cf_formatlist[i].palette != palette)
- i++;
-
- return w9968cf_formatlist[i].depth;
-}
-
-
-/*--------------------------------------------------------------------------
- Return non-zero if the format requires decompression, 0 otherwise.
- --------------------------------------------------------------------------*/
-static inline u8 w9968cf_need_decompression(u16 palette)
-{
- u8 i = 0;
- while (w9968cf_formatlist[i].palette != 0) {
- if (palette == w9968cf_formatlist[i].palette)
- return w9968cf_formatlist[i].compression;
- i++;
- }
- return 0;
-}
-
-
/*--------------------------------------------------------------------------
Adjust the asked values for window width and height.
Return 0 on success, -1 otherwise.
if ((*width < cam->minwidth) || (*height < cam->minheight))
return -ERANGE;
- maxw = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION)
- && w9968cf_vppmod_present ? W9968CF_MAX_WIDTH : cam->maxwidth;
- maxh = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION)
- && w9968cf_vppmod_present ? W9968CF_MAX_HEIGHT : cam->maxheight;
+ maxw = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) &&
+ w9968cf_vpp ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth)
+ : cam->maxwidth;
+ maxh = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) &&
+ w9968cf_vpp ? max((u16)W9968CF_MAX_HEIGHT, cam->maxheight)
+ : cam->maxheight;
if (*width > maxw)
*width = maxw;
*height &= ~15L;
}
- PDBGG("Window size adjusted w=%d, h=%d ", *width, *height)
+ PDBGG("Window size adjusted w=%u, h=%u ", *width, *height)
return 0;
}
spin_unlock_irqrestore(&cam->flist_lock, lock_flags);
- DBG(6, "Frame #%d pushed into the FIFO list. Position %d.", f_num, f)
+ DBG(6, "Frame #%u pushed into the FIFO list. Position %u", f_num, f)
}
spin_unlock(&cam->flist_lock);
- DBG(6,"Popped frame #%zd from the list.",*framep-&cam->frame[0])
+ DBG(6,"Popped frame #%d from the list", (*framep)->number)
}
w9968cf_postprocess_frame(struct w9968cf_device* cam,
struct w9968cf_frame_t* fr)
{
- void *pIn = fr->buffer, *pOut = cam->vpp_buffer, *tmp;
+ void *pIn = fr->buffer, *pOut = cam->frame_vpp.buffer, *tmp;
u16 w = cam->window.width,
h = cam->window.height,
d = cam->picture.depth,
if (cam->vpp_flag & VPP_DECOMPRESSION) {
memcpy(pOut, pIn, fr->length);
_PSWAP(pIn, pOut)
- err = (*w9968cf_vpp_decode)(pIn, fr->length, hw_w, hw_h, pOut);
- PDBGG("Compressed frame length: %li",(unsigned long)fr->length)
+ err = w9968cf_vpp->decode(pIn, fr->length, hw_w, hw_h, pOut);
+ PDBGG("Compressed frame length: %lu",(unsigned long)fr->length)
fr->length = (hw_w*hw_h*hw_d)/8;
_PSWAP(pIn, pOut)
if (err) {
DBG(4, "An error occurred while decoding the frame: "
- "%s.", symbolic(decoder_errlist, err))
+ "%s", symbolic(decoder_errlist, err))
return err;
} else
DBG(6, "Frame decoded")
}
if (cam->vpp_flag & VPP_SWAP_YUV_BYTES) {
- (*w9968cf_vpp_swap_yuvbytes)(pIn, fr->length);
- DBG(6, "Original UYVY component ordering changed.")
+ w9968cf_vpp->swap_yuvbytes(pIn, fr->length);
+ DBG(6, "Original UYVY component ordering changed")
}
if (cam->vpp_flag & VPP_UPSCALE) {
- (*w9968cf_vpp_scale_up)(pIn, pOut, hw_w, hw_h, hw_d, w, h);
+ w9968cf_vpp->scale_up(pIn, pOut, hw_w, hw_h, hw_d, w, h);
fr->length = (w*h*hw_d)/8;
_PSWAP(pIn, pOut)
- DBG(6, "Vertical up-scaling done: %d,%d,%dbpp->%d,%d",
+ DBG(6, "Vertical up-scaling done: %u,%u,%ubpp->%u,%u",
hw_w, hw_h, hw_d, w, h)
}
if (cam->vpp_flag & VPP_UYVY_TO_RGBX) {
- (*w9968cf_vpp_uyvy_to_rgbx)(pIn, fr->length, pOut, fmt, rgb);
+ w9968cf_vpp->uyvy_to_rgbx(pIn, fr->length, pOut, fmt, rgb);
fr->length = (w*h*d)/8;
_PSWAP(pIn, pOut)
- DBG(6, "UYVY-16bit to %s conversion done.",
+ DBG(6, "UYVY-16bit to %s conversion done",
symbolic(v4l1_plist, fmt))
}
if (pOut == fr->buffer)
- memcpy(fr->buffer, cam->vpp_buffer, fr->length);
+ memcpy(fr->buffer, cam->frame_vpp.buffer, fr->length);
return 0;
}
/****************************************************************************
- * CMOS sensor control routines *
+ * Image sensor control routines *
****************************************************************************/
static int
}
-static inline int
+static int
w9968cf_sensor_cmd(struct w9968cf_device* cam, unsigned int cmd, void* arg)
{
struct i2c_client* c = cam->sensor_client;
int rc = 0;
- if (c->driver->command) {
- rc = c->driver->command(cam->sensor_client, cmd, arg);
- /* The I2C driver returns -EPERM on non-supported controls */
- return (rc < 0 && rc != -EPERM) ? rc : 0;
- } else
- return -ENODEV;
+ if (!c || !c->driver || !c->driver->command)
+ return -EINVAL;
+
+ rc = c->driver->command(c, cmd, arg);
+ /* The I2C driver returns -EPERM on non-supported controls */
+ return (rc < 0 && rc != -EPERM) ? rc : 0;
}
/*--------------------------------------------------------------------------
- Update some settings of the CMOS sensor.
+ Update some settings of the image sensor.
Returns: 0 on success, a negative number otherwise.
--------------------------------------------------------------------------*/
static int w9968cf_sensor_update_settings(struct w9968cf_device* cam)
/*--------------------------------------------------------------------------
- Get some current picture settings from the CMOS sensor and update the
+ Get some current picture settings from the image sensor and update the
internal 'picture' structure of the camera.
Returns: 0 on success, a negative number otherwise.
--------------------------------------------------------------------------*/
return err;
cam->picture.hue = v;
- DBG(5, "Got picture settings from the CMOS sensor.")
+ DBG(5, "Got picture settings from the image sensor")
PDBGG("Brightness, contrast, hue, colour, whiteness are "
- "%d,%d,%d,%d,%d.", cam->picture.brightness,cam->picture.contrast,
+ "%u,%u,%u,%u,%u", cam->picture.brightness,cam->picture.contrast,
cam->picture.hue, cam->picture.colour, cam->picture.whiteness)
return 0;
/*--------------------------------------------------------------------------
- Update picture settings of the CMOS sensor.
+ Update picture settings of the image sensor.
Returns: 0 on success, a negative number otherwise.
--------------------------------------------------------------------------*/
static int
pict.contrast);
if (err)
goto fail;
- DBG(4, "Contrast changed from %d to %d.",
+ DBG(4, "Contrast changed from %u to %u",
cam->picture.contrast, pict.contrast)
cam->picture.contrast = pict.contrast;
}
pict.brightness);
if (err)
goto fail;
- DBG(4, "Brightness changed from %d to %d.",
+ DBG(4, "Brightness changed from %u to %u",
cam->picture.brightness, pict.brightness)
cam->picture.brightness = pict.brightness;
}
pict.colour);
if (err)
goto fail;
- DBG(4, "Colour changed from %d to %d.",
+ DBG(4, "Colour changed from %u to %u",
cam->picture.colour, pict.colour)
cam->picture.colour = pict.colour;
}
pict.hue);
if (err)
goto fail;
- DBG(4, "Hue changed from %d to %d.",
+ DBG(4, "Hue changed from %u to %u",
cam->picture.hue, pict.hue)
cam->picture.hue = pict.hue;
}
return 0;
fail:
- DBG(4, "Failed to change sensor picture setting.")
+ DBG(4, "Failed to change sensor picture setting")
return err;
}
****************************************************************************/
/*--------------------------------------------------------------------------
- This function is called when a supported CMOS sensor is detected.
+ This function is called when a supported image sensor is detected.
Return 0 if the initialization succeeds, a negative number otherwise.
--------------------------------------------------------------------------*/
static int w9968cf_sensor_init(struct w9968cf_device* cam)
cam->minheight = 48;
break;
default:
- DBG(1, "Not supported CMOS sensor detected for %s.",
+ DBG(1, "Not supported image sensor detected for %s",
symbolic(camlist, cam->id))
return -EINVAL;
}
case CC_OV7620:
cam->start_cropx = 287;
cam->start_cropy = 35;
- /* Seems to work around a bug in the CMOS sensor */
+ /* Seems to work around a bug in the image sensor */
cam->vs_polarity = 1;
cam->hs_polarity = 1;
break;
cam->sensor_initialized = 1;
- DBG(2, "%s CMOS sensor initialized.", symbolic(senlist, cam->sensor))
+ DBG(2, "%s image sensor initialized", symbolic(senlist, cam->sensor))
return 0;
error:
cam->sensor_initialized = 0;
cam->sensor = CC_UNKNOWN;
- DBG(1, "CMOS sensor initialization failed for %s (/dev/video%d). "
- "Try to detach and attach this device again.",
+ DBG(1, "Image sensor initialization failed for %s (/dev/video%d). "
+ "Try to detach and attach this device again",
symbolic(camlist, cam->id), cam->v4ldev->minor)
return err;
}
cam->users = 0;
cam->disconnected = 0;
- cam->usbdev = udev;
cam->id = mod_id;
cam->sensor = CC_UNKNOWN;
cam->sensor_initialized = 0;
else
cam->picture.palette = W9968CF_PALETTE_DECOMP_ON;
}
+ cam->picture.depth = w9968cf_valid_depth(cam->picture.palette);
cam->force_rgb = (force_rgb[dev_nr] == 0 || force_rgb[dev_nr] == 1)
? (u8)force_rgb[dev_nr] : W9968CF_FORCE_RGB;
cam->window.clipcount = 0;
cam->window.flags = 0;
- /* If the video post-processing module is not present, some paramaters
- must be overridden: */
- if (!w9968cf_vppmod_present) {
- if (cam->decompression == 1)
- cam->decompression = 2;
- cam->upscaling = 0;
- if (cam->picture.palette != VIDEO_PALETTE_UYVY)
- cam->force_palette = 0;
- cam->picture.palette = VIDEO_PALETTE_UYVY;
- }
-
- cam->picture.depth = w9968cf_valid_depth(cam->picture.palette);
-
- DBG(3, "%s configured with settings #%d:",
+ DBG(3, "%s configured with settings #%u:",
symbolic(camlist, cam->id), dev_nr)
- DBG(3, "- Data packet size for USB isochrnous transfer: %d bytes.",
+ DBG(3, "- Data packet size for USB isochrnous transfer: %u bytes",
wMaxPacketSize[cam->altsetting-1])
- DBG(3, "- Number of requested video frame buffers: %d",
+ DBG(3, "- Number of requested video frame buffers: %u",
cam->max_buffers)
if (cam->double_buffer)
- DBG(3, "- Hardware double buffering enabled.")
+ DBG(3, "- Hardware double buffering enabled")
else
- DBG(3, "- Hardware double buffering disabled.")
+ DBG(3, "- Hardware double buffering disabled")
if (cam->filter_type == 0)
- DBG(3, "- Video filtering disabled.")
+ DBG(3, "- Video filtering disabled")
else if (cam->filter_type == 1)
- DBG(3, "- Video filtering enabled: type 1-2-1.")
+ DBG(3, "- Video filtering enabled: type 1-2-1")
else if (cam->filter_type == 2)
- DBG(3, "- Video filtering enabled: type 2-3-6-3-2.")
+ DBG(3, "- Video filtering enabled: type 2-3-6-3-2")
if (cam->clamping)
- DBG(3, "- Video data clamping (CCIR-601 format) enabled.")
+ DBG(3, "- Video data clamping (CCIR-601 format) enabled")
else
- DBG(3, "- Video data clamping (CCIR-601 format) disabled.")
+ DBG(3, "- Video data clamping (CCIR-601 format) disabled")
if (cam->largeview)
- DBG(3, "- Large view enabled.")
+ DBG(3, "- Large view enabled")
else
- DBG(3, "- Large view disabled.")
+ DBG(3, "- Large view disabled")
if ((cam->decompression) == 0 && (!cam->force_palette))
- DBG(3, "- Decompression disabled.")
+ DBG(3, "- Decompression disabled")
else if ((cam->decompression) == 1 && (!cam->force_palette))
- DBG(3, "- Decompression forced.")
+ DBG(3, "- Decompression forced")
else if ((cam->decompression) == 2 && (!cam->force_palette))
- DBG(3, "- Decompression allowed.")
+ DBG(3, "- Decompression allowed")
if (cam->upscaling)
- DBG(3, "- Software image scaling enabled.")
+ DBG(3, "- Software image scaling enabled")
else
- DBG(3, "- Software image scaling disabled.")
+ DBG(3, "- Software image scaling disabled")
if (cam->force_palette)
- DBG(3, "- Image palette forced to %s.",
+ DBG(3, "- Image palette forced to %s",
symbolic(v4l1_plist, cam->picture.palette))
if (cam->force_rgb)
- DBG(3, "- RGB component ordering will be used instead of BGR.")
+ DBG(3, "- RGB component ordering will be used instead of BGR")
if (cam->auto_brt)
- DBG(3, "- Auto brightness enabled.")
+ DBG(3, "- Auto brightness enabled")
else
- DBG(3, "- Auto brightness disabled.")
+ DBG(3, "- Auto brightness disabled")
if (cam->auto_exp)
- DBG(3, "- Auto exposure enabled.")
+ DBG(3, "- Auto exposure enabled")
else
- DBG(3, "- Auto exposure disabled.")
+ DBG(3, "- Auto exposure disabled")
if (cam->backlight)
- DBG(3, "- Backlight exposure algorithm enabled.")
+ DBG(3, "- Backlight exposure algorithm enabled")
else
- DBG(3, "- Backlight exposure algorithm disabled.")
+ DBG(3, "- Backlight exposure algorithm disabled")
if (cam->mirror)
- DBG(3, "- Mirror enabled.")
+ DBG(3, "- Mirror enabled")
else
- DBG(3, "- Mirror disabled.")
+ DBG(3, "- Mirror disabled")
if (cam->bandfilt)
- DBG(3, "- Banding filter enabled.")
+ DBG(3, "- Banding filter enabled")
else
- DBG(3, "- Banding filter disabled.")
+ DBG(3, "- Banding filter disabled")
- DBG(3, "- Power lighting frequency: %d", cam->lightfreq)
+ DBG(3, "- Power lighting frequency: %u", cam->lightfreq)
if (cam->clockdiv == -1)
- DBG(3, "- Automatic clock divisor enabled.")
+ DBG(3, "- Automatic clock divisor enabled")
else
DBG(3, "- Clock divisor: %d", cam->clockdiv)
if (cam->monochrome)
- DBG(3, "- CMOS sensor used as monochrome.")
+ DBG(3, "- Image sensor used as monochrome")
else
- DBG(3, "- CMOS sensor not used as monochrome.")
+ DBG(3, "- Image sensor not used as monochrome")
+}
+
+
+/*--------------------------------------------------------------------------
+ If the video post-processing module is not loaded, some parameters
+ must be overridden.
+ --------------------------------------------------------------------------*/
+static void w9968cf_adjust_configuration(struct w9968cf_device* cam)
+{
+ if (!w9968cf_vpp) {
+ if (cam->decompression == 1) {
+ cam->decompression = 2;
+ DBG(2, "Video post-processing module not found: "
+ "'decompression' parameter forced to 2")
+ }
+ if (cam->upscaling) {
+ cam->upscaling = 0;
+ DBG(2, "Video post-processing module not found: "
+ "'upscaling' parameter forced to 0")
+ }
+ if (cam->picture.palette != VIDEO_PALETTE_UYVY) {
+ cam->force_palette = 0;
+ DBG(2, "Video post-processing module not found: "
+ "'force_palette' parameter forced to 0")
+ }
+ cam->picture.palette = VIDEO_PALETTE_UYVY;
+ cam->picture.depth = w9968cf_valid_depth(cam->picture.palette);
+ }
}
kfree(cam->data_buffer);
up(&w9968cf_devlist_sem);
-
- DBG(5, "Resources released.")
}
struct w9968cf_device* cam;
int err;
+ /* This the only safe way to prevent race conditions with disconnect */
+ if (!down_read_trylock(&w9968cf_disconnect))
+ return -ERESTARTSYS;
+
cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp));
down(&cam->dev_sem);
if (cam->sensor == CC_UNKNOWN) {
- DBG(2, "No supported CMOS sensor has been detected by the "
+ DBG(2, "No supported image sensor has been detected by the "
"'ovcamchip' module for the %s (/dev/video%d). Make "
- "sure it is loaded *before* the 'w9968cf' module.",
+ "sure it is loaded *before* (re)connecting the camera.",
symbolic(camlist, cam->id), cam->v4ldev->minor)
up(&cam->dev_sem);
+ up_read(&w9968cf_disconnect);
return -ENODEV;
}
if (cam->users) {
- DBG(2, "%s (/dev/video%d) has been already occupied by '%s'.",
+ DBG(2, "%s (/dev/video%d) has been already occupied by '%s'",
symbolic(camlist, cam->id),cam->v4ldev->minor,cam->command)
if ((filp->f_flags & O_NONBLOCK)||(filp->f_flags & O_NDELAY)) {
up(&cam->dev_sem);
+ up_read(&w9968cf_disconnect);
return -EWOULDBLOCK;
}
-retry:
up(&cam->dev_sem);
- err = wait_event_interruptible(cam->open, cam->disconnected ||
- (cam->users == 0));
- if (err)
+ err = wait_event_interruptible_exclusive(cam->open,
+ cam->disconnected ||
+ !cam->users);
+ if (err) {
+ up_read(&w9968cf_disconnect);
return err;
- if (cam->disconnected)
+ }
+ if (cam->disconnected) {
+ up_read(&w9968cf_disconnect);
return -ENODEV;
+ }
down(&cam->dev_sem);
- /*recheck - there may be several waiters */
- if (cam->users)
- goto retry;
}
DBG(5, "Opening '%s', /dev/video%d ...",
cam->streaming = 0;
cam->misconfigured = 0;
- if (!w9968cf_vppmod_present)
- w9968cf_vppmod_detect();
+ w9968cf_adjust_configuration(cam);
if ((err = w9968cf_allocate_memory(cam)))
goto deallocate_memory;
init_waitqueue_head(&cam->wait_queue);
+ DBG(5, "Video device is open")
+
up(&cam->dev_sem);
+ up_read(&w9968cf_disconnect);
- DBG(5, "Video device is open.")
return 0;
deallocate_memory:
w9968cf_deallocate_memory(cam);
- DBG(2, "Failed to open the video device.")
+ DBG(2, "Failed to open the video device")
up(&cam->dev_sem);
+ up_read(&w9968cf_disconnect);
return err;
}
cam->users--;
w9968cf_deallocate_memory(cam);
+ wake_up_interruptible_nr(&cam->open, 1);
- wake_up_interruptible(&cam->open);
-
- DBG(5, "Video device closed.")
+ DBG(5, "Video device closed")
up(&cam->dev_sem);
return 0;
}
static ssize_t
-w9968cf_read(struct file* filp, char* buf, size_t count, loff_t* f_pos)
+w9968cf_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
{
struct w9968cf_device* cam;
struct w9968cf_frame_t* fr;
return -ERESTARTSYS;
if (cam->disconnected) {
- DBG(2, "Device not present.")
+ DBG(2, "Device not present")
up(&cam->fileop_sem);
return -ENODEV;
}
fr = (cam->frame[0].status == F_READY) ? &cam->frame[0]:&cam->frame[1];
- if (w9968cf_vppmod_present)
+ if (w9968cf_vpp)
w9968cf_postprocess_frame(cam, fr);
if (count > fr->length)
fr->status = F_UNUSED;
- DBG(5, "%zd bytes read.", count)
+ DBG(5, "%zu bytes read", count)
up(&cam->fileop_sem);
return count;
struct w9968cf_device* cam = (struct w9968cf_device*)
video_get_drvdata(video_devdata(filp));
unsigned long vsize = vma->vm_end - vma->vm_start,
- psize = cam->nbuffers * w9968cf_get_max_bufsize(cam),
+ psize = cam->nbuffers * cam->frame[0].size,
start = vma->vm_start,
pos = (unsigned long)cam->frame[0].buffer,
page;
if (cam->disconnected) {
- DBG(2, "Device not present.")
+ DBG(2, "Device not present")
return -ENODEV;
}
if (cam->misconfigured) {
- DBG(2, "The camera is misconfigured. Close and open it again.")
+ DBG(2, "The camera is misconfigured. Close and open it again")
return -EIO;
}
- PDBGG("mmapping %li bytes...", vsize)
+ PDBGG("mmapping %lu bytes...", vsize)
- if (vsize > psize - (vma->vm_pgoff << PAGE_SHIFT))
- return -EAGAIN;
+ if (vsize > psize - (vma->vm_pgoff << PAGE_SHIFT))
+ return -EINVAL;
while (vsize > 0) {
- page = kvirt_to_pa(pos) + vma->vm_pgoff;
- if (remap_page_range(vma, start, page, PAGE_SIZE,
- vma->vm_page_prot))
+ page = vmalloc_to_pfn((void *)pos);
+ if (remap_pfn_range(vma, start, page + vma->vm_pgoff,
+ PAGE_SIZE, vma->vm_page_prot))
return -EAGAIN;
start += PAGE_SIZE;
pos += PAGE_SIZE;
- vsize = (vsize > PAGE_SIZE) ? vsize-PAGE_SIZE : 0;
+ vsize -= PAGE_SIZE;
}
- DBG(5, "mmap method successfully called.")
+ DBG(5, "mmap method successfully called")
return 0;
}
return -ERESTARTSYS;
if (cam->disconnected) {
- DBG(2, "Device not present.")
+ DBG(2, "Device not present")
up(&cam->fileop_sem);
return -ENODEV;
}
return -EIO;
}
- err = w9968cf_v4l_ioctl(inode, filp, cmd, (void* )arg);
+ err = w9968cf_v4l_ioctl(inode, filp, cmd, (void __user *)arg);
up(&cam->fileop_sem);
return err;
}
-static int
-w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
- unsigned int cmd, void* arg)
+static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
+ unsigned int cmd, void __user * arg)
{
struct w9968cf_device* cam;
const char* v4l1_ioctls[] = {
};
#define V4L1_IOCTL(cmd) \
- ((_IOC_NR((cmd)) < sizeof(v4l1_ioctls)/sizeof(char*)) ? \
+ ((_IOC_NR((cmd)) < ARRAY_SIZE(v4l1_ioctls)) ? \
v4l1_ioctls[_IOC_NR((cmd))] : "?")
cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp));
};
sprintf(cap.name, "W996[87]CF USB Camera #%d",
cam->v4ldev->minor);
- cap.maxwidth = (cam->upscaling && w9968cf_vppmod_present)
- ? W9968CF_MAX_WIDTH : cam->maxwidth;
- cap.maxheight = (cam->upscaling && w9968cf_vppmod_present)
- ? W9968CF_MAX_HEIGHT : cam->maxheight;
+ cap.maxwidth = (cam->upscaling && w9968cf_vpp)
+ ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth)
+ : cam->maxwidth;
+ cap.maxheight = (cam->upscaling && w9968cf_vpp)
+ ? max((u16)W9968CF_MAX_HEIGHT, cam->maxheight)
+ : cam->maxheight;
if (copy_to_user(arg, &cap, sizeof(cap)))
return -EFAULT;
- DBG(5, "VIDIOCGCAP successfully called.")
+ DBG(5, "VIDIOCGCAP successfully called")
return 0;
}
if (copy_to_user(arg, &chan, sizeof(chan)))
return -EFAULT;
- DBG(5, "VIDIOCGCHAN successfully called.")
+ DBG(5, "VIDIOCGCHAN successfully called")
return 0;
}
if (chan.channel != 0)
return -EINVAL;
- DBG(5, "VIDIOCSCHAN successfully called.")
+ DBG(5, "VIDIOCSCHAN successfully called")
return 0;
}
if (copy_to_user(arg, &cam->picture, sizeof(cam->picture)))
return -EFAULT;
- DBG(5, "VIDIOCGPICT successfully called.")
+ DBG(5, "VIDIOCGPICT successfully called")
return 0;
}
if (copy_from_user(&pict, arg, sizeof(pict)))
return -EFAULT;
- if ( (cam->force_palette || !w9968cf_vppmod_present)
+ if ( (cam->force_palette || !w9968cf_vpp)
&& pict.palette != cam->picture.palette ) {
- DBG(4, "Palette %s rejected. Only %s is allowed.",
+ DBG(4, "Palette %s rejected: only %s is allowed",
symbolic(v4l1_plist, pict.palette),
symbolic(v4l1_plist, cam->picture.palette))
return -EINVAL;
}
if (!w9968cf_valid_palette(pict.palette)) {
- DBG(4, "Palette %s not supported. VIDIOCSPICT failed.",
+ DBG(4, "Palette %s not supported. VIDIOCSPICT failed",
symbolic(v4l1_plist, pict.palette))
return -EINVAL;
}
if (cam->decompression == 0) {
if (w9968cf_need_decompression(pict.palette)) {
DBG(4, "Decompression disabled: palette %s is not "
- "allowed. VIDIOCSPICT failed.",
+ "allowed. VIDIOCSPICT failed",
symbolic(v4l1_plist, pict.palette))
return -EINVAL;
}
} else if (cam->decompression == 1) {
if (!w9968cf_need_decompression(pict.palette)) {
DBG(4, "Decompression forced: palette %s is not "
- "allowed. VIDIOCSPICT failed.",
+ "allowed. VIDIOCSPICT failed",
symbolic(v4l1_plist, pict.palette))
return -EINVAL;
}
}
if (pict.depth != w9968cf_valid_depth(pict.palette)) {
- DBG(4, "Requested depth %d bpp is not valid for %s "
- "palette: ignored and changed to %d bpp.",
+ DBG(4, "Requested depth %u bpp is not valid for %s "
+ "palette: ignored and changed to %u bpp",
pict.depth, symbolic(v4l1_plist, pict.palette),
w9968cf_valid_depth(pict.palette))
pict.depth = w9968cf_valid_depth(pict.palette);
return -EIO;
- DBG(5, "VIDIOCSPICT successfully called.")
+ DBG(5, "VIDIOCSPICT successfully called")
return 0;
}
if (copy_from_user(&win, arg, sizeof(win)))
return -EFAULT;
- DBG(6, "VIDIOCSWIN called: clipcount=%d, flags=%d, "
- "x=%d, y=%d, %dx%d", win.clipcount, win.flags,
+ DBG(6, "VIDIOCSWIN called: clipcount=%d, flags=%u, "
+ "x=%u, y=%u, %ux%u", win.clipcount, win.flags,
win.x, win.y, win.width, win.height)
if (win.clipcount != 0 || win.flags != 0)
if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width,
(u16*)&win.height))) {
- DBG(4, "Resolution not supported (%dx%d)."
- "VIDIOCSWIN failed.", win.width, win.height)
+ DBG(4, "Resolution not supported (%ux%u). "
+ "VIDIOCSWIN failed", win.width, win.height)
return err;
}
if (copy_to_user(arg,&cam->window,sizeof(struct video_window)))
return -EFAULT;
- DBG(5, "VIDIOCGWIN successfully called.")
+ DBG(5, "VIDIOCGWIN successfully called")
return 0;
}
struct video_mbuf mbuf;
u8 i;
- mbuf.size = cam->nbuffers * w9968cf_get_max_bufsize(cam);
+ mbuf.size = cam->nbuffers * cam->frame[0].size;
mbuf.frames = cam->nbuffers;
for (i = 0; i < cam->nbuffers; i++)
mbuf.offsets[i] = (unsigned long)cam->frame[i].buffer -
if (copy_to_user(arg, &mbuf, sizeof(mbuf)))
return -EFAULT;
- DBG(5, "VIDIOCGMBUF successfully called.")
+ DBG(5, "VIDIOCGMBUF successfully called")
return 0;
}
if (copy_from_user(&mmap, arg, sizeof(mmap)))
return -EFAULT;
- DBG(6, "VIDIOCMCAPTURE called: frame #%d, format=%s, %dx%d",
+ DBG(6, "VIDIOCMCAPTURE called: frame #%u, format=%s, %dx%d",
mmap.frame, symbolic(v4l1_plist, mmap.format),
mmap.width, mmap.height)
if (mmap.frame >= cam->nbuffers) {
- DBG(4, "Invalid frame number (%d). "
- "VIDIOCMCAPTURE failed.", mmap.frame)
+ DBG(4, "Invalid frame number (%u). "
+ "VIDIOCMCAPTURE failed", mmap.frame)
return -EINVAL;
}
if (mmap.format!=cam->picture.palette &&
- (cam->force_palette || !w9968cf_vppmod_present)) {
- DBG(4, "Palette %s rejected. Only %s is allowed.",
+ (cam->force_palette || !w9968cf_vpp)) {
+ DBG(4, "Palette %s rejected: only %s is allowed",
symbolic(v4l1_plist, mmap.format),
symbolic(v4l1_plist, cam->picture.palette))
return -EINVAL;
if (!w9968cf_valid_palette(mmap.format)) {
DBG(4, "Palette %s not supported. "
- "VIDIOCMCAPTURE failed.",
+ "VIDIOCMCAPTURE failed",
symbolic(v4l1_plist, mmap.format))
return -EINVAL;
}
if (cam->decompression == 0) {
if (w9968cf_need_decompression(mmap.format)) {
DBG(4, "Decompression disabled: palette %s is not "
- "allowed. VIDIOCSPICT failed.",
+ "allowed. VIDIOCSPICT failed",
symbolic(v4l1_plist, mmap.format))
return -EINVAL;
}
} else if (cam->decompression == 1) {
if (!w9968cf_need_decompression(mmap.format)) {
DBG(4, "Decompression forced: palette %s is not "
- "allowed. VIDIOCSPICT failed.",
+ "allowed. VIDIOCSPICT failed",
symbolic(v4l1_plist, mmap.format))
return -EINVAL;
}
if ((err = w9968cf_adjust_window_size(cam, (u16*)&mmap.width,
(u16*)&mmap.height))) {
DBG(4, "Resolution not supported (%dx%d). "
- "VIDIOCMCAPTURE failed.",
+ "VIDIOCMCAPTURE failed",
mmap.width, mmap.height)
return err;
}
if(*cam->requested_frame
|| cam->frame_current->queued) {
DBG(6, "VIDIOCMCAPTURE. Change settings for "
- "frame #%d: %dx%d, format %s. Wait...",
+ "frame #%u: %dx%d, format %s. Wait...",
mmap.frame, mmap.width, mmap.height,
symbolic(v4l1_plist, mmap.format))
err = wait_event_interruptible
} else if (fr->queued) {
- DBG(6, "Wait until frame #%d is free.", mmap.frame)
+ DBG(6, "Wait until frame #%u is free", mmap.frame)
err = wait_event_interruptible(cam->wait_queue,
cam->disconnected ||
}
w9968cf_push_frame(cam, mmap.frame);
- DBG(5, "VIDIOCMCAPTURE(%d): successfully called.", mmap.frame)
+ DBG(5, "VIDIOCMCAPTURE(%u): successfully called", mmap.frame)
return 0;
}
return -EFAULT;
if (f_num >= cam->nbuffers) {
- DBG(4, "Invalid frame number (%d). "
- "VIDIOCMCAPTURE failed.", f_num)
+ DBG(4, "Invalid frame number (%u). "
+ "VIDIOCMCAPTURE failed", f_num)
return -EINVAL;
}
- DBG(6, "VIDIOCSYNC called for frame #%d", f_num)
+ DBG(6, "VIDIOCSYNC called for frame #%u", f_num)
fr = &cam->frame[f_num];
switch (fr->status) {
case F_UNUSED:
if (!fr->queued) {
- DBG(4, "VIDIOSYNC: Frame #%d not requested!",
+ DBG(4, "VIDIOSYNC: Frame #%u not requested!",
f_num)
return -EFAULT;
}
break;
}
- if (w9968cf_vppmod_present)
+ if (w9968cf_vpp)
w9968cf_postprocess_frame(cam, fr);
fr->status = F_UNUSED;
- DBG(5, "VIDIOCSYNC(%d) successfully called.", f_num)
+ DBG(5, "VIDIOCSYNC(%u) successfully called", f_num)
return 0;
}
if (copy_to_user(arg, &unit, sizeof(unit)))
return -EFAULT;
- DBG(5, "VIDIOCGUNIT successfully called.")
+ DBG(5, "VIDIOCGUNIT successfully called")
return 0;
}
if (clear_user(arg, sizeof(struct video_buffer)))
return -EFAULT;
- DBG(5, "VIDIOCGFBUF successfully called.")
+ DBG(5, "VIDIOCGFBUF successfully called")
return 0;
}
if (copy_to_user(arg, &tuner, sizeof(tuner)))
return -EFAULT;
- DBG(5, "VIDIOCGTUNER successfully called.")
+ DBG(5, "VIDIOCGTUNER successfully called")
return 0;
}
if (tuner.mode != VIDEO_MODE_AUTO)
return -EINVAL;
- DBG(5, "VIDIOCSTUNER successfully called.")
+ DBG(5, "VIDIOCSTUNER successfully called")
return 0;
}
"(type 0x%01X, "
"n. 0x%01X, "
"dir. 0x%01X, "
- "size 0x%02X).",
+ "size 0x%02X)",
V4L1_IOCTL(cmd),
_IOC_TYPE(cmd),_IOC_NR(cmd),_IOC_DIR(cmd),_IOC_SIZE(cmd))
"type 0x%01X, "
"n. 0x%01X, "
"dir. 0x%01X, "
- "size 0x%02X.",
+ "size 0x%02X",
V4L1_IOCTL(cmd),
_IOC_TYPE(cmd),_IOC_NR(cmd),_IOC_DIR(cmd),_IOC_SIZE(cmd))
.release = w9968cf_release,
.read = w9968cf_read,
.ioctl = w9968cf_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.mmap = w9968cf_mmap,
.llseek = no_llseek,
};
u8 sc = 0; /* number of simultaneous cameras */
static unsigned short dev_nr = 0; /* we are handling device number n */
- if (udev->descriptor.idVendor == winbond_id_table[0].idVendor &&
- udev->descriptor.idProduct == winbond_id_table[0].idProduct)
+ if (le16_to_cpu(udev->descriptor.idVendor) == winbond_id_table[0].idVendor &&
+ le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[0].idProduct)
mod_id = W9968CF_MOD_CLVBWGP; /* see camlist[] table */
-
- else if (udev->descriptor.idVendor == winbond_id_table[1].idVendor &&
- udev->descriptor.idProduct == winbond_id_table[1].idProduct)
+ else if (le16_to_cpu(udev->descriptor.idVendor) == winbond_id_table[1].idVendor &&
+ le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[1].idProduct)
mod_id = W9968CF_MOD_GENERIC; /* see camlist[] table */
-
else
return -ENODEV;
- DBG(2, "%s detected.", symbolic(camlist, mod_id))
+ cam = (struct w9968cf_device*)
+ kmalloc(sizeof(struct w9968cf_device), GFP_KERNEL);
+ if (!cam)
+ return -ENOMEM;
+
+ memset(cam, 0, sizeof(*cam));
+
+ init_MUTEX(&cam->dev_sem);
+ down(&cam->dev_sem);
+
+ cam->usbdev = udev;
+ /* NOTE: a local copy is used to avoid possible race conditions */
+ memcpy(&cam->dev, &udev->dev, sizeof(struct device));
+
+ DBG(2, "%s detected", symbolic(camlist, mod_id))
if (simcams > W9968CF_MAX_DEVICES)
simcams = W9968CF_SIMCAMS;
if (sc >= simcams) {
DBG(2, "Device rejected: too many connected cameras "
- "(max. %d)", simcams)
- return -EPERM;
- }
-
- cam = (struct w9968cf_device*)
- kmalloc(sizeof(struct w9968cf_device), GFP_KERNEL);
-
- if (!cam) {
- DBG(1, "Couldn't allocate %zd bytes of kernel memory.",
- sizeof(struct w9968cf_device))
- err = -ENOMEM;
+ "(max. %u)", simcams)
+ err = -EPERM;
goto fail;
}
- memset(cam, 0, sizeof(*cam));
- init_MUTEX(&cam->dev_sem);
- down(&cam->dev_sem);
/* Allocate 2 bytes of memory for camera control USB transfers */
- if (!(cam->control_buffer = (u16*)kmalloc(2, GFP_KERNEL))) {
- DBG(1,"Couldn't allocate memory for camera control transfers.")
+ if (!(cam->control_buffer = kmalloc(2, GFP_KERNEL))) {
+ DBG(1,"Couldn't allocate memory for camera control transfers")
err = -ENOMEM;
goto fail;
}
memset(cam->control_buffer, 0, 2);
/* Allocate 8 bytes of memory for USB data transfers to the FSB */
- if (!(cam->data_buffer = (u16*)kmalloc(8, GFP_KERNEL))) {
+ if (!(cam->data_buffer = kmalloc(8, GFP_KERNEL))) {
DBG(1, "Couldn't allocate memory for data "
- "transfers to the FSB.")
+ "transfers to the FSB")
err = -ENOMEM;
goto fail;
}
/* Register the V4L device */
cam->v4ldev = video_device_alloc();
if (!cam->v4ldev) {
- DBG(1, "Could not allocate memory for a V4L structure.")
+ DBG(1, "Could not allocate memory for a V4L structure")
err = -ENOMEM;
goto fail;
}
cam->v4ldev->minor = video_nr[dev_nr];
cam->v4ldev->release = video_device_release;
video_set_drvdata(cam->v4ldev, cam);
+ cam->v4ldev->dev = &cam->dev;
err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
video_nr[dev_nr]);
if (err) {
- DBG(1, "V4L device registration failed.")
+ DBG(1, "V4L device registration failed")
if (err == -ENFILE && video_nr[dev_nr] == -1)
- DBG(2, "Couldn't find a free /dev/videoX node.")
+ DBG(2, "Couldn't find a free /dev/videoX node")
video_nr[dev_nr] = -1;
dev_nr = (dev_nr < W9968CF_MAX_DEVICES-1) ? dev_nr+1 : 0;
goto fail;
}
- DBG(2, "V4L device registered as /dev/video%d.", cam->v4ldev->minor)
+ DBG(2, "V4L device registered as /dev/video%d", cam->v4ldev->minor)
/* Set some basic constants */
w9968cf_configure_camera(cam, udev, mod_id, dev_nr);
w9968cf_i2c_init(cam);
- up(&cam->dev_sem);
-
usb_set_intfdata(intf, cam);
+ up(&cam->dev_sem);
return 0;
fail: /* Free unused memory */
- if (cam) {
- if (cam->control_buffer)
- kfree(cam->control_buffer);
- if (cam->data_buffer)
- kfree(cam->data_buffer);
- if (cam->v4ldev)
- video_device_release(cam->v4ldev);
- up(&cam->dev_sem);
- kfree(cam);
- }
+ kfree(cam->control_buffer);
+ kfree(cam->data_buffer);
+ if (cam->v4ldev)
+ video_device_release(cam->v4ldev);
+ up(&cam->dev_sem);
+ kfree(cam);
return err;
}
struct w9968cf_device* cam =
(struct w9968cf_device*)usb_get_intfdata(intf);
+ down_write(&w9968cf_disconnect);
+
if (cam) {
/* Prevent concurrent accesses to data */
down(&cam->dev_sem);
- cam->streaming = 0;
cam->disconnected = 1;
DBG(2, "Disconnecting %s...", symbolic(camlist, cam->id))
- if (waitqueue_active(&cam->open))
- wake_up_interruptible(&cam->open);
+ wake_up_interruptible_all(&cam->open);
if (cam->users) {
DBG(2, "The device is open (/dev/video%d)! "
"Process name: %s. Deregistration and memory "
"deallocation are deferred on close.",
cam->v4ldev->minor, cam->command)
-
cam->misconfigured = 1;
-
- if (waitqueue_active(&cam->wait_queue))
- wake_up_interruptible(&cam->wait_queue);
+ w9968cf_stop_transfer(cam);
+ wake_up_interruptible(&cam->wait_queue);
} else
w9968cf_release_resources(cam);
kfree(cam);
}
- usb_set_intfdata(intf, NULL);
+ up_write(&w9968cf_disconnect);
}
static struct usb_driver w9968cf_usb_driver = {
- .owner = THIS_MODULE,
.name = "w9968cf",
.id_table = winbond_id_table,
.probe = w9968cf_usb_probe,
* Module init, exit and intermodule communication *
****************************************************************************/
-static int w9968cf_vppmod_detect(void)
-{
- w9968cf_vpp_init_decoder = inter_module_get("w9968cf_init_decoder");
-
- if (!w9968cf_vpp_init_decoder) {
- if (vppmod_load)
- w9968cf_vpp_init_decoder = inter_module_get_request
- ( "w9968cf_init_decoder",
- "w9968cf-vpp" );
- if (!w9968cf_vpp_init_decoder) {
- w9968cf_vppmod_present = 0;
- DBG(4, "Video post-processing module not detected.")
- return -ENODEV;
- }
- }
-
- w9968cf_vpp_check_headers = inter_module_get("w9968cf_check_headers");
- w9968cf_vpp_decode = inter_module_get("w9968cf_decode");
- w9968cf_vpp_swap_yuvbytes = inter_module_get("w9968cf_swap_yuvbytes");
- w9968cf_vpp_uyvy_to_rgbx = inter_module_get("w9968cf_uyvy_to_rgbx");
- w9968cf_vpp_scale_up = inter_module_get("w9968cf_scale_up");
-
- w9968cf_vppmod_present = 1;
-
- /* Initialization */
- (*w9968cf_vpp_init_decoder)();
-
- DBG(2, "Video post-processing module detected.")
- return 0;
-}
-
-
-static void w9968cf_vppmod_release(void)
-{
- inter_module_put("w9968cf_init_decoder");
- inter_module_put("w9968cf_check_headers");
- inter_module_put("w9968cf_decode");
- inter_module_put("w9968cf_swap_yuvbytes");
- inter_module_put("w9968cf_uyvy_to_rgbx");
- inter_module_put("w9968cf_scale_up");
-
- DBG(2, "Video post-processing module released.")
-}
-
-
static int __init w9968cf_module_init(void)
{
int err;
- DBG(2, W9968CF_MODULE_NAME" "W9968CF_MODULE_VERSION)
- DBG(3, W9968CF_MODULE_AUTHOR)
-
- init_MUTEX(&w9968cf_devlist_sem);
+ KDBG(2, W9968CF_MODULE_NAME" "W9968CF_MODULE_VERSION)
+ KDBG(3, W9968CF_MODULE_AUTHOR)
- w9968cf_vppmod_detect();
+ if (ovmod_load)
+ request_module("ovcamchip");
- if ((err = usb_register(&w9968cf_usb_driver))) {
- if (w9968cf_vppmod_present)
- w9968cf_vppmod_release();
+ if ((err = usb_register(&w9968cf_usb_driver)))
return err;
- }
return 0;
}
/* w9968cf_usb_disconnect() will be called */
usb_deregister(&w9968cf_usb_driver);
- if (w9968cf_vppmod_present)
- w9968cf_vppmod_release();
-
- DBG(2, W9968CF_MODULE_NAME" deregistered.")
+ KDBG(2, W9968CF_MODULE_NAME" deregistered")
}
module_init(w9968cf_module_init);
module_exit(w9968cf_module_exit);
+