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