diff options
| -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; |
