X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=gp2x%2Fpollux_dpc_set.c;fp=gp2x%2Fpollux_dpc_set.c;h=beddc21bbfb7855f4aee7139cd7056d753f646d7;hb=e8f5db5d5a80a62069354466c64a9b90a2ced47c;hp=0000000000000000000000000000000000000000;hpb=c872443f88bd037784f795767041db9e307ac3f0;p=gpsp.git diff --git a/gp2x/pollux_dpc_set.c b/gp2x/pollux_dpc_set.c new file mode 100644 index 0000000..beddc21 --- /dev/null +++ b/gp2x/pollux_dpc_set.c @@ -0,0 +1,168 @@ +/* + * quick tool to set LCD timings for Wiz + * (c) notaz, 2009 + * code dedicated to public domain. + * + * HTOTAL: X VTOTAL: 341 + * HSWIDTH: 1 VSWIDTH: 0 + * HASTART: 37 VASTART: 17 + * HAEND: 277 VAEND: 337 + * + * 120Hz + * pcd 8, 447: + 594us + * pcd 9, 397: + 36us + * pcd 10, 357: - 523us + * pcd 11, 325: +1153us + * + * 'lcd_timings=397,1,37,277,341,0,17,337;clkdiv0=9' + */ + +#include +#include +#include +#include "pollux_dpc_set.h" + +/* + * set LCD timings based on preformated string (see usage() below for params). + * returns 0 on success. + */ +int pollux_dpc_set(volatile unsigned short *memregs, const char *str) +{ + int timings[8], have_timings = 0; + int pcd = 0, have_pcd = 0; + const char *p; + int i, ret; + + if (str == NULL) + return -1; + + p = str; + while (1) + { + if (strncmp(p, "lcd_timings=", 12) == 0) + { + int c; + p += 12; + ret = sscanf(p, "%d,%d,%d,%d,%d,%d,%d,%d", + &timings[0], &timings[1], &timings[2], &timings[3], + &timings[4], &timings[5], &timings[6], &timings[7]); + if (ret != 8) + break; + /* skip seven commas */ + for (c = 0; c < 7 && *p != 0; p++) + if (*p == ',') + c++; + if (c != 7) + break; + /* skip last number */ + while ('0' <= *p && *p <= '9') + p++; + have_timings = 1; + } + else if (strncmp(p, "clkdiv0=", 8) == 0) + { + char *ep; + p += 8; + pcd = strtoul(p, &ep, 10); + if (p == ep) + break; + p = ep; + have_pcd = 1; + } + else + break; + + while (*p == ';' || *p == ' ') + p++; + if (*p == 0) + goto parse_done; + } + + fprintf(stderr, "dpc_set parser: error at '%s'\n", p); + return -1; + +parse_done: + /* some validation */ + if (have_timings) + { + for (i = 0; i < 8; i++) + if (timings[i] & ~0xffff) { + fprintf(stderr, "dpc_set: invalid timing %d: %d\n", i, timings[i]); + return -1; + } + } + + if (have_pcd) + { + if ((pcd - 1) & ~0x3f) { + fprintf(stderr, "dpc_set: invalid clkdiv0: %d\n", pcd); + return -1; + } + } + + /* write */ + if (have_timings) + { + for (i = 0; i < 8; i++) + memregs[(0x307c>>1) + i] = timings[i]; + } + + if (have_pcd) + { + int tmp; + pcd = (pcd - 1) & 0x3f; + tmp = memregs[0x31c4>>1]; + memregs[0x31c4>>1] = (tmp & ~0x3f0) | (pcd << 4); + } + + return 0; +} + +#ifdef BINARY +#include +#include +#include +#include +#include + +static void usage(const char *binary) +{ + printf("usage:\n%s \n" + "set_str:\n" + " lcd_timings=\n" + " clkdiv0=\n", binary); +} + +int main(int argc, char *argv[]) +{ + volatile unsigned short *memregs; + int ret, memdev; + + if (argc != 2) { + usage(argv[0]); + return 1; + } + + memdev = open("/dev/mem", O_RDWR); + if (memdev == -1) + { + perror("open(/dev/mem) failed"); + return 1; + } + + memregs = mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0xc0000000); + if (memregs == MAP_FAILED) + { + perror("mmap(memregs) failed"); + close(memdev); + return 1; + } + + ret = pollux_dpc_set(memregs, argv[1]); + + munmap((void *)memregs, 0x10000); + close(memdev); + + return ret; +} +#endif