Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Erik Andren and committed by
Mauro Carvalho Chehab
c109f816 a3a58467

+5441
+1
Documentation/video4linux/gspca.txt
··· 7 7 xxxx vend:prod 8 8 ---- 9 9 spca501 0000:0000 MystFromOri Unknow Camera 10 + m5602 0402:5602 ALi Video Camera Controller 10 11 spca501 040a:0002 Kodak DVC-325 11 12 spca500 040a:0300 Kodak EZ200 12 13 zc3xx 041e:041e Creative WebCam Live!
+12
Documentation/video4linux/m5602.txt
··· 1 + This document describes the ALi m5602 bridge connected 2 + to the following supported sensors: 3 + OmniVision OV9650, 4 + Samsung s5k83a, 5 + Samsung s5k4aa, 6 + Micron mt9m111, 7 + Pixel plus PO1030 8 + 9 + This driver mimics the windows drivers, which have a braindead implementation sending bayer-encoded frames at VGA resolution. 10 + In 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 + 12 + Anyway, have fun and please report any bugs to m560x-driver-devel@lists.sourceforge.net
+3
drivers/media/video/gspca/Kconfig
··· 11 11 12 12 To compile this driver as modules, choose M here: the 13 13 modules will be called gspca_xxxx. 14 + 15 + source "drivers/media/video/gspca/m5602/Kconfig" 16 +
+3
drivers/media/video/gspca/Makefile
··· 28 28 gspca_tv8532-objs := tv8532.o 29 29 gspca_vc032x-objs := vc032x.o 30 30 gspca_zc3xx-objs := zc3xx.o 31 + 32 + obj-$(CONFIG_USB_M5602) += m5602/ 33 +
+11
drivers/media/video/gspca/m5602/Kconfig
··· 1 + config 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.
+11
drivers/media/video/gspca/m5602/Makefile
··· 1 + obj-$(CONFIG_USB_M5602) += gspca_m5602.o 2 + 3 + gspca_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 + 10 + EXTRA_CFLAGS += -Idrivers/media/video/gspca 11 +
+180
drivers/media/video/gspca/m5602/m5602_bridge.h
··· 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 */ 131 + static const unsigned char bridge_urb_skeleton[] = { 132 + 0x13, 0x00, 0x81, 0x00 133 + }; 134 + 135 + /* A skeleton used for sending messages to the sensor */ 136 + static 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 */ 146 + struct 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 + 162 + int m5602_read_bridge( 163 + struct sd *sd, u8 address, u8 *i2c_data); 164 + 165 + int m5602_write_bridge( 166 + struct sd *sd, u8 address, u8 i2c_data); 167 + 168 + int m5602_configure(struct gspca_dev *gspca_dev, 169 + const struct usb_device_id *id); 170 + 171 + int m5602_init(struct gspca_dev *gspca_dev); 172 + 173 + void m5602_start_transfer(struct gspca_dev *gspca_dev); 174 + 175 + void m5602_stop_transfer(struct gspca_dev *gspca_dev); 176 + 177 + void m5602_urb_complete(struct gspca_dev *gspca_dev, struct gspca_frame *frame, 178 + __u8 *data, int len); 179 + 180 + #endif
+321
drivers/media/video/gspca/m5602/m5602_core.c
··· 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 */ 26 + int force_sensor; 27 + int dump_bridge; 28 + int dump_sensor; 29 + unsigned int m5602_debug; 30 + 31 + static const __devinitdata struct usb_device_id m5602_table[] = { 32 + {USB_DEVICE(0x0402, 0x5602)}, 33 + {} 34 + }; 35 + 36 + MODULE_DEVICE_TABLE(usb, m5602_table); 37 + 38 + /* sub-driver description, the ctrl and nctrl is filled at probe time */ 39 + static 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 */ 49 + int 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 */ 70 + int 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 */ 96 + static 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 + 107 + int 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 + 156 + int 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 + 168 + void 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 + 183 + void 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 + 234 + void 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 */ 240 + int 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 + 262 + fail: 263 + PDEBUG(DBG_GSPCA, "m5602_configure failed"); 264 + cam->cam_mode = NULL; 265 + cam->nmodes = 0; 266 + 267 + return err; 268 + } 269 + 270 + static 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 + 277 + static 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 -- */ 289 + static 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 + } 296 + static void __exit mod_m5602_exit(void) 297 + { 298 + usb_deregister(&sd_driver); 299 + PDEBUG(D_PROBE, "m5602 module deregistered"); 300 + } 301 + 302 + module_init(mod_m5602_init); 303 + module_exit(mod_m5602_exit); 304 + 305 + MODULE_AUTHOR(DRIVER_AUTHOR); 306 + MODULE_DESCRIPTION(DRIVER_DESC); 307 + MODULE_LICENSE("GPL"); 308 + module_param_named(debug, m5602_debug, int, S_IRUGO | S_IWUSR); 309 + MODULE_PARM_DESC(debug, "toggles debug on/off"); 310 + 311 + module_param(force_sensor, int, S_IRUGO | S_IWUSR); 312 + MODULE_PARM_DESC(force_sensor, 313 + "force detection of sensor, " 314 + "1 = OV9650, 2 = S5K83A, 3 = S5K4AA, 4 = MT9M111, 5 = PO1030"); 315 + 316 + module_param(dump_bridge, bool, S_IRUGO | S_IWUSR); 317 + MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup"); 318 + 319 + module_param(dump_sensor, bool, S_IRUGO | S_IWUSR); 320 + MODULE_PARM_DESC(dump_sensor, "Dumps all usb sensor registers " 321 + "at startup providing a sensor is found");
+343
drivers/media/video/gspca/m5602/m5602_mt9m111.c
··· 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 + 21 + int 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 + 62 + sensor_found: 63 + sd->gspca_dev.cam.cam_mode = mt9m111.modes; 64 + sd->gspca_dev.cam.nmodes = mt9m111.nmodes; 65 + return 0; 66 + } 67 + 68 + int 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 + 94 + int mt9m111_power_down(struct sd *sd) 95 + { 96 + return 0; 97 + } 98 + 99 + int 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 + 113 + int 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); 133 + out: 134 + return (err < 0) ? err : 0; 135 + } 136 + 137 + int 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 + 151 + int 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); 171 + out: 172 + return (err < 0) ? err : 0; 173 + } 174 + 175 + int 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 + 194 + int 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); 228 + out: 229 + return (err < 0) ? err : 0; 230 + } 231 + 232 + int 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 + } 261 + out: 262 + return (err < 0) ? err : 0; 263 + } 264 + 265 + int 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 + 309 + void 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 + }
+1020
drivers/media/video/gspca/m5602/m5602_mt9m111.h
··· 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 */ 83 + extern int force_sensor; 84 + extern int dump_sensor; 85 + extern unsigned int m5602_debug; 86 + 87 + int mt9m111_probe(struct sd *sd); 88 + int mt9m111_init(struct sd *sd); 89 + int mt9m111_power_down(struct sd *sd); 90 + 91 + int mt9m111_read_sensor(struct sd *sd, const u8 address, 92 + u8 *i2c_data, const u8 len); 93 + 94 + int mt9m111_write_sensor(struct sd *sd, const u8 address, 95 + u8 *i2c_data, const u8 len); 96 + 97 + void mt9m111_dump_registers(struct sd *sd); 98 + 99 + int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val); 100 + int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); 101 + int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); 102 + int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val); 103 + int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val); 104 + int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val); 105 + 106 + static 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 + 176 + static 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 + 209 + static 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
+544
drivers/media/video/gspca/m5602/m5602_ov9650.c
··· 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 + 21 + int 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 + 49 + int 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 + 93 + int 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 + 132 + sensor_found: 133 + sd->gspca_dev.cam.cam_mode = ov9650.modes; 134 + sd->gspca_dev.cam.nmodes = ov9650.nmodes; 135 + return 0; 136 + } 137 + 138 + int 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 + 164 + int 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 + 179 + int 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); 201 + out: 202 + return (err < 0) ? err : 0; 203 + } 204 + 205 + int 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 + 232 + out: 233 + return (err < 0) ? err : 0; 234 + } 235 + 236 + int 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 + 251 + int 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 + 272 + int 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 + 286 + int 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 + 301 + int 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 + 315 + int 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 + 330 + int 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 + 346 + int 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); 365 + out: 366 + return (err < 0) ? err : 0; 367 + } 368 + 369 + int 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 + 385 + int 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); 404 + out: 405 + return (err < 0) ? err : 0; 406 + } 407 + 408 + int 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); 422 + out: 423 + return (err < 0) ? err : 0; 424 + } 425 + 426 + int 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 + 450 + out: 451 + return (err < 0) ? err : 0; 452 + } 453 + 454 + int 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 + 467 + int 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); 480 + out: 481 + return (err < 0) ? err : 0; 482 + } 483 + 484 + int 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 + 497 + int 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); 510 + out: 511 + return (err < 0) ? err : 0; 512 + } 513 + 514 + void 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 + }
+501
drivers/media/video/gspca/m5602/m5602_ov9650.h
··· 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 */ 122 + extern int force_sensor; 123 + extern int dump_sensor; 124 + extern unsigned int m5602_debug; 125 + 126 + int ov9650_probe(struct sd *sd); 127 + int ov9650_init(struct sd *sd); 128 + int ov9650_power_down(struct sd *sd); 129 + 130 + int ov9650_read_sensor(struct sd *sd, const u8 address, 131 + u8 *i2c_data, const u8 len); 132 + int ov9650_write_sensor(struct sd *sd, const u8 address, 133 + u8 *i2c_data, const u8 len); 134 + 135 + void ov9650_dump_registers(struct sd *sd); 136 + 137 + int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val); 138 + int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); 139 + int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val); 140 + int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val); 141 + int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); 142 + int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); 143 + int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); 144 + int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); 145 + int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); 146 + int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val); 147 + int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); 148 + int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val); 149 + int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); 150 + int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val); 151 + int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val); 152 + int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val); 153 + int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val); 154 + int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val); 155 + 156 + static 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 + 284 + static 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 + 310 + static 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 + 447 + static 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 */ 469 + static 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
+334
drivers/media/video/gspca/m5602/m5602_po1030.c
··· 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 + 21 + int 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 + 59 + sensor_found: 60 + sd->gspca_dev.cam.cam_mode = po1030.modes; 61 + sd->gspca_dev.cam.nmodes = po1030.nmodes; 62 + return 0; 63 + } 64 + 65 + int 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 + 89 + int 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 + 131 + int 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 + 170 + int 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); 187 + out: 188 + return (err < 0) ? err : 0; 189 + } 190 + 191 + int 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 + 214 + out: 215 + return (err < 0) ? err : 0; 216 + } 217 + 218 + int 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 + 232 + int 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 + 245 + int 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 + 258 + int 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 + 271 + int 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 + 285 + int 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 + 298 + int po1030_power_down(struct sd *sd) 299 + { 300 + return 0; 301 + } 302 + 303 + void 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 + }
+478
drivers/media/video/gspca/m5602/m5602_po1030.h
··· 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 */ 122 + extern int force_sensor; 123 + extern int dump_sensor; 124 + extern unsigned int m5602_debug; 125 + 126 + int po1030_probe(struct sd *sd); 127 + int po1030_init(struct sd *sd); 128 + int po1030_power_down(struct sd *sd); 129 + 130 + void po1030_dump_registers(struct sd *sd); 131 + 132 + int po1030_read_sensor(struct sd *sd, const u8 address, 133 + u8 *i2c_data, const u8 len); 134 + int po1030_write_sensor(struct sd *sd, const u8 address, 135 + u8 *i2c_data, const u8 len); 136 + 137 + int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); 138 + int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val); 139 + int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val); 140 + int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val); 141 + int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); 142 + int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); 143 + int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); 144 + int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); 145 + 146 + static 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 + 227 + static 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 + 288 + static 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
+460
drivers/media/video/gspca/m5602/m5602_s5k4aa.c
··· 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 + 21 + int 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"); 78 + sensor_found: 79 + sd->gspca_dev.cam.cam_mode = s5k4aa.modes; 80 + sd->gspca_dev.cam.nmodes = s5k4aa.nmodes; 81 + return 0; 82 + } 83 + 84 + int 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 + } 120 + out: 121 + return (err < 0) ? err : 0; 122 + } 123 + 124 + int 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 + 168 + int 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 + 226 + int s5k4aa_power_down(struct sd *sd) 227 + { 228 + return 0; 229 + } 230 + 231 + int 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); 249 + out: 250 + return (err < 0) ? err : 0; 251 + } 252 + 253 + int 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); 269 + out: 270 + return (err < 0) ? err : 0; 271 + } 272 + 273 + int 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 + 287 + out: 288 + return (err < 0) ? err : 0; 289 + } 290 + 291 + int 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 + } 325 + out: 326 + return (err < 0) ? err : 0; 327 + } 328 + 329 + int 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); 342 + out: 343 + return (err < 0) ? err : 0; 344 + } 345 + 346 + int 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 + } 381 + out: 382 + return (err < 0) ? err : 0; 383 + } 384 + 385 + int 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 + 399 + out: 400 + return (err < 0) ? err : 0; 401 + } 402 + 403 + int 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 + 417 + out: 418 + return (err < 0) ? err : 0; 419 + } 420 + 421 + void 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 + }
+368
drivers/media/video/gspca/m5602/m5602_s5k4aa.h
··· 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 */ 64 + extern int force_sensor; 65 + extern int dump_sensor; 66 + extern unsigned int m5602_debug; 67 + 68 + int s5k4aa_probe(struct sd *sd); 69 + int s5k4aa_init(struct sd *sd); 70 + int s5k4aa_power_down(struct sd *sd); 71 + 72 + void s5k4aa_dump_registers(struct sd *sd); 73 + 74 + int s5k4aa_read_sensor(struct sd *sd, const u8 address, 75 + u8 *i2c_data, const u8 len); 76 + int s5k4aa_write_sensor(struct sd *sd, const u8 address, 77 + u8 *i2c_data, const u8 len); 78 + 79 + int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); 80 + int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val); 81 + int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); 82 + int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val); 83 + int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); 84 + int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val); 85 + int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val); 86 + int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val); 87 + 88 + static 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 + 169 + static 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 + 213 + static 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 + 342 + static 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
+331
drivers/media/video/gspca/m5602/m5602_s5k83a.c
··· 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 + 21 + int 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 + 63 + sensor_found: 64 + sd->gspca_dev.cam.cam_mode = s5k83a.modes; 65 + sd->gspca_dev.cam.nmodes = s5k83a.nmodes; 66 + return 0; 67 + } 68 + 69 + int 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 + 106 + out: 107 + return (err < 0) ? err : 0; 108 + } 109 + 110 + int 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 + 154 + int 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 + 192 + int s5k83a_power_down(struct sd *sd) 193 + { 194 + return 0; 195 + } 196 + 197 + void 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 + 239 + int 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 + 252 + int 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 + 279 + int 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 + 291 + int 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 + 303 + int 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 + 320 + int 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 + }
+444
drivers/media/video/gspca/m5602/m5602_s5k83a.h
··· 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 */ 37 + extern int force_sensor; 38 + extern int dump_sensor; 39 + extern unsigned int m5602_debug; 40 + 41 + 42 + int s5k83a_probe(struct sd *sd); 43 + int s5k83a_init(struct sd *sd); 44 + int s5k83a_power_down(struct sd *sd); 45 + 46 + void s5k83a_dump_registers(struct sd *sd); 47 + 48 + int s5k83a_read_sensor(struct sd *sd, const u8 address, 49 + u8 *i2c_data, const u8 len); 50 + int s5k83a_write_sensor(struct sd *sd, const u8 address, 51 + u8 *i2c_data, const u8 len); 52 + 53 + int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val); 54 + int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); 55 + int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val); 56 + int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val); 57 + int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val); 58 + int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val); 59 + 60 + static 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 + 129 + static 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 + */ 172 + static 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
+76
drivers/media/video/gspca/m5602/m5602_sensor.h
··· 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 */ 30 + enum 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 */ 39 + enum instruction { 40 + BRIDGE, 41 + SENSOR, 42 + SENSOR_LONG 43 + }; 44 + 45 + struct 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