From e8f5db5d5a80a62069354466c64a9b90a2ced47c Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 24 Jun 2009 21:18:37 +0300 Subject: [PATCH] pollux_dpc_set integrated --- gp2x/Makefile | 1 + gp2x/gp2x.c | 4 + gp2x/pollux_dpc_set.c | 168 ++++++++++++++++++++++++++++++++++++++++++ gp2x/pollux_dpc_set.h | 10 +++ 4 files changed, 183 insertions(+) create mode 100644 gp2x/pollux_dpc_set.c create mode 100644 gp2x/pollux_dpc_set.h diff --git a/gp2x/Makefile b/gp2x/Makefile index 376970b..ed01178 100644 --- a/gp2x/Makefile +++ b/gp2x/Makefile @@ -12,6 +12,7 @@ OBJS = main.o cpu.o memory.u video.o input.o sound.o gp2x.o gui.o \ cheats.o zip.o cpu_threaded.z arm_stub.o video_blend.o \ warm.o upscale_aspect.o ifeq ($(WIZ),1) +OBJS += pollux_dpc_set.o BIN = gpsp_wiz else BIN = gpsp_gp2x diff --git a/gp2x/gp2x.c b/gp2x/gp2x.c index 6d9f82e..41e3f8b 100644 --- a/gp2x/gp2x.c +++ b/gp2x/gp2x.c @@ -29,6 +29,7 @@ #include "../common.h" #include "gp2x.h" #include "warm.h" +#include "pollux_dpc_set.h" u32 gp2x_audio_volume = 74/2; u32 gpsp_gp2x_dev_audio = 0; @@ -124,6 +125,9 @@ void wiz_lcd_set_portrait(int y) gpsp_gp2x_memregl[0x4004>>2] = y ? 0x013f00ef : 0x00ef013f; gpsp_gp2x_memregl[0x4000>>2] |= 1 << 3; old_y = y; + + /* the above ioctl resets LCD timings, so set them here */ + pollux_dpc_set(gpsp_gp2x_memregs, getenv("pollux_dpc_set")); } static void fb_video_exit() 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 diff --git a/gp2x/pollux_dpc_set.h b/gp2x/pollux_dpc_set.h new file mode 100644 index 0000000..53155d1 --- /dev/null +++ b/gp2x/pollux_dpc_set.h @@ -0,0 +1,10 @@ +#ifdef __cplusplus +extern "C" +{ +#endif + +int pollux_dpc_set(volatile unsigned short *memregs, const char *str); + +#ifdef __cplusplus +} +#endif -- 2.39.2