aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/pxafb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/pxafb.c')
-rw-r--r--drivers/video/pxafb.c108
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
394static 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