summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Hourihane <alanh@tungstengraphics.com>2007-09-27 14:21:03 +0100
committerAlan Hourihane <alanh@tungstengraphics.com>2007-09-27 14:21:03 +0100
commit2ed12b6b7eee8a1b5b0adf0cd8f3cb8c1bc3ccaf (patch)
tree964fc478e345a330d926857352b1bfdf59d6d375
parent61dfd19de81716aea0eaba90518fcb110b46b8f0 (diff)
Add some more checks to modelist walking for matching
incoming modes to current modelist.
-rw-r--r--linux-core/intel_fb.c39
-rw-r--r--linux-core/intel_i2c.c3
-rw-r--r--linux-core/intel_sdvo.c11
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;
}