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 rem_bytes -= read_bytes; 244 data += read_bytes; 245 num_properties--; 246 } 247 } 248 249 err_no_prop: 250 core->error = error; 251 complete(&core->done); 252 } 253 254 static void 255 sys_get_prop_image_version(struct device *dev, 256 struct hfi_msg_sys_property_info_pkt *pkt) 257 { 258 int req_bytes; 259 260 req_bytes = pkt->hdr.size - sizeof(*pkt); 261 262 if (req_bytes < 128 || !pkt->data[1] || pkt->num_properties > 1) 263 /* bad packet */ 264 return; 265 266 dev_dbg(dev, "F/W version: %s\n", (u8 *)&pkt->data[1]); 267 } 268 269 static void hfi_sys_property_info(struct venus_core *core, 270 struct venus_inst *inst, void *packet) 271 { 272 struct hfi_msg_sys_property_info_pkt *pkt = packet; 273 struct device *dev = core->dev; 274 275 if (!pkt->num_properties) { 276 dev_dbg(dev, "%s: no properties\n", __func__); 277 return; 278 } 279 280 switch (pkt->data[0]) { 281 case HFI_PROPERTY_SYS_IMAGE_VERSION: 282 sys_get_prop_image_version(dev, pkt); 283 break; 284 default: 285 dev_dbg(dev, "%s: unknown property data\n", __func__); 286 break; 287 } 288 } 289 290 static void hfi_sys_rel_resource_done(struct venus_core *core, 291 struct venus_inst *inst, 292 void *packet) 293 { 294 struct hfi_msg_sys_release_resource_done_pkt *pkt = packet; 295 296 core->error = pkt->error_type; 297 complete(&core->done); 298 } 299 300 static void hfi_sys_ping_done(struct venus_core *core, struct venus_inst *inst, 301 void *packet) 302 { 303 struct hfi_msg_sys_ping_ack_pkt *pkt = packet; 304 305 core->error = HFI_ERR_NONE; 306 307 if (pkt->client_data != 0xbeef) 308 core->error = HFI_ERR_SYS_FATAL; 309 310 complete(&core->done); 311 } 312 313 static void hfi_sys_idle_done(struct venus_core *core, struct venus_inst *inst, 314 void *packet) 315 { 316 dev_dbg(core->dev, "sys idle\n"); 317 } 318 319 static void hfi_sys_pc_prepare_done(struct venus_core *core, 320 struct venus_inst *inst, void *packet) 321 { 322 struct hfi_msg_sys_pc_prep_done_pkt *pkt = packet; 323 324 dev_dbg(core->dev, "pc prepare done (error %x)\n", pkt->error_type); 325 } 326 327 static void 328 hfi_copy_cap_prop(struct hfi_capability *in, struct venus_inst *inst) 329 { 330 if (!in || !inst) 331 return; 332 333 switch (in->capability_type) { 334 case HFI_CAPABILITY_FRAME_WIDTH: 335 inst->cap_width = *in; 336 break; 337 case HFI_CAPABILITY_FRAME_HEIGHT: 338 inst->cap_height = *in; 339 break; 340 case HFI_CAPABILITY_MBS_PER_FRAME: 341 inst->cap_mbs_per_frame = *in; 342 break; 343 case HFI_CAPABILITY_MBS_PER_SECOND: 344 inst->cap_mbs_per_sec = *in; 345 break; 346 case HFI_CAPABILITY_FRAMERATE: 347 inst->cap_framerate = *in; 348 break; 349 case HFI_CAPABILITY_SCALE_X: 350 inst->cap_scale_x = *in; 351 break; 352 case HFI_CAPABILITY_SCALE_Y: 353 inst->cap_scale_y = *in; 354 break; 355 case HFI_CAPABILITY_BITRATE: 356 inst->cap_bitrate = *in; 357 break; 358 case HFI_CAPABILITY_HIER_P_NUM_ENH_LAYERS: 359 inst->cap_hier_p = *in; 360 break; 361 case HFI_CAPABILITY_ENC_LTR_COUNT: 362 inst->cap_ltr_count = *in; 363 break; 364 case HFI_CAPABILITY_CP_OUTPUT2_THRESH: 365 inst->cap_secure_output2_threshold = *in; 366 break; 367 default: 368 break; 369 } 370 } 371 372 static unsigned int 373 session_get_prop_profile_level(struct hfi_msg_session_property_info_pkt *pkt, 374 struct hfi_profile_level *profile_level) 375 { 376 struct hfi_profile_level *hfi; 377 u32 req_bytes; 378 379 req_bytes = pkt->shdr.hdr.size - sizeof(*pkt); 380 381 if (!req_bytes || req_bytes % sizeof(struct hfi_profile_level)) 382 /* bad packet */ 383 return HFI_ERR_SESSION_INVALID_PARAMETER; 384 385 hfi = (struct hfi_profile_level *)&pkt->data[1]; 386 profile_level->profile = hfi->profile; 387 profile_level->level = hfi->level; 388 389 return HFI_ERR_NONE; 390 } 391 392 static unsigned int 393 session_get_prop_buf_req(struct hfi_msg_session_property_info_pkt *pkt, 394 struct hfi_buffer_requirements *bufreq) 395 { 396 struct hfi_buffer_requirements *buf_req; 397 u32 req_bytes; 398 unsigned int idx = 0; 399 400 req_bytes = pkt->shdr.hdr.size - sizeof(*pkt); 401 402 if (!req_bytes || req_bytes % sizeof(*buf_req) || !pkt->data[1]) 403 /* bad packet */ 404 return HFI_ERR_SESSION_INVALID_PARAMETER; 405 406 buf_req = (struct hfi_buffer_requirements *)&pkt->data[1]; 407 if (!buf_req) 408 return HFI_ERR_SESSION_INVALID_PARAMETER; 409 410 while (req_bytes) { 411 memcpy(&bufreq[idx], buf_req, sizeof(*bufreq)); 412 idx++; 413 414 if (idx > HFI_BUFFER_TYPE_MAX) 415 return HFI_ERR_SESSION_INVALID_PARAMETER; 416 417 req_bytes -= sizeof(struct hfi_buffer_requirements); 418 buf_req++; 419 } 420 421 return HFI_ERR_NONE; 422 } 423 424 static void hfi_session_prop_info(struct venus_core *core, 425 struct venus_inst *inst, void *packet) 426 { 427 struct hfi_msg_session_property_info_pkt *pkt = packet; 428 struct device *dev = core->dev; 429 union hfi_get_property *hprop = &inst->hprop; 430 unsigned int error = HFI_ERR_NONE; 431 432 if (!pkt->num_properties) { 433 error = HFI_ERR_SESSION_INVALID_PARAMETER; 434 dev_err(dev, "%s: no properties\n", __func__); 435 goto done; 436 } 437 438 switch (pkt->data[0]) { 439 case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS: 440 memset(hprop->bufreq, 0, sizeof(hprop->bufreq)); 441 error = session_get_prop_buf_req(pkt, hprop->bufreq); 442 break; 443 case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT: 444 memset(&hprop->profile_level, 0, sizeof(hprop->profile_level)); 445 error = session_get_prop_profile_level(pkt, 446 &hprop->profile_level); 447 break; 448 case HFI_PROPERTY_CONFIG_VDEC_ENTROPY: 449 break; 450 default: 451 dev_dbg(dev, "%s: unknown property id:%x\n", __func__, 452 pkt->data[0]); 453 return; 454 } 455 456 done: 457 inst->error = error; 458 complete(&inst->done); 459 } 460 461 static u32 init_done_read_prop(struct venus_core *core, struct venus_inst *inst, 462 struct hfi_msg_session_init_done_pkt *pkt) 463 { 464 struct device *dev = core->dev; 465 u32 rem_bytes, num_props; 466 u32 ptype, next_offset = 0; 467 u32 err; 468 u8 *data; 469 470 rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt) + sizeof(u32); 471 if (!rem_bytes) { 472 dev_err(dev, "%s: missing property info\n", __func__); 473 return HFI_ERR_SESSION_INSUFFICIENT_RESOURCES; 474 } 475 476 err = pkt->error_type; 477 if (err) 478 return err; 479 480 data = (u8 *)&pkt->data[0]; 481 num_props = pkt->num_properties; 482 483 while (err == HFI_ERR_NONE && num_props && rem_bytes >= sizeof(u32)) { 484 ptype = *((u32 *)data); 485 next_offset = sizeof(u32); 486 487 switch (ptype) { 488 case HFI_PROPERTY_PARAM_CODEC_MASK_SUPPORTED: { 489 struct hfi_codec_mask_supported *masks = 490 (struct hfi_codec_mask_supported *) 491 (data + next_offset); 492 493 next_offset += sizeof(*masks); 494 num_props--; 495 break; 496 } 497 case HFI_PROPERTY_PARAM_CAPABILITY_SUPPORTED: { 498 struct hfi_capabilities *caps; 499 struct hfi_capability *cap; 500 u32 num_caps; 501 502 if ((rem_bytes - next_offset) < sizeof(*cap)) { 503 err = HFI_ERR_SESSION_INVALID_PARAMETER; 504 break; 505 } 506 507 caps = (struct hfi_capabilities *)(data + next_offset); 508 509 num_caps = caps->num_capabilities; 510 cap = &caps->data[0]; 511 next_offset += sizeof(u32); 512 513 while (num_caps && 514 (rem_bytes - next_offset) >= sizeof(u32)) { 515 hfi_copy_cap_prop(cap, inst); 516 cap++; 517 next_offset += sizeof(*cap); 518 num_caps--; 519 } 520 num_props--; 521 break; 522 } 523 case HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED: { 524 struct hfi_uncompressed_format_supported *prop = 525 (struct hfi_uncompressed_format_supported *) 526 (data + next_offset); 527 u32 num_fmt_entries; 528 u8 *fmt; 529 struct hfi_uncompressed_plane_info *inf; 530 531 if ((rem_bytes - next_offset) < sizeof(*prop)) { 532 err = HFI_ERR_SESSION_INVALID_PARAMETER; 533 break; 534 } 535 536 num_fmt_entries = prop->format_entries; 537 next_offset = sizeof(*prop) - sizeof(u32); 538 fmt = (u8 *)&prop->format_info[0]; 539 540 dev_dbg(dev, "uncomm format support num entries:%u\n", 541 num_fmt_entries); 542 543 while (num_fmt_entries) { 544 struct hfi_uncompressed_plane_constraints *cnts; 545 u32 bytes_to_skip; 546 547 inf = (struct hfi_uncompressed_plane_info *)fmt; 548 549 if ((rem_bytes - next_offset) < sizeof(*inf)) { 550 err = HFI_ERR_SESSION_INVALID_PARAMETER; 551 break; 552 } 553 554 dev_dbg(dev, "plane info: fmt:%x, planes:%x\n", 555 inf->format, inf->num_planes); 556 557 cnts = &inf->plane_format[0]; 558 dev_dbg(dev, "%u %u %u %u\n", 559 cnts->stride_multiples, 560 cnts->max_stride, 561 cnts->min_plane_buffer_height_multiple, 562 cnts->buffer_alignment); 563 564 bytes_to_skip = sizeof(*inf) - sizeof(*cnts) + 565 inf->num_planes * sizeof(*cnts); 566 567 fmt += bytes_to_skip; 568 next_offset += bytes_to_skip; 569 num_fmt_entries--; 570 } 571 num_props--; 572 break; 573 } 574 case HFI_PROPERTY_PARAM_PROPERTIES_SUPPORTED: { 575 struct hfi_properties_supported *prop = 576 (struct hfi_properties_supported *) 577 (data + next_offset); 578 579 next_offset += sizeof(*prop) - sizeof(u32) 580 + prop->num_properties * sizeof(u32); 581 num_props--; 582 break; 583 } 584 case HFI_PROPERTY_PARAM_PROFILE_LEVEL_SUPPORTED: { 585 struct hfi_profile_level_supported *prop = 586 (struct hfi_profile_level_supported *) 587 (data + next_offset); 588 struct hfi_profile_level *pl; 589 unsigned int prop_count = 0; 590 unsigned int count = 0; 591 u8 *ptr; 592 593 ptr = (u8 *)&prop->profile_level[0]; 594 prop_count = prop->profile_count; 595 596 if (prop_count > HFI_MAX_PROFILE_COUNT) 597 prop_count = HFI_MAX_PROFILE_COUNT; 598 599 while (prop_count) { 600 ptr++; 601 pl = (struct hfi_profile_level *)ptr; 602 603 inst->pl[count].profile = pl->profile; 604 inst->pl[count].level = pl->level; 605 prop_count--; 606 count++; 607 ptr += sizeof(*pl) / sizeof(u32); 608 } 609 610 inst->pl_count = count; 611 next_offset += sizeof(*prop) - sizeof(*pl) + 612 prop->profile_count * sizeof(*pl); 613 614 num_props--; 615 break; 616 } 617 case HFI_PROPERTY_PARAM_INTERLACE_FORMAT_SUPPORTED: { 618 next_offset += 619 sizeof(struct hfi_interlace_format_supported); 620 num_props--; 621 break; 622 } 623 case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SUPPORTED: { 624 struct hfi_nal_stream_format *nal = 625 (struct hfi_nal_stream_format *) 626 (data + next_offset); 627 dev_dbg(dev, "NAL format: %x\n", nal->format); 628 next_offset += sizeof(*nal); 629 num_props--; 630 break; 631 } 632 case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT: { 633 next_offset += sizeof(u32); 634 num_props--; 635 break; 636 } 637 case HFI_PROPERTY_PARAM_MAX_SEQUENCE_HEADER_SIZE: { 638 u32 *max_seq_sz = (u32 *)(data + next_offset); 639 640 dev_dbg(dev, "max seq header sz: %x\n", *max_seq_sz); 641 next_offset += sizeof(u32); 642 num_props--; 643 break; 644 } 645 case HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH: { 646 next_offset += sizeof(struct hfi_intra_refresh); 647 num_props--; 648 break; 649 } 650 case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE_SUPPORTED: { 651 struct hfi_buffer_alloc_mode_supported *prop = 652 (struct hfi_buffer_alloc_mode_supported *) 653 (data + next_offset); 654 unsigned int i; 655 656 for (i = 0; i < prop->num_entries; i++) { 657 if (prop->buffer_type == HFI_BUFFER_OUTPUT || 658 prop->buffer_type == HFI_BUFFER_OUTPUT2) { 659 switch (prop->data[i]) { 660 case HFI_BUFFER_MODE_STATIC: 661 inst->cap_bufs_mode_static = 1; 662 break; 663 case HFI_BUFFER_MODE_DYNAMIC: 664 inst->cap_bufs_mode_dynamic = 1; 665 break; 666 default: 667 break; 668 } 669 } 670 } 671 next_offset += sizeof(*prop) - 672 sizeof(u32) + prop->num_entries * sizeof(u32); 673 num_props--; 674 break; 675 } 676 default: 677 dev_dbg(dev, "%s: default case %#x\n", __func__, ptype); 678 break; 679 } 680 681 rem_bytes -= next_offset; 682 data += next_offset; 683 } 684 685 return err; 686 } 687 688 static void hfi_session_init_done(struct venus_core *core, 689 struct venus_inst *inst, void *packet) 690 { 691 struct hfi_msg_session_init_done_pkt *pkt = packet; 692 unsigned int error; 693 694 error = pkt->error_type; 695 if (error != HFI_ERR_NONE) 696 goto done; 697 698 if (core->res->hfi_version != HFI_VERSION_1XX) 699 goto done; 700 701 error = init_done_read_prop(core, inst, pkt); 702 703 done: 704 inst->error = error; 705 complete(&inst->done); 706 } 707 708 static void hfi_session_load_res_done(struct venus_core *core, 709 struct venus_inst *inst, void *packet) 710 { 711 struct hfi_msg_session_load_resources_done_pkt *pkt = packet; 712 713 inst->error = pkt->error_type; 714 complete(&inst->done); 715 } 716 717 static void hfi_session_flush_done(struct venus_core *core, 718 struct venus_inst *inst, void *packet) 719 { 720 struct hfi_msg_session_flush_done_pkt *pkt = packet; 721 722 inst->error = pkt->error_type; 723 complete(&inst->done); 724 } 725 726 static void hfi_session_etb_done(struct venus_core *core, 727 struct venus_inst *inst, void *packet) 728 { 729 struct hfi_msg_session_empty_buffer_done_pkt *pkt = packet; 730 731 inst->error = pkt->error_type; 732 inst->ops->buf_done(inst, HFI_BUFFER_INPUT, pkt->input_tag, 733 pkt->filled_len, pkt->offset, 0, 0, 0); 734 } 735 736 static void hfi_session_ftb_done(struct venus_core *core, 737 struct venus_inst *inst, void *packet) 738 { 739 u32 session_type = inst->session_type; 740 u64 timestamp_us = 0; 741 u32 timestamp_hi = 0, timestamp_lo = 0; 742 unsigned int error; 743 u32 flags = 0, hfi_flags = 0, offset = 0, filled_len = 0; 744 u32 pic_type = 0, buffer_type = 0, output_tag = -1; 745 746 if (session_type == VIDC_SESSION_TYPE_ENC) { 747 struct hfi_msg_session_fbd_compressed_pkt *pkt = packet; 748 749 timestamp_hi = pkt->time_stamp_hi; 750 timestamp_lo = pkt->time_stamp_lo; 751 hfi_flags = pkt->flags; 752 offset = pkt->offset; 753 filled_len = pkt->filled_len; 754 pic_type = pkt->picture_type; 755 output_tag = pkt->output_tag; 756 buffer_type = HFI_BUFFER_OUTPUT; 757 758 error = pkt->error_type; 759 } else if (session_type == VIDC_SESSION_TYPE_DEC) { 760 struct hfi_msg_session_fbd_uncompressed_plane0_pkt *pkt = 761 packet; 762 763 timestamp_hi = pkt->time_stamp_hi; 764 timestamp_lo = pkt->time_stamp_lo; 765 hfi_flags = pkt->flags; 766 offset = pkt->offset; 767 filled_len = pkt->filled_len; 768 pic_type = pkt->picture_type; 769 output_tag = pkt->output_tag; 770 771 if (pkt->stream_id == 0) 772 buffer_type = HFI_BUFFER_OUTPUT; 773 else if (pkt->stream_id == 1) 774 buffer_type = HFI_BUFFER_OUTPUT2; 775 776 error = pkt->error_type; 777 } else { 778 error = HFI_ERR_SESSION_INVALID_PARAMETER; 779 } 780 781 if (buffer_type != HFI_BUFFER_OUTPUT) 782 goto done; 783 784 if (hfi_flags & HFI_BUFFERFLAG_EOS) 785 flags |= V4L2_BUF_FLAG_LAST; 786 787 switch (pic_type) { 788 case HFI_PICTURE_IDR: 789 case HFI_PICTURE_I: 790 flags |= V4L2_BUF_FLAG_KEYFRAME; 791 break; 792 case HFI_PICTURE_P: 793 flags |= V4L2_BUF_FLAG_PFRAME; 794 break; 795 case HFI_PICTURE_B: 796 flags |= V4L2_BUF_FLAG_BFRAME; 797 break; 798 case HFI_FRAME_NOTCODED: 799 case HFI_UNUSED_PICT: 800 case HFI_FRAME_YUV: 801 default: 802 break; 803 } 804 805 if (!(hfi_flags & HFI_BUFFERFLAG_TIMESTAMPINVALID) && filled_len) { 806 timestamp_us = timestamp_hi; 807 timestamp_us = (timestamp_us << 32) | timestamp_lo; 808 } 809 810 done: 811 inst->error = error; 812 inst->ops->buf_done(inst, buffer_type, output_tag, filled_len, 813 offset, flags, hfi_flags, timestamp_us); 814 } 815 816 static void hfi_session_start_done(struct venus_core *core, 817 struct venus_inst *inst, void *packet) 818 { 819 struct hfi_msg_session_start_done_pkt *pkt = packet; 820 821 inst->error = pkt->error_type; 822 complete(&inst->done); 823 } 824 825 static void hfi_session_stop_done(struct venus_core *core, 826 struct venus_inst *inst, void *packet) 827 { 828 struct hfi_msg_session_stop_done_pkt *pkt = packet; 829 830 inst->error = pkt->error_type; 831 complete(&inst->done); 832 } 833 834 static void hfi_session_rel_res_done(struct venus_core *core, 835 struct venus_inst *inst, void *packet) 836 { 837 struct hfi_msg_session_release_resources_done_pkt *pkt = packet; 838 839 inst->error = pkt->error_type; 840 complete(&inst->done); 841 } 842 843 static void hfi_session_rel_buf_done(struct venus_core *core, 844 struct venus_inst *inst, void *packet) 845 { 846 struct hfi_msg_session_release_buffers_done_pkt *pkt = packet; 847 848 inst->error = pkt->error_type; 849 complete(&inst->done); 850 } 851 852 static void hfi_session_end_done(struct venus_core *core, 853 struct venus_inst *inst, void *packet) 854 { 855 struct hfi_msg_session_end_done_pkt *pkt = packet; 856 857 inst->error = pkt->error_type; 858 complete(&inst->done); 859 } 860 861 static void hfi_session_abort_done(struct venus_core *core, 862 struct venus_inst *inst, void *packet) 863 { 864 struct hfi_msg_sys_session_abort_done_pkt *pkt = packet; 865 866 inst->error = pkt->error_type; 867 complete(&inst->done); 868 } 869 870 static void hfi_session_get_seq_hdr_done(struct venus_core *core, 871 struct venus_inst *inst, void *packet) 872 { 873 struct hfi_msg_session_get_sequence_hdr_done_pkt *pkt = packet; 874 875 inst->error = pkt->error_type; 876 complete(&inst->done); 877 } 878 879 struct hfi_done_handler { 880 u32 pkt; 881 u32 pkt_sz; 882 u32 pkt_sz2; 883 void (*done)(struct venus_core *, struct venus_inst *, void *); 884 bool is_sys_pkt; 885 }; 886 887 static const struct hfi_done_handler handlers[] = { 888 {.pkt = HFI_MSG_EVENT_NOTIFY, 889 .pkt_sz = sizeof(struct hfi_msg_event_notify_pkt), 890 .done = hfi_event_notify, 891 }, 892 {.pkt = HFI_MSG_SYS_INIT, 893 .pkt_sz = sizeof(struct hfi_msg_sys_init_done_pkt), 894 .done = hfi_sys_init_done, 895 .is_sys_pkt = true, 896 }, 897 {.pkt = HFI_MSG_SYS_PROPERTY_INFO, 898 .pkt_sz = sizeof(struct hfi_msg_sys_property_info_pkt), 899 .done = hfi_sys_property_info, 900 .is_sys_pkt = true, 901 }, 902 {.pkt = HFI_MSG_SYS_RELEASE_RESOURCE, 903 .pkt_sz = sizeof(struct hfi_msg_sys_release_resource_done_pkt), 904 .done = hfi_sys_rel_resource_done, 905 .is_sys_pkt = true, 906 }, 907 {.pkt = HFI_MSG_SYS_PING_ACK, 908 .pkt_sz = sizeof(struct hfi_msg_sys_ping_ack_pkt), 909 .done = hfi_sys_ping_done, 910 .is_sys_pkt = true, 911 }, 912 {.pkt = HFI_MSG_SYS_IDLE, 913 .pkt_sz = sizeof(struct hfi_msg_sys_idle_pkt), 914 .done = hfi_sys_idle_done, 915 .is_sys_pkt = true, 916 }, 917 {.pkt = HFI_MSG_SYS_PC_PREP, 918 .pkt_sz = sizeof(struct hfi_msg_sys_pc_prep_done_pkt), 919 .done = hfi_sys_pc_prepare_done, 920 .is_sys_pkt = true, 921 }, 922 {.pkt = HFI_MSG_SYS_SESSION_INIT, 923 .pkt_sz = sizeof(struct hfi_msg_session_init_done_pkt), 924 .done = hfi_session_init_done, 925 }, 926 {.pkt = HFI_MSG_SYS_SESSION_END, 927 .pkt_sz = sizeof(struct hfi_msg_session_end_done_pkt), 928 .done = hfi_session_end_done, 929 }, 930 {.pkt = HFI_MSG_SESSION_LOAD_RESOURCES, 931 .pkt_sz = sizeof(struct hfi_msg_session_load_resources_done_pkt), 932 .done = hfi_session_load_res_done, 933 }, 934 {.pkt = HFI_MSG_SESSION_START, 935 .pkt_sz = sizeof(struct hfi_msg_session_start_done_pkt), 936 .done = hfi_session_start_done, 937 }, 938 {.pkt = HFI_MSG_SESSION_STOP, 939 .pkt_sz = sizeof(struct hfi_msg_session_stop_done_pkt), 940 .done = hfi_session_stop_done, 941 }, 942 {.pkt = HFI_MSG_SYS_SESSION_ABORT, 943 .pkt_sz = sizeof(struct hfi_msg_sys_session_abort_done_pkt), 944 .done = hfi_session_abort_done, 945 }, 946 {.pkt = HFI_MSG_SESSION_EMPTY_BUFFER, 947 .pkt_sz = sizeof(struct hfi_msg_session_empty_buffer_done_pkt), 948 .done = hfi_session_etb_done, 949 }, 950 {.pkt = HFI_MSG_SESSION_FILL_BUFFER, 951 .pkt_sz = sizeof(struct hfi_msg_session_fbd_uncompressed_plane0_pkt), 952 .pkt_sz2 = sizeof(struct hfi_msg_session_fbd_compressed_pkt), 953 .done = hfi_session_ftb_done, 954 }, 955 {.pkt = HFI_MSG_SESSION_FLUSH, 956 .pkt_sz = sizeof(struct hfi_msg_session_flush_done_pkt), 957 .done = hfi_session_flush_done, 958 }, 959 {.pkt = HFI_MSG_SESSION_PROPERTY_INFO, 960 .pkt_sz = sizeof(struct hfi_msg_session_property_info_pkt), 961 .done = hfi_session_prop_info, 962 }, 963 {.pkt = HFI_MSG_SESSION_RELEASE_RESOURCES, 964 .pkt_sz = sizeof(struct hfi_msg_session_release_resources_done_pkt), 965 .done = hfi_session_rel_res_done, 966 }, 967 {.pkt = HFI_MSG_SESSION_GET_SEQUENCE_HEADER, 968 .pkt_sz = sizeof(struct hfi_msg_session_get_sequence_hdr_done_pkt), 969 .done = hfi_session_get_seq_hdr_done, 970 }, 971 {.pkt = HFI_MSG_SESSION_RELEASE_BUFFERS, 972 .pkt_sz = sizeof(struct hfi_msg_session_release_buffers_done_pkt), 973 .done = hfi_session_rel_buf_done, 974 }, 975 }; 976 977 void hfi_process_watchdog_timeout(struct venus_core *core) 978 { 979 event_sys_error(core, EVT_SYS_WATCHDOG_TIMEOUT, NULL); 980 } 981 982 static struct venus_inst *to_instance(struct venus_core *core, u32 session_id) 983 { 984 struct venus_inst *inst; 985 986 mutex_lock(&core->lock); 987 list_for_each_entry(inst, &core->instances, list) 988 if (hash32_ptr(inst) == session_id) { 989 mutex_unlock(&core->lock); 990 return inst; 991 } 992 mutex_unlock(&core->lock); 993 994 return NULL; 995 } 996 997 u32 hfi_process_msg_packet(struct venus_core *core, struct hfi_pkt_hdr *hdr) 998 { 999 const struct hfi_done_handler *handler; 1000 struct device *dev = core->dev; 1001 struct venus_inst *inst; 1002 bool found = false; 1003 unsigned int i; 1004 1005 for (i = 0; i < ARRAY_SIZE(handlers); i++) { 1006 handler = &handlers[i]; 1007 if (handler->pkt != hdr->pkt_type) 1008 continue; 1009 found = true; 1010 break; 1011 } 1012 1013 if (!found) 1014 return hdr->pkt_type; 1015 1016 if (hdr->size && hdr->size < handler->pkt_sz && 1017 hdr->size < handler->pkt_sz2) { 1018 dev_err(dev, "bad packet size (%d should be %d, pkt type:%x)\n", 1019 hdr->size, handler->pkt_sz, hdr->pkt_type); 1020 1021 return hdr->pkt_type; 1022 } 1023 1024 if (handler->is_sys_pkt) { 1025 inst = NULL; 1026 } else { 1027 struct hfi_session_pkt *pkt; 1028 1029 pkt = (struct hfi_session_pkt *)hdr; 1030 inst = to_instance(core, pkt->shdr.session_id); 1031 1032 if (!inst) 1033 dev_warn(dev, "no valid instance(pkt session_id:%x, pkt:%x)\n", 1034 pkt->shdr.session_id, 1035 handler ? handler->pkt : 0); 1036 1037 /* 1038 * Event of type HFI_EVENT_SYS_ERROR will not have any session 1039 * associated with it 1040 */ 1041 if (!inst && hdr->pkt_type != HFI_MSG_EVENT_NOTIFY) { 1042 dev_err(dev, "got invalid session id:%x\n", 1043 pkt->shdr.session_id); 1044 goto invalid_session; 1045 } 1046 } 1047 1048 handler->done(core, inst, hdr); 1049 1050 invalid_session: 1051 return hdr->pkt_type; 1052 } 1053