aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErik Andren <erik.andren@gmail.com>2008-10-01 03:51:53 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-10-12 07:37:13 -0400
commitc109f8168f259ea1f1ab7009c6b99dbe8ea0e2b2 (patch)
tree6dac06f9756469284dcc8c6dccb88ecdd4b10f9c
parenta3a58467db3c90a1e289970ef319c7abb90be617 (diff)
V4L/DVB (9091): gspca: Subdriver m5602 (ALi) added.
This patch adds support for the ALi m5602 usb bridge and is based on the gspca framework. It contains code for communicating with 5 different sensors: OmniVision OV9650, Pixel Plus PO1030, Samsung S5K83A, S5K4AA and finally Micron MT9M111. Signed-off-by: Erik Andren <erik.andren@gmail.com> Signed-off-by: Jean-Francois Moine <moinejf@free.fr> [mchehab@redhat.com: fix m5602/Makefile] [mchehab@redhat.com: extern debug caused conflicts. Renamed to m5602_debug] Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--Documentation/video4linux/gspca.txt1
-rw-r--r--Documentation/video4linux/m5602.txt12
-rw-r--r--drivers/media/video/gspca/Kconfig3
-rw-r--r--drivers/media/video/gspca/Makefile3
-rw-r--r--drivers/media/video/gspca/m5602/Kconfig11
-rw-r--r--drivers/media/video/gspca/m5602/Makefile11
-rw-r--r--drivers/media/video/gspca/m5602/m5602_bridge.h180
-rw-r--r--drivers/media/video/gspca/m5602/m5602_core.c321
-rw-r--r--drivers/media/video/gspca/m5602/m5602_mt9m111.c343
-rw-r--r--drivers/media/video/gspca/m5602/m5602_mt9m111.h1020
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov9650.c544
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov9650.h501
-rw-r--r--drivers/media/video/gspca/m5602/m5602_po1030.c334
-rw-r--r--drivers/media/video/gspca/m5602/m5602_po1030.h478
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k4aa.c460
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k4aa.h368
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k83a.c331
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k83a.h444
-rw-r--r--drivers/media/video/gspca/m5602/m5602_sensor.h76
19 files changed, 5441 insertions, 0 deletions
diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt
index 04c612eb897c..004818fab040 100644
--- a/Documentation/video4linux/gspca.txt
+++ b/Documentation/video4linux/gspca.txt
@@ -7,6 +7,7 @@ The modules are:
7xxxx vend:prod 7xxxx vend:prod
8---- 8----
9spca501 0000:0000 MystFromOri Unknow Camera 9spca501 0000:0000 MystFromOri Unknow Camera
10m5602 0402:5602 ALi Video Camera Controller
10spca501 040a:0002 Kodak DVC-325 11spca501 040a:0002 Kodak DVC-325
11spca500 040a:0300 Kodak EZ200 12spca500 040a:0300 Kodak EZ200
12zc3xx 041e:041e Creative WebCam Live! 13zc3xx 041e:041e Creative WebCam Live!
diff --git a/Documentation/video4linux/m5602.txt b/Documentation/video4linux/m5602.txt
new file mode 100644
index 000000000000..4450ab13f37b
--- /dev/null
+++ b/Documentation/video4linux/m5602.txt
@@ -0,0 +1,12 @@
1This document describes the ALi m5602 bridge connected
2to the following supported sensors:
3OmniVision OV9650,
4Samsung s5k83a,
5Samsung s5k4aa,
6Micron mt9m111,
7Pixel plus PO1030
8
9This driver mimics the windows drivers, which have a braindead implementation sending bayer-encoded frames at VGA resolution.
10In a perfect world we should be able to reprogram the m5602 and the connected sensor in hardware instead, supporting a range of resolutions and pixelformats
11
12Anyway, have fun and please report any bugs to m560x-driver-devel@lists.sourceforge.net
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig
index 42b90742b40b..fd31099e36a1 100644
--- a/drivers/media/video/gspca/Kconfig
+++ b/drivers/media/video/gspca/Kconfig
@@ -11,3 +11,6 @@ config USB_GSPCA
11 11
12 To compile this driver as modules, choose M here: the 12 To compile this driver as modules, choose M here: the
13 modules will be called gspca_xxxx. 13 modules will be called gspca_xxxx.
14
15source "drivers/media/video/gspca/m5602/Kconfig"
16
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile
index 78bad045913f..488ed97c58a3 100644
--- a/drivers/media/video/gspca/Makefile
+++ b/drivers/media/video/gspca/Makefile
@@ -28,3 +28,6 @@ gspca_t613-objs := t613.o
28gspca_tv8532-objs := tv8532.o 28gspca_tv8532-objs := tv8532.o
29gspca_vc032x-objs := vc032x.o 29gspca_vc032x-objs := vc032x.o
30gspca_zc3xx-objs := zc3xx.o 30gspca_zc3xx-objs := zc3xx.o
31
32obj-$(CONFIG_USB_M5602) += m5602/
33
diff --git a/drivers/media/video/gspca/m5602/Kconfig b/drivers/media/video/gspca/m5602/Kconfig
new file mode 100644
index 000000000000..7de33e22117e
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/Kconfig
@@ -0,0 +1,11 @@
1config USB_M5602
2 tristate "USB ALi m5602 Webcam support"
3 depends on VIDEO_V4L2 && USB_GSPCA
4 help
5 Say Y here if you want support for cameras based on the
6 ALi m5602 connected to various image sensors.
7
8 See <file:Documentation/video4linux/m5602.txt> for more info.
9
10 To compile this driver as a module, choose M here: the
11 module will be called gspca-m5602.
diff --git a/drivers/media/video/gspca/m5602/Makefile b/drivers/media/video/gspca/m5602/Makefile
new file mode 100644
index 000000000000..226ab4fc9d60
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/Makefile
@@ -0,0 +1,11 @@
1obj-$(CONFIG_USB_M5602) += gspca_m5602.o
2
3gspca_m5602-objs := m5602_core.o \
4 m5602_ov9650.o \
5 m5602_mt9m111.o \
6 m5602_po1030.o \
7 m5602_s5k83a.o \
8 m5602_s5k4aa.o
9
10EXTRA_CFLAGS += -Idrivers/media/video/gspca
11
diff --git a/drivers/media/video/gspca/m5602/m5602_bridge.h b/drivers/media/video/gspca/m5602/m5602_bridge.h
new file mode 100644
index 000000000000..fcbc37bfea51
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_bridge.h
@@ -0,0 +1,180 @@
1/*
2 * USB Driver for ALi m5602 based webcams
3 *
4 * Copyright (C) 2008 Erik Andren
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#ifndef M5602_BRIDGE_H_
20#define M5602_BRIDGE_H_
21
22#include "gspca.h"
23
24#define MODULE_NAME "ALi m5602"
25
26/*****************************************************************************/
27
28#undef PDEBUG
29#undef info
30#undef err
31
32#define err(format, arg...) printk(KERN_ERR KBUILD_MODNAME ": " \
33 format "\n" , ## arg)
34#define info(format, arg...) printk(KERN_INFO KBUILD_MODNAME ": " \
35 format "\n" , ## arg)
36
37/* Debug parameters */
38#define DBG_INIT 0x1
39#define DBG_PROBE 0x2
40#define DBG_V4L2 0x4
41#define DBG_TRACE 0x8
42#define DBG_DATA 0x10
43#define DBG_V4L2_CID 0x20
44#define DBG_GSPCA 0x40
45
46#define PDEBUG(level, fmt, args...) \
47 do { \
48 if (m5602_debug & level) \
49 info("[%s:%d] " fmt, __func__, __LINE__ , \
50 ## args); \
51 } while (0)
52
53/*****************************************************************************/
54
55#define M5602_XB_SENSOR_TYPE 0x00
56#define M5602_XB_SENSOR_CTRL 0x01
57#define M5602_XB_LINE_OF_FRAME_H 0x02
58#define M5602_XB_LINE_OF_FRAME_L 0x03
59#define M5602_XB_PIX_OF_LINE_H 0x04
60#define M5602_XB_PIX_OF_LINE_L 0x05
61#define M5602_XB_VSYNC_PARA 0x06
62#define M5602_XB_HSYNC_PARA 0x07
63#define M5602_XB_TEST_MODE_1 0x08
64#define M5602_XB_TEST_MODE_2 0x09
65#define M5602_XB_SIG_INI 0x0a
66#define M5602_XB_DS_PARA 0x0e
67#define M5602_XB_TRIG_PARA 0x0f
68#define M5602_XB_CLK_PD 0x10
69#define M5602_XB_MCU_CLK_CTRL 0x12
70#define M5602_XB_MCU_CLK_DIV 0x13
71#define M5602_XB_SEN_CLK_CTRL 0x14
72#define M5602_XB_SEN_CLK_DIV 0x15
73#define M5602_XB_AUD_CLK_CTRL 0x16
74#define M5602_XB_AUD_CLK_DIV 0x17
75#define M5602_XB_DEVCTR1 0x41
76#define M5602_XB_EPSETR0 0x42
77#define M5602_XB_EPAFCTR 0x47
78#define M5602_XB_EPBFCTR 0x49
79#define M5602_XB_EPEFCTR 0x4f
80#define M5602_XB_TEST_REG 0x53
81#define M5602_XB_ALT2SIZE 0x54
82#define M5602_XB_ALT3SIZE 0x55
83#define M5602_XB_OBSFRAME 0x56
84#define M5602_XB_PWR_CTL 0x59
85#define M5602_XB_ADC_CTRL 0x60
86#define M5602_XB_ADC_DATA 0x61
87#define M5602_XB_MISC_CTRL 0x62
88#define M5602_XB_SNAPSHOT 0x63
89#define M5602_XB_SCRATCH_1 0x64
90#define M5602_XB_SCRATCH_2 0x65
91#define M5602_XB_SCRATCH_3 0x66
92#define M5602_XB_SCRATCH_4 0x67
93#define M5602_XB_I2C_CTRL 0x68
94#define M5602_XB_I2C_CLK_DIV 0x69
95#define M5602_XB_I2C_DEV_ADDR 0x6a
96#define M5602_XB_I2C_REG_ADDR 0x6b
97#define M5602_XB_I2C_DATA 0x6c
98#define M5602_XB_I2C_STATUS 0x6d
99#define M5602_XB_GPIO_DAT_H 0x70
100#define M5602_XB_GPIO_DAT_L 0x71
101#define M5602_XB_GPIO_DIR_H 0x72
102#define M5602_XB_GPIO_DIR_L 0x73
103#define M5602_XB_GPIO_EN_H 0x74
104#define M5602_XB_GPIO_EN_L 0x75
105#define M5602_XB_GPIO_DAT 0x76
106#define M5602_XB_GPIO_DIR 0x77
107#define M5602_XB_MISC_CTL 0x70
108
109#define I2C_BUSY 0x80
110
111/*****************************************************************************/
112
113/* Driver info */
114#define DRIVER_AUTHOR "ALi m5602 Linux Driver Project"
115#define DRIVER_DESC "ALi m5602 webcam driver"
116
117#define M5602_ISOC_ENDPOINT_ADDR 0x81
118#define M5602_INTR_ENDPOINT_ADDR 0x82
119
120#define M5602_MAX_FRAMES 32
121#define M5602_URBS 2
122#define M5602_ISOC_PACKETS 14
123
124#define M5602_URB_TIMEOUT msecs_to_jiffies(2 * M5602_ISOC_PACKETS)
125#define M5602_URB_MSG_TIMEOUT 5000
126#define M5602_FRAME_TIMEOUT 2
127
128/*****************************************************************************/
129
130/* A skeleton used for sending messages to the m5602 bridge */
131static const unsigned char bridge_urb_skeleton[] = {
132 0x13, 0x00, 0x81, 0x00
133};
134
135/* A skeleton used for sending messages to the sensor */
136static const unsigned char sensor_urb_skeleton[] = {
137 0x23, M5602_XB_GPIO_EN_H, 0x81, 0x06,
138 0x23, M5602_XB_MISC_CTRL, 0x81, 0x80,
139 0x13, M5602_XB_I2C_DEV_ADDR, 0x81, 0x00,
140 0x13, M5602_XB_I2C_REG_ADDR, 0x81, 0x00,
141 0x13, M5602_XB_I2C_DATA, 0x81, 0x00,
142 0x13, M5602_XB_I2C_CTRL, 0x81, 0x11
143};
144
145/* m5602 device descriptor, currently it just wraps the m5602_camera struct */
146struct sd {
147 struct gspca_dev gspca_dev;
148
149 /* The name of the m5602 camera */
150 char *name;
151
152 /* A pointer to the currently connected sensor */
153 struct m5602_sensor *sensor;
154
155 /* The current frame's id, used to detect frame boundaries */
156 u8 frame_id;
157
158 /* The current frame count */
159 u32 frame_count;
160};
161
162int m5602_read_bridge(
163 struct sd *sd, u8 address, u8 *i2c_data);
164
165int m5602_write_bridge(
166 struct sd *sd, u8 address, u8 i2c_data);
167
168int m5602_configure(struct gspca_dev *gspca_dev,
169 const struct usb_device_id *id);
170
171int m5602_init(struct gspca_dev *gspca_dev);
172
173void m5602_start_transfer(struct gspca_dev *gspca_dev);
174
175void m5602_stop_transfer(struct gspca_dev *gspca_dev);
176
177void m5602_urb_complete(struct gspca_dev *gspca_dev, struct gspca_frame *frame,
178 __u8 *data, int len);
179
180#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c
new file mode 100644
index 000000000000..559495e2d11e
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_core.c
@@ -0,0 +1,321 @@
1/*
2 * USB Driver for ALi m5602 based webcams
3 *
4 * Copyright (C) 2008 Erik Andren
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#include "m5602_ov9650.h"
20#include "m5602_mt9m111.h"
21#include "m5602_po1030.h"
22#include "m5602_s5k83a.h"
23#include "m5602_s5k4aa.h"
24
25/* Kernel module parameters */
26int force_sensor;
27int dump_bridge;
28int dump_sensor;
29unsigned int m5602_debug;
30
31static const __devinitdata struct usb_device_id m5602_table[] = {
32 {USB_DEVICE(0x0402, 0x5602)},
33 {}
34};
35
36MODULE_DEVICE_TABLE(usb, m5602_table);
37
38/* sub-driver description, the ctrl and nctrl is filled at probe time */
39static struct sd_desc sd_desc = {
40 .name = MODULE_NAME,
41 .config = m5602_configure,
42 .init = m5602_init,
43 .start = m5602_start_transfer,
44 .stopN = m5602_stop_transfer,
45 .pkt_scan = m5602_urb_complete
46};
47
48/* Reads a byte from the m5602 */
49int m5602_read_bridge(struct sd *sd, u8 address, u8 *i2c_data)
50{
51 int err;
52 struct usb_device *udev = sd->gspca_dev.dev;
53 __u8 *buf = sd->gspca_dev.usb_buf;
54
55 err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
56 0x04, 0xc0, 0x14,
57 0x8100 + address, buf,
58 1, M5602_URB_MSG_TIMEOUT);
59 *i2c_data = buf[0];
60
61 PDEBUG(DBG_TRACE, "Reading bridge register 0x%x containing 0x%x",
62 address, *i2c_data);
63
64 /* usb_control_msg(...) returns the number of bytes sent upon success,
65 mask that and return zero upon success instead*/
66 return (err < 0) ? err : 0;
67}
68
69/* Writes a byte to to the m5602 */
70int m5602_write_bridge(struct sd *sd, u8 address, u8 i2c_data)
71{
72 int err;
73 struct usb_device *udev = sd->gspca_dev.dev;
74 __u8 *buf = sd->gspca_dev.usb_buf;
75
76 PDEBUG(DBG_TRACE, "Writing bridge register 0x%x with 0x%x",
77 address, i2c_data);
78
79 memcpy(buf, bridge_urb_skeleton,
80 sizeof(bridge_urb_skeleton));
81 buf[1] = address;
82 buf[3] = i2c_data;
83
84 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
85 0x04, 0x40, 0x19,
86 0x0000, buf,
87 4, M5602_URB_MSG_TIMEOUT);
88
89 /* usb_control_msg(...) returns the number of bytes sent upon success,
90 mask that and return zero upon success instead */
91 return (err < 0) ? err : 0;
92}
93
94/* Dump all the registers of the m5602 bridge,
95 unfortunately this breaks the camera until it's power cycled */
96static void m5602_dump_bridge(struct sd *sd)
97{
98 int i;
99 for (i = 0; i < 0x80; i++) {
100 unsigned char val = 0;
101 m5602_read_bridge(sd, i, &val);
102 info("ALi m5602 address 0x%x contains 0x%x", i, val);
103 }
104 info("Warning: The camera probably won't work until it's power cycled");
105}
106
107int m5602_probe_sensor(struct sd *sd)
108{
109 /* Try the po1030 */
110 sd->sensor = &po1030;
111 if (!sd->sensor->probe(sd)) {
112 sd_desc.ctrls = po1030.ctrls;
113 sd_desc.nctrls = po1030.nctrls;
114 return 0;
115 }
116
117 /* Try the mt9m111 sensor */
118 sd->sensor = &mt9m111;
119 if (!sd->sensor->probe(sd)) {
120 sd_desc.ctrls = mt9m111.ctrls;
121 sd_desc.nctrls = mt9m111.nctrls;
122 return 0;
123 }
124
125 /* Try the s5k4aa */
126 sd->sensor = &s5k4aa;
127 if (!sd->sensor->probe(sd)) {
128 sd_desc.ctrls = s5k4aa.ctrls;
129 sd_desc.nctrls = s5k4aa.nctrls;
130 return 0;
131 }
132
133 /* Try the ov9650 */
134 sd->sensor = &ov9650;
135 if (!sd->sensor->probe(sd)) {
136 sd_desc.ctrls = ov9650.ctrls;
137 sd_desc.nctrls = ov9650.nctrls;
138 return 0;
139 }
140
141 /* Try the s5k83a */
142 sd->sensor = &s5k83a;
143 if (!sd->sensor->probe(sd)) {
144 sd_desc.ctrls = s5k83a.ctrls;
145 sd_desc.nctrls = s5k83a.nctrls;
146 return 0;
147 }
148
149
150 /* More sensor probe function goes here */
151 info("Failed to find a sensor");
152 sd->sensor = NULL;
153 return -ENODEV;
154}
155
156int m5602_init(struct gspca_dev *gspca_dev)
157{
158 struct sd *sd = (struct sd *) gspca_dev;
159 int err;
160
161 PDEBUG(DBG_TRACE, "Initializing ALi m5602 webcam");
162 /* Run the init sequence */
163 err = sd->sensor->init(sd);
164
165 return err;
166}
167
168void m5602_start_transfer(struct gspca_dev *gspca_dev)
169{
170 struct sd *sd = (struct sd *) gspca_dev;
171 __u8 *buf = sd->gspca_dev.usb_buf;
172
173 /* Send start command to the camera */
174 const u8 buffer[4] = {0x13, 0xf9, 0x0f, 0x01};
175 memcpy(buf, buffer, sizeof(buffer));
176 usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0),
177 0x04, 0x40, 0x19, 0x0000, buf,
178 4, M5602_URB_MSG_TIMEOUT);
179
180 PDEBUG(DBG_V4L2, "Transfer started");
181}
182
183void m5602_urb_complete(struct gspca_dev *gspca_dev, struct gspca_frame *frame,
184 __u8 *data, int len)
185{
186 struct sd *sd = (struct sd *) gspca_dev;
187
188 if (len < 6) {
189 PDEBUG(DBG_DATA, "Packet is less than 6 bytes");
190 return;
191 }
192
193 /* Frame delimiter: ff xx xx xx ff ff */
194 if (data[0] == 0xff && data[4] == 0xff && data[5] == 0xff &&
195 data[2] != sd->frame_id) {
196 PDEBUG(DBG_DATA, "Frame delimiter detected");
197 sd->frame_id = data[2];
198
199 /* Remove the extra fluff appended on each header */
200 data += 6;
201 len -= 6;
202
203 /* Complete the last frame (if any) */
204 frame = gspca_frame_add(gspca_dev, LAST_PACKET,
205 frame, data, 0);
206
207 /* Create a new frame */
208 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
209
210 PDEBUG(DBG_V4L2, "Starting new frame. First urb contained %d",
211 len);
212
213 } else {
214 int cur_frame_len = frame->data_end - frame->data;
215
216 /* Remove urb header */
217 data += 4;
218 len -= 4;
219
220 if (cur_frame_len + len <= frame->v4l2_buf.length) {
221 PDEBUG(DBG_DATA, "Continuing frame copying %d bytes",
222 len);
223
224 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
225 data, len);
226 } else if (frame->v4l2_buf.length - cur_frame_len > 0) {
227 /* Add the remaining data up to frame size */
228 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data,
229 frame->v4l2_buf.length - cur_frame_len);
230 }
231 }
232}
233
234void m5602_stop_transfer(struct gspca_dev *gspca_dev)
235{
236 /* Is there are a command to stop a data transfer? */
237}
238
239/* this function is called at probe time */
240int m5602_configure(struct gspca_dev *gspca_dev,
241 const struct usb_device_id *id)
242{
243 struct sd *sd = (struct sd *) gspca_dev;
244 struct cam *cam;
245 int err;
246
247 PDEBUG(DBG_GSPCA, "m5602_configure start");
248 cam = &gspca_dev->cam;
249 cam->epaddr = M5602_ISOC_ENDPOINT_ADDR;
250
251 if (dump_bridge)
252 m5602_dump_bridge(sd);
253
254 /* Probe sensor */
255 err = m5602_probe_sensor(sd);
256 if (err)
257 goto fail;
258
259 PDEBUG(DBG_GSPCA, "m5602_configure end");
260 return 0;
261
262fail:
263 PDEBUG(DBG_GSPCA, "m5602_configure failed");
264 cam->cam_mode = NULL;
265 cam->nmodes = 0;
266
267 return err;
268}
269
270static int m5602_probe(struct usb_interface *intf,
271 const struct usb_device_id *id)
272{
273 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
274 THIS_MODULE);
275}
276
277static struct usb_driver sd_driver = {
278 .name = MODULE_NAME,
279 .id_table = m5602_table,
280 .probe = m5602_probe,
281#ifdef CONFIG_PM
282 .suspend = gspca_suspend,
283 .resume = gspca_resume,
284#endif
285 .disconnect = gspca_disconnect
286};
287
288/* -- module insert / remove -- */
289static int __init mod_m5602_init(void)
290{
291 if (usb_register(&sd_driver) < 0)
292 return -1;
293 PDEBUG(D_PROBE, "m5602 module registered");
294 return 0;
295}
296static void __exit mod_m5602_exit(void)
297{
298 usb_deregister(&sd_driver);
299 PDEBUG(D_PROBE, "m5602 module deregistered");
300}
301
302module_init(mod_m5602_init);
303module_exit(mod_m5602_exit);
304
305MODULE_AUTHOR(DRIVER_AUTHOR);
306MODULE_DESCRIPTION(DRIVER_DESC);
307MODULE_LICENSE("GPL");
308module_param_named(debug, m5602_debug, int, S_IRUGO | S_IWUSR);
309MODULE_PARM_DESC(debug, "toggles debug on/off");
310
311module_param(force_sensor, int, S_IRUGO | S_IWUSR);
312MODULE_PARM_DESC(force_sensor,
313 "force detection of sensor, "
314 "1 = OV9650, 2 = S5K83A, 3 = S5K4AA, 4 = MT9M111, 5 = PO1030");
315
316module_param(dump_bridge, bool, S_IRUGO | S_IWUSR);
317MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup");
318
319module_param(dump_sensor, bool, S_IRUGO | S_IWUSR);
320MODULE_PARM_DESC(dump_sensor, "Dumps all usb sensor registers "
321 "at startup providing a sensor is found");
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/drivers/media/video/gspca/m5602/m5602_mt9m111.c
new file mode 100644
index 000000000000..17f04dd5e1d3
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.c
@@ -0,0 +1,343 @@
1/*
2 * Driver for the mt9m111 sensor
3 *
4 * Copyright (C) 2008 Erik Andren
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#include "m5602_mt9m111.h"
20
21int mt9m111_probe(struct sd *sd)
22{
23 u8 data[2] = {0x00, 0x00};
24 int i;
25
26 if (force_sensor) {
27 if (force_sensor == MT9M111_SENSOR) {
28 info("Forcing a %s sensor", mt9m111.name);
29 goto sensor_found;
30 }
31 /* If we want to force another sensor, don't try to probe this
32 * one */
33 return -ENODEV;
34 }
35
36 info("Probing for a mt9m111 sensor");
37
38 /* Do the preinit */
39 for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) {
40 if (preinit_mt9m111[i][0] == BRIDGE) {
41 m5602_write_bridge(sd,
42 preinit_mt9m111[i][1],
43 preinit_mt9m111[i][2]);
44 } else {
45 data[0] = preinit_mt9m111[i][2];
46 data[1] = preinit_mt9m111[i][3];
47 mt9m111_write_sensor(sd,
48 preinit_mt9m111[i][1], data, 2);
49 }
50 }
51
52 if (mt9m111_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
53 return -ENODEV;
54
55 if ((data[0] == 0x14) && (data[1] == 0x3a)) {
56 info("Detected a mt9m111 sensor");
57 goto sensor_found;
58 }
59
60 return -ENODEV;
61
62sensor_found:
63 sd->gspca_dev.cam.cam_mode = mt9m111.modes;
64 sd->gspca_dev.cam.nmodes = mt9m111.nmodes;
65 return 0;
66}
67
68int mt9m111_init(struct sd *sd)
69{
70 int i, err;
71
72 /* Init the sensor */
73 for (i = 0; i < ARRAY_SIZE(init_mt9m111); i++) {
74 u8 data[2];
75
76 if (init_mt9m111[i][0] == BRIDGE) {
77 err = m5602_write_bridge(sd,
78 init_mt9m111[i][1],
79 init_mt9m111[i][2]);
80 } else {
81 data[0] = init_mt9m111[i][2];
82 data[1] = init_mt9m111[i][3];
83 err = mt9m111_write_sensor(sd,
84 init_mt9m111[i][1], data, 2);
85 }
86 }
87
88 if (dump_sensor)
89 mt9m111_dump_registers(sd);
90
91 return (err < 0) ? err : 0;
92}
93
94int mt9m111_power_down(struct sd *sd)
95{
96 return 0;
97}
98
99int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
100{
101 int err;
102 u8 data[2] = {0x00, 0x00};
103 struct sd *sd = (struct sd *) gspca_dev;
104
105 err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
106 data, 2);
107 *val = data[0] & MT9M111_RMB_MIRROR_ROWS;
108 PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val);
109
110 return (err < 0) ? err : 0;
111}
112
113int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
114{
115 int err;
116 u8 data[2] = {0x00, 0x00};
117 struct sd *sd = (struct sd *) gspca_dev;
118
119 PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val);
120
121 /* Set the correct page map */
122 err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
123 if (err < 0)
124 goto out;
125
126 err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
127 if (err < 0)
128 goto out;
129
130 data[0] = (data[0] & 0xfe) | val;
131 err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
132 data, 2);
133out:
134 return (err < 0) ? err : 0;
135}
136
137int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
138{
139 int err;
140 u8 data[2] = {0x00, 0x00};
141 struct sd *sd = (struct sd *) gspca_dev;
142
143 err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
144 data, 2);
145 *val = data[0] & MT9M111_RMB_MIRROR_COLS;
146 PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val);
147
148 return (err < 0) ? err : 0;
149}
150
151int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
152{
153 int err;
154 u8 data[2] = {0x00, 0x00};
155 struct sd *sd = (struct sd *) gspca_dev;
156
157 PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d", val);
158
159 /* Set the correct page map */
160 err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
161 if (err < 0)
162 goto out;
163
164 err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
165 if (err < 0)
166 goto out;
167
168 data[0] = (data[0] & 0xfd) | ((val << 1) & 0x02);
169 err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
170 data, 2);
171out:
172 return (err < 0) ? err : 0;
173}
174
175int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
176{
177 int err, tmp;
178 u8 data[2] = {0x00, 0x00};
179 struct sd *sd = (struct sd *) gspca_dev;
180
181 err = mt9m111_read_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2);
182 tmp = ((data[1] << 8) | data[0]);
183
184 *val = ((tmp & (1 << 10)) * 2) |
185 ((tmp & (1 << 9)) * 2) |
186 ((tmp & (1 << 8)) * 2) |
187 (tmp & 0x7f);
188
189 PDEBUG(DBG_V4L2_CID, "Read gain %d", *val);
190
191 return (err < 0) ? err : 0;
192}
193
194int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
195{
196 int err, tmp;
197 u8 data[2] = {0x00, 0x00};
198 struct sd *sd = (struct sd *) gspca_dev;
199
200 /* Set the correct page map */
201 err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
202 if (err < 0)
203 goto out;
204
205 if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2)
206 return -EINVAL;
207
208 if ((val >= INITIAL_MAX_GAIN * 2 * 2) &&
209 (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2))
210 tmp = (1 << 10) | (val << 9) |
211 (val << 8) | (val / 8);
212 else if ((val >= INITIAL_MAX_GAIN * 2) &&
213 (val < INITIAL_MAX_GAIN * 2 * 2))
214 tmp = (1 << 9) | (1 << 8) | (val / 4);
215 else if ((val >= INITIAL_MAX_GAIN) &&
216 (val < INITIAL_MAX_GAIN * 2))
217 tmp = (1 << 8) | (val / 2);
218 else
219 tmp = val;
220
221 data[1] = (tmp & 0xff00) >> 8;
222 data[0] = (tmp & 0xff);
223 PDEBUG(DBG_V4L2_CID, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
224 data[1], data[0]);
225
226 err = mt9m111_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
227 data, 2);
228out:
229 return (err < 0) ? err : 0;
230}
231
232int mt9m111_read_sensor(struct sd *sd, const u8 address,
233 u8 *i2c_data, const u8 len) {
234 int err, i;
235
236 do {
237 err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
238 } while ((*i2c_data & I2C_BUSY) && !err);
239 if (err < 0)
240 goto out;
241
242 err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
243 sd->sensor->i2c_slave_id);
244 if (err < 0)
245 goto out;
246
247 err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
248 if (err < 0)
249 goto out;
250
251 err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x1a);
252 if (err < 0)
253 goto out;
254
255 for (i = 0; i < len && !err; i++) {
256 err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
257
258 PDEBUG(DBG_TRACE, "Reading sensor register "
259 "0x%x contains 0x%x ", address, *i2c_data);
260 }
261out:
262 return (err < 0) ? err : 0;
263}
264
265int mt9m111_write_sensor(struct sd *sd, const u8 address,
266 u8 *i2c_data, const u8 len)
267{
268 int err, i;
269 u8 *p;
270 struct usb_device *udev = sd->gspca_dev.dev;
271 __u8 *buf = sd->gspca_dev.usb_buf;
272
273 /* No sensor with a data width larger
274 than 16 bits has yet been seen, nor with 0 :p*/
275 if (len > 2 || !len)
276 return -EINVAL;
277
278 memcpy(buf, sensor_urb_skeleton,
279 sizeof(sensor_urb_skeleton));
280
281 buf[11] = sd->sensor->i2c_slave_id;
282 buf[15] = address;
283
284 p = buf + 16;
285
286 /* Copy a four byte write sequence for each byte to be written to */
287 for (i = 0; i < len; i++) {
288 memcpy(p, sensor_urb_skeleton + 16, 4);
289 p[3] = i2c_data[i];
290 p += 4;
291 PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x",
292 address, i2c_data[i]);
293 }
294
295 /* Copy the tailer */
296 memcpy(p, sensor_urb_skeleton + 20, 4);
297
298 /* Set the total length */
299 p[3] = 0x10 + len;
300
301 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
302 0x04, 0x40, 0x19,
303 0x0000, buf,
304 20 + len * 4, M5602_URB_MSG_TIMEOUT);
305
306 return (err < 0) ? err : 0;
307}
308
309void mt9m111_dump_registers(struct sd *sd)
310{
311 u8 address, value[2] = {0x00, 0x00};
312
313 info("Dumping the mt9m111 register state");
314
315 info("Dumping the mt9m111 sensor core registers");
316 value[1] = MT9M111_SENSOR_CORE;
317 mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
318 for (address = 0; address < 0xff; address++) {
319 mt9m111_read_sensor(sd, address, value, 2);
320 info("register 0x%x contains 0x%x%x",
321 address, value[0], value[1]);
322 }
323
324 info("Dumping the mt9m111 color pipeline registers");
325 value[1] = MT9M111_COLORPIPE;
326 mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
327 for (address = 0; address < 0xff; address++) {
328 mt9m111_read_sensor(sd, address, value, 2);
329 info("register 0x%x contains 0x%x%x",
330 address, value[0], value[1]);
331 }
332
333 info("Dumping the mt9m111 camera control registers");
334 value[1] = MT9M111_CAMERA_CONTROL;
335 mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
336 for (address = 0; address < 0xff; address++) {
337 mt9m111_read_sensor(sd, address, value, 2);
338 info("register 0x%x contains 0x%x%x",
339 address, value[0], value[1]);
340 }
341
342 info("mt9m111 register state dump complete");
343}
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/drivers/media/video/gspca/m5602/m5602_mt9m111.h
new file mode 100644
index 000000000000..79a5d8878190
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.h
@@ -0,0 +1,1020 @@
1/*
2 * Driver for the mt9m111 sensor
3 *
4 * Copyright (C) 2008 Erik Andren
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * Some defines taken from the mt9m111 sensor driver
14 * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr>
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License as
18 * published by the Free Software Foundation, version 2.
19 *
20 */
21
22#ifndef M5602_MT9M111_H_
23#define M5602_MT9M111_H_
24
25#include "m5602_sensor.h"
26
27/*****************************************************************************/
28
29#define MT9M111_SC_CHIPVER 0x00
30#define MT9M111_SC_ROWSTART 0x01
31#define MT9M111_SC_COLSTART 0x02
32#define MT9M111_SC_WINDOW_HEIGHT 0x03
33#define MT9M111_SC_WINDOW_WIDTH 0x04
34#define MT9M111_SC_HBLANK_CONTEXT_B 0x05
35#define MT9M111_SC_VBLANK_CONTEXT_B 0x06
36#define MT9M111_SC_HBLANK_CONTEXT_A 0x07
37#define MT9M111_SC_VBLANK_CONTEXT_A 0x08
38#define MT9M111_SC_SHUTTER_WIDTH 0x09
39#define MT9M111_SC_ROW_SPEED 0x0a
40
41#define MT9M111_SC_EXTRA_DELAY 0x0b
42#define MT9M111_SC_SHUTTER_DELAY 0x0c
43#define MT9M111_SC_RESET 0x0d
44#define MT9M111_SC_R_MODE_CONTEXT_B 0x20
45#define MT9M111_SC_R_MODE_CONTEXT_A 0x21
46#define MT9M111_SC_FLASH_CONTROL 0x23
47#define MT9M111_SC_GREEN_1_GAIN 0x2b
48#define MT9M111_SC_BLUE_GAIN 0x2c
49#define MT9M111_SC_RED_GAIN 0x2d
50#define MT9M111_SC_GREEN_2_GAIN 0x2e
51#define MT9M111_SC_GLOBAL_GAIN 0x2f
52
53#define MT9M111_RMB_MIRROR_ROWS (1 << 0)
54#define MT9M111_RMB_MIRROR_COLS (1 << 1)
55
56#define MT9M111_CONTEXT_CONTROL 0xc8
57#define MT9M111_PAGE_MAP 0xf0
58#define MT9M111_BYTEWISE_ADDRESS 0xf1
59
60#define MT9M111_CP_OPERATING_MODE_CTL 0x06
61#define MT9M111_CP_LUMA_OFFSET 0x34
62#define MT9M111_CP_LUMA_CLIP 0x35
63#define MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A 0x3a
64#define MT9M111_CP_LENS_CORRECTION_1 0x3b
65#define MT9M111_CP_DEFECT_CORR_CONTEXT_A 0x4c
66#define MT9M111_CP_DEFECT_CORR_CONTEXT_B 0x4d
67#define MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B 0x9b
68#define MT9M111_CP_GLOBAL_CLK_CONTROL 0xb3
69
70#define MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18 0x65
71#define MT9M111_CC_AWB_PARAMETER_7 0x28
72
73#define MT9M111_SENSOR_CORE 0x00
74#define MT9M111_COLORPIPE 0x01
75#define MT9M111_CAMERA_CONTROL 0x02
76
77#define INITIAL_MAX_GAIN 64
78#define DEFAULT_GAIN 283
79
80/*****************************************************************************/
81
82/* Kernel module parameters */
83extern int force_sensor;
84extern int dump_sensor;
85extern unsigned int m5602_debug;
86
87int mt9m111_probe(struct sd *sd);
88int mt9m111_init(struct sd *sd);
89int mt9m111_power_down(struct sd *sd);
90
91int mt9m111_read_sensor(struct sd *sd, const u8 address,
92 u8 *i2c_data, const u8 len);
93
94int mt9m111_write_sensor(struct sd *sd, const u8 address,
95 u8 *i2c_data, const u8 len);
96
97void mt9m111_dump_registers(struct sd *sd);
98
99int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
100int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
101int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
102int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
103int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
104int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val);
105
106static struct m5602_sensor mt9m111 = {
107 .name = "MT9M111",
108
109 .i2c_slave_id = 0xba,
110
111 .probe = mt9m111_probe,
112 .init = mt9m111_init,
113 .power_down = mt9m111_power_down,
114
115 .read_sensor = mt9m111_read_sensor,
116 .write_sensor = mt9m111_write_sensor,
117
118 .nctrls = 3,
119 .ctrls = {
120 {
121 {
122 .id = V4L2_CID_VFLIP,
123 .type = V4L2_CTRL_TYPE_BOOLEAN,
124 .name = "vertical flip",
125 .minimum = 0,
126 .maximum = 1,
127 .step = 1,
128 .default_value = 0
129 },
130 .set = mt9m111_set_vflip,
131 .get = mt9m111_get_vflip
132 }, {
133 {
134 .id = V4L2_CID_HFLIP,
135 .type = V4L2_CTRL_TYPE_BOOLEAN,
136 .name = "horizontal flip",
137 .minimum = 0,
138 .maximum = 1,
139 .step = 1,
140 .default_value = 0
141 },
142 .set = mt9m111_set_hflip,
143 .get = mt9m111_get_hflip
144 }, {
145 {
146 .id = V4L2_CID_GAIN,
147 .type = V4L2_CTRL_TYPE_INTEGER,
148 .name = "gain",
149 .minimum = 0,
150 .maximum = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2,
151 .step = 1,
152 .default_value = DEFAULT_GAIN,
153 .flags = V4L2_CTRL_FLAG_SLIDER
154 },
155 .set = mt9m111_set_hflip,
156 .get = mt9m111_get_hflip
157 }
158 },
159
160 .nmodes = 1,
161 .modes = {
162 {
163 M5602_DEFAULT_FRAME_WIDTH,
164 M5602_DEFAULT_FRAME_HEIGHT,
165 V4L2_PIX_FMT_SBGGR8,
166 V4L2_FIELD_NONE,
167 .sizeimage =
168 M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT,
169 .bytesperline = M5602_DEFAULT_FRAME_WIDTH,
170 .colorspace = V4L2_COLORSPACE_SRGB,
171 .priv = 1
172 }
173 }
174};
175
176static const unsigned char preinit_mt9m111[][4] =
177{
178 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
179 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
180 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
181 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
182 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
183 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
184 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
185 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
186
187 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
188 {SENSOR, MT9M111_SC_RESET, 0xff, 0xf7},
189
190 {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
191 {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
192 {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
193 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
194 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
195 {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
196 {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
197 {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
198
199 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
200 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
201 {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
202 {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
203 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
204 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
205
206 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}
207};
208
209static const unsigned char init_mt9m111[][4] =
210{
211 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
212 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
213 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
214 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
215 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
216 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
217 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
218 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
219 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
220 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
221 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
222
223 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
224 {SENSOR, MT9M111_SC_RESET, 0xff, 0xff},
225 {SENSOR, MT9M111_SC_RESET, 0xff, 0xff},
226 {SENSOR, MT9M111_SC_RESET, 0xff, 0xde},
227 {SENSOR, MT9M111_SC_RESET, 0xff, 0xff},
228 {SENSOR, MT9M111_SC_RESET, 0xff, 0xf7},
229 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
230
231 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
232
233 {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0xff, 0xff},
234
235 {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
236 {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
237 {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
238 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
239 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
240 {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
241 {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
242 {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
243 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
244 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
245 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
246 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
247 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
248 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
249 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
250 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
251 {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
252 {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
253 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
254 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
255 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
256
257 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
258 {SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
259 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
260 {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
261 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
262 {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
263 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
264 {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
265 {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
266 {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
267 {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
268 {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
269 {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
270 {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
271 {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
272 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
273
274 {SENSOR, 0xcd, 0x00, 0x0e},
275 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
276 {SENSOR, 0xd0, 0x00, 0x40},
277 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
278 {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
279 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
280 {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
281 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
282 {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
283 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
284 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
285 {SENSOR, 0x33, 0x03, 0x49},
286 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
287
288 {SENSOR, 0x33, 0x03, 0x49},
289 {SENSOR, 0x34, 0xc0, 0x19},
290 {SENSOR, 0x3f, 0x20, 0x20},
291 {SENSOR, 0x40, 0x20, 0x20},
292 {SENSOR, 0x5a, 0xc0, 0x0a},
293 {SENSOR, 0x70, 0x7b, 0x0a},
294 {SENSOR, 0x71, 0xff, 0x00},
295 {SENSOR, 0x72, 0x19, 0x0e},
296 {SENSOR, 0x73, 0x18, 0x0f},
297 {SENSOR, 0x74, 0x57, 0x32},
298 {SENSOR, 0x75, 0x56, 0x34},
299 {SENSOR, 0x76, 0x73, 0x35},
300 {SENSOR, 0x77, 0x30, 0x12},
301 {SENSOR, 0x78, 0x79, 0x02},
302 {SENSOR, 0x79, 0x75, 0x06},
303 {SENSOR, 0x7a, 0x77, 0x0a},
304 {SENSOR, 0x7b, 0x78, 0x09},
305 {SENSOR, 0x7c, 0x7d, 0x06},
306 {SENSOR, 0x7d, 0x31, 0x10},
307 {SENSOR, 0x7e, 0x00, 0x7e},
308 {SENSOR, 0x80, 0x59, 0x04},
309 {SENSOR, 0x81, 0x59, 0x04},
310 {SENSOR, 0x82, 0x57, 0x0a},
311 {SENSOR, 0x83, 0x58, 0x0b},
312 {SENSOR, 0x84, 0x47, 0x0c},
313 {SENSOR, 0x85, 0x48, 0x0e},
314 {SENSOR, 0x86, 0x5b, 0x02},
315 {SENSOR, 0x87, 0x00, 0x5c},
316 {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
317 {SENSOR, 0x60, 0x00, 0x80},
318 {SENSOR, 0x61, 0x00, 0x00},
319 {SENSOR, 0x62, 0x00, 0x00},
320 {SENSOR, 0x63, 0x00, 0x00},
321 {SENSOR, 0x64, 0x00, 0x00},
322
323 {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
324 {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18},
325 {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04},
326 {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08},
327 {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38},
328 {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
329 {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38},
330 {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
331 {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03},
332 {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03},
333 {SENSOR, 0x30, 0x04, 0x00},
334
335 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
336 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
337 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
338 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
339 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
340 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
341 {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
342 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
343 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
344 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
345 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
346 {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
347 {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
348 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
349 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
350 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
351 {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
352 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
353 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
354 {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
355 {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00},
356 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
357 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
358 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00},
359 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
360 {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4},
361 {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea},
362
363 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
364 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
365 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
366 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
367 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
368 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
369 {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
370 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
371 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
372 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
373 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
374 {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
375 {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
376 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
377 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
378 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
379 {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
380 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
381 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
382 {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
383 {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00},
384 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
385 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
386 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
387
388 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
389 {SENSOR, MT9M111_SC_RESET, 0x00, 0x09},
390 {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
391 {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
392 {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c},
393 {SENSOR, MT9M111_SC_RESET, 0x00, 0x04},
394 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
395 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
396 {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03},
397 {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
398 {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
399 {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
400 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
401 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
402 {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
403 {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
404 {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
405 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
406 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
407 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
408 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
409 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
410 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
411 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
412 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
413 {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
414 {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
415 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
416 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
417 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
418
419 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
420 {SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
421 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
422 {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
423 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
424 {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
425 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
426 {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
427 {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
428 {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
429 {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
430 {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
431 {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
432 {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
433 {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
434
435 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
436 {SENSOR, 0xcd, 0x00, 0x0e},
437 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
438 {SENSOR, 0xd0, 0x00, 0x40},
439 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
440 {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
441 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
442 {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
443 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
444 {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
445 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
446 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
447 {SENSOR, 0x33, 0x03, 0x49},
448 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
449
450 {SENSOR, 0x33, 0x03, 0x49},
451 {SENSOR, 0x34, 0xc0, 0x19},
452 {SENSOR, 0x3f, 0x20, 0x20},
453 {SENSOR, 0x40, 0x20, 0x20},
454 {SENSOR, 0x5a, 0xc0, 0x0a},
455 {SENSOR, 0x70, 0x7b, 0x0a},
456 {SENSOR, 0x71, 0xff, 0x00},
457 {SENSOR, 0x72, 0x19, 0x0e},
458 {SENSOR, 0x73, 0x18, 0x0f},
459 {SENSOR, 0x74, 0x57, 0x32},
460 {SENSOR, 0x75, 0x56, 0x34},
461 {SENSOR, 0x76, 0x73, 0x35},
462 {SENSOR, 0x77, 0x30, 0x12},
463 {SENSOR, 0x78, 0x79, 0x02},
464 {SENSOR, 0x79, 0x75, 0x06},
465 {SENSOR, 0x7a, 0x77, 0x0a},
466 {SENSOR, 0x7b, 0x78, 0x09},
467 {SENSOR, 0x7c, 0x7d, 0x06},
468 {SENSOR, 0x7d, 0x31, 0x10},
469 {SENSOR, 0x7e, 0x00, 0x7e},
470 {SENSOR, 0x80, 0x59, 0x04},
471 {SENSOR, 0x81, 0x59, 0x04},
472 {SENSOR, 0x82, 0x57, 0x0a},
473 {SENSOR, 0x83, 0x58, 0x0b},
474 {SENSOR, 0x84, 0x47, 0x0c},
475 {SENSOR, 0x85, 0x48, 0x0e},
476 {SENSOR, 0x86, 0x5b, 0x02},
477 {SENSOR, 0x87, 0x00, 0x5c},
478 {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
479 {SENSOR, 0x60, 0x00, 0x80},
480 {SENSOR, 0x61, 0x00, 0x00},
481 {SENSOR, 0x62, 0x00, 0x00},
482 {SENSOR, 0x63, 0x00, 0x00},
483 {SENSOR, 0x64, 0x00, 0x00},
484
485 {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
486 {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18},
487 {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04},
488 {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08},
489 {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38},
490 {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
491 {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38},
492 {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
493 {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03},
494 {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03},
495 {SENSOR, 0x30, 0x04, 0x00},
496
497 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
498 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
499 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
500 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
501 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
502 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
503 {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
504 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
505 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
506 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
507 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
508 {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
509 {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
510 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
511 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
512 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
513 {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
514 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
515 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
516 {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
517 {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00},
518 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
519 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
520 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00},
521 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
522 {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4},
523 {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea},
524 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
525 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
526
527 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
528 {SENSOR, MT9M111_SC_RESET, 0x00, 0x09},
529 {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
530 {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
531 {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c},
532 {SENSOR, MT9M111_SC_RESET, 0x00, 0x04},
533 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
534
535 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
536 {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03},
537 {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
538 {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
539 {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
540 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
541 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
542 {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
543 {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
544 {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
545 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
546 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
547 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
548 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
549 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
550 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
551 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
552 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
553 {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
554 {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
555 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
556 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
557 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
558
559 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
560 {SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
561 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
562 {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
563 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
564 {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
565 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
566 {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
567 {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
568 {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
569 {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
570 {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
571 {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
572 {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
573 {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
574
575 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
576 {SENSOR, 0xcd, 0x00, 0x0e},
577 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
578 {SENSOR, 0xd0, 0x00, 0x40},
579 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
580 {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
581 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
582 {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
583 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
584 {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
585 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
586 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
587 {SENSOR, 0x33, 0x03, 0x49},
588 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
589
590 {SENSOR, 0x33, 0x03, 0x49},
591 {SENSOR, 0x34, 0xc0, 0x19},
592 {SENSOR, 0x3f, 0x20, 0x20},
593 {SENSOR, 0x40, 0x20, 0x20},
594 {SENSOR, 0x5a, 0xc0, 0x0a},
595 {SENSOR, 0x70, 0x7b, 0x0a},
596 {SENSOR, 0x71, 0xff, 0x00},
597 {SENSOR, 0x72, 0x19, 0x0e},
598 {SENSOR, 0x73, 0x18, 0x0f},
599 {SENSOR, 0x74, 0x57, 0x32},
600 {SENSOR, 0x75, 0x56, 0x34},
601 {SENSOR, 0x76, 0x73, 0x35},
602 {SENSOR, 0x77, 0x30, 0x12},
603 {SENSOR, 0x78, 0x79, 0x02},
604 {SENSOR, 0x79, 0x75, 0x06},
605 {SENSOR, 0x7a, 0x77, 0x0a},
606 {SENSOR, 0x7b, 0x78, 0x09},
607 {SENSOR, 0x7c, 0x7d, 0x06},
608 {SENSOR, 0x7d, 0x31, 0x10},
609 {SENSOR, 0x7e, 0x00, 0x7e},
610 {SENSOR, 0x80, 0x59, 0x04},
611 {SENSOR, 0x81, 0x59, 0x04},
612 {SENSOR, 0x82, 0x57, 0x0a},
613 {SENSOR, 0x83, 0x58, 0x0b},
614 {SENSOR, 0x84, 0x47, 0x0c},
615 {SENSOR, 0x85, 0x48, 0x0e},
616 {SENSOR, 0x86, 0x5b, 0x02},
617 {SENSOR, 0x87, 0x00, 0x5c},
618 {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
619 {SENSOR, 0x60, 0x00, 0x80},
620 {SENSOR, 0x61, 0x00, 0x00},
621 {SENSOR, 0x62, 0x00, 0x00},
622 {SENSOR, 0x63, 0x00, 0x00},
623 {SENSOR, 0x64, 0x00, 0x00},
624
625 {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
626 {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18},
627 {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04},
628 {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08},
629 {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38},
630 {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
631 {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38},
632 {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
633 {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03},
634 {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03},
635 {SENSOR, 0x30, 0x04, 0x00},
636
637 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
638 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
639 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
640 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
641 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
642 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
643 {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
644 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
645 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
646 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
647 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
648 {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
649 {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
650 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
651 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
652 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
653 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
654 {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
655 {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00},
656 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
657 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
658 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00},
659 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
660 {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4},
661 {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea},
662 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
663 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
664 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
665 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
666 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
667 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
668 {SENSOR, MT9M111_SC_RESET, 0x00, 0x09},
669 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
670 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
671 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
672 {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
673 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
674 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
675 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
676 {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
677 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
678 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
679 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
680 {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c},
681 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
682 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
683 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
684 {SENSOR, MT9M111_SC_RESET, 0x00, 0x04},
685 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
686 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
687 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
688 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
689 {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03},
690 {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
691 {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
692 {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
693 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
694 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
695 {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
696 {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
697 {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
698 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
699 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
700 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
701 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
702 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
703 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
704 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
705 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
706 {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
707 {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
708 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
709 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
710 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
711 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
712 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
713 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
714 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
715 {SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
716 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
717 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
718 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
719 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
720 {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
721 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
722 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
723 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
724 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
725
726 {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
727 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
728 {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
729 {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
730 {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
731 {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
732 {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
733 {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
734 {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
735 {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
736
737 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
738 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
739 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
740 {SENSOR, 0xcd, 0x00, 0x0e},
741 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
742 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
743 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
744 {SENSOR, 0xd0, 0x00, 0x40},
745 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
746 {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
747 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
748 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
749 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
750 {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
751 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
752 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
753 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
754 {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
755 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
756 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
757 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
758 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
759 {SENSOR, 0x33, 0x03, 0x49},
760 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
761 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
762 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
763
764 {SENSOR, 0x33, 0x03, 0x49},
765 {SENSOR, 0x34, 0xc0, 0x19},
766 {SENSOR, 0x3f, 0x20, 0x20},
767 {SENSOR, 0x40, 0x20, 0x20},
768 {SENSOR, 0x5a, 0xc0, 0x0a},
769 {SENSOR, 0x70, 0x7b, 0x0a},
770 {SENSOR, 0x71, 0xff, 0x00},
771 {SENSOR, 0x72, 0x19, 0x0e},
772 {SENSOR, 0x73, 0x18, 0x0f},
773 {SENSOR, 0x74, 0x57, 0x32},
774 {SENSOR, 0x75, 0x56, 0x34},
775 {SENSOR, 0x76, 0x73, 0x35},
776 {SENSOR, 0x77, 0x30, 0x12},
777 {SENSOR, 0x78, 0x79, 0x02},
778 {SENSOR, 0x79, 0x75, 0x06},
779 {SENSOR, 0x7a, 0x77, 0x0a},
780 {SENSOR, 0x7b, 0x78, 0x09},
781 {SENSOR, 0x7c, 0x7d, 0x06},
782 {SENSOR, 0x7d, 0x31, 0x10},
783 {SENSOR, 0x7e, 0x00, 0x7e},
784 {SENSOR, 0x80, 0x59, 0x04},
785 {SENSOR, 0x81, 0x59, 0x04},
786 {SENSOR, 0x82, 0x57, 0x0a},
787 {SENSOR, 0x83, 0x58, 0x0b},
788 {SENSOR, 0x84, 0x47, 0x0c},
789 {SENSOR, 0x85, 0x48, 0x0e},
790 {SENSOR, 0x86, 0x5b, 0x02},
791 {SENSOR, 0x87, 0x00, 0x5c},
792 {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
793 {SENSOR, 0x60, 0x00, 0x80},
794 {SENSOR, 0x61, 0x00, 0x00},
795 {SENSOR, 0x62, 0x00, 0x00},
796 {SENSOR, 0x63, 0x00, 0x00},
797 {SENSOR, 0x64, 0x00, 0x00},
798 {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
799 {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12},
800 {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00},
801 {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10},
802 {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60},
803 {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
804 {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60},
805 {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
806 {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x0f},
807 {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f},
808 {SENSOR, 0x30, 0x04, 0x00},
809
810 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
811 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
812 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
813 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
814 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
815 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
816 {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
817 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
818 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
819 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
820 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
821 {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
822 {BRIDGE, M5602_XB_VSYNC_PARA, 0xe3, 0x00},
823 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
824 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
825 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
826 {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
827 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
828 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
829 {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
830 {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00},
831 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
832 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
833 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
834
835 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
836 {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90},
837 {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xe6},
838 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
839 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
840 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
841 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
842 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
843 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
844 {SENSOR, MT9M111_SC_RESET, 0x00, 0x09},
845 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
846 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
847 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
848 {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
849 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
850 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
851 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
852 {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
853 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
854 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
855 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
856 {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c},
857 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
858 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
859 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
860 {SENSOR, MT9M111_SC_RESET, 0x00, 0x04},
861 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
862 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
863 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
864 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
865 {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03},
866
867 {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
868 {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
869 {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
870 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
871 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
872 {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
873 {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
874 {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
875 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
876 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
877 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
878 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
879 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
880 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
881 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
882 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
883 {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
884 {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
885 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
886 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
887 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
888 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
889 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
890 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
891 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
892 {SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
893 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
894 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
895 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
896 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
897 {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
898 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
899 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
900 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
901 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
902 {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
903 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
904 {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
905 {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
906 {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
907 {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
908 {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
909 {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
910 {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
911 {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
912
913 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
914 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
915 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
916 {SENSOR, 0xcd, 0x00, 0x0e},
917 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
918 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
919 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
920 {SENSOR, 0xd0, 0x00, 0x40},
921 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
922 {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
923 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
924 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
925 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
926 {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
927 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
928 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
929 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
930 {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
931 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
932
933 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
934 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
935 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
936 {SENSOR, 0x33, 0x03, 0x49},
937 {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
938 {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
939 {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
940
941 {SENSOR, 0x33, 0x03, 0x49},
942 {SENSOR, 0x34, 0xc0, 0x19},
943 {SENSOR, 0x3f, 0x20, 0x20},
944 {SENSOR, 0x40, 0x20, 0x20},
945 {SENSOR, 0x5a, 0xc0, 0x0a},
946 {SENSOR, 0x70, 0x7b, 0x0a},
947 {SENSOR, 0x71, 0xff, 0x00},
948 {SENSOR, 0x72, 0x19, 0x0e},
949 {SENSOR, 0x73, 0x18, 0x0f},
950 {SENSOR, 0x74, 0x57, 0x32},
951 {SENSOR, 0x75, 0x56, 0x34},
952 {SENSOR, 0x76, 0x73, 0x35},
953 {SENSOR, 0x77, 0x30, 0x12},
954 {SENSOR, 0x78, 0x79, 0x02},
955 {SENSOR, 0x79, 0x75, 0x06},
956 {SENSOR, 0x7a, 0x77, 0x0a},
957 {SENSOR, 0x7b, 0x78, 0x09},
958 {SENSOR, 0x7c, 0x7d, 0x06},
959 {SENSOR, 0x7d, 0x31, 0x10},
960 {SENSOR, 0x7e, 0x00, 0x7e},
961 {SENSOR, 0x80, 0x59, 0x04},
962 {SENSOR, 0x81, 0x59, 0x04},
963 {SENSOR, 0x82, 0x57, 0x0a},
964 {SENSOR, 0x83, 0x58, 0x0b},
965 {SENSOR, 0x84, 0x47, 0x0c},
966 {SENSOR, 0x85, 0x48, 0x0e},
967 {SENSOR, 0x86, 0x5b, 0x02},
968 {SENSOR, 0x87, 0x00, 0x5c},
969 {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
970 {SENSOR, 0x60, 0x00, 0x80},
971 {SENSOR, 0x61, 0x00, 0x00},
972 {SENSOR, 0x62, 0x00, 0x00},
973 {SENSOR, 0x63, 0x00, 0x00},
974 {SENSOR, 0x64, 0x00, 0x00},
975
976 {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
977 {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12},
978 {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00},
979 {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10},
980 {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60},
981 {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
982 {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60},
983 {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
984 {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x0f},
985 {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f},
986 {SENSOR, 0x30, 0x04, 0x00},
987
988 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
989 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
990 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
991 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
992 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
993 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
994 {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
995 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
996 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
997 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
998 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
999 {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
1000 {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00},
1001 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
1002 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
1003 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
1004 {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
1005 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
1006 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
1007 {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
1008 {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00},
1009 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
1010 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
1011 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
1012
1013 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
1014 /* Set number of blank rows chosen to 400 */
1015 {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90},
1016 /* Set the global gain to 283 (of 512) */
1017 {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x03, 0x63}
1018};
1019
1020#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c
new file mode 100644
index 000000000000..74c3ffec0ca2
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c
@@ -0,0 +1,544 @@
1/*
2 * Driver for the ov9650 sensor
3 *
4 * Copyright (C) 2008 Erik Andren
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#include "m5602_ov9650.h"
20
21int ov9650_read_sensor(struct sd *sd, const u8 address,
22 u8 *i2c_data, const u8 len)
23{
24 int err, i;
25
26 /* The ov9650 registers have a max depth of one byte */
27 if (len > 1 || !len)
28 return -EINVAL;
29
30 do {
31 err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
32 } while ((*i2c_data & I2C_BUSY) && !err);
33
34 m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
35 ov9650.i2c_slave_id);
36 m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
37 m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len);
38 m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08);
39
40 for (i = 0; i < len; i++) {
41 err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
42
43 PDEBUG(DBG_TRACE, "Reading sensor register "
44 "0x%x containing 0x%x ", address, *i2c_data);
45 }
46 return (err < 0) ? err : 0;
47}
48
49int ov9650_write_sensor(struct sd *sd, const u8 address,
50 u8 *i2c_data, const u8 len)
51{
52 int err, i;
53 u8 *p;
54 struct usb_device *udev = sd->gspca_dev.dev;
55 __u8 *buf = sd->gspca_dev.usb_buf;
56
57 /* The ov9650 only supports one byte writes */
58 if (len > 1 || !len)
59 return -EINVAL;
60
61 memcpy(buf, sensor_urb_skeleton,
62 sizeof(sensor_urb_skeleton));
63
64 buf[11] = sd->sensor->i2c_slave_id;
65 buf[15] = address;
66
67 /* Special case larger sensor writes */
68 p = buf + 16;
69
70 /* Copy a four byte write sequence for each byte to be written to */
71 for (i = 0; i < len; i++) {
72 memcpy(p, sensor_urb_skeleton + 16, 4);
73 p[3] = i2c_data[i];
74 p += 4;
75 PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x",
76 address, i2c_data[i]);
77 }
78
79 /* Copy the tailer */
80 memcpy(p, sensor_urb_skeleton + 20, 4);
81
82 /* Set the total length */
83 p[3] = 0x10 + len;
84
85 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
86 0x04, 0x40, 0x19,
87 0x0000, buf,
88 20 + len * 4, M5602_URB_MSG_TIMEOUT);
89
90 return (err < 0) ? err : 0;
91}
92
93int ov9650_probe(struct sd *sd)
94{
95 u8 prod_id = 0, ver_id = 0, i;
96
97 if (force_sensor) {
98 if (force_sensor == OV9650_SENSOR) {
99 info("Forcing an %s sensor", ov9650.name);
100 goto sensor_found;
101 }
102 /* If we want to force another sensor,
103 don't try to probe this one */
104 return -ENODEV;
105 }
106
107 info("Probing for an ov9650 sensor");
108
109 /* Run the pre-init to actually probe the unit */
110 for (i = 0; i < ARRAY_SIZE(preinit_ov9650); i++) {
111 u8 data = preinit_ov9650[i][2];
112 if (preinit_ov9650[i][0] == SENSOR)
113 ov9650_write_sensor(sd,
114 preinit_ov9650[i][1], &data, 1);
115 else
116 m5602_write_bridge(sd, preinit_ov9650[i][1], data);
117 }
118
119 if (ov9650_read_sensor(sd, OV9650_PID, &prod_id, 1))
120 return -ENODEV;
121
122 if (ov9650_read_sensor(sd, OV9650_VER, &ver_id, 1))
123 return -ENODEV;
124
125 if ((prod_id == 0x96) && (ver_id == 0x52)) {
126 info("Detected an ov9650 sensor");
127 goto sensor_found;
128 }
129
130 return -ENODEV;
131
132sensor_found:
133 sd->gspca_dev.cam.cam_mode = ov9650.modes;
134 sd->gspca_dev.cam.nmodes = ov9650.nmodes;
135 return 0;
136}
137
138int ov9650_init(struct sd *sd)
139{
140 int i, err = 0;
141 u8 data;
142
143 if (dump_sensor)
144 ov9650_dump_registers(sd);
145
146 for (i = 0; i < ARRAY_SIZE(init_ov9650) && !err; i++) {
147 data = init_ov9650[i][2];
148 if (init_ov9650[i][0] == SENSOR)
149 err = ov9650_write_sensor(sd, init_ov9650[i][1],
150 &data, 1);
151 else
152 err = m5602_write_bridge(sd, init_ov9650[i][1], data);
153 }
154
155 if (!err && dmi_check_system(ov9650_flip_dmi_table)) {
156 info("vflip quirk active");
157 data = 0x30;
158 err = ov9650_write_sensor(sd, OV9650_MVFP, &data, 1);
159 }
160
161 return (err < 0) ? err : 0;
162}
163
164int ov9650_power_down(struct sd *sd)
165{
166 int i;
167 for (i = 0; i < ARRAY_SIZE(power_down_ov9650); i++) {
168 u8 data = power_down_ov9650[i][2];
169 if (power_down_ov9650[i][0] == SENSOR)
170 ov9650_write_sensor(sd,
171 power_down_ov9650[i][1], &data, 1);
172 else
173 m5602_write_bridge(sd, power_down_ov9650[i][1], data);
174 }
175
176 return 0;
177}
178
179int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
180{
181 struct sd *sd = (struct sd *) gspca_dev;
182 u8 i2c_data;
183 int err;
184
185 err = ov9650_read_sensor(sd, OV9650_COM1, &i2c_data, 1);
186 if (err < 0)
187 goto out;
188 *val = i2c_data & 0x03;
189
190 err = ov9650_read_sensor(sd, OV9650_AECH, &i2c_data, 1);
191 if (err < 0)
192 goto out;
193 *val |= (i2c_data << 2);
194
195 err = ov9650_read_sensor(sd, OV9650_AECHM, &i2c_data, 1);
196 if (err < 0)
197 goto out;
198 *val |= (i2c_data & 0x3f) << 10;
199
200 PDEBUG(DBG_V4L2_CID, "Read exposure %d", *val);
201out:
202 return (err < 0) ? err : 0;
203}
204
205int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
206{
207 struct sd *sd = (struct sd *) gspca_dev;
208 u8 i2c_data;
209 int err;
210
211 PDEBUG(DBG_V4L2_CID, "Set exposure to %d",
212 val & 0xffff);
213
214 /* The 6 MSBs */
215 i2c_data = (val >> 10) & 0x3f;
216 err = ov9650_write_sensor(sd, OV9650_AECHM,
217 &i2c_data, 1);
218 if (err < 0)
219 goto out;
220
221 /* The 8 middle bits */
222 i2c_data = (val >> 2) & 0xff;
223 err = ov9650_write_sensor(sd, OV9650_AECH,
224 &i2c_data, 1);
225 if (err < 0)
226 goto out;
227
228 /* The 2 LSBs */
229 i2c_data = val & 0x03;
230 err = ov9650_write_sensor(sd, OV9650_COM1, &i2c_data, 1);
231
232out:
233 return (err < 0) ? err : 0;
234}
235
236int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
237{
238 int err;
239 u8 i2c_data;
240 struct sd *sd = (struct sd *) gspca_dev;
241
242 ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
243 *val = (i2c_data & 0x03) << 8;
244
245 err = ov9650_read_sensor(sd, OV9650_GAIN, &i2c_data, 1);
246 *val |= i2c_data;
247 PDEBUG(DBG_V4L2_CID, "Read gain %d", *val);
248 return (err < 0) ? err : 0;
249}
250
251int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
252{
253 int err;
254 u8 i2c_data;
255 struct sd *sd = (struct sd *) gspca_dev;
256
257 /* The 2 MSB */
258 /* Read the OV9650_VREF register first to avoid
259 corrupting the VREF high and low bits */
260 ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
261 /* Mask away all uninteresting bits */
262 i2c_data = ((val & 0x0300) >> 2) |
263 (i2c_data & 0x3F);
264 err = ov9650_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
265
266 /* The 8 LSBs */
267 i2c_data = val & 0xff;
268 err = ov9650_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
269 return (err < 0) ? err : 0;
270}
271
272int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
273{
274 int err;
275 u8 i2c_data;
276 struct sd *sd = (struct sd *) gspca_dev;
277
278 err = ov9650_read_sensor(sd, OV9650_RED, &i2c_data, 1);
279 *val = i2c_data;
280
281 PDEBUG(DBG_V4L2_CID, "Read red gain %d", *val);
282
283 return (err < 0) ? err : 0;
284}
285
286int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
287{
288 int err;
289 u8 i2c_data;
290 struct sd *sd = (struct sd *) gspca_dev;
291
292 PDEBUG(DBG_V4L2_CID, "Set red gain to %d",
293 val & 0xff);
294
295 i2c_data = val & 0xff;
296 err = ov9650_write_sensor(sd, OV9650_RED, &i2c_data, 1);
297
298 return (err < 0) ? err : 0;
299}
300
301int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
302{
303 int err;
304 u8 i2c_data;
305 struct sd *sd = (struct sd *) gspca_dev;
306
307 err = ov9650_read_sensor(sd, OV9650_BLUE, &i2c_data, 1);
308 *val = i2c_data;
309
310 PDEBUG(DBG_V4L2_CID, "Read blue gain %d", *val);
311
312 return (err < 0) ? err : 0;
313}
314
315int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
316{
317 int err;
318 u8 i2c_data;
319 struct sd *sd = (struct sd *) gspca_dev;
320
321 PDEBUG(DBG_V4L2_CID, "Set blue gain to %d",
322 val & 0xff);
323
324 i2c_data = val & 0xff;
325 err = ov9650_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
326
327 return (err < 0) ? err : 0;
328}
329
330int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
331{
332 int err;
333 u8 i2c_data;
334 struct sd *sd = (struct sd *) gspca_dev;
335
336 err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
337 if (dmi_check_system(ov9650_flip_dmi_table))
338 *val = ((i2c_data & OV9650_HFLIP) >> 5) ? 0 : 1;
339 else
340 *val = (i2c_data & OV9650_HFLIP) >> 5;
341 PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val);
342
343 return (err < 0) ? err : 0;
344}
345
346int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
347{
348 int err;
349 u8 i2c_data;
350 struct sd *sd = (struct sd *) gspca_dev;
351
352 PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d", val);
353 err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
354 if (err < 0)
355 goto out;
356
357 if (dmi_check_system(ov9650_flip_dmi_table))
358 i2c_data = ((i2c_data & 0xdf) |
359 (((val ? 0 : 1) & 0x01) << 5));
360 else
361 i2c_data = ((i2c_data & 0xdf) |
362 ((val & 0x01) << 5));
363
364 err = ov9650_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
365out:
366 return (err < 0) ? err : 0;
367}
368
369int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
370{
371 int err;
372 u8 i2c_data;
373 struct sd *sd = (struct sd *) gspca_dev;
374
375 err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
376 if (dmi_check_system(ov9650_flip_dmi_table))
377 *val = ((i2c_data & 0x10) >> 4) ? 0 : 1;
378 else
379 *val = (i2c_data & 0x10) >> 4;
380 PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val);
381
382 return (err < 0) ? err : 0;
383}
384
385int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
386{
387 int err;
388 u8 i2c_data;
389 struct sd *sd = (struct sd *) gspca_dev;
390
391 PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val);
392 err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
393 if (err < 0)
394 goto out;
395
396 if (dmi_check_system(ov9650_flip_dmi_table))
397 i2c_data = ((i2c_data & 0xef) |
398 (((val ? 0 : 1) & 0x01) << 4));
399 else
400 i2c_data = ((i2c_data & 0xef) |
401 ((val & 0x01) << 4));
402
403 err = ov9650_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
404out:
405 return (err < 0) ? err : 0;
406}
407
408int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
409{
410 int err;
411 u8 i2c_data;
412 struct sd *sd = (struct sd *) gspca_dev;
413
414 err = ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
415 if (err < 0)
416 goto out;
417 *val = (i2c_data & 0x03) << 8;
418
419 err = ov9650_read_sensor(sd, OV9650_GAIN, &i2c_data, 1);
420 *val |= i2c_data;
421 PDEBUG(DBG_V4L2_CID, "Read gain %d", *val);
422out:
423 return (err < 0) ? err : 0;
424}
425
426int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
427{
428 int err;
429 u8 i2c_data;
430 struct sd *sd = (struct sd *) gspca_dev;
431
432 PDEBUG(DBG_V4L2_CID, "Set gain to %d", val & 0x3ff);
433
434 /* Read the OV9650_VREF register first to avoid
435 corrupting the VREF high and low bits */
436 err = ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
437 if (err < 0)
438 goto out;
439
440 /* Mask away all uninteresting bits */
441 i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F);
442 err = ov9650_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
443 if (err < 0)
444 goto out;
445
446 /* The 8 LSBs */
447 i2c_data = val & 0xff;
448 err = ov9650_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
449
450out:
451 return (err < 0) ? err : 0;
452}
453
454int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val)
455{
456 int err;
457 u8 i2c_data;
458 struct sd *sd = (struct sd *) gspca_dev;
459
460 err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
461 *val = (i2c_data & OV9650_AWB_EN) >> 1;
462 PDEBUG(DBG_V4L2_CID, "Read auto white balance %d", *val);
463
464 return (err < 0) ? err : 0;
465}
466
467int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val)
468{
469 int err;
470 u8 i2c_data;
471 struct sd *sd = (struct sd *) gspca_dev;
472
473 PDEBUG(DBG_V4L2_CID, "Set auto white balance to %d", val);
474 err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
475 if (err < 0)
476 goto out;
477
478 i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
479 err = ov9650_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
480out:
481 return (err < 0) ? err : 0;
482}
483
484int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
485{
486 int err;
487 u8 i2c_data;
488 struct sd *sd = (struct sd *) gspca_dev;
489
490 err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
491 *val = (i2c_data & OV9650_AGC_EN) >> 2;
492 PDEBUG(DBG_V4L2_CID, "Read auto gain control %d", *val);
493
494 return (err < 0) ? err : 0;
495}
496
497int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
498{
499 int err;
500 u8 i2c_data;
501 struct sd *sd = (struct sd *) gspca_dev;
502
503 PDEBUG(DBG_V4L2_CID, "Set auto gain control to %d", val);
504 err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
505 if (err < 0)
506 goto out;
507
508 i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
509 err = ov9650_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
510out:
511 return (err < 0) ? err : 0;
512}
513
514void ov9650_dump_registers(struct sd *sd)
515{
516 int address;
517 info("Dumping the ov9650 register state");
518 for (address = 0; address < 0xa9; address++) {
519 u8 value;
520 ov9650_read_sensor(sd, address, &value, 1);
521 info("register 0x%x contains 0x%x",
522 address, value);
523 }
524
525 info("ov9650 register state dump complete");
526
527 info("Probing for which registers that are read/write");
528 for (address = 0; address < 0xff; address++) {
529 u8 old_value, ctrl_value;
530 u8 test_value[2] = {0xff, 0xff};
531
532 ov9650_read_sensor(sd, address, &old_value, 1);
533 ov9650_write_sensor(sd, address, test_value, 1);
534 ov9650_read_sensor(sd, address, &ctrl_value, 1);
535
536 if (ctrl_value == test_value[0])
537 info("register 0x%x is writeable", address);
538 else
539 info("register 0x%x is read only", address);
540
541 /* Restore original value */
542 ov9650_write_sensor(sd, address, &old_value, 1);
543 }
544}
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.h b/drivers/media/video/gspca/m5602/m5602_ov9650.h
new file mode 100644
index 000000000000..486ea337a8b4
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_ov9650.h
@@ -0,0 +1,501 @@
1/*
2 * Driver for the ov9650 sensor
3 *
4 * Copyright (C) 2008 Erik Andren
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#ifndef M5602_OV9650_H_
20#define M5602_OV9650_H_
21
22#include <linux/dmi.h>
23
24#include "m5602_sensor.h"
25
26/*****************************************************************************/
27
28#define OV9650_GAIN 0x00
29#define OV9650_BLUE 0x01
30#define OV9650_RED 0x02
31#define OV9650_VREF 0x03
32#define OV9650_COM1 0x04
33#define OV9650_BAVE 0x05
34#define OV9650_GEAVE 0x06
35#define OV9650_RSVD7 0x07
36#define OV9650_PID 0x0a
37#define OV9650_VER 0x0b
38#define OV9650_COM3 0x0c
39#define OV9650_COM5 0x0e
40#define OV9650_COM6 0x0f
41#define OV9650_AECH 0x10
42#define OV9650_CLKRC 0x11
43#define OV9650_COM7 0x12
44#define OV9650_COM8 0x13
45#define OV9650_COM9 0x14
46#define OV9650_COM10 0x15
47#define OV9650_RSVD16 0x16
48#define OV9650_HSTART 0x17
49#define OV9650_HSTOP 0x18
50#define OV9650_VSTRT 0x19
51#define OV9650_VSTOP 0x1a
52#define OV9650_PSHFT 0x1b
53#define OV9650_MVFP 0x1e
54#define OV9650_AEW 0x24
55#define OV9650_AEB 0x25
56#define OV9650_VPT 0x26
57#define OV9650_BBIAS 0x27
58#define OV9650_GbBIAS 0x28
59#define OV9650_Gr_COM 0x29
60#define OV9650_RBIAS 0x2c
61#define OV9650_HREF 0x32
62#define OV9650_CHLF 0x33
63#define OV9650_ARBLM 0x34
64#define OV9650_RSVD35 0x35
65#define OV9650_RSVD36 0x36
66#define OV9650_ADC 0x37
67#define OV9650_ACOM38 0x38
68#define OV9650_OFON 0x39
69#define OV9650_TSLB 0x3a
70#define OV9650_COM12 0x3c
71#define OV9650_COM13 0x3d
72#define OV9650_COM15 0x40
73#define OV9650_COM16 0x41
74#define OV9650_LCC1 0x62
75#define OV9650_LCC2 0x63
76#define OV9650_LCC3 0x64
77#define OV9650_LCC4 0x65
78#define OV9650_LCC5 0x66
79#define OV9650_HV 0x69
80#define OV9650_DBLV 0x6b
81#define OV9650_COM21 0x8b
82#define OV9650_COM22 0x8c
83#define OV9650_COM24 0x8e
84#define OV9650_DBLC1 0x8f
85#define OV9650_RSVD94 0x94
86#define OV9650_RSVD95 0x95
87#define OV9650_RSVD96 0x96
88#define OV9650_LCCFB 0x9d
89#define OV9650_LCCFR 0x9e
90#define OV9650_AECHM 0xa1
91#define OV9650_COM26 0xa5
92#define OV9650_ACOMA8 0xa8
93#define OV9650_ACOMA9 0xa9
94
95#define OV9650_REGISTER_RESET (1 << 7)
96#define OV9650_VGA_SELECT (1 << 6)
97#define OV9650_RGB_SELECT (1 << 2)
98#define OV9650_RAW_RGB_SELECT (1 << 0)
99
100#define OV9650_FAST_AGC_AEC (1 << 7)
101#define OV9650_AEC_UNLIM_STEP_SIZE (1 << 6)
102#define OV9650_BANDING (1 << 5)
103#define OV9650_AGC_EN (1 << 2)
104#define OV9650_AWB_EN (1 << 1)
105#define OV9650_AEC_EN (1 << 0)
106
107#define OV9650_VARIOPIXEL (1 << 2)
108#define OV9650_SYSTEM_CLK_SEL (1 << 7)
109#define OV9650_SLAM_MODE (1 << 4)
110
111#define OV9650_VFLIP (1 << 4)
112#define OV9650_HFLIP (1 << 5)
113
114#define GAIN_DEFAULT 0x14
115#define RED_GAIN_DEFAULT 0x70
116#define BLUE_GAIN_DEFAULT 0x20
117#define EXPOSURE_DEFAULT 0x5003
118
119/*****************************************************************************/
120
121/* Kernel module parameters */
122extern int force_sensor;
123extern int dump_sensor;
124extern unsigned int m5602_debug;
125
126int ov9650_probe(struct sd *sd);
127int ov9650_init(struct sd *sd);
128int ov9650_power_down(struct sd *sd);
129
130int ov9650_read_sensor(struct sd *sd, const u8 address,
131 u8 *i2c_data, const u8 len);
132int ov9650_write_sensor(struct sd *sd, const u8 address,
133 u8 *i2c_data, const u8 len);
134
135void ov9650_dump_registers(struct sd *sd);
136
137int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
138int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
139int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
140int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val);
141int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
142int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
143int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
144int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
145int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
146int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
147int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
148int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
149int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
150int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
151int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val);
152int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val);
153int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
154int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
155
156static struct m5602_sensor ov9650 = {
157 .name = "OV9650",
158 .i2c_slave_id = 0x60,
159 .probe = ov9650_probe,
160 .init = ov9650_init,
161 .power_down = ov9650_power_down,
162 .read_sensor = ov9650_read_sensor,
163 .write_sensor = ov9650_write_sensor,
164
165 .nctrls = 8,
166 .ctrls = {
167 {
168 {
169 .id = V4L2_CID_EXPOSURE,
170 .type = V4L2_CTRL_TYPE_INTEGER,
171 .name = "exposure",
172 .minimum = 0x00,
173 .maximum = 0xffff,
174 .step = 0x1,
175 .default_value = EXPOSURE_DEFAULT,
176 .flags = V4L2_CTRL_FLAG_SLIDER
177 },
178 .set = ov9650_set_exposure,
179 .get = ov9650_get_exposure
180 }, {
181 {
182 .id = V4L2_CID_GAIN,
183 .type = V4L2_CTRL_TYPE_INTEGER,
184 .name = "gain",
185 .minimum = 0x00,
186 .maximum = 0x3ff,
187 .step = 0x1,
188 .default_value = GAIN_DEFAULT,
189 .flags = V4L2_CTRL_FLAG_SLIDER
190 },
191 .set = ov9650_set_gain,
192 .get = ov9650_get_gain
193 }, {
194 {
195 .type = V4L2_CTRL_TYPE_INTEGER,
196 .name = "red balance",
197 .minimum = 0x00,
198 .maximum = 0xff,
199 .step = 0x1,
200 .default_value = RED_GAIN_DEFAULT,
201 .flags = V4L2_CTRL_FLAG_SLIDER
202 },
203 .set = ov9650_set_red_balance,
204 .get = ov9650_get_red_balance
205 }, {
206 {
207 .type = V4L2_CTRL_TYPE_INTEGER,
208 .name = "blue balance",
209 .minimum = 0x00,
210 .maximum = 0xff,
211 .step = 0x1,
212 .default_value = BLUE_GAIN_DEFAULT,
213 .flags = V4L2_CTRL_FLAG_SLIDER
214 },
215 .set = ov9650_set_blue_balance,
216 .get = ov9650_get_blue_balance
217 }, {
218 {
219 .id = V4L2_CID_HFLIP,
220 .type = V4L2_CTRL_TYPE_BOOLEAN,
221 .name = "horizontal flip",
222 .minimum = 0,
223 .maximum = 1,
224 .step = 1,
225 .default_value = 0
226 },
227 .set = ov9650_set_hflip,
228 .get = ov9650_get_hflip
229 }, {
230 {
231 .id = V4L2_CID_VFLIP,
232 .type = V4L2_CTRL_TYPE_BOOLEAN,
233 .name = "vertical flip",
234 .minimum = 0,
235 .maximum = 1,
236 .step = 1,
237 .default_value = 0
238 },
239 .set = ov9650_set_vflip,
240 .get = ov9650_get_vflip
241 }, {
242 {
243 .id = V4L2_CID_AUTO_WHITE_BALANCE,
244 .type = V4L2_CTRL_TYPE_BOOLEAN,
245 .name = "auto white balance",
246 .minimum = 0,
247 .maximum = 1,
248 .step = 1,
249 .default_value = 0
250 },
251 .set = ov9650_set_auto_white_balance,
252 .get = ov9650_get_auto_white_balance
253 }, {
254 {
255 .id = V4L2_CID_AUTOGAIN,
256 .type = V4L2_CTRL_TYPE_BOOLEAN,
257 .name = "auto gain control",
258 .minimum = 0,
259 .maximum = 1,
260 .step = 1,
261 .default_value = 0
262 },
263 .set = ov9650_set_auto_gain,
264 .get = ov9650_get_auto_gain
265 }
266 },
267
268 .nmodes = 1,
269 .modes = {
270 {
271 M5602_DEFAULT_FRAME_WIDTH,
272 M5602_DEFAULT_FRAME_HEIGHT,
273 V4L2_PIX_FMT_SBGGR8,
274 V4L2_FIELD_NONE,
275 .sizeimage =
276 M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT,
277 .bytesperline = M5602_DEFAULT_FRAME_WIDTH,
278 .colorspace = V4L2_COLORSPACE_SRGB,
279 .priv = 1
280 }
281 }
282};
283
284static const unsigned char preinit_ov9650[][3] =
285{
286 /* [INITCAM] */
287 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
288 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
289 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
290 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
291 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
292 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
293
294 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08},
295 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
296 {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
297 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
298 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
299 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
300 {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
301 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a},
302 /* Reset chip */
303 {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
304 /* Enable double clock */
305 {SENSOR, OV9650_CLKRC, 0x80},
306 /* Do something out of spec with the power */
307 {SENSOR, OV9650_OFON, 0x40}
308};
309
310static const unsigned char init_ov9650[][3] =
311{
312 /* [INITCAM] */
313 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
314 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
315 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
316 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
317 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
318 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
319
320 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08},
321 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
322 {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
323 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
324 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
325 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
326 {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
327 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a},
328 /* Reset chip */
329 {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
330 /* Enable double clock */
331 {SENSOR, OV9650_CLKRC, 0x80},
332 /* Do something out of spec with the power */
333 {SENSOR, OV9650_OFON, 0x40},
334
335 /* Set QQVGA */
336 {SENSOR, OV9650_COM1, 0x20},
337 /* Set fast AGC/AEC algorithm with unlimited step size */
338 {SENSOR, OV9650_COM8, OV9650_FAST_AGC_AEC |
339 OV9650_AEC_UNLIM_STEP_SIZE |
340 OV9650_AWB_EN | OV9650_AGC_EN},
341
342 {SENSOR, OV9650_CHLF, 0x10},
343 {SENSOR, OV9650_ARBLM, 0xbf},
344 {SENSOR, OV9650_ACOM38, 0x81},
345 /* Turn off color matrix coefficient double option */
346 {SENSOR, OV9650_COM16, 0x00},
347 /* Enable color matrix for RGB/YUV, Delay Y channel,
348 set output Y/UV delay to 1 */
349 {SENSOR, OV9650_COM13, 0x19},
350 /* Enable digital BLC, Set output mode to U Y V Y */
351 {SENSOR, OV9650_TSLB, 0x0c},
352 /* Limit the AGC/AEC stable upper region */
353 {SENSOR, OV9650_COM24, 0x00},
354 /* Enable HREF and some out of spec things */
355 {SENSOR, OV9650_COM12, 0x73},
356 /* Set all DBLC offset signs to positive and
357 do some out of spec stuff */
358 {SENSOR, OV9650_DBLC1, 0xdf},
359 {SENSOR, OV9650_COM21, 0x06},
360 {SENSOR, OV9650_RSVD35, 0x91},
361 /* Necessary, no camera stream without it */
362 {SENSOR, OV9650_RSVD16, 0x06},
363 {SENSOR, OV9650_RSVD94, 0x99},
364 {SENSOR, OV9650_RSVD95, 0x99},
365 {SENSOR, OV9650_RSVD96, 0x04},
366 /* Enable full range output */
367 {SENSOR, OV9650_COM15, 0x0},
368 /* Enable HREF at optical black, enable ADBLC bias,
369 enable ADBLC, reset timings at format change */
370 {SENSOR, OV9650_COM6, 0x4b},
371 /* Subtract 32 from the B channel bias */
372 {SENSOR, OV9650_BBIAS, 0xa0},
373 /* Subtract 32 from the Gb channel bias */
374 {SENSOR, OV9650_GbBIAS, 0xa0},
375 /* Do not bypass the analog BLC and to some out of spec stuff */
376 {SENSOR, OV9650_Gr_COM, 0x00},
377 /* Subtract 32 from the R channel bias */
378 {SENSOR, OV9650_RBIAS, 0xa0},
379 /* Subtract 32 from the R channel bias */
380 {SENSOR, OV9650_RBIAS, 0x0},
381 {SENSOR, OV9650_COM26, 0x80},
382 {SENSOR, OV9650_ACOMA9, 0x98},
383 /* Set the AGC/AEC stable region upper limit */
384 {SENSOR, OV9650_AEW, 0x68},
385 /* Set the AGC/AEC stable region lower limit */
386 {SENSOR, OV9650_AEB, 0x5c},
387 /* Set the high and low limit nibbles to 3 */
388 {SENSOR, OV9650_VPT, 0xc3},
389 /* Set the Automatic Gain Ceiling (AGC) to 128x,
390 drop VSYNC at frame drop,
391 limit exposure timing,
392 drop frame when the AEC step is larger than the exposure gap */
393 {SENSOR, OV9650_COM9, 0x6e},
394 /* Set VSYNC negative, Set RESET to SLHS (slave mode horizontal sync)
395 and set PWDN to SLVS (slave mode vertical sync) */
396 {SENSOR, OV9650_COM10, 0x42},
397 /* Set horizontal column start high to default value */
398 {SENSOR, OV9650_HSTART, 0x1a},
399 /* Set horizontal column end */
400 {SENSOR, OV9650_HSTOP, 0xbf},
401 /* Complementing register to the two writes above */
402 {SENSOR, OV9650_HREF, 0xb2},
403 /* Set vertical row start high bits */
404 {SENSOR, OV9650_VSTRT, 0x02},
405 /* Set vertical row end low bits */
406 {SENSOR, OV9650_VSTOP, 0x7e},
407 /* Set complementing vertical frame control */
408 {SENSOR, OV9650_VREF, 0x10},
409 /* Set raw RGB output format with VGA resolution */
410 {SENSOR, OV9650_COM7, OV9650_VGA_SELECT |
411 OV9650_RGB_SELECT |
412 OV9650_RAW_RGB_SELECT},
413 {SENSOR, OV9650_ADC, 0x04},
414 {SENSOR, OV9650_HV, 0x40},
415 /* Enable denoise, and white-pixel erase */
416 {SENSOR, OV9650_COM22, 0x23},
417
418 /* Set the high bits of the exposure value */
419 {SENSOR, OV9650_AECH, ((EXPOSURE_DEFAULT & 0xff00) >> 8)},
420
421 /* Set the low bits of the exposure value */
422 {SENSOR, OV9650_COM1, (EXPOSURE_DEFAULT & 0xff)},
423 {SENSOR, OV9650_GAIN, GAIN_DEFAULT},
424 {SENSOR, OV9650_BLUE, BLUE_GAIN_DEFAULT},
425 {SENSOR, OV9650_RED, RED_GAIN_DEFAULT},
426
427 {SENSOR, OV9650_COM3, OV9650_VARIOPIXEL},
428 {SENSOR, OV9650_COM5, OV9650_SYSTEM_CLK_SEL},
429
430 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82},
431 {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00},
432 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
433 {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00},
434 {BRIDGE, M5602_XB_SIG_INI, 0x01},
435 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
436 {BRIDGE, M5602_XB_VSYNC_PARA, 0x09},
437 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
438 {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
439 {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0},
440 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
441 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
442 {BRIDGE, M5602_XB_HSYNC_PARA, 0x5e},
443 {BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
444 {BRIDGE, M5602_XB_HSYNC_PARA, 0xde}
445};
446
447static const unsigned char power_down_ov9650[][3] =
448{
449 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
450 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
451 {SENSOR, OV9650_COM7, 0x80},
452 {SENSOR, OV9650_OFON, 0xf4},
453 {SENSOR, OV9650_MVFP, 0x80},
454 {SENSOR, OV9650_DBLV, 0x3f},
455 {SENSOR, OV9650_RSVD36, 0x49},
456 {SENSOR, OV9650_COM7, 0x05},
457
458 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
459 {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
460 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
461 {BRIDGE, M5602_XB_GPIO_EN_L, 0x06},
462 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
463 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
464 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}
465};
466
467/* Vertically and horizontally flips the image if matched, needed for machines
468 where the sensor is mounted upside down */
469static const struct dmi_system_id ov9650_flip_dmi_table[] = {
470 {
471 .ident = "ASUS A6VC",
472 .matches = {
473 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
474 DMI_MATCH(DMI_PRODUCT_NAME, "A6VC")
475 }
476 },
477 {
478 .ident = "ASUS A6VM",
479 .matches = {
480 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
481 DMI_MATCH(DMI_PRODUCT_NAME, "A6VM")
482 }
483 },
484 {
485 .ident = "ASUS A6JC",
486 .matches = {
487 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
488 DMI_MATCH(DMI_PRODUCT_NAME, "A6JC")
489 }
490 },
491 {
492 .ident = "ASUS A6Kt",
493 .matches = {
494 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
495 DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt")
496 }
497 },
498 { }
499};
500
501#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.c b/drivers/media/video/gspca/m5602/m5602_po1030.c
new file mode 100644
index 000000000000..14a8f929dd18
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_po1030.c
@@ -0,0 +1,334 @@
1/*
2 * Driver for the po1030 sensor
3 *
4 * Copyright (c) 2008 Erik Andren
5 * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#include "m5602_po1030.h"
20
21int po1030_probe(struct sd *sd)
22{
23 u8 prod_id = 0, ver_id = 0, i;
24
25 if (force_sensor) {
26 if (force_sensor == PO1030_SENSOR) {
27 info("Forcing a %s sensor", po1030.name);
28 goto sensor_found;
29 }
30 /* If we want to force another sensor, don't try to probe this
31 * one */
32 return -ENODEV;
33 }
34
35 info("Probing for a po1030 sensor");
36
37 /* Run the pre-init to actually probe the unit */
38 for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) {
39 u8 data = preinit_po1030[i][2];
40 if (preinit_po1030[i][0] == SENSOR)
41 po1030_write_sensor(sd,
42 preinit_po1030[i][1], &data, 1);
43 else
44 m5602_write_bridge(sd, preinit_po1030[i][1], data);
45 }
46
47 if (po1030_read_sensor(sd, 0x3, &prod_id, 1))
48 return -ENODEV;
49
50 if (po1030_read_sensor(sd, 0x4, &ver_id, 1))
51 return -ENODEV;
52
53 if ((prod_id == 0x02) && (ver_id == 0xef)) {
54 info("Detected a po1030 sensor");
55 goto sensor_found;
56 }
57 return -ENODEV;
58
59sensor_found:
60 sd->gspca_dev.cam.cam_mode = po1030.modes;
61 sd->gspca_dev.cam.nmodes = po1030.nmodes;
62 return 0;
63}
64
65int po1030_read_sensor(struct sd *sd, const u8 address,
66 u8 *i2c_data, const u8 len)
67{
68 int err, i;
69
70 do {
71 err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
72 } while ((*i2c_data & I2C_BUSY) && !err);
73
74 m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
75 sd->sensor->i2c_slave_id);
76 m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
77 m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len);
78 m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08);
79
80 for (i = 0; i < len; i++) {
81 err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
82
83 PDEBUG(DBG_TRACE, "Reading sensor register "
84 "0x%x containing 0x%x ", address, *i2c_data);
85 }
86 return (err < 0) ? err : 0;
87}
88
89int po1030_write_sensor(struct sd *sd, const u8 address,
90 u8 *i2c_data, const u8 len)
91{
92 int err, i;
93 u8 *p;
94 struct usb_device *udev = sd->gspca_dev.dev;
95 __u8 *buf = sd->gspca_dev.usb_buf;
96
97 /* The po1030 only supports one byte writes */
98 if (len > 1 || !len)
99 return -EINVAL;
100
101 memcpy(buf, sensor_urb_skeleton, sizeof(sensor_urb_skeleton));
102
103 buf[11] = sd->sensor->i2c_slave_id;
104 buf[15] = address;
105
106 p = buf + 16;
107
108 /* Copy a four byte write sequence for each byte to be written to */
109 for (i = 0; i < len; i++) {
110 memcpy(p, sensor_urb_skeleton + 16, 4);
111 p[3] = i2c_data[i];
112 p += 4;
113 PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x",
114 address, i2c_data[i]);
115 }
116
117 /* Copy the footer */
118 memcpy(p, sensor_urb_skeleton + 20, 4);
119
120 /* Set the total length */
121 p[3] = 0x10 + len;
122
123 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
124 0x04, 0x40, 0x19,
125 0x0000, buf,
126 20 + len * 4, M5602_URB_MSG_TIMEOUT);
127
128 return (err < 0) ? err : 0;
129}
130
131int po1030_init(struct sd *sd)
132{
133 int i, err = 0;
134
135 /* Init the sensor */
136 for (i = 0; i < ARRAY_SIZE(init_po1030); i++) {
137 u8 data[2] = {0x00, 0x00};
138
139 switch (init_po1030[i][0]) {
140 case BRIDGE:
141 err = m5602_write_bridge(sd,
142 init_po1030[i][1],
143 init_po1030[i][2]);
144 break;
145
146 case SENSOR:
147 data[0] = init_po1030[i][2];
148 err = po1030_write_sensor(sd,
149 init_po1030[i][1], data, 1);
150 break;
151
152 case SENSOR_LONG:
153 data[0] = init_po1030[i][2];
154 data[1] = init_po1030[i][3];
155 err = po1030_write_sensor(sd,
156 init_po1030[i][1], data, 2);
157 break;
158 default:
159 info("Invalid stream command, exiting init");
160 return -EINVAL;
161 }
162 }
163
164 if (dump_sensor)
165 po1030_dump_registers(sd);
166
167 return (err < 0) ? err : 0;
168}
169
170int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
171{
172 struct sd *sd = (struct sd *) gspca_dev;
173 u8 i2c_data;
174 int err;
175
176 err = po1030_read_sensor(sd, PO1030_REG_INTEGLINES_H,
177 &i2c_data, 1);
178 if (err < 0)
179 goto out;
180 *val = (i2c_data << 8);
181
182 err = po1030_read_sensor(sd, PO1030_REG_INTEGLINES_M,
183 &i2c_data, 1);
184 *val |= i2c_data;
185
186 PDEBUG(DBG_V4L2_CID, "Exposure read as %d", *val);
187out:
188 return (err < 0) ? err : 0;
189}
190
191int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
192{
193 struct sd *sd = (struct sd *) gspca_dev;
194 u8 i2c_data;
195 int err;
196
197 PDEBUG(DBG_V4L2, "Set exposure to %d", val & 0xffff);
198
199 i2c_data = ((val & 0xff00) >> 8);
200 PDEBUG(DBG_V4L2, "Set exposure to high byte to 0x%x",
201 i2c_data);
202
203 err = po1030_write_sensor(sd, PO1030_REG_INTEGLINES_H,
204 &i2c_data, 1);
205 if (err < 0)
206 goto out;
207
208 i2c_data = (val & 0xff);
209 PDEBUG(DBG_V4L2, "Set exposure to low byte to 0x%x",
210 i2c_data);
211 err = po1030_write_sensor(sd, PO1030_REG_INTEGLINES_M,
212 &i2c_data, 1);
213
214out:
215 return (err < 0) ? err : 0;
216}
217
218int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
219{
220 struct sd *sd = (struct sd *) gspca_dev;
221 u8 i2c_data;
222 int err;
223
224 err = po1030_read_sensor(sd, PO1030_REG_GLOBALGAIN,
225 &i2c_data, 1);
226 *val = i2c_data;
227 PDEBUG(DBG_V4L2_CID, "Read global gain %d", *val);
228
229 return (err < 0) ? err : 0;
230}
231
232int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
233{
234 struct sd *sd = (struct sd *) gspca_dev;
235 u8 i2c_data;
236 int err;
237
238 i2c_data = val & 0xff;
239 PDEBUG(DBG_V4L2, "Set global gain to %d", i2c_data);
240 err = po1030_write_sensor(sd, PO1030_REG_GLOBALGAIN,
241 &i2c_data, 1);
242 return (err < 0) ? err : 0;
243}
244
245int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
246{
247 struct sd *sd = (struct sd *) gspca_dev;
248 u8 i2c_data;
249 int err;
250
251 err = po1030_read_sensor(sd, PO1030_REG_RED_GAIN,
252 &i2c_data, 1);
253 *val = i2c_data;
254 PDEBUG(DBG_V4L2_CID, "Read red gain %d", *val);
255 return (err < 0) ? err : 0;
256}
257
258int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
259{
260 struct sd *sd = (struct sd *) gspca_dev;
261 u8 i2c_data;
262 int err;
263
264 i2c_data = val & 0xff;
265 PDEBUG(DBG_V4L2, "Set red gain to %d", i2c_data);
266 err = po1030_write_sensor(sd, PO1030_REG_RED_GAIN,
267 &i2c_data, 1);
268 return (err < 0) ? err : 0;
269}
270
271int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
272{
273 struct sd *sd = (struct sd *) gspca_dev;
274 u8 i2c_data;
275 int err;
276
277 err = po1030_read_sensor(sd, PO1030_REG_BLUE_GAIN,
278 &i2c_data, 1);
279 *val = i2c_data;
280 PDEBUG(DBG_V4L2_CID, "Read blue gain %d", *val);
281
282 return (err < 0) ? err : 0;
283}
284
285int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
286{
287 struct sd *sd = (struct sd *) gspca_dev;
288 u8 i2c_data;
289 int err;
290 i2c_data = val & 0xff;
291 PDEBUG(DBG_V4L2, "Set blue gain to %d", i2c_data);
292 err = po1030_write_sensor(sd, PO1030_REG_BLUE_GAIN,
293 &i2c_data, 1);
294
295 return (err < 0) ? err : 0;
296}
297
298int po1030_power_down(struct sd *sd)
299{
300 return 0;
301}
302
303void po1030_dump_registers(struct sd *sd)
304{
305 int address;
306 u8 value = 0;
307
308 info("Dumping the po1030 sensor core registers");
309 for (address = 0; address < 0x7f; address++) {
310 po1030_read_sensor(sd, address, &value, 1);
311 info("register 0x%x contains 0x%x",
312 address, value);
313 }
314
315 info("po1030 register state dump complete");
316
317 info("Probing for which registers that are read/write");
318 for (address = 0; address < 0xff; address++) {
319 u8 old_value, ctrl_value;
320 u8 test_value[2] = {0xff, 0xff};
321
322 po1030_read_sensor(sd, address, &old_value, 1);
323 po1030_write_sensor(sd, address, test_value, 1);
324 po1030_read_sensor(sd, address, &ctrl_value, 1);
325
326 if (ctrl_value == test_value[0])
327 info("register 0x%x is writeable", address);
328 else
329 info("register 0x%x is read only", address);
330
331 /* Restore original value */
332 po1030_write_sensor(sd, address, &old_value, 1);
333 }
334}
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.h b/drivers/media/video/gspca/m5602/m5602_po1030.h
new file mode 100644
index 000000000000..68f34c97bf44
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_po1030.h
@@ -0,0 +1,478 @@
1/*
2 * Driver for the po1030 sensor.
3 * This is probably a pixel plus sensor but we haven't identified it yet
4 *
5 * Copyright (c) 2008 Erik Andren
6 * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
7 * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
8 *
9 * Portions of code to USB interface and ALi driver software,
10 * Copyright (c) 2006 Willem Duinker
11 * v4l2 interface modeled after the V4L2 driver
12 * for SN9C10x PC Camera Controllers
13 *
14 * Register defines taken from Pascal Stangs Proxycon Armlib
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License as
18 * published by the Free Software Foundation, version 2.
19 *
20 */
21
22#ifndef M5602_PO1030_H_
23#define M5602_PO1030_H_
24
25#include "m5602_sensor.h"
26
27/*****************************************************************************/
28
29#define PO1030_REG_DEVID_H 0x00
30#define PO1030_REG_DEVID_L 0x01
31#define PO1030_REG_FRAMEWIDTH_H 0x04
32#define PO1030_REG_FRAMEWIDTH_L 0x05
33#define PO1030_REG_FRAMEHEIGHT_H 0x06
34#define PO1030_REG_FRAMEHEIGHT_L 0x07
35#define PO1030_REG_WINDOWX_H 0x08
36#define PO1030_REG_WINDOWX_L 0x09
37#define PO1030_REG_WINDOWY_H 0x0a
38#define PO1030_REG_WINDOWY_L 0x0b
39#define PO1030_REG_WINDOWWIDTH_H 0x0c
40#define PO1030_REG_WINDOWWIDTH_L 0x0d
41#define PO1030_REG_WINDOWHEIGHT_H 0x0e
42#define PO1030_REG_WINDOWHEIGHT_L 0x0f
43
44#define PO1030_REG_GLOBALIBIAS 0x12
45#define PO1030_REG_PIXELIBIAS 0x13
46
47#define PO1030_REG_GLOBALGAIN 0x15
48#define PO1030_REG_RED_GAIN 0x16
49#define PO1030_REG_GREEN_1_GAIN 0x17
50#define PO1030_REG_BLUE_GAIN 0x18
51#define PO1030_REG_GREEN_2_GAIN 0x19
52
53#define PO1030_REG_INTEGLINES_H 0x1a
54#define PO1030_REG_INTEGLINES_M 0x1b
55#define PO1030_REG_INTEGLINES_L 0x1c
56
57#define PO1030_REG_CONTROL1 0x1d
58#define PO1030_REG_CONTROL2 0x1e
59#define PO1030_REG_CONTROL3 0x1f
60#define PO1030_REG_CONTROL4 0x20
61
62#define PO1030_REG_PERIOD50_H 0x23
63#define PO1030_REG_PERIOD50_L 0x24
64#define PO1030_REG_PERIOD60_H 0x25
65#define PO1030_REG_PERIOD60_L 0x26
66#define PO1030_REG_REGCLK167 0x27
67#define PO1030_REG_DELTA50 0x28
68#define PO1030_REG_DELTA60 0x29
69
70#define PO1030_REG_ADCOFFSET 0x2c
71
72/* Gamma Correction Coeffs */
73#define PO1030_REG_GC0 0x2d
74#define PO1030_REG_GC1 0x2e
75#define PO1030_REG_GC2 0x2f
76#define PO1030_REG_GC3 0x30
77#define PO1030_REG_GC4 0x31
78#define PO1030_REG_GC5 0x32
79#define PO1030_REG_GC6 0x33
80#define PO1030_REG_GC7 0x34
81
82/* Color Transform Matrix */
83#define PO1030_REG_CT0 0x35
84#define PO1030_REG_CT1 0x36
85#define PO1030_REG_CT2 0x37
86#define PO1030_REG_CT3 0x38
87#define PO1030_REG_CT4 0x39
88#define PO1030_REG_CT5 0x3a
89#define PO1030_REG_CT6 0x3b
90#define PO1030_REG_CT7 0x3c
91#define PO1030_REG_CT8 0x3d
92
93#define PO1030_REG_AUTOCTRL1 0x3e
94#define PO1030_REG_AUTOCTRL2 0x3f
95
96#define PO1030_REG_YTARGET 0x40
97#define PO1030_REG_GLOBALGAINMIN 0x41
98#define PO1030_REG_GLOBALGAINMAX 0x42
99
100/* Output format control */
101#define PO1030_REG_OUTFORMCTRL1 0x5a
102#define PO1030_REG_OUTFORMCTRL2 0x5b
103#define PO1030_REG_OUTFORMCTRL3 0x5c
104#define PO1030_REG_OUTFORMCTRL4 0x5d
105#define PO1030_REG_OUTFORMCTRL5 0x5e
106
107/* Imaging coefficients */
108#define PO1030_REG_YBRIGHT 0x73
109#define PO1030_REG_YCONTRAST 0x74
110#define PO1030_REG_YSATURATION 0x75
111
112/*****************************************************************************/
113
114#define PO1030_GLOBAL_GAIN_DEFAULT 0x12
115#define PO1030_EXPOSURE_DEFAULT 0xf0ff
116#define PO1030_BLUE_GAIN_DEFAULT 0x40
117#define PO1030_RED_GAIN_DEFAULT 0x40
118
119/*****************************************************************************/
120
121/* Kernel module parameters */
122extern int force_sensor;
123extern int dump_sensor;
124extern unsigned int m5602_debug;
125
126int po1030_probe(struct sd *sd);
127int po1030_init(struct sd *sd);
128int po1030_power_down(struct sd *sd);
129
130void po1030_dump_registers(struct sd *sd);
131
132int po1030_read_sensor(struct sd *sd, const u8 address,
133 u8 *i2c_data, const u8 len);
134int po1030_write_sensor(struct sd *sd, const u8 address,
135 u8 *i2c_data, const u8 len);
136
137int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
138int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
139int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
140int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val);
141int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
142int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
143int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
144int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
145
146static struct m5602_sensor po1030 = {
147 .name = "PO1030",
148
149 .i2c_slave_id = 0xdc,
150
151 .probe = po1030_probe,
152 .init = po1030_init,
153 .power_down = po1030_power_down,
154
155 .nctrls = 4,
156 .ctrls = {
157 {
158 {
159 .id = V4L2_CID_GAIN,
160 .type = V4L2_CTRL_TYPE_INTEGER,
161 .name = "gain",
162 .minimum = 0x00,
163 .maximum = 0xff,
164 .step = 0x1,
165 .default_value = PO1030_GLOBAL_GAIN_DEFAULT,
166 .flags = V4L2_CTRL_FLAG_SLIDER
167 },
168 .set = po1030_set_gain,
169 .get = po1030_get_gain
170 }, {
171 {
172 .id = V4L2_CID_EXPOSURE,
173 .type = V4L2_CTRL_TYPE_INTEGER,
174 .name = "exposure",
175 .minimum = 0x00,
176 .maximum = 0xffff,
177 .step = 0x1,
178 .default_value = PO1030_EXPOSURE_DEFAULT,
179 .flags = V4L2_CTRL_FLAG_SLIDER
180 },
181 .set = po1030_set_exposure,
182 .get = po1030_get_exposure
183 }, {
184 {
185 .id = V4L2_CID_RED_BALANCE,
186 .type = V4L2_CTRL_TYPE_INTEGER,
187 .name = "red balance",
188 .minimum = 0x00,
189 .maximum = 0xff,
190 .step = 0x1,
191 .default_value = PO1030_RED_GAIN_DEFAULT,
192 .flags = V4L2_CTRL_FLAG_SLIDER
193 },
194 .set = po1030_set_red_balance,
195 .get = po1030_get_red_balance
196 }, {
197 {
198 .id = V4L2_CID_BLUE_BALANCE,
199 .type = V4L2_CTRL_TYPE_INTEGER,
200 .name = "blue balance",
201 .minimum = 0x00,
202 .maximum = 0xff,
203 .step = 0x1,
204 .default_value = PO1030_BLUE_GAIN_DEFAULT,
205 .flags = V4L2_CTRL_FLAG_SLIDER
206 },
207 .set = po1030_set_blue_balance,
208 .get = po1030_get_blue_balance
209 }
210 },
211 .nmodes = 1,
212 .modes = {
213 {
214 M5602_DEFAULT_FRAME_WIDTH,
215 M5602_DEFAULT_FRAME_HEIGHT,
216 V4L2_PIX_FMT_SBGGR8,
217 V4L2_FIELD_NONE,
218 .sizeimage =
219 M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT,
220 .bytesperline = M5602_DEFAULT_FRAME_WIDTH,
221 .colorspace = V4L2_COLORSPACE_SRGB,
222 .priv = 1
223 }
224 }
225};
226
227static const unsigned char preinit_po1030[][3] =
228{
229 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
230 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
231 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
232 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
233 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
234 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
235 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
236 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
237 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
238
239 {SENSOR, PO1030_REG_AUTOCTRL2, 0x24},
240
241 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
242 {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
243 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
244 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
245 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
246 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
247 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
248 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06},
249 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
250 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
251 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
252 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81},
253 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
254 {BRIDGE, M5602_XB_SIG_INI, 0x01},
255 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
256 {BRIDGE, M5602_XB_VSYNC_PARA, 0x02},
257 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
258 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
259 {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
260 {BRIDGE, M5602_XB_VSYNC_PARA, 0xec},
261 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
262 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
263 {BRIDGE, M5602_XB_SIG_INI, 0x00},
264 {BRIDGE, M5602_XB_SIG_INI, 0x02},
265 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
266 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
267 {BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
268 {BRIDGE, M5602_XB_HSYNC_PARA, 0x87},
269 {BRIDGE, M5602_XB_SIG_INI, 0x00},
270
271 {SENSOR, PO1030_REG_AUTOCTRL2, 0x24},
272
273 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
274 {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
275 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
276 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
277 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
278 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
279 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
280 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
281 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
282 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
283 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
284 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
285 {BRIDGE, M5602_XB_GPIO_DAT, 0x00}
286};
287
288static const unsigned char init_po1030[][4] =
289{
290 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
291 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
292 /*sequence 1*/
293 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
294 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
295 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
296 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
297
298 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
299 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
300 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
301 /*end of sequence 1*/
302
303 /*sequence 2 (same as stop sequence)*/
304 {SENSOR, PO1030_REG_AUTOCTRL2, 0x24},
305 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
306 {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
307 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
308 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
309 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
310
311 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
312 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
313 /*end of sequence 2*/
314
315 /*sequence 5*/
316 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06},
317 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
318 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
319 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
320 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81},
321 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
322 {BRIDGE, M5602_XB_SIG_INI, 0x01},
323 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
324 {BRIDGE, M5602_XB_VSYNC_PARA, 0x02},
325 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
326 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
327 {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
328 {BRIDGE, M5602_XB_VSYNC_PARA, 0xec},
329 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
330 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
331 {BRIDGE, M5602_XB_SIG_INI, 0x00},
332 {BRIDGE, M5602_XB_SIG_INI, 0x02},
333 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
334 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
335 {BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
336 {BRIDGE, M5602_XB_HSYNC_PARA, 0x87},
337 {BRIDGE, M5602_XB_SIG_INI, 0x00},
338 /*end of sequence 5*/
339
340 /*sequence 2 stop */
341 {SENSOR, PO1030_REG_AUTOCTRL2, 0x24},
342
343 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
344 {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
345 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
346 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
347 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
348 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
349 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
350 /*end of sequence 2 stop */
351
352/* ---------------------------------
353 * end of init - begin of start
354 * --------------------------------- */
355
356 /*sequence 3*/
357 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
358 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
359 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
360 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
361 /*end of sequence 3*/
362 /*sequence 4*/
363 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
364 {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
365 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
366 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
367
368 {SENSOR, PO1030_REG_AUTOCTRL2, 0x04},
369
370 /* Set the width to 751 */
371 {SENSOR, PO1030_REG_FRAMEWIDTH_H, 0x02},
372 {SENSOR, PO1030_REG_FRAMEWIDTH_L, 0xef},
373
374 /* Set the height to 540 */
375 {SENSOR, PO1030_REG_FRAMEHEIGHT_H, 0x02},
376 {SENSOR, PO1030_REG_FRAMEHEIGHT_L, 0x1c},
377
378 /* Set the x window to 1 */
379 {SENSOR, PO1030_REG_WINDOWX_H, 0x00},
380 {SENSOR, PO1030_REG_WINDOWX_L, 0x01},
381
382 /* Set the y window to 1 */
383 {SENSOR, PO1030_REG_WINDOWY_H, 0x00},
384 {SENSOR, PO1030_REG_WINDOWX_L, 0x01},
385
386 {SENSOR, PO1030_REG_WINDOWWIDTH_H, 0x02},
387 {SENSOR, PO1030_REG_WINDOWWIDTH_L, 0x87},
388 {SENSOR, PO1030_REG_WINDOWHEIGHT_H, 0x01},
389 {SENSOR, PO1030_REG_WINDOWHEIGHT_L, 0xe3},
390
391 {SENSOR, PO1030_REG_OUTFORMCTRL2, 0x04},
392 {SENSOR, PO1030_REG_OUTFORMCTRL2, 0x04},
393 {SENSOR, PO1030_REG_AUTOCTRL1, 0x08},
394 {SENSOR, PO1030_REG_CONTROL2, 0x03},
395 {SENSOR, 0x21, 0x90},
396 {SENSOR, PO1030_REG_YTARGET, 0x60},
397 {SENSOR, 0x59, 0x13},
398 {SENSOR, PO1030_REG_OUTFORMCTRL1, 0x40},
399 {SENSOR, 0x5f, 0x00},
400 {SENSOR, 0x60, 0x80},
401 {SENSOR, 0x78, 0x14},
402 {SENSOR, 0x6f, 0x01},
403 {SENSOR, PO1030_REG_CONTROL1, 0x18},
404 {SENSOR, PO1030_REG_GLOBALGAINMAX, 0x14},
405 {SENSOR, 0x63, 0x38},
406 {SENSOR, 0x64, 0x38},
407 {SENSOR, PO1030_REG_CONTROL1, 0x58},
408 {SENSOR, PO1030_REG_RED_GAIN, 0x30},
409 {SENSOR, PO1030_REG_GREEN_1_GAIN, 0x30},
410 {SENSOR, PO1030_REG_BLUE_GAIN, 0x30},
411 {SENSOR, PO1030_REG_GREEN_2_GAIN, 0x30},
412 {SENSOR, PO1030_REG_GC0, 0x10},
413 {SENSOR, PO1030_REG_GC1, 0x20},
414 {SENSOR, PO1030_REG_GC2, 0x40},
415 {SENSOR, PO1030_REG_GC3, 0x60},
416 {SENSOR, PO1030_REG_GC4, 0x80},
417 {SENSOR, PO1030_REG_GC5, 0xa0},
418 {SENSOR, PO1030_REG_GC6, 0xc0},
419 {SENSOR, PO1030_REG_GC7, 0xff},
420 /*end of sequence 4*/
421 /*sequence 5*/
422 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06},
423 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
424 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
425 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
426 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81},
427 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
428 {BRIDGE, M5602_XB_SIG_INI, 0x01},
429 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
430 {BRIDGE, M5602_XB_VSYNC_PARA, 0x02},
431 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
432 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
433 {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
434 {BRIDGE, M5602_XB_VSYNC_PARA, 0xec},
435 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
436 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
437 {BRIDGE, M5602_XB_SIG_INI, 0x00},
438 {BRIDGE, M5602_XB_SIG_INI, 0x00},
439 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
440 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
441 {BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
442 {BRIDGE, M5602_XB_HSYNC_PARA, 0x7e},
443 {BRIDGE, M5602_XB_SIG_INI, 0x00},
444 /*end of sequence 5*/
445
446 /*sequence 6*/
447 /* Changing 40 in f0 the image becomes green in bayer mode and red in
448 * rgb mode */
449 {SENSOR, PO1030_REG_RED_GAIN, PO1030_RED_GAIN_DEFAULT},
450 /* in changing 40 in f0 the image becomes green in bayer mode and red in
451 * rgb mode */
452 {SENSOR, PO1030_REG_BLUE_GAIN, PO1030_BLUE_GAIN_DEFAULT},
453
454 /* with a very low lighted environment increase the exposure but
455 * decrease the FPS (Frame Per Second) */
456 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
457 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
458
459 /* Controls high exposure more than SENSOR_LOW_EXPOSURE, use only in
460 * low lighted environment (f0 is more than ff ?)*/
461 {SENSOR, PO1030_REG_INTEGLINES_H, ((PO1030_EXPOSURE_DEFAULT >> 2)
462 & 0xff)},
463
464 /* Controls middle exposure, use only in high lighted environment */
465 {SENSOR, PO1030_REG_INTEGLINES_M, PO1030_EXPOSURE_DEFAULT & 0xff},
466
467 /* Controls clarity (not sure) */
468 {SENSOR, PO1030_REG_INTEGLINES_L, 0x00},
469 /* Controls gain (the image is more lighted) */
470 {SENSOR, PO1030_REG_GLOBALGAIN, PO1030_GLOBAL_GAIN_DEFAULT},
471
472 /* Sets the width */
473 {SENSOR, PO1030_REG_FRAMEWIDTH_H, 0x02},
474 {SENSOR, PO1030_REG_FRAMEWIDTH_L, 0xef}
475 /*end of sequence 6*/
476};
477
478#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
new file mode 100644
index 000000000000..3a2ae7a2e267
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
@@ -0,0 +1,460 @@
1/*
2 * Driver for the s5k4aa sensor
3 *
4 * Copyright (C) 2008 Erik Andren
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#include "m5602_s5k4aa.h"
20
21int s5k4aa_probe(struct sd *sd)
22{
23 u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
24 const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75};
25 int i, err = 0;
26
27 if (force_sensor) {
28 if (force_sensor == S5K4AA_SENSOR) {
29 info("Forcing a %s sensor", s5k4aa.name);
30 goto sensor_found;
31 }
32 /* If we want to force another sensor, don't try to probe this
33 * one */
34 return -ENODEV;
35 }
36
37 info("Probing for a s5k4aa sensor");
38
39 /* Preinit the sensor */
40 for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) {
41 u8 data[2] = {0x00, 0x00};
42
43 switch (preinit_s5k4aa[i][0]) {
44 case BRIDGE:
45 err = m5602_write_bridge(sd,
46 preinit_s5k4aa[i][1],
47 preinit_s5k4aa[i][2]);
48 break;
49
50 case SENSOR:
51 data[0] = preinit_s5k4aa[i][2];
52 err = s5k4aa_write_sensor(sd,
53 preinit_s5k4aa[i][1],
54 data, 1);
55 break;
56
57 case SENSOR_LONG:
58 data[0] = preinit_s5k4aa[i][2];
59 data[1] = preinit_s5k4aa[i][3];
60 err = s5k4aa_write_sensor(sd,
61 preinit_s5k4aa[i][1],
62 data, 2);
63 break;
64 default:
65 info("Invalid stream command, exiting init");
66 return -EINVAL;
67 }
68 }
69
70 /* Test some registers, but we don't know their exact meaning yet */
71 if (s5k4aa_read_sensor(sd, 0x00, prod_id, sizeof(prod_id)))
72 return -ENODEV;
73
74 if (memcmp(prod_id, expected_prod_id, sizeof(prod_id)))
75 return -ENODEV;
76 else
77 info("Detected a s5k4aa sensor");
78sensor_found:
79 sd->gspca_dev.cam.cam_mode = s5k4aa.modes;
80 sd->gspca_dev.cam.nmodes = s5k4aa.nmodes;
81 return 0;
82}
83
84int s5k4aa_read_sensor(struct sd *sd, const u8 address,
85 u8 *i2c_data, const u8 len)
86{
87 int err, i;
88
89 do {
90 err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
91 } while ((*i2c_data & I2C_BUSY) && !err);
92 if (err < 0)
93 goto out;
94
95 err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
96 sd->sensor->i2c_slave_id);
97 if (err < 0)
98 goto out;
99
100 err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
101 if (err < 0)
102 goto out;
103
104 err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len);
105 if (err < 0)
106 goto out;
107
108 do {
109 err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
110 } while ((*i2c_data & I2C_BUSY) && !err);
111 if (err < 0)
112 goto out;
113
114 for (i = 0; (i < len) & !err; i++) {
115 err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
116
117 PDEBUG(DBG_TRACE, "Reading sensor register "
118 "0x%x containing 0x%x ", address, *i2c_data);
119 }
120out:
121 return (err < 0) ? err : 0;
122}
123
124int s5k4aa_write_sensor(struct sd *sd, const u8 address,
125 u8 *i2c_data, const u8 len)
126{
127 int err, i;
128 u8 *p;
129 struct usb_device *udev = sd->gspca_dev.dev;
130 __u8 *buf = sd->gspca_dev.usb_buf;
131
132 /* No sensor with a data width larger than 16 bits has yet been seen */
133 if (len > 2 || !len)
134 return -EINVAL;
135
136 memcpy(buf, sensor_urb_skeleton,
137 sizeof(sensor_urb_skeleton));
138
139 buf[11] = sd->sensor->i2c_slave_id;
140 buf[15] = address;
141
142 /* Special case larger sensor writes */
143 p = buf + 16;
144
145 /* Copy a four byte write sequence for each byte to be written to */
146 for (i = 0; i < len; i++) {
147 memcpy(p, sensor_urb_skeleton + 16, 4);
148 p[3] = i2c_data[i];
149 p += 4;
150 PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x",
151 address, i2c_data[i]);
152 }
153
154 /* Copy the tailer */
155 memcpy(p, sensor_urb_skeleton + 20, 4);
156
157 /* Set the total length */
158 p[3] = 0x10 + len;
159
160 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
161 0x04, 0x40, 0x19,
162 0x0000, buf,
163 20 + len * 4, M5602_URB_MSG_TIMEOUT);
164
165 return (err < 0) ? err : 0;
166}
167
168int s5k4aa_init(struct sd *sd)
169{
170 int i, err = 0;
171
172 for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) {
173 u8 data[2] = {0x00, 0x00};
174
175 switch (init_s5k4aa[i][0]) {
176 case BRIDGE:
177 err = m5602_write_bridge(sd,
178 init_s5k4aa[i][1],
179 init_s5k4aa[i][2]);
180 break;
181
182 case SENSOR:
183 data[0] = init_s5k4aa[i][2];
184 err = s5k4aa_write_sensor(sd,
185 init_s5k4aa[i][1], data, 1);
186 break;
187
188 case SENSOR_LONG:
189 data[0] = init_s5k4aa[i][2];
190 data[1] = init_s5k4aa[i][3];
191 err = s5k4aa_write_sensor(sd,
192 init_s5k4aa[i][1], data, 2);
193 break;
194 default:
195 info("Invalid stream command, exiting init");
196 return -EINVAL;
197 }
198 }
199
200 if (dump_sensor)
201 s5k4aa_dump_registers(sd);
202
203 if (!err && dmi_check_system(s5k4aa_vflip_dmi_table)) {
204 u8 data = 0x02;
205 info("vertical flip quirk active");
206 s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
207 s5k4aa_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
208 data |= S5K4AA_RM_V_FLIP;
209 data &= ~S5K4AA_RM_H_FLIP;
210 s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
211
212 /* Decrement COLSTART to preserve color order (BGGR) */
213 s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
214 data--;
215 s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
216
217 /* Increment ROWSTART to preserve color order (BGGR) */
218 s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
219 data++;
220 s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
221 }
222
223 return (err < 0) ? err : 0;
224}
225
226int s5k4aa_power_down(struct sd *sd)
227{
228 return 0;
229}
230
231int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
232{
233 struct sd *sd = (struct sd *) gspca_dev;
234 u8 data = S5K4AA_PAGE_MAP_2;
235 int err;
236
237 err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
238 if (err < 0)
239 goto out;
240
241 err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
242 if (err < 0)
243 goto out;
244
245 *val = data << 8;
246 err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
247 *val |= data;
248 PDEBUG(DBG_V4L2_CID, "Read exposure %d", *val);
249out:
250 return (err < 0) ? err : 0;
251}
252
253int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
254{
255 struct sd *sd = (struct sd *) gspca_dev;
256 u8 data = S5K4AA_PAGE_MAP_2;
257 int err;
258
259 PDEBUG(DBG_V4L2_CID, "Set exposure to %d", val);
260 err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
261 if (err < 0)
262 goto out;
263 data = (val >> 8) & 0xff;
264 err = s5k4aa_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
265 if (err < 0)
266 goto out;
267 data = val & 0xff;
268 err = s5k4aa_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
269out:
270 return (err < 0) ? err : 0;
271}
272
273int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
274{
275 struct sd *sd = (struct sd *) gspca_dev;
276 u8 data = S5K4AA_PAGE_MAP_2;
277 int err;
278
279 err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
280 if (err < 0)
281 goto out;
282
283 err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
284 *val = (data & S5K4AA_RM_V_FLIP) >> 7;
285 PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val);
286
287out:
288 return (err < 0) ? err : 0;
289}
290
291int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
292{
293 struct sd *sd = (struct sd *) gspca_dev;
294 u8 data = S5K4AA_PAGE_MAP_2;
295 int err;
296
297 PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val);
298 err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
299 if (err < 0)
300 goto out;
301 err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
302 if (err < 0)
303 goto out;
304 data = ((data & ~S5K4AA_RM_V_FLIP)
305 | ((val & 0x01) << 7));
306 err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
307 if (err < 0)
308 goto out;
309
310 if (val) {
311 err = s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
312 if (err < 0)
313 goto out;
314
315 data++;
316 err = s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
317 } else {
318 err = s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
319 if (err < 0)
320 goto out;
321
322 data--;
323 err = s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
324 }
325out:
326 return (err < 0) ? err : 0;
327}
328
329int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
330{
331 struct sd *sd = (struct sd *) gspca_dev;
332 u8 data = S5K4AA_PAGE_MAP_2;
333 int err;
334
335 err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
336 if (err < 0)
337 goto out;
338
339 err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
340 *val = (data & S5K4AA_RM_H_FLIP) >> 6;
341 PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val);
342out:
343 return (err < 0) ? err : 0;
344}
345
346int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
347{
348 struct sd *sd = (struct sd *) gspca_dev;
349 u8 data = S5K4AA_PAGE_MAP_2;
350 int err;
351
352 PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d",
353 val);
354 err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
355 if (err < 0)
356 goto out;
357 err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
358 if (err < 0)
359 goto out;
360
361 data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6));
362 err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
363 if (err < 0)
364 goto out;
365
366 if (val) {
367 err = s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
368 if (err < 0)
369 goto out;
370 data++;
371 err = s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
372 if (err < 0)
373 goto out;
374 } else {
375 err = s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
376 if (err < 0)
377 goto out;
378 data--;
379 err = s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
380 }
381out:
382 return (err < 0) ? err : 0;
383}
384
385int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
386{
387 struct sd *sd = (struct sd *) gspca_dev;
388 u8 data = S5K4AA_PAGE_MAP_2;
389 int err;
390
391 err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
392 if (err < 0)
393 goto out;
394
395 err = s5k4aa_read_sensor(sd, S5K4AA_GAIN_2, &data, 1);
396 *val = data;
397 PDEBUG(DBG_V4L2_CID, "Read gain %d", *val);
398
399out:
400 return (err < 0) ? err : 0;
401}
402
403int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
404{
405 struct sd *sd = (struct sd *) gspca_dev;
406 u8 data = S5K4AA_PAGE_MAP_2;
407 int err;
408
409 PDEBUG(DBG_V4L2_CID, "Set gain to %d", val);
410 err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
411 if (err < 0)
412 goto out;
413
414 data = val & 0xff;
415 err = s5k4aa_write_sensor(sd, S5K4AA_GAIN_2, &data, 1);
416
417out:
418 return (err < 0) ? err : 0;
419}
420
421void s5k4aa_dump_registers(struct sd *sd)
422{
423 int address;
424 u8 page, old_page;
425 s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
426 for (page = 0; page < 16; page++) {
427 s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
428 info("Dumping the s5k4aa register state for page 0x%x", page);
429 for (address = 0; address <= 0xff; address++) {
430 u8 value = 0;
431 s5k4aa_read_sensor(sd, address, &value, 1);
432 info("register 0x%x contains 0x%x",
433 address, value);
434 }
435 }
436 info("s5k4aa register state dump complete");
437
438 for (page = 0; page < 16; page++) {
439 s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
440 info("Probing for which registers that are "
441 "read/write for page 0x%x", page);
442 for (address = 0; address <= 0xff; address++) {
443 u8 old_value, ctrl_value, test_value = 0xff;
444
445 s5k4aa_read_sensor(sd, address, &old_value, 1);
446 s5k4aa_write_sensor(sd, address, &test_value, 1);
447 s5k4aa_read_sensor(sd, address, &ctrl_value, 1);
448
449 if (ctrl_value == test_value)
450 info("register 0x%x is writeable", address);
451 else
452 info("register 0x%x is read only", address);
453
454 /* Restore original value */
455 s5k4aa_write_sensor(sd, address, &old_value, 1);
456 }
457 }
458 info("Read/write register probing complete");
459 s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
460}
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h
new file mode 100644
index 000000000000..1e4213a73214
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h
@@ -0,0 +1,368 @@
1/*
2 * Driver for the s5k4aa sensor
3 *
4 * Copyright (C) 2008 Erik Andren
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#ifndef M5602_S5K4AA_H_
20#define M5602_S5K4AA_H_
21
22#include <linux/dmi.h>
23
24#include "m5602_sensor.h"
25
26/*****************************************************************************/
27
28#define S5K4AA_PAGE_MAP 0xec
29
30#define S5K4AA_PAGE_MAP_0 0x00
31#define S5K4AA_PAGE_MAP_1 0x01
32#define S5K4AA_PAGE_MAP_2 0x02
33
34/* Sensor register definitions for page 0x02 */
35#define S5K4AA_READ_MODE 0x03
36#define S5K4AA_ROWSTART_HI 0x04
37#define S5K4AA_ROWSTART_LO 0x05
38#define S5K4AA_COLSTART_HI 0x06
39#define S5K4AA_COLSTART_LO 0x07
40#define S5K4AA_WINDOW_HEIGHT_HI 0x08
41#define S5K4AA_WINDOW_HEIGHT_LO 0x09
42#define S5K4AA_WINDOW_WIDTH_HI 0x0a
43#define S5K4AA_WINDOW_WIDTH_LO 0x0b
44#define S5K4AA_GLOBAL_GAIN__ 0x0f /* Only a guess ATM !!! */
45#define S5K4AA_H_BLANK_HI__ 0x1d /* Only a guess ATM !!! sync lost
46 if too low, reduces frame rate
47 if too high */
48#define S5K4AA_H_BLANK_LO__ 0x1e /* Only a guess ATM !!! */
49#define S5K4AA_EXPOSURE_HI 0x17
50#define S5K4AA_EXPOSURE_LO 0x18
51#define S5K4AA_GAIN_1 0x1f /* (digital?) gain : 5 bits */
52#define S5K4AA_GAIN_2 0x20 /* (analogue?) gain : 7 bits */
53
54#define S5K4AA_RM_ROW_SKIP_4X 0x08
55#define S5K4AA_RM_ROW_SKIP_2X 0x04
56#define S5K4AA_RM_COL_SKIP_4X 0x02
57#define S5K4AA_RM_COL_SKIP_2X 0x01
58#define S5K4AA_RM_H_FLIP 0x40
59#define S5K4AA_RM_V_FLIP 0x80
60
61/*****************************************************************************/
62
63/* Kernel module parameters */
64extern int force_sensor;
65extern int dump_sensor;
66extern unsigned int m5602_debug;
67
68int s5k4aa_probe(struct sd *sd);
69int s5k4aa_init(struct sd *sd);
70int s5k4aa_power_down(struct sd *sd);
71
72void s5k4aa_dump_registers(struct sd *sd);
73
74int s5k4aa_read_sensor(struct sd *sd, const u8 address,
75 u8 *i2c_data, const u8 len);
76int s5k4aa_write_sensor(struct sd *sd, const u8 address,
77 u8 *i2c_data, const u8 len);
78
79int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
80int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
81int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
82int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
83int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
84int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
85int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
86int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val);
87
88static struct m5602_sensor s5k4aa = {
89 .name = "S5K4AA",
90 .probe = s5k4aa_probe,
91 .init = s5k4aa_init,
92 .power_down = s5k4aa_power_down,
93 .read_sensor = s5k4aa_read_sensor,
94 .write_sensor = s5k4aa_write_sensor,
95 .i2c_slave_id = 0x5a,
96 .nctrls = 4,
97 .ctrls = {
98 {
99 {
100 .id = V4L2_CID_VFLIP,
101 .type = V4L2_CTRL_TYPE_BOOLEAN,
102 .name = "vertical flip",
103 .minimum = 0,
104 .maximum = 1,
105 .step = 1,
106 .default_value = 0
107 },
108 .set = s5k4aa_set_vflip,
109 .get = s5k4aa_get_vflip
110
111 }, {
112 {
113 .id = V4L2_CID_HFLIP,
114 .type = V4L2_CTRL_TYPE_BOOLEAN,
115 .name = "horizontal flip",
116 .minimum = 0,
117 .maximum = 1,
118 .step = 1,
119 .default_value = 0
120 },
121 .set = s5k4aa_set_hflip,
122 .get = s5k4aa_get_hflip
123
124 }, {
125 {
126 .id = V4L2_CID_GAIN,
127 .type = V4L2_CTRL_TYPE_INTEGER,
128 .name = "Gain",
129 .minimum = 0,
130 .maximum = 127,
131 .step = 1,
132 .default_value = 0xa0,
133 .flags = V4L2_CTRL_FLAG_SLIDER
134 },
135 .set = s5k4aa_set_gain,
136 .get = s5k4aa_get_gain
137 }, {
138 {
139 .id = V4L2_CID_EXPOSURE,
140 .type = V4L2_CTRL_TYPE_INTEGER,
141 .name = "Exposure",
142 .minimum = 13,
143 .maximum = 0xfff,
144 .step = 1,
145 .default_value = 0x100,
146 .flags = V4L2_CTRL_FLAG_SLIDER
147 },
148 .set = s5k4aa_set_exposure,
149 .get = s5k4aa_get_exposure
150 }
151 },
152
153 .nmodes = 1,
154 .modes = {
155 {
156 M5602_DEFAULT_FRAME_WIDTH,
157 M5602_DEFAULT_FRAME_HEIGHT,
158 V4L2_PIX_FMT_SBGGR8,
159 V4L2_FIELD_NONE,
160 .sizeimage =
161 M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT,
162 .bytesperline = M5602_DEFAULT_FRAME_WIDTH,
163 .colorspace = V4L2_COLORSPACE_SRGB,
164 .priv = 1
165 }
166 }
167};
168
169static const unsigned char preinit_s5k4aa[][4] =
170{
171 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
172 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
173 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
174 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
175 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
176 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
177 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
178
179 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
180 {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
181 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
182 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
183 {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
184 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
185 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
186 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
187 {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00},
188 {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
189 {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
190 {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
191 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
192 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
193 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
194 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
195
196 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
197 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
198 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
199 {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00},
200 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
201 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
202 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
203 {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
204 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
205 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
206 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
207 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
208 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
209
210 {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00}
211};
212
213static const unsigned char init_s5k4aa[][4] =
214{
215 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
216 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
217 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
218 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
219 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
220 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
221 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
222
223 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
224 {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
225 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
226 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
227 {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
228 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
229 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
230 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
231 {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00},
232 {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
233 {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
234 {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
235 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
236 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
237 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
238 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
239
240 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
241 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
242 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
243 {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00},
244 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
245 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
246 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
247 {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
248 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
249 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
250 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
251 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
252 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
253
254 {SENSOR, S5K4AA_PAGE_MAP, 0x07, 0x00},
255 {SENSOR, 0x36, 0x01, 0x00},
256 {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00},
257 {SENSOR, 0x7b, 0xff, 0x00},
258 {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
259 {SENSOR, 0x0c, 0x05, 0x00},
260 {SENSOR, 0x02, 0x0e, 0x00},
261 {SENSOR, S5K4AA_GAIN_1, 0x0f, 0x00},
262 {SENSOR, S5K4AA_GAIN_2, 0x00, 0x00},
263 {SENSOR, S5K4AA_GLOBAL_GAIN__, 0x01, 0x00},
264 {SENSOR, 0x11, 0x00, 0x00},
265 {SENSOR, 0x12, 0x00, 0x00},
266 {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
267 {SENSOR, S5K4AA_READ_MODE, 0xa0, 0x00},
268 {SENSOR, 0x37, 0x00, 0x00},
269 {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00},
270 {SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00},
271 {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00},
272 {SENSOR, S5K4AA_COLSTART_LO, 0x0b, 0x00},
273 {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00},
274 {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc4, 0x00},
275 {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00},
276 {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x08, 0x00},
277 {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00},
278 {SENSOR, S5K4AA_H_BLANK_LO__, 0x48, 0x00},
279 {SENSOR, S5K4AA_EXPOSURE_HI, 0x00, 0x00},
280 {SENSOR, S5K4AA_EXPOSURE_LO, 0x43, 0x00},
281 {SENSOR, 0x11, 0x04, 0x00},
282 {SENSOR, 0x12, 0xc3, 0x00},
283 {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
284
285 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
286 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
287 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
288 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
289 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
290 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
291 {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
292 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
293 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
294 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
295 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
296 /* VSYNC_PARA, VSYNC_PARA : img height 480 = 0x01e0 */
297 {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
298 {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00},
299 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
300 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
301 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
302 {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
303 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
304 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
305 /* HSYNC_PARA, HSYNC_PARA : img width 640 = 0x0280 */
306 {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
307 {BRIDGE, M5602_XB_HSYNC_PARA, 0x80, 0x00},
308 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
309 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
310 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */
311
312 {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
313 {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP | S5K4AA_RM_ROW_SKIP_2X
314 | S5K4AA_RM_COL_SKIP_2X, 0x00},
315 /* 0x37 : Fix image stability when light is too bright and improves
316 * image quality in 640x480, but worsens it in 1280x1024 */
317 {SENSOR, 0x37, 0x01, 0x00},
318 /* ROWSTART_HI, ROWSTART_LO : 10 + (1024-960)/2 = 42 = 0x002a */
319 {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00},
320 {SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00},
321 {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00},
322 {SENSOR, S5K4AA_COLSTART_LO, 0x0c, 0x00},
323 /* window_height_hi, window_height_lo : 960 = 0x03c0 */
324 {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00},
325 {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc0, 0x00},
326 /* window_width_hi, window_width_lo : 1280 = 0x0500 */
327 {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00},
328 {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00},
329 {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00},
330 {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00}, /* helps to sync... */
331 {SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00},
332 {SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00},
333 {SENSOR, 0x11, 0x04, 0x00},
334 {SENSOR, 0x12, 0xc3, 0x00},
335 {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
336 {SENSOR, 0x02, 0x0e, 0x00},
337 {SENSOR_LONG, S5K4AA_GLOBAL_GAIN__, 0x0f, 0x00},
338 {SENSOR, S5K4AA_GAIN_1, 0x0b, 0x00},
339 {SENSOR, S5K4AA_GAIN_2, 0xa0, 0x00}
340};
341
342static const struct dmi_system_id s5k4aa_vflip_dmi_table[] = {
343 {
344 .ident = "Fujitsu-Siemens Amilo Xa 2528",
345 .matches = {
346 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
347 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528")
348 }
349 },
350 {
351 .ident = "Fujitsu-Siemens Amilo Xi 2550",
352 .matches = {
353 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
354 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2550")
355 }
356 },
357 {
358 .ident = "MSI GX700",
359 .matches = {
360 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
361 DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
362 DMI_MATCH(DMI_BIOS_DATE, "07/26/2007")
363 }
364 },
365 { }
366};
367
368#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/drivers/media/video/gspca/m5602/m5602_s5k83a.c
new file mode 100644
index 000000000000..a4d6a8163120
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.c
@@ -0,0 +1,331 @@
1/*
2 * Driver for the s5k83a sensor
3 *
4 * Copyright (C) 2008 Erik Andren
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#include "m5602_s5k83a.h"
20
21int s5k83a_probe(struct sd *sd)
22{
23 u8 prod_id = 0, ver_id = 0;
24 int i, err = 0;
25
26 if (force_sensor) {
27 if (force_sensor == S5K83A_SENSOR) {
28 info("Forcing a %s sensor", s5k83a.name);
29 goto sensor_found;
30 }
31 /* If we want to force another sensor, don't try to probe this
32 * one */
33 return -ENODEV;
34 }
35
36 info("Probing for a s5k83a sensor");
37
38 /* Preinit the sensor */
39 for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) {
40 u8 data[2] = {preinit_s5k83a[i][2], preinit_s5k83a[i][3]};
41 if (preinit_s5k83a[i][0] == SENSOR)
42 err = s5k83a_write_sensor(sd, preinit_s5k83a[i][1],
43 data, 2);
44 else
45 err = m5602_write_bridge(sd, preinit_s5k83a[i][1],
46 data[0]);
47 }
48
49 /* We don't know what register (if any) that contain the product id
50 * Just pick the first addresses that seem to produce the same results
51 * on multiple machines */
52 if (s5k83a_read_sensor(sd, 0x00, &prod_id, 1))
53 return -ENODEV;
54
55 if (s5k83a_read_sensor(sd, 0x01, &ver_id, 1))
56 return -ENODEV;
57
58 if ((prod_id == 0xff) || (ver_id == 0xff))
59 return -ENODEV;
60 else
61 info("Detected a s5k83a sensor");
62
63sensor_found:
64 sd->gspca_dev.cam.cam_mode = s5k83a.modes;
65 sd->gspca_dev.cam.nmodes = s5k83a.nmodes;
66 return 0;
67}
68
69int s5k83a_read_sensor(struct sd *sd, const u8 address,
70 u8 *i2c_data, const u8 len)
71{
72 int err, i;
73
74 do {
75 err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
76 } while ((*i2c_data & I2C_BUSY) && !err);
77 if (err < 0)
78 goto out;
79
80 err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
81 sd->sensor->i2c_slave_id);
82 if (err < 0)
83 goto out;
84
85 err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
86 if (err < 0)
87 goto out;
88
89 err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len);
90 if (err < 0)
91 goto out;
92
93 do {
94 err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
95 } while ((*i2c_data & I2C_BUSY) && !err);
96
97 if (err < 0)
98 goto out;
99 for (i = 0; i < len && !len; i++) {
100 err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
101
102 PDEBUG(DBG_TRACE, "Reading sensor register "
103 "0x%x containing 0x%x ", address, *i2c_data);
104 }
105
106out:
107 return (err < 0) ? err : 0;
108}
109
110int s5k83a_write_sensor(struct sd *sd, const u8 address,
111 u8 *i2c_data, const u8 len)
112{
113 int err, i;
114 u8 *p;
115 struct usb_device *udev = sd->gspca_dev.dev;
116 __u8 *buf = sd->gspca_dev.usb_buf;
117
118 /* No sensor with a data width larger than 16 bits has yet been seen */
119 if (len > 2 || !len)
120 return -EINVAL;
121
122 memcpy(buf, sensor_urb_skeleton,
123 sizeof(sensor_urb_skeleton));
124
125 buf[11] = sd->sensor->i2c_slave_id;
126 buf[15] = address;
127
128 /* Special case larger sensor writes */
129 p = buf + 16;
130
131 /* Copy a four byte write sequence for each byte to be written to */
132 for (i = 0; i < len; i++) {
133 memcpy(p, sensor_urb_skeleton + 16, 4);
134 p[3] = i2c_data[i];
135 p += 4;
136 PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x",
137 address, i2c_data[i]);
138 }
139
140 /* Copy the tailer */
141 memcpy(p, sensor_urb_skeleton + 20, 4);
142
143 /* Set the total length */
144 p[3] = 0x10 + len;
145
146 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
147 0x04, 0x40, 0x19,
148 0x0000, buf,
149 20 + len * 4, M5602_URB_MSG_TIMEOUT);
150
151 return (err < 0) ? err : 0;
152}
153
154int s5k83a_init(struct sd *sd)
155{
156 int i, err = 0;
157
158 for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) {
159 u8 data[2] = {0x00, 0x00};
160
161 switch (init_s5k83a[i][0]) {
162 case BRIDGE:
163 err = m5602_write_bridge(sd,
164 init_s5k83a[i][1],
165 init_s5k83a[i][2]);
166 break;
167
168 case SENSOR:
169 data[0] = init_s5k83a[i][2];
170 err = s5k83a_write_sensor(sd,
171 init_s5k83a[i][1], data, 1);
172 break;
173
174 case SENSOR_LONG:
175 data[0] = init_s5k83a[i][2];
176 data[1] = init_s5k83a[i][3];
177 err = s5k83a_write_sensor(sd,
178 init_s5k83a[i][1], data, 2);
179 break;
180 default:
181 info("Invalid stream command, exiting init");
182 return -EINVAL;
183 }
184 }
185
186 if (dump_sensor)
187 s5k83a_dump_registers(sd);
188
189 return (err < 0) ? err : 0;
190}
191
192int s5k83a_power_down(struct sd *sd)
193{
194 return 0;
195}
196
197void s5k83a_dump_registers(struct sd *sd)
198{
199 int address;
200 u8 page, old_page;
201 s5k83a_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
202
203 for (page = 0; page < 16; page++) {
204 s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
205 info("Dumping the s5k83a register state for page 0x%x", page);
206 for (address = 0; address <= 0xff; address++) {
207 u8 val = 0;
208 s5k83a_read_sensor(sd, address, &val, 1);
209 info("register 0x%x contains 0x%x",
210 address, val);
211 }
212 }
213 info("s5k83a register state dump complete");
214
215 for (page = 0; page < 16; page++) {
216 s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
217 info("Probing for which registers that are read/write "
218 "for page 0x%x", page);
219 for (address = 0; address <= 0xff; address++) {
220 u8 old_val, ctrl_val, test_val = 0xff;
221
222 s5k83a_read_sensor(sd, address, &old_val, 1);
223 s5k83a_write_sensor(sd, address, &test_val, 1);
224 s5k83a_read_sensor(sd, address, &ctrl_val, 1);
225
226 if (ctrl_val == test_val)
227 info("register 0x%x is writeable", address);
228 else
229 info("register 0x%x is read only", address);
230
231 /* Restore original val */
232 s5k83a_write_sensor(sd, address, &old_val, 1);
233 }
234 }
235 info("Read/write register probing complete");
236 s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
237}
238
239int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
240{
241 int err;
242 u8 data[2];
243 struct sd *sd = (struct sd *) gspca_dev;
244
245 err = s5k83a_read_sensor(sd, S5K83A_BRIGHTNESS, data, 2);
246 data[1] = data[1] << 1;
247 *val = data[1];
248
249 return (err < 0) ? err : 0;
250}
251
252int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
253{
254 int err;
255 u8 data[2];
256 struct sd *sd = (struct sd *) gspca_dev;
257
258 data[0] = 0x00;
259 data[1] = 0x20;
260 err = s5k83a_write_sensor(sd, 0x14, data, 2);
261 if (err < 0)
262 return err;
263
264 data[0] = 0x01;
265 data[1] = 0x00;
266 err = s5k83a_write_sensor(sd, 0x0d, data, 2);
267 if (err < 0)
268 return err;
269
270 /* FIXME: This is not sane, we need to figure out the composition
271 of these registers */
272 data[0] = val >> 3; /* brightness, high 5 bits */
273 data[1] = val >> 1; /* brightness, high 7 bits */
274 err = s5k83a_write_sensor(sd, S5K83A_BRIGHTNESS, data, 2);
275
276 return (err < 0) ? err : 0;
277}
278
279int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val)
280{
281 int err;
282 u8 data;
283 struct sd *sd = (struct sd *) gspca_dev;
284
285 err = s5k83a_read_sensor(sd, S5K83A_WHITENESS, &data, 1);
286
287 *val = data;
288 return (err < 0) ? err : 0;
289}
290
291int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val)
292{
293 int err;
294 u8 data[1];
295 struct sd *sd = (struct sd *) gspca_dev;
296
297 data[0] = val;
298 err = s5k83a_write_sensor(sd, S5K83A_WHITENESS, data, 1);
299
300 return (err < 0) ? err : 0;
301}
302
303int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
304{
305 int err;
306 u8 data[2];
307 struct sd *sd = (struct sd *) gspca_dev;
308
309 err = s5k83a_read_sensor(sd, S5K83A_GAIN, data, 2);
310
311 data[1] = data[1] & 0x3f;
312 if (data[1] > S5K83A_MAXIMUM_GAIN)
313 data[1] = S5K83A_MAXIMUM_GAIN;
314
315 *val = data[1];
316
317 return (err < 0) ? err : 0;
318}
319
320int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
321{
322 int err = 0;
323 u8 data[2];
324 struct sd *sd = (struct sd *) gspca_dev;
325
326 data[0] = 0;
327 data[1] = val;
328 err = s5k83a_write_sensor(sd, S5K83A_GAIN, data, 2);
329
330 return (err < 0) ? err : 0;
331}
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/drivers/media/video/gspca/m5602/m5602_s5k83a.h
new file mode 100644
index 000000000000..a57f623d80c3
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.h
@@ -0,0 +1,444 @@
1/*
2 * Driver for the s5k83a sensor
3 *
4 * Copyright (C) 2008 Erik Andren
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#ifndef M5602_S5K83A_H_
20#define M5602_S5K83A_H_
21
22#include "m5602_sensor.h"
23
24#define S5K83A_PAGE_MAP 0xec
25#define S5K83A_GAIN 0x18
26#define S5K83A_WHITENESS 0x0a
27#define S5K83A_BRIGHTNESS 0x1b
28
29#define S5K83A_DEFAULT_BRIGHTNESS 0x71
30#define S5K83A_DEFAULT_WHITENESS 0x7e
31#define S5K83A_DEFAULT_GAIN 0x00
32#define S5K83A_MAXIMUM_GAIN 0x3c
33
34/*****************************************************************************/
35
36/* Kernel module parameters */
37extern int force_sensor;
38extern int dump_sensor;
39extern unsigned int m5602_debug;
40
41
42int s5k83a_probe(struct sd *sd);
43int s5k83a_init(struct sd *sd);
44int s5k83a_power_down(struct sd *sd);
45
46void s5k83a_dump_registers(struct sd *sd);
47
48int s5k83a_read_sensor(struct sd *sd, const u8 address,
49 u8 *i2c_data, const u8 len);
50int s5k83a_write_sensor(struct sd *sd, const u8 address,
51 u8 *i2c_data, const u8 len);
52
53int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
54int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
55int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val);
56int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val);
57int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val);
58int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
59
60static struct m5602_sensor s5k83a = {
61 .name = "S5K83A",
62 .probe = s5k83a_probe,
63 .init = s5k83a_init,
64 .power_down = s5k83a_power_down,
65 .read_sensor = s5k83a_read_sensor,
66 .write_sensor = s5k83a_write_sensor,
67 .i2c_slave_id = 0x5a,
68 .nctrls = 3,
69 .ctrls = {
70 {
71 {
72 .id = V4L2_CID_BRIGHTNESS,
73 .type = V4L2_CTRL_TYPE_INTEGER,
74 .name = "brightness",
75 .minimum = 0x00,
76 .maximum = 0xff,
77 .step = 0x01,
78 .default_value = S5K83A_DEFAULT_BRIGHTNESS,
79 .flags = V4L2_CTRL_FLAG_SLIDER
80 },
81 .set = s5k83a_set_brightness,
82 .get = s5k83a_get_brightness
83
84 }, {
85 {
86 .id = V4L2_CID_WHITENESS,
87 .type = V4L2_CTRL_TYPE_INTEGER,
88 .name = "whiteness",
89 .minimum = 0x00,
90 .maximum = 0xff,
91 .step = 0x01,
92 .default_value = S5K83A_DEFAULT_WHITENESS,
93 .flags = V4L2_CTRL_FLAG_SLIDER
94 },
95 .set = s5k83a_set_whiteness,
96 .get = s5k83a_get_whiteness,
97 }, {
98 {
99 .id = V4L2_CID_GAIN,
100 .type = V4L2_CTRL_TYPE_INTEGER,
101 .name = "gain",
102 .minimum = 0x00,
103 .maximum = S5K83A_MAXIMUM_GAIN,
104 .step = 0x01,
105 .default_value = S5K83A_DEFAULT_GAIN,
106 .flags = V4L2_CTRL_FLAG_SLIDER
107 },
108 .set = s5k83a_set_gain,
109 .get = s5k83a_get_gain
110 }
111 },
112 .nmodes = 1,
113 .modes = {
114 {
115 M5602_DEFAULT_FRAME_WIDTH,
116 M5602_DEFAULT_FRAME_HEIGHT,
117 V4L2_PIX_FMT_SBGGR8,
118 V4L2_FIELD_NONE,
119 .sizeimage =
120 M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT,
121 .bytesperline = M5602_DEFAULT_FRAME_WIDTH,
122 .colorspace = V4L2_COLORSPACE_SRGB,
123 .priv = 1
124
125 }
126 }
127};
128
129static const unsigned char preinit_s5k83a[][4] =
130{
131 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
132 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
133 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
134 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
135 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
136 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
137 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
138
139 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
140 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
141 {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
142 {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
143 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
144 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
145 {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
146 {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
147 {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
148 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
149 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
150 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
151 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
152 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
153 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
154 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
155 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
156 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
157 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
158 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
159 {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
160 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
161 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
162 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
163 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
164 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
165
166 {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00}
167};
168
169/* This could probably be considerably shortened.
170 I don't have the hardware to experiment with it, patches welcome
171*/
172static const unsigned char init_s5k83a[][4] =
173{
174 {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00},
175 {SENSOR, 0xaf, 0x01, 0x00},
176 {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00},
177 {SENSOR, 0x7b, 0xff, 0x00},
178 {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
179 {SENSOR, 0x01, 0x50, 0x00},
180 {SENSOR, 0x12, 0x20, 0x00},
181 {SENSOR, 0x17, 0x40, 0x00},
182 {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00},
183 {SENSOR, 0x1c, 0x00, 0x00},
184 {SENSOR, 0x02, 0x70, 0x00},
185 {SENSOR, 0x03, 0x0b, 0x00},
186 {SENSOR, 0x04, 0xf0, 0x00},
187 {SENSOR, 0x05, 0x0b, 0x00},
188 {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
189
190 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
191 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
192 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
193 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
194 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
195 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
196 {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
197 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
198 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
199 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
200 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
201 {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
202 {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00},
203 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
204 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
205 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
206 {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
207 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
208 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
209 {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
210 {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00},
211 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
212 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
213 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
214
215 {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
216 {SENSOR, 0x06, 0x71, 0x00},
217 {SENSOR, 0x07, 0xe8, 0x00},
218 {SENSOR, 0x08, 0x02, 0x00},
219 {SENSOR, 0x09, 0x88, 0x00},
220 {SENSOR, 0x14, 0x00, 0x00},
221 {SENSOR, 0x15, 0x20, 0x00},
222 {SENSOR, 0x19, 0x00, 0x00},
223 {SENSOR, 0x1a, 0x98, 0x00},
224 {SENSOR, 0x0f, 0x02, 0x00},
225 {SENSOR, 0x10, 0xe5, 0x00},
226 {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
227 {SENSOR_LONG, 0x14, 0x00, 0x20},
228 {SENSOR_LONG, 0x0d, 0x00, 0x7d},
229 {SENSOR_LONG, 0x1b, 0x0d, 0x05},
230
231 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
232 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
233 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
234 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
235 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
236 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
237 {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
238 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
239 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
240 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
241 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
242 {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
243 {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00},
244 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
245 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
246 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
247 {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
248 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
249 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
250 {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
251 {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00},
252
253 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
254 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
255 {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
256 {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
257 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
258 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
259 {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
260 {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
261 {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
262 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
263 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
264 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
265 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
266 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
267 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
268 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
269 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
270 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
271 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
272 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
273 {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
274 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
275 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
276 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
277 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
278 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
279
280 {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00},
281 {SENSOR, 0xaf, 0x01, 0x00},
282 {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
283 /* ff ( init value )is very dark) || 71 and f0 better */
284 {SENSOR, 0x7b, 0xff, 0x00},
285 {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
286 {SENSOR, 0x01, 0x50, 0x00},
287 {SENSOR, 0x12, 0x20, 0x00},
288 {SENSOR, 0x17, 0x40, 0x00},
289 {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00},
290 {SENSOR, 0x1c, 0x00, 0x00},
291 {SENSOR, 0x02, 0x70, 0x00},
292 /* some values like 0x10 give a blue-purple image */
293 {SENSOR, 0x03, 0x0b, 0x00},
294 {SENSOR, 0x04, 0xf0, 0x00},
295 {SENSOR, 0x05, 0x0b, 0x00},
296 {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
297
298 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
299 /* under 80 don't work, highter depend on value */
300 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
301
302 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
303 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
304 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
305 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
306 {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
307 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
308 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
309 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
310 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
311 {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
312 {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00},
313 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
314 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
315 {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
316 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
317 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
318 {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
319 {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00},
320
321 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
322 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
323 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
324
325 {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
326 {SENSOR, 0x06, 0x71, 0x00},
327 {SENSOR, 0x07, 0xe8, 0x00},
328 {SENSOR, 0x08, 0x02, 0x00},
329 {SENSOR, 0x09, 0x88, 0x00},
330 {SENSOR, 0x14, 0x00, 0x00},
331 {SENSOR, 0x15, 0x20, 0x00},
332 {SENSOR, 0x19, 0x00, 0x00},
333 {SENSOR, 0x1a, 0x98, 0x00},
334 {SENSOR, 0x0f, 0x02, 0x00},
335 {SENSOR, 0x10, 0xe5, 0x00},
336 {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
337 {SENSOR_LONG, 0x14, 0x00, 0x20},
338 {SENSOR_LONG, 0x0d, 0x00, 0x7d},
339 {SENSOR_LONG, 0x1b, 0x0d, 0x05},
340
341 /* The following sequence is useless after a clean boot
342 but is necessary after resume from suspend */
343 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
344 {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
345 {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
346 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
347 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
348 {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
349 {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
350 {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
351 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
352 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
353 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
354 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
355 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
356 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
357 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
358 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
359 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
360 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
361 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
362 {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
363 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
364 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
365 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
366 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
367 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
368
369 {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00},
370 {SENSOR, 0xaf, 0x01, 0x00},
371 {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00},
372 {SENSOR, 0x7b, 0xff, 0x00},
373 {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
374 {SENSOR, 0x01, 0x50, 0x00},
375 {SENSOR, 0x12, 0x20, 0x00},
376 {SENSOR, 0x17, 0x40, 0x00},
377 {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00},
378 {SENSOR, 0x1c, 0x00, 0x00},
379 {SENSOR, 0x02, 0x70, 0x00},
380 {SENSOR, 0x03, 0x0b, 0x00},
381 {SENSOR, 0x04, 0xf0, 0x00},
382 {SENSOR, 0x05, 0x0b, 0x00},
383 {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
384
385 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
386 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
387 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
388 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
389 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
390 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
391 {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
392 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
393 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
394 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
395 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
396 {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
397 {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00},
398 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
399 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
400 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
401 {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
402 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
403 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
404 {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
405 {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00},
406 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
407 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
408 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
409
410 {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
411 {SENSOR, 0x06, 0x71, 0x00},
412 {SENSOR, 0x07, 0xe8, 0x00},
413 {SENSOR, 0x08, 0x02, 0x00},
414 {SENSOR, 0x09, 0x88, 0x00},
415 {SENSOR, 0x14, 0x00, 0x00},
416 {SENSOR, 0x15, 0x20, 0x00},
417 {SENSOR, 0x19, 0x00, 0x00},
418 {SENSOR, 0x1a, 0x98, 0x00},
419 {SENSOR, 0x0f, 0x02, 0x00},
420
421 {SENSOR, 0x10, 0xe5, 0x00},
422 {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
423 {SENSOR_LONG, 0x14, 0x00, 0x20},
424 {SENSOR_LONG, 0x0d, 0x00, 0x7d},
425 {SENSOR_LONG, 0x1b, 0x0d, 0x05},
426
427 /* normal colors
428 (this is value after boot, but after tries can be different) */
429 {SENSOR, 0x00, 0x06, 0x00},
430
431 /* set default brightness */
432 {SENSOR_LONG, 0x14, 0x00, 0x20},
433 {SENSOR_LONG, 0x0d, 0x01, 0x00},
434 {SENSOR_LONG, 0x1b, S5K83A_DEFAULT_BRIGHTNESS >> 3,
435 S5K83A_DEFAULT_BRIGHTNESS >> 1},
436
437 /* set default whiteness */
438 {SENSOR, S5K83A_WHITENESS, S5K83A_DEFAULT_WHITENESS, 0x00},
439
440 /* set default gain */
441 {SENSOR_LONG, 0x18, 0x00, S5K83A_DEFAULT_GAIN}
442};
443
444#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_sensor.h b/drivers/media/video/gspca/m5602/m5602_sensor.h
new file mode 100644
index 000000000000..930fcaab4416
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_sensor.h
@@ -0,0 +1,76 @@
1/*
2 * USB Driver for ALi m5602 based webcams
3 *
4 * Copyright (C) 2008 Erik Andren
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#ifndef M5602_SENSOR_H_
20#define M5602_SENSOR_H_
21
22#include "m5602_bridge.h"
23
24#define M5602_DEFAULT_FRAME_WIDTH 640
25#define M5602_DEFAULT_FRAME_HEIGHT 480
26
27#define M5602_MAX_CTRLS (V4L2_CID_LASTP1 - V4L2_CID_BASE + 10)
28
29/* Enumerates all supported sensors */
30enum sensors {
31 OV9650_SENSOR = 1,
32 S5K83A_SENSOR = 2,
33 S5K4AA_SENSOR = 3,
34 MT9M111_SENSOR = 4,
35 PO1030_SENSOR = 5
36};
37
38/* Enumerates all possible instruction types */
39enum instruction {
40 BRIDGE,
41 SENSOR,
42 SENSOR_LONG
43};
44
45struct m5602_sensor {
46 /* Defines the name of a sensor */
47 char name[32];
48
49 /* What i2c address the sensor is connected to */
50 u8 i2c_slave_id;
51
52 /* Probes if the sensor is connected */
53 int (*probe)(struct sd *sd);
54
55 /* Performs a initialization sequence */
56 int (*init)(struct sd *sd);
57
58 /* Performs a power down sequence */
59 int (*power_down)(struct sd *sd);
60
61 /* Reads a sensor register */
62 int (*read_sensor)(struct sd *sd, const u8 address,
63 u8 *i2c_data, const u8 len);
64
65 /* Writes to a sensor register */
66 int (*write_sensor)(struct sd *sd, const u8 address,
67 u8 *i2c_data, const u8 len);
68
69 int nctrls;
70 struct ctrl ctrls[M5602_MAX_CTRLS];
71
72 char nmodes;
73 struct v4l2_pix_format modes[];
74};
75
76#endif