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 (661 loc) · 21.1 KB

SDL_ipodvideo.c

File metadata and controls

795 lines (661 loc) · 21.1 KB
 
Feb 21, 2006
Feb 21, 2006
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2006 Sam Lantinga
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
529
530
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");
}
while (posted);
Sep 8, 2005
Sep 8, 2005
531
532
533
}
// enough space for 160x128x2
Jul 10, 2006
Jul 10, 2006
534
static char ipod_scr[160 * (128 / 4)];
Sep 8, 2005
Sep 8, 2005
535
536
537
538
539
540
541
542
#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
543
544
static int
M_timer_get_current(void)
Sep 8, 2005
Sep 8, 2005
545
{
Jul 10, 2006
Jul 10, 2006
546
return inl(lcd_rtc);
Sep 8, 2005
Sep 8, 2005
547
548
549
}
/* check if number of useconds has past */
Jul 10, 2006
Jul 10, 2006
550
551
static int
M_timer_check(int clock_start, int usecs)
Sep 8, 2005
Sep 8, 2005
552
{
Jul 10, 2006
Jul 10, 2006
553
554
555
556
557
558
559
560
unsigned long clock;
clock = inl(lcd_rtc);
if ((clock - clock_start) >= usecs) {
return 1;
} else {
return 0;
}
Sep 8, 2005
Sep 8, 2005
561
562
563
}
/* wait for LCD with timeout */
Jul 10, 2006
Jul 10, 2006
564
565
static void
M_lcd_wait_write(void)
Sep 8, 2005
Sep 8, 2005
566
{
Jul 10, 2006
Jul 10, 2006
567
568
569
570
571
572
573
574
575
if ((inl(lcd_base) & 0x8000) != 0) {
int start = M_timer_get_current();
do {
if ((inl(lcd_base) & (unsigned int) 0x8000) == 0)
break;
}
while (M_timer_check(start, 1000) == 0);
}
Sep 8, 2005
Sep 8, 2005
576
577
578
579
}
/* send LCD data */
Jul 10, 2006
Jul 10, 2006
580
581
static void
M_lcd_send_data(int data_lo, int data_hi)
Sep 8, 2005
Sep 8, 2005
582
{
Jul 10, 2006
Jul 10, 2006
583
584
585
586
587
588
589
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
590
591
592
593
594
595
596
}
/* send LCD command */
static void
M_lcd_prepare_cmd(int cmd)
{
Jul 10, 2006
Jul 10, 2006
597
M_lcd_wait_write();
Sep 8, 2005
Sep 8, 2005
598
Jul 10, 2006
Jul 10, 2006
599
600
601
602
603
outl(0x0, lcd_base + LCD_CMD);
M_lcd_wait_write();
outl(cmd, lcd_base + LCD_CMD);
Sep 8, 2005
Sep 8, 2005
604
605
606
607
}
/* send LCD command and data */
Jul 10, 2006
Jul 10, 2006
608
609
static void
M_lcd_cmd_and_data(int cmd, int data_lo, int data_hi)
Sep 8, 2005
Sep 8, 2005
610
{
Jul 10, 2006
Jul 10, 2006
611
M_lcd_prepare_cmd(cmd);
Sep 8, 2005
Sep 8, 2005
612
Jul 10, 2006
Jul 10, 2006
613
M_lcd_send_data(data_lo, data_hi);
Sep 8, 2005
Sep 8, 2005
614
615
616
}
// Copied from uW
Jul 10, 2006
Jul 10, 2006
617
618
static void
M_update_display(int sx, int sy, int mx, int my)
Sep 8, 2005
Sep 8, 2005
619
{
Jul 10, 2006
Jul 10, 2006
620
621
int y;
unsigned short cursor_pos;
Sep 8, 2005
Sep 8, 2005
622
Jul 10, 2006
Jul 10, 2006
623
624
sx >>= 3;
mx >>= 3;
Sep 8, 2005
Sep 8, 2005
625
Jul 10, 2006
Jul 10, 2006
626
cursor_pos = sx + (sy << 5);
Sep 8, 2005
Sep 8, 2005
627
Jul 10, 2006
Jul 10, 2006
628
629
630
for (y = sy; y <= my; y++) {
unsigned char *img_data;
int x;
Sep 8, 2005
Sep 8, 2005
631
Jul 10, 2006
Jul 10, 2006
632
633
/* move the cursor */
M_lcd_cmd_and_data(0x11, cursor_pos >> 8, cursor_pos & 0xff);
Sep 8, 2005
Sep 8, 2005
634
Jul 10, 2006
Jul 10, 2006
635
636
/* setup for printing */
M_lcd_prepare_cmd(0x12);
Sep 8, 2005
Sep 8, 2005
637
Jul 10, 2006
Jul 10, 2006
638
img_data = ipod_scr + (sx << 1) + (y * (lcd_width / 4));
Sep 8, 2005
Sep 8, 2005
639
Jul 10, 2006
Jul 10, 2006
640
641
642
643
/* 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
644
Jul 10, 2006
Jul 10, 2006
645
646
img_data += 2;
}
Sep 8, 2005
Sep 8, 2005
647
Jul 10, 2006
Jul 10, 2006
648
649
650
/* update cursor pos counter */
cursor_pos += 0x20;
}
Sep 8, 2005
Sep 8, 2005
651
652
653
}
/* get current usec counter */
Jul 10, 2006
Jul 10, 2006
654
655
static int
C_timer_get_current(void)
Sep 8, 2005
Sep 8, 2005
656
{
Jul 10, 2006
Jul 10, 2006
657
return inl(0x60005010);
Sep 8, 2005
Sep 8, 2005
658
659
660
}
/* check if number of useconds has past */
Jul 10, 2006
Jul 10, 2006
661
662
static int
C_timer_check(int clock_start, int usecs)
Sep 8, 2005
Sep 8, 2005
663
{
Jul 10, 2006
Jul 10, 2006
664
665
666
667
668
669
670
671
unsigned long clock;
clock = inl(0x60005010);
if ((clock - clock_start) >= usecs) {
return 1;
} else {
return 0;
}
Sep 8, 2005
Sep 8, 2005
672
673
674
}
/* wait for LCD with timeout */
Jul 10, 2006
Jul 10, 2006
675
676
static void
C_lcd_wait_write(void)
Sep 8, 2005
Sep 8, 2005
677
{
Jul 10, 2006
Jul 10, 2006
678
679
680
681
682
683
684
685
686
if ((inl(0x70008A0C) & 0x80000000) != 0) {
int start = C_timer_get_current();
do {
if ((inl(0x70008A0C) & 0x80000000) == 0)
break;
}
while (C_timer_check(start, 1000) == 0);
}
Sep 8, 2005
Sep 8, 2005
687
}
Jul 10, 2006
Jul 10, 2006
688
689
static void
C_lcd_cmd_data(int cmd, int data)
Sep 8, 2005
Sep 8, 2005
690
{
Jul 10, 2006
Jul 10, 2006
691
692
C_lcd_wait_write();
outl(cmd | 0x80000000, 0x70008A0C);
Sep 8, 2005
Sep 8, 2005
693
Jul 10, 2006
Jul 10, 2006
694
695
C_lcd_wait_write();
outl(data | 0x80000000, 0x70008A0C);
Sep 8, 2005
Sep 8, 2005
696
697
}
Jul 10, 2006
Jul 10, 2006
698
699
static void
C_update_display(int sx, int sy, int mx, int my)
Sep 8, 2005
Sep 8, 2005
700
{
Jul 10, 2006
Jul 10, 2006
701
702
int height = (my - sy) + 1;
int width = (mx - sx) + 1;
Sep 8, 2005
Sep 8, 2005
703
Jul 10, 2006
Jul 10, 2006
704
char *addr = SDL_VideoSurface->pixels;
Sep 8, 2005
Sep 8, 2005
705
Jul 10, 2006
Jul 10, 2006
706
707
if (width & 1)
width++;
Sep 8, 2005
Sep 8, 2005
708
Jul 10, 2006
Jul 10, 2006
709
710
711
/* 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
712
Jul 10, 2006
Jul 10, 2006
713
714
715
716
/* 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
717
Jul 10, 2006
Jul 10, 2006
718
addr += sx + sy * SDL_VideoSurface->pitch;
Sep 8, 2005
Sep 8, 2005
719
Jul 10, 2006
Jul 10, 2006
720
721
while (height > 0) {
int h, x, y, pixels_to_write;
Sep 8, 2005
Sep 8, 2005
722
Jul 10, 2006
Jul 10, 2006
723
pixels_to_write = (width * height) * 2;
Sep 8, 2005
Sep 8, 2005
724
Jul 10, 2006
Jul 10, 2006
725
726
727
728
729
730
/* 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
731
Jul 10, 2006
Jul 10, 2006
732
733
734
outl(0x10000080, 0x70008A20);
outl((pixels_to_write - 1) | 0xC0010000, 0x70008A24);
outl(0x34000000, 0x70008A20);
Sep 8, 2005
Sep 8, 2005
735
Jul 10, 2006
Jul 10, 2006
736
737
738
739
740
/* 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
741
Jul 10, 2006
Jul 10, 2006
742
743
two_pixels = addr[0] | (addr[1] << 16);
addr += 2;
Sep 8, 2005
Sep 8, 2005
744
Jul 10, 2006
Jul 10, 2006
745
while ((inl(0x70008A20) & 0x1000000) == 0);
Sep 8, 2005
Sep 8, 2005
746
Jul 10, 2006
Jul 10, 2006
747
748
749
/* output 2 pixels */
outl(two_pixels, 0x70008B00);
}
Sep 8, 2005
Sep 8, 2005
750
Jul 10, 2006
Jul 10, 2006
751
752
addr += SDL_VideoSurface->w - width;
}
Sep 8, 2005
Sep 8, 2005
753
Jul 10, 2006
Jul 10, 2006
754
while ((inl(0x70008A20) & 0x4000000) == 0);
Sep 8, 2005
Sep 8, 2005
755
Jul 10, 2006
Jul 10, 2006
756
outl(0x0, 0x70008A24);
Sep 8, 2005
Sep 8, 2005
757
Jul 10, 2006
Jul 10, 2006
758
759
height = height - h;
}
Sep 8, 2005
Sep 8, 2005
760
761
762
}
// Should work with photo. However, I don't have one, so I'm not sure.
Jul 10, 2006
Jul 10, 2006
763
764
static void
iPod_UpdateRects(_THIS, int nrects, SDL_Rect * rects)
Sep 8, 2005
Sep 8, 2005
765
766
{
if (SDL_VideoSurface->format->BitsPerPixel == 16) {
Jul 10, 2006
Jul 10, 2006
767
C_update_display(0, 0, lcd_width, lcd_height);
Sep 8, 2005
Sep 8, 2005
768
} else {
Jul 10, 2006
Jul 10, 2006
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
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 *
SDL_VideoSurface->
pitch
+
x] &
3) << (2 * (x % 4));
}
}
}
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: */