Created
February 19, 2015 12:02
-
-
Save carlocaione/0839701c89cacd5986ac to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */ | |
/* | |
* Copyright © 2011 Texas Instruments, Inc | |
* | |
* Permission is hereby granted, free of charge, to any person obtaining a | |
* copy of this software and associated documentation files (the "Software"), | |
* to deal in the Software without restriction, including without limitation | |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
* and/or sell copies of the Software, and to permit persons to whom the | |
* Software is furnished to do so, subject to the following conditions: | |
* | |
* The above copyright notice and this permission notice (including the next | |
* paragraph) shall be included in all copies or substantial portions of the | |
* Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
* SOFTWARE. | |
* | |
* Authors: | |
* Ian Elliott <ianelliottus@yahoo.com> | |
* Rob Clark <rob@ti.com> | |
*/ | |
#include <sys/types.h> | |
#include <time.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <unistd.h> | |
#include <linux/fb.h> | |
#include <sys/ioctl.h> | |
#include <sys/mman.h> | |
#include <pixman.h> | |
#include <ump/ump.h> | |
#include <ump/ump_ref_drv.h> | |
#ifdef HAVE_CONFIG_H | |
#include "config.h" | |
#endif | |
#include "armsoc_driver.h" | |
#include "micmap.h" | |
#include "xf86cmap.h" | |
#include "xf86RandR12.h" | |
#include "xf86drmMode.h" | |
#include "compat-api.h" | |
#include "drmmode_driver.h" | |
#define DRM_DEVICE "/dev/dri/card%d" | |
Bool armsocDebug; | |
/* | |
* Forward declarations: | |
*/ | |
static const OptionInfoRec *ARMSOCAvailableOptions(int chipid, int busid); | |
static void ARMSOCIdentify(int flags); | |
static Bool ARMSOCProbe(DriverPtr drv, int flags); | |
static Bool ARMSOCPreInit(ScrnInfoPtr pScrn, int flags); | |
static Bool ARMSOCScreenInit(SCREEN_INIT_ARGS_DECL); | |
static void ARMSOCLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, | |
LOCO *colors, VisualPtr pVisual); | |
static Bool ARMSOCCloseScreen(CLOSE_SCREEN_ARGS_DECL); | |
static Bool ARMSOCCreateScreenResources(ScreenPtr pScreen); | |
static void ARMSOCBlockHandler(BLOCKHANDLER_ARGS_DECL); | |
static Bool ARMSOCSwitchMode(SWITCH_MODE_ARGS_DECL); | |
static void ARMSOCAdjustFrame(ADJUST_FRAME_ARGS_DECL); | |
static Bool ARMSOCEnterVT(VT_FUNC_ARGS_DECL); | |
static void ARMSOCLeaveVT(VT_FUNC_ARGS_DECL); | |
static void ARMSOCFreeScreen(FREE_SCREEN_ARGS_DECL); | |
/** | |
* A structure used by the XFree86 code when loading this driver, so that it | |
* can access the Probe() function, and other functions/info that it uses | |
* before it calls the Probe() function. The name of this structure must be | |
* the all-upper-case version of the driver name. | |
*/ | |
_X_EXPORT DriverRec ARMSOC = { | |
ARMSOC_VERSION, | |
(char *)ARMSOC_DRIVER_NAME, | |
ARMSOCIdentify, | |
ARMSOCProbe, | |
ARMSOCAvailableOptions, | |
NULL, | |
0, | |
NULL, | |
#ifdef XSERVER_LIBPCIACCESS | |
NULL, | |
NULL | |
#endif | |
}; | |
/** Supported "chipsets." */ | |
#define ARMSOC_CHIPSET_NAME "Mali" | |
/** Supported options, as enum values. */ | |
enum { | |
OPTION_DEBUG, | |
OPTION_NO_FLIP, | |
OPTION_CARD_NUM, | |
OPTION_BUSID, | |
OPTION_DRIVERNAME, | |
OPTION_DRI_NUM_BUF, | |
OPTION_INIT_FROM_FBDEV, | |
}; | |
/** Supported options. */ | |
static const OptionInfoRec ARMSOCOptions[] = { | |
{ OPTION_DEBUG, "Debug", OPTV_BOOLEAN, {0}, FALSE }, | |
{ OPTION_NO_FLIP, "NoFlip", OPTV_BOOLEAN, {0}, FALSE }, | |
{ OPTION_CARD_NUM, "DRICard", OPTV_INTEGER, {0}, FALSE }, | |
{ OPTION_BUSID, "BusID", OPTV_STRING, {0}, FALSE }, | |
{ OPTION_DRIVERNAME, "DriverName", OPTV_STRING, {0}, FALSE }, | |
{ OPTION_DRI_NUM_BUF, "DRI2MaxBuffers", OPTV_INTEGER, {-1}, FALSE }, | |
{ OPTION_INIT_FROM_FBDEV, "InitFromFBDev", OPTV_STRING, {0}, FALSE }, | |
{ -1, NULL, OPTV_NONE, {0}, FALSE } | |
}; | |
/** | |
* Helper functions for sharing a DRM connection across screens. | |
*/ | |
static struct ARMSOCConnection { | |
const char *driver_name; | |
const char *bus_id; | |
unsigned int card_num; | |
int fd; | |
int open_count; | |
int master_count; | |
} connection = {NULL, NULL, 0, -1, 0, 0}; | |
static int | |
ARMSOCSetDRMMaster(void) | |
{ | |
int ret = 0; | |
assert(connection.fd >= 0); | |
if (!connection.master_count) | |
ret = drmSetMaster(connection.fd); | |
if (!ret) | |
connection.master_count++; | |
return ret; | |
} | |
static int | |
ARMSOCDropDRMMaster(void) | |
{ | |
int ret = 0; | |
assert(connection.fd >= 0); | |
assert(connection.master_count > 0); | |
if (1 == connection.master_count) | |
ret = drmDropMaster(connection.fd); | |
if (!ret) | |
connection.master_count--; | |
return ret; | |
} | |
static void | |
ARMSOCShowDriverInfo(int fd) | |
{ | |
char *bus_id; | |
drmVersionPtr version; | |
char *deviceName; | |
EARLY_INFO_MSG("Opened DRM"); | |
deviceName = drmGetDeviceNameFromFd(fd); | |
EARLY_INFO_MSG(" DeviceName is [%s]", | |
deviceName ? deviceName : "NULL"); | |
drmFree(deviceName); | |
bus_id = drmGetBusid(fd); | |
EARLY_INFO_MSG(" bus_id is [%s]", | |
bus_id ? bus_id : "NULL"); | |
drmFreeBusid(bus_id); | |
version = drmGetVersion(fd); | |
if (version) { | |
EARLY_INFO_MSG(" DriverName is [%s]", | |
version->name); | |
EARLY_INFO_MSG(" version is [%d.%d.%d]", | |
version->version_major, | |
version->version_minor, | |
version->version_patchlevel); | |
drmFreeVersion(version); | |
} else { | |
EARLY_INFO_MSG(" version is [NULL]"); | |
} | |
return; | |
} | |
static int | |
ARMSOCOpenDRMCard(void) | |
{ | |
int fd; | |
if ((connection.bus_id) || (connection.driver_name)) { | |
/* user specified bus ID or driver name - pass to drmOpen */ | |
EARLY_INFO_MSG("Opening driver [%s], bus_id [%s]", | |
connection.driver_name ? | |
connection.driver_name : "NULL", | |
connection.bus_id ? | |
connection.bus_id : "NULL"); | |
fd = drmOpen(connection.driver_name, connection.bus_id); | |
if (fd < 0) | |
goto fail2; | |
} else { | |
char filename[32]; | |
int err; | |
drmSetVersion sv; | |
char *bus_id, *bus_id_copy; | |
/* open with card_num */ | |
snprintf(filename, sizeof(filename), | |
DRM_DEVICE, connection.card_num); | |
EARLY_INFO_MSG( | |
"No BusID or DriverName specified - opening %s", | |
filename); | |
fd = open(filename, O_RDWR, 0); | |
if (-1 == fd) | |
goto fail2; | |
/* Set interface version to initialise bus id */ | |
sv.drm_di_major = 1; | |
sv.drm_di_minor = 1; | |
sv.drm_dd_major = -1; | |
sv.drm_dd_minor = -1; | |
err = drmSetInterfaceVersion(fd, &sv); | |
if (err) { | |
EARLY_ERROR_MSG( | |
"Cannot set the DRM interface version."); | |
goto fail1; | |
} | |
/* get the bus id */ | |
bus_id = drmGetBusid(fd); | |
if (!bus_id) { | |
EARLY_ERROR_MSG("Couldn't get BusID from %s", | |
filename); | |
goto fail1; | |
} | |
EARLY_INFO_MSG("Got BusID %s", bus_id); | |
bus_id_copy = malloc(strlen(bus_id)+1); | |
if (!bus_id_copy) { | |
EARLY_ERROR_MSG("Memory alloc failed"); | |
goto fail1; | |
} | |
strcpy(bus_id_copy, bus_id); | |
drmFreeBusid(bus_id); | |
err = close(fd); | |
if (err) { | |
free(bus_id_copy); | |
EARLY_ERROR_MSG("Couldn't close %s", filename); | |
goto fail2; | |
} | |
/* use bus_id to open driver */ | |
fd = drmOpen(NULL, bus_id_copy); | |
free(bus_id_copy); | |
if (fd < 0) | |
goto fail2; | |
} | |
ARMSOCShowDriverInfo(fd); | |
return fd; | |
fail1: | |
close(fd); | |
fail2: | |
EARLY_ERROR_MSG( | |
"Cannot open a connection with the DRM - %s", | |
strerror(errno)); | |
return -1; | |
} | |
static Bool | |
ARMSOCOpenDRM(ScrnInfoPtr pScrn) | |
{ | |
struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); | |
drmSetVersion sv; | |
int err; | |
if (connection.fd < 0) { | |
assert(!connection.open_count); | |
assert(!connection.master_count); | |
pARMSOC->drmFD = ARMSOCOpenDRMCard(); | |
if (pARMSOC->drmFD < 0) | |
return FALSE; | |
/* Check that what we are or can become drm master by | |
* attempting a drmSetInterfaceVersion(). If successful | |
* this leaves us as master. | |
* (see DRIOpenDRMMaster() in DRI1) | |
*/ | |
sv.drm_di_major = 1; | |
sv.drm_di_minor = 1; | |
sv.drm_dd_major = -1; | |
sv.drm_dd_minor = -1; | |
err = drmSetInterfaceVersion(pARMSOC->drmFD, &sv); | |
if (err != 0) { | |
ERROR_MSG("Cannot set the DRM interface version."); | |
drmClose(pARMSOC->drmFD); | |
pARMSOC->drmFD = -1; | |
return FALSE; | |
} | |
connection.fd = pARMSOC->drmFD; | |
connection.open_count = 1; | |
connection.master_count = 1; | |
} else { | |
assert(connection.open_count); | |
connection.open_count++; | |
connection.master_count++; | |
pARMSOC->drmFD = connection.fd; | |
} | |
pARMSOC->deviceName = drmGetDeviceNameFromFd(pARMSOC->drmFD); | |
return TRUE; | |
} | |
/** | |
* Helper function for closing a connection to the DRM. | |
*/ | |
static void | |
ARMSOCCloseDRM(ScrnInfoPtr pScrn) | |
{ | |
struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); | |
if (pARMSOC && (pARMSOC->drmFD >= 0)) { | |
drmFree(pARMSOC->deviceName); | |
connection.open_count--; | |
if (!connection.open_count) { | |
assert(!connection.master_count); | |
drmClose(pARMSOC->drmFD); | |
connection.fd = -1; | |
} | |
pARMSOC->drmFD = -1; | |
} | |
} | |
static Bool ARMSOCCopyFB(ScrnInfoPtr pScrn, const char *fb_dev, unsigned char *src, drmModeFBPtr fb, drmModeCrtcPtr crtc) | |
{ | |
struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); | |
int src_cpp; | |
uint32_t src_pitch; | |
int src_pixman_stride; | |
int dst_pixman_stride; | |
int dst_width, dst_height, dst_bpp, dst_pitch; | |
unsigned int src_size = 0; | |
unsigned char *dst = NULL; | |
struct fb_var_screeninfo vinfo; | |
int fd = -1; | |
int width, height; | |
FILE *file = fopen("/root/LOG", "a"); | |
pixman_bool_t pixman_ret; | |
Bool ret = FALSE; | |
fb_dev = NULL; | |
dst = armsoc_bo_map(pARMSOC->scanout); | |
if (!dst) { | |
ERROR_MSG("Couldn't map scanout bo"); | |
fputs("Couldn't map scanout bo", file); | |
goto exit; | |
} | |
// fd = open(fb_dev, O_RDONLY | O_SYNC); | |
// if (fd == -1) { | |
// ERROR_MSG("Couldn't open %s", fb_dev); | |
// goto exit; | |
// } | |
// | |
// if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0) { | |
// ERROR_MSG("Vscreeninfo ioctl failed"); | |
// goto exit; | |
// } | |
memset(&vinfo, 0, sizeof(vinfo)); | |
vinfo.bits_per_pixel = fb->bpp; | |
vinfo.xres_virtual = fb->width; | |
vinfo.yres_virtual = fb->height; | |
vinfo.xoffset = crtc->x; | |
vinfo.yoffset = crtc->y; | |
src_cpp = (vinfo.bits_per_pixel + 7) / 8; | |
src_pitch = vinfo.xres_virtual * src_cpp; | |
src_size = vinfo.yres_virtual * src_pitch; | |
vinfo.xres = vinfo.xres_virtual; | |
vinfo.yres = vinfo.yres_virtual; | |
fprintf(file, "vinfo.bits_per_pixel: %d, vinfo.xres_virtual: %d, vinfo.yres_virtual: %d, vinfo.xoffset: %d, vinfo.yoffset: %d, src_cpp: %d, src_pitch: %d, src_size:%d\n", | |
vinfo.bits_per_pixel, vinfo.xres_virtual, vinfo.yres_virtual, vinfo.xoffset, | |
vinfo.yoffset, src_cpp, src_pitch, src_size); | |
// src = mmap(NULL, src_size, PROT_READ, MAP_SHARED, fd, 0); | |
// if (src == MAP_FAILED) { | |
// ERROR_MSG("Couldn't mmap %s", fb_dev); | |
// fprintf(file, "Couldn't mmap %s", fb_dev); | |
// goto exit; | |
// } | |
dst_width = armsoc_bo_width(pARMSOC->scanout); | |
dst_height = armsoc_bo_height(pARMSOC->scanout); | |
dst_bpp = armsoc_bo_bpp(pARMSOC->scanout); | |
dst_pitch = armsoc_bo_pitch(pARMSOC->scanout); | |
width = min(vinfo.xres, dst_width); | |
height = min(vinfo.yres, dst_height); | |
fprintf(file, "dst_width: %d, dst_height: %d, dst_bpp: %d, dst_pitch: %d, width: %d, height: %d\n", dst_width, dst_height, dst_bpp, dst_pitch, width, height); | |
/* The stride parameters pixman takes are in multiples of uint32_t, | |
* which is the data type of the pointer passed */ | |
src_pixman_stride = src_pitch/sizeof(uint32_t); | |
dst_pixman_stride = dst_pitch/sizeof(uint32_t); | |
fprintf(file, "src_pixman_stride: %d, dst_pixman_stride: %d\n", src_pixman_stride, dst_pixman_stride); | |
/* We could handle the cases where stride is not a multiple of uint32_t, | |
* but they will be rare so not currently worth the added complexity */ | |
if (src_pitch%sizeof(uint32_t) || dst_pitch%sizeof(uint32_t)) { | |
ERROR_MSG( | |
"Buffer strides need to be a multiple of 4 bytes to initialize from fbdev device"); | |
fprintf(file, "Buffer strides need to be a multiple of 4 bytes to initialize from fbdev device"); | |
goto exit; | |
} | |
/* similarly using pixman_blt doesn't allow for format conversion, so | |
* check if they don't match and print a message */ | |
// if (vinfo.bits_per_pixel != dst_bpp || vinfo.grayscale != 0 || | |
// vinfo.nonstd != 0 || | |
// vinfo.red.offset != pScrn->offset.red || | |
// vinfo.red.length != pScrn->weight.red || | |
// vinfo.red.msb_right != 0 || | |
// vinfo.green.offset != pScrn->offset.green || | |
// vinfo.green.length != pScrn->weight.green || | |
// vinfo.green.msb_right != 0 || | |
// vinfo.blue.offset != pScrn->offset.blue || | |
// vinfo.blue.length != pScrn->weight.blue || | |
// vinfo.blue.msb_right != 0) { | |
// ERROR_MSG("Format of %s does not match scanout buffer", fb_dev); | |
// goto exit; | |
// } | |
/* NB: We have to call pixman direct instead of wrapping the buffers as | |
* Pixmaps as this function is called from ScreenInit. Pixmaps cannot be | |
* created until X calls CreateScratchPixmapsForScreen(), and the screen | |
* pixmap is not initialized until X calls CreateScreenResources */ | |
pixman_ret = pixman_blt((uint32_t *)src, (uint32_t *)dst, | |
src_pixman_stride, dst_pixman_stride, | |
vinfo.bits_per_pixel, dst_bpp, vinfo.xoffset, | |
vinfo.yoffset, 0, 0, width, height); | |
if (!pixman_ret) { | |
ERROR_MSG("Pixman failed to blit from %s to scanout buffer", | |
fb_dev); | |
fprintf(file, "Pixman failed to blit from %s to scanout buffer", fb_dev); | |
goto exit; | |
} | |
/* fill any area not covered by the blit */ | |
if (width < dst_width) { | |
pixman_ret = pixman_fill((uint32_t *)dst, dst_pixman_stride, | |
dst_bpp, width, 0, dst_width-width, dst_height, | |
0); | |
if (!pixman_ret) { | |
ERROR_MSG( | |
"Pixman failed to fill margin of scanout buffer"); | |
fprintf(file, "Pixman failed to fill margin of scanout buffer"); | |
goto exit; | |
} | |
} | |
if (height < dst_height) { | |
pixman_ret = pixman_fill((uint32_t *)dst, dst_pixman_stride, | |
dst_bpp, 0, height, width, dst_height-height, | |
0); | |
if (!pixman_ret) { | |
ERROR_MSG( | |
"Pixman failed to fill margin of scanout buffer"); | |
fprintf(file, "Pixman failed to fill margin of scanout buffer"); | |
goto exit; | |
} | |
} | |
ret = TRUE; | |
fclose(file); | |
exit: | |
if (src) | |
munmap(src, src_size); | |
if (fd >= 0) | |
close(fd); | |
return ret; | |
} | |
/** Let the XFree86 code know the Setup() function. */ | |
static MODULESETUPPROTO(ARMSOCSetup); | |
/** Provide basic version information to the XFree86 code. */ | |
static XF86ModuleVersionInfo ARMSOCVersRec = { | |
ARMSOC_DRIVER_NAME, | |
MODULEVENDORSTRING, | |
MODINFOSTRING1, | |
MODINFOSTRING2, | |
XORG_VERSION_CURRENT, | |
PACKAGE_VERSION_MAJOR, | |
PACKAGE_VERSION_MINOR, | |
PACKAGE_VERSION_PATCHLEVEL, | |
ABI_CLASS_VIDEODRV, | |
ABI_VIDEODRV_VERSION, | |
MOD_CLASS_VIDEODRV, | |
{0, 0, 0, 0} | |
}; | |
/** Let the XFree86 code know about the VersRec and Setup() function. */ | |
_X_EXPORT XF86ModuleData armsocModuleData = { &ARMSOCVersRec, ARMSOCSetup, NULL }; | |
/** | |
* The first function that the XFree86 code calls, after loading this module. | |
*/ | |
static pointer | |
ARMSOCSetup(pointer module, pointer opts, int *errmaj, int *errmin) | |
{ | |
static Bool setupDone = FALSE; | |
/* This module should be loaded only once, but check to be sure: */ | |
if (!setupDone) { | |
setupDone = TRUE; | |
xf86AddDriver(&ARMSOC, module, 0); | |
/* The return value must be non-NULL on success even | |
* though there is no TearDownProc. | |
*/ | |
return (pointer) 1; | |
} else { | |
if (errmaj) | |
*errmaj = LDR_ONCEONLY; | |
return NULL; | |
} | |
} | |
/** | |
* The mandatory AvailableOptions() function. It returns the available driver | |
* options to the "-configure" option, so that an xorg.conf file can be built | |
* and the user can see which options are available for them to use. | |
*/ | |
static const OptionInfoRec * | |
ARMSOCAvailableOptions(int chipid, int busid) | |
{ | |
return ARMSOCOptions; | |
} | |
/** | |
* The mandatory Identify() function. It is run before Probe(), and prints out | |
* an identifying message. | |
*/ | |
static void | |
ARMSOCIdentify(int flags) | |
{ | |
xf86Msg(X_INFO, "%s: Driver for ARM Mali compatible chipsets\n", ARMSOC_NAME); | |
} | |
/** | |
* The driver's Probe() function. This function finds all instances of | |
* ARM hardware that the driver supports (from within the "xorg.conf" | |
* device sections), and for instances not already claimed by another driver, | |
* claim the instances, and allocate a ScrnInfoRec. Only minimal hardware | |
* probing is allowed here. | |
*/ | |
static Bool | |
ARMSOCProbe(DriverPtr drv, int flags) | |
{ | |
int i; | |
ScrnInfoPtr pScrn; | |
GDevPtr *devSections = NULL; | |
int numDevSections; | |
Bool foundScreen = FALSE; | |
/* Get the "xorg.conf" file device sections that match this driver, and | |
* return (error out) if there are none: | |
*/ | |
numDevSections = xf86MatchDevice(ARMSOC_DRIVER_NAME, &devSections); | |
if (numDevSections <= 0) { | |
EARLY_ERROR_MSG( | |
"Did not find any matching device section in configuration file"); | |
if (flags & PROBE_DETECT) { | |
/* if we are probing, assume one and lets see if we can | |
* open the device to confirm it is there: | |
*/ | |
numDevSections = 1; | |
} else { | |
return FALSE; | |
} | |
} | |
for (i = 0; i < numDevSections; i++) { | |
int fd; | |
if (devSections) { | |
const char *busIdStr; | |
const char *driverNameStr; | |
const char *cardNumStr; | |
/* get the Bus ID */ | |
busIdStr = xf86FindOptionValue( | |
devSections[i]->options, | |
"BusID"); | |
/* get the DriverName */ | |
driverNameStr = xf86FindOptionValue( | |
devSections[i]->options, | |
"DriverName"); | |
/* get the card_num from xorg.conf if present */ | |
cardNumStr = xf86FindOptionValue( | |
devSections[i]->options, | |
"DRICard"); | |
if (busIdStr && driverNameStr) { | |
EARLY_WARNING_MSG( | |
"Option DriverName ignored (BusID is specified)"); | |
} | |
if (busIdStr || driverNameStr) { | |
if (cardNumStr) { | |
EARLY_WARNING_MSG( | |
"Option DRICard ignored (BusID or DriverName are specified)"); | |
} | |
} | |
if (busIdStr) { | |
if (0 == strlen(busIdStr)) { | |
EARLY_ERROR_MSG( | |
"Missing value for Option BusID"); | |
return FALSE; | |
} | |
connection.bus_id = busIdStr; | |
} else if (driverNameStr) { | |
if (0 == strlen(driverNameStr)) { | |
EARLY_ERROR_MSG( | |
"Missing value for Option DriverName"); | |
return FALSE; | |
} | |
connection.driver_name = driverNameStr; | |
} else if (cardNumStr) { | |
char *endptr; | |
errno = 0; | |
connection.card_num = strtol(cardNumStr, | |
&endptr, 10); | |
if (('\0' == *cardNumStr) || | |
('\0' != *endptr) || | |
(errno != 0)) { | |
EARLY_ERROR_MSG( | |
"Bad Option DRICard value : %s", | |
cardNumStr); | |
return FALSE; | |
} | |
} | |
} | |
fd = ARMSOCOpenDRMCard(); | |
if (fd >= 0) { | |
struct ARMSOCRec *pARMSOC; | |
/* Allocate the ScrnInfoRec */ | |
pScrn = xf86AllocateScreen(drv, 0); | |
if (!pScrn) { | |
EARLY_ERROR_MSG( | |
"Cannot allocate a ScrnInfoPtr"); | |
return FALSE; | |
} | |
/* Allocate the driver's Screen-specific, "private" | |
* data structure and hook it into the ScrnInfoRec's | |
* driverPrivate field. | |
*/ | |
pScrn->driverPrivate = | |
calloc(1, sizeof(struct ARMSOCRec)); | |
if (!pScrn->driverPrivate) | |
return FALSE; | |
pARMSOC = ARMSOCPTR(pScrn); | |
/* initially mark to use all DRM crtcs */ | |
pARMSOC->crtcNum = -1; | |
if (flags & PROBE_DETECT) { | |
/* just add the device.. we aren't a PCI device, | |
* so call xf86AddBusDeviceToConfigure() | |
* directly | |
*/ | |
xf86AddBusDeviceToConfigure(ARMSOC_DRIVER_NAME, | |
BUS_NONE, NULL, i); | |
foundScreen = TRUE; | |
drmClose(fd); | |
continue; | |
} | |
if (devSections) { | |
int entity = xf86ClaimNoSlot(drv, 0, | |
devSections[i], TRUE); | |
xf86AddEntityToScreen(pScrn, entity); | |
} | |
/* if there are multiple screens, use a separate | |
* crtc for each one | |
*/ | |
if (numDevSections > 1) | |
pARMSOC->crtcNum = i; | |
xf86Msg(X_INFO, "Screen:%d, CRTC:%d\n", | |
pScrn->scrnIndex, | |
pARMSOC->crtcNum); | |
foundScreen = TRUE; | |
pScrn->driverVersion = ARMSOC_VERSION; | |
pScrn->driverName = (char *)ARMSOC_DRIVER_NAME; | |
pScrn->name = (char *)ARMSOC_NAME; | |
pScrn->Probe = ARMSOCProbe; | |
pScrn->PreInit = ARMSOCPreInit; | |
pScrn->ScreenInit = ARMSOCScreenInit; | |
pScrn->SwitchMode = ARMSOCSwitchMode; | |
pScrn->AdjustFrame = ARMSOCAdjustFrame; | |
pScrn->EnterVT = ARMSOCEnterVT; | |
pScrn->LeaveVT = ARMSOCLeaveVT; | |
pScrn->FreeScreen = ARMSOCFreeScreen; | |
/* would be nice to keep the connection open */ | |
drmClose(fd); | |
} | |
} | |
free(devSections); | |
return foundScreen; | |
} | |
/* Find a drmmode driver with the same name as the underlying | |
* drm kernel driver */ | |
static struct drmmode_interface *get_drmmode_implementation(int drm_fd) | |
{ | |
drmVersionPtr version; | |
struct drmmode_interface *ret = NULL; | |
struct drmmode_interface *ifaces[] = { | |
&exynos_interface, | |
&pl111_interface, | |
&meson_interface, | |
}; | |
int i; | |
version = drmGetVersion(drm_fd); | |
if (!version) | |
return NULL; | |
for (i = 0; i < ARRAY_SIZE(ifaces); i++) { | |
struct drmmode_interface *iface = ifaces[i]; | |
if (strcmp(version->name, iface->driver_name) == 0) { | |
ret = iface; | |
break; | |
} | |
} | |
drmFreeVersion(version); | |
return ret; | |
} | |
/** | |
* The driver's PreInit() function. Additional hardware probing is allowed | |
* now, including display configuration. | |
*/ | |
static Bool | |
ARMSOCPreInit(ScrnInfoPtr pScrn, int flags) | |
{ | |
struct ARMSOCRec *pARMSOC; | |
int default_depth, fbbpp; | |
rgb defaultWeight = { 0, 0, 0 }; | |
rgb defaultMask = { 0, 0, 0 }; | |
Gamma defaultGamma = { 0.0, 0.0, 0.0 }; | |
int driNumBufs; | |
TRACE_ENTER(); | |
if (flags & PROBE_DETECT) { | |
ERROR_MSG( | |
"The %s driver does not support the \"-configure\" or \"-probe\" command line arguments.", | |
ARMSOC_NAME); | |
return FALSE; | |
} | |
/* Check the number of entities, and fail if it isn't one. */ | |
if (pScrn->numEntities != 1) { | |
ERROR_MSG( | |
"Driver expected 1 entity, but found %d for screen %d", | |
pScrn->numEntities, pScrn->scrnIndex); | |
return FALSE; | |
} | |
pARMSOC = ARMSOCPTR(pScrn); | |
pARMSOC->pEntityInfo = xf86GetEntityInfo(pScrn->entityList[0]); | |
pScrn->monitor = pScrn->confScreen->monitor; | |
/* Get the current depth, and set it for XFree86: */ | |
default_depth = 24; /* TODO: MIDEGL-1445: get from kernel */ | |
fbbpp = 32; /* TODO: MIDEGL-1445: get from kernel */ | |
if (!xf86SetDepthBpp(pScrn, default_depth, 0, fbbpp, Support32bppFb)) { | |
/* The above function prints an error message. */ | |
goto fail; | |
} | |
xf86PrintDepthBpp(pScrn); | |
/* Set the color weight: */ | |
if (!xf86SetWeight(pScrn, defaultWeight, defaultMask)) { | |
/* The above function prints an error message. */ | |
goto fail; | |
} | |
/* Set the gamma: */ | |
if (!xf86SetGamma(pScrn, defaultGamma)) { | |
/* The above function prints an error message. */ | |
goto fail; | |
} | |
/* Visual init: */ | |
if (!xf86SetDefaultVisual(pScrn, -1)) { | |
/* The above function prints an error message. */ | |
goto fail; | |
} | |
/* We don't support 8-bit depths: */ | |
if (pScrn->depth < 16) { | |
ERROR_MSG( | |
"The requested default visual (%s) has an unsupported depth (%d).", | |
xf86GetVisualName(pScrn->defaultVisual), | |
pScrn->depth); | |
goto fail; | |
} | |
/* Using a programmable clock: */ | |
pScrn->progClock = TRUE; | |
/* Open a connection to the DRM, so we can communicate | |
* with the KMS code: | |
*/ | |
if (!ARMSOCOpenDRM(pScrn)) | |
goto fail; | |
if (ump_open() != UMP_OK) | |
goto fail2; | |
/* Optional umplock support. */ | |
pARMSOC->umplock_fd = open("/dev/umplock", O_RDWR); | |
if (pARMSOC->umplock_fd < 0) | |
WARNING_MSG("Failed to open /dev/umplock."); | |
pARMSOC->drmmode_interface = | |
get_drmmode_implementation(pARMSOC->drmFD); | |
if (!pARMSOC->drmmode_interface) | |
goto fail2; | |
/* create DRM device instance: */ | |
pARMSOC->dev = armsoc_device_new(pARMSOC->drmFD, | |
pARMSOC->drmmode_interface->create_custom_gem); | |
/* set chipset name: */ | |
pScrn->chipset = (char *)ARMSOC_CHIPSET_NAME; | |
INFO_MSG("Chipset: %s", pScrn->chipset); | |
/* | |
* Process the "xorg.conf" file options: | |
*/ | |
xf86CollectOptions(pScrn, NULL); | |
pARMSOC->pOptionInfo = calloc(1, sizeof(ARMSOCOptions)); | |
if (!pARMSOC->pOptionInfo) | |
goto fail2; | |
memcpy(pARMSOC->pOptionInfo, ARMSOCOptions, sizeof(ARMSOCOptions)); | |
xf86ProcessOptions(pScrn->scrnIndex, | |
pARMSOC->pEntityInfo->device->options, | |
pARMSOC->pOptionInfo); | |
/* Determine if the user wants debug messages turned on: */ | |
armsocDebug = xf86ReturnOptValBool(pARMSOC->pOptionInfo, | |
OPTION_DEBUG, FALSE); | |
if (!xf86GetOptValInteger(pARMSOC->pOptionInfo, OPTION_DRI_NUM_BUF, | |
&driNumBufs)) { | |
/* Default to double buffering */ | |
driNumBufs = 2; | |
} | |
if (driNumBufs < 2) { | |
ERROR_MSG( | |
"Invalid option for %s: %d. Must be greater than or equal to 2", | |
xf86TokenToOptName(pARMSOC->pOptionInfo, | |
OPTION_DRI_NUM_BUF), | |
driNumBufs); | |
return FALSE; | |
} | |
pARMSOC->driNumBufs = driNumBufs; | |
/* Determine if user wants to disable buffer flipping: */ | |
pARMSOC->NoFlip = xf86ReturnOptValBool(pARMSOC->pOptionInfo, | |
OPTION_NO_FLIP, FALSE); | |
INFO_MSG("Buffer Flipping is %s", | |
pARMSOC->NoFlip ? "Disabled" : "Enabled"); | |
/* | |
* Select the video modes: | |
*/ | |
INFO_MSG("Setting the video modes ..."); | |
/* Don't call drmCheckModesettingSupported() as its written only for | |
* PCI devices. | |
*/ | |
/* Do initial KMS setup: */ | |
if (!drmmode_pre_init(pScrn, pARMSOC->drmFD, | |
(pScrn->bitsPerPixel >> 3))) { | |
ERROR_MSG("Cannot get KMS resources"); | |
goto fail2; | |
} else { | |
INFO_MSG("Got KMS resources"); | |
} | |
xf86RandR12PreInit(pScrn); | |
/* Let XFree86 calculate or get (from command line) the display DPI: */ | |
xf86SetDpi(pScrn, 0, 0); | |
/* Ensure we have a supported depth: */ | |
switch (pScrn->bitsPerPixel) { | |
case 16: | |
case 24: | |
case 32: | |
break; | |
default: | |
ERROR_MSG( | |
"The requested number of bits per pixel (%d) is unsupported.", | |
pScrn->bitsPerPixel); | |
goto fail2; | |
} | |
/* Load external sub-modules now: */ | |
if (!(xf86LoadSubModule(pScrn, "dri2") && | |
xf86LoadSubModule(pScrn, "exa") && | |
xf86LoadSubModule(pScrn, "fb"))) { | |
goto fail2; | |
} | |
TRACE_EXIT(); | |
return TRUE; | |
fail2: | |
/* Cleanup here where we know whether we took a connection | |
* instead of in FreeScreen where we don't */ | |
ARMSOCDropDRMMaster(); | |
ARMSOCCloseDRM(pScrn); | |
fail: | |
TRACE_EXIT(); | |
return FALSE; | |
} | |
/** | |
* Initialize EXA and DRI2 | |
*/ | |
static void | |
ARMSOCAccelInit(ScreenPtr pScreen) | |
{ | |
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); | |
struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); | |
if (!pARMSOC->pARMSOCEXA) | |
pARMSOC->pARMSOCEXA = InitNullEXA(pScreen, pScrn, | |
pARMSOC->drmFD); | |
if (pARMSOC->pARMSOCEXA) | |
pARMSOC->dri = ARMSOCDRI2ScreenInit(pScreen); | |
else | |
pARMSOC->dri = FALSE; | |
} | |
/** | |
* The driver's ScreenInit() function, called at the start of each server | |
* generation. Fill in pScreen, map the frame buffer, save state, | |
* initialize the mode, etc. | |
*/ | |
static Bool | |
ARMSOCScreenInit(SCREEN_INIT_ARGS_DECL) | |
{ | |
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); | |
#ifndef XF86_SCRN_INTERFACE | |
int scrnIndex = pScrn->scrnIndex; | |
#endif | |
struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); | |
VisualPtr visual; | |
xf86CrtcConfigPtr xf86_config; | |
int j; | |
char *fbdev; | |
FILE *file = fopen("/root/LOG", "a"); | |
int width, height; | |
TRACE_ENTER(); | |
pARMSOC->created_scanout_pixmap = FALSE; | |
/* set drm master before allocating scanout buffer */ | |
if (ARMSOCSetDRMMaster()) { | |
ERROR_MSG("Cannot get DRM master: %s", strerror(errno)); | |
goto fail; | |
} | |
/* Allocate initial scanout buffer */ | |
DEBUG_MSG("allocating new scanout buffer: %dx%d", | |
pScrn->virtualX, pScrn->virtualY); | |
assert(!pARMSOC->scanout); | |
width = pScrn->currentMode->HDisplay | |
+ 2*(pScrn->currentMode->HSkew >> 8); | |
height = pScrn->currentMode->VDisplay | |
+ 2*(pScrn->currentMode->HSkew & 0xFF); | |
if (pScrn->virtualX > width) | |
width = pScrn->virtualX; | |
if (pScrn->virtualY > height) | |
height = pScrn->virtualY; | |
pARMSOC->scanout = armsoc_bo_new_with_dim(pARMSOC->dev, width, | |
height, pScrn->depth, pScrn->bitsPerPixel, | |
ARMSOC_BO_SCANOUT); | |
if (!pARMSOC->scanout) { | |
ERROR_MSG("Cannot allocate scanout buffer\n"); | |
goto fail1; | |
} | |
pScrn->displayWidth = armsoc_bo_pitch(pARMSOC->scanout) / | |
((pScrn->bitsPerPixel+7) / 8); | |
xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); | |
/* need to point to new screen on server regeneration */ | |
for (j = 0; j < xf86_config->num_crtc; j++) | |
xf86_config->crtc[j]->scrn = pScrn; | |
for (j = 0; j < xf86_config->num_output; j++) | |
xf86_config->output[j]->scrn = pScrn; | |
/* | |
* The next step is to setup the screen's visuals, and initialize the | |
* framebuffer code. In cases where the framebuffer's default | |
* choices for things like visual layouts and bits per RGB are OK, | |
* this may be as simple as calling the framebuffer's ScreenInit() | |
* function. If not, the visuals will need to be setup before calling | |
* a fb ScreenInit() function and fixed up after. | |
* | |
* For most PC hardware at depths >= 8, the defaults that fb uses | |
* are not appropriate. In this driver, we fixup the visuals after. | |
*/ | |
/* Reset the visual list. */ | |
miClearVisualTypes(); | |
if (!miSetVisualTypes(pScrn->bitsPerPixel, | |
miGetDefaultVisualMask(pScrn->depth), | |
pScrn->rgbBits, pScrn->defaultVisual)) { | |
ERROR_MSG( | |
"Cannot initialize the visual type for %d bits per pixel!", | |
pScrn->bitsPerPixel); | |
goto fail2; | |
} | |
if (pScrn->bitsPerPixel == 32 && pScrn->depth == 24) { | |
/* Also add a 24 bit depth visual */ | |
if (!miSetVisualTypes(24, miGetDefaultVisualMask(pScrn->depth), | |
pScrn->rgbBits, pScrn->defaultVisual)) { | |
WARNING_MSG( | |
"Cannot initialize a 24 depth visual for 32bpp"); | |
} else { | |
INFO_MSG("Initialized a 24 depth visual for 32bpp"); | |
} | |
} | |
if (!miSetPixmapDepths()) { | |
ERROR_MSG("Cannot initialize the pixmap depth!"); | |
goto fail3; | |
} | |
/* Initialize some generic 2D drawing functions: */ | |
if (!fbScreenInit(pScreen, armsoc_bo_map(pARMSOC->scanout), | |
pScrn->virtualX, pScrn->virtualY, | |
pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, | |
pScrn->bitsPerPixel)) { | |
ERROR_MSG("fbScreenInit() failed!"); | |
goto fail3; | |
} | |
/* Fixup RGB ordering: */ | |
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; | |
visual->bitsPerRGBValue = pScrn->rgbBits; | |
visual->ColormapEntries = 1 << pScrn->rgbBits; | |
} | |
} | |
/* Continue initializing the generic 2D drawing functions after | |
* fixing the RGB ordering: | |
*/ | |
if (!fbPictureInit(pScreen, NULL, 0)) { | |
ERROR_MSG("fbPictureInit() failed!"); | |
goto fail4; | |
} | |
/* Set the initial black & white colormap indices: */ | |
xf86SetBlackWhitePixels(pScreen); | |
/* Initialize external sub-modules for EXA now, this has to be before | |
* miDCInitialize() otherwise stacking order for wrapped ScreenPtr fxns | |
* ends up in the wrong order. | |
*/ | |
ARMSOCAccelInit(pScreen); | |
/* Initialize backing store: */ | |
xf86SetBackingStore(pScreen); | |
{ | |
drmModeResPtr res; | |
drmModeCrtcPtr crtc; | |
drmModeFBPtr fb; | |
struct drm_mode_map_dumb mreq; | |
int ret; | |
uint8_t *map; | |
size_t size; | |
unsigned int i, j, off; | |
uint8_t r, g, b; | |
res = drmModeGetResources(pARMSOC->drmFD); | |
crtc = drmModeGetCrtc(pARMSOC->drmFD, res->crtcs[0]); | |
fb = drmModeGetFB(pARMSOC->drmFD, crtc->buffer_id); | |
fprintf(file, "crtc->buffer_id: %d, fb->handle: %d\n", crtc->buffer_id, fb->handle); | |
memset(&mreq, 0, sizeof(mreq)); | |
mreq.handle = fb->handle; | |
ret = drmIoctl(pARMSOC->drmFD, DRM_IOCTL_MODE_MAP_DUMB, &mreq); | |
if (ret) { | |
fprintf(file, "error in drmIoctl\n"); | |
} | |
size = fb->pitch * fb->height; | |
fprintf(file, "pitch: %d, height: %d, width: %d\n", fb->pitch, fb->height, fb->width); | |
fprintf(file, "->x: %d, ->y: %d\n", crtc->x, crtc->y); | |
map = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, pARMSOC->drmFD, mreq.offset); | |
if (map == MAP_FAILED) { | |
fprintf(file, "error in mmap\n"); | |
} | |
// for (i = 0; i < size; i++) { | |
// fprintf(file, "%x", map[i]); | |
// if (!(i % 80)) | |
// fprintf(file, "\n"); | |
// } | |
fclose(file); | |
file = fopen("/dev/kmsg","w"); | |
fputs("<1>================================ init ARMSOCCopyFB\n", file); | |
fclose(file); | |
ARMSOCCopyFB(pScrn, fbdev, map, fb, crtc); | |
file = fopen("/dev/kmsg","w"); | |
fputs("<1>================================ end ARMSOCCopyFB\n", file); | |
fclose(file); | |
if (0) { | |
srand(time(NULL)); | |
memset(map, 0, size); | |
for (j = 0; j < fb->height; j++) { | |
for (i = 0; i < fb->width; i++) { | |
r = rand() % 0xff; | |
g = rand() % 0xff; | |
b = rand() % 0xff; | |
off = fb->pitch * j + i * 4; | |
*(uint32_t *)&map[off] = (r << 16) | (g << 8) | b; | |
} | |
} | |
} | |
//drmModeFreeFB(fb); | |
//drmModeFreeCrtc(crtc); | |
//drmModeFreeResources(res); | |
pScreen->canDoBGNoneRoot = TRUE; | |
} | |
if (0) { | |
fbdev = xf86GetOptValString(pARMSOC->pOptionInfo, | |
OPTION_INIT_FROM_FBDEV); | |
if (fbdev && *fbdev != '\0') { | |
if (ARMSOCCopyFB(pScrn, fbdev, NULL, NULL, NULL)) { | |
/* Only allow None BG root if we initialized the scanout | |
* buffer */ | |
pScreen->canDoBGNoneRoot = TRUE; | |
} | |
} | |
} | |
/* Enable cursor position updates by mouse signal handler: */ | |
xf86SetSilkenMouse(pScreen); | |
/* Initialize the cursor: */ | |
if (!miDCInitialize(pScreen, xf86GetPointerScreenFuncs())) { | |
ERROR_MSG("miDCInitialize() failed!"); | |
goto fail5; | |
} | |
/* ignore failures here as we will fall back to software cursor */ | |
(void)drmmode_cursor_init(pScreen); | |
/* TODO: MIDEGL-1458: Is this the right place for this? | |
* The Intel i830 driver says: | |
* "Must force it before EnterVT, so we are in control of VT..." | |
*/ | |
pScrn->vtSema = TRUE; | |
/* Take over the virtual terminal from the console, set the | |
* desired mode, etc.: | |
*/ | |
if (0) { | |
if (!ARMSOCEnterVT(VT_FUNC_ARGS(0))) { | |
ERROR_MSG("ARMSOCEnterVT() failed!"); | |
goto fail6; | |
} | |
} | |
/* Do some XRandR initialization. Return value is not useful */ | |
(void)xf86CrtcScreenInit(pScreen); | |
if (!miCreateDefColormap(pScreen)) { | |
ERROR_MSG("Cannot create colormap!"); | |
goto fail7; | |
} | |
if (!xf86HandleColormaps(pScreen, 1 << pScrn->rgbBits, pScrn->rgbBits, | |
ARMSOCLoadPalette, NULL, CMAP_PALETTED_TRUECOLOR)) { | |
ERROR_MSG("xf86HandleColormaps() failed!"); | |
goto fail8; | |
} | |
/* Setup power management: */ | |
xf86DPMSInit(pScreen, xf86DPMSSet, 0); | |
pScreen->SaveScreen = xf86SaveScreen; | |
/* Wrap some screen functions: */ | |
wrap(pARMSOC, pScreen, CloseScreen, ARMSOCCloseScreen); | |
wrap(pARMSOC, pScreen, CreateScreenResources, | |
ARMSOCCreateScreenResources); | |
wrap(pARMSOC, pScreen, BlockHandler, ARMSOCBlockHandler); | |
drmmode_screen_init(pScrn); | |
TRACE_EXIT(); | |
return TRUE; | |
/* cleanup on failures */ | |
fail8: | |
/* uninstall the default colormap */ | |
miUninstallColormap(GetInstalledmiColormap(pScreen)); | |
fail7: | |
ARMSOCLeaveVT(VT_FUNC_ARGS(0)); | |
pScrn->vtSema = FALSE; | |
fail6: | |
drmmode_cursor_fini(pScreen); | |
fail5: | |
if (pARMSOC->dri) | |
ARMSOCDRI2CloseScreen(pScreen); | |
if (pARMSOC->pARMSOCEXA) | |
if (pARMSOC->pARMSOCEXA->CloseScreen) | |
pARMSOC->pARMSOCEXA->CloseScreen(CLOSE_SCREEN_ARGS); | |
fail4: | |
/* Call the CloseScreen functions for fbInitScreen, miDCInitialize, | |
* exaDriverInit & xf86CrtcScreenInit as appropriate via their | |
* wrapped pointers. | |
* exaDDXCloseScreen uses the XF86SCRNINFO macro so we must | |
* set up the key for this before it gets called. | |
*/ | |
dixSetPrivate(&pScreen->devPrivates, xf86ScreenKey, pScrn); | |
(*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); | |
fail3: | |
/* reset the visual list */ | |
miClearVisualTypes(); | |
fail2: | |
/* release the scanout buffer */ | |
armsoc_bo_unreference(pARMSOC->scanout); | |
pARMSOC->scanout = NULL; | |
pScrn->displayWidth = 0; | |
fail1: | |
/* drop drm master */ | |
(void)drmDropMaster(pARMSOC->drmFD); | |
fail: | |
TRACE_EXIT(); | |
return FALSE; | |
} | |
static void | |
ARMSOCLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, | |
LOCO *colors, VisualPtr pVisual) | |
{ | |
TRACE_ENTER(); | |
TRACE_EXIT(); | |
} | |
/** | |
* The driver's CloseScreen() function. This is called at the end of each | |
* server generation. Restore state, unmap the frame buffer (and any other | |
* mapped memory regions), and free per-Screen data structures (except those | |
* held by pScrn). | |
*/ | |
static Bool | |
ARMSOCCloseScreen(CLOSE_SCREEN_ARGS_DECL) | |
{ | |
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); | |
struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); | |
Bool ret; | |
TRACE_ENTER(); | |
drmmode_screen_fini(pScrn); | |
drmmode_cursor_fini(pScreen); | |
/* pScreen->devPrivate holds the root pixmap created around our bo by miCreateResources which is installed | |
* by fbScreenInit() when called from ARMSOCScreenInit(). | |
* This pixmap should be destroyed in miScreenClose() but this isn't wrapped by fbScreenInit() so to prevent a leak | |
* we do it here, before calling the CloseScreen chain which would just free pScreen->devPrivate in fbCloseScreen() | |
*/ | |
if (pScreen->devPrivate) { | |
(void) (*pScreen->DestroyPixmap)(pScreen->devPrivate); | |
pScreen->devPrivate = NULL; | |
} | |
unwrap(pARMSOC, pScreen, CloseScreen); | |
unwrap(pARMSOC, pScreen, BlockHandler); | |
unwrap(pARMSOC, pScreen, CreateScreenResources); | |
ret = (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); | |
if (pARMSOC->dri) | |
ARMSOCDRI2CloseScreen(pScreen); | |
if (pARMSOC->pARMSOCEXA) | |
if (pARMSOC->pARMSOCEXA->CloseScreen) | |
pARMSOC->pARMSOCEXA->CloseScreen(CLOSE_SCREEN_ARGS); | |
armsoc_bo_unreference(pARMSOC->scanout); | |
pARMSOC->scanout = NULL; | |
pScrn->displayWidth = 0; | |
if (pScrn->vtSema == TRUE) | |
ARMSOCLeaveVT(VT_FUNC_ARGS(0)); | |
pScrn->vtSema = FALSE; | |
TRACE_EXIT(); | |
return ret; | |
} | |
/** | |
* Adjust the screen pixmap for the current location of the front buffer. | |
* This is done at EnterVT when buffers are bound as long as the resources | |
* have already been created, but the first EnterVT happens before | |
* CreateScreenResources. | |
*/ | |
static Bool | |
ARMSOCCreateScreenResources(ScreenPtr pScreen) | |
{ | |
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); | |
struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); | |
swap(pARMSOC, pScreen, CreateScreenResources); | |
if (!(*pScreen->CreateScreenResources) (pScreen)) | |
return FALSE; | |
swap(pARMSOC, pScreen, CreateScreenResources); | |
return TRUE; | |
} | |
static void | |
ARMSOCBlockHandler(BLOCKHANDLER_ARGS_DECL) | |
{ | |
SCREEN_PTR(arg); | |
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); | |
struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); | |
swap(pARMSOC, pScreen, BlockHandler); | |
(*pScreen->BlockHandler) (BLOCKHANDLER_ARGS); | |
swap(pARMSOC, pScreen, BlockHandler); | |
} | |
/** | |
* The driver's SwitchMode() function. Initialize the new mode for the | |
* Screen. | |
*/ | |
static Bool | |
ARMSOCSwitchMode(SWITCH_MODE_ARGS_DECL) | |
{ | |
SCRN_INFO_PTR(arg); | |
return xf86SetSingleMode(pScrn, mode, RR_Rotate_0); | |
} | |
/** | |
* The driver's AdjustFrame() function. For cases where the frame buffer is | |
* larger than the monitor resolution, this function can pan around the frame | |
* buffer within the "viewport" of the monitor. | |
*/ | |
static void | |
ARMSOCAdjustFrame(ADJUST_FRAME_ARGS_DECL) | |
{ | |
SCRN_INFO_PTR(arg); | |
drmmode_adjust_frame(pScrn, x, y); | |
} | |
/** | |
* The driver's EnterVT() function. This is called at server startup time, and | |
* when the X server takes over the virtual terminal from the console. As | |
* such, it may need to save the current (i.e. console) HW state, and set the | |
* HW state as needed by the X server. | |
*/ | |
static Bool | |
ARMSOCEnterVT(VT_FUNC_ARGS_DECL) | |
{ | |
SCRN_INFO_PTR(arg); | |
int i, ret; | |
TRACE_ENTER(); | |
for (i = 1; i < currentMaxClients; i++) { | |
if (clients[i]) | |
AttendClient(clients[i]); | |
} | |
ret = ARMSOCSetDRMMaster(); | |
if (ret) { | |
ERROR_MSG("Cannot get DRM master: %s", strerror(errno)); | |
return FALSE; | |
} | |
if (!xf86SetDesiredModes(pScrn)) { | |
ERROR_MSG("xf86SetDesiredModes() failed!"); | |
return FALSE; | |
} | |
TRACE_EXIT(); | |
return TRUE; | |
} | |
/** | |
* The driver's LeaveVT() function. This is called when the X server | |
* temporarily gives up the virtual terminal to the console. As such, it may | |
* need to restore the console's HW state. | |
*/ | |
static void | |
ARMSOCLeaveVT(VT_FUNC_ARGS_DECL) | |
{ | |
SCRN_INFO_PTR(arg); | |
int i, ret; | |
TRACE_ENTER(); | |
for (i = 1; i < currentMaxClients; i++) { | |
if (clients[i]) | |
IgnoreClient(clients[i]); | |
} | |
ret = ARMSOCDropDRMMaster(); | |
if (ret) | |
WARNING_MSG("drmDropMaster failed: %s", strerror(errno)); | |
TRACE_EXIT(); | |
} | |
/** | |
* The driver's FreeScreen() function. | |
* Frees the ScrnInfoRec driverPrivate field when a screen is | |
* deleted by the common layer. | |
* This function is not used in normal (error free) operation. | |
*/ | |
static void | |
ARMSOCFreeScreen(FREE_SCREEN_ARGS_DECL) | |
{ | |
SCRN_INFO_PTR(arg); | |
struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); | |
TRACE_ENTER(); | |
if (!pARMSOC) { | |
/* This can happen if a Screen is deleted after Probe(): */ | |
return; | |
} | |
if (pARMSOC->pARMSOCEXA) { | |
if (pARMSOC->pARMSOCEXA->FreeScreen) | |
pARMSOC->pARMSOCEXA->FreeScreen( | |
FREE_SCREEN_ARGS(pScrn)); | |
} | |
armsoc_device_del(pARMSOC->dev); | |
/* Free the driver's Screen-specific, "private" data structure and | |
* NULL-out the ScrnInfoRec's driverPrivate field. | |
*/ | |
if (pScrn->driverPrivate) { | |
free(pScrn->driverPrivate); | |
pScrn->driverPrivate = NULL; | |
} | |
TRACE_EXIT(); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment