Add DRM driver abstraction
This adds an abstraction interface in src/drmmode_driver.h for the
driver-specific values (and in future functions) that we need. It
also adds documentation and build system support (--with-drmmode)
to choose your supported driver.
Initially, the dumb allocation flags and page flip events flags
are abstracted with support for pl111 and eynos.
A template implementation is also provided for ease of adding new
driver support.
Change-Id: I98890ddab6b907c3007b72a662ecd7ee6caa4402
diff --git a/README b/README
index 10bd463..8d05217 100644
--- a/README
+++ b/README
@@ -1,23 +1,28 @@
xf86-video-armsoc
Open-source X.org graphics driver for ARM graphics
-Platform specific values
-------------------------
-The meaning of the bits in the 'flags' element in the drm_mode_create_dumb struct
-used by DRM_IOCTL_MODE_CREATE_DUMB is platform dependent.
-The defines for the flag values in omap_drmif_fb.h should be modified for the target platform in use.
+DRM driver selection
+--------------------
+While most operations use only the standard DRM modesetting interfaces, certain operations
+unavoidably rely on specific driver behaviour (including dumb buffer allocation flags and cursor
+plane z-ordering). As such, the armsoc driver must be configured for a particular DRM driver.
-The example given is for a DRM driver which uses bit 0 of flags to select the buffer type.
-In this case a value of 1 for bit 0 selects a buffer with a scanoutable allocation.
+The currently supported DRM drivers are:
+- pl111
+- exynos
-The platform specific defines are :
+To configure armsoc for one of these, pass the --with-drmmode option to ./configure. For example:
- /* Platform specific values for the flags element of the drm_mode_create_dumb struct
- * used by DRM_IOCTL_MODE_CREATE_DUMB. Substitute appropriate values for the target drm driver.
- */
- #define DRM_BO_SCANOUT 0x00000001 /* request scanout compatible buffer */
- #define DRM_BO_NON_SCANOUT 0x00000000 /* request non-scanout compatible buffer */
+$ ./configure --with-drmmode=pl111
+For other drivers, you will need to implement this support yourself. A template implementation is
+provided in src/drmmode_template which can be built by passing --with-drmmode=template to ./configure.
+The interface is defined and documented in src/drmmode_driver.h, and you should refer to this while
+modifying the template to set up your DRM driver's abstraction appropriately.
+
+You can also copy src/drmmode_template into src/drmmode_<yourdrivername> and build with:
+
+$ ./configure --with-drmmode=<yourdrivername>
HW Cursors support
-------------------
@@ -35,4 +40,4 @@
For example to set HW_CURSOR_PL111 cursor support set DRM_CURSOR_PLANE_FORMAT in the following way:
-#define DRM_CURSOR_PLANE_FORMAT HW_CURSOR_PL111
\ No newline at end of file
+#define DRM_CURSOR_PLANE_FORMAT HW_CURSOR_PL111
diff --git a/configure.ac b/configure.ac
index d47f8ef..258de0d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -38,6 +38,15 @@
[moduledir="$withval"],
[moduledir="$libdir/xorg/modules"])
+AC_MSG_CHECKING([which DRM driver to use])
+AC_ARG_WITH(drmmode,
+ AC_HELP_STRING([--with-drmmode],
+ [Which DRM driver to use (see README)]),
+ [drmmode=$withval],
+ AC_MSG_FAILURE([You must specify which DRM driver to build for - see README]))
+AC_MSG_RESULT([$drmmode])
+AC_SUBST(drmmode)
+
# Checks for extensions
XORG_DRIVER_CHECK_EXT(RANDR, randrproto)
XORG_DRIVER_CHECK_EXT(RENDER, renderproto)
diff --git a/src/Makefile.am b/src/Makefile.am
index 632c656..c66f875 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -40,6 +40,7 @@
armsoc_drv_la_LDFLAGS = -module -avoid-version -no-undefined
armsoc_drv_la_LIBADD = @XORG_LIBS@
armsoc_drv_ladir = @moduledir@/drivers
+DRMMODE_SRCS = drmmode_@drmmode@/drmmode_@drmmode@.c
armsoc_drv_la_SOURCES = \
drmmode_display.c \
@@ -50,5 +51,5 @@
omap_dri2.c \
omap_driver.c \
omap_dumb.c \
- drm_pl111_cursor.c
-
+ drm_pl111_cursor.c \
+ $(DRMMODE_SRCS)
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index be041a9..5973e8e 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -94,6 +94,8 @@
#include <sys/ioctl.h>
#include <libudev.h>
+#include "drmmode_driver.h"
+
typedef struct {
/* hardware cursor: */
drmModePlane *ovr;
@@ -1237,16 +1239,16 @@
int
drmmode_page_flip(DrawablePtr draw, uint32_t fb_id, void *priv)
{
- ScrnInfoPtr scrn = xf86Screens[draw->pScreen->myNum];
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ ScrnInfoPtr pScrn = xf86Screens[draw->pScreen->myNum];
+ OMAPPtr pOMAP = OMAPPTR(pScrn);
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
drmmode_crtc_private_ptr crtc = config->crtc[0]->driver_private;
drmmode_ptr mode = crtc->drmmode;
int ret, i, failed = 0, num_flipped = 0;
unsigned int flags = 0;
-#if OMAP_USE_PAGE_FLIP_EVENTS
- flags |= DRM_MODE_PAGE_FLIP_EVENT;
-#endif
+ if (pOMAP->drmmode->use_page_flip_events)
+ flags |= DRM_MODE_PAGE_FLIP_EVENT;
/* if we can flip, we must be fullscreen.. so flip all CRTC's.. */
for (i = 0; i < config->num_crtc; i++) {
@@ -1255,7 +1257,7 @@
ret = drmModePageFlip(mode->fd, crtc->mode_crtc->crtc_id,
fb_id, flags, priv);
if (ret) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"flip queue failed: %s\n", strerror(errno));
failed = 1;
}
diff --git a/src/drmmode_driver.h b/src/drmmode_driver.h
new file mode 100644
index 0000000..dfb5daf
--- /dev/null
+++ b/src/drmmode_driver.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright © 2013 ARM Limited.
+ *
+ * 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, 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ */
+
+#ifndef DRMMODE_DRIVER_H
+#define DRMMODE_DRIVER_H
+
+#include <stdint.h>
+
+struct drmmode_interface {
+ /* Flags value to pass to DRM_IOCTL_MODE_CREATE_DUMB to allocate a scanout-capable
+ * buffer. A buffer allocated with these flags must be able to be wrapped in a
+ * DRM framebuffer (via DRM_IOCTL_MODE_ADDFB or DRM_IOCTL_MODE_ADDFB2).
+ */
+ uint32_t dumb_scanout_flags;
+
+ /* Flags value to pass to DRM_IOCTL_MODE_CREATE_DUMB to allocate a
+ * non-scanout-capable buffer. It is acceptable for the driver to create a
+ * scanout-capable buffer when given this flag, this flag is used to give the
+ * option of preserving scarce scanout-capable memory if applicable.
+ */
+ uint32_t dumb_no_scanout_flags;
+
+ /* Boolean value indicating whether DRM page flip events should be requested and
+ * waited for during DRM_IOCTL_MODE_PAGE_FLIP.
+ */
+ int use_page_flip_events;
+};
+
+struct drmmode_interface *drmmode_interface_get_implementation(int drm_fd);
+
+#endif
diff --git a/src/drmmode_exynos/drmmode_exynos.c b/src/drmmode_exynos/drmmode_exynos.c
new file mode 100644
index 0000000..1bd174e
--- /dev/null
+++ b/src/drmmode_exynos/drmmode_exynos.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2013 ARM Limited.
+ *
+ * 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, 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ */
+
+#include "../drmmode_driver.h"
+
+struct drmmode_interface exynos_interface = {
+ 0x00000001 /* dumb_scanout_flags */,
+ 0x00000001 /* dumb_no_scanout_flags */,
+ 1 /* use_page_flip_events */
+};
+
+struct drmmode_interface *drmmode_interface_get_implementation(int drm_fd)
+{
+ return &exynos_interface;
+}
diff --git a/src/drmmode_pl111/drmmode_pl111.c b/src/drmmode_pl111/drmmode_pl111.c
new file mode 100644
index 0000000..7795246
--- /dev/null
+++ b/src/drmmode_pl111/drmmode_pl111.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2013 ARM Limited.
+ *
+ * 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, 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ */
+
+#include "../drmmode_driver.h"
+
+struct drmmode_interface pl111_interface = {
+ 0x00000001 /* dumb_scanout_flags */,
+ 0x00000000 /* dumb_no_scanout_flags */,
+ 0 /* use_page_flip_events */
+};
+
+struct drmmode_interface *drmmode_interface_get_implementation(int drm_fd)
+{
+ return &pl111_interface;
+}
diff --git a/src/drmmode_template/drmmode_template.c b/src/drmmode_template/drmmode_template.c
new file mode 100644
index 0000000..39af8e4
--- /dev/null
+++ b/src/drmmode_template/drmmode_template.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2013 ARM Limited.
+ *
+ * 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, 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ */
+
+#include "../drmmode_driver.h"
+
+struct drmmode_interface template_interface = {
+ 0x00000000 /* dumb_scanout_flags */,
+ 0x00000000 /* dumb_no_scanout_flags */,
+ 1 /* use_page_flip_events */
+};
+
+struct drmmode_interface *drmmode_interface_get_implementation(int drm_fd)
+{
+ return &template_interface;
+}
diff --git a/src/omap_dri2.c b/src/omap_dri2.c
index ebcaebe..4e2587c 100644
--- a/src/omap_dri2.c
+++ b/src/omap_dri2.c
@@ -41,6 +41,8 @@
# error "Requires newer DRI2"
#endif
+#include "drmmode_driver.h"
+
typedef struct {
DRI2BufferRec base;
@@ -541,12 +543,13 @@
* Error while flipping; bail.
*/
cmd->flags |= OMAP_SWAP_FAIL;
-#if !OMAP_USE_PAGE_FLIP_EVENTS
- cmd->swapCount = 0;
-#else
- cmd->swapCount = -(ret + 1);
+
+ if (pOMAP->drmmode->use_page_flip_events)
+ cmd->swapCount = -(ret + 1);
+ else
+ cmd->swapCount = 0;
+
if (cmd->swapCount == 0)
-#endif
{
OMAPDRI2SwapComplete(cmd);
}
@@ -554,12 +557,13 @@
} else {
if (ret == 0)
cmd->flags |= OMAP_SWAP_FAKE_FLIP;
-#if !OMAP_USE_PAGE_FLIP_EVENTS
- cmd->swapCount = 0;
-#else
- cmd->swapCount = ret;
+
+ if (pOMAP->drmmode->use_page_flip_events)
+ cmd->swapCount = ret;
+ else
+ cmd->swapCount = 0;
+
if (cmd->swapCount == 0)
-#endif
{
OMAPDRI2SwapComplete(cmd);
}
diff --git a/src/omap_driver.c b/src/omap_driver.c
index 1e488b1..884988c 100644
--- a/src/omap_driver.c
+++ b/src/omap_driver.c
@@ -38,6 +38,8 @@
#include "omap_driver.h"
#include "compat-api.h"
+#include "drmmode_driver.h"
+
Bool omapDebug = 0;
/*
@@ -483,8 +485,14 @@
}
DEBUG_MSG("Became DRM master.");
+ pOMAP->drmmode = drmmode_interface_get_implementation(pOMAP->drmFD);
+ if (!pOMAP->drmmode)
+ goto fail;
+
/* create DRM device instance: */
- pOMAP->dev = omap_device_new(pOMAP->drmFD);
+ pOMAP->dev = omap_device_new(pOMAP->drmFD,
+ pOMAP->drmmode->dumb_scanout_flags,
+ pOMAP->drmmode->dumb_no_scanout_flags);
/* query chip-id: */
if (omap_get_param(pOMAP->dev, OMAP_PARAM_CHIPSET_ID, &value)) {
diff --git a/src/omap_driver.h b/src/omap_driver.h
index 93cd3b4..312ca6e 100644
--- a/src/omap_driver.h
+++ b/src/omap_driver.h
@@ -71,7 +71,6 @@
#define OMAP_MINOR_VERSION 83
#define OMAP_PATCHLEVEL 0
-#define OMAP_USE_PAGE_FLIP_EVENTS 0
#define OMAP_SUPPORT_GAMMA 0
#define CURSORW (64)
@@ -137,6 +136,8 @@
char *deviceName;
+ struct drmmode_interface *drmmode;
+
/** DRM device instance */
struct omap_device *dev;
diff --git a/src/omap_drmif_fb.h b/src/omap_drmif_fb.h
index b37acaa..25bf5ad 100644
--- a/src/omap_drmif_fb.h
+++ b/src/omap_drmif_fb.h
@@ -31,15 +31,6 @@
#define HW_CURSOR_ARGB (0)
#define HW_CURSOR_PL111 (1)
-/* Platform specific values for the flags element of the drm_mode_create_dumb struct
- * used by DRM_IOCTL_MODE_CREATE_DUMB. These are used by omap_bo_new_with_dim() to
- * request either a scanoutable or non-scanoutable buffer
- */
-/*
- * THESE VALUES SHOULD BE CUSTOMISED FOR THE TARGET DRM DRIVER - SEE THE README FILE
- */
-#define DRM_BO_SCANOUT 0x00000001 /* request scanout compatible buffer */
-#define DRM_BO_NON_SCANOUT 0x00000000 /* request non-scanout compatible buffer */
/*
* HARDWARE CURSOR SUPORT CONFIGURATION
@@ -62,7 +53,7 @@
OMAP_BO_NON_SCANOUT
};
-struct omap_device *omap_device_new(int fd);
+struct omap_device *omap_device_new(int fd, uint32_t dumb_scanout_flags, uint32_t dumb_no_scanout_flags);
void omap_device_del(struct omap_device *dev);
int omap_bo_get_name(struct omap_bo *bo, uint32_t *name);
uint32_t omap_bo_handle(struct omap_bo *bo);
diff --git a/src/omap_dumb.c b/src/omap_dumb.c
index 90b61b3..a2a32db 100644
--- a/src/omap_dumb.c
+++ b/src/omap_dumb.c
@@ -32,9 +32,12 @@
#include <xf86drmMode.h>
#include "omap_drmif_fb.h"
+#include "drmmode_driver.h"
struct omap_device {
int fd;
+ uint32_t dumb_scanout_flags;
+ uint32_t dumb_no_scanout_flags;
};
struct omap_bo {
@@ -55,13 +58,15 @@
/* device related functions:
*/
-struct omap_device *omap_device_new(int fd)
+struct omap_device *omap_device_new(int fd, uint32_t dumb_scanout_flags, uint32_t dumb_no_scanout_flags)
{
struct omap_device *new_dev = malloc(sizeof(*new_dev));
if (!new_dev)
return NULL;
new_dev->fd = fd;
+ new_dev->dumb_scanout_flags = dumb_scanout_flags;
+ new_dev->dumb_no_scanout_flags = dumb_no_scanout_flags;
return new_dev;
}
@@ -126,11 +131,11 @@
assert((OMAP_BO_SCANOUT == buf_type) || (OMAP_BO_NON_SCANOUT == buf_type));
if (OMAP_BO_SCANOUT == buf_type)
{
- create_dumb.flags = DRM_BO_SCANOUT;
+ create_dumb.flags = dev->dumb_scanout_flags;
}
else
{
- create_dumb.flags = DRM_BO_NON_SCANOUT;
+ create_dumb.flags = dev->dumb_no_scanout_flags;
}
res = drmIoctl(dev->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);