/* * 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