From 2e34d11541e1f987c7ca0556592cb16f4d232299 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 10 Jun 2013 13:06:35 +0200 Subject: nouveau: enable support for normal optimus configuration nvd7 has no display engine, only enable sink output capability if there is a crtc. drmmode doesn't work without crtc's, so prevent crashes by skipping the drmmode code in that case. Signed-off-by: Maarten Lankhorst --- src/drmmode_display.c | 40 ++++++++++++++++++++++++++------------ src/nouveau_dri2.c | 3 +++ src/nv_driver.c | 53 +++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 74 insertions(+), 22 deletions(-) diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 6033a6d..8fd1dd0 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -1129,14 +1129,17 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); ScreenPtr screen = xf86ScrnToScreen(scrn); NVPtr pNv = NVPTR(scrn); - drmmode_crtc_private_ptr - drmmode_crtc = xf86_config->crtc[0]->driver_private; - drmmode_ptr drmmode = drmmode_crtc->drmmode; - uint32_t old_width, old_height, old_pitch, old_fb_id; + drmmode_crtc_private_ptr drmmode_crtc = NULL; + drmmode_ptr drmmode = NULL; + uint32_t old_width, old_height, old_pitch, old_fb_id = 0; struct nouveau_bo *old_bo = NULL; int ret, i, pitch; PixmapPtr ppix; + if (xf86_config->num_crtc) { + drmmode_crtc = xf86_config->crtc[0]->driver_private; + drmmode = drmmode_crtc->drmmode; + } ErrorF("resize called %d %d\n", width, height); if (scrn->virtualX == width && scrn->virtualY == height) @@ -1145,7 +1148,8 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) old_width = scrn->virtualX; old_height = scrn->virtualY; old_pitch = scrn->displayWidth; - old_fb_id = drmmode->fb_id; + if (drmmode) + old_fb_id = drmmode->fb_id; nouveau_bo_ref(pNv->scanout, &old_bo); nouveau_bo_ref(NULL, &pNv->scanout); @@ -1162,11 +1166,13 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) nouveau_bo_map(pNv->scanout, NOUVEAU_BO_RDWR, pNv->client); - ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth, - scrn->bitsPerPixel, pitch, pNv->scanout->handle, - &drmmode->fb_id); - if (ret) - goto fail; + if (drmmode) { + ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth, + scrn->bitsPerPixel, pitch, pNv->scanout->handle, + &drmmode->fb_id); + if (ret) + goto fail; + } if (pNv->ShadowPtr) { free(pNv->ShadowPtr); @@ -1214,7 +1220,8 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) scrn->virtualX = old_width; scrn->virtualY = old_height; scrn->displayWidth = old_pitch; - drmmode->fb_id = old_fb_id; + if (drmmode) + drmmode->fb_id = old_fb_id; return FALSE; } @@ -1241,6 +1248,14 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp) xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width, drmmode->mode_res->max_height); + + if (!drmmode->mode_res->count_connectors || + !drmmode->mode_res->count_crtcs) { + drmModeFreeResources(drmmode->mode_res); + xfree(drmmode); + goto done; + } + for (i = 0; i < drmmode->mode_res->count_crtcs; i++) { if (!xf86IsEntityShared(pScrn->entityList[0]) || (pScrn->confScreen->device->screen == i)) @@ -1250,6 +1265,7 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp) for (i = 0; i < drmmode->mode_res->count_connectors; i++) drmmode_output_init(pScrn, drmmode, i); +done: #ifdef NOUVEAU_PIXMAP_SHARING xf86ProviderSetup(pScrn, NULL, "nouveau"); #endif @@ -1280,7 +1296,7 @@ drmmode_remove_fb(ScrnInfoPtr pScrn) drmmode_crtc_private_ptr drmmode_crtc; drmmode_ptr drmmode; - if (config) + if (config && config->num_crtc) crtc = config->crtc[0]; if (!crtc) return; diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index e462a86..5511b36 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -266,6 +266,9 @@ can_exchange(DrawablePtr draw, PixmapPtr dst_pix, PixmapPtr src_pix) NVPtr pNv = NVPTR(scrn); int i; + if (!xf86_config->num_crtc) + return FALSE; + for (i = 0; i < xf86_config->num_crtc; i++) { xf86CrtcPtr crtc = xf86_config->crtc[i]; if (crtc->enabled && crtc->rotatedData) diff --git a/src/nv_driver.c b/src/nv_driver.c index 8a112db..38eddac 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -426,7 +426,7 @@ NVEnterVT(VT_FUNC_ARGS_DECL) if (ret) ErrorF("Unable to get master: %s\n", strerror(errno)); - if (!xf86SetDesiredModes(pScrn)) + if (XF86_CRTC_CONFIG_PTR(pScrn)->num_crtc && !xf86SetDesiredModes(pScrn)) return FALSE; if (pNv->overlayAdaptor && pNv->Architecture != NV_ARCH_04) @@ -559,7 +559,8 @@ NVCloseScreen(CLOSE_SCREEN_ARGS_DECL) ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); NVPtr pNv = NVPTR(pScrn); - drmmode_screen_fini(pScreen); + if (XF86_CRTC_CONFIG_PTR(pScrn)->num_crtc) + drmmode_screen_fini(pScreen); if (!pNv->NoAccel) nouveau_dri2_fini(pScreen); @@ -687,6 +688,7 @@ nouveau_setup_capabilities(ScrnInfoPtr pScrn) { #ifdef NOUVEAU_PIXMAP_SHARING NVPtr pNv = NVPTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); uint64_t value; int ret; @@ -695,8 +697,11 @@ nouveau_setup_capabilities(ScrnInfoPtr pScrn) if (ret == 0) { if (value & DRM_PRIME_CAP_EXPORT) pScrn->capabilities |= RR_Capability_SourceOutput; - if (value & DRM_PRIME_CAP_IMPORT) - pScrn->capabilities |= RR_Capability_SourceOffload | RR_Capability_SinkOutput; + if (value & DRM_PRIME_CAP_IMPORT) { + pScrn->capabilities |= RR_Capability_SourceOffload; + if (xf86_config->num_crtc) + pScrn->capabilities |= RR_Capability_SinkOutput; + } } #endif } @@ -862,8 +867,6 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) NVPreInitFail("\n"); dev = pNv->dev; - nouveau_setup_capabilities(pScrn); - pScrn->chipset = malloc(sizeof(char) * 25); sprintf(pScrn->chipset, "NVIDIA NV%02x", dev->chipset); xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Chipset: \"%s\"\n", pScrn->chipset); @@ -1102,9 +1105,35 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) if (!xf86SetGamma(pScrn, gammazeros)) NVPreInitFail("\n"); - /* No usable mode */ +#ifdef NOUVEAU_PIXMAP_SHARING + /* + * The driver will not work as gpu screen without acceleration enabled. + * To support this usecase modesetting ddx can be used instead. + */ + if (pNv->NoAccel || pNv->ShadowFB) { + /* + * Optimus mode requires acceleration enabled. + * So if no mode is found, or the screen is created + * as a gpu screen the pre init should fail. + */ + if (pScrn->is_gpu || !pScrn->modes) + return FALSE; + } + +#else + /* No usable mode, no optimus config possible */ if (!pScrn->modes) return FALSE; +#endif + + nouveau_setup_capabilities(pScrn); + + if (!pScrn->modes) { + pScrn->modes = xf86ModesAdd(pScrn->modes, + xf86CVTMode(pScrn->display->virtualX, + pScrn->display->virtualY, + 60, 0, 0)); + } /* Set the current mode to the first in the list */ pScrn->currentMode = pScrn->modes; @@ -1389,7 +1418,7 @@ NVScreenInit(SCREEN_INIT_ARGS_DECL) * Initialize HW cursor layer. * Must follow software cursor initialization. */ - if (pNv->HWCursor) { + if (xf86_config->num_crtc && pNv->HWCursor) { ret = drmmode_cursor_init(pScreen); if (ret != TRUE) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, @@ -1444,7 +1473,8 @@ NVScreenInit(SCREEN_INIT_ARGS_DECL) * Initialize colormap layer. * Must follow initialization of the default colormap */ - if (!xf86HandleColormaps(pScreen, 256, 8, NVLoadPalette, + if (xf86_config->num_crtc && + !xf86HandleColormaps(pScreen, 256, 8, NVLoadPalette, NULL, CMAP_PALETTED_TRUECOLOR)) return FALSE; @@ -1452,7 +1482,10 @@ NVScreenInit(SCREEN_INIT_ARGS_DECL) if (serverGeneration == 1) xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); - drmmode_screen_init(pScreen); + if (xf86_config->num_crtc) + drmmode_screen_init(pScreen); + else + pNv->glx_vblank = FALSE; return TRUE; } -- cgit v1.2.1