/* Probe the I2C bus and initialise the sensor chip */ int stk_sensor_init(struct stk_camera *dev) { u8 idl = 0; u8 idh = 0; if (stk_camera_write_reg(dev, STK_IIC_ENABLE, STK_IIC_ENABLE_YES) || stk_camera_write_reg(dev, STK_IIC_ADDR, SENSOR_ADDRESS) || stk_sensor_outb(dev, REG_COM7, COM7_RESET)) { STK_ERROR("Sensor resetting failed\n"); return -ENODEV; } msleep(10); /* Read the manufacturer ID: ov = 0x7FA2 */ if (stk_sensor_inb(dev, REG_MIDH, &idh) || stk_sensor_inb(dev, REG_MIDL, &idl)) { STK_ERROR("Strange error reading sensor ID\n"); return -ENODEV; } if (idh != 0x7f || idl != 0xa2) { STK_ERROR("Huh? you don't have a sensor from ovt\n"); return -ENODEV; } if (stk_sensor_inb(dev, REG_PID, &idh) || stk_sensor_inb(dev, REG_VER, &idl)) { STK_ERROR("Could not read sensor model\n"); return -ENODEV; } stk_sensor_write_regvals(dev, ov_initvals); msleep(10); STK_INFO("OmniVision sensor detected, id %02X%02X" " at address %x\n", idh, idl, SENSOR_ADDRESS); return 0; }
static int stk_sensor_inb(struct stk_camera *dev, u8 reg, u8 *val) { int i = 0; int tmpval = 0; if (stk_camera_write_reg(dev, STK_IIC_RX_INDEX, reg)) return 1; if (stk_camera_write_reg(dev, STK_IIC_OP, STK_IIC_OP_RX)) return 1; do { if (stk_camera_read_reg(dev, STK_IIC_STAT, &tmpval)) return 1; i++; } while (tmpval == 0 && i < MAX_RETRIES); if (tmpval != STK_IIC_STAT_RX_OK) { if (tmpval) STK_ERROR("stk_sensor_inb failed, status=0x%02x\n", tmpval); return 1; } if (stk_camera_read_reg(dev, STK_IIC_RX_VALUE, &tmpval)) return 1; *val = (u8) tmpval; return 0; }
static int stk_start_stream(struct stk_camera *dev) { int value; int i, ret; int value_116, value_117; if (!is_present(dev)) return -ENODEV; if (!is_memallocd(dev) || !is_initialised(dev)) { STK_ERROR("FIXME: Buffers are not allocated\n"); return -EFAULT; } ret = usb_set_interface(dev->udev, 0, 5); if (ret < 0) STK_ERROR("usb_set_interface failed !\n"); if (stk_sensor_wakeup(dev)) STK_ERROR("error awaking the sensor\n"); stk_camera_read_reg(dev, 0x0116, &value_116); stk_camera_read_reg(dev, 0x0117, &value_117); stk_camera_write_reg(dev, 0x0116, 0x0000); stk_camera_write_reg(dev, 0x0117, 0x0000); stk_camera_read_reg(dev, 0x0100, &value); stk_camera_write_reg(dev, 0x0100, value | 0x80); stk_camera_write_reg(dev, 0x0116, value_116); stk_camera_write_reg(dev, 0x0117, value_117); for (i = 0; i < MAX_ISO_BUFS; i++) { if (dev->isobufs[i].urb) { ret = usb_submit_urb(dev->isobufs[i].urb, GFP_KERNEL); atomic_inc(&dev->urbs_used); if (ret) return ret; } } set_streaming(dev); return 0; }
static int stk_stop_stream(struct stk_camera *dev) { int value; int i; if (is_present(dev)) { stk_camera_read_reg(dev, 0x0100, &value); stk_camera_write_reg(dev, 0x0100, value & ~0x80); if (dev->isobufs != NULL) { for (i = 0; i < MAX_ISO_BUFS; i++) { if (dev->isobufs[i].urb) usb_kill_urb(dev->isobufs[i].urb); } } unset_streaming(dev); if (usb_set_interface(dev->udev, 0, 0)) STK_ERROR("usb_set_interface failed !\n"); if (stk_sensor_sleep(dev)) STK_ERROR("error suspending the sensor\n"); } return 0; }
/* * This function is called as an URB transfert is complete (Isochronous pipe). * So, the traitement is done in interrupt time, so it has be fast, not crash, * and not stall. Neat. */ static void stk_isoc_handler(struct urb *urb) { int i; int ret; int framelen; unsigned long flags; unsigned char *fill = NULL; unsigned char *iso_buf = NULL; struct stk_camera *dev; struct stk_sio_buffer *fb; dev = (struct stk_camera *) urb->context; if (dev == NULL) { STK_ERROR("isoc_handler called with NULL device !\n"); return; } if (urb->status == -ENOENT || urb->status == -ECONNRESET || urb->status == -ESHUTDOWN) { atomic_dec(&dev->urbs_used); return; } spin_lock_irqsave(&dev->spinlock, flags); if (urb->status != -EINPROGRESS && urb->status != 0) { STK_ERROR("isoc_handler: urb->status == %d\n", urb->status); goto resubmit; } if (list_empty(&dev->sio_avail)) { /*FIXME Stop streaming after a while */ (void) (printk_ratelimit() && STK_ERROR("isoc_handler without available buffer!\n")); goto resubmit; } fb = list_first_entry(&dev->sio_avail, struct stk_sio_buffer, list); fill = fb->buffer + fb->v4lbuf.bytesused; for (i = 0; i < urb->number_of_packets; i++) { if (urb->iso_frame_desc[i].status != 0) { if (urb->iso_frame_desc[i].status != -EXDEV) STK_ERROR("Frame %d has error %d\n", i, urb->iso_frame_desc[i].status); continue; } framelen = urb->iso_frame_desc[i].actual_length; iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset; if (framelen <= 4) continue; /* no data */ /* * we found something informational from there * the isoc frames have to type of headers * type1: 00 xx 00 00 or 20 xx 00 00 * type2: 80 xx 00 00 00 00 00 00 or a0 xx 00 00 00 00 00 00 * xx is a sequencer which has never been seen over 0x3f * imho data written down looks like bayer, i see similarities * after every 640 bytes */ if (*iso_buf & 0x80) { framelen -= 8; iso_buf += 8; /* This marks a new frame */ if (fb->v4lbuf.bytesused != 0 && fb->v4lbuf.bytesused != dev->frame_size) { (void) (printk_ratelimit() && STK_ERROR("frame %d, " "bytesused=%d, skipping\n", i, fb->v4lbuf.bytesused)); fb->v4lbuf.bytesused = 0; fill = fb->buffer; } else if (fb->v4lbuf.bytesused == dev->frame_size) { if (list_is_singular(&dev->sio_avail)) { /* Always reuse the last buffer */ fb->v4lbuf.bytesused = 0; fill = fb->buffer; } else { list_move_tail(dev->sio_avail.next, &dev->sio_full); wake_up(&dev->wait_frame); fb = list_first_entry(&dev->sio_avail, struct stk_sio_buffer, list); fb->v4lbuf.bytesused = 0; fill = fb->buffer; } } } else {
int stk_sensor_configure(struct stk_camera *dev) { int com7; /* * We setup the sensor to output dummy lines in low-res modes, * so we don't get absurdly hight framerates. */ unsigned dummylines; int flip; struct regval *rv; switch (dev->vsettings.mode) { case MODE_QCIF: com7 = COM7_FMT_QCIF; dummylines = 604; break; case MODE_QVGA: com7 = COM7_FMT_QVGA; dummylines = 267; break; case MODE_CIF: com7 = COM7_FMT_CIF; dummylines = 412; break; case MODE_VGA: com7 = COM7_FMT_VGA; dummylines = 11; break; case MODE_SXGA: com7 = COM7_FMT_SXGA; dummylines = 0; break; default: STK_ERROR("Unsupported mode %d\n", dev->vsettings.mode); return -EFAULT; } switch (dev->vsettings.palette) { case V4L2_PIX_FMT_UYVY: com7 |= COM7_YUV; rv = ov_fmt_uyvy; break; case V4L2_PIX_FMT_YUYV: com7 |= COM7_YUV; rv = ov_fmt_yuyv; break; case V4L2_PIX_FMT_RGB565: com7 |= COM7_RGB; rv = ov_fmt_rgbp; break; case V4L2_PIX_FMT_RGB565X: com7 |= COM7_RGB; rv = ov_fmt_rgbr; break; case V4L2_PIX_FMT_SBGGR8: com7 |= COM7_PBAYER; rv = ov_fmt_bayer; break; default: STK_ERROR("Unsupported colorspace\n"); return -EFAULT; } /*FIXME sometimes the sensor go to a bad state stk_sensor_write_regvals(dev, ov_initvals); */ stk_sensor_outb(dev, REG_COM7, com7); msleep(50); stk_sensor_write_regvals(dev, rv); flip = (dev->vsettings.vflip?MVFP_FLIP:0) | (dev->vsettings.hflip?MVFP_MIRROR:0); stk_sensor_outb(dev, REG_MVFP, flip); if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8 && !dev->vsettings.vflip) stk_sensor_outb(dev, REG_TSLB, 0x08); stk_sensor_outb(dev, REG_ADVFH, dummylines >> 8); stk_sensor_outb(dev, REG_ADVFL, dummylines & 0xff); msleep(50); switch (dev->vsettings.mode) { case MODE_VGA: if (stk_sensor_set_hw(dev, 302, 1582, 6, 486)) STK_ERROR("stk_sensor_set_hw failed (VGA)\n"); break; case MODE_SXGA: case MODE_CIF: case MODE_QVGA: case MODE_QCIF: /*FIXME These settings seem ignored by the sensor if (stk_sensor_set_hw(dev, 220, 1500, 10, 1034)) STK_ERROR("stk_sensor_set_hw failed (SXGA)\n"); */ break; } msleep(10); return 0; }
int stk_sensor_configure(struct stk_camera *dev) { int com7; unsigned dummylines; int flip; struct regval *rv; switch (dev->vsettings.mode) { case MODE_QCIF: com7 = COM7_FMT_QCIF; dummylines = 604; break; case MODE_QVGA: com7 = COM7_FMT_QVGA; dummylines = 267; break; case MODE_CIF: com7 = COM7_FMT_CIF; dummylines = 412; break; case MODE_VGA: com7 = COM7_FMT_VGA; dummylines = 11; break; case MODE_SXGA: com7 = COM7_FMT_SXGA; dummylines = 0; break; default: STK_ERROR("Unsupported mode %d\n", dev->vsettings.mode); return -EFAULT; } switch (dev->vsettings.palette) { case V4L2_PIX_FMT_UYVY: com7 |= COM7_YUV; rv = ov_fmt_uyvy; break; case V4L2_PIX_FMT_YUYV: com7 |= COM7_YUV; rv = ov_fmt_yuyv; break; case V4L2_PIX_FMT_RGB565: com7 |= COM7_RGB; rv = ov_fmt_rgbp; break; case V4L2_PIX_FMT_RGB565X: com7 |= COM7_RGB; rv = ov_fmt_rgbr; break; case V4L2_PIX_FMT_SBGGR8: com7 |= COM7_PBAYER; rv = ov_fmt_bayer; break; default: STK_ERROR("Unsupported colorspace\n"); return -EFAULT; } stk_sensor_outb(dev, REG_COM7, com7); msleep(50); stk_sensor_write_regvals(dev, rv); flip = (dev->vsettings.vflip?MVFP_FLIP:0) | (dev->vsettings.hflip?MVFP_MIRROR:0); stk_sensor_outb(dev, REG_MVFP, flip); if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8 && !dev->vsettings.vflip) stk_sensor_outb(dev, REG_TSLB, 0x08); stk_sensor_outb(dev, REG_ADVFH, dummylines >> 8); stk_sensor_outb(dev, REG_ADVFL, dummylines & 0xff); msleep(50); switch (dev->vsettings.mode) { case MODE_VGA: if (stk_sensor_set_hw(dev, 302, 1582, 6, 486)) STK_ERROR("stk_sensor_set_hw failed (VGA)\n"); break; case MODE_SXGA: case MODE_CIF: case MODE_QVGA: case MODE_QCIF: break; } msleep(10); return 0; }