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