Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
8327 maxcodehac 1
#include "pxa255_LCD.h"
2
#include "mem.h"
3
 
4
 
5
 
6
#define LCD_IMAGE		"LCD.bmp"
7
#define UNMASKABLE_INTS		0x7C8E
8
 
9
 
10
static void pxa255lcdPrvUpdateInts(Pxa255lcd* lcd){
11
 
12
	UInt16 ints = lcd->lcsr & lcd->intMask;
13
 
14
	if((ints && !lcd->intWasPending) || (!ints && lcd->intWasPending)){
15
 
16
		lcd->intWasPending = !!ints;
17
		pxa255icInt(lcd->ic, PXA255_I_LCD, !!ints);
18
	}
19
}
20
 
21
static Boolean pxa255lcdPrvMemAccessF(void* userData, UInt32 pa, UInt8 size, Boolean write, void* buf){
22
 
23
	Pxa255lcd* lcd = userData;
24
	UInt32 val = 0;
25
	UInt16 v16;
26
 
27
	if(size != 4) {
28
		err_str(__FILE__ ": Unexpected ");
29
	//	err_str(write ? "write" : "read");
30
	//	err_str(" of ");
31
	//	err_dec(size);
32
	//	err_str(" bytes to 0x");
33
	//	err_hex(pa);
34
	//	err_str("\r\n");
35
		return true;		//we do not support non-word accesses
36
	}
37
 
38
	pa = (pa - PXA255_LCD_BASE) >> 2;
39
 
40
	if(write){
41
		val = *(UInt32*)buf;
42
 
43
		switch(pa){
44
			case 0:
45
				if((lcd->lccr0 ^ val) & 0x0001){		//something changed about enablement - handle it
46
 
47
					lcd->enbChanged = 1;
48
				}
49
				lcd->lccr0 = val;
50
				//recalc intMask
51
				v16 = UNMASKABLE_INTS;
52
				if(val & 0x00200000UL){	//output fifo underrun
53
					v16 |= 0x0040;
54
				}
55
				if(val & 0x00100000UL){	//branch int
56
					v16 |= 0x0200;
57
				}
58
				if(val & 0x00000400UL){	//quick disable
59
					v16 |= 0x0001;
60
				}
61
				if(val & 0x00000040UL){	//end of frame
62
					v16 |= 0x0080;
63
				}
64
				if(val & 0x00000020UL){	//input fifo underrun
65
					v16 |= 0x0030;
66
				}
67
				if(val & 0x00000010UL){	//start of frame
68
					v16 |= 0x0002;
69
				}
70
				lcd->intMask = v16;
71
				pxa255lcdPrvUpdateInts(lcd);
72
				break;
73
 
74
			case 1:
75
				lcd->lccr1 = val;
76
				break;
77
 
78
			case 2:
79
				lcd->lccr2 = val;
80
				break;
81
 
82
			case 3:
83
				lcd->lccr3 = val;
84
				break;
85
 
86
			case 8:
87
				lcd->fbr0 = val;
88
				break;
89
 
90
			case 9:
91
				lcd->fbr1 = val;
92
				break;
93
 
94
			case 14:
95
				lcd->lcsr &=~ val;
96
				pxa255lcdPrvUpdateInts(lcd);
97
				break;
98
 
99
			case 15:
100
				lcd->liicr = val;
101
				break;
102
 
103
			case 16:
104
				lcd->trgbr = val;
105
				break;
106
 
107
			case 17:
108
				lcd->tcr = val;
109
				break;
110
 
111
			case 128:
112
				lcd->fdadr0 = val;
113
				break;
114
 
115
			case 132:
116
				lcd->fdadr1 = val;
117
				break;
118
		}
119
	}
120
	else{
121
		switch(pa){
122
			case 0:
123
				val = lcd->lccr0;
124
				break;
125
 
126
			case 1:
127
				val = lcd->lccr1;
128
				break;
129
 
130
			case 2:
131
				val = lcd->lccr2;
132
				break;
133
 
134
			case 3:
135
				val = lcd->lccr3;
136
				break;
137
 
138
			case 8:
139
				val = lcd->fbr0;
140
				break;
141
 
142
			case 9:
143
				val = lcd->fbr1;
144
				break;
145
 
146
			case 14:
147
				val = lcd->lcsr;
148
				break;
149
 
150
			case 15:
151
				val = lcd->liicr;
152
				break;
153
 
154
			case 16:
155
				val = lcd->trgbr;
156
				break;
157
 
158
			case 17:
159
				val = lcd->tcr;
160
				break;
161
 
162
			case 128:
163
				val = lcd->fdadr0;
164
				break;
165
 
166
			case 129:
167
				val = lcd->fsadr0;
168
				break;
169
 
170
			case 130:
171
				val = lcd->fidr0;
172
				break;
173
 
174
			case 131:
175
				val = lcd->ldcmd0;
176
				break;
177
 
178
			case 132:
179
				val = lcd->fdadr1;
180
				break;
181
 
182
			case 133:
183
				val = lcd->fsadr1;
184
				break;
185
 
186
			case 134:
187
				val = lcd->fidr1;
188
				break;
189
 
190
			case 135:
191
				val = lcd->ldcmd1;
192
				break;
193
		}
194
		*(UInt32*)buf = val;
195
	}
196
 
197
	return true;
198
}
199
 
