1 /*
2 *
3 * SPDX-License-Identifier: GPL-2.0
4 *
5 * Copyright (C) 2011-2018 ARM 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
20 #include <linux/version.h>
21 #include <linux/irqreturn.h>
22 #include <linux/of_address.h>
23 #include <linux/of_irq.h>
24 #include <linux/ioport.h>
25 #include <linux/of_platform.h>
26 #include <linux/dma-mapping.h>
27 #include <linux/interrupt.h>
28 #include <linux/kernel.h>
29 #include <linux/device.h>
30 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 19, 0))
31 #include <linux/dma-contiguous.h>
32 #endif
33 #include <linux/of_reserved_mem.h>
34 #include <linux/platform_device.h>
35 #include <linux/device.h>
36 #include <linux/module.h>
37 #include <linux/of_fdt.h>
38 #include <linux/fs.h>
39 #include <linux/uaccess.h>
40 #include <linux/io.h>
41 #include <linux/kfifo.h>
42 #include <linux/completion.h>
43 #include <linux/jiffies.h>
44 #include <linux/version.h>
45 #include <linux/slab.h>
46
47 #include "acamera_types.h"
48 #include "acamera_logger.h"
49 #include "system_am_md.h"
50
51 #define AM_MD_IRQ 131
52 #define AM_MD_MEMORY 0x70000000
53 #define AM_MD_NAME "amlogic, isp-md"
54
55 static struct am_md *g_md;
56
57 T_MD_PRM am_md_reg;
58
59 /*****************************************************************/
write_reg(unsigned long addr,uint32_t val)60 static uint32_t write_reg(unsigned long addr, uint32_t val)
61 {
62 void __iomem *io_addr;
63
64 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 19, 0))
65 io_addr = ioremap_nocache(addr, 8);
66 #else
67 io_addr = ioremap(addr, 8);
68 #endif
69 if (io_addr == NULL) {
70 LOG(LOG_ERR, "%s: Failed to ioremap addr\n", __func__);
71 return -1;
72 }
73 __raw_writel(val, io_addr);
74 iounmap(io_addr);
75
76 return 0;
77 }
78
md_write_reg(int addr,uint32_t val)79 static inline void md_write_reg(int addr, uint32_t val)
80 {
81 void __iomem *base = g_md->base_addr;
82
83 if (base != NULL) {
84 base = base + addr;
85 writel(val, base);
86 } else
87 pr_err("isp-sc write register failed.\n");
88
89 return;
90 }
91
92
93 /*************************************************************************
94 > File Name: isp_md_pkg.c
95 > Author: ma6174
96 > Mail: ma6174@163.com
97 > Created Time: Thu 09 May 2019 02:18:28 PM PDT
98 ************************************************************************/
99 //int param_md_init(T_MD_PRM *reg, int xsize, int ysize)
param_md_init(T_MD_PRM * reg)100 int param_md_init(T_MD_PRM *reg)
101 {
102 //int xsize = 1920;
103 //int ysize = 1080;
104 int k;
105 #if 0
106 int bld_coefs[4] = {32, 32, 32, 32};
107 // (256)x 4xstep(1+1 + 2 + 4 + 8 + 16 +32 +64 +128 + 128 + 128 + 128 + 128 + 128 + 128) = 61 taps
108 int eotf_u12[61] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, // xdelt = 1, 1
109 10, 12, 14, 16, 20, 24, 28, 32, // xdelt = 2, 4
110 40, 48, 56, 64, 80, 96, 112, 128, // xdelt = 8, 16
111 160, 192, 224, 256, 320, 384, 448, 512, // xdelt = 32, 64
112 640, 768, 892,1024, 1152,1280,1408,1536, // xdelt = 128
113 1664,1792,1920,2048, 2176,2304,2432,2560,
114 2688,2816,2944,3072, 3200,3328,3456,3584,
115 3712,3840,3968,4095}; // linear one
116 int eotf_u12_sqrt[61] = { 0, 64, 91, 111, 128, 143, 157, 169, 181, // xdelt = 1, 1
117 202, 222, 239, 256, 286, 314, 339, 362, // xdelt = 2, 4
118 405, 443, 479, 512, 572, 627, 677, 724, // xdelt = 8, 16
119 810, 887, 958,1024, 1145,1254,1355,1448, // xdelt = 32, 64
120 1619,1774,1911,2048, 2172,2290,2401,2508, // xdelt = 128
121 2611,2709,2804,2896, 2985,3072,3156,3238,
122 3318,3396,3473,3547, 3620,3692,3762,3831,
123 3899,3966,4031,4095}; // square root
124 int inpc_winxxyy[4] = {0, xsize, 0, ysize};
125 int win_xxyy[4]= {0, 1023, 0, 1023};
126 #endif
127 //MIN((eotf_u10+2)>>2,1023):
128 int eotf_u10[61] = { 0, 0, 1, 1, 1, 1, 2, 2, 2, // xdelt = 1, 1
129 3, 3, 4, 4, 5, 6, 7, 8, // xdelt = 2, 4
130 10, 12, 14, 16, 20, 24, 28, 32, // xdelt = 8, 16
131 40, 48, 56, 64, 80, 96, 112, 128, // xdelt = 32, 64
132 160, 192, 223, 256, 288, 320, 352, 384, // xdelt = 128
133 416, 448, 480, 512, 544, 576, 608, 640,
134 672, 704, 736, 768, 800, 832, 864, 896,
135 928, 960, 992,1023}; // linear one
136 //RTL CONTROL
137 //REG_NAME: MD_TOP_GCLK
138 reg->reg_md_gclk = 0; // u32: clock gate control
139 // end
140
141 //REG_NAME: MD_TOP_CTRL
142 reg->reg_md_top_ctrl = 0x3c0204; // u32: md top ntrol
143 // end
144 //REG_NAME: MD_WR_CTRL0
145 reg->reg_wr_axi_wr_en =1; //u1: axi wr enable
146 reg->reg_wr_axi_req_en =1; //u1: axi request enable
147 reg->reg_wr_axi_bypass =0; //u1: bypass axi wr
148 reg->reg_wr_total_size =57600; //u24: pixels hsize * vsize
149 //end
150 //REG_NAME: MD_WR_CTRL1
151 reg->reg_wr_base_addr = 0x80000000; //u32: wr axi base address
152 //end
153 //REG_NAME: MD_WR_CTRL2
154 //u9
155 reg->reg_wr_burst_lens= 2; //u3: burst_lens limiation, burst_size: 0: 1x128, 1: 2x128, 2��3: 4x128
156 reg->reg_wr_req_th = 4; //u4: fifo depth req_th * 8 *128 bits in fifo. >=1
157 reg->reg_wr_urgent_ctrl = 0; //u16: urgent control, randome
158 //end
159 //REG_NAME: MD_WR_CTRL3
160 reg->reg_wr_awid = 0; //u8: wr id ,random
161 reg->reg_wr_awprot = 0; //u3: awprot for security control,random
162 //u21
163 //end
164 //REG_NAME:MD_RO_WR_ST0
165 reg->RO_wr_st0 = 0; //u32
166 //end
167 //REG_NAME:MD_RO_WR_ST1
168 reg->RO_wr_st1 = 0; //u32
169 //end
170 //REG_NAME:MD_RO_WR_ST2
171 reg->RO_wr_st2 = 0; //u32
172 //end
173
174 //REG_NAME: MD_RD_CTRL0
175 reg->reg_rd_axi_rd_en =1; //u1: axi rd enable
176 reg->reg_rd_axi_req_en =1; //u1: axi request enable
177 //u6
178 reg->reg_rd_total_size = 57600; //u24: total size hsize*vsize, <= 1024*1024
179 //end
180 //REG_NAME: MD_RD_CTRL1
181 reg->reg_rd_base_addr = 0x80000000; //u32
182 //end
183 //REG_NAME:MD_RD_CTRL2
184 //u9
185 reg->reg_rd_burst_lens = 2 ; //u3: burst_lens limiation, burst_size: 0: 1x128, 1: 2x128, 2��3: 4x128
186 reg->reg_rd_req_th = 4 ; //u4: fifo depth req_th * 8 *128 bits in fifo.
187 reg->reg_rd_urgent_ctrl = 0 ; //u16: urgent control
188 //end
189 //REG_NAME:MD_RD_CTRL3
190 reg->reg_rd_arid = 0 ; //u8: wr id
191 reg->reg_rd_arprot = 0; //u3: awprot for security control
192 //u21
193 //end
194 //REG_NAME:MD_RO_RD_ST0
195 reg->RO_rd_st0 =0 ; //u32
196 //end
197 //REG_NAME:MD_RO_RD_ST1
198 reg->RO_rd_st1 =0 ; //u32
199 //end
200
201
202 // cmodel control
203 //REG_NAME: MD_INPUT_CTRL0
204 reg->reg_md_enable = 1; //u1: lp motion detection enable, 0: disable; 1: enable
205 reg->reg_md_raw_xphase_ofst= 0; //u1: horizontal phase of the raw data, 0: start wz R-col (RGGB or GBRG); 1: start wz B-col (GRBG or BGGR)
206 reg->reg_md_raw_yphase_ofst= 0; //u1: vertical phase of the raw data, 0: start wz R-row (RGGB or GRBG); 1: start wz B-row (GRBG or BGGR)
207 reg->reg_md_is_on_raw = 1; //u1: the md_sel is on raw data, set together with md_sel. 0: YUV/RGB; 1:RAW
208
209 reg->reg_md_input_sel = 1; //u4: data selection for the lp motion detection. 0: raw sensor input; 1: raw WDR stitch; 2:raw fed_out(nr_in); 3:raw mirror_in; 4?? RGB after dms; 5: IRout; 6:RGB/YUV after gamma; 7: fe_o yuv bypass , default=1
210
211 reg->reg_md_input_ls = 0; //u4, E domain data left shift bit num to align with u20 Odomain data and will clip to u10 by droping 10lsb, e.g. yuv is u12, then ls = 8;
212 //u20
213 //end
214
215 //REG_NAME: MD_INPUT_SIZE
216 //u3
217 reg->reg_md_input_xsize = 1920; //u13, xsize of the input in pixels, set to image xsize
218 //u3
219 reg->reg_md_input_ysize = 1080; //u13, ysize of the input in pixels, set to image ysize
220 //end
221
222 //step-I O domain reg_RGGB data do the black-level sub, gain, OETF
223 //for (k=0;k<4;k++) {
224 // if (reg->reg_md_is_on_raw==1)
225 // reg->reg_md_inpc_winxxyy[k] = inpc_winxxyy[k]>>1;//u12x4, input combined window for processing.
226 // else
227 // reg->reg_md_inpc_winxxyy[k] = inpc_winxxyy[k]; //u12x4, input combined window for processing.
228 //REG_NAME: MD_WINXY_0
229 //u4
230 reg->reg_md_inpc_winxxyy[0] = 0; //u12, input combined window for processing. aligned to 2
231 //u4
232 reg->reg_md_inpc_winxxyy[1] = 960; //u12, input combined window for processing.
233 //end
234 //REG_NAME: MD_WINXY_1
235 //u4
236 reg->reg_md_inpc_winxxyy[2] = 0; //u12, input combined window for processing.
237 //u4
238 reg->reg_md_inpc_winxxyy[3] = 540; //u12, input combined window for processing.
239 //end
240
241 //REG_NAME: MD_RGGB_OFSET_0
242 //u12
243 reg->reg_md_rggb_ofset[0]= 0; //s20, ofset to the components, same as the ISP mission mode ofset
244 //end
245 //REG_NAME: MD_RGGB_OFSET_1
246 //u12
247 reg->reg_md_rggb_ofset[1]= 0; //s20, ofset to the components, same as the ISP mission mode ofset
248 //end
249 //REG_NAME: MD_RGGB_OFSET_2
250 //u12
251 reg->reg_md_rggb_ofset[2]= 0; //s20, ofset to the components, same as the ISP mission mode ofset
252 //end
253 //REG_NAME: MD_RGGB_OFSET_3
254 //u12
255 reg->reg_md_rggb_ofset[3]= 0; //s20, ofset to the components, same as the ISP mission mode ofset
256 //end
257
258
259 //reg->reg_md_rggb_gain[k] = 1024; //u12x4, gain to different channel, normalize to 1024 as "1.0"
260 //REG_NAME: MD_RGGB_GAIN_0
261 //u4
262 reg->reg_md_rggb_gain[0] = 1024; //u12, gain to different channel, normalize to 1024 as "1.0"
263 //u4
264 reg->reg_md_rggb_gain[1] = 1024; //u12, gain to different channel, normalize to 1024 as "1.0"
265 //end
266 //REG_NAME: MD_RGGB_GAIN_1
267 //u4
268 reg->reg_md_rggb_gain[2] = 1024; //u12, gain to different channel, normalize to 1024 as "1.0"
269 //u4
270 reg->reg_md_rggb_gain[3] = 1024; //u12, gain to different channel, normalize to 1024 as "1.0"
271 //end
272 //reg->reg_md_bld_coefs[k] = bld_coefs[k]; //u8x4, blender coef of the components to Y, normalize to 128 as "1"
273
274 //REG_NAME: MD_RGGB_COEF
275 reg->reg_md_bld_coefs[0] = 32; //u8, blender coef of the components to Y, normalize to 128 as "1"
276 reg->reg_md_bld_coefs[1] = 32; //u8, blender coef of the components to Y, normalize to 128 as "1"
277 reg->reg_md_bld_coefs[2] = 32; //u8, blender coef of the components to Y, normalize to 128 as "1"
278 reg->reg_md_bld_coefs[3] = 32; //u8, blender coef of the components to Y, normalize to 128 as "1"
279 //end
280
281 //}
282 //for (k=0;k<61;k++)
283 //reg->reg_md_comb_eotf[k] = MIN((eotf_u12[k]+2)>>2, 1023); //u10x61,OETF, piece wise lut TODO
284 for(k=0; k<20; k++) {
285 //REG_NAME: MD_COMB_EOTF
286 reg->reg_md_comb_eotf[3*k] = eotf_u10[3*k]; //u10, piec wise lut
287 reg->reg_md_comb_eotf[3*k+1] = eotf_u10[3*k+1]; //u10, piec wise lut
288 reg->reg_md_comb_eotf[3*k+2] = eotf_u10[3*k+2]; //u10, piec wise lut
289 //u2
290 //end
291 }
292 //for(k=20; k<21; k++) {
293 //REG_NAME: MD_COMB_EOTF_20
294 //u22
295 reg->reg_md_comb_eotf[60] = eotf_u10[60]; //u10, piec wise lut
296 //end
297 //}
298 //REG_NAME: MD_EOTF
299 //u30
300 reg->reg_md_bld_use_max = 0; //u1, use max of the components for the blender, 0: no max, 1:max (more sensitive)
301 reg->reg_md_eotf_en = 1; //u1,OETF, piece wise lut enable
302 //end
303 //step-II the downscaled frame buffer size
304 //REG_NAME: MD_DS_STEP
305 //u12
306 reg->reg_ds_hstep = 3; //u4: integer pixel ratio for horizontal scalar, o2i_ratio= 1/step, 1��15
307 //u12
308 reg->reg_ds_vstep = 3; //u4: integer pixel ratio for vertical scalar, o2i_ratio= 1/step??1��15
309 //end
310
311 //REG_NAME: MD_DS_OSIZE
312 //u4
313 //reg->reg_ds_ocol = (reg->reg_md_is_on_raw==1)? (xsize/2/reg->reg_ds_hstep+1):(xsize/reg->reg_ds_hstep+1); //u12: actual downscaled field buffer col number.
314 //<1024x1024
315 reg->reg_ds_ocol = 320; //u12: actual downscaled field buffer col number.
316 //u4
317 //reg->reg_ds_orow = (reg->reg_md_is_on_raw==1)? (ysize/2/reg->reg_ds_vstep+1):(ysize/reg->reg_ds_vstep+1); //u12: actual downscaled field buffer row number.
318 reg->reg_ds_orow = 180; //u12: actual downscaled field buffer row number.
319 //end
320
321 //REG_NAME: MD_DS_CTRL
322 //u21
323 reg->reg_ds_inp8b = 0; //u1, input to ds accum cell use 8bits instead of 10bits,only set to 1 when (v_step*h_step>64) 0: input 10bits, 1: input 8bits
324 //reg->reg_ds_norm = MIN(((reg->reg_ds_inp8b)? 4096:1024)/(reg->reg_ds_hstep*reg->reg_ds_vstep), 1023); //u10; normalization gain to the accum to get the 8bits data for ddr, norm = (inp8b? 4096:1024)/pixelnum(v_step*h_step)
325 reg->reg_ds_norm = 256; //u10; normalization gain to the accum to get the 8bits data for ddr, norm = (inp8b? 4096:1024)/pixelnum(v_step*h_step)
326 //end
327
328
329 //step-III do the sad calculation and sum-up for RO
330 //REG_NAME: MD_CORE_CTRL0
331 //u4
332 reg->reg_md_sad_mode = 2; //u3, window size for sad, 0: no sad, 1: 1x7, 2:3x3; 3:3x5, else 3x7
333 reg->reg_md_edge_mode = 0; //u1, mode for the pre and cur edge calculation, 0: min(edge_pre, edge_cur); 1: avg(edge_pre, edge_cur)
334 reg->reg_md_coring = 6; //u8, coring for sad for noise robustness. sad_core = max(sad-coring,0);
335 //u2
336 reg->reg_md_edge_ratio = 4; //u6, ratio to edge as dynamic coring part, final_coring or 1b_thrd = (edge*ratio + coring); norm to 16 as '1'
337 //u8
338 //end
339 //for (k=0;k<4; k++)
340 //reg->reg_md_win_xxyy[k] = win_xxyy[k]; //u8x4: window for motion sum statistics on down-scaled image. [x_st x_ed; y_st y_ed]*4
341
342 // set the win_xxyy, avoid the out of range
343 //if (reg->reg_md_is_on_raw==1) {
344 // reg->reg_md_win_xxyy[1] = xsize/2/(reg->reg_ds_hstep);
345 // reg->reg_md_win_xxyy[3] = ysize/2/(reg->reg_ds_vstep); }
346 //else{
347 // reg->reg_md_win_xxyy[1] = xsize/(reg->reg_ds_hstep);
348 // reg->reg_md_win_xxyy[3] = ysize/(reg->reg_ds_vstep); }
349 //REG_NAME: MD_WIN_XXYY0
350 //u6
351 reg->reg_md_win_xxyy[0] = 0; //u10 window for motion sum statistics on down-scaled image. [x_st x_ed; y_st y_ed]*4
352 //u6
353 reg->reg_md_win_xxyy[1] = 1023; //u10 window for motion sum statistics on down-scaled image. [x_st x_ed; y_st y_ed]*4
354 //end
355 //REG_NAME: MD_WIN_XXYY1
356 //u6
357 reg->reg_md_win_xxyy[2] = 0; //u10 window for motion sum statistics on down-scaled image. [x_st x_ed; y_st y_ed]*4
358 //u6
359 reg->reg_md_win_xxyy[3] = 1023; //u10 window for motion sum statistics on down-scaled image. [x_st x_ed; y_st y_ed]*4
360 //end
361
362 // the output sum of motion, put to read-only registers
363 //REG_NAME: RO_MD_SAD_SUM
364 //u4
365 reg->RO_md_sad_sum = 0; //u28, sum of the motion sad for all the pixels within the window;
366 //end
367 //REG_NAME: RO_MD_1BM_SUM
368 //u12
369 reg->RO_md_1bm_sum = 0; //u20, sum of the 1bit motion for all the pixels within the window;
370 //end
371 //REG_NAME: RO_MD_EDG_SUM
372 //u4
373 reg->RO_md_edg_sum = 0; //u28, sum of the edge info for all the pixels within the window;
374 //end
375
376 // to HW decision on is_motion and send out interupt to CPU
377 //valid_num = (reg->reg_md_win_xxyy[1]-reg->reg_md_win_xxyy[0]+ 1)*(reg->reg_md_win_xxyy[3]-reg->reg_md_win_xxyy[2] + 1)*16; //2^^24
378 //reg->reg_ismot_sad_thrd = MIN(16*((valid_num*64)>>10), (1<<24)-1); //u24, threshold to sum_sad for current frame is motion
379 //REG_NAME: MD_ISMOT_SAD_THRD
380 //u8
381 reg->reg_ismot_sad_thrd = 600; //u24, threshold to sum_sad for current frame is motion
382 //end
383 //REG_NAME: MD_ISMOT_1BM_THRD
384 //u16
385 //reg->reg_ismot_1bm_thrd = MIN(((valid_num*64)>>10), (1<<16)-1) ; //u16, threshold to sum_1bm for current frame consider as motion
386 reg->reg_ismot_1bm_thrd = 600; //u16, threshold to sum_1bm for current frame consider as motion
387 //end
388
389 //added for new feature by Augustine
390 //REG_NAME: MD_WR_P_BADDR
391 reg->reg_wr_base_addr_p = 0x80008000; //u32,pre-pre base addr
392 //end
393
394 //REG_NAME: MD_RD_P_BADDR
395 reg->reg_rd_base_addr_p = 0x80008000; //u32,pre-pre base addr
396 //end
397
398 return 0;
399 }
400
param_md_input(T_MD_PRM * reg,int hsize_i,int vsize_i,int in_sel)401 int param_md_input(T_MD_PRM *reg, int hsize_i, int vsize_i, int in_sel)
402 {
403 reg->reg_md_input_sel = in_sel;
404 reg->reg_md_input_xsize = hsize_i;
405 reg->reg_md_input_ysize = vsize_i;
406 if (reg->reg_md_input_sel>3) {
407 reg->reg_md_is_on_raw = 0;
408 reg->reg_md_input_ls = 8;
409 reg->reg_md_eotf_en = 0; //do oe function
410 }
411
412 return 0;
413 }
414
param_md_scale(T_MD_PRM * reg,int hsize_i,int vsize_i,int hsize_o,int vsize_o,int32_t base_axi_addr)415 int param_md_scale(T_MD_PRM *reg, int hsize_i, int vsize_i, int hsize_o, int vsize_o, int32_t base_axi_addr)
416 {
417 reg->reg_ds_hstep = (reg->reg_md_is_on_raw==1)? hsize_i/2/hsize_o : hsize_i/hsize_o ;
418 reg->reg_ds_vstep = (reg->reg_md_is_on_raw==1)? vsize_i/2/vsize_o : vsize_i/vsize_o ;
419
420 reg->reg_ds_ocol = (reg->reg_md_is_on_raw==1)? (hsize_i/2/reg->reg_ds_hstep):(hsize_i/reg->reg_ds_hstep);
421 reg->reg_ds_orow = (reg->reg_md_is_on_raw==1)? (vsize_i/2/reg->reg_ds_vstep):(vsize_i/reg->reg_ds_vstep);
422
423 reg->reg_wr_base_addr = base_axi_addr; //u32,pre-pre base addr
424 //end
425
426 //REG_NAME: MD_RD_P_BADDR
427 reg->reg_rd_base_addr = base_axi_addr; //u32,pre-pre base addr
428 //end
429 reg->reg_wr_total_size = reg->reg_ds_ocol * reg->reg_ds_orow;
430 reg->reg_rd_total_size = reg->reg_ds_ocol * reg->reg_ds_orow;
431
432 return 0;
433
434 }
435
param_md_detect(T_MD_PRM * reg,int md_sad_thrd,int md_1bm_thrd)436 int param_md_detect(T_MD_PRM *reg, int md_sad_thrd, int md_1bm_thrd)
437 {
438 reg->reg_ismot_sad_thrd = md_sad_thrd;
439 reg->reg_ismot_1bm_thrd = md_1bm_thrd;
440 return 0;
441 }
442
param_md_set(T_MD_PRM * reg)443 int param_md_set(T_MD_PRM *reg)
444 {
445 int k,sel;
446 sel = 0;
447 write_reg(MD_TOP_CTRL, reg->reg_md_top_ctrl);// = 0x3c0204;
448 write_reg(MD_WR_CTRL0, (reg->reg_wr_axi_wr_en<<31)|
449 (reg->reg_wr_axi_req_en<<30)|
450 (reg->reg_wr_axi_bypass<<29)|
451 (reg->reg_wr_total_size & 0xffffff));// =57600;
452
453 write_reg(MD_WR_CTRL1, reg->reg_wr_base_addr);// = 0x80000000;
454
455 write_reg(MD_RD_CTRL0, (reg->reg_rd_axi_rd_en<<31)|
456 (reg->reg_rd_axi_req_en<<30)|
457 (reg->reg_rd_total_size & 0xffffff));// =57600;
458
459 write_reg(MD_RD_CTRL1, reg->reg_rd_base_addr);// = 0x80000000;
460
461 write_reg(MD_INPUT_SIZE,
462 ((reg->reg_md_input_xsize & 0x1fff) <<16) |
463 (reg->reg_md_input_ysize & 0x1fff));
464
465 write_reg(MD_WINXY_0 ,
466 ((reg->reg_md_inpc_winxxyy[0] & 0x1fff)<<16) |
467 ((reg->reg_md_inpc_winxxyy[1] & 0x1fff)));
468
469 write_reg(MD_WINXY_1,
470 ((reg->reg_md_inpc_winxxyy[2] & 0x1fff)<<16) |
471 ((reg->reg_md_inpc_winxxyy[3] & 0x1fff)));
472
473 write_reg(MD_RGGB_OFSET_0 , reg->reg_md_rggb_ofset[0]);
474 write_reg(MD_RGGB_OFSET_1 , reg->reg_md_rggb_ofset[1]);
475 write_reg(MD_RGGB_OFSET_2 , reg->reg_md_rggb_ofset[2]);
476 write_reg(MD_RGGB_OFSET_3 , reg->reg_md_rggb_ofset[3]);
477
478 write_reg(MD_RGGB_GAIN_0,
479 ((reg->reg_md_rggb_gain[0] & 0xfff)<<16) |
480 ((reg->reg_md_rggb_gain[1] & 0xfff)));
481
482 write_reg(MD_RGGB_GAIN_1,
483 ((reg->reg_md_rggb_gain[2] & 0xfff)<<16) |
484 ((reg->reg_md_rggb_gain[3] & 0xfff)));
485
486
487 write_reg(MD_RGGB_COEF,
488 ((reg->reg_md_bld_coefs[0] & 0xff)<<24)|
489 ((reg->reg_md_bld_coefs[1] & 0xff)<<16)|
490 ((reg->reg_md_bld_coefs[2] & 0xff)<<18)|
491 ((reg->reg_md_bld_coefs[3] & 0xff)));
492
493
494 for(k=0; k<20; k++) {
495 write_reg(MD_COMB_EOTF_0 + k*4,
496 ((reg->reg_md_comb_eotf[3*k] & 0x3ff) << 22)|
497 ((reg->reg_md_comb_eotf[3*k+1] & 0x3ff) << 12)|
498 ((reg->reg_md_comb_eotf[3*k+2] & 0x3ff) << 2));
499
500 }
501 write_reg(MD_COMB_EOTF_20, reg->reg_md_comb_eotf[60] & 0x3ff);
502
503 write_reg(MD_EOTF,
504 (reg->reg_md_bld_use_max << 1) |
505 reg->reg_md_eotf_en);
506
507 write_reg(MD_DS_STEP,
508 (reg->reg_ds_hstep << 16) |
509 reg->reg_ds_vstep);
510
511 write_reg(MD_DS_OSIZE,
512 (reg->reg_ds_ocol << 16) |
513 reg->reg_ds_orow);
514
515 write_reg(MD_DS_CTRL,
516 (reg->reg_ds_inp8b <<10)|
517 reg->reg_ds_norm);
518
519 write_reg(MD_CORE_CTRL0,
520 ((reg->reg_md_sad_mode & 0x7)<<25) |
521 ((reg->reg_md_edge_mode & 0x1) << 24) |
522 ((reg->reg_md_coring & 0xff) <<16) |
523 ((reg->reg_md_edge_ratio & 0x3f) << 8));
524
525 write_reg(MD_WIN_XXYY0 ,
526 ((reg->reg_md_win_xxyy[0] & 0x3ff)<<16) |
527 ((reg->reg_md_win_xxyy[1] & 0x3ff)));
528
529 write_reg(MD_WIN_XXYY1,
530 ((reg->reg_md_win_xxyy[2] & 0x3ff)<<16) |
531 ((reg->reg_md_win_xxyy[3] & 0x3ff)));
532
533
534 write_reg(MD_ISMOT_SAD_THRD, reg->reg_ismot_sad_thrd);// = 65536;d
535 write_reg(MD_ISMOT_1BM_THRD, reg->reg_ismot_1bm_thrd);// = 4096;
536 write_reg(MD_WR_P_BADDR, reg->reg_wr_base_addr_p);// = 0x80008000;
537 write_reg(MD_RD_P_BADDR, reg->reg_rd_base_addr_p);// = 0x80008000;
538
539
540 write_reg(MD_INPUT_CTRL0,
541 ((reg->reg_md_enable & 0x1) <<31)|
542 ((reg->reg_md_raw_xphase_ofst & 0x1) <<30)|
543 ((reg->reg_md_raw_yphase_ofst & 0x1) <<29)|
544 ((reg->reg_md_is_on_raw & 0x1) <<28)|
545 ((reg->reg_md_input_sel & 0xf) <<24)|
546 ((reg->reg_md_input_ls & 0xf) <<20));
547
548 return 0;
549 }
550
motion_detection_isr(int irq,void * para)551 static irqreturn_t motion_detection_isr(int irq, void *para)
552 {
553 pr_err("Motion detection event\n");
554
555 return IRQ_HANDLED;
556 }
557
am_md_parse_dt(struct device_node * node)558 int am_md_parse_dt(struct device_node *node)
559 {
560 int rtn = -1;
561 int irq = -1;
562 struct resource rs;
563 struct am_md *t_md = NULL;
564
565 if (node == NULL) {
566 pr_err("%s: Error input param\n", __func__);
567 return -1;
568 }
569
570 rtn = of_device_is_compatible(node, AM_MD_NAME);
571 if (rtn == 0) {
572 pr_err("%s: Error match compatible\n", __func__);
573 return -1;
574 }
575
576 t_md = kzalloc(sizeof(*t_md), GFP_KERNEL);
577 if (t_md == NULL) {
578 pr_err("%s: Failed to alloc isp-md\n", __func__);
579 return -1;
580 }
581
582 t_md->of_node = node;
583
584 rtn = of_address_to_resource(node, 0, &rs);
585 if (rtn != 0) {
586 pr_err("%s:Error get isp-md reg resource\n", __func__);
587 goto reg_error;
588 }
589
590 pr_info("%s: rs idx info: name: %s\n", __func__, rs.name);
591 if (strcmp(rs.name, "isp_md") == 0) {
592 t_md->reg = rs;
593 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 19, 0))
594 t_md->base_addr = ioremap_nocache(t_md->reg.start, resource_size(&t_md->reg));
595 #else
596 t_md->base_addr = ioremap(t_md->reg.start, resource_size(&t_md->reg));
597 #endif
598 }
599
600 irq = irq_of_parse_and_map(node, 0);
601 if (irq <= 0) {
602 pr_err("%s:Error get isp_md irq\n", __func__);
603 goto irq_error;
604 }
605
606 t_md->irq = irq;
607 pr_info("%s:rs info: irq: %d\n", __func__, t_md->irq);
608
609 t_md->p_dev = of_find_device_by_node(node);
610
611 g_md = t_md;
612
613 return 0;
614 irq_error:
615 iounmap(t_md->base_addr);
616 t_md->base_addr = NULL;
617
618 reg_error:
619 if (t_md != NULL)
620 kfree(t_md);
621
622 return -1;
623 }
624
am_md_init(void)625 void am_md_init(void)
626 {
627 int ret = 0;
628
629 param_md_init(&am_md_reg);
630 param_md_input(&am_md_reg, 1920, 1080, 1);
631 param_md_scale(&am_md_reg, 1920, 1080, 480, 270, AM_MD_MEMORY);
632 param_md_set(&am_md_reg);
633
634 ret = request_irq(g_md->irq, motion_detection_isr, IRQF_SHARED | IRQF_TRIGGER_RISING,
635 "isp-md-irq", (void *)g_md);
636
637 return;
638 }
639
am_md_deinit(void)640 void am_md_deinit(void)
641 {
642 if (g_md == NULL) {
643 pr_err("Error g_md is NULL\n");
644 return;
645 }
646
647 if (g_md->base_addr != NULL)
648 {
649 iounmap(g_md->base_addr);
650 g_md->base_addr = NULL;
651 }
652
653 if(g_md->irq)
654 free_irq(g_md->irq, NULL);
655
656 if(g_md)
657 {
658 kfree(g_md);
659 g_md = NULL;
660 }
661 }
662