diff options
Diffstat (limited to 'drivers/media/video/gspca/ov534.c')
-rw-r--r-- | drivers/media/video/gspca/ov534.c | 146 |
1 files changed, 107 insertions, 39 deletions
diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 04753391de3e..b5acb1e4b4e7 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c | |||
@@ -34,6 +34,8 @@ | |||
34 | 34 | ||
35 | #include "gspca.h" | 35 | #include "gspca.h" |
36 | 36 | ||
37 | #include <linux/fixp-arith.h> | ||
38 | |||
37 | #define OV534_REG_ADDRESS 0xf1 /* sensor address */ | 39 | #define OV534_REG_ADDRESS 0xf1 /* sensor address */ |
38 | #define OV534_REG_SUBADDR 0xf2 | 40 | #define OV534_REG_SUBADDR 0xf2 |
39 | #define OV534_REG_WRITE 0xf3 | 41 | #define OV534_REG_WRITE 0xf3 |
@@ -53,6 +55,8 @@ MODULE_LICENSE("GPL"); | |||
53 | 55 | ||
54 | /* controls */ | 56 | /* controls */ |
55 | enum e_ctrl { | 57 | enum e_ctrl { |
58 | HUE, | ||
59 | SATURATION, | ||
56 | BRIGHTNESS, | 60 | BRIGHTNESS, |
57 | CONTRAST, | 61 | CONTRAST, |
58 | GAIN, | 62 | GAIN, |
@@ -63,7 +67,6 @@ enum e_ctrl { | |||
63 | SHARPNESS, | 67 | SHARPNESS, |
64 | HFLIP, | 68 | HFLIP, |
65 | VFLIP, | 69 | VFLIP, |
66 | COLORS, | ||
67 | LIGHTFREQ, | 70 | LIGHTFREQ, |
68 | NCTRLS /* number of controls */ | 71 | NCTRLS /* number of controls */ |
69 | }; | 72 | }; |
@@ -87,6 +90,8 @@ enum sensors { | |||
87 | }; | 90 | }; |
88 | 91 | ||
89 | /* V4L2 controls supported by the driver */ | 92 | /* V4L2 controls supported by the driver */ |
93 | static void sethue(struct gspca_dev *gspca_dev); | ||
94 | static void setsaturation(struct gspca_dev *gspca_dev); | ||
90 | static void setbrightness(struct gspca_dev *gspca_dev); | 95 | static void setbrightness(struct gspca_dev *gspca_dev); |
91 | static void setcontrast(struct gspca_dev *gspca_dev); | 96 | static void setcontrast(struct gspca_dev *gspca_dev); |
92 | static void setgain(struct gspca_dev *gspca_dev); | 97 | static void setgain(struct gspca_dev *gspca_dev); |
@@ -96,13 +101,36 @@ static void setawb(struct gspca_dev *gspca_dev); | |||
96 | static void setaec(struct gspca_dev *gspca_dev); | 101 | static void setaec(struct gspca_dev *gspca_dev); |
97 | static void setsharpness(struct gspca_dev *gspca_dev); | 102 | static void setsharpness(struct gspca_dev *gspca_dev); |
98 | static void sethvflip(struct gspca_dev *gspca_dev); | 103 | static void sethvflip(struct gspca_dev *gspca_dev); |
99 | static void setcolors(struct gspca_dev *gspca_dev); | ||
100 | static void setlightfreq(struct gspca_dev *gspca_dev); | 104 | static void setlightfreq(struct gspca_dev *gspca_dev); |
101 | 105 | ||
102 | static int sd_start(struct gspca_dev *gspca_dev); | 106 | static int sd_start(struct gspca_dev *gspca_dev); |
103 | static void sd_stopN(struct gspca_dev *gspca_dev); | 107 | static void sd_stopN(struct gspca_dev *gspca_dev); |
104 | 108 | ||
105 | static const struct ctrl sd_ctrls[] = { | 109 | static const struct ctrl sd_ctrls[] = { |
110 | [HUE] = { | ||
111 | { | ||
112 | .id = V4L2_CID_HUE, | ||
113 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
114 | .name = "Hue", | ||
115 | .minimum = -90, | ||
116 | .maximum = 90, | ||
117 | .step = 1, | ||
118 | .default_value = 0, | ||
119 | }, | ||
120 | .set_control = sethue | ||
121 | }, | ||
122 | [SATURATION] = { | ||
123 | { | ||
124 | .id = V4L2_CID_SATURATION, | ||
125 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
126 | .name = "Saturation", | ||
127 | .minimum = 0, | ||
128 | .maximum = 255, | ||
129 | .step = 1, | ||
130 | .default_value = 64, | ||
131 | }, | ||
132 | .set_control = setsaturation | ||
133 | }, | ||
106 | [BRIGHTNESS] = { | 134 | [BRIGHTNESS] = { |
107 | { | 135 | { |
108 | .id = V4L2_CID_BRIGHTNESS, | 136 | .id = V4L2_CID_BRIGHTNESS, |
@@ -223,18 +251,6 @@ static const struct ctrl sd_ctrls[] = { | |||
223 | }, | 251 | }, |
224 | .set_control = sethvflip | 252 | .set_control = sethvflip |
225 | }, | 253 | }, |
226 | [COLORS] = { | ||
227 | { | ||
228 | .id = V4L2_CID_SATURATION, | ||
229 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
230 | .name = "Saturation", | ||
231 | .minimum = 0, | ||
232 | .maximum = 6, | ||
233 | .step = 1, | ||
234 | .default_value = 3, | ||
235 | }, | ||
236 | .set_control = setcolors | ||
237 | }, | ||
238 | [LIGHTFREQ] = { | 254 | [LIGHTFREQ] = { |
239 | { | 255 | { |
240 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | 256 | .id = V4L2_CID_POWER_LINE_FREQUENCY, |
@@ -684,7 +700,7 @@ static const u8 sensor_init_772x[][2] = { | |||
684 | { 0x9c, 0x20 }, | 700 | { 0x9c, 0x20 }, |
685 | { 0x9e, 0x81 }, | 701 | { 0x9e, 0x81 }, |
686 | 702 | ||
687 | { 0xa6, 0x04 }, | 703 | { 0xa6, 0x07 }, |
688 | { 0x7e, 0x0c }, | 704 | { 0x7e, 0x0c }, |
689 | { 0x7f, 0x16 }, | 705 | { 0x7f, 0x16 }, |
690 | { 0x80, 0x2a }, | 706 | { 0x80, 0x2a }, |
@@ -955,6 +971,74 @@ static void set_frame_rate(struct gspca_dev *gspca_dev) | |||
955 | PDEBUG(D_PROBE, "frame_rate: %d", r->fps); | 971 | PDEBUG(D_PROBE, "frame_rate: %d", r->fps); |
956 | } | 972 | } |
957 | 973 | ||
974 | static void sethue(struct gspca_dev *gspca_dev) | ||
975 | { | ||
976 | struct sd *sd = (struct sd *) gspca_dev; | ||
977 | int val; | ||
978 | |||
979 | val = sd->ctrls[HUE].val; | ||
980 | if (sd->sensor == SENSOR_OV767x) { | ||
981 | /* TBD */ | ||
982 | } else { | ||
983 | s16 huesin; | ||
984 | s16 huecos; | ||
985 | |||
986 | /* fixp_sin and fixp_cos accept only positive values, while | ||
987 | * our val is between -90 and 90 | ||
988 | */ | ||
989 | val += 360; | ||
990 | |||
991 | /* According to the datasheet the registers expect HUESIN and | ||
992 | * HUECOS to be the result of the trigonometric functions, | ||
993 | * scaled by 0x80. | ||
994 | * | ||
995 | * The 0x100 here represents the maximun absolute value | ||
996 | * returned byt fixp_sin and fixp_cos, so the scaling will | ||
997 | * consider the result like in the interval [-1.0, 1.0]. | ||
998 | */ | ||
999 | huesin = fixp_sin(val) * 0x80 / 0x100; | ||
1000 | huecos = fixp_cos(val) * 0x80 / 0x100; | ||
1001 | |||
1002 | if (huesin < 0) { | ||
1003 | sccb_reg_write(gspca_dev, 0xab, | ||
1004 | sccb_reg_read(gspca_dev, 0xab) | 0x2); | ||
1005 | huesin = -huesin; | ||
1006 | } else { | ||
1007 | sccb_reg_write(gspca_dev, 0xab, | ||
1008 | sccb_reg_read(gspca_dev, 0xab) & ~0x2); | ||
1009 | |||
1010 | } | ||
1011 | sccb_reg_write(gspca_dev, 0xa9, (u8)huecos); | ||
1012 | sccb_reg_write(gspca_dev, 0xaa, (u8)huesin); | ||
1013 | } | ||
1014 | } | ||
1015 | |||
1016 | static void setsaturation(struct gspca_dev *gspca_dev) | ||
1017 | { | ||
1018 | struct sd *sd = (struct sd *) gspca_dev; | ||
1019 | int val; | ||
1020 | |||
1021 | val = sd->ctrls[SATURATION].val; | ||
1022 | if (sd->sensor == SENSOR_OV767x) { | ||
1023 | int i; | ||
1024 | static u8 color_tb[][6] = { | ||
1025 | {0x42, 0x42, 0x00, 0x11, 0x30, 0x41}, | ||
1026 | {0x52, 0x52, 0x00, 0x16, 0x3c, 0x52}, | ||
1027 | {0x66, 0x66, 0x00, 0x1b, 0x4b, 0x66}, | ||
1028 | {0x80, 0x80, 0x00, 0x22, 0x5e, 0x80}, | ||
1029 | {0x9a, 0x9a, 0x00, 0x29, 0x71, 0x9a}, | ||
1030 | {0xb8, 0xb8, 0x00, 0x31, 0x87, 0xb8}, | ||
1031 | {0xdd, 0xdd, 0x00, 0x3b, 0xa2, 0xdd}, | ||
1032 | }; | ||
1033 | |||
1034 | for (i = 0; i < ARRAY_SIZE(color_tb[0]); i++) | ||
1035 | sccb_reg_write(gspca_dev, 0x4f + i, color_tb[val][i]); | ||
1036 | } else { | ||
1037 | sccb_reg_write(gspca_dev, 0xa7, val); /* U saturation */ | ||
1038 | sccb_reg_write(gspca_dev, 0xa8, val); /* V saturation */ | ||
1039 | } | ||
1040 | } | ||
1041 | |||
958 | static void setbrightness(struct gspca_dev *gspca_dev) | 1042 | static void setbrightness(struct gspca_dev *gspca_dev) |
959 | { | 1043 | { |
960 | struct sd *sd = (struct sd *) gspca_dev; | 1044 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -1132,26 +1216,6 @@ static void sethvflip(struct gspca_dev *gspca_dev) | |||
1132 | } | 1216 | } |
1133 | } | 1217 | } |
1134 | 1218 | ||
1135 | static void setcolors(struct gspca_dev *gspca_dev) | ||
1136 | { | ||
1137 | struct sd *sd = (struct sd *) gspca_dev; | ||
1138 | u8 val; | ||
1139 | int i; | ||
1140 | static u8 color_tb[][6] = { | ||
1141 | {0x42, 0x42, 0x00, 0x11, 0x30, 0x41}, | ||
1142 | {0x52, 0x52, 0x00, 0x16, 0x3c, 0x52}, | ||
1143 | {0x66, 0x66, 0x00, 0x1b, 0x4b, 0x66}, | ||
1144 | {0x80, 0x80, 0x00, 0x22, 0x5e, 0x80}, | ||
1145 | {0x9a, 0x9a, 0x00, 0x29, 0x71, 0x9a}, | ||
1146 | {0xb8, 0xb8, 0x00, 0x31, 0x87, 0xb8}, | ||
1147 | {0xdd, 0xdd, 0x00, 0x3b, 0xa2, 0xdd}, | ||
1148 | }; | ||
1149 | |||
1150 | val = sd->ctrls[COLORS].val; | ||
1151 | for (i = 0; i < ARRAY_SIZE(color_tb[0]); i++) | ||
1152 | sccb_reg_write(gspca_dev, 0x4f + i, color_tb[val][i]); | ||
1153 | } | ||
1154 | |||
1155 | static void setlightfreq(struct gspca_dev *gspca_dev) | 1219 | static void setlightfreq(struct gspca_dev *gspca_dev) |
1156 | { | 1220 | { |
1157 | struct sd *sd = (struct sd *) gspca_dev; | 1221 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -1225,9 +1289,13 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1225 | 1289 | ||
1226 | if ((sensor_id & 0xfff0) == 0x7670) { | 1290 | if ((sensor_id & 0xfff0) == 0x7670) { |
1227 | sd->sensor = SENSOR_OV767x; | 1291 | sd->sensor = SENSOR_OV767x; |
1228 | gspca_dev->ctrl_dis = (1 << GAIN) | | 1292 | gspca_dev->ctrl_dis = (1 << HUE) | |
1293 | (1 << GAIN) | | ||
1229 | (1 << AGC) | | 1294 | (1 << AGC) | |
1230 | (1 << SHARPNESS); /* auto */ | 1295 | (1 << SHARPNESS); /* auto */ |
1296 | sd->ctrls[SATURATION].min = 0, | ||
1297 | sd->ctrls[SATURATION].max = 6, | ||
1298 | sd->ctrls[SATURATION].def = 3, | ||
1231 | sd->ctrls[BRIGHTNESS].min = -127; | 1299 | sd->ctrls[BRIGHTNESS].min = -127; |
1232 | sd->ctrls[BRIGHTNESS].max = 127; | 1300 | sd->ctrls[BRIGHTNESS].max = 127; |
1233 | sd->ctrls[BRIGHTNESS].def = 0; | 1301 | sd->ctrls[BRIGHTNESS].def = 0; |
@@ -1243,7 +1311,6 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1243 | gspca_dev->cam.nmodes = ARRAY_SIZE(ov767x_mode); | 1311 | gspca_dev->cam.nmodes = ARRAY_SIZE(ov767x_mode); |
1244 | } else { | 1312 | } else { |
1245 | sd->sensor = SENSOR_OV772x; | 1313 | sd->sensor = SENSOR_OV772x; |
1246 | gspca_dev->ctrl_dis = (1 << COLORS); | ||
1247 | gspca_dev->cam.bulk = 1; | 1314 | gspca_dev->cam.bulk = 1; |
1248 | gspca_dev->cam.bulk_size = 16384; | 1315 | gspca_dev->cam.bulk_size = 16384; |
1249 | gspca_dev->cam.bulk_nurbs = 2; | 1316 | gspca_dev->cam.bulk_nurbs = 2; |
@@ -1302,6 +1369,9 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1302 | 1369 | ||
1303 | set_frame_rate(gspca_dev); | 1370 | set_frame_rate(gspca_dev); |
1304 | 1371 | ||
1372 | if (!(gspca_dev->ctrl_dis & (1 << HUE))) | ||
1373 | sethue(gspca_dev); | ||
1374 | setsaturation(gspca_dev); | ||
1305 | if (!(gspca_dev->ctrl_dis & (1 << AGC))) | 1375 | if (!(gspca_dev->ctrl_dis & (1 << AGC))) |
1306 | setagc(gspca_dev); | 1376 | setagc(gspca_dev); |
1307 | setawb(gspca_dev); | 1377 | setawb(gspca_dev); |
@@ -1314,8 +1384,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1314 | if (!(gspca_dev->ctrl_dis & (1 << SHARPNESS))) | 1384 | if (!(gspca_dev->ctrl_dis & (1 << SHARPNESS))) |
1315 | setsharpness(gspca_dev); | 1385 | setsharpness(gspca_dev); |
1316 | sethvflip(gspca_dev); | 1386 | sethvflip(gspca_dev); |
1317 | if (!(gspca_dev->ctrl_dis & (1 << COLORS))) | ||
1318 | setcolors(gspca_dev); | ||
1319 | setlightfreq(gspca_dev); | 1387 | setlightfreq(gspca_dev); |
1320 | 1388 | ||
1321 | ov534_set_led(gspca_dev, 1); | 1389 | ov534_set_led(gspca_dev, 1); |