tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / media / sprd_isp / isp2.0 / sharkl / src / isp_k_2d_lsc.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 <linux/delay.h>
17 #include <video/sprd_isp.h>
18 #include <asm/cacheflush.h>
19 #include "isp_block.h"
20 #include "isp_reg.h"
21 #include "isp_drv.h"
22
23 #define ISP_LSC_TIME_OUT_MAX        500
24 #define ISP_LSC_BUF0                0
25 #define ISP_LSC_BUF1                1
26
27 static int32_t isp_k_2d_lsc_param_load(struct isp_memory *src_buf,
28                 struct isp_k_private *isp_private)
29 {
30         int32_t ret = 0;
31         uint32_t time_out_cnt = 0;
32         uint32_t addr = 0, reg_value = 0;
33         void *buf_ptr = (void *)isp_private->lsc_buf_addr;
34         uint32_t buf_len = isp_private->lsc_buf_len;
35
36         if ((0x00 != src_buf->addr) && (0x00 != src_buf->len)
37                 && (00 != isp_private->lsc_buf_addr) && (0x00 != isp_private->lsc_buf_len)
38                 && (src_buf->len <= isp_private->lsc_buf_len)) {
39
40                 ret = copy_from_user((void *)isp_private->lsc_buf_addr, (void *)src_buf->addr, src_buf->len);
41                 if ( 0 != ret) {
42                         printk("isp_k_2d_lsc_param_load: copy error, ret=0x%x\n", (uint32_t)ret);
43                         return -1;
44                 }
45
46                 dmac_flush_range(buf_ptr, buf_ptr + buf_len);
47                 outer_flush_range(__pa(buf_ptr), __pa(buf_ptr) + buf_len);
48
49                 addr = (uint32_t)__pa(isp_private->lsc_buf_addr);
50
51 #if defined(CONFIG_MACH_CORE3)
52                 {
53                         unsigned long flags;
54
55                         local_irq_save(flags);
56
57                         reg_value = REG_RD(ISP_LSC_STATUS);
58                         while((0x00 == (reg_value & ISP_LNC_STATUS_OK))
59                                 && (time_out_cnt < (ISP_LSC_TIME_OUT_MAX * 1000))) {
60                                 udelay(1);
61                                 reg_value = REG_RD(ISP_LSC_STATUS);
62                                 time_out_cnt++;
63                         }
64                         if (time_out_cnt >= (ISP_LSC_TIME_OUT_MAX * 1000)) {
65                                 ret = -1;
66                                 printk("isp_k_2d_lsc_param_load: lsc status time out error.\n");
67                         }
68
69                         if (ISP_LSC_BUF0 = isp_private->lsc_load_buf_id) {
70                                 isp_private->lsc_load_buf_id = ISP_LSC_BUF1;
71                         } else {
72                                 isp_private->lsc_load_buf_id = ISP_LSC_BUF0;
73                         }
74                         REG_MWR(ISP_LSC_LOAD_BUF, BIT_0, isp_private->lsc_load_buf_id);
75                         REG_WR(ISP_LSC_PARAM_ADDR, addr);
76                         REG_OWR(ISP_LSC_LOAD_EB, BIT_0);
77                         isp_private->lsc_update_buf_id = isp_private->lsc_load_buf_id;
78
79                         local_irq_restore(flags);
80                 }
81 #else
82                 if (ISP_LSC_BUF0 == isp_private->lsc_load_buf_id) {
83                         isp_private->lsc_load_buf_id = ISP_LSC_BUF1;
84                 } else {
85                         isp_private->lsc_load_buf_id = ISP_LSC_BUF0;
86                 }
87                 REG_MWR(ISP_LSC_LOAD_BUF, BIT_0, isp_private->lsc_load_buf_id);
88                 REG_WR(ISP_LSC_PARAM_ADDR, addr);
89                 REG_OWR(ISP_LSC_LOAD_EB, BIT_0);
90                 isp_private->lsc_update_buf_id = isp_private->lsc_load_buf_id;
91 #endif
92                 reg_value = REG_RD(ISP_INT_RAW);
93
94                 while ((0x00 == (reg_value & ISP_INT_LSC_LOAD))
95                         && (time_out_cnt < ISP_LSC_TIME_OUT_MAX)) {
96                         udelay(1);
97                         reg_value = REG_RD(ISP_INT_RAW);
98                         time_out_cnt++;
99                 }
100                 if (time_out_cnt >= ISP_LSC_TIME_OUT_MAX) {
101                         ret = -1;
102                         printk("isp_k_2d_lsc_param_load: lsc load time out error.\n");
103                 }
104                 REG_OWR(ISP_INT_CLEAR, ISP_INT_LSC_LOAD);
105         } else {
106                 printk("isp_k_2d_lsc_param_load: buffer error.\n");
107         }
108
109         return ret;
110 }
111
112 static int32_t isp_k_2d_lsc_block(struct isp_io_param *param,
113                 struct isp_k_private *isp_private)
114 {
115         int32_t ret = 0;
116         struct isp_memory src_buf;
117         struct isp_dev_lsc_info lsc_info;
118
119         memset(&lsc_info, 0x00, sizeof(lsc_info));
120
121         ret = copy_from_user((void *)&lsc_info, param->property_param, sizeof(lsc_info));
122         if (0 != ret) {
123                 printk("isp_k_2d_lsc_block: copy error, ret=0x%x\n", (uint32_t)ret);
124                 return -1;
125         }
126
127         if (lsc_info.bypass) {
128                 REG_OWR(ISP_LSC_PARAM, BIT_0);
129         } else {
130                 REG_MWR(ISP_LSC_PARAM, BIT_0, 0);
131         }
132
133         REG_MWR(ISP_LSC_GRID_PITCH, 0x1FF, lsc_info.grid_pitch);
134
135         REG_MWR(ISP_LSC_GRID_PITCH, (BIT_17 | BIT_16), (lsc_info.grid_mode << 16));
136
137         REG_MWR(ISP_LSC_MISC, (BIT_1 | BIT_0), lsc_info.endian);
138
139         src_buf.addr = lsc_info.buf_addr;
140         src_buf.len = lsc_info.buf_len;
141         ret = isp_k_2d_lsc_param_load(&src_buf, isp_private);
142
143         return ret;
144 }
145
146 static int32_t isp_k_lsc_bypass(struct isp_io_param *param)
147 {
148         int32_t ret = 0;
149         uint32_t bypass = 0;
150
151         ret = copy_from_user((void *)&bypass, param->property_param, sizeof(bypass));
152         if (0 != ret) {
153                 printk("isp_k_lsc_bypass: copy error, ret=0x%x\n", (uint32_t)ret);
154                 return -1;
155         }
156
157         if (bypass) {
158                 REG_OWR(ISP_LSC_PARAM, BIT_0);
159         } else {
160                 REG_MWR(ISP_LSC_PARAM, BIT_0, 0);
161         }
162
163         return ret;
164 }
165
166 static int32_t isp_k_2d_lsc_param_update(struct isp_io_param *param,
167                 struct isp_k_private *isp_private)
168 {
169         int32_t ret = 0;
170
171         REG_MWR(ISP_LSC_PARAM, BIT_1, (isp_private->lsc_update_buf_id << 1));
172
173         return ret;
174 }
175
176 static int32_t isp_k_2d_lsc_pos(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_lens_pos: copy error, ret=0x%x\n", (uint32_t)ret);
185                 return -1;
186         }
187
188         val = ((offset.y & 0x7F) << 8) | (offset.x & 0x7F);
189
190         REG_WR(ISP_LSC_SLICE_POS, val);
191
192         return ret;
193 }
194
195 static int32_t isp_k_2d_lsc_grid_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_2d_lsc_grid_size: copy error, ret=0x%x\n", (uint32_t)ret);
204                 return -1;
205         }
206
207         val = ((size.height & 0xFFFF) << 16) | (size.width & 0xFFFF);
208         REG_WR(ISP_LSC_GRID_SIZE, val);
209
210         return ret;
211 }
212
213 static int32_t isp_k_2d_lsc_slice_size(struct isp_io_param *param)
214 {
215         int32_t ret = 0;
216         uint32_t val = 0;
217         struct isp_img_size size = {0, 0};
218
219         ret = copy_from_user((void *)&size, param->property_param, sizeof(size));
220         if (0 != ret) {
221                 printk("isp_k_2d_lsc_slice_size: copy error, ret=0x%x\n", (uint32_t)ret);
222                 return -1;
223         }
224
225         val = ((size.height & 0xFFFF) << 16) | (size.width & 0xFFFF);
226
227         REG_WR(ISP_LSC_SLICE_SIZE, val);
228
229         return ret;
230 }
231
232 int32_t isp_k_cfg_2d_lsc(struct isp_io_param *param,
233                 struct isp_k_private *isp_private)
234 {
235         int32_t ret = 0;
236
237         if (!param) {
238                 printk("isp_k_cfg_2d_lsc: param is null error.\n");
239                 return -1;
240         }
241
242         if (NULL == param->property_param) {
243                 printk("isp_k_cfg_2d_lsc: property_param is null error.\n");
244                 return -1;
245         }
246
247         switch(param->property) {
248         case ISP_PRO_2D_LSC_BLOCK:
249                 ret = isp_k_2d_lsc_block(param, isp_private);
250                 break;
251         case ISP_PRO_2D_LSC_BYPASS:
252                 ret = isp_k_lsc_bypass(param);
253                 break;
254         case ISP_PRO_2D_LSC_PARAM_UPDATE:
255                 ret = isp_k_2d_lsc_param_update(param, isp_private);
256                 break;
257         case ISP_PRO_2D_LSC_POS:
258                 ret = isp_k_2d_lsc_pos(param);
259                 break;
260         case ISP_PRO_2D_LSC_GRID_SIZE:
261                 ret = isp_k_2d_lsc_grid_size(param);
262                 break;
263         case ISP_PRO_2D_LSC_SLICE_SIZE:
264                 ret = isp_k_2d_lsc_slice_size(param);
265                 break;
266         default:
267                 printk("isp_k_cfg_2d_lsc: fail cmd id:%d, not supported.\n", param->property);
268                 break;
269         }
270
271         return ret;
272 }