aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/kdrive/epson/epson13806.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/kdrive/epson/epson13806.c')
-rw-r--r--xorg-server/hw/kdrive/epson/epson13806.c604
1 files changed, 604 insertions, 0 deletions
diff --git a/xorg-server/hw/kdrive/epson/epson13806.c b/xorg-server/hw/kdrive/epson/epson13806.c
new file mode 100644
index 000000000..6cf8c9ad9
--- /dev/null
+++ b/xorg-server/hw/kdrive/epson/epson13806.c
@@ -0,0 +1,604 @@
+/*
+ * Copyright 2004 by Costas Stylianou <costas.stylianou@psion.com> +44(0)7850 394095
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Costas Sylianou not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Costas Stylianou makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as is" without express or implied warranty.
+ *
+ * COSTAS STYLIANOU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL COSTAS STYLIANOU BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * epson13806.c - Implementation of hardware accelerated functions for
+ * Epson S1D13806 graphics controller.
+ *
+ * History:
+ * 28-Jan-04 C.Stylianou PRJ NBL: Created from fbdev.c.
+ * 30-Mar-04 Phil Blundell/Peter Naulls Integration with XFree 4.3
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <kdrive-config.h>
+#endif
+
+#include <sys/ioctl.h>
+
+#include "epson13806.h"
+#include "epson13806reg.h"
+
+extern int KdTsPhyScreen;
+
+Bool
+epsonInitialize (KdCardInfo *card, EpsonPriv *priv)
+{
+ int k;
+ unsigned long off;
+ if ((priv->fd = open("/dev/fb0", O_RDWR)) < 0) {
+ perror("Error opening /dev/fb0\n");
+ return FALSE;
+ }
+
+ if ((k=ioctl(priv->fd, FBIOGET_FSCREENINFO, &priv->fix)) < 0) {
+ perror("Error with /dev/fb ioctl FIOGET_FSCREENINFO");
+ close (priv->fd);
+ return FALSE;
+ }
+
+ if ((k=ioctl(priv->fd, FBIOGET_VSCREENINFO, &priv->var)) < 0) {
+ perror("Error with /dev/fb ioctl FIOGET_VSCREENINFO");
+ close (priv->fd);
+ return FALSE;
+ }
+
+ priv->fb_base = KdMapDevice (EPSON13806_PHYSICAL_VMEM_ADDR, EPSON13806_VMEM_SIZE);
+
+
+ if (priv->fb_base == (char *)-1) {
+ perror("ERROR: mmap framebuffer fails!");
+ close (priv->fd);
+ return FALSE;
+ }
+
+ off = (unsigned long) priv->fix.smem_start % (unsigned long) getpagesize();
+ priv->fb = priv->fb_base + off;
+ return TRUE;
+}
+
+Bool
+epsonCardInit (KdCardInfo *card)
+{
+ EpsonPriv *priv;
+
+ priv = (EpsonPriv *) xalloc (sizeof (EpsonPriv));
+ if (!priv)
+ return FALSE;
+
+ if (!epsonInitialize (card, priv))
+ {
+ xfree (priv);
+ return FALSE;
+ }
+ card->driver = priv;
+
+ // Call InitEpson to map onto Epson registers
+ initEpson13806();
+
+ return TRUE;
+}
+
+#define FBDEV_KLUDGE_FORMAT
+#ifdef FBDEV_KLUDGE_FORMAT
+static Pixel
+epsonMakeContig (Pixel orig, Pixel others)
+{
+ Pixel low;
+
+ low = lowbit (orig) >> 1;
+ while (low && (others & low) == 0)
+ {
+ orig |= low;
+ low >>= 1;
+ }
+ return orig;
+}
+#endif
+
+Bool
+epsonScreenInitialize (KdScreenInfo *screen, EpsonScrPriv *scrpriv)
+{
+ EpsonPriv *priv = screen->card->driver;
+ Pixel allbits;
+ int depth;
+ Bool gray;
+ depth = priv->var.bits_per_pixel;
+ gray = priv->var.grayscale;
+
+
+ screen->fb[0].visuals = (1 << TrueColor);
+#define Mask(o,l) (((1 << l) - 1) << o)
+ screen->fb[0].redMask = Mask (priv->var.red.offset, priv->var.red.length);
+ screen->fb[0].greenMask = Mask (priv->var.green.offset, priv->var.green.length);
+ screen->fb[0].blueMask = Mask (priv->var.blue.offset, priv->var.blue.length);
+#ifdef FBDEV_KLUDGE_FORMAT
+ /*
+ * This is a kludge so that Render will work -- fill in the gaps
+ * in the pixel
+ */
+ screen->fb[0].redMask = epsonMakeContig (screen->fb[0].redMask,
+ screen->fb[0].greenMask|
+ screen->fb[0].blueMask);
+
+ screen->fb[0].greenMask = epsonMakeContig (screen->fb[0].greenMask,
+ screen->fb[0].redMask|
+ screen->fb[0].blueMask);
+
+ screen->fb[0].blueMask = epsonMakeContig (screen->fb[0].blueMask,
+ screen->fb[0].redMask|
+ screen->fb[0].greenMask);
+
+#endif
+ allbits = screen->fb[0].redMask | screen->fb[0].greenMask | screen->fb[0].blueMask;
+ depth = 32;
+ while (depth && !(allbits & (1 << (depth - 1))))
+ depth--;
+
+ screen->rate = 60;
+ scrpriv->randr = screen->randr;
+
+ {
+ screen->fb[0].depth = depth;
+ screen->fb[0].bitsPerPixel = priv->var.bits_per_pixel;
+ screen->width = priv->var.xres;
+ screen->height = priv->var.yres;
+ screen->fb[0].byteStride = priv->fix.line_length;
+ screen->fb[0].pixelStride = (priv->fix.line_length * 8 /
+ priv->var.bits_per_pixel);
+ screen->fb[0].frameBuffer = (CARD8 *) (priv->fb);
+ screen->off_screen_base = screen->fb[0].byteStride * screen->height;
+ screen->memory_base = priv->fb;
+ screen->memory_size = EPSON13806_VMEM_SIZE;
+ }
+ return TRUE;
+}
+
+Bool
+epsonScreenInit (KdScreenInfo *screen)
+{
+ EpsonScrPriv *scrpriv;
+
+ scrpriv = xalloc (sizeof (EpsonScrPriv));
+ if (!scrpriv)
+ return FALSE;
+ memset (scrpriv, '\0', sizeof (EpsonScrPriv));
+ screen->driver = scrpriv;
+ if (!epsonScreenInitialize (screen, scrpriv)) {
+ screen->driver = 0;
+ xfree (scrpriv);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void *
+epsonWindowLinear (ScreenPtr pScreen,
+ CARD32 row,
+ CARD32 offset,
+ int mode,
+ CARD32 *size,
+ void *closure)
+{
+ KdScreenPriv(pScreen);
+ EpsonPriv *priv = pScreenPriv->card->driver;
+
+ if (!pScreenPriv->enabled)
+ return 0;
+ *size = priv->fix.line_length;
+ return (CARD8 *) priv->fb + row * priv->fix.line_length + offset;
+}
+
+
+#ifdef RANDR
+static Bool
+epsonRandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EpsonScrPriv *scrpriv = screen->driver;
+#if 0
+ RRVisualGroupPtr pVisualGroup;
+ RRGroupOfVisualGroupPtr pGroupOfVisualGroup;
+#endif
+ RRScreenSizePtr pSize;
+ Rotation randr;
+ int n;
+
+ *rotations = RR_Rotate_0|RR_Rotate_90|RR_Rotate_180|RR_Rotate_270;
+
+ for (n = 0; n < pScreen->numDepths; n++)
+ if (pScreen->allowedDepths[n].numVids)
+ break;
+ if (n == pScreen->numDepths)
+ return FALSE;
+
+#if 0
+ pVisualGroup = RRCreateVisualGroup (pScreen);
+ if (!pVisualGroup)
+ return FALSE;
+
+ if (!RRAddDepthToVisualGroup (pScreen, pVisualGroup, &pScreen->allowedDepths[n])) {
+ RRDestroyVisualGroup (pScreen, pVisualGroup);
+ return FALSE;
+ }
+
+ pVisualGroup = RRRegisterVisualGroup (pScreen, pVisualGroup);
+ if (!pVisualGroup)
+ return FALSE;
+
+ pGroupOfVisualGroup = RRCreateGroupOfVisualGroup (pScreen);
+
+ if (!RRAddVisualGroupToGroupOfVisualGroup (pScreen,
+ pGroupOfVisualGroup,
+ pVisualGroup))
+ {
+ RRDestroyGroupOfVisualGroup (pScreen, pGroupOfVisualGroup);
+ /* pVisualGroup left until screen closed */
+ return FALSE;
+ }
+
+ pGroupOfVisualGroup = RRRegisterGroupOfVisualGroup (pScreen, pGroupOfVisualGroup);
+ if (!pGroupOfVisualGroup)
+ return FALSE;
+#endif
+
+ pSize = RRRegisterSize (pScreen,
+ screen->width,
+ screen->height,
+ screen->width_mm,
+ screen->height_mm);
+
+ randr = KdSubRotation (scrpriv->randr, screen->randr);
+
+ RRSetCurrentConfig (pScreen, randr, RR_Rotate_0, pSize);
+
+ return TRUE;
+}
+
+static Bool
+epsonRandRSetConfig (ScreenPtr pScreen,
+ Rotation randr,
+ int rate,
+ RRScreenSizePtr pSize)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EpsonScrPriv *scrpriv = screen->driver;
+ Bool wasEnabled = pScreenPriv->enabled;
+
+ randr = KdAddRotation (randr, screen->randr);
+
+ if (scrpriv->randr != randr)
+ {
+ if (wasEnabled)
+ KdDisableScreen (pScreen);
+
+ scrpriv->randr = randr;
+
+ if (wasEnabled)
+ KdEnableScreen (pScreen);
+ }
+ return TRUE;
+}
+
+static Bool
+epsonRandRInit (ScreenPtr pScreen)
+{
+ rrScrPrivPtr pScrPriv;
+
+ if (!RRScreenInit (pScreen))
+ return FALSE;
+
+ pScrPriv = rrGetScrPriv(pScreen);
+ pScrPriv->rrGetInfo = epsonRandRGetInfo;
+ pScrPriv->rrSetConfig = epsonRandRSetConfig;
+ return TRUE;
+}
+#endif
+
+static Bool
+epsonCreateColormap (ColormapPtr pmap)
+{
+ ScreenPtr pScreen = pmap->pScreen;
+ KdScreenPriv(pScreen);
+ EpsonPriv *priv = pScreenPriv->card->driver;
+ VisualPtr pVisual;
+ int i;
+ int nent;
+ xColorItem *pdefs;
+
+ switch (priv->fix.visual) {
+ case FB_VISUAL_STATIC_PSEUDOCOLOR:
+ pVisual = pmap->pVisual;
+ nent = pVisual->ColormapEntries;
+ pdefs = xalloc (nent * sizeof (xColorItem));
+ if (!pdefs)
+ return FALSE;
+ for (i = 0; i < nent; i++)
+ pdefs[i].pixel = i;
+ epsonGetColors (pScreen, 0, nent, pdefs);
+ for (i = 0; i < nent; i++)
+ {
+ pmap->red[i].co.local.red = pdefs[i].red;
+ pmap->red[i].co.local.green = pdefs[i].green;
+ pmap->red[i].co.local.blue = pdefs[i].blue;
+ }
+ xfree (pdefs);
+ return TRUE;
+
+ default:
+ return fbInitializeColormap (pmap);
+ }
+}
+
+Bool
+epsonInitScreen (ScreenPtr pScreen)
+{
+#ifdef TOUCHSCREEN
+ KdTsPhyScreen = pScreen->myNum;
+#endif
+
+ pScreen->CreateColormap = epsonCreateColormap;
+
+ return TRUE;
+}
+
+static Bool
+epsonFinishInitScreen (ScreenPtr pScreen)
+{
+ if (!shadowSetup (pScreen))
+ return FALSE;
+
+#ifdef RANDR
+ if (!epsonRandRInit (pScreen))
+ return FALSE;
+#endif
+
+ return TRUE;
+}
+
+static Bool
+epsonSetShadow (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EpsonScrPriv *scrpriv = screen->driver;
+ ShadowUpdateProc update;
+ ShadowWindowProc window;
+
+ window = epsonWindowLinear;
+ update = shadowUpdatePacked;
+
+ return KdShadowSet (pScreen, scrpriv->randr, update, window);
+}
+
+static Bool
+epsonCreateResources (ScreenPtr pScreen)
+{
+ return epsonSetShadow (pScreen);
+}
+
+void
+epsonPreserve (KdCardInfo *card)
+{
+}
+
+Bool
+epsonEnable (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ EpsonPriv *priv = pScreenPriv->card->driver;
+ int k;
+
+ priv->var.activate = FB_ACTIVATE_NOW|FB_CHANGE_CMAP_VBL;
+
+ /* display it on the LCD */
+ k = ioctl (priv->fd, FBIOPUT_VSCREENINFO, &priv->var);
+ if (k < 0) {
+ perror ("FBIOPUT_VSCREENINFO");
+ return FALSE;
+ }
+
+ k = ioctl (priv->fd, FBIOGET_FSCREENINFO, &priv->fix);
+ if (k < 0) {
+ perror ("FBIOGET_FSCREENINFO");
+ return FALSE;
+ }
+
+ if (priv->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+ struct fb_cmap cmap;
+ int i;
+
+ for (i = 0;
+ i < (1 << priv->var.red.length) ||
+ i < (1 << priv->var.green.length) ||
+ i < (1 << priv->var.blue.length); i++) {
+ priv->red[i] = i * 65535 / ((1 << priv->var.red.length) - 1);
+ priv->green[i] = i * 65535 / ((1 << priv->var.green.length) - 1);
+ priv->blue[i] = i * 65535 / ((1 << priv->var.blue.length) - 1);
+ }
+ cmap.start = 0;
+ cmap.len = i;
+ cmap.red = &priv->red[0];
+ cmap.green = &priv->green[0];
+ cmap.blue = &priv->blue[0];
+ cmap.transp = 0;
+ ioctl (priv->fd, FBIOPUTCMAP, &cmap);
+ }
+ return TRUE;
+}
+
+Bool
+epsonDPMS (ScreenPtr pScreen, int mode)
+{
+ KdScreenPriv(pScreen);
+ EpsonPriv *priv = pScreenPriv->card->driver;
+ static int oldmode = -1;
+
+ if (mode == oldmode)
+ return TRUE;
+#ifdef FBIOPUT_POWERMODE
+ if (ioctl (priv->fd, FBIOPUT_POWERMODE, &mode) >= 0) {
+ oldmode = mode;
+ return TRUE;
+ }
+#endif
+#ifdef FBIOBLANK
+ if (ioctl (priv->fd, FBIOBLANK, mode ? mode + 1 : 0) >= 0) {
+ oldmode = mode;
+ return TRUE;
+ }
+#endif
+ return FALSE;
+}
+
+void
+epsonDisable (ScreenPtr pScreen)
+{
+}
+
+void
+epsonRestore (KdCardInfo *card)
+{
+}
+
+void
+epsonScreenFini (KdScreenInfo *screen)
+{
+}
+
+void
+epsonCardFini (KdCardInfo *card)
+{
+ EpsonPriv *priv = card->driver;
+
+ munmap (priv->fb_base, priv->fix.smem_len);
+ close (priv->fd);
+ xfree (priv);
+}
+
+void
+epsonGetColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs)
+{
+ KdScreenPriv(pScreen);
+ EpsonPriv *priv = pScreenPriv->card->driver;
+ struct fb_cmap cmap;
+ int p;
+ int k;
+ int min, max;
+
+ min = 256;
+ max = 0;
+ for (k = 0; k < n; k++) {
+ if (pdefs[k].pixel < min)
+ min = pdefs[k].pixel;
+ if (pdefs[k].pixel > max)
+ max = pdefs[k].pixel;
+ }
+ cmap.start = min;
+ cmap.len = max - min + 1;
+ cmap.red = &priv->red[min];
+ cmap.green = &priv->green[min];;
+ cmap.blue = &priv->blue[min];
+ cmap.transp = 0;
+ k = ioctl (priv->fd, FBIOGETCMAP, &cmap);
+ if (k < 0) {
+ perror ("can't get colormap");
+ return;
+ }
+ while (n--) {
+ p = pdefs->pixel;
+ pdefs->red = priv->red[p];
+ pdefs->green = priv->green[p];
+ pdefs->blue = priv->blue[p];
+ pdefs++;
+ }
+}
+
+void
+epsonPutColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs)
+{
+ KdScreenPriv(pScreen);
+ EpsonPriv *priv = pScreenPriv->card->driver;
+ struct fb_cmap cmap;
+ int p;
+ int min, max;
+
+ min = 256;
+ max = 0;
+ while (n--) {
+ p = pdefs->pixel;
+ priv->red[p] = pdefs->red;
+ priv->green[p] = pdefs->green;
+ priv->blue[p] = pdefs->blue;
+ if (p < min)
+ min = p;
+ if (p > max)
+ max = p;
+ pdefs++;
+ }
+ cmap.start = min;
+ cmap.len = max - min + 1;
+ cmap.red = &priv->red[min];
+ cmap.green = &priv->green[min];
+ cmap.blue = &priv->blue[min];
+ cmap.transp = 0;
+ ioctl (priv->fd, FBIOPUTCMAP, &cmap);
+}
+
+
+
+KdCardFuncs epsonFuncs = {
+ epsonCardInit, /* cardinit */
+ epsonScreenInit, /* scrinit */
+ epsonInitScreen, /* initScreen */
+ epsonFinishInitScreen,
+ epsonCreateResources,
+ epsonPreserve, /* preserve */
+ epsonEnable, /* enable */
+ epsonDPMS, /* dpms */
+ epsonDisable, /* disable */
+ epsonRestore, /* restore */
+ epsonScreenFini, /* scrfini */
+ epsonCardFini, /* cardfini */
+
+ 0, /* initCursor */
+ 0, /* enableCursor */
+ 0, /* disableCursor */
+ 0, /* finiCursor */
+ 0, /* recolorCursor */
+
+ /*
+ * History:
+ * 28-Jan-04 C.Stylianou NBL: Added the following for h/w accel.
+ *
+ */
+
+ epsonDrawInit, /* initAccel */
+ epsonDrawEnable, /* enableAccel */
+ epsonDrawDisable, /* disableAccel */
+ epsonDrawFini, /* finiAccel */
+
+ epsonGetColors, /* getColors */
+ epsonPutColors, /* putColors */
+};