tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / media / sprd_scale / scale_drv.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 #include <linux/kernel.h>
14 #include <linux/slab.h>
15 #include <linux/interrupt.h>
16 #include <linux/bitops.h>
17 #include <linux/semaphore.h>
18 #include <linux/delay.h>
19 #include <asm/io.h>
20 #ifndef CONFIG_64BIT
21 #include <soc/sprd/hardware.h>
22 #endif
23 #include "scale_drv.h"
24 #include "gen_scale_coef.h"
25 #include "dcam_drv.h"
26
27 #define SCALE_LOWEST_ADDR 0x800
28 #define SCALE_ADDR_INVALIDE(addr) ((addr) < SCALE_LOWEST_ADDR)
29 #define SCALE_YUV_ADDR_INVALIDE(y,u,v) \
30         (SCALE_ADDR_INVALIDE(y) && \
31         SCALE_ADDR_INVALIDE(u) && \
32         SCALE_ADDR_INVALIDE(v))
33 #define SC_COEFF_H_TAB_OFFSET 0x1400
34 #define SC_COEFF_V_TAB_OFFSET 0x14F0
35 #define SC_COEFF_V_CHROMA_TAB_OFFSET 0x18F0
36 #define SC_COEFF_COEF_SIZE (1 << 10)
37 #define SC_COEFF_TMP_SIZE (21 << 10)
38 #define SC_H_COEF_SIZE (0xC0)
39 #define SC_V_COEF_SIZE (0x210)
40 #define SC_V_CHROM_COEF_SIZE (0x210)
41 #define SC_COEFF_H_NUM (SC_H_COEF_SIZE / 4)
42 #define SC_COEFF_V_NUM (SC_V_COEF_SIZE / 4)
43 #define SC_COEFF_V_CHROMA_NUM (SC_V_CHROM_COEF_SIZE / 4)
44 #define SCALE_PIXEL_ALIGNED 4
45 #define SCALE_SLICE_HEIGHT_ALIGNED 4
46
47 int scale_k_module_en(struct device_node *dn)
48 {
49         int ret = 0;
50
51         ret = dcam_get_resizer(DCAM_WAIT_FOREVER);
52         if (ret) {
53                 printk("scale_module_en, failed to get review path %d \n", ret);
54                 goto get_resizer_fail;
55         }
56
57         ret = dcam_module_en(dn);
58         if (ret) {
59                 printk("scale_module_en, failed to enable scale module %d \n", ret);
60                 goto dcam_eb_fail;
61         }
62
63         return ret;
64
65 dcam_eb_fail:
66         dcam_rel_resizer();
67 get_resizer_fail:
68         return ret;
69 }
70
71 int scale_k_module_dis(struct device_node *dn)
72 {
73         int ret = 0;
74
75         ret = dcam_module_dis(dn);
76         if (ret) {
77                 printk("scale_module_dis, failed to disable scale module %d \n", ret);
78         }
79
80         ret = dcam_rel_resizer();
81         if (ret) {
82                 printk("scale_module_dis, failed to free review path %d \n", ret);
83         }
84
85         return ret;
86 }
87
88 static int scale_k_check_deci_slice_mode(uint32_t deci_val, uint32_t slice_h)
89 {
90         int rtn = 0;
91
92         if (deci_val > 0) {
93                 if ((slice_h >= deci_val) && (0 == (slice_h % deci_val))) {
94                         rtn = 0;
95                 } else {
96                         rtn = -1;
97                 }
98         }
99         return rtn;
100 }
101
102 static int scale_k_set_sc_coeff(struct scale_path_info *path_info_ptr)
103 {
104         uint32_t i = 0;
105         unsigned long h_coeff_addr = SCALE_BASE;
106         unsigned long v_coeff_addr = SCALE_BASE;
107         unsigned long v_chroma_coeff_addr = SCALE_BASE;
108         uint32_t *tmp_buf = NULL;
109         uint32_t *h_coeff = NULL;
110         uint32_t *v_coeff = NULL;
111         uint32_t *v_chroma_coeff = NULL;
112         uint32_t scale2yuv420 = 0;
113         uint8_t y_tap = 0;
114         uint8_t uv_tap = 0;
115
116         if (!path_info_ptr) {
117                 printk("scale_k_set_sc_coeff error: path_info_ptr null \n");
118                 return -1;
119         }
120
121         tmp_buf = (uint32_t *)path_info_ptr->coeff_addr;
122         if (NULL == tmp_buf) {
123                 printk("scale_k_set_sc_coeff error: coeff mem null \n");
124                 return -1;;
125         }
126
127         h_coeff_addr += SC_COEFF_H_TAB_OFFSET;
128         v_coeff_addr += SC_COEFF_V_TAB_OFFSET;
129         v_chroma_coeff_addr += SC_COEFF_V_CHROMA_TAB_OFFSET;
130
131         if (SCALE_YUV420 == path_info_ptr->output_format)
132                 scale2yuv420 = 1;
133
134         h_coeff = tmp_buf;
135         v_coeff = tmp_buf + (SC_COEFF_COEF_SIZE/4);
136         v_chroma_coeff = v_coeff + (SC_COEFF_COEF_SIZE/4);
137
138         if (!(GenScaleCoeff((int16_t)path_info_ptr->sc_input_size.w,
139                 (int16_t)path_info_ptr->sc_input_size.h,
140                 (int16_t)path_info_ptr->output_size.w,
141                 (int16_t)path_info_ptr->output_size.h,
142                 h_coeff,
143                 v_coeff,
144                 v_chroma_coeff,
145                 scale2yuv420,
146                 &y_tap,
147                 &uv_tap,
148                 tmp_buf + (SC_COEFF_COEF_SIZE*3/4),
149                 SC_COEFF_TMP_SIZE))) {
150                 printk("scale_k_set_sc_coeff error: gen scale coeff \n");
151                 return -1;
152         }
153
154         for (i = 0; i < SC_COEFF_H_NUM; i++) {
155                 REG_WR(h_coeff_addr, *h_coeff);
156                 h_coeff_addr += 4;
157                 h_coeff++;
158         }
159
160         for (i = 0; i < SC_COEFF_V_NUM; i++) {
161                 REG_WR(v_coeff_addr, *v_coeff);
162                 v_coeff_addr += 4;
163                 v_coeff++;
164         }
165
166         for (i = 0; i < SC_COEFF_V_CHROMA_NUM; i++) {
167                 REG_WR(v_chroma_coeff_addr, *v_chroma_coeff);
168                 v_chroma_coeff_addr += 4;
169                 v_chroma_coeff++;
170         }
171
172         REG_MWR(SCALE_CFG, (BIT_19 | BIT_18 | BIT_17 | BIT_16), ((y_tap & 0x0F) << 16));
173         REG_MWR(SCALE_CFG, (BIT_15 | BIT_14 | BIT_13 | BIT_12 | BIT_11), ((uv_tap & 0x1F) << 11));
174
175         return 0;
176 }
177
178 static int scale_k_calc_sc_size(struct scale_path_info *path_info_ptr)
179 {
180         int rtn = 0;
181         uint32_t reg_val = 0;
182         uint32_t div_factor = 1;
183         uint32_t i = 0, pixel_aligned_num = 0;
184
185         if (!path_info_ptr) {
186                 printk("scale_k_calc_sc_size error: path_info_ptr null \n");
187                 return -1;
188         }
189
190         if (path_info_ptr->input_rect.w > (path_info_ptr->output_size.w * SCALE_SC_COEFF_MAX * (1 << SCALE_DECI_FAC_MAX)) ||
191                 path_info_ptr->input_rect.h > (path_info_ptr->output_size.h * SCALE_SC_COEFF_MAX * (1 << SCALE_DECI_FAC_MAX)) ||
192                 path_info_ptr->input_rect.w * SCALE_SC_COEFF_MAX < path_info_ptr->output_size.w ||
193                 path_info_ptr->input_rect.h * SCALE_SC_COEFF_MAX < path_info_ptr->output_size.h) {
194                 printk("scale_k_calc_sc_size error: input{%d %d}, output{%d %d}\n",
195                         path_info_ptr->input_rect.w, path_info_ptr->input_rect.h,
196                         path_info_ptr->output_size.w, path_info_ptr->output_size.h);
197                 rtn = -1;
198         } else {
199                 path_info_ptr->sc_input_size.w = path_info_ptr->input_rect.w;
200                 path_info_ptr->sc_input_size.h = path_info_ptr->input_rect.h;
201                 if (path_info_ptr->input_rect.w > path_info_ptr->output_size.w * SCALE_SC_COEFF_MAX ||
202                         path_info_ptr->input_rect.h > path_info_ptr->output_size.h * SCALE_SC_COEFF_MAX) {
203                         for (i = 0; i < SCALE_DECI_FAC_MAX; i++) {
204                                 div_factor = (uint32_t)(SCALE_SC_COEFF_MAX * (1 << (1 + i)));
205                                 if (path_info_ptr->input_rect.w <= (path_info_ptr->output_size.w * div_factor) &&
206                                         path_info_ptr->input_rect.h <= (path_info_ptr->output_size.h * div_factor)) {
207                                         break;
208                                 }
209                         }
210                         path_info_ptr->sc_deci_val = (1 << (1 + i));
211                         pixel_aligned_num = (path_info_ptr->sc_deci_val >= SCALE_PIXEL_ALIGNED) ? path_info_ptr->sc_deci_val : SCALE_PIXEL_ALIGNED;
212                         path_info_ptr->sc_input_size.w = path_info_ptr->input_rect.w >> (1 + i);
213                         path_info_ptr->sc_input_size.h = path_info_ptr->input_rect.h >> (1 + i);
214                         if ((path_info_ptr->sc_input_size.w % pixel_aligned_num) ||
215                                 (path_info_ptr->sc_input_size.h % pixel_aligned_num)) {
216                                 path_info_ptr->sc_input_size.w = path_info_ptr->sc_input_size.w / pixel_aligned_num * pixel_aligned_num;
217                                 path_info_ptr->sc_input_size.h = path_info_ptr->sc_input_size.h / pixel_aligned_num * pixel_aligned_num;
218                                 path_info_ptr->input_rect.w = path_info_ptr->sc_input_size.w << (1 + i);
219                                 path_info_ptr->input_rect.h = path_info_ptr->sc_input_size.h << (1 + i);
220                         }
221
222                         REG_WR(SCALE_TRIM_START, 0);
223                         reg_val = path_info_ptr->sc_input_size.w | (path_info_ptr->sc_input_size.h << 16);
224                         REG_WR(SCALE_TRIM_SIZE, reg_val);
225                         REG_WR(SCALE_SRC_SIZE, reg_val);
226
227                         REG_OWR(SCALE_REV_BURST_IN_CFG, SCALE_BURST_SUB_EB_BIT);
228                         REG_MWR(SCALE_REV_BURST_IN_CFG, SCALE_BURST_SUB_SAMPLE_MASK, (i << 13));
229                         REG_MWR(SCALE_REV_BURST_IN_CFG, SCALE_BURST_SRC_WIDTH_MASK, path_info_ptr->input_size.w);
230                         reg_val = path_info_ptr->input_rect.x | (path_info_ptr->input_rect.y << 16);
231                         REG_WR(SCALE_REV_BURST_IN_TRIM_START, reg_val);
232                         reg_val = path_info_ptr->input_rect.w | (path_info_ptr->input_rect.h << 16);
233                         REG_WR(SCALE_REV_BURST_IN_TRIM_SIZE, reg_val);
234                 }
235
236         }
237
238         return rtn;
239 }
240
241 static int scale_k_cfg_scaler(struct scale_path_info *path_info_ptr)
242 {
243         int rtn = 0;
244
245         if (!path_info_ptr) {
246                 printk("scale_k_cfg_scaler error: path_info_ptr null \n");
247                 return -1;
248         }
249
250         rtn = scale_k_calc_sc_size(path_info_ptr);
251         if (rtn) {
252                 printk("scale_k_cfg_scaler error: calc \n");
253                 return rtn;
254         }
255
256         if (path_info_ptr->sc_input_size.w != path_info_ptr->output_size.w ||
257                 path_info_ptr->sc_input_size.h != path_info_ptr->output_size.h ||
258                 SCALE_YUV420 == path_info_ptr->input_format) {
259                 REG_MWR(SCALE_CFG, SCALE_BYPASS_BIT, 0);
260                 rtn = scale_k_set_sc_coeff(path_info_ptr);
261                 if (rtn) {
262                         printk("scale_k_cfg_scaler error: coeff \n");
263                 }
264         } else {
265                 REG_OWR(SCALE_CFG, SCALE_BYPASS_BIT);
266         }
267
268         return rtn;
269 }
270
271 int scale_k_slice_cfg(struct scale_slice_param_t *cfg_ptr, struct scale_path_info *path_info_ptr)
272 {
273         int rtn = 0;
274         uint32_t reg_val = 0;
275
276         if (!cfg_ptr || !path_info_ptr) {
277                 printk("scale_k_io_cfg error: cfg_ptr=%p path_info_ptr=%p",
278                         cfg_ptr, path_info_ptr);
279                 return -1;
280         }
281
282         /*set slice scale height*/
283         if (cfg_ptr->slice_height > SCALE_FRAME_HEIGHT_MAX
284                 || (cfg_ptr->slice_height  % SCALE_SLICE_HEIGHT_ALIGNED)) {
285                 printk("scale_k_io_cfg error: slice_height:%d \n",
286                         cfg_ptr->slice_height);
287                 rtn = -1;
288                 goto cfg_exit;
289         } else {
290                 REG_MWR(SCALE_REV_SLICE_CFG, SCALE_INPUT_SLICE_HEIGHT_MASK, cfg_ptr->slice_height);
291                 path_info_ptr->slice_height = cfg_ptr->slice_height;
292         }
293
294         /*set input rect*/
295         if (cfg_ptr->input_rect.x > SCALE_FRAME_WIDTH_MAX
296                 || cfg_ptr->input_rect.y > SCALE_FRAME_HEIGHT_MAX
297                 || cfg_ptr->input_rect.w > SCALE_FRAME_WIDTH_MAX
298                 || cfg_ptr->input_rect.h > SCALE_FRAME_HEIGHT_MAX) {
299                 printk("scale_k_io_cfg error: input_rect {%d %d %d %d} \n",
300                         cfg_ptr->input_rect.x, cfg_ptr->input_rect.y,
301                         cfg_ptr->input_rect.w, cfg_ptr->input_rect.h);
302                 rtn = -1;
303                 goto cfg_exit;
304         } else {
305                 reg_val = cfg_ptr->input_rect.x | (cfg_ptr->input_rect.y << 16);
306                 REG_WR(SCALE_REV_BURST_IN_TRIM_START, reg_val);
307                 REG_WR(SCALE_TRIM_START, 0);
308                 reg_val = cfg_ptr->input_rect.w | (cfg_ptr->input_rect.h << 16);
309                 REG_WR(SCALE_REV_BURST_IN_TRIM_SIZE, reg_val);
310                 REG_WR(SCALE_TRIM_SIZE, reg_val);
311                 REG_WR(SCALE_SRC_SIZE, reg_val);
312                 memcpy((void*)&path_info_ptr->input_rect, (void*)&cfg_ptr->input_rect,
313                         sizeof(struct scale_rect_t ));
314         }
315
316         /*set input address*/
317         if (SCALE_YUV_ADDR_INVALIDE(cfg_ptr->input_addr.yaddr,
318                 cfg_ptr->input_addr.uaddr, cfg_ptr->input_addr.vaddr)) {
319                 printk("scale_k_io_cfg error: input_addr {%x %x %x} \n",
320                         cfg_ptr->input_addr.yaddr, cfg_ptr->input_addr.uaddr,
321                         cfg_ptr->input_addr.vaddr);
322                 rtn = -1;
323                 goto cfg_exit;
324         } else {
325                 REG_WR(SCALE_FRM_IN_Y, cfg_ptr->input_addr.yaddr);
326                 REG_WR(SCALE_FRM_IN_U, cfg_ptr->input_addr.uaddr);
327                 REG_WR(SCALE_FRM_IN_V, cfg_ptr->input_addr.vaddr);
328                 path_info_ptr->input_addr.yaddr = cfg_ptr->input_addr.yaddr;
329                 path_info_ptr->input_addr.uaddr = cfg_ptr->input_addr.uaddr;
330                 path_info_ptr->input_addr.vaddr = cfg_ptr->input_addr.vaddr;
331         }
332
333         /*set output address*/
334         if (SCALE_YUV_ADDR_INVALIDE(cfg_ptr->output_addr.yaddr,
335                 cfg_ptr->output_addr.uaddr, cfg_ptr->output_addr.vaddr)) {
336                 printk("scale_k_io_cfg error: output_addr {%x %x %x} \n",
337                         cfg_ptr->output_addr.yaddr, cfg_ptr->output_addr.uaddr,
338                         cfg_ptr->output_addr.vaddr);
339                 rtn = -1;
340                 goto cfg_exit;
341         } else {
342                 REG_WR(SCALE_FRM_OUT_Y, cfg_ptr->output_addr.yaddr);
343                 REG_WR(SCALE_FRM_OUT_U, cfg_ptr->output_addr.uaddr);
344                 REG_WR(SCALE_FRM_OUT_V, cfg_ptr->output_addr.vaddr);
345                 path_info_ptr->output_addr.yaddr = cfg_ptr->output_addr.yaddr;
346                 path_info_ptr->output_addr.uaddr = cfg_ptr->output_addr.uaddr;
347                 path_info_ptr->output_addr.vaddr = cfg_ptr->output_addr.vaddr;
348         }
349
350 cfg_exit:
351         return rtn;
352 }
353
354 int scale_k_frame_cfg(struct scale_frame_param_t *cfg_ptr, struct scale_path_info *path_info_ptr)
355 {
356         int rtn = 0;
357         uint32_t reg_val = 0;
358
359         if (!cfg_ptr || !path_info_ptr) {
360                 printk("scale_k_io_cfg error: cfg_ptr=%p path_info_ptr=%p",
361                         cfg_ptr, path_info_ptr);
362                 return -1;
363         }
364
365         SCALE_TRACE("scale_k_io_cfg :  input_size {%d %d} \n",
366                 cfg_ptr->input_size.w, cfg_ptr->input_size.h);
367         /*set input size*/
368         if (cfg_ptr->input_size.w > SCALE_FRAME_WIDTH_MAX
369                 || cfg_ptr->input_size.h > SCALE_FRAME_HEIGHT_MAX) {
370                 printk("scale_k_io_cfg error:  input_size {%d %d} \n",
371                         cfg_ptr->input_size.w, cfg_ptr->input_size.h);
372                 rtn = -1;
373                 goto cfg_exit;
374         } else {
375                 REG_MWR(SCALE_REV_BURST_IN_CFG, SCALE_BURST_SUB_EB_BIT, 0);
376                 REG_MWR(SCALE_REV_BURST_IN_CFG, SCALE_BURST_SUB_SAMPLE_MASK, 0);
377                 REG_MWR(SCALE_REV_BURST_IN_CFG, SCALE_BURST_SRC_WIDTH_MASK, cfg_ptr->input_size.w);
378                 path_info_ptr->input_size.w = cfg_ptr->input_size.w;
379                 path_info_ptr->input_size.h= cfg_ptr->input_size.h;
380         }
381
382         SCALE_TRACE("scale_k_io_cfg : input_rect {%d %d %d %d} \n",
383                 cfg_ptr->input_rect.x, cfg_ptr->input_rect.y,
384                 cfg_ptr->input_rect.w, cfg_ptr->input_rect.h);
385         /*set input rect*/
386         if (cfg_ptr->input_rect.x > SCALE_FRAME_WIDTH_MAX
387                 || cfg_ptr->input_rect.x > SCALE_FRAME_HEIGHT_MAX
388                 || cfg_ptr->input_rect.w > SCALE_FRAME_WIDTH_MAX
389                 || cfg_ptr->input_rect.h > SCALE_FRAME_HEIGHT_MAX) {
390                 printk("scale_k_io_cfg error: input_rect {%d %d %d %d} \n",
391                         cfg_ptr->input_rect.x, cfg_ptr->input_rect.y,
392                         cfg_ptr->input_rect.w, cfg_ptr->input_rect.h);
393                 rtn = -1;
394                 goto cfg_exit;
395         } else {
396                 reg_val = cfg_ptr->input_rect.x | (cfg_ptr->input_rect.y << 16);
397                 REG_WR(SCALE_REV_BURST_IN_TRIM_START, reg_val);
398                 REG_WR(SCALE_TRIM_START, 0);
399                 reg_val = cfg_ptr->input_rect.w | (cfg_ptr->input_rect.h << 16);
400                 REG_WR(SCALE_REV_BURST_IN_TRIM_SIZE, reg_val);
401                 REG_WR(SCALE_TRIM_SIZE, reg_val);
402                 REG_WR(SCALE_SRC_SIZE, reg_val);
403                 memcpy((void*)&path_info_ptr->input_rect, (void*)&cfg_ptr->input_rect,
404                         sizeof(struct scale_rect_t ));
405         }
406
407         SCALE_TRACE("scale_k_io_cfg : input_format:%d \n",
408                 cfg_ptr->input_format);
409         /*set input foramt*/
410         path_info_ptr->input_format = cfg_ptr->input_format;
411         if (SCALE_YUV422 == cfg_ptr->input_format
412                 || SCALE_YUV420 == cfg_ptr->input_format ||
413                 SCALE_YUV420_3FRAME == cfg_ptr->input_format) {
414                 REG_MWR(SCALE_REV_BURST_IN_CFG, SCALE_BURST_INPUT_MODE_MASK, (cfg_ptr->input_format << 16));
415         } else {
416                 printk("scale_k_io_cfg error: input_format:%d \n",
417                         cfg_ptr->input_format);
418                 rtn = -1;
419                 goto cfg_exit;
420         }
421
422         SCALE_TRACE("scale_k_io_cfg : input_addr {%x %x %x} \n",
423                 cfg_ptr->input_addr.yaddr, cfg_ptr->input_addr.uaddr,
424                 cfg_ptr->input_addr.vaddr);
425         /*set input address*/
426         if (SCALE_YUV_ADDR_INVALIDE(cfg_ptr->input_addr.yaddr,
427                 cfg_ptr->input_addr.uaddr, cfg_ptr->input_addr.vaddr)) {
428                 printk("scale_k_io_cfg error: input_addr {%x %x %x} \n",
429                         cfg_ptr->input_addr.yaddr, cfg_ptr->input_addr.uaddr,
430                         cfg_ptr->input_addr.vaddr);
431                 rtn = -1;
432                 goto cfg_exit;
433         } else {
434                 REG_WR(SCALE_FRM_IN_Y, cfg_ptr->input_addr.yaddr);
435                 REG_WR(SCALE_FRM_IN_U, cfg_ptr->input_addr.uaddr);
436                 REG_WR(SCALE_FRM_IN_V, cfg_ptr->input_addr.vaddr);
437                 path_info_ptr->input_addr.yaddr = cfg_ptr->input_addr.yaddr;
438                 path_info_ptr->input_addr.uaddr = cfg_ptr->input_addr.uaddr;
439                 path_info_ptr->input_addr.vaddr = cfg_ptr->input_addr.vaddr;
440         }
441
442         SCALE_TRACE("scale_k_io_cfg : input_endian {%d %d} \n",
443                 cfg_ptr->input_endian.y_endian, cfg_ptr->input_endian.uv_endian);
444         /*set input endian*/
445         if (cfg_ptr->input_endian.y_endian >= SCALE_ENDIAN_MAX
446                 ||cfg_ptr->input_endian.uv_endian >= SCALE_ENDIAN_MAX) {
447                 printk("scale_k_io_cfg error: input_endian {%d %d} \n",
448                         cfg_ptr->input_endian.y_endian, cfg_ptr->input_endian.uv_endian);
449                 rtn = -1;
450                 goto cfg_exit;
451         } else {
452                 cfg_ptr->input_endian.uv_endian = cfg_ptr->input_endian.y_endian;
453                 dcam_glb_reg_owr(SCALE_ENDIAN_SEL,(SCALE_AXI_RD_ENDIAN_BIT | SCALE_AXI_WR_ENDIAN_BIT), DCAM_ENDIAN_REG);
454                 dcam_glb_reg_mwr(SCALE_ENDIAN_SEL, SCALE_INPUT_Y_ENDIAN_MASK, cfg_ptr->input_endian.y_endian, DCAM_ENDIAN_REG);
455                 dcam_glb_reg_mwr(SCALE_ENDIAN_SEL, SCALE_INPUT_UV_ENDIAN_MASK, (cfg_ptr->input_endian.uv_endian << 2), DCAM_ENDIAN_REG);
456                 SCALE_TRACE("scale_k_io_cfg: output_endian {%d %d} 0x%x \n",
457                         cfg_ptr->input_endian.y_endian, cfg_ptr->input_endian.uv_endian, REG_RD(SCALE_ENDIAN_SEL));
458         }
459
460         SCALE_TRACE("scale_k_io_cfg: output_size {%d %d} \n",
461                 cfg_ptr->output_size.w, cfg_ptr->output_size.h);
462
463         /*set output size*/
464         if (cfg_ptr->output_size.w > SCALE_FRAME_WIDTH_MAX ||
465                 cfg_ptr->output_size.h > SCALE_FRAME_HEIGHT_MAX) {
466                 printk("scale_k_io_cfg error: output_size {%d %d} \n",
467                         cfg_ptr->output_size.w, cfg_ptr->output_size.h);
468                 rtn = -1;
469                 goto cfg_exit;
470         } else {
471                 reg_val = cfg_ptr->output_size.w | (cfg_ptr->output_size.h << 16);
472                 REG_WR(SCALE_DST_SIZE, reg_val);
473                 path_info_ptr->output_size.w = cfg_ptr->output_size.w;
474                 path_info_ptr->output_size.h = cfg_ptr->output_size.h;
475         }
476
477         SCALE_TRACE("scale_k_io_cfg: output_format:%d \n",
478                 cfg_ptr->output_format);
479
480         /*set output format*/
481         path_info_ptr->output_format = cfg_ptr->output_format;
482         if (SCALE_YUV422 == cfg_ptr->output_format) {
483                 REG_MWR(SCALE_CFG, SCALE_OUTPUT_MODE_MASK, (0 << 6));
484         } else if (SCALE_YUV420 == cfg_ptr->output_format) {
485                 REG_MWR(SCALE_CFG, SCALE_OUTPUT_MODE_MASK, (1 << 6));
486         } else if (SCALE_YUV420_3FRAME == cfg_ptr->output_format) {
487                 REG_MWR(SCALE_CFG, SCALE_OUTPUT_MODE_MASK, (3 << 6));
488         } else {
489                 printk("scale_k_io_cfg error: output_format:%d \n",
490                         cfg_ptr->output_format);
491                 rtn = -1;
492                 goto cfg_exit;
493         }
494
495         SCALE_TRACE("scale_k_io_cfg : output_addr {%x %x %x} \n",
496                 cfg_ptr->output_addr.yaddr, cfg_ptr->output_addr.uaddr,
497                 cfg_ptr->output_addr.vaddr);
498
499         /*set output address*/
500         if (SCALE_YUV_ADDR_INVALIDE(cfg_ptr->output_addr.yaddr,
501                 cfg_ptr->output_addr.uaddr, cfg_ptr->output_addr.vaddr)) {
502                 printk("scale_k_io_cfg error: output_addr {%x %x %x} \n",
503                         cfg_ptr->output_addr.yaddr, cfg_ptr->output_addr.uaddr,
504                         cfg_ptr->output_addr.vaddr);
505                 rtn = -1;
506                 goto cfg_exit;
507         } else {
508                 REG_WR(SCALE_FRM_OUT_Y, cfg_ptr->output_addr.yaddr);
509                 REG_WR(SCALE_FRM_OUT_U, cfg_ptr->output_addr.uaddr);
510                 REG_WR(SCALE_FRM_OUT_V, cfg_ptr->output_addr.vaddr);
511                 path_info_ptr->output_addr.yaddr = cfg_ptr->output_addr.yaddr;
512                 path_info_ptr->output_addr.uaddr = cfg_ptr->output_addr.uaddr;
513                 path_info_ptr->output_addr.vaddr = cfg_ptr->output_addr.vaddr;
514         }
515
516         SCALE_TRACE("scale_k_io_cfg: output_endian {%d %d} \n",
517                 cfg_ptr->output_endian.y_endian, cfg_ptr->output_endian.uv_endian);
518
519         /*set output endian*/
520         if (cfg_ptr->output_endian.y_endian >= SCALE_ENDIAN_MAX ||
521                 cfg_ptr->output_endian.uv_endian >= SCALE_ENDIAN_MAX) {
522                 printk("scale_k_io_cfg error: output_endian {%d %d} \n",
523                         cfg_ptr->output_endian.y_endian, cfg_ptr->output_endian.uv_endian);
524                 rtn = -1;
525                 goto cfg_exit;
526         } else {
527                 cfg_ptr->output_endian.uv_endian = cfg_ptr->output_endian.y_endian;
528                 dcam_glb_reg_owr(SCALE_ENDIAN_SEL,(SCALE_AXI_RD_ENDIAN_BIT|SCALE_AXI_WR_ENDIAN_BIT), DCAM_ENDIAN_REG);
529                 dcam_glb_reg_mwr(SCALE_ENDIAN_SEL, SCALE_OUTPUT_Y_ENDIAN_MASK, (cfg_ptr->output_endian.y_endian << 10), DCAM_ENDIAN_REG);
530                 dcam_glb_reg_mwr(SCALE_ENDIAN_SEL, SCALE_OUTPUT_UV_ENDIAN_MASK, (cfg_ptr->output_endian.uv_endian<< 12), DCAM_ENDIAN_REG);
531                 SCALE_TRACE("scale_k_io_cfg: output_endian {%d %d} 0x%x \n",
532                         cfg_ptr->output_endian.y_endian, cfg_ptr->output_endian.uv_endian, REG_RD(SCALE_ENDIAN_SEL));
533         }
534
535         SCALE_TRACE("scale_k_io_cfg: scale_mode:%d \n",
536                 cfg_ptr->scale_mode);
537
538         /*set scale mode*/
539         if (cfg_ptr->scale_mode >= SCALE_MODE_MAX) {
540                 printk("scale_k_io_cfg error: scale_mode:%d \n",
541                         cfg_ptr->scale_mode);
542                 rtn = -1;
543                 goto cfg_exit;
544         } else {
545                 if (SCALE_MODE_NORMAL == cfg_ptr->scale_mode) {
546                         REG_MWR(SCALE_CFG, SCALE_MODE_MASK, SCALE_MODE_NORMAL_TYPE);
547                 } else if(SCALE_MODE_SLICE == cfg_ptr->scale_mode) {
548                         REG_MWR(SCALE_CFG, SCALE_MODE_MASK, SCALE_MODE_SLICE_TYPE);
549                         REG_MWR(SCALE_REV_SLICE_CFG, SCALE_SLICE_TYPE_BIT, 0);
550                 }else{
551                         REG_MWR(SCALE_CFG, SCALE_MODE_MASK, SCALE_MODE_SLICE_TYPE);
552                         REG_OWR(SCALE_REV_SLICE_CFG, SCALE_SLICE_TYPE_BIT);
553                 }
554                 path_info_ptr->scale_mode = cfg_ptr->scale_mode;
555         }
556
557         /*set slice scale height*/
558         if (SCALE_MODE_SLICE == cfg_ptr->scale_mode
559                 || SCALE_MODE_SLICE_READDR ==cfg_ptr->scale_mode) {
560                 if (cfg_ptr->slice_height > SCALE_FRAME_HEIGHT_MAX
561                         || (cfg_ptr->slice_height  % SCALE_SLICE_HEIGHT_ALIGNED)) {
562                         printk("scale_k_io_cfg error: slice_height:%d \n",
563                                 cfg_ptr->slice_height);
564                         rtn = -1;
565                         goto cfg_exit;
566                 } else {
567                         REG_MWR(SCALE_REV_SLICE_CFG, SCALE_INPUT_SLICE_HEIGHT_MASK, cfg_ptr->slice_height);
568                         path_info_ptr->slice_height = cfg_ptr->slice_height;
569                 }
570         }
571
572 cfg_exit:
573         return rtn;
574 }
575
576 int scale_k_start(struct scale_frame_param_t *cfg_ptr, struct scale_path_info *path_info_ptr)
577 {
578         int rtn = 0;
579
580         if (!path_info_ptr) {
581                 printk("scale_k_start error: path_info_ptr null \n");
582                 return -1;
583         }
584
585         dcam_resize_start();
586
587         rtn = scale_k_frame_cfg(cfg_ptr, path_info_ptr);
588         if (rtn) {
589                 printk("scale_k_start error: frame cfg \n");
590                 goto start_exit;
591         }
592
593         if (SCALE_MODE_NORMAL == path_info_ptr->scale_mode) {
594                 if (path_info_ptr->output_size.w > SCALE_FRAME_WIDTH_MAX) {
595                         rtn = -1;
596                         printk("scale_k_start error: frame output_size_w=%d \n",
597                                 path_info_ptr->output_size.w);
598                         goto start_exit;
599                 }
600         } else {
601                 if (path_info_ptr->output_size.w > SCALE_LINE_BUF_LENGTH) {
602                         rtn = -1;
603                         printk("scale_k_start error: frame output_size_w=%d \n",
604                                 path_info_ptr->output_size.w);
605                         goto start_exit;
606                 }
607         }
608
609         path_info_ptr->slice_in_height = 0;
610         path_info_ptr->slice_out_height = 0;
611         path_info_ptr->is_last_slice = 0;
612         path_info_ptr->sc_deci_val = 0;
613
614         REG_MWR(SCALE_CFG, (SCALE_DEC_X_EB_BIT|SCALE_DEC_Y_EB_BIT), 0);
615
616         rtn = scale_k_cfg_scaler(path_info_ptr);
617         if (rtn) {
618                 printk("scale_k_start error: cfg \n");
619                 goto start_exit;
620         }
621
622         if (SCALE_MODE_NORMAL != path_info_ptr->scale_mode) {
623                 path_info_ptr->slice_in_height += path_info_ptr->slice_height;
624                 rtn = scale_k_check_deci_slice_mode(path_info_ptr->sc_deci_val, path_info_ptr->slice_height);
625                 if (rtn) goto start_exit;
626         }
627         dcam_glb_reg_mwr(SCALE_BASE, SCALE_PATH_MASK, SCALE_PATH_SELECT, DCAM_CFG_REG);
628         dcam_glb_reg_owr(SCALE_BASE, SCALE_PATH_EB_BIT, DCAM_CFG_REG);
629
630         dcam_glb_reg_owr(SCALE_CTRL, (SCALE_FRC_COPY_BIT|SCALE_COEFF_FRC_COPY_BIT), DCAM_CONTROL_REG);
631         REG_OWR(SCALE_REV_BURST_IN_CFG, SCALE_START_BIT);
632         printk("scale_k_start\n");
633         return rtn;
634
635 start_exit:
636         dcam_resize_end();
637         SCALE_TRACE("scale_k_start error: ret=%d \n", rtn);
638         return rtn;
639 }
640
641 int scale_k_continue(struct scale_slice_param_t *cfg_ptr, struct scale_path_info *path_info_ptr)
642 {
643         int rtn = 0;
644         uint32_t slice_h = 0;
645
646         if (!path_info_ptr) {
647                 printk("scale_k_continue error: path_info_ptr null \n");
648                 return -1;
649         }
650
651         rtn = scale_k_slice_cfg(cfg_ptr, path_info_ptr);
652         if (rtn) {
653                 printk("rot_k_ioctl error: slice cfg \n");
654                 return -1;
655         }
656
657
658         SCALE_TRACE("scale_k_continue: { %d, %d, %d} \n",
659                 path_info_ptr->slice_height, path_info_ptr->slice_in_height, path_info_ptr->scale_mode);
660
661         if (SCALE_MODE_NORMAL != path_info_ptr->scale_mode) {
662                 if (path_info_ptr->slice_in_height + path_info_ptr->slice_height >= path_info_ptr->input_rect.h) {
663                         slice_h = path_info_ptr->input_rect.h - path_info_ptr->slice_in_height;
664                         if (scale_k_check_deci_slice_mode(path_info_ptr->sc_deci_val, slice_h)) {
665                                 printk("scale_k_continue error: check deci \n");
666                                 return -1;
667                         }
668                         path_info_ptr->is_last_slice = 1;
669                         REG_MWR(SCALE_REV_SLICE_CFG, SCALE_INPUT_SLICE_HEIGHT_MASK, slice_h);
670                         REG_OWR(SCALE_REV_SLICE_CFG, SCALE_IS_LAST_SLICE_BIT);
671                 } else {
672                         path_info_ptr->is_last_slice = 0;
673                         REG_MWR(SCALE_REV_SLICE_CFG, SCALE_IS_LAST_SLICE_BIT, 0);
674                 }
675                 path_info_ptr->slice_in_height += path_info_ptr->slice_height;
676         }
677
678         dcam_glb_reg_owr(SCALE_CTRL, SCALE_START_BIT, DCAM_CONTROL_REG);
679
680         return rtn;
681 }
682
683 int scale_k_stop(void)
684 {
685         int rtn = 0;
686
687         dcam_glb_reg_mwr(SCALE_BASE, SCALE_PATH_EB_BIT, 0, DCAM_CFG_REG);
688
689         return rtn;
690 }
691
692 int scale_k_isr(struct dcam_frame* dcam_frm, void* u_data)
693 {
694         unsigned long flag;
695         scale_isr_func user_isr_func;
696         struct scale_drv_private *private = (struct scale_drv_private *)u_data;
697         struct scale_path_info *path_info_ptr;
698         struct scale_frame_info_t *frm_info_ptr;
699
700         if (!private) {
701                 printk("scale_k_isr error: private null \n");
702                 goto isr_exit;
703         }
704
705         user_isr_func = private->user_isr_func;
706         if (!user_isr_func) {
707                 printk("scale_k_isr error: user_isr_func null \n");
708                 goto isr_exit;
709         }
710         path_info_ptr = &private->path_info;
711         frm_info_ptr = &private->frm_info;
712
713         spin_lock_irqsave(&private->scale_drv_lock, flag);
714
715         memset(frm_info_ptr, 0, sizeof(struct scale_frame_info_t));
716         frm_info_ptr->yaddr = path_info_ptr->output_addr.yaddr;
717         frm_info_ptr->uaddr = path_info_ptr->output_addr.uaddr;
718         frm_info_ptr->vaddr = path_info_ptr->output_addr.vaddr;
719         frm_info_ptr->width = path_info_ptr->output_size.w;
720         if (SCALE_MODE_NORMAL != path_info_ptr->scale_mode) {
721                 frm_info_ptr->height_uv = REG_RD(SCALE_REV_SLICE_O_VCNT);
722                 frm_info_ptr->height_uv = (frm_info_ptr->height_uv >> 16) & SCALE_OUTPUT_SLICE_HEIGHT_MASK;
723                 frm_info_ptr->height = REG_RD(SCALE_REV_SLICE_O_VCNT);
724                 frm_info_ptr->height = frm_info_ptr->height & SCALE_OUTPUT_SLICE_HEIGHT_MASK;
725                 path_info_ptr->slice_out_height += frm_info_ptr->height;
726         } else {
727                 frm_info_ptr->height = path_info_ptr->output_size.h;
728         }
729
730         if (path_info_ptr->is_wait_stop) {
731                 up(&path_info_ptr->done_sem);
732                 path_info_ptr->is_wait_stop = 0;
733         }
734         if (SCALE_MODE_NORMAL == path_info_ptr->scale_mode ||
735                 (SCALE_MODE_NORMAL != path_info_ptr->scale_mode && path_info_ptr->output_size.h == path_info_ptr->slice_out_height)) {
736                 printk("begin to dcam_resize_end\n");
737                 dcam_resize_end();
738         }
739         user_isr_func(private->scale_fd);
740         spin_unlock_irqrestore(&private->scale_drv_lock, flag);
741
742 isr_exit:
743         return 0;
744 }
745
746 int scale_k_isr_reg(scale_isr_func user_func, struct scale_drv_private *drv_private)
747 {
748         int rtn = 0;
749         unsigned long flag;
750
751         if (user_func) {
752                 if (!drv_private) {
753                         rtn = -1;
754                         printk("scale_reg_isr Failed \n");
755                         goto reg_exit;
756                 }
757
758                 spin_lock_irqsave(&drv_private->scale_drv_lock, flag);
759                 drv_private->user_isr_func = user_func;
760                 spin_unlock_irqrestore(&drv_private->scale_drv_lock, flag);
761
762                 dcam_reg_isr(DCAM_PATH2_DONE, scale_k_isr, (void *)drv_private);
763         } else {
764                 dcam_reg_isr(DCAM_PATH2_DONE, NULL, NULL);
765         }
766
767 reg_exit:
768         return rtn;
769 }