mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2026-05-05 06:38:03 +02:00
Merge remote branch 'origin/modesetting-101' into modesetting-101
This commit is contained in:
commit
9420ab4b41
30 changed files with 8288 additions and 85 deletions
|
|
@ -23,9 +23,9 @@ libdrm_ladir = $(libdir)
|
|||
libdrm_la_LDFLAGS = -version-number 2:3:0 -no-undefined
|
||||
|
||||
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}
|
||||
libdrminclude_HEADERS = xf86drm.h xf86mm.h
|
||||
libdrminclude_HEADERS = xf86drm.h xf86mm.h xf86drmMode.h
|
||||
|
||||
EXTRA_DIST = ChangeLog TODO
|
||||
|
|
|
|||
412
libdrm/xf86drmMode.c
Normal file
412
libdrm/xf86drmMode.c
Normal file
|
|
@ -0,0 +1,412 @@
|
|||
/*
|
||||
* \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>
|
||||
#include <string.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 drmModeFreeFB(drmModeFBPtr 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;
|
||||
|
||||
memset(&res, 0, sizeof(struct drm_mode_card_res));
|
||||
|
||||
if (ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
|
||||
return 0;
|
||||
|
||||
if (res.count_fbs)
|
||||
res.fb_id = drmMalloc(res.count_fbs*sizeof(uint32_t));
|
||||
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)) {
|
||||
r = NULL;
|
||||
goto err_allocs;
|
||||
}
|
||||
|
||||
/*
|
||||
* return
|
||||
*/
|
||||
|
||||
|
||||
if (!(r = drmMalloc(sizeof(*r))))
|
||||
return 0;
|
||||
|
||||
r->count_fbs = res.count_fbs;
|
||||
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->fbs = drmAllocCpy(res.fb_id, res.count_fbs, sizeof(uint32_t));
|
||||
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));
|
||||
|
||||
err_allocs:
|
||||
drmFree(res.fb_id);
|
||||
drmFree(res.crtc_id);
|
||||
drmFree(res.output_id);
|
||||
drmFree(res.modes);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
|
||||
uint8_t bpp, uint32_t pitch, drmBO *bo, uint32_t *buf_id)
|
||||
{
|
||||
struct drm_mode_fb_cmd f;
|
||||
int ret;
|
||||
|
||||
f.width = width;
|
||||
f.height = height;
|
||||
f.pitch = pitch;
|
||||
f.bpp = bpp;
|
||||
f.depth = depth;
|
||||
f.handle = bo->handle;
|
||||
|
||||
if (ret = ioctl(fd, DRM_IOCTL_MODE_ADDFB, &f))
|
||||
return ret;
|
||||
|
||||
*buf_id = f.buffer_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drmModeRmFB(int fd, uint32_t bufferId)
|
||||
{
|
||||
return ioctl(fd, DRM_IOCTL_MODE_RMFB, bufferId);
|
||||
}
|
||||
|
||||
drmModeFBPtr drmModeGetFB(int fd, uint32_t buf)
|
||||
{
|
||||
struct drm_mode_fb_cmd info;
|
||||
drmModeFBPtr r;
|
||||
|
||||
info.buffer_id = buf;
|
||||
|
||||
if (ioctl(fd, DRM_IOCTL_MODE_GETFB, &info))
|
||||
return NULL;
|
||||
|
||||
if (!(r = drmMalloc(sizeof(*r))))
|
||||
return NULL;
|
||||
|
||||
r->buffer_id = info.buffer_id;
|
||||
r->width = info.width;
|
||||
r->height = info.height;
|
||||
r->pitch = info.pitch;
|
||||
r->bpp = info.bpp;
|
||||
r->handle = info.handle;
|
||||
r->depth = info.depth;
|
||||
|
||||
return r;
|
||||
}
|
||||
#if 0
|
||||
int drmModeForceProbe(int fd, uint32_t outputId)
|
||||
{
|
||||
/* TODO impl/keep? */
|
||||
}
|
||||
|
||||
#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->buffer_id = 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));
|
||||
strncpy(r->name, out.name, DRM_OUTPUT_NAME_LEN);
|
||||
r->name[DRM_OUTPUT_NAME_LEN-1] = 0;
|
||||
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
|
||||
|
||||
284
libdrm/xf86drmMode.h
Normal file
284
libdrm/xf86drmMode.h
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
/*
|
||||
* \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 {
|
||||
|
||||
int count_fbs;
|
||||
uint32_t *fbs;
|
||||
|
||||
int count_crtcs;
|
||||
uint32_t *crtcs;
|
||||
|
||||
int count_outputs;
|
||||
uint32_t *outputs;
|
||||
|
||||
int count_modes;
|
||||
struct drm_mode_modeinfo *modes;
|
||||
|
||||
} drmModeRes, *drmModeResPtr;
|
||||
|
||||
typedef struct drm_mode_fb_cmd drmModeFB, *drmModeFBPtr;
|
||||
|
||||
typedef struct _drmModeCrtc {
|
||||
|
||||
unsigned int buffer_id; /**< FB id to connect to 0 = disconnect*/
|
||||
|
||||
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 */
|
||||
unsigned char name[DRM_OUTPUT_NAME_LEN];
|
||||
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 drmModeFreeFB( drmModeFBPtr 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 drmModeFBPtr drmModeGetFB(int fd, uint32_t bufferId);
|
||||
|
||||
/**
|
||||
* Creates a new framebuffer with an buffer object as its scanout buffer.
|
||||
*/
|
||||
extern int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
|
||||
uint8_t bpp, uint32_t pitch, drmBO *bo,
|
||||
uint32_t *buf_id);
|
||||
/**
|
||||
* Destroies the given framebuffer.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
|
|
@ -13,13 +13,15 @@ drm-objs := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \
|
|||
drm_sysfs.o drm_pci.o drm_agpsupport.o drm_scatter.o \
|
||||
drm_memory_debug.o ati_pcigart.o drm_sman.o \
|
||||
drm_hashtab.o drm_mm.o drm_object.o drm_compat.o \
|
||||
drm_fence.o drm_ttm.o drm_bo.o drm_bo_move.o
|
||||
drm_fence.o drm_ttm.o drm_bo.o drm_bo_move.o drm_crtc.o \
|
||||
drm_edid.o drm_modes.o drm_fb.o
|
||||
tdfx-objs := tdfx_drv.o
|
||||
r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o
|
||||
mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
|
||||
i810-objs := i810_drv.o i810_dma.o
|
||||
i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \
|
||||
i915_buffer.o
|
||||
i915_buffer.o intel_display.o intel_crt.o intel_lvds.o \
|
||||
intel_sdvo.o intel_modes.o intel_i2c.o i915_init.o
|
||||
nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \
|
||||
nouveau_object.o nouveau_irq.o \
|
||||
nv04_timer.o \
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@
|
|||
#include <linux/poll.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include "drm.h"
|
||||
#include "drm_crtc.h"
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define __OS_HAS_AGP (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE)))
|
||||
|
|
@ -164,6 +165,8 @@
|
|||
|
||||
#include "drm_compat.h"
|
||||
|
||||
#include "drm_crtc.h"
|
||||
|
||||
/***********************************************************************/
|
||||
/** \name Macros to make printk easier */
|
||||
/*@{*/
|
||||
|
|
@ -831,6 +834,9 @@ typedef struct drm_device {
|
|||
unsigned int drw_info_length;
|
||||
drm_drawable_info_t **drw_info;
|
||||
/*@} */
|
||||
|
||||
/* DRM mode setting */
|
||||
struct drm_mode_config mode_config;
|
||||
} drm_device_t;
|
||||
|
||||
#if __OS_HAS_AGP
|
||||
|
|
|
|||
|
|
@ -89,6 +89,9 @@ static int drm_bo_vm_pre_move(drm_buffer_object_t * bo, int old_is_pci)
|
|||
#ifdef DRM_ODD_MM_COMPAT
|
||||
int ret;
|
||||
|
||||
if (!bo->map_list.map)
|
||||
return 0;
|
||||
|
||||
ret = drm_bo_lock_kmm(bo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -96,6 +99,9 @@ static int drm_bo_vm_pre_move(drm_buffer_object_t * bo, int old_is_pci)
|
|||
if (old_is_pci)
|
||||
drm_bo_finish_unmap(bo);
|
||||
#else
|
||||
if (!bo->map_list.map)
|
||||
return 0;
|
||||
|
||||
drm_bo_unmap_virtual(bo);
|
||||
#endif
|
||||
return 0;
|
||||
|
|
@ -106,6 +112,9 @@ static void drm_bo_vm_post_move(drm_buffer_object_t * bo)
|
|||
#ifdef DRM_ODD_MM_COMPAT
|
||||
int ret;
|
||||
|
||||
if (!bo->map_list.map)
|
||||
return;
|
||||
|
||||
ret = drm_bo_remap_bound(bo);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to remap a bound buffer object.\n"
|
||||
|
|
@ -131,6 +140,11 @@ static int drm_bo_add_ttm(drm_buffer_object_t * bo)
|
|||
if (!bo->ttm)
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
case drm_bo_type_kernel:
|
||||
bo->ttm = drm_ttm_init(dev, bo->mem.num_pages << PAGE_SHIFT);
|
||||
if (!bo->ttm)
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
case drm_bo_type_user:
|
||||
case drm_bo_type_fake:
|
||||
break;
|
||||
|
|
@ -1530,7 +1544,7 @@ static int drm_bo_handle_wait(drm_file_t * priv, uint32_t handle,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int drm_buffer_object_create(drm_file_t * priv,
|
||||
int drm_buffer_object_create(drm_device_t *dev,
|
||||
unsigned long size,
|
||||
drm_bo_type_t type,
|
||||
uint32_t mask,
|
||||
|
|
@ -1539,7 +1553,6 @@ int drm_buffer_object_create(drm_file_t * priv,
|
|||
unsigned long buffer_start,
|
||||
drm_buffer_object_t ** buf_obj)
|
||||
{
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_buffer_manager_t *bm = &dev->bm;
|
||||
drm_buffer_object_t *bo;
|
||||
int ret = 0;
|
||||
|
|
@ -1615,6 +1628,7 @@ int drm_buffer_object_create(drm_file_t * priv,
|
|||
drm_bo_usage_deref_unlocked(bo);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_buffer_object_create);
|
||||
|
||||
static int drm_bo_add_user_object(drm_file_t * priv, drm_buffer_object_t * bo,
|
||||
int shareable)
|
||||
|
|
@ -1670,7 +1684,8 @@ int drm_bo_ioctl(DRM_IOCTL_ARGS)
|
|||
switch (req->op) {
|
||||
case drm_bo_create:
|
||||
rep.ret =
|
||||
drm_buffer_object_create(priv, req->size,
|
||||
drm_buffer_object_create(priv->head->dev,
|
||||
req->size,
|
||||
req->type,
|
||||
req->mask,
|
||||
req->hint,
|
||||
|
|
|
|||
|
|
@ -60,6 +60,13 @@
|
|||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
|
||||
#undef DRM_IRQ_ARGS
|
||||
#define DRM_IRQ_ARGS int irq, void *arg, struct pt_regs *regs
|
||||
|
||||
typedef _Bool bool;
|
||||
enum {
|
||||
false = 0,
|
||||
true = 1
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef list_for_each_safe
|
||||
|
|
|
|||
1107
linux-core/drm_crtc.c
Normal file
1107
linux-core/drm_crtc.c
Normal file
File diff suppressed because it is too large
Load diff
480
linux-core/drm_crtc.h
Normal file
480
linux-core/drm_crtc.h
Normal file
|
|
@ -0,0 +1,480 @@
|
|||
/*
|
||||
* Copyright © 2006 Keith Packard
|
||||
* Copyright © 2007 Intel Corporation
|
||||
* Jesse Barnes <jesse.barnes@intel.com>
|
||||
*/
|
||||
#ifndef __DRM_CRTC_H__
|
||||
#define __DRM_CRTC_H__
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/idr.h>
|
||||
|
||||
#include <linux/fb.h>
|
||||
|
||||
struct drm_device;
|
||||
|
||||
/*
|
||||
* Note on terminology: here, for brevity and convenience, we refer to output
|
||||
* control chips as 'CRTCs'. They can control any type of output, VGA, LVDS,
|
||||
* DVI, etc. And 'screen' refers to the whole of the visible display, which
|
||||
* may span multiple monitors (and therefore multiple CRTC and output
|
||||
* structures).
|
||||
*/
|
||||
|
||||
enum drm_mode_status {
|
||||
MODE_OK = 0, /* Mode OK */
|
||||
MODE_HSYNC, /* hsync out of range */
|
||||
MODE_VSYNC, /* vsync out of range */
|
||||
MODE_H_ILLEGAL, /* mode has illegal horizontal timings */
|
||||
MODE_V_ILLEGAL, /* mode has illegal horizontal timings */
|
||||
MODE_BAD_WIDTH, /* requires an unsupported linepitch */
|
||||
MODE_NOMODE, /* no mode with a maching name */
|
||||
MODE_NO_INTERLACE, /* interlaced mode not supported */
|
||||
MODE_NO_DBLESCAN, /* doublescan mode not supported */
|
||||
MODE_NO_VSCAN, /* multiscan mode not supported */
|
||||
MODE_MEM, /* insufficient video memory */
|
||||
MODE_VIRTUAL_X, /* mode width too large for specified virtual size */
|
||||
MODE_VIRTUAL_Y, /* mode height too large for specified virtual size */
|
||||
MODE_MEM_VIRT, /* insufficient video memory given virtual size */
|
||||
MODE_NOCLOCK, /* no fixed clock available */
|
||||
MODE_CLOCK_HIGH, /* clock required is too high */
|
||||
MODE_CLOCK_LOW, /* clock required is too low */
|
||||
MODE_CLOCK_RANGE, /* clock/mode isn't in a ClockRange */
|
||||
MODE_BAD_HVALUE, /* horizontal timing was out of range */
|
||||
MODE_BAD_VVALUE, /* vertical timing was out of range */
|
||||
MODE_BAD_VSCAN, /* VScan value out of range */
|
||||
MODE_HSYNC_NARROW, /* horizontal sync too narrow */
|
||||
MODE_HSYNC_WIDE, /* horizontal sync too wide */
|
||||
MODE_HBLANK_NARROW, /* horizontal blanking too narrow */
|
||||
MODE_HBLANK_WIDE, /* horizontal blanking too wide */
|
||||
MODE_VSYNC_NARROW, /* vertical sync too narrow */
|
||||
MODE_VSYNC_WIDE, /* vertical sync too wide */
|
||||
MODE_VBLANK_NARROW, /* vertical blanking too narrow */
|
||||
MODE_VBLANK_WIDE, /* vertical blanking too wide */
|
||||
MODE_PANEL, /* exceeds panel dimensions */
|
||||
MODE_INTERLACE_WIDTH, /* width too large for interlaced mode */
|
||||
MODE_ONE_WIDTH, /* only one width is supported */
|
||||
MODE_ONE_HEIGHT, /* only one height is supported */
|
||||
MODE_ONE_SIZE, /* only one resolution is supported */
|
||||
MODE_NO_REDUCED, /* monitor doesn't accept reduced blanking */
|
||||
MODE_BAD = -2, /* unspecified reason */
|
||||
MODE_ERROR = -1 /* error condition */
|
||||
};
|
||||
|
||||
#define DRM_MODE_TYPE_BUILTIN (1<<0)
|
||||
#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN)
|
||||
#define DRM_MODE_TYPE_CRTC_C ((1<<2) | DRM_MODE_TYPE_BUILTIN)
|
||||
#define DRM_MODE_TYPE_PREFERRED (1<<3)
|
||||
#define DRM_MODE_TYPE_DEFAULT (1<<4)
|
||||
#define DRM_MODE_TYPE_USERDEF (1<<5)
|
||||
#define DRM_MODE_TYPE_DRIVER (1<<6)
|
||||
|
||||
#define DRM_MODE_TYPE_CLOCK_CRTC_C (DRM_MODE_TYPE_CLOCK_C | \
|
||||
DRM_MODE_TYPE_CRTC_C)
|
||||
|
||||
#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), \
|
||||
.hdisplay = (hd), .hsync_start = (hss), .hsync_end = (hse), \
|
||||
.htotal = (ht), .hskew = (hsk), .vdisplay = (vd), \
|
||||
.vsync_start = (vss), .vsync_end = (vse), .vtotal = (vt), \
|
||||
.vscan = (vs), .flags = (f), .vrefresh = 0
|
||||
|
||||
struct drm_display_mode {
|
||||
/* Header */
|
||||
struct list_head head;
|
||||
char name[DRM_DISPLAY_MODE_LEN];
|
||||
int mode_id;
|
||||
enum drm_mode_status status;
|
||||
int type;
|
||||
|
||||
/* Proposed mode values */
|
||||
int clock;
|
||||
int hdisplay;
|
||||
int hsync_start;
|
||||
int hsync_end;
|
||||
int htotal;
|
||||
int hskew;
|
||||
int vdisplay;
|
||||
int vsync_start;
|
||||
int vsync_end;
|
||||
int vtotal;
|
||||
int vscan;
|
||||
unsigned int flags;
|
||||
|
||||
/* Actual mode we give to hw */
|
||||
int clock_index;
|
||||
int synth_clock;
|
||||
int crtc_hdisplay;
|
||||
int crtc_hblank_start;
|
||||
int crtc_hblank_end;
|
||||
int crtc_hsync_start;
|
||||
int crtc_hsync_end;
|
||||
int crtc_htotal;
|
||||
int crtc_hskew;
|
||||
int crtc_vdisplay;
|
||||
int crtc_vblank_start;
|
||||
int crtc_vblank_end;
|
||||
int crtc_vsync_start;
|
||||
int crtc_vsync_end;
|
||||
int crtc_vtotal;
|
||||
int crtc_hadjusted;
|
||||
int crtc_vadjusted;
|
||||
|
||||
/* Driver private mode info */
|
||||
int private_size;
|
||||
int *private;
|
||||
int private_flags;
|
||||
|
||||
int vrefresh;
|
||||
float hsync;
|
||||
};
|
||||
|
||||
/* Video mode flags */
|
||||
#define V_PHSYNC (1<<0)
|
||||
#define V_NHSYNC (1<<1)
|
||||
#define V_PVSYNC (1<<2)
|
||||
#define V_NVSYNC (1<<3)
|
||||
#define V_INTERLACE (1<<4)
|
||||
#define V_DBLSCAN (1<<5)
|
||||
#define V_CSYNC (1<<6)
|
||||
#define V_PCSYNC (1<<7)
|
||||
#define V_NCSYNC (1<<8)
|
||||
#define V_HSKEW (1<<9) /* hskew provided */
|
||||
#define V_BCAST (1<<10)
|
||||
#define V_PIXMUX (1<<11)
|
||||
#define V_DBLCLK (1<<12)
|
||||
#define V_CLKDIV2 (1<<13)
|
||||
|
||||
#define CRTC_INTERLACE_HALVE_V 0x1 /* halve V values for interlacing */
|
||||
#define DPMSModeOn 0
|
||||
#define DPMSModeStandby 1
|
||||
#define DPMSModeSuspend 2
|
||||
#define DPMSModeOff 3
|
||||
|
||||
enum drm_output_status {
|
||||
output_status_connected,
|
||||
output_status_disconnected,
|
||||
output_status_unknown,
|
||||
};
|
||||
|
||||
enum subpixel_order {
|
||||
SubPixelUnknown = 0,
|
||||
SubPixelHorizontalRGB,
|
||||
SubPixelHorizontalBGR,
|
||||
SubPixelVerticalRGB,
|
||||
SubPixelVerticalBGR,
|
||||
SubPixelNone,
|
||||
};
|
||||
|
||||
struct drm_framebuffer {
|
||||
struct drm_device *dev;
|
||||
struct list_head head;
|
||||
int id; /* idr assigned */
|
||||
unsigned int pitch;
|
||||
unsigned long offset;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
/* depth can be 15 or 16 */
|
||||
unsigned int depth;
|
||||
int bits_per_pixel;
|
||||
int flags;
|
||||
struct drm_buffer_object *bo;
|
||||
void *fbdev;
|
||||
u32 pseudo_palette[17];
|
||||
void *virtual_base;
|
||||
};
|
||||
struct drm_crtc;
|
||||
struct drm_output;
|
||||
|
||||
/**
|
||||
* drm_crtc_funcs - control CRTCs for a given device
|
||||
* @dpms: control display power levels
|
||||
* @save: save CRTC state
|
||||
* @resore: restore CRTC state
|
||||
* @lock: lock the CRTC
|
||||
* @unlock: unlock the CRTC
|
||||
* @shadow_allocate: allocate shadow pixmap
|
||||
* @shadow_create: create shadow pixmap for rotation support
|
||||
* @shadow_destroy: free shadow pixmap
|
||||
* @mode_fixup: fixup proposed mode
|
||||
* @mode_set: set the desired mode on the CRTC
|
||||
* @gamma_set: specify color ramp for CRTC
|
||||
* @cleanup: cleanup driver private state prior to close
|
||||
*
|
||||
* The drm_crtc_funcs structure is the central CRTC management structure
|
||||
* in the DRM. Each CRTC controls one or more outputs (note that the name
|
||||
* CRTC is simply historical, a CRTC may control LVDS, VGA, DVI, TV out, etc.
|
||||
* outputs, not just CRTs).
|
||||
*
|
||||
* Each driver is responsible for filling out this structure at startup time,
|
||||
* in addition to providing other modesetting features, like i2c and DDC
|
||||
* bus accessors.
|
||||
*/
|
||||
struct drm_crtc_funcs {
|
||||
/*
|
||||
* Control power levels on the CRTC. If the mode passed in is
|
||||
* unsupported, the provider must use the next lowest power level.
|
||||
*/
|
||||
void (*dpms)(struct drm_crtc *crtc, int mode);
|
||||
|
||||
/* JJJ: Are these needed? */
|
||||
/* Save CRTC state */
|
||||
void (*save)(struct drm_crtc *crtc); /* suspend? */
|
||||
/* Restore CRTC state */
|
||||
void (*restore)(struct drm_crtc *crtc); /* resume? */
|
||||
bool (*lock)(struct drm_crtc *crtc);
|
||||
void (*unlock)(struct drm_crtc *crtc);
|
||||
|
||||
void (*prepare)(struct drm_crtc *crtc);
|
||||
void (*commit)(struct drm_crtc *crtc);
|
||||
|
||||
/* Provider can fixup or change mode timings before modeset occurs */
|
||||
bool (*mode_fixup)(struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode);
|
||||
/* Actually set the mode */
|
||||
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);
|
||||
/* Driver cleanup routine */
|
||||
void (*cleanup)(struct drm_crtc *crtc);
|
||||
};
|
||||
|
||||
/**
|
||||
* drm_crtc - central CRTC control structure
|
||||
* @enabled: is this CRTC enabled?
|
||||
* @x: x position on screen
|
||||
* @y: y position on screen
|
||||
* @desired_mode: new desired mode
|
||||
* @desired_x: desired x for desired_mode
|
||||
* @desired_y: desired y for desired_mode
|
||||
* @funcs: CRTC control functions
|
||||
* @driver_private: arbitrary driver data
|
||||
*
|
||||
* Each CRTC may have one or more outputs associated with it. This structure
|
||||
* allows the CRTC to be controlled.
|
||||
*/
|
||||
struct drm_crtc {
|
||||
struct drm_device *dev;
|
||||
struct list_head head;
|
||||
|
||||
int id; /* idr assigned */
|
||||
|
||||
/* framebuffer the CRTC is currently bound to */
|
||||
struct drm_framebuffer *fb;
|
||||
|
||||
bool enabled;
|
||||
|
||||
/* JJJ: are these needed? */
|
||||
bool cursor_in_range;
|
||||
bool cursor_shown;
|
||||
|
||||
struct drm_display_mode mode;
|
||||
|
||||
int x, y;
|
||||
struct drm_display_mode *desired_mode;
|
||||
int desired_x, desired_y;
|
||||
const struct drm_crtc_funcs *funcs;
|
||||
void *driver_private;
|
||||
|
||||
/* RRCrtcPtr randr_crtc? */
|
||||
};
|
||||
|
||||
extern struct drm_crtc *drm_crtc_create(struct drm_device *dev,
|
||||
const struct drm_crtc_funcs *funcs);
|
||||
|
||||
/**
|
||||
* drm_output_funcs - control outputs on a given device
|
||||
* @init: setup this output
|
||||
* @dpms: set power state (see drm_crtc_funcs above)
|
||||
* @save: save output state
|
||||
* @restore: restore output state
|
||||
* @mode_valid: is this mode valid on the given output?
|
||||
* @mode_fixup: try to fixup proposed mode for this output
|
||||
* @mode_set: set this mode
|
||||
* @detect: is this output active?
|
||||
* @get_modes: get mode list for this output
|
||||
* @set_property: property for this output may need update
|
||||
* @cleanup: output is going away, cleanup
|
||||
*
|
||||
* Each CRTC may have one or more outputs attached to it. The functions
|
||||
* below allow the core DRM code to control outputs, enumerate available modes,
|
||||
* etc.
|
||||
*/
|
||||
struct drm_output_funcs {
|
||||
void (*init)(struct drm_output *output);
|
||||
void (*dpms)(struct drm_output *output, int mode);
|
||||
void (*save)(struct drm_output *output);
|
||||
void (*restore)(struct drm_output *output);
|
||||
int (*mode_valid)(struct drm_output *output,
|
||||
struct drm_display_mode *mode);
|
||||
bool (*mode_fixup)(struct drm_output *output,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode);
|
||||
void (*prepare)(struct drm_output *output);
|
||||
void (*commit)(struct drm_output *output);
|
||||
void (*mode_set)(struct drm_output *output,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode);
|
||||
enum drm_output_status (*detect)(struct drm_output *output);
|
||||
int (*get_modes)(struct drm_output *output);
|
||||
/* JJJ: type checking for properties via property value type */
|
||||
bool (*set_property)(struct drm_output *output, int prop, void *val);
|
||||
void (*cleanup)(struct drm_output *output);
|
||||
};
|
||||
|
||||
#define DRM_OUTPUT_LEN 32
|
||||
/**
|
||||
* drm_output - central DRM output control structure
|
||||
* @crtc: CRTC this output is currently connected to, NULL if none
|
||||
* @possible_crtcs: bitmap of CRTCS this output could be attached to
|
||||
* @possible_clones: bitmap of possible outputs this output could clone
|
||||
* @interlace_allowed: can this output handle interlaced modes?
|
||||
* @doublescan_allowed: can this output handle doublescan?
|
||||
* @available_modes: modes available on this output (from get_modes() + user)
|
||||
* @initial_x: initial x position for this output
|
||||
* @initial_y: initial y position for this output
|
||||
* @status: output connected?
|
||||
* @subpixel_order: for this output
|
||||
* @mm_width: displayable width of output in mm
|
||||
* @mm_height: displayable height of output in mm
|
||||
* @name: name of output (should be one of a few standard names)
|
||||
* @funcs: output control functions
|
||||
* @driver_private: private driver data
|
||||
*
|
||||
* Each output may be connected to one or more CRTCs, or may be clonable by
|
||||
* another output if they can share a CRTC. Each output also has a specific
|
||||
* position in the broader display (referred to as a 'screen' though it could
|
||||
* span multiple monitors).
|
||||
*/
|
||||
struct drm_output {
|
||||
struct drm_device *dev;
|
||||
struct list_head head;
|
||||
struct drm_crtc *crtc;
|
||||
int id; /* idr assigned */
|
||||
unsigned long possible_crtcs;
|
||||
unsigned long possible_clones;
|
||||
bool interlace_allowed;
|
||||
bool doublescan_allowed;
|
||||
spinlock_t modes_lock;
|
||||
struct list_head modes; /* list of modes on this output */
|
||||
/*
|
||||
OptionInfoPtr options;
|
||||
XF86ConfMonitorPtr conf_monitor;
|
||||
*/
|
||||
int initial_x, initial_y;
|
||||
enum drm_output_status status;
|
||||
|
||||
/* these are modes added by probing with DDC or the BIOS */
|
||||
struct list_head probed_modes;
|
||||
|
||||
/* xf86MonPtr MonInfo; */
|
||||
enum subpixel_order subpixel_order;
|
||||
int mm_width, mm_height;
|
||||
struct edid *monitor_info;
|
||||
char name[DRM_OUTPUT_LEN];
|
||||
const struct drm_output_funcs *funcs;
|
||||
void *driver_private;
|
||||
/* RROutputPtr randr_output? */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_mode_config_funcs - configure CRTCs for a given screen layout
|
||||
* @resize: adjust CRTCs as necessary for the proposed layout
|
||||
*
|
||||
* Currently only a resize hook is available. DRM will call back into the
|
||||
* driver with a new screen width and height. If the driver can't support
|
||||
* the proposed size, it can return false. Otherwise it should adjust
|
||||
* the CRTC<->output mappings as needed and update its view of the screen.
|
||||
*/
|
||||
struct drm_mode_config_funcs {
|
||||
bool (*resize)(struct drm_device *dev, int width, int height);
|
||||
};
|
||||
|
||||
/**
|
||||
* drm_mode_config - Mode configuration control structure
|
||||
*
|
||||
*/
|
||||
struct drm_mode_config {
|
||||
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 */
|
||||
int num_fb;
|
||||
struct list_head fb_list;
|
||||
int num_output;
|
||||
struct list_head output_list;
|
||||
|
||||
/* int compat_output? */
|
||||
int num_crtc;
|
||||
struct list_head crtc_list;
|
||||
|
||||
int min_width, min_height;
|
||||
int max_width, max_height;
|
||||
/* DamagePtr rotationDamage? */
|
||||
/* DGA stuff? */
|
||||
struct drm_mode_config_funcs *funcs;
|
||||
int fb_base;
|
||||
};
|
||||
|
||||
struct drm_output *drm_output_create(struct drm_device *dev,
|
||||
const struct drm_output_funcs *funcs,
|
||||
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 int drm_add_edid_modes(struct drm_output *output,
|
||||
struct i2c_adapter *adapter);
|
||||
extern void drm_mode_probed_add(struct drm_output *output, struct drm_display_mode *mode);
|
||||
extern void drm_mode_remove(struct drm_output *output, 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,
|
||||
struct drm_display_mode *mode);
|
||||
extern void drm_mode_config_init(struct drm_device *dev);
|
||||
extern void drm_mode_config_cleanup(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);
|
||||
extern void drm_mode_list_concat(struct list_head *head,
|
||||
struct list_head *new);
|
||||
extern void drm_mode_validate_size(struct drm_device *dev,
|
||||
struct list_head *mode_list,
|
||||
int maxX, int maxY, int maxPitch);
|
||||
extern void drm_mode_prune_invalid(struct drm_device *dev,
|
||||
struct list_head *mode_list, bool verbose);
|
||||
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 struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev);
|
||||
extern bool drm_initial_config(struct drm_device *dev,
|
||||
struct drm_framebuffer *fb, 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_remove(struct drm_device *dev, struct drm_framebuffer *fb);
|
||||
|
||||
/* 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);
|
||||
extern int drm_mode_addfb(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
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);
|
||||
#endif /* __DRM_CRTC_H__ */
|
||||
|
||||
|
|
@ -123,6 +123,13 @@ static drm_ioctl_desc_t drm_ioctls[] = {
|
|||
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_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},
|
||||
[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},
|
||||
};
|
||||
|
||||
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
|
||||
|
|
@ -150,8 +157,6 @@ int drm_lastclose(drm_device_t * dev)
|
|||
* We can't do much about this function failing.
|
||||
*/
|
||||
|
||||
drm_bo_driver_finish(dev);
|
||||
|
||||
if (dev->driver->lastclose)
|
||||
dev->driver->lastclose(dev);
|
||||
DRM_DEBUG("driver lastclose completed\n");
|
||||
|
|
@ -394,6 +399,8 @@ static void drm_cleanup(drm_device_t * dev)
|
|||
DRM_DEBUG("mtrr_del=%d\n", retval);
|
||||
}
|
||||
|
||||
drm_bo_driver_finish(dev);
|
||||
|
||||
if (drm_core_has_AGP(dev) && dev->agp) {
|
||||
drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
|
||||
dev->agp = NULL;
|
||||
|
|
|
|||
468
linux-core/drm_edid.c
Normal file
468
linux-core/drm_edid.c
Normal file
|
|
@ -0,0 +1,468 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Intel Corporation
|
||||
* Jesse Barnes <jesse.barnes@intel.com>
|
||||
*
|
||||
* DDC probing routines (drm_ddc_read & drm_do_probe_ddc_edid) originally from
|
||||
* FB layer.
|
||||
* Copyright (C) 2006 Dennis Munsie <dmunsie@cecropia.com>
|
||||
*/
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
#include "drmP.h"
|
||||
#include "drm_edid.h"
|
||||
|
||||
/* Valid EDID header has these bytes */
|
||||
static u8 edid_header[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
|
||||
|
||||
/**
|
||||
* edid_valid - sanity check EDID data
|
||||
* @edid: EDID data
|
||||
*
|
||||
* Sanity check the EDID block by looking at the header, the version number
|
||||
* and the checksum. Return 0 if the EDID doesn't check out, or 1 if it's
|
||||
* valid.
|
||||
*/
|
||||
static bool edid_valid(struct edid *edid)
|
||||
{
|
||||
int i;
|
||||
u8 csum = 0;
|
||||
u8 *raw_edid = (u8 *)edid;
|
||||
|
||||
if (memcmp(edid->header, edid_header, sizeof(edid_header)))
|
||||
goto bad;
|
||||
if (edid->version != 1)
|
||||
goto bad;
|
||||
if (edid->revision <= 0 || edid->revision > 3)
|
||||
goto bad;
|
||||
|
||||
for (i = 0; i < EDID_LENGTH; i++)
|
||||
csum += raw_edid[i];
|
||||
if (csum)
|
||||
goto bad;
|
||||
|
||||
return 1;
|
||||
|
||||
bad:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_mode_std - convert standard mode info (width, height, refresh) into mode
|
||||
* @t: standard timing params
|
||||
*
|
||||
* Take the standard timing params (in this case width, aspect, and refresh)
|
||||
* and convert them into a real mode using CVT.
|
||||
*
|
||||
* Punts for now, but should eventually use the FB layer's CVT based mode
|
||||
* generation code.
|
||||
*/
|
||||
struct drm_display_mode *drm_mode_std(struct drm_device *dev,
|
||||
struct std_timing *t)
|
||||
{
|
||||
// struct fb_videomode mode;
|
||||
|
||||
// fb_find_mode_cvt(&mode, 0, 0);
|
||||
/* JJJ: convert to drm_display_mode */
|
||||
struct drm_display_mode *mode;
|
||||
int hsize = t->hsize * 8 + 248, vsize;
|
||||
|
||||
mode = drm_crtc_mode_create(dev);
|
||||
if (!mode)
|
||||
return NULL;
|
||||
|
||||
if (t->aspect_ratio == 0)
|
||||
vsize = (hsize * 10) / 16;
|
||||
else if (t->aspect_ratio == 1)
|
||||
vsize = (hsize * 3) / 4;
|
||||
else if (t->aspect_ratio == 2)
|
||||
vsize = (hsize * 4) / 5;
|
||||
else
|
||||
vsize = (hsize * 9) / 16;
|
||||
|
||||
snprintf(mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d", hsize, vsize);
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_mode_detailed - create a new mode from an EDID detailed timing section
|
||||
* @timing: EDID detailed timing info
|
||||
* @preferred: is this a preferred mode?
|
||||
*
|
||||
* An EDID detailed timing block contains enough info for us to create and
|
||||
* return a new struct drm_display_mode. The @preferred flag will be set
|
||||
* if this is the display's preferred timing, and we'll use it to indicate
|
||||
* to the other layers that this mode is desired.
|
||||
*/
|
||||
struct drm_display_mode *drm_mode_detailed(drm_device_t *dev,
|
||||
struct detailed_timing *timing)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
struct detailed_pixel_timing *pt = &timing->data.pixel_data;
|
||||
|
||||
if (pt->stereo) {
|
||||
printk(KERN_WARNING "stereo mode not supported\n");
|
||||
return NULL;
|
||||
}
|
||||
if (!pt->separate_sync) {
|
||||
printk(KERN_WARNING "integrated sync not supported\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mode = drm_crtc_mode_create(dev);
|
||||
if (!mode)
|
||||
return NULL;
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER;
|
||||
mode->clock = timing->pixel_clock * 10;
|
||||
|
||||
mode->hdisplay = (pt->hactive_hi << 8) | pt->hactive_lo;
|
||||
mode->hsync_start = mode->hdisplay + ((pt->hsync_offset_hi << 8) |
|
||||
pt->hsync_offset_lo);
|
||||
mode->hsync_end = mode->hsync_start +
|
||||
((pt->hsync_pulse_width_hi << 8) |
|
||||
pt->hsync_pulse_width_lo);
|
||||
mode->htotal = mode->hdisplay + ((pt->hblank_hi << 8) | pt->hblank_lo);
|
||||
|
||||
mode->vdisplay = (pt->vactive_hi << 8) | pt->vactive_lo;
|
||||
mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 8) |
|
||||
pt->vsync_offset_lo);
|
||||
mode->vsync_end = mode->vsync_start +
|
||||
((pt->vsync_pulse_width_hi << 8) |
|
||||
pt->vsync_pulse_width_lo);
|
||||
mode->vtotal = mode->vdisplay + ((pt->vblank_hi << 8) | pt->vblank_lo);
|
||||
|
||||
snprintf(mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d", mode->hdisplay,
|
||||
mode->vdisplay);
|
||||
|
||||
if (pt->interlaced)
|
||||
mode->flags |= V_INTERLACE;
|
||||
|
||||
mode->flags |= pt->hsync_positive ? V_PHSYNC : V_NHSYNC;
|
||||
mode->flags |= pt->vsync_positive ? V_PVSYNC : V_NVSYNC;
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Detailed mode info for the EDID "established modes" data to use.
|
||||
*/
|
||||
static struct drm_display_mode edid_est_modes[] = {
|
||||
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
|
||||
968, 1056, 0, 600, 601, 605, 628, 0,
|
||||
V_PHSYNC | V_PVSYNC) }, /* 800x600@60Hz */
|
||||
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824,
|
||||
896, 1024, 0, 600, 601, 603, 625, 0,
|
||||
V_PHSYNC | V_PVSYNC) }, /* 800x600@56Hz */
|
||||
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656,
|
||||
720, 840, 0, 480, 481, 484, 500, 0,
|
||||
V_NHSYNC | V_NVSYNC) }, /* 640x480@75Hz */
|
||||
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664,
|
||||
704, 832, 0, 480, 489, 491, 520, 0,
|
||||
V_NHSYNC | V_NVSYNC) }, /* 640x480@72Hz */
|
||||
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 30240, 640, 704,
|
||||
768, 864, 0, 480, 483, 486, 525, 0,
|
||||
V_NHSYNC | V_NVSYNC) }, /* 640x480@67Hz */
|
||||
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25200, 640, 656,
|
||||
752, 800, 0, 480, 490, 492, 525, 0,
|
||||
V_NHSYNC | V_NVSYNC) }, /* 640x480@60Hz */
|
||||
{ DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 738,
|
||||
846, 900, 0, 400, 421, 423, 449, 0,
|
||||
V_NHSYNC | V_NVSYNC) }, /* 720x400@88Hz */
|
||||
{ DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 28320, 720, 738,
|
||||
846, 900, 0, 400, 412, 414, 449, 0,
|
||||
V_NHSYNC | V_PVSYNC) }, /* 720x400@70Hz */
|
||||
{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296,
|
||||
1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
|
||||
V_PHSYNC | V_PVSYNC) }, /* 1280x1024@75Hz */
|
||||
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78800, 1024, 1040,
|
||||
1136, 1312, 0, 768, 769, 772, 800, 0,
|
||||
V_PHSYNC | V_PVSYNC) }, /* 1024x768@75Hz */
|
||||
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048,
|
||||
1184, 1328, 0, 768, 771, 777, 806, 0,
|
||||
V_NHSYNC | V_NVSYNC) }, /* 1024x768@70Hz */
|
||||
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
|
||||
1184, 1344, 0, 768, 771, 777, 806, 0,
|
||||
V_NHSYNC | V_NVSYNC) }, /* 1024x768@60Hz */
|
||||
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER,44900, 1024, 1032,
|
||||
1208, 1264, 0, 768, 768, 776, 817, 0,
|
||||
V_PHSYNC | V_PVSYNC | V_INTERLACE) }, /* 1024x768@43Hz */
|
||||
{ DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 57284, 832, 864,
|
||||
928, 1152, 0, 624, 625, 628, 667, 0,
|
||||
V_NHSYNC | V_NVSYNC) }, /* 832x624@75Hz */
|
||||
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816,
|
||||
896, 1056, 0, 600, 601, 604, 625, 0,
|
||||
V_PHSYNC | V_PVSYNC) }, /* 800x600@75Hz */
|
||||
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856,
|
||||
976, 1040, 0, 600, 637, 643, 666, 0,
|
||||
V_PHSYNC | V_PVSYNC) }, /* 800x600@72Hz */
|
||||
{ DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216,
|
||||
1344, 1600, 0, 864, 865, 868, 900, 0,
|
||||
V_PHSYNC | V_PVSYNC) }, /* 1152x864@75Hz */
|
||||
};
|
||||
|
||||
#define EDID_EST_TIMINGS 16
|
||||
#define EDID_STD_TIMINGS 8
|
||||
#define EDID_DETAILED_TIMINGS 4
|
||||
|
||||
/**
|
||||
* add_established_modes - get est. modes from EDID and add them
|
||||
* @edid: EDID block to scan
|
||||
*
|
||||
* Each EDID block contains a bitmap of the supported "established modes" list
|
||||
* (defined above). Tease them out and add them to the global modes list.
|
||||
*/
|
||||
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 |
|
||||
(edid->established_timings.t2 << 8) |
|
||||
((edid->established_timings.mfg_rsvd & 0x80) << 9);
|
||||
int i, modes = 0;
|
||||
|
||||
for (i = 0; i <= EDID_EST_TIMINGS; i++)
|
||||
if (est_bits & (1<<i)) {
|
||||
struct drm_display_mode *newmode;
|
||||
newmode = drm_mode_duplicate(dev, &edid_est_modes[i]);
|
||||
drm_mode_probed_add(output, newmode);
|
||||
modes++;
|
||||
}
|
||||
|
||||
return modes;
|
||||
}
|
||||
|
||||
/**
|
||||
* add_standard_modes - get std. modes from EDID and add them
|
||||
* @edid: EDID block to scan
|
||||
*
|
||||
* Standard modes can be calculated using the CVT standard. Grab them from
|
||||
* @edid, calculate them, and add them to the list.
|
||||
*/
|
||||
static int add_standard_modes(struct drm_output *output, struct edid *edid)
|
||||
{
|
||||
struct drm_device *dev = output->dev;
|
||||
int i, modes = 0;
|
||||
|
||||
for (i = 0; i < EDID_STD_TIMINGS; i++) {
|
||||
struct std_timing *t = &edid->standard_timings[i];
|
||||
struct drm_display_mode *newmode;
|
||||
|
||||
/* If std timings bytes are 1, 1 it's empty */
|
||||
if (t->hsize == 1 && (t->aspect_ratio | t->vfreq) == 1)
|
||||
continue;
|
||||
|
||||
newmode = drm_mode_std(dev, &edid->standard_timings[i]);
|
||||
drm_mode_probed_add(output, newmode);
|
||||
modes++;
|
||||
}
|
||||
|
||||
return modes;
|
||||
}
|
||||
|
||||
/**
|
||||
* add_detailed_modes - get detailed mode info from EDID data
|
||||
* @edid: EDID block to scan
|
||||
*
|
||||
* Some of the detailed timing sections may contain mode information. Grab
|
||||
* it and add it to the list.
|
||||
*/
|
||||
static int add_detailed_info(struct drm_output *output, struct edid *edid)
|
||||
{
|
||||
struct drm_device *dev = output->dev;
|
||||
int i, j, modes = 0;
|
||||
|
||||
for (i = 0; i < EDID_DETAILED_TIMINGS; i++) {
|
||||
struct detailed_timing *timing = &edid->detailed_timings[i];
|
||||
struct detailed_non_pixel *data = &timing->data.other_data;
|
||||
struct drm_display_mode *newmode;
|
||||
|
||||
/* EDID up to and including 1.2 may put monitor info here */
|
||||
if (edid->version == 1 && edid->revision < 3)
|
||||
continue;
|
||||
|
||||
/* Detailed mode timing */
|
||||
if (timing->pixel_clock) {
|
||||
newmode = drm_mode_detailed(dev, timing);
|
||||
/* First detailed mode is preferred */
|
||||
if (i == 0 && edid->preferred_timing)
|
||||
newmode->type |= DRM_MODE_TYPE_PREFERRED;
|
||||
drm_mode_probed_add(output, newmode);
|
||||
|
||||
modes++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Other timing or info */
|
||||
switch (data->type) {
|
||||
case EDID_DETAIL_MONITOR_SERIAL:
|
||||
break;
|
||||
case EDID_DETAIL_MONITOR_STRING:
|
||||
break;
|
||||
case EDID_DETAIL_MONITOR_RANGE:
|
||||
/* Get monitor range data */
|
||||
break;
|
||||
case EDID_DETAIL_MONITOR_NAME:
|
||||
break;
|
||||
case EDID_DETAIL_MONITOR_CPDATA:
|
||||
break;
|
||||
case EDID_DETAIL_STD_MODES:
|
||||
/* Five modes per detailed section */
|
||||
for (j = 0; j < 5; i++) {
|
||||
struct std_timing *std;
|
||||
struct drm_display_mode *newmode;
|
||||
|
||||
std = &data->data.timings[j];
|
||||
newmode = drm_mode_std(dev, std);
|
||||
drm_mode_probed_add(output, newmode);
|
||||
modes++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return modes;
|
||||
}
|
||||
|
||||
#define DDC_ADDR 0x50
|
||||
|
||||
static unsigned char *drm_do_probe_ddc_edid(struct i2c_adapter *adapter)
|
||||
{
|
||||
unsigned char start = 0x0;
|
||||
unsigned char *buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = DDC_ADDR,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = &start,
|
||||
}, {
|
||||
.addr = DDC_ADDR,
|
||||
.flags = I2C_M_RD,
|
||||
.len = EDID_LENGTH,
|
||||
.buf = buf,
|
||||
}
|
||||
};
|
||||
|
||||
if (!buf) {
|
||||
dev_warn(&adapter->dev, "unable to allocate memory for EDID "
|
||||
"block.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (i2c_transfer(adapter, msgs, 2) == 2)
|
||||
return buf;
|
||||
|
||||
dev_info(&adapter->dev, "unable to read EDID block.\n");
|
||||
kfree(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static unsigned char *drm_ddc_read(struct i2c_adapter *adapter)
|
||||
{
|
||||
struct i2c_algo_bit_data *algo_data = adapter->algo_data;
|
||||
unsigned char *edid = NULL;
|
||||
int i, j;
|
||||
|
||||
/*
|
||||
* Startup the bus:
|
||||
* Set clock line high (but give it time to come up)
|
||||
* Then set clock & data low
|
||||
*/
|
||||
algo_data->setscl(algo_data->data, 1);
|
||||
udelay(550); /* startup delay */
|
||||
algo_data->setscl(algo_data->data, 0);
|
||||
algo_data->setsda(algo_data->data, 0);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
/* For some old monitors we need the
|
||||
* following process to initialize/stop DDC
|
||||
*/
|
||||
algo_data->setsda(algo_data->data, 0);
|
||||
msleep(13);
|
||||
|
||||
algo_data->setscl(algo_data->data, 1);
|
||||
for (j = 0; j < 5; j++) {
|
||||
msleep(10);
|
||||
if (algo_data->getscl(algo_data->data))
|
||||
break;
|
||||
}
|
||||
if (j == 5)
|
||||
continue;
|
||||
|
||||
algo_data->setsda(algo_data->data, 0);
|
||||
msleep(15);
|
||||
algo_data->setscl(algo_data->data, 0);
|
||||
msleep(15);
|
||||
algo_data->setsda(algo_data->data, 1);
|
||||
msleep(15);
|
||||
|
||||
/* Do the real work */
|
||||
edid = drm_do_probe_ddc_edid(adapter);
|
||||
algo_data->setsda(algo_data->data, 0);
|
||||
algo_data->setscl(algo_data->data, 0);
|
||||
msleep(15);
|
||||
|
||||
algo_data->setscl(algo_data->data, 1);
|
||||
for (j = 0; j < 10; j++) {
|
||||
msleep(10);
|
||||
if (algo_data->getscl(algo_data->data))
|
||||
break;
|
||||
}
|
||||
|
||||
algo_data->setsda(algo_data->data, 1);
|
||||
msleep(15);
|
||||
algo_data->setscl(algo_data->data, 0);
|
||||
if (edid)
|
||||
break;
|
||||
}
|
||||
/* Release the DDC lines when done or the Apple Cinema HD display
|
||||
* will switch off
|
||||
*/
|
||||
algo_data->setsda(algo_data->data, 0);
|
||||
algo_data->setscl(algo_data->data, 0);
|
||||
algo_data->setscl(algo_data->data, 1);
|
||||
|
||||
return edid;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_add_edid_modes - add modes from EDID data, if available
|
||||
* @output: output we're probing
|
||||
* @adapter: i2c adapter to use for DDC
|
||||
*
|
||||
* Poke the given output's i2c channel to grab EDID data if possible. If we
|
||||
* get any, add the specified modes to the output's mode list.
|
||||
*
|
||||
* Return number of modes added or 0 if we couldn't find any.
|
||||
*/
|
||||
int drm_add_edid_modes(struct drm_output *output, struct i2c_adapter *adapter)
|
||||
{
|
||||
struct edid *edid;
|
||||
int num_modes = 0;
|
||||
|
||||
edid = (struct edid *)drm_ddc_read(adapter);
|
||||
if (!edid) {
|
||||
dev_warn(&output->dev->pdev->dev, "%s: no EDID data\n",
|
||||
output->name);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (!edid_valid(edid)) {
|
||||
dev_warn(&output->dev->pdev->dev, "%s: EDID invalid.\n",
|
||||
output->name);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
num_modes += add_established_modes(output, edid);
|
||||
num_modes += add_standard_modes(output, edid);
|
||||
num_modes += add_detailed_info(output, edid);
|
||||
|
||||
return num_modes;
|
||||
|
||||
out_err:
|
||||
kfree(edid);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_add_edid_modes);
|
||||
176
linux-core/drm_edid.h
Normal file
176
linux-core/drm_edid.h
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
#ifndef __DRM_EDID_H__
|
||||
#define __DRM_EDID_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define EDID_LENGTH 128
|
||||
#define DDC_ADDR 0x50
|
||||
|
||||
#ifdef BIG_ENDIAN
|
||||
#error "EDID structure is little endian, need big endian versions"
|
||||
#endif
|
||||
|
||||
struct est_timings {
|
||||
u8 t1;
|
||||
u8 t2;
|
||||
u8 mfg_rsvd;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct std_timing {
|
||||
u8 hsize; /* need to multiply by 8 then add 248 */
|
||||
u8 vfreq:6; /* need to add 60 */
|
||||
u8 aspect_ratio:2; /* 00=16:10, 01=4:3, 10=5:4, 11=16:9 */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* If detailed data is pixel timing */
|
||||
struct detailed_pixel_timing {
|
||||
u8 hactive_lo;
|
||||
u8 hblank_lo;
|
||||
u8 hblank_hi:4;
|
||||
u8 hactive_hi:4;
|
||||
u8 vactive_lo;
|
||||
u8 vblank_lo;
|
||||
u8 vblank_hi:4;
|
||||
u8 vactive_hi:4;
|
||||
u8 hsync_offset_lo;
|
||||
u8 hsync_pulse_width_lo;
|
||||
u8 vsync_pulse_width_lo:4;
|
||||
u8 vsync_offset_lo:4;
|
||||
u8 hsync_pulse_width_hi:2;
|
||||
u8 hsync_offset_hi:2;
|
||||
u8 vsync_pulse_width_hi:2;
|
||||
u8 vsync_offset_hi:2;
|
||||
u8 width_mm_lo;
|
||||
u8 height_mm_lo;
|
||||
u8 height_mm_hi:4;
|
||||
u8 width_mm_hi:4;
|
||||
u8 hborder;
|
||||
u8 vborder;
|
||||
u8 unknown0:1;
|
||||
u8 vsync_positive:1;
|
||||
u8 hsync_positive:1;
|
||||
u8 separate_sync:2;
|
||||
u8 stereo:1;
|
||||
u8 unknown6:1;
|
||||
u8 interlaced:1;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* If it's not pixel timing, it'll be one of the below */
|
||||
struct detailed_data_string {
|
||||
u8 str[13];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct detailed_data_monitor_range {
|
||||
u8 min_vfreq;
|
||||
u8 max_vfreq;
|
||||
u8 min_hfreq_khz;
|
||||
u8 max_hfreq_khz;
|
||||
u8 pixel_clock_mhz; /* need to multiply by 10 */
|
||||
u16 sec_gtf_toggle; /* A000=use above, 20=use below */ /* FIXME: byte order */
|
||||
u8 hfreq_start_khz; /* need to multiply by 2 */
|
||||
u8 c; /* need to divide by 2 */
|
||||
u16 m; /* FIXME: byte order */
|
||||
u8 k;
|
||||
u8 j; /* need to divide by 2 */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct detailed_data_wpindex {
|
||||
u8 white_y_lo:2;
|
||||
u8 white_x_lo:2;
|
||||
u8 pad:4;
|
||||
u8 white_x_hi;
|
||||
u8 white_y_hi;
|
||||
u8 gamma; /* need to divide by 100 then add 1 */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct detailed_data_color_point {
|
||||
u8 windex1;
|
||||
u8 wpindex1[3];
|
||||
u8 windex2;
|
||||
u8 wpindex2[3];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct detailed_non_pixel {
|
||||
u8 pad1;
|
||||
u8 type; /* ff=serial, fe=string, fd=monitor range, fc=monitor name
|
||||
fb=color point data, fa=standard timing data,
|
||||
f9=undefined, f8=mfg. reserved */
|
||||
u8 pad2;
|
||||
union {
|
||||
struct detailed_data_string str;
|
||||
struct detailed_data_monitor_range range;
|
||||
struct detailed_data_wpindex color;
|
||||
struct std_timing timings[5];
|
||||
} data;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define EDID_DETAIL_STD_MODES 0xfa
|
||||
#define EDID_DETAIL_MONITOR_CPDATA 0xfb
|
||||
#define EDID_DETAIL_MONITOR_NAME 0xfc
|
||||
#define EDID_DETAIL_MONITOR_RANGE 0xfd
|
||||
#define EDID_DETAIL_MONITOR_STRING 0xfe
|
||||
#define EDID_DETAIL_MONITOR_SERIAL 0xff
|
||||
|
||||
struct detailed_timing {
|
||||
u16 pixel_clock; /* need to multiply by 10 KHz */ /* FIXME: byte order */
|
||||
union {
|
||||
struct detailed_pixel_timing pixel_data;
|
||||
struct detailed_non_pixel other_data;
|
||||
} data;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct edid {
|
||||
u8 header[8];
|
||||
/* Vendor & product info */
|
||||
u16 mfg_id; /* FIXME: byte order */
|
||||
u16 prod_code; /* FIXME: byte order */
|
||||
u32 serial; /* FIXME: byte order */
|
||||
u8 mfg_week;
|
||||
u8 mfg_year;
|
||||
/* EDID version */
|
||||
u8 version;
|
||||
u8 revision;
|
||||
/* Display info: */
|
||||
/* input definition */
|
||||
u8 serration_vsync:1;
|
||||
u8 sync_on_green:1;
|
||||
u8 composite_sync:1;
|
||||
u8 separate_syncs:1;
|
||||
u8 blank_to_black:1;
|
||||
u8 video_level:2;
|
||||
u8 digital:1; /* bits below must be zero if set */
|
||||
u8 width_cm;
|
||||
u8 height_cm;
|
||||
u8 gamma;
|
||||
/* feature support */
|
||||
u8 default_gtf:1;
|
||||
u8 preferred_timing:1;
|
||||
u8 standard_color:1;
|
||||
u8 display_type:2; /* 00=mono, 01=rgb, 10=non-rgb, 11=unknown */
|
||||
u8 pm_active_off:1;
|
||||
u8 pm_suspend:1;
|
||||
u8 pm_standby:1;
|
||||
/* Color characteristics */
|
||||
u8 red_green_lo;
|
||||
u8 black_white_lo;
|
||||
u8 red_x;
|
||||
u8 red_y;
|
||||
u8 green_x;
|
||||
u8 green_y;
|
||||
u8 blue_x;
|
||||
u8 blue_y;
|
||||
u8 white_x;
|
||||
u8 white_y;
|
||||
/* Est. timings and mfg rsvd timings*/
|
||||
struct est_timings established_timings;
|
||||
/* Standard timings 1-8*/
|
||||
struct std_timing standard_timings[8];
|
||||
/* Detailing timings 1-4 */
|
||||
struct detailed_timing detailed_timings[4];
|
||||
/* Number of 128 byte ext. blocks */
|
||||
u8 extensions;
|
||||
/* Checksum */
|
||||
u8 checksum;
|
||||
} __attribute__((packed));
|
||||
|
||||
#endif /* __DRM_EDID_H__ */
|
||||
201
linux-core/drm_fb.c
Normal file
201
linux-core/drm_fb.c
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Copyright © 2007 David Airlie
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* David Airlie
|
||||
*/
|
||||
/*
|
||||
* Modularization
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include "drmP.h"
|
||||
struct drmfb_par {
|
||||
struct drm_device *dev;
|
||||
struct drm_framebuffer *fb;
|
||||
};
|
||||
|
||||
static int drmfb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
||||
unsigned blue, unsigned transp,
|
||||
struct fb_info *info)
|
||||
{
|
||||
struct drmfb_par *par = info->par;
|
||||
struct drm_framebuffer *fb = par->fb;
|
||||
if (regno > 17)
|
||||
return 1;
|
||||
|
||||
if (regno < 16) {
|
||||
switch (fb->depth) {
|
||||
case 15:
|
||||
fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) |
|
||||
((green & 0xf800) >> 6) |
|
||||
((blue & 0xf800) >> 11);
|
||||
break;
|
||||
case 16:
|
||||
fb->pseudo_palette[regno] = (red & 0xf800) |
|
||||
((green & 0xfc00) >> 5) |
|
||||
((blue & 0xf800) >> 11);
|
||||
break;
|
||||
case 24:
|
||||
case 32:
|
||||
fb->pseudo_palette[regno] = ((red & 0xff00) << 8) |
|
||||
(green & 0xff00) |
|
||||
((blue & 0xff00) >> 8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this will let fbcon do the mode init */
|
||||
static int drmfb_set_par(struct fb_info *info)
|
||||
{
|
||||
struct drmfb_par *par = info->par;
|
||||
struct drm_device *dev = par->dev;
|
||||
|
||||
drm_set_desired_modes(dev);
|
||||
}
|
||||
|
||||
static struct fb_ops drmfb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
// .fb_open = drmfb_open,
|
||||
// .fb_read = drmfb_read,
|
||||
// .fb_write = drmfb_write,
|
||||
// .fb_release = drmfb_release,
|
||||
// .fb_ioctl = drmfb_ioctl,
|
||||
.fb_set_par = drmfb_set_par,
|
||||
.fb_setcolreg = drmfb_setcolreg,
|
||||
.fb_fillrect = cfb_fillrect,
|
||||
.fb_copyarea = cfb_copyarea,
|
||||
.fb_imageblit = cfb_imageblit,
|
||||
};
|
||||
|
||||
int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb)
|
||||
{
|
||||
struct fb_info *info;
|
||||
struct drmfb_par *par;
|
||||
struct device *device = &dev->pdev->dev;
|
||||
struct fb_var_screeninfo *var_info;
|
||||
unsigned long base, size;
|
||||
|
||||
info = framebuffer_alloc(sizeof(struct drmfb_par), device);
|
||||
if (!info){
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fb->fbdev = info;
|
||||
|
||||
par = info->par;
|
||||
|
||||
par->dev = dev;
|
||||
par->fb = fb;
|
||||
|
||||
info->fbops = &drmfb_ops;
|
||||
|
||||
strcpy(info->fix.id, "drmfb");
|
||||
info->fix.smem_start = fb->offset + dev->mode_config.fb_base;
|
||||
info->fix.smem_len = (8*1024*1024);
|
||||
info->fix.type = FB_TYPE_PACKED_PIXELS;
|
||||
info->fix.visual = FB_VISUAL_DIRECTCOLOR;
|
||||
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->flags = FBINFO_DEFAULT;
|
||||
|
||||
base = fb->bo->offset + dev->mode_config.fb_base;
|
||||
size = (fb->bo->mem.num_pages * PAGE_SIZE);
|
||||
|
||||
DRM_DEBUG("remapping %08X %d\n", base, size);
|
||||
fb->virtual_base = ioremap_nocache(base, size);
|
||||
|
||||
info->screen_base = fb->virtual_base;
|
||||
info->screen_size = size;
|
||||
info->pseudo_palette = fb->pseudo_palette;
|
||||
info->var.xres = fb->width;
|
||||
info->var.xres_virtual = fb->pitch;
|
||||
info->var.yres = fb->height;
|
||||
info->var.yres_virtual = fb->height;
|
||||
info->var.bits_per_pixel = fb->bits_per_pixel;
|
||||
info->var.xoffset = 0;
|
||||
info->var.yoffset = 0;
|
||||
info->var.activate = FB_ACTIVATE_NOW;
|
||||
info->var.height = -1;
|
||||
info->var.width = -1;
|
||||
info->var.vmode = FB_VMODE_NONINTERLACED;
|
||||
|
||||
DRM_DEBUG("fb depth is %d\n", fb->depth);
|
||||
switch(fb->depth) {
|
||||
case 8:
|
||||
case 15:
|
||||
case 16:
|
||||
break;
|
||||
default:
|
||||
case 24:
|
||||
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;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (register_framebuffer(info) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
|
||||
info->fix.id);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drmfb_probe);
|
||||
|
||||
int drmfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
|
||||
{
|
||||
struct fb_info *info = fb->fbdev;
|
||||
|
||||
if (info) {
|
||||
iounmap(fb->virtual_base);
|
||||
unregister_framebuffer(info);
|
||||
framebuffer_release(info);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drmfb_remove);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
static int drm_open_helper(struct inode *inode, struct file *filp,
|
||||
drm_device_t * dev);
|
||||
|
||||
static int drm_setup(drm_device_t * dev)
|
||||
int drm_setup(drm_device_t * dev)
|
||||
{
|
||||
drm_local_map_t *map;
|
||||
int i;
|
||||
|
|
@ -121,6 +121,7 @@ static int drm_setup(drm_device_t * dev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_setup);
|
||||
|
||||
/**
|
||||
* Open file.
|
||||
|
|
|
|||
338
linux-core/drm_modes.c
Normal file
338
linux-core/drm_modes.c
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
/*
|
||||
* Copyright © 1997-2003 by The XFree86 Project, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
|
||||
*
|
||||
* Except as contained in this notice, the name of the copyright holder(s)
|
||||
* and author(s) shall not be used in advertising or otherwise to promote
|
||||
* the sale, use or other dealings in this Software without prior written
|
||||
* authorization from the copyright holder(s) and author(s).
|
||||
*/
|
||||
/*
|
||||
* Copyright © 2007 Dave Airlie
|
||||
*/
|
||||
|
||||
#include <linux/list.h>
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "drm_crtc.h"
|
||||
|
||||
void drm_mode_debug_printmodeline(struct drm_device *dev,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
DRM_DEBUG("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d\n",
|
||||
mode->mode_id, mode->name, mode->vrefresh / 1000, mode->clock,
|
||||
mode->hdisplay, mode->hsync_start,
|
||||
mode->hsync_end, mode->htotal,
|
||||
mode->vdisplay, mode->vsync_start,
|
||||
mode->vsync_end, mode->vtotal);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_debug_printmodeline);
|
||||
|
||||
void drm_mode_list_concat(struct list_head *head, struct list_head *new)
|
||||
{
|
||||
|
||||
struct list_head *entry, *tmp;
|
||||
|
||||
list_for_each_safe(entry, tmp, head) {
|
||||
list_move_tail(entry, new);
|
||||
}
|
||||
}
|
||||
|
||||
int drm_mode_width(struct drm_display_mode *mode)
|
||||
{
|
||||
return mode->hdisplay;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_width);
|
||||
|
||||
int drm_mode_height(struct drm_display_mode *mode)
|
||||
{
|
||||
return mode->vdisplay;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_height);
|
||||
|
||||
int drm_mode_vrefresh(struct drm_display_mode *mode)
|
||||
{
|
||||
int refresh = 0;
|
||||
|
||||
if (mode->vrefresh > 0)
|
||||
refresh = mode->vrefresh;
|
||||
else if (mode->htotal > 0 && mode->vtotal > 0) {
|
||||
refresh = ((mode->clock * 1000) * 1000) / mode->htotal / mode->vtotal;
|
||||
if (mode->flags & V_INTERLACE)
|
||||
refresh *= 2;
|
||||
if (mode->flags & V_DBLSCAN)
|
||||
refresh /= 2;
|
||||
if (mode->vscan > 1)
|
||||
refresh /= mode->vscan;
|
||||
}
|
||||
return refresh;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_vrefresh);
|
||||
|
||||
|
||||
void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)
|
||||
{
|
||||
if ((p == NULL) || ((p->type & DRM_MODE_TYPE_CRTC_C) == DRM_MODE_TYPE_BUILTIN))
|
||||
return;
|
||||
|
||||
p->crtc_hdisplay = p->hdisplay;
|
||||
p->crtc_hsync_start = p->hsync_start;
|
||||
p->crtc_hsync_end = p->hsync_end;
|
||||
p->crtc_htotal = p->htotal;
|
||||
p->crtc_hskew = p->hskew;
|
||||
p->crtc_vdisplay = p->vdisplay;
|
||||
p->crtc_vsync_start = p->vsync_start;
|
||||
p->crtc_vsync_end = p->vsync_end;
|
||||
p->crtc_vtotal = p->vtotal;
|
||||
|
||||
if (p->flags & V_INTERLACE) {
|
||||
if (adjust_flags & CRTC_INTERLACE_HALVE_V) {
|
||||
p->crtc_vdisplay /= 2;
|
||||
p->crtc_vsync_start /= 2;
|
||||
p->crtc_vsync_end /= 2;
|
||||
p->crtc_vtotal /= 2;
|
||||
}
|
||||
|
||||
p->crtc_vtotal |= 1;
|
||||
}
|
||||
|
||||
if (p->flags & V_DBLSCAN) {
|
||||
p->crtc_vdisplay *= 2;
|
||||
p->crtc_vsync_start *= 2;
|
||||
p->crtc_vsync_end *= 2;
|
||||
p->crtc_vtotal *= 2;
|
||||
}
|
||||
|
||||
if (p->vscan > 1) {
|
||||
p->crtc_vdisplay *= p->vscan;
|
||||
p->crtc_vsync_start *= p->vscan;
|
||||
p->crtc_vsync_end *= p->vscan;
|
||||
p->crtc_vtotal *= p->vscan;
|
||||
}
|
||||
|
||||
p->crtc_vblank_start = min(p->crtc_vsync_start, p->crtc_vdisplay);
|
||||
p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal);
|
||||
p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay);
|
||||
p->crtc_hblank_end = max(p->crtc_hsync_end, p->crtc_htotal);
|
||||
|
||||
p->crtc_hadjusted = false;
|
||||
p->crtc_vadjusted = false;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_set_crtcinfo);
|
||||
|
||||
|
||||
/**
|
||||
* drm_mode_duplicate - allocate and duplicate an existing mode
|
||||
* @m: mode to duplicate
|
||||
*
|
||||
* Just allocate a new mode, copy the existing mode into it, and return
|
||||
* a pointer to it. Used to create new instances of established modes.
|
||||
*/
|
||||
struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_display_mode *nmode;
|
||||
int new_id;
|
||||
|
||||
nmode = drm_crtc_mode_create(dev);
|
||||
if (!nmode)
|
||||
return NULL;
|
||||
|
||||
new_id = nmode->mode_id;
|
||||
*nmode = *mode;
|
||||
nmode->mode_id = new_id;
|
||||
INIT_LIST_HEAD(&nmode->head);
|
||||
return nmode;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_duplicate);
|
||||
|
||||
bool drm_mode_equal(struct drm_display_mode *mode1, struct drm_display_mode *mode2)
|
||||
{
|
||||
if (mode1->clock == mode2->clock &&
|
||||
mode1->hdisplay == mode2->hdisplay &&
|
||||
mode1->hsync_start == mode2->hsync_start &&
|
||||
mode1->hsync_end == mode2->hsync_end &&
|
||||
mode1->htotal == mode2->htotal &&
|
||||
mode1->hskew == mode2->hskew &&
|
||||
mode1->vdisplay == mode2->vdisplay &&
|
||||
mode1->vsync_start == mode2->vsync_start &&
|
||||
mode1->vsync_end == mode2->vsync_end &&
|
||||
mode1->vtotal == mode2->vtotal &&
|
||||
mode1->vscan == mode2->vscan &&
|
||||
mode1->flags == mode2->flags)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_equal);
|
||||
|
||||
void drm_mode_validate_size(struct drm_device *dev,
|
||||
struct list_head *mode_list,
|
||||
int maxX, int maxY, int maxPitch)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
list_for_each_entry(mode, mode_list, head) {
|
||||
if (maxPitch > 0 && mode->hdisplay > maxPitch)
|
||||
mode->status = MODE_BAD_WIDTH;
|
||||
|
||||
if (maxX > 0 && mode->hdisplay > maxX)
|
||||
mode->status = MODE_VIRTUAL_X;
|
||||
|
||||
if (maxY > 0 && mode->vdisplay > maxY)
|
||||
mode->status = MODE_VIRTUAL_Y;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_validate_size);
|
||||
|
||||
void drm_mode_validate_clocks(struct drm_device *dev,
|
||||
struct list_head *mode_list,
|
||||
int *min, int *max, int n_ranges)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
int i;
|
||||
|
||||
list_for_each_entry(mode, mode_list, head) {
|
||||
bool good = false;
|
||||
for (i = 0; i < n_ranges; i++) {
|
||||
if (mode->clock >= min[i] && mode->clock <= max[i]) {
|
||||
good = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!good)
|
||||
mode->status = MODE_CLOCK_RANGE;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_validate_clocks);
|
||||
|
||||
void drm_mode_prune_invalid(struct drm_device *dev,
|
||||
struct list_head *mode_list, bool verbose)
|
||||
{
|
||||
struct drm_display_mode *mode, *t;
|
||||
|
||||
list_for_each_entry_safe(mode, t, mode_list, head) {
|
||||
if (mode->status != MODE_OK) {
|
||||
list_del(&mode->head);
|
||||
if (verbose)
|
||||
DRM_DEBUG("Not using %s mode %d\n", mode->name, mode->status);
|
||||
kfree(mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int drm_mode_compare(struct list_head *lh_a, struct list_head *lh_b)
|
||||
{
|
||||
struct drm_display_mode *a = list_entry(lh_a, struct drm_display_mode, head);
|
||||
struct drm_display_mode *b = list_entry(lh_b, struct drm_display_mode, head);
|
||||
int diff;
|
||||
|
||||
diff = ((b->type & DRM_MODE_TYPE_PREFERRED) != 0) -
|
||||
((a->type & DRM_MODE_TYPE_PREFERRED) != 0);
|
||||
if (diff)
|
||||
return diff;
|
||||
diff = b->hdisplay * b->vdisplay - a->hdisplay * a->vdisplay;
|
||||
if (diff)
|
||||
return diff;
|
||||
diff = b->clock - a->clock;
|
||||
return diff;
|
||||
}
|
||||
|
||||
/* list sort from Mark J Roberts (mjr@znex.org) */
|
||||
void list_sort(struct list_head *head, int (*cmp)(struct list_head *a, struct list_head *b))
|
||||
{
|
||||
struct list_head *p, *q, *e, *list, *tail, *oldhead;
|
||||
int insize, nmerges, psize, qsize, i;
|
||||
|
||||
list = head->next;
|
||||
list_del(head);
|
||||
insize = 1;
|
||||
for (;;) {
|
||||
p = oldhead = list;
|
||||
list = tail = NULL;
|
||||
nmerges = 0;
|
||||
|
||||
while (p) {
|
||||
nmerges++;
|
||||
q = p;
|
||||
psize = 0;
|
||||
for (i = 0; i < insize; i++) {
|
||||
psize++;
|
||||
q = q->next == oldhead ? NULL : q->next;
|
||||
if (!q)
|
||||
break;
|
||||
}
|
||||
|
||||
qsize = insize;
|
||||
while (psize > 0 || (qsize > 0 && q)) {
|
||||
if (!psize) {
|
||||
e = q;
|
||||
q = q->next;
|
||||
qsize--;
|
||||
if (q == oldhead)
|
||||
q = NULL;
|
||||
} else if (!qsize || !q) {
|
||||
e = p;
|
||||
p = p->next;
|
||||
psize--;
|
||||
if (p == oldhead)
|
||||
p = NULL;
|
||||
} else if (cmp(p, q) <= 0) {
|
||||
e = p;
|
||||
p = p->next;
|
||||
psize--;
|
||||
if (p == oldhead)
|
||||
p = NULL;
|
||||
} else {
|
||||
e = q;
|
||||
q = q->next;
|
||||
qsize--;
|
||||
if (q == oldhead)
|
||||
q = NULL;
|
||||
}
|
||||
if (tail)
|
||||
tail->next = e;
|
||||
else
|
||||
list = e;
|
||||
e->prev = tail;
|
||||
tail = e;
|
||||
}
|
||||
p = q;
|
||||
}
|
||||
|
||||
tail->next = list;
|
||||
list->prev = tail;
|
||||
|
||||
if (nmerges <= 1)
|
||||
break;
|
||||
|
||||
insize *= 2;
|
||||
}
|
||||
|
||||
head->next = list;
|
||||
head->prev = list->prev;
|
||||
list->prev->next = head;
|
||||
list->prev = head;
|
||||
}
|
||||
|
||||
void drm_mode_sort(struct list_head *mode_list)
|
||||
{
|
||||
list_sort(mode_list, drm_mode_compare);
|
||||
}
|
||||
138
linux-core/edid.h
Normal file
138
linux-core/edid.h
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* drivers/video/edid.h - EDID/DDC Header
|
||||
*
|
||||
* Based on:
|
||||
* 1. XFree86 4.3.0, edid.h
|
||||
* Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
|
||||
*
|
||||
* 2. John Fremlin <vii@users.sourceforge.net> and
|
||||
* Ani Joshi <ajoshi@unixbox.com>
|
||||
*
|
||||
* DDC is a Trademark of VESA (Video Electronics Standard Association).
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#ifndef __EDID_H__
|
||||
#define __EDID_H__
|
||||
|
||||
#define EDID_LENGTH 0x80
|
||||
#define EDID_HEADER 0x00
|
||||
#define EDID_HEADER_END 0x07
|
||||
|
||||
#define ID_MANUFACTURER_NAME 0x08
|
||||
#define ID_MANUFACTURER_NAME_END 0x09
|
||||
#define ID_MODEL 0x0a
|
||||
|
||||
#define ID_SERIAL_NUMBER 0x0c
|
||||
|
||||
#define MANUFACTURE_WEEK 0x10
|
||||
#define MANUFACTURE_YEAR 0x11
|
||||
|
||||
#define EDID_STRUCT_VERSION 0x12
|
||||
#define EDID_STRUCT_REVISION 0x13
|
||||
|
||||
#define EDID_STRUCT_DISPLAY 0x14
|
||||
|
||||
#define DPMS_FLAGS 0x18
|
||||
#define ESTABLISHED_TIMING_1 0x23
|
||||
#define ESTABLISHED_TIMING_2 0x24
|
||||
#define MANUFACTURERS_TIMINGS 0x25
|
||||
|
||||
/* standard timings supported */
|
||||
#define STD_TIMING 8
|
||||
#define STD_TIMING_DESCRIPTION_SIZE 2
|
||||
#define STD_TIMING_DESCRIPTIONS_START 0x26
|
||||
|
||||
#define DETAILED_TIMING_DESCRIPTIONS_START 0x36
|
||||
#define DETAILED_TIMING_DESCRIPTION_SIZE 18
|
||||
#define NO_DETAILED_TIMING_DESCRIPTIONS 4
|
||||
|
||||
#define DETAILED_TIMING_DESCRIPTION_1 0x36
|
||||
#define DETAILED_TIMING_DESCRIPTION_2 0x48
|
||||
#define DETAILED_TIMING_DESCRIPTION_3 0x5a
|
||||
#define DETAILED_TIMING_DESCRIPTION_4 0x6c
|
||||
|
||||
#define DESCRIPTOR_DATA 5
|
||||
|
||||
#define UPPER_NIBBLE( x ) \
|
||||
(((128|64|32|16) & (x)) >> 4)
|
||||
|
||||
#define LOWER_NIBBLE( x ) \
|
||||
((1|2|4|8) & (x))
|
||||
|
||||
#define COMBINE_HI_8LO( hi, lo ) \
|
||||
( (((unsigned)hi) << 8) | (unsigned)lo )
|
||||
|
||||
#define COMBINE_HI_4LO( hi, lo ) \
|
||||
( (((unsigned)hi) << 4) | (unsigned)lo )
|
||||
|
||||
#define PIXEL_CLOCK_LO (unsigned)block[ 0 ]
|
||||
#define PIXEL_CLOCK_HI (unsigned)block[ 1 ]
|
||||
#define PIXEL_CLOCK (COMBINE_HI_8LO( PIXEL_CLOCK_HI,PIXEL_CLOCK_LO )*10000)
|
||||
#define H_ACTIVE_LO (unsigned)block[ 2 ]
|
||||
#define H_BLANKING_LO (unsigned)block[ 3 ]
|
||||
#define H_ACTIVE_HI UPPER_NIBBLE( (unsigned)block[ 4 ] )
|
||||
#define H_ACTIVE COMBINE_HI_8LO( H_ACTIVE_HI, H_ACTIVE_LO )
|
||||
#define H_BLANKING_HI LOWER_NIBBLE( (unsigned)block[ 4 ] )
|
||||
#define H_BLANKING COMBINE_HI_8LO( H_BLANKING_HI, H_BLANKING_LO )
|
||||
|
||||
#define V_ACTIVE_LO (unsigned)block[ 5 ]
|
||||
#define V_BLANKING_LO (unsigned)block[ 6 ]
|
||||
#define V_ACTIVE_HI UPPER_NIBBLE( (unsigned)block[ 7 ] )
|
||||
#define V_ACTIVE COMBINE_HI_8LO( V_ACTIVE_HI, V_ACTIVE_LO )
|
||||
#define V_BLANKING_HI LOWER_NIBBLE( (unsigned)block[ 7 ] )
|
||||
#define V_BLANKING COMBINE_HI_8LO( V_BLANKING_HI, V_BLANKING_LO )
|
||||
|
||||
#define H_SYNC_OFFSET_LO (unsigned)block[ 8 ]
|
||||
#define H_SYNC_WIDTH_LO (unsigned)block[ 9 ]
|
||||
|
||||
#define V_SYNC_OFFSET_LO UPPER_NIBBLE( (unsigned)block[ 10 ] )
|
||||
#define V_SYNC_WIDTH_LO LOWER_NIBBLE( (unsigned)block[ 10 ] )
|
||||
|
||||
#define V_SYNC_WIDTH_HI ((unsigned)block[ 11 ] & (1|2))
|
||||
#define V_SYNC_OFFSET_HI (((unsigned)block[ 11 ] & (4|8)) >> 2)
|
||||
|
||||
#define H_SYNC_WIDTH_HI (((unsigned)block[ 11 ] & (16|32)) >> 4)
|
||||
#define H_SYNC_OFFSET_HI (((unsigned)block[ 11 ] & (64|128)) >> 6)
|
||||
|
||||
#define V_SYNC_WIDTH COMBINE_HI_4LO( V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO )
|
||||
#define V_SYNC_OFFSET COMBINE_HI_4LO( V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO )
|
||||
|
||||
#define H_SYNC_WIDTH COMBINE_HI_4LO( H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO )
|
||||
#define H_SYNC_OFFSET COMBINE_HI_4LO( H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO )
|
||||
|
||||
#define H_SIZE_LO (unsigned)block[ 12 ]
|
||||
#define V_SIZE_LO (unsigned)block[ 13 ]
|
||||
|
||||
#define H_SIZE_HI UPPER_NIBBLE( (unsigned)block[ 14 ] )
|
||||
#define V_SIZE_HI LOWER_NIBBLE( (unsigned)block[ 14 ] )
|
||||
|
||||
#define H_SIZE COMBINE_HI_8LO( H_SIZE_HI, H_SIZE_LO )
|
||||
#define V_SIZE COMBINE_HI_8LO( V_SIZE_HI, V_SIZE_LO )
|
||||
|
||||
#define H_BORDER (unsigned)block[ 15 ]
|
||||
#define V_BORDER (unsigned)block[ 16 ]
|
||||
|
||||
#define FLAGS (unsigned)block[ 17 ]
|
||||
|
||||
#define INTERLACED (FLAGS&128)
|
||||
#define SYNC_TYPE (FLAGS&3<<3) /* bits 4,3 */
|
||||
#define SYNC_SEPARATE (3<<3)
|
||||
#define HSYNC_POSITIVE (FLAGS & 4)
|
||||
#define VSYNC_POSITIVE (FLAGS & 2)
|
||||
|
||||
#define V_MIN_RATE block[ 5 ]
|
||||
#define V_MAX_RATE block[ 6 ]
|
||||
#define H_MIN_RATE block[ 7 ]
|
||||
#define H_MAX_RATE block[ 8 ]
|
||||
#define MAX_PIXEL_CLOCK (((int)block[ 9 ]) * 10)
|
||||
#define GTF_SUPPORT block[10]
|
||||
|
||||
#define DPMS_ACTIVE_OFF (1 << 5)
|
||||
#define DPMS_SUSPEND (1 << 6)
|
||||
#define DPMS_STANDBY (1 << 7)
|
||||
|
||||
#endif /* __EDID_H__ */
|
||||
|
|
@ -79,6 +79,7 @@ static struct drm_driver driver = {
|
|||
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL |
|
||||
DRIVER_IRQ_VBL2,
|
||||
.load = i915_driver_load,
|
||||
.unload = i915_driver_unload,
|
||||
.firstopen = i915_driver_firstopen,
|
||||
.lastclose = i915_driver_lastclose,
|
||||
.preclose = i915_driver_preclose,
|
||||
|
|
|
|||
1
linux-core/i915_init.c
Symbolic link
1
linux-core/i915_init.c
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../shared-core/i915_init.c
|
||||
269
linux-core/intel_crt.c
Normal file
269
linux-core/intel_crt.c
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
/*
|
||||
* Copyright © 2006-2007 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "drm_crtc.h"
|
||||
#include "intel_drv.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
static void intel_crt_dpms(struct drm_output *output, int mode)
|
||||
{
|
||||
drm_device_t *dev = output->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
u32 temp;
|
||||
|
||||
temp = I915_READ(ADPA);
|
||||
temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
|
||||
temp &= ~ADPA_DAC_ENABLE;
|
||||
|
||||
switch(mode) {
|
||||
case DPMSModeOn:
|
||||
temp |= ADPA_DAC_ENABLE;
|
||||
break;
|
||||
case DPMSModeStandby:
|
||||
temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE;
|
||||
break;
|
||||
case DPMSModeSuspend:
|
||||
temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE;
|
||||
break;
|
||||
case DPMSModeOff:
|
||||
temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
|
||||
break;
|
||||
}
|
||||
|
||||
I915_WRITE(ADPA, temp);
|
||||
}
|
||||
|
||||
static void intel_crt_save(struct drm_output *output)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void intel_crt_restore(struct drm_output *output)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static int intel_crt_mode_valid(struct drm_output *output,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
if (mode->flags & V_DBLSCAN)
|
||||
return MODE_NO_DBLESCAN;
|
||||
|
||||
if (mode->clock > 400000 || mode->clock < 25000)
|
||||
return MODE_CLOCK_RANGE;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static bool intel_crt_mode_fixup(struct drm_output *output,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void intel_crt_mode_set(struct drm_output *output,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
drm_device_t *dev = output->dev;
|
||||
struct drm_crtc *crtc = output->crtc;
|
||||
struct intel_crtc *intel_crtc = crtc->driver_private;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int dpll_md_reg;
|
||||
u32 adpa, dpll_md;
|
||||
|
||||
if (intel_crtc->pipe == 0)
|
||||
dpll_md_reg = DPLL_A_MD;
|
||||
else
|
||||
dpll_md_reg = DPLL_B_MD;
|
||||
|
||||
/*
|
||||
* Disable separate mode multiplier used when cloning SDVO to CRT
|
||||
* XXX this needs to be adjusted when we really are cloning
|
||||
*/
|
||||
if (IS_I965G(dev)) {
|
||||
dpll_md = I915_READ(dpll_md_reg);
|
||||
I915_WRITE(dpll_md_reg,
|
||||
dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
|
||||
}
|
||||
|
||||
adpa = 0;
|
||||
if (adjusted_mode->flags & V_PHSYNC)
|
||||
adpa |= ADPA_HSYNC_ACTIVE_HIGH;
|
||||
if (adjusted_mode->flags & V_PVSYNC)
|
||||
adpa |= ADPA_VSYNC_ACTIVE_HIGH;
|
||||
|
||||
if (intel_crtc->pipe == 0)
|
||||
adpa |= ADPA_PIPE_A_SELECT;
|
||||
else
|
||||
adpa |= ADPA_PIPE_B_SELECT;
|
||||
|
||||
I915_WRITE(ADPA, adpa);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
|
||||
*
|
||||
* Only for I945G/GM.
|
||||
*
|
||||
* \return TRUE if CRT is connected.
|
||||
* \return FALSE if CRT is disconnected.
|
||||
*/
|
||||
static bool intel_crt_detect_hotplug(struct drm_output *output)
|
||||
{
|
||||
drm_device_t *dev = output->dev;
|
||||
// struct intel_output *intel_output = output->driver_private;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
u32 temp;
|
||||
// const int timeout_ms = 1000;
|
||||
// int starttime, curtime;
|
||||
|
||||
temp = I915_READ(PORT_HOTPLUG_EN);
|
||||
|
||||
I915_WRITE(PORT_HOTPLUG_EN, temp | CRT_HOTPLUG_FORCE_DETECT | (1 << 5));
|
||||
#if 0
|
||||
for (curtime = starttime = GetTimeInMillis();
|
||||
(curtime - starttime) < timeout_ms; curtime = GetTimeInMillis())
|
||||
{
|
||||
if ((I915_READ(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT) == 0)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if ((I915_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) ==
|
||||
CRT_HOTPLUG_MONITOR_COLOR)
|
||||
{
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool intel_crt_detect_ddc(struct drm_output *output)
|
||||
{
|
||||
struct intel_output *intel_output = output->driver_private;
|
||||
|
||||
/* CRT should always be at 0, but check anyway */
|
||||
if (intel_output->type != INTEL_OUTPUT_ANALOG)
|
||||
return false;
|
||||
|
||||
return intel_ddc_probe(output);
|
||||
}
|
||||
|
||||
static enum drm_output_status intel_crt_detect(struct drm_output *output)
|
||||
{
|
||||
drm_device_t *dev = output->dev;
|
||||
struct intel_output *intel_output = output->driver_private;
|
||||
|
||||
if (IS_I945G(dev)| IS_I945GM(dev) || IS_I965G(dev)) {
|
||||
if (intel_crt_detect_hotplug(output))
|
||||
return output_status_connected;
|
||||
else
|
||||
return output_status_disconnected;
|
||||
}
|
||||
|
||||
/* Set up the DDC bus. */
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, GPIOA, "CRTDDC_A");
|
||||
if (!intel_output->ddc_bus) {
|
||||
dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
|
||||
"failed.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (intel_crt_detect_ddc(output)) {
|
||||
intel_i2c_destroy(intel_output->ddc_bus);
|
||||
return output_status_connected;
|
||||
}
|
||||
|
||||
intel_i2c_destroy(intel_output->ddc_bus);
|
||||
/* TODO use load detect */
|
||||
return output_status_unknown;
|
||||
}
|
||||
|
||||
static void intel_crt_destroy(struct drm_output *output)
|
||||
{
|
||||
if (output->driver_private)
|
||||
kfree(output->driver_private);
|
||||
}
|
||||
|
||||
static int intel_crt_get_modes(struct drm_output *output)
|
||||
{
|
||||
struct drm_device *dev = output->dev;
|
||||
struct intel_output *intel_output = output->driver_private;
|
||||
int ret;
|
||||
|
||||
/* Set up the DDC bus. */
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, GPIOA, "CRTDDC_A");
|
||||
if (!intel_output->ddc_bus) {
|
||||
dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
|
||||
"failed.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = intel_ddc_get_modes(output);
|
||||
intel_i2c_destroy(intel_output->ddc_bus);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Routines for controlling stuff on the analog port
|
||||
*/
|
||||
static const struct drm_output_funcs intel_crt_output_funcs = {
|
||||
.dpms = intel_crt_dpms,
|
||||
.save = intel_crt_save,
|
||||
.restore = intel_crt_restore,
|
||||
.mode_valid = intel_crt_mode_valid,
|
||||
.mode_fixup = intel_crt_mode_fixup,
|
||||
.prepare = intel_output_prepare,
|
||||
.mode_set = intel_crt_mode_set,
|
||||
.commit = intel_output_commit,
|
||||
.detect = intel_crt_detect,
|
||||
.get_modes = intel_crt_get_modes,
|
||||
.cleanup = intel_crt_destroy,
|
||||
};
|
||||
|
||||
void intel_crt_init(drm_device_t *dev)
|
||||
{
|
||||
struct drm_output *output;
|
||||
struct intel_output *intel_output;
|
||||
|
||||
output = drm_output_create(dev, &intel_crt_output_funcs, "VGA");
|
||||
|
||||
intel_output = kmalloc(sizeof(struct intel_output), GFP_KERNEL);
|
||||
if (!intel_output) {
|
||||
drm_output_destroy(output);
|
||||
return;
|
||||
}
|
||||
|
||||
intel_output->type = INTEL_OUTPUT_ANALOG;
|
||||
output->driver_private = intel_output;
|
||||
output->interlace_allowed = 0;
|
||||
output->doublescan_allowed = 0;
|
||||
}
|
||||
1203
linux-core/intel_display.c
Normal file
1203
linux-core/intel_display.c
Normal file
File diff suppressed because it is too large
Load diff
78
linux-core/intel_drv.h
Normal file
78
linux-core/intel_drv.h
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
|
||||
* Copyright (c) 2007 Intel Corporation
|
||||
* Jesse Barnes <jesse.barnes@intel.com>
|
||||
*/
|
||||
#ifndef __INTEL_DRV_H__
|
||||
#define __INTEL_DRV_H__
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-id.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
#include "drm_crtc.h"
|
||||
|
||||
/*
|
||||
* Display related stuff
|
||||
*/
|
||||
|
||||
/* store information about an Ixxx DVO */
|
||||
/* The i830->i865 use multiple DVOs with multiple i2cs */
|
||||
/* the i915, i945 have a single sDVO i2c bus - which is different */
|
||||
#define MAX_OUTPUTS 6
|
||||
|
||||
#define INTEL_I2C_BUS_DVO 1
|
||||
#define INTEL_I2C_BUS_SDVO 2
|
||||
|
||||
/* these are outputs from the chip - integrated only
|
||||
external chips are via DVO or SDVO output */
|
||||
#define INTEL_OUTPUT_UNUSED 0
|
||||
#define INTEL_OUTPUT_ANALOG 1
|
||||
#define INTEL_OUTPUT_DVO 2
|
||||
#define INTEL_OUTPUT_SDVO 3
|
||||
#define INTEL_OUTPUT_LVDS 4
|
||||
#define INTEL_OUTPUT_TVOUT 5
|
||||
|
||||
#define INTEL_DVO_CHIP_NONE 0
|
||||
#define INTEL_DVO_CHIP_LVDS 1
|
||||
#define INTEL_DVO_CHIP_TMDS 2
|
||||
#define INTEL_DVO_CHIP_TVOUT 4
|
||||
|
||||
struct intel_i2c_chan {
|
||||
drm_device_t *drm_dev; /* for getting at dev. private (mmio etc.) */
|
||||
u32 reg; /* GPIO reg */
|
||||
struct i2c_adapter adapter;
|
||||
struct i2c_algo_bit_data algo;
|
||||
u8 slave_addr;
|
||||
};
|
||||
|
||||
struct intel_output {
|
||||
int type;
|
||||
struct intel_i2c_chan *i2c_bus; /* for control functions */
|
||||
struct intel_i2c_chan *ddc_bus; /* for DDC only stuff */
|
||||
bool load_detect_tmp;
|
||||
void *dev_priv;
|
||||
};
|
||||
|
||||
struct intel_crtc {
|
||||
int pipe;
|
||||
u8 lut_r[256], lut_g[256], lut_b[256];
|
||||
};
|
||||
|
||||
struct intel_i2c_chan *intel_i2c_create(drm_device_t *dev, const u32 reg,
|
||||
const char *name);
|
||||
void intel_i2c_destroy(struct intel_i2c_chan *chan);
|
||||
int intel_ddc_get_modes(struct drm_output *output);
|
||||
extern bool intel_ddc_probe(struct drm_output *output);
|
||||
|
||||
extern void intel_crt_init(drm_device_t *dev);
|
||||
extern void intel_sdvo_init(drm_device_t *dev, int output_device);
|
||||
extern void intel_lvds_init(drm_device_t *dev);
|
||||
|
||||
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);
|
||||
extern void intel_wait_for_vblank(drm_device_t *dev);
|
||||
|
||||
#endif /* __INTEL_DRV_H__ */
|
||||
187
linux-core/intel_i2c.c
Normal file
187
linux-core/intel_i2c.c
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* Copyright © 2006-2007 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
|
||||
* Jesse Barnes <jesse.barnes@intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-id.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "intel_drv.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
/*
|
||||
* Intel GPIO access functions
|
||||
*/
|
||||
|
||||
#define I2C_RISEFALL_TIME 20
|
||||
|
||||
static int get_clock(void *data)
|
||||
{
|
||||
struct intel_i2c_chan *chan = data;
|
||||
drm_i915_private_t *dev_priv = chan->drm_dev->dev_private;
|
||||
u32 val;
|
||||
|
||||
val = I915_READ(chan->reg);
|
||||
return ((val & GPIO_CLOCK_VAL_IN) != 0);
|
||||
}
|
||||
|
||||
static int get_data(void *data)
|
||||
{
|
||||
struct intel_i2c_chan *chan = data;
|
||||
drm_i915_private_t *dev_priv = chan->drm_dev->dev_private;
|
||||
u32 val;
|
||||
|
||||
val = I915_READ(chan->reg);
|
||||
return ((val & GPIO_DATA_VAL_IN) != 0);
|
||||
}
|
||||
|
||||
static void set_clock(void *data, int state_high)
|
||||
{
|
||||
struct intel_i2c_chan *chan = data;
|
||||
drm_device_t *dev = chan->drm_dev;
|
||||
drm_i915_private_t *dev_priv = chan->drm_dev->dev_private;
|
||||
u32 reserved = 0, clock_bits;
|
||||
|
||||
/* On most chips, these bits must be preserved in software. */
|
||||
if (!IS_I830(dev) && !IS_845G(dev))
|
||||
reserved = I915_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
|
||||
GPIO_CLOCK_PULLUP_DISABLE);
|
||||
|
||||
if (state_high)
|
||||
clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK;
|
||||
else
|
||||
clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
|
||||
GPIO_CLOCK_VAL_MASK;
|
||||
I915_WRITE(chan->reg, reserved | clock_bits);
|
||||
udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */
|
||||
}
|
||||
|
||||
static void set_data(void *data, int state_high)
|
||||
{
|
||||
struct intel_i2c_chan *chan = data;
|
||||
drm_device_t *dev = chan->drm_dev;
|
||||
drm_i915_private_t *dev_priv = chan->drm_dev->dev_private;
|
||||
u32 reserved = 0, data_bits;
|
||||
|
||||
/* On most chips, these bits must be preserved in software. */
|
||||
if (!IS_I830(dev) && !IS_845G(dev))
|
||||
reserved = I915_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
|
||||
GPIO_CLOCK_PULLUP_DISABLE);
|
||||
|
||||
if (state_high)
|
||||
data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK;
|
||||
else
|
||||
data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
|
||||
GPIO_DATA_VAL_MASK;
|
||||
|
||||
I915_WRITE(chan->reg, reserved | data_bits);
|
||||
udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg
|
||||
* @dev: DRM device
|
||||
* @output: driver specific output device
|
||||
* @reg: GPIO reg to use
|
||||
* @name: name for this bus
|
||||
*
|
||||
* Creates and registers a new i2c bus with the Linux i2c layer, for use
|
||||
* in output probing and control (e.g. DDC or SDVO control functions).
|
||||
*
|
||||
* Possible values for @reg include:
|
||||
* %GPIOA
|
||||
* %GPIOB
|
||||
* %GPIOC
|
||||
* %GPIOD
|
||||
* %GPIOE
|
||||
* %GPIOF
|
||||
* %GPIOG
|
||||
* %GPIOH
|
||||
* see PRM for details on how these different busses are used.
|
||||
*/
|
||||
struct intel_i2c_chan *intel_i2c_create(drm_device_t *dev, const u32 reg,
|
||||
const char *name)
|
||||
{
|
||||
struct intel_i2c_chan *chan;
|
||||
|
||||
chan = kzalloc(sizeof(struct intel_i2c_chan), GFP_KERNEL);
|
||||
if (!chan)
|
||||
goto out_free;
|
||||
|
||||
chan->drm_dev = dev;
|
||||
chan->reg = reg;
|
||||
snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name);
|
||||
chan->adapter.owner = THIS_MODULE;
|
||||
chan->adapter.id = I2C_HW_B_INTELFB;
|
||||
chan->adapter.algo_data = &chan->algo;
|
||||
chan->adapter.dev.parent = &dev->pdev->dev;
|
||||
chan->algo.setsda = set_data;
|
||||
chan->algo.setscl = set_clock;
|
||||
chan->algo.getsda = get_data;
|
||||
chan->algo.getscl = get_clock;
|
||||
chan->algo.udelay = 20;
|
||||
chan->algo.timeout = usecs_to_jiffies(2200);
|
||||
chan->algo.data = chan;
|
||||
|
||||
i2c_set_adapdata(&chan->adapter, chan);
|
||||
|
||||
if(i2c_bit_add_bus(&chan->adapter))
|
||||
goto out_free;
|
||||
|
||||
/* JJJ: raise SCL and SDA? */
|
||||
set_data(chan, 1);
|
||||
set_clock(chan, 1);
|
||||
udelay(20);
|
||||
|
||||
return chan;
|
||||
|
||||
out_free:
|
||||
kfree(chan);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_i2c_destroy - unregister and free i2c bus resources
|
||||
* @output: channel to free
|
||||
*
|
||||
* Unregister the adapter from the i2c layer, then free the structure.
|
||||
*/
|
||||
void intel_i2c_destroy(struct intel_i2c_chan *chan)
|
||||
{
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
i2c_del_adapter(&chan->adapter);
|
||||
kfree(chan);
|
||||
}
|
||||
|
||||
|
||||
|
||||
472
linux-core/intel_lvds.c
Normal file
472
linux-core/intel_lvds.c
Normal file
|
|
@ -0,0 +1,472 @@
|
|||
/*
|
||||
* Copyright © 2006-2007 Intel Corporation
|
||||
* Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
* Dave Airlie <airlied@linux.ie>
|
||||
* Jesse Barnes <jesse.barnes@intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "drm_crtc.h"
|
||||
#include "drm_edid.h"
|
||||
#include "intel_drv.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
/**
|
||||
* Sets the backlight level.
|
||||
*
|
||||
* \param level backlight level, from 0 to intel_lvds_get_max_backlight().
|
||||
*/
|
||||
static void intel_lvds_set_backlight(struct drm_device *dev, int level)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
u32 blc_pwm_ctl;
|
||||
|
||||
blc_pwm_ctl = I915_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
I915_WRITE(BLC_PWM_CTL, (blc_pwm_ctl |
|
||||
(level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum level of the backlight duty cycle field.
|
||||
*/
|
||||
static u32 intel_lvds_get_max_backlight(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
return ((I915_READ(BLC_PWM_CTL) & BACKLIGHT_MODULATION_FREQ_MASK) >>
|
||||
BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the power state for the panel.
|
||||
*/
|
||||
static void intel_lvds_set_power(struct drm_device *dev, bool on)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
u32 pp_status;
|
||||
|
||||
if (on) {
|
||||
I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) |
|
||||
POWER_TARGET_ON);
|
||||
do {
|
||||
pp_status = I915_READ(PP_STATUS);
|
||||
} while ((pp_status & PP_ON) == 0);
|
||||
|
||||
intel_lvds_set_backlight(dev, dev_priv->backlight_duty_cycle);
|
||||
} else {
|
||||
intel_lvds_set_backlight(dev, 0);
|
||||
|
||||
I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) &
|
||||
~POWER_TARGET_ON);
|
||||
do {
|
||||
pp_status = I915_READ(PP_STATUS);
|
||||
} while (pp_status & PP_ON);
|
||||
}
|
||||
}
|
||||
|
||||
static void intel_lvds_dpms(struct drm_output *output, int mode)
|
||||
{
|
||||
struct drm_device *dev = output->dev;
|
||||
|
||||
if (mode == DPMSModeOn)
|
||||
intel_lvds_set_power(dev, true);
|
||||
else
|
||||
intel_lvds_set_power(dev, false);
|
||||
|
||||
/* XXX: We never power down the LVDS pairs. */
|
||||
}
|
||||
|
||||
static void intel_lvds_save(struct drm_output *output)
|
||||
{
|
||||
struct drm_device *dev = output->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
dev_priv->savePP_ON = I915_READ(LVDSPP_ON);
|
||||
dev_priv->savePP_OFF = I915_READ(LVDSPP_OFF);
|
||||
dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL);
|
||||
dev_priv->savePP_CYCLE = I915_READ(PP_CYCLE);
|
||||
dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
|
||||
dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL &
|
||||
BACKLIGHT_DUTY_CYCLE_MASK);
|
||||
|
||||
/*
|
||||
* If the light is off at server startup, just make it full brightness
|
||||
*/
|
||||
if (dev_priv->backlight_duty_cycle == 0)
|
||||
dev_priv->backlight_duty_cycle =
|
||||
intel_lvds_get_max_backlight(dev);
|
||||
}
|
||||
|
||||
static void intel_lvds_restore(struct drm_output *output)
|
||||
{
|
||||
struct drm_device *dev = output->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
|
||||
I915_WRITE(LVDSPP_ON, dev_priv->savePP_ON);
|
||||
I915_WRITE(LVDSPP_OFF, dev_priv->savePP_OFF);
|
||||
I915_WRITE(PP_CYCLE, dev_priv->savePP_CYCLE);
|
||||
I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
|
||||
if (dev_priv->savePP_CONTROL & POWER_TARGET_ON)
|
||||
intel_lvds_set_power(dev, true);
|
||||
else
|
||||
intel_lvds_set_power(dev, false);
|
||||
}
|
||||
|
||||
static int intel_lvds_mode_valid(struct drm_output *output,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_device *dev = output->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_display_mode *fixed_mode = dev_priv->panel_fixed_mode;
|
||||
|
||||
if (fixed_mode) {
|
||||
if (mode->hdisplay > fixed_mode->hdisplay)
|
||||
return MODE_PANEL;
|
||||
if (mode->vdisplay > fixed_mode->vdisplay)
|
||||
return MODE_PANEL;
|
||||
}
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static bool intel_lvds_mode_fixup(struct drm_output *output,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct drm_device *dev = output->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = output->crtc->driver_private;
|
||||
struct drm_output *tmp_output;
|
||||
|
||||
#if 0 /* FIXME: Check for other outputs on this pipe */
|
||||
spin_lock(&dev->mode_config.config_lock);
|
||||
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 "
|
||||
"output on the same pipe\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
spin_lock(&dev->mode_config.config_lock);
|
||||
#endif
|
||||
|
||||
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,
|
||||
* with the panel scaling set up to source from the H/VDisplay
|
||||
* of the original mode.
|
||||
*/
|
||||
if (dev_priv->panel_fixed_mode != NULL) {
|
||||
adjusted_mode->hdisplay = dev_priv->panel_fixed_mode->hdisplay;
|
||||
adjusted_mode->hsync_start =
|
||||
dev_priv->panel_fixed_mode->hsync_start;
|
||||
adjusted_mode->hsync_end =
|
||||
dev_priv->panel_fixed_mode->hsync_end;
|
||||
adjusted_mode->htotal = dev_priv->panel_fixed_mode->htotal;
|
||||
adjusted_mode->vdisplay = dev_priv->panel_fixed_mode->vdisplay;
|
||||
adjusted_mode->vsync_start =
|
||||
dev_priv->panel_fixed_mode->vsync_start;
|
||||
adjusted_mode->vsync_end =
|
||||
dev_priv->panel_fixed_mode->vsync_end;
|
||||
adjusted_mode->vtotal = dev_priv->panel_fixed_mode->vtotal;
|
||||
adjusted_mode->clock = dev_priv->panel_fixed_mode->clock;
|
||||
drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: It would be nice to support lower refresh rates on the
|
||||
* panels to reduce power consumption, and perhaps match the
|
||||
* user's requested refresh rate.
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void intel_lvds_mode_set(struct drm_output *output,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct drm_device *dev = output->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = output->crtc->driver_private;
|
||||
u32 pfit_control;
|
||||
|
||||
/*
|
||||
* The LVDS pin pair will already have been turned on in the
|
||||
* intel_crtc_mode_set since it has a large impact on the DPLL
|
||||
* settings.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Enable automatic panel scaling so that non-native modes fill the
|
||||
* screen. Should be enabled before the pipe is enabled, according to
|
||||
* register description and PRM.
|
||||
*/
|
||||
pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
|
||||
VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR);
|
||||
|
||||
if (!IS_I965G(dev)) {
|
||||
if (dev_priv->panel_wants_dither)
|
||||
pfit_control |= PANEL_8TO6_DITHER_ENABLE;
|
||||
}
|
||||
else
|
||||
pfit_control |= intel_crtc->pipe << PFIT_PIPE_SHIFT;
|
||||
|
||||
I915_WRITE(PFIT_CONTROL, pfit_control);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect the LVDS connection.
|
||||
*
|
||||
* This always returns OUTPUT_STATUS_CONNECTED. This output should only have
|
||||
* been set up if the LVDS was actually connected anyway.
|
||||
*/
|
||||
static enum drm_output_status intel_lvds_detect(struct drm_output *output)
|
||||
{
|
||||
return output_status_connected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
|
||||
*/
|
||||
static int intel_lvds_get_modes(struct drm_output *output)
|
||||
{
|
||||
struct intel_output *intel_output = output->driver_private;
|
||||
struct drm_device *dev = output->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct edid *edid_info;
|
||||
int ret = 0;
|
||||
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, GPIOC, "LVDSDDC_C");
|
||||
if (!intel_output->ddc_bus) {
|
||||
dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
|
||||
"failed.\n");
|
||||
return 0;
|
||||
}
|
||||
ret = intel_ddc_get_modes(output);
|
||||
intel_i2c_destroy(intel_output->ddc_bus);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Didn't get an EDID */
|
||||
if (!output->monitor_info) {
|
||||
struct detailed_data_monitor_range *edid_range;
|
||||
edid_info = kzalloc(sizeof(*output->monitor_info), GFP_KERNEL);
|
||||
if (!edid_info)
|
||||
goto out;
|
||||
|
||||
edid_info->detailed_timings[0].data.other_data.type =
|
||||
EDID_DETAIL_MONITOR_RANGE;
|
||||
edid_range = &edid_info->detailed_timings[0].data.other_data.data.range;
|
||||
|
||||
/* Set wide sync ranges so we get all modes
|
||||
* handed to valid_mode for checking
|
||||
*/
|
||||
edid_range->min_vfreq = 0;
|
||||
edid_range->max_vfreq = 200;
|
||||
edid_range->min_hfreq_khz = 0;
|
||||
edid_range->max_hfreq_khz = 200;
|
||||
output->monitor_info = edid_info;
|
||||
}
|
||||
|
||||
out:
|
||||
if (dev_priv->panel_fixed_mode != NULL) {
|
||||
struct drm_display_mode *mode =
|
||||
drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
|
||||
drm_mode_probed_add(output, mode);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void intel_lvds_destroy(struct drm_output *output)
|
||||
{
|
||||
if (output->driver_private)
|
||||
kfree(output->driver_private);
|
||||
}
|
||||
|
||||
static const struct drm_output_funcs intel_lvds_output_funcs = {
|
||||
.dpms = intel_lvds_dpms,
|
||||
.save = intel_lvds_save,
|
||||
.restore = intel_lvds_restore,
|
||||
.mode_valid = intel_lvds_mode_valid,
|
||||
.mode_fixup = intel_lvds_mode_fixup,
|
||||
.prepare = intel_output_prepare,
|
||||
.mode_set = intel_lvds_mode_set,
|
||||
.commit = intel_output_commit,
|
||||
.detect = intel_lvds_detect,
|
||||
.get_modes = intel_lvds_get_modes,
|
||||
.cleanup = intel_lvds_destroy
|
||||
};
|
||||
|
||||
/**
|
||||
* intel_lvds_init - setup LVDS outputs on this device
|
||||
* @dev: drm device
|
||||
*
|
||||
* Create the output, register the LVDS DDC bus, and try to figure out what
|
||||
* modes we can display on the LVDS panel (if present).
|
||||
*/
|
||||
void intel_lvds_init(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_output *output;
|
||||
struct intel_output *intel_output;
|
||||
struct drm_display_mode *scan; /* *modes, *bios_mode; */
|
||||
|
||||
output = drm_output_create(dev, &intel_lvds_output_funcs, "LVDS");
|
||||
if (!output)
|
||||
return;
|
||||
|
||||
intel_output = kmalloc(sizeof(struct intel_output), GFP_KERNEL);
|
||||
if (!intel_output) {
|
||||
drm_output_destroy(output);
|
||||
return;
|
||||
}
|
||||
|
||||
intel_output->type = INTEL_OUTPUT_LVDS;
|
||||
output->driver_private = intel_output;
|
||||
output->subpixel_order = SubPixelHorizontalRGB;
|
||||
output->interlace_allowed = FALSE;
|
||||
output->doublescan_allowed = FALSE;
|
||||
|
||||
/* Set up the DDC bus. */
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, GPIOC, "LVDSDDC_C");
|
||||
if (!intel_output->ddc_bus) {
|
||||
dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
|
||||
"failed.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to get the fixed panel mode from DDC. Assume that the
|
||||
* preferred mode is the right one.
|
||||
*/
|
||||
intel_ddc_get_modes(output);
|
||||
intel_i2c_destroy(intel_output->ddc_bus);
|
||||
list_for_each_entry(scan, &output->probed_modes, head) {
|
||||
if (scan->type & DRM_MODE_TYPE_PREFERRED) {
|
||||
dev_priv->panel_fixed_mode =
|
||||
drm_mode_duplicate(dev, scan);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* If we didn't get EDID, try checking if the panel is already turned
|
||||
* on. If so, assume that whatever is currently programmed is the
|
||||
* correct mode.
|
||||
*/
|
||||
if (!dev_priv->panel_fixed_mode) {
|
||||
u32 lvds = I915_READ(LVDS);
|
||||
int pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
|
||||
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
struct drm_crtc *crtc;
|
||||
/* FIXME: need drm_crtc_from_pipe */
|
||||
//crtc = drm_crtc_from_pipe(mode_config, pipe);
|
||||
|
||||
if (lvds & LVDS_PORT_EN && 0) {
|
||||
dev_priv->panel_fixed_mode =
|
||||
intel_crtc_mode_get(dev, crtc);
|
||||
if (dev_priv->panel_fixed_mode)
|
||||
dev_priv->panel_fixed_mode->type |=
|
||||
DRM_MODE_TYPE_PREFERRED;
|
||||
}
|
||||
}
|
||||
|
||||
/* No BIOS poking yet... */
|
||||
/* Get the LVDS fixed mode out of the BIOS. We should support LVDS
|
||||
* with the BIOS being unavailable or broken, but lack the
|
||||
* configuration options for now.
|
||||
*/
|
||||
bios_mode = intel_bios_get_panel_mode(pScrn);
|
||||
if (bios_mode != NULL) {
|
||||
if (dev_priv->panel_fixed_mode != NULL) {
|
||||
if (dev_priv->debug_modes &&
|
||||
!xf86ModesEqual(dev_priv->panel_fixed_mode,
|
||||
bios_mode))
|
||||
{
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
||||
"BIOS panel mode data doesn't match probed data, "
|
||||
"continuing with probed.\n");
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS mode:\n");
|
||||
xf86PrintModeline(pScrn->scrnIndex, bios_mode);
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "probed mode:\n");
|
||||
xf86PrintModeline(pScrn->scrnIndex, dev_priv->panel_fixed_mode);
|
||||
xfree(bios_mode->name);
|
||||
xfree(bios_mode);
|
||||
}
|
||||
} else {
|
||||
dev_priv->panel_fixed_mode = bios_mode;
|
||||
}
|
||||
} else {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
||||
"Couldn't detect panel mode. Disabling panel\n");
|
||||
goto disable_exit;
|
||||
}
|
||||
|
||||
/* Blacklist machines with BIOSes that list an LVDS panel without actually
|
||||
* having one.
|
||||
*/
|
||||
if (dev_priv->PciInfo->chipType == PCI_CHIP_I945_GM) {
|
||||
if (dev_priv->PciInfo->subsysVendor == 0xa0a0) /* aopen mini pc */
|
||||
goto disable_exit;
|
||||
|
||||
if ((dev_priv->PciInfo->subsysVendor == 0x8086) &&
|
||||
(dev_priv->PciInfo->subsysCard == 0x7270)) {
|
||||
/* It's a Mac Mini or Macbook Pro.
|
||||
*
|
||||
* Apple hardware is out to get us. The macbook pro has a real
|
||||
* LVDS panel, but the mac mini does not, and they have the same
|
||||
* device IDs. We'll distinguish by panel size, on the assumption
|
||||
* that Apple isn't about to make any machines with an 800x600
|
||||
* display.
|
||||
*/
|
||||
|
||||
if (dev_priv->panel_fixed_mode != NULL &&
|
||||
dev_priv->panel_fixed_mode->HDisplay == 800 &&
|
||||
dev_priv->panel_fixed_mode->VDisplay == 600)
|
||||
{
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||||
"Suspected Mac Mini, ignoring the LVDS\n");
|
||||
goto disable_exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
55
linux-core/intel_modes.c
Normal file
55
linux-core/intel_modes.c
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
|
||||
* Copyright (c) 2007 Intel Corporation
|
||||
* Jesse Barnes <jesse.barnes@intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/fb.h>
|
||||
#include "drmP.h"
|
||||
#include "intel_drv.h"
|
||||
|
||||
/**
|
||||
* intel_ddc_probe
|
||||
*
|
||||
*/
|
||||
bool intel_ddc_probe(struct drm_output *output)
|
||||
{
|
||||
struct intel_output *intel_output = output->driver_private;
|
||||
u8 out_buf[] = { 0x0, 0x0};
|
||||
u8 buf[2];
|
||||
int ret;
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = 0x50,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = out_buf,
|
||||
},
|
||||
{
|
||||
.addr = 0x50,
|
||||
.flags = I2C_M_RD,
|
||||
.len = 1,
|
||||
.buf = buf,
|
||||
}
|
||||
};
|
||||
|
||||
ret = i2c_transfer(&intel_output->ddc_bus->adapter, msgs, 2);
|
||||
if (ret == 2)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_ddc_get_modes - get modelist from monitor
|
||||
* @output: DRM output device to use
|
||||
*
|
||||
* Fetch the EDID information from @output using the DDC bus.
|
||||
*/
|
||||
int intel_ddc_get_modes(struct drm_output *output)
|
||||
{
|
||||
struct intel_output *intel_output = output->driver_private;
|
||||
|
||||
return drm_add_edid_modes(output, &intel_output->ddc_bus->adapter);
|
||||
}
|
||||
1059
linux-core/intel_sdvo.c
Normal file
1059
linux-core/intel_sdvo.c
Normal file
File diff suppressed because it is too large
Load diff
324
linux-core/intel_sdvo_regs.h
Normal file
324
linux-core/intel_sdvo_regs.h
Normal file
|
|
@ -0,0 +1,324 @@
|
|||
/*
|
||||
* Copyright © 2006-2007 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file SDVO command definitions and structures.
|
||||
*/
|
||||
|
||||
#define SDVO_OUTPUT_FIRST (0)
|
||||
#define SDVO_OUTPUT_TMDS0 (1 << 0)
|
||||
#define SDVO_OUTPUT_RGB0 (1 << 1)
|
||||
#define SDVO_OUTPUT_CVBS0 (1 << 2)
|
||||
#define SDVO_OUTPUT_SVID0 (1 << 3)
|
||||
#define SDVO_OUTPUT_YPRPB0 (1 << 4)
|
||||
#define SDVO_OUTPUT_SCART0 (1 << 5)
|
||||
#define SDVO_OUTPUT_LVDS0 (1 << 6)
|
||||
#define SDVO_OUTPUT_TMDS1 (1 << 8)
|
||||
#define SDVO_OUTPUT_RGB1 (1 << 13)
|
||||
#define SDVO_OUTPUT_LVDS1 (1 << 14)
|
||||
#define SDVO_OUTPUT_LAST (14)
|
||||
|
||||
struct intel_sdvo_caps {
|
||||
u8 vendor_id;
|
||||
u8 device_id;
|
||||
u8 device_rev_id;
|
||||
u8 sdvo_version_major;
|
||||
u8 sdvo_version_minor;
|
||||
unsigned int sdvo_inputs_mask:2;
|
||||
unsigned int smooth_scaling:1;
|
||||
unsigned int sharp_scaling:1;
|
||||
unsigned int up_scaling:1;
|
||||
unsigned int down_scaling:1;
|
||||
unsigned int stall_support:1;
|
||||
unsigned int pad:1;
|
||||
u16 output_flags;
|
||||
} __attribute__((packed));
|
||||
|
||||
/** This matches the EDID DTD structure, more or less */
|
||||
struct intel_sdvo_dtd {
|
||||
struct {
|
||||
u16 clock; /**< pixel clock, in 10kHz units */
|
||||
u8 h_active; /**< lower 8 bits (pixels) */
|
||||
u8 h_blank; /**< lower 8 bits (pixels) */
|
||||
u8 h_high; /**< upper 4 bits each h_active, h_blank */
|
||||
u8 v_active; /**< lower 8 bits (lines) */
|
||||
u8 v_blank; /**< lower 8 bits (lines) */
|
||||
u8 v_high; /**< upper 4 bits each v_active, v_blank */
|
||||
} part1;
|
||||
|
||||
struct {
|
||||
u8 h_sync_off; /**< lower 8 bits, from hblank start */
|
||||
u8 h_sync_width; /**< lower 8 bits (pixels) */
|
||||
/** lower 4 bits each vsync offset, vsync width */
|
||||
u8 v_sync_off_width;
|
||||
/**
|
||||
* 2 high bits of hsync offset, 2 high bits of hsync width,
|
||||
* bits 4-5 of vsync offset, and 2 high bits of vsync width.
|
||||
*/
|
||||
u8 sync_off_width_high;
|
||||
u8 dtd_flags;
|
||||
u8 sdvo_flags;
|
||||
/** bits 6-7 of vsync offset at bits 6-7 */
|
||||
u8 v_sync_off_high;
|
||||
u8 reserved;
|
||||
} part2;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct intel_sdvo_pixel_clock_range {
|
||||
u16 min; /**< pixel clock, in 10kHz units */
|
||||
u16 max; /**< pixel clock, in 10kHz units */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct intel_sdvo_preferred_input_timing_args {
|
||||
u16 clock;
|
||||
u16 width;
|
||||
u16 height;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* I2C registers for SDVO */
|
||||
#define SDVO_I2C_ARG_0 0x07
|
||||
#define SDVO_I2C_ARG_1 0x06
|
||||
#define SDVO_I2C_ARG_2 0x05
|
||||
#define SDVO_I2C_ARG_3 0x04
|
||||
#define SDVO_I2C_ARG_4 0x03
|
||||
#define SDVO_I2C_ARG_5 0x02
|
||||
#define SDVO_I2C_ARG_6 0x01
|
||||
#define SDVO_I2C_ARG_7 0x00
|
||||
#define SDVO_I2C_OPCODE 0x08
|
||||
#define SDVO_I2C_CMD_STATUS 0x09
|
||||
#define SDVO_I2C_RETURN_0 0x0a
|
||||
#define SDVO_I2C_RETURN_1 0x0b
|
||||
#define SDVO_I2C_RETURN_2 0x0c
|
||||
#define SDVO_I2C_RETURN_3 0x0d
|
||||
#define SDVO_I2C_RETURN_4 0x0e
|
||||
#define SDVO_I2C_RETURN_5 0x0f
|
||||
#define SDVO_I2C_RETURN_6 0x10
|
||||
#define SDVO_I2C_RETURN_7 0x11
|
||||
#define SDVO_I2C_VENDOR_BEGIN 0x20
|
||||
|
||||
/* Status results */
|
||||
#define SDVO_CMD_STATUS_POWER_ON 0x0
|
||||
#define SDVO_CMD_STATUS_SUCCESS 0x1
|
||||
#define SDVO_CMD_STATUS_NOTSUPP 0x2
|
||||
#define SDVO_CMD_STATUS_INVALID_ARG 0x3
|
||||
#define SDVO_CMD_STATUS_PENDING 0x4
|
||||
#define SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED 0x5
|
||||
#define SDVO_CMD_STATUS_SCALING_NOT_SUPP 0x6
|
||||
|
||||
/* SDVO commands, argument/result registers */
|
||||
|
||||
#define SDVO_CMD_RESET 0x01
|
||||
|
||||
/** Returns a struct intel_sdvo_caps */
|
||||
#define SDVO_CMD_GET_DEVICE_CAPS 0x02
|
||||
|
||||
#define SDVO_CMD_GET_FIRMWARE_REV 0x86
|
||||
# define SDVO_DEVICE_FIRMWARE_MINOR SDVO_I2C_RETURN_0
|
||||
# define SDVO_DEVICE_FIRMWARE_MAJOR SDVO_I2C_RETURN_1
|
||||
# define SDVO_DEVICE_FIRMWARE_PATCH SDVO_I2C_RETURN_2
|
||||
|
||||
/**
|
||||
* Reports which inputs are trained (managed to sync).
|
||||
*
|
||||
* Devices must have trained within 2 vsyncs of a mode change.
|
||||
*/
|
||||
#define SDVO_CMD_GET_TRAINED_INPUTS 0x03
|
||||
struct intel_sdvo_get_trained_inputs_response {
|
||||
unsigned int input0_trained:1;
|
||||
unsigned int input1_trained:1;
|
||||
unsigned int pad:6;
|
||||
} __attribute__((packed));
|
||||
|
||||
/** Returns a struct intel_sdvo_output_flags of active outputs. */
|
||||
#define SDVO_CMD_GET_ACTIVE_OUTPUTS 0x04
|
||||
|
||||
/**
|
||||
* Sets the current set of active outputs.
|
||||
*
|
||||
* Takes a struct intel_sdvo_output_flags. Must be preceded by a SET_IN_OUT_MAP
|
||||
* on multi-output devices.
|
||||
*/
|
||||
#define SDVO_CMD_SET_ACTIVE_OUTPUTS 0x05
|
||||
|
||||
/**
|
||||
* Returns the current mapping of SDVO inputs to outputs on the device.
|
||||
*
|
||||
* Returns two struct intel_sdvo_output_flags structures.
|
||||
*/
|
||||
#define SDVO_CMD_GET_IN_OUT_MAP 0x06
|
||||
|
||||
/**
|
||||
* Sets the current mapping of SDVO inputs to outputs on the device.
|
||||
*
|
||||
* Takes two struct i380_sdvo_output_flags structures.
|
||||
*/
|
||||
#define SDVO_CMD_SET_IN_OUT_MAP 0x07
|
||||
|
||||
/**
|
||||
* Returns a struct intel_sdvo_output_flags of attached displays.
|
||||
*/
|
||||
#define SDVO_CMD_GET_ATTACHED_DISPLAYS 0x0b
|
||||
|
||||
/**
|
||||
* Returns a struct intel_sdvo_ouptut_flags of displays supporting hot plugging.
|
||||
*/
|
||||
#define SDVO_CMD_GET_HOT_PLUG_SUPPORT 0x0c
|
||||
|
||||
/**
|
||||
* Takes a struct intel_sdvo_output_flags.
|
||||
*/
|
||||
#define SDVO_CMD_SET_ACTIVE_HOT_PLUG 0x0d
|
||||
|
||||
/**
|
||||
* Returns a struct intel_sdvo_output_flags of displays with hot plug
|
||||
* interrupts enabled.
|
||||
*/
|
||||
#define SDVO_CMD_GET_ACTIVE_HOT_PLUG 0x0e
|
||||
|
||||
#define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE 0x0f
|
||||
struct intel_sdvo_get_interrupt_event_source_response {
|
||||
u16 interrupt_status;
|
||||
unsigned int ambient_light_interrupt:1;
|
||||
unsigned int pad:7;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* Selects which input is affected by future input commands.
|
||||
*
|
||||
* Commands affected include SET_INPUT_TIMINGS_PART[12],
|
||||
* GET_INPUT_TIMINGS_PART[12], GET_PREFERRED_INPUT_TIMINGS_PART[12],
|
||||
* GET_INPUT_PIXEL_CLOCK_RANGE, and CREATE_PREFERRED_INPUT_TIMINGS.
|
||||
*/
|
||||
#define SDVO_CMD_SET_TARGET_INPUT 0x10
|
||||
struct intel_sdvo_set_target_input_args {
|
||||
unsigned int target_1:1;
|
||||
unsigned int pad:7;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* Takes a struct intel_sdvo_output_flags of which outputs are targetted by
|
||||
* future output commands.
|
||||
*
|
||||
* Affected commands inclue SET_OUTPUT_TIMINGS_PART[12],
|
||||
* GET_OUTPUT_TIMINGS_PART[12], and GET_OUTPUT_PIXEL_CLOCK_RANGE.
|
||||
*/
|
||||
#define SDVO_CMD_SET_TARGET_OUTPUT 0x11
|
||||
|
||||
#define SDVO_CMD_GET_INPUT_TIMINGS_PART1 0x12
|
||||
#define SDVO_CMD_GET_INPUT_TIMINGS_PART2 0x13
|
||||
#define SDVO_CMD_SET_INPUT_TIMINGS_PART1 0x14
|
||||
#define SDVO_CMD_SET_INPUT_TIMINGS_PART2 0x15
|
||||
#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART1 0x16
|
||||
#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART2 0x17
|
||||
#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART1 0x18
|
||||
#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART2 0x19
|
||||
/* Part 1 */
|
||||
# define SDVO_DTD_CLOCK_LOW SDVO_I2C_ARG_0
|
||||
# define SDVO_DTD_CLOCK_HIGH SDVO_I2C_ARG_1
|
||||
# define SDVO_DTD_H_ACTIVE SDVO_I2C_ARG_2
|
||||
# define SDVO_DTD_H_BLANK SDVO_I2C_ARG_3
|
||||
# define SDVO_DTD_H_HIGH SDVO_I2C_ARG_4
|
||||
# define SDVO_DTD_V_ACTIVE SDVO_I2C_ARG_5
|
||||
# define SDVO_DTD_V_BLANK SDVO_I2C_ARG_6
|
||||
# define SDVO_DTD_V_HIGH SDVO_I2C_ARG_7
|
||||
/* Part 2 */
|
||||
# define SDVO_DTD_HSYNC_OFF SDVO_I2C_ARG_0
|
||||
# define SDVO_DTD_HSYNC_WIDTH SDVO_I2C_ARG_1
|
||||
# define SDVO_DTD_VSYNC_OFF_WIDTH SDVO_I2C_ARG_2
|
||||
# define SDVO_DTD_SYNC_OFF_WIDTH_HIGH SDVO_I2C_ARG_3
|
||||
# define SDVO_DTD_DTD_FLAGS SDVO_I2C_ARG_4
|
||||
# define SDVO_DTD_DTD_FLAG_INTERLACED (1 << 7)
|
||||
# define SDVO_DTD_DTD_FLAG_STEREO_MASK (3 << 5)
|
||||
# define SDVO_DTD_DTD_FLAG_INPUT_MASK (3 << 3)
|
||||
# define SDVO_DTD_DTD_FLAG_SYNC_MASK (3 << 1)
|
||||
# define SDVO_DTD_SDVO_FLAS SDVO_I2C_ARG_5
|
||||
# define SDVO_DTD_SDVO_FLAG_STALL (1 << 7)
|
||||
# define SDVO_DTD_SDVO_FLAG_CENTERED (0 << 6)
|
||||
# define SDVO_DTD_SDVO_FLAG_UPPER_LEFT (1 << 6)
|
||||
# define SDVO_DTD_SDVO_FLAG_SCALING_MASK (3 << 4)
|
||||
# define SDVO_DTD_SDVO_FLAG_SCALING_NONE (0 << 4)
|
||||
# define SDVO_DTD_SDVO_FLAG_SCALING_SHARP (1 << 4)
|
||||
# define SDVO_DTD_SDVO_FLAG_SCALING_SMOOTH (2 << 4)
|
||||
# define SDVO_DTD_VSYNC_OFF_HIGH SDVO_I2C_ARG_6
|
||||
|
||||
/**
|
||||
* Generates a DTD based on the given width, height, and flags.
|
||||
*
|
||||
* This will be supported by any device supporting scaling or interlaced
|
||||
* modes.
|
||||
*/
|
||||
#define SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING 0x1a
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_LOW SDVO_I2C_ARG_0
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_HIGH SDVO_I2C_ARG_1
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_LOW SDVO_I2C_ARG_2
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_HIGH SDVO_I2C_ARG_3
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_LOW SDVO_I2C_ARG_4
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_HIGH SDVO_I2C_ARG_5
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_FLAGS SDVO_I2C_ARG_6
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_INTERLACED (1 << 0)
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_SCALED (1 << 1)
|
||||
|
||||
#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1 0x1b
|
||||
#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2 0x1c
|
||||
|
||||
/** Returns a struct intel_sdvo_pixel_clock_range */
|
||||
#define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE 0x1d
|
||||
/** Returns a struct intel_sdvo_pixel_clock_range */
|
||||
#define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE 0x1e
|
||||
|
||||
/** Returns a byte bitfield containing SDVO_CLOCK_RATE_MULT_* flags */
|
||||
#define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS 0x1f
|
||||
|
||||
/** Returns a byte containing a SDVO_CLOCK_RATE_MULT_* flag */
|
||||
#define SDVO_CMD_GET_CLOCK_RATE_MULT 0x20
|
||||
/** Takes a byte containing a SDVO_CLOCK_RATE_MULT_* flag */
|
||||
#define SDVO_CMD_SET_CLOCK_RATE_MULT 0x21
|
||||
# define SDVO_CLOCK_RATE_MULT_1X (1 << 0)
|
||||
# define SDVO_CLOCK_RATE_MULT_2X (1 << 1)
|
||||
# define SDVO_CLOCK_RATE_MULT_4X (1 << 3)
|
||||
|
||||
#define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27
|
||||
|
||||
#define SDVO_CMD_GET_TV_FORMAT 0x28
|
||||
|
||||
#define SDVO_CMD_SET_TV_FORMAT 0x29
|
||||
|
||||
#define SDVO_CMD_GET_SUPPORTED_POWER_STATES 0x2a
|
||||
#define SDVO_CMD_GET_ENCODER_POWER_STATE 0x2b
|
||||
#define SDVO_CMD_SET_ENCODER_POWER_STATE 0x2c
|
||||
# define SDVO_ENCODER_STATE_ON (1 << 0)
|
||||
# define SDVO_ENCODER_STATE_STANDBY (1 << 1)
|
||||
# define SDVO_ENCODER_STATE_SUSPEND (1 << 2)
|
||||
# define SDVO_ENCODER_STATE_OFF (1 << 3)
|
||||
|
||||
#define SDVO_CMD_SET_TV_RESOLUTION_SUPPORT 0x93
|
||||
|
||||
#define SDVO_CMD_SET_CONTROL_BUS_SWITCH 0x7a
|
||||
# define SDVO_CONTROL_BUS_PROM 0x0
|
||||
# define SDVO_CONTROL_BUS_DDC1 0x1
|
||||
# define SDVO_CONTROL_BUS_DDC2 0x2
|
||||
# define SDVO_CONTROL_BUS_DDC3 0x3
|
||||
|
||||
|
|
@ -795,6 +795,7 @@ typedef struct drm_fence_arg {
|
|||
|
||||
typedef enum {
|
||||
drm_bo_type_dc,
|
||||
drm_bo_type_kernel, /* for initial kernel allocations */
|
||||
drm_bo_type_user,
|
||||
drm_bo_type_fake
|
||||
}drm_bo_type_t;
|
||||
|
|
@ -888,6 +889,91 @@ typedef union drm_mm_init_arg{
|
|||
} rep;
|
||||
} drm_mm_init_arg_t;
|
||||
|
||||
/*
|
||||
* Drm mode setting
|
||||
*/
|
||||
#define DRM_OUTPUT_NAME_LEN 32
|
||||
#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 {
|
||||
|
||||
int count_fbs;
|
||||
unsigned int __user *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 char name[DRM_OUTPUT_NAME_LEN];
|
||||
|
||||
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 */
|
||||
|
||||
};
|
||||
|
||||
struct drm_mode_fb_cmd {
|
||||
unsigned int buffer_id;
|
||||
unsigned int width, height;
|
||||
unsigned int pitch;
|
||||
unsigned int bpp;
|
||||
unsigned int handle;
|
||||
unsigned int depth;
|
||||
};
|
||||
|
||||
/**
|
||||
* \name Ioctls Definitions
|
||||
*/
|
||||
|
|
@ -959,6 +1045,13 @@ typedef union drm_mm_init_arg{
|
|||
|
||||
#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)
|
||||
#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)
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -31,13 +31,6 @@
|
|||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
#define IS_I965G(dev) (dev->pci_device == 0x2972 || \
|
||||
dev->pci_device == 0x2982 || \
|
||||
dev->pci_device == 0x2992 || \
|
||||
dev->pci_device == 0x29A2 || \
|
||||
dev->pci_device == 0x2A02)
|
||||
|
||||
|
||||
/* Really want an OS-independent resettable timer. Would like to have
|
||||
* this loop run for (eg) 3 sec, but have the timer reset every time
|
||||
* the head pointer changes, so that EBUSY only happens if the ring
|
||||
|
|
@ -85,8 +78,9 @@ void i915_kernel_lost_context(drm_device_t * dev)
|
|||
dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
|
||||
}
|
||||
|
||||
static int i915_dma_cleanup(drm_device_t * dev)
|
||||
int i915_dma_cleanup(drm_device_t * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
/* Make sure interrupts are disabled here because the uninstall ioctl
|
||||
* may not have been called from userspace and after dev_private
|
||||
* is freed, it's too late.
|
||||
|
|
@ -94,25 +88,16 @@ static int i915_dma_cleanup(drm_device_t * dev)
|
|||
if (dev->irq)
|
||||
drm_irq_uninstall(dev);
|
||||
|
||||
if (dev->dev_private) {
|
||||
drm_i915_private_t *dev_priv =
|
||||
(drm_i915_private_t *) dev->dev_private;
|
||||
|
||||
if (dev_priv->ring.virtual_start) {
|
||||
drm_core_ioremapfree(&dev_priv->ring.map, dev);
|
||||
}
|
||||
|
||||
if (dev_priv->status_page_dmah) {
|
||||
drm_pci_free(dev, dev_priv->status_page_dmah);
|
||||
/* Need to rewrite hardware status page */
|
||||
I915_WRITE(0x02080, 0x1ffff000);
|
||||
}
|
||||
|
||||
drm_free(dev->dev_private, sizeof(drm_i915_private_t),
|
||||
DRM_MEM_DRIVER);
|
||||
|
||||
dev->dev_private = NULL;
|
||||
if (dev_priv->status_page_dmah) {
|
||||
drm_pci_free(dev, dev_priv->status_page_dmah);
|
||||
dev_priv->status_page_dmah = NULL;
|
||||
dev_priv->hw_status_page = NULL;
|
||||
dev_priv->dma_status_page = 0;
|
||||
/* Need to rewrite hardware status page */
|
||||
I915_WRITE(0x02080, 0x1ffff000);
|
||||
}
|
||||
|
||||
dev_priv->sarea_priv = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -121,8 +106,6 @@ static int i915_initialize(drm_device_t * dev,
|
|||
drm_i915_private_t * dev_priv,
|
||||
drm_i915_init_t * init)
|
||||
{
|
||||
memset(dev_priv, 0, sizeof(drm_i915_private_t));
|
||||
|
||||
DRM_GETSAREA();
|
||||
if (!dev_priv->sarea) {
|
||||
DRM_ERROR("can not find sarea!\n");
|
||||
|
|
@ -131,14 +114,6 @@ static int i915_initialize(drm_device_t * dev,
|
|||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
|
||||
if (!dev_priv->mmio_map) {
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
i915_dma_cleanup(dev);
|
||||
DRM_ERROR("can not find mmio map!\n");
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
dev_priv->sarea_priv = (drm_i915_sarea_t *)
|
||||
((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
|
||||
|
||||
|
|
@ -195,7 +170,9 @@ static int i915_initialize(drm_device_t * dev,
|
|||
|
||||
I915_WRITE(0x02080, dev_priv->dma_status_page);
|
||||
DRM_DEBUG("Enabled hardware status page\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
|
||||
//drm_set_desired_modes(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -237,7 +214,7 @@ static int i915_dma_resume(drm_device_t * dev)
|
|||
static int i915_dma_init(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv;
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
drm_i915_init_t init;
|
||||
int retcode = 0;
|
||||
|
||||
|
|
@ -246,10 +223,6 @@ static int i915_dma_init(DRM_IOCTL_ARGS)
|
|||
|
||||
switch (init.func) {
|
||||
case I915_INIT_DMA:
|
||||
dev_priv = drm_alloc(sizeof(drm_i915_private_t),
|
||||
DRM_MEM_DRIVER);
|
||||
if (dev_priv == NULL)
|
||||
return DRM_ERR(ENOMEM);
|
||||
retcode = i915_initialize(dev, dev_priv, &init);
|
||||
break;
|
||||
case I915_CLEANUP_DMA:
|
||||
|
|
@ -878,36 +851,6 @@ static int i915_mmio(DRM_IOCTL_ARGS)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int i915_driver_load(drm_device_t *dev, unsigned long flags)
|
||||
{
|
||||
/* i915 has 4 more counters */
|
||||
dev->counters += 4;
|
||||
dev->types[6] = _DRM_STAT_IRQ;
|
||||
dev->types[7] = _DRM_STAT_PRIMARY;
|
||||
dev->types[8] = _DRM_STAT_SECONDARY;
|
||||
dev->types[9] = _DRM_STAT_DMA;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i915_driver_lastclose(drm_device_t * dev)
|
||||
{
|
||||
if (dev->dev_private) {
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
i915_do_cleanup_pageflip(dev);
|
||||
i915_mem_takedown(&(dev_priv->agp_heap));
|
||||
}
|
||||
i915_dma_cleanup(dev);
|
||||
}
|
||||
|
||||
void i915_driver_preclose(drm_device_t * dev, DRMFILE filp)
|
||||
{
|
||||
if (dev->dev_private) {
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
i915_mem_release(dev, filp, dev_priv->agp_heap);
|
||||
}
|
||||
}
|
||||
|
||||
drm_ioctl_desc_t i915_ioctls[] = {
|
||||
[DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
|
||||
[DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, DRM_AUTH},
|
||||
|
|
@ -948,8 +891,21 @@ int i915_driver_device_is_agp(drm_device_t * dev)
|
|||
|
||||
int i915_driver_firstopen(struct drm_device *dev)
|
||||
{
|
||||
#ifdef I915_HAVE_BUFFER
|
||||
drm_bo_driver_init(dev);
|
||||
#endif
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (!dev_priv->mmio_map) {
|
||||
ret = drm_addmap(dev, dev_priv->mmiobase, dev_priv->mmiolen,
|
||||
_DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->mmio_map);
|
||||
if (ret != 0) {
|
||||
DRM_ERROR("Cannot add mapping for MMIO registers\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
DRM_DEBUG("dev_priv->mmio map is %p\n", dev_priv->mmio_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -92,6 +92,10 @@ typedef struct drm_i915_private {
|
|||
drm_local_map_t *sarea;
|
||||
drm_local_map_t *mmio_map;
|
||||
|
||||
unsigned long baseaddr;
|
||||
unsigned long mmiobase;
|
||||
unsigned long mmiolen;
|
||||
|
||||
drm_i915_sarea_t *sarea_priv;
|
||||
drm_i915_ring_buffer_t ring;
|
||||
|
||||
|
|
@ -130,6 +134,67 @@ typedef struct drm_i915_private {
|
|||
spinlock_t swaps_lock;
|
||||
drm_i915_vbl_swap_t vbl_swaps;
|
||||
unsigned int swaps_pending;
|
||||
|
||||
/* LVDS info */
|
||||
int backlight_duty_cycle; /* restore backlight to this value */
|
||||
bool panel_wants_dither;
|
||||
struct drm_display_mode *panel_fixed_mode;
|
||||
|
||||
/* Register state */
|
||||
u32 saveDSPACNTR;
|
||||
u32 saveDSPBCNTR;
|
||||
u32 savePIPEACONF;
|
||||
u32 savePIPEBCONF;
|
||||
u32 savePIPEASRC;
|
||||
u32 savePIPEBSRC;
|
||||
u32 saveFPA0;
|
||||
u32 saveFPA1;
|
||||
u32 saveDPLL_A;
|
||||
u32 saveDPLL_A_MD;
|
||||
u32 saveHTOTAL_A;
|
||||
u32 saveHBLANK_A;
|
||||
u32 saveHSYNC_A;
|
||||
u32 saveVTOTAL_A;
|
||||
u32 saveVBLANK_A;
|
||||
u32 saveVSYNC_A;
|
||||
u32 saveDSPASTRIDE;
|
||||
u32 saveDSPASIZE;
|
||||
u32 saveDSPAPOS;
|
||||
u32 saveDSPABASE;
|
||||
u32 saveDSPASURF;
|
||||
u32 saveFPB0;
|
||||
u32 saveFPB1;
|
||||
u32 saveDPLL_B;
|
||||
u32 saveDPLL_B_MD;
|
||||
u32 saveHTOTAL_B;
|
||||
u32 saveHBLANK_B;
|
||||
u32 saveHSYNC_B;
|
||||
u32 saveVTOTAL_B;
|
||||
u32 saveVBLANK_B;
|
||||
u32 saveVSYNC_B;
|
||||
u32 saveDSPBSTRIDE;
|
||||
u32 saveDSPBSIZE;
|
||||
u32 saveDSPBPOS;
|
||||
u32 saveDSPBBASE;
|
||||
u32 saveDSPBSURF;
|
||||
u32 saveVCLK_DIVISOR_VGA0;
|
||||
u32 saveVCLK_DIVISOR_VGA1;
|
||||
u32 saveVCLK_POST_DIV;
|
||||
u32 saveVGACNTRL;
|
||||
u32 saveADPA;
|
||||
u32 saveLVDS;
|
||||
u32 saveDVOA;
|
||||
u32 saveDVOB;
|
||||
u32 saveDVOC;
|
||||
u32 savePP_ON;
|
||||
u32 savePP_OFF;
|
||||
u32 savePP_CONTROL;
|
||||
u32 savePP_CYCLE;
|
||||
u32 savePFIT_CONTROL;
|
||||
u32 savePaletteA[256];
|
||||
u32 savePaletteB[256];
|
||||
u32 saveSWF[17];
|
||||
u32 saveBLC_PWM_CTL;
|
||||
} drm_i915_private_t;
|
||||
|
||||
enum intel_chip_family {
|
||||
|
|
@ -145,6 +210,8 @@ extern int i915_max_ioctl;
|
|||
/* i915_dma.c */
|
||||
extern void i915_kernel_lost_context(drm_device_t * dev);
|
||||
extern int i915_driver_load(struct drm_device *, unsigned long flags);
|
||||
extern int i915_driver_unload(drm_device_t *dev);
|
||||
extern int i915_driver_firstopen(struct drm_device *dev);
|
||||
extern void i915_driver_lastclose(drm_device_t * dev);
|
||||
extern void i915_driver_preclose(drm_device_t * dev, DRMFILE filp);
|
||||
extern int i915_driver_device_is_agp(drm_device_t * dev);
|
||||
|
|
@ -206,6 +273,12 @@ extern int i915_move(drm_buffer_object_t *bo, int evict,
|
|||
|
||||
#endif
|
||||
|
||||
|
||||
/* modesetting */
|
||||
extern void intel_modeset_init(drm_device_t *dev);
|
||||
extern void intel_modeset_cleanup(drm_device_t *dev);
|
||||
|
||||
|
||||
#define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, (reg))
|
||||
#define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, (reg), (val))
|
||||
#define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, (reg))
|
||||
|
|
@ -245,6 +318,27 @@ extern int i915_move(drm_buffer_object_t *bo, int evict,
|
|||
|
||||
extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
|
||||
|
||||
/*
|
||||
* The Bridge device's PCI config space has information about the
|
||||
* fb aperture size and the amount of pre-reserved memory.
|
||||
*/
|
||||
#define INTEL_GMCH_CTRL 0x52
|
||||
#define INTEL_GMCH_ENABLED 0x4
|
||||
#define INTEL_GMCH_MEM_MASK 0x1
|
||||
#define INTEL_GMCH_MEM_64M 0x1
|
||||
#define INTEL_GMCH_MEM_128M 0
|
||||
|
||||
#define INTEL_855_GMCH_GMS_MASK (0x7 << 4)
|
||||
#define INTEL_855_GMCH_GMS_DISABLED (0x0 << 4)
|
||||
#define INTEL_855_GMCH_GMS_STOLEN_1M (0x1 << 4)
|
||||
#define INTEL_855_GMCH_GMS_STOLEN_4M (0x2 << 4)
|
||||
#define INTEL_855_GMCH_GMS_STOLEN_8M (0x3 << 4)
|
||||
#define INTEL_855_GMCH_GMS_STOLEN_16M (0x4 << 4)
|
||||
#define INTEL_855_GMCH_GMS_STOLEN_32M (0x5 << 4)
|
||||
|
||||
#define INTEL_915G_GMCH_GMS_STOLEN_48M (0x6 << 4)
|
||||
#define INTEL_915G_GMCH_GMS_STOLEN_64M (0x7 << 4)
|
||||
|
||||
#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
|
||||
#define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23))
|
||||
#define CMD_REPORT_HEAD (7<<23)
|
||||
|
|
@ -273,6 +367,30 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
|
|||
#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17)
|
||||
#define I915_VBLANK_CLEAR (1UL<<1)
|
||||
|
||||
#define GPIOA 0x5010
|
||||
#define GPIOB 0x5014
|
||||
#define GPIOC 0x5018
|
||||
#define GPIOD 0x501c
|
||||
#define GPIOE 0x5020
|
||||
#define GPIOF 0x5024
|
||||
#define GPIOG 0x5028
|
||||
#define GPIOH 0x502c
|
||||
# define GPIO_CLOCK_DIR_MASK (1 << 0)
|
||||
# define GPIO_CLOCK_DIR_IN (0 << 1)
|
||||
# define GPIO_CLOCK_DIR_OUT (1 << 1)
|
||||
# define GPIO_CLOCK_VAL_MASK (1 << 2)
|
||||
# define GPIO_CLOCK_VAL_OUT (1 << 3)
|
||||
# define GPIO_CLOCK_VAL_IN (1 << 4)
|
||||
# define GPIO_CLOCK_PULLUP_DISABLE (1 << 5)
|
||||
# define GPIO_DATA_DIR_MASK (1 << 8)
|
||||
# define GPIO_DATA_DIR_IN (0 << 9)
|
||||
# define GPIO_DATA_DIR_OUT (1 << 9)
|
||||
# define GPIO_DATA_VAL_MASK (1 << 10)
|
||||
# define GPIO_DATA_VAL_OUT (1 << 11)
|
||||
# define GPIO_DATA_VAL_IN (1 << 12)
|
||||
# define GPIO_DATA_PULLUP_DISABLE (1 << 13)
|
||||
|
||||
|
||||
#define SRX_INDEX 0x3c4
|
||||
#define SRX_DATA 0x3c5
|
||||
#define SR01 1
|
||||
|
|
@ -281,6 +399,8 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
|
|||
#define PPCR 0x61204
|
||||
#define PPCR_ON (1<<0)
|
||||
|
||||
#define DVOA 0x61120
|
||||
#define DVOA_ON (1<<31)
|
||||
#define DVOB 0x61140
|
||||
#define DVOB_ON (1<<31)
|
||||
#define DVOC 0x61160
|
||||
|
|
@ -363,4 +483,443 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
|
|||
|
||||
#define READ_BREADCRUMB(dev_priv) (((volatile u32*)(dev_priv->hw_status_page))[5])
|
||||
#define READ_HWSP(dev_priv, reg) (((volatile u32*)(dev_priv->hw_status_page))[reg])
|
||||
|
||||
#define BLC_PWM_CTL 0x61254
|
||||
#define BACKLIGHT_MODULATION_FREQ_SHIFT (17)
|
||||
/**
|
||||
* This is the most significant 15 bits of the number of backlight cycles in a
|
||||
* complete cycle of the modulated backlight control.
|
||||
*
|
||||
* The actual value is this field multiplied by two.
|
||||
*/
|
||||
#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17)
|
||||
#define BLM_LEGACY_MODE (1 << 16)
|
||||
/**
|
||||
* This is the number of cycles out of the backlight modulation cycle for which
|
||||
* the backlight is on.
|
||||
*
|
||||
* This field must be no greater than the number of cycles in the complete
|
||||
* backlight modulation cycle.
|
||||
*/
|
||||
#define BACKLIGHT_DUTY_CYCLE_SHIFT (0)
|
||||
#define BACKLIGHT_DUTY_CYCLE_MASK (0xffff)
|
||||
|
||||
#define I915_GCFGC 0xf0
|
||||
#define I915_LOW_FREQUENCY_ENABLE (1 << 7)
|
||||
#define I915_DISPLAY_CLOCK_190_200_MHZ (0 << 4)
|
||||
#define I915_DISPLAY_CLOCK_333_MHZ (4 << 4)
|
||||
#define I915_DISPLAY_CLOCK_MASK (7 << 4)
|
||||
|
||||
#define I855_HPLLCC 0xc0
|
||||
#define I855_CLOCK_CONTROL_MASK (3 << 0)
|
||||
#define I855_CLOCK_133_200 (0 << 0)
|
||||
#define I855_CLOCK_100_200 (1 << 0)
|
||||
#define I855_CLOCK_100_133 (2 << 0)
|
||||
#define I855_CLOCK_166_250 (3 << 0)
|
||||
|
||||
/* I830 CRTC registers */
|
||||
#define HTOTAL_A 0x60000
|
||||
#define HBLANK_A 0x60004
|
||||
#define HSYNC_A 0x60008
|
||||
#define VTOTAL_A 0x6000c
|
||||
#define VBLANK_A 0x60010
|
||||
#define VSYNC_A 0x60014
|
||||
#define PIPEASRC 0x6001c
|
||||
#define BCLRPAT_A 0x60020
|
||||
#define VSYNCSHIFT_A 0x60028
|
||||
|
||||
#define HTOTAL_B 0x61000
|
||||
#define HBLANK_B 0x61004
|
||||
#define HSYNC_B 0x61008
|
||||
#define VTOTAL_B 0x6100c
|
||||
#define VBLANK_B 0x61010
|
||||
#define VSYNC_B 0x61014
|
||||
#define PIPEBSRC 0x6101c
|
||||
#define BCLRPAT_B 0x61020
|
||||
#define VSYNCSHIFT_B 0x61028
|
||||
|
||||
#define PP_STATUS 0x61200
|
||||
# define PP_ON (1 << 31)
|
||||
/**
|
||||
* Indicates that all dependencies of the panel are on:
|
||||
*
|
||||
* - PLL enabled
|
||||
* - pipe enabled
|
||||
* - LVDS/DVOB/DVOC on
|
||||
*/
|
||||
# define PP_READY (1 << 30)
|
||||
# define PP_SEQUENCE_NONE (0 << 28)
|
||||
# define PP_SEQUENCE_ON (1 << 28)
|
||||
# define PP_SEQUENCE_OFF (2 << 28)
|
||||
# define PP_SEQUENCE_MASK 0x30000000
|
||||
#define PP_CONTROL 0x61204
|
||||
# define POWER_TARGET_ON (1 << 0)
|
||||
|
||||
#define LVDSPP_ON 0x61208
|
||||
#define LVDSPP_OFF 0x6120c
|
||||
#define PP_CYCLE 0x61210
|
||||
|
||||
#define PFIT_CONTROL 0x61230
|
||||
# define PFIT_ENABLE (1 << 31)
|
||||
# define PFIT_PIPE_MASK (3 << 29)
|
||||
# define PFIT_PIPE_SHIFT 29
|
||||
# define VERT_INTERP_DISABLE (0 << 10)
|
||||
# define VERT_INTERP_BILINEAR (1 << 10)
|
||||
# define VERT_INTERP_MASK (3 << 10)
|
||||
# define VERT_AUTO_SCALE (1 << 9)
|
||||
# define HORIZ_INTERP_DISABLE (0 << 6)
|
||||
# define HORIZ_INTERP_BILINEAR (1 << 6)
|
||||
# define HORIZ_INTERP_MASK (3 << 6)
|
||||
# define HORIZ_AUTO_SCALE (1 << 5)
|
||||
# define PANEL_8TO6_DITHER_ENABLE (1 << 3)
|
||||
|
||||
#define PFIT_PGM_RATIOS 0x61234
|
||||
# define PFIT_VERT_SCALE_MASK 0xfff00000
|
||||
# define PFIT_HORIZ_SCALE_MASK 0x0000fff0
|
||||
|
||||
#define PFIT_AUTO_RATIOS 0x61238
|
||||
|
||||
|
||||
#define DPLL_A 0x06014
|
||||
#define DPLL_B 0x06018
|
||||
# define DPLL_VCO_ENABLE (1 << 31)
|
||||
# define DPLL_DVO_HIGH_SPEED (1 << 30)
|
||||
# define DPLL_SYNCLOCK_ENABLE (1 << 29)
|
||||
# define DPLL_VGA_MODE_DIS (1 << 28)
|
||||
# define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */
|
||||
# define DPLLB_MODE_LVDS (2 << 26) /* i915 */
|
||||
# define DPLL_MODE_MASK (3 << 26)
|
||||
# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */
|
||||
# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */
|
||||
# define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */
|
||||
# define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */
|
||||
# define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */
|
||||
# define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */
|
||||
/**
|
||||
* The i830 generation, in DAC/serial mode, defines p1 as two plus this
|
||||
* bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set.
|
||||
*/
|
||||
# define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000
|
||||
/**
|
||||
* The i830 generation, in LVDS mode, defines P1 as the bit number set within
|
||||
* this field (only one bit may be set).
|
||||
*/
|
||||
# define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000
|
||||
# define DPLL_FPA01_P1_POST_DIV_SHIFT 16
|
||||
# define PLL_P2_DIVIDE_BY_4 (1 << 23) /* i830, required in DVO non-gang */
|
||||
# define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */
|
||||
# define PLL_REF_INPUT_DREFCLK (0 << 13)
|
||||
# define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */
|
||||
# define PLL_REF_INPUT_TVCLKINBC (2 << 13) /* SDVO TVCLKIN */
|
||||
# define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13)
|
||||
# define PLL_REF_INPUT_MASK (3 << 13)
|
||||
# define PLL_LOAD_PULSE_PHASE_SHIFT 9
|
||||
/*
|
||||
* Parallel to Serial Load Pulse phase selection.
|
||||
* Selects the phase for the 10X DPLL clock for the PCIe
|
||||
* digital display port. The range is 4 to 13; 10 or more
|
||||
* is just a flip delay. The default is 6
|
||||
*/
|
||||
# define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
|
||||
# define DISPLAY_RATE_SELECT_FPA1 (1 << 8)
|
||||
|
||||
/**
|
||||
* SDVO multiplier for 945G/GM. Not used on 965.
|
||||
*
|
||||
* \sa DPLL_MD_UDI_MULTIPLIER_MASK
|
||||
*/
|
||||
# define SDVO_MULTIPLIER_MASK 0x000000ff
|
||||
# define SDVO_MULTIPLIER_SHIFT_HIRES 4
|
||||
# define SDVO_MULTIPLIER_SHIFT_VGA 0
|
||||
|
||||
/** @defgroup DPLL_MD
|
||||
* @{
|
||||
*/
|
||||
/** Pipe A SDVO/UDI clock multiplier/divider register for G965. */
|
||||
#define DPLL_A_MD 0x0601c
|
||||
/** Pipe B SDVO/UDI clock multiplier/divider register for G965. */
|
||||
#define DPLL_B_MD 0x06020
|
||||
/**
|
||||
* UDI pixel divider, controlling how many pixels are stuffed into a packet.
|
||||
*
|
||||
* Value is pixels minus 1. Must be set to 1 pixel for SDVO.
|
||||
*/
|
||||
# define DPLL_MD_UDI_DIVIDER_MASK 0x3f000000
|
||||
# define DPLL_MD_UDI_DIVIDER_SHIFT 24
|
||||
/** UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
|
||||
# define DPLL_MD_VGA_UDI_DIVIDER_MASK 0x003f0000
|
||||
# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT 16
|
||||
/**
|
||||
* SDVO/UDI pixel multiplier.
|
||||
*
|
||||
* SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
|
||||
* clock rate is 10 times the DPLL clock. At low resolution/refresh rate
|
||||
* modes, the bus rate would be below the limits, so SDVO allows for stuffing
|
||||
* dummy bytes in the datastream at an increased clock rate, with both sides of
|
||||
* the link knowing how many bytes are fill.
|
||||
*
|
||||
* So, for a mode with a dotclock of 65Mhz, we would want to double the clock
|
||||
* rate to 130Mhz to get a bus rate of 1.30Ghz. The DPLL clock rate would be
|
||||
* set to 130Mhz, and the SDVO multiplier set to 2x in this register and
|
||||
* through an SDVO command.
|
||||
*
|
||||
* This register field has values of multiplication factor minus 1, with
|
||||
* a maximum multiplier of 5 for SDVO.
|
||||
*/
|
||||
# define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00
|
||||
# define DPLL_MD_UDI_MULTIPLIER_SHIFT 8
|
||||
/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
|
||||
* This best be set to the default value (3) or the CRT won't work. No,
|
||||
* I don't entirely understand what this does...
|
||||
*/
|
||||
# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f
|
||||
# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0
|
||||
/** @} */
|
||||
|
||||
#define DPLL_TEST 0x606c
|
||||
# define DPLLB_TEST_SDVO_DIV_1 (0 << 22)
|
||||
# define DPLLB_TEST_SDVO_DIV_2 (1 << 22)
|
||||
# define DPLLB_TEST_SDVO_DIV_4 (2 << 22)
|
||||
# define DPLLB_TEST_SDVO_DIV_MASK (3 << 22)
|
||||
# define DPLLB_TEST_N_BYPASS (1 << 19)
|
||||
# define DPLLB_TEST_M_BYPASS (1 << 18)
|
||||
# define DPLLB_INPUT_BUFFER_ENABLE (1 << 16)
|
||||
# define DPLLA_TEST_N_BYPASS (1 << 3)
|
||||
# define DPLLA_TEST_M_BYPASS (1 << 2)
|
||||
# define DPLLA_INPUT_BUFFER_ENABLE (1 << 0)
|
||||
|
||||
#define ADPA 0x61100
|
||||
#define ADPA_DAC_ENABLE (1<<31)
|
||||
#define ADPA_DAC_DISABLE 0
|
||||
#define ADPA_PIPE_SELECT_MASK (1<<30)
|
||||
#define ADPA_PIPE_A_SELECT 0
|
||||
#define ADPA_PIPE_B_SELECT (1<<30)
|
||||
#define ADPA_USE_VGA_HVPOLARITY (1<<15)
|
||||
#define ADPA_SETS_HVPOLARITY 0
|
||||
#define ADPA_VSYNC_CNTL_DISABLE (1<<11)
|
||||
#define ADPA_VSYNC_CNTL_ENABLE 0
|
||||
#define ADPA_HSYNC_CNTL_DISABLE (1<<10)
|
||||
#define ADPA_HSYNC_CNTL_ENABLE 0
|
||||
#define ADPA_VSYNC_ACTIVE_HIGH (1<<4)
|
||||
#define ADPA_VSYNC_ACTIVE_LOW 0
|
||||
#define ADPA_HSYNC_ACTIVE_HIGH (1<<3)
|
||||
#define ADPA_HSYNC_ACTIVE_LOW 0
|
||||
|
||||
#define FPA0 0x06040
|
||||
#define FPA1 0x06044
|
||||
#define FPB0 0x06048
|
||||
#define FPB1 0x0604c
|
||||
# define FP_N_DIV_MASK 0x003f0000
|
||||
# define FP_N_DIV_SHIFT 16
|
||||
# define FP_M1_DIV_MASK 0x00003f00
|
||||
# define FP_M1_DIV_SHIFT 8
|
||||
# define FP_M2_DIV_MASK 0x0000003f
|
||||
# define FP_M2_DIV_SHIFT 0
|
||||
|
||||
|
||||
#define PORT_HOTPLUG_EN 0x61110
|
||||
# define SDVOB_HOTPLUG_INT_EN (1 << 26)
|
||||
# define SDVOC_HOTPLUG_INT_EN (1 << 25)
|
||||
# define TV_HOTPLUG_INT_EN (1 << 18)
|
||||
# define CRT_HOTPLUG_INT_EN (1 << 9)
|
||||
# define CRT_HOTPLUG_FORCE_DETECT (1 << 3)
|
||||
|
||||
#define PORT_HOTPLUG_STAT 0x61114
|
||||
# define CRT_HOTPLUG_INT_STATUS (1 << 11)
|
||||
# define TV_HOTPLUG_INT_STATUS (1 << 10)
|
||||
# define CRT_HOTPLUG_MONITOR_MASK (3 << 8)
|
||||
# define CRT_HOTPLUG_MONITOR_COLOR (3 << 8)
|
||||
# define CRT_HOTPLUG_MONITOR_MONO (2 << 8)
|
||||
# define CRT_HOTPLUG_MONITOR_NONE (0 << 8)
|
||||
# define SDVOC_HOTPLUG_INT_STATUS (1 << 7)
|
||||
# define SDVOB_HOTPLUG_INT_STATUS (1 << 6)
|
||||
|
||||
#define SDVOB 0x61140
|
||||
#define SDVOC 0x61160
|
||||
#define SDVO_ENABLE (1 << 31)
|
||||
#define SDVO_PIPE_B_SELECT (1 << 30)
|
||||
#define SDVO_STALL_SELECT (1 << 29)
|
||||
#define SDVO_INTERRUPT_ENABLE (1 << 26)
|
||||
/**
|
||||
* 915G/GM SDVO pixel multiplier.
|
||||
*
|
||||
* Programmed value is multiplier - 1, up to 5x.
|
||||
*
|
||||
* \sa DPLL_MD_UDI_MULTIPLIER_MASK
|
||||
*/
|
||||
#define SDVO_PORT_MULTIPLY_MASK (7 << 23)
|
||||
#define SDVO_PORT_MULTIPLY_SHIFT 23
|
||||
#define SDVO_PHASE_SELECT_MASK (15 << 19)
|
||||
#define SDVO_PHASE_SELECT_DEFAULT (6 << 19)
|
||||
#define SDVO_CLOCK_OUTPUT_INVERT (1 << 18)
|
||||
#define SDVOC_GANG_MODE (1 << 16)
|
||||
#define SDVO_BORDER_ENABLE (1 << 7)
|
||||
#define SDVOB_PCIE_CONCURRENCY (1 << 3)
|
||||
#define SDVO_DETECTED (1 << 2)
|
||||
/* Bits to be preserved when writing */
|
||||
#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14))
|
||||
#define SDVOC_PRESERVE_MASK (1 << 17)
|
||||
|
||||
/** @defgroup LVDS
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* This register controls the LVDS output enable, pipe selection, and data
|
||||
* format selection.
|
||||
*
|
||||
* All of the clock/data pairs are force powered down by power sequencing.
|
||||
*/
|
||||
#define LVDS 0x61180
|
||||
/**
|
||||
* Enables the LVDS port. This bit must be set before DPLLs are enabled, as
|
||||
* the DPLL semantics change when the LVDS is assigned to that pipe.
|
||||
*/
|
||||
# define LVDS_PORT_EN (1 << 31)
|
||||
/** Selects pipe B for LVDS data. Must be set on pre-965. */
|
||||
# define LVDS_PIPEB_SELECT (1 << 30)
|
||||
|
||||
/**
|
||||
* Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
|
||||
* pixel.
|
||||
*/
|
||||
# define LVDS_A0A2_CLKA_POWER_MASK (3 << 8)
|
||||
# define LVDS_A0A2_CLKA_POWER_DOWN (0 << 8)
|
||||
# define LVDS_A0A2_CLKA_POWER_UP (3 << 8)
|
||||
/**
|
||||
* Controls the A3 data pair, which contains the additional LSBs for 24 bit
|
||||
* mode. Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
|
||||
* on.
|
||||
*/
|
||||
# define LVDS_A3_POWER_MASK (3 << 6)
|
||||
# define LVDS_A3_POWER_DOWN (0 << 6)
|
||||
# define LVDS_A3_POWER_UP (3 << 6)
|
||||
/**
|
||||
* Controls the CLKB pair. This should only be set when LVDS_B0B3_POWER_UP
|
||||
* is set.
|
||||
*/
|
||||
# define LVDS_CLKB_POWER_MASK (3 << 4)
|
||||
# define LVDS_CLKB_POWER_DOWN (0 << 4)
|
||||
# define LVDS_CLKB_POWER_UP (3 << 4)
|
||||
|
||||
/**
|
||||
* Controls the B0-B3 data pairs. This must be set to match the DPLL p2
|
||||
* setting for whether we are in dual-channel mode. The B3 pair will
|
||||
* additionally only be powered up when LVDS_A3_POWER_UP is set.
|
||||
*/
|
||||
# define LVDS_B0B3_POWER_MASK (3 << 2)
|
||||
# define LVDS_B0B3_POWER_DOWN (0 << 2)
|
||||
# define LVDS_B0B3_POWER_UP (3 << 2)
|
||||
|
||||
#define PIPEACONF 0x70008
|
||||
#define PIPEACONF_ENABLE (1<<31)
|
||||
#define PIPEACONF_DISABLE 0
|
||||
#define PIPEACONF_DOUBLE_WIDE (1<<30)
|
||||
#define I965_PIPECONF_ACTIVE (1<<30)
|
||||
#define PIPEACONF_SINGLE_WIDE 0
|
||||
#define PIPEACONF_PIPE_UNLOCKED 0
|
||||
#define PIPEACONF_PIPE_LOCKED (1<<25)
|
||||
#define PIPEACONF_PALETTE 0
|
||||
#define PIPEACONF_GAMMA (1<<24)
|
||||
#define PIPECONF_FORCE_BORDER (1<<25)
|
||||
#define PIPECONF_PROGRESSIVE (0 << 21)
|
||||
#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21)
|
||||
#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21)
|
||||
|
||||
#define PIPEBCONF 0x71008
|
||||
#define PIPEBCONF_ENABLE (1<<31)
|
||||
#define PIPEBCONF_DISABLE 0
|
||||
#define PIPEBCONF_DOUBLE_WIDE (1<<30)
|
||||
#define PIPEBCONF_DISABLE 0
|
||||
#define PIPEBCONF_GAMMA (1<<24)
|
||||
#define PIPEBCONF_PALETTE 0
|
||||
|
||||
#define PIPEBGCMAXRED 0x71010
|
||||
#define PIPEBGCMAXGREEN 0x71014
|
||||
#define PIPEBGCMAXBLUE 0x71018
|
||||
#define PIPEBSTAT 0x71024
|
||||
#define PIPEBFRAMEHIGH 0x71040
|
||||
#define PIPEBFRAMEPIXEL 0x71044
|
||||
|
||||
#define DSPACNTR 0x70180
|
||||
#define DSPBCNTR 0x71180
|
||||
#define DISPLAY_PLANE_ENABLE (1<<31)
|
||||
#define DISPLAY_PLANE_DISABLE 0
|
||||
#define DISPPLANE_GAMMA_ENABLE (1<<30)
|
||||
#define DISPPLANE_GAMMA_DISABLE 0
|
||||
#define DISPPLANE_PIXFORMAT_MASK (0xf<<26)
|
||||
#define DISPPLANE_8BPP (0x2<<26)
|
||||
#define DISPPLANE_15_16BPP (0x4<<26)
|
||||
#define DISPPLANE_16BPP (0x5<<26)
|
||||
#define DISPPLANE_32BPP_NO_ALPHA (0x6<<26)
|
||||
#define DISPPLANE_32BPP (0x7<<26)
|
||||
#define DISPPLANE_STEREO_ENABLE (1<<25)
|
||||
#define DISPPLANE_STEREO_DISABLE 0
|
||||
#define DISPPLANE_SEL_PIPE_MASK (1<<24)
|
||||
#define DISPPLANE_SEL_PIPE_A 0
|
||||
#define DISPPLANE_SEL_PIPE_B (1<<24)
|
||||
#define DISPPLANE_SRC_KEY_ENABLE (1<<22)
|
||||
#define DISPPLANE_SRC_KEY_DISABLE 0
|
||||
#define DISPPLANE_LINE_DOUBLE (1<<20)
|
||||
#define DISPPLANE_NO_LINE_DOUBLE 0
|
||||
#define DISPPLANE_STEREO_POLARITY_FIRST 0
|
||||
#define DISPPLANE_STEREO_POLARITY_SECOND (1<<18)
|
||||
/* plane B only */
|
||||
#define DISPPLANE_ALPHA_TRANS_ENABLE (1<<15)
|
||||
#define DISPPLANE_ALPHA_TRANS_DISABLE 0
|
||||
#define DISPPLANE_SPRITE_ABOVE_DISPLAYA 0
|
||||
#define DISPPLANE_SPRITE_ABOVE_OVERLAY (1)
|
||||
|
||||
#define DSPABASE 0x70184
|
||||
#define DSPASTRIDE 0x70188
|
||||
|
||||
#define DSPBBASE 0x71184
|
||||
#define DSPBADDR DSPBBASE
|
||||
#define DSPBSTRIDE 0x71188
|
||||
|
||||
#define DSPAKEYVAL 0x70194
|
||||
#define DSPAKEYMASK 0x70198
|
||||
|
||||
#define DSPAPOS 0x7018C /* reserved */
|
||||
#define DSPASIZE 0x70190
|
||||
#define DSPBPOS 0x7118C
|
||||
#define DSPBSIZE 0x71190
|
||||
|
||||
#define DSPASURF 0x7019C
|
||||
#define DSPATILEOFF 0x701A4
|
||||
|
||||
#define DSPBSURF 0x7119C
|
||||
#define DSPBTILEOFF 0x711A4
|
||||
|
||||
#define VGACNTRL 0x71400
|
||||
# define VGA_DISP_DISABLE (1 << 31)
|
||||
# define VGA_2X_MODE (1 << 30)
|
||||
# define VGA_PIPE_B_SELECT (1 << 29)
|
||||
|
||||
/*
|
||||
* Palette registers
|
||||
*/
|
||||
#define PALETTE_A 0x0a000
|
||||
#define PALETTE_B 0x0a800
|
||||
|
||||
#define IS_I830(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82830_CGC)
|
||||
#define IS_845G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82845G_IG)
|
||||
#define IS_I85X(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82855GM_IG)
|
||||
#define IS_I855(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82855GM_IG)
|
||||
#define IS_I865G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82865_IG)
|
||||
|
||||
#define IS_I915G(pI810) (dev->pci_device == PCI_DEVICE_ID_INTEL_82915G_IG)/* || dev->pci_device == PCI_DEVICE_ID_INTELPCI_CHIP_E7221_G)*/
|
||||
#define IS_I915GM(pI810) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82915GM_IG)
|
||||
#define IS_I945G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82945G_IG)
|
||||
#define IS_I945GM(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82945GM_IG)
|
||||
|
||||
#define IS_I965G(dev) ((dev)->pci_device == 0x2972 || \
|
||||
(dev)->pci_device == 0x2982 || \
|
||||
(dev)->pci_device == 0x2992 || \
|
||||
(dev)->pci_device == 0x29A2)
|
||||
|
||||
|
||||
#define IS_I9XX(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810) || IS_I965G(pI810))
|
||||
|
||||
#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810))
|
||||
|
||||
#endif
|
||||
|
|
|
|||
304
shared-core/i915_init.c
Normal file
304
shared-core/i915_init.c
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Intel Corporation
|
||||
* Jesse Barnes <jesse.barnes@intel.com>
|
||||
*
|
||||
* Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
|
||||
* 2004 Sylvain Meyer
|
||||
*
|
||||
* GPL/BSD dual license
|
||||
*/
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "drm_sarea.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
/**
|
||||
* i915_probe_agp - get AGP bootup configuration
|
||||
* @pdev: PCI device
|
||||
* @aperture_size: returns AGP aperture configured size
|
||||
* @preallocated_size: returns size of BIOS preallocated AGP space
|
||||
*
|
||||
* Since Intel integrated graphics are UMA, the BIOS has to set aside
|
||||
* some RAM for the framebuffer at early boot. This code figures out
|
||||
* how much was set aside so we can use it for our own purposes.
|
||||
*/
|
||||
int i915_probe_agp(struct pci_dev *pdev, unsigned long *aperture_size,
|
||||
unsigned long *preallocated_size)
|
||||
{
|
||||
struct pci_dev *bridge_dev;
|
||||
u16 tmp = 0;
|
||||
unsigned long overhead;
|
||||
|
||||
bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
|
||||
if (!bridge_dev) {
|
||||
DRM_ERROR("bridge device not found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get the fb aperture size and "stolen" memory amount. */
|
||||
pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp);
|
||||
pci_dev_put(bridge_dev);
|
||||
|
||||
*aperture_size = 1024 * 1024;
|
||||
*preallocated_size = 1024 * 1024;
|
||||
|
||||
switch (pdev->device) {
|
||||
case PCI_DEVICE_ID_INTEL_82830_CGC:
|
||||
case PCI_DEVICE_ID_INTEL_82845G_HB:
|
||||
case PCI_DEVICE_ID_INTEL_82855GM_IG:
|
||||
case PCI_DEVICE_ID_INTEL_82865_IG:
|
||||
if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M)
|
||||
*aperture_size *= 64;
|
||||
else
|
||||
*aperture_size *= 128;
|
||||
break;
|
||||
default:
|
||||
/* 9xx supports large sizes, just look at the length */
|
||||
*aperture_size = pci_resource_len(pdev, 2);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some of the preallocated space is taken by the GTT
|
||||
* and popup. GTT is 1K per MB of aperture size, and popup is 4K.
|
||||
*/
|
||||
overhead = (*aperture_size / 1024) + 4096;
|
||||
switch (tmp & INTEL_855_GMCH_GMS_MASK) {
|
||||
case INTEL_855_GMCH_GMS_STOLEN_1M:
|
||||
break; /* 1M already */
|
||||
case INTEL_855_GMCH_GMS_STOLEN_4M:
|
||||
*preallocated_size *= 4;
|
||||
break;
|
||||
case INTEL_855_GMCH_GMS_STOLEN_8M:
|
||||
*preallocated_size *= 8;
|
||||
break;
|
||||
case INTEL_855_GMCH_GMS_STOLEN_16M:
|
||||
*preallocated_size *= 16;
|
||||
break;
|
||||
case INTEL_855_GMCH_GMS_STOLEN_32M:
|
||||
*preallocated_size *= 32;
|
||||
break;
|
||||
case INTEL_915G_GMCH_GMS_STOLEN_48M:
|
||||
*preallocated_size *= 48;
|
||||
break;
|
||||
case INTEL_915G_GMCH_GMS_STOLEN_64M:
|
||||
*preallocated_size *= 64;
|
||||
break;
|
||||
case INTEL_855_GMCH_GMS_DISABLED:
|
||||
DRM_ERROR("video memory is disabled\n");
|
||||
return -1;
|
||||
default:
|
||||
DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n",
|
||||
tmp & INTEL_855_GMCH_GMS_MASK);
|
||||
return -1;
|
||||
}
|
||||
*preallocated_size -= overhead;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i915_driver_load - setup chip and create an initial config
|
||||
* @dev: DRM device
|
||||
* @flags: startup flags
|
||||
*
|
||||
* The driver load routine has to do several things:
|
||||
* - drive output discovery via intel_modeset_init()
|
||||
* - initialize the memory manager
|
||||
* - allocate initial config memory
|
||||
* - setup the DRM framebuffer with the allocated memory
|
||||
*/
|
||||
int i915_driver_load(drm_device_t *dev, unsigned long flags)
|
||||
{
|
||||
drm_i915_private_t *dev_priv;
|
||||
drm_i915_init_t init;
|
||||
drm_buffer_object_t *entry;
|
||||
struct drm_framebuffer *fb;
|
||||
unsigned long agp_size, prealloc_size;
|
||||
int hsize, vsize, bytes_per_pixel, size, ret;
|
||||
|
||||
dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER);
|
||||
if (dev_priv == NULL)
|
||||
return DRM_ERR(ENOMEM);
|
||||
|
||||
memset(dev_priv, 0, sizeof(drm_i915_private_t));
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
// dev_priv->flags = flags;
|
||||
|
||||
/* i915 has 4 more counters */
|
||||
dev->counters += 4;
|
||||
dev->types[6] = _DRM_STAT_IRQ;
|
||||
dev->types[7] = _DRM_STAT_PRIMARY;
|
||||
dev->types[8] = _DRM_STAT_SECONDARY;
|
||||
dev->types[9] = _DRM_STAT_DMA;
|
||||
|
||||
if (IS_I9XX(dev)) {
|
||||
dev_priv->mmiobase = drm_get_resource_start(dev, 0);
|
||||
dev_priv->mmiolen = drm_get_resource_len(dev, 0);
|
||||
dev->mode_config.fb_base = dev_priv->baseaddr =
|
||||
drm_get_resource_start(dev, 2) & 0xff000000;
|
||||
} else if (drm_get_resource_start(dev, 1)) {
|
||||
dev_priv->mmiobase = drm_get_resource_start(dev, 1);
|
||||
dev_priv->mmiolen = drm_get_resource_len(dev, 1);
|
||||
dev->mode_config.fb_base = dev_priv->baseaddr =
|
||||
drm_get_resource_start(dev, 0) & 0xff000000;
|
||||
} else {
|
||||
DRM_ERROR("Unable to find MMIO registers\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = drm_addmap(dev, dev_priv->mmiobase, dev_priv->mmiolen,
|
||||
_DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->mmio_map);
|
||||
if (ret != 0) {
|
||||
DRM_ERROR("Cannot add mapping for MMIO registers\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = drm_setup(dev);
|
||||
if (ret) {
|
||||
DRM_ERROR("drm_setup failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
DRM_GETSAREA();
|
||||
if (!dev_priv->sarea) {
|
||||
DRM_ERROR("can not find sarea!\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
i915_dma_cleanup(dev);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
/* FIXME: assume sarea_priv is right after SAREA */
|
||||
dev_priv->sarea_priv = dev_priv->sarea->handle + sizeof(drm_sarea_t);
|
||||
|
||||
/*
|
||||
* Initialize the memory manager for local and AGP space
|
||||
*/
|
||||
drm_bo_driver_init(dev);
|
||||
|
||||
i915_probe_agp(dev->pdev, &agp_size, &prealloc_size);
|
||||
drm_bo_init_mm(dev, DRM_BO_MEM_PRIV0, dev_priv->baseaddr,
|
||||
prealloc_size);
|
||||
|
||||
/* Allocate scanout buffer and command ring */
|
||||
/* FIXME: types and other args correct? */
|
||||
hsize = 1280;
|
||||
vsize = 800;
|
||||
bytes_per_pixel = 4;
|
||||
size = hsize * vsize * 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, PAGE_SIZE, 0,
|
||||
&entry);
|
||||
|
||||
DRM_DEBUG("allocated bo, start: 0x%lx, offset: 0x%lx\n",
|
||||
entry->buffer_start, entry->offset);
|
||||
intel_modeset_init(dev);
|
||||
|
||||
fb = drm_framebuffer_create(dev);
|
||||
if (!fb) {
|
||||
DRM_ERROR("failed to allocate fb\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fb->width = hsize;
|
||||
fb->height = vsize;
|
||||
fb->pitch = hsize;
|
||||
fb->bits_per_pixel = bytes_per_pixel * 8;
|
||||
fb->depth = bytes_per_pixel * 8;
|
||||
fb->offset = entry->offset;
|
||||
fb->bo = entry;
|
||||
|
||||
drm_initial_config(dev, fb, false);
|
||||
drmfb_probe(dev, fb);
|
||||
#if 0
|
||||
/* FIXME: command ring needs AGP space, do we own it at this point? */
|
||||
dev_priv->ring.Start = dev_priv->baseaddr;
|
||||
dev_priv->ring.End = 128*1024;
|
||||
dev_priv->ring.Size = 128*1024;
|
||||
dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
|
||||
|
||||
dev_priv->ring.map.offset = dev_priv->ring.Start;
|
||||
dev_priv->ring.map.size = dev_priv->ring.Size;
|
||||
dev_priv->ring.map.type = 0;
|
||||
dev_priv->ring.map.flags = 0;
|
||||
dev_priv->ring.map.mtrr = 0;
|
||||
|
||||
drm_core_ioremap(&dev_priv->ring.map, dev);
|
||||
|
||||
if (dev_priv->ring.map.handle == NULL) {
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
i915_dma_cleanup(dev);
|
||||
DRM_ERROR("can not ioremap virtual address for"
|
||||
" ring buffer\n");
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
|
||||
dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
|
||||
dev_priv->cpp = 4;
|
||||
dev_priv->sarea_priv->pf_current_page = 0;
|
||||
|
||||
/* We are using separate values as placeholders for mechanisms for
|
||||
* private backbuffer/depthbuffer usage.
|
||||
*/
|
||||
dev_priv->use_mi_batchbuffer_start = 0;
|
||||
|
||||
/* Allow hardware batchbuffers unless told otherwise.
|
||||
*/
|
||||
dev_priv->allow_batchbuffer = 1;
|
||||
|
||||
/* Program Hardware Status Page */
|
||||
dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE,
|
||||
0xffffffff);
|
||||
|
||||
if (!dev_priv->status_page_dmah) {
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
i915_dma_cleanup(dev);
|
||||
DRM_ERROR("Can not allocate hardware status page\n");
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
|
||||
dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
|
||||
|
||||
memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
|
||||
DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
|
||||
|
||||
I915_WRITE(0x02080, dev_priv->dma_status_page);
|
||||
DRM_DEBUG("Enabled hardware status page\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i915_driver_unload(drm_device_t *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_framebuffer *fb;
|
||||
|
||||
/* FIXME: remove framebuffer */
|
||||
intel_modeset_cleanup(dev);
|
||||
drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
|
||||
|
||||
dev->dev_private = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i915_driver_lastclose(drm_device_t * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
i915_mem_takedown(&(dev_priv->agp_heap));
|
||||
|
||||
i915_dma_cleanup(dev);
|
||||
|
||||
dev_priv->mmio_map = NULL;
|
||||
}
|
||||
|
||||
void i915_driver_preclose(drm_device_t * dev, DRMFILE filp)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
i915_mem_release(dev, filp, dev_priv->agp_heap);
|
||||
}
|
||||
|
||||
Loading…
Add table
Reference in a new issue