Merge branch 'modesetting-101' of git+ssh://git.freedesktop.org/git/mesa/drm into modesetting-101

main
Jesse Barnes 2007-04-05 09:27:12 -07:00
commit 50ee722e01
10 changed files with 1224 additions and 28 deletions

View File

@ -23,9 +23,9 @@ libdrm_ladir = $(libdir)
libdrm_la_LDFLAGS = -version-number 2:3:0 -no-undefined libdrm_la_LDFLAGS = -version-number 2:3:0 -no-undefined
AM_CFLAGS = -I$(top_srcdir)/shared-core AM_CFLAGS = -I$(top_srcdir)/shared-core
libdrm_la_SOURCES = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c libdrm_la_SOURCES = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c xf86drmMode.c
libdrmincludedir = ${includedir} libdrmincludedir = ${includedir}
libdrminclude_HEADERS = xf86drm.h xf86mm.h libdrminclude_HEADERS = xf86drm.h xf86mm.h xf86drmMode.h
EXTRA_DIST = ChangeLog TODO EXTRA_DIST = ChangeLog TODO

408
libdrm/xf86drmMode.c Normal file
View File

@ -0,0 +1,408 @@
/*
* \file xf86drmMode.c
* Header for DRM modesetting interface.
*
* \author Jakob Bornecrantz <wallbraker@gmail.com>
*
* \par Acknowledgements:
* Feb 2007, Dave Airlie <airlied@linux.ie>
*/
/*
* Copyright (c) <year> <copyright holders>
*
* 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 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.
*
*/
/*
* TODO the types we are after are defined in diffrent headers on diffrent
* platforms find which headers to include to get uint32_t
*/
#include <stdint.h>
#include "xf86drmMode.h"
#include "xf86drm.h"
#include <drm.h>
/*
* Util functions
*/
void* drmAllocCpy(void *array, int count, int entry_size)
{
char *r;
int i;
if (!count || !array || !entry_size)
return 0;
if (!(r = drmMalloc(count*entry_size)))
return 0;
for (i = 0; i < count; i++)
memcpy(r+(entry_size*i), array+(entry_size*i), entry_size);
return r;
}
/**
* Generate crtc and output ids.
*
* Will generate ids starting from 1 up to count if count is greater then 0.
*/
static uint32_t* drmAllocGenerate(int count)
{
uint32_t *r;
int i;
if(0 <= count)
return 0;
if (!(r = drmMalloc(count*sizeof(*r))))
return 0;
for (i = 0; i < count; r[i] = ++i);
return 0;
}
/*
* A couple of free functions.
*/
void drmModeFreeModeInfo(struct drm_mode_modeinfo *ptr)
{
if (!ptr)
return;
drmFree(ptr);
}
void drmModeFreeResources(drmModeResPtr ptr)
{
if (!ptr)
return;
drmFree(ptr->modes);
drmFree(ptr);
}
void drmModeFreeFrameBuffer(drmModeFrameBufferPtr ptr)
{
if (!ptr)
return;
/* we might add more frees later. */
drmFree(ptr);
}
void drmModeFreeCrtc(drmModeCrtcPtr ptr)
{
if (!ptr)
return;
drmFree(ptr);
}
void drmModeFreeOutput(drmModeOutputPtr ptr)
{
if (!ptr)
return;
drmFree(ptr->modes);
drmFree(ptr);
}
/*
* ModeSetting functions.
*/
drmModeResPtr drmModeGetResources(int fd)
{
struct drm_mode_card_res res;
int i;
drmModeResPtr r = 0;
res.count_crtcs = 0;
res.count_outputs = 0;
res.count_modes = 0;
res.modes = 0;
if (ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
return 0;
if (res.count_crtcs)
res.crtc_id = drmMalloc(res.count_crtcs*sizeof(uint32_t));
if (res.count_outputs)
res.output_id = drmMalloc(res.count_outputs*sizeof(uint32_t));
if (res.count_modes)
res.modes = drmMalloc(res.count_modes*sizeof(*res.modes));
if (ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
goto err_allocs;
/*
* return
*/
if (!(r = drmMalloc(sizeof(*r))))
return 0;
r->frameBufferId = res.fb_id;
r->count_crtcs = res.count_crtcs;
r->count_outputs = res.count_outputs;
r->count_modes = res.count_modes;
/* TODO we realy should test if these allocs fails. */
r->crtcs = drmAllocCpy(res.crtc_id, res.count_crtcs, sizeof(uint32_t));
r->outputs = drmAllocCpy(res.output_id, res.count_outputs, sizeof(uint32_t));
r->modes = drmAllocCpy(res.modes, res.count_modes, sizeof(struct drm_mode_modeinfo));
drmFree(res.crtc_id);
drmFree(res.output_id);
drmFree(res.modes);
return r;
err_allocs:
drmFree(res.crtc_id);
drmFree(res.output_id);
drmFree(res.modes);
return 0;
}
#if 0
int drmModeForceProbe(int fd, uint32_t outputId)
{
/* TODO impl/keep? */
}
drmModeFrameBufferPtr drmModeGetFrameBuffer(int fd, uint32_t buf)
{
// struct drm_mode_fb_cmd info;
drmModeFrameBufferPtr r;
// if (ioctl(fd, DRM_IOCTL_MODE_GETFRAMEBUFFER, &info))
return 0;
if (!(r = drmMalloc(sizeof(*r))))
return 0;
/* TODO change to new code
r->minWidth = info.minWidth;
r->maxWidth = info.maxWidth;
r->minHeight = info.minHeight;
r->maxHeight = info.maxHeight;*/
return r;
}
uint32_t drmModeNewFrameBuffer(int fd, uint32_t width, uint32_t height,
uint8_t bpp, uint32_t pitch, drmBO *bo)
{
drm_mode_fb_cmd_t f;
f.handle = bo->handle;
f.width = width;
f.height = height;
f.pitch = pitch;
// if (ioctl(fd, DRM_IOCTL_MODE_NEWFRAMEBUFFER, &f))
return 0;
return f.bufferId;
}
int drmModeDesFrameBuffer(int fd, uint32_t bufferId)
{
// return ioctl(fd, DRM_IOCTL_MODE_DESFRAMEBUFFER, bufferId);
}
#endif
/*
* Crtc function.
*/
drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
{
struct drm_mode_crtc crtc;
drmModeCrtcPtr r;
int i = 0;
crtc.count_outputs = 0;
crtc.outputs = 0;
crtc.count_possibles = 0;
crtc.possibles = 0;
crtc.crtc_id = crtcId;
if (ioctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc))
return 0;
/*
* return
*/
if (!(r = drmMalloc(sizeof(*r))))
return 0;
r->x = crtc.x;
r->y = crtc.y;
r->mode = crtc.mode;
// r->width = crtc.width;
// r->height = crtc.height;
r->bufferId = crtc.fb_id;
r->gamma_size = crtc.gamma_size;
r->count_outputs = crtc.count_outputs;
r->count_possibles = crtc.count_possibles;
/* TODO we realy should test if these alloc & cpy fails. */
r->outputs = crtc.outputs;
r->possibles = crtc.possibles;
return r;
err_allocs:
return 0;
}
int drmModeSetCrtc(
int fd, uint32_t crtcId, uint32_t bufferId,
uint32_t x, uint32_t y, uint32_t modeId,
uint32_t *outputs, int count
)
{
struct drm_mode_crtc crtc;
crtc.count_outputs = 0;
crtc.outputs = 0;
crtc.count_possibles = 0;
crtc.possibles = 0;
crtc.x = x;
crtc.y = y;
crtc.crtc_id = crtcId;
crtc.fb_id = bufferId;
crtc.set_outputs = outputs;
crtc.count_outputs = count;
crtc.mode = modeId;
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;
drmModeOutputPtr r = 0;
out.output = output_id;
out.count_crtcs = 0;
out.crtcs = 0;
out.count_clones = 0;
out.clones = 0;
out.count_modes = 0;
out.modes = 0;
if (ioctl(fd, DRM_IOCTL_MODE_GETOUTPUT, &out))
return 0;
if (out.count_modes)
out.modes = drmMalloc(out.count_modes*sizeof(uint32_t));
if (ioctl(fd, DRM_IOCTL_MODE_GETOUTPUT, &out))
goto err_allocs;
if(!(r = drmMalloc(sizeof(*r))))
return 0;
r->connection = out.connection;
r->mmWidth = out.mm_width;
r->mmHeight = out.mm_height;
r->subpixel = out.subpixel;
r->count_crtcs = out.count_crtcs;
r->count_clones = out.count_clones;
r->count_modes = out.count_modes;
/* TODO we should test if these alloc & cpy fails. */
r->crtcs = out.crtcs;
r->clones = out.clones;
r->modes = drmAllocCpy(out.modes, out.count_modes, sizeof(uint32_t));
return r;
err_allocs:
drmFree(out.modes);
return 0;
}
#if 0
uint32_t drmModeNewMode(int fd, struct drm_mode_modeinfo *modeInfo)
{
/* TODO impl */
}
int drmModeDesMode(int fd, uint32_t modeId)
{
// return ioctl(fd, DRM_IOCTL_MODE_DESMODE, modeId);
}
int drmModeAddMode(int fd, uint32_t outputId, uint32_t modeId)
{
drm_mode_outputmode_t res;
res.outputId = outputId;
res.modeId = modeId;
// return ioctl(fd, DRM_IOCTL_MODE_ADDMODE, &res);
}
int drmModeDelMode(int fd, uint32_t outputId, uint32_t modeId)
{
drm_mode_outputmode_t res;
res.outputId = outputId;
res.modeId = modeId;
// return ioctl(fd, DRM_IOCTL_MODE_DELMODE, &res);
}
#endif

290
libdrm/xf86drmMode.h Normal file
View File

@ -0,0 +1,290 @@
/*
* \file xf86drmMode.h
* Header for DRM modesetting interface.
*
* \author Jakob Bornecrantz <wallbraker@gmail.com>
*
* \par Acknowledgements:
* Feb 2007, Dave Airlie <airlied@linux.ie>
*/
/*
* Copyright (c) <year> <copyright holders>
*
* 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 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.
*
*/
#include <drm.h>
#include "xf86mm.h"
/*
* This is the interface for modesetting for drm.
*
* 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
* 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.
*
*/
typedef struct _drmModeGammaTriple {
uint16_t r, g, b;
} drmModeGammaTriple, *drmModeGammaTriplePtr;
typedef struct _drmModeRes {
uint32_t frameBufferId;
int count_crtcs;
uint32_t *crtcs;
int count_outputs;
uint32_t *outputs;
int count_modes;
struct drm_mode_modeinfo *modes;
} drmModeRes, *drmModeResPtr;
typedef struct _drmModeFrameBuffer {
uint32_t minWidth, maxWidth;
uint32_t minHeight, maxHeight;
} drmModeFrameBuffer, *drmModeFrameBufferPtr;
typedef struct _drmModeCrtc {
unsigned int bufferId; /**< Buffer currently connected to */
uint32_t x, y; /**< Position on the frameuffer */
uint32_t width, height;
uint32_t mode; /**< Current mode used */
int count_outputs;
uint32_t outputs; /**< Outputs that are connected */
int count_possibles;
uint32_t possibles; /**< Outputs that can be connected */
int gamma_size; /**< Number of gamma stops */
} drmModeCrtc, *drmModeCrtcPtr;
typedef enum {
DRM_MODE_CONNECTED = 1,
DRM_MODE_DISCONNECTED = 2,
DRM_MODE_UNKNOWNCONNECTION = 3
} drmModeConnection;
typedef enum {
DRM_MODE_SUBPIXEL_UNKNOWN = 1,
DRM_MODE_SUBPIXEL_HORIZONTAL_RGB = 2,
DRM_MODE_SUBPIXEL_HORIZONTAL_BGR = 3,
DRM_MODE_SUBPIXEL_VERTICAL_RGB = 4,
DRM_MODE_SUBPIXEL_VERTICAL_BGR = 5,
DRM_MODE_SUBPIXEL_NONE = 6
} drmModeSubPixel;
typedef struct _drmModeOutput {
unsigned int crtc; /**< Crtc currently connected to */
drmModeConnection connection;
uint32_t mmWidth, mmHeight; /**< HxW in millimeters */
drmModeSubPixel subpixel;
int count_crtcs;
uint32_t crtcs; /**< Possible crtc to connect to */
int count_clones;
uint32_t clones; /**< Mask of clones */
int count_modes;
uint32_t *modes; /**< List of modes ids */
} 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 );
extern void drmModeFreeFrameBuffer( drmModeFrameBufferPtr ptr );
extern void drmModeFreeCrtc( drmModeCrtcPtr ptr );
extern void drmModeFreeOutput( drmModeOutputPtr ptr );
/**
* Retrives all of the resources associated with a card.
*/
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.
*/
/**
* Retrive information about framebuffer bufferId
*/
extern drmModeFrameBufferPtr drmModeGetFramebuffer(int fd,
uint32_t bufferId);
/**
* Creates a new framebuffer with an buffer object as its scanout buffer.
*/
extern uint32_t drmModeNewFrameBuffer(int fd,
uint32_t width, uint32_t height,
uint8_t bbp, uint32_t pitch, drmBO *bo);
/**
* Destroies the given framebuffer.
*/
extern int drmModeDesFrameBuffer(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.
*/
/**
* Retrive information about the ctrt crtcId
*/
extern drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId);
/**
* Set the mode on a crtc crtcId with the given mode modeId.
*/
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
*/
/**
* Retrive information about the output outputId.
*/
extern drmModeOutputPtr drmModeGetOutput(int fd,
uint32_t outputId);
/**
* Creates a new mode from the given mode info.
* Name must be unique.
*/
extern uint32_t drmModeNewMode(int fd, struct drm_mode_modeinfo *modeInfo);
/**
* Destroys a mode created with CreateMode, must be unused.
*/
extern int drmModeDesMode(int fd, uint32_t modeId);
/**
* Adds the given mode to an output.
*/
extern int drmModeAddMode(int fd, uint32_t outputId, uint32_t modeId);
/**
* Deletes a mode Added with AddOutputMode from the output,
* must be unused, by the given mode.
*/
extern int drmModeDelMode(int fd, uint32_t outputId, uint32_t modeId);

View File

@ -60,6 +60,13 @@
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
#undef DRM_IRQ_ARGS #undef DRM_IRQ_ARGS
#define DRM_IRQ_ARGS int irq, void *arg, struct pt_regs *regs #define DRM_IRQ_ARGS int irq, void *arg, struct pt_regs *regs
typedef _Bool bool;
enum {
false = 0,
true = 1
};
#endif #endif
#ifndef list_for_each_safe #ifndef list_for_each_safe

View File

@ -3,6 +3,33 @@
#include "drm.h" #include "drm.h"
#include "drm_crtc.h" #include "drm_crtc.h"
int drm_mode_idr_get(struct drm_device *dev, void *ptr)
{
int new_id = 0;
int ret;
again:
if (idr_pre_get(&dev->crtc_config.crtc_idr, GFP_KERNEL) == 0) {
DRM_ERROR("Ran out memory getting a mode number\n");
return 0;
}
spin_lock(&dev->crtc_config.config_lock);
ret = idr_get_new_above(&dev->crtc_config.crtc_idr, ptr, 1, &new_id);
if (ret == -EAGAIN) {
spin_unlock(&dev->crtc_config.config_lock);
goto again;
}
spin_unlock(&dev->crtc_config.config_lock);
return new_id;
}
void drm_mode_idr_put(struct drm_device *dev, int id)
{
idr_remove(&dev->crtc_config.crtc_idr, id);
}
struct drm_framebuffer *drm_framebuffer_create(drm_device_t *dev) struct drm_framebuffer *drm_framebuffer_create(drm_device_t *dev)
{ {
struct drm_framebuffer *fb; struct drm_framebuffer *fb;
@ -21,6 +48,7 @@ struct drm_framebuffer *drm_framebuffer_create(drm_device_t *dev)
return NULL; return NULL;
} }
fb->id = drm_mode_idr_get(dev, fb);
fb->dev = dev; fb->dev = dev;
spin_lock(&dev->crtc_config.config_lock); spin_lock(&dev->crtc_config.config_lock);
dev->crtc_config.num_fb++; dev->crtc_config.num_fb++;
@ -35,6 +63,7 @@ void drm_framebuffer_destroy(struct drm_framebuffer *fb)
drm_device_t *dev = fb->dev; drm_device_t *dev = fb->dev;
spin_lock(&dev->crtc_config.config_lock); spin_lock(&dev->crtc_config.config_lock);
drm_mode_idr_put(dev, fb->id);
list_del(&fb->head); list_del(&fb->head);
dev->crtc_config.num_fb--; dev->crtc_config.num_fb--;
spin_unlock(&dev->crtc_config.config_lock); spin_unlock(&dev->crtc_config.config_lock);
@ -45,19 +74,21 @@ void drm_framebuffer_destroy(struct drm_framebuffer *fb)
struct drm_crtc *drm_crtc_create(drm_device_t *dev, struct drm_crtc *drm_crtc_create(drm_device_t *dev,
const struct drm_crtc_funcs *funcs) const struct drm_crtc_funcs *funcs)
{ {
struct drm_crtc *crtc = NULL; struct drm_crtc *crtc;
crtc = kmalloc(sizeof(struct drm_crtc), GFP_KERNEL);
crtc = kzalloc(sizeof(struct drm_crtc), GFP_KERNEL);
if (!crtc) if (!crtc)
return NULL; return NULL;
crtc->dev = dev; crtc->dev = dev;
crtc->funcs = funcs; crtc->funcs = funcs;
spin_lock(&dev->crtc_config.config_lock); crtc->id = drm_mode_idr_get(dev, crtc);
DRM_DEBUG("crtc %p got id %d\n", crtc, crtc->id);
spin_lock(&dev->crtc_config.config_lock);
list_add_tail(&crtc->head, &dev->crtc_config.crtc_list); list_add_tail(&crtc->head, &dev->crtc_config.crtc_list);
dev->crtc_config.num_crtc++; dev->crtc_config.num_crtc++;
spin_unlock(&dev->crtc_config.config_lock); spin_unlock(&dev->crtc_config.config_lock);
return crtc; return crtc;
@ -71,7 +102,9 @@ void drm_crtc_destroy(struct drm_crtc *crtc)
if (crtc->funcs->cleanup) if (crtc->funcs->cleanup)
(*crtc->funcs->cleanup)(crtc); (*crtc->funcs->cleanup)(crtc);
spin_lock(&dev->crtc_config.config_lock); spin_lock(&dev->crtc_config.config_lock);
drm_mode_idr_put(dev, crtc->id);
list_del(&crtc->head); list_del(&crtc->head);
dev->crtc_config.num_crtc--; dev->crtc_config.num_crtc--;
spin_unlock(&dev->crtc_config.config_lock); spin_unlock(&dev->crtc_config.config_lock);
@ -154,7 +187,7 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
bool ret = false; bool ret = false;
struct drm_output *output; struct drm_output *output;
adjusted_mode = drm_mode_duplicate(mode); adjusted_mode = drm_mode_duplicate(dev, mode);
crtc->enabled = drm_crtc_in_use(crtc); crtc->enabled = drm_crtc_in_use(crtc);
@ -230,6 +263,7 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
} }
/* XXX free adjustedmode */ /* XXX free adjustedmode */
drm_crtc_mode_destroy(dev, adjusted_mode);
ret = TRUE; ret = TRUE;
/* TODO */ /* TODO */
// if (scrn->pScreen) // if (scrn->pScreen)
@ -256,6 +290,7 @@ bool drm_set_desired_modes(struct drm_device *dev)
list_for_each_entry(crtc, &dev->crtc_config.crtc_list, head) { list_for_each_entry(crtc, &dev->crtc_config.crtc_list, head) {
output = NULL; output = NULL;
DRM_DEBUG("crtc is %d\n", crtc->id);
list_for_each_entry(list_output, &dev->crtc_config.output_list, head) { list_for_each_entry(list_output, &dev->crtc_config.output_list, head) {
if (list_output->crtc == crtc) { if (list_output->crtc == crtc) {
output = list_output; output = list_output;
@ -267,10 +302,10 @@ bool drm_set_desired_modes(struct drm_device *dev)
continue; continue;
memset(&crtc->mode, 0, sizeof(crtc->mode)); memset(&crtc->mode, 0, sizeof(crtc->mode));
if (!crtc->desired_mode.crtc_hdisplay) { if (!crtc->desired_mode->crtc_hdisplay) {
} }
if (!drm_crtc_set_mode(crtc, &crtc->desired_mode, if (!drm_crtc_set_mode(crtc, crtc->desired_mode,
crtc->desired_x, crtc->desired_y)) crtc->desired_x, crtc->desired_y))
return false; return false;
} }
@ -344,6 +379,7 @@ struct drm_output *drm_output_create(drm_device_t *dev,
output->dev = dev; output->dev = dev;
output->funcs = funcs; output->funcs = funcs;
output->id = drm_mode_idr_get(dev, output);
if (name) if (name)
strncpy(output->name, name, DRM_OUTPUT_LEN); strncpy(output->name, name, DRM_OUTPUT_LEN);
output->name[DRM_OUTPUT_LEN - 1] = 0; output->name[DRM_OUTPUT_LEN - 1] = 0;
@ -381,6 +417,7 @@ void drm_output_destroy(struct drm_output *output)
drm_mode_remove(output, mode); drm_mode_remove(output, mode);
spin_lock(&dev->crtc_config.config_lock); spin_lock(&dev->crtc_config.config_lock);
drm_mode_idr_put(dev, output->id);
list_del(&output->head); list_del(&output->head);
spin_unlock(&dev->crtc_config.config_lock); spin_unlock(&dev->crtc_config.config_lock);
kfree(output); kfree(output);
@ -401,12 +438,33 @@ bool drm_output_rename(struct drm_output *output, const char *name)
} }
EXPORT_SYMBOL(drm_output_rename); EXPORT_SYMBOL(drm_output_rename);
struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev)
{
int ret;
struct drm_display_mode *nmode;
nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL);
if (!nmode)
return NULL;
nmode->mode_id = drm_mode_idr_get(dev, nmode);
return nmode;
}
void drm_crtc_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode)
{
drm_mode_idr_put(dev, mode->mode_id);
kfree(mode);
}
void drm_crtc_config_init(drm_device_t *dev) void drm_crtc_config_init(drm_device_t *dev)
{ {
spin_lock_init(&dev->crtc_config.config_lock); spin_lock_init(&dev->crtc_config.config_lock);
INIT_LIST_HEAD(&dev->crtc_config.fb_list); INIT_LIST_HEAD(&dev->crtc_config.fb_list);
INIT_LIST_HEAD(&dev->crtc_config.crtc_list); INIT_LIST_HEAD(&dev->crtc_config.crtc_list);
INIT_LIST_HEAD(&dev->crtc_config.output_list); INIT_LIST_HEAD(&dev->crtc_config.output_list);
idr_init(&dev->crtc_config.crtc_idr);
} }
EXPORT_SYMBOL(drm_crtc_config_init); EXPORT_SYMBOL(drm_crtc_config_init);
@ -441,7 +499,7 @@ void drm_framebuffer_set_object(drm_device_t *dev, unsigned long handle)
ret = 0; ret = 0;
out_err: out_err:
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return ret; return;
} }
EXPORT_SYMBOL(drm_framebuffer_set_object); EXPORT_SYMBOL(drm_framebuffer_set_object);
@ -465,6 +523,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow)
/* bind both CRTCs to this fb */ /* bind both CRTCs to this fb */
/* only initialise one crtc to enabled state */ /* only initialise one crtc to enabled state */
list_for_each_entry(crtc, &dev->crtc_config.crtc_list, head) { list_for_each_entry(crtc, &dev->crtc_config.crtc_list, head) {
DRM_DEBUG("crtc is %d\n", crtc->id);
crtc->fb = fb; crtc->fb = fb;
if (!vga_crtc) { if (!vga_crtc) {
vga_crtc = crtc; vga_crtc = crtc;
@ -497,7 +556,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow)
break; break;
DRM_DEBUG("Setting desired mode for output %s\n", output->name); DRM_DEBUG("Setting desired mode for output %s\n", output->name);
drm_mode_debug_printmodeline(dev, des_mode); drm_mode_debug_printmodeline(dev, des_mode);
output->crtc->desired_mode = *des_mode; output->crtc->desired_mode = des_mode;
output->initial_x = 0; output->initial_x = 0;
output->initial_y = 0; output->initial_y = 0;
use_output = output; use_output = output;
@ -509,7 +568,7 @@ bool drm_initial_config(drm_device_t *dev, bool can_grow)
break; break;
DRM_DEBUG("Setting desired mode for output %s\n", output->name); DRM_DEBUG("Setting desired mode for output %s\n", output->name);
drm_mode_debug_printmodeline(dev, des_mode); drm_mode_debug_printmodeline(dev, des_mode);
output->crtc->desired_mode = *des_mode; output->crtc->desired_mode = des_mode;
#endif #endif
output->initial_x = 0; output->initial_x = 0;
output->initial_y = 0; output->initial_y = 0;
@ -531,10 +590,331 @@ void drm_crtc_config_cleanup(drm_device_t *dev)
drm_output_destroy(output); drm_output_destroy(output);
} }
list_for_each_entry_safe(crtc, ct, &dev->crtc_config.crtc_list, head) { list_for_each_entry_safe(crtc, ct, &dev->crtc_config.crtc_list, head) {
drm_crtc_destroy(crtc); drm_crtc_destroy(crtc);
} }
} }
EXPORT_SYMBOL(drm_crtc_config_cleanup); EXPORT_SYMBOL(drm_crtc_config_cleanup);
int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, struct drm_display_mode *new_mode, struct drm_output **output_set)
{
drm_device_t *dev = crtc->dev;
struct drm_crtc **save_crtcs, *new_crtc;
bool save_enabled = crtc->enabled;
bool changed;
struct drm_output *output;
int count = 0, ro;
save_crtcs = kzalloc(dev->crtc_config.num_crtc * sizeof(struct drm_crtc *), GFP_KERNEL);
if (!save_crtcs)
return -ENOMEM;
if (crtc_info->x != crtc->x || crtc_info->y != crtc->y)
changed = true;
if (crtc->mode.mode_id != new_mode->mode_id)
changed = true;
list_for_each_entry(output, &dev->crtc_config.output_list, head) {
save_crtcs[count++] = output->crtc;
if (output->crtc == crtc)
new_crtc = NULL;
else
new_crtc = output->crtc;
for (ro = 0; ro < crtc_info->count_outputs; ro++)
{
if (output_set[ro] == output)
new_crtc = crtc;
}
if (new_crtc != output->crtc) {
changed = true;
output->crtc = new_crtc;
}
}
if (changed) {
crtc->enabled = new_mode != NULL;
if (new_mode) {
DRM_DEBUG("attempting to set mode from userspace\n");
drm_mode_debug_printmodeline(dev, new_mode);
if (!drm_crtc_set_mode(crtc, new_mode, crtc_info->x,
crtc_info->y)) {
crtc->enabled = save_enabled;
count = 0;
list_for_each_entry(output, &dev->crtc_config.output_list, head)
output->crtc = save_crtcs[count++];
kfree(save_crtcs);
return -EINVAL;
}
crtc->desired_x = crtc_info->x;
crtc->desired_y = crtc_info->y;
crtc->desired_mode = new_mode;
}
drm_disable_unused_functions(dev);
}
kfree(save_crtcs);
return 0;
}
void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, struct drm_display_mode *in)
{
out->id = in->mode_id;
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->flags = in->flags;
strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
}
/* IOCTL code from userspace */
int drm_mode_getresources(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_card_res __user *argp = (void __user *)arg;
struct drm_mode_card_res card_res;
struct list_head *lh;
struct drm_output *output;
struct drm_crtc *crtc;
struct drm_mode_modeinfo u_mode;
struct drm_display_mode *mode;
int retcode = 0;
int mode_count= 0;
int output_count = 0;
int crtc_count = 0;
int copied = 0;
memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
list_for_each(lh, &dev->crtc_config.crtc_list)
crtc_count++;
list_for_each_entry(output, &dev->crtc_config.output_list,
head)
{
output_count++;
list_for_each(lh, &output->modes)
mode_count++;
}
if (copy_from_user(&card_res, argp, sizeof(card_res)))
return -EFAULT;
/* handle this in 3 parts */
/* CRTCs */
if (card_res.count_crtcs >= crtc_count) {
copied = 0;
list_for_each_entry(crtc, &dev->crtc_config.crtc_list, head){
DRM_DEBUG("CRTC ID is %d\n", crtc->id);
if (put_user(crtc->id, &card_res.crtc_id[copied++])) {
retcode = -EFAULT;
goto done;
}
}
}
card_res.count_crtcs = crtc_count;
/* Outputs */
if (card_res.count_outputs >= output_count) {
copied = 0;
list_for_each_entry(output, &dev->crtc_config.output_list,
head) {
DRM_DEBUG("OUTPUT ID is %d\n", output->id);
if (put_user(output->id, &card_res.output_id[copied++])) {
retcode = -EFAULT;
goto done;
}
}
}
card_res.count_outputs = output_count;
/* Modes */
if (card_res.count_modes >= mode_count) {
copied = 0;
list_for_each_entry(output, &dev->crtc_config.output_list,
head) {
list_for_each_entry(mode, &output->modes, 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;
done:
DRM_DEBUG("Counted %d %d %d\n", card_res.count_crtcs,
card_res.count_outputs,
card_res.count_modes);
if (copy_to_user(argp, &card_res, sizeof(card_res)))
return -EFAULT;
return retcode;
}
int drm_mode_getcrtc(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_crtc __user *argp = (void __user *)arg;
struct drm_mode_crtc crtc_resp;
struct drm_crtc *crtc;
struct drm_output *output;
int ocount;
int retcode = 0;
if (copy_from_user(&crtc_resp, argp, sizeof(crtc_resp)))
return -EFAULT;
crtc = idr_find(&dev->crtc_config.crtc_idr, crtc_resp.crtc_id);
if (!crtc || (crtc->id != crtc_resp.crtc_id))
return -EINVAL;
crtc_resp.x = crtc->x;
crtc_resp.y = crtc->y;
crtc_resp.fb_id = 1;
crtc_resp.outputs = 0;
if (crtc->enabled) {
crtc_resp.mode = crtc->mode.mode_id;
ocount = 0;
list_for_each_entry(output, &dev->crtc_config.output_list, head) {
if (output->crtc == crtc)
crtc_resp.outputs |= 1 << (ocount++);
}
} else {
crtc_resp.mode = 0;
}
if (copy_to_user(argp, &crtc_resp, sizeof(crtc_resp)))
return -EFAULT;
return retcode;
}
int drm_mode_getoutput(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_get_output __user *argp = (void __user *)arg;
struct drm_mode_get_output out_resp;
struct drm_output *output;
struct drm_display_mode *mode;
int mode_count = 0;
int retcode = 0;
int copied = 0;
if (copy_from_user(&out_resp, argp, sizeof(out_resp)))
return -EFAULT;
output= idr_find(&dev->crtc_config.crtc_idr, out_resp.output);
if (!output || (output->id != out_resp.output))
return -EINVAL;
list_for_each_entry(mode, &output->modes, head)
mode_count++;
out_resp.mm_width = output->mm_width;
out_resp.mm_height = output->mm_height;
out_resp.subpixel = output->subpixel_order;
out_resp.connection = output->status;
if (output->crtc)
out_resp.crtc = output->crtc->id;
else
out_resp.crtc = 0;
if (out_resp.count_modes >= mode_count) {
copied = 0;
list_for_each_entry(mode, &output->modes, head) {
if (put_user(mode->mode_id, &out_resp.modes[copied++])) {
retcode = -EFAULT;
goto done;
}
}
}
out_resp.count_modes = mode_count;
done:
if (copy_to_user(argp, &out_resp, sizeof(out_resp)))
return -EFAULT;
return retcode;
}
int drm_mode_setcrtc(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_crtc __user *argp = (void __user *)arg;
struct drm_mode_crtc crtc_req;
struct drm_crtc *crtc;
struct drm_output **output_set = NULL, *output;
struct drm_display_mode *mode;
int retcode = 0;
int i;
if (copy_from_user(&crtc_req, argp, sizeof(crtc_req)))
return -EFAULT;
crtc = idr_find(&dev->crtc_config.crtc_idr, crtc_req.crtc_id);
if (!crtc || (crtc->id != crtc_req.crtc_id))
return -EINVAL;
if (crtc_req.mode) {
mode = idr_find(&dev->crtc_config.crtc_idr, crtc_req.mode);
if (!mode || (mode->mode_id != crtc_req.mode))
return -EINVAL;
} else
mode = NULL;
if (crtc_req.count_outputs == 0 && mode)
return -EINVAL;
if (crtc_req.count_outputs > 0 && !mode)
return -EINVAL;
if (crtc_req.count_outputs > 0) {
u32 out_id;
output_set = kmalloc(crtc_req.count_outputs * sizeof(struct drm_output *), GFP_KERNEL);
if (!output_set)
return -ENOMEM;
for (i = 0; i < crtc_req.count_outputs; i++)
{
if (get_user(out_id, &crtc_req.set_outputs[i]))
return -EFAULT;
output = idr_find(&dev->crtc_config.crtc_idr, out_id);
if (!output || (out_id != output->id))
return -EINVAL;
output_set[i] = output;
}
}
retcode = drm_crtc_set_config(crtc, &crtc_req, mode, output_set);
return retcode;
}

View File

@ -9,6 +9,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/idr.h>
#include "drmP.h" #include "drmP.h"
#include "drm.h" #include "drm.h"
@ -73,8 +74,6 @@ enum drm_mode_status {
#define DRM_MODE_TYPE_CLOCK_CRTC_C (DRM_MODE_TYPE_CLOCK_C | \ #define DRM_MODE_TYPE_CLOCK_CRTC_C (DRM_MODE_TYPE_CLOCK_C | \
DRM_MODE_TYPE_CRTC_C) DRM_MODE_TYPE_CRTC_C)
#define DRM_DISPLAY_MODE_LEN 32
#define DRM_MODE(nm, t, c, hd, hss, hse, ht, hsk, vd, vss, vse, vt, vs, f) \ #define DRM_MODE(nm, t, c, hd, hss, hse, ht, hsk, vd, vss, vse, vt, vs, f) \
.name = nm, .status = 0, .type = (t), .clock = (c), \ .name = nm, .status = 0, .type = (t), .clock = (c), \
.hdisplay = (hd), .hsync_start = (hss), .hsync_end = (hse), \ .hdisplay = (hd), .hsync_start = (hss), .hsync_end = (hse), \
@ -86,6 +85,7 @@ struct drm_display_mode {
/* Header */ /* Header */
struct list_head head; struct list_head head;
char name[DRM_DISPLAY_MODE_LEN]; char name[DRM_DISPLAY_MODE_LEN];
int mode_id;
enum drm_mode_status status; enum drm_mode_status status;
int type; int type;
@ -171,6 +171,7 @@ enum subpixel_order {
struct drm_framebuffer { struct drm_framebuffer {
struct drm_device *dev; struct drm_device *dev;
struct list_head head; struct list_head head;
int id; /* idr assigned */
unsigned int pitch; unsigned int pitch;
unsigned long offset; unsigned long offset;
unsigned int width; unsigned int width;
@ -257,6 +258,8 @@ struct drm_crtc {
struct drm_device *dev; struct drm_device *dev;
struct list_head head; struct list_head head;
int id; /* idr assigned */
/* framebuffer the CRTC is currently bound to */ /* framebuffer the CRTC is currently bound to */
struct drm_framebuffer *fb; struct drm_framebuffer *fb;
@ -269,7 +272,7 @@ struct drm_crtc {
struct drm_display_mode mode; struct drm_display_mode mode;
int x, y; int x, y;
struct drm_display_mode desired_mode; struct drm_display_mode *desired_mode;
int desired_x, desired_y; int desired_x, desired_y;
const struct drm_crtc_funcs *funcs; const struct drm_crtc_funcs *funcs;
void *driver_private; void *driver_private;
@ -348,6 +351,7 @@ struct drm_output {
struct drm_device *dev; struct drm_device *dev;
struct list_head head; struct list_head head;
struct drm_crtc *crtc; struct drm_crtc *crtc;
int id; /* idr assigned */
unsigned long possible_crtcs; unsigned long possible_crtcs;
unsigned long possible_clones; unsigned long possible_clones;
bool interlace_allowed; bool interlace_allowed;
@ -392,6 +396,7 @@ struct drm_crtc_config_funcs {
*/ */
struct drm_crtc_config { struct drm_crtc_config {
spinlock_t config_lock; spinlock_t config_lock;
struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, output, modes - just makes life easier */
/* this is limited to one for now */ /* this is limited to one for now */
int num_fb; int num_fb;
struct list_head fb_list; struct list_head fb_list;
@ -419,10 +424,26 @@ int drm_add_edid_modes(struct drm_output *output,
struct i2c_adapter *adapter); struct i2c_adapter *adapter);
void drm_mode_probed_add(struct drm_output *output, struct drm_display_mode *mode); void drm_mode_probed_add(struct drm_output *output, struct drm_display_mode *mode);
void drm_mode_remove(struct drm_output *output, struct drm_display_mode *mode); void drm_mode_remove(struct drm_output *output, struct drm_display_mode *mode);
extern struct drm_display_mode *drm_mode_duplicate(struct drm_display_mode *mode); extern struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
struct drm_display_mode *mode);
extern void drm_mode_debug_printmodeline(struct drm_device *dev, extern void drm_mode_debug_printmodeline(struct drm_device *dev,
struct drm_display_mode *mode); struct drm_display_mode *mode);
extern void drm_crtc_config_init(struct drm_device *dev); extern void drm_crtc_config_init(struct drm_device *dev);
extern void drm_crtc_config_cleanup(struct drm_device *dev); extern void drm_crtc_config_cleanup(struct drm_device *dev);
extern void drm_disable_unused_functions(struct drm_device *dev); extern void drm_disable_unused_functions(struct drm_device *dev);
extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev);
extern void drm_crtc_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode);
/* IOCTLs */
extern int drm_mode_getresources(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int drm_mode_getcrtc(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int drm_mode_getoutput(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int drm_mode_setcrtc(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
#endif /* __DRM_CRTC_H__ */ #endif /* __DRM_CRTC_H__ */

View File

@ -123,6 +123,10 @@ static drm_ioctl_desc_t drm_ioctls[] = {
DRM_AUTH }, DRM_AUTH },
[DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = {drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = {drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_MODE_GETRESOURCES)] = {drm_mode_getresources, DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_MODE_GETCRTC)] = {drm_mode_getcrtc, DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_MODE_GETOUTPUT)] = {drm_mode_getoutput, DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_MODE_SETCRTC)] = {drm_mode_setcrtc, DRM_MASTER|DRM_ROOT_ONLY},
}; };
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )

View File

@ -217,7 +217,8 @@ bad:
* *
* Punts for now. * Punts for now.
*/ */
struct drm_display_mode *drm_mode_std(struct std_timing *t) struct drm_display_mode *drm_mode_std(struct drm_device *dev,
struct std_timing *t)
{ {
// struct fb_videomode mode; // struct fb_videomode mode;
@ -226,7 +227,7 @@ struct drm_display_mode *drm_mode_std(struct std_timing *t)
struct drm_display_mode *mode; struct drm_display_mode *mode;
int hsize = t->hsize * 8 + 248, vsize; int hsize = t->hsize * 8 + 248, vsize;
mode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL); mode = drm_crtc_mode_create(dev);
if (!mode) if (!mode)
return NULL; return NULL;
@ -244,7 +245,8 @@ struct drm_display_mode *drm_mode_std(struct std_timing *t)
return mode; return mode;
} }
struct drm_display_mode *drm_mode_detailed(struct detailed_timing *timing, struct drm_display_mode *drm_mode_detailed(drm_device_t *dev,
struct detailed_timing *timing,
bool preferred) bool preferred)
{ {
struct drm_display_mode *mode; struct drm_display_mode *mode;
@ -259,7 +261,7 @@ struct drm_display_mode *drm_mode_detailed(struct detailed_timing *timing,
return NULL; return NULL;
} }
mode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL); mode = drm_crtc_mode_create(dev);
if (!mode) if (!mode)
return NULL; return NULL;
@ -362,6 +364,7 @@ static struct drm_display_mode established_modes[] = {
*/ */
static int add_established_modes(struct drm_output *output, struct edid *edid) static int add_established_modes(struct drm_output *output, struct edid *edid)
{ {
struct drm_device *dev = output->dev;
unsigned long est_bits = edid->established_timings.t1 | unsigned long est_bits = edid->established_timings.t1 |
(edid->established_timings.t2 << 8) | (edid->established_timings.t2 << 8) |
((edid->established_timings.mfg_rsvd & 0x80) << 9); ((edid->established_timings.mfg_rsvd & 0x80) << 9);
@ -370,7 +373,7 @@ static int add_established_modes(struct drm_output *output, struct edid *edid)
for (i = 0; i <= EDID_EST_TIMINGS; i++) for (i = 0; i <= EDID_EST_TIMINGS; i++)
if (est_bits & (1<<i)) { if (est_bits & (1<<i)) {
drm_mode_probed_add(output, drm_mode_probed_add(output,
drm_mode_duplicate(&established_modes[i])); drm_mode_duplicate(dev, &established_modes[i]));
modes++; modes++;
} }
@ -387,6 +390,7 @@ static int add_established_modes(struct drm_output *output, struct edid *edid)
static int add_standard_modes(struct drm_output *output, struct edid *edid) static int add_standard_modes(struct drm_output *output, struct edid *edid)
{ {
int i, modes = 0; int i, modes = 0;
struct drm_device *dev = output->dev;
for (i = 0; i < EDID_STD_TIMINGS; i++) { for (i = 0; i < EDID_STD_TIMINGS; i++) {
struct std_timing *t = &edid->standard_timings[i]; struct std_timing *t = &edid->standard_timings[i];
@ -396,7 +400,7 @@ static int add_standard_modes(struct drm_output *output, struct edid *edid)
continue; continue;
drm_mode_probed_add(output, drm_mode_probed_add(output,
drm_mode_std(&edid->standard_timings[i])); drm_mode_std(dev, &edid->standard_timings[i]));
modes++; modes++;
} }
@ -414,6 +418,7 @@ static int add_detailed_info(struct drm_output *output, struct edid *edid)
{ {
int i, j, modes = 0; int i, j, modes = 0;
bool preferred = 0; bool preferred = 0;
struct drm_device *dev = output->dev;
for (i = 0; i < EDID_DETAILED_TIMINGS; i++) { for (i = 0; i < EDID_DETAILED_TIMINGS; i++) {
struct detailed_timing *timing = &edid->detailed_timings[i]; struct detailed_timing *timing = &edid->detailed_timings[i];
@ -428,7 +433,7 @@ static int add_detailed_info(struct drm_output *output, struct edid *edid)
if (i == 0 && edid->preferred_timing) if (i == 0 && edid->preferred_timing)
preferred = 1; preferred = 1;
drm_mode_probed_add(output, drm_mode_probed_add(output,
drm_mode_detailed(timing, preferred)); drm_mode_detailed(dev, timing, preferred));
modes++; modes++;
continue; continue;
} }
@ -451,7 +456,7 @@ static int add_detailed_info(struct drm_output *output, struct edid *edid)
struct std_timing *std; struct std_timing *std;
std = &data->data.timings[j]; std = &data->data.timings[j];
drm_mode_probed_add(output, drm_mode_std(std)); drm_mode_probed_add(output, drm_mode_std(dev, std));
modes++; modes++;
} }
break; break;

View File

@ -115,15 +115,18 @@ void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)
EXPORT_SYMBOL(drm_mode_set_crtcinfo); EXPORT_SYMBOL(drm_mode_set_crtcinfo);
struct drm_display_mode *drm_mode_duplicate(struct drm_display_mode *mode) struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, struct drm_display_mode *mode)
{ {
struct drm_display_mode *nmode; struct drm_display_mode *nmode;
int new_id;
nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL); nmode = drm_crtc_mode_create(dev);
if (!nmode) if (!nmode)
return NULL; return NULL;
new_id = nmode->mode_id;
*nmode = *mode; *nmode = *mode;
nmode->mode_id = new_id;
INIT_LIST_HEAD(&nmode->head); INIT_LIST_HEAD(&nmode->head);
return nmode; return nmode;
} }

View File

@ -888,6 +888,80 @@ typedef union drm_mm_init_arg{
} rep; } rep;
} drm_mm_init_arg_t; } drm_mm_init_arg_t;
/*
* Drm mode setting
*/
#define DRM_DISPLAY_MODE_LEN 32
struct drm_mode_modeinfo {
unsigned int id;
unsigned int clock;
unsigned short hdisplay, hsync_start, hsync_end, htotal, hskew;
unsigned short vdisplay, vsync_start, vsync_end, vtotal, vscan;
unsigned int flags;
char name[DRM_DISPLAY_MODE_LEN];
};
struct drm_mode_card_res {
unsigned int fb_id;
int count_crtcs;
unsigned int __user *crtc_id;
int count_outputs;
unsigned int __user *output_id;
int count_modes;
struct drm_mode_modeinfo __user *modes;
};
struct drm_mode_crtc {
unsigned int crtc_id; /**< Id */
unsigned int fb_id; /**< Id of framebuffer */
int x, y; /**< Position on the frameuffer */
unsigned int mode; /**< Current mode used */
int count_outputs;
unsigned int outputs; /**< Outputs that are connected */
int count_possibles;
unsigned int possibles; /**< Outputs that can be connected */
unsigned int __user *set_outputs; /**< Outputs to be connected */
int gamma_size;
};
struct drm_mode_get_output {
unsigned int output; /**< Id */
unsigned int crtc; /**< Id of crtc */
unsigned int connection;
unsigned int mm_width, mm_height; /**< HxW in millimeters */
unsigned int subpixel;
int count_crtcs;
unsigned int crtcs; /**< possible crtc to connect to */
int count_clones;
unsigned int clones; /**< list of clones */
int count_modes;
unsigned int __user *modes; /**< list of modes it supports */
};
/** /**
* \name Ioctls Definitions * \name Ioctls Definitions
*/ */
@ -959,6 +1033,10 @@ typedef union drm_mm_init_arg{
#define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, drm_update_draw_t) #define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, drm_update_draw_t)
#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res)
#define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc)
#define DRM_IOCTL_MODE_GETOUTPUT DRM_IOWR(0xA2, struct drm_mode_get_output)
#define DRM_IOCTL_MODE_SETCRTC DRM_IOWR(0xA3, struct drm_mode_crtc)
/*@}*/ /*@}*/
/** /**