diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 9 | ||||
-rw-r--r-- | src/drmmode_display.c | 1035 | ||||
-rw-r--r-- | src/drmmode_display.h | 74 | ||||
-rwxr-xr-x | src/pcidb/parse_pci_ids.pl | 2 | ||||
-rw-r--r-- | src/radeon.h | 18 | ||||
-rw-r--r-- | src/radeon_accel.c | 6 | ||||
-rw-r--r-- | src/radeon_chipinfo_gen.h | 2 | ||||
-rw-r--r-- | src/radeon_commonfuncs.c | 59 | ||||
-rw-r--r-- | src/radeon_dri2.c | 318 | ||||
-rw-r--r-- | src/radeon_dri2.h | 42 | ||||
-rw-r--r-- | src/radeon_driver.c | 13 | ||||
-rw-r--r-- | src/radeon_exa.c | 7 | ||||
-rw-r--r-- | src/radeon_exa_funcs.c | 5 | ||||
-rw-r--r-- | src/radeon_kms.c | 837 | ||||
-rw-r--r-- | src/radeon_legacy_memory.c | 22 | ||||
-rw-r--r-- | src/radeon_probe.c | 71 | ||||
-rw-r--r-- | src/radeon_probe.h | 11 |
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_ */ |