// File: /workspace/github_c_makefile_star2_O1/xiane[P]libvphevcodec/AML_HEVCEncoder.cpp
// Function: Wave4VpuInit(AMVHEVCEncHandle_s*, unsigned int)
AMVEnc_Status Wave4VpuInit(AMVHEVCEncHandle *Handle, Uint32 coreIdx) {
    vpu_buffer_t vb;
    Uint32 codeBase;
    Uint32* codeVaddr;
    Uint32 codeSize;
    Uint32 size;
    Uint32 i, regVal, remapSize;
    Uint32 hwOption = 0;
    uint32_t timeoutTicks = 0;

    vdi_get_common_memory(coreIdx, &vb);

    vdi_clear_memory(coreIdx, vb.phys_addr, vb.size);

    VLOG(DEBUG, "\nvdi_get_common_memory, paddr:0x%08lx\n", vb.phys_addr);

    codeSize = (vb.size & ~0xfff);

    size = sizeof(bit_code);
    if (size == 0 || size >= codeSize) {
        return AMVENC_INVALID_PARAM;
    }

    VLOG(DEBUG, "\nmonet.bin size :%d!!!\n", size);
    codeBase = (Uint32) vb.phys_addr;

    codeVaddr = (Uint32*) vb.virt_addr;

    VLOG(DEBUG, "\nVPU INIT Start!!!\n");

    //for (i=W4_CMD_REG_BASE; i<W4_CMD_REG_END; i+=4)
    //    VpuWriteReg(coreIdx, i, 0x00);

    VpuWriteMem(coreIdx, codeBase, (unsigned char* )bit_code, size);
    VLOG(DEBUG, "Code: 0x%08x, 0x%08x,0x%08x,0x%08x,\n", codeVaddr[0], codeVaddr[1], codeVaddr[2], codeVaddr[3]);
    vdi_set_bit_firmware_to_pm(coreIdx, (Uint16*) bit_code);

    regVal = 0;
    VpuWriteReg(coreIdx, W4_PO_CONF, regVal);

    regVal = VpuReadReg(coreIdx, W4_VPU_RESET_STATUS);
    VLOG(NONE, "W4_VPU_RESET_STATUS :0x%x\n", regVal);

    /* Reset All blocks */
    regVal = 0x7ffffff;
    VpuWriteReg(coreIdx, W4_VPU_RESET_REQ, regVal);    // Reset All blocks
    /* Waiting reset done */

    regVal = VpuReadReg(coreIdx, W4_VPU_RESET_STATUS);
    VLOG(NONE, "W4_VPU_RESET_STATUS :0x%x\n", regVal);

    if (vdi_wait_vpu_busy(coreIdx, VPU_BUSY_CHECK_TIMEOUT, W4_VPU_RESET_STATUS) == -1) {
        VLOG(ERR, "VPU init(W4_VPU_RESET_REQ) timeout\n");
        VpuWriteReg(coreIdx, W4_VPU_RESET_REQ, 0);
        return AMVENC_TIMEOUT;
    }

    VpuWriteReg(coreIdx, W4_VPU_RESET_REQ, 0);

    /* clear registers */
    for (i = W4_CMD_REG_BASE; i < W4_CMD_REG_END; i += 4)
        VpuWriteReg(coreIdx, i, 0x00);

    /* remap page size */
    remapSize = (codeSize >> 12) & 0x1ff;
    regVal = 0x80000000 | (0 << 16) | (W4_REMAP_CODE_INDEX << 12) | (1 << 11) | remapSize;
    VpuWriteReg(coreIdx, W4_VPU_REMAP_CTRL, regVal);
    VpuWriteReg(coreIdx, W4_VPU_REMAP_VADDR, 0x00000000); /* DO NOT CHANGE! */
    VpuWriteReg(coreIdx, W4_VPU_REMAP_PADDR, codeBase);
    VpuWriteReg(coreIdx, W4_ADDR_CODE_BASE, codeBase);
    VpuWriteReg(coreIdx, W4_CODE_SIZE, codeSize);
    VpuWriteReg(coreIdx, W4_CODE_PARAM, 0);

    regVal = VpuReadReg(coreIdx, W4_VPU_REMAP_PADDR);
    VLOG(NONE, "W4_VPU_REMAP_PADDR :0x%x\n", regVal);

    VpuWriteReg(coreIdx, W4_COMMAND_OPTION, 0);
    timeoutTicks = COMMAND_TIMEOUT * VCPU_CLOCK_IN_MHZ * (1000000 >> 15);
    timeoutTicks = timeoutTicks / 120;
    if (Handle->enc_width * Handle->enc_height <= 1280 * 720)
        timeoutTicks = timeoutTicks / 16; //  /8 == 20ms  /4 == 40 ms  /16 == 10ms
    else if (Handle->enc_width * Handle->enc_height <= 1920 * 1088)
        timeoutTicks = timeoutTicks / 8;
    else
        timeoutTicks = timeoutTicks / 2;
    VpuWriteReg(coreIdx, W4_TIMEOUT_CNT, timeoutTicks);

    VpuWriteReg(coreIdx, W4_HW_OPTION, hwOption);
    /* Interrupt */
    // for encoder interrupt
    regVal = (1 << W4_INT_ENC_PIC);
    regVal |= (1 << W4_INT_SLEEP_VPU);
    regVal |= (1 << W4_INT_SET_PARAM);
    // for decoder interrupt
    regVal |= (1 << W4_INT_DEC_PIC_HDR);
    regVal |= (1 << W4_INT_DEC_PIC);
    regVal |= (1 << W4_INT_QUERY_DEC);
    regVal |= (1 << W4_INT_SLEEP_VPU);
    regVal |= (1 << W4_INT_BSBUF_EMPTY);

    //regVal = 0xfffffefe;
    regVal = 0xfffff6ff; // remove wake up int bit 11
    VpuWriteReg(coreIdx, W4_VPU_VINT_ENABLE, regVal);

    VpuWriteReg(coreIdx, W4_VPU_BUSY_STATUS, 1);
    VpuWriteReg(coreIdx, W4_RET_SUCCESS, 0);  //for debug
    VpuWriteReg(coreIdx, W4_CORE_INDEX, 0);
    //VpuWriteReg(coreIdx, W4_INST_INDEX,  (instanceIndex&0xffff)|(codecMode<<16));
    VpuWriteReg(coreIdx, W4_INST_INDEX, 0);

    VpuWriteReg(coreIdx, W4_COMMAND, INIT_VPU);
    VpuWriteReg(coreIdx, W4_VPU_HOST_INT_REQ, 1);
    //Wave4BitIssueCommand(coreIdx,0, INIT_VPU);
    VpuWriteReg(coreIdx, W4_VPU_REMAP_CORE_START, 1);

    regVal = VpuReadReg(coreIdx, W4_VPU_BUSY_STATUS);
    VLOG(NONE, "W4_VPU_BUSY_STATUS :0x%x\n", regVal);

    //if (vdi_wait_vpu_busy(coreIdx, VPU_BUSY_CHECK_TIMEOUT, W4_VPU_BUSY_STATUS) == -1) {
    //    VLOG(ERR, "VPU init(W4_VPU_REMAP_CORE_START) timeout\n");
    //    return AMVENC_TIMEOUT;
    //}

    if (vdi_wait_interrupt(coreIdx, VPU_BUSY_CHECK_TIMEOUT) == -1) {
        VLOG(ERR, "VPU Wake timeout");
        reset_error = 1;
        return AMVENC_TIMEOUT;
    }

    regVal = VpuReadReg(coreIdx, W4_VCPU_CUR_PC);
    VLOG(NONE, "Cur PC :0x%x\n", regVal);
    regVal = VpuReadReg(coreIdx, W4_RET_SUCCESS);
    VLOG(DEBUG, "W4_RET_SUCCESS :0x%x\n", regVal);
    if (regVal == 0) {
        uint32_t reasonCode = VpuReadReg(coreIdx, W4_RET_FAIL_REASON);
        VLOG(ERR, "VPU init(W4_RET_SUCCESS) failed(%d) REASON CODE(%08x)\n", regVal, reasonCode);
        return AMVENC_HARDWARE;
    }

    VpuWriteReg(coreIdx, W4_VPU_BUSY_STATUS, 1);
    VpuWriteReg(coreIdx, W4_RET_SUCCESS, 0);  //for debug
    VpuWriteReg(coreIdx, W4_CORE_INDEX, 0);
    //VpuWriteReg(coreIdx, W4_INST_INDEX,  (instanceIndex&0xffff)|(codecMode<<16));

    VpuWriteReg(coreIdx, W4_COMMAND, GET_FW_VERSION);
    VpuWriteReg(coreIdx, W4_VPU_HOST_INT_REQ, 1);
    //Wave4BitIssueCommand(coreIdx, 0, GET_FW_VERSION);
    regVal = VpuReadReg(coreIdx, W4_VPU_BUSY_STATUS);
    VLOG(NONE, "W4_VPU_BUSY_STATUS :0x%x\n", regVal);
    if (vdi_wait_vpu_busy(coreIdx, VPU_BUSY_CHECK_TIMEOUT, W4_VPU_BUSY_STATUS) == -1) {
        VLOG(ERR, "VPU init(GET_FW_VERSION) timeout\n");
        return AMVENC_TIMEOUT;
    }
    regVal = VpuReadReg(coreIdx, W4_RET_SUCCESS);
    VLOG(NONE, "W4_RET_SUCCESS :0x%x\n", regVal);
    if (regVal == 0) {
        uint32_t reasonCode = VpuReadReg(coreIdx, W4_RET_FAIL_REASON);
        VLOG(ERR, "VPU init(GET_FW_VERSION) failed(%d) REASON CODE(%08x)\n", regVal, reasonCode);
        return AMVENC_HARDWARE;
    }

    regVal = VpuReadReg(coreIdx, W4_RET_PRODUCT_NAME);
    VLOG(DEBUG, "Product name %s\n", (Uint8*) &regVal);
    regVal = VpuReadReg(coreIdx, W4_RET_PRODUCT_VERSION);
    VLOG(DEBUG, "Product ver %x\n", regVal);

    regVal = VpuReadReg(coreIdx, W4_RET_STD_DEF0);
    VLOG(DEBUG, "Product W4_RET_STD_DEF0 %x\n", regVal);
    regVal = VpuReadReg(coreIdx, W4_RET_STD_DEF1);
    VLOG(DEBUG, "Product W4_RET_STD_DEF1 %x\n", regVal);
    regVal = VpuReadReg(coreIdx, W4_RET_CONF_FEATURE);
    VLOG(DEBUG, "Product W4_RET_CONF_FEATURE %x\n", regVal);
    regVal = VpuReadReg(coreIdx, W4_RET_CONFIG_DATE);
    VLOG(DEBUG, "Product W4_RET_CONFIG_DATE %x\n", regVal);
    regVal = VpuReadReg(coreIdx, W4_RET_CONFIG_REVISION);
    VLOG(DEBUG, "Product W4_RET_CONFIG_REVISION %x\n", regVal);
    regVal = VpuReadReg(coreIdx, W4_RET_CONFIG_TYPE);
    VLOG(DEBUG, "Product W4_RET_CONFIG_TYPE %x\n", regVal);

    regVal = VpuReadReg(coreIdx, W4_VPU_BUSY_STATUS);
    VLOG(DEBUG, "W4_VPU_BUSY_STATUS :0x%x\n", regVal);

    if (vdi_wait_vpu_busy(coreIdx, VPU_BUSY_CHECK_TIMEOUT, W4_VPU_BUSY_STATUS) == -1) {
        VLOG(ERR, "VPU init(Finish) timeout\n");
        return AMVENC_TIMEOUT;
    }
    return AMVENC_SUCCESS;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movl %esi, %ebx
movq %rdi, %r14
leaq 0x8(%rsp), %r15
movl %esi, %edi
movq %r15, %rsi
callq 0x2180
movl (%r15), %edx
movl 0x8(%r15), %esi
movl %ebx, %edi
callq 0x2160
movl (%r15), %r12d
movl %r12d, %ebp
andl $0xfffff000, %ebp       # imm = 0xFFFFF000
movl $0xffffffda, %eax       # imm = 0xFFFFFFDA
cmpl $0x22881, %ebp          # imm = 0x22881
jb 0x4c48
movl 0x10(%rsp), %r15d
leaq 0x47c1(%rip), %r13      # 0x9028
movl %ebx, %edi
movl %r15d, %esi
movq %r13, %rdx
movl $0x22880, %ecx          # imm = 0x22880
callq 0x2110
movl %ebx, %edi
movq %r13, %rsi
callq 0x2290
movl %ebx, %edi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2150
movl %ebx, %edi
movl $0x54, %esi
callq 0x2200
movl %ebx, %edi
movl $0x50, %esi
movl $0x7ffffff, %edx        # imm = 0x7FFFFFF
callq 0x2150
movl %ebx, %edi
movl $0x54, %esi
callq 0x2200
movl %ebx, %edi
movl $0x1388, %esi           # imm = 0x1388
movl $0x54, %edx
callq 0x2060
cmpl $-0x1, %eax
je 0x4ba2
movl %ebx, %edi
movl $0x50, %esi
xorl %edx, %edx
callq 0x2150
movl $0xfc, %r13d
addl $0x4, %r13d
movl %ebx, %edi
movl %r13d, %esi
xorl %edx, %edx
callq 0x2150
cmpl $0x1fc, %r13d           # imm = 0x1FC
jb 0x48e5
shrl $0xc, %r12d
andl $0x1ff, %r12d           # imm = 0x1FF
orl $0x80000800, %r12d      # imm = 0x80000800
movl %ebx, %edi
movl $0x60, %esi
movl %r12d, %edx
callq 0x2150
movl %ebx, %edi
movl $0x64, %esi
xorl %edx, %edx
callq 0x2150
movl %ebx, %edi
movl $0x68, %esi
movl %r15d, %edx
callq 0x2150
movl %ebx, %edi
movl $0x118, %esi            # imm = 0x118
movl %r15d, %edx
callq 0x2150
movl %ebx, %edi
movl $0x11c, %esi            # imm = 0x11C
movl %ebp, %edx
callq 0x2150
movl %ebx, %edi
movl $0x120, %esi            # imm = 0x120
xorl %edx, %edx
callq 0x2150
movl %ebx, %edi
movl $0x68, %esi
callq 0x2200
movl %ebx, %edi
movl $0x10c, %esi            # imm = 0x10C
xorl %edx, %edx
callq 0x2150
movl 0x10(%r14), %eax
imull 0xc(%r14), %eax
cmpl $0x1fe001, %eax         # imm = 0x1FE001
movl $0xfa, %ecx
movl $0x3e8, %esi            # imm = 0x3E8
cmovbl %ecx, %esi
cmpl $0xe1001, %eax          # imm = 0xE1001
movl $0x7d, %edx
cmovael %esi, %edx
movl %ebx, %edi
movl $0x134, %esi            # imm = 0x134
callq 0x2150
movl %ebx, %edi
movl $0x124, %esi            # imm = 0x124
xorl %edx, %edx
callq 0x2150
movl %ebx, %edi
movl $0x48, %esi
movl $0xfffff6ff, %edx       # imm = 0xFFFFF6FF
callq 0x2150
movl %ebx, %edi
movl $0x70, %esi
movl $0x1, %edx
callq 0x2150
movl %ebx, %edi
movl $0x110, %esi            # imm = 0x110
xorl %edx, %edx
callq 0x2150
movl %ebx, %edi
movl $0x104, %esi            # imm = 0x104
xorl %edx, %edx
callq 0x2150
movl %ebx, %edi
movl $0x108, %esi            # imm = 0x108
xorl %edx, %edx
callq 0x2150
movl %ebx, %edi
movl $0x100, %esi            # imm = 0x100
movl $0x1, %edx
callq 0x2150
movl %ebx, %edi
movl $0x38, %esi
movl $0x1, %edx
callq 0x2150
movl %ebx, %edi
movl $0x6c, %esi
movl $0x1, %edx
callq 0x2150
movl %ebx, %edi
movl $0x70, %esi
callq 0x2200
movl %ebx, %edi
movl $0x1388, %esi           # imm = 0x1388
callq 0x2340
cmpl $-0x1, %eax
je 0x4bc8
movl %ebx, %edi
movl $0x4, %esi
callq 0x2200
movl %ebx, %edi
movl $0x110, %esi            # imm = 0x110
callq 0x2200
testl %eax, %eax
je 0x4be9
movl %ebx, %edi
movl $0x70, %esi
movl $0x1, %edx
callq 0x2150
movl %ebx, %edi
movl $0x110, %esi            # imm = 0x110
xorl %edx, %edx
callq 0x2150
movl %ebx, %edi
movl $0x104, %esi            # imm = 0x104
xorl %edx, %edx
callq 0x2150
movl %ebx, %edi
movl $0x100, %esi            # imm = 0x100
movl $0x100, %edx            # imm = 0x100
callq 0x2150
movl %ebx, %edi
movl $0x38, %esi
movl $0x1, %edx
callq 0x2150
movl %ebx, %edi
movl $0x70, %esi
callq 0x2200
movl %ebx, %edi
movl $0x1388, %esi           # imm = 0x1388
movl $0x70, %edx
callq 0x2060
cmpl $-0x1, %eax
je 0x4bfe
movl %ebx, %edi
movl $0x110, %esi            # imm = 0x110
callq 0x2200
testl %eax, %eax
je 0x4c1b
movl %ebx, %edi
movl $0x11c, %esi            # imm = 0x11C
callq 0x2200
movl %ebx, %edi
movl $0x120, %esi            # imm = 0x120
callq 0x2200
movl %ebx, %edi
movl $0x124, %esi            # imm = 0x124
callq 0x2200
movl %ebx, %edi
movl $0x128, %esi            # imm = 0x128
callq 0x2200
movl %ebx, %edi
movl $0x12c, %esi            # imm = 0x12C
callq 0x2200
movl %ebx, %edi
movl $0x130, %esi            # imm = 0x130
callq 0x2200
movl %ebx, %edi
movl $0x134, %esi            # imm = 0x134
callq 0x2200
movl %ebx, %edi
movl $0x138, %esi            # imm = 0x138
callq 0x2200
movl %ebx, %edi
movl $0x70, %esi
callq 0x2200
movl %ebx, %edi
movl $0x1388, %esi           # imm = 0x1388
movl $0x70, %edx
callq 0x2060
movl %eax, %ecx
movl $0x1, %eax
cmpl $-0x1, %ecx
jne 0x4c48
leaq 0x2844a(%rip), %rdi     # 0x2cfea
jmp 0x4c05
leaq 0x2847b(%rip), %rdi     # 0x2d024
callq 0x2280
movl $0xa, %edi
callq 0x2220
movl %ebx, %edi
movl $0x50, %esi
xorl %edx, %edx
callq 0x2150
jmp 0x4c14
leaq 0x28188(%rip), %rdi     # 0x2cd57
xorl %eax, %eax
callq 0x2050
movl $0xa, %edi
callq 0x2220
movb $0x1, 0x2b5ed(%rip)     # 0x301d4
jmp 0x4c14
movl %ebx, %edi
movl $0x114, %esi            # imm = 0x114
callq 0x2200
leaq 0x281c0(%rip), %rdi     # 0x2cdbc
jmp 0x4c2e
leaq 0x283fe(%rip), %rdi     # 0x2d003
callq 0x2280
movl $0xa, %edi
callq 0x2220
movl $0xffffffdc, %eax       # imm = 0xFFFFFFDC
jmp 0x4c48
movl %ebx, %edi
movl $0x114, %esi            # imm = 0x114
callq 0x2200
leaq 0x281c5(%rip), %rdi     # 0x2cdf3
xorl %esi, %esi
movl %eax, %edx
xorl %eax, %eax
callq 0x2050
movl $0xa, %edi
callq 0x2220
movl $0xffffffdb, %eax       # imm = 0xFFFFFFDB
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq