// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Sonix sn9c201 sn9c202 library
*
* Copyright (C) 2012 Jean-Francois Moine <http://moinejf.free.fr >
* Copyright (C) 2008-2009 microdia project <microdia@googlegroups.com>
* Copyright (C) 2009 Brian Johnson <brijohn@gmail.com>
*/
#define pr_fmt(fmt) KBUILD_MODNAME
": " fmt
#include <linux/input.h>
#include "gspca.h"
#include "jpeg.h"
#include <linux/dmi.h>
MODULE_AUTHOR(
"Brian Johnson <brijohn@gmail.com>, microdia project <microdia@googlegroups.com>" );
MODULE_DESCRIPTION(
"GSPCA/SN9C20X USB Camera Driver" );
MODULE_LICENSE(
"GPL" );
/*
* Pixel format private data
*/
#define SCALE_MASK
0 x0f
#define SCALE_160x120
0
#define SCALE_320x240
1
#define SCALE_640x480
2
#define SCALE_1280x1024
3
#define MODE_RAW
0 x10
#define MODE_JPEG
0 x20
#define MODE_SXGA
0 x80
#define SENSOR_OV9650
0
#define SENSOR_OV9655
1
#define SENSOR_SOI968
2
#define SENSOR_OV7660
3
#define SENSOR_OV7670
4
#define SENSOR_MT9V011
5
#define SENSOR_MT9V111
6
#define SENSOR_MT9V112
7
#define SENSOR_MT9M001
8
#define SENSOR_MT9M111
9
#define SENSOR_MT9M112
10
#define SENSOR_HV7131R
11
#define SENSOR_MT9VPRB
12
/* camera flags */
#define HAS_NO_BUTTON
0 x1
#define LED_REVERSE
0 x2
/* some cameras unset gpio to turn on leds */
#define FLIP_DETECT
0 x4
#define HAS_LED_TORCH
0 x8
/* specific webcam descriptor */
struct sd {
struct gspca_dev gspca_dev;
struct {
/* color control cluster */
struct v4l2_ctrl *brightness;
struct v4l2_ctrl *contrast;
struct v4l2_ctrl *saturation;
struct v4l2_ctrl *hue;
};
struct {
/* blue/red balance control cluster */
struct v4l2_ctrl *blue;
struct v4l2_ctrl *red;
};
struct {
/* h/vflip control cluster */
struct v4l2_ctrl *hflip;
struct v4l2_ctrl *vflip;
};
struct v4l2_ctrl *gamma;
struct {
/* autogain and exposure or gain control cluster */
struct v4l2_ctrl *autogain;
struct v4l2_ctrl *exposure;
struct v4l2_ctrl *gain;
};
struct v4l2_ctrl *jpegqual;
struct v4l2_ctrl *led_mode;
struct work_struct work;
u32 pktsz;
/* (used by pkt_scan) */
u16 npkt;
s8 nchg;
u8 fmt;
/* (used for JPEG QTAB update */
#define MIN_AVG_LUM
80
#define MAX_AVG_LUM
130
atomic_t avg_lum;
u8 old_step;
u8 older_step;
u8 exposure_step;
u8 i2c_addr;
u8 i2c_intf;
u8 sensor;
u8 hstart;
u8 vstart;
u8 jpeg_hdr[JPEG_HDR_SZ];
u8 flags;
};
static void qual_upd(
struct work_struct *work);
struct i2c_reg_u8 {
u8 reg;
u8 val;
};
struct i2c_reg_u16 {
u8 reg;
u16 val;
};
static const struct dmi_system_id flip_dmi_table[] = {
{
.ident =
"MSI MS-1034" ,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR,
"MICRO-STAR INT'L CO.,LTD." ),
DMI_MATCH(DMI_PRODUCT_NAME,
"MS-1034" ),
DMI_MATCH(DMI_PRODUCT_VERSION,
"0341" )
}
},
{
.ident =
"MSI MS-1039" ,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR,
"MICRO-STAR INT'L CO.,LTD." ),
DMI_MATCH(DMI_PRODUCT_NAME,
"MS-1039" ),
}
},
{
.ident =
"MSI MS-1632" ,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR,
"MSI" ),
DMI_MATCH(DMI_BOARD_NAME,
"MS-1632" )
}
},
{
.ident =
"MSI MS-1633X" ,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR,
"MSI" ),
DMI_MATCH(DMI_BOARD_NAME,
"MS-1633X" )
}
},
{
.ident =
"MSI MS-1635X" ,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR,
"MSI" ),
DMI_MATCH(DMI_BOARD_NAME,
"MS-1635X" )
}
},
{
.ident =
"ASUSTeK W7J" ,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR,
"ASUSTeK Computer Inc." ),
DMI_MATCH(DMI_BOARD_NAME,
"W7J " )
}
},
{}
};
static const struct v4l2_pix_format vga_mode[] = {
{
160 ,
120 , V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline =
160 ,
.sizeimage =
160 *
120 *
4 /
8 +
590 ,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = SCALE_160x120 | MODE_JPEG},
{
160 ,
120 , V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
.bytesperline =
160 ,
.sizeimage =
160 *
120 ,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = SCALE_160x120 | MODE_RAW},
{
160 ,
120 , V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
.bytesperline =
160 ,
.sizeimage =
240 *
120 ,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = SCALE_160x120},
{
320 ,
240 , V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline =
320 ,
.sizeimage =
320 *
240 *
4 /
8 +
590 ,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = SCALE_320x240 | MODE_JPEG},
{
320 ,
240 , V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
.bytesperline =
320 ,
.sizeimage =
320 *
240 ,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = SCALE_320x240 | MODE_RAW},
{
320 ,
240 , V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
.bytesperline =
320 ,
.sizeimage =
480 *
240 ,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = SCALE_320x240},
{
640 ,
480 , V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline =
640 ,
.sizeimage =
640 *
480 *
4 /
8 +
590 ,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = SCALE_640x480 | MODE_JPEG},
{
640 ,
480 , V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
.bytesperline =
640 ,
.sizeimage =
640 *
480 ,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = SCALE_640x480 | MODE_RAW},
{
640 ,
480 , V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
.bytesperline =
640 ,
.sizeimage =
960 *
480 ,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = SCALE_640x480},
};
static const struct v4l2_pix_format sxga_mode[] = {
{
160 ,
120 , V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline =
160 ,
.sizeimage =
160 *
120 *
4 /
8 +
590 ,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = SCALE_160x120 | MODE_JPEG},
{
160 ,
120 , V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
.bytesperline =
160 ,
.sizeimage =
160 *
120 ,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = SCALE_160x120 | MODE_RAW},
{
160 ,
120 , V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
.bytesperline =
160 ,
.sizeimage =
240 *
120 ,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = SCALE_160x120},
{
320 ,
240 , V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline =
320 ,
.sizeimage =
320 *
240 *
4 /
8 +
590 ,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = SCALE_320x240 | MODE_JPEG},
{
320 ,
240 , V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
.bytesperline =
320 ,
.sizeimage =
320 *
240 ,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = SCALE_320x240 | MODE_RAW},
{
320 ,
240 , V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
.bytesperline =
320 ,
.sizeimage =
480 *
240 ,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = SCALE_320x240},
{
640 ,
480 , V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline =
640 ,
.sizeimage =
640 *
480 *
4 /
8 +
590 ,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = SCALE_640x480 | MODE_JPEG},
{
640 ,
480 , V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
.bytesperline =
640 ,
.sizeimage =
640 *
480 ,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = SCALE_640x480 | MODE_RAW},
{
640 ,
480 , V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
.bytesperline =
640 ,
.sizeimage =
960 *
480 ,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = SCALE_640x480},
{
1280 ,
1024 , V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
.bytesperline =
1280 ,
.sizeimage =
1280 *
1024 ,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
};
static const struct v4l2_pix_format mono_mode[] = {
{
160 ,
120 , V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
.bytesperline =
160 ,
.sizeimage =
160 *
120 ,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = SCALE_160x120 | MODE_RAW},
{
320 ,
240 , V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
.bytesperline =
320 ,
.sizeimage =
320 *
240 ,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = SCALE_320x240 | MODE_RAW},
{
640 ,
480 , V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
.bytesperline =
640 ,
.sizeimage =
640 *
480 ,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = SCALE_640x480 | MODE_RAW},
{
1280 ,
1024 , V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
.bytesperline =
1280 ,
.sizeimage =
1280 *
1024 ,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
};
static const s16 hsv_red_x[] = {
41 ,
44 ,
46 ,
48 ,
50 ,
52 ,
54 ,
56 ,
58 ,
60 ,
62 ,
64 ,
66 ,
68 ,
70 ,
72 ,
74 ,
76 ,
78 ,
80 ,
81 ,
83 ,
85 ,
87 ,
88 ,
90 ,
92 ,
93 ,
95 ,
97 ,
98 ,
100 ,
101 ,
102 ,
104 ,
105 ,
107 ,
108 ,
109 ,
110 ,
112 ,
113 ,
114 ,
115 ,
116 ,
117 ,
118 ,
119 ,
120 ,
121 ,
122 ,
123 ,
123 ,
124 ,
125 ,
125 ,
126 ,
127 ,
127 ,
128 ,
128 ,
129 ,
129 ,
129 ,
130 ,
130 ,
130 ,
130 ,
131 ,
131 ,
131 ,
131 ,
131 ,
131 ,
131 ,
131 ,
130 ,
130 ,
130 ,
130 ,
129 ,
129 ,
129 ,
128 ,
128 ,
127 ,
127 ,
126 ,
125 ,
125 ,
124 ,
123 ,
122 ,
122 ,
121 ,
120 ,
119 ,
118 ,
117 ,
116 ,
115 ,
114 ,
112 ,
111 ,
110 ,
109 ,
107 ,
106 ,
105 ,
103 ,
102 ,
101 ,
99 ,
98 ,
96 ,
94 ,
93 ,
91 ,
90 ,
88 ,
86 ,
84 ,
83 ,
81 ,
79 ,
77 ,
75 ,
74 ,
72 ,
70 ,
68 ,
66 ,
64 ,
62 ,
60 ,
58 ,
56 ,
54 ,
52 ,
49 ,
47 ,
45 ,
43 ,
41 ,
39 ,
36 ,
34 ,
32 ,
30 ,
28 ,
25 ,
23 ,
21 ,
19 ,
16 ,
14 ,
12 ,
9 ,
7 ,
5 ,
3 ,
0 , -
1 , -
3 , -
6 , -
8 , -
10 , -
12 ,
-
15 , -
17 , -
19 , -
22 , -
24 , -
26 , -
28 , -
30 ,
-
33 , -
35 , -
37 , -
39 , -
41 , -
44 , -
46 , -
48 ,
-
50 , -
52 , -
54 , -
56 , -
58 , -
60 , -
62 , -
64 ,
-
66 , -
68 , -
70 , -
72 , -
74 , -
76 , -
78 , -
80 ,
-
81 , -
83 , -
85 , -
87 , -
88 , -
90 , -
92 , -
93 ,
-
95 , -
97 , -
98 , -
100 , -
101 , -
102 , -
104 , -
105 ,
-
107 , -
108 , -
109 , -
110 , -
112 , -
113 , -
114 , -
115 ,
-
116 , -
117 , -
118 , -
119 , -
120 , -
121 , -
122 , -
123 ,
-
123 , -
124 , -
125 , -
125 , -
126 , -
127 , -
127 , -
128 ,
-
128 , -
128 , -
128 , -
128 , -
128 , -
128 , -
128 , -
128 ,
-
128 , -
128 , -
128 , -
128 , -
128 , -
128 , -
128 , -
128 ,
-
128 , -
128 , -
128 , -
128 , -
128 , -
128 , -
128 , -
128 ,
-
128 , -
127 , -
127 , -
126 , -
125 , -
125 , -
124 , -
123 ,
-
122 , -
122 , -
121 , -
120 , -
119 , -
118 , -
117 , -
116 ,
-
115 , -
114 , -
112 , -
111 , -
110 , -
109 , -
107 , -
106 ,
-
105 , -
103 , -
102 , -
101 , -
99 , -
98 , -
96 , -
94 ,
-
93 , -
91 , -
90 , -
88 , -
86 , -
84 , -
83 , -
81 ,
-
79 , -
77 , -
75 , -
74 , -
72 , -
70 , -
68 , -
66 ,
-
64 , -
62 , -
60 , -
58 , -
56 , -
54 , -
52 , -
49 ,
-
47 , -
45 , -
43 , -
41 , -
39 , -
36 , -
34 , -
32 ,
-
30 , -
28 , -
25 , -
23 , -
21 , -
19 , -
16 , -
14 ,
-
12 , -
9 , -
7 , -
5 , -
3 ,
0 ,
1 ,
3 ,
6 ,
8 ,
10 ,
12 ,
15 ,
17 ,
19 ,
22 ,
24 ,
26 ,
28 ,
30 ,
33 ,
35 ,
37 ,
39 ,
41
};
static const s16 hsv_red_y[] = {
82 ,
80 ,
78 ,
76 ,
74 ,
73 ,
71 ,
69 ,
67 ,
65 ,
63 ,
61 ,
58 ,
56 ,
54 ,
52 ,
50 ,
48 ,
46 ,
44 ,
41 ,
39 ,
37 ,
35 ,
32 ,
30 ,
28 ,
26 ,
23 ,
21 ,
19 ,
16 ,
14 ,
12 ,
10 ,
7 ,
5 ,
3 ,
0 , -
1 ,
-
3 , -
6 , -
8 , -
10 , -
13 , -
15 , -
17 , -
19 ,
-
22 , -
24 , -
26 , -
29 , -
31 , -
33 , -
35 , -
38 ,
-
40 , -
42 , -
44 , -
46 , -
48 , -
51 , -
53 , -
55 ,
-
57 , -
59 , -
61 , -
63 , -
65 , -
67 , -
69 , -
71 ,
-
73 , -
75 , -
77 , -
79 , -
81 , -
82 , -
84 , -
86 ,
-
88 , -
89 , -
91 , -
93 , -
94 , -
96 , -
98 , -
99 ,
-
101 , -
102 , -
104 , -
105 , -
106 , -
108 , -
109 , -
110 ,
-
112 , -
113 , -
114 , -
115 , -
116 , -
117 , -
119 , -
120 ,
-
120 , -
121 , -
122 , -
123 , -
124 , -
125 , -
126 , -
126 ,
-
127 , -
128 , -
128 , -
128 , -
128 , -
128 , -
128 , -
128 ,
-
128 , -
128 , -
128 , -
128 , -
128 , -
128 , -
128 , -
128 ,
-
128 , -
128 , -
128 , -
128 , -
128 , -
128 , -
128 , -
128 ,
-
128 , -
128 , -
128 , -
128 , -
128 , -
128 , -
128 , -
128 ,
-
127 , -
127 , -
126 , -
125 , -
125 , -
124 , -
123 , -
122 ,
-
121 , -
120 , -
119 , -
118 , -
117 , -
116 , -
115 , -
114 ,
-
113 , -
111 , -
110 , -
109 , -
107 , -
106 , -
105 , -
103 ,
-
102 , -
100 , -
99 , -
97 , -
96 , -
94 , -
92 , -
91 ,
-
89 , -
87 , -
85 , -
84 , -
82 , -
80 , -
78 , -
76 ,
-
74 , -
73 , -
71 , -
69 , -
67 , -
65 , -
63 , -
61 ,
-
58 , -
56 , -
54 , -
52 , -
50 , -
48 , -
46 , -
44 ,
-
41 , -
39 , -
37 , -
35 , -
32 , -
30 , -
28 , -
26 ,
-
23 , -
21 , -
19 , -
16 , -
14 , -
12 , -
10 , -
7 ,
-
5 , -
3 ,
0 ,
1 ,
3 ,
6 ,
8 ,
10 ,
13 ,
15 ,
17 ,
19 ,
22 ,
24 ,
26 ,
29 ,
31 ,
33 ,
35 ,
38 ,
40 ,
42 ,
44 ,
46 ,
48 ,
51 ,
53 ,
55 ,
57 ,
59 ,
61 ,
63 ,
65 ,
67 ,
69 ,
71 ,
73 ,
75 ,
77 ,
79 ,
81 ,
82 ,
84 ,
86 ,
88 ,
89 ,
91 ,
93 ,
94 ,
96 ,
98 ,
99 ,
101 ,
102 ,
104 ,
105 ,
106 ,
108 ,
109 ,
110 ,
112 ,
113 ,
114 ,
115 ,
116 ,
117 ,
119 ,
120 ,
120 ,
121 ,
122 ,
123 ,
124 ,
125 ,
126 ,
126 ,
127 ,
128 ,
128 ,
129 ,
129 ,
130 ,
130 ,
131 ,
131 ,
131 ,
131 ,
132 ,
132 ,
132 ,
132 ,
132 ,
132 ,
132 ,
132 ,
132 ,
132 ,
132 ,
132 ,
131 ,
131 ,
131 ,
130 ,
130 ,
130 ,
129 ,
129 ,
128 ,
127 ,
127 ,
126 ,
125 ,
125 ,
124 ,
123 ,
122 ,
121 ,
120 ,
119 ,
118 ,
117 ,
116 ,
115 ,
114 ,
113 ,
111 ,
110 ,
109 ,
107 ,
106 ,
105 ,
103 ,
102 ,
100 ,
99 ,
97 ,
96 ,
94 ,
92 ,
91 ,
89 ,
87 ,
85 ,
84 ,
82
};
static const s16 hsv_green_x[] = {
-
124 , -
124 , -
125 , -
125 , -
125 , -
125 , -
125 , -
125 ,
-
125 , -
126 , -
126 , -
125 , -
125 , -
125 , -
125 , -
125 ,
-
125 , -
124 , -
124 , -
124 , -
123 , -
123 , -
122 , -
122 ,
-
121 , -
121 , -
120 , -
120 , -
119 , -
118 , -
117 , -
117 ,
-
116 , -
115 , -
114 , -
113 , -
112 , -
111 , -
110 , -
109 ,
-
108 , -
107 , -
105 , -
104 , -
103 , -
102 , -
100 , -
99 ,
-
98 , -
96 , -
95 , -
93 , -
92 , -
91 , -
89 , -
87 ,
-
86 , -
84 , -
83 , -
81 , -
79 , -
77 , -
76 , -
74 ,
-
72 , -
70 , -
69 , -
67 , -
65 , -
63 , -
61 , -
59 ,
-
57 , -
55 , -
53 , -
51 , -
49 , -
47 , -
45 , -
43 ,
-
41 , -
39 , -
37 , -
35 , -
33 , -
30 , -
28 , -
26 ,
-
24 , -
22 , -
20 , -
18 , -
15 , -
13 , -
11 , -
9 ,
-
7 , -
4 , -
2 ,
0 ,
1 ,
3 ,
6 ,
8 ,
10 ,
12 ,
14 ,
17 ,
19 ,
21 ,
23 ,
25 ,
27 ,
29 ,
32 ,
34 ,
36 ,
38 ,
40 ,
42 ,
44 ,
46 ,
48 ,
50 ,
52 ,
54 ,
56 ,
58 ,
60 ,
62 ,
64 ,
66 ,
68 ,
70 ,
71 ,
73 ,
75 ,
77 ,
78 ,
80 ,
82 ,
83 ,
85 ,
87 ,
88 ,
90 ,
91 ,
93 ,
94 ,
96 ,
97 ,
98 ,
100 ,
101 ,
102 ,
104 ,
105 ,
106 ,
107 ,
108 ,
109 ,
111 ,
112 ,
113 ,
113 ,
114 ,
115 ,
116 ,
117 ,
118 ,
118 ,
119 ,
120 ,
120 ,
121 ,
122 ,
122 ,
123 ,
123 ,
124 ,
124 ,
124 ,
125 ,
125 ,
125 ,
125 ,
125 ,
125 ,
125 ,
126 ,
126 ,
125 ,
125 ,
125 ,
125 ,
125 ,
125 ,
124 ,
124 ,
124 ,
123 ,
123 ,
122 ,
122 ,
121 ,
121 ,
120 ,
120 ,
119 ,
118 ,
117 ,
117 ,
116 ,
115 ,
114 ,
113 ,
112 ,
111 ,
110 ,
109 ,
108 ,
107 ,
105 ,
104 ,
103 ,
102 ,
100 ,
99 ,
98 ,
96 ,
95 ,
93 ,
92 ,
91 ,
89 ,
87 ,
86 ,
84 ,
83 ,
81 ,
79 ,
77 ,
76 ,
74 ,
72 ,
70 ,
69 ,
67 ,
65 ,
63 ,
61 ,
59 ,
57 ,
55 ,
53 ,
51 ,
49 ,
47 ,
45 ,
43 ,
41 ,
39 ,
37 ,
35 ,
33 ,
30 ,
28 ,
26 ,
24 ,
22 ,
20 ,
18 ,
15 ,
13 ,
11 ,
9 ,
7 ,
4 ,
2 ,
0 ,
-
1 , -
3 , -
6 , -
8 , -
10 , -
12 , -
14 , -
17 ,
-
19 , -
21 , -
23 , -
25 , -
27 , -
29 , -
32 , -
34 ,
-
36 , -
38 , -
40 , -
42 , -
44 , -
46 , -
48 , -
50 ,
-
52 , -
54 , -
56 , -
58 , -
60 , -
62 , -
64 , -
66 ,
-
68 , -
70 , -
71 , -
73 , -
75 , -
77 , -
78 , -
80 ,
-
82 , -
83 , -
85 , -
87 , -
88 , -
90 , -
91 , -
93 ,
-
94 , -
96 , -
97 , -
98 , -
100 , -
101 , -
102 , -
104 ,
-
105 , -
106 , -
107 , -
108 , -
109 , -
111 , -
112 , -
113 ,
-
113 , -
114 , -
115 , -
116 , -
117 , -
118 , -
118 , -
119 ,
-
120 , -
120 , -
121 , -
122 , -
122 , -
123 , -
123 , -
124 , -
124
};
static const s16 hsv_green_y[] = {
-
100 , -
99 , -
98 , -
97 , -
95 , -
94 , -
93 , -
91 ,
-
90 , -
89 , -
87 , -
86 , -
84 , -
83 , -
81 , -
80 ,
-
78 , -
76 , -
75 , -
73 , -
71 , -
70 , -
68 , -
66 ,
-
64 , -
63 , -
61 , -
59 , -
57 , -
55 , -
53 , -
51 ,
-
49 , -
48 , -
46 , -
44 , -
42 , -
40 , -
38 , -
36 ,
-
34 , -
32 , -
30 , -
27 , -
25 , -
23 , -
21 , -
19 ,
-
17 , -
15 , -
13 , -
11 , -
9 , -
7 , -
4 , -
2 ,
0 ,
1 ,
3 ,
5 ,
7 ,
9 ,
11 ,
14 ,
16 ,
18 ,
20 ,
22 ,
24 ,
26 ,
28 ,
30 ,
32 ,
34 ,
36 ,
38 ,
40 ,
42 ,
44 ,
46 ,
48 ,
50 ,
52 ,
54 ,
56 ,
58 ,
59 ,
61 ,
63 ,
65 ,
67 ,
68 ,
70 ,
72 ,
74 ,
75 ,
77 ,
78 ,
80 ,
82 ,
83 ,
85 ,
86 ,
88 ,
89 ,
90 ,
92 ,
93 ,
95 ,
96 ,
97 ,
98 ,
100 ,
101 ,
102 ,
103 ,
104 ,
105 ,
106 ,
107 ,
108 ,
109 ,
110 ,
111 ,
112 ,
112 ,
113 ,
114 ,
115 ,
115 ,
116 ,
116 ,
117 ,
117 ,
118 ,
118 ,
119 ,
119 ,
119 ,
120 ,
120 ,
120 ,
120 ,
120 ,
121 ,
121 ,
121 ,
121 ,
121 ,
121 ,
120 ,
120 ,
120 ,
120 ,
120 ,
119 ,
119 ,
119 ,
118 ,
118 ,
117 ,
117 ,
116 ,
116 ,
115 ,
114 ,
114 ,
113 ,
112 ,
111 ,
111 ,
110 ,
109 ,
108 ,
107 ,
106 ,
105 ,
104 ,
103 ,
102 ,
100 ,
99 ,
98 ,
97 ,
95 ,
94 ,
93 ,
91 ,
90 ,
89 ,
87 ,
86 ,
84 ,
83 ,
81 ,
80 ,
78 ,
76 ,
75 ,
73 ,
71 ,
70 ,
68 ,
66 ,
64 ,
63 ,
61 ,
59 ,
57 ,
55 ,
53 ,
51 ,
49 ,
48 ,
46 ,
44 ,
42 ,
40 ,
38 ,
36 ,
34 ,
32 ,
30 ,
27 ,
25 ,
23 ,
21 ,
19 ,
17 ,
15 ,
13 ,
11 ,
9 ,
7 ,
4 ,
2 ,
0 , -
1 , -
3 , -
5 ,
-
7 , -
9 , -
11 , -
14 , -
16 , -
18 , -
20 , -
22 ,
-
24 , -
26 , -
28 , -
30 , -
32 , -
34 , -
36 , -
38 ,
-
40 , -
42 , -
44 , -
46 , -
48 , -
50 , -
52 , -
54 ,
-
56 , -
58 , -
59 , -
61 , -
63 , -
65 , -
67 , -
68 ,
-
70 , -
72 , -
74 , -
75 , -
77 , -
78 , -
80 , -
82 ,
-
83 , -
85 , -
86 , -
88 , -
89 , -
90 , -
92 , -
93 ,
-
95 , -
96 , -
97 , -
98 , -
100 , -
101 , -
102 , -
103 ,
-
104 , -
105 , -
106 , -
107 , -
108 , -
109 , -
110 , -
111 ,
-
112 , -
112 , -
113 , -
114 , -
115 , -
115 , -
116 , -
116 ,
-
117 , -
117 , -
118 , -
118 , -
119 , -
119 , -
119 , -
120 ,
-
120 , -
120 , -
120 , -
120 , -
121 , -
121 , -
121 , -
121 ,
-
121 , -
121 , -
120 , -
120 , -
120 , -
120 , -
120 , -
119 ,
-
119 , -
119 , -
118 , -
118 , -
117 , -
117 , -
116 , -
116 ,
-
115 , -
114 , -
114 , -
113 , -
112 , -
111 , -
111 , -
110 ,
-
109 , -
108 , -
107 , -
106 , -
105 , -
104 , -
103 , -
102 , -
100
};
static const s16 hsv_blue_x[] = {
112 ,
113 ,
114 ,
114 ,
115 ,
116 ,
117 ,
117 ,
118 ,
118 ,
119 ,
119 ,
120 ,
120 ,
120 ,
121 ,
121 ,
121 ,
122 ,
122 ,
122 ,
122 ,
122 ,
122 ,
122 ,
122 ,
122 ,
122 ,
122 ,
122 ,
121 ,
121 ,
121 ,
120 ,
120 ,
120 ,
119 ,
119 ,
118 ,
118 ,
117 ,
116 ,
116 ,
115 ,
114 ,
113 ,
113 ,
112 ,
111 ,
110 ,
109 ,
108 ,
107 ,
106 ,
105 ,
104 ,
103 ,
102 ,
100 ,
99 ,
98 ,
97 ,
95 ,
94 ,
93 ,
91 ,
90 ,
88 ,
87 ,
85 ,
84 ,
82 ,
80 ,
79 ,
77 ,
76 ,
74 ,
72 ,
70 ,
69 ,
67 ,
65 ,
63 ,
61 ,
60 ,
58 ,
56 ,
54 ,
52 ,
50 ,
48 ,
46 ,
44 ,
42 ,
40 ,
38 ,
36 ,
34 ,
32 ,
30 ,
28 ,
26 ,
24 ,
22 ,
19 ,
17 ,
15 ,
13 ,
11 ,
9 ,
7 ,
5 ,
2 ,
0 , -
1 , -
3 , -
5 , -
7 , -
9 , -
12 ,
-
14 , -
16 , -
18 , -
20 , -
22 , -
24 , -
26 , -
28 ,
-
31 , -
33 , -
35 , -
37 , -
39 , -
41 , -
43 , -
45 ,
-
47 , -
49 , -
51 , -
53 , -
54 , -
56 , -
58 , -
60 ,
-
62 , -
64 , -
66 , -
67 , -
69 , -
71 , -
73 , -
74 ,
-
76 , -
78 , -
79 , -
81 , -
83 , -
84 , -
86 , -
87 ,
-
89 , -
90 , -
92 , -
93 , -
94 , -
96 , -
97 , -
98 ,
-
99 , -
101 , -
102 , -
103 , -
104 , -
105 , -
106 , -
107 ,
-
108 , -
109 , -
110 , -
111 , -
112 , -
113 , -
114 , -
114 ,
-
115 , -
116 , -
117 , -
117 , -
118 , -
118 , -
119 , -
119 ,
-
120 , -
120 , -
120 , -
121 , -
121 , -
121 , -
122 , -
122 ,
-
122 , -
122 , -
122 , -
122 , -
122 , -
122 , -
122 , -
122 ,
-
122 , -
122 , -
121 , -
121 , -
121 , -
120 , -
120 , -
120 ,
-
119 , -
119 , -
118 , -
118 , -
117 , -
116 , -
116 , -
115 ,
-
114 , -
113 , -
113 , -
112 , -
111 , -
110 , -
109 , -
108 ,
-
107 , -
106 , -
105 , -
104 , -
103 , -
102 , -
100 , -
99 ,
-
98 , -
97 , -
95 , -
94 , -
93 , -
91 , -
90 , -
88 ,
-
87 , -
85 , -
84 , -
82 , -
80 , -
79 , -
77 , -
76 ,
-
74 , -
72 , -
70 , -
69 , -
67 , -
65 , -
63 , -
61 ,
-
60 , -
58 , -
56 , -
54 , -
52 , -
50 , -
48 , -
46 ,
-
44 , -
42 , -
40 , -
38 , -
36 , -
34 , -
32 , -
30 ,
-
28 , -
26 , -
24 , -
22 , -
19 , -
17 , -
15 , -
13 ,
-
11 , -
9 , -
7 , -
5 , -
2 ,
0 ,
1 ,
3 ,
5 ,
7 ,
9 ,
12 ,
14 ,
16 ,
18 ,
20 ,
22 ,
24 ,
26 ,
28 ,
31 ,
33 ,
35 ,
37 ,
39 ,
41 ,
43 ,
45 ,
47 ,
49 ,
51 ,
53 ,
54 ,
56 ,
58 ,
60 ,
62 ,
64 ,
66 ,
67 ,
69 ,
71 ,
73 ,
74 ,
76 ,
78 ,
79 ,
81 ,
83 ,
84 ,
86 ,
87 ,
89 ,
90 ,
92 ,
93 ,
94 ,
96 ,
97 ,
98 ,
99 ,
101 ,
102 ,
103 ,
104 ,
105 ,
106 ,
107 ,
108 ,
109 ,
110 ,
111 ,
112
};
static const s16 hsv_blue_y[] = {
-
11 , -
13 , -
15 , -
17 , -
19 , -
21 , -
23 , -
25 ,
-
27 , -
29 , -
31 , -
33 , -
35 , -
37 , -
39 , -
41 ,
-
43 , -
45 , -
46 , -
48 , -
50 , -
52 , -
54 , -
55 ,
-
57 , -
59 , -
61 , -
62 , -
64 , -
66 , -
67 , -
69 ,
-
71 , -
72 , -
74 , -
75 , -
77 , -
78 , -
80 , -
81 ,
-
83 , -
84 , -
86 , -
87 , -
88 , -
90 , -
91 , -
92 ,
-
93 , -
95 , -
96 , -
97 , -
98 , -
99 , -
100 , -
101 ,
-
102 , -
103 , -
104 , -
105 , -
106 , -
106 , -
107 , -
108 ,
-
109 , -
109 , -
110 , -
111 , -
111 , -
112 , -
112 , -
113 ,
-
113 , -
114 , -
114 , -
114 , -
115 , -
115 , -
115 , -
115 ,
-
116 , -
116 , -
116 , -
116 , -
116 , -
116 , -
116 , -
116 ,
-
116 , -
115 , -
115 , -
115 , -
115 , -
114 , -
114 , -
114 ,
-
113 , -
113 , -
112 , -
112 , -
111 , -
111 , -
110 , -
110 ,
-
109 , -
108 , -
108 , -
107 , -
106 , -
105 , -
104 , -
103 ,
-
102 , -
101 , -
100 , -
99 , -
98 , -
97 , -
96 , -
95 ,
-
94 , -
93 , -
91 , -
90 , -
89 , -
88 , -
86 , -
85 ,
-
84 , -
82 , -
81 , -
79 , -
78 , -
76 , -
75 , -
73 ,
-
71 , -
70 , -
68 , -
67 , -
65 , -
63 , -
62 , -
60 ,
-
58 , -
56 , -
55 , -
53 , -
51 , -
49 , -
47 , -
45 ,
-
44 , -
42 , -
40 , -
38 , -
36 , -
34 , -
32 , -
30 ,
-
28 , -
26 , -
24 , -
22 , -
20 , -
18 , -
16 , -
14 ,
-
12 , -
10 , -
8 , -
6 , -
4 , -
2 ,
0 ,
1 ,
3 ,
5 ,
7 ,
9 ,
11 ,
13 ,
15 ,
17 ,
19 ,
21 ,
23 ,
25 ,
27 ,
29 ,
31 ,
33 ,
35 ,
37 ,
39 ,
41 ,
43 ,
45 ,
46 ,
48 ,
50 ,
52 ,
54 ,
55 ,
57 ,
59 ,
61 ,
62 ,
64 ,
66 ,
67 ,
69 ,
71 ,
72 ,
74 ,
75 ,
77 ,
78 ,
80 ,
81 ,
83 ,
84 ,
86 ,
87 ,
88 ,
90 ,
91 ,
92 ,
93 ,
95 ,
96 ,
97 ,
98 ,
99 ,
100 ,
101 ,
102 ,
103 ,
104 ,
105 ,
106 ,
106 ,
107 ,
108 ,
109 ,
109 ,
110 ,
111 ,
111 ,
112 ,
112 ,
113 ,
113 ,
114 ,
114 ,
114 ,
115 ,
115 ,
115 ,
115 ,
116 ,
116 ,
116 ,
116 ,
116 ,
116 ,
116 ,
116 ,
116 ,
115 ,
115 ,
115 ,
115 ,
114 ,
114 ,
114 ,
113 ,
113 ,
112 ,
112 ,
111 ,
111 ,
110 ,
110 ,
109 ,
108 ,
108 ,
107 ,
106 ,
105 ,
104 ,
103 ,
102 ,
101 ,
100 ,
99 ,
98 ,
97 ,
96 ,
95 ,
94 ,
93 ,
91 ,
90 ,
89 ,
88 ,
86 ,
85 ,
84 ,
82 ,
81 ,
79 ,
78 ,
76 ,
75 ,
73 ,
71 ,
70 ,
68 ,
67 ,
65 ,
63 ,
62 ,
60 ,
58 ,
56 ,
55 ,
53 ,
51 ,
49 ,
47 ,
45 ,
44 ,
42 ,
40 ,
38 ,
36 ,
34 ,
32 ,
30 ,
28 ,
26 ,
24 ,
22 ,
20 ,
18 ,
16 ,
14 ,
12 ,
10 ,
8 ,
6 ,
4 ,
2 ,
0 , -
1 , -
3 , -
5 , -
7 , -
9 , -
11
};
static const u16 bridge_init[][
2 ] = {
{
0 x1000,
0 x78}, {
0 x1001,
0 x40}, {
0 x1002,
0 x1c},
{
0 x1020,
0 x80}, {
0 x1061,
0 x01}, {
0 x1067,
0 x40},
{
0 x1068,
0 x30}, {
0 x1069,
0 x20}, {
0 x106a,
0 x10},
{
0 x106b,
0 x08}, {
0 x1188,
0 x87}, {
0 x11a1,
0 x00},
{
0 x11a2,
0 x00}, {
0 x11a3,
0 x6a}, {
0 x11a4,
0 x50},
{
0 x11ab,
0 x00}, {
0 x11ac,
0 x00}, {
0 x11ad,
0 x50},
{
0 x11ae,
0 x3c}, {
0 x118a,
0 x04}, {
0 x0395,
0 x04},
{
0 x11b8,
0 x3a}, {
0 x118b,
0 x0e}, {
0 x10f7,
0 x05},
{
0 x10f8,
0 x14}, {
0 x10fa,
0 xff}, {
0 x10f9,
0 x00},
{
0 x11ba,
0 x0a}, {
0 x11a5,
0 x2d}, {
0 x11a6,
0 x2d},
{
0 x11a7,
0 x3a}, {
0 x11a8,
0 x05}, {
0 x11a9,
0 x04},
{
0 x11aa,
0 x3f}, {
0 x11af,
0 x28}, {
0 x11b0,
0 xd8},
{
0 x11b1,
0 x14}, {
0 x11b2,
0 xec}, {
0 x11b3,
0 x32},
{
0 x11b4,
0 xdd}, {
0 x11b5,
0 x32}, {
0 x11b6,
0 xdd},
{
0 x10e0,
0 x2c}, {
0 x11bc,
0 x40}, {
0 x11bd,
0 x01},
{
0 x11be,
0 xf0}, {
0 x11bf,
0 x00}, {
0 x118c,
0 x1f},
{
0 x118d,
0 x1f}, {
0 x118e,
0 x1f}, {
0 x118f,
0 x1f},
{
0 x1180,
0 x01}, {
0 x1181,
0 x00}, {
0 x1182,
0 x01},
{
0 x1183,
0 x00}, {
0 x1184,
0 x50}, {
0 x1185,
0 x80},
{
0 x1007,
0 x00}
};
/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */
static const u8 ov_gain[] = {
0 x00
/* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */,
0 x10
/* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */,
0 x18
/* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */,
0 x30
/* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */,
0 x34
/* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */,
0 x38
/* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */,
0 x3c
/* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */,
0 x70
/* 8x */
};
/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */
static const u16 micron1_gain[] = {
/* 1x 1.25x 1.5x 1.75x */
0 x0020,
0 x0028,
0 x0030,
0 x0038,
/* 2x 2.25x 2.5x 2.75x */
0 x00a0,
0 x00a4,
0 x00a8,
0 x00ac,
/* 3x 3.25x 3.5x 3.75x */
0 x00b0,
0 x00b4,
0 x00b8,
0 x00bc,
/* 4x 4.25x 4.5x 4.75x */
0 x00c0,
0 x00c4,
0 x00c8,
0 x00cc,
/* 5x 5.25x 5.5x 5.75x */
0 x00d0,
0 x00d4,
0 x00d8,
0 x00dc,
/* 6x 6.25x 6.5x 6.75x */
0 x00e0,
0 x00e4,
0 x00e8,
0 x00ec,
/* 7x 7.25x 7.5x 7.75x */
0 x00f0,
0 x00f4,
0 x00f8,
0 x00fc,
/* 8x */
0 x01c0
};
/* mt9m001 sensor uses a different gain formula then other micron sensors */
/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */
static const u16 micron2_gain[] = {
/* 1x 1.25x 1.5x 1.75x */
0 x0008,
0 x000a,
0 x000c,
0 x000e,
/* 2x 2.25x 2.5x 2.75x */
0 x0010,
0 x0012,
0 x0014,
0 x0016,
/* 3x 3.25x 3.5x 3.75x */
0 x0018,
0 x001a,
0 x001c,
0 x001e,
/* 4x 4.25x 4.5x 4.75x */
0 x0020,
0 x0051,
0 x0052,
0 x0053,
/* 5x 5.25x 5.5x 5.75x */
0 x0054,
0 x0055,
0 x0056,
0 x0057,
/* 6x 6.25x 6.5x 6.75x */
0 x0058,
0 x0059,
0 x005a,
0 x005b,
/* 7x 7.25x 7.5x 7.75x */
0 x005c,
0 x005d,
0 x005e,
0 x005f,
/* 8x */
0 x0060
};
/* Gain = .5 + bit[7:0] / 16 */
static const u8 hv7131r_gain[] = {
0 x08
/* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */,
0 x18
/* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */,
0 x28
/* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */,
0 x38
/* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */,
0 x48
/* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */,
0 x58
/* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */,
0 x68
/* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */,
0 x78
/* 8x */
};
static const struct i2c_reg_u8 soi968_init[] = {
{
0 x0c,
0 x00}, {
0 x0f,
0 x1f},
{
0 x11,
0 x80}, {
0 x38,
0 x52}, {
0 x1e,
0 x00},
{
0 x33,
0 x08}, {
0 x35,
0 x8c}, {
0 x36,
0 x0c},
{
0 x37,
0 x04}, {
0 x45,
0 x04}, {
0 x47,
0 xff},
{
0 x3e,
0 x00}, {
0 x3f,
0 x00}, {
0 x3b,
0 x20},
{
0 x3a,
0 x96}, {
0 x3d,
0 x0a}, {
0 x14,
0 x8e},
{
0 x13,
0 x8b}, {
0 x12,
0 x40}, {
0 x17,
0 x13},
{
0 x18,
0 x63}, {
0 x19,
0 x01}, {
0 x1a,
0 x79},
{
0 x32,
0 x24}, {
0 x03,
0 x00}, {
0 x11,
0 x40},
{
0 x2a,
0 x10}, {
0 x2b,
0 xe0}, {
0 x10,
0 x32},
{
0 x00,
0 x00}, {
0 x01,
0 x80}, {
0 x02,
0 x80},
};
static const struct i2c_reg_u8 ov7660_init[] = {
{
0 x0e,
0 x80}, {
0 x0d,
0 x08}, {
0 x0f,
0 xc3},
{
0 x04,
0 xc3}, {
0 x10,
0 x40}, {
0 x11,
0 x40},
{
0 x12,
0 x05}, {
0 x13,
0 xba}, {
0 x14,
0 x2a},
/* HDG Set hstart and hstop, datasheet default 0x11, 0x61, using
0x10, 0x61 and sd->hstart, vstart = 3, fixes ugly colored borders */
{
0 x17,
0 x10}, {
0 x18,
0 x61},
{
0 x37,
0 x0f}, {
0 x38,
0 x02}, {
0 x39,
0 x43},
{
0 x3a,
0 x00}, {
0 x69,
0 x90}, {
0 x2d,
0 x00},
{
0 x2e,
0 x00}, {
0 x01,
0 x78}, {
0 x02,
0 x50},
};
static const struct i2c_reg_u8 ov7670_init[] = {
{
0 x11,
0 x80}, {
0 x3a,
0 x04}, {
0 x12,
0 x01},
{
0 x32,
0 xb6}, {
0 x03,
0 x0a}, {
0 x0c,
0 x00}, {
0 x3e,
0 x00},
{
0 x70,
0 x3a}, {
0 x71,
0 x35}, {
0 x72,
0 x11}, {
0 x73,
0 xf0},
{
0 xa2,
0 x02}, {
0 x13,
0 xe0}, {
0 x00,
0 x00}, {
0 x10,
0 x00},
{
0 x0d,
0 x40}, {
0 x14,
0 x28}, {
0 xa5,
0 x05}, {
0 xab,
0 x07},
{
0 x24,
0 x95}, {
0 x25,
0 x33}, {
0 x26,
0 xe3}, {
0 x9f,
0 x75},
{
0 xa0,
0 x65}, {
0 xa1,
0 x0b}, {
0 xa6,
0 xd8}, {
0 xa7,
0 xd8},
{
0 xa8,
0 xf0}, {
0 xa9,
0 x90}, {
0 xaa,
0 x94}, {
0 x13,
0 xe5},
{
0 x0e,
0 x61}, {
0 x0f,
0 x4b}, {
0 x16,
0 x02}, {
0 x1e,
0 x27},
{
0 x21,
0 x02}, {
0 x22,
0 x91}, {
0 x29,
0 x07}, {
0 x33,
0 x0b},
{
0 x35,
0 x0b}, {
0 x37,
0 x1d}, {
0 x38,
0 x71}, {
0 x39,
0 x2a},
{
0 x3c,
0 x78}, {
0 x4d,
0 x40}, {
0 x4e,
0 x20}, {
0 x69,
0 x00},
{
0 x74,
0 x19}, {
0 x8d,
0 x4f}, {
0 x8e,
0 x00}, {
0 x8f,
0 x00},
{
0 x90,
0 x00}, {
0 x91,
0 x00}, {
0 x96,
0 x00}, {
0 x9a,
0 x80},
{
0 xb0,
0 x84}, {
0 xb1,
0 x0c}, {
0 xb2,
0 x0e}, {
0 xb3,
0 x82},
{
0 xb8,
0 x0a}, {
0 x43,
0 x0a}, {
0 x44,
0 xf0}, {
0 x45,
0 x20},
{
0 x46,
0 x7d}, {
0 x47,
0 x29}, {
0 x48,
0 x4a}, {
0 x59,
0 x8c},
{
0 x5a,
0 xa5}, {
0 x5b,
0 xde}, {
0 x5c,
0 x96}, {
0 x5d,
0 x66},
{
0 x5e,
0 x10}, {
0 x6c,
0 x0a}, {
0 x6d,
0 x55}, {
0 x6e,
0 x11},
{
0 x6f,
0 x9e}, {
0 x6a,
0 x40}, {
0 x01,
0 x40}, {
0 x02,
0 x40},
{
0 x13,
0 xe7}, {
0 x4f,
0 x6e}, {
0 x50,
0 x70}, {
0 x51,
0 x02},
{
0 x52,
0 x1d}, {
0 x53,
0 x56}, {
0 x54,
0 x73}, {
0 x55,
0 x0a},
{
0 x56,
0 x55}, {
0 x57,
0 x80}, {
0 x58,
0 x9e}, {
0 x41,
0 x08},
{
0 x3f,
0 x02}, {
0 x75,
0 x03}, {
0 x76,
0 x63}, {
0 x4c,
0 x04},
{
0 x77,
0 x06}, {
0 x3d,
0 x02}, {
0 x4b,
0 x09}, {
0 xc9,
0 x30},
{
0 x41,
0 x08}, {
0 x56,
0 x48}, {
0 x34,
0 x11}, {
0 xa4,
0 x88},
{
0 x96,
0 x00}, {
0 x97,
0 x30}, {
0 x98,
0 x20}, {
0 x99,
0 x30},
{
0 x9a,
0 x84}, {
0 x9b,
0 x29}, {
0 x9c,
0 x03}, {
0 x9d,
0 x99},
{
0 x9e,
0 x7f}, {
0 x78,
0 x04}, {
0 x79,
0 x01}, {
0 xc8,
0 xf0},
{
0 x79,
0 x0f}, {
0 xc8,
0 x00}, {
0 x79,
0 x10}, {
0 xc8,
0 x7e},
{
0 x79,
0 x0a}, {
0 xc8,
0 x80}, {
0 x79,
0 x0b}, {
0 xc8,
0 x01},
{
0 x79,
0 x0c}, {
0 xc8,
0 x0f}, {
0 x79,
0 x0d}, {
0 xc8,
0 x20},
{
0 x79,
0 x09}, {
0 xc8,
0 x80}, {
0 x79,
0 x02}, {
0 xc8,
0 xc0},
{
0 x79,
0 x03}, {
0 xc8,
0 x40}, {
0 x79,
0 x05}, {
0 xc8,
0 x30},
{
0 x79,
0 x26}, {
0 x62,
0 x20}, {
0 x63,
0 x00}, {
0 x64,
0 x06},
{
0 x65,
0 x00}, {
0 x66,
0 x05}, {
0 x94,
0 x05}, {
0 x95,
0 x0a},
{
0 x17,
0 x13}, {
0 x18,
0 x01}, {
0 x19,
0 x02}, {
0 x1a,
0 x7a},
{
0 x46,
0 x59}, {
0 x47,
0 x30}, {
0 x58,
0 x9a}, {
0 x59,
0 x84},
{
0 x5a,
0 x91}, {
0 x5b,
0 x57}, {
0 x5c,
0 x75}, {
0 x5d,
0 x6d},
{
0 x5e,
0 x13}, {
0 x64,
0 x07}, {
0 x94,
0 x07}, {
0 x95,
0 x0d},
{
0 xa6,
0 xdf}, {
0 xa7,
0 xdf}, {
0 x48,
0 x4d}, {
0 x51,
0 x00},
{
0 x6b,
0 x0a}, {
0 x11,
0 x80}, {
0 x2a,
0 x00}, {
0 x2b,
0 x00},
{
0 x92,
0 x00}, {
0 x93,
0 x00}, {
0 x55,
0 x0a}, {
0 x56,
0 x60},
{
0 x4f,
0 x6e}, {
0 x50,
0 x70}, {
0 x51,
0 x00}, {
0 x52,
0 x1d},
{
0 x53,
0 x56}, {
0 x54,
0 x73}, {
0 x58,
0 x9a}, {
0 x4f,
0 x6e},
{
0 x50,
0 x70}, {
0 x51,
0 x00}, {
0 x52,
0 x1d}, {
0 x53,
0 x56},
{
0 x54,
0 x73}, {
0 x58,
0 x9a}, {
0 x3f,
0 x01}, {
0 x7b,
0 x03},
{
0 x7c,
0 x09}, {
0 x7d,
0 x16}, {
0 x7e,
0 x38}, {
0 x7f,
0 x47},
{
0 x80,
0 x53}, {
0 x81,
0 x5e}, {
0 x82,
0 x6a}, {
0 x83,
0 x74},
{
0 x84,
0 x80}, {
0 x85,
0 x8c}, {
0 x86,
0 x9b}, {
0 x87,
0 xb2},
{
0 x88,
0 xcc}, {
0 x89,
0 xe5}, {
0 x7a,
0 x24}, {
0 x3b,
0 x00},
{
0 x9f,
0 x76}, {
0 xa0,
0 x65}, {
0 x13,
0 xe2}, {
0 x6b,
0 x0a},
{
0 x11,
0 x80}, {
0 x2a,
0 x00}, {
0 x2b,
0 x00}, {
0 x92,
0 x00},
{
0 x93,
0 x00},
};
static const struct i2c_reg_u8 ov9650_init[] = {
{
0 x00,
0 x00}, {
0 x01,
0 x78},
{
0 x02,
0 x78}, {
0 x03,
0 x36}, {
0 x04,
0 x03},
{
0 x05,
0 x00}, {
0 x06,
0 x00}, {
0 x08,
0 x00},
{
0 x09,
0 x01}, {
0 x0c,
0 x00}, {
0 x0d,
0 x00},
{
0 x0e,
0 xa0}, {
0 x0f,
0 x52}, {
0 x10,
0 x7c},
{
0 x11,
0 x80}, {
0 x12,
0 x45}, {
0 x13,
0 xc2},
{
0 x14,
0 x2e}, {
0 x15,
0 x00}, {
0 x16,
0 x07},
{
0 x17,
0 x24}, {
0 x18,
0 xc5}, {
0 x19,
0 x00},
{
0 x1a,
0 x3c}, {
0 x1b,
0 x00}, {
0 x1e,
0 x04},
{
0 x1f,
0 x00}, {
0 x24,
0 x78}, {
0 x25,
0 x68},
{
0 x26,
0 xd4}, {
0 x27,
0 x80}, {
0 x28,
0 x80},
{
0 x29,
0 x30}, {
0 x2a,
0 x00}, {
0 x2b,
0 x00},
{
0 x2c,
0 x80}, {
0 x2d,
0 x00}, {
0 x2e,
0 x00},
{
0 x2f,
0 x00}, {
0 x30,
0 x08}, {
0 x31,
0 x30},
{
0 x32,
0 x84}, {
0 x33,
0 xe2}, {
0 x34,
0 xbf},
{
0 x35,
0 x81}, {
0 x36,
0 xf9}, {
0 x37,
0 x00},
{
0 x38,
0 x93}, {
0 x39,
0 x50}, {
0 x3a,
0 x01},
{
0 x3b,
0 x01}, {
0 x3c,
0 x73}, {
0 x3d,
0 x19},
{
0 x3e,
0 x0b}, {
0 x3f,
0 x80}, {
0 x40,
0 xc1},
{
0 x41,
0 x00}, {
0 x42,
0 x08}, {
0 x67,
0 x80},
{
0 x68,
0 x80}, {
0 x69,
0 x40}, {
0 x6a,
0 x00},
{
0 x6b,
0 x0a}, {
0 x8b,
0 x06}, {
0 x8c,
0 x20},
{
0 x8d,
0 x00}, {
0 x8e,
0 x00}, {
0 x8f,
0 xdf},
{
0 x92,
0 x00}, {
0 x93,
0 x00}, {
0 x94,
0 x88},
{
0 x95,
0 x88}, {
0 x96,
0 x04}, {
0 xa1,
0 x00},
{
0 xa5,
0 x80}, {
0 xa8,
0 x80}, {
0 xa9,
0 xb8},
{
0 xaa,
0 x92}, {
0 xab,
0 x0a},
};
static const struct i2c_reg_u8 ov9655_init[] = {
{
0 x0e,
0 x61}, {
0 x11,
0 x80}, {
0 x13,
0 xba},
{
0 x14,
0 x2e}, {
0 x16,
0 x24}, {
0 x1e,
0 x04}, {
0 x27,
0 x08},
{
0 x28,
0 x08}, {
0 x29,
0 x15}, {
0 x2c,
0 x08}, {
0 x34,
0 x3d},
{
0 x35,
0 x00}, {
0 x38,
0 x12}, {
0 x0f,
0 x42}, {
0 x39,
0 x57},
{
0 x3a,
0 x00}, {
0 x3b,
0 xcc}, {
0 x3c,
0 x0c}, {
0 x3d,
0 x19},
{
0 x3e,
0 x0c}, {
0 x3f,
0 x01}, {
0 x41,
0 x40}, {
0 x42,
0 x80},
{
0 x45,
0 x46}, {
0 x46,
0 x62}, {
0 x47,
0 x2a}, {
0 x48,
0 x3c},
{
0 x4a,
0 xf0}, {
0 x4b,
0 xdc}, {
0 x4c,
0 xdc}, {
0 x4d,
0 xdc},
{
0 x4e,
0 xdc}, {
0 x6c,
0 x04}, {
0 x6f,
0 x9e}, {
0 x70,
0 x05},
{
0 x71,
0 x78}, {
0 x77,
0 x02}, {
0 x8a,
0 x23}, {
0 x90,
0 x7e},
{
0 x91,
0 x7c}, {
0 x9f,
0 x6e}, {
0 xa0,
0 x6e}, {
0 xa5,
0 x68},
{
0 xa6,
0 x60}, {
0 xa8,
0 xc1}, {
0 xa9,
0 xfa}, {
0 xaa,
0 x92},
{
0 xab,
0 x04}, {
0 xac,
0 x80}, {
0 xad,
0 x80}, {
0 xae,
0 x80},
{
0 xaf,
0 x80}, {
0 xb2,
0 xf2}, {
0 xb3,
0 x20}, {
0 xb5,
0 x00},
{
0 xb6,
0 xaf}, {
0 xbb,
0 xae}, {
0 xbc,
0 x44}, {
0 xbd,
0 x44},
{
0 xbe,
0 x3b}, {
0 xbf,
0 x3a}, {
0 xc1,
0 xc8}, {
0 xc2,
0 x01},
{
0 xc4,
0 x00}, {
0 xc6,
0 x85}, {
0 xc7,
0 x81}, {
0 xc9,
0 xe0},
{
0 xca,
0 xe8}, {
0 xcc,
0 xd8}, {
0 xcd,
0 x93}, {
0 x2d,
0 x00},
{
0 x2e,
0 x00}, {
0 x01,
0 x80}, {
0 x02,
0 x80}, {
0 x12,
0 x61},
{
0 x36,
0 xfa}, {
0 x8c,
0 x8d}, {
0 xc0,
0 xaa}, {
0 x69,
0 x0a},
{
0 x03,
0 x09}, {
0 x17,
0 x16}, {
0 x18,
0 x6e}, {
0 x19,
0 x01},
{
0 x1a,
0 x3e}, {
0 x32,
0 x09}, {
0 x2a,
0 x10}, {
0 x2b,
0 x0a},
{
0 x92,
0 x00}, {
0 x93,
0 x00}, {
0 xa1,
0 x00}, {
0 x10,
0 x7c},
{
0 x04,
0 x03}, {
0 x00,
0 x13},
};
static const struct i2c_reg_u16 mt9v112_init[] = {
{
0 xf0,
0 x0000}, {
0 x0d,
0 x0021}, {
0 x0d,
0 x0020},
{
0 x34,
0 xc019}, {
0 x0a,
0 x0011}, {
0 x0b,
0 x000b},
{
0 x20,
0 x0703}, {
0 x35,
0 x2022}, {
0 xf0,
0 x0001},
{
0 x05,
0 x0000}, {
0 x06,
0 x340c}, {
0 x3b,
0 x042a},
{
0 x3c,
0 x0400}, {
0 xf0,
0 x0002}, {
0 x2e,
0 x0c58},
{
0 x5b,
0 x0001}, {
0 xc8,
0 x9f0b}, {
0 xf0,
0 x0001},
{
0 x9b,
0 x5300}, {
0 xf0,
0 x0000}, {
0 x2b,
0 x0020},
{
0 x2c,
0 x002a}, {
0 x2d,
0 x0032}, {
0 x2e,
0 x0020},
{
0 x09,
0 x01dc}, {
0 x01,
0 x000c}, {
0 x02,
0 x0020},
{
0 x03,
0 x01e0}, {
0 x04,
0 x0280}, {
0 x06,
0 x000c},
{
0 x05,
0 x0098}, {
0 x20,
0 x0703}, {
0 x09,
0 x01f2},
{
0 x2b,
0 x00a0}, {
0 x2c,
0 x00a0}, {
0 x2d,
0 x00a0},
{
0 x2e,
0 x00a0}, {
0 x01,
0 x000c}, {
0 x02,
0 x0020},
{
0 x03,
0 x01e0}, {
0 x04,
0 x0280}, {
0 x06,
0 x000c},
{
0 x05,
0 x0098}, {
0 x09,
0 x01c1}, {
0 x2b,
0 x00ae},
{
0 x2c,
0 x00ae}, {
0 x2d,
0 x00ae}, {
0 x2e,
0 x00ae},
};
static const struct i2c_reg_u16 mt9v111_init[] = {
{
0 x01,
0 x0004}, {
0 x0d,
0 x0001}, {
0 x0d,
0 x0000},
{
0 x01,
0 x0001}, {
0 x05,
0 x0004}, {
0 x2d,
0 xe0a0},
{
0 x2e,
0 x0c64}, {
0 x2f,
0 x0064}, {
0 x06,
0 x600e},
{
0 x08,
0 x0480}, {
0 x01,
0 x0004}, {
0 x02,
0 x0016},
{
0 x03,
0 x01e7}, {
0 x04,
0 x0287}, {
0 x05,
0 x0004},
{
0 x06,
0 x002d}, {
0 x07,
0 x3002}, {
0 x08,
0 x0008},
{
0 x0e,
0 x0008}, {
0 x20,
0 x0000}
};
static const struct i2c_reg_u16 mt9v011_init[] = {
{
0 x07,
0 x0002}, {
0 x0d,
0 x0001}, {
0 x0d,
0 x0000},
{
0 x01,
0 x0008}, {
0 x02,
0 x0016}, {
0 x03,
0 x01e1},
{
0 x04,
0 x0281}, {
0 x05,
0 x0083}, {
0 x06,
0 x0006},
{
0 x0d,
0 x0002}, {
0 x0a,
0 x0000}, {
0 x0b,
0 x0000},
{
0 x0c,
0 x0000}, {
0 x0d,
0 x0000}, {
0 x0e,
0 x0000},
{
0 x0f,
0 x0000}, {
0 x10,
0 x0000}, {
0 x11,
0 x0000},
{
0 x12,
0 x0000}, {
0 x13,
0 x0000}, {
0 x14,
0 x0000},
{
0 x15,
0 x0000}, {
0 x16,
0 x0000}, {
0 x17,
0 x0000},
{
0 x18,
0 x0000}, {
0 x19,
0 x0000}, {
0 x1a,
0 x0000},
{
0 x1b,
0 x0000}, {
0 x1c,
0 x0000}, {
0 x1d,
0 x0000},
{
0 x32,
0 x0000}, {
0 x20,
0 x1101}, {
0 x21,
0 x0000},
{
0 x22,
0 x0000}, {
0 x23,
0 x0000}, {
0 x24,
0 x0000},
{
0 x25,
0 x0000}, {
0 x26,
0 x0000}, {
0 x27,
0 x0024},
{
0 x2f,
0 xf7b0}, {
0 x30,
0 x0005}, {
0 x31,
0 x0000},
{
0 x32,
0 x0000}, {
0 x33,
0 x0000}, {
0 x34,
0 x0100},
{
0 x3d,
0 x068f}, {
0 x40,
0 x01e0}, {
0 x41,
0 x00d1},
{
0 x44,
0 x0082}, {
0 x5a,
0 x0000}, {
0 x5b,
0 x0000},
{
0 x5c,
0 x0000}, {
0 x5d,
0 x0000}, {
0 x5e,
0 x0000},
{
0 x5f,
0 xa31d}, {
0 x62,
0 x0611}, {
0 x0a,
0 x0000},
{
0 x06,
0 x0029}, {
0 x05,
0 x0009}, {
0 x20,
0 x1101},
{
0 x20,
0 x1101}, {
0 x09,
0 x0064}, {
0 x07,
0 x0003},
{
0 x2b,
0 x0033}, {
0 x2c,
0 x00a0}, {
0 x2d,
0 x00a0},
{
0 x2e,
0 x0033}, {
0 x07,
0 x0002}, {
0 x06,
0 x0000},
{
0 x06,
0 x0029}, {
0 x05,
0 x0009},
};
static const struct i2c_reg_u16 mt9m001_init[] = {
{
0 x0d,
0 x0001},
{
0 x0d,
0 x0000},
{
0 x04,
0 x0500},
/* hres = 1280 */
{
0 x03,
0 x0400},
/* vres = 1024 */
{
0 x20,
0 x1100},
{
0 x06,
0 x0010},
{
0 x2b,
0 x0024},
{
0 x2e,
0 x0024},
{
0 x35,
0 x0024},
{
0 x2d,
0 x0020},
{
0 x2c,
0 x0020},
{
0 x09,
0 x0ad4},
{
0 x35,
0 x0057},
};
static const struct i2c_reg_u16 mt9m111_init[] = {
{
0 xf0,
0 x0000}, {
0 x0d,
0 x0021}, {
0 x0d,
0 x0008},
{
0 xf0,
0 x0001}, {
0 x3a,
0 x4300}, {
0 x9b,
0 x4300},
{
0 x06,
0 x708e}, {
0 xf0,
0 x0002}, {
0 x2e,
0 x0a1e},
{
0 xf0,
0 x0000},
};
static const struct i2c_reg_u16 mt9m112_init[] = {
{
0 xf0,
0 x0000}, {
0 x0d,
0 x0021}, {
0 x0d,
0 x0008},
{
0 xf0,
0 x0001}, {
0 x3a,
0 x4300}, {
0 x9b,
0 x4300},
{
0 x06,
0 x708e}, {
0 xf0,
0 x0002}, {
0 x2e,
0 x0a1e},
{
0 xf0,
0 x0000},
};
static const struct i2c_reg_u8 hv7131r_init[] = {
{
0 x02,
0 x08}, {
0 x02,
0 x00}, {
0 x01,
0 x08},
{
0 x02,
0 x00}, {
0 x20,
0 x00}, {
0 x21,
0 xd0},
{
0 x22,
0 x00}, {
0 x23,
0 x09}, {
0 x01,
0 x08},
{
0 x01,
0 x08}, {
0 x01,
0 x08}, {
0 x25,
0 x07},
{
0 x26,
0 xc3}, {
0 x27,
0 x50}, {
0 x30,
0 x62},
{
0 x31,
0 x10}, {
0 x32,
0 x06}, {
0 x33,
0 x10},
{
0 x20,
0 x00}, {
0 x21,
0 xd0}, {
0 x22,
0 x00},
{
0 x23,
0 x09}, {
0 x01,
0 x08},
};
static void reg_r(
struct gspca_dev *gspca_dev, u16 reg, u16 length)
{
struct usb_device *dev = gspca_dev->dev;
int result;
if (gspca_dev->usb_err <
0 )
return ;
result = usb_control_msg(dev, usb_rcvctrlpipe(dev,
0 ),
0 x00,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
reg,
0 x00,
gspca_dev->usb_buf,
length,
500 );
if (unlikely(result <
0 || result != length)) {
pr_err(
"Read register %02x failed %d\n" , reg, result);
gspca_dev->usb_err = result;
/*
* Make sure the buffer is zeroed to avoid uninitialized
* values.
*/
memset(gspca_dev->usb_buf,
0 , USB_BUF_SZ);
}
}
static void reg_w(
struct gspca_dev *gspca_dev, u16 reg,
const u8 *buffer,
int length)
{
struct usb_device *dev = gspca_dev->dev;
int result;
if (gspca_dev->usb_err <
0 )
return ;
memcpy(gspca_dev->usb_buf, buffer, length);
result = usb_control_msg(dev, usb_sndctrlpipe(dev,
0 ),
0 x08,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
reg,
0 x00,
gspca_dev->usb_buf,
length,
500 );
if (unlikely(result <
0 || result != length)) {
pr_err(
"Write register %02x failed %d\n" , reg, result);
gspca_dev->usb_err = result;
}
}
static void reg_w1(
struct gspca_dev *gspca_dev, u16 reg,
const u8 value)
{
reg_w(gspca_dev, reg, &value,
1 );
}
static void i2c_w(
struct gspca_dev *gspca_dev,
const u8 *buffer)
{
int i;
reg_w(gspca_dev,
0 x10c0, buffer,
8 );
for (i =
0 ; i <
5 ; i++) {
reg_r(gspca_dev,
0 x10c0,
1 );
if (gspca_dev->usb_err <
0 )
return ;
if (gspca_dev->usb_buf[
0 ] &
0 x04) {
if (gspca_dev->usb_buf[
0 ] &
0 x08) {
pr_err(
"i2c_w error\n" );
gspca_dev->usb_err = -EIO;
}
return ;
}
msleep(
10 );
}
pr_err(
"i2c_w reg %02x no response\n" , buffer[
2 ]);
/* gspca_dev->usb_err = -EIO; fixme: may occur */
}
static void i2c_w1(
struct gspca_dev *gspca_dev, u8 reg, u8 val)
{
struct sd *sd = (
struct sd *) gspca_dev;
u8 row[
8 ];
/*
* from the point of view of the bridge, the length
* includes the address
*/
row[
0 ] = sd->i2c_intf | (
2 <<
4 );
row[
1 ] = sd->i2c_addr;
row[
2 ] = reg;
row[
3 ] = val;
row[
4 ] =
0 x00;
row[
5 ] =
0 x00;
row[
6 ] =
0 x00;
row[
7 ] =
0 x10;
i2c_w(gspca_dev, row);
}
static void i2c_w1_buf(
struct gspca_dev *gspca_dev,
const struct i2c_reg_u8 *buf,
int sz)
{
while (--sz >=
0 ) {
i2c_w1(gspca_dev, buf->reg, buf->val);
buf++;
}
}
static void i2c_w2(
struct gspca_dev *gspca_dev, u8 reg, u16 val)
{
struct sd *sd = (
struct sd *) gspca_dev;
u8 row[
8 ];
/*
* from the point of view of the bridge, the length
* includes the address
*/
row[
0 ] = sd->i2c_intf | (
3 <<
4 );
row[
1 ] = sd->i2c_addr;
row[
2 ] = reg;
row[
3 ] = val >>
8 ;
row[
4 ] = val;
row[
5 ] =
0 x00;
row[
6 ] =
0 x00;
row[
7 ] =
0 x10;
i2c_w(gspca_dev, row);
}
static void i2c_w2_buf(
struct gspca_dev *gspca_dev,
const struct i2c_reg_u16 *buf,
int sz)
{
while (--sz >=
0 ) {
i2c_w2(gspca_dev, buf->reg, buf->val);
buf++;
}
}
static void i2c_r1(
struct gspca_dev *gspca_dev, u8 reg, u8 *val)
{
struct sd *sd = (
struct sd *) gspca_dev;
u8 row[
8 ];
row[
0 ] = sd->i2c_intf | (
1 <<
4 );
row[
1 ] = sd->i2c_addr;
row[
2 ] = reg;
row[
3 ] =
0 ;
row[
4 ] =
0 ;
row[
5 ] =
0 ;
row[
6 ] =
0 ;
row[
7 ] =
0 x10;
i2c_w(gspca_dev, row);
row[
0 ] = sd->i2c_intf | (
1 <<
4 ) |
0 x02;
row[
2 ] =
0 ;
i2c_w(gspca_dev, row);
reg_r(gspca_dev,
0 x10c2,
5 );
*val = gspca_dev->usb_buf[
4 ];
}
static void i2c_r2(
struct gspca_dev *gspca_dev, u8 reg, u16 *val)
{
struct sd *sd = (
struct sd *) gspca_dev;
u8 row[
8 ];
row[
0 ] = sd->i2c_intf | (
1 <<
4 );
row[
1 ] = sd->i2c_addr;
row[
2 ] = reg;
row[
3 ] =
0 ;
row[
4 ] =
0 ;
row[
5 ] =
0 ;
row[
6 ] =
0 ;
row[
7 ] =
0 x10;
i2c_w(gspca_dev, row);
row[
0 ] = sd->i2c_intf | (
2 <<
4 ) |
0 x02;
row[
2 ] =
0 ;
i2c_w(gspca_dev, row);
reg_r(gspca_dev,
0 x10c2,
5 );
*val = (gspca_dev->usb_buf[
3 ] <<
8 ) | gspca_dev->usb_buf[
4 ];
}
static void ov9650_init_sensor(
struct gspca_dev *gspca_dev)
{
u16 id;
struct sd *sd = (
struct sd *) gspca_dev;
i2c_r2(gspca_dev,
0 x1c, &id);
if (gspca_dev->usb_err <
0 )
return ;
if (id !=
0 x7fa2) {
pr_err(
"sensor id for ov9650 doesn't match (0x%04x)\n" , id);
gspca_dev->usb_err = -ENODEV;
return ;
}
i2c_w1(gspca_dev,
0 x12,
0 x80);
/* sensor reset */
msleep(
200 );
i2c_w1_buf(gspca_dev, ov9650_init, ARRAY_SIZE(ov9650_init));
if (gspca_dev->usb_err <
0 )
pr_err(
"OV9650 sensor initialization failed\n" );
sd->hstart =
1 ;
sd->vstart =
7 ;
}
static void ov9655_init_sensor(
struct gspca_dev *gspca_dev)
{
struct sd *sd = (
struct sd *) gspca_dev;
i2c_w1(gspca_dev,
0 x12,
0 x80);
/* sensor reset */
msleep(
200 );
i2c_w1_buf(gspca_dev, ov9655_init, ARRAY_SIZE(ov9655_init));
if (gspca_dev->usb_err <
0 )
pr_err(
"OV9655 sensor initialization failed\n" );
sd->hstart =
1 ;
sd->vstart =
2 ;
}
static void soi968_init_sensor(
struct gspca_dev *gspca_dev)
{
struct sd *sd = (
struct sd *) gspca_dev;
i2c_w1(gspca_dev,
0 x12,
0 x80);
/* sensor reset */
msleep(
200 );
i2c_w1_buf(gspca_dev, soi968_init, ARRAY_SIZE(soi968_init));
if (gspca_dev->usb_err <
0 )
pr_err(
"SOI968 sensor initialization failed\n" );
sd->hstart =
60 ;
sd->vstart =
11 ;
}
static void ov7660_init_sensor(
struct gspca_dev *gspca_dev)
{
struct sd *sd = (
struct sd *) gspca_dev;
i2c_w1(gspca_dev,
0 x12,
0 x80);
/* sensor reset */
msleep(
200 );
i2c_w1_buf(gspca_dev, ov7660_init, ARRAY_SIZE(ov7660_init));
if (gspca_dev->usb_err <
0 )
pr_err(
"OV7660 sensor initialization failed\n" );
sd->hstart =
3 ;
sd->vstart =
3 ;
}
static void ov7670_init_sensor(
struct gspca_dev *gspca_dev)
{
struct sd *sd = (
struct sd *) gspca_dev;
i2c_w1(gspca_dev,
0 x12,
0 x80);
/* sensor reset */
msleep(
200 );
i2c_w1_buf(gspca_dev, ov7670_init, ARRAY_SIZE(ov7670_init));
if (gspca_dev->usb_err <
0 )
pr_err(
"OV7670 sensor initialization failed\n" );
sd->hstart =
0 ;
sd->vstart =
1 ;
}
static void mt9v_init_sensor(
struct gspca_dev *gspca_dev)
{
struct sd *sd = (
struct sd *) gspca_dev;
u16 value;
sd->i2c_addr =
0 x5d;
i2c_r2(gspca_dev,
0 xff, &value);
if (gspca_dev->usb_err >=
0
&& value ==
0 x8243) {
i2c_w2_buf(gspca_dev, mt9v011_init, ARRAY_SIZE(mt9v011_init));
if (gspca_dev->usb_err <
0 ) {
pr_err(
"MT9V011 sensor initialization failed\n" );
return ;
}
sd->hstart =
2 ;
sd->vstart =
2 ;
sd->sensor = SENSOR_MT9V011;
pr_info(
"MT9V011 sensor detected\n" );
return ;
}
gspca_dev->usb_err =
0 ;
sd->i2c_addr =
0 x5c;
i2c_w2(gspca_dev,
0 x01,
0 x0004);
i2c_r2(gspca_dev,
0 xff, &value);
if (gspca_dev->usb_err >=
0
&& value ==
0 x823a) {
i2c_w2_buf(gspca_dev, mt9v111_init, ARRAY_SIZE(mt9v111_init));
if (gspca_dev->usb_err <
0 ) {
pr_err(
"MT9V111 sensor initialization failed\n" );
return ;
}
sd->hstart =
2 ;
sd->vstart =
2 ;
sd->sensor = SENSOR_MT9V111;
pr_info(
"MT9V111 sensor detected\n" );
return ;
}
gspca_dev->usb_err =
0 ;
sd->i2c_addr =
0 x5d;
i2c_w2(gspca_dev,
0 xf0,
0 x0000);
if (gspca_dev->usb_err <
0 ) {
gspca_dev->usb_err =
0 ;
sd->i2c_addr =
0 x48;
i2c_w2(gspca_dev,
0 xf0,
0 x0000);
}
i2c_r2(gspca_dev,
0 x00, &value);
if (gspca_dev->usb_err >=
0
&& value ==
0 x1229) {
i2c_w2_buf(gspca_dev, mt9v112_init, ARRAY_SIZE(mt9v112_init));
if (gspca_dev->usb_err <
0 ) {
pr_err(
"MT9V112 sensor initialization failed\n" );
return ;
}
sd->hstart =
6 ;
sd->vstart =
2 ;
sd->sensor = SENSOR_MT9V112;
pr_info(
"MT9V112 sensor detected\n" );
return ;
}
gspca_dev->usb_err = -ENODEV;
}
static void mt9m112_init_sensor(
struct gspca_dev *gspca_dev)
{
struct sd *sd = (
struct sd *) gspca_dev;
i2c_w2_buf(gspca_dev, mt9m112_init, ARRAY_SIZE(mt9m112_init));
if (gspca_dev->usb_err <
0 )
pr_err(
"MT9M112 sensor initialization failed\n" );
sd->hstart =
0 ;
sd->vstart =
2 ;
}
static void mt9m111_init_sensor(
struct gspca_dev *gspca_dev)
{
struct sd *sd = (
struct sd *) gspca_dev;
i2c_w2_buf(gspca_dev, mt9m111_init, ARRAY_SIZE(mt9m111_init));
if (gspca_dev->usb_err <
0 )
pr_err(
"MT9M111 sensor initialization failed\n" );
sd->hstart =
0 ;
sd->vstart =
2 ;
}
static void mt9m001_init_sensor(
struct gspca_dev *gspca_dev)
{
struct sd *sd = (
struct sd *) gspca_dev;
u16 id;
i2c_r2(gspca_dev,
0 x00, &id);
if (gspca_dev->usb_err <
0 )
return ;
/* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
switch (id) {
case 0 x8411:
case 0 x8421:
pr_info(
"MT9M001 color sensor detected\n" );
break ;
case 0 x8431:
pr_info(
"MT9M001 mono sensor detected\n" );
break ;
default :
pr_err(
"No MT9M001 chip detected, ID = %x\n\n" , id);
gspca_dev->usb_err = -ENODEV;
return ;
}
i2c_w2_buf(gspca_dev, mt9m001_init, ARRAY_SIZE(mt9m001_init));
if (gspca_dev->usb_err <
0 )
pr_err(
"MT9M001 sensor initialization failed\n" );
sd->hstart =
1 ;
sd->vstart =
1 ;
}
static void hv7131r_init_sensor(
struct gspca_dev *gspca_dev)
{
struct sd *sd = (
struct sd *) gspca_dev;
i2c_w1_buf(gspca_dev, hv7131r_init, ARRAY_SIZE(hv7131r_init));
if (gspca_dev->usb_err <
0 )
pr_err(
"HV7131R Sensor initialization failed\n" );
sd->hstart =
0 ;
sd->vstart =
1 ;
}
static void set_cmatrix(
struct gspca_dev *gspca_dev,
s32 brightness, s32 contrast, s32 satur, s32 hue)
{
s32 hue_coord, hue_index =
180 + hue;
u8 cmatrix[
21 ];
memset(cmatrix,
0 ,
sizeof (cmatrix));
cmatrix[
2 ] = (contrast *
0 x25 /
0 x100) +
0 x26;
cmatrix[
0 ] =
0 x13 + (cmatrix[
2 ] -
0 x26) *
0 x13 /
0 x25;
cmatrix[
4 ] =
0 x07 + (cmatrix[
2 ] -
0 x26) *
0 x07 /
0 x25;
cmatrix[
18 ] = brightness -
0 x80;
hue_coord = (hsv_red_x[hue_index] * satur) >>
8 ;
cmatrix[
6 ] = hue_coord;
cmatrix[
7 ] = (hue_coord >>
8 ) &
0 x0f;
hue_coord = (hsv_red_y[hue_index] * satur) >>
8 ;
cmatrix[
8 ] = hue_coord;
cmatrix[
9 ] = (hue_coord >>
8 ) &
0 x0f;
hue_coord = (hsv_green_x[hue_index] * satur) >>
8 ;
cmatrix[
10 ] = hue_coord;
cmatrix[
11 ] = (hue_coord >>
8 ) &
0 x0f;
hue_coord = (hsv_green_y[hue_index] * satur) >>
8 ;
cmatrix[
12 ] = hue_coord;
cmatrix[
13 ] = (hue_coord >>
8 ) &
0 x0f;
hue_coord = (hsv_blue_x[hue_index] * satur) >>
8 ;
cmatrix[
14 ] = hue_coord;
cmatrix[
15 ] = (hue_coord >>
8 ) &
0 x0f;
hue_coord = (hsv_blue_y[hue_index] * satur) >>
8 ;
cmatrix[
16 ] = hue_coord;
cmatrix[
17 ] = (hue_coord >>
8 ) &
0 x0f;
reg_w(gspca_dev,
0 x10e1, cmatrix,
21 );
}
static void set_gamma(
struct gspca_dev *gspca_dev, s32 val)
{
u8 gamma[
17 ];
u8 gval = val *
0 xb8 /
0 x100;
gamma[
0 ] =
0 x0a;
gamma[
1 ] =
0 x13 + (gval * (
0 xcb -
0 x13) /
0 xb8);
gamma[
2 ] =
0 x25 + (gval * (
0 xee -
0 x25) /
0 xb8);
gamma[
3 ] =
0 x37 + (gval * (
0 xfa -
0 x37) /
0 xb8);
gamma[
4 ] =
0 x45 + (gval * (
0 xfc -
0 x45) /
0 xb8);
gamma[
5 ] =
0 x55 + (gval * (
0 xfb -
0 x55) /
0 xb8);
gamma[
6 ] =
0 x65 + (gval * (
0 xfc -
0 x65) /
0 xb8);
gamma[
7 ] =
0 x74 + (gval * (
0 xfd -
0 x74) /
0 xb8);
gamma[
8 ] =
0 x83 + (gval * (
0 xfe -
0 x83) /
0 xb8);
gamma[
9 ] =
0 x92 + (gval * (
0 xfc -
0 x92) /
0 xb8);
gamma[
10 ] =
0 xa1 + (gval * (
0 xfc -
0 xa1) /
0 xb8);
gamma[
11 ] =
0 xb0 + (gval * (
0 xfc -
0 xb0) /
0 xb8);
gamma[
12 ] =
0 xbf + (gval * (
0 xfb -
0 xbf) /
0 xb8);
gamma[
13 ] =
0 xce + (gval * (
0 xfb -
0 xce) /
0 xb8);
gamma[
14 ] =
0 xdf + (gval * (
0 xfd -
0 xdf) /
0 xb8);
gamma[
15 ] =
0 xea + (gval * (
0 xf9 -
0 xea) /
0 xb8);
gamma[
16 ] =
0 xf5;
reg_w(gspca_dev,
0 x1190, gamma,
17 );
}
static void set_redblue(
struct gspca_dev *gspca_dev, s32 blue, s32 red)
{
reg_w1(gspca_dev,
0 x118c, red);
reg_w1(gspca_dev,
0 x118f, blue);
}
static void set_hvflip(
struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
{
u8 value, tslb;
u16 value2;
struct sd *sd = (
struct sd *) gspca_dev;
if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) {
hflip = !hflip;
vflip = !vflip;
}
switch (sd->sensor) {
case SENSOR_OV7660:
value =
0 x01;
if (hflip)
value |=
0 x20;
if (vflip) {
value |=
0 x10;
sd->vstart =
2 ;
}
else {
sd->vstart =
3 ;
}
reg_w1(gspca_dev,
0 x1182, sd->vstart);
i2c_w1(gspca_dev,
0 x1e, value);
break ;
case SENSOR_OV9650:
i2c_r1(gspca_dev,
0 x1e, &value);
value &= ~
0 x30;
tslb =
0 x01;
if (hflip)
value |=
0 x20;
if (vflip) {
value |=
0 x10;
tslb =
0 x49;
}
i2c_w1(gspca_dev,
0 x1e, value);
i2c_w1(gspca_dev,
0 x3a, tslb);
break ;
case SENSOR_MT9V111:
case SENSOR_MT9V011:
i2c_r2(gspca_dev,
0 x20, &value2);
value2 &= ~
0 xc0a0;
if (hflip)
value2 |=
0 x8080;
if (vflip)
value2 |=
0 x4020;
i2c_w2(gspca_dev,
0 x20, value2);
break ;
case SENSOR_MT9M112:
case SENSOR_MT9M111:
case SENSOR_MT9V112:
i2c_r2(gspca_dev,
0 x20, &value2);
value2 &= ~
0 x0003;
if (hflip)
value2 |=
0 x0002;
if (vflip)
value2 |=
0 x0001;
i2c_w2(gspca_dev,
0 x20, value2);
break ;
case SENSOR_HV7131R:
i2c_r1(gspca_dev,
0 x01, &value);
value &= ~
0 x03;
if (vflip)
value |=
0 x01;
if (hflip)
value |=
0 x02;
i2c_w1(gspca_dev,
0 x01, value);
break ;
}
}
static void set_exposure(
struct gspca_dev *gspca_dev, s32 expo)
{
struct sd *sd = (
struct sd *) gspca_dev;
u8 exp[
8 ] = {sd->i2c_intf, sd->i2c_addr,
0 x00,
0 x00,
0 x00,
0 x00,
0 x00,
0 x10};
int expo2;
if (gspca_dev->streaming)
exp[
7 ] =
0 x1e;
switch (sd->sensor) {
case SENSOR_OV7660:
case SENSOR_OV7670:
case SENSOR_OV9655:
case SENSOR_OV9650:
if (expo >
547 )
expo2 =
547 ;
else
expo2 = expo;
exp[
0 ] |= (
2 <<
4 );
exp[
2 ] =
0 x10;
/* AECH */
exp[
3 ] = expo2 >>
2 ;
exp[
7 ] =
0 x10;
i2c_w(gspca_dev, exp);
exp[
2 ] =
0 x04;
/* COM1 */
exp[
3 ] = expo2 &
0 x0003;
exp[
7 ] =
0 x10;
i2c_w(gspca_dev, exp);
expo -= expo2;
exp[
7 ] =
0 x1e;
exp[
0 ] |= (
3 <<
4 );
exp[
2 ] =
0 x2d;
/* ADVFL & ADVFH */
exp[
3 ] = expo;
exp[
4 ] = expo >>
8 ;
break ;
case SENSOR_MT9M001:
case SENSOR_MT9V112:
case SENSOR_MT9V011:
exp[
0 ] |= (
3 <<
4 );
exp[
2 ] =
0 x09;
exp[
3 ] = expo >>
8 ;
exp[
4 ] = expo;
break ;
case SENSOR_HV7131R:
exp[
0 ] |= (
4 <<
4 );
exp[
2 ] =
0 x25;
exp[
3 ] = expo >>
5 ;
exp[
4 ] = expo <<
3 ;
exp[
5 ] =
0 ;
break ;
default :
return ;
}
i2c_w(gspca_dev, exp);
}
static void set_gain(
struct gspca_dev *gspca_dev, s32 g)
{
struct sd *sd = (
struct sd *) gspca_dev;
u8 gain[
8 ] = {sd->i2c_intf, sd->i2c_addr,
0 x00,
0 x00,
0 x00,
0 x00,
0 x00,
0 x10};
if (gspca_dev->streaming)
gain[
7 ] =
0 x15;
/* or 1d ? */
switch (sd->sensor) {
case SENSOR_OV7660:
case SENSOR_OV7670:
case SENSOR_SOI968:
case SENSOR_OV9655:
case SENSOR_OV9650:
gain[
0 ] |= (
2 <<
4 );
gain[
3 ] = ov_gain[g];
break ;
case SENSOR_MT9V011:
gain[
0 ] |= (
3 <<
4 );
gain[
2 ] =
0 x35;
gain[
3 ] = micron1_gain[g] >>
8 ;
gain[
4 ] = micron1_gain[g];
break ;
case SENSOR_MT9V112:
gain[
0 ] |= (
3 <<
4 );
gain[
2 ] =
0 x2f;
gain[
3 ] = micron1_gain[g] >>
8 ;
gain[
4 ] = micron1_gain[g];
break ;
case SENSOR_MT9M001:
gain[
0 ] |= (
3 <<
4 );
gain[
2 ] =
0 x2f;
gain[
3 ] = micron2_gain[g] >>
8 ;
gain[
4 ] = micron2_gain[g];
break ;
case SENSOR_HV7131R:
gain[
0 ] |= (
2 <<
4 );
gain[
2 ] =
0 x30;
gain[
3 ] = hv7131r_gain[g];
break ;
default :
return ;
}
i2c_w(gspca_dev, gain);
}
static void set_led_mode(
struct gspca_dev *gspca_dev, s32 val)
{
reg_w1(gspca_dev,
0 x1007,
0 x60);
reg_w1(gspca_dev,
0 x1006, val ?
0 x40 :
0 x00);
}
static void set_quality(
struct gspca_dev *gspca_dev, s32 val)
{
struct sd *sd = (
struct sd *) gspca_dev;
jpeg_set_qual(sd->jpeg_hdr, val);
reg_w1(gspca_dev,
0 x1061,
0 x01);
/* stop transfer */
reg_w1(gspca_dev,
0 x10e0, sd->fmt |
0 x20);
/* write QTAB */
reg_w(gspca_dev,
0 x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET],
64 );
reg_w(gspca_dev,
0 x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET],
64 );
reg_w1(gspca_dev,
0 x1061,
0 x03);
/* restart transfer */
reg_w1(gspca_dev,
0 x10e0, sd->fmt);
sd->fmt ^=
0 x0c;
/* invert QTAB use + write */
reg_w1(gspca_dev,
0 x10e0, sd->fmt);
}
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int sd_dbg_g_register(
struct gspca_dev *gspca_dev,
struct v4l2_dbg_register *reg)
{
struct sd *sd = (
struct sd *) gspca_dev;
reg->size =
1 ;
switch (reg->match.addr) {
case 0 :
if (reg->reg <
0 x1000 || reg->reg >
0 x11ff)
return -EINVAL;
reg_r(gspca_dev, reg->reg,
1 );
reg->val = gspca_dev->usb_buf[
0 ];
return gspca_dev->usb_err;
case 1 :
if (sd->sensor >= SENSOR_MT9V011 &&
sd->sensor <= SENSOR_MT9M112) {
i2c_r2(gspca_dev, reg->reg, (u16 *) ®->val);
reg->size =
2 ;
}
else {
i2c_r1(gspca_dev, reg->reg, (u8 *) ®->val);
}
return gspca_dev->usb_err;
}
return -EINVAL;
}
static int sd_dbg_s_register(
struct gspca_dev *gspca_dev,
const struct v4l2_dbg_register *reg)
{
struct sd *sd = (
struct sd *) gspca_dev;
switch (reg->match.addr) {
case 0 :
if (reg->reg <
0 x1000 || reg->reg >
0 x11ff)
return -EINVAL;
reg_w1(gspca_dev, reg->reg, reg->val);
return gspca_dev->usb_err;
case 1 :
if (sd->sensor >= SENSOR_MT9V011 &&
sd->sensor <= SENSOR_MT9M112) {
i2c_w2(gspca_dev, reg->reg, reg->val);
}
else {
i2c_w1(gspca_dev, reg->reg, reg->val);
}
return gspca_dev->usb_err;
}
return -EINVAL;
}
static int sd_chip_info(
struct gspca_dev *gspca_dev,
struct v4l2_dbg_chip_info *chip)
{
if (chip->match.addr >
1 )
return -EINVAL;
if (chip->match.addr ==
1 )
strscpy(chip->name,
"sensor" ,
sizeof (chip->name));
return 0 ;
}
#endif
static int sd_config(
struct gspca_dev *gspca_dev,
const struct usb_device_id *id)
{
struct sd *sd = (
struct sd *) gspca_dev;
struct cam *cam;
cam = &gspca_dev->cam;
cam->needs_full_bandwidth =
1 ;
sd->sensor = id->driver_info >>
8 ;
sd->i2c_addr = id->driver_info;
sd->flags = id->driver_info >>
16 ;
sd->i2c_intf =
0 x80;
/* i2c 100 Kb/s */
switch (sd->sensor) {
case SENSOR_MT9M112:
case SENSOR_MT9M111:
case SENSOR_OV9650:
case SENSOR_SOI968:
cam->cam_mode = sxga_mode;
cam->nmodes = ARRAY_SIZE(sxga_mode);
break ;
case SENSOR_MT9M001:
cam->cam_mode = mono_mode;
cam->nmodes = ARRAY_SIZE(mono_mode);
break ;
case SENSOR_HV7131R:
sd->i2c_intf =
0 x81;
/* i2c 400 Kb/s */
fallthrough;
default :
cam->cam_mode = vga_mode;
cam->nmodes = ARRAY_SIZE(vga_mode);
break ;
}
sd->old_step =
0 ;
sd->older_step =
0 ;
sd->exposure_step =
16 ;
INIT_WORK(&sd->work, qual_upd);
return 0 ;
}
static int sd_s_ctrl(
struct v4l2_ctrl *ctrl)
{
struct gspca_dev *gspca_dev =
container_of(ctrl->handler,
struct gspca_dev, ctrl_handler);
struct sd *sd = (
struct sd *)gspca_dev;
gspca_dev->usb_err =
0 ;
if (!gspca_dev->streaming)
return 0 ;
switch (ctrl->id) {
/* color control cluster */
case V4L2_CID_BRIGHTNESS:
set_cmatrix(gspca_dev, sd->brightness->val,
sd->contrast->val, sd->saturation->val, sd->hue->val);
break ;
case V4L2_CID_GAMMA:
set_gamma(gspca_dev, ctrl->val);
break ;
/* blue/red balance cluster */
case V4L2_CID_BLUE_BALANCE:
set_redblue(gspca_dev, sd->blue->val, sd->red->val);
break ;
/* h/vflip cluster */
case V4L2_CID_HFLIP:
set_hvflip(gspca_dev, sd->hflip->val, sd->vflip->val);
break ;
/* standalone exposure control */
case V4L2_CID_EXPOSURE:
set_exposure(gspca_dev, ctrl->val);
break ;
/* standalone gain control */
case V4L2_CID_GAIN:
set_gain(gspca_dev, ctrl->val);
break ;
/* autogain + exposure or gain control cluster */
case V4L2_CID_AUTOGAIN:
if (sd->sensor == SENSOR_SOI968)
set_gain(gspca_dev, sd->gain->val);
else
set_exposure(gspca_dev, sd->exposure->val);
break ;
case V4L2_CID_JPEG_COMPRESSION_QUALITY:
set_quality(gspca_dev, ctrl->val);
break ;
case V4L2_CID_FLASH_LED_MODE:
set_led_mode(gspca_dev, ctrl->val);
break ;
}
return gspca_dev->usb_err;
}
static const struct v4l2_ctrl_ops sd_ctrl_ops = {
.s_ctrl = sd_s_ctrl,
};
static int sd_init_controls(
struct gspca_dev *gspca_dev)
{
struct sd *sd = (
struct sd *) gspca_dev;
struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
gspca_dev->vdev.ctrl_handler = hdl;
v4l2_ctrl_handler_init(hdl,
13 );
sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_BRIGHTNESS,
0 ,
255 ,
1 ,
127 );
sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_CONTRAST,
0 ,
255 ,
1 ,
127 );
sd->saturation = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_SATURATION,
0 ,
255 ,
1 ,
127 );
sd->hue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_HUE, -
180 ,
180 ,
1 ,
0 );
sd->gamma = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_GAMMA,
0 ,
255 ,
1 ,
0 x10);
sd->blue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_BLUE_BALANCE,
0 ,
127 ,
1 ,
0 x28);
sd->red = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_RED_BALANCE,
0 ,
127 ,
1 ,
0 x28);
if (sd->sensor != SENSOR_OV9655 && sd->sensor != SENSOR_SOI968 &&
sd->sensor != SENSOR_OV7670 && sd->sensor != SENSOR_MT9M001 &&
sd->sensor != SENSOR_MT9VPRB) {
sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_HFLIP,
0 ,
1 ,
1 ,
0 );
sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_VFLIP,
0 ,
1 ,
1 ,
0 );
}
if (sd->sensor != SENSOR_SOI968 && sd->sensor != SENSOR_MT9VPRB &&
sd->sensor != SENSOR_MT9M112 && sd->sensor != SENSOR_MT9M111 &&
sd->sensor != SENSOR_MT9V111)
sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_EXPOSURE,
0 ,
0 x1780,
1 ,
0 x33);
if (sd->sensor != SENSOR_MT9VPRB && sd->sensor != SENSOR_MT9M112 &&
sd->sensor != SENSOR_MT9M111 && sd->sensor != SENSOR_MT9V111) {
sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_GAIN,
0 ,
28 ,
1 ,
0 );
sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_AUTOGAIN,
0 ,
1 ,
1 ,
1 );
}
sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_JPEG_COMPRESSION_QUALITY,
50 ,
90 ,
1 ,
80 );
if (sd->flags & HAS_LED_TORCH)
sd->led_mode = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
V4L2_CID_FLASH_LED_MODE, V4L2_FLASH_LED_MODE_TORCH,
~
0 x5, V4L2_FLASH_LED_MODE_NONE);
if (hdl->error) {
pr_err(
"Could not initialize controls\n" );
return hdl->error;
}
v4l2_ctrl_cluster(
4 , &sd->brightness);
v4l2_ctrl_cluster(
2 , &sd->blue);
if (sd->hflip)
v4l2_ctrl_cluster(
2 , &sd->hflip);
if (sd->autogain) {
if (sd->sensor == SENSOR_SOI968)
/* this sensor doesn't have the exposure control and
autogain is clustered with gain instead. This works
because sd->exposure == NULL. */
v4l2_ctrl_auto_cluster(
3 , &sd->autogain,
0 ,
false );
else
/* Otherwise autogain is clustered with exposure. */
v4l2_ctrl_auto_cluster(
2 , &sd->autogain,
0 ,
false );
}
return 0 ;
}
static int sd_init(
struct gspca_dev *gspca_dev)
{
struct sd *sd = (
struct sd *) gspca_dev;
int i;
u8 value;
u8 i2c_init[
9 ] = {
0 x80, sd->i2c_addr,
0 x00,
0 x00,
0 x00,
0 x00,
0 x00,
0 x00,
0 x03
};
for (i =
0 ; i < ARRAY_SIZE(bridge_init); i++) {
value = bridge_init[i][
1 ];
reg_w(gspca_dev, bridge_init[i][
0 ], &value,
1 );
if (gspca_dev->usb_err <
0 ) {
pr_err(
"Device initialization failed\n" );
return gspca_dev->usb_err;
}
}
if (sd->flags & LED_REVERSE)
reg_w1(gspca_dev,
0 x1006,
0 x00);
else
reg_w1(gspca_dev,
0 x1006,
0 x20);
reg_w(gspca_dev,
0 x10c0, i2c_init,
9 );
if (gspca_dev->usb_err <
0 ) {
pr_err(
"Device initialization failed\n" );
return gspca_dev->usb_err;
}
switch (sd->sensor) {
case SENSOR_OV9650:
ov9650_init_sensor(gspca_dev);
if (gspca_dev->usb_err <
0 )
break ;
pr_info(
"OV9650 sensor detected\n" );
break ;
case SENSOR_OV9655:
ov9655_init_sensor(gspca_dev);
if (gspca_dev->usb_err <
0 )
break ;
pr_info(
"OV9655 sensor detected\n" );
break ;
case SENSOR_SOI968:
soi968_init_sensor(gspca_dev);
if (gspca_dev->usb_err <
0 )
break ;
pr_info(
"SOI968 sensor detected\n" );
break ;
case SENSOR_OV7660:
ov7660_init_sensor(gspca_dev);
if (gspca_dev->usb_err <
0 )
break ;
pr_info(
"OV7660 sensor detected\n" );
break ;
case SENSOR_OV7670:
ov7670_init_sensor(gspca_dev);
if (gspca_dev->usb_err <
0 )
break ;
pr_info(
"OV7670 sensor detected\n" );
break ;
case SENSOR_MT9VPRB:
mt9v_init_sensor(gspca_dev);
if (gspca_dev->usb_err <
0 )
break ;
pr_info(
"MT9VPRB sensor detected\n" );
break ;
case SENSOR_MT9M111:
mt9m111_init_sensor(gspca_dev);
if (gspca_dev->usb_err <
0 )
break ;
pr_info(
"MT9M111 sensor detected\n" );
break ;
case SENSOR_MT9M112:
mt9m112_init_sensor(gspca_dev);
if (gspca_dev->usb_err <
0 )
break ;
pr_info(
"MT9M112 sensor detected\n" );
break ;
case SENSOR_MT9M001:
mt9m001_init_sensor(gspca_dev);
if (gspca_dev->usb_err <
0 )
break ;
break ;
case SENSOR_HV7131R:
hv7131r_init_sensor(gspca_dev);
if (gspca_dev->usb_err <
0 )
break ;
pr_info(
"HV7131R sensor detected\n" );
break ;
default :
pr_err(
"Unsupported sensor\n" );
gspca_dev->usb_err = -ENODEV;
}
return gspca_dev->usb_err;
}
static void configure_sensor_output(
struct gspca_dev *gspca_dev,
int mode)
{
struct sd *sd = (
struct sd *) gspca_dev;
u8 value;
switch (sd->sensor) {
case SENSOR_SOI968:
if (mode & MODE_SXGA) {
i2c_w1(gspca_dev,
0 x17,
0 x1d);
i2c_w1(gspca_dev,
0 x18,
0 xbd);
i2c_w1(gspca_dev,
0 x19,
0 x01);
i2c_w1(gspca_dev,
0 x1a,
0 x81);
i2c_w1(gspca_dev,
0 x12,
0 x00);
sd->hstart =
140 ;
sd->vstart =
19 ;
}
else {
i2c_w1(gspca_dev,
0 x17,
0 x13);
i2c_w1(gspca_dev,
0 x18,
0 x63);
i2c_w1(gspca_dev,
0 x19,
0 x01);
i2c_w1(gspca_dev,
0 x1a,
0 x79);
i2c_w1(gspca_dev,
0 x12,
0 x40);
sd->hstart =
60 ;
sd->vstart =
11 ;
}
break ;
case SENSOR_OV9650:
if (mode & MODE_SXGA) {
i2c_w1(gspca_dev,
0 x17,
0 x1b);
i2c_w1(gspca_dev,
0 x18,
0 xbc);
i2c_w1(gspca_dev,
0 x19,
0 x01);
i2c_w1(gspca_dev,
0 x1a,
0 x82);
i2c_r1(gspca_dev,
0 x12, &value);
i2c_w1(gspca_dev,
0 x12, value &
0 x07);
}
else {
i2c_w1(gspca_dev,
0 x17,
0 x24);
i2c_w1(gspca_dev,
0 x18,
0 xc5);
i2c_w1(gspca_dev,
0 x19,
0 x00);
i2c_w1(gspca_dev,
0 x1a,
0 x3c);
i2c_r1(gspca_dev,
0 x12, &value);
i2c_w1(gspca_dev,
0 x12, (value &
0 x7) |
0 x40);
}
break ;
case SENSOR_MT9M112:
case SENSOR_MT9M111:
if (mode & MODE_SXGA) {
i2c_w2(gspca_dev,
0 xf0,
0 x0002);
i2c_w2(gspca_dev,
0 xc8,
0 x970b);
i2c_w2(gspca_dev,
0 xf0,
0 x0000);
}
else {
i2c_w2(gspca_dev,
0 xf0,
0 x0002);
i2c_w2(gspca_dev,
0 xc8,
0 x8000);
i2c_w2(gspca_dev,
0 xf0,
0 x0000);
}
break ;
}
}
static int sd_isoc_init(
struct gspca_dev *gspca_dev)
{
struct usb_interface *intf;
u32 flags = gspca_dev->cam.cam_mode[(
int )gspca_dev->curr_mode].priv;
/*
* When using the SN9C20X_I420 fmt the sn9c20x needs more bandwidth
* than our regular bandwidth calculations reserve, so we force the
* use of a specific altsetting when using the SN9C20X_I420 fmt.
*/
if (!(flags & (MODE_RAW | MODE_JPEG))) {
intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
if (intf->num_altsetting !=
9 ) {
pr_warn(
"sn9c20x camera with unknown number of alt settings (%d), please report!\n" ,
intf->num_altsetting);
gspca_dev->alt = intf->num_altsetting;
return 0 ;
}
switch (gspca_dev->pixfmt.width) {
case 160 :
/* 160x120 */
gspca_dev->alt =
2 ;
break ;
case 320 :
/* 320x240 */
gspca_dev->alt =
6 ;
break ;
default :
/* >= 640x480 */
gspca_dev->alt =
9 ;
break ;
}
}
return 0 ;
}
#define HW_WIN(mode, hstart, vstart) \
((
const u8 []){hstart,
0 , vstart,
0 , \
(mode & MODE_SXGA ?
1280 >>
4 :
640 >>
4 ), \
(mode & MODE_SXGA ?
1024 >>
3 :
480 >>
3 )})
#define CLR_WIN(width, height) \
((
const u8 [])\
{
0 , width >>
2 ,
0 , height >>
1 ,\
((width >>
10 ) &
0 x01) | ((height >>
8 ) &
0 x6)})
static int sd_start(
struct gspca_dev *gspca_dev)
{
struct sd *sd = (
struct sd *) gspca_dev;
int mode = gspca_dev->cam.cam_mode[(
int ) gspca_dev->curr_mode].priv;
int width = gspca_dev->pixfmt.width;
int height = gspca_dev->pixfmt.height;
u8 fmt, scale =
0 ;
jpeg_define(sd->jpeg_hdr, height, width,
0 x21);
jpeg_set_qual(sd->jpeg_hdr, v4l2_ctrl_g_ctrl(sd->jpegqual));
if (mode & MODE_RAW)
fmt =
0 x2d;
else if (mode & MODE_JPEG)
fmt =
0 x24;
else
fmt =
0 x2f;
/* YUV 420 */
sd->fmt = fmt;
switch (mode & SCALE_MASK) {
case SCALE_1280x1024:
scale =
0 xc0;
pr_info(
"Set 1280x1024\n" );
break ;
case SCALE_640x480:
scale =
0 x80;
pr_info(
"Set 640x480\n" );
break ;
case SCALE_320x240:
scale =
0 x90;
pr_info(
"Set 320x240\n" );
break ;
case SCALE_160x120:
scale =
0 xa0;
pr_info(
"Set 160x120\n" );
break ;
}
configure_sensor_output(gspca_dev, mode);
reg_w(gspca_dev,
0 x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET],
64 );
reg_w(gspca_dev,
0 x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET],
64 );
reg_w(gspca_dev,
0 x10fb, CLR_WIN(width, height),
5 );
reg_w(gspca_dev,
0 x1180, HW_WIN(mode, sd->hstart, sd->vstart),
6 );
reg_w1(gspca_dev,
0 x1189, scale);
reg_w1(gspca_dev,
0 x10e0, fmt);
set_cmatrix(gspca_dev, v4l2_ctrl_g_ctrl(sd->brightness),
v4l2_ctrl_g_ctrl(sd->contrast),
v4l2_ctrl_g_ctrl(sd->saturation),
v4l2_ctrl_g_ctrl(sd->hue));
set_gamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
set_redblue(gspca_dev, v4l2_ctrl_g_ctrl(sd->blue),
v4l2_ctrl_g_ctrl(sd->red));
if (sd->gain)
set_gain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain));
if (sd->exposure)
set_exposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure));
if (sd->hflip)
set_hvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip),
v4l2_ctrl_g_ctrl(sd->vflip));
reg_w1(gspca_dev,
0 x1007,
0 x20);
reg_w1(gspca_dev,
0 x1061,
0 x03);
/* if JPEG, prepare the compression quality update */
if (mode & MODE_JPEG) {
sd->pktsz = sd->npkt =
0 ;
sd->nchg =
0 ;
}
if (sd->led_mode)
v4l2_ctrl_s_ctrl(sd->led_mode,
0 );
return gspca_dev->usb_err;
}
static void sd_stopN(
struct gspca_dev *gspca_dev)
{
reg_w1(gspca_dev,
0 x1007,
0 x00);
reg_w1(gspca_dev,
0 x1061,
0 x01);
}
/* called on streamoff with alt==0 and on disconnect */
/* the usb_lock is held at entry - restore on exit */
static void sd_stop0(
struct gspca_dev *gspca_dev)
{
struct sd *sd = (
struct sd *) gspca_dev;
mutex_unlock(&gspca_dev->usb_lock);
flush_work(&sd->work);
mutex_lock(&gspca_dev->usb_lock);
}
static void do_autoexposure(
struct gspca_dev *gspca_dev, u16 avg_lum)
{
struct sd *sd = (
struct sd *) gspca_dev;
s32 cur_exp = v4l2_ctrl_g_ctrl(sd->exposure);
s32 max = sd->exposure->maximum - sd->exposure_step;
s32 min = sd->exposure->minimum + sd->exposure_step;
s16 new_exp;
/*
* some hardcoded values are present
* like those for maximal/minimal exposure
* and exposure steps
*/
if (avg_lum < MIN_AVG_LUM) {
if (cur_exp > max)
return ;
new_exp = cur_exp + sd->exposure_step;
if (new_exp > max)
new_exp = max;
if (new_exp < min)
new_exp = min;
v4l2_ctrl_s_ctrl(sd->exposure, new_exp);
sd->older_step = sd->old_step;
sd->old_step =
1 ;
if (sd->old_step ^ sd->older_step)
sd->exposure_step /=
2 ;
else
sd->exposure_step +=
2 ;
}
if (avg_lum > MAX_AVG_LUM) {
if (cur_exp < min)
return ;
new_exp = cur_exp - sd->exposure_step;
if (new_exp > max)
new_exp = max;
if (new_exp < min)
new_exp = min;
v4l2_ctrl_s_ctrl(sd->exposure, new_exp);
sd->older_step = sd->old_step;
sd->old_step =
0 ;
if (sd->old_step ^ sd->older_step)
sd->exposure_step /=
2 ;
else
sd->exposure_step +=
2 ;
}
}
static void do_autogain(
struct gspca_dev *gspca_dev, u16 avg_lum)
{
struct sd *sd = (
struct sd *) gspca_dev;
s32 cur_gain = v4l2_ctrl_g_ctrl(sd->gain);
if (avg_lum < MIN_AVG_LUM && cur_gain < sd->gain->maximum)
v4l2_ctrl_s_ctrl(sd->gain, cur_gain +
1 );
if (avg_lum > MAX_AVG_LUM && cur_gain > sd->gain->minimum)
v4l2_ctrl_s_ctrl(sd->gain, cur_gain -
1 );
}
static void sd_dqcallback(
struct gspca_dev *gspca_dev)
{
struct sd *sd = (
struct sd *) gspca_dev;
int avg_lum;
if (sd->autogain == NULL || !v4l2_ctrl_g_ctrl(sd->autogain))
return ;
avg_lum = atomic_read(&sd->avg_lum);
if (sd->sensor == SENSOR_SOI968)
do_autogain(gspca_dev, avg_lum);
else
do_autoexposure(gspca_dev, avg_lum);
}
/* JPEG quality update */
/* This function is executed from a work queue. */
static void qual_upd(
struct work_struct *work)
{
struct sd *sd = container_of(work,
struct sd, work);
struct gspca_dev *gspca_dev = &sd->gspca_dev;
s32 qual = v4l2_ctrl_g_ctrl(sd->jpegqual);
/* To protect gspca_dev->usb_buf and gspca_dev->usb_err */
mutex_lock(&gspca_dev->usb_lock);
gspca_dbg(gspca_dev, D_STREAM,
"qual_upd %d%%\n" , qual);
gspca_dev->usb_err =
0 ;
set_quality(gspca_dev, qual);
mutex_unlock(&gspca_dev->usb_lock);
}
#if IS_ENABLED(CONFIG_INPUT)
static int sd_int_pkt_scan(
struct gspca_dev *gspca_dev,
u8 *data,
/* interrupt packet */
int len)
/* interrupt packet length */
{
struct sd *sd = (
struct sd *) gspca_dev;
if (!(sd->flags & HAS_NO_BUTTON) && len ==
1 ) {
input_report_key(gspca_dev->input_dev, KEY_CAMERA,
1 );
input_sync(gspca_dev->input_dev);
input_report_key(gspca_dev->input_dev, KEY_CAMERA,
0 );
input_sync(gspca_dev->input_dev);
return 0 ;
}
return -EINVAL;
}
#endif
/* check the JPEG compression */
static void transfer_check(
struct gspca_dev *gspca_dev,
u8 *data)
{
struct sd *sd = (
struct sd *) gspca_dev;
int new_qual, r;
new_qual =
0 ;
/* if USB error, discard the frame and decrease the quality */
if (data[
6 ] &
0 x08) {
/* USB FIFO full */
gspca_dev->last_packet_type = DISCARD_PACKET;
new_qual = -
5 ;
}
else {
/* else, compute the filling rate and a new JPEG quality */
r = (sd->pktsz *
100 ) /
(sd->npkt *
gspca_dev->urb[
0 ]->iso_frame_desc[
0 ].length);
if (r >=
85 )
new_qual = -
3 ;
else if (r <
75 )
new_qual =
2 ;
}
if (new_qual !=
0 ) {
sd->nchg += new_qual;
if (sd->nchg < -
6 || sd->nchg >=
12 ) {
/* Note: we are in interrupt context, so we can't
use v4l2_ctrl_g/s_ctrl here. Access the value
directly instead. */
s32 curqual = sd->jpegqual->cur.val;
sd->nchg =
0 ;
new_qual += curqual;
if (new_qual < sd->jpegqual->minimum)
new_qual = sd->jpegqual->minimum;
else if (new_qual > sd->jpegqual->maximum)
new_qual = sd->jpegqual->maximum;
if (new_qual != curqual) {
sd->jpegqual->cur.val = new_qual;
schedule_work(&sd->work);
}
}
}
else {
sd->nchg =
0 ;
}
sd->pktsz = sd->npkt =
0 ;
}
static void sd_pkt_scan(
struct gspca_dev *gspca_dev,
u8 *data,
/* isoc packet */
int len)
/* iso packet length */
{
struct sd *sd = (
struct sd *) gspca_dev;
int avg_lum, is_jpeg;
static const u8 frame_header[] = {
0 xff,
0 xff,
0 x00,
0 xc4,
0 xc4,
0 x96
};
is_jpeg = (sd->fmt &
0 x03) ==
0 ;
if (len >=
64 && memcmp(data, frame_header,
6 ) ==
0 ) {
avg_lum = ((data[
35 ] >>
2 ) &
3 ) |
(data[
20 ] <<
2 ) |
(data[
19 ] <<
10 );
avg_lum += ((data[
35 ] >>
4 ) &
3 ) |
(data[
22 ] <<
2 ) |
(data[
21 ] <<
10 );
avg_lum += ((data[
35 ] >>
6 ) &
3 ) |
(data[
24 ] <<
2 ) |
(data[
23 ] <<
10 );
avg_lum += (data[
36 ] &
3 ) |
(data[
26 ] <<
2 ) |
(data[
25 ] <<
10 );
avg_lum += ((data[
36 ] >>
2 ) &
3 ) |
(data[
28 ] <<
2 ) |
(data[
27 ] <<
10 );
avg_lum += ((data[
36 ] >>
4 ) &
3 ) |
(data[
30 ] <<
2 ) |
(data[
29 ] <<
10 );
avg_lum += ((data[
36 ] >>
6 ) &
3 ) |
(data[
32 ] <<
2 ) |
(data[
31 ] <<
10 );
avg_lum += ((data[
44 ] >>
4 ) &
3 ) |
(data[
34 ] <<
2 ) |
(data[
33 ] <<
10 );
avg_lum >>=
9 ;
atomic_set(&sd->avg_lum, avg_lum);
if (is_jpeg)
transfer_check(gspca_dev, data);
gspca_frame_add(gspca_dev, LAST_PACKET, NULL,
0 );
len -=
64 ;
if (len ==
0 )
return ;
data +=
64 ;
}
if (gspca_dev->last_packet_type == LAST_PACKET) {
if (is_jpeg) {
gspca_frame_add(gspca_dev, FIRST_PACKET,
sd->jpeg_hdr, JPEG_HDR_SZ);
gspca_frame_add(gspca_dev, INTER_PACKET,
data, len);
}
else {
gspca_frame_add(gspca_dev, FIRST_PACKET,
data, len);
}
}
else {
/* if JPEG, count the packets and their size */
if (is_jpeg) {
sd->npkt++;
sd->pktsz += len;
}
gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
}
}
/* sub-driver description */
static const struct sd_desc sd_desc = {
.name = KBUILD_MODNAME,
.config = sd_config,
.init = sd_init,
.init_controls = sd_init_controls,
.isoc_init = sd_isoc_init,
.start = sd_start,
.stopN = sd_stopN,
.stop0 = sd_stop0,
.pkt_scan = sd_pkt_scan,
#if IS_ENABLED(CONFIG_INPUT)
.int_pkt_scan = sd_int_pkt_scan,
#endif
.dq_callback = sd_dqcallback,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.set_register = sd_dbg_s_register,
.get_register = sd_dbg_g_register,
.get_chip_info = sd_chip_info,
#endif
};
#define SN9C20X(sensor, i2c_addr, flags) \
.driver_info = ((flags &
0 xff) <<
16 ) \
| (SENSOR_
## sensor <<
8 ) \
| (i2c_addr)
static const struct usb_device_id device_table[] = {
{USB_DEVICE(
0 x0c45,
0 x6240), SN9C20X(MT9M001,
0 x5d,
0 )},
{USB_DEVICE(
0 x0c45,
0 x6242), SN9C20X(MT9M111,
0 x5d, HAS_LED_TORCH)},
{USB_DEVICE(
0 x0c45,
0 x6248), SN9C20X(OV9655,
0 x30,
0 )},
{USB_DEVICE(
0 x0c45,
0 x624c), SN9C20X(MT9M112,
0 x5d,
0 )},
{USB_DEVICE(
0 x0c45,
0 x624e), SN9C20X(SOI968,
0 x30, LED_REVERSE)},
{USB_DEVICE(
0 x0c45,
0 x624f), SN9C20X(OV9650,
0 x30,
(FLIP_DETECT | HAS_NO_BUTTON))},
{USB_DEVICE(
0 x0c45,
0 x6251), SN9C20X(OV9650,
0 x30,
0 )},
{USB_DEVICE(
0 x0c45,
0 x6253), SN9C20X(OV9650,
0 x30,
0 )},
{USB_DEVICE(
0 x0c45,
0 x6260), SN9C20X(OV7670,
0 x21,
0 )},
{USB_DEVICE(
0 x0c45,
0 x6270), SN9C20X(MT9VPRB,
0 x00,
0 )},
{USB_DEVICE(
0 x0c45,
0 x627b), SN9C20X(OV7660,
0 x21, FLIP_DETECT)},
{USB_DEVICE(
0 x0c45,
0 x627c), SN9C20X(HV7131R,
0 x11,
0 )},
{USB_DEVICE(
0 x0c45,
0 x627f), SN9C20X(OV9650,
0 x30,
0 )},
{USB_DEVICE(
0 x0c45,
0 x6280), SN9C20X(MT9M001,
0 x5d,
0 )},
{USB_DEVICE(
0 x0c45,
0 x6282), SN9C20X(MT9M111,
0 x5d,
0 )},
{USB_DEVICE(
0 x0c45,
0 x6288), SN9C20X(OV9655,
0 x30,
0 )},
{USB_DEVICE(
0 x0c45,
0 x628c), SN9C20X(MT9M112,
0 x5d,
0 )},
{USB_DEVICE(
0 x0c45,
0 x628e), SN9C20X(SOI968,
0 x30,
0 )},
{USB_DEVICE(
0 x0c45,
0 x628f), SN9C20X(OV9650,
0 x30,
0 )},
{USB_DEVICE(
0 x0c45,
0 x62a0), SN9C20X(OV7670,
0 x21,
0 )},
{USB_DEVICE(
0 x0c45,
0 x62b0), SN9C20X(MT9VPRB,
0 x00,
0 )},
{USB_DEVICE(
0 x0c45,
0 x62b3), SN9C20X(OV9655,
0 x30, LED_REVERSE)},
{USB_DEVICE(
0 x0c45,
0 x62bb), SN9C20X(OV7660,
0 x21, LED_REVERSE)},
{USB_DEVICE(
0 x0c45,
0 x62bc), SN9C20X(HV7131R,
0 x11,
0 )},
{USB_DEVICE(
0 x045e,
0 x00f4), SN9C20X(OV9650,
0 x30,
0 )},
{USB_DEVICE(
0 x145f,
0 x013d), SN9C20X(OV7660,
0 x21,
0 )},
{USB_DEVICE(
0 x0458,
0 x7029), SN9C20X(HV7131R,
0 x11,
0 )},
{USB_DEVICE(
0 x0458,
0 x7045), SN9C20X(MT9M112,
0 x5d, LED_REVERSE)},
{USB_DEVICE(
0 x0458,
0 x704a), SN9C20X(MT9M112,
0 x5d,
0 )},
{USB_DEVICE(
0 x0458,
0 x704c), SN9C20X(MT9M112,
0 x5d,
0 )},
{USB_DEVICE(
0 xa168,
0 x0610), SN9C20X(HV7131R,
0 x11,
0 )},
{USB_DEVICE(
0 xa168,
0 x0611), SN9C20X(HV7131R,
0 x11,
0 )},
{USB_DEVICE(
0 xa168,
0 x0613), SN9C20X(HV7131R,
0 x11,
0 )},
{USB_DEVICE(
0 xa168,
0 x0618), SN9C20X(HV7131R,
0 x11,
0 )},
{USB_DEVICE(
0 xa168,
0 x0614), SN9C20X(MT9M111,
0 x5d,
0 )},
{USB_DEVICE(
0 xa168,
0 x0615), SN9C20X(MT9M111,
0 x5d,
0 )},
{USB_DEVICE(
0 xa168,
0 x0617), SN9C20X(MT9M111,
0 x5d,
0 )},
{}
};
MODULE_DEVICE_TABLE(usb, device_table);
/* -- device connect -- */
static int sd_probe(
struct usb_interface *intf,
const struct usb_device_id *id)
{
return gspca_dev_probe(intf, id, &sd_desc,
sizeof (
struct sd),
THIS_MODULE);
}
static struct usb_driver sd_driver = {
.name = KBUILD_MODNAME,
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
#ifdef CONFIG_PM
.suspend = gspca_suspend,
.resume = gspca_resume,
.reset_resume = gspca_resume,
#endif
};
module_usb_driver(sd_driver);
Messung V0.5 in Prozent C=95 H=93 G=93
¤ Dauer der Verarbeitung: 0.43 Sekunden
(vorverarbeitet am 2026-06-08)
¤
*© Formatika GbR, Deutschland