diff options
author | Hans de Goede <j.w.r.degoede@hhs.nl> | 2008-07-16 09:16:28 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-07-20 06:27:15 -0400 |
commit | 66f358211d4f8bf1a43e3aef9565c5c1454f73b3 (patch) | |
tree | da06b6dfdc5186d9e15834ced0d734130ebcf389 /drivers/media | |
parent | 5c6644f305650d3d533b67fc74a96e4a2ea0aa89 (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/media')
-rw-r--r-- | drivers/media/video/gspca/sonixb.c | 100 |
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); | |||
85 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | 86 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); |
86 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | 87 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); |
87 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | 88 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); |
89 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | ||
90 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | ||
88 | 91 | ||
89 | static struct ctrl sd_ctrls[] = { | 92 | static 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 | ||
152 | static struct v4l2_pix_format vga_mode[] = { | 169 | static 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 | ||
235 | static const __u8 initOv7630[] = { | 247 | static 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 | ||
732 | static 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 | ||
717 | static void do_autogain(struct gspca_dev *gspca_dev) | 761 | static 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 | ||
1210 | static 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 | |||
1220 | static 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 | |||
1228 | static 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 */ |
1165 | static const struct sd_desc sd_desc = { | 1250 | static 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 -- */ |