* (of course, that's handled by a different source file :)
*/
-//#include <stdio.h>
-//#include <string.h>
-#include <ctype.h>
-
#include "pico_int.h"
#include "patch.h"
void PicoWrite16(unsigned int a, unsigned short d);
+/* avoid dependency on newer glibc */
+static int isspace_(int c)
+{
+ return (0x09 <= c && c <= 0x0d) || c == ' ';
+}
+
void PicoPatchUnload(void)
{
if (PicoPatches != NULL)
llen = strlen(buff);
for (clen = 0; clen < llen; clen++)
- if (isspace(buff[clen])) break;
+ if (isspace_(buff[clen]))
+ break;
buff[clen] = 0;
if (clen > 11 || clen < 8)
strcpy(PicoPatches[PicoPatchCount].code, buff);
/* strip */
for (clen++; clen < llen; clen++)
- if (!isspace(buff[clen])) break;
+ if (!isspace_(buff[clen]))
+ break;
for (llen--; llen > 0; llen--)
- if (!isspace(buff[llen])) break;
+ if (!isspace_(buff[llen]))
+ break;
buff[llen+1] = 0;
strncpy(PicoPatches[PicoPatchCount].name, buff + clen, 51);
PicoPatches[PicoPatchCount].name[51] = 0;
#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;
\r
#include <stdio.h>\r
#include <stdlib.h>\r
-#include <ctype.h> // tolower\r
#ifndef NO_SYNC\r
#include <unistd.h>\r
#endif\r
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
}\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
#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,
\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
{\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
\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
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);
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);
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);
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
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
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
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
\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
\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
\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
}\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
\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
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
+#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"
* 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,
[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;
#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);
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;
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;
{\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
#include "../common/emu.h"
#include "../linux/sndout_oss.h"
+#include <pico/pico.h>
+
/* GP2X local */
int default_cpu_clock;
void *gp2x_screens[4];
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;
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;
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();
--- /dev/null
+/*
+ * 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
--- /dev/null
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+int pollux_set(volatile unsigned short *memregs, const char *str);
+
+#ifdef __cplusplus
+}
+#endif
#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)
{
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);
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 };
/* 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);
}
/* doulblebuffered flip */
-void gp2x_video_flip2(void)
+static void gp2x_video_flip2_(void)
{
unsigned short msw = (unsigned short)(gp2x_screenaddrs_use[screensel&1] >> 16);
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];
*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;
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
// 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))
#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;
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);
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;
}
}
-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;
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;
/* 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)
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);
+#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);
}