Revert "media: camera config changes"
[linux-2.6.git] / drivers / media / video / tegra / ov5640.c
1 /*
2  * ov5640.c - ov5640 sensor driver
3  *
4  * Copyright (c) 2011 - 2012, NVIDIA, All Rights Reserved.
5  *
6  * Contributors:
7  *      Abhinav Sinha <absinha@nvidia.com>
8  *
9  * Leverage soc380.c
10  *
11  * This file is licensed under the terms of the GNU General Public License
12  * version 2. This program is licensed "as is" without any warranty of any
13  * kind, whether express or implied.
14  */
15
16 /**
17  * SetMode Sequence for 640x480. Phase 0. Sensor Dependent.
18  * This sequence should put sensor in streaming mode for 640x480
19  * This is usually given by the FAE or the sensor vendor.
20  */
21
22 #include <linux/delay.h>
23 #include <linux/fs.h>
24 #include <linux/i2c.h>
25 #include <linux/miscdevice.h>
26 #include <linux/slab.h>
27 #include <linux/uaccess.h>
28 #include <media/ov5640.h>
29
30 #include "ov5640_tables.h"
31
32 /* Focuser single step & full scale transition time truth table
33  * in the format of:
34  *    index     mode            single step transition  full scale transition
35  *      0       0                       0                       0
36  *      1       1                       50uS                    51.2mS
37  *      2       1                       100uS                   102.3mS
38  *      3       1                       200uS                   204.6mS
39  *      4       1                       400uS                   409.2mS
40  *      5       1                       800uS                   818.4mS
41  *      6       1                       1600uS                  1637.0mS
42  *      7       1                       3200uS                  3274.0mS
43  *      8       0                       0                       0
44  *      9       2                       50uS                    1.1mS
45  *      A       2                       100uS                   2.2mS
46  *      B       2                       200uS                   4.4mS
47  *      C       2                       400uS                   8.8mS
48  *      D       2                       800uS                   17.6mS
49  *      E       2                       1600uS                  35.2mS
50  *      F       2                       3200uS                  70.4mS
51  */
52
53 /* pick up the mode index setting and its settle time from the above table */
54 #define OV5640_VCM_DACMODE 0x3602
55 #define OV5640_TRANSITION_MODE 0x0B
56 #define SETTLETIME_MS 5
57
58 #define POS_LOW (0)
59 #define POS_HIGH (1023)
60 #define FPOS_COUNT 1024
61 #define FOCAL_LENGTH (10.0f)
62 #define FNUMBER (2.8f)
63
64 #define SIZEOF_I2C_TRANSBUF 64
65
66 struct ov5640_info {
67         int mode;
68         struct miscdevice miscdev_info;
69         struct i2c_client *i2c_client;
70         struct ov5640_platform_data *pdata;
71         struct ov5640_config focuser;
72         int af_fw_loaded;
73         struct kobject *kobj;
74         struct device *dev;
75         u8 i2c_trans_buf[SIZEOF_I2C_TRANSBUF];
76 };
77
78 static int ov5640_read_reg(struct i2c_client *client, u16 addr, u8 *val)
79 {
80         int err;
81         struct i2c_msg msg[2];
82         unsigned char data[3];
83
84         if (!client->adapter)
85                 return -ENODEV;
86
87         msg[0].addr = client->addr;
88         msg[0].flags = 0;
89         msg[0].len = 2;
90         msg[0].buf = data;
91
92         /* high byte goes out first */
93         data[0] = (u8) (addr >> 8);
94         data[1] = (u8) (addr & 0xff);
95
96         msg[1].addr = client->addr;
97         msg[1].flags = I2C_M_RD;
98         msg[1].len = 1;
99         msg[1].buf = data + 2;
100
101         err = i2c_transfer(client->adapter, msg, 2);
102
103         if (err != 2)
104                 return -EINVAL;
105
106         *val = data[2];
107
108         return 0;
109 }
110
111 #ifdef KERNEL_WARNING
112 static int ov5640_write_reg(struct i2c_client *client, u8 addr, u8 value)
113 {
114         int count;
115         struct i2c_msg msg[1];
116         unsigned char data[4];
117
118         if (!client->adapter)
119                 return -ENODEV;
120
121         data[0] = addr;
122         data[1] = (u8) (addr & 0xff);
123         data[2] = value;
124
125         msg[0].addr = client->addr;
126         msg[0].flags = 0;
127         msg[0].len = 3;
128         msg[0].buf = data;
129
130         count = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
131         if (count == ARRAY_SIZE(msg))
132                 return 0;
133         dev_err(&client->dev,
134                 "ov5840: i2c transfer failed, addr: %x, value: %02x\n",
135                addr, (u32)value);
136         return -EIO;
137 }
138 #endif
139
140 static int ov5640_write_bulk_reg(struct i2c_client *client, u8 *data, int len)
141 {
142         int err;
143         struct i2c_msg msg;
144
145         if (!client->adapter)
146                 return -ENODEV;
147
148         msg.addr = client->addr;
149         msg.flags = 0;
150         msg.len = len;
151         msg.buf = data;
152
153         err = i2c_transfer(client->adapter, &msg, 1);
154         if (err == 1)
155                 return 0;
156
157         dev_err(&client->dev, "ov5640: i2c transfer failed at %x\n",
158                 (int)data[0] << 8 | data[1]);
159
160         return err;
161 }
162
163 static int ov5640_write_table(struct ov5640_info *info,
164                               struct ov5640_reg table[],
165                               struct ov5640_reg override_list[],
166                               int num_override_regs)
167 {
168         int err;
169         struct ov5640_reg *next, *n_next;
170         u8 *b_ptr = info->i2c_trans_buf;
171         unsigned int buf_filled = 0;
172         int i;
173         u16 val;
174
175         for (next = table; next->addr != OV5640_TABLE_END; next++) {
176                 if (next->addr == OV5640_TABLE_WAIT_MS) {
177                         msleep(next->val);
178                         continue;
179                 }
180
181                 val = next->val;
182
183                 /* When an override list is passed in, replace the reg */
184                 /* value to write if the reg is in the list            */
185                 if (override_list) {
186                         for (i = 0; i < num_override_regs; i++) {
187                                 if (next->addr == override_list[i].addr) {
188                                         val = override_list[i].val;
189                                         break;
190                                 }
191                         }
192                 }
193
194                 if (!buf_filled) {
195                         b_ptr = info->i2c_trans_buf;
196                         *b_ptr++ = next->addr >> 8;
197                         *b_ptr++ = next->addr & 0xff;
198                         buf_filled = 2;
199                 }
200                 *b_ptr++ = val;
201                 buf_filled++;
202
203                 n_next = next + 1;
204                 if (n_next->addr != OV5640_TABLE_END &&
205                         n_next->addr != OV5640_TABLE_WAIT_MS &&
206                         buf_filled < SIZEOF_I2C_TRANSBUF &&
207                         n_next->addr == next->addr + 1) {
208                         continue;
209                 }
210
211                 err = ov5640_write_bulk_reg(info->i2c_client,
212                         info->i2c_trans_buf, buf_filled);
213                 if (err)
214                         return err;
215
216                 buf_filled = 0;
217         }
218         return 0;
219 }
220
221 static int ov5640_set_mode(struct ov5640_info *info, struct ov5640_mode *mode)
222 {
223         int sensor_mode;
224         int err;
225
226         dev_info(info->dev, "%s: xres %u yres %u\n",
227                         __func__, mode->xres, mode->yres);
228         if (!info->af_fw_loaded) {
229                 err = ov5640_write_table(info, tbl_af_firmware, NULL, 0);
230                 if (err)
231                         return err;
232                 info->af_fw_loaded = 1;
233         }
234
235         if (mode->xres == 2592 && mode->yres == 1944)
236                 sensor_mode = OV5640_MODE_2592x1944;
237         else if (mode->xres == 1920 && mode->yres == 1080)
238                 sensor_mode = OV5640_MODE_1920x1080;
239         else if (mode->xres == 1296 && mode->yres == 964)
240                 sensor_mode = OV5640_MODE_1296x972;
241         else {
242                 dev_info(info->dev, "%s: invalid resolution: %d %d\n",
243                                 __func__, mode->xres, mode->yres);
244                 return -EINVAL;
245         }
246
247         err = ov5640_write_table(info, mode_table[sensor_mode],
248                 NULL, 0);
249         if (err)
250                 return err;
251
252         info->mode = sensor_mode;
253         return 0;
254 }
255
256 static int ov5640_set_af_mode(struct ov5640_info *info, u8 mode)
257 {
258         dev_info(info->dev, "%s: mode %d\n", __func__, mode);
259         if (mode == OV5640_AF_INIFINITY)
260                 return ov5640_write_table(info, tbl_release_focus, NULL, 0);
261
262         if (mode == OV5640_AF_TRIGGER)
263                 return ov5640_write_table(info, tbl_single_focus, NULL, 0);
264
265         return -EINVAL;
266 }
267
268 static int ov5640_get_af_status(struct ov5640_info *info, u8 *val)
269 {
270         int err;
271
272         err = ov5640_read_reg(info->i2c_client, 0x3023, val);
273         if (err)
274                 return -EINVAL;
275
276         dev_info(info->dev, "%s: value %02x\n", __func__, (u32)val);
277         return 0;
278 }
279
280 static int ov5640_set_position(struct ov5640_info *info, u32 position)
281 {
282         u8 data[4];
283
284         if (position < info->focuser.pos_low ||
285             position > info->focuser.pos_high)
286                 return -EINVAL;
287
288         data[0] = (OV5640_VCM_DACMODE >> 8) & 0xff;
289         data[1] = OV5640_VCM_DACMODE & 0xff;
290         data[2] = ((position & 0xf) << 4) | OV5640_TRANSITION_MODE;
291         data[3] = (position * 0x3f0) >> 4;
292         return ov5640_write_bulk_reg(info->i2c_client, data, 4);
293 }
294
295 static int ov5640_set_power(struct ov5640_info *info, u32 level)
296 {
297         switch (level) {
298         case OV5640_POWER_LEVEL_OFF:
299         case OV5640_POWER_LEVEL_SUS:
300                 if (info->pdata && info->pdata->power_off)
301                         info->pdata->power_off();
302                 info->af_fw_loaded = 0;
303                 info->mode = 0;
304                 break;
305         case OV5640_POWER_LEVEL_ON:
306                 if (info->pdata && info->pdata->power_on)
307                         info->pdata->power_on();
308                 break;
309         default:
310                 dev_err(info->dev, "unknown power level %d.\n", level);
311                 return -EINVAL;
312         }
313
314         return 0;
315 }
316
317 static long ov5640_ioctl(struct file *file,
318                          unsigned int cmd, unsigned long arg)
319 {
320         struct ov5640_info *info = file->private_data;
321
322         switch (cmd) {
323         case OV5640_IOCTL_SET_SENSOR_MODE:
324         {
325                 struct ov5640_mode mode;
326                 if (copy_from_user(&mode,
327                                    (const void __user *)arg,
328                                    sizeof(struct ov5640_mode))) {
329                         return -EFAULT;
330                 }
331
332                 return ov5640_set_mode(info, &mode);
333         }
334         case OV5640_IOCTL_GET_CONFIG:
335         {
336                 if (copy_to_user((void __user *) arg,
337                                  &info->focuser,
338                                  sizeof(info->focuser))) {
339                         dev_err(info->dev, "%s: 0x%x\n", __func__, __LINE__);
340                         return -EFAULT;
341                 }
342
343                 break;
344         }
345         case OV5640_IOCTL_GET_AF_STATUS:
346         {
347                 int err;
348                 u8 val;
349
350                 if (!info->af_fw_loaded) {
351                         dev_err(info->dev, "OV5640 AF fw not loaded!\n");
352                         break;
353                 }
354
355                 err = ov5640_get_af_status(info, &val);
356                 if (err)
357                         return err;
358
359                 if (copy_to_user((void __user *) arg,
360                                  &val, sizeof(val))) {
361                         dev_err(info->dev, "%s: 0x%x\n", __func__, __LINE__);
362                         return -EFAULT;
363                 }
364                 break;
365         }
366         case OV5640_IOCTL_SET_AF_MODE:
367                 if (!info->af_fw_loaded) {
368                         dev_err(info->dev, "OV5640 AF fw not loaded!\n");
369                         break;
370                 }
371                 return ov5640_set_af_mode(info, (u8)arg);
372         case OV5640_IOCTL_POWER_LEVEL:
373                 return ov5640_set_power(info, (u32)arg);
374         case OV5640_IOCTL_SET_FPOSITION:
375                 return ov5640_set_position(info, (u32)arg);
376         case OV5640_IOCTL_GET_SENSOR_STATUS:
377         {
378                 u8 status = 0;
379                 if (copy_to_user((void __user *)arg, &status,
380                                  1)) {
381                         dev_info(info->dev, "%s %d\n", __func__, __LINE__);
382                         return -EFAULT;
383                 }
384                 return 0;
385         }
386         default:
387                 return -EINVAL;
388         }
389         return 0;
390 }
391
392 static int ov5640_open(struct inode *inode, struct file *file)
393 {
394         struct miscdevice *miscdev = file->private_data;
395         struct ov5640_info *info;
396
397         pr_info("%s\n", __func__);
398         if (!miscdev) {
399                 pr_err("miscdev == NULL\n");
400                 return -1;
401         }
402         info = container_of(miscdev, struct ov5640_info, miscdev_info);
403         file->private_data = info;
404
405         return 0;
406 }
407
408 int ov5640_release(struct inode *inode, struct file *file)
409 {
410         file->private_data = NULL;
411         pr_info("%s\n", __func__);
412         return 0;
413 }
414
415 static const struct file_operations ov5640_fileops = {
416         .owner = THIS_MODULE,
417         .open = ov5640_open,
418         .unlocked_ioctl = ov5640_ioctl,
419         .release = ov5640_release,
420 };
421
422 static struct miscdevice ov5640_device = {
423         .minor = MISC_DYNAMIC_MINOR,
424         .name = "ov5640",
425         .fops = &ov5640_fileops,
426 };
427
428 static int ov5640_probe(struct i2c_client *client,
429                         const struct i2c_device_id *id)
430 {
431         struct ov5640_info *info;
432         int err;
433
434         dev_info(&client->dev, "ov5640: probing sensor.\n");
435
436         info = devm_kzalloc(&client->dev,
437                         sizeof(struct ov5640_info), GFP_KERNEL);
438         if (!info) {
439                 dev_err(&client->dev, "ov5640: Unable to allocate memory!\n");
440                 return -ENOMEM;
441         }
442
443         memcpy(&(info->miscdev_info),
444                 &ov5640_device,
445                 sizeof(struct miscdevice));
446
447         err = misc_register(&(info->miscdev_info));
448         if (err) {
449                 dev_err(&client->dev,
450                         "ov5640: Unable to register misc device!\n");
451                 devm_kfree(&client->dev, info);
452                 return err;
453         }
454
455         info->dev = &client->dev;
456         info->pdata = client->dev.platform_data;
457         info->i2c_client = client;
458         info->focuser.settle_time = SETTLETIME_MS;
459         info->focuser.focal_length = FOCAL_LENGTH;
460         info->focuser.fnumber = FNUMBER;
461         info->focuser.pos_low = POS_LOW;
462         info->focuser.pos_high = POS_HIGH;
463
464         i2c_set_clientdata(client, info);
465         return 0;
466 }
467
468 static int ov5640_remove(struct i2c_client *client)
469 {
470         struct ov5640_info *info;
471         info = i2c_get_clientdata(client);
472         misc_deregister(&ov5640_device);
473         return 0;
474 }
475
476 static const struct i2c_device_id ov5640_id[] = {
477         { "ov5640", 0 },
478         { },
479 };
480
481 MODULE_DEVICE_TABLE(i2c, ov5640_id);
482
483 static struct i2c_driver ov5640_i2c_driver = {
484         .driver = {
485                 .name = "ov5640",
486                 .owner = THIS_MODULE,
487         },
488         .probe = ov5640_probe,
489         .remove = ov5640_remove,
490         .id_table = ov5640_id,
491 };
492
493 module_i2c_driver(ov5640_i2c_driver);