~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/media/video/m5mols/m5mols_controls.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Controls for M-5MOLS 8M Pixel camera sensor with 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/delay.h>
 
18
#include <linux/videodev2.h>
 
19
#include <media/v4l2-ctrls.h>
 
20
 
 
21
#include "m5mols.h"
 
22
#include "m5mols_reg.h"
 
23
 
 
24
static struct m5mols_scenemode m5mols_default_scenemode[] = {
 
25
        [REG_SCENE_NORMAL] = {
 
26
                REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
 
27
                REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
 
28
                REG_AF_NORMAL, REG_FD_OFF,
 
29
                REG_MCC_NORMAL, REG_LIGHT_OFF, REG_FLASH_OFF,
 
30
                5, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
 
31
        },
 
32
        [REG_SCENE_PORTRAIT] = {
 
33
                REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
 
34
                REG_CHROMA_ON, 3, REG_EDGE_ON, 4,
 
35
                REG_AF_NORMAL, BIT_FD_EN | BIT_FD_DRAW_FACE_FRAME,
 
36
                REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
 
37
                6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
 
38
        },
 
39
        [REG_SCENE_LANDSCAPE] = {
 
40
                REG_AE_ALL, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
 
41
                REG_CHROMA_ON, 4, REG_EDGE_ON, 6,
 
42
                REG_AF_NORMAL, REG_FD_OFF,
 
43
                REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
 
44
                6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
 
45
        },
 
46
        [REG_SCENE_SPORTS] = {
 
47
                REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
 
48
                REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
 
49
                REG_AF_NORMAL, REG_FD_OFF,
 
50
                REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
 
51
                6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
 
52
        },
 
53
        [REG_SCENE_PARTY_INDOOR] = {
 
54
                REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
 
55
                REG_CHROMA_ON, 4, REG_EDGE_ON, 5,
 
56
                REG_AF_NORMAL, REG_FD_OFF,
 
57
                REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
 
58
                6, REG_ISO_200, REG_CAP_NONE, REG_WDR_OFF,
 
59
        },
 
60
        [REG_SCENE_BEACH_SNOW] = {
 
61
                REG_AE_CENTER, REG_AE_INDEX_10_POS, REG_AWB_AUTO, 0,
 
62
                REG_CHROMA_ON, 4, REG_EDGE_ON, 5,
 
63
                REG_AF_NORMAL, REG_FD_OFF,
 
64
                REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
 
65
                6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF,
 
66
        },
 
67
        [REG_SCENE_SUNSET] = {
 
68
                REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET,
 
69
                REG_AWB_DAYLIGHT,
 
70
                REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
 
71
                REG_AF_NORMAL, REG_FD_OFF,
 
72
                REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
 
73
                6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
 
74
        },
 
75
        [REG_SCENE_DAWN_DUSK] = {
 
76
                REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET,
 
77
                REG_AWB_FLUORESCENT_1,
 
78
                REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
 
79
                REG_AF_NORMAL, REG_FD_OFF,
 
80
                REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
 
81
                6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
 
82
        },
 
83
        [REG_SCENE_FALL] = {
 
84
                REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
 
85
                REG_CHROMA_ON, 5, REG_EDGE_ON, 5,
 
86
                REG_AF_NORMAL, REG_FD_OFF,
 
87
                REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
 
88
                6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
 
89
        },
 
90
        [REG_SCENE_NIGHT] = {
 
91
                REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
 
92
                REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
 
93
                REG_AF_NORMAL, REG_FD_OFF,
 
94
                REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
 
95
                6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
 
96
        },
 
97
        [REG_SCENE_AGAINST_LIGHT] = {
 
98
                REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
 
99
                REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
 
100
                REG_AF_NORMAL, REG_FD_OFF,
 
101
                REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
 
102
                6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
 
103
        },
 
104
        [REG_SCENE_FIRE] = {
 
105
                REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
 
106
                REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
 
107
                REG_AF_NORMAL, REG_FD_OFF,
 
108
                REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
 
109
                6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF,
 
110
        },
 
111
        [REG_SCENE_TEXT] = {
 
112
                REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
 
113
                REG_CHROMA_ON, 3, REG_EDGE_ON, 7,
 
114
                REG_AF_MACRO, REG_FD_OFF,
 
115
                REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
 
116
                6, REG_ISO_AUTO, REG_CAP_ANTI_SHAKE, REG_WDR_ON,
 
117
        },
 
118
        [REG_SCENE_CANDLE] = {
 
119
                REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
 
120
                REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
 
121
                REG_AF_NORMAL, REG_FD_OFF,
 
122
                REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
 
123
                6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
 
124
        },
 
125
};
 
