// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Connexant Cx11646 library
* Copyright ( C ) 2004 Michel Xhaard mxhaard @ magic . fr
*
* V4L2 by Jean - Francois Moine < http : //moinejf.free.fr>
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define MODULE_NAME "conex"
#include "gspca.h"
#define CONEX_CAM 1 /* special JPEG header */
#include "jpeg.h"
MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>" );
MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver" );
MODULE_LICENSE("GPL" );
#define QUALITY 50
/* specific webcam descriptor */
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
struct v4l2_ctrl *brightness;
struct v4l2_ctrl *contrast;
struct v4l2_ctrl *sat;
u8 jpeg_hdr[JPEG_HDR_SZ];
};
static const struct v4l2_pix_format vga_mode[] = {
{176 , 144 , V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline = 176 ,
.sizeimage = 176 * 144 * 3 / 8 + 590 ,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = 3 },
{320 , 240 , V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline = 320 ,
.sizeimage = 320 * 240 * 3 / 8 + 590 ,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = 2 },
{352 , 288 , V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline = 352 ,
.sizeimage = 352 * 288 * 3 / 8 + 590 ,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = 1 },
{640 , 480 , V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline = 640 ,
.sizeimage = 640 * 480 * 3 / 8 + 590 ,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = 0 },
};
/* the read bytes are found in gspca_dev->usb_buf */
static void reg_r(struct gspca_dev *gspca_dev,
__u16 index,
__u16 len)
{
struct usb_device *dev = gspca_dev->dev;
if (len > USB_BUF_SZ) {
gspca_err(gspca_dev, "reg_r: buffer overflow\n" );
return ;
}
usb_control_msg(dev,
usb_rcvctrlpipe(dev, 0 ),
0 ,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0 ,
index, gspca_dev->usb_buf, len,
500 );
gspca_dbg(gspca_dev, D_USBI, "reg read [%02x] -> %02x ..\n" ,
index, gspca_dev->usb_buf[0 ]);
}
/* the bytes to write are in gspca_dev->usb_buf */
static void reg_w_val(struct gspca_dev *gspca_dev,
__u16 index,
__u8 val)
{
struct usb_device *dev = gspca_dev->dev;
gspca_dev->usb_buf[0 ] = val;
usb_control_msg(dev,
usb_sndctrlpipe(dev, 0 ),
0 ,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0 ,
index, gspca_dev->usb_buf, 1 , 500 );
}
static void reg_w(struct gspca_dev *gspca_dev,
__u16 index,
const __u8 *buffer,
__u16 len)
{
struct usb_device *dev = gspca_dev->dev;
if (len > USB_BUF_SZ) {
gspca_err(gspca_dev, "reg_w: buffer overflow\n" );
return ;
}
gspca_dbg(gspca_dev, D_USBO, "reg write [%02x] = %02x..\n" ,
index, *buffer);
memcpy(gspca_dev->usb_buf, buffer, len);
usb_control_msg(dev,
usb_sndctrlpipe(dev, 0 ),
0 ,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0 ,
index, gspca_dev->usb_buf, len, 500 );
}
static const __u8 cx_sensor_init[][4 ] = {
{0 x88, 0 x11, 0 x01, 0 x01},
{0 x88, 0 x12, 0 x70, 0 x01},
{0 x88, 0 x0f, 0 x00, 0 x01},
{0 x88, 0 x05, 0 x01, 0 x01},
{}
};
static const __u8 cx11646_fw1[][3 ] = {
{0 x00, 0 x02, 0 x00},
{0 x01, 0 x43, 0 x00},
{0 x02, 0 xA7, 0 x00},
{0 x03, 0 x8B, 0 x01},
{0 x04, 0 xE9, 0 x02},
{0 x05, 0 x08, 0 x04},
{0 x06, 0 x08, 0 x05},
{0 x07, 0 x07, 0 x06},
{0 x08, 0 xE7, 0 x06},
{0 x09, 0 xC6, 0 x07},
{0 x0A, 0 x86, 0 x08},
{0 x0B, 0 x46, 0 x09},
{0 x0C, 0 x05, 0 x0A},
{0 x0D, 0 xA5, 0 x0A},
{0 x0E, 0 x45, 0 x0B},
{0 x0F, 0 xE5, 0 x0B},
{0 x10, 0 x85, 0 x0C},
{0 x11, 0 x25, 0 x0D},
{0 x12, 0 xC4, 0 x0D},
{0 x13, 0 x45, 0 x0E},
{0 x14, 0 xE4, 0 x0E},
{0 x15, 0 x64, 0 x0F},
{0 x16, 0 xE4, 0 x0F},
{0 x17, 0 x64, 0 x10},
{0 x18, 0 xE4, 0 x10},
{0 x19, 0 x64, 0 x11},
{0 x1A, 0 xE4, 0 x11},
{0 x1B, 0 x64, 0 x12},
{0 x1C, 0 xE3, 0 x12},
{0 x1D, 0 x44, 0 x13},
{0 x1E, 0 xC3, 0 x13},
{0 x1F, 0 x24, 0 x14},
{0 x20, 0 xA3, 0 x14},
{0 x21, 0 x04, 0 x15},
{0 x22, 0 x83, 0 x15},
{0 x23, 0 xE3, 0 x15},
{0 x24, 0 x43, 0 x16},
{0 x25, 0 xA4, 0 x16},
{0 x26, 0 x23, 0 x17},
{0 x27, 0 x83, 0 x17},
{0 x28, 0 xE3, 0 x17},
{0 x29, 0 x43, 0 x18},
{0 x2A, 0 xA3, 0 x18},
{0 x2B, 0 x03, 0 x19},
{0 x2C, 0 x63, 0 x19},
{0 x2D, 0 xC3, 0 x19},
{0 x2E, 0 x22, 0 x1A},
{0 x2F, 0 x63, 0 x1A},
{0 x30, 0 xC3, 0 x1A},
{0 x31, 0 x23, 0 x1B},
{0 x32, 0 x83, 0 x1B},
{0 x33, 0 xE2, 0 x1B},
{0 x34, 0 x23, 0 x1C},
{0 x35, 0 x83, 0 x1C},
{0 x36, 0 xE2, 0 x1C},
{0 x37, 0 x23, 0 x1D},
{0 x38, 0 x83, 0 x1D},
{0 x39, 0 xE2, 0 x1D},
{0 x3A, 0 x23, 0 x1E},
{0 x3B, 0 x82, 0 x1E},
{0 x3C, 0 xC3, 0 x1E},
{0 x3D, 0 x22, 0 x1F},
{0 x3E, 0 x63, 0 x1F},
{0 x3F, 0 xC1, 0 x1F},
{}
};
static void cx11646_fw(struct gspca_dev*gspca_dev)
{
int i = 0 ;
reg_w_val(gspca_dev, 0 x006a, 0 x02);
while (cx11646_fw1[i][1 ]) {
reg_w(gspca_dev, 0 x006b, cx11646_fw1[i], 3 );
i++;
}
reg_w_val(gspca_dev, 0 x006a, 0 x00);
}
static const __u8 cxsensor[] = {
0 x88, 0 x12, 0 x70, 0 x01,
0 x88, 0 x0d, 0 x02, 0 x01,
0 x88, 0 x0f, 0 x00, 0 x01,
0 x88, 0 x03, 0 x71, 0 x01, 0 x88, 0 x04, 0 x00, 0 x01, /* 3 */
0 x88, 0 x02, 0 x10, 0 x01,
0 x88, 0 x00, 0 xD4, 0 x01, 0 x88, 0 x01, 0 x01, 0 x01, /* 5 */
0 x88, 0 x0B, 0 x00, 0 x01,
0 x88, 0 x0A, 0 x0A, 0 x01,
0 x88, 0 x00, 0 x08, 0 x01, 0 x88, 0 x01, 0 x00, 0 x01, /* 8 */
0 x88, 0 x05, 0 x01, 0 x01,
0 xA1, 0 x18, 0 x00, 0 x01,
0 x00
};
static const __u8 reg20[] = { 0 x10, 0 x42, 0 x81, 0 x19, 0 xd3, 0 xff, 0 xa7, 0 xff };
static const __u8 reg28[] = { 0 x87, 0 x00, 0 x87, 0 x00, 0 x8f, 0 xff, 0 xea, 0 xff };
static const __u8 reg10[] = { 0 xb1, 0 xb1 };
static const __u8 reg71a[] = { 0 x08, 0 x18, 0 x0a, 0 x1e }; /* 640 */
static const __u8 reg71b[] = { 0 x04, 0 x0c, 0 x05, 0 x0f };
/* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
static const __u8 reg71c[] = { 0 x02, 0 x07, 0 x03, 0 x09 };
/* 320{0x04,0x0c,0x05,0x0f}; //320 */
static const __u8 reg71d[] = { 0 x02, 0 x07, 0 x03, 0 x09 }; /* 176 */
static const __u8 reg7b[] = { 0 x00, 0 xff, 0 x00, 0 xff, 0 x00, 0 xff };
static void cx_sensor(struct gspca_dev*gspca_dev)
{
int i = 0 ;
int length;
const __u8 *ptsensor = cxsensor;
reg_w(gspca_dev, 0 x0020, reg20, 8 );
reg_w(gspca_dev, 0 x0028, reg28, 8 );
reg_w(gspca_dev, 0 x0010, reg10, 2 );
reg_w_val(gspca_dev, 0 x0092, 0 x03);
switch (gspca_dev->cam.cam_mode[(int ) gspca_dev->curr_mode].priv) {
case 0 :
reg_w(gspca_dev, 0 x0071, reg71a, 4 );
break ;
case 1 :
reg_w(gspca_dev, 0 x0071, reg71b, 4 );
break ;
default :
/* case 2: */
reg_w(gspca_dev, 0 x0071, reg71c, 4 );
break ;
case 3 :
reg_w(gspca_dev, 0 x0071, reg71d, 4 );
break ;
}
reg_w(gspca_dev, 0 x007b, reg7b, 6 );
reg_w_val(gspca_dev, 0 x00f8, 0 x00);
reg_w(gspca_dev, 0 x0010, reg10, 2 );
reg_w_val(gspca_dev, 0 x0098, 0 x41);
for (i = 0 ; i < 11 ; i++) {
if (i == 3 || i == 5 || i == 8 )
length = 8 ;
else
length = 4 ;
reg_w(gspca_dev, 0 x00e5, ptsensor, length);
if (length == 4 )
reg_r(gspca_dev, 0 x00e8, 1 );
else
reg_r(gspca_dev, 0 x00e8, length);
ptsensor += length;
}
reg_r(gspca_dev, 0 x00e7, 8 );
}
static const __u8 cx_inits_176[] = {
0 x33, 0 x81, 0 xB0, 0 x00, 0 x90, 0 x00, 0 x0A, 0 x03, /* 176x144 */
0 x00, 0 x03, 0 x03, 0 x03, 0 x1B, 0 x05, 0 x30, 0 x03,
0 x65, 0 x15, 0 x18, 0 x25, 0 x03, 0 x25, 0 x08, 0 x30,
0 x3B, 0 x25, 0 x10, 0 x00, 0 x04, 0 x00, 0 x00, 0 x00,
0 xDC, 0 xFF, 0 xEE, 0 xFF, 0 xC5, 0 xFF, 0 xBF, 0 xFF,
0 xF7, 0 xFF, 0 x88, 0 xFF, 0 x66, 0 x02, 0 x28, 0 x02,
0 x1E, 0 x03, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00
};
static const __u8 cx_inits_320[] = {
0 x7f, 0 x7f, 0 x40, 0 x01, 0 xf0, 0 x00, 0 x02, 0 x01,
0 x00, 0 x01, 0 x01, 0 x01, 0 x10, 0 x00, 0 x02, 0 x01,
0 x65, 0 x45, 0 xfa, 0 x4c, 0 x2c, 0 xdf, 0 xb9, 0 x81,
0 x30, 0 x00, 0 x00, 0 x00, 0 x04, 0 x00, 0 x00, 0 x00,
0 xe2, 0 xff, 0 xf1, 0 xff, 0 xc2, 0 xff, 0 xbc, 0 xff,
0 xf5, 0 xff, 0 x6d, 0 xff, 0 xf6, 0 x01, 0 x43, 0 x02,
0 xd3, 0 x03, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00
};
static const __u8 cx_inits_352[] = {
0 x2e, 0 x7c, 0 x60, 0 x01, 0 x20, 0 x01, 0 x05, 0 x03,
0 x00, 0 x06, 0 x03, 0 x06, 0 x1b, 0 x10, 0 x05, 0 x3b,
0 x30, 0 x25, 0 x18, 0 x25, 0 x08, 0 x30, 0 x03, 0 x25,
0 x3b, 0 x30, 0 x25, 0 x1b, 0 x10, 0 x05, 0 x00, 0 x00,
0 xe3, 0 xff, 0 xf1, 0 xff, 0 xc2, 0 xff, 0 xbc, 0 xff,
0 xf5, 0 xff, 0 x6b, 0 xff, 0 xee, 0 x01, 0 x43, 0 x02,
0 xe4, 0 x03, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00
};
static const __u8 cx_inits_640[] = {
0 x7e, 0 x7e, 0 x80, 0 x02, 0 xe0, 0 x01, 0 x01, 0 x01,
0 x00, 0 x02, 0 x01, 0 x02, 0 x10, 0 x30, 0 x01, 0 x01,
0 x65, 0 x45, 0 xf7, 0 x52, 0 x2c, 0 xdf, 0 xb9, 0 x81,
0 x30, 0 x00, 0 x00, 0 x00, 0 x04, 0 x00, 0 x00, 0 x00,
0 xe2, 0 xff, 0 xf1, 0 xff, 0 xc2, 0 xff, 0 xbc, 0 xff,
0 xf6, 0 xff, 0 x7b, 0 xff, 0 x01, 0 x02, 0 x43, 0 x02,
0 x77, 0 x03, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00
};
static void cx11646_initsize(struct gspca_dev *gspca_dev)
{
const __u8 *cxinit;
static const __u8 reg12[] = { 0 x08, 0 x05, 0 x07, 0 x04, 0 x24 };
static const __u8 reg17[] =
{ 0 x0a, 0 x00, 0 xf2, 0 x01, 0 x0f, 0 x00, 0 x97, 0 x02 };
switch (gspca_dev->cam.cam_mode[(int ) gspca_dev->curr_mode].priv) {
case 0 :
cxinit = cx_inits_640;
break ;
case 1 :
cxinit = cx_inits_352;
break ;
default :
/* case 2: */
cxinit = cx_inits_320;
break ;
case 3 :
cxinit = cx_inits_176;
break ;
}
reg_w_val(gspca_dev, 0 x009a, 0 x01);
reg_w_val(gspca_dev, 0 x0010, 0 x10);
reg_w(gspca_dev, 0 x0012, reg12, 5 );
reg_w(gspca_dev, 0 x0017, reg17, 8 );
reg_w_val(gspca_dev, 0 x00c0, 0 x00);
reg_w_val(gspca_dev, 0 x00c1, 0 x04);
reg_w_val(gspca_dev, 0 x00c2, 0 x04);
reg_w(gspca_dev, 0 x0061, cxinit, 8 );
cxinit += 8 ;
reg_w(gspca_dev, 0 x00ca, cxinit, 8 );
cxinit += 8 ;
reg_w(gspca_dev, 0 x00d2, cxinit, 8 );
cxinit += 8 ;
reg_w(gspca_dev, 0 x00da, cxinit, 6 );
cxinit += 8 ;
reg_w(gspca_dev, 0 x0041, cxinit, 8 );
cxinit += 8 ;
reg_w(gspca_dev, 0 x0049, cxinit, 8 );
cxinit += 8 ;
reg_w(gspca_dev, 0 x0051, cxinit, 2 );
reg_r(gspca_dev, 0 x0010, 1 );
}
static const __u8 cx_jpeg_init[][8 ] = {
{0 xff, 0 xd8, 0 xff, 0 xdb, 0 x00, 0 x84, 0 x00, 0 x15}, /* 1 */
{0 x0f, 0 x10, 0 x12, 0 x10, 0 x0d, 0 x15, 0 x12, 0 x11},
{0 x12, 0 x18, 0 x16, 0 x15, 0 x19, 0 x20, 0 x35, 0 x22},
{0 x20, 0 x1d, 0 x1d, 0 x20, 0 x41, 0 x2e, 0 x31, 0 x26},
{0 x35, 0 x4d, 0 x43, 0 x51, 0 x4f, 0 x4b, 0 x43, 0 x4a},
{0 x49, 0 x55, 0 x5F, 0 x79, 0 x67, 0 x55, 0 x5A, 0 x73},
{0 x5B, 0 x49, 0 x4A, 0 x6A, 0 x90, 0 x6B, 0 x73, 0 x7D},
{0 x81, 0 x88, 0 x89, 0 x88, 0 x52, 0 x66, 0 x95, 0 xA0},
{0 x94, 0 x84, 0 x9E, 0 x79, 0 x85, 0 x88, 0 x83, 0 x01},
{0 x15, 0 x0F, 0 x10, 0 x12, 0 x10, 0 x0D, 0 x15, 0 x12},
{0 x11, 0 x12, 0 x18, 0 x16, 0 x15, 0 x19, 0 x20, 0 x35},
{0 x22, 0 x20, 0 x1D, 0 x1D, 0 x20, 0 x41, 0 x2E, 0 x31},
{0 x26, 0 x35, 0 x4D, 0 x43, 0 x51, 0 x4F, 0 x4B, 0 x43},
{0 x4A, 0 x49, 0 x55, 0 x5F, 0 x79, 0 x67, 0 x55, 0 x5A},
{0 x73, 0 x5B, 0 x49, 0 x4A, 0 x6A, 0 x90, 0 x6B, 0 x73},
{0 x7D, 0 x81, 0 x88, 0 x89, 0 x88, 0 x52, 0 x66, 0 x95},
{0 xA0, 0 x94, 0 x84, 0 x9E, 0 x79, 0 x85, 0 x88, 0 x83},
{0 xFF, 0 xC4, 0 x01, 0 xA2, 0 x00, 0 x00, 0 x01, 0 x05},
{0 x01, 0 x01, 0 x01, 0 x01, 0 x01, 0 x01, 0 x00, 0 x00},
{0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x01, 0 x02},
{0 x03, 0 x04, 0 x05, 0 x06, 0 x07, 0 x08, 0 x09, 0 x0A},
{0 x0B, 0 x01, 0 x00, 0 x03, 0 x01, 0 x01, 0 x01, 0 x01},
{0 x01, 0 x01, 0 x01, 0 x01, 0 x01, 0 x00, 0 x00, 0 x00},
{0 x00, 0 x00, 0 x00, 0 x01, 0 x02, 0 x03, 0 x04, 0 x05},
{0 x06, 0 x07, 0 x08, 0 x09, 0 x0A, 0 x0B, 0 x10, 0 x00},
{0 x02, 0 x01, 0 x03, 0 x03, 0 x02, 0 x04, 0 x03, 0 x05},
{0 x05, 0 x04, 0 x04, 0 x00, 0 x00, 0 x01, 0 x7D, 0 x01},
{0 x02, 0 x03, 0 x00, 0 x04, 0 x11, 0 x05, 0 x12, 0 x21},
{0 x31, 0 x41, 0 x06, 0 x13, 0 x51, 0 x61, 0 x07, 0 x22},
{0 x71, 0 x14, 0 x32, 0 x81, 0 x91, 0 xA1, 0 x08, 0 x23},
{0 x42, 0 xB1, 0 xC1, 0 x15, 0 x52, 0 xD1, 0 xF0, 0 x24},
{0 x33, 0 x62, 0 x72, 0 x82, 0 x09, 0 x0A, 0 x16, 0 x17},
{0 x18, 0 x19, 0 x1A, 0 x25, 0 x26, 0 x27, 0 x28, 0 x29},
{0 x2A, 0 x34, 0 x35, 0 x36, 0 x37, 0 x38, 0 x39, 0 x3A},
{0 x43, 0 x44, 0 x45, 0 x46, 0 x47, 0 x48, 0 x49, 0 x4A},
{0 x53, 0 x54, 0 x55, 0 x56, 0 x57, 0 x58, 0 x59, 0 x5A},
{0 x63, 0 x64, 0 x65, 0 x66, 0 x67, 0 x68, 0 x69, 0 x6A},
{0 x73, 0 x74, 0 x75, 0 x76, 0 x77, 0 x78, 0 x79, 0 x7A},
{0 x83, 0 x84, 0 x85, 0 x86, 0 x87, 0 x88, 0 x89, 0 x8A},
{0 x92, 0 x93, 0 x94, 0 x95, 0 x96, 0 x97, 0 x98, 0 x99},
{0 x9A, 0 xA2, 0 xA3, 0 xA4, 0 xA5, 0 xA6, 0 xA7, 0 xA8},
{0 xA9, 0 xAA, 0 xB2, 0 xB3, 0 xB4, 0 xB5, 0 xB6, 0 xB7},
{0 xB8, 0 xB9, 0 xBA, 0 xC2, 0 xC3, 0 xC4, 0 xC5, 0 xC6},
{0 xC7, 0 xC8, 0 xC9, 0 xCA, 0 xD2, 0 xD3, 0 xD4, 0 xD5},
{0 xD6, 0 xD7, 0 xD8, 0 xD9, 0 xDA, 0 xE1, 0 xE2, 0 xE3},
{0 xE4, 0 xE5, 0 xE6, 0 xE7, 0 xE8, 0 xE9, 0 xEA, 0 xF1},
{0 xF2, 0 xF3, 0 xF4, 0 xF5, 0 xF6, 0 xF7, 0 xF8, 0 xF9},
{0 xFA, 0 x11, 0 x00, 0 x02, 0 x01, 0 x02, 0 x04, 0 x04},
{0 x03, 0 x04, 0 x07, 0 x05, 0 x04, 0 x04, 0 x00, 0 x01},
{0 x02, 0 x77, 0 x00, 0 x01, 0 x02, 0 x03, 0 x11, 0 x04},
{0 x05, 0 x21, 0 x31, 0 x06, 0 x12, 0 x41, 0 x51, 0 x07},
{0 x61, 0 x71, 0 x13, 0 x22, 0 x32, 0 x81, 0 x08, 0 x14},
{0 x42, 0 x91, 0 xA1, 0 xB1, 0 xC1, 0 x09, 0 x23, 0 x33},
{0 x52, 0 xF0, 0 x15, 0 x62, 0 x72, 0 xD1, 0 x0A, 0 x16},
{0 x24, 0 x34, 0 xE1, 0 x25, 0 xF1, 0 x17, 0 x18, 0 x19},
{0 x1A, 0 x26, 0 x27, 0 x28, 0 x29, 0 x2A, 0 x35, 0 x36},
{0 x37, 0 x38, 0 x39, 0 x3A, 0 x43, 0 x44, 0 x45, 0 x46},
{0 x47, 0 x48, 0 x49, 0 x4A, 0 x53, 0 x54, 0 x55, 0 x56},
{0 x57, 0 x58, 0 x59, 0 x5A, 0 x63, 0 x64, 0 x65, 0 x66},
{0 x67, 0 x68, 0 x69, 0 x6A, 0 x73, 0 x74, 0 x75, 0 x76},
{0 x77, 0 x78, 0 x79, 0 x7A, 0 x82, 0 x83, 0 x84, 0 x85},
{0 x86, 0 x87, 0 x88, 0 x89, 0 x8A, 0 x92, 0 x93, 0 x94},
{0 x95, 0 x96, 0 x97, 0 x98, 0 x99, 0 x9A, 0 xA2, 0 xA3},
{0 xA4, 0 xA5, 0 xA6, 0 xA7, 0 xA8, 0 xA9, 0 xAA, 0 xB2},
{0 xB3, 0 xB4, 0 xB5, 0 xB6, 0 xB7, 0 xB8, 0 xB9, 0 xBA},
{0 xC2, 0 xC3, 0 xC4, 0 xC5, 0 xC6, 0 xC7, 0 xC8, 0 xC9},
{0 xCA, 0 xD2, 0 xD3, 0 xD4, 0 xD5, 0 xD6, 0 xD7, 0 xD8},
{0 xD9, 0 xDA, 0 xE2, 0 xE3, 0 xE4, 0 xE5, 0 xE6, 0 xE7},
{0 xE8, 0 xE9, 0 xEA, 0 xF2, 0 xF3, 0 xF4, 0 xF5, 0 xF6},
{0 xF7, 0 xF8, 0 xF9, 0 xFA, 0 xFF, 0 x20, 0 x00, 0 x1F},
{0 x02, 0 x0C, 0 x00, 0 x00, 0 x0A, 0 x00, 0 x00, 0 x00},
{0 x00, 0 x00, 0 x11, 0 x00, 0 x11, 0 x22, 0 x00, 0 x22},
{0 x22, 0 x11, 0 x22, 0 x22, 0 x11, 0 x33, 0 x33, 0 x11},
{0 x44, 0 x66, 0 x22, 0 x55, 0 x66, 0 xFF, 0 xDD, 0 x00},
{0 x04, 0 x00, 0 x14, 0 xFF, 0 xC0, 0 x00, 0 x11, 0 x08},
{0 x00, 0 xF0, 0 x01, 0 x40, 0 x03, 0 x00, 0 x21, 0 x00},
{0 x01, 0 x11, 0 x01, 0 x02, 0 x11, 0 x01, 0 xFF, 0 xDA},
{0 x00, 0 x0C, 0 x03, 0 x00, 0 x00, 0 x01, 0 x11, 0 x02},
{0 x11, 0 x00, 0 x3F, 0 x00, 0 xFF, 0 xD9, 0 x00, 0 x00} /* 79 */
};
static const __u8 cxjpeg_640[][8 ] = {
{0 xff, 0 xd8, 0 xff, 0 xdb, 0 x00, 0 x84, 0 x00, 0 x10}, /* 1 */
{0 x0b, 0 x0c, 0 x0e, 0 x0c, 0 x0a, 0 x10, 0 x0e, 0 x0d},
{0 x0e, 0 x12, 0 x11, 0 x10, 0 x13, 0 x18, 0 x28, 0 x1a},
{0 x18, 0 x16, 0 x16, 0 x18, 0 x31, 0 x23, 0 x25, 0 x1d},
{0 x28, 0 x3a, 0 x33, 0 x3D, 0 x3C, 0 x39, 0 x33, 0 x38},
{0 x37, 0 x40, 0 x48, 0 x5C, 0 x4E, 0 x40, 0 x44, 0 x57},
{0 x45, 0 x37, 0 x38, 0 x50, 0 x6D, 0 x51, 0 x57, 0 x5F},
{0 x62, 0 x67, 0 x68, 0 x67, 0 x3E, 0 x4D, 0 x71, 0 x79},
{0 x70, 0 x64, 0 x78, 0 x5C, 0 x65, 0 x67, 0 x63, 0 x01},
{0 x10, 0 x0B, 0 x0C, 0 x0E, 0 x0C, 0 x0A, 0 x10, 0 x0E},
{0 x0D, 0 x0E, 0 x12, 0 x11, 0 x10, 0 x13, 0 x18, 0 x28},
{0 x1A, 0 x18, 0 x16, 0 x16, 0 x18, 0 x31, 0 x23, 0 x25},
{0 x1D, 0 x28, 0 x3A, 0 x33, 0 x3D, 0 x3C, 0 x39, 0 x33},
{0 x38, 0 x37, 0 x40, 0 x48, 0 x5C, 0 x4E, 0 x40, 0 x44},
{0 x57, 0 x45, 0 x37, 0 x38, 0 x50, 0 x6D, 0 x51, 0 x57},
{0 x5F, 0 x62, 0 x67, 0 x68, 0 x67, 0 x3E, 0 x4D, 0 x71},
{0 x79, 0 x70, 0 x64, 0 x78, 0 x5C, 0 x65, 0 x67, 0 x63},
{0 xFF, 0 x20, 0 x00, 0 x1F, 0 x00, 0 x83, 0 x00, 0 x00},
{0 x0A, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x11, 0 x00},
{0 x11, 0 x22, 0 x00, 0 x22, 0 x22, 0 x11, 0 x22, 0 x22},
{0 x11, 0 x33, 0 x33, 0 x11, 0 x44, 0 x66, 0 x22, 0 x55},
{0 x66, 0 xFF, 0 xDD, 0 x00, 0 x04, 0 x00, 0 x28, 0 xFF},
{0 xC0, 0 x00, 0 x11, 0 x08, 0 x01, 0 xE0, 0 x02, 0 x80},
{0 x03, 0 x00, 0 x21, 0 x00, 0 x01, 0 x11, 0 x01, 0 x02},
{0 x11, 0 x01, 0 xFF, 0 xDA, 0 x00, 0 x0C, 0 x03, 0 x00},
{0 x00, 0 x01, 0 x11, 0 x02, 0 x11, 0 x00, 0 x3F, 0 x00},
{0 xFF, 0 xD9, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00} /* 27 */
};
static const __u8 cxjpeg_352[][8 ] = {
{0 xff, 0 xd8, 0 xff, 0 xdb, 0 x00, 0 x84, 0 x00, 0 x0d},
{0 x09, 0 x09, 0 x0b, 0 x09, 0 x08, 0 x0D, 0 x0b, 0 x0a},
{0 x0b, 0 x0e, 0 x0d, 0 x0d, 0 x0f, 0 x13, 0 x1f, 0 x14},
{0 x13, 0 x11, 0 x11, 0 x13, 0 x26, 0 x1b, 0 x1d, 0 x17},
{0 x1F, 0 x2D, 0 x28, 0 x30, 0 x2F, 0 x2D, 0 x28, 0 x2C},
{0 x2B, 0 x32, 0 x38, 0 x48, 0 x3D, 0 x32, 0 x35, 0 x44},
{0 x36, 0 x2B, 0 x2C, 0 x3F, 0 x55, 0 x3F, 0 x44, 0 x4A},
{0 x4D, 0 x50, 0 x51, 0 x50, 0 x30, 0 x3C, 0 x58, 0 x5F},
{0 x58, 0 x4E, 0 x5E, 0 x48, 0 x4F, 0 x50, 0 x4D, 0 x01},
{0 x0D, 0 x09, 0 x09, 0 x0B, 0 x09, 0 x08, 0 x0D, 0 x0B},
{0 x0A, 0 x0B, 0 x0E, 0 x0D, 0 x0D, 0 x0F, 0 x13, 0 x1F},
{0 x14, 0 x13, 0 x11, 0 x11, 0 x13, 0 x26, 0 x1B, 0 x1D},
{0 x17, 0 x1F, 0 x2D, 0 x28, 0 x30, 0 x2F, 0 x2D, 0 x28},
{0 x2C, 0 x2B, 0 x32, 0 x38, 0 x48, 0 x3D, 0 x32, 0 x35},
{0 x44, 0 x36, 0 x2B, 0 x2C, 0 x3F, 0 x55, 0 x3F, 0 x44},
{0 x4A, 0 x4D, 0 x50, 0 x51, 0 x50, 0 x30, 0 x3C, 0 x58},
{0 x5F, 0 x58, 0 x4E, 0 x5E, 0 x48, 0 x4F, 0 x50, 0 x4D},
{0 xFF, 0 x20, 0 x00, 0 x1F, 0 x01, 0 x83, 0 x00, 0 x00},
{0 x0A, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x11, 0 x00},
{0 x11, 0 x22, 0 x00, 0 x22, 0 x22, 0 x11, 0 x22, 0 x22},
{0 x11, 0 x33, 0 x33, 0 x11, 0 x44, 0 x66, 0 x22, 0 x55},
{0 x66, 0 xFF, 0 xDD, 0 x00, 0 x04, 0 x00, 0 x16, 0 xFF},
{0 xC0, 0 x00, 0 x11, 0 x08, 0 x01, 0 x20, 0 x01, 0 x60},
{0 x03, 0 x00, 0 x21, 0 x00, 0 x01, 0 x11, 0 x01, 0 x02},
{0 x11, 0 x01, 0 xFF, 0 xDA, 0 x00, 0 x0C, 0 x03, 0 x00},
{0 x00, 0 x01, 0 x11, 0 x02, 0 x11, 0 x00, 0 x3F, 0 x00},
{0 xFF, 0 xD9, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00}
};
static const __u8 cxjpeg_320[][8 ] = {
{0 xff, 0 xd8, 0 xff, 0 xdb, 0 x00, 0 x84, 0 x00, 0 x05},
{0 x03, 0 x04, 0 x04, 0 x04, 0 x03, 0 x05, 0 x04, 0 x04},
{0 x04, 0 x05, 0 x05, 0 x05, 0 x06, 0 x07, 0 x0c, 0 x08},
{0 x07, 0 x07, 0 x07, 0 x07, 0 x0f, 0 x0b, 0 x0b, 0 x09},
{0 x0C, 0 x11, 0 x0F, 0 x12, 0 x12, 0 x11, 0 x0f, 0 x11},
{0 x11, 0 x13, 0 x16, 0 x1C, 0 x17, 0 x13, 0 x14, 0 x1A},
{0 x15, 0 x11, 0 x11, 0 x18, 0 x21, 0 x18, 0 x1A, 0 x1D},
{0 x1D, 0 x1F, 0 x1F, 0 x1F, 0 x13, 0 x17, 0 x22, 0 x24},
{0 x22, 0 x1E, 0 x24, 0 x1C, 0 x1E, 0 x1F, 0 x1E, 0 x01},
{0 x05, 0 x03, 0 x04, 0 x04, 0 x04, 0 x03, 0 x05, 0 x04},
{0 x04, 0 x04, 0 x05, 0 x05, 0 x05, 0 x06, 0 x07, 0 x0C},
{0 x08, 0 x07, 0 x07, 0 x07, 0 x07, 0 x0F, 0 x0B, 0 x0B},
{0 x09, 0 x0C, 0 x11, 0 x0F, 0 x12, 0 x12, 0 x11, 0 x0F},
{0 x11, 0 x11, 0 x13, 0 x16, 0 x1C, 0 x17, 0 x13, 0 x14},
{0 x1A, 0 x15, 0 x11, 0 x11, 0 x18, 0 x21, 0 x18, 0 x1A},
{0 x1D, 0 x1D, 0 x1F, 0 x1F, 0 x1F, 0 x13, 0 x17, 0 x22},
{0 x24, 0 x22, 0 x1E, 0 x24, 0 x1C, 0 x1E, 0 x1F, 0 x1E},
{0 xFF, 0 x20, 0 x00, 0 x1F, 0 x02, 0 x0C, 0 x00, 0 x00},
{0 x0A, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x11, 0 x00},
{0 x11, 0 x22, 0 x00, 0 x22, 0 x22, 0 x11, 0 x22, 0 x22},
{0 x11, 0 x33, 0 x33, 0 x11, 0 x44, 0 x66, 0 x22, 0 x55},
{0 x66, 0 xFF, 0 xDD, 0 x00, 0 x04, 0 x00, 0 x14, 0 xFF},
{0 xC0, 0 x00, 0 x11, 0 x08, 0 x00, 0 xF0, 0 x01, 0 x40},
{0 x03, 0 x00, 0 x21, 0 x00, 0 x01, 0 x11, 0 x01, 0 x02},
{0 x11, 0 x01, 0 xFF, 0 xDA, 0 x00, 0 x0C, 0 x03, 0 x00},
{0 x00, 0 x01, 0 x11, 0 x02, 0 x11, 0 x00, 0 x3F, 0 x00},
{0 xFF, 0 xD9, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00} /* 27 */
};
static const __u8 cxjpeg_176[][8 ] = {
{0 xff, 0 xd8, 0 xff, 0 xdb, 0 x00, 0 x84, 0 x00, 0 x0d},
{0 x09, 0 x09, 0 x0B, 0 x09, 0 x08, 0 x0D, 0 x0B, 0 x0A},
{0 x0B, 0 x0E, 0 x0D, 0 x0D, 0 x0F, 0 x13, 0 x1F, 0 x14},
{0 x13, 0 x11, 0 x11, 0 x13, 0 x26, 0 x1B, 0 x1D, 0 x17},
{0 x1F, 0 x2D, 0 x28, 0 x30, 0 x2F, 0 x2D, 0 x28, 0 x2C},
{0 x2B, 0 x32, 0 x38, 0 x48, 0 x3D, 0 x32, 0 x35, 0 x44},
{0 x36, 0 x2B, 0 x2C, 0 x3F, 0 x55, 0 x3F, 0 x44, 0 x4A},
{0 x4D, 0 x50, 0 x51, 0 x50, 0 x30, 0 x3C, 0 x58, 0 x5F},
{0 x58, 0 x4E, 0 x5E, 0 x48, 0 x4F, 0 x50, 0 x4D, 0 x01},
{0 x0D, 0 x09, 0 x09, 0 x0B, 0 x09, 0 x08, 0 x0D, 0 x0B},
{0 x0A, 0 x0B, 0 x0E, 0 x0D, 0 x0D, 0 x0F, 0 x13, 0 x1F},
{0 x14, 0 x13, 0 x11, 0 x11, 0 x13, 0 x26, 0 x1B, 0 x1D},
{0 x17, 0 x1F, 0 x2D, 0 x28, 0 x30, 0 x2F, 0 x2D, 0 x28},
{0 x2C, 0 x2B, 0 x32, 0 x38, 0 x48, 0 x3D, 0 x32, 0 x35},
{0 x44, 0 x36, 0 x2B, 0 x2C, 0 x3F, 0 x55, 0 x3F, 0 x44},
{0 x4A, 0 x4D, 0 x50, 0 x51, 0 x50, 0 x30, 0 x3C, 0 x58},
{0 x5F, 0 x58, 0 x4E, 0 x5E, 0 x48, 0 x4F, 0 x50, 0 x4D},
{0 xFF, 0 x20, 0 x00, 0 x1F, 0 x03, 0 xA1, 0 x00, 0 x00},
{0 x0A, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x11, 0 x00},
{0 x11, 0 x22, 0 x00, 0 x22, 0 x22, 0 x11, 0 x22, 0 x22},
{0 x11, 0 x33, 0 x33, 0 x11, 0 x44, 0 x66, 0 x22, 0 x55},
{0 x66, 0 xFF, 0 xDD, 0 x00, 0 x04, 0 x00, 0 x0B, 0 xFF},
{0 xC0, 0 x00, 0 x11, 0 x08, 0 x00, 0 x90, 0 x00, 0 xB0},
{0 x03, 0 x00, 0 x21, 0 x00, 0 x01, 0 x11, 0 x01, 0 x02},
{0 x11, 0 x01, 0 xFF, 0 xDA, 0 x00, 0 x0C, 0 x03, 0 x00},
{0 x00, 0 x01, 0 x11, 0 x02, 0 x11, 0 x00, 0 x3F, 0 x00},
{0 xFF, 0 xD9, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00}
};
/* 640 take with the zcx30x part */
static const __u8 cxjpeg_qtable[][8 ] = {
{0 xff, 0 xd8, 0 xff, 0 xdb, 0 x00, 0 x84, 0 x00, 0 x08},
{0 x06, 0 x06, 0 x07, 0 x06, 0 x05, 0 x08, 0 x07, 0 x07},
{0 x07, 0 x09, 0 x09, 0 x08, 0 x0a, 0 x0c, 0 x14, 0 x0a},
{0 x0c, 0 x0b, 0 x0b, 0 x0c, 0 x19, 0 x12, 0 x13, 0 x0f},
{0 x14, 0 x1d, 0 x1a, 0 x1f, 0 x1e, 0 x1d, 0 x1a, 0 x1c},
{0 x1c, 0 x20, 0 x24, 0 x2e, 0 x27, 0 x20, 0 x22, 0 x2c},
{0 x23, 0 x1c, 0 x1c, 0 x28, 0 x37, 0 x29, 0 x2c, 0 x30},
{0 x31, 0 x34, 0 x34, 0 x34, 0 x1f, 0 x27, 0 x39, 0 x3d},
{0 x38, 0 x32, 0 x3c, 0 x2e, 0 x33, 0 x34, 0 x32, 0 x01},
{0 x09, 0 x09, 0 x09, 0 x0c, 0 x0b, 0 x0c, 0 x18, 0 x0a},
{0 x0a, 0 x18, 0 x32, 0 x21, 0 x1c, 0 x21, 0 x32, 0 x32},
{0 x32, 0 x32, 0 x32, 0 x32, 0 x32, 0 x32, 0 x32, 0 x32},
{0 x32, 0 x32, 0 x32, 0 x32, 0 x32, 0 x32, 0 x32, 0 x32},
{0 x32, 0 x32, 0 x32, 0 x32, 0 x32, 0 x32, 0 x32, 0 x32},
{0 x32, 0 x32, 0 x32, 0 x32, 0 x32, 0 x32, 0 x32, 0 x32},
{0 x32, 0 x32, 0 x32, 0 x32, 0 x32, 0 x32, 0 x32, 0 x32},
{0 x32, 0 x32, 0 x32, 0 x32, 0 x32, 0 x32, 0 x32, 0 x32},
{0 xFF, 0 xD9, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00} /* 18 */
};
static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
{
int i;
int length;
reg_w_val(gspca_dev, 0 x00c0, 0 x01);
reg_w_val(gspca_dev, 0 x00c3, 0 x00);
reg_w_val(gspca_dev, 0 x00c0, 0 x00);
reg_r(gspca_dev, 0 x0001, 1 );
length = 8 ;
for (i = 0 ; i < 79 ; i++) {
if (i == 78 )
length = 6 ;
reg_w(gspca_dev, 0 x0008, cx_jpeg_init[i], length);
}
reg_r(gspca_dev, 0 x0002, 1 );
reg_w_val(gspca_dev, 0 x0055, 0 x14);
}
static const __u8 reg12[] = { 0 x0a, 0 x05, 0 x07, 0 x04, 0 x19 };
static const __u8 regE5_8[] =
{ 0 x88, 0 x00, 0 xd4, 0 x01, 0 x88, 0 x01, 0 x01, 0 x01 };
static const __u8 regE5a[] = { 0 x88, 0 x0a, 0 x0c, 0 x01 };
static const __u8 regE5b[] = { 0 x88, 0 x0b, 0 x12, 0 x01 };
static const __u8 regE5c[] = { 0 x88, 0 x05, 0 x01, 0 x01 };
static const __u8 reg51[] = { 0 x77, 0 x03 };
#define reg70 0 x03
static void cx11646_jpeg(struct gspca_dev*gspca_dev)
{
int i;
int length;
__u8 Reg55;
int retry;
reg_w_val(gspca_dev, 0 x00c0, 0 x01);
reg_w_val(gspca_dev, 0 x00c3, 0 x00);
reg_w_val(gspca_dev, 0 x00c0, 0 x00);
reg_r(gspca_dev, 0 x0001, 1 );
length = 8 ;
switch (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv) {
case 0 :
for (i = 0 ; i < 27 ; i++) {
if (i == 26 )
length = 2 ;
reg_w(gspca_dev, 0 x0008, cxjpeg_640[i], length);
}
Reg55 = 0 x28;
break ;
case 1 :
for (i = 0 ; i < 27 ; i++) {
if (i == 26 )
length = 2 ;
reg_w(gspca_dev, 0 x0008, cxjpeg_352[i], length);
}
Reg55 = 0 x16;
break ;
default :
/* case 2: */
for (i = 0 ; i < 27 ; i++) {
if (i == 26 )
length = 2 ;
reg_w(gspca_dev, 0 x0008, cxjpeg_320[i], length);
}
Reg55 = 0 x14;
break ;
case 3 :
for (i = 0 ; i < 27 ; i++) {
if (i == 26 )
length = 2 ;
reg_w(gspca_dev, 0 x0008, cxjpeg_176[i], length);
}
Reg55 = 0 x0B;
break ;
}
reg_r(gspca_dev, 0 x0002, 1 );
reg_w_val(gspca_dev, 0 x0055, Reg55);
reg_r(gspca_dev, 0 x0002, 1 );
reg_w(gspca_dev, 0 x0010, reg10, 2 );
reg_w_val(gspca_dev, 0 x0054, 0 x02);
reg_w_val(gspca_dev, 0 x0054, 0 x01);
reg_w_val(gspca_dev, 0 x0000, 0 x94);
reg_w_val(gspca_dev, 0 x0053, 0 xc0);
reg_w_val(gspca_dev, 0 x00fc, 0 xe1);
reg_w_val(gspca_dev, 0 x0000, 0 x00);
/* wait for completion */
retry = 50 ;
do {
reg_r(gspca_dev, 0 x0002, 1 );
/* 0x07 until 0x00 */
if (gspca_dev->usb_buf[0 ] == 0 x00)
break ;
reg_w_val(gspca_dev, 0 x0053, 0 x00);
} while (--retry);
if (retry == 0 )
gspca_err(gspca_dev, "Damned Errors sending jpeg Table\n" );
/* send the qtable now */
reg_r(gspca_dev, 0 x0001, 1 ); /* -> 0x18 */
length = 8 ;
for (i = 0 ; i < 18 ; i++) {
if (i == 17 )
length = 2 ;
reg_w(gspca_dev, 0 x0008, cxjpeg_qtable[i], length);
}
reg_r(gspca_dev, 0 x0002, 1 ); /* 0x00 */
reg_r(gspca_dev, 0 x0053, 1 ); /* 0x00 */
reg_w_val(gspca_dev, 0 x0054, 0 x02);
reg_w_val(gspca_dev, 0 x0054, 0 x01);
reg_w_val(gspca_dev, 0 x0000, 0 x94);
reg_w_val(gspca_dev, 0 x0053, 0 xc0);
reg_r(gspca_dev, 0 x0038, 1 ); /* 0x40 */
reg_r(gspca_dev, 0 x0038, 1 ); /* 0x40 */
reg_r(gspca_dev, 0 x001f, 1 ); /* 0x38 */
reg_w(gspca_dev, 0 x0012, reg12, 5 );
reg_w(gspca_dev, 0 x00e5, regE5_8, 8 );
reg_r(gspca_dev, 0 x00e8, 8 );
reg_w(gspca_dev, 0 x00e5, regE5a, 4 );
reg_r(gspca_dev, 0 x00e8, 1 ); /* 0x00 */
reg_w_val(gspca_dev, 0 x009a, 0 x01);
reg_w(gspca_dev, 0 x00e5, regE5b, 4 );
reg_r(gspca_dev, 0 x00e8, 1 ); /* 0x00 */
reg_w(gspca_dev, 0 x00e5, regE5c, 4 );
reg_r(gspca_dev, 0 x00e8, 1 ); /* 0x00 */
reg_w(gspca_dev, 0 x0051, reg51, 2 );
reg_w(gspca_dev, 0 x0010, reg10, 2 );
reg_w_val(gspca_dev, 0 x0070, reg70);
}
static void cx11646_init1(struct gspca_dev *gspca_dev)
{
int i = 0 ;
reg_w_val(gspca_dev, 0 x0010, 0 x00);
reg_w_val(gspca_dev, 0 x0053, 0 x00);
reg_w_val(gspca_dev, 0 x0052, 0 x00);
reg_w_val(gspca_dev, 0 x009b, 0 x2f);
reg_w_val(gspca_dev, 0 x009c, 0 x10);
reg_r(gspca_dev, 0 x0098, 1 );
reg_w_val(gspca_dev, 0 x0098, 0 x40);
reg_r(gspca_dev, 0 x0099, 1 );
reg_w_val(gspca_dev, 0 x0099, 0 x07);
reg_w_val(gspca_dev, 0 x0039, 0 x40);
reg_w_val(gspca_dev, 0 x003c, 0 xff);
reg_w_val(gspca_dev, 0 x003f, 0 x1f);
reg_w_val(gspca_dev, 0 x003d, 0 x40);
/* reg_w_val(gspca_dev, 0x003d, 0x60); */
reg_r(gspca_dev, 0 x0099, 1 ); /* ->0x07 */
while (cx_sensor_init[i][0 ]) {
reg_w_val(gspca_dev, 0 x00e5, cx_sensor_init[i][0 ]);
reg_r(gspca_dev, 0 x00e8, 1 ); /* -> 0x00 */
if (i == 1 ) {
reg_w_val(gspca_dev, 0 x00ed, 0 x01);
reg_r(gspca_dev, 0 x00ed, 1 ); /* -> 0x01 */
}
i++;
}
reg_w_val(gspca_dev, 0 x00c3, 0 x00);
}
/* this function is called at probe time */
static int sd_config(struct gspca_dev *gspca_dev,
const struct usb_device_id *id)
{
struct cam *cam;
cam = &gspca_dev->cam;
cam->cam_mode = vga_mode;
cam->nmodes = ARRAY_SIZE(vga_mode);
return 0 ;
}
/* this function is called at probe and resume time */
static int sd_init(struct gspca_dev *gspca_dev)
{
cx11646_init1(gspca_dev);
cx11646_initsize(gspca_dev);
cx11646_fw(gspca_dev);
cx_sensor(gspca_dev);
cx11646_jpegInit(gspca_dev);
return 0 ;
}
static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
/* create the JPEG header */
jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
gspca_dev->pixfmt.width,
0 x22); /* JPEG 411 */
jpeg_set_qual(sd->jpeg_hdr, QUALITY);
cx11646_initsize(gspca_dev);
cx11646_fw(gspca_dev);
cx_sensor(gspca_dev);
cx11646_jpeg(gspca_dev);
return 0 ;
}
/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
int retry = 50 ;
if (!gspca_dev->present)
return ;
reg_w_val(gspca_dev, 0 x0000, 0 x00);
reg_r(gspca_dev, 0 x0002, 1 );
reg_w_val(gspca_dev, 0 x0053, 0 x00);
while (retry--) {
/* reg_r(gspca_dev, 0x0002, 1);*/
reg_r(gspca_dev, 0 x0053, 1 );
if (gspca_dev->usb_buf[0 ] == 0 )
break ;
}
reg_w_val(gspca_dev, 0 x0000, 0 x00);
reg_r(gspca_dev, 0 x0002, 1 );
reg_w_val(gspca_dev, 0 x0010, 0 x00);
reg_r(gspca_dev, 0 x0033, 1 );
reg_w_val(gspca_dev, 0 x00fc, 0 xe0);
}
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
u8 *data, /* isoc packet */
int len) /* iso packet length */
{
struct sd *sd = (struct sd *) gspca_dev;
if (data[0 ] == 0 xff && data[1 ] == 0 xd8) {
/* start of frame */
gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0 );
/* put the JPEG header in the new frame */
gspca_frame_add(gspca_dev, FIRST_PACKET,
sd->jpeg_hdr, JPEG_HDR_SZ);
data += 2 ;
len -= 2 ;
}
gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
}
static void setbrightness(struct gspca_dev *gspca_dev, s32 val, s32 sat)
{
__u8 regE5cbx[] = { 0 x88, 0 x00, 0 xd4, 0 x01, 0 x88, 0 x01, 0 x01, 0 x01 };
__u8 reg51c[2 ];
regE5cbx[2 ] = val;
reg_w(gspca_dev, 0 x00e5, regE5cbx, 8 );
reg_r(gspca_dev, 0 x00e8, 8 );
reg_w(gspca_dev, 0 x00e5, regE5c, 4 );
reg_r(gspca_dev, 0 x00e8, 1 ); /* 0x00 */
reg51c[0 ] = 0 x77;
reg51c[1 ] = sat;
reg_w(gspca_dev, 0 x0051, reg51c, 2 );
reg_w(gspca_dev, 0 x0010, reg10, 2 );
reg_w_val(gspca_dev, 0 x0070, reg70);
}
static void setcontrast(struct gspca_dev *gspca_dev, s32 val, s32 sat)
{
__u8 regE5acx[] = { 0 x88, 0 x0a, 0 x0c, 0 x01 }; /* seem MSB */
/* __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01}; * LSB */
__u8 reg51c[2 ];
regE5acx[2 ] = val;
reg_w(gspca_dev, 0 x00e5, regE5acx, 4 );
reg_r(gspca_dev, 0 x00e8, 1 ); /* 0x00 */
reg51c[0 ] = 0 x77;
reg51c[1 ] = sat;
reg_w(gspca_dev, 0 x0051, reg51c, 2 );
reg_w(gspca_dev, 0 x0010, reg10, 2 );
reg_w_val(gspca_dev, 0 x0070, reg70);
}
static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct gspca_dev *gspca_dev =
container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
struct sd *sd = (struct sd *)gspca_dev;
gspca_dev->usb_err = 0 ;
if (!gspca_dev->streaming)
return 0 ;
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
setbrightness(gspca_dev, ctrl->val, sd->sat->cur.val);
break ;
case V4L2_CID_CONTRAST:
setcontrast(gspca_dev, ctrl->val, sd->sat->cur.val);
break ;
case V4L2_CID_SATURATION:
setbrightness(gspca_dev, sd->brightness->cur.val, ctrl->val);
setcontrast(gspca_dev, sd->contrast->cur.val, ctrl->val);
break ;
}
return gspca_dev->usb_err;
}
static const struct v4l2_ctrl_ops sd_ctrl_ops = {
.s_ctrl = sd_s_ctrl,
};
static int sd_init_controls(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *)gspca_dev;
struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
gspca_dev->vdev.ctrl_handler = hdl;
v4l2_ctrl_handler_init(hdl, 3 );
sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_BRIGHTNESS, 0 , 255 , 1 , 0 xd4);
sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_CONTRAST, 0 x0a, 0 x1f, 1 , 0 x0c);
sd->sat = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_SATURATION, 0 , 7 , 1 , 3 );
if (hdl->error) {
pr_err("Could not initialize controls\n" );
return hdl->error;
}
return 0 ;
}
/* sub-driver description */
static const struct sd_desc sd_desc = {
.name = MODULE_NAME,
.config = sd_config,
.init = sd_init,
.init_controls = sd_init_controls,
.start = sd_start,
.stop0 = sd_stop0,
.pkt_scan = sd_pkt_scan,
};
/* -- module initialisation -- */
static const struct usb_device_id device_table[] = {
{USB_DEVICE(0 x0572, 0 x0041)},
{}
};
MODULE_DEVICE_TABLE(usb, device_table);
/* -- device connect -- */
static int sd_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
return gspca_dev_probe(intf, id, &sd_desc, sizeof (struct sd),
THIS_MODULE);
}
static struct usb_driver sd_driver = {
.name = MODULE_NAME,
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
#ifdef CONFIG_PM
.suspend = gspca_suspend,
.resume = gspca_resume,
.reset_resume = gspca_resume,
#endif
};
module_usb_driver(sd_driver);
Messung V0.5 in Prozent C=94 H=91 G=92