From fa8d133192876a802fbac43c0a0bfe4f5f85b682 Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 17 Jul 2009 22:49:29 +0000 Subject: [PATCH] gp2x+wiz binary support, wiz code wip git-svn-id: file:///home/notaz/opt/svn/PicoDrive/platform@705 be3aeb3a-fb24-0410-a615-afba39da0efa --- common/config.c | 8 +- common/emu.c | 20 ++- common/emu.h | 8 + common/menu.c | 30 +++- common/menu.h | 1 + common/plat.h | 3 + gp2x/Makefile | 28 ++-- gp2x/emu.c | 42 +++-- gp2x/in_gp2x.c | 71 ++++++++- gp2x/main.c | 2 + gp2x/plat.c | 40 ++++- gp2x/pollux_set.c | 380 ++++++++++++++++++++++++++++++++++++++++++++++ gp2x/pollux_set.h | 10 ++ gp2x/soc.c | 18 ++- gp2x/soc.h | 24 +-- gp2x/soc_mmsp2.c | 58 ++++--- gp2x/soc_pollux.c | 240 +++++++++++++++++++++++++++++ 17 files changed, 897 insertions(+), 86 deletions(-) create mode 100644 gp2x/pollux_set.c create mode 100644 gp2x/pollux_set.h diff --git a/common/config.c b/common/config.c index c5ff538..4f80c86 100644 --- a/common/config.c +++ b/common/config.c @@ -451,13 +451,13 @@ static int custom_read(menu_entry *me, const char *var, const char *val) #ifdef __GP2X__ if (strcasecmp(var, "Scaling") != 0) return 0; if (strcasecmp(val, "OFF") == 0) { - currentConfig.scaling = 0; + currentConfig.scaling = EOPT_SCALE_NONE; } else if (strcasecmp(val, "hw horizontal") == 0) { - currentConfig.scaling = 1; + currentConfig.scaling = EOPT_SCALE_HW_H; } else if (strcasecmp(val, "hw horiz. + vert.") == 0) { - currentConfig.scaling = 2; + currentConfig.scaling = EOPT_SCALE_HW_HV; } else if (strcasecmp(val, "sw horizontal") == 0) { - currentConfig.scaling = 3; + currentConfig.scaling = EOPT_SCALE_SW_H; } else return 0; return 1; diff --git a/common/emu.c b/common/emu.c index 542abf5..5f18dd0 100644 --- a/common/emu.c +++ b/common/emu.c @@ -5,7 +5,6 @@ #include #include -#include // tolower #ifndef NO_SYNC #include #endif @@ -47,12 +46,13 @@ unsigned char *movie_data = NULL; static int movie_size = 0; -// utilities +/* don't use tolower() for easy old glibc binary compatibility */ static void strlwr_(char *string) { char *p; for (p = string; *p; p++) - *p = (char)tolower(*p); + if ('A' <= *p && *p <= 'Z') + *p += 'a' - 'A'; } static int try_rfn_cut(char *fname) @@ -621,17 +621,21 @@ int emu_ReadConfig(int game, int no_defaults) } } + plat_validate_config(); + // some sanity checks - if (currentConfig.CPUclock < 10 || currentConfig.CPUclock > 4096) currentConfig.CPUclock = 200; #ifdef PSP + /* TODO: mv to plat_validate_config() */ + if (currentConfig.CPUclock < 10 || currentConfig.CPUclock > 4096) currentConfig.CPUclock = 200; if (currentConfig.gamma < -4 || currentConfig.gamma > 16) currentConfig.gamma = 0; if (currentConfig.gamma2 < 0 || currentConfig.gamma2 > 2) currentConfig.gamma2 = 0; -#else - if (currentConfig.gamma < 10 || currentConfig.gamma > 300) currentConfig.gamma = 100; #endif - if (currentConfig.volume < 0 || currentConfig.volume > 99) currentConfig.volume = 50; + if (currentConfig.volume < 0 || currentConfig.volume > 99) + currentConfig.volume = 50; + + if (ret == 0) + config_slot_current = config_slot; - if (ret == 0) config_slot_current = config_slot; return (ret == 0); } diff --git a/common/emu.h b/common/emu.h index 2c8de5c..808bcb0 100644 --- a/common/emu.h +++ b/common/emu.h @@ -27,8 +27,16 @@ extern int g_screen_height; #define EOPT_MMUHACK (1<<4) #define EOPT_NO_AUTOSVCFG (1<<5) #define EOPT_RAM_TIMINGS (1<<8) +#define EOPT_A_SN_GAMMA (1<<12) #define EOPT_PSYNC (1<<13) +enum { + EOPT_SCALE_NONE = 0, + EOPT_SCALE_SW_H, + EOPT_SCALE_HW_H, + EOPT_SCALE_HW_HV, +}; + typedef struct _currentConfig_t { // char lastRomFile[512]; int EmuOpt; // LSb->MSb: use_sram, show_fps, enable_sound, gzip_saves, diff --git a/common/menu.c b/common/menu.c index d7d93b3..b5c3495 100644 --- a/common/menu.c +++ b/common/menu.c @@ -1443,12 +1443,12 @@ static int menu_loop_adv_options(menu_id id, int keys) static const char *mgn_opt_scaling(menu_id id, int *offs) { - *offs = -12; + *offs = -13; switch (currentConfig.scaling) { - default: return " OFF"; - case 1: return "hw horizontal"; - case 2: return "hw horiz. + vert."; - case 3: return "sw horizontal"; + default: return " OFF"; + case EOPT_SCALE_HW_H: return " hw horizontal"; + case EOPT_SCALE_HW_HV: return "hw horiz. + vert"; + case EOPT_SCALE_SW_H: return " sw horizontal"; } } @@ -1462,8 +1462,8 @@ static menu_entry e_menu_gfx_options[] = { mee_range_cust("Scaling", MA_OPT_SCALING, currentConfig.scaling, 0, 3, mgn_opt_scaling), mee_range_cust("Gamma correction", MA_OPT2_GAMMA, currentConfig.gamma, 1, 300, mgn_aopt_gamma), - mee_onoff ("A_SN's gamma curve", MA_OPT2_A_SN_GAMMA, currentConfig.EmuOpt, 0x1000), - mee_onoff ("Perfect vsync", MA_OPT2_VSYNC, currentConfig.EmuOpt, 0x2000), + mee_onoff ("A_SN's gamma curve", MA_OPT2_A_SN_GAMMA, currentConfig.EmuOpt, EOPT_A_SN_GAMMA), + mee_onoff ("Perfect vsync", MA_OPT2_VSYNC, currentConfig.EmuOpt, EOPT_PSYNC), mee_end, }; @@ -2044,6 +2044,22 @@ void me_update_msg(const char *msg) // ------------ util ------------ +/* wiz for now, probably extend later */ +void menu_plat_setup(int is_wiz) +{ + int i; + + if (!is_wiz) + return; + + me_enable(e_menu_adv_options, MA_OPT_ARM940_SOUND, 0); + me_enable(e_menu_gfx_options, MA_OPT2_GAMMA, 0); + me_enable(e_menu_gfx_options, MA_OPT2_A_SN_GAMMA, 0); + + i = me_id2offset(e_menu_gfx_options, MA_OPT_SCALING); + e_menu_gfx_options[i].max = 1; /* only off and sw */ +} + /* TODO: rename */ void menu_darken_bg(void *dst, int pixels, int darker) { diff --git a/common/menu.h b/common/menu.h index 430f002..588bfb9 100644 --- a/common/menu.h +++ b/common/menu.h @@ -153,6 +153,7 @@ extern me_bind_action me_ctrl_actions[15]; extern me_bind_action emuctrl_actions[]; // platform code void menu_init(void); +void menu_plat_setup(int is_wiz); void text_out16(int x, int y, const char *texto, ...); void me_update_msg(const char *msg); diff --git a/common/plat.h b/common/plat.h index ac7a438..607b811 100644 --- a/common/plat.h +++ b/common/plat.h @@ -19,6 +19,7 @@ int emu_getMainDir(char *dst, int len); void menu_romload_prepare(const char *rom_name); void menu_romload_end(void); +void plat_early_init(void); void plat_init(void); void plat_finish(void); @@ -27,6 +28,8 @@ void plat_video_menu_enter(int is_rom_loaded); void plat_video_menu_begin(void); void plat_video_menu_end(void); +void plat_validate_config(void); + int plat_is_dir(const char *path); int plat_wait_event(int *fds_hnds, int count, int timeout_ms); void plat_sleep_ms(int ms); diff --git a/gp2x/Makefile b/gp2x/Makefile index 01dbaf4..00fdb78 100644 --- a/gp2x/Makefile +++ b/gp2x/Makefile @@ -32,20 +32,20 @@ use_cyclone = 1 endif DEFINC = -I../.. -I. -DARM -D__GP2X__ -DIN_GP2X # -DBENCHMARK -COPT_COMMON = -Wall -Winline -COPT_COMMON += -static +CFLAGS += -Wall -Winline ifeq ($(DEBUG),) -COPT_COMMON += -O3 -ftracer -fstrength-reduce -fomit-frame-pointer -fstrict-aliasing -ffast-math +# -ftracer # TODO measure impact +CFLAGS += -O3 -fstrength-reduce -fomit-frame-pointer -fstrict-aliasing -ffast-math else -COPT_COMMON += -ggdb +CFLAGS += -ggdb endif ifeq "$(profile)" "1" -COPT_COMMON += -fprofile-generate +CFLAGS += -fprofile-generate endif ifeq "$(profile)" "2" -COPT_COMMON += -fprofile-use +CFLAGS += -fprofile-use endif -CFLAGS = $(COPT_COMMON) -mcpu=arm920t -mtune=arm920t +CFLAGS += -mcpu=arm920t -mtune=arm920t SFLAGS = $(CFLAGS) ASFLAGS = -mcpu=arm920t -mfloat-abi=soft CC = $(CROSS)gcc @@ -55,7 +55,7 @@ LD = $(CROSS)ld OBJCOPY = $(CROSS)objcopy # frontend -OBJS += main.o soc.o soc_mmsp2.o soc_pollux.o emu.o in_gp2x.o plat.o warm.o +OBJS += main.o soc.o soc_mmsp2.o soc_pollux.o pollux_set.o emu.o in_gp2x.o plat.o warm.o # 940 core control OBJS += 940ctl.o @@ -122,22 +122,22 @@ DIRS = platform platform/gp2x platform/linux platform/common pico pico/cd pico/p pico/carthw/svp zlib unzip cpu cpu/musashi cpu/Cyclone/proj cpu/Cyclone/tools cpu/mz80 cpu/DrZ80 -all: mkdirs PicoDrive.gpe +all: mkdirs PicoDrive include ../common/common_arm.mak -PicoDrive.gpe : $(OBJS) ../common/helix/$(CROSS)helix-mp3.a +PicoDrive : $(OBJS) ../common/helix/$(CROSS)helix-mp3.a @echo ">>>" $@ $(CC) -o $@ $(CFLAGS) $^ -lm -lpng -Wl,-Map=PicoDrive.map ifeq ($(DEBUG),) $(STRIP) $@ endif -up: PicoDrive.gpe - @cp -v PicoDrive.gpe /mnt/gp2x/mnt/sd/emus/PicoDrive/ +up: PicoDrive + @cp -v PicoDrive /mnt/gp2x/mnt/sd/emus/PicoDrive/ clean: tidy - $(RM) PicoDrive.gpe + $(RM) PicoDrive tidy: $(RM) $(OBJS) @@ -151,7 +151,7 @@ $(error need VER) endif endif -rel: PicoDrive.gpe code940/pico940_v3.bin readme.txt PicoDrive.man.txt PicoDrive.png ../game_def.cfg +rel: PicoDrive PicoDrive.gpe code940/pico940_v3.bin readme.txt PicoDrive.man.txt PicoDrive.png ../game_def.cfg zip -9 -j ../../PicoDrive_$(VER).zip $^ mmuhack.o zip -9 -r ../../PicoDrive_$(VER).zip skin -i \*.png -i \*.txt mkdir bin_to_cso_mp3 diff --git a/gp2x/emu.c b/gp2x/emu.c index 592c360..c78b706 100644 --- a/gp2x/emu.c +++ b/gp2x/emu.c @@ -101,12 +101,16 @@ void emu_Init(void) static void scaling_update(void) { - PicoOpt &= ~0x4100; + PicoOpt &= ~(POPT_DIS_32C_BORDER|POPT_EN_SOFTSCALE); switch (currentConfig.scaling) { - default: break; // off - case 1: // hw hor - case 2: PicoOpt |= 0x0100; break; // hw hor+vert - case 3: PicoOpt |= 0x4000; break; // sw hor + default:break; + case EOPT_SCALE_HW_H: + case EOPT_SCALE_HW_HV: + PicoOpt |= POPT_DIS_32C_BORDER; + break; + case EOPT_SCALE_SW_H: + PicoOpt |= POPT_EN_SOFTSCALE; + break; } } @@ -133,19 +137,25 @@ void emu_Deinit(void) void emu_prepareDefaultConfig(void) { + gp2x_soc_t soc; + memset(&defaultConfig, 0, sizeof(defaultConfig)); - defaultConfig.EmuOpt = 0x9d | 0x00700; // | <- ram_tmng, confirm_save, cd_leds - defaultConfig.s_PicoOpt = 0x0f | POPT_EXT_FM|POPT_EN_MCD_PCM|POPT_EN_MCD_CDDA|POPT_EN_SVP_DRC|POPT_ACC_SPRITES; + defaultConfig.EmuOpt = 0x9d | EOPT_RAM_TIMINGS | 0x600; // | <- confirm_save, cd_leds + defaultConfig.s_PicoOpt = 0x0f | POPT_EN_MCD_PCM|POPT_EN_MCD_CDDA|POPT_EN_SVP_DRC|POPT_ACC_SPRITES; defaultConfig.s_PsndRate = 44100; defaultConfig.s_PicoRegion = 0; // auto defaultConfig.s_PicoAutoRgnOrder = 0x184; // US, EU, JP defaultConfig.s_PicoCDBuffers = 0; defaultConfig.Frameskip = -1; // auto - defaultConfig.CPUclock = -1; + defaultConfig.CPUclock = default_cpu_clock; defaultConfig.volume = 50; defaultConfig.gamma = 100; defaultConfig.scaling = 0; defaultConfig.turbo_rate = 15; + + soc = soc_detect(); + if (soc == SOCID_MMSP2) + defaultConfig.s_PicoOpt |= POPT_EXT_FM; } void osd_text(int x, int y, const char *text) @@ -295,8 +305,10 @@ static void blit(const char *fps, const char *notice) if (notice || (emu_opt & 2)) { int h = 232; - if (currentConfig.scaling == 2 && !(Pico.video.reg[1]&8)) h -= 8; - if (notice) osd_text(4, h, notice); + if (currentConfig.scaling == EOPT_SCALE_HW_HV && !(Pico.video.reg[1]&8)) + h -= 8; + if (notice) + osd_text(4, h, notice); if (emu_opt & 2) osd_text(osd_fps_x, h, fps); } @@ -362,7 +374,7 @@ static void vidResetMode(void) } Pico.m.dirtyPal = 1; // reset scaling - if (currentConfig.scaling == 2 && !(Pico.video.reg[1]&8)) + if (currentConfig.scaling == EOPT_SCALE_HW_HV && !(Pico.video.reg[1]&8)) gp2x_video_RGB_setscaling(8, (PicoOpt&0x100)&&!(Pico.video.reg[12]&1) ? 256 : 320, 224); else gp2x_video_RGB_setscaling(0, (PicoOpt&0x100)&&!(Pico.video.reg[12]&1) ? 256 : 320, 240); } @@ -773,16 +785,13 @@ void emu_Loop(void) if ((EmuOpt_old ^ currentConfig.EmuOpt) & EOPT_RAM_TIMINGS) { if (currentConfig.EmuOpt & EOPT_RAM_TIMINGS) - /* craigix: --cas 2 --trc 6 --tras 4 --twr 1 --tmrd 1 --trfc 1 --trp 2 --trcd 2 */ - set_ram_timings(2, 6, 4, 1, 1, 1, 2, 2); + set_ram_timings(); else unset_ram_timings(); } if (gp2x_old_clock < 0) gp2x_old_clock = default_cpu_clock; - if (currentConfig.CPUclock < 0) - currentConfig.CPUclock = default_cpu_clock; if (gp2x_old_clock != currentConfig.CPUclock) { printf("changing clock to %i...", currentConfig.CPUclock); fflush(stdout); gp2x_set_cpuclk(currentConfig.CPUclock); @@ -885,7 +894,8 @@ void emu_Loop(void) vidCpyM2 = vidCpyM2_32col; } } - if (currentConfig.scaling == 2 && !(modes&8)) // want vertical scaling and game is not in 240 line mode + /* want vertical scaling and game is not in 240 line mode */ + if (currentConfig.scaling == EOPT_SCALE_HW_HV && !(modes&8)) gp2x_video_RGB_setscaling(8, scalex, 224); else gp2x_video_RGB_setscaling(0, scalex, 240); oldmodes = modes; diff --git a/gp2x/in_gp2x.c b/gp2x/in_gp2x.c index 8066ca7..ab4ba17 100644 --- a/gp2x/in_gp2x.c +++ b/gp2x/in_gp2x.c @@ -1,5 +1,10 @@ +#include #include #include +#include +#include +#include +#include #include "../common/input.h" #include "in_gp2x.h" @@ -12,6 +17,9 @@ * both must be pressed for action to happen) */ static int in_gp2x_combo_keys = 0; static int in_gp2x_combo_acts = 0; +static int gpiodev = -1; /* Wiz only */ + +static int (*in_gp2x_get_bits)(void); enum { BTN_UP = 0, BTN_LEFT = 2, BTN_DOWN = 4, BTN_RIGHT = 6, BTN_START = 8, BTN_SELECT = 9, BTN_L = 10, BTN_R = 11, @@ -28,18 +36,48 @@ static const char * const in_gp2x_keys[IN_GP2X_NBUTTONS] = { [BTN_PUSH] = "PUSH" }; +static int in_gp2x_get_mmsp2_bits(void); +static int in_gp2x_get_wiz_bits(void); static void in_gp2x_probe(void) { + gp2x_soc_t soc; + + soc = soc_detect(); + switch (soc) + { + case SOCID_MMSP2: + in_gp2x_get_bits = in_gp2x_get_mmsp2_bits; + break; + case SOCID_POLLUX: + gpiodev = open("/dev/GPIO", O_RDONLY); + if (gpiodev < 0) { + perror("in_gp2x: couldn't open /dev/GPIO"); + return; + } + in_gp2x_get_bits = in_gp2x_get_wiz_bits; + break; + default: + return; + } + in_register(IN_PREFIX "GP2X pad", IN_DRVID_GP2X, -1, (void *)1, 1); } +static void in_gp2x_free(void *drv_data) +{ + if (gpiodev >= 0) { + close(gpiodev); + gpiodev = -1; + } +} + static int in_gp2x_get_bind_count(void) { return IN_GP2X_NBUTTONS; } -static int in_gp2x_get_gpio_bits(void) +static int in_gp2x_get_mmsp2_bits(void) { #ifndef FAKE_IN_GP2X extern volatile unsigned short *gp2x_memregs; @@ -60,12 +98,38 @@ static int in_gp2x_get_gpio_bits(void) #endif } +static int in_gp2x_get_wiz_bits(void) +{ + int value = 0; + read(gpiodev, &value, 4); + if (value & 0x02) + value |= 0x05; + if (value & 0x08) + value |= 0x14; + if (value & 0x20) + value |= 0x50; + if (value & 0x80) + value |= 0x41; + + /* convert to GP2X style */ + value &= 0x7ff55; + if (value & (1 << 16)) + value |= 1 << BTN_VOL_UP; + if (value & (1 << 17)) + value |= 1 << BTN_VOL_DOWN; + if (value & (1 << 18)) + value |= 1 << BTN_PUSH; + value &= ~0x70000; + + return value; +} + /* returns bitfield of binds of pressed buttons */ int in_gp2x_update(void *drv_data, int *binds) { int i, keys, ret = 0; - keys = in_gp2x_get_gpio_bits(); + keys = in_gp2x_get_bits(); if (keys & in_gp2x_combo_keys) return in_combos_do(keys, binds, BTN_PUSH, in_gp2x_combo_keys, in_gp2x_combo_acts); @@ -84,7 +148,7 @@ int in_gp2x_update_keycode(void *data, int *is_down) static int old_val = 0; int val, diff, i; - val = in_gp2x_get_gpio_bits(); + val = in_gp2x_get_bits(); diff = val ^ old_val; if (diff == 0) return -1; @@ -238,6 +302,7 @@ void in_gp2x_init(void *vdrv) drv->prefix = in_gp2x_prefix; drv->probe = in_gp2x_probe; + drv->free = in_gp2x_free; drv->get_bind_count = in_gp2x_get_bind_count; drv->get_def_binds = in_gp2x_get_def_binds; drv->clean_binds = in_gp2x_clean_binds; diff --git a/gp2x/main.c b/gp2x/main.c index 7ceeec3..6ac16b8 100644 --- a/gp2x/main.c +++ b/gp2x/main.c @@ -66,6 +66,8 @@ int main(int argc, char *argv[]) { g_argv = argv; + plat_early_init(); + /* in_init() must go before config, config accesses in_ fwk */ in_init(); emu_prepareDefaultConfig(); diff --git a/gp2x/plat.c b/gp2x/plat.c index 4ae956c..c2dce2d 100644 --- a/gp2x/plat.c +++ b/gp2x/plat.c @@ -12,6 +12,8 @@ #include "../common/emu.h" #include "../linux/sndout_oss.h" +#include + /* GP2X local */ int default_cpu_clock; void *gp2x_screens[4]; @@ -101,7 +103,22 @@ void plat_video_menu_end(void) gp2x_video_flip2(); } -void plat_init(void) +void plat_validate_config(void) +{ + gp2x_soc_t soc; + + soc = soc_detect(); + if (soc != SOCID_MMSP2) + PicoOpt &= ~POPT_EXT_FM; + + if (currentConfig.gamma < 10 || currentConfig.gamma > 300) + currentConfig.gamma = 100; + + if (currentConfig.CPUclock < 10 || currentConfig.CPUclock > 1024) + currentConfig.CPUclock = default_cpu_clock; +} + +void plat_early_init(void) { gp2x_soc_t soc; @@ -109,11 +126,9 @@ void plat_init(void) switch (soc) { case SOCID_MMSP2: - mmsp2_init(); default_cpu_clock = 200; break; case SOCID_POLLUX: - pollux_init(); strcpy(cpu_clk_name, "Wiz CPU clock"); default_cpu_clock = 533; break; @@ -121,6 +136,25 @@ void plat_init(void) fprintf(stderr, "could not recognize SoC, bailing out.\n"); exit(1); } +} + +void plat_init(void) +{ + gp2x_soc_t soc; + + soc = soc_detect(); + switch (soc) + { + case SOCID_MMSP2: + mmsp2_init(); + break; + case SOCID_POLLUX: + pollux_init(); + menu_plat_setup(1); + break; + default: + break; + } warm_init(); diff --git a/gp2x/pollux_set.c b/gp2x/pollux_set.c new file mode 100644 index 0000000..fc60b27 --- /dev/null +++ b/gp2x/pollux_set.c @@ -0,0 +1,380 @@ +/* + * quick tool to set various timings for Wiz + * + * Copyright (c) Gražvydas "notaz" Ignotas, 2009 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the organization nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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;dpc_clkdiv0=9' + * 'ram_timings=2,9,4,1,1,1,1' + */ + +#include +#include +#include +#include "pollux_set.h" + +/* parse stuff */ +static int parse_lcd_timings(const char *str, void *data) +{ + int *lcd_timings = data; + const char *p = str; + int ret, c; + ret = sscanf(str, "%d,%d,%d,%d,%d,%d,%d,%d", + &lcd_timings[0], &lcd_timings[1], &lcd_timings[2], &lcd_timings[3], + &lcd_timings[4], &lcd_timings[5], &lcd_timings[6], &lcd_timings[7]); + if (ret != 8) + return -1; + /* skip seven commas */ + for (c = 0; c < 7 && *p != 0; p++) + if (*p == ',') + c++; + if (c != 7) + return -1; + /* skip last number */ + while ('0' <= *p && *p <= '9') + p++; + + return p - str; +} + +static int parse_ram_timings(const char *str, void *data) +{ + int *ram_timings = data; + const char *p = str; + int ret, c; + float cas; + + ret = sscanf(p, "%f,%d,%d,%d,%d,%d,%d", + &cas, &ram_timings[1], &ram_timings[2], &ram_timings[3], + &ram_timings[4], &ram_timings[5], &ram_timings[6]); + if (ret != 7) + return -1; + if (cas == 2) + ram_timings[0] = 1; + else if (cas == 2.5) + ram_timings[0] = 2; + else if (cas == 3) + ram_timings[0] = 3; + else + return -1; + for (c = 0; c < 6 && *p != 0; p++) + if (*p == ',') + c++; + if (c != 6) + return -1; + while ('0' <= *p && *p <= '9') + p++; + + return p - str; +} + +static int parse_decimal(const char *str, void *data) +{ + char *ep; + + *(int *)data = strtoul(str, &ep, 10); + if (ep == str) + return -1; + + return ep - str; +} + +/* validate and apply stuff */ +static int apply_lcd_timings(volatile unsigned short *memregs, void *data) +{ + int *lcd_timings = data; + int i; + + for (i = 0; i < 8; i++) { + if (lcd_timings[i] & ~0xffff) { + fprintf(stderr, "pollux_set: invalid lcd timing %d: %d\n", i, lcd_timings[i]); + return -1; + } + } + + for (i = 0; i < 8; i++) + memregs[(0x307c>>1) + i] = lcd_timings[i]; + + return 0; +} + +static const struct { + signed char adj; /* how to adjust value passed by user */ + signed short min; /* range of */ + signed short max; /* allowed values (inclusive) */ +} +ram_ranges[] = { + { 0, 1, 3 }, /* cas (cl) */ + { -2, 0, 15 }, /* trc */ + { -2, 0, 15 }, /* tras */ + { 0, 0, 15 }, /* twr */ + { 0, 0, 15 }, /* tmrd */ + { 0, 0, 15 }, /* trp */ + { 0, 0, 15 }, /* trcd */ +}; + +static int apply_ram_timings(volatile unsigned short *memregs, void *data) +{ + int *ram_timings = data; + int i, val; + + for (i = 0; i < 7; i++) + { + ram_timings[i] += ram_ranges[i].adj; + if (ram_timings[i] < ram_ranges[i].min || ram_timings[i] > ram_ranges[i].max) { + fprintf(stderr, "pollux_set: invalid RAM timing %d\n", i); + return -1; + } + } + + val = memregs[0x14802>>1] & 0x0f00; + val |= (ram_timings[4] << 12) | (ram_timings[5] << 4) | ram_timings[6]; + memregs[0x14802>>1] = val; + + val = memregs[0x14804>>1] & 0x4000; + val |= (ram_timings[0] << 12) | (ram_timings[1] << 8) | + (ram_timings[2] << 4) | ram_timings[3]; + val |= 0x8000; + memregs[0x14804>>1] = val; + + for (i = 0; i < 0x100000 && (memregs[0x14804>>1] & 0x8000); i++) + ; + + return 0; +} + +static int apply_dpc_clkdiv0(volatile unsigned short *memregs, void *data) +{ + int pcd = *(int *)data; + int tmp; + + if ((pcd - 1) & ~0x3f) { + fprintf(stderr, "pollux_set: invalid lcd clkdiv0: %d\n", pcd); + return -1; + } + + pcd = (pcd - 1) & 0x3f; + tmp = memregs[0x31c4>>1]; + memregs[0x31c4>>1] = (tmp & ~0x3f0) | (pcd << 4); + + return 0; +} + +static int apply_cpuclk(volatile unsigned short *memregs, void *data) +{ + volatile unsigned int *memregl = (volatile void *)memregs; + int mhz = *(int *)data; + int mdiv, pdiv, sdiv = 0; + int i, v; + + // m = MDIV, p = PDIV, s = SDIV + #define SYS_CLK_FREQ 27 + pdiv = 9; + mdiv = (mhz * pdiv) / SYS_CLK_FREQ; + if (mdiv & ~0x3ff) + return -1; + v = (pdiv<<18) | (mdiv<<8) | sdiv; + + memregl[0xf004>>2] = v; + memregl[0xf07c>>2] |= 0x8000; + for (i = 0; (memregl[0xf07c>>2] & 0x8000) && i < 0x100000; i++) + ; + + return 0; +} + +static int lcd_timings[8]; +static int ram_timings[7]; +static int dpc_clkdiv0; +static int cpuclk; + +static const char lcd_t_help[] = "htotal,hswidth,hastart,haend,vtotal,vswidth,vastart,vaend"; +static const char ram_t_help[] = "CAS,tRC,tRAS,tWR,tMRD,tRP,tRCD"; + +static const struct { + const char *name; + const char *help; + int (*parse)(const char *str, void *data); + int (*apply)(volatile unsigned short *memregs, void *data); + void *data; +} +all_params[] = { + { "lcd_timings", lcd_t_help, parse_lcd_timings, apply_lcd_timings, lcd_timings }, + { "ram_timings", ram_t_help, parse_ram_timings, apply_ram_timings, ram_timings }, + { "dpc_clkdiv0", "divider", parse_decimal, apply_dpc_clkdiv0, &dpc_clkdiv0 }, + { "clkdiv0", "divider", parse_decimal, apply_dpc_clkdiv0, &dpc_clkdiv0 }, /* alias */ + { "cpuclk", "MHZ", parse_decimal, apply_cpuclk, &cpuclk }, +}; +#define ALL_PARAM_COUNT (sizeof(all_params) / sizeof(all_params[0])) + +/* + * set timings based on preformated string + * returns 0 on success. + */ +int pollux_set(volatile unsigned short *memregs, const char *str) +{ + int parsed_params[ALL_PARAM_COUNT]; + int applied_params[ALL_PARAM_COUNT]; + int applied_something = 0; + const char *p, *po; + int i, ret; + + if (str == NULL) + return -1; + + memset(parsed_params, 0, sizeof(parsed_params)); + memset(applied_params, 0, sizeof(applied_params)); + + p = str; + while (1) + { +again: + while (*p == ';' || *p == ' ') + p++; + if (*p == 0) + break; + + for (i = 0; i < ALL_PARAM_COUNT; i++) + { + int param_len = strlen(all_params[i].name); + if (strncmp(p, all_params[i].name, param_len) == 0 && p[param_len] == '=') + { + p += param_len + 1; + ret = all_params[i].parse(p, all_params[i].data); + if (ret < 0) { + fprintf(stderr, "pollux_set parser: error at %-10s\n", p); + fprintf(stderr, " valid format is: <%s>\n", all_params[i].help); + return -1; + } + parsed_params[i] = 1; + p += ret; + goto again; + } + } + + /* Unknown param. Attempt to be forward compatible and ignore it. */ + for (po = p; *p != 0 && *p != ';'; p++) + ; + + fprintf(stderr, "unhandled param: "); + fwrite(po, 1, p - po, stderr); + fprintf(stderr, "\n"); + } + + /* validate and apply */ + for (i = 0; i < ALL_PARAM_COUNT; i++) + { + if (!parsed_params[i]) + continue; + + ret = all_params[i].apply(memregs, all_params[i].data); + if (ret < 0) { + fprintf(stderr, "pollux_set: failed to apply %s (bad value?)\n", + all_params[i].name); + continue; + } + + applied_something = 1; + applied_params[i] = 1; + } + + if (applied_something) + { + int c; + printf("applied: "); + for (i = c = 0; i < ALL_PARAM_COUNT; i++) + { + if (!applied_params[i]) + continue; + if (c != 0) + printf(", "); + printf("%s", all_params[i].name); + c++; + } + printf("\n"); + } + + return 0; +} + +#ifdef BINARY +#include +#include +#include +#include +#include + +static void usage(const char *binary) +{ + int i; + printf("usage:\n%s \n" + "set_str:\n", binary); + for (i = 0; i < ALL_PARAM_COUNT; i++) + printf(" %s=<%s>\n", all_params[i].name, all_params[i].help); +} + +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, 0x20000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0xc0000000); + if (memregs == MAP_FAILED) + { + perror("mmap(memregs) failed"); + close(memdev); + return 1; + } + + ret = pollux_set(memregs, argv[1]); + + munmap((void *)memregs, 0x20000); + close(memdev); + + return ret; +} +#endif diff --git a/gp2x/pollux_set.h b/gp2x/pollux_set.h new file mode 100644 index 0000000..64bb220 --- /dev/null +++ b/gp2x/pollux_set.h @@ -0,0 +1,10 @@ +#ifdef __cplusplus +extern "C" +{ +#endif + +int pollux_set(volatile unsigned short *memregs, const char *str); + +#ifdef __cplusplus +} +#endif diff --git a/gp2x/soc.c b/gp2x/soc.c index 68b2c89..d9b956f 100644 --- a/gp2x/soc.c +++ b/gp2x/soc.c @@ -7,7 +7,23 @@ #include #include "soc.h" -#include "../common/emu.h" + +void (*gp2x_video_flip)(void); +void (*gp2x_video_flip2)(void); +void (*gp2x_video_changemode_ll)(int bpp); +void (*gp2x_video_setpalette)(int *pal, int len); +void (*gp2x_video_RGB_setscaling)(int ln_offs, int W, int H); +void (*gp2x_video_wait_vsync)(void); + +void (*gp2x_set_cpuclk)(unsigned int mhz); + +void (*set_lcd_custom_rate)(int is_pal); +void (*unset_lcd_custom_rate)(void); +void (*set_lcd_gamma)(int g100, int A_SNs_curve); + +void (*set_ram_timings)(void); +void (*unset_ram_timings)(void); + gp2x_soc_t soc_detect(void) { diff --git a/gp2x/soc.h b/gp2x/soc.h index 7f84e97..35fe804 100644 --- a/gp2x/soc.h +++ b/gp2x/soc.h @@ -12,19 +12,19 @@ void pollux_init(void); void pollux_finish(void); /* SoC specific functions */ -void gp2x_video_flip(void); -void gp2x_video_flip2(void); -void gp2x_video_changemode_ll(int bpp); -void gp2x_video_setpalette(int *pal, int len); -void gp2x_video_RGB_setscaling(int ln_offs, int W, int H); -void gp2x_video_wait_vsync(void); +extern void (*gp2x_video_flip)(void); +extern void (*gp2x_video_flip2)(void); +extern void (*gp2x_video_changemode_ll)(int bpp); +extern void (*gp2x_video_setpalette)(int *pal, int len); +extern void (*gp2x_video_RGB_setscaling)(int ln_offs, int W, int H); +extern void (*gp2x_video_wait_vsync)(void); -void gp2x_set_cpuclk(unsigned int mhz); +extern void (*gp2x_set_cpuclk)(unsigned int mhz); -void set_lcd_custom_rate(int is_pal); -void unset_lcd_custom_rate(void); -void set_lcd_gamma(int g100, int A_SNs_curve); +extern void (*set_lcd_custom_rate)(int is_pal); +extern void (*unset_lcd_custom_rate)(void); +extern void (*set_lcd_gamma)(int g100, int A_SNs_curve); -void set_ram_timings(int tCAS, int tRC, int tRAS, int tWR, int tMRD, int tRFC, int tRP, int tRCD); -void unset_ram_timings(void); +extern void (*set_ram_timings)(void); +extern void (*unset_ram_timings)(void); diff --git a/gp2x/soc_mmsp2.c b/gp2x/soc_mmsp2.c index 32399d7..c136287 100644 --- a/gp2x/soc_mmsp2.c +++ b/gp2x/soc_mmsp2.c @@ -20,7 +20,7 @@ volatile unsigned long *gp2x_memregl; extern void *gp2x_screens[4]; static int screensel = 0; -int memdev = 0; /* used by code940 */ +int memdev = -1; /* used by code940 */ static int touchdev = -1; static int touchcal[7] = { 6203, 0, -1501397, 0, -4200, 16132680, 65536 }; @@ -37,7 +37,7 @@ static unsigned short gp2x_screenaddr_old[4]; /* video stuff */ -void gp2x_video_flip(void) +static void gp2x_video_flip_(void) { unsigned short lsw = (unsigned short) gp2x_screenaddrs_use[screensel&3]; unsigned short msw = (unsigned short)(gp2x_screenaddrs_use[screensel&3] >> 16); @@ -52,7 +52,7 @@ void gp2x_video_flip(void) } /* doulblebuffered flip */ -void gp2x_video_flip2(void) +static void gp2x_video_flip2_(void) { unsigned short msw = (unsigned short)(gp2x_screenaddrs_use[screensel&1] >> 16); @@ -65,13 +65,13 @@ void gp2x_video_flip2(void) g_screen_ptr = gp2x_screens[++screensel&1]; } -void gp2x_video_changemode_ll(int bpp) +static void gp2x_video_changemode_ll_(int bpp) { gp2x_memregs[0x28DA>>1] = (((bpp+1)/8)<<9)|0xAB; /*8/15/16/24bpp...*/ gp2x_memregs[0x290C>>1] = 320*((bpp+1)/8); /*line width in bytes*/ } -void gp2x_video_setpalette(int *pal, int len) +static void gp2x_video_setpalette_(int *pal, int len) { unsigned short *g = (unsigned short *)pal; volatile unsigned short *memreg = &gp2x_memregs[0x295A>>1]; @@ -83,8 +83,7 @@ void gp2x_video_setpalette(int *pal, int len) *memreg = *g++; } -// TV Compatible function // -void gp2x_video_RGB_setscaling(int ln_offs, int W, int H) +static void gp2x_video_RGB_setscaling_(int ln_offs, int W, int H) { float escalaw, escalah; int bpp = (gp2x_memregs[0x28DA>>1]>>9)&0x3; @@ -99,7 +98,7 @@ void gp2x_video_RGB_setscaling(int ln_offs, int W, int H) escalaw = 1024.0; // RGB Horiz LCD escalah = 320.0; // RGB Vert LCD - if(gp2x_memregs[0x2800>>1]&0x100) //TV-Out + if (gp2x_memregs[0x2800>>1]&0x100) //TV-Out { escalaw=489.0; // RGB Horiz TV (PAL, NTSC) if (gp2x_memregs[0x2818>>1] == 287) //PAL @@ -110,14 +109,15 @@ void gp2x_video_RGB_setscaling(int ln_offs, int W, int H) // scale horizontal scalw = (unsigned short)((float)escalaw *(W/320.0)); - /* if there is no horizontal scaling, vertical doesn't work. Here is a nasty wrokaround... */ + /* if there is no horizontal scaling, vertical doesn't work. + * Here is a nasty wrokaround... */ if (H != 240 && W == 320) scalw--; gp2x_memregs[0x2906>>1]=scalw; // scale vertical gp2x_memregl[0x2908>>2]=(unsigned long)((float)escalah *bpp *(H/240.0)); } -void gp2x_video_wait_vsync(void) +static void gp2x_video_wait_vsync_(void) { unsigned short v = gp2x_memregs[0x1182>>1]; while (!((v ^ gp2x_memregs[0x1182>>1]) & 0x10)) @@ -148,7 +148,7 @@ void reset940(int yes, int bank) #define SYS_CLK_FREQ 7372800 -void gp2x_set_cpuclk(unsigned int mhz) +static void gp2x_set_cpuclk_(unsigned int mhz) { unsigned int mdiv, pdiv, sdiv = 0; unsigned int v; @@ -176,7 +176,7 @@ static unsigned short memtimex[2]; if (t & ~mask) \ goto bad -void set_ram_timings(int tCAS, int tRC, int tRAS, int tWR, int tMRD, int tRFC, int tRP, int tRCD) +static void set_ram_timing_vals(int tCAS, int tRC, int tRAS, int tWR, int tMRD, int tRFC, int tRP, int tRCD) { int i; TIMING_CHECK(tCAS, -2, 0x1); @@ -206,7 +206,13 @@ bad: fprintf(stderr, "RAM timings invalid.\n"); } -void unset_ram_timings(void) +static void set_ram_timings_(void) +{ + /* craigix: --cas 2 --trc 6 --tras 4 --twr 1 --tmrd 1 --trfc 1 --trp 2 --trcd 2 */ + set_ram_timing_vals(2, 6, 4, 1, 1, 1, 2, 2); +} + +static void unset_ram_timings_(void) { gp2x_memregs[0x3802>>1] = memtimex[0]; gp2x_memregs[0x3804>>1] = memtimex[1] | 0x8000; @@ -279,7 +285,7 @@ static void set_reg_setting(const reg_setting *set) } } -void set_lcd_custom_rate(int is_pal) +static void set_lcd_custom_rate_(int is_pal) { if (gp2x_memregs[0x2800>>1] & 0x100) // tv-out return; @@ -291,13 +297,13 @@ void set_lcd_custom_rate(int is_pal) printf("done.\n"); } -void unset_lcd_custom_rate(void) +static void unset_lcd_custom_rate_(void) { printf("reset to prev LCD refresh.\n"); set_reg_setting(lcd_rate_defaults); } -void set_lcd_gamma(int g100, int A_SNs_curve) +static void set_lcd_gamma_(int g100, int A_SNs_curve) { float gamma = (float) g100 / 100; int i; @@ -473,6 +479,22 @@ void mmsp2_init(void) /* code940 portion */ sharedmem940_init(); + + gp2x_video_flip = gp2x_video_flip_; + gp2x_video_flip2 = gp2x_video_flip2_; + gp2x_video_changemode_ll = gp2x_video_changemode_ll_; + gp2x_video_setpalette = gp2x_video_setpalette_; + gp2x_video_RGB_setscaling = gp2x_video_RGB_setscaling_; + gp2x_video_wait_vsync = gp2x_video_wait_vsync_; + + gp2x_set_cpuclk = gp2x_set_cpuclk_; + + set_lcd_custom_rate = set_lcd_custom_rate_; + unset_lcd_custom_rate = unset_lcd_custom_rate_; + set_lcd_gamma = set_lcd_gamma_; + + set_ram_timings = set_ram_timings_; + unset_ram_timings = unset_ram_timings_; } void mmsp2_finish(void) @@ -486,8 +508,8 @@ void mmsp2_finish(void) gp2x_memregs[0x2912>>1] = gp2x_screenaddr_old[2]; gp2x_memregs[0x2914>>1] = gp2x_screenaddr_old[3]; - unset_ram_timings(); - unset_lcd_custom_rate(); + unset_ram_timings_(); + unset_lcd_custom_rate_(); munmap(gp2x_screens[0], FRAMEBUFF_WHOLESIZE); munmap((void *)gp2x_memregs, 0x10000); diff --git a/gp2x/soc_pollux.c b/gp2x/soc_pollux.c index c8ca1b8..fb7e66f 100644 --- a/gp2x/soc_pollux.c +++ b/gp2x/soc_pollux.c @@ -1,9 +1,249 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "soc.h" +#include "plat_gp2x.h" +#include "../common/emu.h" +#include "../common/arm_utils.h" +#include "pollux_set.h" + +static volatile unsigned short *memregs; +static volatile unsigned long *memregl; +static int memdev = -1; + +extern void *gp2x_screens[4]; + +#define fb_buf_count 4 +static unsigned int fb_paddr[fb_buf_count]; +static int fb_work_buf; +static int fbdev = -1; + + +/* video stuff */ +static void pollux_video_flip(int buf_count) +{ + memregl[0x406C>>2] = fb_paddr[fb_work_buf]; + memregl[0x4058>>2] |= 0x10; + fb_work_buf++; + if (fb_work_buf >= buf_count) + fb_work_buf = 0; + g_screen_ptr = gp2x_screens[fb_work_buf]; +} + +static void gp2x_video_flip_(void) +{ + pollux_video_flip(fb_buf_count); +} + +/* doulblebuffered flip */ +static void gp2x_video_flip2_(void) +{ + pollux_video_flip(2); +} + +static void gp2x_video_changemode_ll_(int bpp) +{ + int code = 0, bytes = 2; + unsigned int r; + switch (bpp) + { + case 8: + code = 0x443a; + bytes = 1; + break; + + case 15: + case 16: + code = 0x4432; + bytes = 2; + break; + + default: + printf("unhandled bpp request: %d\n", bpp); + return; + } + + memregl[0x405c>>2] = bytes; + memregl[0x4060>>2] = bytes * 320; + + r = memregl[0x4058>>2]; + r = (r & 0xffff) | (code << 16) | 0x10; + memregl[0x4058>>2] = r; +} + +static void gp2x_video_setpalette_(int *pal, int len) +{ + /* pollux palette is 16bpp only.. */ + int i; + for (i = 0; i < len; i++) + { + int c = pal[i]; + c = ((c >> 8) & 0xf800) | ((c >> 5) & 0x07c0) | ((c >> 3) & 0x001f); + memregl[0x4070>>2] = (i << 24) | c; + } +} + +static void gp2x_video_RGB_setscaling_(int ln_offs, int W, int H) +{ + /* maybe a job for 3d hardware? */ +} + +static void gp2x_video_wait_vsync_(void) +{ + while (!(memregl[0x308c>>2] & (1 << 10))); + spend_cycles(128); + memregl[0x308c>>2] |= 1 << 10; +} + +/* CPU clock */ +static void gp2x_set_cpuclk_(unsigned int mhz) +{ + char buff[24]; + snprintf(buff, sizeof(buff), "cpuclk=%u", mhz); + pollux_set(memregs, buff); +} + +/* misc */ +static void pollux_set_fromenv(const char *env_var) +{ + const char *set_string; + set_string = getenv(env_var); + if (set_string) + pollux_set(memregs, set_string); + else + printf("env var %s not defined.\n", env_var); +} + +/* RAM timings */ +static unsigned short memtimex[2]; + +static void set_ram_timings_(void) +{ + pollux_set_fromenv("POLLUX_RAM_TIMINGS"); +} + +static void unset_ram_timings_(void) +{ + int i; + + memregs[0x14802>>1] = memtimex[0]; + memregs[0x14804>>1] = memtimex[1] | 0x8000; + + for (i = 0; i < 0x100000; i++) + if (!(memregs[0x14804>>1] & 0x8000)) + break; + + printf("RAM timings reset to startup values.\n"); +} + +/* LCD refresh */ +static void set_lcd_custom_rate_(int is_pal) +{ + char buff[32]; + + snprintf(buff, sizeof(buff), "POLLUX_LCD_TIMINGS_%s", is_pal ? "PAL" : "NTSC"); + pollux_set_fromenv(buff); +} + +static void unset_lcd_custom_rate_(void) +{ +} + +static void set_lcd_gamma_(int g100, int A_SNs_curve) +{ + /* hm, the LCD possibly can do it (but not POLLUX) */ +} void pollux_init(void) { + struct fb_fix_screeninfo fbfix; + int i, ret; + + memdev = open("/dev/mem", O_RDWR); + if (memdev == -1) { + perror("open(/dev/mem) failed"); + exit(1); + } + + memregs = mmap(0, 0x20000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0xc0000000); + if (memregs == MAP_FAILED) { + perror("mmap(memregs) failed"); + exit(1); + } + memregl = (volatile void *)memregs; + + fbdev = open("/dev/fb0", O_RDWR); + if (fbdev < 0) { + perror("can't open fbdev"); + exit(1); + } + + ret = ioctl(fbdev, FBIOGET_FSCREENINFO, &fbfix); + if (ret == -1) { + perror("ioctl(fbdev) failed"); + exit(1); + } + + printf("framebuffer: \"%s\" @ %08lx\n", fbfix.id, fbfix.smem_start); + fb_paddr[0] = fbfix.smem_start; + + gp2x_screens[0] = mmap(0, 320*240*2*fb_buf_count, PROT_READ|PROT_WRITE, + MAP_SHARED, memdev, fb_paddr[0]); + if (gp2x_screens[0] == MAP_FAILED) + { + perror("mmap(gp2x_screens) failed"); + exit(1); + } + memset(gp2x_screens[0], 0, 320*240*2*fb_buf_count); + + printf(" %p -> %08x\n", gp2x_screens[0], fb_paddr[0]); + for (i = 1; i < fb_buf_count; i++) + { + fb_paddr[i] = fb_paddr[i-1] + 320*240*2; + gp2x_screens[i] = (char *)gp2x_screens[i-1] + 320*240*2; + printf(" %p -> %08x\n", gp2x_screens[i], fb_paddr[i]); + } + fb_work_buf = 0; + g_screen_ptr = gp2x_screens[0]; + + memtimex[0] = memregs[0x14802>>1]; + memtimex[1] = memregs[0x14804>>1]; + + gp2x_video_flip = gp2x_video_flip_; + gp2x_video_flip2 = gp2x_video_flip2_; + gp2x_video_changemode_ll = gp2x_video_changemode_ll_; + gp2x_video_setpalette = gp2x_video_setpalette_; + gp2x_video_RGB_setscaling = gp2x_video_RGB_setscaling_; + gp2x_video_wait_vsync = gp2x_video_wait_vsync_; + + gp2x_set_cpuclk = gp2x_set_cpuclk_; + + set_lcd_custom_rate = set_lcd_custom_rate_; + unset_lcd_custom_rate = unset_lcd_custom_rate_; + set_lcd_gamma = set_lcd_gamma_; + + set_ram_timings = set_ram_timings_; + unset_ram_timings = unset_ram_timings_; } void pollux_finish(void) { + /* switch to default fb mem, turn portrait off */ + memregl[0x406C>>2] = fb_paddr[0]; + memregl[0x4058>>2] |= 0x10; +// wiz_lcd_set_portrait(0); + close(fbdev); + + munmap((void *)memregs, 0x20000); + close(memdev); } -- 2.39.5