126
 
 
127
/**
 
128
 * m5mols_do_scenemode() - Change current scenemode
 
129
 * @mode:       Desired mode of the scenemode
 
130
 *
 
131
 * WARNING: The execution order is important. Do not change the order.
 
132
 */
 
133
int m5mols_do_scenemode(struct m5mols_info *info, u8 mode)
 
134
{
 
135
        struct v4l2_subdev *sd = &info->sd;
 
136
        struct m5mols_scenemode scenemode = m5mols_default_scenemode[mode];
 
137
        int ret;
 
138
 
 
139
        if (mode > REG_SCENE_CANDLE)
 
140
                return -EINVAL;
 
141
 
 
142
        ret = m5mols_lock_3a(info, false);
 
143
        if (!ret)
 
144
                ret = m5mols_write(sd, AE_EV_PRESET_MONITOR, mode);
 
145
        if (!ret)
 
146
                ret = m5mols_write(sd, AE_EV_PRESET_CAPTURE, mode);
 
147
        if (!ret)
 
148
                ret = m5mols_write(sd, AE_MODE, scenemode.metering);
 
149
        if (!ret)
 
150
                ret = m5mols_write(sd, AE_INDEX, scenemode.ev_bias);
 
151
        if (!ret)
 
152
                ret = m5mols_write(sd, AWB_MODE, scenemode.wb_mode);
 
153
        if (!ret)
 
154
                ret = m5mols_write(sd, AWB_MANUAL, scenemode.wb_preset);
 
155
        if (!ret)
 
156
                ret = m5mols_write(sd, MON_CHROMA_EN, scenemode.chroma_en);
 
157
        if (!ret)
 
158
                ret = m5mols_write(sd, MON_CHROMA_LVL, scenemode.chroma_lvl);
 
159
        if (!ret)
 
160
                ret = m5mols_write(sd, MON_EDGE_EN, scenemode.edge_en);
 
161
        if (!ret)
 
162
                ret = m5mols_write(sd, MON_EDGE_LVL, scenemode.edge_lvl);
 
163
        if (!ret && is_available_af(info))
 
164
                ret = m5mols_write(sd, AF_MODE, scenemode.af_range);
 
165
        if (!ret && is_available_af(info))
 
166
                ret = m5mols_write(sd, FD_CTL, scenemode.fd_mode);
 
167
        if (!ret)
 
168
                ret = m5mols_write(sd, MON_TONE_CTL, scenemode.tone);
 
169
        if (!ret)
 
170
                ret = m5mols_write(sd, AE_ISO, scenemode.iso);
 
171
        if (!ret)
 
172
                ret = m5mols_mode(info, REG_CAPTURE);
 
173
        if (!ret)
 
174
                ret = m5mols_write(sd, CAPP_WDR_EN, scenemode.wdr);
 
175
        if (!ret)
 
176
                ret = m5mols_write(sd, CAPP_MCC_MODE, scenemode.mcc);
 
177
        if (!ret)
 
178
                ret = m5mols_write(sd, CAPP_LIGHT_CTRL, scenemode.light);
 
179
        if (!ret)
 
180
                ret = m5mols_write(sd, CAPP_FLASH_CTRL, scenemode.flash);
 
181
        if (!ret)
 
182
                ret = m5mols_write(sd, CAPC_MODE, scenemode.capt_mode);
 
183
        if (!ret)
 
184
                ret = m5mols_mode(info, REG_MONITOR);
 
185
 
 
186
        return ret;
 
187
}
 
188
 
 
189
static int m5mols_lock_ae(struct m5mols_info *info, bool lock)
 
190
{
 
191
        int ret = 0;
 
192
 
 
193
        if (info->lock_ae != lock)
 
194
                ret = m5mols_write(&info->sd, AE_LOCK,
 
195
                                lock ? REG_AE_LOCK : REG_AE_UNLOCK);
 
196
        if (!ret)
 
197
                info->lock_ae = lock;
 
198
 
 
199
        return ret;
 
200
}
 
201
 
 
202
static int m5mols_lock_awb(struct m5mols_info *info, bool lock)
 
203
{
 
204
        int ret = 0;
 
205
 
 
206
        if (info->lock_awb != lock)
 
207
                ret = m5mols_write(&info->sd, AWB_LOCK,
 
208
                                lock ? REG_AWB_LOCK : REG_AWB_UNLOCK);
 
209
        if (!ret)
 
210
                info->lock_awb = lock;
 
211
 
 
212
        return ret;
 
213
}
 
