unsigned gpu_fft_base_exec(struct GPU_FFT_BASE *base, int num_qpus) { unsigned rc; base->peri[V3D_PCTRE] |= 0x80000000; if (base->vc_msg) { // Use mailbox // Returns: 0x0 for success; 0x80000000 for timeout rc = execute_qpu(base->mb, num_qpus, base->vc_msg, GPU_FFT_NO_FLUSH, GPU_FFT_TIMEOUT); } else { // Direct register poking rc = gpu_fft_base_exec_direct(base, num_qpus); } base->peri[V3D_PCTRE] &= ~0x80000000; return rc; }
int main(int argc, char *argv[]) { int mb = mbox_open(); /* Enable QPU for execution */ int qpu_enabled = !qpu_enable(mb, 1); if (!qpu_enabled) { printf("Unable to enable QPU. Check your firmware is latest."); goto cleanup; } /* Allocate GPU memory and map it into ARM address space */ unsigned size = 4096; unsigned align = 4096; unsigned handle = mem_alloc(mb, size, align, GPU_MEM_FLG); if (!handle) { printf("Failed to allocate GPU memory."); goto cleanup; } void *gpu_pointer = (void *)mem_lock(mb, handle); void *arm_pointer = mapmem((unsigned)gpu_pointer+GPU_MEM_MAP, size); unsigned *p = (unsigned *)arm_pointer; /* +---------------+ <----+ | QPU Code | | | ... | | +---------------+ <--+ | | Uniforms | | | +---------------+ | | | QPU0 Uniform -----+ | | QPU0 Start -------+ | ... | | QPUn Uniform | | QPUn PC -------+ +---------------+ */ /* Copy QPU program into GPU memory */ unsigned *qpu_code = p; memcpy(p, program, sizeof program); p += (sizeof program)/(sizeof program[0]); /* Build Uniforms */ unsigned *qpu_uniform = p; *p++ = 1; /* Build QPU Launch messages */ unsigned *qpu_msg = p; *p++ = as_gpu_address(qpu_uniform); *p++ = as_gpu_address(qpu_code); int i; for (i=0; i<16+1+2; i++) { printf("%08x: %08x\n", gpu_pointer+i*4, ((unsigned *)arm_pointer)[i]); } printf("qpu exec %08x\n", gpu_pointer + ((void *)qpu_msg - arm_pointer)); /* Launch QPU program and block till its done */ unsigned r = execute_qpu(mb, GPU_QPUS, as_gpu_address(qpu_msg), 1, 10000); printf("%d\n", r); cleanup: /* Release GPU memory */ if (arm_pointer) { unmapmem(arm_pointer, size); } if (handle) { mem_unlock(mb, handle); mem_free(mb, handle); } /* Release QPU */ if (qpu_enabled) { qpu_enable(mb, 0); } /* Release mailbox */ mbox_close(mb); }