xref: /OK3568_Linux_fs/external/mpp/osal/driver/mpp_device.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright 2020 Rockchip Electronics Co. LTD
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define MODULE_TAG "mpp_device"
18 
19 #include <string.h>
20 
21 #include "mpp_env.h"
22 #include "mpp_mem.h"
23 #include "mpp_common.h"
24 
25 #include "mpp_platform.h"
26 #include "mpp_device_debug.h"
27 #include "mpp_service_api.h"
28 #include "vcodec_service_api.h"
29 
30 typedef struct MppDevImpl_t {
31     MppClientType   type;
32 
33     void            *ctx;
34     const MppDevApi *api;
35 } MppDevImpl;
36 
37 RK_U32 mpp_device_debug = 0;
38 
mpp_dev_init(MppDev * ctx,MppClientType type)39 MPP_RET mpp_dev_init(MppDev *ctx, MppClientType type)
40 {
41     if (NULL == ctx) {
42         mpp_err_f("found NULL input ctx\n");
43         return MPP_ERR_NULL_PTR;
44     }
45 
46     mpp_env_get_u32("mpp_device_debug", &mpp_device_debug, 0);
47 
48     *ctx = NULL;
49 
50     RK_U32 codec_type = mpp_get_vcodec_type();
51     if (!(codec_type & (1 << type))) {
52         mpp_err_f("found unsupported client type %d in platform %x\n",
53                   type, codec_type);
54         return MPP_ERR_VALUE;
55     }
56 
57     MppIoctlVersion ioctl_version = mpp_get_ioctl_version();
58     const MppDevApi *api = NULL;
59 
60     switch (ioctl_version) {
61     case IOCTL_VCODEC_SERVICE : {
62         api = &vcodec_service_api;
63     } break;
64     case IOCTL_MPP_SERVICE_V1 : {
65         api = &mpp_service_api;
66     } break;
67     default : {
68         mpp_err_f("invalid ioctl verstion %d\n", ioctl_version);
69         return MPP_NOK;
70     } break;
71     }
72 
73     MppDevImpl *impl = mpp_calloc(MppDevImpl, 1);
74     void *impl_ctx = mpp_calloc_size(void, api->ctx_size);
75     if (NULL == impl || NULL == impl_ctx) {
76         mpp_err_f("malloc failed impl %p impl_ctx %p\n", impl, impl_ctx);
77         MPP_FREE(impl);
78         MPP_FREE(impl_ctx);
79         return MPP_ERR_MALLOC;
80     }
81 
82     impl->ctx = impl_ctx;
83     impl->api = api;
84     impl->type = type;
85     *ctx = impl;
86 
87     return api->init(impl_ctx, type);
88 }
89 
mpp_dev_deinit(MppDev ctx)90 MPP_RET mpp_dev_deinit(MppDev ctx)
91 {
92     if (NULL == ctx) {
93         mpp_err_f("found NULL input ctx\n");
94         return MPP_ERR_NULL_PTR;
95     }
96 
97     MppDevImpl *p = (MppDevImpl *)ctx;
98     MPP_RET ret = MPP_OK;
99 
100     if (p->api && p->api->deinit && p->ctx)
101         ret = p->api->deinit(p->ctx);
102 
103     MPP_FREE(p->ctx);
104     MPP_FREE(p);
105 
106     return ret;
107 }
108 
mpp_dev_ioctl(MppDev ctx,RK_S32 cmd,void * param)109 MPP_RET mpp_dev_ioctl(MppDev ctx, RK_S32 cmd, void *param)
110 {
111     if (NULL == ctx) {
112         mpp_err_f("found NULL input ctx\n");
113         return MPP_ERR_NULL_PTR;
114     }
115 
116     MppDevImpl *p = (MppDevImpl *)ctx;
117     const MppDevApi *api = p->api;
118     void *impl_ctx = p->ctx;
119     MPP_RET ret = MPP_OK;
120 
121     if (NULL == impl_ctx || NULL == api)
122         return ret;
123 
124     switch (cmd) {
125     case MPP_DEV_BATCH_ON : {
126         if (api->attach)
127             ret = api->attach(impl_ctx);
128     } break;
129     case MPP_DEV_BATCH_OFF : {
130         if (api->detach)
131             ret = api->detach(impl_ctx);
132     } break;
133     case MPP_DEV_DELIMIT : {
134         if (api->delimit)
135             ret = api->delimit(impl_ctx);
136     } break;
137     case MPP_DEV_SET_CB_CTX: {
138         if (api->set_cb_ctx)
139             ret = api->set_cb_ctx(impl_ctx, param);
140     } break;
141     case MPP_DEV_REG_WR : {
142         if (api->reg_wr)
143             ret = api->reg_wr(impl_ctx, param);
144     } break;
145     case MPP_DEV_REG_RD : {
146         if (api->reg_rd)
147             ret = api->reg_rd(impl_ctx, param);
148     } break;
149     case MPP_DEV_REG_OFFSET : {
150         if (api->reg_offset)
151             ret = api->reg_offset(impl_ctx, param);
152     } break;
153     case MPP_DEV_REG_OFFS : {
154         if (api->reg_offs)
155             ret = api->reg_offs(impl_ctx, param);
156     } break;
157     case MPP_DEV_RCB_INFO : {
158         if (api->rcb_info)
159             ret = api->rcb_info(impl_ctx, param);
160     } break;
161     case MPP_DEV_SET_INFO : {
162         if (api->set_info)
163             ret = api->set_info(impl_ctx, param);
164     } break;
165     case MPP_DEV_SET_ERR_REF_HACK : {
166         if (api->set_err_ref_hack)
167             ret = api->set_err_ref_hack(impl_ctx, param);
168     } break;
169     case MPP_DEV_CMD_SEND : {
170         if (api->cmd_send)
171             ret = api->cmd_send(impl_ctx);
172     } break;
173     case MPP_DEV_CMD_POLL : {
174         if (api->cmd_poll)
175             ret = api->cmd_poll(impl_ctx, param);
176     } break;
177     default : {
178         mpp_err_f("invalid cmd %d\n", cmd);
179     } break;
180     }
181 
182     return ret;
183 }
184 
mpp_dev_set_reg_offset(MppDev dev,RK_S32 index,RK_U32 offset)185 MPP_RET mpp_dev_set_reg_offset(MppDev dev, RK_S32 index, RK_U32 offset)
186 {
187     MppDevRegOffsetCfg trans_cfg;
188 
189     trans_cfg.reg_idx = index;
190     trans_cfg.offset = offset;
191 
192     return mpp_dev_ioctl(dev, MPP_DEV_REG_OFFSET, &trans_cfg);
193 }
194 
195 /* register offset multi config */
mpp_dev_multi_offset_init(MppDevRegOffCfgs ** cfgs,RK_S32 size)196 MPP_RET mpp_dev_multi_offset_init(MppDevRegOffCfgs **cfgs, RK_S32 size)
197 {
198     RK_S32 cfg_size = sizeof(MppDevRegOffCfgs) + size * sizeof(MppDevRegOffsetCfg);
199     MppDevRegOffCfgs *p = NULL;
200 
201     if (NULL == cfgs || size <= 0) {
202         mpp_err_f("invalid pointer %p size %d\n", cfgs, size);
203         return MPP_NOK;
204     }
205 
206     p = mpp_calloc_size(MppDevRegOffCfgs, cfg_size);
207     if (p)
208         p->size = size;
209 
210     *cfgs = p;
211 
212     return (p) ? MPP_OK : MPP_NOK;
213 }
214 
mpp_dev_multi_offset_deinit(MppDevRegOffCfgs * cfgs)215 MPP_RET mpp_dev_multi_offset_deinit(MppDevRegOffCfgs *cfgs)
216 {
217     MPP_FREE(cfgs);
218 
219     return MPP_OK;
220 }
221 
mpp_dev_multi_offset_reset(MppDevRegOffCfgs * cfgs)222 MPP_RET mpp_dev_multi_offset_reset(MppDevRegOffCfgs *cfgs)
223 {
224     if (cfgs) {
225         memset(cfgs->cfgs, 0, cfgs->count * sizeof(cfgs->cfgs[0]));
226         cfgs->count = 0;
227     }
228 
229     return MPP_OK;
230 }
231 
mpp_dev_multi_offset_update(MppDevRegOffCfgs * cfgs,RK_S32 index,RK_U32 offset)232 MPP_RET mpp_dev_multi_offset_update(MppDevRegOffCfgs *cfgs, RK_S32 index, RK_U32 offset)
233 {
234     MppDevRegOffsetCfg *cfg;
235     RK_S32 count;
236     RK_S32 i;
237 
238     if (NULL == cfgs)
239         return MPP_NOK;
240 
241     if (cfgs->count >= cfgs->size) {
242         mpp_err_f("invalid cfgs count %d : %d\n", cfgs->count, cfgs->size);
243         return MPP_NOK;
244     }
245 
246     count = cfgs->count;
247     cfg = cfgs->cfgs;
248 
249     for (i = 0; i < count; i++, cfg++) {
250 
251         if (cfg->reg_idx == (RK_U32)index) {
252             cfg->offset = offset;
253             return MPP_OK;
254         }
255     }
256 
257     cfg->reg_idx = index;
258     cfg->offset = offset;
259     cfgs->count++;
260 
261     return MPP_OK;
262 }
263