tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / media / sprd_isp / isp2.0 / pike / 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/uaccess.h>
15 #include <linux/sprd_mm.h>
16 #include <video/sprd_isp.h>
17 #include "isp_reg.h"
18 #include "isp_drv.h"
19
20 static int32_t isp_k_awb_block(struct isp_io_param *param)
21 {
22         int32_t ret = 0;
23         uint32_t val = 0;
24         uint32_t i = 0;
25         struct isp_dev_awb_info_v2 awb_info;
26
27         ret = copy_from_user((void *)&awb_info, param->property_param, sizeof(awb_info));
28         if (0 != ret) {
29                 printk("isp_k_awbm_bypass: copy error, ret=0x%x\n", (uint32_t)ret);
30                 return -1;
31         }
32
33         //printk("isp_k_awb_block: %d  %d  %d  %d \n",awb_info.slice_size.width,awb_info.slice_size.height,awb_info.block_size.width,awb_info.block_size.height);
34         //printk("isp_k_awb_block: gain r=%d  gr=%d  b=%d \n",awb_info.gain.r,awb_info.gain.gr,awb_info.gain.b);
35         //printk("isp_k_awb_block: offset r=%d  gr=%d  b=%d  \n",awb_info.gain_offset.r,awb_info.gain_offset.gr,awb_info.gain_offset.b);
36         /*AWBM*/
37
38         REG_MWR(ISP_AWBM_PARAM, BIT_0, awb_info.awbm_bypass);
39
40         REG_MWR(ISP_AWBM_PARAM, BIT_1, awb_info.mode << 1);
41
42         val = (awb_info.skip_num & 0x0F) << 2;
43         REG_MWR(ISP_AWBM_PARAM, (BIT_5 | BIT_4 | BIT_3 | BIT_2), val);
44
45         val = ((awb_info.block_offset.y & 0xFFFF) << 16) | (awb_info.block_offset.x & 0xFFFF);
46         REG_WR(ISP_AWBM_BLOCK_OFFSET, val);
47
48         val = ((awb_info.block_size.height & 0x1FF) << 9) | (awb_info.block_size.width & 0x1FF);
49         REG_MWR(ISP_AWBM_BLOCK_SIZE, 0x1FFFF, val);
50
51         val = (awb_info.shift & 0x1F) << 18;
52         REG_MWR(ISP_AWBM_BLOCK_SIZE, (0x1F << 18), val);
53
54         REG_MWR(ISP_AWBM_PARAM, BIT_8, awb_info.thr_bypass << 8);
55
56         for (i = 0; i < 5; i++) {
57                 val = ((awb_info.rect_pos.start_x[i] & 0x3FF) << 16) | (awb_info.rect_pos.start_y[i] & 0x3FF);
58                 REG_WR(ISP_AWBM_WR_0_S + i * 8, val);
59                 val = ((awb_info.rect_pos.end_x[i] & 0x3FF) << 16) | (awb_info.rect_pos.end_y[i] & 0x3FF);
60                 REG_WR(ISP_AWBM_WR_0_E + i * 8, val);
61         }
62
63         for (i = 0; i < 5; i++) {
64                 val = ((awb_info.circle_pos.x[i] & 0x3FF) << 18) | ((awb_info.circle_pos.y[i] & 0x3FF) << 8) | (awb_info.circle_pos.r[i] & 0xFF);
65                 REG_WR(ISP_AWBM_NW_0_XYR + i * 4, val);
66         }
67
68         for (i = 0; i < 5; i++) {
69                 val = ((awb_info.clctor_pos.start_x[i] & 0x3FF) << 16) | (awb_info.clctor_pos.start_y[i] & 0x3FF);
70                 REG_WR(ISP_AWBM_CLCTOR_0_S + i * 8, val);
71                 val = ((awb_info.clctor_pos.end_x[i] & 0x3FF) << 16) | (awb_info.clctor_pos.end_y[i] & 0x3FF);
72                 REG_WR(ISP_AWBM_CLCTOR_0_E + i * 8, val);
73         }
74
75         val = ((awb_info.thr.g_low & 0x3FF) << 20) | ((awb_info.thr.r_high & 0x3FF) << 10) | (awb_info.thr.r_low & 0x3FF);
76         REG_WR(ISP_AWBM_THR_VALUE1, val);
77         val = ((awb_info.thr.b_high & 0x3FF) << 20) | ((awb_info.thr.b_low & 0x3FF) << 10) | (awb_info.thr.g_high & 0x3FF);
78         REG_WR(ISP_AWBM_THR_VALUE2, val);
79
80 //      val = ((awb_info.slice_size.height & 0xFFFF) << 16) | (awb_info.slice_size.width & 0xFFFF);
81 //      REG_WR(ISP_AEM_SLICE_SIZE, val);
82
83         REG_MWR(ISP_AWBM_PARAM, BIT_6, awb_info.skip_num_clear << 6);
84         REG_MWR(ISP_AWBM_POSITION_SEL, BIT_0, awb_info.position_sel);
85
86         REG_WR(ISP_AWBM_MEM_ADDR, awb_info.mem_addr);
87
88         /*AWBC*/
89
90         REG_MWR(ISP_AWBC_PARAM, BIT_0, awb_info.awbc_bypass);
91
92         REG_MWR(ISP_AWBC_PARAM, BIT_1, awb_info.alpha_bypass << 1);
93
94         val = (awb_info.alpha_value & 0x3FF) << 4;
95         REG_MWR(ISP_AWBC_PARAM, 0x3FF0, val);
96
97         REG_MWR(ISP_AWBC_PARAM, BIT_3, awb_info.buf_sel << 3);
98
99         val = ((awb_info.gain.b & 0x3FFF) << 16) | (awb_info.gain.r & 0x3FFF);
100         REG_WR(ISP_AWBC_GAIN0, val);
101         val = ((awb_info.gain.gb & 0x3FFF) << 16) | (awb_info.gain.gr & 0x3FFF);
102         REG_WR(ISP_AWBC_GAIN1, val);
103
104         val = ((awb_info.thrd.b & 0x3FF) << 20) | ((awb_info.thrd.g & 0x3FF) << 10) | (awb_info.thrd.r & 0x3FF);
105         REG_WR(ISP_AWBC_THRD, val);
106
107         val = ((awb_info.gain_offset.b & 0xFFFF) << 16) | (awb_info.gain_offset.r & 0xFFFF);
108         REG_WR(ISP_AWBC_OFFSET0, val);
109         val = ((awb_info.gain_offset.gb & 0xFFFF) << 16) | (awb_info.gain_offset.gr & 0xFFFF);
110         REG_WR(ISP_AWBC_OFFSET1, val);
111
112         val = ((awb_info.gain_buff.b & 0x3FFF) << 16) | (awb_info.gain_buff.r & 0x3FFF);
113         REG_WR(ISP_AWBC_GAIN0_BUF, val);
114         val = ((awb_info.gain_buff.gb & 0x3FFF) << 16) | (awb_info.gain_buff.gr & 0x3FFF);
115         REG_WR(ISP_AWBC_GAIN1_BUF, val);
116
117         val = ((awb_info.gain_offset_buff.b & 0xFFFF) << 16) | (awb_info.gain_offset_buff.r & 0xFFFF);
118         REG_WR(ISP_AWBC_OFFSET0_BUF, val);
119         val = ((awb_info.gain_offset_buff.gb & 0xFFFF) << 16) | (awb_info.gain_offset_buff.gr & 0xFFFF);
120         REG_WR(ISP_AWBC_OFFSET1_BUF, val);
121
122         return ret;
123 }
124
125 static int32_t isp_k_raw_awb_statistics(struct isp_io_param *param,
126         struct isp_k_private *isp_private)
127 {
128         int32_t ret = 0, i = 0;
129         unsigned long addr = 0;
130         struct isp_raw_awbm_statistics *awbm_statistics = NULL;
131
132         awbm_statistics = (struct isp_raw_awbm_statistics *)isp_private->raw_awbm_buf_addr;
133         if (!awbm_statistics) {
134                 ret = -1;
135                 printk("isp_k_raw_awb_statistics: alloc memory error.\n");
136                 return -1;
137         }
138
139         addr = ISP_RAW_AWBM_OUTPUT;
140
141         for (i = 0x00; i < ISP_RAW_AWBM_ITEM; i++) {
142                 (awbm_statistics + i)->num4 = REG_RD(addr) >> 16;
143                 (awbm_statistics + i)->num_t = REG_RD(addr) & 0xffff;
144                 (awbm_statistics + i)->num2 = REG_RD(addr + 4) >> 16;
145                 (awbm_statistics + i)->num3 = REG_RD(addr + 4) & 0xffff;
146                 (awbm_statistics + i)->num0 = REG_RD(addr + 8) >> 16;
147                 (awbm_statistics + i)->num1 = REG_RD(addr + 8) & 0xffff;
148                 (awbm_statistics + i)->block_b = REG_RD(addr + 12);
149                 (awbm_statistics + i)->block_g = REG_RD(addr + 16);
150                 (awbm_statistics + i)->block_r = REG_RD(addr + 20);
151                 addr += 32;
152         }
153
154         ret = copy_to_user(param->property_param, (void*)awbm_statistics, sizeof(struct isp_raw_awbm_statistics) * ISP_RAW_AWBM_ITEM);
155         if (0 != ret) {
156                 ret = -1;
157                 printk("isp_k_raw_awb_statistics: copy error, ret=0x%x\n", (uint32_t)ret);
158         }
159
160         return ret;
161 }
162
163 int32_t isp_k_cfg_awb(struct isp_io_param *param,
164         struct isp_k_private *isp_private)
165 {
166         int32_t ret = 0;
167
168         if (!param) {
169                 printk("isp_k_cfg_awb: param is null error.\n");
170                 return -1;
171         }
172
173         if (NULL == param->property_param) {
174                 printk("isp_k_cfg_awb: property_param is null error.\n");
175                 return -1;
176         }
177
178         switch(param->property) {
179         case ISP_PRO_AWB_BLOCK:
180                 ret = isp_k_awb_block(param);
181                 break;
182         case ISP_PRO_AWBM_STATISTICS:
183                 ret = isp_k_raw_awb_statistics(param, isp_private);
184                 break;
185         default:
186                 printk("isp_k_cfg_awb: fail cmd id:%d, not supported.\n", param->property);
187                 break;
188         }
189
190         return ret;
191 }