summaryrefslogtreecommitdiff
path: root/drivers/amvdec_ports/aml_vcodec_dec_drv.c (plain)
blob: 43ff0c5951a88dac1fb1faa00e8129710343b76b
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
33#include "aml_vcodec_drv.h"
34#include "aml_vcodec_dec.h"
35#include "aml_vcodec_dec_pm.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
52bool scatter_mem_enable;
53bool param_sets_from_ucode;
54
55static 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_waitqueue_head(&ctx->wq);
87 init_completion(&ctx->comp);
88
89 ctx->scatter_mem_enable = scatter_mem_enable ? 1 : 0;
90 ctx->param_sets_from_ucode = param_sets_from_ucode ? 1 : 0;
91
92 ctx->type = AML_INST_DECODER;
93 ret = aml_vcodec_dec_ctrls_setup(ctx);
94 if (ret) {
95 aml_v4l2_err("Failed to setup vcodec controls");
96 goto err_ctrls_setup;
97 }
98 ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev_dec, ctx,
99 &aml_vcodec_dec_queue_init);
100 if (IS_ERR((__force void *)ctx->m2m_ctx)) {
101 ret = PTR_ERR((__force void *)ctx->m2m_ctx);
102 aml_v4l2_err("Failed to v4l2_m2m_ctx_init() (%d)", ret);
103 goto err_m2m_ctx_init;
104 }
105 src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx,
106 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
107 ctx->empty_flush_buf->vb.vb2_buf.vb2_queue = src_vq;
108 ctx->empty_flush_buf->lastframe = true;
109 aml_vcodec_dec_set_default_params(ctx);
110
111 ret = aml_thread_start(ctx, try_to_capture, AML_THREAD_CAPTURE, "cap");
112 if (ret) {
113 aml_v4l2_err("Failed to creat capture thread.");
114 goto err_creat_thread;
115 }
116
117 list_add(&ctx->list, &dev->ctx_list);
118
119 mutex_unlock(&dev->dev_mutex);
120 pr_info("[%d] %s decoder\n", ctx->id, dev_name(&dev->plat_dev->dev));
121
122 return ret;
123
124 /* Deinit when failure occurred */
125err_creat_thread:
126 v4l2_m2m_ctx_release(ctx->m2m_ctx);
127err_m2m_ctx_init:
128 v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
129err_ctrls_setup:
130 v4l2_fh_del(&ctx->fh);
131 v4l2_fh_exit(&ctx->fh);
132 kfree(ctx->empty_flush_buf);
133 kfree(ctx);
134 mutex_unlock(&dev->dev_mutex);
135
136 return ret;
137}
138
139static int fops_vcodec_release(struct file *file)
140{
141 struct aml_vcodec_dev *dev = video_drvdata(file);
142 struct aml_vcodec_ctx *ctx = fh_to_ctx(file->private_data);
143
144 pr_info("[%d] release decoder\n", ctx->id);
145 mutex_lock(&dev->dev_mutex);
146
147 /*
148 * Call v4l2_m2m_ctx_release before aml_vcodec_dec_release. First, it
149 * makes sure the worker thread is not running after vdec_if_deinit.
150 * Second, the decoder will be flushed and all the buffers will be
151 * returned in stop_streaming.
152 */
153 aml_thread_stop(ctx);
154 wait_vcodec_ending(ctx);
155 v4l2_m2m_ctx_release(ctx->m2m_ctx);
156 aml_vcodec_dec_release(ctx);
157
158 v4l2_fh_del(&ctx->fh);
159 v4l2_fh_exit(&ctx->fh);
160 v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
161
162 list_del_init(&ctx->list);
163 kfree(ctx->empty_flush_buf);
164 kfree(ctx);
165 mutex_unlock(&dev->dev_mutex);
166 return 0;
167}
168
169static int v4l2video_file_release(struct inode *inode, struct file *file)
170{
171 aml_v4l2_debug(2,"%s: file: 0x%p, data: %p",
172 __func__, file, file->private_data);
173
174 if (file->private_data)
175 vdec_frame_buffer_release(file->private_data);
176
177 return 0;
178}
179
180const struct file_operations v4l2_file_fops = {
181 .release = v4l2video_file_release,
182};
183
184int v4l2_alloc_fd(int *fd)
185{
186 struct file *file = NULL;
187 int file_fd = get_unused_fd_flags(O_CLOEXEC);
188
189 if (file_fd < 0) {
190 pr_err("%s: get unused fd fail\n", __func__);
191 return -ENODEV;
192 }
193
194 file = anon_inode_getfile("v4l2_meta_file", &v4l2_file_fops, NULL, 0);
195 if (IS_ERR(file)) {
196 put_unused_fd(file_fd);
197 pr_err("%s: anon_inode_getfile fail\n", __func__);
198 return -ENODEV;
199 }
200
201 file->private_data =
202 kzalloc(sizeof(struct file_private_data), GFP_KERNEL);
203 if (!file->private_data) {
204 pr_err("%s: alloc priv data faild.\n", __func__);
205 return -ENOMEM;
206 }
207
208 aml_v4l2_debug(2, "%s: fd %d, file %p", __func__, file_fd, file);
209
210 fd_install(file_fd, file);
211 *fd = file_fd;
212
213 return 0;
214}
215
216extern const struct file_operations v4l2_file_fops;
217bool is_v4l2_buf_file(struct file *file)
218{
219 return file->f_op == &v4l2_file_fops;
220}
221
222int v4l2_check_fd(int fd)
223{
224 struct file *file;
225
226 file = fget(fd);
227
228 if (!file) {
229 pr_err("%s: fget fd %d fail!\n", __func__, fd);
230 return -EBADF;
231 }
232
233 if (!is_v4l2_buf_file(file)) {
234 fput(file);
235 pr_err("%s: is_v4l2_buf_file fail!\n", __func__);
236 return -1;
237 }
238
239 fput(file);
240
241 aml_v4l2_debug(5, "%s: ioctl ok, comm %s, pid %d",
242 __func__, current->comm, current->pid);
243
244 return 0;
245}
246
247int dmabuf_fd_install_data(int fd, void* data, u32 size)
248{
249 struct file *file;
250
251 file = fget(fd);
252
253 if (!file) {
254 pr_err("%s: fget fd %d fail!, comm %s, pid %d\n",
255 __func__, fd, current->comm, current->pid);
256 return -EBADF;
257 }
258
259 if (!is_v4l2_buf_file(file)) {
260 fput(file);
261 pr_err("%s the buf file checked fail!\n", __func__);
262 return -EBADF;
263 }
264
265 memcpy(file->private_data, data, size);
266
267 fput(file);
268
269 return 0;
270}
271
272void* v4l_get_vf_handle(int fd)
273{
274 struct file *file;
275 struct file_private_data *data = NULL;
276 void *vf_handle = 0;
277
278 file = fget(fd);
279
280 if (!file) {
281 pr_err("%s: fget fd %d fail!, comm %s, pid %d\n",
282 __func__, fd, current->comm, current->pid);
283 return NULL;
284 }
285
286 if (!is_v4l2_buf_file(file)) {
287 fput(file);
288 pr_err("%s the buf file checked fail!\n", __func__);
289 return NULL;
290 }
291
292 data = (struct file_private_data*) file->private_data;
293 if (data)
294 vf_handle = &data->vf;
295
296 fput(file);
297
298 return vf_handle;
299}
300
301
302static long v4l2_vcodec_ioctl(struct file *file,
303 unsigned int cmd,
304 ulong arg)
305{
306 long ret = 0;
307 void __user *argp = (void __user *)arg;
308
309 switch (cmd) {
310 case V4LVIDEO_IOCTL_ALLOC_FD:
311 {
312 u32 v4lvideo_fd = 0;
313
314 ret = v4l2_alloc_fd(&v4lvideo_fd);
315 if (ret != 0)
316 break;
317 put_user(v4lvideo_fd, (u32 __user *)argp);
318 aml_v4l2_debug(4, "%s: V4LVIDEO_IOCTL_ALLOC_FD fd %d",
319 __func__, v4lvideo_fd);
320 break;
321 }
322 case V4LVIDEO_IOCTL_CHECK_FD:
323 {
324 u32 v4lvideo_fd = 0;
325
326 get_user(v4lvideo_fd, (u32 __user *)argp);
327 ret = v4l2_check_fd(v4lvideo_fd);
328 if (ret != 0)
329 break;
330 aml_v4l2_debug(4, "%s: V4LVIDEO_IOCTL_CHECK_FD fd %d",
331 __func__, v4lvideo_fd);
332 break;
333 }
334 case V4LVIDEO_IOCTL_SET_CONFIG_PARAMS:
335 {
336 struct aml_vcodec_ctx *ctx = NULL;
337
338 if (is_v4l2_buf_file(file))
339 break;
340
341 ctx = fh_to_ctx(file->private_data);
342 if (copy_from_user((void *)&ctx->config,
343 (void *)argp, sizeof(ctx->config))) {
344 pr_err("[%s],set config parm err\n", __func__);
345 return -EFAULT;
346 }
347 break;
348 }
349 case V4LVIDEO_IOCTL_GET_CONFIG_PARAMS:
350 {
351 struct aml_vcodec_ctx *ctx = NULL;
352
353 if (is_v4l2_buf_file(file))
354 break;
355
356 ctx = fh_to_ctx(file->private_data);
357 if (copy_to_user((void *)argp,
358 (void *)&ctx->config, sizeof(ctx->config))) {
359 pr_err("[%s],get config parm err\n", __func__);
360 return -EFAULT;
361 }
362 break;
363 }
364 default:
365 return video_ioctl2(file, cmd, arg);
366 }
367 return ret;
368}
369
370#ifdef CONFIG_COMPAT
371static long v4l2_compat_ioctl(struct file *file,
372 unsigned int cmd, ulong arg)
373{
374 long ret = 0;
375
376 ret = v4l2_vcodec_ioctl(file, cmd, (ulong)compat_ptr(arg));
377 return ret;
378}
379#endif
380
381static const struct v4l2_file_operations aml_vcodec_fops = {
382 .owner = THIS_MODULE,
383 .open = fops_vcodec_open,
384 .release = fops_vcodec_release,
385 .poll = v4l2_m2m_fop_poll,
386 .unlocked_ioctl = v4l2_vcodec_ioctl,
387#ifdef CONFIG_COMPAT
388 .compat_ioctl32 = v4l2_compat_ioctl,
389#endif
390 .mmap = v4l2_m2m_fop_mmap,
391};
392
393static int aml_vcodec_probe(struct platform_device *pdev)
394{
395 struct aml_vcodec_dev *dev;
396 struct video_device *vfd_dec;
397 int ret = 0;
398
399 dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
400 if (!dev)
401 return -ENOMEM;
402
403 INIT_LIST_HEAD(&dev->ctx_list);
404 dev->plat_dev = pdev;
405
406 mutex_init(&dev->dec_mutex);
407 mutex_init(&dev->dev_mutex);
408 spin_lock_init(&dev->irqlock);
409
410 snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s",
411 "[/AML_V4L2_VDEC]");
412
413 ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
414 if (ret) {
415 aml_v4l2_err("v4l2_device_register err=%d", ret);
416 goto err_res;
417 }
418
419 init_waitqueue_head(&dev->queue);
420
421 vfd_dec = video_device_alloc();
422 if (!vfd_dec) {
423 aml_v4l2_err("Failed to allocate video device");
424 ret = -ENOMEM;
425 goto err_dec_alloc;
426 }
427
428 vfd_dec->fops = &aml_vcodec_fops;
429 vfd_dec->ioctl_ops = &aml_vdec_ioctl_ops;
430 vfd_dec->release = video_device_release;
431 vfd_dec->lock = &dev->dev_mutex;
432 vfd_dec->v4l2_dev = &dev->v4l2_dev;
433 vfd_dec->vfl_dir = VFL_DIR_M2M;
434 vfd_dec->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE |
435 V4L2_CAP_STREAMING;
436
437 snprintf(vfd_dec->name, sizeof(vfd_dec->name), "%s",
438 AML_VCODEC_DEC_NAME);
439 video_set_drvdata(vfd_dec, dev);
440 dev->vfd_dec = vfd_dec;
441 platform_set_drvdata(pdev, dev);
442
443 dev->m2m_dev_dec = v4l2_m2m_init(&aml_vdec_m2m_ops);
444 if (IS_ERR((__force void *)dev->m2m_dev_dec)) {
445 aml_v4l2_err("Failed to init mem2mem dec device");
446 ret = PTR_ERR((__force void *)dev->m2m_dev_dec);
447 goto err_dec_mem_init;
448 }
449
450 dev->decode_workqueue =
451 alloc_ordered_workqueue(AML_VCODEC_DEC_NAME,
452 WQ_MEM_RECLAIM | WQ_FREEZABLE);
453 if (!dev->decode_workqueue) {
454 aml_v4l2_err("Failed to create decode workqueue");
455 ret = -EINVAL;
456 goto err_event_workq;
457 }
458
459 //dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num);
460
461 ret = video_register_device(vfd_dec, VFL_TYPE_GRABBER, 26);
462 if (ret) {
463 pr_err("Failed to register video device\n");
464 goto err_dec_reg;
465 }
466
467 pr_info("decoder registered as /dev/video%d\n", vfd_dec->num);
468
469 return 0;
470
471err_dec_reg:
472 destroy_workqueue(dev->decode_workqueue);
473err_event_workq:
474 v4l2_m2m_release(dev->m2m_dev_dec);
475err_dec_mem_init:
476 video_unregister_device(vfd_dec);
477err_dec_alloc:
478 v4l2_device_unregister(&dev->v4l2_dev);
479err_res:
480
481 return ret;
482}
483
484static const struct of_device_id aml_vcodec_match[] = {
485 {.compatible = "amlogic, vcodec-dec",},
486 {},
487};
488
489MODULE_DEVICE_TABLE(of, aml_vcodec_match);
490
491static int aml_vcodec_dec_remove(struct platform_device *pdev)
492{
493 struct aml_vcodec_dev *dev = platform_get_drvdata(pdev);
494
495 flush_workqueue(dev->decode_workqueue);
496 destroy_workqueue(dev->decode_workqueue);
497
498 if (dev->m2m_dev_dec)
499 v4l2_m2m_release(dev->m2m_dev_dec);
500
501 if (dev->vfd_dec)
502 video_unregister_device(dev->vfd_dec);
503
504 v4l2_device_unregister(&dev->v4l2_dev);
505
506 return 0;
507}
508
509/*static void aml_vcodec_dev_release(struct device *dev)
510{
511}*/
512
513static struct platform_driver aml_vcodec_dec_driver = {
514 .probe = aml_vcodec_probe,
515 .remove = aml_vcodec_dec_remove,
516 .driver = {
517 .name = AML_VCODEC_DEC_NAME,
518 .of_match_table = aml_vcodec_match,
519 },
520};
521
522/*
523static struct platform_device aml_vcodec_dec_device = {
524 .name = AML_VCODEC_DEC_NAME,
525 .dev.release = aml_vcodec_dev_release,
526};*/
527
528module_platform_driver(aml_vcodec_dec_driver);
529
530/*
531static int __init amvdec_ports_init(void)
532{
533 int ret;
534
535 ret = platform_device_register(&aml_vcodec_dec_device);
536 if (ret)
537 return ret;
538
539 ret = platform_driver_register(&aml_vcodec_dec_driver);
540 if (ret)
541 platform_device_unregister(&aml_vcodec_dec_device);
542
543 return ret;
544}
545
546static void __exit amvdec_ports_exit(void)
547{
548 platform_driver_unregister(&aml_vcodec_dec_driver);
549 platform_device_unregister(&aml_vcodec_dec_device);
550}
551
552module_init(amvdec_ports_init);
553module_exit(amvdec_ports_exit);
554*/
555
556module_param(aml_v4l2_dbg_level, int, 0644);
557module_param(aml_vcodec_dbg, bool, 0644);
558
559bool aml_set_vfm_enable;
560EXPORT_SYMBOL(aml_set_vfm_enable);
561module_param(aml_set_vfm_enable, bool, 0644);
562
563int aml_set_vfm_path;
564EXPORT_SYMBOL(aml_set_vfm_path);
565module_param(aml_set_vfm_path, int, 0644);
566
567bool aml_set_vdec_type_enable;
568EXPORT_SYMBOL(aml_set_vdec_type_enable);
569module_param(aml_set_vdec_type_enable, bool, 0644);
570
571int aml_set_vdec_type;
572EXPORT_SYMBOL(aml_set_vdec_type);
573module_param(aml_set_vdec_type, int, 0644);
574
575int vp9_need_prefix;
576EXPORT_SYMBOL(vp9_need_prefix);
577module_param(vp9_need_prefix, int, 0644);
578
579bool multiplanar;
580EXPORT_SYMBOL(multiplanar);
581module_param(multiplanar, bool, 0644);
582
583EXPORT_SYMBOL(scatter_mem_enable);
584module_param(scatter_mem_enable, bool, 0644);
585
586EXPORT_SYMBOL(param_sets_from_ucode);
587module_param(param_sets_from_ucode, bool, 0644);
588
589MODULE_LICENSE("GPL v2");
590MODULE_DESCRIPTION("AML video codec V4L2 decoder driver");
591
592