aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/gspca/ov519.c214
-rw-r--r--include/linux/videodev2.h3
2 files changed, 207 insertions, 10 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 -- */
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index f24eceecc5a6..772d226cb5ca 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -894,9 +894,10 @@ enum v4l2_colorfx {
894 V4L2_COLORFX_BW = 1, 894 V4L2_COLORFX_BW = 1,
895 V4L2_COLORFX_SEPIA = 2, 895 V4L2_COLORFX_SEPIA = 2,
896}; 896};
897#define V4L2_CID_AUTOBRIGHTNESS (V4L2_CID_BASE+32)
897 898
898/* last CID + 1 */ 899/* last CID + 1 */
899#define V4L2_CID_LASTP1 (V4L2_CID_BASE+32) 900#define V4L2_CID_LASTP1 (V4L2_CID_BASE+33)
900 901
901/* MPEG-class control IDs defined by V4L2 */ 902/* MPEG-class control IDs defined by V4L2 */
902#define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) 903#define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900)