1 /*
2 Copyright (c) 2003 Andreas Robinson, All rights reserved.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8 */
9
10
11 /*
12
13 EPIA-M benchmarks (df_dok)
14
15 SW v0.0.1 v0.1.0 v0.2.0 v0.3
16
17 Anti-aliased Text 98.97 - - - 280.80 KChars/sec
18 Anti-aliased Text (blend) 28.85 - - - 280.61 KChars/sec
19 Fill Rectangles 25.21 443.46 437.05 432.39 435.60 Mpixel/sec
20 Fill Rectangles (blend) 5.54 - 130.12 128.42 127.82 MPixel/sec
21 Fill Triangles 24.84 173.44 129.76 127.86 128.63 MPixel/sec
22 Fill Triangles (blend) 5.46 - 129.81 127.86 128.67 MPixel/sec
23 Draw Rectangles 11.82 58.98 59.07 52.48 55.10 KRects/sec
24 Draw Rectangles (blend) 1.98 - 32.13 22.76 23.50 KRects/sec
25 Draw Lines 42.67 283.81 292.33 193.87 203.20 KLines/sec
26 Draw Lines (blend) 8.54 - 142.62 101.23 102.80 KLines/sec
27 Blit 21.48 - 117.38 114.26 114.41 MPixel/sec
28 Blit colorkeyed 22.54 - 117.34 114.26 114.41 MPixel/sec
29 Blit w/ format conversion 16.22 - - 103.41 103.00 MPixel/sec
30 Blit from 32bit (blend) 4.19 - - 87.72 87.32 MPixel/sec
31 Blit from 8bit palette 11.02 - - 110.13 113.37 MPixel/sec
32 Blit from 8bit pal. (blend) 3.78 - - 110.20 113.40 MPixel/sec
33 Stretch Blit 23.19 - - 99.53 99.32 MPixel/sec
34 Stretch Blit colorkeyed 25.04 - - 5.00 38.00 MPixel/sec
35
36
37 Comparing M9000 and M10000
38
39 v0.2.0 M9000 M10000
40
41 Anti-aliased Text - - KChars/sec
42 Anti-aliased Text (blend) - - KChars/sec
43 Fill Rectangles 401.82 432.39 Mpixel/sec
44 Fill Rectangles (blend) 129.05 128.42 MPixel/sec
45 Fill Triangles 128.46 127.86 MPixel/sec
46 Fill Triangles (blend) 128.46 127.86 MPixel/sec
47 Draw Rectangles 55.51 52.48 KRects/sec
48 Draw Rectangles (blend) 26.90 22.76 KRects/sec
49 Draw Lines 225.00 193.87 KLines/sec
50 Draw Lines (blend) 121.29 101.23 KLines/sec
51 Blit 112.36 114.26 MPixel/sec
52 Blit colorkeyed 112.28 114.26 MPixel/sec
53 Blit w/ format conversion 103.92 103.41 MPixel/sec
54 Blit from 32bit (blend) 87.89 87.72 MPixel/sec
55 Blit from 8bit palette 110.56 110.13 MPixel/sec
56 Blit from 8bit pal. (blend) 110.56 110.20 MPixel/sec
57 Stretch Blit 108.67 99.53 MPixel/sec
58 Stretch Blit colorkeyed 4.79 5.00 MPixel/sec
59
60
61 v0.0.1 and v0.1.0 are tested on an EPIA-M9000,
62 later versions on an EPIA-M10000.
63
64 */
65
66 // DirectFB headers
67
68 #include <config.h>
69
70 #include <directfb.h>
71
72 #include <fusion/shmalloc.h>
73
74 #include <direct/messages.h>
75
76 #include <core/coretypes.h>
77 #include <core/core.h>
78 #include <core/gfxcard.h>
79 #include <core/graphics_driver.h>
80 #include <core/system.h>
81 #include <core/screens.h>
82
83 #include <fbdev/fb.h>
84
85 // System headers
86
87 #include <sys/types.h>
88 #include <sys/stat.h>
89 #include <fcntl.h>
90 #include <sys/mman.h>
91 #include <stdlib.h>
92 #include <unistd.h>
93 #include <stdio.h>
94
95 #include <string.h>
96
97 // Driver headers
98
99 #include "unichrome.h"
100 #include "uc_state.h"
101 #include "uc_accel.h"
102 #include "uc_fifo.h"
103 #include "mmio.h"
104
105 #ifndef FB_ACCEL_VIA_UNICHROME
106 #define FB_ACCEL_VIA_UNICHROME 77
107 #endif
108
109 extern DisplayLayerFuncs ucOverlayFuncs;
110 extern DisplayLayerFuncs ucPrimaryFuncs;
111
112 extern DisplayLayerFuncs ucOldPrimaryFuncs;
113 extern void *ucOldPrimaryDriverData;
114
DFB_GRAPHICS_DRIVER(cle266)115 DFB_GRAPHICS_DRIVER(cle266)
116
117 //----------
118
119
120 /**
121 * Dump beginning of virtual queue.
122 * Use it to check that the VQ actually is in use. */
123 #if 0
124 static void uc_dump_vq(UcDeviceData *ucdev)
125 {
126 int i;
127 u8* vq;
128
129 if (!ucdev->vq_start) return;
130 vq = dfb_system_video_memory_virtual(ucdev->vq_start);
131
132 for (i = 0; i < 128; i++) {
133 printf("%02x ", *(vq+i));
134 if ((i+1) % 16 == 0) printf("\n");
135 }
136 }
137 #endif
138
139 /** Allocate memory for the virtual queue. */
140
141 static DFBResult uc_alloc_vq(CoreGraphicsDevice *device, UcDeviceData *ucdev)
142 {
143 if (ucdev->vq_start) return DFB_OK;
144
145 ucdev->vq_size = 256*1024; // 256kb
146 ucdev->vq_start = dfb_gfxcard_reserve_memory( device, ucdev->vq_size );
147
148 if (!ucdev->vq_start)
149 return DFB_INIT;
150
151 ucdev->vq_end = ucdev->vq_start + ucdev->vq_size - 1;
152
153 // Debug: clear buffer
154 memset((void *) dfb_system_video_memory_virtual(ucdev->vq_start),
155 0xcc, ucdev->vq_size);
156
157 // uc_dump_vq(ucdev);
158
159 return DFB_OK;
160 }
161
162 /**
163 * Initialize the hardware.
164 * @param enable enable VQ if true (else disable it.)
165 */
166
uc_init_2d_engine(CoreGraphicsDevice * device,UcDeviceData * ucdev,UcDriverData * ucdrv,bool enable)167 static DFBResult uc_init_2d_engine(CoreGraphicsDevice *device, UcDeviceData *ucdev, UcDriverData *ucdrv, bool enable)
168 {
169 DFBResult result = DFB_OK;
170 volatile u8* hwregs = ucdrv->hwregs;
171
172 // Init 2D engine registers to reset 2D engine
173
174 VIA_OUT(hwregs, 0x04, 0x0);
175 VIA_OUT(hwregs, 0x08, 0x0);
176 VIA_OUT(hwregs, 0x0c, 0x0);
177 VIA_OUT(hwregs, 0x10, 0x0);
178 VIA_OUT(hwregs, 0x14, 0x0);
179 VIA_OUT(hwregs, 0x18, 0x0);
180 VIA_OUT(hwregs, 0x1c, 0x0);
181 VIA_OUT(hwregs, 0x20, 0x0);
182 VIA_OUT(hwregs, 0x24, 0x0);
183 VIA_OUT(hwregs, 0x28, 0x0);
184 VIA_OUT(hwregs, 0x2c, 0x0);
185 VIA_OUT(hwregs, 0x30, 0x0);
186 VIA_OUT(hwregs, 0x34, 0x0);
187 VIA_OUT(hwregs, 0x38, 0x0);
188 VIA_OUT(hwregs, 0x3c, 0x0);
189 VIA_OUT(hwregs, 0x40, 0x0);
190
191 // Init AGP and VQ registers
192
193 VIA_OUT(hwregs, 0x43c, 0x00100000);
194 VIA_OUT(hwregs, 0x440, 0x00000000);
195 VIA_OUT(hwregs, 0x440, 0x00333004);
196 VIA_OUT(hwregs, 0x440, 0x60000000);
197 VIA_OUT(hwregs, 0x440, 0x61000000);
198 VIA_OUT(hwregs, 0x440, 0x62000000);
199 VIA_OUT(hwregs, 0x440, 0x63000000);
200 VIA_OUT(hwregs, 0x440, 0x64000000);
201 VIA_OUT(hwregs, 0x440, 0x7D000000);
202
203 VIA_OUT(hwregs, 0x43c, 0xfe020000);
204 VIA_OUT(hwregs, 0x440, 0x00000000);
205
206 if (enable) {
207 result = uc_alloc_vq(device,ucdev);
208 enable = (result == DFB_OK);
209 }
210
211 if (enable) { // Enable VQ
212
213 VIA_OUT(hwregs, 0x43c, 0x00fe0000);
214 VIA_OUT(hwregs, 0x440, 0x080003fe);
215 VIA_OUT(hwregs, 0x440, 0x0a00027c);
216 VIA_OUT(hwregs, 0x440, 0x0b000260);
217 VIA_OUT(hwregs, 0x440, 0x0c000274);
218 VIA_OUT(hwregs, 0x440, 0x0d000264);
219 VIA_OUT(hwregs, 0x440, 0x0e000000);
220 VIA_OUT(hwregs, 0x440, 0x0f000020);
221 VIA_OUT(hwregs, 0x440, 0x1000027e);
222 VIA_OUT(hwregs, 0x440, 0x110002fe);
223 VIA_OUT(hwregs, 0x440, 0x200f0060);
224
225 VIA_OUT(hwregs, 0x440, 0x00000006);
226 VIA_OUT(hwregs, 0x440, 0x40008c0f);
227 VIA_OUT(hwregs, 0x440, 0x44000000);
228 VIA_OUT(hwregs, 0x440, 0x45080c04);
229 VIA_OUT(hwregs, 0x440, 0x46800408);
230
231 VIA_OUT(hwregs, 0x440, 0x52000000 |
232 ((ucdev->vq_start & 0xFF000000) >> 24) |
233 ((ucdev->vq_end & 0xFF000000) >> 16));
234 VIA_OUT(hwregs, 0x440, 0x50000000 | (ucdev->vq_start & 0xFFFFFF));
235 VIA_OUT(hwregs, 0x440, 0x51000000 | (ucdev->vq_end & 0xFFFFFF));
236 VIA_OUT(hwregs, 0x440, 0x53000000 | (ucdev->vq_size >> 3));
237 }
238 else { // Disable VQ
239
240 VIA_OUT(hwregs, 0x43c, 0x00fe0000);
241 VIA_OUT(hwregs, 0x440, 0x00000004);
242 VIA_OUT(hwregs, 0x440, 0x40008c0f);
243 VIA_OUT(hwregs, 0x440, 0x44000000);
244 VIA_OUT(hwregs, 0x440, 0x45080c04);
245 VIA_OUT(hwregs, 0x440, 0x46800408);
246 }
247
248 return result;
249 }
250
uc_init_3d_engine(volatile u8 * hwregs,int hwrev,bool init_all)251 static void uc_init_3d_engine(volatile u8* hwregs, int hwrev, bool init_all)
252 {
253 u32 i;
254
255 if (init_all) {
256
257 // Clear NotTex registers (?)
258
259 VIA_OUT(hwregs, 0x43C, 0x00010000);
260 for (i = 0; i <= 0x7d; i++)
261 VIA_OUT(hwregs, 0x440, i << 24);
262
263 // Clear texture unit 0 (?)
264
265 VIA_OUT(hwregs, 0x43C, 0x00020000);
266 for (i = 0; i <= 0x94; i++)
267 VIA_OUT(hwregs, 0x440, i << 24);
268 VIA_OUT(hwregs, 0x440, 0x82400000);
269
270 // Clear texture unit 1 (?)
271
272 VIA_OUT(hwregs, 0x43C, 0x01020000);
273 for (i = 0; i <= 0x94; i++)
274 VIA_OUT(hwregs, 0x440, i << 24);
275 VIA_OUT(hwregs, 0x440, 0x82400000);
276
277 // Clear general texture settings (?)
278
279 VIA_OUT(hwregs, 0x43C, 0xfe020000);
280 for (i = 0; i <= 0x03; i++)
281 VIA_OUT(hwregs, 0x440, i << 24);
282
283 // Clear palette settings (?)
284
285 VIA_OUT(hwregs, 0x43C, 0x00030000);
286 for (i = 0; i <= 0xff; i++)
287 VIA_OUT(hwregs, 0x440, 0);
288
289 VIA_OUT(hwregs, 0x43C, 0x00100000);
290 VIA_OUT(hwregs, 0x440, 0x00333004);
291 VIA_OUT(hwregs, 0x440, 0x10000002);
292 VIA_OUT(hwregs, 0x440, 0x60000000);
293 VIA_OUT(hwregs, 0x440, 0x61000000);
294 VIA_OUT(hwregs, 0x440, 0x62000000);
295 VIA_OUT(hwregs, 0x440, 0x63000000);
296 VIA_OUT(hwregs, 0x440, 0x64000000);
297
298 VIA_OUT(hwregs, 0x43C, 0x00fe0000);
299
300 if (hwrev >= 3)
301 VIA_OUT(hwregs, 0x440,0x40008c0f);
302 else
303 VIA_OUT(hwregs, 0x440,0x4000800f);
304
305 VIA_OUT(hwregs, 0x440,0x44000000);
306 VIA_OUT(hwregs, 0x440,0x45080C04);
307 VIA_OUT(hwregs, 0x440,0x46800408);
308 VIA_OUT(hwregs, 0x440,0x50000000);
309 VIA_OUT(hwregs, 0x440,0x51000000);
310 VIA_OUT(hwregs, 0x440,0x52000000);
311 VIA_OUT(hwregs, 0x440,0x53000000);
312
313 }
314
315 VIA_OUT(hwregs, 0x43C,0x00fe0000);
316 VIA_OUT(hwregs, 0x440,0x08000001);
317 VIA_OUT(hwregs, 0x440,0x0A000183);
318 VIA_OUT(hwregs, 0x440,0x0B00019F);
319 VIA_OUT(hwregs, 0x440,0x0C00018B);
320 VIA_OUT(hwregs, 0x440,0x0D00019B);
321 VIA_OUT(hwregs, 0x440,0x0E000000);
322 VIA_OUT(hwregs, 0x440,0x0F000000);
323 VIA_OUT(hwregs, 0x440,0x10000000);
324 VIA_OUT(hwregs, 0x440,0x11000000);
325 VIA_OUT(hwregs, 0x440,0x20000000);
326 }
327
328 /** */
329
uc_after_set_var(void * drv,void * dev)330 static void uc_after_set_var(void* drv, void* dev)
331 {
332 UcDriverData* ucdrv = (UcDriverData*) drv;
333
334 VGA_OUT8(ucdrv->hwregs, 0x3c4, 0x1a);
335 // Clear bit 6 in extended VGA register 0x1a to prevent system lockup.
336 VGA_OUT8(ucdrv->hwregs, 0x3c5, VGA_IN8(ucdrv->hwregs, 0x3c5) & 0xbf);
337 // Set bit 2, it might make a difference.
338 VGA_OUT8(ucdrv->hwregs, 0x3c5, VGA_IN8(ucdrv->hwregs, 0x3c5) | 0x4);
339 }
340
341 /** Wait until the engine is idle. */
342
uc_engine_sync(void * drv,void * dev)343 static DFBResult uc_engine_sync(void* drv, void* dev)
344 {
345 UcDriverData* ucdrv = (UcDriverData*) drv;
346 UcDeviceData* ucdev = (UcDeviceData*) dev;
347
348 int loop = 0;
349
350 /* printf("Entering uc_engine_sync(), status is 0x%08x\n",
351 VIA_IN(ucdrv->hwregs, VIA_REG_STATUS));
352 */
353
354 while ((VIA_IN(ucdrv->hwregs, VIA_REG_STATUS) & 0xfffeffff) != 0x00020000) {
355 if (++loop > MAXLOOP) {
356 D_ERROR("DirectFB/VIA: Timeout waiting for idle engine!\n");
357 break;
358 }
359 }
360
361 /* printf("Leaving uc_engine_sync(), status is 0x%08x, "
362 "waiting for %d (0x%x) cycles.\n",
363 VIA_IN(ucdrv->hwregs, VIA_REG_STATUS), loop, loop);
364 */
365
366 ucdev->idle_waitcycles += loop;
367 ucdev->must_wait = 0;
368
369 return DFB_OK;
370 }
371
372
373 // DirectFB interfacing functions --------------------------------------------
374
driver_probe(CoreGraphicsDevice * device)375 static int driver_probe(CoreGraphicsDevice *device)
376 {
377 struct stat s;
378
379 switch (dfb_gfxcard_get_accelerator( device )) {
380 case FB_ACCEL_VIA_UNICHROME:
381 return 1;
382 }
383
384 return stat(UNICHROME_DEVICE, &s) + 1;
385 }
386
driver_get_info(CoreGraphicsDevice * device,GraphicsDriverInfo * info)387 static void driver_get_info(CoreGraphicsDevice* device,
388 GraphicsDriverInfo* info)
389 {
390 // Fill in driver info structure.
391
392 snprintf(info->name,
393 DFB_GRAPHICS_DRIVER_INFO_NAME_LENGTH,
394 "VIA UniChrome Driver");
395
396 snprintf(info->vendor,
397 DFB_GRAPHICS_DRIVER_INFO_VENDOR_LENGTH,
398 "-");
399
400 snprintf(info->url,
401 DFB_GRAPHICS_DRIVER_INFO_URL_LENGTH,
402 "http://www.directfb.org");
403
404 snprintf(info->license,
405 DFB_GRAPHICS_DRIVER_INFO_LICENSE_LENGTH,
406 "LGPL");
407
408 info->version.major = 0;
409 info->version.minor = 3;
410
411 info->driver_data_size = sizeof (UcDriverData);
412 info->device_data_size = sizeof (UcDeviceData);
413 }
414
415
driver_init_driver(CoreGraphicsDevice * device,GraphicsDeviceFuncs * funcs,void * driver_data,void * device_data,CoreDFB * core)416 static DFBResult driver_init_driver(CoreGraphicsDevice* device,
417 GraphicsDeviceFuncs* funcs,
418 void* driver_data,
419 void* device_data,
420 CoreDFB *core)
421 {
422 UcDriverData *ucdrv = (UcDriverData*) driver_data;
423
424 //printf("Entering %s\n", __PRETTY_FUNCTION__);
425
426 ucdrv->file = -1;
427 ucdrv->pool = dfb_core_shmpool( core );
428
429 ucdrv->hwregs = dfb_gfxcard_map_mmio( device, 0, 0 );
430 if (!ucdrv->hwregs) {
431 int fd;
432
433 fd = open(UNICHROME_DEVICE, O_RDWR | O_SYNC, 0);
434 if (fd < 0) {
435 D_ERROR("Could not access %s. "
436 "Is the cle266vgaio module installed?\n", UNICHROME_DEVICE);
437 return DFB_IO;
438 }
439
440 ucdrv->file = fd;
441
442 ucdrv->hwregs = mmap(NULL, 0x1000000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
443 if (ucdrv->hwregs == MAP_FAILED)
444 return DFB_IO;
445 }
446
447 /* FIXME: this belongs to device_data! */
448 ucdrv->fifo = uc_fifo_create(ucdrv->pool, UC_FIFO_SIZE);
449 if (!ucdrv->fifo)
450 return D_OOSHM();
451
452 uc_after_set_var(driver_data, device_data);
453
454 ucdrv->hwrev = 3; // FIXME: Get the real hardware revision number!!!
455
456 // Driver specific initialization
457
458 funcs->CheckState = uc_check_state;
459 funcs->SetState = uc_set_state;
460 funcs->EngineSync = uc_engine_sync;
461 funcs->EmitCommands = uc_emit_commands;
462 funcs->FlushTextureCache = uc_flush_texture_cache;
463 funcs->AfterSetVar = uc_after_set_var;
464
465 funcs->FillRectangle = uc_fill_rectangle;
466 funcs->DrawRectangle = uc_draw_rectangle;
467 funcs->DrawLine = uc_draw_line;
468 funcs->FillTriangle = uc_fill_triangle;
469 funcs->Blit = uc_blit;
470 funcs->StretchBlit = uc_stretch_blit;
471 funcs->TextureTriangles = uc_texture_triangles;
472
473
474 /* install primary layer hooks */
475 if ( getenv("DFB_CLE266_UNDERLAY"))
476 dfb_layers_hook_primary( device, driver_data, &ucPrimaryFuncs,
477 &ucOldPrimaryFuncs, &ucOldPrimaryDriverData );
478
479 dfb_layers_register( dfb_screens_at(DSCID_PRIMARY),
480 driver_data, &ucOverlayFuncs );
481
482 return DFB_OK;
483 }
484
driver_init_device(CoreGraphicsDevice * device,GraphicsDeviceInfo * device_info,void * driver_data,void * device_data)485 static DFBResult driver_init_device(CoreGraphicsDevice* device,
486 GraphicsDeviceInfo* device_info,
487 void* driver_data,
488 void* device_data)
489 {
490 UcDriverData *ucdrv = (UcDriverData*) driver_data;
491 UcDeviceData *ucdev = (UcDeviceData*) device_data;
492
493 //printf("Entering %s\n", __PRETTY_FUNCTION__);
494
495 snprintf(device_info->name,
496 DFB_GRAPHICS_DEVICE_INFO_NAME_LENGTH, "UniChrome");
497 snprintf(device_info->vendor,
498 DFB_GRAPHICS_DEVICE_INFO_VENDOR_LENGTH, "VIA/S3G");
499
500 device_info->caps.flags = CCF_CLIPPING;
501 device_info->caps.accel =
502 UC_DRAWING_FUNCTIONS_2D | UC_DRAWING_FUNCTIONS_3D |
503 UC_BLITTING_FUNCTIONS_2D | UC_BLITTING_FUNCTIONS_3D;
504
505 device_info->caps.drawing = UC_DRAWING_FLAGS_2D | UC_DRAWING_FLAGS_3D;
506 device_info->caps.blitting = UC_BLITTING_FLAGS_2D | UC_BLITTING_FLAGS_3D;
507
508 device_info->limits.surface_byteoffset_alignment = 32;
509 device_info->limits.surface_pixelpitch_alignment = 32;
510
511 ucdev->pitch = 0;
512 ucdev->draw_rop2d = VIA_ROP_P;
513 ucdev->draw_rop3d = HC_HROP_P;
514 ucdev->color = 0;
515 ucdev->bflags = 0;
516
517 ucdev->must_wait = 0;
518 ucdev->cmd_waitcycles = 0;
519 ucdev->idle_waitcycles = 0;
520
521 uc_init_2d_engine(device, ucdev, ucdrv, false); // VQ disabled - can't make it work.
522 uc_init_3d_engine(ucdrv->hwregs, ucdrv->hwrev, 1);
523
524 return DFB_OK;
525 }
526
driver_close_device(CoreGraphicsDevice * device,void * driver_data,void * device_data)527 static void driver_close_device(CoreGraphicsDevice *device,
528 void *driver_data, void *device_data)
529 {
530 UcDriverData* ucdrv = (UcDriverData*) driver_data;
531 UcDeviceData* ucdev = (UcDeviceData*) device_data;
532
533 // uc_dump_vq(ucdev);
534
535 uc_engine_sync(driver_data, device_data);
536 uc_init_2d_engine(device, ucdev, ucdrv, false);
537 }
538
driver_close_driver(CoreGraphicsDevice * device,void * driver_data)539 static void driver_close_driver(CoreGraphicsDevice* device, void* driver_data)
540 {
541 UcDriverData* ucdrv = (UcDriverData*) driver_data;
542
543 if (ucdrv->fifo)
544 uc_fifo_destroy( ucdrv->pool, ucdrv->fifo );
545
546 if (ucdrv->file != -1)
547 close( ucdrv->file );
548 }
549