Revert "media: camera config changes"
[linux-2.6.git] / drivers / media / video / tegra / soc380.c
1 /*
2  * soc380.c - soc380 sensor driver
3  *
4  * Copyright (c) 2011, NVIDIA, All Rights Reserved.
5  *
6  * Contributors:
7  *      Abhinav Sinha <absinha@nvidia.com>
8  *
9  * Leverage OV2710.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/soc380.h>
29
30 struct soc380_reg {
31         u16 addr;
32         u16 val;
33 };
34
35 struct soc380_info {
36         int mode;
37         struct i2c_client *i2c_client;
38         struct soc380_platform_data *pdata;
39 };
40
41 #define SOC380_TABLE_WAIT_MS 0
42 #define SOC380_TABLE_END 1
43 #define SOC380_MAX_RETRIES 3
44
45 static struct soc380_reg mode_640x480[] = {
46         {0x001A, 0x0011},
47
48         {SOC380_TABLE_WAIT_MS, 1},
49
50         {0x001A, 0x0010},
51
52         {SOC380_TABLE_WAIT_MS, 1},
53
54         {0x0018, 0x4028},
55         {0x001A, 0x0210},
56         {0x0010, 0x021c},
57         {0x0012, 0x0000},
58         {0x0014, 0x244B},
59
60         {SOC380_TABLE_WAIT_MS, 10},
61
62         {0x0014, 0x304B},
63
64         {SOC380_TABLE_WAIT_MS, 50},
65
66         {0x0014, 0xB04A},
67
68         {0x098C, 0x2703},
69         {0x0990, 0x0280},
70         {0x098C, 0x2705},
71         {0x0990, 0x01E0},
72         {0x098C, 0x2707},
73         {0x0990, 0x0280},
74         {0x098C, 0x2709},
75         {0x0990, 0x01E0},
76         {0x098C, 0x270D},
77         {0x0990, 0x0000},
78         {0x098C, 0x270F},
79         {0x0990, 0x0000},
80         {0x098C, 0x2711},
81         {0x0990, 0x01E7},
82         {0x098C, 0x2713},
83         {0x0990, 0x0287},
84         {0x098C, 0x2715},
85         {0x0990, 0x0001},
86         {0x098C, 0x2717},
87         {0x0990, 0x0026},
88         {0x098C, 0x2719},
89         {0x0990, 0x001A},
90         {0x098C, 0x271B},
91         {0x0990, 0x006B},
92         {0x098C, 0x271D},
93         {0x0990, 0x006B},
94         {0x098C, 0x271F},
95         {0x0990, 0x022A},
96         {0x098C, 0x2721},
97         {0x0990, 0x034A},
98         {0x098C, 0x2723},
99         {0x0990, 0x0000},
100         {0x098C, 0x2725},
101         {0x0990, 0x0000},
102         {0x098C, 0x2727},
103         {0x0990, 0x01E7},
104         {0x098C, 0x2729},
105         {0x0990, 0x0287},
106         {0x098C, 0x272B},
107         {0x0990, 0x0001},
108         {0x098C, 0x272D},
109         {0x0990, 0x0026},
110         {0x098C, 0x272F},
111         {0x0990, 0x001A},
112         {0x098C, 0x2731},
113         {0x0990, 0x006B},
114         {0x098C, 0x2733},
115         {0x0990, 0x006B},
116         {0x098C, 0x2735},
117         {0x0990, 0x022A},
118         {0x098C, 0x2737},
119         {0x0990, 0x034A},
120         {0x098C, 0x2739},
121         {0x0990, 0x0000},
122         {0x098C, 0x273B},
123         {0x0990, 0x027F},
124         {0x098C, 0x273D},
125         {0x0990, 0x0000},
126         {0x098C, 0x273F},
127         {0x0990, 0x01DF},
128         {0x098C, 0x2747},
129         {0x0990, 0x0000},
130         {0x098C, 0x2749},
131         {0x0990, 0x027F},
132         {0x098C, 0x274B},
133         {0x0990, 0x0000},
134         {0x098C, 0x274D},
135         {0x0990, 0x01DF},
136         {0x098C, 0x222D},
137         {0x0990, 0x008B},
138         {0x098C, 0xA408},
139         {0x0990, 0x0021},
140         {0x098C, 0xA409},
141         {0x0990, 0x0023},
142         {0x098C, 0xA40A},
143         {0x0990, 0x0028},
144         {0x098C, 0xA40B},
145         {0x0990, 0x002A},
146         {0x098C, 0x2411},
147         {0x0990, 0x008B},
148         {0x098C, 0x2413},
149         {0x0990, 0x00A6},
150         {0x098C, 0x2415},
151         {0x0990, 0x008B},
152         {0x098C, 0x2417},
153         {0x0990, 0x00A6},
154         {0x098C, 0xA404},
155         {0x0990, 0x0010},
156         {0x098C, 0xA40D},
157         {0x0990, 0x0002},
158         {0x098C, 0xA40E},
159         {0x0990, 0x0003},
160         {0x098C, 0xA410},
161         {0x0990, 0x000A},
162         {0x098C, 0xA215},
163         {0x0990, 0x0003},
164         {0x098C, 0xA20C},
165         {0x0990, 0x0003},
166
167         {0x098C, 0xA103},
168         {0x0990, 0x0006},
169         {SOC380_TABLE_WAIT_MS, 100},
170
171         {0x098C, 0xA103},
172         {0x0990, 0x0005},
173         {SOC380_TABLE_WAIT_MS, 50},
174
175         {SOC380_TABLE_END, 0x0000}
176 };
177
178 enum {
179         SOC380_MODE_680x480,
180 };
181
182 static struct soc380_reg *mode_table[] = {
183         [SOC380_MODE_680x480] = mode_640x480,
184 };
185
186 static int soc380_read_reg(struct i2c_client *client, u16 addr, u16 *val)
187 {
188         int err;
189         struct i2c_msg msg[2];
190         unsigned char data[4];
191
192         if (!client->adapter)
193                 return -ENODEV;
194
195         msg[0].addr = client->addr;
196         msg[0].flags = 0;
197         msg[0].len = 2;
198         msg[0].buf = data;
199
200         /* high byte goes out first */
201         data[0] = (u8) (addr >> 8);
202         data[1] = (u8) (addr & 0xff);
203
204         msg[1].addr = client->addr;
205         msg[1].flags = I2C_M_RD;
206         msg[1].len = 2;
207         msg[1].buf = data + 2;
208
209         err = i2c_transfer(client->adapter, msg, 2);
210
211         if (err != 2)
212                 return -EINVAL;
213
214         *val = data[2] << 8 | data[3];
215
216         return 0;
217 }
218
219 static int soc380_write_reg(struct i2c_client *client, u16 addr, u16 val)
220 {
221         int err;
222         struct i2c_msg msg;
223         unsigned char data[4];
224         int retry = 0;
225
226         if (!client->adapter)
227                 return -ENODEV;
228
229         data[0] = (u8) (addr >> 8);
230         data[1] = (u8) (addr & 0xff);
231         data[2] = (u8) (val >> 8);
232         data[3] = (u8) (val & 0xff);
233
234         msg.addr = client->addr;
235         msg.flags = 0;
236         msg.len = 4;
237         msg.buf = data;
238
239         do {
240                 err = i2c_transfer(client->adapter, &msg, 1);
241                 if (err == 1)
242                         return 0;
243                 retry++;
244                 pr_err("soc380: i2c transfer failed, retrying %x %x\n",
245                        addr, val);
246                 msleep(3);
247         } while (retry <= SOC380_MAX_RETRIES);
248
249         return err;
250 }
251
252 static int soc380_write_table(struct i2c_client *client,
253                               const struct soc380_reg table[],
254                               const struct soc380_reg override_list[],
255                               int num_override_regs)
256 {
257         int err;
258         const struct soc380_reg *next;
259         int i;
260         u16 val;
261
262         for (next = table; next->addr != SOC380_TABLE_END; next++) {
263                 if (next->addr == SOC380_TABLE_WAIT_MS) {
264                         msleep(next->val);
265                         continue;
266                 }
267
268                 val = next->val;
269
270                 /* When an override list is passed in, replace the reg */
271                 /* value to write if the reg is in the list            */
272                 if (override_list) {
273                         for (i = 0; i < num_override_regs; i++) {
274                                 if (next->addr == override_list[i].addr) {
275                                         val = override_list[i].val;
276                                         break;
277                                 }
278                         }
279                 }
280
281                 err = soc380_write_reg(client, next->addr, val);
282                 if (err)
283                         return err;
284         }
285         return 0;
286 }
287
288 static int soc380_set_mode(struct soc380_info *info, struct soc380_mode *mode)
289 {
290         int sensor_mode;
291         int err;
292
293         pr_info("%s: xres %u yres %u\n", __func__, mode->xres, mode->yres);
294         if (mode->xres == 640 && mode->yres == 480)
295                 sensor_mode = SOC380_MODE_680x480;
296         else {
297                 pr_err("%s: invalid resolution supplied to set mode %d %d\n",
298                        __func__, mode->xres, mode->yres);
299                 return -EINVAL;
300         }
301
302         err = soc380_write_table(info->i2c_client, mode_table[sensor_mode],
303                 NULL, 0);
304         if (err)
305                 return err;
306
307         info->mode = sensor_mode;
308         return 0;
309 }
310
311 static int soc380_get_status(struct soc380_info *info,
312                 struct soc380_status *dev_status)
313 {
314         int err;
315
316         err = soc380_write_reg(info->i2c_client, 0x98C, dev_status->data);
317         if (err)
318                 return err;
319
320         err = soc380_read_reg(info->i2c_client, 0x0990,
321                 (u16 *) &dev_status->status);
322         if (err)
323                 return err;
324
325         return err;
326 }
327
328 static long soc380_ioctl(struct file *file,
329                          unsigned int cmd, unsigned long arg)
330 {
331         int err;
332         struct soc380_info *info = file->private_data;
333
334         switch (cmd) {
335         case SOC380_IOCTL_SET_MODE:
336         {
337                 struct soc380_mode mode;
338                 if (copy_from_user(&mode,
339                                    (const void __user *)arg,
340                                    sizeof(struct soc380_mode))) {
341                         return -EFAULT;
342                 }
343
344                 return soc380_set_mode(info, &mode);
345         }
346         case SOC380_IOCTL_GET_STATUS:
347         {
348                 struct soc380_status dev_status;
349                 if (copy_from_user(&dev_status,
350                                    (const void __user *)arg,
351                                    sizeof(struct soc380_status))) {
352                         return -EFAULT;
353                 }
354
355                 err = soc380_get_status(info, &dev_status);
356                 if (err)
357                         return err;
358                 if (copy_to_user((void __user *)arg, &dev_status,
359                                  sizeof(struct soc380_status))) {
360                         return -EFAULT;
361                 }
362                 return 0;
363         }
364         default:
365                 return -EINVAL;
366         }
367         return 0;
368 }
369
370 static struct soc380_info *info;
371
372 static int soc380_open(struct inode *inode, struct file *file)
373 {
374         struct soc380_status dev_status;
375         int err;
376
377         file->private_data = info;
378         if (info->pdata && info->pdata->power_on)
379                 info->pdata->power_on();
380
381         dev_status.data = 0;
382         dev_status.status = 0;
383         err = soc380_get_status(info, &dev_status);
384         return err;
385 }
386
387 int soc380_release(struct inode *inode, struct file *file)
388 {
389         if (info->pdata && info->pdata->power_off)
390                 info->pdata->power_off();
391         file->private_data = NULL;
392         return 0;
393 }
394
395 static const struct file_operations soc380_fileops = {
396         .owner = THIS_MODULE,
397         .open = soc380_open,
398         .unlocked_ioctl = soc380_ioctl,
399         .release = soc380_release,
400 };
401
402 static struct miscdevice soc380_device = {
403         .minor = MISC_DYNAMIC_MINOR,
404         .name = "soc380",
405         .fops = &soc380_fileops,
406 };
407
408 static int soc380_probe(struct i2c_client *client,
409                         const struct i2c_device_id *id)
410 {
411         int err;
412
413         pr_info("soc380: probing sensor.\n");
414
415         info = kzalloc(sizeof(struct soc380_info), GFP_KERNEL);
416         if (!info) {
417                 pr_err("soc380: Unable to allocate memory!\n");
418                 return -ENOMEM;
419         }
420
421         err = misc_register(&soc380_device);
422         if (err) {
423                 pr_err("soc380: Unable to register misc device!\n");
424                 kfree(info);
425                 return err;
426         }
427
428         info->pdata = client->dev.platform_data;
429         info->i2c_client = client;
430
431         i2c_set_clientdata(client, info);
432         return 0;
433 }
434
435 static int soc380_remove(struct i2c_client *client)
436 {
437         struct soc380_info *info;
438         info = i2c_get_clientdata(client);
439         misc_deregister(&soc380_device);
440         kfree(info);
441         return 0;
442 }
443
444 static const struct i2c_device_id soc380_id[] = {
445         { "soc380", 0 },
446         { },
447 };
448
449 MODULE_DEVICE_TABLE(i2c, soc380_id);
450
451 static struct i2c_driver soc380_i2c_driver = {
452         .driver = {
453                 .name = "soc380",
454                 .owner = THIS_MODULE,
455         },
456         .probe = soc380_probe,
457         .remove = soc380_remove,
458         .id_table = soc380_id,
459 };
460
461 static int __init soc380_init(void)
462 {
463         pr_info("soc380 sensor driver loading\n");
464         return i2c_add_driver(&soc380_i2c_driver);
465 }
466
467 static void __exit soc380_exit(void)
468 {
469         i2c_del_driver(&soc380_i2c_driver);
470 }
471
472 module_init(soc380_init);
473 module_exit(soc380_exit);
474 MODULE_LICENSE("GPL v2");