summaryrefslogtreecommitdiff
path: root/linux-core/intel_fb.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2007-11-26 15:06:42 +1100
committerDave Airlie <airlied@redhat.com>2007-11-26 15:06:42 +1100
commitf9ac54b0319b273de83a004d6cfdf46a3b9d6ced (patch)
tree9f1f0dfac06537e01c849b01bd24e2f53cf3653c /linux-core/intel_fb.c
parent362f4283205a01b2a60a49838721e9fff9ae1a4c (diff)
fb: make fb interface use user mode attach/detach for adding modes
Diffstat (limited to 'linux-core/intel_fb.c')
-rw-r--r--linux-core/intel_fb.c65
1 files changed, 30 insertions, 35 deletions
diff --git a/linux-core/intel_fb.c b/linux-core/intel_fb.c
index 3a4ffc7f..5f43f291 100644
--- a/linux-core/intel_fb.c
+++ b/linux-core/intel_fb.c
@@ -223,7 +223,7 @@ static int intelfb_set_par(struct fb_info *info)
struct intelfb_par *par = info->par;
struct drm_framebuffer *fb = par->crtc->fb;
struct drm_device *dev = par->dev;
- struct drm_display_mode *drm_mode;
+ struct drm_display_mode *drm_mode, *search_mode;
struct drm_output *output;
struct fb_var_screeninfo *var = &info->var;
int found = 0;
@@ -248,34 +248,7 @@ static int intelfb_set_par(struct fb_info *info)
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 &&
- (((PICOS2KHZ(var->pixclock))/1000) >= ((drm_mode->clock/1000)-1)) &&
- (((PICOS2KHZ(var->pixclock))/1000) <= ((drm_mode->clock/1000)+1))) {
- found = 1;
- break;
- }
- }
-
- if (!found) {
- DRM_ERROR("Couldn't find a mode for requested %dx%d-%d\n",
- var->xres,var->yres,var_to_refresh(var));
- return -EINVAL;
- }
-#else
-
+ /* create a drm mode */
drm_mode = drm_mode_create(dev);
drm_mode->hdisplay = var->xres;
drm_mode->hsync_start = drm_mode->hdisplay + var->right_margin;
@@ -289,14 +262,36 @@ static int intelfb_set_par(struct fb_info *info)
drm_mode->vrefresh = drm_mode_vrefresh(drm_mode);
drm_mode_set_name(drm_mode);
drm_mode_set_crtcinfo(drm_mode, CRTC_INTERLACE_HALVE_V);
-#endif
- drm_mode_addmode(dev, drm_mode);
- if (par->fb_mode)
- drm_mode_rmmode(dev, par->fb_mode);
+ list_for_each_entry(output, &dev->mode_config.output_list, head) {
+ if (output->crtc == par->crtc)
+ break;
+ }
+
+ drm_mode_debug_printmodeline(dev, drm_mode);
+ list_for_each_entry(search_mode, &output->modes, head) {
+ DRM_ERROR("mode %s : %s\n", drm_mode->name, search_mode->name);
+ drm_mode_debug_printmodeline(dev, search_mode);
+ if (drm_mode_equal(drm_mode, search_mode)) {
+ drm_mode_destroy(dev, drm_mode);
+ drm_mode = search_mode;
+ found = 1;
+ break;
+ }
+ }
- par->fb_mode = drm_mode;
- drm_mode_debug_printmodeline(dev, drm_mode);
+ if (!found) {
+ drm_mode_addmode(dev, drm_mode);
+ if (par->fb_mode) {
+ drm_mode_detachmode_crtc(dev, par->fb_mode);
+ drm_mode_rmmode(dev, par->fb_mode);
+ }
+
+ par->fb_mode = drm_mode;
+ drm_mode_debug_printmodeline(dev, drm_mode);
+ /* attach mode */
+ drm_mode_attachmode_crtc(dev, par->crtc, par->fb_mode);
+ }
if (!drm_crtc_set_mode(par->crtc, drm_mode, 0, 0))
return -EINVAL;