@@ -27,6 +27,29 @@
addresses is a - sign that register description is not valid for the
matching IC.
+ Register page 0:
+
+ Address Description
+ 0x72/- Different test patterns:
+ bit 0..3: 0 -> image, test pattern off
+ 1 -> white
+ 2 -> black
+ 3 -> red
+ 4 -> green
+ 5 -> blue
+ 6 -> cyan
+ 7 -> magenta
+ 8 -> yellow
+ 9 -> color bars
+ 10 -> high resolution color pattern
+ 11 -> black to white gradient from top to bottom
+ 12 -> white to black gradient from left to right
+ 13 -> white to black gradient repeats from left to right
+ 14 -> dark gray (#111111)
+ 15 -> dark gray 2 (#111111)
+ bit 4: overlay some diagnostic points over the image
+ bit 5..7: no effect
+
Register page 1:
Address Description
@@ -57,6 +80,7 @@
0 | 0x0f..0x20 | setcolors()
0 | 0xa2..0xab | setbrightcont()
0 | 0x55 | setedgedetect()
+ 0 | 0x72 | settestpattern()
0 | 0xc5 | setredbalance()
0 | 0xc6 | setwhitebalance()
0 | 0xc7 | setbluebalance()
@@ -91,6 +115,8 @@ struct sd {
__u8 hflip;
__u8 vflip;
unsigned char edge_detect;
+ unsigned char test_pattern;
+ unsigned char test_overlay;
u8 sof_read;
u8 autogain_ignore_frames;
@@ -123,9 +149,14 @@ static int sd_setexposure(struct gspca_d
static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setedgedetect(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getedgedetect(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_settestpattern(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_gettestpattern(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_settestoverlay(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_gettestoverlay(struct gspca_dev *gspca_dev, __s32 *val);
#define V4L2_CID_PRIVATE_EDGE_DETECT (V4L2_CID_PRIVATE_BASE+0)
-
+#define V4L2_CID_PRIVATE_TEST_PATTERN (V4L2_CID_PRIVATE_BASE+1)
+#define V4L2_CID_PRIVATE_TEST_OVERLAY (V4L2_CID_PRIVATE_BASE+2)
static struct ctrl sd_ctrls[] = {
/* This control is pac7302 only */
@@ -307,6 +338,34 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setedgedetect,
.get = sd_getedgedetect,
},
+ {
+ {
+ .id = V4L2_CID_PRIVATE_TEST_PATTERN,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Test Pattern",
+ .minimum = 0,
+ .maximum = 15,
+ .step = 1,
+#define TEST_PATTERN_DEF 0
+ .default_value = TEST_PATTERN_DEF,
+ },
+ .set = sd_settestpattern,
+ .get = sd_gettestpattern,
+ },
+ {
+ {
+ .id = V4L2_CID_PRIVATE_TEST_OVERLAY,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Test Overlay",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+#define TEST_OVERLAY_DEF 0
+ .default_value = TEST_OVERLAY_DEF,
+ },
+ .set = sd_settestoverlay,
+ .get = sd_gettestoverlay,
+ },
};
@@ -595,6 +654,9 @@ static int sd_config(struct gspca_dev *g
sd->hflip = HFLIP_DEF;
sd->vflip = VFLIP_DEF;
sd->edge_detect = EDGE_DETECT_DEF;
+ sd->test_pattern = TEST_PATTERN_DEF;
+ sd->test_overlay = TEST_OVERLAY_DEF;
+
return 0;
}
@@ -780,6 +842,23 @@ static int setedgedetect(struct gspca_de
return ret;
}
+static int settestpattern(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int ret;
+ __u8 data;
+
+ ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
+ data = sd->test_pattern | (sd->test_overlay ? 0x10 : 0x00);
+ if (0 <= ret)
+ ret = reg_w(gspca_dev, 0x72, data);
+
+ if (0 <= ret)
+ ret = reg_w(gspca_dev, 0xdc, 0x01);
+
+ return ret;
+}
+
/* this function is called at probe and resume time for pac7302 */
static int sd_init(struct gspca_dev *gspca_dev)
{
@@ -814,6 +893,8 @@ static int sd_start(struct gspca_dev *gs
sethvflip(gspca_dev);
if (0 <= ret)
ret = setedgedetect(gspca_dev);
+ if (0 <= ret)
+ ret = settestpattern(gspca_dev);
/* only resolution 640x480 is supported for pac7302 */
@@ -1224,6 +1305,127 @@ static int sd_getedgedetect(struct gspca
return 0;
}
+static int sd_settestpattern(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int ret = 0;
+
+ sd->test_pattern = val;
+ if (gspca_dev->streaming)
+ ret = settestpattern(gspca_dev);
+ if (0 <= ret)
+ ret = 0;
+ return ret;
+}
+
+static int sd_gettestpattern(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->test_pattern;
+ return 0;
+}
+
+static int sd_settestoverlay(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int ret = 0;
+
+ sd->test_overlay = val;
+ if (gspca_dev->streaming)
+ ret = settestpattern(gspca_dev);
+ if (0 <= ret)
+ ret = 0;
+ return ret;
+}
+
+static int sd_gettestoverlay(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->test_overlay;
+ return 0;
+}
+
+static int sd_querymenu(struct gspca_dev *gspca_dev,
+ struct v4l2_querymenu *menu)
+{
+ int ret = -EINVAL;
+
+ switch (menu->id) {
+ case V4L2_CID_PRIVATE_TEST_PATTERN :
+ switch (menu->index) {
+ case 0:
+ strcpy((char *) menu->name, "off");
+ ret = 0;
+ break;
+ case 1:
+ strcpy((char *) menu->name, "white");
+ ret = 0;
+ break;
+ case 2:
+ strcpy((char *) menu->name, "black");
+ ret = 0;
+ break;
+ case 3:
+ strcpy((char *) menu->name, "red");
+ ret = 0;
+ break;
+ case 4:
+ strcpy((char *) menu->name, "green");
+ ret = 0;
+ break;
+ case 5:
+ strcpy((char *) menu->name, "blue");
+ ret = 0;
+ break;
+ case 6:
+ strcpy((char *) menu->name, "cyan");
+ ret = 0;
+ break;
+ case 7:
+ strcpy((char *) menu->name, "magenta");
+ ret = 0;
+ break;
+ case 8:
+ strcpy((char *) menu->name, "yellow");
+ ret = 0;
+ break;
+ case 9:
+ strcpy((char *) menu->name, "color bars");
+ ret = 0;
+ break;
+ case 10:
+ strcpy((char *) menu->name, "high resolution color pattern");
+ ret = 0;
+ break;
+ case 11:
+ strcpy((char *) menu->name, "top-bottom gradient");
+ ret = 0;
+ break;
+ case 12:
+ strcpy((char *) menu->name, "left-right gradient");
+ ret = 0;
+ break;
+ case 13:
+ strcpy((char *) menu->name, "repeating left-right gradient");
+ ret = 0;
+ break;
+ case 14:
+ strcpy((char *) menu->name, "dark gray");
+ ret = 0;
+ break;
+ case 15:
+ strcpy((char *) menu->name, "dark gray 2");
+ ret = 0;
+ break;
+ }
+ break;
+ }
+ return ret;
+}
+
+
/* sub-driver description for pac7302 */
static struct sd_desc sd_desc = {
.name = MODULE_NAME,
@@ -1236,6 +1438,7 @@ static struct sd_desc sd_desc = {
.stop0 = sd_stop0,
.pkt_scan = sd_pkt_scan,
.dq_callback = do_autogain,
+ .querymenu = sd_querymenu,
};
/* -- module initialisation -- */