mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2026-01-03 19:50:18 +01:00
Merge branch 'modesetting-101' of git+ssh://git.freedesktop.org/git/mesa/drm into origin/modesetting-101
Conflicts: linux-core/drm_crtc.c linux-core/drm_fb.c Lots of changes to merge with alanh's latest stuff: o fix use of fb->pitch now that it has the right value o add new helper for finding the CRTC given an FB o fix new fb_probe/fb_remove functions to take a CRTC o fixup callers of new FB routines o port drm_fb changes to intel_fb o check for errors after creating fb buffer object o go back to using cfb_imageblit since the accel stubs aren't ready
This commit is contained in:
commit
b7bf317f42
17 changed files with 1028 additions and 364 deletions
|
|
@ -238,15 +238,10 @@ drmModeFBPtr drmModeGetFB(int fd, uint32_t buf)
|
|||
|
||||
return r;
|
||||
}
|
||||
#if 0
|
||||
int drmModeForceProbe(int fd, uint32_t outputId)
|
||||
{
|
||||
/* TODO impl/keep? */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Crtc function.
|
||||
* Crtc functions
|
||||
*/
|
||||
|
||||
drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
|
||||
|
|
@ -274,9 +269,7 @@ drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
|
|||
r->x = crtc.x;
|
||||
r->y = crtc.y;
|
||||
r->mode = crtc.mode;
|
||||
// r->width = crtc.width;
|
||||
// r->height = crtc.height;
|
||||
r->buffer_id = crtc.fb_id;
|
||||
r->buffer_id = crtc.fb_id;
|
||||
r->gamma_size = crtc.gamma_size;
|
||||
r->count_outputs = crtc.count_outputs;
|
||||
r->count_possibles = crtc.count_possibles;
|
||||
|
|
@ -305,8 +298,8 @@ int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
|
|||
|
||||
crtc.x = x;
|
||||
crtc.y = y;
|
||||
crtc.crtc_id = crtcId;
|
||||
crtc.fb_id = bufferId;
|
||||
crtc.crtc_id = crtcId;
|
||||
crtc.fb_id = bufferId;
|
||||
crtc.set_outputs = outputs;
|
||||
crtc.count_outputs = count;
|
||||
crtc.mode = modeId;
|
||||
|
|
@ -314,22 +307,11 @@ int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
|
|||
return ioctl(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
|
||||
}
|
||||
|
||||
#if 0
|
||||
drmModeGammaTriplePtr drmModeGetCrtcGamma(int fd, uint32_t crtc, int *count)
|
||||
{
|
||||
/* TODO impl */
|
||||
}
|
||||
|
||||
int drmModeSetCrtcGamma(int fd, uint32_t crtcId,
|
||||
drmModeGammaTriplePtr ptr, int count)
|
||||
{
|
||||
/* TODO impl */
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
* Output manipulation
|
||||
*/
|
||||
|
||||
drmModeOutputPtr drmModeGetOutput(int fd, uint32_t output_id)
|
||||
{
|
||||
struct drm_mode_get_output out;
|
||||
|
|
@ -376,37 +358,38 @@ err_allocs:
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
uint32_t drmModeNewMode(int fd, struct drm_mode_modeinfo *modeInfo)
|
||||
uint32_t drmModeAddMode(int fd, struct drm_mode_modeinfo *mode_info)
|
||||
{
|
||||
/* TODO impl */
|
||||
if (ioctl(fd, DRM_IOCTL_MODE_ADDMODE, mode_info))
|
||||
return 0;
|
||||
|
||||
return mode_info->id;
|
||||
}
|
||||
|
||||
int drmModeDesMode(int fd, uint32_t modeId)
|
||||
int drmModeRmMode(int fd, uint32_t mode_id)
|
||||
{
|
||||
// return ioctl(fd, DRM_IOCTL_MODE_DESMODE, modeId);
|
||||
return ioctl(fd, DRM_IOCTL_MODE_RMMODE, mode_id);
|
||||
}
|
||||
|
||||
int drmModeAddMode(int fd, uint32_t outputId, uint32_t modeId)
|
||||
int drmModeAttachMode(int fd, uint32_t output_id, uint32_t mode_id)
|
||||
{
|
||||
|
||||
drm_mode_outputmode_t res;
|
||||
struct drm_mode_mode_cmd res;
|
||||
|
||||
res.outputId = outputId;
|
||||
res.modeId = modeId;
|
||||
res.output_id = output_id;
|
||||
res.mode_id = mode_id;
|
||||
|
||||
// return ioctl(fd, DRM_IOCTL_MODE_ADDMODE, &res);
|
||||
return ioctl(fd, DRM_IOCTL_MODE_ATTACHMODE, &res);
|
||||
}
|
||||
|
||||
int drmModeDelMode(int fd, uint32_t outputId, uint32_t modeId)
|
||||
int drmModeDetachMode(int fd, uint32_t output_id, uint32_t mode_id)
|
||||
{
|
||||
drm_mode_outputmode_t res;
|
||||
struct drm_mode_mode_cmd res;
|
||||
|
||||
res.outputId = outputId;
|
||||
res.modeId = modeId;
|
||||
res.output_id = output_id;
|
||||
res.mode_id = mode_id;
|
||||
|
||||
// return ioctl(fd, DRM_IOCTL_MODE_DELMODE, &res);
|
||||
return ioctl(fd, DRM_IOCTL_MODE_DETACHMODE, &res);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -40,25 +40,17 @@
|
|||
* In order to use this interface you must include either <stdint.h> or another
|
||||
* header defining uint32_t, int32_t and uint16_t.
|
||||
*
|
||||
* It aims to provide a randr compatible interface for modesettings in the
|
||||
* It aims to provide a randr1.2 compatible interface for modesettings in the
|
||||
* kernel, the interface is also ment to be used by libraries like EGL.
|
||||
*
|
||||
* More information can be found in randrproto.txt which can be found here:
|
||||
* http://gitweb.freedesktop.org/?p=xorg/proto/randrproto.git
|
||||
*
|
||||
* All framebuffer, crtc and output ids start at 1 while 0 is either an invalid
|
||||
* parameter or used to indicate that the command should disconnect from the
|
||||
* currently bound target, as with drmModeMapOutput.
|
||||
*
|
||||
* Currently only one framebuffer exist and has a id of 1, which is also the
|
||||
* default framebuffer and should allways be avaible to the client, unless
|
||||
* it is locked/used or any other limiting state is applied on it.
|
||||
*
|
||||
* There are some major diffrences to be noted. Unlike the randr1.2 proto you
|
||||
* need to create the memory object of the framebuffer yourself with the ttm
|
||||
* buffer object interface. This object needs to be pinned.
|
||||
*/
|
||||
|
||||
typedef struct _drmModeGammaTriple {
|
||||
uint16_t r, g, b;
|
||||
} drmModeGammaTriple, *drmModeGammaTriplePtr;
|
||||
|
||||
typedef struct _drmModeRes {
|
||||
|
||||
|
|
@ -130,53 +122,7 @@ typedef struct _drmModeOutput {
|
|||
|
||||
} drmModeOutput, *drmModeOutputPtr;
|
||||
|
||||
/*
|
||||
* RRSetScreenConfig o
|
||||
* RRGetScreenInfo o
|
||||
*
|
||||
* RRGetScreenSizeRange - see frameBuffer info
|
||||
* RRSetScreenSize
|
||||
* RRGetScreenResources
|
||||
*
|
||||
* RRGetOutputInfo
|
||||
*
|
||||
* RRListOutputProperties *
|
||||
* RRQueryOutputProperty *
|
||||
* RRConfigureOutputProperty *
|
||||
* RRChangeOutputProperty *
|
||||
* RRDeleteOutputProperty *
|
||||
* RRGetOutputProperty *
|
||||
*
|
||||
* RRCreateMode
|
||||
* RRDestroyMode
|
||||
* RRAddOutputMode
|
||||
* RRDeleteOutputMode
|
||||
*
|
||||
* RRGetCrtcInfo
|
||||
* RRSetCrtcConfig
|
||||
*
|
||||
* RRGetCrtcGammaSize - see crtc info
|
||||
* RRGetCrtcGamma
|
||||
* RRSetCrtcGamma
|
||||
*
|
||||
* drmModeGetResources
|
||||
* drmModeForceProbe
|
||||
*
|
||||
* drmModeGetFrameBufferInfo
|
||||
* drmModeSetFrameBufferSize
|
||||
*
|
||||
* drmModeGetCrtcInfo
|
||||
* drmModeSetCrtcConfig
|
||||
* drmModeGetCrtcGamma
|
||||
* drmModeSetCrtcGamma
|
||||
*
|
||||
* drmModeGetOutputInfo
|
||||
*
|
||||
* drmModeAddMode
|
||||
* drmModeDestroyMode
|
||||
* drmModeAddOutputMode
|
||||
* drmModeDeleteOutputMode
|
||||
*/
|
||||
|
||||
|
||||
extern void drmModeFreeModeInfo( struct drm_mode_modeinfo *ptr );
|
||||
extern void drmModeFreeResources( drmModeResPtr ptr );
|
||||
|
|
@ -189,11 +135,6 @@ extern void drmModeFreeOutput( drmModeOutputPtr ptr );
|
|||
*/
|
||||
extern drmModeResPtr drmModeGetResources(int fd);
|
||||
|
||||
/**
|
||||
* Forces a probe of the give output outputId, on 0 all will be probed.
|
||||
*/
|
||||
extern int drmModeForceProbe(int fd, uint32_t outputId);
|
||||
|
||||
|
||||
/*
|
||||
* FrameBuffer manipulation.
|
||||
|
|
@ -215,13 +156,9 @@ extern int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
|
|||
*/
|
||||
extern int drmModeRmFB(int fd, uint32_t bufferId);
|
||||
|
||||
/**
|
||||
* Changes the scanout buffer to the given buffer object.
|
||||
*/
|
||||
extern int drmModeFlipFrameBuffer(int fd, uint32_t bufferId, drmBO *bo);
|
||||
|
||||
/*
|
||||
* Crtc function.
|
||||
* Crtc functions
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
@ -236,19 +173,6 @@ extern int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
|
|||
uint32_t x, uint32_t y, uint32_t modeId,
|
||||
uint32_t *outputs, int count);
|
||||
|
||||
/**
|
||||
* Gets the gamma from a crtc
|
||||
*/
|
||||
extern drmModeGammaTriplePtr drmModeGetCrtcGamma(int fd, uint32_t crtcId,
|
||||
int *count);
|
||||
|
||||
/**
|
||||
* Sets the gamma on a crtc
|
||||
*/
|
||||
extern int drmModeSetCrtcGamma(int fd, uint32_t crtcId,
|
||||
drmModeGammaTriplePtr ptr, int count);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Output manipulation
|
||||
|
|
@ -261,24 +185,24 @@ extern drmModeOutputPtr drmModeGetOutput(int fd,
|
|||
uint32_t outputId);
|
||||
|
||||
/**
|
||||
* Creates a new mode from the given mode info.
|
||||
* Adds a new mode from the given mode info.
|
||||
* Name must be unique.
|
||||
*/
|
||||
extern uint32_t drmModeNewMode(int fd, struct drm_mode_modeinfo *modeInfo);
|
||||
extern uint32_t drmModeAddMode(int fd, struct drm_mode_modeinfo *modeInfo);
|
||||
|
||||
/**
|
||||
* Destroys a mode created with CreateMode, must be unused.
|
||||
* Removes a mode created with AddMode, must be unused.
|
||||
*/
|
||||
extern int drmModeDesMode(int fd, uint32_t modeId);
|
||||
extern int drmModeRmMode(int fd, uint32_t modeId);
|
||||
|
||||
/**
|
||||
* Adds the given mode to an output.
|
||||
* Attaches the given mode to an output.
|
||||
*/
|
||||
extern int drmModeAddMode(int fd, uint32_t outputId, uint32_t modeId);
|
||||
extern int drmModeAttachMode(int fd, uint32_t outputId, uint32_t modeId);
|
||||
|
||||
/**
|
||||
* Deletes a mode Added with AddOutputMode from the output,
|
||||
* Detaches a mode from the output
|
||||
* must be unused, by the given mode.
|
||||
*/
|
||||
extern int drmModeDelMode(int fd, uint32_t outputId, uint32_t modeId);
|
||||
extern int drmModeDetachMode(int fd, uint32_t outputId, uint32_t modeId);
|
||||
|
||||
|
|
|
|||
|
|
@ -662,8 +662,8 @@ struct drm_driver {
|
|||
void (*set_version) (struct drm_device * dev, drm_set_version_t * sv);
|
||||
|
||||
/* FB routines, if present */
|
||||
int (*fb_probe)(struct drm_device *dev, struct drm_framebuffer *fb);
|
||||
int (*fb_remove)(struct drm_device *dev, struct drm_framebuffer *fb);
|
||||
int (*fb_probe)(struct drm_device *dev, struct drm_crtc *crtc);
|
||||
int (*fb_remove)(struct drm_device *dev, struct drm_crtc *crtc);
|
||||
|
||||
struct drm_fence_driver *fence_driver;
|
||||
struct drm_bo_driver *bo_driver;
|
||||
|
|
|
|||
|
|
@ -86,6 +86,31 @@ void drm_idr_put(struct drm_device *dev, int id)
|
|||
idr_remove(&dev->mode_config.crtc_idr, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_crtc_from_fb - find the CRTC structure associated with an fb
|
||||
* @dev: DRM device
|
||||
* @fb: framebuffer in question
|
||||
*
|
||||
* LOCKING:
|
||||
* Caller must hold mode_config lock.
|
||||
*
|
||||
* Find CRTC in the mode_config structure that matches @fb.
|
||||
*
|
||||
* RETURNS:
|
||||
* Pointer to the CRTC or NULL if it wasn't found.
|
||||
*/
|
||||
struct drm_crtc *drm_crtc_from_fb(struct drm_device *dev,
|
||||
struct drm_framebuffer *fb)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
if (crtc->fb == fb)
|
||||
return crtc;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_framebuffer_create - create a new framebuffer object
|
||||
* @dev: DRM device
|
||||
|
|
@ -252,7 +277,7 @@ EXPORT_SYMBOL(drm_crtc_in_use);
|
|||
* Detailed mode info for a standard 640x480@60Hz monitor
|
||||
*/
|
||||
static struct drm_display_mode std_mode[] = {
|
||||
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25200, 640, 656,
|
||||
{ DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 25200, 640, 656,
|
||||
752, 800, 0, 480, 490, 492, 525, 0,
|
||||
V_NHSYNC | V_NVSYNC) }, /* 640x480@60Hz */
|
||||
};
|
||||
|
|
@ -465,51 +490,7 @@ done:
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_set_desired_modes - set a good mode on every CRTC & output
|
||||
* @dev: DRM device
|
||||
*
|
||||
* LOCKING:
|
||||
* Caller? (FIXME)
|
||||
*
|
||||
* Each CRTC may have a desired mode associated with it. This routine simply
|
||||
* walks @dev's mode_config and sets the desired mode on every CRTC. Intended
|
||||
* for use at startup time.
|
||||
*
|
||||
* RETURNS:
|
||||
* True if modes were set, false otherwise.
|
||||
*/
|
||||
bool drm_set_desired_modes(struct drm_device *dev)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_output *output, *list_output;
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
output = NULL;
|
||||
|
||||
list_for_each_entry(list_output, &dev->mode_config.output_list,
|
||||
head) {
|
||||
if (list_output->crtc == crtc) {
|
||||
output = list_output;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Skip disabled crtcs */
|
||||
if (!output) {
|
||||
DRM_DEBUG("skipping disabled crtc\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!drm_crtc_set_mode(crtc, crtc->desired_mode,
|
||||
crtc->desired_x, crtc->desired_y))
|
||||
return false;
|
||||
}
|
||||
|
||||
drm_disable_unused_functions(dev);
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_set_desired_modes);
|
||||
EXPORT_SYMBOL(drm_crtc_set_mode);
|
||||
|
||||
/**
|
||||
* drm_disable_unused_functions - disable unused objects
|
||||
|
|
@ -715,6 +696,7 @@ struct drm_display_mode *drm_mode_create(struct drm_device *dev)
|
|||
nmode->mode_id = drm_idr_get(dev, nmode);
|
||||
return nmode;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_create);
|
||||
|
||||
/**
|
||||
* drm_mode_destroy - remove a mode
|
||||
|
|
@ -732,6 +714,7 @@ void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode)
|
|||
|
||||
kfree(mode);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_destroy);
|
||||
|
||||
/**
|
||||
* drm_mode_config_init - initialize DRM mode_configuration structure
|
||||
|
|
@ -749,6 +732,7 @@ void drm_mode_config_init(drm_device_t *dev)
|
|||
INIT_LIST_HEAD(&dev->mode_config.fb_list);
|
||||
INIT_LIST_HEAD(&dev->mode_config.crtc_list);
|
||||
INIT_LIST_HEAD(&dev->mode_config.output_list);
|
||||
INIT_LIST_HEAD(&dev->mode_config.usermode_list);
|
||||
idr_init(&dev->mode_config.crtc_idr);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_config_init);
|
||||
|
|
@ -798,26 +782,94 @@ out_err:
|
|||
}
|
||||
|
||||
/**
|
||||
* drm_setup_output - setup an output structure
|
||||
* @output: output to setup
|
||||
* @crtc: CRTC this output belongs to
|
||||
* @mode: desired mode for this output
|
||||
* drm_pick_crtcs - pick crtcs for output devices
|
||||
* @dev: DRM device
|
||||
*
|
||||
* LOCKING:
|
||||
* None.
|
||||
*
|
||||
* Setup @output with the parameters given, with its initial coordinates set
|
||||
* at the origin.
|
||||
*/
|
||||
static void drm_setup_output(struct drm_output *output, struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode)
|
||||
static void drm_pick_crtcs (drm_device_t *dev)
|
||||
{
|
||||
output->crtc = crtc;
|
||||
output->crtc->desired_mode = mode;
|
||||
output->initial_x = 0;
|
||||
output->initial_y = 0;
|
||||
int c, o;
|
||||
struct drm_output *output, *output_equal;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_display_mode *des_mode = NULL, *modes, *modes_equal;
|
||||
|
||||
list_for_each_entry(output, &dev->mode_config.output_list, head) {
|
||||
output->crtc = NULL;
|
||||
|
||||
/* Don't hook up outputs that are disconnected ??
|
||||
*
|
||||
* This is debateable. Do we want fixed /dev/fbX or
|
||||
* dynamic on hotplug (need mode code for that though) ?
|
||||
*
|
||||
* If we don't hook up outputs now, then we only create
|
||||
* /dev/fbX for the output that's enabled, that's good as
|
||||
* the users console will be on that output.
|
||||
*
|
||||
* If we do hook up outputs that are disconnected now, then
|
||||
* the user may end up having to muck about with the fbcon
|
||||
* map flags to assign his console to the enabled output. Ugh.
|
||||
*/
|
||||
if (output->status != output_status_connected)
|
||||
continue;
|
||||
|
||||
des_mode = NULL;
|
||||
list_for_each_entry(des_mode, &output->modes, head) {
|
||||
if (des_mode->flags & DRM_MODE_TYPE_PREFERRED)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* No preferred mode, let's select another which should pick
|
||||
* the default 640x480 if nothing else is here.
|
||||
*
|
||||
*/
|
||||
if (!des_mode || !(des_mode->flags & DRM_MODE_TYPE_PREFERRED)) {
|
||||
list_for_each_entry(des_mode, &output->modes, head) {
|
||||
if (des_mode->flags & DRM_MODE_TYPE_DEFAULT)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
c = -1;
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
c++;
|
||||
if ((output->possible_crtcs & (1 << c)) == 0)
|
||||
continue;
|
||||
|
||||
#if 0 /* should we try and clone ?? - code not tested - FIXME */
|
||||
o = -1;
|
||||
list_for_each_entry(output_equal, &dev->mode_config.output_list, head) {
|
||||
o++;
|
||||
if (output->id == output_equal->id)
|
||||
continue;
|
||||
|
||||
list_for_each_entry(modes, &output->modes, head) {
|
||||
list_for_each_entry(modes_equal, &output_equal->modes, head) {
|
||||
if (drm_mode_equal (modes, modes_equal)) {
|
||||
if ((output->possible_clones & (1 << o))) {
|
||||
goto clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clone:
|
||||
#endif
|
||||
/* Found a CRTC to attach to, do it ! */
|
||||
output->crtc = crtc;
|
||||
output->crtc->desired_mode = des_mode;
|
||||
output->initial_x = 0;
|
||||
output->initial_y = 0;
|
||||
DRM_DEBUG("Desired mode for CRTC %d is %s\n",c,des_mode->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* drm_initial_config - setup a sane initial output configuration
|
||||
* @dev: DRM device
|
||||
|
|
@ -830,108 +882,68 @@ static void drm_setup_output(struct drm_output *output, struct drm_crtc *crtc,
|
|||
* At the moment, this is a cloned configuration across all heads with
|
||||
* a new framebuffer object as the backing store.
|
||||
*
|
||||
* FIXME: return value and better initial config.
|
||||
*
|
||||
* RETURNS:
|
||||
* Zero if everything went ok, nonzero otherwise.
|
||||
*/
|
||||
bool drm_initial_config(drm_device_t *dev, bool can_grow)
|
||||
{
|
||||
/* do a hardcoded initial configuration here */
|
||||
struct drm_crtc *crtc, *vga_crtc = NULL, *tmds_crtc = NULL,
|
||||
*lvds_crtc = NULL;
|
||||
struct drm_display_mode *des_mode = NULL;
|
||||
struct drm_output *output;
|
||||
struct drm_framebuffer *fb;
|
||||
drm_buffer_object_t *fbo;
|
||||
unsigned long size, bytes_per_pixel;
|
||||
|
||||
fb = drm_framebuffer_create(dev);
|
||||
if (!fb) {
|
||||
DRM_ERROR("failed to allocate fb.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
/* bind both CRTCs to this fb */
|
||||
/* only initialise one crtc to enabled state */
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
crtc->fb = fb;
|
||||
if (!vga_crtc) {
|
||||
vga_crtc = crtc;
|
||||
crtc->enabled = 1;
|
||||
crtc->desired_x = 0;
|
||||
crtc->desired_y = 0;
|
||||
} else {
|
||||
if (!lvds_crtc) {
|
||||
lvds_crtc = crtc;
|
||||
crtc->enabled = 1;
|
||||
crtc->desired_x = 0;
|
||||
crtc->desired_y = 0;
|
||||
}
|
||||
if (!tmds_crtc) {
|
||||
tmds_crtc = crtc;
|
||||
crtc->enabled = 1;
|
||||
crtc->desired_x = 0;
|
||||
crtc->desired_y = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
int ret;
|
||||
|
||||
drm_crtc_probe_output_modes(dev, 2048, 2048);
|
||||
|
||||
/* hard bind the CRTCS */
|
||||
drm_pick_crtcs(dev);
|
||||
|
||||
/* bind analog output to one crtc */
|
||||
list_for_each_entry(output, &dev->mode_config.output_list, head) {
|
||||
struct drm_display_mode *des_mode = NULL;
|
||||
|
||||
if (list_empty(&output->modes))
|
||||
/* can't setup the output if there's no assigned crtc or mode */
|
||||
if (!output->crtc || !output->crtc->desired_mode)
|
||||
continue;
|
||||
|
||||
/* Get the first preferred moded */
|
||||
list_for_each_entry(des_mode, &output->modes, head) {
|
||||
if (des_mode->flags & DRM_MODE_TYPE_PREFERRED)
|
||||
break;
|
||||
fb = drm_framebuffer_create(dev);
|
||||
if (!fb) {
|
||||
DRM_ERROR("failed to allocate fb.\n");
|
||||
return true;
|
||||
}
|
||||
output->crtc->fb = fb;
|
||||
des_mode = output->crtc->desired_mode;
|
||||
|
||||
if (!des_mode)
|
||||
continue;
|
||||
|
||||
if (!strncmp(output->name, "VGA", 3)) {
|
||||
DRM_DEBUG("VGA preferred mode: %s\n", des_mode->name);
|
||||
drm_setup_output(output, vga_crtc, des_mode);
|
||||
} else if (!strncmp(output->name, "TMDS", 4)) {
|
||||
DRM_DEBUG("TMDS preferred mode: %s\n", des_mode->name);
|
||||
drm_setup_output(output, tmds_crtc, des_mode);
|
||||
} else if (!strncmp(output->name, "LVDS", 3)) {
|
||||
DRM_DEBUG("LVDS preferred mode: %s\n", des_mode->name);
|
||||
drm_setup_output(output, lvds_crtc, des_mode);
|
||||
} else
|
||||
output->crtc = NULL;
|
||||
|
||||
/* FB config is max of above desired resolutions */
|
||||
/* FIXME: per-output FBs/CRTCs */
|
||||
if (des_mode->hdisplay > fb->width)
|
||||
fb->width = des_mode->hdisplay;
|
||||
if (des_mode->vdisplay > fb->height)
|
||||
fb->height = des_mode->vdisplay;
|
||||
}
|
||||
|
||||
/* FIXME: multiple depths */
|
||||
bytes_per_pixel = 4;
|
||||
fb->bits_per_pixel = bytes_per_pixel * 8;
|
||||
fb->pitch = fb->width * ((fb->bits_per_pixel + 1) / 8);
|
||||
fb->depth = bytes_per_pixel * 8;
|
||||
size = fb->width * fb->height * bytes_per_pixel;
|
||||
drm_buffer_object_create(dev, size, drm_bo_type_kernel,
|
||||
DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE |
|
||||
DRM_BO_FLAG_MEM_PRIV0 | DRM_BO_FLAG_NO_MOVE,
|
||||
0, 0, 0,
|
||||
&fbo);
|
||||
DRM_DEBUG("allocated %dx%d fb: 0x%08lx, bo %p\n", fb->width,
|
||||
fb->height, fbo->offset, fbo);
|
||||
fb->offset = fbo->offset;
|
||||
fb->bo = fbo;
|
||||
dev->driver->fb_probe(dev, fb);
|
||||
/* FIXME: multiple depths */
|
||||
bytes_per_pixel = 4;
|
||||
fb->bits_per_pixel = 32;
|
||||
fb->pitch = fb->width * ((fb->bits_per_pixel + 1) / 8);
|
||||
fb->depth = 24;
|
||||
size = fb->width * fb->height * bytes_per_pixel;
|
||||
/* FIXME - what about resizeable objects ??? */
|
||||
ret = drm_buffer_object_create(dev, size, drm_bo_type_kernel,
|
||||
DRM_BO_FLAG_READ |
|
||||
DRM_BO_FLAG_WRITE |
|
||||
DRM_BO_FLAG_MEM_PRIV0 |
|
||||
DRM_BO_FLAG_NO_MOVE,
|
||||
0, 0, 0,
|
||||
&fbo);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "failed to allocate framebuffer\n");
|
||||
drm_framebuffer_destroy(fb);
|
||||
continue;
|
||||
}
|
||||
fb->offset = fbo->offset;
|
||||
fb->bo = fbo;
|
||||
printk("allocated %dx%d fb: 0x%08lx, bo %p\n", fb->width,
|
||||
fb->height, fbo->offset, fbo);
|
||||
dev->driver->fb_probe(dev, output->crtc);
|
||||
}
|
||||
drm_disable_unused_functions(dev);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -954,6 +966,7 @@ void drm_mode_config_cleanup(drm_device_t *dev)
|
|||
struct drm_output *output, *ot;
|
||||
struct drm_crtc *crtc, *ct;
|
||||
struct drm_framebuffer *fb, *fbt;
|
||||
struct drm_display_mode *mode, *mt;
|
||||
list_for_each_entry_safe(output, ot, &dev->mode_config.output_list, head) {
|
||||
drm_output_destroy(output);
|
||||
}
|
||||
|
|
@ -962,8 +975,12 @@ void drm_mode_config_cleanup(drm_device_t *dev)
|
|||
drm_crtc_destroy(crtc);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(mode, mt, &dev->mode_config.usermode_list, head) {
|
||||
drm_mode_destroy(dev, mode);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
|
||||
dev->driver->fb_remove(dev, fb);
|
||||
dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb));
|
||||
/* If this FB was the kernel one, free it */
|
||||
if (fb->bo->type == drm_bo_type_kernel) {
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
|
@ -1089,6 +1106,35 @@ void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, struct drm_display
|
|||
out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_crtc_convert_to_umode - convert a modeinfo into a drm_display_mode
|
||||
* @out: drm_display_mode to return to the user
|
||||
* @in: drm_mode_modeinfo to use
|
||||
*
|
||||
* LOCKING:
|
||||
* None.
|
||||
*
|
||||
* Convert a drmo_mode_modeinfo into a drm_display_mode structure to return to
|
||||
* the caller.
|
||||
*/
|
||||
void drm_crtc_convert_umode(struct drm_display_mode *out, struct drm_mode_modeinfo *in)
|
||||
{
|
||||
out->clock = in->clock;
|
||||
out->hdisplay = in->hdisplay;
|
||||
out->hsync_start = in->hsync_start;
|
||||
out->hsync_end = in->hsync_end;
|
||||
out->htotal = in->htotal;
|
||||
out->hskew = in->hskew;
|
||||
out->vdisplay = in->vdisplay;
|
||||
out->vsync_start = in->vsync_start;
|
||||
out->vsync_end = in->vsync_end;
|
||||
out->vtotal = in->vtotal;
|
||||
out->vscan = in->vscan;
|
||||
out->vrefresh = in->vrefresh;
|
||||
out->flags = in->flags;
|
||||
strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
|
||||
out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_mode_getresources - get graphics configuration
|
||||
|
|
@ -1142,6 +1188,8 @@ int drm_mode_getresources(struct inode *inode, struct file *filp,
|
|||
list_for_each(lh, &output->modes)
|
||||
mode_count++;
|
||||
}
|
||||
list_for_each(lh, &dev->mode_config.usermode_list)
|
||||
mode_count++;
|
||||
|
||||
if (copy_from_user(&card_res, argp, sizeof(card_res)))
|
||||
return -EFAULT;
|
||||
|
|
@ -1154,6 +1202,8 @@ int drm_mode_getresources(struct inode *inode, struct file *filp,
|
|||
list_for_each(lh, &output->modes)
|
||||
mode_count++;
|
||||
}
|
||||
list_for_each(lh, &dev->mode_config.usermode_list)
|
||||
mode_count++;
|
||||
}
|
||||
|
||||
/* handle this in 4 parts */
|
||||
|
|
@ -1210,6 +1260,14 @@ int drm_mode_getresources(struct inode *inode, struct file *filp,
|
|||
}
|
||||
}
|
||||
}
|
||||
/* add in user modes */
|
||||
list_for_each_entry(mode, &dev->mode_config.usermode_list, head) {
|
||||
drm_crtc_convert_to_umode(&u_mode, mode);
|
||||
if (copy_to_user(&card_res.modes[copied++], &u_mode, sizeof(struct drm_mode_modeinfo))) {
|
||||
retcode = -EFAULT;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
card_res.count_modes = mode_count;
|
||||
|
||||
|
|
@ -1311,6 +1369,7 @@ int drm_mode_getoutput(struct inode *inode, struct file *filp,
|
|||
int mode_count = 0;
|
||||
int retcode = 0;
|
||||
int copied = 0;
|
||||
int i;
|
||||
|
||||
if (copy_from_user(&out_resp, argp, sizeof(out_resp)))
|
||||
return -EFAULT;
|
||||
|
|
@ -1322,6 +1381,10 @@ int drm_mode_getoutput(struct inode *inode, struct file *filp,
|
|||
|
||||
list_for_each_entry(mode, &output->modes, head)
|
||||
mode_count++;
|
||||
|
||||
for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++)
|
||||
if (output->user_mode_ids[i] != 0)
|
||||
mode_count++;
|
||||
|
||||
strncpy(out_resp.name, output->name, DRM_OUTPUT_NAME_LEN);
|
||||
out_resp.name[DRM_OUTPUT_NAME_LEN-1] = 0;
|
||||
|
|
@ -1343,6 +1406,14 @@ int drm_mode_getoutput(struct inode *inode, struct file *filp,
|
|||
goto done;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) {
|
||||
if (output->user_mode_ids[i] != 0)
|
||||
if (put_user(output->user_mode_ids[i], &out_resp.modes[copied++])) {
|
||||
retcode = -EFAULT;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
out_resp.count_modes = mode_count;
|
||||
|
||||
|
|
@ -1407,9 +1478,13 @@ int drm_mode_setcrtc(struct inode *inode, struct file *filp,
|
|||
if (!mode || (mode->mode_id != crtc_req.mode)) {
|
||||
struct drm_output *output;
|
||||
|
||||
list_for_each_entry(output, &dev->mode_config.output_list, head) {
|
||||
list_for_each_entry(mode, &output->modes, head) {
|
||||
drm_mode_debug_printmodeline(dev, mode);
|
||||
list_for_each_entry(output,
|
||||
&dev->mode_config.output_list,
|
||||
head) {
|
||||
list_for_each_entry(mode, &output->modes,
|
||||
head) {
|
||||
drm_mode_debug_printmodeline(dev,
|
||||
mode);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1517,17 +1592,20 @@ int drm_mode_addfb(struct inode *inode, struct file *filp,
|
|||
r.buffer_id = fb->id;
|
||||
|
||||
list_add(&fb->filp_head, &priv->fbs);
|
||||
|
||||
if (copy_to_user(argp, &r, sizeof(r)))
|
||||
return -EFAULT;
|
||||
|
||||
/* bind the fb to the crtc for now */
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
crtc->fb = fb;
|
||||
|
||||
dev->driver->fb_probe(dev, crtc);
|
||||
}
|
||||
}
|
||||
if (copy_to_user(argp, &r, sizeof(r)))
|
||||
return -EFAULT;
|
||||
|
||||
dev->driver->fb_probe(dev, fb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1563,7 +1641,8 @@ int drm_mode_rmfb(struct inode *inode, struct file *filp,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev->driver->fb_remove(dev, fb);
|
||||
dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb));
|
||||
|
||||
/* TODO check if we own the buffer */
|
||||
/* TODO release all crtc connected to the framebuffer */
|
||||
/* bind the fb to the crtc for now */
|
||||
|
|
@ -1644,8 +1723,199 @@ void drm_fb_release(struct file *filp)
|
|||
|
||||
list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
|
||||
list_del(&fb->filp_head);
|
||||
dev->driver->fb_remove(dev, fb);
|
||||
dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb));
|
||||
drm_framebuffer_destroy(fb);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_fb_newmode - adds a user defined mode
|
||||
* @inode: inode from the ioctl
|
||||
* @filp: file * from the ioctl
|
||||
* @cmd: cmd from ioctl
|
||||
* @arg: arg from ioctl
|
||||
*
|
||||
* Adds a user specified mode to the kernel.
|
||||
*
|
||||
* Called by the user via ioctl.
|
||||
*
|
||||
* RETURNS:
|
||||
* writes new mode id into arg.
|
||||
* Zero on success, errno on failure.
|
||||
*/
|
||||
int drm_mode_addmode(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
struct drm_mode_modeinfo __user *argp = (void __user *)arg;
|
||||
struct drm_mode_modeinfo new_mode;
|
||||
struct drm_display_mode *user_mode;
|
||||
|
||||
if (copy_from_user(&new_mode, argp, sizeof(new_mode)))
|
||||
return -EFAULT;
|
||||
|
||||
user_mode = drm_mode_create(dev);
|
||||
if (!user_mode)
|
||||
return -ENOMEM;
|
||||
|
||||
drm_crtc_convert_umode(user_mode, &new_mode);
|
||||
user_mode->type |= DRM_MODE_TYPE_USERDEF;
|
||||
|
||||
user_mode->output_count = 0;
|
||||
|
||||
spin_lock(&dev->mode_config.config_lock);
|
||||
list_add(&user_mode->head, &dev->mode_config.usermode_list);
|
||||
spin_unlock(&dev->mode_config.config_lock);
|
||||
|
||||
new_mode.id = user_mode->mode_id;
|
||||
if (copy_to_user(argp, &new_mode, sizeof(new_mode)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_fb_rmmode - removes a user defined mode
|
||||
* @inode: inode from the ioctl
|
||||
* @filp: file * from the ioctl
|
||||
* @cmd: cmd from ioctl
|
||||
* @arg: arg from ioctl
|
||||
*
|
||||
* Remove the user defined mode specified by the user.
|
||||
*
|
||||
* Called by the user via ioctl
|
||||
*
|
||||
* RETURNS:
|
||||
* Zero on success, errno on failure.
|
||||
*/
|
||||
int drm_mode_rmmode(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
uint32_t id = arg;
|
||||
struct drm_display_mode *mode, *t;
|
||||
int retcode = -EINVAL;
|
||||
|
||||
mode = idr_find(&dev->mode_config.crtc_idr, id);
|
||||
if (!mode || (id != mode->mode_id))
|
||||
return -EINVAL;
|
||||
|
||||
if (!(mode->type & DRM_MODE_TYPE_USERDEF))
|
||||
return -EINVAL;
|
||||
|
||||
if (mode->output_count)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock(&dev->mode_config.config_lock);
|
||||
list_for_each_entry(t, &dev->mode_config.usermode_list, head) {
|
||||
if (t == mode) {
|
||||
list_del(&mode->head);
|
||||
drm_mode_destroy(dev, mode);
|
||||
retcode = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&dev->mode_config.config_lock);
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_fb_attachmode - Attach a user mode to an output
|
||||
* @inode: inode from the ioctl
|
||||
* @filp: file * from the ioctl
|
||||
* @cmd: cmd from ioctl
|
||||
* @arg: arg from ioctl
|
||||
*
|
||||
* This attaches a user specified mode to an output.
|
||||
* Called by the user via ioctl.
|
||||
*
|
||||
* RETURNS:
|
||||
* Zero on success, errno on failure.
|
||||
*/
|
||||
int drm_mode_attachmode(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
struct drm_mode_mode_cmd __user *argp = (void __user *)arg;
|
||||
struct drm_mode_mode_cmd mode_cmd;
|
||||
struct drm_output *output;
|
||||
struct drm_display_mode *mode;
|
||||
int i;
|
||||
|
||||
if (copy_from_user(&mode_cmd, argp, sizeof(mode_cmd)))
|
||||
return -EFAULT;
|
||||
|
||||
mode = idr_find(&dev->mode_config.crtc_idr, mode_cmd.mode_id);
|
||||
if (!mode || (mode->mode_id != mode_cmd.mode_id))
|
||||
return -EINVAL;
|
||||
|
||||
output = idr_find(&dev->mode_config.crtc_idr, mode_cmd.output_id);
|
||||
if (!output || (output->id != mode_cmd.output_id))
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) {
|
||||
if (output->user_mode_ids[i] == 0) {
|
||||
output->user_mode_ids[i] = mode->mode_id;
|
||||
mode->output_count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == DRM_OUTPUT_MAX_UMODES)
|
||||
return -ENOSPC;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* drm_fb_detachmode - Detach a user specified mode from an output
|
||||
* @inode: inode from the ioctl
|
||||
* @filp: file * from the ioctl
|
||||
* @cmd: cmd from ioctl
|
||||
* @arg: arg from ioctl
|
||||
*
|
||||
* Called by the user via ioctl.
|
||||
*
|
||||
* RETURNS:
|
||||
* Zero on success, errno on failure.
|
||||
*/
|
||||
int drm_mode_detachmode(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
struct drm_mode_mode_cmd __user *argp = (void __user *)arg;
|
||||
struct drm_mode_mode_cmd mode_cmd;
|
||||
struct drm_output *output;
|
||||
struct drm_display_mode *mode;
|
||||
int i, found = 0;
|
||||
|
||||
if (copy_from_user(&mode_cmd, argp, sizeof(mode_cmd)))
|
||||
return -EFAULT;
|
||||
|
||||
mode = idr_find(&dev->mode_config.crtc_idr, mode_cmd.mode_id);
|
||||
if (!mode || (mode->mode_id != mode_cmd.mode_id))
|
||||
return -EINVAL;
|
||||
|
||||
output = idr_find(&dev->mode_config.crtc_idr, mode_cmd.output_id);
|
||||
if (!output || (output->id != mode_cmd.output_id))
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) {
|
||||
if (output->user_mode_ids[i] == mode->mode_id) {
|
||||
output->user_mode_ids[i] = 0;
|
||||
mode->output_count--;
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ struct drm_display_mode {
|
|||
struct list_head head;
|
||||
char name[DRM_DISPLAY_MODE_LEN];
|
||||
int mode_id;
|
||||
int output_count;
|
||||
enum drm_mode_status status;
|
||||
int type;
|
||||
|
||||
|
|
@ -293,8 +294,8 @@ struct drm_crtc_funcs {
|
|||
void (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode, int x, int y);
|
||||
/* Set gamma on the CRTC */
|
||||
void (*gamma_set)(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
|
||||
int size);
|
||||
void (*gamma_set)(struct drm_crtc *crtc, u16 r, u16 g, u16 b,
|
||||
int regno);
|
||||
/* Driver cleanup routine */
|
||||
void (*cleanup)(struct drm_crtc *crtc);
|
||||
};
|
||||
|
|
@ -319,7 +320,7 @@ struct drm_crtc {
|
|||
|
||||
int id; /* idr assigned */
|
||||
|
||||
/* framebuffer the CRTC is currently bound to */
|
||||
/* framebuffer the output is currently bound to */
|
||||
struct drm_framebuffer *fb;
|
||||
|
||||
bool enabled;
|
||||
|
|
@ -382,6 +383,7 @@ struct drm_output_funcs {
|
|||
void (*cleanup)(struct drm_output *output);
|
||||
};
|
||||
|
||||
#define DRM_OUTPUT_MAX_UMODES 16
|
||||
#define DRM_OUTPUT_LEN 32
|
||||
/**
|
||||
* drm_output - central DRM output control structure
|
||||
|
|
@ -417,6 +419,7 @@ struct drm_output {
|
|||
bool doublescan_allowed;
|
||||
spinlock_t modes_lock; /* protects modes and probed_modes lists */
|
||||
struct list_head modes; /* list of modes on this output */
|
||||
|
||||
/*
|
||||
OptionInfoPtr options;
|
||||
XF86ConfMonitorPtr conf_monitor;
|
||||
|
|
@ -434,7 +437,9 @@ struct drm_output {
|
|||
char name[DRM_OUTPUT_LEN];
|
||||
const struct drm_output_funcs *funcs;
|
||||
void *driver_private;
|
||||
/* RROutputPtr randr_output? */
|
||||
|
||||
u32 user_mode_ids[DRM_OUTPUT_MAX_UMODES];
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -467,6 +472,7 @@ struct drm_mode_config {
|
|||
int num_crtc;
|
||||
struct list_head crtc_list;
|
||||
|
||||
struct list_head usermode_list;
|
||||
int min_width, min_height;
|
||||
int max_width, max_height;
|
||||
/* DamagePtr rotationDamage? */
|
||||
|
|
@ -480,6 +486,7 @@ struct drm_output *drm_output_create(struct drm_device *dev,
|
|||
const char *name);
|
||||
extern void drm_output_destroy(struct drm_output *output);
|
||||
extern bool drm_output_rename(struct drm_output *output, const char *name);
|
||||
extern void drm_fb_release(struct file *filp);
|
||||
|
||||
extern int drm_add_edid_modes(struct drm_output *output,
|
||||
struct i2c_adapter *adapter);
|
||||
|
|
@ -492,6 +499,7 @@ extern void drm_mode_debug_printmodeline(struct drm_device *dev,
|
|||
extern void drm_mode_config_init(struct drm_device *dev);
|
||||
extern void drm_mode_config_cleanup(struct drm_device *dev);
|
||||
extern void drm_mode_set_name(struct drm_display_mode *mode);
|
||||
extern bool drm_mode_equal(struct drm_display_mode *mode1, struct drm_display_mode *mode2);
|
||||
extern void drm_disable_unused_functions(struct drm_device *dev);
|
||||
|
||||
extern struct drm_display_mode *drm_mode_create(struct drm_device *dev);
|
||||
|
|
@ -507,12 +515,13 @@ extern void drm_mode_sort(struct list_head *mode_list);
|
|||
extern int drm_mode_vrefresh(struct drm_display_mode *mode);
|
||||
extern void drm_mode_set_crtcinfo(struct drm_display_mode *p,
|
||||
int adjust_flags);
|
||||
extern void drm_mode_output_list_update(struct drm_output *output);
|
||||
|
||||
extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev);
|
||||
extern bool drm_initial_config(struct drm_device *dev, bool cangrow);
|
||||
extern void drm_framebuffer_set_object(struct drm_device *dev,
|
||||
unsigned long handle);
|
||||
extern bool drm_set_desired_modes(struct drm_device *dev);
|
||||
extern int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb);
|
||||
extern int drmfb_probe(struct drm_device *dev, struct drm_crtc *crtc);
|
||||
extern int drmfb_remove(struct drm_device *dev, struct drm_framebuffer *fb);
|
||||
|
||||
/* IOCTLs */
|
||||
|
|
@ -531,5 +540,14 @@ extern int drm_mode_rmfb(struct inode *inode, struct file *filp,
|
|||
unsigned int cmd, unsigned long arg);
|
||||
extern int drm_mode_getfb(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
extern int drm_mode_addmode(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
extern int drm_mode_rmmode(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
extern int drm_mode_attachmode(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
extern int drm_mode_detachmode(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
#endif /* __DRM_CRTC_H__ */
|
||||
|
||||
|
|
|
|||
|
|
@ -130,6 +130,10 @@ static drm_ioctl_desc_t drm_ioctls[] = {
|
|||
[DRM_IOCTL_NR(DRM_IOCTL_MODE_ADDFB)] = {drm_mode_addfb, DRM_MASTER|DRM_ROOT_ONLY},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_MODE_RMFB)] = {drm_mode_rmfb, DRM_MASTER|DRM_ROOT_ONLY},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_MODE_GETFB)] = {drm_mode_getfb, DRM_MASTER|DRM_ROOT_ONLY},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_MODE_ADDMODE)] = {drm_mode_addmode, DRM_MASTER|DRM_ROOT_ONLY},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_MODE_RMMODE)] = {drm_mode_rmmode, DRM_MASTER|DRM_ROOT_ONLY},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_MODE_ATTACHMODE)] = {drm_mode_attachmode, DRM_MASTER|DRM_ROOT_ONLY},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_MODE_DETACHMODE)] = {drm_mode_detachmode, DRM_MASTER|DRM_ROOT_ONLY},
|
||||
};
|
||||
|
||||
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
|
||||
|
|
|
|||
|
|
@ -39,9 +39,11 @@
|
|||
#include <linux/init.h>
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm_crtc.h"
|
||||
|
||||
struct drmfb_par {
|
||||
struct drm_device *dev;
|
||||
struct drm_framebuffer *fb;
|
||||
struct drm_crtc *crtc;
|
||||
};
|
||||
|
||||
static int drmfb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
||||
|
|
@ -49,11 +51,20 @@ static int drmfb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
|||
struct fb_info *info)
|
||||
{
|
||||
struct drmfb_par *par = info->par;
|
||||
struct drm_framebuffer *fb = par->fb;
|
||||
if (regno > 17)
|
||||
struct drm_framebuffer *fb = par->crtc->fb;
|
||||
struct drm_crtc *crtc = par->crtc;
|
||||
|
||||
if (regno > 255)
|
||||
return 1;
|
||||
|
||||
if (regno < 16) {
|
||||
if (fb->depth == 8) {
|
||||
if (crtc->funcs->gamma_set) {
|
||||
crtc->funcs->gamma_set(crtc, red, green, blue, regno);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (regno < 16) {
|
||||
switch (fb->depth) {
|
||||
case 15:
|
||||
fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) |
|
||||
|
|
@ -72,8 +83,119 @@ static int drmfb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
|||
((blue & 0xff00) >> 8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drmfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
|
||||
{
|
||||
struct drmfb_par *par = info->par;
|
||||
struct drm_device *dev = par->dev;
|
||||
struct drm_framebuffer *fb = par->crtc->fb;
|
||||
struct drm_display_mode *drm_mode;
|
||||
struct drm_output *output;
|
||||
int depth;
|
||||
|
||||
if (!var->pixclock)
|
||||
return -EINVAL;
|
||||
|
||||
/* Need to resize the fb object !!! */
|
||||
if (var->xres > fb->width || var->yres > fb->height) {
|
||||
DRM_ERROR("Requested width/height is greater than current fb object %dx%d > %dx%d\n",var->xres,var->yres,fb->width,fb->height);
|
||||
DRM_ERROR("Need resizing code.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (var->bits_per_pixel) {
|
||||
case 16:
|
||||
depth = (var->green.length == 6) ? 16 : 15;
|
||||
break;
|
||||
case 32:
|
||||
depth = (var->transp.length > 0) ? 32 : 24;
|
||||
break;
|
||||
default:
|
||||
depth = var->bits_per_pixel;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (depth) {
|
||||
case 8:
|
||||
var->red.offset = 0;
|
||||
var->green.offset = 0;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.length = 8;
|
||||
var->transp.length = 0;
|
||||
var->transp.offset = 0;
|
||||
break;
|
||||
case 15:
|
||||
var->red.offset = 10;
|
||||
var->green.offset = 5;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 5;
|
||||
var->green.length = 5;
|
||||
var->blue.length = 5;
|
||||
var->transp.length = 1;
|
||||
var->transp.offset = 15;
|
||||
break;
|
||||
case 16:
|
||||
var->red.offset = 11;
|
||||
var->green.offset = 6;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 5;
|
||||
var->green.length = 6;
|
||||
var->blue.length = 5;
|
||||
var->transp.length = 0;
|
||||
var->transp.offset = 0;
|
||||
break;
|
||||
case 24:
|
||||
var->red.offset = 16;
|
||||
var->green.offset = 8;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.length = 8;
|
||||
var->transp.length = 0;
|
||||
var->transp.offset = 0;
|
||||
break;
|
||||
case 32:
|
||||
var->red.offset = 16;
|
||||
var->green.offset = 8;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.length = 8;
|
||||
var->transp.length = 8;
|
||||
var->transp.offset = 24;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Here we walk the output mode list and look for modes. If we haven't
|
||||
* got it, then bail. Not very nice, so this is disabled.
|
||||
* In the set_par code, we create our mode based on the incoming
|
||||
* parameters. Nicer, but may not be desired by some.
|
||||
*/
|
||||
list_for_each_entry(output, &dev->mode_config.output_list, head) {
|
||||
if (output->crtc == par->crtc)
|
||||
break;
|
||||
}
|
||||
|
||||
list_for_each_entry(drm_mode, &output->modes, head) {
|
||||
if (drm_mode->hdisplay == var->xres &&
|
||||
drm_mode->vdisplay == var->yres &&
|
||||
drm_mode->clock != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!drm_mode)
|
||||
return -EINVAL;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -81,9 +203,74 @@ static int drmfb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
|||
static int drmfb_set_par(struct fb_info *info)
|
||||
{
|
||||
struct drmfb_par *par = info->par;
|
||||
struct drm_framebuffer *fb = par->crtc->fb;
|
||||
struct drm_device *dev = par->dev;
|
||||
struct drm_display_mode *drm_mode;
|
||||
struct fb_var_screeninfo *var = &info->var;
|
||||
struct drm_output *output;
|
||||
|
||||
switch (var->bits_per_pixel) {
|
||||
case 16:
|
||||
fb->depth = (var->green.length == 6) ? 16 : 15;
|
||||
break;
|
||||
case 32:
|
||||
fb->depth = (var->transp.length > 0) ? 32 : 24;
|
||||
break;
|
||||
default:
|
||||
fb->depth = var->bits_per_pixel;
|
||||
break;
|
||||
}
|
||||
|
||||
fb->bits_per_pixel = var->bits_per_pixel;
|
||||
|
||||
info->fix.line_length = fb->pitch;
|
||||
info->fix.smem_len = info->fix.line_length * fb->height;
|
||||
info->fix.visual = (fb->depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
|
||||
|
||||
info->screen_size = info->fix.smem_len; /* ??? */
|
||||
|
||||
/* Should we walk the output's modelist or just create our own ???
|
||||
* For now, we create and destroy a mode based on the incoming
|
||||
* parameters. But there's commented out code below which scans
|
||||
* the output list too.
|
||||
*/
|
||||
#if 0
|
||||
list_for_each_entry(output, &dev->mode_config.output_list, head) {
|
||||
if (output->crtc == par->crtc)
|
||||
break;
|
||||
}
|
||||
|
||||
list_for_each_entry(drm_mode, &output->modes, head) {
|
||||
if (drm_mode->hdisplay == var->xres &&
|
||||
drm_mode->vdisplay == var->yres &&
|
||||
drm_mode->clock != 0)
|
||||
break;
|
||||
}
|
||||
#else
|
||||
drm_mode = drm_mode_create(dev);
|
||||
drm_mode->hdisplay = var->xres;
|
||||
drm_mode->hsync_start = drm_mode->hdisplay + var->right_margin;
|
||||
drm_mode->hsync_end = drm_mode->hsync_start + var->hsync_len;
|
||||
drm_mode->htotal = drm_mode->hsync_end + var->left_margin;
|
||||
drm_mode->vdisplay = var->yres;
|
||||
drm_mode->vsync_start = drm_mode->vdisplay + var->lower_margin;
|
||||
drm_mode->vsync_end = drm_mode->vsync_start + var->vsync_len;
|
||||
drm_mode->vtotal = drm_mode->vsync_end + var->upper_margin;
|
||||
drm_mode->clock = PICOS2KHZ(var->pixclock);
|
||||
drm_mode->vrefresh = drm_mode_vrefresh(drm_mode);
|
||||
drm_mode_set_name(drm_mode);
|
||||
#endif
|
||||
|
||||
if (!drm_crtc_set_mode(par->crtc, drm_mode, 0, 0))
|
||||
return -EINVAL;
|
||||
|
||||
/* Have to destroy our created mode if we're not searching the mode
|
||||
* list for it.
|
||||
*/
|
||||
#if 1
|
||||
drm_mode_destroy(dev, drm_mode);
|
||||
#endif
|
||||
|
||||
drm_set_desired_modes(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -94,6 +281,7 @@ static struct fb_ops drmfb_ops = {
|
|||
// .fb_write = drmfb_write,
|
||||
// .fb_release = drmfb_release,
|
||||
// .fb_ioctl = drmfb_ioctl,
|
||||
.fb_check_var = drmfb_check_var,
|
||||
.fb_set_par = drmfb_set_par,
|
||||
.fb_setcolreg = drmfb_setcolreg,
|
||||
.fb_fillrect = cfb_fillrect,
|
||||
|
|
@ -101,11 +289,13 @@ static struct fb_ops drmfb_ops = {
|
|||
.fb_imageblit = cfb_imageblit,
|
||||
};
|
||||
|
||||
int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb)
|
||||
int drmfb_probe(struct drm_device *dev, struct drm_crtc *crtc)
|
||||
{
|
||||
struct fb_info *info;
|
||||
struct drm_framebuffer *fb = crtc->fb;
|
||||
struct drmfb_par *par;
|
||||
struct device *device = &dev->pdev->dev;
|
||||
struct drm_display_mode *mode = crtc->desired_mode;
|
||||
int ret;
|
||||
|
||||
info = framebuffer_alloc(sizeof(struct drmfb_par), device);
|
||||
|
|
@ -118,20 +308,20 @@ int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb)
|
|||
par = info->par;
|
||||
|
||||
par->dev = dev;
|
||||
par->fb = fb;
|
||||
par->crtc = crtc;
|
||||
|
||||
info->fbops = &drmfb_ops;
|
||||
|
||||
strcpy(info->fix.id, "drmfb");
|
||||
info->fix.smem_start = fb->offset + dev->mode_config.fb_base;
|
||||
info->fix.smem_len = fb->bo->mem.size;
|
||||
info->fix.type = FB_TYPE_PACKED_PIXELS;
|
||||
info->fix.visual = FB_VISUAL_DIRECTCOLOR;
|
||||
info->fix.visual = FB_VISUAL_TRUECOLOR;
|
||||
info->fix.accel = FB_ACCEL_NONE;
|
||||
info->fix.type_aux = 0;
|
||||
info->fix.mmio_start = 0;
|
||||
info->fix.mmio_len = 0;
|
||||
info->fix.line_length = fb->pitch * ((fb->bits_per_pixel + 1) / 8);
|
||||
info->fix.line_length = fb->pitch;
|
||||
info->fix.smem_start = fb->offset + dev->mode_config.fb_base;
|
||||
info->fix.smem_len = info->fix.line_length * fb->height;
|
||||
|
||||
info->flags = FBINFO_DEFAULT;
|
||||
|
||||
|
|
@ -140,11 +330,9 @@ int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb)
|
|||
DRM_ERROR("error mapping fb: %d\n", ret);
|
||||
|
||||
info->screen_base = fb->virtual_base;
|
||||
info->screen_size = fb->bo->mem.size;
|
||||
info->screen_size = info->fix.smem_len; /* ??? */
|
||||
info->pseudo_palette = fb->pseudo_palette;
|
||||
info->var.xres = fb->width;
|
||||
info->var.xres_virtual = fb->pitch;
|
||||
info->var.yres = fb->height;
|
||||
info->var.xres_virtual = fb->width;
|
||||
info->var.yres_virtual = fb->height;
|
||||
info->var.bits_per_pixel = fb->bits_per_pixel;
|
||||
info->var.xoffset = 0;
|
||||
|
|
@ -154,24 +342,69 @@ int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb)
|
|||
info->var.width = -1;
|
||||
info->var.vmode = FB_VMODE_NONINTERLACED;
|
||||
|
||||
info->var.xres = mode->hdisplay;
|
||||
info->var.right_margin = mode->hsync_start - mode->hdisplay;
|
||||
info->var.hsync_len = mode->hsync_end - mode->hsync_start;
|
||||
info->var.left_margin = mode->htotal - mode->hsync_end;
|
||||
info->var.yres = mode->vdisplay;
|
||||
info->var.lower_margin = mode->vsync_start - mode->vdisplay;
|
||||
info->var.vsync_len = mode->vsync_end - mode->vsync_start;
|
||||
info->var.upper_margin = mode->vtotal - mode->vsync_end;
|
||||
info->var.pixclock = 10000000 / mode->htotal * 1000 /
|
||||
mode->vtotal * 100;
|
||||
/* avoid overflow */
|
||||
info->var.pixclock = info->var.pixclock * 1000 / mode->vrefresh;
|
||||
|
||||
DRM_DEBUG("fb depth is %d\n", fb->depth);
|
||||
switch(fb->depth) {
|
||||
case 8:
|
||||
case 15:
|
||||
case 16:
|
||||
info->var.red.offset = 0;
|
||||
info->var.green.offset = 0;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = 8; /* 8bit DAC */
|
||||
info->var.green.length = 8;
|
||||
info->var.blue.length = 8;
|
||||
info->var.transp.offset = 0;
|
||||
info->var.transp.length = 0;
|
||||
break;
|
||||
case 15:
|
||||
info->var.red.offset = 10;
|
||||
info->var.green.offset = 5;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = info->var.green.length =
|
||||
info->var.blue.length = 5;
|
||||
info->var.transp.offset = 15;
|
||||
info->var.transp.length = 1;
|
||||
break;
|
||||
case 16:
|
||||
info->var.red.offset = 11;
|
||||
info->var.green.offset = 5;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = 5;
|
||||
info->var.green.length = 6;
|
||||
info->var.blue.length = 5;
|
||||
info->var.transp.offset = 0;
|
||||
info->var.transp.length = 0;
|
||||
break;
|
||||
default:
|
||||
case 24:
|
||||
info->var.red.offset = 16;
|
||||
info->var.green.offset = 8;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = info->var.green.length =
|
||||
info->var.blue.length = 8;
|
||||
info->var.transp.offset = 0;
|
||||
info->var.transp.length = 0;
|
||||
break;
|
||||
case 32:
|
||||
info->var.red.offset = 16;
|
||||
info->var.green.offset = 8;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = info->var.green.length =
|
||||
info->var.blue.length = 8;
|
||||
if (fb->depth == 32) {
|
||||
info->var.transp.offset = 24;
|
||||
info->var.transp.length = 8;
|
||||
}
|
||||
info->var.transp.offset = 24;
|
||||
info->var.transp.length = 8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -533,7 +533,7 @@ void drm_mode_sort(struct list_head *mode_list)
|
|||
*/
|
||||
void drm_mode_output_list_update(struct drm_output *output)
|
||||
{
|
||||
struct drm_display_mode *mode, *t;
|
||||
struct drm_display_mode *mode;
|
||||
struct drm_display_mode *pmode, *pt;
|
||||
int found_it;
|
||||
list_for_each_entry_safe(pmode, pt, &output->probed_modes,
|
||||
|
|
|
|||
|
|
@ -459,6 +459,7 @@ extern int drm_bo_mem_space(drm_buffer_object_t * bo,
|
|||
drm_bo_mem_reg_t * mem, int no_wait);
|
||||
extern int drm_bo_move_buffer(drm_buffer_object_t * bo, uint32_t new_mem_flags,
|
||||
int no_wait, int move_unfenced);
|
||||
extern int drm_bo_clean_mm(struct drm_device *dev, unsigned mem_type);
|
||||
|
||||
/*
|
||||
* Buffer object memory move helpers.
|
||||
|
|
|
|||
|
|
@ -787,6 +787,9 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
else
|
||||
dpll |= PLL_REF_INPUT_DREFCLK;
|
||||
|
||||
/* setup pipeconf */
|
||||
pipeconf = I915_READ(pipeconf_reg);
|
||||
|
||||
/* Set up the display plane register */
|
||||
dspcntr = DISPPLANE_GAMMA_ENABLE;
|
||||
|
||||
|
|
@ -814,7 +817,6 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
else
|
||||
dspcntr |= DISPPLANE_SEL_PIPE_B;
|
||||
|
||||
pipeconf = I915_READ(pipeconf_reg);
|
||||
if (pipe == 0 && !IS_I965G(dev)) {
|
||||
/* Enable pixel doubling when the dot clock is > 90% of the (display)
|
||||
* core speed.
|
||||
|
|
@ -955,19 +957,14 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
|
|||
}
|
||||
|
||||
/** Sets the color ramps on behalf of RandR */
|
||||
static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
|
||||
u16 *blue, int size)
|
||||
static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
|
||||
u16 blue, int regno)
|
||||
{
|
||||
struct intel_crtc *intel_crtc = crtc->driver_private;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
intel_crtc->lut_r[i] = red[i] >> 8;
|
||||
intel_crtc->lut_g[i] = green[i] >> 8;
|
||||
intel_crtc->lut_b[i] = blue[i] >> 8;
|
||||
}
|
||||
|
||||
intel_crtc_load_lut(crtc);
|
||||
intel_crtc->lut_r[regno] = red >> 8;
|
||||
intel_crtc->lut_g[regno] = green >> 8;
|
||||
intel_crtc->lut_b[regno] = blue >> 8;
|
||||
}
|
||||
|
||||
/* Returns the clock of the currently programmed mode of the given pipe. */
|
||||
|
|
@ -1176,7 +1173,8 @@ static void intel_setup_outputs(drm_device_t *dev)
|
|||
(1 << INTEL_OUTPUT_SDVO));
|
||||
break;
|
||||
case INTEL_OUTPUT_ANALOG:
|
||||
crtc_mask = ((1 << 0));
|
||||
crtc_mask = ((1 << 0)|
|
||||
(1 << 1));
|
||||
clone_mask = ((1 << INTEL_OUTPUT_ANALOG) |
|
||||
(1 << INTEL_OUTPUT_DVO) |
|
||||
(1 << INTEL_OUTPUT_SDVO));
|
||||
|
|
@ -1223,7 +1221,6 @@ void intel_modeset_init(drm_device_t *dev)
|
|||
intel_setup_outputs(dev);
|
||||
|
||||
//drm_initial_config(dev, false);
|
||||
//drm_set_desired_modes(dev);
|
||||
}
|
||||
|
||||
void intel_modeset_cleanup(drm_device_t *dev)
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ extern void intel_crtc_load_lut(struct drm_crtc *crtc);
|
|||
extern void intel_output_prepare (struct drm_output *output);
|
||||
extern void intel_output_commit (struct drm_output *output);
|
||||
extern struct drm_display_mode *intel_crtc_mode_get(drm_device_t *dev,
|
||||
struct drm_crtc *crtc);
|
||||
struct drm_crtc *crtc);
|
||||
extern void intel_wait_for_vblank(drm_device_t *dev);
|
||||
extern struct drm_crtc *intel_get_crtc_from_pipe(drm_device_t *dev, int pipe);
|
||||
|
||||
|
|
|
|||
|
|
@ -40,12 +40,13 @@
|
|||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "drm_crtc.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
struct intelfb_par {
|
||||
struct drm_device *dev;
|
||||
struct drm_framebuffer *fb;
|
||||
struct drm_crtc *crtc;
|
||||
};
|
||||
|
||||
static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
||||
|
|
@ -53,10 +54,18 @@ static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
|||
struct fb_info *info)
|
||||
{
|
||||
struct intelfb_par *par = info->par;
|
||||
struct drm_framebuffer *fb = par->fb;
|
||||
if (regno > 17)
|
||||
struct drm_framebuffer *fb = par->crtc->fb;
|
||||
struct drm_crtc *crtc = par->crtc;
|
||||
|
||||
if (regno > 255)
|
||||
return 1;
|
||||
|
||||
if (fb->depth == 8) {
|
||||
if (crtc->funcs->gamma_set)
|
||||
crtc->funcs->gamma_set(crtc, red, green, blue, regno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (regno < 16) {
|
||||
switch (fb->depth) {
|
||||
case 15:
|
||||
|
|
@ -81,16 +90,194 @@ static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int intelfb_check_var(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info)
|
||||
{
|
||||
struct intelfb_par *par = info->par;
|
||||
struct drm_device *dev = par->dev;
|
||||
struct drm_framebuffer *fb = par->crtc->fb;
|
||||
struct drm_display_mode *drm_mode;
|
||||
struct drm_output *output;
|
||||
int depth;
|
||||
|
||||
if (!var->pixclock)
|
||||
return -EINVAL;
|
||||
|
||||
/* Need to resize the fb object !!! */
|
||||
if (var->xres > fb->width || var->yres > fb->height) {
|
||||
DRM_ERROR("Requested width/height is greater than current fb object %dx%d > %dx%d\n",var->xres,var->yres,fb->width,fb->height);
|
||||
DRM_ERROR("Need resizing code.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (var->bits_per_pixel) {
|
||||
case 16:
|
||||
depth = (var->green.length == 6) ? 16 : 15;
|
||||
break;
|
||||
case 32:
|
||||
depth = (var->transp.length > 0) ? 32 : 24;
|
||||
break;
|
||||
default:
|
||||
depth = var->bits_per_pixel;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (depth) {
|
||||
case 8:
|
||||
var->red.offset = 0;
|
||||
var->green.offset = 0;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.length = 8;
|
||||
var->transp.length = 0;
|
||||
var->transp.offset = 0;
|
||||
break;
|
||||
case 15:
|
||||
var->red.offset = 10;
|
||||
var->green.offset = 5;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 5;
|
||||
var->green.length = 5;
|
||||
var->blue.length = 5;
|
||||
var->transp.length = 1;
|
||||
var->transp.offset = 15;
|
||||
break;
|
||||
case 16:
|
||||
var->red.offset = 11;
|
||||
var->green.offset = 6;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 5;
|
||||
var->green.length = 6;
|
||||
var->blue.length = 5;
|
||||
var->transp.length = 0;
|
||||
var->transp.offset = 0;
|
||||
break;
|
||||
case 24:
|
||||
var->red.offset = 16;
|
||||
var->green.offset = 8;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.length = 8;
|
||||
var->transp.length = 0;
|
||||
var->transp.offset = 0;
|
||||
break;
|
||||
case 32:
|
||||
var->red.offset = 16;
|
||||
var->green.offset = 8;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.length = 8;
|
||||
var->transp.length = 8;
|
||||
var->transp.offset = 24;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Here we walk the output mode list and look for modes. If we haven't
|
||||
* got it, then bail. Not very nice, so this is disabled.
|
||||
* In the set_par code, we create our mode based on the incoming
|
||||
* parameters. Nicer, but may not be desired by some.
|
||||
*/
|
||||
list_for_each_entry(output, &dev->mode_config.output_list, head) {
|
||||
if (output->crtc == par->crtc)
|
||||
break;
|
||||
}
|
||||
|
||||
list_for_each_entry(drm_mode, &output->modes, head) {
|
||||
if (drm_mode->hdisplay == var->xres &&
|
||||
drm_mode->vdisplay == var->yres &&
|
||||
drm_mode->clock != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!drm_mode)
|
||||
return -EINVAL;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this will let fbcon do the mode init */
|
||||
static int intelfb_set_par(struct fb_info *info)
|
||||
{
|
||||
struct intelfb_par *par = info->par;
|
||||
struct drm_framebuffer *fb = par->crtc->fb;
|
||||
struct drm_device *dev = par->dev;
|
||||
struct drm_display_mode *drm_mode;
|
||||
struct fb_var_screeninfo *var = &info->var;
|
||||
struct drm_output *output;
|
||||
|
||||
switch (var->bits_per_pixel) {
|
||||
case 16:
|
||||
fb->depth = (var->green.length == 6) ? 16 : 15;
|
||||
break;
|
||||
case 32:
|
||||
fb->depth = (var->transp.length > 0) ? 32 : 24;
|
||||
break;
|
||||
default:
|
||||
fb->depth = var->bits_per_pixel;
|
||||
break;
|
||||
}
|
||||
|
||||
fb->bits_per_pixel = var->bits_per_pixel;
|
||||
|
||||
info->fix.line_length = fb->pitch;
|
||||
info->fix.smem_len = info->fix.line_length * fb->height;
|
||||
info->fix.visual = (fb->depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
|
||||
|
||||
info->screen_size = info->fix.smem_len; /* ??? */
|
||||
|
||||
/* Should we walk the output's modelist or just create our own ???
|
||||
* For now, we create and destroy a mode based on the incoming
|
||||
* parameters. But there's commented out code below which scans
|
||||
* the output list too.
|
||||
*/
|
||||
#if 0
|
||||
list_for_each_entry(output, &dev->mode_config.output_list, head) {
|
||||
if (output->crtc == par->crtc)
|
||||
break;
|
||||
}
|
||||
|
||||
list_for_each_entry(drm_mode, &output->modes, head) {
|
||||
if (drm_mode->hdisplay == var->xres &&
|
||||
drm_mode->vdisplay == var->yres &&
|
||||
drm_mode->clock != 0)
|
||||
break;
|
||||
}
|
||||
#else
|
||||
drm_mode = drm_mode_create(dev);
|
||||
drm_mode->hdisplay = var->xres;
|
||||
drm_mode->hsync_start = drm_mode->hdisplay + var->right_margin;
|
||||
drm_mode->hsync_end = drm_mode->hsync_start + var->hsync_len;
|
||||
drm_mode->htotal = drm_mode->hsync_end + var->left_margin;
|
||||
drm_mode->vdisplay = var->yres;
|
||||
drm_mode->vsync_start = drm_mode->vdisplay + var->lower_margin;
|
||||
drm_mode->vsync_end = drm_mode->vsync_start + var->vsync_len;
|
||||
drm_mode->vtotal = drm_mode->vsync_end + var->upper_margin;
|
||||
drm_mode->clock = PICOS2KHZ(var->pixclock);
|
||||
drm_mode->vrefresh = drm_mode_vrefresh(drm_mode);
|
||||
drm_mode_set_name(drm_mode);
|
||||
#endif
|
||||
|
||||
if (!drm_crtc_set_mode(par->crtc, drm_mode, 0, 0))
|
||||
return -EINVAL;
|
||||
|
||||
/* Have to destroy our created mode if we're not searching the mode
|
||||
* list for it.
|
||||
*/
|
||||
#if 1
|
||||
drm_mode_destroy(dev, drm_mode);
|
||||
#endif
|
||||
|
||||
drm_set_desired_modes(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void intelfb_copyarea(struct fb_info *info,
|
||||
const struct fb_copyarea *region)
|
||||
{
|
||||
|
|
@ -234,6 +421,7 @@ void intelfb_imageblit(struct fb_info *info, const struct fb_image *image)
|
|||
OUT_RING(MI_NOOP);
|
||||
ADVANCE_LP_RING();
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct fb_ops intelfb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
|
|
@ -242,18 +430,21 @@ static struct fb_ops intelfb_ops = {
|
|||
// .fb_write = intelfb_write,
|
||||
// .fb_release = intelfb_release,
|
||||
// .fb_ioctl = intelfb_ioctl,
|
||||
.fb_check_var = intelfb_check_var,
|
||||
.fb_set_par = intelfb_set_par,
|
||||
.fb_setcolreg = intelfb_setcolreg,
|
||||
.fb_fillrect = cfb_fillrect,
|
||||
.fb_copyarea = cfb_copyarea, //intelfb_copyarea,
|
||||
.fb_imageblit = intelfb_imageblit,
|
||||
.fb_imageblit = cfb_imageblit, //intelfb_imageblit,
|
||||
};
|
||||
|
||||
int intelfb_probe(struct drm_device *dev, struct drm_framebuffer *fb)
|
||||
int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc)
|
||||
{
|
||||
struct fb_info *info;
|
||||
struct intelfb_par *par;
|
||||
struct device *device = &dev->pdev->dev;
|
||||
struct drm_framebuffer *fb = crtc->fb;
|
||||
struct drm_display_mode *mode = crtc->desired_mode;
|
||||
int ret;
|
||||
|
||||
info = framebuffer_alloc(sizeof(struct intelfb_par), device);
|
||||
|
|
@ -266,24 +457,24 @@ int intelfb_probe(struct drm_device *dev, struct drm_framebuffer *fb)
|
|||
par = info->par;
|
||||
|
||||
par->dev = dev;
|
||||
par->fb = fb;
|
||||
par->crtc = crtc;
|
||||
|
||||
info->fbops = &intelfb_ops;
|
||||
|
||||
strcpy(info->fix.id, "intelfb");
|
||||
info->fix.smem_start = fb->offset + dev->mode_config.fb_base;
|
||||
info->fix.smem_len = fb->bo->mem.size;
|
||||
info->fix.type = FB_TYPE_PACKED_PIXELS;
|
||||
info->fix.visual = FB_VISUAL_TRUECOLOR;
|
||||
info->fix.type_aux = 0;
|
||||
info->fix.xpanstep = 8;
|
||||
info->fix.ypanstep = 1;
|
||||
info->fix.ywrapstep = 0;
|
||||
info->fix.visual = FB_VISUAL_DIRECTCOLOR;
|
||||
info->fix.accel = FB_ACCEL_I830;
|
||||
info->fix.type_aux = 0;
|
||||
info->fix.mmio_start = 0;
|
||||
info->fix.mmio_len = 0;
|
||||
info->fix.line_length = fb->pitch;
|
||||
info->fix.smem_start = fb->offset + dev->mode_config.fb_base;
|
||||
info->fix.smem_len = info->fix.line_length * fb->height;
|
||||
|
||||
info->flags = FBINFO_DEFAULT;
|
||||
|
||||
|
|
@ -292,11 +483,9 @@ int intelfb_probe(struct drm_device *dev, struct drm_framebuffer *fb)
|
|||
DRM_ERROR("error mapping fb: %d\n", ret);
|
||||
|
||||
info->screen_base = fb->virtual_base;
|
||||
info->screen_size = fb->bo->mem.size;
|
||||
info->screen_size = info->fix.smem_len; /* FIXME */
|
||||
info->pseudo_palette = fb->pseudo_palette;
|
||||
info->var.xres = fb->width;
|
||||
info->var.xres_virtual = fb->width;
|
||||
info->var.yres = fb->height;
|
||||
info->var.yres_virtual = fb->height;
|
||||
info->var.bits_per_pixel = fb->bits_per_pixel;
|
||||
info->var.xoffset = 0;
|
||||
|
|
@ -306,6 +495,17 @@ int intelfb_probe(struct drm_device *dev, struct drm_framebuffer *fb)
|
|||
info->var.width = -1;
|
||||
info->var.vmode = FB_VMODE_NONINTERLACED;
|
||||
|
||||
info->var.xres = mode->hdisplay;
|
||||
info->var.right_margin = mode->hsync_start - mode->hdisplay;
|
||||
info->var.hsync_len = mode->hsync_end - mode->hsync_start;
|
||||
info->var.left_margin = mode->htotal - mode->hsync_end;
|
||||
info->var.yres = mode->vdisplay;
|
||||
info->var.lower_margin = mode->vsync_start - mode->vdisplay;
|
||||
info->var.vsync_len = mode->vsync_end - mode->vsync_start;
|
||||
info->var.upper_margin = mode->vtotal - mode->vsync_end;
|
||||
info->var.pixclock = 10000000 / mode->htotal * 1000 /
|
||||
mode->vtotal * 100000 / mode->vrefresh;
|
||||
|
||||
info->pixmap.size = 64*1024;
|
||||
info->pixmap.buf_align = 8;
|
||||
info->pixmap.access_align = 32;
|
||||
|
|
@ -316,21 +516,52 @@ int intelfb_probe(struct drm_device *dev, struct drm_framebuffer *fb)
|
|||
DRM_DEBUG(" pitch is %d\n", fb->pitch);
|
||||
switch(fb->depth) {
|
||||
case 8:
|
||||
case 15:
|
||||
info->var.red.offset = 0;
|
||||
info->var.green.offset = 0;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = 8; /* 8bit DAC */
|
||||
info->var.green.length = 8;
|
||||
info->var.blue.length = 8;
|
||||
info->var.transp.offset = 0;
|
||||
info->var.transp.length = 0;
|
||||
break;
|
||||
case 15:
|
||||
info->var.red.offset = 10;
|
||||
info->var.green.offset = 5;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = info->var.green.length =
|
||||
info->var.blue.length = 5;
|
||||
info->var.transp.offset = 15;
|
||||
info->var.transp.length = 1;
|
||||
break;
|
||||
case 16:
|
||||
break;
|
||||
default:
|
||||
info->var.red.offset = 11;
|
||||
info->var.green.offset = 5;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = 5;
|
||||
info->var.green.length = 6;
|
||||
info->var.blue.length = 5;
|
||||
info->var.transp.offset = 0;
|
||||
break;
|
||||
case 24:
|
||||
info->var.red.offset = 16;
|
||||
info->var.green.offset = 8;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = info->var.green.length =
|
||||
info->var.blue.length = 8;
|
||||
info->var.transp.offset = 0;
|
||||
info->var.transp.length = 0;
|
||||
break;
|
||||
case 32:
|
||||
info->var.red.offset = 16;
|
||||
info->var.green.offset = 8;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = info->var.green.length =
|
||||
info->var.blue.length = 8;
|
||||
if (fb->depth == 32) {
|
||||
info->var.transp.offset = 24;
|
||||
info->var.transp.length = 8;
|
||||
}
|
||||
info->var.transp.offset = 24;
|
||||
info->var.transp.length = 8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -343,8 +574,9 @@ int intelfb_probe(struct drm_device *dev, struct drm_framebuffer *fb)
|
|||
}
|
||||
EXPORT_SYMBOL(intelfb_probe);
|
||||
|
||||
int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
|
||||
int intelfb_remove(struct drm_device *dev, struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_framebuffer *fb = crtc->fb;
|
||||
struct fb_info *info = fb->fbdev;
|
||||
|
||||
if (info) {
|
||||
|
|
|
|||
|
|
@ -164,6 +164,13 @@ static bool intel_lvds_mode_fixup(struct drm_output *output,
|
|||
struct intel_crtc *intel_crtc = output->crtc->driver_private;
|
||||
struct drm_output *tmp_output;
|
||||
|
||||
/* Should never happen!! */
|
||||
if (!IS_I965G(dev) && intel_crtc->pipe == 0) {
|
||||
printk(KERN_ERR "Can't support LVDS on pipe A\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Should never happen!! */
|
||||
list_for_each_entry(tmp_output, &dev->mode_config.output_list, head) {
|
||||
if (tmp_output != output && tmp_output->crtc == output->crtc) {
|
||||
printk(KERN_ERR "Can't enable LVDS and another "
|
||||
|
|
@ -172,11 +179,6 @@ static bool intel_lvds_mode_fixup(struct drm_output *output,
|
|||
}
|
||||
}
|
||||
|
||||
if (intel_crtc->pipe == 0) {
|
||||
printk(KERN_ERR "Can't support LVDS on pipe A\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have timings from the BIOS for the panel, put them in
|
||||
* to the adjusted mode. The CRTC will be set up for this mode,
|
||||
|
|
|
|||
|
|
@ -525,7 +525,6 @@ static bool intel_sdvo_get_preferred_input_timing(struct drm_output *output,
|
|||
|
||||
static int intel_sdvo_get_clock_rate_mult(struct drm_output *output)
|
||||
{
|
||||
struct intel_output *intel_output = output->driver_private;
|
||||
u8 response, status;
|
||||
|
||||
intel_sdvo_write_cmd(output, SDVO_CMD_GET_CLOCK_RATE_MULT, NULL, 0);
|
||||
|
|
@ -895,8 +894,6 @@ static enum drm_output_status intel_sdvo_detect(struct drm_output *output)
|
|||
|
||||
static int intel_sdvo_get_modes(struct drm_output *output)
|
||||
{
|
||||
struct drm_display_mode *modes;
|
||||
|
||||
/* set the bus switch and get the modes */
|
||||
intel_sdvo_set_control_bus_switch(output, SDVO_CONTROL_BUS_DDC2);
|
||||
intel_ddc_get_modes(output);
|
||||
|
|
@ -1013,26 +1010,18 @@ void intel_sdvo_init(drm_device_t *dev, int output_device)
|
|||
|
||||
memset(&sdvo_priv->active_outputs, 0, sizeof(sdvo_priv->active_outputs));
|
||||
|
||||
/* TODO, CVBS, SVID, YPRPB & SCART outputs.
|
||||
* drm_initial_config probably wants tweaking too to support the
|
||||
* above. But has fixed VGA, TMDS and LVDS checking code. That should
|
||||
* be dealt with.
|
||||
*/
|
||||
/* TODO, CVBS, SVID, YPRPB & SCART outputs. */
|
||||
if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0)
|
||||
{
|
||||
sdvo_priv->active_outputs = SDVO_OUTPUT_RGB0;
|
||||
output->subpixel_order = SubPixelHorizontalRGB;
|
||||
/* drm_initial_config wants this name, but should be RGB */
|
||||
/* Use this for now.... */
|
||||
name_prefix="VGA";
|
||||
name_prefix="RGB";
|
||||
}
|
||||
else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1)
|
||||
{
|
||||
sdvo_priv->active_outputs = SDVO_OUTPUT_RGB1;
|
||||
output->subpixel_order = SubPixelHorizontalRGB;
|
||||
/* drm_initial_config wants this name, but should be RGB */
|
||||
/* Use this for now.... */
|
||||
name_prefix="VGA";
|
||||
name_prefix="RGB";
|
||||
}
|
||||
else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -978,6 +978,11 @@ struct drm_mode_fb_cmd {
|
|||
unsigned int depth;
|
||||
};
|
||||
|
||||
struct drm_mode_mode_cmd {
|
||||
unsigned int output_id;
|
||||
unsigned int mode_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* \name Ioctls Definitions
|
||||
*/
|
||||
|
|
@ -1055,7 +1060,12 @@ struct drm_mode_fb_cmd {
|
|||
#define DRM_IOCTL_MODE_SETCRTC DRM_IOWR(0xA3, struct drm_mode_crtc)
|
||||
#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xA4, struct drm_mode_fb_cmd)
|
||||
#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xA5, unsigned int)
|
||||
#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xA6, struct drm_mode_fb_cmd)
|
||||
#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xA6, struct drm_mode_fb_cmd)
|
||||
|
||||
#define DRM_IOCTL_MODE_ADDMODE DRM_IOWR(0xA7, struct drm_mode_modeinfo)
|
||||
#define DRM_IOCTL_MODE_RMMODE DRM_IOWR(0xA8, unsigned int)
|
||||
#define DRM_IOCTL_MODE_ATTACHMODE DRM_IOWR(0xA9, struct drm_mode_mode_cmd)
|
||||
#define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xAA, struct drm_mode_mode_cmd)
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -221,6 +221,7 @@ extern void i915_emit_breadcrumb(drm_device_t *dev);
|
|||
extern void i915_dispatch_flip(drm_device_t * dev, int pipes, int sync);
|
||||
extern int i915_emit_mi_flush(drm_device_t *dev, uint32_t flush);
|
||||
extern int i915_driver_firstopen(struct drm_device *dev);
|
||||
extern int i915_dma_cleanup(drm_device_t * dev);
|
||||
|
||||
/* i915_irq.c */
|
||||
extern int i915_irq_emit(DRM_IOCTL_ARGS);
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ int i915_driver_load(drm_device_t *dev, unsigned long flags)
|
|||
|
||||
/* FIXME: need wrapper with PCI mem checks */
|
||||
ret = drm_mem_reg_ioremap(dev, &dev_priv->ring_buffer->mem,
|
||||
&dev_priv->ring.virtual_start);
|
||||
(void **) &dev_priv->ring.virtual_start);
|
||||
if (ret)
|
||||
DRM_ERROR("error mapping ring buffer: %d\n", ret);
|
||||
|
||||
|
|
@ -272,7 +272,7 @@ int i915_driver_unload(drm_device_t *dev)
|
|||
drm_mem_reg_iounmap(dev, &dev_priv->ring_buffer->mem,
|
||||
dev_priv->ring.virtual_start);
|
||||
|
||||
DRM_DEBUG("usage is %d\n", dev_priv->ring_buffer->usage);
|
||||
DRM_DEBUG("usage is %d\n", atomic_read(&dev_priv->ring_buffer->usage));
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
drm_bo_usage_deref_locked(dev_priv->ring_buffer);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue