diff options
Diffstat (limited to 'drivers/media/video/gspca/ov519.c')
-rw-r--r-- | drivers/media/video/gspca/ov519.c | 476 |
1 files changed, 225 insertions, 251 deletions
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 83139efc4629..b4f00ec0885c 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c | |||
@@ -40,14 +40,15 @@ struct sd { | |||
40 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 40 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
41 | 41 | ||
42 | /* Determined by sensor type */ | 42 | /* Determined by sensor type */ |
43 | short maxwidth; | 43 | char sif; |
44 | short maxheight; | ||
45 | 44 | ||
46 | unsigned char primary_i2c_slave; /* I2C write id of sensor */ | 45 | unsigned char primary_i2c_slave; /* I2C write id of sensor */ |
47 | 46 | ||
48 | unsigned char brightness; | 47 | unsigned char brightness; |
49 | unsigned char contrast; | 48 | unsigned char contrast; |
50 | unsigned char colors; | 49 | unsigned char colors; |
50 | __u8 hflip; | ||
51 | __u8 vflip; | ||
51 | 52 | ||
52 | char compress; /* Should the next frame be compressed? */ | 53 | char compress; /* Should the next frame be compressed? */ |
53 | char compress_inited; /* Are compression params uploaded? */ | 54 | char compress_inited; /* Are compression params uploaded? */ |
@@ -77,9 +78,12 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | |||
77 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | 78 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); |
78 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | 79 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); |
79 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | 80 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); |
81 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); | ||
82 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
83 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); | ||
84 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
80 | 85 | ||
81 | static struct ctrl sd_ctrls[] = { | 86 | static struct ctrl sd_ctrls[] = { |
82 | #define SD_BRIGHTNESS 0 | ||
83 | { | 87 | { |
84 | { | 88 | { |
85 | .id = V4L2_CID_BRIGHTNESS, | 89 | .id = V4L2_CID_BRIGHTNESS, |
@@ -88,12 +92,12 @@ static struct ctrl sd_ctrls[] = { | |||
88 | .minimum = 0, | 92 | .minimum = 0, |
89 | .maximum = 255, | 93 | .maximum = 255, |
90 | .step = 1, | 94 | .step = 1, |
91 | .default_value = 127, | 95 | #define BRIGHTNESS_DEF 127 |
96 | .default_value = BRIGHTNESS_DEF, | ||
92 | }, | 97 | }, |
93 | .set = sd_setbrightness, | 98 | .set = sd_setbrightness, |
94 | .get = sd_getbrightness, | 99 | .get = sd_getbrightness, |
95 | }, | 100 | }, |
96 | #define SD_CONTRAST 1 | ||
97 | { | 101 | { |
98 | { | 102 | { |
99 | .id = V4L2_CID_CONTRAST, | 103 | .id = V4L2_CID_CONTRAST, |
@@ -102,31 +106,61 @@ static struct ctrl sd_ctrls[] = { | |||
102 | .minimum = 0, | 106 | .minimum = 0, |
103 | .maximum = 255, | 107 | .maximum = 255, |
104 | .step = 1, | 108 | .step = 1, |
105 | .default_value = 127, | 109 | #define CONTRAST_DEF 127 |
110 | .default_value = CONTRAST_DEF, | ||
106 | }, | 111 | }, |
107 | .set = sd_setcontrast, | 112 | .set = sd_setcontrast, |
108 | .get = sd_getcontrast, | 113 | .get = sd_getcontrast, |
109 | }, | 114 | }, |
110 | #define SD_COLOR 2 | ||
111 | { | 115 | { |
112 | { | 116 | { |
113 | .id = V4L2_CID_SATURATION, | 117 | .id = V4L2_CID_SATURATION, |
114 | .type = V4L2_CTRL_TYPE_INTEGER, | 118 | .type = V4L2_CTRL_TYPE_INTEGER, |
115 | .name = "Saturation", | 119 | .name = "Color", |
116 | .minimum = 0, | 120 | .minimum = 0, |
117 | .maximum = 255, | 121 | .maximum = 255, |
118 | .step = 1, | 122 | .step = 1, |
119 | .default_value = 127, | 123 | #define COLOR_DEF 127 |
124 | .default_value = COLOR_DEF, | ||
120 | }, | 125 | }, |
121 | .set = sd_setcolors, | 126 | .set = sd_setcolors, |
122 | .get = sd_getcolors, | 127 | .get = sd_getcolors, |
123 | }, | 128 | }, |
129 | /* next controls work with ov7670 only */ | ||
130 | { | ||
131 | { | ||
132 | .id = V4L2_CID_HFLIP, | ||
133 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
134 | .name = "Mirror", | ||
135 | .minimum = 0, | ||
136 | .maximum = 1, | ||
137 | .step = 1, | ||
138 | #define HFLIP_DEF 0 | ||
139 | .default_value = HFLIP_DEF, | ||
140 | }, | ||
141 | .set = sd_sethflip, | ||
142 | .get = sd_gethflip, | ||
143 | }, | ||
144 | { | ||
145 | { | ||
146 | .id = V4L2_CID_VFLIP, | ||
147 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
148 | .name = "Vflip", | ||
149 | .minimum = 0, | ||
150 | .maximum = 1, | ||
151 | .step = 1, | ||
152 | #define VFLIP_DEF 0 | ||
153 | .default_value = VFLIP_DEF, | ||
154 | }, | ||
155 | .set = sd_setvflip, | ||
156 | .get = sd_getvflip, | ||
157 | }, | ||
124 | }; | 158 | }; |
125 | 159 | ||
126 | static struct v4l2_pix_format vga_mode[] = { | 160 | static struct v4l2_pix_format vga_mode[] = { |
127 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 161 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
128 | .bytesperline = 320, | 162 | .bytesperline = 320, |
129 | .sizeimage = 320 * 240 * 3 / 8 + 589, | 163 | .sizeimage = 320 * 240 * 3 / 8 + 590, |
130 | .colorspace = V4L2_COLORSPACE_JPEG, | 164 | .colorspace = V4L2_COLORSPACE_JPEG, |
131 | .priv = 1}, | 165 | .priv = 1}, |
132 | {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 166 | {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
@@ -138,12 +172,12 @@ static struct v4l2_pix_format vga_mode[] = { | |||
138 | static struct v4l2_pix_format sif_mode[] = { | 172 | static struct v4l2_pix_format sif_mode[] = { |
139 | {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 173 | {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
140 | .bytesperline = 176, | 174 | .bytesperline = 176, |
141 | .sizeimage = 176 * 144 * 3 / 8 + 589, | 175 | .sizeimage = 176 * 144 * 3 / 8 + 590, |
142 | .colorspace = V4L2_COLORSPACE_JPEG, | 176 | .colorspace = V4L2_COLORSPACE_JPEG, |
143 | .priv = 1}, | 177 | .priv = 1}, |
144 | {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 178 | {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
145 | .bytesperline = 352, | 179 | .bytesperline = 352, |
146 | .sizeimage = 352 * 288 * 3 / 8 + 589, | 180 | .sizeimage = 352 * 288 * 3 / 8 + 590, |
147 | .colorspace = V4L2_COLORSPACE_JPEG, | 181 | .colorspace = V4L2_COLORSPACE_JPEG, |
148 | .priv = 0}, | 182 | .priv = 0}, |
149 | }; | 183 | }; |
@@ -225,6 +259,7 @@ static struct v4l2_pix_format sif_mode[] = { | |||
225 | #define OV7670_REG_VSTART 0x19 /* Vert start high bits */ | 259 | #define OV7670_REG_VSTART 0x19 /* Vert start high bits */ |
226 | #define OV7670_REG_VSTOP 0x1a /* Vert stop high bits */ | 260 | #define OV7670_REG_VSTOP 0x1a /* Vert stop high bits */ |
227 | #define OV7670_REG_MVFP 0x1e /* Mirror / vflip */ | 261 | #define OV7670_REG_MVFP 0x1e /* Mirror / vflip */ |
262 | #define OV7670_MVFP_VFLIP 0x10 /* vertical flip */ | ||
228 | #define OV7670_MVFP_MIRROR 0x20 /* Mirror image */ | 263 | #define OV7670_MVFP_MIRROR 0x20 /* Mirror image */ |
229 | #define OV7670_REG_AEW 0x24 /* AGC upper limit */ | 264 | #define OV7670_REG_AEW 0x24 /* AGC upper limit */ |
230 | #define OV7670_REG_AEB 0x25 /* AGC lower limit */ | 265 | #define OV7670_REG_AEB 0x25 /* AGC lower limit */ |
@@ -258,16 +293,6 @@ static struct v4l2_pix_format sif_mode[] = { | |||
258 | #define OV7670_REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ | 293 | #define OV7670_REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ |
259 | #define OV7670_REG_BD60MAX 0xab /* 60hz banding step limit */ | 294 | #define OV7670_REG_BD60MAX 0xab /* 60hz banding step limit */ |
260 | 295 | ||
261 | struct ovsensor_window { | ||
262 | short x; | ||
263 | short y; | ||
264 | short width; | ||
265 | short height; | ||
266 | /* int format; */ | ||
267 | short quarter; /* Scale width and height down 2x */ | ||
268 | short clockdiv; /* Clock divisor setting */ | ||
269 | }; | ||
270 | |||
271 | static unsigned char ov7670_abs_to_sm(unsigned char v) | 296 | static unsigned char ov7670_abs_to_sm(unsigned char v) |
272 | { | 297 | { |
273 | if (v > 127) | 298 | if (v > 127) |
@@ -499,19 +524,6 @@ static int init_ov_sensor(struct sd *sd) | |||
499 | return 0; | 524 | return 0; |
500 | } | 525 | } |
501 | 526 | ||
502 | /* Switch on standard JPEG compression. Returns 0 for success. */ | ||
503 | static int ov519_init_compression(struct sd *sd) | ||
504 | { | ||
505 | if (!sd->compress_inited) { | ||
506 | if (reg_w_mask(sd, OV519_SYS_EN_CLK1, 1 << 2, 1 << 2) < 0) { | ||
507 | PDEBUG(D_ERR, "Error switching to compressed mode"); | ||
508 | return -EIO; | ||
509 | } | ||
510 | sd->compress_inited = 1; | ||
511 | } | ||
512 | return 0; | ||
513 | } | ||
514 | |||
515 | /* Set the read and write slave IDs. The "slave" argument is the write slave, | 527 | /* Set the read and write slave IDs. The "slave" argument is the write slave, |
516 | * and the read slave will be set to (slave + 1). | 528 | * and the read slave will be set to (slave + 1). |
517 | * This should not be called from outside the i2c I/O functions. | 529 | * This should not be called from outside the i2c I/O functions. |
@@ -681,21 +693,17 @@ static int ov8xx0_configure(struct sd *sd) | |||
681 | return -1; | 693 | return -1; |
682 | } | 694 | } |
683 | if ((rc & 3) == 1) { | 695 | if ((rc & 3) == 1) { |
684 | PDEBUG(D_PROBE, "Sensor is an OV8610"); | ||
685 | sd->sensor = SEN_OV8610; | 696 | sd->sensor = SEN_OV8610; |
686 | } else { | 697 | } else { |
687 | PDEBUG(D_ERR, "Unknown image sensor version: %d", rc & 3); | 698 | PDEBUG(D_ERR, "Unknown image sensor version: %d", rc & 3); |
688 | return -1; | 699 | return -1; |
689 | } | 700 | } |
690 | PDEBUG(D_PROBE, "Writing 8610 registers"); | 701 | PDEBUG(D_PROBE, "Writing 8610 registers"); |
691 | if (write_i2c_regvals(sd, | 702 | if (write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610))) |
692 | norm_8610, | ||
693 | sizeof norm_8610 / sizeof norm_8610[0])) | ||
694 | return -1; | 703 | return -1; |
695 | 704 | ||
696 | /* Set sensor-specific vars */ | 705 | /* Set sensor-specific vars */ |
697 | sd->maxwidth = 640; | 706 | /* sd->sif = 0; already done */ |
698 | sd->maxheight = 480; | ||
699 | return 0; | 707 | return 0; |
700 | } | 708 | } |
701 | 709 | ||
@@ -825,7 +833,7 @@ static int ov7xx0_configure(struct sd *sd) | |||
825 | { OV7670_REG_COM7, OV7670_COM7_RESET }, | 833 | { OV7670_REG_COM7, OV7670_COM7_RESET }, |
826 | { OV7670_REG_TSLB, 0x04 }, /* OV */ | 834 | { OV7670_REG_TSLB, 0x04 }, /* OV */ |
827 | { OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */ | 835 | { OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */ |
828 | { OV7670_REG_CLKRC, 0x1 }, | 836 | { OV7670_REG_CLKRC, 0x01 }, |
829 | /* | 837 | /* |
830 | * Set the hardware window. These values from OV don't entirely | 838 | * Set the hardware window. These values from OV don't entirely |
831 | * make sense - hstop is less than hstart. But they work... | 839 | * make sense - hstop is less than hstart. But they work... |
@@ -839,16 +847,12 @@ static int ov7xx0_configure(struct sd *sd) | |||
839 | { 0x70, 0x3a }, { 0x71, 0x35 }, | 847 | { 0x70, 0x3a }, { 0x71, 0x35 }, |
840 | { 0x72, 0x11 }, { 0x73, 0xf0 }, | 848 | { 0x72, 0x11 }, { 0x73, 0xf0 }, |
841 | { 0xa2, 0x02 }, | 849 | { 0xa2, 0x02 }, |
842 | /* jfm */ | 850 | /* { OV7670_REG_COM10, 0x0 }, */ |
843 | /* { OV7670_REG_COM10, 0x0 }, */ | ||
844 | 851 | ||
845 | /* Gamma curve values */ | 852 | /* Gamma curve values */ |
846 | { 0x7a, 0x20 }, | 853 | { 0x7a, 0x20 }, |
847 | /* jfm:win 7b=1c */ | ||
848 | { 0x7b, 0x10 }, | 854 | { 0x7b, 0x10 }, |
849 | /* jfm:win 7c=28 */ | ||
850 | { 0x7c, 0x1e }, | 855 | { 0x7c, 0x1e }, |
851 | /* jfm:win 7d=3c */ | ||
852 | { 0x7d, 0x35 }, | 856 | { 0x7d, 0x35 }, |
853 | { 0x7e, 0x5a }, { 0x7f, 0x69 }, | 857 | { 0x7e, 0x5a }, { 0x7f, 0x69 }, |
854 | { 0x80, 0x76 }, { 0x81, 0x80 }, | 858 | { 0x80, 0x76 }, { 0x81, 0x80 }, |
@@ -864,13 +868,11 @@ static int ov7xx0_configure(struct sd *sd) | |||
864 | | OV7670_COM8_BFILT }, | 868 | | OV7670_COM8_BFILT }, |
865 | { OV7670_REG_GAIN, 0 }, { OV7670_REG_AECH, 0 }, | 869 | { OV7670_REG_GAIN, 0 }, { OV7670_REG_AECH, 0 }, |
866 | { OV7670_REG_COM4, 0x40 }, /* magic reserved bit */ | 870 | { OV7670_REG_COM4, 0x40 }, /* magic reserved bit */ |
867 | /* jfm:win 14=38 */ | ||
868 | { OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */ | 871 | { OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */ |
869 | { OV7670_REG_BD50MAX, 0x05 }, { OV7670_REG_BD60MAX, 0x07 }, | 872 | { OV7670_REG_BD50MAX, 0x05 }, { OV7670_REG_BD60MAX, 0x07 }, |
870 | { OV7670_REG_AEW, 0x95 }, { OV7670_REG_AEB, 0x33 }, | 873 | { OV7670_REG_AEW, 0x95 }, { OV7670_REG_AEB, 0x33 }, |
871 | { OV7670_REG_VPT, 0xe3 }, { OV7670_REG_HAECC1, 0x78 }, | 874 | { OV7670_REG_VPT, 0xe3 }, { OV7670_REG_HAECC1, 0x78 }, |
872 | { OV7670_REG_HAECC2, 0x68 }, | 875 | { OV7670_REG_HAECC2, 0x68 }, |
873 | /* jfm:win a1=0b */ | ||
874 | { 0xa1, 0x03 }, /* magic */ | 876 | { 0xa1, 0x03 }, /* magic */ |
875 | { OV7670_REG_HAECC3, 0xd8 }, { OV7670_REG_HAECC4, 0xd8 }, | 877 | { OV7670_REG_HAECC3, 0xd8 }, { OV7670_REG_HAECC4, 0xd8 }, |
876 | { OV7670_REG_HAECC5, 0xf0 }, { OV7670_REG_HAECC6, 0x90 }, | 878 | { OV7670_REG_HAECC5, 0xf0 }, { OV7670_REG_HAECC6, 0x90 }, |
@@ -884,8 +886,6 @@ static int ov7xx0_configure(struct sd *sd) | |||
884 | /* Almost all of these are magic "reserved" values. */ | 886 | /* Almost all of these are magic "reserved" values. */ |
885 | { OV7670_REG_COM5, 0x61 }, { OV7670_REG_COM6, 0x4b }, | 887 | { OV7670_REG_COM5, 0x61 }, { OV7670_REG_COM6, 0x4b }, |
886 | { 0x16, 0x02 }, | 888 | { 0x16, 0x02 }, |
887 | /* jfm */ | ||
888 | /* { OV7670_REG_MVFP, 0x07|OV7670_MVFP_MIRROR }, */ | ||
889 | { OV7670_REG_MVFP, 0x07 }, | 889 | { OV7670_REG_MVFP, 0x07 }, |
890 | { 0x21, 0x02 }, { 0x22, 0x91 }, | 890 | { 0x21, 0x02 }, { 0x22, 0x91 }, |
891 | { 0x29, 0x07 }, { 0x33, 0x0b }, | 891 | { 0x29, 0x07 }, { 0x33, 0x0b }, |
@@ -930,7 +930,10 @@ static int ov7xx0_configure(struct sd *sd) | |||
930 | { OV7670_REG_EDGE, 0 }, | 930 | { OV7670_REG_EDGE, 0 }, |
931 | { 0x75, 0x05 }, { 0x76, 0xe1 }, | 931 | { 0x75, 0x05 }, { 0x76, 0xe1 }, |
932 | { 0x4c, 0 }, { 0x77, 0x01 }, | 932 | { 0x4c, 0 }, { 0x77, 0x01 }, |
933 | { OV7670_REG_COM13, 0xc3 }, { 0x4b, 0x09 }, | 933 | { OV7670_REG_COM13, OV7670_COM13_GAMMA |
934 | | OV7670_COM13_UVSAT | ||
935 | | 2}, /* was 3 */ | ||
936 | { 0x4b, 0x09 }, | ||
934 | { 0xc9, 0x60 }, { OV7670_REG_COM16, 0x38 }, | 937 | { 0xc9, 0x60 }, { OV7670_REG_COM16, 0x38 }, |
935 | { 0x56, 0x40 }, | 938 | { 0x56, 0x40 }, |
936 | 939 | ||
@@ -956,30 +959,10 @@ static int ov7xx0_configure(struct sd *sd) | |||
956 | { 0x79, 0x03 }, { 0xc8, 0x40 }, | 959 | { 0x79, 0x03 }, { 0xc8, 0x40 }, |
957 | { 0x79, 0x05 }, { 0xc8, 0x30 }, | 960 | { 0x79, 0x05 }, { 0xc8, 0x30 }, |
958 | { 0x79, 0x26 }, | 961 | { 0x79, 0x26 }, |
959 | 962 | }; | |
960 | /* Format YUV422 */ | ||
961 | { OV7670_REG_COM7, OV7670_COM7_YUV }, /* Selects YUV mode */ | ||
962 | { OV7670_REG_RGB444, 0 }, /* No RGB444 please */ | ||
963 | { OV7670_REG_COM1, 0 }, | ||
964 | { OV7670_REG_COM15, OV7670_COM15_R00FF }, | ||
965 | { OV7670_REG_COM9, 0x18 }, | ||
966 | /* 4x gain ceiling; 0x8 is reserved bit */ | ||
967 | { 0x4f, 0x80 }, /* "matrix coefficient 1" */ | ||
968 | { 0x50, 0x80 }, /* "matrix coefficient 2" */ | ||
969 | { 0x52, 0x22 }, /* "matrix coefficient 4" */ | ||
970 | { 0x53, 0x5e }, /* "matrix coefficient 5" */ | ||
971 | { 0x54, 0x80 }, /* "matrix coefficient 6" */ | ||
972 | { OV7670_REG_COM13, OV7670_COM13_GAMMA|OV7670_COM13_UVSAT }, | ||
973 | }; | ||
974 | 963 | ||
975 | PDEBUG(D_PROBE, "starting OV7xx0 configuration"); | 964 | PDEBUG(D_PROBE, "starting OV7xx0 configuration"); |
976 | 965 | ||
977 | /* jfm:already done? */ | ||
978 | if (init_ov_sensor(sd) < 0) | ||
979 | PDEBUG(D_ERR, "Failed to read sensor ID"); | ||
980 | else | ||
981 | PDEBUG(D_PROBE, "OV7xx0 initialized"); | ||
982 | |||
983 | /* Detect sensor (sub)type */ | 966 | /* Detect sensor (sub)type */ |
984 | rc = i2c_r(sd, OV7610_REG_COM_I); | 967 | rc = i2c_r(sd, OV7610_REG_COM_I); |
985 | 968 | ||
@@ -1025,20 +1008,25 @@ static int ov7xx0_configure(struct sd *sd) | |||
1025 | return low; | 1008 | return low; |
1026 | } | 1009 | } |
1027 | if (high == 0x76) { | 1010 | if (high == 0x76) { |
1028 | if (low == 0x30) { | 1011 | switch (low) { |
1012 | case 0x30: | ||
1029 | PDEBUG(D_PROBE, "Sensor is an OV7630/OV7635"); | 1013 | PDEBUG(D_PROBE, "Sensor is an OV7630/OV7635"); |
1030 | sd->sensor = SEN_OV7630; | 1014 | sd->sensor = SEN_OV7630; |
1031 | } else if (low == 0x40) { | 1015 | break; |
1016 | case 0x40: | ||
1032 | PDEBUG(D_PROBE, "Sensor is an OV7645"); | 1017 | PDEBUG(D_PROBE, "Sensor is an OV7645"); |
1033 | sd->sensor = SEN_OV7640; /* FIXME */ | 1018 | sd->sensor = SEN_OV7640; /* FIXME */ |
1034 | } else if (low == 0x45) { | 1019 | break; |
1020 | case 0x45: | ||
1035 | PDEBUG(D_PROBE, "Sensor is an OV7645B"); | 1021 | PDEBUG(D_PROBE, "Sensor is an OV7645B"); |
1036 | sd->sensor = SEN_OV7640; /* FIXME */ | 1022 | sd->sensor = SEN_OV7640; /* FIXME */ |
1037 | } else if (low == 0x48) { | 1023 | break; |
1024 | case 0x48: | ||
1038 | PDEBUG(D_PROBE, "Sensor is an OV7648"); | 1025 | PDEBUG(D_PROBE, "Sensor is an OV7648"); |
1039 | sd->sensor = SEN_OV7640; /* FIXME */ | 1026 | sd->sensor = SEN_OV7640; /* FIXME */ |
1040 | } else { | 1027 | break; |
1041 | PDEBUG(D_PROBE, "Unknown sensor: 0x76%X", low); | 1028 | default: |
1029 | PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low); | ||
1042 | return -1; | 1030 | return -1; |
1043 | } | 1031 | } |
1044 | } else { | 1032 | } else { |
@@ -1050,34 +1038,34 @@ static int ov7xx0_configure(struct sd *sd) | |||
1050 | return -1; | 1038 | return -1; |
1051 | } | 1039 | } |
1052 | 1040 | ||
1053 | if (sd->sensor == SEN_OV7620) { | 1041 | switch (sd->sensor) { |
1042 | case SEN_OV7620: | ||
1054 | PDEBUG(D_PROBE, "Writing 7620 registers"); | 1043 | PDEBUG(D_PROBE, "Writing 7620 registers"); |
1055 | if (write_i2c_regvals(sd, norm_7620, | 1044 | if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620))) |
1056 | sizeof norm_7620 / sizeof norm_7620[0])) | ||
1057 | return -1; | 1045 | return -1; |
1058 | } else if (sd->sensor == SEN_OV7630) { | 1046 | break; |
1047 | case SEN_OV7630: | ||
1059 | PDEBUG(D_ERR, "7630 is not supported by this driver version"); | 1048 | PDEBUG(D_ERR, "7630 is not supported by this driver version"); |
1060 | return -1; | 1049 | return -1; |
1061 | } else if (sd->sensor == SEN_OV7640) { | 1050 | case SEN_OV7640: |
1062 | PDEBUG(D_PROBE, "Writing 7640 registers"); | 1051 | PDEBUG(D_PROBE, "Writing 7640 registers"); |
1063 | if (write_i2c_regvals(sd, norm_7640, | 1052 | if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640))) |
1064 | sizeof norm_7640 / sizeof norm_7640[0])) | ||
1065 | return -1; | 1053 | return -1; |
1066 | } else if (sd->sensor == SEN_OV7670) { | 1054 | break; |
1055 | case SEN_OV7670: | ||
1067 | PDEBUG(D_PROBE, "Writing 7670 registers"); | 1056 | PDEBUG(D_PROBE, "Writing 7670 registers"); |
1068 | if (write_i2c_regvals(sd, norm_7670, | 1057 | if (write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670))) |
1069 | sizeof norm_7670 / sizeof norm_7670[0])) | ||
1070 | return -1; | 1058 | return -1; |
1071 | } else { | 1059 | break; |
1060 | default: | ||
1072 | PDEBUG(D_PROBE, "Writing 7610 registers"); | 1061 | PDEBUG(D_PROBE, "Writing 7610 registers"); |
1073 | if (write_i2c_regvals(sd, norm_7610, | 1062 | if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610))) |
1074 | sizeof norm_7610 / sizeof norm_7610[0])) | ||
1075 | return -1; | 1063 | return -1; |
1064 | break; | ||
1076 | } | 1065 | } |
1077 | 1066 | ||
1078 | /* Set sensor-specific vars */ | 1067 | /* Set sensor-specific vars */ |
1079 | sd->maxwidth = 640; | 1068 | /* sd->sif = 0; already done */ |
1080 | sd->maxheight = 480; | ||
1081 | return 0; | 1069 | return 0; |
1082 | } | 1070 | } |
1083 | 1071 | ||
@@ -1231,43 +1219,45 @@ static int ov6xx0_configure(struct sd *sd) | |||
1231 | /* Ugh. The first two bits are the version bits, but | 1219 | /* Ugh. The first two bits are the version bits, but |
1232 | * the entire register value must be used. I guess OVT | 1220 | * the entire register value must be used. I guess OVT |
1233 | * underestimated how many variants they would make. */ | 1221 | * underestimated how many variants they would make. */ |
1234 | if (rc == 0x00) { | 1222 | switch (rc) { |
1223 | case 0x00: | ||
1235 | sd->sensor = SEN_OV6630; | 1224 | sd->sensor = SEN_OV6630; |
1236 | PDEBUG(D_ERR, | 1225 | PDEBUG(D_ERR, |
1237 | "WARNING: Sensor is an OV66308. Your camera may have"); | 1226 | "WARNING: Sensor is an OV66308. Your camera may have"); |
1238 | PDEBUG(D_ERR, "been misdetected in previous driver versions."); | 1227 | PDEBUG(D_ERR, "been misdetected in previous driver versions."); |
1239 | } else if (rc == 0x01) { | 1228 | break; |
1229 | case 0x01: | ||
1240 | sd->sensor = SEN_OV6620; | 1230 | sd->sensor = SEN_OV6620; |
1241 | PDEBUG(D_PROBE, "Sensor is an OV6620"); | 1231 | break; |
1242 | } else if (rc == 0x02) { | 1232 | case 0x02: |
1243 | sd->sensor = SEN_OV6630; | 1233 | sd->sensor = SEN_OV6630; |
1244 | PDEBUG(D_PROBE, "Sensor is an OV66308AE"); | 1234 | PDEBUG(D_PROBE, "Sensor is an OV66308AE"); |
1245 | } else if (rc == 0x03) { | 1235 | break; |
1236 | case 0x03: | ||
1246 | sd->sensor = SEN_OV6630; | 1237 | sd->sensor = SEN_OV6630; |
1247 | PDEBUG(D_PROBE, "Sensor is an OV66308AF"); | 1238 | PDEBUG(D_PROBE, "Sensor is an OV66308AF"); |
1248 | } else if (rc == 0x90) { | 1239 | break; |
1240 | case 0x90: | ||
1249 | sd->sensor = SEN_OV6630; | 1241 | sd->sensor = SEN_OV6630; |
1250 | PDEBUG(D_ERR, | 1242 | PDEBUG(D_ERR, |
1251 | "WARNING: Sensor is an OV66307. Your camera may have"); | 1243 | "WARNING: Sensor is an OV66307. Your camera may have"); |
1252 | PDEBUG(D_ERR, "been misdetected in previous driver versions."); | 1244 | PDEBUG(D_ERR, "been misdetected in previous driver versions."); |
1253 | } else { | 1245 | break; |
1246 | default: | ||
1254 | PDEBUG(D_ERR, "FATAL: Unknown sensor version: 0x%02x", rc); | 1247 | PDEBUG(D_ERR, "FATAL: Unknown sensor version: 0x%02x", rc); |
1255 | return -1; | 1248 | return -1; |
1256 | } | 1249 | } |
1257 | 1250 | ||
1258 | /* Set sensor-specific vars */ | 1251 | /* Set sensor-specific vars */ |
1259 | sd->maxwidth = 352; | 1252 | sd->sif = 1; |
1260 | sd->maxheight = 288; | ||
1261 | 1253 | ||
1262 | if (sd->sensor == SEN_OV6620) { | 1254 | if (sd->sensor == SEN_OV6620) { |
1263 | PDEBUG(D_PROBE, "Writing 6x20 registers"); | 1255 | PDEBUG(D_PROBE, "Writing 6x20 registers"); |
1264 | if (write_i2c_regvals(sd, norm_6x20, | 1256 | if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20))) |
1265 | sizeof norm_6x20 / sizeof norm_6x20[0])) | ||
1266 | return -1; | 1257 | return -1; |
1267 | } else { | 1258 | } else { |
1268 | PDEBUG(D_PROBE, "Writing 6x30 registers"); | 1259 | PDEBUG(D_PROBE, "Writing 6x30 registers"); |
1269 | if (write_i2c_regvals(sd, norm_6x30, | 1260 | if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30))) |
1270 | sizeof norm_6x30 / sizeof norm_6x30[0])) | ||
1271 | return -1; | 1261 | return -1; |
1272 | } | 1262 | } |
1273 | return 0; | 1263 | return 0; |
@@ -1276,14 +1266,8 @@ static int ov6xx0_configure(struct sd *sd) | |||
1276 | /* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */ | 1266 | /* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */ |
1277 | static void ov51x_led_control(struct sd *sd, int on) | 1267 | static void ov51x_led_control(struct sd *sd, int on) |
1278 | { | 1268 | { |
1279 | PDEBUG(D_STREAM, "LED (%s)", on ? "on" : "off"); | 1269 | /* PDEBUG(D_STREAM, "LED (%s)", on ? "on" : "off"); */ |
1280 | 1270 | reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */ | |
1281 | /* if (sd->bridge == BRG_OV511PLUS) */ | ||
1282 | /* reg_w(sd, R511_SYS_LED_CTL, on ? 1 : 0); */ | ||
1283 | /* else if (sd->bridge == BRG_OV519) */ | ||
1284 | reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */ | ||
1285 | /* else if (sd->bclass == BCL_OV518) */ | ||
1286 | /* reg_w_mask(sd, R518_GPIO_OUT, on ? 0x02 : 0x00, 0x02); */ | ||
1287 | } | 1271 | } |
1288 | 1272 | ||
1289 | /* this function is called at probe time */ | 1273 | /* this function is called at probe time */ |
@@ -1293,11 +1277,8 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1293 | struct sd *sd = (struct sd *) gspca_dev; | 1277 | struct sd *sd = (struct sd *) gspca_dev; |
1294 | struct cam *cam; | 1278 | struct cam *cam; |
1295 | 1279 | ||
1296 | /* (from ov519_configure) */ | ||
1297 | static const struct ov_regvals init_519[] = { | 1280 | static const struct ov_regvals init_519[] = { |
1298 | { 0x5a, 0x6d }, /* EnableSystem */ | 1281 | { 0x5a, 0x6d }, /* EnableSystem */ |
1299 | /* jfm trace usbsnoop3-1.txt */ | ||
1300 | /* jfm 53 = fb */ | ||
1301 | { 0x53, 0x9b }, | 1282 | { 0x53, 0x9b }, |
1302 | { 0x54, 0xff }, /* set bit2 to enable jpeg */ | 1283 | { 0x54, 0xff }, /* set bit2 to enable jpeg */ |
1303 | { 0x5d, 0x03 }, | 1284 | { 0x5d, 0x03 }, |
@@ -1314,9 +1295,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1314 | 1295 | ||
1315 | if (write_regvals(sd, init_519, ARRAY_SIZE(init_519))) | 1296 | if (write_regvals(sd, init_519, ARRAY_SIZE(init_519))) |
1316 | goto error; | 1297 | goto error; |
1317 | /* jfm: not seen in windows trace */ | ||
1318 | if (ov519_init_compression(sd)) | ||
1319 | goto error; | ||
1320 | ov51x_led_control(sd, 0); /* turn LED off */ | 1298 | ov51x_led_control(sd, 0); /* turn LED off */ |
1321 | 1299 | ||
1322 | /* Test for 76xx */ | 1300 | /* Test for 76xx */ |
@@ -1365,16 +1343,18 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1365 | 1343 | ||
1366 | cam = &gspca_dev->cam; | 1344 | cam = &gspca_dev->cam; |
1367 | cam->epaddr = OV511_ENDPOINT_ADDRESS; | 1345 | cam->epaddr = OV511_ENDPOINT_ADDRESS; |
1368 | if (sd->maxwidth == 640) { | 1346 | if (!sd->sif) { |
1369 | cam->cam_mode = vga_mode; | 1347 | cam->cam_mode = vga_mode; |
1370 | cam->nmodes = sizeof vga_mode / sizeof vga_mode[0]; | 1348 | cam->nmodes = ARRAY_SIZE(vga_mode); |
1371 | } else { | 1349 | } else { |
1372 | cam->cam_mode = sif_mode; | 1350 | cam->cam_mode = sif_mode; |
1373 | cam->nmodes = sizeof sif_mode / sizeof sif_mode[0]; | 1351 | cam->nmodes = ARRAY_SIZE(sif_mode); |
1374 | } | 1352 | } |
1375 | sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; | 1353 | sd->brightness = BRIGHTNESS_DEF; |
1376 | sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; | 1354 | sd->contrast = CONTRAST_DEF; |
1377 | sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value; | 1355 | sd->colors = COLOR_DEF; |
1356 | sd->hflip = HFLIP_DEF; | ||
1357 | sd->vflip = VFLIP_DEF; | ||
1378 | return 0; | 1358 | return 0; |
1379 | error: | 1359 | error: |
1380 | PDEBUG(D_ERR, "OV519 Config failed"); | 1360 | PDEBUG(D_ERR, "OV519 Config failed"); |
@@ -1394,8 +1374,7 @@ static int sd_open(struct gspca_dev *gspca_dev) | |||
1394 | * | 1374 | * |
1395 | * Do not put any sensor-specific code in here (including I2C I/O functions) | 1375 | * Do not put any sensor-specific code in here (including I2C I/O functions) |
1396 | */ | 1376 | */ |
1397 | static int ov519_mode_init_regs(struct sd *sd, | 1377 | static int ov519_mode_init_regs(struct sd *sd) |
1398 | int width, int height) | ||
1399 | { | 1378 | { |
1400 | static const struct ov_regvals mode_init_519_ov7670[] = { | 1379 | static const struct ov_regvals mode_init_519_ov7670[] = { |
1401 | { 0x5d, 0x03 }, /* Turn off suspend mode */ | 1380 | { 0x5d, 0x03 }, /* Turn off suspend mode */ |
@@ -1441,36 +1420,23 @@ static int ov519_mode_init_regs(struct sd *sd, | |||
1441 | /* windows reads 0x55 at this point, why? */ | 1420 | /* windows reads 0x55 at this point, why? */ |
1442 | }; | 1421 | }; |
1443 | 1422 | ||
1444 | /* int hi_res; */ | ||
1445 | |||
1446 | PDEBUG(D_CONF, "mode init %dx%d", width, height); | ||
1447 | |||
1448 | /* if (width >= 800 && height >= 600) | ||
1449 | hi_res = 1; | ||
1450 | else | ||
1451 | hi_res = 0; */ | ||
1452 | |||
1453 | /* if (ov51x_stop(sd) < 0) | ||
1454 | return -EIO; */ | ||
1455 | |||
1456 | /******** Set the mode ********/ | 1423 | /******** Set the mode ********/ |
1457 | if (sd->sensor != SEN_OV7670) { | 1424 | if (sd->sensor != SEN_OV7670) { |
1458 | if (write_regvals(sd, mode_init_519, | 1425 | if (write_regvals(sd, mode_init_519, |
1459 | ARRAY_SIZE(mode_init_519))) | 1426 | ARRAY_SIZE(mode_init_519))) |
1460 | return -EIO; | 1427 | return -EIO; |
1428 | if (sd->sensor == SEN_OV7640) { | ||
1429 | /* Select 8-bit input mode */ | ||
1430 | reg_w_mask(sd, OV519_CAM_DFR, 0x10, 0x10); | ||
1431 | } | ||
1461 | } else { | 1432 | } else { |
1462 | if (write_regvals(sd, mode_init_519_ov7670, | 1433 | if (write_regvals(sd, mode_init_519_ov7670, |
1463 | ARRAY_SIZE(mode_init_519_ov7670))) | 1434 | ARRAY_SIZE(mode_init_519_ov7670))) |
1464 | return -EIO; | 1435 | return -EIO; |
1465 | } | 1436 | } |
1466 | 1437 | ||
1467 | if (sd->sensor == SEN_OV7640) { | 1438 | reg_w(sd, OV519_CAM_H_SIZE, sd->gspca_dev.width >> 4); |
1468 | /* Select 8-bit input mode */ | 1439 | reg_w(sd, OV519_CAM_V_SIZE, sd->gspca_dev.height >> 3); |
1469 | reg_w_mask(sd, OV519_CAM_DFR, 0x10, 0x10); | ||
1470 | } | ||
1471 | |||
1472 | reg_w(sd, OV519_CAM_H_SIZE, width >> 4); | ||
1473 | reg_w(sd, OV519_CAM_V_SIZE, height >> 3); | ||
1474 | reg_w(sd, OV519_CAM_X_OFFSETL, 0x00); | 1440 | reg_w(sd, OV519_CAM_X_OFFSETL, 0x00); |
1475 | reg_w(sd, OV519_CAM_X_OFFSETH, 0x00); | 1441 | reg_w(sd, OV519_CAM_X_OFFSETH, 0x00); |
1476 | reg_w(sd, OV519_CAM_Y_OFFSETL, 0x00); | 1442 | reg_w(sd, OV519_CAM_Y_OFFSETL, 0x00); |
@@ -1485,9 +1451,10 @@ static int ov519_mode_init_regs(struct sd *sd, | |||
1485 | 1451 | ||
1486 | /* FIXME: These are only valid at the max resolution. */ | 1452 | /* FIXME: These are only valid at the max resolution. */ |
1487 | sd->clockdiv = 0; | 1453 | sd->clockdiv = 0; |
1488 | if (sd->sensor == SEN_OV7640) { | 1454 | switch (sd->sensor) { |
1455 | case SEN_OV7640: | ||
1489 | switch (sd->frame_rate) { | 1456 | switch (sd->frame_rate) { |
1490 | /*jfm: default was 30 fps */ | 1457 | /*fixme: default was 30 fps */ |
1491 | case 30: | 1458 | case 30: |
1492 | reg_w(sd, 0xa4, 0x0c); | 1459 | reg_w(sd, 0xa4, 0x0c); |
1493 | reg_w(sd, 0x23, 0xff); | 1460 | reg_w(sd, 0x23, 0xff); |
@@ -1517,7 +1484,8 @@ static int ov519_mode_init_regs(struct sd *sd, | |||
1517 | sd->clockdiv = 1; | 1484 | sd->clockdiv = 1; |
1518 | break; | 1485 | break; |
1519 | } | 1486 | } |
1520 | } else if (sd->sensor == SEN_OV8610) { | 1487 | break; |
1488 | case SEN_OV8610: | ||
1521 | switch (sd->frame_rate) { | 1489 | switch (sd->frame_rate) { |
1522 | default: /* 15 fps */ | 1490 | default: /* 15 fps */ |
1523 | /* case 15: */ | 1491 | /* case 15: */ |
@@ -1533,41 +1501,37 @@ static int ov519_mode_init_regs(struct sd *sd, | |||
1533 | reg_w(sd, 0x23, 0x1b); | 1501 | reg_w(sd, 0x23, 0x1b); |
1534 | break; | 1502 | break; |
1535 | } | 1503 | } |
1536 | sd->clockdiv = 0; | 1504 | break; |
1537 | } else if (sd->sensor == SEN_OV7670) { /* guesses, based on 7640 */ | 1505 | case SEN_OV7670: /* guesses, based on 7640 */ |
1538 | PDEBUG(D_STREAM, "Setting framerate to %d fps", | 1506 | PDEBUG(D_STREAM, "Setting framerate to %d fps", |
1539 | (sd->frame_rate == 0) ? 15 : sd->frame_rate); | 1507 | (sd->frame_rate == 0) ? 15 : sd->frame_rate); |
1508 | reg_w(sd, 0xa4, 0x10); | ||
1540 | switch (sd->frame_rate) { | 1509 | switch (sd->frame_rate) { |
1541 | case 30: | 1510 | case 30: |
1542 | reg_w(sd, 0xa4, 0x10); | ||
1543 | reg_w(sd, 0x23, 0xff); | 1511 | reg_w(sd, 0x23, 0xff); |
1544 | break; | 1512 | break; |
1545 | case 20: | 1513 | case 20: |
1546 | reg_w(sd, 0xa4, 0x10); | ||
1547 | reg_w(sd, 0x23, 0x1b); | 1514 | reg_w(sd, 0x23, 0x1b); |
1548 | break; | 1515 | break; |
1549 | default: /* 15 fps */ | 1516 | default: |
1550 | /* case 15: */ | 1517 | /* case 15: */ |
1551 | reg_w(sd, 0xa4, 0x10); | ||
1552 | reg_w(sd, 0x23, 0xff); | 1518 | reg_w(sd, 0x23, 0xff); |
1553 | sd->clockdiv = 1; | 1519 | sd->clockdiv = 1; |
1554 | break; | 1520 | break; |
1555 | } | 1521 | } |
1522 | break; | ||
1556 | } | 1523 | } |
1557 | 1524 | ||
1558 | /* if (ov51x_restart(sd) < 0) | ||
1559 | return -EIO; */ | ||
1560 | |||
1561 | /* Reset it just for good measure */ | ||
1562 | /* if (ov51x_reset(sd, OV511_RESET_NOREGS) < 0) | ||
1563 | return -EIO; */ | ||
1564 | return 0; | 1525 | return 0; |
1565 | } | 1526 | } |
1566 | 1527 | ||
1567 | static int mode_init_ov_sensor_regs(struct sd *sd, | 1528 | static int mode_init_ov_sensor_regs(struct sd *sd) |
1568 | struct ovsensor_window *win) | ||
1569 | { | 1529 | { |
1570 | int qvga = win->quarter; | 1530 | struct gspca_dev *gspca_dev; |
1531 | int qvga; | ||
1532 | |||
1533 | gspca_dev = &sd->gspca_dev; | ||
1534 | qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; | ||
1571 | 1535 | ||
1572 | /******** Mode (VGA/QVGA) and sensor specific regs ********/ | 1536 | /******** Mode (VGA/QVGA) and sensor specific regs ********/ |
1573 | switch (sd->sensor) { | 1537 | switch (sd->sensor) { |
@@ -1611,8 +1575,6 @@ static int mode_init_ov_sensor_regs(struct sd *sd, | |||
1611 | OV7670_COM7_FMT_MASK); | 1575 | OV7670_COM7_FMT_MASK); |
1612 | break; | 1576 | break; |
1613 | case SEN_OV6620: | 1577 | case SEN_OV6620: |
1614 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); | ||
1615 | break; | ||
1616 | case SEN_OV6630: | 1578 | case SEN_OV6630: |
1617 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); | 1579 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); |
1618 | break; | 1580 | break; |
@@ -1621,24 +1583,21 @@ static int mode_init_ov_sensor_regs(struct sd *sd, | |||
1621 | } | 1583 | } |
1622 | 1584 | ||
1623 | /******** Palette-specific regs ********/ | 1585 | /******** Palette-specific regs ********/ |
1624 | /* Need to do work here for the OV7670 */ | 1586 | if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) { |
1625 | 1587 | /* not valid on the OV6620/OV7620/6630? */ | |
1626 | if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) { | 1588 | i2c_w_mask(sd, 0x0e, 0x00, 0x40); |
1627 | /* not valid on the OV6620/OV7620/6630? */ | 1589 | } |
1628 | i2c_w_mask(sd, 0x0e, 0x00, 0x40); | ||
1629 | } | ||
1630 | 1590 | ||
1631 | /* The OV518 needs special treatment. Although both the OV518 | 1591 | /* The OV518 needs special treatment. Although both the OV518 |
1632 | * and the OV6630 support a 16-bit video bus, only the 8 bit Y | 1592 | * and the OV6630 support a 16-bit video bus, only the 8 bit Y |
1633 | * bus is actually used. The UV bus is tied to ground. | 1593 | * bus is actually used. The UV bus is tied to ground. |
1634 | * Therefore, the OV6630 needs to be in 8-bit multiplexed | 1594 | * Therefore, the OV6630 needs to be in 8-bit multiplexed |
1635 | * output mode */ | 1595 | * output mode */ |
1636 | 1596 | ||
1637 | /* OV7640 is 8-bit only */ | 1597 | /* OV7640 is 8-bit only */ |
1638 | 1598 | ||
1639 | if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV7640) | 1599 | if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV7640) |
1640 | i2c_w_mask(sd, 0x13, 0x00, 0x20); | 1600 | i2c_w_mask(sd, 0x13, 0x00, 0x20); |
1641 | /* } */ | ||
1642 | 1601 | ||
1643 | /******** Clock programming ********/ | 1602 | /******** Clock programming ********/ |
1644 | /* The OV6620 needs special handling. This prevents the | 1603 | /* The OV6620 needs special handling. This prevents the |
@@ -1647,14 +1606,14 @@ static int mode_init_ov_sensor_regs(struct sd *sd, | |||
1647 | 1606 | ||
1648 | /* Clock down */ | 1607 | /* Clock down */ |
1649 | i2c_w(sd, 0x2a, 0x04); | 1608 | i2c_w(sd, 0x2a, 0x04); |
1650 | i2c_w(sd, 0x11, win->clockdiv); | 1609 | i2c_w(sd, 0x11, sd->clockdiv); |
1651 | i2c_w(sd, 0x2a, 0x84); | 1610 | i2c_w(sd, 0x2a, 0x84); |
1652 | /* This next setting is critical. It seems to improve | 1611 | /* This next setting is critical. It seems to improve |
1653 | * the gain or the contrast. The "reserved" bits seem | 1612 | * the gain or the contrast. The "reserved" bits seem |
1654 | * to have some effect in this case. */ | 1613 | * to have some effect in this case. */ |
1655 | i2c_w(sd, 0x2d, 0x85); | 1614 | i2c_w(sd, 0x2d, 0x85); |
1656 | } else if (win->clockdiv >= 0) { | 1615 | } else if (sd->clockdiv >= 0) { |
1657 | i2c_w(sd, 0x11, win->clockdiv); | 1616 | i2c_w(sd, 0x11, sd->clockdiv); |
1658 | } | 1617 | } |
1659 | 1618 | ||
1660 | /******** Special Features ********/ | 1619 | /******** Special Features ********/ |
@@ -1674,7 +1633,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd, | |||
1674 | /* is fully tested. */ | 1633 | /* is fully tested. */ |
1675 | /* 7620/6620/6630? don't have register 0x35, so play it safe */ | 1634 | /* 7620/6620/6630? don't have register 0x35, so play it safe */ |
1676 | if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) { | 1635 | if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) { |
1677 | if (win->width == 640 /*&& win->height == 480*/) | 1636 | if (!qvga) |
1678 | i2c_w(sd, 0x35, 0x9e); | 1637 | i2c_w(sd, 0x35, 0x9e); |
1679 | else | 1638 | else |
1680 | i2c_w(sd, 0x35, 0x1e); | 1639 | i2c_w(sd, 0x35, 0x1e); |
@@ -1682,13 +1641,31 @@ static int mode_init_ov_sensor_regs(struct sd *sd, | |||
1682 | return 0; | 1641 | return 0; |
1683 | } | 1642 | } |
1684 | 1643 | ||
1685 | static int set_ov_sensor_window(struct sd *sd, | 1644 | static void sethvflip(struct sd *sd) |
1686 | struct ovsensor_window *win) | ||
1687 | { | 1645 | { |
1646 | if (sd->sensor != SEN_OV7670) | ||
1647 | return; | ||
1648 | if (sd->gspca_dev.streaming) | ||
1649 | ov51x_stop(sd); | ||
1650 | i2c_w_mask(sd, OV7670_REG_MVFP, | ||
1651 | OV7670_MVFP_MIRROR * sd->hflip | ||
1652 | | OV7670_MVFP_VFLIP * sd->vflip, | ||
1653 | OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP); | ||
1654 | if (sd->gspca_dev.streaming) | ||
1655 | ov51x_restart(sd); | ||
1656 | } | ||
1657 | |||
1658 | static int set_ov_sensor_window(struct sd *sd) | ||
1659 | { | ||
1660 | struct gspca_dev *gspca_dev; | ||
1661 | int qvga; | ||
1688 | int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; | 1662 | int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; |
1689 | int ret, hstart, hstop, vstop, vstart; | 1663 | int ret, hstart, hstop, vstop, vstart; |
1690 | __u8 v; | 1664 | __u8 v; |
1691 | 1665 | ||
1666 | gspca_dev = &sd->gspca_dev; | ||
1667 | qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; | ||
1668 | |||
1692 | /* The different sensor ICs handle setting up of window differently. | 1669 | /* The different sensor ICs handle setting up of window differently. |
1693 | * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */ | 1670 | * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */ |
1694 | switch (sd->sensor) { | 1671 | switch (sd->sensor) { |
@@ -1733,7 +1710,7 @@ static int set_ov_sensor_window(struct sd *sd, | |||
1733 | switch (sd->sensor) { | 1710 | switch (sd->sensor) { |
1734 | case SEN_OV6620: | 1711 | case SEN_OV6620: |
1735 | case SEN_OV6630: | 1712 | case SEN_OV6630: |
1736 | if (win->quarter) { /* QCIF */ | 1713 | if (qvga) { /* QCIF */ |
1737 | hwscale = 0; | 1714 | hwscale = 0; |
1738 | vwscale = 0; | 1715 | vwscale = 0; |
1739 | } else { /* CIF */ | 1716 | } else { /* CIF */ |
@@ -1743,7 +1720,7 @@ static int set_ov_sensor_window(struct sd *sd, | |||
1743 | } | 1720 | } |
1744 | break; | 1721 | break; |
1745 | case SEN_OV8610: | 1722 | case SEN_OV8610: |
1746 | if (win->quarter) { /* QSVGA */ | 1723 | if (qvga) { /* QSVGA */ |
1747 | hwscale = 1; | 1724 | hwscale = 1; |
1748 | vwscale = 1; | 1725 | vwscale = 1; |
1749 | } else { /* SVGA */ | 1726 | } else { /* SVGA */ |
@@ -1752,7 +1729,7 @@ static int set_ov_sensor_window(struct sd *sd, | |||
1752 | } | 1729 | } |
1753 | break; | 1730 | break; |
1754 | default: /* SEN_OV7xx0 */ | 1731 | default: /* SEN_OV7xx0 */ |
1755 | if (win->quarter) { /* QVGA */ | 1732 | if (qvga) { /* QVGA */ |
1756 | hwscale = 1; | 1733 | hwscale = 1; |
1757 | vwscale = 0; | 1734 | vwscale = 0; |
1758 | } else { /* VGA */ | 1735 | } else { /* VGA */ |
@@ -1761,7 +1738,7 @@ static int set_ov_sensor_window(struct sd *sd, | |||
1761 | } | 1738 | } |
1762 | } | 1739 | } |
1763 | 1740 | ||
1764 | ret = mode_init_ov_sensor_regs(sd, win); | 1741 | ret = mode_init_ov_sensor_regs(sd); |
1765 | if (ret < 0) | 1742 | if (ret < 0) |
1766 | return ret; | 1743 | return ret; |
1767 | 1744 | ||
@@ -1782,7 +1759,7 @@ static int set_ov_sensor_window(struct sd *sd, | |||
1782 | /* I can hard code this for OV7670s */ | 1759 | /* I can hard code this for OV7670s */ |
1783 | /* Yes, these numbers do look odd, but they're tested and work! */ | 1760 | /* Yes, these numbers do look odd, but they're tested and work! */ |
1784 | if (sd->sensor == SEN_OV7670) { | 1761 | if (sd->sensor == SEN_OV7670) { |
1785 | if (win->quarter) { /* QVGA from ov7670.c by | 1762 | if (qvga) { /* QVGA from ov7670.c by |
1786 | * Jonathan Corbet */ | 1763 | * Jonathan Corbet */ |
1787 | hstart = 164; | 1764 | hstart = 164; |
1788 | hstop = 20; | 1765 | hstop = 20; |
@@ -1796,75 +1773,45 @@ static int set_ov_sensor_window(struct sd *sd, | |||
1796 | } | 1773 | } |
1797 | /* OV7670 hardware window registers are split across | 1774 | /* OV7670 hardware window registers are split across |
1798 | * multiple locations */ | 1775 | * multiple locations */ |
1799 | i2c_w(sd, OV7670_REG_HSTART, (hstart >> 3) & 0xff); | 1776 | i2c_w(sd, OV7670_REG_HSTART, hstart >> 3); |
1800 | i2c_w(sd, OV7670_REG_HSTOP, (hstop >> 3) & 0xff); | 1777 | i2c_w(sd, OV7670_REG_HSTOP, hstop >> 3); |
1801 | v = i2c_r(sd, OV7670_REG_HREF); | 1778 | v = i2c_r(sd, OV7670_REG_HREF); |
1802 | v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x07); | 1779 | v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x07); |
1803 | msleep(10); /* need to sleep between read and write to | 1780 | msleep(10); /* need to sleep between read and write to |
1804 | * same reg! */ | 1781 | * same reg! */ |
1805 | i2c_w(sd, OV7670_REG_HREF, v); | 1782 | i2c_w(sd, OV7670_REG_HREF, v); |
1806 | 1783 | ||
1807 | i2c_w(sd, OV7670_REG_VSTART, (vstart >> 2) & 0xff); | 1784 | i2c_w(sd, OV7670_REG_VSTART, vstart >> 2); |
1808 | i2c_w(sd, OV7670_REG_VSTOP, (vstop >> 2) & 0xff); | 1785 | i2c_w(sd, OV7670_REG_VSTOP, vstop >> 2); |
1809 | v = i2c_r(sd, OV7670_REG_VREF); | 1786 | v = i2c_r(sd, OV7670_REG_VREF); |
1810 | v = (v & 0xc0) | ((vstop & 0x3) << 2) | (vstart & 0x03); | 1787 | v = (v & 0xc0) | ((vstop & 0x3) << 2) | (vstart & 0x03); |
1811 | msleep(10); /* need to sleep between read and write to | 1788 | msleep(10); /* need to sleep between read and write to |
1812 | * same reg! */ | 1789 | * same reg! */ |
1813 | i2c_w(sd, OV7670_REG_VREF, v); | 1790 | i2c_w(sd, OV7670_REG_VREF, v); |
1814 | 1791 | sethvflip(sd); | |
1815 | } else { | 1792 | } else { |
1816 | i2c_w(sd, 0x17, hwsbase + (win->x >> hwscale)); | 1793 | i2c_w(sd, 0x17, hwsbase); |
1817 | i2c_w(sd, 0x18, hwebase + ((win->x + win->width) >> hwscale)); | 1794 | i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale)); |
1818 | i2c_w(sd, 0x19, vwsbase + (win->y >> vwscale)); | 1795 | i2c_w(sd, 0x19, vwsbase); |
1819 | i2c_w(sd, 0x1a, vwebase + ((win->y + win->height) >> vwscale)); | 1796 | i2c_w(sd, 0x1a, vwebase + (sd->gspca_dev.height >> vwscale)); |
1820 | } | 1797 | } |
1821 | return 0; | 1798 | return 0; |
1822 | } | 1799 | } |
1823 | 1800 | ||
1824 | static int ov_sensor_mode_setup(struct sd *sd, | ||
1825 | int width, int height) | ||
1826 | { | ||
1827 | struct ovsensor_window win; | ||
1828 | |||
1829 | /* win.format = mode; */ | ||
1830 | |||
1831 | /* Unless subcapture is enabled, | ||
1832 | * center the image window and downsample | ||
1833 | * if possible to increase the field of view */ | ||
1834 | /* NOTE: OV518(+) and OV519 does downsampling on its own */ | ||
1835 | win.width = width; | ||
1836 | win.height = height; | ||
1837 | if (width == sd->maxwidth) | ||
1838 | win.quarter = 0; | ||
1839 | else | ||
1840 | win.quarter = 1; | ||
1841 | |||
1842 | /* Center it */ | ||
1843 | win.x = (win.width - width) / 2; | ||
1844 | win.y = (win.height - height) / 2; | ||
1845 | |||
1846 | /* Clock is determined by OV519 frame rate code */ | ||
1847 | win.clockdiv = sd->clockdiv; | ||
1848 | |||
1849 | PDEBUG(D_CONF, "Setting clock divider to %d", win.clockdiv); | ||
1850 | return set_ov_sensor_window(sd, &win); | ||
1851 | } | ||
1852 | |||
1853 | /* -- start the camera -- */ | 1801 | /* -- start the camera -- */ |
1854 | static void sd_start(struct gspca_dev *gspca_dev) | 1802 | static void sd_start(struct gspca_dev *gspca_dev) |
1855 | { | 1803 | { |
1856 | struct sd *sd = (struct sd *) gspca_dev; | 1804 | struct sd *sd = (struct sd *) gspca_dev; |
1857 | int ret; | 1805 | int ret; |
1858 | 1806 | ||
1859 | 1807 | ret = ov519_mode_init_regs(sd); | |
1860 | ret = ov519_mode_init_regs(sd, gspca_dev->width, gspca_dev->height); | ||
1861 | if (ret < 0) | 1808 | if (ret < 0) |
1862 | goto out; | 1809 | goto out; |
1863 | ret = ov_sensor_mode_setup(sd, gspca_dev->width, gspca_dev->height); | 1810 | ret = set_ov_sensor_window(sd); |
1864 | if (ret < 0) | 1811 | if (ret < 0) |
1865 | goto out; | 1812 | goto out; |
1866 | 1813 | ||
1867 | ret = ov51x_restart((struct sd *) gspca_dev); | 1814 | ret = ov51x_restart(sd); |
1868 | if (ret < 0) | 1815 | if (ret < 0) |
1869 | goto out; | 1816 | goto out; |
1870 | PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt); | 1817 | PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt); |
@@ -1938,12 +1885,10 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
1938 | { | 1885 | { |
1939 | struct sd *sd = (struct sd *) gspca_dev; | 1886 | struct sd *sd = (struct sd *) gspca_dev; |
1940 | int val; | 1887 | int val; |
1941 | /* int was_streaming; */ | ||
1942 | 1888 | ||
1943 | val = sd->brightness; | 1889 | val = sd->brightness; |
1944 | PDEBUG(D_CONF, "brightness:%d", val); | 1890 | PDEBUG(D_CONF, "brightness:%d", val); |
1945 | /* was_streaming = gspca_dev->streaming; | 1891 | /* if (gspca_dev->streaming) |
1946 | * if (was_streaming) | ||
1947 | * ov51x_stop(sd); */ | 1892 | * ov51x_stop(sd); */ |
1948 | switch (sd->sensor) { | 1893 | switch (sd->sensor) { |
1949 | case SEN_OV8610: | 1894 | case SEN_OV8610: |
@@ -1961,12 +1906,12 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
1961 | i2c_w(sd, OV7610_REG_BRT, val); | 1906 | i2c_w(sd, OV7610_REG_BRT, val); |
1962 | break; | 1907 | break; |
1963 | case SEN_OV7670: | 1908 | case SEN_OV7670: |
1964 | /*jfm - from windblows | 1909 | /*win trace |
1965 | * i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_AEC); */ | 1910 | * i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_AEC); */ |
1966 | i2c_w(sd, OV7670_REG_BRIGHT, ov7670_abs_to_sm(val)); | 1911 | i2c_w(sd, OV7670_REG_BRIGHT, ov7670_abs_to_sm(val)); |
1967 | break; | 1912 | break; |
1968 | } | 1913 | } |
1969 | /* if (was_streaming) | 1914 | /* if (gspca_dev->streaming) |
1970 | * ov51x_restart(sd); */ | 1915 | * ov51x_restart(sd); */ |
1971 | } | 1916 | } |
1972 | 1917 | ||
@@ -1974,12 +1919,10 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
1974 | { | 1919 | { |
1975 | struct sd *sd = (struct sd *) gspca_dev; | 1920 | struct sd *sd = (struct sd *) gspca_dev; |
1976 | int val; | 1921 | int val; |
1977 | /* int was_streaming; */ | ||
1978 | 1922 | ||
1979 | val = sd->contrast; | 1923 | val = sd->contrast; |
1980 | PDEBUG(D_CONF, "contrast:%d", val); | 1924 | PDEBUG(D_CONF, "contrast:%d", val); |
1981 | /* was_streaming = gspca_dev->streaming; | 1925 | /* if (gspca_dev->streaming) |
1982 | if (was_streaming) | ||
1983 | ov51x_stop(sd); */ | 1926 | ov51x_stop(sd); */ |
1984 | switch (sd->sensor) { | 1927 | switch (sd->sensor) { |
1985 | case SEN_OV7610: | 1928 | case SEN_OV7610: |
@@ -2016,7 +1959,7 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
2016 | i2c_w(sd, OV7670_REG_CONTRAS, val >> 1); | 1959 | i2c_w(sd, OV7670_REG_CONTRAS, val >> 1); |
2017 | break; | 1960 | break; |
2018 | } | 1961 | } |
2019 | /* if (was_streaming) | 1962 | /* if (gspca_dev->streaming) |
2020 | ov51x_restart(sd); */ | 1963 | ov51x_restart(sd); */ |
2021 | } | 1964 | } |
2022 | 1965 | ||
@@ -2024,12 +1967,10 @@ static void setcolors(struct gspca_dev *gspca_dev) | |||
2024 | { | 1967 | { |
2025 | struct sd *sd = (struct sd *) gspca_dev; | 1968 | struct sd *sd = (struct sd *) gspca_dev; |
2026 | int val; | 1969 | int val; |
2027 | /* int was_streaming; */ | ||
2028 | 1970 | ||
2029 | val = sd->colors; | 1971 | val = sd->colors; |
2030 | PDEBUG(D_CONF, "saturation:%d", val); | 1972 | PDEBUG(D_CONF, "saturation:%d", val); |
2031 | /* was_streaming = gspca_dev->streaming; | 1973 | /* if (gspca_dev->streaming) |
2032 | if (was_streaming) | ||
2033 | ov51x_stop(sd); */ | 1974 | ov51x_stop(sd); */ |
2034 | switch (sd->sensor) { | 1975 | switch (sd->sensor) { |
2035 | case SEN_OV8610: | 1976 | case SEN_OV8610: |
@@ -2055,7 +1996,7 @@ static void setcolors(struct gspca_dev *gspca_dev) | |||
2055 | /* set REG_COM13 values for UV sat auto mode */ | 1996 | /* set REG_COM13 values for UV sat auto mode */ |
2056 | break; | 1997 | break; |
2057 | } | 1998 | } |
2058 | /* if (was_streaming) | 1999 | /* if (gspca_dev->streaming) |
2059 | ov51x_restart(sd); */ | 2000 | ov51x_restart(sd); */ |
2060 | } | 2001 | } |
2061 | 2002 | ||
@@ -2110,6 +2051,40 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) | |||
2110 | return 0; | 2051 | return 0; |
2111 | } | 2052 | } |
2112 | 2053 | ||
2054 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) | ||
2055 | { | ||
2056 | struct sd *sd = (struct sd *) gspca_dev; | ||
2057 | |||
2058 | sd->hflip = val; | ||
2059 | sethvflip(sd); | ||
2060 | return 0; | ||
2061 | } | ||
2062 | |||
2063 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
2064 | { | ||
2065 | struct sd *sd = (struct sd *) gspca_dev; | ||
2066 | |||
2067 | *val = sd->hflip; | ||
2068 | return 0; | ||
2069 | } | ||
2070 | |||
2071 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) | ||
2072 | { | ||
2073 | struct sd *sd = (struct sd *) gspca_dev; | ||
2074 | |||
2075 | sd->vflip = val; | ||
2076 | sethvflip(sd); | ||
2077 | return 0; | ||
2078 | } | ||
2079 | |||
2080 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
2081 | { | ||
2082 | struct sd *sd = (struct sd *) gspca_dev; | ||
2083 | |||
2084 | *val = sd->vflip; | ||
2085 | return 0; | ||
2086 | } | ||
2087 | |||
2113 | /* sub-driver description */ | 2088 | /* sub-driver description */ |
2114 | static const struct sd_desc sd_desc = { | 2089 | static const struct sd_desc sd_desc = { |
2115 | .name = MODULE_NAME, | 2090 | .name = MODULE_NAME, |
@@ -2178,4 +2153,3 @@ module_exit(sd_mod_exit); | |||
2178 | 2153 | ||
2179 | module_param(frame_rate, int, 0644); | 2154 | module_param(frame_rate, int, 0644); |
2180 | MODULE_PARM_DESC(frame_rate, "Frame rate (5, 10, 15, 20 or 30 fps)"); | 2155 | MODULE_PARM_DESC(frame_rate, "Frame rate (5, 10, 15, 20 or 30 fps)"); |
2181 | |||