gp2x+wiz binary support, wiz code wip
authornotaz <notasas@gmail.com>
Fri, 17 Jul 2009 22:49:29 +0000 (22:49 +0000)
committernotaz <notasas@gmail.com>
Fri, 17 Jul 2009 22:49:29 +0000 (22:49 +0000)
git-svn-id: file:///home/notaz/opt/svn/PicoDrive/platform@705 be3aeb3a-fb24-0410-a615-afba39da0efa

17 files changed:
common/config.c
common/emu.c
common/emu.h
common/menu.c
common/menu.h
common/plat.h
gp2x/Makefile
gp2x/emu.c
gp2x/in_gp2x.c
gp2x/main.c
gp2x/plat.c
gp2x/pollux_set.c [new file with mode: 0644]
gp2x/pollux_set.h [new file with mode: 0644]
gp2x/soc.c
gp2x/soc.h
gp2x/soc_mmsp2.c
gp2x/soc_pollux.c

index c5ff538..4f80c86 100644 (file)
@@ -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;
index 542abf5..5f18dd0 100644 (file)
@@ -5,7 +5,6 @@
 \r
 #include <stdio.h>\r
 #include <stdlib.h>\r
-#include <ctype.h> // tolower\r
 #ifndef NO_SYNC\r
 #include <unistd.h>\r
 #endif\r
@@ -47,12 +46,13 @@ unsigned char *movie_data = NULL;
 static int movie_size = 0;\r
 \r
 \r
-// utilities\r
+/* don't use tolower() for easy old glibc binary compatibility */\r
 static void strlwr_(char *string)\r
 {\r
        char *p;\r
        for (p = string; *p; p++)\r
-               *p = (char)tolower(*p);\r
+               if ('A' <= *p && *p <= 'Z')\r
+                       *p += 'a' - 'A';\r
 }\r
 \r
 static int try_rfn_cut(char *fname)\r
@@ -621,17 +621,21 @@ int emu_ReadConfig(int game, int no_defaults)
                }\r
        }\r
 \r
+       plat_validate_config();\r
+\r
        // some sanity checks\r
-       if (currentConfig.CPUclock < 10 || currentConfig.CPUclock > 4096) currentConfig.CPUclock = 200;\r
 #ifdef PSP\r
+       /* TODO: mv to plat_validate_config() */\r
+       if (currentConfig.CPUclock < 10 || currentConfig.CPUclock > 4096) currentConfig.CPUclock = 200;\r
        if (currentConfig.gamma < -4 || currentConfig.gamma >  16) currentConfig.gamma = 0;\r
        if (currentConfig.gamma2 < 0 || currentConfig.gamma2 > 2)  currentConfig.gamma2 = 0;\r
-#else\r
-       if (currentConfig.gamma < 10 || currentConfig.gamma > 300) currentConfig.gamma = 100;\r
 #endif\r
-       if (currentConfig.volume < 0 || currentConfig.volume > 99) currentConfig.volume = 50;\r
+       if (currentConfig.volume < 0 || currentConfig.volume > 99)\r
+               currentConfig.volume = 50;\r
+\r
+       if (ret == 0)\r
+               config_slot_current = config_slot;\r
 \r
-       if (ret == 0) config_slot_current = config_slot;\r
        return (ret == 0);\r
 }\r
 \r
index 2c8de5c..808bcb0 100644 (file)
@@ -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,
index d7d93b3..b5c3495 100644 (file)
@@ -1443,12 +1443,12 @@ static int menu_loop_adv_options(menu_id id, int keys)
 \r
 static const char *mgn_opt_scaling(menu_id id, int *offs)\r
 {\r
-       *offs = -12;\r
+       *offs = -13;\r
        switch (currentConfig.scaling) {\r
-               default: return "            OFF";\r
-               case 1:  return "hw horizontal";\r
-               case 2:  return "hw horiz. + vert.";\r
-               case 3:  return "sw horizontal";\r
+               default:               return "             OFF";\r
+               case EOPT_SCALE_HW_H:  return "   hw horizontal";\r
+               case EOPT_SCALE_HW_HV: return "hw horiz. + vert";\r
+               case EOPT_SCALE_SW_H:  return "   sw horizontal";\r
        }\r
 }\r
 \r
