• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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