summaryrefslogtreecommitdiff
path: root/drivers/amvdec_ports/aml_vcodec_dec_drv.c (plain)
blob: d35d738454b8237ea996b442407aaf0eda05f287
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
272static long v4l2_vcodec_ioctl(struct file *file,
273 unsigned int cmd,
274 ulong arg)
275{
276 long ret = 0;
277 void __user *argp = (void __user *)arg;
278
279 switch (cmd) {
280 case V4LVIDEO_IOCTL_ALLOC_FD:
281 {
282 u32 v4lvideo_fd = 0;
283
284 ret = v4l2_alloc_fd(&v4lvideo_fd);
285 if (ret != 0)
286 break;
287 put_user(v4lvideo_fd, (u32 __user *)argp);
288 aml_v4l2_debug(4, "%s: V4LVIDEO_IOCTL_ALLOC_FD fd %d",
289 __func__, v4lvideo_fd);
290 break;
291 }
292 case V4LVIDEO_IOCTL_CHECK_FD:
293 {
294 u32 v4lvideo_fd = 0;
295
296 get_user(v4lvideo_fd, (u32 __user *)argp);
297 ret = v4l2_check_fd(v4lvideo_fd);
298 if (ret != 0)
299 break;
300 aml_v4l2_debug(4, "%s: V4LVIDEO_IOCTL_CHECK_FD fd %d",
301 __func__, v4lvideo_fd);
302 break;
303 }
304 case V4LVIDEO_IOCTL_SET_CONFIG_PARAMS:
305 {
306 struct aml_vcodec_ctx *ctx = NULL;
307
308 if (is_v4l2_buf_file(file))
309 break;
310
311 ctx = fh_to_ctx(file->private_data);
312 if (copy_from_user((void *)&ctx->config,
313 (void *)argp, sizeof(ctx->config))) {
314 pr_err("[%s],set config parm err\n", __func__);
315 return -EFAULT;
316 }
317 break;
318 }
319 case V4LVIDEO_IOCTL_GET_CONFIG_PARAMS:
320 {
321 struct aml_vcodec_ctx *ctx = NULL;
322
323 if (is_v4l2_buf_file(file))
324 break;
325
326 ctx = fh_to_ctx(file->private_data);
327 if (copy_to_user((void *)argp,
328 (void *)&ctx->config, sizeof(ctx->config))) {
329 pr_err("[%s],get config parm err\n", __func__);
330 return -EFAULT;
331 }
332 break;
333 }
334 default:
335 return video_ioctl2(file, cmd, arg);
336 }
337 return ret;
338}
339
340#ifdef CONFIG_COMPAT
341static long v4l2_compat_ioctl(struct file *file,
342 unsigned int cmd, ulong arg)
343{
344 long ret = 0;
345
346 ret = v4l2_vcodec_ioctl(file, cmd, (ulong)compat_ptr(arg));
347 return ret;
348}
349#endif
350
351static const struct v4l2_file_operations aml_vcodec_fops = {
352 .owner = THIS_MODULE,
353 .open = fops_vcodec_open,
354 .release = fops_vcodec_release,
355 .poll = v4l2_m2m_fop_poll,
356 .unlocked_ioctl = v4l2_vcodec_ioctl,
357#ifdef CONFIG_COMPAT
358 .compat_ioctl32 = v4l2_compat_ioctl,
359#endif
360 .mmap = v4l2_m2m_fop_mmap,
361};
362
363static int aml_vcodec_probe(struct platform_device *pdev)
364{
365 struct aml_vcodec_dev *dev;
366 struct video_device *vfd_dec;
367 int ret = 0;
368
369 dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
370 if (!dev)
371 return -ENOMEM;
372
373 INIT_LIST_HEAD(&dev->ctx_list);
374 dev->plat_dev = pdev;
375
376 mutex_init(&dev->dec_mutex);
377 mutex_init(&dev->dev_mutex);
378 spin_lock_init(&dev->irqlock);
379
380 snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s",
381 "[/AML_V4L2_VDEC]");
382
383 ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
384 if (ret) {
385 aml_v4l2_err("v4l2_device_register err=%d", ret);
386 goto err_res;
387 }
388
389 init_waitqueue_head(&dev->queue);
390
391 vfd_dec = video_device_alloc();
392 if (!vfd_dec) {
393 aml_v4l2_err("Failed to allocate video device");
394 ret = -ENOMEM;
395 goto err_dec_alloc;
396 }
397
398 vfd_dec->fops = &aml_vcodec_fops;
399 vfd_dec->ioctl_ops = &aml_vdec_ioctl_ops;
400 vfd_dec->release = video_device_release;
401 vfd_dec->lock = &dev->dev_mutex;
402 vfd_dec->v4l2_dev = &dev->v4l2_dev;
403 vfd_dec->vfl_dir = VFL_DIR_M2M;
404 vfd_dec->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE |
405 V4L2_CAP_STREAMING;
406
407 snprintf(vfd_dec->name, sizeof(vfd_dec->name), "%s",
408 AML_VCODEC_DEC_NAME);
409 video_set_drvdata(vfd_dec, dev);
410 dev->vfd_dec = vfd_dec;
411 platform_set_drvdata(pdev, dev);
412
413 dev->m2m_dev_dec = v4l2_m2m_init(&aml_vdec_m2m_ops);
414 if (IS_ERR((__force void *)dev->m2m_dev_dec)) {
415 aml_v4l2_err("Failed to init mem2mem dec device");
416 ret = PTR_ERR((__force void *)dev->m2m_dev_dec);
417 goto err_dec_mem_init;
418 }
419
420 dev->decode_workqueue =
421 alloc_ordered_workqueue(AML_VCODEC_DEC_NAME,
422 WQ_MEM_RECLAIM | WQ_FREEZABLE);
423 if (!dev->decode_workqueue) {
424 aml_v4l2_err("Failed to create decode workqueue");
425 ret = -EINVAL;
426 goto err_event_workq;
427 }
428
429 //dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num);
430
431 ret = video_register_device(vfd_dec, VFL_TYPE_GRABBER, 26);
432 if (ret) {
433 pr_err("Failed to register video device\n");
434 goto err_dec_reg;
435 }
436
437 pr_info("decoder registered as /dev/video%d\n", vfd_dec->num);
438
439 return 0;
440
441err_dec_reg:
442 destroy_workqueue(dev->decode_workqueue);
443err_event_workq:
444 v4l2_m2m_release(dev->m2m_dev_dec);
445err_dec_mem_init:
446 video_unregister_device(vfd_dec);
447err_dec_alloc:
448 v4l2_device_unregister(&dev->v4l2_dev);
449err_res:
450
451 return ret;
452}
453
454static const struct of_device_id aml_vcodec_match[] = {
455 {.compatible = "amlogic, vcodec-dec",},
456 {},
457};
458
459MODULE_DEVICE_TABLE(of, aml_vcodec_match);
460
461static int aml_vcodec_dec_remove(struct platform_device *pdev)
462{
463 struct aml_vcodec_dev *dev = platform_get_drvdata(pdev);
464
465 flush_workqueue(dev->decode_workqueue);
466 destroy_workqueue(dev->decode_workqueue);
467
468 if (dev->m2m_dev_dec)
469 v4l2_m2m_release(dev->m2m_dev_dec);
470
471 if (dev->vfd_dec)
472 video_unregister_device(dev->vfd_dec);
473
474 v4l2_device_unregister(&dev->v4l2_dev);
475
476 return 0;
477}
478
479/*static void aml_vcodec_dev_release(struct device *dev)
480{
481}*/
482
483static struct platform_driver aml_vcodec_dec_driver = {
484 .probe = aml_vcodec_probe,
485 .remove = aml_vcodec_dec_remove,
486 .driver = {
487 .name = AML_VCODEC_DEC_NAME,
488 .of_match_table = aml_vcodec_match,
489 },
490};
491
492/*
493static struct platform_device aml_vcodec_dec_device = {
494 .name = AML_VCODEC_DEC_NAME,
495 .dev.release = aml_vcodec_dev_release,
496};*/
497
498module_platform_driver(aml_vcodec_dec_driver);
499
500/*
501static int __init amvdec_ports_init(void)
502{
503 int ret;
504
505 ret = platform_device_register(&aml_vcodec_dec_device);
506 if (ret)
507 return ret;
508
509 ret = platform_driver_register(&aml_vcodec_dec_driver);
510 if (ret)
511 platform_device_unregister(&aml_vcodec_dec_device);
512
513 return ret;
514}
515
516static void __exit amvdec_ports_exit(void)
517{
518 platform_driver_unregister(&aml_vcodec_dec_driver);
519 platform_device_unregister(&aml_vcodec_dec_device);
520}
521
522module_init(amvdec_ports_init);
523module_exit(amvdec_ports_exit);
524*/
525
526module_param(aml_v4l2_dbg_level, int, 0644);
527module_param(aml_vcodec_dbg, bool, 0644);
528
529bool aml_set_vfm_enable;
530EXPORT_SYMBOL(aml_set_vfm_enable);
531module_param(aml_set_vfm_enable, bool, 0644);
532
533int aml_set_vfm_path;
534EXPORT_SYMBOL(aml_set_vfm_path);
535module_param(aml_set_vfm_path, int, 0644);
536
537bool aml_set_vdec_type_enable;
538EXPORT_SYMBOL(aml_set_vdec_type_enable);
539module_param(aml_set_vdec_type_enable, bool, 0644);
540
541int aml_set_vdec_type;
542EXPORT_SYMBOL(aml_set_vdec_type);
543module_param(aml_set_vdec_type, int, 0644);
544
545int vp9_need_prefix;
546EXPORT_SYMBOL(vp9_need_prefix);
547module_param(vp9_need_prefix, int, 0644);
548
549bool multiplanar;
550EXPORT_SYMBOL(multiplanar);
551module_param(multiplanar, bool, 0644);
552
553EXPORT_SYMBOL(scatter_mem_enable);
554module_param(scatter_mem_enable, bool, 0644);
555
556EXPORT_SYMBOL(param_sets_from_ucode);
557module_param(param_sets_from_ucode, bool, 0644);
558
559MODULE_LICENSE("GPL v2");
560MODULE_DESCRIPTION("AML video codec V4L2 decoder driver");
561
562