summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am9
-rw-r--r--src/drmmode_display.c1035
-rw-r--r--src/drmmode_display.h74
-rwxr-xr-xsrc/pcidb/parse_pci_ids.pl2
-rw-r--r--src/radeon.h18
-rw-r--r--src/radeon_accel.c6
-rw-r--r--src/radeon_chipinfo_gen.h2
-rw-r--r--src/radeon_commonfuncs.c59
-rw-r--r--src/radeon_dri2.c318
-rw-r--r--src/radeon_dri2.h42
-rw-r--r--src/radeon_driver.c13
-rw-r--r--src/radeon_exa.c7
-rw-r--r--src/radeon_exa_funcs.c5
-rw-r--r--src/radeon_kms.c837
-rw-r--r--src/radeon_legacy_memory.c22
-rw-r--r--src/radeon_probe.c71
-rw-r--r--src/radeon_probe.h11
17 files changed, 2498 insertions, 33 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 1864f96e..421d1636 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -26,7 +26,7 @@
# _ladir passes a dummy rpath to libtool so the thing will actually link
# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
-radeon_drv_la_LIBADD =
+radeon_drv_la_LIBADD = $(LIBDRM_RADEON_LIBS)
if DRI
RADEON_DRI_SRCS = radeon_dri.c
@@ -65,6 +65,10 @@ XMODE_SRCS=\
modes/xf86Rotate.c \
modes/xf86DiDGA.c
+if XF86DRM_MODE
+RADEON_KMS_SRCS=radeon_dri2.c radeon_kms.c drmmode_display.c
+endif
+
if USE_EXA
RADEON_EXA_SOURCES = radeon_exa.c r600_exa.c r6xx_accel.c r600_textured_videofuncs.c r600_shader.c
endif
@@ -95,7 +99,8 @@ radeon_drv_la_SOURCES = \
radeon_textured_video.c radeon_pm.c \
radeon_crtc.c radeon_output.c radeon_modes.c radeon_tv.c \
$(RADEON_ATOMBIOS_SOURCES) radeon_atombios.c radeon_atomwrapper.c \
- $(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) atombios_output.c atombios_crtc.c
+ $(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) atombios_output.c atombios_crtc.c \
+ $(RADEON_KMS_SRCS)
if XMODES
radeon_drv_la_SOURCES += \
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
new file mode 100644
index 00000000..644727dc
--- /dev/null
+++ b/src/drmmode_display.c
@@ -0,0 +1,1035 @@
+/*
+ * Copyright © 2007 Red Hat, Inc.
+ *
+ * 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.
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef XF86DRM_MODE
+#include <sys/ioctl.h>
+#include "micmap.h"
+#include "xf86cmap.h"
+#include "radeon.h"
+#include "radeon_reg.h"
+#include "radeon_drm.h"
+#include "sarea.h"
+
+#include "drmmode_display.h"
+
+/* DPMS */
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
+
+static void
+drmmode_ConvertFromKMode(ScrnInfoPtr scrn,
+ drmModeModeInfo *kmode,
+ DisplayModePtr mode)
+{
+ memset(mode, 0, sizeof(DisplayModeRec));
+ mode->status = MODE_OK;
+
+ mode->Clock = kmode->clock;
+
+ mode->HDisplay = kmode->hdisplay;
+ mode->HSyncStart = kmode->hsync_start;
+ mode->HSyncEnd = kmode->hsync_end;
+ mode->HTotal = kmode->htotal;
+ mode->HSkew = kmode->hskew;
+
+ mode->VDisplay = kmode->vdisplay;
+ mode->VSyncStart = kmode->vsync_start;
+ mode->VSyncEnd = kmode->vsync_end;
+ mode->VTotal = kmode->vtotal;
+ mode->VScan = kmode->vscan;
+
+ mode->Flags = kmode->flags; //& FLAG_BITS;
+ mode->name = strdup(kmode->name);
+
+ if (kmode->type & DRM_MODE_TYPE_DRIVER)
+ mode->type = M_T_DRIVER;
+ if (kmode->type & DRM_MODE_TYPE_PREFERRED)
+ mode->type |= M_T_PREFERRED;
+ xf86SetModeCrtc (mode, scrn->adjustFlags);
+}
+
+static void
+drmmode_ConvertToKMode(ScrnInfoPtr scrn,
+ drmModeModeInfo *kmode,
+ DisplayModePtr mode)
+{
+ memset(kmode, 0, sizeof(*kmode));
+
+ kmode->clock = mode->Clock;
+ kmode->hdisplay = mode->HDisplay;
+ kmode->hsync_start = mode->HSyncStart;
+ kmode->hsync_end = mode->HSyncEnd;
+ kmode->htotal = mode->HTotal;
+ kmode->hskew = mode->HSkew;
+
+ kmode->vdisplay = mode->VDisplay;
+ kmode->vsync_start = mode->VSyncStart;
+ kmode->vsync_end = mode->VSyncEnd;
+ kmode->vtotal = mode->VTotal;
+ kmode->vscan = mode->VScan;
+
+ kmode->flags = mode->Flags; //& FLAG_BITS;
+ if (mode->name)
+ strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
+ kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
+
+}
+
+static void
+drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
+{
+#if 0
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+// drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+// drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+ /* bonghits in the randr 1.2 - uses dpms to disable crtc - bad buzz */
+ if (mode == DPMSModeOff) {
+// drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+// 0, 0, 0, NULL, 0, NULL);
+ }
+#endif
+}
+
+static PixmapPtr
+create_pixmap_for_fbcon(drmmode_ptr drmmode,
+ ScrnInfoPtr pScrn, int crtc_id)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ drmmode_crtc_private_ptr drmmode_crtc;
+ ScreenPtr pScreen = pScrn->pScreen;
+ PixmapPtr pixmap;
+ struct radeon_bo *bo;
+ drmModeFBPtr fbcon;
+ struct drm_gem_flink flink;
+
+ drmmode_crtc = xf86_config->crtc[crtc_id]->driver_private;
+
+ fbcon = drmModeGetFB(drmmode->fd, drmmode_crtc->mode_crtc->buffer_id);
+ if (fbcon == NULL)
+ return NULL;
+
+ flink.handle = fbcon->handle;
+ if (ioctl(drmmode->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Couldn't flink fbcon handle\n");
+ return NULL;
+ }
+
+ bo = radeon_bo_open(drmmode->bufmgr, flink.name, 0, 0, 0, 0);
+ if (bo == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Couldn't allocate bo for fbcon handle\n");
+ return NULL;
+ }
+
+ pixmap = GetScratchPixmapHeader(pScreen,
+ fbcon->width, fbcon->height,
+ fbcon->depth, fbcon->bpp,
+ fbcon->pitch, NULL);
+ if (pixmap == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Couldn't allocate pixmap fbcon contents\n");
+ return NULL;
+ }
+
+ radeon_set_pixmap_bo(pixmap, bo);
+
+ radeon_bo_unref(bo);
+ drmModeFreeFB(fbcon);
+ return pixmap;
+}
+
+void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ PixmapPtr src, dst;
+ ScreenPtr pScreen = pScrn->pScreen;
+ int crtc_id = 0;
+ int i;
+ int pitch = pScrn->displayWidth * info->CurrentLayout.pixel_bytes;
+
+ if (info->ChipFamily >= CHIP_FAMILY_R600)
+ return;
+
+ for (i = 0; i < xf86_config->num_crtc; i++) {
+ xf86CrtcPtr crtc = xf86_config->crtc[i];
+ drmmode_crtc_private_ptr drmmode_crtc;
+
+ drmmode_crtc = crtc->driver_private;
+ if (drmmode_crtc->mode_crtc->buffer_id)
+ crtc_id = i;
+ }
+
+ src = create_pixmap_for_fbcon(drmmode, pScrn, crtc_id);
+ if (!src)
+ return;
+
+ dst = GetScratchPixmapHeader(pScreen,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->depth, pScrn->bitsPerPixel,
+ pitch, NULL);
+ radeon_set_pixmap_bo(dst, info->front_bo);
+ info->accel_state->exa->PrepareCopy (src, dst,
+ -1, -1, GXcopy, FB_ALLONES);
+ info->accel_state->exa->Copy (dst, 0, 0, 0, 0,
+ pScrn->virtualX, pScrn->virtualY);
+ info->accel_state->exa->DoneCopy (dst);
+ radeon_cs_flush_indirect(pScrn);
+
+ (*pScreen->DestroyPixmap)(dst);
+ (*pScreen->DestroyPixmap)(src);
+
+}
+
+static Bool
+drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
+ Rotation rotation, int x, int y)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+ int saved_x, saved_y;
+ Rotation saved_rotation;
+ DisplayModeRec saved_mode;
+ uint32_t *output_ids;
+ int output_count = 0;
+ Bool ret = TRUE;
+ int i;
+ int fb_id;
+ drmModeModeInfo kmode;
+ int pitch = pScrn->displayWidth * info->CurrentLayout.pixel_bytes;
+
+ if (drmmode->fb_id == 0) {
+ ret = drmModeAddFB(drmmode->fd,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->depth, pScrn->bitsPerPixel,
+ pitch,
+ info->front_bo->handle,
+ &drmmode->fb_id);
+ if (ret < 0) {
+ ErrorF("failed to add fb\n");
+ return FALSE;
+ }
+ }
+
+ saved_mode = crtc->mode;
+ saved_x = crtc->x;
+ saved_y = crtc->y;
+ saved_rotation = crtc->rotation;
+
+ if (mode) {
+ crtc->mode = *mode;
+ crtc->x = x;
+ crtc->y = y;
+ crtc->rotation = rotation;
+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,5,99,0,0)
+ crtc->transformPresent = FALSE;
+#endif
+ }
+
+ output_ids = xcalloc(sizeof(uint32_t), xf86_config->num_output);
+ if (!output_ids) {
+ ret = FALSE;
+ goto done;
+ }
+
+ if (mode) {
+ for (i = 0; i < xf86_config->num_output; i++) {
+ xf86OutputPtr output = xf86_config->output[i];
+ drmmode_output_private_ptr drmmode_output;
+
+ if (output->crtc != crtc)
+ continue;
+
+ drmmode_output = output->driver_private;
+ output_ids[output_count] = drmmode_output->mode_output->connector_id;
+ output_count++;
+ }
+
+ if (!xf86CrtcRotate(crtc)) {
+ goto done;
+ }
+
+ drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
+
+ fb_id = drmmode->fb_id;
+ if (drmmode_crtc->rotate_fb_id) {
+ fb_id = drmmode_crtc->rotate_fb_id;
+ x = y = 0;
+ }
+ ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+ fb_id, x, y, output_ids, output_count, &kmode);
+ if (ret)
+ xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
+ "failed to set mode: %s", strerror(-ret));
+ else
+ ret = TRUE;
+
+ if (crtc->scrn->pScreen)
+ xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen);
+ /* go through all the outputs and force DPMS them back on? */
+ for (i = 0; i < xf86_config->num_output; i++) {
+ xf86OutputPtr output = xf86_config->output[i];
+ drmmode_output_private_ptr drmmode_output;
+
+ if (output->crtc != crtc)
+ continue;
+
+ output->funcs->dpms(output, DPMSModeOn);
+ }
+ }
+
+
+
+done:
+ if (!ret) {
+ crtc->x = saved_x;
+ crtc->y = saved_y;
+ crtc->rotation = saved_rotation;
+ crtc->mode = saved_mode;
+ }
+ return ret;
+}
+
+static void
+drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
+{
+
+}
+
+static void
+drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+ drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y);
+}
+
+static void
+drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ void *ptr;
+
+ /* cursor should be mapped already */
+ ptr = drmmode_crtc->cursor_bo->ptr;
+
+ memcpy (ptr, image, 64 * 64 * 4);
+
+ return;
+}
+
+
+static void
+drmmode_hide_cursor (xf86CrtcPtr crtc)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+ drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 64, 64);
+
+}
+
+static void
+drmmode_show_cursor (xf86CrtcPtr crtc)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+ uint32_t handle = drmmode_crtc->cursor_bo->handle;
+
+ drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle, 64, 64);
+}
+
+static void *
+drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+ int size;
+ struct radeon_bo *rotate_bo;
+ int ret;
+ unsigned long rotate_pitch;
+
+ width = RADEON_ALIGN(width, 63);
+ rotate_pitch = width * drmmode->cpp;
+
+ size = rotate_pitch * height;
+
+ rotate_bo = radeon_bo_open(drmmode->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ if (rotate_bo == NULL)
+ return NULL;
+
+ radeon_bo_map(rotate_bo, 1);
+
+ ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth,
+ crtc->scrn->bitsPerPixel, rotate_pitch,
+ rotate_bo->handle,
+ &drmmode_crtc->rotate_fb_id);
+ if (ret) {
+ ErrorF("failed to add rotate fb\n");
+ }
+
+ drmmode_crtc->rotate_bo = rotate_bo;
+ return drmmode_crtc->rotate_bo->ptr;
+}
+
+static PixmapPtr
+drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+ unsigned long rotate_pitch;
+ PixmapPtr rotate_pixmap;
+
+ if (!data)
+ data = drmmode_crtc_shadow_allocate (crtc, width, height);
+
+ rotate_pitch = RADEON_ALIGN(width, 63) * drmmode->cpp;
+
+ rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
+ width, height,
+ pScrn->depth,
+ pScrn->bitsPerPixel,
+ rotate_pitch,
+ data);
+
+ if (rotate_pixmap == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Couldn't allocate shadow pixmap for rotated CRTC\n");
+ }
+
+ if (drmmode_crtc->rotate_bo)
+ radeon_set_pixmap_bo(rotate_pixmap, drmmode_crtc->rotate_bo);
+ return rotate_pixmap;
+
+}
+
+static void
+drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+ if (rotate_pixmap)
+ FreeScratchPixmapHeader(rotate_pixmap);
+
+ if (data) {
+ drmModeRmFB(drmmode->fd, drmmode_crtc->rotate_fb_id);
+ drmmode_crtc->rotate_fb_id = 0;
+ radeon_bo_unmap(drmmode_crtc->rotate_bo);
+ radeon_bo_unref(drmmode_crtc->rotate_bo);
+ drmmode_crtc->rotate_bo = NULL;
+ }
+
+}
+
+static void
+drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green,
+ uint16_t *blue, int size)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+ drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+ size, red, green, blue);
+}
+
+static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
+ .dpms = drmmode_crtc_dpms,
+ .set_mode_major = drmmode_set_mode_major,
+ .set_cursor_colors = drmmode_set_cursor_colors,
+ .set_cursor_position = drmmode_set_cursor_position,
+ .show_cursor = drmmode_show_cursor,
+ .hide_cursor = drmmode_hide_cursor,
+ .load_cursor_argb = drmmode_load_cursor_argb,
+
+ .gamma_set = drmmode_crtc_gamma_set,
+ .shadow_create = drmmode_crtc_shadow_create,
+ .shadow_allocate = drmmode_crtc_shadow_allocate,
+ .shadow_destroy = drmmode_crtc_shadow_destroy,
+ .destroy = NULL, /* XXX */
+};
+
+
+static void
+drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
+{
+ xf86CrtcPtr crtc;
+ drmmode_crtc_private_ptr drmmode_crtc;
+
+ crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
+ if (crtc == NULL)
+ return;
+
+ drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
+ drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]);
+ drmmode_crtc->drmmode = drmmode;
+ crtc->driver_private = drmmode_crtc;
+
+ return;
+}
+
+static xf86OutputStatus
+drmmode_output_detect(xf86OutputPtr output)
+{
+ /* go to the hw and retrieve a new output struct */
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+ drmmode_ptr drmmode = drmmode_output->drmmode;
+ xf86OutputStatus status;
+ drmModeFreeConnector(drmmode_output->mode_output);
+
+ drmmode_output->mode_output = drmModeGetConnector(drmmode->fd, drmmode_output->output_id);
+
+ switch (drmmode_output->mode_output->connection) {
+ case DRM_MODE_CONNECTED:
+ status = XF86OutputStatusConnected;
+ break;
+ case DRM_MODE_DISCONNECTED:
+ status = XF86OutputStatusDisconnected;
+ break;
+ default:
+ case DRM_MODE_UNKNOWNCONNECTION:
+ status = XF86OutputStatusUnknown;
+ break;
+ }
+ return status;
+}
+
+static Bool
+drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
+{
+ return MODE_OK;
+}
+
+static DisplayModePtr
+drmmode_output_get_modes(xf86OutputPtr output)
+{
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+ drmModeConnectorPtr koutput = drmmode_output->mode_output;
+ drmmode_ptr drmmode = drmmode_output->drmmode;
+ int i;
+ DisplayModePtr Modes = NULL, Mode;
+ drmModePropertyPtr props;
+
+ /* look for an EDID property */
+ for (i = 0; i < koutput->count_props; i++) {
+ props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
+ if (props && (props->flags & DRM_MODE_PROP_BLOB)) {
+ if (!strcmp(props->name, "EDID")) {
+ if (drmmode_output->edid_blob)
+ drmModeFreePropertyBlob(drmmode_output->edid_blob);
+ drmmode_output->edid_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]);
+ }
+ drmModeFreeProperty(props);
+ }
+ }
+
+ if (drmmode_output->edid_blob)
+ xf86OutputSetEDID(output, xf86InterpretEDID(output->scrn->scrnIndex, drmmode_output->edid_blob->data));
+ else
+ xf86OutputSetEDID(output, xf86InterpretEDID(output->scrn->scrnIndex, NULL));
+
+ /* modes should already be available */
+ for (i = 0; i < koutput->count_modes; i++) {
+ Mode = xnfalloc(sizeof(DisplayModeRec));
+
+ drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode);
+ Modes = xf86ModesAdd(Modes, Mode);
+
+ }
+ return Modes;
+}
+
+static void
+drmmode_output_destroy(xf86OutputPtr output)
+{
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+
+ if (drmmode_output->edid_blob)
+ drmModeFreePropertyBlob(drmmode_output->edid_blob);
+ drmModeFreeConnector(drmmode_output->mode_output);
+ xfree(drmmode_output);
+ output->driver_private = NULL;
+}
+
+static void
+drmmode_output_dpms(xf86OutputPtr output, int mode)
+{
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+ drmModeConnectorPtr koutput = drmmode_output->mode_output;
+ drmmode_ptr drmmode = drmmode_output->drmmode;
+
+ drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
+ drmmode_output->dpms_enum_id, mode);
+ return;
+}
+
+static const xf86OutputFuncsRec drmmode_output_funcs = {
+ .dpms = drmmode_output_dpms,
+#if 0
+
+ .save = drmmode_crt_save,
+ .restore = drmmode_crt_restore,
+ .mode_fixup = drmmode_crt_mode_fixup,
+ .prepare = drmmode_output_prepare,
+ .mode_set = drmmode_crt_mode_set,
+ .commit = drmmode_output_commit,
+#endif
+ .detect = drmmode_output_detect,
+ .mode_valid = drmmode_output_mode_valid,
+
+ .get_modes = drmmode_output_get_modes,
+ .destroy = drmmode_output_destroy
+};
+
+static int subpixel_conv_table[7] = { 0, SubPixelUnknown,
+ SubPixelHorizontalRGB,
+ SubPixelHorizontalBGR,
+ SubPixelVerticalRGB,
+ SubPixelVerticalBGR,
+ SubPixelNone };
+
+const char *output_names[] = { "None",
+ "VGA",
+ "DVI",
+ "DVI",
+ "DVI",
+ "Composite",
+ "TV",
+ "LVDS",
+ "CTV",
+ "DIN",
+ "DP",
+ "HDMI",
+ "HDMI",
+};
+
+static void
+drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
+{
+ xf86OutputPtr output;
+ drmModeConnectorPtr koutput;
+ drmModeEncoderPtr kencoder;
+ drmmode_output_private_ptr drmmode_output;
+ drmModePropertyPtr props;
+ char name[32];
+ int i;
+
+ koutput = drmModeGetConnector(drmmode->fd, drmmode->mode_res->connectors[num]);
+ if (!koutput)
+ return;
+
+ kencoder = drmModeGetEncoder(drmmode->fd, koutput->encoders[0]);
+ if (!kencoder) {
+ drmModeFreeConnector(koutput);
+ return;
+ }
+
+ /* need to do smart conversion here for compat with non-kms ATI driver */
+ if (koutput->connector_type_id == 1) {
+ switch(koutput->connector_type) {
+ case DRM_MODE_CONNECTOR_VGA:
+ case DRM_MODE_CONNECTOR_DVII:
+ case DRM_MODE_CONNECTOR_DVID:
+ case DRM_MODE_CONNECTOR_DVIA:
+ case DRM_MODE_CONNECTOR_HDMIA:
+ case DRM_MODE_CONNECTOR_HDMIB:
+ snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1);
+ break;
+ default:
+ snprintf(name, 32, "%s", output_names[koutput->connector_type]);
+ break;
+ }
+ } else {
+ snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1);
+ }
+
+ output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name);
+ if (!output) {
+ drmModeFreeEncoder(kencoder);
+ drmModeFreeConnector(koutput);
+ return;
+ }
+
+ drmmode_output = xcalloc(sizeof(drmmode_output_private_rec), 1);
+ if (!drmmode_output) {
+ xf86OutputDestroy(output);
+ drmModeFreeConnector(koutput);
+ drmModeFreeEncoder(kencoder);
+ return;
+ }
+
+ drmmode_output->output_id = drmmode->mode_res->connectors[num];
+ drmmode_output->mode_output = koutput;
+ drmmode_output->mode_encoder = kencoder;
+ drmmode_output->drmmode = drmmode;
+ output->mm_width = koutput->mmWidth;
+ output->mm_height = koutput->mmHeight;
+
+ output->subpixel_order = subpixel_conv_table[koutput->subpixel];
+ output->driver_private = drmmode_output;
+
+ output->possible_crtcs = kencoder->possible_crtcs;
+ output->possible_clones = kencoder->possible_clones;
+
+ for (i = 0; i < koutput->count_props; i++) {
+ props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
+ if (props && (props->flags && DRM_MODE_PROP_ENUM)) {
+ if (!strcmp(props->name, "DPMS")) {
+ drmmode_output->dpms_enum_id = koutput->props[i];
+ drmModeFreeProperty(props);
+ break;
+ }
+ drmModeFreeProperty(props);
+ }
+ }
+
+ return;
+}
+
+static Bool
+drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ drmmode_crtc_private_ptr
+ drmmode_crtc = xf86_config->crtc[0]->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ struct radeon_bo *old_front = NULL;
+ Bool ret;
+ ScreenPtr screen = screenInfo.screens[scrn->scrnIndex];
+ uint32_t old_fb_id;
+ int i, pitch, old_width, old_height, old_pitch;
+ int screen_size;
+ int cpp = info->CurrentLayout.pixel_bytes;
+ struct radeon_bo *front_bo;
+
+ if (scrn->virtualX == width && scrn->virtualY == height)
+ return TRUE;
+
+ front_bo = radeon_get_pixmap_bo(screen->GetScreenPixmap(screen));
+ radeon_cs_flush_indirect(scrn);
+
+ if (front_bo)
+ radeon_bo_wait(front_bo);
+
+ pitch = RADEON_ALIGN(width, 63);
+ height = RADEON_ALIGN(height, 16);
+
+ screen_size = pitch * height * cpp;
+
+ xf86DrvMsg(scrn->scrnIndex, X_INFO,
+ "Allocate new frame buffer %dx%d stride %d\n",
+ width, height, pitch);
+
+ old_width = scrn->virtualX;
+ old_height = scrn->virtualY;
+ old_pitch = scrn->displayWidth;
+ old_fb_id = drmmode->fb_id;
+ old_front = info->front_bo;
+
+ scrn->virtualX = width;
+ scrn->virtualY = height;
+ scrn->displayWidth = pitch;
+
+ info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ if (!info->front_bo)
+ goto fail;
+
+ ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth,
+ scrn->bitsPerPixel, pitch * cpp,
+ info->front_bo->handle,
+ &drmmode->fb_id);
+ if (ret)
+ goto fail;
+
+ radeon_set_pixmap_bo(screen->GetScreenPixmap(screen), info->front_bo);
+ screen->ModifyPixmapHeader(screen->GetScreenPixmap(screen),
+ width, height, -1, -1, pitch * cpp, NULL);
+
+ // xf86DrvMsg(scrn->scrnIndex, X_INFO, "New front buffer at 0x%lx\n",
+ // info->front_bo-);
+
+ for (i = 0; i < xf86_config->num_crtc; i++) {
+ xf86CrtcPtr crtc = xf86_config->crtc[i];
+
+ if (!crtc->enabled)
+ continue;
+
+ drmmode_set_mode_major(crtc, &crtc->mode,
+ crtc->rotation, crtc->x, crtc->y);
+ }
+
+ if (old_fb_id)
+ drmModeRmFB(drmmode->fd, old_fb_id);
+ if (old_front)
+ radeon_bo_unref(old_front);
+
+ return TRUE;
+
+ fail:
+ if (info->front_bo)
+ radeon_bo_unref(info->front_bo);
+ info->front_bo = old_front;
+ scrn->virtualX = old_width;
+ scrn->virtualY = old_height;
+ scrn->displayWidth = old_pitch;
+ drmmode->fb_id = old_fb_id;
+
+ return FALSE;
+}
+
+static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
+ drmmode_xf86crtc_resize
+};
+
+
+Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, char *busId, char *driver_name, int cpp, int zaphod_mask)
+{
+ xf86CrtcConfigPtr xf86_config;
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+ int i;
+ Bool ret;
+
+ /* Create a bus Id */
+ /* Low level DRM open */
+ if (!pRADEONEnt->fd) {
+ ret = DRIOpenDRMMaster(pScrn, SAREA_MAX, busId, driver_name);
+ if (!ret) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[dri] DRIGetVersion failed to open the DRM\n"
+ "[dri] Disabling DRI.\n");
+ return FALSE;
+ }
+
+ drmmode->fd = DRIMasterFD(pScrn);
+ pRADEONEnt->fd = drmmode->fd;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ " reusing fd for second head\n");
+ drmmode->fd = pRADEONEnt->fd;
+ }
+ xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
+ xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+
+ drmmode->cpp = cpp;
+ drmmode->mode_res = drmModeGetResources(drmmode->fd);
+ if (!drmmode->mode_res)
+ return FALSE;
+
+ xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width, drmmode->mode_res->max_height);
+ for (i = 0; i < drmmode->mode_res->count_crtcs; i++)
+ if (zaphod_mask & (1 << i))
+ drmmode_crtc_init(pScrn, drmmode, i);
+
+ for (i = 0; i < drmmode->mode_res->count_connectors; i++)
+ if (zaphod_mask & (1 << i))
+ drmmode_output_init(pScrn, drmmode, i);
+
+ xf86InitialConfiguration(pScrn, TRUE);
+
+ return TRUE;
+}
+
+Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo_manager *bufmgr)
+{
+ drmmode->bufmgr = bufmgr;
+ return TRUE;
+}
+
+
+
+void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ xf86CrtcPtr crtc = xf86_config->crtc[id];
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+ drmmode_crtc->cursor_bo = bo;
+}
+
+void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y, int flags)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ xf86OutputPtr output = config->output[config->compat_output];
+ xf86CrtcPtr crtc = output->crtc;
+
+ if (crtc && crtc->enabled) {
+ drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
+ x, y);
+ }
+}
+
+Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int c;
+
+ drmmode_copy_fb(pScrn, drmmode);
+
+ for (c = 0; c < config->num_crtc; c++) {
+ xf86CrtcPtr crtc = config->crtc[c];
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ xf86OutputPtr output = NULL;
+ int o;
+
+ /* Skip disabled CRTCs */
+ if (!crtc->enabled) {
+ drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+ 0, 0, 0, NULL, 0, NULL);
+ continue;
+ }
+
+ if (config->output[config->compat_output]->crtc == crtc)
+ output = config->output[config->compat_output];
+ else
+ {
+ for (o = 0; o < config->num_output; o++)
+ if (config->output[o]->crtc == crtc)
+ {
+ output = config->output[o];
+ break;
+ }
+ }
+ /* paranoia */
+ if (!output)
+ continue;
+
+ /* Mark that we'll need to re-set the mode for sure */
+ memset(&crtc->mode, 0, sizeof(crtc->mode));
+ if (!crtc->desiredMode.CrtcHDisplay)
+ {
+ DisplayModePtr mode = xf86OutputFindClosestMode (output, pScrn->currentMode);
+
+ if (!mode)
+ return FALSE;
+ crtc->desiredMode = *mode;
+ crtc->desiredRotation = RR_Rotate_0;
+ crtc->desiredX = 0;
+ crtc->desiredY = 0;
+ }
+
+ if (!crtc->funcs->set_mode_major(crtc, &crtc->desiredMode, crtc->desiredRotation,
+ crtc->desiredX, crtc->desiredY))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void drmmode_load_palette(ScrnInfoPtr pScrn, int numColors,
+ int *indices, LOCO *colors, VisualPtr pVisual)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ uint16_t lut_r[256], lut_g[256], lut_b[256];
+ int index, j, i;
+ int c;
+
+ for (c = 0; c < xf86_config->num_crtc; c++) {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+ for (i = 0 ; i < 256; i++) {
+ lut_r[i] = drmmode_crtc->lut_r[i] << 6;
+ lut_g[i] = drmmode_crtc->lut_g[i] << 6;
+ lut_b[i] = drmmode_crtc->lut_b[i] << 6;
+ }
+
+ switch(pScrn->depth) {
+ case 15:
+ for (i = 0; i < numColors; i++) {
+ index = indices[i];
+ for (j = 0; j < 8; j++) {
+ lut_r[index * 8 + j] = colors[index].red << 6;
+ lut_g[index * 8 + j] = colors[index].green << 6;
+ lut_b[index * 8 + j] = colors[index].blue << 6;
+ }
+ }
+ break;
+ case 16:
+ for (i = 0; i < numColors; i++) {
+ index = indices[i];
+
+ if (i <= 31) {
+ for (j = 0; j < 8; j++) {
+ lut_r[index * 8 + j] = colors[index].red << 6;
+ lut_b[index * 8 + j] = colors[index].blue << 6;
+ }
+ }
+
+ for (j = 0; j < 4; j++) {
+ lut_g[index * 4 + j] = colors[index].green << 6;
+ }
+ }
+ break;
+ default:
+ for (i = 0; i < numColors; i++) {
+ index = indices[i];
+ lut_r[index] = colors[index].red << 6;
+ lut_g[index] = colors[index].green << 6;
+ lut_b[index] = colors[index].blue << 6;
+ }
+ break;
+ }
+
+ /* Make the change through RandR */
+#ifdef RANDR_12_INTERFACE
+ if (crtc->randr_crtc)
+ RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
+ else
+#endif
+ crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
+ }
+}
+
+Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn)
+{
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "Initializing kms color map\n");
+ if (!miCreateDefColormap(pScreen))
+ return FALSE;
+ /* all radeons support 10 bit CLUTs */
+ if (!xf86HandleColormaps(pScreen, 256, 10,
+ drmmode_load_palette, NULL,
+ CMAP_PALETTED_TRUECOLOR
+#if 0 /* This option messes up text mode! (eich@suse.de) */
+ | CMAP_LOAD_EVEN_IF_OFFSCREEN
+#endif
+ | CMAP_RELOAD_ON_MODE_SWITCH))
+ return FALSE;
+ return TRUE;
+}
+#endif
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
new file mode 100644
index 00000000..b8f921de
--- /dev/null
+++ b/src/drmmode_display.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright © 2007 Red Hat, Inc.
+ *
+ * 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.
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ *
+ */
+#ifndef DRMMODE_DISPLAY_H
+#define DRMMODE_DISPLAY_H
+
+#ifdef XF86DRM_MODE
+
+#include "xf86drmMode.h"
+
+#include "radeon_probe.h"
+
+typedef struct {
+ int fd;
+ int fb_id;
+ drmModeResPtr mode_res;
+ drmModeFBPtr mode_fb;
+ int cpp;
+ struct radeon_bo_manager *bufmgr;
+} drmmode_rec, *drmmode_ptr;
+
+typedef struct {
+
+ drmmode_ptr drmmode;
+ drmModeCrtcPtr mode_crtc;
+ struct radeon_bo *cursor_bo;
+ struct radeon_bo *rotate_bo;
+ int rotate_fb_id;
+ uint16_t lut_r[256], lut_g[256], lut_b[256];
+} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
+
+typedef struct {
+ drmmode_ptr drmmode;
+ int output_id;
+ drmModeConnectorPtr mode_output;
+ drmModeEncoderPtr mode_encoder;
+ drmModePropertyBlobPtr edid_blob;
+ int dpms_enum_id;
+} drmmode_output_private_rec, *drmmode_output_private_ptr;
+
+
+extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, char *busId, char *driver_name, int cpp, int zaphod_mask);
+extern Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo_manager *bufmgr);
+extern void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo);
+void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y, int flags);
+extern Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
+extern void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
+extern Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn);
+#endif
+
+#endif
diff --git a/src/pcidb/parse_pci_ids.pl b/src/pcidb/parse_pci_ids.pl
index a3a8af89..d1900a48 100755
--- a/src/pcidb/parse_pci_ids.pl
+++ b/src/pcidb/parse_pci_ids.pl
@@ -33,7 +33,7 @@ print PCICHIPSET "PciChipsets RADEONPciChipsets[] = {\n";
print PCIDEVICEMATCH "/* This file is autogenerated please do not edit */\n";
print PCIDEVICEMATCH "static const struct pci_id_match radeon_device_match[] = {\n";
print RADEONCHIPINFO "/* This file is autogenerated please do not edit */\n";
-print RADEONCHIPINFO "RADEONCardInfo RADEONCards[] = {\n";
+print RADEONCHIPINFO "static RADEONCardInfo RADEONCards[] = {\n";
while (<CSV>) {
if ($csv->parse($_)) {
my @columns = $csv->fields();
diff --git a/src/radeon.h b/src/radeon.h
index 0dce081a..82136c83 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -89,6 +89,8 @@
#ifdef XF86DRM_MODE
#include "radeon_bo.h"
#include "radeon_cs.h"
+#include "radeon_dri2.h"
+#include "drmmode_display.h"
#else
#include "radeon_dummy_bufmgr.h"
#endif
@@ -857,6 +859,9 @@ typedef struct {
RADEONCardType cardType; /* Current card is a PCI card */
struct radeon_cp *cp;
struct radeon_dri *dri;
+#ifdef XF86DRM_MODE
+ struct radeon_dri2 dri2;
+#endif
#ifdef USE_EXA
Bool accelDFS;
#endif
@@ -972,10 +977,17 @@ typedef struct {
int can_resize;
void (*reemit_current2d)(ScrnInfoPtr pScrn, int op); // emit the current 2D state into the IB
struct radeon_2d_state state_2d;
+ Bool kms_enabled;
+ struct radeon_bo *front_bo;
#ifdef XF86DRM_MODE
struct radeon_bo_manager *bufmgr;
struct radeon_cs_manager *csm;
struct radeon_cs *cs;
+
+ struct radeon_bo *cursor_bo[2];
+ uint64_t vram_size;
+ uint64_t gart_size;
+ drmmode_rec drmmode;
#else
/* fake bool */
Bool cs;
@@ -1163,6 +1175,12 @@ extern void RADEONInitMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
extern void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn,
RADEONSavePtr restore);
+Bool RADEONGetRec(ScrnInfoPtr pScrn);
+void RADEONFreeRec(ScrnInfoPtr pScrn);
+Bool RADEONPreInitVisual(ScrnInfoPtr pScrn);
+Bool RADEONPreInitWeight(ScrnInfoPtr pScrn);
+
+
/* radeon_pm.c */
extern void RADEONPMInit(ScrnInfoPtr pScrn);
extern void RADEONPMBlockHandler(ScrnInfoPtr pScrn);
diff --git a/src/radeon_accel.c b/src/radeon_accel.c
index 5e24683d..79052a15 100644
--- a/src/radeon_accel.c
+++ b/src/radeon_accel.c
@@ -1131,8 +1131,10 @@ void RADEONInit3DEngine(ScrnInfoPtr pScrn)
if (info->directRenderingEnabled) {
drm_radeon_sarea_t *pSAREAPriv;
- pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
- pSAREAPriv->ctx_owner = DRIGetContext(pScrn->pScreen);
+ if (!info->kms_enabled) {
+ pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
+ pSAREAPriv->ctx_owner = DRIGetContext(pScrn->pScreen);
+ }
RADEONInit3DEngineCP(pScrn);
} else
#endif
diff --git a/src/radeon_chipinfo_gen.h b/src/radeon_chipinfo_gen.h
index bffe88ed..641361dd 100644
--- a/src/radeon_chipinfo_gen.h
+++ b/src/radeon_chipinfo_gen.h
@@ -1,5 +1,5 @@
/* This file is autogenerated please do not edit */
-RADEONCardInfo RADEONCards[] = {
+static RADEONCardInfo RADEONCards[] = {
{ 0x3150, CHIP_FAMILY_RV380, 1, 0, 0, 0, 0 },
{ 0x3151, CHIP_FAMILY_RV380, 0, 0, 0, 0, 0 },
{ 0x3152, CHIP_FAMILY_RV380, 1, 0, 0, 0, 0 },
diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c
index 6ea05137..a9471432 100644
--- a/src/radeon_commonfuncs.c
+++ b/src/radeon_commonfuncs.c
@@ -811,6 +811,39 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
}
+#if defined(ACCEL_CP) && defined(XF86DRM_MODE)
+void drmmode_wait_for_vline(ScrnInfoPtr pScrn, PixmapPtr pPix,
+ int crtc, int start, int stop)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ uint32_t offset;
+ drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[crtc]->driver_private;
+ ACCEL_PREAMBLE();
+
+ BEGIN_ACCEL(3);
+
+ if (IS_AVIVO_VARIANT) {
+ uint32_t reg = AVIVO_D1MODE_VLINE_START_END; /* this is just a marker */
+ OUT_ACCEL_REG(reg,
+ ((start << AVIVO_D1MODE_VLINE_START_SHIFT) |
+ (stop << AVIVO_D1MODE_VLINE_END_SHIFT) |
+ AVIVO_D1MODE_VLINE_INV));
+ } else {
+ OUT_ACCEL_REG(RADEON_CRTC_GUI_TRIG_VLINE, /* another placeholder */
+ ((start << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
+ (stop << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT) |
+ RADEON_CRTC_GUI_TRIG_VLINE_INV));
+ }
+ OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_CRTC_VLINE |
+ RADEON_ENG_DISPLAY_SELECT_CRTC0));
+
+ OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_NOP, 0));
+ OUT_RING(drmmode_crtc->mode_crtc->crtc_id);
+ FINISH_ACCEL();
+}
+#endif
+
/* inserts a wait for vline in the command stream */
void FUNC_NAME(RADEONWaitForVLine)(ScrnInfoPtr pScrn, PixmapPtr pPix,
int crtc, int start, int stop)
@@ -829,16 +862,21 @@ void FUNC_NAME(RADEONWaitForVLine)(ScrnInfoPtr pScrn, PixmapPtr pPix,
if (!xf86_config->crtc[crtc]->enabled)
return;
+ if (info->cs) {
+ if (pPix != pScrn->pScreen->GetScreenPixmap(pScrn->pScreen))
+ return;
+ } else {
#ifdef USE_EXA
- if (info->useEXA)
- offset = exaGetPixmapOffset(pPix);
- else
+ if (info->useEXA)
+ offset = exaGetPixmapOffset(pPix);
+ else
#endif
- offset = pPix->devPrivate.ptr - info->FB;
+ offset = pPix->devPrivate.ptr - info->FB;
- /* if drawing to front buffer */
- if (offset != 0)
- return;
+ /* if drawing to front buffer */
+ if (offset != 0)
+ return;
+ }
start = max(start, 0);
stop = min(stop, xf86_config->crtc[crtc]->mode.VDisplay);
@@ -846,6 +884,13 @@ void FUNC_NAME(RADEONWaitForVLine)(ScrnInfoPtr pScrn, PixmapPtr pPix,
if (start > xf86_config->crtc[crtc]->mode.VDisplay)
return;
+#if defined(ACCEL_CP) && defined(XF86DRM_MODE)
+ if (info->kms_enabled) {
+ drmmode_wait_for_vline(pScrn, pPix, crtc, start, stop);
+ return;
+ }
+#endif
+
BEGIN_ACCEL(2);
if (IS_AVIVO_VARIANT) {
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
new file mode 100644
index 00000000..0a30f8fc
--- /dev/null
+++ b/src/radeon_dri2.c
@@ -0,0 +1,318 @@
+/*
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "radeon.h"
+#include "radeon_dri2.h"
+#include "radeon_version.h"
+
+#ifdef RADEON_DRI2
+
+#if DRI2INFOREC_VERSION >= 1
+#define USE_DRI2_1_1_0
+#endif
+
+struct dri2_buffer_priv {
+ PixmapPtr pixmap;
+ unsigned int attachment;
+};
+
+
+#ifndef USE_DRI2_1_1_0
+static DRI2BufferPtr
+radeon_dri2_create_buffers(DrawablePtr drawable,
+ unsigned int *attachments,
+ int count)
+{
+ ScreenPtr pScreen = drawable->pScreen;
+ DRI2BufferPtr buffers;
+ struct dri2_buffer_priv *privates;
+ PixmapPtr pixmap, depth_pixmap;
+ struct radeon_exa_pixmap_priv *driver_priv;
+ int i, r;
+
+ buffers = xcalloc(count, sizeof *buffers);
+ if (buffers == NULL) {
+ return NULL;
+ }
+ privates = xcalloc(count, sizeof(struct dri2_buffer_priv));
+ if (privates == NULL) {
+ xfree(buffers);
+ return NULL;
+ }
+
+ depth_pixmap = NULL;
+ for (i = 0; i < count; i++) {
+ if (attachments[i] == DRI2BufferFrontLeft) {
+ if (drawable->type == DRAWABLE_PIXMAP) {
+ pixmap = (Pixmap*)drawable;
+ } else {
+ pixmap = (*pScreen->GetWindowPixmap)((WindowPtr)drawable);
+ }
+ pixmap->refcnt++;
+ } else if (attachments[i] == DRI2BufferStencil && depth_pixmap) {
+ pixmap = depth_pixmap;
+ pixmap->refcnt++;
+ } else {
+ pixmap = (*pScreen->CreatePixmap)(pScreen,
+ drawable->width,
+ drawable->height,
+ drawable->depth,
+ 0);
+ }
+
+ if (attachments[i] == DRI2BufferDepth) {
+ depth_pixmap = pixmap;
+ }
+ driver_priv = exaGetPixmapDriverPrivate(pixmap);
+ buffers[i].name = radeon_gem_name_bo(driver_priv->bo);
+
+ buffers[i].attachment = attachments[i];
+ buffers[i].pitch = pixmap->devKind;
+ buffers[i].cpp = pixmap->drawable.bitsPerPixel / 8;
+ buffers[i].driverPrivate = &privates[i];
+ buffers[i].flags = 0;
+ privates[i].pixmap = pixmap;
+ privates[i].attachment = attachments[i];
+ }
+ return buffers;
+}
+#else
+static DRI2BufferPtr
+radeon_dri2_create_buffer(DrawablePtr drawable,
+ unsigned int attachment,
+ unsigned int format)
+{
+ ScreenPtr pScreen = drawable->pScreen;
+ DRI2BufferPtr buffers;
+ struct dri2_buffer_priv *privates;
+ PixmapPtr pixmap, depth_pixmap;
+ struct radeon_exa_pixmap_priv *driver_priv;
+ int r;
+
+ buffers = xcalloc(1, sizeof *buffers);
+ if (buffers == NULL) {
+ return NULL;
+ }
+ privates = xcalloc(1, sizeof(struct dri2_buffer_priv));
+ if (privates == NULL) {
+ xfree(buffers);
+ return NULL;
+ }
+
+ depth_pixmap = NULL;
+
+ if (attachment == DRI2BufferFrontLeft) {
+ if (drawable->type == DRAWABLE_PIXMAP) {
+ pixmap = (PixmapPtr)drawable;
+ } else {
+ pixmap = (*pScreen->GetWindowPixmap)((WindowPtr)drawable);
+ }
+ pixmap->refcnt++;
+ } else if (attachment == DRI2BufferStencil && depth_pixmap) {
+ pixmap = depth_pixmap;
+ pixmap->refcnt++;
+ } else {
+ pixmap = (*pScreen->CreatePixmap)(pScreen,
+ drawable->width,
+ drawable->height,
+ (format != 0)?format:drawable->depth,
+ 0);
+ }
+
+ if (attachment == DRI2BufferDepth) {
+ depth_pixmap = pixmap;
+ }
+ driver_priv = exaGetPixmapDriverPrivate(pixmap);
+ buffers->name = radeon_bo_name_bo(driver_priv->bo);
+ buffers->attachment = attachment;
+ buffers->pitch = pixmap->devKind;
+ buffers->cpp = pixmap->drawable.bitsPerPixel / 8;
+ buffers->driverPrivate = privates;
+ buffers->format = format;
+ buffers->flags = 0; /* not tiled */
+ privates->pixmap = pixmap;
+ privates->attachment = attachment;
+
+ return buffers;
+}
+#endif
+
+#ifndef USE_DRI2_1_1_0
+static void
+radeon_dri2_destroy_buffers(DrawablePtr drawable,
+ DRI2BufferPtr buffers,
+ int count)
+{
+ ScreenPtr pScreen = drawable->pScreen;
+ struct dri2_buffer_priv *private;
+ int i;
+
+ for (i = 0; i < count; i++) {
+ private = buffers[i].driverPrivate;
+ (*pScreen->DestroyPixmap)(private->pixmap);
+ }
+ if (buffers) {
+ xfree(buffers[0].driverPrivate);
+ xfree(buffers);
+ }
+}
+#else
+static void
+radeon_dri2_destroy_buffer(DrawablePtr drawable, DRI2BufferPtr buffers)
+{
+ if(buffers)
+ {
+ ScreenPtr pScreen = drawable->pScreen;
+ struct dri2_buffer_priv *private;
+
+ private = buffers->driverPrivate;
+ (*pScreen->DestroyPixmap)(private->pixmap);
+
+ xfree(buffers->driverPrivate);
+ xfree(buffers);
+ }
+}
+#endif
+
+static void
+radeon_dri2_copy_region(DrawablePtr drawable,
+ RegionPtr region,
+ DRI2BufferPtr dest_buffer,
+ DRI2BufferPtr src_buffer)
+{
+ struct dri2_buffer_priv *src_private = src_buffer->driverPrivate;
+ struct dri2_buffer_priv *dst_private = dest_buffer->driverPrivate;
+ ScreenPtr pScreen = drawable->pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ PixmapPtr src_pixmap;
+ PixmapPtr dst_pixmap;
+ RegionPtr copy_clip;
+ GCPtr gc;
+
+ 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);
+ radeon_cs_flush_indirect(pScrn);
+}
+
+Bool
+radeon_dri2_screen_init(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ DRI2InfoRec dri2_info;
+ int fd;
+ char *bus_id;
+ char *tmp_bus_id;
+ int cmp;
+ int i;
+
+ if (!info->useEXA) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI2 requires EXA\n");
+ return FALSE;
+ }
+
+ /* The whole drmOpen thing is a fiasco and we need to find a way
+ * back to just using open(2). For now, however, lets just make
+ * things worse with even more ad hoc directory walking code to
+ * discover the device file name. */
+ bus_id = DRICreatePCIBusID(info->PciInfo);
+ for (i = 0; i < DRM_MAX_MINOR; i++) {
+ sprintf(info->dri2.device_name, DRM_DEV_NAME, DRM_DIR_NAME, i);
+ fd = open(info->dri2.device_name, O_RDWR);
+ if (fd < 0)
+ continue;
+
+ tmp_bus_id = drmGetBusid(fd);
+ close(fd);
+ if (tmp_bus_id == NULL)
+ continue;
+
+ cmp = strcmp(tmp_bus_id, bus_id);
+ drmFree(tmp_bus_id);
+ if (cmp == 0)
+ break;
+ }
+ xfree(bus_id);
+
+ if (i == DRM_MAX_MINOR) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "DRI2: failed to open drm device\n");
+ return FALSE;
+ }
+
+ if ( (info->ChipFamily >= CHIP_FAMILY_R300) ) {
+ dri2_info.driverName = R300_DRIVER_NAME;
+ } else if ( info->ChipFamily >= CHIP_FAMILY_R200 ) {
+ dri2_info.driverName = R200_DRIVER_NAME;
+ } else {
+ dri2_info.driverName = RADEON_DRIVER_NAME;
+ }
+ dri2_info.fd = info->dri2.drm_fd;
+ dri2_info.deviceName = info->dri2.device_name;
+#ifndef USE_DRI2_1_1_0
+ dri2_info.version = 1;
+ dri2_info.CreateBuffers = radeon_dri2_create_buffers;
+ dri2_info.DestroyBuffers = radeon_dri2_destroy_buffers;
+#else
+ dri2_info.version = 2;
+ dri2_info.CreateBuffer = radeon_dri2_create_buffer;
+ dri2_info.DestroyBuffer = radeon_dri2_destroy_buffer;
+#endif
+ dri2_info.CopyRegion = radeon_dri2_copy_region;
+ info->dri2.enabled = DRI2ScreenInit(pScreen, &dri2_info);
+ return info->dri2.enabled;
+}
+
+void radeon_dri2_close_screen(ScreenPtr pScreen)
+{
+ DRI2CloseScreen(pScreen);
+}
+
+#endif
diff --git a/src/radeon_dri2.h b/src/radeon_dri2.h
new file mode 100644
index 00000000..899a6261
--- /dev/null
+++ b/src/radeon_dri2.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2008 Jerome 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.
+ */
+#ifndef RADEON_DRI2_H
+#define RADEON_DRI2_H
+
+struct radeon_dri2 {
+ int drm_fd;
+ Bool enabled;
+ char device_name[64];
+};
+
+#ifdef RADEON_DRI2
+#include "dri2.h"
+Bool radeon_dri2_screen_init(ScreenPtr pScreen);
+void radeon_dri2_close_screen(ScreenPtr pScreen);
+#endif
+
+#endif
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 9a1d4d7f..317612d3 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -340,7 +340,7 @@ RADEONPostInt10Check(ScrnInfoPtr pScrn, void *ptr)
}
/* Allocate our private RADEONInfoRec */
-static Bool RADEONGetRec(ScrnInfoPtr pScrn)
+Bool RADEONGetRec(ScrnInfoPtr pScrn)
{
if (pScrn->driverPrivate) return TRUE;
@@ -349,7 +349,7 @@ static Bool RADEONGetRec(ScrnInfoPtr pScrn)
}
/* Free our private RADEONInfoRec */
-static void RADEONFreeRec(ScrnInfoPtr pScrn)
+void RADEONFreeRec(ScrnInfoPtr pScrn)
{
RADEONInfoPtr info;
int i;
@@ -1251,7 +1251,7 @@ static void RADEONGetClockInfo(ScrnInfoPtr pScrn)
/* This is called by RADEONPreInit to set up the default visual */
-static Bool RADEONPreInitVisual(ScrnInfoPtr pScrn)
+Bool RADEONPreInitVisual(ScrnInfoPtr pScrn)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
@@ -1308,7 +1308,7 @@ static Bool RADEONPreInitVisual(ScrnInfoPtr pScrn)
}
/* This is called by RADEONPreInit to handle all color weight issues */
-static Bool RADEONPreInitWeight(ScrnInfoPtr pScrn)
+Bool RADEONPreInitWeight(ScrnInfoPtr pScrn)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
@@ -2813,6 +2813,7 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
info->IsSecondary = FALSE;
info->IsPrimary = FALSE;
+ info->kms_enabled = FALSE;
info->pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
if (info->pEnt->location.type != BUS_PCI) goto fail;
@@ -5627,7 +5628,7 @@ Bool RADEONEnterVT(int scrnIndex, int flags)
RADEONRestoreSurfaces(pScrn, info->ModeReg);
#ifdef XF86DRI
if (info->directRenderingEnabled) {
- if (info->cardType == CARD_PCIE &&
+ if (info->cardType == CARD_PCIE &&
info->dri->pKernelDRMVersion->version_minor >= 19 &&
info->FbSecureSize) {
#if X_BYTE_ORDER == X_BIG_ENDIAN
@@ -5641,7 +5642,7 @@ Bool RADEONEnterVT(int scrnIndex, int flags)
#if X_BYTE_ORDER == X_BIG_ENDIAN
OUTREG(RADEON_SURFACE_CNTL, sctrl);
#endif
- }
+ }
/* get the DRI back into shape after resume */
RADEONDRISetVBlankInterrupt (pScrn, TRUE);
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 5b20ecab..9444da38 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -344,7 +344,7 @@ static Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index)
/* if we have more refs than just the BO then flush */
if (driver_priv->bo->cref > 1)
- RADEONCPFlushIndirect(pScrn, 0);
+ radeon_cs_flush_indirect(pScrn);
radeon_bo_wait(driver_priv->bo);
@@ -387,7 +387,7 @@ void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align)
return new_priv;
new_priv->bo = radeon_bo_open(info->bufmgr, 0, size,
- align, 0, 0);
+ align, 0, 0);
if (!new_priv->bo) {
xfree(new_priv);
ErrorF("Failed to alloc memory\n");
@@ -404,6 +404,9 @@ static void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv)
RADEONInfoPtr info = RADEONPTR(pScrn);
struct radeon_exa_pixmap_priv *driver_priv = driverPriv;
+ if (!driverPriv)
+ return;
+
radeon_bo_unref(driver_priv->bo);
xfree(driverPriv);
}
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 42a5ebc2..5b723609 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -376,7 +376,7 @@ RADEONUploadToScreenCP(PixmapPtr pDst, int x, int y, int w, int h,
TRACE;
- if (info->cs)
+ if (info->kms_enabled)
return FALSE;
if (bpp < 8)
@@ -454,6 +454,9 @@ RADEONDownloadFromScreenCP(PixmapPtr pSrc, int x, int y, int w, int h,
TRACE;
+ if (info->kms_enabled)
+ return FALSE;
+
/*
* Try to accelerate download. Use an indirect buffer as scratch space,
* blitting the bits to one half while copying them out of the other one and
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
new file mode 100644
index 00000000..9fc66438
--- /dev/null
+++ b/src/radeon_kms.c
@@ -0,0 +1,837 @@
+/*
+ * Copyright © 2009 Red Hat, Inc.
+ *
+ * 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.
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <sys/ioctl.h>
+/* Driver data structures */
+#include "radeon.h"
+#include "radeon_reg.h"
+#include "radeon_probe.h"
+#include "micmap.h"
+
+#include "shadow.h"
+
+#include "atipciids.h"
+
+
+
+#ifdef XF86DRM_MODE
+
+#include "radeon_chipset_gen.h"
+#include "radeon_chipinfo_gen.h"
+
+#define CURSOR_WIDTH 64
+#define CURSOR_HEIGHT 64
+
+#include "radeon_bo_gem.h"
+#include "radeon_cs_gem.h"
+static Bool radeon_setup_kernel_mem(ScreenPtr pScreen);
+
+const OptionInfoRec RADEONOptions_KMS[] = {
+ { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_PAGE_FLIP, "EnablePageFlip", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_ACCEL_DFS, "AccelDFS", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_IGNORE_EDID, "IgnoreEDID", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_COLOR_TILING, "ColorTiling", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_RENDER_ACCEL, "RenderAccel", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_SUBPIXEL_ORDER, "SubPixelOrder", OPTV_ANYSTR, {0}, FALSE },
+ { OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE },
+ { OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_TVSTD, "TVStandard", OPTV_STRING, {0}, FALSE },
+ { OPTION_EXA_VSYNC, "EXAVSync", OPTV_BOOLEAN, {0}, FALSE },
+ { -1, NULL, OPTV_NONE, {0}, FALSE }
+};
+
+extern _X_EXPORT int gRADEONEntityIndex;
+
+static int getRADEONEntityIndex(void)
+{
+ return gRADEONEntityIndex;
+}
+
+static void *
+radeonShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, int mode,
+ CARD32 *size, void *closure)
+{
+ ScrnInfoPtr pScrn = xf86Screens[screen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ int stride;
+
+ stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8;
+ *size = stride;
+
+ return ((uint8_t *)info->front_bo->ptr + row * stride + offset);
+}
+
+static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ PixmapPtr pixmap;
+
+ pScreen->CreateScreenResources = info->CreateScreenResources;
+ if (!(*pScreen->CreateScreenResources)(pScreen))
+ return FALSE;
+ pScreen->CreateScreenResources = RADEONCreateScreenResources_KMS;
+
+ if (info->r600_shadow_fb) {
+ pixmap = pScreen->GetScreenPixmap(pScreen);
+
+ if (!shadowAdd(pScreen, pixmap, shadowUpdatePackedWeak(),
+ radeonShadowWindow, 0, NULL))
+ return FALSE;
+ }
+
+ if (info->dri2.enabled) {
+ if (info->front_bo) {
+ PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen);
+ radeon_set_pixmap_bo(pPix, info->front_bo);
+ }
+ }
+ return TRUE;
+}
+
+static void RADEONBlockHandler_KMS(int i, pointer blockData,
+ pointer pTimeout, pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[i];
+ ScrnInfoPtr pScrn = xf86Screens[i];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ pScreen->BlockHandler = info->BlockHandler;
+ (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
+ pScreen->BlockHandler = RADEONBlockHandler_KMS;
+
+ if (info->VideoTimerCallback)
+ (*info->VideoTimerCallback)(pScrn, currentTime.milliseconds);
+
+ info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
+ radeon_cs_flush_indirect(pScrn);
+}
+
+static Bool RADEONPreInitAccel_KMS(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ if (!(info->accel_state = xcalloc(1, sizeof(struct radeon_accel_state)))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to allocate accel_state rec!\n");
+ return FALSE;
+ }
+ info->accel_state->fifo_slots = 0;
+
+ if (info->ChipFamily >= CHIP_FAMILY_R600) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Using shadowfb for KMS on R600+\n");
+ info->r600_shadow_fb = TRUE;
+ if (!xf86LoadSubModule(pScrn, "shadow"))
+ info->r600_shadow_fb = FALSE;
+ return TRUE;
+ }
+
+
+ if ((info->ChipFamily == CHIP_FAMILY_RS100) ||
+ (info->ChipFamily == CHIP_FAMILY_RS200) ||
+ (info->ChipFamily == CHIP_FAMILY_RS300) ||
+ (info->ChipFamily == CHIP_FAMILY_RS400) ||
+ (info->ChipFamily == CHIP_FAMILY_RS480) ||
+ (info->ChipFamily == CHIP_FAMILY_RS600) ||
+ (info->ChipFamily == CHIP_FAMILY_RS690) ||
+ (info->ChipFamily == CHIP_FAMILY_RS740))
+ info->accel_state->has_tcl = FALSE;
+ else {
+ info->accel_state->has_tcl = TRUE;
+ }
+
+ info->useEXA = TRUE;
+
+ if (info->useEXA) {
+ int errmaj = 0, errmin = 0;
+ info->exaReq.majorversion = EXA_VERSION_MAJOR;
+ info->exaReq.minorversion = EXA_VERSION_MINOR;
+ if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL,
+ &info->exaReq, &errmaj, &errmin)) {
+ LoaderErrorMsg(NULL, "exa", errmaj, errmin);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static Bool RADEONPreInitChipType_KMS(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ uint32_t cmd_stat;
+ int i;
+
+ info->Chipset = PCI_DEV_DEVICE_ID(info->PciInfo);
+ pScrn->chipset = (char *)xf86TokenToString(RADEONChipsets, info->Chipset);
+ if (!pScrn->chipset) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "ChipID 0x%04x is not recognized\n", info->Chipset);
+ return FALSE;
+ }
+
+ if (info->Chipset < 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Chipset \"%s\" is not recognized\n", pScrn->chipset);
+ return FALSE;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Chipset: \"%s\" (ChipID = 0x%04x)\n",
+ pScrn->chipset,
+ info->Chipset);
+
+ for (i = 0; i < sizeof(RADEONCards) / sizeof(RADEONCardInfo); i++) {
+ if (info->Chipset == RADEONCards[i].pci_device_id) {
+ RADEONCardInfo *card = &RADEONCards[i];
+ info->ChipFamily = card->chip_family;
+ info->IsMobility = card->mobility;
+ info->IsIGP = card->igp;
+ break;
+ }
+ }
+
+ info->cardType = CARD_PCI;
+
+ PCI_READ_LONG(info->PciInfo, &cmd_stat, PCI_CMD_STAT_REG);
+ if (cmd_stat & RADEON_CAP_LIST) {
+ uint32_t cap_ptr, cap_id;
+
+ PCI_READ_LONG(info->PciInfo, &cap_ptr, RADEON_CAPABILITIES_PTR_PCI_CONFIG);
+ cap_ptr &= RADEON_CAP_PTR_MASK;
+
+ while(cap_ptr != RADEON_CAP_ID_NULL) {
+ PCI_READ_LONG(info->PciInfo, &cap_id, cap_ptr);
+ if ((cap_id & 0xff)== RADEON_CAP_ID_AGP) {
+ info->cardType = CARD_AGP;
+ break;
+ }
+ if ((cap_id & 0xff)== RADEON_CAP_ID_EXP) {
+ info->cardType = CARD_PCIE;
+ break;
+ }
+ cap_ptr = (cap_id >> 8) & RADEON_CAP_PTR_MASK;
+ }
+ }
+
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s card detected\n",
+ (info->cardType==CARD_PCI) ? "PCI" :
+ (info->cardType==CARD_PCIE) ? "PCIE" : "AGP");
+
+ /* treat PCIE IGP cards as PCI */
+ if (info->cardType == CARD_PCIE && info->IsIGP)
+ info->cardType = CARD_PCI;
+
+ if ((info->ChipFamily >= CHIP_FAMILY_R600) && info->IsIGP)
+ info->cardType = CARD_PCIE;
+
+ /* not sure about gart table requirements */
+ if ((info->ChipFamily == CHIP_FAMILY_RS600) && info->IsIGP)
+ info->cardType = CARD_PCIE;
+
+#ifdef RENDER
+ info->RenderAccel = xf86ReturnOptValBool(info->Options, OPTION_RENDER_ACCEL,
+ info->Chipset != PCI_CHIP_RN50_515E &&
+ info->Chipset != PCI_CHIP_RN50_5969);
+#endif
+ return TRUE;
+}
+
+static Bool radeon_alloc_dri(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ if (!(info->dri = xcalloc(1, sizeof(struct radeon_dri)))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"Unable to allocate dri rec!\n");
+ return FALSE;
+ }
+
+ if (!(info->cp = xcalloc(1, sizeof(struct radeon_cp)))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"Unable to allocate cp rec!\n");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
+{
+ RADEONInfoPtr info;
+ RADEONEntPtr pRADEONEnt;
+ DevUnion* pPriv;
+ int zaphod_mask = 0;
+ char *bus_id;
+ Gamma zeros = { 0.0, 0.0, 0.0 };
+
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "RADEONPreInit_KMS\n");
+ if (pScrn->numEntities != 1) return FALSE;
+ if (!RADEONGetRec(pScrn)) return FALSE;
+
+ info = RADEONPTR(pScrn);
+ info->MMIO = NULL;
+ info->IsSecondary = FALSE;
+ info->IsPrimary = FALSE;
+ info->kms_enabled = TRUE;
+ info->pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
+ if (info->pEnt->location.type != BUS_PCI) goto fail;
+
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
+ getRADEONEntityIndex());
+ pRADEONEnt = pPriv->ptr;
+
+ if(xf86IsEntityShared(pScrn->entityList[0]))
+ {
+ if(xf86IsPrimInitDone(pScrn->entityList[0]))
+ {
+ info->IsSecondary = TRUE;
+ pRADEONEnt->pSecondaryScrn = pScrn;
+ }
+ else
+ {
+ info->IsPrimary = TRUE;
+ xf86SetPrimInitDone(pScrn->entityList[0]);
+ pRADEONEnt->pPrimaryScrn = pScrn;
+ pRADEONEnt->HasSecondary = FALSE;
+ }
+ }
+
+ info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index);
+ pScrn->monitor = pScrn->confScreen->monitor;
+
+ if (!RADEONPreInitVisual(pScrn))
+ goto fail;
+
+ xf86CollectOptions(pScrn, NULL);
+ if (!(info->Options = xalloc(sizeof(RADEONOptions_KMS))))
+ goto fail;
+
+ memcpy(info->Options, RADEONOptions_KMS, sizeof(RADEONOptions_KMS));
+ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options);
+
+ if (!RADEONPreInitWeight(pScrn))
+ goto fail;
+
+ if (!RADEONPreInitChipType_KMS(pScrn))
+ goto fail;
+
+ if (!radeon_alloc_dri(pScrn))
+ return FALSE;
+
+ zaphod_mask = 0xf;
+ if (info->IsPrimary)
+ zaphod_mask = 0xd;
+ if (info->IsSecondary)
+ zaphod_mask = 0x2;
+
+ bus_id = DRICreatePCIBusID(info->PciInfo);
+ if (drmmode_pre_init(pScrn, &info->drmmode, bus_id, "radeon", pScrn->bitsPerPixel / 8, zaphod_mask) == FALSE) {
+ xfree(bus_id);
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Kernel modesetting setup failed\n");
+ goto fail;
+ }
+
+ info->dri->drmFD = info->drmmode.fd;
+ info->dri2.drm_fd = info->drmmode.fd;
+ info->dri2.enabled = FALSE;
+ xfree(bus_id);
+ info->dri->pKernelDRMVersion = drmGetVersion(info->dri->drmFD);
+ if (info->dri->pKernelDRMVersion == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "RADEONDRIGetVersion failed to get the DRM version\n");
+ goto fail;
+ }
+
+ {
+ struct drm_radeon_gem_info mminfo;
+
+ if (!drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_GEM_INFO, &mminfo, sizeof(mminfo)))
+ {
+ info->vram_size = mminfo.vram_visible;
+ info->gart_size = mminfo.gart_size;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "mem size init: gart size :%llx vram size: s:%llx visible:%llx\n",
+ mminfo.gart_size, mminfo.vram_size, mminfo.vram_visible);
+ }
+ }
+
+ if (info->ChipFamily < CHIP_FAMILY_R600) {
+ info->useEXA = TRUE;
+ info->directRenderingEnabled = TRUE;
+ }
+
+ RADEONSetPitch(pScrn);
+
+ /* Set display resolution */
+ xf86SetDpi(pScrn, 0, 0);
+
+ /* Get ScreenInit function */
+ if (!xf86LoadSubModule(pScrn, "fb")) return FALSE;
+
+ if (!xf86SetGamma(pScrn, zeros)) return FALSE;
+
+ if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
+ if (!xf86LoadSubModule(pScrn, "ramdac")) return FALSE;
+ }
+
+ if (!RADEONPreInitAccel_KMS(pScrn)) goto fail;
+
+ if (pScrn->modes == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
+ goto fail;
+ }
+
+ return TRUE;
+ fail:
+ RADEONFreeRec(pScrn);
+ return FALSE;
+
+}
+
+static Bool RADEONCursorInit_KMS(ScreenPtr pScreen)
+{
+ return xf86_cursors_init (pScreen, CURSOR_WIDTH, CURSOR_HEIGHT,
+ (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
+ HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
+ HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
+ HARDWARE_CURSOR_ARGB));
+}
+
+static Bool RADEONSaveScreen_KMS(ScreenPtr pScreen, int mode)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ Bool unblank;
+
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "RADEONSaveScreen(%d)\n", mode);
+
+ unblank = xf86IsUnblank(mode);
+ if (unblank) SetTimeSinceLastInputEvent();
+
+ if ((pScrn != NULL) && pScrn->vtSema) {
+ if (unblank)
+ RADEONUnblank(pScrn);
+ else
+ RADEONBlank(pScrn);
+ }
+ return TRUE;
+}
+
+/* Called at the end of each server generation. Restore the original
+ * text mode, unmap video memory, and unwrap and call the saved
+ * CloseScreen function.
+ */
+static Bool RADEONCloseScreen_KMS(int scrnIndex, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "RADEONCloseScreen\n");
+
+ if (info->accel_state->exa) {
+ exaDriverFini(pScreen);
+ xfree(info->accel_state->exa);
+ info->accel_state->exa = NULL;
+ }
+
+ if (info->cursor) xf86DestroyCursorInfoRec(info->cursor);
+ info->cursor = NULL;
+
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "Disposing DGA\n");
+ if (info->DGAModes) xfree(info->DGAModes);
+ info->DGAModes = NULL;
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "Unmapping memory\n");
+
+ pScrn->vtSema = FALSE;
+ xf86ClearPrimInitDone(info->pEnt->index);
+ pScreen->BlockHandler = info->BlockHandler;
+ pScreen->CloseScreen = info->CloseScreen;
+ return (*pScreen->CloseScreen)(scrnIndex, pScreen);
+}
+
+
+void RADEONFreeScreen_KMS(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "RADEONFreeScreen\n");
+
+ /* when server quits at PreInit, we don't need do this anymore*/
+ if (!info) return;
+
+ RADEONFreeRec(pScrn);
+}
+
+Bool RADEONScreenInit_KMS(int scrnIndex, ScreenPtr pScreen,
+ int argc, char **argv)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ int subPixelOrder = SubPixelUnknown;
+ char* s;
+ void *front_ptr;
+
+ pScrn->fbOffset = 0;
+
+ miClearVisualTypes();
+ if (!miSetVisualTypes(pScrn->depth,
+ miGetDefaultVisualMask(pScrn->depth),
+ pScrn->rgbBits,
+ pScrn->defaultVisual)) return FALSE;
+ miSetPixmapDepths ();
+
+ info->directRenderingEnabled = radeon_dri2_screen_init(pScreen);
+
+ front_ptr = info->FB;
+
+ info->bufmgr = radeon_bo_manager_gem_ctor(info->dri->drmFD);
+ if (!info->bufmgr) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "failed to initialise GEM buffer manager");
+ return FALSE;
+ }
+ drmmode_set_bufmgr(pScrn, &info->drmmode, info->bufmgr);
+
+ info->csm = radeon_cs_manager_gem_ctor(info->dri->drmFD);
+ if (!info->csm) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "failed to initialise command submission manager");
+ return FALSE;
+ }
+
+ info->cs = radeon_cs_create(info->csm, RADEON_BUFFER_SIZE/4);
+ if (!info->cs) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "failed to initialise command submission buffer");
+ return FALSE;
+ }
+
+ radeon_cs_set_limit(info->cs, RADEON_GEM_DOMAIN_GTT, info->gart_size);
+
+ radeon_setup_kernel_mem(pScreen);
+ front_ptr = info->front_bo->ptr;
+
+ if (info->r600_shadow_fb) {
+ info->fb_shadow = xcalloc(1,
+ pScrn->displayWidth * pScrn->virtualY *
+ ((pScrn->bitsPerPixel + 7) >> 3));
+ if (info->fb_shadow == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to allocate shadow framebuffer\n");
+ info->r600_shadow_fb = FALSE;
+ } else {
+ if (!fbScreenInit(pScreen, info->fb_shadow,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
+ pScrn->bitsPerPixel))
+ return FALSE;
+ }
+ }
+
+ if (info->r600_shadow_fb == FALSE) {
+ /* Init fb layer */
+ if (!fbScreenInit(pScreen, front_ptr,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
+ pScrn->bitsPerPixel))
+ return FALSE;
+ }
+
+ xf86SetBlackWhitePixels(pScreen);
+
+ if (pScrn->bitsPerPixel > 8) {
+ VisualPtr visual;
+
+ 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;
+ }
+ }
+ }
+
+ /* Must be after RGB order fixed */
+ fbPictureInit (pScreen, 0, 0);
+
+#ifdef RENDER
+ if ((s = xf86GetOptValString(info->Options, OPTION_SUBPIXEL_ORDER))) {
+ if (strcmp(s, "RGB") == 0) subPixelOrder = SubPixelHorizontalRGB;
+ else if (strcmp(s, "BGR") == 0) subPixelOrder = SubPixelHorizontalBGR;
+ else if (strcmp(s, "NONE") == 0) subPixelOrder = SubPixelNone;
+ PictureSetSubpixelOrder (pScreen, subPixelOrder);
+ }
+#endif
+
+ pScrn->vtSema = TRUE;
+ /* Backing store setup */
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "Initializing backing store\n");
+ miInitializeBackingStore(pScreen);
+ xf86SetBackingStore(pScreen);
+
+
+ if (info->directRenderingEnabled) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Direct rendering disabled\n");
+ }
+
+ if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "Initializing Acceleration\n");
+ if (RADEONAccelInit(pScreen)) {
+ xf86DrvMsg(scrnIndex, X_INFO, "Acceleration enabled\n");
+ info->accelOn = TRUE;
+ } else {
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "Acceleration initialization failed\n");
+ xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
+ info->accelOn = FALSE;
+ }
+ } else {
+ xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
+ info->accelOn = FALSE;
+ }
+
+ /* Init DPMS */
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "Initializing DPMS\n");
+ xf86DPMSInit(pScreen, xf86DPMSSet, 0);
+
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "Initializing Cursor\n");
+
+ /* Set Silken Mouse */
+ xf86SetSilkenMouse(pScreen);
+
+ /* Cursor setup */
+ miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
+
+ if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
+ if (RADEONCursorInit_KMS(pScreen)) {
+ }
+ }
+
+ /* DGA setup */
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "Initializing DGA\n");
+ RADEONDGAInit(pScreen);
+
+ /* Init Xv */
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "Initializing Xv\n");
+ RADEONInitVideo(pScreen);
+
+ if (info->r600_shadow_fb == TRUE) {
+ if (!shadowSetup(pScreen)) {
+ return FALSE;
+ }
+ }
+ pScrn->pScreen = pScreen;
+
+ if (!drmmode_set_desired_modes(pScrn, &info->drmmode))
+ return FALSE;
+
+ /* Provide SaveScreen & wrap BlockHandler and CloseScreen */
+ /* Wrap CloseScreen */
+ info->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = RADEONCloseScreen_KMS;
+ pScreen->SaveScreen = RADEONSaveScreen_KMS;
+ info->BlockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = RADEONBlockHandler_KMS;
+ info->CreateScreenResources = pScreen->CreateScreenResources;
+ pScreen->CreateScreenResources = RADEONCreateScreenResources_KMS;
+
+ if (!xf86CrtcScreenInit (pScreen))
+ return FALSE;
+
+ /* Wrap pointer motion to flip touch screen around */
+// info->PointerMoved = pScrn->PointerMoved;
+// pScrn->PointerMoved = RADEONPointerMoved;
+
+ if (!drmmode_setup_colormap(pScreen, pScrn))
+ return FALSE;
+
+ /* Note unused options */
+ if (serverGeneration == 1)
+ xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
+
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "RADEONScreenInit finished\n");
+
+ return TRUE;
+}
+
+Bool RADEONEnterVT_KMS(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ int ret;
+
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "RADEONEnterVT_KMS\n");
+
+
+ ret = ioctl(info->dri->drmFD, DRM_IOCTL_SET_MASTER, NULL);
+ if (ret == -EINVAL)
+ ErrorF("Unable to retrieve master\n");
+
+ info->accel_state->XInited3D = FALSE;
+ info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
+
+ pScrn->vtSema = TRUE;
+
+ if (!drmmode_set_desired_modes(pScrn, &info->drmmode))
+ return FALSE;
+
+ if (info->adaptor)
+ RADEONResetVideo(pScrn);
+
+ return TRUE;
+}
+
+
+void RADEONLeaveVT_KMS(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "RADEONLeaveVT_KMS\n");
+
+ ioctl(info->dri->drmFD, DRM_IOCTL_DROP_MASTER, NULL);
+
+#ifdef HAVE_FREE_SHADOW
+ xf86RotateFreeShadow(pScrn);
+#endif
+
+ xf86_hide_cursors (pScrn);
+ info->accel_state->XInited3D = FALSE;
+ info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
+
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "Ok, leaving now...\n");
+}
+
+
+Bool RADEONSwitchMode_KMS(int scrnIndex, DisplayModePtr mode, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ Bool ret;
+ ret = xf86SetSingleMode (pScrn, mode, RR_Rotate_0);
+ return ret;
+
+}
+
+void RADEONAdjustFrame_KMS(int scrnIndex, int x, int y, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ drmmode_adjust_frame(pScrn, &info->drmmode, x, y, flags);
+ return;
+}
+
+static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int cpp = info->CurrentLayout.pixel_bytes;
+ int screen_size;
+ int stride = pScrn->displayWidth * cpp;
+ int total_size_bytes = 0, remain_size_bytes;
+ int pagesize = 4096;
+
+ if (info->accel_state->exa != NULL) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map already initialized\n");
+ return FALSE;
+ }
+ info->accel_state->exa = exaDriverAlloc();
+ if (info->accel_state->exa == NULL)
+ return FALSE;
+
+ screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * stride;
+ {
+ int cursor_size = 64 * 4 * 64;
+ int c;
+
+ cursor_size = RADEON_ALIGN(cursor_size, pagesize);
+ for (c = 0; c < xf86_config->num_crtc; c++) {
+ /* cursor objects */
+ info->cursor_bo[c] = radeon_bo_open(info->bufmgr, 0, cursor_size,
+ 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ if (!info->cursor_bo[c]) {
+ return FALSE;
+ }
+
+ if (radeon_bo_map(info->cursor_bo[c], 1)) {
+ ErrorF("Failed to map cursor buffer memory\n");
+ }
+
+ drmmode_set_cursor(pScrn, &info->drmmode, c, info->cursor_bo[c]);
+ total_size_bytes += cursor_size;
+ }
+ }
+
+ screen_size = RADEON_ALIGN(screen_size, pagesize);
+ /* keep area front front buffer - but don't allocate it yet */
+ total_size_bytes += screen_size;
+
+ /* work out from the mm size what the exa / tex sizes need to be */
+ remain_size_bytes = info->vram_size - total_size_bytes;
+
+ info->dri->textureSize = 0;
+
+ info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size,
+ 0, RADEON_GEM_DOMAIN_VRAM, 0);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer size: %dK\n", info->front_bo->size/1024);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Remaining VRAM size (used for pixmaps): %dK\n", remain_size_bytes/1024);
+
+ /* set the emit limit at 90% of VRAM */
+ remain_size_bytes = (remain_size_bytes / 10) * 9;
+
+ radeon_cs_set_limit(info->cs, RADEON_GEM_DOMAIN_VRAM, remain_size_bytes);
+ return TRUE;
+}
+
+#endif
diff --git a/src/radeon_legacy_memory.c b/src/radeon_legacy_memory.c
index 861fd979..02b95edc 100644
--- a/src/radeon_legacy_memory.c
+++ b/src/radeon_legacy_memory.c
@@ -21,6 +21,20 @@ radeon_legacy_allocate_memory(ScrnInfoPtr pScrn,
RADEONInfoPtr info = RADEONPTR(pScrn);
uint32_t offset = 0;
+#ifdef XF86DRM_MODE
+ if (info->cs) {
+ struct radeon_bo *video_bo;
+
+ video_bo = radeon_bo_open(info->bufmgr, 0, size, 4096, 0, 0);
+
+ *mem_struct = video_bo;
+
+ if (!video_bo)
+ return 0;
+
+ return (uint32_t)-1;
+ }
+#endif
#ifdef USE_EXA
if (info->useEXA) {
ExaOffscreenArea *area = *mem_struct;
@@ -94,6 +108,14 @@ radeon_legacy_free_memory(ScrnInfoPtr pScrn,
void *mem_struct)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
+
+#ifdef XF86DRM_MODE
+ if (info->cs) {
+ struct radeon_bo *bo = mem_struct;
+ radeon_bo_unref(bo);
+ return;
+ }
+#endif
#ifdef USE_EXA
ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
diff --git a/src/radeon_probe.c b/src/radeon_probe.c
index 041bab67..38fe0b04 100644
--- a/src/radeon_probe.c
+++ b/src/radeon_probe.c
@@ -36,6 +36,7 @@
* Authors:
* Kevin E. Martin <martin@xfree86.org>
* Rickard E. Faith <faith@valinux.com>
+ * KMS support - Dave Airlie <airlied@redhat.com>
*/
#include "radeon_probe.h"
@@ -76,11 +77,42 @@ RADEONIdentify(int flags)
RADEONChipsets);
}
+
+#ifdef XF86DRM_MODE
+static Bool radeon_kernel_mode_enabled(ScrnInfoPtr pScrn, struct pci_device *pci_dev)
+{
+ char *busIdString;
+ int ret;
+
+ if (!xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
+ "[KMS] No DRICreatePCIBusID symbol, no kernel modesetting.\n");
+ return FALSE;
+ }
+
+ busIdString = DRICreatePCIBusID(pci_dev);
+ ret = drmCheckModesettingSupported(busIdString);
+ xfree(busIdString);
+ if (ret) {
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
+ "[KMS] drm report modesetting isn't supported.\n");
+ return FALSE;
+ }
+
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
+ "[KMS] Kernel modesetting enabled.\n");
+ return TRUE;
+}
+#else
+#define radeon_kernel_mode_enabled(x, y) FALSE
+#endif
+
static Bool
-radeon_get_scrninfo(int entity_num)
+radeon_get_scrninfo(int entity_num, void *pci_dev)
{
ScrnInfoPtr pScrn = NULL;
EntityInfoPtr pEnt;
+ int kms = 0;
pScrn = xf86ConfigPciEntity(pScrn, 0, entity_num, RADEONPciChipsets,
NULL,
@@ -89,6 +121,11 @@ radeon_get_scrninfo(int entity_num)
if (!pScrn)
return FALSE;
+ if (pci_dev) {
+ if (radeon_kernel_mode_enabled(pScrn, pci_dev))
+ kms = 1;
+ }
+
pScrn->driverVersion = RADEON_VERSION_CURRENT;
pScrn->driverName = RADEON_DRIVER_NAME;
pScrn->name = RADEON_NAME;
@@ -97,14 +134,26 @@ radeon_get_scrninfo(int entity_num)
#else
pScrn->Probe = RADEONProbe;
#endif
- pScrn->PreInit = RADEONPreInit;
- pScrn->ScreenInit = RADEONScreenInit;
- pScrn->SwitchMode = RADEONSwitchMode;
- pScrn->AdjustFrame = RADEONAdjustFrame;
- pScrn->EnterVT = RADEONEnterVT;
- pScrn->LeaveVT = RADEONLeaveVT;
- pScrn->FreeScreen = RADEONFreeScreen;
- pScrn->ValidMode = RADEONValidMode;
+
+ if (kms == 1) {
+ pScrn->PreInit = RADEONPreInit_KMS;
+ pScrn->ScreenInit = RADEONScreenInit_KMS;
+ pScrn->SwitchMode = RADEONSwitchMode_KMS;
+ pScrn->AdjustFrame = RADEONAdjustFrame_KMS;
+ pScrn->EnterVT = RADEONEnterVT_KMS;
+ pScrn->LeaveVT = RADEONLeaveVT_KMS;
+ pScrn->FreeScreen = RADEONFreeScreen_KMS;
+ pScrn->ValidMode = RADEONValidMode;
+ } else {
+ pScrn->PreInit = RADEONPreInit;
+ pScrn->ScreenInit = RADEONScreenInit;
+ pScrn->SwitchMode = RADEONSwitchMode;
+ pScrn->AdjustFrame = RADEONAdjustFrame;
+ pScrn->EnterVT = RADEONEnterVT;
+ pScrn->LeaveVT = RADEONLeaveVT;
+ pScrn->FreeScreen = RADEONFreeScreen;
+ pScrn->ValidMode = RADEONValidMode;
+ }
pEnt = xf86GetEntityInfo(entity_num);
@@ -178,7 +227,7 @@ RADEONProbe(DriverPtr drv, int flags)
foundScreen = TRUE;
} else {
for (i = 0; i < numUsed; i++) {
- if (radeon_get_scrninfo(usedChips[i]))
+ if (radeon_get_scrninfo(usedChips[i], NULL))
foundScreen = TRUE;
}
}
@@ -199,7 +248,7 @@ radeon_pci_probe(
intptr_t match_data
)
{
- return radeon_get_scrninfo(entity_num);
+ return radeon_get_scrninfo(entity_num, (void *)device);
}
#endif /* XSERVER_LIBPCIACCESS */
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index 31709e86..9cac15c5 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -615,6 +615,7 @@ typedef struct
RADEONSaveRec SavedReg; /* Original (text) mode */
void *MMIO; /* Map of MMIO region */
+ int fd; /* for sharing across zaphod heads */
} RADEONEntRec, *RADEONEntPtr;
/* radeon_probe.c */
@@ -636,4 +637,14 @@ extern ModeStatus RADEONValidMode(int, DisplayModePtr, Bool, int);
extern const OptionInfoRec *RADEONOptionsWeak(void);
+#ifdef XF86DRM_MODE
+extern Bool RADEONPreInit_KMS(ScrnInfoPtr, int);
+extern Bool RADEONScreenInit_KMS(int, ScreenPtr, int, char **);
+extern Bool RADEONSwitchMode_KMS(int, DisplayModePtr, int);
+extern void RADEONAdjustFrame_KMS(int, int, int, int);
+extern Bool RADEONEnterVT_KMS(int, int);
+extern void RADEONLeaveVT_KMS(int, int);
+extern void RADEONFreeScreen_KMS(int scrnIndex, int flags);
+#endif
+
#endif /* _RADEON_PROBE_H_ */