Path: blob/master/drivers/media/video/gspca/conex.c
17602 views
/*1* Connexant Cx11646 library2* Copyright (C) 2004 Michel Xhaard [email protected]3*4* V4L2 by Jean-Francois Moine <http://moinejf.free.fr>5*6* This program is free software; you can redistribute it and/or modify7* it under the terms of the GNU General Public License as published by8* the Free Software Foundation; either version 2 of the License, or9* any later version.10*11* This program is distributed in the hope that it will be useful,12* but WITHOUT ANY WARRANTY; without even the implied warranty of13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14* GNU General Public License for more details.15*16* You should have received a copy of the GNU General Public License17* along with this program; if not, write to the Free Software18* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA19*/2021#define MODULE_NAME "conex"2223#include "gspca.h"24#define CONEX_CAM 1 /* special JPEG header */25#include "jpeg.h"2627MODULE_AUTHOR("Michel Xhaard <[email protected]>");28MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");29MODULE_LICENSE("GPL");3031/* specific webcam descriptor */32struct sd {33struct gspca_dev gspca_dev; /* !! must be the first item */3435unsigned char brightness;36unsigned char contrast;37unsigned char colors;38u8 quality;39#define QUALITY_MIN 3040#define QUALITY_MAX 6041#define QUALITY_DEF 404243u8 jpeg_hdr[JPEG_HDR_SZ];44};4546/* V4L2 controls supported by the driver */47static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);48static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);49static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);50static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);51static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);52static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);5354static const struct ctrl sd_ctrls[] = {55{56{57.id = V4L2_CID_BRIGHTNESS,58.type = V4L2_CTRL_TYPE_INTEGER,59.name = "Brightness",60.minimum = 0,61.maximum = 255,62.step = 1,63#define BRIGHTNESS_DEF 0xd464.default_value = BRIGHTNESS_DEF,65},66.set = sd_setbrightness,67.get = sd_getbrightness,68},69{70{71.id = V4L2_CID_CONTRAST,72.type = V4L2_CTRL_TYPE_INTEGER,73.name = "Contrast",74.minimum = 0x0a,75.maximum = 0x1f,76.step = 1,77#define CONTRAST_DEF 0x0c78.default_value = CONTRAST_DEF,79},80.set = sd_setcontrast,81.get = sd_getcontrast,82},83{84{85.id = V4L2_CID_SATURATION,86.type = V4L2_CTRL_TYPE_INTEGER,87.name = "Color",88.minimum = 0,89.maximum = 7,90.step = 1,91#define COLOR_DEF 392.default_value = COLOR_DEF,93},94.set = sd_setcolors,95.get = sd_getcolors,96},97};9899static const struct v4l2_pix_format vga_mode[] = {100{176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,101.bytesperline = 176,102.sizeimage = 176 * 144 * 3 / 8 + 590,103.colorspace = V4L2_COLORSPACE_JPEG,104.priv = 3},105{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,106.bytesperline = 320,107.sizeimage = 320 * 240 * 3 / 8 + 590,108.colorspace = V4L2_COLORSPACE_JPEG,109.priv = 2},110{352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,111.bytesperline = 352,112.sizeimage = 352 * 288 * 3 / 8 + 590,113.colorspace = V4L2_COLORSPACE_JPEG,114.priv = 1},115{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,116.bytesperline = 640,117.sizeimage = 640 * 480 * 3 / 8 + 590,118.colorspace = V4L2_COLORSPACE_JPEG,119.priv = 0},120};121122/* the read bytes are found in gspca_dev->usb_buf */123static void reg_r(struct gspca_dev *gspca_dev,124__u16 index,125__u16 len)126{127struct usb_device *dev = gspca_dev->dev;128129#ifdef GSPCA_DEBUG130if (len > USB_BUF_SZ) {131err("reg_r: buffer overflow");132return;133}134#endif135usb_control_msg(dev,136usb_rcvctrlpipe(dev, 0),1370,138USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,1390,140index, gspca_dev->usb_buf, len,141500);142PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",143index, gspca_dev->usb_buf[0]);144}145146/* the bytes to write are in gspca_dev->usb_buf */147static void reg_w_val(struct gspca_dev *gspca_dev,148__u16 index,149__u8 val)150{151struct usb_device *dev = gspca_dev->dev;152153gspca_dev->usb_buf[0] = val;154usb_control_msg(dev,155usb_sndctrlpipe(dev, 0),1560,157USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,1580,159index, gspca_dev->usb_buf, 1, 500);160}161162static void reg_w(struct gspca_dev *gspca_dev,163__u16 index,164const __u8 *buffer,165__u16 len)166{167struct usb_device *dev = gspca_dev->dev;168169#ifdef GSPCA_DEBUG170if (len > USB_BUF_SZ) {171err("reg_w: buffer overflow");172return;173}174PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);175#endif176memcpy(gspca_dev->usb_buf, buffer, len);177usb_control_msg(dev,178usb_sndctrlpipe(dev, 0),1790,180USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,1810,182index, gspca_dev->usb_buf, len, 500);183}184185static const __u8 cx_sensor_init[][4] = {186{0x88, 0x11, 0x01, 0x01},187{0x88, 0x12, 0x70, 0x01},188{0x88, 0x0f, 0x00, 0x01},189{0x88, 0x05, 0x01, 0x01},190{}191};192193static const __u8 cx11646_fw1[][3] = {194{0x00, 0x02, 0x00},195{0x01, 0x43, 0x00},196{0x02, 0xA7, 0x00},197{0x03, 0x8B, 0x01},198{0x04, 0xE9, 0x02},199{0x05, 0x08, 0x04},200{0x06, 0x08, 0x05},201{0x07, 0x07, 0x06},202{0x08, 0xE7, 0x06},203{0x09, 0xC6, 0x07},204{0x0A, 0x86, 0x08},205{0x0B, 0x46, 0x09},206{0x0C, 0x05, 0x0A},207{0x0D, 0xA5, 0x0A},208{0x0E, 0x45, 0x0B},209{0x0F, 0xE5, 0x0B},210{0x10, 0x85, 0x0C},211{0x11, 0x25, 0x0D},212{0x12, 0xC4, 0x0D},213{0x13, 0x45, 0x0E},214{0x14, 0xE4, 0x0E},215{0x15, 0x64, 0x0F},216{0x16, 0xE4, 0x0F},217{0x17, 0x64, 0x10},218{0x18, 0xE4, 0x10},219{0x19, 0x64, 0x11},220{0x1A, 0xE4, 0x11},221{0x1B, 0x64, 0x12},222{0x1C, 0xE3, 0x12},223{0x1D, 0x44, 0x13},224{0x1E, 0xC3, 0x13},225{0x1F, 0x24, 0x14},226{0x20, 0xA3, 0x14},227{0x21, 0x04, 0x15},228{0x22, 0x83, 0x15},229{0x23, 0xE3, 0x15},230{0x24, 0x43, 0x16},231{0x25, 0xA4, 0x16},232{0x26, 0x23, 0x17},233{0x27, 0x83, 0x17},234{0x28, 0xE3, 0x17},235{0x29, 0x43, 0x18},236{0x2A, 0xA3, 0x18},237{0x2B, 0x03, 0x19},238{0x2C, 0x63, 0x19},239{0x2D, 0xC3, 0x19},240{0x2E, 0x22, 0x1A},241{0x2F, 0x63, 0x1A},242{0x30, 0xC3, 0x1A},243{0x31, 0x23, 0x1B},244{0x32, 0x83, 0x1B},245{0x33, 0xE2, 0x1B},246{0x34, 0x23, 0x1C},247{0x35, 0x83, 0x1C},248{0x36, 0xE2, 0x1C},249{0x37, 0x23, 0x1D},250{0x38, 0x83, 0x1D},251{0x39, 0xE2, 0x1D},252{0x3A, 0x23, 0x1E},253{0x3B, 0x82, 0x1E},254{0x3C, 0xC3, 0x1E},255{0x3D, 0x22, 0x1F},256{0x3E, 0x63, 0x1F},257{0x3F, 0xC1, 0x1F},258{}259};260static void cx11646_fw(struct gspca_dev*gspca_dev)261{262int i = 0;263264reg_w_val(gspca_dev, 0x006a, 0x02);265while (cx11646_fw1[i][1]) {266reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);267i++;268}269reg_w_val(gspca_dev, 0x006a, 0x00);270}271272static const __u8 cxsensor[] = {2730x88, 0x12, 0x70, 0x01,2740x88, 0x0d, 0x02, 0x01,2750x88, 0x0f, 0x00, 0x01,2760x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01, /* 3 */2770x88, 0x02, 0x10, 0x01,2780x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01, /* 5 */2790x88, 0x0B, 0x00, 0x01,2800x88, 0x0A, 0x0A, 0x01,2810x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01, /* 8 */2820x88, 0x05, 0x01, 0x01,2830xA1, 0x18, 0x00, 0x01,2840x00285};286287static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };288static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };289static const __u8 reg10[] = { 0xb1, 0xb1 };290static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e }; /* 640 */291static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };292/* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */293static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };294/* 320{0x04,0x0c,0x05,0x0f}; //320 */295static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 }; /* 176 */296static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };297298static void cx_sensor(struct gspca_dev*gspca_dev)299{300int i = 0;301int length;302const __u8 *ptsensor = cxsensor;303304reg_w(gspca_dev, 0x0020, reg20, 8);305reg_w(gspca_dev, 0x0028, reg28, 8);306reg_w(gspca_dev, 0x0010, reg10, 8);307reg_w_val(gspca_dev, 0x0092, 0x03);308309switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {310case 0:311reg_w(gspca_dev, 0x0071, reg71a, 4);312break;313case 1:314reg_w(gspca_dev, 0x0071, reg71b, 4);315break;316default:317/* case 2: */318reg_w(gspca_dev, 0x0071, reg71c, 4);319break;320case 3:321reg_w(gspca_dev, 0x0071, reg71d, 4);322break;323}324reg_w(gspca_dev, 0x007b, reg7b, 6);325reg_w_val(gspca_dev, 0x00f8, 0x00);326reg_w(gspca_dev, 0x0010, reg10, 8);327reg_w_val(gspca_dev, 0x0098, 0x41);328for (i = 0; i < 11; i++) {329if (i == 3 || i == 5 || i == 8)330length = 8;331else332length = 4;333reg_w(gspca_dev, 0x00e5, ptsensor, length);334if (length == 4)335reg_r(gspca_dev, 0x00e8, 1);336else337reg_r(gspca_dev, 0x00e8, length);338ptsensor += length;339}340reg_r(gspca_dev, 0x00e7, 8);341}342343static const __u8 cx_inits_176[] = {3440x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03, /* 176x144 */3450x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,3460x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,3470x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,3480xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF,3490xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,3500x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00351};352static const __u8 cx_inits_320[] = {3530x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,3540x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,3550x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,3560x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,3570xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,3580xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,3590xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00360};361static const __u8 cx_inits_352[] = {3620x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,3630x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,3640x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,3650x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00,3660xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,3670xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,3680xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00369};370static const __u8 cx_inits_640[] = {3710x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,3720x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,3730x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,3740x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,3750xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,3760xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02,3770x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00378};379380static void cx11646_initsize(struct gspca_dev *gspca_dev)381{382const __u8 *cxinit;383static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };384static const __u8 reg17[] =385{ 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };386387switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {388case 0:389cxinit = cx_inits_640;390break;391case 1:392cxinit = cx_inits_352;393break;394default:395/* case 2: */396cxinit = cx_inits_320;397break;398case 3:399cxinit = cx_inits_176;400break;401}402reg_w_val(gspca_dev, 0x009a, 0x01);403reg_w_val(gspca_dev, 0x0010, 0x10);404reg_w(gspca_dev, 0x0012, reg12, 5);405reg_w(gspca_dev, 0x0017, reg17, 8);406reg_w_val(gspca_dev, 0x00c0, 0x00);407reg_w_val(gspca_dev, 0x00c1, 0x04);408reg_w_val(gspca_dev, 0x00c2, 0x04);409410reg_w(gspca_dev, 0x0061, cxinit, 8);411cxinit += 8;412reg_w(gspca_dev, 0x00ca, cxinit, 8);413cxinit += 8;414reg_w(gspca_dev, 0x00d2, cxinit, 8);415cxinit += 8;416reg_w(gspca_dev, 0x00da, cxinit, 6);417cxinit += 8;418reg_w(gspca_dev, 0x0041, cxinit, 8);419cxinit += 8;420reg_w(gspca_dev, 0x0049, cxinit, 8);421cxinit += 8;422reg_w(gspca_dev, 0x0051, cxinit, 2);423424reg_r(gspca_dev, 0x0010, 1);425}426427static const __u8 cx_jpeg_init[][8] = {428{0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15}, /* 1 */429{0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},430{0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},431{0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26},432{0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a},433{0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73},434{0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D},435{0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0},436{0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01},437{0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12},438{0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35},439{0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31},440{0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43},441{0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A},442{0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73},443{0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95},444{0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83},445{0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05},446{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00},447{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02},448{0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},449{0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01},450{0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00},451{0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05},452{0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00},453{0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05},454{0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01},455{0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21},456{0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22},457{0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23},458{0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24},459{0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17},460{0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29},461{0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A},462{0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A},463{0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A},464{0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A},465{0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A},466{0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A},467{0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99},468{0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8},469{0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},470{0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6},471{0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5},472{0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3},473{0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1},474{0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9},475{0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04},476{0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01},477{0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04},478{0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07},479{0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14},480{0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33},481{0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16},482{0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19},483{0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36},484{0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46},485{0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56},486{0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66},487{0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76},488{0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85},489{0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94},490{0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3},491{0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2},492{0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA},493{0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9},494{0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8},495{0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7},496{0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6},497{0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F},498{0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00},499{0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22},500{0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11},501{0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00},502{0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08},503{0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00},504{0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA},505{0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02},506{0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00} /* 79 */507};508509510static const __u8 cxjpeg_640[][8] = {511{0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10}, /* 1 */512{0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},513{0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},514{0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d},515{0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38},516{0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57},517{0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F},518{0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79},519{0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01},520{0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E},521{0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28},522{0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25},523{0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33},524{0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44},525{0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57},526{0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71},527{0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63},528{0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00},529{0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},530{0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},531{0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},532{0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF},533{0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80},534{0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},535{0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},536{0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},537{0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */538};539static const __u8 cxjpeg_352[][8] = {540{0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},541{0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},542{0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},543{0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17},544{0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},545{0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},546{0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},547{0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},548{0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},549{0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},550{0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},551{0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},552{0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},553{0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},554{0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},555{0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},556{0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},557{0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00},558{0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},559{0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},560{0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},561{0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF},562{0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60},563{0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},564{0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},565{0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},566{0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}567};568static const __u8 cxjpeg_320[][8] = {569{0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},570{0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},571{0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},572{0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09},573{0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11},574{0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A},575{0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D},576{0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24},577{0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01},578{0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04},579{0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C},580{0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B},581{0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F},582{0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14},583{0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A},584{0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22},585{0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E},586{0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00},587{0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},588{0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},589{0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},590{0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF},591{0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40},592{0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},593{0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},594{0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},595{0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */596};597static const __u8 cxjpeg_176[][8] = {598{0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},599{0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},600{0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},601{0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17},602{0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},603{0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},604{0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},605{0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},606{0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},607{0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},608{0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},609{0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},610{0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},611{0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},612{0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},613{0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},614{0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},615{0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00},616{0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},617{0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},618{0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},619{0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF},620{0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0},621{0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},622{0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},623{0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},624{0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}625};626/* 640 take with the zcx30x part */627static const __u8 cxjpeg_qtable[][8] = {628{0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},629{0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},630{0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},631{0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},632{0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},633{0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},634{0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},635{0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},636{0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},637{0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},638{0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32},639{0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},640{0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},641{0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},642{0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},643{0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},644{0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},645{0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 18 */646};647648649static void cx11646_jpegInit(struct gspca_dev*gspca_dev)650{651int i;652int length;653654reg_w_val(gspca_dev, 0x00c0, 0x01);655reg_w_val(gspca_dev, 0x00c3, 0x00);656reg_w_val(gspca_dev, 0x00c0, 0x00);657reg_r(gspca_dev, 0x0001, 1);658length = 8;659for (i = 0; i < 79; i++) {660if (i == 78)661length = 6;662reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);663}664reg_r(gspca_dev, 0x0002, 1);665reg_w_val(gspca_dev, 0x0055, 0x14);666}667668static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };669static const __u8 regE5_8[] =670{ 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };671static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };672static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };673static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };674static const __u8 reg51[] = { 0x77, 0x03 };675#define reg70 0x03676677static void cx11646_jpeg(struct gspca_dev*gspca_dev)678{679int i;680int length;681__u8 Reg55;682int retry;683684reg_w_val(gspca_dev, 0x00c0, 0x01);685reg_w_val(gspca_dev, 0x00c3, 0x00);686reg_w_val(gspca_dev, 0x00c0, 0x00);687reg_r(gspca_dev, 0x0001, 1);688length = 8;689switch (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv) {690case 0:691for (i = 0; i < 27; i++) {692if (i == 26)693length = 2;694reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);695}696Reg55 = 0x28;697break;698case 1:699for (i = 0; i < 27; i++) {700if (i == 26)701length = 2;702reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);703}704Reg55 = 0x16;705break;706default:707/* case 2: */708for (i = 0; i < 27; i++) {709if (i == 26)710length = 2;711reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);712}713Reg55 = 0x14;714break;715case 3:716for (i = 0; i < 27; i++) {717if (i == 26)718length = 2;719reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);720}721Reg55 = 0x0B;722break;723}724725reg_r(gspca_dev, 0x0002, 1);726reg_w_val(gspca_dev, 0x0055, Reg55);727reg_r(gspca_dev, 0x0002, 1);728reg_w(gspca_dev, 0x0010, reg10, 2);729reg_w_val(gspca_dev, 0x0054, 0x02);730reg_w_val(gspca_dev, 0x0054, 0x01);731reg_w_val(gspca_dev, 0x0000, 0x94);732reg_w_val(gspca_dev, 0x0053, 0xc0);733reg_w_val(gspca_dev, 0x00fc, 0xe1);734reg_w_val(gspca_dev, 0x0000, 0x00);735/* wait for completion */736retry = 50;737do {738reg_r(gspca_dev, 0x0002, 1);739/* 0x07 until 0x00 */740if (gspca_dev->usb_buf[0] == 0x00)741break;742reg_w_val(gspca_dev, 0x0053, 0x00);743} while (--retry);744if (retry == 0)745PDEBUG(D_ERR, "Damned Errors sending jpeg Table");746/* send the qtable now */747reg_r(gspca_dev, 0x0001, 1); /* -> 0x18 */748length = 8;749for (i = 0; i < 18; i++) {750if (i == 17)751length = 2;752reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);753754}755reg_r(gspca_dev, 0x0002, 1); /* 0x00 */756reg_r(gspca_dev, 0x0053, 1); /* 0x00 */757reg_w_val(gspca_dev, 0x0054, 0x02);758reg_w_val(gspca_dev, 0x0054, 0x01);759reg_w_val(gspca_dev, 0x0000, 0x94);760reg_w_val(gspca_dev, 0x0053, 0xc0);761762reg_r(gspca_dev, 0x0038, 1); /* 0x40 */763reg_r(gspca_dev, 0x0038, 1); /* 0x40 */764reg_r(gspca_dev, 0x001f, 1); /* 0x38 */765reg_w(gspca_dev, 0x0012, reg12, 5);766reg_w(gspca_dev, 0x00e5, regE5_8, 8);767reg_r(gspca_dev, 0x00e8, 8);768reg_w(gspca_dev, 0x00e5, regE5a, 4);769reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */770reg_w_val(gspca_dev, 0x009a, 0x01);771reg_w(gspca_dev, 0x00e5, regE5b, 4);772reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */773reg_w(gspca_dev, 0x00e5, regE5c, 4);774reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */775776reg_w(gspca_dev, 0x0051, reg51, 2);777reg_w(gspca_dev, 0x0010, reg10, 2);778reg_w_val(gspca_dev, 0x0070, reg70);779}780781static void cx11646_init1(struct gspca_dev *gspca_dev)782{783int i = 0;784785reg_w_val(gspca_dev, 0x0010, 0x00);786reg_w_val(gspca_dev, 0x0053, 0x00);787reg_w_val(gspca_dev, 0x0052, 0x00);788reg_w_val(gspca_dev, 0x009b, 0x2f);789reg_w_val(gspca_dev, 0x009c, 0x10);790reg_r(gspca_dev, 0x0098, 1);791reg_w_val(gspca_dev, 0x0098, 0x40);792reg_r(gspca_dev, 0x0099, 1);793reg_w_val(gspca_dev, 0x0099, 0x07);794reg_w_val(gspca_dev, 0x0039, 0x40);795reg_w_val(gspca_dev, 0x003c, 0xff);796reg_w_val(gspca_dev, 0x003f, 0x1f);797reg_w_val(gspca_dev, 0x003d, 0x40);798/* reg_w_val(gspca_dev, 0x003d, 0x60); */799reg_r(gspca_dev, 0x0099, 1); /* ->0x07 */800801while (cx_sensor_init[i][0]) {802reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);803reg_r(gspca_dev, 0x00e8, 1); /* -> 0x00 */804if (i == 1) {805reg_w_val(gspca_dev, 0x00ed, 0x01);806reg_r(gspca_dev, 0x00ed, 1); /* -> 0x01 */807}808i++;809}810reg_w_val(gspca_dev, 0x00c3, 0x00);811}812813/* this function is called at probe time */814static int sd_config(struct gspca_dev *gspca_dev,815const struct usb_device_id *id)816{817struct sd *sd = (struct sd *) gspca_dev;818struct cam *cam;819820cam = &gspca_dev->cam;821cam->cam_mode = vga_mode;822cam->nmodes = ARRAY_SIZE(vga_mode);823824sd->brightness = BRIGHTNESS_DEF;825sd->contrast = CONTRAST_DEF;826sd->colors = COLOR_DEF;827sd->quality = QUALITY_DEF;828return 0;829}830831/* this function is called at probe and resume time */832static int sd_init(struct gspca_dev *gspca_dev)833{834cx11646_init1(gspca_dev);835cx11646_initsize(gspca_dev);836cx11646_fw(gspca_dev);837cx_sensor(gspca_dev);838cx11646_jpegInit(gspca_dev);839return 0;840}841842static int sd_start(struct gspca_dev *gspca_dev)843{844struct sd *sd = (struct sd *) gspca_dev;845846/* create the JPEG header */847jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,8480x22); /* JPEG 411 */849jpeg_set_qual(sd->jpeg_hdr, sd->quality);850851cx11646_initsize(gspca_dev);852cx11646_fw(gspca_dev);853cx_sensor(gspca_dev);854cx11646_jpeg(gspca_dev);855return 0;856}857858/* called on streamoff with alt 0 and on disconnect */859static void sd_stop0(struct gspca_dev *gspca_dev)860{861int retry = 50;862863if (!gspca_dev->present)864return;865reg_w_val(gspca_dev, 0x0000, 0x00);866reg_r(gspca_dev, 0x0002, 1);867reg_w_val(gspca_dev, 0x0053, 0x00);868869while (retry--) {870/* reg_r(gspca_dev, 0x0002, 1);*/871reg_r(gspca_dev, 0x0053, 1);872if (gspca_dev->usb_buf[0] == 0)873break;874}875reg_w_val(gspca_dev, 0x0000, 0x00);876reg_r(gspca_dev, 0x0002, 1);877878reg_w_val(gspca_dev, 0x0010, 0x00);879reg_r(gspca_dev, 0x0033, 1);880reg_w_val(gspca_dev, 0x00fc, 0xe0);881}882883static void sd_pkt_scan(struct gspca_dev *gspca_dev,884u8 *data, /* isoc packet */885int len) /* iso packet length */886{887struct sd *sd = (struct sd *) gspca_dev;888889if (data[0] == 0xff && data[1] == 0xd8) {890891/* start of frame */892gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);893894/* put the JPEG header in the new frame */895gspca_frame_add(gspca_dev, FIRST_PACKET,896sd->jpeg_hdr, JPEG_HDR_SZ);897data += 2;898len -= 2;899}900gspca_frame_add(gspca_dev, INTER_PACKET, data, len);901}902903static void setbrightness(struct gspca_dev *gspca_dev)904{905struct sd *sd = (struct sd *) gspca_dev;906__u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };907__u8 reg51c[2];908__u8 bright;909__u8 colors;910911bright = sd->brightness;912regE5cbx[2] = bright;913reg_w(gspca_dev, 0x00e5, regE5cbx, 8);914reg_r(gspca_dev, 0x00e8, 8);915reg_w(gspca_dev, 0x00e5, regE5c, 4);916reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */917918colors = sd->colors;919reg51c[0] = 0x77;920reg51c[1] = colors;921reg_w(gspca_dev, 0x0051, reg51c, 2);922reg_w(gspca_dev, 0x0010, reg10, 2);923reg_w_val(gspca_dev, 0x0070, reg70);924}925926static void setcontrast(struct gspca_dev *gspca_dev)927{928struct sd *sd = (struct sd *) gspca_dev;929__u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 }; /* seem MSB */930/* __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01}; * LSB */931__u8 reg51c[2];932933regE5acx[2] = sd->contrast;934reg_w(gspca_dev, 0x00e5, regE5acx, 4);935reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */936reg51c[0] = 0x77;937reg51c[1] = sd->colors;938reg_w(gspca_dev, 0x0051, reg51c, 2);939reg_w(gspca_dev, 0x0010, reg10, 2);940reg_w_val(gspca_dev, 0x0070, reg70);941}942943static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)944{945struct sd *sd = (struct sd *) gspca_dev;946947sd->brightness = val;948if (gspca_dev->streaming)949setbrightness(gspca_dev);950return 0;951}952953static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)954{955struct sd *sd = (struct sd *) gspca_dev;956957*val = sd->brightness;958return 0;959}960961static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)962{963struct sd *sd = (struct sd *) gspca_dev;964965sd->contrast = val;966if (gspca_dev->streaming)967setcontrast(gspca_dev);968return 0;969}970971static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)972{973struct sd *sd = (struct sd *) gspca_dev;974975*val = sd->contrast;976return 0;977}978979static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)980{981struct sd *sd = (struct sd *) gspca_dev;982983sd->colors = val;984if (gspca_dev->streaming) {985setbrightness(gspca_dev);986setcontrast(gspca_dev);987}988return 0;989}990991static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)992{993struct sd *sd = (struct sd *) gspca_dev;994995*val = sd->colors;996return 0;997}998999static int sd_set_jcomp(struct gspca_dev *gspca_dev,1000struct v4l2_jpegcompression *jcomp)1001{1002struct sd *sd = (struct sd *) gspca_dev;10031004if (jcomp->quality < QUALITY_MIN)1005sd->quality = QUALITY_MIN;1006else if (jcomp->quality > QUALITY_MAX)1007sd->quality = QUALITY_MAX;1008else1009sd->quality = jcomp->quality;1010if (gspca_dev->streaming)1011jpeg_set_qual(sd->jpeg_hdr, sd->quality);1012return 0;1013}10141015static int sd_get_jcomp(struct gspca_dev *gspca_dev,1016struct v4l2_jpegcompression *jcomp)1017{1018struct sd *sd = (struct sd *) gspca_dev;10191020memset(jcomp, 0, sizeof *jcomp);1021jcomp->quality = sd->quality;1022jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT1023| V4L2_JPEG_MARKER_DQT;1024return 0;1025}10261027/* sub-driver description */1028static const struct sd_desc sd_desc = {1029.name = MODULE_NAME,1030.ctrls = sd_ctrls,1031.nctrls = ARRAY_SIZE(sd_ctrls),1032.config = sd_config,1033.init = sd_init,1034.start = sd_start,1035.stop0 = sd_stop0,1036.pkt_scan = sd_pkt_scan,1037.get_jcomp = sd_get_jcomp,1038.set_jcomp = sd_set_jcomp,1039};10401041/* -- module initialisation -- */1042static const struct usb_device_id device_table[] = {1043{USB_DEVICE(0x0572, 0x0041)},1044{}1045};1046MODULE_DEVICE_TABLE(usb, device_table);10471048/* -- device connect -- */1049static int sd_probe(struct usb_interface *intf,1050const struct usb_device_id *id)1051{1052return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),1053THIS_MODULE);1054}10551056static struct usb_driver sd_driver = {1057.name = MODULE_NAME,1058.id_table = device_table,1059.probe = sd_probe,1060.disconnect = gspca_disconnect,1061#ifdef CONFIG_PM1062.suspend = gspca_suspend,1063.resume = gspca_resume,1064#endif1065};10661067/* -- module insert / remove -- */1068static int __init sd_mod_init(void)1069{1070return usb_register(&sd_driver);1071}1072static void __exit sd_mod_exit(void)1073{1074usb_deregister(&sd_driver);1075}10761077module_init(sd_mod_init);1078module_exit(sd_mod_exit);107910801081