fix build
[ginge.git] / common / wiz_video.c
1 /*
2  * GINGE - GINGE Is Not Gp2x Emulator
3  * (C) notaz, 2010-2011
4  *
5  * This work is licensed under the MAME license, see COPYING file for details.
6  */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <fcntl.h>
13 #include <sys/ioctl.h>
14 #include <sys/mman.h>
15 #include <unistd.h>
16 #include <linux/fb.h>
17 #include "warm/warm.h"
18
19 static volatile unsigned short *memregs;
20 static volatile unsigned int   *memregl;
21 int probably_caanoo;
22 int memdev = -1;
23
24 #define FB_BUF_COUNT 4
25 static unsigned int fb_paddr[FB_BUF_COUNT];
26 static int fb_buf_count = FB_BUF_COUNT;
27 static int fb_work_buf;
28 static int fbdev = -1;
29
30 static void *gp2x_screens[FB_BUF_COUNT];
31 static void *g_screen_ptr;
32
33
34 static void vout_gp2x_flip(void)
35 {
36         memregl[0x406C>>2] = fb_paddr[fb_work_buf];
37         memregl[0x4058>>2] |= 0x10;
38
39         fb_work_buf++;
40         if (fb_work_buf >= fb_buf_count)
41                 fb_work_buf = 0;
42         g_screen_ptr = gp2x_screens[fb_work_buf];
43 }
44
45 static int vout_gp2x_init(int no_dblbuf)
46 {
47         struct fb_fix_screeninfo fbfix;
48         int i, ret;
49
50         memdev = open("/dev/mem", O_RDWR);
51         if (memdev == -1) {
52                 perror("open(/dev/mem) failed");
53                 exit(1);
54         }
55
56         memregs = mmap(0, 0x20000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0xc0000000);
57         if (memregs == MAP_FAILED) {
58                 perror("mmap(memregs) failed");
59                 exit(1);
60         }
61         memregl = (volatile void *)memregs;
62
63         fbdev = open("/dev/fb0", O_RDWR);
64         if (fbdev < 0) {
65                 perror("can't open fbdev");
66                 exit(1);
67         }
68
69         ret = ioctl(fbdev, FBIOGET_FSCREENINFO, &fbfix);
70         if (ret == -1) {
71                 perror("ioctl(fbdev) failed");
72                 exit(1);
73         }
74
75         printf("framebuffer: \"%s\" @ %08lx\n", fbfix.id, fbfix.smem_start);
76         fb_paddr[0] = fbfix.smem_start;
77         probably_caanoo = fb_paddr[0] >= 0x4000000;
78         printf("looking like Caanoo? %s.\n", probably_caanoo ? "yes" : "no");
79
80         gp2x_screens[0] = mmap(0, 320*240*2*FB_BUF_COUNT, PROT_READ|PROT_WRITE,
81                         MAP_SHARED, memdev, fb_paddr[0]);
82         if (gp2x_screens[0] == MAP_FAILED)
83         {
84                 perror("mmap(gp2x_screens) failed");
85                 exit(1);
86         }
87         memset(gp2x_screens[0], 0, 320*240*2*FB_BUF_COUNT);
88
89         if (!no_dblbuf) {
90                 warm_init();
91                 ret = warm_change_cb_range(WCB_B_BIT, 1, gp2x_screens[0], 320*240*2*FB_BUF_COUNT);
92                 if (ret != 0)
93                         fprintf(stderr, "could not make fb buferable.\n");
94         }
95
96         // printf("  %p -> %08x\n", gp2x_screens[0], fb_paddr[0]);
97         for (i = 1; i < FB_BUF_COUNT; i++)
98         {
99                 fb_paddr[i] = fb_paddr[i-1] + 320*240*2;
100                 gp2x_screens[i] = (char *)gp2x_screens[i-1] + 320*240*2;
101                 // printf("  %p -> %08x\n", gp2x_screens[i], fb_paddr[i]);
102         }
103         fb_work_buf = 0;
104         g_screen_ptr = gp2x_screens[0];
105
106         if (no_dblbuf)
107                 fb_buf_count = 1;
108
109         return 0;
110 }
111
112 static void vout_gp2x_set_mode(int bpp, int rot)
113 {
114         int rot_cmd[2] = { 0, 0 };
115         int code = 0, bytes = 2;
116         unsigned int r;
117         int ret;
118
119         if (probably_caanoo)
120                 rot = 0;
121
122         rot_cmd[0] = rot ? 6 : 5;
123         ret = ioctl(fbdev, _IOW('D', 90, int[2]), rot_cmd);
124         if (ret < 0)
125                 perror("rot ioctl failed");
126
127         memregl[0x4004>>2] = rot ? 0x013f00ef : 0x00ef013f;
128         memregl[0x4000>>2] |= 1 << 3;
129
130         switch (bpp)
131         {
132                 case 8:
133                         code = 0x443a;
134                         bytes = 1;
135                         break;
136
137                 case 15:
138                 case 16:
139                         code = 0x4432;
140                         bytes = 2;
141                         break;
142
143                 default:
144                         fprintf(stderr, "unhandled bpp request: %d\n", abs(bpp));
145                         return;
146         }
147
148         memregl[0x405c>>2] = bytes;
149         memregl[0x4060>>2] = bytes * (rot ? 240 : 320);
150
151         r = memregl[0x4058>>2];
152         r = (r & 0xffff) | (code << 16) | 0x10;
153         memregl[0x4058>>2] = r;
154 }
155
156 static void vout_gp2x_set_palette16(unsigned short *pal, int len)
157 {
158         int i;
159         for (i = 0; i < len; i++)
160                 memregl[0x4070>>2] = (i << 24) | pal[i];
161 }
162
163 static void vout_gp2x_set_palette32(unsigned int *pal, int len)
164 {
165         /* pollux palette is 16bpp only.. */
166         int i;
167         for (i = 0; i < len; i++)
168         {
169                 int c = pal[i];
170                 c = ((c >> 8) & 0xf800) | ((c >> 5) & 0x07c0) | ((c >> 3) & 0x001f);
171                 memregl[0x4070>>2] = (i << 24) | c;
172         }
173 }
174
175 void vout_gp2x_finish(void)
176 {
177         if (memregl != NULL) {
178                 if (memregl[0x4058>>2] & 0x10)
179                         usleep(100000);
180                 if (memregl[0x4058>>2] & 0x10)
181                         printf("MLCCONTROL1 dirty? %08x %08x\n",
182                                 memregl[0x406C>>2], memregl[0x4058>>2]);
183
184                 memregl[0x406C>>2] = fb_paddr[0];
185                 memregl[0x4058>>2] |= 0x10;
186                 munmap((void *)memregs, 0x20000);
187                 memregs = NULL;
188                 memregl = NULL;
189         }
190
191         close(fbdev);
192         close(memdev);
193
194         warm_finish();
195 }
196