tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / media / sprd_isp / isp2.0 / sharkl / src / isp_k_awb.c
1 /*
2  * Copyright (C) 2012 Spreadtrum Communications Inc.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13
14 #include <linux/vmalloc.h>
15 #include <linux/uaccess.h>
16 #include <linux/sprd_mm.h>
17 #include <video/sprd_isp.h>
18 #include "isp_reg.h"
19 #include "isp_drv.h"
20
21 static int32_t isp_k_awb_block(struct isp_io_param *param)
22 {
23         int32_t ret = 0;
24         uint32_t val = 0;
25         struct isp_dev_awb_info awb_info;
26
27         memset(&awb_info, 0x00, sizeof(awb_info));
28
29         ret = copy_from_user((void *)&awb_info, param->property_param, sizeof(awb_info));
30         if (0 != ret) {
31                 printk("isp_k_awbm_bypass: copy error, ret=0x%x\n", (uint32_t)ret);
32                 return -1;
33         }
34
35         /*AWBM*/
36         if (awb_info.mode) {
37                 REG_OWR(ISP_AWBM_PARAM, BIT_1);
38         } else {
39                 REG_MWR(ISP_AWBM_PARAM, BIT_1, 0);
40         }
41
42         REG_MWR(ISP_AWBM_PARAM, (BIT_5 | BIT_4 | BIT_3 | BIT_2), (awb_info.skip_num << 2));
43
44         val = ((awb_info.offset_y & 0xFFFF) << 16) | (awb_info.offset_x & 0xFFFF);
45         REG_WR(ISP_AWBM_BLOCK_OFFSET, val);
46
47         val = ((awb_info.win_h & 0x1FF) << 9) | (awb_info.win_w & 0x1FF);
48         REG_MWR(ISP_AWBM_BLOCK_SIZE, 0x1FFFF, val);
49
50         REG_MWR(ISP_AWBM_BLOCK_SIZE, (0x1F << 18), (awb_info.shift << 18));
51
52         if (awb_info.awbm_bypass) {
53                 REG_OWR(ISP_AWBM_PARAM, BIT_0);
54         } else {
55                 REG_MWR(ISP_AWBM_PARAM, BIT_0, 0);
56         }
57
58         /*AWBC*/
59         val = ((awb_info.b_gain & 0xFFFF) << 16) | (awb_info.r_gain& 0xFFFF);
60         REG_WR(ISP_AWBC_GAIN0, val);
61
62         val = ((awb_info.g_gain & 0xFFFF) << 16) | (awb_info.g_gain & 0xFFFF);
63         REG_WR(ISP_AWBC_GAIN1, val);
64
65         val = ((awb_info.b_thrd& 0x3FF) << 20) | ((awb_info.g_thrd & 0x3FF) << 10) | (awb_info.r_thrd & 0x3FF);
66         REG_WR(ISP_AWBC_THRD, val);
67
68         val = ((awb_info.b_offset & 0xFFFF) << 16) | (awb_info.r_offset & 0xFFFF);
69         REG_WR(ISP_AWBC_OFFSET0, val);
70
71         val = ((awb_info.g_offset & 0xFFFF) << 16) | (awb_info.g_offset & 0xFFFF);
72         REG_WR(ISP_AWBC_OFFSET1, val);
73
74         if (awb_info.awbc_bypass) {
75                 REG_OWR(ISP_AWBC_PARAM, BIT_0);
76         } else {
77                 REG_MWR(ISP_AWBC_PARAM, BIT_0, 0);
78         }
79
80         return ret;
81 }
82
83
84 static int32_t isp_k_awbm_statistics(struct isp_io_param *param)
85 {
86         int32_t ret = 0, i = 0;
87         uint32_t val0 = 0, val1 = 0, addr = 0;
88         struct isp_awbm_statistics *awbm_statistics = NULL;
89
90         awbm_statistics = vzalloc(sizeof(struct isp_awbm_statistics));/*To be optimized later*/
91         if (!awbm_statistics) {
92                 ret = -1;
93                 printk("isp_k_awbm_info: alloc memory error.\n");
94                 return -1;
95         }
96
97         addr = ISP_AWBM_OUTPUT;
98         for (i = 0x00; i < ISP_AWBM_ITEM; i++) {
99                 val0 = REG_RD(addr);
100                 val1 = REG_RD(addr + 4);
101                 awbm_statistics->r[i]= (val1 >> 11) & 0x1fffff;
102                 awbm_statistics->g[i]= val0 & 0x3fffff;
103                 awbm_statistics->b[i]= ((val1 & 0x7ff) << 10) | ((val0 >> 22) & 0x3ff);
104                 addr += 8;
105         }
106
107         ret = copy_to_user(param->property_param, (void*)awbm_statistics, sizeof(struct isp_awbm_statistics));
108         if (0 != ret) {
109                 ret = -1;
110                 printk("isp_k_awbm_info: copy error, ret=0x%x\n", (uint32_t)ret);
111         }
112
113         vfree(awbm_statistics);
114
115         return ret;
116 }
117
118 static int32_t isp_k_awbm_bypass(struct isp_io_param *param)
119 {
120         int32_t ret = 0;
121         uint32_t bypass = 0;
122
123         ret = copy_from_user((void *)&bypass, param->property_param, sizeof(bypass));
124         if (0 != ret) {
125                 printk("isp_k_awbm_bypass: copy error, ret=0x%x\n", (uint32_t)ret);
126                 return -1;
127         }
128
129         if (bypass) {
130                 REG_OWR(ISP_AWBM_PARAM, BIT_0);
131         } else {
132                 REG_MWR(ISP_AWBM_PARAM, BIT_0, 0);
133         }
134
135         return ret;
136 }
137
138 static int32_t isp_k_awbm_mode(struct isp_io_param *param)
139 {
140         int32_t ret = 0;
141         uint32_t mode = 0;
142
143         ret = copy_from_user((void *)&mode, param->property_param, sizeof(mode));
144         if (0 != ret) {
145                 printk("isp_k_awbm_mode: copy error, ret=0x%x\n", (uint32_t)ret);
146                 return -1;
147         }
148
149         if (mode) {
150                 REG_OWR(ISP_AWBM_PARAM, BIT_1);
151         } else {
152                 REG_MWR(ISP_AWBM_PARAM, BIT_1, 0);
153         }
154
155         return ret;
156 }
157
158 static int32_t isp_k_awbm_skip_num(struct isp_io_param *param)
159 {
160         int32_t ret = 0;
161         uint32_t val = 0;
162         uint32_t num = 0;
163
164         ret = copy_from_user((void *)&num, param->property_param, sizeof(num));
165         if (0 != ret) {
166                 printk("isp_k_awbm_skip_num: copy error, ret=0x%x\n", (uint32_t)ret);
167                 return -1;
168         }
169
170         val = (num & 0x0F) << 2;
171         REG_MWR(ISP_AWBM_PARAM, (BIT_5 | BIT_4 | BIT_3 | BIT_2), val);
172
173         return ret;
174 }
175
176 static int32_t isp_k_awbm_block_offset(struct isp_io_param *param)
177 {
178         int32_t ret = 0;
179         uint32_t val = 0;
180         struct isp_img_offset offset = {0, 0};
181
182         ret = copy_from_user((void *)&offset, param->property_param, sizeof(offset));
183         if (0 != ret) {
184                 printk("isp_k_awbm_block_offset: copy error, ret=0x%x\n", (uint32_t)ret);
185                 return -1;
186         }
187
188         val = ((offset.y & 0xFFFF) << 16) | (offset.x & 0xFFFF);
189
190         REG_WR(ISP_AWBM_BLOCK_OFFSET, val);
191
192         return ret;
193 }
194
195 static int32_t isp_k_awbm_block_size(struct isp_io_param *param)
196 {
197         int32_t ret = 0;
198         uint32_t val = 0;
199         struct isp_img_size size = {0, 0};
200
201         ret = copy_from_user((void *)&size, param->property_param, sizeof(size));
202         if (0 != ret) {
203                 printk("isp_k_awbm_block_size: copy error, ret=0x%x\n", (uint32_t)ret);
204                 return -1;
205         }
206
207         val = ((size.height & 0x1FF) << 9) | (size.width & 0x1FF);
208
209         REG_MWR(ISP_AWBM_BLOCK_SIZE, 0x1FFFF, val);
210
211         return ret;
212 }
213
214 static int32_t isp_k_awbm_shift(struct isp_io_param *param)
215 {
216         int32_t ret = 0;
217         uint32_t shift = 0;
218
219         ret = copy_from_user((void *)&shift, param->property_param, sizeof(shift));
220         if (0 != ret) {
221                 printk("isp_k_awbm_shift: copy error, ret=0x%x\n", (uint32_t)ret);
222                 return -1;
223         }
224
225         shift = (shift & 0x1F) << 18;
226
227         REG_MWR(ISP_AWBM_BLOCK_SIZE, (0x1F << 18), shift);
228
229         return ret;
230 }
231
232 static int32_t isp_k_awbc_bypass(struct isp_io_param *param)
233 {
234         int32_t ret = 0;
235         uint32_t bypass = 0;
236
237         ret = copy_from_user((void *)&bypass, param->property_param, sizeof(bypass));
238         if (0 != ret) {
239                 printk("isp_k_awbc_bypass: copy error, ret=0x%x\n", (uint32_t)ret);
240                 return -1;
241         }
242
243         if (bypass) {
244                 REG_OWR(ISP_AWBC_PARAM, BIT_0);
245         } else {
246                 REG_MWR(ISP_AWBC_PARAM, BIT_0, 0);
247         }
248
249         return ret;
250 }
251
252 static int32_t isp_k_awbc_gain(struct isp_io_param *param)
253 {
254         int32_t ret = 0;
255         uint32_t val = 0;
256         struct isp_awbc_rgb gain= {0, 0, 0};
257
258         ret = copy_from_user((void *)&gain, param->property_param, sizeof(gain));
259         if (0 != ret) {
260                 printk("isp_k_awbc_gain: copy error, ret=0x%x\n", (uint32_t)ret);
261                 return -1;
262         }
263
264         val = ((gain.b & 0xFFFF) << 16) | (gain.r & 0xFFFF);
265         REG_WR(ISP_AWBC_GAIN0, val);
266
267         val = ((gain.g & 0xFFFF) << 16) | (gain.g & 0xFFFF);
268         REG_WR(ISP_AWBC_GAIN1, val);
269
270         return ret;
271 }
272
273 static int32_t isp_k_awbc_thrd(struct isp_io_param *param)
274 {
275         int32_t ret = 0;
276         uint32_t val = 0;
277         struct isp_awbc_rgb thrd= {0, 0, 0};
278
279         ret = copy_from_user((void *)&thrd, param->property_param, sizeof(thrd));
280         if (0 != ret) {
281                 printk("isp_k_awbc_thrd: copy error, ret=0x%x\n", (uint32_t)ret);
282                 return -1;
283         }
284
285         val = ((thrd.b & 0x3FF) << 20) | ((thrd.g & 0x3FF) << 10) | (thrd.r & 0x3FF);
286         REG_WR(ISP_AWBC_THRD, val);
287
288         return ret;
289 }
290
291 static int32_t isp_k_awbc_gain_offset(struct isp_io_param *param)
292 {
293         int32_t ret = 0;
294         uint32_t val = 0;
295         struct isp_awbc_rgb gain_offset= {0, 0, 0};
296
297         ret = copy_from_user((void *)&gain_offset, param->property_param, sizeof(gain_offset));
298         if (0 != ret) {
299                 printk("isp_k_awbc_gain_offset: copy error, ret=0x%x\n", (uint32_t)ret);
300                 return -1;
301         }
302
303         val = ((gain_offset.b & 0xFFFF) << 16) | (gain_offset.r & 0xFFFF);
304         REG_WR(ISP_AWBC_OFFSET0, val);
305
306         val = ((gain_offset.g & 0xFFFF) << 16) | (gain_offset.g & 0xFFFF);
307         REG_WR(ISP_AWBC_OFFSET1, val);
308
309         return ret;
310 }
311
312 int32_t isp_k_cfg_awb(struct isp_io_param *param,
313         struct isp_k_private *isp_private)
314 {
315         int32_t ret = 0;
316
317         if (!param) {
318                 printk("isp_k_cfg_awb: param is null error.\n");
319                 return -1;
320         }
321
322         if (NULL == param->property_param) {
323                 printk("isp_k_cfg_awb: property_param is null error.\n");
324                 return -1;
325         }
326
327         switch(param->property) {
328         case ISP_PRO_AWB_BLOCK:
329                 ret = isp_k_awb_block(param);
330                 break;
331         case ISP_PRO_AWBM_STATISTICS:
332                 ret = isp_k_awbm_statistics(param);
333                 break;
334         case ISP_PRO_AWBM_BYPASS:
335                 ret = isp_k_awbm_bypass(param);
336                 break;
337         case ISP_PRO_AWBM_MODE:
338                 ret = isp_k_awbm_mode(param);
339                 break;
340         case ISP_PRO_AWBM_SKIP_NUM:
341                 ret = isp_k_awbm_skip_num(param);
342                 break;
343         case ISP_PRO_AWBM_BLOCK_OFFSET:
344                 ret = isp_k_awbm_block_offset(param);
345                 break;
346         case ISP_PRO_AWBM_BLOCK_SIZE:
347                 ret = isp_k_awbm_block_size(param);
348                 break;
349         case ISP_PRO_AWBM_SHIFT:
350                 ret = isp_k_awbm_shift(param);
351                 break;
352         case ISP_PRO_AWBC_BYPASS:
353                 ret = isp_k_awbc_bypass(param);
354                 break;
355         case ISP_PRO_AWBC_GAIN:
356                 ret = isp_k_awbc_gain(param);
357                 break;
358         case ISP_PRO_AWBC_THRD:
359                 ret = isp_k_awbc_thrd(param);
360                 break;
361         case ISP_PRO_AWBC_GAIN_OFFSET:
362                 ret = isp_k_awbc_gain_offset(param);
363                 break;
364         default:
365                 printk("isp_k_cfg_awb: fail cmd id:%d, not supported.\n", param->property);
366                 break;
367         }
368
369         return ret;
370 }