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 } 1054