@@ -1462,8 +1462,8 @@ static menu_entry e_menu_gfx_options[] =
 {\r
        mee_range_cust("Scaling",                  MA_OPT_SCALING,        currentConfig.scaling, 0, 3, mgn_opt_scaling),\r
        mee_range_cust("Gamma correction",         MA_OPT2_GAMMA,         currentConfig.gamma, 1, 300, mgn_aopt_gamma),\r
-       mee_onoff     ("A_SN's gamma curve",       MA_OPT2_A_SN_GAMMA,    currentConfig.EmuOpt, 0x1000),\r
-       mee_onoff     ("Perfect vsync",            MA_OPT2_VSYNC,         currentConfig.EmuOpt, 0x2000),\r
+       mee_onoff     ("A_SN's gamma curve",       MA_OPT2_A_SN_GAMMA,    currentConfig.EmuOpt, EOPT_A_SN_GAMMA),\r
+       mee_onoff     ("Perfect vsync",            MA_OPT2_VSYNC,         currentConfig.EmuOpt, EOPT_PSYNC),\r
        mee_end,\r
 };\r
 \r
@@ -2044,6 +2044,22 @@ void me_update_msg(const char *msg)
 \r
 // ------------ util ------------\r
 \r
+/* wiz for now, probably extend later */\r
+void menu_plat_setup(int is_wiz)\r
+{\r
+       int i;\r
+\r
+       if (!is_wiz)\r
+               return;\r
+\r
+       me_enable(e_menu_adv_options, MA_OPT_ARM940_SOUND, 0);\r
+       me_enable(e_menu_gfx_options, MA_OPT2_GAMMA, 0);\r
+       me_enable(e_menu_gfx_options, MA_OPT2_A_SN_GAMMA, 0);\r
+\r
+       i = me_id2offset(e_menu_gfx_options, MA_OPT_SCALING);\r
+       e_menu_gfx_options[i].max = 1;  /* only off and sw */\r
+}\r
+\r
 /* TODO: rename */\r
 void menu_darken_bg(void *dst, int pixels, int darker)\r
 {\r
index 430f002..588bfb9 100644 (file)
@@ -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);
 
index ac7a438..607b811 100644 (file)
@@ -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);
index 01dbaf4..00fdb78 100644 (file)
@@ -32,20 +32,20 @@ use_cyclone = 1
 endif\r
 \r
 DEFINC = -I../.. -I. -DARM -D__GP2X__ -DIN_GP2X # -DBENCHMARK\r
-COPT_COMMON = -Wall -Winline\r
-COPT_COMMON += -static\r
+CFLAGS += -Wall -Winline\r
 ifeq ($(DEBUG),)\r
-COPT_COMMON += -O3 -ftracer -fstrength-reduce -fomit-frame-pointer -fstrict-aliasing -ffast-math\r
+# -ftracer # TODO measure impact\r
+CFLAGS += -O3 -fstrength-reduce -fomit-frame-pointer -fstrict-aliasing -ffast-math\r
 else\r
-COPT_COMMON += -ggdb\r
+CFLAGS += -ggdb\r
 endif\r
 ifeq "$(profile)" "1"\r
-COPT_COMMON += -fprofile-generate\r
+CFLAGS += -fprofile-generate\r
 endif\r
 ifeq "$(profile)" "2"\r
-COPT_COMMON += -fprofile-use\r
+CFLAGS += -fprofile-use\r
 endif\r
-CFLAGS = $(COPT_COMMON) -mcpu=arm920t -mtune=arm920t\r
+CFLAGS += -mcpu=arm920t -mtune=arm920t\r
 SFLAGS = $(CFLAGS)\r
 ASFLAGS = -mcpu=arm920t -mfloat-abi=soft\r
 CC = $(CROSS)gcc\r
@@ -55,7 +55,7 @@ LD = $(CROSS)ld
 OBJCOPY = $(CROSS)objcopy\r
 \r
 # frontend\r
-OBJS += main.o soc.o soc_mmsp2.o soc_pollux.o emu.o in_gp2x.o plat.o warm.o\r
+OBJS += main.o soc.o soc_mmsp2.o soc_pollux.o pollux_set.o emu.o in_gp2x.o plat.o warm.o\r
 # 940 core control\r
 OBJS += 940ctl.o\r
 \r
@@ -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\r
 \r
 \r
-all: mkdirs PicoDrive.gpe\r
+all: mkdirs PicoDrive\r
 \r
 include ../common/common_arm.mak\r
 \r
-PicoDrive.gpe : $(OBJS) ../common/helix/$(CROSS)helix-mp3.a\r
+PicoDrive : $(OBJS) ../common/helix/$(CROSS)helix-mp3.a\r
        @echo ">>>" $@\r
        $(CC) -o $@ $(CFLAGS) $^ -lm -lpng -Wl,-Map=PicoDrive.map\r
 ifeq ($(DEBUG),)\r
        $(STRIP) $@\r
 endif\r
 \r
