diff options
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | src/Makefile.am | 12 | ||||
-rw-r--r-- | src/glamo-display.c | 2 | ||||
-rw-r--r-- | src/glamo-dri2.c | 356 | ||||
-rw-r--r-- | src/glamo-dri2.h | 26 | ||||
-rw-r--r-- | src/glamo-driver.c | 108 | ||||
-rw-r--r-- | src/glamo-drm.c | 107 | ||||
-rw-r--r-- | src/glamo-drm.h | 38 | ||||
-rw-r--r-- | src/glamo-kms-crtc.c | 245 | ||||
-rw-r--r-- | src/glamo-kms-crtc.h | 25 | ||||
-rw-r--r-- | src/glamo-kms-driver.c | 478 | ||||
-rw-r--r-- | src/glamo-kms-driver.h | 34 | ||||
-rw-r--r-- | src/glamo-kms-exa.c | 594 | ||||
-rw-r--r-- | src/glamo-kms-exa.h | 34 | ||||
-rw-r--r-- | src/glamo-kms-output.c | 304 | ||||
-rw-r--r-- | src/glamo-kms-output.h | 25 | ||||
-rw-r--r-- | src/glamo.h | 28 |
17 files changed, 2393 insertions, 27 deletions
diff --git a/configure.ac b/configure.ac index 628537c..d9b08a9 100644 --- a/configure.ac +++ b/configure.ac @@ -70,7 +70,7 @@ XORG_DRIVER_CHECK_EXT(XV, videoproto) # Checks for pkg-config packages PKG_CHECK_MODULES(XORG, [xorg-server >= 1.0.99.901 xproto fontsproto $REQUIRED_MODULES]) -sdkdir=$(pkg-config --variable=sdkdir xorg-server) +sdkdir=$($PKG_CONFIG --variable=sdkdir xorg-server) if test "x$JBT6K74_SET_STATE" = xyes; then AC_DEFINE(JBT6K74_SET_STATE, 1, [Set jbt6k74 state when changing resolution]) @@ -82,6 +82,8 @@ if test "x$HAVE_ENGINE_IOCTLS" = xyes; then fi # Checks for libraries. +PKG_CHECK_MODULES(DRI, [libdrm xf86driproto]) +CFLAGS="$XORG_CFLAGS $DRI_CFLAGS" # Checks for header files. AC_HEADER_STDC diff --git a/src/Makefile.am b/src/Makefile.am index d229347..a1e8d0a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,9 +23,9 @@ # -avoid-version prevents gratuitous .0.0.0 version numbers on the end # _ladir passes a dummy rpath to libtool so the thing will actually link # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. -AM_CFLAGS = @XORG_CFLAGS@ -pedantic -Wall -Werror -std=gnu99 +AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -pedantic -Wall -Werror -std=gnu99 glamo_drv_la_LTLIBRARIES = glamo_drv.la -glamo_drv_la_LDFLAGS = -module -avoid-version +glamo_drv_la_LDFLAGS = -module -avoid-version -ldrm -ldrm_glamo glamo_drv_ladir = @moduledir@/drivers glamo_drv_la_SOURCES = \ @@ -35,4 +35,10 @@ glamo_drv_la_SOURCES = \ glamo-draw.c \ glamo-display.c \ glamo-output.c \ - glamo-engine.c + glamo-engine.c \ + glamo-kms-driver.c \ + glamo-kms-crtc.c \ + glamo-kms-output.c \ + glamo-dri2.c \ + glamo-kms-exa.c \ + glamo-drm.c diff --git a/src/glamo-display.c b/src/glamo-display.c index 4562546..fede315 100644 --- a/src/glamo-display.c +++ b/src/glamo-display.c @@ -38,7 +38,7 @@ #include <unistd.h> #define DPMS_SERVER -#include <X11/extensions/dpms.h> +#include <X11/extensions/dpmsconst.h> #include "glamo.h" #include "glamo-regs.h" diff --git a/src/glamo-dri2.c b/src/glamo-dri2.c new file mode 100644 index 0000000..6b743f4 --- /dev/null +++ b/src/glamo-dri2.c @@ -0,0 +1,356 @@ +/* + * DRI for the SMedia Glamo3362 X.org Driver + * + * Modified: 2009 by Thomas White <taw@bitwiz.org.uk> + * + * Based on dri2.c from xf86-video-modesetting, to which the following + * notice applies: + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Author: Alan Hourihane <alanh@tungstengraphics.com> + * + * + * Also based partially on xf86-video-ati, to which the following + * notice applies: + * + * Copyright 2008 Kristian Høgsberg + * Copyright 2008 Jérôme Glisse + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation on the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR + * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <xf86.h> +#include <xf86_OSproc.h> +#include <xf86drm.h> +#include <dri2.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <glamo_bo_gem.h> + +#include "glamo.h" +#include "glamo-dri2.h" +#include "glamo-kms-exa.h" + + +struct glamo_dri2_buffer_priv { + PixmapPtr pixmap; + unsigned int attachment; +}; + + +#if DRI2INFOREC_VERSION >= 3 + +static DRI2BufferPtr glamoCreateBuffer(DrawablePtr drawable, + unsigned int attachment, + unsigned int format) +{ + ScreenPtr pScreen = drawable->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + DRI2BufferPtr buffer; + struct glamo_dri2_buffer_priv *private; + PixmapPtr pixmap; + struct glamo_exa_pixmap_priv *driver_priv; + int r; + + buffer = xcalloc(1, sizeof(*buffer)); + if (buffer == NULL) { + return NULL; + } + private = xcalloc(1, sizeof(*private)); + if (private == NULL) { + xfree(buffer); + return NULL; + } + + if ( attachment == DRI2BufferFrontLeft ) { + if ( drawable->type == DRAWABLE_PIXMAP ) { + pixmap = (PixmapPtr)drawable; + } else { + pixmap = pScreen->GetWindowPixmap((WindowPtr)drawable); + } + pixmap->refcnt++; + } else { + pixmap = pScreen->CreatePixmap(pScreen, + drawable->width, + drawable->height, + (format != 0)?format:drawable->depth, + 0); + } + exaMoveInPixmap(pixmap); + driver_priv = exaGetPixmapDriverPrivate(pixmap); + if ( !driver_priv ) { + xfree(buffer); + xfree(private); + return NULL; + } + r = glamo_gem_name_buffer(driver_priv->bo, &buffer->name); + if (r) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Couldn't name buffer: %d %s\n", + r, strerror(r)); + xfree(buffer); + xfree(private); + return NULL; + } + buffer->attachment = attachment; + buffer->pitch = pixmap->devKind; + buffer->cpp = pixmap->drawable.bitsPerPixel / 8; + buffer->driverPrivate = private; + buffer->format = format; + buffer->flags = 0; + private->pixmap = pixmap; + private->attachment = attachment; + + return buffer; +} + +#else + +static DRI2BufferPtr glamoCreateBuffers(DrawablePtr drawable, + unsigned int *attachments, int count) +{ + ScreenPtr pScreen = drawable->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + int i; + DRI2BufferPtr buffers; + struct glamo_dri2_buffer_priv *privates; + + buffers = xcalloc(count, sizeof *buffers); + if ( buffers == NULL ) return NULL; + privates = xcalloc(count, sizeof *privates); + if ( privates == NULL ) { + xfree(buffers); + return NULL; + } + + /* For each attachment */ + for ( i=0; i<count; i++ ) { + + PixmapPtr pixmap; + struct glamo_exa_pixmap_priv *driver_priv; + int r; + + if ( attachments[i] == DRI2BufferFrontLeft ) { + if ( drawable->type == DRAWABLE_PIXMAP ) { + pixmap = (PixmapPtr)drawable; + } else { + pixmap = pScreen->GetWindowPixmap( + (WindowPtr)drawable); + } + pixmap->refcnt++; + } else { + pixmap = pScreen->CreatePixmap(pScreen, + drawable->width, + drawable->height, + drawable->depth, + 0); + } + exaMoveInPixmap(pixmap); + driver_priv = exaGetPixmapDriverPrivate(pixmap); + if ( !driver_priv ) { + xfree(buffers); + xfree(privates); + return NULL; + } + r = glamo_gem_name_buffer(driver_priv->bo, &buffers[i].name); + if (r) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Couldn't name buffer: %d %s\n", + r, strerror(r)); + xfree(buffers); + xfree(privates); + return NULL; + } + buffers[i].attachment = attachments[i]; + buffers[i].pitch = pixmap->devKind; + buffers[i].cpp = pixmap->drawable.bitsPerPixel / 8; + buffers[i].driverPrivate = &privates[i]; + buffers[i].format = drawable->depth; + buffers[i].flags = 0; + privates[i].pixmap = pixmap; + privates[i].attachment = attachments[i]; + + } + + return buffers; +} + +#endif + +#if DRI2INFOREC_VERSION >= 3 + +static void glamoDestroyBuffer(DrawablePtr pDraw, + DRI2BufferPtr buffer) +{ + ScreenPtr pScreen = pDraw->pScreen; + struct glamo_dri2_buffer_priv *private; + + private = buffer->driverPrivate; + pScreen->DestroyPixmap(private->pixmap); + + if ( buffer ) { + xfree(buffer->driverPrivate); + } +} + +#else + +static void glamoDestroyBuffers(DrawablePtr pDraw, + DRI2BufferPtr buffers, int count) +{ + ScreenPtr pScreen = pDraw->pScreen; + int i; + + for ( i=0; i<count; i++ ) { + GlamoDRI2BufferPrivatePtr private; + private = buffers[i].driverPrivate; + pScreen->DestroyPixmap(private->pixmap); + } + + if ( buffers ) { + xfree(buffers[0].driverPrivate); + xfree(buffers); + } +} + +#endif + + +static void glamoCopyRegion(DrawablePtr drawable, RegionPtr region, + DRI2BufferPtr dst_buffer, DRI2BufferPtr src_buffer) +{ + struct glamo_dri2_buffer_priv *src_private; + struct glamo_dri2_buffer_priv *dst_private; + ScreenPtr pScreen = drawable->pScreen; + PixmapPtr src_pixmap; + PixmapPtr dst_pixmap; + RegionPtr copy_clip; + GCPtr gc; + + src_private = src_buffer->driverPrivate; + dst_private = dst_buffer->driverPrivate; + src_pixmap = src_private->pixmap; + dst_pixmap = dst_private->pixmap; + + if (src_private->attachment == DRI2BufferFrontLeft) { + src_pixmap = (PixmapPtr)drawable; + } + if (dst_private->attachment == DRI2BufferFrontLeft) { + dst_pixmap = (PixmapPtr)drawable; + } + + gc = GetScratchGC(drawable->depth, pScreen); + copy_clip = REGION_CREATE(pScreen, NULL, 0); + REGION_COPY(pScreen, copy_clip, region); + gc->funcs->ChangeClip(gc, CT_REGION, copy_clip, 0); + ValidateGC(&dst_pixmap->drawable, gc); + gc->ops->CopyArea(&src_pixmap->drawable, &dst_pixmap->drawable, gc, + 0, 0, drawable->width, drawable->height, 0, 0); + FreeScratchGC(gc); +} + + +void driScreenInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + GlamoPtr pGlamo = GlamoPTR(pScrn); + DRI2InfoRec dri2info; + char *p; + struct stat sbuf; + dev_t d; + int i; + + fstat(pGlamo->drm_fd, &sbuf); + d = sbuf.st_rdev; + p = pGlamo->drm_devname; + for ( i=0; i<DRM_MAX_MINOR; i++ ) { + sprintf(p, DRM_DEV_NAME, DRM_DIR_NAME, i); + if ( stat(p, &sbuf) == 0 && sbuf.st_rdev == d ) break; + } + if ( i == DRM_MAX_MINOR ) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "[glamo-dri] Failed to find name of DRM device\n"); + return; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[glamo-dri] Name of DRM device is '%s'\n", p); + + dri2info.version = DRI2INFOREC_VERSION; + dri2info.fd = pGlamo->drm_fd; + dri2info.deviceName = p; + dri2info.driverName = "glamo"; + +#if DRI2INFOREC_VERSION >= 3 + dri2info.CreateBuffer = glamoCreateBuffer; + dri2info.DestroyBuffer = glamoDestroyBuffer; +#else + dri2info.CreateBuffers = glamoCreateBuffers; + dri2info.DestroyBuffers = glamoDestroyBuffers; +#endif + dri2info.CopyRegion = glamoCopyRegion; + + if ( !DRI2ScreenInit(pScreen, &dri2info) ) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[glamo-dri] DRI2 initialisation failed\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[glamo-dri] DRI2 initialisation succeeded\n"); + } +} + + +void driCloseScreen(ScreenPtr pScreen) +{ + DRI2CloseScreen(pScreen); +} diff --git a/src/glamo-dri2.h b/src/glamo-dri2.h new file mode 100644 index 0000000..5834410 --- /dev/null +++ b/src/glamo-dri2.h @@ -0,0 +1,26 @@ +/* + * DRI for the SMedia Glamo3362 X.org Driver + * + * Copyright 2009 Thomas White <taw@bitwiz.org.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include "xf86.h" + +extern void driScreenInit(ScreenPtr pScreen); +extern void driCloseScreen(ScreenPtr pScreen); diff --git a/src/glamo-driver.c b/src/glamo-driver.c index 4dd9a9c..17b661e 100644 --- a/src/glamo-driver.c +++ b/src/glamo-driver.c @@ -34,6 +34,7 @@ #include "glamo.h" #include "glamo-regs.h" +#include "glamo-kms-driver.h" #include <fcntl.h> #include <unistd.h> @@ -179,7 +180,7 @@ GlamoSetup(pointer module, pointer opts, int *errmaj, int *errmin) #endif /* XFree86LOADER */ -static Bool +Bool GlamoGetRec(ScrnInfoPtr pScrn) { if (pScrn->driverPrivate != NULL) @@ -189,7 +190,7 @@ GlamoGetRec(ScrnInfoPtr pScrn) return TRUE; } -static void +void GlamoFreeRec(ScrnInfoPtr pScrn) { if (pScrn->driverPrivate == NULL) @@ -274,39 +275,31 @@ GlamoIdentify(int flags) } static Bool -GlamoProbe(DriverPtr drv, int flags) +GlamoFbdevProbe(DriverPtr drv, GDevPtr *devSections, int numDevSections) { - int i; - ScrnInfoPtr pScrn; - GDevPtr *devSections; - int numDevSections; char *dev; Bool foundScreen = FALSE; + int i; + ScrnInfoPtr pScrn; - TRACE("probe start"); - - /* For now, just bail out for PROBE_DETECT. */ - if (flags & PROBE_DETECT) - return FALSE; - - if ((numDevSections = xf86MatchDevice(GLAMO_DRIVER_NAME, &devSections)) <= 0) - return FALSE; - - if (!xf86LoadDrvSubModule(drv, "fbdevhw")) - return FALSE; + if (!xf86LoadDrvSubModule(drv, "fbdevhw")) return FALSE; for (i = 0; i < numDevSections; i++) { + dev = xf86FindOptionValue(devSections[i]->options, "Device"); if (fbdevHWProbe(NULL, dev, NULL)) { int entity; pScrn = NULL; entity = xf86ClaimFbSlot(drv, 0, devSections[i], TRUE); - pScrn = xf86ConfigFbEntity(pScrn,0,entity, - NULL, NULL, NULL, NULL); + pScrn = xf86ConfigFbEntity(pScrn,0,entity, NULL, NULL, + NULL, NULL); if (pScrn) { + foundScreen = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Not using KMS\n"); pScrn->driverVersion = GLAMO_VERSION; pScrn->driverName = GLAMO_DRIVER_NAME; @@ -321,10 +314,82 @@ GlamoProbe(DriverPtr drv, int flags) pScrn->ValidMode = fbdevHWValidModeWeak(); xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "using %s\n", dev ? dev : "default device"); + "using %s\n", + dev ? dev : "default device\n"); + } } + } + + return foundScreen; +} + +static Bool +GlamoKMSProbe(DriverPtr drv, GDevPtr *devSections, int numDevSections) +{ + ScrnInfoPtr pScrn = NULL; + int entity; + Bool foundScreen = FALSE; + int i; + + for ( i = 0; i < numDevSections; i++ ) { + + /* This is a little dodgy. We aren't really using fbdevhw + * (/dev/fb0 is irrelevant), but we need a device entity to make + * the later stages of initialisation work. xf86ClaimFbSlot() + * does the minimum required to make this work, so we use it + * despite the above. */ + entity = xf86ClaimFbSlot(drv, 0, devSections[i], TRUE); + pScrn = xf86ConfigFbEntity(pScrn, 0, entity, NULL, NULL, NULL, + NULL); + + if ( pScrn ) { + + foundScreen = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using KMS!\n"); + + /* Plug in KMS functions */ + pScrn->driverVersion = GLAMO_VERSION; + pScrn->driverName = GLAMO_DRIVER_NAME; + pScrn->name = GLAMO_NAME; + pScrn->PreInit = GlamoKMSPreInit; + pScrn->ScreenInit = GlamoKMSScreenInit; + pScrn->SwitchMode = GlamoKMSSwitchMode; + pScrn->AdjustFrame = GlamoKMSAdjustFrame; + pScrn->EnterVT = GlamoKMSEnterVT; + pScrn->LeaveVT = GlamoKMSLeaveVT; + pScrn->ValidMode = GlamoKMSValidMode; + + } + } + + return foundScreen; +} + +static Bool +GlamoProbe(DriverPtr drv, int flags) +{ + GDevPtr *devSections; + int numDevSections; + Bool foundScreen = FALSE; + + TRACE("probe start"); + + /* For now, just bail out for PROBE_DETECT. */ + if (flags & PROBE_DETECT) + return FALSE; + + numDevSections = xf86MatchDevice(GLAMO_DRIVER_NAME, &devSections); + if (numDevSections <= 0) return FALSE; + + /* Is today a good day to use KMS? */ + if ( GlamoKernelModesettingAvailable() ) { + foundScreen = GlamoKMSProbe(drv, devSections, numDevSections); + } else { + foundScreen = GlamoFbdevProbe(drv, devSections, numDevSections); + } + xfree(devSections); TRACE("probe done"); return foundScreen; @@ -799,4 +864,3 @@ GlamoLoadColormap(ScrnInfoPtr pScrn, int numColors, int *indices, (colors[indices[i]].blue >> 3); } } - diff --git a/src/glamo-drm.c b/src/glamo-drm.c new file mode 100644 index 0000000..aac93bb --- /dev/null +++ b/src/glamo-drm.c @@ -0,0 +1,107 @@ +/* + * DRI for the SMedia Glamo3362 X.org Driver + * + * Copyright 2009 Thomas White <taw@bitwiz.org.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <xf86.h> +#include <xf86drm.h> +#include <glamo_drm.h> +#include <glamo_bo.h> + +#include "glamo.h" + + +/* Submit the prepared command sequence to the kernel */ +void GlamoDRMDispatch(GlamoPtr pGlamo) +{ + drm_glamo_cmd_buffer_t cmdbuf; + int r; + + cmdbuf.buf = (char *)pGlamo->cmdq_drm; + cmdbuf.bufsz = pGlamo->cmdq_drm_used * 2; /* -> bytes */ + cmdbuf.nobjs = pGlamo->cmdq_obj_used; + cmdbuf.objs = pGlamo->cmdq_objs; + cmdbuf.obj_pos = pGlamo->cmdq_obj_pos; + + r = drmCommandWrite(pGlamo->drm_fd, DRM_GLAMO_CMDBUF, + &cmdbuf, sizeof(cmdbuf)); + if ( r != 0 ) { + xf86DrvMsg(pGlamo->pScreen->myNum, X_ERROR, + "DRM_GLAMO_CMDBUF failed\n"); + } + + /* Reset counts to zero for the next sequence */ + pGlamo->cmdq_obj_used = 0; + pGlamo->cmdq_drm_used = 0; +} + + +void GlamoDRMAddCommand(GlamoPtr pGlamo, uint16_t reg, uint16_t val) +{ + if ( pGlamo->cmdq_drm_used == pGlamo->cmdq_drm_size ) { + xf86DrvMsg(pGlamo->pScreen->myNum, X_INFO, + "Forced command cache flush.\n"); + GlamoDRMDispatch(pGlamo); + } + + /* Record command */ + pGlamo->cmdq_drm[pGlamo->cmdq_drm_used++] = reg; + pGlamo->cmdq_drm[pGlamo->cmdq_drm_used++] = val; +} + + +void GlamoDRMAddCommandBO(GlamoPtr pGlamo, uint16_t reg, struct glamo_bo *bo) +{ + if ( pGlamo->cmdq_drm_used == pGlamo->cmdq_drm_size ) { + xf86DrvMsg(pGlamo->pScreen->myNum, X_INFO, + "Forced command cache flush.\n"); + GlamoDRMDispatch(pGlamo); + } + + /* Record object position */ + pGlamo->cmdq_objs[pGlamo->cmdq_obj_used] = bo->handle; + /* -> bytes */ + pGlamo->cmdq_obj_pos[pGlamo->cmdq_obj_used] = pGlamo->cmdq_drm_used * 2; + pGlamo->cmdq_obj_used++; + + /* Record command */ + pGlamo->cmdq_drm[pGlamo->cmdq_drm_used++] = reg; + pGlamo->cmdq_drm[pGlamo->cmdq_drm_used++] = 0x0000; + pGlamo->cmdq_drm[pGlamo->cmdq_drm_used++] = reg+2; + pGlamo->cmdq_drm[pGlamo->cmdq_drm_used++] = 0x0000; + + pGlamo->last_buffer_object = bo; +} + + +void GlamoDRMInit(GlamoPtr pGlamo) +{ + pGlamo->cmdq_objs = malloc(1024); + pGlamo->cmdq_obj_pos = malloc(1024); + pGlamo->cmdq_obj_used = 0; + pGlamo->cmdq_drm_used = 0; + pGlamo->cmdq_drm_size = 4 * 1024; + pGlamo->cmdq_drm = malloc(pGlamo->cmdq_drm_size); +} diff --git a/src/glamo-drm.h b/src/glamo-drm.h new file mode 100644 index 0000000..6e0693f --- /dev/null +++ b/src/glamo-drm.h @@ -0,0 +1,38 @@ +/* + * DRI for the SMedia Glamo3362 X.org Driver + * + * Copyright 2009 Thomas White <taw@bitwiz.org.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + + +#ifndef _GLAMO_DRM_H +#define _GLAMO_DRM_H + +#include <stdint.h> +#include <glamo_bo.h> + +#include "glamo.h" + +extern void GlamoDRMInit(GlamoPtr pGlamo); +extern void GlamoDRMDispatch(GlamoPtr pGlamo); +extern void GlamoDRMAddCommand(GlamoPtr pGlamo, uint16_t reg, uint16_t val); +extern void GlamoDRMAddCommandBO(GlamoPtr pGlamo, uint16_t reg, + struct glamo_bo *bo); + +#endif /* _GLAMO_DRM_H */ diff --git a/src/glamo-kms-crtc.c b/src/glamo-kms-crtc.c new file mode 100644 index 0000000..fdf0e9f --- /dev/null +++ b/src/glamo-kms-crtc.c @@ -0,0 +1,245 @@ +/* + * KMS Support for the SMedia Glamo3362 X.org Driver + * + * Modified: 2009 by Thomas White <taw@bitwiz.org.uk> + * + * Based on crtc.c from xf86-video-modesetting, to which the following + * notice applies: + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Author: Alan Hourihane <alanh@tungstengraphics.com> + * + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <unistd.h> +#include <string.h> +#include <assert.h> +#include <stdlib.h> +#include <math.h> +#include <stdint.h> +#include <errno.h> + +#include <xf86.h> +#include <xf86i2c.h> +#include <xf86Crtc.h> +#include <xf86drm.h> +#include <drm.h> +#include <xf86drmMode.h> +#include <xf86Modes.h> +#define DPMS_SERVER +#include <X11/extensions/dpmsconst.h> + +#include "glamo.h" +#include "glamo-kms-crtc.h" + + +struct crtc_private +{ + drmModeCrtcPtr drm_crtc; +}; + + +static void crtc_dpms(xf86CrtcPtr crtc, int mode) +{ + switch (mode) { + case DPMSModeOn: + case DPMSModeStandby: + case DPMSModeSuspend: + break; + case DPMSModeOff: + break; + } +} + + +static Bool crtc_lock(xf86CrtcPtr crtc) +{ + return FALSE; +} + + +static void crtc_unlock(xf86CrtcPtr crtc) +{ +} + + +static void crtc_prepare(xf86CrtcPtr crtc) +{ +} + + +static void crtc_commit(xf86CrtcPtr crtc) +{ +} + + +static Bool crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + return TRUE; +} + + +static void crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, + DisplayModePtr adjusted_mode, int x, int y) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn); + GlamoPtr pGlamo = GlamoPTR(crtc->scrn); + xf86OutputPtr output = config->output[config->compat_output]; + drmModeConnectorPtr drm_connector = output->driver_private; + struct crtc_private *crtcp = crtc->driver_private; + drmModeCrtcPtr drm_crtc = crtcp->drm_crtc; + drmModeModeInfo drm_mode; + + drm_mode.clock = mode->Clock; + drm_mode.hdisplay = mode->HDisplay; + drm_mode.hsync_start = mode->HSyncStart; + drm_mode.hsync_end = mode->HSyncEnd; + drm_mode.htotal = mode->HTotal; + drm_mode.vdisplay = mode->VDisplay; + drm_mode.vsync_start = mode->VSyncStart; + drm_mode.vsync_end = mode->VSyncEnd; + drm_mode.vtotal = mode->VTotal; + drm_mode.flags = mode->Flags; + drm_mode.hskew = mode->HSkew; + drm_mode.vscan = mode->VScan; + drm_mode.vrefresh = mode->VRefresh; + if ( !mode->name ) + xf86SetModeDefaultName(mode); + strncpy(drm_mode.name, mode->name, DRM_DISPLAY_MODE_LEN); + + drmModeSetCrtc(pGlamo->drm_fd, drm_crtc->crtc_id, pGlamo->fb_id, x, y, + &drm_connector->connector_id, 1, &drm_mode); +} + + +void crtc_load_lut(xf86CrtcPtr crtc) +{ +} + + +static void crtc_gamma_set(xf86CrtcPtr crtc, + CARD16 *red, CARD16 *green, CARD16 *blue, + int size) +{ +} + + +static void *crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) +{ + return NULL; +} + + +static PixmapPtr crtc_shadow_create(xf86CrtcPtr crtc, void *data, + int width, int height) +{ + return NULL; +} + + +static void crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, + void *data) +{ +} + + +static void crtc_destroy(xf86CrtcPtr crtc) +{ + struct crtc_private *crtcp = crtc->driver_private; + + drmModeFreeCrtc(crtcp->drm_crtc); + xfree(crtcp); +} + + +static const xf86CrtcFuncsRec crtc_funcs = { + .dpms = crtc_dpms, + .save = NULL, + .restore = NULL, + .lock = crtc_lock, + .unlock = crtc_unlock, + .mode_fixup = crtc_mode_fixup, + .prepare = crtc_prepare, + .mode_set = crtc_mode_set, + .commit = crtc_commit, + .gamma_set = crtc_gamma_set, + .shadow_create = crtc_shadow_create, + .shadow_allocate = crtc_shadow_allocate, + .shadow_destroy = crtc_shadow_destroy, + .set_cursor_position = NULL, + .show_cursor = NULL, + .hide_cursor = NULL, + .load_cursor_image = NULL, /* lets convert to argb only */ + .set_cursor_colors = NULL, /* using argb only */ + .load_cursor_argb = NULL, + .destroy = crtc_destroy, +}; + + +void crtc_init(ScrnInfoPtr pScrn) +{ + xf86CrtcPtr crtc; + GlamoPtr pGlamo = GlamoPTR(pScrn); + drmModeResPtr res; + drmModeCrtcPtr drm_crtc = NULL; + struct crtc_private *crtcp; + int c; + + res = drmModeGetResources(pGlamo->drm_fd); + if (res == 0) { + ErrorF("Failed drmModeGetResources %d\n", errno); + return; + } + + for (c = 0; c < res->count_crtcs; c++) { + drm_crtc = drmModeGetCrtc(pGlamo->drm_fd, res->crtcs[c]); + if (!drm_crtc) + continue; + + crtc = xf86CrtcCreate(pScrn, &crtc_funcs); + if (crtc == NULL) + goto out; + + crtcp = xcalloc(1, sizeof(struct crtc_private)); + if (!crtcp) { + xf86CrtcDestroy(crtc); + goto out; + } + + crtcp->drm_crtc = drm_crtc; + + crtc->driver_private = crtcp; + } + +out: + drmModeFreeResources(res); +} diff --git a/src/glamo-kms-crtc.h b/src/glamo-kms-crtc.h new file mode 100644 index 0000000..1860b2d --- /dev/null +++ b/src/glamo-kms-crtc.h @@ -0,0 +1,25 @@ +/* + * KMS CRTC handling for the SMedia Glamo3362 X.org Driver + * + * Copyright 2009 Thomas White <taw@bitwiz.org.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include "xf86.h" + +extern void crtc_init(ScrnInfoPtr pScrn); diff --git a/src/glamo-kms-driver.c b/src/glamo-kms-driver.c new file mode 100644 index 0000000..34c7baf --- /dev/null +++ b/src/glamo-kms-driver.c @@ -0,0 +1,478 @@ +/* + * KMS Support for the SMedia Glamo3362 X.org Driver + * + * Copyright 2009 Thomas White <taw@bitwiz.org.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * The KMS parts of this driver are based on xf86-video-modesetting, to + * which the following notice applies: + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Author: Alan Hourihane <alanh@tungstengraphics.com> + * + */ + + +#include <sys/types.h> +#include <dirent.h> +#include <stdint.h> + +#include <xorg-server.h> +#include <drm.h> +#include <xf86drm.h> +#include <xf86drmMode.h> + +#include "xf86.h" +#include "xf86Crtc.h" +#include "xf86str.h" +#include "xf86drm.h" +#include "micmap.h" + +#include "glamo.h" +#include "glamo-kms-driver.h" +#include "glamo-kms-exa.h" +#include "glamo-dri2.h" +#include "glamo-kms-crtc.h" +#include "glamo-kms-output.h" + + +/* Return TRUE if KMS can be used */ +Bool GlamoKernelModesettingAvailable() +{ + DIR *dir; + struct dirent *ent; + + dir = opendir("/sys/bus/platform/devices/glamo-fb.0/"); + if ( !dir ) return FALSE; + + do { + + ent = readdir(dir); + if ( !ent ) return FALSE; + + if ( strncmp(ent->d_name, "drm:controlD", 12) == 0 ) { + closedir(dir); + return TRUE; + } + + } while ( ent ); + + closedir(dir); + return FALSE; +} + + +void GlamoKMSAdjustFrame(int scrnIndex, int x, int y, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr output = config->output[config->compat_output]; + xf86CrtcPtr crtc = output->crtc; + + if (crtc && crtc->enabled) { + crtc->funcs->mode_set(crtc, + pScrn->currentMode, + pScrn->currentMode, + x, y); + crtc->x = output->initial_x + x; + crtc->y = output->initial_y + y; + } +} + + +static Bool CreateFrontBuffer(ScrnInfoPtr pScrn) +{ + GlamoPtr pGlamo = GlamoPTR(pScrn); + ScreenPtr pScreen = pScrn->pScreen; + PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen); + unsigned int flags; + + GlamoKMSExaMakeFullyFledged(rootPixmap, + pScrn->virtualX, pScrn->virtualY, + pScrn->depth, pScrn->bitsPerPixel, + pScrn->displayWidth*pScrn->bitsPerPixel/8); + + drmModeAddFB(pGlamo->drm_fd, + pScrn->virtualX, + pScrn->virtualY, + pScrn->depth, + pScrn->bitsPerPixel, + pScrn->displayWidth * pScrn->bitsPerPixel / 8, + driGetPixmapHandle(rootPixmap, &flags), &pGlamo->fb_id); + + pScrn->frameX0 = 0; + pScrn->frameY0 = 0; + GlamoKMSAdjustFrame(pScrn->scrnIndex, + pScrn->frameX0, pScrn->frameY0, + 0); + + return TRUE; +} + + +static Bool crtc_resize(ScrnInfoPtr pScrn, int width, int height) +{ + GlamoPtr pGlamo = GlamoPTR(pScrn); + + if ( (width == pScrn->virtualX) && (height == pScrn->virtualY) ) + return TRUE; /* Nothing to do */ + + ErrorF("RESIZING TO %dx%d\n", width, height); + + pScrn->virtualX = width; + pScrn->virtualY = height; + + /* HW dependent - FIXME */ + pScrn->displayWidth = pScrn->virtualX; + + drmModeRmFB(pGlamo->drm_fd, pGlamo->fb_id); + + /* now create new frontbuffer */ + return CreateFrontBuffer(pScrn); +} + + +static const xf86CrtcConfigFuncsRec crtc_config_funcs = { + crtc_resize +}; + + +Bool GlamoKMSPreInit(ScrnInfoPtr pScrn, int flags) +{ + xf86CrtcConfigPtr xf86_config; + GlamoPtr pGlamo; + rgb defaultWeight = { 0, 0, 0 }; + int max_width, max_height; + Gamma zeros = { 0.0, 0.0, 0.0 }; + + /* Can't do this yet */ + if ( flags & PROBE_DETECT ) { + ConfiguredMonitor = NULL; + return TRUE; + } + + /* Allocate driverPrivate */ + if ( !GlamoGetRec(pScrn) ) return FALSE; + pGlamo = GlamoPTR(pScrn); + pGlamo->SaveGeneration = -1; + + pScrn->displayWidth = 24; /* Nonsense default value */ + + /* Open DRM */ + pGlamo->drm_fd = drmOpen(NULL, "platform:glamo-fb"); + if ( pGlamo->drm_fd < 0 ) return FALSE; + + pScrn->monitor = pScrn->confScreen->monitor; + pScrn->progClock = TRUE; + pScrn->rgbBits = 8; + + /* Prefer 16bpp for everything */ + if ( !xf86SetDepthBpp(pScrn, 16, 16, 16, NoDepth24Support) ) { + return FALSE; + } + + /* We can only handle 16bpp */ + if ( pScrn->depth != 16 ) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Given depth (%d) is not supported by the driver\n", + pScrn->depth); + return FALSE; + } + xf86PrintDepthBpp(pScrn); + + if ( !xf86SetWeight(pScrn, defaultWeight, defaultWeight) ) return FALSE; + if ( !xf86SetDefaultVisual(pScrn, -1) ) return FALSE; + + /* Allocate an xf86CrtcConfig */ + xf86CrtcConfigInit(pScrn, &crtc_config_funcs); + xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + + max_width = 480; + max_height = 640; + xf86CrtcSetSizeRange(pScrn, 320, 200, max_width, max_height); + + crtc_init(pScrn); + output_init(pScrn); + + if ( !xf86InitialConfiguration(pScrn, TRUE) ) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); + return FALSE; + } + + if ( !xf86SetGamma(pScrn, zeros) ) { + return FALSE; + } + + if ( pScrn->modes == NULL ) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n"); + return FALSE; + } + + pScrn->currentMode = pScrn->modes; + + /* Set display resolution */ + xf86SetDpi(pScrn, 0, 0); + + /* Load the required sub modules */ + if (!xf86LoadSubModule(pScrn, "fb")) return FALSE; + xf86LoadSubModule(pScrn, "exa"); + xf86LoadSubModule(pScrn, "dri2"); + + return TRUE; +} + + +static Bool GlamoKMSCloseScreen(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + GlamoPtr pGlamo = GlamoPTR(pScrn); + + if ( pScrn->vtSema ) { + GlamoKMSLeaveVT(scrnIndex, 0); + } + driCloseScreen(pScreen); + + pScreen->CreateScreenResources = pGlamo->CreateScreenResources; + + if ( pGlamo->exa ) { + GlamoKMSExaClose(pScrn); + } + + drmClose(pGlamo->drm_fd); + pGlamo->drm_fd = -1; + + pScrn->vtSema = FALSE; + pScreen->CloseScreen = pGlamo->CloseScreen; + return (*pScreen->CloseScreen)(scrnIndex, pScreen); +} + + +static Bool GlamoKMSCreateScreenResources(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + GlamoPtr pGlamo = GlamoPTR(pScrn); + PixmapPtr rootPixmap; + Bool ret; + unsigned int flags; + + pScreen->CreateScreenResources = pGlamo->CreateScreenResources; + ret = pScreen->CreateScreenResources(pScreen); + pScreen->CreateScreenResources = GlamoKMSCreateScreenResources; + + rootPixmap = pScreen->GetScreenPixmap(pScreen); + + if (!GlamoKMSExaMakeFullyFledged(rootPixmap, -1, -1, -1, -1, -1)) + FatalError("Couldn't adjust screen pixmap\n"); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Adding FB: %i %i %i %i %i %i\n", + pGlamo->drm_fd, pScrn->virtualX, pScrn->virtualY, + pScrn->depth, pScrn->bitsPerPixel, + pScrn->displayWidth * pScrn->bitsPerPixel / 8); + + drmModeAddFB(pGlamo->drm_fd, + pScrn->virtualX, + pScrn->virtualY, + pScrn->depth, + pScrn->bitsPerPixel, + pScrn->displayWidth * pScrn->bitsPerPixel / 8, + driGetPixmapHandle(rootPixmap, &flags), &pGlamo->fb_id); + + GlamoKMSAdjustFrame(pScrn->scrnIndex, + pScrn->frameX0, pScrn->frameY0, + 0); + + return ret; +} + + +Bool GlamoKMSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, + char **argv) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + GlamoPtr pGlamo = GlamoPTR(pScrn); + VisualPtr visual; + + /* Deal with server regeneration */ + if ( pGlamo->drm_fd < 0 ) { + pGlamo->drm_fd = drmOpen(NULL, "platform:glamo-fb"); + if ( pGlamo->drm_fd < 0 ) return FALSE; + } + + pScrn->pScreen = pScreen; + pGlamo->pScreen = pScreen; + + /* HW dependent - FIXME */ + pScrn->displayWidth = pScrn->virtualX; + + miClearVisualTypes(); + + if ( !miSetVisualTypes(pScrn->depth, + miGetDefaultVisualMask(pScrn->depth), + pScrn->rgbBits, pScrn->defaultVisual) ) { + return FALSE; + } + + if ( !miSetPixmapDepths() ) return FALSE; + + pScrn->memPhysBase = 0; + pScrn->fbOffset = 0; + + if ( !fbScreenInit(pScreen, NULL, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth, pScrn->bitsPerPixel) ) { + return FALSE; + } + + if (pScrn->bitsPerPixel > 8) { + /* Fixup RGB ordering */ + visual = pScreen->visuals + pScreen->numVisuals; + while (--visual >= pScreen->visuals) { + if ((visual->class | DynamicClass) == DirectColor) { + visual->offsetRed = pScrn->offset.red; + visual->offsetGreen = pScrn->offset.green; + visual->offsetBlue = pScrn->offset.blue; + visual->redMask = pScrn->mask.red; + visual->greenMask = pScrn->mask.green; + visual->blueMask = pScrn->mask.blue; + } + } + } + + fbPictureInit(pScreen, NULL, 0); + + pGlamo->CreateScreenResources = pScreen->CreateScreenResources; + pScreen->CreateScreenResources = GlamoKMSCreateScreenResources; + + xf86SetBlackWhitePixels(pScreen); + + GlamoKMSExaInit(pScrn); + + miInitializeBackingStore(pScreen); + xf86SetBackingStore(pScreen); + xf86SetSilkenMouse(pScreen); + miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); + + /* Must force it before EnterVT, so we are in control of VT and + * later memory should be bound when allocating, e.g rotate_mem */ + pScrn->vtSema = TRUE; + + pScreen->SaveScreen = xf86SaveScreen; + pGlamo->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = GlamoKMSCloseScreen; + + if ( !xf86CrtcScreenInit(pScreen) ) return FALSE; + + if ( !miCreateDefColormap(pScreen) ) return FALSE; + + xf86DPMSInit(pScreen, xf86DPMSSet, 0); + + if ( serverGeneration == 1 ) { + xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); + } + + driScreenInit(pScreen); + + return GlamoKMSEnterVT(scrnIndex, 1); +} + + +Bool GlamoKMSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + return xf86SetSingleMode(pScrn, mode, RR_Rotate_0); +} + + +Bool GlamoKMSEnterVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + GlamoPtr pGlamo = GlamoPTR(pScrn); + + /* Only save state once per server generation since that's what most + * drivers do. Could change this to save state at each VT enter. */ + if ( pGlamo->SaveGeneration != serverGeneration ) { + pGlamo->SaveGeneration = serverGeneration; + /* ...except there is no hardware state to save */ + } + + if ( !flags ) { + /* signals startup as we'll do this in CreateScreenResources */ + CreateFrontBuffer(pScrn); + } + + if ( !xf86SetDesiredModes(pScrn) ) return FALSE; + + return TRUE; +} + + +void GlamoKMSLeaveVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + GlamoPtr pGlamo = GlamoPTR(pScrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int o; + + for (o = 0; o < config->num_crtc; o++) { + + xf86CrtcPtr crtc = config->crtc[o]; + + if ( crtc->rotatedPixmap || crtc->rotatedData ) { + crtc->funcs->shadow_destroy(crtc, crtc->rotatedPixmap, + crtc->rotatedData); + crtc->rotatedPixmap = NULL; + crtc->rotatedData = NULL; + } + + } + + drmModeRmFB(pGlamo->drm_fd, pGlamo->fb_id); + + pScrn->vtSema = FALSE; +} + + +ModeStatus GlamoKMSValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, + int flags) +{ + return MODE_OK; +} diff --git a/src/glamo-kms-driver.h b/src/glamo-kms-driver.h new file mode 100644 index 0000000..7d67feb --- /dev/null +++ b/src/glamo-kms-driver.h @@ -0,0 +1,34 @@ +/* + * KMS Support for the SMedia Glamo3362 X.org Driver + * + * Copyright 2009 Thomas White <taw@bitwiz.org.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include "xf86.h" + +extern Bool GlamoKernelModesettingAvailable(); +extern Bool GlamoKMSPreInit(ScrnInfoPtr pScrn, int flags); +extern Bool GlamoKMSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, + char **argv); +extern Bool GlamoKMSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags); +extern void GlamoKMSAdjustFrame(int scrnIndex, int x, int y, int flags); +extern Bool GlamoKMSEnterVT(int scrnIndex, int flags); +extern void GlamoKMSLeaveVT(int scrnIndex, int flags); +extern ModeStatus GlamoKMSValidMode(int scrnIndex, DisplayModePtr mode, + Bool verbose, int flags); diff --git a/src/glamo-kms-exa.c b/src/glamo-kms-exa.c new file mode 100644 index 0000000..f29c296 --- /dev/null +++ b/src/glamo-kms-exa.c @@ -0,0 +1,594 @@ +/* + * EXA via DRI for the SMedia Glamo3362 X.org Driver + * + * Copyright 2009 Thomas White <taw@bitwiz.org.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * The contents of this file are based on glamo-draw.c, to which the following + * notice applies: + * + * Copyright 2007 OpenMoko, Inc. + * + * This driver is based on Xati, + * Copyright 2003 Eric Anholt + * + * 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 the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS 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. + */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "glamo-log.h" +#include "glamo.h" +#include "glamo-regs.h" +#include "glamo-kms-exa.h" +#include "glamo-drm.h" + +#include <drm/glamo_drm.h> +#include <drm/glamo_bo.h> +#include <drm/glamo_bo_gem.h> +#include <xf86drm.h> + + +#if GLAMO_TRACE_FALL + #define GLAMO_FALLBACK(x) \ + do { \ + ErrorF("%s: ", __FUNCTION__); \ + ErrorF x; \ + return FALSE; \ + } while (0) +#else + #define GLAMO_FALLBACK(x) return FALSE +#endif + + +static const CARD8 GLAMOSolidRop[16] = { + /* GXclear */ 0x00, /* 0 */ + /* GXand */ 0xa0, /* src AND dst */ + /* GXandReverse */ 0x50, /* src AND NOT dst */ + /* GXcopy */ 0xf0, /* src */ + /* GXandInverted*/ 0x0a, /* NOT src AND dst */ + /* GXnoop */ 0xaa, /* dst */ + /* GXxor */ 0x5a, /* src XOR dst */ + /* GXor */ 0xfa, /* src OR dst */ + /* GXnor */ 0x05, /* NOT src AND NOT dst */ + /* GXequiv */ 0xa5, /* NOT src XOR dst */ + /* GXinvert */ 0x55, /* NOT dst */ + /* GXorReverse */ 0xf5, /* src OR NOT dst */ + /* GXcopyInverted*/ 0x0f, /* NOT src */ + /* GXorInverted */ 0xaf, /* NOT src OR dst */ + /* GXnand */ 0x5f, /* NOT src OR NOT dst */ + /* GXset */ 0xff, /* 1 */ +}; + + +static const CARD8 GLAMOBltRop[16] = { + /* GXclear */ 0x00, /* 0 */ + /* GXand */ 0x88, /* src AND dst */ + /* GXandReverse */ 0x44, /* src AND NOT dst */ + /* GXcopy */ 0xcc, /* src */ + /* GXandInverted*/ 0x22, /* NOT src AND dst */ + /* GXnoop */ 0xaa, /* dst */ + /* GXxor */ 0x66, /* src XOR dst */ + /* GXor */ 0xee, /* src OR dst */ + /* GXnor */ 0x11, /* NOT src AND NOT dst */ + /* GXequiv */ 0x99, /* NOT src XOR dst */ + /* GXinvert */ 0x55, /* NOT dst */ + /* GXorReverse */ 0xdd, /* src OR NOT dst */ + /* GXcopyInverted*/ 0x33, /* NOT src */ + /* GXorInverted */ 0xbb, /* NOT src OR dst */ + /* GXnand */ 0x77, /* NOT src OR NOT dst */ + /* GXset */ 0xff, /* 1 */ +}; + + +unsigned int driGetPixmapHandle(PixmapPtr pPixmap, unsigned int *flags) +{ + struct glamo_exa_pixmap_priv *priv; + + priv = exaGetPixmapDriverPrivate(pPixmap); + if (!priv) { + FatalError("NO PIXMAP PRIVATE\n"); + return 0; + } + + return priv->bo->handle; +} + + +static Bool GlamoKMSExaPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg) +{ + ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum]; + GlamoPtr pGlamo = GlamoPTR(pScrn); + CARD16 op, pitch; + FbBits mask; + struct glamo_exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix); + + if (pPix->drawable.bitsPerPixel != 16) { + GLAMO_FALLBACK(("Only 16bpp is supported\n")); + } + + mask = FbFullMask(16); + if ((pm & mask) != mask) { + GLAMO_FALLBACK(("Can't do planemask 0x%08x\n", + (unsigned int)pm)); + } + + op = GLAMOSolidRop[alu] << 8; + pitch = pPix->devKind; + + GlamoDRMAddCommandBO(pGlamo, GLAMO_REG_2D_DST_ADDRL, priv->bo); + GlamoDRMAddCommand(pGlamo, GLAMO_REG_2D_DST_PITCH, pitch & 0x7ff); + GlamoDRMAddCommand(pGlamo, GLAMO_REG_2D_DST_HEIGHT, pPix->drawable.height); + GlamoDRMAddCommand(pGlamo, GLAMO_REG_2D_PAT_FG, fg); + GlamoDRMAddCommand(pGlamo, GLAMO_REG_2D_COMMAND2, op); + + return TRUE; +} + + +static void GlamoKMSExaSolid(PixmapPtr pPix, int x1, int y1, int x2, int y2) +{ + ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum]; + GlamoPtr pGlamo = GlamoPTR(pScrn); + + GlamoDRMAddCommand(pGlamo, GLAMO_REG_2D_DST_X, x1); + GlamoDRMAddCommand(pGlamo, GLAMO_REG_2D_DST_Y, y1); + GlamoDRMAddCommand(pGlamo, GLAMO_REG_2D_RECT_WIDTH, x2 - x1); + GlamoDRMAddCommand(pGlamo, GLAMO_REG_2D_RECT_HEIGHT, y2 - y1); + GlamoDRMAddCommand(pGlamo, GLAMO_REG_2D_COMMAND3, 0); +} + + +static void GlamoKMSExaDoneSolid(PixmapPtr pPix) +{ + ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum]; + GlamoPtr pGlamo = GlamoPTR(pScrn); + + GlamoDRMDispatch(pGlamo); + exaMarkSync(pGlamo->pScreen); +} + + +static Bool GlamoKMSExaPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, int dx, int dy, + int alu, Pixel pm) +{ + ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; + GlamoPtr pGlamo = GlamoPTR(pScrn); + FbBits mask; + CARD16 src_pitch, dst_pitch; + CARD16 op; + struct glamo_exa_pixmap_priv *priv_src; + struct glamo_exa_pixmap_priv *priv_dst; + + priv_src = exaGetPixmapDriverPrivate(pSrc); + priv_dst = exaGetPixmapDriverPrivate(pDst); + + if (pSrc->drawable.bitsPerPixel != 16 || + pDst->drawable.bitsPerPixel != 16) { + GLAMO_FALLBACK(("Only 16bpp is supported")); + } + + mask = FbFullMask(16); + if ((pm & mask) != mask) { + GLAMO_FALLBACK(("Can't do planemask 0x%08x", + (unsigned int) pm)); + } + + src_pitch = pSrc->devKind; + dst_pitch = pDst->devKind; + op = GLAMOBltRop[alu] << 8; + + GlamoDRMAddCommandBO(pGlamo, GLAMO_REG_2D_SRC_ADDRL, priv_src->bo); + GlamoDRMAddCommand(pGlamo, GLAMO_REG_2D_SRC_PITCH, src_pitch & 0x7ff); + + GlamoDRMAddCommandBO(pGlamo, GLAMO_REG_2D_DST_ADDRL, priv_dst->bo); + GlamoDRMAddCommand(pGlamo, GLAMO_REG_2D_DST_PITCH, dst_pitch & 0x7ff); + GlamoDRMAddCommand(pGlamo, GLAMO_REG_2D_DST_HEIGHT, pDst->drawable.height); + + GlamoDRMAddCommand(pGlamo, GLAMO_REG_2D_COMMAND2, op); + + return TRUE; +} + + +static void GlamoKMSExaCopy(PixmapPtr pDst, int srcX, int srcY, + int dstX, int dstY, int width, int height) +{ + ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; + GlamoPtr pGlamo = GlamoPTR(pScrn); + + GlamoDRMAddCommand(pGlamo, GLAMO_REG_2D_SRC_X, srcX); + GlamoDRMAddCommand(pGlamo, GLAMO_REG_2D_SRC_Y, srcY); + GlamoDRMAddCommand(pGlamo, GLAMO_REG_2D_DST_X, dstX); + GlamoDRMAddCommand(pGlamo, GLAMO_REG_2D_DST_Y, dstY); + GlamoDRMAddCommand(pGlamo, GLAMO_REG_2D_RECT_WIDTH, width); + GlamoDRMAddCommand(pGlamo, GLAMO_REG_2D_RECT_HEIGHT, height); + GlamoDRMAddCommand(pGlamo, GLAMO_REG_2D_COMMAND3, 0); +} + + +static void GlamoKMSExaDoneCopy(PixmapPtr pDst) +{ + ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; + GlamoPtr pGlamo = GlamoPTR(pScrn); + + GlamoDRMDispatch(pGlamo); + exaMarkSync(pGlamo->pScreen); +} + + +/* Generate an integer token which can be used for synchronisation later. + * We do this by putting the most recently used buffer object into a list, + * and returning the index into that list. + * To make things a little more exciting, the list is a ring buffer. */ +static int GlamoKMSExaMarkSync(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + GlamoPtr pGlamo = GlamoPTR(pScrn); + unsigned int idx; + + idx = pGlamo->exa_marker_index; + pGlamo->exa_buffer_markers[idx] = pGlamo->last_buffer_object; + + pGlamo->exa_marker_index = (idx+1) % NUM_EXA_BUFFER_MARKERS; + + return 1; +} + + +static void GlamoKMSExaWaitMarker(ScreenPtr pScreen, int idx) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + GlamoPtr pGlamo = GlamoPTR(pScrn); + struct glamo_bo *bo; + + bo = pGlamo->exa_buffer_markers[idx]; + + if ( bo ) { + glamo_bo_wait(bo); + } else { + + struct drm_glamo_gem_wait_rendering args; + + args.handle = 0; + args.have_handle = 0; + drmCommandWriteRead(pGlamo->bufmgr->fd, + DRM_GLAMO_GEM_WAIT_RENDERING, + &args, sizeof(args)); + } +} + + +static void *GlamoKMSExaCreatePixmap(ScreenPtr screen, int size, int align) +{ + ScrnInfoPtr pScrn = xf86Screens[screen->myNum]; + GlamoPtr pGlamo = GlamoPTR(pScrn); + struct glamo_exa_pixmap_priv *new_priv; + + new_priv = xcalloc(1, sizeof(struct glamo_exa_pixmap_priv)); + if (!new_priv) + return NULL; + + /* See GlamoKMSExaModifyPixmapHeader() below */ + if (size == 0) + return new_priv; + + /* Dive into the kernel (via libdrm) to allocate some VRAM */ + new_priv->bo = glamo_bo_open(pGlamo->bufmgr, 0, size, align, + GLAMO_GEM_DOMAIN_VRAM, 0); + if (!new_priv->bo) { + xfree(new_priv); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to create pixmap\n"); + return NULL; + } + + return new_priv; +} + + +static void GlamoKMSExaDestroyPixmap(ScreenPtr pScreen, void *driverPriv) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + GlamoPtr pGlamo = GlamoPTR(pScrn); + struct glamo_exa_pixmap_priv *driver_priv = driverPriv; + int i; + + /* We're about to (probably) delete a buffer object, so zip through + * the list of EXA wait markers and delete any references. */ + for ( i=0; i<NUM_EXA_BUFFER_MARKERS; i++ ) { + if ( pGlamo->exa_buffer_markers[i] == driver_priv->bo ) { + pGlamo->exa_buffer_markers[i] = NULL; + } + } + if ( pGlamo->last_buffer_object == driver_priv->bo ) { + pGlamo->last_buffer_object = NULL; + } + + if (driver_priv->bo) + glamo_bo_unref(driver_priv->bo); + + xfree(driver_priv); +} + + +static Bool GlamoKMSExaPixmapIsOffscreen(PixmapPtr pPix) +{ + struct glamo_exa_pixmap_priv *driver_priv; + + driver_priv = exaGetPixmapDriverPrivate(pPix); + if (driver_priv && driver_priv->bo) + return TRUE; + + return FALSE; +} + + +static Bool GlamoKMSExaPrepareAccess(PixmapPtr pPix, int index) +{ + ScreenPtr screen = pPix->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[screen->myNum]; + struct glamo_exa_pixmap_priv *driver_priv; + + driver_priv = exaGetPixmapDriverPrivate(pPix); + if (!driver_priv) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "%s: no driver private?\n", __FUNCTION__); + return FALSE; + } + + if (!driver_priv->bo) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "%s: no buffer object?\n", __FUNCTION__); + return TRUE; + } + + /* Return as quickly as possible if we have a mapping already */ + if ( driver_priv->bo->virtual ) { + pPix->devPrivate.ptr = driver_priv->bo->virtual; + glamo_bo_wait(driver_priv->bo); + return TRUE; + } + + if ( glamo_bo_map(driver_priv->bo, 1) ) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "%s: bo map failed\n", __FUNCTION__); + return FALSE; + } + pPix->devPrivate.ptr = driver_priv->bo->virtual; + glamo_bo_wait(driver_priv->bo); + + return TRUE; +} + + +static void GlamoKMSExaFinishAccess(PixmapPtr pPix, int index) +{ + /* Leave the mapping intact for fast restoration of access later */ + pPix->devPrivate.ptr = NULL; +} + + +/* This essentially does the job of ModifyPixmapHeader, for the occasions + * when we need to update the properties of the screen pixmap. */ +Bool GlamoKMSExaMakeFullyFledged(PixmapPtr pPix, int width, int height, + int depth, int bitsPerPixel, int devKind) +{ + ScreenPtr screen = pPix->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[screen->myNum]; + GlamoPtr pGlamo = GlamoPTR(pScrn); + struct glamo_exa_pixmap_priv *priv; + int new_size; + + if (depth <= 0) depth = pPix->drawable.depth; + if (bitsPerPixel <= 0) bitsPerPixel = pPix->drawable.bitsPerPixel; + if (width <= 0) width = pPix->drawable.width; + if (height <= 0) height = pPix->drawable.height; + if (width <= 0 || height <= 0 || depth <= 0) return FALSE; + + miModifyPixmapHeader(pPix, width, height, depth, + bitsPerPixel, devKind, NULL); + + priv = exaGetPixmapDriverPrivate(pPix); + if (!priv) { + /* This should never, ever, happen */ + FatalError("Fledgeling pixmap had no driver private!\n"); + return FALSE; + } + + new_size = (width * height * depth) / 8; + if ( new_size == 0 ) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Fledgeling pixmap would still have zero size!" + " %ix%i %i bpp depth=%i\n", width, height, + bitsPerPixel, depth); + new_size = 1; + } + + if ( priv->bo == NULL ) { + + /* This pixmap has no associated buffer object. + * It's time to create one */ + priv->bo = glamo_bo_open(pGlamo->bufmgr, 0, new_size, 2, + GLAMO_GEM_DOMAIN_VRAM, 0); + if ( priv->bo == NULL ) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Couldn't create buffer object for" + " fledgeling pixmap!\n"); + return FALSE; + } + + } else { + + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Fledgeling pixmap already had a buffer object!\n"); + + } + + return TRUE; +} + + +Bool GlamoKMSExaCheckComposite(int op, + PicturePtr pSrcPicture, + PicturePtr pMaskPicture, + PicturePtr pDstPicture) +{ + return FALSE; +} + + +Bool GlamoKMSExaPrepareComposite(int op, + PicturePtr pSrcPicture, + PicturePtr pMaskPicture, + PicturePtr pDstPicture, + PixmapPtr pSrc, + PixmapPtr pMask, + PixmapPtr pDst) +{ + return FALSE; +} + + +void GlamoKMSExaComposite(PixmapPtr pDst, + int srcX, + int srcY, + int maskX, + int maskY, + int dstX, + int dstY, + int width, + int height) +{ +} + + +void GlamoKMSExaDoneComposite(PixmapPtr pDst) +{ +} + + +void GlamoKMSExaClose(ScrnInfoPtr pScrn) +{ + exaDriverFini(pScrn->pScreen); +} + + +void GlamoKMSExaInit(ScrnInfoPtr pScrn) +{ + GlamoPtr pGlamo = GlamoPTR(pScrn); + Bool success = FALSE; + ExaDriverPtr exa; + int i; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "EXA hardware acceleration initialising\n"); + + exa = exaDriverAlloc(); + if ( !exa ) return; + pGlamo->exa = exa; + + exa->exa_major = EXA_VERSION_MAJOR; + exa->exa_minor = EXA_VERSION_MINOR; + exa->memoryBase = 0; + exa->memorySize = 0; + exa->offScreenBase = 0; + exa->pixmapOffsetAlign = 2; + exa->pixmapPitchAlign = 2; + exa->maxX = 640; + exa->maxY = 640; + + /* Solid fills */ + exa->PrepareSolid = GlamoKMSExaPrepareSolid; + exa->Solid = GlamoKMSExaSolid; + exa->DoneSolid = GlamoKMSExaDoneSolid; + + /* Blits */ + exa->PrepareCopy = GlamoKMSExaPrepareCopy; + exa->Copy = GlamoKMSExaCopy; + exa->DoneCopy = GlamoKMSExaDoneCopy; + + /* Composite (though these just cause fallback) */ + exa->CheckComposite = GlamoKMSExaCheckComposite; + exa->PrepareComposite = GlamoKMSExaPrepareComposite; + exa->Composite = GlamoKMSExaComposite; + exa->DoneComposite = GlamoKMSExaDoneComposite; + + exa->DownloadFromScreen = NULL; + exa->UploadToScreen = NULL; + exa->UploadToScratch = NULL; + + exa->MarkSync = GlamoKMSExaMarkSync; + exa->WaitMarker = GlamoKMSExaWaitMarker; + + /* Prepare temporary buffers */ + GlamoDRMInit(pGlamo); + pGlamo->last_buffer_object = NULL; + for ( i=0; i<NUM_EXA_BUFFER_MARKERS; i++ ) { + pGlamo->exa_buffer_markers[i] = NULL; + } + pGlamo->exa_marker_index = 0; + if ( !pGlamo->cmdq_drm ) return; + + /* Tell EXA that we're going to take care of memory + * management ourselves. */ + exa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS; +#ifdef EXA_MIXED_PIXMAPS + exa->flags |= EXA_MIXED_PIXMAPS; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using mixed mode pixmaps\n"); +#endif + exa->PrepareAccess = GlamoKMSExaPrepareAccess; + exa->FinishAccess = GlamoKMSExaFinishAccess; + exa->CreatePixmap = GlamoKMSExaCreatePixmap; + exa->DestroyPixmap = GlamoKMSExaDestroyPixmap; + exa->PixmapIsOffscreen = GlamoKMSExaPixmapIsOffscreen; + exa->ModifyPixmapHeader = NULL; + + /* Hook up with libdrm */ + pGlamo->bufmgr = glamo_bo_manager_gem_ctor(pGlamo->drm_fd); + + success = exaDriverInit(pScrn->pScreen, exa); + if (success) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Initialized EXA acceleration\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to initialize EXA acceleration\n"); + xfree(pGlamo->exa); + pGlamo->exa = NULL; + } +} diff --git a/src/glamo-kms-exa.h b/src/glamo-kms-exa.h new file mode 100644 index 0000000..0473b3b --- /dev/null +++ b/src/glamo-kms-exa.h @@ -0,0 +1,34 @@ +/* + * EXA via DRI for the SMedia Glamo3362 X.org Driver + * + * Copyright 2009 Thomas White <taw@bitwiz.org.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include "xf86.h" + +struct glamo_exa_pixmap_priv { + struct glamo_bo *bo; +}; + +extern void GlamoKMSExaInit(ScrnInfoPtr pScrn); +extern void GlamoKMSExaClose(ScrnInfoPtr pScrn); +extern unsigned int driGetPixmapHandle(PixmapPtr pPixmap, unsigned int *flags); +extern Bool GlamoKMSExaMakeFullyFledged(PixmapPtr pPix, int width, int height, + int depth, int bitsPerPixel, + int devKind); diff --git a/src/glamo-kms-output.c b/src/glamo-kms-output.c new file mode 100644 index 0000000..7b9f997 --- /dev/null +++ b/src/glamo-kms-output.c @@ -0,0 +1,304 @@ +/* + * KMS Support for the SMedia Glamo3362 X.org Driver + * + * Modified: 2009 by Thomas White <taw@bitwiz.org.uk> + * + * Based on output.c from xf86-video-modesetting, to which the following + * notice applies: + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Author: Alan Hourihane <alanh@tungstengraphics.com> + * + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <xf86.h> +#include <xf86i2c.h> +#include <xf86Crtc.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#define DPMS_SERVER +#include <X11/extensions/dpmsconst.h> +#include <X11/Xatom.h> +#include <xf86drmMode.h> + +#include "glamo.h" +#include "glamo-kms-output.h" + + +static char *connector_enum_list[] = { + "Unknown", + "VGA", + "DVI-I", + "DVI-D", + "DVI-A", + "Composite", + "SVIDEO", + "LVDS", + "Component", + "9-pin DIN", + "DisplayPort", + "HDMI Type A", + "HDMI Type B", +}; + + +static void dpms(xf86OutputPtr output, int mode) +{ +} + + +static void save(xf86OutputPtr output) +{ +} + + +static void restore(xf86OutputPtr output) +{ +} + + +static int mode_valid(xf86OutputPtr output, DisplayModePtr pMode) +{ + return MODE_OK; +} + + +static Bool mode_fixup(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + return TRUE; +} + + +static void prepare(xf86OutputPtr output) +{ + dpms(output, DPMSModeOff); +} + + +static void mode_set(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ +} + + +static void commit(xf86OutputPtr output) +{ + dpms(output, DPMSModeOn); +} + + +static xf86OutputStatus detect(xf86OutputPtr output) +{ + drmModeConnectorPtr drm_connector = output->driver_private; + + switch (drm_connector->connection) { + case DRM_MODE_CONNECTED: + return XF86OutputStatusConnected; + case DRM_MODE_DISCONNECTED: + return XF86OutputStatusDisconnected; + default: + return XF86OutputStatusUnknown; + } +} + + +static DisplayModePtr get_modes(xf86OutputPtr output) +{ + drmModeConnectorPtr drm_connector = output->driver_private; + drmModeModeInfoPtr drm_mode = NULL; + DisplayModePtr modes = NULL, mode = NULL; + int i; + + for (i = 0; i < drm_connector->count_modes; i++) { + drm_mode = &drm_connector->modes[i]; + if (drm_mode) { + mode = xcalloc(1, sizeof(DisplayModeRec)); + if (!mode) + continue; + mode->type = 0; + mode->Clock = drm_mode->clock; + mode->HDisplay = drm_mode->hdisplay; + mode->HSyncStart = drm_mode->hsync_start; + mode->HSyncEnd = drm_mode->hsync_end; + mode->HTotal = drm_mode->htotal; + mode->VDisplay = drm_mode->vdisplay; + mode->VSyncStart = drm_mode->vsync_start; + mode->VSyncEnd = drm_mode->vsync_end; + mode->VTotal = drm_mode->vtotal; + mode->Flags = drm_mode->flags; + mode->HSkew = drm_mode->hskew; + mode->VScan = drm_mode->vscan; + mode->VRefresh = xf86ModeVRefresh(mode); + mode->Private = (void *)drm_mode; + xf86SetModeDefaultName(mode); + modes = xf86ModesAdd(modes, mode); + xf86PrintModeline(0, mode); + } + } + + return modes; +} + + +static void destroy(xf86OutputPtr output) +{ + drmModeFreeConnector(output->driver_private); +} + + +static void create_resources(xf86OutputPtr output) +{ +#ifdef RANDR_12_INTERFACE +#endif /* RANDR_12_INTERFACE */ +} + + +#ifdef RANDR_12_INTERFACE +static Bool set_property(xf86OutputPtr output, Atom property, + RRPropertyValuePtr value) +{ + return TRUE; +} +#endif /* RANDR_12_INTERFACE */ + + +#ifdef RANDR_13_INTERFACE +static Bool get_property(xf86OutputPtr output, Atom property) +{ + return TRUE; +} +#endif /* RANDR_13_INTERFACE */ + + +#ifdef RANDR_GET_CRTC_INTERFACE +static xf86CrtcPtr get_crtc(xf86OutputPtr output) +{ + return NULL; +} +#endif + + +static const xf86OutputFuncsRec output_funcs = { + .create_resources = create_resources, + .dpms = dpms, + .save = save, + .restore = restore, + .mode_valid = mode_valid, + .mode_fixup = mode_fixup, + .prepare = prepare, + .mode_set = mode_set, + .commit = commit, + .detect = detect, + .get_modes = get_modes, +#ifdef RANDR_12_INTERFACE + .set_property = set_property, +#endif +#ifdef RANDR_13_INTERFACE + .get_property = get_property, +#endif + .destroy = destroy, +#ifdef RANDR_GET_CRTC_INTERFACE + .get_crtc = get_crtc, +#endif +}; + + +void output_init(ScrnInfoPtr pScrn) +{ + GlamoPtr pGlamo = GlamoPTR(pScrn); + xf86OutputPtr output; + drmModeResPtr res; + drmModeConnectorPtr drm_connector = NULL; + drmModeEncoderPtr drm_encoder = NULL; + char *name; + int c, v, p; + + res = drmModeGetResources(pGlamo->drm_fd); + if (res == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed drmModeGetResources\n"); + return; + } + + for (c = 0; c < res->count_connectors; c++) { + drm_connector = drmModeGetConnector(pGlamo->drm_fd, + res->connectors[c]); + if (!drm_connector) + goto out; + + for (p = 0; p < drm_connector->count_props; p++) { + drmModePropertyPtr prop; + + prop = drmModeGetProperty(pGlamo->drm_fd, + drm_connector->props[p]); + + name = NULL; + if (prop) { + ErrorF("VALUES %d\n", prop->count_values); + for (v = 0; v < prop->count_values; v++) { + ErrorF("%s %lld\n", prop->name, + prop->values[v]); + } + } + } + + name = connector_enum_list[drm_connector->connector_type]; + + output = xf86OutputCreate(pScrn, &output_funcs, name); + if (!output) + continue; + + drm_encoder = drmModeGetEncoder(pGlamo->drm_fd, + drm_connector->encoders[0]); + if (drm_encoder) { + output->possible_crtcs = drm_encoder->possible_crtcs; + output->possible_clones = drm_encoder->possible_clones; + } else { + output->possible_crtcs = 0; + output->possible_clones = 0; + } + output->driver_private = drm_connector; + output->subpixel_order = SubPixelHorizontalRGB; + output->interlaceAllowed = FALSE; + output->doubleScanAllowed = FALSE; + } + +out: + drmModeFreeResources(res); +} diff --git a/src/glamo-kms-output.h b/src/glamo-kms-output.h new file mode 100644 index 0000000..0bb7565 --- /dev/null +++ b/src/glamo-kms-output.h @@ -0,0 +1,25 @@ +/* + * KMS Support for the SMedia Glamo3362 X.org Driver + * + * Copyright 2009 Thomas White <taw@bitwiz.org.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include "xf86.h" + +extern void output_init(ScrnInfoPtr pScrn); diff --git a/src/glamo.h b/src/glamo.h index 6abf84a..d335ce3 100644 --- a/src/glamo.h +++ b/src/glamo.h @@ -37,6 +37,8 @@ #include "xf86.h" #include "exa.h" #include <linux/fb.h> +#include <drm/drm.h> +#include <drm/glamo_bo.h> #define GLAMO_REG_BASE(c) ((c)->attr.address[0]) #define GLAMO_REG_SIZE(c) (0x2400) @@ -73,6 +75,9 @@ MMIO_IN16(__volatile__ void *base, const unsigned long offset) #endif +/* The number of EXA wait markers which can be active at once */ +#define NUM_EXA_BUFFER_MARKERS 32 + typedef volatile CARD16 VOL16; typedef struct _MemBuf { @@ -105,6 +110,18 @@ typedef struct { */ MemBuf *cmd_queue; + /* The same, when using DRM */ + uint16_t *cmdq_drm; + int cmdq_drm_used; + int cmdq_drm_size; + int cmdq_obj_used; + uint32_t *cmdq_objs; + unsigned int *cmdq_obj_pos; + struct glamo_bo *last_buffer_object; /* The last buffer object + * referenced in the cmdq */ + struct glamo_bo *exa_buffer_markers[NUM_EXA_BUFFER_MARKERS]; + unsigned int exa_marker_index; /* Index into exa_buffer_markers */ + /* What was GLAMOCardInfo */ volatile char *reg_base; Bool is_3362; @@ -135,6 +152,13 @@ typedef struct { /* Use hardware acceleration */ Bool accel; + /* Things to do with DRI */ + int drm_fd; + unsigned int SaveGeneration; + unsigned int fb_id; + char drm_devname[64]; + struct glamo_bo_manager *bufmgr; + uint16_t *colormap; } GlamoRec, *GlamoPtr; @@ -175,4 +199,8 @@ GlamoCrtcInit(ScrnInfoPtr pScrn); void GlamoOutputInit(ScrnInfoPtr pScrn); +/* glamo-driver.c */ +extern Bool GlamoGetRec(ScrnInfoPtr pScrn); +extern void GlamoFreeRec(ScrnInfoPtr pScrn); + #endif /* _GLAMO_H_ */ |