diff options
author | Alan Hourihane <alanh@tungstengraphics.com> | 2007-09-27 14:21:03 +0100 |
---|---|---|
committer | Alan Hourihane <alanh@tungstengraphics.com> | 2007-09-27 14:21:03 +0100 |
commit | 2ed12b6b7eee8a1b5b0adf0cd8f3cb8c1bc3ccaf (patch) | |
tree | 964fc478e345a330d926857352b1bfdf59d6d375 | |
parent | 61dfd19de81716aea0eaba90518fcb110b46b8f0 (diff) |
Add some more checks to modelist walking for matching
incoming modes to current modelist.
-rw-r--r-- | linux-core/intel_fb.c | 39 | ||||
-rw-r--r-- | linux-core/intel_i2c.c | 3 | ||||
-rw-r--r-- | linux-core/intel_sdvo.c | 11 |
3 files changed, 44 insertions, 9 deletions
diff --git a/linux-core/intel_fb.c b/linux-core/intel_fb.c index 048295ab..04fd0fdd 100644 --- a/linux-core/intel_fb.c +++ b/linux-core/intel_fb.c @@ -49,6 +49,17 @@ struct intelfb_par { struct drm_crtc *crtc; }; +static int +var_to_refresh(const struct fb_var_screeninfo *var) +{ + int xtot = var->xres + var->left_margin + var->right_margin + + var->hsync_len; + int ytot = var->yres + var->upper_margin + var->lower_margin + + var->vsync_len; + + return (1000000000 / var->pixclock * 1000 + 500) / xtot / ytot; +} + static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) @@ -98,7 +109,7 @@ static int intelfb_check_var(struct fb_var_screeninfo *var, struct drm_framebuffer *fb = par->crtc->fb; struct drm_display_mode *drm_mode; struct drm_output *output; - int depth; + int depth, found = 0; if (!var->pixclock) return -EINVAL; @@ -191,11 +202,14 @@ static int intelfb_check_var(struct fb_var_screeninfo *var, list_for_each_entry(drm_mode, &output->modes, head) { if (drm_mode->hdisplay == var->xres && drm_mode->vdisplay == var->yres && - drm_mode->clock != 0) + (((PICOS2KHZ(var->pixclock))/1000) >= ((drm_mode->clock/1000)-1)) && + (((PICOS2KHZ(var->pixclock))/1000) <= ((drm_mode->clock/1000)+1))) { + found = 1; break; + } } - if (!drm_mode) + if (!found) return -EINVAL; #endif @@ -210,7 +224,9 @@ static int intelfb_set_par(struct fb_info *info) struct drm_framebuffer *fb = par->crtc->fb; struct drm_device *dev = par->dev; struct drm_display_mode *drm_mode; + struct drm_output *output; struct fb_var_screeninfo *var = &info->var; + int found = 0; switch (var->bits_per_pixel) { case 16: @@ -246,9 +262,18 @@ static int intelfb_set_par(struct fb_info *info) list_for_each_entry(drm_mode, &output->modes, head) { if (drm_mode->hdisplay == var->xres && drm_mode->vdisplay == var->yres && - drm_mode->clock != 0) + (((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 drm_mode = drm_mode_create(dev); drm_mode->hdisplay = var->xres; @@ -265,13 +290,15 @@ static int intelfb_set_par(struct fb_info *info) drm_mode_set_crtcinfo(drm_mode, CRTC_INTERLACE_HALVE_V); #endif + drm_mode_debug_printmodeline(dev, drm_mode); + 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 +#if 1 drm_mode_destroy(dev, drm_mode); #endif @@ -472,6 +499,7 @@ int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc) drm_bo_type_kernel, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | + DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MEM_VRAM, 0, 0, 0, &fbo); @@ -629,6 +657,7 @@ int intelfb_remove(struct drm_device *dev, struct drm_crtc *crtc) unregister_framebuffer(info); framebuffer_release(info); drm_mem_reg_iounmap(dev, &fb->bo->mem, fb->virtual_base); + drm_framebuffer_destroy(fb); } return 0; } diff --git a/linux-core/intel_i2c.c b/linux-core/intel_i2c.c index b512e592..efcbf656 100644 --- a/linux-core/intel_i2c.c +++ b/linux-core/intel_i2c.c @@ -140,6 +140,9 @@ struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg, chan->reg = reg; snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name); chan->adapter.owner = THIS_MODULE; +#ifndef I2C_HW_B_INTELFB +#define I2C_HW_B_INTELFB I2C_HW_B_I810 +#endif chan->adapter.id = I2C_HW_B_INTELFB; chan->adapter.algo_data = &chan->algo; chan->adapter.dev.parent = &dev->pdev->dev; diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 19df1d4d..51fe43cb 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -730,9 +730,12 @@ static void intel_sdvo_dpms(struct drm_output *output, int mode) &input2); - /* Warn if the device reported failure to sync. */ + /* Warn if the device reported failure to sync. + * A lot of SDVO devices fail to notify of sync, but it's + * a given it the status is a success, we succeeded. + */ if (status == SDVO_CMD_STATUS_SUCCESS && !input1) { - DRM_ERROR("First %s output reported failure to sync\n", + DRM_DEBUG("First %s output reported failure to sync\n", SDVO_NAME(sdvo_priv)); } @@ -839,10 +842,10 @@ static int intel_sdvo_mode_valid(struct drm_output *output, return MODE_NO_DBLESCAN; if (sdvo_priv->pixel_clock_min > mode->clock) - return MODE_CLOCK_HIGH; + return MODE_CLOCK_LOW; if (sdvo_priv->pixel_clock_max < mode->clock) - return MODE_CLOCK_LOW; + return MODE_CLOCK_HIGH; return MODE_OK; } |