1 /*
2 *
3 * SPDX-License-Identifier: GPL-2.0
4 *
5 * Copyright (C) 2018 Amlogic or its affiliates
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 */
19 #define pr_fmt(fmt) "AM_SC: " fmt
20
21 #include <linux/version.h>
22 #include <linux/irqreturn.h>
23 #include <linux/of_address.h>
24 #include <linux/of_irq.h>
25 #include <linux/ioport.h>
26 #include <linux/of_platform.h>
27 #include <linux/dma-mapping.h>
28 #include <linux/interrupt.h>
29 #include <linux/kernel.h>
30 #include <linux/device.h>
31 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 19, 0))
32 #include <linux/dma-contiguous.h>
33 #endif
34 #include <linux/of_reserved_mem.h>
35 #include <linux/platform_device.h>
36 #include <linux/device.h>
37 #include <linux/module.h>
38 #include <linux/of_fdt.h>
39 #include <linux/fs.h>
40 #include <linux/uaccess.h>
41 #include <linux/io.h>
42
43 #include "system_am_sc.h"
44
45 #define AM_SC_NAME "amlogic, isp-sc"
46 static int buffer_id;
47
48 #define ENABLE_SC_BOTTOM_HALF_TASKLET
49
50
51 #ifdef ENABLE_SC_BOTTOM_HALF_TASKLET
52 // tasklet structure
53 struct sc_tasklet_t {
54 struct tasklet_struct tasklet_obj;
55 struct kfifo sc_fifo_out;
56 };
57 static int frame_id = 0;
58 static struct sc_tasklet_t sc_tasklet;
59 #endif
60
61 static bool stop_flag = false;
62 tframe_t* temp_buf = NULL;
63 tframe_t* cur_frame;
64 tframe_t* pre_frame;
65
66 const int isp_filt_coef0[] = //bicubic
67 {
68 0x00800000,
69 0x007f0100,
70 0xff7f0200,
71 0xfe7f0300,
72 0xfd7e0500,
73 0xfc7e0600,
74 0xfb7d0800,
75 0xfb7c0900,
76 0xfa7b0b00,
77 0xfa7a0dff,
78 0xf9790fff,
79 0xf97711ff,
80 0xf87613ff,
81 0xf87416fe,
82 0xf87218fe,
83 0xf8701afe,
84 0xf76f1dfd,
85 0xf76d1ffd,
86 0xf76b21fd,
87 0xf76824fd,
88 0xf76627fc,
89 0xf76429fc,
90 0xf7612cfc,
91 0xf75f2ffb,
92 0xf75d31fb,
93 0xf75a34fb,
94 0xf75837fa,
95 0xf7553afa,
96 0xf8523cfa,
97 0xf8503ff9,
98 0xf84d42f9,
99 0xf84a45f9,
100 0xf84848f8
101 };
102
103 #if 0
104 const int isp_filt_coef1[] = // 2point bilinear
105 {
106 0x00800000,
107 0x007e0200,
108 0x007c0400,
109 0x007a0600,
110 0x00780800,
111 0x00760a00,
112 0x00740c00,
113 0x00720e00,
114 0x00701000,
115 0x006e1200,
116 0x006c1400,
117 0x006a1600,
118 0x00681800,
119 0x00661a00,
120 0x00641c00,
121 0x00621e00,
122 0x00602000,
123 0x005e2200,
124 0x005c2400,
125 0x005a2600,
126 0x00582800,
127 0x00562a00,
128 0x00542c00,
129 0x00522e00,
130 0x00503000,
131 0x004e3200,
132 0x004c3400,
133 0x004a3600,
134 0x00483800,
135 0x00463a00,
136 0x00443c00,
137 0x00423e00,
138 0x00404000
139 };
140 #endif
141
142 static int isp_filt_coef2[] = // 2point bilinear, bank_length == 2
143 {
144 0x80000000,
145 0x7e020000,
146 0x7c040000,
147 0x7a060000,
148 0x78080000,
149 0x760a0000,
150 0x740c0000,
151 0x720e0000,
152 0x70100000,
153 0x6e120000,
154 0x6c140000,
155 0x6a160000,
156 0x68180000,
157 0x661a0000,
158 0x641c0000,
159 0x621e0000,
160 0x60200000,
161 0x5e220000,
162 0x5c240000,
163 0x5a260000,
164 0x58280000,
165 0x562a0000,
166 0x542c0000,
167 0x522e0000,
168 0x50300000,
169 0x4e320000,
170 0x4c340000,
171 0x4a360000,
172 0x48380000,
173 0x463a0000,
174 0x443c0000,
175 0x423e0000,
176 0x40400000
177 };
178
179 #define ZOOM_BITS 20
180 #define PHASE_BITS 16
181
182 typedef enum {
183 F2V_IT2IT = 0,
184 F2V_IB2IB,
185 F2V_IT2IB,
186 F2V_IB2IT,
187 F2V_P2IT,
188 F2V_P2IB,
189 F2V_IT2P,
190 F2V_IB2P,
191 F2V_P2P,
192 F2V_TYPE_MAX
193 } f2v_vphase_type_t; /* frame to video conversion type */
194
195 typedef struct {
196 u8 rcv_num; //0~15
197 u8 rpt_num; // 0~3
198 u16 phase;
199 //s8 repeat_skip_chroma;
200 //u8 phase_chroma;
201 } f2v_vphase_t;
202
203 typedef struct ISP_MIF_TYPE {
204 int reg_rev_x;
205 int reg_rev_y;
206 int reg_little_endian;
207 int reg_bit10_mode;
208 int reg_enable_3ch;
209 int reg_only_1ch;
210 int reg_words_lim;
211 int reg_burst_lim;
212 int reg_rgb_mode;
213 int reg_hconv_mode;
214 int reg_vconv_mode;
215 u16 reg_hsizem1;
216 u16 reg_vsizem1;
217 u16 reg_start_x;
218 u16 reg_start_y;
219 u16 reg_end_x;
220 u16 reg_end_y;
221 int reg_pingpong_en;
222 u16 reg_canvas_strb_luma;
223 u16 reg_canvas_strb_chroma;
224 u16 reg_canvas_strb_r;
225 u32 reg_canvas_baddr_luma;
226 u32 reg_canvas_baddr_chroma;
227 u32 reg_canvas_baddr_r;
228 u32 reg_canvas_baddr_luma_other;
229 u32 reg_canvas_baddr_chroma_other;
230 u32 reg_canvas_baddr_r_other;
231 } ISP_MIF_t;
232
233 static const u8 f2v_420_in_pos_luma[F2V_TYPE_MAX] = {0, 2, 0, 2, 0, 0, 0, 2, 0};
234 //static const u8 f2v_420_in_pos_chroma[F2V_TYPE_MAX] = {1, 5, 1, 5, 2, 2, 1, 5, 2};
235 static const u8 f2v_420_out_pos[F2V_TYPE_MAX] = {0, 2, 2, 0, 0, 2, 0, 0, 0};
236
237 static int rgb2yuvpre[3] = {0, 0, 0};
238 static int rgb2yuvpos[3] = {64, 512, 512};
239 static int rgb2yuvpos_invert[3] = {512, 512, 64};
240 static int yuv2rgbpre[3] = {-64, -512, -512};
241 static int yuv2rgbpos[3] = {0, 0, 0};
242 static int rgb2ycbcr[15] = {230,594,52,-125,-323,448,448,-412,-36,0,0,0,0,0,0};
243 static int rgb2ycbcr_invert[15] = {-125, -323, 448, 448,-412,-36, 230, 594, 52, 0,0,0,0,0,0};
244 static int ycbcr2rgb[15] = {1197,0,1726,1197,-193,-669,1197,2202,0,0,0,0,0,0,0};
245 static ISP_MIF_t isp_frame = {
246 0, // int reg_rev_x
247 0, // int reg_rev_y
248 1, // int reg_little_endian
249 0, // int reg_bit10_mode
250 0, // int reg_enable_3ch
251 0, // int reg_only_1ch
252 4, // int reg_words_lim
253 3, // int reg_burst_lim
254 1, // int reg_rgb_mode
255 2, // int reg_hconv_mode
256 2, // int reg_vconv_mode
257 1279, // int reg_hsizem1
258 719, // int reg_vsizem1
259 0, // int reg_start_x
260 0, // int reg_start_y
261 1279, // int reg_end_x
262 719, // int reg_end_y
263 1, // pingpong en
264 0x780, // int16_t reg_canvas_strb_luma
265 0x780, // int16_t reg_canvas_strb_chroma
266 0x780, // int16_t reg_canvas_strb_r
267 0x4000000, // int32_t reg_canvas_baddr_luma
268 0x5000000, // int32_t reg_canvas_baddr_chroma
269 0x6000000, // int32_t reg_canvas_baddr_r
270 0x7000000, // int32_t reg_canvas_baddr_luma_other
271 0x8000000, // int32_t reg_canvas_baddr_chroma_other
272 0x9000000 // int32_t reg_canvas_baddr_r_other
273 };
274
275 static u32 start_delay_th = 1;
276 static u32 start_delay_cnt;
277 static u8 ch_mode = 0; // 0: normal, 1: force 1 ch, 3: force 3 ch;
278 static u32 last_end_frame = 0;
279 static u32 isr_count;
280 static struct am_sc *g_sc;
281
f2v_get_vertical_phase(u32 zoom_ratio,f2v_vphase_type_t type,u8 bank_length,f2v_vphase_t * vphase)282 void f2v_get_vertical_phase(
283 u32 zoom_ratio,
284 f2v_vphase_type_t type,
285 u8 bank_length,
286 f2v_vphase_t *vphase)
287 {
288 int offset_in, offset_out;
289
290 /* luma */
291 offset_in = f2v_420_in_pos_luma[type] << PHASE_BITS;
292 offset_out = (f2v_420_out_pos[type] * zoom_ratio)
293 >> (ZOOM_BITS - PHASE_BITS);
294
295 vphase->rcv_num = bank_length;
296 if (bank_length == 4 || bank_length == 3)
297 vphase->rpt_num = 1;
298 else
299 vphase->rpt_num = 0;
300
301 if (offset_in > offset_out) {
302 vphase->rpt_num = vphase->rpt_num + 1;
303 vphase->phase =
304 ((4 << PHASE_BITS) + offset_out - offset_in) >> 2;
305 } else {
306 while ((offset_in + (4 << PHASE_BITS)) <= offset_out) {
307 if (vphase->rpt_num == 1)
308 vphase->rpt_num = 0;
309 else
310 vphase->rcv_num++;
311 offset_in += 4 << PHASE_BITS;
312 }
313 vphase->phase = (offset_out - offset_in) >> 2;
314 }
315 }
316
update_wr_reg_bits(unsigned int reg,unsigned int mask,unsigned int val)317 static inline void update_wr_reg_bits(
318 unsigned int reg,
319 unsigned int mask,
320 unsigned int val)
321 {
322 unsigned int tmp, orig;
323 void __iomem *base = g_sc->base_addr;
324
325 if (base != NULL) {
326 orig = readl(base + reg);
327 tmp = orig & ~mask;
328 tmp |= val & mask;
329 writel(tmp, base + reg);
330 }
331 }
332
sc_wr_reg_bits(unsigned int adr,unsigned int val,unsigned int start,unsigned int len)333 static inline void sc_wr_reg_bits(
334 unsigned int adr, unsigned int val,
335 unsigned int start, unsigned int len)
336 {
337 update_wr_reg_bits(adr,
338 ((1 << len) - 1) << start, val << start);
339 }
340
sc_reg_wr(int addr,uint32_t val)341 static inline void sc_reg_wr(
342 int addr, uint32_t val)
343 {
344 void __iomem *base = g_sc->base_addr;
345
346 if (base != NULL) {
347 base = base + addr;
348 writel(val, base);
349 } else
350 pr_err("isp-sc write register failed.\n");
351
352 }
353
sc_reg_rd(int addr,uint32_t * val)354 static inline void sc_reg_rd(
355 int addr, uint32_t *val)
356 {
357 void __iomem *base = g_sc->base_addr;
358
359 if (base != NULL && val) {
360 base = base + addr;
361 *val = readl(base);
362 } else
363 pr_err("isp-sc read register failed.\n");
364
365 }
366
isp_sc_setting(u32 src_w,u32 src_h,u32 dst_w,u32 dst_h)367 static void isp_sc_setting(
368 u32 src_w, u32 src_h,
369 u32 dst_w, u32 dst_h)
370 {
371 f2v_vphase_t vphase;
372 s32 i;
373 s32 hsc_en, vsc_en;
374 s32 prehsc_en,prevsc_en;
375 s32 vsc_double_line_mode;
376 u32 p_src_w, p_src_h;
377 u32 vert_phase_step, horz_phase_step;
378 u8 top_rcv_num, bot_rcv_num;
379 u8 top_rpt_num, bot_rpt_num;
380 u16 top_vphase, bot_vphase;
381 u8 is_frame;
382 s32 vert_bank_length = 4;
383 s32 *filt_coef0 = (s32 *)&isp_filt_coef0[0];
384 //s32 *filt_coef1 = (s32 *)&isp_filt_coef1[0];
385 s32 *filt_coef2 = (s32 *)&isp_filt_coef2[0];
386 f2v_vphase_type_t top_conv_type = F2V_P2P;
387 f2v_vphase_type_t bot_conv_type = F2V_P2P;
388
389 prehsc_en = 0;
390 prevsc_en = 0;
391 vsc_double_line_mode = 0;
392
393 if (src_h != dst_h)
394 vsc_en = 1;
395 else
396 vsc_en = 0;
397 if (src_w != dst_w)
398 hsc_en = 1;
399 else
400 hsc_en = 0;
401
402 p_src_w = prehsc_en ? ((src_w + 1) >> 1) : src_w;
403 p_src_h = prevsc_en ? ((src_h + 1) >> 1) : src_h;
404
405 if (p_src_w > 2048) {
406 //force vert bank length = 2
407 vert_bank_length = 2;
408 vsc_double_line_mode = 1;
409 }
410
411 //write vert filter coefs
412 sc_reg_wr(ISP_SC_COEF_IDX, 0x0000);
413 for (i = 0; i < 33; i++) {
414 if (vert_bank_length == 2)
415 sc_reg_wr(ISP_SC_COEF, filt_coef2[i]); //bilinear
416 else
417 sc_reg_wr(ISP_SC_COEF, filt_coef0[i]); //bicubic
418 }
419
420 //write horz filter coefs
421 sc_reg_wr(ISP_SC_COEF_IDX, 0x0100);
422 for (i = 0; i < 33; i++) {
423 sc_reg_wr(ISP_SC_COEF, filt_coef0[i]); //bicubic
424 }
425
426 if (p_src_h > 2048)
427 vert_phase_step =
428 ((p_src_h << 18) / dst_h) << 2;
429 else
430 vert_phase_step = (p_src_h << 20) / dst_h;
431
432 if (p_src_w > 2048)
433 horz_phase_step =
434 ((p_src_w << 18) / dst_w) << 2;
435 else
436 horz_phase_step = (p_src_w << 20) / dst_w;
437
438 is_frame = (top_conv_type == F2V_IT2P)
439 || (top_conv_type == F2V_IB2P)
440 || (top_conv_type == F2V_P2P);
441
442 if (is_frame) {
443 f2v_get_vertical_phase(
444 vert_phase_step, top_conv_type,
445 vert_bank_length, &vphase);
446 top_rcv_num = vphase.rcv_num;
447 top_rpt_num = vphase.rpt_num;
448 top_vphase = vphase.phase;
449 bot_rcv_num = 0;
450 bot_rpt_num = 0;
451 bot_vphase = 0;
452 } else {
453 f2v_get_vertical_phase(
454 vert_phase_step, top_conv_type,
455 vert_bank_length, &vphase);
456 top_rcv_num = vphase.rcv_num;
457 top_rpt_num = vphase.rpt_num;
458 top_vphase = vphase.phase;
459
460 f2v_get_vertical_phase(
461 vert_phase_step, bot_conv_type,
462 vert_bank_length, &vphase);
463 bot_rcv_num = vphase.rcv_num;
464 bot_rpt_num = vphase.rpt_num;
465 bot_vphase = vphase.phase;
466 }
467
468 vert_phase_step = (vert_phase_step << 4);
469 horz_phase_step = (horz_phase_step << 4);
470
471 sc_reg_wr(ISP_SC_LINE_IN_LENGTH, src_w);
472 sc_reg_wr(ISP_SC_PIC_IN_HEIGHT, src_h);
473 sc_reg_wr(ISP_VSC_REGION12_STARTP, 0);
474 sc_reg_wr(ISP_VSC_REGION34_STARTP,
475 ((dst_h << 16) | dst_h));
476 sc_reg_wr(ISP_VSC_REGION4_ENDP, dst_h - 1);
477
478 sc_reg_wr(ISP_VSC_START_PHASE_STEP, vert_phase_step);
479 sc_reg_wr(ISP_VSC_REGION0_PHASE_SLOPE, 0);
480 sc_reg_wr(ISP_VSC_REGION1_PHASE_SLOPE, 0);
481 sc_reg_wr(ISP_VSC_REGION3_PHASE_SLOPE, 0);
482 sc_reg_wr(ISP_VSC_REGION4_PHASE_SLOPE, 0);
483
484 sc_reg_wr(ISP_VSC_PHASE_CTRL,
485 (vsc_double_line_mode << 17) |
486 ((!is_frame) << 16) |
487 (0 << 15) |
488 (bot_rpt_num << 13) |
489 (bot_rcv_num << 8) |
490 (0 << 7) |
491 (top_rpt_num << 5) |
492 (top_rcv_num << 0));
493 sc_reg_wr(ISP_VSC_INI_PHASE,
494 (bot_vphase << 16) | top_vphase);
495 sc_reg_wr(ISP_HSC_REGION12_STARTP, 0);
496 sc_reg_wr(ISP_HSC_REGION34_STARTP,
497 (dst_w << 16) | dst_w);
498 sc_reg_wr(ISP_HSC_REGION4_ENDP, dst_w - 1);
499
500 sc_reg_wr(ISP_HSC_START_PHASE_STEP, horz_phase_step);
501 sc_reg_wr(ISP_HSC_REGION0_PHASE_SLOPE, 0);
502 sc_reg_wr(ISP_HSC_REGION1_PHASE_SLOPE, 0);
503 sc_reg_wr(ISP_HSC_REGION3_PHASE_SLOPE, 0);
504 sc_reg_wr(ISP_HSC_REGION4_PHASE_SLOPE, 0);
505
506 sc_reg_wr(ISP_HSC_PHASE_CTRL,
507 (1 << 21) | (4 << 16) | 0);
508 sc_reg_wr(ISP_SC_MISC,
509 (prevsc_en << 21) |
510 (prehsc_en << 20) | // prehsc_en
511 (prevsc_en << 19) | // prevsc_en
512 (vsc_en << 18) | // vsc_en
513 (hsc_en << 17) | // hsc_en
514 (1 << 16) | // sc_top_en
515 (1 << 15) | // vd1 sc out enable
516 (0 << 12) | // horz nonlinear 4region enable
517 (4 << 8) | // horz scaler bank length
518 (0 << 5) | // vert scaler phase field mode enable
519 (0 << 4) | // vert nonlinear 4region enable
520 (vert_bank_length << 0)); // vert scaler bank length
521 }
522
isp_mtx_setting(s32 mode)523 void isp_mtx_setting(s32 mode)
524 {
525 s32 mat_conv_en = 0;
526 s32 i, pre_offset[3] ={0, 0, 0}, post_offset[3]= {0, 0, 0};
527 s32 mat_coef[15];
528 bool invert = false;
529
530 if ((ch_mode == 0) && (mode == 1)
531 && (isp_frame.reg_rgb_mode == 1))
532 invert = true;
533
534 if (mode == 1) {
535 mat_conv_en = 1;
536 for (i = 0; i < 3; i++) {
537 pre_offset[i] = rgb2yuvpre[i];
538 post_offset[i] = (invert == true) ?
539 rgb2yuvpos_invert[i] :
540 rgb2yuvpos[i];
541 }
542 for (i = 0; i < 15; i++)
543 mat_coef[i] = (invert == true) ?
544 rgb2ycbcr_invert[i] :
545 rgb2ycbcr[i];
546 } else if (mode == 2) {
547 mat_conv_en = 1;
548 for (i = 0; i < 3; i++) {
549 pre_offset[i] = yuv2rgbpre[i];
550 post_offset[i] = yuv2rgbpos[i];
551 }
552 for (i = 0; i < 15; i++)
553 mat_coef[i] = ycbcr2rgb[i];
554 }
555 sc_reg_wr(ISP_MATRIX_COEF00_01,
556 (mat_coef[0 * 3 + 0] << 16) |
557 (mat_coef[0 * 3 + 1] & 0x1FFF));
558 sc_reg_wr(ISP_MATRIX_COEF02_10,
559 (mat_coef[0 * 3 + 2] << 16) |
560 (mat_coef[1 * 3 + 0] & 0x1FFF));
561 sc_reg_wr(ISP_MATRIX_COEF11_12,
562 (mat_coef[1 * 3 + 1] << 16) |
563 (mat_coef[1 * 3 + 2] & 0x1FFF));
564 sc_reg_wr(ISP_MATRIX_COEF20_21,
565 (mat_coef[2 * 3 + 0] << 16) |
566 (mat_coef[2 * 3 + 1] & 0x1FFF));
567 sc_reg_wr(ISP_MATRIX_COEF22,
568 mat_coef[2 * 3 + 2]);
569 sc_reg_wr(ISP_MATRIX_OFFSET0_1,
570 (post_offset[0] << 16) |
571 (post_offset[1] & 0xFFF));
572 sc_reg_wr(ISP_MATRIX_OFFSET2,
573 post_offset[2]);
574 sc_reg_wr(ISP_MATRIX_PRE_OFFSET0_1,
575 (pre_offset[0] << 16) |
576 (pre_offset[1] & 0xFFF));
577 sc_reg_wr(ISP_MATRIX_PRE_OFFSET2,
578 pre_offset[2]);
579 sc_reg_wr(ISP_MATRIX_EN_CTRL,
580 mat_conv_en);
581 }
582
isp_mif_setting(ISP_MIF_t * wr_mif)583 void isp_mif_setting(ISP_MIF_t *wr_mif)
584 {
585 u8 swap_uv = 0;
586 if (g_sc->info.in_fmt == RGB24) {
587 if (g_sc->info.out_fmt == NV12_YUV) {
588 swap_uv = 0;
589 }
590 } else if (g_sc->info.in_fmt == AYUV) {
591 if (g_sc->info.out_fmt == NV12_YUV) {
592 swap_uv = 1;
593 }
594 }
595
596 sc_wr_reg_bits(ISP_SCWR_MIF_CTRL0,
597 ((1 << 0) |
598 (0 << 1) |
599 (0 << 2) |
600 (0 << 3) |
601 (wr_mif->reg_rev_x << 4) |
602 (wr_mif->reg_rev_y << 5) |
603 (wr_mif->reg_little_endian << 6) |
604 (0 << 7) |
605 (1 << 8) |
606 (swap_uv << 9) |
607 (0 <<10) |
608 (wr_mif->reg_bit10_mode << 11) |
609 (wr_mif->reg_enable_3ch << 12) |
610 (wr_mif->reg_only_1ch << 13)),
611 0, 14);
612 sc_wr_reg_bits(ISP_SCWR_MIF_CTRL0,
613 wr_mif->reg_pingpong_en, 17, 1);
614 sc_reg_wr(ISP_SCWR_MIF_CTRL1,
615 wr_mif->reg_words_lim |
616 (wr_mif->reg_burst_lim << 4) |
617 (wr_mif->reg_rgb_mode << 8) |
618 (wr_mif->reg_hconv_mode << 10) |
619 (wr_mif->reg_vconv_mode << 12) |
620 (0 << 16) |
621 (0 << 20));
622 sc_reg_wr(ISP_SCWR_MIF_CTRL2, 0);
623 sc_reg_wr(ISP_SCWR_MIF_CTRL3,
624 wr_mif->reg_hsizem1 |
625 (wr_mif->reg_vsizem1 << 16));
626 sc_reg_wr(ISP_SCWR_MIF_CTRL4,
627 wr_mif->reg_start_x |
628 (wr_mif->reg_start_y << 16));
629 sc_reg_wr(ISP_SCWR_MIF_CTRL5,
630 wr_mif->reg_end_x |
631 (wr_mif->reg_end_y << 16));
632 sc_reg_wr(ISP_SCWR_MIF_CTRL6,
633 (wr_mif->reg_canvas_strb_luma & 0xffff) |
634 (wr_mif->reg_canvas_strb_chroma << 16));
635 sc_reg_wr(ISP_SCWR_MIF_CTRL7,
636 wr_mif->reg_canvas_strb_r);
637 sc_reg_wr(ISP_SCWR_MIF_CTRL11,
638 wr_mif->reg_canvas_baddr_luma_other);
639 sc_reg_wr(ISP_SCWR_MIF_CTRL12,
640 wr_mif->reg_canvas_baddr_chroma_other);
641 sc_reg_wr(ISP_SCWR_MIF_CTRL13,
642 wr_mif->reg_canvas_baddr_r_other);
643 sc_reg_wr(ISP_SCWR_MIF_CTRL8,
644 wr_mif->reg_canvas_baddr_luma);
645 sc_reg_wr(ISP_SCWR_MIF_CTRL9,
646 wr_mif->reg_canvas_baddr_chroma);
647 sc_reg_wr(ISP_SCWR_MIF_CTRL10,
648 wr_mif->reg_canvas_baddr_r);
649 }
650
enable_isp_scale(int initial_en,u32 src_w,u32 src_h,u32 out_w,u32 out_h,int mux_sel,int sc_en,int mtx_mode,ISP_MIF_t * wr_mif)651 static void enable_isp_scale(
652 int initial_en,
653 u32 src_w,
654 u32 src_h,
655 u32 out_w,
656 u32 out_h,
657 int mux_sel,
658 int sc_en,
659 int mtx_mode, //1:rgb->yuv,2:yuv->rgb,0:bypass
660 ISP_MIF_t *wr_mif)
661 {
662 /* don't enable mif first, and use wr done int */
663 int enable = 0;
664 int rgb_swap = 0;
665 int irq_sel = 0;
666 u32 val = 0;
667
668 if (g_sc->info.in_fmt == RGB24) {
669 if (g_sc->info.out_fmt == AYUV) {
670 rgb_swap = 5;
671 }
672 } else if (g_sc->info.in_fmt == AYUV) {
673 if (g_sc->info.out_fmt == AYUV) {
674 rgb_swap = 5;
675 }
676 }
677
678 if (sc_en)
679 isp_sc_setting(src_w, src_h, out_w, out_h);
680
681 if (initial_en) {
682 sc_reg_wr(ISP_SCWR_SYNC_DLY, 0);
683 sc_reg_wr(ISP_SCWR_TOP_CTRL,
684 ((mux_sel & 0x7) << 20) |
685 (1 << 16) |
686 (rgb_swap << 13) |
687 (0x0 << 10) |
688 (1 << 1));
689 isp_mtx_setting(mtx_mode);
690 sc_wr_reg_bits(ISP_SCWR_MIF_CTRL0, 1, 14, 1);
691 sc_wr_reg_bits(ISP_SCWR_MIF_CTRL0, 1, 20, 1);
692 isp_mif_setting(wr_mif);
693 sc_wr_reg_bits(ISP_SCWR_MIF_CTRL0, 0, 14, 1);
694 if (wr_mif->reg_pingpong_en) {
695 sc_wr_reg_bits(ISP_SCWR_MIF_CTRL0, 0, 19, 1);
696 sc_wr_reg_bits(ISP_SCWR_MIF_CTRL0, 1, 18, 1); // pingpong init
697 sc_wr_reg_bits(ISP_SCWR_MIF_CTRL0, 0, 18, 1); // pingpong init
698 }
699 sc_reg_wr(ISP_SCWR_TOP_CTRL,
700 ((mux_sel & 0x7) << 20) |
701 (1 << 16) |
702 (rgb_swap << 13) |
703 (0x0 << 10) |
704 (irq_sel << 3) |
705 (1 << 1) |
706 enable);
707 //generated the vsync by register control
708 sc_wr_reg_bits(ISP_SCWR_TOP_CTRL, 3, 10, 2);
709 sc_wr_reg_bits(ISP_SCWR_TOP_CTRL, 1, 12, 1);
710 sc_wr_reg_bits(ISP_SCWR_TOP_CTRL, 0, 12, 1);
711 sc_wr_reg_bits(ISP_SCWR_TOP_CTRL, 0, 10, 2);
712 sc_reg_wr(ISP_SCWR_SYNC_DLY, 4096);
713
714 sc_reg_rd(ISP_SCWR_TOP_DBG0, &val);
715 if (val & (1 << 6))
716 last_end_frame = 1;
717 else
718 last_end_frame = 0;
719 } else {
720 sc_reg_wr(ISP_SCWR_SYNC_DLY, 4096); //very important
721 isp_mif_setting(wr_mif);
722 sc_wr_reg_bits(ISP_SCWR_TOP_CTRL,
723 (mux_sel & 0x7), 20, 3);
724 sc_wr_reg_bits(ISP_SCWR_TOP_CTRL, rgb_swap, 13, 3);
725 sc_wr_reg_bits(ISP_SCWR_TOP_CTRL, 0, 10, 1);
726 sc_wr_reg_bits(ISP_SCWR_TOP_CTRL,
727 (1 << 1) | enable, 0, 2);
728 }
729
730 sc_reg_wr(ISP_SCWR_SC_CTRL1,
731 ((src_w & 0xfff) << 16) | (src_h & 0xfff));
732 //sc_reg_wr(ISP_SCWR_SYNC_DLY, 300);
733 }
734
init_sc_mif_setting(ISP_MIF_t * mif_frame)735 static void init_sc_mif_setting(ISP_MIF_t *mif_frame)
736 {
737 u32 plane_size, frame_size;
738 unsigned long flags;
739 tframe_t *buf = NULL;
740 int retval;
741
742 if (!mif_frame)
743 return;
744
745 spin_lock_irqsave( &g_sc->sc_lock, flags );
746 if (kfifo_len(&g_sc->sc_fifo_in) > 0) {
747 retval = kfifo_out(&g_sc->sc_fifo_in, &buf, sizeof(tframe_t*));
748 if (retval == sizeof(tframe_t*)) {
749 pre_frame = buf;
750 } else {
751 pr_info("%d, fifo out failed.\n", __LINE__);
752 }
753 } else {
754 pr_info("%d, sc fifo is empty .\n", __LINE__);
755 }
756 spin_unlock_irqrestore( &g_sc->sc_lock, flags );
757
758 if (g_sc->info.out_fmt == NV12_GREY) {
759 ch_mode = 1;
760 } else {
761 ch_mode = 0;
762 }
763
764 memset(mif_frame, 0, sizeof(ISP_MIF_t));
765 plane_size = g_sc->info.out_w * g_sc->info.out_h;
766 mif_frame->reg_little_endian = 1;
767 if ((g_sc->info.in_fmt == RGB24) ||
768 (g_sc->info.in_fmt == AYUV)) {
769 if ((g_sc->info.out_fmt == RGB24) ||
770 (g_sc->info.out_fmt == AYUV)) {
771 mif_frame->reg_rgb_mode = 1;
772 } else if (g_sc->info.out_fmt == NV12_YUV) {
773 mif_frame->reg_rgb_mode = 2;
774 } else if (g_sc->info.out_fmt == UYVY) {
775 mif_frame->reg_rgb_mode = 0;
776 } else if (g_sc->info.out_fmt == NV12_GREY) {
777 mif_frame->reg_rgb_mode = 2;
778 }
779 } else if ((g_sc->info.in_fmt == NV12_YUV) ||
780 (g_sc->info.in_fmt == NV12_GREY)) {
781 if (g_sc->info.out_fmt == NV12_GREY) {
782 mif_frame->reg_rgb_mode = 2;
783 }
784 }
785 mif_frame->reg_bit10_mode = 0;
786 mif_frame->reg_words_lim = 4;
787 mif_frame->reg_burst_lim = 3;
788 mif_frame->reg_hconv_mode = 2;
789 mif_frame->reg_vconv_mode = 0;
790 mif_frame->reg_pingpong_en = 1;
791 mif_frame->reg_start_x = 0;
792 mif_frame->reg_start_y = 0;
793 mif_frame->reg_end_x = g_sc->info.out_w -1;
794 mif_frame->reg_end_y = g_sc->info.out_h - 1;
795 mif_frame->reg_hsizem1 = g_sc->info.out_w - 1;
796 mif_frame->reg_vsizem1 = g_sc->info.out_h - 1;
797 if (ch_mode == 1) {
798 mif_frame->reg_only_1ch = 1;
799 mif_frame->reg_enable_3ch = 0;
800 frame_size = plane_size;
801 mif_frame->reg_canvas_strb_luma =
802 g_sc->info.out_w;
803 mif_frame->reg_canvas_strb_chroma = 0;
804 mif_frame->reg_canvas_strb_r = 0;
805 mif_frame->reg_hconv_mode = 2;
806 mif_frame->reg_vconv_mode = 2;
807 mif_frame->reg_rgb_mode = 2;
808 } else if (ch_mode == 3) {
809 mif_frame->reg_only_1ch = 0;
810 mif_frame->reg_enable_3ch = 1;
811 frame_size = plane_size * 3;
812 mif_frame->reg_canvas_strb_luma =
813 g_sc->info.out_w;
814 mif_frame->reg_canvas_strb_chroma =
815 g_sc->info.out_w;
816 mif_frame->reg_canvas_strb_r =
817 g_sc->info.out_w;
818 mif_frame->reg_hconv_mode = 2;
819 mif_frame->reg_vconv_mode = 2;
820 mif_frame->reg_rgb_mode = 2;
821 } else {
822 mif_frame->reg_only_1ch = 0;
823 mif_frame->reg_enable_3ch = 0;
824 if (mif_frame->reg_rgb_mode == 0) {
825 frame_size = plane_size * 2;
826 mif_frame->reg_canvas_strb_luma =
827 g_sc->info.out_w * 2;
828 mif_frame->reg_canvas_strb_chroma = 0;
829 mif_frame->reg_canvas_strb_r = 0;
830 } else if (mif_frame->reg_rgb_mode == 1) {
831 frame_size = plane_size * 3;
832 mif_frame->reg_canvas_strb_luma =
833 g_sc->info.out_w * 3;
834 mif_frame->reg_canvas_strb_chroma = 0;
835 mif_frame->reg_canvas_strb_r = 0;
836 } else if (mif_frame->reg_rgb_mode == 2) {
837 frame_size = plane_size * 3 / 2;
838 mif_frame->reg_canvas_strb_luma =
839 g_sc->info.out_w;
840 mif_frame->reg_canvas_strb_chroma =
841 g_sc->info.out_w;
842 mif_frame->reg_canvas_strb_r = 0;
843 } else {
844 frame_size = plane_size * 3;
845 mif_frame->reg_canvas_strb_luma =
846 g_sc->info.out_w * 3;
847 mif_frame->reg_canvas_strb_chroma = 0;
848 mif_frame->reg_canvas_strb_r = 0;
849 }
850 }
851 mif_frame->reg_canvas_baddr_luma =
852 buf->primary.address;
853 mif_frame->reg_canvas_baddr_luma_other =
854 mif_frame->reg_canvas_baddr_luma;
855
856 if (mif_frame->reg_canvas_strb_chroma) {
857 mif_frame->reg_canvas_baddr_chroma =
858 buf->secondary.address;
859 mif_frame->reg_canvas_baddr_chroma_other =
860 mif_frame->reg_canvas_baddr_luma_other;
861 }
862
863 if (mif_frame->reg_canvas_strb_r) {
864 mif_frame->reg_canvas_baddr_r =
865 buf->secondary.address;
866 mif_frame->reg_canvas_baddr_r_other =
867 mif_frame->reg_canvas_baddr_chroma_other;
868 }
869
870 if (!mif_frame->reg_pingpong_en) {
871 mif_frame->reg_canvas_baddr_luma_other = 0;
872 mif_frame->reg_canvas_baddr_chroma_other = 0;
873 mif_frame->reg_canvas_baddr_r_other = 0;
874 }
875
876 pr_info("init_sc_mif_setting: %dx%d -> %dx%d, %x-%x-%x-%x-%x-%x, stride: %x-%x-%x\n",
877 g_sc->info.src_w, g_sc->info.src_h,
878 g_sc->info.out_w, g_sc->info.out_h,
879 mif_frame->reg_canvas_baddr_luma,
880 mif_frame->reg_canvas_baddr_chroma,
881 mif_frame->reg_canvas_baddr_r,
882 mif_frame->reg_canvas_baddr_luma_other,
883 mif_frame->reg_canvas_baddr_chroma_other,
884 mif_frame->reg_canvas_baddr_r_other,
885 mif_frame->reg_canvas_strb_luma,
886 mif_frame->reg_canvas_strb_chroma,
887 mif_frame->reg_canvas_strb_r);
888 }
889
write_to_file(char * buf,int size)890 static int write_to_file(char *buf, int size)
891 {
892 int ret = 0;
893 struct file *fp = NULL;
894 mm_segment_t old_fs;
895 loff_t pos = 0;
896 int nwrite = 0;
897
898 /* change to KERNEL_DS address limit */
899 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0))
900 old_fs = get_fs();
901 set_fs(KERNEL_DS);
902 #endif
903
904 /* open file to write */
905 fp = filp_open("/media/sc_img.raw", O_WRONLY|O_CREAT, 0640);
906 if (!fp) {
907 printk("%s: open file error\n", __FUNCTION__);
908 ret = -1;
909 goto exit;
910 }
911
912 /* Write buf to file */
913 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0))
914 nwrite = vfs_write(fp, buf, size, &pos);
915 #else
916 nwrite = kernel_write(fp, buf, size, &pos);
917 #endif
918 if (fp) {
919 filp_close(fp, NULL);
920 }
921 exit:
922 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0))
923 set_fs(old_fs);
924 #endif
925 return ret;
926 }
927
sc_frame_read(struct device * dev,struct device_attribute * attr,char * buf)928 static ssize_t sc_frame_read(struct device *dev,
929 struct device_attribute *attr, char *buf)
930 {
931 char buf1[50];
932
933 pr_info("sc-read.\n");
934 //buf = (char *)sc_cma_mem;
935 write_to_file(buf, g_sc->info.out_w * g_sc->info.out_h * 3);
936 return sprintf(buf1,"buffer_id:%d", buffer_id);
937 }
938
sc_frame_write(struct device * dev,struct device_attribute * attr,char const * buf,size_t size)939 static ssize_t sc_frame_write(struct device *dev,
940 struct device_attribute *attr, char const *buf, size_t size)
941 {
942 unsigned long write_flag = 0;
943 int retval = 0;
944
945 retval = kstrtoul(buf, 10, &write_flag);
946
947 if (retval) {
948 pr_err("Error to count strtoul\n");
949 return retval;
950 }
951 return size;
952 }
953 static DEVICE_ATTR(sc_frame, S_IRUGO | S_IWUSR, sc_frame_read, sc_frame_write);
954
955 #ifdef ENABLE_SC_BOTTOM_HALF_TASKLET
sc_do_tasklet(unsigned long data)956 void sc_do_tasklet( unsigned long data )
957 {
958 tframe_t *f_buff;
959 metadata_t metadata;
960 memset(&metadata, 0, sizeof(metadata_t));
961
962 while (kfifo_out(&sc_tasklet.sc_fifo_out, &f_buff, sizeof(tframe_t*))) {
963 metadata.width = g_sc->info.out_w;
964 metadata.height = g_sc->info.out_h;
965 metadata.frame_id = frame_id;
966 metadata.frame_number = frame_id;
967 metadata.line_size = (((3 * g_sc->info.out_w) + 127) & (~127));
968 g_sc->callback(g_sc->ctx, f_buff, &metadata );
969 frame_id++;
970 }
971 }
972 #endif
973
sc_config_next_buffer(tframe_t * f_buf,int ping)974 void sc_config_next_buffer(tframe_t* f_buf, int ping)
975 {
976 if (ping) {
977 isp_frame.reg_canvas_baddr_luma = f_buf->primary.address;
978 isp_frame.reg_canvas_baddr_chroma = f_buf->secondary.address;
979 isp_frame.reg_canvas_baddr_r = f_buf->secondary.address;
980 } else {
981 isp_frame.reg_canvas_baddr_luma_other = f_buf->primary.address;
982 isp_frame.reg_canvas_baddr_chroma_other = f_buf->secondary.address;
983 isp_frame.reg_canvas_baddr_r_other = f_buf->secondary.address;
984 }
985 isp_mif_setting(&isp_frame);
986 }
987
isp_sc_isr(int irq,void * data)988 static irqreturn_t isp_sc_isr(int irq, void *data)
989 {
990 if (start_delay_cnt < start_delay_th) {
991 start_delay_cnt++;
992 } else {
993 /* maybe need drop one more frame */
994 if (start_delay_cnt == start_delay_th) {
995 isr_count = 0;
996 /* sc_wr_reg_bits(ISP_SCWR_MIF_CTRL2, 1, 14, 1); */
997 sc_wr_reg_bits(ISP_SCWR_TOP_CTRL, 1, 0, 1);
998 start_delay_cnt++;
999 } else {
1000 u32 flag = 0;
1001 tframe_t *f_buf = NULL;
1002 unsigned long flags;
1003 int retval;
1004
1005 spin_lock_irqsave( &g_sc->sc_lock, flags );
1006 if (kfifo_len(&g_sc->sc_fifo_in) > 0) {
1007 retval = kfifo_out(&g_sc->sc_fifo_in, &f_buf, sizeof(tframe_t*));
1008 if (retval != sizeof(tframe_t*))
1009 pr_info("%d, fifo out failed.\n", __LINE__);
1010 } else {
1011 //pr_info("%d, sc fifo is empty .\n", __LINE__);
1012 f_buf = pre_frame;
1013 pre_frame = NULL;
1014 }
1015 spin_unlock_irqrestore( &g_sc->sc_lock, flags );
1016
1017 sc_reg_rd(ISP_SCWR_TOP_DBG0, &flag);
1018 sc_config_next_buffer(f_buf, (flag & (1 << 8)) ? 0 : 1);
1019 flag = (flag & (1 << 6)) ? 1 : 0;
1020 isr_count++;
1021 cur_frame = f_buf;
1022
1023 if (flag == last_end_frame) {
1024 if (!pre_frame) {
1025 if (!kfifo_is_full(&g_sc->sc_fifo_in)) {
1026 spin_lock_irqsave( &g_sc->sc_lock, flags );
1027 kfifo_in(&g_sc->sc_fifo_in, &(f_buf), sizeof(tframe_t*));
1028 spin_unlock_irqrestore(&g_sc->sc_lock, flags);
1029 }
1030 } else {
1031 if (!kfifo_is_full(&g_sc->sc_fifo_in)) {
1032 spin_lock_irqsave( &g_sc->sc_lock, flags );
1033 kfifo_in(&g_sc->sc_fifo_in, &(pre_frame), sizeof(tframe_t*));
1034 spin_unlock_irqrestore(&g_sc->sc_lock, flags);
1035 }
1036 }
1037 } else {
1038 if (pre_frame) {
1039 if (!kfifo_is_full(&sc_tasklet.sc_fifo_out)) {
1040 kfifo_in(&sc_tasklet.sc_fifo_out, &(pre_frame), sizeof(tframe_t*));
1041 }
1042 tasklet_schedule(&sc_tasklet.tasklet_obj);
1043 }
1044 }
1045 pre_frame = cur_frame;
1046 last_end_frame = flag;
1047 buffer_id ^= 1;
1048 }
1049 }
1050 return IRQ_HANDLED;
1051 }
1052
am_sc_parse_dt(struct device_node * node)1053 int am_sc_parse_dt(struct device_node *node)
1054 {
1055 int rtn = -1;
1056 int irq = -1;
1057 struct resource rs;
1058 struct am_sc *t_sc = NULL;
1059
1060 if (node == NULL) {
1061 pr_err("%s: Error input param\n", __func__);
1062 return -1;
1063 }
1064
1065 rtn = of_device_is_compatible(node, AM_SC_NAME);
1066 if (rtn == 0) {
1067 pr_err("%s: Error match compatible\n", __func__);
1068 return -1;
1069 }
1070
1071 t_sc = kzalloc(sizeof(*t_sc), GFP_KERNEL);
1072 if (t_sc == NULL) {
1073 pr_err("%s: Failed to alloc isp-sc\n", __func__);
1074 return -1;
1075 }
1076
1077 t_sc->of_node = node;
1078
1079 rtn = of_address_to_resource(node, 0, &rs);
1080 if (rtn != 0) {
1081 pr_err("%s:Error get isp-sc reg resource\n", __func__);
1082 goto reg_error;
1083 }
1084
1085 pr_info("%s: rs idx info: name: %s\n", __func__, rs.name);
1086 if (strcmp(rs.name, "isp_sc") == 0) {
1087 t_sc->reg = rs;
1088 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 19, 0))
1089 t_sc->base_addr = ioremap_nocache(
1090 t_sc->reg.start, resource_size(&t_sc->reg));
1091 #else
1092 t_sc->base_addr = ioremap(
1093 t_sc->reg.start, resource_size(&t_sc->reg));
1094 #endif
1095 }
1096
1097 irq = irq_of_parse_and_map(node, 0);
1098 if (irq <= 0) {
1099 pr_err("%s:Error get isp-sc irq\n", __func__);
1100 goto irq_error;
1101 }
1102
1103 t_sc->irq = irq;
1104 pr_info("%s:rs info: irq: %d\n", __func__, t_sc->irq);
1105
1106 t_sc->p_dev = of_find_device_by_node(node);
1107
1108 device_create_file(&(t_sc->p_dev->dev), &dev_attr_sc_frame);
1109
1110 g_sc = t_sc;
1111
1112 return 0;
1113 irq_error:
1114 iounmap(t_sc->base_addr);
1115 t_sc->base_addr = NULL;
1116
1117 reg_error:
1118 if (t_sc != NULL)
1119 kfree(t_sc);
1120 return -1;
1121 }
1122
am_sc_deinit_parse_dt(void)1123 void am_sc_deinit_parse_dt(void)
1124 {
1125 if (g_sc == NULL) {
1126 pr_err("Error g_sc is NULL\n");
1127 return;
1128 }
1129
1130 if (g_sc->p_dev != NULL)
1131 device_remove_file(&(g_sc->p_dev->dev), &dev_attr_sc_frame);
1132
1133 if (g_sc->base_addr != NULL) {
1134 iounmap(g_sc->base_addr);
1135 g_sc->base_addr = NULL;
1136 }
1137
1138 kfree(g_sc);
1139 g_sc = NULL;
1140 }
1141
am_sc_api_dma_buffer(tframe_t * data,unsigned int index)1142 void am_sc_api_dma_buffer(tframe_t * data, unsigned int index)
1143 {
1144 unsigned long flags;
1145
1146 spin_lock_irqsave(&g_sc->sc_lock, flags);
1147 tframe_t *buf = temp_buf + index;
1148 memcpy(buf, data, sizeof(tframe_t));
1149 if (!kfifo_is_full(&g_sc->sc_fifo_in)) {
1150 kfifo_in(&g_sc->sc_fifo_in, &buf, sizeof(tframe_t*));
1151 } else {
1152 pr_info("sc fifo is full .\n");
1153 }
1154 spin_unlock_irqrestore(&g_sc->sc_lock, flags);
1155
1156 }
1157
am_sc_get_width(void)1158 uint32_t am_sc_get_width(void)
1159 {
1160 if (!g_sc) {
1161 pr_info("%d, g_sc is NULL.\n", __LINE__);
1162 return -1;
1163 }
1164 return g_sc->info.out_w;
1165 }
1166
am_sc_set_width(uint32_t src_w,uint32_t out_w)1167 void am_sc_set_width(uint32_t src_w, uint32_t out_w)
1168 {
1169 if (!g_sc) {
1170 pr_info("%d, g_sc is NULL.\n", __LINE__);
1171 return;
1172 }
1173 if (g_sc->info.src_w == 0)
1174 g_sc->info.src_w = src_w;
1175 g_sc->info.out_w = out_w;
1176 }
1177
am_sc_set_src_width(uint32_t src_w)1178 void am_sc_set_src_width(uint32_t src_w)
1179 {
1180 if (!g_sc) {
1181 pr_info("%d, g_sc is NULL.\n", __LINE__);
1182 return;
1183 }
1184 g_sc->info.src_w = src_w;
1185 }
1186
am_sc_set_src_height(uint32_t src_h)1187 void am_sc_set_src_height(uint32_t src_h)
1188 {
1189 if (!g_sc) {
1190 pr_info("%d, g_sc is NULL.\n", __LINE__);
1191 return;
1192 }
1193 g_sc->info.src_h = src_h;
1194 }
1195
am_sc_get_height(void)1196 uint32_t am_sc_get_height(void)
1197 {
1198 if (!g_sc) {
1199 pr_info("%d, g_sc is NULL.\n", __LINE__);
1200 return -1;
1201 }
1202 return g_sc->info.out_h;
1203 }
1204
am_sc_get_output_format(void)1205 uint32_t am_sc_get_output_format(void)
1206 {
1207 if (!g_sc) {
1208 pr_info("%d, g_sc is NULL.\n", __LINE__);
1209 return -1;
1210 }
1211 return g_sc->info.out_fmt;
1212 }
1213
1214
am_sc_set_height(uint32_t src_h,uint32_t out_h)1215 void am_sc_set_height(uint32_t src_h, uint32_t out_h)
1216 {
1217 if (!g_sc) {
1218 pr_info("%d, g_sc is NULL.\n", __LINE__);
1219 return;
1220 }
1221 if (g_sc->info.src_h == 0)
1222 g_sc->info.src_h = src_h;
1223 g_sc->info.out_h = out_h;
1224 }
1225
am_sc_set_input_format(uint32_t value)1226 void am_sc_set_input_format(uint32_t value)
1227 {
1228 if (!g_sc) {
1229 pr_info("%d, g_sc is NULL.\n", __LINE__);
1230 return;
1231 }
1232 g_sc->info.in_fmt = value;
1233 }
1234
am_sc_set_output_format(uint32_t value)1235 void am_sc_set_output_format(uint32_t value)
1236 {
1237 if (!g_sc) {
1238 pr_info("%d, g_sc is NULL.\n", __LINE__);
1239 return;
1240 }
1241 g_sc->info.out_fmt = value;
1242 }
1243
am_sc_set_buf_num(uint32_t num)1244 void am_sc_set_buf_num(uint32_t num)
1245 {
1246 if (!g_sc) {
1247 pr_info("%d, g_sc is NULL.\n", __LINE__);
1248 return;
1249 }
1250 g_sc->req_buf_num = num;
1251 }
1252
am_sc_set_callback(acamera_context_ptr_t p_ctx,buffer_callback_t ds2_callback)1253 int am_sc_set_callback(acamera_context_ptr_t p_ctx, buffer_callback_t ds2_callback)
1254 {
1255 if (!g_sc) {
1256 pr_info("%d, g_sc is NULL.\n", __LINE__);
1257 return -1;
1258 }
1259 g_sc->callback = ds2_callback;
1260 g_sc->ctx = p_ctx;
1261 return 0;
1262 }
1263
am_sc_system_init(void)1264 int am_sc_system_init(void)
1265 {
1266 int ret = 0;
1267
1268 if (!g_sc) {
1269 pr_info("%d, g_sc is NULL.\n", __LINE__);
1270 return -1;
1271 }
1272
1273 if(g_sc->req_buf_num == 0)
1274 return 0;
1275
1276 ret = kfifo_alloc(&g_sc->sc_fifo_in, PAGE_SIZE, GFP_KERNEL);
1277 if (ret) {
1278 pr_info("alloc sc fifo failed.\n");
1279 return ret;
1280 }
1281
1282 spin_lock_init(&g_sc->sc_lock);
1283 stop_flag = false;
1284 start_delay_cnt = 0;
1285 buffer_id = 0;
1286
1287 cur_frame = NULL;
1288 pre_frame = NULL;
1289
1290 if (!temp_buf) {
1291 temp_buf = (tframe_t*)kmalloc( sizeof(tframe_t) * (g_sc->req_buf_num), GFP_KERNEL | __GFP_NOFAIL);
1292 }
1293
1294 #ifdef ENABLE_SC_BOTTOM_HALF_TASKLET
1295 ret = kfifo_alloc(&sc_tasklet.sc_fifo_out, PAGE_SIZE, GFP_KERNEL);
1296 if (ret) {
1297 pr_info("alloc sc_tasklet fifo failed.\n");
1298 return ret;
1299 }
1300 tasklet_init( &sc_tasklet.tasklet_obj, sc_do_tasklet, (unsigned long)&sc_tasklet );
1301 frame_id = 0;
1302 #endif
1303
1304 ret = request_irq(g_sc->irq, isp_sc_isr, IRQF_SHARED | IRQF_TRIGGER_RISING,
1305 "isp-sc-irq", (void *)g_sc);
1306 pr_info("am_sc_system_init : irq = %d, ret = %d\n", g_sc->irq, ret);
1307 return ret;
1308 }
1309
am_sc_hw_init(void)1310 int am_sc_hw_init(void)
1311 {
1312 if (!g_sc) {
1313 pr_info("%d, g_sc is NULL.\n", __LINE__);
1314 return -1;
1315 }
1316
1317 pr_info("src_w = %d, src_h = %d, out_w = %d, out_h = %d\n",
1318 g_sc->info.src_w, g_sc->info.src_h, g_sc->info.out_w, g_sc->info.out_h);
1319
1320 int mtx_mode = 0;
1321 init_sc_mif_setting(&isp_frame);
1322 buffer_id = 0;
1323 if (g_sc->info.in_fmt == RGB24) {
1324 if (g_sc->info.out_fmt == RGB24) {
1325 mtx_mode = 0;
1326 } else if ((g_sc->info.out_fmt == NV12_YUV) ||
1327 (g_sc->info.out_fmt == UYVY) ||
1328 (g_sc->info.out_fmt == AYUV)) {
1329 mtx_mode = 1;
1330 } else if (g_sc->info.out_fmt == NV12_GREY) {
1331 mtx_mode = 1;
1332 }
1333 } else if (g_sc->info.in_fmt == AYUV) {
1334 if ((g_sc->info.out_fmt == NV12_YUV) ||
1335 (g_sc->info.out_fmt == UYVY) ||
1336 (g_sc->info.out_fmt == AYUV)) {
1337 mtx_mode = 0;
1338 } else if (g_sc->info.out_fmt == RGB24) {
1339 mtx_mode = 2;
1340 } else if (g_sc->info.out_fmt == NV12_GREY) {
1341 mtx_mode = 0;
1342 }
1343 } else if ((g_sc->info.in_fmt == NV12_YUV) ||
1344 (g_sc->info.in_fmt == NV12_GREY)) {
1345 if (g_sc->info.out_fmt == NV12_GREY) {
1346 mtx_mode = 0;
1347 }
1348 }
1349 enable_isp_scale(1,
1350 g_sc->info.src_w, g_sc->info.src_h,
1351 g_sc->info.out_w, g_sc->info.out_h, 0, 1, mtx_mode,
1352 &isp_frame);
1353 return 0;
1354 }
1355
am_sc_start(void)1356 int am_sc_start(void)
1357 {
1358 if (!g_sc) {
1359 pr_info("%d, g_sc is NULL.\n", __LINE__);
1360 return -1;
1361 }
1362
1363 /* switch int to sync reset for start and delay frame */
1364 sc_wr_reg_bits(ISP_SCWR_TOP_CTRL, 1, 3, 1);
1365 return 0;
1366 }
1367
am_sc_reset(void)1368 int am_sc_reset(void)
1369 {
1370 return 0;
1371 }
1372
am_sc_stop(void)1373 int am_sc_stop(void)
1374 {
1375 if (!g_sc) {
1376 pr_info("%d, g_sc is NULL.\n", __LINE__);
1377 return -1;
1378 }
1379
1380 if (!stop_flag) {
1381 sc_wr_reg_bits(ISP_SCWR_TOP_CTRL, 0, 1, 1);
1382 sc_wr_reg_bits(ISP_SCWR_TOP_CTRL, 0, 0, 1);
1383 sc_wr_reg_bits(ISP_SCWR_TOP_CTRL, 0, 3, 1);
1384
1385 kfifo_free(&g_sc->sc_fifo_in);
1386 #ifdef ENABLE_SC_BOTTOM_HALF_TASKLET
1387 // kill tasklet
1388 kfifo_free(&sc_tasklet.sc_fifo_out);
1389 tasklet_kill( &sc_tasklet.tasklet_obj );
1390 frame_id = 0;
1391 #endif
1392
1393 start_delay_cnt = 0;
1394 cur_frame = NULL;
1395 pre_frame = NULL;
1396
1397 if (temp_buf != NULL) {
1398 kfree(temp_buf);
1399 temp_buf = NULL;
1400 }
1401 free_irq(g_sc->irq, (void *)g_sc);
1402
1403 g_sc->info.src_w = 0;
1404 g_sc->info.src_h = 0;
1405 stop_flag = true;
1406 }
1407
1408 return 0;
1409 }
1410
am_sc_system_deinit(void)1411 int am_sc_system_deinit(void)
1412 {
1413 if (!g_sc) {
1414 pr_info("%d, g_sc is NULL.\n", __LINE__);
1415 return -1;
1416 }
1417
1418 iounmap(g_sc->base_addr);
1419 g_sc->base_addr = NULL;
1420
1421 kfree(g_sc);
1422 g_sc = NULL;
1423 return 0;
1424 }
1425
1426
am_sc_hw_deinit(void)1427 int am_sc_hw_deinit(void)
1428 {
1429 return 0;
1430 }
1431
1432