• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
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 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 * Description:
19 */
20 
21 #define DEBUG
22 #include <linux/slab.h>
23 #include <linux/interrupt.h>
24 #include <linux/irq.h>
25 #include <linux/module.h>
26 #include <linux/of_device.h>
27 #include <linux/of.h>
28 #include <media/v4l2-event.h>
29 #include <media/v4l2-mem2mem.h>
30 #include <media/videobuf2-dma-contig.h>
31 #include <linux/kthread.h>
32 #include <linux/compat.h>
33 
34 #include "aml_vcodec_drv.h"
35 #include "aml_vcodec_dec.h"
36 #include "aml_vcodec_util.h"
37 #include "aml_vcodec_vfm.h"
38 #include <linux/file.h>
39 #include <linux/anon_inodes.h>
40 
41 #define VDEC_HW_ACTIVE		0x10
42 #define VDEC_IRQ_CFG		0x11
43 #define VDEC_IRQ_CLR		0x10
44 #define VDEC_IRQ_CFG_REG	0xa4
45 
46 #define V4LVIDEO_IOC_MAGIC  'I'
47 #define V4LVIDEO_IOCTL_ALLOC_FD				_IOW(V4LVIDEO_IOC_MAGIC, 0x02, int)
48 #define V4LVIDEO_IOCTL_CHECK_FD				_IOW(V4LVIDEO_IOC_MAGIC, 0x03, int)
49 #define V4LVIDEO_IOCTL_SET_CONFIG_PARAMS	_IOWR(V4LVIDEO_IOC_MAGIC, 0x04, struct v4l2_config_parm)
50 #define V4LVIDEO_IOCTL_GET_CONFIG_PARAMS	_IOWR(V4LVIDEO_IOC_MAGIC, 0x05, struct v4l2_config_parm)
51 
52 bool param_sets_from_ucode = 1;
53 bool enable_drm_mode;
54 
fops_vcodec_open(struct file * file)55 static int fops_vcodec_open(struct file *file)
56 {
57 	struct aml_vcodec_dev *dev = video_drvdata(file);
58 	struct aml_vcodec_ctx *ctx = NULL;
59 	struct aml_video_dec_buf *aml_buf = NULL;
60 	int ret = 0;
61 	struct vb2_queue *src_vq;
62 
63 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
64 	if (!ctx)
65 		return -ENOMEM;
66 	aml_buf = kzalloc(sizeof(*aml_buf), GFP_KERNEL);
67 	if (!aml_buf) {
68 		kfree(ctx);
69 		return -ENOMEM;
70 	}
71 
72 	mutex_lock(&dev->dev_mutex);
73 	ctx->empty_flush_buf = aml_buf;
74 	ctx->id = dev->id_counter++;
75 	v4l2_fh_init(&ctx->fh, video_devdata(file));
76 	file->private_data = &ctx->fh;
77 	v4l2_fh_add(&ctx->fh);
78 	INIT_LIST_HEAD(&ctx->list);
79 	INIT_LIST_HEAD(&ctx->vdec_thread_list);
80 	dev->filp = file;
81 	ctx->dev = dev;
82 	init_waitqueue_head(&ctx->queue);
83 	mutex_init(&ctx->state_lock);
84 	mutex_init(&ctx->lock);
85 	spin_lock_init(&ctx->slock);
86 	init_completion(&ctx->comp);
87 
88 	ctx->param_sets_from_ucode = param_sets_from_ucode ? 1 : 0;
89 
90 	if (enable_drm_mode) {
91 		ctx->is_drm_mode = true;
92 		ctx->param_sets_from_ucode = true;
93 	}
94 
95 	ctx->type = AML_INST_DECODER;
96 	ret = aml_vcodec_dec_ctrls_setup(ctx);
97 	if (ret) {
98 		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
99 			"Failed to setup vcodec controls\n");
100 		goto err_ctrls_setup;
101 	}
102 	ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev_dec, ctx,
103 		&aml_vcodec_dec_queue_init);
104 	if (IS_ERR((__force void *)ctx->m2m_ctx)) {
105 		ret = PTR_ERR((__force void *)ctx->m2m_ctx);
106 		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
107 			"Failed to v4l2_m2m_ctx_init() (%d)\n", ret);
108 		goto err_m2m_ctx_init;
109 	}
110 	src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx,
111 				V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
112 	ctx->output_thread_ready = true;
113 	ctx->empty_flush_buf->vb.vb2_buf.vb2_queue = src_vq;
114 	ctx->empty_flush_buf->lastframe = true;
115 	aml_vcodec_dec_set_default_params(ctx);
116 
117 	ret = aml_thread_start(ctx, try_to_capture, AML_THREAD_CAPTURE, "cap");
118 	if (ret) {
119 		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
120 			"Failed to creat capture thread.\n");
121 		goto err_creat_thread;
122 	}
123 
124 	list_add(&ctx->list, &dev->ctx_list);
125 
126 	mutex_unlock(&dev->dev_mutex);
127 	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO, "%s decoder %lx\n",
128 		dev_name(&dev->plat_dev->dev), (ulong)ctx);
129 
130 	return ret;
131 
132 	/* Deinit when failure occurred */
133 err_creat_thread:
134 	v4l2_m2m_ctx_release(ctx->m2m_ctx);
135 err_m2m_ctx_init:
136 	v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
137 err_ctrls_setup:
138 	v4l2_fh_del(&ctx->fh);
139 	v4l2_fh_exit(&ctx->fh);
140 	kfree(ctx->empty_flush_buf);
141 	kfree(ctx);
142 	mutex_unlock(&dev->dev_mutex);
143 
144 	return ret;
145 }
146 
fops_vcodec_release(struct file * file)147 static int fops_vcodec_release(struct file *file)
148 {
149 	struct aml_vcodec_dev *dev = video_drvdata(file);
150 	struct aml_vcodec_ctx *ctx = fh_to_ctx(file->private_data);
151 
152 	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO, "release decoder %lx\n", (ulong) ctx);
153 	mutex_lock(&dev->dev_mutex);
154 
155 	/*
156 	 * Call v4l2_m2m_ctx_release before aml_vcodec_dec_release. First, it
157 	 * makes sure the worker thread is not running after vdec_if_deinit.
158 	 * Second, the decoder will be flushed and all the buffers will be
159 	 * returned in stop_streaming.
160 	 */
161 	aml_thread_stop(ctx);
162 	wait_vcodec_ending(ctx);
163 	v4l2_m2m_ctx_release(ctx->m2m_ctx);
164 	aml_vcodec_dec_release(ctx);
165 
166 	v4l2_fh_del(&ctx->fh);
167 	v4l2_fh_exit(&ctx->fh);
168 	v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
169 
170 	list_del_init(&ctx->list);
171 	kfree(ctx->empty_flush_buf);
172 	kfree(ctx);
173 	mutex_unlock(&dev->dev_mutex);
174 	return 0;
175 }
176 
v4l2video_file_release(struct inode * inode,struct file * file)177 static int v4l2video_file_release(struct inode *inode, struct file *file)
178 {
179 	v4l_dbg(0, V4L_DEBUG_CODEC_BUFMGR, "file: %lx, data: %lx\n",
180 		(ulong) file, (ulong) file->private_data);
181 
182 	if (file->private_data)
183 		vdec_frame_buffer_release(file->private_data);
184 
185 	return 0;
186 }
187 
188 const struct file_operations v4l2_file_fops = {
189 	.release = v4l2video_file_release,
190 };
191 
v4l2_alloc_fd(int * fd)192 int v4l2_alloc_fd(int *fd)
193 {
194 	struct file *file = NULL;
195 	int file_fd = get_unused_fd_flags(O_CLOEXEC);
196 
197 	if (file_fd < 0) {
198 		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
199 			"get unused fd fail\n");
200 		return -ENODEV;
201 	}
202 
203 	file = anon_inode_getfile("v4l2_meta_file", &v4l2_file_fops, NULL, 0);
204 	if (IS_ERR(file)) {
205 		put_unused_fd(file_fd);
206 		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
207 			"anon_inode_getfile fail\n");
208 		return -ENODEV;
209 	}
210 
211 	file->private_data =
212 		kzalloc(sizeof(struct file_private_data), GFP_KERNEL);
213 	if (!file->private_data) {
214 		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
215 			"alloc priv data faild.\n");
216 		return -ENOMEM;
217 	}
218 
219 	v4l_dbg(0, V4L_DEBUG_CODEC_BUFMGR, "fd %d, file %lx, data: %lx\n",
220 		file_fd, (ulong) file, (ulong) file->private_data);
221 
222 	fd_install(file_fd, file);
223 	*fd = file_fd;
224 
225 	return 0;
226 }
227 
228 extern const struct file_operations v4l2_file_fops;
is_v4l2_buf_file(struct file * file)229 bool is_v4l2_buf_file(struct file *file)
230 {
231 	return file->f_op == &v4l2_file_fops;
232 }
233 
v4l2_check_fd(int fd)234 int v4l2_check_fd(int fd)
235 {
236 	struct file *file;
237 
238 	file = fget(fd);
239 
240 	if (!file) {
241 		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
242 			"fget fd %d fail!\n", fd);
243 		return -EBADF;
244 	}
245 
246 	if (!is_v4l2_buf_file(file)) {
247 		fput(file);
248 		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
249 			"is_v4l2_buf_file fail!\n");
250 		return -1;
251 	}
252 
253 	fput(file);
254 
255 	v4l_dbg(0, V4L_DEBUG_CODEC_EXINFO,
256 		"ioctl ok, comm %s, pid %d\n",
257 		 current->comm, current->pid);
258 
259 	return 0;
260 }
261 
dmabuf_fd_install_data(int fd,void * data,u32 size)262 int dmabuf_fd_install_data(int fd, void* data, u32 size)
263 {
264 	struct file *file;
265 
266 	file = fget(fd);
267 
268 	if (!file) {
269 		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
270 			"fget fd %d fail!, comm %s, pid %d\n",
271 			fd, current->comm, current->pid);
272 		return -EBADF;
273 	}
274 
275 	if (!is_v4l2_buf_file(file)) {
276 		fput(file);
277 		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
278 			"the buf file checked fail!\n");
279 		return -EBADF;
280 	}
281 
282 	memcpy(file->private_data, data, size);
283 
284 	fput(file);
285 
286 	return 0;
287 }
288 
v4l_get_vf_handle(int fd)289 void* v4l_get_vf_handle(int fd)
290 {
291 	struct file *file;
292 	struct file_private_data *data = NULL;
293 	void *vf_handle = 0;
294 
295 	file = fget(fd);
296 
297 	if (!file) {
298 		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
299 			"fget fd %d fail!, comm %s, pid %d\n",
300 			fd, current->comm, current->pid);
301 		return NULL;
302 	}
303 
304 	if (!is_v4l2_buf_file(file)) {
305 		fput(file);
306 		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
307 			"the buf file checked fail!\n");
308 		return NULL;
309 	}
310 
311 	data = (struct file_private_data*) file->private_data;
312 	if (data) {
313 		vf_handle = &data->vf;
314 		v4l_dbg(0, V4L_DEBUG_CODEC_BUFMGR, "file: %lx, data: %lx\n",
315 			(ulong) file, (ulong) data);
316 	}
317 
318 	fput(file);
319 
320 	return vf_handle;
321 }
322 
323 
v4l2_vcodec_ioctl(struct file * file,unsigned int cmd,ulong arg)324 static long v4l2_vcodec_ioctl(struct file *file,
325 			unsigned int cmd,
326 			ulong arg)
327 {
328 	long ret = 0;
329 	void __user *argp = (void __user *)arg;
330 
331 	switch (cmd) {
332 	case V4LVIDEO_IOCTL_ALLOC_FD:
333 	{
334 		u32 v4lvideo_fd = 0;
335 
336 		ret = v4l2_alloc_fd(&v4lvideo_fd);
337 		if (ret != 0)
338 			break;
339 		put_user(v4lvideo_fd, (u32 __user *)argp);
340 		v4l_dbg(0, V4L_DEBUG_CODEC_EXINFO,
341 			"V4LVIDEO_IOCTL_ALLOC_FD fd %d\n",
342 			v4lvideo_fd);
343 		break;
344 	}
345 	case V4LVIDEO_IOCTL_CHECK_FD:
346 	{
347 		u32 v4lvideo_fd = 0;
348 
349 		get_user(v4lvideo_fd, (u32 __user *)argp);
350 		ret = v4l2_check_fd(v4lvideo_fd);
351 		if (ret != 0)
352 			break;
353 		v4l_dbg(0, V4L_DEBUG_CODEC_EXINFO,
354 			"V4LVIDEO_IOCTL_CHECK_FD fd %d\n",
355 			v4lvideo_fd);
356 		break;
357 	}
358 	case V4LVIDEO_IOCTL_SET_CONFIG_PARAMS:
359 	{
360 		struct aml_vcodec_ctx *ctx = NULL;
361 
362 		if (is_v4l2_buf_file(file))
363 			break;
364 
365 		ctx = fh_to_ctx(file->private_data);
366 		if (copy_from_user((void *)&ctx->config,
367 			(void *)argp, sizeof(ctx->config))) {
368 			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
369 				"set config parm err\n");
370 			return -EFAULT;
371 		}
372 		break;
373 	}
374 	case V4LVIDEO_IOCTL_GET_CONFIG_PARAMS:
375 	{
376 		struct aml_vcodec_ctx *ctx = NULL;
377 
378 		if (is_v4l2_buf_file(file))
379 			break;
380 
381 		ctx = fh_to_ctx(file->private_data);
382 		if (copy_to_user((void *)argp,
383 			(void *)&ctx->config, sizeof(ctx->config))) {
384 			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
385 				"get config parm err\n");
386 			return -EFAULT;
387 		}
388 		break;
389 	}
390 	default:
391 		return video_ioctl2(file, cmd, arg);
392 	}
393 	return ret;
394 }
395 
396 #ifdef CONFIG_COMPAT
v4l2_compat_ioctl(struct file * file,unsigned int cmd,ulong arg)397 static long v4l2_compat_ioctl(struct file *file,
398 	unsigned int cmd, ulong arg)
399 {
400 	long ret = 0;
401 
402 	ret = v4l2_vcodec_ioctl(file, cmd, (ulong)compat_ptr(arg));
403 	return ret;
404 }
405 #endif
406 
407 static const struct v4l2_file_operations aml_vcodec_fops = {
408 	.owner		= THIS_MODULE,
409 	.open		= fops_vcodec_open,
410 	.release	= fops_vcodec_release,
411 	.poll		= v4l2_m2m_fop_poll,
412 	.unlocked_ioctl = v4l2_vcodec_ioctl,
413 #ifdef CONFIG_COMPAT
414 	.compat_ioctl32 = v4l2_compat_ioctl,
415 #endif
416 	.mmap		= v4l2_m2m_fop_mmap,
417 };
418 
aml_vcodec_probe(struct platform_device * pdev)419 static int aml_vcodec_probe(struct platform_device *pdev)
420 {
421 	struct aml_vcodec_dev *dev;
422 	struct video_device *vfd_dec;
423 	int ret = 0;
424 
425 	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
426 	if (!dev)
427 		return -ENOMEM;
428 
429 	INIT_LIST_HEAD(&dev->ctx_list);
430 	dev->plat_dev = pdev;
431 
432 	mutex_init(&dev->dec_mutex);
433 	mutex_init(&dev->dev_mutex);
434 	spin_lock_init(&dev->irqlock);
435 
436 	snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s",
437 		"[/AML_V4L2_VDEC]");
438 
439 	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
440 	if (ret) {
441 		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
442 			"v4l2_device_register err=%d\n", ret);
443 		goto err_res;
444 	}
445 
446 	init_waitqueue_head(&dev->queue);
447 
448 	vfd_dec = video_device_alloc();
449 	if (!vfd_dec) {
450 		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
451 			"Failed to allocate video device\n");
452 		ret = -ENOMEM;
453 		goto err_dec_alloc;
454 	}
455 
456 	vfd_dec->fops		= &aml_vcodec_fops;
457 	vfd_dec->ioctl_ops	= &aml_vdec_ioctl_ops;
458 	vfd_dec->release	= video_device_release;
459 	vfd_dec->lock		= &dev->dev_mutex;
460 	vfd_dec->v4l2_dev	= &dev->v4l2_dev;
461 	vfd_dec->vfl_dir	= VFL_DIR_M2M;
462 	vfd_dec->device_caps	= V4L2_CAP_VIDEO_M2M_MPLANE |
463 				V4L2_CAP_STREAMING;
464 
465 	snprintf(vfd_dec->name, sizeof(vfd_dec->name), "%s",
466 		AML_VCODEC_DEC_NAME);
467 	video_set_drvdata(vfd_dec, dev);
468 	dev->vfd_dec = vfd_dec;
469 	platform_set_drvdata(pdev, dev);
470 
471 	dev->m2m_dev_dec = v4l2_m2m_init(&aml_vdec_m2m_ops);
472 	if (IS_ERR((__force void *)dev->m2m_dev_dec)) {
473 		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
474 			"Failed to init mem2mem dec device\n");
475 		ret = PTR_ERR((__force void *)dev->m2m_dev_dec);
476 		goto err_dec_mem_init;
477 	}
478 
479 	dev->decode_workqueue =
480 		alloc_ordered_workqueue(AML_VCODEC_DEC_NAME,
481 			WQ_MEM_RECLAIM | WQ_FREEZABLE);
482 	if (!dev->decode_workqueue) {
483 		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
484 			"Failed to create decode workqueue\n");
485 		ret = -EINVAL;
486 		goto err_event_workq;
487 	}
488 
489 	//dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num);
490 
491 	ret = video_register_device(vfd_dec, VFL_TYPE_VIDEO, 26);
492 	if (ret) {
493 		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
494 			"Failed to register video device\n");
495 		goto err_dec_reg;
496 	}
497 
498 	v4l_dbg(0, V4L_DEBUG_CODEC_PRINFO,
499 		"decoder registered as /dev/video%d\n", vfd_dec->num);
500 
501 	return 0;
502 
503 err_dec_reg:
504 	destroy_workqueue(dev->decode_workqueue);
505 err_event_workq:
506 	v4l2_m2m_release(dev->m2m_dev_dec);
507 err_dec_mem_init:
508 	video_unregister_device(vfd_dec);
509 err_dec_alloc:
510 	v4l2_device_unregister(&dev->v4l2_dev);
511 err_res:
512 
513 	return ret;
514 }
515 
516 static const struct of_device_id aml_vcodec_match[] = {
517 	{.compatible = "amlogic, vcodec-dec",},
518 	{},
519 };
520 
521 MODULE_DEVICE_TABLE(of, aml_vcodec_match);
522 
aml_vcodec_dec_remove(struct platform_device * pdev)523 static int aml_vcodec_dec_remove(struct platform_device *pdev)
524 {
525 	struct aml_vcodec_dev *dev = platform_get_drvdata(pdev);
526 
527 	flush_workqueue(dev->decode_workqueue);
528 	destroy_workqueue(dev->decode_workqueue);
529 
530 	if (dev->m2m_dev_dec)
531 		v4l2_m2m_release(dev->m2m_dev_dec);
532 
533 	if (dev->vfd_dec)
534 		video_unregister_device(dev->vfd_dec);
535 
536 	v4l2_device_unregister(&dev->v4l2_dev);
537 
538 	return 0;
539 }
540 
541 /*static void aml_vcodec_dev_release(struct device *dev)
542 {
543 }*/
544 
545 static struct platform_driver aml_vcodec_dec_driver = {
546 	.probe	= aml_vcodec_probe,
547 	.remove	= aml_vcodec_dec_remove,
548 	.driver	= {
549 		.name	= AML_VCODEC_DEC_NAME,
550 		.of_match_table = aml_vcodec_match,
551 	},
552 };
553 
554 /*
555 static struct platform_device aml_vcodec_dec_device = {
556 	.name		= AML_VCODEC_DEC_NAME,
557 	.dev.release	= aml_vcodec_dev_release,
558 };*/
559 
560 module_platform_driver(aml_vcodec_dec_driver);
561 
562 /*
563 static int __init amvdec_ports_init(void)
564 {
565 	int ret;
566 
567 	ret = platform_device_register(&aml_vcodec_dec_device);
568 	if (ret)
569 		return ret;
570 
571 	ret = platform_driver_register(&aml_vcodec_dec_driver);
572 	if (ret)
573 		platform_device_unregister(&aml_vcodec_dec_device);
574 
575 	return ret;
576 }
577 
578 static void __exit amvdec_ports_exit(void)
579 {
580 	platform_driver_unregister(&aml_vcodec_dec_driver);
581 	platform_device_unregister(&aml_vcodec_dec_device);
582 }
583 
584 module_init(amvdec_ports_init);
585 module_exit(amvdec_ports_exit);
586 */
587 
588 u32 debug_mode;
589 EXPORT_SYMBOL(debug_mode);
590 module_param(debug_mode, uint, 0644);
591 
592 bool aml_set_vfm_enable;
593 EXPORT_SYMBOL(aml_set_vfm_enable);
594 module_param(aml_set_vfm_enable, bool, 0644);
595 
596 int aml_set_vfm_path;
597 EXPORT_SYMBOL(aml_set_vfm_path);
598 module_param(aml_set_vfm_path, int, 0644);
599 
600 bool aml_set_vdec_type_enable;
601 EXPORT_SYMBOL(aml_set_vdec_type_enable);
602 module_param(aml_set_vdec_type_enable, bool, 0644);
603 
604 int aml_set_vdec_type;
605 EXPORT_SYMBOL(aml_set_vdec_type);
606 module_param(aml_set_vdec_type, int, 0644);
607 
608 int vp9_need_prefix;
609 EXPORT_SYMBOL(vp9_need_prefix);
610 module_param(vp9_need_prefix, int, 0644);
611 
612 bool multiplanar;
613 EXPORT_SYMBOL(multiplanar);
614 module_param(multiplanar, bool, 0644);
615 
616 bool dump_capture_frame;
617 EXPORT_SYMBOL(dump_capture_frame);
618 module_param(dump_capture_frame, bool, 0644);
619 
620 EXPORT_SYMBOL(param_sets_from_ucode);
621 module_param(param_sets_from_ucode, bool, 0644);
622 
623 EXPORT_SYMBOL(enable_drm_mode);
624 module_param(enable_drm_mode, bool, 0644);
625 
626 MODULE_LICENSE("GPL v2");
627 MODULE_DESCRIPTION("AML video codec V4L2 decoder driver");
628 
629