200
static UInt32 pxa255PrvGetWord(Pxa255lcd* lcd, UInt32 addr){
201
 
202
	UInt32 v;
203
 
204
	if(!memAccess(lcd->mem, addr, 4, false, &v)) return 0;
205
 
206
	return v;
207
}
208
 
209
static void pxa255LcdPrvDma(Pxa255lcd* lcd, void* dest, UInt32 addr, UInt32 len){
210
 
211
	UInt32 t;
212
	UInt8* d = dest;
213
 
214
	//we assume aligntment here both on part of dest and of addr
215
 
216
	while(len){
217
 
218
		t = pxa255PrvGetWord(lcd, addr);
219
		if(len--) *d++ = t;
220
		if(len--) *d++ = t >> 8;
221
		if(len--) *d++ = t >> 16;
222
		if(len--) *d++ = t >> 24;
223
		addr += 4;
224
	}
225
}
226
 
227
#ifndef EMBEDDED
228
	#include 
229
 
230
	static _INLINE_ void pxa255LcdScreenDataPixel(Pxa255lcd* lcd, UInt8* buf){
231
 
232
		UInt8 r, g, b;
233
		const UInt32 W = 640;
234
		const UInt32 H = 480;
235
 
236
		b = buf[0] << 3;
237
		r = buf[1] & 0xF8;
238
		g = (buf[1] << 5) | ((buf[0] >> 3) & 0x1C);
239
 
240
		{
241
			static UInt32 pn = 0;
242
			static FILE* bmp = NULL;
243
 
244
			if(pn == 0){
245
				bmp = fopen(LCD_IMAGE, "w+b");
246
				if(bmp){
247
 
248
					const UInt32 off = 56;
249
					const UInt32 sz = 320 * 320 * 3 + off;
250
					#define LE32(x)	((int)((x) & 0xFF)), ((int)(((x) >> 8) & 0xFF)), ((int)(((x) >> 16) & 0xFF)), ((int)((x) >> 24))
251
					#define LE16(x) ((int)((x) & 0xFF)), ((int)(((x) >> 8) & 0xFF))
252
 
253
					fprintf(bmp, "BM%c%c%c%c%c%c%c%c%c%c%c%c", LE32(sz), LE16(0), LE16(0), LE32(off));	//bitmap file header
254
					fprintf(bmp, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", LE32(40), LE32(W), LE32(-H), LE16(1), LE16(24), LE32(0), LE32(W * H * 3), LE32(2835), LE32(2835), LE32(0), LE32(0)); //BITMAPCOREHEADER
255
					fprintf(bmp, "%c%c",0 ,0); //spacer to align bmp data to 4 bytes
256
 
257
					#undef LE32
258
				}
259
			}
260
			if(bmp){
261
 
262
				fprintf(bmp, "%c%c%c", b, g, r);
263
			}
264
			pn++;
265
			if(pn == W * H){
266
				pn = 0;
267
				if(bmp){
268
 
269
					fclose(bmp);
270
					bmp = NULL;
271
				}
272
			}
273
		}
274
	}
275
 
276
	#ifndef PXA255_LCD_SUPPORTS_PALLETES
277
	static void pxa255LcdSetFakePal(UInt8* buf, UInt8 bpp, UInt8 val){
278
 
279
		while(bpp++ < 8) val = (val << 1) | (val & 1);	//sign extend up (weird but works)
280
 
281
		buf[1] = (val & 0xF8) | (val >> 3);
282
		buf[0] = ((val & 0xFC) << 5) | val >> 3;
283
	}
284
	#endif
285
 
286
	static void pxa255LcdScreenDataDma(Pxa255lcd* lcd, UInt32 addr/*PA*/, UInt32 len){
287
 
288
		UInt8 data[4];
289
		UInt32 i, j;
290
		void* ptr;
291
	#ifndef PXA255_LCD_SUPPORTS_PALLETES
292
		UInt8 val[2];
293
	#endif
294
 
295
		len /= 4;
296
		while(len--){
297
			pxa255LcdPrvDma(lcd, data, addr, 4);
298
			addr += 4;
299
 
300
			switch((lcd->lccr3 >> 24) & 7){
301
 
302
				case 0:		//1BPP
303
 
304
				#ifdef PXA255_LCD_SUPPORTS_PALLETES
305
					ptr = lcd->palette + ((data[i] >> j) & 1) * 2;
306
				#else
307
					ptr = val;
308
					pxa255LcdSetFakePal(val, 1, (data[i] >> j) & 1);
309
				#endif
310
					for(i = 0; i < 4; i += 1) for(j = 0; j < 8; j += 1) pxa255LcdScreenDataPixel(lcd, ptr);
311
					break;
312
 
313
				case 1:		//2BPP
314
 
315
				#ifdef PXA255_LCD_SUPPORTS_PALLETES
316
					ptr = lcd->palette + ((data[i] >> j) & 3) * 2;
317
				#else
318
					ptr = val;
319
					pxa255LcdSetFakePal(val, 2, (data[i] >> j) & 3);
320
				#endif
321
					for(i = 0; i < 4; i += 1) for(j = 0; j < 8; j += 2) pxa255LcdScreenDataPixel(lcd, ptr);
322
					break;
323
 
324
				case 2:		//4BPP
325
 
326
				#ifdef PXA255_LCD_SUPPORTS_PALLETES
327
					ptr = lcd->palette + ((data[i] >> j) & 15) * 2;
328
				#else
329
					ptr = val;
330
					pxa255LcdSetFakePal(val, 4, (data[i] >> j) & 15);
331
				#endif
332
					for(i = 0; i < 4; i += 1) for(j = 0; j < 8; j += 4) pxa255LcdScreenDataPixel(lcd, ptr);
333
					break;
334
 
335
				case 3:		//8BPP
336
 
337
				#ifdef PXA255_LCD_SUPPORTS_PALLETES
338
					ptr = lcd->palette + (data[i] * 2);
339
				#else
340
					ptr = val;
341
					pxa255LcdSetFakePal(val, 8, data[i]);
342
				#endif
343
					for(i = 0; i < 4; i += 1) pxa255LcdScreenDataPixel(lcd, ptr);
344
					break;
345
 
346
				case 4:		//16BPP
347
 
348
					for(i = 0; i < 4; i +=2 ) pxa255LcdScreenDataPixel(lcd, data + i);
349
					break;
350
 
351
				default:
352
 
353
					;//BAD
354
			}
355
		}
356
	}
357
#else
358
	static void pxa255LcdScreenDataDma(Pxa255lcd* lcd, UInt32 addr/*PA*/, UInt32 len){
359
 
360
		//nothing
361
	}
362
#endif
363
 
364
void pxa255lcdFrame(Pxa255lcd* lcd){
365
	//every other call starts a frame, the others end one [this generates spacing between interrupts so as to not confuse guest OS]
366
 
367
	if(lcd->enbChanged){
368
 
369
		if(lcd->lccr0 & 0x0001){	//just got enabled
370
 
371
			//TODO: perhaps check settings?
372
		}
373
		else{				// we just got quick disabled - kill current frame and do no more
374
 
375
			lcd->lcsr |= 0x0080;	//quick disable happened
376
			lcd->state = LCD_STATE_IDLE;
377
		}
378
		lcd->enbChanged = false;
379
	}
380
 
381
	if(lcd->lccr0 & 0x0001){			//enabled - do a frame
382
 
383
		UInt32 descrAddr, len;
384
 
385
		switch(lcd->state){
386
 
387
			case LCD_STATE_IDLE:
388
 
389
				if(lcd->fbr0 & 1){	//branch
390
 
391
					lcd->fbr0 &=~ 1UL;
392
					if(lcd->fbr0 & 2) lcd->lcsr |= 0x0200;
393
					descrAddr = lcd->fbr0 &~ 0xFUL;
394
				} else descrAddr = lcd->fdadr0;
395
				lcd->fdadr0 = pxa255PrvGetWord(lcd, descrAddr + 0);
396
				lcd->fsadr0 = pxa255PrvGetWord(lcd, descrAddr + 4);
397
				lcd->fidr0  = pxa255PrvGetWord(lcd, descrAddr + 8);
398
				lcd->ldcmd0 = pxa255PrvGetWord(lcd, descrAddr + 12);
399
 
400
				lcd->state = LCD_STATE_DMA_0_START;
401
				break;
402
 
403
			case LCD_STATE_DMA_0_START:
404
 
405
				if(lcd->ldcmd0 & 0x00400000UL) lcd->lcsr |= 0x0002;	//set SOF is DMA 0 started
406
				len = lcd->ldcmd0 & 0x000FFFFFUL;
407
 
408
				if(lcd->ldcmd0 & 0x04000000UL){	//pallette data
409
 
410
					#ifdef PXA255_LCD_SUPPORTS_PALLETES
411
						if(len > sizeof(lcd->palette)){
412
 
413
							len = sizeof(lcd->palette);
414
 
415
							pxa255LcdPrvDma(lcd, lcd->palette, lcd->fsadr0, len);
416
						}
417
					#endif
418
				}
419
				else{
420
 
421
					lcd->frameNum++;
422
					if(!(lcd->frameNum & 63)) pxa255LcdScreenDataDma(lcd, lcd->fsadr0, len);
423
				}
424
 
425
				lcd->state = LCD_STATE_DMA_0_END;
426
				break;
427
 
428
			case LCD_STATE_DMA_0_END:
429
 
430
				if(lcd->ldcmd0 & 0x00200000UL) lcd->lcsr |= 0x0100;	//set EOF is DMA 0 finished
431
				lcd->state = LCD_STATE_IDLE;
432
				break;
433
		}
434
	}
435
	pxa255lcdPrvUpdateInts(lcd);
436
}
437
 
438
 
439
Boolean pxa255lcdInit(Pxa255lcd* lcd, ArmMem* physMem, Pxa255ic* ic){
440
 
441
 
442
	__mem_zero(lcd, sizeof(Pxa255lcd));
443
 
444
	lcd->ic = ic;
445
	lcd->mem = physMem;
446
	lcd->intMask = UNMASKABLE_INTS;
447
 
448
	return memRegionAdd(physMem, PXA255_LCD_BASE, PXA255_LCD_SIZE, pxa255lcdPrvMemAccessF, lcd);
449
}
450