1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * Copyright 2020-2021 NXP |
4 | */ |
5 | |
6 | #ifndef _AMPHION_VPU_RPC_H |
7 | #define _AMPHION_VPU_RPC_H |
8 | |
9 | #include <media/videobuf2-core.h> |
10 | #include "vpu_codec.h" |
11 | |
12 | struct vpu_rpc_buffer_desc { |
13 | u32 wptr; |
14 | u32 rptr; |
15 | u32 start; |
16 | u32 end; |
17 | }; |
18 | |
19 | struct vpu_shared_addr { |
20 | void *iface; |
21 | struct vpu_rpc_buffer_desc *cmd_desc; |
22 | void *cmd_mem_vir; |
23 | struct vpu_rpc_buffer_desc *msg_desc; |
24 | void *msg_mem_vir; |
25 | |
26 | unsigned long boot_addr; |
27 | struct vpu_core *core; |
28 | void *priv; |
29 | }; |
30 | |
31 | struct { |
32 | u32 ; |
33 | u32 ; |
34 | u32 ; |
35 | }; |
36 | |
37 | struct vpu_rpc_event { |
38 | struct vpu_rpc_event_header hdr; |
39 | u32 data[128]; |
40 | }; |
41 | |
42 | struct vpu_iface_ops { |
43 | bool (*check_codec)(enum vpu_core_type type); |
44 | bool (*check_fmt)(enum vpu_core_type type, u32 pixelfmt); |
45 | u32 (*get_data_size)(void); |
46 | int (*check_memory_region)(dma_addr_t base, dma_addr_t addr, u32 size); |
47 | int (*boot_core)(struct vpu_core *core); |
48 | int (*shutdown_core)(struct vpu_core *core); |
49 | int (*restore_core)(struct vpu_core *core); |
50 | int (*get_power_state)(struct vpu_core *core); |
51 | int (*on_firmware_loaded)(struct vpu_core *core); |
52 | void (*init_rpc)(struct vpu_shared_addr *shared, |
53 | struct vpu_buffer *rpc, dma_addr_t boot_addr); |
54 | void (*set_log_buf)(struct vpu_shared_addr *shared, |
55 | struct vpu_buffer *log); |
56 | void (*set_system_cfg)(struct vpu_shared_addr *shared, |
57 | u32 regs_base, void __iomem *regs, u32 index); |
58 | void (*set_stream_cfg)(struct vpu_shared_addr *shared, u32 index); |
59 | u32 (*get_version)(struct vpu_shared_addr *shared); |
60 | u32 (*get_max_instance_count)(struct vpu_shared_addr *shared); |
61 | int (*get_stream_buffer_size)(struct vpu_shared_addr *shared); |
62 | int (*send_cmd_buf)(struct vpu_shared_addr *shared, |
63 | struct vpu_rpc_event *cmd); |
64 | int (*receive_msg_buf)(struct vpu_shared_addr *shared, |
65 | struct vpu_rpc_event *msg); |
66 | int (*pack_cmd)(struct vpu_rpc_event *pkt, u32 index, u32 id, void *data); |
67 | int (*convert_msg_id)(u32 msg_id); |
68 | int (*unpack_msg_data)(struct vpu_rpc_event *pkt, void *data); |
69 | int (*input_frame)(struct vpu_shared_addr *shared, |
70 | struct vpu_inst *inst, struct vb2_buffer *vb); |
71 | int (*config_memory_resource)(struct vpu_shared_addr *shared, |
72 | u32 instance, |
73 | u32 type, |
74 | u32 index, |
75 | struct vpu_buffer *buf); |
76 | int (*config_stream_buffer)(struct vpu_shared_addr *shared, |
77 | u32 instance, |
78 | struct vpu_buffer *buf); |
79 | int (*update_stream_buffer)(struct vpu_shared_addr *shared, |
80 | u32 instance, u32 ptr, bool write); |
81 | int (*get_stream_buffer_desc)(struct vpu_shared_addr *shared, |
82 | u32 instance, |
83 | struct vpu_rpc_buffer_desc *desc); |
84 | int (*set_encode_params)(struct vpu_shared_addr *shared, |
85 | u32 instance, |
86 | struct vpu_encode_params *params, |
87 | u32 update); |
88 | int (*set_decode_params)(struct vpu_shared_addr *shared, |
89 | u32 instance, |
90 | struct vpu_decode_params *params, |
91 | u32 update); |
92 | int (*add_scode)(struct vpu_shared_addr *shared, |
93 | u32 instance, |
94 | struct vpu_buffer *stream_buffer, |
95 | u32 pixelformat, |
96 | u32 scode_type); |
97 | int (*pre_send_cmd)(struct vpu_shared_addr *shared, u32 instance); |
98 | int (*post_send_cmd)(struct vpu_shared_addr *shared, u32 instance); |
99 | int (*init_instance)(struct vpu_shared_addr *shared, u32 instance); |
100 | }; |
101 | |
102 | enum { |
103 | VPU_CORE_MEMORY_INVALID = 0, |
104 | VPU_CORE_MEMORY_CACHED, |
105 | VPU_CORE_MEMORY_UNCACHED |
106 | }; |
107 | |
108 | struct vpu_rpc_region_t { |
109 | dma_addr_t start; |
110 | dma_addr_t end; |
111 | dma_addr_t type; |
112 | }; |
113 | |
114 | struct vpu_iface_ops *vpu_core_get_iface(struct vpu_core *core); |
115 | struct vpu_iface_ops *vpu_inst_get_iface(struct vpu_inst *inst); |
116 | int vpu_iface_check_memory_region(struct vpu_core *core, dma_addr_t addr, u32 size); |
117 | |
118 | static inline bool vpu_iface_check_codec(struct vpu_core *core) |
119 | { |
120 | struct vpu_iface_ops *ops = vpu_core_get_iface(core); |
121 | |
122 | if (ops && ops->check_codec) |
123 | return ops->check_codec(core->type); |
124 | |
125 | return true; |
126 | } |
127 | |
128 | static inline bool vpu_iface_check_format(struct vpu_inst *inst, u32 pixelfmt) |
129 | { |
130 | struct vpu_iface_ops *ops = vpu_inst_get_iface(inst); |
131 | |
132 | if (ops && ops->check_fmt) |
133 | return ops->check_fmt(inst->type, pixelfmt); |
134 | |
135 | return true; |
136 | } |
137 | |
138 | static inline int vpu_iface_boot_core(struct vpu_core *core) |
139 | { |
140 | struct vpu_iface_ops *ops = vpu_core_get_iface(core); |
141 | |
142 | if (ops && ops->boot_core) |
143 | return ops->boot_core(core); |
144 | return 0; |
145 | } |
146 | |
147 | static inline int vpu_iface_get_power_state(struct vpu_core *core) |
148 | { |
149 | struct vpu_iface_ops *ops = vpu_core_get_iface(core); |
150 | |
151 | if (ops && ops->get_power_state) |
152 | return ops->get_power_state(core); |
153 | return 1; |
154 | } |
155 | |
156 | static inline int vpu_iface_shutdown_core(struct vpu_core *core) |
157 | { |
158 | struct vpu_iface_ops *ops = vpu_core_get_iface(core); |
159 | |
160 | if (ops && ops->shutdown_core) |
161 | return ops->shutdown_core(core); |
162 | return 0; |
163 | } |
164 | |
165 | static inline int vpu_iface_restore_core(struct vpu_core *core) |
166 | { |
167 | struct vpu_iface_ops *ops = vpu_core_get_iface(core); |
168 | |
169 | if (ops && ops->restore_core) |
170 | return ops->restore_core(core); |
171 | return 0; |
172 | } |
173 | |
174 | static inline int vpu_iface_on_firmware_loaded(struct vpu_core *core) |
175 | { |
176 | struct vpu_iface_ops *ops = vpu_core_get_iface(core); |
177 | |
178 | if (ops && ops->on_firmware_loaded) |
179 | return ops->on_firmware_loaded(core); |
180 | |
181 | return 0; |
182 | } |
183 | |
184 | static inline u32 vpu_iface_get_data_size(struct vpu_core *core) |
185 | { |
186 | struct vpu_iface_ops *ops = vpu_core_get_iface(core); |
187 | |
188 | if (!ops || !ops->get_data_size) |
189 | return 0; |
190 | |
191 | return ops->get_data_size(); |
192 | } |
193 | |
194 | static inline int vpu_iface_init(struct vpu_core *core, |
195 | struct vpu_shared_addr *shared, |
196 | struct vpu_buffer *rpc, |
197 | dma_addr_t boot_addr) |
198 | { |
199 | struct vpu_iface_ops *ops = vpu_core_get_iface(core); |
200 | |
201 | if (!ops || !ops->init_rpc) |
202 | return -EINVAL; |
203 | |
204 | ops->init_rpc(shared, rpc, boot_addr); |
205 | core->iface = shared; |
206 | shared->core = core; |
207 | if (rpc->bytesused > rpc->length) |
208 | return -ENOSPC; |
209 | return 0; |
210 | } |
211 | |
212 | static inline int vpu_iface_set_log_buf(struct vpu_core *core, |
213 | struct vpu_buffer *log) |
214 | { |
215 | struct vpu_iface_ops *ops = vpu_core_get_iface(core); |
216 | |
217 | if (!ops) |
218 | return -EINVAL; |
219 | |
220 | if (ops->set_log_buf) |
221 | ops->set_log_buf(core->iface, log); |
222 | |
223 | return 0; |
224 | } |
225 | |
226 | static inline int vpu_iface_config_system(struct vpu_core *core, u32 regs_base, void __iomem *regs) |
227 | { |
228 | struct vpu_iface_ops *ops = vpu_core_get_iface(core); |
229 | |
230 | if (!ops) |
231 | return -EINVAL; |
232 | if (ops->set_system_cfg) |
233 | ops->set_system_cfg(core->iface, regs_base, regs, core->id); |
234 | |
235 | return 0; |
236 | } |
237 | |
238 | static inline int vpu_iface_get_stream_buffer_size(struct vpu_core *core) |
239 | { |
240 | struct vpu_iface_ops *ops = vpu_core_get_iface(core); |
241 | |
242 | if (!ops || !ops->get_stream_buffer_size) |
243 | return 0; |
244 | |
245 | return ops->get_stream_buffer_size(core->iface); |
246 | } |
247 | |
248 | static inline int vpu_iface_config_stream(struct vpu_inst *inst) |
249 | { |
250 | struct vpu_iface_ops *ops = vpu_core_get_iface(core: inst->core); |
251 | |
252 | if (!ops || inst->id < 0) |
253 | return -EINVAL; |
254 | if (ops->set_stream_cfg) |
255 | ops->set_stream_cfg(inst->core->iface, inst->id); |
256 | return 0; |
257 | } |
258 | |
259 | static inline int vpu_iface_send_cmd(struct vpu_core *core, struct vpu_rpc_event *cmd) |
260 | { |
261 | struct vpu_iface_ops *ops = vpu_core_get_iface(core); |
262 | |
263 | if (!ops || !ops->send_cmd_buf) |
264 | return -EINVAL; |
265 | |
266 | return ops->send_cmd_buf(core->iface, cmd); |
267 | } |
268 | |
269 | static inline int vpu_iface_receive_msg(struct vpu_core *core, struct vpu_rpc_event *msg) |
270 | { |
271 | struct vpu_iface_ops *ops = vpu_core_get_iface(core); |
272 | |
273 | if (!ops || !ops->receive_msg_buf) |
274 | return -EINVAL; |
275 | |
276 | return ops->receive_msg_buf(core->iface, msg); |
277 | } |
278 | |
279 | static inline int vpu_iface_pack_cmd(struct vpu_core *core, |
280 | struct vpu_rpc_event *pkt, |
281 | u32 index, u32 id, void *data) |
282 | { |
283 | struct vpu_iface_ops *ops = vpu_core_get_iface(core); |
284 | |
285 | if (!ops || !ops->pack_cmd) |
286 | return -EINVAL; |
287 | return ops->pack_cmd(pkt, index, id, data); |
288 | } |
289 | |
290 | static inline int vpu_iface_convert_msg_id(struct vpu_core *core, u32 msg_id) |
291 | { |
292 | struct vpu_iface_ops *ops = vpu_core_get_iface(core); |
293 | |
294 | if (!ops || !ops->convert_msg_id) |
295 | return -EINVAL; |
296 | |
297 | return ops->convert_msg_id(msg_id); |
298 | } |
299 | |
300 | static inline int vpu_iface_unpack_msg_data(struct vpu_core *core, |
301 | struct vpu_rpc_event *pkt, void *data) |
302 | { |
303 | struct vpu_iface_ops *ops = vpu_core_get_iface(core); |
304 | |
305 | if (!ops || !ops->unpack_msg_data) |
306 | return -EINVAL; |
307 | |
308 | return ops->unpack_msg_data(pkt, data); |
309 | } |
310 | |
311 | static inline int vpu_iface_input_frame(struct vpu_inst *inst, |
312 | struct vb2_buffer *vb) |
313 | { |
314 | struct vpu_iface_ops *ops = vpu_core_get_iface(core: inst->core); |
315 | int ret; |
316 | |
317 | if (!ops || !ops->input_frame) |
318 | return -EINVAL; |
319 | |
320 | ret = ops->input_frame(inst->core->iface, inst, vb); |
321 | if (ret < 0) |
322 | return ret; |
323 | inst->total_input_count++; |
324 | return ret; |
325 | } |
326 | |
327 | static inline int vpu_iface_config_memory_resource(struct vpu_inst *inst, |
328 | u32 type, |
329 | u32 index, |
330 | struct vpu_buffer *buf) |
331 | { |
332 | struct vpu_iface_ops *ops = vpu_core_get_iface(core: inst->core); |
333 | |
334 | if (!ops || !ops->config_memory_resource || inst->id < 0) |
335 | return -EINVAL; |
336 | |
337 | return ops->config_memory_resource(inst->core->iface, |
338 | inst->id, |
339 | type, index, buf); |
340 | } |
341 | |
342 | static inline int vpu_iface_config_stream_buffer(struct vpu_inst *inst, |
343 | struct vpu_buffer *buf) |
344 | { |
345 | struct vpu_iface_ops *ops = vpu_core_get_iface(core: inst->core); |
346 | |
347 | if (!ops || !ops->config_stream_buffer || inst->id < 0) |
348 | return -EINVAL; |
349 | |
350 | if ((buf->phys % 4) || (buf->length % 4)) |
351 | return -EINVAL; |
352 | if (buf->phys + buf->length > (u64)UINT_MAX) |
353 | return -EINVAL; |
354 | |
355 | return ops->config_stream_buffer(inst->core->iface, inst->id, buf); |
356 | } |
357 | |
358 | static inline int vpu_iface_update_stream_buffer(struct vpu_inst *inst, |
359 | u32 ptr, bool write) |
360 | { |
361 | struct vpu_iface_ops *ops = vpu_core_get_iface(core: inst->core); |
362 | |
363 | if (!ops || !ops->update_stream_buffer || inst->id < 0) |
364 | return -EINVAL; |
365 | |
366 | return ops->update_stream_buffer(inst->core->iface, inst->id, ptr, write); |
367 | } |
368 | |
369 | static inline int vpu_iface_get_stream_buffer_desc(struct vpu_inst *inst, |
370 | struct vpu_rpc_buffer_desc *desc) |
371 | { |
372 | struct vpu_iface_ops *ops = vpu_core_get_iface(core: inst->core); |
373 | |
374 | if (!ops || !ops->get_stream_buffer_desc || inst->id < 0) |
375 | return -EINVAL; |
376 | |
377 | if (!desc) |
378 | return 0; |
379 | |
380 | return ops->get_stream_buffer_desc(inst->core->iface, inst->id, desc); |
381 | } |
382 | |
383 | static inline u32 vpu_iface_get_version(struct vpu_core *core) |
384 | { |
385 | struct vpu_iface_ops *ops = vpu_core_get_iface(core); |
386 | |
387 | if (!ops || !ops->get_version) |
388 | return 0; |
389 | |
390 | return ops->get_version(core->iface); |
391 | } |
392 | |
393 | static inline u32 vpu_iface_get_max_instance_count(struct vpu_core *core) |
394 | { |
395 | struct vpu_iface_ops *ops = vpu_core_get_iface(core); |
396 | |
397 | if (!ops || !ops->get_max_instance_count) |
398 | return 0; |
399 | |
400 | return ops->get_max_instance_count(core->iface); |
401 | } |
402 | |
403 | static inline int vpu_iface_set_encode_params(struct vpu_inst *inst, |
404 | struct vpu_encode_params *params, u32 update) |
405 | { |
406 | struct vpu_iface_ops *ops = vpu_core_get_iface(core: inst->core); |
407 | |
408 | if (!ops || !ops->set_encode_params || inst->id < 0) |
409 | return -EINVAL; |
410 | |
411 | return ops->set_encode_params(inst->core->iface, inst->id, params, update); |
412 | } |
413 | |
414 | static inline int vpu_iface_set_decode_params(struct vpu_inst *inst, |
415 | struct vpu_decode_params *params, u32 update) |
416 | { |
417 | struct vpu_iface_ops *ops = vpu_core_get_iface(core: inst->core); |
418 | |
419 | if (!ops || !ops->set_decode_params || inst->id < 0) |
420 | return -EINVAL; |
421 | |
422 | return ops->set_decode_params(inst->core->iface, inst->id, params, update); |
423 | } |
424 | |
425 | static inline int vpu_iface_add_scode(struct vpu_inst *inst, u32 scode_type) |
426 | { |
427 | struct vpu_iface_ops *ops = vpu_core_get_iface(core: inst->core); |
428 | |
429 | if (!ops || !ops->add_scode || inst->id < 0) |
430 | return -EINVAL; |
431 | |
432 | return ops->add_scode(inst->core->iface, inst->id, |
433 | &inst->stream_buffer, |
434 | inst->out_format.pixfmt, |
435 | scode_type); |
436 | } |
437 | |
438 | static inline int vpu_iface_pre_send_cmd(struct vpu_inst *inst) |
439 | { |
440 | struct vpu_iface_ops *ops = vpu_core_get_iface(core: inst->core); |
441 | |
442 | if (ops && ops->pre_send_cmd && inst->id >= 0) |
443 | return ops->pre_send_cmd(inst->core->iface, inst->id); |
444 | return 0; |
445 | } |
446 | |
447 | static inline int vpu_iface_post_send_cmd(struct vpu_inst *inst) |
448 | { |
449 | struct vpu_iface_ops *ops = vpu_core_get_iface(core: inst->core); |
450 | |
451 | if (ops && ops->post_send_cmd && inst->id >= 0) |
452 | return ops->post_send_cmd(inst->core->iface, inst->id); |
453 | return 0; |
454 | } |
455 | |
456 | static inline int vpu_iface_init_instance(struct vpu_inst *inst) |
457 | { |
458 | struct vpu_iface_ops *ops = vpu_core_get_iface(core: inst->core); |
459 | |
460 | if (ops && ops->init_instance && inst->id >= 0) |
461 | return ops->init_instance(inst->core->iface, inst->id); |
462 | |
463 | return 0; |
464 | } |
465 | |
466 | #endif |
467 | |