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