more unification; replace some magic bits to defines
[libpicofe.git] / gp2x / soc_pollux.c
CommitLineData
fa8d1331 1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <math.h>
5#include <sys/types.h>
6#include <sys/stat.h>
7#include <fcntl.h>
8#include <sys/mman.h>
9#include <unistd.h>
10#include <sys/ioctl.h>
11#include <linux/fb.h>
12
13#include "soc.h"
14#include "plat_gp2x.h"
15#include "../common/emu.h"
16#include "../common/arm_utils.h"
17#include "pollux_set.h"
18
19static volatile unsigned short *memregs;
20static volatile unsigned long *memregl;
21static int memdev = -1;
22
23extern void *gp2x_screens[4];
24
25#define fb_buf_count 4
26static unsigned int fb_paddr[fb_buf_count];
27static int fb_work_buf;
28static int fbdev = -1;
29
30
31/* video stuff */
32static void pollux_video_flip(int buf_count)
33{
34 memregl[0x406C>>2] = fb_paddr[fb_work_buf];
35 memregl[0x4058>>2] |= 0x10;
36 fb_work_buf++;
37 if (fb_work_buf >= buf_count)
38 fb_work_buf = 0;
39 g_screen_ptr = gp2x_screens[fb_work_buf];
40}
41
42static void gp2x_video_flip_(void)
43{
44 pollux_video_flip(fb_buf_count);
45}
46
47/* doulblebuffered flip */
48static void gp2x_video_flip2_(void)
49{
50 pollux_video_flip(2);
51}
52
53static void gp2x_video_changemode_ll_(int bpp)
54{
55 int code = 0, bytes = 2;
56 unsigned int r;
57 switch (bpp)
58 {
59 case 8:
60 code = 0x443a;
61 bytes = 1;
62 break;
63
64 case 15:
65 case 16:
66 code = 0x4432;
67 bytes = 2;
68 break;
69
70 default:
71 printf("unhandled bpp request: %d\n", bpp);
72 return;
73 }
74
75 memregl[0x405c>>2] = bytes;
76 memregl[0x4060>>2] = bytes * 320;
77
78 r = memregl[0x4058>>2];
79 r = (r & 0xffff) | (code << 16) | 0x10;
80 memregl[0x4058>>2] = r;
81}
82
83static void gp2x_video_setpalette_(int *pal, int len)
84{
85 /* pollux palette is 16bpp only.. */
86 int i;
87 for (i = 0; i < len; i++)
88 {
89 int c = pal[i];
90 c = ((c >> 8) & 0xf800) | ((c >> 5) & 0x07c0) | ((c >> 3) & 0x001f);
91 memregl[0x4070>>2] = (i << 24) | c;
92 }
93}
94
95static void gp2x_video_RGB_setscaling_(int ln_offs, int W, int H)
96{
97 /* maybe a job for 3d hardware? */
98}
99
100static void gp2x_video_wait_vsync_(void)
101{
102 while (!(memregl[0x308c>>2] & (1 << 10)));
103 spend_cycles(128);
104 memregl[0x308c>>2] |= 1 << 10;
105}
106
107/* CPU clock */
108static void gp2x_set_cpuclk_(unsigned int mhz)
109{
110 char buff[24];
111 snprintf(buff, sizeof(buff), "cpuclk=%u", mhz);
112 pollux_set(memregs, buff);
113}
114
115/* misc */
116static void pollux_set_fromenv(const char *env_var)
117{
118 const char *set_string;
119 set_string = getenv(env_var);
120 if (set_string)
121 pollux_set(memregs, set_string);
122 else
123 printf("env var %s not defined.\n", env_var);
124}
125
126/* RAM timings */
127static unsigned short memtimex[2];
128
129static void set_ram_timings_(void)
130{
131 pollux_set_fromenv("POLLUX_RAM_TIMINGS");
132}
133
134static void unset_ram_timings_(void)
135{
136 int i;
137
138 memregs[0x14802>>1] = memtimex[0];
139 memregs[0x14804>>1] = memtimex[1] | 0x8000;
140
141 for (i = 0; i < 0x100000; i++)
142 if (!(memregs[0x14804>>1] & 0x8000))
143 break;
144
145 printf("RAM timings reset to startup values.\n");
146}
147
148/* LCD refresh */
149static void set_lcd_custom_rate_(int is_pal)
150{
151 char buff[32];
152
153 snprintf(buff, sizeof(buff), "POLLUX_LCD_TIMINGS_%s", is_pal ? "PAL" : "NTSC");
154 pollux_set_fromenv(buff);
155}
156
157static void unset_lcd_custom_rate_(void)
158{
159}
160
161static void set_lcd_gamma_(int g100, int A_SNs_curve)
162{
163 /* hm, the LCD possibly can do it (but not POLLUX) */
164}
d572cbad 165
166void pollux_init(void)
167{
fa8d1331 168 struct fb_fix_screeninfo fbfix;
169 int i, ret;
170
171 memdev = open("/dev/mem", O_RDWR);
172 if (memdev == -1) {
173 perror("open(/dev/mem) failed");
174 exit(1);
175 }
176
177 memregs = mmap(0, 0x20000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0xc0000000);
178 if (memregs == MAP_FAILED) {
179 perror("mmap(memregs) failed");
180 exit(1);
181 }
182 memregl = (volatile void *)memregs;
183
184 fbdev = open("/dev/fb0", O_RDWR);
185 if (fbdev < 0) {
186 perror("can't open fbdev");
187 exit(1);
188 }
189
190 ret = ioctl(fbdev, FBIOGET_FSCREENINFO, &fbfix);
191 if (ret == -1) {
192 perror("ioctl(fbdev) failed");
193 exit(1);
194 }
195
196 printf("framebuffer: \"%s\" @ %08lx\n", fbfix.id, fbfix.smem_start);
197 fb_paddr[0] = fbfix.smem_start;
198
199 gp2x_screens[0] = mmap(0, 320*240*2*fb_buf_count, PROT_READ|PROT_WRITE,
200 MAP_SHARED, memdev, fb_paddr[0]);
201 if (gp2x_screens[0] == MAP_FAILED)
202 {
203 perror("mmap(gp2x_screens) failed");
204 exit(1);
205 }
206 memset(gp2x_screens[0], 0, 320*240*2*fb_buf_count);
207
208 printf(" %p -> %08x\n", gp2x_screens[0], fb_paddr[0]);
209 for (i = 1; i < fb_buf_count; i++)
210 {
211 fb_paddr[i] = fb_paddr[i-1] + 320*240*2;
212 gp2x_screens[i] = (char *)gp2x_screens[i-1] + 320*240*2;
213 printf(" %p -> %08x\n", gp2x_screens[i], fb_paddr[i]);
214 }
215 fb_work_buf = 0;
216 g_screen_ptr = gp2x_screens[0];
217
218 memtimex[0] = memregs[0x14802>>1];
219 memtimex[1] = memregs[0x14804>>1];
220
221 gp2x_video_flip = gp2x_video_flip_;
222 gp2x_video_flip2 = gp2x_video_flip2_;
223 gp2x_video_changemode_ll = gp2x_video_changemode_ll_;
224 gp2x_video_setpalette = gp2x_video_setpalette_;
225 gp2x_video_RGB_setscaling = gp2x_video_RGB_setscaling_;
226 gp2x_video_wait_vsync = gp2x_video_wait_vsync_;
227
228 gp2x_set_cpuclk = gp2x_set_cpuclk_;
229
230 set_lcd_custom_rate = set_lcd_custom_rate_;
231 unset_lcd_custom_rate = unset_lcd_custom_rate_;
232 set_lcd_gamma = set_lcd_gamma_;
233
234 set_ram_timings = set_ram_timings_;
235 unset_ram_timings = unset_ram_timings_;
d572cbad 236}
237
238void pollux_finish(void)
239{
fa8d1331 240 /* switch to default fb mem, turn portrait off */
241 memregl[0x406C>>2] = fb_paddr[0];
242 memregl[0x4058>>2] |= 0x10;
243// wiz_lcd_set_portrait(0);
244 close(fbdev);
245
246 munmap((void *)memregs, 0x20000);
247 close(memdev);
d572cbad 248}
249