upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / media / video / m5mols / m5mols_capture.c
1 /*
2  * The Capture code for Fujitsu M-5MOLS ISP
3  *
4  * Copyright (C) 2011 Samsung Electronics Co., Ltd.
5  * Author: HeungJun Kim, riverful.kim@samsung.com
6  *
7  * Copyright (C) 2009 Samsung Electronics Co., Ltd.
8  * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  */
15
16 #include <linux/i2c.h>
17 #include <linux/slab.h>
18 #include <linux/irq.h>
19 #include <linux/interrupt.h>
20 #include <linux/delay.h>
21 #include <linux/version.h>
22 #include <linux/gpio.h>
23 #include <linux/regulator/consumer.h>
24 #include <linux/videodev2.h>
25 #include <linux/version.h>
26 #include <media/v4l2-ctrls.h>
27 #include <media/v4l2-device.h>
28 #include <media/v4l2-subdev.h>
29 #include <media/m5mols.h>
30
31 #include "m5mols.h"
32 #include "m5mols_reg.h"
33
34 static int m5mols_capture_handler_error(struct m5mols_info *info,
35                                         int timeout)
36 {
37         int ret;
38
39         /* Disable all interrupt & clear desired interrupt */
40         ret = i2c_w8_system(&info->sd, CAT0_INT_ENABLE,
41                         info->interrupt & ~(REG_INT_CAPTURE));
42         if (ret)
43                 return -EPERM;
44
45         /* If all timeout exhausted, return error. */
46         if (!timeout)
47                 return -ETIMEDOUT;
48
49         /* Clear capture */
50         if (!ret)
51                 info->capture = false;
52
53         return 0;
54 }
55
56 /* m5mols_capture_info() - Gather captured image informations. For now,
57  * it gathers only EXIF information and file size. */
58 static int m5mols_capture_info(struct m5mols_info *info, bool msgon)
59 {
60         struct v4l2_subdev *sd = &info->sd;
61         struct m5mols_exif *exif = &info->cap.exif;
62         int denominator, numerator;
63         int ret;
64
65         ret = i2c_r32_exif(sd, CAT7_INFO_EXPTIME_NU, &numerator);
66         if (!ret)
67                 ret = i2c_r32_exif(sd, CAT7_INFO_EXPTIME_DE, &denominator);
68         if (!ret)
69                 exif->exposure_time = (u32)(numerator / denominator);
70         if (ret)
71                 return ret;
72
73         ret = i2c_r32_exif(sd, CAT7_INFO_TV_NU, &numerator);
74         if (!ret)
75                 ret = i2c_r32_exif(sd, CAT7_INFO_TV_DE, &denominator);
76         if (!ret)
77                 exif->shutter_speed = (u32)(numerator / denominator);
78         if (ret)
79                 return ret;
80
81         ret = i2c_r32_exif(sd, CAT7_INFO_AV_NU, &numerator);
82         if (!ret)
83                 ret = i2c_r32_exif(sd, CAT7_INFO_AV_DE, &denominator);
84         if (!ret)
85                 exif->aperture = (u32)(numerator / denominator);
86         if (ret)
87                 return ret;
88
89         ret = i2c_r32_exif(sd, CAT7_INFO_BV_NU, &numerator);
90         if (!ret)
91                 ret = i2c_r32_exif(sd, CAT7_INFO_BV_DE, &denominator);
92         if (!ret)
93                 exif->brightness = (u32)(numerator / denominator);
94         if (ret)
95                 return ret;
96
97         ret = i2c_r32_exif(sd, CAT7_INFO_EBV_NU, &numerator);
98         if (!ret)
99                 ret = i2c_r32_exif(sd, CAT7_INFO_EBV_DE, &denominator);
100         if (!ret)
101                 exif->exposure_bias = (u32)(numerator / denominator);
102         if (ret)
103                 return ret;
104
105         ret = i2c_r16_exif(sd, CAT7_INFO_ISO, (u32 *)&exif->iso_speed);
106         if (!ret)
107                 ret = i2c_r16_exif(sd, CAT7_INFO_FLASH, (u32 *)&exif->flash);
108         if (!ret)
109                 ret = i2c_r16_exif(sd, CAT7_INFO_SDR, (u32 *)&exif->sdr);
110         if (!ret)
111                 ret = i2c_r16_exif(sd, CAT7_INFO_QVAL, (u32 *)&exif->qval);
112         if (ret)
113                 return ret;
114
115         if (!ret)
116                 ret = i2c_r32_capt_ctrl(sd, CATC_CAP_IMAGE_SIZE,
117                                 &info->cap.main);
118         if (!ret)
119                 ret = i2c_r32_capt_ctrl(sd, CATC_CAP_THUMB_SIZE,
120                                 &info->cap.thumb);
121         if (ret)
122                 return ret;
123
124         info->cap.total = info->cap.main + info->cap.thumb;
125
126         if (msgon) {
127                 struct i2c_client *client = v4l2_get_subdevdata(sd);
128                 struct device *cdev = &client->dev;
129
130                 dev_info(cdev, "capture: total size\t%d\n", info->cap.total);
131                 dev_info(cdev, "capture: main size\t%d\n", info->cap.main);
132                 dev_info(cdev, "capture: thumb size\t%d\n", info->cap.thumb);
133                 dev_info(cdev, "capture: exposure_time\t%d\n",
134                                 exif->exposure_time);
135                 dev_info(cdev, "capture: shutter_speed\t%d\n",
136                                 exif->shutter_speed);
137                 dev_info(cdev, "capture: aperture\t%d\n", exif->aperture);
138                 dev_info(cdev, "capture: brightness\t%d\n", exif->brightness);
139                 dev_info(cdev, "capture: exposure_bias\t%d\n",
140                                 exif->exposure_bias);
141                 dev_info(cdev, "capture: iso_speed\t%d\n", exif->iso_speed);
142                 dev_info(cdev, "capture: flash\t%d\n", exif->flash);
143                 dev_info(cdev, "capture: sdr\t%d\n", exif->sdr);
144                 dev_info(cdev, "capture: qval\t%d\n", exif->qval);
145         }
146
147         return ret;
148 }
149
150 int m5mols_start_capture(struct m5mols_info *info)
151 {
152         struct v4l2_subdev *sd = &info->sd;
153         u32 resolution = info->resolution;
154         int timeout;
155         int ret;
156
157         /*
158          * Preparing capture. Setting control & interrupt before entering
159          * capture mode
160          *
161          * 1) change to MONITOR mode for operating control & interrupt
162          * 2) set controls (considering v4l2_control value & lock 3A)
163          * 3) set interrupt
164          * 4) change to CAPTURE mode
165          */
166         ret = m5mols_change_mode(info, REG_MODE_MONITOR);
167         if (!ret)
168                 ret = m5mols_sync_control(info);
169         if (!ret)
170                 ret = m5mols_lock_3a(info, true);
171         if (!ret)
172                 ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE);
173         if (!ret)
174                 ret = m5mols_change_mode(info, REG_MODE_CAPTURE);
175         if (!ret)
176                 /* Wait for capture interrupt, after changing capture mode */
177                 timeout = wait_event_interruptible_timeout(info->wait_capture,
178                                 is_captured(info), msecs_to_jiffies(2000));
179         if (!ret && is_captured(info))
180                 ret = m5mols_capture_handler_error(info, timeout);
181         if (!ret)
182                 ret = m5mols_lock_3a(info, false);
183         if (ret)
184                 return ret;
185
186         /*
187          * Starting capture. Setting capture frame count and resolution and
188          * the format(available format: JPEG, Bayer RAW, YUV).
189          *
190          * 1) select single or multi(enable to 25), format, size
191          * 2) set interrupt
192          * 3) start capture(for main image, now)
193          * 4) get information
194          * 5) notify file size to v4l2 device(e.g, to s5p-fimc v4l2 device)
195          */
196         ret = i2c_w8_capt_ctrl(sd, CATC_CAP_SEL_FRAME, 1);
197         if (!ret)
198                 ret = i2c_w8_capt_param(sd, CATB_YUVOUT_MAIN, REG_JPEG);
199         if (!ret)
200                 ret = i2c_w8_capt_param(sd, CATB_MAIN_IMAGE_SIZE, resolution);
201         if (!ret)
202                 ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE);
203         if (!ret)
204                 ret = i2c_w8_capt_ctrl(sd, CATC_CAP_START, REG_CAP_START_MAIN);
205         if (!ret)
206                 /* Wait for capture interrupt, after starting capture */
207                 timeout = wait_event_interruptible_timeout(info->wait_capture,
208                                 is_captured(info), msecs_to_jiffies(2000));
209         if (!ret && is_captured(info))
210                 ret = m5mols_capture_info(info, false);
211         if (!ret)
212                 v4l2_subdev_notify(sd, 0, &info->cap.total);
213         if (!ret)
214                 ret = m5mols_capture_handler_error(info, timeout);
215
216         return ret;
217 }