GNU Linux-libre 4.14.332-gnu1
[releases.git] / drivers / media / platform / mtk-vcodec / vdec_drv_if.c
1 /*
2  * Copyright (c) 2016 MediaTek Inc.
3  * Author: PC Chen <pc.chen@mediatek.com>
4  *         Tiffany Lin <tiffany.lin@mediatek.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
15
16 #include <linux/interrupt.h>
17 #include <linux/kernel.h>
18 #include <linux/slab.h>
19
20 #include "vdec_drv_if.h"
21 #include "mtk_vcodec_dec.h"
22 #include "vdec_drv_base.h"
23 #include "mtk_vcodec_dec_pm.h"
24 #include "mtk_vpu.h"
25
26 const struct vdec_common_if *get_h264_dec_comm_if(void);
27 const struct vdec_common_if *get_vp8_dec_comm_if(void);
28 const struct vdec_common_if *get_vp9_dec_comm_if(void);
29
30 int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
31 {
32         int ret = 0;
33
34         switch (fourcc) {
35         case V4L2_PIX_FMT_H264:
36                 ctx->dec_if = get_h264_dec_comm_if();
37                 break;
38         case V4L2_PIX_FMT_VP8:
39                 ctx->dec_if = get_vp8_dec_comm_if();
40                 break;
41         case V4L2_PIX_FMT_VP9:
42                 ctx->dec_if = get_vp9_dec_comm_if();
43                 break;
44         default:
45                 return -EINVAL;
46         }
47
48         mtk_vdec_lock(ctx);
49         mtk_vcodec_dec_clock_on(&ctx->dev->pm);
50         ret = ctx->dec_if->init(ctx, &ctx->drv_handle);
51         mtk_vcodec_dec_clock_off(&ctx->dev->pm);
52         mtk_vdec_unlock(ctx);
53
54         return ret;
55 }
56
57 int vdec_if_decode(struct mtk_vcodec_ctx *ctx, struct mtk_vcodec_mem *bs,
58                    struct vdec_fb *fb, bool *res_chg)
59 {
60         int ret = 0;
61
62         if (bs) {
63                 if ((bs->dma_addr & 63) != 0) {
64                         mtk_v4l2_err("bs dma_addr should 64 byte align");
65                         return -EINVAL;
66                 }
67         }
68
69         if (fb) {
70                 if (((fb->base_y.dma_addr & 511) != 0) ||
71                     ((fb->base_c.dma_addr & 511) != 0)) {
72                         mtk_v4l2_err("frame buffer dma_addr should 512 byte align");
73                         return -EINVAL;
74                 }
75         }
76
77         if (ctx->drv_handle == 0)
78                 return -EIO;
79
80         mtk_vdec_lock(ctx);
81
82         mtk_vcodec_set_curr_ctx(ctx->dev, ctx);
83         mtk_vcodec_dec_clock_on(&ctx->dev->pm);
84         enable_irq(ctx->dev->dec_irq);
85         ret = ctx->dec_if->decode(ctx->drv_handle, bs, fb, res_chg);
86         disable_irq(ctx->dev->dec_irq);
87         mtk_vcodec_dec_clock_off(&ctx->dev->pm);
88         mtk_vcodec_set_curr_ctx(ctx->dev, NULL);
89
90         mtk_vdec_unlock(ctx);
91
92         return ret;
93 }
94
95 int vdec_if_get_param(struct mtk_vcodec_ctx *ctx, enum vdec_get_param_type type,
96                       void *out)
97 {
98         int ret = 0;
99
100         if (ctx->drv_handle == 0)
101                 return -EIO;
102
103         mtk_vdec_lock(ctx);
104         ret = ctx->dec_if->get_param(ctx->drv_handle, type, out);
105         mtk_vdec_unlock(ctx);
106
107         return ret;
108 }
109
110 void vdec_if_deinit(struct mtk_vcodec_ctx *ctx)
111 {
112         if (ctx->drv_handle == 0)
113                 return;
114
115         mtk_vdec_lock(ctx);
116         mtk_vcodec_dec_clock_on(&ctx->dev->pm);
117         ctx->dec_if->deinit(ctx->drv_handle);
118         mtk_vcodec_dec_clock_off(&ctx->dev->pm);
119         mtk_vdec_unlock(ctx);
120
121         ctx->drv_handle = 0;
122 }