Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Latest commit

 

History

History
795 lines (660 loc) · 21.3 KB

SDL_ipodvideo.c

File metadata and controls

795 lines (660 loc) · 21.3 KB
 
Feb 21, 2006
Feb 21, 2006
1
2
/*
SDL - Simple DirectMedia Layer
Dec 8, 2008
Dec 8, 2008
3
Copyright (C) 1997-2009 Sam Lantinga
Feb 21, 2006
Feb 21, 2006
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
Sep 8, 2005
Sep 8, 2005
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <sys/types.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <termios.h>
#include <ctype.h>
#include <linux/vt.h>
#include <linux/kd.h>
#include <linux/keyboard.h>
#include <linux/fb.h>
#include "SDL_video.h"
#include "SDL_mouse.h"
Feb 16, 2006
Feb 16, 2006
40
41
42
#include "../SDL_sysvideo.h"
#include "../SDL_pixels_c.h"
#include "../../events/SDL_events_c.h"
Sep 8, 2005
Sep 8, 2005
43
44
45
46
47
#include "SDL_sysevents.h"
#include "SDL_ipodvideo.h"
#define _THIS SDL_VideoDevice *this
Jul 10, 2006
Jul 10, 2006
48
49
50
51
52
53
54
55
56
57
58
static int iPod_VideoInit(_THIS, SDL_PixelFormat * vformat);
static SDL_Rect **iPod_ListModes(_THIS, SDL_PixelFormat * format,
Uint32 flags);
static SDL_Surface *iPod_SetVideoMode(_THIS, SDL_Surface * current,
int width, int height, int bpp,
Uint32 flags);
static int iPod_SetColors(_THIS, int firstcolor, int ncolors,
SDL_Color * colors);
static void iPod_UpdateRects(_THIS, int nrects, SDL_Rect * rects);
static void iPod_VideoQuit(_THIS);
static void iPod_PumpEvents(_THIS);
Sep 8, 2005
Sep 8, 2005
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
static long iPod_GetGeneration();
static int initd = 0;
static int kbfd = -1;
static int fbfd = -1;
static int oldvt = -1;
static int curvt = -1;
static int old_kbmode = -1;
static long generation = 0;
static struct termios old_termios, cur_termios;
FILE *dbgout;
#define LCD_DATA 0x10
#define LCD_CMD 0x08
#define IPOD_OLD_LCD_BASE 0xc0001000
#define IPOD_OLD_LCD_RTC 0xcf001110
#define IPOD_NEW_LCD_BASE 0x70003000
#define IPOD_NEW_LCD_RTC 0x60005010
static unsigned long lcd_base, lcd_rtc, lcd_width, lcd_height;
Jul 10, 2006
Jul 10, 2006
82
83
static long
iPod_GetGeneration()
Sep 8, 2005
Sep 8, 2005
84
85
86
87
88
{
int i;
char cpuinfo[256];
char *ptr;
FILE *file;
Jul 10, 2006
Jul 10, 2006
89
Sep 8, 2005
Sep 8, 2005
90
if ((file = fopen("/proc/cpuinfo", "r")) != NULL) {
Jul 10, 2006
Jul 10, 2006
91
92
93
94
while (fgets(cpuinfo, sizeof(cpuinfo), file) != NULL)
if (SDL_strncmp(cpuinfo, "Revision", 8) == 0)
break;
fclose(file);
Sep 8, 2005
Sep 8, 2005
95
96
97
98
}
for (i = 0; !isspace(cpuinfo[i]); i++);
for (; isspace(cpuinfo[i]); i++);
ptr = cpuinfo + i + 2;
Jul 10, 2006
Jul 10, 2006
99
Feb 7, 2006
Feb 7, 2006
100
return SDL_strtol(ptr, NULL, 10);
Sep 8, 2005
Sep 8, 2005
101
102
}
Jul 10, 2006
Jul 10, 2006
103
104
static int
iPod_Available()
Sep 8, 2005
Sep 8, 2005
105
106
107
108
{
return 1;
}
Jul 10, 2006
Jul 10, 2006
109
110
static void
iPod_DeleteDevice(SDL_VideoDevice * device)
Sep 8, 2005
Sep 8, 2005
111
{
Jul 10, 2006
Jul 10, 2006
112
113
free(device->hidden);
free(device);
Sep 8, 2005
Sep 8, 2005
114
115
}
Jul 10, 2006
Jul 10, 2006
116
117
118
119
void
iPod_InitOSKeymap(_THIS)
{
}
Sep 8, 2005
Sep 8, 2005
120
Jul 10, 2006
Jul 10, 2006
121
122
static SDL_VideoDevice *
iPod_CreateDevice(int devindex)
Sep 8, 2005
Sep 8, 2005
123
124
{
SDL_VideoDevice *this;
Jul 10, 2006
Jul 10, 2006
125
126
this = (SDL_VideoDevice *) SDL_malloc(sizeof(SDL_VideoDevice));
Sep 8, 2005
Sep 8, 2005
127
if (this) {
Jul 10, 2006
Jul 10, 2006
128
129
130
memset(this, 0, sizeof *this);
this->hidden = (struct SDL_PrivateVideoData *)
SDL_malloc(sizeof(struct SDL_PrivateVideoData));
Sep 8, 2005
Sep 8, 2005
131
132
}
if (!this || !this->hidden) {
Jul 10, 2006
Jul 10, 2006
133
134
135
136
SDL_OutOfMemory();
if (this)
SDL_free(this);
return 0;
Sep 8, 2005
Sep 8, 2005
137
}
Jul 10, 2006
Jul 10, 2006
138
139
memset(this->hidden, 0, sizeof(struct SDL_PrivateVideoData));
Sep 8, 2005
Sep 8, 2005
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
generation = iPod_GetGeneration();
this->VideoInit = iPod_VideoInit;
this->ListModes = iPod_ListModes;
this->SetVideoMode = iPod_SetVideoMode;
this->SetColors = iPod_SetColors;
this->UpdateRects = iPod_UpdateRects;
this->VideoQuit = iPod_VideoQuit;
this->AllocHWSurface = 0;
this->CheckHWBlit = 0;
this->FillHWRect = 0;
this->SetHWColorKey = 0;
this->SetHWAlpha = 0;
this->LockHWSurface = 0;
this->UnlockHWSurface = 0;
this->FlipHWSurface = 0;
this->FreeHWSurface = 0;
this->SetCaption = 0;
this->SetIcon = 0;
this->IconifyWindow = 0;
this->GrabInput = 0;
this->GetWMInfo = 0;
this->InitOSKeymap = iPod_InitOSKeymap;
this->PumpEvents = iPod_PumpEvents;
this->free = iPod_DeleteDevice;
return this;
}
VideoBootStrap iPod_bootstrap = {
"ipod", "iPod Framebuffer Driver",
iPod_Available, iPod_CreateDevice
};
//--//
Jul 10, 2006
Jul 10, 2006
176
177
static int
iPod_VideoInit(_THIS, SDL_PixelFormat * vformat)
Sep 8, 2005
Sep 8, 2005
178
179
{
if (!initd) {
Jul 10, 2006
Jul 10, 2006
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
/*** Code adapted/copied from SDL fbcon driver. ***/
static const char *const tty0[] = { "/dev/tty0", "/dev/vc/0", 0 };
static const char *const vcs[] = { "/dev/vc/%d", "/dev/tty%d", 0 };
int i, tty0_fd;
dbgout =
fdopen(open("/etc/sdlpod.log", O_WRONLY | O_SYNC | O_APPEND),
"a");
if (dbgout) {
setbuf(dbgout, 0);
fprintf(dbgout, "--> Started SDL <--\n");
}
// Try to query for a free VT
tty0_fd = -1;
for (i = 0; tty0[i] && (tty0_fd < 0); ++i) {
tty0_fd = open(tty0[i], O_WRONLY, 0);
}
if (tty0_fd < 0) {
tty0_fd = dup(0); /* Maybe stdin is a VT? */
}
ioctl(tty0_fd, VT_OPENQRY, &curvt);
close(tty0_fd);
tty0_fd = open("/dev/tty", O_RDWR, 0);
if (tty0_fd >= 0) {
ioctl(tty0_fd, TIOCNOTTY, 0);
close(tty0_fd);
}
if ((geteuid() == 0) && (curvt > 0)) {
for (i = 0; vcs[i] && (kbfd < 0); ++i) {
char vtpath[12];
SDL_snprintf(vtpath, SDL_arraysize(vtpath), vcs[i], curvt);
kbfd = open(vtpath, O_RDWR);
}
}
if (kbfd < 0) {
if (dbgout)
fprintf(dbgout, "Couldn't open any VC\n");
return -1;
}
if (dbgout)
fprintf(stderr, "Current VT: %d\n", curvt);
if (kbfd >= 0) {
/* Switch to the correct virtual terminal */
if (curvt > 0) {
struct vt_stat vtstate;
if (ioctl(kbfd, VT_GETSTATE, &vtstate) == 0) {
oldvt = vtstate.v_active;
}
if (ioctl(kbfd, VT_ACTIVATE, curvt) == 0) {
if (dbgout)
fprintf(dbgout, "Waiting for switch to this VT... ");
ioctl(kbfd, VT_WAITACTIVE, curvt);
if (dbgout)
fprintf(dbgout, "done!\n");
}
}
// Set terminal input mode
if (tcgetattr(kbfd, &old_termios) < 0) {
if (dbgout)
fprintf(dbgout, "Can't get termios\n");
return -1;
}
cur_termios = old_termios;
// cur_termios.c_iflag &= ~(ICRNL | INPCK | ISTRIP | IXON);
// cur_termios.c_iflag |= (BRKINT);
// cur_termios.c_lflag &= ~(ICANON | ECHO | ISIG | IEXTEN);
// cur_termios.c_oflag &= ~(OPOST);
// cur_termios.c_oflag |= (ONOCR | ONLRET);
cur_termios.c_lflag &= ~(ICANON | ECHO | ISIG);
cur_termios.c_iflag &=
~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
cur_termios.c_cc[VMIN] = 0;
cur_termios.c_cc[VTIME] = 0;
if (tcsetattr(kbfd, TCSAFLUSH, &cur_termios) < 0) {
if (dbgout)
fprintf(dbgout, "Can't set termios\n");
return -1;
}
if (ioctl(kbfd, KDSKBMODE, K_MEDIUMRAW) < 0) {
if (dbgout)
fprintf(dbgout, "Can't set medium-raw mode\n");
return -1;
}
if (ioctl(kbfd, KDSETMODE, KD_GRAPHICS) < 0) {
if (dbgout)
fprintf(dbgout, "Can't set graphics\n");
return -1;
}
}
// Open the framebuffer
if ((fbfd = open("/dev/fb0", O_RDWR)) < 0) {
if (dbgout)
fprintf(dbgout, "Can't open framebuffer\n");
return -1;
} else {
struct fb_var_screeninfo vinfo;
if (dbgout)
fprintf(dbgout, "Generation: %ld\n", generation);
if (generation >= 40000) {
lcd_base = IPOD_NEW_LCD_BASE;
} else {
lcd_base = IPOD_OLD_LCD_BASE;
}
ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo);
close(fbfd);
if (lcd_base == IPOD_OLD_LCD_BASE)
lcd_rtc = IPOD_OLD_LCD_RTC;
else if (lcd_base == IPOD_NEW_LCD_BASE)
lcd_rtc = IPOD_NEW_LCD_RTC;
else {
SDL_SetError("Unknown iPod version");
return -1;
}
lcd_width = vinfo.xres;
lcd_height = vinfo.yres;
if (dbgout)
fprintf(dbgout, "LCD is %dx%d\n", lcd_width, lcd_height);
}
fcntl(kbfd, F_SETFL, O_RDWR | O_NONBLOCK);
/* Determine the current screen size */
this->info.current_w = lcd_width;
this->info.current_h = lcd_height;
if ((generation >= 60000) && (generation < 70000)) {
vformat->BitsPerPixel = 16;
vformat->Rmask = 0xF800;
vformat->Gmask = 0x07E0;
vformat->Bmask = 0x001F;
} else {
vformat->BitsPerPixel = 8;
vformat->Rmask = vformat->Gmask = vformat->Bmask = 0;
}
initd = 1;
if (dbgout)
fprintf(dbgout, "Initialized.\n\n");
Sep 8, 2005
Sep 8, 2005
331
332
333
334
}
return 0;
}
Jul 10, 2006
Jul 10, 2006
335
336
static SDL_Rect **
iPod_ListModes(_THIS, SDL_PixelFormat * format, Uint32 flags)
Sep 8, 2005
Sep 8, 2005
337
338
339
340
341
{
int width, height, fd;
static SDL_Rect r;
static SDL_Rect *rs[2] = { &r, 0 };
Jul 10, 2006
Jul 10, 2006
342
343
if ((fd = open("/dev/fb0", O_RDWR)) < 0) {
return 0;
Sep 8, 2005
Sep 8, 2005
344
} else {
Jul 10, 2006
Jul 10, 2006
345
346
347
348
349
350
351
struct fb_var_screeninfo vinfo;
ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo);
close(fbfd);
width = vinfo.xres;
height = vinfo.yres;
Sep 8, 2005
Sep 8, 2005
352
353
354
355
356
357
358
359
}
r.x = r.y = 0;
r.w = width;
r.h = height;
return rs;
}
Jul 10, 2006
Jul 10, 2006
360
361
362
static SDL_Surface *
iPod_SetVideoMode(_THIS, SDL_Surface * current, int width, int height,
int bpp, Uint32 flags)
Sep 8, 2005
Sep 8, 2005
363
364
365
{
Uint32 Rmask, Gmask, Bmask;
if (bpp > 8) {
Jul 10, 2006
Jul 10, 2006
366
367
368
Rmask = 0xF800;
Gmask = 0x07E0;
Bmask = 0x001F;
Sep 8, 2005
Sep 8, 2005
369
} else {
Jul 10, 2006
Jul 10, 2006
370
Rmask = Gmask = Bmask = 0;
Sep 8, 2005
Sep 8, 2005
371
372
}
Jul 10, 2006
Jul 10, 2006
373
374
375
if (this->hidden->buffer)
SDL_free(this->hidden->buffer);
this->hidden->buffer = SDL_malloc(width * height * (bpp / 8));
Sep 8, 2005
Sep 8, 2005
376
if (!this->hidden->buffer) {
Jul 10, 2006
Jul 10, 2006
377
378
SDL_SetError("Couldn't allocate buffer for requested mode");
return 0;
Sep 8, 2005
Sep 8, 2005
379
380
}
Jul 10, 2006
Jul 10, 2006
381
memset(this->hidden->buffer, 0, width * height * (bpp / 8));
Sep 8, 2005
Sep 8, 2005
382
Jul 10, 2006
Jul 10, 2006
383
384
385
386
387
if (!SDL_ReallocFormat(current, bpp, Rmask, Gmask, Bmask, 0)) {
SDL_SetError("Couldn't allocate new pixel format");
SDL_free(this->hidden->buffer);
this->hidden->buffer = 0;
return 0;
Sep 8, 2005
Sep 8, 2005
388
389
390
}
if (bpp <= 8) {
Jul 10, 2006
Jul 10, 2006
391
392
393
394
395
396
397
398
int i, j;
for (i = 0; i < 256; i += 4) {
for (j = 0; j < 4; j++) {
current->format->palette->colors[i + j].r = 85 * j;
current->format->palette->colors[i + j].g = 85 * j;
current->format->palette->colors[i + j].b = 85 * j;
}
}
Sep 8, 2005
Sep 8, 2005
399
400
401
402
403
404
405
406
407
408
409
}
current->flags = flags & SDL_FULLSCREEN;
this->hidden->w = current->w = width;
this->hidden->h = current->h = height;
current->pitch = current->w * (bpp / 8);
current->pixels = this->hidden->buffer;
return current;
}
Jul 10, 2006
Jul 10, 2006
410
411
static int
iPod_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color * colors)
Sep 8, 2005
Sep 8, 2005
412
{
Jul 10, 2006
Jul 10, 2006
413
414
415
416
417
418
419
420
421
422
if (SDL_VideoSurface && SDL_VideoSurface->format
&& SDL_VideoSurface->format->palette) {
int i, j;
for (i = 0; i < 256; i += 4) {
for (j = 0; j < 4; j++) {
SDL_VideoSurface->format->palette->colors[i + j].r = 85 * j;
SDL_VideoSurface->format->palette->colors[i + j].g = 85 * j;
SDL_VideoSurface->format->palette->colors[i + j].b = 85 * j;
}
}
Sep 8, 2005
Sep 8, 2005
423
424
425
426
}
return 0;
}
Jul 10, 2006
Jul 10, 2006
427
428
static void
iPod_VideoQuit(_THIS)
Sep 8, 2005
Sep 8, 2005
429
{
Jul 10, 2006
Jul 10, 2006
430
431
ioctl(kbfd, KDSETMODE, KD_TEXT);
tcsetattr(kbfd, TCSAFLUSH, &old_termios);
Sep 8, 2005
Sep 8, 2005
432
433
434
old_kbmode = -1;
if (oldvt > 0)
Jul 10, 2006
Jul 10, 2006
435
436
ioctl(kbfd, VT_ACTIVATE, oldvt);
Sep 8, 2005
Sep 8, 2005
437
if (kbfd > 0)
Jul 10, 2006
Jul 10, 2006
438
close(kbfd);
Sep 8, 2005
Sep 8, 2005
439
440
if (dbgout) {
Jul 10, 2006
Jul 10, 2006
441
442
fprintf(dbgout, "<-- Ended SDL -->\n");
fclose(dbgout);
Sep 8, 2005
Sep 8, 2005
443
}
Jul 10, 2006
Jul 10, 2006
444
Sep 8, 2005
Sep 8, 2005
445
446
447
448
kbfd = -1;
}
static char iPod_SC_keymap[] = {
Jul 10, 2006
Jul 10, 2006
449
450
0, /* 0 - no key */
'[' - 0x40, /* ESC (Ctrl+[) */
Sep 8, 2005
Sep 8, 2005
451
452
'1', '2', '3', '4', '5', '6', '7', '8', '9',
'-', '=',
Jul 10, 2006
Jul 10, 2006
453
'\b', '\t', /* Backspace, Tab (Ctrl+H,Ctrl+I) */
Sep 8, 2005
Sep 8, 2005
454
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']',
Jul 10, 2006
Jul 10, 2006
455
'\n', 0, /* Enter, Left CTRL */
Sep 8, 2005
Sep 8, 2005
456
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
Jul 10, 2006
Jul 10, 2006
457
0, '\\', /* left shift, backslash */
Sep 8, 2005
Sep 8, 2005
458
'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
Jul 10, 2006
Jul 10, 2006
459
460
461
462
463
464
465
466
467
468
469
470
471
0, '*', 0, ' ', 0, /* right shift, KP mul, left alt, space, capslock */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F1-10 */
0, 0, /* numlock, scrollock */
'7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.', /* numeric keypad */
0, 0, /* padding */
0, 0, 0, /* "less" (?), F11, F12 */
0, 0, 0, 0, 0, 0, 0, /* padding */
'\n', 0, '/', 0, 0, /* KP enter, Rctrl, Ctrl, KP div, PrtSc, RAlt */
0, 0, 0, 0, 0, 0, 0, 0, 0, /* Break, Home, Up, PgUp, Left, Right, End, Down, PgDn */
0, 0, /* Ins, Del */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* padding */
0, 0, /* RWin, LWin */
0 /* no key */
Sep 8, 2005
Sep 8, 2005
472
473
};
Jul 10, 2006
Jul 10, 2006
474
475
476
static void
iPod_keyboard()
Sep 8, 2005
Sep 8, 2005
477
478
479
480
481
482
483
484
{
unsigned char keybuf[128];
int i, nread;
SDL_keysym keysym;
SDL_Event ev;
keysym.mod = 0;
keysym.scancode = 0xff;
Jul 10, 2006
Jul 10, 2006
485
memset(&ev, 0, sizeof(SDL_Event));
Sep 8, 2005
Sep 8, 2005
486
Jul 10, 2006
Jul 10, 2006
487
nread = read(kbfd, keybuf, 128);
Sep 8, 2005
Sep 8, 2005
488
for (i = 0; i < nread; i++) {
Jul 10, 2006
Jul 10, 2006
489
char ascii = iPod_SC_keymap[keybuf[i] & 0x7f];
Sep 8, 2005
Sep 8, 2005
490
Jul 10, 2006
Jul 10, 2006
491
492
493
if (dbgout)
fprintf(dbgout, "Key! %02x is %c %s", keybuf[i], ascii,
(keybuf[i] & 0x80) ? "up" : "down");
Sep 8, 2005
Sep 8, 2005
494
Jul 10, 2006
Jul 10, 2006
495
496
497
498
499
keysym.sym = keysym.unicode = ascii;
ev.type = (keybuf[i] & 0x80) ? SDL_KEYUP : SDL_KEYDOWN;
ev.key.state = 0;
ev.key.keysym = keysym;
SDL_PushEvent(&ev);
Sep 8, 2005
Sep 8, 2005
500
501
502
}
}
Jul 10, 2006
Jul 10, 2006
503
504
static void
iPod_PumpEvents(_THIS)
Sep 8, 2005
Sep 8, 2005
505
506
507
508
509
510
511
{
fd_set fdset;
int max_fd = 0;
static struct timeval zero;
int posted;
do {
Jul 10, 2006
Jul 10, 2006
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
posted = 0;
FD_ZERO(&fdset);
if (kbfd >= 0) {
FD_SET(kbfd, &fdset);
max_fd = kbfd;
}
if (dbgout)
fprintf(dbgout, "Selecting");
if (select(max_fd + 1, &fdset, 0, 0, &zero) > 0) {
if (dbgout)
fprintf(dbgout, " -> match!\n");
iPod_keyboard();
posted++;
}
if (dbgout)
fprintf(dbgout, "\n");
Aug 27, 2008
Aug 27, 2008
529
} while (posted);
Sep 8, 2005
Sep 8, 2005
530
531
532
}
// enough space for 160x128x2
Jul 10, 2006
Jul 10, 2006
533
static char ipod_scr[160 * (128 / 4)];
Sep 8, 2005
Sep 8, 2005
534
535
536
537
538
539
540
541
#define outl(datum,addr) (*(volatile unsigned long *)(addr) = (datum))
#define inl(addr) (*(volatile unsigned long *)(addr))
/*** The following LCD code is taken from Linux kernel uclinux-2.4.24-uc0-ipod2,
file arch/armnommu/mach-ipod/fb.c. A few modifications have been made. ***/
/* get current usec counter */
Jul 10, 2006
Jul 10, 2006
542
543
static int
M_timer_get_current(void)
Sep 8, 2005
Sep 8, 2005
544
{
Jul 10, 2006
Jul 10, 2006
545
return inl(lcd_rtc);
Sep 8, 2005
Sep 8, 2005
546
547
548
}
/* check if number of useconds has past */
Jul 10, 2006
Jul 10, 2006
549
550
static int
M_timer_check(int clock_start, int usecs)
Sep 8, 2005
Sep 8, 2005
551
{
Jul 10, 2006
Jul 10, 2006
552
553
554
555
556
557
558
559
unsigned long clock;
clock = inl(lcd_rtc);
if ((clock - clock_start) >= usecs) {
return 1;
} else {
return 0;
}
Sep 8, 2005
Sep 8, 2005
560
561
562
}
/* wait for LCD with timeout */
Jul 10, 2006
Jul 10, 2006
563
564
static void
M_lcd_wait_write(void)
Sep 8, 2005
Sep 8, 2005
565
{
Jul 10, 2006
Jul 10, 2006
566
567
568
569
570
571
if ((inl(lcd_base) & 0x8000) != 0) {
int start = M_timer_get_current();
do {
if ((inl(lcd_base) & (unsigned int) 0x8000) == 0)
break;
Aug 27, 2008
Aug 27, 2008
572
} while (M_timer_check(start, 1000) == 0);
Jul 10, 2006
Jul 10, 2006
573
}
Sep 8, 2005
Sep 8, 2005
574
575
576
577
}
/* send LCD data */
Jul 10, 2006
Jul 10, 2006
578
579
static void
M_lcd_send_data(int data_lo, int data_hi)
Sep 8, 2005
Sep 8, 2005
580
{
Jul 10, 2006
Jul 10, 2006
581
582
583
584
585
586
587
M_lcd_wait_write();
outl(data_lo, lcd_base + LCD_DATA);
M_lcd_wait_write();
outl(data_hi, lcd_base + LCD_DATA);
Sep 8, 2005
Sep 8, 2005
588
589
590
591
592
593
594
}
/* send LCD command */
static void
M_lcd_prepare_cmd(int cmd)
{
Jul 10, 2006
Jul 10, 2006
595
M_lcd_wait_write();
Sep 8, 2005
Sep 8, 2005
596
Jul 10, 2006
Jul 10, 2006
597
598
599
600
601
outl(0x0, lcd_base + LCD_CMD);
M_lcd_wait_write();
outl(cmd, lcd_base + LCD_CMD);
Sep 8, 2005
Sep 8, 2005
602
603
604
605
}
/* send LCD command and data */
Jul 10, 2006
Jul 10, 2006
606
607
static void
M_lcd_cmd_and_data(int cmd, int data_lo, int data_hi)
Sep 8, 2005
Sep 8, 2005
608
{
Jul 10, 2006
Jul 10, 2006
609
M_lcd_prepare_cmd(cmd);
Sep 8, 2005
Sep 8, 2005
610
Jul 10, 2006
Jul 10, 2006
611
M_lcd_send_data(data_lo, data_hi);
Sep 8, 2005
Sep 8, 2005
612
613
614
}
// Copied from uW
Jul 10, 2006
Jul 10, 2006
615
616
static void
M_update_display(int sx, int sy, int mx, int my)
Sep 8, 2005
Sep 8, 2005
617
{
Jul 10, 2006
Jul 10, 2006
618
619
int y;
unsigned short cursor_pos;
Sep 8, 2005
Sep 8, 2005
620
Jul 10, 2006
Jul 10, 2006
621
622
sx >>= 3;
mx >>= 3;
Sep 8, 2005
Sep 8, 2005
623
Jul 10, 2006
Jul 10, 2006
624
cursor_pos = sx + (sy << 5);
Sep 8, 2005
Sep 8, 2005
625
Jul 10, 2006
Jul 10, 2006
626
627
628
for (y = sy; y <= my; y++) {
unsigned char *img_data;
int x;
Sep 8, 2005
Sep 8, 2005
629
Jul 10, 2006
Jul 10, 2006
630
631
/* move the cursor */
M_lcd_cmd_and_data(0x11, cursor_pos >> 8, cursor_pos & 0xff);
Sep 8, 2005
Sep 8, 2005
632
Jul 10, 2006
Jul 10, 2006
633
634
/* setup for printing */
M_lcd_prepare_cmd(0x12);
Sep 8, 2005
Sep 8, 2005
635
Jul 10, 2006
Jul 10, 2006
636
img_data = ipod_scr + (sx << 1) + (y * (lcd_width / 4));
Sep 8, 2005
Sep 8, 2005
637
Jul 10, 2006
Jul 10, 2006
638
639
640
641
/* loops up to 160 times */
for (x = sx; x <= mx; x++) {
/* display eight pixels */
M_lcd_send_data(*(img_data + 1), *img_data);
Sep 8, 2005
Sep 8, 2005
642
Jul 10, 2006
Jul 10, 2006
643
644
img_data += 2;
}
Sep 8, 2005
Sep 8, 2005
645
Jul 10, 2006
Jul 10, 2006
646
647
648
/* update cursor pos counter */
cursor_pos += 0x20;
}
Sep 8, 2005
Sep 8, 2005
649
650
651
}
/* get current usec counter */
Jul 10, 2006
Jul 10, 2006
652
653
static int
C_timer_get_current(void)
Sep 8, 2005
Sep 8, 2005
654
{
Jul 10, 2006
Jul 10, 2006
655
return inl(0x60005010);
Sep 8, 2005
Sep 8, 2005
656
657
658
}
/* check if number of useconds has past */
Jul 10, 2006
Jul 10, 2006
659
660
static int
C_timer_check(int clock_start, int usecs)
Sep 8, 2005
Sep 8, 2005
661
{
Jul 10, 2006
Jul 10, 2006
662
663
664
665
666
667
668
669
unsigned long clock;
clock = inl(0x60005010);
if ((clock - clock_start) >= usecs) {
return 1;
} else {
return 0;
}
Sep 8, 2005
Sep 8, 2005
670
671
672
}
/* wait for LCD with timeout */
Jul 10, 2006
Jul 10, 2006
673
674
static void
C_lcd_wait_write(void)
Sep 8, 2005
Sep 8, 2005
675
{
Jul 10, 2006
Jul 10, 2006
676
677
678
679
680
681
if ((inl(0x70008A0C) & 0x80000000) != 0) {
int start = C_timer_get_current();
do {
if ((inl(0x70008A0C) & 0x80000000) == 0)
break;
Aug 27, 2008
Aug 27, 2008
682
} while (C_timer_check(start, 1000) == 0);
Jul 10, 2006
Jul 10, 2006
683
}
Sep 8, 2005
Sep 8, 2005
684
}
Aug 27, 2008
Aug 27, 2008
685
Jul 10, 2006
Jul 10, 2006
686
687
static void
C_lcd_cmd_data(int cmd, int data)
Sep 8, 2005
Sep 8, 2005
688
{
Jul 10, 2006
Jul 10, 2006
689
690
C_lcd_wait_write();
outl(cmd | 0x80000000, 0x70008A0C);
Sep 8, 2005
Sep 8, 2005
691
Jul 10, 2006
Jul 10, 2006
692
693
C_lcd_wait_write();
outl(data | 0x80000000, 0x70008A0C);
Sep 8, 2005
Sep 8, 2005
694
695
}
Jul 10, 2006
Jul 10, 2006
696
697
static void
C_update_display(int sx, int sy, int mx, int my)
Sep 8, 2005
Sep 8, 2005
698
{
Jul 10, 2006
Jul 10, 2006
699
700
int height = (my - sy) + 1;
int width = (mx - sx) + 1;
Sep 8, 2005
Sep 8, 2005
701
Jul 10, 2006
Jul 10, 2006
702
char *addr = SDL_VideoSurface->pixels;
Sep 8, 2005
Sep 8, 2005
703
Jul 10, 2006
Jul 10, 2006
704
705
if (width & 1)
width++;
Sep 8, 2005
Sep 8, 2005
706
Jul 10, 2006
Jul 10, 2006
707
708
709
/* start X and Y */
C_lcd_cmd_data(0x12, (sy & 0xff));
C_lcd_cmd_data(0x13, (((SDL_VideoSurface->w - 1) - sx) & 0xff));
Sep 8, 2005
Sep 8, 2005
710
Jul 10, 2006
Jul 10, 2006
711
712
713
714
/* max X and Y */
C_lcd_cmd_data(0x15, (((sy + height) - 1) & 0xff));
C_lcd_cmd_data(0x16,
(((((SDL_VideoSurface->w - 1) - sx) - width) + 1) & 0xff));
Sep 8, 2005
Sep 8, 2005
715
Jul 10, 2006
Jul 10, 2006
716
addr += sx + sy * SDL_VideoSurface->pitch;
Sep 8, 2005
Sep 8, 2005
717
Jul 10, 2006
Jul 10, 2006
718
719
while (height > 0) {
int h, x, y, pixels_to_write;
Sep 8, 2005
Sep 8, 2005
720
Jul 10, 2006
Jul 10, 2006
721
pixels_to_write = (width * height) * 2;
Sep 8, 2005
Sep 8, 2005
722
Jul 10, 2006
Jul 10, 2006
723
724
725
726
727
728
/* calculate how much we can do in one go */
h = height;
if (pixels_to_write > 64000) {
h = (64000 / 2) / width;
pixels_to_write = (width * h) * 2;
}
Sep 8, 2005
Sep 8, 2005
729
Jul 10, 2006
Jul 10, 2006
730
731
732
outl(0x10000080, 0x70008A20);
outl((pixels_to_write - 1) | 0xC0010000, 0x70008A24);
outl(0x34000000, 0x70008A20);
Sep 8, 2005
Sep 8, 2005
733
Jul 10, 2006
Jul 10, 2006
734
735
736
737
738
/* for each row */
for (x = 0; x < h; x++) {
/* for each column */
for (y = 0; y < width; y += 2) {
unsigned two_pixels;
Sep 8, 2005
Sep 8, 2005
739
Jul 10, 2006
Jul 10, 2006
740
741
two_pixels = addr[0] | (addr[1] << 16);
addr += 2;
Sep 8, 2005
Sep 8, 2005
742
Jul 10, 2006
Jul 10, 2006
743
while ((inl(0x70008A20) & 0x1000000) == 0);
Sep 8, 2005
Sep 8, 2005
744
Jul 10, 2006
Jul 10, 2006
745
746
747
/* output 2 pixels */
outl(two_pixels, 0x70008B00);
}
Sep 8, 2005
Sep 8, 2005
748
Jul 10, 2006
Jul 10, 2006
749
750
addr += SDL_VideoSurface->w - width;
}
Sep 8, 2005
Sep 8, 2005
751
Jul 10, 2006
Jul 10, 2006
752
while ((inl(0x70008A20) & 0x4000000) == 0);
Sep 8, 2005
Sep 8, 2005
753
Jul 10, 2006
Jul 10, 2006
754
outl(0x0, 0x70008A24);
Sep 8, 2005
Sep 8, 2005
755
Jul 10, 2006
Jul 10, 2006
756
757
height = height - h;
}
Sep 8, 2005
Sep 8, 2005
758
759
760
}
// Should work with photo. However, I don't have one, so I'm not sure.
Jul 10, 2006
Jul 10, 2006
761
762
static void
iPod_UpdateRects(_THIS, int nrects, SDL_Rect * rects)
Sep 8, 2005
Sep 8, 2005
763
764
{
if (SDL_VideoSurface->format->BitsPerPixel == 16) {
Jul 10, 2006
Jul 10, 2006
765
C_update_display(0, 0, lcd_width, lcd_height);
Sep 8, 2005
Sep 8, 2005
766
} else {
Jul 10, 2006
Jul 10, 2006
767
768
769
770
771
772
773
774
775
776
777
778
779
int i, y, x;
for (i = 0; i < nrects; i++) {
SDL_Rect *r = rects + i;
if (!r) {
continue;
}
for (y = r->y; (y < r->y + r->h) && y < lcd_height; y++) {
for (x = r->x; (x < r->x + r->w) && x < lcd_width; x++) {
ipod_scr[y * (lcd_width / 4) + x / 4] &=
~(3 << (2 * (x % 4)));
ipod_scr[y * (lcd_width / 4) + x / 4] |=
(((Uint8 *) (SDL_VideoSurface->pixels))[y *
Jan 10, 2009
Jan 10, 2009
780
781
SDL_VideoSurface->
pitch +
Aug 27, 2008
Aug 27, 2008
782
783
784
785
786
x] & 3) << (2
*
(x
%
4));
Jul 10, 2006
Jul 10, 2006
787
788
789
790
791
}
}
}
M_update_display(0, 0, lcd_width, lcd_height);
Sep 8, 2005
Sep 8, 2005
792
793
}
}
Jul 10, 2006
Jul 10, 2006
794
795
/* vi: set ts=4 sw=4 expandtab: */