diff options
-rw-r--r-- | drivers/media/video/gspca/ov519.c | 214 | ||||
-rw-r--r-- | include/linux/videodev2.h | 3 |
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); | |||
94 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); | 96 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); |
95 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); | 97 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); |
96 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); | 98 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); |
99 | static int sd_setautobrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
100 | static int sd_getautobrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
101 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | ||
102 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | ||
97 | static void setbrightness(struct gspca_dev *gspca_dev); | 103 | static void setbrightness(struct gspca_dev *gspca_dev); |
98 | static void setcontrast(struct gspca_dev *gspca_dev); | 104 | static void setcontrast(struct gspca_dev *gspca_dev); |
99 | static void setcolors(struct gspca_dev *gspca_dev); | 105 | static void setcolors(struct gspca_dev *gspca_dev); |
106 | static void setautobrightness(struct sd *sd); | ||
107 | static void setfreq(struct sd *sd); | ||
100 | 108 | ||
101 | static struct ctrl sd_ctrls[] = { | 109 | static 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 | ||
177 | static const struct v4l2_pix_format ov519_vga_mode[] = { | 230 | static 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; |
1666 | error: | 1731 | error: |
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 | ||
2551 | static 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 | |||
2559 | static 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 | |||
2485 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 2615 | static 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 | ||
2705 | static 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 | |||
2715 | static 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 | |||
2723 | static 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 | |||
2733 | static 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 | |||
2741 | static 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 */ |
2576 | static const struct sd_desc sd_desc = { | 2771 | static 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) |