V4L/DVB (11970): gspca - ov519: Add support for the ov518 bridge.
Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
253f13d5cd
commit
49809d6a51
|
@ -50,6 +50,13 @@ static int i2c_detect_tries = 10;
|
|||
struct sd {
|
||||
struct gspca_dev gspca_dev; /* !! must be the first item */
|
||||
|
||||
char bridge;
|
||||
#define BRIDGE_OV511 0
|
||||
#define BRIDGE_OV511PLUS 1
|
||||
#define BRIDGE_OV518 2
|
||||
#define BRIDGE_OV518PLUS 3
|
||||
#define BRIDGE_OV519 4
|
||||
|
||||
/* Determined by sensor type */
|
||||
__u8 sif;
|
||||
|
||||
|
@ -87,6 +94,9 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
|
|||
static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
|
||||
static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
|
||||
static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
|
||||
static void setbrightness(struct gspca_dev *gspca_dev);
|
||||
static void setcontrast(struct gspca_dev *gspca_dev);
|
||||
static void setcolors(struct gspca_dev *gspca_dev);
|
||||
|
||||
static struct ctrl sd_ctrls[] = {
|
||||
{
|
||||
|
@ -164,7 +174,7 @@ static struct ctrl sd_ctrls[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static const struct v4l2_pix_format vga_mode[] = {
|
||||
static const struct v4l2_pix_format ov519_vga_mode[] = {
|
||||
{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
||||
.bytesperline = 320,
|
||||
.sizeimage = 320 * 240 * 3 / 8 + 590,
|
||||
|
@ -176,7 +186,7 @@ static const struct v4l2_pix_format vga_mode[] = {
|
|||
.colorspace = V4L2_COLORSPACE_JPEG,
|
||||
.priv = 0},
|
||||
};
|
||||
static const struct v4l2_pix_format sif_mode[] = {
|
||||
static const struct v4l2_pix_format ov519_sif_mode[] = {
|
||||
{176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
||||
.bytesperline = 176,
|
||||
.sizeimage = 176 * 144 * 3 / 8 + 590,
|
||||
|
@ -189,6 +199,47 @@ static const struct v4l2_pix_format sif_mode[] = {
|
|||
.priv = 0},
|
||||
};
|
||||
|
||||
static const struct v4l2_pix_format ov518_vga_mode[] = {
|
||||
{320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
|
||||
.bytesperline = 320,
|
||||
.sizeimage = 320 * 240 * 3 / 8 + 590,
|
||||
.colorspace = V4L2_COLORSPACE_JPEG,
|
||||
.priv = 1},
|
||||
{640, 480, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
|
||||
.bytesperline = 640,
|
||||
.sizeimage = 640 * 480 * 3 / 8 + 590,
|
||||
.colorspace = V4L2_COLORSPACE_JPEG,
|
||||
.priv = 0},
|
||||
};
|
||||
static const struct v4l2_pix_format ov518_sif_mode[] = {
|
||||
{176, 144, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
|
||||
.bytesperline = 176,
|
||||
.sizeimage = 40000,
|
||||
.colorspace = V4L2_COLORSPACE_JPEG,
|
||||
.priv = 1},
|
||||
{352, 288, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
|
||||
.bytesperline = 352,
|
||||
.sizeimage = 352 * 288 * 3 / 8 + 590,
|
||||
.colorspace = V4L2_COLORSPACE_JPEG,
|
||||
.priv = 0},
|
||||
};
|
||||
|
||||
|
||||
/* Registers common to OV511 / OV518 */
|
||||
#define R51x_SYS_RESET 0x50
|
||||
#define R51x_SYS_INIT 0x53
|
||||
#define R51x_SYS_SNAP 0x52
|
||||
#define R51x_SYS_CUST_ID 0x5F
|
||||
#define R51x_COMP_LUT_BEGIN 0x80
|
||||
|
||||
/* OV511 Camera interface register numbers */
|
||||
#define R511_SYS_LED_CTL 0x55 /* OV511+ only */
|
||||
#define OV511_RESET_NOREGS 0x3F /* All but OV511 & regs */
|
||||
|
||||
/* OV518 Camera interface register numbers */
|
||||
#define R518_GPIO_OUT 0x56 /* OV518(+) only */
|
||||
#define R518_GPIO_CTL 0x57 /* OV518(+) only */
|
||||
|
||||
/* OV519 Camera interface register numbers */
|
||||
#define OV519_R10_H_SIZE 0x10
|
||||
#define OV519_R11_V_SIZE 0x11
|
||||
|
@ -224,6 +275,8 @@ static const struct v4l2_pix_format sif_mode[] = {
|
|||
|
||||
/* OV7610 registers */
|
||||
#define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */
|
||||
#define OV7610_REG_BLUE 0x01 /* blue channel balance */
|
||||
#define OV7610_REG_RED 0x02 /* red channel balance */
|
||||
#define OV7610_REG_SAT 0x03 /* saturation */
|
||||
#define OV8610_REG_HUE 0x04 /* 04 reserved */
|
||||
#define OV7610_REG_CNT 0x05 /* Y contrast */
|
||||
|
@ -846,11 +899,12 @@ static unsigned char ov7670_abs_to_sm(unsigned char v)
|
|||
static int reg_w(struct sd *sd, __u16 index, __u8 value)
|
||||
{
|
||||
int ret;
|
||||
int req = (sd->bridge <= BRIDGE_OV511PLUS) ? 2 : 1;
|
||||
|
||||
sd->gspca_dev.usb_buf[0] = value;
|
||||
ret = usb_control_msg(sd->gspca_dev.dev,
|
||||
usb_sndctrlpipe(sd->gspca_dev.dev, 0),
|
||||
1, /* REQ_IO (ov518/519) */
|
||||
req,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
0, index,
|
||||
sd->gspca_dev.usb_buf, 1, 500);
|
||||
|
@ -864,10 +918,11 @@ static int reg_w(struct sd *sd, __u16 index, __u8 value)
|
|||
static int reg_r(struct sd *sd, __u16 index)
|
||||
{
|
||||
int ret;
|
||||
int req = (sd->bridge <= BRIDGE_OV511PLUS) ? 3 : 1;
|
||||
|
||||
ret = usb_control_msg(sd->gspca_dev.dev,
|
||||
usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
|
||||
1, /* REQ_IO */
|
||||
req,
|
||||
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
0, index, sd->gspca_dev.usb_buf, 1, 500);
|
||||
|
||||
|
@ -923,6 +978,28 @@ static int reg_w_mask(struct sd *sd,
|
|||
return reg_w(sd, index, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes multiple (n) byte value to a single register. Only valid with certain
|
||||
* registers (0x30 and 0xc4 - 0xce).
|
||||
*/
|
||||
static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n)
|
||||
{
|
||||
int ret;
|
||||
|
||||
*((u32 *)sd->gspca_dev.usb_buf) = __cpu_to_le32(value);
|
||||
|
||||
ret = usb_control_msg(sd->gspca_dev.dev,
|
||||
usb_sndctrlpipe(sd->gspca_dev.dev, 0),
|
||||
1 /* REG_IO */,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
0, index,
|
||||
sd->gspca_dev.usb_buf, n, 500);
|
||||
if (ret < 0)
|
||||
PDEBUG(D_ERR, "Write reg32 [%02x] %08x failed", index, value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The OV518 I2C I/O procedure is different, hence, this function.
|
||||
* This is normally only called from i2c_w(). Note that this function
|
||||
|
@ -1014,20 +1091,47 @@ static inline int ov51x_stop(struct sd *sd)
|
|||
{
|
||||
PDEBUG(D_STREAM, "stopping");
|
||||
sd->stopped = 1;
|
||||
return reg_w(sd, OV519_SYS_RESET1, 0x0f);
|
||||
switch (sd->bridge) {
|
||||
case BRIDGE_OV511:
|
||||
case BRIDGE_OV511PLUS:
|
||||
return reg_w(sd, R51x_SYS_RESET, 0x3d);
|
||||
case BRIDGE_OV518:
|
||||
case BRIDGE_OV518PLUS:
|
||||
return reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a);
|
||||
case BRIDGE_OV519:
|
||||
return reg_w(sd, OV519_SYS_RESET1, 0x0f);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not
|
||||
* actually stopped (for performance). */
|
||||
static inline int ov51x_restart(struct sd *sd)
|
||||
{
|
||||
int rc;
|
||||
|
||||
PDEBUG(D_STREAM, "restarting");
|
||||
if (!sd->stopped)
|
||||
return 0;
|
||||
sd->stopped = 0;
|
||||
|
||||
/* Reinitialize the stream */
|
||||
return reg_w(sd, OV519_SYS_RESET1, 0x00);
|
||||
switch (sd->bridge) {
|
||||
case BRIDGE_OV511:
|
||||
case BRIDGE_OV511PLUS:
|
||||
return reg_w(sd, R51x_SYS_RESET, 0x00);
|
||||
case BRIDGE_OV518:
|
||||
case BRIDGE_OV518PLUS:
|
||||
rc = reg_w(sd, 0x2f, 0x80);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
return reg_w(sd, R51x_SYS_RESET, 0x00);
|
||||
case BRIDGE_OV519:
|
||||
return reg_w(sd, OV519_SYS_RESET1, 0x00);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This does an initial reset of an OmniVision sensor and ensures that I2C
|
||||
|
@ -1287,16 +1391,161 @@ 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)
|
||||
{
|
||||
reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */
|
||||
switch (sd->bridge) {
|
||||
/* OV511 has no LED control */
|
||||
case BRIDGE_OV511PLUS:
|
||||
reg_w(sd, R511_SYS_LED_CTL, on ? 1 : 0);
|
||||
break;
|
||||
case BRIDGE_OV518:
|
||||
case BRIDGE_OV518PLUS:
|
||||
reg_w_mask(sd, R518_GPIO_OUT, on ? 0x02 : 0x00, 0x02);
|
||||
break;
|
||||
case BRIDGE_OV519:
|
||||
reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* this function is called at probe time */
|
||||
static int sd_config(struct gspca_dev *gspca_dev,
|
||||
const struct usb_device_id *id)
|
||||
/* OV518 quantization tables are 8x4 (instead of 8x8) */
|
||||
static int ov518_upload_quan_tables(struct sd *sd)
|
||||
{
|
||||
const unsigned char yQuanTable518[] = {
|
||||
5, 4, 5, 6, 6, 7, 7, 7,
|
||||
5, 5, 5, 5, 6, 7, 7, 7,
|
||||
6, 6, 6, 6, 7, 7, 7, 8,
|
||||
7, 7, 6, 7, 7, 7, 8, 8
|
||||
};
|
||||
|
||||
const unsigned char uvQuanTable518[] = {
|
||||
6, 6, 6, 7, 7, 7, 7, 7,
|
||||
6, 6, 6, 7, 7, 7, 7, 7,
|
||||
6, 6, 6, 7, 7, 7, 7, 8,
|
||||
7, 7, 7, 7, 7, 7, 8, 8
|
||||
};
|
||||
|
||||
const unsigned char *pYTable = yQuanTable518;
|
||||
const unsigned char *pUVTable = uvQuanTable518;
|
||||
unsigned char val0, val1;
|
||||
int i, rc, reg = R51x_COMP_LUT_BEGIN;
|
||||
|
||||
PDEBUG(D_PROBE, "Uploading quantization tables");
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
val0 = *pYTable++;
|
||||
val1 = *pYTable++;
|
||||
val0 &= 0x0f;
|
||||
val1 &= 0x0f;
|
||||
val0 |= val1 << 4;
|
||||
rc = reg_w(sd, reg, val0);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
val0 = *pUVTable++;
|
||||
val1 = *pUVTable++;
|
||||
val0 &= 0x0f;
|
||||
val1 &= 0x0f;
|
||||
val0 |= val1 << 4;
|
||||
rc = reg_w(sd, reg + 16, val0);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
reg++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This initializes the OV518/OV518+ and the sensor */
|
||||
static int ov518_configure(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
struct cam *cam;
|
||||
int rc;
|
||||
|
||||
/* For 518 and 518+ */
|
||||
static struct ov_regvals init_518[] = {
|
||||
{ R51x_SYS_RESET, 0x40 },
|
||||
{ R51x_SYS_INIT, 0xe1 },
|
||||
{ R51x_SYS_RESET, 0x3e },
|
||||
{ R51x_SYS_INIT, 0xe1 },
|
||||
{ R51x_SYS_RESET, 0x00 },
|
||||
{ R51x_SYS_INIT, 0xe1 },
|
||||
{ 0x46, 0x00 },
|
||||
{ 0x5d, 0x03 },
|
||||
};
|
||||
|
||||
static struct ov_regvals norm_518[] = {
|
||||
{ R51x_SYS_SNAP, 0x02 }, /* Reset */
|
||||
{ R51x_SYS_SNAP, 0x01 }, /* Enable */
|
||||
{ 0x31, 0x0f },
|
||||
{ 0x5d, 0x03 },
|
||||
{ 0x24, 0x9f },
|
||||
{ 0x25, 0x90 },
|
||||
{ 0x20, 0x00 },
|
||||
{ 0x51, 0x04 },
|
||||
{ 0x71, 0x19 },
|
||||
{ 0x2f, 0x80 },
|
||||
};
|
||||
|
||||
static struct ov_regvals norm_518_p[] = {
|
||||
{ R51x_SYS_SNAP, 0x02 }, /* Reset */
|
||||
{ R51x_SYS_SNAP, 0x01 }, /* Enable */
|
||||
{ 0x31, 0x0f },
|
||||
{ 0x5d, 0x03 },
|
||||
{ 0x24, 0x9f },
|
||||
{ 0x25, 0x90 },
|
||||
{ 0x20, 0x60 },
|
||||
{ 0x51, 0x02 },
|
||||
{ 0x71, 0x19 },
|
||||
{ 0x40, 0xff },
|
||||
{ 0x41, 0x42 },
|
||||
{ 0x46, 0x00 },
|
||||
{ 0x33, 0x04 },
|
||||
{ 0x21, 0x19 },
|
||||
{ 0x3f, 0x10 },
|
||||
{ 0x2f, 0x80 },
|
||||
};
|
||||
|
||||
/* First 5 bits of custom ID reg are a revision ID on OV518 */
|
||||
PDEBUG(D_PROBE, "Device revision %d",
|
||||
0x1F & reg_r(sd, R51x_SYS_CUST_ID));
|
||||
|
||||
rc = write_regvals(sd, init_518, ARRAY_SIZE(init_518));
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* Set LED GPIO pin to output mode */
|
||||
rc = reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
switch (sd->bridge) {
|
||||
case BRIDGE_OV518:
|
||||
rc = write_regvals(sd, norm_518, ARRAY_SIZE(norm_518));
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
break;
|
||||
case BRIDGE_OV518PLUS:
|
||||
rc = write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p));
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = ov518_upload_quan_tables(sd);
|
||||
if (rc < 0) {
|
||||
PDEBUG(D_ERR, "Error uploading quantization tables");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = reg_w(sd, 0x2f, 0x80);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ov519_configure(struct sd *sd)
|
||||
{
|
||||
static const struct ov_regvals init_519[] = {
|
||||
{ 0x5a, 0x6d }, /* EnableSystem */
|
||||
{ 0x53, 0x9b },
|
||||
|
@ -1313,8 +1562,32 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
|||
/* windows reads 0x55 at this point*/
|
||||
};
|
||||
|
||||
if (write_regvals(sd, init_519, ARRAY_SIZE(init_519)))
|
||||
return write_regvals(sd, init_519, ARRAY_SIZE(init_519));
|
||||
}
|
||||
|
||||
/* this function is called at probe time */
|
||||
static int sd_config(struct gspca_dev *gspca_dev,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
struct cam *cam;
|
||||
int ret = 0;
|
||||
|
||||
sd->bridge = id->driver_info;
|
||||
|
||||
switch (sd->bridge) {
|
||||
case BRIDGE_OV518:
|
||||
case BRIDGE_OV518PLUS:
|
||||
ret = ov518_configure(gspca_dev);
|
||||
break;
|
||||
case BRIDGE_OV519:
|
||||
ret = ov519_configure(sd);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ov51x_led_control(sd, 0); /* turn LED off */
|
||||
|
||||
/* Test for 76xx */
|
||||
|
@ -1360,12 +1633,26 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
|||
}
|
||||
|
||||
cam = &gspca_dev->cam;
|
||||
if (!sd->sif) {
|
||||
cam->cam_mode = vga_mode;
|
||||
cam->nmodes = ARRAY_SIZE(vga_mode);
|
||||
} else {
|
||||
cam->cam_mode = sif_mode;
|
||||
cam->nmodes = ARRAY_SIZE(sif_mode);
|
||||
switch (sd->bridge) {
|
||||
case BRIDGE_OV518:
|
||||
case BRIDGE_OV518PLUS:
|
||||
if (!sd->sif) {
|
||||
cam->cam_mode = ov518_vga_mode;
|
||||
cam->nmodes = ARRAY_SIZE(ov518_vga_mode);
|
||||
} else {
|
||||
cam->cam_mode = ov518_sif_mode;
|
||||
cam->nmodes = ARRAY_SIZE(ov518_sif_mode);
|
||||
}
|
||||
break;
|
||||
case BRIDGE_OV519:
|
||||
if (!sd->sif) {
|
||||
cam->cam_mode = ov519_vga_mode;
|
||||
cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
|
||||
} else {
|
||||
cam->cam_mode = ov519_sif_mode;
|
||||
cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
|
||||
}
|
||||
break;
|
||||
}
|
||||
sd->brightness = BRIGHTNESS_DEF;
|
||||
sd->contrast = CONTRAST_DEF;
|
||||
|
@ -1422,6 +1709,106 @@ static int sd_init(struct gspca_dev *gspca_dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Sets up the OV518/OV518+ with the given image parameters
|
||||
*
|
||||
* OV518 needs a completely different approach, until we can figure out what
|
||||
* the individual registers do. Also, only 15 FPS is supported now.
|
||||
*
|
||||
* Do not put any sensor-specific code in here (including I2C I/O functions)
|
||||
*/
|
||||
static int ov518_mode_init_regs(struct sd *sd)
|
||||
{
|
||||
int hsegs, vsegs;
|
||||
|
||||
/******** Set the mode ********/
|
||||
|
||||
reg_w(sd, 0x2b, 0);
|
||||
reg_w(sd, 0x2c, 0);
|
||||
reg_w(sd, 0x2d, 0);
|
||||
reg_w(sd, 0x2e, 0);
|
||||
reg_w(sd, 0x3b, 0);
|
||||
reg_w(sd, 0x3c, 0);
|
||||
reg_w(sd, 0x3d, 0);
|
||||
reg_w(sd, 0x3e, 0);
|
||||
|
||||
if (sd->bridge == BRIDGE_OV518) {
|
||||
/* Set 8-bit (YVYU) input format */
|
||||
reg_w_mask(sd, 0x20, 0x08, 0x08);
|
||||
|
||||
/* Set 12-bit (4:2:0) output format */
|
||||
reg_w_mask(sd, 0x28, 0x80, 0xf0);
|
||||
reg_w_mask(sd, 0x38, 0x80, 0xf0);
|
||||
} else {
|
||||
reg_w(sd, 0x28, 0x80);
|
||||
reg_w(sd, 0x38, 0x80);
|
||||
}
|
||||
|
||||
hsegs = sd->gspca_dev.width / 16;
|
||||
vsegs = sd->gspca_dev.height / 4;
|
||||
|
||||
reg_w(sd, 0x29, hsegs);
|
||||
reg_w(sd, 0x2a, vsegs);
|
||||
|
||||
reg_w(sd, 0x39, hsegs);
|
||||
reg_w(sd, 0x3a, vsegs);
|
||||
|
||||
/* Windows driver does this here; who knows why */
|
||||
reg_w(sd, 0x2f, 0x80);
|
||||
|
||||
/******** Set the framerate (to 30 FPS) ********/
|
||||
if (sd->bridge == BRIDGE_OV518PLUS)
|
||||
sd->clockdiv = 1;
|
||||
else
|
||||
sd->clockdiv = 0;
|
||||
|
||||
/* Mode independent, but framerate dependent, regs */
|
||||
reg_w(sd, 0x51, 0x04); /* Clock divider; lower==faster */
|
||||
reg_w(sd, 0x22, 0x18);
|
||||
reg_w(sd, 0x23, 0xff);
|
||||
|
||||
if (sd->bridge == BRIDGE_OV518PLUS)
|
||||
reg_w(sd, 0x21, 0x19);
|
||||
else
|
||||
reg_w(sd, 0x71, 0x17); /* Compression-related? */
|
||||
|
||||
/* FIXME: Sensor-specific */
|
||||
/* Bit 5 is what matters here. Of course, it is "reserved" */
|
||||
i2c_w(sd, 0x54, 0x23);
|
||||
|
||||
reg_w(sd, 0x2f, 0x80);
|
||||
|
||||
if (sd->bridge == BRIDGE_OV518PLUS) {
|
||||
reg_w(sd, 0x24, 0x94);
|
||||
reg_w(sd, 0x25, 0x90);
|
||||
ov518_reg_w32(sd, 0xc4, 400, 2); /* 190h */
|
||||
ov518_reg_w32(sd, 0xc6, 540, 2); /* 21ch */
|
||||
ov518_reg_w32(sd, 0xc7, 540, 2); /* 21ch */
|
||||
ov518_reg_w32(sd, 0xc8, 108, 2); /* 6ch */
|
||||
ov518_reg_w32(sd, 0xca, 131098, 3); /* 2001ah */
|
||||
ov518_reg_w32(sd, 0xcb, 532, 2); /* 214h */
|
||||
ov518_reg_w32(sd, 0xcc, 2400, 2); /* 960h */
|
||||
ov518_reg_w32(sd, 0xcd, 32, 2); /* 20h */
|
||||
ov518_reg_w32(sd, 0xce, 608, 2); /* 260h */
|
||||
} else {
|
||||
reg_w(sd, 0x24, 0x9f);
|
||||
reg_w(sd, 0x25, 0x90);
|
||||
ov518_reg_w32(sd, 0xc4, 400, 2); /* 190h */
|
||||
ov518_reg_w32(sd, 0xc6, 381, 2); /* 17dh */
|
||||
ov518_reg_w32(sd, 0xc7, 381, 2); /* 17dh */
|
||||
ov518_reg_w32(sd, 0xc8, 128, 2); /* 80h */
|
||||
ov518_reg_w32(sd, 0xca, 183331, 3); /* 2cc23h */
|
||||
ov518_reg_w32(sd, 0xcb, 746, 2); /* 2eah */
|
||||
ov518_reg_w32(sd, 0xcc, 1750, 2); /* 6d6h */
|
||||
ov518_reg_w32(sd, 0xcd, 45, 2); /* 2dh */
|
||||
ov518_reg_w32(sd, 0xce, 851, 2); /* 353h */
|
||||
}
|
||||
|
||||
reg_w(sd, 0x2f, 0x80);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Sets up the OV519 with the given image parameters
|
||||
*
|
||||
* OV519 needs a completely different approach, until we can figure out what
|
||||
|
@ -1740,6 +2127,11 @@ static int set_ov_sensor_window(struct sd *sd)
|
|||
hwebase = 0x3a;
|
||||
vwsbase = 0x05;
|
||||
vwebase = 0x06;
|
||||
if (qvga) {
|
||||
/* HDG: this fixes U and V getting swapped */
|
||||
hwsbase--;
|
||||
vwsbase--;
|
||||
}
|
||||
break;
|
||||
case SEN_OV7620:
|
||||
hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */
|
||||
|
@ -1855,15 +2247,28 @@ static int set_ov_sensor_window(struct sd *sd)
|
|||
static int sd_start(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
ret = ov519_mode_init_regs(sd);
|
||||
switch (sd->bridge) {
|
||||
case BRIDGE_OV518:
|
||||
case BRIDGE_OV518PLUS:
|
||||
ret = ov518_mode_init_regs(sd);
|
||||
break;
|
||||
case BRIDGE_OV519:
|
||||
ret = ov519_mode_init_regs(sd);
|
||||
break;
|
||||
}
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = set_ov_sensor_window(sd);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
setcontrast(gspca_dev);
|
||||
setbrightness(gspca_dev);
|
||||
setcolors(gspca_dev);
|
||||
|
||||
ret = ov51x_restart(sd);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
@ -1882,7 +2287,30 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
|
|||
ov51x_led_control(sd, 0);
|
||||
}
|
||||
|
||||
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
||||
static void ov518_pkt_scan(struct gspca_dev *gspca_dev,
|
||||
struct gspca_frame *frame, /* target */
|
||||
__u8 *data, /* isoc packet */
|
||||
int len) /* iso packet length */
|
||||
{
|
||||
PDEBUG(D_STREAM, "ov518_pkt_scan: %d bytes", len);
|
||||
|
||||
if (len & 7) {
|
||||
len--;
|
||||
PDEBUG(D_STREAM, "packet number: %d\n", (int)data[len]);
|
||||
}
|
||||
|
||||
/* A false positive here is likely, until OVT gives me
|
||||
* the definitive SOF/EOF format */
|
||||
if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) {
|
||||
gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0);
|
||||
gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, 0);
|
||||
}
|
||||
|
||||
/* intermediate packet */
|
||||
gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
|
||||
}
|
||||
|
||||
static void ov519_pkt_scan(struct gspca_dev *gspca_dev,
|
||||
struct gspca_frame *frame, /* target */
|
||||
__u8 *data, /* isoc packet */
|
||||
int len) /* iso packet length */
|
||||
|
@ -1926,6 +2354,27 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
|||
data, len);
|
||||
}
|
||||
|
||||
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
||||
struct gspca_frame *frame, /* target */
|
||||
__u8 *data, /* isoc packet */
|
||||
int len) /* iso packet length */
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
switch (sd->bridge) {
|
||||
case BRIDGE_OV511:
|
||||
case BRIDGE_OV511PLUS:
|
||||
break;
|
||||
case BRIDGE_OV518:
|
||||
case BRIDGE_OV518PLUS:
|
||||
ov518_pkt_scan(gspca_dev, frame, data, len);
|
||||
break;
|
||||
case BRIDGE_OV519:
|
||||
ov519_pkt_scan(gspca_dev, frame, data, len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* -- management routines -- */
|
||||
|
||||
static void setbrightness(struct gspca_dev *gspca_dev)
|
||||
|
@ -1970,6 +2419,7 @@ static void setcontrast(struct gspca_dev *gspca_dev)
|
|||
break;
|
||||
case SEN_OV6630:
|
||||
i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f);
|
||||
break;
|
||||
case SEN_OV8610: {
|
||||
static const __u8 ctab[] = {
|
||||
0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f
|
||||
|
@ -2136,19 +2586,21 @@ static const struct sd_desc sd_desc = {
|
|||
|
||||
/* -- module initialisation -- */
|
||||
static const __devinitdata struct usb_device_id device_table[] = {
|
||||
{USB_DEVICE(0x041e, 0x4052)},
|
||||
{USB_DEVICE(0x041e, 0x405f)},
|
||||
{USB_DEVICE(0x041e, 0x4060)},
|
||||
{USB_DEVICE(0x041e, 0x4061)},
|
||||
{USB_DEVICE(0x041e, 0x4064)},
|
||||
{USB_DEVICE(0x041e, 0x4068)},
|
||||
{USB_DEVICE(0x045e, 0x028c)},
|
||||
{USB_DEVICE(0x054c, 0x0154)},
|
||||
{USB_DEVICE(0x054c, 0x0155)},
|
||||
{USB_DEVICE(0x05a9, 0x0519)},
|
||||
{USB_DEVICE(0x05a9, 0x0530)},
|
||||
{USB_DEVICE(0x05a9, 0x4519)},
|
||||
{USB_DEVICE(0x05a9, 0x8519)},
|
||||
{USB_DEVICE(0x041e, 0x4052), .driver_info = BRIDGE_OV519 },
|
||||
{USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 },
|
||||
{USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 },
|
||||
{USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 },
|
||||
{USB_DEVICE(0x041e, 0x4064), .driver_info = BRIDGE_OV519 },
|
||||
{USB_DEVICE(0x041e, 0x4068), .driver_info = BRIDGE_OV519 },
|
||||
{USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 },
|
||||
{USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 },
|
||||
{USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 },
|
||||
{USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 },
|
||||
{USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 },
|
||||
{USB_DEVICE(0x05a9, 0x0530), .driver_info = BRIDGE_OV519 },
|
||||
{USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 },
|
||||
{USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 },
|
||||
{USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS },
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -347,7 +347,8 @@ struct v4l2_pix_format {
|
|||
#define V4L2_PIX_FMT_MR97310A v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */
|
||||
#define V4L2_PIX_FMT_SQ905C v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */
|
||||
#define V4L2_PIX_FMT_PJPG v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */
|
||||
#define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') /* 16 YVU 4:2:2 */
|
||||
#define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') /* 16 YVU 4:2:2 */
|
||||
#define V4L2_PIX_FMT_OV518 v4l2_fourcc('O', '5', '1', '8') /* ov518 JPEG */
|
||||
|
||||
/*
|
||||
* F O R M A T E N U M E R A T I O N
|
||||
|
|
Loading…
Reference in New Issue