void gpu_fft_base_release(struct GPU_FFT_BASE *base) { int mb = base->mb; unsigned handle = base->handle, size = base->size; unmapmem((void*)base->peri, base->peri_size); unmapmem((void*)base, size); mem_unlock(mb, handle); mem_free(mb, handle); qpu_enable(mb, 0); }
int gpu_fft_alloc(int mb, unsigned size, struct GPU_FFT_PTR *ptr) { struct GPU_FFT_HOST host; struct GPU_FFT_BASE *base; volatile unsigned *peri; unsigned handle; if (gpu_fft_get_host_info(&host)) return -5; if (qpu_enable(mb, 1)) return -1; // Shared memory handle = mem_alloc(mb, size, 4096, host.mem_flg); if (!handle) { qpu_enable(mb, 0); return -3; } peri = (volatile unsigned *)mapmem(host.peri_addr, host.peri_size); if (!peri) { mem_free(mb, handle); qpu_enable(mb, 0); return -4; } ptr->vc = mem_lock(mb, handle); ptr->arm.vptr = mapmem(BUS_TO_PHYS(ptr->vc + host.mem_map), size); base = (struct GPU_FFT_BASE *)ptr->arm.vptr; base->peri = peri; base->peri_size = host.peri_size; base->mb = mb; base->handle = handle; base->size = size; return 0; }
int main(int argc, char **argv) { mbox = mbox_open(); // The blob now has this nice handy call which powers up the v3d pipeline. qpu_enable(mbox, 1); // map v3d's registers into our address space. v3d = (unsigned *) mapmem(0x20c00000, 0x1000); if(v3d[V3D_IDENT0] != 0x02443356) { // Magic number. printf("Error: V3D pipeline isn't powered up and accessable.\n"); exit(-1); } // We now have access to the v3d registers, we should do something. testTriangle(); return 0; }
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); }