* [RFC PATCH] atmel_lcdfb: avoid division by zero
@ 2008-06-06 10:34 Nicolas Ferre
0 siblings, 0 replies; only message in thread
From: Nicolas Ferre @ 2008-06-06 10:34 UTC (permalink / raw)
To: linux-fbdev-devel-bounces, Antonino A. Daplas
Cc: Linux Kernel list, Haavard Skinnemoen, Andrew Victor,
ARM Linux Mailing List
Avoid division by zero in atmel_lcdfb_check_var() function.
If pixclock is not specified while passing a var structure in
the check_var() funtion, a division by zero occurs (when
translating pixclock to KHz).
This patch adds a checking of this value and try to choose a
video mode in the modelist.
The mode found in the probe function in added to the modelist.
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
Please tell me if it is a proper way to implement a mean of
having a good var in check_var() function.
Is an -EINVAL error is legitimate in the case of a zero value
for pixclock or bits_per_pixel (if I cannot find a good modeline) ?
drivers/video/atmel_lcdfb.c | 36 ++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index b004036..f2e8d1b 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -256,6 +256,21 @@ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo)
return 0;
}
+static const struct fb_videomode *atmel_lcdfb_choose_mode(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct fb_videomode varfbmode;
+ const struct fb_videomode *fbmode = NULL;
+
+ fb_var_to_videomode(&varfbmode, var);
+ fbmode = fb_find_nearest_mode(&varfbmode, &info->modelist);
+ if (fbmode) {
+ fb_videomode_to_var(var, fbmode);
+ }
+ return fbmode;
+}
+
+
/**
* atmel_lcdfb_check_var - Validates a var passed in.
* @var: frame buffer variable screen structure
@@ -289,6 +304,15 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
dev_dbg(dev, "%s:\n", __func__);
+
+ if (!(var->pixclock && var->bits_per_pixel)) {
+ /* choose a suitable mode if possible */
+ if (!atmel_lcdfb_choose_mode(var, info)) {
+ dev_err(dev, "needed value not specified\n");
+ return -EINVAL;
+ }
+ }
+
dev_dbg(dev, " resolution: %ux%u\n", var->xres, var->yres);
dev_dbg(dev, " pixclk: %lu KHz\n", PICOS2KHZ(var->pixclock));
dev_dbg(dev, " bpp: %u\n", var->bits_per_pixel);
@@ -299,6 +323,13 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
return -EINVAL;
}
+ /* Do not allow to have real resoulution larger than virtual */
+ if (var->xres > var->xres_virtual)
+ var->xres_virtual = var->xres;
+
+ if (var->yres > var->yres_virtual)
+ var->yres_virtual = var->yres;
+
/* Force same alignment for each line */
var->xres = (var->xres + 3) & ~3UL;
var->xres_virtual = (var->xres_virtual + 3) & ~3UL;
@@ -691,6 +722,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
struct fb_info *info;
struct atmel_lcdfb_info *sinfo;
struct atmel_lcdfb_info *pdata_sinfo;
+ struct fb_videomode fbmode;
struct resource *regs = NULL;
struct resource *map = NULL;
int ret;
@@ -853,6 +885,10 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
goto free_cmap;
}
+ /* add selected videomode to modelist */
+ fb_var_to_videomode(&fbmode, &info->var);
+ fb_add_videomode(&fbmode, &info->modelist);
+
/* Power up the LCDC screen */
if (sinfo->atmel_lcdfb_power_control)
sinfo->atmel_lcdfb_power_control(1);
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2008-06-06 10:35 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-06 10:34 [RFC PATCH] atmel_lcdfb: avoid division by zero Nicolas Ferre
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.