diff options
Diffstat (limited to 'src/radeon_kms.c')
-rw-r--r-- | src/radeon_kms.c | 837 |
1 files changed, 837 insertions, 0 deletions
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 |