2 * Copyright (C) 2012 Spreadtrum Communications Inc.
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.
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.
14 #include <linux/vmalloc.h>
15 #include <linux/uaccess.h>
16 #include <linux/sprd_mm.h>
17 #include <video/sprd_isp.h>
21 static int32_t isp_k_awb_block(struct isp_io_param *param)
25 struct isp_dev_awb_info awb_info;
27 memset(&awb_info, 0x00, sizeof(awb_info));
29 ret = copy_from_user((void *)&awb_info, param->property_param, sizeof(awb_info));
31 printk("isp_k_awbm_bypass: copy error, ret=0x%x\n", (uint32_t)ret);
37 REG_OWR(ISP_AWBM_PARAM, BIT_1);
39 REG_MWR(ISP_AWBM_PARAM, BIT_1, 0);
42 REG_MWR(ISP_AWBM_PARAM, (BIT_5 | BIT_4 | BIT_3 | BIT_2), (awb_info.skip_num << 2));
44 val = ((awb_info.offset_y & 0xFFFF) << 16) | (awb_info.offset_x & 0xFFFF);
45 REG_WR(ISP_AWBM_BLOCK_OFFSET, val);
47 val = ((awb_info.win_h & 0x1FF) << 9) | (awb_info.win_w & 0x1FF);
48 REG_MWR(ISP_AWBM_BLOCK_SIZE, 0x1FFFF, val);
50 REG_MWR(ISP_AWBM_BLOCK_SIZE, (0x1F << 18), (awb_info.shift << 18));
52 if (awb_info.awbm_bypass) {
53 REG_OWR(ISP_AWBM_PARAM, BIT_0);
55 REG_MWR(ISP_AWBM_PARAM, BIT_0, 0);
59 val = ((awb_info.b_gain & 0xFFFF) << 16) | (awb_info.r_gain& 0xFFFF);
60 REG_WR(ISP_AWBC_GAIN0, val);
62 val = ((awb_info.g_gain & 0xFFFF) << 16) | (awb_info.g_gain & 0xFFFF);
63 REG_WR(ISP_AWBC_GAIN1, val);
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);
68 val = ((awb_info.b_offset & 0xFFFF) << 16) | (awb_info.r_offset & 0xFFFF);
69 REG_WR(ISP_AWBC_OFFSET0, val);
71 val = ((awb_info.g_offset & 0xFFFF) << 16) | (awb_info.g_offset & 0xFFFF);
72 REG_WR(ISP_AWBC_OFFSET1, val);
74 if (awb_info.awbc_bypass) {
75 REG_OWR(ISP_AWBC_PARAM, BIT_0);
77 REG_MWR(ISP_AWBC_PARAM, BIT_0, 0);
84 static int32_t isp_k_awbm_statistics(struct isp_io_param *param)
86 int32_t ret = 0, i = 0;
87 uint32_t val0 = 0, val1 = 0, addr = 0;
88 struct isp_awbm_statistics *awbm_statistics = NULL;
90 awbm_statistics = vzalloc(sizeof(struct isp_awbm_statistics));/*To be optimized later*/
91 if (!awbm_statistics) {
93 printk("isp_k_awbm_info: alloc memory error.\n");
97 addr = ISP_AWBM_OUTPUT;
98 for (i = 0x00; i < ISP_AWBM_ITEM; i++) {
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);
107 ret = copy_to_user(param->property_param, (void*)awbm_statistics, sizeof(struct isp_awbm_statistics));
110 printk("isp_k_awbm_info: copy error, ret=0x%x\n", (uint32_t)ret);
113 vfree(awbm_statistics);
118 static int32_t isp_k_awbm_bypass(struct isp_io_param *param)
123 ret = copy_from_user((void *)&bypass, param->property_param, sizeof(bypass));
125 printk("isp_k_awbm_bypass: copy error, ret=0x%x\n", (uint32_t)ret);
130 REG_OWR(ISP_AWBM_PARAM, BIT_0);
132 REG_MWR(ISP_AWBM_PARAM, BIT_0, 0);
138 static int32_t isp_k_awbm_mode(struct isp_io_param *param)
143 ret = copy_from_user((void *)&mode, param->property_param, sizeof(mode));
145 printk("isp_k_awbm_mode: copy error, ret=0x%x\n", (uint32_t)ret);
150 REG_OWR(ISP_AWBM_PARAM, BIT_1);
152 REG_MWR(ISP_AWBM_PARAM, BIT_1, 0);
158 static int32_t isp_k_awbm_skip_num(struct isp_io_param *param)
164 ret = copy_from_user((void *)&num, param->property_param, sizeof(num));
166 printk("isp_k_awbm_skip_num: copy error, ret=0x%x\n", (uint32_t)ret);
170 val = (num & 0x0F) << 2;
171 REG_MWR(ISP_AWBM_PARAM, (BIT_5 | BIT_4 | BIT_3 | BIT_2), val);
176 static int32_t isp_k_awbm_block_offset(struct isp_io_param *param)
180 struct isp_img_offset offset = {0, 0};
182 ret = copy_from_user((void *)&offset, param->property_param, sizeof(offset));
184 printk("isp_k_awbm_block_offset: copy error, ret=0x%x\n", (uint32_t)ret);
188 val = ((offset.y & 0xFFFF) << 16) | (offset.x & 0xFFFF);
190 REG_WR(ISP_AWBM_BLOCK_OFFSET, val);
195 static int32_t isp_k_awbm_block_size(struct isp_io_param *param)
199 struct isp_img_size size = {0, 0};
201 ret = copy_from_user((void *)&size, param->property_param, sizeof(size));
203 printk("isp_k_awbm_block_size: copy error, ret=0x%x\n", (uint32_t)ret);
207 val = ((size.height & 0x1FF) << 9) | (size.width & 0x1FF);
209 REG_MWR(ISP_AWBM_BLOCK_SIZE, 0x1FFFF, val);
214 static int32_t isp_k_awbm_shift(struct isp_io_param *param)
219 ret = copy_from_user((void *)&shift, param->property_param, sizeof(shift));
221 printk("isp_k_awbm_shift: copy error, ret=0x%x\n", (uint32_t)ret);
225 shift = (shift & 0x1F) << 18;
227 REG_MWR(ISP_AWBM_BLOCK_SIZE, (0x1F << 18), shift);
232 static int32_t isp_k_awbc_bypass(struct isp_io_param *param)
237 ret = copy_from_user((void *)&bypass, param->property_param, sizeof(bypass));
239 printk("isp_k_awbc_bypass: copy error, ret=0x%x\n", (uint32_t)ret);
244 REG_OWR(ISP_AWBC_PARAM, BIT_0);
246 REG_MWR(ISP_AWBC_PARAM, BIT_0, 0);
252 static int32_t isp_k_awbc_gain(struct isp_io_param *param)
256 struct isp_awbc_rgb gain= {0, 0, 0};
258 ret = copy_from_user((void *)&gain, param->property_param, sizeof(gain));
260 printk("isp_k_awbc_gain: copy error, ret=0x%x\n", (uint32_t)ret);
264 val = ((gain.b & 0xFFFF) << 16) | (gain.r & 0xFFFF);
265 REG_WR(ISP_AWBC_GAIN0, val);
267 val = ((gain.g & 0xFFFF) << 16) | (gain.g & 0xFFFF);
268 REG_WR(ISP_AWBC_GAIN1, val);
273 static int32_t isp_k_awbc_thrd(struct isp_io_param *param)
277 struct isp_awbc_rgb thrd= {0, 0, 0};
279 ret = copy_from_user((void *)&thrd, param->property_param, sizeof(thrd));
281 printk("isp_k_awbc_thrd: copy error, ret=0x%x\n", (uint32_t)ret);
285 val = ((thrd.b & 0x3FF) << 20) | ((thrd.g & 0x3FF) << 10) | (thrd.r & 0x3FF);
286 REG_WR(ISP_AWBC_THRD, val);
291 static int32_t isp_k_awbc_gain_offset(struct isp_io_param *param)
295 struct isp_awbc_rgb gain_offset= {0, 0, 0};
297 ret = copy_from_user((void *)&gain_offset, param->property_param, sizeof(gain_offset));
299 printk("isp_k_awbc_gain_offset: copy error, ret=0x%x\n", (uint32_t)ret);
303 val = ((gain_offset.b & 0xFFFF) << 16) | (gain_offset.r & 0xFFFF);
304 REG_WR(ISP_AWBC_OFFSET0, val);
306 val = ((gain_offset.g & 0xFFFF) << 16) | (gain_offset.g & 0xFFFF);
307 REG_WR(ISP_AWBC_OFFSET1, val);
312 int32_t isp_k_cfg_awb(struct isp_io_param *param,
313 struct isp_k_private *isp_private)
318 printk("isp_k_cfg_awb: param is null error.\n");
322 if (NULL == param->property_param) {
323 printk("isp_k_cfg_awb: property_param is null error.\n");
327 switch(param->property) {
328 case ISP_PRO_AWB_BLOCK:
329 ret = isp_k_awb_block(param);
331 case ISP_PRO_AWBM_STATISTICS:
332 ret = isp_k_awbm_statistics(param);
334 case ISP_PRO_AWBM_BYPASS:
335 ret = isp_k_awbm_bypass(param);
337 case ISP_PRO_AWBM_MODE:
338 ret = isp_k_awbm_mode(param);
340 case ISP_PRO_AWBM_SKIP_NUM:
341 ret = isp_k_awbm_skip_num(param);
343 case ISP_PRO_AWBM_BLOCK_OFFSET:
344 ret = isp_k_awbm_block_offset(param);
346 case ISP_PRO_AWBM_BLOCK_SIZE:
347 ret = isp_k_awbm_block_size(param);
349 case ISP_PRO_AWBM_SHIFT:
350 ret = isp_k_awbm_shift(param);
352 case ISP_PRO_AWBC_BYPASS:
353 ret = isp_k_awbc_bypass(param);
355 case ISP_PRO_AWBC_GAIN:
356 ret = isp_k_awbc_gain(param);
358 case ISP_PRO_AWBC_THRD:
359 ret = isp_k_awbc_thrd(param);
361 case ISP_PRO_AWBC_GAIN_OFFSET:
362 ret = isp_k_awbc_gain_offset(param);
365 printk("isp_k_cfg_awb: fail cmd id:%d, not supported.\n", param->property);