214
 
 
215
/* m5mols_lock_3a() - Lock 3A(Auto Exposure, Auto Whitebalance, Auto Focus) */
 
216
int m5mols_lock_3a(struct m5mols_info *info, bool lock)
 
217
{
 
218
        int ret;
 
219
 
 
220
        ret = m5mols_lock_ae(info, lock);
 
221
        if (!ret)
 
222
                ret = m5mols_lock_awb(info, lock);
 
223
        /* Don't need to handle unlocking AF */
 
224
        if (!ret && is_available_af(info) && lock)
 
225
                ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP);
 
226
 
 
227
        return ret;
 
228
}
 
229
 
 
230
/* m5mols_set_ctrl() - The main s_ctrl function called by m5mols_set_ctrl() */
 
231
int m5mols_set_ctrl(struct v4l2_ctrl *ctrl)
 
232
{
 
233
        struct v4l2_subdev *sd = to_sd(ctrl);
 
234
        struct m5mols_info *info = to_m5mols(sd);
 
235
        int ret;
 
236
 
 
237
        switch (ctrl->id) {
 
238
        case V4L2_CID_ZOOM_ABSOLUTE:
 
239
                return m5mols_write(sd, MON_ZOOM, ctrl->val);
 
240
 
 
241
        case V4L2_CID_EXPOSURE_AUTO:
 
242
                ret = m5mols_lock_ae(info,
 
243
                        ctrl->val == V4L2_EXPOSURE_AUTO ? false : true);
 
244
                if (!ret && ctrl->val == V4L2_EXPOSURE_AUTO)
 
245
                        ret = m5mols_write(sd, AE_MODE, REG_AE_ALL);
 
246
                if (!ret && ctrl->val == V4L2_EXPOSURE_MANUAL) {
 
247
                        int val = info->exposure->val;
 
248
                        ret = m5mols_write(sd, AE_MODE, REG_AE_OFF);
 
249
                        if (!ret)
 
250
                                ret = m5mols_write(sd, AE_MAN_GAIN_MON, val);
 
251
                        if (!ret)
 
252
                                ret = m5mols_write(sd, AE_MAN_GAIN_CAP, val);
 
253
                }
 
254
                return ret;
 
255
 
 
256
        case V4L2_CID_AUTO_WHITE_BALANCE:
 
257
                ret = m5mols_lock_awb(info, ctrl->val ? false : true);
 
258
                if (!ret)
 
259
                        ret = m5mols_write(sd, AWB_MODE, ctrl->val ?
 
260
                                REG_AWB_AUTO : REG_AWB_PRESET);
 
261
                return ret;
 
262
 
 
263
        case V4L2_CID_SATURATION:
 
264
                ret = m5mols_write(sd, MON_CHROMA_LVL, ctrl->val);
 
265
                if (!ret)
 
266
                        ret = m5mols_write(sd, MON_CHROMA_EN, REG_CHROMA_ON);
 
267
                return ret;
 
268
 
 
269
        case V4L2_CID_COLORFX:
 
270
                /*
 
271
                 * This control uses two kinds of registers: normal & color.
 
272
                 * The normal effect belongs to category 1, while the color
 
273
                 * one belongs to category 2.
 
274
                 *
 
275
                 * The normal effect uses one register: CAT1_EFFECT.
 
276
                 * The color effect uses three registers:
 
277
                 * CAT2_COLOR_EFFECT, CAT2_CFIXR, CAT2_CFIXB.
 
278
                 */
 
279
                ret = m5mols_write(sd, PARM_EFFECT,
 
280
                        ctrl->val == V4L2_COLORFX_NEGATIVE ? REG_EFFECT_NEGA :
 
281
                        ctrl->val == V4L2_COLORFX_EMBOSS ? REG_EFFECT_EMBOSS :
 
282
                        REG_EFFECT_OFF);
 
283
                if (!ret)
 
284
                        ret = m5mols_write(sd, MON_EFFECT,
 
285
                                ctrl->val == V4L2_COLORFX_SEPIA ?
 
286
                                REG_COLOR_EFFECT_ON : REG_COLOR_EFFECT_OFF);
 
287
                if (!ret)
 
288
                        ret = m5mols_write(sd, MON_CFIXR,
 
289
                                ctrl->val == V4L2_COLORFX_SEPIA ?
 
290
                                REG_CFIXR_SEPIA : 0);
 
291
                if (!ret)
 
292
                        ret = m5mols_write(sd, MON_CFIXB,
 
293
                                ctrl->val == V4L2_COLORFX_SEPIA ?
 
294
                                REG_CFIXB_SEPIA : 0);
 
295
                return ret;
 
296
        }
 
297
 
 
298
        return -EINVAL;
 
299
}