From 383e3445afd2a37194e5903dcf095d451955869b Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 3 Dec 2013 23:43:50 +0000 Subject: Convert Armada DRM CRTC into a set of library functions Convert much more of the Armada DRM driver to be a set of library Armada independent DRM functions. Signed-off-by: Russell King --- src/armada_drm.c | 839 ++++++++++------------------------------------------ src/armada_drm.h | 58 +--- src/armada_drm_xv.c | 44 +-- src/common_drm.c | 700 ++++++++++++++++++++++++++++++++++++++++++- src/common_drm.h | 74 ++++- src/vivante_utils.h | 1 + 6 files changed, 939 insertions(+), 777 deletions(-) diff --git a/src/armada_drm.c b/src/armada_drm.c index 7f6ff11..c3df7a4 100644 --- a/src/armada_drm.c +++ b/src/armada_drm.c @@ -25,10 +25,6 @@ #include #include -#ifdef HAVE_UDEV -#include -#endif - #include "compat-api.h" #include "vivante.h" #include "vivante_dri2.h" @@ -39,55 +35,37 @@ #define DRM_MODULE_NAME "armada-drm" #define DRM_DEFAULT_BUS_ID NULL +enum { + OPTION_XV_ACCEL, + OPTION_USE_GPU, +}; + const OptionInfoRec armada_drm_options[] = { - { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_XV_ACCEL, "XvAccel", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_USE_GPU, "UseGPU", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_HOTPLUG, "HotPlug", OPTV_BOOLEAN, {0}, TRUE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; static void armada_drm_ModifyScreenPixmap(ScreenPtr pScreen, - struct armada_drm_info *drm, int width, int height, int depth, int bpp, + struct armada_drm_info *arm, int width, int height, int depth, int bpp, struct drm_armada_bo *bo) { PixmapPtr pixmap = pScreen->GetScreenPixmap(pScreen); pScreen->ModifyPixmapHeader(pixmap, width, height, depth, bpp, bo->pitch, bo->ptr); - if (drm->accel) + if (arm->accel) vivante_set_pixmap_bo(pixmap, bo); } -static void drmmode_ConvertToKMode(drmModeModeInfoPtr 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; - if (mode->name) - strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN); - kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0; -} - static struct drm_armada_bo *armada_bo_alloc_framebuffer(ScrnInfoPtr pScrn, int width, int height, int bpp) { - struct armada_drm_info *drm = GET_DRM_INFO(pScrn); + struct armada_drm_info *arm = GET_ARMADA_DRM_INFO(pScrn); struct drm_armada_bo *bo; int ret; - bo = drm_armada_bo_dumb_create(drm->bufmgr, width, height, bpp); + bo = drm_armada_bo_dumb_create(arm->bufmgr, width, height, bpp); if (!bo) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] failed to allocate new bo: %s\n", @@ -113,100 +91,20 @@ static struct drm_armada_bo *armada_bo_alloc_framebuffer(ScrnInfoPtr pScrn, /* * CRTC support */ -static Bool armada_drm_crtc_apply(xf86CrtcPtr crtc, drmModeModeInfoPtr kmode) -{ - ScrnInfoPtr pScrn = crtc->scrn; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - struct armada_crtc_info *drmc = armada_crtc(crtc); - uint32_t fb_id, *output_ids; - int x, y, i, ret, output_num; - - if (!kmode) - kmode = &drmc->kmode; - - output_ids = calloc(xf86_config->num_output, sizeof *output_ids); - if (!output_ids) - return FALSE; - - for (output_num = i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - struct armada_conn_info *conn; - - if (output->crtc == crtc) { - conn = output->driver_private; - output_ids[output_num++] = conn->mode_output->connector_id; - } - } - - if (!xf86CrtcRotate(crtc)) { - ret = FALSE; - goto done; - } - - crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, - crtc->gamma_blue, crtc->gamma_size); - - if (drmc->rotate_fb_id) { - fb_id = drmc->rotate_fb_id; - x = y = 0; - } else { - fb_id = drmc->drm->fb_id; - x = crtc->x; - y = crtc->y; - } - - ret = drmModeSetCrtc(drmc->drm_fd, drmc->mode_crtc->crtc_id, fb_id, - x, y, output_ids, output_num, kmode); - if (ret) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[drm] failed to set mode on crtc %u: %s\n", - drmc->mode_crtc->crtc_id, strerror(errno)); - ret = FALSE; - } else { - ret = TRUE; - - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - - if (output->crtc != crtc) - continue; - - output->funcs->dpms(output, DPMSModeOn); - } - } - - /* Work around stricter checks in X */ - if (pScrn->pScreen && drmc->drm->hw_cursor) - xf86_reload_cursors(pScrn->pScreen); - -done: - free(output_ids); - return ret; -} - -static void armada_drm_crtc_dpms(xf86CrtcPtr crtc, int mode) -{ -} - static Bool armada_drm_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, int x, int y) { ScrnInfoPtr pScrn = crtc->scrn; - struct armada_crtc_info *drmc = armada_crtc(crtc); - struct armada_drm_info *drm = drmc->drm; - drmModeModeInfo kmode; - DisplayModeRec saved_mode; - Rotation saved_rotation; - int ret, saved_x, saved_y; + struct common_drm_info *drm = GET_DRM_INFO(pScrn); + struct armada_drm_info *arm = GET_ARMADA_DRM_INFO(pScrn); if (drm->fb_id == 0) { - ret = drmModeAddFB(drmc->drm_fd, - pScrn->virtualX, pScrn->virtualY, - pScrn->depth, pScrn->bitsPerPixel, - drm->front_bo->pitch, drm->front_bo->handle, - &drm->fb_id); - if (ret < 0) { + if (drmModeAddFB(drm->fd, + pScrn->virtualX, pScrn->virtualY, + pScrn->depth, pScrn->bitsPerPixel, + arm->front_bo->pitch, arm->front_bo->handle, + &drm->fb_id) < 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] failed to add fb: %s\n", strerror(errno)); @@ -214,73 +112,23 @@ armada_drm_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, } } - saved_mode = crtc->mode; - saved_x = crtc->x; - saved_y = crtc->y; - saved_rotation = crtc->rotation; - crtc->mode = *mode; - crtc->x = x; - crtc->y = y; - crtc->rotation = rotation; - - drmmode_ConvertToKMode(&kmode, mode); - - ret = armada_drm_crtc_apply(crtc, &kmode); - if (!ret) { - crtc->mode = saved_mode; - crtc->x = saved_x; - crtc->y = saved_y; - crtc->rotation = saved_rotation; - } else - drmc->kmode = kmode; - return ret; -} - -static void armada_drm_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, - CARD16 *green, CARD16 *blue, int size) -{ - struct armada_crtc_info *drmc = armada_crtc(crtc); - - drmModeCrtcSetGamma(drmc->drm_fd, drmc->mode_crtc->crtc_id, - size, red, green, blue); -} - -static void armada_drm_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y) -{ - struct armada_crtc_info *drmc = armada_crtc(crtc); - - drmModeMoveCursor(drmc->drm_fd, drmc->mode_crtc->crtc_id, x, y); -} - -static void armada_drm_crtc_show_cursor(xf86CrtcPtr crtc) -{ - struct armada_crtc_info *drmc = armada_crtc(crtc); - - drmModeSetCursor(drmc->drm_fd, drmc->mode_crtc->crtc_id, - drmc->cursor_bo->handle, - drmc->cursor_max_width, drmc->cursor_max_height); -} - -static void armada_drm_crtc_hide_cursor(xf86CrtcPtr crtc) -{ - struct armada_crtc_info *drmc = armada_crtc(crtc); - - drmModeSetCursor(drmc->drm_fd, drmc->mode_crtc->crtc_id, 0, 0, 0); + return common_drm_crtc_set_mode_major(crtc, mode, rotation, x, y); } static void armada_drm_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image) { - struct armada_crtc_info *drmc = armada_crtc(crtc); + struct common_crtc_info *drmc = common_crtc(crtc); + struct common_drm_info *drm = GET_DRM_INFO(crtc->scrn); - drm_armada_bo_subdata(drmc->cursor_bo, 0, - drmc->cursor_max_width * - drmc->cursor_max_height * 4, image); + drm_armada_bo_subdata(drmc->cursor_data, 0, + drm->cursor_max_width * + drm->cursor_max_height * 4, image); } static void * armada_drm_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) { - struct armada_crtc_info *drmc = armada_crtc(crtc); + struct common_crtc_info *drmc = common_crtc(crtc); ScrnInfoPtr pScrn = crtc->scrn; struct drm_armada_bo *bo; int ret; @@ -311,31 +159,31 @@ static PixmapPtr armada_drm_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) { - struct armada_crtc_info *drmc = armada_crtc(crtc); - ScrnInfoPtr scrn = crtc->scrn; + ScrnInfoPtr pScrn = crtc->scrn; + struct armada_drm_info *arm = GET_ARMADA_DRM_INFO(pScrn); PixmapPtr rotate_pixmap; struct drm_armada_bo *bo; if (!data) data = armada_drm_crtc_shadow_allocate(crtc, width, height); if (!data) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate shadow pixmap data for rotated CRTC\n"); return NULL; } bo = data; - rotate_pixmap = GetScratchPixmapHeader(scrn->pScreen, width, height, - scrn->depth, scrn->bitsPerPixel, + rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen, width, height, + pScrn->depth, pScrn->bitsPerPixel, bo->pitch, bo->ptr); if (!rotate_pixmap) { - xf86DrvMsg(scrn->scrnIndex, X_ERROR, + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate shadow pixmap for rotated CRTC\n"); return NULL; } - if (drmc->drm->accel) + if (arm->accel) vivante_set_pixmap_bo(rotate_pixmap, bo); return rotate_pixmap; @@ -346,13 +194,13 @@ armada_drm_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rot_pixmap, void *data) { if (rot_pixmap) { - struct armada_drm_info *drm = GET_DRM_INFO(crtc->scrn); - if (drm->accel) + struct armada_drm_info *arm = GET_ARMADA_DRM_INFO(crtc->scrn); + if (arm->accel) vivante_free_pixmap(rot_pixmap); FreeScratchPixmapHeader(rot_pixmap); } if (data) { - struct armada_crtc_info *drmc = armada_crtc(crtc); + struct common_crtc_info *drmc = common_crtc(crtc); drmModeRmFB(drmc->drm_fd, drmc->rotate_fb_id); drmc->rotate_fb_id = 0; @@ -363,12 +211,12 @@ armada_drm_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rot_pixmap, static void armada_drm_crtc_destroy(xf86CrtcPtr crtc) { - struct armada_crtc_info *drmc = armada_crtc(crtc); + struct common_crtc_info *drmc = common_crtc(crtc); - if (drmc->cursor_bo) { + if (drmc->cursor_data) { drmModeSetCursor(drmc->drm_fd, drmc->mode_crtc->crtc_id, 0, 0, 0); - drm_armada_bo_put(drmc->cursor_bo); + drm_armada_bo_put(drmc->cursor_data); } drmModeFreeCrtc(drmc->mode_crtc); @@ -376,12 +224,12 @@ static void armada_drm_crtc_destroy(xf86CrtcPtr crtc) } static const xf86CrtcFuncsRec drm_crtc_funcs = { - .dpms = armada_drm_crtc_dpms, - .gamma_set = armada_drm_crtc_gamma_set, + .dpms = common_drm_crtc_dpms, + .gamma_set = common_drm_crtc_gamma_set, .set_mode_major = armada_drm_crtc_set_mode_major, - .set_cursor_position = armada_drm_crtc_set_cursor_position, - .show_cursor = armada_drm_crtc_show_cursor, - .hide_cursor = armada_drm_crtc_hide_cursor, + .set_cursor_position = common_drm_crtc_set_cursor_position, + .show_cursor = common_drm_crtc_show_cursor, + .hide_cursor = common_drm_crtc_hide_cursor, .load_cursor_argb = armada_drm_crtc_load_cursor_argb, .shadow_create = armada_drm_crtc_shadow_create, .shadow_allocate = armada_drm_crtc_shadow_allocate, @@ -389,52 +237,41 @@ static const xf86CrtcFuncsRec drm_crtc_funcs = { .destroy = armada_drm_crtc_destroy, }; -static Bool -armada_drm_crtc_init(ScrnInfoPtr pScrn, struct armada_drm_info *drm, - unsigned num) +static void armada_drm_crtc_alloc_cursors(ScrnInfoPtr pScrn) { - struct armada_crtc_info *drmc; - xf86CrtcPtr crtc; - uint32_t id; - - id = drm->mode_res->crtcs[num]; - - crtc = xf86CrtcCreate(pScrn, &drm_crtc_funcs); - if (!crtc) - return FALSE; - - drmc = xnfcalloc(1, sizeof *drmc); - if (!drmc) - return FALSE; - - drmc->drm_fd = drm->fd; - drmc->drm = drm; - drmc->num = num; - drmc->cursor_max_width = CURSOR_MAX_WIDTH; - drmc->cursor_max_height = CURSOR_MAX_HEIGHT; - drmc->mode_crtc = drmModeGetCrtc(drmc->drm_fd, id); - crtc->driver_private = drmc; - - /* Test whether hardware cursor is supported */ - if (drmModeSetCursor(drmc->drm_fd, id, 0, 0, 0)) - drm->has_hw_cursor = FALSE; - - drmc->cursor_bo = drm_armada_bo_dumb_create(drm->bufmgr, - drmc->cursor_max_width, - drmc->cursor_max_height, - 32); + struct common_drm_info *drm = GET_DRM_INFO(pScrn); + struct armada_drm_info *arm = GET_ARMADA_DRM_INFO(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; - return TRUE; + for (i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + struct common_crtc_info *drmc = common_crtc(crtc); + struct drm_armada_bo *bo; + + bo = drm_armada_bo_dumb_create(arm->bufmgr, + drm->cursor_max_width, + drm->cursor_max_height, + 32); + + if (bo) { + drmc->cursor_handle = bo->handle; + drmc->cursor_data = bo; + } else { + drm->has_hw_cursor = FALSE; + break; + } + } } static Bool armada_drm_xf86crtc_resize(ScrnInfoPtr pScrn, int width, int height) { ScreenPtr screen = screenInfo.screens[pScrn->scrnIndex]; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - struct armada_drm_info *drm = GET_DRM_INFO(pScrn); + struct common_drm_info *drm = GET_DRM_INFO(pScrn); + struct armada_drm_info *arm = GET_ARMADA_DRM_INFO(pScrn); struct drm_armada_bo *bo, *old_bo; - uint32_t old_fb_id; - int ret, i; + uint32_t fb_id; + int ret, displayWidth; if (pScrn->virtualX == width && pScrn->virtualY == height) return TRUE; @@ -444,10 +281,9 @@ static Bool armada_drm_xf86crtc_resize(ScrnInfoPtr pScrn, int width, int height) if (!bo) return FALSE; - old_fb_id = drm->fb_id; ret = drmModeAddFB(drm->fd, width, height, pScrn->depth, pScrn->bitsPerPixel, - bo->pitch, bo->handle, &drm->fb_id); + bo->pitch, bo->handle, &fb_id); if (ret) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] failed to add fb: %s\n", strerror(errno)); @@ -455,25 +291,14 @@ static Bool armada_drm_xf86crtc_resize(ScrnInfoPtr pScrn, int width, int height) return FALSE; } - /* Okay, now switch everything */ - pScrn->virtualX = width; - pScrn->virtualY = height; - pScrn->displayWidth = bo->pitch / drm->cpp; - old_bo = drm->front_bo; - drm->front_bo = bo; + old_bo = arm->front_bo; + arm->front_bo = bo; - armada_drm_ModifyScreenPixmap(screen, drm, width, height, -1, -1, bo); + armada_drm_ModifyScreenPixmap(screen, arm, width, height, -1, -1, bo); - for (i = 0; i < xf86_config->num_crtc; i++) { - xf86CrtcPtr crtc = xf86_config->crtc[i]; - - if (!crtc->enabled) - continue; - - armada_drm_crtc_apply(crtc, NULL); - } + displayWidth = bo->pitch / arm->cpp; + common_drm_crtc_resize(pScrn, width, height, displayWidth, fb_id); - drmModeRmFB(drm->fd, old_fb_id); drm_armada_bo_put(old_bo); return TRUE; } @@ -482,174 +307,6 @@ static const xf86CrtcConfigFuncsRec armada_drm_config_funcs = { armada_drm_xf86crtc_resize, }; -#ifdef HAVE_UDEV -static void armada_drm_handle_uevent(int fd, pointer data) -{ - ScrnInfoPtr pScrn = data; - struct armada_drm_info *drm = GET_DRM_INFO(pScrn); - struct udev_device *ud; - - ud = udev_monitor_receive_device(drm->udev.monitor); - if (ud) { - dev_t dev = udev_device_get_devnum(ud); - const char *hp = udev_device_get_property_value(ud, "HOTPLUG"); - - if (dev == drm->udev.drm_dev && hp && strtol(hp, NULL, 10) == 1) - RRGetInfo(screenInfo.screens[pScrn->scrnIndex], TRUE); - - udev_device_unref(ud); - } -} - -static Bool armada_drm_udev_init(ScrnInfoPtr pScrn) -{ - struct armada_drm_info *drm = GET_DRM_INFO(pScrn); - struct udev_monitor *udev_mon; - struct udev *udev; - struct stat st; - MessageType from = X_CONFIG; - Bool hotplug; - - if (!xf86GetOptValBool(drm->Options, OPTION_HOTPLUG, &hotplug)) { - from = X_DEFAULT; - hotplug = TRUE; - } - - xf86DrvMsg(pScrn->scrnIndex, from, "hotplug detection %sabled\n", - hotplug ? "en" : "dis"); - if (!hotplug) - return TRUE; - - if (fstat(drm->fd, &st) || !S_ISCHR(st.st_mode)) - return FALSE; - - drm->udev.drm_dev = st.st_rdev; - - udev = udev_new(); - if (!udev) - return FALSE; - - udev_mon = udev_monitor_new_from_netlink(udev, "udev"); - if (!udev_mon) { - udev_unref(udev); - return FALSE; - } - - if (udev_monitor_filter_add_match_subsystem_devtype(udev_mon, - "drm", "drm_minor") || - udev_monitor_enable_receiving(udev_mon)) { - udev_monitor_unref(udev_mon); - udev_unref(udev); - return FALSE; - } - - drm->udev.monitor = udev_mon; - drm->udev.handler = xf86AddGeneralHandler(udev_monitor_get_fd(udev_mon), - armada_drm_handle_uevent, - pScrn); - - return TRUE; -} - -static void armada_drm_udev_fini(ScrnInfoPtr pScrn, struct armada_drm_info *drm) -{ - if (drm->udev.monitor) { - struct udev *udev = udev_monitor_get_udev(drm->udev.monitor); - - xf86RemoveGeneralHandler(drm->udev.handler); - udev_monitor_unref(drm->udev.monitor); - udev_unref(udev); - } -} -#endif - -static void armada_drm_LoadPalette(ScrnInfoPtr pScrn, int num, 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 i, p; - - for (i = 0; i < num; i++) { - int index = indices[i]; - lut_r[index] = colors[index].red << 8; - lut_g[index] = colors[index].green << 8; - lut_b[index] = colors[index].blue << 8; - } - - for (p = 0; p < xf86_config->num_crtc; p++) { - xf86CrtcPtr crtc = xf86_config->crtc[p]; - -#ifdef RANDR_12_INTERFACE - RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b); -#else - crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256); -#endif - } -} - -static void armada_drm_AdjustFrame(ADJUST_FRAME_ARGS_DECL) -{ - SCRN_INFO_PTR(arg); - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - xf86OutputPtr output = config->output[config->compat_output]; - xf86CrtcPtr crtc = output->crtc; - - if (crtc && crtc->enabled) { - int saved_x = crtc->x; - int saved_y = crtc->y; - int ret; - - crtc->x = x; - crtc->y = y; - - ret = crtc->funcs->set_mode_major(crtc, &crtc->mode, - crtc->rotation, x, y); - if (!ret) { - crtc->x = saved_x; - crtc->y = saved_y; - } - } -} - -static Bool armada_drm_EnterVT(VT_FUNC_ARGS_DECL) -{ - SCRN_INFO_PTR(arg); - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - struct armada_drm_info *drm = GET_DRM_INFO(pScrn); - int i; - - if (drmSetMaster(drm->fd)) - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "[drm] set master failed: %s\n", strerror(errno)); - - if (!xf86SetDesiredModes(pScrn)) - return FALSE; - - /* Disable unused CRTCs */ - for (i = 0; i < config->num_crtc; i++) { - xf86CrtcPtr crtc = config->crtc[i]; - struct armada_crtc_info *drmc = armada_crtc(crtc); - if (!crtc->enabled) - drmModeSetCrtc(drm->fd, drmc->mode_crtc->crtc_id, - 0, 0, 0, NULL, 0, NULL); - } - - return TRUE; -} - -static void armada_drm_LeaveVT(VT_FUNC_ARGS_DECL) -{ - SCRN_INFO_PTR(arg); - struct armada_drm_info *drm = GET_DRM_INFO(pScrn); - - xf86RotateFreeShadow(pScrn); - - xf86_hide_cursors(pScrn); - - drmDropMaster(drm->fd); -} - static ModeStatus armada_drm_ValidMode(SCRN_ARG_TYPE arg1, DisplayModePtr mode, Bool verbose, int flags) @@ -667,84 +324,47 @@ armada_drm_ValidMode(SCRN_ARG_TYPE arg1, DisplayModePtr mode, Bool verbose, return MODE_OK; } -static Bool armada_drm_SwitchMode(SWITCH_MODE_ARGS_DECL) -{ - SCRN_INFO_PTR(arg); - - return xf86SetSingleMode(pScrn, mode, RR_Rotate_0); -} - static Bool armada_drm_CloseScreen(CLOSE_SCREEN_ARGS_DECL) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); - struct armada_drm_info *drm = GET_DRM_INFO(pScrn); + struct armada_drm_info *arm = GET_ARMADA_DRM_INFO(pScrn); PixmapPtr pixmap = pScreen->GetScreenPixmap(pScreen); - Bool ret; - -#ifdef HAVE_UDEV - armada_drm_udev_fini(pScrn, drm); -#endif - if (drm->fb_id) { - drmModeRmFB(drm->fd, drm->fb_id); - drm->fb_id = 0; + if (arm->front_bo) { + drm_armada_bo_put(arm->front_bo); + arm->front_bo = NULL; } - if (drm->front_bo) { - drm_armada_bo_put(drm->front_bo); - drm->front_bo = NULL; - } - if (drm->accel) - vivante_free_pixmap(pixmap); - - if (drm->hw_cursor) - xf86_cursors_fini(pScreen); - - pScreen->CloseScreen = drm->CloseScreen; - ret = (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); - if (pScrn->vtSema) - armada_drm_LeaveVT(VT_FUNC_ARGS(0)); + if (arm->accel) + vivante_free_pixmap(pixmap); - pScrn->vtSema = FALSE; + pScreen->CloseScreen = arm->CloseScreen; - return ret; + return pScreen->CloseScreen(CLOSE_SCREEN_ARGS); } static Bool armada_drm_CreateScreenResources(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - struct armada_drm_info *drm = GET_DRM_INFO(pScrn); + struct armada_drm_info *arm = GET_ARMADA_DRM_INFO(pScrn); Bool ret; - pScreen->CreateScreenResources = drm->CreateScreenResources; + pScreen->CreateScreenResources = arm->CreateScreenResources; ret = pScreen->CreateScreenResources(pScreen); if (ret) { - struct drm_armada_bo *bo = drm->front_bo; + struct drm_armada_bo *bo = arm->front_bo; - armada_drm_ModifyScreenPixmap(pScreen, drm, -1, -1, -1, -1, bo); + armada_drm_ModifyScreenPixmap(pScreen, arm, -1, -1, -1, -1, bo); } return ret; } -static void armada_drm_wakeup_handler(pointer data, int err, pointer p) -{ - struct armada_drm_info *drm = data; - fd_set *read_mask = p; - - if (data == NULL || err < 0) - return; - - if (FD_ISSET(drm->fd, read_mask)) - drmHandleEvent(drm->fd, &drm->event_context); -} - -static Bool -armada_drm_ScreenInit(SCREEN_INIT_ARGS_DECL) +static Bool armada_drm_ScreenInit(SCREEN_INIT_ARGS_DECL) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); - struct armada_drm_info *drm = GET_DRM_INFO(pScrn); + struct common_drm_info *drm = GET_DRM_INFO(pScrn); + struct armada_drm_info *arm = GET_ARMADA_DRM_INFO(pScrn); struct drm_armada_bo *bo; - int visuals, preferredCVC; if (drmSetMaster(drm->fd)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, @@ -752,239 +372,70 @@ armada_drm_ScreenInit(SCREEN_INIT_ARGS_DECL) return FALSE; } - drm->accel = xf86ReturnOptValBool(drm->Options, OPTION_USE_GPU, TRUE); + arm->accel = xf86ReturnOptValBool(arm->Options, OPTION_USE_GPU, TRUE); bo = armada_bo_alloc_framebuffer(pScrn, pScrn->virtualX, pScrn->virtualY, pScrn->bitsPerPixel); if (!bo) return FALSE; - drm->front_bo = bo; - pScrn->displayWidth = bo->pitch / drm->cpp; + arm->front_bo = bo; + pScrn->displayWidth = bo->pitch / arm->cpp; - miClearVisualTypes(); - if (pScrn->bitsPerPixel > 8) { - visuals = TrueColorMask; - preferredCVC = TrueColor; - } else { - visuals = miGetDefaultVisualMask(pScrn->depth); - preferredCVC = pScrn->defaultVisual; - } - - if (!miSetVisualTypes(pScrn->depth, visuals, pScrn->rgbBits, preferredCVC)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[drm] failed to set visual types for %d bpp depth %d\n", - pScrn->bitsPerPixel, pScrn->depth); + if (!common_drm_PreScreenInit(pScreen)) return FALSE; - } - - if (!miSetPixmapDepths()) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[drm] failed to set pixmap depths\n"); - return FALSE; - } - - if (!fbScreenInit(pScreen, NULL, pScrn->virtualX, pScrn->virtualY, - pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, - pScrn->bitsPerPixel)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[drm] fbScreenInit failed\n"); - return FALSE; - } - - if (pScrn->bitsPerPixel > 8) { - /* Fixup RGB ordering */ - VisualPtr 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; - } - } - } - - if (!fbPictureInit(pScreen, NULL, 0)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[drm] fbPictureInit failed\n"); - return FALSE; - } - - xf86SetBlackWhitePixels(pScreen); - - if (drm->accel && !vivante_ScreenInit(pScreen, drm->bufmgr)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "[drm] Vivante initialization failed, running unaccelerated\n"); - drm->accel = FALSE; - } - - xf86SetBackingStore(pScreen); - xf86SetSilkenMouse(pScreen); - - /* software cursor */ - miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); - - drm->hw_cursor = xf86ReturnOptValBool(drm->Options, OPTION_HW_CURSOR, - drm->has_hw_cursor); - if (drm->hw_cursor && !drm->has_hw_cursor) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No hardware cursor support - disabling hardware cursors\n"); - drm->hw_cursor = FALSE; - } - if (drm->hw_cursor && - xf86_cursors_init(pScreen, - CURSOR_MAX_WIDTH, CURSOR_MAX_HEIGHT, - HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | - HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | - HARDWARE_CURSOR_INVERT_MASK | - HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | - HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | - HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | - HARDWARE_CURSOR_UPDATE_UNHIDDEN | - HARDWARE_CURSOR_ARGB)) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using hardware cursors\n"); - } else { - drm->hw_cursor = FALSE; - } - pScreen->SaveScreen = xf86SaveScreen; - drm->CloseScreen = pScreen->CloseScreen; + arm->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = armada_drm_CloseScreen; - drm->CreateScreenResources = pScreen->CreateScreenResources; + arm->CreateScreenResources = pScreen->CreateScreenResources; pScreen->CreateScreenResources = armada_drm_CreateScreenResources; - if (!xf86CrtcScreenInit(pScreen)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[drm] failed to initialize screen\n"); - return FALSE; + if (arm->accel && !vivante_ScreenInit(pScreen, arm->bufmgr)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "[drm] Vivante initialization failed, running unaccelerated\n"); + arm->accel = FALSE; } - if (!miCreateDefColormap(pScreen)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[drm] failed to initialize default colormap\n"); + if (!common_drm_PostScreenInit(pScreen)) return FALSE; - } - if (!xf86HandleColormaps(pScreen, 256, 8, armada_drm_LoadPalette, NULL, - CMAP_RELOAD_ON_MODE_SWITCH | - CMAP_PALETTED_TRUECOLOR)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[drm] failed to initialize colormap handler\n"); - return FALSE; - } - - xf86DPMSInit(pScreen, xf86DPMSSet, 0); - - if (xf86ReturnOptValBool(drm->Options, OPTION_XV_ACCEL, TRUE)) + if (xf86ReturnOptValBool(arm->Options, OPTION_XV_ACCEL, TRUE)) armada_drm_XvInit(pScrn); - /* Setup the synchronisation feedback */ - AddGeneralSocket(drm->fd); - RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, - armada_drm_wakeup_handler, drm); - -#ifdef HAVE_UDEV - if (!armada_drm_udev_init(pScrn)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[drm] failed to connect with udev: %s\n", - strerror(errno)); - return FALSE; - } -#endif - pScrn->vtSema = TRUE; - return armada_drm_EnterVT(VT_FUNC_ARGS(0)); + return common_drm_EnterVT(VT_FUNC_ARGS(0)); } static Bool armada_drm_pre_init(ScrnInfoPtr pScrn) { - struct armada_drm_info *drm = GET_DRM_INFO(pScrn); - drmVersionPtr version; - Gamma zeros = { 0.0, 0.0, 0.0 }; - int i; + struct armada_drm_info *arm = GET_ARMADA_DRM_INFO(pScrn); xf86CollectOptions(pScrn, NULL); - drm->Options = malloc(sizeof(armada_drm_options)); - if (!drm->Options) + arm->Options = malloc(sizeof(armada_drm_options)); + if (!arm->Options) return FALSE; - memcpy(drm->Options, armada_drm_options, sizeof(armada_drm_options)); - xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, drm->Options); - - version = drmGetVersion(drm->fd); - if (version) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "hardware: %s\n", - version->name); - drmFreeVersion(version); - } + memcpy(arm->Options, armada_drm_options, sizeof(armada_drm_options)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, arm->Options); - drm->cpp = (pScrn->bitsPerPixel + 7) / 8; + arm->cpp = (pScrn->bitsPerPixel + 7) / 8; xf86CrtcConfigInit(pScrn, &armada_drm_config_funcs); - drm->mode_res = drmModeGetResources(drm->fd); - if (!drm->mode_res) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "failed to get resources: %s\n", strerror(errno)); + if (!common_drm_init_mode_resources(pScrn, &drm_crtc_funcs)) return FALSE; - } - - xf86CrtcSetSizeRange(pScrn, drm->mode_res->min_width, - drm->mode_res->min_height, - drm->mode_res->max_width, - drm->mode_res->max_height); - - drm->has_hw_cursor = TRUE; - for (i = 0; i < drm->mode_res->count_crtcs; i++) - if (!armada_drm_crtc_init(pScrn, drm, i)) - return FALSE; - - for (i = 0; i < drm->mode_res->count_connectors; i++) - common_drm_conn_init(pScrn, drm->fd, - drm->mode_res->connectors[i]); - xf86InitialConfiguration(pScrn, TRUE); - - /* Limit the maximum framebuffer size to 16MB */ - pScrn->videoRam = 16 * 1048576; - - drm->event_context.version = DRM_EVENT_CONTEXT_VERSION; -#ifdef HAVE_DRI2 - drm->event_context.vblank_handler = vivante_dri2_vblank; -#else - drm->event_context.vblank_handler = NULL; -#endif - drm->event_context.page_flip_handler = NULL; - - 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); - - if (!xf86LoadSubModule(pScrn, "fb")) - return FALSE; + armada_drm_crtc_alloc_cursors(pScrn); return TRUE; } -static int armada_get_cap(struct armada_drm_info *drm, uint64_t cap, - uint64_t *val, int scrnIndex, const char *name) +static int armada_get_cap(int fd, uint64_t cap, uint64_t *val, int scrnIndex, + const char *name) { int err; - err = drmGetCap(drm->fd, cap, val); + err = drmGetCap(fd, cap, val); if (err) xf86DrvMsg(scrnIndex, X_ERROR, "[drm] failed to get %s capability: %s\n", @@ -995,9 +446,10 @@ static int armada_get_cap(struct armada_drm_info *drm, uint64_t cap, static Bool armada_drm_open_master(ScrnInfoPtr pScrn) { - struct armada_drm_info *drm; + struct all_drm_info *drm; EntityInfoPtr pEnt; drmSetVersion sv; + drmVersionPtr version; const char *busid = DRM_DEFAULT_BUS_ID; uint64_t val; int err; @@ -1017,8 +469,16 @@ static Bool armada_drm_open_master(ScrnInfoPtr pScrn) if (!drm) return FALSE; - drm->fd = drmOpen(DRM_MODULE_NAME, busid); - if (drm->fd < 0) { + drm->common.cursor_max_width = CURSOR_MAX_WIDTH; + drm->common.cursor_max_height = CURSOR_MAX_HEIGHT; + drm->common.private = &drm->armada; + drm->common.event_context.version = DRM_EVENT_CONTEXT_VERSION; +#ifdef HAVE_DRI2 + drm->common.event_context.vblank_handler = vivante_dri2_vblank; +#endif + + drm->common.fd = drmOpen(DRM_MODULE_NAME, busid); + if (drm->common.fd < 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] Failed to open DRM device for %s: %s\n", busid, strerror(errno)); @@ -1033,7 +493,7 @@ static Bool armada_drm_open_master(ScrnInfoPtr pScrn) sv.drm_di_minor = 1; sv.drm_dd_major = -1; sv.drm_dd_minor = -1; - err = drmSetInterfaceVersion(drm->fd, &sv); + err = drmSetInterfaceVersion(drm->common.fd, &sv); if (err) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] failed to set DRM interface version: %s\n", @@ -1041,7 +501,7 @@ static Bool armada_drm_open_master(ScrnInfoPtr pScrn) goto err_drm_close; } - if (armada_get_cap(drm, DRM_CAP_PRIME, &val, + if (armada_get_cap(drm->common.fd, DRM_CAP_PRIME, &val, pScrn->scrnIndex, "DRM_CAP_PRIME")) goto err_drm_close; if (!(val & DRM_PRIME_CAP_EXPORT)) { @@ -1050,7 +510,7 @@ static Bool armada_drm_open_master(ScrnInfoPtr pScrn) goto err_drm_close; } - if (armada_get_cap(drm, DRM_CAP_DUMB_BUFFER, &val, + if (armada_get_cap(drm->common.fd, DRM_CAP_DUMB_BUFFER, &val, pScrn->scrnIndex, "DRM_CAP_DUMB_BUFFER")) goto err_drm_close; if (!val) { @@ -1059,41 +519,42 @@ static Bool armada_drm_open_master(ScrnInfoPtr pScrn) goto err_drm_close; } - err = drm_armada_init(drm->fd, &drm->bufmgr); + err = drm_armada_init(drm->common.fd, &drm->armada.bufmgr); if (err) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] failed to initialize Armada DRM manager.\n"); goto err_drm_close; } - SET_DRM_INFO(pScrn, drm); + SET_DRM_INFO(pScrn, &drm->common); + + version = drmGetVersion(drm->common.fd); + if (version) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "hardware: %s\n", + version->name); + drmFreeVersion(version); + } return TRUE; err_drm_close: - drmClose(drm->fd); + drmClose(drm->common.fd); err_free: free(drm); return FALSE; } -static void armada_drm_close_master(ScrnInfoPtr pScrn) -{ - struct armada_drm_info *drm = GET_DRM_INFO(pScrn); - - if (drm) { - drm_armada_fini(drm->bufmgr); - drmClose(drm->fd); - SET_DRM_INFO(pScrn, NULL); - free(drm); - } -} - static void armada_drm_FreeScreen(FREE_SCREEN_ARGS_DECL) { SCRN_INFO_PTR(arg); - armada_drm_close_master(pScrn); + if (pScrn->driverPrivate) { + struct armada_drm_info *arm = GET_ARMADA_DRM_INFO(pScrn); + + drm_armada_fini(arm->bufmgr); + } + + common_drm_FreeScreen(FREE_SCREEN_ARGS(pScrn)); } static Bool armada_drm_PreInit(ScrnInfoPtr pScrn, int flags) @@ -1113,6 +574,8 @@ static Bool armada_drm_PreInit(ScrnInfoPtr pScrn, int flags) return FALSE; } + /* Limit the maximum framebuffer size to 16MB */ + pScrn->videoRam = 16 * 1048576; pScrn->monitor = pScrn->confScreen->monitor; pScrn->progClock = TRUE; pScrn->rgbBits = 8; @@ -1165,10 +628,10 @@ Bool armada_drm_init_screen(ScrnInfoPtr pScrn) { pScrn->PreInit = armada_drm_PreInit; pScrn->ScreenInit = armada_drm_ScreenInit; - pScrn->SwitchMode = armada_drm_SwitchMode; - pScrn->AdjustFrame = armada_drm_AdjustFrame; - pScrn->EnterVT = armada_drm_EnterVT; - pScrn->LeaveVT = armada_drm_LeaveVT; + pScrn->SwitchMode = common_drm_SwitchMode; + pScrn->AdjustFrame = common_drm_AdjustFrame; + pScrn->EnterVT = common_drm_EnterVT; + pScrn->LeaveVT = common_drm_LeaveVT; pScrn->FreeScreen = armada_drm_FreeScreen; pScrn->ValidMode = armada_drm_ValidMode; diff --git a/src/armada_drm.h b/src/armada_drm.h index 0f765cf..a7a9824 100644 --- a/src/armada_drm.h +++ b/src/armada_drm.h @@ -11,63 +11,25 @@ #include #include -struct drm_armada_bo; - -struct armada_crtc_info { - int drm_fd; - struct armada_drm_info *drm; - unsigned num; - unsigned short cursor_max_width; - unsigned short cursor_max_height; - drmModeModeInfo kmode; - drmModeCrtcPtr mode_crtc; - - struct drm_armada_bo *cursor_bo; - - uint32_t rotate_fb_id; -}; -#define armada_crtc(crtc) \ - ((struct armada_crtc_info *)(crtc)->driver_private) - -struct drm_udev_info { - struct udev_monitor *monitor; - pointer *handler; - dev_t drm_dev; -}; +#include "common_drm.h" struct armada_drm_info { - int fd; + OptionInfoPtr Options; + CloseScreenProcPtr CloseScreen; + CreateScreenResourcesProcPtr CreateScreenResources; struct drm_armada_bufmgr *bufmgr; - drmEventContext event_context; - - unsigned cpp; - struct drm_armada_bo *front_bo; - uint32_t fb_id; - drmModeResPtr mode_res; - - Bool has_hw_cursor; - Bool hw_cursor; Bool accel; - -#ifdef HAVE_UDEV - struct drm_udev_info udev; -#endif - - CloseScreenProcPtr CloseScreen; - CreateScreenResourcesProcPtr CreateScreenResources; - OptionInfoPtr Options; + unsigned cpp; }; -enum { - OPTION_HW_CURSOR, - OPTION_XV_ACCEL, - OPTION_USE_GPU, - OPTION_HOTPLUG, +struct all_drm_info { + struct common_drm_info common; + struct armada_drm_info armada; }; -#define GET_DRM_INFO(pScrn) ((struct armada_drm_info *)(pScrn)->driverPrivate) -#define SET_DRM_INFO(pScrn, ptr) ((pScrn)->driverPrivate = (ptr)) +#define GET_ARMADA_DRM_INFO(pScrn) \ + ((struct armada_drm_info *)GET_DRM_INFO(pScrn)->private) /* DRM core support */ Bool armada_drm_init_screen(ScrnInfoPtr pScrn); diff --git a/src/armada_drm_xv.c b/src/armada_drm_xv.c index 94257f6..b3e545b 100644 --- a/src/armada_drm_xv.c +++ b/src/armada_drm_xv.c @@ -15,6 +15,7 @@ #include #include "armada_drm.h" +#include "common_drm.h" #include "drm_fourcc.h" #include "xf86Crtc.h" #include "xf86xv.h" @@ -55,7 +56,8 @@ struct armada_format { }; struct drm_xv { - struct armada_drm_info *drm; + int fd; + struct drm_armada_bufmgr *bufmgr; /* Common information */ xf86CrtcPtr desired_crtc; @@ -123,7 +125,7 @@ static int armada_drm_prop_set(ScrnInfoPtr pScrn, struct drm_xv *drmxv, if (!drmxv->planes[i]) continue; - drmModeObjectSetProperty(drmxv->drm->fd, + drmModeObjectSetProperty(drmxv->fd, drmxv->planes[i]->plane_id, DRM_MODE_OBJECT_PLANE, prop_id, value); @@ -144,7 +146,7 @@ static int armada_drm_old_update_attr(struct drm_xv *drmxv) arg = drmxv->attrs; arg.flags = ARMADA_OVERLAY_UPDATE_ATTRS; - drmIoctl(drmxv->drm->fd, DRM_IOCTL_ARMADA_OVERLAY_ATTRS, &arg); + drmIoctl(drmxv->fd, DRM_IOCTL_ARMADA_OVERLAY_ATTRS, &arg); return Success; } @@ -384,7 +386,7 @@ static void armada_drm_bufs_free(struct drm_xv *drmxv) if (drmxv->bufs[i].fb_id) { if (drmxv->bufs[i].fb_id == drmxv->plane_fb_id) drmxv->plane_fb_id = 0; - drmModeRmFB(drmxv->drm->fd, drmxv->bufs[i].fb_id); + drmModeRmFB(drmxv->fd, drmxv->bufs[i].fb_id); drmxv->bufs[i].fb_id = 0; } if (drmxv->bufs[i].bo) { @@ -394,7 +396,7 @@ static void armada_drm_bufs_free(struct drm_xv *drmxv) } if (drmxv->plane_fb_id) { - drmModeRmFB(drmxv->drm->fd, drmxv->plane_fb_id); + drmModeRmFB(drmxv->fd, drmxv->plane_fb_id); drmxv->plane_fb_id = 0; } @@ -416,7 +418,7 @@ armada_drm_create_fbid(struct drm_xv *drmxv, struct drm_armada_bo *bo, handles[2] = bo->handle; /* Create the framebuffer object for this buffer */ - if (drmModeAddFB2(drmxv->drm->fd, drmxv->width, drmxv->height, + if (drmModeAddFB2(drmxv->fd, drmxv->width, drmxv->height, drmxv->plane_format->drm_format, handles, drmxv->pitches, drmxv->offsets, id, 0)) return FALSE; @@ -426,7 +428,7 @@ armada_drm_create_fbid(struct drm_xv *drmxv, struct drm_armada_bo *bo, static int armada_drm_bufs_alloc(struct drm_xv *drmxv) { - struct drm_armada_bufmgr *bufmgr = drmxv->drm->bufmgr; + struct drm_armada_bufmgr *bufmgr = drmxv->bufmgr; uint32_t width = drmxv->width; uint32_t height = drmxv->image_size / width / 4; unsigned i; @@ -505,7 +507,7 @@ armada_drm_get_xvbo(ScrnInfoPtr pScrn, struct drm_xv *drmxv, unsigned char *buf, uint32_t name = ((uint32_t *)buf)[1]; /* Lookup the bo for the global name */ - bo = drm_armada_bo_create_from_name(drmxv->drm->bufmgr, name); + bo = drm_armada_bo_create_from_name(drmxv->bufmgr, name); if (!bo) return BadAlloc; @@ -733,7 +735,7 @@ armada_drm_plane_StopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup) RegionEmpty(&drmxv->clipBoxes); - ret = drmModeSetPlane(drmxv->drm->fd, drmxv->plane->plane_id, + ret = drmModeSetPlane(drmxv->fd, drmxv->plane->plane_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); if (ret) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, @@ -759,7 +761,7 @@ static Bool armada_drm_check_plane(ScrnInfoPtr pScrn, struct drm_xv *drmxv, return FALSE; } - crtc_mask = 1 << armada_crtc(crtc)->num; + crtc_mask = 1 << common_crtc(crtc)->num; plane = drmxv->plane; if (plane && !(plane->possible_crtcs & crtc_mask)) { @@ -814,8 +816,8 @@ armada_drm_plane_Put(ScrnInfoPtr pScrn, struct drm_xv *drmxv, uint32_t fb_id, crtc_y = dst->y1 - crtc->y; plane = drmxv->plane; - drmModeSetPlane(drmxv->drm->fd, plane->plane_id, - armada_crtc(crtc)->mode_crtc->crtc_id, fb_id, 0, + drmModeSetPlane(drmxv->fd, plane->plane_id, + common_crtc(crtc)->mode_crtc->crtc_id, fb_id, 0, crtc_x, crtc_y, dst->x2 - dst->x1, dst->y2 - dst->y1, x1, y1, x2 - x1, y2 - y1); @@ -859,7 +861,7 @@ static int armada_drm_plane_PutImage(ScrnInfoPtr pScrn, /* If there was a previous fb, release it. */ if (drmxv->is_bmm && drmxv->plane_fb_id && drmxv->plane_fb_id != fb_id) { - drmModeRmFB(drmxv->drm->fd, drmxv->plane_fb_id); + drmModeRmFB(drmxv->fd, drmxv->plane_fb_id); drmxv->plane_fb_id = 0; } @@ -984,7 +986,8 @@ static Bool armada_drm_init_atoms(ScrnInfoPtr pScrn) Bool armada_drm_XvInit(ScrnInfoPtr pScrn) { ScreenPtr scrn = screenInfo.screens[pScrn->scrnIndex]; - struct armada_drm_info *drm = GET_DRM_INFO(pScrn); + struct common_drm_info *drm = GET_DRM_INFO(pScrn); + struct armada_drm_info *arm = GET_ARMADA_DRM_INFO(pScrn); XF86VideoAdaptorPtr xv[2], plane; drmModePlaneResPtr res; struct drm_xv *drmxv; @@ -1000,11 +1003,12 @@ Bool armada_drm_XvInit(ScrnInfoPtr pScrn) if (!drmxv) return FALSE; - drmxv->drm = drm; + drmxv->fd = drm->fd; + drmxv->bufmgr = arm->bufmgr; drmxv->autopaint_colorkey = TRUE; /* Get the plane resources and the overlay planes */ - res = drmModeGetPlaneResources(drm->fd); + res = drmModeGetPlaneResources(drmxv->fd); if (!res) goto err_free; @@ -1014,8 +1018,8 @@ Bool armada_drm_XvInit(ScrnInfoPtr pScrn) uint32_t plane_id = res->planes[i]; unsigned j; - drmxv->planes[i] = drmModeGetPlane(drm->fd, plane_id); - props = drmModeObjectGetProperties(drm->fd, plane_id, + drmxv->planes[i] = drmModeGetPlane(drmxv->fd, plane_id); + props = drmModeObjectGetProperties(drmxv->fd, plane_id, DRM_MODE_OBJECT_PLANE); if (!drmxv->planes[i] || !props) { drmModeFreePlaneResources(res); @@ -1026,7 +1030,7 @@ Bool armada_drm_XvInit(ScrnInfoPtr pScrn) drmModePropertyPtr prop; unsigned k; - prop = drmModeGetProperty(drm->fd, props->props[j]); + prop = drmModeGetProperty(drmxv->fd, props->props[j]); if (!prop) continue; @@ -1052,7 +1056,7 @@ Bool armada_drm_XvInit(ScrnInfoPtr pScrn) /* Done with the plane resources */ drmModeFreePlaneResources(res); - drmIoctl(drm->fd, DRM_IOCTL_ARMADA_OVERLAY_ATTRS, &drmxv->attrs); + drmIoctl(drmxv->fd, DRM_IOCTL_ARMADA_OVERLAY_ATTRS, &drmxv->attrs); if (drmxv->prop_values[PROP_DRM_COLORKEY]) { drmxv->attrs.color_key = drmxv->prop_values[PROP_DRM_COLORKEY]; armada_drm_old_update_attr(drmxv); diff --git a/src/common_drm.c b/src/common_drm.c index ad98db4..0771b49 100644 --- a/src/common_drm.c +++ b/src/common_drm.c @@ -29,6 +29,17 @@ #include #endif +enum { + OPTION_HW_CURSOR, + OPTION_HOTPLUG, +}; + +static const OptionInfoRec common_drm_options[] = { + { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_HOTPLUG, "HotPlug", OPTV_BOOLEAN, {0}, TRUE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + struct common_drm_property { drmModePropertyPtr mode_prop; uint64_t value; @@ -36,6 +47,16 @@ struct common_drm_property { Atom *atoms; }; +struct common_conn_info { + int drm_fd; + int drm_id; + int dpms_mode; + int nprops; + struct common_drm_property *props; + drmModeConnectorPtr mode_output; + drmModeEncoderPtr mode_encoder; +}; + static void drmmode_ConvertFromKMode(ScrnInfoPtr pScrn, drmModeModeInfoPtr kmode, DisplayModePtr mode) { @@ -63,7 +84,7 @@ static void drmmode_ConvertFromKMode(ScrnInfoPtr pScrn, } static drmModePropertyPtr common_drm_conn_find_property( - struct armada_conn_info *conn, const char *name, uint32_t *blob) + struct common_conn_info *conn, const char *name, uint32_t *blob) { drmModeConnectorPtr koutput = conn->mode_output; int i; @@ -88,7 +109,7 @@ static drmModePropertyPtr common_drm_conn_find_property( static void common_drm_conn_create_resources(xf86OutputPtr output) { - struct armada_conn_info *conn = output->driver_private; + struct common_conn_info *conn = output->driver_private; drmModeConnectorPtr mop = conn->mode_output; int i, j, n, err; @@ -195,7 +216,7 @@ static void common_drm_conn_create_resources(xf86OutputPtr output) static void common_drm_conn_dpms(xf86OutputPtr output, int mode) { - struct armada_conn_info *conn = output->driver_private; + struct common_conn_info *conn = output->driver_private; drmModePropertyPtr p = common_drm_conn_find_property(conn, "DPMS", NULL); if (p) { @@ -208,7 +229,7 @@ static void common_drm_conn_dpms(xf86OutputPtr output, int mode) static xf86OutputStatus common_drm_conn_detect(xf86OutputPtr output) { - struct armada_conn_info *conn = output->driver_private; + struct common_conn_info *conn = output->driver_private; xf86OutputStatus status = XF86OutputStatusUnknown; drmModeConnectorPtr koutput; @@ -241,7 +262,7 @@ common_drm_conn_mode_valid(xf86OutputPtr output, DisplayModePtr pModes) static DisplayModePtr common_drm_conn_get_modes(xf86OutputPtr output) { ScrnInfoPtr pScrn = output->scrn; - struct armada_conn_info *conn = output->driver_private; + struct common_conn_info *conn = output->driver_private; drmModePropertyBlobPtr edid = NULL; DisplayModePtr modes = NULL; drmModePropertyPtr p; @@ -275,7 +296,7 @@ static DisplayModePtr common_drm_conn_get_modes(xf86OutputPtr output) static Bool common_drm_conn_set_property(xf86OutputPtr output, Atom property, RRPropertyValuePtr value) { - struct armada_conn_info *conn = output->driver_private; + struct common_conn_info *conn = output->driver_private; int i; for (i = 0; i < conn->nprops; i++) { @@ -330,7 +351,7 @@ static Bool common_drm_conn_get_property(xf86OutputPtr output, Atom property) static void common_drm_conn_destroy(xf86OutputPtr output) { - struct armada_conn_info *conn = output->driver_private; + struct common_conn_info *conn = output->driver_private; drmModeFreeConnector(conn->mode_output); drmModeFreeEncoder(conn->mode_encoder); @@ -364,19 +385,20 @@ static const int subpixel_conv_table[] = { SubPixelVerticalRGB, SubPixelVerticalBGR, SubPixelNone }; -void common_drm_conn_init(ScrnInfoPtr pScrn, int fd, uint32_t id) +static void common_drm_conn_init(ScrnInfoPtr pScrn, uint32_t id) { + struct common_drm_info *drm = GET_DRM_INFO(pScrn); drmModeConnectorPtr koutput; drmModeEncoderPtr kencoder; xf86OutputPtr output; - struct armada_conn_info *conn; + struct common_conn_info *conn; char name[32]; - koutput = drmModeGetConnector(fd, id); + koutput = drmModeGetConnector(drm->fd, id); if (!koutput) return; - kencoder = drmModeGetEncoder(fd, koutput->encoders[0]); + kencoder = drmModeGetEncoder(drm->fd, koutput->encoders[0]); if (!kencoder) { drmModeFreeConnector(koutput); return; @@ -401,7 +423,7 @@ void common_drm_conn_init(ScrnInfoPtr pScrn, int fd, uint32_t id) return; } - conn->drm_fd = fd; + conn->drm_fd = drm->fd; conn->drm_id = id; conn->mode_output = koutput; conn->mode_encoder = kencoder; @@ -415,3 +437,657 @@ void common_drm_conn_init(ScrnInfoPtr pScrn, int fd, uint32_t id) output->interlaceAllowed = 1; /* wish there was a way to read that */ output->doubleScanAllowed = 0; } + +/* + * CRTC support + */ +static void common_drm_reload_hw_cursors(ScrnInfoPtr pScrn) +{ + struct common_drm_info *drm = GET_DRM_INFO(pScrn); + + /* Work around stricter checks in X */ + if (pScrn->pScreen && drm->hw_cursor) + xf86_reload_cursors(pScrn->pScreen); +} + +static void drmmode_ConvertToKMode(drmModeModeInfoPtr 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; + if (mode->name) + strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN); + kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0; +} + +static Bool common_drm_crtc_apply(xf86CrtcPtr crtc, uint32_t front_fb_id) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + struct common_crtc_info *drmc = common_crtc(crtc); + drmModeModeInfo kmode; + uint32_t fb_id, *output_ids; + int x, y, i, ret, output_num; + + output_ids = calloc(xf86_config->num_output, sizeof *output_ids); + if (!output_ids) + return FALSE; + + for (output_num = i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + struct common_conn_info *conn; + + if (output->crtc == crtc) { + conn = output->driver_private; + output_ids[output_num++] = conn->mode_output->connector_id; + } + } + + if (!xf86CrtcRotate(crtc)) { + ret = FALSE; + goto done; + } + + crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, + crtc->gamma_blue, crtc->gamma_size); + + if (drmc->rotate_fb_id) { + fb_id = drmc->rotate_fb_id; + x = y = 0; + } else { + fb_id = front_fb_id; + x = crtc->x; + y = crtc->y; + } + + drmmode_ConvertToKMode(&kmode, &crtc->mode); + + ret = drmModeSetCrtc(drmc->drm_fd, drmc->mode_crtc->crtc_id, fb_id, + x, y, output_ids, output_num, &kmode); + if (ret) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] failed to set mode on crtc %u: %s\n", + drmc->mode_crtc->crtc_id, strerror(errno)); + ret = FALSE; + } else { + ret = TRUE; + + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + + if (output->crtc != crtc) + continue; + + output->funcs->dpms(output, DPMSModeOn); + } + } + +done: + free(output_ids); + return ret; +} + +void common_drm_crtc_dpms(xf86CrtcPtr crtc, int mode) +{ +} + +Bool common_drm_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, + Rotation rotation, int x, int y) +{ + struct common_drm_info *drm = GET_DRM_INFO(crtc->scrn); + DisplayModeRec saved_mode; + Rotation saved_rotation; + int ret, saved_x, saved_y; + + saved_mode = crtc->mode; + saved_x = crtc->x; + saved_y = crtc->y; + saved_rotation = crtc->rotation; + crtc->mode = *mode; + crtc->x = x; + crtc->y = y; + crtc->rotation = rotation; + + ret = common_drm_crtc_apply(crtc, drm->fb_id); + if (!ret) { + crtc->mode = saved_mode; + crtc->x = saved_x; + crtc->y = saved_y; + crtc->rotation = saved_rotation; + } + + common_drm_reload_hw_cursors(crtc->scrn); + + return ret; +} + +void common_drm_crtc_resize(ScrnInfoPtr pScrn, int width, int height, + int displayWidth, uint32_t fb_id) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + struct common_drm_info *drm = GET_DRM_INFO(pScrn); + uint32_t old_fb_id; + int i; + + pScrn->virtualX = width; + pScrn->virtualY = height; + pScrn->displayWidth = displayWidth; + + old_fb_id = drm->fb_id; + drm->fb_id = fb_id; + + for (i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + + if (!crtc->enabled) + continue; + + common_drm_crtc_apply(crtc, fb_id); + } + + common_drm_reload_hw_cursors(pScrn); + + drmModeRmFB(drm->fd, old_fb_id); +} + +void common_drm_crtc_gamma_set(xf86CrtcPtr crtc, + CARD16 *red, CARD16 *green, CARD16 *blue, int size) +{ + struct common_crtc_info *drmc = common_crtc(crtc); + + drmModeCrtcSetGamma(drmc->drm_fd, drmc->mode_crtc->crtc_id, + size, red, green, blue); +} + +void common_drm_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y) +{ + struct common_crtc_info *drmc = common_crtc(crtc); + + drmModeMoveCursor(drmc->drm_fd, drmc->mode_crtc->crtc_id, x, y); +} + +void common_drm_crtc_show_cursor(xf86CrtcPtr crtc) +{ + struct common_drm_info *drm = GET_DRM_INFO(crtc->scrn); + struct common_crtc_info *drmc = common_crtc(crtc); + + drmModeSetCursor(drmc->drm_fd, drmc->mode_crtc->crtc_id, + drmc->cursor_handle, + drm->cursor_max_width, drm->cursor_max_height); +} + +void common_drm_crtc_hide_cursor(xf86CrtcPtr crtc) +{ + struct common_crtc_info *drmc = common_crtc(crtc); + + drmModeSetCursor(drmc->drm_fd, drmc->mode_crtc->crtc_id, 0, 0, 0); +} + +static Bool common_drm_crtc_init(ScrnInfoPtr pScrn, unsigned num, + const xf86CrtcFuncsRec *funcs) +{ + struct common_drm_info *drm = GET_DRM_INFO(pScrn); + struct common_crtc_info *drmc; + xf86CrtcPtr crtc; + uint32_t id; + + id = drm->mode_res->crtcs[num]; + + crtc = xf86CrtcCreate(pScrn, funcs); + if (!crtc) + return FALSE; + + drmc = xnfcalloc(1, sizeof *drmc); + drmc->drm_fd = drm->fd; + drmc->num = num; + drmc->mode_crtc = drmModeGetCrtc(drmc->drm_fd, id); + crtc->driver_private = drmc; + + /* Test whether hardware cursor is supported */ + if (drmModeSetCursor(drmc->drm_fd, id, 0, 0, 0)) + drm->has_hw_cursor = FALSE; + + return TRUE; +} + +Bool common_drm_init_mode_resources(ScrnInfoPtr pScrn, + const xf86CrtcFuncsRec *funcs) +{ + struct common_drm_info *drm = GET_DRM_INFO(pScrn); + Gamma zeros = { 0.0, 0.0, 0.0 }; + int i; + + drm->mode_res = drmModeGetResources(drm->fd); + if (!drm->mode_res) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "failed to get resources: %s\n", strerror(errno)); + return FALSE; + } + + xf86CrtcSetSizeRange(pScrn, drm->mode_res->min_width, + drm->mode_res->min_height, + drm->mode_res->max_width, + drm->mode_res->max_height); + + drm->has_hw_cursor = TRUE; + for (i = 0; i < drm->mode_res->count_crtcs; i++) + if (!common_drm_crtc_init(pScrn, i, funcs)) + return FALSE; + + for (i = 0; i < drm->mode_res->count_connectors; i++) + common_drm_conn_init(pScrn, drm->mode_res->connectors[i]); + + xf86InitialConfiguration(pScrn, TRUE); + + 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); + + if (!xf86LoadSubModule(pScrn, "fb")) + return FALSE; + + return TRUE; +} + +void common_drm_LoadPalette(ScrnInfoPtr pScrn, int num, 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 i, p; + + for (i = 0; i < num; i++) { + int index = indices[i]; + lut_r[index] = colors[index].red << 8; + lut_g[index] = colors[index].green << 8; + lut_b[index] = colors[index].blue << 8; + } + + for (p = 0; p < xf86_config->num_crtc; p++) { + xf86CrtcPtr crtc = xf86_config->crtc[p]; + +#ifdef RANDR_12_INTERFACE + RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b); +#else + crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256); +#endif + } +} + +#ifdef HAVE_UDEV +static void common_drm_handle_uevent(int fd, pointer data) +{ + ScrnInfoPtr pScrn = data; + struct common_drm_info *drm = GET_DRM_INFO(pScrn); + struct udev_device *ud; + + ud = udev_monitor_receive_device(drm->udev.monitor); + if (ud) { + dev_t dev = udev_device_get_devnum(ud); + const char *hp = udev_device_get_property_value(ud, "HOTPLUG"); + + if (dev == drm->udev.drm_dev && hp && strtol(hp, NULL, 10) == 1) + RRGetInfo(screenInfo.screens[pScrn->scrnIndex], TRUE); + + udev_device_unref(ud); + } +} + +static Bool common_drm_udev_CloseScreen(CLOSE_SCREEN_ARGS_DECL) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + struct common_drm_info *drm = GET_DRM_INFO(pScrn); + + if (drm->udev.monitor) { + struct udev *udev = udev_monitor_get_udev(drm->udev.monitor); + + xf86RemoveGeneralHandler(drm->udev.handler); + udev_monitor_unref(drm->udev.monitor); + udev_unref(udev); + } + + pScreen->CloseScreen = drm->udev.CloseScreen; + + return pScreen->CloseScreen(CLOSE_SCREEN_ARGS); +} + +static Bool common_drm_udev_init(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + struct common_drm_info *drm = GET_DRM_INFO(pScrn); + MessageType from = X_CONFIG; + struct udev_monitor *udev_mon; + struct udev *udev; + struct stat st; + Bool hotplug; + + if (!xf86GetOptValBool(drm->Options, OPTION_HOTPLUG, &hotplug)) { + from = X_DEFAULT; + hotplug = TRUE; + } + + xf86DrvMsg(pScrn->scrnIndex, from, "hotplug detection %sabled\n", + hotplug ? "en" : "dis"); + if (!hotplug) + return TRUE; + + if (fstat(drm->fd, &st) || !S_ISCHR(st.st_mode)) + return FALSE; + + drm->udev.drm_dev = st.st_rdev; + + udev = udev_new(); + if (!udev) + return FALSE; + + udev_mon = udev_monitor_new_from_netlink(udev, "udev"); + if (!udev_mon) { + udev_unref(udev); + return FALSE; + } + + if (udev_monitor_filter_add_match_subsystem_devtype(udev_mon, + "drm", "drm_minor") || + udev_monitor_enable_receiving(udev_mon)) { + udev_monitor_unref(udev_mon); + udev_unref(udev); + return FALSE; + } + + drm->udev.monitor = udev_mon; + drm->udev.handler = xf86AddGeneralHandler(udev_monitor_get_fd(udev_mon), + common_drm_handle_uevent, + pScrn); + + drm->udev.CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = common_drm_udev_CloseScreen; + + return TRUE; +} +#endif + +static Bool common_drm_CloseScreen(CLOSE_SCREEN_ARGS_DECL) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + struct common_drm_info *drm = GET_DRM_INFO(pScrn); + Bool ret; + + if (drm->fb_id) { + drmModeRmFB(drm->fd, drm->fb_id); + drm->fb_id = 0; + } + + if (drm->hw_cursor) + xf86_cursors_fini(pScreen); + + pScreen->CloseScreen = drm->CloseScreen; + ret = (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); + + if (pScrn->vtSema) + common_drm_LeaveVT(VT_FUNC_ARGS(0)); + + pScrn->vtSema = FALSE; + + return ret; +} + +Bool common_drm_PreScreenInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + struct common_drm_info *drm = GET_DRM_INFO(pScrn); + int visuals, preferredCVC; + + drm->Options = xnfalloc(sizeof(common_drm_options)); + memcpy(drm->Options, common_drm_options, sizeof(common_drm_options)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, drm->Options); + + miClearVisualTypes(); + if (pScrn->bitsPerPixel > 8) { + visuals = TrueColorMask; + preferredCVC = TrueColor; + } else { + visuals = miGetDefaultVisualMask(pScrn->depth); + preferredCVC = pScrn->defaultVisual; + } + + if (!miSetVisualTypes(pScrn->depth, visuals, pScrn->rgbBits, preferredCVC)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] failed to set visual types for %d bpp depth %d\n", + pScrn->bitsPerPixel, pScrn->depth); + return FALSE; + } + + if (!miSetPixmapDepths()) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] failed to set pixmap depths\n"); + return FALSE; + } + + if (!fbScreenInit(pScreen, NULL, pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, + pScrn->bitsPerPixel)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] fbScreenInit failed\n"); + return FALSE; + } + + if (pScrn->bitsPerPixel > 8) { + /* Fixup RGB ordering */ + VisualPtr 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; + } + } + } + + if (!fbPictureInit(pScreen, NULL, 0)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] fbPictureInit failed\n"); + return FALSE; + } + + xf86SetBlackWhitePixels(pScreen); + + xf86SetBackingStore(pScreen); + xf86SetSilkenMouse(pScreen); + + drm->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = common_drm_CloseScreen; + + return TRUE; +} + +static void common_drm_wakeup_handler(pointer data, int err, pointer p) +{ + struct common_drm_info *drm = data; + fd_set *read_mask = p; + + if (data == NULL || err < 0) + return; + + if (FD_ISSET(drm->fd, read_mask)) + drmHandleEvent(drm->fd, &drm->event_context); +} + +Bool common_drm_PostScreenInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + struct common_drm_info *drm = GET_DRM_INFO(pScrn); + + pScreen->SaveScreen = xf86SaveScreen; + + /* software cursor */ + miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); + + drm->hw_cursor = xf86ReturnOptValBool(drm->Options, + OPTION_HW_CURSOR, + drm->has_hw_cursor); + if (drm->hw_cursor && !drm->has_hw_cursor) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "No hardware cursor support - disabling hardware cursors\n"); + drm->hw_cursor = FALSE; + } + if (drm->hw_cursor && + xf86_cursors_init(pScreen, + drm->cursor_max_width, drm->cursor_max_height, + HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | + HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | + HARDWARE_CURSOR_INVERT_MASK | + HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | + HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | + HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | + HARDWARE_CURSOR_UPDATE_UNHIDDEN | + HARDWARE_CURSOR_ARGB)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using hardware cursors\n"); + } else { + drm->hw_cursor = FALSE; + } + + if (!xf86CrtcScreenInit(pScreen)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] failed to initialize screen\n"); + return FALSE; + } + + if (!miCreateDefColormap(pScreen)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] failed to initialize default colormap\n"); + return FALSE; + } + + if (!xf86HandleColormaps(pScreen, 256, 8, common_drm_LoadPalette, NULL, + CMAP_RELOAD_ON_MODE_SWITCH | + CMAP_PALETTED_TRUECOLOR)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] failed to initialize colormap handler\n"); + return FALSE; + } + + xf86DPMSInit(pScreen, xf86DPMSSet, 0); + + /* Setup the synchronisation feedback */ + AddGeneralSocket(drm->fd); + RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, + common_drm_wakeup_handler, drm); + +#ifdef HAVE_UDEV + if (!common_drm_udev_init(pScreen)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] failed to connect with udev: %s\n", + strerror(errno)); + return FALSE; + } +#endif + + return TRUE; +} + +Bool common_drm_SwitchMode(SWITCH_MODE_ARGS_DECL) +{ + SCRN_INFO_PTR(arg); + + return xf86SetSingleMode(pScrn, mode, RR_Rotate_0); +} + +void common_drm_AdjustFrame(ADJUST_FRAME_ARGS_DECL) +{ + SCRN_INFO_PTR(arg); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr output = xf86_config->output[xf86_config->compat_output]; + xf86CrtcPtr crtc = output->crtc; + + if (crtc && crtc->enabled) { + int saved_x = crtc->x; + int saved_y = crtc->y; + int ret; + + crtc->x = x; + crtc->y = y; + + ret = crtc->funcs->set_mode_major(crtc, &crtc->mode, + crtc->rotation, x, y); + if (!ret) { + crtc->x = saved_x; + crtc->y = saved_y; + } + } +} + +Bool common_drm_EnterVT(VT_FUNC_ARGS_DECL) +{ + SCRN_INFO_PTR(arg); + struct common_drm_info *drm = GET_DRM_INFO(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + + if (drmSetMaster(drm->fd)) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "[drm] set master failed: %s\n", strerror(errno)); + + if (!xf86SetDesiredModes(pScrn)) + return FALSE; + + /* Disable unused CRTCs */ + for (i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + struct common_crtc_info *drmc = common_crtc(crtc); + + if (!crtc->enabled) + drmModeSetCrtc(drmc->drm_fd, drmc->mode_crtc->crtc_id, + 0, 0, 0, NULL, 0, NULL); + } + + return TRUE; +} + +void common_drm_LeaveVT(VT_FUNC_ARGS_DECL) +{ + SCRN_INFO_PTR(arg); + struct common_drm_info *drm = GET_DRM_INFO(pScrn); + + xf86RotateFreeShadow(pScrn); + + xf86_hide_cursors(pScrn); + + drmDropMaster(drm->fd); +} + +void common_drm_FreeScreen(FREE_SCREEN_ARGS_DECL) +{ + SCRN_INFO_PTR(arg); + struct common_drm_info *drm = GET_DRM_INFO(pScrn); + + if (drm) { + drmClose(drm->fd); + SET_DRM_INFO(pScrn, NULL); + free(drm); + } +} diff --git a/src/common_drm.h b/src/common_drm.h index a23cd6e..b0c3cd4 100644 --- a/src/common_drm.h +++ b/src/common_drm.h @@ -1,18 +1,74 @@ #ifndef COMMON_DRM_H #define COMMON_DRM_H -struct common_drm_property; +#include "compat-api.h" +#include "xf86Crtc.h" -struct armada_conn_info { +struct common_crtc_info { int drm_fd; - int drm_id; - int dpms_mode; - int nprops; - struct common_drm_property *props; - drmModeConnectorPtr mode_output; - drmModeEncoderPtr mode_encoder; + unsigned num; + drmModeCrtcPtr mode_crtc; + void *cursor_data; + uint32_t cursor_handle; + uint32_t rotate_fb_id; }; +#define common_crtc(crtc) \ + ((struct common_crtc_info *)(crtc)->driver_private) -void common_drm_conn_init(ScrnInfoPtr pScrn, int fd, uint32_t id); +struct drm_udev_info { + struct udev_monitor *monitor; + pointer *handler; + dev_t drm_dev; + CloseScreenProcPtr CloseScreen; +}; + +struct common_drm_info { + int fd; + drmEventContext event_context; + uint32_t fb_id; + drmModeResPtr mode_res; + + Bool has_hw_cursor; + Bool hw_cursor; + unsigned short cursor_max_width; + unsigned short cursor_max_height; + +#ifdef HAVE_UDEV + struct drm_udev_info udev; +#endif + + OptionInfoPtr Options; + CloseScreenProcPtr CloseScreen; + + void *private; +}; + +#define GET_DRM_INFO(pScrn) ((struct common_drm_info *)(pScrn)->driverPrivate) +#define SET_DRM_INFO(pScrn, ptr) ((pScrn)->driverPrivate = (ptr)) + +void common_drm_crtc_dpms(xf86CrtcPtr crtc, int mode); +Bool common_drm_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, + Rotation rotation, int x, int y); +void common_drm_crtc_resize(ScrnInfoPtr pScrn, int width, int height, + int displayWidth, uint32_t fb_id); +void common_drm_crtc_gamma_set(xf86CrtcPtr crtc, + CARD16 *red, CARD16 *green, CARD16 *blue, int size); +void common_drm_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y); +void common_drm_crtc_show_cursor(xf86CrtcPtr crtc); +void common_drm_crtc_hide_cursor(xf86CrtcPtr crtc); + +Bool common_drm_init_mode_resources(ScrnInfoPtr pScrn, + const xf86CrtcFuncsRec *funcs); + +void common_drm_LoadPalette(ScrnInfoPtr pScrn, int num, int *indices, + LOCO *colors, VisualPtr pVisual); +Bool common_drm_PreScreenInit(ScreenPtr pScreen); +Bool common_drm_PostScreenInit(ScreenPtr pScreen); +Bool common_drm_SwitchMode(SWITCH_MODE_ARGS_DECL); +void common_drm_AdjustFrame(ADJUST_FRAME_ARGS_DECL); +Bool common_drm_EnterVT(VT_FUNC_ARGS_DECL); +void common_drm_LeaveVT(VT_FUNC_ARGS_DECL); + +void common_drm_FreeScreen(FREE_SCREEN_ARGS_DECL); #endif diff --git a/src/vivante_utils.h b/src/vivante_utils.h index e7bd2d4..da8ef2c 100644 --- a/src/vivante_utils.h +++ b/src/vivante_utils.h @@ -10,6 +10,7 @@ /* Needed for gcsRECT */ #include +struct drm_armada_bo; struct vivante; struct vivante_pixmap; -- cgit v1.2.3