-up: PicoDrive.gpe\r
-       @cp -v PicoDrive.gpe /mnt/gp2x/mnt/sd/emus/PicoDrive/\r
+up: PicoDrive\r
+       @cp -v PicoDrive /mnt/gp2x/mnt/sd/emus/PicoDrive/\r
 \r
 clean: tidy\r
-       $(RM) PicoDrive.gpe\r
+       $(RM) PicoDrive\r
 tidy:\r
        $(RM) $(OBJS)\r
 \r
@@ -151,7 +151,7 @@ $(error need VER)
 endif\r
 endif\r
 \r
-rel: PicoDrive.gpe code940/pico940_v3.bin readme.txt PicoDrive.man.txt PicoDrive.png ../game_def.cfg\r
+rel: PicoDrive PicoDrive.gpe code940/pico940_v3.bin readme.txt PicoDrive.man.txt PicoDrive.png ../game_def.cfg\r
        zip -9 -j ../../PicoDrive_$(VER).zip $^ mmuhack.o\r
        zip -9 -r ../../PicoDrive_$(VER).zip skin -i \*.png -i \*.txt\r
        mkdir bin_to_cso_mp3\r
index 592c360..c78b706 100644 (file)
@@ -101,12 +101,16 @@ void emu_Init(void)
 \r
 static void scaling_update(void)\r
 {\r
-       PicoOpt &= ~0x4100;\r
+       PicoOpt &= ~(POPT_DIS_32C_BORDER|POPT_EN_SOFTSCALE);\r
        switch (currentConfig.scaling) {\r
-               default: break; // off\r
-               case 1:  // hw hor\r
-               case 2:  PicoOpt |=  0x0100; break; // hw hor+vert\r
-               case 3:  PicoOpt |=  0x4000; break; // sw hor\r
+               default:break;\r
+               case EOPT_SCALE_HW_H:\r
+               case EOPT_SCALE_HW_HV:\r
+                       PicoOpt |= POPT_DIS_32C_BORDER;\r
+                       break;\r
+               case EOPT_SCALE_SW_H:\r
+                       PicoOpt |= POPT_EN_SOFTSCALE;\r
+                       break;\r
        }\r
 }\r
 \r
@@ -133,19 +137,25 @@ void emu_Deinit(void)
 \r
 void emu_prepareDefaultConfig(void)\r
 {\r
+       gp2x_soc_t soc;\r
+\r
        memset(&defaultConfig, 0, sizeof(defaultConfig));\r
-       defaultConfig.EmuOpt    = 0x9d | 0x00700; // | <- ram_tmng, confirm_save, cd_leds\r
-       defaultConfig.s_PicoOpt = 0x0f | POPT_EXT_FM|POPT_EN_MCD_PCM|POPT_EN_MCD_CDDA|POPT_EN_SVP_DRC|POPT_ACC_SPRITES;\r
+       defaultConfig.EmuOpt    = 0x9d | EOPT_RAM_TIMINGS | 0x600; // | <- confirm_save, cd_leds\r
+       defaultConfig.s_PicoOpt = 0x0f | POPT_EN_MCD_PCM|POPT_EN_MCD_CDDA|POPT_EN_SVP_DRC|POPT_ACC_SPRITES;\r
        defaultConfig.s_PsndRate = 44100;\r
        defaultConfig.s_PicoRegion = 0; // auto\r
        defaultConfig.s_PicoAutoRgnOrder = 0x184; // US, EU, JP\r
        defaultConfig.s_PicoCDBuffers = 0;\r
        defaultConfig.Frameskip = -1; // auto\r
-       defaultConfig.CPUclock = -1;\r
+       defaultConfig.CPUclock = default_cpu_clock;\r
        defaultConfig.volume = 50;\r
        defaultConfig.gamma = 100;\r
        defaultConfig.scaling = 0;\r
        defaultConfig.turbo_rate = 15;\r
+\r
+       soc = soc_detect();\r
+       if (soc == SOCID_MMSP2)\r
+               defaultConfig.s_PicoOpt |= POPT_EXT_FM;\r
 }\r
 \r
 void osd_text(int x, int y, const char *text)\r
