Path: blob/master/drivers/media/video/gspca/mr97310a.c
17683 views
/*1* Mars MR97310A library2*3* The original mr97310a driver, which supported the Aiptek Pencam VGA+, is4* Copyright (C) 2009 Kyle Guinn <[email protected]>5*6* Support for the MR97310A cameras in addition to the Aiptek Pencam VGA+7* and for the routines for detecting and classifying these various cameras,8* is Copyright (C) 2009 Theodore Kilgore <[email protected]>9*10* Support for the control settings for the CIF cameras is11* Copyright (C) 2009 Hans de Goede <[email protected]> and12* Thomas Kaiser <[email protected]>13*14* Support for the control settings for the VGA cameras is15* Copyright (C) 2009 Theodore Kilgore <[email protected]>16*17* Several previously unsupported cameras are owned and have been tested by18* Hans de Goede <[email protected]> and19* Thomas Kaiser <[email protected]> and20* Theodore Kilgore <[email protected]> and21* Edmond Rodriguez <[email protected]> and22* Aurelien Jacobs <[email protected]>23*24* The MR97311A support in gspca/mars.c has been helpful in understanding some25* of the registers in these cameras.26*27* This program is free software; you can redistribute it and/or modify28* it under the terms of the GNU General Public License as published by29* the Free Software Foundation; either version 2 of the License, or30* any later version.31*32* This program is distributed in the hope that it will be useful,33* but WITHOUT ANY WARRANTY; without even the implied warranty of34* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the35* GNU General Public License for more details.36*37* You should have received a copy of the GNU General Public License38* along with this program; if not, write to the Free Software39* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA40*/4142#define MODULE_NAME "mr97310a"4344#include "gspca.h"4546#define CAM_TYPE_CIF 047#define CAM_TYPE_VGA 14849#define MR97310A_BRIGHTNESS_DEFAULT 05051#define MR97310A_EXPOSURE_MIN 052#define MR97310A_EXPOSURE_MAX 409553#define MR97310A_EXPOSURE_DEFAULT 10005455#define MR97310A_GAIN_MIN 056#define MR97310A_GAIN_MAX 3157#define MR97310A_GAIN_DEFAULT 255859#define MR97310A_CONTRAST_MIN 060#define MR97310A_CONTRAST_MAX 3161#define MR97310A_CONTRAST_DEFAULT 236263#define MR97310A_CS_GAIN_MIN 064#define MR97310A_CS_GAIN_MAX 0x7ff65#define MR97310A_CS_GAIN_DEFAULT 0x1106667#define MR97310A_MIN_CLOCKDIV_MIN 368#define MR97310A_MIN_CLOCKDIV_MAX 869#define MR97310A_MIN_CLOCKDIV_DEFAULT 37071MODULE_AUTHOR("Kyle Guinn <[email protected]>,"72"Theodore Kilgore <[email protected]>");73MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver");74MODULE_LICENSE("GPL");7576/* global parameters */77static int force_sensor_type = -1;78module_param(force_sensor_type, int, 0644);79MODULE_PARM_DESC(force_sensor_type, "Force sensor type (-1 (auto), 0 or 1)");8081/* specific webcam descriptor */82struct sd {83struct gspca_dev gspca_dev; /* !! must be the first item */84u8 sof_read;85u8 cam_type; /* 0 is CIF and 1 is VGA */86u8 sensor_type; /* We use 0 and 1 here, too. */87u8 do_lcd_stop;88u8 adj_colors;8990int brightness;91u16 exposure;92u32 gain;93u8 contrast;94u8 min_clockdiv;95};9697struct sensor_w_data {98u8 reg;99u8 flags;100u8 data[16];101int len;102};103104static void sd_stopN(struct gspca_dev *gspca_dev);105static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);106static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);107static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);108static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);109static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);110static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);111static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);112static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);113static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val);114static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val);115static void setbrightness(struct gspca_dev *gspca_dev);116static void setexposure(struct gspca_dev *gspca_dev);117static void setgain(struct gspca_dev *gspca_dev);118static void setcontrast(struct gspca_dev *gspca_dev);119120/* V4L2 controls supported by the driver */121static const struct ctrl sd_ctrls[] = {122/* Separate brightness control description for Argus QuickClix as it has123* different limits from the other mr97310a cameras, and separate gain124* control for Sakar CyberPix camera. */125{126#define NORM_BRIGHTNESS_IDX 0127{128.id = V4L2_CID_BRIGHTNESS,129.type = V4L2_CTRL_TYPE_INTEGER,130.name = "Brightness",131.minimum = -254,132.maximum = 255,133.step = 1,134.default_value = MR97310A_BRIGHTNESS_DEFAULT,135.flags = 0,136},137.set = sd_setbrightness,138.get = sd_getbrightness,139},140{141#define ARGUS_QC_BRIGHTNESS_IDX 1142{143.id = V4L2_CID_BRIGHTNESS,144.type = V4L2_CTRL_TYPE_INTEGER,145.name = "Brightness",146.minimum = 0,147.maximum = 15,148.step = 1,149.default_value = MR97310A_BRIGHTNESS_DEFAULT,150.flags = 0,151},152.set = sd_setbrightness,153.get = sd_getbrightness,154},155{156#define EXPOSURE_IDX 2157{158.id = V4L2_CID_EXPOSURE,159.type = V4L2_CTRL_TYPE_INTEGER,160.name = "Exposure",161.minimum = MR97310A_EXPOSURE_MIN,162.maximum = MR97310A_EXPOSURE_MAX,163.step = 1,164.default_value = MR97310A_EXPOSURE_DEFAULT,165.flags = 0,166},167.set = sd_setexposure,168.get = sd_getexposure,169},170{171#define GAIN_IDX 3172{173.id = V4L2_CID_GAIN,174.type = V4L2_CTRL_TYPE_INTEGER,175.name = "Gain",176.minimum = MR97310A_GAIN_MIN,177.maximum = MR97310A_GAIN_MAX,178.step = 1,179.default_value = MR97310A_GAIN_DEFAULT,180.flags = 0,181},182.set = sd_setgain,183.get = sd_getgain,184},185{186#define SAKAR_CS_GAIN_IDX 4187{188.id = V4L2_CID_GAIN,189.type = V4L2_CTRL_TYPE_INTEGER,190.name = "Gain",191.minimum = MR97310A_CS_GAIN_MIN,192.maximum = MR97310A_CS_GAIN_MAX,193.step = 1,194.default_value = MR97310A_CS_GAIN_DEFAULT,195.flags = 0,196},197.set = sd_setgain,198.get = sd_getgain,199},200{201#define CONTRAST_IDX 5202{203.id = V4L2_CID_CONTRAST,204.type = V4L2_CTRL_TYPE_INTEGER,205.name = "Contrast",206.minimum = MR97310A_CONTRAST_MIN,207.maximum = MR97310A_CONTRAST_MAX,208.step = 1,209.default_value = MR97310A_CONTRAST_DEFAULT,210.flags = 0,211},212.set = sd_setcontrast,213.get = sd_getcontrast,214},215{216#define MIN_CLOCKDIV_IDX 6217{218.id = V4L2_CID_PRIVATE_BASE,219.type = V4L2_CTRL_TYPE_INTEGER,220.name = "Minimum Clock Divider",221.minimum = MR97310A_MIN_CLOCKDIV_MIN,222.maximum = MR97310A_MIN_CLOCKDIV_MAX,223.step = 1,224.default_value = MR97310A_MIN_CLOCKDIV_DEFAULT,225.flags = 0,226},227.set = sd_setmin_clockdiv,228.get = sd_getmin_clockdiv,229},230};231232static const struct v4l2_pix_format vga_mode[] = {233{160, 120, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,234.bytesperline = 160,235.sizeimage = 160 * 120,236.colorspace = V4L2_COLORSPACE_SRGB,237.priv = 4},238{176, 144, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,239.bytesperline = 176,240.sizeimage = 176 * 144,241.colorspace = V4L2_COLORSPACE_SRGB,242.priv = 3},243{320, 240, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,244.bytesperline = 320,245.sizeimage = 320 * 240,246.colorspace = V4L2_COLORSPACE_SRGB,247.priv = 2},248{352, 288, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,249.bytesperline = 352,250.sizeimage = 352 * 288,251.colorspace = V4L2_COLORSPACE_SRGB,252.priv = 1},253{640, 480, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,254.bytesperline = 640,255.sizeimage = 640 * 480,256.colorspace = V4L2_COLORSPACE_SRGB,257.priv = 0},258};259260/* the bytes to write are in gspca_dev->usb_buf */261static int mr_write(struct gspca_dev *gspca_dev, int len)262{263int rc;264265rc = usb_bulk_msg(gspca_dev->dev,266usb_sndbulkpipe(gspca_dev->dev, 4),267gspca_dev->usb_buf, len, NULL, 500);268if (rc < 0)269err("reg write [%02x] error %d",270gspca_dev->usb_buf[0], rc);271return rc;272}273274/* the bytes are read into gspca_dev->usb_buf */275static int mr_read(struct gspca_dev *gspca_dev, int len)276{277int rc;278279rc = usb_bulk_msg(gspca_dev->dev,280usb_rcvbulkpipe(gspca_dev->dev, 3),281gspca_dev->usb_buf, len, NULL, 500);282if (rc < 0)283err("reg read [%02x] error %d",284gspca_dev->usb_buf[0], rc);285return rc;286}287288static int sensor_write_reg(struct gspca_dev *gspca_dev, u8 reg, u8 flags,289const u8 *data, int len)290{291gspca_dev->usb_buf[0] = 0x1f;292gspca_dev->usb_buf[1] = flags;293gspca_dev->usb_buf[2] = reg;294memcpy(gspca_dev->usb_buf + 3, data, len);295296return mr_write(gspca_dev, len + 3);297}298299static int sensor_write_regs(struct gspca_dev *gspca_dev,300const struct sensor_w_data *data, int len)301{302int i, rc;303304for (i = 0; i < len; i++) {305rc = sensor_write_reg(gspca_dev, data[i].reg, data[i].flags,306data[i].data, data[i].len);307if (rc < 0)308return rc;309}310311return 0;312}313314static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data)315{316struct sd *sd = (struct sd *) gspca_dev;317u8 buf, confirm_reg;318int rc;319320buf = data;321if (sd->cam_type == CAM_TYPE_CIF) {322rc = sensor_write_reg(gspca_dev, reg, 0x01, &buf, 1);323confirm_reg = sd->sensor_type ? 0x13 : 0x11;324} else {325rc = sensor_write_reg(gspca_dev, reg, 0x00, &buf, 1);326confirm_reg = 0x11;327}328if (rc < 0)329return rc;330331buf = 0x01;332rc = sensor_write_reg(gspca_dev, confirm_reg, 0x00, &buf, 1);333if (rc < 0)334return rc;335336return 0;337}338339static int cam_get_response16(struct gspca_dev *gspca_dev, u8 reg, int verbose)340{341int err_code;342343gspca_dev->usb_buf[0] = reg;344err_code = mr_write(gspca_dev, 1);345if (err_code < 0)346return err_code;347348err_code = mr_read(gspca_dev, 16);349if (err_code < 0)350return err_code;351352if (verbose)353PDEBUG(D_PROBE, "Register: %02x reads %02x%02x%02x", reg,354gspca_dev->usb_buf[0],355gspca_dev->usb_buf[1],356gspca_dev->usb_buf[2]);357358return 0;359}360361static int zero_the_pointer(struct gspca_dev *gspca_dev)362{363__u8 *data = gspca_dev->usb_buf;364int err_code;365u8 status = 0;366int tries = 0;367368err_code = cam_get_response16(gspca_dev, 0x21, 0);369if (err_code < 0)370return err_code;371372data[0] = 0x19;373data[1] = 0x51;374err_code = mr_write(gspca_dev, 2);375if (err_code < 0)376return err_code;377378err_code = cam_get_response16(gspca_dev, 0x21, 0);379if (err_code < 0)380return err_code;381382data[0] = 0x19;383data[1] = 0xba;384err_code = mr_write(gspca_dev, 2);385if (err_code < 0)386return err_code;387388err_code = cam_get_response16(gspca_dev, 0x21, 0);389if (err_code < 0)390return err_code;391392data[0] = 0x19;393data[1] = 0x00;394err_code = mr_write(gspca_dev, 2);395if (err_code < 0)396return err_code;397398err_code = cam_get_response16(gspca_dev, 0x21, 0);399if (err_code < 0)400return err_code;401402data[0] = 0x19;403data[1] = 0x00;404err_code = mr_write(gspca_dev, 2);405if (err_code < 0)406return err_code;407408while (status != 0x0a && tries < 256) {409err_code = cam_get_response16(gspca_dev, 0x21, 0);410status = data[0];411tries++;412if (err_code < 0)413return err_code;414}415if (status != 0x0a)416PDEBUG(D_ERR, "status is %02x", status);417418tries = 0;419while (tries < 4) {420data[0] = 0x19;421data[1] = 0x00;422err_code = mr_write(gspca_dev, 2);423if (err_code < 0)424return err_code;425426err_code = cam_get_response16(gspca_dev, 0x21, 0);427status = data[0];428tries++;429if (err_code < 0)430return err_code;431}432433data[0] = 0x19;434err_code = mr_write(gspca_dev, 1);435if (err_code < 0)436return err_code;437438err_code = mr_read(gspca_dev, 16);439if (err_code < 0)440return err_code;441442return 0;443}444445static int stream_start(struct gspca_dev *gspca_dev)446{447gspca_dev->usb_buf[0] = 0x01;448gspca_dev->usb_buf[1] = 0x01;449return mr_write(gspca_dev, 2);450}451452static void stream_stop(struct gspca_dev *gspca_dev)453{454gspca_dev->usb_buf[0] = 0x01;455gspca_dev->usb_buf[1] = 0x00;456if (mr_write(gspca_dev, 2) < 0)457PDEBUG(D_ERR, "Stream Stop failed");458}459460static void lcd_stop(struct gspca_dev *gspca_dev)461{462gspca_dev->usb_buf[0] = 0x19;463gspca_dev->usb_buf[1] = 0x54;464if (mr_write(gspca_dev, 2) < 0)465PDEBUG(D_ERR, "LCD Stop failed");466}467468static int isoc_enable(struct gspca_dev *gspca_dev)469{470gspca_dev->usb_buf[0] = 0x00;471gspca_dev->usb_buf[1] = 0x4d; /* ISOC transferring enable... */472return mr_write(gspca_dev, 2);473}474475/* This function is called at probe time */476static int sd_config(struct gspca_dev *gspca_dev,477const struct usb_device_id *id)478{479struct sd *sd = (struct sd *) gspca_dev;480struct cam *cam;481int gain_default = MR97310A_GAIN_DEFAULT;482int err_code;483484cam = &gspca_dev->cam;485cam->cam_mode = vga_mode;486cam->nmodes = ARRAY_SIZE(vga_mode);487sd->do_lcd_stop = 0;488489/* Several of the supported CIF cameras share the same USB ID but490* require different initializations and different control settings.491* The same is true of the VGA cameras. Therefore, we are forced492* to start the initialization process in order to determine which493* camera is present. Some of the supported cameras require the494* memory pointer to be set to 0 as the very first item of business495* or else they will not stream. So we do that immediately.496*/497err_code = zero_the_pointer(gspca_dev);498if (err_code < 0)499return err_code;500501err_code = stream_start(gspca_dev);502if (err_code < 0)503return err_code;504505/* Now, the query for sensor type. */506err_code = cam_get_response16(gspca_dev, 0x07, 1);507if (err_code < 0)508return err_code;509510if (id->idProduct == 0x0110 || id->idProduct == 0x010e) {511sd->cam_type = CAM_TYPE_CIF;512cam->nmodes--;513/*514* All but one of the known CIF cameras share the same USB ID,515* but two different init routines are in use, and the control516* settings are different, too. We need to detect which camera517* of the two known varieties is connected!518*519* A list of known CIF cameras follows. They all report either520* 0200 for type 0 or 0300 for type 1.521* If you have another to report, please do522*523* Name sd->sensor_type reported by524*525* Sakar 56379 Spy-shot 0 T. Kilgore526* Innovage 0 T. Kilgore527* Vivitar Mini 0 H. De Goede528* Vivitar Mini 0 E. Rodriguez529* Vivitar Mini 1 T. Kilgore530* Elta-Media 8212dc 1 T. Kaiser531* Philips dig. keych. 1 T. Kilgore532* Trust Spyc@m 100 1 A. Jacobs533*/534switch (gspca_dev->usb_buf[0]) {535case 2:536sd->sensor_type = 0;537break;538case 3:539sd->sensor_type = 1;540break;541default:542err("Unknown CIF Sensor id : %02x",543gspca_dev->usb_buf[1]);544return -ENODEV;545}546PDEBUG(D_PROBE, "MR97310A CIF camera detected, sensor: %d",547sd->sensor_type);548} else {549sd->cam_type = CAM_TYPE_VGA;550551/*552* Here is a table of the responses to the query for sensor553* type, from the known MR97310A VGA cameras. Six different554* cameras of which five share the same USB ID.555*556* Name gspca_dev->usb_buf[] sd->sensor_type557* sd->do_lcd_stop558* Aiptek Pencam VGA+ 0300 0 1559* ION digital 0300 0 1560* Argus DC-1620 0450 1 0561* Argus QuickClix 0420 1 1562* Sakar 77379 Digital 0350 0 1563* Sakar 1638x CyberPix 0120 0 2564*565* Based upon these results, we assume default settings566* and then correct as necessary, as follows.567*568*/569570sd->sensor_type = 1;571sd->do_lcd_stop = 0;572sd->adj_colors = 0;573if (gspca_dev->usb_buf[0] == 0x01) {574sd->sensor_type = 2;575} else if ((gspca_dev->usb_buf[0] != 0x03) &&576(gspca_dev->usb_buf[0] != 0x04)) {577err("Unknown VGA Sensor id Byte 0: %02x",578gspca_dev->usb_buf[0]);579err("Defaults assumed, may not work");580err("Please report this");581}582/* Sakar Digital color needs to be adjusted. */583if ((gspca_dev->usb_buf[0] == 0x03) &&584(gspca_dev->usb_buf[1] == 0x50))585sd->adj_colors = 1;586if (gspca_dev->usb_buf[0] == 0x04) {587sd->do_lcd_stop = 1;588switch (gspca_dev->usb_buf[1]) {589case 0x50:590sd->sensor_type = 0;591PDEBUG(D_PROBE, "sensor_type corrected to 0");592break;593case 0x20:594/* Nothing to do here. */595break;596default:597err("Unknown VGA Sensor id Byte 1: %02x",598gspca_dev->usb_buf[1]);599err("Defaults assumed, may not work");600err("Please report this");601}602}603PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d",604sd->sensor_type);605}606/* Stop streaming as we've started it only to probe the sensor type. */607sd_stopN(gspca_dev);608609if (force_sensor_type != -1) {610sd->sensor_type = !!force_sensor_type;611PDEBUG(D_PROBE, "Forcing sensor type to: %d",612sd->sensor_type);613}614615/* Setup controls depending on camera type */616if (sd->cam_type == CAM_TYPE_CIF) {617/* No brightness for sensor_type 0 */618if (sd->sensor_type == 0)619gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) |620(1 << ARGUS_QC_BRIGHTNESS_IDX) |621(1 << CONTRAST_IDX) |622(1 << SAKAR_CS_GAIN_IDX);623else624gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) |625(1 << CONTRAST_IDX) |626(1 << SAKAR_CS_GAIN_IDX) |627(1 << MIN_CLOCKDIV_IDX);628} else {629/* All controls need to be disabled if VGA sensor_type is 0 */630if (sd->sensor_type == 0)631gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) |632(1 << ARGUS_QC_BRIGHTNESS_IDX) |633(1 << EXPOSURE_IDX) |634(1 << GAIN_IDX) |635(1 << CONTRAST_IDX) |636(1 << SAKAR_CS_GAIN_IDX) |637(1 << MIN_CLOCKDIV_IDX);638else if (sd->sensor_type == 2) {639gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) |640(1 << ARGUS_QC_BRIGHTNESS_IDX) |641(1 << GAIN_IDX) |642(1 << MIN_CLOCKDIV_IDX);643gain_default = MR97310A_CS_GAIN_DEFAULT;644} else if (sd->do_lcd_stop)645/* Argus QuickClix has different brightness limits */646gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) |647(1 << CONTRAST_IDX) |648(1 << SAKAR_CS_GAIN_IDX);649else650gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) |651(1 << CONTRAST_IDX) |652(1 << SAKAR_CS_GAIN_IDX);653}654655sd->brightness = MR97310A_BRIGHTNESS_DEFAULT;656sd->exposure = MR97310A_EXPOSURE_DEFAULT;657sd->gain = gain_default;658sd->contrast = MR97310A_CONTRAST_DEFAULT;659sd->min_clockdiv = MR97310A_MIN_CLOCKDIV_DEFAULT;660661return 0;662}663664/* this function is called at probe and resume time */665static int sd_init(struct gspca_dev *gspca_dev)666{667return 0;668}669670static int start_cif_cam(struct gspca_dev *gspca_dev)671{672struct sd *sd = (struct sd *) gspca_dev;673__u8 *data = gspca_dev->usb_buf;674int err_code;675static const __u8 startup_string[] = {6760x00,6770x0d,6780x01,6790x00, /* Hsize/8 for 352 or 320 */6800x00, /* Vsize/4 for 288 or 240 */6810x13, /* or 0xbb, depends on sensor */6820x00, /* Hstart, depends on res. */6830x00, /* reserved ? */6840x00, /* Vstart, depends on res. and sensor */6850x50, /* 0x54 to get 176 or 160 */6860xc0687};688689/* Note: Some of the above descriptions guessed from MR97113A driver */690691memcpy(data, startup_string, 11);692if (sd->sensor_type)693data[5] = 0xbb;694695switch (gspca_dev->width) {696case 160:697data[9] |= 0x04; /* reg 8, 2:1 scale down from 320 */698/* fall thru */699case 320:700default:701data[3] = 0x28; /* reg 2, H size/8 */702data[4] = 0x3c; /* reg 3, V size/4 */703data[6] = 0x14; /* reg 5, H start */704data[8] = 0x1a + sd->sensor_type; /* reg 7, V start */705break;706case 176:707data[9] |= 0x04; /* reg 8, 2:1 scale down from 352 */708/* fall thru */709case 352:710data[3] = 0x2c; /* reg 2, H size/8 */711data[4] = 0x48; /* reg 3, V size/4 */712data[6] = 0x06; /* reg 5, H start */713data[8] = 0x06 - sd->sensor_type; /* reg 7, V start */714break;715}716err_code = mr_write(gspca_dev, 11);717if (err_code < 0)718return err_code;719720if (!sd->sensor_type) {721static const struct sensor_w_data cif_sensor0_init_data[] = {722{0x02, 0x00, {0x03, 0x5a, 0xb5, 0x01,7230x0f, 0x14, 0x0f, 0x10}, 8},724{0x0c, 0x00, {0x04, 0x01, 0x01, 0x00, 0x1f}, 5},725{0x12, 0x00, {0x07}, 1},726{0x1f, 0x00, {0x06}, 1},727{0x27, 0x00, {0x04}, 1},728{0x29, 0x00, {0x0c}, 1},729{0x40, 0x00, {0x40, 0x00, 0x04}, 3},730{0x50, 0x00, {0x60}, 1},731{0x60, 0x00, {0x06}, 1},732{0x6b, 0x00, {0x85, 0x85, 0xc8, 0xc8, 0xc8, 0xc8}, 6},733{0x72, 0x00, {0x1e, 0x56}, 2},734{0x75, 0x00, {0x58, 0x40, 0xa2, 0x02, 0x31, 0x02,7350x31, 0x80, 0x00}, 9},736{0x11, 0x00, {0x01}, 1},737{0, 0, {0}, 0}738};739err_code = sensor_write_regs(gspca_dev, cif_sensor0_init_data,740ARRAY_SIZE(cif_sensor0_init_data));741} else { /* sd->sensor_type = 1 */742static const struct sensor_w_data cif_sensor1_init_data[] = {743/* Reg 3,4, 7,8 get set by the controls */744{0x02, 0x00, {0x10}, 1},745{0x05, 0x01, {0x22}, 1}, /* 5/6 also seen as 65h/32h */746{0x06, 0x01, {0x00}, 1},747{0x09, 0x02, {0x0e}, 1},748{0x0a, 0x02, {0x05}, 1},749{0x0b, 0x02, {0x05}, 1},750{0x0c, 0x02, {0x0f}, 1},751{0x0d, 0x02, {0x07}, 1},752{0x0e, 0x02, {0x0c}, 1},753{0x0f, 0x00, {0x00}, 1},754{0x10, 0x00, {0x06}, 1},755{0x11, 0x00, {0x07}, 1},756{0x12, 0x00, {0x00}, 1},757{0x13, 0x00, {0x01}, 1},758{0, 0, {0}, 0}759};760/* Without this command the cam won't work with USB-UHCI */761gspca_dev->usb_buf[0] = 0x0a;762gspca_dev->usb_buf[1] = 0x00;763err_code = mr_write(gspca_dev, 2);764if (err_code < 0)765return err_code;766err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data,767ARRAY_SIZE(cif_sensor1_init_data));768}769return err_code;770}771772static int start_vga_cam(struct gspca_dev *gspca_dev)773{774struct sd *sd = (struct sd *) gspca_dev;775__u8 *data = gspca_dev->usb_buf;776int err_code;777static const __u8 startup_string[] =778{0x00, 0x0d, 0x01, 0x00, 0x00, 0x2b, 0x00, 0x00,7790x00, 0x50, 0xc0};780/* What some of these mean is explained in start_cif_cam(), above */781782memcpy(data, startup_string, 11);783if (!sd->sensor_type) {784data[5] = 0x00;785data[10] = 0x91;786}787if (sd->sensor_type == 2) {788data[5] = 0x00;789data[10] = 0x18;790}791792switch (gspca_dev->width) {793case 160:794data[9] |= 0x0c; /* reg 8, 4:1 scale down */795/* fall thru */796case 320:797data[9] |= 0x04; /* reg 8, 2:1 scale down */798/* fall thru */799case 640:800default:801data[3] = 0x50; /* reg 2, H size/8 */802data[4] = 0x78; /* reg 3, V size/4 */803data[6] = 0x04; /* reg 5, H start */804data[8] = 0x03; /* reg 7, V start */805if (sd->sensor_type == 2) {806data[6] = 2;807data[8] = 1;808}809if (sd->do_lcd_stop)810data[8] = 0x04; /* Bayer tile shifted */811break;812813case 176:814data[9] |= 0x04; /* reg 8, 2:1 scale down */815/* fall thru */816case 352:817data[3] = 0x2c; /* reg 2, H size */818data[4] = 0x48; /* reg 3, V size */819data[6] = 0x94; /* reg 5, H start */820data[8] = 0x63; /* reg 7, V start */821if (sd->do_lcd_stop)822data[8] = 0x64; /* Bayer tile shifted */823break;824}825826err_code = mr_write(gspca_dev, 11);827if (err_code < 0)828return err_code;829830if (!sd->sensor_type) {831static const struct sensor_w_data vga_sensor0_init_data[] = {832{0x01, 0x00, {0x0c, 0x00, 0x04}, 3},833{0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4},834{0x20, 0x00, {0x00, 0x80, 0x00, 0x08}, 4},835{0x25, 0x00, {0x03, 0xa9, 0x80}, 3},836{0x30, 0x00, {0x30, 0x18, 0x10, 0x18}, 4},837{0, 0, {0}, 0}838};839err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data,840ARRAY_SIZE(vga_sensor0_init_data));841} else if (sd->sensor_type == 1) {842static const struct sensor_w_data color_adj[] = {843{0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,844/* adjusted blue, green, red gain correct845too much blue from the Sakar Digital */8460x05, 0x01, 0x04}, 8}847};848849static const struct sensor_w_data color_no_adj[] = {850{0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,851/* default blue, green, red gain settings */8520x07, 0x00, 0x01}, 8}853};854855static const struct sensor_w_data vga_sensor1_init_data[] = {856{0x11, 0x04, {0x01}, 1},857{0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01,858/* These settings may be better for some cameras */859/* {0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01, */8600x00, 0x0a}, 7},861{0x11, 0x04, {0x01}, 1},862{0x12, 0x00, {0x00, 0x63, 0x00, 0x70, 0x00, 0x00}, 6},863{0x11, 0x04, {0x01}, 1},864{0, 0, {0}, 0}865};866867if (sd->adj_colors)868err_code = sensor_write_regs(gspca_dev, color_adj,869ARRAY_SIZE(color_adj));870else871err_code = sensor_write_regs(gspca_dev, color_no_adj,872ARRAY_SIZE(color_no_adj));873874if (err_code < 0)875return err_code;876877err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data,878ARRAY_SIZE(vga_sensor1_init_data));879} else { /* sensor type == 2 */880static const struct sensor_w_data vga_sensor2_init_data[] = {881882{0x01, 0x00, {0x48}, 1},883{0x02, 0x00, {0x22}, 1},884/* Reg 3 msb and 4 is lsb of the exposure setting*/885{0x05, 0x00, {0x10}, 1},886{0x06, 0x00, {0x00}, 1},887{0x07, 0x00, {0x00}, 1},888{0x08, 0x00, {0x00}, 1},889{0x09, 0x00, {0x00}, 1},890/* The following are used in the gain control891* which is BTW completely borked in the OEM driver892* The values for each color go from 0 to 0x7ff893*{0x0a, 0x00, {0x01}, 1}, green1 gain msb894*{0x0b, 0x00, {0x10}, 1}, green1 gain lsb895*{0x0c, 0x00, {0x01}, 1}, red gain msb896*{0x0d, 0x00, {0x10}, 1}, red gain lsb897*{0x0e, 0x00, {0x01}, 1}, blue gain msb898*{0x0f, 0x00, {0x10}, 1}, blue gain lsb899*{0x10, 0x00, {0x01}, 1}, green2 gain msb900*{0x11, 0x00, {0x10}, 1}, green2 gain lsb901*/902{0x12, 0x00, {0x00}, 1},903{0x13, 0x00, {0x04}, 1}, /* weird effect on colors */904{0x14, 0x00, {0x00}, 1},905{0x15, 0x00, {0x06}, 1},906{0x16, 0x00, {0x01}, 1},907{0x17, 0x00, {0xe2}, 1}, /* vertical alignment */908{0x18, 0x00, {0x02}, 1},909{0x19, 0x00, {0x82}, 1}, /* don't mess with */910{0x1a, 0x00, {0x00}, 1},911{0x1b, 0x00, {0x20}, 1},912/* {0x1c, 0x00, {0x17}, 1}, contrast control */913{0x1d, 0x00, {0x80}, 1}, /* moving causes a mess */914{0x1e, 0x00, {0x08}, 1}, /* moving jams the camera */915{0x1f, 0x00, {0x0c}, 1},916{0x20, 0x00, {0x00}, 1},917{0, 0, {0}, 0}918};919err_code = sensor_write_regs(gspca_dev, vga_sensor2_init_data,920ARRAY_SIZE(vga_sensor2_init_data));921}922return err_code;923}924925static int sd_start(struct gspca_dev *gspca_dev)926{927struct sd *sd = (struct sd *) gspca_dev;928int err_code;929930sd->sof_read = 0;931932/* Some of the VGA cameras require the memory pointer933* to be set to 0 again. We have been forced to start the934* stream in sd_config() to detect the hardware, and closed it.935* Thus, we need here to do a completely fresh and clean start. */936err_code = zero_the_pointer(gspca_dev);937if (err_code < 0)938return err_code;939940err_code = stream_start(gspca_dev);941if (err_code < 0)942return err_code;943944if (sd->cam_type == CAM_TYPE_CIF) {945err_code = start_cif_cam(gspca_dev);946} else {947err_code = start_vga_cam(gspca_dev);948}949if (err_code < 0)950return err_code;951952setbrightness(gspca_dev);953setcontrast(gspca_dev);954setexposure(gspca_dev);955setgain(gspca_dev);956957return isoc_enable(gspca_dev);958}959960static void sd_stopN(struct gspca_dev *gspca_dev)961{962struct sd *sd = (struct sd *) gspca_dev;963964stream_stop(gspca_dev);965/* Not all the cams need this, but even if not, probably a good idea */966zero_the_pointer(gspca_dev);967if (sd->do_lcd_stop)968lcd_stop(gspca_dev);969}970971static void setbrightness(struct gspca_dev *gspca_dev)972{973struct sd *sd = (struct sd *) gspca_dev;974u8 val;975u8 sign_reg = 7; /* This reg and the next one used on CIF cams. */976u8 value_reg = 8; /* VGA cams seem to use regs 0x0b and 0x0c */977static const u8 quick_clix_table[] =978/* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */979{ 0, 4, 8, 12, 1, 2, 3, 5, 6, 9, 7, 10, 13, 11, 14, 15};980/*981* This control is disabled for CIF type 1 and VGA type 0 cameras.982* It does not quite act linearly for the Argus QuickClix camera,983* but it does control brightness. The values are 0 - 15 only, and984* the table above makes them act consecutively.985*/986if ((gspca_dev->ctrl_dis & (1 << NORM_BRIGHTNESS_IDX)) &&987(gspca_dev->ctrl_dis & (1 << ARGUS_QC_BRIGHTNESS_IDX)))988return;989990if (sd->cam_type == CAM_TYPE_VGA) {991sign_reg += 4;992value_reg += 4;993}994995/* Note register 7 is also seen as 0x8x or 0xCx in some dumps */996if (sd->brightness > 0) {997sensor_write1(gspca_dev, sign_reg, 0x00);998val = sd->brightness;999} else {1000sensor_write1(gspca_dev, sign_reg, 0x01);1001val = (257 - sd->brightness);1002}1003/* Use lookup table for funky Argus QuickClix brightness */1004if (sd->do_lcd_stop)1005val = quick_clix_table[val];10061007sensor_write1(gspca_dev, value_reg, val);1008}10091010static void setexposure(struct gspca_dev *gspca_dev)1011{1012struct sd *sd = (struct sd *) gspca_dev;1013int exposure = MR97310A_EXPOSURE_DEFAULT;1014u8 buf[2];10151016if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX))1017return;10181019if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) {1020/* This cam does not like exposure settings < 300,1021so scale 0 - 4095 to 300 - 4095 */1022exposure = (sd->exposure * 9267) / 10000 + 300;1023sensor_write1(gspca_dev, 3, exposure >> 4);1024sensor_write1(gspca_dev, 4, exposure & 0x0f);1025} else if (sd->sensor_type == 2) {1026exposure = sd->exposure;1027exposure >>= 3;1028sensor_write1(gspca_dev, 3, exposure >> 8);1029sensor_write1(gspca_dev, 4, exposure & 0xff);1030} else {1031/* We have both a clock divider and an exposure register.1032We first calculate the clock divider, as that determines1033the maximum exposure and then we calculate the exposure1034register setting (which goes from 0 - 511).10351036Note our 0 - 4095 exposure is mapped to 0 - 5111037milliseconds exposure time */1038u8 clockdiv = (60 * sd->exposure + 7999) / 8000;10391040/* Limit framerate to not exceed usb bandwidth */1041if (clockdiv < sd->min_clockdiv && gspca_dev->width >= 320)1042clockdiv = sd->min_clockdiv;1043else if (clockdiv < 2)1044clockdiv = 2;10451046if (sd->cam_type == CAM_TYPE_VGA && clockdiv < 4)1047clockdiv = 4;10481049/* Frame exposure time in ms = 1000 * clockdiv / 60 ->1050exposure = (sd->exposure / 8) * 511 / (1000 * clockdiv / 60) */1051exposure = (60 * 511 * sd->exposure) / (8000 * clockdiv);1052if (exposure > 511)1053exposure = 511;10541055/* exposure register value is reversed! */1056exposure = 511 - exposure;10571058buf[0] = exposure & 0xff;1059buf[1] = exposure >> 8;1060sensor_write_reg(gspca_dev, 0x0e, 0, buf, 2);1061sensor_write1(gspca_dev, 0x02, clockdiv);1062}1063}10641065static void setgain(struct gspca_dev *gspca_dev)1066{1067struct sd *sd = (struct sd *) gspca_dev;1068u8 gainreg;10691070if ((gspca_dev->ctrl_dis & (1 << GAIN_IDX)) &&1071(gspca_dev->ctrl_dis & (1 << SAKAR_CS_GAIN_IDX)))1072return;10731074if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1)1075sensor_write1(gspca_dev, 0x0e, sd->gain);1076else if (sd->cam_type == CAM_TYPE_VGA && sd->sensor_type == 2)1077for (gainreg = 0x0a; gainreg < 0x11; gainreg += 2) {1078sensor_write1(gspca_dev, gainreg, sd->gain >> 8);1079sensor_write1(gspca_dev, gainreg + 1, sd->gain & 0xff);1080}1081else1082sensor_write1(gspca_dev, 0x10, sd->gain);1083}10841085static void setcontrast(struct gspca_dev *gspca_dev)1086{1087struct sd *sd = (struct sd *) gspca_dev;10881089if (gspca_dev->ctrl_dis & (1 << CONTRAST_IDX))1090return;10911092sensor_write1(gspca_dev, 0x1c, sd->contrast);1093}109410951096static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)1097{1098struct sd *sd = (struct sd *) gspca_dev;10991100sd->brightness = val;1101if (gspca_dev->streaming)1102setbrightness(gspca_dev);1103return 0;1104}11051106static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)1107{1108struct sd *sd = (struct sd *) gspca_dev;11091110*val = sd->brightness;1111return 0;1112}11131114static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)1115{1116struct sd *sd = (struct sd *) gspca_dev;11171118sd->exposure = val;1119if (gspca_dev->streaming)1120setexposure(gspca_dev);1121return 0;1122}11231124static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)1125{1126struct sd *sd = (struct sd *) gspca_dev;11271128*val = sd->exposure;1129return 0;1130}11311132static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)1133{1134struct sd *sd = (struct sd *) gspca_dev;11351136sd->gain = val;1137if (gspca_dev->streaming)1138setgain(gspca_dev);1139return 0;1140}11411142static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)1143{1144struct sd *sd = (struct sd *) gspca_dev;11451146*val = sd->gain;1147return 0;1148}11491150static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)1151{1152struct sd *sd = (struct sd *) gspca_dev;11531154sd->contrast = val;1155if (gspca_dev->streaming)1156setcontrast(gspca_dev);1157return 0;1158}115911601161static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)1162{1163struct sd *sd = (struct sd *) gspca_dev;11641165*val = sd->contrast;1166return 0;1167}11681169static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val)1170{1171struct sd *sd = (struct sd *) gspca_dev;11721173sd->min_clockdiv = val;1174if (gspca_dev->streaming)1175setexposure(gspca_dev);1176return 0;1177}11781179static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val)1180{1181struct sd *sd = (struct sd *) gspca_dev;11821183*val = sd->min_clockdiv;1184return 0;1185}11861187/* Include pac common sof detection functions */1188#include "pac_common.h"11891190static void sd_pkt_scan(struct gspca_dev *gspca_dev,1191u8 *data, /* isoc packet */1192int len) /* iso packet length */1193{1194struct sd *sd = (struct sd *) gspca_dev;1195unsigned char *sof;11961197sof = pac_find_sof(&sd->sof_read, data, len);1198if (sof) {1199int n;12001201/* finish decoding current frame */1202n = sof - data;1203if (n > sizeof pac_sof_marker)1204n -= sizeof pac_sof_marker;1205else1206n = 0;1207gspca_frame_add(gspca_dev, LAST_PACKET,1208data, n);1209/* Start next frame. */1210gspca_frame_add(gspca_dev, FIRST_PACKET,1211pac_sof_marker, sizeof pac_sof_marker);1212len -= sof - data;1213data = sof;1214}1215gspca_frame_add(gspca_dev, INTER_PACKET, data, len);1216}12171218/* sub-driver description */1219static const struct sd_desc sd_desc = {1220.name = MODULE_NAME,1221.ctrls = sd_ctrls,1222.nctrls = ARRAY_SIZE(sd_ctrls),1223.config = sd_config,1224.init = sd_init,1225.start = sd_start,1226.stopN = sd_stopN,1227.pkt_scan = sd_pkt_scan,1228};12291230/* -- module initialisation -- */1231static const struct usb_device_id device_table[] = {1232{USB_DEVICE(0x08ca, 0x0110)}, /* Trust Spyc@m 100 */1233{USB_DEVICE(0x08ca, 0x0111)}, /* Aiptek Pencam VGA+ */1234{USB_DEVICE(0x093a, 0x010f)}, /* All other known MR97310A VGA cams */1235{USB_DEVICE(0x093a, 0x010e)}, /* All known MR97310A CIF cams */1236{}1237};1238MODULE_DEVICE_TABLE(usb, device_table);12391240/* -- device connect -- */1241static int sd_probe(struct usb_interface *intf,1242const struct usb_device_id *id)1243{1244return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),1245THIS_MODULE);1246}12471248static struct usb_driver sd_driver = {1249.name = MODULE_NAME,1250.id_table = device_table,1251.probe = sd_probe,1252.disconnect = gspca_disconnect,1253#ifdef CONFIG_PM1254.suspend = gspca_suspend,1255.resume = gspca_resume,1256#endif1257};12581259/* -- module insert / remove -- */1260static int __init sd_mod_init(void)1261{1262return usb_register(&sd_driver);1263}1264static void __exit sd_mod_exit(void)1265{1266usb_deregister(&sd_driver);1267}12681269module_init(sd_mod_init);1270module_exit(sd_mod_exit);127112721273