aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHans de Goede <j.w.r.degoede@hhs.nl>2008-07-16 09:16:28 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-07-20 06:27:15 -0400
commit66f358211d4f8bf1a43e3aef9565c5c1454f73b3 (patch)
treeda06b6dfdc5186d9e15834ced0d734130ebcf389 /drivers
parent5c6644f305650d3d533b67fc74a96e4a2ea0aa89 (diff)
V4L/DVB (8364): gspca: Support of powerline frequency for ov6650.
Signed-off-by: Hans de Goede <j.w.r.degoede@hhs.nl> Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/gspca/sonixb.c100
1 files changed, 93 insertions, 7 deletions
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
index a512772664a3..51435e3dbb10 100644
--- a/drivers/media/video/gspca/sonixb.c
+++ b/drivers/media/video/gspca/sonixb.c
@@ -44,6 +44,7 @@ struct sd {
44 unsigned char brightness; 44 unsigned char brightness;
45 unsigned char autogain; 45 unsigned char autogain;
46 unsigned char autogain_ignore_frames; 46 unsigned char autogain_ignore_frames;
47 unsigned char freq; /* light freq filter setting */
47 48
48 unsigned char fr_h_sz; /* size of frame header */ 49 unsigned char fr_h_sz; /* size of frame header */
49 char sensor; /* Type of image sensor chip */ 50 char sensor; /* Type of image sensor chip */
@@ -85,6 +86,8 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
85static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); 86static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
86static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); 87static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
87static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); 88static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
89static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
90static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
88 91
89static struct ctrl sd_ctrls[] = { 92static struct ctrl sd_ctrls[] = {
90 { 93 {
@@ -147,6 +150,20 @@ static struct ctrl sd_ctrls[] = {
147 .set = sd_setautogain, 150 .set = sd_setautogain,
148 .get = sd_getautogain, 151 .get = sd_getautogain,
149 }, 152 },
153 {
154 {
155 .id = V4L2_CID_POWER_LINE_FREQUENCY,
156 .type = V4L2_CTRL_TYPE_MENU,
157 .name = "Light frequency filter",
158 .minimum = 0,
159 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
160 .step = 1,
161#define FREQ_DEF 1
162 .default_value = FREQ_DEF,
163 },
164 .set = sd_setfreq,
165 .get = sd_getfreq,
166 },
150}; 167};
151 168
152static struct v4l2_pix_format vga_mode[] = { 169static struct v4l2_pix_format vga_mode[] = {
@@ -225,11 +242,6 @@ static const __u8 ov6650_sensor_init[][8] =
225 /* Some more unknown stuff */ 242 /* Some more unknown stuff */
226 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10}, 243 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
227 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */ 244 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
228 {0xa0, 0x60, 0x10, 0x57, 0x99, 0x04, 0x94, 0x16},
229 /* Framerate adjust register for artificial light 50 hz flicker
230 compensation, identical to ov6630 0x2b register, see 6630 datasheet.
231 0x4f -> (30 fps -> 25 fps), 0x00 -> no adjustment */
232 {0xa0, 0x60, 0x2b, 0x4f, 0x99, 0x04, 0x94, 0x15},
233}; 245};
234 246
235static const __u8 initOv7630[] = { 247static const __u8 initOv7630[] = {
@@ -657,8 +669,12 @@ static void setexposure(struct gspca_dev *gspca_dev)
657 */ 669 */
658 __u8 i2c[] = {0xb0, 0x60, 0x10, 0x00, 0xc0, 0x00, 0x00, 0x10}; 670 __u8 i2c[] = {0xb0, 0x60, 0x10, 0x00, 0xc0, 0x00, 0x00, 0x10};
659 int reg10, reg11; 671 int reg10, reg11;
660 /* No clear idea why, but setting reg10 above this value 672 /* ov6645 datasheet says reg10_max is 9a, but that uses
661 results in no change */ 673 tline * 2 * reg10 as formula for calculating texpo, the
674 ov6650 probably uses the same formula as the 7730 which uses
675 tline * 4 * reg10, which explains why the reg10max we've
676 found experimentally for the ov6650 is exactly half that of
677 the ov6645. */
662 const int reg10_max = 0x4d; 678 const int reg10_max = 0x4d;
663 679
664 reg11 = (60 * sd->exposure + 999) / 1000; 680 reg11 = (60 * sd->exposure + 999) / 1000;
@@ -713,6 +729,34 @@ static void setexposure(struct gspca_dev *gspca_dev)
713 } 729 }
714} 730}
715 731
732static void setfreq(struct gspca_dev *gspca_dev)
733{
734 struct sd *sd = (struct sd *) gspca_dev;
735
736 switch (sd->sensor) {
737 case SENSOR_OV6650: {
738 /* Framerate adjust register for artificial light 50 hz flicker
739 compensation, identical to ov6630 0x2b register, see ov6630
740 datasheet.
741 0x4f -> (30 fps -> 25 fps), 0x00 -> no adjustment */
742 __u8 i2c[] = {0xa0, 0x60, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
743 switch (sd->freq) {
744 default:
745/* case 0: * no filter*/
746/* case 2: * 60 hz */
747 i2c[3] = 0;
748 break;
749 case 1: /* 50 hz */
750 i2c[3] = 0x4f;
751 break;
752 }
753 if (i2c_w(gspca_dev, i2c) < 0)
754 PDEBUG(D_ERR, "i2c error setfreq");
755 break;
756 }
757 }
758}
759
716 760
717static void do_autogain(struct gspca_dev *gspca_dev) 761static void do_autogain(struct gspca_dev *gspca_dev)
718{ 762{
@@ -746,6 +790,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
746 sd->fr_h_sz = 12; /* default size of the frame header */ 790 sd->fr_h_sz = 12; /* default size of the frame header */
747 sd->sd_desc.nctrls = 2; /* default nb of ctrls */ 791 sd->sd_desc.nctrls = 2; /* default nb of ctrls */
748 sd->autogain = AUTOGAIN_DEF; /* default is autogain active */ 792 sd->autogain = AUTOGAIN_DEF; /* default is autogain active */
793 sd->freq = FREQ_DEF;
749 794
750 product = id->idProduct; 795 product = id->idProduct;
751/* switch (id->idVendor) { */ 796/* switch (id->idVendor) { */
@@ -1004,6 +1049,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
1004 setgain(gspca_dev); 1049 setgain(gspca_dev);
1005 setbrightness(gspca_dev); 1050 setbrightness(gspca_dev);
1006 setexposure(gspca_dev); 1051 setexposure(gspca_dev);
1052 setfreq(gspca_dev);
1007 1053
1008 sd->autogain_ignore_frames = 0; 1054 sd->autogain_ignore_frames = 0;
1009 atomic_set(&sd->avg_lum, -1); 1055 atomic_set(&sd->avg_lum, -1);
@@ -1161,6 +1207,45 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1161 return 0; 1207 return 0;
1162} 1208}
1163 1209
1210static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1211{
1212 struct sd *sd = (struct sd *) gspca_dev;
1213
1214 sd->freq = val;
1215 if (gspca_dev->streaming)
1216 setfreq(gspca_dev);
1217 return 0;
1218}
1219
1220static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1221{
1222 struct sd *sd = (struct sd *) gspca_dev;
1223
1224 *val = sd->freq;
1225 return 0;
1226}
1227
1228static int sd_querymenu(struct gspca_dev *gspca_dev,
1229 struct v4l2_querymenu *menu)
1230{
1231 switch (menu->id) {
1232 case V4L2_CID_POWER_LINE_FREQUENCY:
1233 switch (menu->index) {
1234 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1235 strcpy((char *) menu->name, "NoFliker");
1236 return 0;
1237 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1238 strcpy((char *) menu->name, "50 Hz");
1239 return 0;
1240 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1241 strcpy((char *) menu->name, "60 Hz");
1242 return 0;
1243 }
1244 break;
1245 }
1246 return -EINVAL;
1247}
1248
1164/* sub-driver description */ 1249/* sub-driver description */
1165static const struct sd_desc sd_desc = { 1250static const struct sd_desc sd_desc = {
1166 .name = MODULE_NAME, 1251 .name = MODULE_NAME,
@@ -1173,6 +1258,7 @@ static const struct sd_desc sd_desc = {
1173 .stop0 = sd_stop0, 1258 .stop0 = sd_stop0,
1174 .close = sd_close, 1259 .close = sd_close,
1175 .pkt_scan = sd_pkt_scan, 1260 .pkt_scan = sd_pkt_scan,
1261 .querymenu = sd_querymenu,
1176}; 1262};
1177 1263
1178/* -- module initialisation -- */ 1264/* -- module initialisation -- */