summaryrefslogtreecommitdiff
path: root/Source/DirectFB/gfxdrivers/cle266/unichrome.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/gfxdrivers/cle266/unichrome.c')
-rwxr-xr-xSource/DirectFB/gfxdrivers/cle266/unichrome.c548
1 files changed, 548 insertions, 0 deletions
diff --git a/Source/DirectFB/gfxdrivers/cle266/unichrome.c b/Source/DirectFB/gfxdrivers/cle266/unichrome.c
new file mode 100755
index 0000000..7dbb8bc
--- /dev/null
+++ b/Source/DirectFB/gfxdrivers/cle266/unichrome.c
@@ -0,0 +1,548 @@
+/*
+ Copyright (c) 2003 Andreas Robinson, All rights reserved.
+
+ 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 of the License, or (at your option) any later version.
+*/
+
+
+/*
+
+EPIA-M benchmarks (df_dok)
+
+ SW v0.0.1 v0.1.0 v0.2.0 v0.3
+
+Anti-aliased Text 98.97 - - - 280.80 KChars/sec
+Anti-aliased Text (blend) 28.85 - - - 280.61 KChars/sec
+Fill Rectangles 25.21 443.46 437.05 432.39 435.60 Mpixel/sec
+Fill Rectangles (blend) 5.54 - 130.12 128.42 127.82 MPixel/sec
+Fill Triangles 24.84 173.44 129.76 127.86 128.63 MPixel/sec
+Fill Triangles (blend) 5.46 - 129.81 127.86 128.67 MPixel/sec
+Draw Rectangles 11.82 58.98 59.07 52.48 55.10 KRects/sec
+Draw Rectangles (blend) 1.98 - 32.13 22.76 23.50 KRects/sec
+Draw Lines 42.67 283.81 292.33 193.87 203.20 KLines/sec
+Draw Lines (blend) 8.54 - 142.62 101.23 102.80 KLines/sec
+Blit 21.48 - 117.38 114.26 114.41 MPixel/sec
+Blit colorkeyed 22.54 - 117.34 114.26 114.41 MPixel/sec
+Blit w/ format conversion 16.22 - - 103.41 103.00 MPixel/sec
+Blit from 32bit (blend) 4.19 - - 87.72 87.32 MPixel/sec
+Blit from 8bit palette 11.02 - - 110.13 113.37 MPixel/sec
+Blit from 8bit pal. (blend) 3.78 - - 110.20 113.40 MPixel/sec
+Stretch Blit 23.19 - - 99.53 99.32 MPixel/sec
+Stretch Blit colorkeyed 25.04 - - 5.00 38.00 MPixel/sec
+
+
+Comparing M9000 and M10000
+
+v0.2.0 M9000 M10000
+
+Anti-aliased Text - - KChars/sec
+Anti-aliased Text (blend) - - KChars/sec
+Fill Rectangles 401.82 432.39 Mpixel/sec
+Fill Rectangles (blend) 129.05 128.42 MPixel/sec
+Fill Triangles 128.46 127.86 MPixel/sec
+Fill Triangles (blend) 128.46 127.86 MPixel/sec
+Draw Rectangles 55.51 52.48 KRects/sec
+Draw Rectangles (blend) 26.90 22.76 KRects/sec
+Draw Lines 225.00 193.87 KLines/sec
+Draw Lines (blend) 121.29 101.23 KLines/sec
+Blit 112.36 114.26 MPixel/sec
+Blit colorkeyed 112.28 114.26 MPixel/sec
+Blit w/ format conversion 103.92 103.41 MPixel/sec
+Blit from 32bit (blend) 87.89 87.72 MPixel/sec
+Blit from 8bit palette 110.56 110.13 MPixel/sec
+Blit from 8bit pal. (blend) 110.56 110.20 MPixel/sec
+Stretch Blit 108.67 99.53 MPixel/sec
+Stretch Blit colorkeyed 4.79 5.00 MPixel/sec
+
+
+v0.0.1 and v0.1.0 are tested on an EPIA-M9000,
+later versions on an EPIA-M10000.
+
+*/
+
+// DirectFB headers
+
+#include <config.h>
+
+#include <directfb.h>
+
+#include <fusion/shmalloc.h>
+
+#include <direct/messages.h>
+
+#include <core/coretypes.h>
+#include <core/core.h>
+#include <core/gfxcard.h>
+#include <core/graphics_driver.h>
+#include <core/system.h>
+#include <core/screens.h>
+
+#include <fbdev/fb.h>
+
+// System headers
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include <string.h>
+
+// Driver headers
+
+#include "unichrome.h"
+#include "uc_state.h"
+#include "uc_accel.h"
+#include "uc_fifo.h"
+#include "mmio.h"
+
+#ifndef FB_ACCEL_VIA_UNICHROME
+#define FB_ACCEL_VIA_UNICHROME 77
+#endif
+
+extern DisplayLayerFuncs ucOverlayFuncs;
+extern DisplayLayerFuncs ucPrimaryFuncs;
+
+extern DisplayLayerFuncs ucOldPrimaryFuncs;
+extern void *ucOldPrimaryDriverData;
+
+DFB_GRAPHICS_DRIVER(cle266)
+
+//----------
+
+
+/**
+ * Dump beginning of virtual queue.
+ * Use it to check that the VQ actually is in use. */
+#if 0
+static void uc_dump_vq(UcDeviceData *ucdev)
+{
+ int i;
+ u8* vq;
+
+ if (!ucdev->vq_start) return;
+ vq = dfb_system_video_memory_virtual(ucdev->vq_start);
+
+ for (i = 0; i < 128; i++) {
+ printf("%02x ", *(vq+i));
+ if ((i+1) % 16 == 0) printf("\n");
+ }
+}
+#endif
+
+/** Allocate memory for the virtual queue. */
+
+static DFBResult uc_alloc_vq(CoreGraphicsDevice *device, UcDeviceData *ucdev)
+{
+ if (ucdev->vq_start) return DFB_OK;
+
+ ucdev->vq_size = 256*1024; // 256kb
+ ucdev->vq_start = dfb_gfxcard_reserve_memory( device, ucdev->vq_size );
+
+ if (!ucdev->vq_start)
+ return DFB_INIT;
+
+ ucdev->vq_end = ucdev->vq_start + ucdev->vq_size - 1;
+
+ // Debug: clear buffer
+ memset((void *) dfb_system_video_memory_virtual(ucdev->vq_start),
+ 0xcc, ucdev->vq_size);
+
+ // uc_dump_vq(ucdev);
+
+ return DFB_OK;
+}
+
+/**
+ * Initialize the hardware.
+ * @param enable enable VQ if true (else disable it.)
+ */
+
+static DFBResult uc_init_2d_engine(CoreGraphicsDevice *device, UcDeviceData *ucdev, UcDriverData *ucdrv, bool enable)
+{
+ DFBResult result = DFB_OK;
+ volatile u8* hwregs = ucdrv->hwregs;
+
+ // Init 2D engine registers to reset 2D engine
+
+ VIA_OUT(hwregs, 0x04, 0x0);
+ VIA_OUT(hwregs, 0x08, 0x0);
+ VIA_OUT(hwregs, 0x0c, 0x0);
+ VIA_OUT(hwregs, 0x10, 0x0);
+ VIA_OUT(hwregs, 0x14, 0x0);
+ VIA_OUT(hwregs, 0x18, 0x0);
+ VIA_OUT(hwregs, 0x1c, 0x0);
+ VIA_OUT(hwregs, 0x20, 0x0);
+ VIA_OUT(hwregs, 0x24, 0x0);
+ VIA_OUT(hwregs, 0x28, 0x0);
+ VIA_OUT(hwregs, 0x2c, 0x0);
+ VIA_OUT(hwregs, 0x30, 0x0);
+ VIA_OUT(hwregs, 0x34, 0x0);
+ VIA_OUT(hwregs, 0x38, 0x0);
+ VIA_OUT(hwregs, 0x3c, 0x0);
+ VIA_OUT(hwregs, 0x40, 0x0);
+
+ // Init AGP and VQ registers
+
+ VIA_OUT(hwregs, 0x43c, 0x00100000);
+ VIA_OUT(hwregs, 0x440, 0x00000000);
+ VIA_OUT(hwregs, 0x440, 0x00333004);
+ VIA_OUT(hwregs, 0x440, 0x60000000);
+ VIA_OUT(hwregs, 0x440, 0x61000000);
+ VIA_OUT(hwregs, 0x440, 0x62000000);
+ VIA_OUT(hwregs, 0x440, 0x63000000);
+ VIA_OUT(hwregs, 0x440, 0x64000000);
+ VIA_OUT(hwregs, 0x440, 0x7D000000);
+
+ VIA_OUT(hwregs, 0x43c, 0xfe020000);
+ VIA_OUT(hwregs, 0x440, 0x00000000);
+
+ if (enable) {
+ result = uc_alloc_vq(device,ucdev);
+ enable = (result == DFB_OK);
+ }
+
+ if (enable) { // Enable VQ
+
+ VIA_OUT(hwregs, 0x43c, 0x00fe0000);
+ VIA_OUT(hwregs, 0x440, 0x080003fe);
+ VIA_OUT(hwregs, 0x440, 0x0a00027c);
+ VIA_OUT(hwregs, 0x440, 0x0b000260);
+ VIA_OUT(hwregs, 0x440, 0x0c000274);
+ VIA_OUT(hwregs, 0x440, 0x0d000264);
+ VIA_OUT(hwregs, 0x440, 0x0e000000);
+ VIA_OUT(hwregs, 0x440, 0x0f000020);
+ VIA_OUT(hwregs, 0x440, 0x1000027e);
+ VIA_OUT(hwregs, 0x440, 0x110002fe);
+ VIA_OUT(hwregs, 0x440, 0x200f0060);
+
+ VIA_OUT(hwregs, 0x440, 0x00000006);
+ VIA_OUT(hwregs, 0x440, 0x40008c0f);
+ VIA_OUT(hwregs, 0x440, 0x44000000);
+ VIA_OUT(hwregs, 0x440, 0x45080c04);
+ VIA_OUT(hwregs, 0x440, 0x46800408);
+
+ VIA_OUT(hwregs, 0x440, 0x52000000 |
+ ((ucdev->vq_start & 0xFF000000) >> 24) |
+ ((ucdev->vq_end & 0xFF000000) >> 16));
+ VIA_OUT(hwregs, 0x440, 0x50000000 | (ucdev->vq_start & 0xFFFFFF));
+ VIA_OUT(hwregs, 0x440, 0x51000000 | (ucdev->vq_end & 0xFFFFFF));
+ VIA_OUT(hwregs, 0x440, 0x53000000 | (ucdev->vq_size >> 3));
+ }
+ else { // Disable VQ
+
+ VIA_OUT(hwregs, 0x43c, 0x00fe0000);
+ VIA_OUT(hwregs, 0x440, 0x00000004);
+ VIA_OUT(hwregs, 0x440, 0x40008c0f);
+ VIA_OUT(hwregs, 0x440, 0x44000000);
+ VIA_OUT(hwregs, 0x440, 0x45080c04);
+ VIA_OUT(hwregs, 0x440, 0x46800408);
+ }
+
+ return result;
+}
+
+static void uc_init_3d_engine(volatile u8* hwregs, int hwrev, bool init_all)
+{
+ u32 i;
+
+ if (init_all) {
+
+ // Clear NotTex registers (?)
+
+ VIA_OUT(hwregs, 0x43C, 0x00010000);
+ for (i = 0; i <= 0x7d; i++)
+ VIA_OUT(hwregs, 0x440, i << 24);
+
+ // Clear texture unit 0 (?)
+
+ VIA_OUT(hwregs, 0x43C, 0x00020000);
+ for (i = 0; i <= 0x94; i++)
+ VIA_OUT(hwregs, 0x440, i << 24);
+ VIA_OUT(hwregs, 0x440, 0x82400000);
+
+ // Clear texture unit 1 (?)
+
+ VIA_OUT(hwregs, 0x43C, 0x01020000);
+ for (i = 0; i <= 0x94; i++)
+ VIA_OUT(hwregs, 0x440, i << 24);
+ VIA_OUT(hwregs, 0x440, 0x82400000);
+
+ // Clear general texture settings (?)
+
+ VIA_OUT(hwregs, 0x43C, 0xfe020000);
+ for (i = 0; i <= 0x03; i++)
+ VIA_OUT(hwregs, 0x440, i << 24);
+
+ // Clear palette settings (?)
+
+ VIA_OUT(hwregs, 0x43C, 0x00030000);
+ for (i = 0; i <= 0xff; i++)
+ VIA_OUT(hwregs, 0x440, 0);
+
+ VIA_OUT(hwregs, 0x43C, 0x00100000);
+ VIA_OUT(hwregs, 0x440, 0x00333004);
+ VIA_OUT(hwregs, 0x440, 0x10000002);
+ VIA_OUT(hwregs, 0x440, 0x60000000);
+ VIA_OUT(hwregs, 0x440, 0x61000000);
+ VIA_OUT(hwregs, 0x440, 0x62000000);
+ VIA_OUT(hwregs, 0x440, 0x63000000);
+ VIA_OUT(hwregs, 0x440, 0x64000000);
+
+ VIA_OUT(hwregs, 0x43C, 0x00fe0000);
+
+ if (hwrev >= 3)
+ VIA_OUT(hwregs, 0x440,0x40008c0f);
+ else
+ VIA_OUT(hwregs, 0x440,0x4000800f);
+
+ VIA_OUT(hwregs, 0x440,0x44000000);
+ VIA_OUT(hwregs, 0x440,0x45080C04);
+ VIA_OUT(hwregs, 0x440,0x46800408);
+ VIA_OUT(hwregs, 0x440,0x50000000);
+ VIA_OUT(hwregs, 0x440,0x51000000);
+ VIA_OUT(hwregs, 0x440,0x52000000);
+ VIA_OUT(hwregs, 0x440,0x53000000);
+
+ }
+
+ VIA_OUT(hwregs, 0x43C,0x00fe0000);
+ VIA_OUT(hwregs, 0x440,0x08000001);
+ VIA_OUT(hwregs, 0x440,0x0A000183);
+ VIA_OUT(hwregs, 0x440,0x0B00019F);
+ VIA_OUT(hwregs, 0x440,0x0C00018B);
+ VIA_OUT(hwregs, 0x440,0x0D00019B);
+ VIA_OUT(hwregs, 0x440,0x0E000000);
+ VIA_OUT(hwregs, 0x440,0x0F000000);
+ VIA_OUT(hwregs, 0x440,0x10000000);
+ VIA_OUT(hwregs, 0x440,0x11000000);
+ VIA_OUT(hwregs, 0x440,0x20000000);
+}
+
+/** */
+
+static void uc_after_set_var(void* drv, void* dev)
+{
+ UcDriverData* ucdrv = (UcDriverData*) drv;
+
+ VGA_OUT8(ucdrv->hwregs, 0x3c4, 0x1a);
+ // Clear bit 6 in extended VGA register 0x1a to prevent system lockup.
+ VGA_OUT8(ucdrv->hwregs, 0x3c5, VGA_IN8(ucdrv->hwregs, 0x3c5) & 0xbf);
+ // Set bit 2, it might make a difference.
+ VGA_OUT8(ucdrv->hwregs, 0x3c5, VGA_IN8(ucdrv->hwregs, 0x3c5) | 0x4);
+}
+
+/** Wait until the engine is idle. */
+
+static DFBResult uc_engine_sync(void* drv, void* dev)
+{
+ UcDriverData* ucdrv = (UcDriverData*) drv;
+ UcDeviceData* ucdev = (UcDeviceData*) dev;
+
+ int loop = 0;
+
+/* printf("Entering uc_engine_sync(), status is 0x%08x\n",
+ VIA_IN(ucdrv->hwregs, VIA_REG_STATUS));
+*/
+
+ while ((VIA_IN(ucdrv->hwregs, VIA_REG_STATUS) & 0xfffeffff) != 0x00020000) {
+ if (++loop > MAXLOOP) {
+ D_ERROR("DirectFB/VIA: Timeout waiting for idle engine!\n");
+ break;
+ }
+ }
+
+ /* printf("Leaving uc_engine_sync(), status is 0x%08x, "
+ "waiting for %d (0x%x) cycles.\n",
+ VIA_IN(ucdrv->hwregs, VIA_REG_STATUS), loop, loop);
+ */
+
+ ucdev->idle_waitcycles += loop;
+ ucdev->must_wait = 0;
+
+ return DFB_OK;
+}
+
+
+// DirectFB interfacing functions --------------------------------------------
+
+static int driver_probe(CoreGraphicsDevice *device)
+{
+ struct stat s;
+
+ switch (dfb_gfxcard_get_accelerator( device )) {
+ case FB_ACCEL_VIA_UNICHROME:
+ return 1;
+ }
+
+ return stat(UNICHROME_DEVICE, &s) + 1;
+}
+
+static void driver_get_info(CoreGraphicsDevice* device,
+ GraphicsDriverInfo* info)
+{
+ // Fill in driver info structure.
+
+ snprintf(info->name,
+ DFB_GRAPHICS_DRIVER_INFO_NAME_LENGTH,
+ "VIA UniChrome Driver");
+
+ snprintf(info->vendor,
+ DFB_GRAPHICS_DRIVER_INFO_VENDOR_LENGTH,
+ "-");
+
+ snprintf(info->url,
+ DFB_GRAPHICS_DRIVER_INFO_URL_LENGTH,
+ "http://www.directfb.org");
+
+ snprintf(info->license,
+ DFB_GRAPHICS_DRIVER_INFO_LICENSE_LENGTH,
+ "LGPL");
+
+ info->version.major = 0;
+ info->version.minor = 3;
+
+ info->driver_data_size = sizeof (UcDriverData);
+ info->device_data_size = sizeof (UcDeviceData);
+}
+
+
+static DFBResult driver_init_driver(CoreGraphicsDevice* device,
+ GraphicsDeviceFuncs* funcs,
+ void* driver_data,
+ void* device_data,
+ CoreDFB *core)
+{
+ UcDriverData *ucdrv = (UcDriverData*) driver_data;
+
+ //printf("Entering %s\n", __PRETTY_FUNCTION__);
+
+ ucdrv->file = -1;
+ ucdrv->pool = dfb_core_shmpool( core );
+
+ ucdrv->hwregs = dfb_gfxcard_map_mmio( device, 0, 0 );
+ if (!ucdrv->hwregs) {
+ int fd;
+
+ fd = open(UNICHROME_DEVICE, O_RDWR | O_SYNC, 0);
+ if (fd < 0) {
+ D_ERROR("Could not access %s. "
+ "Is the cle266vgaio module installed?\n", UNICHROME_DEVICE);
+ return DFB_IO;
+ }
+
+ ucdrv->file = fd;
+
+ ucdrv->hwregs = mmap(NULL, 0x1000000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (ucdrv->hwregs == MAP_FAILED)
+ return DFB_IO;
+ }
+
+ /* FIXME: this belongs to device_data! */
+ ucdrv->fifo = uc_fifo_create(ucdrv->pool, UC_FIFO_SIZE);
+ if (!ucdrv->fifo)
+ return D_OOSHM();
+
+ uc_after_set_var(driver_data, device_data);
+
+ ucdrv->hwrev = 3; // FIXME: Get the real hardware revision number!!!
+
+ // Driver specific initialization
+
+ funcs->CheckState = uc_check_state;
+ funcs->SetState = uc_set_state;
+ funcs->EngineSync = uc_engine_sync;
+ funcs->EmitCommands = uc_emit_commands;
+ funcs->FlushTextureCache = uc_flush_texture_cache;
+ funcs->AfterSetVar = uc_after_set_var;
+
+ funcs->FillRectangle = uc_fill_rectangle;
+ funcs->DrawRectangle = uc_draw_rectangle;
+ funcs->DrawLine = uc_draw_line;
+ funcs->FillTriangle = uc_fill_triangle;
+ funcs->Blit = uc_blit;
+ funcs->StretchBlit = uc_stretch_blit;
+ funcs->TextureTriangles = uc_texture_triangles;
+
+
+ /* install primary layer hooks */
+ if ( getenv("DFB_CLE266_UNDERLAY"))
+ dfb_layers_hook_primary( device, driver_data, &ucPrimaryFuncs,
+ &ucOldPrimaryFuncs, &ucOldPrimaryDriverData );
+
+ dfb_layers_register( dfb_screens_at(DSCID_PRIMARY),
+ driver_data, &ucOverlayFuncs );
+
+ return DFB_OK;
+}
+
+static DFBResult driver_init_device(CoreGraphicsDevice* device,
+ GraphicsDeviceInfo* device_info,
+ void* driver_data,
+ void* device_data)
+{
+ UcDriverData *ucdrv = (UcDriverData*) driver_data;
+ UcDeviceData *ucdev = (UcDeviceData*) device_data;
+
+ //printf("Entering %s\n", __PRETTY_FUNCTION__);
+
+ snprintf(device_info->name,
+ DFB_GRAPHICS_DEVICE_INFO_NAME_LENGTH, "UniChrome");
+ snprintf(device_info->vendor,
+ DFB_GRAPHICS_DEVICE_INFO_VENDOR_LENGTH, "VIA/S3G");
+
+ device_info->caps.flags = CCF_CLIPPING;
+ device_info->caps.accel =
+ UC_DRAWING_FUNCTIONS_2D | UC_DRAWING_FUNCTIONS_3D |
+ UC_BLITTING_FUNCTIONS_2D | UC_BLITTING_FUNCTIONS_3D;
+
+ device_info->caps.drawing = UC_DRAWING_FLAGS_2D | UC_DRAWING_FLAGS_3D;
+ device_info->caps.blitting = UC_BLITTING_FLAGS_2D | UC_BLITTING_FLAGS_3D;
+
+ device_info->limits.surface_byteoffset_alignment = 32;
+ device_info->limits.surface_pixelpitch_alignment = 32;
+
+ ucdev->pitch = 0;
+ ucdev->draw_rop2d = VIA_ROP_P;
+ ucdev->draw_rop3d = HC_HROP_P;
+ ucdev->color = 0;
+ ucdev->bflags = 0;
+
+ ucdev->must_wait = 0;
+ ucdev->cmd_waitcycles = 0;
+ ucdev->idle_waitcycles = 0;
+
+ uc_init_2d_engine(device, ucdev, ucdrv, false); // VQ disabled - can't make it work.
+ uc_init_3d_engine(ucdrv->hwregs, ucdrv->hwrev, 1);
+
+ return DFB_OK;
+}
+
+static void driver_close_device(CoreGraphicsDevice *device,
+ void *driver_data, void *device_data)
+{
+ UcDriverData* ucdrv = (UcDriverData*) driver_data;
+ UcDeviceData* ucdev = (UcDeviceData*) device_data;
+
+ // uc_dump_vq(ucdev);
+
+ uc_engine_sync(driver_data, device_data);
+ uc_init_2d_engine(device, ucdev, ucdrv, false);
+}
+
+static void driver_close_driver(CoreGraphicsDevice* device, void* driver_data)
+{
+ UcDriverData* ucdrv = (UcDriverData*) driver_data;
+
+ if (ucdrv->fifo)
+ uc_fifo_destroy( ucdrv->pool, ucdrv->fifo );
+
+ if (ucdrv->file != -1)
+ close( ucdrv->file );
+}