Loading drivers/media/video/gspca/ov519.c +143 −251 Original line number Diff line number Diff line Loading @@ -40,8 +40,7 @@ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ /* Determined by sensor type */ short maxwidth; short maxheight; char sif; unsigned char primary_i2c_slave; /* I2C write id of sensor */ Loading Loading @@ -85,7 +84,6 @@ static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); static struct ctrl sd_ctrls[] = { #define SD_BRIGHTNESS 0 { { .id = V4L2_CID_BRIGHTNESS, Loading @@ -94,12 +92,12 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 255, .step = 1, .default_value = 127, #define BRIGHTNESS_DEF 127 .default_value = BRIGHTNESS_DEF, }, .set = sd_setbrightness, .get = sd_getbrightness, }, #define SD_CONTRAST 1 { { .id = V4L2_CID_CONTRAST, Loading @@ -108,21 +106,22 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 255, .step = 1, .default_value = 127, #define CONTRAST_DEF 127 .default_value = CONTRAST_DEF, }, .set = sd_setcontrast, .get = sd_getcontrast, }, #define SD_COLOR 2 { { .id = V4L2_CID_SATURATION, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Saturation", .name = "Color", .minimum = 0, .maximum = 255, .step = 1, .default_value = 127, #define COLOR_DEF 127 .default_value = COLOR_DEF, }, .set = sd_setcolors, .get = sd_getcolors, Loading Loading @@ -161,7 +160,7 @@ static struct ctrl sd_ctrls[] = { static struct v4l2_pix_format vga_mode[] = { {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 589, .sizeimage = 320 * 240 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 1}, {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, Loading @@ -173,12 +172,12 @@ static struct v4l2_pix_format vga_mode[] = { static struct v4l2_pix_format sif_mode[] = { {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 176, .sizeimage = 176 * 144 * 3 / 8 + 589, .sizeimage = 176 * 144 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 1}, {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 352, .sizeimage = 352 * 288 * 3 / 8 + 589, .sizeimage = 352 * 288 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 0}, }; Loading Loading @@ -294,16 +293,6 @@ static struct v4l2_pix_format sif_mode[] = { #define OV7670_REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ #define OV7670_REG_BD60MAX 0xab /* 60hz banding step limit */ struct ovsensor_window { short x; short y; short width; short height; /* int format; */ short quarter; /* Scale width and height down 2x */ short clockdiv; /* Clock divisor setting */ }; static unsigned char ov7670_abs_to_sm(unsigned char v) { if (v > 127) Loading Loading @@ -535,19 +524,6 @@ static int init_ov_sensor(struct sd *sd) return 0; } /* Switch on standard JPEG compression. Returns 0 for success. */ static int ov519_init_compression(struct sd *sd) { if (!sd->compress_inited) { if (reg_w_mask(sd, OV519_SYS_EN_CLK1, 1 << 2, 1 << 2) < 0) { PDEBUG(D_ERR, "Error switching to compressed mode"); return -EIO; } sd->compress_inited = 1; } return 0; } /* Set the read and write slave IDs. The "slave" argument is the write slave, * and the read slave will be set to (slave + 1). * This should not be called from outside the i2c I/O functions. Loading Loading @@ -717,21 +693,17 @@ static int ov8xx0_configure(struct sd *sd) return -1; } if ((rc & 3) == 1) { PDEBUG(D_PROBE, "Sensor is an OV8610"); sd->sensor = SEN_OV8610; } else { PDEBUG(D_ERR, "Unknown image sensor version: %d", rc & 3); return -1; } PDEBUG(D_PROBE, "Writing 8610 registers"); if (write_i2c_regvals(sd, norm_8610, sizeof norm_8610 / sizeof norm_8610[0])) if (write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610))) return -1; /* Set sensor-specific vars */ sd->maxwidth = 640; sd->maxheight = 480; /* sd->sif = 0; already done */ return 0; } Loading Loading @@ -861,7 +833,7 @@ static int ov7xx0_configure(struct sd *sd) { OV7670_REG_COM7, OV7670_COM7_RESET }, { OV7670_REG_TSLB, 0x04 }, /* OV */ { OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */ { OV7670_REG_CLKRC, 0x1 }, { OV7670_REG_CLKRC, 0x01 }, /* * Set the hardware window. These values from OV don't entirely * make sense - hstop is less than hstart. But they work... Loading @@ -875,16 +847,12 @@ static int ov7xx0_configure(struct sd *sd) { 0x70, 0x3a }, { 0x71, 0x35 }, { 0x72, 0x11 }, { 0x73, 0xf0 }, { 0xa2, 0x02 }, /* jfm */ /* { OV7670_REG_COM10, 0x0 }, */ /* Gamma curve values */ { 0x7a, 0x20 }, /* jfm:win 7b=1c */ { 0x7b, 0x10 }, /* jfm:win 7c=28 */ { 0x7c, 0x1e }, /* jfm:win 7d=3c */ { 0x7d, 0x35 }, { 0x7e, 0x5a }, { 0x7f, 0x69 }, { 0x80, 0x76 }, { 0x81, 0x80 }, Loading @@ -900,13 +868,11 @@ static int ov7xx0_configure(struct sd *sd) | OV7670_COM8_BFILT }, { OV7670_REG_GAIN, 0 }, { OV7670_REG_AECH, 0 }, { OV7670_REG_COM4, 0x40 }, /* magic reserved bit */ /* jfm:win 14=38 */ { OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */ { OV7670_REG_BD50MAX, 0x05 }, { OV7670_REG_BD60MAX, 0x07 }, { OV7670_REG_AEW, 0x95 }, { OV7670_REG_AEB, 0x33 }, { OV7670_REG_VPT, 0xe3 }, { OV7670_REG_HAECC1, 0x78 }, { OV7670_REG_HAECC2, 0x68 }, /* jfm:win a1=0b */ { 0xa1, 0x03 }, /* magic */ { OV7670_REG_HAECC3, 0xd8 }, { OV7670_REG_HAECC4, 0xd8 }, { OV7670_REG_HAECC5, 0xf0 }, { OV7670_REG_HAECC6, 0x90 }, Loading @@ -920,8 +886,6 @@ static int ov7xx0_configure(struct sd *sd) /* Almost all of these are magic "reserved" values. */ { OV7670_REG_COM5, 0x61 }, { OV7670_REG_COM6, 0x4b }, { 0x16, 0x02 }, /* jfm */ /* { OV7670_REG_MVFP, 0x07|OV7670_MVFP_MIRROR }, */ { OV7670_REG_MVFP, 0x07 }, { 0x21, 0x02 }, { 0x22, 0x91 }, { 0x29, 0x07 }, { 0x33, 0x0b }, Loading Loading @@ -995,17 +959,10 @@ static int ov7xx0_configure(struct sd *sd) { 0x79, 0x03 }, { 0xc8, 0x40 }, { 0x79, 0x05 }, { 0xc8, 0x30 }, { 0x79, 0x26 }, }; PDEBUG(D_PROBE, "starting OV7xx0 configuration"); /* jfm:already done? */ if (init_ov_sensor(sd) < 0) PDEBUG(D_ERR, "Failed to read sensor ID"); else PDEBUG(D_PROBE, "OV7xx0 initialized"); /* Detect sensor (sub)type */ rc = i2c_r(sd, OV7610_REG_COM_I); Loading Loading @@ -1051,20 +1008,25 @@ static int ov7xx0_configure(struct sd *sd) return low; } if (high == 0x76) { if (low == 0x30) { switch (low) { case 0x30: PDEBUG(D_PROBE, "Sensor is an OV7630/OV7635"); sd->sensor = SEN_OV7630; } else if (low == 0x40) { break; case 0x40: PDEBUG(D_PROBE, "Sensor is an OV7645"); sd->sensor = SEN_OV7640; /* FIXME */ } else if (low == 0x45) { break; case 0x45: PDEBUG(D_PROBE, "Sensor is an OV7645B"); sd->sensor = SEN_OV7640; /* FIXME */ } else if (low == 0x48) { break; case 0x48: PDEBUG(D_PROBE, "Sensor is an OV7648"); sd->sensor = SEN_OV7640; /* FIXME */ } else { PDEBUG(D_PROBE, "Unknown sensor: 0x76%X", low); break; default: PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low); return -1; } } else { Loading @@ -1076,34 +1038,34 @@ static int ov7xx0_configure(struct sd *sd) return -1; } if (sd->sensor == SEN_OV7620) { switch (sd->sensor) { case SEN_OV7620: PDEBUG(D_PROBE, "Writing 7620 registers"); if (write_i2c_regvals(sd, norm_7620, sizeof norm_7620 / sizeof norm_7620[0])) if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620))) return -1; } else if (sd->sensor == SEN_OV7630) { break; case SEN_OV7630: PDEBUG(D_ERR, "7630 is not supported by this driver version"); return -1; } else if (sd->sensor == SEN_OV7640) { case SEN_OV7640: PDEBUG(D_PROBE, "Writing 7640 registers"); if (write_i2c_regvals(sd, norm_7640, sizeof norm_7640 / sizeof norm_7640[0])) if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640))) return -1; } else if (sd->sensor == SEN_OV7670) { break; case SEN_OV7670: PDEBUG(D_PROBE, "Writing 7670 registers"); if (write_i2c_regvals(sd, norm_7670, sizeof norm_7670 / sizeof norm_7670[0])) if (write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670))) return -1; } else { break; default: PDEBUG(D_PROBE, "Writing 7610 registers"); if (write_i2c_regvals(sd, norm_7610, sizeof norm_7610 / sizeof norm_7610[0])) if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610))) return -1; break; } /* Set sensor-specific vars */ sd->maxwidth = 640; sd->maxheight = 480; /* sd->sif = 0; already done */ return 0; } Loading Loading @@ -1257,43 +1219,45 @@ static int ov6xx0_configure(struct sd *sd) /* Ugh. The first two bits are the version bits, but * the entire register value must be used. I guess OVT * underestimated how many variants they would make. */ if (rc == 0x00) { switch (rc) { case 0x00: sd->sensor = SEN_OV6630; PDEBUG(D_ERR, "WARNING: Sensor is an OV66308. Your camera may have"); PDEBUG(D_ERR, "been misdetected in previous driver versions."); } else if (rc == 0x01) { break; case 0x01: sd->sensor = SEN_OV6620; PDEBUG(D_PROBE, "Sensor is an OV6620"); } else if (rc == 0x02) { break; case 0x02: sd->sensor = SEN_OV6630; PDEBUG(D_PROBE, "Sensor is an OV66308AE"); } else if (rc == 0x03) { break; case 0x03: sd->sensor = SEN_OV6630; PDEBUG(D_PROBE, "Sensor is an OV66308AF"); } else if (rc == 0x90) { break; case 0x90: sd->sensor = SEN_OV6630; PDEBUG(D_ERR, "WARNING: Sensor is an OV66307. Your camera may have"); PDEBUG(D_ERR, "been misdetected in previous driver versions."); } else { break; default: PDEBUG(D_ERR, "FATAL: Unknown sensor version: 0x%02x", rc); return -1; } /* Set sensor-specific vars */ sd->maxwidth = 352; sd->maxheight = 288; sd->sif = 1; if (sd->sensor == SEN_OV6620) { PDEBUG(D_PROBE, "Writing 6x20 registers"); if (write_i2c_regvals(sd, norm_6x20, sizeof norm_6x20 / sizeof norm_6x20[0])) if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20))) return -1; } else { PDEBUG(D_PROBE, "Writing 6x30 registers"); if (write_i2c_regvals(sd, norm_6x30, sizeof norm_6x30 / sizeof norm_6x30[0])) if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30))) return -1; } return 0; Loading @@ -1302,14 +1266,8 @@ static int ov6xx0_configure(struct sd *sd) /* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */ static void ov51x_led_control(struct sd *sd, int on) { PDEBUG(D_STREAM, "LED (%s)", on ? "on" : "off"); /* if (sd->bridge == BRG_OV511PLUS) */ /* reg_w(sd, R511_SYS_LED_CTL, on ? 1 : 0); */ /* else if (sd->bridge == BRG_OV519) */ /* PDEBUG(D_STREAM, "LED (%s)", on ? "on" : "off"); */ reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */ /* else if (sd->bclass == BCL_OV518) */ /* reg_w_mask(sd, R518_GPIO_OUT, on ? 0x02 : 0x00, 0x02); */ } /* this function is called at probe time */ Loading @@ -1319,11 +1277,8 @@ static int sd_config(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; /* (from ov519_configure) */ static const struct ov_regvals init_519[] = { { 0x5a, 0x6d }, /* EnableSystem */ /* jfm trace usbsnoop3-1.txt */ /* jfm 53 = fb */ { 0x53, 0x9b }, { 0x54, 0xff }, /* set bit2 to enable jpeg */ { 0x5d, 0x03 }, Loading @@ -1340,9 +1295,6 @@ static int sd_config(struct gspca_dev *gspca_dev, if (write_regvals(sd, init_519, ARRAY_SIZE(init_519))) goto error; /* jfm: not seen in windows trace */ if (ov519_init_compression(sd)) goto error; ov51x_led_control(sd, 0); /* turn LED off */ /* Test for 76xx */ Loading Loading @@ -1391,16 +1343,16 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; cam->epaddr = OV511_ENDPOINT_ADDRESS; if (sd->maxwidth == 640) { if (!sd->sif) { cam->cam_mode = vga_mode; cam->nmodes = sizeof vga_mode / sizeof vga_mode[0]; cam->nmodes = ARRAY_SIZE(vga_mode); } else { cam->cam_mode = sif_mode; cam->nmodes = sizeof sif_mode / sizeof sif_mode[0]; cam->nmodes = ARRAY_SIZE(sif_mode); } 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->hflip = HFLIP_DEF; sd->vflip = VFLIP_DEF; return 0; Loading @@ -1422,8 +1374,7 @@ static int sd_open(struct gspca_dev *gspca_dev) * * Do not put any sensor-specific code in here (including I2C I/O functions) */ static int ov519_mode_init_regs(struct sd *sd, int width, int height) static int ov519_mode_init_regs(struct sd *sd) { static const struct ov_regvals mode_init_519_ov7670[] = { { 0x5d, 0x03 }, /* Turn off suspend mode */ Loading Loading @@ -1469,36 +1420,23 @@ static int ov519_mode_init_regs(struct sd *sd, /* windows reads 0x55 at this point, why? */ }; /* int hi_res; */ PDEBUG(D_CONF, "mode init %dx%d", width, height); /* if (width >= 800 && height >= 600) hi_res = 1; else hi_res = 0; */ /* if (ov51x_stop(sd) < 0) return -EIO; */ /******** Set the mode ********/ if (sd->sensor != SEN_OV7670) { if (write_regvals(sd, mode_init_519, ARRAY_SIZE(mode_init_519))) return -EIO; if (sd->sensor == SEN_OV7640) { /* Select 8-bit input mode */ reg_w_mask(sd, OV519_CAM_DFR, 0x10, 0x10); } } else { if (write_regvals(sd, mode_init_519_ov7670, ARRAY_SIZE(mode_init_519_ov7670))) return -EIO; } if (sd->sensor == SEN_OV7640) { /* Select 8-bit input mode */ reg_w_mask(sd, OV519_CAM_DFR, 0x10, 0x10); } reg_w(sd, OV519_CAM_H_SIZE, width >> 4); reg_w(sd, OV519_CAM_V_SIZE, height >> 3); reg_w(sd, OV519_CAM_H_SIZE, sd->gspca_dev.width >> 4); reg_w(sd, OV519_CAM_V_SIZE, sd->gspca_dev.height >> 3); reg_w(sd, OV519_CAM_X_OFFSETL, 0x00); reg_w(sd, OV519_CAM_X_OFFSETH, 0x00); reg_w(sd, OV519_CAM_Y_OFFSETL, 0x00); Loading @@ -1513,9 +1451,10 @@ static int ov519_mode_init_regs(struct sd *sd, /* FIXME: These are only valid at the max resolution. */ sd->clockdiv = 0; if (sd->sensor == SEN_OV7640) { switch (sd->sensor) { case SEN_OV7640: switch (sd->frame_rate) { /*jfm: default was 30 fps */ /*fixme: default was 30 fps */ case 30: reg_w(sd, 0xa4, 0x0c); reg_w(sd, 0x23, 0xff); Loading Loading @@ -1545,7 +1484,8 @@ static int ov519_mode_init_regs(struct sd *sd, sd->clockdiv = 1; break; } } else if (sd->sensor == SEN_OV8610) { break; case SEN_OV8610: switch (sd->frame_rate) { default: /* 15 fps */ /* case 15: */ Loading @@ -1561,41 +1501,37 @@ static int ov519_mode_init_regs(struct sd *sd, reg_w(sd, 0x23, 0x1b); break; } sd->clockdiv = 0; } else if (sd->sensor == SEN_OV7670) { /* guesses, based on 7640 */ break; case SEN_OV7670: /* guesses, based on 7640 */ PDEBUG(D_STREAM, "Setting framerate to %d fps", (sd->frame_rate == 0) ? 15 : sd->frame_rate); reg_w(sd, 0xa4, 0x10); switch (sd->frame_rate) { case 30: reg_w(sd, 0xa4, 0x10); reg_w(sd, 0x23, 0xff); break; case 20: reg_w(sd, 0xa4, 0x10); reg_w(sd, 0x23, 0x1b); break; default: /* 15 fps */ default: /* case 15: */ reg_w(sd, 0xa4, 0x10); reg_w(sd, 0x23, 0xff); sd->clockdiv = 1; break; } break; } /* if (ov51x_restart(sd) < 0) return -EIO; */ /* Reset it just for good measure */ /* if (ov51x_reset(sd, OV511_RESET_NOREGS) < 0) return -EIO; */ return 0; } static int mode_init_ov_sensor_regs(struct sd *sd, struct ovsensor_window *win) static int mode_init_ov_sensor_regs(struct sd *sd) { int qvga = win->quarter; struct gspca_dev *gspca_dev; int qvga; gspca_dev = &sd->gspca_dev; qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; /******** Mode (VGA/QVGA) and sensor specific regs ********/ switch (sd->sensor) { Loading Loading @@ -1639,8 +1575,6 @@ static int mode_init_ov_sensor_regs(struct sd *sd, OV7670_COM7_FMT_MASK); break; case SEN_OV6620: i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); break; case SEN_OV6630: i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); break; Loading @@ -1649,8 +1583,6 @@ static int mode_init_ov_sensor_regs(struct sd *sd, } /******** Palette-specific regs ********/ /* Need to do work here for the OV7670 */ if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) { /* not valid on the OV6620/OV7620/6630? */ i2c_w_mask(sd, 0x0e, 0x00, 0x40); Loading @@ -1666,7 +1598,6 @@ static int mode_init_ov_sensor_regs(struct sd *sd, if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV7640) i2c_w_mask(sd, 0x13, 0x00, 0x20); /* } */ /******** Clock programming ********/ /* The OV6620 needs special handling. This prevents the Loading @@ -1675,14 +1606,14 @@ static int mode_init_ov_sensor_regs(struct sd *sd, /* Clock down */ i2c_w(sd, 0x2a, 0x04); i2c_w(sd, 0x11, win->clockdiv); i2c_w(sd, 0x11, sd->clockdiv); i2c_w(sd, 0x2a, 0x84); /* This next setting is critical. It seems to improve * the gain or the contrast. The "reserved" bits seem * to have some effect in this case. */ i2c_w(sd, 0x2d, 0x85); } else if (win->clockdiv >= 0) { i2c_w(sd, 0x11, win->clockdiv); } else if (sd->clockdiv >= 0) { i2c_w(sd, 0x11, sd->clockdiv); } /******** Special Features ********/ Loading @@ -1702,7 +1633,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd, /* is fully tested. */ /* 7620/6620/6630? don't have register 0x35, so play it safe */ if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) { if (win->width == 640 /*&& win->height == 480*/) if (!qvga) i2c_w(sd, 0x35, 0x9e); else i2c_w(sd, 0x35, 0x1e); Loading @@ -1710,33 +1641,31 @@ static int mode_init_ov_sensor_regs(struct sd *sd, return 0; } static void sethflip(struct sd *sd) { if (sd->gspca_dev.streaming) ov51x_stop(sd); i2c_w_mask(sd, OV7670_REG_MVFP, OV7670_MVFP_MIRROR * sd->hflip, OV7670_MVFP_MIRROR); if (sd->gspca_dev.streaming) ov51x_restart(sd); } static void setvflip(struct sd *sd) static void sethvflip(struct sd *sd) { if (sd->sensor != SEN_OV7670) return; if (sd->gspca_dev.streaming) ov51x_stop(sd); i2c_w_mask(sd, OV7670_REG_MVFP, OV7670_MVFP_VFLIP * sd->vflip, OV7670_MVFP_VFLIP); OV7670_MVFP_MIRROR * sd->hflip | OV7670_MVFP_VFLIP * sd->vflip, OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP); if (sd->gspca_dev.streaming) ov51x_restart(sd); } static int set_ov_sensor_window(struct sd *sd, struct ovsensor_window *win) static int set_ov_sensor_window(struct sd *sd) { struct gspca_dev *gspca_dev; int qvga; int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; int ret, hstart, hstop, vstop, vstart; __u8 v; gspca_dev = &sd->gspca_dev; qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; /* The different sensor ICs handle setting up of window differently. * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */ switch (sd->sensor) { Loading Loading @@ -1781,7 +1710,7 @@ static int set_ov_sensor_window(struct sd *sd, switch (sd->sensor) { case SEN_OV6620: case SEN_OV6630: if (win->quarter) { /* QCIF */ if (qvga) { /* QCIF */ hwscale = 0; vwscale = 0; } else { /* CIF */ Loading @@ -1791,7 +1720,7 @@ static int set_ov_sensor_window(struct sd *sd, } break; case SEN_OV8610: if (win->quarter) { /* QSVGA */ if (qvga) { /* QSVGA */ hwscale = 1; vwscale = 1; } else { /* SVGA */ Loading @@ -1800,7 +1729,7 @@ static int set_ov_sensor_window(struct sd *sd, } break; default: /* SEN_OV7xx0 */ if (win->quarter) { /* QVGA */ if (qvga) { /* QVGA */ hwscale = 1; vwscale = 0; } else { /* VGA */ Loading @@ -1809,7 +1738,7 @@ static int set_ov_sensor_window(struct sd *sd, } } ret = mode_init_ov_sensor_regs(sd, win); ret = mode_init_ov_sensor_regs(sd); if (ret < 0) return ret; Loading @@ -1830,7 +1759,7 @@ static int set_ov_sensor_window(struct sd *sd, /* I can hard code this for OV7670s */ /* Yes, these numbers do look odd, but they're tested and work! */ if (sd->sensor == SEN_OV7670) { if (win->quarter) { /* QVGA from ov7670.c by if (qvga) { /* QVGA from ov7670.c by * Jonathan Corbet */ hstart = 164; hstop = 20; Loading @@ -1844,76 +1773,45 @@ static int set_ov_sensor_window(struct sd *sd, } /* OV7670 hardware window registers are split across * multiple locations */ i2c_w(sd, OV7670_REG_HSTART, (hstart >> 3) & 0xff); i2c_w(sd, OV7670_REG_HSTOP, (hstop >> 3) & 0xff); i2c_w(sd, OV7670_REG_HSTART, hstart >> 3); i2c_w(sd, OV7670_REG_HSTOP, hstop >> 3); v = i2c_r(sd, OV7670_REG_HREF); v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x07); msleep(10); /* need to sleep between read and write to * same reg! */ i2c_w(sd, OV7670_REG_HREF, v); i2c_w(sd, OV7670_REG_VSTART, (vstart >> 2) & 0xff); i2c_w(sd, OV7670_REG_VSTOP, (vstop >> 2) & 0xff); i2c_w(sd, OV7670_REG_VSTART, vstart >> 2); i2c_w(sd, OV7670_REG_VSTOP, vstop >> 2); v = i2c_r(sd, OV7670_REG_VREF); v = (v & 0xc0) | ((vstop & 0x3) << 2) | (vstart & 0x03); msleep(10); /* need to sleep between read and write to * same reg! */ i2c_w(sd, OV7670_REG_VREF, v); sethflip(sd); setvflip(sd); sethvflip(sd); } else { i2c_w(sd, 0x17, hwsbase + (win->x >> hwscale)); i2c_w(sd, 0x18, hwebase + ((win->x + win->width) >> hwscale)); i2c_w(sd, 0x19, vwsbase + (win->y >> vwscale)); i2c_w(sd, 0x1a, vwebase + ((win->y + win->height) >> vwscale)); i2c_w(sd, 0x17, hwsbase); i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale)); i2c_w(sd, 0x19, vwsbase); i2c_w(sd, 0x1a, vwebase + (sd->gspca_dev.height >> vwscale)); } return 0; } static int ov_sensor_mode_setup(struct sd *sd, int width, int height) { struct ovsensor_window win; /* win.format = mode; */ /* Unless subcapture is enabled, * center the image window and downsample * if possible to increase the field of view */ /* NOTE: OV518(+) and OV519 does downsampling on its own */ win.width = width; win.height = height; if (width == sd->maxwidth) win.quarter = 0; else win.quarter = 1; /* Center it */ win.x = (win.width - width) / 2; win.y = (win.height - height) / 2; /* Clock is determined by OV519 frame rate code */ win.clockdiv = sd->clockdiv; PDEBUG(D_CONF, "Setting clock divider to %d", win.clockdiv); return set_ov_sensor_window(sd, &win); } /* -- start the camera -- */ static void sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int ret; ret = ov519_mode_init_regs(sd, gspca_dev->width, gspca_dev->height); ret = ov519_mode_init_regs(sd); if (ret < 0) goto out; ret = ov_sensor_mode_setup(sd, gspca_dev->width, gspca_dev->height); ret = set_ov_sensor_window(sd); if (ret < 0) goto out; ret = ov51x_restart((struct sd *) gspca_dev); ret = ov51x_restart(sd); if (ret < 0) goto out; PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt); Loading Loading @@ -1987,12 +1885,10 @@ static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int val; /* int was_streaming; */ val = sd->brightness; PDEBUG(D_CONF, "brightness:%d", val); /* was_streaming = gspca_dev->streaming; * if (was_streaming) /* if (gspca_dev->streaming) * ov51x_stop(sd); */ switch (sd->sensor) { case SEN_OV8610: Loading @@ -2010,12 +1906,12 @@ static void setbrightness(struct gspca_dev *gspca_dev) i2c_w(sd, OV7610_REG_BRT, val); break; case SEN_OV7670: /*jfm - from windblows /*win trace * i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_AEC); */ i2c_w(sd, OV7670_REG_BRIGHT, ov7670_abs_to_sm(val)); break; } /* if (was_streaming) /* if (gspca_dev->streaming) * ov51x_restart(sd); */ } Loading @@ -2023,12 +1919,10 @@ static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int val; /* int was_streaming; */ val = sd->contrast; PDEBUG(D_CONF, "contrast:%d", val); /* was_streaming = gspca_dev->streaming; if (was_streaming) /* if (gspca_dev->streaming) ov51x_stop(sd); */ switch (sd->sensor) { case SEN_OV7610: Loading Loading @@ -2065,7 +1959,7 @@ static void setcontrast(struct gspca_dev *gspca_dev) i2c_w(sd, OV7670_REG_CONTRAS, val >> 1); break; } /* if (was_streaming) /* if (gspca_dev->streaming) ov51x_restart(sd); */ } Loading @@ -2073,12 +1967,10 @@ static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int val; /* int was_streaming; */ val = sd->colors; PDEBUG(D_CONF, "saturation:%d", val); /* was_streaming = gspca_dev->streaming; if (was_streaming) /* if (gspca_dev->streaming) ov51x_stop(sd); */ switch (sd->sensor) { case SEN_OV8610: Loading @@ -2104,7 +1996,7 @@ static void setcolors(struct gspca_dev *gspca_dev) /* set REG_COM13 values for UV sat auto mode */ break; } /* if (was_streaming) /* if (gspca_dev->streaming) ov51x_restart(sd); */ } Loading Loading @@ -2164,7 +2056,7 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) struct sd *sd = (struct sd *) gspca_dev; sd->hflip = val; sethflip(sd); sethvflip(sd); return 0; } Loading @@ -2181,7 +2073,7 @@ static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) struct sd *sd = (struct sd *) gspca_dev; sd->vflip = val; setvflip(sd); sethvflip(sd); return 0; } Loading Loading
drivers/media/video/gspca/ov519.c +143 −251 Original line number Diff line number Diff line Loading @@ -40,8 +40,7 @@ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ /* Determined by sensor type */ short maxwidth; short maxheight; char sif; unsigned char primary_i2c_slave; /* I2C write id of sensor */ Loading Loading @@ -85,7 +84,6 @@ static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); static struct ctrl sd_ctrls[] = { #define SD_BRIGHTNESS 0 { { .id = V4L2_CID_BRIGHTNESS, Loading @@ -94,12 +92,12 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 255, .step = 1, .default_value = 127, #define BRIGHTNESS_DEF 127 .default_value = BRIGHTNESS_DEF, }, .set = sd_setbrightness, .get = sd_getbrightness, }, #define SD_CONTRAST 1 { { .id = V4L2_CID_CONTRAST, Loading @@ -108,21 +106,22 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 255, .step = 1, .default_value = 127, #define CONTRAST_DEF 127 .default_value = CONTRAST_DEF, }, .set = sd_setcontrast, .get = sd_getcontrast, }, #define SD_COLOR 2 { { .id = V4L2_CID_SATURATION, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Saturation", .name = "Color", .minimum = 0, .maximum = 255, .step = 1, .default_value = 127, #define COLOR_DEF 127 .default_value = COLOR_DEF, }, .set = sd_setcolors, .get = sd_getcolors, Loading Loading @@ -161,7 +160,7 @@ static struct ctrl sd_ctrls[] = { static struct v4l2_pix_format vga_mode[] = { {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 589, .sizeimage = 320 * 240 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 1}, {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, Loading @@ -173,12 +172,12 @@ static struct v4l2_pix_format vga_mode[] = { static struct v4l2_pix_format sif_mode[] = { {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 176, .sizeimage = 176 * 144 * 3 / 8 + 589, .sizeimage = 176 * 144 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 1}, {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 352, .sizeimage = 352 * 288 * 3 / 8 + 589, .sizeimage = 352 * 288 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 0}, }; Loading Loading @@ -294,16 +293,6 @@ static struct v4l2_pix_format sif_mode[] = { #define OV7670_REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ #define OV7670_REG_BD60MAX 0xab /* 60hz banding step limit */ struct ovsensor_window { short x; short y; short width; short height; /* int format; */ short quarter; /* Scale width and height down 2x */ short clockdiv; /* Clock divisor setting */ }; static unsigned char ov7670_abs_to_sm(unsigned char v) { if (v > 127) Loading Loading @@ -535,19 +524,6 @@ static int init_ov_sensor(struct sd *sd) return 0; } /* Switch on standard JPEG compression. Returns 0 for success. */ static int ov519_init_compression(struct sd *sd) { if (!sd->compress_inited) { if (reg_w_mask(sd, OV519_SYS_EN_CLK1, 1 << 2, 1 << 2) < 0) { PDEBUG(D_ERR, "Error switching to compressed mode"); return -EIO; } sd->compress_inited = 1; } return 0; } /* Set the read and write slave IDs. The "slave" argument is the write slave, * and the read slave will be set to (slave + 1). * This should not be called from outside the i2c I/O functions. Loading Loading @@ -717,21 +693,17 @@ static int ov8xx0_configure(struct sd *sd) return -1; } if ((rc & 3) == 1) { PDEBUG(D_PROBE, "Sensor is an OV8610"); sd->sensor = SEN_OV8610; } else { PDEBUG(D_ERR, "Unknown image sensor version: %d", rc & 3); return -1; } PDEBUG(D_PROBE, "Writing 8610 registers"); if (write_i2c_regvals(sd, norm_8610, sizeof norm_8610 / sizeof norm_8610[0])) if (write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610))) return -1; /* Set sensor-specific vars */ sd->maxwidth = 640; sd->maxheight = 480; /* sd->sif = 0; already done */ return 0; } Loading Loading @@ -861,7 +833,7 @@ static int ov7xx0_configure(struct sd *sd) { OV7670_REG_COM7, OV7670_COM7_RESET }, { OV7670_REG_TSLB, 0x04 }, /* OV */ { OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */ { OV7670_REG_CLKRC, 0x1 }, { OV7670_REG_CLKRC, 0x01 }, /* * Set the hardware window. These values from OV don't entirely * make sense - hstop is less than hstart. But they work... Loading @@ -875,16 +847,12 @@ static int ov7xx0_configure(struct sd *sd) { 0x70, 0x3a }, { 0x71, 0x35 }, { 0x72, 0x11 }, { 0x73, 0xf0 }, { 0xa2, 0x02 }, /* jfm */ /* { OV7670_REG_COM10, 0x0 }, */ /* Gamma curve values */ { 0x7a, 0x20 }, /* jfm:win 7b=1c */ { 0x7b, 0x10 }, /* jfm:win 7c=28 */ { 0x7c, 0x1e }, /* jfm:win 7d=3c */ { 0x7d, 0x35 }, { 0x7e, 0x5a }, { 0x7f, 0x69 }, { 0x80, 0x76 }, { 0x81, 0x80 }, Loading @@ -900,13 +868,11 @@ static int ov7xx0_configure(struct sd *sd) | OV7670_COM8_BFILT }, { OV7670_REG_GAIN, 0 }, { OV7670_REG_AECH, 0 }, { OV7670_REG_COM4, 0x40 }, /* magic reserved bit */ /* jfm:win 14=38 */ { OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */ { OV7670_REG_BD50MAX, 0x05 }, { OV7670_REG_BD60MAX, 0x07 }, { OV7670_REG_AEW, 0x95 }, { OV7670_REG_AEB, 0x33 }, { OV7670_REG_VPT, 0xe3 }, { OV7670_REG_HAECC1, 0x78 }, { OV7670_REG_HAECC2, 0x68 }, /* jfm:win a1=0b */ { 0xa1, 0x03 }, /* magic */ { OV7670_REG_HAECC3, 0xd8 }, { OV7670_REG_HAECC4, 0xd8 }, { OV7670_REG_HAECC5, 0xf0 }, { OV7670_REG_HAECC6, 0x90 }, Loading @@ -920,8 +886,6 @@ static int ov7xx0_configure(struct sd *sd) /* Almost all of these are magic "reserved" values. */ { OV7670_REG_COM5, 0x61 }, { OV7670_REG_COM6, 0x4b }, { 0x16, 0x02 }, /* jfm */ /* { OV7670_REG_MVFP, 0x07|OV7670_MVFP_MIRROR }, */ { OV7670_REG_MVFP, 0x07 }, { 0x21, 0x02 }, { 0x22, 0x91 }, { 0x29, 0x07 }, { 0x33, 0x0b }, Loading Loading @@ -995,17 +959,10 @@ static int ov7xx0_configure(struct sd *sd) { 0x79, 0x03 }, { 0xc8, 0x40 }, { 0x79, 0x05 }, { 0xc8, 0x30 }, { 0x79, 0x26 }, }; PDEBUG(D_PROBE, "starting OV7xx0 configuration"); /* jfm:already done? */ if (init_ov_sensor(sd) < 0) PDEBUG(D_ERR, "Failed to read sensor ID"); else PDEBUG(D_PROBE, "OV7xx0 initialized"); /* Detect sensor (sub)type */ rc = i2c_r(sd, OV7610_REG_COM_I); Loading Loading @@ -1051,20 +1008,25 @@ static int ov7xx0_configure(struct sd *sd) return low; } if (high == 0x76) { if (low == 0x30) { switch (low) { case 0x30: PDEBUG(D_PROBE, "Sensor is an OV7630/OV7635"); sd->sensor = SEN_OV7630; } else if (low == 0x40) { break; case 0x40: PDEBUG(D_PROBE, "Sensor is an OV7645"); sd->sensor = SEN_OV7640; /* FIXME */ } else if (low == 0x45) { break; case 0x45: PDEBUG(D_PROBE, "Sensor is an OV7645B"); sd->sensor = SEN_OV7640; /* FIXME */ } else if (low == 0x48) { break; case 0x48: PDEBUG(D_PROBE, "Sensor is an OV7648"); sd->sensor = SEN_OV7640; /* FIXME */ } else { PDEBUG(D_PROBE, "Unknown sensor: 0x76%X", low); break; default: PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low); return -1; } } else { Loading @@ -1076,34 +1038,34 @@ static int ov7xx0_configure(struct sd *sd) return -1; } if (sd->sensor == SEN_OV7620) { switch (sd->sensor) { case SEN_OV7620: PDEBUG(D_PROBE, "Writing 7620 registers"); if (write_i2c_regvals(sd, norm_7620, sizeof norm_7620 / sizeof norm_7620[0])) if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620))) return -1; } else if (sd->sensor == SEN_OV7630) { break; case SEN_OV7630: PDEBUG(D_ERR, "7630 is not supported by this driver version"); return -1; } else if (sd->sensor == SEN_OV7640) { case SEN_OV7640: PDEBUG(D_PROBE, "Writing 7640 registers"); if (write_i2c_regvals(sd, norm_7640, sizeof norm_7640 / sizeof norm_7640[0])) if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640))) return -1; } else if (sd->sensor == SEN_OV7670) { break; case SEN_OV7670: PDEBUG(D_PROBE, "Writing 7670 registers"); if (write_i2c_regvals(sd, norm_7670, sizeof norm_7670 / sizeof norm_7670[0])) if (write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670))) return -1; } else { break; default: PDEBUG(D_PROBE, "Writing 7610 registers"); if (write_i2c_regvals(sd, norm_7610, sizeof norm_7610 / sizeof norm_7610[0])) if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610))) return -1; break; } /* Set sensor-specific vars */ sd->maxwidth = 640; sd->maxheight = 480; /* sd->sif = 0; already done */ return 0; } Loading Loading @@ -1257,43 +1219,45 @@ static int ov6xx0_configure(struct sd *sd) /* Ugh. The first two bits are the version bits, but * the entire register value must be used. I guess OVT * underestimated how many variants they would make. */ if (rc == 0x00) { switch (rc) { case 0x00: sd->sensor = SEN_OV6630; PDEBUG(D_ERR, "WARNING: Sensor is an OV66308. Your camera may have"); PDEBUG(D_ERR, "been misdetected in previous driver versions."); } else if (rc == 0x01) { break; case 0x01: sd->sensor = SEN_OV6620; PDEBUG(D_PROBE, "Sensor is an OV6620"); } else if (rc == 0x02) { break; case 0x02: sd->sensor = SEN_OV6630; PDEBUG(D_PROBE, "Sensor is an OV66308AE"); } else if (rc == 0x03) { break; case 0x03: sd->sensor = SEN_OV6630; PDEBUG(D_PROBE, "Sensor is an OV66308AF"); } else if (rc == 0x90) { break; case 0x90: sd->sensor = SEN_OV6630; PDEBUG(D_ERR, "WARNING: Sensor is an OV66307. Your camera may have"); PDEBUG(D_ERR, "been misdetected in previous driver versions."); } else { break; default: PDEBUG(D_ERR, "FATAL: Unknown sensor version: 0x%02x", rc); return -1; } /* Set sensor-specific vars */ sd->maxwidth = 352; sd->maxheight = 288; sd->sif = 1; if (sd->sensor == SEN_OV6620) { PDEBUG(D_PROBE, "Writing 6x20 registers"); if (write_i2c_regvals(sd, norm_6x20, sizeof norm_6x20 / sizeof norm_6x20[0])) if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20))) return -1; } else { PDEBUG(D_PROBE, "Writing 6x30 registers"); if (write_i2c_regvals(sd, norm_6x30, sizeof norm_6x30 / sizeof norm_6x30[0])) if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30))) return -1; } return 0; Loading @@ -1302,14 +1266,8 @@ static int ov6xx0_configure(struct sd *sd) /* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */ static void ov51x_led_control(struct sd *sd, int on) { PDEBUG(D_STREAM, "LED (%s)", on ? "on" : "off"); /* if (sd->bridge == BRG_OV511PLUS) */ /* reg_w(sd, R511_SYS_LED_CTL, on ? 1 : 0); */ /* else if (sd->bridge == BRG_OV519) */ /* PDEBUG(D_STREAM, "LED (%s)", on ? "on" : "off"); */ reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */ /* else if (sd->bclass == BCL_OV518) */ /* reg_w_mask(sd, R518_GPIO_OUT, on ? 0x02 : 0x00, 0x02); */ } /* this function is called at probe time */ Loading @@ -1319,11 +1277,8 @@ static int sd_config(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; /* (from ov519_configure) */ static const struct ov_regvals init_519[] = { { 0x5a, 0x6d }, /* EnableSystem */ /* jfm trace usbsnoop3-1.txt */ /* jfm 53 = fb */ { 0x53, 0x9b }, { 0x54, 0xff }, /* set bit2 to enable jpeg */ { 0x5d, 0x03 }, Loading @@ -1340,9 +1295,6 @@ static int sd_config(struct gspca_dev *gspca_dev, if (write_regvals(sd, init_519, ARRAY_SIZE(init_519))) goto error; /* jfm: not seen in windows trace */ if (ov519_init_compression(sd)) goto error; ov51x_led_control(sd, 0); /* turn LED off */ /* Test for 76xx */ Loading Loading @@ -1391,16 +1343,16 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; cam->epaddr = OV511_ENDPOINT_ADDRESS; if (sd->maxwidth == 640) { if (!sd->sif) { cam->cam_mode = vga_mode; cam->nmodes = sizeof vga_mode / sizeof vga_mode[0]; cam->nmodes = ARRAY_SIZE(vga_mode); } else { cam->cam_mode = sif_mode; cam->nmodes = sizeof sif_mode / sizeof sif_mode[0]; cam->nmodes = ARRAY_SIZE(sif_mode); } 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->hflip = HFLIP_DEF; sd->vflip = VFLIP_DEF; return 0; Loading @@ -1422,8 +1374,7 @@ static int sd_open(struct gspca_dev *gspca_dev) * * Do not put any sensor-specific code in here (including I2C I/O functions) */ static int ov519_mode_init_regs(struct sd *sd, int width, int height) static int ov519_mode_init_regs(struct sd *sd) { static const struct ov_regvals mode_init_519_ov7670[] = { { 0x5d, 0x03 }, /* Turn off suspend mode */ Loading Loading @@ -1469,36 +1420,23 @@ static int ov519_mode_init_regs(struct sd *sd, /* windows reads 0x55 at this point, why? */ }; /* int hi_res; */ PDEBUG(D_CONF, "mode init %dx%d", width, height); /* if (width >= 800 && height >= 600) hi_res = 1; else hi_res = 0; */ /* if (ov51x_stop(sd) < 0) return -EIO; */ /******** Set the mode ********/ if (sd->sensor != SEN_OV7670) { if (write_regvals(sd, mode_init_519, ARRAY_SIZE(mode_init_519))) return -EIO; if (sd->sensor == SEN_OV7640) { /* Select 8-bit input mode */ reg_w_mask(sd, OV519_CAM_DFR, 0x10, 0x10); } } else { if (write_regvals(sd, mode_init_519_ov7670, ARRAY_SIZE(mode_init_519_ov7670))) return -EIO; } if (sd->sensor == SEN_OV7640) { /* Select 8-bit input mode */ reg_w_mask(sd, OV519_CAM_DFR, 0x10, 0x10); } reg_w(sd, OV519_CAM_H_SIZE, width >> 4); reg_w(sd, OV519_CAM_V_SIZE, height >> 3); reg_w(sd, OV519_CAM_H_SIZE, sd->gspca_dev.width >> 4); reg_w(sd, OV519_CAM_V_SIZE, sd->gspca_dev.height >> 3); reg_w(sd, OV519_CAM_X_OFFSETL, 0x00); reg_w(sd, OV519_CAM_X_OFFSETH, 0x00); reg_w(sd, OV519_CAM_Y_OFFSETL, 0x00); Loading @@ -1513,9 +1451,10 @@ static int ov519_mode_init_regs(struct sd *sd, /* FIXME: These are only valid at the max resolution. */ sd->clockdiv = 0; if (sd->sensor == SEN_OV7640) { switch (sd->sensor) { case SEN_OV7640: switch (sd->frame_rate) { /*jfm: default was 30 fps */ /*fixme: default was 30 fps */ case 30: reg_w(sd, 0xa4, 0x0c); reg_w(sd, 0x23, 0xff); Loading Loading @@ -1545,7 +1484,8 @@ static int ov519_mode_init_regs(struct sd *sd, sd->clockdiv = 1; break; } } else if (sd->sensor == SEN_OV8610) { break; case SEN_OV8610: switch (sd->frame_rate) { default: /* 15 fps */ /* case 15: */ Loading @@ -1561,41 +1501,37 @@ static int ov519_mode_init_regs(struct sd *sd, reg_w(sd, 0x23, 0x1b); break; } sd->clockdiv = 0; } else if (sd->sensor == SEN_OV7670) { /* guesses, based on 7640 */ break; case SEN_OV7670: /* guesses, based on 7640 */ PDEBUG(D_STREAM, "Setting framerate to %d fps", (sd->frame_rate == 0) ? 15 : sd->frame_rate); reg_w(sd, 0xa4, 0x10); switch (sd->frame_rate) { case 30: reg_w(sd, 0xa4, 0x10); reg_w(sd, 0x23, 0xff); break; case 20: reg_w(sd, 0xa4, 0x10); reg_w(sd, 0x23, 0x1b); break; default: /* 15 fps */ default: /* case 15: */ reg_w(sd, 0xa4, 0x10); reg_w(sd, 0x23, 0xff); sd->clockdiv = 1; break; } break; } /* if (ov51x_restart(sd) < 0) return -EIO; */ /* Reset it just for good measure */ /* if (ov51x_reset(sd, OV511_RESET_NOREGS) < 0) return -EIO; */ return 0; } static int mode_init_ov_sensor_regs(struct sd *sd, struct ovsensor_window *win) static int mode_init_ov_sensor_regs(struct sd *sd) { int qvga = win->quarter; struct gspca_dev *gspca_dev; int qvga; gspca_dev = &sd->gspca_dev; qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; /******** Mode (VGA/QVGA) and sensor specific regs ********/ switch (sd->sensor) { Loading Loading @@ -1639,8 +1575,6 @@ static int mode_init_ov_sensor_regs(struct sd *sd, OV7670_COM7_FMT_MASK); break; case SEN_OV6620: i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); break; case SEN_OV6630: i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); break; Loading @@ -1649,8 +1583,6 @@ static int mode_init_ov_sensor_regs(struct sd *sd, } /******** Palette-specific regs ********/ /* Need to do work here for the OV7670 */ if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) { /* not valid on the OV6620/OV7620/6630? */ i2c_w_mask(sd, 0x0e, 0x00, 0x40); Loading @@ -1666,7 +1598,6 @@ static int mode_init_ov_sensor_regs(struct sd *sd, if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV7640) i2c_w_mask(sd, 0x13, 0x00, 0x20); /* } */ /******** Clock programming ********/ /* The OV6620 needs special handling. This prevents the Loading @@ -1675,14 +1606,14 @@ static int mode_init_ov_sensor_regs(struct sd *sd, /* Clock down */ i2c_w(sd, 0x2a, 0x04); i2c_w(sd, 0x11, win->clockdiv); i2c_w(sd, 0x11, sd->clockdiv); i2c_w(sd, 0x2a, 0x84); /* This next setting is critical. It seems to improve * the gain or the contrast. The "reserved" bits seem * to have some effect in this case. */ i2c_w(sd, 0x2d, 0x85); } else if (win->clockdiv >= 0) { i2c_w(sd, 0x11, win->clockdiv); } else if (sd->clockdiv >= 0) { i2c_w(sd, 0x11, sd->clockdiv); } /******** Special Features ********/ Loading @@ -1702,7 +1633,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd, /* is fully tested. */ /* 7620/6620/6630? don't have register 0x35, so play it safe */ if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) { if (win->width == 640 /*&& win->height == 480*/) if (!qvga) i2c_w(sd, 0x35, 0x9e); else i2c_w(sd, 0x35, 0x1e); Loading @@ -1710,33 +1641,31 @@ static int mode_init_ov_sensor_regs(struct sd *sd, return 0; } static void sethflip(struct sd *sd) { if (sd->gspca_dev.streaming) ov51x_stop(sd); i2c_w_mask(sd, OV7670_REG_MVFP, OV7670_MVFP_MIRROR * sd->hflip, OV7670_MVFP_MIRROR); if (sd->gspca_dev.streaming) ov51x_restart(sd); } static void setvflip(struct sd *sd) static void sethvflip(struct sd *sd) { if (sd->sensor != SEN_OV7670) return; if (sd->gspca_dev.streaming) ov51x_stop(sd); i2c_w_mask(sd, OV7670_REG_MVFP, OV7670_MVFP_VFLIP * sd->vflip, OV7670_MVFP_VFLIP); OV7670_MVFP_MIRROR * sd->hflip | OV7670_MVFP_VFLIP * sd->vflip, OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP); if (sd->gspca_dev.streaming) ov51x_restart(sd); } static int set_ov_sensor_window(struct sd *sd, struct ovsensor_window *win) static int set_ov_sensor_window(struct sd *sd) { struct gspca_dev *gspca_dev; int qvga; int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; int ret, hstart, hstop, vstop, vstart; __u8 v; gspca_dev = &sd->gspca_dev; qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; /* The different sensor ICs handle setting up of window differently. * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */ switch (sd->sensor) { Loading Loading @@ -1781,7 +1710,7 @@ static int set_ov_sensor_window(struct sd *sd, switch (sd->sensor) { case SEN_OV6620: case SEN_OV6630: if (win->quarter) { /* QCIF */ if (qvga) { /* QCIF */ hwscale = 0; vwscale = 0; } else { /* CIF */ Loading @@ -1791,7 +1720,7 @@ static int set_ov_sensor_window(struct sd *sd, } break; case SEN_OV8610: if (win->quarter) { /* QSVGA */ if (qvga) { /* QSVGA */ hwscale = 1; vwscale = 1; } else { /* SVGA */ Loading @@ -1800,7 +1729,7 @@ static int set_ov_sensor_window(struct sd *sd, } break; default: /* SEN_OV7xx0 */ if (win->quarter) { /* QVGA */ if (qvga) { /* QVGA */ hwscale = 1; vwscale = 0; } else { /* VGA */ Loading @@ -1809,7 +1738,7 @@ static int set_ov_sensor_window(struct sd *sd, } } ret = mode_init_ov_sensor_regs(sd, win); ret = mode_init_ov_sensor_regs(sd); if (ret < 0) return ret; Loading @@ -1830,7 +1759,7 @@ static int set_ov_sensor_window(struct sd *sd, /* I can hard code this for OV7670s */ /* Yes, these numbers do look odd, but they're tested and work! */ if (sd->sensor == SEN_OV7670) { if (win->quarter) { /* QVGA from ov7670.c by if (qvga) { /* QVGA from ov7670.c by * Jonathan Corbet */ hstart = 164; hstop = 20; Loading @@ -1844,76 +1773,45 @@ static int set_ov_sensor_window(struct sd *sd, } /* OV7670 hardware window registers are split across * multiple locations */ i2c_w(sd, OV7670_REG_HSTART, (hstart >> 3) & 0xff); i2c_w(sd, OV7670_REG_HSTOP, (hstop >> 3) & 0xff); i2c_w(sd, OV7670_REG_HSTART, hstart >> 3); i2c_w(sd, OV7670_REG_HSTOP, hstop >> 3); v = i2c_r(sd, OV7670_REG_HREF); v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x07); msleep(10); /* need to sleep between read and write to * same reg! */ i2c_w(sd, OV7670_REG_HREF, v); i2c_w(sd, OV7670_REG_VSTART, (vstart >> 2) & 0xff); i2c_w(sd, OV7670_REG_VSTOP, (vstop >> 2) & 0xff); i2c_w(sd, OV7670_REG_VSTART, vstart >> 2); i2c_w(sd, OV7670_REG_VSTOP, vstop >> 2); v = i2c_r(sd, OV7670_REG_VREF); v = (v & 0xc0) | ((vstop & 0x3) << 2) | (vstart & 0x03); msleep(10); /* need to sleep between read and write to * same reg! */ i2c_w(sd, OV7670_REG_VREF, v); sethflip(sd); setvflip(sd); sethvflip(sd); } else { i2c_w(sd, 0x17, hwsbase + (win->x >> hwscale)); i2c_w(sd, 0x18, hwebase + ((win->x + win->width) >> hwscale)); i2c_w(sd, 0x19, vwsbase + (win->y >> vwscale)); i2c_w(sd, 0x1a, vwebase + ((win->y + win->height) >> vwscale)); i2c_w(sd, 0x17, hwsbase); i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale)); i2c_w(sd, 0x19, vwsbase); i2c_w(sd, 0x1a, vwebase + (sd->gspca_dev.height >> vwscale)); } return 0; } static int ov_sensor_mode_setup(struct sd *sd, int width, int height) { struct ovsensor_window win; /* win.format = mode; */ /* Unless subcapture is enabled, * center the image window and downsample * if possible to increase the field of view */ /* NOTE: OV518(+) and OV519 does downsampling on its own */ win.width = width; win.height = height; if (width == sd->maxwidth) win.quarter = 0; else win.quarter = 1; /* Center it */ win.x = (win.width - width) / 2; win.y = (win.height - height) / 2; /* Clock is determined by OV519 frame rate code */ win.clockdiv = sd->clockdiv; PDEBUG(D_CONF, "Setting clock divider to %d", win.clockdiv); return set_ov_sensor_window(sd, &win); } /* -- start the camera -- */ static void sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int ret; ret = ov519_mode_init_regs(sd, gspca_dev->width, gspca_dev->height); ret = ov519_mode_init_regs(sd); if (ret < 0) goto out; ret = ov_sensor_mode_setup(sd, gspca_dev->width, gspca_dev->height); ret = set_ov_sensor_window(sd); if (ret < 0) goto out; ret = ov51x_restart((struct sd *) gspca_dev); ret = ov51x_restart(sd); if (ret < 0) goto out; PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt); Loading Loading @@ -1987,12 +1885,10 @@ static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int val; /* int was_streaming; */ val = sd->brightness; PDEBUG(D_CONF, "brightness:%d", val); /* was_streaming = gspca_dev->streaming; * if (was_streaming) /* if (gspca_dev->streaming) * ov51x_stop(sd); */ switch (sd->sensor) { case SEN_OV8610: Loading @@ -2010,12 +1906,12 @@ static void setbrightness(struct gspca_dev *gspca_dev) i2c_w(sd, OV7610_REG_BRT, val); break; case SEN_OV7670: /*jfm - from windblows /*win trace * i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_AEC); */ i2c_w(sd, OV7670_REG_BRIGHT, ov7670_abs_to_sm(val)); break; } /* if (was_streaming) /* if (gspca_dev->streaming) * ov51x_restart(sd); */ } Loading @@ -2023,12 +1919,10 @@ static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int val; /* int was_streaming; */ val = sd->contrast; PDEBUG(D_CONF, "contrast:%d", val); /* was_streaming = gspca_dev->streaming; if (was_streaming) /* if (gspca_dev->streaming) ov51x_stop(sd); */ switch (sd->sensor) { case SEN_OV7610: Loading Loading @@ -2065,7 +1959,7 @@ static void setcontrast(struct gspca_dev *gspca_dev) i2c_w(sd, OV7670_REG_CONTRAS, val >> 1); break; } /* if (was_streaming) /* if (gspca_dev->streaming) ov51x_restart(sd); */ } Loading @@ -2073,12 +1967,10 @@ static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int val; /* int was_streaming; */ val = sd->colors; PDEBUG(D_CONF, "saturation:%d", val); /* was_streaming = gspca_dev->streaming; if (was_streaming) /* if (gspca_dev->streaming) ov51x_stop(sd); */ switch (sd->sensor) { case SEN_OV8610: Loading @@ -2104,7 +1996,7 @@ static void setcolors(struct gspca_dev *gspca_dev) /* set REG_COM13 values for UV sat auto mode */ break; } /* if (was_streaming) /* if (gspca_dev->streaming) ov51x_restart(sd); */ } Loading Loading @@ -2164,7 +2056,7 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) struct sd *sd = (struct sd *) gspca_dev; sd->hflip = val; sethflip(sd); sethvflip(sd); return 0; } Loading @@ -2181,7 +2073,7 @@ static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) struct sd *sd = (struct sd *) gspca_dev; sd->vflip = val; setvflip(sd); sethvflip(sd); return 0; } Loading