#include #include #include #include #include #include #include #include #include #include #include #include #include #include "videodev2.h" #include #include "ivtv-ext-api.h" typedef unsigned long long W64; static inline W64 rdtsc() { W64 t; asm volatile("rdtsc" : "=A" (t)); return t; } inline int bit(unsigned int v, unsigned int i) { return (v >> i) & 1; } int get_state(int fd, struct ivtvfb_ioctl_state_info* state, struct ivtv_osd_coords* osd) { if (ioctl(fd, IVTVFB_IOCTL_GET_STATE, state) < 0) { fprintf(stderr, "IVTVFB_IOCTL_GET_STATE failed (error: %s)\n", strerror(errno)); return -2; } printf("Framebuffer state:\n"); printf(" Framebuffer state: %s\n", (state->status & IVTVFB_STATUS_ENABLED) ? "ON" : "off"); printf(" Global alpha: %s\n", (state->status & IVTVFB_STATUS_GLOBAL_ALPHA) ? "ENABLED" : "disabled"); printf(" Local alpha: %s\n", (state->status & IVTVFB_STATUS_LOCAL_ALPHA) ? "ENABLED" : "disabled"); printf(" Flicker reduction: %s\n", (state->status & IVTVFB_STATUS_FLICKER_REDUCTION) ? "ENABLED" : "disabled"); printf(" Global alpha value: %d\n", (int)state->alpha); if (ioctl(fd, IVTVFB_IOCTL_GET_ACTIVE_BUFFER, osd) < 0) { fprintf(stderr, "IVTVFB_IOCTL_GET_ACTIVE_BUFFER failed (error: %s)\n", strerror(errno)); return -2; } printf("Active buffer:\n"); printf(" Offset: 0x%08x\n", osd->offset); printf(" Maximum offset: 0x%08x\n", osd->max_offset); printf(" Horizontal stride: %d 32-bit words\n", osd->pixel_stride); printf(" Vertical lines: %d lines\n", osd->lines); printf(" Coordinates (x, y): %d, %d\n", osd->x, osd->y); printf("\n"); return 0; } //++MTY TODO This is specific to the CPU being tested! Get from /proc/cpuinfo, etc. instead... #define CPU_HZ (1.6*1000*1000*1000) void ivtv_frame_loop(int fd) { struct ivtvfb_ioctl_dma_host_to_ivtv_args args; int size = 720*480*4; char* buffer = (char*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, 0, 0); printf("frameloop: Mapped userspace buffer 0x%08x of %d bytes:\n", (unsigned long)buffer, size); fflush(stdout); int rc = mlock(buffer, size); printf("mlock rc = %d\n", rc); int val = 0; int iters = 1024; W64 tprev; int i; for (i = 0; i < iters; i++) { tprev = rdtsc(); //printf("%lld: (iter %d) filling userspace buffer...\n", tprev, i); memset(buffer, val & 0xff, size); val++; args.source = buffer; args.dest_offset = 0; args.count = size; //printf("%lld: (iter %d) Starting DMA...\n", rdtsc(), i); if (ioctl(fd, IVTVFB_IOCTL_PREP_FRAME, &args) < 0) { fprintf(stderr, "IVTVFB_IOCTL_PREP_DMA failed (error: %s)\n", strerror(errno)); return -3; } W64 tnow = rdtsc(); W64 tdiff = (tnow - tprev); float fps = (float)CPU_HZ / (float)tdiff; printf("iter %d: time = %f fps\n", i, fps); } } int main(int argc, char* argv[]) { if (argc < 2) { fprintf(stderr, "Syntax is:\n"); fprintf(stderr, " ivtvfbctl /dev/fbX [-on|-off] [-globalalpha|-noglobalalpha] [-localalpha|-nolocalalpha] [-flicker|-noflicker] [-alpha]\n"); return -1; } int fd; char* filename = argv[1]; if ((fd = open(filename, O_RDWR)) < 0) { fprintf(stderr, "Failed to open %s: %s\n", filename, strerror(errno)); return -2; } struct ivtvfb_ioctl_state_info state; struct ivtv_osd_coords osd; int rc = get_state(fd, &state, &osd); if (rc) return rc; int do_bltcopy = 0; int do_prep_dma = 0; int i; for (i = 2; i < argc; i++) { if (!strcmp(argv[i], "-on")) state.status |= IVTVFB_STATUS_ENABLED; else if (!strcmp(argv[i], "-off")) state.status &= ~IVTVFB_STATUS_ENABLED; else if (!strcmp(argv[i], "-globalalpha")) state.status |= IVTVFB_STATUS_GLOBAL_ALPHA; else if (!strcmp(argv[i], "-noglobalalpha")) state.status &= ~IVTVFB_STATUS_GLOBAL_ALPHA; else if (!strcmp(argv[i], "-localalpha")) state.status |= IVTVFB_STATUS_LOCAL_ALPHA; else if (!strcmp(argv[i], "-nolocalalpha")) state.status &= ~IVTVFB_STATUS_LOCAL_ALPHA; else if (!strcmp(argv[i], "-flicker")) state.status |= IVTVFB_STATUS_FLICKER_REDUCTION; else if (!strcmp(argv[i], "-noflicker")) state.status &= ~IVTVFB_STATUS_FLICKER_REDUCTION; else if (!strcmp(argv[i], "-alpha")) { if (++i >= argc) { fprintf(stderr, "Missing parameter to -alpha\n"); return -3; } state.alpha = strtol(argv[i], NULL, 0); } else if (!strcmp(argv[i], "-osdoffset")) { if (++i >= argc) { fprintf(stderr, "Missing parameter to -osdoffset\n"); return -3; } osd.offset = strtol(argv[i], NULL, 0); } else if (!strcmp(argv[i], "-osdstride")) { if (++i >= argc) { fprintf(stderr, "Missing parameter to -osdstride\n"); return -3; } osd.pixel_stride = strtol(argv[i], NULL, 0); } else if (!strcmp(argv[i], "-osdlines")) { if (++i >= argc) { fprintf(stderr, "Missing parameter to -osdline\n"); return -3; } osd.lines = strtol(argv[i], NULL, 0); } else if (!strcmp(argv[i], "-osdx")) { if (++i >= argc) { fprintf(stderr, "Missing parameter to -osdx\n"); return -3; } osd.x = strtol(argv[i], NULL, 0); } else if (!strcmp(argv[i], "-osdy")) { if (++i >= argc) { fprintf(stderr, "Missing parameter to -osdy\n"); return -3; } osd.y = strtol(argv[i], NULL, 0); } else if (!strcmp(argv[i], "-bltcopy")) { do_bltcopy = 1; } else if (!strcmp(argv[i], "-prepdma")) { do_prep_dma = 1; } else { fprintf(stderr, "Invalid option '%s'\n", argv[i]); return -3; } } if (do_bltcopy) { printf("ivtvfbctl: Doing BLT copy...\n"); fflush(stdout); struct ivtvfb_ioctl_blt_copy_args args; args.x = 50; args.y = 50; args.width = 620; args.height = 380; args.source_offset = 0; args.source_stride = 720; if (ioctl(fd, IVTVFB_IOCTL_BLT_COPY, &args) < 0) { fprintf(stderr, "%s: IVTVFB_IOCTL_BLT_COPY failed (error: %s)\n", filename, strerror(errno)); return -3; } } else if (do_prep_dma) { ivtv_frame_loop(fd); } else { if (ioctl(fd, IVTVFB_IOCTL_SET_STATE, &state) < 0) { fprintf(stderr, "%s: IVTVFB_IOCTL_SET_STATE failed (error: %s)\n", filename, strerror(errno)); return -3; } if (ioctl(fd, IVTVFB_IOCTL_SET_ACTIVE_BUFFER, &osd) < 0) { fprintf(stderr, "%s: IVTVFB_IOCTL_SET_ACTIVE_BUFFER failed (error: %s)\n", filename, strerror(errno)); return -3; } } rc = get_state(fd, &state, &osd); if (rc) return rc; close(fd); return 0; }