]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/media/platform/qcom/venus/hfi_msgs.c
Merge tag 'for-linus-20170825' of git://git.infradead.org/linux-mtd
[mirror_ubuntu-artful-kernel.git] / drivers / media / platform / qcom / venus / hfi_msgs.c
1 /*
2 * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
3 * Copyright (C) 2017 Linaro Ltd.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 and
7 * only version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15 #include <linux/hash.h>
16 #include <linux/list.h>
17 #include <linux/slab.h>
18 #include <media/videobuf2-v4l2.h>
19
20 #include "core.h"
21 #include "hfi.h"
22 #include "hfi_helper.h"
23 #include "hfi_msgs.h"
24
25 static void event_seq_changed(struct venus_core *core, struct venus_inst *inst,
26 struct hfi_msg_event_notify_pkt *pkt)
27 {
28 struct hfi_event_data event = {0};
29 int num_properties_changed;
30 struct hfi_framesize *frame_sz;
31 struct hfi_profile_level *profile_level;
32 u8 *data_ptr;
33 u32 ptype;
34
35 inst->error = HFI_ERR_NONE;
36
37 switch (pkt->event_data1) {
38 case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES:
39 case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES:
40 break;
41 default:
42 inst->error = HFI_ERR_SESSION_INVALID_PARAMETER;
43 goto done;
44 }
45
46 event.event_type = pkt->event_data1;
47
48 num_properties_changed = pkt->event_data2;
49 if (!num_properties_changed) {
50 inst->error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES;
51 goto done;
52 }
53
54 data_ptr = (u8 *)&pkt->ext_event_data[0];
55 do {
56 ptype = *((u32 *)data_ptr);
57 switch (ptype) {
58 case HFI_PROPERTY_PARAM_FRAME_SIZE:
59 data_ptr += sizeof(u32);
60 frame_sz = (struct hfi_framesize *)data_ptr;
61 event.width = frame_sz->width;
62 event.height = frame_sz->height;
63 data_ptr += sizeof(frame_sz);
64 break;
65 case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
66 data_ptr += sizeof(u32);
67 profile_level = (struct hfi_profile_level *)data_ptr;
68 event.profile = profile_level->profile;
69 event.level = profile_level->level;
70 data_ptr += sizeof(profile_level);
71 break;
72 default:
73 break;
74 }
75 num_properties_changed--;
76 } while (num_properties_changed > 0);
77
78 done:
79 inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event);
80 }
81
82 static void event_release_buffer_ref(struct venus_core *core,
83 struct venus_inst *inst,
84 struct hfi_msg_event_notify_pkt *pkt)
85 {
86 struct hfi_event_data event = {0};
87 struct hfi_msg_event_release_buffer_ref_pkt *data;
88
89 data = (struct hfi_msg_event_release_buffer_ref_pkt *)
90 pkt->ext_event_data;
91
92 event.event_type = HFI_EVENT_RELEASE_BUFFER_REFERENCE;
93 event.packet_buffer = data->packet_buffer;
94 event.extradata_buffer = data->extradata_buffer;
95 event.tag = data->output_tag;
96
97 inst->error = HFI_ERR_NONE;
98 inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event);
99 }
100
101 static void event_sys_error(struct venus_core *core, u32 event,
102 struct hfi_msg_event_notify_pkt *pkt)
103 {
104 if (pkt)
105 dev_dbg(core->dev,
106 "sys error (session id:%x, data1:%x, data2:%x)\n",
107 pkt->shdr.session_id, pkt->event_data1,
108 pkt->event_data2);
109
110 core->core_ops->event_notify(core, event);
111 }
112
113 static void
114 event_session_error(struct venus_core *core, struct venus_inst *inst,
115 struct hfi_msg_event_notify_pkt *pkt)
116 {
117 struct device *dev = core->dev;
118
119 dev_dbg(dev, "session error: event id:%x, session id:%x\n",
120 pkt->event_data1, pkt->shdr.session_id);
121
122 if (!inst)
123 return;
124
125 switch (pkt->event_data1) {
126 /* non fatal session errors */
127 case HFI_ERR_SESSION_INVALID_SCALE_FACTOR:
128 case HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE:
129 case HFI_ERR_SESSION_UNSUPPORTED_SETTING:
130 case HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED:
131 inst->error = HFI_ERR_NONE;
132 break;
133 default:
134 dev_err(dev, "session error: event id:%x (%x), session id:%x\n",
135 pkt->event_data1, pkt->event_data2,
136 pkt->shdr.session_id);
137
138 inst->error = pkt->event_data1;
139 inst->ops->event_notify(inst, EVT_SESSION_ERROR, NULL);
140 break;
141 }
142 }
143
144 static void hfi_event_notify(struct venus_core *core, struct venus_inst *inst,
145 void *packet)
146 {
147 struct hfi_msg_event_notify_pkt *pkt = packet;
148
149 if (!packet)
150 return;
151
152 switch (pkt->event_id) {
153 case HFI_EVENT_SYS_ERROR:
154 event_sys_error(core, EVT_SYS_ERROR, pkt);
155 break;
156 case HFI_EVENT_SESSION_ERROR:
157 event_session_error(core, inst, pkt);
158 break;
159 case HFI_EVENT_SESSION_SEQUENCE_CHANGED:
160 event_seq_changed(core, inst, pkt);
161 break;
162 case HFI_EVENT_RELEASE_BUFFER_REFERENCE:
163 event_release_buffer_ref(core, inst, pkt);
164 break;
165 case HFI_EVENT_SESSION_PROPERTY_CHANGED:
166 break;
167 default:
168 break;
169 }
170 }
171
172 static void hfi_sys_init_done(struct venus_core *core, struct venus_inst *inst,
173 void *packet)
174 {
175 struct hfi_msg_sys_init_done_pkt *pkt = packet;
176 u32 rem_bytes, read_bytes = 0, num_properties;
177 u32 error, ptype;
178 u8 *data;
179
180 error = pkt->error_type;
181 if (error != HFI_ERR_NONE)
182 goto err_no_prop;
183
184 num_properties = pkt->num_properties;
185
186 if (!num_properties) {
187 error = HFI_ERR_SYS_INVALID_PARAMETER;
188 goto err_no_prop;
189 }
190
191 rem_bytes = pkt->hdr.size - sizeof(*pkt) + sizeof(u32);
192
193 if (!rem_bytes) {
194 /* missing property data */
195 error = HFI_ERR_SYS_INSUFFICIENT_RESOURCES;
196 goto err_no_prop;
197 }
198
199 data = (u8 *)&pkt->data[0];
200
201 if (core->res->hfi_version == HFI_VERSION_3XX)
202 goto err_no_prop;
203
204 while (num_properties && rem_bytes >= sizeof(u32)) {
205 ptype = *((u32 *)data);
206 data += sizeof(u32);
207
208 switch (ptype) {
209 case HFI_PROPERTY_PARAM_CODEC_SUPPORTED: {
210 struct hfi_codec_supported *prop;
211
212 prop = (struct hfi_codec_supported *)data;
213
214 if (rem_bytes < sizeof(*prop)) {
215 error = HFI_ERR_SYS_INSUFFICIENT_RESOURCES;
216 break;
217 }
218
219 read_bytes += sizeof(*prop) + sizeof(u32);
220 core->dec_codecs = prop->dec_codecs;
221 core->enc_codecs = prop->enc_codecs;
222 break;
223 }
224 case HFI_PROPERTY_PARAM_MAX_SESSIONS_SUPPORTED: {
225 struct hfi_max_sessions_supported *prop;
226
227 if (rem_bytes < sizeof(*prop)) {
228 error = HFI_ERR_SYS_INSUFFICIENT_RESOURCES;
229 break;
230 }
231
232 prop = (struct hfi_max_sessions_supported *)data;
233 read_bytes += sizeof(*prop) + sizeof(u32);
234 core->max_sessions_supported = prop->max_sessions;
235 break;
236 }
237 default:
238 error = HFI_ERR_SYS_INVALID_PARAMETER;
239 break;
240 }
241
242 if (error)
243 break;
244
245 rem_bytes -= read_bytes;
246 data += read_bytes;
247 num_properties--;
248 }
249
250 err_no_prop:
251 core->error = error;
252 complete(&core->done);
253 }
254
255 static void
256 sys_get_prop_image_version(struct device *dev,
257 struct hfi_msg_sys_property_info_pkt *pkt)
258 {
259 int req_bytes;
260
261 req_bytes = pkt->hdr.size - sizeof(*pkt);
262
263 if (req_bytes < 128 || !pkt->data[1] || pkt->num_properties > 1)
264 /* bad packet */
265 return;
266
267 dev_dbg(dev, "F/W version: %s\n", (u8 *)&pkt->data[1]);
268 }
269
270 static void hfi_sys_property_info(struct venus_core *core,
271 struct venus_inst *inst, void *packet)
272 {
273 struct hfi_msg_sys_property_info_pkt *pkt = packet;
274 struct device *dev = core->dev;
275
276 if (!pkt->num_properties) {
277 dev_dbg(dev, "%s: no properties\n", __func__);
278 return;
279 }
280
281 switch (pkt->data[0]) {
282 case HFI_PROPERTY_SYS_IMAGE_VERSION:
283 sys_get_prop_image_version(dev, pkt);
284 break;
285 default:
286 dev_dbg(dev, "%s: unknown property data\n", __func__);
287 break;
288 }
289 }
290
291 static void hfi_sys_rel_resource_done(struct venus_core *core,
292 struct venus_inst *inst,
293 void *packet)
294 {
295 struct hfi_msg_sys_release_resource_done_pkt *pkt = packet;
296
297 core->error = pkt->error_type;
298 complete(&core->done);
299 }
300
301 static void hfi_sys_ping_done(struct venus_core *core, struct venus_inst *inst,
302 void *packet)
303 {
304 struct hfi_msg_sys_ping_ack_pkt *pkt = packet;
305
306 core->error = HFI_ERR_NONE;
307
308 if (pkt->client_data != 0xbeef)
309 core->error = HFI_ERR_SYS_FATAL;
310
311 complete(&core->done);
312 }
313
314 static void hfi_sys_idle_done(struct venus_core *core, struct venus_inst *inst,
315 void *packet)
316 {
317 dev_dbg(core->dev, "sys idle\n");
318 }
319
320 static void hfi_sys_pc_prepare_done(struct venus_core *core,
321 struct venus_inst *inst, void *packet)
322 {
323 struct hfi_msg_sys_pc_prep_done_pkt *pkt = packet;
324
325 dev_dbg(core->dev, "pc prepare done (error %x)\n", pkt->error_type);
326 }
327
328 static void
329 hfi_copy_cap_prop(struct hfi_capability *in, struct venus_inst *inst)
330 {
331 if (!in || !inst)
332 return;
333
334 switch (in->capability_type) {
335 case HFI_CAPABILITY_FRAME_WIDTH:
336 inst->cap_width = *in;
337 break;
338 case HFI_CAPABILITY_FRAME_HEIGHT:
339 inst->cap_height = *in;
340 break;
341 case HFI_CAPABILITY_MBS_PER_FRAME:
342 inst->cap_mbs_per_frame = *in;
343 break;
344 case HFI_CAPABILITY_MBS_PER_SECOND:
345 inst->cap_mbs_per_sec = *in;
346 break;
347 case HFI_CAPABILITY_FRAMERATE:
348 inst->cap_framerate = *in;
349 break;
350 case HFI_CAPABILITY_SCALE_X:
351 inst->cap_scale_x = *in;
352 break;
353 case HFI_CAPABILITY_SCALE_Y:
354 inst->cap_scale_y = *in;
355 break;
356 case HFI_CAPABILITY_BITRATE:
357 inst->cap_bitrate = *in;
358 break;
359 case HFI_CAPABILITY_HIER_P_NUM_ENH_LAYERS:
360 inst->cap_hier_p = *in;
361 break;
362 case HFI_CAPABILITY_ENC_LTR_COUNT:
363 inst->cap_ltr_count = *in;
364 break;
365 case HFI_CAPABILITY_CP_OUTPUT2_THRESH:
366 inst->cap_secure_output2_threshold = *in;
367 break;
368 default:
369 break;
370 }
371 }
372
373 static unsigned int
374 session_get_prop_profile_level(struct hfi_msg_session_property_info_pkt *pkt,
375 struct hfi_profile_level *profile_level)
376 {
377 struct hfi_profile_level *hfi;
378 u32 req_bytes;
379
380 req_bytes = pkt->shdr.hdr.size - sizeof(*pkt);
381
382 if (!req_bytes || req_bytes % sizeof(struct hfi_profile_level))
383 /* bad packet */
384 return HFI_ERR_SESSION_INVALID_PARAMETER;
385
386 hfi = (struct hfi_profile_level *)&pkt->data[1];
387 profile_level->profile = hfi->profile;
388 profile_level->level = hfi->level;
389
390 return HFI_ERR_NONE;
391 }
392
393 static unsigned int
394 session_get_prop_buf_req(struct hfi_msg_session_property_info_pkt *pkt,
395 struct hfi_buffer_requirements *bufreq)
396 {
397 struct hfi_buffer_requirements *buf_req;
398 u32 req_bytes;
399 unsigned int idx = 0;
400
401 req_bytes = pkt->shdr.hdr.size - sizeof(*pkt);
402
403 if (!req_bytes || req_bytes % sizeof(*buf_req) || !pkt->data[1])
404 /* bad packet */
405 return HFI_ERR_SESSION_INVALID_PARAMETER;
406
407 buf_req = (struct hfi_buffer_requirements *)&pkt->data[1];
408 if (!buf_req)
409 return HFI_ERR_SESSION_INVALID_PARAMETER;
410
411 while (req_bytes) {
412 memcpy(&bufreq[idx], buf_req, sizeof(*bufreq));
413 idx++;
414
415 if (idx > HFI_BUFFER_TYPE_MAX)
416 return HFI_ERR_SESSION_INVALID_PARAMETER;
417
418 req_bytes -= sizeof(struct hfi_buffer_requirements);
419 buf_req++;
420 }
421
422 return HFI_ERR_NONE;
423 }
424
425 static void hfi_session_prop_info(struct venus_core *core,
426 struct venus_inst *inst, void *packet)
427 {
428 struct hfi_msg_session_property_info_pkt *pkt = packet;
429 struct device *dev = core->dev;
430 union hfi_get_property *hprop = &inst->hprop;
431 unsigned int error = HFI_ERR_NONE;
432
433 if (!pkt->num_properties) {
434 error = HFI_ERR_SESSION_INVALID_PARAMETER;
435 dev_err(dev, "%s: no properties\n", __func__);
436 goto done;
437 }
438
439 switch (pkt->data[0]) {
440 case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
441 memset(hprop->bufreq, 0, sizeof(hprop->bufreq));
442 error = session_get_prop_buf_req(pkt, hprop->bufreq);
443 break;
444 case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
445 memset(&hprop->profile_level, 0, sizeof(hprop->profile_level));
446 error = session_get_prop_profile_level(pkt,
447 &hprop->profile_level);
448 break;
449 case HFI_PROPERTY_CONFIG_VDEC_ENTROPY:
450 break;
451 default:
452 dev_dbg(dev, "%s: unknown property id:%x\n", __func__,
453 pkt->data[0]);
454 return;
455 }
456
457 done:
458 inst->error = error;
459 complete(&inst->done);
460 }
461
462 static u32 init_done_read_prop(struct venus_core *core, struct venus_inst *inst,
463 struct hfi_msg_session_init_done_pkt *pkt)
464 {
465 struct device *dev = core->dev;
466 u32 rem_bytes, num_props;
467 u32 ptype, next_offset = 0;
468 u32 err;
469 u8 *data;
470
471 rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt) + sizeof(u32);
472 if (!rem_bytes) {
473 dev_err(dev, "%s: missing property info\n", __func__);
474 return HFI_ERR_SESSION_INSUFFICIENT_RESOURCES;
475 }
476
477 err = pkt->error_type;
478 if (err)
479 return err;
480
481 data = (u8 *)&pkt->data[0];
482 num_props = pkt->num_properties;
483
484 while (err == HFI_ERR_NONE && num_props && rem_bytes >= sizeof(u32)) {
485 ptype = *((u32 *)data);
486 next_offset = sizeof(u32);
487
488 switch (ptype) {
489 case HFI_PROPERTY_PARAM_CODEC_MASK_SUPPORTED: {
490 struct hfi_codec_mask_supported *masks =
491 (struct hfi_codec_mask_supported *)
492 (data + next_offset);
493
494 next_offset += sizeof(*masks);
495 num_props--;
496 break;
497 }
498 case HFI_PROPERTY_PARAM_CAPABILITY_SUPPORTED: {
499 struct hfi_capabilities *caps;
500 struct hfi_capability *cap;
501 u32 num_caps;
502
503 if ((rem_bytes - next_offset) < sizeof(*cap)) {
504 err = HFI_ERR_SESSION_INVALID_PARAMETER;
505 break;
506 }
507
508 caps = (struct hfi_capabilities *)(data + next_offset);
509
510 num_caps = caps->num_capabilities;
511 cap = &caps->data[0];
512 next_offset += sizeof(u32);
513
514 while (num_caps &&
515 (rem_bytes - next_offset) >= sizeof(u32)) {
516 hfi_copy_cap_prop(cap, inst);
517 cap++;
518 next_offset += sizeof(*cap);
519 num_caps--;
520 }
521 num_props--;
522 break;
523 }
524 case HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED: {
525 struct hfi_uncompressed_format_supported *prop =
526 (struct hfi_uncompressed_format_supported *)
527 (data + next_offset);
528 u32 num_fmt_entries;
529 u8 *fmt;
530 struct hfi_uncompressed_plane_info *inf;
531
532 if ((rem_bytes - next_offset) < sizeof(*prop)) {
533 err = HFI_ERR_SESSION_INVALID_PARAMETER;
534 break;
535 }
536
537 num_fmt_entries = prop->format_entries;
538 next_offset = sizeof(*prop) - sizeof(u32);
539 fmt = (u8 *)&prop->format_info[0];
540
541 dev_dbg(dev, "uncomm format support num entries:%u\n",
542 num_fmt_entries);
543
544 while (num_fmt_entries) {
545 struct hfi_uncompressed_plane_constraints *cnts;
546 u32 bytes_to_skip;
547
548 inf = (struct hfi_uncompressed_plane_info *)fmt;
549
550 if ((rem_bytes - next_offset) < sizeof(*inf)) {
551 err = HFI_ERR_SESSION_INVALID_PARAMETER;
552 break;
553 }
554
555 dev_dbg(dev, "plane info: fmt:%x, planes:%x\n",
556 inf->format, inf->num_planes);
557
558 cnts = &inf->plane_format[0];
559 dev_dbg(dev, "%u %u %u %u\n",
560 cnts->stride_multiples,
561 cnts->max_stride,
562 cnts->min_plane_buffer_height_multiple,
563 cnts->buffer_alignment);
564
565 bytes_to_skip = sizeof(*inf) - sizeof(*cnts) +
566 inf->num_planes * sizeof(*cnts);
567
568 fmt += bytes_to_skip;
569 next_offset += bytes_to_skip;
570 num_fmt_entries--;
571 }
572 num_props--;
573 break;
574 }
575 case HFI_PROPERTY_PARAM_PROPERTIES_SUPPORTED: {
576 struct hfi_properties_supported *prop =
577 (struct hfi_properties_supported *)
578 (data + next_offset);
579
580 next_offset += sizeof(*prop) - sizeof(u32)
581 + prop->num_properties * sizeof(u32);
582 num_props--;
583 break;
584 }
585 case HFI_PROPERTY_PARAM_PROFILE_LEVEL_SUPPORTED: {
586 struct hfi_profile_level_supported *prop =
587 (struct hfi_profile_level_supported *)
588 (data + next_offset);
589 struct hfi_profile_level *pl;
590 unsigned int prop_count = 0;
591 unsigned int count = 0;
592 u8 *ptr;
593
594 ptr = (u8 *)&prop->profile_level[0];
595 prop_count = prop->profile_count;
596
597 if (prop_count > HFI_MAX_PROFILE_COUNT)
598 prop_count = HFI_MAX_PROFILE_COUNT;
599
600 while (prop_count) {
601 ptr++;
602 pl = (struct hfi_profile_level *)ptr;
603
604 inst->pl[count].profile = pl->profile;
605 inst->pl[count].level = pl->level;
606 prop_count--;
607 count++;
608 ptr += sizeof(*pl) / sizeof(u32);
609 }
610
611 inst->pl_count = count;
612 next_offset += sizeof(*prop) - sizeof(*pl) +
613 prop->profile_count * sizeof(*pl);
614
615 num_props--;
616 break;
617 }
618 case HFI_PROPERTY_PARAM_INTERLACE_FORMAT_SUPPORTED: {
619 next_offset +=
620 sizeof(struct hfi_interlace_format_supported);
621 num_props--;
622 break;
623 }
624 case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SUPPORTED: {
625 struct hfi_nal_stream_format *nal =
626 (struct hfi_nal_stream_format *)
627 (data + next_offset);
628 dev_dbg(dev, "NAL format: %x\n", nal->format);
629 next_offset += sizeof(*nal);
630 num_props--;
631 break;
632 }
633 case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT: {
634 next_offset += sizeof(u32);
635 num_props--;
636 break;
637 }
638 case HFI_PROPERTY_PARAM_MAX_SEQUENCE_HEADER_SIZE: {
639 u32 *max_seq_sz = (u32 *)(data + next_offset);
640
641 dev_dbg(dev, "max seq header sz: %x\n", *max_seq_sz);
642 next_offset += sizeof(u32);
643 num_props--;
644 break;
645 }
646 case HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH: {
647 next_offset += sizeof(struct hfi_intra_refresh);
648 num_props--;
649 break;
650 }
651 case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE_SUPPORTED: {
652 struct hfi_buffer_alloc_mode_supported *prop =
653 (struct hfi_buffer_alloc_mode_supported *)
654 (data + next_offset);
655 unsigned int i;
656
657 for (i = 0; i < prop->num_entries; i++) {
658 if (prop->buffer_type == HFI_BUFFER_OUTPUT ||
659 prop->buffer_type == HFI_BUFFER_OUTPUT2) {
660 switch (prop->data[i]) {
661 case HFI_BUFFER_MODE_STATIC:
662 inst->cap_bufs_mode_static = 1;
663 break;
664 case HFI_BUFFER_MODE_DYNAMIC:
665 inst->cap_bufs_mode_dynamic = 1;
666 break;
667 default:
668 break;
669 }
670 }
671 }
672 next_offset += sizeof(*prop) -
673 sizeof(u32) + prop->num_entries * sizeof(u32);
674 num_props--;
675 break;
676 }
677 default:
678 dev_dbg(dev, "%s: default case %#x\n", __func__, ptype);
679 break;
680 }
681
682 rem_bytes -= next_offset;
683 data += next_offset;
684 }
685
686 return err;
687 }
688
689 static void hfi_session_init_done(struct venus_core *core,
690 struct venus_inst *inst, void *packet)
691 {
692 struct hfi_msg_session_init_done_pkt *pkt = packet;
693 unsigned int error;
694
695 error = pkt->error_type;
696 if (error != HFI_ERR_NONE)
697 goto done;
698
699 if (core->res->hfi_version != HFI_VERSION_1XX)
700 goto done;
701
702 error = init_done_read_prop(core, inst, pkt);
703
704 done:
705 inst->error = error;
706 complete(&inst->done);
707 }
708
709 static void hfi_session_load_res_done(struct venus_core *core,
710 struct venus_inst *inst, void *packet)
711 {
712 struct hfi_msg_session_load_resources_done_pkt *pkt = packet;
713
714 inst->error = pkt->error_type;
715 complete(&inst->done);
716 }
717
718 static void hfi_session_flush_done(struct venus_core *core,
719 struct venus_inst *inst, void *packet)
720 {
721 struct hfi_msg_session_flush_done_pkt *pkt = packet;
722
723 inst->error = pkt->error_type;
724 complete(&inst->done);
725 }
726
727 static void hfi_session_etb_done(struct venus_core *core,
728 struct venus_inst *inst, void *packet)
729 {
730 struct hfi_msg_session_empty_buffer_done_pkt *pkt = packet;
731
732 inst->error = pkt->error_type;
733 inst->ops->buf_done(inst, HFI_BUFFER_INPUT, pkt->input_tag,
734 pkt->filled_len, pkt->offset, 0, 0, 0);
735 }
736
737 static void hfi_session_ftb_done(struct venus_core *core,
738 struct venus_inst *inst, void *packet)
739 {
740 u32 session_type = inst->session_type;
741 u64 timestamp_us = 0;
742 u32 timestamp_hi = 0, timestamp_lo = 0;
743 unsigned int error;
744 u32 flags = 0, hfi_flags = 0, offset = 0, filled_len = 0;
745 u32 pic_type = 0, buffer_type = 0, output_tag = -1;
746
747 if (session_type == VIDC_SESSION_TYPE_ENC) {
748 struct hfi_msg_session_fbd_compressed_pkt *pkt = packet;
749
750 timestamp_hi = pkt->time_stamp_hi;
751 timestamp_lo = pkt->time_stamp_lo;
752 hfi_flags = pkt->flags;
753 offset = pkt->offset;
754 filled_len = pkt->filled_len;
755 pic_type = pkt->picture_type;
756 output_tag = pkt->output_tag;
757 buffer_type = HFI_BUFFER_OUTPUT;
758
759 error = pkt->error_type;
760 } else if (session_type == VIDC_SESSION_TYPE_DEC) {
761 struct hfi_msg_session_fbd_uncompressed_plane0_pkt *pkt =
762 packet;
763
764 timestamp_hi = pkt->time_stamp_hi;
765 timestamp_lo = pkt->time_stamp_lo;
766 hfi_flags = pkt->flags;
767 offset = pkt->offset;
768 filled_len = pkt->filled_len;
769 pic_type = pkt->picture_type;
770 output_tag = pkt->output_tag;
771
772 if (pkt->stream_id == 0)
773 buffer_type = HFI_BUFFER_OUTPUT;
774 else if (pkt->stream_id == 1)
775 buffer_type = HFI_BUFFER_OUTPUT2;
776
777 error = pkt->error_type;
778 } else {
779 error = HFI_ERR_SESSION_INVALID_PARAMETER;
780 }
781
782 if (buffer_type != HFI_BUFFER_OUTPUT)
783 goto done;
784
785 if (hfi_flags & HFI_BUFFERFLAG_EOS)
786 flags |= V4L2_BUF_FLAG_LAST;
787
788 switch (pic_type) {
789 case HFI_PICTURE_IDR:
790 case HFI_PICTURE_I:
791 flags |= V4L2_BUF_FLAG_KEYFRAME;
792 break;
793 case HFI_PICTURE_P:
794 flags |= V4L2_BUF_FLAG_PFRAME;
795 break;
796 case HFI_PICTURE_B:
797 flags |= V4L2_BUF_FLAG_BFRAME;
798 break;
799 case HFI_FRAME_NOTCODED:
800 case HFI_UNUSED_PICT:
801 case HFI_FRAME_YUV:
802 default:
803 break;
804 }
805
806 if (!(hfi_flags & HFI_BUFFERFLAG_TIMESTAMPINVALID) && filled_len) {
807 timestamp_us = timestamp_hi;
808 timestamp_us = (timestamp_us << 32) | timestamp_lo;
809 }
810
811 done:
812 inst->error = error;
813 inst->ops->buf_done(inst, buffer_type, output_tag, filled_len,
814 offset, flags, hfi_flags, timestamp_us);
815 }
816
817 static void hfi_session_start_done(struct venus_core *core,
818 struct venus_inst *inst, void *packet)
819 {
820 struct hfi_msg_session_start_done_pkt *pkt = packet;
821
822 inst->error = pkt->error_type;
823 complete(&inst->done);
824 }
825
826 static void hfi_session_stop_done(struct venus_core *core,
827 struct venus_inst *inst, void *packet)
828 {
829 struct hfi_msg_session_stop_done_pkt *pkt = packet;
830
831 inst->error = pkt->error_type;
832 complete(&inst->done);
833 }
834
835 static void hfi_session_rel_res_done(struct venus_core *core,
836 struct venus_inst *inst, void *packet)
837 {
838 struct hfi_msg_session_release_resources_done_pkt *pkt = packet;
839
840 inst->error = pkt->error_type;
841 complete(&inst->done);
842 }
843
844 static void hfi_session_rel_buf_done(struct venus_core *core,
845 struct venus_inst *inst, void *packet)
846 {
847 struct hfi_msg_session_release_buffers_done_pkt *pkt = packet;
848
849 inst->error = pkt->error_type;
850 complete(&inst->done);
851 }
852
853 static void hfi_session_end_done(struct venus_core *core,
854 struct venus_inst *inst, void *packet)
855 {
856 struct hfi_msg_session_end_done_pkt *pkt = packet;
857
858 inst->error = pkt->error_type;
859 complete(&inst->done);
860 }
861
862 static void hfi_session_abort_done(struct venus_core *core,
863 struct venus_inst *inst, void *packet)
864 {
865 struct hfi_msg_sys_session_abort_done_pkt *pkt = packet;
866
867 inst->error = pkt->error_type;
868 complete(&inst->done);
869 }
870
871 static void hfi_session_get_seq_hdr_done(struct venus_core *core,
872 struct venus_inst *inst, void *packet)
873 {
874 struct hfi_msg_session_get_sequence_hdr_done_pkt *pkt = packet;
875
876 inst->error = pkt->error_type;
877 complete(&inst->done);
878 }
879
880 struct hfi_done_handler {
881 u32 pkt;
882 u32 pkt_sz;
883 u32 pkt_sz2;
884 void (*done)(struct venus_core *, struct venus_inst *, void *);
885 bool is_sys_pkt;
886 };
887
888 static const struct hfi_done_handler handlers[] = {
889 {.pkt = HFI_MSG_EVENT_NOTIFY,
890 .pkt_sz = sizeof(struct hfi_msg_event_notify_pkt),
891 .done = hfi_event_notify,
892 },
893 {.pkt = HFI_MSG_SYS_INIT,
894 .pkt_sz = sizeof(struct hfi_msg_sys_init_done_pkt),
895 .done = hfi_sys_init_done,
896 .is_sys_pkt = true,
897 },
898 {.pkt = HFI_MSG_SYS_PROPERTY_INFO,
899 .pkt_sz = sizeof(struct hfi_msg_sys_property_info_pkt),
900 .done = hfi_sys_property_info,
901 .is_sys_pkt = true,
902 },
903 {.pkt = HFI_MSG_SYS_RELEASE_RESOURCE,
904 .pkt_sz = sizeof(struct hfi_msg_sys_release_resource_done_pkt),
905 .done = hfi_sys_rel_resource_done,
906 .is_sys_pkt = true,
907 },
908 {.pkt = HFI_MSG_SYS_PING_ACK,
909 .pkt_sz = sizeof(struct hfi_msg_sys_ping_ack_pkt),
910 .done = hfi_sys_ping_done,
911 .is_sys_pkt = true,
912 },
913 {.pkt = HFI_MSG_SYS_IDLE,
914 .pkt_sz = sizeof(struct hfi_msg_sys_idle_pkt),
915 .done = hfi_sys_idle_done,
916 .is_sys_pkt = true,
917 },
918 {.pkt = HFI_MSG_SYS_PC_PREP,
919 .pkt_sz = sizeof(struct hfi_msg_sys_pc_prep_done_pkt),
920 .done = hfi_sys_pc_prepare_done,
921 .is_sys_pkt = true,
922 },
923 {.pkt = HFI_MSG_SYS_SESSION_INIT,
924 .pkt_sz = sizeof(struct hfi_msg_session_init_done_pkt),
925 .done = hfi_session_init_done,
926 },
927 {.pkt = HFI_MSG_SYS_SESSION_END,
928 .pkt_sz = sizeof(struct hfi_msg_session_end_done_pkt),
929 .done = hfi_session_end_done,
930 },
931 {.pkt = HFI_MSG_SESSION_LOAD_RESOURCES,
932 .pkt_sz = sizeof(struct hfi_msg_session_load_resources_done_pkt),
933 .done = hfi_session_load_res_done,
934 },
935 {.pkt = HFI_MSG_SESSION_START,
936 .pkt_sz = sizeof(struct hfi_msg_session_start_done_pkt),
937 .done = hfi_session_start_done,
938 },
939 {.pkt = HFI_MSG_SESSION_STOP,
940 .pkt_sz = sizeof(struct hfi_msg_session_stop_done_pkt),
941 .done = hfi_session_stop_done,
942 },
943 {.pkt = HFI_MSG_SYS_SESSION_ABORT,
944 .pkt_sz = sizeof(struct hfi_msg_sys_session_abort_done_pkt),
945 .done = hfi_session_abort_done,
946 },
947 {.pkt = HFI_MSG_SESSION_EMPTY_BUFFER,
948 .pkt_sz = sizeof(struct hfi_msg_session_empty_buffer_done_pkt),
949 .done = hfi_session_etb_done,
950 },
951 {.pkt = HFI_MSG_SESSION_FILL_BUFFER,
952 .pkt_sz = sizeof(struct hfi_msg_session_fbd_uncompressed_plane0_pkt),
953 .pkt_sz2 = sizeof(struct hfi_msg_session_fbd_compressed_pkt),
954 .done = hfi_session_ftb_done,
955 },
956 {.pkt = HFI_MSG_SESSION_FLUSH,
957 .pkt_sz = sizeof(struct hfi_msg_session_flush_done_pkt),
958 .done = hfi_session_flush_done,
959 },
960 {.pkt = HFI_MSG_SESSION_PROPERTY_INFO,
961 .pkt_sz = sizeof(struct hfi_msg_session_property_info_pkt),
962 .done = hfi_session_prop_info,
963 },
964 {.pkt = HFI_MSG_SESSION_RELEASE_RESOURCES,
965 .pkt_sz = sizeof(struct hfi_msg_session_release_resources_done_pkt),
966 .done = hfi_session_rel_res_done,
967 },
968 {.pkt = HFI_MSG_SESSION_GET_SEQUENCE_HEADER,
969 .pkt_sz = sizeof(struct hfi_msg_session_get_sequence_hdr_done_pkt),
970 .done = hfi_session_get_seq_hdr_done,
971 },
972 {.pkt = HFI_MSG_SESSION_RELEASE_BUFFERS,
973 .pkt_sz = sizeof(struct hfi_msg_session_release_buffers_done_pkt),
974 .done = hfi_session_rel_buf_done,
975 },
976 };
977
978 void hfi_process_watchdog_timeout(struct venus_core *core)
979 {
980 event_sys_error(core, EVT_SYS_WATCHDOG_TIMEOUT, NULL);
981 }
982
983 static struct venus_inst *to_instance(struct venus_core *core, u32 session_id)
984 {
985 struct venus_inst *inst;
986
987 mutex_lock(&core->lock);
988 list_for_each_entry(inst, &core->instances, list)
989 if (hash32_ptr(inst) == session_id) {
990 mutex_unlock(&core->lock);
991 return inst;
992 }
993 mutex_unlock(&core->lock);
994
995 return NULL;
996 }
997
998 u32 hfi_process_msg_packet(struct venus_core *core, struct hfi_pkt_hdr *hdr)
999 {
1000 const struct hfi_done_handler *handler;
1001 struct device *dev = core->dev;
1002 struct venus_inst *inst;
1003 bool found = false;
1004 unsigned int i;
1005
1006 for (i = 0; i < ARRAY_SIZE(handlers); i++) {
1007 handler = &handlers[i];
1008 if (handler->pkt != hdr->pkt_type)
1009 continue;
1010 found = true;
1011 break;
1012 }
1013
1014 if (!found)
1015 return hdr->pkt_type;
1016
1017 if (hdr->size && hdr->size < handler->pkt_sz &&
1018 hdr->size < handler->pkt_sz2) {
1019 dev_err(dev, "bad packet size (%d should be %d, pkt type:%x)\n",
1020 hdr->size, handler->pkt_sz, hdr->pkt_type);
1021
1022 return hdr->pkt_type;
1023 }
1024
1025 if (handler->is_sys_pkt) {
1026 inst = NULL;
1027 } else {
1028 struct hfi_session_pkt *pkt;
1029
1030 pkt = (struct hfi_session_pkt *)hdr;
1031 inst = to_instance(core, pkt->shdr.session_id);
1032
1033 if (!inst)
1034 dev_warn(dev, "no valid instance(pkt session_id:%x, pkt:%x)\n",
1035 pkt->shdr.session_id,
1036 handler ? handler->pkt : 0);
1037
1038 /*
1039 * Event of type HFI_EVENT_SYS_ERROR will not have any session
1040 * associated with it
1041 */
1042 if (!inst && hdr->pkt_type != HFI_MSG_EVENT_NOTIFY) {
1043 dev_err(dev, "got invalid session id:%x\n",
1044 pkt->shdr.session_id);
1045 goto invalid_session;
1046 }
1047 }
1048
1049 handler->done(core, inst, hdr);
1050
1051 invalid_session:
1052 return hdr->pkt_type;
1053 }