1 From 0d55b08388f12c7c22cae9c6c745995d051624ba Mon Sep 17 00:00:00 2001
2 From: Zheng Ba <zheng.ba@intel.com>
3 Date: Thu, 1 Apr 2010 16:29:43 +0800
4 Subject: [PATCH 3/3] Moorestown Camera Imaging driver Beta 10.0
6 Patch-mainline: 2.6.35?
10 3469638 3469639 3469710 3469822 (high)
13 Changes from Beta 8.0:
15 3469056 3469058 (critical)
16 3469705 3469696 3469709 3469510 (medium)
18 Changes from Beta 7.0:
19 1. Fixed hsd sighting 3469681,3469682,3469683 (high)
21 Changes from Beta 6.0:
22 1. Fixed hsd sighting 3469668 (high)
23 2. Fixed ov5630 v4l2 view-finding dark issue
24 3. Enabled support for popular v4l2 applications (cheese, skype, ffmpeg)
26 Changes from Beta 5.1:
27 1. Fixed CRITICAL sighting 3469558 -- ciapp fails to launch with segment fault
28 2. Fixed HIGH sighting 3479513 -- ov5630 AWB unstable
29 3. Improved KMOT sensor 720p fps from 30 to 40
31 Changes from Beta 5.0:
32 Fixed a critical issue of camera driver not loading -- hsd 3469557
34 Main changes from Beta 4.0:
35 Fixed 4 HSD sightings: 3469392,3469099,3469470,3469500
37 Main changes from Beta 3.0:
38 Fixed 7 HSD sightings: 3469264,3469112,3469395,3469103,3469105,3469471,3469484
40 Main changes from Beta 2.0:
41 Fixed 6 HSD sightings: 3469047,3469315,3469317,3469101,3468409,3469391
43 Main changes from Beta 1.1:
44 1. Added interrupt mode for jpeg capture and KMOT viewfinding
45 2. Fixed HSD sighting 3469228 and 3469147
47 Main changes from Alpha2:
48 Enabled MIPI interface in ISP driver and KMOT sensor s5k4e1.
49 Enabled FIFO in ISP driver, which doubled the fps in view-finding mode.
50 Enabled Subdev Framework in CI kernel driver.
51 Enabled AF Continuous Mode.
52 Enabled AE scene evaluation.
54 Enabled the camera drivers in kernel:
55 Device Drivers --> Multimedia support --> Video For Linux
56 Device Drivers --> Mulitmedia support --> Video capture adapters -->
57 --> Moorestown Langwell Camera Imaging Subsystem support.
60 1. camera driver depends on GPIO library and I2C driver.
64 2. camera driver depends on videobuf-core and videobuf-dma-contig.
67 3. enable multimedia support and video capture.
68 CONFIG_MEDIA_SUPPORT=y
70 CONFIG_VIDEO_V4L2_COMMON=y
73 4. camera drivers incluing ISP, 5630, 5630-motor, s5k4e1, s5k4e1-motor, 2650,
76 CONFIG_VIDEO_MRST_ISP=y
77 CONFIG_VIDEO_MRST_OV5630=y
78 CONFIG_VIDEO_MRST_OV5630_MOTOR=y
79 CONFIG_VIDEO_MRST_S5K4E1=y
80 CONFIG_VIDEO_MRST_S5K4E1_MOTOR=y
81 CONFIG_VIDEO_MRST_FLASH=y
82 CONFIG_VIDEO_MRST_OV2650=y
83 CONFIG_VIDEO_MRST_OV9665=y
84 Signed-off-by: Zheng Ba <zheng.ba@intel.com>
86 drivers/media/video/mrstci/mrstflash/Kconfig | 9 +
87 drivers/media/video/mrstci/mrstflash/Makefile | 3 +
88 drivers/media/video/mrstci/mrstflash/mrstflash.c | 150 +++
89 drivers/media/video/mrstci/mrstov2650/Kconfig | 9 +
90 drivers/media/video/mrstci/mrstov2650/Makefile | 3 +
91 drivers/media/video/mrstci/mrstov2650/mrstov2650.c | 1190 ++++++++++++++++++++
92 drivers/media/video/mrstci/mrstov2650/ov2650.h | 766 +++++++++++++
93 drivers/media/video/mrstci/mrstov5630/Kconfig | 9 +
94 drivers/media/video/mrstci/mrstov5630/Makefile | 4 +
95 drivers/media/video/mrstci/mrstov5630/ov5630.c | 1153 +++++++++++++++++++
96 drivers/media/video/mrstci/mrstov5630/ov5630.h | 672 +++++++++++
97 .../media/video/mrstci/mrstov5630_motor/Kconfig | 9 +
98 .../media/video/mrstci/mrstov5630_motor/Makefile | 3 +
99 .../mrstci/mrstov5630_motor/mrstov5630_motor.c | 428 +++++++
100 .../video/mrstci/mrstov5630_motor/ov5630_motor.h | 86 ++
101 drivers/media/video/mrstci/mrstov9665/Kconfig | 9 +
102 drivers/media/video/mrstci/mrstov9665/Makefile | 3 +
103 drivers/media/video/mrstci/mrstov9665/mrstov9665.c | 972 ++++++++++++++++
104 drivers/media/video/mrstci/mrstov9665/ov9665.h | 263 +++++
105 drivers/media/video/mrstci/mrsts5k4e1/Kconfig | 9 +
106 drivers/media/video/mrstci/mrsts5k4e1/Makefile | 3 +
107 drivers/media/video/mrstci/mrsts5k4e1/mrsts5k4e1.c | 1024 +++++++++++++++++
108 drivers/media/video/mrstci/mrsts5k4e1/mrsts5k4e1.h | 662 +++++++++++
109 .../media/video/mrstci/mrsts5k4e1_motor/Kconfig | 9 +
110 .../media/video/mrstci/mrsts5k4e1_motor/Makefile | 3 +
111 .../mrstci/mrsts5k4e1_motor/mrsts5k4e1_motor.c | 430 +++++++
112 .../mrstci/mrsts5k4e1_motor/mrsts5k4e1_motor.h | 102 ++
113 27 files changed, 7983 insertions(+), 0 deletions(-)
114 create mode 100644 drivers/media/video/mrstci/mrstflash/Kconfig
115 create mode 100644 drivers/media/video/mrstci/mrstflash/Makefile
116 create mode 100644 drivers/media/video/mrstci/mrstflash/mrstflash.c
117 create mode 100644 drivers/media/video/mrstci/mrstov2650/Kconfig
118 create mode 100644 drivers/media/video/mrstci/mrstov2650/Makefile
119 create mode 100644 drivers/media/video/mrstci/mrstov2650/mrstov2650.c
120 create mode 100644 drivers/media/video/mrstci/mrstov2650/ov2650.h
121 create mode 100644 drivers/media/video/mrstci/mrstov5630/Kconfig
122 create mode 100644 drivers/media/video/mrstci/mrstov5630/Makefile
123 create mode 100644 drivers/media/video/mrstci/mrstov5630/ov5630.c
124 create mode 100644 drivers/media/video/mrstci/mrstov5630/ov5630.h
125 create mode 100644 drivers/media/video/mrstci/mrstov5630_motor/Kconfig
126 create mode 100644 drivers/media/video/mrstci/mrstov5630_motor/Makefile
127 create mode 100644 drivers/media/video/mrstci/mrstov5630_motor/mrstov5630_motor.c
128 create mode 100644 drivers/media/video/mrstci/mrstov5630_motor/ov5630_motor.h
129 create mode 100644 drivers/media/video/mrstci/mrstov9665/Kconfig
130 create mode 100644 drivers/media/video/mrstci/mrstov9665/Makefile
131 create mode 100644 drivers/media/video/mrstci/mrstov9665/mrstov9665.c
132 create mode 100644 drivers/media/video/mrstci/mrstov9665/ov9665.h
133 create mode 100755 drivers/media/video/mrstci/mrsts5k4e1/Kconfig
134 create mode 100644 drivers/media/video/mrstci/mrsts5k4e1/Makefile
135 create mode 100755 drivers/media/video/mrstci/mrsts5k4e1/mrsts5k4e1.c
136 create mode 100755 drivers/media/video/mrstci/mrsts5k4e1/mrsts5k4e1.h
137 create mode 100755 drivers/media/video/mrstci/mrsts5k4e1_motor/Kconfig
138 create mode 100644 drivers/media/video/mrstci/mrsts5k4e1_motor/Makefile
139 create mode 100644 drivers/media/video/mrstci/mrsts5k4e1_motor/mrsts5k4e1_motor.c
140 create mode 100644 drivers/media/video/mrstci/mrsts5k4e1_motor/mrsts5k4e1_motor.h
142 diff --git a/drivers/media/video/mrstci/mrstflash/Kconfig b/drivers/media/video/mrstci/mrstflash/Kconfig
144 index 0000000..72099c5
146 +++ b/drivers/media/video/mrstci/mrstflash/Kconfig
148 +config VIDEO_MRST_FLASH
149 + tristate "Moorestown flash"
150 + depends on I2C && VIDEO_MRST_ISP
153 + Say Y here if your platform support moorestown flash.
155 + To compile this driver as a module, choose M here: the
156 + module will be called mrstov2650.ko.
157 diff --git a/drivers/media/video/mrstci/mrstflash/Makefile b/drivers/media/video/mrstci/mrstflash/Makefile
159 index 0000000..068f638
161 +++ b/drivers/media/video/mrstci/mrstflash/Makefile
163 +obj-$(CONFIG_VIDEO_MRST_FLASH) += mrstflash.o
165 +EXTRA_CFLAGS += -I$(src)/../include
166 diff --git a/drivers/media/video/mrstci/mrstflash/mrstflash.c b/drivers/media/video/mrstci/mrstflash/mrstflash.c
168 index 0000000..5611e6b
170 +++ b/drivers/media/video/mrstci/mrstflash/mrstflash.c
173 + * Support for Moorestown Langwell Camera Imaging camera flash.
175 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
177 + * This program is free software; you can redistribute it and/or
178 + * modify it under the terms of the GNU General Public License version
179 + * 2 as published by the Free Software Foundation.
181 + * This program is distributed in the hope that it will be useful,
182 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
183 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
184 + * GNU General Public License for more details.
186 + * You should have received a copy of the GNU General Public License
187 + * along with this program; if not, write to the Free Software
188 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
192 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
195 +#include <linux/module.h>
196 +#include <linux/types.h>
197 +#include <linux/kernel.h>
198 +#include <linux/mm.h>
199 +#include <linux/string.h>
200 +#include <linux/errno.h>
201 +#include <linux/init.h>
202 +#include <linux/kmod.h>
203 +#include <linux/device.h>
204 +#include <linux/delay.h>
205 +#include <linux/fs.h>
206 +#include <linux/init.h>
207 +#include <linux/slab.h>
208 +#include <linux/delay.h>
209 +#include <linux/i2c.h>
210 +#include <linux/gpio.h>
211 +#include <linux/videodev2.h>
212 +#include <media/v4l2-device.h>
213 +#include <media/v4l2-chip-ident.h>
214 +#include <media/v4l2-i2c-drv.h>
217 +module_param(debug, bool, 0644);
218 +MODULE_PARM_DESC(debug, "Debug level (0-1)");
220 +MODULE_AUTHOR("Xiaolin Zhang <xiaolin.zhang@intel.com>");
221 +MODULE_DESCRIPTION("A low-level driver for mrst flash");
222 +MODULE_LICENSE("GPL");
224 +static int flash_g_chip_ident(struct v4l2_subdev *sd,
225 + struct v4l2_dbg_chip_ident *chip)
227 + struct i2c_client *client = v4l2_get_subdevdata(sd);
229 +#define V4L2_IDENT_MRST_FLASH 8248
230 + return v4l2_chip_ident_i2c_client(client, chip,
231 + V4L2_IDENT_MRST_FLASH, 0);
234 +static const struct v4l2_subdev_core_ops flash_core_ops = {
235 + .g_chip_ident = flash_g_chip_ident,
237 +static const struct v4l2_subdev_ops flash_ops = {
238 + .core = &flash_core_ops,
241 +static int flash_detect(struct i2c_client *client)
243 + struct i2c_adapter *adapter = client->adapter;
246 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
249 + if (adapter->nr != 0)
252 + pid = i2c_smbus_read_byte_data(client, 0x10);
254 + printk(KERN_ERR "camera flash device found\n");
255 + v4l_dbg(1, debug, client, "found camera flash device");
257 + printk(KERN_ERR "no camera flash device found\n");
264 +static int flash_probe(struct i2c_client *client,
265 + const struct i2c_device_id *id)
269 + struct v4l2_subdev *sd;
271 + v4l_info(client, "chip found @ 0x%x (%s)\n",
272 + client->addr << 1, client->adapter->name);
274 + sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
275 + ret = flash_detect(client);
279 + v4l2_i2c_subdev_init(sd, client, &flash_ops);
281 + ver = i2c_smbus_read_byte_data(client, 0x50);
282 + v4l_dbg(1, debug, client, "detect:CST from device is 0x%x", ver);
283 + pid = i2c_smbus_read_byte_data(client, 0x20);
284 + v4l_dbg(1, debug, client, "detect:MFPC from device is 0x%x", pid);
285 + pid = i2c_smbus_read_byte_data(client, 0xA0);
286 + v4l_dbg(1, debug, client, "detect:TCC from device is 0x%x", pid);
287 + pid = i2c_smbus_read_byte_data(client, 0xB0);
288 + v4l_dbg(1, debug, client, "detect:FCC from device is 0x%x", pid);
289 + pid = i2c_smbus_read_byte_data(client, 0xC0);
290 + v4l_dbg(1, debug, client, "detect:FDC from device is 0x%x", pid);
291 + i2c_smbus_write_byte_data(client, 0xc0, 0xff); /*set FST to 1000us*/
292 + pid = i2c_smbus_read_byte_data(client, 0xc0);
293 + v4l_dbg(1, debug, client, "FDC from device is 0x%x", pid);
295 + v4l_dbg(1, debug, client,
296 + "successfully load camera flash device driver");
300 +static int flash_remove(struct i2c_client *client)
302 + struct v4l2_subdev *sd = i2c_get_clientdata(client);
304 + v4l2_device_unregister_subdev(sd);
309 +static const struct i2c_device_id flash_id[] = {
310 + {"mrst_camera_flash", 0},
314 +MODULE_DEVICE_TABLE(i2c, flash_id);
316 +static struct v4l2_i2c_driver_data v4l2_i2c_data = {
317 + .name = "mrst_camera_flash",
318 + .probe = flash_probe,
319 + .remove = flash_remove,
320 + .id_table = flash_id,
322 diff --git a/drivers/media/video/mrstci/mrstov2650/Kconfig b/drivers/media/video/mrstci/mrstov2650/Kconfig
324 index 0000000..d39d894
326 +++ b/drivers/media/video/mrstci/mrstov2650/Kconfig
328 +config VIDEO_MRST_OV2650
329 + tristate "Moorestown OV2650 SoC Sensor"
330 + depends on I2C && VIDEO_MRST_ISP
333 + Say Y here if your platform support OV2650 SoC Sensor.
335 + To compile this driver as a module, choose M here: the
336 + module will be called mrstov2650.ko.
337 diff --git a/drivers/media/video/mrstci/mrstov2650/Makefile b/drivers/media/video/mrstci/mrstov2650/Makefile
339 index 0000000..fb16d57
341 +++ b/drivers/media/video/mrstci/mrstov2650/Makefile
343 +obj-$(CONFIG_VIDEO_MRST_OV2650) += mrstov2650.o
345 +EXTRA_CFLAGS += -I$(src)/../include
346 \ No newline at end of file
347 diff --git a/drivers/media/video/mrstci/mrstov2650/mrstov2650.c b/drivers/media/video/mrstci/mrstov2650/mrstov2650.c
349 index 0000000..7f0d478
351 +++ b/drivers/media/video/mrstci/mrstov2650/mrstov2650.c
354 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
356 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
358 + * This program is free software; you can redistribute it and/or
359 + * modify it under the terms of the GNU General Public License version
360 + * 2 as published by the Free Software Foundation.
362 + * This program is distributed in the hope that it will be useful,
363 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
364 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
365 + * GNU General Public License for more details.
367 + * You should have received a copy of the GNU General Public License
368 + * along with this program; if not, write to the Free Software
369 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
373 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
376 +#include <linux/module.h>
377 +#include <linux/types.h>
378 +#include <linux/kernel.h>
379 +#include <linux/mm.h>
380 +#include <linux/string.h>
381 +#include <linux/errno.h>
382 +#include <linux/init.h>
383 +#include <linux/kmod.h>
384 +#include <linux/device.h>
385 +#include <linux/delay.h>
386 +#include <linux/fs.h>
387 +#include <linux/init.h>
388 +#include <linux/slab.h>
389 +#include <linux/delay.h>
390 +#include <linux/i2c.h>
391 +#include <linux/gpio.h>
392 +#include <linux/videodev2.h>
393 +#include <media/v4l2-device.h>
394 +#include <media/v4l2-chip-ident.h>
395 +#include <media/v4l2-i2c-drv.h>
397 +#include "ci_sensor_common.h"
400 +static int mrstov2650_debug;
401 +module_param(mrstov2650_debug, int, 0644);
402 +MODULE_PARM_DESC(mrstov2650_debug, "Debug level (0-1)");
404 +#define dprintk(level, fmt, arg...) do { \
405 + if (mrstov2650_debug >= level) \
406 + printk(KERN_DEBUG "mrstisp@%s: " fmt "\n", \
407 + __func__, ## arg); } \
410 +#define eprintk(fmt, arg...) \
411 + printk(KERN_ERR "mrstisp@%s: line %d: " fmt "\n", \
412 + __func__, __LINE__, ## arg);
414 +#define DBG_entering dprintk(2, "entering");
415 +#define DBG_leaving dprintk(2, "leaving");
416 +#define DBG_line dprintk(2, " line: %d", __LINE__);
418 +static inline struct ci_sensor_config *to_sensor_config(struct v4l2_subdev *sd)
420 + return container_of(sd, struct ci_sensor_config, sd);
423 +static struct ov2650_format_struct {
426 + struct regval_list *regs;
427 +} ov2650_formats[] = {
429 + .desc = "YUYV 4:2:2",
430 + .pixelformat = SENSOR_MODE_BT601,
434 +#define N_OV2650_FMTS ARRAY_SIZE(ov2650_formats)
436 +static struct ov2650_res_struct {
441 + /* FIXME: correct the fps values.. */
444 + struct regval_list *regs;
448 + .res = SENSOR_RES_UXGA,
453 + .regs = ov2650_res_uxga,
457 + .res = SENSOR_RES_SXGA,
462 + .regs = ov2650_res_sxga,
466 + .res = SENSOR_RES_SVGA,
471 + .regs = ov2650_res_svga,
475 + .res = SENSOR_RES_VGA,
480 + .regs = ov2650_res_vga_vario,
484 + .res = SENSOR_RES_QVGA,
489 + .regs = ov2650_res_qvga,
493 +#define N_RES (ARRAY_SIZE(ov2650_res))
496 + * I2C Read & Write stuff
498 +static int ov2650_read(struct i2c_client *c, u16 reg, u8 *value)
502 + struct i2c_msg msg[2];
506 + /* Read needs two message to go */
507 + memset(&msg, 0, sizeof(msg));
511 + msgbuf[i++] = reg >> 8;
513 + msg[0].addr = c->addr;
514 + msg[0].buf = msgbuf;
517 + msg[1].addr = c->addr;
518 + msg[1].flags = I2C_M_RD;
519 + msg[1].buf = &ret_val;
522 + ret = i2c_transfer(c->adapter, &msg[0], 2);
525 + ret = (ret == 2) ? 0 : -1;
529 +static int ov2650_write(struct i2c_client *c, u16 reg, u8 value)
532 + struct i2c_msg msg;
535 + /* Writing only needs one message */
536 + memset(&msg, 0, sizeof(msg));
538 + msgbuf[i++] = reg >> 8;
540 + msgbuf[i++] = value;
542 + msg.addr = c->addr;
547 + ret = i2c_transfer(c->adapter, &msg, 1);
549 + /* If this is a reset register, wait for 1ms */
550 + if (reg == OV2650_SYS && (value & 0x80))
553 + ret = (ret == 1) ? 0 : -1;
557 +static int ov2650_write_array(struct i2c_client *c, struct regval_list *vals)
559 + struct regval_list *p;
564 + while (p->reg_num != 0xffff) {
565 + ov2650_write(c, p->reg_num, p->value);
566 + ov2650_read(c, p->reg_num, &read_val);
567 + if (read_val != p->value)
575 +static int ov2650_set_data_pin_in(struct i2c_client *client)
580 + ret += ov2650_write(client, 0x30b0, 0x00);
582 + ret += ov2650_read(client, 0x30b1, ®);
584 + ret += ov2650_write(client, 0x30b1, reg);
589 +static int ov2650_set_data_pin_out(struct i2c_client *client)
594 + ret += ov2650_write(client, 0x30b0, 0xff);
596 + ret += ov2650_read(client, 0x30b1, ®);
599 + ret += ov2650_write(client, 0x30b1, reg);
604 + * Sensor specific helper function
606 +static int ov2650_standby(void)
608 + gpio_set_value(GPIO_STDBY_PIN, 1);
609 + dprintk(1, "PM: standby called\n");
613 +static int ov2650_wakeup(void)
615 + gpio_set_value(GPIO_STDBY_PIN, 0);
616 + dprintk(1, "PM: wakeup called\n");
620 +static int ov2650_s_power(struct v4l2_subdev *sd, u32 val)
629 +static int ov2650_init(struct i2c_client *c)
632 + struct v4l2_subdev *sd = i2c_get_clientdata(c);
633 + struct ci_sensor_config *info = to_sensor_config(sd);
635 + /* Fill the configuration structure */
636 + /* Note this default configuration value */
637 + info->mode = ov2650_formats[0].pixelformat;
638 + info->res = ov2650_res[0].res;
639 + info->type = SENSOR_TYPE_SOC;
640 + info->bls = SENSOR_BLS_OFF;
641 + info->gamma = SENSOR_GAMMA_ON;
642 + info->cconv = SENSOR_CCONV_ON;
643 + info->blc = SENSOR_BLC_AUTO;
644 + info->agc = SENSOR_AGC_AUTO;
645 + info->awb = SENSOR_AWB_AUTO;
646 + info->aec = SENSOR_AEC_AUTO;
647 + info->bus_width = SENSOR_BUSWIDTH_8BIT_ZZ;
648 + info->ycseq = SENSOR_YCSEQ_YCBYCR;
649 + info->conv422 = SENSOR_CONV422_COSITED;
650 + info->bpat = SENSOR_BPAT_BGBGGRGR;/* GRGRBGBG; */
651 + info->field_inv = SENSOR_FIELDINV_NOSWAP;
652 + info->field_sel = SENSOR_FIELDSEL_BOTH;
653 + info->hpol = SENSOR_HPOL_REFPOS;
654 + info->vpol = SENSOR_VPOL_POS;
655 + info->edge = SENSOR_EDGE_RISING;
656 + info->flicker_freq = SENSOR_FLICKER_100;
657 + info->cie_profile = 0;
658 + memcpy(info->name, "ov2650", 7);
660 + ret = ov2650_write(c, OV2650_SYS, 0x80);
661 + /* Set registers into default config value */
662 + ret += ov2650_write_array(c, ov2650_def_reg);
664 + /* added by wen to stop sensor from streaming */
665 + ov2650_write(c, 0x3086, 0x0f);
666 + ov2650_set_data_pin_in(c);
672 +static int distance(struct ov2650_res_struct *res, u32 w, u32 h)
675 + if (res->width < w || res->height < h)
678 + ret = ((res->width - w) + (res->height - h));
682 +static int ov2650_try_res(u32 *w, u32 *h)
684 + struct ov2650_res_struct *res_index, *p = NULL;
685 + int dis, last_dis = ov2650_res->width + ov2650_res->height;
687 + dprintk(1, "&&&&& before %dx%d", *w, *h);
688 + for (res_index = ov2650_res;
689 + res_index < ov2650_res + N_RES;
691 + if ((res_index->width <= *w) && (res_index->height <= *h))
693 + dis = distance(res_index, *w, *h);
694 + if (dis < last_dis) {
699 + if ((res_index->width < *w) || (res_index->height < *h)) {
700 + if (res_index != ov2650_res)
709 + if ((w != NULL) && (h != NULL)) {
714 + if (res_index == ov2650_res + N_RES)
715 + res_index = ov2650_res + N_RES - 1;
717 + *w = res_index->width;
718 + *h = res_index->height;
720 + dprintk(1, "&&&&& after %dx%d", *w, *h);
724 +static struct ov2650_res_struct *ov2650_to_res(u32 w, u32 h)
726 + struct ov2650_res_struct *res_index;
728 + for (res_index = ov2650_res;
729 + res_index < ov2650_res + N_RES;
731 + if ((res_index->width == w) && (res_index->height == h))
734 + if (res_index >= ov2650_res + N_RES)
735 + res_index--; /* Take the bigger one */
740 +static int ov2650_try_fmt(struct v4l2_subdev *sd,
741 + struct v4l2_format *fmt)
744 + dprintk(1, "&&&&& before %dx%d", fmt->fmt.pix.width,
745 + fmt->fmt.pix.height);
746 + return ov2650_try_res(&fmt->fmt.pix.width, &fmt->fmt.pix.height);
747 + dprintk(1, "&&&&& after %dx%d", fmt->fmt.pix.width,
748 + fmt->fmt.pix.height);
752 +static int ov2650_get_fmt(struct v4l2_subdev *sd,
753 + struct v4l2_format *fmt)
755 + struct ci_sensor_config *info = to_sensor_config(sd);
756 + unsigned short width, height;
759 + ci_sensor_res2size(info->res, &width, &height);
761 + /* Marked the current sensor res as being "used" */
762 + for (index = 0; index < N_RES; index++) {
763 + if ((width == ov2650_res[index].width) &&
764 + (height == ov2650_res[index].height)) {
765 + ov2650_res[index].used = 1;
768 + ov2650_res[index].used = 0;
771 + fmt->fmt.pix.width = width;
772 + fmt->fmt.pix.height = height;
776 +static int ov2650_set_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
778 + struct i2c_client *client = v4l2_get_subdevdata(sd);
779 + struct ci_sensor_config *info = to_sensor_config(sd);
781 + struct ov2650_res_struct *res_index;
787 + width = fmt->fmt.pix.width;
788 + height = fmt->fmt.pix.height;
790 + ret = ov2650_try_res(&width, &height);
791 + res_index = ov2650_to_res(width, height);
795 + /* if ((info->res != res_index->res) && (res_index->regs)) { */
796 + if (res_index->regs) {
798 + dprintk(2, "changing res from to %dx%d", width, height);
799 + ret = ov2650_write(client, OV2650_SYS, 0x80);
800 + ret += ov2650_write_array(client, ov2650_def_reg);
801 + ret += ov2650_write_array(client, res_index->regs);
804 + if(res_index->res == SENSOR_RES_VGA) {
805 + ret += ov2650_write_array(c, ov2650_def_reg);
806 + ret += ov2650_write_array(c, res_index->regs);
808 + ret += ov2650_write_array(c, ov2650_res_vga_reverse);
809 + ret += ov2650_write_array(c, res_index->regs);
813 + /* Add delay here to get better image */
815 + if (res_index->res == SENSOR_RES_SXGA ||
816 + res_index->res == SENSOR_RES_UXGA)
822 + /* Marked current sensor res as being "used" */
823 + for (index = 0; index < N_RES; index++) {
824 + if ((width == ov2650_res[index].width) &&
825 + (height == ov2650_res[index].height)) {
826 + ov2650_res[index].used = 1;
829 + ov2650_res[index].used = 0;
832 + for (index = 0; index < N_RES; index++)
833 + dprintk(2, "index = %d, used = %d\n", index,
834 + ov2650_res[index].used);
838 + info->res = res_index->res;
842 + unsigned char value;
843 + printk(KERN_WARNING "2650 reg dumping start:\n");
844 + for(i = 0x3000; i <= 0x360B; i ++) {
845 + ov2650_read(c, i, &value);
846 + printk(KERN_WARNING "reg at offset %4x = %x\n", i, value);
848 + printk(KERN_WARNING "2650 reg dumping finished:\n");
856 +static int ov2650_q_hflip(struct v4l2_subdev *sd, __s32 *value)
858 + struct i2c_client *client = v4l2_get_subdevdata(sd);
862 + err = ov2650_read(client, OV2650_TMC_6, &v);
863 + *value = (v & 0x02) == 0x02;
867 +static int ov2650_t_hflip(struct v4l2_subdev *sd, int value)
869 + struct i2c_client *client = v4l2_get_subdevdata(sd);
870 + struct ci_sensor_config *info = to_sensor_config(sd);
871 + unsigned char v, v1 = 0;
874 + value = value >= 1 ? 1 : 0;
875 + err = ov2650_read(client, OV2650_TMC_6, &v);
879 + info->bpat = SENSOR_BPAT_GRGRBGBG;/*BGBGGRGR;*/
883 + info->bpat = SENSOR_BPAT_BGBGGRGR;
885 + err += ov2650_write(client, OV2650_TMC_6, v);
886 + err += ov2650_write(client, 0x3090, v1);
887 + msleep(10); /* FIXME */
892 +static int ov2650_q_vflip(struct v4l2_subdev *sd, __s32 *value)
894 + struct i2c_client *client = v4l2_get_subdevdata(sd);
898 + err = ov2650_read(client, OV2650_TMC_6, &v);
899 + *value = (v & 0x01) == 0x01;
904 +static int ov2650_t_vflip(struct v4l2_subdev *sd, int value)
906 + struct i2c_client *client = v4l2_get_subdevdata(sd);
910 + value = value >= 1 ? 1 : 0;
911 + err = ov2650_read(client, OV2650_TMC_6, &v);
916 + err += ov2650_write(client, OV2650_TMC_6, v);
917 + msleep(10); /* FIXME */
923 +static int ov2650_t_awb(struct i2c_client *c, int value)
927 + struct ci_sensor_config *info = i2c_get_clientdata(c);
929 + value = value >= 1 ? 1 : 0;
930 + ret = ov2650_read(c, OV2650_ISP_CTL_0, &v);
931 + if (value & 0x01) {
933 + info->awb = SENSOR_AWB_AUTO;
936 + info->awb = SENSOR_AWB_OFF;
938 + ret += ov2650_write(c, OV2650_ISP_CTL_0, v);
939 + msleep(10); /* FIXME */
944 +static int ov2650_q_awb(struct i2c_client *c, int *value)
949 + ret = ov2650_read(c, OV2650_ISP_CTL_0, &v);
950 + *value = (v & 0x30) == 0x30;
954 +static int ov2650_t_agc(struct i2c_client *c, int value)
958 + struct ci_sensor_config *info = i2c_get_clientdata(c);
960 + value = value >= 1 ? 1 : 0;
961 + ret = ov2650_read(c, OV2650_ISP_CTL_0, &v);
962 + if (value & 0x01) {
964 + info->agc = SENSOR_AGC_AUTO;
967 + info->agc = SENSOR_AGC_OFF;
969 + ret += ov2650_write(c, OV2650_ISP_CTL_0, v);
970 + msleep(10); /* FIXME */
975 +static int ov2650_q_agc(struct i2c_client *c, int *value)
980 + ret = ov2650_read(c, OV2650_ISP_CTL_0, &v);
981 + *value = (v & 0x10) == 0x10;
985 +static int ov2650_t_blc(struct i2c_client *c, int value)
990 + value = value >= 1 ? 1 : 0;
992 + ret = ov2650_read(c, OV2650_BLCC, &v);
997 + ret += ov2650_write(c, OV2650_BLCC, v);
998 + msleep(10); /* FIXME */
1003 +static int ov2650_q_blc(struct i2c_client *c, int *value)
1008 + ret = ov2650_read(c, OV2650_BLCC, &v);
1009 + *value = (v & 0x10) == 0x10;
1014 +static struct ov2650_control {
1015 + struct v4l2_queryctrl qc;
1016 + int (*query)(struct v4l2_subdev *sd, __s32 *value);
1017 + int (*tweak)(struct v4l2_subdev *sd, int value);
1018 +} ov2650_controls[] = {
1021 + .id = V4L2_CID_VFLIP,
1022 + .type = V4L2_CTRL_TYPE_BOOLEAN,
1023 + .name = "Vertical flip",
1027 + .default_value = 0,
1029 + .tweak = ov2650_t_vflip,
1030 + .query = ov2650_q_vflip,
1034 + .id = V4L2_CID_HFLIP,
1035 + .type = V4L2_CTRL_TYPE_BOOLEAN,
1036 + .name = "Horizontal mirror",
1040 + .default_value = 0,
1042 + .tweak = ov2650_t_hflip,
1043 + .query = ov2650_q_hflip,
1048 + .index = V4L2_CID_AUTO_WHITE_BALANCE,
1049 + .type = V4L2_CTRL_TYPE_BOOLEAN,
1050 + .name = "Auto White Balance",
1056 + .tweak = ov2650_t_awb,
1057 + .query = ov2650_q_awb,
1061 + .index = V4L2_CID_AUTOGAIN,
1062 + .type = V4L2_CTRL_TYPE_BOOLEAN,
1063 + .name = "Auto Gain Control",
1069 + .tweak = ov2650_t_agc,
1070 + .query = ov2650_q_agc,
1075 + .index = V4L2_CID_BLACK_LEVEL,
1076 + .type = V4L2_CTRL_TYPE_BOOLEAN,
1077 + .name = "Black Level Control",
1083 + .tweak = ov2650_t_blc,
1084 + .query = ov2650_q_blc,
1089 +#define N_CONTROLS (ARRAY_SIZE(ov2650_controls))
1091 +static struct ov2650_control *ov2650_find_control(__u32 id)
1095 + for (i = 0; i < N_CONTROLS; i++)
1096 + if (ov2650_controls[i].qc.id == id)
1097 + return ov2650_controls + i;
1101 +static int ov2650_queryctrl(struct v4l2_subdev *sd,
1102 + struct v4l2_queryctrl *qc)
1104 + struct ov2650_control *octrl;
1105 + octrl = ov2650_find_control(qc->id);
1106 + if (NULL == octrl)
1112 +static int ov2650_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
1114 + struct ov2650_control *octrl = ov2650_find_control(ctrl->id);
1117 + if (octrl == NULL)
1119 + ret = octrl->query(sd, &ctrl->value);
1125 +static int ov2650_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
1127 + struct ov2650_control *octrl = ov2650_find_control(ctrl->id);
1130 + if (octrl == NULL)
1132 + ret = octrl->tweak(sd, ctrl->value);
1138 +static int ov2650_get_caps(struct i2c_client *c, struct ci_sensor_caps *caps)
1143 + caps->bus_width = SENSOR_BUSWIDTH_8BIT_ZZ;
1144 + caps->mode = SENSOR_MODE_BT601;
1145 + caps->field_inv = SENSOR_FIELDINV_NOSWAP;
1146 + caps->field_sel = SENSOR_FIELDSEL_BOTH;
1147 + caps->ycseq = SENSOR_YCSEQ_YCBYCR;
1148 + caps->conv422 = SENSOR_CONV422_COSITED;
1149 + caps->bpat = SENSOR_BPAT_BGBGGRGR;
1150 + caps->hpol = SENSOR_HPOL_REFPOS;
1151 + caps->vpol = SENSOR_VPOL_POS;
1152 + caps->edge = SENSOR_EDGE_RISING;
1153 + caps->bls = SENSOR_BLS_OFF;
1154 + caps->gamma = SENSOR_GAMMA_ON;
1155 + caps->cconv = SENSOR_CCONV_ON;
1156 + caps->res = SENSOR_RES_UXGA | SENSOR_RES_SXGA | SENSOR_RES_SVGA
1157 + | SENSOR_RES_VGA | SENSOR_RES_QVGA;
1158 + caps->blc = SENSOR_BLC_AUTO;
1159 + caps->agc = SENSOR_AGC_AUTO;
1160 + caps->awb = SENSOR_AWB_AUTO;
1161 + caps->aec = SENSOR_AEC_AUTO;
1162 + caps->cie_profile = 0;
1163 + caps->flicker_freq = SENSOR_FLICKER_100 | SENSOR_FLICKER_120;
1164 + caps->type = SENSOR_TYPE_SOC;
1165 + /* caps->name = "ov2650"; */
1166 + strcpy(caps->name, "ov2650");
1171 +static int ov2650_get_config(struct i2c_client *c,
1172 + struct ci_sensor_config *config)
1174 + struct ci_sensor_config *info = i2c_get_clientdata(c);
1176 + if (config == NULL) {
1177 + printk(KERN_WARNING "sensor_get_config: NULL pointer\n");
1181 + memcpy(config, info, sizeof(struct ci_sensor_config));
1186 +static int ov2650_setup(struct i2c_client *c,
1187 + const struct ci_sensor_config *config)
1190 + struct ov2650_res_struct *res_index;
1191 + struct ci_sensor_config *info = i2c_get_clientdata(c);
1194 + /* Soft reset camera first*/
1195 + ret = ov2650_write(c, OV2650_SYS, 0x80);
1197 + /* Set registers into default config value */
1198 + ret += ov2650_write_array(c, ov2650_def_reg);
1200 + /* set image resolution */
1201 + ci_sensor_res2size(config->res, &width, &high);
1202 + ret += ov2650_try_res(c, &width, &high);
1203 + res_index = ov2650_find_res(width, high);
1204 + if (res_index->regs)
1205 + ret += ov2650_write_array(c, res_index->regs);
1207 + info->res = res_index->res;
1210 + if (config->blc != info->blc) {
1211 + ret += ov2650_t_blc(c, config->blc);
1212 + info->blc = config->blc;
1215 + if (config->agc != info->agc) {
1216 + ret += ov2650_t_agc(c, config->agc);
1217 + info->agc = config->agc;
1220 + if (config->awb != info->awb) {
1221 + ret += ov2650_t_awb(c, config->awb);
1222 + info->awb = config->awb;
1224 + /* Add some delay here to get a better image*/
1225 + if (res_index->res == SENSOR_RES_SXGA ||
1226 + res_index->res == SENSOR_RES_UXGA)
1235 + * File operation functions
1240 +static int ov2650_open(struct i2c_setting *c, void *priv)
1242 + struct i2c_client *client = c->sensor_client;
1243 + /* Just wake up sensor */
1244 + if (ov2650_wakeup())
1246 + ov2650_init(client);
1247 + /*Sleep sensor now*/
1248 + ov2650_write(client, 0x3086, 0x0f);
1250 + /* set data pin to input */
1251 + if (ov2650_set_data_pin_in(client))
1257 +static int ov2650_release(struct i2c_setting *c, void *priv)
1259 + /* Just suspend the sensor */
1264 +static int ov2650_on(struct i2c_setting *c)
1268 + /* Software wake up sensor */
1269 + ret = ov2650_write(c->sensor_client, 0x3086, 0x00);
1271 + /* set data pin to output */
1272 + return ret + ov2650_set_data_pin_out(c->sensor_client);
1275 +static int ov2650_off(struct i2c_setting *c)
1279 + /* Software standby sensor */
1280 + ret = ov2650_write(c->sensor_client, 0x3086, 0x0f);
1282 + /* set data pin to input */
1283 + return ret + ov2650_set_data_pin_in(c->sensor_client);
1286 +static struct sensor_device ov2650 = {
1288 + .type = SENSOR_TYPE_SOC,
1290 + .open = ov2650_open,
1291 + .release = ov2650_release,
1293 + .off = ov2650_off,
1294 + .querycap = ov2650_get_caps,
1295 + .get_config = ov2650_get_config,
1296 + .set_config = ov2650_setup,
1297 + .enum_parm = ov2650_queryctrl,
1298 + .get_parm = ov2650_g_ctrl,
1299 + .set_parm = ov2650_s_ctrl,
1300 + .try_res = ov2650_try_res,
1301 + .set_res = ov2650_set_res,
1302 + .suspend = ov2650_standby,
1303 + .resume = ov2650_wakeup,
1304 + .get_ls_corr_config = NULL,
1312 +static int ov2650_s_stream(struct v4l2_subdev *sd, int enable)
1314 + struct i2c_client *client = v4l2_get_subdevdata(sd);
1320 + ov2650_write(client, 0x3086, 0x00);
1321 + ov2650_set_data_pin_out(client);
1324 + ov2650_write(client, 0x3086, 0x0f);
1325 + ov2650_set_data_pin_in(client);
1332 +static int ov2650_enum_framesizes(struct v4l2_subdev *sd,
1333 + struct v4l2_frmsizeenum *fsize)
1335 + unsigned int index = fsize->index;
1339 + if (index >= N_RES)
1342 + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1343 + fsize->discrete.width = ov2650_res[index].width;
1344 + fsize->discrete.height = ov2650_res[index].height;
1345 + fsize->reserved[0] = ov2650_res[index].used;
1352 +static int ov2650_enum_frameintervals(struct v4l2_subdev *sd,
1353 + struct v4l2_frmivalenum *fival)
1355 + unsigned int index = fival->index;
1359 + if (index >= N_RES)
1362 + fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
1363 + fival->discrete.numerator = 1;
1364 + fival->discrete.denominator = ov2650_res[index].fps;
1370 +static int ov2650_g_chip_ident(struct v4l2_subdev *sd,
1371 + struct v4l2_dbg_chip_ident *chip)
1373 + struct i2c_client *client = v4l2_get_subdevdata(sd);
1375 +#define V4L2_IDENT_OV2650 8244
1376 + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV2650, 0);
1379 +#ifdef CONFIG_VIDEO_ADV_DEBUG
1380 +static int ov2650_g_register(struct v4l2_subdev *sd,
1381 + struct v4l2_dbg_register *reg)
1383 + struct i2c_client *client = v4l2_get_subdevdata(sd);
1384 + unsigned char val = 0;
1387 + if (!v4l2_chip_match_i2c_client(client, ®->match))
1389 + if (!capable(CAP_SYS_ADMIN))
1391 + ret = ov2650_read(client, reg->reg & 0xffff, &val);
1397 +static int ov2650_s_register(struct v4l2_subdev *sd,
1398 + struct v4l2_dbg_register *reg)
1400 + struct i2c_client *client = v4l2_get_subdevdata(sd);
1402 + if (!v4l2_chip_match_i2c_client(client, ®->match))
1404 + if (!capable(CAP_SYS_ADMIN))
1406 + ov2650_write(client, reg->reg & 0xffff, reg->val & 0xff);
1411 +static const struct v4l2_subdev_video_ops ov2650_video_ops = {
1412 + .try_fmt = ov2650_try_fmt,
1413 + .s_fmt = ov2650_set_fmt,
1414 + .g_fmt = ov2650_get_fmt,
1415 + .s_stream = ov2650_s_stream,
1416 + .enum_framesizes = ov2650_enum_framesizes,
1417 + .enum_frameintervals = ov2650_enum_frameintervals,
1420 +static const struct v4l2_subdev_core_ops ov2650_core_ops = {
1421 + .g_chip_ident = ov2650_g_chip_ident,
1422 + .queryctrl = ov2650_queryctrl,
1423 + .g_ctrl = ov2650_g_ctrl,
1424 + .s_ctrl = ov2650_s_ctrl,
1425 + .s_gpio = ov2650_s_power,
1426 + /*.g_ext_ctrls = ov2650_g_ext_ctrls,*/
1427 + /*.s_ext_ctrls = ov2650_s_ext_ctrls,*/
1428 +#ifdef CONFIG_VIDEO_ADV_DEBUG
1429 + .g_register = ov2650_g_register,
1430 + .s_register = ov2650_s_register,
1434 +static const struct v4l2_subdev_ops ov2650_ops = {
1435 + .core = &ov2650_core_ops,
1436 + .video = &ov2650_video_ops,
1443 +static unsigned short normal_i2c[] = {I2C_OV2650 >> 1, I2C_CLIENT_END};
1446 +static struct i2c_driver ov2650_driver;
1448 +static int ov2650_detect(struct i2c_client *client)
1450 + struct i2c_adapter *adapter = client->adapter;
1451 + int adap_id = i2c_adapter_id(adapter);
1454 + printk(KERN_WARNING "Now start ov2650 detect\n");
1455 + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
1461 + /* if (ov2650_wakeup()) */
1462 + /* return -ENODEV; */
1465 + ov2650_read(client, OV2650_PID_L, &value);
1466 + if (value != 0x52)
1472 +static int ov2650_probe(struct i2c_client *client,
1473 + const struct i2c_device_id *id)
1475 + struct ci_sensor_config *info;
1476 + struct v4l2_subdev *sd;
1481 + printk(KERN_INFO "Init ov2650 sensor \n");
1483 + v4l_info(client, "chip found @ 0x%x (%s)\n",
1484 + client->addr << 1, client->adapter->name);
1486 + * Setup sensor configuration structure
1488 + info = kzalloc(sizeof(struct ci_sensor_config), GFP_KERNEL);
1492 + ret = ov2650_detect(client);
1499 + v4l2_i2c_subdev_init(sd, client, &ov2650_ops);
1502 + * TODO: Need to check if this can be here.
1503 + * Turn into standby mode
1505 + /* ov2650_standby(); */
1506 + ret += ov2650_init(client);
1509 + printk(KERN_INFO "Init ov2650 sensor success, ret = %d\n", ret);
1515 +static int ov2650_remove(struct i2c_client *client)
1517 + struct v4l2_subdev *sd = i2c_get_clientdata(client);
1519 + v4l2_device_unregister_subdev(sd);
1520 + kfree(to_sensor_config(sd));
1524 +static const struct i2c_device_id ov2650_id[] = {
1529 +MODULE_DEVICE_TABLE(i2c, ov2650_id);
1531 +static struct v4l2_i2c_driver_data v4l2_i2c_data = {
1533 + .probe = ov2650_probe,
1534 + .remove = ov2650_remove,
1535 + /* .suspend = ov2650_suspend,
1536 + * .resume = ov2650_resume, */
1537 + .id_table = ov2650_id,
1540 +MODULE_AUTHOR("Xiaolin Zhang <xiaolin.zhang@intel.com>");
1541 +MODULE_DESCRIPTION("A low-level driver for OmniVision 2650 sensors");
1542 +MODULE_LICENSE("GPL");
1543 diff --git a/drivers/media/video/mrstci/mrstov2650/ov2650.h b/drivers/media/video/mrstci/mrstov2650/ov2650.h
1544 new file mode 100644
1545 index 0000000..f5c0418
1547 +++ b/drivers/media/video/mrstci/mrstov2650/ov2650.h
1550 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
1552 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
1554 + * This program is free software; you can redistribute it and/or
1555 + * modify it under the terms of the GNU General Public License version
1556 + * 2 as published by the Free Software Foundation.
1558 + * This program is distributed in the hope that it will be useful,
1559 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1560 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1561 + * GNU General Public License for more details.
1563 + * You should have received a copy of the GNU General Public License
1564 + * along with this program; if not, write to the Free Software
1565 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
1566 + * 02110-1301, USA.
1569 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
1572 +#define I2C_OV2650 0x60
1573 +/* Should add to kernel source */
1574 +#define I2C_DRIVERID_OV2650 1047
1575 +/* GPIO pin on Moorestown */
1576 +#define GPIO_SCLK_25 44
1577 +#define GPIO_STB_PIN 47
1578 +#define GPIO_STDBY_PIN 48
1579 +#define GPIO_RESET_PIN 50
1581 +/* System control register */
1582 +#define OV2650_AGC 0x3000
1583 +#define OV2650_AGCS 0x3001
1584 +#define OV2650_AEC_H 0x3002
1585 +#define OV2650_AEC_L 0x3003
1586 +#define OV2650_AECL 0x3004
1587 +#define OV2650_AECS_H 0x3008
1588 +#define OV2650_AECS_L 0x3009
1589 +#define OV2650_PID_H 0x300A
1590 +#define OV2650_PID_L 0x300B
1591 +#define OV2650_SCCB 0x300C
1592 +#define OV2650_PCLK 0x300D
1593 +#define OV2650_PLL_1 0x300E
1594 +#define OV2650_PLL_2 0x300F
1595 +#define OV2650_PLL_3 0x3010
1596 +#define OV2650_CLK 0x3011
1597 +#define OV2650_SYS 0x3012
1598 +#define OV2650_AUTO_1 0x3013
1599 +#define OV2650_AUTO_2 0x3014
1600 +#define OV2650_AUTO_3 0x3015
1601 +#define OV2650_AUTO_4 0x3016
1602 +#define OV2650_AUTO_5 0x3017
1603 +#define OV2650_WPT 0x3018
1604 +#define OV2650_BPT 0x3019
1605 +#define OV2650_VPT 0x301A
1606 +#define OV2650_YAVG 0x301B
1607 +#define OV2650_AECG_50 0x301C
1608 +#define OV2650_AECG_60 0x301D
1609 +#define OV2650_RZM_H 0x301E
1610 +#define OV2650_RZM_L 0x301F
1611 +#define OV2650_HS_H 0x3020
1612 +#define OV2650_HS_L 0x3021
1613 +#define OV2650_VS_H 0x3022
1614 +#define OV2650_VS_L 0x3023
1615 +#define OV2650_HW_H 0x3024
1616 +#define OV2650_HW_L 0x3025
1617 +#define OV2650_VH_H 0x3026
1618 +#define OV2650_VH_L 0x3027
1619 +#define OV2650_HTS_H 0x3028
1620 +#define OV2650_HTS_L 0x3029
1621 +#define OV2650_VTS_H 0x302A
1622 +#define OV2650_VTS_L 0x302B
1623 +#define OV2650_EXHTS 0x302C
1624 +#define OV2650_EXVTS_H 0x302D
1625 +#define OV2650_EXVTS_L 0x302E
1626 +#define OV2650_WET_0 0x3030
1627 +#define OV2650_WET_1 0x3031
1628 +#define OV2650_WET_2 0x3032
1629 +#define OV2650_WET_3 0x3033
1630 +#define OV2650_AHS_H 0x3038
1631 +#define OV2650_AHS_L 0x3039
1632 +#define OV2650_AVS_H 0x303A
1633 +#define OV2650_AVS_L 0x303B
1634 +#define OV2650_AHW_H 0x303C
1635 +#define OV2650_AHW_L 0x303D
1636 +#define OV2650_AVH_H 0x303E
1637 +#define OV2650_AVH_L 0x303F
1638 +#define OV2650_HISTO_0 0x3040
1639 +#define OV2650_HISTO_1 0x3041
1640 +#define OV2650_HISTO_2 0x3042
1641 +#define OV2650_HISTO_3 0x3043
1642 +#define OV2650_HISTO_4 0x3044
1643 +#define OV2650_BLC9A 0x3069
1644 +#define OV2650_BLCC 0x306C
1645 +#define OV2650_BLCD 0x306D
1646 +#define OV2650_BLCF 0x306F
1647 +#define OV2650_BD50_L 0x3070
1648 +#define OV2650_BD50_H 0x3071
1649 +#define OV2650_BD60_L 0x3072
1650 +#define OV2650_BD60_H 0x3073
1651 +#define OV2650_TMC_0 0x3076
1652 +#define OV2650_TMC_1 0x3077
1653 +#define OV2650_TMC_2 0x3078
1654 +#define OV2650_TMC_4 0x307A
1655 +#define OV2650_TMC_6 0x307C
1656 +#define OV2650_TMC_8 0x307E
1657 +#define OV2650_TMC_I2C 0x3084
1658 +#define OV2650_TMC_10 0x3086
1659 +#define OV2650_TMC_11 0x3087
1660 +#define OV2650_ISP_XO_H 0x3088
1661 +#define OV2650_ISP_XO_L 0x3089
1662 +#define OV2650_ISP_YO_H 0x308A
1663 +#define OV2650_ISP_YO_L 0x308B
1664 +#define OV2650_TMC_12 0x308C
1665 +#define OV2650_TMC_13 0x308D
1666 +#define OV2650_EFUSE 0x308F
1667 +#define OV2650_IO_CTL_0 0x30B0
1668 +#define OV2650_IO_CRL_1 0x30B1
1669 +#define OV2650_IO_CTL_2 0x30B2
1670 +#define OV2650_LAEC 0x30F0
1671 +#define OV2650_GRP_EOP 0x30FF
1674 +#define OV2650_SC_CTL_0 0x3100
1675 +#define OV2650_SC_SYN_CTL_0 0x3104
1676 +#define OV2650_SC_SYN_CTL_1 0x3105
1677 +#define OV2650_SC_SYN_CTL_3 0x3107
1678 +#define OV2650_SC_SYN_CTL_4 0x3108
1680 +/* DSP control register */
1681 +#define OV2650_ISP_CTL_0 0x3300
1682 +#define OV2650_ISP_CTL_1 0x3301
1683 +#define OV2650_ISP_CTL_2 0x3302
1684 +#define OV2650_ISP_CTL_3 0x3303
1685 +#define OV2650_ISP_CTL_4 0x3304
1686 +#define OV2650_ISP_CTL_5 0x3305
1687 +#define OV2650_ISP_CTL_6 0x3306
1688 +#define OV2650_ISP_CTL_7 0x3307
1689 +#define OV2650_ISP_CTL_8 0x3308
1690 +#define OV2650_ISP_CTL_9 0x3309
1691 +#define OV2650_ISP_CTL_A 0x330A
1692 +#define OV2650_ISP_CTL_B 0x330B
1693 +#define OV2650_ISP_CTL_10 0x3310
1694 +#define OV2650_ISP_CTL_11 0x3311
1695 +#define OV2650_ISP_CTL_12 0x3312
1696 +#define OV2650_ISP_CTL_13 0x3313
1697 +#define OV2650_ISP_CTL_14 0x3314
1698 +#define OV2650_ISP_CTL_15 0x3315
1699 +#define OV2650_ISP_CTL_16 0x3316
1700 +#define OV2650_ISP_CTL_17 0x3317
1701 +#define OV2650_ISP_CTL_18 0x3318
1702 +#define OV2650_ISP_CTL_19 0x3319
1703 +#define OV2650_ISP_CTL_1A 0x331A
1704 +#define OV2650_ISP_CTL_1B 0x331B
1705 +#define OV2650_ISP_CTL_1C 0x331C
1706 +#define OV2650_ISP_CTL_1D 0x331D
1707 +#define OV2650_ISP_CTL_1E 0x331E
1708 +#define OV2650_ISP_CTL_20 0x3320
1709 +#define OV2650_ISP_CTL_21 0x3321
1710 +#define OV2650_ISP_CTL_22 0x3322
1711 +#define OV2650_ISP_CTL_23 0x3323
1712 +#define OV2650_ISP_CTL_24 0x3324
1713 +#define OV2650_ISP_CTL_27 0x3327
1714 +#define OV2650_ISP_CTL_28 0x3328
1715 +#define OV2650_ISP_CTL_29 0x3329
1716 +#define OV2650_ISP_CTL_2A 0x332A
1717 +#define OV2650_ISP_CTL_2B 0x332B
1718 +#define OV2650_ISP_CTL_2C 0x332C
1719 +#define OV2650_ISP_CTL_2D 0x332D
1720 +#define OV2650_ISP_CTL_2E 0x332E
1721 +#define OV2650_ISP_CTL_2F 0x332F
1722 +#define OV2650_ISP_CTL_30 0x3330
1723 +#define OV2650_ISP_CTL_31 0x3331
1724 +#define OV2650_ISP_CTL_32 0x3332
1725 +#define OV2650_ISP_CTL_33 0x3333
1726 +#define OV2650_ISP_CTL_34 0x3334
1727 +#define OV2650_ISP_CTL_35 0x3335
1728 +#define OV2650_ISP_CTL_36 0x3336
1729 +#define OV2650_ISP_CTL_40 0x3340
1730 +#define OV2650_ISP_CTL_41 0x3341
1731 +#define OV2650_ISP_CTL_42 0x3342
1732 +#define OV2650_ISP_CTL_43 0x3343
1733 +#define OV2650_ISP_CTL_44 0x3344
1734 +#define OV2650_ISP_CTL_45 0x3345
1735 +#define OV2650_ISP_CTL_46 0x3346
1736 +#define OV2650_ISP_CTL_47 0x3347
1737 +#define OV2650_ISP_CTL_48 0x3348
1738 +#define OV2650_ISP_CTL_49 0x3349
1739 +#define OV2650_ISP_CTL_4A 0x334A
1740 +#define OV2650_ISP_CTL_4B 0x334B
1741 +#define OV2650_ISP_CTL_4C 0x334C
1742 +#define OV2650_ISP_CTL_4D 0x334D
1743 +#define OV2650_ISP_CTL_4E 0x334E
1744 +#define OV2650_ISP_CTL_4F 0x334F
1745 +#define OV2650_ISP_CTL_50 0x3350
1746 +#define OV2650_ISP_CTL_51 0x3351
1747 +#define OV2650_ISP_CTL_52 0x3352
1748 +#define OV2650_ISP_CTL_53 0x3353
1749 +#define OV2650_ISP_CTL_54 0x3354
1750 +#define OV2650_ISP_CTL_55 0x3355
1751 +#define OV2650_ISP_CTL_56 0x3356
1752 +#define OV2650_ISP_CTL_57 0x3357
1753 +#define OV2650_ISP_CTL_58 0x3358
1754 +#define OV2650_ISP_CTL_59 0x3359
1755 +#define OV2650_ISP_CTL_5A 0x335A
1756 +#define OV2650_ISP_CTL_5B 0x335B
1757 +#define OV2650_ISP_CTL_5C 0x335C
1758 +#define OV2650_ISP_CTL_5D 0x335D
1759 +#define OV2650_ISP_CTL_5E 0x335E
1760 +#define OV2650_ISP_CTL_5F 0x335F
1761 +#define OV2650_ISP_CTL_60 0x3360
1762 +#define OV2650_ISP_CTL_61 0x3361
1763 +#define OV2650_ISP_CTL_62 0x3362
1764 +#define OV2650_ISP_CTL_63 0x3363
1765 +#define OV2650_ISP_CTL_64 0x3364
1766 +#define OV2650_ISP_CTL_65 0x3365
1767 +#define OV2650_ISP_CTL_6A 0x336A
1768 +#define OV2650_ISP_CTL_6B 0x336B
1769 +#define OV2650_ISP_CTL_6C 0x336C
1770 +#define OV2650_ISP_CTL_6E 0x336E
1771 +#define OV2650_ISP_CTL_71 0x3371
1772 +#define OV2650_ISP_CTL_72 0x3372
1773 +#define OV2650_ISP_CTL_73 0x3373
1774 +#define OV2650_ISP_CTL_74 0x3374
1775 +#define OV2650_ISP_CTL_75 0x3375
1776 +#define OV2650_ISP_CTL_76 0x3376
1777 +#define OV2650_ISP_CTL_77 0x3377
1778 +#define OV2650_ISP_CTL_78 0x3378
1779 +#define OV2650_ISP_CTL_79 0x3379
1780 +#define OV2650_ISP_CTL_7A 0x337A
1781 +#define OV2650_ISP_CTL_7B 0x337B
1782 +#define OV2650_ISP_CTL_7C 0x337C
1783 +#define OV2650_ISP_CTL_80 0x3380
1784 +#define OV2650_ISP_CTL_81 0x3381
1785 +#define OV2650_ISP_CTL_82 0x3382
1786 +#define OV2650_ISP_CTL_83 0x3383
1787 +#define OV2650_ISP_CTL_84 0x3384
1788 +#define OV2650_ISP_CTL_85 0x3385
1789 +#define OV2650_ISP_CTL_86 0x3386
1790 +#define OV2650_ISP_CTL_87 0x3387
1791 +#define OV2650_ISP_CTL_88 0x3388
1792 +#define OV2650_ISP_CTL_89 0x3389
1793 +#define OV2650_ISP_CTL_8A 0x338A
1794 +#define OV2650_ISP_CTL_8B 0x338B
1795 +#define OV2650_ISP_CTL_8C 0x338C
1796 +#define OV2650_ISP_CTL_8D 0x338D
1797 +#define OV2650_ISP_CTL_8E 0x338E
1798 +#define OV2650_ISP_CTL_90 0x3390
1799 +#define OV2650_ISP_CTL_91 0x3391
1800 +#define OV2650_ISP_CTL_92 0x3392
1801 +#define OV2650_ISP_CTL_93 0x3393
1802 +#define OV2650_ISP_CTL_94 0x3394
1803 +#define OV2650_ISP_CTL_95 0x3395
1804 +#define OV2650_ISP_CTL_96 0x3396
1805 +#define OV2650_ISP_CTL_97 0x3397
1806 +#define OV2650_ISP_CTL_98 0x3398
1807 +#define OV2650_ISP_CTL_99 0x3399
1808 +#define OV2650_ISP_CTL_9A 0x339A
1809 +#define OV2650_ISP_CTL_A0 0x33A0
1810 +#define OV2650_ISP_CTL_A1 0x33A1
1811 +#define OV2650_ISP_CTL_A2 0x33A2
1812 +#define OV2650_ISP_CTL_A3 0x33A3
1813 +#define OV2650_ISP_CTL_A4 0x33A4
1814 +#define OV2650_ISP_CTL_A5 0x33A5
1815 +#define OV2650_ISP_CTL_A6 0x33A6
1816 +#define OV2650_ISP_CTL_A7 0x33A7
1817 +#define OV2650_ISP_CTL_A8 0x33A8
1818 +#define OV2650_ISP_CTL_AA 0x33AA
1819 +#define OV2650_ISP_CTL_AB 0x33AB
1820 +#define OV2650_ISP_CTL_AC 0x33AC
1821 +#define OV2650_ISP_CTL_AD 0x33AD
1822 +#define OV2650_ISP_CTL_AE 0x33AE
1823 +#define OV2650_ISP_CTL_AF 0x33AF
1824 +#define OV2650_ISP_CTL_B0 0x33B0
1825 +#define OV2650_ISP_CTL_B1 0x33B1
1826 +#define OV2650_ISP_CTL_B2 0x33B2
1827 +#define OV2650_ISP_CTL_B3 0x33B3
1828 +#define OV2650_ISP_CTL_B4 0x33B4
1829 +#define OV2650_ISP_CTL_B5 0x33B5
1830 +#define OV2650_ISP_CTL_B6 0x33B6
1831 +#define OV2650_ISP_CTL_B7 0x33B7
1832 +#define OV2650_ISP_CTL_B8 0x33B8
1833 +#define OV2650_ISP_CTL_B9 0x33B9
1835 +/* Format register */
1836 +#define OV2650_FMT_CTL_0 0x3400
1837 +#define OV2650_FMT_CTL_1 0x3401
1838 +#define OV2650_FMT_CTL_2 0x3402
1839 +#define OV2650_FMT_CTL_3 0x3403
1840 +#define OV2650_FMT_CTL_4 0x3404
1841 +#define OV2650_FMT_CTL_5 0x3405
1842 +#define OV2650_FMT_CTL_6 0x3406
1843 +#define OV2650_FMT_CTL_7 0x3407
1844 +#define OV2650_FMT_CTL_8 0x3408
1845 +#define OV2650_DITHER_CTL 0x3409
1846 +#define OV2650_DVP_CTL_0 0x3600
1847 +#define OV2650_DVP_CTL_1 0x3601
1848 +#define OV2650_DVP_CTL_6 0x3606
1849 +#define OV2650_DVP_CTL_7 0x3607
1850 +#define OV2650_DVP_CTL_9 0x3609
1851 +#define OV2650_DVP_CTL_B 0x360B
1853 +/* General definition for ov2650 */
1854 +#define OV2650_OUTWND_MAX_H UXGA_SIZE_H
1855 +#define OV2650_OUTWND_MAX_V UXGA_SIZE_V
1857 +struct regval_list {
1863 + * Default register value
1866 +static struct regval_list ov2650_def_reg[] = {
2071 +static struct regval_list ov2650_res_svga[] = {
2136 +static struct regval_list ov2650_res_vga_vario[] = {
2174 + {0x3014, 0x84}, /* note this */
2180 +/* 640x480 reverse */
2182 +static struct regval_list ov2650_res_vga_reverse[] = {
2228 +static struct regval_list ov2650_res_qvga[] = {
2258 + {0x3015, 0x02}, /* note this */
2266 +static struct regval_list ov2650_res_uxga[] = {
2267 + /* Note this added by debug */
2279 +static struct regval_list ov2650_res_sxga[] = {
2315 diff --git a/drivers/media/video/mrstci/mrstov5630/Kconfig b/drivers/media/video/mrstci/mrstov5630/Kconfig
2316 new file mode 100644
2317 index 0000000..a28ddc2
2319 +++ b/drivers/media/video/mrstci/mrstov5630/Kconfig
2321 +config VIDEO_MRST_OV5630
2322 + tristate "Moorestown OV5630 RAW Sensor"
2323 + depends on I2C && VIDEO_MRST_ISP
2326 + Say Y here if your platform support OV5630 RAW Sensor.
2328 + To compile this driver as a module, choose M here: the
2329 + module will be called mrstov2650.ko.
2330 diff --git a/drivers/media/video/mrstci/mrstov5630/Makefile b/drivers/media/video/mrstci/mrstov5630/Makefile
2331 new file mode 100644
2332 index 0000000..c67abff
2334 +++ b/drivers/media/video/mrstci/mrstov5630/Makefile
2336 +mrstov5630-objs = ov5630.o
2337 +obj-$(CONFIG_VIDEO_MRST_OV5630) += mrstov5630.o
2339 +EXTRA_CFLAGS += -I$(src)/../include
2340 diff --git a/drivers/media/video/mrstci/mrstov5630/ov5630.c b/drivers/media/video/mrstci/mrstov5630/ov5630.c
2341 new file mode 100644
2342 index 0000000..6498153
2344 +++ b/drivers/media/video/mrstci/mrstov5630/ov5630.c
2347 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
2349 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
2351 + * This program is free software; you can redistribute it and/or
2352 + * modify it under the terms of the GNU General Public License version
2353 + * 2 as published by the Free Software Foundation.
2355 + * This program is distributed in the hope that it will be useful,
2356 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2357 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2358 + * GNU General Public License for more details.
2360 + * You should have received a copy of the GNU General Public License
2361 + * along with this program; if not, write to the Free Software
2362 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
2363 + * 02110-1301, USA.
2366 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
2369 +#include <linux/module.h>
2370 +#include <linux/types.h>
2371 +#include <linux/kernel.h>
2372 +#include <linux/mm.h>
2373 +#include <linux/string.h>
2374 +#include <linux/errno.h>
2375 +#include <linux/init.h>
2376 +#include <linux/kmod.h>
2377 +#include <linux/device.h>
2378 +#include <linux/delay.h>
2379 +#include <linux/fs.h>
2380 +#include <linux/init.h>
2381 +#include <linux/slab.h>
2382 +#include <linux/delay.h>
2383 +#include <linux/i2c.h>
2384 +#include <linux/gpio.h>
2386 +#include <media/v4l2-device.h>
2387 +#include <media/v4l2-chip-ident.h>
2388 +#include <media/v4l2-i2c-drv.h>
2390 +#include "ci_sensor_common.h"
2391 +#include "ov5630.h"
2393 +static int mrstov5630_debug;
2394 +module_param(mrstov5630_debug, int, 0644);
2395 +MODULE_PARM_DESC(mrstov5630_debug, "Debug level (0-1)");
2397 +#define dprintk(level, fmt, arg...) do { \
2398 + if (mrstov5630_debug >= level) \
2399 + printk(KERN_DEBUG "mrstisp@%s: " fmt "\n", \
2400 + __func__, ## arg); } \
2403 +#define eprintk(fmt, arg...) \
2404 + printk(KERN_ERR "mrstisp@%s: line %d: " fmt "\n", \
2405 + __func__, __LINE__, ## arg);
2407 +#define DBG_entering dprintk(2, "entering");
2408 +#define DBG_leaving dprintk(2, "leaving");
2409 +#define DBG_line dprintk(2, " line: %d", __LINE__);
2411 +static inline struct ci_sensor_config *to_sensor_config(struct v4l2_subdev *sd)
2413 + return container_of(sd, struct ci_sensor_config, sd);
2416 +/* static int ov5630_set_res(struct i2c_client *c, const int w, const int h);
2418 +static struct ov5630_format_struct {
2420 + __u32 pixelformat;
2421 + struct regval_list *regs;
2422 +} ov5630_formats[] = {
2424 + .desc = "Raw RGB Bayer",
2425 + .pixelformat = SENSOR_MODE_BAYER,
2429 +#define N_OV5630_FMTS ARRAY_SIZE(ov5630_formats)
2431 +static struct ov5630_res_struct {
2436 + /* FIXME: correct the fps values.. */
2439 + struct regval_list *regs;
2442 + .desc = "QSXGA_PLUS4",
2443 + .res = SENSOR_RES_QXGA_PLUS,
2448 + .regs = ov5630_res_qsxga_plus4,
2452 + .res = SENSOR_RES_1080P,
2457 + .regs = ov5630_res_1080p,
2460 + .desc = "XGA_PLUS",
2461 + .res = SENSOR_RES_XGA_PLUS,
2466 + .regs = ov5630_res_xga_plus,
2470 + .res = SENSOR_RES_720P,
2475 + .regs = ov5630_res_720p,
2479 + .res = SENSOR_RES_VGA,
2484 + .regs = ov5630_res_vga_ac04_bill,
2488 +#define N_RES (ARRAY_SIZE(ov5630_res))
2491 + * I2C Read & Write stuff
2493 +static int ov5630_read(struct i2c_client *c, u32 reg, u32 *value)
2497 + struct i2c_msg msg[2];
2501 + /* Read needs two message to go */
2502 + memset(&msg, 0, sizeof(msg));
2507 + msgbuf[i++] = ((u16)reg) >> 8;
2508 + msgbuf[i++] = ((u16)reg) & 0xff;
2509 + msg[0].addr = c->addr;
2510 + msg[0].buf = msgbuf;
2513 + msg[1].addr = c->addr;
2514 + msg[1].flags = I2C_M_RD;
2515 + msg[1].buf = &ret_val;
2518 + ret = i2c_transfer(c->adapter, &msg[0], 2);
2521 + ret = (ret == 2) ? 0 : -1;
2525 +static int ov5630_write(struct i2c_client *c, u32 reg, u32 value)
2528 + struct i2c_msg msg;
2531 + /* Writing only needs one message */
2532 + memset(&msg, 0, sizeof(msg));
2534 + msgbuf[i++] = ((u16)reg) >> 8;
2535 + msgbuf[i++] = (u16)reg & 0xff;
2536 + msgbuf[i++] = (u8)value;
2538 + msg.addr = c->addr;
2543 + ret = i2c_transfer(c->adapter, &msg, 1);
2545 + /* If this is a reset register, wait for 1ms */
2546 + if (reg == OV5630_SYS && (value & 0x80))
2549 + ret = (ret == 1) ? 0 : -1;
2553 +static int ov5630_write_array(struct i2c_client *c, struct regval_list *vals)
2555 + struct regval_list *p;
2560 + while (p->reg_num != 0xffff) {
2561 + ov5630_write(c, (u32)p->reg_num, (u32)p->value);
2562 + ov5630_read(c, (u32)p->reg_num, &read_val);
2563 + if (read_val != p->value)
2572 + * Sensor specific helper function
2574 +static int ov5630_standby(void)
2576 + gpio_set_value(GPIO_STDBY_PIN, 1);
2577 + /* ov5630_motor_standby(); */
2578 + dprintk(1, "PM: standby called\n");
2582 +static int ov5630_wakeup(void)
2584 + gpio_set_value(GPIO_STDBY_PIN, 0);
2585 + /* ov5630_motor_wakeup(); */
2586 + dprintk(1, "PM: wakeup called\n");
2590 +static int ov5630_s_power(struct v4l2_subdev *sd, u32 val)
2599 +static int ov5630_set_img_ctrl(struct i2c_client *c,
2600 + const struct ci_sensor_config *config)
2604 + /* struct ci_sensor_config *info = i2c_get_clientdata(c); */
2606 + switch (config->blc) {
2607 + case SENSOR_BLC_OFF:
2608 + err |= ov5630_read(c, OV5630_ISP_CTL00, ®_val);
2609 + err |= ov5630_write(c, OV5630_ISP_CTL00, reg_val & 0xFE);
2611 + case SENSOR_BLC_AUTO:
2612 + err |= ov5630_read(c, OV5630_ISP_CTL00, ®_val);
2613 + err |= ov5630_write(c, OV5630_ISP_CTL00, reg_val | 0x01);
2617 + switch (config->agc) {
2618 + case SENSOR_AGC_AUTO:
2619 + err |= ov5630_read(c, OV5630_AUTO_1, ®_val);
2620 + err |= ov5630_write(c, OV5630_AUTO_1, reg_val | 0x04);
2622 + case SENSOR_AGC_OFF:
2623 + err |= ov5630_read(c, OV5630_AUTO_1, ®_val);
2624 + err |= ov5630_write(c, OV5630_AUTO_1, reg_val & ~0x04);
2628 + switch (config->awb) {
2629 + case SENSOR_AWB_AUTO:
2630 + err |= ov5630_read(c, OV5630_ISP_CTL00, ®_val);
2631 + err |= ov5630_write(c, OV5630_ISP_CTL00, reg_val | 0x30);
2633 + case SENSOR_AWB_OFF:
2634 + err |= ov5630_read(c, OV5630_ISP_CTL00, ®_val);
2635 + err |= ov5630_write(c, OV5630_ISP_CTL00, reg_val & ~0x30);
2639 + switch (config->aec) {
2640 + case SENSOR_AEC_AUTO:
2641 + err |= ov5630_read(c, OV5630_AUTO_1, ®_val);
2642 + err |= ov5630_write(c, OV5630_AUTO_1, reg_val | 0xFB);
2644 + case SENSOR_AEC_OFF:
2645 + err |= ov5630_read(c, OV5630_AUTO_1, ®_val);
2646 + err |= ov5630_write(c, OV5630_AUTO_1, reg_val & 0xF6);
2653 +static int ov5630_init(struct i2c_client *c)
2656 + struct v4l2_subdev *sd = i2c_get_clientdata(c);
2657 + struct ci_sensor_config *info = to_sensor_config(sd);
2660 + /* Fill the configuration structure */
2661 + /* Note this default configuration value */
2662 + info->mode = ov5630_formats[0].pixelformat;
2663 + info->res = ov5630_res[0].res;
2664 + info->type = SENSOR_TYPE_RAW;
2665 + info->bls = SENSOR_BLS_OFF;
2666 + info->gamma = SENSOR_GAMMA_OFF;
2667 + info->cconv = SENSOR_CCONV_OFF;
2668 + info->blc = SENSOR_BLC_AUTO;
2669 + info->agc = SENSOR_AGC_AUTO;
2670 + info->awb = SENSOR_AWB_AUTO;
2671 + info->aec = SENSOR_AEC_AUTO;
2672 + /* info->bus_width = SENSOR_BUSWIDTH_10BIT; */
2673 + info->bus_width = SENSOR_BUSWIDTH_10BIT_ZZ;
2674 + info->ycseq = SENSOR_YCSEQ_YCBYCR;
2675 + /* info->conv422 = SENSOR_CONV422_NOCOSITED; */
2676 + info->conv422 = SENSOR_CONV422_COSITED;
2677 + info->bpat = SENSOR_BPAT_BGBGGRGR;
2678 + info->field_inv = SENSOR_FIELDINV_NOSWAP;
2679 + info->field_sel = SENSOR_FIELDSEL_BOTH;
2680 + info->hpol = SENSOR_HPOL_REFPOS;
2681 + info->vpol = SENSOR_VPOL_NEG;
2682 + info->edge = SENSOR_EDGE_RISING;
2683 + info->flicker_freq = SENSOR_FLICKER_100;
2684 + info->cie_profile = SENSOR_CIEPROF_F11;
2686 + memcpy(info->name, name, 7);
2688 + /* Reset sensor hardware, and implement the setting*/
2689 + ret = ov5630_write(c, (u32)OV5630_SYS, (u32)0x80);
2690 + ret += ov5630_write(c, (u32)OV5630_IMAGE_SYSTEM, (u32)0x00);
2692 + /* Set registers into default config value */
2693 + ret += ov5630_write_array(c, ov5630_def_reg);
2695 + /* Set MIPI interface */
2697 + ret += ov5630_write_array(c, ov5630_mipi);
2700 + /* turn off AE AEB AGC */
2701 + ret += ov5630_set_img_ctrl(c, info);
2704 + /* ret += ov5630_write(c, (u32)OV5630_IMAGE_SYSTEM, (u32)0x01); */
2705 + /* ret += ov5630_write(c, (u32)0x3096, (u32)0x50); */
2708 + /* Added by wen to stop sensor from streaming */
2709 + ov5630_write(c, (u32)OV5630_IMAGE_SYSTEM, (u32)0x00);
2710 + ov5630_write(c, 0x30b0, 0x00);
2711 + ov5630_write(c, 0x30b1, 0x00);
2715 +static int distance(struct ov5630_res_struct *res, u32 w, u32 h)
2718 + if (res->width < w || res->height < h)
2721 + ret = ((res->width - w) + (res->height - h));
2724 +static int ov5630_try_res(u32 *w, u32 *h)
2726 + struct ov5630_res_struct *res_index, *p = NULL;
2727 + int dis, last_dis = ov5630_res->width + ov5630_res->height;
2731 + for (res_index = ov5630_res;
2732 + res_index < ov5630_res + N_RES;
2734 + if ((res_index->width < *w) || (res_index->height < *h))
2736 + dis = distance(res_index, *w, *h);
2737 + if (dis < last_dis) {
2745 + else if ((p->width < *w) || (p->height < *h)) {
2746 + if (p != ov5630_res)
2750 + if ((w != NULL) && (h != NULL)) {
2759 +static struct ov5630_res_struct *ov5630_to_res(u32 w, u32 h)
2761 + struct ov5630_res_struct *res_index;
2763 + for (res_index = ov5630_res;
2764 + res_index < ov5630_res + N_RES;
2766 + if ((res_index->width == w) && (res_index->height == h))
2769 + if (res_index >= ov5630_res + N_RES)
2770 + res_index--; /* Take the bigger one */
2775 +static int ov5630_try_fmt(struct v4l2_subdev *sd,
2776 + struct v4l2_format *fmt)
2779 + return ov5630_try_res(&fmt->fmt.pix.width, &fmt->fmt.pix.height);
2783 +static int ov5630_get_fmt(struct v4l2_subdev *sd,
2784 + struct v4l2_format *fmt)
2786 + struct ci_sensor_config *info = to_sensor_config(sd);
2787 + unsigned short width, height;
2790 + ci_sensor_res2size(info->res, &width, &height);
2792 + /* Marked the current sensor res as being "used" */
2793 + for (index = 0; index < N_RES; index++) {
2794 + if ((width == ov5630_res[index].width) &&
2795 + (height == ov5630_res[index].height)) {
2796 + ov5630_res[index].used = 1;
2799 + ov5630_res[index].used = 0;
2802 + fmt->fmt.pix.width = width;
2803 + fmt->fmt.pix.height = height;
2807 +static int ov5630_set_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
2809 + struct i2c_client *c = v4l2_get_subdevdata(sd);
2810 + struct ci_sensor_config *info = to_sensor_config(sd);
2812 + struct ov5630_res_struct *res_index;
2813 + u32 width, height;
2818 + width = fmt->fmt.pix.width;
2819 + height = fmt->fmt.pix.height;
2821 + dprintk(1, "was told to set fmt (%d x %d) ", width, height);
2823 + ret = ov5630_try_res(&width, &height);
2825 + dprintk(1, "setting fmt (%d x %d) ", width, height);
2827 + res_index = ov5630_to_res(width, height);
2831 + if (res_index->regs) {
2832 + /* Soft reset camera first*/
2833 + ret = ov5630_write(c, (u32)OV5630_SYS, (u32)0x80);
2835 + /* software sleep/standby */
2836 + ret += ov5630_write(c, (u32)OV5630_IMAGE_SYSTEM, (u32)0x00);
2838 + /* Set registers into default config value */
2839 + ret += ov5630_write_array(c, ov5630_def_reg);
2841 + /* set image resolution */
2842 + ret += ov5630_write_array(c, res_index->regs);
2844 + /* turn off AE AEB AGC */
2845 + ret += ov5630_set_img_ctrl(c, info);
2847 + /* Set MIPI interface */
2849 + ret += ov5630_write_array(c, ov5630_mipi);
2852 + if (res_index->res == SENSOR_RES_VGA)
2853 + ret += ov5630_write(c, (u32)0x3015, (u32)0x03);
2856 + ret = ov5630_write(c, (u32)OV5630_IMAGE_SYSTEM, (u32)0x01);
2857 + ret = ov5630_write(c, (u32)0x3096, (u32)0x50);
2859 + info->res = res_index->res;
2861 + /* Marked current sensor res as being "used" */
2862 + for (index = 0; index < N_RES; index++) {
2863 + if ((width == ov5630_res[index].width) &&
2864 + (height == ov5630_res[index].height)) {
2865 + ov5630_res[index].used = 1;
2868 + ov5630_res[index].used = 0;
2871 + for (index = 0; index < N_RES; index++)
2872 + dprintk(2, "index = %d, used = %d\n", index,
2873 + ov5630_res[index].used);
2875 + eprintk("no res for (%d x %d)", width, height);
2882 +static int ov5630_t_gain(struct v4l2_subdev *sd, int value)
2884 + struct i2c_client *client = v4l2_get_subdevdata(sd);
2889 + dprintk(2, "writing gain %x to 0x3000", value);
2891 + ov5630_read(client, 0x3000, &v);
2892 + v = (v & 0x80) + value;
2893 + ov5630_write(client, 0x3000, v);
2895 + dprintk(2, "gain %x was writen to 0x3000", v);
2901 +static int ov5630_t_exposure(struct v4l2_subdev *sd, int value)
2903 + struct i2c_client *client = v4l2_get_subdevdata(sd);
2909 + ov5630_read(client, 0x3013, &v);
2910 + dprintk(2, "0x3013 = %x", v);
2912 + /* turn off agc/aec */
2914 + ov5630_write(client, 0x3013, v);
2915 + /* turn off awb */
2916 + ov5630_read(client, OV5630_ISP_CTL00, ®_val);
2917 + ov5630_write(client, OV5630_ISP_CTL00, reg_val & ~0x30);
2919 + ov5630_read(client, 0x3014, &v);
2920 + dprintk(2, "0x3014 = %x", v);
2921 + ov5630_read(client, 0x3002, &v);
2922 + dprintk(2, "0x3002 = %x", v);
2923 + ov5630_read(client, 0x3003, &v);
2924 + dprintk(2, "0x3003 = %x", v);
2926 + dprintk(2, "writing exposure %x to 0x3002/3", value);
2929 + ov5630_write(client, 0x3002, v);
2930 + dprintk(2, "exposure %x was writen to 0x3002", v);
2933 + ov5630_write(client, 0x3003, v);
2934 + dprintk(2, "exposure %x was writen to 0x3003", v);
2940 +static struct ov5630_control {
2941 + struct v4l2_queryctrl qc;
2942 + int (*query)(struct v4l2_subdev *sd, __s32 *value);
2943 + int (*tweak)(struct v4l2_subdev *sd, int value);
2944 +} ov5630_controls[] = {
2947 + .id = V4L2_CID_GAIN,
2948 + .type = V4L2_CTRL_TYPE_INTEGER,
2949 + .name = "global gain",
2953 + .default_value = 0x00,
2956 + .tweak = ov5630_t_gain,
2957 +/* .query = ov5630_q_gain, */
2961 + .id = V4L2_CID_EXPOSURE,
2962 + .type = V4L2_CTRL_TYPE_INTEGER,
2963 + .name = "exposure",
2965 + .maximum = 0xFFFF,
2967 + .default_value = 0x00,
2970 + .tweak = ov5630_t_exposure,
2971 +/* .query = ov5630_q_exposure; */
2974 +#define N_CONTROLS (ARRAY_SIZE(ov5630_controls))
2977 +static int ov5630_g_gain(struct v4l2_subdev *sd, int value)
2979 + struct i2c_client *client = v4l2_get_subdevdata(sd);
2984 + ov5630_write(client, 0x3000, &v);
2985 + dprintk(2, "writing gain %x to 0x3000", value);
2993 +static struct ov5630_control *ov5630_find_control(__u32 id)
2997 + for (i = 0; i < N_CONTROLS; i++)
2998 + if (ov5630_controls[i].qc.id == id)
2999 + return ov5630_controls + i;
3003 +static int ov5630_queryctrl(struct v4l2_subdev *sd,
3004 + struct v4l2_queryctrl *qc)
3006 + struct ov5630_control *ctrl = ov5630_find_control(qc->id);
3014 +static int ov5630_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
3017 + struct ov5630_control *octrl = ov5630_find_control(ctrl->id);
3021 + if (octrl == NULL)
3023 + ret = octrl->query(sd, &ctrl->value);
3031 +static int ov5630_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
3033 + struct ov5630_control *octrl = ov5630_find_control(ctrl->id);
3036 + if (octrl == NULL)
3038 + ret = octrl->tweak(sd, ctrl->value);
3045 +static int ov5630_get_caps(struct i2c_client *c, struct ci_sensor_caps *caps)
3050 + caps->bus_width = SENSOR_BUSWIDTH_10BIT;
3051 + caps->mode = SENSOR_MODE_BAYER;
3052 + caps->field_inv = SENSOR_FIELDINV_NOSWAP;
3053 + caps->field_sel = SENSOR_FIELDSEL_BOTH;
3054 + caps->ycseq = SENSOR_YCSEQ_YCBYCR;
3055 + caps->conv422 = SENSOR_CONV422_NOCOSITED;
3056 + caps->bpat = SENSOR_BPAT_BGBGGRGR;
3057 + caps->hpol = SENSOR_HPOL_REFPOS;
3058 + caps->vpol = SENSOR_VPOL_NEG;
3059 + caps->edge = SENSOR_EDGE_RISING;
3060 + caps->bls = SENSOR_BLS_OFF;
3061 + caps->gamma = SENSOR_GAMMA_OFF;
3062 + caps->cconv = SENSOR_CCONV_OFF;
3063 + caps->res = SENSOR_RES_QXGA_PLUS | SENSOR_RES_1080P |
3064 + SENSOR_RES_XGA_PLUS | SENSOR_RES_720P | SENSOR_RES_VGA;
3065 + caps->blc = SENSOR_BLC_OFF;
3066 + caps->agc = SENSOR_AGC_OFF;
3067 + caps->awb = SENSOR_AWB_OFF;
3068 + caps->aec = SENSOR_AEC_OFF;
3069 + caps->cie_profile = SENSOR_CIEPROF_D65 | SENSOR_CIEPROF_D75 |
3070 + SENSOR_CIEPROF_F11 | SENSOR_CIEPROF_F12 | SENSOR_CIEPROF_A |
3071 + SENSOR_CIEPROF_F2;
3072 + caps->flicker_freq = SENSOR_FLICKER_100 | SENSOR_FLICKER_120;
3073 + caps->type = SENSOR_TYPE_RAW;
3074 + /* caps->name = "ov5630"; */
3075 + strcpy(caps->name, "ov5630");
3080 +static int ov5630_get_config(struct i2c_client *c,
3081 + struct ci_sensor_config *config)
3083 + struct ci_sensor_config *info = i2c_get_clientdata(c);
3085 + if (config == NULL) {
3086 + printk(KERN_WARNING "sensor_get_config: NULL pointer\n");
3090 + memcpy(config, info, sizeof(struct ci_sensor_config));
3095 +static int ov5630_setup(struct i2c_client *c,
3096 + const struct ci_sensor_config *config)
3100 + struct ov5630_res_struct *res_index;
3101 + struct ci_sensor_config *info = i2c_get_clientdata(c);
3103 + /* Soft reset camera first*/
3104 + ret = ov5630_write(c, (u32)OV5630_SYS, (u32)0x80);
3106 + /* software sleep/standby */
3107 + ret = ov5630_write(c, (u32)OV5630_IMAGE_SYSTEM, (u32)0x00);
3109 + /* Set registers into default config value */
3110 + ret = ov5630_write_array(c, ov5630_def_reg);
3112 + /* set image resolution */
3113 + ci_sensor_res2size(config->res, &width, &high);
3114 + ret += ov5630_try_res(&width, &high);
3115 + res_index = ov5630_find_res(width, high);
3116 + if (res_index->regs)
3117 + ret += ov5630_write_array(c, res_index->regs);
3119 + info->res = res_index->res;
3121 + ret += ov5630_set_img_ctrl(c, config);
3123 + /* Set MIPI interface */
3125 + ret += ov5630_write_array(c, ov5630_mipi);
3129 + ret += ov5630_write(c, (u32)OV5630_IMAGE_SYSTEM, (u32)0x01);
3130 + ret += ov5630_write(c, (u32)0x3096, (u32)0x50);
3132 + /*Note here for the time delay */
3139 + * File operation functions
3141 +static int ov5630_dvp_enable(struct i2c_client *client)
3147 + ret = ov5630_read(client, 0x3506, ®);
3150 + ret += ov5630_write(client, 0x3506, reg);
3155 +static int ov5630_dvp_disable(struct i2c_client *client)
3161 + ret = ov5630_read(client, 0x3506, ®);
3163 + ret += ov5630_write(client, 0x3506, reg);
3168 +static int ov5630_open(struct i2c_setting *c, void *priv)
3170 + /* Just wake up sensor */
3171 + if (ov5630_wakeup())
3173 + ov5630_init(c->sensor_client);
3174 + /* ov5630_motor_init(c->motor_client); */
3175 + ov5630_write(c->sensor_client, (u32)OV5630_IMAGE_SYSTEM, (u32)0x00);
3177 + /* disable dvp_en */
3178 + ov5630_dvp_disable(c->sensor_client);
3183 +static int ov5630_release(struct i2c_setting *c, void *priv)
3185 + /* Just suspend the sensor */
3186 + if (ov5630_standby())
3191 +static int ov5630_on(struct i2c_setting *c)
3195 + /* Software wake up sensor */
3196 + ret = ov5630_write(c->sensor_client,
3197 + (u32)OV5630_IMAGE_SYSTEM, (u32)0x01);
3199 + /* enable dvp_en */
3200 + return ret + ov5630_dvp_enable(c->sensor_client);
3203 +static int ov5630_off(struct i2c_setting *c)
3207 + /* Software standby sensor */
3208 + ret = ov5630_write(c->sensor_client,
3209 + (u32)OV5630_IMAGE_SYSTEM, (u32)0x00);
3210 + /* disable dvp_en */
3211 + return ret + ov5630_dvp_disable(c->sensor_client);
3214 +static struct sensor_device ov5630 = {
3216 + .type = SENSOR_TYPE_RAW,
3218 + .open = ov5630_open,
3219 + .release = ov5630_release,
3221 + .off = ov5630_off,
3222 + .querycap = ov5630_get_caps,
3223 + .get_config = ov5630_get_config,
3224 + .set_config = ov5630_setup,
3225 + .enum_parm = ov5630_queryctrl,
3226 + .get_parm = ov5630_g_ctrl,
3227 + .set_parm = ov5630_s_ctrl,
3228 + .try_res = ov5630_try_res,
3229 + .set_res = ov5630_set_res,
3230 + .get_ls_corr_config = NULL,
3231 + .mdi_get_focus = ov5630_motor_get_focus,
3232 + .mdi_set_focus = ov5630_motor_set_focus,
3233 + .mdi_max_step = ov5630_motor_max_step,
3234 + .mdi_calibrate = NULL,
3235 + .read = ov5630_read,
3236 + .write = ov5630_write,
3237 + .suspend = ov5630_standby,
3238 + .resume = ov5630_wakeup,
3243 +static int ov5630_s_stream(struct v4l2_subdev *sd, int enable)
3245 + struct i2c_client *client = v4l2_get_subdevdata(sd);
3249 + ov5630_write(client, (u32)OV5630_IMAGE_SYSTEM, (u32)0x01);
3250 + ov5630_write(client, 0x30b0, 0xff);
3251 + ov5630_write(client, 0x30b1, 0xff);
3254 + ov5630_write(client, (u32)OV5630_IMAGE_SYSTEM, (u32)0x00);
3255 + ov5630_write(client, 0x30b0, 0x00);
3256 + ov5630_write(client, 0x30b1, 0x00);
3263 +static int ov5630_enum_framesizes(struct v4l2_subdev *sd,
3264 + struct v4l2_frmsizeenum *fsize)
3266 + unsigned int index = fsize->index;
3270 + if (index >= N_RES)
3273 + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
3274 + fsize->discrete.width = ov5630_res[index].width;
3275 + fsize->discrete.height = ov5630_res[index].height;
3276 + fsize->reserved[0] = ov5630_res[index].used;
3283 +static int ov5630_enum_frameintervals(struct v4l2_subdev *sd,
3284 + struct v4l2_frmivalenum *fival)
3286 + unsigned int index = fival->index;
3290 + if (index >= N_RES)
3293 + fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
3294 + fival->discrete.numerator = 1;
3295 + fival->discrete.denominator = ov5630_res[index].fps;
3302 +static int ov5630_g_chip_ident(struct v4l2_subdev *sd,
3303 + struct v4l2_dbg_chip_ident *chip)
3305 + struct i2c_client *client = v4l2_get_subdevdata(sd);
3307 +#define V4L2_IDENT_OV5630 8245
3308 + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV5630, 0);
3311 +#ifdef CONFIG_VIDEO_ADV_DEBUG
3312 +static int ov5630_g_register(struct v4l2_subdev *sd,
3313 + struct v4l2_dbg_register *reg)
3315 + struct i2c_client *client = v4l2_get_subdevdata(sd);
3316 + unsigned char val = 0;
3319 + if (!v4l2_chip_match_i2c_client(client, ®->match))
3321 + if (!capable(CAP_SYS_ADMIN))
3323 + ret = ov5630_read(client, reg->reg & 0xffff, &val);
3329 +static int ov5630_s_register(struct v4l2_subdev *sd,
3330 + struct v4l2_dbg_register *reg)
3332 + struct i2c_client *client = v4l2_get_subdevdata(sd);
3334 + if (!v4l2_chip_match_i2c_client(client, ®->match))
3336 + if (!capable(CAP_SYS_ADMIN))
3338 + ov5630_write(client, reg->reg & 0xffff, reg->val & 0xff);
3343 +static const struct v4l2_subdev_video_ops ov5630_video_ops = {
3344 + .try_fmt = ov5630_try_fmt,
3345 + .s_fmt = ov5630_set_fmt,
3346 + .g_fmt = ov5630_get_fmt,
3347 + .s_stream = ov5630_s_stream,
3348 + .enum_framesizes = ov5630_enum_framesizes,
3349 + .enum_frameintervals = ov5630_enum_frameintervals,
3352 +static const struct v4l2_subdev_core_ops ov5630_core_ops = {
3353 + .g_chip_ident = ov5630_g_chip_ident,
3354 + .queryctrl = ov5630_queryctrl,
3355 + .g_ctrl = ov5630_g_ctrl,
3356 + .s_ctrl = ov5630_s_ctrl,
3357 + .s_gpio = ov5630_s_power,
3358 + /*.g_ext_ctrls = ov5630_g_ext_ctrls,*/
3359 + /*.s_ext_ctrls = ov5630_s_ext_ctrls,*/
3360 +#ifdef CONFIG_VIDEO_ADV_DEBUG
3361 + .g_register = ov5630_g_register,
3362 + .s_register = ov5630_s_register,
3366 +static const struct v4l2_subdev_ops ov5630_ops = {
3367 + .core = &ov5630_core_ops,
3368 + .video = &ov5630_video_ops,
3375 +static unsigned short normal_i2c[] = {I2C_OV5630 >> 1,
3379 +static struct i2c_driver ov5630_driver;
3381 +static int ov5630_detect(struct i2c_client *client)
3383 + struct i2c_adapter *adapter = client->adapter;
3384 + int adap_id = i2c_adapter_id(adapter);
3387 + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
3388 + eprintk("error i2c check func");
3392 + if (adap_id != 1) {
3393 + eprintk("adap_id != 1");
3397 + /* if (ov5630_wakeup()) */
3398 + /* return -ENODEV; */
3401 + ov5630_read(client, (u32)OV5630_PID_H, &value);
3402 + if ((u8)value != 0x56) {
3403 + dprintk(1, "PID != 0x56, but %x", value);
3404 + dprintk(2, "client->addr = %x", client->addr);
3408 + printk(KERN_INFO "Init ov5630 sensor success\n");
3412 +static int ov5630_probe(struct i2c_client *client,
3413 + const struct i2c_device_id *id)
3415 + struct ci_sensor_config *info;
3416 + struct v4l2_subdev *sd;
3418 +/* struct i2c_client *motor; */
3421 + v4l_info(client, "chip found @ 0x%x (%s)\n",
3422 + client->addr << 1, client->adapter->name);
3424 + * Setup sensor configuration structure
3426 + info = kzalloc(sizeof(struct ci_sensor_config), GFP_KERNEL);
3428 + eprintk("fail to malloc for ci_sensor_config");
3433 + ret = ov5630_detect(client);
3435 + dprintk(1, "error ov5630_detect");
3440 + v4l2_i2c_subdev_init(sd, client, &ov5630_ops);
3443 + * Initialization OV5630
3444 + * then turn into standby mode
3446 + /* ret = ov5630_standby(); */
3447 + ret = ov5630_init(client);
3449 + eprintk("error calling ov5630_init");
3465 + * XXX: Need to be checked
3467 +static int ov5630_remove(struct i2c_client *client)
3469 + struct v4l2_subdev *sd = i2c_get_clientdata(client);
3473 + v4l2_device_unregister_subdev(sd);
3474 + kfree(to_sensor_config(sd));
3480 +static const struct i2c_device_id ov5630_id[] = {
3485 +MODULE_DEVICE_TABLE(i2c, ov5630_id);
3487 +static struct v4l2_i2c_driver_data v4l2_i2c_data = {
3489 + .probe = ov5630_probe,
3490 + .remove = ov5630_remove,
3491 + /* .suspend = ov5630_suspend,
3492 + * .resume = ov5630_resume, */
3493 + .id_table = ov5630_id,
3496 +MODULE_AUTHOR("Xiaolin Zhang <xiaolin.zhang@intel.com>");
3497 +MODULE_DESCRIPTION("A low-level driver for OmniVision 5630 sensors");
3498 +MODULE_LICENSE("GPL");
3499 diff --git a/drivers/media/video/mrstci/mrstov5630/ov5630.h b/drivers/media/video/mrstci/mrstov5630/ov5630.h
3500 new file mode 100644
3501 index 0000000..3da0ecd
3503 +++ b/drivers/media/video/mrstci/mrstov5630/ov5630.h
3506 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
3508 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
3510 + * This program is free software; you can redistribute it and/or
3511 + * modify it under the terms of the GNU General Public License version
3512 + * 2 as published by the Free Software Foundation.
3514 + * This program is distributed in the hope that it will be useful,
3515 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3516 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3517 + * GNU General Public License for more details.
3519 + * You should have received a copy of the GNU General Public License
3520 + * along with this program; if not, write to the Free Software
3521 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
3522 + * 02110-1301, USA.
3525 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
3528 +#define I2C_OV5630 0x6C
3529 +/* Should add to kernel source */
3530 +#define I2C_DRIVERID_OV5630 1046
3531 +/* GPIO pin on Moorestown */
3532 +#define GPIO_SCLK_25 44
3533 +#define GPIO_STB_PIN 47
3534 +#define GPIO_STDBY_PIN 49
3535 +#define GPIO_RESET_PIN 50
3537 +/* System control register */
3538 +#define OV5630_AGC 0x3000
3539 +#define OV5630_AGCS 0x3001
3540 +#define OV5630_AEC_H 0x3002
3541 +#define OV5630_AEC_L 0x3003
3542 +#define OV5630_LAEC_H 0x3004
3543 +#define OV5630_LAEC_L 0x3005
3544 +#define OV5630_AECS_H 0x3008
3545 +#define OV5630_AECS_L 0x3009
3546 +#define OV5630_PID_H 0x300A
3547 +#define OV5630_PID_L 0x300B
3548 +#define OV5630_SCCB_ID 0x300C
3549 +#define OV5630_PLL_1 0x300E
3550 +#define OV5630_PLL_2 0x300F
3551 +#define OV5630_PLL_3 0x3010
3552 +#define OV5630_PLL_4 0x3011
3553 +#define OV5630_SYS 0x3012
3554 +#define OV5630_AUTO_1 0x3013
3555 +#define OV5630_AUTO_2 0x3014
3556 +#define OV5630_AUTO_3 0x3015
3557 +#define OV5630_AUTO_4 0x3016
3558 +#define OV5630_AUTO_5 0x3017
3559 +#define OV5630_WPT 0x3018
3560 +#define OV5630_BPT 0x3019
3561 +#define OV5630_VPT 0x301A
3562 +#define OV5630_YAVG 0x301B
3563 +#define OV5630_AECG_50 0x301C
3564 +#define OV5630_AECG_60 0x301D
3565 +#define OV5630_ADDVS_H 0x301E
3566 +#define OV5630_ADDVS_L 0x301F
3567 +#define OV5630_FRAME_LENGTH_LINES_H 0x3020
3568 +#define OV5630_FRAME_LENGTH_LINES_L 0x3021
3569 +#define OV5630_LINE_LENGTH_PCK_H 0x3022
3570 +#define OV5630_LINE_LENGTH_PCK_L 0x3023
3571 +#define OV5630_X_ADDR_START_H 0x3024
3572 +#define OV5630_X_ADDR_START_L 0x3025
3573 +#define OV5630_Y_ADDR_START_H 0x3026
3574 +#define OV5630_Y_ADDR_START_L 0x3027
3575 +#define OV5630_X_ADDR_END_H 0x3028
3576 +#define OV5630_X_ADDR_END_L 0x3029
3577 +#define OV5630_Y_ADDR_END_H 0x302A
3578 +#define OV5630_Y_ADDR_END_L 0x302B
3579 +#define OV5630_X_OUTPUT_SIZE_H 0x302C
3580 +#define OV5630_X_OUTPUT_SIZE_L 0x302D
3581 +#define OV5630_Y_OUTPUT_SIZE_H 0x302E
3582 +#define OV5630_Y_OUTPUT_SIZE_L 0x302F
3583 +#define OV5630_FRAME_CNT 0x3030
3584 +#define OV5630_DATR_LMO_0 0x3038
3585 +#define OV5630_DATR_LMO_1 0x3039
3586 +#define OV5630_DATR_LMO_2 0x303A
3587 +#define OV5630_DATR_D56 0x303D
3588 +#define OV5630_DATR_EF 0x303E
3589 +#define OV5630_R_SIGMA_0 0x3048
3590 +#define OV5630_R_SIGMA_1 0x3049
3591 +#define OV5630_R_SIGMA_2 0x304A
3592 +#define OV5630_R_SIGMA_3 0x304B
3593 +#define OV5630_R_SIGMA_4 0x304C
3594 +#define OV5630_R_SIGMA_5 0x304D
3595 +#define OV5630_D56COM 0x304E
3596 +#define OV5630_5060TH 0x3050
3597 +#define OV5630_LMO_TH1 0x3058
3598 +#define OV5630_LMO_TH2 0x3059
3599 +#define OV5630_LMO_K 0x305A
3600 +#define OV5630_BD50ST_H 0x305C
3601 +#define OV5630_BD50ST_L 0x305D
3602 +#define OV5630_BD60ST_H 0x305E
3603 +#define OV5630_BD60ST_L 0x305F
3604 +#define OV5630_HSYNST 0x306D
3605 +#define OV5630_HSYNED 0x306E
3606 +#define OV5630_HSYNED_HSYNST 0x306F
3607 +#define OV5630_TMC_RWIN0 0x3070
3608 +#define OV5630_IO_CTRL0 0x30B0
3609 +#define OV5630_IO_CTRL1 0x30B1
3610 +#define OV5630_IO_CTRL2 0x30B2
3611 +#define OV5630_DSIO_0 0x30B3
3612 +#define OV5630_DSIO_1 0x30B4
3613 +#define OV5630_DSIO_2 0x30B5
3614 +#define OV5630_TMC_10 0x30B6
3615 +#define OV5630_TMC_12 0x30B7
3616 +#define OV5630_TMC_14 0x30B9
3617 +#define OV5630_TMC_COM4 0x30BA
3618 +#define OV5630_TMC_REG6C 0x30BB
3619 +#define OV5630_TMC_REG6E 0x30BC
3620 +#define OV5630_R_CLK_S 0x30BD
3621 +#define OV5630_R_CLK_A 0x30BE
3622 +#define OV5630_R_CLK_A1 0x30BF
3623 +#define OV5630_FRS_0 0x30E0
3624 +#define OV5630_FRS_1 0x30E1
3625 +#define OV5630_FRS_2 0x30E2
3626 +#define OV5630_FRS_3 0x30E3
3627 +#define OV5630_FRS_FECNT 0x30E4
3628 +#define OV5630_FRS_FECNT_0 0x30E5
3629 +#define OV5630_FRS_FECNT_1 0x30E6
3630 +#define OV5630_FRS_RFRM 0x30E7
3631 +#define OV5630_FRS_RSTRB 0x30E8
3632 +#define OV5630_SA1TMC 0x30E9
3633 +#define OV5630_TMC_MISC0 0x30EA
3634 +#define OV5630_TMC_MISC1 0x30EB
3635 +#define OV5630_FLEX_TXP 0x30F0
3636 +#define OV5630_FLEX_FLT 0x30F1
3637 +#define OV5630_FLEX_TXT 0x30F2
3638 +#define OV5630_FLEX_HBK 0x30F3
3639 +#define OV5630_FLEX_HSG 0x30F4
3640 +#define OV5630_FLEX_SA1SFT 0x30F5
3641 +#define OV5630_RVSOPT 0x30F6
3642 +#define OV5630_AUTO 0x30F7
3643 +#define OV5630_IMAGE_TRANSFORM 0x30F8
3644 +#define OV5630_IMAGE_LUM 0x30F9
3645 +#define OV5630_IMAGE_SYSTEM 0x30FA
3646 +#define OV5630_GROUP_WR 0x30FF
3648 +/* CIF control register */
3649 +#define OV5630_CIF_CTRL2 0x3202
3651 +/* ISP control register */
3652 +#define OV5630_ISP_CTL00 0x3300
3653 +#define OV5630_ISP_CTL01 0x3301
3654 +#define OV5630_ISP_CTL02 0x3302
3655 +#define OV5630_ISP_03 0x3303
3656 +#define OV5630_ISP_DIG_GAIN_MAN 0x3304
3657 +#define OV5630_ISP_BIAS_MAN 0x3305
3658 +#define OV5630_ISP_06 0x3306
3659 +#define OV5630_ISP_STABLE_RANGE 0x3307
3660 +#define OV5630_ISP_R_GAIN_MAN_1 0x3308
3661 +#define OV5630_ISP_R_GAIN_MAN_0 0x3309
3662 +#define OV5630_ISP_G_GAIN_MAN_1 0x330A
3663 +#define OV5630_ISP_G_GAIN_MAN_0 0x330B
3664 +#define OV5630_ISP_B_GAIN_MAN_1 0x330C
3665 +#define OV5630_ISP_B_GAIN_MAN_0 0x330D
3666 +#define OV5630_ISP_STABLE_RANGEW 0x330E
3667 +#define OV5630_ISP_AWB_FRAME_CNT 0x330F
3668 +#define OV5630_ISP_11 0x3311
3669 +#define OV5630_ISP_12 0x3312
3670 +#define OV5630_ISP_13 0x3313
3671 +#define OV5630_ISP_HSIZE_IN_1 0x3314
3672 +#define OV5630_ISP_HSIZE_IN_0 0x3315
3673 +#define OV5630_ISP_VSIZE_IN_1 0x3316
3674 +#define OV5630_ISP_VSIZE_IN_0 0x3317
3675 +#define OV5630_ISP_18 0x3318
3676 +#define OV5630_ISP_19 0x3319
3677 +#define OV5630_ISP_EVEN_MAN0 0x331A
3678 +#define OV5630_ISP_EVEN_MAN1 0x331B
3679 +#define OV5630_ISP_EVEN_MAN2 0x331C
3680 +#define OV5630_ISP_EVEN_MAN3 0x331D
3681 +#define OV5630_ISP_1E 0x331E
3682 +#define OV5630_ISP_1F 0x331F
3683 +#define OV5630_ISP_BLC_LMT_OPTION 0x3320
3684 +#define OV5630_ISP_BLC_THRE 0x3321
3685 +#define OV5630_ISP_22 0x3322
3686 +#define OV5630_ISP_23 0x3323
3687 +#define OV5630_ISP_BLC_MAN0_1 0x3324
3688 +#define OV5630_ISP_BLC_MAN0_0 0x3325
3689 +#define OV5630_ISP_BLC_MAN1_1 0x3326
3690 +#define OV5630_ISP_BLC_MAN1_0 0x3327
3691 +#define OV5630_ISP_BLC_MAN2_1 0x3328
3692 +#define OV5630_ISP_BLC_MAN2_0 0x3329
3693 +#define OV5630_ISP_BLC_MAN3_1 0x332A
3694 +#define OV5630_ISP_BLC_MAN3_0 0x332B
3695 +#define OV5630_ISP_BLC_MAN4_1 0x332C
3696 +#define OV5630_ISP_BLC_MAN4_0 0x332D
3697 +#define OV5630_ISP_BLC_MAN5_1 0x332E
3698 +#define OV5630_ISP_BLC_MAN5_0 0x332F
3699 +#define OV5630_ISP_BLC_MAN6_1 0x3330
3700 +#define OV5630_ISP_BLC_MAN6_0 0x3331
3701 +#define OV5630_ISP_BLC_MAN7_1 0x3332
3702 +#define OV5630_ISP_BLC_MAN7_0 0x3333
3703 +#define OV5630_ISP_CD 0x33CD
3704 +#define OV5630_ISP_FF 0x33FF
3706 +/* clipping control register */
3707 +#define OV5630_CLIP_CTRL0 0x3400
3708 +#define OV5630_CLIP_CTRL1 0x3401
3709 +#define OV5630_CLIP_CTRL2 0x3402
3710 +#define OV5630_CLIP_CTRL3 0x3403
3711 +#define OV5630_CLIP_CTRL4 0x3404
3712 +#define OV5630_CLIP_CTRL5 0x3405
3713 +#define OV5630_CLIP_CTRL6 0x3406
3714 +#define OV5630_CLIP_CTRL7 0x3407
3716 +/* DVP control register */
3717 +#define OV5630_DVP_CTRL00 0x3500
3718 +#define OV5630_DVP_CTRL01 0x3501
3719 +#define OV5630_DVP_CTRL02 0x3502
3720 +#define OV5630_DVP_CTRL03 0x3503
3721 +#define OV5630_DVP_CTRL04 0x3504
3722 +#define OV5630_DVP_CTRL05 0x3505
3723 +#define OV5630_DVP_CTRL06 0x3506
3724 +#define OV5630_DVP_CTRL07 0x3507
3725 +#define OV5630_DVP_CTRL08 0x3508
3726 +#define OV5630_DVP_CTRL09 0x3509
3727 +#define OV5630_DVP_CTRL0A 0x350A
3728 +#define OV5630_DVP_CTRL0B 0x350B
3729 +#define OV5630_DVP_CTRL0C 0x350C
3730 +#define OV5630_DVP_CTRL0D 0x350D
3731 +#define OV5630_DVP_CTRL0E 0x350E
3732 +#define OV5630_DVP_CTRL0F 0x350F
3733 +#define OV5630_DVP_CTRL10 0x3510
3734 +#define OV5630_DVP_CTRL11 0x3511
3735 +#define OV5630_DVP_CTRL12 0x3512
3736 +#define OV5630_DVP_CTRL13 0x3513
3737 +#define OV5630_DVP_CTRL14 0x3514
3738 +#define OV5630_DVP_CTRL15 0x3515
3739 +#define OV5630_DVP_CTRL16 0x3516
3740 +#define OV5630_DVP_CTRL17 0x3517
3741 +#define OV5630_DVP_CTRL18 0x3518
3742 +#define OV5630_DVP_CTRL19 0x3519
3743 +#define OV5630_DVP_CTRL1A 0x351A
3744 +#define OV5630_DVP_CTRL1B 0x351B
3745 +#define OV5630_DVP_CTRL1C 0x351C
3746 +#define OV5630_DVP_CTRL1D 0x351D
3747 +#define OV5630_DVP_CTRL1E 0x351E
3748 +#define OV5630_DVP_CTRL1F 0x351F
3750 +/* MIPI control register */
3751 +#define OV5630_MIPI_CTRL00 0x3600
3752 +#define OV5630_MIPI_CTRL01 0x3601
3753 +#define OV5630_MIPI_CTRL02 0x3602
3754 +#define OV5630_MIPI_CTRL03 0x3603
3755 +#define OV5630_MIPI_CTRL04 0x3604
3756 +#define OV5630_MIPI_CTRL05 0x3605
3757 +#define OV5630_MIPI_CTRL06 0x3606
3758 +#define OV5630_MIPI_CTRL07 0x3607
3759 +#define OV5630_MIPI_CTRL08 0x3608
3760 +#define OV5630_MIPI_CTRL09 0x3609
3761 +#define OV5630_MIPI_CTRL0A 0x360A
3762 +#define OV5630_MIPI_CTRL0B 0x360B
3763 +#define OV5630_MIPI_CTRL0C 0x360C
3764 +#define OV5630_MIPI_CTRL0D 0x360D
3765 +#define OV5630_MIPI_CTRL0E 0x360E
3766 +#define OV5630_MIPI_CTRL0F 0x360F
3767 +#define OV5630_MIPI_CTRL10 0x3610
3768 +#define OV5630_MIPI_CTRL11 0x3611
3769 +#define OV5630_MIPI_CTRL12 0x3612
3770 +#define OV5630_MIPI_CTRL13 0x3613
3771 +#define OV5630_MIPI_CTRL14 0x3614
3772 +#define OV5630_MIPI_CTRL15 0x3615
3773 +#define OV5630_MIPI_CTRL16 0x3616
3774 +#define OV5630_MIPI_CTRL17 0x3617
3775 +#define OV5630_MIPI_CTRL18 0x3618
3776 +#define OV5630_MIPI_CTRL19 0x3619
3777 +#define OV5630_MIPI_CTRL1A 0x361A
3778 +#define OV5630_MIPI_CTRL1B 0x361B
3779 +#define OV5630_MIPI_CTRL1C 0x361C
3780 +#define OV5630_MIPI_CTRL1D 0x361D
3781 +#define OV5630_MIPI_CTRL1E 0x361E
3782 +#define OV5630_MIPI_CTRL1F 0x361F
3783 +#define OV5630_MIPI_CTRL20 0x3620
3784 +#define OV5630_MIPI_CTRL21 0x3621
3785 +#define OV5630_MIPI_CTRL22 0x3622
3786 +#define OV5630_MIPI_CTRL23 0x3623
3787 +#define OV5630_MIPI_CTRL24 0x3624
3788 +#define OV5630_MIPI_CTRL25 0x3625
3789 +#define OV5630_MIPI_CTRL26 0x3626
3790 +#define OV5630_MIPI_CTRL27 0x3627
3791 +#define OV5630_MIPI_CTRL28 0x3628
3792 +#define OV5630_MIPI_CTRL29 0x3629
3793 +#define OV5630_MIPI_CTRL2A 0x362A
3794 +#define OV5630_MIPI_CTRL2B 0x362B
3795 +#define OV5630_MIPI_CTRL2C 0x362C
3796 +#define OV5630_MIPI_CTRL2D 0x362D
3797 +#define OV5630_MIPI_CTRL2E 0x362E
3798 +#define OV5630_MIPI_CTRL2F 0x362F
3799 +#define OV5630_MIPI_CTRL30 0x3630
3800 +#define OV5630_MIPI_CTRL31 0x3631
3801 +#define OV5630_MIPI_CTRL32 0x3632
3802 +#define OV5630_MIPI_CTRL33 0x3633
3803 +#define OV5630_MIPI_CTRL34 0x3634
3804 +#define OV5630_MIPI_CTRL35 0x3635
3805 +#define OV5630_MIPI_CTRL36 0x3636
3806 +#define OV5630_MIPI_CTRL37 0x3637
3807 +#define OV5630_MIPI_CTRL38 0x3638
3808 +#define OV5630_MIPI_CTRL39 0x3639
3809 +#define OV5630_MIPI_CTRL3A 0x363A
3810 +#define OV5630_MIPI_CTRL3B 0x363B
3811 +#define OV5630_MIPI_CTRL3C 0x363C
3812 +#define OV5630_MIPI_CTRL3D 0x363D
3813 +#define OV5630_MIPI_CTRL3E 0x363E
3814 +#define OV5630_MIPI_CTRL3F 0x363F
3815 +#define OV5630_MIPI_RO61 0x3661
3816 +#define OV5630_MIPI_RO62 0x3662
3817 +#define OV5630_MIPI_RO63 0x3663
3818 +#define OV5630_MIPI_RO64 0x3664
3819 +#define OV5630_MIPI_RO65 0x3665
3820 +#define OV5630_MIPI_RO66 0x3666
3822 +/* General definition for ov5630 */
3823 +#define OV5630_OUTWND_MAX_H QSXXGA_PLUS4_SIZE_H
3824 +#define OV5630_OUTWND_MAX_V QSXGA_PLUS4_SIZE_V
3826 +struct regval_list {
3832 + * Default register value
3833 + * 5Mega Pixel, 2592x1944
3835 +static struct regval_list ov5630_def_reg[] = {
3836 + {0x300f, 0x00}, /*00*/
3887 + {0x300e, 0xb1/*b0*/}, /* Note this PLL setting*/
3888 + {0x300f, 0x10}, /*00*/
3889 + {0x3010, 0x07}, /*change from 0f according to SV */
3923 +/* MIPI register are removed by Wen */
3926 +static struct regval_list ov5630_res_qsxga_plus4[] = {
3929 + {0x3022, 0x0c/*0a*/},
3930 + {0x3023, 0xa0/*00*/},
3936 + /* 30fps , 96 MHZ*/
3937 + /* {0x300f, 0x10}, */
3961 +static struct regval_list ov5630_res_1080p[] = {
3965 + {0x3022, 0x0b/*0a*/},
3966 + {0x3023, 0x32/*00*/},
3970 + {0x3025, 0x6e/*70*/},
3982 + {0x3315, 0x82/*80*/},
3986 + /* 30fps , 96 MHZ*/
3987 + {0x300f, 0x10}, /* 00 */
4010 +/* 1280x960 V1F2_H1F2 */
4011 +static struct regval_list ov5630_res_xga_plus[] = {
4014 + {0x3022, 0x0c/*07*/},
4015 + {0x3023, 0x8c/*76*/},
4021 + {0x3027, 0x10/*14*/},
4025 + {0x302b, 0xa7/*a7*/},
4034 + {0x3315, 0x02/*00*/},
4038 + {0x300f, 0x10}, /* 00 */
4060 +/* 1280x720, V1F2 & H1F2 */
4061 +static struct regval_list ov5630_res_720p[] = {
4071 + /* Crop then downscale */
4094 + /* Add this to test setting from OVT */
4095 + {0x300f, 0x10}, /*00*/
4118 +static struct regval_list ov5630_res_vga_ac04_bill[] = {
4127 + {0x3025, 0x2c},/*2c*/
4143 + {0x3315, 0x04},/*04*/
4148 + {0x300f, 0x10/*00*/},
4177 diff --git a/drivers/media/video/mrstci/mrstov5630_motor/Kconfig b/drivers/media/video/mrstci/mrstov5630_motor/Kconfig
4178 new file mode 100644
4179 index 0000000..b6dcf62
4181 +++ b/drivers/media/video/mrstci/mrstov5630_motor/Kconfig
4183 +config VIDEO_MRST_OV5630_MOTOR
4184 + tristate "Moorestown OV5630 motor"
4185 + depends on I2C && VIDEO_MRST_ISP && VIDEO_MRST_OV5630
4188 + Say Y here if your platform support OV5630 motor
4190 + To compile this driver as a module, choose M here: the
4191 + module will be called mrstov2650.ko.
4192 diff --git a/drivers/media/video/mrstci/mrstov5630_motor/Makefile b/drivers/media/video/mrstci/mrstov5630_motor/Makefile
4193 new file mode 100644
4194 index 0000000..056b2a6
4196 +++ b/drivers/media/video/mrstci/mrstov5630_motor/Makefile
4198 +obj-$(CONFIG_VIDEO_MRST_OV2650) += mrstov5630_motor.o
4200 +EXTRA_CFLAGS += -I$(src)/../include
4201 diff --git a/drivers/media/video/mrstci/mrstov5630_motor/mrstov5630_motor.c b/drivers/media/video/mrstci/mrstov5630_motor/mrstov5630_motor.c
4202 new file mode 100644
4203 index 0000000..1bb7274
4205 +++ b/drivers/media/video/mrstci/mrstov5630_motor/mrstov5630_motor.c
4208 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
4210 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
4212 + * This program is free software; you can redistribute it and/or
4213 + * modify it under the terms of the GNU General Public License version
4214 + * 2 as published by the Free Software Foundation.
4216 + * This program is distributed in the hope that it will be useful,
4217 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4218 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4219 + * GNU General Public License for more details.
4221 + * You should have received a copy of the GNU General Public License
4222 + * along with this program; if not, write to the Free Software
4223 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
4224 + * 02110-1301, USA.
4227 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
4230 +#include <linux/module.h>
4231 +#include <linux/types.h>
4232 +#include <linux/kernel.h>
4233 +#include <linux/mm.h>
4234 +#include <linux/string.h>
4235 +#include <linux/errno.h>
4236 +#include <linux/init.h>
4237 +#include <linux/kmod.h>
4238 +#include <linux/device.h>
4239 +#include <linux/delay.h>
4240 +#include <linux/fs.h>
4241 +#include <linux/init.h>
4242 +#include <linux/slab.h>
4243 +#include <linux/delay.h>
4244 +#include <linux/i2c.h>
4245 +#include <linux/gpio.h>
4247 +#include <media/v4l2-device.h>
4248 +#include <media/v4l2-chip-ident.h>
4249 +#include <media/v4l2-i2c-drv.h>
4251 +#include "ov5630_motor.h"
4254 +#include <asm/ipc_defs.h>
4255 +#define PMIC_WRITE1(ipcbuf, reg1, val1) \
4257 + memset(&ipcbuf, 0, sizeof(struct ipc_pmic_reg_data)); \
4259 + ipcbuf.num_entries = 1; \
4260 + ipcbuf.pmic_reg_data[0].register_address = reg1; \
4261 + ipcbuf.pmic_reg_data[0].value = val1; \
4262 + if (ipc_pmic_register_write(&ipcbuf, 1) != 0) { \
4267 +static int mrstov5630_motor_debug;
4268 +module_param(mrstov5630_motor_debug, int, 0644);
4269 +MODULE_PARM_DESC(mrstov5630_motor_debug, "Debug level (0-1)");
4271 +#define dprintk(level, fmt, arg...) do { \
4272 + if (mrstov5630_motor_debug >= level) \
4273 + printk(KERN_DEBUG "mrstisp@%s: " fmt "\n", \
4274 + __func__, ## arg); } \
4277 +#define eprintk(fmt, arg...) \
4278 + printk(KERN_ERR "mrstisp@%s: line %d: " fmt "\n", \
4279 + __func__, __LINE__, ## arg);
4281 +#define DBG_entering dprintk(2, "entering");
4282 +#define DBG_leaving dprintk(2, "leaving");
4283 +#define DBG_line dprintk(2, " line: %d", __LINE__);
4285 +static inline struct ov5630_motor *to_motor_config(struct v4l2_subdev *sd)
4287 + return container_of(sd, struct ov5630_motor, sd);
4290 +static int motor_read(struct i2c_client *c, u16 *reg)
4293 + struct i2c_msg msg;
4296 + /* Read needs two message to go */
4300 + memset(&msg, 0, sizeof(msg));
4301 + msg.addr = c->addr;
4304 + msg.flags = I2C_M_RD;
4306 + ret = i2c_transfer(c->adapter, &msg, 1);
4308 + *reg = (msgbuf[0] << 8 | msgbuf[1]);
4310 + ret = (ret == 1) ? 0 : -1;
4314 +static int motor_write(struct i2c_client *c, u16 reg)
4317 + struct i2c_msg msg;
4320 + /* Writing only needs one message */
4321 + memset(&msg, 0, sizeof(msg));
4322 + msgbuf[0] = reg >> 8;
4325 + msg.addr = c->addr;
4330 + ret = i2c_transfer(c->adapter, &msg, 1);
4332 + ret = (ret == 1) ? 0 : -1;
4336 +static int ov5630_motor_goto_position(struct i2c_client *c,
4337 + unsigned short code,
4338 + struct ov5630_motor *config)
4340 + int max_code, min_code;
4344 + max_code = config->macro_code;
4345 + min_code = config->infin_code;
4347 + if (code > max_code)
4349 + if (code < min_code)
4352 + cmdh = (MOTOR_DAC_CODE_H(code));
4353 + cmdl = (MOTOR_DAC_CODE_L(code) | MOTOR_DAC_CTRL_MODE_2(SUB_MODE_4));
4354 + cmd = cmdh << 8 | cmdl;
4356 + motor_write(c, cmd);
4357 + /*Delay more than full-scale transition time 8.8ms*/
4359 + motor_read(c, &val);
4361 + return (cmd == val ? 0 : -1);
4364 +int ov5630_motor_wakeup(void)
4366 + return gpio_direction_output(GPIO_AF_PD, 1);
4369 +int ov5630_motor_standby(void)
4371 + return gpio_direction_output(GPIO_AF_PD, 0);
4374 +int ov5630_motor_init(struct i2c_client *client, struct ov5630_motor *config)
4377 + int infin_cur, macro_cur;
4379 + /* Power on motor */
4380 + struct ipc_pmic_reg_data ipcbuf;
4382 + PMIC_WRITE1(ipcbuf, 0x50, 0x27);
4383 + printk(KERN_WARNING "Power on Vcc33 for motor\n");
4386 + infin_cur = MAX(MOTOR_INFIN_CUR, MOTOR_DAC_MIN_CUR);
4387 + macro_cur = MIN(MOTOR_MACRO_CUR, MOTOR_DAC_MAX_CUR);
4389 + config->infin_cur = infin_cur;
4390 + config->macro_cur = macro_cur;
4392 + config->infin_code = (int)((infin_cur * MOTOR_DAC_MAX_CODE)
4393 + / MOTOR_DAC_MAX_CUR);
4394 + config->macro_code = (int)((macro_cur * MOTOR_DAC_MAX_CODE)
4395 + / MOTOR_DAC_MAX_CUR);
4397 + config->max_step = ((config->macro_code - config->infin_code)
4398 + >> MOTOR_STEP_SHIFT) + 1;
4399 + /* Note here, maybe macro_code */
4400 + ret = ov5630_motor_goto_position(client, config->infin_code, config);
4402 + config->cur_code = config->infin_code;
4404 + printk(KERN_ERR "Error while initializing motor\n");
4409 +int ov5630_motor_set_focus(struct i2c_client *c, int step,
4410 + struct ov5630_motor *config)
4413 + int max_step = config->max_step;
4414 + unsigned int val = step;
4417 + dprintk(1, "setting setp %d", step);
4418 + if (val > max_step)
4421 + s_code = (val << MOTOR_STEP_SHIFT);
4422 + s_code += config->infin_code;
4424 + ret = ov5630_motor_goto_position(c, s_code, config);
4426 + config->cur_code = s_code;
4432 +static int ov5630_motor_s_ctrl(struct v4l2_subdev *sd,
4433 + struct v4l2_control *ctrl)
4435 + struct i2c_client *c = v4l2_get_subdevdata(sd);
4436 + struct ov5630_motor *config = to_motor_config(sd);
4440 + ret = ov5630_motor_set_focus(c, ctrl->value, config);
4442 + eprintk("error call ov5630_motor_set_focue");
4448 +int ov5630_motor_get_focus(struct i2c_client *c, unsigned int *step,
4449 + struct ov5630_motor *config)
4453 + ret_step = ((config->cur_code - config->infin_code)
4454 + >> MOTOR_STEP_SHIFT);
4456 + if (ret_step <= config->max_step)
4459 + *step = config->max_step;
4464 +static int ov5630_motor_g_ctrl(struct v4l2_subdev *sd,
4465 + struct v4l2_control *ctrl)
4467 + struct i2c_client *c = v4l2_get_subdevdata(sd);
4468 + struct ov5630_motor *config = to_motor_config(sd);
4472 + dprintk(2, "c = %p, config = %p, ctrl = %p", c, config, ctrl);
4473 + ret = ov5630_motor_get_focus(c, &ctrl->value, config);
4475 + eprintk("error call ov5630_motor_get_focue");
4481 +int ov5630_motor_max_step(struct i2c_client *c, unsigned int *max_code,
4482 + struct ov5630_motor *config)
4484 + if (config->max_step != 0)
4485 + *max_code = config->max_step;
4489 +static int ov5630_motor_queryctrl(struct v4l2_subdev *sd,
4490 + struct v4l2_queryctrl *qc)
4492 + struct ov5630_motor *config = to_motor_config(sd);
4496 + if (qc->id != V4L2_CID_FOCUS_ABSOLUTE)
4499 + dprintk(1, "got focus range of %d", config->max_step);
4500 + if (config->max_step != 0)
4501 + qc->maximum = config->max_step;
4505 +static const struct v4l2_subdev_core_ops ov5630_motor_core_ops = {
4507 + .queryctrl = ov5630_queryctrl,
4508 + .g_ctrl = ov5630_g_ctrl,
4510 + .g_ctrl = ov5630_motor_g_ctrl,
4511 + .s_ctrl = ov5630_motor_s_ctrl,
4512 + .queryctrl = ov5630_motor_queryctrl,
4515 +static const struct v4l2_subdev_ops ov5630_motor_ops = {
4516 + .core = &ov5630_motor_core_ops,
4519 +static int ov5630_motor_detect(struct i2c_client *client)
4521 + struct i2c_adapter *adapter = client->adapter;
4522 + int adap_id = i2c_adapter_id(adapter);
4524 + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
4525 + eprintk("error i2c check func");
4529 + if (adap_id != 1) {
4530 + eprintk("adap_id != 1");
4534 + /* if (ov5630_motor_wakeup()) */
4535 + /* return -ENODEV; */
4536 + ov5630_motor_wakeup();
4540 + ov5630_motor_read(client, (u32)OV5630_PID_H, &value);
4541 + if ((u8)value != 0x56) {
4542 + eprintk("PID != 0x56, but %x", value);
4543 + dprintk(2, "client->addr = %x", client->addr);
4551 +static int ov5630_motor_probe(struct i2c_client *client,
4552 + const struct i2c_device_id *id)
4554 + struct ov5630_motor *info;
4555 + struct v4l2_subdev *sd;
4557 +/* struct i2c_client *motor; */
4560 + v4l_info(client, "chip found @ 0x%x (%s)\n",
4561 + client->addr << 1, client->adapter->name);
4563 + * Setup sensor configuration structure
4565 + info = kzalloc(sizeof(struct ov5630_motor), GFP_KERNEL);
4567 + eprintk("fail to malloc for ci_motor");
4572 + ret = ov5630_motor_detect(client);
4574 + eprintk("error ov5630_motor_detect");
4579 + v4l2_i2c_subdev_init(sd, client, &ov5630_motor_ops);
4582 + * Initialization OV5630
4583 + * then turn into standby mode
4585 + /* ret = ov5630_motor_standby(); */
4586 + ret = ov5630_motor_init(client, info);
4588 + eprintk("error calling ov5630_motor_init");
4603 + * XXX: Need to be checked
4605 +static int ov5630_motor_remove(struct i2c_client *client)
4607 + struct v4l2_subdev *sd = i2c_get_clientdata(client);
4611 + v4l2_device_unregister_subdev(sd);
4612 + kfree(to_motor_config(sd));
4618 +static const struct i2c_device_id ov5630_motor_id[] = {
4619 + {"ov5630_motor", 0},
4622 +MODULE_DEVICE_TABLE(i2c, ov5630_motor_id);
4624 +static struct v4l2_i2c_driver_data v4l2_i2c_data = {
4625 + .name = "ov5630_motor",
4626 + .probe = ov5630_motor_probe,
4627 + .remove = ov5630_motor_remove,
4628 + /* .suspend = ov5630_suspend,
4629 + * .resume = ov5630_resume, */
4630 + .id_table = ov5630_motor_id,
4632 +MODULE_AUTHOR("Xiaolin Zhang <xiaolin.zhang@intel.com>");
4633 +MODULE_DESCRIPTION("A low-level driver for OmniVision 5630 sensors");
4634 +MODULE_LICENSE("GPL");
4635 diff --git a/drivers/media/video/mrstci/mrstov5630_motor/ov5630_motor.h b/drivers/media/video/mrstci/mrstov5630_motor/ov5630_motor.h
4636 new file mode 100644
4637 index 0000000..302c218
4639 +++ b/drivers/media/video/mrstci/mrstov5630_motor/ov5630_motor.h
4642 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
4644 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
4646 + * This program is free software; you can redistribute it and/or
4647 + * modify it under the terms of the GNU General Public License version
4648 + * 2 as published by the Free Software Foundation.
4650 + * This program is distributed in the hope that it will be useful,
4651 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4652 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4653 + * GNU General Public License for more details.
4655 + * You should have received a copy of the GNU General Public License
4656 + * along with this program; if not, write to the Free Software
4657 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
4658 + * 02110-1301, USA.
4661 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
4664 +#include <media/v4l2-subdev.h>
4666 +/* VCM start current (mA) */
4667 +#define MOTOR_INFIN_CUR 15
4668 +/* VCM max current for Macro (mA) */
4669 +#define MOTOR_MACRO_CUR 90
4670 +/* DAC output max current (mA) */
4671 +#define MOTOR_DAC_MAX_CUR 100
4672 +/* DAC output min current (mA) */
4673 +#define MOTOR_DAC_MIN_CUR 3
4675 +#define MOTOR_DAC_BIT_RES 10
4676 +#define MOTOR_DAC_MAX_CODE ((1 << MOTOR_DAC_BIT_RES) - 1)
4678 +#define MOTOR_STEP_SHIFT 4
4680 +#define MAX(x, y) ((x) > (y) ? (x) : (y))
4681 +#define MIN(x, y) ((x) < (y) ? (x) : (y))
4683 +/* DAC register related define */
4684 +#define MOTOR_POWER_DOWN (1 << 7)
4685 +#define PD_ENABLE (1 << 7)
4686 +#define PD_DISABLE (0)
4688 +#define MOTOR_DAC_CODE_H(x) ((x >> 4) & 0x3f)
4689 +#define MOTOR_DAC_CODE_L(x) ((x << 4) & 0xf0)
4691 +#define MOTOR_DAC_CTRL_MODE_0 0x00
4692 +#define MOTOR_DAC_CTRL_MODE_1(x) (x & 0x07)
4693 +#define MOTOR_DAC_CTRL_MODE_2(x) ((x & 0x07) | 0x08)
4695 +#define SUB_MODE_1 0x01
4696 +#define SUB_MODE_2 0x02
4697 +#define SUB_MODE_3 0x03
4698 +#define SUB_MODE_4 0x04
4699 +#define SUB_MODE_5 0x05
4700 +#define SUB_MODE_6 0x06
4701 +#define SUB_MODE_7 0x07
4703 +#define OV5630_MOTOR_ADDR (0x18 >> 1)
4704 +#define POWER_EN_PIN 7
4705 +#define GPIO_AF_PD 95
4707 +struct ov5630_motor{
4708 + unsigned int infin_cur;
4709 + unsigned int infin_code;
4710 + unsigned int macro_cur;
4711 + unsigned int macro_code;
4712 + unsigned int max_step;
4713 + unsigned int cur_code;
4714 + struct v4l2_subdev sd;
4717 +extern int ov5630_motor_init(struct i2c_client *client, struct ov5630_motor
4719 +extern int ov5630_motor_standby(void);
4720 +extern int ov5630_motor_wakeup(void);
4721 +extern int ov5630_motor_set_focus(struct i2c_client *c, int step,
4722 + struct ov5630_motor *config);
4723 +extern int ov5630_motor_get_focus(struct i2c_client *c, unsigned int *step,
4724 + struct ov5630_motor *config);
4725 +extern int ov5630_motor_max_step(struct i2c_client *c, unsigned int *max_code,
4726 + struct ov5630_motor *config);
4727 diff --git a/drivers/media/video/mrstci/mrstov9665/Kconfig b/drivers/media/video/mrstci/mrstov9665/Kconfig
4728 new file mode 100644
4729 index 0000000..ba9b692
4731 +++ b/drivers/media/video/mrstci/mrstov9665/Kconfig
4733 +config VIDEO_MRST_OV9665
4734 + tristate "Moorestown OV9665 SoC Sensor"
4735 + depends on I2C && VIDEO_MRST_ISP
4738 + Say Y here if your platform support OV9665 SoC Sensor.
4740 + To compile this driver as a module, choose M here: the
4741 + module will be called mrstov9665.ko.
4742 diff --git a/drivers/media/video/mrstci/mrstov9665/Makefile b/drivers/media/video/mrstci/mrstov9665/Makefile
4743 new file mode 100644
4744 index 0000000..871b6bf
4746 +++ b/drivers/media/video/mrstci/mrstov9665/Makefile
4748 +obj-$(CONFIG_VIDEO_MRST_OV9665) += mrstov9665.o
4750 +EXTRA_CFLAGS += -I$(src)/../include
4751 diff --git a/drivers/media/video/mrstci/mrstov9665/mrstov9665.c b/drivers/media/video/mrstci/mrstov9665/mrstov9665.c
4752 new file mode 100644
4753 index 0000000..04e553a
4755 +++ b/drivers/media/video/mrstci/mrstov9665/mrstov9665.c
4758 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
4760 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
4762 + * This program is free software; you can redistribute it and/or
4763 + * modify it under the terms of the GNU General Public License version
4764 + * 2 as published by the Free Software Foundation.
4766 + * This program is distributed in the hope that it will be useful,
4767 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4768 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4769 + * GNU General Public License for more details.
4771 + * You should have received a copy of the GNU General Public License
4772 + * along with this program; if not, write to the Free Software
4773 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
4774 + * 02110-1301, USA.
4777 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
4780 +#include <linux/module.h>
4781 +#include <linux/types.h>
4782 +#include <linux/kernel.h>
4783 +#include <linux/mm.h>
4784 +#include <linux/string.h>
4785 +#include <linux/errno.h>
4786 +#include <linux/init.h>
4787 +#include <linux/kmod.h>
4788 +#include <linux/device.h>
4789 +#include <linux/delay.h>
4790 +#include <linux/fs.h>
4791 +#include <linux/init.h>
4792 +#include <linux/slab.h>
4793 +#include <linux/delay.h>
4794 +#include <linux/i2c.h>
4795 +#include <linux/gpio.h>
4796 +#include <linux/videodev2.h>
4798 +#include <media/v4l2-device.h>
4799 +#include <media/v4l2-chip-ident.h>
4800 +#include <media/v4l2-i2c-drv.h>
4802 +#include "ci_sensor_common.h"
4803 +#include "ov9665.h"
4805 +static int mrstov9665_debug;
4806 +module_param(mrstov9665_debug, int, 0644);
4807 +MODULE_PARM_DESC(mrstov9665_debug, "Debug level (0-1)");
4809 +#define dprintk(level, fmt, arg...) do { \
4810 + if (mrstov9665_debug >= level) \
4811 + printk(KERN_DEBUG "mrstisp@%s: " fmt "\n", \
4812 + __func__, ## arg); } \
4815 +#define eprintk(fmt, arg...) \
4816 + printk(KERN_ERR "mrstisp@%s: line %d: " fmt "\n", \
4817 + __func__, __LINE__, ## arg);
4819 +#define DBG_entering dprintk(2, "entering");
4820 +#define DBG_leaving dprintk(2, "leaving");
4821 +#define DBG_line dprintk(2, " line: %d", __LINE__);
4823 +static inline struct ci_sensor_config *to_sensor_config(struct v4l2_subdev *sd)
4825 + return container_of(sd, struct ci_sensor_config, sd);
4828 +static struct ov9665_format_struct {
4830 + __u32 pixelformat;
4831 + struct regval_list *regs;
4832 +} ov9665_formats[] = {
4834 + .desc = "YUYV 4:2:2",
4835 + .pixelformat = SENSOR_MODE_BT601,
4839 +#define N_OV9665_FMTS ARRAY_SIZE(ov9665_formats)
4841 +static struct ov9665_res_struct {
4846 + /* FIXME: correct the fps values.. */
4849 + struct regval_list *regs;
4853 + .res = SENSOR_RES_SXGA,
4858 + .regs = ov9665_res_sxga,
4862 + .res = SENSOR_RES_VGA,
4867 + .regs = ov9665_res_vga,
4870 +#define N_RES (ARRAY_SIZE(ov9665_res))
4873 + * I2C Read & Write stuff
4875 +static int ov9665_read(struct i2c_client *c, unsigned char reg,
4876 + unsigned char *value)
4880 + ret = i2c_smbus_read_byte_data(c, reg);
4882 + *value = (unsigned char) ret;
4888 +static int ov9665_write(struct i2c_client *c, unsigned char reg,
4889 + unsigned char value)
4891 + int ret = i2c_smbus_write_byte_data(c, reg, value);
4892 + if (reg == 0x12 && (value & 0x80))
4893 + msleep(2); /* Wait for reset to run */
4898 + * Write a list of register settings; ff/ff stops the process.
4900 +static int ov9665_write_array(struct i2c_client *c, struct regval_list *vals)
4902 + struct regval_list *p;
4907 + while (p->reg_num != 0xff) {
4908 + ov9665_write(c, p->reg_num, p->value);
4909 + ov9665_read(c, p->reg_num, &read_val);
4910 + if (read_val != p->value)
4919 +static int ov9665_set_data_pin_in(struct i2c_client *client)
4923 + ret += ov9665_write(client, 0xd5, 0x00);
4924 + ret += ov9665_write(client, 0xd6, 0x00);
4929 +static int ov9665_set_data_pin_out(struct i2c_client *client)
4933 + ret += ov9665_write(client, 0xd5, 0xff);
4934 + ret += ov9665_write(client, 0xd6, 0xff);
4939 + * Sensor specific helper function
4941 +static int ov9665_standby(void)
4943 + /* Pull the pin to high to hardware standby */
4944 + gpio_set_value(GPIO_STDBY_PIN, 1);
4945 + dprintk(1, "PM: standby called\n");
4949 +static int ov9665_wakeup(void)
4951 + /* Pull the pin to low*/
4952 + gpio_set_value(GPIO_STDBY_PIN, 0);
4953 + dprintk(1, "PM: wakeup called\n");
4958 +static int ov9665_s_power(struct v4l2_subdev *sd, u32 val)
4967 +static int ov9665_init(struct i2c_client *c)
4970 + struct v4l2_subdev *sd = i2c_get_clientdata(c);
4971 + struct ci_sensor_config *info = to_sensor_config(sd);
4974 + /* Fill the configuration structure */
4975 + /* Note this default configuration value */
4976 + info->mode = ov9665_formats[0].pixelformat;
4977 + info->res = ov9665_res[0].res;
4978 + info->type = SENSOR_TYPE_SOC;
4979 + info->bls = SENSOR_BLS_OFF;
4980 + info->gamma = SENSOR_GAMMA_ON;
4981 + info->cconv = SENSOR_CCONV_ON;
4982 + info->blc = SENSOR_BLC_AUTO;
4983 + info->agc = SENSOR_AGC_AUTO;
4984 + info->awb = SENSOR_AWB_AUTO;
4985 + info->aec = SENSOR_AEC_AUTO;
4986 + info->bus_width = SENSOR_BUSWIDTH_8BIT_ZZ;
4987 + info->ycseq = SENSOR_YCSEQ_YCBYCR;
4988 + info->conv422 = SENSOR_CONV422_COSITED;
4989 + info->bpat = SENSOR_BPAT_GRGRBGBG;
4990 + info->field_inv = SENSOR_FIELDINV_NOSWAP;
4991 + info->field_sel = SENSOR_FIELDSEL_BOTH;
4992 + info->hpol = SENSOR_HPOL_REFPOS;
4993 + info->vpol = SENSOR_VPOL_POS;
4994 + info->edge = SENSOR_EDGE_FALLING;
4995 + info->flicker_freq = SENSOR_FLICKER_100;
4996 + info->cie_profile = 0;
4997 + memcpy(info->name, "ov9665", 7);
4999 + ret = ov9665_write(c, 0x12, 0x80);
5000 + /* Set registers into default config value */
5001 + ret += ov9665_write_array(c, ov9665_def_reg);
5003 + ov9665_read(c, 0x09, ®);
5005 + ov9665_write(c, 0x09, reg);
5006 + ov9665_set_data_pin_in(c);
5012 +static int distance(struct ov9665_res_struct *res, u32 w, u32 h)
5015 + if (res->width < w || res->height < h)
5018 + ret = ((res->width - w) + (res->height - h));
5021 +static int ov9665_try_res(u32 *w, u32 *h)
5023 + struct ov9665_res_struct *res_index, *p = NULL;
5024 + int dis, last_dis = ov9665_res->width + ov9665_res->height;
5026 + dprintk(1, "&&&&& before %dx%d", *w, *h);
5027 + for (res_index = ov9665_res;
5028 + res_index < ov9665_res + N_RES;
5030 + if ((res_index->width <= *w) && (res_index->height <= *h))
5032 + dis = distance(res_index, *w, *h);
5033 + if (dis < last_dis) {
5038 + if ((res_index->width < *w) || (res_index->height < *h)) {
5039 + if (res_index != ov9665_res)
5048 + if ((w != NULL) && (h != NULL)) {
5053 + if (res_index == ov9665_res + N_RES)
5054 + res_index = ov9665_res + N_RES - 1;
5056 + *w = res_index->width;
5057 + *h = res_index->height;
5059 + dprintk(1, "&&&&& after %dx%d", *w, *h);
5063 +static struct ov9665_res_struct *ov9665_to_res(u32 w, u32 h)
5065 + struct ov9665_res_struct *res_index;
5067 + for (res_index = ov9665_res;
5068 + res_index < ov9665_res + N_RES;
5070 + if ((res_index->width == w) && (res_index->height == h))
5073 + if (res_index >= ov9665_res + N_RES)
5074 + res_index--; /* Take the bigger one */
5079 +static int ov9665_try_fmt(struct v4l2_subdev *sd,
5080 + struct v4l2_format *fmt)
5083 + return ov9665_try_res(&fmt->fmt.pix.width, &fmt->fmt.pix.height);
5087 +static int ov9665_get_fmt(struct v4l2_subdev *sd,
5088 + struct v4l2_format *fmt)
5090 + struct ci_sensor_config *info = to_sensor_config(sd);
5091 + unsigned short width, height;
5094 + ci_sensor_res2size(info->res, &width, &height);
5096 + /* Marked the current sensor res as being "used" */
5097 + for (index = 0; index < N_RES; index++) {
5098 + if ((width == ov9665_res[index].width) &&
5099 + (height == ov9665_res[index].height)) {
5100 + ov9665_res[index].used = 1;
5103 + ov9665_res[index].used = 0;
5106 + fmt->fmt.pix.width = width;
5107 + fmt->fmt.pix.height = height;
5111 +static int ov9665_set_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
5113 + struct i2c_client *c = v4l2_get_subdevdata(sd);
5114 + struct ci_sensor_config *info = to_sensor_config(sd);
5116 + struct ov9665_res_struct *res_index;
5117 + u32 width, height;
5122 + width = fmt->fmt.pix.width;
5123 + height = fmt->fmt.pix.height;
5125 + ret = ov9665_try_res(&width, &height);
5126 + res_index = ov9665_to_res(width, height);
5129 + /* if ((info->res != res_index->res) && (res_index->regs)) { */
5130 + if ( res_index->regs) {
5131 + ret = ov9665_write(c, 0x12, 0x80);
5132 + ret += ov9665_write_array(c, ov9665_def_reg);
5133 + ret += ov9665_write_array(c, res_index->regs);
5134 + /* Add delay here to get better image */
5136 + for (index = 0; index < N_RES; index++) {
5137 + if ((width == ov9665_res[index].width) &&
5138 + (height == ov9665_res[index].height)) {
5139 + ov9665_res[index].used = 1;
5142 + ov9665_res[index].used = 0;
5145 + for (index = 0; index < N_RES; index++)
5146 + dprintk(2, "index = %d, used = %d\n", index,
5147 + ov9665_res[index].used);
5150 + info->res = res_index->res;
5156 +static int ov9665_q_hflip(struct v4l2_subdev *sd, __s32 *value)
5158 + struct i2c_client *client = v4l2_get_subdevdata(sd);
5160 + unsigned char v = 0;
5162 + ret = ov9665_read(client, 0x04, &v);
5163 + *value = ((v & 0x80) == 0x80);
5167 +static int ov9665_t_hflip(struct v4l2_subdev *sd, int value)
5169 + struct i2c_client *client = v4l2_get_subdevdata(sd);
5170 + unsigned char v = 0;
5173 + value = value >= 1 ? 1 : 0;
5174 + ret = ov9665_read(client, 0x33, &v);
5179 + ret += ov9665_write(client, 0x33, v);
5181 + ret += ov9665_read(client, 0x04, &v);
5186 + ret += ov9665_write(client, 0x04, v);
5187 + msleep(10); /* FIXME */
5191 +static int ov9665_q_vflip(struct v4l2_subdev *sd, __s32 *value)
5193 + struct i2c_client *client = v4l2_get_subdevdata(sd);
5195 + unsigned char v = 0;
5197 + ret = ov9665_read(client, 0x04, &v);
5198 + *value = ((v & 0x40) == 0x40);
5202 +static int ov9665_t_vflip(struct v4l2_subdev *sd, int value)
5204 + struct i2c_client *client = v4l2_get_subdevdata(sd);
5205 + unsigned char v = 0;
5208 + value = value >= 1 ? 1 : 0;
5209 + ret = ov9665_read(client, 0x04, &v);
5214 + ret += ov9665_write(client, 0x04, v);
5215 + msleep(10); /* FIXME */
5219 +static struct ov9665_control {
5220 + struct v4l2_queryctrl qc;
5221 + int (*query)(struct v4l2_subdev *sd, __s32 *value);
5222 + int (*tweak)(struct v4l2_subdev *sd, int value);
5223 +} ov9665_controls[] = {
5226 + .id = V4L2_CID_VFLIP,
5227 + .type = V4L2_CTRL_TYPE_BOOLEAN,
5228 + .name = "Vertical flip",
5232 + .default_value = 0,
5234 + .tweak = ov9665_t_vflip,
5235 + .query = ov9665_q_vflip,
5239 + .id = V4L2_CID_HFLIP,
5240 + .type = V4L2_CTRL_TYPE_BOOLEAN,
5241 + .name = "Horizontal mirror",
5245 + .default_value = 0,
5247 + .tweak = ov9665_t_hflip,
5248 + .query = ov9665_q_hflip,
5251 +#define N_CONTROLS (ARRAY_SIZE(ov9665_controls))
5253 +static struct ov9665_control *ov9665_find_control(__u32 id)
5257 + for (i = 0; i < N_CONTROLS; i++)
5258 + if (ov9665_controls[i].qc.id == id)
5259 + return ov9665_controls + i;
5263 +static int ov9665_queryctrl(struct v4l2_subdev *sd,
5264 + struct v4l2_queryctrl *qc)
5266 + struct ov9665_control *ctrl = ov9665_find_control(qc->id);
5274 +static int ov9665_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
5276 + struct ov9665_control *octrl = ov9665_find_control(ctrl->id);
5279 + if (octrl == NULL)
5281 + ret = octrl->query(sd, &ctrl->value);
5287 +static int ov9665_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
5289 + struct ov9665_control *octrl = ov9665_find_control(ctrl->id);
5292 + if (octrl == NULL)
5294 + ret = octrl->tweak(sd, ctrl->value);
5301 +static int ov9665_get_caps(struct i2c_client *c, struct ci_sensor_caps *caps)
5306 + caps->bus_width = SENSOR_BUSWIDTH_8BIT_ZZ;
5307 + caps->mode = SENSOR_MODE_BT601;
5308 + caps->field_inv = SENSOR_FIELDINV_NOSWAP;
5309 + caps->field_sel = SENSOR_FIELDSEL_BOTH;
5310 + caps->ycseq = SENSOR_YCSEQ_YCBYCR;
5311 + caps->conv422 = SENSOR_CONV422_COSITED;
5312 + caps->bpat = SENSOR_BPAT_GRGRBGBG;
5313 + caps->hpol = SENSOR_HPOL_REFPOS;
5314 + caps->vpol = SENSOR_VPOL_POS;
5315 + caps->edge = SENSOR_EDGE_FALLING;
5316 + caps->bls = SENSOR_BLS_OFF;
5317 + caps->gamma = SENSOR_GAMMA_ON;
5318 + caps->cconv = SENSOR_CCONV_ON;
5319 + caps->res = SENSOR_RES_SXGA | SENSOR_RES_VGA;
5320 + caps->blc = SENSOR_BLC_AUTO;
5321 + caps->agc = SENSOR_AGC_AUTO;
5322 + caps->awb = SENSOR_AWB_AUTO;
5323 + caps->aec = SENSOR_AEC_AUTO;
5324 + caps->cie_profile = 0;
5325 + caps->flicker_freq = SENSOR_FLICKER_100 | SENSOR_FLICKER_120;
5326 + caps->type = SENSOR_TYPE_SOC;
5327 + /* caps->name = "ov9665"; */
5328 + strcpy(caps->name, "ov9665");
5333 +static int ov9665_get_config(struct i2c_client *c,
5334 + struct ci_sensor_config *config)
5336 + struct ci_sensor_config *info = i2c_get_clientdata(c);
5338 + if (config == NULL) {
5339 + printk(KERN_WARNING "sensor_get_config: NULL pointer\n");
5343 + memset(config, 0, sizeof(struct ci_sensor_config *));
5344 + memcpy(config, info, sizeof(struct ci_sensor_config));
5349 +static int ov9665_setup(struct i2c_client *c,
5350 + const struct ci_sensor_config *config)
5353 + struct ov9665_res_struct *res_index;
5354 + struct ci_sensor_config *info = i2c_get_clientdata(c);
5357 + /* Soft reset camera first*/
5358 + ret = ov9665_write(c, 0x12, 0x80);
5360 + /* Set registers into default config value */
5361 + ret += ov9665_write_array(c, ov9665_def_reg);
5363 + /* set image resolution */
5364 + ci_sensor_res2size(config->res, &width, &high);
5365 + ret += ov9665_try_res(c, &width, &high);
5366 + res_index = ov9665_find_res(width, high);
5367 + if (res_index->regs)
5368 + ret += ov9665_write_array(c, res_index->regs);
5370 + info->res = res_index->res;
5372 + /* Add some delay here to get a better image*/
5378 +static int ov9665_set_data_pin_in(struct i2c_client *client)
5382 + ret += ov9665_write(client, 0xd5, 0x00);
5383 + ret += ov9665_write(client, 0xd6, 0x00);
5388 +static int ov9665_set_data_pin_out(struct i2c_client *client)
5392 + ret += ov9665_write(client, 0xd5, 0xff);
5393 + ret += ov9665_write(client, 0xd6, 0xff);
5398 + * File operation functions
5400 +static int ov9665_open(struct i2c_setting *c, void *priv)
5402 + struct i2c_client *client = c->sensor_client;
5405 + /* Just wake up sensor */
5406 + if (ov9665_wakeup())
5409 + ov9665_init(client);
5410 + ret = ov9665_read(client, 0x09, ®);
5412 + ret += ov9665_write(client, 0x09, reg);
5414 + if (ov9665_set_data_pin_in(client))
5417 + if (ov9665_standby())
5423 +static int ov9665_release(struct i2c_setting *c, void *priv)
5425 + /* Just suspend the sensor */
5426 + if (ov9665_standby())
5431 +static int ov9665_on(struct i2c_setting *c)
5433 + struct i2c_client *client = c->sensor_client;
5437 + ret = ov9665_read(client, 0x09, ®);
5438 + reg = reg & ~0x10;
5439 + ret = ov9665_write(client, 0x09, reg);
5441 + if (ov9665_set_data_pin_out(client))
5447 +static int ov9665_off(struct i2c_setting *c)
5449 + struct i2c_client *client = c->sensor_client;
5453 + ret = ov9665_read(client, 0x09, ®);
5455 + ret += ov9665_write(client, 0x09, reg);
5457 + if (ov9665_set_data_pin_in(client))
5463 +static struct sensor_device ov9665 = {
5465 + .type = SENSOR_TYPE_SOC,
5467 + .open = ov9665_open,
5468 + .release = ov9665_release,
5470 + .off = ov9665_off,
5471 + .querycap = ov9665_get_caps,
5472 + .get_config = ov9665_get_config,
5473 + .set_config = ov9665_setup,
5474 + .enum_parm = ov9665_queryctrl,
5475 + .get_parm = ov9665_g_ctrl,
5476 + .set_parm = ov9665_s_ctrl,
5477 + .try_res = ov9665_try_res,
5478 + .set_res = ov9665_set_res,
5479 + .suspend = ov9665_standby,
5480 + .resume = ov9665_wakeup,
5481 + .get_ls_corr_config = NULL,
5489 +static int ov9665_s_stream(struct v4l2_subdev *sd, int enable)
5491 + struct i2c_client *client = v4l2_get_subdevdata(sd);
5496 + ov9665_read(client, 0x09, ®);
5497 + reg = reg & ~0x10;
5498 + ov9665_write(client, 0x09, reg);
5499 + ov9665_set_data_pin_out(client);
5503 + ov9665_read(client, 0x09, ®);
5505 + ov9665_write(client, 0x09, reg);
5506 + ov9665_set_data_pin_in(client);
5513 +static int ov9665_enum_framesizes(struct v4l2_subdev *sd,
5514 + struct v4l2_frmsizeenum *fsize)
5516 + unsigned int index = fsize->index;
5520 + if (index >= N_RES)
5523 + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
5524 + fsize->discrete.width = ov9665_res[index].width;
5525 + fsize->discrete.height = ov9665_res[index].height;
5526 + fsize->reserved[0] = ov9665_res[index].used;
5533 +static int ov9665_enum_frameintervals(struct v4l2_subdev *sd,
5534 + struct v4l2_frmivalenum *fival)
5536 + unsigned int index = fival->index;
5540 + if (index >= N_RES)
5543 + fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
5544 + fival->discrete.numerator = 1;
5545 + fival->discrete.denominator = ov9665_res[index].fps;
5552 +static int ov9665_g_chip_ident(struct v4l2_subdev *sd,
5553 + struct v4l2_dbg_chip_ident *chip)
5555 + struct i2c_client *client = v4l2_get_subdevdata(sd);
5557 +#define V4L2_IDENT_OV9665 8246
5558 + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV9665, 0);
5561 +#ifdef CONFIG_VIDEO_ADV_DEBUG
5562 +static int ov9665_g_register(struct v4l2_subdev *sd,
5563 + struct v4l2_dbg_register *reg)
5565 + struct i2c_client *client = v4l2_get_subdevdata(sd);
5566 + unsigned char val = 0;
5569 + if (!v4l2_chip_match_i2c_client(client, ®->match))
5571 + if (!capable(CAP_SYS_ADMIN))
5573 + ret = ov9665_read(client, reg->reg & 0xffff, &val);
5579 +static int ov9665_s_register(struct v4l2_subdev *sd,
5580 + struct v4l2_dbg_register *reg)
5582 + struct i2c_client *client = v4l2_get_subdevdata(sd);
5584 + if (!v4l2_chip_match_i2c_client(client, ®->match))
5586 + if (!capable(CAP_SYS_ADMIN))
5588 + ov9665_write(client, reg->reg & 0xffff, reg->val & 0xff);
5593 +static const struct v4l2_subdev_video_ops ov9665_video_ops = {
5594 + .try_fmt = ov9665_try_fmt,
5595 + .s_fmt = ov9665_set_fmt,
5596 + .g_fmt = ov9665_get_fmt,
5597 + .s_stream = ov9665_s_stream,
5598 + .enum_framesizes = ov9665_enum_framesizes,
5599 + .enum_frameintervals = ov9665_enum_frameintervals,
5602 +static const struct v4l2_subdev_core_ops ov9665_core_ops = {
5603 + .g_chip_ident = ov9665_g_chip_ident,
5604 + .queryctrl = ov9665_queryctrl,
5605 + .g_ctrl = ov9665_g_ctrl,
5606 + .s_ctrl = ov9665_s_ctrl,
5607 + .s_gpio = ov9665_s_power,
5608 + /*.g_ext_ctrls = ov9665_g_ext_ctrls,*/
5609 + /*.s_ext_ctrls = ov9665_s_ext_ctrls,*/
5610 +#ifdef CONFIG_VIDEO_ADV_DEBUG
5611 + .g_register = ov9665_g_register,
5612 + .s_register = ov9665_s_register,
5616 +static const struct v4l2_subdev_ops ov9665_ops = {
5617 + .core = &ov9665_core_ops,
5618 + .video = &ov9665_video_ops,
5624 +static unsigned short normal_i2c[] = {0x30, I2C_CLIENT_END};
5627 +static struct i2c_driver ov9665_driver;
5629 +static int ov9665_detect(struct i2c_client *client)
5631 + struct i2c_adapter *adapter = client->adapter;
5632 + int adap_id = i2c_adapter_id(adapter);
5635 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
5643 + ov9665_read(client, 0x0a, &config);
5644 + if (config != 0x96)
5647 + ov9665_read(client, 0x0b, &config);
5648 + if (config != 0x63)
5654 +static int ov9665_probe(struct i2c_client *client,
5655 + const struct i2c_device_id *id)
5657 + struct ci_sensor_config *info;
5658 + struct v4l2_subdev *sd;
5663 + * Setup sensor configuration structure
5665 + info = kzalloc(sizeof(struct ci_sensor_config), GFP_KERNEL);
5669 + ret = ov9665_detect(client);
5676 + v4l2_i2c_subdev_init(sd, client, &ov9665_ops);
5679 + * Initialization OV9665
5680 + * then turn into standby mode
5682 + /* ret = ov9665_standby(); */
5683 + ret = ov9665_init(client);
5685 + eprintk("error init ov9665");
5690 + printk(KERN_INFO "Init ov9665 sensor success\n");
5700 + * XXX: Need to be checked
5702 +static int ov9665_remove(struct i2c_client *client)
5704 + struct v4l2_subdev *sd = i2c_get_clientdata(client);
5706 + v4l2_device_unregister_subdev(sd);
5707 + kfree(to_sensor_config(sd));
5712 +static const struct i2c_device_id ov9665_id[] = {
5717 +MODULE_DEVICE_TABLE(i2c, ov9665_id);
5719 +static struct v4l2_i2c_driver_data v4l2_i2c_data = {
5721 + .probe = ov9665_probe,
5722 + .remove = ov9665_remove,
5723 + .id_table = ov9665_id,
5726 +MODULE_AUTHOR("Xiaolin Zhang <xiaolin.zhang@intel.com>");
5727 +MODULE_DESCRIPTION("A low-level driver for OmniVision 9665 sensors");
5728 +MODULE_LICENSE("GPL");
5729 diff --git a/drivers/media/video/mrstci/mrstov9665/ov9665.h b/drivers/media/video/mrstci/mrstov9665/ov9665.h
5730 new file mode 100644
5731 index 0000000..6fc9d12
5733 +++ b/drivers/media/video/mrstci/mrstov9665/ov9665.h
5736 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
5738 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
5740 + * This program is free software; you can redistribute it and/or
5741 + * modify it under the terms of the GNU General Public License version
5742 + * 2 as published by the Free Software Foundation.
5744 + * This program is distributed in the hope that it will be useful,
5745 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5746 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5747 + * GNU General Public License for more details.
5749 + * You should have received a copy of the GNU General Public License
5750 + * along with this program; if not, write to the Free Software
5751 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
5752 + * 02110-1301, USA.
5755 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
5758 +#define I2C_OV9665 0x60
5759 +/* Should add to kernel source */
5760 +#define I2C_DRIVERID_OV9665 1047
5761 +/* GPIO pin on Moorestown */
5762 +#define GPIO_SCLK_25 44
5763 +#define GPIO_STB_PIN 47
5764 +#define GPIO_STDBY_PIN 48
5765 +#define GPIO_RESET_PIN 50
5767 +struct regval_list {
5773 + * Default register value
5776 +static struct regval_list ov9665_def_reg[] = {
5823 + {0x0C, 0x3a}, /* Auto detect for 50/60 */
5931 +static struct regval_list ov9665_res_sxga[] = {
5932 + {0x0c, 0xbc}, /* note this */
5937 +static struct regval_list ov9665_res_vga[] = {
5942 + {0x12, 0x40}, /*VGA format*/
5943 + {0x14, 0x30}, /*4x*/
5946 + {0x5c, 0x80}, /* Full average AEC */
5948 + /* Windows setting */
5971 + /* Scale window */
5982 + /*This is for Color Matrix*/
5998 diff --git a/drivers/media/video/mrstci/mrsts5k4e1/Kconfig b/drivers/media/video/mrstci/mrsts5k4e1/Kconfig
5999 new file mode 100755
6000 index 0000000..7dee787
6002 +++ b/drivers/media/video/mrstci/mrsts5k4e1/Kconfig
6004 +config VIDEO_MRST_S5K4E1
6005 + tristate "Moorestown s5k4e1 RAW Sensor"
6006 + depends on I2C && VIDEO_MRST_ISP
6009 + Say Y here if your platform support s5k4e1 RAW Sensor.
6011 + To compile this driver as a module, choose M here: the
6012 + module will be called mrstov2650.ko.
6013 diff --git a/drivers/media/video/mrstci/mrsts5k4e1/Makefile b/drivers/media/video/mrstci/mrsts5k4e1/Makefile
6014 new file mode 100644
6015 index 0000000..8733fa8
6017 +++ b/drivers/media/video/mrstci/mrsts5k4e1/Makefile
6019 +obj-$(CONFIG_VIDEO_MRST_S5K4E1) += mrsts5k4e1.o
6021 +EXTRA_CFLAGS += -I$(src)/../include
6022 diff --git a/drivers/media/video/mrstci/mrsts5k4e1/mrsts5k4e1.c b/drivers/media/video/mrstci/mrsts5k4e1/mrsts5k4e1.c
6023 new file mode 100755
6024 index 0000000..f644531
6026 +++ b/drivers/media/video/mrstci/mrsts5k4e1/mrsts5k4e1.c
6029 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
6031 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
6033 + * This program is free software; you can redistribute it and/or
6034 + * modify it under the terms of the GNU General Public License version
6035 + * 2 as published by the Free Software Foundation.
6037 + * This program is distributed in the hope that it will be useful,
6038 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6039 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6040 + * GNU General Public License for more details.
6042 + * You should have received a copy of the GNU General Public License
6043 + * along with this program; if not, write to the Free Software
6044 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
6045 + * 02110-1301, USA.
6048 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
6051 +#include <linux/module.h>
6052 +#include <linux/types.h>
6053 +#include <linux/kernel.h>
6054 +#include <linux/mm.h>
6055 +#include <linux/string.h>
6056 +#include <linux/errno.h>
6057 +#include <linux/init.h>
6058 +#include <linux/kmod.h>
6059 +#include <linux/device.h>
6060 +#include <linux/delay.h>
6061 +#include <linux/fs.h>
6062 +#include <linux/init.h>
6063 +#include <linux/slab.h>
6064 +#include <linux/delay.h>
6065 +#include <linux/i2c.h>
6066 +#include <linux/gpio.h>
6068 +#include <media/v4l2-device.h>
6069 +#include <media/v4l2-chip-ident.h>
6070 +#include <media/v4l2-i2c-drv.h>
6072 +#include "ci_sensor_common.h"
6073 +#include "mrsts5k4e1.h"
6074 +/* #include "priv.h" */
6075 +/* extern const struct DumpRegs regs_d[]; */
6077 +static int s5k4e1_debug;
6078 +module_param(s5k4e1_debug, int, 0644);
6079 +MODULE_PARM_DESC(s5k4e1_debug, "Debug level (0-1)");
6081 +#define dprintk(level, fmt, arg...) \
6083 + if (s5k4e1_debug >= level) \
6084 + printk(KERN_DEBUG "mrstisp@%s: " fmt "\n", \
6085 + __func__, ## arg);\
6088 +#define eprintk(fmt, arg...) \
6089 + printk(KERN_ERR "mrstisp@%s:" fmt "\n", \
6090 + __func__, ## arg);
6092 +#define DBG_entering dprintk(1, "entering");
6093 +#define DBG_leaving dprintk(1, "leaving");
6094 +#define DBG_line dprintk(1, " line: %d", __LINE__);
6096 +static inline struct ci_sensor_config *to_sensor_config(struct v4l2_subdev *sd)
6098 + return container_of(sd, struct ci_sensor_config, sd);
6101 +static struct s5k4e1_format_struct {
6103 + __u32 pixelformat;
6104 + struct regval_list *regs;
6105 +} s5k4e1_formats[] = {
6107 + .desc = "Raw RGB Bayer",
6108 + .pixelformat = SENSOR_MODE_MIPI,
6112 +#define N_S5K4E1_FMTS ARRAY_SIZE(s5k4e1_formats)
6114 +static struct s5k4e1_res_struct {
6119 + /* FIXME: correct the fps values.. */
6122 + struct regval_list *regs;
6125 + .desc = "QSXGA_PLUS4",
6126 + .res = SENSOR_RES_QXGA_PLUS,
6131 + .regs = s5k4e1_res_qsxga_plus4,
6135 + .res = SENSOR_RES_1080P,
6140 + .regs = s5k4e1_res_1080p,
6143 + .desc = "VGA_PLUS",
6144 + .res = SENSOR_RES_VGA_PLUS,
6149 + .regs = s5k4e1_res_vga_ac04_bill,
6153 + .res = SENSOR_RES_720P,
6158 + .regs = s5k4e1_res_720p,
6162 + .res = SENSOR_RES_VGA,
6167 + .regs = s5k4e1_res_vga_ac04_bill,
6171 +#define N_RES (ARRAY_SIZE(s5k4e1_res))
6174 + * I2C Read & Write stuff
6176 +static int s5k4e1_read(struct i2c_client *c, u32 reg, u32 *value)
6180 + struct i2c_msg msg[2];
6184 + /* Read needs two message to go */
6185 + memset(&msg, 0, sizeof(msg));
6190 + msgbuf[i++] = ((u16)reg) >> 8;
6191 + msgbuf[i++] = ((u16)reg) & 0xff;
6192 + msg[0].addr = c->addr;
6193 + msg[0].buf = msgbuf;
6196 + msg[1].addr = c->addr;
6197 + msg[1].flags = I2C_M_RD;
6198 + msg[1].buf = &ret_val;
6201 + ret = i2c_transfer(c->adapter, &msg[0], 2);
6204 + ret = (ret == 2) ? 0 : -1;
6205 + dprintk(2, "reg:0x%8x, value:0x%8x - %s", reg, *value,
6206 + (ret ? "failed" : "succesfully"));
6210 +static int s5k4e1_write(struct i2c_client *c, u32 reg, u32 value)
6213 + struct i2c_msg msg;
6216 + /* Writing only needs one message */
6217 + memset(&msg, 0, sizeof(msg));
6219 + msgbuf[i++] = ((u16)reg) >> 8;
6220 + msgbuf[i++] = (u16)reg & 0xff;
6221 + msgbuf[i++] = (u8)value;
6223 + msg.addr = c->addr;
6228 + ret = i2c_transfer(c->adapter, &msg, 1);
6230 + /* If this is a reset register, wait for 1ms */
6231 + if (reg == 0x0103 && (value & 0x01))
6232 + /*Note here, check if this is needed */
6235 + ret = (ret == 1) ? 0 : -1;
6236 + dprintk(2, "reg:0x%8x, value:0x%8x - %s", reg, value,
6237 + (ret ? "failed" : "successfully"));
6241 +static int s5k4e1_write_array(struct i2c_client *c, struct regval_list *vals)
6243 + struct regval_list *p;
6251 + while (p->reg_num != 0xffff) {
6252 + s5k4e1_write(c, (u32)p->reg_num, (u32)p->value);
6253 + s5k4e1_read(c, (u32)p->reg_num, &read_val);
6255 + if (read_val != p->value) {
6256 + eprintk("0x%x write error:should be 0x%x, but 0x%x",
6257 + p->reg_num, p->value, read_val);
6263 + dprintk(1, "sucessfully wrote %d registers, err is %d", i,
6269 + * Sensor specific helper function
6271 +static int s5k4e1_standby(void)
6273 + gpio_set_value(GPIO_STDBY_PIN, 1);
6274 + dprintk(1, "PM: standby called\n");
6278 +static int s5k4e1_wakeup(void)
6280 + gpio_set_value(GPIO_STDBY_PIN, 0);
6281 + dprintk(1, "PM: wakeup called\n");
6285 +static int s5k4e1_s_power(struct v4l2_subdev *sd, u32 val)
6294 +static int s5k4e1_set_img_ctrl(struct i2c_client *c,
6295 + const struct ci_sensor_config *config)
6301 + switch (config->blc) {
6302 + /* only SENSOR_BLC_AUTO supported */
6303 + case SENSOR_BLC_AUTO:
6306 + dprintk(1, "BLC not supported,\
6307 + set to BLC_AUTO by default.");
6310 + switch (config->bls) {
6311 + /* only SENSOR_BLS_OFF supported */
6312 + case SENSOR_BLS_OFF:
6315 + dprintk(1, "Black level not supported,\
6316 + set to BLS_OFF by default.");
6319 + switch (config->agc) {
6320 + /* only SENSOR_AGC_OFF supported */
6321 + case SENSOR_AGC_OFF:
6324 + dprintk(1, "AGC not supported,\
6325 + set to AGC_OFF by default.");
6328 + switch (config->awb) {
6329 + /* only SENSOR_AWB_OFF supported */
6330 + case SENSOR_AWB_OFF:
6333 + dprintk(1, "AWB not supported,\
6334 + set to AWB_OFF by default.");
6337 + switch (config->aec) {
6338 + /* only SENSOR_AEC_OFF supported */
6339 + case SENSOR_AEC_OFF:
6342 + dprintk(1, "AEC not supported,\
6343 + set to AEC_OFF by default.");
6350 +static int s5k4e1_init(struct i2c_client *c)
6353 + struct v4l2_subdev *sd = i2c_get_clientdata(c);
6354 + struct ci_sensor_config *info = to_sensor_config(sd);
6359 + /* Fill the configuration structure */
6360 + /* Note this default configuration value */
6361 + info->mode = s5k4e1_formats[0].pixelformat;
6362 + info->res = s5k4e1_res[0].res;
6363 + info->type = SENSOR_TYPE_RAW;
6364 + info->bls = SENSOR_BLS_OFF;
6365 + info->gamma = SENSOR_GAMMA_OFF;
6366 + info->cconv = SENSOR_CCONV_OFF;
6367 + info->blc = SENSOR_BLC_AUTO;
6368 + info->agc = SENSOR_AGC_OFF;
6369 + info->awb = SENSOR_AWB_OFF;
6370 + info->aec = SENSOR_AEC_OFF;
6371 + /*info->bus_width = SENSOR_BUSWIDTH_10BIT_ZZ;*/
6372 + info->bus_width = SENSOR_BUSWIDTH_12BIT;
6373 + info->ycseq = SENSOR_YCSEQ_YCBYCR;
6374 + info->conv422 = SENSOR_CONV422_COSITED;
6375 + /*info->conv422 = SENSOR_CONV422_NOCOSITED;*/
6376 + info->bpat = SENSOR_BPAT_GRGRBGBG;
6377 + info->field_inv = SENSOR_FIELDINV_NOSWAP;
6378 + info->field_sel = SENSOR_FIELDSEL_BOTH;
6379 + info->hpol = SENSOR_HPOL_REFPOS;
6380 + info->vpol = SENSOR_VPOL_NEG;
6381 + info->edge = SENSOR_EDGE_RISING;
6382 + info->flicker_freq = SENSOR_FLICKER_100;
6383 + info->cie_profile = SENSOR_CIEPROF_F11;
6384 + info->mipi_mode = SENSOR_MIPI_MODE_RAW_10;
6386 + memcpy(info->name, name, 7);
6388 + /* Reset sensor hardware, and implement the setting*/
6389 + ret += s5k4e1_write(c, 0x0100, (u32)0x00);
6390 + /*TODO: See if we can ignore this*/
6391 + ret = s5k4e1_write(c, 0x0103, (u32)0x01);
6393 + /* sw reset -- delay 3.1ms */
6396 + /* Set registers into default config value */
6397 + /* ret += s5k4e1_write_array(c, s5k4e1_def_reg); */
6399 + /* Set MIPI interface */
6401 + ret += s5k4e1_write_array(c, s5k4e1_mipi);
6404 + ret += s5k4e1_set_img_ctrl(c, info); /*FIXME*/
6407 + /* ret += s5k4e1_write(c, 0x0100, (u32)0x01); */
6408 + ret += s5k4e1_write(c, 0x0100, (u32)0x00);
6417 +static int distance(struct s5k4e1_res_struct *res, u32 w, u32 h)
6423 + if (res->width < w || res->height < h)
6426 + ret = ((res->width - w) + (res->height - h));
6433 +static int s5k4e1_try_res(u32 *w, u32 *h)
6435 + struct s5k4e1_res_struct *res_index, *p = NULL;
6436 + int dis, last_dis = s5k4e1_res->width + s5k4e1_res->height;
6440 + for (res_index = s5k4e1_res;
6441 + res_index < s5k4e1_res + N_RES;
6443 + if ((res_index->width < *w) || (res_index->height < *h))
6445 + dis = distance(res_index, *w, *h);
6446 + if (dis < last_dis) {
6454 + else if ((p->width < *w) || (p->height < *h)) {
6455 + if (p != s5k4e1_res)
6459 + if ((w != NULL) && (h != NULL)) {
6468 +static struct s5k4e1_res_struct *s5k4e1_to_res(u32 w, u32 h)
6470 + struct s5k4e1_res_struct *res_index;
6474 + for (res_index = s5k4e1_res;
6475 + res_index < s5k4e1_res + N_RES;
6477 + if ((res_index->width == w) && (res_index->height == h))
6480 + if (res_index >= s5k4e1_res + N_RES)
6481 + res_index--; /* Take the bigger one */
6488 +static int s5k4e1_try_fmt(struct v4l2_subdev *sd,
6489 + struct v4l2_format *fmt)
6492 + return s5k4e1_try_res(&fmt->fmt.pix.width, &fmt->fmt.pix.height);
6496 +static int s5k4e1_get_fmt(struct v4l2_subdev *sd,
6497 + struct v4l2_format *fmt)
6499 + struct ci_sensor_config *info = to_sensor_config(sd);
6500 + unsigned short width, height;
6503 + ci_sensor_res2size(info->res, &width, &height);
6505 + /* Marked the current sensor res as being "used" */
6506 + for (index = 0; index < N_RES; index++) {
6507 + if ((width == s5k4e1_res[index].width) &&
6508 + (height == s5k4e1_res[index].height)) {
6509 + s5k4e1_res[index].used = 1;
6512 + s5k4e1_res[index].used = 0;
6515 + fmt->fmt.pix.width = width;
6516 + fmt->fmt.pix.height = height;
6522 +/* chuanxiao add, to dump regs */
6523 +static int s5k4e1_dump_regs(struct i2c_client *c)
6525 + /*struct i2c_client *c = v4l2_get_subdevdata(sd);*/
6526 + const struct DumpRegs *p = regs_d;
6528 + u32 value1, value2, value3, value4;
6529 + while (p->ulFlags != eTableEnd) {
6530 + if (p->ulFlags & eFourBytes) {
6531 + s5k4e1_read(c, (u32)p->ulAddr, &value1);
6532 + s5k4e1_read(c, (u32)p->ulAddr+1, &value2);
6533 + s5k4e1_read(c, (u32)p->ulAddr+2, &value3);
6534 + s5k4e1_read(c, (u32)p->ulAddr+3, &value4);
6535 + value = value1<<24 | value2<<16 | value3<<8 | value4;
6536 + } else if (p->ulFlags & eTwoBytes) {
6537 + s5k4e1_read(c, (u32)p->ulAddr, &value1);
6538 + s5k4e1_read(c, (u32)p->ulAddr+1, &value2);
6539 + value = value1<<8 | value2;
6541 + s5k4e1_read(c, (u32)p->ulAddr, &value);
6543 + if (value == p->ulDefaultValue)
6544 + dprintk(0, "%s\t @ 0x%x = 0x%lx (= default value)\n",
6545 + p->pszName, p->ulAddr, value);
6547 + dprintk(0, "%s\t @ 0x%x = 0x%lx (default was 0x%lx)\n",
6548 + p->pszName, p->ulAddr, value, p->ulDefaultValue);
6550 + dprintk(0, "%-30s @ 0x%04X = 0x%08X", p->pszName,
6551 + p->ulAddr, value);
6558 +static int s5k4e1_set_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
6560 + struct i2c_client *c = v4l2_get_subdevdata(sd);
6561 + struct ci_sensor_config *info = to_sensor_config(sd);
6563 + struct s5k4e1_res_struct *res_index;
6564 + u32 width, height;
6569 + width = fmt->fmt.pix.width;
6570 + height = fmt->fmt.pix.height;
6572 + dprintk(1, "was told to set fmt (%d x %d) ", width, height);
6573 + ret = s5k4e1_try_res(&width, &height);
6575 + res_index = s5k4e1_to_res(width, height);
6579 + if (res_index->regs) {
6580 + /* software sleep/standby */
6581 + ret += s5k4e1_write(c, 0x0100, (u32)0x00);
6583 + /* Soft reset camera first*/
6584 + /*TODO: See if we can ignore this*/
6585 + ret = s5k4e1_write(c, 0x0103, (u32)0xff);
6587 + /* Set registers into default config value */
6588 + /* ret += s5k4e1_write_array(c, s5k4e1_def_reg);*/
6590 + /* set image resolution */
6591 + ret += s5k4e1_write_array(c, res_index->regs);
6593 + ret += s5k4e1_set_img_ctrl(c, info);
6595 + /* XXX setup with unknow meaning ... */
6596 + /* ret += s5k4e1_write(c, 0x30b0, 0xfe); */
6598 + /* Set MIPI interface */
6600 + ret += s5k4e1_write_array(c, s5k4e1_mipi);
6604 + ret = s5k4e1_write(c, 0x0100, (u32)0x01);
6607 + info->res = res_index->res;
6609 + /* Marked current sensor res as being "used" */
6610 + for (index = 0; index < N_RES; index++) {
6611 + if ((width == s5k4e1_res[index].width) &&
6612 + (height == s5k4e1_res[index].height)) {
6613 + s5k4e1_res[index].used = 1;
6616 + s5k4e1_res[index].used = 0;
6619 + for (index = 0; index < N_RES; index++)
6620 + dprintk(2, "index = %d, used = %d\n", index,
6621 + s5k4e1_res[index].used);
6625 + eprintk("no res for (%d x %d)", width, height);
6632 +static int s5k4e1_t_gain(struct v4l2_subdev *sd, int value)
6634 + struct i2c_client *client = v4l2_get_subdevdata(sd);
6638 + s5k4e1_write(client, 0x0104, 1); /*hold*/
6641 + s5k4e1_write(client, 0x0204, value >> 8);
6643 + s5k4e1_write(client, 0x0205, value & 0xff);
6645 + s5k4e1_write(client, 0x0104, 0); /*unhold*/
6647 + dprintk(1, "gain %x was writen to 0x0204/5", value);
6653 +static int s5k4e1_t_exposure(struct v4l2_subdev *sd, int value)
6655 + struct i2c_client *client = v4l2_get_subdevdata(sd);
6659 + s5k4e1_write(client, 0x0104, 1); /*hold*/
6661 + /* fine integration time */
6662 + s5k4e1_write(client, 0x0200, value >> 24);
6664 + s5k4e1_write(client, 0x0201, (value >> 16) & 0xff);
6666 + /* coarse integration time */
6667 + s5k4e1_write(client, 0x0202, (value & 0xff00) >> 8);
6669 + s5k4e1_write(client, 0x0203, value & 0xff);
6671 + s5k4e1_write(client, 0x0104, 0); /*unhold*/
6673 + dprintk(1, "exposure %x was writen to 0x0200/1/2/3", value);
6679 +static struct s5k4e1_control {
6680 + struct v4l2_queryctrl qc;
6681 + int (*query)(struct v4l2_subdev *sd, __s32 *value);
6682 + int (*tweak)(struct v4l2_subdev *sd, int value);
6683 +} s5k4e1_controls[] = {
6686 + .id = V4L2_CID_GAIN,
6687 + .type = V4L2_CTRL_TYPE_INTEGER,
6688 + .name = "global gain",
6690 + .maximum = 0xFFFF,
6692 + .default_value = 0x00,
6695 + .tweak = s5k4e1_t_gain,
6699 + .id = V4L2_CID_EXPOSURE,
6700 + .type = V4L2_CTRL_TYPE_INTEGER,
6701 + .name = "exposure",
6703 + .maximum = 0xFFFF,
6705 + .default_value = 0x00,
6708 + .tweak = s5k4e1_t_exposure,
6711 +#define N_CONTROLS (ARRAY_SIZE(s5k4e1_controls))
6713 +static struct s5k4e1_control *s5k4e1_find_control(__u32 id)
6718 + for (i = 0; i < N_CONTROLS; i++)
6719 + if (s5k4e1_controls[i].qc.id == id)
6720 + return s5k4e1_controls + i;
6725 +static int s5k4e1_queryctrl(struct v4l2_subdev *sd,
6726 + struct v4l2_queryctrl *qc)
6728 + struct s5k4e1_control *ctrl = s5k4e1_find_control(qc->id);
6739 +static int s5k4e1_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
6742 + struct s5k4e1_control *octrl = s5k4e1_find_control(parm->index);
6745 + if (octrl == NULL)
6747 + ret = octrl->query(client, &parm->value);
6754 +static int s5k4e1_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
6756 + struct s5k4e1_control *octrl = s5k4e1_find_control(ctrl->id);
6761 + if (octrl == NULL)
6763 + ret = octrl->tweak(sd, ctrl->value);
6771 +static int s5k4e1_s_stream(struct v4l2_subdev *sd, int enable)
6773 + struct i2c_client *client = v4l2_get_subdevdata(sd);
6777 + s5k4e1_write(client, (u32)0x0100, 0x01);
6778 + /*chuanxiao add, dump s5k4e1 regs*/
6779 + /* s5k4e1_dump_regs(client); */
6781 + s5k4e1_write(client, (u32)0x0100, 0x00);
6789 +static int s5k4e1_enum_framesizes(struct v4l2_subdev *sd,
6790 + struct v4l2_frmsizeenum *fsize)
6792 + unsigned int index = fsize->index;
6796 + if (index >= N_RES)
6799 + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
6800 + fsize->discrete.width = s5k4e1_res[index].width;
6801 + fsize->discrete.height = s5k4e1_res[index].height;
6802 + fsize->reserved[0] = s5k4e1_res[index].used;
6809 +static int s5k4e1_enum_frameintervals(struct v4l2_subdev *sd,
6810 + struct v4l2_frmivalenum *fival)
6812 + unsigned int index = fival->index;
6816 + if (index >= N_RES)
6819 + fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
6820 + fival->discrete.numerator = 1;
6821 + fival->discrete.denominator = s5k4e1_res[index].fps;
6828 +static int s5k4e1_g_chip_ident(struct v4l2_subdev *sd,
6829 + struct v4l2_dbg_chip_ident *chip)
6831 + struct i2c_client *client = v4l2_get_subdevdata(sd);
6835 +#define V4L2_IDENT_S5K4E1 8250
6838 + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_S5K4E1, 0);
6841 +#ifdef CONFIG_VIDEO_ADV_DEBUG
6842 +static int s5k4e1_g_register(struct v4l2_subdev *sd,
6843 + struct v4l2_dbg_register *reg)
6845 + struct i2c_client *client = v4l2_get_subdevdata(sd);
6846 + unsigned char val = 0;
6849 + if (!v4l2_chip_match_i2c_client(client, ®->match))
6851 + if (!capable(CAP_SYS_ADMIN))
6853 + ret = s5k4e1_read(client, reg->reg & 0xffff, &val);
6859 +static int s5k4e1_s_register(struct v4l2_subdev *sd,
6860 + struct v4l2_dbg_register *reg)
6862 + struct i2c_client *client = v4l2_get_subdevdata(sd);
6864 + if (!v4l2_chip_match_i2c_client(client, ®->match))
6866 + if (!capable(CAP_SYS_ADMIN))
6868 + s5k4e1_write(client, reg->reg & 0xffff, reg->val & 0xff);
6873 +static const struct v4l2_subdev_video_ops s5k4e1_video_ops = {
6874 + .try_fmt = s5k4e1_try_fmt,
6875 + .s_fmt = s5k4e1_set_fmt,
6876 + .g_fmt = s5k4e1_get_fmt,
6877 + .s_stream = s5k4e1_s_stream,
6878 + .enum_framesizes = s5k4e1_enum_framesizes,
6879 + .enum_frameintervals = s5k4e1_enum_frameintervals,
6882 +static const struct v4l2_subdev_core_ops s5k4e1_core_ops = {
6883 + .g_chip_ident = s5k4e1_g_chip_ident,
6884 + .queryctrl = s5k4e1_queryctrl,
6885 + .g_ctrl = s5k4e1_g_ctrl,
6886 + .s_ctrl = s5k4e1_s_ctrl,
6887 + .s_gpio = s5k4e1_s_power,
6888 + /*.g_ext_ctrls = s5k4e1_g_ext_ctrls,*/
6889 + /*.s_ext_ctrls = s5k4e1_s_ext_ctrls,*/
6890 +#ifdef CONFIG_VIDEO_ADV_DEBUG
6891 + .g_register = s5k4e1_g_register,
6892 + .s_register = s5k4e1_s_register,
6896 +static const struct v4l2_subdev_ops s5k4e1_ops = {
6897 + .core = &s5k4e1_core_ops,
6898 + .video = &s5k4e1_video_ops,
6905 +static unsigned short normal_i2c[] = {0x36, I2C_CLIENT_END};
6908 +static struct i2c_driver i2c_driver_s5k4e1_sensor;
6910 +static int s5k4e1_detect(struct i2c_client *client)
6912 + struct i2c_adapter *adapter = client->adapter;
6913 + int adap_id = i2c_adapter_id(adapter);
6918 + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
6919 + eprintk("error i2c check func");
6923 + if (adap_id != 1) {
6924 + eprintk("adap_id != 1");
6928 + if (s5k4e1_wakeup()) {
6929 + eprintk("sensor wakeup failed");
6933 + s5k4e1_read(client, 0x0003, &value);
6934 + dprintk(1, "Read from 0x0003: %x", value);
6935 + if ((value != 0x09))
6938 + s5k4e1_read(client, 0x0000, &value);
6939 + dprintk(1, "Read from 0x0000: %x", value);
6940 + if ((value != 0x4e) && (value != 0x10))
6943 + s5k4e1_read(client, 0x0001, &value);
6944 + dprintk(1, "Read from 0x0001: %x", value);
6945 + if ((value != 0x4e) && (value != 0x10))
6948 + /*TODO EVT3 detect*/
6949 + s5k4e1_read(client, 0x0002, &value);
6950 + dprintk(1, "Read from 0x0002: %x", value);
6951 + if (value == 0x0010) {
6952 + dprintk(1, "EVT3 module not supported!");
6960 +static int s5k4e1_probe(struct i2c_client *client,
6961 + const struct i2c_device_id *id)
6963 + struct ci_sensor_config *info;
6964 + struct v4l2_subdev *sd;
6969 + v4l_info(client, "chip found @ 0x%x (%s)\n",
6970 + client->addr << 1, client->adapter->name);
6973 + * Setup sensor configuration structure
6975 + info = kzalloc(sizeof(struct ci_sensor_config), GFP_KERNEL);
6977 + dprintk(0, "fail to malloc for ci_sensor_config");
6982 + ret = s5k4e1_detect(client);
6984 + dprintk(0, "error s5k4e1_detect");
6989 + v4l2_i2c_subdev_init(sd, client, &s5k4e1_ops);
6992 + * Initialization S5K4E1
6993 + * then turn into standby mode
6995 + ret = s5k4e1_init(client);
6997 + dprintk(0, "error calling s5k4e1_init");
7002 + dprintk(0, "Init s5k4e1 sensor successfully");
7017 +static int s5k4e1_remove(struct i2c_client *client)
7019 + struct v4l2_subdev *sd = i2c_get_clientdata(client);
7023 + v4l2_device_unregister_subdev(sd);
7024 + kfree(to_sensor_config(sd));
7031 + * i2c_driver for s5k4e1_sensor
7033 +static const struct i2c_device_id s5k4e1_id[] = {
7038 +MODULE_DEVICE_TABLE(i2c, s5k4e1_id);
7040 +static struct v4l2_i2c_driver_data v4l2_i2c_data = {
7042 + .probe = s5k4e1_probe,
7043 + .remove = s5k4e1_remove,
7044 + /* .suspend = s5k4e1_suspend,
7045 + * .resume = s5k4e1_resume, */
7046 + .id_table = s5k4e1_id,
7049 +MODULE_AUTHOR("Xiaolin Zhang <xiaolin.zhang@intel.com>");
7050 +MODULE_DESCRIPTION("A low-level driver for Samsung S5K4E1 sensors");
7051 +MODULE_LICENSE("GPL");
7052 diff --git a/drivers/media/video/mrstci/mrsts5k4e1/mrsts5k4e1.h b/drivers/media/video/mrstci/mrsts5k4e1/mrsts5k4e1.h
7053 new file mode 100755
7054 index 0000000..d722035
7056 +++ b/drivers/media/video/mrstci/mrsts5k4e1/mrsts5k4e1.h
7059 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
7061 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
7063 + * This program is free software; you can redistribute it and/or
7064 + * modify it under the terms of the GNU General Public License version
7065 + * 2 as published by the Free Software Foundation.
7067 + * This program is distributed in the hope that it will be useful,
7068 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7069 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7070 + * GNU General Public License for more details.
7072 + * You should have received a copy of the GNU General Public License
7073 + * along with this program; if not, write to the Free Software
7074 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
7075 + * 02110-1301, USA.
7078 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
7081 +#define I2C_S5K4E1 0x6C
7082 +/* Should add to kernel source */
7083 +#define I2C_DRIVERID_S5K4E1 1046
7084 +/* GPIO pin on Moorestown */
7085 +#define GPIO_SCLK_25 44
7086 +#define GPIO_STB_PIN 47
7087 +#define GPIO_STDBY_PIN 49
7088 +#define GPIO_RESET_PIN 50
7090 +struct regval_list {
7096 + * Default register value
7097 + * 5Mega Pixel, 2592x1944
7099 +/* MIPI register are removed by Wen */
7102 +static struct regval_list s5k4e1_res_qsxga_plus4[] = {
7103 + /* Reset for operation */
7104 + {0x0100, 0x00}, /* stream off */
7105 + {0x0103, 0x01}, /* software reset */
7109 + * This register is for FACTORY ONLY.
7110 + * If you change it without prior notification,
7111 + * You are RESPONSIBLE for the FAILURE that will happen in the future.
7114 +/* CDS timing setting ... */
7115 + {0x3000, 0x04}, /* ct_ld_start (default = 07h) */
7116 + {0x3001, 0x02}, /* ct_sl_start (default = 05h) */
7117 + {0x3002, 0x0C}, /* ct_rx_start (default = 21h) */
7118 + {0x3003, 0x0E}, /* ct_cds_start (default = 23h) */
7119 + {0x3004, 0x2C}, /* ct_smp_width (default = 60h) */
7120 + {0x3005, 0x0D}, /* ct_az_width (default = 28h) */
7121 + {0x3006, 0x39}, /* ct_s1r_width (default = 88h) */
7122 + {0x3007, 0x02}, /* ct_tx_start (default = 06h) */
7123 + {0x3008, 0x3C}, /* ct_tx_width 1.5us (default = 7Ch) */
7124 + {0x3009, 0x3C}, /* ct_stx_width 1.5us (default = 7Ch) */
7125 + {0x300A, 0x28}, /* ct_dtx_width 1us (default = 3Eh) */
7126 + {0x300B, 0x15}, /* ct_rmp_rst_start (default = 44h) */
7127 + {0x300C, 0x15}, /* ct_rmp_sig_start (default = 48h) */
7128 + {0x300D, 0x02}, /* ct_rmp_lat (default = 02h) */
7129 + {0x300E, 0xA9}, /* D-Shut en[7], CLP On[5], LD high[4] */
7131 +/* CDS option setting ... */
7132 + {0x3010, 0x00}, /* smp_en[2]=0(00) 1(04) row_id[1:0] = 00 */
7133 + {0x3011, 0x7A}, /* RST_MX (288), SIG_MX (1024+352) */
7134 + {0x3012, 0x30}, /* SIG offset1 48 code */
7135 + {0x3013, 0xA0}, /* RST offset1 160 code */
7136 + {0x3014, 0x00}, /* SIG offset2 */
7137 + {0x3015, 0x00}, /* RST offset2 */
7138 + {0x3016, 0x02}, /* ADC_SAT (510mV) */
7139 + {0x3017, 0x94}, /* RMP_INIT[3:0](RMP_REG) 1.8V MS[6:4]=1 */
7140 + {0x3018, 0x78}, /* rmp option - ramp connect[MSB] +RMP INIT DAC MIN */
7141 + {0x301D, 0xD4}, /* CLP level (default = 0Fh) */
7143 + {0x3021, 0x02}, /* inrush ctrl[1] off */
7144 + {0x3022, 0x44}, /* pump ring oscillator set [7:4]=CP, [3:0]=NCP */
7145 + {0x3024, 0x40}, /* pix voltage 2.8V (default = 88h) */
7146 + {0x3027, 0x08}, /* ntg voltage (default = 04h) */
7148 +/* Pixel option setting ... */
7149 + {0x301C, 0x05}, /* Pixel Bias [3:0] (default = 03h) */
7150 + {0x30D8, 0x3F}, /* All tx off 2f, on 3f */
7152 +/* ADLC setting ... */
7153 + {0x3070, 0x5F}, /* [6]L-ADLC BPR, [4]ch sel, [3]L-ADLC, [2]F-ADLC */
7154 + {0x3071, 0x00}, /* F&L-adlc max 127 (default = 11h, max 255) */
7155 + {0x3080, 0x04}, /* F-ADLC filter A (default = 10h) */
7156 + {0x3081, 0x38}, /* F-ADLC filter B (default = 20h) */
7158 +/* Integration setting ... */
7159 + {0x0202, 0x03}, /* coarse integration time */
7161 + {0x0204, 0x00}, /* analog gain[msb] 0100 x8 0080 x4 */
7162 + {0x0205, 0x80}, /* analog gain[lsb] 0040 x2 0020 x1 */
7165 + {0x0340, 0x07}, /* Capture 07B4(1960[# of row]+12[V-blank]) */
7166 + {0x0341, 0xA4}, /* Preview 03E0(980[# of row]+12[V-blank]) */
7169 + {0x0342, 0x0A}, /* 2738 */
7170 + {0x0343, 0xB2}, /* (Same as sensor default) */
7172 +/* embedded 2-line OFF setting ... */
7174 + {0x3084, 0x15}, /* SYNC Mode */
7176 +/* (3) MIPI 2-lane Serial(TST = 0000b or TST = 0010b), 30 fps */
7181 + {0x30BD, 0x00}, /* SEL_CCP[0] */
7182 + {0x30B2, 0x08}, /* PLL P = 8 */
7183 + {0x30B3, 0x00}, /* PLL M[8] = 0 */
7184 + {0x30B5, 0x01}, /* PLL S = 0 */
7185 + {0x30BE, 0x1A}, /* M_PCLKDIV_AUTO[4], M_DIV_PCLK[3:0] */
7188 + {0x30C0, 0x00}, /* video_offset[7:4] 3240%12 */
7189 + {0x30C1, 0x01}, /* pack video enable [0] */
7190 + {0x30C8, 0x0C}, /* video_data_length 3260 = 2608 * 1.25 */
7192 + {0x30E2, 0x02}, /* num lanes[1:0] = 2 */
7193 + {0x30EE, 0x02}, /* DPHY enable [1] */
7194 + {0x30F1, 0x70}, /* DPHY BANDCTRL 800MHz=80.6MHz */
7195 + {0x3111, 0x86}, /* Embedded data off [5] */
7211 + /* This is to set FRAME_NUM > 0 */
7214 + /* Add this setting according to Bill's test */
7220 + {0x020E, 0x01}, /* Gr Digital Gain */
7222 + {0x0210, 0x01}, /* Red Digital Gain */
7224 + {0x0212, 0x01}, /* Blue Digital Gain */
7226 + {0x0214, 0x01}, /* Gb Digital Gain */
7232 + /*Apply Bill's setting*/
7236 + {0x0307, 0x50}, /* vcc_out = 80 */
7237 + {0x30B5, 0x01}, /* pll_s = 1 */
7242 + {0x30BE, 0x1A}, /* DIV_M_PCLK = 5 */
7244 + {0x0100, 0x01}, /* stream on */
7250 +static struct regval_list s5k4e1_res_1080p[] = {
7251 +/* Reset for operation ... */
7252 + {0x0100, 0x00}, /* stream off */
7253 + {0x0103, 0x01}, /* software reset */
7257 + * This register is for FACTORY ONLY.
7258 + * If you change it without prior notification,
7259 + * You are RESPONSIBLE for the FAILURE that will happen in the future.
7262 +/* CDS timing setting ... */
7263 + {0x3000, 0x04}, /* ct_ld_start (default = 07h) */
7264 + {0x3001, 0x02}, /* ct_sl_start (default = 05h) */
7265 + {0x3002, 0x0C}, /* ct_rx_start (default = 21h) */
7266 + {0x3003, 0x0E}, /* ct_cds_start (default = 23h) */
7267 + {0x3004, 0x2C}, /* ct_smp_width (default = 60h) */
7268 + {0x3005, 0x0D}, /* ct_az_width (default = 28h) */
7269 + {0x3006, 0x39}, /* ct_s1r_width (default = 88h) */
7270 + {0x3007, 0x02}, /* ct_tx_start (default = 06h) */
7271 + {0x3008, 0x3C}, /* ct_tx_width 1.5us (default = 7Ch) */
7272 + {0x300A, 0x28}, /* ct_dtx_width 1us (default = 3Eh) */
7273 + {0x300B, 0x15}, /* ct_rmp_rst_start (default = 44h) */
7274 + {0x300C, 0x15}, /* ct_rmp_sig_start (default = 48h) */
7275 + {0x300D, 0x02}, /* ct_rmp_lat (default = 02h) */
7276 + {0x300E, 0xA9}, /* D-Shut en[7], CLP On[5], LD high[4] */
7278 +/* CDS option setting ... */
7279 + {0x3010, 0x00}, /* smp_en[2]=0(00) 1(04) row_id[1:0] = 00 */
7280 + {0x3011, 0x7A}, /* RST_MX (288), SIG_MX (1024+352) */
7281 + {0x3012, 0x30}, /* SIG offset1 48 code */
7282 + {0x3013, 0xA0}, /* RST offset1 160 code */
7283 + {0x3014, 0x00}, /* SIG offset2 */
7284 + {0x3015, 0x00}, /* RST offset2 */
7285 + {0x3016, 0x0A}, /* ADC_SAT (510mV) */
7286 + {0x3017, 0x94}, /* RMP_INIT[3:0](RMP_REG) 1.8V MS[6:4]=1 */
7287 + {0x3018, 0x78}, /* rmp option - ramp connect[MSB] +RMP INIT DAC MIN */
7289 + {0x301D, 0xD4}, /* CLP level (default = 0Fh) */
7291 + {0x3021, 0x02}, /* inrush ctrl[1] off */
7292 + {0x3022, 0x41}, /* pump ring oscillator set [7:4]=CP, [3:0]=NCP */
7293 + {0x3024, 0x08}, /* pix voltage 2.8V (default = 88h) */
7294 + {0x3027, 0x08}, /* ntg voltage (default = 04h) */
7296 +/* Pixel option setting ... */
7297 + {0x301C, 0x05}, /* Pixel Bias [3:0] (default = 03h) */
7298 + {0x30D8, 0x3F}, /* All tx off 2f, on 3f */
7300 +/* ADLC setting ... */
7301 + {0x3070, 0x5F}, /* [6]L-ADLC BPR, [4]ch sel, [3]L-ADLC, [2]F-ADLC */
7302 + {0x3071, 0x00}, /* F&L-adlc max 127 (default = 11h, max 255) */
7303 + {0x3080, 0x04}, /* F-ADLC filter A (default = 10h) */
7304 + {0x3081, 0x38}, /* F-ADLC filter B (default = 20h) */
7306 +/* Integration setting ... */
7307 + {0x0202, 0x03}, /* coarse integration time */
7309 + {0x0204, 0x00}, /* analog gain[msb] 0100 x8 0080 x4 */
7310 + {0x0205, 0x80}, /* analog gain[lsb] 0040 x2 0020 x1 */
7313 + {0x0340, 0x04}, /*Capture 07B4(1960[# of row]+12[V-blank]) */
7314 + {0x0341, 0x44}, /*Preview 03E0(980[# of row]+12[V-blank]) */
7317 + {0x0342, 0x0A}, /* 2738 */
7318 + {0x0343, 0xB2}, /*(Same as sensor default) */
7320 +/* embedded 2-line OFF setting ... */
7322 + {0x3084, 0x15}, /* SYNC Mode */
7324 +/* PLL & MIPI setting ... */
7325 +/* input clock 25MHz */
7327 +/* (3) MIPI 2-lane Serial(TST = 0000b or TST = 0010b), 30 fps */
7328 + {0x30BD, 0x00}, /* SEL_CCP[0] */
7329 + {0x30B2, 0x08}, /* PLL P = 8 */
7330 + {0x30B3, 0x00}, /* PLL M[8] = 0 */
7331 + {0x30B4, 0x78}, /* PLL M = 129 */
7332 + {0x30B5, 0x00}, /* PLL S = 0 */
7333 + {0x30BE, 0x1A}, /* M_PCLKDIV_AUTO[4], M_DIV_PCLK[3:0] */
7336 + {0x30C0, 0x00}, /* video_offset[7:4] 2400%12 */
7337 + {0x30C1, 0x01}, /* pack video enable [0] */
7338 + {0x30C8, 0x09}, /* video_data_length 2400 = 1920 * 1.25 */
7340 + {0x30E2, 0x02}, /* num lanes[1:0] = 2 */
7341 + {0x30EE, 0x02}, /* DPHY enable [1] */
7342 + {0x30F1, 0x70}, /* DPHY BANDCTRL 800MHz=80.6MHz */
7343 + {0x3111, 0x86}, /* Embedded data off [5] */
7350 + {0x0344, 0x01}, /*x_addr_start 344 */
7352 + {0x0348, 0x08}, /*x_addr_end 2263 */
7354 + {0x0346, 0x01}, /*y_addr_start 440 */
7356 + {0x034A, 0x05}, /*y_addr_end 1519 */
7359 + {0x034C, 0x07}, /*x_output_size 1920 */
7361 + {0x034E, 0x04}, /*y_output_size 1080 */
7366 + {0x020E, 0x01}, /*Gr Digital Gain */
7368 + {0x0210, 0x01}, /*Red Digital Gain */
7370 + {0x0212, 0x01}, /*Blue Digital Gain */
7372 + {0x0214, 0x01}, /*Gb Digital Gain */
7378 + /*Apply Bill's setting*/
7382 + {0x0307, 0x50}, /*vcc_out = 80 */
7383 + {0x30B5, 0x01}, /*pll_s = 1 */
7388 + {0x30BE, 0x1A}, /*DIV_M_PCLK = 5 */
7392 + {0x0100, 0x01}, /* stream on */
7397 +/* 1280x720, V1F2 & H1F2 */
7398 +static struct regval_list s5k4e1_res_720p[] = {
7399 + {0x0100, 0x00}, /* stream off */
7400 + {0x0103, 0x01}, /* software reset */
7402 +/* CDS timing setting ... */
7419 +/* CDS option setting ... */
7436 +/* Pixel option setting ... */
7437 + {0x301C, 0x05}, /* Pixel Bias [3:0] (default = 03h) */
7438 + {0x30D8, 0x3F}, /* All tx off 2f, on 3f */
7440 +/* ADLC setting ... */
7446 +/* Integration setting ... */
7457 + {0x0342, 0x0A}, /*2738 */
7460 +/* Average Sub-sampling */
7464 +/* embedded 2-line OFF setting ... */
7468 +/* PLL & MIPI setting ... */
7470 +/* (3) MIPI 2-lane Serial(TST = 0000b or TST = 0010b), 60 fps */
7493 +/* MIPI Size Setting ... */
7513 + {0x034C, 0x05}, /* x_output_size = 1280 */
7515 + {0x034E, 0x02}, /* y_output_size = 720 */
7531 + /*Apply Bill's setting*/
7535 + {0x0307, 0x50}, /*vcc_out = 80 */
7536 + {0x30B5, 0x01}, /*pll_s = 1 */
7541 + {0x30BE, 0x15}, /*DIV_M_PCLK = 5 */
7543 + {0x0100, 0x01}, /* stream on */
7548 +static struct regval_list s5k4e1_res_vga_ac04_bill[] = {
7549 + {0x0100, 0x00}, /* stream off */
7550 + {0x0103, 0x01}, /* software reset */
7666 + /* Apply Bill's setting */
7678 + /* {0x0100, 0x01}, */
7679 + /* {0xffff, 0xff}, */
7690 + {0x0344, 0x00}, /* x_addr_start = 0 */
7692 + {0x0348, 0x0A}, /* x_addr_end = 2607 */
7694 + {0x0346, 0x00}, /* y_addr_start = 0 */
7696 + {0x034A, 0x07}, /* y_addr_end = 1959 */
7706 + {0x034c, 0x05}, /* x_output_size = 1304 */
7708 + {0x034e, 0x03}, /* y_output_size = 980 */
7712 + {0x30C8, 0x06}, /* x_output_size * 1.25 */
7720 diff --git a/drivers/media/video/mrstci/mrsts5k4e1_motor/Kconfig b/drivers/media/video/mrstci/mrsts5k4e1_motor/Kconfig
7721 new file mode 100755
7722 index 0000000..27cb730
7724 +++ b/drivers/media/video/mrstci/mrsts5k4e1_motor/Kconfig
7726 +config VIDEO_MRST_S5K4E1_MOTOR
7727 + tristate "Moorestown s5k4e1 motor"
7728 + depends on I2C && VIDEO_MRST_ISP && VIDEO_MRST_S5K4E1
7731 + Say Y here if your platform support s5k4e1 motor.
7733 + To compile this driver as a module, choose M here: the
7734 + module will be called mrstov2650.ko.
7735 diff --git a/drivers/media/video/mrstci/mrsts5k4e1_motor/Makefile b/drivers/media/video/mrstci/mrsts5k4e1_motor/Makefile
7736 new file mode 100644
7737 index 0000000..68c9fbc
7739 +++ b/drivers/media/video/mrstci/mrsts5k4e1_motor/Makefile
7741 +obj-$(CONFIG_VIDEO_MRST_S5K4E1_MOTOR) += mrsts5k4e1_motor.o
7743 +EXTRA_CFLAGS += -I$(src)/../include
7744 diff --git a/drivers/media/video/mrstci/mrsts5k4e1_motor/mrsts5k4e1_motor.c b/drivers/media/video/mrstci/mrsts5k4e1_motor/mrsts5k4e1_motor.c
7745 new file mode 100644
7746 index 0000000..cd2813b
7748 +++ b/drivers/media/video/mrstci/mrsts5k4e1_motor/mrsts5k4e1_motor.c
7751 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
7753 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
7755 + * This program is free software; you can redistribute it and/or
7756 + * modify it under the terms of the GNU General Public License version
7757 + * 2 as published by the Free Software Foundation.
7759 + * This program is distributed in the hope that it will be useful,
7760 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7761 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7762 + * GNU General Public License for more details.
7764 + * You should have received a copy of the GNU General Public License
7765 + * along with this program; if not, write to the Free Software
7766 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
7767 + * 02110-1301, USA.
7770 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
7773 +#include <linux/module.h>
7774 +#include <linux/types.h>
7775 +#include <linux/kernel.h>
7776 +#include <linux/mm.h>
7777 +#include <linux/string.h>
7778 +#include <linux/errno.h>
7779 +#include <linux/init.h>
7780 +#include <linux/kmod.h>
7781 +#include <linux/device.h>
7782 +#include <linux/delay.h>
7783 +#include <linux/fs.h>
7784 +#include <linux/slab.h>
7785 +#include <linux/delay.h>
7786 +#include <linux/i2c.h>
7787 +#include <linux/gpio.h>
7789 +#include <media/v4l2-device.h>
7790 +#include <media/v4l2-chip-ident.h>
7791 +#include <media/v4l2-i2c-drv.h>
7793 +#include "mrsts5k4e1_motor.h"
7795 +static int s5k4e1_motor_debug;
7796 +module_param(s5k4e1_motor_debug, int, 0644);
7797 +MODULE_PARM_DESC(s5k4e1_motor_debug, "Debug level (0-1)");
7799 +#define dprintk(level, fmt, arg...) \
7801 + if (s5k4e1_motor_debug >= level) \
7802 + printk(KERN_DEBUG "mrstisp@%s: " fmt "\n", __func__, ## arg); \
7805 +#define eprintk(fmt, arg...) \
7806 + printk(KERN_ERR "mrstisp@%s: line %d: " fmt "\n", \
7807 + __func__, __LINE__, ## arg);
7809 +#define DBG_entering dprintk(1, "entering");
7810 +#define DBG_leaving dprintk(1, "leaving");
7811 +#define DBG_line dprintk(1, " line: %d", __LINE__);
7813 +static inline struct s5k4e1_motor *to_motor_config(struct v4l2_subdev *sd)
7815 + return container_of(sd, struct s5k4e1_motor, sd);
7818 +/*static struct s5k4e1_motor *config; */
7819 +static int motor_read(struct i2c_client *c, u32 *reg)
7822 + struct i2c_msg msg;
7829 + memset(&msg, 0, sizeof(msg));
7830 + msg.addr = c->addr;
7833 + msg.flags = I2C_M_RD;
7835 + ret = i2c_transfer(c->adapter, &msg, 1);
7837 + *reg = (msgbuf[0] << 16 | msgbuf[1] << 8 | msgbuf[2]);
7839 + ret = (ret == 1) ? 0 : -1;
7843 +static int motor_write(struct i2c_client *c, u32 reg)
7846 + struct i2c_msg msg;
7849 + memset(&msg, 0, sizeof(msg));
7850 + msgbuf[0] = (reg & 0x00FFFFFFFF) >> 16;
7851 + msgbuf[1] = (reg & 0x0000FFFF) >> 8 ;
7854 + msg.addr = c->addr;
7859 + ret = i2c_transfer(c->adapter, &msg, 1);
7861 + ret = (ret == 1) ? 0 : -1;
7865 +static int s5k4e1_motor_goto_position(struct i2c_client *c,
7866 + unsigned short code,
7867 + struct s5k4e1_motor *config,
7868 + unsigned int step)
7870 + int max_code, min_code;
7871 + int timeout = 25; /*TODO: check the timeout time */
7872 + u8 cmdh, cmdl, finished;
7873 + u32 cmd = 0, val = 0;
7875 + max_code = config->macro_code;
7876 + min_code = config->infin_code;
7878 + if (code > max_code)
7880 + if (code < min_code)
7883 + cmdh = MOTOR_DAC_CTRL_MODE_1 | (code >> 8); /* PS EN x x M W TD9 TD8*/
7884 + cmdl = code; /* TD7 ~ TD0 */
7885 + cmd |= (cmdh << 16) | (cmdl << 8);
7887 + dprintk(1, "cmdh: %x, cmdl: %x, cmd: %x", cmdh, cmdl, cmd);
7888 + dprintk(1, "DAC code: %x", code);
7890 + motor_write(c, cmd);
7892 + while ((!finished) && timeout--) {
7894 + motor_read(c, &val);
7898 + dprintk(1, "cmdh & MOTOR_F = %x", cmdh & MOTOR_F);
7899 + finished = cmdh & MOTOR_F;
7900 + finished = (finished) ? 0 : 1;
7904 + dprintk(1, "Moving from code %x to code %x takes %d ms.",
7905 + config->cur_code, code, 25-timeout);
7908 + eprintk("Unable to move motor to step %d, TIMEOUT!!", step);
7914 +int s5k4e1_motor_wakeup(struct i2c_client *client)
7916 + /* hardware wakeup: set PS = 1 */
7917 + return motor_write(client, 0xC00000);
7920 +int s5k4e1_motor_standby(struct i2c_client *client)
7922 + /* hardware standby: set PS = 0 */
7923 + return motor_write(client, 0x400000);
7926 +int s5k4e1_motor_init(struct i2c_client *client, struct s5k4e1_motor *config)
7930 + int infin_cur, macro_cur;
7931 + int step_res, step_time;
7935 + infin_cur = MAX(MOTOR_INFIN_CUR, MOTOR_DAC_MIN_CUR);
7936 + macro_cur = MIN(MOTOR_MACRO_CUR, MOTOR_DAC_MAX_CUR);
7937 + step_res = 1 << MOTOR_STEP_SHIFT;
7938 + step_time = MOTOR_STEP_TIME;
7940 + /*config->motor = client;*/
7941 + config->infin_cur = infin_cur;
7942 + config->macro_cur = macro_cur;
7944 + config->infin_code = MOTOR_INFIN_CODE;
7945 + config->macro_code = MOTOR_MACRO_CODE;
7947 + config->max_step = ((config->macro_code - config->infin_code)
7948 + >> MOTOR_STEP_SHIFT) + 1;
7949 + config->step_res = step_res;
7950 + config->step_time = step_time;
7952 + dprintk(1, "max_step: %d, step_res: %d, step_time: %d",
7953 + config->max_step, step_res, step_time);
7955 + /* Set motor step time and resolution */
7956 + val = (MOTOR_DAC_CTRL_MODE_0 << 16) | (step_res << 8) | step_time;
7957 + ret = motor_write(client, val);
7959 + /* Note here, maybe macro_code */
7960 + ret |= s5k4e1_motor_goto_position(client, config->infin_code,
7963 + config->cur_code = config->infin_code;
7964 + dprintk(1, "Motor initialization success!");
7966 + eprintk("Error while initializing motor!!!");
7971 +int s5k4e1_motor_set_focus(struct i2c_client *c,
7972 + unsigned int step,
7973 + struct s5k4e1_motor *config)
7976 + int max_step = config->max_step;
7977 + unsigned int val = step;
7979 + if (val > max_step)
7982 + s_code = (val << MOTOR_STEP_SHIFT);
7983 + s_code += config->infin_code;
7985 + ret = s5k4e1_motor_goto_position(c, s_code, config, step);
7987 + config->cur_code = s_code;
7992 +static int s5k4e1_motor_g_ctrl(struct v4l2_subdev *sd,
7993 + struct v4l2_control *ctrl)
7995 + struct i2c_client *c = v4l2_get_subdevdata(sd);
7996 + struct s5k4e1_motor *config = to_motor_config(sd);
8000 + ret = s5k4e1_motor_get_focus(c, &ctrl->value, config);
8002 + eprintk("error call s5k4e1_motor_get_focue");
8009 +static int s5k4e1_motor_s_ctrl(struct v4l2_subdev *sd,
8010 + struct v4l2_control *ctrl)
8012 + struct i2c_client *c = v4l2_get_subdevdata(sd);
8013 + struct s5k4e1_motor *config = to_motor_config(sd);
8017 + ret = s5k4e1_motor_set_focus(c, ctrl->value, config);
8019 + eprintk("error call s5k4e1_motor_set_focue");
8026 +int s5k4e1_motor_get_focus(struct i2c_client *c,
8027 + unsigned int *step,
8028 + struct s5k4e1_motor *config)
8032 + ret_step = ((config->cur_code - config->infin_code)
8033 + >> MOTOR_STEP_SHIFT);
8035 + if (ret_step <= config->max_step)
8038 + *step = config->max_step;
8043 +int s5k4e1_motor_max_step(struct i2c_client *c,
8044 + unsigned int *max_code,
8045 + struct s5k4e1_motor *config)
8047 + if (config->max_step != 0)
8048 + *max_code = config->max_step;
8053 +static int s5k4e1_motor_queryctrl(struct v4l2_subdev *sd,
8054 + struct v4l2_queryctrl *qc)
8056 + struct s5k4e1_motor *config = to_motor_config(sd);
8059 + dprintk(1, "got focus range of %d", config->max_step);
8060 + if (config->max_step != 0)
8061 + qc->maximum = config->max_step;
8066 +static const struct v4l2_subdev_core_ops s5k4e1_motor_core_ops = {
8067 + .g_ctrl = s5k4e1_motor_g_ctrl,
8068 + .s_ctrl = s5k4e1_motor_s_ctrl,
8069 + .queryctrl = s5k4e1_motor_queryctrl,
8072 +static const struct v4l2_subdev_ops s5k4e1_motor_ops = {
8073 + .core = &s5k4e1_motor_core_ops,
8076 +static int s5k4e1_motor_detect(struct i2c_client *client)
8078 + struct i2c_adapter *adapter = client->adapter;
8079 + int adap_id = i2c_adapter_id(adapter);
8081 + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
8082 + eprintk("error i2c check func");
8086 + if (adap_id != 1) {
8087 + eprintk("adap_id != 1");
8091 + if (s5k4e1_motor_wakeup(client))
8092 + eprintk("unable to wakeup s5k4e1 motor.");
8097 +static int s5k4e1_motor_probe(struct i2c_client *client,
8098 + const struct i2c_device_id *id)
8100 + struct s5k4e1_motor *info;
8101 + struct v4l2_subdev *sd;
8103 +/* struct i2c_client *motor; */
8106 + v4l_info(client, "chip found @ 0x%x (%s)\n",
8107 + client->addr << 1, client->adapter->name);
8109 + * Setup sensor configuration structure
8111 + info = kzalloc(sizeof(struct s5k4e1_motor), GFP_KERNEL);
8113 + eprintk("fail to malloc for ci_motor");
8118 + ret = s5k4e1_motor_detect(client);
8120 + eprintk("error s5k4e1_motor_detect");
8125 + v4l2_i2c_subdev_init(sd, client, &s5k4e1_motor_ops);
8128 + * Initialization S5K4E1
8129 + * then turn into standby mode
8131 + ret = s5k4e1_motor_init(client, info);
8133 + eprintk("error calling s5k4e1_motor_init");
8148 + * XXX: Need to be checked
8150 +static int s5k4e1_motor_remove(struct i2c_client *client)
8152 + struct v4l2_subdev *sd = i2c_get_clientdata(client);
8156 + v4l2_device_unregister_subdev(sd);
8157 + kfree(to_motor_config(sd));
8163 +static const struct i2c_device_id s5k4e1_motor_id[] = {
8164 + {"s5k4e1_motor", 0},
8167 +MODULE_DEVICE_TABLE(i2c, s5k4e1_motor_id);
8169 +static struct v4l2_i2c_driver_data v4l2_i2c_data = {
8170 + .name = "s5k4e1_motor",
8171 + .probe = s5k4e1_motor_probe,
8172 + .remove = s5k4e1_motor_remove,
8173 + /* .suspend = ov5630_suspend,
8174 + * .resume = ov5630_resume, */
8175 + .id_table = s5k4e1_motor_id,
8177 +MODULE_AUTHOR("Xiaolin Zhang <xiaolin.zhang@intel.com>");
8178 +MODULE_DESCRIPTION("A low-level driver for Samsung S5K4E1 sensor motor");
8179 +MODULE_LICENSE("GPL");
8180 diff --git a/drivers/media/video/mrstci/mrsts5k4e1_motor/mrsts5k4e1_motor.h b/drivers/media/video/mrstci/mrsts5k4e1_motor/mrsts5k4e1_motor.h
8181 new file mode 100644
8182 index 0000000..04f9436
8184 +++ b/drivers/media/video/mrstci/mrsts5k4e1_motor/mrsts5k4e1_motor.h
8187 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
8189 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
8191 + * This program is free software; you can redistribute it and/or
8192 + * modify it under the terms of the GNU General Public License version
8193 + * 2 as published by the Free Software Foundation.
8195 + * This program is distributed in the hope that it will be useful,
8196 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8197 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8198 + * GNU General Public License for more details.
8200 + * You should have received a copy of the GNU General Public License
8201 + * along with this program; if not, write to the Free Software
8202 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
8203 + * 02110-1301, USA.
8206 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
8209 +#include <media/v4l2-subdev.h>
8211 +/* DAC output max current (mA) */
8212 +#define MOTOR_DAC_MAX_CUR 125
8213 +/* DAC output min current (mA) */
8214 +#define MOTOR_DAC_MIN_CUR 1
8215 +/* DAC max code (Hex) */
8216 +#define MOTOR_DAC_CODE_MAX 0x3FF
8217 +/* DAC min code (Hex) */
8218 +#define MOTOR_DAC_CODE_MIN 0x0
8220 +/* VCM start code (Hex) */
8221 +#define MOTOR_INFIN_CODE 0x120
8222 +/* VCM stop code (Hex) */
8223 +#define MOTOR_MACRO_CODE 0x205
8225 +#define MOTOR_STEP_SHIFT 4 /* Step res = 2^4 = 10H */
8226 +#define MOTOR_STEP_TIME 20 /* Step time = 50us x 20d = 1ms */
8228 +/* VCM start current (mA) */
8229 +#define MOTOR_INFIN_CUR ((MOTOR_DAC_MAX_CUR / MOTOR_DAC_CODE_MAX) \
8230 + * MOTOR_INFIN_CODE + 1)
8231 +/* VCM max current for Macro (mA) */
8232 +#define MOTOR_MACRO_CUR ((MOTOR_DAC_MAX_CUR / MOTOR_DAC_CODE_MAX) \
8233 + * MOTOR_MACRO_CODE + 1)
8236 +#define MOTOR_DAC_BIT_RES 10
8237 +#define MOTOR_DAC_MAX_CODE ((1 << MOTOR_DAC_BIT_RES) - 1)
8239 +#define MOTOR_STEP_SHIFT 4
8241 +#define MAX(x, y) ((x) > (y) ? (x) : (y))
8242 +#define MIN(x, y) ((x) < (y) ? (x) : (y))
8244 +/* DAC register related define */
8245 +#define MOTOR_PS (1 << 7) /* power save */
8246 +#define MOTOR_EN (1 << 6) /* out pin status*/
8247 +#define MOTOR_M (1 << 3) /* mode select */
8248 +#define MOTOR_W (1 << 2) /* register address */
8249 +#define MOTOR_F (1 << 4) /* finish flag */
8251 +#define MOTOR_DAC_CODE_L(x) (x & 0xff)
8252 +#define MOTOR_DAC_CODE_H(x) ((x >> 8) & 0xf3)
8254 +/* Step mode setting */
8255 +#define MOTOR_DAC_CTRL_MODE_0 0xCC
8256 +/* DAC code setting */
8257 +#define MOTOR_DAC_CTRL_MODE_1 0xC8
8259 +#define S5K4E1_MOTOR_ADDR (0x18 >> 1)
8260 +/*#define POWER_EN_PIN 7*/
8261 +#define GPIO_AF_PD 95
8265 +struct s5k4e1_motor{
8266 + /*struct i2c_client *motor;*/
8267 + unsigned int infin_cur;
8268 + unsigned int infin_code;
8269 + unsigned int macro_cur;
8270 + unsigned int macro_code;
8271 + unsigned int max_step;
8272 + unsigned int cur_code;
8273 + unsigned int step_res;
8274 + unsigned int step_time;
8275 + struct v4l2_subdev sd;
8278 +extern int s5k4e1_motor_init(struct i2c_client *client,
8279 + struct s5k4e1_motor *config);
8280 +extern int s5k4e1_motor_standby(struct i2c_client *client);
8281 +extern int s5k4e1_motor_wakeup(struct i2c_client *client);
8282 +extern int s5k4e1_motor_set_focus(struct i2c_client *c, unsigned int step,
8283 + struct s5k4e1_motor *config);
8284 +extern int s5k4e1_motor_get_focus(struct i2c_client *c, unsigned int *step,
8285 + struct s5k4e1_motor *config);
8286 +extern int s5k4e1_motor_max_step(struct i2c_client *c, unsigned int *max_code,
8287 + struct s5k4e1_motor *config);