@@ -295,8 +305,10 @@ static void blit(const char *fps, const char *notice)
 \r
        if (notice || (emu_opt & 2)) {\r
                int h = 232;\r
-               if (currentConfig.scaling == 2 && !(Pico.video.reg[1]&8)) h -= 8;\r
-               if (notice) osd_text(4, h, notice);\r
+               if (currentConfig.scaling == EOPT_SCALE_HW_HV && !(Pico.video.reg[1]&8))\r
+                       h -= 8;\r
+               if (notice)\r
+                       osd_text(4, h, notice);\r
                if (emu_opt & 2)\r
                        osd_text(osd_fps_x, h, fps);\r
        }\r
@@ -362,7 +374,7 @@ static void vidResetMode(void)
        }\r
        Pico.m.dirtyPal = 1;\r
        // reset scaling\r
-       if (currentConfig.scaling == 2 && !(Pico.video.reg[1]&8))\r
+       if (currentConfig.scaling == EOPT_SCALE_HW_HV && !(Pico.video.reg[1]&8))\r
             gp2x_video_RGB_setscaling(8, (PicoOpt&0x100)&&!(Pico.video.reg[12]&1) ? 256 : 320, 224);\r
        else gp2x_video_RGB_setscaling(0, (PicoOpt&0x100)&&!(Pico.video.reg[12]&1) ? 256 : 320, 240);\r
 }\r
@@ -773,16 +785,13 @@ void emu_Loop(void)
 \r
        if ((EmuOpt_old ^ currentConfig.EmuOpt) & EOPT_RAM_TIMINGS) {\r
                if (currentConfig.EmuOpt & EOPT_RAM_TIMINGS)\r
-                       /* craigix: --cas 2 --trc 6 --tras 4 --twr 1 --tmrd 1 --trfc 1 --trp 2 --trcd 2 */\r
-                       set_ram_timings(2, 6, 4, 1, 1, 1, 2, 2);\r
+                       set_ram_timings();\r
                else\r
                        unset_ram_timings();\r
        }\r
 \r
        if (gp2x_old_clock < 0)\r
                gp2x_old_clock = default_cpu_clock;\r
-       if (currentConfig.CPUclock < 0)\r
-               currentConfig.CPUclock = default_cpu_clock;\r
        if (gp2x_old_clock != currentConfig.CPUclock) {\r
                printf("changing clock to %i...", currentConfig.CPUclock); fflush(stdout);\r
                gp2x_set_cpuclk(currentConfig.CPUclock);\r
@@ -885,7 +894,8 @@ void emu_Loop(void)
                                        vidCpyM2 = vidCpyM2_32col;\r
                                }\r
                        }\r
-                       if (currentConfig.scaling == 2 && !(modes&8)) // want vertical scaling and game is not in 240 line mode\r
+                       /* want vertical scaling and game is not in 240 line mode */\r
+                       if (currentConfig.scaling == EOPT_SCALE_HW_HV && !(modes&8))\r
                             gp2x_video_RGB_setscaling(8, scalex, 224);\r
                        else gp2x_video_RGB_setscaling(0, scalex, 240);\r
                        oldmodes = modes;\r
index 8066ca7..ab4ba17 100644 (file)
@@ -1,5 +1,10 @@
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
 
 #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;
index 7ceeec3..6ac16b8 100644 (file)
@@ -66,6 +66,8 @@ int main(int argc, char *argv[])
 {\r
        g_argv = argv;\r
 \r
+       plat_early_init();\r
+\r
        /* in_init() must go before config, config accesses in_ fwk */\r
        in_init();\r
        emu_prepareDefaultConfig();\r
index 4ae956c..c2dce2d 100644 (file)
@@ -12,6 +12,8 @@
 #include "../common/emu.h"
 #include "../linux/sndout_oss.h"
 
+#include <pico/pico.h>
+
 /* 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 (file)
index 0000000..fc60b27
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+static void usage(const char *binary)
+{
+       int i;
+       printf("usage:\n%s <set_str[;set_str[;...]]>\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 (file)
index 0000000..64bb220
--- /dev/null
@@ -0,0 +1,10 @@
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+int pollux_set(volatile unsigned short *memregs, const char *str);
+
+#ifdef __cplusplus
+}
+#endif
index 68b2c89..d9b956f 100644 (file)
@@ -7,7 +7,23 @@
 #include <unistd.h>
 
 #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)
 {
index 7f84e97..35fe804 100644 (file)
@@ -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);
 
index 32399d7..c136287 100644 (file)
@@ -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);
index c8ca1b8..fb7e66f 100644 (file)
@@ -1,9 +1,249 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/fb.h>
+
+#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);
 }