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 16 #include <linux/delay.h> 17 #include <linux/device.h> 18 #include <linux/dma-mapping.h> 19 #include <linux/interrupt.h> 20 #include <linux/iopoll.h> 21 #include <linux/kernel.h> 22 #include <linux/qcom_scm.h> 23 #include <linux/slab.h> 24 25 #include "core.h" 26 #include "hfi_cmds.h" 27 #include "hfi_msgs.h" 28 #include "hfi_venus.h" 29 #include "hfi_venus_io.h" 30 31 #define HFI_MASK_QHDR_TX_TYPE 0xff000000 32 #define HFI_MASK_QHDR_RX_TYPE 0x00ff0000 33 #define HFI_MASK_QHDR_PRI_TYPE 0x0000ff00 34 #define HFI_MASK_QHDR_ID_TYPE 0x000000ff 35 36 #define HFI_HOST_TO_CTRL_CMD_Q 0 37 #define HFI_CTRL_TO_HOST_MSG_Q 1 38 #define HFI_CTRL_TO_HOST_DBG_Q 2 39 #define HFI_MASK_QHDR_STATUS 0x000000ff 40 41 #define IFACEQ_NUM 3 42 #define IFACEQ_CMD_IDX 0 43 #define IFACEQ_MSG_IDX 1 44 #define IFACEQ_DBG_IDX 2 45 #define IFACEQ_MAX_BUF_COUNT 50 46 #define IFACEQ_MAX_PARALLEL_CLNTS 16 47 #define IFACEQ_DFLT_QHDR 0x01010000 48 49 #define POLL_INTERVAL_US 50 50 51 #define IFACEQ_MAX_PKT_SIZE 1024 52 #define IFACEQ_MED_PKT_SIZE 768 53 #define IFACEQ_MIN_PKT_SIZE 8 54 #define IFACEQ_VAR_SMALL_PKT_SIZE 100 55 #define IFACEQ_VAR_LARGE_PKT_SIZE 512 56 #define IFACEQ_VAR_HUGE_PKT_SIZE (1024 * 12) 57 58 enum tzbsp_video_state { 59 TZBSP_VIDEO_STATE_SUSPEND = 0, 60 TZBSP_VIDEO_STATE_RESUME 61 }; 62 63 struct hfi_queue_table_header { 64 u32 version; 65 u32 size; 66 u32 qhdr0_offset; 67 u32 qhdr_size; 68 u32 num_q; 69 u32 num_active_q; 70 }; 71 72 struct hfi_queue_header { 73 u32 status; 74 u32 start_addr; 75 u32 type; 76 u32 q_size; 77 u32 pkt_size; 78 u32 pkt_drop_cnt; 79 u32 rx_wm; 80 u32 tx_wm; 81 u32 rx_req; 82 u32 tx_req; 83 u32 rx_irq_status; 84 u32 tx_irq_status; 85 u32 read_idx; 86 u32 write_idx; 87 }; 88 89 #define IFACEQ_TABLE_SIZE \ 90 (sizeof(struct hfi_queue_table_header) + \ 91 sizeof(struct hfi_queue_header) * IFACEQ_NUM) 92 93 #define IFACEQ_QUEUE_SIZE (IFACEQ_MAX_PKT_SIZE * \ 94 IFACEQ_MAX_BUF_COUNT * IFACEQ_MAX_PARALLEL_CLNTS) 95 96 #define IFACEQ_GET_QHDR_START_ADDR(ptr, i) \ 97 (void *)(((ptr) + sizeof(struct hfi_queue_table_header)) + \ 98 ((i) * sizeof(struct hfi_queue_header))) 99 100 #define QDSS_SIZE SZ_4K 101 #define SFR_SIZE SZ_4K 102 #define QUEUE_SIZE \ 103 (IFACEQ_TABLE_SIZE + (IFACEQ_QUEUE_SIZE * IFACEQ_NUM)) 104 105 #define ALIGNED_QDSS_SIZE ALIGN(QDSS_SIZE, SZ_4K) 106 #define ALIGNED_SFR_SIZE ALIGN(SFR_SIZE, SZ_4K) 107 #define ALIGNED_QUEUE_SIZE ALIGN(QUEUE_SIZE, SZ_4K) 108 #define SHARED_QSIZE ALIGN(ALIGNED_SFR_SIZE + ALIGNED_QUEUE_SIZE + \ 109 ALIGNED_QDSS_SIZE, SZ_1M) 110 111 struct mem_desc { 112 dma_addr_t da; /* device address */ 113 void *kva; /* kernel virtual address */ 114 u32 size; 115 unsigned long attrs; 116 }; 117 118 struct iface_queue { 119 struct hfi_queue_header *qhdr; 120 struct mem_desc qmem; 121 }; 122 123 enum venus_state { 124 VENUS_STATE_DEINIT = 1, 125 VENUS_STATE_INIT, 126 }; 127 128 struct venus_hfi_device { 129 struct venus_core *core; 130 u32 irq_status; 131 u32 last_packet_type; 132 bool power_enabled; 133 bool suspended; 134 enum venus_state state; 135 /* serialize read / write to the shared memory */ 136 struct mutex lock; 137 struct completion pwr_collapse_prep; 138 struct completion release_resource; 139 struct mem_desc ifaceq_table; 140 struct mem_desc sfr; 141 struct iface_queue queues[IFACEQ_NUM]; 142 u8 pkt_buf[IFACEQ_VAR_HUGE_PKT_SIZE]; 143 u8 dbg_buf[IFACEQ_VAR_HUGE_PKT_SIZE]; 144 }; 145 146 static bool venus_pkt_debug; 147 static int venus_fw_debug = HFI_DEBUG_MSG_ERROR | HFI_DEBUG_MSG_FATAL; 148 static bool venus_sys_idle_indicator; 149 static bool venus_fw_low_power_mode = true; 150 static int venus_hw_rsp_timeout = 1000; 151 static bool venus_fw_coverage; 152 153 static void venus_set_state(struct venus_hfi_device *hdev, 154 enum venus_state state) 155 { 156 mutex_lock(&hdev->lock); 157 hdev->state = state; 158 mutex_unlock(&hdev->lock); 159 } 160 161 static bool venus_is_valid_state(struct venus_hfi_device *hdev) 162 { 163 return hdev->state != VENUS_STATE_DEINIT; 164 } 165 166 static void venus_dump_packet(struct venus_hfi_device *hdev, const void *packet) 167 { 168 size_t pkt_size = *(u32 *)packet; 169 170 if (!venus_pkt_debug) 171 return; 172 173 print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 1, packet, 174 pkt_size, true); 175 } 176 177 static int venus_write_queue(struct venus_hfi_device *hdev, 178 struct iface_queue *queue, 179 void *packet, u32 *rx_req) 180 { 181 struct hfi_queue_header *qhdr; 182 u32 dwords, new_wr_idx; 183 u32 empty_space, rd_idx, wr_idx, qsize; 184 u32 *wr_ptr; 185 186 if (!queue->qmem.kva) 187 return -EINVAL; 188 189 qhdr = queue->qhdr; 190 if (!qhdr) 191 return -EINVAL; 192 193 venus_dump_packet(hdev, packet); 194 195 dwords = (*(u32 *)packet) >> 2; 196 if (!dwords) 197 return -EINVAL; 198 199 rd_idx = qhdr->read_idx; 200 wr_idx = qhdr->write_idx; 201 qsize = qhdr->q_size; 202 /* ensure rd/wr indices's are read from memory */ 203 rmb(); 204 205 if (wr_idx >= rd_idx) 206 empty_space = qsize - (wr_idx - rd_idx); 207 else 208 empty_space = rd_idx - wr_idx; 209 210 if (empty_space <= dwords) { 211 qhdr->tx_req = 1; 212 /* ensure tx_req is updated in memory */ 213 wmb(); 214 return -ENOSPC; 215 } 216 217 qhdr->tx_req = 0; 218 /* ensure tx_req is updated in memory */ 219 wmb(); 220 221 new_wr_idx = wr_idx + dwords; 222 wr_ptr = (u32 *)(queue->qmem.kva + (wr_idx << 2)); 223 if (new_wr_idx < qsize) { 224 memcpy(wr_ptr, packet, dwords << 2); 225 } else { 226 size_t len; 227 228 new_wr_idx -= qsize; 229 len = (dwords - new_wr_idx) << 2; 230 memcpy(wr_ptr, packet, len); 231 memcpy(queue->qmem.kva, packet + len, new_wr_idx << 2); 232 } 233 234 /* make sure packet is written before updating the write index */ 235 wmb(); 236 237 qhdr->write_idx = new_wr_idx; 238 *rx_req = qhdr->rx_req ? 1 : 0; 239 240 /* make sure write index is updated before an interrupt is raised */ 241 mb(); 242 243 return 0; 244 } 245 246 static int venus_read_queue(struct venus_hfi_device *hdev, 247 struct iface_queue *queue, void *pkt, u32 *tx_req) 248 { 249 struct hfi_queue_header *qhdr; 250 u32 dwords, new_rd_idx; 251 u32 rd_idx, wr_idx, type, qsize; 252 u32 *rd_ptr; 253 u32 recv_request = 0; 254 int ret = 0; 255 256 if (!queue->qmem.kva) 257 return -EINVAL; 258 259 qhdr = queue->qhdr; 260 if (!qhdr) 261 return -EINVAL; 262 263 type = qhdr->type; 264 rd_idx = qhdr->read_idx; 265 wr_idx = qhdr->write_idx; 266 qsize = qhdr->q_size; 267 268 /* make sure data is valid before using it */ 269 rmb(); 270 271 /* 272 * Do not set receive request for debug queue, if set, Venus generates 273 * interrupt for debug messages even when there is no response message 274 * available. In general debug queue will not become full as it is being 275 * emptied out for every interrupt from Venus. Venus will anyway 276 * generates interrupt if it is full. 277 */ 278 if (type & HFI_CTRL_TO_HOST_MSG_Q) 279 recv_request = 1; 280 281 if (rd_idx == wr_idx) { 282 qhdr->rx_req = recv_request; 283 *tx_req = 0; 284 /* update rx_req field in memory */ 285 wmb(); 286 return -ENODATA; 287 } 288 289 rd_ptr = (u32 *)(queue->qmem.kva + (rd_idx << 2)); 290 dwords = *rd_ptr >> 2; 291 if (!dwords) 292 return -EINVAL; 293 294 new_rd_idx = rd_idx + dwords; 295 if (((dwords << 2) <= IFACEQ_VAR_HUGE_PKT_SIZE) && rd_idx <= qsize) { 296 if (new_rd_idx < qsize) { 297 memcpy(pkt, rd_ptr, dwords << 2); 298 } else { 299 size_t len; 300 301 new_rd_idx -= qsize; 302 len = (dwords - new_rd_idx) << 2; 303 memcpy(pkt, rd_ptr, len); 304 memcpy(pkt + len, queue->qmem.kva, new_rd_idx << 2); 305 } 306 } else { 307 /* bad packet received, dropping */ 308 new_rd_idx = qhdr->write_idx; 309 ret = -EBADMSG; 310 } 311 312 /* ensure the packet is read before updating read index */ 313 rmb(); 314 315 qhdr->read_idx = new_rd_idx; 316 /* ensure updating read index */ 317 wmb(); 318 319 rd_idx = qhdr->read_idx; 320 wr_idx = qhdr->write_idx; 321 /* ensure rd/wr indices are read from memory */ 322 rmb(); 323 324 if (rd_idx != wr_idx) 325 qhdr->rx_req = 0; 326 else 327 qhdr->rx_req = recv_request; 328 329 *tx_req = qhdr->tx_req ? 1 : 0; 330 331 /* ensure rx_req is stored to memory and tx_req is loaded from memory */ 332 mb(); 333 334 venus_dump_packet(hdev, pkt); 335 336 return ret; 337 } 338 339 static int venus_alloc(struct venus_hfi_device *hdev, struct mem_desc *desc, 340 u32 size) 341 { 342 struct device *dev = hdev->core->dev; 343 344 desc->attrs = DMA_ATTR_WRITE_COMBINE; 345 desc->size = ALIGN(size, SZ_4K); 346 347 desc->kva = dma_alloc_attrs(dev, desc->size, &desc->da, GFP_KERNEL, 348 desc->attrs); 349 if (!desc->kva) 350 return -ENOMEM; 351 352 return 0; 353 } 354 355 static void venus_free(struct venus_hfi_device *hdev, struct mem_desc *mem) 356 { 357 struct device *dev = hdev->core->dev; 358 359 dma_free_attrs(dev, mem->size, mem->kva, mem->da, mem->attrs); 360 } 361 362 static void venus_writel(struct venus_hfi_device *hdev, u32 reg, u32 value) 363 { 364 writel(value, hdev->core->base + reg); 365 } 366 367 static u32 venus_readl(struct venus_hfi_device *hdev, u32 reg) 368 { 369 return readl(hdev->core->base + reg); 370 } 371 372 static void venus_set_registers(struct venus_hfi_device *hdev) 373 { 374 const struct venus_resources *res = hdev->core->res; 375 const struct reg_val *tbl = res->reg_tbl; 376 unsigned int count = res->reg_tbl_size; 377 unsigned int i; 378 379 for (i = 0; i < count; i++) 380 venus_writel(hdev, tbl[i].reg, tbl[i].value); 381 } 382 383 static void venus_soft_int(struct venus_hfi_device *hdev) 384 { 385 venus_writel(hdev, CPU_IC_SOFTINT, BIT(CPU_IC_SOFTINT_H2A_SHIFT)); 386 } 387 388 static int venus_iface_cmdq_write_nolock(struct venus_hfi_device *hdev, 389 void *pkt) 390 { 391 struct device *dev = hdev->core->dev; 392 struct hfi_pkt_hdr *cmd_packet; 393 struct iface_queue *queue; 394 u32 rx_req; 395 int ret; 396 397 if (!venus_is_valid_state(hdev)) 398 return -EINVAL; 399 400 cmd_packet = (struct hfi_pkt_hdr *)pkt; 401 hdev->last_packet_type = cmd_packet->pkt_type; 402 403 queue = &hdev->queues[IFACEQ_CMD_IDX]; 404 405 ret = venus_write_queue(hdev, queue, pkt, &rx_req); 406 if (ret) { 407 dev_err(dev, "write to iface cmd queue failed (%d)\n", ret); 408 return ret; 409 } 410 411 if (rx_req) 412 venus_soft_int(hdev); 413 414 return 0; 415 } 416 417 static int venus_iface_cmdq_write(struct venus_hfi_device *hdev, void *pkt) 418 { 419 int ret; 420 421 mutex_lock(&hdev->lock); 422 ret = venus_iface_cmdq_write_nolock(hdev, pkt); 423 mutex_unlock(&hdev->lock); 424 425 return ret; 426 } 427 428 static int venus_hfi_core_set_resource(struct venus_core *core, u32 id, 429 u32 size, u32 addr, void *cookie) 430 { 431 struct venus_hfi_device *hdev = to_hfi_priv(core); 432 struct hfi_sys_set_resource_pkt *pkt; 433 u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE]; 434 int ret; 435 436 if (id == VIDC_RESOURCE_NONE) 437 return 0; 438 439 pkt = (struct hfi_sys_set_resource_pkt *)packet; 440 441 ret = pkt_sys_set_resource(pkt, id, size, addr, cookie); 442 if (ret) 443 return ret; 444 445 ret = venus_iface_cmdq_write(hdev, pkt); 446 if (ret) 447 return ret; 448 449 return 0; 450 } 451 452 static int venus_boot_core(struct venus_hfi_device *hdev) 453 { 454 struct device *dev = hdev->core->dev; 455 static const unsigned int max_tries = 100; 456 u32 ctrl_status = 0; 457 unsigned int count = 0; 458 int ret = 0; 459 460 venus_writel(hdev, VIDC_CTRL_INIT, BIT(VIDC_CTRL_INIT_CTRL_SHIFT)); 461 venus_writel(hdev, WRAPPER_INTR_MASK, WRAPPER_INTR_MASK_A2HVCODEC_MASK); 462 venus_writel(hdev, CPU_CS_SCIACMDARG3, 1); 463 464 while (!ctrl_status && count < max_tries) { 465 ctrl_status = venus_readl(hdev, CPU_CS_SCIACMDARG0); 466 if ((ctrl_status & CPU_CS_SCIACMDARG0_ERROR_STATUS_MASK) == 4) { 467 dev_err(dev, "invalid setting for UC_REGION\n"); 468 ret = -EINVAL; 469 break; 470 } 471 472 usleep_range(500, 1000); 473 count++; 474 } 475 476 if (count >= max_tries) 477 ret = -ETIMEDOUT; 478 479 return ret; 480 } 481 482 static u32 venus_hwversion(struct venus_hfi_device *hdev) 483 { 484 struct device *dev = hdev->core->dev; 485 u32 ver = venus_readl(hdev, WRAPPER_HW_VERSION); 486 u32 major, minor, step; 487 488 major = ver & WRAPPER_HW_VERSION_MAJOR_VERSION_MASK; 489 major = major >> WRAPPER_HW_VERSION_MAJOR_VERSION_SHIFT; 490 minor = ver & WRAPPER_HW_VERSION_MINOR_VERSION_MASK; 491 minor = minor >> WRAPPER_HW_VERSION_MINOR_VERSION_SHIFT; 492 step = ver & WRAPPER_HW_VERSION_STEP_VERSION_MASK; 493 494 dev_dbg(dev, "venus hw version %x.%x.%x\n", major, minor, step); 495 496 return major; 497 } 498 499 static int venus_run(struct venus_hfi_device *hdev) 500 { 501 struct device *dev = hdev->core->dev; 502 int ret; 503 504 /* 505 * Re-program all of the registers that get reset as a result of 506 * regulator_disable() and _enable() 507 */ 508 venus_set_registers(hdev); 509 510 venus_writel(hdev, UC_REGION_ADDR, hdev->ifaceq_table.da); 511 venus_writel(hdev, UC_REGION_SIZE, SHARED_QSIZE); 512 venus_writel(hdev, CPU_CS_SCIACMDARG2, hdev->ifaceq_table.da); 513 venus_writel(hdev, CPU_CS_SCIACMDARG1, 0x01); 514 if (hdev->sfr.da) 515 venus_writel(hdev, SFR_ADDR, hdev->sfr.da); 516 517 ret = venus_boot_core(hdev); 518 if (ret) { 519 dev_err(dev, "failed to reset venus core\n"); 520 return ret; 521 } 522 523 venus_hwversion(hdev); 524 525 return 0; 526 } 527 528 static int venus_halt_axi(struct venus_hfi_device *hdev) 529 { 530 void __iomem *base = hdev->core->base; 531 struct device *dev = hdev->core->dev; 532 u32 val; 533 int ret; 534 535 if (IS_V4(hdev->core)) { 536 val = venus_readl(hdev, WRAPPER_CPU_AXI_HALT); 537 val |= WRAPPER_CPU_AXI_HALT_HALT; 538 venus_writel(hdev, WRAPPER_CPU_AXI_HALT, val); 539 540 ret = readl_poll_timeout(base + WRAPPER_CPU_AXI_HALT_STATUS, 541 val, 542 val & WRAPPER_CPU_AXI_HALT_STATUS_IDLE, 543 POLL_INTERVAL_US, 544 VBIF_AXI_HALT_ACK_TIMEOUT_US); 545 if (ret) { 546 dev_err(dev, "AXI bus port halt timeout\n"); 547 return ret; 548 } 549 550 return 0; 551 } 552 553 /* Halt AXI and AXI IMEM VBIF Access */ 554 val = venus_readl(hdev, VBIF_AXI_HALT_CTRL0); 555 val |= VBIF_AXI_HALT_CTRL0_HALT_REQ; 556 venus_writel(hdev, VBIF_AXI_HALT_CTRL0, val); 557 558 /* Request for AXI bus port halt */ 559 ret = readl_poll_timeout(base + VBIF_AXI_HALT_CTRL1, val, 560 val & VBIF_AXI_HALT_CTRL1_HALT_ACK, 561 POLL_INTERVAL_US, 562 VBIF_AXI_HALT_ACK_TIMEOUT_US); 563 if (ret) { 564 dev_err(dev, "AXI bus port halt timeout\n"); 565 return ret; 566 } 567 568 return 0; 569 } 570 571 static int venus_power_off(struct venus_hfi_device *hdev) 572 { 573 int ret; 574 575 if (!hdev->power_enabled) 576 return 0; 577 578 ret = qcom_scm_set_remote_state(TZBSP_VIDEO_STATE_SUSPEND, 0); 579 if (ret) 580 return ret; 581 582 ret = venus_halt_axi(hdev); 583 if (ret) 584 return ret; 585 586 hdev->power_enabled = false; 587 588 return 0; 589 } 590 591 static int venus_power_on(struct venus_hfi_device *hdev) 592 { 593 int ret; 594 595 if (hdev->power_enabled) 596 return 0; 597 598 ret = qcom_scm_set_remote_state(TZBSP_VIDEO_STATE_RESUME, 0); 599 if (ret) 600 goto err; 601 602 ret = venus_run(hdev); 603 if (ret) 604 goto err_suspend; 605 606 hdev->power_enabled = true; 607 608 return 0; 609 610 err_suspend: 611 qcom_scm_set_remote_state(TZBSP_VIDEO_STATE_SUSPEND, 0); 612 err: 613 hdev->power_enabled = false; 614 return ret; 615 } 616 617 static int venus_iface_msgq_read_nolock(struct venus_hfi_device *hdev, 618 void *pkt) 619 { 620 struct iface_queue *queue; 621 u32 tx_req; 622 int ret; 623 624 if (!venus_is_valid_state(hdev)) 625 return -EINVAL; 626 627 queue = &hdev->queues[IFACEQ_MSG_IDX]; 628 629 ret = venus_read_queue(hdev, queue, pkt, &tx_req); 630 if (ret) 631 return ret; 632 633 if (tx_req) 634 venus_soft_int(hdev); 635 636 return 0; 637 } 638 639 static int venus_iface_msgq_read(struct venus_hfi_device *hdev, void *pkt) 640 { 641 int ret; 642 643 mutex_lock(&hdev->lock); 644 ret = venus_iface_msgq_read_nolock(hdev, pkt); 645 mutex_unlock(&hdev->lock); 646 647 return ret; 648 } 649 650 static int venus_iface_dbgq_read_nolock(struct venus_hfi_device *hdev, 651 void *pkt) 652 { 653 struct iface_queue *queue; 654 u32 tx_req; 655 int ret; 656 657 ret = venus_is_valid_state(hdev); 658 if (!ret) 659 return -EINVAL; 660 661 queue = &hdev->queues[IFACEQ_DBG_IDX]; 662 663 ret = venus_read_queue(hdev, queue, pkt, &tx_req); 664 if (ret) 665 return ret; 666 667 if (tx_req) 668 venus_soft_int(hdev); 669 670 return 0; 671 } 672 673 static int venus_iface_dbgq_read(struct venus_hfi_device *hdev, void *pkt) 674 { 675 int ret; 676 677 if (!pkt) 678 return -EINVAL; 679 680 mutex_lock(&hdev->lock); 681 ret = venus_iface_dbgq_read_nolock(hdev, pkt); 682 mutex_unlock(&hdev->lock); 683 684 return ret; 685 } 686 687 static void venus_set_qhdr_defaults(struct hfi_queue_header *qhdr) 688 { 689 qhdr->status = 1; 690 qhdr->type = IFACEQ_DFLT_QHDR; 691 qhdr->q_size = IFACEQ_QUEUE_SIZE / 4; 692 qhdr->pkt_size = 0; 693 qhdr->rx_wm = 1; 694 qhdr->tx_wm = 1; 695 qhdr->rx_req = 1; 696 qhdr->tx_req = 0; 697 qhdr->rx_irq_status = 0; 698 qhdr->tx_irq_status = 0; 699 qhdr->read_idx = 0; 700 qhdr->write_idx = 0; 701 } 702 703 static void venus_interface_queues_release(struct venus_hfi_device *hdev) 704 { 705 mutex_lock(&hdev->lock); 706 707 venus_free(hdev, &hdev->ifaceq_table); 708 venus_free(hdev, &hdev->sfr); 709 710 memset(hdev->queues, 0, sizeof(hdev->queues)); 711 memset(&hdev->ifaceq_table, 0, sizeof(hdev->ifaceq_table)); 712 memset(&hdev->sfr, 0, sizeof(hdev->sfr)); 713 714 mutex_unlock(&hdev->lock); 715 } 716 717 static int venus_interface_queues_init(struct venus_hfi_device *hdev) 718 { 719 struct hfi_queue_table_header *tbl_hdr; 720 struct iface_queue *queue; 721 struct hfi_sfr *sfr; 722 struct mem_desc desc = {0}; 723 unsigned int offset; 724 unsigned int i; 725 int ret; 726 727 ret = venus_alloc(hdev, &desc, ALIGNED_QUEUE_SIZE); 728 if (ret) 729 return ret; 730 731 hdev->ifaceq_table = desc; 732 offset = IFACEQ_TABLE_SIZE; 733 734 for (i = 0; i < IFACEQ_NUM; i++) { 735 queue = &hdev->queues[i]; 736 queue->qmem.da = desc.da + offset; 737 queue->qmem.kva = desc.kva + offset; 738 queue->qmem.size = IFACEQ_QUEUE_SIZE; 739 offset += queue->qmem.size; 740 queue->qhdr = 741 IFACEQ_GET_QHDR_START_ADDR(hdev->ifaceq_table.kva, i); 742 743 venus_set_qhdr_defaults(queue->qhdr); 744 745 queue->qhdr->start_addr = queue->qmem.da; 746 747 if (i == IFACEQ_CMD_IDX) 748 queue->qhdr->type |= HFI_HOST_TO_CTRL_CMD_Q; 749 else if (i == IFACEQ_MSG_IDX) 750 queue->qhdr->type |= HFI_CTRL_TO_HOST_MSG_Q; 751 else if (i == IFACEQ_DBG_IDX) 752 queue->qhdr->type |= HFI_CTRL_TO_HOST_DBG_Q; 753 } 754 755 tbl_hdr = hdev->ifaceq_table.kva; 756 tbl_hdr->version = 0; 757 tbl_hdr->size = IFACEQ_TABLE_SIZE; 758 tbl_hdr->qhdr0_offset = sizeof(struct hfi_queue_table_header); 759 tbl_hdr->qhdr_size = sizeof(struct hfi_queue_header); 760 tbl_hdr->num_q = IFACEQ_NUM; 761 tbl_hdr->num_active_q = IFACEQ_NUM; 762 763 /* 764 * Set receive request to zero on debug queue as there is no 765 * need of interrupt from video hardware for debug messages 766 */ 767 queue = &hdev->queues[IFACEQ_DBG_IDX]; 768 queue->qhdr->rx_req = 0; 769 770 ret = venus_alloc(hdev, &desc, ALIGNED_SFR_SIZE); 771 if (ret) { 772 hdev->sfr.da = 0; 773 } else { 774 hdev->sfr = desc; 775 sfr = hdev->sfr.kva; 776 sfr->buf_size = ALIGNED_SFR_SIZE; 777 } 778 779 /* ensure table and queue header structs are settled in memory */ 780 wmb(); 781 782 return 0; 783 } 784 785 static int venus_sys_set_debug(struct venus_hfi_device *hdev, u32 debug) 786 { 787 struct hfi_sys_set_property_pkt *pkt; 788 u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE]; 789 int ret; 790 791 pkt = (struct hfi_sys_set_property_pkt *)packet; 792 793 pkt_sys_debug_config(pkt, HFI_DEBUG_MODE_QUEUE, debug); 794 795 ret = venus_iface_cmdq_write(hdev, pkt); 796 if (ret) 797 return ret; 798 799 return 0; 800 } 801 802 static int venus_sys_set_coverage(struct venus_hfi_device *hdev, u32 mode) 803 { 804 struct hfi_sys_set_property_pkt *pkt; 805 u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE]; 806 int ret; 807 808 pkt = (struct hfi_sys_set_property_pkt *)packet; 809 810 pkt_sys_coverage_config(pkt, mode); 811 812 ret = venus_iface_cmdq_write(hdev, pkt); 813 if (ret) 814 return ret; 815 816 return 0; 817 } 818 819 static int venus_sys_set_idle_message(struct venus_hfi_device *hdev, 820 bool enable) 821 { 822 struct hfi_sys_set_property_pkt *pkt; 823 u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE]; 824 int ret; 825 826 if (!enable) 827 return 0; 828 829 pkt = (struct hfi_sys_set_property_pkt *)packet; 830 831 pkt_sys_idle_indicator(pkt, enable); 832 833 ret = venus_iface_cmdq_write(hdev, pkt); 834 if (ret) 835 return ret; 836 837 return 0; 838 } 839 840 static int venus_sys_set_power_control(struct venus_hfi_device *hdev, 841 bool enable) 842 { 843 struct hfi_sys_set_property_pkt *pkt; 844 u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE]; 845 int ret; 846 847 pkt = (struct hfi_sys_set_property_pkt *)packet; 848 849 pkt_sys_power_control(pkt, enable); 850 851 ret = venus_iface_cmdq_write(hdev, pkt); 852 if (ret) 853 return ret; 854 855 return 0; 856 } 857 858 static int venus_get_queue_size(struct venus_hfi_device *hdev, 859 unsigned int index) 860 { 861 struct hfi_queue_header *qhdr; 862 863 if (index >= IFACEQ_NUM) 864 return -EINVAL; 865 866 qhdr = hdev->queues[index].qhdr; 867 if (!qhdr) 868 return -EINVAL; 869 870 return abs(qhdr->read_idx - qhdr->write_idx); 871 } 872 873 static int venus_sys_set_default_properties(struct venus_hfi_device *hdev) 874 { 875 struct device *dev = hdev->core->dev; 876 int ret; 877 878 ret = venus_sys_set_debug(hdev, venus_fw_debug); 879 if (ret) 880 dev_warn(dev, "setting fw debug msg ON failed (%d)\n", ret); 881 882 /* 883 * Idle indicator is disabled by default on some 4xx firmware versions, 884 * enable it explicitly in order to make suspend functional by checking 885 * WFI (wait-for-interrupt) bit. 886 */ 887 if (IS_V4(hdev->core)) 888 venus_sys_idle_indicator = true; 889 890 ret = venus_sys_set_idle_message(hdev, venus_sys_idle_indicator); 891 if (ret) 892 dev_warn(dev, "setting idle response ON failed (%d)\n", ret); 893 894 ret = venus_sys_set_power_control(hdev, venus_fw_low_power_mode); 895 if (ret) 896 dev_warn(dev, "setting hw power collapse ON failed (%d)\n", 897 ret); 898 899 return ret; 900 } 901 902 static int venus_session_cmd(struct venus_inst *inst, u32 pkt_type) 903 { 904 struct venus_hfi_device *hdev = to_hfi_priv(inst->core); 905 struct hfi_session_pkt pkt; 906 907 pkt_session_cmd(&pkt, pkt_type, inst); 908 909 return venus_iface_cmdq_write(hdev, &pkt); 910 } 911 912 static void venus_flush_debug_queue(struct venus_hfi_device *hdev) 913 { 914 struct device *dev = hdev->core->dev; 915 void *packet = hdev->dbg_buf; 916 917 while (!venus_iface_dbgq_read(hdev, packet)) { 918 struct hfi_msg_sys_coverage_pkt *pkt = packet; 919 920 if (pkt->hdr.pkt_type != HFI_MSG_SYS_COV) { 921 struct hfi_msg_sys_debug_pkt *pkt = packet; 922 923 dev_dbg(dev, "%s", pkt->msg_data); 924 } 925 } 926 } 927 928 static int venus_prepare_power_collapse(struct venus_hfi_device *hdev, 929 bool wait) 930 { 931 unsigned long timeout = msecs_to_jiffies(venus_hw_rsp_timeout); 932 struct hfi_sys_pc_prep_pkt pkt; 933 int ret; 934 935 init_completion(&hdev->pwr_collapse_prep); 936 937 pkt_sys_pc_prep(&pkt); 938 939 ret = venus_iface_cmdq_write(hdev, &pkt); 940 if (ret) 941 return ret; 942 943 if (!wait) 944 return 0; 945 946 ret = wait_for_completion_timeout(&hdev->pwr_collapse_prep, timeout); 947 if (!ret) { 948 venus_flush_debug_queue(hdev); 949 return -ETIMEDOUT; 950 } 951 952 return 0; 953 } 954 955 static int venus_are_queues_empty(struct venus_hfi_device *hdev) 956 { 957 int ret1, ret2; 958 959 ret1 = venus_get_queue_size(hdev, IFACEQ_MSG_IDX); 960 if (ret1 < 0) 961 return ret1; 962 963 ret2 = venus_get_queue_size(hdev, IFACEQ_CMD_IDX); 964 if (ret2 < 0) 965 return ret2; 966 967 if (!ret1 && !ret2) 968 return 1; 969 970 return 0; 971 } 972 973 static void venus_sfr_print(struct venus_hfi_device *hdev) 974 { 975 struct device *dev = hdev->core->dev; 976 struct hfi_sfr *sfr = hdev->sfr.kva; 977 void *p; 978 979 if (!sfr) 980 return; 981 982 p = memchr(sfr->data, '\0', sfr->buf_size); 983 /* 984 * SFR isn't guaranteed to be NULL terminated since SYS_ERROR indicates 985 * that Venus is in the process of crashing. 986 */ 987 if (!p) 988 sfr->data[sfr->buf_size - 1] = '\0'; 989 990 dev_err_ratelimited(dev, "SFR message from FW: %s\n", sfr->data); 991 } 992 993 static void venus_process_msg_sys_error(struct venus_hfi_device *hdev, 994 void *packet) 995 { 996 struct hfi_msg_event_notify_pkt *event_pkt = packet; 997 998 if (event_pkt->event_id != HFI_EVENT_SYS_ERROR) 999 return; 1000 1001 venus_set_state(hdev, VENUS_STATE_DEINIT); 1002 1003 /* 1004 * Once SYS_ERROR received from HW, it is safe to halt the AXI. 1005 * With SYS_ERROR, Venus FW may have crashed and HW might be 1006 * active and causing unnecessary transactions. Hence it is 1007 * safe to stop all AXI transactions from venus subsystem. 1008 */ 1009 venus_halt_axi(hdev); 1010 venus_sfr_print(hdev); 1011 } 1012 1013 static irqreturn_t venus_isr_thread(struct venus_core *core) 1014 { 1015 struct venus_hfi_device *hdev = to_hfi_priv(core); 1016 const struct venus_resources *res; 1017 void *pkt; 1018 u32 msg_ret; 1019 1020 if (!hdev) 1021 return IRQ_NONE; 1022 1023 res = hdev->core->res; 1024 pkt = hdev->pkt_buf; 1025 1026 if (hdev->irq_status & WRAPPER_INTR_STATUS_A2HWD_MASK) { 1027 venus_sfr_print(hdev); 1028 hfi_process_watchdog_timeout(core); 1029 } 1030 1031 while (!venus_iface_msgq_read(hdev, pkt)) { 1032 msg_ret = hfi_process_msg_packet(core, pkt); 1033 switch (msg_ret) { 1034 case HFI_MSG_EVENT_NOTIFY: 1035 venus_process_msg_sys_error(hdev, pkt); 1036 break; 1037 case HFI_MSG_SYS_INIT: 1038 venus_hfi_core_set_resource(core, res->vmem_id, 1039 res->vmem_size, 1040 res->vmem_addr, 1041 hdev); 1042 break; 1043 case HFI_MSG_SYS_RELEASE_RESOURCE: 1044 complete(&hdev->release_resource); 1045 break; 1046 case HFI_MSG_SYS_PC_PREP: 1047 complete(&hdev->pwr_collapse_prep); 1048 break; 1049 default: 1050 break; 1051 } 1052 } 1053 1054 venus_flush_debug_queue(hdev); 1055 1056 return IRQ_HANDLED; 1057 } 1058 1059 static irqreturn_t venus_isr(struct venus_core *core) 1060 { 1061 struct venus_hfi_device *hdev = to_hfi_priv(core); 1062 u32 status; 1063 1064 if (!hdev) 1065 return IRQ_NONE; 1066 1067 status = venus_readl(hdev, WRAPPER_INTR_STATUS); 1068 1069 if (status & WRAPPER_INTR_STATUS_A2H_MASK || 1070 status & WRAPPER_INTR_STATUS_A2HWD_MASK || 1071 status & CPU_CS_SCIACMDARG0_INIT_IDLE_MSG_MASK) 1072 hdev->irq_status = status; 1073 1074 venus_writel(hdev, CPU_CS_A2HSOFTINTCLR, 1); 1075 venus_writel(hdev, WRAPPER_INTR_CLEAR, status); 1076 1077 return IRQ_WAKE_THREAD; 1078 } 1079 1080 static int venus_core_init(struct venus_core *core) 1081 { 1082 struct venus_hfi_device *hdev = to_hfi_priv(core); 1083 struct device *dev = core->dev; 1084 struct hfi_sys_get_property_pkt version_pkt; 1085 struct hfi_sys_init_pkt pkt; 1086 int ret; 1087 1088 pkt_sys_init(&pkt, HFI_VIDEO_ARCH_OX); 1089 1090 venus_set_state(hdev, VENUS_STATE_INIT); 1091 1092 ret = venus_iface_cmdq_write(hdev, &pkt); 1093 if (ret) 1094 return ret; 1095 1096 pkt_sys_image_version(&version_pkt); 1097 1098 ret = venus_iface_cmdq_write(hdev, &version_pkt); 1099 if (ret) 1100 dev_warn(dev, "failed to send image version pkt to fw\n"); 1101 1102 ret = venus_sys_set_default_properties(hdev); 1103 if (ret) 1104 return ret; 1105 1106 return 0; 1107 } 1108 1109 static int venus_core_deinit(struct venus_core *core) 1110 { 1111 struct venus_hfi_device *hdev = to_hfi_priv(core); 1112 1113 venus_set_state(hdev, VENUS_STATE_DEINIT); 1114 hdev->suspended = true; 1115 hdev->power_enabled = false; 1116 1117 return 0; 1118 } 1119 1120 static int venus_core_ping(struct venus_core *core, u32 cookie) 1121 { 1122 struct venus_hfi_device *hdev = to_hfi_priv(core); 1123 struct hfi_sys_ping_pkt pkt; 1124 1125 pkt_sys_ping(&pkt, cookie); 1126 1127 return venus_iface_cmdq_write(hdev, &pkt); 1128 } 1129 1130 static int venus_core_trigger_ssr(struct venus_core *core, u32 trigger_type) 1131 { 1132 struct venus_hfi_device *hdev = to_hfi_priv(core); 1133 struct hfi_sys_test_ssr_pkt pkt; 1134 int ret; 1135 1136 ret = pkt_sys_ssr_cmd(&pkt, trigger_type); 1137 if (ret) 1138 return ret; 1139 1140 return venus_iface_cmdq_write(hdev, &pkt); 1141 } 1142 1143 static int venus_session_init(struct venus_inst *inst, u32 session_type, 1144 u32 codec) 1145 { 1146 struct venus_hfi_device *hdev = to_hfi_priv(inst->core); 1147 struct hfi_session_init_pkt pkt; 1148 int ret; 1149 1150 ret = pkt_session_init(&pkt, inst, session_type, codec); 1151 if (ret) 1152 goto err; 1153 1154 ret = venus_iface_cmdq_write(hdev, &pkt); 1155 if (ret) 1156 goto err; 1157 1158 return 0; 1159 1160 err: 1161 venus_flush_debug_queue(hdev); 1162 return ret; 1163 } 1164 1165 static int venus_session_end(struct venus_inst *inst) 1166 { 1167 struct venus_hfi_device *hdev = to_hfi_priv(inst->core); 1168 struct device *dev = hdev->core->dev; 1169 1170 if (venus_fw_coverage) { 1171 if (venus_sys_set_coverage(hdev, venus_fw_coverage)) 1172 dev_warn(dev, "fw coverage msg ON failed\n"); 1173 } 1174 1175 return venus_session_cmd(inst, HFI_CMD_SYS_SESSION_END); 1176 } 1177 1178 static int venus_session_abort(struct venus_inst *inst) 1179 { 1180 struct venus_hfi_device *hdev = to_hfi_priv(inst->core); 1181 1182 venus_flush_debug_queue(hdev); 1183 1184 return venus_session_cmd(inst, HFI_CMD_SYS_SESSION_ABORT); 1185 } 1186 1187 static int venus_session_flush(struct venus_inst *inst, u32 flush_mode) 1188 { 1189 struct venus_hfi_device *hdev = to_hfi_priv(inst->core); 1190 struct hfi_session_flush_pkt pkt; 1191 int ret; 1192 1193 ret = pkt_session_flush(&pkt, inst, flush_mode); 1194 if (ret) 1195 return ret; 1196 1197 return venus_iface_cmdq_write(hdev, &pkt); 1198 } 1199 1200 static int venus_session_start(struct venus_inst *inst) 1201 { 1202 return venus_session_cmd(inst, HFI_CMD_SESSION_START); 1203 } 1204 1205 static int venus_session_stop(struct venus_inst *inst) 1206 { 1207 return venus_session_cmd(inst, HFI_CMD_SESSION_STOP); 1208 } 1209 1210 static int venus_session_continue(struct venus_inst *inst) 1211 { 1212 return venus_session_cmd(inst, HFI_CMD_SESSION_CONTINUE); 1213 } 1214 1215 static int venus_session_etb(struct venus_inst *inst, 1216 struct hfi_frame_data *in_frame) 1217 { 1218 struct venus_hfi_device *hdev = to_hfi_priv(inst->core); 1219 u32 session_type = inst->session_type; 1220 int ret; 1221 1222 if (session_type == VIDC_SESSION_TYPE_DEC) { 1223 struct hfi_session_empty_buffer_compressed_pkt pkt; 1224 1225 ret = pkt_session_etb_decoder(&pkt, inst, in_frame); 1226 if (ret) 1227 return ret; 1228 1229 ret = venus_iface_cmdq_write(hdev, &pkt); 1230 } else if (session_type == VIDC_SESSION_TYPE_ENC) { 1231 struct hfi_session_empty_buffer_uncompressed_plane0_pkt pkt; 1232 1233 ret = pkt_session_etb_encoder(&pkt, inst, in_frame); 1234 if (ret) 1235 return ret; 1236 1237 ret = venus_iface_cmdq_write(hdev, &pkt); 1238 } else { 1239 ret = -EINVAL; 1240 } 1241 1242 return ret; 1243 } 1244 1245 static int venus_session_ftb(struct venus_inst *inst, 1246 struct hfi_frame_data *out_frame) 1247 { 1248 struct venus_hfi_device *hdev = to_hfi_priv(inst->core); 1249 struct hfi_session_fill_buffer_pkt pkt; 1250 int ret; 1251 1252 ret = pkt_session_ftb(&pkt, inst, out_frame); 1253 if (ret) 1254 return ret; 1255 1256 return venus_iface_cmdq_write(hdev, &pkt); 1257 } 1258 1259 static int venus_session_set_buffers(struct venus_inst *inst, 1260 struct hfi_buffer_desc *bd) 1261 { 1262 struct venus_hfi_device *hdev = to_hfi_priv(inst->core); 1263 struct hfi_session_set_buffers_pkt *pkt; 1264 u8 packet[IFACEQ_VAR_LARGE_PKT_SIZE]; 1265 int ret; 1266 1267 if (bd->buffer_type == HFI_BUFFER_INPUT) 1268 return 0; 1269 1270 pkt = (struct hfi_session_set_buffers_pkt *)packet; 1271 1272 ret = pkt_session_set_buffers(pkt, inst, bd); 1273 if (ret) 1274 return ret; 1275 1276 return venus_iface_cmdq_write(hdev, pkt); 1277 } 1278 1279 static int venus_session_unset_buffers(struct venus_inst *inst, 1280 struct hfi_buffer_desc *bd) 1281 { 1282 struct venus_hfi_device *hdev = to_hfi_priv(inst->core); 1283 struct hfi_session_release_buffer_pkt *pkt; 1284 u8 packet[IFACEQ_VAR_LARGE_PKT_SIZE]; 1285 int ret; 1286 1287 if (bd->buffer_type == HFI_BUFFER_INPUT) 1288 return 0; 1289 1290 pkt = (struct hfi_session_release_buffer_pkt *)packet; 1291 1292 ret = pkt_session_unset_buffers(pkt, inst, bd); 1293 if (ret) 1294 return ret; 1295 1296 return venus_iface_cmdq_write(hdev, pkt); 1297 } 1298 1299 static int venus_session_load_res(struct venus_inst *inst) 1300 { 1301 return venus_session_cmd(inst, HFI_CMD_SESSION_LOAD_RESOURCES); 1302 } 1303 1304 static int venus_session_release_res(struct venus_inst *inst) 1305 { 1306 return venus_session_cmd(inst, HFI_CMD_SESSION_RELEASE_RESOURCES); 1307 } 1308 1309 static int venus_session_parse_seq_hdr(struct venus_inst *inst, u32 seq_hdr, 1310 u32 seq_hdr_len) 1311 { 1312 struct venus_hfi_device *hdev = to_hfi_priv(inst->core); 1313 struct hfi_session_parse_sequence_header_pkt *pkt; 1314 u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE]; 1315 int ret; 1316 1317 pkt = (struct hfi_session_parse_sequence_header_pkt *)packet; 1318 1319 ret = pkt_session_parse_seq_header(pkt, inst, seq_hdr, seq_hdr_len); 1320 if (ret) 1321 return ret; 1322 1323 ret = venus_iface_cmdq_write(hdev, pkt); 1324 if (ret) 1325 return ret; 1326 1327 return 0; 1328 } 1329 1330 static int venus_session_get_seq_hdr(struct venus_inst *inst, u32 seq_hdr, 1331 u32 seq_hdr_len) 1332 { 1333 struct venus_hfi_device *hdev = to_hfi_priv(inst->core); 1334 struct hfi_session_get_sequence_header_pkt *pkt; 1335 u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE]; 1336 int ret; 1337 1338 pkt = (struct hfi_session_get_sequence_header_pkt *)packet; 1339 1340 ret = pkt_session_get_seq_hdr(pkt, inst, seq_hdr, seq_hdr_len); 1341 if (ret) 1342 return ret; 1343 1344 return venus_iface_cmdq_write(hdev, pkt); 1345 } 1346 1347 static int venus_session_set_property(struct venus_inst *inst, u32 ptype, 1348 void *pdata) 1349 { 1350 struct venus_hfi_device *hdev = to_hfi_priv(inst->core); 1351 struct hfi_session_set_property_pkt *pkt; 1352 u8 packet[IFACEQ_VAR_LARGE_PKT_SIZE]; 1353 int ret; 1354 1355 pkt = (struct hfi_session_set_property_pkt *)packet; 1356 1357 ret = pkt_session_set_property(pkt, inst, ptype, pdata); 1358 if (ret) 1359 return ret; 1360 1361 return venus_iface_cmdq_write(hdev, pkt); 1362 } 1363 1364 static int venus_session_get_property(struct venus_inst *inst, u32 ptype) 1365 { 1366 struct venus_hfi_device *hdev = to_hfi_priv(inst->core); 1367 struct hfi_session_get_property_pkt pkt; 1368 int ret; 1369 1370 ret = pkt_session_get_property(&pkt, inst, ptype); 1371 if (ret) 1372 return ret; 1373 1374 return venus_iface_cmdq_write(hdev, &pkt); 1375 } 1376 1377 static int venus_resume(struct venus_core *core) 1378 { 1379 struct venus_hfi_device *hdev = to_hfi_priv(core); 1380 int ret = 0; 1381 1382 mutex_lock(&hdev->lock); 1383 1384 if (!hdev->suspended) 1385 goto unlock; 1386 1387 ret = venus_power_on(hdev); 1388 1389 unlock: 1390 if (!ret) 1391 hdev->suspended = false; 1392 1393 mutex_unlock(&hdev->lock); 1394 1395 return ret; 1396 } 1397 1398 static int venus_suspend_1xx(struct venus_core *core) 1399 { 1400 struct venus_hfi_device *hdev = to_hfi_priv(core); 1401 struct device *dev = core->dev; 1402 u32 ctrl_status; 1403 int ret; 1404 1405 if (!hdev->power_enabled || hdev->suspended) 1406 return 0; 1407 1408 mutex_lock(&hdev->lock); 1409 ret = venus_is_valid_state(hdev); 1410 mutex_unlock(&hdev->lock); 1411 1412 if (!ret) { 1413 dev_err(dev, "bad state, cannot suspend\n"); 1414 return -EINVAL; 1415 } 1416 1417 ret = venus_prepare_power_collapse(hdev, true); 1418 if (ret) { 1419 dev_err(dev, "prepare for power collapse fail (%d)\n", ret); 1420 return ret; 1421 } 1422 1423 mutex_lock(&hdev->lock); 1424 1425 if (hdev->last_packet_type != HFI_CMD_SYS_PC_PREP) { 1426 mutex_unlock(&hdev->lock); 1427 return -EINVAL; 1428 } 1429 1430 ret = venus_are_queues_empty(hdev); 1431 if (ret < 0 || !ret) { 1432 mutex_unlock(&hdev->lock); 1433 return -EINVAL; 1434 } 1435 1436 ctrl_status = venus_readl(hdev, CPU_CS_SCIACMDARG0); 1437 if (!(ctrl_status & CPU_CS_SCIACMDARG0_PC_READY)) { 1438 mutex_unlock(&hdev->lock); 1439 return -EINVAL; 1440 } 1441 1442 ret = venus_power_off(hdev); 1443 if (ret) { 1444 mutex_unlock(&hdev->lock); 1445 return ret; 1446 } 1447 1448 hdev->suspended = true; 1449 1450 mutex_unlock(&hdev->lock); 1451 1452 return 0; 1453 } 1454 1455 static bool venus_cpu_and_video_core_idle(struct venus_hfi_device *hdev) 1456 { 1457 u32 ctrl_status, cpu_status; 1458 1459 cpu_status = venus_readl(hdev, WRAPPER_CPU_STATUS); 1460 ctrl_status = venus_readl(hdev, CPU_CS_SCIACMDARG0); 1461 1462 if (cpu_status & WRAPPER_CPU_STATUS_WFI && 1463 ctrl_status & CPU_CS_SCIACMDARG0_INIT_IDLE_MSG_MASK) 1464 return true; 1465 1466 return false; 1467 } 1468 1469 static bool venus_cpu_idle_and_pc_ready(struct venus_hfi_device *hdev) 1470 { 1471 u32 ctrl_status, cpu_status; 1472 1473 cpu_status = venus_readl(hdev, WRAPPER_CPU_STATUS); 1474 ctrl_status = venus_readl(hdev, CPU_CS_SCIACMDARG0); 1475 1476 if (cpu_status & WRAPPER_CPU_STATUS_WFI && 1477 ctrl_status & CPU_CS_SCIACMDARG0_PC_READY) 1478 return true; 1479 1480 return false; 1481 } 1482 1483 static int venus_suspend_3xx(struct venus_core *core) 1484 { 1485 struct venus_hfi_device *hdev = to_hfi_priv(core); 1486 struct device *dev = core->dev; 1487 bool val; 1488 int ret; 1489 1490 if (!hdev->power_enabled || hdev->suspended) 1491 return 0; 1492 1493 mutex_lock(&hdev->lock); 1494 ret = venus_is_valid_state(hdev); 1495 mutex_unlock(&hdev->lock); 1496 1497 if (!ret) { 1498 dev_err(dev, "bad state, cannot suspend\n"); 1499 return -EINVAL; 1500 } 1501 1502 /* 1503 * Power collapse sequence for Venus 3xx and 4xx versions: 1504 * 1. Check for ARM9 and video core to be idle by checking WFI bit 1505 * (bit 0) in CPU status register and by checking Idle (bit 30) in 1506 * Control status register for video core. 1507 * 2. Send a command to prepare for power collapse. 1508 * 3. Check for WFI and PC_READY bits. 1509 */ 1510 ret = readx_poll_timeout(venus_cpu_and_video_core_idle, hdev, val, val, 1511 1500, 100 * 1500); 1512 if (ret) 1513 return ret; 1514 1515 ret = venus_prepare_power_collapse(hdev, false); 1516 if (ret) { 1517 dev_err(dev, "prepare for power collapse fail (%d)\n", ret); 1518 return ret; 1519 } 1520 1521 ret = readx_poll_timeout(venus_cpu_idle_and_pc_ready, hdev, val, val, 1522 1500, 100 * 1500); 1523 if (ret) 1524 return ret; 1525 1526 mutex_lock(&hdev->lock); 1527 1528 ret = venus_power_off(hdev); 1529 if (ret) { 1530 dev_err(dev, "venus_power_off (%d)\n", ret); 1531 mutex_unlock(&hdev->lock); 1532 return ret; 1533 } 1534 1535 hdev->suspended = true; 1536 1537 mutex_unlock(&hdev->lock); 1538 1539 return 0; 1540 } 1541 1542 static int venus_suspend(struct venus_core *core) 1543 { 1544 if (IS_V3(core) || IS_V4(core)) 1545 return venus_suspend_3xx(core); 1546 1547 return venus_suspend_1xx(core); 1548 } 1549 1550 static const struct hfi_ops venus_hfi_ops = { 1551 .core_init = venus_core_init, 1552 .core_deinit = venus_core_deinit, 1553 .core_ping = venus_core_ping, 1554 .core_trigger_ssr = venus_core_trigger_ssr, 1555 1556 .session_init = venus_session_init, 1557 .session_end = venus_session_end, 1558 .session_abort = venus_session_abort, 1559 .session_flush = venus_session_flush, 1560 .session_start = venus_session_start, 1561 .session_stop = venus_session_stop, 1562 .session_continue = venus_session_continue, 1563 .session_etb = venus_session_etb, 1564 .session_ftb = venus_session_ftb, 1565 .session_set_buffers = venus_session_set_buffers, 1566 .session_unset_buffers = venus_session_unset_buffers, 1567 .session_load_res = venus_session_load_res, 1568 .session_release_res = venus_session_release_res, 1569 .session_parse_seq_hdr = venus_session_parse_seq_hdr, 1570 .session_get_seq_hdr = venus_session_get_seq_hdr, 1571 .session_set_property = venus_session_set_property, 1572 .session_get_property = venus_session_get_property, 1573 1574 .resume = venus_resume, 1575 .suspend = venus_suspend, 1576 1577 .isr = venus_isr, 1578 .isr_thread = venus_isr_thread, 1579 }; 1580 1581 void venus_hfi_destroy(struct venus_core *core) 1582 { 1583 struct venus_hfi_device *hdev = to_hfi_priv(core); 1584 1585 venus_interface_queues_release(hdev); 1586 mutex_destroy(&hdev->lock); 1587 kfree(hdev); 1588 core->priv = NULL; 1589 core->ops = NULL; 1590 } 1591 1592 int venus_hfi_create(struct venus_core *core) 1593 { 1594 struct venus_hfi_device *hdev; 1595 int ret; 1596 1597 hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); 1598 if (!hdev) 1599 return -ENOMEM; 1600 1601 mutex_init(&hdev->lock); 1602 1603 hdev->core = core; 1604 hdev->suspended = true; 1605 core->priv = hdev; 1606 core->ops = &venus_hfi_ops; 1607 core->core_caps = ENC_ROTATION_CAPABILITY | ENC_SCALING_CAPABILITY | 1608 ENC_DEINTERLACE_CAPABILITY | 1609 DEC_MULTI_STREAM_CAPABILITY; 1610 1611 ret = venus_interface_queues_init(hdev); 1612 if (ret) 1613 goto err_kfree; 1614 1615 return 0; 1616 1617 err_kfree: 1618 kfree(hdev); 1619 core->priv = NULL; 1620 core->ops = NULL; 1621 return ret; 1622 } 1623