summaryrefslogtreecommitdiff
path: root/linux-core
diff options
context:
space:
mode:
authorroot <root@localhost.(none)>2007-05-17 12:46:36 +0100
committerroot <root@localhost.(none)>2007-05-17 12:46:36 +0100
commit5ce8aaae7251e60c078eda0a21894aae0e1d7a45 (patch)
tree97855e1a7492e547445f2a56e84a3b70d8683108 /linux-core
parenteba00df1203040905d38bf0ef449d25d6dbdb72c (diff)
Large changes for fbdev support.
Change from DIRECTCOLOR to TRUECOLOR, and enable support for PSEUDOCOLOR. DIRECTCOLOR support needs more work. Add the ability to change the mode on the fbdev device. Support depth 8, 15, 16 and 24 (and 32). Add a /dev/fbX device per CRTC, but there's some code which doesn't allocate the fbX device unless the output is actually enabled. Read the code on this as it impacts the fbcon map flags. Pick CRTC's based on the available outputs. More work could be done here to match modes, so cloning could be achieved on outputs. This fits more inline with what the X code does.
Diffstat (limited to 'linux-core')
-rw-r--r--linux-core/drm_crtc.c234
-rw-r--r--linux-core/drm_crtc.h11
-rw-r--r--linux-core/drm_fb.c267
-rw-r--r--linux-core/intel_display.c23
-rw-r--r--linux-core/intel_drv.h2
-rw-r--r--linux-core/intel_lvds.c12
-rw-r--r--linux-core/intel_sdvo.c14
7 files changed, 375 insertions, 188 deletions
diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c
index a8f14e17..d710a4e7 100644
--- a/linux-core/drm_crtc.c
+++ b/linux-core/drm_crtc.c
@@ -467,51 +467,6 @@ done:
}
/**
- * drm_set_desired_modes - set a good mode on every CRTC & output
- * @dev: DRM device
- *
- * LOCKING:
- * Caller? (FIXME)
- *
- * Each CRTC may have a desired mode associated with it. This routine simply
- * walks @dev's mode_config and sets the desired mode on every CRTC. Intended
- * for use at startup time.
- *
- * RETURNS:
- * True if modes were set, false otherwise.
- */
-bool drm_set_desired_modes(struct drm_device *dev)
-{
- struct drm_crtc *crtc;
- struct drm_output *output, *list_output;
-
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- output = NULL;
-
- list_for_each_entry(list_output, &dev->mode_config.output_list,
- head) {
- if (list_output->crtc == crtc) {
- output = list_output;
- break;
- }
- }
- /* Skip disabled crtcs */
- if (!output) {
- DRM_DEBUG("skipping disabled crtc\n");
- continue;
- }
-
- if (!drm_crtc_set_mode(crtc, crtc->desired_mode,
- crtc->desired_x, crtc->desired_y))
- return false;
- }
-
- drm_disable_unused_functions(dev);
- return true;
-}
-EXPORT_SYMBOL(drm_set_desired_modes);
-
-/**
* drm_disable_unused_functions - disable unused objects
* @dev: DRM device
*
@@ -799,26 +754,82 @@ out_err:
}
/**
- * drm_setup_output - setup an output structure
- * @output: output to setup
- * @crtc: CRTC this output belongs to
- * @mode: desired mode for this output
+ * drm_pick_crtcs - pick crtcs for output devices
+ * @dev: DRM device
*
* LOCKING:
* None.
- *
- * Setup @output with the parameters given, with its initial coordinates set
- * at the origin.
*/
-static void drm_setup_output(struct drm_output *output, struct drm_crtc *crtc,
- struct drm_display_mode *mode)
+static void drm_pick_crtcs (drm_device_t *dev)
{
- output->crtc = crtc;
- output->crtc->desired_mode = mode;
- output->initial_x = 0;
- output->initial_y = 0;
+ int c, o;
+ struct drm_output *output, *output_equal;
+ struct drm_crtc *crtc;
+ struct drm_display_mode *des_mode = NULL, *modes, *modes_equal;
+
+ list_for_each_entry(output, &dev->mode_config.output_list, head) {
+ output->crtc = NULL;
+
+ /* Don't hook up outputs that are disconnected ??
+ *
+ * This is debateable. Do we want fixed /dev/fbX or
+ * dynamic on hotplug (need mode code for that though) ?
+ *
+ * If we don't hook up outputs now, then we only create
+ * /dev/fbX for the output that's enabled, that's good as
+ * the users console will be on that output.
+ *
+ * If we do hook up outputs that are disconnected now, then
+ * the user may end up having to muck about with the fbcon
+ * map flags to assign his console to the enabled output. Ugh.
+ */
+ if (output->status != output_status_connected)
+ continue;
+
+ des_mode = NULL;
+ list_for_each_entry(des_mode, &output->modes, head) {
+ if (des_mode->flags & DRM_MODE_TYPE_PREFERRED)
+ break;
+ }
+
+ c = -1;
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ c++;
+ if ((output->possible_crtcs & (1 << c)) == 0)
+ continue;
+
+#if 0 /* should we try and clone ?? - code not tested - FIXME */
+ o = -1;
+ list_for_each_entry(output_equal, &dev->mode_config.output_list, head) {
+ o++;
+ if (output->id == output_equal->id)
+ continue;
+
+ list_for_each_entry(modes, &output->modes, head) {
+ list_for_each_entry(modes_equal, &output_equal->modes, head) {
+ if (drm_mode_equal (modes, modes_equal)) {
+ if ((output->possible_clones & (1 << o))) {
+ goto clone;
+ }
+ }
+ }
+ }
+ }
+
+clone:
+#endif
+ /* Found a CRTC to attach to, do it ! */
+ output->crtc = crtc;
+ output->crtc->desired_mode = des_mode;
+ output->initial_x = 0;
+ output->initial_y = 0;
+ DRM_DEBUG("Desired mode for CRTC %d is %dx%x\n",c,des_mode->hdisplay,des_mode->vdisplay);
+ break;
+ }
+ }
}
+
/**
* drm_initial_config - setup a sane initial output configuration
* @dev: DRM device
@@ -831,109 +842,61 @@ static void drm_setup_output(struct drm_output *output, struct drm_crtc *crtc,
* At the moment, this is a cloned configuration across all heads with
* a new framebuffer object as the backing store.
*
- * FIXME: return value and better initial config.
- *
* RETURNS:
* Zero if everything went ok, nonzero otherwise.
*/
bool drm_initial_config(drm_device_t *dev, bool can_grow)
{
/* do a hardcoded initial configuration here */
- struct drm_crtc *crtc, *vga_crtc = NULL, *tmds_crtc = NULL,
- *lvds_crtc = NULL;
+ struct drm_display_mode *des_mode = NULL;
struct drm_output *output;
struct drm_framebuffer *fb;
drm_buffer_object_t *fbo;
unsigned long size, bytes_per_pixel;
- fb = drm_framebuffer_create(dev);
- if (!fb) {
- DRM_ERROR("failed to allocate fb.\n");
- return true;
- }
-
- /* bind both CRTCs to this fb */
- /* only initialise one crtc to enabled state */
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- crtc->fb = fb;
- if (!vga_crtc) {
- vga_crtc = crtc;
- crtc->enabled = 1;
- crtc->desired_x = 0;
- crtc->desired_y = 0;
- } else {
- if (!lvds_crtc) {
- lvds_crtc = crtc;
- crtc->enabled = 1;
- crtc->desired_x = 0;
- crtc->desired_y = 0;
- }
- if (!tmds_crtc) {
- tmds_crtc = crtc;
- crtc->enabled = 1;
- crtc->desired_x = 0;
- crtc->desired_y = 0;
- }
- }
- }
-
drm_crtc_probe_output_modes(dev, 2048, 2048);
- /* hard bind the CRTCS */
+ drm_pick_crtcs(dev);
- /* bind analog output to one crtc */
list_for_each_entry(output, &dev->mode_config.output_list, head) {
- struct drm_display_mode *des_mode = NULL;
- if (list_empty(&output->modes))
+ /* can't setup the output if there's no assigned crtc or mode */
+ if (!output->crtc || !output->crtc->desired_mode)
continue;
- /* Get the first preferred moded */
- list_for_each_entry(des_mode, &output->modes, head) {
- if (des_mode->flags & DRM_MODE_TYPE_PREFERRED)
- break;
+ fb = drm_framebuffer_create(dev);
+ if (!fb) {
+ DRM_ERROR("failed to allocate fb.\n");
+ return true;
}
+ output->crtc->fb = fb;
+ des_mode = output->crtc->desired_mode;
- if (!des_mode)
- continue;
-
- if (!strncmp(output->name, "VGA", 3)) {
- DRM_DEBUG("VGA preferred mode: %s\n", des_mode->name);
- drm_setup_output(output, vga_crtc, des_mode);
- } else if (!strncmp(output->name, "TMDS", 4)) {
- DRM_DEBUG("TMDS preferred mode: %s\n", des_mode->name);
- drm_setup_output(output, tmds_crtc, des_mode);
- } else if (!strncmp(output->name, "LVDS", 3)) {
- DRM_DEBUG("LVDS preferred mode: %s\n", des_mode->name);
- drm_setup_output(output, lvds_crtc, des_mode);
- } else
- output->crtc = NULL;
-
- /* FB config is max of above desired resolutions */
- /* FIXME: per-output FBs/CRTCs */
if (des_mode->hdisplay > fb->width) {
fb->width = des_mode->hdisplay;
fb->pitch = fb->width;
}
if (des_mode->vdisplay > fb->height)
fb->height = des_mode->vdisplay;
- }
- /* FIXME: multiple depths */
- bytes_per_pixel = 4;
- fb->bits_per_pixel = bytes_per_pixel * 8;
- fb->depth = bytes_per_pixel * 8;
- size = fb->width * fb->height * bytes_per_pixel;
- drm_buffer_object_create(dev, size, drm_bo_type_kernel,
+ /* FIXME: multiple depths */
+ bytes_per_pixel = 4;
+ fb->bits_per_pixel = 32;
+ fb->depth = 24;
+ size = fb->pitch * fb->height * bytes_per_pixel;
+ /* FIXME - what about resizeable objects ??? */
+ drm_buffer_object_create(dev, size, drm_bo_type_kernel,
DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE |
DRM_BO_FLAG_MEM_PRIV0 | DRM_BO_FLAG_NO_MOVE,
0, 0, 0,
&fbo);
- DRM_DEBUG("allocated %dx%d fb: 0x%08lx, bo %p\n", fb->width,
- fb->height, fbo->offset, fbo);
- fb->offset = fbo->offset;
- fb->bo = fbo;
- drmfb_probe(dev, fb);
+ printk("allocated %dx%d fb: 0x%08lx, bo %p\n", fb->width,
+ fb->height, fbo->offset, fbo);
+ fb->offset = fbo->offset;
+ fb->bo = fbo;
+ drmfb_probe(dev, output->crtc);
+ }
+ drm_disable_unused_functions(dev);
return false;
}
@@ -1582,17 +1545,20 @@ int drm_mode_addfb(struct inode *inode, struct file *filp,
r.buffer_id = fb->id;
list_add(&fb->filp_head, &priv->fbs);
+
+ if (copy_to_user(argp, &r, sizeof(r)))
+ return -EFAULT;
+
/* bind the fb to the crtc for now */
{
struct drm_crtc *crtc;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
crtc->fb = fb;
+
+ drmfb_probe(dev, crtc);
}
}
- if (copy_to_user(argp, &r, sizeof(r)))
- return -EFAULT;
- drmfb_probe(dev, fb);
return 0;
}
@@ -1629,6 +1595,7 @@ int drm_mode_rmfb(struct inode *inode, struct file *filp,
}
drmfb_remove(dev, fb);
+
/* TODO check if we own the buffer */
/* TODO release all crtc connected to the framebuffer */
/* bind the fb to the crtc for now */
@@ -1711,7 +1678,6 @@ void drm_fb_release(struct file *filp)
list_del(&fb->filp_head);
drmfb_remove(dev, fb);
drm_framebuffer_destroy(fb);
-
}
}
diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h
index 12c7eef1..fa143e6e 100644
--- a/linux-core/drm_crtc.h
+++ b/linux-core/drm_crtc.h
@@ -294,8 +294,8 @@ struct drm_crtc_funcs {
void (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode, int x, int y);
/* Set gamma on the CRTC */
- void (*gamma_set)(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
- int size);
+ void (*gamma_set)(struct drm_crtc *crtc, u16 r, u16 g, u16 b,
+ int regno);
/* Driver cleanup routine */
void (*cleanup)(struct drm_crtc *crtc);
};
@@ -320,7 +320,7 @@ struct drm_crtc {
int id; /* idr assigned */
- /* framebuffer the CRTC is currently bound to */
+ /* framebuffer the output is currently bound to */
struct drm_framebuffer *fb;
bool enabled;
@@ -439,6 +439,7 @@ struct drm_output {
void *driver_private;
u32 user_mode_ids[DRM_OUTPUT_MAX_UMODES];
+
};
/**
@@ -498,6 +499,7 @@ extern void drm_mode_debug_printmodeline(struct drm_device *dev,
extern void drm_mode_config_init(struct drm_device *dev);
extern void drm_mode_config_cleanup(struct drm_device *dev);
extern void drm_mode_set_name(struct drm_display_mode *mode);
+extern bool drm_mode_equal(struct drm_display_mode *mode1, struct drm_display_mode *mode2);
extern void drm_disable_unused_functions(struct drm_device *dev);
extern struct drm_display_mode *drm_mode_create(struct drm_device *dev);
@@ -519,8 +521,7 @@ extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev);
extern bool drm_initial_config(struct drm_device *dev, bool cangrow);
extern void drm_framebuffer_set_object(struct drm_device *dev,
unsigned long handle);
-extern bool drm_set_desired_modes(struct drm_device *dev);
-extern int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb);
+extern int drmfb_probe(struct drm_device *dev, struct drm_crtc *crtc);
extern int drmfb_remove(struct drm_device *dev, struct drm_framebuffer *fb);
/* IOCTLs */
diff --git a/linux-core/drm_fb.c b/linux-core/drm_fb.c
index c0453258..8fd0f620 100644
--- a/linux-core/drm_fb.c
+++ b/linux-core/drm_fb.c
@@ -39,9 +39,11 @@
#include <linux/init.h>
#include "drmP.h"
+#include "drm_crtc.h"
+
struct drmfb_par {
struct drm_device *dev;
- struct drm_framebuffer *fb;
+ struct drm_crtc *crtc;
};
static int drmfb_setcolreg(unsigned regno, unsigned red, unsigned green,
@@ -49,11 +51,20 @@ static int drmfb_setcolreg(unsigned regno, unsigned red, unsigned green,
struct fb_info *info)
{
struct drmfb_par *par = info->par;
- struct drm_framebuffer *fb = par->fb;
- if (regno > 17)
+ struct drm_framebuffer *fb = par->crtc->fb;
+ struct drm_crtc *crtc = par->crtc;
+
+ if (regno > 255)
return 1;
- if (regno < 16) {
+ if (fb->depth == 8) {
+ if (crtc->funcs->gamma_set) {
+ crtc->funcs->gamma_set(crtc, red, green, blue, regno);
+ }
+ return 0;
+ }
+
+ if (regno < 16) {
switch (fb->depth) {
case 15:
fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) |
@@ -72,8 +83,118 @@ static int drmfb_setcolreg(unsigned regno, unsigned red, unsigned green,
((blue & 0xff00) >> 8);
break;
}
+ }
+
+ return 0;
+}
+
+static int drmfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ struct drmfb_par *par = info->par;
+ struct drm_device *dev = par->dev;
+ struct drm_display_mode *drm_mode;
+ struct drm_output *output;
+ int depth;
+
+ if (!var->pixclock)
+ return -EINVAL;
+
+ /* Need to resize the fb object !!! */
+ if (var->xres > fb->width || var->yres > fb->height) {
+ DRM_ERROR("Requested width/height is greater than current fb object %dx%d > %dx%d\n",var->xres,var->yres,fb->width,fb->height);
+ DRM_ERROR("Need resizing code.\n");
+ return -EINVAL;
+ }
+
+ switch (var->bits_per_pixel) {
+ case 16:
+ depth = (var->green.length == 6) ? 16 : 15;
+ break;
+ case 32:
+ depth = (var->transp.length > 0) ? 32 : 24;
+ break;
+ default:
+ depth = var->bits_per_pixel;
+ break;
+ }
+
+ switch (depth) {
+ case 8:
+ var->red.offset = 0;
+ var->green.offset = 0;
+ var->blue.offset = 0;
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
+ var->transp.length = 0;
+ var->transp.offset = 0;
+ break;
+ case 15:
+ var->red.offset = 10;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->red.length = 5;
+ var->green.length = 5;
+ var->blue.length = 5;
+ var->transp.length = 1;
+ var->transp.offset = 15;
+ break;
+ case 16:
+ var->red.offset = 11;
+ var->green.offset = 6;
+ var->blue.offset = 0;
+ var->red.length = 5;
+ var->green.length = 6;
+ var->blue.length = 5;
+ var->transp.length = 0;
+ var->transp.offset = 0;
+ break;
+ case 24:
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
+ var->transp.length = 0;
+ var->transp.offset = 0;
+ break;
+ case 32:
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
+ var->transp.length = 8;
+ var->transp.offset = 24;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+#if 0
+ /* Here we walk the output mode list and look for modes. If we haven't
+ * got it, then bail. Not very nice, so this is disabled.
+ * In the set_par code, we create our mode based on the incoming
+ * parameters. Nicer, but may not be desired by some.
+ */
+ list_for_each_entry(output, &dev->mode_config.output_list, head) {
+ if (output->crtc == par->crtc)
+ break;
+ }
+
+ list_for_each_entry(drm_mode, &output->modes, head) {
+ if (drm_mode->hdisplay == var->xres &&
+ drm_mode->vdisplay == var->yres &&
+ drm_mode->clock != 0)
+ break;
}
+ if (!drm_mode)
+ return -EINVAL;
+#endif
+
return 0;
}
@@ -81,9 +202,74 @@ static int drmfb_setcolreg(unsigned regno, unsigned red, unsigned green,
static int drmfb_set_par(struct fb_info *info)
{
struct drmfb_par *par = info->par;
+ struct drm_framebuffer *fb = par->crtc->fb;
struct drm_device *dev = par->dev;
+ struct drm_display_mode *drm_mode;
+ struct fb_var_screeninfo *var = &info->var;
+ struct drm_output *output;
+
+ switch (var->bits_per_pixel) {
+ case 16:
+ fb->depth = (var->green.length == 6) ? 16 : 15;
+ break;
+ case 32:
+ fb->depth = (var->transp.length > 0) ? 32 : 24;
+ break;
+ default:
+ fb->depth = var->bits_per_pixel;
+ break;
+ }
+
+ fb->bits_per_pixel = var->bits_per_pixel;
+
+ info->fix.line_length = fb->pitch * ((fb->bits_per_pixel + 1) / 8);
+ info->fix.smem_len = info->fix.line_length * fb->height;
+ info->fix.visual = (fb->depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+
+ info->screen_size = info->fix.smem_len; /* ??? */
+
+ /* Should we walk the output's modelist or just create our own ???
+ * For now, we create and destroy a mode based on the incoming
+ * parameters. But there's commented out code below which scans
+ * the output list too.
+ */
+#if 0
+ list_for_each_entry(output, &dev->mode_config.output_list, head) {
+ if (output->crtc == par->crtc)
+ break;
+ }
+
+ list_for_each_entry(drm_mode, &output->modes, head) {
+ if (drm_mode->hdisplay == var->xres &&
+ drm_mode->vdisplay == var->yres &&
+ drm_mode->clock != 0)
+ break;
+ }
+#else
+ drm_mode = drm_mode_create(dev);
+ drm_mode->hdisplay = var->xres;
+ drm_mode->hsync_start = drm_mode->hdisplay + var->right_margin;
+ drm_mode->hsync_end = drm_mode->hsync_start + var->hsync_len;
+ drm_mode->htotal = drm_mode->hsync_end + var->left_margin;
+ drm_mode->vdisplay = var->yres;
+ drm_mode->vsync_start = drm_mode->vdisplay + var->lower_margin;
+ drm_mode->vsync_end = drm_mode->vsync_start + var->vsync_len;
+ drm_mode->vtotal = drm_mode->vsync_end + var->upper_margin;
+ drm_mode->clock = PICOS2KHZ(var->pixclock);
+ drm_mode->vrefresh = drm_mode_vrefresh(drm_mode);
+ drm_mode_set_name(drm_mode);
+#endif
+
+ if (!drm_crtc_set_mode(par->crtc, drm_mode, 0, 0))
+ return -EINVAL;
+
+ /* Have to destroy our created mode if we're not searching the mode
+ * list for it.
+ */
+#if 1
+ drm_mode_destroy(dev, drm_mode);
+#endif
- drm_set_desired_modes(dev);
return 0;
}
@@ -94,6 +280,7 @@ static struct fb_ops drmfb_ops = {
// .fb_write = drmfb_write,
// .fb_release = drmfb_release,
// .fb_ioctl = drmfb_ioctl,
+ .fb_check_var = drmfb_check_var,
.fb_set_par = drmfb_set_par,
.fb_setcolreg = drmfb_setcolreg,
.fb_fillrect = cfb_fillrect,
@@ -101,12 +288,13 @@ static struct fb_ops drmfb_ops = {
.fb_imageblit = cfb_imageblit,
};
-int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb)
+int drmfb_probe(struct drm_device *dev, struct drm_crtc *crtc)
{
struct fb_info *info;
+ struct drm_framebuffer *fb = crtc->fb;
struct drmfb_par *par;
struct device *device = &dev->pdev->dev;
- unsigned long size = (8*1024*1024); /* FIXME */
+ struct drm_display_mode *mode = crtc->desired_mode;
int ret;
info = framebuffer_alloc(sizeof(struct drmfb_par), device);
@@ -119,20 +307,20 @@ int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb)
par = info->par;
par->dev = dev;
- par->fb = fb;
+ par->crtc = crtc;
info->fbops = &drmfb_ops;
strcpy(info->fix.id, "drmfb");
- info->fix.smem_start = fb->offset + dev->mode_config.fb_base;
- info->fix.smem_len = size;
info->fix.type = FB_TYPE_PACKED_PIXELS;
- info->fix.visual = FB_VISUAL_DIRECTCOLOR;
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
info->fix.accel = FB_ACCEL_NONE;
info->fix.type_aux = 0;
info->fix.mmio_start = 0;
info->fix.mmio_len = 0;
info->fix.line_length = fb->pitch * ((fb->bits_per_pixel + 1) / 8);
+ info->fix.smem_start = fb->offset + dev->mode_config.fb_base;
+ info->fix.smem_len = info->fix.line_length * fb->height;
info->flags = FBINFO_DEFAULT;
@@ -141,11 +329,9 @@ int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb)
DRM_ERROR("error mapping fb: %d\n", ret);
info->screen_base = fb->virtual_base;
- info->screen_size = size;
+ info->screen_size = info->fix.smem_len; /* ??? */
info->pseudo_palette = fb->pseudo_palette;
- info->var.xres = fb->width;
info->var.xres_virtual = fb->pitch;
- info->var.yres = fb->height;
info->var.yres_virtual = fb->height;
info->var.bits_per_pixel = fb->bits_per_pixel;
info->var.xoffset = 0;
@@ -155,24 +341,67 @@ int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb)
info->var.width = -1;
info->var.vmode = FB_VMODE_NONINTERLACED;
+ info->var.xres = mode->hdisplay;
+ info->var.right_margin = mode->hsync_start - mode->hdisplay;
+ info->var.hsync_len = mode->hsync_end - mode->hsync_start;
+ info->var.left_margin = mode->htotal - mode->hsync_end;
+ info->var.yres = mode->vdisplay;
+ info->var.lower_margin = mode->vsync_start - mode->vdisplay;
+ info->var.vsync_len = mode->vsync_end - mode->vsync_start;
+ info->var.upper_margin = mode->vtotal - mode->vsync_end;
+ info->var.pixclock = 10000000 / mode->htotal * 1000 /
+ mode->vtotal * 100000 / mode->vrefresh;
+
DRM_DEBUG("fb depth is %d\n", fb->depth);
switch(fb->depth) {
case 8:
+ info->var.red.offset = 0;
+ info->var.green.offset = 0;
+ info->var.blue.offset = 0;
+ info->var.red.length = 8; /* 8bit DAC */
+ info->var.green.length = 8;
+ info->var.blue.length = 8;
+ info->var.transp.offset = 0;
+ info->var.transp.length = 0;
+ break;
case 15:
+ info->var.red.offset = 10;
+ info->var.green.offset = 5;
+ info->var.blue.offset = 0;
+ info->var.red.length = info->var.green.length =
+ info->var.blue.length = 5;
+ info->var.transp.offset = 15;
+ info->var.transp.length = 1;
+ break;
case 16:
+ info->var.red.offset = 11;
+ info->var.green.offset = 5;
+ info->var.blue.offset = 0;
+ info->var.red.length = 5;
+ info->var.green.length = 6;
+ info->var.blue.length = 5;
+ info->var.transp.offset = 0;
+ info->var.transp.length = 0;
break;
- default:
case 24:
+ info->var.red.offset = 16;
+ info->var.green.offset = 8;
+ info->var.blue.offset = 0;
+ info->var.red.length = info->var.green.length =
+ info->var.blue.length = 8;
+ info->var.transp.offset = 0;
+ info->var.transp.length = 0;
+ break;
case 32:
info->var.red.offset = 16;
info->var.green.offset = 8;
info->var.blue.offset = 0;
info->var.red.length = info->var.green.length =
info->var.blue.length = 8;
- if (fb->depth == 32) {
- info->var.transp.offset = 24;
- info->var.transp.length = 8;
- }
+ info->var.transp.offset = 24;
+ info->var.transp.length = 8;
+ break;
+ default:
break;
}
diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c
index 7d581175..7879965e 100644
--- a/linux-core/intel_display.c
+++ b/linux-core/intel_display.c
@@ -787,6 +787,9 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
else
dpll |= PLL_REF_INPUT_DREFCLK;
+ /* setup pipeconf */
+ pipeconf = I915_READ(pipeconf_reg);
+
/* Set up the display plane register */
dspcntr = DISPPLANE_GAMMA_ENABLE;
@@ -814,7 +817,6 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
else
dspcntr |= DISPPLANE_SEL_PIPE_B;
- pipeconf = I915_READ(pipeconf_reg);
if (pipe == 0 && !IS_I965G(dev)) {
/* Enable pixel doubling when the dot clock is > 90% of the (display)
* core speed.
@@ -955,19 +957,14 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
}
/** Sets the color ramps on behalf of RandR */
-static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
- u16 *blue, int size)
+static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
+ u16 blue, int regno)
{
struct intel_crtc *intel_crtc = crtc->driver_private;
- int i;
- for (i = 0; i < 256; i++) {
- intel_crtc->lut_r[i] = red[i] >> 8;
- intel_crtc->lut_g[i] = green[i] >> 8;
- intel_crtc->lut_b[i] = blue[i] >> 8;
- }
-
- intel_crtc_load_lut(crtc);
+ intel_crtc->lut_r[regno] = red >> 8;
+ intel_crtc->lut_g[regno] = green >> 8;
+ intel_crtc->lut_b[regno] = blue >> 8;
}
/* Returns the clock of the currently programmed mode of the given pipe. */
@@ -1176,7 +1173,8 @@ static void intel_setup_outputs(drm_device_t *dev)
(1 << INTEL_OUTPUT_SDVO));
break;
case INTEL_OUTPUT_ANALOG:
- crtc_mask = ((1 << 0));
+ crtc_mask = ((1 << 0)|
+ (1 << 1));
clone_mask = ((1 << INTEL_OUTPUT_ANALOG) |
(1 << INTEL_OUTPUT_DVO) |
(1 << INTEL_OUTPUT_SDVO));
@@ -1223,7 +1221,6 @@ void intel_modeset_init(drm_device_t *dev)
intel_setup_outputs(dev);
//drm_initial_config(dev, false);
- //drm_set_desired_modes(dev);
}
void intel_modeset_cleanup(drm_device_t *dev)
diff --git a/linux-core/intel_drv.h b/linux-core/intel_drv.h
index aa33437d..fdf260e9 100644
--- a/linux-core/intel_drv.h
+++ b/linux-core/intel_drv.h
@@ -72,7 +72,7 @@ extern void intel_crtc_load_lut(struct drm_crtc *crtc);
extern void intel_output_prepare (struct drm_output *output);
extern void intel_output_commit (struct drm_output *output);
extern struct drm_display_mode *intel_crtc_mode_get(drm_device_t *dev,
- struct drm_crtc *crtc);
+ struct drm_crtc *crtc);
extern void intel_wait_for_vblank(drm_device_t *dev);
extern struct drm_crtc *intel_get_crtc_from_pipe(drm_device_t *dev, int pipe);
diff --git a/linux-core/intel_lvds.c b/linux-core/intel_lvds.c
index 74b040ba..942eb2ab 100644
--- a/linux-core/intel_lvds.c
+++ b/linux-core/intel_lvds.c
@@ -164,6 +164,13 @@ static bool intel_lvds_mode_fixup(struct drm_output *output,
struct intel_crtc *intel_crtc = output->crtc->driver_private;
struct drm_output *tmp_output;
+ /* Should never happen!! */
+ if (!IS_I965G(dev) && intel_crtc->pipe == 0) {
+ printk(KERN_ERR "Can't support LVDS on pipe A\n");
+ return false;
+ }
+
+ /* Should never happen!! */
list_for_each_entry(tmp_output, &dev->mode_config.output_list, head) {
if (tmp_output != output && tmp_output->crtc == output->crtc) {
printk(KERN_ERR "Can't enable LVDS and another "
@@ -172,11 +179,6 @@ static bool intel_lvds_mode_fixup(struct drm_output *output,
}
}
- if (intel_crtc->pipe == 0) {
- printk(KERN_ERR "Can't support LVDS on pipe A\n");
- return false;
- }
-
/*
* If we have timings from the BIOS for the panel, put them in
* to the adjusted mode. The CRTC will be set up for this mode,
diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c
index 58aa432c..c02fd958 100644
--- a/linux-core/intel_sdvo.c
+++ b/linux-core/intel_sdvo.c
@@ -1010,26 +1010,18 @@ void intel_sdvo_init(drm_device_t *dev, int output_device)
memset(&sdvo_priv->active_outputs, 0, sizeof(sdvo_priv->active_outputs));
- /* TODO, CVBS, SVID, YPRPB & SCART outputs.
- * drm_initial_config probably wants tweaking too to support the
- * above. But has fixed VGA, TMDS and LVDS checking code. That should
- * be dealt with.
- */
+ /* TODO, CVBS, SVID, YPRPB & SCART outputs. */
if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0)
{
sdvo_priv->active_outputs = SDVO_OUTPUT_RGB0;
output->subpixel_order = SubPixelHorizontalRGB;
- /* drm_initial_config wants this name, but should be RGB */
- /* Use this for now.... */
- name_prefix="VGA";
+ name_prefix="RGB";
}
else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1)
{
sdvo_priv->active_outputs = SDVO_OUTPUT_RGB1;
output->subpixel_order = SubPixelHorizontalRGB;
- /* drm_initial_config wants this name, but should be RGB */
- /* Use this for now.... */
- name_prefix="VGA";
+ name_prefix="RGB";
}
else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0)
{