aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/i810
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2009-12-15 19:46:32 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-16 10:20:02 -0500
commitb689a9e8362ed909045f99517b735c7c60835f7c (patch)
tree6860a06fc12d2f0940e7a3b95b6d6dd3c1f7a727 /drivers/video/i810
parent8a8e6b9d554d3889ca062cf9fea0a664231e0774 (diff)
i810fb: fix stack exploding
Alan Cox has found that the i810fb function "uses a whopping 2.5K of stack". Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Reported-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video/i810')
-rw-r--r--drivers/video/i810/i810_dvt.c53
1 files changed, 29 insertions, 24 deletions
diff --git a/drivers/video/i810/i810_dvt.c b/drivers/video/i810/i810_dvt.c
index 27fa703a2e0a..b4b3670667ab 100644
--- a/drivers/video/i810/i810_dvt.c
+++ b/drivers/video/i810/i810_dvt.c
@@ -212,24 +212,29 @@ inline void round_off_yres(u32 *xres, u32 *yres)
212 *yres = (*xres * 3) >> 2; 212 *yres = (*xres * 3) >> 2;
213} 213}
214 214
215void i810fb_encode_registers(const struct fb_var_screeninfo *var, 215static int i810fb_find_best_mode(u32 xres, u32 yres, u32 pixclock)
216 struct i810fb_par *par, u32 xres, u32 yres)
217{ 216{
218 u32 diff = 0, diff_best = 0xFFFFFFFF, i = 0, i_best = 0; 217 u32 diff = 0, diff_best = 0xFFFFFFFF, i = 0, i_best = 0;
219 u8 hfl; 218 u8 hfl = (u8) ((xres >> 3) - 1);
220 219
221 hfl = (u8) ((xres >> 3) - 1);
222 for (i = 0; i < ARRAY_SIZE(std_modes); i++) { 220 for (i = 0; i < ARRAY_SIZE(std_modes); i++) {
223 if (std_modes[i].cr01 == hfl) { 221 if (std_modes[i].cr01 == hfl) {
224 if (std_modes[i].pixclock <= par->regs.pixclock) 222 if (std_modes[i].pixclock <= pixclock)
225 diff = par->regs.pixclock - 223 diff = pixclock - std_modes[i].pixclock;
226 std_modes[i].pixclock;
227 if (diff < diff_best) { 224 if (diff < diff_best) {
228 i_best = i; 225 i_best = i;
229 diff_best = diff; 226 diff_best = diff;
230 } 227 }
231 } 228 }
232 } 229 }
230 return i_best;
231}
232
233void i810fb_encode_registers(const struct fb_var_screeninfo *var,
234 struct i810fb_par *par, u32 xres, u32 yres)
235{
236 u32 i_best = i810fb_find_best_mode(xres, yres, par->regs.pixclock);
237
233 par->regs = std_modes[i_best]; 238 par->regs = std_modes[i_best];
234 239
235 /* overlay */ 240 /* overlay */
@@ -239,36 +244,36 @@ void i810fb_encode_registers(const struct fb_var_screeninfo *var,
239 244
240void i810fb_fill_var_timings(struct fb_var_screeninfo *var) 245void i810fb_fill_var_timings(struct fb_var_screeninfo *var)
241{ 246{
242 struct i810fb_par par;
243 u32 total, xres, yres; 247 u32 total, xres, yres;
248 u32 mode, pixclock;
244 249
245 xres = var->xres; 250 xres = var->xres;
246 yres = var->yres; 251 yres = var->yres;
247 252
248 par.regs.pixclock = 1000000000/var->pixclock; 253 pixclock = 1000000000 / var->pixclock;
249 i810fb_encode_registers(var, &par, xres, yres); 254 mode = i810fb_find_best_mode(xres, yres, pixclock);
250 255
251 total = ((par.regs.cr00 | (par.regs.cr35 & 1) << 8) + 3) << 3; 256 total = (std_modes[mode].cr00 | (std_modes[mode].cr35 & 1) << 8) + 3;
257 total <<= 3;
252 258
253 var->pixclock = 1000000000/par.regs.pixclock; 259 var->pixclock = 1000000000 / std_modes[mode].pixclock;
254 var->right_margin = (par.regs.cr04 << 3) - xres; 260 var->right_margin = (std_modes[mode].cr04 << 3) - xres;
255 var->hsync_len = ((par.regs.cr05 & 0x1F) - 261 var->hsync_len = ((std_modes[mode].cr05 & 0x1F) -
256 (par.regs.cr04 & 0x1F)) << 3; 262 (std_modes[mode].cr04 & 0x1F)) << 3;
257 var->left_margin = (total - (xres + var->right_margin + 263 var->left_margin = (total - (xres + var->right_margin +
258 var->hsync_len)); 264 var->hsync_len));
259 var->sync = FB_SYNC_ON_GREEN; 265 var->sync = FB_SYNC_ON_GREEN;
260 if (~(par.regs.msr & (1 << 6))) 266 if (~(std_modes[mode].msr & (1 << 6)))
261 var->sync |= FB_SYNC_HOR_HIGH_ACT; 267 var->sync |= FB_SYNC_HOR_HIGH_ACT;
262 if (~(par.regs.msr & (1 << 7))) 268 if (~(std_modes[mode].msr & (1 << 7)))
263 var->sync |= FB_SYNC_VERT_HIGH_ACT; 269 var->sync |= FB_SYNC_VERT_HIGH_ACT;
264 270
265 271 total = (std_modes[mode].cr06 | (std_modes[mode].cr30 & 0xF) << 8) + 2;
266 total = ((par.regs.cr06 | (par.regs.cr30 & 0x0F) << 8)) + 2; 272 var->lower_margin = (std_modes[mode].cr10 |
267 var->lower_margin = (par.regs.cr10 | 273 (std_modes[mode].cr32 & 0x0F) << 8) - yres;
268 (par.regs.cr32 & 0x0F) << 8) - yres; 274 var->vsync_len = (std_modes[mode].cr11 & 0x0F) -
269 var->vsync_len = (par.regs.cr11 & 0x0F) - (var->lower_margin & 0x0F); 275 (var->lower_margin & 0x0F);
270 var->upper_margin = total - (yres + var->lower_margin + 276 var->upper_margin = total - (yres + var->lower_margin + var->vsync_len);
271 var->vsync_len);
272} 277}
273 278
274u32 i810_get_watermark(struct fb_var_screeninfo *var, 279u32 i810_get_watermark(struct fb_var_screeninfo *var,