xorg_driver.c revision 7e02303497237cde958c28608477d0c355a8038b
1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * All Rights Reserved.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining a
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * copy of this software and associated documentation files (the
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * "Software"), to deal in the Software without restriction, including
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * without limitation the rights to use, copy, modify, merge, publish,
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * distribute, sub license, and/or sell copies of the Software, and to
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * permit persons to whom the Software is furnished to do so, subject to
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * the following conditions:
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * The above copyright notice and this permission notice (including the
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * next paragraph) shall be included in all copies or substantial portions
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * of the Software.
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Author: Alan Hourihane <alanh@tungstengraphics.com>
273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Author: Jakob Bornecrantz <wallbraker@gmail.com>
283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "xorg-server.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xf86.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xf86_OSproc.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "compiler.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xf86PciInfo.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xf86Pci.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "mipointer.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "micmap.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/extensions/randr.h>
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "fb.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "edid.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xf86i2c.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xf86Crtc.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "miscstruct.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dixstruct.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xf86cmap.h"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xf86xv.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xorgVersion.h"
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef XSERVER_LIBPCIACCESS
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#error "libpciaccess needed"
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pciaccess.h>
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "state_tracker/drm_driver.h"
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "pipe/p_context.h"
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xorg_tracker.h"
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xorg_winsys.h"
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_LIBKMS
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "libkms.h"
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
6458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)/*
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Functions and symbols exported to Xorg via pointers.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static Bool drv_pre_init(ScrnInfoPtr pScrn, int flags);
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static Bool drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc,
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			    char **argv);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static Bool drv_switch_mode(int scrnIndex, DisplayModePtr mode, int flags);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void drv_adjust_frame(int scrnIndex, int x, int y, int flags);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static Bool drv_enter_vt(int scrnIndex, int flags);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void drv_leave_vt(int scrnIndex, int flags);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void drv_free_screen(int scrnIndex, int flags);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static ModeStatus drv_valid_mode(int scrnIndex, DisplayModePtr mode, Bool verbose,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			         int flags);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef enum
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles){
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OPTION_SW_CURSOR,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OPTION_2D_ACCEL,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OPTION_DEBUG_FALLBACK,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OPTION_THROTTLE_SWAP,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OPTION_THROTTLE_DIRTY,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OPTION_3D_ACCEL
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} drv_option_enums;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const OptionInfoRec drv_options[] = {
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {OPTION_2D_ACCEL, "2DAccel", OPTV_BOOLEAN, {0}, FALSE},
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {OPTION_DEBUG_FALLBACK, "DebugFallback", OPTV_BOOLEAN, {0}, FALSE},
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {OPTION_THROTTLE_SWAP, "SwapThrottling", OPTV_BOOLEAN, {0}, FALSE},
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {OPTION_THROTTLE_DIRTY, "DirtyThrottling", OPTV_BOOLEAN, {0}, FALSE},
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {OPTION_3D_ACCEL, "3DAccel", OPTV_BOOLEAN, {0}, FALSE},
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {-1, NULL, OPTV_NONE, {0}, FALSE}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Exported Xorg driver functions to winsys
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const OptionInfoRec *
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xorg_tracker_available_options(int chipid, int busid)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return drv_options;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)xorg_tracker_set_functions(ScrnInfoPtr scrn)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scrn->PreInit = drv_pre_init;
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scrn->ScreenInit = drv_screen_init;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scrn->SwitchMode = drv_switch_mode;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scrn->AdjustFrame = drv_adjust_frame;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scrn->EnterVT = drv_enter_vt;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scrn->LeaveVT = drv_leave_vt;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scrn->FreeScreen = drv_free_screen;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scrn->ValidMode = drv_valid_mode;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Bool
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xorg_tracker_have_modesetting(ScrnInfoPtr pScrn, struct pci_device *device)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *BusID = malloc(64);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sprintf(BusID, "pci:%04x:%02x:%02x.%d",
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    device->domain, device->bus,
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    device->dev, device->func);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (drmCheckModesettingSupported(BusID)) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		       "Drm modesetting not supported %s\n", BusID);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	free(BusID);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return FALSE;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   "Drm modesetting supported on %s\n", BusID);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(BusID);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRUE;
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Internal function definitions
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static Bool drv_init_front_buffer_functions(ScrnInfoPtr pScrn);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static Bool drv_close_screen(int scrnIndex, ScreenPtr pScreen);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Internal functions
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static Bool
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)drv_get_rec(ScrnInfoPtr pScrn)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (pScrn->driverPrivate)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return TRUE;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pScrn->driverPrivate = xnfcalloc(1, sizeof(modesettingRec));
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRUE;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)drv_free_rec(ScrnInfoPtr pScrn)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!pScrn)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!pScrn->driverPrivate)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(pScrn->driverPrivate);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pScrn->driverPrivate = NULL;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)drv_probe_ddc(ScrnInfoPtr pScrn, int index)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ConfiguredMonitor = NULL;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static Bool
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)drv_crtc_resize(ScrnInfoPtr pScrn, int width, int height)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modesettingPtr ms = modesettingPTR(pScrn);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CustomizerPtr cust = ms->cust;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScreenPtr pScreen = pScrn->pScreen;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int old_width, old_height;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PixmapPtr rootPixmap;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (width == pScrn->virtualX && height == pScrn->virtualY)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return TRUE;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cust && cust->winsys_check_fb_size &&
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	!cust->winsys_check_fb_size(cust, width*pScrn->bitsPerPixel / 8,
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    height)) {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   "Requested framebuffer size %dx%dx%d will not fit "
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   "in display memory.\n",
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   width, height, pScrn->bitsPerPixel);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return FALSE;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    old_width = pScrn->virtualX;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    old_height = pScrn->virtualY;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pScrn->virtualX = width;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pScrn->virtualY = height;
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* ms->create_front_buffer will remove the old front buffer */
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rootPixmap = pScreen->GetScreenPixmap(pScreen);
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!pScreen->ModifyPixmapHeader(rootPixmap, width, height, -1, -1, -1, NULL))
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	goto error_modify;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pScrn->displayWidth = rootPixmap->devKind / (rootPixmap->drawable.bitsPerPixel / 8);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ms->create_front_buffer(pScrn) || !ms->bind_front_buffer(pScrn))
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	goto error_create;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * create && bind will turn off all crtc(s) in the kernel so we need to
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * re-enable all the crtcs again. For real HW we might want to do this
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * before destroying the old framebuffer.
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < xf86_config->num_crtc; i++) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xf86CrtcPtr crtc = xf86_config->crtc[i];
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!crtc->enabled)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    continue;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation, crtc->x, crtc->y);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRUE;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * This is the error recovery path.
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)error_create:
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!pScreen->ModifyPixmapHeader(rootPixmap, old_width, old_height, -1, -1, -1, NULL))
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	FatalError("failed to resize rootPixmap error path\n");
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pScrn->displayWidth = rootPixmap->devKind / (rootPixmap->drawable.bitsPerPixel / 8);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)error_modify:
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pScrn->virtualX = old_width;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pScrn->virtualY = old_height;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ms->create_front_buffer(pScrn) && ms->bind_front_buffer(pScrn))
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return FALSE;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FatalError("failed to setup old framebuffer\n");
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return FALSE;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const xf86CrtcConfigFuncsRec crtc_config_funcs = {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    .resize = drv_crtc_resize
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static Bool
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)drv_init_drm(ScrnInfoPtr pScrn)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    modesettingPtr ms = modesettingPTR(pScrn);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* deal with server regeneration */
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ms->fd < 0) {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	char *BusID;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	BusID = malloc(64);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sprintf(BusID, "PCI:%d:%d:%d",
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		((ms->PciInfo->domain << 8) | ms->PciInfo->bus),
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ms->PciInfo->dev, ms->PciInfo->func
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    );
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ms->fd = drmOpen(driver_descriptor.driver_name, BusID);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ms->isMaster = TRUE;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	free(BusID);
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ms->fd >= 0)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return TRUE;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return FALSE;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRUE;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static Bool
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)drv_init_resource_management(ScrnInfoPtr pScrn)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modesettingPtr ms = modesettingPTR(pScrn);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScreenPtr pScreen = pScrn->pScreen;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Bool fbAccessDisabled;
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CARD8 *fbstart;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ms->screen || ms->kms)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return TRUE;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ms->no3D)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ms->screen = driver_descriptor.create_screen(ms->fd);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ms->screen)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return TRUE;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_LIBKMS
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!kms_create(ms->fd, &ms->kms))
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return TRUE;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return FALSE;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)drv_cleanup_fences(ScrnInfoPtr pScrn)
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles){
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modesettingPtr ms = modesettingPTR(pScrn);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert(ms->screen);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < XORG_NR_FENCES; i++) {
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if (ms->fence[i]) {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ms->screen->fence_finish(ms->screen, ms->fence[i],
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     PIPE_TIMEOUT_INFINITE);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ms->screen->fence_reference(ms->screen, &ms->fence[i], NULL);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static Bool
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)drv_pre_init(ScrnInfoPtr pScrn, int flags)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xf86CrtcConfigPtr xf86_config;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modesettingPtr ms;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rgb defaultWeight = { 0, 0, 0 };
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EntityInfoPtr pEnt;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EntPtr msEnt = NULL;
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CustomizerPtr cust;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Bool use3D;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pScrn->numEntities != 1)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return FALSE;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (flags & PROBE_DETECT) {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	drv_probe_ddc(pScrn, pEnt->index);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return TRUE;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cust = (CustomizerPtr) pScrn->driverPrivate;
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pScrn->driverPrivate = NULL;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Allocate driverPrivate */
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!drv_get_rec(pScrn))
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return FALSE;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ms = modesettingPTR(pScrn);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ms->pEnt = pEnt;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ms->cust = cust;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ms->fb_id = -1;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pScrn->displayWidth = 640;	       /* default it */
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ms->pEnt->location.type != BUS_PCI)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return FALSE;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ms->PciInfo = xf86GetPciInfoForEntity(ms->pEnt->index);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Allocate an entity private if necessary */
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (xf86IsEntityShared(pScrn->entityList[0])) {
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	FatalError("Entity");
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	msEnt = xf86GetEntityPrivate(pScrn->entityList[0],
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				     modesettingEntityIndex)->ptr;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ms->entityPrivate = msEnt;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	(void)msEnt;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ms->entityPrivate = NULL;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (xf86IsEntityShared(pScrn->entityList[0])) {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (xf86IsPrimInitDone(pScrn->entityList[0])) {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* do something */
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else {
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xf86SetPrimInitDone(pScrn->entityList[0]);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ms->fd = -1;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!drv_init_drm(pScrn))
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return FALSE;
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pScrn->monitor = pScrn->confScreen->monitor;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pScrn->progClock = TRUE;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pScrn->rgbBits = 8;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!xf86SetDepthBpp
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	(pScrn, 0, 0, 0,
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 PreferConvert24to32 | SupportConvert24to32 | Support32bppFb))
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return FALSE;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (pScrn->depth) {
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 8:
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 15:
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 16:
4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case 24:
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	break;
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   "Given depth (%d) is not supported by the driver\n",
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   pScrn->depth);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return FALSE;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xf86PrintDepthBpp(pScrn);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return FALSE;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!xf86SetDefaultVisual(pScrn, -1))
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return FALSE;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Process the options */
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xf86CollectOptions(pScrn, NULL);
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(ms->Options = malloc(sizeof(drv_options))))
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return FALSE;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(ms->Options, drv_options, sizeof(drv_options));
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->Options);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    use3D = cust ? !cust->no_3d : TRUE;
4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ms->from_3D = xf86GetOptValBool(ms->Options, OPTION_3D_ACCEL,
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    &use3D) ?
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	X_CONFIG : X_PROBED;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ms->no3D = !use3D;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!drv_init_resource_management(pScrn)) {
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not init "
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					       "Gallium3D or libKMS.\n");
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return FALSE;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Allocate an xf86CrtcConfig */
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xf86CrtcConfigInit(pScrn, &crtc_config_funcs);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* get max width and height */
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	drmModeResPtr res;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int max_width, max_height;
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	res = drmModeGetResources(ms->fd);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	max_width = res->max_width;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	max_height = res->max_height;
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ms->screen) {
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    int max;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    max = ms->screen->get_param(ms->screen,
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					PIPE_CAP_MAX_TEXTURE_2D_LEVELS);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    max = 1 << (max - 1);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    max_width = max < max_width ? max : max_width;
4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	    max_height = max < max_height ? max : max_height;
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xf86CrtcSetSizeRange(pScrn, res->min_width,
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			     res->min_height, max_width, max_height);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   "Min width %d, Max Width %d.\n",
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   res->min_width, max_width);
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   "Min height %d, Max Height %d.\n",
4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		   res->min_height, max_height);
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	drmModeFreeResources(res);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (xf86ReturnOptValBool(ms->Options, OPTION_SW_CURSOR, FALSE)) {
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ms->SWCursor = TRUE;
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xorg_crtc_init(pScrn);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xorg_output_init(pScrn);
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cust && cust->winsys_pre_init && !cust->winsys_pre_init(cust, ms->fd))
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return FALSE;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!xf86InitialConfiguration(pScrn, TRUE)) {
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return FALSE;
5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * If the driver can do gamma correction, it should call xf86SetGamma() here.
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	Gamma zeros = { 0.0, 0.0, 0.0 };
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!xf86SetGamma(pScrn, zeros)) {
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return FALSE;
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pScrn->modes == NULL) {
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return FALSE;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pScrn->currentMode = pScrn->modes;
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Set display resolution */
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xf86SetDpi(pScrn, 0, 0);
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Load the required sub modules */
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!xf86LoadSubModule(pScrn, "fb"))
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return FALSE;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* XXX: these aren't needed when we are using libkms */
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!xf86LoadSubModule(pScrn, "exa"))
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return FALSE;
5355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DRI2
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!xf86LoadSubModule(pScrn, "dri2"))
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return FALSE;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRUE;
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void xorg_flush(ScreenPtr pScreen)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modesettingPtr ms = modesettingPTR(xf86Screens[pScreen->myNum]);
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ms->ctx) {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int j;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ms->ctx->flush(ms->ctx,
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		       ms->dirtyThrottling ?
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		       &ms->fence[XORG_NR_FENCES-1] :
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		       NULL);
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ms->dirtyThrottling) {
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (ms->fence[0])
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ms->ctx->screen->fence_finish(ms->ctx->screen,
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              ms->fence[0],
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              PIPE_TIMEOUT_INFINITE);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* The amount of rendering generated by a block handler can be
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     * quite small.  Let us get a fair way ahead of hardware before
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     * throttling.
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     */
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    for (j = 0; j < XORG_NR_FENCES - 1; j++)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ms->screen->fence_reference(ms->screen,
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					    &ms->fence[j],
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					    ms->fence[j+1]);
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ms->screen->fence_reference(ms->screen,
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					&ms->fence[XORG_NR_FENCES-1],
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					NULL);
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DRM_MODE_FEATURE_DIRTYFB
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	RegionPtr dirty = DamageRegion(ms->damage);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	unsigned num_cliprects = REGION_NUM_RECTS(dirty);
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (num_cliprects) {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    drmModeClip *clip = alloca(num_cliprects * sizeof(drmModeClip));
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    BoxPtr rect = REGION_RECTS(dirty);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    int i, ret;
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* XXX no need for copy? */
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    for (i = 0; i < num_cliprects; i++, rect++) {
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		clip[i].x1 = rect->x1;
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		clip[i].y1 = rect->y1;
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		clip[i].x2 = rect->x2;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		clip[i].y2 = rect->y2;
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* TODO query connector property to see if this is needed */
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ret = drmModeDirtyFB(ms->fd, ms->fb_id, clip, num_cliprects);
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (ret) {
598		debug_printf("%s: failed to send dirty (%i, %s)\n",
599			     __func__, ret, strerror(-ret));
600	    }
601
602	    DamageEmpty(ms->damage);
603	}
604    }
605#endif
606}
607
608static void drv_block_handler(int i, pointer blockData, pointer pTimeout,
609                              pointer pReadmask)
610{
611    ScreenPtr pScreen = screenInfo.screens[i];
612    modesettingPtr ms = modesettingPTR(xf86Screens[pScreen->myNum]);
613
614    pScreen->BlockHandler = ms->blockHandler;
615    pScreen->BlockHandler(i, blockData, pTimeout, pReadmask);
616    pScreen->BlockHandler = drv_block_handler;
617
618    xorg_flush(pScreen);
619}
620
621static Bool
622drv_create_screen_resources(ScreenPtr pScreen)
623{
624    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
625    modesettingPtr ms = modesettingPTR(pScrn);
626    PixmapPtr rootPixmap;
627    Bool ret;
628
629    ms->noEvict = TRUE;
630
631    pScreen->CreateScreenResources = ms->createScreenResources;
632    ret = pScreen->CreateScreenResources(pScreen);
633    pScreen->CreateScreenResources = drv_create_screen_resources;
634
635    ms->bind_front_buffer(pScrn);
636
637    ms->noEvict = FALSE;
638
639    drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
640
641#ifdef DRM_MODE_FEATURE_DIRTYFB
642    rootPixmap = pScreen->GetScreenPixmap(pScreen);
643    ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE,
644                              pScreen, rootPixmap);
645
646    if (ms->damage) {
647       DamageRegister(&rootPixmap->drawable, ms->damage);
648
649       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n");
650    } else {
651       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
652                  "Failed to create screen damage record\n");
653       return FALSE;
654    }
655#else
656    (void)rootPixmap;
657#endif
658
659    return ret;
660}
661
662static Bool
663drv_set_master(ScrnInfoPtr pScrn)
664{
665    modesettingPtr ms = modesettingPTR(pScrn);
666
667    if (!ms->isMaster && drmSetMaster(ms->fd) != 0) {
668	if (errno == EINVAL) {
669	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
670		       "drmSetMaster failed: 2.6.29 or newer kernel required for "
671		       "multi-server DRI\n");
672	} else {
673	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
674		       "drmSetMaster failed: %s\n", strerror(errno));
675	}
676	return FALSE;
677    }
678
679    ms->isMaster = TRUE;
680    return TRUE;
681}
682
683
684static void drv_load_palette(ScrnInfoPtr pScrn, int numColors,
685			     int *indices, LOCO *colors, VisualPtr pVisual)
686{
687    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
688    modesettingPtr ms = modesettingPTR(pScrn);
689    int index, j, i;
690    int c;
691
692    switch(pScrn->depth) {
693    case 15:
694	for (i = 0; i < numColors; i++) {
695	    index = indices[i];
696	    for (j = 0; j < 8; j++) {
697		ms->lut_r[index * 8 + j] = colors[index].red << 8;
698		ms->lut_g[index * 8 + j] = colors[index].green << 8;
699		ms->lut_b[index * 8 + j] = colors[index].blue << 8;
700	    }
701	}
702	break;
703    case 16:
704	for (i = 0; i < numColors; i++) {
705	    index = indices[i];
706
707	    if (index < 32) {
708		for (j = 0; j < 8; j++) {
709		    ms->lut_r[index * 8 + j] = colors[index].red << 8;
710		    ms->lut_b[index * 8 + j] = colors[index].blue << 8;
711		}
712	    }
713
714	    for (j = 0; j < 4; j++) {
715		ms->lut_g[index * 4 + j] = colors[index].green << 8;
716	    }
717	}
718	break;
719    default:
720	for (i = 0; i < numColors; i++) {
721	    index = indices[i];
722	    ms->lut_r[index] = colors[index].red << 8;
723	    ms->lut_g[index] = colors[index].green << 8;
724	    ms->lut_b[index] = colors[index].blue << 8;
725	}
726	break;
727    }
728
729    for (c = 0; c < xf86_config->num_crtc; c++) {
730	xf86CrtcPtr crtc = xf86_config->crtc[c];
731
732	/* Make the change through RandR */
733#ifdef RANDR_12_INTERFACE
734	if (crtc->randr_crtc)
735	    RRCrtcGammaSet(crtc->randr_crtc, ms->lut_r, ms->lut_g, ms->lut_b);
736	else
737#endif
738	    crtc->funcs->gamma_set(crtc, ms->lut_r, ms->lut_g, ms->lut_b, 256);
739    }
740}
741
742
743static Bool
744drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
745{
746    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
747    modesettingPtr ms = modesettingPTR(pScrn);
748    VisualPtr visual;
749    CustomizerPtr cust = ms->cust;
750    MessageType from_st;
751    MessageType from_dt;
752
753    if (!drv_set_master(pScrn))
754	return FALSE;
755
756    if (!drv_init_front_buffer_functions(pScrn)) {
757	FatalError("Could not init front buffer manager");
758	return FALSE;
759    }
760
761    pScrn->pScreen = pScreen;
762
763    /* HW dependent - FIXME */
764    pScrn->displayWidth = pScrn->virtualX;
765
766    miClearVisualTypes();
767
768    if (!miSetVisualTypes(pScrn->depth,
769			  miGetDefaultVisualMask(pScrn->depth),
770			  pScrn->rgbBits, pScrn->defaultVisual))
771	return FALSE;
772
773    if (!miSetPixmapDepths())
774	return FALSE;
775
776    pScrn->memPhysBase = 0;
777    pScrn->fbOffset = 0;
778
779    if (!fbScreenInit(pScreen, NULL,
780		      pScrn->virtualX, pScrn->virtualY,
781		      pScrn->xDpi, pScrn->yDpi,
782		      pScrn->displayWidth, pScrn->bitsPerPixel))
783	return FALSE;
784
785    if (pScrn->bitsPerPixel > 8) {
786	/* Fixup RGB ordering */
787	visual = pScreen->visuals + pScreen->numVisuals;
788	while (--visual >= pScreen->visuals) {
789	    if ((visual->class | DynamicClass) == DirectColor) {
790		visual->offsetRed = pScrn->offset.red;
791		visual->offsetGreen = pScrn->offset.green;
792		visual->offsetBlue = pScrn->offset.blue;
793		visual->redMask = pScrn->mask.red;
794		visual->greenMask = pScrn->mask.green;
795		visual->blueMask = pScrn->mask.blue;
796	    }
797	}
798    }
799
800    fbPictureInit(pScreen, NULL, 0);
801
802    ms->blockHandler = pScreen->BlockHandler;
803    pScreen->BlockHandler = drv_block_handler;
804    ms->createScreenResources = pScreen->CreateScreenResources;
805    pScreen->CreateScreenResources = drv_create_screen_resources;
806
807    xf86SetBlackWhitePixels(pScreen);
808
809    ms->accelerate_2d = xf86ReturnOptValBool(ms->Options, OPTION_2D_ACCEL, FALSE);
810    ms->debug_fallback = xf86ReturnOptValBool(ms->Options, OPTION_DEBUG_FALLBACK, ms->accelerate_2d);
811
812    if (cust && cust->winsys_screen_init)
813	cust->winsys_screen_init(cust);
814
815    ms->swapThrottling = cust ?  cust->swap_throttling : TRUE;
816    from_st = xf86GetOptValBool(ms->Options, OPTION_THROTTLE_SWAP,
817				&ms->swapThrottling) ?
818	X_CONFIG : X_DEFAULT;
819
820    ms->dirtyThrottling = cust ?  cust->dirty_throttling : TRUE;
821    from_dt = xf86GetOptValBool(ms->Options, OPTION_THROTTLE_DIRTY,
822				&ms->dirtyThrottling) ?
823	X_CONFIG : X_DEFAULT;
824
825    if (ms->screen) {
826	ms->exa = xorg_exa_init(pScrn, ms->accelerate_2d);
827
828	xorg_xv_init(pScreen);
829#ifdef DRI2
830	xorg_dri2_init(pScreen);
831#endif
832    }
833
834    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "##################################\n");
835    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "# Usefull debugging info follows #\n");
836    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "##################################\n");
837    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %s backend\n",
838	       ms->screen ? "Gallium3D" : "libkms");
839    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D Acceleration is %s\n",
840	       ms->screen && ms->accelerate_2d ? "enabled" : "disabled");
841    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Fallback debugging is %s\n",
842	       ms->debug_fallback ? "enabled" : "disabled");
843#ifdef DRI2
844    xf86DrvMsg(pScrn->scrnIndex, ms->from_3D, "3D Acceleration is %s\n",
845	       ms->screen ? "enabled" : "disabled");
846#else
847    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "3D Acceleration is disabled\n");
848#endif
849    xf86DrvMsg(pScrn->scrnIndex, from_st, "Swap Throttling is %s.\n",
850	       ms->swapThrottling ? "enabled" : "disabled");
851    xf86DrvMsg(pScrn->scrnIndex, from_dt, "Dirty Throttling is %s.\n",
852	       ms->dirtyThrottling ? "enabled" : "disabled");
853
854    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "##################################\n");
855
856    miInitializeBackingStore(pScreen);
857    xf86SetBackingStore(pScreen);
858    xf86SetSilkenMouse(pScreen);
859    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
860
861    /* Need to extend HWcursor support to handle mask interleave */
862    if (!ms->SWCursor)
863	xf86_cursors_init(pScreen, 64, 64,
864			  HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
865			  HARDWARE_CURSOR_ARGB |
866			  ((cust && cust->unhidden_hw_cursor_update) ?
867			   HARDWARE_CURSOR_UPDATE_UNHIDDEN : 0));
868
869    /* Must force it before EnterVT, so we are in control of VT and
870     * later memory should be bound when allocating, e.g rotate_mem */
871    pScrn->vtSema = TRUE;
872
873    pScreen->SaveScreen = xf86SaveScreen;
874    ms->CloseScreen = pScreen->CloseScreen;
875    pScreen->CloseScreen = drv_close_screen;
876
877    if (!xf86CrtcScreenInit(pScreen))
878	return FALSE;
879
880    if (!miCreateDefColormap(pScreen))
881	return FALSE;
882    if (!xf86HandleColormaps(pScreen, 256, 8, drv_load_palette, NULL,
883			     CMAP_PALETTED_TRUECOLOR |
884			     CMAP_RELOAD_ON_MODE_SWITCH))
885	return FALSE;
886
887    xf86DPMSInit(pScreen, xf86DPMSSet, 0);
888
889    if (serverGeneration == 1)
890	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
891
892    return drv_enter_vt(scrnIndex, 1);
893}
894
895static void
896drv_adjust_frame(int scrnIndex, int x, int y, int flags)
897{
898    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
899    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
900    xf86OutputPtr output = config->output[config->compat_output];
901    xf86CrtcPtr crtc = output->crtc;
902
903    if (crtc && crtc->enabled) {
904	crtc->funcs->set_mode_major(crtc, pScrn->currentMode,
905				    RR_Rotate_0, x, y);
906	crtc->x = output->initial_x + x;
907	crtc->y = output->initial_y + y;
908    }
909}
910
911static void
912drv_free_screen(int scrnIndex, int flags)
913{
914    drv_free_rec(xf86Screens[scrnIndex]);
915}
916
917static void
918drv_leave_vt(int scrnIndex, int flags)
919{
920    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
921    modesettingPtr ms = modesettingPTR(pScrn);
922    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
923    CustomizerPtr cust = ms->cust;
924    int o;
925
926    if (cust && cust->winsys_leave_vt)
927	cust->winsys_leave_vt(cust);
928
929    for (o = 0; o < config->num_crtc; o++) {
930	xf86CrtcPtr crtc = config->crtc[o];
931
932	xorg_crtc_cursor_destroy(crtc);
933
934	if (crtc->rotatedPixmap || crtc->rotatedData) {
935	    crtc->funcs->shadow_destroy(crtc, crtc->rotatedPixmap,
936					crtc->rotatedData);
937	    crtc->rotatedPixmap = NULL;
938	    crtc->rotatedData = NULL;
939	}
940    }
941
942    if (ms->fb_id != -1) {
943	drmModeRmFB(ms->fd, ms->fb_id);
944	ms->fb_id = -1;
945    }
946
947    /* idle hardware */
948    if (!ms->kms)
949	drv_cleanup_fences(pScrn);
950
951    if (drmDropMaster(ms->fd))
952	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
953		   "drmDropMaster failed: %s\n", strerror(errno));
954
955    ms->isMaster = FALSE;
956    pScrn->vtSema = FALSE;
957}
958
959/*
960 * This gets called when gaining control of the VT, and from ScreenInit().
961 */
962static Bool
963drv_enter_vt(int scrnIndex, int flags)
964{
965    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
966    modesettingPtr ms = modesettingPTR(pScrn);
967    CustomizerPtr cust = ms->cust;
968
969    if (!drv_set_master(pScrn))
970	return FALSE;
971
972    if (!ms->create_front_buffer(pScrn))
973	return FALSE;
974
975    if (!flags && !ms->bind_front_buffer(pScrn))
976	return FALSE;
977
978    if (!xf86SetDesiredModes(pScrn))
979	return FALSE;
980
981    if (cust && cust->winsys_enter_vt)
982	cust->winsys_enter_vt(cust);
983
984    return TRUE;
985}
986
987static Bool
988drv_switch_mode(int scrnIndex, DisplayModePtr mode, int flags)
989{
990    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
991
992    return xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
993}
994
995static Bool
996drv_close_screen(int scrnIndex, ScreenPtr pScreen)
997{
998    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
999    modesettingPtr ms = modesettingPTR(pScrn);
1000    CustomizerPtr cust = ms->cust;
1001
1002    if (ms->cursor) {
1003       FreeCursor(ms->cursor, None);
1004       ms->cursor = NULL;
1005    }
1006
1007    if (cust && cust->winsys_screen_close)
1008	cust->winsys_screen_close(cust);
1009
1010#ifdef DRI2
1011    if (ms->screen)
1012	xorg_dri2_close(pScreen);
1013#endif
1014
1015    pScreen->BlockHandler = ms->blockHandler;
1016    pScreen->CreateScreenResources = ms->createScreenResources;
1017
1018#ifdef DRM_MODE_FEATURE_DIRTYFB
1019    if (ms->damage) {
1020	DamageUnregister(&pScreen->GetScreenPixmap(pScreen)->drawable, ms->damage);
1021	DamageDestroy(ms->damage);
1022	ms->damage = NULL;
1023    }
1024#endif
1025
1026    ms->destroy_front_buffer(pScrn);
1027
1028    if (ms->exa)
1029	xorg_exa_close(pScrn);
1030    ms->exa = NULL;
1031
1032    /* calls drop master make sure we don't talk to 3D HW after that */
1033    if (pScrn->vtSema) {
1034	drv_leave_vt(scrnIndex, 0);
1035    }
1036
1037    pScrn->vtSema = FALSE;
1038    pScreen->CloseScreen = ms->CloseScreen;
1039
1040    return (*pScreen->CloseScreen) (scrnIndex, pScreen);
1041}
1042
1043static ModeStatus
1044drv_valid_mode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
1045{
1046    return MODE_OK;
1047}
1048
1049
1050/*
1051 * Front buffer backing store functions.
1052 */
1053
1054static Bool
1055drv_destroy_front_buffer_ga3d(ScrnInfoPtr pScrn)
1056{
1057    modesettingPtr ms = modesettingPTR(pScrn);
1058
1059    if (!ms->root_texture)
1060	return TRUE;
1061
1062    if (ms->fb_id != -1) {
1063	drmModeRmFB(ms->fd, ms->fb_id);
1064	ms->fb_id = -1;
1065    }
1066
1067    pipe_resource_reference(&ms->root_texture, NULL);
1068    return TRUE;
1069}
1070
1071static Bool
1072drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn)
1073{
1074    modesettingPtr ms = modesettingPTR(pScrn);
1075    struct pipe_resource *tex;
1076    struct winsys_handle whandle;
1077    unsigned fb_id;
1078    int ret;
1079
1080    ms->noEvict = TRUE;
1081
1082    tex = xorg_exa_create_root_texture(pScrn, pScrn->virtualX, pScrn->virtualY,
1083				       pScrn->depth, pScrn->bitsPerPixel);
1084
1085    if (!tex)
1086	return FALSE;
1087
1088    memset(&whandle, 0, sizeof(whandle));
1089    whandle.type = DRM_API_HANDLE_TYPE_KMS;
1090
1091    if (!ms->screen->resource_get_handle(ms->screen, tex, &whandle))
1092	goto err_destroy;
1093
1094    ret = drmModeAddFB(ms->fd,
1095		       pScrn->virtualX,
1096		       pScrn->virtualY,
1097		       pScrn->depth,
1098		       pScrn->bitsPerPixel,
1099		       whandle.stride,
1100		       whandle.handle,
1101		       &fb_id);
1102    if (ret) {
1103	debug_printf("%s: failed to create framebuffer (%i, %s)\n",
1104		     __func__, ret, strerror(-ret));
1105	goto err_destroy;
1106    }
1107
1108    if (!drv_destroy_front_buffer_ga3d(pScrn))
1109	FatalError("%s: failed to take down old framebuffer\n", __func__);
1110
1111    pScrn->frameX0 = 0;
1112    pScrn->frameY0 = 0;
1113    drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
1114
1115    pipe_resource_reference(&ms->root_texture, tex);
1116    pipe_resource_reference(&tex, NULL);
1117    ms->fb_id = fb_id;
1118
1119    return TRUE;
1120
1121err_destroy:
1122    pipe_resource_reference(&tex, NULL);
1123    return FALSE;
1124}
1125
1126static Bool
1127drv_bind_front_buffer_ga3d(ScrnInfoPtr pScrn)
1128{
1129    modesettingPtr ms = modesettingPTR(pScrn);
1130    ScreenPtr pScreen = pScrn->pScreen;
1131    PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
1132    struct pipe_resource *check;
1133
1134    xorg_exa_set_displayed_usage(rootPixmap);
1135    xorg_exa_set_shared_usage(rootPixmap);
1136    xorg_exa_set_texture(rootPixmap, ms->root_texture);
1137    if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, NULL))
1138	FatalError("Couldn't adjust screen pixmap\n");
1139
1140    check = xorg_exa_get_texture(rootPixmap);
1141    if (ms->root_texture != check)
1142	FatalError("Created new root texture\n");
1143
1144    pipe_resource_reference(&check, NULL);
1145    return TRUE;
1146}
1147
1148#ifdef HAVE_LIBKMS
1149static Bool
1150drv_destroy_front_buffer_kms(ScrnInfoPtr pScrn)
1151{
1152    modesettingPtr ms = modesettingPTR(pScrn);
1153    ScreenPtr pScreen = pScrn->pScreen;
1154    PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
1155
1156    /* XXX Do something with the rootPixmap.
1157     * This currently works fine but if we are getting crashes in
1158     * the fb functions after VT switches maybe look more into it.
1159     */
1160    (void)rootPixmap;
1161
1162    if (!ms->root_bo)
1163	return TRUE;
1164
1165    if (ms->fb_id != -1) {
1166	drmModeRmFB(ms->fd, ms->fb_id);
1167	ms->fb_id = -1;
1168    }
1169
1170    kms_bo_unmap(ms->root_bo);
1171    kms_bo_destroy(&ms->root_bo);
1172    return TRUE;
1173}
1174
1175static Bool
1176drv_create_front_buffer_kms(ScrnInfoPtr pScrn)
1177{
1178    modesettingPtr ms = modesettingPTR(pScrn);
1179    unsigned handle, stride;
1180    struct kms_bo *bo;
1181    unsigned attr[8];
1182    unsigned fb_id;
1183    int ret;
1184
1185    attr[0] = KMS_BO_TYPE;
1186#ifdef KMS_BO_TYPE_SCANOUT_X8R8G8B8
1187    attr[1] = KMS_BO_TYPE_SCANOUT_X8R8G8B8;
1188#else
1189    attr[1] = KMS_BO_TYPE_SCANOUT;
1190#endif
1191    attr[2] = KMS_WIDTH;
1192    attr[3] = pScrn->virtualX;
1193    attr[4] = KMS_HEIGHT;
1194    attr[5] = pScrn->virtualY;
1195    attr[6] = 0;
1196
1197    if (kms_bo_create(ms->kms, attr, &bo))
1198	return FALSE;
1199
1200    if (kms_bo_get_prop(bo, KMS_PITCH, &stride))
1201	goto err_destroy;
1202
1203    if (kms_bo_get_prop(bo, KMS_HANDLE, &handle))
1204	goto err_destroy;
1205
1206    ret = drmModeAddFB(ms->fd,
1207		       pScrn->virtualX,
1208		       pScrn->virtualY,
1209		       pScrn->depth,
1210		       pScrn->bitsPerPixel,
1211		       stride,
1212		       handle,
1213		       &fb_id);
1214    if (ret) {
1215	debug_printf("%s: failed to create framebuffer (%i, %s)",
1216		     __func__, ret, strerror(-ret));
1217	goto err_destroy;
1218    }
1219
1220    if (!drv_destroy_front_buffer_kms(pScrn))
1221	FatalError("%s: could not takedown old bo", __func__);
1222
1223    pScrn->frameX0 = 0;
1224    pScrn->frameY0 = 0;
1225    drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
1226    ms->root_bo = bo;
1227    ms->fb_id = fb_id;
1228
1229    return TRUE;
1230
1231err_destroy:
1232    kms_bo_destroy(&bo);
1233    return FALSE;
1234}
1235
1236static Bool
1237drv_bind_front_buffer_kms(ScrnInfoPtr pScrn)
1238{
1239    modesettingPtr ms = modesettingPTR(pScrn);
1240    ScreenPtr pScreen = pScrn->pScreen;
1241    PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
1242    unsigned stride;
1243    void *ptr;
1244
1245    if (kms_bo_get_prop(ms->root_bo, KMS_PITCH, &stride))
1246	return FALSE;
1247
1248    if (kms_bo_map(ms->root_bo, &ptr))
1249	goto err_destroy;
1250
1251    pScreen->ModifyPixmapHeader(rootPixmap,
1252				pScrn->virtualX,
1253				pScrn->virtualY,
1254				pScreen->rootDepth,
1255				pScrn->bitsPerPixel,
1256				stride,
1257				ptr);
1258
1259#if (XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 9, 99, 1, 0))
1260
1261    /* This a hack to work around EnableDisableFBAccess setting the pointer
1262     * the real fix would be to replace pScrn->EnableDisableFBAccess hook
1263     * and set the rootPixmap->devPrivate.ptr to something valid before that.
1264     *
1265     * But in its infinit visdome something uses either this some times before
1266     * that, so our hook doesn't get called before the crash happens.
1267     */
1268    pScrn->pixmapPrivate.ptr = ptr;
1269
1270#endif
1271
1272    return TRUE;
1273
1274err_destroy:
1275    kms_bo_destroy(&ms->root_bo);
1276    return FALSE;
1277}
1278#endif /* HAVE_LIBKMS */
1279
1280static Bool drv_init_front_buffer_functions(ScrnInfoPtr pScrn)
1281{
1282    modesettingPtr ms = modesettingPTR(pScrn);
1283    if (ms->screen) {
1284	ms->destroy_front_buffer = drv_destroy_front_buffer_ga3d;
1285	ms->create_front_buffer = drv_create_front_buffer_ga3d;
1286	ms->bind_front_buffer = drv_bind_front_buffer_ga3d;
1287#ifdef HAVE_LIBKMS
1288    } else if (ms->kms) {
1289	ms->destroy_front_buffer = drv_destroy_front_buffer_kms;
1290	ms->create_front_buffer = drv_create_front_buffer_kms;
1291	ms->bind_front_buffer = drv_bind_front_buffer_kms;
1292#endif
1293    } else
1294	return FALSE;
1295
1296    return TRUE;
1297}
1298
1299CustomizerPtr xorg_customizer(ScrnInfoPtr pScrn)
1300{
1301    return modesettingPTR(pScrn)->cust;
1302}
1303
1304Bool xorg_has_gallium(ScrnInfoPtr pScrn)
1305{
1306    return modesettingPTR(pScrn)->screen != NULL;
1307}
1308
1309/* vim: set sw=4 ts=8 sts=4: */
1310