diff options
Diffstat (limited to 'drivers/video/pxafb.c')
-rw-r--r-- | drivers/video/pxafb.c | 108 |
1 files changed, 44 insertions, 64 deletions
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 1faf52642f5f..7935706a7565 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c | |||
@@ -391,6 +391,46 @@ static void pxafb_setmode(struct fb_var_screeninfo *var, | |||
391 | pxafb_set_pixfmt(var, mode->depth); | 391 | pxafb_set_pixfmt(var, mode->depth); |
392 | } | 392 | } |
393 | 393 | ||
394 | static int pxafb_adjust_timing(struct pxafb_info *fbi, | ||
395 | struct fb_var_screeninfo *var) | ||
396 | { | ||
397 | int line_length; | ||
398 | |||
399 | var->xres = max_t(int, var->xres, MIN_XRES); | ||
400 | var->yres = max_t(int, var->yres, MIN_YRES); | ||
401 | |||
402 | if (!(fbi->lccr0 & LCCR0_LCDT)) { | ||
403 | clamp_val(var->hsync_len, 1, 64); | ||
404 | clamp_val(var->vsync_len, 1, 64); | ||
405 | clamp_val(var->left_margin, 1, 255); | ||
406 | clamp_val(var->right_margin, 1, 255); | ||
407 | clamp_val(var->upper_margin, 1, 255); | ||
408 | clamp_val(var->lower_margin, 1, 255); | ||
409 | } | ||
410 | |||
411 | /* make sure each line is aligned on word boundary */ | ||
412 | line_length = var->xres * var->bits_per_pixel / 8; | ||
413 | line_length = ALIGN(line_length, 4); | ||
414 | var->xres = line_length * 8 / var->bits_per_pixel; | ||
415 | |||
416 | /* we don't support xpan, force xres_virtual to be equal to xres */ | ||
417 | var->xres_virtual = var->xres; | ||
418 | |||
419 | if (var->accel_flags & FB_ACCELF_TEXT) | ||
420 | var->yres_virtual = fbi->fb.fix.smem_len / line_length; | ||
421 | else | ||
422 | var->yres_virtual = max(var->yres_virtual, var->yres); | ||
423 | |||
424 | /* check for limits */ | ||
425 | if (var->xres > MAX_XRES || var->yres > MAX_YRES) | ||
426 | return -EINVAL; | ||
427 | |||
428 | if (var->yres > var->yres_virtual) | ||
429 | return -EINVAL; | ||
430 | |||
431 | return 0; | ||
432 | } | ||
433 | |||
394 | /* | 434 | /* |
395 | * pxafb_check_var(): | 435 | * pxafb_check_var(): |
396 | * Get the video params out of 'var'. If a value doesn't fit, round it up, | 436 | * Get the video params out of 'var'. If a value doesn't fit, round it up, |
@@ -406,11 +446,6 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
406 | struct pxafb_mach_info *inf = fbi->dev->platform_data; | 446 | struct pxafb_mach_info *inf = fbi->dev->platform_data; |
407 | int err; | 447 | int err; |
408 | 448 | ||
409 | if (var->xres < MIN_XRES) | ||
410 | var->xres = MIN_XRES; | ||
411 | if (var->yres < MIN_YRES) | ||
412 | var->yres = MIN_YRES; | ||
413 | |||
414 | if (inf->fixed_modes) { | 449 | if (inf->fixed_modes) { |
415 | struct pxafb_mode_info *mode; | 450 | struct pxafb_mode_info *mode; |
416 | 451 | ||
@@ -418,24 +453,8 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
418 | if (!mode) | 453 | if (!mode) |
419 | return -EINVAL; | 454 | return -EINVAL; |
420 | pxafb_setmode(var, mode); | 455 | pxafb_setmode(var, mode); |
421 | } else { | ||
422 | if (var->xres > inf->modes->xres) | ||
423 | return -EINVAL; | ||
424 | if (var->yres > inf->modes->yres) | ||
425 | return -EINVAL; | ||
426 | if (var->bits_per_pixel > inf->modes->bpp) | ||
427 | return -EINVAL; | ||
428 | } | 456 | } |
429 | 457 | ||
430 | /* we don't support xpan, force xres_virtual to be equal to xres */ | ||
431 | var->xres_virtual = var->xres; | ||
432 | |||
433 | if (var->accel_flags & FB_ACCELF_TEXT) | ||
434 | var->yres_virtual = fbi->fb.fix.smem_len / | ||
435 | (var->xres_virtual * var->bits_per_pixel / 8); | ||
436 | else | ||
437 | var->yres_virtual = max(var->yres_virtual, var->yres); | ||
438 | |||
439 | /* do a test conversion to BPP fields to check the color formats */ | 458 | /* do a test conversion to BPP fields to check the color formats */ |
440 | err = pxafb_var_to_bpp(var); | 459 | err = pxafb_var_to_bpp(var); |
441 | if (err < 0) | 460 | if (err < 0) |
@@ -443,6 +462,10 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
443 | 462 | ||
444 | pxafb_set_pixfmt(var, var_to_depth(var)); | 463 | pxafb_set_pixfmt(var, var_to_depth(var)); |
445 | 464 | ||
465 | err = pxafb_adjust_timing(fbi, var); | ||
466 | if (err) | ||
467 | return err; | ||
468 | |||
446 | #ifdef CONFIG_CPU_FREQ | 469 | #ifdef CONFIG_CPU_FREQ |
447 | pr_debug("pxafb: dma period = %d ps\n", | 470 | pr_debug("pxafb: dma period = %d ps\n", |
448 | pxafb_display_dma_period(var)); | 471 | pxafb_display_dma_period(var)); |
@@ -948,49 +971,6 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, | |||
948 | { | 971 | { |
949 | u_long flags; | 972 | u_long flags; |
950 | 973 | ||
951 | #if DEBUG_VAR | ||
952 | if (!(fbi->lccr0 & LCCR0_LCDT)) { | ||
953 | if (var->xres < 16 || var->xres > 1024) | ||
954 | printk(KERN_ERR "%s: invalid xres %d\n", | ||
955 | fbi->fb.fix.id, var->xres); | ||
956 | switch (var->bits_per_pixel) { | ||
957 | case 1: | ||
958 | case 2: | ||
959 | case 4: | ||
960 | case 8: | ||
961 | case 16: | ||
962 | case 24: | ||
963 | case 32: | ||
964 | break; | ||
965 | default: | ||
966 | printk(KERN_ERR "%s: invalid bit depth %d\n", | ||
967 | fbi->fb.fix.id, var->bits_per_pixel); | ||
968 | break; | ||
969 | } | ||
970 | |||
971 | if (var->hsync_len < 1 || var->hsync_len > 64) | ||
972 | printk(KERN_ERR "%s: invalid hsync_len %d\n", | ||
973 | fbi->fb.fix.id, var->hsync_len); | ||
974 | if (var->left_margin < 1 || var->left_margin > 255) | ||
975 | printk(KERN_ERR "%s: invalid left_margin %d\n", | ||
976 | fbi->fb.fix.id, var->left_margin); | ||
977 | if (var->right_margin < 1 || var->right_margin > 255) | ||
978 | printk(KERN_ERR "%s: invalid right_margin %d\n", | ||
979 | fbi->fb.fix.id, var->right_margin); | ||
980 | if (var->yres < 1 || var->yres > 1024) | ||
981 | printk(KERN_ERR "%s: invalid yres %d\n", | ||
982 | fbi->fb.fix.id, var->yres); | ||
983 | if (var->vsync_len < 1 || var->vsync_len > 64) | ||
984 | printk(KERN_ERR "%s: invalid vsync_len %d\n", | ||
985 | fbi->fb.fix.id, var->vsync_len); | ||
986 | if (var->upper_margin < 0 || var->upper_margin > 255) | ||
987 | printk(KERN_ERR "%s: invalid upper_margin %d\n", | ||
988 | fbi->fb.fix.id, var->upper_margin); | ||
989 | if (var->lower_margin < 0 || var->lower_margin > 255) | ||
990 | printk(KERN_ERR "%s: invalid lower_margin %d\n", | ||
991 | fbi->fb.fix.id, var->lower_margin); | ||
992 | } | ||
993 | #endif | ||
994 | /* Update shadow copy atomically */ | 974 | /* Update shadow copy atomically */ |
995 | local_irq_save(flags); | 975 | local_irq_save(flags); |
996 | 976 | ||