From 89f9a2b48dabb22e84ddf4ca07284499aa5fc152 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 29 Jul 2009 13:02:50 +0200 Subject: gspca_pac207: remove a number of unneeded (repeated) register writes From: Hans de Goede gspca_pac207: remove a number of unneeded (repeated) register writes Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/pac207.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/pac207.c b/linux/drivers/media/video/gspca/pac207.c index 95a97ab68..f20d21b1c 100644 --- a/linux/drivers/media/video/gspca/pac207.c +++ b/linux/drivers/media/video/gspca/pac207.c @@ -169,13 +169,9 @@ static const __u8 pac207_sensor_init[][8] = { {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0xf0}, {0x00, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30}, {0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00}, - {0x00, 0x00, 0x32, 0x00, 0x96, 0x00, 0xa2, 0x02}, {0x32, 0x00, 0x96, 0x00, 0xA2, 0x02, 0xaf, 0x00}, }; - /* 48 reg_72 Rate Control end BalSize_4a =0x36 */ -static const __u8 PacReg72[] = { 0x00, 0x00, 0x36, 0x00 }; - static int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index, const u8 *buffer, u16 length) { @@ -274,7 +270,6 @@ static int sd_init(struct gspca_dev *gspca_dev) * Bit_1=LED, * Bit_2=Compression test mode enable */ pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */ - pac207_write_reg(gspca_dev, 0x11, 0x30); /* Analog Bias */ return 0; } @@ -289,9 +284,7 @@ static int sd_start(struct gspca_dev *gspca_dev) pac207_write_regs(gspca_dev, 0x0002, pac207_sensor_init[0], 8); pac207_write_regs(gspca_dev, 0x000a, pac207_sensor_init[1], 8); pac207_write_regs(gspca_dev, 0x0012, pac207_sensor_init[2], 8); - pac207_write_regs(gspca_dev, 0x0040, pac207_sensor_init[3], 8); - pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[4], 8); - pac207_write_regs(gspca_dev, 0x0048, PacReg72, 4); + pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[3], 8); /* Compression Balance */ if (gspca_dev->width == 176) -- cgit v1.2.3 From 2f1c03be87cb8cd9f645aaf4c5c7206f3141ddad Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 29 Jul 2009 13:03:17 +0200 Subject: gspca_pac207: enable higher framerates / lower exposure settings From: Hans de Goede Now that we've figured out the higher compression settings (supported in libv4l-0.6.0 and later, so after this patch the driver should be used with libv4l-0.6.0 or higher only!), we can enable higher framerates. Which means lower exposure times, which is important for the use of the pac207 in full daylight. This patch also tweakes the brightness default and the per color gain balances to use the values which are adviced by Pixart in the pac207 application note. Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/pac207.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/pac207.c b/linux/drivers/media/video/gspca/pac207.c index f20d21b1c..96659433d 100644 --- a/linux/drivers/media/video/gspca/pac207.c +++ b/linux/drivers/media/video/gspca/pac207.c @@ -35,25 +35,17 @@ MODULE_LICENSE("GPL"); #define PAC207_BRIGHTNESS_MIN 0 #define PAC207_BRIGHTNESS_MAX 255 -#define PAC207_BRIGHTNESS_DEFAULT 4 /* power on default: 4 */ - -/* An exposure value of 4 also works (3 does not) but then we need to lower - the compression balance setting when in 352x288 mode, otherwise the usb - bandwidth is not enough and packets get dropped resulting in corrupt - frames. The problem with this is that when the compression balance gets - lowered below 0x80, the pac207 starts using a different compression - algorithm for some lines, these lines get prefixed with a 0x2dd2 prefix - and currently we do not know how to decompress these lines, so for now - we use a minimum exposure value of 5 */ -#define PAC207_EXPOSURE_MIN 5 +#define PAC207_BRIGHTNESS_DEFAULT 46 + +#define PAC207_EXPOSURE_MIN 3 #define PAC207_EXPOSURE_MAX 26 -#define PAC207_EXPOSURE_DEFAULT 5 /* power on default: 3 ?? */ -#define PAC207_EXPOSURE_KNEE 11 /* 4 = 30 fps, 11 = 8, 15 = 6 */ +#define PAC207_EXPOSURE_DEFAULT 5 /* power on default: 3 */ +#define PAC207_EXPOSURE_KNEE 8 /* 4 = 30 fps, 11 = 8, 15 = 6 */ #define PAC207_GAIN_MIN 0 #define PAC207_GAIN_MAX 31 #define PAC207_GAIN_DEFAULT 9 /* power on default: 9 */ -#define PAC207_GAIN_KNEE 20 +#define PAC207_GAIN_KNEE 31 #define PAC207_AUTOGAIN_DEADZONE 30 @@ -166,8 +158,8 @@ static const struct v4l2_pix_format sif_mode[] = { }; static const __u8 pac207_sensor_init[][8] = { - {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0xf0}, - {0x00, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30}, + {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0x84}, + {0x49, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30}, {0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00}, {0x32, 0x00, 0x96, 0x00, 0xA2, 0x02, 0xaf, 0x00}, }; @@ -290,7 +282,7 @@ static int sd_start(struct gspca_dev *gspca_dev) if (gspca_dev->width == 176) pac207_write_reg(gspca_dev, 0x4a, 0xff); else - pac207_write_reg(gspca_dev, 0x4a, 0x88); + pac207_write_reg(gspca_dev, 0x4a, 0x30); pac207_write_reg(gspca_dev, 0x4b, 0x00); /* Sram test value */ pac207_write_reg(gspca_dev, 0x08, sd->brightness); @@ -339,7 +331,7 @@ static void pac207_do_auto_gain(struct gspca_dev *gspca_dev) if (sd->autogain_ignore_frames > 0) sd->autogain_ignore_frames--; else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, - 100 + sd->brightness / 2, PAC207_AUTOGAIN_DEADZONE, + 100, PAC207_AUTOGAIN_DEADZONE, PAC207_GAIN_KNEE, PAC207_EXPOSURE_KNEE)) sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; } -- cgit v1.2.3 From 5c78539069b4f258563e13e160393079e04a6d37 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Fri, 14 Aug 2009 11:51:52 +0200 Subject: gspca: mr97310a add support for CIF and more VGA camera's From: Theodore Kilgore This patch adds supports for mr97310a camera's with CIF sensors (2 different types) and for VGA mr97310a camera with a different sensor then supported until now. This patch also add support for controls for one of the 2 CIF sensors, this was written by Thomas Kaiser Priority: normal Signed-off-by: Theodore Kilgore Signed-off-by: Thomas Kaiser Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/mr97310a.c | 797 ++++++++++++++++++++++++----- 1 file changed, 682 insertions(+), 115 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index 301325134..3a3edf82a 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -3,6 +3,21 @@ * * Copyright (C) 2009 Kyle Guinn * + * Support for the MR97310A cameras in addition to the Aiptek Pencam VGA+ + * and for the routines for detecting and classifying these various cameras, + * + * Copyright (C) 2009 Theodore Kilgore + * + * Acknowledgements: + * + * The MR97311A support in gspca/mars.c has been helpful in understanding some + * of the registers in these cameras. + * + * Hans de Goede and + * Thomas Kaiser + * have assisted with their experience. Each of them has also helped by + * testing a previously unsupported camera. + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -22,7 +37,23 @@ #include "gspca.h" -MODULE_AUTHOR("Kyle Guinn "); +#define CAM_TYPE_CIF 0 +#define CAM_TYPE_VGA 1 + +#define MR97310A_BRIGHTNESS_MIN -254 +#define MR97310A_BRIGHTNESS_MAX 255 +#define MR97310A_BRIGHTNESS_DEFAULT 0 + +#define MR97310A_EXPOSURE_MIN 300 +#define MR97310A_EXPOSURE_MAX 4095 +#define MR97310A_EXPOSURE_DEFAULT 1000 + +#define MR97310A_GAIN_MIN 0 +#define MR97310A_GAIN_MAX 31 +#define MR97310A_GAIN_DEFAULT 25 + +MODULE_AUTHOR("Kyle Guinn ," + "Theodore Kilgore "); MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver"); MODULE_LICENSE("GPL"); @@ -30,10 +61,75 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ u8 sof_read; + u8 cam_type; /* 0 is CIF and 1 is VGA */ + u8 sensor_type; /* We use 0 and 1 here, too. */ + u8 do_lcd_stop; + u8 regs[15]; + + int brightness; + u16 exposure; + u8 autogain; + u8 gain; }; +struct sensor_w_data { + u8 reg; + u8 flags; + u8 data[16]; + int len; +}; + +static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); + /* V4L2 controls supported by the driver */ static struct ctrl sd_ctrls[] = { + { + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = MR97310A_BRIGHTNESS_MIN, + .maximum = MR97310A_BRIGHTNESS_MAX, + .step = 1, + .default_value = MR97310A_BRIGHTNESS_DEFAULT, + .flags = 0, + }, + .set = sd_setbrightness, + .get = sd_getbrightness, + }, + { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = MR97310A_EXPOSURE_MIN, + .maximum = MR97310A_EXPOSURE_MAX, + .step = 1, + .default_value = MR97310A_EXPOSURE_DEFAULT, + .flags = 0, + }, + .set = sd_setexposure, + .get = sd_getexposure, + }, + { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = MR97310A_GAIN_MIN, + .maximum = MR97310A_GAIN_MAX, + .step = 1, + .default_value = MR97310A_GAIN_DEFAULT, + .flags = 0, + }, + .set = sd_setgain, + .get = sd_getgain, + }, }; static const struct v4l2_pix_format vga_mode[] = { @@ -65,7 +161,7 @@ static const struct v4l2_pix_format vga_mode[] = { }; /* the bytes to write are in gspca_dev->usb_buf */ -static int reg_w(struct gspca_dev *gspca_dev, int len) +static int mr_write(struct gspca_dev *gspca_dev, int len) { int rc; @@ -78,15 +174,200 @@ static int reg_w(struct gspca_dev *gspca_dev, int len) return rc; } +/* the bytes are read into gspca_dev->usb_buf */ +static int mr_read(struct gspca_dev *gspca_dev, int len) +{ + int rc; + + rc = usb_bulk_msg(gspca_dev->dev, + usb_rcvbulkpipe(gspca_dev->dev, 3), + gspca_dev->usb_buf, len, NULL, 500); + if (rc < 0) + PDEBUG(D_ERR, "reg read [%02x] error %d", + gspca_dev->usb_buf[0], rc); + return rc; +} + +static int sensor_write_reg(struct gspca_dev *gspca_dev, u8 reg, u8 flags, + const u8 *data, int len) +{ + gspca_dev->usb_buf[0] = 0x1f; + gspca_dev->usb_buf[1] = flags; + gspca_dev->usb_buf[2] = reg; + memcpy(gspca_dev->usb_buf + 3, data, len); + + return mr_write(gspca_dev, len + 3); +} + +static int sensor_write_regs(struct gspca_dev *gspca_dev, + const struct sensor_w_data *data, int len) +{ + int i, rc; + + for (i = 0; i < len; i++) { + rc = sensor_write_reg(gspca_dev, data[i].reg, data[i].flags, + data[i].data, data[i].len); + if (rc < 0) + return rc; + } + + return 0; +} + +static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data) +{ + u8 buf; + int rc; + + buf = data; + rc = sensor_write_reg(gspca_dev, reg, 0x01, &buf, 1); + if (rc < 0) + return rc; + + buf = 0x01; + rc = sensor_write_reg(gspca_dev, 0x13, 0x00, &buf, 1); + if (rc < 0) + return rc; + + return 0; +} + +static int cam_get_response16(struct gspca_dev *gspca_dev) +{ + __u8 *data = gspca_dev->usb_buf; + int err_code; + + data[0] = 0x21; + err_code = mr_write(gspca_dev, 1); + if (err_code < 0) + return err_code; + + err_code = mr_read(gspca_dev, 16); + return err_code; +} + +static int zero_the_pointer(struct gspca_dev *gspca_dev) +{ + __u8 *data = gspca_dev->usb_buf; + int err_code; + u8 status = 0; + int tries = 0; + + err_code = cam_get_response16(gspca_dev); + if (err_code < 0) + return err_code; + + err_code = mr_write(gspca_dev, 1); + data[0] = 0x19; + data[1] = 0x51; + err_code = mr_write(gspca_dev, 2); + if (err_code < 0) + return err_code; + + err_code = cam_get_response16(gspca_dev); + if (err_code < 0) + return err_code; + + data[0] = 0x19; + data[1] = 0xba; + err_code = mr_write(gspca_dev, 2); + if (err_code < 0) + return err_code; + + err_code = cam_get_response16(gspca_dev); + if (err_code < 0) + return err_code; + + data[0] = 0x19; + data[1] = 0x00; + err_code = mr_write(gspca_dev, 2); + if (err_code < 0) + return err_code; + + err_code = cam_get_response16(gspca_dev); + if (err_code < 0) + return err_code; + + data[0] = 0x19; + data[1] = 0x00; + err_code = mr_write(gspca_dev, 2); + if (err_code < 0) + return err_code; + + while (status != 0x0a && tries < 256) { + err_code = cam_get_response16(gspca_dev); + status = data[0]; + tries++; + if (err_code < 0) + return err_code; + } + PDEBUG(D_ERR, "status is %02x", status); + + tries = 0; + while (tries < 4) { + data[0] = 0x19; + data[1] = 0x00; + err_code = mr_write(gspca_dev, 2); + if (err_code < 0) + return err_code; + + err_code = cam_get_response16(gspca_dev); + status = data[0]; + tries++; + if (err_code < 0) + return err_code; + } + PDEBUG(D_ERR, "Read 16 bytes from camera"); + + data[0] = 0x19; + err_code = mr_write(gspca_dev, 1); + if (err_code < 0) + return err_code; + + err_code = mr_read(gspca_dev, 16); + if (err_code < 0) + return err_code; + + return 0; +} + +static u8 get_sensor_id(struct gspca_dev *gspca_dev) +{ + int err_code; + + gspca_dev->usb_buf[0] = 0x1e; + err_code = mr_write(gspca_dev, 1); + if (err_code < 0) + return err_code; + + err_code = mr_read(gspca_dev, 16); + if (err_code < 0) + return err_code; + + PDEBUG(D_ERR, "Read 16 bytes from camera"); + PDEBUG(D_ERR, "Byte zero reported is %01x", gspca_dev->usb_buf[0]); + + return gspca_dev->usb_buf[0]; +} + /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) { + struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; cam = &gspca_dev->cam; cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); + sd->cam_type = CAM_TYPE_VGA; + PDEBUG(D_PROBE, + "MR97310A camera detected" + " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); + if (id->idProduct == 0x010e) { + cam->nmodes--; + sd->cam_type = CAM_TYPE_CIF; + } return 0; } @@ -96,183 +377,468 @@ static int sd_init(struct gspca_dev *gspca_dev) return 0; } -static int sd_start(struct gspca_dev *gspca_dev) +static int adjust_cif_sensor(struct gspca_dev *gspca_dev) +{ + /* + * FIXME: The following sequence resets brightness, contrast, and + * related settings. Some of the values are adjustable, presumably + * based upon what is detected in the frames. Here, only some + * vaules are used which are compromises. When more is known about + * what is done here, this needs to be moved out to presently + * nonexistent functions which do controls. The same control messages + * do work for all of the CIF cameras. + */ + + const struct sensor_w_data cif_sensor1_adjust_data[] = { + {0x02, 0x01, {0x10, 0x12, 0x0a}, 3}, + /* Last or possibly two last bytes adjustable, above. */ + {0x13, 0x04, {0x01}, 1}, /* seems to mean "write" */ + {0x05, 0x01, {0x22, 0x00, 0x81, 0x06}, 4}, + /* Last or possibly two last bytes adjustable, above. */ + {0x13, 0x04, {0x01}, 1}, + {0x09, 0x02, {0x05, 0x00, 0x00, 0x05, 0x07, 0x16}, 6}, + /* Last or possibly two last bytes adjustable, above. */ + {0x13, 0x04, {0x01}, 1}, + {0, 0, {0}, 0} + }; + + return sensor_write_regs(gspca_dev, cif_sensor1_adjust_data, + ARRAY_SIZE(cif_sensor1_adjust_data)); +} + +static int start_cif_cam(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; __u8 *data = gspca_dev->usb_buf; int err_code; - - sd->sof_read = 0; - - /* Note: register descriptions guessed from MR97113A driver */ - + const __u8 startup_string[] = { + 0x00, + 0x0d, + 0x01, + 0x00, /* Hsize/8 for 352 or 320 */ + 0x00, /* Vsize/4 for 288 or 240 */ + 0x13, /* or 0xbb, depends on sensor */ + 0x00, /* Hstart, depends on res. */ + 0x00, /* reserved ? */ + 0x00, /* Vstart, depends on res. and sensor */ + 0x50, /* 0x54 to get 176 or 160 */ + 0xc0 + }; + + /* Note: Some of the above descriptions guessed from MR97113A driver */ + sd->sensor_type = 0; data[0] = 0x01; data[1] = 0x01; - err_code = reg_w(gspca_dev, 2); + err_code = mr_write(gspca_dev, 2); if (err_code < 0) return err_code; - data[0] = 0x00; - data[1] = 0x0d; - data[2] = 0x01; - data[5] = 0x2b; - data[7] = 0x00; - data[9] = 0x50; /* reg 8, no scale down */ - data[10] = 0xc0; + msleep(200); + data[0] = get_sensor_id(gspca_dev); + /* + * Known CIF cameras. If you have another to report, please do + * + * Name byte just read sd->sensor_type + * reported by + * Sakar Spy-shot 0x28 T. Kilgore 0 + * Innovage 0xf5 (unstable) T. Kilgore 0 + * Vivitar Mini 0x53 H. De Goede 0 + * Vivitar Mini 0x08 T. Kilgore 1 + * Elta-Media 8212dc 0x23 T. Kaiser 1 + * Philips dig. keych. 0x37 T. Kilgore 1 + */ + if ((data[0] & 0x78) == 8 || (data[0] & 0x2) == 0x2) + sd->sensor_type = 1; + + PDEBUG(D_ERR, "Sensor type is %01x", sd->sensor_type); + memcpy(data, startup_string, 11); + if (sd->sensor_type) + data[5] = 0xbb; switch (gspca_dev->width) { case 160: - data[9] |= 0x0c; /* reg 8, 4:1 scale down */ + data[9] |= 0x04; /* reg 8, 2:1 scale down from 320 */ /* fall thru */ case 320: - data[9] |= 0x04; /* reg 8, 2:1 scale down */ - /* fall thru */ - case 640: default: - data[3] = 0x50; /* reg 2, H size */ - data[4] = 0x78; /* reg 3, V size */ - data[6] = 0x04; /* reg 5, H start */ - data[8] = 0x03; /* reg 7, V start */ + data[3] = 0x28; /* reg 2, H size/8 */ + data[4] = 0x3c; /* reg 3, V size/4 */ + data[6] = 0x14; /* reg 5, H start */ + data[8] = 0x1a + sd->sensor_type; /* reg 7, V start */ break; - case 176: - data[9] |= 0x04; /* reg 8, 2:1 scale down */ + data[9] |= 0x04; /* reg 8, 2:1 scale down from 352 */ /* fall thru */ case 352: - data[3] = 0x2c; /* reg 2, H size */ - data[4] = 0x48; /* reg 3, V size */ - data[6] = 0x94; /* reg 5, H start */ - data[8] = 0x63; /* reg 7, V start */ + data[3] = 0x2c; /* reg 2, H size/8 */ + data[4] = 0x48; /* reg 3, V size/4 */ + data[6] = 0x06; /* reg 5, H start */ + data[8] = 0x06 + sd->sensor_type; /* reg 7, V start */ break; } - - err_code = reg_w(gspca_dev, 11); + err_code = mr_write(gspca_dev, 11); if (err_code < 0) return err_code; - data[0] = 0x0a; - data[1] = 0x80; - err_code = reg_w(gspca_dev, 2); + if (!sd->sensor_type) { + const struct sensor_w_data cif_sensor0_init_data[] = { + {0x02, 0x00, {0x03, 0x5a, 0xb5, 0x01, + 0x0f, 0x14, 0x0f, 0x10}, 8}, + {0x0c, 0x00, {0x04, 0x01, 0x01, 0x00, 0x1f}, 5}, + {0x12, 0x00, {0x07}, 1}, + {0x1f, 0x00, {0x06}, 1}, + {0x27, 0x00, {0x04}, 1}, + {0x29, 0x00, {0x0c}, 1}, + {0x40, 0x00, {0x40, 0x00, 0x04}, 3}, + {0x50, 0x00, {0x60}, 1}, + {0x60, 0x00, {0x06}, 1}, + {0x6b, 0x00, {0x85, 0x85, 0xc8, 0xc8, 0xc8, 0xc8}, 6}, + {0x72, 0x00, {0x1e, 0x56}, 2}, + {0x75, 0x00, {0x58, 0x40, 0xa2, 0x02, 0x31, 0x02, + 0x31, 0x80, 0x00}, 9}, + {0x11, 0x00, {0x01}, 1}, + {0, 0, {0}, 0} + }; + err_code = sensor_write_regs(gspca_dev, cif_sensor0_init_data, + ARRAY_SIZE(cif_sensor0_init_data)); + } else { /* sd->sensor_type = 1 */ + const struct sensor_w_data cif_sensor1_init_data[] = { + {0x02, 0x00, {0x10}, 1}, + {0x03, 0x01, {0x12}, 1}, + {0x04, 0x01, {0x05}, 1}, + {0x05, 0x01, {0x65}, 1}, + {0x06, 0x01, {0x32}, 1}, + {0x07, 0x01, {0x00}, 1}, + {0x08, 0x02, {0x06}, 1}, + {0x09, 0x02, {0x0e}, 1}, + {0x0a, 0x02, {0x05}, 1}, + {0x0b, 0x02, {0x05}, 1}, + {0x0c, 0x02, {0x0f}, 1}, + {0x0d, 0x02, {0x00}, 1}, + {0x0e, 0x02, {0x0c}, 1}, + {0x0f, 0x00, {0x00}, 1}, + {0x10, 0x00, {0x06}, 1}, + {0x11, 0x00, {0x07}, 1}, + {0x12, 0x00, {0x00}, 1}, + {0x13, 0x00, {0x01}, 1}, + {0, 0, {0}, 0} + }; + err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data, + ARRAY_SIZE(cif_sensor1_init_data)); + } if (err_code < 0) return err_code; - data[0] = 0x14; - data[1] = 0x0a; - err_code = reg_w(gspca_dev, 2); + msleep(200); + data[0] = 0x00; + data[1] = 0x4d; /* ISOC transfering enable... */ + err_code = mr_write(gspca_dev, 2); if (err_code < 0) return err_code; - data[0] = 0x1b; - data[1] = 0x00; - err_code = reg_w(gspca_dev, 2); + msleep(200); + err_code = adjust_cif_sensor(gspca_dev); if (err_code < 0) return err_code; - data[0] = 0x15; - data[1] = 0x16; - err_code = reg_w(gspca_dev, 2); - if (err_code < 0) - return err_code; + msleep(200); + return 0; +} - data[0] = 0x16; - data[1] = 0x10; - err_code = reg_w(gspca_dev, 2); - if (err_code < 0) - return err_code; +static int start_vga_cam(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + __u8 *data = gspca_dev->usb_buf; + int err_code; + const __u8 startup_string[] = {0x00, 0x0d, 0x01, 0x00, 0x00, 0x2b, + 0x00, 0x00, 0x00, 0x50, 0xc0}; - data[0] = 0x17; - data[1] = 0x3a; - err_code = reg_w(gspca_dev, 2); - if (err_code < 0) - return err_code; + /* What some of these mean is explained in start_cif_cam(), above */ + sd->sof_read = 0; - data[0] = 0x18; - data[1] = 0x68; - err_code = reg_w(gspca_dev, 2); + /* + * We have to know which camera we have, because the register writes + * depend upon the camera. This test, run before we actually enter + * the initialization routine, distinguishes most of the cameras, If + * needed, another routine is done later, too. + */ + memset(data, 0, 16); + data[0] = 0x20; + err_code = mr_write(gspca_dev, 1); if (err_code < 0) return err_code; - data[0] = 0x1f; - data[1] = 0x00; - data[2] = 0x02; - data[3] = 0x06; - data[4] = 0x59; - data[5] = 0x0c; - data[6] = 0x16; - data[7] = 0x00; - data[8] = 0x07; - data[9] = 0x00; - data[10] = 0x01; - err_code = reg_w(gspca_dev, 11); + err_code = mr_read(gspca_dev, 16); if (err_code < 0) return err_code; - data[0] = 0x1f; - data[1] = 0x04; - data[2] = 0x11; - data[3] = 0x01; - err_code = reg_w(gspca_dev, 4); - if (err_code < 0) - return err_code; + PDEBUG(D_ERR, "Read 16 bytes from camera"); + PDEBUG(D_ERR, "Byte reported is %02x", data[0]); - data[0] = 0x1f; - data[1] = 0x00; - data[2] = 0x0a; - data[3] = 0x00; - data[4] = 0x01; - data[5] = 0x00; - data[6] = 0x00; - data[7] = 0x01; - data[8] = 0x00; - data[9] = 0x0a; - err_code = reg_w(gspca_dev, 10); - if (err_code < 0) - return err_code; + msleep(200); + /* + * Known VGA cameras. If you have another to report, please do + * + * Name byte just read sd->sensor_type + * sd->do_lcd_stop + * Aiptek Pencam VGA+ 0x31 0 1 + * ION digital 0x31 0 1 + * Argus DC-1620 0x30 1 0 + * Argus QuickClix 0x30 1 1 (not caught here) + */ + sd->sensor_type = data[0] & 1; + sd->do_lcd_stop = (~data[0]) & 1; - data[0] = 0x1f; - data[1] = 0x04; - data[2] = 0x11; - data[3] = 0x01; - err_code = reg_w(gspca_dev, 4); + + + /* Streaming setup begins here. */ + + + data[0] = 0x01; + data[1] = 0x01; + err_code = mr_write(gspca_dev, 2); if (err_code < 0) return err_code; - data[0] = 0x1f; - data[1] = 0x00; - data[2] = 0x12; - data[3] = 0x00; - data[4] = 0x63; - data[5] = 0x00; - data[6] = 0x70; - data[7] = 0x00; - data[8] = 0x00; - err_code = reg_w(gspca_dev, 9); + /* + * A second test can now resolve any remaining ambiguity in the + * identification of the camera type, + */ + if (!sd->sensor_type) { + data[0] = get_sensor_id(gspca_dev); + if (data[0] == 0x7f) { + sd->sensor_type = 1; + PDEBUG(D_ERR, "sensor_type corrected to 1"); + } + msleep(200); + } + + /* + * Known VGA cameras. + * This test is only run if the previous test returned 0x30, but + * here is the information for all others, too, just for reference. + * + * Name byte just read sd->sensor_type + * + * Aiptek Pencam VGA+ 0xfb (this test not run) 1 + * ION digital 0xbd (this test not run) 1 + * Argus DC-1620 0xe5 (no change) 0 + * Argus QuickClix 0x7f (reclassified) 1 + */ + memcpy(data, startup_string, 11); + if (!sd->sensor_type) { + data[5] = 0x00; + data[10] = 0x91; + } + + switch (gspca_dev->width) { + case 160: + data[9] |= 0x0c; /* reg 8, 4:1 scale down */ + /* fall thru */ + case 320: + data[9] |= 0x04; /* reg 8, 2:1 scale down */ + /* fall thru */ + case 640: + default: + data[3] = 0x50; /* reg 2, H size/8 */ + data[4] = 0x78; /* reg 3, V size/4 */ + data[6] = 0x04; /* reg 5, H start */ + data[8] = 0x03; /* reg 7, V start */ + if (sd->do_lcd_stop) + data[8] = 0x04; /* Bayer tile shifted */ + break; + + case 176: + data[9] |= 0x04; /* reg 8, 2:1 scale down */ + /* fall thru */ + case 352: + data[3] = 0x2c; /* reg 2, H size */ + data[4] = 0x48; /* reg 3, V size */ + data[6] = 0x94; /* reg 5, H start */ + data[8] = 0x63; /* reg 7, V start */ + if (sd->do_lcd_stop) + data[8] = 0x64; /* Bayer tile shifted */ + break; + } + + err_code = mr_write(gspca_dev, 11); if (err_code < 0) return err_code; - data[0] = 0x1f; - data[1] = 0x04; - data[2] = 0x11; - data[3] = 0x01; - err_code = reg_w(gspca_dev, 4); + if (!sd->sensor_type) { + /* The only known sensor_type 0 cam is the Argus DC-1620 */ + const struct sensor_w_data vga_sensor0_init_data[] = { + {0x01, 0x00, {0x0c, 0x00, 0x04}, 3}, + {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4}, + {0x20, 0x00, {0x00, 0x80, 0x00, 0x08}, 4}, + {0x25, 0x00, {0x03, 0xa9, 0x80}, 3}, + {0x30, 0x00, {0x30, 0x18, 0x10, 0x18}, 4}, + {0, 0, {0}, 0} + }; + err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data, + ARRAY_SIZE(vga_sensor0_init_data)); + } else { /* sd->sensor_type = 1 */ + const struct sensor_w_data vga_sensor1_init_data[] = { + {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, + 0x07, 0x00, 0x01}, 8}, + {0x11, 0x04, {0x01}, 1}, + /*{0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01, */ + {0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01, + 0x00, 0x0a}, 7}, + {0x11, 0x04, {0x01}, 1}, + {0x12, 0x00, {0x00, 0x63, 0x00, 0x70, 0x00, 0x00}, 6}, + {0x11, 0x04, {0x01}, 1}, + {0, 0, {0}, 0} + }; + err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data, + ARRAY_SIZE(vga_sensor1_init_data)); + } if (err_code < 0) return err_code; + msleep(200); data[0] = 0x00; data[1] = 0x4d; /* ISOC transfering enable... */ - err_code = reg_w(gspca_dev, 2); + err_code = mr_write(gspca_dev, 2); + + return err_code; +} + +static int sd_start(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int err_code; + struct cam *cam; + + /* TEST TEST */ + int i; + for (i = 2; i <= 14; i++) + sd->regs[i] = sd_ctrls[i - 2].qctrl.default_value; + + cam = &gspca_dev->cam; + sd->sof_read = 0; + /* + * Some of the supported cameras require the memory pointer to be + * set to 0, or else they will not stream. + */ + zero_the_pointer(gspca_dev); + msleep(200); + if (sd->cam_type == CAM_TYPE_CIF) { + PDEBUG(D_ERR, "CIF camera"); + err_code = start_cif_cam(gspca_dev); + } else { + PDEBUG(D_ERR, "VGA camera"); + err_code = start_vga_cam(gspca_dev); + } return err_code; } static void sd_stopN(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; int result; gspca_dev->usb_buf[0] = 1; gspca_dev->usb_buf[1] = 0; - result = reg_w(gspca_dev, 2); + result = mr_write(gspca_dev, 2); if (result < 0) PDEBUG(D_ERR, "Camera Stop failed"); + + /* Not all the cams need this, but even if not, probably a good idea */ + zero_the_pointer(gspca_dev); + if (sd->do_lcd_stop) { + gspca_dev->usb_buf[0] = 0x19; + gspca_dev->usb_buf[1] = 0x54; + result = mr_write(gspca_dev, 2); + if (result < 0) + PDEBUG(D_ERR, "Camera Stop failed"); + } +} + +static void setbrightness(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 val; + if (sd->brightness > 0) { + sensor_write1(gspca_dev, 7, 0); + val = sd->brightness; + } else { + sensor_write1(gspca_dev, 7, 1); + val = 257 - sd->brightness; + } + sensor_write1(gspca_dev, 8, val); +} + +static void setexposure(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 val; + + val = sd->exposure >> 4; + sensor_write1(gspca_dev, 3, val); + val = sd->exposure & 0xf; + sensor_write1(gspca_dev, 4, val); +} + +static void setgain(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sensor_write1(gspca_dev, 3, sd->gain); +} + +static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->brightness = val; + if (gspca_dev->streaming) + setbrightness(gspca_dev); + return 0; +} + +static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->brightness; + return 0; +} + +static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->exposure = val; + if (gspca_dev->streaming) + setexposure(gspca_dev); + return 0; +} + +static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->exposure; + return 0; +} + +static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->gain = val; + if (gspca_dev->streaming) + setgain(gspca_dev); + return 0; +} + +static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->gain; + return 0; } /* Include pac common sof detection functions */ @@ -320,8 +886,9 @@ static const struct sd_desc sd_desc = { /* -- module initialisation -- */ static const __devinitdata struct usb_device_id device_table[] = { - {USB_DEVICE(0x08ca, 0x0111)}, - {USB_DEVICE(0x093a, 0x010f)}, + {USB_DEVICE(0x08ca, 0x0111)}, /* Aiptek Pencam VGA+ */ + {USB_DEVICE(0x093a, 0x010f)}, /* All other known MR97310A VGA cams */ + {USB_DEVICE(0x093a, 0x010e)}, /* All known MR97310A CIF cams */ {} }; MODULE_DEVICE_TABLE(usb, device_table); -- cgit v1.2.3 From a701e8b02349206dd6c5b3a050bcf945091e1c38 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Fri, 14 Aug 2009 11:56:32 +0200 Subject: gspca: mr97310a fix detection of sensortype for vivicam with id byte of 0x53 From: Hans de Goede gspca: mr97310a fix detection of sensortype for vivicam with id byte of 0x53 Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/mr97310a.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index 3a3edf82a..db2f84e63 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -447,7 +447,8 @@ static int start_cif_cam(struct gspca_dev *gspca_dev) * Elta-Media 8212dc 0x23 T. Kaiser 1 * Philips dig. keych. 0x37 T. Kilgore 1 */ - if ((data[0] & 0x78) == 8 || (data[0] & 0x2) == 0x2) + if ((data[0] & 0x78) == 8 || + ((data[0] & 0x2) == 0x2 && data[0] != 0x53)) sd->sensor_type = 1; PDEBUG(D_ERR, "Sensor type is %01x", sd->sensor_type); -- cgit v1.2.3 From 7ba548f6dd9dbb151271b980bf96189a73979a12 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Fri, 14 Aug 2009 15:15:52 +0200 Subject: gspca_mr97310a: cleanup/fixup control handling From: Hans de Goede gspca_mr97310a: cleanup/fixup control handling Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/mr97310a.c | 98 ++++++++++++++---------------- 1 file changed, 45 insertions(+), 53 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index db2f84e63..3bdf06469 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -64,11 +64,9 @@ struct sd { u8 cam_type; /* 0 is CIF and 1 is VGA */ u8 sensor_type; /* We use 0 and 1 here, too. */ u8 do_lcd_stop; - u8 regs[15]; int brightness; u16 exposure; - u8 autogain; u8 gain; }; @@ -85,10 +83,14 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); +static void setbrightness(struct gspca_dev *gspca_dev); +static void setexposure(struct gspca_dev *gspca_dev); +static void setgain(struct gspca_dev *gspca_dev); /* V4L2 controls supported by the driver */ static struct ctrl sd_ctrls[] = { { +#define BRIGHTNESS_IDX 0 { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, @@ -103,6 +105,7 @@ static struct ctrl sd_ctrls[] = { .get = sd_getbrightness, }, { +#define EXPOSURE_IDX 1 { .id = V4L2_CID_EXPOSURE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -117,6 +120,7 @@ static struct ctrl sd_ctrls[] = { .get = sd_getexposure, }, { +#define GAIN_IDX 2 { .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, @@ -360,14 +364,24 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); - sd->cam_type = CAM_TYPE_VGA; + PDEBUG(D_PROBE, "MR97310A camera detected" " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); + if (id->idProduct == 0x010e) { - cam->nmodes--; sd->cam_type = CAM_TYPE_CIF; + cam->nmodes--; + } else { + sd->cam_type = CAM_TYPE_VGA; + gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) | + (1 << EXPOSURE_IDX) | (1 << GAIN_IDX); } + + sd->brightness = MR97310A_BRIGHTNESS_DEFAULT; + sd->exposure = MR97310A_EXPOSURE_DEFAULT; + sd->gain = MR97310A_GAIN_DEFAULT; + return 0; } @@ -377,35 +391,6 @@ static int sd_init(struct gspca_dev *gspca_dev) return 0; } -static int adjust_cif_sensor(struct gspca_dev *gspca_dev) -{ - /* - * FIXME: The following sequence resets brightness, contrast, and - * related settings. Some of the values are adjustable, presumably - * based upon what is detected in the frames. Here, only some - * vaules are used which are compromises. When more is known about - * what is done here, this needs to be moved out to presently - * nonexistent functions which do controls. The same control messages - * do work for all of the CIF cameras. - */ - - const struct sensor_w_data cif_sensor1_adjust_data[] = { - {0x02, 0x01, {0x10, 0x12, 0x0a}, 3}, - /* Last or possibly two last bytes adjustable, above. */ - {0x13, 0x04, {0x01}, 1}, /* seems to mean "write" */ - {0x05, 0x01, {0x22, 0x00, 0x81, 0x06}, 4}, - /* Last or possibly two last bytes adjustable, above. */ - {0x13, 0x04, {0x01}, 1}, - {0x09, 0x02, {0x05, 0x00, 0x00, 0x05, 0x07, 0x16}, 6}, - /* Last or possibly two last bytes adjustable, above. */ - {0x13, 0x04, {0x01}, 1}, - {0, 0, {0}, 0} - }; - - return sensor_write_regs(gspca_dev, cif_sensor1_adjust_data, - ARRAY_SIZE(cif_sensor1_adjust_data)); -} - static int start_cif_cam(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -452,6 +437,11 @@ static int start_cif_cam(struct gspca_dev *gspca_dev) sd->sensor_type = 1; PDEBUG(D_ERR, "Sensor type is %01x", sd->sensor_type); + + if (sd->sensor_type == 0) + gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) | + (1 << EXPOSURE_IDX) | (1 << GAIN_IDX); + memcpy(data, startup_string, 11); if (sd->sensor_type) data[5] = 0xbb; @@ -504,18 +494,15 @@ static int start_cif_cam(struct gspca_dev *gspca_dev) ARRAY_SIZE(cif_sensor0_init_data)); } else { /* sd->sensor_type = 1 */ const struct sensor_w_data cif_sensor1_init_data[] = { + /* Reg 3,4, 7,8 get set by the controls */ {0x02, 0x00, {0x10}, 1}, - {0x03, 0x01, {0x12}, 1}, - {0x04, 0x01, {0x05}, 1}, - {0x05, 0x01, {0x65}, 1}, - {0x06, 0x01, {0x32}, 1}, - {0x07, 0x01, {0x00}, 1}, - {0x08, 0x02, {0x06}, 1}, + {0x05, 0x01, {0x22}, 1}, /* 5/6 also seen as 65h/32h */ + {0x06, 0x01, {0x00}, 1}, {0x09, 0x02, {0x0e}, 1}, {0x0a, 0x02, {0x05}, 1}, {0x0b, 0x02, {0x05}, 1}, {0x0c, 0x02, {0x0f}, 1}, - {0x0d, 0x02, {0x00}, 1}, + {0x0d, 0x02, {0x07}, 1}, {0x0e, 0x02, {0x0c}, 1}, {0x0f, 0x00, {0x00}, 1}, {0x10, 0x00, {0x06}, 1}, @@ -530,19 +517,18 @@ static int start_cif_cam(struct gspca_dev *gspca_dev) if (err_code < 0) return err_code; + setbrightness(gspca_dev); + setexposure(gspca_dev); + setgain(gspca_dev); + msleep(200); + data[0] = 0x00; data[1] = 0x4d; /* ISOC transfering enable... */ err_code = mr_write(gspca_dev, 2); if (err_code < 0) return err_code; - msleep(200); - err_code = adjust_cif_sensor(gspca_dev); - if (err_code < 0) - return err_code; - - msleep(200); return 0; } @@ -711,11 +697,6 @@ static int sd_start(struct gspca_dev *gspca_dev) int err_code; struct cam *cam; - /* TEST TEST */ - int i; - for (i = 2; i <= 14; i++) - sd->regs[i] = sd_ctrls[i - 2].qctrl.default_value; - cam = &gspca_dev->cam; sd->sof_read = 0; /* @@ -760,11 +741,16 @@ static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; u8 val; + + if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS_IDX)) + return; + + /* Note register 7 is also seen as 0x8x or 0xCx in dumps */ if (sd->brightness > 0) { - sensor_write1(gspca_dev, 7, 0); + sensor_write1(gspca_dev, 7, 0x00); val = sd->brightness; } else { - sensor_write1(gspca_dev, 7, 1); + sensor_write1(gspca_dev, 7, 0x01); val = 257 - sd->brightness; } sensor_write1(gspca_dev, 8, val); @@ -775,6 +761,9 @@ static void setexposure(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; u8 val; + if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) + return; + val = sd->exposure >> 4; sensor_write1(gspca_dev, 3, val); val = sd->exposure & 0xf; @@ -785,6 +774,9 @@ static void setgain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + if (gspca_dev->ctrl_dis & (1 << GAIN_IDX)) + return; + sensor_write1(gspca_dev, 3, sd->gain); } -- cgit v1.2.3 From a7cb5b967c6700a7b3cd5d489d92871e2fd5ba16 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Fri, 14 Aug 2009 15:40:26 +0200 Subject: gspca_mr97310a: Move detection of CIF sensor type to probe() function From: Hans de Goede gspca_mr97310a: Move detection of CIF sensor type to probe() function, so that the right controls are set to disabled from the start, rather then having them disappear all of a sudden when the stream is started. Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/mr97310a.c | 59 +++++++++++++++++------------- 1 file changed, 34 insertions(+), 25 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index 3bdf06469..1a6532fa8 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -360,6 +360,8 @@ static int sd_config(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; + __u8 *data = gspca_dev->usb_buf; + int err_code; cam = &gspca_dev->cam; cam->cam_mode = vga_mode; @@ -372,6 +374,38 @@ static int sd_config(struct gspca_dev *gspca_dev, if (id->idProduct == 0x010e) { sd->cam_type = CAM_TYPE_CIF; cam->nmodes--; + + data[0] = 0x01; + data[1] = 0x01; + err_code = mr_write(gspca_dev, 2); + if (err_code < 0) + return err_code; + + msleep(200); + data[0] = get_sensor_id(gspca_dev); + /* + * Known CIF cameras. If you have another to report, please do + * + * Name byte just read sd->sensor_type + * reported by + * Sakar Spy-shot 0x28 T. Kilgore 0 + * Innovage 0xf5 (unstable) T. Kilgore 0 + * Vivitar Mini 0x53 H. De Goede 0 + * Vivitar Mini 0x08 T. Kilgore 1 + * Elta-Media 8212dc 0x23 T. Kaiser 1 + * Philips dig. keych. 0x37 T. Kilgore 1 + */ + if ((data[0] & 0x78) == 8 || + ((data[0] & 0x2) == 0x2 && data[0] != 0x53)) + sd->sensor_type = 1; + else + sd->sensor_type = 0; + + PDEBUG(D_ERR, "Sensor type is %01x", sd->sensor_type); + + if (sd->sensor_type == 0) + gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) | + (1 << EXPOSURE_IDX) | (1 << GAIN_IDX); } else { sd->cam_type = CAM_TYPE_VGA; gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) | @@ -411,37 +445,12 @@ static int start_cif_cam(struct gspca_dev *gspca_dev) }; /* Note: Some of the above descriptions guessed from MR97113A driver */ - sd->sensor_type = 0; data[0] = 0x01; data[1] = 0x01; err_code = mr_write(gspca_dev, 2); if (err_code < 0) return err_code; - msleep(200); - data[0] = get_sensor_id(gspca_dev); - /* - * Known CIF cameras. If you have another to report, please do - * - * Name byte just read sd->sensor_type - * reported by - * Sakar Spy-shot 0x28 T. Kilgore 0 - * Innovage 0xf5 (unstable) T. Kilgore 0 - * Vivitar Mini 0x53 H. De Goede 0 - * Vivitar Mini 0x08 T. Kilgore 1 - * Elta-Media 8212dc 0x23 T. Kaiser 1 - * Philips dig. keych. 0x37 T. Kilgore 1 - */ - if ((data[0] & 0x78) == 8 || - ((data[0] & 0x2) == 0x2 && data[0] != 0x53)) - sd->sensor_type = 1; - - PDEBUG(D_ERR, "Sensor type is %01x", sd->sensor_type); - - if (sd->sensor_type == 0) - gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) | - (1 << EXPOSURE_IDX) | (1 << GAIN_IDX); - memcpy(data, startup_string, 11); if (sd->sensor_type) data[5] = 0xbb; -- cgit v1.2.3 From 30f3a12506fbaced440cb99a0a893825dbec6f1f Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Fri, 14 Aug 2009 16:05:38 +0200 Subject: gspca_mr97310a: make the probing a bit less chatty From: Hans de Goede gspca_mr97310a: make the probing a bit less chatty Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/mr97310a.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index 1a6532fa8..7540ea94e 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -305,7 +305,8 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev) if (err_code < 0) return err_code; } - PDEBUG(D_ERR, "status is %02x", status); + if (status != 0x0a) + PDEBUG(D_ERR, "status is %02x", status); tries = 0; while (tries < 4) { @@ -321,7 +322,6 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev) if (err_code < 0) return err_code; } - PDEBUG(D_ERR, "Read 16 bytes from camera"); data[0] = 0x19; err_code = mr_write(gspca_dev, 1); @@ -348,8 +348,7 @@ static u8 get_sensor_id(struct gspca_dev *gspca_dev) if (err_code < 0) return err_code; - PDEBUG(D_ERR, "Read 16 bytes from camera"); - PDEBUG(D_ERR, "Byte zero reported is %01x", gspca_dev->usb_buf[0]); + PDEBUG(D_PROBE, "Byte zero reported is %01x", gspca_dev->usb_buf[0]); return gspca_dev->usb_buf[0]; } @@ -367,10 +366,6 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); - PDEBUG(D_PROBE, - "MR97310A camera detected" - " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); - if (id->idProduct == 0x010e) { sd->cam_type = CAM_TYPE_CIF; cam->nmodes--; @@ -401,13 +396,15 @@ static int sd_config(struct gspca_dev *gspca_dev, else sd->sensor_type = 0; - PDEBUG(D_ERR, "Sensor type is %01x", sd->sensor_type); + PDEBUG(D_PROBE, "MR97310A CIF camera detected, sensor: %d", + sd->sensor_type); if (sd->sensor_type == 0) gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) | (1 << EXPOSURE_IDX) | (1 << GAIN_IDX); } else { sd->cam_type = CAM_TYPE_VGA; + PDEBUG(D_PROBE, "MR97310A VGA camera detected"); gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) | (1 << EXPOSURE_IDX) | (1 << GAIN_IDX); } @@ -568,8 +565,7 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) if (err_code < 0) return err_code; - PDEBUG(D_ERR, "Read 16 bytes from camera"); - PDEBUG(D_ERR, "Byte reported is %02x", data[0]); + PDEBUG(D_PROBE, "Byte reported is %02x", data[0]); msleep(200); /* @@ -604,7 +600,7 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) data[0] = get_sensor_id(gspca_dev); if (data[0] == 0x7f) { sd->sensor_type = 1; - PDEBUG(D_ERR, "sensor_type corrected to 1"); + PDEBUG(D_PROBE, "sensor_type corrected to 1"); } msleep(200); } @@ -715,10 +711,8 @@ static int sd_start(struct gspca_dev *gspca_dev) zero_the_pointer(gspca_dev); msleep(200); if (sd->cam_type == CAM_TYPE_CIF) { - PDEBUG(D_ERR, "CIF camera"); err_code = start_cif_cam(gspca_dev); } else { - PDEBUG(D_ERR, "VGA camera"); err_code = start_vga_cam(gspca_dev); } return err_code; -- cgit v1.2.3 From 1043cd3f4a29434ea131163d1a1d4a21da04150b Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Fri, 14 Aug 2009 22:11:36 +0200 Subject: gspca_mr97310a: Add controls for CIF type 0 sensor cams From: Hans de Goede gspca_mr97310a: Add controls for CIF type 0 sensor cams Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/mr97310a.c | 56 +++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 9 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index 7540ea94e..1ee3d1ee5 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -220,7 +220,8 @@ static int sensor_write_regs(struct gspca_dev *gspca_dev, static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data) { - u8 buf; + struct sd *sd = (struct sd *) gspca_dev; + u8 buf, confirm_reg; int rc; buf = data; @@ -229,7 +230,8 @@ static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data) return rc; buf = 0x01; - rc = sensor_write_reg(gspca_dev, 0x13, 0x00, &buf, 1); + confirm_reg = sd->sensor_type ? 0x13 : 0x11; + rc = sensor_write_reg(gspca_dev, confirm_reg, 0x00, &buf, 1); if (rc < 0) return rc; @@ -400,8 +402,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->sensor_type); if (sd->sensor_type == 0) - gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) | - (1 << EXPOSURE_IDX) | (1 << GAIN_IDX); + gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX); } else { sd->cam_type = CAM_TYPE_VGA; PDEBUG(D_PROBE, "MR97310A VGA camera detected"); @@ -767,10 +768,43 @@ static void setexposure(struct gspca_dev *gspca_dev) if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) return; - val = sd->exposure >> 4; - sensor_write1(gspca_dev, 3, val); - val = sd->exposure & 0xf; - sensor_write1(gspca_dev, 4, val); + if (sd->sensor_type) { + val = sd->exposure >> 4; + sensor_write1(gspca_dev, 3, val); + val = sd->exposure & 0xf; + sensor_write1(gspca_dev, 4, val); + } else { + u8 clockdiv; + int exposure; + + /* We have both a clock divider and an exposure register. + We first calculate the clock divider, as that determines + the maximum exposure and then we calculayte the exposure + register setting (which goes from 0 - 511). + + Note our 0 - 4095 exposure is mapped to 0 - 511 + milliseconds exposure time */ + clockdiv = (60 * sd->exposure + 7999) / 8000; + + /* Limit framerate to not exceed usb bandwidth */ + if (clockdiv < 3 && gspca_dev->width >= 320) + clockdiv = 3; + else if (clockdiv < 2) + clockdiv = 2; + + /* Frame exposure time in ms = 1000 * clockdiv / 60 -> + exposure = (sd->exposure / 8) * 511 / (1000 * clockdiv / 60) */ + exposure = (60 * 511 * sd->exposure) / (8000 * clockdiv); + if (exposure > 511) + exposure = 511; + + /* exposure register value is reversed! */ + exposure = 511 - exposure; + + sensor_write1(gspca_dev, 0x02, clockdiv); + sensor_write1(gspca_dev, 0x0e, exposure & 0xff); + sensor_write1(gspca_dev, 0x0f, exposure >> 8); + } } static void setgain(struct gspca_dev *gspca_dev) @@ -780,7 +814,11 @@ static void setgain(struct gspca_dev *gspca_dev) if (gspca_dev->ctrl_dis & (1 << GAIN_IDX)) return; - sensor_write1(gspca_dev, 3, sd->gain); + if (sd->sensor_type) { + sensor_write1(gspca_dev, 3, sd->gain); + } else { + sensor_write1(gspca_dev, 0x10, sd->gain); + } } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) -- cgit v1.2.3 From f56e5f83c8445db50b3cba3013170785c52ac486 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Mon, 17 Aug 2009 17:25:17 +0200 Subject: gspca_mr97310a: Use correct register for CIF type 1 sensor gain settings From: Hans de Goede gspca_mr97310a: Use correct register for CIF type 1 sensor gain settings Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/mr97310a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index 1ee3d1ee5..8190a1d4d 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -815,7 +815,7 @@ static void setgain(struct gspca_dev *gspca_dev) return; if (sd->sensor_type) { - sensor_write1(gspca_dev, 3, sd->gain); + sensor_write1(gspca_dev, 0x0e, sd->gain); } else { sensor_write1(gspca_dev, 0x10, sd->gain); } -- cgit v1.2.3 From 9e33225665c1037f2fce51f4f1b65d40b639dbeb Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 25 Aug 2009 09:14:04 +0200 Subject: gspca - pac7311: Webcam 06f8:3009 added. From: Stephane Marguet (Stemp) Priority: normal Signed-off-by: Stephane Marguet (Stemp) Signed-off-by: Jean-Francois Moine --- linux/Documentation/video4linux/gspca.txt | 1 + linux/drivers/media/video/gspca/pac7311.c | 1 + 2 files changed, 2 insertions(+) (limited to 'linux') diff --git a/linux/Documentation/video4linux/gspca.txt b/linux/Documentation/video4linux/gspca.txt index 76203a221..4686e84dd 100644 --- a/linux/Documentation/video4linux/gspca.txt +++ b/linux/Documentation/video4linux/gspca.txt @@ -183,6 +183,7 @@ ov534 06f8:3002 Hercules Blog Webcam ov534 06f8:3003 Hercules Dualpix HD Weblog sonixj 06f8:3004 Hercules Classic Silver sonixj 06f8:3008 Hercules Deluxe Optical Glass +pac7311 06f8:3009 Hercules Classic Link spca508 0733:0110 ViewQuest VQ110 spca508 0130:0130 Clone Digital Webcam 11043 spca501 0733:0401 Intel Create and Share diff --git a/linux/drivers/media/video/gspca/pac7311.c b/linux/drivers/media/video/gspca/pac7311.c index ed10134c9..356111956 100644 --- a/linux/drivers/media/video/gspca/pac7311.c +++ b/linux/drivers/media/video/gspca/pac7311.c @@ -1071,6 +1071,7 @@ static struct sd_desc sd_desc = { /* -- module initialisation -- */ static __devinitdata struct usb_device_id device_table[] = { + {USB_DEVICE(0x06f8, 0x3009), .driver_info = SENSOR_PAC7302}, {USB_DEVICE(0x093a, 0x2600), .driver_info = SENSOR_PAC7311}, {USB_DEVICE(0x093a, 0x2601), .driver_info = SENSOR_PAC7311}, {USB_DEVICE(0x093a, 0x2603), .driver_info = SENSOR_PAC7311}, -- cgit v1.2.3 From 33b4b30509d2a665196e5316229ec345df8757b6 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 29 Aug 2009 12:11:58 +0200 Subject: gspca - sonixj: Don't use mdelay(). From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 6a668deb1..55970fee6 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -1177,7 +1177,7 @@ static int configure_gpio(struct gspca_dev *gspca_dev, reg_w1(gspca_dev, 0x17, 0x20); reg_w1(gspca_dev, 0x01, 0x62); reg_w1(gspca_dev, 0x01, 0x42); - mdelay(100); + msleep(100); reg_w1(gspca_dev, 0x02, 0x62); break; /* case SENSOR_HV7131R: */ -- cgit v1.2.3 From 2eee59b3a4bdc1e3b1341ea567a653105e9abe6d Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 31 Aug 2009 11:15:22 +0200 Subject: gspca - sunplus: Optimize code. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sunplus.c | 372 +++++++++++++----------------- 1 file changed, 165 insertions(+), 207 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/sunplus.c b/linux/drivers/media/video/gspca/sunplus.c index 33bac051d..94a3f53c6 100644 --- a/linux/drivers/media/video/gspca/sunplus.c +++ b/linux/drivers/media/video/gspca/sunplus.c @@ -32,22 +32,22 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - unsigned char brightness; - unsigned char contrast; - unsigned char colors; - unsigned char autogain; + u8 brightness; + u8 contrast; + u8 colors; + u8 autogain; u8 quality; #define QUALITY_MIN 70 #define QUALITY_MAX 95 #define QUALITY_DEF 85 - char bridge; + u8 bridge; #define BRIDGE_SPCA504 0 #define BRIDGE_SPCA504B 1 #define BRIDGE_SPCA504C 2 #define BRIDGE_SPCA533 3 #define BRIDGE_SPCA536 4 - char subtype; + u8 subtype; #define AiptekMiniPenCam13 1 #define LogitechClickSmart420 2 #define LogitechClickSmart820 3 @@ -68,7 +68,6 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); static struct ctrl sd_ctrls[] = { -#define SD_BRIGHTNESS 0 { { .id = V4L2_CID_BRIGHTNESS, @@ -77,12 +76,12 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 0xff, .step = 1, - .default_value = 0, +#define BRIGHTNESS_DEF 0 + .default_value = BRIGHTNESS_DEF, }, .set = sd_setbrightness, .get = sd_getbrightness, }, -#define SD_CONTRAST 1 { { .id = V4L2_CID_CONTRAST, @@ -91,12 +90,12 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 0xff, .step = 1, - .default_value = 0x20, +#define CONTRAST_DEF 0x20 + .default_value = CONTRAST_DEF, }, .set = sd_setcontrast, .get = sd_getcontrast, }, -#define SD_COLOR 2 { { .id = V4L2_CID_SATURATION, @@ -105,12 +104,12 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 0xff, .step = 1, - .default_value = 0x1a, +#define COLOR_DEF 0x1a + .default_value = COLOR_DEF, }, .set = sd_setcolors, .get = sd_getcolors, }, -#define SD_AUTOGAIN 3 { { .id = V4L2_CID_AUTOGAIN, @@ -119,7 +118,8 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, - .default_value = 1, +#define AUTOGAIN_DEF 1 + .default_value = AUTOGAIN_DEF, }, .set = sd_setautogain, .get = sd_getautogain, @@ -181,14 +181,20 @@ static const struct v4l2_pix_format vga_mode2[] = { #define SPCA504_PCCAM600_OFFSET_MODE 5 #define SPCA504_PCCAM600_OFFSET_DATA 14 /* Frame packet header offsets for the spca533 */ -#define SPCA533_OFFSET_DATA 16 +#define SPCA533_OFFSET_DATA 16 #define SPCA533_OFFSET_FRAMSEQ 15 /* Frame packet header offsets for the spca536 */ -#define SPCA536_OFFSET_DATA 4 -#define SPCA536_OFFSET_FRAMSEQ 1 +#define SPCA536_OFFSET_DATA 4 +#define SPCA536_OFFSET_FRAMSEQ 1 + +struct cmd { + u8 req; + u16 val; + u16 idx; +}; /* Initialisation data for the Creative PC-CAM 600 */ -static const __u16 spca504_pccam600_init_data[][3] = { +static const struct cmd spca504_pccam600_init_data[] = { /* {0xa0, 0x0000, 0x0503}, * capture mode */ {0x00, 0x0000, 0x2000}, {0x00, 0x0013, 0x2301}, @@ -219,22 +225,20 @@ static const __u16 spca504_pccam600_init_data[][3] = { {0x00, 0x0003, 0x2000}, {0x00, 0x0013, 0x2301}, {0x00, 0x0003, 0x2000}, - {} }; /* Creative PC-CAM 600 specific open data, sent before using the * generic initialisation data from spca504_open_data. */ -static const __u16 spca504_pccam600_open_data[][3] = { +static const struct cmd spca504_pccam600_open_data[] = { {0x00, 0x0001, 0x2501}, {0x20, 0x0500, 0x0001}, /* snapshot mode */ {0x00, 0x0003, 0x2880}, {0x00, 0x0001, 0x2881}, - {} }; /* Initialisation data for the logitech clicksmart 420 */ -static const __u16 spca504A_clicksmart420_init_data[][3] = { +static const struct cmd spca504A_clicksmart420_init_data[] = { /* {0xa0, 0x0000, 0x0503}, * capture mode */ {0x00, 0x0000, 0x2000}, {0x00, 0x0013, 0x2301}, @@ -261,7 +265,7 @@ static const __u16 spca504A_clicksmart420_init_data[][3] = { #endif #if 1 - {0x0a1, 0x0080, 0x0001}, + {0xa1, 0x0080, 0x0001}, {0x30, 0x0049, 0x0000}, {0x30, 0x0060, 0x0005}, {0x0c, 0x0004, 0x0000}, @@ -285,11 +289,10 @@ static const __u16 spca504A_clicksmart420_init_data[][3] = { {0x00, 0x0013, 0x2301}, {0x00, 0x0003, 0x2000}, #endif - {} }; /* clicksmart 420 open data ? */ -static const __u16 spca504A_clicksmart420_open_data[][3] = { +static const struct cmd spca504A_clicksmart420_open_data[] = { {0x00, 0x0001, 0x2501}, {0x20, 0x0502, 0x0000}, {0x06, 0x0000, 0x0000}, @@ -433,10 +436,9 @@ static const __u16 spca504A_clicksmart420_open_data[][3] = { {0x00, 0x0028, 0x287f}, {0xa0, 0x0000, 0x0503}, - {} }; -static const __u8 qtable_creative_pccam[2][64] = { +static const u8 qtable_creative_pccam[2][64] = { { /* Q-table Y-components */ 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12, 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11, @@ -461,7 +463,7 @@ static const __u8 qtable_creative_pccam[2][64] = { * except for one byte. Possibly a typo? * NWG: 18/05/2003. */ -static const __u8 qtable_spca504_default[2][64] = { +static const u8 qtable_spca504_default[2][64] = { { /* Q-table Y-components */ 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12, 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11, @@ -485,9 +487,9 @@ static const __u8 qtable_spca504_default[2][64] = { /* read bytes to gspca_dev->usb_buf */ static void reg_r(struct gspca_dev *gspca_dev, - __u16 req, - __u16 index, - __u16 len) + u8 req, + u16 index, + u16 len) { #ifdef GSPCA_DEBUG if (len > USB_BUF_SZ) { @@ -505,31 +507,26 @@ static void reg_r(struct gspca_dev *gspca_dev, 500); } -/* write bytes from gspca_dev->usb_buf */ -static void reg_w(struct gspca_dev *gspca_dev, - __u16 req, - __u16 value, - __u16 index, - __u16 len) +/* write one byte */ +static void reg_w_1(struct gspca_dev *gspca_dev, + u8 req, + u16 value, + u16 index, + u16 byte) { -#ifdef GSPCA_DEBUG - if (len > USB_BUF_SZ) { - err("reg_w: buffer overflow"); - return; - } -#endif + gspca_dev->usb_buf[0] = byte; usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, index, - len ? gspca_dev->usb_buf : NULL, len, + gspca_dev->usb_buf, 1, 500); } /* write req / index / value */ static int reg_w_riv(struct usb_device *dev, - __u16 req, __u16 index, __u16 value) + u8 req, u16 index, u16 value) { int ret; @@ -547,7 +544,7 @@ static int reg_w_riv(struct usb_device *dev, /* read 1 byte */ static int reg_r_1(struct gspca_dev *gspca_dev, - __u16 value) /* wValue */ + u16 value) /* wValue */ { int ret; @@ -568,9 +565,9 @@ static int reg_r_1(struct gspca_dev *gspca_dev, /* read 1 or 2 bytes - returns < 0 if error */ static int reg_r_12(struct gspca_dev *gspca_dev, - __u16 req, /* bRequest */ - __u16 index, /* wIndex */ - __u16 length) /* wLength (1 or 2 only) */ + u8 req, /* bRequest */ + u16 index, /* wIndex */ + u16 length) /* wLength (1 or 2 only) */ { int ret; @@ -591,43 +588,40 @@ static int reg_r_12(struct gspca_dev *gspca_dev, } static int write_vector(struct gspca_dev *gspca_dev, - const __u16 data[][3]) + const struct cmd *data, int ncmds) { struct usb_device *dev = gspca_dev->dev; - int ret, i = 0; + int ret; - while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) { - ret = reg_w_riv(dev, data[i][0], data[i][2], data[i][1]); + while (--ncmds >= 0) { + ret = reg_w_riv(dev, data->req, data->idx, data->val); if (ret < 0) { PDEBUG(D_ERR, - "Register write failed for 0x%x,0x%x,0x%x", - data[i][0], data[i][1], data[i][2]); + "Register write failed for 0x%02x, 0x%04x, 0x%04x", + data->req, data->val, data->idx); return ret; } - i++; + data++; } return 0; } static int spca50x_setup_qtable(struct gspca_dev *gspca_dev, - unsigned int request, - unsigned int ybase, - unsigned int cbase, - const __u8 qtable[2][64]) + const u8 qtable[2][64]) { struct usb_device *dev = gspca_dev->dev; int i, err; /* loop over y components */ for (i = 0; i < 64; i++) { - err = reg_w_riv(dev, request, ybase + i, qtable[0][i]); + err = reg_w_riv(dev, 0x00, 0x2800 + i, qtable[0][i]); if (err < 0) return err; } /* loop over c components */ for (i = 0; i < 64; i++) { - err = reg_w_riv(dev, request, cbase + i, qtable[1][i]); + err = reg_w_riv(dev, 0x00, 0x2840 + i, qtable[1][i]); if (err < 0) return err; } @@ -635,34 +629,34 @@ static int spca50x_setup_qtable(struct gspca_dev *gspca_dev, } static void spca504_acknowledged_command(struct gspca_dev *gspca_dev, - __u16 req, __u16 idx, __u16 val) + u8 req, u16 idx, u16 val) { struct usb_device *dev = gspca_dev->dev; - __u8 notdone; + int notdone; reg_w_riv(dev, req, idx, val); notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1); reg_w_riv(dev, req, idx, val); - PDEBUG(D_FRAM, "before wait 0x%x", notdone); + PDEBUG(D_FRAM, "before wait 0x%04x", notdone); msleep(200); notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1); - PDEBUG(D_FRAM, "after wait 0x%x", notdone); + PDEBUG(D_FRAM, "after wait 0x%04x", notdone); } static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev, - __u16 req, - __u16 idx, __u16 val, __u8 stat, __u8 count) + u8 req, + u16 idx, u16 val, u8 stat, u8 count) { struct usb_device *dev = gspca_dev->dev; - __u8 status; - __u8 endcode; + int status; + u8 endcode; reg_w_riv(dev, req, idx, val); status = reg_r_12(gspca_dev, 0x01, 0x0001, 1); endcode = stat; - PDEBUG(D_FRAM, "Status 0x%x Need 0x%x", status, stat); + PDEBUG(D_FRAM, "Status 0x%x Need 0x%04x", status, stat); if (!count) return; count = 200; @@ -672,7 +666,7 @@ static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev, /* reg_w_riv(dev, req, idx, val); */ status = reg_r_12(gspca_dev, 0x01, 0x0001, 1); if (status == endcode) { - PDEBUG(D_FRAM, "status 0x%x after wait 0x%x", + PDEBUG(D_FRAM, "status 0x%04x after wait %d", status, 200 - count); break; } @@ -699,8 +693,7 @@ static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev) while (--count > 0) { reg_r(gspca_dev, 0x21, 1, 1); if (gspca_dev->usb_buf[0] != 0) { - gspca_dev->usb_buf[0] = 0; - reg_w(gspca_dev, 0x21, 0, 1, 1); + reg_w_1(gspca_dev, 0x21, 0, 1, 0); reg_r(gspca_dev, 0x21, 1, 1); spca504B_PollingDataReady(gspca_dev); break; @@ -711,7 +704,7 @@ static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev) static void spca50x_GetFirmware(struct gspca_dev *gspca_dev) { - __u8 *data; + u8 *data; data = gspca_dev->usb_buf; reg_r(gspca_dev, 0x20, 0, 5); @@ -725,41 +718,34 @@ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; struct usb_device *dev = gspca_dev->dev; - __u8 Size; - __u8 Type; + u8 Size; int rc; - Size = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; - Type = 0; + Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; switch (sd->bridge) { case BRIDGE_SPCA533: - reg_w(gspca_dev, 0x31, 0, 0, 0); + reg_w_riv(dev, 0x31, 0, 0); spca504B_WaitCmdStatus(gspca_dev); rc = spca504B_PollingDataReady(gspca_dev); spca50x_GetFirmware(gspca_dev); - gspca_dev->usb_buf[0] = 2; /* type */ - reg_w(gspca_dev, 0x24, 0, 8, 1); + reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */ reg_r(gspca_dev, 0x24, 8, 1); - gspca_dev->usb_buf[0] = Size; - reg_w(gspca_dev, 0x25, 0, 4, 1); + reg_w_1(gspca_dev, 0x25, 0, 4, Size); reg_r(gspca_dev, 0x25, 4, 1); /* size */ rc = spca504B_PollingDataReady(gspca_dev); /* Init the cam width height with some values get on init ? */ - reg_w(gspca_dev, 0x31, 0, 4, 0); + reg_w_riv(dev, 0x31, 0, 0x04); spca504B_WaitCmdStatus(gspca_dev); rc = spca504B_PollingDataReady(gspca_dev); break; default: /* case BRIDGE_SPCA504B: */ /* case BRIDGE_SPCA536: */ - gspca_dev->usb_buf[0] = Size; - reg_w(gspca_dev, 0x25, 0, 4, 1); + reg_w_1(gspca_dev, 0x25, 0, 4, Size); reg_r(gspca_dev, 0x25, 4, 1); /* size */ - Type = 6; - gspca_dev->usb_buf[0] = Type; - reg_w(gspca_dev, 0x27, 0, 0, 1); + reg_w_1(gspca_dev, 0x27, 0, 0, 6); reg_r(gspca_dev, 0x27, 0, 1); /* type */ rc = spca504B_PollingDataReady(gspca_dev); break; @@ -799,17 +785,51 @@ static void spca504_wait_status(struct gspca_dev *gspca_dev) static void spca504B_setQtable(struct gspca_dev *gspca_dev) { - gspca_dev->usb_buf[0] = 3; - reg_w(gspca_dev, 0x26, 0, 0, 1); + reg_w_1(gspca_dev, 0x26, 0, 0, 3); reg_r(gspca_dev, 0x26, 0, 1); spca504B_PollingDataReady(gspca_dev); } -static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev) +static void setbrightness(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + struct usb_device *dev = gspca_dev->dev; + u16 reg; + + reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7; + reg_w_riv(dev, 0x00, reg, sd->brightness); +} + +static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + struct usb_device *dev = gspca_dev->dev; + u16 reg; + + reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8; + reg_w_riv(dev, 0x00, reg, sd->contrast); +} + +static void setcolors(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + struct usb_device *dev = gspca_dev->dev; + u16 reg; + + reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae; + reg_w_riv(dev, 0x00, reg, sd->colors); +} + +static void init_ctl_reg(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + struct usb_device *dev = gspca_dev->dev; int pollreg = 1; + setbrightness(gspca_dev); + setcontrast(gspca_dev); + setcolors(gspca_dev); + switch (sd->bridge) { case BRIDGE_SPCA504: case BRIDGE_SPCA504C: @@ -818,20 +838,14 @@ static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev) default: /* case BRIDGE_SPCA533: */ /* case BRIDGE_SPCA504B: */ - reg_w(gspca_dev, 0, 0, 0x21a7, 0); /* brightness */ - reg_w(gspca_dev, 0, 0x20, 0x21a8, 0); /* contrast */ - reg_w(gspca_dev, 0, 0, 0x21ad, 0); /* hue */ - reg_w(gspca_dev, 0, 1, 0x21ac, 0); /* sat/hue */ - reg_w(gspca_dev, 0, 0x20, 0x21ae, 0); /* saturation */ - reg_w(gspca_dev, 0, 0, 0x21a3, 0); /* gamma */ + reg_w_riv(dev, 0, 0x00, 0x21ad); /* hue */ + reg_w_riv(dev, 0, 0x01, 0x21ac); /* sat/hue */ + reg_w_riv(dev, 0, 0x00, 0x21a3); /* gamma */ break; case BRIDGE_SPCA536: - reg_w(gspca_dev, 0, 0, 0x20f0, 0); - reg_w(gspca_dev, 0, 0x21, 0x20f1, 0); - reg_w(gspca_dev, 0, 0x40, 0x20f5, 0); - reg_w(gspca_dev, 0, 1, 0x20f4, 0); - reg_w(gspca_dev, 0, 0x40, 0x20f6, 0); - reg_w(gspca_dev, 0, 0, 0x2089, 0); + reg_w_riv(dev, 0, 0x40, 0x20f5); + reg_w_riv(dev, 0, 0x01, 0x20f4); + reg_w_riv(dev, 0, 0x00, 0x2089); break; } if (pollreg) @@ -886,9 +900,10 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->nmodes = ARRAY_SIZE(vga_mode2); break; } - sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; - sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; - sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value; + sd->brightness = BRIGHTNESS_DEF; + sd->contrast = CONTRAST_DEF; + sd->colors = COLOR_DEF; + sd->autogain = AUTOGAIN_DEF; sd->quality = QUALITY_DEF; return 0; } @@ -898,32 +913,29 @@ static int sd_init(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; struct usb_device *dev = gspca_dev->dev; - int rc; - __u8 i; - __u8 info[6]; - int err_code; + int i, err_code; + u8 info[6]; switch (sd->bridge) { case BRIDGE_SPCA504B: - reg_w(gspca_dev, 0x1d, 0, 0, 0); - reg_w(gspca_dev, 0, 1, 0x2306, 0); - reg_w(gspca_dev, 0, 0, 0x0d04, 0); - reg_w(gspca_dev, 0, 0, 0x2000, 0); - reg_w(gspca_dev, 0, 0x13, 0x2301, 0); - reg_w(gspca_dev, 0, 0, 0x2306, 0); + reg_w_riv(dev, 0x1d, 0x00, 0); + reg_w_riv(dev, 0, 0x01, 0x2306); + reg_w_riv(dev, 0, 0x00, 0x0d04); + reg_w_riv(dev, 0, 0x00, 0x2000); + reg_w_riv(dev, 0, 0x13, 0x2301); + reg_w_riv(dev, 0, 0x00, 0x2306); /* fall thru */ case BRIDGE_SPCA533: - rc = spca504B_PollingDataReady(gspca_dev); + spca504B_PollingDataReady(gspca_dev); spca50x_GetFirmware(gspca_dev); break; case BRIDGE_SPCA536: spca50x_GetFirmware(gspca_dev); reg_r(gspca_dev, 0x00, 0x5002, 1); - gspca_dev->usb_buf[0] = 0; - reg_w(gspca_dev, 0x24, 0, 0, 1); + reg_w_1(gspca_dev, 0x24, 0, 0, 0); reg_r(gspca_dev, 0x24, 0, 1); - rc = spca504B_PollingDataReady(gspca_dev); - reg_w(gspca_dev, 0x34, 0, 0, 0); + spca504B_PollingDataReady(gspca_dev); + reg_w_riv(dev, 0x34, 0, 0); spca504B_WaitCmdStatus(gspca_dev); break; case BRIDGE_SPCA504C: /* pccam600 */ @@ -933,12 +945,13 @@ static int sd_init(struct gspca_dev *gspca_dev) spca504_wait_status(gspca_dev); if (sd->subtype == LogitechClickSmart420) write_vector(gspca_dev, - spca504A_clicksmart420_open_data); + spca504A_clicksmart420_open_data, + ARRAY_SIZE(spca504A_clicksmart420_open_data)); else - write_vector(gspca_dev, spca504_pccam600_open_data); + write_vector(gspca_dev, spca504_pccam600_open_data, + ARRAY_SIZE(spca504_pccam600_open_data)); err_code = spca50x_setup_qtable(gspca_dev, - 0x00, 0x2800, - 0x2840, qtable_creative_pccam); + qtable_creative_pccam); if (err_code < 0) { PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed"); return err_code; @@ -976,8 +989,8 @@ static int sd_init(struct gspca_dev *gspca_dev) 6, 0, 0x86, 1); */ /* spca504A_acknowledged_command (gspca_dev, 0x24, 0, 0, 0x9D, 1); */ - reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */ - reg_w_riv(dev, 0x0, 0x2310, 0x05); + reg_w_riv(dev, 0x00, 0x270c, 0x05); /* L92 sno1t.txt */ + reg_w_riv(dev, 0x00, 0x2310, 0x05); spca504A_acknowledged_command(gspca_dev, 0x01, 0x0f, 0, 0xff, 0); } @@ -985,8 +998,6 @@ static int sd_init(struct gspca_dev *gspca_dev) reg_w_riv(dev, 0, 0x2000, 0); reg_w_riv(dev, 0, 0x2883, 1); err_code = spca50x_setup_qtable(gspca_dev, - 0x00, 0x2800, - 0x2840, qtable_spca504_default); if (err_code < 0) { PDEBUG(D_ERR, "spca50x_setup_qtable failed"); @@ -1001,10 +1012,9 @@ static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; struct usb_device *dev = gspca_dev->dev; - int rc; int enable; - __u8 i; - __u8 info[6]; + int i; + u8 info[6]; /* create the JPEG header */ sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); @@ -1022,17 +1032,20 @@ static int sd_start(struct gspca_dev *gspca_dev) /* case BRIDGE_SPCA504B: */ /* case BRIDGE_SPCA533: */ /* case BRIDGE_SPCA536: */ - if (sd->subtype == MegapixV4 || - sd->subtype == LogitechClickSmart820 || - sd->subtype == MegaImageVI) { - reg_w(gspca_dev, 0xf0, 0, 0, 0); + switch (sd->subtype) { + case MegapixV4: + case LogitechClickSmart820: + case MegaImageVI: + reg_w_riv(dev, 0xf0, 0, 0); spca504B_WaitCmdStatus(gspca_dev); reg_r(gspca_dev, 0xf0, 4, 0); spca504B_WaitCmdStatus(gspca_dev); - } else { - reg_w(gspca_dev, 0x31, 0, 4, 0); + break; + default: + reg_w_riv(dev, 0x31, 0, 0x04); spca504B_WaitCmdStatus(gspca_dev); - rc = spca504B_PollingDataReady(gspca_dev); + spca504B_PollingDataReady(gspca_dev); + break; } break; case BRIDGE_SPCA504: @@ -1066,15 +1079,17 @@ static int sd_start(struct gspca_dev *gspca_dev) spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); } spca504B_SetSizeType(gspca_dev); - reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */ - reg_w_riv(dev, 0x0, 0x2310, 0x05); + reg_w_riv(dev, 0x00, 0x270c, 0x05); /* L92 sno1t.txt */ + reg_w_riv(dev, 0x00, 0x2310, 0x05); break; case BRIDGE_SPCA504C: if (sd->subtype == LogitechClickSmart420) { write_vector(gspca_dev, - spca504A_clicksmart420_init_data); + spca504A_clicksmart420_init_data, + ARRAY_SIZE(spca504A_clicksmart420_init_data)); } else { - write_vector(gspca_dev, spca504_pccam600_init_data); + write_vector(gspca_dev, spca504_pccam600_init_data, + ARRAY_SIZE(spca504_pccam600_init_data)); } enable = (sd->autogain ? 0x04 : 0x01); reg_w_riv(dev, 0x0c, 0x0000, enable); /* auto exposure */ @@ -1086,7 +1101,7 @@ static int sd_start(struct gspca_dev *gspca_dev) spca504B_SetSizeType(gspca_dev); break; } - sp5xx_initContBrigHueRegisters(gspca_dev); + init_ctl_reg(gspca_dev); return 0; } @@ -1100,7 +1115,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) /* case BRIDGE_SPCA533: */ /* case BRIDGE_SPCA536: */ /* case BRIDGE_SPCA504B: */ - reg_w(gspca_dev, 0x31, 0, 0, 0); + reg_w_riv(dev, 0x31, 0, 0); spca504B_WaitCmdStatus(gspca_dev); spca504B_PollingDataReady(gspca_dev); break; @@ -1118,7 +1133,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) 0x0f, 0x00, 0xff, 1); } else { spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); - reg_w_riv(dev, 0x01, 0x000f, 0x00); + reg_w_riv(dev, 0x01, 0x000f, 0x0000); } break; } @@ -1133,12 +1148,12 @@ static void sd_stop0(struct gspca_dev *gspca_dev) static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { struct sd *sd = (struct sd *) gspca_dev; int i, sof = 0; - static unsigned char ffd9[] = {0xff, 0xd9}; + static u8 ffd9[] = {0xff, 0xd9}; /* frames are jpeg 4.1.1 without 0xff escape */ switch (sd->bridge) { @@ -1226,63 +1241,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } -static void setbrightness(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; - - switch (sd->bridge) { - default: -/* case BRIDGE_SPCA533: */ -/* case BRIDGE_SPCA504B: */ -/* case BRIDGE_SPCA504: */ -/* case BRIDGE_SPCA504C: */ - reg_w_riv(dev, 0x0, 0x21a7, sd->brightness); - break; - case BRIDGE_SPCA536: - reg_w_riv(dev, 0x0, 0x20f0, sd->brightness); - break; - } -} - -static void setcontrast(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; - - switch (sd->bridge) { - default: -/* case BRIDGE_SPCA533: */ -/* case BRIDGE_SPCA504B: */ -/* case BRIDGE_SPCA504: */ -/* case BRIDGE_SPCA504C: */ - reg_w_riv(dev, 0x0, 0x21a8, sd->contrast); - break; - case BRIDGE_SPCA536: - reg_w_riv(dev, 0x0, 0x20f1, sd->contrast); - break; - } -} - -static void setcolors(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; - - switch (sd->bridge) { - default: -/* case BRIDGE_SPCA533: */ -/* case BRIDGE_SPCA504B: */ -/* case BRIDGE_SPCA504: */ -/* case BRIDGE_SPCA504C: */ - reg_w_riv(dev, 0x0, 0x21ae, sd->colors); - break; - case BRIDGE_SPCA536: - reg_w_riv(dev, 0x0, 0x20f6, sd->colors); - break; - } -} - static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; -- cgit v1.2.3 From 36dfe1e93c14212a6fd2939344018445f132789e Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Mon, 31 Aug 2009 16:32:46 +0200 Subject: Add new V4L2_FMT_FLAG_EMULATED flag to videodev2.h From: Hans de Goede V4L2_FMT_FLAG_EMULATED 0x0002 This format is not native to the device but emulated through software (usually libv4l2), where possible try to use a native format instead for better performance. Priority: normal Signed-off-by: Hans de Goede --- linux/include/linux/videodev2.h | 1 + 1 file changed, 1 insertion(+) (limited to 'linux') diff --git a/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h index b61c3b61c..d6f8edb3d 100644 --- a/linux/include/linux/videodev2.h +++ b/linux/include/linux/videodev2.h @@ -374,6 +374,7 @@ struct v4l2_fmtdesc { }; #define V4L2_FMT_FLAG_COMPRESSED 0x0001 +#define V4L2_FMT_FLAG_EMULATED 0x0002 #if 1 /*KEEP*/ /* Experimental Frame Size and frame rate enumeration */ -- cgit v1.2.3 From 4d8330c0438337574c9009264646100a5d1c2060 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 2 Sep 2009 11:04:14 +0200 Subject: gspca - sunplus: The brightness is signed. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sunplus.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/sunplus.c b/linux/drivers/media/video/gspca/sunplus.c index 94a3f53c6..32ff7cd32 100644 --- a/linux/drivers/media/video/gspca/sunplus.c +++ b/linux/drivers/media/video/gspca/sunplus.c @@ -32,7 +32,7 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - u8 brightness; + s8 brightness; u8 contrast; u8 colors; u8 autogain; @@ -73,8 +73,8 @@ static struct ctrl sd_ctrls[] = { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Brightness", - .minimum = 0, - .maximum = 0xff, + .minimum = -128, + .maximum = 127, .step = 1, #define BRIGHTNESS_DEF 0 .default_value = BRIGHTNESS_DEF, -- cgit v1.2.3 From d7afea829cb355469ef35d43604dea1be4358210 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 1 Sep 2009 18:49:05 +0200 Subject: gspca - vc032x: Change the start exchanges of the sensor hv7131r. From: Jean-Francois Moine The new exchanges are taken from the information file of the ms-win driver (usbvm326.inf - webcam 15b8:6002). Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 245 +++++++++++++++++++++---------- 1 file changed, 168 insertions(+), 77 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 6f9aab89c..89e15d150 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -1940,109 +1940,200 @@ static const u8 po3130_initQVGA_data[][4] = { }; static const u8 hv7131r_gamma[17] = { -/* 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, - * 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff */ +#if 1 + 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, + 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff +#else 0x04, 0x1a, 0x36, 0x55, 0x6f, 0x87, 0x9d, 0xb0, 0xc1, 0xcf, 0xda, 0xe4, 0xec, 0xf3, 0xf8, 0xfd, 0xff +#endif }; static const u8 hv7131r_matrix[9] = { 0x5f, 0xec, 0xf5, 0xf1, 0x5a, 0xf5, 0xf1, 0xec, 0x63 }; static const u8 hv7131r_initVGA_data[][4] = { - {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc}, - {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc}, + {0xb3, 0x01, 0x01, 0xcc}, + {0xb0, 0x03, 0x19, 0xcc}, + {0xb0, 0x04, 0x02, 0xcc}, + {0x00, 0x00, 0x20, 0xdd}, {0xb3, 0x00, 0x24, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x05, 0x00, 0xcc}, - {0xb3, 0x06, 0x01, 0xcc}, - {0xb3, 0x01, 0x45, 0xcc}, {0xb3, 0x03, 0x0b, 0xcc}, - {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x00, 0x25, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x03, 0xcc}, + {0xb3, 0x01, 0x45, 0xcc}, + {0xb3, 0x03, 0x0b, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x01, 0xcc}, {0xb3, 0x23, 0xe0, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x22, 0x01, 0xcc}, + {0xb3, 0x23, 0xe0, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x02, 0xcc}, {0xb3, 0x16, 0x02, 0xcc}, - {0xb3, 0x17, 0x7f, 0xcc}, {0xb3, 0x34, 0x01, 0xcc}, - {0xb3, 0x35, 0x91, 0xcc}, {0xb3, 0x00, 0x27, 0xcc}, + {0xb3, 0x17, 0x7f, 0xcc}, + {0xb3, 0x34, 0x01, 0xcc}, + {0xb3, 0x35, 0x91, 0xcc}, + {0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0x73, 0xcc}, - {0xb8, 0x00, 0x23, 0xcc}, {0x00, 0x01, 0x0c, 0xaa}, - {0x00, 0x14, 0x01, 0xaa}, {0x00, 0x15, 0xe6, 0xaa}, - {0x00, 0x16, 0x02, 0xaa}, - {0x00, 0x17, 0x86, 0xaa}, {0x00, 0x23, 0x00, 0xaa}, - {0x00, 0x25, 0x09, 0xaa}, {0x00, 0x26, 0x27, 0xaa}, - {0x00, 0x27, 0xc0, 0xaa}, - {0xb8, 0x2c, 0x60, 0xcc}, {0xb8, 0x2d, 0xf8, 0xcc}, - {0xb8, 0x2e, 0xf8, 0xcc}, {0xb8, 0x2f, 0xf8, 0xcc}, + {0xb8, 0x00, 0x23, 0xcc}, + {0xb8, 0x2c, 0x50, 0xcc}, + {0xb8, 0x2d, 0xf8, 0xcc}, + {0xb8, 0x2e, 0xf8, 0xcc}, + {0xb8, 0x2f, 0xf8, 0xcc}, {0xb8, 0x30, 0x50, 0xcc}, - {0xb8, 0x31, 0xf8, 0xcc}, {0xb8, 0x32, 0xf8, 0xcc}, - {0xb8, 0x33, 0xf8, 0xcc}, {0xb8, 0x34, 0x65, 0xcc}, + {0xb8, 0x31, 0xf8, 0xcc}, + {0xb8, 0x32, 0xf8, 0xcc}, + {0xb8, 0x33, 0xf8, 0xcc}, + {0xb8, 0x34, 0x58, 0xcc}, {0xb8, 0x35, 0x00, 0xcc}, - {0xb8, 0x36, 0x00, 0xcc}, {0xb8, 0x37, 0x00, 0xcc}, - {0xb8, 0x27, 0x20, 0xcc}, {0xb8, 0x01, 0x7d, 0xcc}, + {0xb8, 0x36, 0x00, 0xcc}, + {0xb8, 0x37, 0x00, 0xcc}, + {0xb8, 0x27, 0x20, 0xcc}, + {0xb8, 0x01, 0x7d, 0xcc}, {0xb8, 0x81, 0x09, 0xcc}, - {0xb3, 0x01, 0x41, 0xcc}, {0xb8, 0xfe, 0x00, 0xcc}, - {0xb8, 0xff, 0x28, 0xcc}, {0xb9, 0x00, 0x28, 0xcc}, - {0xb9, 0x01, 0x28, 0xcc}, - {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc}, - {0xb9, 0x04, 0x00, 0xcc}, {0xb9, 0x05, 0x3c, 0xcc}, - {0xb9, 0x06, 0x3c, 0xcc}, - {0xb9, 0x07, 0x3c, 0xcc}, {0xb9, 0x08, 0x3c, 0xcc}, - {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, + {0xb8, 0x8e, 0x00, 0xcc}, + {0xb8, 0x8f, 0xff, 0xcc}, + {0x00, 0x01, 0x0c, 0xaa}, + {0x00, 0x14, 0x01, 0xaa}, + {0x00, 0x15, 0xe6, 0xaa}, + {0x00, 0x16, 0x02, 0xaa}, + {0x00, 0x17, 0x86, 0xaa}, + {0x00, 0x23, 0x00, 0xaa}, + {0x00, 0x25, 0x03, 0xaa}, + {0x00, 0x26, 0xa9, 0xaa}, + {0x00, 0x27, 0x80, 0xaa}, {0x00, 0x30, 0x18, 0xaa}, + {0xb6, 0x00, 0x00, 0xcc}, + {0xb6, 0x03, 0x02, 0xcc}, + {0xb6, 0x02, 0x80, 0xcc}, + {0xb6, 0x05, 0x01, 0xcc}, + {0xb6, 0x04, 0xe0, 0xcc}, + {0xb6, 0x12, 0x78, 0xcc}, + {0xb6, 0x18, 0x02, 0xcc}, + {0xb6, 0x17, 0x58, 0xcc}, + {0xb6, 0x16, 0x00, 0xcc}, + {0xb6, 0x22, 0x12, 0xcc}, + {0xb6, 0x23, 0x0b, 0xcc}, + {0xb3, 0x02, 0x02, 0xcc}, + {0xbf, 0xc0, 0x39, 0xcc}, + {0xbf, 0xc1, 0x04, 0xcc}, + {0xbf, 0xcc, 0x10, 0xcc}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb6, 0x13, 0x13, 0xcc}, + {0xb9, 0x12, 0x00, 0xcc}, + {0xb9, 0x13, 0x0a, 0xcc}, + {0xb9, 0x14, 0x0a, 0xcc}, + {0xb9, 0x15, 0x0a, 0xcc}, + {0xb9, 0x16, 0x0a, 0xcc}, + {0xb8, 0x0c, 0x20, 0xcc}, + {0xb8, 0x0d, 0x70, 0xcc}, + {0xb9, 0x18, 0x00, 0xcc}, + {0xb9, 0x19, 0x0f, 0xcc}, + {0xb9, 0x1a, 0x0f, 0xcc}, + {0xb9, 0x1b, 0x0f, 0xcc}, + {0xb9, 0x1c, 0x0f, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, {} }; static const u8 hv7131r_initQVGA_data[][4] = { - {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc}, - {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc}, + {0xb3, 0x01, 0x01, 0xcc}, + {0xb0, 0x03, 0x19, 0xcc}, + {0xb0, 0x04, 0x02, 0xcc}, + {0x00, 0x00, 0x20, 0xdd}, {0xb3, 0x00, 0x24, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x05, 0x00, 0xcc}, - {0xb3, 0x06, 0x01, 0xcc}, - {0xb3, 0x03, 0x0b, 0xcc}, {0xb3, 0x04, 0x05, 0xcc}, - {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x00, 0x25, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x03, 0xcc}, + {0xb3, 0x01, 0x45, 0xcc}, + {0xb3, 0x03, 0x0b, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x01, 0xcc}, - {0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x14, 0x00, 0xcc}, - {0xb3, 0x15, 0x00, 0xcc}, {0xb3, 0x16, 0x02, 0xcc}, + {0xb3, 0x23, 0xe0, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x02, 0xcc}, + {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc}, - {0xb3, 0x34, 0x01, 0xcc}, {0xb3, 0x35, 0x91, 0xcc}, - {0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0xd1, 0xcc}, - {0xb8, 0x00, 0x21, 0xcc}, - {0x00, 0x01, 0x0c, 0xaa}, {0x00, 0x14, 0x01, 0xaa}, - {0x00, 0x15, 0xe6, 0xaa}, {0x00, 0x16, 0x02, 0xaa}, - {0x00, 0x17, 0x86, 0xaa}, - {0x00, 0x23, 0x00, 0xaa}, {0x00, 0x25, 0x01, 0xaa}, - {0x00, 0x26, 0xd4, 0xaa}, {0x00, 0x27, 0xc0, 0xaa}, - {0xbc, 0x02, 0x08, 0xcc}, - {0xbc, 0x03, 0x70, 0xcc}, {0xbc, 0x04, 0x08, 0xcc}, - {0xbc, 0x05, 0x00, 0xcc}, {0xbc, 0x06, 0x00, 0xcc}, - {0xbc, 0x08, 0x3c, 0xcc}, - {0xbc, 0x09, 0x40, 0xcc}, {0xbc, 0x0a, 0x04, 0xcc}, - {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc}, - {0xb8, 0xfe, 0x02, 0xcc}, - {0xb8, 0xff, 0x07, 0xcc}, {0xb9, 0x00, 0x14, 0xcc}, - {0xb9, 0x01, 0x14, 0xcc}, {0xb9, 0x02, 0x14, 0xcc}, - {0xb9, 0x03, 0x00, 0xcc}, - {0xb9, 0x04, 0x02, 0xcc}, {0xb9, 0x05, 0x05, 0xcc}, - {0xb9, 0x06, 0x0f, 0xcc}, {0xb9, 0x07, 0x0f, 0xcc}, - {0xb9, 0x08, 0x0f, 0xcc}, - {0xb8, 0x2c, 0x60, 0xcc}, {0xb8, 0x2d, 0xf8, 0xcc}, - {0xb8, 0x2e, 0xf8, 0xcc}, {0xb8, 0x2f, 0xf8, 0xcc}, + {0xb3, 0x34, 0x01, 0xcc}, + {0xb3, 0x35, 0x91, 0xcc}, + {0xb3, 0x00, 0x27, 0xcc}, + {0xbc, 0x00, 0xd3, 0xcc}, + {0xb8, 0x00, 0x23, 0xcc}, + {0xb8, 0x2c, 0x50, 0xcc}, + {0xb8, 0x2d, 0xf8, 0xcc}, + {0xb8, 0x2e, 0xf8, 0xcc}, + {0xb8, 0x2f, 0xf8, 0xcc}, {0xb8, 0x30, 0x50, 0xcc}, - {0xb8, 0x31, 0xf8, 0xcc}, {0xb8, 0x32, 0xf8, 0xcc}, + {0xb8, 0x31, 0xf8, 0xcc}, + {0xb8, 0x32, 0xf8, 0xcc}, {0xb8, 0x33, 0xf8, 0xcc}, - {0xb8, 0x34, 0x65, 0xcc}, {0xb8, 0x35, 0x00, 0xcc}, - {0xb8, 0x36, 0x00, 0xcc}, {0xb8, 0x37, 0x00, 0xcc}, + {0xb8, 0x34, 0x58, 0xcc}, + {0xb8, 0x35, 0x00, 0xcc}, + {0xb8, 0x36, 0x00, 0xcc}, + {0xb8, 0x37, 0x00, 0xcc}, {0xb8, 0x27, 0x20, 0xcc}, - {0xb8, 0x01, 0x7d, 0xcc}, {0xb8, 0x81, 0x09, 0xcc}, - {0xb3, 0x01, 0x41, 0xcc}, {0xb8, 0xfe, 0x00, 0xcc}, - {0xb8, 0xff, 0x28, 0xcc}, - {0xb9, 0x00, 0x28, 0xcc}, {0xb9, 0x01, 0x28, 0xcc}, - {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc}, - {0xb9, 0x04, 0x00, 0xcc}, - {0xb9, 0x05, 0x3c, 0xcc}, {0xb9, 0x06, 0x3c, 0xcc}, - {0xb9, 0x07, 0x3c, 0xcc}, {0xb9, 0x08, 0x3c, 0xcc}, + {0xb8, 0x01, 0x7d, 0xcc}, + {0xb8, 0x81, 0x09, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, {0xb8, 0x8e, 0x00, 0xcc}, - {0xb8, 0x8f, 0xff, 0xcc}, {0x00, 0x30, 0x18, 0xaa}, + {0xb8, 0x8f, 0xff, 0xcc}, + {0x00, 0x01, 0x0c, 0xaa}, + {0x00, 0x14, 0x01, 0xaa}, + {0x00, 0x15, 0xe6, 0xaa}, + {0x00, 0x16, 0x02, 0xaa}, + {0x00, 0x17, 0x86, 0xaa}, + {0x00, 0x23, 0x00, 0xaa}, + {0x00, 0x25, 0x03, 0xaa}, + {0x00, 0x26, 0xa9, 0xaa}, + {0x00, 0x27, 0x80, 0xaa}, + {0x00, 0x30, 0x18, 0xaa}, + {0xb6, 0x00, 0x00, 0xcc}, + {0xb6, 0x03, 0x01, 0xcc}, + {0xb6, 0x02, 0x40, 0xcc}, + {0xb6, 0x05, 0x00, 0xcc}, + {0xb6, 0x04, 0xf0, 0xcc}, + {0xb6, 0x12, 0x78, 0xcc}, + {0xb6, 0x18, 0x00, 0xcc}, + {0xb6, 0x17, 0x96, 0xcc}, + {0xb6, 0x16, 0x00, 0xcc}, + {0xb6, 0x22, 0x12, 0xcc}, + {0xb6, 0x23, 0x0b, 0xcc}, + {0xb3, 0x02, 0x02, 0xcc}, + {0xbf, 0xc0, 0x39, 0xcc}, + {0xbf, 0xc1, 0x04, 0xcc}, + {0xbf, 0xcc, 0x10, 0xcc}, + {0xbc, 0x02, 0x18, 0xcc}, + {0xbc, 0x03, 0x50, 0xcc}, + {0xbc, 0x04, 0x18, 0xcc}, + {0xbc, 0x05, 0x00, 0xcc}, + {0xbc, 0x06, 0x00, 0xcc}, + {0xbc, 0x08, 0x30, 0xcc}, + {0xbc, 0x09, 0x40, 0xcc}, + {0xbc, 0x0a, 0x10, 0xcc}, + {0xbc, 0x0b, 0x00, 0xcc}, + {0xbc, 0x0c, 0x00, 0xcc}, + {0xb9, 0x12, 0x00, 0xcc}, + {0xb9, 0x13, 0x0a, 0xcc}, + {0xb9, 0x14, 0x0a, 0xcc}, + {0xb9, 0x15, 0x0a, 0xcc}, + {0xb9, 0x16, 0x0a, 0xcc}, + {0xb9, 0x18, 0x00, 0xcc}, + {0xb9, 0x19, 0x0f, 0xcc}, + {0xb8, 0x0c, 0x20, 0xcc}, + {0xb8, 0x0d, 0x70, 0xcc}, + {0xb9, 0x1a, 0x0f, 0xcc}, + {0xb9, 0x1b, 0x0f, 0xcc}, + {0xb9, 0x1c, 0x0f, 0xcc}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb6, 0x13, 0x13, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, {} }; -- cgit v1.2.3 From 62a6104ddcd7cf381c4f6802b5c029b096d95355 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 1 Sep 2009 19:02:22 +0200 Subject: gspca - vc032x: Do the LED work with the sensor hv7131r. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 89e15d150..9464454f1 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -3410,21 +3410,22 @@ static int sd_start(struct gspca_dev *gspca_dev) put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c); /* set the led on 0x0892 0x0896 */ - if (sd->sensor == SENSOR_PO1200) { - setsharpness(gspca_dev); - sethvflip(gspca_dev); + switch (sd->sensor) { + case SENSOR_PO1200: + case SENSOR_HV7131R: reg_w(gspca_dev->dev, 0x89, 0x0400, 0x1415); - } else if (sd->sensor == SENSOR_MI1310_SOC) { + break; + case SENSOR_MI1310_SOC: reg_w(gspca_dev->dev, 0x89, 0x058c, 0x0000); - msleep(100); - sethvflip(gspca_dev); - setlightfreq(gspca_dev); - } else { + break; + default: reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff); - msleep(100); - sethvflip(gspca_dev); - setlightfreq(gspca_dev); + break; } + msleep(100); + setsharpness(gspca_dev); + sethvflip(gspca_dev); + setlightfreq(gspca_dev); } return 0; } -- cgit v1.2.3 From fe71d82c6502272eee2df15c848cd067cfd7b2f0 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 1 Sep 2009 19:52:04 +0200 Subject: gspca - sonixj / sn9c102: Two drivers for 0c45:60fc and 0c45:613e. From: Jean-Francois Moine Let 0c45:60fc in sn9c102 and 0c45:613e in gspca-sonixj (sensor not supported). Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 2 +- linux/drivers/media/video/sn9c102/sn9c102_devtable.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 55970fee6..3746ddbbe 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -2385,8 +2385,8 @@ static const __devinitdata struct usb_device_id device_table[] = { /* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */ /* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */ {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)}, - {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)}, #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE + {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)}, {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)}, #endif {USB_DEVICE(0x0c45, 0x6100), BSI(SN9C120, MI0360, 0x5d)}, /*sn9c128*/ diff --git a/linux/drivers/media/video/sn9c102/sn9c102_devtable.h b/linux/drivers/media/video/sn9c102/sn9c102_devtable.h index 38a716020..36ee43a9e 100644 --- a/linux/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/linux/drivers/media/video/sn9c102/sn9c102_devtable.h @@ -123,8 +123,8 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), }, #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), }, -#endif { SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), }, +#endif { } }; -- cgit v1.2.3 From b381f98d1b3f7204d763fb132e1c6ee6f384008e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 1 Sep 2009 22:16:23 +0200 Subject: vino: add missing compat.h include. From: Hans Verkuil vino needs compat.h to get the I2C_ADDRS macro on kernels < 2.6.31. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/vino.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux') diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index 8383e6f80..5a8dd5e19 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -50,6 +50,7 @@ #include #include +#include "compat.h" #include "vino.h" #include "saa7191.h" #include "indycam.h" -- cgit v1.2.3 From 3218818d07892e9fd082cf1b3165164eae279bb5 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 2 Sep 2009 00:15:39 +0200 Subject: DVB: make DVB_MAX_ADAPTERS configurable From: Janne Grunau Support for more than 8 DVB devices is requested regularly so make it a kconfig variable instead of a header define. Values in the range 4-32 are tested. Priority: normal Signed-off-by: Janne Grunau Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/Kconfig | 13 +++++++++++++ linux/drivers/media/dvb/dvb-core/dvbdev.h | 5 +++++ 2 files changed, 18 insertions(+) (limited to 'linux') diff --git a/linux/drivers/media/dvb/Kconfig b/linux/drivers/media/dvb/Kconfig index b01986918..1d0e4b1ef 100644 --- a/linux/drivers/media/dvb/Kconfig +++ b/linux/drivers/media/dvb/Kconfig @@ -2,6 +2,19 @@ # DVB device configuration # +config DVB_MAX_ADAPTERS + int "maximum number of DVB/ATSC adapters" + depends on DVB_CORE + default 8 + range 1 255 + help + Maximum number of DVB/ATSC adapters. Increasing this number + increases the memory consumption of the DVB subsystem even + if a much lower number of DVB/ATSC adapters is present. + Only values in the range 4-32 are tested. + + If you are unsure about this, use the default value 8 + config DVB_DYNAMIC_MINORS bool "Dynamic DVB minor allocation" depends on DVB_CORE diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.h b/linux/drivers/media/dvb/dvb-core/dvbdev.h index 487919bea..895e2efca 100644 --- a/linux/drivers/media/dvb/dvb-core/dvbdev.h +++ b/linux/drivers/media/dvb/dvb-core/dvbdev.h @@ -30,7 +30,12 @@ #define DVB_MAJOR 212 +#if defined(CONFIG_DVB_MAX_ADAPTERS) && CONFIG_DVB_MAX_ADAPTERS > 0 +#define DVB_MAX_ADAPTERS CONFIG_DVB_MAX_ADAPTERS +#else +#warning invalid CONFIG_DVB_MAX_ADAPTERS value #define DVB_MAX_ADAPTERS 8 +#endif #define DVB_UNSET (-1) -- cgit v1.2.3 From 39c7c8c56d56cc3a3fd5128d0598944303a929df Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 2 Sep 2009 00:23:09 +0200 Subject: dvb-core: check fe->ops.set_frontend return value From: Janne Grunau Various frontend driver have parameter checks in their set_frontend functions and return an error if the parameters are not supported, tda10021 and cx24116 to name two. The tuning ioctls FE_SET_FRONTEND/FE_SET_PROPERTY only change values in the property cache and return before set_frontend is called. If a set_frontend call in software zigzag algorithm fails and the card was previously locked it will report a lock and the new parameters but is still tuned to the old transport. This is not detectable from userspace. This change checks the return values of fe->ops.set_frontend and changes the state to the added FESTATE_ERROR for software zigzag. No lock will be reported to userspace if the State is FESTATE_ERROR. Priority: normal Signed-off-by: Janne Grunau --- linux/drivers/media/dvb/dvb-core/dvb_frontend.c | 26 ++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c index 41166d407..fbfccbd91 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -77,6 +77,7 @@ MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to seconds on open( #define FESTATE_ZIGZAG_FAST 32 #define FESTATE_ZIGZAG_SLOW 64 #define FESTATE_DISEQC 128 +#define FESTATE_ERROR 256 #define FESTATE_WAITFORLOCK (FESTATE_TUNING_FAST | FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW | FESTATE_DISEQC) #define FESTATE_SEARCHING_FAST (FESTATE_TUNING_FAST | FESTATE_ZIGZAG_FAST) #define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW) @@ -274,6 +275,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra { int autoinversion; int ready = 0; + int fe_set_err = 0; struct dvb_frontend_private *fepriv = fe->frontend_priv; int original_inversion = fepriv->parameters.inversion; u32 original_frequency = fepriv->parameters.frequency; @@ -350,7 +352,11 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra if (autoinversion) fepriv->parameters.inversion = fepriv->inversion; if (fe->ops.set_frontend) - fe->ops.set_frontend(fe, &fepriv->parameters); + fe_set_err = fe->ops.set_frontend(fe, &fepriv->parameters); + if (fe_set_err < 0) { + fepriv->state = FESTATE_ERROR; + return fe_set_err; + } fepriv->parameters.frequency = original_frequency; fepriv->parameters.inversion = original_inversion; @@ -362,6 +368,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra static void dvb_frontend_swzigzag(struct dvb_frontend *fe) { fe_status_t s = 0; + int retval = 0; struct dvb_frontend_private *fepriv = fe->frontend_priv; /* if we've got no parameters, just keep idling */ @@ -375,8 +382,12 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe) if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) { if (fepriv->state & FESTATE_RETUNE) { if (fe->ops.set_frontend) - fe->ops.set_frontend(fe, &fepriv->parameters); - fepriv->state = FESTATE_TUNED; + retval = fe->ops.set_frontend(fe, + &fepriv->parameters); + if (retval < 0) + fepriv->state = FESTATE_ERROR; + else + fepriv->state = FESTATE_TUNED; } fepriv->delay = 3*HZ; fepriv->quality = 0; @@ -454,7 +465,11 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe) fepriv->delay = fepriv->min_delay; /* peform a tune */ - if (dvb_frontend_swzigzag_autotune(fe, fepriv->check_wrapped)) { + retval = dvb_frontend_swzigzag_autotune(fe, + fepriv->check_wrapped); + if (retval < 0) { + return; + } else if (retval) { /* OK, if we've run out of trials at the fast speed. * Drop back to slow for the _next_ attempt */ fepriv->state = FESTATE_SEARCHING_SLOW; @@ -1614,7 +1629,8 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, /* if retune was requested but hasn't occured yet, prevent * that user get signal state from previous tuning */ - if(fepriv->state == FESTATE_RETUNE) { + if (fepriv->state == FESTATE_RETUNE || + fepriv->state == FESTATE_ERROR) { err=0; *status = 0; break; -- cgit v1.2.3 From 47515034f52a7a8848e3636668e31e1af4a79fbe Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 2 Sep 2009 00:24:08 +0200 Subject: dvb-core: check supported QAM modulations From: Janne Grunau Check the modulation in dvb_frontend_check_parameters against frontend's capabilties for FE_QAM devices. Priority: normal Signed-off-by: Janne Grunau --- linux/drivers/media/dvb/dvb-core/dvb_frontend.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'linux') diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c index fbfccbd91..56a11d32a 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -849,6 +849,15 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe, } } + /* check for supported modulation */ + if (fe->ops.info.type == FE_QAM && + (parms->u.qam.modulation > QAM_AUTO || + !((1 << (parms->u.qam.modulation + 10)) & fe->ops.info.caps))) { + printk(KERN_WARNING "DVB: adapter %i frontend %i modulation %u not supported\n", + fe->dvb->num, fe->id, parms->u.qam.modulation); + return -EINVAL; + } + return 0; } -- cgit v1.2.3 From 187a80bf44bebae8fd3a7ff804ecc523aaf6f3ea Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 2 Sep 2009 14:55:16 +0200 Subject: gspca_mr97310a: Allow overriding of detected sensor type From: Hans de Goede gspca_mr97310a: Allow overriding of detected sensor type Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/mr97310a.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index 8190a1d4d..169cdb65c 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -57,6 +57,11 @@ MODULE_AUTHOR("Kyle Guinn ," MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver"); MODULE_LICENSE("GPL"); +/* global parameters */ +int force_sensor_type = -1; +module_param(force_sensor_type, int, 0644); +MODULE_PARM_DESC(force_sensor_type, "Force sensor type (-1 (auto), 0 or 1)"); + /* specific webcam descriptor */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ @@ -401,6 +406,12 @@ static int sd_config(struct gspca_dev *gspca_dev, PDEBUG(D_PROBE, "MR97310A CIF camera detected, sensor: %d", sd->sensor_type); + if (force_sensor_type != -1) { + sd->sensor_type = !! force_sensor_type; + PDEBUG(D_PROBE, "Forcing sensor type to: %d", + sd->sensor_type); + } + if (sd->sensor_type == 0) gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX); } else { @@ -606,6 +617,12 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) msleep(200); } + if (force_sensor_type != -1) { + sd->sensor_type = !! force_sensor_type; + PDEBUG(D_PROBE, "Forcing sensor type to: %d", + sd->sensor_type); + } + /* * Known VGA cameras. * This test is only run if the previous test returned 0x30, but -- cgit v1.2.3 From 4b70cc85ac708fdb3107b4d17851e70e6bf9ecc6 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Thu, 3 Sep 2009 09:14:36 +0200 Subject: gspca_mr97310a: Add one more vivitar mini cam to the list of CIF cams From: Hans de Goede gspca_mr97310a: Add one more vivitar mini cam to the list of CIF cams Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/mr97310a.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index 169cdb65c..140c8f320 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -393,6 +393,7 @@ static int sd_config(struct gspca_dev *gspca_dev, * Sakar Spy-shot 0x28 T. Kilgore 0 * Innovage 0xf5 (unstable) T. Kilgore 0 * Vivitar Mini 0x53 H. De Goede 0 + * Vivitar Mini 0x04 / 0x24 E. Rodriguez 0 * Vivitar Mini 0x08 T. Kilgore 1 * Elta-Media 8212dc 0x23 T. Kaiser 1 * Philips dig. keych. 0x37 T. Kilgore 1 -- cgit v1.2.3 From b90712cf41e75451c3b515ed41d2eda714db3de1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 7 Sep 2009 01:16:50 -0300 Subject: em28xx: ir-kbd-i2c initialization data should point to a persistent object From: Mauro Carvalho Chehab ir-kbd-i2c's ir_probe() function can be called much later (i.e. at ir-kbd-i2c module load), than the lifetime of a struct IR_i2c_init_data allocated off of the stack in cx18_i2c_new_ir() at registration time. Make sure we pass a pointer to a persistent IR_i2c_init_data object at i2c registration time. Thanks to Brain Rogers, Dustin Mitchell, Andy Walls and Jean Delvare to rise this question. Before this patch, if ir-kbd-i2c were probed after em28xx, trash data were used. After the patch, no matter what order, it is properly reported as tested by me: input: i2c IR (i2c IR (EM2840 Hauppaug as /class/input/input10 ir-kbd-i2c: i2c IR (i2c IR (EM2840 Hauppaug detected at i2c-4/4-0030/ir0 [em28xx #0] Priority: high Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 34 ++++++++++++------------- linux/drivers/media/video/em28xx/em28xx.h | 4 +++ 2 files changed, 20 insertions(+), 18 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 656604dc9..d12c8c890 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2275,11 +2275,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev) #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) if (disable_ir) { ir->get_key = NULL; - return ; + return; } #else - struct i2c_board_info info; - struct IR_i2c_init_data init_data; const unsigned short addr_list[] = { 0x30, 0x47, I2C_CLIENT_END }; @@ -2287,9 +2285,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev) if (disable_ir) return; - memset(&info, 0, sizeof(struct i2c_board_info)); - memset(&init_data, 0, sizeof(struct IR_i2c_init_data)); - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + memset(&dev->info, 0, sizeof(&dev->info)); + memset(&dev->init_data, 0, sizeof(dev->init_data)); + strlcpy(dev->info.type, "ir_video", I2C_NAME_SIZE); #endif /* detect & configure */ @@ -2306,9 +2304,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev) snprintf(ir->name, sizeof(ir->name), "i2c IR (EM28XX Terratec)"); #else - init_data.ir_codes = &ir_codes_em_terratec_table; - init_data.get_key = em28xx_get_key_terratec; - init_data.name = "i2c IR (EM28XX Terratec)"; + dev->init_data.ir_codes = &ir_codes_em_terratec_table; + dev->init_data.get_key = em28xx_get_key_terratec; + dev->init_data.name = "i2c IR (EM28XX Terratec)"; #endif break; case (EM2820_BOARD_PINNACLE_USB_2): @@ -2318,9 +2316,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev) snprintf(ir->name, sizeof(ir->name), "i2c IR (EM28XX Pinnacle PCTV)"); #else - init_data.ir_codes = &ir_codes_pinnacle_grey_table; - init_data.get_key = em28xx_get_key_pinnacle_usb_grey; - init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; + dev->init_data.ir_codes = &ir_codes_pinnacle_grey_table; + dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey; + dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; #endif break; case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): @@ -2330,9 +2328,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev) snprintf(ir->name, sizeof(ir->name), "i2c IR (EM2840 Hauppauge)"); #else - init_data.ir_codes = &ir_codes_hauppauge_new_table; - init_data.get_key = em28xx_get_key_em_haup; - init_data.name = "i2c IR (EM2840 Hauppauge)"; + dev->init_data.ir_codes = &ir_codes_hauppauge_new_table; + dev->init_data.get_key = em28xx_get_key_em_haup; + dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; #endif break; case (EM2820_BOARD_MSI_VOX_USB_2): @@ -2346,9 +2344,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev) } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) - if (init_data.name) - info.platform_data = &init_data; - i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); + if (dev->init_data.name) + dev->info.platform_data = &dev->init_data; + i2c_new_probed_device(&dev->i2c_adap, &dev->info, addr_list); #endif } diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index a603d981b..e5d6b0695 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -606,6 +606,10 @@ struct em28xx { struct delayed_work sbutton_query_work; struct em28xx_dvb *dvb; + + /* I2C keyboard data */ + struct i2c_board_info info; + struct IR_i2c_init_data init_data; }; struct em28xx_ops { -- cgit v1.2.3