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