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.
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>
21 #include <soc/sprd/hardware.h>
23 #include "scale_drv.h"
24 #include "gen_scale_coef.h"
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
47 int scale_k_module_en(struct device_node *dn)
51 ret = dcam_get_resizer(DCAM_WAIT_FOREVER);
53 printk("scale_module_en, failed to get review path %d \n", ret);
54 goto get_resizer_fail;
57 ret = dcam_module_en(dn);
59 printk("scale_module_en, failed to enable scale module %d \n", ret);
71 int scale_k_module_dis(struct device_node *dn)
75 ret = dcam_module_dis(dn);
77 printk("scale_module_dis, failed to disable scale module %d \n", ret);
80 ret = dcam_rel_resizer();
82 printk("scale_module_dis, failed to free review path %d \n", ret);
88 static int scale_k_check_deci_slice_mode(uint32_t deci_val, uint32_t slice_h)
93 if ((slice_h >= deci_val) && (0 == (slice_h % deci_val))) {
102 static int scale_k_set_sc_coeff(struct scale_path_info *path_info_ptr)
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;
116 if (!path_info_ptr) {
117 printk("scale_k_set_sc_coeff error: path_info_ptr null \n");
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");
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;
131 if (SCALE_YUV420 == path_info_ptr->output_format)
135 v_coeff = tmp_buf + (SC_COEFF_COEF_SIZE/4);
136 v_chroma_coeff = v_coeff + (SC_COEFF_COEF_SIZE/4);
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,
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");
154 for (i = 0; i < SC_COEFF_H_NUM; i++) {
155 REG_WR(h_coeff_addr, *h_coeff);
160 for (i = 0; i < SC_COEFF_V_NUM; i++) {
161 REG_WR(v_coeff_addr, *v_coeff);
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;
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));
178 static int scale_k_calc_sc_size(struct scale_path_info *path_info_ptr)
181 uint32_t reg_val = 0;
182 uint32_t div_factor = 1;
183 uint32_t i = 0, pixel_aligned_num = 0;
185 if (!path_info_ptr) {
186 printk("scale_k_calc_sc_size error: path_info_ptr null \n");
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);
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)) {
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);
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);
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);
241 static int scale_k_cfg_scaler(struct scale_path_info *path_info_ptr)
245 if (!path_info_ptr) {
246 printk("scale_k_cfg_scaler error: path_info_ptr null \n");
250 rtn = scale_k_calc_sc_size(path_info_ptr);
252 printk("scale_k_cfg_scaler error: calc \n");
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);
262 printk("scale_k_cfg_scaler error: coeff \n");
265 REG_OWR(SCALE_CFG, SCALE_BYPASS_BIT);
271 int scale_k_slice_cfg(struct scale_slice_param_t *cfg_ptr, struct scale_path_info *path_info_ptr)
274 uint32_t reg_val = 0;
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);
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);
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;
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);
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 ));
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);
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;
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);
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;
354 int scale_k_frame_cfg(struct scale_frame_param_t *cfg_ptr, struct scale_path_info *path_info_ptr)
357 uint32_t reg_val = 0;
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);
365 SCALE_TRACE("scale_k_io_cfg : input_size {%d %d} \n",
366 cfg_ptr->input_size.w, cfg_ptr->input_size.h);
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);
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;
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);
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);
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 ));
407 SCALE_TRACE("scale_k_io_cfg : input_format:%d \n",
408 cfg_ptr->input_format);
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));
416 printk("scale_k_io_cfg error: input_format:%d \n",
417 cfg_ptr->input_format);
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);
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;
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);
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);
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));
460 SCALE_TRACE("scale_k_io_cfg: output_size {%d %d} \n",
461 cfg_ptr->output_size.w, cfg_ptr->output_size.h);
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);
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;
477 SCALE_TRACE("scale_k_io_cfg: output_format:%d \n",
478 cfg_ptr->output_format);
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));
489 printk("scale_k_io_cfg error: output_format:%d \n",
490 cfg_ptr->output_format);
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);
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);
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;
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);
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);
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));
535 SCALE_TRACE("scale_k_io_cfg: scale_mode:%d \n",
536 cfg_ptr->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);
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);
551 REG_MWR(SCALE_CFG, SCALE_MODE_MASK, SCALE_MODE_SLICE_TYPE);
552 REG_OWR(SCALE_REV_SLICE_CFG, SCALE_SLICE_TYPE_BIT);
554 path_info_ptr->scale_mode = cfg_ptr->scale_mode;
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);
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;
576 int scale_k_start(struct scale_frame_param_t *cfg_ptr, struct scale_path_info *path_info_ptr)
580 if (!path_info_ptr) {
581 printk("scale_k_start error: path_info_ptr null \n");
587 rtn = scale_k_frame_cfg(cfg_ptr, path_info_ptr);
589 printk("scale_k_start error: frame cfg \n");
593 if (SCALE_MODE_NORMAL == path_info_ptr->scale_mode) {
594 if (path_info_ptr->output_size.w > SCALE_FRAME_WIDTH_MAX) {
596 printk("scale_k_start error: frame output_size_w=%d \n",
597 path_info_ptr->output_size.w);
601 if (path_info_ptr->output_size.w > SCALE_LINE_BUF_LENGTH) {
603 printk("scale_k_start error: frame output_size_w=%d \n",
604 path_info_ptr->output_size.w);
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;
614 REG_MWR(SCALE_CFG, (SCALE_DEC_X_EB_BIT|SCALE_DEC_Y_EB_BIT), 0);
616 rtn = scale_k_cfg_scaler(path_info_ptr);
618 printk("scale_k_start error: cfg \n");
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;
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);
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");
637 SCALE_TRACE("scale_k_start error: ret=%d \n", rtn);
641 int scale_k_continue(struct scale_slice_param_t *cfg_ptr, struct scale_path_info *path_info_ptr)
644 uint32_t slice_h = 0;
646 if (!path_info_ptr) {
647 printk("scale_k_continue error: path_info_ptr null \n");
651 rtn = scale_k_slice_cfg(cfg_ptr, path_info_ptr);
653 printk("rot_k_ioctl error: slice cfg \n");
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);
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");
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);
672 path_info_ptr->is_last_slice = 0;
673 REG_MWR(SCALE_REV_SLICE_CFG, SCALE_IS_LAST_SLICE_BIT, 0);
675 path_info_ptr->slice_in_height += path_info_ptr->slice_height;
678 dcam_glb_reg_owr(SCALE_CTRL, SCALE_START_BIT, DCAM_CONTROL_REG);
683 int scale_k_stop(void)
687 dcam_glb_reg_mwr(SCALE_BASE, SCALE_PATH_EB_BIT, 0, DCAM_CFG_REG);
692 int scale_k_isr(struct dcam_frame* dcam_frm, void* u_data)
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;
701 printk("scale_k_isr error: private null \n");
705 user_isr_func = private->user_isr_func;
706 if (!user_isr_func) {
707 printk("scale_k_isr error: user_isr_func null \n");
710 path_info_ptr = &private->path_info;
711 frm_info_ptr = &private->frm_info;
713 spin_lock_irqsave(&private->scale_drv_lock, flag);
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;
727 frm_info_ptr->height = path_info_ptr->output_size.h;
730 if (path_info_ptr->is_wait_stop) {
731 up(&path_info_ptr->done_sem);
732 path_info_ptr->is_wait_stop = 0;
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");
739 user_isr_func(private->scale_fd);
740 spin_unlock_irqrestore(&private->scale_drv_lock, flag);
746 int scale_k_isr_reg(scale_isr_func user_func, struct scale_drv_private *drv_private)
754 printk("scale_reg_isr Failed \n");
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);
762 dcam_reg_isr(DCAM_PATH2_DONE, scale_k_isr, (void *)drv_private);
764 dcam_reg_isr(DCAM_PATH2_DONE, NULL, NULL);