summaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/sonixj.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/gspca/sonixj.c')
-rw-r--r--drivers/media/video/gspca/sonixj.c108
1 files changed, 86 insertions, 22 deletions
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
index d75b1d20b31..53cb82d9e7c 100644
--- a/drivers/media/video/gspca/sonixj.c
+++ b/drivers/media/video/gspca/sonixj.c
@@ -39,6 +39,7 @@ struct sd {
unsigned char contrast;
unsigned char colors;
unsigned char autogain;
+ __u8 vflip; /* ov7630 only */
signed char ag_cnt;
#define AG_CNT_START 13
@@ -70,6 +71,8 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getcolors(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_setvflip(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
static struct ctrl sd_ctrls[] = {
{
@@ -131,6 +134,22 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setautogain,
.get = sd_getautogain,
},
+/* ov7630 only */
+#define VFLIP_IDX 4
+ {
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Vflip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+#define VFLIP_DEF 1
+ .default_value = VFLIP_DEF,
+ },
+ .set = sd_setvflip,
+ .get = sd_getvflip,
+ },
};
static struct v4l2_pix_format vga_mode[] = {
@@ -248,10 +267,12 @@ static const __u8 gamma_def[] = {
0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
};
+/* color matrix and offsets */
static const __u8 reg84[] = {
- 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
- 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
- 0xf7, 0x0f, 0x00, 0x00, 0x00
+ 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, /* YR YG YB gains */
+ 0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00, /* UR UG UB */
+ 0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f, /* VR VG VB */
+ 0x00, 0x00, 0x00 /* YUV offsets */
};
static const __u8 hv7131r_sensor_init[][8] = {
{0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
@@ -434,7 +455,8 @@ static const __u8 ov7630_sensor_init[][8] = {
{0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
{0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
/*fixme: + 0x12, 0x04*/
- {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10},
+/* {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10}, * COMN
+ * set by setvflip */
{0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
{0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
{0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
@@ -707,6 +729,7 @@ static void i2c_w8(struct gspca_dev *gspca_dev,
0x08, 0, /* value, index */
gspca_dev->usb_buf, 8,
500);
+ msleep(2);
}
/* read 5 bytes in gspca_dev->usb_buf */
@@ -948,6 +971,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
gspca_dev->ctrl_dis = (1 << AUTOGAIN_IDX);
break;
}
+ if (sd->sensor != SENSOR_OV7630)
+ gspca_dev->ctrl_dis |= (1 << VFLIP_IDX);
return 0;
}
@@ -976,13 +1001,13 @@ static int sd_init(struct gspca_dev *gspca_dev)
case BRIDGE_SN9C105:
if (regF1 != 0x11)
return -ENODEV;
- reg_w(gspca_dev, 0x02, regGpio, 2);
+ reg_w(gspca_dev, 0x01, regGpio, 2);
break;
case BRIDGE_SN9C120:
if (regF1 != 0x12)
return -ENODEV;
regGpio[1] = 0x70;
- reg_w(gspca_dev, 0x02, regGpio, 2);
+ reg_w(gspca_dev, 0x01, regGpio, 2);
break;
default:
/* case BRIDGE_SN9C110: */
@@ -1079,20 +1104,17 @@ static unsigned int setexposure(struct gspca_dev *gspca_dev,
static void setbrightcont(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- unsigned val;
+ int val;
__u8 reg84_full[0x15];
- memset(reg84_full, 0, sizeof reg84_full);
- val = sd->contrast * 0x20 / CONTRAST_MAX + 0x10; /* 10..30 */
- reg84_full[2] = val;
- reg84_full[0] = (val + 1) / 2;
- reg84_full[4] = (val + 1) / 5;
- if (val > BRIGHTNESS_DEF)
- val = (sd->brightness - BRIGHTNESS_DEF) * 0x20
+ memcpy(reg84_full, reg84, sizeof reg84_full);
+ val = sd->contrast * 0x30 / CONTRAST_MAX + 0x10; /* 10..40 */
+ reg84_full[0] = (val + 1) / 2; /* red */
+ reg84_full[2] = val; /* green */
+ reg84_full[4] = (val + 1) / 5; /* blue */
+ val = (sd->brightness - BRIGHTNESS_DEF) * 0x10
/ BRIGHTNESS_MAX;
- else
- val = 0;
- reg84_full[0x12] = val; /* 00..1f */
+ reg84_full[0x12] = val & 0x1f; /* 5:0 signed value */
reg_w(gspca_dev, 0x84, reg84_full, sizeof reg84_full);
}
@@ -1171,8 +1193,16 @@ static void setautogain(struct gspca_dev *gspca_dev)
sd->ag_cnt = -1;
}
+static void setvflip(struct sd *sd)
+{
+ if (sd->sensor != SENSOR_OV7630)
+ return;
+ i2c_w1(&sd->gspca_dev, 0x75, /* COMN */
+ sd->vflip ? 0x82 : 0x02);
+}
+
/* -- start the camera -- */
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int i;
@@ -1183,7 +1213,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
static const __u8 CE_ov76xx[] =
- { 0x32, 0xdd, 0x32, 0xdd }; /* OV7630/48 */
+ { 0x32, 0xdd, 0x32, 0xdd };
sn9c1xx = sn_tb[(int) sd->sensor];
configure_gpio(gspca_dev, sn9c1xx);
@@ -1223,8 +1253,15 @@ static void sd_start(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def);
for (i = 0; i < 8; i++)
reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
+ switch (sd->sensor) {
+ case SENSOR_OV7660:
+ reg_w1(gspca_dev, 0x9a, 0x05);
+ break;
+ default:
reg_w1(gspca_dev, 0x9a, 0x08);
reg_w1(gspca_dev, 0x99, 0x59);
+ break;
+ }
mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
if (mode)
@@ -1255,6 +1292,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
break;
case SENSOR_OV7630:
ov7630_InitSensor(gspca_dev);
+ setvflip(sd);
reg17 = 0xe2;
reg1 = 0x44;
break;
@@ -1275,8 +1313,8 @@ static void sd_start(struct gspca_dev *gspca_dev)
/* reg1 = 0x44; */
/* reg1 = 0x46; (done) */
} else {
- reg17 = 0x22; /* 640 MCKSIZE */
- reg1 = 0x06;
+ reg17 = 0xa2; /* 640 */
+ reg1 = 0x44;
}
break;
}
@@ -1285,6 +1323,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
switch (sd->sensor) {
case SENSOR_OV7630:
case SENSOR_OV7648:
+ case SENSOR_OV7660:
reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
break;
default:
@@ -1311,12 +1350,16 @@ static void sd_start(struct gspca_dev *gspca_dev)
setbrightness(gspca_dev);
setcontrast(gspca_dev);
break;
+ case SENSOR_OV7630:
+ setvflip(sd);
+ /* fall thru */
default: /* OV76xx */
setbrightcont(gspca_dev);
break;
}
setautogain(gspca_dev);
reg_w1(gspca_dev, 0x01, reg1);
+ return 0;
}
static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -1537,6 +1580,24 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
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(sd);
+ 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;
+}
+
/* sub-driver description */
static const struct sd_desc sd_desc = {
.name = MODULE_NAME,
@@ -1558,6 +1619,7 @@ static const struct sd_desc sd_desc = {
static const __devinitdata struct usb_device_id device_table[] = {
#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
{USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
+ {USB_DEVICE(0x0458, 0x702e), BSI(SN9C120, OV7660, 0x21)},
{USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
{USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
{USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
@@ -1579,7 +1641,9 @@ static const __devinitdata struct usb_device_id device_table[] = {
/* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
{USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
{USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
-/* {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */
+#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
+ {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)},
+#endif
/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
/* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
/* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */