static Bool TegraScreenInit(SCREEN_INIT_ARGS_DECL) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); TegraPtr tegra = TegraPTR(pScrn); VisualPtr visual; int ret; pScrn->pScreen = pScreen; ret = drmSetMaster(tegra->fd); if (ret) { ErrorF("Unable to set master\n"); return FALSE; } /* HW dependent - FIXME */ pScrn->displayWidth = pScrn->virtualX; if (!drmmode_create_initial_bos(pScrn, &tegra->drmmode)) return FALSE; if (tegra->drmmode.shadow_enable) { tegra->drmmode.shadow_fb = calloc(1, pScrn->displayWidth * pScrn->virtualY * ((pScrn->bitsPerPixel + 7) >> 3)); if (!tegra->drmmode.shadow_fb) tegra->drmmode.shadow_enable = FALSE; }
static Bool TegraCloseScreen(CLOSE_SCREEN_ARGS_DECL) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); TegraPtr tegra = TegraPTR(pScrn); if (tegra->damage) { DamageUnregister(&pScreen->GetScreenPixmap(pScreen)->drawable, tegra->damage); DamageDestroy(tegra->damage); tegra->damage = NULL; } if (tegra->drmmode.shadow_enable) { shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen)); free(tegra->drmmode.shadow_fb); tegra->drmmode.shadow_fb = NULL; } drmmode_uevent_fini(pScrn, &tegra->drmmode); drmmode_free_bos(pScrn, &tegra->drmmode); if (pScrn->vtSema) TegraLeaveVT(VT_FUNC_ARGS); pScreen->CreateScreenResources = tegra->createScreenResources; pScreen->BlockHandler = tegra->BlockHandler; pScrn->vtSema = FALSE; pScreen->CloseScreen = tegra->CloseScreen; return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); }
static void TegraLeaveVT(VT_FUNC_ARGS_DECL) { SCRN_INFO_PTR(arg); TegraPtr tegra = TegraPTR(pScrn); xf86_hide_cursors(pScrn); pScrn->vtSema = FALSE; drmDropMaster(tegra->fd); }
static Bool TegraCreateScreenResources(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); TegraPtr tegra = TegraPTR(pScrn); PixmapPtr rootPixmap; Bool ret; void *pixels; pScreen->CreateScreenResources = tegra->createScreenResources; ret = pScreen->CreateScreenResources(pScreen); pScreen->CreateScreenResources = TegraCreateScreenResources; if (!drmmode_set_desired_modes(pScrn, &tegra->drmmode)) return FALSE; drmmode_uevent_init(pScrn, &tegra->drmmode); if (!tegra->drmmode.want_sw_cursor) drmmode_map_cursor_bos(pScrn, &tegra->drmmode); pixels = drmmode_map_front_bo(&tegra->drmmode); if (!pixels) return FALSE; rootPixmap = pScreen->GetScreenPixmap(pScreen); if (tegra->drmmode.shadow_enable) pixels = tegra->drmmode.shadow_fb; if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, pixels)) FatalError("Couldn't adjust screen pixmap\n"); if (tegra->drmmode.shadow_enable) { if (!shadowAdd(pScreen, rootPixmap, shadowUpdatePackedWeak(), TegraShadowWindow, 0, 0)) return FALSE; } tegra->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE, pScreen, rootPixmap); if (tegra->damage) { DamageRegister(&rootPixmap->drawable, tegra->damage); tegra->dirty_enabled = TRUE; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n"); } else { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to create screen damage record\n"); return FALSE; } return ret; }
static void * TegraShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, int mode, CARD32 *size, void *closure) { ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); TegraPtr tegra = TegraPTR(pScrn); int stride; stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8; *size = stride; return ((uint8_t *)tegra->drmmode.front_bo->ptr + row * stride + offset); }
static void dispatch_dirty_crtc(ScrnInfoPtr scrn, xf86CrtcPtr crtc) { TegraPtr tegra = TegraPTR(scrn); PixmapPtr pixmap = crtc->randr_crtc->scanout_pixmap; TegraPixmapPrivPtr ppriv = TegraGetPixmapPriv(&tegra->drmmode, pixmap); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; DamagePtr damage = drmmode_crtc->slave_damage; int fb_id = ppriv->fb_id; int ret; ret = dispatch_dirty_region(scrn, pixmap, damage, fb_id); if (ret) { } }
static void TegraBlockHandler(BLOCKHANDLER_ARGS_DECL) { SCREEN_PTR(arg); TegraPtr tegra = TegraPTR(xf86ScreenToScrn(pScreen)); pScreen->BlockHandler = tegra->BlockHandler; pScreen->BlockHandler(BLOCKHANDLER_ARGS); pScreen->BlockHandler = TegraBlockHandler; #ifdef TEGRA_OUTPUT_SLAVE_SUPPORT if (pScreen->isGPU) dispatch_slave_dirty(pScreen); else #endif if (tegra->dirty_enabled) dispatch_dirty(pScreen); }
/* * This gets called when gaining control of the VT, and from ScreenInit(). */ static Bool TegraEnterVT(VT_FUNC_ARGS_DECL) { SCRN_INFO_PTR(arg); TegraPtr tegra = TegraPTR(pScrn); pScrn->vtSema = TRUE; if (drmSetMaster(tegra->fd)) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "drmSetMaster failed: %s\n", strerror(errno)); if (!drmmode_set_desired_modes(pScrn, &tegra->drmmode)) return FALSE; return TRUE; }
static Bool TegraSetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle) { ScreenPtr screen = ppix->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); TegraPtr tegra = TegraPTR(scrn); Bool ret; int size = ppix->devKind * ppix->drawable.height; int ihandle = (int)(long)fd_handle; ret = drmmode_SetSlaveBO(ppix, &tegra->drmmode, ihandle, ppix->devKind, size); if (ret == FALSE) return ret; return TRUE; }
void TegraDRI2ScreenInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); TegraPtr tegra = TegraPTR(pScrn); DRI2InfoRec info = { .version = 6, .fd = tegra->fd, .driverName = "tegra", .deviceName = tegra->path, .CreateBuffer = TegraDRI2CreateBuffer, .DestroyBuffer = TegraDRI2DestroyBuffer, .CopyRegion = TegraDRI2CopyRegion, .ScheduleSwap = TegraDRI2ScheduleSwap, .GetMSC = TegraDRI2GetMSC, .ScheduleWaitMSC = TegraDRI2ScheduleWaitMSC, .AuthMagic = drmAuthMagic, }; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "> %s(pScreen=%p)\n", __func__, pScreen); if (xf86LoaderCheckSymbol("DRI2Version")) { int major = 0, minor = 0; DRI2Version(&major, &minor); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DRI2 v%d.%d\n", major, minor); } DRI2ScreenInit(pScreen, &info); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "< %s()\n", __func__); } void TegraDRI2ScreenExit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "> %s(pScreen=%p)\n", __func__, pScreen); DRI2CloseScreen(pScreen); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "< %s()\n", __func__); }
static void dispatch_dirty(ScreenPtr pScreen) { ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); TegraPtr tegra = TegraPTR(scrn); PixmapPtr pixmap = pScreen->GetScreenPixmap(pScreen); int fb_id = tegra->drmmode.fb_id; int ret; ret = dispatch_dirty_region(scrn, pixmap, tegra->damage, fb_id); if (ret == -EINVAL || ret == -ENOSYS) { tegra->dirty_enabled = FALSE; DamageUnregister(&pScreen->GetScreenPixmap(pScreen)->drawable, tegra->damage); DamageDestroy(tegra->damage); tegra->damage = NULL; xf86DrvMsg(scrn->scrnIndex, X_INFO, "Disabling kernel dirty updates, not required.\n"); return; } }
static int dispatch_dirty_region(ScrnInfoPtr scrn, PixmapPtr pixmap, DamagePtr damage, int fb_id) { TegraPtr tegra = TegraPTR(scrn); RegionPtr dirty = DamageRegion(damage); unsigned num_cliprects = REGION_NUM_RECTS(dirty); if (num_cliprects) { drmModeClip *clip = malloc(num_cliprects * sizeof(drmModeClip)); BoxPtr rect = REGION_RECTS(dirty); int i, ret; if (!clip) return -ENOMEM; /* XXX no need for copy? */ for (i = 0; i < num_cliprects; i++, rect++) { clip[i].x1 = rect->x1; clip[i].y1 = rect->y1; clip[i].x2 = rect->x2; clip[i].y2 = rect->y2; } /* TODO query connector property to see if this is needed */ ret = drmModeDirtyFB(tegra->fd, fb_id, clip, num_cliprects); free(clip); DamageEmpty(damage); if (ret) { if (ret == -EINVAL) return ret; } } return 0; }
static Bool TegraPreInit(ScrnInfoPtr pScrn, int flags) { TegraPtr tegra; rgb defaultWeight = { 0, 0, 0 }; EntityInfoPtr pEnt; EntPtr tegraEnt = NULL; Bool prefer_shadow = TRUE; uint64_t value = 0; int ret; int bppflags; int defaultdepth, defaultbpp; Gamma zeros = { 0.0, 0.0, 0.0 }; const char *path; if (pScrn->numEntities != 1) return FALSE; pEnt = xf86GetEntityInfo(pScrn->entityList[0]); if (flags & PROBE_DETECT) return FALSE; /* Allocate driverPrivate */ if (!GetRec(pScrn)) return FALSE; tegra = TegraPTR(pScrn); tegra->pEnt = pEnt; pScrn->displayWidth = 640; /* default it */ /* Allocate an entity private if necessary */ if (xf86IsEntityShared(pScrn->entityList[0])) { tegraEnt = xf86GetEntityPrivate(pScrn->entityList[0], tegraEntityIndex)->ptr; tegra->entityPrivate = tegraEnt; } else tegra->entityPrivate = NULL; if (xf86IsEntityShared(pScrn->entityList[0])) { if (xf86IsPrimInitDone(pScrn->entityList[0])) { /* do something */ } else { xf86SetPrimInitDone(pScrn->entityList[0]); } } pScrn->monitor = pScrn->confScreen->monitor; pScrn->progClock = TRUE; pScrn->rgbBits = 8; switch (pEnt->location.type) { #ifdef XSERVER_PLATFORM_BUS case BUS_PLATFORM: path = xf86_get_platform_device_attrib(pEnt->location.id.plat, ODEV_ATTRIB_PATH); break; #endif default: path = xf86GetOptValString(tegra->pEnt->device->options, OPTION_DEVICE_PATH); break; } tegra->fd = TegraOpenHardware(path); if (tegra->fd < 0) return FALSE; tegra->drmmode.fd = tegra->fd; #ifdef TEGRA_OUTPUT_SLAVE_SUPPORT pScrn->capabilities = 0; #ifdef DRM_CAP_PRIME ret = drmGetCap(tegra->fd, DRM_CAP_PRIME, &value); if (ret == 0) { if (value & DRM_PRIME_CAP_IMPORT) pScrn->capabilities |= RR_Capability_SinkOutput; } #endif #endif drmmode_get_default_bpp(pScrn, &tegra->drmmode, &defaultdepth, &defaultbpp); if (defaultdepth == 24 && defaultbpp == 24) bppflags = Support24bppFb; else bppflags = PreferConvert24to32 | SupportConvert24to32 | Support32bppFb; if (!xf86SetDepthBpp(pScrn, defaultdepth, defaultdepth, defaultbpp, bppflags)) return FALSE; switch (pScrn->depth) { case 15: case 16: case 24: break; default: xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given depth (%d) is not supported by the driver\n", pScrn->depth); return FALSE; } xf86PrintDepthBpp(pScrn); /* Process the options */ xf86CollectOptions(pScrn, NULL); tegra->Options = malloc(sizeof(Options)); if (!tegra->Options) return FALSE; memcpy(tegra->Options, Options, sizeof(Options)); xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, tegra->Options); if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) return FALSE; if (!xf86SetDefaultVisual(pScrn, -1)) return FALSE; if (xf86ReturnOptValBool(tegra->Options, OPTION_SW_CURSOR, FALSE)) tegra->drmmode.want_sw_cursor = TRUE; ret = drmGetCap(tegra->fd, DRM_CAP_DUMB_PREFER_SHADOW, &value); if (!ret) prefer_shadow = !!value; tegra->drmmode.shadow_enable = xf86ReturnOptValBool(tegra->Options, OPTION_SHADOW_FB, prefer_shadow); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ShadowFB: preferred %s, enabled %s\n", prefer_shadow ? "YES" : "NO", tegra->drmmode.shadow_enable ? "YES" : "NO"); if (!drmmode_pre_init(pScrn, &tegra->drmmode, pScrn->bitsPerPixel / 8)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "KMS setup failed\n"); return FALSE; } if (tegra->drmmode.need_sw_cursor) tegra->drmmode.want_sw_cursor = TRUE; /* * If the driver can do gamma correction, it should call xf86SetGamma() here. */ if (!xf86SetGamma(pScrn, zeros)) return FALSE; if (pScrn->modes == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n"); return FALSE; } pScrn->currentMode = pScrn->modes; /* Set display resolution */ xf86SetDpi(pScrn, 0, 0); /* Load the required sub modules */ if (!xf86LoadSubModule(pScrn, "fb")) return FALSE; if (tegra->drmmode.shadow_enable) { if (!xf86LoadSubModule(pScrn, "shadow")) return FALSE; } return TRUE; }