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 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
22 #include <linux/ktime.h>
23 #include <linux/time64.h>
24 #include <linux/timekeeping.h>
25 #endif
26 #include <linux/device.h>
27 #include <linux/slab.h>
28 #include <linux/mm.h>
29 #include <linux/fs.h>
30 #include <linux/miscdevice.h>
31 #include <linux/uaccess.h>
32 #include <linux/spinlock_types.h>
33 #include <linux/wait.h>
34 #include <linux/version.h>
35 #include <linux/vmalloc.h>
36 #include <linux/kfifo.h>
37 #include <linux/kthread.h>
38 #include <linux/delay.h>
39 #include <linux/of_platform.h>
40 #include <linux/of_fdt.h>
41 #include <linux/of_reserved_mem.h>
42 #include <linux/interrupt.h>
43
44 #include "acamera_fw.h"
45 #include "acamera.h"
46 #include "autocapture_fsm.h"
47 #include "acamera_firmware_settings.h"
48 #include "system_autowrite.h"
49 #include "system_am_sc.h"
50 #include "acamera_autocap.h"
51 #include "acamera_autocap_api.h"
52 #include "system_stdlib.h"
53 #include "acamera_3aalg_preset.h"
54
55 #ifdef LOG_MODULE
56 #undef LOG_MODULE
57 #define LOG_MODULE LOG_MODULE_AUTOCAPTURE
58 #endif
59
60 #define AUTOCAP_DEV_NAME_LEN 20
61 #define AUTOCAP_DEV_FORMAT "ac_autocap%d"
62 #define AUTOCAP_DEV_PATH_FORMAT "/dev/" AUTOCAP_DEV_FORMAT
63 #define AUTOCAP_DEV_PATH_LEN ( AUTOCAP_DEV_NAME_LEN )
64
65 #define FW_FR_AUTO_CAP_BASE 0x70000000
66 #define FW_FR_AUTO_CAP_SIZE 0xBDD800
67 #define FW_DS1_AUTO_CAP_BASE 0x70C00000
68 #define FW_DS1_AUTO_CAP_SIZE 0x546000
69 #define FW_DS2_AUTO_CAP_BASE 0x71200000
70 #define FW_DS2_AUTO_CAP_SIZE 0x546000
71
72 #define ISP_FW_FRAME_BUF_INVALID 0 /* buffer data is invalid */
73 #define ISP_FW_FRAME_BUF_VALID 1 /* buffer data is valid */
74
75 #define SUPPORT_CHANNEL 3
76 #define V4L2_BUFFER_SIZE 6
77
78 #if PLATFORM_C308X
79 #define AUTOWRITE_MODULE
80 #endif
81 struct autocapture_context {
82 struct mutex fops_lock;
83 struct miscdevice autocap_dev;
84 int dev_minor_id;
85 char dev_name[AUTOCAP_DEV_NAME_LEN];
86 int dev_opened;
87
88 int fw_id;
89 int get_fr_ds;
90 int hw_reset;
91
92 int thread_stop;
93 uint32_t timestampe[2];
94 int frame_cnt[SUPPORT_CHANNEL];
95 tframe_t d_buff[SUPPORT_CHANNEL][V4L2_BUFFER_SIZE];
96 resource_size_t idx_buf[SUPPORT_CHANNEL][V4L2_BUFFER_SIZE];
97 struct kfifo read_fifo[SUPPORT_CHANNEL];
98 isp_v4l2_stream_t *pstream[SUPPORT_CHANNEL];
99 struct task_struct *kthread_stream;
100
101 #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0))
102 struct timeval t_frm;
103 #else
104 struct timespec64 t_frm;
105 #endif
106 struct autocap_image autocap_frame[SUPPORT_CHANNEL];
107
108 auto_write_cfg_t *auto_cap_cfg;
109
110 autocapture_fsm_t *p_fsm;
111 };
112
113 static struct autocapture_context autocapture_context[FIRMWARE_CONTEXT_NUMBER];
114
115 struct module_cfg_info pipe_cfg[SUPPORT_CHANNEL];
116 struct tasklet_struct tasklet_memcpy;
117 #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0))
118 struct timeval normal_fftt;
119 #else
120 struct timespec64 normal_fftt;
121 #endif
122
123 void fw_auto_cap_init(struct autocapture_context *p_ctx, void *cfg_info);
124 void fw_auto_cap_deinit(struct autocapture_context *p_ctx);
125 #ifdef AUTOWRITE_MODULES_V4L2_API
126 static int autocap_v4l2_stream_copy_thread( void *data );
127 #endif
128
autocapture_fops_mmap(struct file * f,struct vm_area_struct * vma)129 static int autocapture_fops_mmap( struct file *f, struct vm_area_struct *vma )
130 {
131 struct autocapture_context *p_ctx = (struct autocapture_context *)f->private_data;
132 unsigned long user_buf_len = vma->vm_end - vma->vm_start;
133 uint64_t fw_addr_read = 0;
134 int rc;
135
136 if(p_ctx->get_fr_ds == GET_FR)
137 fw_addr_read = FW_FR_AUTO_CAP_BASE;
138 else if(p_ctx->get_fr_ds == GET_DS1)
139 fw_addr_read = FW_DS1_AUTO_CAP_BASE;
140 else if(p_ctx->get_fr_ds == GET_DS2)
141 fw_addr_read = FW_DS2_AUTO_CAP_BASE;
142
143 #ifdef AUTOWRITE_MODULE
144 if(p_ctx->get_fr_ds == GET_FR)
145 fw_addr_read = autowrite_fr_start_address_read();
146 else if(p_ctx->get_fr_ds == GET_DS1)
147 fw_addr_read = autowrite_ds1_start_address_read();
148 else if(p_ctx->get_fr_ds == GET_DS2)
149 fw_addr_read = autowrite_ds2_start_address_read();
150 #endif
151
152 LOG(LOG_CRIT, "p_ctx->get_fr_ds:%d, fw_addr_read:%llx", p_ctx->get_fr_ds, fw_addr_read);
153
154 /* remap the kernel buffer into the user app address space. */
155 rc = remap_pfn_range( vma, vma->vm_start, fw_addr_read >> PAGE_SHIFT, user_buf_len, vma->vm_page_prot );
156 if ( rc < 0 ) {
157 LOG( LOG_ERR, "remap of autocap failed, return: %d.", rc );
158 return rc;
159 }
160
161 return 0;
162 }
163
autocapture_fops_open(struct inode * inode,struct file * f)164 static int autocapture_fops_open( struct inode *inode, struct file *f )
165 {
166 int rc;
167 int i;
168 struct autocapture_context *p_ctx = NULL;
169 int minor = iminor( inode );
170
171 for ( i = 0; i < acamera_get_context_number(); i++ ) {
172 if ( autocapture_context[i].dev_minor_id == minor ) {
173 p_ctx = &autocapture_context[i];
174 break;
175 }
176 }
177
178 if ( !p_ctx ) {
179 LOG( LOG_CRIT, "Fatal error, auto contexts is crashed, contents dump:%d",minor );
180 for ( i = 0; i < acamera_get_context_number(); i++ ) {
181 p_ctx = &autocapture_context[i];
182 LOG( LOG_CRIT, "%d): fw_id: %d, minor_id: %d, name: %s, p_fsm: %p.",
183 i, p_ctx->fw_id, p_ctx->dev_minor_id, p_ctx->dev_name, p_ctx->p_fsm );
184 }
185 return -ERESTARTSYS;
186 }
187
188 rc = mutex_lock_interruptible( &p_ctx->fops_lock );
189 if ( rc ) {
190 LOG( LOG_ERR, "access lock failed, rc: %d.", rc );
191 return rc;
192 }
193
194 if ( p_ctx->dev_opened ) {
195 LOG( LOG_ERR, "open failed, already opened." );
196 rc = -EBUSY;
197 } else {
198 p_ctx->dev_opened = 1;
199 rc = 0;
200 f->private_data = p_ctx;
201 }
202
203 mutex_unlock( &p_ctx->fops_lock );
204
205 return rc;
206 }
207
autocapture_fops_release(struct inode * inode,struct file * f)208 static int autocapture_fops_release( struct inode *inode, struct file *f )
209 {
210 int rc = 0;
211 struct autocapture_context *p_ctx = (struct autocapture_context *)f->private_data;
212
213 rc = mutex_lock_interruptible( &p_ctx->fops_lock );
214 if ( rc ) {
215 LOG( LOG_ERR, "Error: lock failed." );
216 return rc;
217 }
218
219 if ( p_ctx->dev_opened ) {
220 p_ctx->dev_opened = 0;
221 f->private_data = NULL;
222 } else {
223 LOG( LOG_CRIT, "Fatal error: wrong state dev_opened: %d.", p_ctx->dev_opened );
224 rc = -EINVAL;
225 }
226
227 mutex_unlock( &p_ctx->fops_lock );
228
229 return 0;
230 }
231
autocapture_fops_read(struct file * file,char __user * buf,size_t count,loff_t * ppos)232 static ssize_t autocapture_fops_read( struct file *file, char __user *buf, size_t count, loff_t *ppos )
233 {
234 int rc = 0;
235 struct autocapture_context *p_ctx = (struct autocapture_context *)file->private_data;
236
237 if(p_ctx->hw_reset)
238 {
239 #ifdef AUTOWRITE_MODULE
240 uint32_t time_lose = (normal_fftt.tv_sec*1000000 + normal_fftt.tv_usec)/1000 - p_ctx->autocap_frame[dma_fr].endtime;
241 time_lose = time_lose / 33;
242 p_ctx->timestampe[1] = time_lose;
243 LOG(LOG_CRIT, "RTOS ttff:%dus, Switch Lose frame:%d frames", p_ctx->timestampe[0], p_ctx->timestampe[1]);
244 rc = copy_to_user( buf, p_ctx->timestampe, sizeof(uint32_t) * 2 );
245 return rc;
246 #endif
247 }
248
249 if(p_ctx->get_fr_ds == GET_FR)
250 {
251 p_ctx->autocap_frame[dma_fr].format = system_hw_read_32(0x1c0ec) & 0xFF;
252 p_ctx->autocap_frame[dma_fr].imagesize = acamera_isp_input_port_frame_width_read(0) << 16;
253 p_ctx->autocap_frame[dma_fr].imagesize |= acamera_isp_input_port_frame_height_read(0);
254
255 #ifdef AUTOWRITE_MODULE
256 p_ctx->autocap_frame[dma_fr].imagebufferstride = autowrite_fr_image_buffer_stride_read();
257 p_ctx->autocap_frame[dma_fr].count = autowrite_fr_writer_frame_wcount_read();
258 p_ctx->autocap_frame[dma_fr].memory_size = autowrite_fr_writer_memsize_read();
259 #endif
260 }
261 else if(p_ctx->get_fr_ds == GET_DS1)
262 {
263 p_ctx->autocap_frame[dma_ds1].format = system_hw_read_32(0x1c260) & 0xFF;
264 p_ctx->autocap_frame[dma_ds1].imagesize = (system_hw_read_32(0x1c264) & 0xFFFF) << 16;
265 p_ctx->autocap_frame[dma_ds1].imagesize |= ((system_hw_read_32(0x1c264) >> 16) & 0xFFFF);
266
267 #ifdef AUTOWRITE_MODULE
268 p_ctx->autocap_frame[dma_ds1].imagebufferstride = autowrite_ds1_image_buffer_stride_read();
269 p_ctx->autocap_frame[dma_ds1].count = autowrite_ds1_writer_frame_wcount_read();
270 p_ctx->autocap_frame[dma_ds1].memory_size = autowrite_ds1_writer_memsize_read();
271 #endif
272 }
273 else if(p_ctx->get_fr_ds == GET_DS2)
274 {
275 p_ctx->autocap_frame[dma_ds2].format = am_sc_get_output_format();
276 p_ctx->autocap_frame[dma_ds2].imagesize = am_sc_get_width() << 16;
277 p_ctx->autocap_frame[dma_ds2].imagesize |= am_sc_get_height();
278
279 #ifdef AUTOWRITE_MODULE
280 p_ctx->autocap_frame[dma_ds2].imagebufferstride = autowrite_ds2_image_buffer_stride_read();
281 p_ctx->autocap_frame[dma_ds2].count = autowrite_ds2_writer_frame_wcount_read();
282 p_ctx->autocap_frame[dma_ds2].memory_size = autowrite_ds2_writer_memsize_read();
283 #endif
284 }
285
286 rc = copy_to_user( buf, &p_ctx->autocap_frame[p_ctx->get_fr_ds], sizeof(struct autocap_image) );
287 if ( rc ) {
288 LOG( LOG_ERR, "copy_to_user failed, rc: %d.", rc );
289 }
290
291 return rc;
292 }
293
autocapture_fops_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)294 static ssize_t autocapture_fops_write( struct file *file, const char __user *buf, size_t count, loff_t *ppos )
295 {
296 int rc = 0;
297 struct autocapture_context *p_ctx = (struct autocapture_context *)file->private_data;
298
299 rc = copy_from_user( &p_ctx->get_fr_ds, buf, sizeof(int) );
300 if ( rc ) {
301 LOG( LOG_ERR, "copy_from_user failed, not copied: %d", rc );
302 }
303
304 rc = count;
305
306 if(p_ctx->get_fr_ds == 0xAA)
307 {
308 acamera_isp_isp_global_interrupt_mask_vector_write( 0, ISP_IRQ_DISABLE_ALL_IRQ );
309 }
310 else if(p_ctx->get_fr_ds == 0x55)
311 {
312 acamera_isp_isp_global_interrupt_mask_vector_write( 0, ISP_IRQ_MASK_VECTOR );
313 }
314 else if(p_ctx->get_fr_ds == 0xBB)
315 {
316 #ifdef AUTOWRITE_MODULE
317 autowrite_fr_stop();
318 autowrite_ds1_stop();
319 autowrite_ds2_stop();
320 #endif
321 }
322
323 return rc;
324 }
325
326
autocap_get_frame_info(struct autocapture_context * p_ctx,uint32_t type)327 uint32_t autocap_get_frame_info(struct autocapture_context *p_ctx, uint32_t type)
328 {
329 #ifdef AUTOWRITE_MODULE
330 uint32_t realcount = 0;
331 uint32_t fps = 30;
332 #endif
333 #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0))
334 do_gettimeofday(&p_ctx->t_frm);
335 p_ctx->autocap_frame[type].endtime = (p_ctx->t_frm.tv_sec*1000000 + p_ctx->t_frm.tv_usec)/1000;
336 #else
337 ktime_get_real_ts64(&p_ctx->t_frm);
338 p_ctx->autocap_frame[type].endtime = (p_ctx->t_frm.tv_sec*1000000 + p_ctx->t_frm.tv_nsec / 1000)/1000;
339 #endif
340
341 if(p_ctx->hw_reset)
342 return 0;
343
344 #ifdef AUTOWRITE_MODULE
345 switch(type)
346 {
347 case dma_fr:
348 realcount = autowrite_fr_writer_memsize_read()/autowrite_fr_image_buffer_stride_read();
349 p_ctx->autocap_frame[dma_fr].format = system_hw_read_32(0x1c0ec) & 0xFF;
350 p_ctx->autocap_frame[dma_fr].imagesize = acamera_isp_input_port_frame_width_read(0) << 16;
351 p_ctx->autocap_frame[dma_fr].imagesize |= acamera_isp_input_port_frame_height_read(0);
352 p_ctx->autocap_frame[dma_fr].imagebufferstride = autowrite_fr_image_buffer_stride_read();
353 p_ctx->autocap_frame[dma_fr].memory_size = autowrite_fr_writer_memsize_read();
354 p_ctx->autocap_frame[dma_fr].count = autowrite_fr_writer_frame_wcount_read();
355 p_ctx->autocap_frame[dma_fr].s_address = autowrite_fr_start_address_read();
356 if(autowrite_fr_drop_mode_status())
357 {
358 if(autowrite_fr_drop_write_read())
359 fps = 30 * autowrite_fr_drop_write_read() / (autowrite_fr_drop_write_read() + autowrite_fr_drop_jump_read());
360 }
361 break;
362 case dma_ds1:
363 realcount = autowrite_ds1_writer_memsize_read()/autowrite_ds1_image_buffer_stride_read();
364 p_ctx->autocap_frame[dma_ds1].format = system_hw_read_32(0x1c260) & 0xFF;
365 p_ctx->autocap_frame[dma_ds1].imagesize = (system_hw_read_32(0x1c264) & 0xFFFF) << 16;
366 p_ctx->autocap_frame[dma_ds1].imagesize |= ((system_hw_read_32(0x1c264) >> 16) & 0xFFFF);
367 p_ctx->autocap_frame[dma_ds1].imagebufferstride = autowrite_ds1_image_buffer_stride_read();
368 p_ctx->autocap_frame[dma_ds1].memory_size = autowrite_ds1_writer_memsize_read();
369 p_ctx->autocap_frame[dma_ds1].count = autowrite_ds1_writer_frame_wcount_read();
370 p_ctx->autocap_frame[dma_ds1].s_address = autowrite_ds1_start_address_read();
371 if(autowrite_ds1_drop_mode_status())
372 {
373 if(autowrite_ds1_drop_write_read())
374 fps = 30 * autowrite_ds1_drop_write_read() / (autowrite_ds1_drop_write_read() + autowrite_ds1_drop_jump_read());
375 }
376 break;
377 case dma_ds2:
378 realcount = autowrite_ds2_writer_memsize_read()/autowrite_ds2_image_buffer_stride_read();
379 p_ctx->autocap_frame[dma_ds2].format = am_sc_get_output_format();
380 p_ctx->autocap_frame[dma_ds2].imagesize = am_sc_get_width() << 16;
381 p_ctx->autocap_frame[dma_ds2].imagesize |= am_sc_get_height();
382 p_ctx->autocap_frame[dma_ds2].imagebufferstride = autowrite_ds2_image_buffer_stride_read();
383 p_ctx->autocap_frame[dma_ds2].memory_size = autowrite_ds2_writer_memsize_read();
384 p_ctx->autocap_frame[dma_ds2].count = autowrite_ds2_writer_frame_wcount_read();
385 p_ctx->autocap_frame[dma_ds2].s_address = autowrite_ds2_start_address_read();
386 if(autowrite_ds2_drop_mode_status())
387 {
388 if(autowrite_ds2_drop_write_read())
389 fps = 30 * autowrite_ds2_drop_write_read() / (autowrite_ds2_drop_write_read() + autowrite_ds2_drop_jump_read());
390 }
391 break;
392 default:
393 realcount = 0;
394 break;
395 }
396
397 p_ctx->autocap_frame[type].fps = fps;
398
399 if(realcount > p_ctx->autocap_frame[type].count)
400 p_ctx->autocap_frame[type].realcount = p_ctx->autocap_frame[type].count;
401 else
402 p_ctx->autocap_frame[type].realcount = realcount;
403 #endif
404
405 return 0;
406 }
407
autocap_get_frame_addr(struct autocapture_context * p_ctx,struct frame_info * frm)408 uint32_t autocap_get_frame_addr(struct autocapture_context *p_ctx, struct frame_info *frm)
409 {
410 uint32_t type = 0;
411 uint32_t index = 0;
412 uint32_t ret = 0;
413 struct frame_info t_frm;
414
415 if(frm == NULL)
416 {
417 p_ctx->autocap_frame[type].n_address = 0;
418 LOG(LOG_CRIT, "input param null");
419 return -1;
420 }
421
422 ret = copy_from_user(&t_frm, frm, sizeof(t_frm));
423 if(ret)
424 {
425 p_ctx->autocap_frame[type].n_address = 0;
426 LOG(LOG_CRIT, "input param failed");
427 return -1;
428 }
429
430 type = t_frm.type;
431 index = t_frm.index;
432
433 if(p_ctx->autocap_frame[type].realcount == 0 || p_ctx->autocap_frame[type].count == 0)
434 {
435 p_ctx->autocap_frame[type].n_address = 0;
436 LOG(LOG_CRIT, "Please stop autocap firstly");
437 return -1;
438 }
439
440 if((index > p_ctx->autocap_frame[type].realcount) || (type > dma_ds2))
441 {
442 p_ctx->autocap_frame[type].n_address = 0;
443 LOG(LOG_CRIT, "input param error");
444 return -1;
445 }
446
447 if(p_ctx->autocap_frame[type].realcount >= p_ctx->autocap_frame[type].count)
448 {
449 if(index == 0)
450 p_ctx->autocap_frame[type].n_address = p_ctx->autocap_frame[type].s_address + (p_ctx->autocap_frame[type].realcount) * p_ctx->autocap_frame[type].imagebufferstride;
451 else
452 p_ctx->autocap_frame[type].n_address = p_ctx->autocap_frame[type].s_address + (index - 1) * p_ctx->autocap_frame[type].imagebufferstride;
453 }
454 else
455 {
456 uint32_t real_pos = 0;
457 uint32_t pos_offset = p_ctx->autocap_frame[type].count % p_ctx->autocap_frame[type].realcount;
458
459 real_pos = index + pos_offset;
460 if(real_pos >= p_ctx->autocap_frame[type].realcount)
461 real_pos = real_pos % p_ctx->autocap_frame[type].realcount;
462
463 p_ctx->autocap_frame[type].n_address = p_ctx->autocap_frame[type].s_address + real_pos * p_ctx->autocap_frame[type].imagebufferstride;
464 }
465
466 t_frm.framesize = p_ctx->autocap_frame[type].imagebufferstride;
467 t_frm.phy_addr = p_ctx->autocap_frame[type].n_address;
468
469 ret = copy_to_user((void *)frm, &t_frm, sizeof(struct frame_info));
470 if ( ret ) {
471 LOG( LOG_CRIT, "copy_to_user failed, ret: %d.", ret );
472 return -1;
473 }
474
475 return 0;
476 }
477
autocapture_fops_ioctl(struct file * pfile,unsigned int cmd,unsigned long args)478 long autocapture_fops_ioctl (struct file *pfile, unsigned int cmd, unsigned long args)
479 {
480 int rc = 0;
481 struct autocapture_context *p_ctx = (struct autocapture_context *)pfile->private_data;
482
483 switch (cmd)
484 {
485 case IOCTL_GET_FR_INFO:
486 rc = copy_to_user((void *)args, &p_ctx->autocap_frame[dma_fr], sizeof(struct autocap_image));
487 if ( rc ) {
488 LOG( LOG_CRIT, "copy_to_user failed, rc: %d.", rc );
489 }
490 break;
491 case IOCTL_GET_DS1_INFO:
492 rc = copy_to_user((void *)args, &p_ctx->autocap_frame[dma_ds1], sizeof(struct autocap_image));
493 if ( rc ) {
494 LOG( LOG_CRIT, "copy_to_user failed, rc: %d.", rc );
495 }
496 break;
497 case IOCTL_GET_DS2_INFO:
498 rc = copy_to_user((void *)args, &p_ctx->autocap_frame[dma_ds2], sizeof(struct autocap_image));
499 if ( rc ) {
500 LOG( LOG_CRIT, "copy_to_user failed, rc: %d.", rc );
501 }
502 break;
503 #ifdef AUTOWRITE_MODULE
504 case IOCTL_STOP_AUTO:
505 autowrite_fr_stop();
506 autowrite_ds1_stop();
507 autowrite_ds2_stop();
508 autocap_get_frame_info(p_ctx, dma_fr);
509 autocap_get_frame_info(p_ctx, dma_ds1);
510 autocap_get_frame_info(p_ctx, dma_ds2);
511 break;
512 case IOCTL_STOP_AUTO_FR:
513 autowrite_fr_stop();
514 autocap_get_frame_info(p_ctx, dma_fr);
515 p_ctx->get_fr_ds = GET_FR;
516 break;
517 case IOCTL_STOP_AUTO_DS1:
518 autowrite_ds1_stop();
519 autocap_get_frame_info(p_ctx, dma_ds1);
520 p_ctx->get_fr_ds = GET_DS1;
521 break;
522 case IOCTL_STOP_AUTO_DS2:
523 autowrite_ds2_stop();
524 autocap_get_frame_info(p_ctx, dma_ds2);
525 p_ctx->get_fr_ds = GET_DS2;
526 break;
527 case IOCTL_DBGPATH_INFO:
528 autocap_get_frame_info(p_ctx, dma_fr);
529 autocap_get_frame_info(p_ctx, dma_ds1);
530 autocap_get_frame_info(p_ctx, dma_ds2);
531 break;
532 case IOCTL_GET_FRAME_INFO:
533 autocap_get_frame_addr(p_ctx, (void *)args);
534 break;
535 case IOCTL_GET_FR_RTL_INFO:
536 p_ctx->get_fr_ds = GET_FR;
537 autocap_get_frame_info(p_ctx, dma_fr);
538 rc = copy_to_user((void *)args, &p_ctx->autocap_frame[dma_fr], sizeof(struct autocap_image));
539 if ( rc ) {
540 LOG( LOG_CRIT, "copy_to_user failed, rc: %d.", rc );
541 }
542 break;
543 case IOCTL_GET_DS1_RTL_INFO:
544 p_ctx->get_fr_ds = GET_DS1;
545 autocap_get_frame_info(p_ctx, dma_ds1);
546 rc = copy_to_user((void *)args, &p_ctx->autocap_frame[dma_ds1], sizeof(struct autocap_image));
547 if ( rc ) {
548 LOG( LOG_CRIT, "copy_to_user failed, rc: %d.", rc );
549 }
550 break;
551 case IOCTL_GET_DS2_RTL_INFO:
552 p_ctx->get_fr_ds = GET_DS2;
553 autocap_get_frame_info(p_ctx, dma_ds2);
554 rc = copy_to_user((void *)args, &p_ctx->autocap_frame[dma_ds2], sizeof(struct autocap_image));
555 if ( rc ) {
556 LOG( LOG_CRIT, "copy_to_user failed, rc: %d.", rc );
557 }
558 break;
559 #endif
560 default:
561 LOG(LOG_CRIT, "invalid cmd");
562 break;
563 }
564
565 return rc;
566 }
567
autocap_do_tasklet(unsigned long data)568 void autocap_do_tasklet( unsigned long data )
569 {
570 struct autocapture_context *p_ctx;
571 p_ctx = (struct autocapture_context *)data;
572
573 acamera_alg_preset_t *p_pst;
574 char *reserve_virt_addr = phys_to_virt(autowrite_ds1_start_address_read() + autowrite_ds1_writer_memsize_read());
575 p_pst = (acamera_alg_preset_t *)reserve_virt_addr;
576 p_ctx->timestampe[0] = p_pst->other_param.first_frm_timestamp;
577
578 LOG(LOG_CRIT, "Autocap get Pong Buff:%x", p_ctx->autocap_frame[dma_ds1].realcount);
579 uint32_t addr_pong = autowrite_ds1_pong_start();
580 if( autowrite_ds1_ping_start() > autowrite_ds1_pong_start() )
581 addr_pong = autowrite_ds1_ping_start();
582
583 uint32_t addr = p_ctx->autocap_frame[dma_ds1].s_address + (p_ctx->autocap_frame[dma_ds1].realcount) * p_ctx->autocap_frame[dma_ds1].imagebufferstride;
584 memcpy(phys_to_virt(addr), phys_to_virt(addr_pong), p_ctx->autocap_frame[dma_ds1].imagebufferstride);
585 }
586
587 static struct file_operations autocapture_mgr_fops = {
588 .owner = THIS_MODULE,
589 .open = autocapture_fops_open,
590 .release = autocapture_fops_release,
591 .read = autocapture_fops_read,
592 .write = autocapture_fops_write,
593 .unlocked_ioctl = autocapture_fops_ioctl,
594 .llseek = noop_llseek,
595 .mmap = autocapture_fops_mmap,
596 };
597
autocapture_initialize(autocapture_fsm_t * p_fsm)598 void autocapture_initialize( autocapture_fsm_t *p_fsm )
599 {
600 int rc;
601 uint32_t fw_id = p_fsm->cmn.ctx_id;
602 struct miscdevice *p_dev;
603 struct autocapture_context *p_ctx;
604
605 if ( fw_id >= acamera_get_context_number() ) {
606 LOG( LOG_CRIT, "Fatal error: Invalid FW context ID: %d, max is: %d", fw_id, acamera_get_context_number() - 1 );
607 return;
608 }
609
610 p_ctx = &( autocapture_context[fw_id] );
611 memset( p_ctx, 0, sizeof( *p_ctx ) );
612 p_dev = &p_ctx->autocap_dev;
613 snprintf( p_ctx->dev_name, AUTOCAP_DEV_NAME_LEN, AUTOCAP_DEV_FORMAT, fw_id );
614 p_dev->name = p_ctx->dev_name;
615 p_dev->minor = MISC_DYNAMIC_MINOR,
616 p_dev->fops = &autocapture_mgr_fops,
617
618 rc = misc_register( p_dev );
619 if ( rc ) {
620 LOG( LOG_ERR, "init failed, error: register autocap device failed, ret: %d.", rc );
621 return;
622 }
623
624 p_ctx->fw_id = fw_id;
625 p_ctx->dev_minor_id = p_dev->minor;
626 p_ctx->p_fsm = p_fsm;
627 p_ctx->dev_opened = 0;
628 p_ctx->thread_stop = 0;
629 p_ctx->hw_reset = 0;
630
631 mutex_init( &p_ctx->fops_lock );
632
633 #ifdef AUTOWRITE_MODULE
634 auto_cap_init();
635
636 tasklet_init( &tasklet_memcpy, autocap_do_tasklet, (unsigned long)p_ctx );
637 #endif
638
639 #ifdef LINUX_AUTOWRITE_MODULE_TEST
640 struct module_cfg_info m_cfg_fr;
641 struct module_cfg_info m_cfg_ds1;
642 struct module_cfg_info m_cfg_ds2;
643
644 memset(&m_cfg_fr, 0, sizeof(m_cfg_fr));
645 memset(&m_cfg_ds1, 0, sizeof(m_cfg_ds1));
646 memset(&m_cfg_ds2, 0, sizeof(m_cfg_ds2));
647
648 LOG( LOG_CRIT, "zgs autocapture_initialize: %d", __LINE__);
649
650 auto_cap_init();
651
652 m_cfg_fr.p_type = dma_fr;
653 m_cfg_fr.planes = 1;
654 m_cfg_fr.frame_size0 = (1920 * 1080 * 3);
655 fw_auto_cap_init(p_ctx, (void *)&m_cfg_fr);
656
657 m_cfg_ds1.p_type = dma_ds1;
658 m_cfg_ds1.planes = 1;
659 m_cfg_ds1.frame_size0 = (1280 * 720 * 3);
660 fw_auto_cap_init(p_ctx, (void *)&m_cfg_ds1);
661
662 m_cfg_ds2.p_type = dma_ds2;
663 m_cfg_ds2.planes = 1;
664 m_cfg_ds2.frame_size0 = (1280 * 720 * 3);
665 fw_auto_cap_init(p_ctx, (void *)&m_cfg_ds2);
666 #endif
667
668 #ifdef AUTOWRITE_MODULES_V4L2_API
669 int kfifo_ret;
670 int i = 0;
671
672 //p_ctx->get_fr_ds = AUTOCAP_MODE0;
673 if(p_ctx->get_fr_ds == AUTOCAP_MODE0)
674 {
675 for(i = 0; i < SUPPORT_CHANNEL; i++)
676 {
677 p_ctx->frame_cnt[i] = 0;
678 kfifo_ret = kfifo_alloc(&p_ctx->read_fifo[i], PAGE_SIZE, GFP_KERNEL);
679 if (kfifo_ret) {
680 pr_info("alloc adapter fifo failed.\n");
681 return;
682 }
683 }
684
685 acamera_isp_input_port_mode_request_write( 0, ACAMERA_ISP_INPUT_PORT_MODE_REQUEST_SAFE_START );
686 p_ctx->kthread_stream = kthread_run( autocap_v4l2_stream_copy_thread, p_ctx, "autocap_stream" );
687 }
688 #endif
689 return;
690 }
691
autocapture_deinit(autocapture_fsm_ptr_t p_fsm)692 void autocapture_deinit( autocapture_fsm_ptr_t p_fsm )
693 {
694 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0))
695 int rc;
696 #endif
697 int i;
698 uint32_t fw_id = p_fsm->cmn.ctx_id;
699 struct autocapture_context *p_ctx = NULL;
700 struct miscdevice *p_dev = NULL;
701
702 p_ctx = &( autocapture_context[fw_id] );
703 if ( p_ctx->fw_id != fw_id ) {
704 LOG( LOG_CRIT, "Error: ctx_id not match, fsm fw_id: %d, ctx_id: %d.", fw_id, p_ctx->fw_id );
705 return;
706 }
707
708 p_dev = &p_ctx->autocap_dev;
709 if ( !p_dev->name ) {
710 LOG( LOG_CRIT, "skip sbuf[%d] deregister due to NULL name", fw_id );
711 return;
712 }
713
714 p_ctx->thread_stop = 1;
715
716 if(p_ctx->kthread_stream)
717 kthread_stop( p_ctx->kthread_stream );
718
719 for(i = 0 ; i < SUPPORT_CHANNEL; i++)
720 {
721 if(&p_ctx->read_fifo[i])
722 kfifo_free(&p_ctx->read_fifo[i]);
723 }
724
725 #ifdef AUTOWRITE_MODULE
726 auto_cap_deinit();
727 #endif
728
729 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0))
730 misc_deregister( p_dev );
731 #else
732 rc = misc_deregister( p_dev );
733 if ( rc ) {
734 LOG( LOG_ERR, "deregister autocap dev '%s' failed, ret: %d.", p_dev->name, rc );
735 } else {
736 LOG( LOG_INFO, "deregister autocap dev '%s' ok.", p_dev->name );
737 }
738 #endif
739
740 return;
741 }
742
autocapture_hwreset(autocapture_fsm_ptr_t p_fsm)743 void autocapture_hwreset(autocapture_fsm_ptr_t p_fsm )
744 {
745 #ifdef AUTOWRITE_MODULE
746 uint32_t fw_id = p_fsm->cmn.ctx_id;
747 struct autocapture_context *p_ctx = NULL;
748
749 p_ctx = &( autocapture_context[fw_id] );
750
751 if( p_ctx->hw_reset )
752 return;
753
754 system_hw_write_32(0x9c, 0);
755
756 autocap_get_frame_info(p_ctx, dma_fr);
757 autocap_get_frame_info(p_ctx, dma_ds1);
758 autocap_get_frame_info(p_ctx, dma_ds2);
759
760 system_hw_write_32(0x1C260, 0);
761 system_hw_write_32(0x1C2B8, 0);
762 system_hw_write_32(0x34220, 0);
763 system_hw_write_32(0x34278, 0);
764
765 p_ctx->hw_reset = 1;
766
767 if(p_ctx->autocap_frame[dma_ds1].realcount && (p_ctx->autocap_frame[dma_ds1].realcount >= p_ctx->autocap_frame[dma_ds1].count))
768 {
769 tasklet_schedule(&tasklet_memcpy);
770 }
771
772 mdelay(5);
773 autowrite_path_reset();
774 #endif
775
776 return;
777 }
778
779 #ifdef AUTOWRITE_MODULES_V4L2_API
autocap_v4l2_stream_copy_thread(void * data)780 static int autocap_v4l2_stream_copy_thread( void *data )
781 {
782 int read_count = 0;
783 int res = 0;
784 tframe_t f_buff;
785 struct autocapture_context *p_ctx = (struct autocapture_context *)data;
786
787 LOG( LOG_CRIT, "autocap_v4l2_stream_copy_thread enter" );
788 acamera_isp_isp_global_interrupt_mask_vector_write( 0, ISP_IRQ_DISABLE_ALL_IRQ );
789
790 while(!p_ctx->thread_stop)
791 {
792 msleep(100);
793 if(kfifo_len(&p_ctx->read_fifo[0]) == V4L2_BUFFER_SIZE * 8)
794 break;
795 }
796
797 msleep(100);
798
799 LOG( LOG_CRIT, "autocap_v4l2_stream_copy_thread enter" );
800
801 while ( !kthread_should_stop() ) {
802
803 if(p_ctx->pstream[dma_fr] && p_ctx->pstream[dma_fr]->stream_started)
804 {
805 res = autocap_pullbuf(p_ctx->fw_id, dma_fr, f_buff);
806 if(res == 0)
807 continue;
808
809 #ifdef AUTOWRITE_MODULE
810 if(read_count ++ > autowrite_fr_writer_frame_wcount_read())
811 #else
812 if(read_count ++ > 600)
813 #endif
814 break;
815 }
816
817 if(p_ctx->pstream[dma_ds1] && p_ctx->pstream[dma_ds1]->stream_started)
818 {
819 res = autocap_pullbuf(p_ctx->fw_id, dma_ds1, f_buff);
820 if(res == 0)
821 continue;
822 }
823
824 if(p_ctx->pstream[dma_ds2] && p_ctx->pstream[dma_ds2]->stream_started)
825 {
826 res = autocap_pullbuf(p_ctx->fw_id, dma_ds2, f_buff);
827 if(res == 0)
828 continue;
829 }
830
831 msleep(1);
832 //pr_info("read_count :%d, %d, %d", read_count, p_ctx->pstream[0]->stream_started,res);
833 }
834
835 LOG( LOG_CRIT, "autocap_v4l2_stream_copy_thread stop" );
836 acamera_isp_isp_global_interrupt_mask_vector_write( 0, ISP_IRQ_MASK_VECTOR );
837 p_ctx->kthread_stream = NULL;
838 p_ctx->get_fr_ds = 0;
839 return 0;
840 }
841
autocap_pullbuf(int ctx_id,int d_type,tframe_t f_buff)842 uint32_t autocap_pullbuf(int ctx_id, int d_type, tframe_t f_buff)
843 {
844 int kfifo_ret = 0;
845 resource_size_t p_buff;
846
847 struct autocapture_context *p_ctx = NULL;
848 p_ctx = &( autocapture_context[ctx_id] );
849
850 if(kfifo_len(&p_ctx->read_fifo[d_type]) > 0)
851 {
852 kfifo_ret = kfifo_out(&p_ctx->read_fifo[d_type], &p_buff, sizeof(resource_size_t));
853 if (kfifo_ret <= 0) {
854 pr_info("kfifo out failed.%d\n", kfifo_len(&p_ctx->read_fifo[d_type]));
855 return kfifo_ret;
856 }
857
858 //pr_info("\n kfifo out success, p_buff :%lld, %x.\n", p_buff, p_ctx->d_buff[d_type][p_buff].primary.address);
859 p_ctx->pstream[d_type]->frame_mgr.frame_buffer.state = ISP_FW_FRAME_BUF_INVALID;
860 if(d_type == dma_fr)
861 {
862 system_memcpy(phys_to_virt(p_ctx->d_buff[d_type][p_buff].primary.address), phys_to_virt(FW_FR_AUTO_CAP_BASE),
863 p_ctx->d_buff[d_type][p_buff].primary.size+p_ctx->d_buff[d_type][p_buff].secondary.size);
864
865 p_ctx->p_fsm->p_fsm_mgr->p_ctx->settings.callback_fr(ctx_id, &p_ctx->d_buff[d_type][p_buff], NULL);
866 }
867 else if(d_type == dma_ds1)
868 {
869 system_memcpy(phys_to_virt(p_ctx->d_buff[d_type][p_buff].primary.address), phys_to_virt(FW_DS1_AUTO_CAP_BASE), \
870 p_ctx->d_buff[d_type][p_buff].primary.size+p_ctx->d_buff[d_type][p_buff].secondary.size);
871 p_ctx->p_fsm->p_fsm_mgr->p_ctx->settings.callback_ds1(ctx_id, &p_ctx->d_buff[d_type][p_buff], NULL);
872 }
873 else if(d_type == dma_ds2)
874 {
875 system_memcpy(phys_to_virt(p_ctx->d_buff[d_type][p_buff].primary.address), phys_to_virt(FW_DS2_AUTO_CAP_BASE), \
876 p_ctx->d_buff[d_type][p_buff].primary.size+p_ctx->d_buff[d_type][p_buff].secondary.size);
877
878 p_ctx->p_fsm->p_fsm_mgr->p_ctx->settings.callback_ds2(ctx_id, &p_ctx->d_buff[d_type][p_buff], NULL);
879 }
880 }
881
882 return kfifo_ret;
883 }
884
autocap_pushbuf(int ctx_id,int d_type,tframe_t f_buff,isp_v4l2_stream_t * pstream)885 uint32_t autocap_pushbuf(int ctx_id, int d_type, tframe_t f_buff, isp_v4l2_stream_t *pstream)
886 {
887 int kfifo_ret = 0;
888 int frame_cnt = 0;
889 struct autocapture_context *p_ctx = NULL;
890 p_ctx = &( autocapture_context[ctx_id] );
891 frame_cnt = p_ctx->frame_cnt[d_type];
892 p_ctx->pstream[d_type] = pstream;
893
894 acamera_isp_isp_global_interrupt_mask_vector_write( 0, ISP_IRQ_DISABLE_ALL_IRQ );
895
896 system_memcpy(&p_ctx->d_buff[d_type][frame_cnt], &f_buff, sizeof(tframe_t));
897 p_ctx->idx_buf[d_type][frame_cnt] = frame_cnt;
898 if(!kfifo_is_full(&p_ctx->read_fifo[d_type]))
899 {
900 kfifo_ret = kfifo_in(&p_ctx->read_fifo[d_type], &p_ctx->idx_buf[d_type][frame_cnt], sizeof(resource_size_t));
901 if (kfifo_ret == 0) {
902 pr_info("kfifo in failed,%d.\n",ctx_id);
903 return kfifo_ret;
904 }
905 }
906
907 //pr_info("\n kfifo in success, cnt=%x, %x\n",p_ctx->frame_cnt[d_type], p_ctx->d_buff[d_type][frame_cnt].primary.address);
908
909 p_ctx->frame_cnt[d_type] ++;
910 if(p_ctx->frame_cnt[d_type] == V4L2_BUFFER_SIZE)
911 p_ctx->frame_cnt[d_type] = 0;
912
913 return 0;
914 }
915 #endif
916
autocap_get_mode(uint32_t ctx_id)917 uint32_t autocap_get_mode(uint32_t ctx_id)
918 {
919 return autocapture_context[ctx_id].get_fr_ds;
920 }
921
922 /**********************************/
923
autocap_set_new_param(struct module_cfg_info * m_cfg)924 void autocap_set_new_param(struct module_cfg_info *m_cfg)
925 {
926 LOG(LOG_DEBUG, "type:%d, %x, %x", m_cfg->p_type,m_cfg->frame_buffer_start0, m_cfg->frame_size0);
927
928 pipe_cfg[m_cfg->p_type].frame_buffer_start0 = m_cfg->frame_buffer_start0;
929 pipe_cfg[m_cfg->p_type].frame_buffer_start1 = m_cfg->frame_buffer_start1;
930 pipe_cfg[m_cfg->p_type].frame_size0 = m_cfg->frame_size0;
931 pipe_cfg[m_cfg->p_type].frame_size1 = m_cfg->frame_size1;
932 }
933
fw_auto_cap_init(struct autocapture_context * p_ctx,void * cfg_info)934 void fw_auto_cap_init(struct autocapture_context *p_ctx, void *cfg_info)
935 {
936 auto_write_cfg_t *a_cfg = NULL;
937 struct module_cfg_info *m_cfg = (struct module_cfg_info *)cfg_info;
938
939 a_cfg = vmalloc(sizeof(*p_ctx->auto_cap_cfg));
940 if (a_cfg == NULL) {
941 LOG(LOG_ERR, "Failed to alloc mem");
942 return;
943 }
944
945 memset(a_cfg, 0, sizeof(*a_cfg));
946
947 a_cfg->p_type = m_cfg->p_type;
948 a_cfg->frame_size0 = m_cfg->frame_size0;
949 a_cfg->frame_size1 = m_cfg->frame_size1;
950
951 switch (a_cfg->p_type) {
952 case dma_fr:
953 if (m_cfg->planes == 1) {
954 a_cfg->frame_buffer_start0 = FW_FR_AUTO_CAP_BASE;
955 a_cfg->frame_buffer_size0 = FW_FR_AUTO_CAP_SIZE;
956 a_cfg->frame_buffer_start1 = 0x00000000;
957 a_cfg->frame_buffer_size1 = 0x0;
958 } else if (m_cfg->planes == 2) {
959 a_cfg->frame_buffer_start0 = FW_FR_AUTO_CAP_BASE;
960 a_cfg->frame_buffer_size0 = FW_FR_AUTO_CAP_SIZE / 2;
961 a_cfg->frame_buffer_start1 = FW_FR_AUTO_CAP_BASE + (FW_FR_AUTO_CAP_SIZE / 2);
962 a_cfg->frame_buffer_size1 = FW_FR_AUTO_CAP_SIZE / 2;
963 }
964 break;
965 case dma_ds1:
966 if ( m_cfg->planes ==1) {
967 a_cfg->frame_buffer_start0 = FW_DS1_AUTO_CAP_BASE;
968 a_cfg->frame_buffer_size0 = FW_DS1_AUTO_CAP_SIZE;
969 a_cfg->frame_buffer_start1 = 0x00000000;
970 a_cfg->frame_buffer_size1 = 0x0;
971 } else if (m_cfg->planes == 2) {
972 a_cfg->frame_buffer_start0 = FW_DS1_AUTO_CAP_BASE;
973 a_cfg->frame_buffer_size0 = FW_DS1_AUTO_CAP_SIZE / 2;
974 a_cfg->frame_buffer_start1 = FW_DS1_AUTO_CAP_BASE + FW_DS1_AUTO_CAP_SIZE / 2;
975 a_cfg->frame_buffer_size1 = FW_DS1_AUTO_CAP_SIZE / 2;
976 }
977 break;
978 case dma_ds2:
979 if ( m_cfg->planes ==1) {
980 a_cfg->frame_buffer_start0 = FW_DS2_AUTO_CAP_BASE;
981 a_cfg->frame_buffer_size0 = FW_DS2_AUTO_CAP_SIZE;
982 a_cfg->frame_buffer_start1 = 0x00000000;
983 a_cfg->frame_buffer_size1 = 0x0;
984 } else if (m_cfg->planes == 2) {
985 a_cfg->frame_buffer_start0 = FW_DS1_AUTO_CAP_BASE;
986 a_cfg->frame_buffer_size0 = FW_DS1_AUTO_CAP_SIZE / 2;
987 a_cfg->frame_buffer_start1 = FW_DS1_AUTO_CAP_BASE + FW_DS1_AUTO_CAP_SIZE / 2;
988 a_cfg->frame_buffer_size1 = FW_DS1_AUTO_CAP_SIZE / 2;
989 }
990 break;
991 default:
992 vfree(a_cfg);
993 LOG(LOG_ERR, "Error path type");
994 return;
995 }
996
997 if (a_cfg->p_type == dma_fr) {
998 auto_write_fr_init(a_cfg);
999 } else if (a_cfg->p_type == dma_ds1) {
1000 auto_write_ds1_init(a_cfg);
1001 } else if (a_cfg->p_type == dma_ds2) {
1002 auto_write_ds2_init(a_cfg);
1003 } else {
1004 LOG(LOG_CRIT, "can't support autocapture type\n");
1005 }
1006
1007 p_ctx->auto_cap_cfg = a_cfg;
1008 }
1009
fw_auto_cap_deinit(struct autocapture_context * p_ctx)1010 void fw_auto_cap_deinit(struct autocapture_context *p_ctx)
1011 {
1012 if (p_ctx->auto_cap_cfg != NULL) {
1013 vfree(p_ctx->auto_cap_cfg);
1014 p_ctx->auto_cap_cfg = NULL;
1015 }
1016 }
1017
1018