Commit 59f90a01 authored by Hans de Goede's avatar Hans de Goede Committed by Mauro Carvalho Chehab

V4L/DVB: gspca_xirlink_cit: Add support for Model 1, 2 & 4 cameras

Note this is untested as I don't have hardware to test, but all
initsequences were taken over 1 on 1 from the old ibmcam driver so things
should work.
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 1f33de0f
......@@ -57,11 +57,14 @@ struct sd {
#define CIT_MODEL4 3
#define CIT_IBM_NETCAM_PRO 4
u8 input_index;
u8 stop_on_control_change;
u8 sof_read;
u8 sof_len;
u8 contrast;
u8 brightness;
u8 hue;
u8 sharpness;
u8 lighting;
};
/* V4L2 controls supported by the driver */
......@@ -73,6 +76,8 @@ static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val);
static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setlighting(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getlighting(struct gspca_dev *gspca_dev, __s32 *val);
static void sd_stop0(struct gspca_dev *gspca_dev);
static const struct ctrl sd_ctrls[] = {
......@@ -82,10 +87,10 @@ static const struct ctrl sd_ctrls[] = {
.id = V4L2_CID_BRIGHTNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Brightness",
.minimum = 0x0c,
.maximum = 0x3f,
.minimum = 0,
.maximum = 63,
.step = 1,
#define BRIGHTNESS_DEFAULT 0x20
#define BRIGHTNESS_DEFAULT 32
.default_value = BRIGHTNESS_DEFAULT,
.flags = 0,
},
......@@ -114,10 +119,10 @@ static const struct ctrl sd_ctrls[] = {
.id = V4L2_CID_HUE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Hue",
.minimum = 0x05,
.maximum = 0x37,
.minimum = 0,
.maximum = 127,
.step = 1,
#define HUE_DEFAULT 0x20
#define HUE_DEFAULT 63
.default_value = HUE_DEFAULT,
.flags = 0,
},
......@@ -140,6 +145,33 @@ static const struct ctrl sd_ctrls[] = {
.set = sd_setsharpness,
.get = sd_getsharpness,
},
#define SD_LIGHTING 4
{
{
.id = V4L2_CID_BACKLIGHT_COMPENSATION,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Lighting",
.minimum = 0,
.maximum = 2,
.step = 1,
#define LIGHTING_DEFAULT 1
.default_value = LIGHTING_DEFAULT,
.flags = 0,
},
.set = sd_setlighting,
.get = sd_getlighting,
},
};
static const struct v4l2_pix_format cif_yuv_mode[] = {
{176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
.bytesperline = 176,
.sizeimage = 160 * 144 * 3 / 2,
.colorspace = V4L2_COLORSPACE_SRGB},
{352, 288, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
.bytesperline = 352,
.sizeimage = 352 * 288 * 3 / 2,
.colorspace = V4L2_COLORSPACE_SRGB},
};
static const struct v4l2_pix_format vga_yuv_mode[] = {
......@@ -157,6 +189,25 @@ static const struct v4l2_pix_format vga_yuv_mode[] = {
.colorspace = V4L2_COLORSPACE_SRGB},
};
static const struct v4l2_pix_format model2_mode[] = {
{160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
.bytesperline = 160,
.sizeimage = 160 * 120 * 3 / 2,
.colorspace = V4L2_COLORSPACE_SRGB},
{176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
.bytesperline = 176,
.sizeimage = 176 * 144 * 3 / 2,
.colorspace = V4L2_COLORSPACE_SRGB},
{320, 240, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
.bytesperline = 320,
.sizeimage = 320 * 240,
.colorspace = V4L2_COLORSPACE_SRGB},
{352, 288, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
.bytesperline = 352,
.sizeimage = 352 * 288,
.colorspace = V4L2_COLORSPACE_SRGB},
};
/*
* 01.01.08 - Added for RCA video in support -LO
* This struct is used to init the Model3 cam to use the RCA video in port
......@@ -699,6 +750,11 @@ static const u16 rca_initdata[][3] = {
{0, 0x0003, 0x0111},
};
/* TESTME the old ibmcam driver repeats certain commands to Model1 cameras, we
do the same for now (testing needed to see if this is really necessary) */
static const int cit_model1_ntries = 5;
static const int cit_model1_ntries2 = 2;
static int cit_write_reg(struct gspca_dev *gspca_dev, u16 value, u16 index)
{
struct usb_device *udev = gspca_dev->dev;
......@@ -739,7 +795,116 @@ static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index)
}
/*
* ibmcam_model3_Packet1()
* cit_send_FF_04_02()
*
* This procedure sends magic 3-command prefix to the camera.
* The purpose of this prefix is not known.
*
* History:
* 1/2/00 Created.
*/
static void cit_send_FF_04_02(struct gspca_dev *gspca_dev)
{
cit_write_reg(gspca_dev, 0x00FF, 0x0127);
cit_write_reg(gspca_dev, 0x0004, 0x0124);
cit_write_reg(gspca_dev, 0x0002, 0x0124);
}
static void cit_send_00_04_06(struct gspca_dev *gspca_dev)
{
cit_write_reg(gspca_dev, 0x0000, 0x0127);
cit_write_reg(gspca_dev, 0x0004, 0x0124);
cit_write_reg(gspca_dev, 0x0006, 0x0124);
}
static void cit_send_x_00(struct gspca_dev *gspca_dev, unsigned short x)
{
cit_write_reg(gspca_dev, x, 0x0127);
cit_write_reg(gspca_dev, 0x0000, 0x0124);
}
static void cit_send_x_00_05(struct gspca_dev *gspca_dev, unsigned short x)
{
cit_send_x_00(gspca_dev, x);
cit_write_reg(gspca_dev, 0x0005, 0x0124);
}
static void cit_send_x_00_05_02(struct gspca_dev *gspca_dev, unsigned short x)
{
cit_write_reg(gspca_dev, x, 0x0127);
cit_write_reg(gspca_dev, 0x0000, 0x0124);
cit_write_reg(gspca_dev, 0x0005, 0x0124);
cit_write_reg(gspca_dev, 0x0002, 0x0124);
}
static void cit_send_x_01_00_05(struct gspca_dev *gspca_dev, u16 x)
{
cit_write_reg(gspca_dev, x, 0x0127);
cit_write_reg(gspca_dev, 0x0001, 0x0124);
cit_write_reg(gspca_dev, 0x0000, 0x0124);
cit_write_reg(gspca_dev, 0x0005, 0x0124);
}
static void cit_send_x_00_05_02_01(struct gspca_dev *gspca_dev, u16 x)
{
cit_write_reg(gspca_dev, x, 0x0127);
cit_write_reg(gspca_dev, 0x0000, 0x0124);
cit_write_reg(gspca_dev, 0x0005, 0x0124);
cit_write_reg(gspca_dev, 0x0002, 0x0124);
cit_write_reg(gspca_dev, 0x0001, 0x0124);
}
static void cit_send_x_00_05_02_08_01(struct gspca_dev *gspca_dev, u16 x)
{
cit_write_reg(gspca_dev, x, 0x0127);
cit_write_reg(gspca_dev, 0x0000, 0x0124);
cit_write_reg(gspca_dev, 0x0005, 0x0124);
cit_write_reg(gspca_dev, 0x0002, 0x0124);
cit_write_reg(gspca_dev, 0x0008, 0x0124);
cit_write_reg(gspca_dev, 0x0001, 0x0124);
}
static void cit_Packet_Format1(struct gspca_dev *gspca_dev, u16 fkey, u16 val)
{
cit_send_x_01_00_05(gspca_dev, 0x0088);
cit_send_x_00_05(gspca_dev, fkey);
cit_send_x_00_05_02_08_01(gspca_dev, val);
cit_send_x_00_05(gspca_dev, 0x0088);
cit_send_x_00_05_02_01(gspca_dev, fkey);
cit_send_x_00_05(gspca_dev, 0x0089);
cit_send_x_00(gspca_dev, fkey);
cit_send_00_04_06(gspca_dev);
cit_read_reg(gspca_dev, 0x0126);
cit_send_FF_04_02(gspca_dev);
}
static void cit_PacketFormat2(struct gspca_dev *gspca_dev, u16 fkey, u16 val)
{
cit_send_x_01_00_05(gspca_dev, 0x0088);
cit_send_x_00_05(gspca_dev, fkey);
cit_send_x_00_05_02(gspca_dev, val);
}
static void cit_model2_Packet2(struct gspca_dev *gspca_dev)
{
cit_write_reg(gspca_dev, 0x00ff, 0x012d);
cit_write_reg(gspca_dev, 0xfea3, 0x0124);
}
static void cit_model2_Packet1(struct gspca_dev *gspca_dev, u16 v1, u16 v2)
{
cit_write_reg(gspca_dev, 0x00aa, 0x012d);
cit_write_reg(gspca_dev, 0x00ff, 0x012e);
cit_write_reg(gspca_dev, v1, 0x012f);
cit_write_reg(gspca_dev, 0x00ff, 0x0130);
cit_write_reg(gspca_dev, 0xc719, 0x0124);
cit_write_reg(gspca_dev, v2, 0x0127);
cit_model2_Packet2(gspca_dev);
}
/*
* cit_model3_Packet1()
*
* 00_0078_012d
* 00_0097_012f
......@@ -756,6 +921,29 @@ static void cit_model3_Packet1(struct gspca_dev *gspca_dev, u16 v1, u16 v2)
cit_write_reg(gspca_dev, 0xfea8, 0x0124);
}
static void cit_model4_Packet1(struct gspca_dev *gspca_dev, u16 v1, u16 v2)
{
cit_write_reg(gspca_dev, 0x00aa, 0x012d);
cit_write_reg(gspca_dev, v1, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, v2, 0x0127);
cit_write_reg(gspca_dev, 0xfea8, 0x0124);
}
static void cit_model4_BrightnessPacket(struct gspca_dev *gspca_dev, u16 val)
{
cit_write_reg(gspca_dev, 0x00aa, 0x012d);
cit_write_reg(gspca_dev, 0x0026, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, val, 0x0127);
cit_write_reg(gspca_dev, 0x00aa, 0x0130);
cit_write_reg(gspca_dev, 0x82a8, 0x0124);
cit_write_reg(gspca_dev, 0x0038, 0x012d);
cit_write_reg(gspca_dev, 0x0004, 0x012f);
cit_write_reg(gspca_dev, 0xd145, 0x0124);
cit_write_reg(gspca_dev, 0xfffa, 0x0124);
}
/* this function is called at probe time */
static int sd_config(struct gspca_dev *gspca_dev,
const struct usb_device_id *id)
......@@ -769,16 +957,36 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam = &gspca_dev->cam;
switch (sd->model) {
case CIT_MODEL1:
cam->cam_mode = cif_yuv_mode;
cam->nmodes = ARRAY_SIZE(cif_yuv_mode);
gspca_dev->ctrl_dis = (1 << SD_HUE);
break;
case CIT_MODEL2:
cam->cam_mode = model2_mode + 1; /* no 160x120 */
cam->nmodes = 3;
gspca_dev->ctrl_dis = (1 << SD_CONTRAST) |
(1 << SD_SHARPNESS);
break;
case CIT_MODEL3:
cam->cam_mode = vga_yuv_mode;
cam->nmodes = ARRAY_SIZE(vga_yuv_mode);
gspca_dev->ctrl_dis = (1 << SD_HUE);
gspca_dev->ctrl_dis = (1 << SD_HUE) | (1 << SD_LIGHTING);
sd->stop_on_control_change = 1;
break;
case CIT_MODEL4:
cam->cam_mode = model2_mode;
cam->nmodes = ARRAY_SIZE(model2_mode);
gspca_dev->ctrl_dis = (1 << SD_CONTRAST) |
(1 << SD_SHARPNESS) |
(1 << SD_LIGHTING);
break;
case CIT_IBM_NETCAM_PRO:
cam->cam_mode = vga_yuv_mode;
cam->nmodes = 2; /* no 640 x 480 */
cam->input_flags = V4L2_IN_ST_VFLIP;
gspca_dev->ctrl_dis = ~(1 << SD_CONTRAST);
sd->stop_on_control_change = 1;
break;
}
......@@ -786,6 +994,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->contrast = CONTRAST_DEFAULT;
sd->hue = HUE_DEFAULT;
sd->sharpness = SHARPNESS_DEFAULT;
sd->lighting = LIGHTING_DEFAULT;
return 0;
}
......@@ -988,7 +1197,10 @@ static int sd_init(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
switch (sd->model) {
case CIT_MODEL1:
case CIT_MODEL2:
case CIT_MODEL3:
case CIT_MODEL4:
break; /* All is done in sd_start */
case CIT_IBM_NETCAM_PRO:
cit_init_ibm_netcam_pro(gspca_dev);
......@@ -1001,11 +1213,33 @@ static int sd_init(struct gspca_dev *gspca_dev)
static int cit_set_brightness(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int i;
switch (sd->model) {
case CIT_MODEL1:
/* Model 1: Brightness range 0 - 63 */
cit_Packet_Format1(gspca_dev, 0x0031, sd->brightness);
cit_Packet_Format1(gspca_dev, 0x0032, sd->brightness);
cit_Packet_Format1(gspca_dev, 0x0033, sd->brightness);
break;
case CIT_MODEL2:
/* Model 2: Brightness range 0x60 - 0xee */
/* Scale 0 - 63 to 0x60 - 0xee */
i = 0x60 + sd->brightness * 2254 / 1000;
cit_model2_Packet1(gspca_dev, 0x001a, i);
break;
case CIT_MODEL3:
/* Model 3: Brightness range 'i' in [0x0C..0x3F] */
cit_model3_Packet1(gspca_dev, 0x0036, sd->brightness);
i = sd->brightness;
if (i < 0x0c)
i = 0x0c;
cit_model3_Packet1(gspca_dev, 0x0036, i);
break;
case CIT_MODEL4:
/* Model 4: Brightness range 'i' in [0x04..0xb4] */
/* Scale 0 - 63 to 0x04 - 0xb4 */
i = 0x04 + sd->brightness * 2794 / 1000;
cit_model4_BrightnessPacket(gspca_dev, i);
break;
case CIT_IBM_NETCAM_PRO:
/* No (known) brightness control for ibm netcam pro */
......@@ -1020,6 +1254,20 @@ static int cit_set_contrast(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
switch (sd->model) {
case CIT_MODEL1:
{
/* Scale 0 - 20 to 15 - 0 */
int i, new_contrast = (20 - sd->contrast) * 1000 / 1333;
for (i = 0; i < cit_model1_ntries; i++) {
cit_Packet_Format1(gspca_dev, 0x0014, new_contrast);
cit_send_FF_04_02(gspca_dev);
}
break;
}
case CIT_MODEL2:
case CIT_MODEL4:
/* Models 2, 4 do not have this control. */
break;
case CIT_MODEL3:
{ /* Preset hardware values */
static const struct {
......@@ -1053,9 +1301,46 @@ static int cit_set_hue(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
switch (sd->model) {
case CIT_MODEL3:
/* according to the ibmcam driver this does not work 8/
/* cit_model3_Packet1(gspca_dev, 0x007e, sd->hue); */
case CIT_MODEL1:
/* No hue control for model1 */
break;
case CIT_MODEL2:
cit_model2_Packet1(gspca_dev, 0x0024, sd->hue);
/* cit_model2_Packet1(gspca_dev, 0x0020, sat); */
break;
case CIT_MODEL3: {
/* Model 3: Brightness range 'i' in [0x05..0x37] */
/* TESTME according to the ibmcam driver this does not work */
if (0) {
/* Scale 0 - 127 to 0x05 - 0x37 */
int i = 0x05 + sd->hue * 1000 / 2540;
cit_model3_Packet1(gspca_dev, 0x007e, i);
}
break;
}
case CIT_MODEL4:
/* HDG: taken from ibmcam, setting the color gains does not
* really belong here.
*
* I am not sure r/g/b_gain variables exactly control gain
* of those channels. Most likely they subtly change some
* very internal image processing settings in the camera.
* In any case, here is what they do, and feel free to tweak:
*
* r_gain: seriously affects red gain
* g_gain: seriously affects green gain
* b_gain: seriously affects blue gain
* hue: changes average color from violet (0) to red (0xFF)
*/
cit_write_reg(gspca_dev, 0x00aa, 0x012d);
cit_write_reg(gspca_dev, 0x001e, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, 160, 0x0127); /* Green gain */
cit_write_reg(gspca_dev, 160, 0x012e); /* Red gain */
cit_write_reg(gspca_dev, 160, 0x0130); /* Blue gain */
cit_write_reg(gspca_dev, 0x8a28, 0x0124);
cit_write_reg(gspca_dev, sd->hue, 0x012d); /* Hue */
cit_write_reg(gspca_dev, 0xf545, 0x0124);
break;
case CIT_IBM_NETCAM_PRO:
/* No hue control for ibm netcam pro */
......@@ -1069,6 +1354,19 @@ static int cit_set_sharpness(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
switch (sd->model) {
case CIT_MODEL1: {
int i;
const unsigned short sa[] = {
0x11, 0x13, 0x16, 0x18, 0x1a, 0x8, 0x0a };
for (i = 0; i < cit_model1_ntries; i++)
cit_PacketFormat2(gspca_dev, 0x0013, sa[sd->sharpness]);
break;
}
case CIT_MODEL2:
case CIT_MODEL4:
/* Models 2, 4 do not have this control */
break;
case CIT_MODEL3:
{ /*
* "Use a table of magic numbers.
......@@ -1102,17 +1400,62 @@ static int cit_set_sharpness(struct gspca_dev *gspca_dev)
return 0;
}
/*
* cit_set_lighting()
*
* Camera model 1:
* We have 3 levels of lighting conditions: 0=Bright, 1=Medium, 2=Low.
*
* Camera model 2:
* We have 16 levels of lighting, 0 for bright light and up to 15 for
* low light. But values above 5 or so are useless because camera is
* not really capable to produce anything worth viewing at such light.
* This setting may be altered only in certain camera state.
*
* Low lighting forces slower FPS.
*
* History:
* 1/5/00 Created.
* 2/20/00 Added support for Model 2 cameras.
*/
static void cit_set_lighting(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
switch (sd->model) {
case CIT_MODEL1: {
int i;
for (i = 0; i < cit_model1_ntries; i++)
cit_Packet_Format1(gspca_dev, 0x0027, sd->lighting);
break;
}
case CIT_MODEL2:
case CIT_MODEL3:
case CIT_MODEL4:
case CIT_IBM_NETCAM_PRO:
break;
}
}
static int cit_restart_stream(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
switch (sd->model) {
case CIT_MODEL1:
case CIT_MODEL3:
case CIT_IBM_NETCAM_PRO:
cit_write_reg(gspca_dev, 0x0001, 0x0114);
/* Fall through */
case CIT_MODEL2:
case CIT_MODEL4:
cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */
usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe);
cit_write_reg(gspca_dev, 0x0001, 0x0113);
/* This happens repeatedly while streaming with the ibm netcam
pro and the ibmcam driver did it for model3 after changing
settings, but it does not seem to have any effect. */
/* cit_write_reg(gspca_dev, 0x0001, 0x0113); */
break;
}
sd->sof_read = 0;
......@@ -1120,8 +1463,402 @@ static int cit_restart_stream(struct gspca_dev *gspca_dev)
return 0;
}
static int cit_start_model1(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int i, clock_div = 0;
cit_read_reg(gspca_dev, 0x0128);
cit_read_reg(gspca_dev, 0x0100);
cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On */
cit_read_reg(gspca_dev, 0x0100);
cit_write_reg(gspca_dev, 0x81, 0x0100); /* LED Off */
cit_read_reg(gspca_dev, 0x0100);
cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On */
cit_write_reg(gspca_dev, 0x01, 0x0108);
cit_write_reg(gspca_dev, 0x03, 0x0112);
cit_read_reg(gspca_dev, 0x0115);
cit_write_reg(gspca_dev, 0x06, 0x0115);
cit_read_reg(gspca_dev, 0x0116);
cit_write_reg(gspca_dev, 0x44, 0x0116);
cit_read_reg(gspca_dev, 0x0116);
cit_write_reg(gspca_dev, 0x40, 0x0116);
cit_read_reg(gspca_dev, 0x0115);
cit_write_reg(gspca_dev, 0x0e, 0x0115);
cit_write_reg(gspca_dev, 0x19, 0x012c);
cit_Packet_Format1(gspca_dev, 0x00, 0x1e);
cit_Packet_Format1(gspca_dev, 0x39, 0x0d);
cit_Packet_Format1(gspca_dev, 0x39, 0x09);
cit_Packet_Format1(gspca_dev, 0x3b, 0x00);
cit_Packet_Format1(gspca_dev, 0x28, 0x22);
cit_Packet_Format1(gspca_dev, 0x27, 0x00);
cit_Packet_Format1(gspca_dev, 0x2b, 0x1f);
cit_Packet_Format1(gspca_dev, 0x39, 0x08);
for (i = 0; i < cit_model1_ntries; i++)
cit_Packet_Format1(gspca_dev, 0x2c, 0x00);
for (i = 0; i < cit_model1_ntries; i++)
cit_Packet_Format1(gspca_dev, 0x30, 0x14);
cit_PacketFormat2(gspca_dev, 0x39, 0x02);
cit_PacketFormat2(gspca_dev, 0x01, 0xe1);
cit_PacketFormat2(gspca_dev, 0x02, 0xcd);
cit_PacketFormat2(gspca_dev, 0x03, 0xcd);
cit_PacketFormat2(gspca_dev, 0x04, 0xfa);
cit_PacketFormat2(gspca_dev, 0x3f, 0xff);
cit_PacketFormat2(gspca_dev, 0x39, 0x00);
cit_PacketFormat2(gspca_dev, 0x39, 0x02);
cit_PacketFormat2(gspca_dev, 0x0a, 0x37);
cit_PacketFormat2(gspca_dev, 0x0b, 0xb8);
cit_PacketFormat2(gspca_dev, 0x0c, 0xf3);
cit_PacketFormat2(gspca_dev, 0x0d, 0xe3);
cit_PacketFormat2(gspca_dev, 0x0e, 0x0d);
cit_PacketFormat2(gspca_dev, 0x0f, 0xf2);
cit_PacketFormat2(gspca_dev, 0x10, 0xd5);
cit_PacketFormat2(gspca_dev, 0x11, 0xba);
cit_PacketFormat2(gspca_dev, 0x12, 0x53);
cit_PacketFormat2(gspca_dev, 0x3f, 0xff);
cit_PacketFormat2(gspca_dev, 0x39, 0x00);
cit_PacketFormat2(gspca_dev, 0x39, 0x02);
cit_PacketFormat2(gspca_dev, 0x16, 0x00);
cit_PacketFormat2(gspca_dev, 0x17, 0x28);
cit_PacketFormat2(gspca_dev, 0x18, 0x7d);
cit_PacketFormat2(gspca_dev, 0x19, 0xbe);
cit_PacketFormat2(gspca_dev, 0x3f, 0xff);
cit_PacketFormat2(gspca_dev, 0x39, 0x00);
for (i = 0; i < cit_model1_ntries; i++)
cit_Packet_Format1(gspca_dev, 0x00, 0x18);
for (i = 0; i < cit_model1_ntries; i++)
cit_Packet_Format1(gspca_dev, 0x13, 0x18);
for (i = 0; i < cit_model1_ntries; i++)
cit_Packet_Format1(gspca_dev, 0x14, 0x06);
/* TESTME These are handled through controls
KEEP until someone can test leaving this out is ok */
if (0) {
/* This is default brightness */
for (i = 0; i < cit_model1_ntries; i++)
cit_Packet_Format1(gspca_dev, 0x31, 0x37);
for (i = 0; i < cit_model1_ntries; i++)
cit_Packet_Format1(gspca_dev, 0x32, 0x46);
for (i = 0; i < cit_model1_ntries; i++)
cit_Packet_Format1(gspca_dev, 0x33, 0x55);
}
cit_Packet_Format1(gspca_dev, 0x2e, 0x04);
for (i = 0; i < cit_model1_ntries; i++)
cit_Packet_Format1(gspca_dev, 0x2d, 0x04);
for (i = 0; i < cit_model1_ntries; i++)
cit_Packet_Format1(gspca_dev, 0x29, 0x80);
cit_Packet_Format1(gspca_dev, 0x2c, 0x01);
cit_Packet_Format1(gspca_dev, 0x30, 0x17);
cit_Packet_Format1(gspca_dev, 0x39, 0x08);
for (i = 0; i < cit_model1_ntries; i++)
cit_Packet_Format1(gspca_dev, 0x34, 0x00);
cit_write_reg(gspca_dev, 0x00, 0x0101);
cit_write_reg(gspca_dev, 0x00, 0x010a);
switch (gspca_dev->width) {
case 128: /* 128x96 */
cit_write_reg(gspca_dev, 0x80, 0x0103);
cit_write_reg(gspca_dev, 0x60, 0x0105);
cit_write_reg(gspca_dev, 0x0c, 0x010b);
cit_write_reg(gspca_dev, 0x04, 0x011b); /* Same everywhere */
cit_write_reg(gspca_dev, 0x0b, 0x011d);
cit_write_reg(gspca_dev, 0x00, 0x011e); /* Same everywhere */
cit_write_reg(gspca_dev, 0x00, 0x0129);
clock_div = 3;
break;
case 176: /* 176x144 */
cit_write_reg(gspca_dev, 0xb0, 0x0103);
cit_write_reg(gspca_dev, 0x8f, 0x0105);
cit_write_reg(gspca_dev, 0x06, 0x010b);
cit_write_reg(gspca_dev, 0x04, 0x011b); /* Same everywhere */
cit_write_reg(gspca_dev, 0x0d, 0x011d);
cit_write_reg(gspca_dev, 0x00, 0x011e); /* Same everywhere */
cit_write_reg(gspca_dev, 0x03, 0x0129);
clock_div = 3;
break;
case 352: /* 352x288 */
cit_write_reg(gspca_dev, 0xb0, 0x0103);
cit_write_reg(gspca_dev, 0x90, 0x0105);
cit_write_reg(gspca_dev, 0x02, 0x010b);
cit_write_reg(gspca_dev, 0x04, 0x011b); /* Same everywhere */
cit_write_reg(gspca_dev, 0x05, 0x011d);
cit_write_reg(gspca_dev, 0x00, 0x011e); /* Same everywhere */
cit_write_reg(gspca_dev, 0x00, 0x0129);
clock_div = 5;
break;
}
cit_write_reg(gspca_dev, 0xff, 0x012b);
/* TESTME These are handled through controls
KEEP until someone can test leaving this out is ok */
if (0) {
/* This is another brightness - don't know why */
for (i = 0; i < cit_model1_ntries; i++)
cit_Packet_Format1(gspca_dev, 0x31, 0xc3);
for (i = 0; i < cit_model1_ntries; i++)
cit_Packet_Format1(gspca_dev, 0x32, 0xd2);
for (i = 0; i < cit_model1_ntries; i++)
cit_Packet_Format1(gspca_dev, 0x33, 0xe1);
/* Default contrast */
for (i = 0; i < cit_model1_ntries; i++)
cit_Packet_Format1(gspca_dev, 0x14, 0x0a);
/* Default sharpness */
for (i = 0; i < cit_model1_ntries2; i++)
cit_PacketFormat2(gspca_dev, 0x13, 0x1a);
/* Default lighting conditions */
cit_Packet_Format1(gspca_dev, 0x0027, sd->lighting);
}
/* Assorted init */
switch (gspca_dev->width) {
case 128: /* 128x96 */
cit_Packet_Format1(gspca_dev, 0x2b, 0x1e);
cit_write_reg(gspca_dev, 0xc9, 0x0119); /* Same everywhere */
cit_write_reg(gspca_dev, 0x80, 0x0109); /* Same everywhere */
cit_write_reg(gspca_dev, 0x36, 0x0102);
cit_write_reg(gspca_dev, 0x1a, 0x0104);
cit_write_reg(gspca_dev, 0x04, 0x011a); /* Same everywhere */
cit_write_reg(gspca_dev, 0x2b, 0x011c);
cit_write_reg(gspca_dev, 0x23, 0x012a); /* Same everywhere */
break;
case 176: /* 176x144 */
cit_Packet_Format1(gspca_dev, 0x2b, 0x1e);
cit_write_reg(gspca_dev, 0xc9, 0x0119); /* Same everywhere */
cit_write_reg(gspca_dev, 0x80, 0x0109); /* Same everywhere */
cit_write_reg(gspca_dev, 0x04, 0x0102);
cit_write_reg(gspca_dev, 0x02, 0x0104);
cit_write_reg(gspca_dev, 0x04, 0x011a); /* Same everywhere */
cit_write_reg(gspca_dev, 0x2b, 0x011c);
cit_write_reg(gspca_dev, 0x23, 0x012a); /* Same everywhere */
break;
case 352: /* 352x288 */
cit_Packet_Format1(gspca_dev, 0x2b, 0x1f);
cit_write_reg(gspca_dev, 0xc9, 0x0119); /* Same everywhere */
cit_write_reg(gspca_dev, 0x80, 0x0109); /* Same everywhere */
cit_write_reg(gspca_dev, 0x08, 0x0102);
cit_write_reg(gspca_dev, 0x01, 0x0104);
cit_write_reg(gspca_dev, 0x04, 0x011a); /* Same everywhere */
cit_write_reg(gspca_dev, 0x2f, 0x011c);
cit_write_reg(gspca_dev, 0x23, 0x012a); /* Same everywhere */
break;
}
cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On */
cit_write_reg(gspca_dev, clock_div, 0x0111);
sd->sof_len = 4;
return 0;
}
static int cit_start_model2(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int clock_div = 0;
cit_write_reg(gspca_dev, 0x0000, 0x0100); /* LED on */
cit_read_reg(gspca_dev, 0x0116);
cit_write_reg(gspca_dev, 0x0060, 0x0116);
cit_write_reg(gspca_dev, 0x0002, 0x0112);
cit_write_reg(gspca_dev, 0x00bc, 0x012c);
cit_write_reg(gspca_dev, 0x0008, 0x012b);
cit_write_reg(gspca_dev, 0x0000, 0x0108);
cit_write_reg(gspca_dev, 0x0001, 0x0133);
cit_write_reg(gspca_dev, 0x0001, 0x0102);
switch (gspca_dev->width) {
case 176: /* 176x144 */
cit_write_reg(gspca_dev, 0x002c, 0x0103); /* All except 320x240 */
cit_write_reg(gspca_dev, 0x0000, 0x0104); /* Same */
cit_write_reg(gspca_dev, 0x0024, 0x0105); /* 176x144, 352x288 */
cit_write_reg(gspca_dev, 0x00b9, 0x010a); /* Unique to this mode */
cit_write_reg(gspca_dev, 0x0038, 0x0119); /* Unique to this mode */
/* TESTME HDG: this does not seem right
(it is 2 for all other resolutions) */
sd->sof_len = 10;
break;
case 320: /* 320x240 */
cit_write_reg(gspca_dev, 0x0028, 0x0103); /* Unique to this mode */
cit_write_reg(gspca_dev, 0x0000, 0x0104); /* Same */
cit_write_reg(gspca_dev, 0x001e, 0x0105); /* 320x240, 352x240 */
cit_write_reg(gspca_dev, 0x0039, 0x010a); /* All except 176x144 */
cit_write_reg(gspca_dev, 0x0070, 0x0119); /* All except 176x144 */
sd->sof_len = 2;
break;
/* case VIDEOSIZE_352x240: */
cit_write_reg(gspca_dev, 0x002c, 0x0103); /* All except 320x240 */
cit_write_reg(gspca_dev, 0x0000, 0x0104); /* Same */
cit_write_reg(gspca_dev, 0x001e, 0x0105); /* 320x240, 352x240 */
cit_write_reg(gspca_dev, 0x0039, 0x010a); /* All except 176x144 */
cit_write_reg(gspca_dev, 0x0070, 0x0119); /* All except 176x144 */
sd->sof_len = 2;
break;
case 352: /* 352x288 */
cit_write_reg(gspca_dev, 0x002c, 0x0103); /* All except 320x240 */
cit_write_reg(gspca_dev, 0x0000, 0x0104); /* Same */
cit_write_reg(gspca_dev, 0x0024, 0x0105); /* 176x144, 352x288 */
cit_write_reg(gspca_dev, 0x0039, 0x010a); /* All except 176x144 */
cit_write_reg(gspca_dev, 0x0070, 0x0119); /* All except 176x144 */
sd->sof_len = 2;
break;
}
cit_write_reg(gspca_dev, 0x0000, 0x0100); /* LED on */
switch (gspca_dev->width) {
case 176: /* 176x144 */
cit_write_reg(gspca_dev, 0x0050, 0x0111);
cit_write_reg(gspca_dev, 0x00d0, 0x0111);
break;
case 320: /* 320x240 */
case 352: /* 352x288 */
cit_write_reg(gspca_dev, 0x0040, 0x0111);
cit_write_reg(gspca_dev, 0x00c0, 0x0111);
break;
}
cit_write_reg(gspca_dev, 0x009b, 0x010f);
cit_write_reg(gspca_dev, 0x00bb, 0x010f);
/*
* Hardware settings, may affect CMOS sensor; not user controls!
* -------------------------------------------------------------
* 0x0004: no effect
* 0x0006: hardware effect
* 0x0008: no effect
* 0x000a: stops video stream, probably important h/w setting
* 0x000c: changes color in hardware manner (not user setting)
* 0x0012: changes number of colors (does not affect speed)
* 0x002a: no effect
* 0x002c: hardware setting (related to scan lines)
* 0x002e: stops video stream, probably important h/w setting
*/
cit_model2_Packet1(gspca_dev, 0x000a, 0x005c);
cit_model2_Packet1(gspca_dev, 0x0004, 0x0000);
cit_model2_Packet1(gspca_dev, 0x0006, 0x00fb);
cit_model2_Packet1(gspca_dev, 0x0008, 0x0000);
cit_model2_Packet1(gspca_dev, 0x000c, 0x0009);
cit_model2_Packet1(gspca_dev, 0x0012, 0x000a);
cit_model2_Packet1(gspca_dev, 0x002a, 0x0000);
cit_model2_Packet1(gspca_dev, 0x002c, 0x0000);
cit_model2_Packet1(gspca_dev, 0x002e, 0x0008);
/*
* Function 0x0030 pops up all over the place. Apparently
* it is a hardware control register, with every bit assigned to
* do something.
*/
cit_model2_Packet1(gspca_dev, 0x0030, 0x0000);
/*
* Magic control of CMOS sensor. Only lower values like
* 0-3 work, and picture shifts left or right. Don't change.
*/
switch (gspca_dev->width) {
case 176: /* 176x144 */
cit_model2_Packet1(gspca_dev, 0x0014, 0x0002);
cit_model2_Packet1(gspca_dev, 0x0016, 0x0002); /* Horizontal shift */
cit_model2_Packet1(gspca_dev, 0x0018, 0x004a); /* Another hardware setting */
clock_div = 6;
break;
case 320: /* 320x240 */
cit_model2_Packet1(gspca_dev, 0x0014, 0x0009);
cit_model2_Packet1(gspca_dev, 0x0016, 0x0005); /* Horizontal shift */
cit_model2_Packet1(gspca_dev, 0x0018, 0x0044); /* Another hardware setting */
clock_div = 8;
break;
/* case VIDEOSIZE_352x240: */
/* This mode doesn't work as Windows programs it; changed to work */
cit_model2_Packet1(gspca_dev, 0x0014, 0x0009); /* Windows sets this to 8 */
cit_model2_Packet1(gspca_dev, 0x0016, 0x0003); /* Horizontal shift */
cit_model2_Packet1(gspca_dev, 0x0018, 0x0044); /* Windows sets this to 0x0045 */
clock_div = 10;
break;
case 352: /* 352x288 */
cit_model2_Packet1(gspca_dev, 0x0014, 0x0003);
cit_model2_Packet1(gspca_dev, 0x0016, 0x0002); /* Horizontal shift */
cit_model2_Packet1(gspca_dev, 0x0018, 0x004a); /* Another hardware setting */
clock_div = 16;
break;
}
/* TESTME These are handled through controls
KEEP until someone can test leaving this out is ok */
if (0)
cit_model2_Packet1(gspca_dev, 0x001a, 0x005a);
/*
* We have our own frame rate setting varying from 0 (slowest) to 6
* (fastest). The camera model 2 allows frame rate in range [0..0x1F]
# where 0 is also the slowest setting. However for all practical
# reasons high settings make no sense because USB is not fast enough
# to support high FPS. Be aware that the picture datastream will be
# severely disrupted if you ask for frame rate faster than allowed
# for the video size - see below:
*
* Allowable ranges (obtained experimentally on OHCI, K6-3, 450 MHz):
* -----------------------------------------------------------------
* 176x144: [6..31]
* 320x240: [8..31]
* 352x240: [10..31]
* 352x288: [16..31] I have to raise lower threshold for stability...
*
* As usual, slower FPS provides better sensitivity.
*/
cit_model2_Packet1(gspca_dev, 0x001c, clock_div);
/*
* This setting does not visibly affect pictures; left it here
* because it was present in Windows USB data stream. This function
* does not allow arbitrary values and apparently is a bit mask, to
* be activated only at appropriate time. Don't change it randomly!
*/
switch (gspca_dev->width) {
case 176: /* 176x144 */
cit_model2_Packet1(gspca_dev, 0x0026, 0x00c2);
break;
case 320: /* 320x240 */
cit_model2_Packet1(gspca_dev, 0x0026, 0x0044);
break;
/* case VIDEOSIZE_352x240: */
cit_model2_Packet1(gspca_dev, 0x0026, 0x0046);
break;
case 352: /* 352x288 */
cit_model2_Packet1(gspca_dev, 0x0026, 0x0048);
break;
}
/* FIXME this cannot be changed while streaming, so we
should report a grabbed flag for this control. */
cit_model2_Packet1(gspca_dev, 0x0028, sd->lighting);
/* color balance rg2 */
cit_model2_Packet1(gspca_dev, 0x001e, 0x002f);
/* saturation */
cit_model2_Packet1(gspca_dev, 0x0020, 0x0034);
/* color balance yb */
cit_model2_Packet1(gspca_dev, 0x0022, 0x00a0);
/* Hardware control command */
cit_model2_Packet1(gspca_dev, 0x0030, 0x0004);
return 0;
}
static int cit_start_model3(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
const unsigned short compression = 0; /* 0=none, 7=best frame rate */
int i, clock_div = 0;
......@@ -1143,7 +1880,7 @@ static int cit_start_model3(struct gspca_dev *gspca_dev)
cit_read_reg(gspca_dev, 0x0115);
cit_write_reg(gspca_dev, 0x000b, 0x0115);
/* HDG not in ibmcam driver, added to see if it helps with
/* TESTME HDG not in ibmcam driver, added to see if it helps with
auto-detecting between model3 and ibm netcamera pro */
if (0) {
cit_write_reg(gspca_dev, 0x0078, 0x012d);
......@@ -1354,11 +2091,339 @@ static int cit_start_model3(struct gspca_dev *gspca_dev)
}
}
sd->sof_len = 4;
return 0;
}
static int cit_start_model4(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
cit_write_reg(gspca_dev, 0x0000, 0x0100);
cit_write_reg(gspca_dev, 0x00c0, 0x0111);
cit_write_reg(gspca_dev, 0x00bc, 0x012c);
cit_write_reg(gspca_dev, 0x0080, 0x012b);
cit_write_reg(gspca_dev, 0x0000, 0x0108);
cit_write_reg(gspca_dev, 0x0001, 0x0133);
cit_write_reg(gspca_dev, 0x009b, 0x010f);
cit_write_reg(gspca_dev, 0x00bb, 0x010f);
cit_model4_Packet1(gspca_dev, 0x0038, 0x0000);
cit_model4_Packet1(gspca_dev, 0x000a, 0x005c);
cit_write_reg(gspca_dev, 0x00aa, 0x012d);
cit_write_reg(gspca_dev, 0x0004, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, 0x0000, 0x0127);
cit_write_reg(gspca_dev, 0x00fb, 0x012e);
cit_write_reg(gspca_dev, 0x0000, 0x0130);
cit_write_reg(gspca_dev, 0x8a28, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012f);
cit_write_reg(gspca_dev, 0xd055, 0x0124);
cit_write_reg(gspca_dev, 0x000c, 0x0127);
cit_write_reg(gspca_dev, 0x0009, 0x012e);
cit_write_reg(gspca_dev, 0xaa28, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012d);
cit_write_reg(gspca_dev, 0x0012, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, 0x0008, 0x0127);
cit_write_reg(gspca_dev, 0x00aa, 0x0130);
cit_write_reg(gspca_dev, 0x82a8, 0x0124);
cit_write_reg(gspca_dev, 0x002a, 0x012d);
cit_write_reg(gspca_dev, 0x0000, 0x012f);
cit_write_reg(gspca_dev, 0xd145, 0x0124);
cit_write_reg(gspca_dev, 0xfffa, 0x0124);
cit_model4_Packet1(gspca_dev, 0x0034, 0x0000);
switch (gspca_dev->width) {
case 128: /* 128x96 */
cit_write_reg(gspca_dev, 0x0070, 0x0119);
cit_write_reg(gspca_dev, 0x00d0, 0x0111);
cit_write_reg(gspca_dev, 0x0039, 0x010a);
cit_write_reg(gspca_dev, 0x0001, 0x0102);
cit_write_reg(gspca_dev, 0x0028, 0x0103);
cit_write_reg(gspca_dev, 0x0000, 0x0104);
cit_write_reg(gspca_dev, 0x001e, 0x0105);
cit_write_reg(gspca_dev, 0x00aa, 0x012d);
cit_write_reg(gspca_dev, 0x0016, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, 0x000a, 0x0127);
cit_write_reg(gspca_dev, 0x00aa, 0x0130);
cit_write_reg(gspca_dev, 0x82a8, 0x0124);
cit_write_reg(gspca_dev, 0x0014, 0x012d);
cit_write_reg(gspca_dev, 0x0008, 0x012f);
cit_write_reg(gspca_dev, 0xd145, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012e);
cit_write_reg(gspca_dev, 0x001a, 0x0130);
cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
cit_write_reg(gspca_dev, 0x005a, 0x012d);
cit_write_reg(gspca_dev, 0x9545, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x0127);
cit_write_reg(gspca_dev, 0x0018, 0x012e);
cit_write_reg(gspca_dev, 0x0043, 0x0130);
cit_write_reg(gspca_dev, 0x8a28, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012f);
cit_write_reg(gspca_dev, 0xd055, 0x0124);
cit_write_reg(gspca_dev, 0x001c, 0x0127);
cit_write_reg(gspca_dev, 0x00eb, 0x012e);
cit_write_reg(gspca_dev, 0xaa28, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012d);
cit_write_reg(gspca_dev, 0x0032, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, 0x0000, 0x0127);
cit_write_reg(gspca_dev, 0x00aa, 0x0130);
cit_write_reg(gspca_dev, 0x82a8, 0x0124);
cit_write_reg(gspca_dev, 0x0036, 0x012d);
cit_write_reg(gspca_dev, 0x0008, 0x012f);
cit_write_reg(gspca_dev, 0xd145, 0x0124);
cit_write_reg(gspca_dev, 0xfffa, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012d);
cit_write_reg(gspca_dev, 0x001e, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, 0x0017, 0x0127);
cit_write_reg(gspca_dev, 0x0013, 0x012e);
cit_write_reg(gspca_dev, 0x0031, 0x0130);
cit_write_reg(gspca_dev, 0x8a28, 0x0124);
cit_write_reg(gspca_dev, 0x0017, 0x012d);
cit_write_reg(gspca_dev, 0x0078, 0x012f);
cit_write_reg(gspca_dev, 0xd145, 0x0124);
cit_write_reg(gspca_dev, 0x0000, 0x0127);
cit_write_reg(gspca_dev, 0xfea8, 0x0124);
sd->sof_len = 2;
break;
case 160: /* 160x120 */
cit_write_reg(gspca_dev, 0x0038, 0x0119);
cit_write_reg(gspca_dev, 0x00d0, 0x0111);
cit_write_reg(gspca_dev, 0x00b9, 0x010a);
cit_write_reg(gspca_dev, 0x0001, 0x0102);
cit_write_reg(gspca_dev, 0x0028, 0x0103);
cit_write_reg(gspca_dev, 0x0000, 0x0104);
cit_write_reg(gspca_dev, 0x001e, 0x0105);
cit_write_reg(gspca_dev, 0x00aa, 0x012d);
cit_write_reg(gspca_dev, 0x0016, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, 0x000b, 0x0127);
cit_write_reg(gspca_dev, 0x00aa, 0x0130);
cit_write_reg(gspca_dev, 0x82a8, 0x0124);
cit_write_reg(gspca_dev, 0x0014, 0x012d);
cit_write_reg(gspca_dev, 0x0008, 0x012f);
cit_write_reg(gspca_dev, 0xd145, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012e);
cit_write_reg(gspca_dev, 0x001a, 0x0130);
cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
cit_write_reg(gspca_dev, 0x005a, 0x012d);
cit_write_reg(gspca_dev, 0x9545, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x0127);
cit_write_reg(gspca_dev, 0x0018, 0x012e);
cit_write_reg(gspca_dev, 0x0043, 0x0130);
cit_write_reg(gspca_dev, 0x8a28, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012f);
cit_write_reg(gspca_dev, 0xd055, 0x0124);
cit_write_reg(gspca_dev, 0x001c, 0x0127);
cit_write_reg(gspca_dev, 0x00c7, 0x012e);
cit_write_reg(gspca_dev, 0xaa28, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012d);
cit_write_reg(gspca_dev, 0x0032, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, 0x0025, 0x0127);
cit_write_reg(gspca_dev, 0x00aa, 0x0130);
cit_write_reg(gspca_dev, 0x82a8, 0x0124);
cit_write_reg(gspca_dev, 0x0036, 0x012d);
cit_write_reg(gspca_dev, 0x0008, 0x012f);
cit_write_reg(gspca_dev, 0xd145, 0x0124);
cit_write_reg(gspca_dev, 0xfffa, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012d);
cit_write_reg(gspca_dev, 0x001e, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, 0x0048, 0x0127);
cit_write_reg(gspca_dev, 0x0035, 0x012e);
cit_write_reg(gspca_dev, 0x00d0, 0x0130);
cit_write_reg(gspca_dev, 0x8a28, 0x0124);
cit_write_reg(gspca_dev, 0x0048, 0x012d);
cit_write_reg(gspca_dev, 0x0090, 0x012f);
cit_write_reg(gspca_dev, 0xd145, 0x0124);
cit_write_reg(gspca_dev, 0x0001, 0x0127);
cit_write_reg(gspca_dev, 0xfea8, 0x0124);
sd->sof_len = 2;
break;
case 176: /* 176x144 */
cit_write_reg(gspca_dev, 0x0038, 0x0119);
cit_write_reg(gspca_dev, 0x00d0, 0x0111);
cit_write_reg(gspca_dev, 0x00b9, 0x010a);
cit_write_reg(gspca_dev, 0x0001, 0x0102);
cit_write_reg(gspca_dev, 0x002c, 0x0103);
cit_write_reg(gspca_dev, 0x0000, 0x0104);
cit_write_reg(gspca_dev, 0x0024, 0x0105);
cit_write_reg(gspca_dev, 0x00aa, 0x012d);
cit_write_reg(gspca_dev, 0x0016, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, 0x0007, 0x0127);
cit_write_reg(gspca_dev, 0x00aa, 0x0130);
cit_write_reg(gspca_dev, 0x82a8, 0x0124);
cit_write_reg(gspca_dev, 0x0014, 0x012d);
cit_write_reg(gspca_dev, 0x0001, 0x012f);
cit_write_reg(gspca_dev, 0xd145, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012e);
cit_write_reg(gspca_dev, 0x001a, 0x0130);
cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
cit_write_reg(gspca_dev, 0x005e, 0x012d);
cit_write_reg(gspca_dev, 0x9545, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x0127);
cit_write_reg(gspca_dev, 0x0018, 0x012e);
cit_write_reg(gspca_dev, 0x0049, 0x0130);
cit_write_reg(gspca_dev, 0x8a28, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012f);
cit_write_reg(gspca_dev, 0xd055, 0x0124);
cit_write_reg(gspca_dev, 0x001c, 0x0127);
cit_write_reg(gspca_dev, 0x00c7, 0x012e);
cit_write_reg(gspca_dev, 0xaa28, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012d);
cit_write_reg(gspca_dev, 0x0032, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, 0x0028, 0x0127);
cit_write_reg(gspca_dev, 0x00aa, 0x0130);
cit_write_reg(gspca_dev, 0x82a8, 0x0124);
cit_write_reg(gspca_dev, 0x0036, 0x012d);
cit_write_reg(gspca_dev, 0x0008, 0x012f);
cit_write_reg(gspca_dev, 0xd145, 0x0124);
cit_write_reg(gspca_dev, 0xfffa, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012d);
cit_write_reg(gspca_dev, 0x001e, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, 0x0010, 0x0127);
cit_write_reg(gspca_dev, 0x0013, 0x012e);
cit_write_reg(gspca_dev, 0x002a, 0x0130);
cit_write_reg(gspca_dev, 0x8a28, 0x0124);
cit_write_reg(gspca_dev, 0x0010, 0x012d);
cit_write_reg(gspca_dev, 0x006d, 0x012f);
cit_write_reg(gspca_dev, 0xd145, 0x0124);
cit_write_reg(gspca_dev, 0x0001, 0x0127);
cit_write_reg(gspca_dev, 0xfea8, 0x0124);
/* TESTME HDG: this does not seem right
(it is 2 for all other resolutions) */
sd->sof_len = 10;
break;
case 320: /* 320x240 */
cit_write_reg(gspca_dev, 0x0070, 0x0119);
cit_write_reg(gspca_dev, 0x00d0, 0x0111);
cit_write_reg(gspca_dev, 0x0039, 0x010a);
cit_write_reg(gspca_dev, 0x0001, 0x0102);
cit_write_reg(gspca_dev, 0x0028, 0x0103);
cit_write_reg(gspca_dev, 0x0000, 0x0104);
cit_write_reg(gspca_dev, 0x001e, 0x0105);
cit_write_reg(gspca_dev, 0x00aa, 0x012d);
cit_write_reg(gspca_dev, 0x0016, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, 0x000a, 0x0127);
cit_write_reg(gspca_dev, 0x00aa, 0x0130);
cit_write_reg(gspca_dev, 0x82a8, 0x0124);
cit_write_reg(gspca_dev, 0x0014, 0x012d);
cit_write_reg(gspca_dev, 0x0008, 0x012f);
cit_write_reg(gspca_dev, 0xd145, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012e);
cit_write_reg(gspca_dev, 0x001a, 0x0130);
cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
cit_write_reg(gspca_dev, 0x005a, 0x012d);
cit_write_reg(gspca_dev, 0x9545, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x0127);
cit_write_reg(gspca_dev, 0x0018, 0x012e);
cit_write_reg(gspca_dev, 0x0043, 0x0130);
cit_write_reg(gspca_dev, 0x8a28, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012f);
cit_write_reg(gspca_dev, 0xd055, 0x0124);
cit_write_reg(gspca_dev, 0x001c, 0x0127);
cit_write_reg(gspca_dev, 0x00eb, 0x012e);
cit_write_reg(gspca_dev, 0xaa28, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012d);
cit_write_reg(gspca_dev, 0x0032, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, 0x0000, 0x0127);
cit_write_reg(gspca_dev, 0x00aa, 0x0130);
cit_write_reg(gspca_dev, 0x82a8, 0x0124);
cit_write_reg(gspca_dev, 0x0036, 0x012d);
cit_write_reg(gspca_dev, 0x0008, 0x012f);
cit_write_reg(gspca_dev, 0xd145, 0x0124);
cit_write_reg(gspca_dev, 0xfffa, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012d);
cit_write_reg(gspca_dev, 0x001e, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, 0x0017, 0x0127);
cit_write_reg(gspca_dev, 0x0013, 0x012e);
cit_write_reg(gspca_dev, 0x0031, 0x0130);
cit_write_reg(gspca_dev, 0x8a28, 0x0124);
cit_write_reg(gspca_dev, 0x0017, 0x012d);
cit_write_reg(gspca_dev, 0x0078, 0x012f);
cit_write_reg(gspca_dev, 0xd145, 0x0124);
cit_write_reg(gspca_dev, 0x0000, 0x0127);
cit_write_reg(gspca_dev, 0xfea8, 0x0124);
sd->sof_len = 2;
break;
case 352: /* 352x288 */
cit_write_reg(gspca_dev, 0x0070, 0x0119);
cit_write_reg(gspca_dev, 0x00c0, 0x0111);
cit_write_reg(gspca_dev, 0x0039, 0x010a);
cit_write_reg(gspca_dev, 0x0001, 0x0102);
cit_write_reg(gspca_dev, 0x002c, 0x0103);
cit_write_reg(gspca_dev, 0x0000, 0x0104);
cit_write_reg(gspca_dev, 0x0024, 0x0105);
cit_write_reg(gspca_dev, 0x00aa, 0x012d);
cit_write_reg(gspca_dev, 0x0016, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, 0x0006, 0x0127);
cit_write_reg(gspca_dev, 0x00aa, 0x0130);
cit_write_reg(gspca_dev, 0x82a8, 0x0124);
cit_write_reg(gspca_dev, 0x0014, 0x012d);
cit_write_reg(gspca_dev, 0x0002, 0x012f);
cit_write_reg(gspca_dev, 0xd145, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012e);
cit_write_reg(gspca_dev, 0x001a, 0x0130);
cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
cit_write_reg(gspca_dev, 0x005e, 0x012d);
cit_write_reg(gspca_dev, 0x9545, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x0127);
cit_write_reg(gspca_dev, 0x0018, 0x012e);
cit_write_reg(gspca_dev, 0x0049, 0x0130);
cit_write_reg(gspca_dev, 0x8a28, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012f);
cit_write_reg(gspca_dev, 0xd055, 0x0124);
cit_write_reg(gspca_dev, 0x001c, 0x0127);
cit_write_reg(gspca_dev, 0x00cf, 0x012e);
cit_write_reg(gspca_dev, 0xaa28, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012d);
cit_write_reg(gspca_dev, 0x0032, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, 0x0000, 0x0127);
cit_write_reg(gspca_dev, 0x00aa, 0x0130);
cit_write_reg(gspca_dev, 0x82a8, 0x0124);
cit_write_reg(gspca_dev, 0x0036, 0x012d);
cit_write_reg(gspca_dev, 0x0008, 0x012f);
cit_write_reg(gspca_dev, 0xd145, 0x0124);
cit_write_reg(gspca_dev, 0xfffa, 0x0124);
cit_write_reg(gspca_dev, 0x00aa, 0x012d);
cit_write_reg(gspca_dev, 0x001e, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, 0x0010, 0x0127);
cit_write_reg(gspca_dev, 0x0013, 0x012e);
cit_write_reg(gspca_dev, 0x0025, 0x0130);
cit_write_reg(gspca_dev, 0x8a28, 0x0124);
cit_write_reg(gspca_dev, 0x0010, 0x012d);
cit_write_reg(gspca_dev, 0x0048, 0x012f);
cit_write_reg(gspca_dev, 0xd145, 0x0124);
cit_write_reg(gspca_dev, 0x0000, 0x0127);
cit_write_reg(gspca_dev, 0xfea8, 0x0124);
sd->sof_len = 2;
break;
}
cit_model4_Packet1(gspca_dev, 0x0038, 0x0004);
return 0;
}
static int cit_start_ibm_netcam_pro(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
const unsigned short compression = 0; /* 0=none, 7=best frame rate */
int i, clock_div = 0;
......@@ -1446,6 +2511,8 @@ static int cit_start_ibm_netcam_pro(struct gspca_dev *gspca_dev)
}
}
sd->sof_len = 4;
return 0;
}
......@@ -1458,9 +2525,18 @@ static int sd_start(struct gspca_dev *gspca_dev)
int packet_size;
switch (sd->model) {
case CIT_MODEL1:
cit_start_model1(gspca_dev);
break;
case CIT_MODEL2:
cit_start_model2(gspca_dev);
break;
case CIT_MODEL3:
cit_start_model3(gspca_dev);
break;
case CIT_MODEL4:
cit_start_model4(gspca_dev);
break;
case CIT_IBM_NETCAM_PRO:
cit_start_ibm_netcam_pro(gspca_dev);
break;
......@@ -1470,6 +2546,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
cit_set_contrast(gspca_dev);
cit_set_hue(gspca_dev);
cit_set_sharpness(gspca_dev);
cit_set_lighting(gspca_dev);
/* Program max isoc packet size, one day we should use this to
allow us to work together with other isoc devices on the same
......@@ -1492,14 +2569,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
static void sd_stopN(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
switch (sd->model) {
case CIT_MODEL3:
case CIT_IBM_NETCAM_PRO:
cit_write_reg(gspca_dev, 0x0000, 0x010c);
break;
}
}
static void sd_stop0(struct gspca_dev *gspca_dev)
......@@ -1512,6 +2582,24 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
return;
switch (sd->model) {
case CIT_MODEL1:
cit_send_FF_04_02(gspca_dev);
cit_read_reg(gspca_dev, 0x0100);
cit_write_reg(gspca_dev, 0x81, 0x0100); /* LED Off */
break;
case CIT_MODEL2:
case CIT_MODEL4:
cit_model2_Packet1(gspca_dev, 0x0030, 0x0004);
cit_write_reg(gspca_dev, 0x0080, 0x0100); /* LED Off */
cit_write_reg(gspca_dev, 0x0020, 0x0111);
cit_write_reg(gspca_dev, 0x00a0, 0x0111);
cit_model2_Packet1(gspca_dev, 0x0030, 0x0002);
cit_write_reg(gspca_dev, 0x0020, 0x0111);
cit_write_reg(gspca_dev, 0x0000, 0x0112);
break;
case CIT_MODEL3:
cit_write_reg(gspca_dev, 0x0006, 0x012c);
cit_model3_Packet1(gspca_dev, 0x0046, 0x0000);
......@@ -1547,11 +2635,20 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
static u8 *cit_find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
{
struct sd *sd = (struct sd *) gspca_dev;
u8 byte3;
int i;
switch (sd->model) {
case CIT_MODEL1:
case CIT_MODEL3:
case CIT_IBM_NETCAM_PRO:
if (sd->model == CIT_MODEL1)
byte3 = 0x00;
else if (gspca_dev->width == 640)
byte3 = 0x03;
else
byte3 = 0x02;
for (i = 0; i < len; i++) {
switch (sd->sof_read) {
case 0:
......@@ -1566,7 +2663,34 @@ static u8 *cit_find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
break;
case 2:
sd->sof_read = 0;
if (data[i] != 0xff) {
if (data[i] == byte3) {
if (i >= 4)
PDEBUG(D_FRAM,
"header found at offset: %d: %02x %02x 00 ff %02x %02x\n",
i - 2,
data[i - 4],
data[i - 3],
data[i],
data[i + 1]);
return data + i + (sd->sof_len - 2);
}
break;
}
}
break;
case CIT_MODEL2:
case CIT_MODEL4:
/* TESTME we need to find a longer sof signature to avoid
false positives */
for (i = 0; i < len; i++) {
switch (sd->sof_read) {
case 0:
if (data[i] == 0x00)
sd->sof_read++;
break;
case 1:
sd->sof_read = 0;
if (data[i] == 0xff) {
if (i >= 4)
PDEBUG(D_FRAM,
"header found at offset: %d: %02x %02x 00 ff %02x %02x\n",
......@@ -1575,7 +2699,7 @@ static u8 *cit_find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
data[i - 3],
data[i],
data[i + 1]);
return data + i + 2;
return data + i + (sd->sof_len - 2);
}
break;
}
......@@ -1588,6 +2712,7 @@ static u8 *cit_find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
u8 *data, int len)
{
struct sd *sd = (struct sd *) gspca_dev;
unsigned char *sof;
sof = cit_find_sof(gspca_dev, data, len);
......@@ -1596,8 +2721,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
/* finish decoding current frame */
n = sof - data;
if (n > 4)
n -= 4;
if (n > sd->sof_len)
n -= sd->sof_len;
else
n = 0;
gspca_frame_add(gspca_dev, LAST_PACKET,
......@@ -1616,8 +2741,10 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
sd->brightness = val;
if (gspca_dev->streaming) {
if (sd->stop_on_control_change)
sd_stopN(gspca_dev);
cit_set_brightness(gspca_dev);
if (sd->stop_on_control_change)
cit_restart_stream(gspca_dev);
}
......@@ -1639,8 +2766,10 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
sd->contrast = val;
if (gspca_dev->streaming) {
if (sd->stop_on_control_change)
sd_stopN(gspca_dev);
cit_set_contrast(gspca_dev);
if (sd->stop_on_control_change)
cit_restart_stream(gspca_dev);
}
......@@ -1662,8 +2791,10 @@ static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val)
sd->hue = val;
if (gspca_dev->streaming) {
if (sd->stop_on_control_change)
sd_stopN(gspca_dev);
cit_set_hue(gspca_dev);
if (sd->stop_on_control_change)
cit_restart_stream(gspca_dev);
}
return 0;
......@@ -1684,8 +2815,10 @@ static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
sd->sharpness = val;
if (gspca_dev->streaming) {
if (sd->stop_on_control_change)
sd_stopN(gspca_dev);
cit_set_sharpness(gspca_dev);
if (sd->stop_on_control_change)
cit_restart_stream(gspca_dev);
}
return 0;
......@@ -1700,6 +2833,30 @@ static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
static int sd_setlighting(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->lighting = val;
if (gspca_dev->streaming) {
if (sd->stop_on_control_change)
sd_stopN(gspca_dev);
cit_set_lighting(gspca_dev);
if (sd->stop_on_control_change)
cit_restart_stream(gspca_dev);
}
return 0;
}
static int sd_getlighting(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->lighting;
return 0;
}
/* sub-driver description */
static const struct sd_desc sd_desc = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment