Commit 189d92af authored by Jean-Francois Moine's avatar Jean-Francois Moine Committed by Mauro Carvalho Chehab

V4L/DVB (13422): gspca - ov534: ov772x changes from Richard Kaswy.

- 320x240 resolution added
- controls added
- different sd_desc tables
Signed-off-by: default avatarJean-Francois Moine <moinejf@free.fr>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 4bdf4a83
/* /*
* ov534 gspca driver * ov534 gspca driver
*
* Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it> * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
* Copyright (C) 2008 Jim Paris <jim@jtan.com> * Copyright (C) 2008 Jim Paris <jim@jtan.com>
* Copyright (C) 2009 Jean-Francois Moine http://moinejf.free.fr * Copyright (C) 2009 Jean-Francois Moine http://moinejf.free.fr
...@@ -8,6 +9,8 @@ ...@@ -8,6 +9,8 @@
* USB protocol reverse engineered by Jim Paris <jim@jtan.com> * USB protocol reverse engineered by Jim Paris <jim@jtan.com>
* https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/ * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/
* *
* PS3 Eye camera enhanced by Richard Kaswy http://kaswy.free.fr
*
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
...@@ -50,6 +53,14 @@ struct sd { ...@@ -50,6 +53,14 @@ struct sd {
__u32 last_pts; __u32 last_pts;
u16 last_fid; u16 last_fid;
u8 frame_rate; u8 frame_rate;
u8 gain;
u8 exposure;
u8 redblc;
u8 blueblc;
u8 autogain;
u8 sharpness;
u8 hflip;
u8 vflip;
u8 sensor; u8 sensor;
#define SENSOR_OV772X 0 #define SENSOR_OV772X 0
...@@ -57,10 +68,146 @@ struct sd { ...@@ -57,10 +68,146 @@ struct sd {
}; };
/* V4L2 controls supported by the driver */ /* V4L2 controls supported by the driver */
static struct ctrl sd_ctrls[] = { static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getredblc(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setblueblc(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getblueblc(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
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 struct ctrl sd_ctrls_ov772x[] = {
{
{
.id = V4L2_CID_GAIN,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Main Gain",
.minimum = 0,
.maximum = 63,
.step = 1,
#define GAIN_DEF 20
.default_value = GAIN_DEF,
},
.set = sd_setgain,
.get = sd_getgain,
},
{
{
.id = V4L2_CID_EXPOSURE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Exposure",
.minimum = 0,
.maximum = 255,
.step = 1,
#define EXPO_DEF 255
.default_value = EXPO_DEF,
},
.set = sd_setexposure,
.get = sd_getexposure,
},
{
{
.id = V4L2_CID_RED_BALANCE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Red Balance",
.minimum = 0,
.maximum = 255,
.step = 1,
#define RED_BALANCE_DEF 128
.default_value = RED_BALANCE_DEF,
},
.set = sd_setredblc,
.get = sd_getredblc,
},
{
{
.id = V4L2_CID_BLUE_BALANCE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Blue Balance",
.minimum = 0,
.maximum = 255,
.step = 1,
#define BLUE_BALANCE_DEF 128
.default_value = BLUE_BALANCE_DEF,
},
.set = sd_setblueblc,
.get = sd_getblueblc,
},
{
{
.id = V4L2_CID_AUTOGAIN,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "Autogain",
.minimum = 0,
.maximum = 1,
.step = 1,
#define AUTOGAIN_DEF 1
.default_value = AUTOGAIN_DEF,
},
.set = sd_setautogain,
.get = sd_getautogain,
},
{
{
.id = V4L2_CID_SHARPNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Sharpness",
.minimum = 0,
.maximum = 63,
.step = 1,
#define SHARPNESS_DEF 4
.default_value = SHARPNESS_DEF,
},
.set = sd_setsharpness,
.get = sd_getsharpness,
},
{
{
.id = V4L2_CID_HFLIP,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "HFlip",
.minimum = 0,
.maximum = 1,
.step = 1,
#define HFLIP_DEF 0
.default_value = HFLIP_DEF,
},
.set = sd_sethflip,
.get = sd_gethflip,
},
{
{
.id = V4L2_CID_VFLIP,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "VFlip",
.minimum = 0,
.maximum = 1,
.step = 1,
#define VFLIP_DEF 0
.default_value = VFLIP_DEF,
},
.set = sd_setvflip,
.get = sd_getvflip,
},
};
static struct ctrl sd_ctrls_ov965x[] = {
}; };
static const struct v4l2_pix_format vga_yuyv_mode[] = { static const struct v4l2_pix_format vga_yuyv_mode[] = {
{320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
.bytesperline = 320 * 2,
.sizeimage = 320 * 240 * 2,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = 1},
{640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
.bytesperline = 640 * 2, .bytesperline = 640 * 2,
.sizeimage = 640 * 480 * 2, .sizeimage = 640 * 480 * 2,
...@@ -80,8 +227,7 @@ static const struct v4l2_pix_format vga_jpeg_mode[] = { ...@@ -80,8 +227,7 @@ static const struct v4l2_pix_format vga_jpeg_mode[] = {
.colorspace = V4L2_COLORSPACE_JPEG, .colorspace = V4L2_COLORSPACE_JPEG,
.priv = 0}, .priv = 0},
}; };
static const u8 bridge_init_ov772x[][2] = {
static const u8 bridge_init_ov722x[][2] = {
{ 0xc2, 0x0c }, { 0xc2, 0x0c },
{ 0x88, 0xf8 }, { 0x88, 0xf8 },
{ 0xc3, 0x69 }, { 0xc3, 0x69 },
...@@ -122,6 +268,7 @@ static const u8 bridge_init_ov722x[][2] = { ...@@ -122,6 +268,7 @@ static const u8 bridge_init_ov722x[][2] = {
{ 0x1d, 0x40 }, { 0x1d, 0x40 },
{ 0x1d, 0x02 }, /* payload size 0x0200 * 4 = 2048 bytes */ { 0x1d, 0x02 }, /* payload size 0x0200 * 4 = 2048 bytes */
{ 0x1d, 0x00 }, /* payload size */ { 0x1d, 0x00 }, /* payload size */
{ 0x1d, 0x02 }, /* frame size 0x025800 * 4 = 614400 */ { 0x1d, 0x02 }, /* frame size 0x025800 * 4 = 614400 */
{ 0x1d, 0x58 }, /* frame size */ { 0x1d, 0x58 }, /* frame size */
{ 0x1d, 0x00 }, /* frame size */ { 0x1d, 0x00 }, /* frame size */
...@@ -138,10 +285,20 @@ static const u8 bridge_init_ov722x[][2] = { ...@@ -138,10 +285,20 @@ static const u8 bridge_init_ov722x[][2] = {
{ 0xc1, 0x3c }, { 0xc1, 0x3c },
{ 0xc2, 0x0c }, { 0xc2, 0x0c },
}; };
static const u8 sensor_init_ov772x[][2] = {
static const u8 sensor_init_ov722x[][2] = {
{ 0x12, 0x80 }, { 0x12, 0x80 },
{ 0x11, 0x01 }, { 0x11, 0x01 },
/*fixme: better have a delay?*/
{ 0x11, 0x01 },
{ 0x11, 0x01 },
{ 0x11, 0x01 },
{ 0x11, 0x01 },
{ 0x11, 0x01 },
{ 0x11, 0x01 },
{ 0x11, 0x01 },
{ 0x11, 0x01 },
{ 0x11, 0x01 },
{ 0x11, 0x01 },
{ 0x3d, 0x03 }, { 0x3d, 0x03 },
{ 0x17, 0x26 }, { 0x17, 0x26 },
...@@ -154,7 +311,7 @@ static const u8 sensor_init_ov722x[][2] = { ...@@ -154,7 +311,7 @@ static const u8 sensor_init_ov722x[][2] = {
{ 0x65, 0x20 }, { 0x65, 0x20 },
{ 0x11, 0x01 }, { 0x11, 0x01 },
{ 0x42, 0x7f }, { 0x42, 0x7f },
{ 0x63, 0xe0 }, { 0x63, 0xaa }, /* was e0 */
{ 0x64, 0xff }, { 0x64, 0xff },
{ 0x66, 0x00 }, { 0x66, 0x00 },
{ 0x13, 0xf0 }, { 0x13, 0xf0 },
...@@ -221,6 +378,46 @@ static const u8 sensor_init_ov722x[][2] = { ...@@ -221,6 +378,46 @@ static const u8 sensor_init_ov722x[][2] = {
{ 0x8e, 0x00 }, { 0x8e, 0x00 },
{ 0x0c, 0xd0 } { 0x0c, 0xd0 }
}; };
static const u8 bridge_start_ov772x_vga[][2] = {
{0x1c, 0x00},
{0x1d, 0x40},
{0x1d, 0x02},
{0x1d, 0x00},
{0x1d, 0x02},
{0x1d, 0x58},
{0x1d, 0x00},
{0xc0, 0x50},
{0xc1, 0x3c},
};
static const u8 sensor_start_ov772x_vga[][2] = {
{0x12, 0x00},
{0x17, 0x26},
{0x18, 0xa0},
{0x19, 0x07},
{0x1a, 0xf0},
{0x29, 0xa0},
{0x2c, 0xf0},
};
static const u8 bridge_start_ov772x_qvga[][2] = {
{0x1c, 0x00},
{0x1d, 0x40},
{0x1d, 0x02},
{0x1d, 0x00},
{0x1d, 0x01},
{0x1d, 0x4b},
{0x1d, 0x00},
{0xc0, 0x28},
{0xc1, 0x1e},
};
static const u8 sensor_start_ov772x_qvga[][2] = {
{0x12, 0x40},
{0x17, 0x3f},
{0x18, 0x50},
{0x19, 0x03},
{0x1a, 0x78},
{0x29, 0x50},
{0x2c, 0x78},
};
static const u8 bridge_init_ov965x[][2] = { static const u8 bridge_init_ov965x[][2] = {
{0x88, 0xf8}, {0x88, 0xf8},
...@@ -757,35 +954,150 @@ static void sccb_w_array(struct gspca_dev *gspca_dev, ...@@ -757,35 +954,150 @@ static void sccb_w_array(struct gspca_dev *gspca_dev,
static void ov534_set_frame_rate(struct gspca_dev *gspca_dev) static void ov534_set_frame_rate(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
int fr = sd->frame_rate; int i;
struct rate_s {
u8 fps;
u8 r11;
u8 r0d;
u8 re5;
};
const struct rate_s *r;
static const struct rate_s rate_0[] = { /* 640x480 */
{60, 0x01, 0xc1, 0x04},
{50, 0x01, 0x41, 0x02},
{40, 0x02, 0xc1, 0x04},
{30, 0x04, 0x81, 0x02},
{15, 0x03, 0x41, 0x04},
};
static const struct rate_s rate_1[] = { /* 320x240 */
{125, 0x02, 0x81, 0x02},
{100, 0x02, 0xc1, 0x04},
{75, 0x03, 0xc1, 0x04},
{60, 0x04, 0xc1, 0x04},
{50, 0x02, 0x41, 0x04},
{40, 0x03, 0x41, 0x04},
{30, 0x04, 0x41, 0x04},
};
if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv == 0) {
r = rate_0;
i = ARRAY_SIZE(rate_0);
} else {
r = rate_1;
i = ARRAY_SIZE(rate_1);
}
while (--i > 0) {
if (sd->frame_rate >= r->fps)
break;
r++;
}
sccb_reg_write(gspca_dev, 0x11, r->r11);
sccb_reg_write(gspca_dev, 0x0d, r->r0d);
ov534_reg_write(gspca_dev, 0xe5, r->re5);
PDEBUG(D_PROBE, "frame_rate: %d", r->fps);
}
/* ov772x controls */
static void setgain(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
u8 val;
switch (fr) { val = sd->gain;
case 50: switch (val & 0x30) {
sccb_reg_write(gspca_dev, 0x11, 0x01); case 0x00:
sccb_reg_write(gspca_dev, 0x0d, 0x41); val &= 0x0f;
ov534_reg_write(gspca_dev, 0xe5, 0x02);
break; break;
case 40: case 0x10:
sccb_reg_write(gspca_dev, 0x11, 0x02); val &= 0x0f;
sccb_reg_write(gspca_dev, 0x0d, 0xc1); val |= 0x30;
ov534_reg_write(gspca_dev, 0xe5, 0x04);
break; break;
/* case 30: */ case 0x20:
default: val &= 0x0f;
fr = 30; val |= 0x70;
sccb_reg_write(gspca_dev, 0x11, 0x04);
sccb_reg_write(gspca_dev, 0x0d, 0x81);
ov534_reg_write(gspca_dev, 0xe5, 0x02);
break; break;
case 15: default:
sccb_reg_write(gspca_dev, 0x11, 0x03); /* case 0x30: */
sccb_reg_write(gspca_dev, 0x0d, 0x41); val &= 0x0f;
ov534_reg_write(gspca_dev, 0xe5, 0x04); val |= 0xf0;
break; break;
} }
sccb_reg_write(gspca_dev, 0x00, val);
}
static void setexposure(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
u8 val;
val = sd->exposure;
sccb_reg_write(gspca_dev, 0x08, val >> 7);
sccb_reg_write(gspca_dev, 0x10, val << 1);
}
static void setredblc(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->frame_rate = fr; sccb_reg_write(gspca_dev, 0x43, sd->redblc);
PDEBUG(D_PROBE, "frame_rate: %d", fr); }
static void setblueblc(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
sccb_reg_write(gspca_dev, 0x42, sd->blueblc);
}
static void setautogain(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
if (sd->autogain) {
sccb_reg_write(gspca_dev, 0x13, 0xf7); /* AGC,AEC,AWB ON */
sccb_reg_write(gspca_dev, 0x64,
sccb_reg_read(gspca_dev, 0x64) | 0x03);
} else {
sccb_reg_write(gspca_dev, 0x13, 0xf0); /* AGC,AEC,AWB OFF */
sccb_reg_write(gspca_dev, 0x64,
sccb_reg_read(gspca_dev, 0x64) & 0xfc);
}
}
static void setsharpness(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
u8 val;
val = sd->sharpness;
sccb_reg_write(gspca_dev, 0x91, val); /* vga noise */
sccb_reg_write(gspca_dev, 0x8e, val); /* qvga noise */
}
static void sethflip(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
if (sd->hflip == 0)
sccb_reg_write(gspca_dev, 0x0c,
sccb_reg_read(gspca_dev, 0x0c) | 0x40);
else
sccb_reg_write(gspca_dev, 0x0c,
sccb_reg_read(gspca_dev, 0x0c) & 0xbf);
}
static void setvflip(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
if (sd->vflip == 0)
sccb_reg_write(gspca_dev, 0x0c,
sccb_reg_read(gspca_dev, 0x0c) | 0x80);
else
sccb_reg_write(gspca_dev, 0x0c,
sccb_reg_read(gspca_dev, 0x0c) & 0x7f);
} }
/* this function is called at probe time */ /* this function is called at probe time */
...@@ -811,6 +1123,19 @@ static int sd_config(struct gspca_dev *gspca_dev, ...@@ -811,6 +1123,19 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam->nmodes = ARRAY_SIZE(vga_jpeg_mode); cam->nmodes = ARRAY_SIZE(vga_jpeg_mode);
} }
sd->frame_rate = 30;
sd->gain = GAIN_DEF;
sd->exposure = EXPO_DEF;
sd->redblc = RED_BALANCE_DEF;
sd->blueblc = BLUE_BALANCE_DEF;
sd->autogain = AUTOGAIN_DEF;
sd->sharpness = SHARPNESS_DEF;
#if HFLIP_DEF != 0
sd->hflip = HFLIP_DEF;
#endif
#if VFLIP_DEF != 0
sd->vflip = VFLIP_DEF;
#endif
return 0; return 0;
} }
...@@ -847,11 +1172,11 @@ static int sd_init(struct gspca_dev *gspca_dev) ...@@ -847,11 +1172,11 @@ static int sd_init(struct gspca_dev *gspca_dev)
/* initialize */ /* initialize */
switch (sd->sensor) { switch (sd->sensor) {
case SENSOR_OV772X: case SENSOR_OV772X:
reg_w_array(gspca_dev, bridge_init_ov722x, reg_w_array(gspca_dev, bridge_init_ov772x,
ARRAY_SIZE(bridge_init_ov722x)); ARRAY_SIZE(bridge_init_ov772x));
ov534_set_led(gspca_dev, 1); ov534_set_led(gspca_dev, 1);
sccb_w_array(gspca_dev, sensor_init_ov722x, sccb_w_array(gspca_dev, sensor_init_ov772x,
ARRAY_SIZE(sensor_init_ov722x)); ARRAY_SIZE(sensor_init_ov772x));
ov534_reg_write(gspca_dev, 0xe0, 0x09); ov534_reg_write(gspca_dev, 0xe0, 0x09);
ov534_set_led(gspca_dev, 0); ov534_set_led(gspca_dev, 0);
ov534_set_frame_rate(gspca_dev); ov534_set_frame_rate(gspca_dev);
...@@ -875,60 +1200,78 @@ static int sd_init(struct gspca_dev *gspca_dev) ...@@ -875,60 +1200,78 @@ static int sd_init(struct gspca_dev *gspca_dev)
return 0; return 0;
} }
static int sd_start(struct gspca_dev *gspca_dev) static int sd_start_ov772x(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev;
int mode; int mode;
switch (sd->sensor) { mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
case SENSOR_OV772X: if (mode != 0) { /* 320x240 */
ov534_set_led(gspca_dev, 1); reg_w_array(gspca_dev, bridge_start_ov772x_qvga,
ov534_reg_write(gspca_dev, 0xe0, 0x00); ARRAY_SIZE(bridge_start_ov772x_qvga));
break; sccb_w_array(gspca_dev, sensor_start_ov772x_qvga,
default: ARRAY_SIZE(sensor_start_ov772x_qvga));
/* case SENSOR_OV965X: */ } else { /* 640x480 */
reg_w_array(gspca_dev, bridge_start_ov772x_vga,
sccb_w_array(gspca_dev, sensor_start_ov965x, ARRAY_SIZE(bridge_start_ov772x_vga));
ARRAY_SIZE(sensor_start_ov965x)); sccb_w_array(gspca_dev, sensor_start_ov772x_vga,
reg_w_array(gspca_dev, bridge_start_ov965x, ARRAY_SIZE(sensor_start_ov772x_vga));
ARRAY_SIZE(bridge_start_ov965x));
mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
if (mode != 0) { /* 320x240 */
reg_w_array(gspca_dev, bridge_start_ov965x_cif,
ARRAY_SIZE(bridge_start_ov965x_cif));
sccb_w_array(gspca_dev, sensor_start_ov965x_cif,
ARRAY_SIZE(sensor_start_ov965x_cif));
} else { /* 640x480 */
reg_w_array(gspca_dev, bridge_start_ov965x_vga,
ARRAY_SIZE(bridge_start_ov965x_vga));
sccb_w_array(gspca_dev, sensor_start_ov965x_vga,
ARRAY_SIZE(sensor_start_ov965x_vga));
}
sccb_w_array(gspca_dev, sensor_start_ov965x_2,
ARRAY_SIZE(sensor_start_ov965x_2));
ov534_reg_write(gspca_dev, 0xe0, 0x00);
ov534_reg_write(gspca_dev, 0xe0, 0x00);
ov534_set_led(gspca_dev, 1);
} }
ov534_set_frame_rate(gspca_dev);
setautogain(gspca_dev);
setgain(gspca_dev);
setredblc(gspca_dev);
setblueblc(gspca_dev);
setexposure(gspca_dev);
setsharpness(gspca_dev);
setvflip(gspca_dev);
sethflip(gspca_dev);
ov534_set_led(gspca_dev, 1);
ov534_reg_write(gspca_dev, 0xe0, 0x00);
return 0; return 0;
} }
static void sd_stopN(struct gspca_dev *gspca_dev) static int sd_start_ov965x(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev; int mode;
switch (sd->sensor) { sccb_w_array(gspca_dev, sensor_start_ov965x,
case SENSOR_OV772X: ARRAY_SIZE(sensor_start_ov965x));
ov534_reg_write(gspca_dev, 0xe0, 0x09); reg_w_array(gspca_dev, bridge_start_ov965x,
ov534_set_led(gspca_dev, 0); ARRAY_SIZE(bridge_start_ov965x));
break;
default: mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
/* case SENSOR_OV965X: */ if (mode != 0) { /* 320x240 */
ov534_reg_write(gspca_dev, 0xe0, 0x01); reg_w_array(gspca_dev, bridge_start_ov965x_cif,
ov534_set_led(gspca_dev, 0); ARRAY_SIZE(bridge_start_ov965x_cif));
ov534_reg_write(gspca_dev, 0xe0, 0x00); sccb_w_array(gspca_dev, sensor_start_ov965x_cif,
break; ARRAY_SIZE(sensor_start_ov965x_cif));
} else { /* 640x480 */
reg_w_array(gspca_dev, bridge_start_ov965x_vga,
ARRAY_SIZE(bridge_start_ov965x_vga));
sccb_w_array(gspca_dev, sensor_start_ov965x_vga,
ARRAY_SIZE(sensor_start_ov965x_vga));
} }
sccb_w_array(gspca_dev, sensor_start_ov965x_2,
ARRAY_SIZE(sensor_start_ov965x_2));
ov534_reg_write(gspca_dev, 0xe0, 0x00);
ov534_reg_write(gspca_dev, 0xe0, 0x00);
ov534_set_led(gspca_dev, 1);
return 0;
}
static void sd_stopN_ov772x(struct gspca_dev *gspca_dev)
{
ov534_reg_write(gspca_dev, 0xe0, 0x09);
ov534_set_led(gspca_dev, 0);
}
static void sd_stopN_ov965x(struct gspca_dev *gspca_dev)
{
ov534_reg_write(gspca_dev, 0xe0, 0x01);
ov534_set_led(gspca_dev, 0);
ov534_reg_write(gspca_dev, 0xe0, 0x00);
} }
/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
...@@ -1002,7 +1345,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, ...@@ -1002,7 +1345,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame,
data + 12, len - 12); data + 12, len - 12);
} }
/* Done this payload */ /* Done this payload */
goto scan_next; goto scan_next;
...@@ -1016,6 +1358,151 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, ...@@ -1016,6 +1358,151 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame,
} while (remaining_len > 0); } while (remaining_len > 0);
} }
/* ov772x controls */
static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->gain = val;
if (gspca_dev->streaming)
setgain(gspca_dev);
return 0;
}
static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->gain;
return 0;
}
static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->exposure = val;
if (gspca_dev->streaming)
setexposure(gspca_dev);
return 0;
}
static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->exposure;
return 0;
}
static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->redblc = val;
if (gspca_dev->streaming)
setredblc(gspca_dev);
return 0;
}
static int sd_getredblc(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->redblc;
return 0;
}
static int sd_setblueblc(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->blueblc = val;
if (gspca_dev->streaming)
setblueblc(gspca_dev);
return 0;
}
static int sd_getblueblc(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->blueblc;
return 0;
}
static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->autogain = val;
if (gspca_dev->streaming)
setautogain(gspca_dev);
return 0;
}
static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->autogain;
return 0;
}
static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->sharpness = val;
if (gspca_dev->streaming)
setsharpness(gspca_dev);
return 0;
}
static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->sharpness;
return 0;
}
static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->hflip = val;
if (gspca_dev->streaming)
sethflip(gspca_dev);
return 0;
}
static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->hflip;
return 0;
}
static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->vflip = val;
if (gspca_dev->streaming)
setvflip(gspca_dev);
return 0;
}
static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->vflip;
return 0;
}
/* get stream parameters (framerate) */ /* get stream parameters (framerate) */
static int sd_get_streamparm(struct gspca_dev *gspca_dev, static int sd_get_streamparm(struct gspca_dev *gspca_dev,
struct v4l2_streamparm *parm) struct v4l2_streamparm *parm)
...@@ -1047,7 +1534,8 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev, ...@@ -1047,7 +1534,8 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev,
/* Set requested framerate */ /* Set requested framerate */
sd->frame_rate = tpf->denominator / tpf->numerator; sd->frame_rate = tpf->denominator / tpf->numerator;
ov534_set_frame_rate(gspca_dev); if (gspca_dev->streaming)
ov534_set_frame_rate(gspca_dev);
/* Return the actual framerate */ /* Return the actual framerate */
tpf->numerator = 1; tpf->numerator = 1;
...@@ -1057,14 +1545,27 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev, ...@@ -1057,14 +1545,27 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev,
} }
/* sub-driver description */ /* sub-driver description */
static const struct sd_desc sd_desc = { static const struct sd_desc sd_desc_ov772x = {
.name = MODULE_NAME, .name = MODULE_NAME,
.ctrls = sd_ctrls, .ctrls = sd_ctrls_ov772x,
.nctrls = ARRAY_SIZE(sd_ctrls), .nctrls = ARRAY_SIZE(sd_ctrls_ov772x),
.config = sd_config, .config = sd_config,
.init = sd_init, .init = sd_init,
.start = sd_start, .start = sd_start_ov772x,
.stopN = sd_stopN, .stopN = sd_stopN_ov772x,
.pkt_scan = sd_pkt_scan,
.get_streamparm = sd_get_streamparm,
.set_streamparm = sd_set_streamparm,
};
static const struct sd_desc sd_desc_ov965x = {
.name = MODULE_NAME,
.ctrls = sd_ctrls_ov965x,
.nctrls = ARRAY_SIZE(sd_ctrls_ov965x),
.config = sd_config,
.init = sd_init,
.start = sd_start_ov965x,
.stopN = sd_stopN_ov965x,
.pkt_scan = sd_pkt_scan, .pkt_scan = sd_pkt_scan,
.get_streamparm = sd_get_streamparm, .get_streamparm = sd_get_streamparm,
.set_streamparm = sd_set_streamparm, .set_streamparm = sd_set_streamparm,
...@@ -1082,8 +1583,12 @@ MODULE_DEVICE_TABLE(usb, device_table); ...@@ -1082,8 +1583,12 @@ MODULE_DEVICE_TABLE(usb, device_table);
/* -- device connect -- */ /* -- device connect -- */
static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
{ {
return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), return gspca_dev_probe(intf, id,
THIS_MODULE); id->driver_info == SENSOR_OV772X
? &sd_desc_ov772x
: &sd_desc_ov965x,
sizeof(struct sd),
THIS_MODULE);
} }
static struct usb_driver sd_driver = { static struct usb_driver sd_driver = {
...@@ -1101,6 +1606,7 @@ static struct usb_driver sd_driver = { ...@@ -1101,6 +1606,7 @@ static struct usb_driver sd_driver = {
static int __init sd_mod_init(void) static int __init sd_mod_init(void)
{ {
int ret; int ret;
ret = usb_register(&sd_driver); ret = usb_register(&sd_driver);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment