aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/ov519.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2009-06-14 03:32:04 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-06-23 02:11:16 -0400
commit02ab18b0f497bed623814677577b76cc97234085 (patch)
tree4f110a6b30419cae8077546946cf221cfef5a8cb /drivers/media/video/gspca/ov519.c
parentb8bfb5fb348d939a96fc8f71996a2e5e48b4544b (diff)
V4L/DVB (12072): gspca-ov519: add extra controls
This patch adds autobrightness (so that it can be turned off to make the already present brightness control work) and light frequency filtering controls. The lightfreq control needed 2 different entries in the ctrls array, as the number of options differs depending on the sensor. Always one of the 2 entires is disabled ofcourse. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/gspca/ov519.c')
-rw-r--r--drivers/media/video/gspca/ov519.c214
1 files changed, 205 insertions, 9 deletions
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
index 188866ac6cef..baa488dd33d8 100644
--- a/drivers/media/video/gspca/ov519.c
+++ b/drivers/media/video/gspca/ov519.c
@@ -65,6 +65,8 @@ struct sd {
65 __u8 colors; 65 __u8 colors;
66 __u8 hflip; 66 __u8 hflip;
67 __u8 vflip; 67 __u8 vflip;
68 __u8 autobrightness;
69 __u8 freq;
68 70
69 __u8 stopped; /* Streaming is temporarily paused */ 71 __u8 stopped; /* Streaming is temporarily paused */
70 72
@@ -94,11 +96,17 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
94static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); 96static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
95static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); 97static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
96static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); 98static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
99static int sd_setautobrightness(struct gspca_dev *gspca_dev, __s32 val);
100static int sd_getautobrightness(struct gspca_dev *gspca_dev, __s32 *val);
101static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
102static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
97static void setbrightness(struct gspca_dev *gspca_dev); 103static void setbrightness(struct gspca_dev *gspca_dev);
98static void setcontrast(struct gspca_dev *gspca_dev); 104static void setcontrast(struct gspca_dev *gspca_dev);
99static void setcolors(struct gspca_dev *gspca_dev); 105static void setcolors(struct gspca_dev *gspca_dev);
106static void setautobrightness(struct sd *sd);
107static void setfreq(struct sd *sd);
100 108
101static struct ctrl sd_ctrls[] = { 109static const struct ctrl sd_ctrls[] = {
102 { 110 {
103 { 111 {
104 .id = V4L2_CID_BRIGHTNESS, 112 .id = V4L2_CID_BRIGHTNESS,
@@ -141,7 +149,7 @@ static struct ctrl sd_ctrls[] = {
141 .set = sd_setcolors, 149 .set = sd_setcolors,
142 .get = sd_getcolors, 150 .get = sd_getcolors,
143 }, 151 },
144/* next controls work with ov7670 only */ 152/* The flip controls work with ov7670 only */
145#define HFLIP_IDX 3 153#define HFLIP_IDX 3
146 { 154 {
147 { 155 {
@@ -172,6 +180,51 @@ static struct ctrl sd_ctrls[] = {
172 .set = sd_setvflip, 180 .set = sd_setvflip,
173 .get = sd_getvflip, 181 .get = sd_getvflip,
174 }, 182 },
183#define AUTOBRIGHT_IDX 5
184 {
185 {
186 .id = V4L2_CID_AUTOBRIGHTNESS,
187 .type = V4L2_CTRL_TYPE_BOOLEAN,
188 .name = "Auto Brightness",
189 .minimum = 0,
190 .maximum = 1,
191 .step = 1,
192#define AUTOBRIGHT_DEF 1
193 .default_value = AUTOBRIGHT_DEF,
194 },
195 .set = sd_setautobrightness,
196 .get = sd_getautobrightness,
197 },
198#define FREQ_IDX 6
199 {
200 {
201 .id = V4L2_CID_POWER_LINE_FREQUENCY,
202 .type = V4L2_CTRL_TYPE_MENU,
203 .name = "Light frequency filter",
204 .minimum = 0,
205 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
206 .step = 1,
207#define FREQ_DEF 0
208 .default_value = FREQ_DEF,
209 },
210 .set = sd_setfreq,
211 .get = sd_getfreq,
212 },
213#define OV7670_FREQ_IDX 7
214 {
215 {
216 .id = V4L2_CID_POWER_LINE_FREQUENCY,
217 .type = V4L2_CTRL_TYPE_MENU,
218 .name = "Light frequency filter",
219 .minimum = 0,
220 .maximum = 3, /* 0: 0, 1: 50Hz, 2:60Hz 3: Auto Hz */
221 .step = 1,
222#define OV7670_FREQ_DEF 3
223 .default_value = OV7670_FREQ_DEF,
224 },
225 .set = sd_setfreq,
226 .get = sd_getfreq,
227 },
175}; 228};
176 229
177static const struct v4l2_pix_format ov519_vga_mode[] = { 230static const struct v4l2_pix_format ov519_vga_mode[] = {
@@ -416,7 +469,7 @@ static const struct ov_i2c_regvals norm_6x30[] = {
416 { 0x07, 0x2d }, /* Sharpness */ 469 { 0x07, 0x2d }, /* Sharpness */
417 { 0x0c, 0x20 }, 470 { 0x0c, 0x20 },
418 { 0x0d, 0x20 }, 471 { 0x0d, 0x20 },
419 { 0x0e, 0x20 }, 472 { 0x0e, 0xa0 }, /* Was 0x20, bit7 enables a 2x gain which we need */
420 { 0x0f, 0x05 }, 473 { 0x0f, 0x05 },
421 { 0x10, 0x9a }, 474 { 0x10, 0x9a },
422 { 0x11, 0x00 }, /* Pixel clock = fastest */ 475 { 0x11, 0x00 }, /* Pixel clock = fastest */
@@ -1659,9 +1712,21 @@ static int sd_config(struct gspca_dev *gspca_dev,
1659 sd->colors = COLOR_DEF; 1712 sd->colors = COLOR_DEF;
1660 sd->hflip = HFLIP_DEF; 1713 sd->hflip = HFLIP_DEF;
1661 sd->vflip = VFLIP_DEF; 1714 sd->vflip = VFLIP_DEF;
1662 if (sd->sensor != SEN_OV7670) 1715 sd->autobrightness = AUTOBRIGHT_DEF;
1663 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) 1716 if (sd->sensor == SEN_OV7670) {
1664 | (1 << VFLIP_IDX); 1717 sd->freq = OV7670_FREQ_DEF;
1718 gspca_dev->ctrl_dis = 1 << FREQ_IDX;
1719 } else {
1720 sd->freq = FREQ_DEF;
1721 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) |
1722 (1 << OV7670_FREQ_IDX);
1723 }
1724 if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670)
1725 gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT_IDX;
1726 /* OV8610 Frequency filter control should work but needs testing */
1727 if (sd->sensor == SEN_OV8610)
1728 gspca_dev->ctrl_dis |= 1 << FREQ_IDX;
1729
1665 return 0; 1730 return 0;
1666error: 1731error:
1667 PDEBUG(D_ERR, "OV519 Config failed"); 1732 PDEBUG(D_ERR, "OV519 Config failed");
@@ -2233,7 +2298,6 @@ static int set_ov_sensor_window(struct sd *sd)
2233 msleep(10); /* need to sleep between read and write to 2298 msleep(10); /* need to sleep between read and write to
2234 * same reg! */ 2299 * same reg! */
2235 i2c_w(sd, OV7670_REG_VREF, v); 2300 i2c_w(sd, OV7670_REG_VREF, v);
2236 sethvflip(sd);
2237 } else { 2301 } else {
2238 i2c_w(sd, 0x17, hwsbase); 2302 i2c_w(sd, 0x17, hwsbase);
2239 i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale)); 2303 i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale));
@@ -2268,6 +2332,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
2268 setcontrast(gspca_dev); 2332 setcontrast(gspca_dev);
2269 setbrightness(gspca_dev); 2333 setbrightness(gspca_dev);
2270 setcolors(gspca_dev); 2334 setcolors(gspca_dev);
2335 sethvflip(sd);
2336 setautobrightness(sd);
2337 setfreq(sd);
2271 2338
2272 ret = ov51x_restart(sd); 2339 ret = ov51x_restart(sd);
2273 if (ret < 0) 2340 if (ret < 0)
@@ -2394,8 +2461,7 @@ static void setbrightness(struct gspca_dev *gspca_dev)
2394 break; 2461 break;
2395 case SEN_OV7620: 2462 case SEN_OV7620:
2396 /* 7620 doesn't like manual changes when in auto mode */ 2463 /* 7620 doesn't like manual changes when in auto mode */
2397/*fixme 2464 if (!sd->autobrightness)
2398 * if (!sd->auto_brt) */
2399 i2c_w(sd, OV7610_REG_BRT, val); 2465 i2c_w(sd, OV7610_REG_BRT, val);
2400 break; 2466 break;
2401 case SEN_OV7670: 2467 case SEN_OV7670:
@@ -2482,6 +2548,70 @@ static void setcolors(struct gspca_dev *gspca_dev)
2482 } 2548 }
2483} 2549}
2484 2550
2551static void setautobrightness(struct sd *sd)
2552{
2553 if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670)
2554 return;
2555
2556 i2c_w_mask(sd, 0x2d, sd->autobrightness ? 0x10 : 0x00, 0x10);
2557}
2558
2559static void setfreq(struct sd *sd)
2560{
2561 if (sd->sensor == SEN_OV7670) {
2562 switch (sd->freq) {
2563 case 0: /* Banding filter disabled */
2564 i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_BFILT);
2565 break;
2566 case 1: /* 50 hz */
2567 i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT,
2568 OV7670_COM8_BFILT);
2569 i2c_w_mask(sd, OV7670_REG_COM11, 0x08, 0x18);
2570 break;
2571 case 2: /* 60 hz */
2572 i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT,
2573 OV7670_COM8_BFILT);
2574 i2c_w_mask(sd, OV7670_REG_COM11, 0x00, 0x18);
2575 break;
2576 case 3: /* Auto hz */
2577 i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT,
2578 OV7670_COM8_BFILT);
2579 i2c_w_mask(sd, OV7670_REG_COM11, OV7670_COM11_HZAUTO,
2580 0x18);
2581 break;
2582 }
2583 } else {
2584 switch (sd->freq) {
2585 case 0: /* Banding filter disabled */
2586 i2c_w_mask(sd, 0x2d, 0x00, 0x04);
2587 i2c_w_mask(sd, 0x2a, 0x00, 0x80);
2588 break;
2589 case 1: /* 50 hz (filter on and framerate adj) */
2590 i2c_w_mask(sd, 0x2d, 0x04, 0x04);
2591 i2c_w_mask(sd, 0x2a, 0x80, 0x80);
2592 /* 20 fps -> 16.667 fps */
2593 if (sd->sensor == SEN_OV6620 ||
2594 sd->sensor == SEN_OV6630)
2595 i2c_w(sd, 0x2b, 0x5e);
2596 else
2597 i2c_w(sd, 0x2b, 0xac);
2598 break;
2599 case 2: /* 60 hz (filter on, ...) */
2600 i2c_w_mask(sd, 0x2d, 0x04, 0x04);
2601 if (sd->sensor == SEN_OV6620 ||
2602 sd->sensor == SEN_OV6630) {
2603 /* 20 fps -> 15 fps */
2604 i2c_w_mask(sd, 0x2a, 0x80, 0x80);
2605 i2c_w(sd, 0x2b, 0xa8);
2606 } else {
2607 /* no framerate adj. */
2608 i2c_w_mask(sd, 0x2a, 0x00, 0x80);
2609 }
2610 break;
2611 }
2612 }
2613}
2614
2485static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) 2615static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
2486{ 2616{
2487 struct sd *sd = (struct sd *) gspca_dev; 2617 struct sd *sd = (struct sd *) gspca_dev;
@@ -2572,6 +2702,71 @@ static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
2572 return 0; 2702 return 0;
2573} 2703}
2574 2704
2705static int sd_setautobrightness(struct gspca_dev *gspca_dev, __s32 val)
2706{
2707 struct sd *sd = (struct sd *) gspca_dev;
2708
2709 sd->autobrightness = val;
2710 if (gspca_dev->streaming)
2711 setautobrightness(sd);
2712 return 0;
2713}
2714
2715static int sd_getautobrightness(struct gspca_dev *gspca_dev, __s32 *val)
2716{
2717 struct sd *sd = (struct sd *) gspca_dev;
2718
2719 *val = sd->autobrightness;
2720 return 0;
2721}
2722
2723static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
2724{
2725 struct sd *sd = (struct sd *) gspca_dev;
2726
2727 sd->freq = val;
2728 if (gspca_dev->streaming)
2729 setfreq(sd);
2730 return 0;
2731}
2732
2733static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
2734{
2735 struct sd *sd = (struct sd *) gspca_dev;
2736
2737 *val = sd->freq;
2738 return 0;
2739}
2740
2741static int sd_querymenu(struct gspca_dev *gspca_dev,
2742 struct v4l2_querymenu *menu)
2743{
2744 struct sd *sd = (struct sd *) gspca_dev;
2745
2746 switch (menu->id) {
2747 case V4L2_CID_POWER_LINE_FREQUENCY:
2748 switch (menu->index) {
2749 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
2750 strcpy((char *) menu->name, "NoFliker");
2751 return 0;
2752 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
2753 strcpy((char *) menu->name, "50 Hz");
2754 return 0;
2755 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
2756 strcpy((char *) menu->name, "60 Hz");
2757 return 0;
2758 case 3:
2759 if (sd->sensor != SEN_OV7670)
2760 return -EINVAL;
2761
2762 strcpy((char *) menu->name, "Automatic");
2763 return 0;
2764 }
2765 break;
2766 }
2767 return -EINVAL;
2768}
2769
2575/* sub-driver description */ 2770/* sub-driver description */
2576static const struct sd_desc sd_desc = { 2771static const struct sd_desc sd_desc = {
2577 .name = MODULE_NAME, 2772 .name = MODULE_NAME,
@@ -2582,6 +2777,7 @@ static const struct sd_desc sd_desc = {
2582 .start = sd_start, 2777 .start = sd_start,
2583 .stopN = sd_stopN, 2778 .stopN = sd_stopN,
2584 .pkt_scan = sd_pkt_scan, 2779 .pkt_scan = sd_pkt_scan,
2780 .querymenu = sd_querymenu,
2585}; 2781};
2586 2782
2587/* -- module initialisation -- */ 2783/* -- module initialisation -- */