diff options
Diffstat (limited to 'drivers/media/video/gspca/sonixb.c')
-rw-r--r-- | drivers/media/video/gspca/sonixb.c | 96 |
1 files changed, 67 insertions, 29 deletions
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 5033810f56fc..7f67148a5230 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c | |||
@@ -20,6 +20,26 @@ | |||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
21 | */ | 21 | */ |
22 | 22 | ||
23 | /* Some documentation on known sonixb registers: | ||
24 | |||
25 | Reg Use | ||
26 | 0x10 high nibble red gain low nibble blue gain | ||
27 | 0x11 low nibble green gain | ||
28 | 0x12 hstart | ||
29 | 0x13 vstart | ||
30 | 0x15 hsize (hsize = register-value * 16) | ||
31 | 0x16 vsize (vsize = register-value * 16) | ||
32 | 0x17 bit 0 toggle compression quality (according to sn9c102 driver) | ||
33 | 0x18 bit 7 enables compression, bit 4-5 set image down scaling: | ||
34 | 00 scale 1, 01 scale 1/2, 10, scale 1/4 | ||
35 | 0x19 high-nibble is sensor clock divider, changes exposure on sensors which | ||
36 | use a clock generated by the bridge. Some sensors have their own clock. | ||
37 | 0x1c auto_exposure area (for avg_lum) startx (startx = register-value * 32) | ||
38 | 0x1d auto_exposure area (for avg_lum) starty (starty = register-value * 32) | ||
39 | 0x1e auto_exposure area (for avg_lum) stopx (hsize = (0x1e - 0x1c) * 32) | ||
40 | 0x1f auto_exposure area (for avg_lum) stopy (vsize = (0x1f - 0x1d) * 32) | ||
41 | */ | ||
42 | |||
23 | #define MODULE_NAME "sonixb" | 43 | #define MODULE_NAME "sonixb" |
24 | 44 | ||
25 | #include "gspca.h" | 45 | #include "gspca.h" |
@@ -74,10 +94,10 @@ struct sensor_data { | |||
74 | /* sensor_data flags */ | 94 | /* sensor_data flags */ |
75 | #define F_GAIN 0x01 /* has gain */ | 95 | #define F_GAIN 0x01 /* has gain */ |
76 | #define F_SIF 0x02 /* sif or vga */ | 96 | #define F_SIF 0x02 /* sif or vga */ |
77 | #define F_RAW 0x04 /* sensor tested ok with raw bayer mode */ | ||
78 | 97 | ||
79 | /* priv field of struct v4l2_pix_format flags (do not use low nibble!) */ | 98 | /* priv field of struct v4l2_pix_format flags (do not use low nibble!) */ |
80 | #define MODE_RAW 0x10 /* raw bayer mode */ | 99 | #define MODE_RAW 0x10 /* raw bayer mode */ |
100 | #define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */ | ||
81 | 101 | ||
82 | /* ctrl_dis helper macros */ | 102 | /* ctrl_dis helper macros */ |
83 | #define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)) | 103 | #define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)) |
@@ -211,7 +231,7 @@ static struct ctrl sd_ctrls[] = { | |||
211 | static struct v4l2_pix_format vga_mode[] = { | 231 | static struct v4l2_pix_format vga_mode[] = { |
212 | {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | 232 | {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, |
213 | .bytesperline = 160, | 233 | .bytesperline = 160, |
214 | .sizeimage = 160 * 120, | 234 | .sizeimage = 160 * 120 * 5 / 4, |
215 | .colorspace = V4L2_COLORSPACE_SRGB, | 235 | .colorspace = V4L2_COLORSPACE_SRGB, |
216 | .priv = 2 | MODE_RAW}, | 236 | .priv = 2 | MODE_RAW}, |
217 | {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, | 237 | {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, |
@@ -231,9 +251,19 @@ static struct v4l2_pix_format vga_mode[] = { | |||
231 | .priv = 0}, | 251 | .priv = 0}, |
232 | }; | 252 | }; |
233 | static struct v4l2_pix_format sif_mode[] = { | 253 | static struct v4l2_pix_format sif_mode[] = { |
254 | {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
255 | .bytesperline = 160, | ||
256 | .sizeimage = 160 * 120, | ||
257 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
258 | .priv = 1 | MODE_RAW | MODE_REDUCED_SIF}, | ||
259 | {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, | ||
260 | .bytesperline = 160, | ||
261 | .sizeimage = 160 * 120 * 5 / 4, | ||
262 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
263 | .priv = 1 | MODE_REDUCED_SIF}, | ||
234 | {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | 264 | {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, |
235 | .bytesperline = 176, | 265 | .bytesperline = 176, |
236 | .sizeimage = 176 * 144, | 266 | .sizeimage = 176 * 144 * 5 / 4, |
237 | .colorspace = V4L2_COLORSPACE_SRGB, | 267 | .colorspace = V4L2_COLORSPACE_SRGB, |
238 | .priv = 1 | MODE_RAW}, | 268 | .priv = 1 | MODE_RAW}, |
239 | {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, | 269 | {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, |
@@ -241,6 +271,11 @@ static struct v4l2_pix_format sif_mode[] = { | |||
241 | .sizeimage = 176 * 144 * 5 / 4, | 271 | .sizeimage = 176 * 144 * 5 / 4, |
242 | .colorspace = V4L2_COLORSPACE_SRGB, | 272 | .colorspace = V4L2_COLORSPACE_SRGB, |
243 | .priv = 1}, | 273 | .priv = 1}, |
274 | {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, | ||
275 | .bytesperline = 320, | ||
276 | .sizeimage = 320 * 240 * 5 / 4, | ||
277 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
278 | .priv = 0 | MODE_REDUCED_SIF}, | ||
244 | {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, | 279 | {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, |
245 | .bytesperline = 352, | 280 | .bytesperline = 352, |
246 | .sizeimage = 352 * 288 * 5 / 4, | 281 | .sizeimage = 352 * 288 * 5 / 4, |
@@ -266,7 +301,7 @@ static const __u8 initOv6650[] = { | |||
266 | 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, | 301 | 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, |
267 | 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 302 | 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
268 | 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b, | 303 | 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b, |
269 | 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00 | 304 | 0x10, 0x1d, 0x10, 0x02, 0x02, 0x09, 0x07 |
270 | }; | 305 | }; |
271 | static const __u8 ov6650_sensor_init[][8] = | 306 | static const __u8 ov6650_sensor_init[][8] = |
272 | { | 307 | { |
@@ -350,7 +385,7 @@ static const __u8 initPas106[] = { | |||
350 | 0x00, 0x00, | 385 | 0x00, 0x00, |
351 | 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, | 386 | 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, |
352 | 0x16, 0x12, 0x24, COMP1, MCK_INIT1, | 387 | 0x16, 0x12, 0x24, COMP1, MCK_INIT1, |
353 | 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c | 388 | 0x18, 0x10, 0x02, 0x02, 0x09, 0x07 |
354 | }; | 389 | }; |
355 | /* compression 0x86 mckinit1 0x2b */ | 390 | /* compression 0x86 mckinit1 0x2b */ |
356 | static const __u8 pas106_sensor_init[][8] = { | 391 | static const __u8 pas106_sensor_init[][8] = { |
@@ -456,15 +491,14 @@ static const __u8 tas5130_sensor_init[][8] = { | |||
456 | 491 | ||
457 | struct sensor_data sensor_data[] = { | 492 | struct sensor_data sensor_data[] = { |
458 | SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), | 493 | SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), |
459 | SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF|F_RAW, 0, | 494 | SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), |
460 | 0x60), | ||
461 | SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, | 495 | SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, |
462 | F_GAIN, 0, 0x21), | 496 | F_GAIN, 0, 0x21), |
463 | SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ, | 497 | SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ, |
464 | 0), | 498 | 0), |
465 | SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, F_RAW, | 499 | SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, 0, |
466 | NO_EXPO|NO_FREQ, 0), | 500 | NO_EXPO|NO_FREQ, 0), |
467 | SENS(initTas5110, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF|F_RAW, | 501 | SENS(initTas5110, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF, |
468 | NO_BRIGHTNESS|NO_FREQ, 0), | 502 | NO_BRIGHTNESS|NO_FREQ, 0), |
469 | SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, | 503 | SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, |
470 | 0), | 504 | 0), |
@@ -834,10 +868,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
834 | cam->cam_mode = sif_mode; | 868 | cam->cam_mode = sif_mode; |
835 | cam->nmodes = ARRAY_SIZE(sif_mode); | 869 | cam->nmodes = ARRAY_SIZE(sif_mode); |
836 | } | 870 | } |
837 | if (!(sensor_data[sd->sensor].flags & F_RAW)) { | ||
838 | cam->cam_mode++; | ||
839 | cam->nmodes--; | ||
840 | } | ||
841 | sd->brightness = BRIGHTNESS_DEF; | 871 | sd->brightness = BRIGHTNESS_DEF; |
842 | sd->gain = GAIN_DEF; | 872 | sd->gain = GAIN_DEF; |
843 | sd->exposure = EXPOSURE_DEF; | 873 | sd->exposure = EXPOSURE_DEF; |
@@ -864,31 +894,39 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
864 | static void sd_start(struct gspca_dev *gspca_dev) | 894 | static void sd_start(struct gspca_dev *gspca_dev) |
865 | { | 895 | { |
866 | struct sd *sd = (struct sd *) gspca_dev; | 896 | struct sd *sd = (struct sd *) gspca_dev; |
897 | struct cam *cam = &gspca_dev->cam; | ||
867 | int mode, l; | 898 | int mode, l; |
868 | const __u8 *sn9c10x; | 899 | const __u8 *sn9c10x; |
869 | __u8 reg17_19[3]; | 900 | __u8 reg12_19[8]; |
870 | 901 | ||
871 | mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 0x07; | 902 | mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07; |
872 | sn9c10x = sensor_data[sd->sensor].bridge_init[sd->bridge]; | 903 | sn9c10x = sensor_data[sd->sensor].bridge_init[sd->bridge]; |
873 | l = sensor_data[sd->sensor].bridge_init_size[sd->bridge]; | 904 | l = sensor_data[sd->sensor].bridge_init_size[sd->bridge]; |
874 | reg17_19[0] = sn9c10x[0x17 - 1]; | 905 | memcpy(reg12_19, &sn9c10x[0x12 - 1], 8); |
875 | reg17_19[1] = sn9c10x[0x18 - 1] | (mode << 4); | 906 | reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4); |
876 | reg17_19[2] = sn9c10x[0x19 - 1]; | ||
877 | /* Special cases where reg 17 and or 19 value depends on mode */ | 907 | /* Special cases where reg 17 and or 19 value depends on mode */ |
878 | switch (sd->sensor) { | 908 | switch (sd->sensor) { |
879 | case SENSOR_PAS202: | 909 | case SENSOR_PAS202: |
880 | reg17_19[0] = mode ? 0x24 : 0x20; | 910 | reg12_19[5] = mode ? 0x24 : 0x20; |
881 | break; | 911 | break; |
882 | case SENSOR_TAS5130CXX: | 912 | case SENSOR_TAS5130CXX: |
883 | /* probably not mode specific at all most likely the upper | 913 | /* probably not mode specific at all most likely the upper |
884 | nibble of 0x19 is exposure (clock divider) just as with | 914 | nibble of 0x19 is exposure (clock divider) just as with |
885 | the tas5110, we need someone to test this. */ | 915 | the tas5110, we need someone to test this. */ |
886 | reg17_19[2] = mode ? 0x23 : 0x43; | 916 | reg12_19[7] = mode ? 0x23 : 0x43; |
887 | break; | 917 | break; |
888 | } | 918 | } |
889 | /* Disable compression when the raw bayer format has been selected */ | 919 | /* Disable compression when the raw bayer format has been selected */ |
890 | if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) | 920 | if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) |
891 | reg17_19[1] &= ~0x80; | 921 | reg12_19[6] &= ~0x80; |
922 | |||
923 | /* Vga mode emulation on SIF sensor? */ | ||
924 | if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) { | ||
925 | reg12_19[0] += 16; /* 0x12: hstart adjust */ | ||
926 | reg12_19[1] += 24; /* 0x13: vstart adjust */ | ||
927 | reg12_19[3] = 320 / 16; /* 0x15: hsize */ | ||
928 | reg12_19[4] = 240 / 16; /* 0x16: vsize */ | ||
929 | } | ||
892 | 930 | ||
893 | /* reg 0x01 bit 2 video transfert on */ | 931 | /* reg 0x01 bit 2 video transfert on */ |
894 | reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1); | 932 | reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1); |
@@ -907,24 +945,24 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
907 | sd->bridge]); | 945 | sd->bridge]); |
908 | 946 | ||
909 | /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */ | 947 | /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */ |
910 | reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2); | 948 | reg_w(gspca_dev, 0x15, ®12_19[3], 2); |
911 | /* compression register */ | 949 | /* compression register */ |
912 | reg_w(gspca_dev, 0x18, ®17_19[1], 1); | 950 | reg_w(gspca_dev, 0x18, ®12_19[6], 1); |
913 | /* H_start */ | 951 | /* H_start */ |
914 | reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1); | 952 | reg_w(gspca_dev, 0x12, ®12_19[0], 1); |
915 | /* V_START */ | 953 | /* V_START */ |
916 | reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1); | 954 | reg_w(gspca_dev, 0x13, ®12_19[1], 1); |
917 | /* reset 0x17 SensorClk enable inv Clk 0x60 */ | 955 | /* reset 0x17 SensorClk enable inv Clk 0x60 */ |
918 | /*fixme: ov7630 [17]=68 8f (+20 if 102)*/ | 956 | /*fixme: ov7630 [17]=68 8f (+20 if 102)*/ |
919 | reg_w(gspca_dev, 0x17, ®17_19[0], 1); | 957 | reg_w(gspca_dev, 0x17, ®12_19[5], 1); |
920 | /*MCKSIZE ->3 */ /*fixme: not ov7630*/ | 958 | /*MCKSIZE ->3 */ /*fixme: not ov7630*/ |
921 | reg_w(gspca_dev, 0x19, ®17_19[2], 1); | 959 | reg_w(gspca_dev, 0x19, ®12_19[7], 1); |
922 | /* AE_STRX AE_STRY AE_ENDX AE_ENDY */ | 960 | /* AE_STRX AE_STRY AE_ENDX AE_ENDY */ |
923 | reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4); | 961 | reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4); |
924 | /* Enable video transfert */ | 962 | /* Enable video transfert */ |
925 | reg_w(gspca_dev, 0x01, &sn9c10x[0], 1); | 963 | reg_w(gspca_dev, 0x01, &sn9c10x[0], 1); |
926 | /* Compression */ | 964 | /* Compression */ |
927 | reg_w(gspca_dev, 0x18, ®17_19[1], 2); | 965 | reg_w(gspca_dev, 0x18, ®12_19[6], 2); |
928 | msleep(20); | 966 | msleep(20); |
929 | 967 | ||
930 | sd->reg11 = -1; | 968 | sd->reg11 = -1; |