1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
4 * Copyright (C) 2017 Linaro Ltd.
5 */
6 #include <linux/hash.h>
7 #include <linux/list.h>
8 #include <linux/slab.h>
9 #include <linux/soc/qcom/smem.h>
10 #include <media/videobuf2-v4l2.h>
11
12 #include "core.h"
13 #include "hfi.h"
14 #include "hfi_helper.h"
15 #include "hfi_msgs.h"
16 #include "hfi_parser.h"
17
18 #define SMEM_IMG_VER_TBL 469
19 #define VER_STR_SZ 128
20 #define SMEM_IMG_OFFSET_VENUS (14 * 128)
21
event_seq_changed(struct venus_core * core,struct venus_inst * inst,struct hfi_msg_event_notify_pkt * pkt)22 static void event_seq_changed(struct venus_core *core, struct venus_inst *inst,
23 struct hfi_msg_event_notify_pkt *pkt)
24 {
25 enum hfi_version ver = core->res->hfi_version;
26 struct hfi_event_data event = {0};
27 int num_properties_changed;
28 struct hfi_framesize *frame_sz;
29 struct hfi_profile_level *profile_level;
30 struct hfi_bit_depth *pixel_depth;
31 struct hfi_pic_struct *pic_struct;
32 struct hfi_colour_space *colour_info;
33 struct hfi_buffer_requirements *bufreq;
34 struct hfi_extradata_input_crop *crop;
35 struct hfi_dpb_counts *dpb_count;
36 u32 ptype, rem_bytes;
37 u32 size_read = 0;
38 u8 *data_ptr;
39
40 inst->error = HFI_ERR_NONE;
41
42 switch (pkt->event_data1) {
43 case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES:
44 case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES:
45 break;
46 default:
47 inst->error = HFI_ERR_SESSION_INVALID_PARAMETER;
48 inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event);
49 return;
50 }
51
52 event.event_type = pkt->event_data1;
53
54 num_properties_changed = pkt->event_data2;
55 if (!num_properties_changed)
56 goto error;
57
58 data_ptr = (u8 *)&pkt->ext_event_data[0];
59 rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt);
60
61 do {
62 if (rem_bytes < sizeof(u32))
63 goto error;
64 ptype = *((u32 *)data_ptr);
65
66 data_ptr += sizeof(u32);
67 rem_bytes -= sizeof(u32);
68
69 switch (ptype) {
70 case HFI_PROPERTY_PARAM_FRAME_SIZE:
71 if (rem_bytes < sizeof(struct hfi_framesize))
72 goto error;
73
74 frame_sz = (struct hfi_framesize *)data_ptr;
75 event.width = frame_sz->width;
76 event.height = frame_sz->height;
77 size_read = sizeof(struct hfi_framesize);
78 break;
79 case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
80 if (rem_bytes < sizeof(struct hfi_profile_level))
81 goto error;
82
83 profile_level = (struct hfi_profile_level *)data_ptr;
84 event.profile = profile_level->profile;
85 event.level = profile_level->level;
86 size_read = sizeof(struct hfi_profile_level);
87 break;
88 case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH:
89 if (rem_bytes < sizeof(struct hfi_bit_depth))
90 goto error;
91
92 pixel_depth = (struct hfi_bit_depth *)data_ptr;
93 event.bit_depth = pixel_depth->bit_depth;
94 size_read = sizeof(struct hfi_bit_depth);
95 break;
96 case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT:
97 if (rem_bytes < sizeof(struct hfi_pic_struct))
98 goto error;
99
100 pic_struct = (struct hfi_pic_struct *)data_ptr;
101 event.pic_struct = pic_struct->progressive_only;
102 size_read = sizeof(struct hfi_pic_struct);
103 break;
104 case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE:
105 if (rem_bytes < sizeof(struct hfi_colour_space))
106 goto error;
107
108 colour_info = (struct hfi_colour_space *)data_ptr;
109 event.colour_space = colour_info->colour_space;
110 size_read = sizeof(struct hfi_colour_space);
111 break;
112 case HFI_PROPERTY_CONFIG_VDEC_ENTROPY:
113 if (rem_bytes < sizeof(u32))
114 goto error;
115
116 event.entropy_mode = *(u32 *)data_ptr;
117 size_read = sizeof(u32);
118 break;
119 case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
120 if (rem_bytes < sizeof(struct hfi_buffer_requirements))
121 goto error;
122
123 bufreq = (struct hfi_buffer_requirements *)data_ptr;
124 event.buf_count = hfi_bufreq_get_count_min(bufreq, ver);
125 size_read = sizeof(struct hfi_buffer_requirements);
126 break;
127 case HFI_INDEX_EXTRADATA_INPUT_CROP:
128 if (rem_bytes < sizeof(struct hfi_extradata_input_crop))
129 goto error;
130
131 crop = (struct hfi_extradata_input_crop *)data_ptr;
132 event.input_crop.left = crop->left;
133 event.input_crop.top = crop->top;
134 event.input_crop.width = crop->width;
135 event.input_crop.height = crop->height;
136 size_read = sizeof(struct hfi_extradata_input_crop);
137 break;
138 case HFI_PROPERTY_PARAM_VDEC_DPB_COUNTS:
139 if (rem_bytes < sizeof(struct hfi_dpb_counts))
140 goto error;
141
142 dpb_count = (struct hfi_dpb_counts *)data_ptr;
143 event.buf_count = dpb_count->fw_min_cnt;
144 size_read = sizeof(struct hfi_dpb_counts);
145 break;
146 default:
147 size_read = 0;
148 break;
149 }
150 data_ptr += size_read;
151 rem_bytes -= size_read;
152 num_properties_changed--;
153 } while (num_properties_changed > 0);
154
155 inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event);
156 return;
157
158 error:
159 inst->error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES;
160 inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event);
161 }
162
event_release_buffer_ref(struct venus_core * core,struct venus_inst * inst,struct hfi_msg_event_notify_pkt * pkt)163 static void event_release_buffer_ref(struct venus_core *core,
164 struct venus_inst *inst,
165 struct hfi_msg_event_notify_pkt *pkt)
166 {
167 struct hfi_event_data event = {0};
168 struct hfi_msg_event_release_buffer_ref_pkt *data;
169
170 data = (struct hfi_msg_event_release_buffer_ref_pkt *)
171 pkt->ext_event_data;
172
173 event.event_type = HFI_EVENT_RELEASE_BUFFER_REFERENCE;
174 event.packet_buffer = data->packet_buffer;
175 event.extradata_buffer = data->extradata_buffer;
176 event.tag = data->output_tag;
177
178 inst->error = HFI_ERR_NONE;
179 inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event);
180 }
181
event_sys_error(struct venus_core * core,u32 event,struct hfi_msg_event_notify_pkt * pkt)182 static void event_sys_error(struct venus_core *core, u32 event,
183 struct hfi_msg_event_notify_pkt *pkt)
184 {
185 if (pkt)
186 dev_dbg(core->dev, VDBGH
187 "sys error (session id:%x, data1:%x, data2:%x)\n",
188 pkt->shdr.session_id, pkt->event_data1,
189 pkt->event_data2);
190
191 core->core_ops->event_notify(core, event);
192 }
193
194 static void
event_session_error(struct venus_core * core,struct venus_inst * inst,struct hfi_msg_event_notify_pkt * pkt)195 event_session_error(struct venus_core *core, struct venus_inst *inst,
196 struct hfi_msg_event_notify_pkt *pkt)
197 {
198 struct device *dev = core->dev;
199
200 dev_dbg(dev, VDBGH "session error: event id:%x, session id:%x\n",
201 pkt->event_data1, pkt->shdr.session_id);
202
203 if (!inst)
204 return;
205
206 switch (pkt->event_data1) {
207 /* non fatal session errors */
208 case HFI_ERR_SESSION_INVALID_SCALE_FACTOR:
209 case HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE:
210 case HFI_ERR_SESSION_UNSUPPORTED_SETTING:
211 case HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED:
212 inst->error = HFI_ERR_NONE;
213 break;
214 default:
215 dev_err(dev, "session error: event id:%x (%x), session id:%x\n",
216 pkt->event_data1, pkt->event_data2,
217 pkt->shdr.session_id);
218
219 inst->error = pkt->event_data1;
220 inst->ops->event_notify(inst, EVT_SESSION_ERROR, NULL);
221 break;
222 }
223 }
224
hfi_event_notify(struct venus_core * core,struct venus_inst * inst,void * packet)225 static void hfi_event_notify(struct venus_core *core, struct venus_inst *inst,
226 void *packet)
227 {
228 struct hfi_msg_event_notify_pkt *pkt = packet;
229
230 if (!packet)
231 return;
232
233 switch (pkt->event_id) {
234 case HFI_EVENT_SYS_ERROR:
235 event_sys_error(core, EVT_SYS_ERROR, pkt);
236 break;
237 case HFI_EVENT_SESSION_ERROR:
238 event_session_error(core, inst, pkt);
239 break;
240 case HFI_EVENT_SESSION_SEQUENCE_CHANGED:
241 event_seq_changed(core, inst, pkt);
242 break;
243 case HFI_EVENT_RELEASE_BUFFER_REFERENCE:
244 event_release_buffer_ref(core, inst, pkt);
245 break;
246 case HFI_EVENT_SESSION_PROPERTY_CHANGED:
247 break;
248 default:
249 break;
250 }
251 }
252
hfi_sys_init_done(struct venus_core * core,struct venus_inst * inst,void * packet)253 static void hfi_sys_init_done(struct venus_core *core, struct venus_inst *inst,
254 void *packet)
255 {
256 struct hfi_msg_sys_init_done_pkt *pkt = packet;
257 int rem_bytes;
258 u32 error;
259
260 error = pkt->error_type;
261 if (error != HFI_ERR_NONE)
262 goto done;
263
264 if (!pkt->num_properties) {
265 error = HFI_ERR_SYS_INVALID_PARAMETER;
266 goto done;
267 }
268
269 rem_bytes = pkt->hdr.size - sizeof(*pkt);
270 if (rem_bytes <= 0) {
271 /* missing property data */
272 error = HFI_ERR_SYS_INSUFFICIENT_RESOURCES;
273 goto done;
274 }
275
276 error = hfi_parser(core, inst, pkt->data, rem_bytes);
277
278 done:
279 core->error = error;
280 /*
281 * Since core_init could ask for the firmware version to be validated,
282 * completion might have to wait until the version is retrieved.
283 */
284 if (!core->res->min_fw)
285 complete(&core->done);
286 }
287
288 static void
sys_get_prop_image_version(struct venus_core * core,struct hfi_msg_sys_property_info_pkt * pkt)289 sys_get_prop_image_version(struct venus_core *core,
290 struct hfi_msg_sys_property_info_pkt *pkt)
291 {
292 struct device *dev = core->dev;
293 u8 *smem_tbl_ptr;
294 u8 *img_ver;
295 int req_bytes;
296 size_t smem_blk_sz;
297 int ret;
298
299 req_bytes = pkt->hdr.size - sizeof(*pkt);
300
301 if (req_bytes < VER_STR_SZ || !pkt->data[0] || pkt->num_properties > 1)
302 /* bad packet */
303 return;
304
305 img_ver = pkt->data;
306 if (!img_ver)
307 return;
308
309 ret = sscanf(img_ver, "14:video-firmware.%u.%u-%u",
310 &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev);
311 if (ret)
312 goto done;
313
314 ret = sscanf(img_ver, "14:VIDEO.VPU.%u.%u-%u",
315 &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev);
316 if (ret)
317 goto done;
318
319 ret = sscanf(img_ver, "14:VIDEO.VE.%u.%u-%u",
320 &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev);
321 if (ret)
322 goto done;
323
324 dev_err(dev, VDBGL "error reading F/W version\n");
325 return;
326
327 done:
328 dev_dbg(dev, VDBGL "F/W version: %s, major %u, minor %u, revision %u\n",
329 img_ver, core->venus_ver.major, core->venus_ver.minor, core->venus_ver.rev);
330
331 smem_tbl_ptr = qcom_smem_get(QCOM_SMEM_HOST_ANY,
332 SMEM_IMG_VER_TBL, &smem_blk_sz);
333 if (!IS_ERR(smem_tbl_ptr) && smem_blk_sz >= SMEM_IMG_OFFSET_VENUS + VER_STR_SZ)
334 memcpy(smem_tbl_ptr + SMEM_IMG_OFFSET_VENUS,
335 img_ver, VER_STR_SZ);
336
337 /* core_init could have had to wait for a version check */
338 if (core->res->min_fw)
339 complete(&core->done);
340 }
341
hfi_sys_property_info(struct venus_core * core,struct venus_inst * inst,void * packet)342 static void hfi_sys_property_info(struct venus_core *core,
343 struct venus_inst *inst, void *packet)
344 {
345 struct hfi_msg_sys_property_info_pkt *pkt = packet;
346 struct device *dev = core->dev;
347
348 if (!pkt->num_properties) {
349 dev_dbg(dev, VDBGL "no properties\n");
350 return;
351 }
352
353 switch (pkt->property) {
354 case HFI_PROPERTY_SYS_IMAGE_VERSION:
355 sys_get_prop_image_version(core, pkt);
356 break;
357 default:
358 dev_dbg(dev, VDBGL "unknown property data\n");
359 break;
360 }
361 }
362
hfi_sys_rel_resource_done(struct venus_core * core,struct venus_inst * inst,void * packet)363 static void hfi_sys_rel_resource_done(struct venus_core *core,
364 struct venus_inst *inst,
365 void *packet)
366 {
367 struct hfi_msg_sys_release_resource_done_pkt *pkt = packet;
368
369 core->error = pkt->error_type;
370 complete(&core->done);
371 }
372
hfi_sys_ping_done(struct venus_core * core,struct venus_inst * inst,void * packet)373 static void hfi_sys_ping_done(struct venus_core *core, struct venus_inst *inst,
374 void *packet)
375 {
376 struct hfi_msg_sys_ping_ack_pkt *pkt = packet;
377
378 core->error = HFI_ERR_NONE;
379
380 if (pkt->client_data != 0xbeef)
381 core->error = HFI_ERR_SYS_FATAL;
382
383 complete(&core->done);
384 }
385
hfi_sys_idle_done(struct venus_core * core,struct venus_inst * inst,void * packet)386 static void hfi_sys_idle_done(struct venus_core *core, struct venus_inst *inst,
387 void *packet)
388 {
389 dev_dbg(core->dev, VDBGL "sys idle\n");
390 }
391
hfi_sys_pc_prepare_done(struct venus_core * core,struct venus_inst * inst,void * packet)392 static void hfi_sys_pc_prepare_done(struct venus_core *core,
393 struct venus_inst *inst, void *packet)
394 {
395 struct hfi_msg_sys_pc_prep_done_pkt *pkt = packet;
396
397 dev_dbg(core->dev, VDBGL "pc prepare done (error %x)\n",
398 pkt->error_type);
399 }
400
401 static unsigned int
session_get_prop_profile_level(struct hfi_msg_session_property_info_pkt * pkt,struct hfi_profile_level * profile_level)402 session_get_prop_profile_level(struct hfi_msg_session_property_info_pkt *pkt,
403 struct hfi_profile_level *profile_level)
404 {
405 struct hfi_profile_level *hfi;
406 u32 req_bytes;
407
408 req_bytes = pkt->shdr.hdr.size - sizeof(*pkt);
409
410 if (!req_bytes || req_bytes % sizeof(struct hfi_profile_level))
411 /* bad packet */
412 return HFI_ERR_SESSION_INVALID_PARAMETER;
413
414 hfi = (struct hfi_profile_level *)&pkt->data[0];
415 profile_level->profile = hfi->profile;
416 profile_level->level = hfi->level;
417
418 return HFI_ERR_NONE;
419 }
420
421 static unsigned int
session_get_prop_buf_req(struct hfi_msg_session_property_info_pkt * pkt,struct hfi_buffer_requirements * bufreq)422 session_get_prop_buf_req(struct hfi_msg_session_property_info_pkt *pkt,
423 struct hfi_buffer_requirements *bufreq)
424 {
425 struct hfi_buffer_requirements *buf_req;
426 u32 req_bytes;
427 unsigned int idx = 0;
428
429 req_bytes = pkt->shdr.hdr.size - sizeof(*pkt);
430
431 if (!req_bytes || req_bytes % sizeof(*buf_req) || !pkt->data[0])
432 /* bad packet */
433 return HFI_ERR_SESSION_INVALID_PARAMETER;
434
435 buf_req = (struct hfi_buffer_requirements *)&pkt->data[0];
436 if (!buf_req)
437 return HFI_ERR_SESSION_INVALID_PARAMETER;
438
439 while (req_bytes) {
440 memcpy(&bufreq[idx], buf_req, sizeof(*bufreq));
441 idx++;
442
443 if (idx >= HFI_BUFFER_TYPE_MAX)
444 return HFI_ERR_SESSION_INVALID_PARAMETER;
445
446 req_bytes -= sizeof(struct hfi_buffer_requirements);
447 buf_req++;
448 }
449
450 return HFI_ERR_NONE;
451 }
452
hfi_session_prop_info(struct venus_core * core,struct venus_inst * inst,void * packet)453 static void hfi_session_prop_info(struct venus_core *core,
454 struct venus_inst *inst, void *packet)
455 {
456 struct hfi_msg_session_property_info_pkt *pkt = packet;
457 struct device *dev = core->dev;
458 union hfi_get_property *hprop = &inst->hprop;
459 unsigned int error = HFI_ERR_NONE;
460
461 if (!pkt->num_properties) {
462 error = HFI_ERR_SESSION_INVALID_PARAMETER;
463 dev_err(dev, "%s: no properties\n", __func__);
464 goto done;
465 }
466
467 switch (pkt->property) {
468 case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
469 memset(hprop->bufreq, 0, sizeof(hprop->bufreq));
470 error = session_get_prop_buf_req(pkt, hprop->bufreq);
471 break;
472 case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
473 memset(&hprop->profile_level, 0, sizeof(hprop->profile_level));
474 error = session_get_prop_profile_level(pkt,
475 &hprop->profile_level);
476 break;
477 case HFI_PROPERTY_CONFIG_VDEC_ENTROPY:
478 break;
479 default:
480 dev_dbg(dev, VDBGM "unknown property id:%x\n", pkt->property);
481 return;
482 }
483
484 done:
485 inst->error = error;
486 complete(&inst->done);
487 }
488
hfi_session_init_done(struct venus_core * core,struct venus_inst * inst,void * packet)489 static void hfi_session_init_done(struct venus_core *core,
490 struct venus_inst *inst, void *packet)
491 {
492 struct hfi_msg_session_init_done_pkt *pkt = packet;
493 int rem_bytes;
494 u32 error;
495
496 error = pkt->error_type;
497 if (error != HFI_ERR_NONE)
498 goto done;
499
500 if (!IS_V1(core))
501 goto done;
502
503 rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt);
504 if (rem_bytes <= 0) {
505 error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES;
506 goto done;
507 }
508
509 error = hfi_parser(core, inst, pkt->data, rem_bytes);
510 done:
511 inst->error = error;
512 complete(&inst->done);
513 }
514
hfi_session_load_res_done(struct venus_core * core,struct venus_inst * inst,void * packet)515 static void hfi_session_load_res_done(struct venus_core *core,
516 struct venus_inst *inst, void *packet)
517 {
518 struct hfi_msg_session_load_resources_done_pkt *pkt = packet;
519
520 inst->error = pkt->error_type;
521 complete(&inst->done);
522 }
523
hfi_session_flush_done(struct venus_core * core,struct venus_inst * inst,void * packet)524 static void hfi_session_flush_done(struct venus_core *core,
525 struct venus_inst *inst, void *packet)
526 {
527 struct hfi_msg_session_flush_done_pkt *pkt = packet;
528
529 inst->error = pkt->error_type;
530 complete(&inst->done);
531 if (inst->ops->flush_done)
532 inst->ops->flush_done(inst);
533 }
534
hfi_session_etb_done(struct venus_core * core,struct venus_inst * inst,void * packet)535 static void hfi_session_etb_done(struct venus_core *core,
536 struct venus_inst *inst, void *packet)
537 {
538 struct hfi_msg_session_empty_buffer_done_pkt *pkt = packet;
539
540 inst->error = pkt->error_type;
541 inst->ops->buf_done(inst, HFI_BUFFER_INPUT, pkt->input_tag,
542 pkt->filled_len, pkt->offset, 0, 0, 0);
543 }
544
hfi_session_ftb_done(struct venus_core * core,struct venus_inst * inst,void * packet)545 static void hfi_session_ftb_done(struct venus_core *core,
546 struct venus_inst *inst, void *packet)
547 {
548 u32 session_type = inst->session_type;
549 u64 timestamp_us = 0;
550 u32 timestamp_hi = 0, timestamp_lo = 0;
551 unsigned int error;
552 u32 flags = 0, hfi_flags = 0, offset = 0, filled_len = 0;
553 u32 pic_type = 0, buffer_type = 0, output_tag = -1;
554
555 if (session_type == VIDC_SESSION_TYPE_ENC) {
556 struct hfi_msg_session_fbd_compressed_pkt *pkt = packet;
557
558 timestamp_hi = pkt->time_stamp_hi;
559 timestamp_lo = pkt->time_stamp_lo;
560 hfi_flags = pkt->flags;
561 offset = pkt->offset;
562 filled_len = pkt->filled_len;
563 pic_type = pkt->picture_type;
564 output_tag = pkt->output_tag;
565 buffer_type = HFI_BUFFER_OUTPUT;
566
567 error = pkt->error_type;
568 } else if (session_type == VIDC_SESSION_TYPE_DEC) {
569 struct hfi_msg_session_fbd_uncompressed_plane0_pkt *pkt =
570 packet;
571
572 timestamp_hi = pkt->time_stamp_hi;
573 timestamp_lo = pkt->time_stamp_lo;
574 hfi_flags = pkt->flags;
575 offset = pkt->offset;
576 filled_len = pkt->filled_len;
577 pic_type = pkt->picture_type;
578 output_tag = pkt->output_tag;
579
580 if (pkt->stream_id == 0)
581 buffer_type = HFI_BUFFER_OUTPUT;
582 else if (pkt->stream_id == 1)
583 buffer_type = HFI_BUFFER_OUTPUT2;
584
585 error = pkt->error_type;
586 } else {
587 error = HFI_ERR_SESSION_INVALID_PARAMETER;
588 }
589
590 if (buffer_type != HFI_BUFFER_OUTPUT &&
591 buffer_type != HFI_BUFFER_OUTPUT2)
592 goto done;
593
594 if (hfi_flags & HFI_BUFFERFLAG_EOS)
595 flags |= V4L2_BUF_FLAG_LAST;
596
597 switch (pic_type) {
598 case HFI_PICTURE_IDR:
599 case HFI_PICTURE_I:
600 flags |= V4L2_BUF_FLAG_KEYFRAME;
601 break;
602 case HFI_PICTURE_P:
603 flags |= V4L2_BUF_FLAG_PFRAME;
604 break;
605 case HFI_PICTURE_B:
606 flags |= V4L2_BUF_FLAG_BFRAME;
607 break;
608 case HFI_FRAME_NOTCODED:
609 case HFI_UNUSED_PICT:
610 case HFI_FRAME_YUV:
611 default:
612 break;
613 }
614
615 if (!(hfi_flags & HFI_BUFFERFLAG_TIMESTAMPINVALID) && filled_len) {
616 timestamp_us = timestamp_hi;
617 timestamp_us = (timestamp_us << 32) | timestamp_lo;
618 }
619
620 done:
621 inst->error = error;
622 inst->ops->buf_done(inst, buffer_type, output_tag, filled_len,
623 offset, flags, hfi_flags, timestamp_us);
624 }
625
hfi_session_start_done(struct venus_core * core,struct venus_inst * inst,void * packet)626 static void hfi_session_start_done(struct venus_core *core,
627 struct venus_inst *inst, void *packet)
628 {
629 struct hfi_msg_session_start_done_pkt *pkt = packet;
630
631 inst->error = pkt->error_type;
632 complete(&inst->done);
633 }
634
hfi_session_stop_done(struct venus_core * core,struct venus_inst * inst,void * packet)635 static void hfi_session_stop_done(struct venus_core *core,
636 struct venus_inst *inst, void *packet)
637 {
638 struct hfi_msg_session_stop_done_pkt *pkt = packet;
639
640 inst->error = pkt->error_type;
641 complete(&inst->done);
642 }
643
hfi_session_rel_res_done(struct venus_core * core,struct venus_inst * inst,void * packet)644 static void hfi_session_rel_res_done(struct venus_core *core,
645 struct venus_inst *inst, void *packet)
646 {
647 struct hfi_msg_session_release_resources_done_pkt *pkt = packet;
648
649 inst->error = pkt->error_type;
650 complete(&inst->done);
651 }
652
hfi_session_rel_buf_done(struct venus_core * core,struct venus_inst * inst,void * packet)653 static void hfi_session_rel_buf_done(struct venus_core *core,
654 struct venus_inst *inst, void *packet)
655 {
656 struct hfi_msg_session_release_buffers_done_pkt *pkt = packet;
657
658 inst->error = pkt->error_type;
659 complete(&inst->done);
660 }
661
hfi_session_end_done(struct venus_core * core,struct venus_inst * inst,void * packet)662 static void hfi_session_end_done(struct venus_core *core,
663 struct venus_inst *inst, void *packet)
664 {
665 struct hfi_msg_session_end_done_pkt *pkt = packet;
666
667 inst->error = pkt->error_type;
668 complete(&inst->done);
669 }
670
hfi_session_abort_done(struct venus_core * core,struct venus_inst * inst,void * packet)671 static void hfi_session_abort_done(struct venus_core *core,
672 struct venus_inst *inst, void *packet)
673 {
674 struct hfi_msg_sys_session_abort_done_pkt *pkt = packet;
675
676 inst->error = pkt->error_type;
677 complete(&inst->done);
678 }
679
hfi_session_get_seq_hdr_done(struct venus_core * core,struct venus_inst * inst,void * packet)680 static void hfi_session_get_seq_hdr_done(struct venus_core *core,
681 struct venus_inst *inst, void *packet)
682 {
683 struct hfi_msg_session_get_sequence_hdr_done_pkt *pkt = packet;
684
685 inst->error = pkt->error_type;
686 complete(&inst->done);
687 }
688
689 struct hfi_done_handler {
690 u32 pkt;
691 u32 pkt_sz;
692 u32 pkt_sz2;
693 void (*done)(struct venus_core *, struct venus_inst *, void *);
694 bool is_sys_pkt;
695 };
696
697 static const struct hfi_done_handler handlers[] = {
698 {.pkt = HFI_MSG_EVENT_NOTIFY,
699 .pkt_sz = sizeof(struct hfi_msg_event_notify_pkt),
700 .done = hfi_event_notify,
701 },
702 {.pkt = HFI_MSG_SYS_INIT,
703 .pkt_sz = sizeof(struct hfi_msg_sys_init_done_pkt),
704 .done = hfi_sys_init_done,
705 .is_sys_pkt = true,
706 },
707 {.pkt = HFI_MSG_SYS_PROPERTY_INFO,
708 .pkt_sz = sizeof(struct hfi_msg_sys_property_info_pkt),
709 .done = hfi_sys_property_info,
710 .is_sys_pkt = true,
711 },
712 {.pkt = HFI_MSG_SYS_RELEASE_RESOURCE,
713 .pkt_sz = sizeof(struct hfi_msg_sys_release_resource_done_pkt),
714 .done = hfi_sys_rel_resource_done,
715 .is_sys_pkt = true,
716 },
717 {.pkt = HFI_MSG_SYS_PING_ACK,
718 .pkt_sz = sizeof(struct hfi_msg_sys_ping_ack_pkt),
719 .done = hfi_sys_ping_done,
720 .is_sys_pkt = true,
721 },
722 {.pkt = HFI_MSG_SYS_IDLE,
723 .pkt_sz = sizeof(struct hfi_msg_sys_idle_pkt),
724 .done = hfi_sys_idle_done,
725 .is_sys_pkt = true,
726 },
727 {.pkt = HFI_MSG_SYS_PC_PREP,
728 .pkt_sz = sizeof(struct hfi_msg_sys_pc_prep_done_pkt),
729 .done = hfi_sys_pc_prepare_done,
730 .is_sys_pkt = true,
731 },
732 {.pkt = HFI_MSG_SYS_SESSION_INIT,
733 .pkt_sz = sizeof(struct hfi_msg_session_init_done_pkt),
734 .done = hfi_session_init_done,
735 },
736 {.pkt = HFI_MSG_SYS_SESSION_END,
737 .pkt_sz = sizeof(struct hfi_msg_session_end_done_pkt),
738 .done = hfi_session_end_done,
739 },
740 {.pkt = HFI_MSG_SESSION_LOAD_RESOURCES,
741 .pkt_sz = sizeof(struct hfi_msg_session_load_resources_done_pkt),
742 .done = hfi_session_load_res_done,
743 },
744 {.pkt = HFI_MSG_SESSION_START,
745 .pkt_sz = sizeof(struct hfi_msg_session_start_done_pkt),
746 .done = hfi_session_start_done,
747 },
748 {.pkt = HFI_MSG_SESSION_STOP,
749 .pkt_sz = sizeof(struct hfi_msg_session_stop_done_pkt),
750 .done = hfi_session_stop_done,
751 },
752 {.pkt = HFI_MSG_SYS_SESSION_ABORT,
753 .pkt_sz = sizeof(struct hfi_msg_sys_session_abort_done_pkt),
754 .done = hfi_session_abort_done,
755 },
756 {.pkt = HFI_MSG_SESSION_EMPTY_BUFFER,
757 .pkt_sz = sizeof(struct hfi_msg_session_empty_buffer_done_pkt),
758 .done = hfi_session_etb_done,
759 },
760 {.pkt = HFI_MSG_SESSION_FILL_BUFFER,
761 .pkt_sz = sizeof(struct hfi_msg_session_fbd_uncompressed_plane0_pkt),
762 .pkt_sz2 = sizeof(struct hfi_msg_session_fbd_compressed_pkt),
763 .done = hfi_session_ftb_done,
764 },
765 {.pkt = HFI_MSG_SESSION_FLUSH,
766 .pkt_sz = sizeof(struct hfi_msg_session_flush_done_pkt),
767 .done = hfi_session_flush_done,
768 },
769 {.pkt = HFI_MSG_SESSION_PROPERTY_INFO,
770 .pkt_sz = sizeof(struct hfi_msg_session_property_info_pkt),
771 .done = hfi_session_prop_info,
772 },
773 {.pkt = HFI_MSG_SESSION_RELEASE_RESOURCES,
774 .pkt_sz = sizeof(struct hfi_msg_session_release_resources_done_pkt),
775 .done = hfi_session_rel_res_done,
776 },
777 {.pkt = HFI_MSG_SESSION_GET_SEQUENCE_HEADER,
778 .pkt_sz = sizeof(struct hfi_msg_session_get_sequence_hdr_done_pkt),
779 .done = hfi_session_get_seq_hdr_done,
780 },
781 {.pkt = HFI_MSG_SESSION_RELEASE_BUFFERS,
782 .pkt_sz = sizeof(struct hfi_msg_session_release_buffers_done_pkt),
783 .done = hfi_session_rel_buf_done,
784 },
785 };
786
hfi_process_watchdog_timeout(struct venus_core * core)787 void hfi_process_watchdog_timeout(struct venus_core *core)
788 {
789 event_sys_error(core, EVT_SYS_WATCHDOG_TIMEOUT, NULL);
790 }
791
to_instance(struct venus_core * core,u32 session_id)792 static struct venus_inst *to_instance(struct venus_core *core, u32 session_id)
793 {
794 struct venus_inst *inst;
795
796 mutex_lock(&core->lock);
797 list_for_each_entry(inst, &core->instances, list)
798 if (hash32_ptr(inst) == session_id) {
799 mutex_unlock(&core->lock);
800 return inst;
801 }
802 mutex_unlock(&core->lock);
803
804 return NULL;
805 }
806
hfi_process_msg_packet(struct venus_core * core,struct hfi_pkt_hdr * hdr)807 u32 hfi_process_msg_packet(struct venus_core *core, struct hfi_pkt_hdr *hdr)
808 {
809 const struct hfi_done_handler *handler;
810 struct device *dev = core->dev;
811 struct venus_inst *inst;
812 bool found = false;
813 unsigned int i;
814
815 for (i = 0; i < ARRAY_SIZE(handlers); i++) {
816 handler = &handlers[i];
817 if (handler->pkt != hdr->pkt_type)
818 continue;
819 found = true;
820 break;
821 }
822
823 if (!found)
824 return hdr->pkt_type;
825
826 if (hdr->size && hdr->size < handler->pkt_sz &&
827 hdr->size < handler->pkt_sz2) {
828 dev_err(dev, "bad packet size (%d should be %d, pkt type:%x)\n",
829 hdr->size, handler->pkt_sz, hdr->pkt_type);
830
831 return hdr->pkt_type;
832 }
833
834 if (handler->is_sys_pkt) {
835 inst = NULL;
836 } else {
837 struct hfi_session_pkt *pkt;
838
839 pkt = (struct hfi_session_pkt *)hdr;
840 inst = to_instance(core, pkt->shdr.session_id);
841
842 if (!inst)
843 dev_warn(dev, "no valid instance(pkt session_id:%x, pkt:%x)\n",
844 pkt->shdr.session_id,
845 handler ? handler->pkt : 0);
846
847 /*
848 * Event of type HFI_EVENT_SYS_ERROR will not have any session
849 * associated with it
850 */
851 if (!inst && hdr->pkt_type != HFI_MSG_EVENT_NOTIFY) {
852 dev_err(dev, "got invalid session id:%x\n",
853 pkt->shdr.session_id);
854 goto invalid_session;
855 }
856 }
857
858 handler->done(core, inst, hdr);
859
860 invalid_session:
861 return hdr->pkt_type;
862 }
863