diff options
Diffstat (limited to 'extras/recipes-kernel/linux/linux-omap-psp-2.6.32/cam/5m03/0001-mt9p031-import-driver-from-https-github.com-Aptina-B.patch')
-rw-r--r-- | extras/recipes-kernel/linux/linux-omap-psp-2.6.32/cam/5m03/0001-mt9p031-import-driver-from-https-github.com-Aptina-B.patch | 1547 |
1 files changed, 1547 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-omap-psp-2.6.32/cam/5m03/0001-mt9p031-import-driver-from-https-github.com-Aptina-B.patch b/extras/recipes-kernel/linux/linux-omap-psp-2.6.32/cam/5m03/0001-mt9p031-import-driver-from-https-github.com-Aptina-B.patch new file mode 100644 index 00000000..ee728b9d --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-psp-2.6.32/cam/5m03/0001-mt9p031-import-driver-from-https-github.com-Aptina-B.patch | |||
@@ -0,0 +1,1547 @@ | |||
1 | From eefcf5de4689fbd00119d7a7df75244ca6ca1187 Mon Sep 17 00:00:00 2001 | ||
2 | From: Koen Kooi <koen@dominion.thruhere.net> | ||
3 | Date: Sun, 1 May 2011 16:40:54 +0200 | ||
4 | Subject: [PATCH 1/2] mt9p031: import driver from https://github.com/Aptina/BeagleBoard-xM/tree/master/Angstrom/MT9P031 | ||
5 | |||
6 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
7 | --- | ||
8 | drivers/media/video/Kconfig | 6 + | ||
9 | drivers/media/video/Makefile | 1 + | ||
10 | drivers/media/video/mt9p031.c | 1445 +++++++++++++++++++++++++++++++++++++++ | ||
11 | include/media/mt9p031.h | 30 + | ||
12 | include/media/v4l2-chip-ident.h | 1 + | ||
13 | 5 files changed, 1483 insertions(+), 0 deletions(-) | ||
14 | create mode 100644 drivers/media/video/mt9p031.c | ||
15 | create mode 100644 include/media/mt9p031.h | ||
16 | |||
17 | diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig | ||
18 | index 4c1fb0f..59f1133 100644 | ||
19 | --- a/drivers/media/video/Kconfig | ||
20 | +++ b/drivers/media/video/Kconfig | ||
21 | @@ -832,6 +832,12 @@ config SOC_CAMERA_MT9M111 | ||
22 | help | ||
23 | This driver supports MT9M111 and MT9M112 cameras from Micron | ||
24 | |||
25 | +config SOC_CAMERA_MT9P031 | ||
26 | + tristate "mt9p031 support" | ||
27 | + depends on SOC_CAMERA && I2C | ||
28 | + help | ||
29 | + This driver supports MT9P031 cameras from Micron. | ||
30 | + | ||
31 | config SOC_CAMERA_MT9T031 | ||
32 | tristate "mt9t031 support" | ||
33 | depends on SOC_CAMERA && I2C | ||
34 | diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile | ||
35 | index fb7e46c..f3110e7 100644 | ||
36 | --- a/drivers/media/video/Makefile | ||
37 | +++ b/drivers/media/video/Makefile | ||
38 | @@ -79,6 +79,7 @@ obj-$(CONFIG_VIDEO_MT9V113) += mt9v113.o | ||
39 | |||
40 | obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o | ||
41 | obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o | ||
42 | +obj-$(CONFIG_SOC_CAMERA_MT9P031) += mt9p031.o | ||
43 | obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o | ||
44 | obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o | ||
45 | obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o | ||
46 | diff --git a/drivers/media/video/mt9p031.c b/drivers/media/video/mt9p031.c | ||
47 | new file mode 100644 | ||
48 | index 0000000..3047e43 | ||
49 | --- /dev/null | ||
50 | +++ b/drivers/media/video/mt9p031.c | ||
51 | @@ -0,0 +1,1445 @@ | ||
52 | +/* | ||
53 | + * drivers/media/video/mt9p031.c | ||
54 | + * | ||
55 | + * Aptina mt9p031 sensor driver | ||
56 | + * | ||
57 | + * | ||
58 | + * Copyright (C) 2010 Aptina Imaging | ||
59 | + * | ||
60 | + * | ||
61 | + * Leverage mt9p012.c | ||
62 | + * | ||
63 | + * This program is free software; you can redistribute it and/or modify | ||
64 | + * it under the terms of the GNU General Public License version 2 as | ||
65 | + * published by the Free Software Foundation. | ||
66 | + * | ||
67 | + * This program is distributed in the hope that it will be useful, | ||
68 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
69 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
70 | + * GNU General Public License for more details. | ||
71 | + * | ||
72 | + * You should have received a copy of the GNU General Public License | ||
73 | + * along with this program; if not, write to the Free Software | ||
74 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
75 | + * | ||
76 | + */ | ||
77 | + | ||
78 | + | ||
79 | +#include <linux/delay.h> | ||
80 | +#include <linux/i2c.h> | ||
81 | +#include <linux/init.h> | ||
82 | +#include <linux/module.h> | ||
83 | +#include <linux/slab.h> | ||
84 | +#include <linux/kernel.h> | ||
85 | +#include <linux/videodev2.h> | ||
86 | +#include <linux/sysfs.h> | ||
87 | + | ||
88 | +#include <media/mt9p031.h> | ||
89 | +#include <media/v4l2-int-device.h> | ||
90 | +#include <media/v4l2-chip-ident.h> | ||
91 | + | ||
92 | +#define MT9P031_DEBUG | ||
93 | + | ||
94 | +#ifdef MT9P031_DEBUG | ||
95 | +#define DPRINTK_DRIVER(format, ...) \ | ||
96 | + printk(KERN_INFO "_MT9P031_DRIVER: " format, ## __VA_ARGS__) | ||
97 | +#else | ||
98 | +#define DPRINTK_DRIVER(format, ...) | ||
99 | +#endif | ||
100 | +/************************************************************************ | ||
101 | + macro | ||
102 | +************************************************************************/ | ||
103 | +// Macro to configure I2c level shifter. Use only for MT9P031 Headboards from Aptina; not required for Leopard Imaging or elsewise. | ||
104 | +#define MT9P031_HEADBOARD | ||
105 | + | ||
106 | +#define MT9P031_CHIP_ID 0x1801 | ||
107 | +#define MT9P031_MAX_HEIGHT 1944 | ||
108 | +#define MT9P031_MAX_WIDTH 2592 | ||
109 | +#define MT9P031_MIN_HEIGHT 2 | ||
110 | +#define MT9P031_MIN_WIDTH 2 | ||
111 | + | ||
112 | +#define VGA_HEIGHT 480 | ||
113 | +#define VGA_WIDTH 640 | ||
114 | + | ||
115 | +#define MT9P031_NORMAL_OPERATION_MODE (0x1F82) //write | ||
116 | +#define MT9P031_OUTPUT_CTRL_CHIP_UNSELECT (0x1F80) | ||
117 | +#define MT9P031_OUTPUT_CTRL_HALT (0x1F83) | ||
118 | + | ||
119 | +/* FPS Capabilities */ | ||
120 | +#define MT9P031_MIN_FPS 10 | ||
121 | +#define MT9P031_DEF_FPS 30 | ||
122 | +#define MT9P031_MAX_FPS 50 | ||
123 | + | ||
124 | +#define MT9P031_XCLK_NOM_1 12000000 | ||
125 | +#define MT9P031_XCLK_NOM_2 24000000 | ||
126 | + | ||
127 | +/* Analog gain values */ | ||
128 | +#define MT9P031_EV_MIN_GAIN 0 | ||
129 | +#define MT9P031_EV_MAX_GAIN 47 | ||
130 | +#define MT9P031_EV_DEF_GAIN 24 | ||
131 | +#define MT9P031_EV_GAIN_STEP 1 | ||
132 | + | ||
133 | +/* Exposure time values */ | ||
134 | +#define MT9P031_MIN_EXPOSURE 15000 | ||
135 | +#define MT9P031_MAX_EXPOSURE 128000 | ||
136 | +#define MT9P031_DEF_EXPOSURE 33000 | ||
137 | +#define MT9P031_EXPOSURE_STEP 100 | ||
138 | +#define Q12 4096 | ||
139 | +/************************************************************************ | ||
140 | + Register Address | ||
141 | +************************************************************************/ | ||
142 | + | ||
143 | +#define REG_MT9P031_CHIP_VERSION 0x00 | ||
144 | +#define REG_MT9P031_ROWSTART 0x01 | ||
145 | +#define REG_MT9P031_COLSTART 0x02 | ||
146 | +#define REG_MT9P031_HEIGHT 0x03 | ||
147 | +#define REG_MT9P031_WIDTH 0x04 | ||
148 | +#define REG_MT9P031_HBLANK 0x05 | ||
149 | +#define REG_MT9P031_VBLANK 0x06 | ||
150 | +#define REG_MT9P031_OUT_CTRL 0x07 | ||
151 | +#define REG_MT9P031_SHUTTER_WIDTH_U 0x08 | ||
152 | +#define REG_MT9P031_SHUTTER_WIDTH_L 0x09 | ||
153 | +#define REG_MT9P031_PCLK_CTRL 0x0a | ||
154 | +#define REG_MT9P031_RESTART 0x0b | ||
155 | +#define REG_MT9P031_SHUTTER_DELAY 0x0c | ||
156 | +#define REG_MT9P031_RESET 0x0d | ||
157 | + | ||
158 | +#define REG_MT9P031_PLL_CTRL 0x10 | ||
159 | +#define REG_MT9P031_PLL_CONF1 0x11 | ||
160 | +#define REG_MT9P031_PLL_CONF2 0x12 | ||
161 | + | ||
162 | +#define REG_MT9P031_READ_MODE1 0x1e | ||
163 | +#define REG_MT9P031_READ_MODE2 0x20 | ||
164 | +#define REG_MT9P031_ROW_ADDR_MODE 0x22 | ||
165 | +#define REG_MT9P031_COL_ADDR_MODE 0x23 | ||
166 | +#define REG_MT9P031_GREEN_1_GAIN 0x2b | ||
167 | +#define REG_MT9P031_BLUE_GAIN 0x2c | ||
168 | +#define REG_MT9P031_RED_GAIN 0x2d | ||
169 | +#define REG_MT9P031_GREEN_2_GAIN 0x2e | ||
170 | +#define REG_MT9P031_GLOBAL_GAIN 0x35 | ||
171 | +#define REG_MT9P031_CHIP_VERSION_ALT 0x0FF | ||
172 | + | ||
173 | +/************************************************************************ | ||
174 | + struct | ||
175 | +************************************************************************/ | ||
176 | +struct mt9p031_frame_size { | ||
177 | + u16 width; | ||
178 | + u16 height; | ||
179 | +}; | ||
180 | + | ||
181 | +struct mt9p031_priv { | ||
182 | + struct mt9p031_platform_data *pdata; | ||
183 | + struct v4l2_int_device *v4l2_int_device; | ||
184 | + struct i2c_client *client; | ||
185 | + struct v4l2_pix_format pix; | ||
186 | + struct v4l2_fract timeperframe; | ||
187 | + unsigned long xclk_current; | ||
188 | + int fps; | ||
189 | + int scaler; | ||
190 | + int ver; | ||
191 | + int model; | ||
192 | + u32 flags; | ||
193 | +/* for flags */ | ||
194 | +#define INIT_DONE (1<<0) | ||
195 | +}; | ||
196 | + | ||
197 | +struct mt9p031_priv sysPriv; | ||
198 | + | ||
199 | +static const struct v4l2_fmtdesc mt9p031_formats[] = { | ||
200 | + { | ||
201 | + .description = "Bayer (sRGB) 10 bit", | ||
202 | + .pixelformat = V4L2_PIX_FMT_SRGGB10, | ||
203 | + }, | ||
204 | +}; | ||
205 | + | ||
206 | +static const unsigned int mt9p031_num_formats = ARRAY_SIZE(mt9p031_formats); | ||
207 | + | ||
208 | +/***********************Minimum Horizontal blanking*********************/ | ||
209 | +int hb_min[4][4] = { | ||
210 | + { 450, 430, 0, 420 }, | ||
211 | + { 796, 776, 0, 766 }, | ||
212 | + { 0, 0, 0, 0 }, | ||
213 | + { 1488, 1468, 0, 1458 }, | ||
214 | +}; | ||
215 | + | ||
216 | +/**************************supported sizes******************************/ | ||
217 | +const static struct mt9p031_frame_size mt9p031_sizes[] = { | ||
218 | + { 640, 480 }, | ||
219 | + { 1280, 720 }, | ||
220 | + { 1920, 1080 }, | ||
221 | + { 2048, 1536 }, //3MP | ||
222 | + { 2592, 1944 }, //5MP | ||
223 | +}; | ||
224 | + | ||
225 | + | ||
226 | +struct mt9p031_format_params { | ||
227 | + int width; | ||
228 | + int height; | ||
229 | + int row_start; | ||
230 | + int col_start; | ||
231 | + int row_size; | ||
232 | + int col_size; | ||
233 | + int hblank; | ||
234 | + int vblank; | ||
235 | + int integ_time; | ||
236 | + int row_addr_mode; | ||
237 | + int col_addr_mode; | ||
238 | + int read_mode_2_config; | ||
239 | + int shutter_width_hi; | ||
240 | + int shutter_delay; | ||
241 | + int row_bin; | ||
242 | + int col_bin; | ||
243 | +}; | ||
244 | + | ||
245 | +enum mt9p031_image_size { | ||
246 | + VGA_BIN_30FPS, | ||
247 | + HDV_720P_30FPS, | ||
248 | + //HDV_720P_60FPS, | ||
249 | + //HDV_720P_60FPS_LVB, | ||
250 | + HDV_1080P_30FPS, | ||
251 | + MT9P031_THREE_MP, | ||
252 | + MT9P031_FIVE_MP, | ||
253 | +}; | ||
254 | + | ||
255 | +enum mt9p031_image_size mt9p031_current_format; | ||
256 | + | ||
257 | +const struct mt9p031_format_params mt9p031_supported_formats[] = { | ||
258 | + { 640, 480, 64, 24, 1919, 2559, 0, 0, 0x0296, 0x0033, 0x0033, 0x0060, 0, 0, 3, 3 }, // VGA_BIN_30FPS | ||
259 | + { 1280, 720, 64, 24, 1439, 2559, 0, 0, 0x0296, 0x0011, 0x0011, 0x0060, 0, 0, 1, 1 }, // 720P_HD_30FPS | ||
260 | + //{ 1280, 720, 0x0040, 0x0018, 0x059F, 0x09FF, 0, 0, 0x0296, 0x0011, 0x0011, 0x0060, 0, 0, 1, 1 }, // 720P_HD_60FPS | ||
261 | + //{ 1280, 720, 0x0040, 0x0018, 0x059F, 0x09FF, 0, 0x02D0, 0x0296, 0x0011, 0x0011, 0x0060, 0, 0, 1, 1 }, // 720P_HD_60FPS_LVB | ||
262 | + { 1920, 1080, 431, 335, 1079, 1919, 0, 0x0037, 0x01AC, 0, 0, 0x0040, 0, 0, 0, 0 }, // 1080P_30FPS | ||
263 | + { 2048, 1536, 431, 335, 1535, 2047, 0, 0x0037, 0x01AC, 0, 0, 0x0040, 0, 0, 0, 0 }, // 3MP CAPTURE | ||
264 | + { 2592, 1944, 431, 335, 1943, 2591, 0, 0x0037, 0x01AC, 0, 0, 0x0040, 0, 0, 0, 0 }, // 5MP CAPTURE | ||
265 | +}; | ||
266 | + | ||
267 | + | ||
268 | +const struct v4l2_fract mt9p031_frameintervals[] = { | ||
269 | + { .numerator = 1, .denominator = 10 }, | ||
270 | + { .numerator = 1, .denominator = 20 }, | ||
271 | + { .numerator = 1, .denominator = 30 }, | ||
272 | + { .numerator = 1, .denominator = 40 }, | ||
273 | + { .numerator = 1, .denominator = 50 }, | ||
274 | +}; | ||
275 | + | ||
276 | + | ||
277 | +const u16 MT9P031_EV_GAIN_TBL[48] = { | ||
278 | + /* Gain x1 */ | ||
279 | + 8, 9, 10, 11, 12, 13, 14, 15, | ||
280 | + /* Gain x2 */ | ||
281 | + 16, 17, 18, 19, 20, 21, 22, 23, | ||
282 | + /* Gain x3 */ | ||
283 | + 24, 25, 26, 27, 28, 29, 30, 31, | ||
284 | + /* Gain x4 */ | ||
285 | + 32, 33, 34, 35, | ||
286 | + /* Gain x5 */ | ||
287 | + 81, 82, 83, | ||
288 | + /* Gain x6 */ | ||
289 | + 84, 85, 86, 87, 88, 89, 90, 91, | ||
290 | + /* Gain x7 */ | ||
291 | + 92, 93, 94, 95, 96, 97, 98, 99, | ||
292 | + /* Gain x8 */ | ||
293 | + 100, | ||
294 | +}; | ||
295 | + | ||
296 | +#ifdef MT9P031_HEADBOARD | ||
297 | +/** | ||
298 | + * mt9p031_config_PCA9543A - configure on-board I2c level-shifter PCA9543A of MT9P031 Headboards from Aptina | ||
299 | + * @client: pointer to i2c client | ||
300 | + * Configures the level shifter to enable channel 0 | ||
301 | + */ | ||
302 | +static int mt9p031_config_PCA9543A(const struct i2c_client *client) | ||
303 | +{ | ||
304 | + struct i2c_msg msg; | ||
305 | + int ret; | ||
306 | + u8 buf; | ||
307 | + buf = 0x21; | ||
308 | + | ||
309 | + msg.addr = (0xE6 >> 1); //slave address of PCA9543A | ||
310 | + msg.flags = 0; | ||
311 | + msg.len = 1; | ||
312 | + msg.buf = &buf; | ||
313 | + | ||
314 | + ret = i2c_transfer(client->adapter, &msg, 1); | ||
315 | + | ||
316 | + return 0; | ||
317 | + | ||
318 | +} | ||
319 | +#endif //MT9P031_HEADBOARD | ||
320 | + | ||
321 | +/** | ||
322 | + * mt9p031_reg_read - read resgiter value | ||
323 | + * @client: pointer to i2c client | ||
324 | + * @command: register address | ||
325 | + */ | ||
326 | +static int mt9p031_reg_read(const struct i2c_client *client, u16 command, u16 *val) | ||
327 | +{ | ||
328 | + struct i2c_msg msg[2]; | ||
329 | + u8 buf[2]; | ||
330 | + int ret; | ||
331 | + | ||
332 | + // 8-bit/ byte addressable register | ||
333 | + buf[0] = command & 0xff; | ||
334 | + | ||
335 | + msg[0].addr = client->addr; | ||
336 | + msg[0].flags = 0; | ||
337 | + msg[0].len = 1; | ||
338 | + msg[0].buf = buf ; | ||
339 | + ret = i2c_transfer(client->adapter, &msg[0], 1); | ||
340 | + | ||
341 | + if(ret >= 0) { | ||
342 | + msg[1].addr = client->addr; | ||
343 | + msg[1].flags = I2C_M_RD; //1 | ||
344 | + msg[1].len = 2; | ||
345 | + msg[1].buf = buf; | ||
346 | + ret = i2c_transfer(client->adapter, &msg[1], 1); | ||
347 | + } | ||
348 | + /* | ||
349 | + * if return value of this function is < 0, | ||
350 | + * it mean error. | ||
351 | + * else, under 16bit is valid data. | ||
352 | + */ | ||
353 | + if(ret >= 0) { | ||
354 | + *val = 0; | ||
355 | + *val = buf[1] + (buf[0] << 8); | ||
356 | + return 0; | ||
357 | + } | ||
358 | + | ||
359 | + v4l_err(client, "read from offset 0x%x error %d", command, ret); | ||
360 | + return ret; | ||
361 | +} | ||
362 | + | ||
363 | +/** | ||
364 | + * mt9p031_reg_write - read resgiter value | ||
365 | + * @client: pointer to i2c client | ||
366 | + * @command: register address | ||
367 | + * @data: value to be written | ||
368 | + */ | ||
369 | +static int mt9p031_reg_write(const struct i2c_client *client, | ||
370 | + u16 command, u16 data) | ||
371 | +{ | ||
372 | + struct i2c_msg msg; | ||
373 | + u8 buf[3]; | ||
374 | + int ret; | ||
375 | + | ||
376 | + // 8-bit/ byte addressable register | ||
377 | + | ||
378 | + buf[0] = command & 0xff; | ||
379 | + data = swab16(data); | ||
380 | + memcpy(buf + 1, &data, 2); | ||
381 | + | ||
382 | + msg.addr = client->addr; | ||
383 | + msg.flags = 0; | ||
384 | + msg.len = 3; | ||
385 | + msg.buf = buf; | ||
386 | + | ||
387 | + /* | ||
388 | + * i2c_transfer return message length, | ||
389 | + * but this function should return 0 if correct case | ||
390 | + */ | ||
391 | + ret = i2c_transfer(client->adapter, &msg, 1); | ||
392 | + if (ret >= 0) | ||
393 | + ret = 0; | ||
394 | + | ||
395 | + return ret; | ||
396 | +} | ||
397 | + | ||
398 | +/** | ||
399 | + * struct vcontrol - Video controls | ||
400 | + * @v4l2_queryctrl: V4L2 VIDIOC_QUERYCTRL ioctl structure | ||
401 | + * @current_value: current value of this control | ||
402 | + */ | ||
403 | +static struct vcontrol { | ||
404 | + struct v4l2_queryctrl qc; | ||
405 | + int current_value; | ||
406 | +} mt9p031_video_control[] = { | ||
407 | + { | ||
408 | + { | ||
409 | + .id = V4L2_CID_EXPOSURE, | ||
410 | + .type = V4L2_CTRL_TYPE_INTEGER, | ||
411 | + .name = "Exposure", | ||
412 | + .minimum = MT9P031_MIN_EXPOSURE, | ||
413 | + .maximum = MT9P031_MAX_EXPOSURE, | ||
414 | + .step = MT9P031_EXPOSURE_STEP, | ||
415 | + .default_value = MT9P031_DEF_EXPOSURE, | ||
416 | + }, | ||
417 | + .current_value = MT9P031_DEF_EXPOSURE, | ||
418 | + }, | ||
419 | + { | ||
420 | + { | ||
421 | + .id = V4L2_CID_GAIN, | ||
422 | + .type = V4L2_CTRL_TYPE_INTEGER, | ||
423 | + .name = "Analog Gain", | ||
424 | + .minimum = MT9P031_EV_MIN_GAIN, | ||
425 | + .maximum = MT9P031_EV_MAX_GAIN, | ||
426 | + .step = MT9P031_EV_GAIN_STEP, | ||
427 | + .default_value = MT9P031_EV_DEF_GAIN, | ||
428 | + }, | ||
429 | + .current_value = MT9P031_EV_DEF_GAIN, | ||
430 | + }, | ||
431 | +}; | ||
432 | + | ||
433 | +/** | ||
434 | + * find_vctrl - Finds the requested ID in the video control structure array | ||
435 | + * @id: ID of control to search the video control array for | ||
436 | + * | ||
437 | + * Returns the index of the requested ID from the control structure array | ||
438 | + */ | ||
439 | +static int | ||
440 | +find_vctrl(int id) | ||
441 | +{ | ||
442 | + int i; | ||
443 | + | ||
444 | + if (id < V4L2_CID_BASE) | ||
445 | + return -EDOM; | ||
446 | + | ||
447 | + for (i = (ARRAY_SIZE(mt9p031_video_control) - 1); i >= 0; i--) | ||
448 | + if (mt9p031_video_control[i].qc.id == id) | ||
449 | + break; | ||
450 | + if (i < 0) | ||
451 | + i = -EINVAL; | ||
452 | + return i; | ||
453 | +} | ||
454 | + | ||
455 | +/** | ||
456 | + * mt9p031_calc_size - Find the best match for a requested image capture size | ||
457 | + * @width: requested image width in pixels | ||
458 | + * @height: requested image height in pixels | ||
459 | + * | ||
460 | + * Find the best match for a requested image capture size. The best match | ||
461 | + * is chosen as the nearest match that has the same number or fewer pixels | ||
462 | + * as the requested size, or the smallest image size if the requested size | ||
463 | + * has fewer pixels than the smallest image. | ||
464 | + */ | ||
465 | +static enum mt9p031_image_size mt9p031_calc_size(unsigned int width, | ||
466 | + unsigned int height) | ||
467 | +{ | ||
468 | + enum mt9p031_image_size isize; | ||
469 | + unsigned long pixels = width * height; | ||
470 | + | ||
471 | + for (isize = VGA_BIN_30FPS; isize <= MT9P031_FIVE_MP; isize++) { | ||
472 | + if (mt9p031_sizes[isize].height * | ||
473 | + mt9p031_sizes[isize].width >= pixels) { | ||
474 | + | ||
475 | + return isize; | ||
476 | + } | ||
477 | + } | ||
478 | + | ||
479 | + return MT9P031_FIVE_MP; | ||
480 | +} | ||
481 | + | ||
482 | +/** | ||
483 | + * mt9p031_find_isize - Find the best match for a requested image capture size | ||
484 | + * @width: requested image width in pixels | ||
485 | + * @height: requested image height in pixels | ||
486 | + * | ||
487 | + * Find the best match for a requested image capture size. The best match | ||
488 | + * is chosen as the nearest match that has the same number or fewer pixels | ||
489 | + * as the requested size, or the smallest image size if the requested size | ||
490 | + * has fewer pixels than the smallest image. | ||
491 | + */ | ||
492 | +static enum mt9p031_image_size mt9p031_find_isize(unsigned int width) | ||
493 | +{ | ||
494 | + enum mt9p031_image_size isize; | ||
495 | + | ||
496 | + for (isize = VGA_BIN_30FPS; isize <= MT9P031_FIVE_MP; isize++) { | ||
497 | + if (mt9p031_sizes[isize].width >= width) | ||
498 | + break; | ||
499 | + } | ||
500 | + | ||
501 | + return isize; | ||
502 | +} | ||
503 | + | ||
504 | +/** | ||
505 | + * mt9p031_calc_xclk - Calculate the required xclk frequency | ||
506 | + * @c: i2c client driver structure | ||
507 | + * | ||
508 | + * Given the image capture format in pix, the nominal frame period in | ||
509 | + * timeperframe, calculate and return the required xclk frequency | ||
510 | + */ | ||
511 | +static unsigned long mt9p031_calc_xclk(struct i2c_client *c) | ||
512 | +{ | ||
513 | + struct mt9p031_priv *priv = i2c_get_clientdata(c); | ||
514 | + struct v4l2_fract *timeperframe = &priv->timeperframe; | ||
515 | + | ||
516 | + if (timeperframe->numerator == 0 || | ||
517 | + timeperframe->denominator == 0) { | ||
518 | + /* supply a default nominal_timeperframe */ | ||
519 | + timeperframe->numerator = 1; | ||
520 | + timeperframe->denominator = MT9P031_DEF_FPS; | ||
521 | + } | ||
522 | + | ||
523 | + priv->fps = timeperframe->denominator / timeperframe->numerator; | ||
524 | + if (priv->fps < MT9P031_MIN_FPS) | ||
525 | + priv->fps = MT9P031_MIN_FPS; | ||
526 | + else if (priv->fps > MT9P031_MAX_FPS) | ||
527 | + priv->fps = MT9P031_MAX_FPS; | ||
528 | + | ||
529 | + timeperframe->numerator = 1; | ||
530 | + timeperframe->denominator = priv->fps; | ||
531 | + | ||
532 | + return MT9P031_XCLK_NOM_1; | ||
533 | +} | ||
534 | + | ||
535 | +/** | ||
536 | + * mt9p031_set_params - sets register settings according to resolution | ||
537 | + * @client: pointer to standard i2c client | ||
538 | + * @width: width as queried by ioctl | ||
539 | + * @height: height as queried by ioctl | ||
540 | + */ | ||
541 | +static int mt9p031_set_params(struct i2c_client *client, u32 width, u32 height) | ||
542 | +{ | ||
543 | + struct mt9p031_priv *priv = i2c_get_clientdata(client); | ||
544 | + struct v4l2_pix_format *pix = &priv->pix; | ||
545 | + int ret; | ||
546 | + enum mt9p031_image_size i; | ||
547 | + | ||
548 | + i = mt9p031_find_isize(pix->width); | ||
549 | + priv->pix.width = mt9p031_supported_formats[i].width; | ||
550 | + priv->pix.height = mt9p031_supported_formats[i].height; | ||
551 | + | ||
552 | + ret = mt9p031_reg_write(client, REG_MT9P031_ROWSTART, mt9p031_supported_formats[i].row_start); //ROW_WINDOW_START_REG | ||
553 | + ret |= mt9p031_reg_write(client, REG_MT9P031_COLSTART, mt9p031_supported_formats[i].col_start); //COL_WINDOW_START_REG | ||
554 | + ret |= mt9p031_reg_write(client, REG_MT9P031_HEIGHT, mt9p031_supported_formats[i].row_size); //ROW_WINDOW_SIZE_REG=1439 | ||
555 | + ret |= mt9p031_reg_write(client, REG_MT9P031_WIDTH, mt9p031_supported_formats[i].col_size); //COL_WINDOW_SIZE_REG=2559 | ||
556 | + ret |= mt9p031_reg_write(client, REG_MT9P031_HBLANK, mt9p031_supported_formats[i].hblank); //HORZ_BLANK=0 | ||
557 | + ret |= mt9p031_reg_write(client, REG_MT9P031_VBLANK, mt9p031_supported_formats[i].vblank); //VERT_BLANK_REG=720 | ||
558 | + ret |= mt9p031_reg_write(client, REG_MT9P031_SHUTTER_WIDTH_L, 0x0400); //SHUTTER_WIDTH_LOW (INTEG_TIME_REG = 1024) | ||
559 | + ret |= mt9p031_reg_write(client, REG_MT9P031_ROW_ADDR_MODE, mt9p031_supported_formats[i].row_addr_mode); //ROW_MODE, ROW_SKIP=1, ROW_BIN=1 | ||
560 | + ret |= mt9p031_reg_write(client, REG_MT9P031_COL_ADDR_MODE, mt9p031_supported_formats[i].col_addr_mode); //COL_MODE, COL_SKIP=1, COL_BIN=1 | ||
561 | + ret |= mt9p031_reg_write(client, REG_MT9P031_READ_MODE2, mt9p031_supported_formats[i].read_mode_2_config); //READ_MODE_2, COL_SUM | ||
562 | + ret |= mt9p031_reg_write(client, REG_MT9P031_SHUTTER_WIDTH_U, mt9p031_supported_formats[i].shutter_width_hi); //SHUTTER_WIDTH_HI | ||
563 | + ret |= mt9p031_reg_write(client, REG_MT9P031_SHUTTER_WIDTH_L, mt9p031_supported_formats[i].integ_time); //SHUTTER_WIDTH_LOW (INTEG_TIME_REG) | ||
564 | + ret |= mt9p031_reg_write(client, REG_MT9P031_SHUTTER_DELAY, mt9p031_supported_formats[i].shutter_delay); //SHUTTER_DELAY_REG | ||
565 | + | ||
566 | + return ret; | ||
567 | +} | ||
568 | + | ||
569 | +/** | ||
570 | + * mt9p031_init_camera - initialize camera settings | ||
571 | + * @client: pointer to i2c client | ||
572 | + * Initialize camera settings | ||
573 | + */ | ||
574 | +static int mt9p031_init_camera(const struct i2c_client *client) | ||
575 | +{ | ||
576 | + int ret; | ||
577 | + struct mt9p031_priv *priv = i2c_get_clientdata(client); | ||
578 | + struct v4l2_pix_format *pix = &priv->pix; | ||
579 | + | ||
580 | + ret = mt9p031_reg_write(client, REG_MT9P031_PLL_CTRL, 0x0051); //PLL_CTRL; power up pll | ||
581 | + ret |= mt9p031_reg_write(client, REG_MT9P031_PLL_CONF1, 0x1801); //PLL_CONFIG_1: m=24, n=1 | ||
582 | + ret |= mt9p031_reg_write(client, REG_MT9P031_PLL_CONF2, 0x0002); //PLL_CONFIG_2: p1=2, p2=0 | ||
583 | + mdelay(10); //wait 10 ms for VCO to lock | ||
584 | + ret |= mt9p031_reg_write(client, REG_MT9P031_PLL_CTRL, 0x0053); //PLL_CONTROL; use PLL | ||
585 | + mdelay(200); | ||
586 | + | ||
587 | + ret |= mt9p031_set_params(priv->client, pix->width, pix->height); | ||
588 | + | ||
589 | + ret |= mt9p031_reg_write(client, REG_MT9P031_RESET, 0x0001); //High | ||
590 | + ret |= mt9p031_reg_write(client, REG_MT9P031_RESET, 0x0000); //Low | ||
591 | + mdelay(100); | ||
592 | + | ||
593 | + ret |= mt9p031_reg_write(client, REG_MT9P031_GREEN_1_GAIN, 0x0051); //Green1_gain_reg | ||
594 | + ret |= mt9p031_reg_write(client, REG_MT9P031_BLUE_GAIN, 0x0051); //Blue_gain_reg | ||
595 | + ret |= mt9p031_reg_write(client, REG_MT9P031_RED_GAIN, 0x0051); //Red_gain_reg | ||
596 | + ret |= mt9p031_reg_write(client, REG_MT9P031_GREEN_2_GAIN, 0x0051); //Green2_gain_reg | ||
597 | + ret |= mt9p031_reg_write(client, REG_MT9P031_GLOBAL_GAIN, 0x0008); //Analog Gain | ||
598 | + ret |= mt9p031_reg_write(client, REG_MT9P031_READ_MODE1, 0x0006); //Read_mode_1 //disable AB | ||
599 | + ret |= mt9p031_reg_write(client, REG_MT9P031_OUT_CTRL, 0x1F8E); //Enable parll fifo data | ||
600 | + | ||
601 | + return ret>= 0 ? 0 : -EIO; | ||
602 | +} | ||
603 | + | ||
604 | +/************************************************************************ | ||
605 | + i2c driver | ||
606 | +************************************************************************/ | ||
607 | +/** | ||
608 | + * mt9p031_detect - Detect if an mt9p031 is present, and if so which revision | ||
609 | + * @client: pointer to the i2c client driver structure | ||
610 | + * | ||
611 | + * Returns a negative error number if no device is detected | ||
612 | + */ | ||
613 | +static int mt9p031_detect(struct i2c_client *client) | ||
614 | +{ | ||
615 | + struct mt9p031_priv *priv = i2c_get_clientdata(client); | ||
616 | + const char *devname; | ||
617 | + u16 chipid; | ||
618 | + | ||
619 | + if (!client) | ||
620 | + return -ENODEV; | ||
621 | + /* | ||
622 | + * Set Normal Mode | ||
623 | + */ | ||
624 | + if(mt9p031_reg_write(client, REG_MT9P031_OUT_CTRL, MT9P031_NORMAL_OPERATION_MODE)) | ||
625 | + return -ENODEV; | ||
626 | + /* | ||
627 | + * check and show chip ID | ||
628 | + */ | ||
629 | + if(mt9p031_reg_read(client, REG_MT9P031_CHIP_VERSION, &chipid)) | ||
630 | + return -ENODEV; | ||
631 | + | ||
632 | + if(chipid == MT9P031_CHIP_ID) { | ||
633 | + devname = "mt9p031"; | ||
634 | + priv->model = V4L2_IDENT_MT9P031; | ||
635 | + dev_info(&client->dev, "%s chip ID %04x\n", devname, chipid); | ||
636 | + return 0; | ||
637 | + } | ||
638 | + | ||
639 | + dev_err(&client->dev, "Product ID error %04x\n", chipid); | ||
640 | + return -ENODEV; | ||
641 | +} | ||
642 | + | ||
643 | +/** | ||
644 | + * mt9p031_set_exposure_time - sets exposure time per input value | ||
645 | + * @exp_time: exposure time to be set on device | ||
646 | + * @client: pointer to standard i2c client | ||
647 | + * @lvc: pointer to V4L2 exposure entry in video_controls array | ||
648 | + * | ||
649 | + * If the requested exposure time is within the allowed limits, the HW | ||
650 | + * is configured to use the new exposure time, and the video_controls | ||
651 | + * array is updated with the new current value. | ||
652 | + * The function returns 0 upon success. Otherwise an error code is | ||
653 | + * returned. | ||
654 | + */ | ||
655 | +static int mt9p031_set_exposure_time(u32 exp_time, struct i2c_client *client, | ||
656 | + struct vcontrol *lvc) | ||
657 | +{ | ||
658 | + int ret = 0, i, shutter_width, so_p, t_pix_clk, sd_p, shutter_delay; | ||
659 | + int sw_l ,sw_u ,W ,h_blanking, t_row; | ||
660 | + | ||
661 | + if(exp_time < MT9P031_MIN_EXPOSURE) | ||
662 | + exp_time = MT9P031_MIN_EXPOSURE; | ||
663 | + else if(exp_time > MT9P031_MAX_EXPOSURE) | ||
664 | + exp_time = MT9P031_MAX_EXPOSURE; | ||
665 | + | ||
666 | + shutter_delay = mt9p031_supported_formats[mt9p031_current_format].shutter_delay; | ||
667 | + sd_p = min(shutter_delay + 1, 1504); | ||
668 | + so_p = 208 * (mt9p031_supported_formats[mt9p031_current_format].row_bin + 1) + 98 + sd_p - 94; | ||
669 | + t_pix_clk = (Q12/96 ); | ||
670 | + h_blanking = mt9p031_supported_formats[mt9p031_current_format].hblank + 1; | ||
671 | + W = 2 * (int)((mt9p031_supported_formats[mt9p031_current_format].row_size + 1) / (2 * (mt9p031_supported_formats[mt9p031_current_format].row_bin + 1)) + 1); | ||
672 | + t_row = 2 * t_pix_clk * max(W/2 + max(h_blanking, hb_min[mt9p031_supported_formats[mt9p031_current_format].row_bin][mt9p031_supported_formats[mt9p031_current_format].col_bin]), | ||
673 | + (41 + 346 * (mt9p031_supported_formats[mt9p031_current_format].row_bin + 1) + 99))/Q12; | ||
674 | + | ||
675 | + shutter_width = (exp_time + 2*so_p*t_pix_clk) / t_row; | ||
676 | + | ||
677 | + if (shutter_width< 3) { | ||
678 | + sd_p = 1232 > shutter_delay ? 1232 : shutter_delay; | ||
679 | + so_p = 208 * (mt9p031_supported_formats[mt9p031_current_format].row_bin + 1) + 98 + sd_p - 94; | ||
680 | + shutter_width = ((exp_time*Q12 + 2*so_p*t_pix_clk) / (t_row * Q12)); | ||
681 | + } | ||
682 | + | ||
683 | + if (shutter_width < 1) | ||
684 | + shutter_width = 1; | ||
685 | + sw_l = shutter_width& 0xffff; | ||
686 | + sw_u = (shutter_width)>> 16; | ||
687 | + ret = mt9p031_reg_write(client, REG_MT9P031_SHUTTER_WIDTH_L,sw_l); | ||
688 | + mdelay(1); | ||
689 | + ret = mt9p031_reg_write(client, REG_MT9P031_SHUTTER_WIDTH_U,sw_u); | ||
690 | + | ||
691 | + if (ret) | ||
692 | + dev_err(&client->dev, "Error setting exposure time %d\n", | ||
693 | + ret); | ||
694 | + else{ | ||
695 | + i = find_vctrl(V4L2_CID_EXPOSURE); | ||
696 | + if (i >= 0) { | ||
697 | + lvc = &mt9p031_video_control[i]; | ||
698 | + lvc->current_value = exp_time; | ||
699 | + } | ||
700 | + } | ||
701 | + | ||
702 | + return ret; | ||
703 | +} | ||
704 | + | ||
705 | +/** | ||
706 | + * mt9p031_set_gain - sets sensor analog gain per input value | ||
707 | + * @lineargain: analog gain value index to be set on device | ||
708 | + * @client: pointer to standard i2c client | ||
709 | + * @lvc: pointer to V4L2 analog gain entry in video_controls array | ||
710 | + * | ||
711 | + * If the requested analog gain is within the allowed limits, the HW | ||
712 | + * is configured to use the new gain value, and the video_controls | ||
713 | + * array is updated with the new current value. | ||
714 | + * The function returns 0 upon success. Otherwise an error code is | ||
715 | + * returned. | ||
716 | + */ | ||
717 | +int mt9p031_set_gain(u16 lineargain, struct i2c_client *client, | ||
718 | + struct vcontrol *lvc) | ||
719 | +{ | ||
720 | + int ret= 0, i; | ||
721 | + u16 reg_gain = 0; | ||
722 | + | ||
723 | + if (lineargain < MT9P031_EV_MIN_GAIN) { | ||
724 | + lineargain = MT9P031_EV_MIN_GAIN; | ||
725 | + v4l_err(client, "Gain out of legal range."); | ||
726 | + } | ||
727 | + if (lineargain > MT9P031_EV_MAX_GAIN) { | ||
728 | + lineargain = MT9P031_EV_MAX_GAIN; | ||
729 | + v4l_err(client, "Gain out of legal range."); | ||
730 | + } | ||
731 | + | ||
732 | + reg_gain = MT9P031_EV_GAIN_TBL[lineargain]; | ||
733 | + ret = mt9p031_reg_write(client, REG_MT9P031_GLOBAL_GAIN, | ||
734 | + reg_gain); | ||
735 | + | ||
736 | + if (ret) { | ||
737 | + dev_err(&client->dev, "Error setting gain.%d", ret); | ||
738 | + return ret; | ||
739 | + } | ||
740 | + else { | ||
741 | + i = find_vctrl(V4L2_CID_GAIN); | ||
742 | + if (i >= 0) { | ||
743 | + lvc = &mt9p031_video_control[i]; | ||
744 | + lvc->current_value = lineargain; | ||
745 | + } | ||
746 | + } | ||
747 | + | ||
748 | + return ret; | ||
749 | +} | ||
750 | + | ||
751 | +/************************************************************************ | ||
752 | + v4l2_ioctls | ||
753 | +************************************************************************/ | ||
754 | + | ||
755 | +/** | ||
756 | + * mt9p031_v4l2_int_s_power - V4L2 sensor interface handler for vidioc_int_s_power_num | ||
757 | + * @s: pointer to standard V4L2 device structure | ||
758 | + * @on: power state to which device is to be set | ||
759 | + * | ||
760 | + * Sets devices power state to requrested state, if possible. | ||
761 | + */ | ||
762 | +static int mt9p031_v4l2_int_s_power(struct v4l2_int_device *s, | ||
763 | + enum v4l2_power power) | ||
764 | +{ | ||
765 | + struct mt9p031_priv *priv = s->priv; | ||
766 | + struct i2c_client *client = priv->client; | ||
767 | + | ||
768 | + int ret; | ||
769 | + | ||
770 | + switch (power) { | ||
771 | + case V4L2_POWER_STANDBY: | ||
772 | + /* FALLTHROUGH */ | ||
773 | + case V4L2_POWER_OFF: | ||
774 | + ret = priv->pdata->power_set(s, power); | ||
775 | + if (ret < 0) { | ||
776 | + dev_err(&client->dev, "Unable to set target board power " | ||
777 | + "state (OFF/STANDBY)\n"); | ||
778 | + return ret; | ||
779 | + } | ||
780 | + break; | ||
781 | + case V4L2_POWER_ON: | ||
782 | + ret = priv->pdata->power_set(s, power); | ||
783 | + | ||
784 | + if (ret < 0) { | ||
785 | + dev_err(&client->dev, "Unable to set target board power " | ||
786 | + "state (ON)\n"); | ||
787 | + return ret; | ||
788 | + } | ||
789 | + if (!(priv->flags & INIT_DONE)) { | ||
790 | + ret = mt9p031_detect(client); | ||
791 | + if (ret < 0) { | ||
792 | + dev_err(&client->dev, "Unable to detect sensor\n"); | ||
793 | + return ret; | ||
794 | + } | ||
795 | + priv->flags |= INIT_DONE; | ||
796 | + } | ||
797 | + | ||
798 | + ret = mt9p031_init_camera(client); | ||
799 | + if (ret < 0) { | ||
800 | + dev_err(&client->dev, "Unable to initialize sensor\n"); | ||
801 | + return ret; | ||
802 | + } | ||
803 | + } | ||
804 | + | ||
805 | + return 0; | ||
806 | +} | ||
807 | + | ||
808 | +/** | ||
809 | + * mt9p031_v4l2_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl | ||
810 | + * @s: pointer to standard V4L2 device structure | ||
811 | + * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure | ||
812 | + * | ||
813 | + * If the requested control is supported, sets the control's current | ||
814 | + * value in HW (and updates the video_control[] array). Otherwise, | ||
815 | + * returns -EINVAL if the control is not supported. | ||
816 | + */ | ||
817 | +static int mt9p031_v4l2_s_ctrl(struct v4l2_int_device *s, | ||
818 | + struct v4l2_control *vc) | ||
819 | +{ | ||
820 | + int retval = -EINVAL; | ||
821 | + int i; | ||
822 | + struct vcontrol *lvc; | ||
823 | + struct mt9p031_priv *priv = s->priv; | ||
824 | + struct i2c_client *client = priv->client; | ||
825 | + | ||
826 | + i = find_vctrl(vc->id); | ||
827 | + if (i < 0) | ||
828 | + return -EINVAL; | ||
829 | + lvc = &mt9p031_video_control[i]; | ||
830 | + | ||
831 | + switch (vc->id) { | ||
832 | + case V4L2_CID_EXPOSURE: | ||
833 | + retval = mt9p031_set_exposure_time(vc->value, client, lvc); | ||
834 | + break; | ||
835 | + case V4L2_CID_GAIN: | ||
836 | + retval = mt9p031_set_gain(vc->value, client, lvc); | ||
837 | + break; | ||
838 | + } | ||
839 | + | ||
840 | + return retval; | ||
841 | +} | ||
842 | + | ||
843 | +/** | ||
844 | + * mt9p031_v4l2_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl | ||
845 | + * @s: pointer to standard V4L2 device structure | ||
846 | + * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure | ||
847 | + * | ||
848 | + * If the requested control is supported, returns the control's current | ||
849 | + * value from the video_control[] array. Otherwise, returns -EINVAL | ||
850 | + * if the control is not supported. | ||
851 | + */ | ||
852 | +static int mt9p031_v4l2_g_ctrl(struct v4l2_int_device *s, | ||
853 | + struct v4l2_control *vc) | ||
854 | +{ | ||
855 | + struct vcontrol *lvc; | ||
856 | + int i; | ||
857 | + | ||
858 | + i = find_vctrl(vc->id); | ||
859 | + if (i < 0) | ||
860 | + return -EINVAL; | ||
861 | + lvc = &mt9p031_video_control[i]; | ||
862 | + | ||
863 | + switch (vc->id) { | ||
864 | + case V4L2_CID_EXPOSURE: | ||
865 | + vc->value = lvc->current_value; | ||
866 | + break; | ||
867 | + case V4L2_CID_GAIN: | ||
868 | + vc->value = lvc->current_value; | ||
869 | + break; | ||
870 | + } | ||
871 | + | ||
872 | + return 0; | ||
873 | +} | ||
874 | + | ||
875 | +/** | ||
876 | + * mt9p031_v4l2_queryctrl - V4L2 sensor interface handler for VIDIOC_QUERYCTRL ioctl | ||
877 | + * @s: pointer to standard V4L2 device structure | ||
878 | + * @qc: standard V4L2 VIDIOC_QUERYCTRL ioctl structure | ||
879 | + * | ||
880 | + * If the requested control is supported, returns the control information | ||
881 | + * from the video_control[] array. Otherwise, returns -EINVAL if the | ||
882 | + * control is not supported. | ||
883 | + */ | ||
884 | +static int mt9p031_v4l2_queryctrl(struct v4l2_int_device *s, struct v4l2_queryctrl *qc) | ||
885 | +{ | ||
886 | + int i; | ||
887 | + | ||
888 | + i = find_vctrl(qc->id); | ||
889 | + if (i == -EINVAL) | ||
890 | + qc->flags = V4L2_CTRL_FLAG_DISABLED; | ||
891 | + | ||
892 | + if (i < 0) | ||
893 | + return -EINVAL; | ||
894 | + | ||
895 | + *qc = mt9p031_video_control[i].qc; | ||
896 | + return 0; | ||
897 | +} | ||
898 | + | ||
899 | + | ||
900 | +/** | ||
901 | + * mt9p031_v4l2_int_enum_fmt_cap - Implement the CAPTURE buffer VIDIOC_ENUM_FMT ioctl | ||
902 | + * @s: pointer to standard V4L2 device structure | ||
903 | + * @fmt: standard V4L2 VIDIOC_ENUM_FMT ioctl structure | ||
904 | + * | ||
905 | + * Implement the VIDIOC_ENUM_FMT ioctl for the CAPTURE buffer type. | ||
906 | + */ | ||
907 | +static int mt9p031_v4l2_int_enum_fmt_cap(struct v4l2_int_device *s, | ||
908 | + struct v4l2_fmtdesc *fmt) | ||
909 | +{ | ||
910 | + int index = fmt->index; | ||
911 | + enum v4l2_buf_type type = fmt->type; | ||
912 | + | ||
913 | + memset(fmt, 0, sizeof(*fmt)); | ||
914 | + fmt->index = index; | ||
915 | + fmt->type = type; | ||
916 | + | ||
917 | + switch (fmt->type) { | ||
918 | + case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
919 | + if (index >= ARRAY_SIZE(mt9p031_formats)) | ||
920 | + return -EINVAL; | ||
921 | + break; | ||
922 | + default: | ||
923 | + return -EINVAL; | ||
924 | + } | ||
925 | + | ||
926 | + strlcpy(fmt->description, mt9p031_formats[index].description, | ||
927 | + sizeof(fmt->description)); | ||
928 | + fmt->pixelformat = mt9p031_formats[index].pixelformat; | ||
929 | + | ||
930 | + return 0; | ||
931 | +} | ||
932 | + | ||
933 | +/** | ||
934 | + * mt9p031_v4l2_int_try_fmt_cap - Implement the CAPTURE buffer VIDIOC_TRY_FMT ioctl | ||
935 | + * @s: pointer to standard V4L2 device structure | ||
936 | + * @f: pointer to standard V4L2 VIDIOC_TRY_FMT ioctl structure | ||
937 | + * | ||
938 | + * Implement the VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type. This | ||
939 | + * ioctl is used to negotiate the image capture size and pixel format | ||
940 | + * without actually making it take effect. | ||
941 | + */ | ||
942 | +static int mt9p031_v4l2_int_try_fmt_cap(struct v4l2_int_device *s, | ||
943 | + struct v4l2_format *f) | ||
944 | +{ | ||
945 | + enum mt9p031_image_size isize; | ||
946 | + int ifmt; | ||
947 | + struct v4l2_pix_format *pix = &f->fmt.pix; | ||
948 | + struct mt9p031_priv *priv = s->priv; | ||
949 | + struct v4l2_pix_format *pix2 = &priv->pix; | ||
950 | + | ||
951 | + isize = mt9p031_calc_size(pix->width, pix->height); | ||
952 | + mt9p031_current_format = isize; | ||
953 | + | ||
954 | + pix->width = mt9p031_sizes[isize].width; | ||
955 | + pix->height = mt9p031_sizes[isize].height; | ||
956 | + for (ifmt = 0; ifmt < mt9p031_num_formats; ifmt++) { | ||
957 | + if (pix->pixelformat == mt9p031_formats[ifmt].pixelformat) | ||
958 | + break; | ||
959 | + } | ||
960 | + if (ifmt == mt9p031_num_formats) | ||
961 | + ifmt = 0; | ||
962 | + pix->pixelformat = mt9p031_formats[ifmt].pixelformat; | ||
963 | + pix->field = V4L2_FIELD_NONE; | ||
964 | + pix->bytesperline = pix->width * 2; | ||
965 | + pix->sizeimage = pix->bytesperline * pix->height; | ||
966 | + pix->priv = 0; | ||
967 | + pix->colorspace = V4L2_COLORSPACE_SRGB; | ||
968 | + | ||
969 | + *pix2 = *pix; | ||
970 | + | ||
971 | + return 0; | ||
972 | +} | ||
973 | + | ||
974 | +/** | ||
975 | + * mt9p031_v4l2_int_s_fmt_cap - V4L2 sensor interface handler for VIDIOC_S_FMT ioctl | ||
976 | + * @s: pointer to standard V4L2 device structure | ||
977 | + * @f: pointer to standard V4L2 VIDIOC_S_FMT ioctl structure | ||
978 | + * | ||
979 | + * If the requested format is supported, configures the HW to use that | ||
980 | + * format, returns error code if format not supported or HW can't be | ||
981 | + * correctly configured. | ||
982 | + */ | ||
983 | +static int mt9p031_v4l2_int_s_fmt_cap(struct v4l2_int_device *s, | ||
984 | + struct v4l2_format *f) | ||
985 | +{ | ||
986 | + struct mt9p031_priv *priv = s->priv; | ||
987 | + struct v4l2_pix_format *pix = &f->fmt.pix; | ||
988 | + int rval; | ||
989 | + | ||
990 | + rval = mt9p031_v4l2_int_try_fmt_cap(s, f); | ||
991 | + if (!rval) | ||
992 | + priv->pix = *pix; | ||
993 | + | ||
994 | + return rval; | ||
995 | +} | ||
996 | + | ||
997 | +/** | ||
998 | + * mt9p031_v4l2_int_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap | ||
999 | + * @s: pointer to standard V4L2 device structure | ||
1000 | + * @f: pointer to standard V4L2 v4l2_format structure | ||
1001 | + * | ||
1002 | + * Returns the sensor's current pixel format in the v4l2_format | ||
1003 | + * parameter. | ||
1004 | + */ | ||
1005 | +static int mt9p031_v4l2_int_g_fmt_cap(struct v4l2_int_device *s, | ||
1006 | + struct v4l2_format *f) | ||
1007 | +{ | ||
1008 | + struct mt9p031_priv *priv = s->priv; | ||
1009 | + | ||
1010 | + f->fmt.pix.width = priv->pix.width; | ||
1011 | + f->fmt.pix.height = priv->pix.height; | ||
1012 | + f->fmt.pix.pixelformat = V4L2_COLORSPACE_SRGB; | ||
1013 | + f->fmt.pix.pixelformat = priv->pix.pixelformat; | ||
1014 | + f->fmt.pix.field = V4L2_FIELD_NONE; | ||
1015 | + | ||
1016 | + return 0; | ||
1017 | +} | ||
1018 | + | ||
1019 | +/** | ||
1020 | + * mt9p031_v4l2_int_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl | ||
1021 | + * @s: pointer to standard V4L2 device structure | ||
1022 | + * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure | ||
1023 | + * | ||
1024 | + * Configures the sensor to use the input parameters, if possible. If | ||
1025 | + * not possible, reverts to the old parameters and returns the | ||
1026 | + * appropriate error code. | ||
1027 | + */ | ||
1028 | + | ||
1029 | + | ||
1030 | +static int mt9p031_v4l2_int_s_parm(struct v4l2_int_device *s, | ||
1031 | + struct v4l2_streamparm *a) | ||
1032 | +{ | ||
1033 | + struct mt9p031_priv *priv = s->priv; | ||
1034 | + struct i2c_client *client = priv->client; | ||
1035 | + struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe; | ||
1036 | + | ||
1037 | + priv->timeperframe = *timeperframe; | ||
1038 | + priv->xclk_current = mt9p031_calc_xclk(client); | ||
1039 | + *timeperframe = priv->timeperframe; | ||
1040 | + | ||
1041 | + return 0; | ||
1042 | +} | ||
1043 | + | ||
1044 | +/** | ||
1045 | + * mt9p031_v4l2_int_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl | ||
1046 | + * @s: pointer to standard V4L2 device structure | ||
1047 | + * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure | ||
1048 | + * | ||
1049 | + * Returns the sensor's video CAPTURE parameters. | ||
1050 | + */ | ||
1051 | +static int mt9p031_v4l2_int_g_parm(struct v4l2_int_device *s, | ||
1052 | + struct v4l2_streamparm *a) | ||
1053 | +{ | ||
1054 | + struct mt9p031_priv *priv = s->priv; | ||
1055 | + struct v4l2_captureparm *cparm = &a->parm.capture; | ||
1056 | + | ||
1057 | + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1058 | + return -EINVAL; | ||
1059 | + | ||
1060 | + memset(a, 0, sizeof(*a)); | ||
1061 | + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1062 | + | ||
1063 | + cparm->capability = V4L2_CAP_TIMEPERFRAME; | ||
1064 | + cparm->timeperframe.numerator = 1; | ||
1065 | + cparm->timeperframe = priv->timeperframe; | ||
1066 | + | ||
1067 | + return 0; | ||
1068 | +} | ||
1069 | + | ||
1070 | +/** | ||
1071 | + * mt9p031_v4l2_int_g_priv - V4L2 sensor interface handler for vidioc_int_g_priv_num | ||
1072 | + * @s: pointer to standard V4L2 device structure | ||
1073 | + * @p: void pointer to hold sensor's private data address | ||
1074 | + * | ||
1075 | + * Returns device's (sensor's) private data area address in p parameter | ||
1076 | + */ | ||
1077 | +static int mt9p031_v4l2_int_g_priv(struct v4l2_int_device *s, void *p) | ||
1078 | +{ | ||
1079 | + struct mt9p031_priv *priv = s->priv; | ||
1080 | + | ||
1081 | + return priv->pdata->priv_data_set(p); | ||
1082 | +} | ||
1083 | + | ||
1084 | +/** | ||
1085 | + * mt9p031_v4l2_int_g_ifparm - V4L2 sensor interface handler for vidioc_int_g_priv_num | ||
1086 | + * @s: pointer to standard V4L2 device structure | ||
1087 | + * @p: void pointer to hold sensor's ifparm | ||
1088 | + * | ||
1089 | + * Returns device's (sensor's) ifparm in p parameter | ||
1090 | + */ | ||
1091 | +static int mt9p031_v4l2_int_g_ifparm(struct v4l2_int_device *s, | ||
1092 | + struct v4l2_ifparm *p) | ||
1093 | +{ | ||
1094 | + struct mt9p031_priv *priv = s->priv; | ||
1095 | + int rval; | ||
1096 | + | ||
1097 | + if (p == NULL) | ||
1098 | + return -EINVAL; | ||
1099 | + | ||
1100 | + if (!priv->pdata->ifparm) | ||
1101 | + return -EINVAL; | ||
1102 | + | ||
1103 | + rval = priv->pdata->ifparm(p); | ||
1104 | + if (rval) { | ||
1105 | + v4l_err(priv->client, "g_ifparm.Err[%d]\n", rval); | ||
1106 | + return rval; | ||
1107 | + } | ||
1108 | + | ||
1109 | + return 0; | ||
1110 | +} | ||
1111 | + | ||
1112 | +/** | ||
1113 | + * mt9p031_v4l2_int_enum_framesizes - V4L2 sensor if handler for vidioc_int_enum_framesizes | ||
1114 | + * @s: pointer to standard V4L2 device structure | ||
1115 | + * @frms: pointer to standard V4L2 framesizes enumeration structure | ||
1116 | + * | ||
1117 | + * Returns possible framesizes depending on choosen pixel format | ||
1118 | + */ | ||
1119 | +static int mt9p031_v4l2_int_enum_framesizes(struct v4l2_int_device *s, | ||
1120 | + struct v4l2_frmsizeenum *frms) | ||
1121 | +{ | ||
1122 | + int ifmt; | ||
1123 | + | ||
1124 | + for (ifmt = 0; ifmt < ARRAY_SIZE(mt9p031_formats); ifmt++) | ||
1125 | + if (mt9p031_formats[ifmt].pixelformat == frms->pixel_format) | ||
1126 | + break; | ||
1127 | + | ||
1128 | + if (ifmt == ARRAY_SIZE(mt9p031_formats)) | ||
1129 | + return -EINVAL; | ||
1130 | + | ||
1131 | + /* Do we already reached all discrete framesizes? */ | ||
1132 | + if (frms->index >= ARRAY_SIZE(mt9p031_sizes)) | ||
1133 | + return -EINVAL; | ||
1134 | + | ||
1135 | + frms->type = V4L2_FRMSIZE_TYPE_DISCRETE; | ||
1136 | + frms->discrete.width = mt9p031_sizes[frms->index].width; | ||
1137 | + frms->discrete.height = mt9p031_sizes[frms->index].height; | ||
1138 | + | ||
1139 | + return 0; | ||
1140 | +} | ||
1141 | + | ||
1142 | +static int mt9p031_v4l2_int_enum_frameintervals(struct v4l2_int_device *s, | ||
1143 | + struct v4l2_frmivalenum *frmi) | ||
1144 | +{ | ||
1145 | + int ifmt; | ||
1146 | + int max_size; | ||
1147 | + | ||
1148 | + for (ifmt = 0; ifmt < ARRAY_SIZE(mt9p031_formats); ifmt++) | ||
1149 | + if (mt9p031_formats[ifmt].pixelformat == frmi->pixel_format) | ||
1150 | + break; | ||
1151 | + | ||
1152 | + if (ifmt == ARRAY_SIZE(mt9p031_formats)) | ||
1153 | + return -EINVAL; | ||
1154 | + | ||
1155 | + max_size = ARRAY_SIZE(mt9p031_sizes); | ||
1156 | + | ||
1157 | + for(ifmt = 0; ifmt < max_size; ifmt++) { | ||
1158 | + if(frmi->width <= mt9p031_sizes[ifmt].width) { | ||
1159 | + frmi->type = V4L2_FRMSIZE_TYPE_DISCRETE; | ||
1160 | + frmi->discrete.numerator = | ||
1161 | + mt9p031_frameintervals[frmi->index].numerator; | ||
1162 | + frmi->discrete.denominator = | ||
1163 | + mt9p031_frameintervals[frmi->index].denominator; | ||
1164 | + | ||
1165 | + if(frmi->discrete.denominator <= mt9p031_frameintervals[max_size - ifmt - 1].denominator) | ||
1166 | + return 0; | ||
1167 | + else | ||
1168 | + return -EINVAL; | ||
1169 | + } | ||
1170 | + } | ||
1171 | + | ||
1172 | + return 0; | ||
1173 | +} | ||
1174 | + | ||
1175 | +static struct v4l2_int_ioctl_desc mt9p031_ioctl_desc[] = { | ||
1176 | + { .num = vidioc_int_enum_framesizes_num, | ||
1177 | + .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_enum_framesizes }, | ||
1178 | + { .num = vidioc_int_enum_frameintervals_num, | ||
1179 | + .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_enum_frameintervals }, | ||
1180 | + { .num = vidioc_int_s_power_num, | ||
1181 | + .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_s_power }, | ||
1182 | + { .num = vidioc_int_g_priv_num, | ||
1183 | + .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_g_priv }, | ||
1184 | + { .num = vidioc_int_g_ifparm_num, | ||
1185 | + .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_g_ifparm }, | ||
1186 | + { .num = vidioc_int_enum_fmt_cap_num, | ||
1187 | + .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_enum_fmt_cap }, | ||
1188 | + { .num = vidioc_int_try_fmt_cap_num, | ||
1189 | + .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_try_fmt_cap }, | ||
1190 | + { .num = vidioc_int_g_fmt_cap_num, | ||
1191 | + .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_g_fmt_cap }, | ||
1192 | + { .num = vidioc_int_s_fmt_cap_num, | ||
1193 | + .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_s_fmt_cap }, | ||
1194 | + { .num = vidioc_int_g_parm_num, | ||
1195 | + .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_g_parm }, | ||
1196 | + { .num = vidioc_int_s_parm_num, | ||
1197 | + .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_s_parm }, | ||
1198 | + { .num = vidioc_int_g_ctrl_num, | ||
1199 | + .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_g_ctrl }, | ||
1200 | + { .num = vidioc_int_s_ctrl_num, | ||
1201 | + .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_s_ctrl }, | ||
1202 | + { .num = vidioc_int_queryctrl_num, | ||
1203 | + .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_queryctrl }, | ||
1204 | +}; | ||
1205 | + | ||
1206 | +#ifdef MT9P031_DEBUG | ||
1207 | +/** | ||
1208 | + * --------------------------------------------------------------------------------- | ||
1209 | + * Sysfs | ||
1210 | + * --------------------------------------------------------------------------------- | ||
1211 | + */ | ||
1212 | + | ||
1213 | +/* Basic register read write support */ | ||
1214 | +static u16 mt9p031_attr_basic_addr = 0x0000; | ||
1215 | + | ||
1216 | +static ssize_t | ||
1217 | +mt9p031_basic_reg_addr_show( struct device *dev, struct device_attribute *attr, char *buf) | ||
1218 | +{ | ||
1219 | + return sprintf(buf, "0x%x\n", mt9p031_attr_basic_addr); | ||
1220 | +} | ||
1221 | + | ||
1222 | +static ssize_t | ||
1223 | +mt9p031_basic_reg_addr_store( struct device *dev, struct device_attribute *attr, const char *buf, size_t n) | ||
1224 | +{ | ||
1225 | + u16 val; | ||
1226 | + sscanf(buf, "%hx", &val); | ||
1227 | + mt9p031_attr_basic_addr = (u16) val; | ||
1228 | + return n; | ||
1229 | +} | ||
1230 | + | ||
1231 | +static DEVICE_ATTR( basic_reg_addr, S_IRUGO|S_IWUSR, mt9p031_basic_reg_addr_show, mt9p031_basic_reg_addr_store); | ||
1232 | + | ||
1233 | + | ||
1234 | +static ssize_t | ||
1235 | +mt9p031_basic_reg_val_show( struct device *dev, struct device_attribute *attr, char *buf) | ||
1236 | +{ | ||
1237 | + u16 val; | ||
1238 | + int ret; | ||
1239 | + ret = mt9p031_reg_read(sysPriv.client, mt9p031_attr_basic_addr, &val); | ||
1240 | + if(ret < 0){ | ||
1241 | + printk(KERN_INFO "mt9p031: Basic register read failed"); | ||
1242 | + return 1; // nothing processed | ||
1243 | + } else { | ||
1244 | + return sprintf(buf, "0x%x\n", val); | ||
1245 | + } | ||
1246 | +} | ||
1247 | + | ||
1248 | +static ssize_t | ||
1249 | +mt9p031_basic_reg_val_store( struct device *dev, struct device_attribute *attr, const char *buf, size_t n) | ||
1250 | +{ | ||
1251 | + u32 val; | ||
1252 | + sscanf(buf, "%x", &val); | ||
1253 | + | ||
1254 | + if (mt9p031_reg_write(sysPriv.client, mt9p031_attr_basic_addr, (u16)val)) { | ||
1255 | + printk(KERN_INFO "mt9p031: Basic regiser write failed"); | ||
1256 | + return n; // nothing processed | ||
1257 | + } else { | ||
1258 | + return n; | ||
1259 | + } | ||
1260 | +} | ||
1261 | +static DEVICE_ATTR( basic_reg_val, S_IRUGO|S_IWUSR, mt9p031_basic_reg_val_show, mt9p031_basic_reg_val_store); | ||
1262 | + | ||
1263 | + | ||
1264 | +/* Exposure time access support */ | ||
1265 | +static ssize_t | ||
1266 | +mt9p031_exposure_val_show( struct device *dev, struct device_attribute *attr, char *buf) | ||
1267 | +{ | ||
1268 | + u32 val; | ||
1269 | + struct vcontrol *lvc; | ||
1270 | + int i = find_vctrl(V4L2_CID_EXPOSURE); | ||
1271 | + if (i < 0) | ||
1272 | + return -EINVAL; | ||
1273 | + lvc = &mt9p031_video_control[i]; | ||
1274 | + val = lvc->current_value; | ||
1275 | + | ||
1276 | + if(val < 0){ | ||
1277 | + printk(KERN_INFO "mt9p031: Exposure value read failed"); | ||
1278 | + return 1; // nothing processed | ||
1279 | + } else { | ||
1280 | + return sprintf(buf, "%d\n", val); | ||
1281 | + } | ||
1282 | +} | ||
1283 | + | ||
1284 | + | ||
1285 | +static ssize_t | ||
1286 | +mt9p031_exposure_val_store( struct device *dev, struct device_attribute *attr, const char *buf, size_t n) | ||
1287 | +{ | ||
1288 | + u32 val; | ||
1289 | + struct i2c_client *client; | ||
1290 | + struct vcontrol *lvc; | ||
1291 | + | ||
1292 | + sscanf(buf, "%d", &val); | ||
1293 | + client = sysPriv.client; | ||
1294 | + | ||
1295 | + lvc = &mt9p031_video_control[V4L2_CID_EXPOSURE]; | ||
1296 | + | ||
1297 | + if (mt9p031_set_exposure_time((u32)val, client, lvc)) { | ||
1298 | + printk(KERN_INFO "mt9p031: Exposure write failed"); | ||
1299 | + return n; // nothing processed | ||
1300 | + } else { | ||
1301 | + return n; | ||
1302 | + } | ||
1303 | +} | ||
1304 | + | ||
1305 | +static DEVICE_ATTR( exposure_val, S_IRUGO|S_IWUSR, mt9p031_exposure_val_show, mt9p031_exposure_val_store); | ||
1306 | + | ||
1307 | + | ||
1308 | +/* Global Gain access support */ | ||
1309 | +static ssize_t | ||
1310 | +mt9p031_gain_val_show( struct device *dev, struct device_attribute *attr, char *buf) | ||
1311 | +{ | ||
1312 | + u16 val; | ||
1313 | + struct vcontrol *lvc; | ||
1314 | + | ||
1315 | + int i = find_vctrl(V4L2_CID_GAIN); | ||
1316 | + if (i < 0) | ||
1317 | + return -EINVAL; | ||
1318 | + lvc = &mt9p031_video_control[i]; | ||
1319 | + val = lvc->current_value; | ||
1320 | + | ||
1321 | + if(val < 0){ | ||
1322 | + printk(KERN_INFO "mt9p031: Global Gain value read failed"); | ||
1323 | + return 1; // nothing processed | ||
1324 | + } else { | ||
1325 | + return sprintf(buf, "%d\n", val); | ||
1326 | + } | ||
1327 | +} | ||
1328 | + | ||
1329 | +static ssize_t | ||
1330 | +mt9p031_gain_val_store( struct device *dev, struct device_attribute *attr, const char *buf, size_t n) | ||
1331 | +{ | ||
1332 | + u16 val; | ||
1333 | + struct i2c_client *client; | ||
1334 | + struct vcontrol *lvc; | ||
1335 | + | ||
1336 | + sscanf(buf, "%hd", &val); | ||
1337 | + client = sysPriv.client; | ||
1338 | + | ||
1339 | + lvc = &mt9p031_video_control[V4L2_CID_GAIN]; | ||
1340 | + | ||
1341 | + if (mt9p031_set_gain(val, client, lvc)) { | ||
1342 | + printk(KERN_INFO "mt9p031: Global gain write failed"); | ||
1343 | + return n; // nothing processed | ||
1344 | + } else { | ||
1345 | + return n; | ||
1346 | + } | ||
1347 | +} | ||
1348 | + | ||
1349 | +static DEVICE_ATTR( gain_val, S_IRUGO|S_IWUSR, mt9p031_gain_val_show, mt9p031_gain_val_store); | ||
1350 | + | ||
1351 | + | ||
1352 | +static struct attribute *mt9p031_sysfs_attr[] = { | ||
1353 | + &dev_attr_basic_reg_addr.attr, | ||
1354 | + &dev_attr_basic_reg_val.attr, | ||
1355 | + &dev_attr_exposure_val.attr, | ||
1356 | + &dev_attr_gain_val.attr, | ||
1357 | +}; | ||
1358 | + | ||
1359 | +static int mt9p031_sysfs_add(struct kobject *kobj) | ||
1360 | +{ | ||
1361 | + int i = ARRAY_SIZE(mt9p031_sysfs_attr); | ||
1362 | + int rval = 0; | ||
1363 | + | ||
1364 | + do { | ||
1365 | + rval = sysfs_create_file(kobj, mt9p031_sysfs_attr[--i]); | ||
1366 | + } while((i > 0) && (rval == 0)); | ||
1367 | + return rval; | ||
1368 | +} | ||
1369 | + | ||
1370 | +static int mt9p031_sysfs_rm(struct kobject *kobj) | ||
1371 | +{ | ||
1372 | + int i = ARRAY_SIZE(mt9p031_sysfs_attr); | ||
1373 | + int rval = 0; | ||
1374 | + | ||
1375 | + do { | ||
1376 | + sysfs_remove_file(kobj, mt9p031_sysfs_attr[--i]); | ||
1377 | + } while(i > 0); | ||
1378 | + return rval; | ||
1379 | +} | ||
1380 | +#endif //MT9P031_DEBUG | ||
1381 | + | ||
1382 | +static struct v4l2_int_slave mt9p031_slave = { | ||
1383 | + .ioctls = mt9p031_ioctl_desc, | ||
1384 | + .num_ioctls = ARRAY_SIZE(mt9p031_ioctl_desc), | ||
1385 | +}; | ||
1386 | + | ||
1387 | +static int mt9p031_probe(struct i2c_client *client, | ||
1388 | + const struct i2c_device_id *did) | ||
1389 | +{ | ||
1390 | + struct mt9p031_priv *priv; | ||
1391 | + struct v4l2_int_device *v4l2_int_device; | ||
1392 | + int ret; | ||
1393 | + if (!client->dev.platform_data) { | ||
1394 | + dev_err(&client->dev, "no platform data?\n"); | ||
1395 | + return -ENODEV; | ||
1396 | + } | ||
1397 | + | ||
1398 | + priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
1399 | + if (!priv) | ||
1400 | + return -ENOMEM; | ||
1401 | + | ||
1402 | + v4l2_int_device = kzalloc(sizeof(*v4l2_int_device), GFP_KERNEL); | ||
1403 | + if (!v4l2_int_device) { | ||
1404 | + kfree(priv); | ||
1405 | + return -ENOMEM; | ||
1406 | + } | ||
1407 | + | ||
1408 | +#ifdef MT9P031_HEADBOARD | ||
1409 | + mt9p031_config_PCA9543A(client); //configure i2c level shifter on mt9p031 head-board, no need for Leopard module | ||
1410 | + mdelay(10); | ||
1411 | +#endif //MT9P031_HEADBOARD | ||
1412 | + | ||
1413 | + v4l2_int_device->module = THIS_MODULE; | ||
1414 | + strncpy(v4l2_int_device->name, "mt9p031", sizeof(v4l2_int_device->name)); | ||
1415 | + | ||
1416 | + v4l2_int_device->type = v4l2_int_type_slave; | ||
1417 | + v4l2_int_device->u.slave = &mt9p031_slave; | ||
1418 | + | ||
1419 | + v4l2_int_device->priv = priv; | ||
1420 | + | ||
1421 | + priv->v4l2_int_device = v4l2_int_device; | ||
1422 | + priv->client = client; | ||
1423 | + priv->pdata = client->dev.platform_data; | ||
1424 | + | ||
1425 | + priv->pdata->flags = MT9P031_FLAG_PCLK_RISING_EDGE; | ||
1426 | + | ||
1427 | + /* Setting Pixel Values */ | ||
1428 | + priv->pix.width = mt9p031_sizes[0].width; | ||
1429 | + priv->pix.height = mt9p031_sizes[0].height; | ||
1430 | + priv->pix.pixelformat = mt9p031_formats[0].pixelformat; | ||
1431 | + | ||
1432 | + i2c_set_clientdata(client, priv); | ||
1433 | + | ||
1434 | + sysPriv.client = priv->client; | ||
1435 | + | ||
1436 | + ret = v4l2_int_device_register(priv->v4l2_int_device); | ||
1437 | + if (ret) { | ||
1438 | + i2c_set_clientdata(client, NULL); | ||
1439 | + kfree(v4l2_int_device); | ||
1440 | + kfree(priv); | ||
1441 | + } | ||
1442 | + | ||
1443 | +#ifdef MT9P031_DEBUG | ||
1444 | + mt9p031_sysfs_add(&client->dev.kobj); | ||
1445 | +#endif //MT9P031_DEBUG | ||
1446 | + return ret; | ||
1447 | +} | ||
1448 | + | ||
1449 | +static int mt9p031_remove(struct i2c_client *client) | ||
1450 | +{ | ||
1451 | + struct mt9p031_priv *priv = i2c_get_clientdata(client); | ||
1452 | + | ||
1453 | + v4l2_int_device_unregister(priv->v4l2_int_device); | ||
1454 | + i2c_set_clientdata(client, NULL); | ||
1455 | + mt9p031_sysfs_rm(&client->dev.kobj); | ||
1456 | + | ||
1457 | + kfree(priv->v4l2_int_device); | ||
1458 | + kfree(priv); | ||
1459 | + return 0; | ||
1460 | +} | ||
1461 | + | ||
1462 | +static const struct i2c_device_id mt9p031_id[] = { | ||
1463 | + { "mt9p031", 0 }, | ||
1464 | + { } | ||
1465 | +}; | ||
1466 | +MODULE_DEVICE_TABLE(i2c, mt9p031_id); | ||
1467 | + | ||
1468 | +static struct i2c_driver mt9p031_i2c_driver = { | ||
1469 | + .driver = { | ||
1470 | + .name = "mt9p031", | ||
1471 | + }, | ||
1472 | + .probe = mt9p031_probe, | ||
1473 | + .remove = mt9p031_remove, | ||
1474 | + .id_table = mt9p031_id, | ||
1475 | +}; | ||
1476 | + | ||
1477 | +/************************************************************************ | ||
1478 | + module function | ||
1479 | +************************************************************************/ | ||
1480 | +static int __init mt9p031_module_init(void) | ||
1481 | +{ | ||
1482 | + return i2c_add_driver(&mt9p031_i2c_driver); | ||
1483 | +} | ||
1484 | + | ||
1485 | +static void __exit mt9p031_module_exit(void) | ||
1486 | +{ | ||
1487 | + i2c_del_driver(&mt9p031_i2c_driver); | ||
1488 | +} | ||
1489 | + | ||
1490 | +module_init(mt9p031_module_init); | ||
1491 | +module_exit(mt9p031_module_exit); | ||
1492 | + | ||
1493 | +MODULE_DESCRIPTION("mt9p031 sensor driver"); | ||
1494 | +MODULE_AUTHOR("Aptina"); | ||
1495 | +MODULE_LICENSE("GPL v2"); | ||
1496 | + | ||
1497 | diff --git a/include/media/mt9p031.h b/include/media/mt9p031.h | ||
1498 | new file mode 100644 | ||
1499 | index 0000000..d119589 | ||
1500 | --- /dev/null | ||
1501 | +++ b/include/media/mt9p031.h | ||
1502 | @@ -0,0 +1,30 @@ | ||
1503 | +/* mt9p031 Camera | ||
1504 | + * | ||
1505 | + * This program is free software; you can redistribute it and/or modify | ||
1506 | + * it under the terms of the GNU General Public License version 2 as | ||
1507 | + * published by the Free Software Foundation. | ||
1508 | + */ | ||
1509 | + | ||
1510 | +#ifndef __MT9P031_H__ | ||
1511 | +#define __MT9P031_H__ | ||
1512 | + | ||
1513 | +#include <media/v4l2-int-device.h> | ||
1514 | + | ||
1515 | +#define MT9P031_I2C_ADDR 0x48 //(0x90 >> 1) | ||
1516 | + | ||
1517 | +#define MT9P031_CLK_MAX (27000000) /* 27MHz */ | ||
1518 | +#define MT9P031_CLK_MIN (6000000) /* 6Mhz */ | ||
1519 | + | ||
1520 | +#define MT9P031_FLAG_PCLK_RISING_EDGE (1 << 0) | ||
1521 | +#define MT9P031_FLAG_DATAWIDTH_8 (1 << 1) /* default width is 10 */ | ||
1522 | + | ||
1523 | +struct mt9p031_platform_data { | ||
1524 | + char *master; | ||
1525 | + int (*power_set) (struct v4l2_int_device *s, enum v4l2_power on); | ||
1526 | + int (*ifparm) (struct v4l2_ifparm *p); | ||
1527 | + int (*priv_data_set) (void *); | ||
1528 | + u32 (*set_xclk) (struct v4l2_int_device *s, u32 xclkfreq); | ||
1529 | + u32 flags; | ||
1530 | +}; | ||
1531 | + | ||
1532 | +#endif /* __MT9P031_H__ */ | ||
1533 | diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h | ||
1534 | index 6cc107d..7599bf1 100644 | ||
1535 | --- a/include/media/v4l2-chip-ident.h | ||
1536 | +++ b/include/media/v4l2-chip-ident.h | ||
1537 | @@ -271,6 +271,7 @@ enum { | ||
1538 | V4L2_IDENT_MT9T112 = 45022, | ||
1539 | V4L2_IDENT_MT9V111 = 45031, | ||
1540 | V4L2_IDENT_MT9V112 = 45032, | ||
1541 | + V4L2_IDENT_MT9P031 = 6145, | ||
1542 | |||
1543 | /* HV7131R CMOS sensor: just ident 46000 */ | ||
1544 | V4L2_IDENT_HV7131R = 46000, | ||
1545 | -- | ||
1546 | 1.6.6.1 | ||
1547 | |||