aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/cirrusfb.c
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2009-03-31 18:25:09 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-01 11:59:27 -0400
commit99a4584752bb41330342a427d014482525de7433 (patch)
tree5a705f234f5ace69c028578102919394dfc0bf26 /drivers/video/cirrusfb.c
parent1b48cb563d59e03dbf530174f30c0ed3b6fba513 (diff)
cirrusfb: check_var improvements
Break cirrusfb_decode_var() function into two parts: cirrusfb_check_pixclock() which can be called from the cirrusfb_check_var() aand merge rest into the cirrusfb_set_par_foo(). This allows rejecting modes with too high pixclock before before any change to hardware state (and a console is messed up). Also, fix RGB field's lengths for 8bpp modes to correct ones so X11 works with fbdev driver with cirrusfb. Kill some redundant function calls or register loads. Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video/cirrusfb.c')
-rw-r--r--drivers/video/cirrusfb.c195
1 files changed, 74 insertions, 121 deletions
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 12f45520e5d3..bab713b63a0c 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -432,6 +432,53 @@ static int cirrusfb_check_mclk(struct fb_info *info, long freq)
432 return 0; 432 return 0;
433} 433}
434 434
435static int cirrusfb_check_pixclock(const struct fb_var_screeninfo *var,
436 struct fb_info *info)
437{
438 long freq;
439 long maxclock;
440 struct cirrusfb_info *cinfo = info->par;
441 unsigned maxclockidx = var->bits_per_pixel >> 3;
442
443 /* convert from ps to kHz */
444 freq = PICOS2KHZ(var->pixclock);
445
446 dev_dbg(info->device, "desired pixclock: %ld kHz\n", freq);
447
448 maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
449 cinfo->multiplexing = 0;
450
451 /* If the frequency is greater than we can support, we might be able
452 * to use multiplexing for the video mode */
453 if (freq > maxclock) {
454 switch (cinfo->btype) {
455 case BT_ALPINE:
456 case BT_GD5480:
457 cinfo->multiplexing = 1;
458 break;
459
460 default:
461 dev_err(info->device,
462 "Frequency greater than maxclock (%ld kHz)\n",
463 maxclock);
464 return -EINVAL;
465 }
466 }
467#if 0
468 /* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where
469 * the VCLK is double the pixel clock. */
470 switch (var->bits_per_pixel) {
471 case 16:
472 case 32:
473 if (var->xres <= 800)
474 /* Xbh has this type of clock for 32-bit */
475 freq /= 2;
476 break;
477 }
478#endif
479 return 0;
480}
481
435static int cirrusfb_check_var(struct fb_var_screeninfo *var, 482static int cirrusfb_check_var(struct fb_var_screeninfo *var,
436 struct fb_info *info) 483 struct fb_info *info)
437{ 484{
@@ -449,7 +496,7 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
449 496
450 case 8: 497 case 8:
451 var->red.offset = 0; 498 var->red.offset = 0;
452 var->red.length = 6; 499 var->red.length = 8;
453 var->green = var->red; 500 var->green = var->red;
454 var->blue = var->red; 501 var->blue = var->red;
455 break; 502 break;
@@ -513,7 +560,6 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
513 return -EINVAL; 560 return -EINVAL;
514 } 561 }
515 562
516
517 if (var->xoffset < 0) 563 if (var->xoffset < 0)
518 var->xoffset = 0; 564 var->xoffset = 0;
519 if (var->yoffset < 0) 565 if (var->yoffset < 0)
@@ -544,80 +590,9 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
544 return -EINVAL; 590 return -EINVAL;
545 } 591 }
546 592
547 return 0; 593 if (cirrusfb_check_pixclock(var, info))
548} 594 return -EINVAL;
549
550static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
551 struct fb_info *info)
552{
553 long freq;
554 long maxclock;
555 int maxclockidx = var->bits_per_pixel >> 3;
556 struct cirrusfb_info *cinfo = info->par;
557
558 switch (var->bits_per_pixel) {
559 case 1:
560 info->fix.line_length = var->xres_virtual / 8;
561 info->fix.visual = FB_VISUAL_MONO10;
562 break;
563
564 case 8:
565 info->fix.line_length = var->xres_virtual;
566 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
567 break;
568
569 case 16:
570 case 32:
571 info->fix.line_length = var->xres_virtual * maxclockidx;
572 info->fix.visual = FB_VISUAL_TRUECOLOR;
573 break;
574
575 default:
576 dev_dbg(info->device,
577 "Unsupported bpp size: %d\n", var->bits_per_pixel);
578 assert(false);
579 /* should never occur */
580 break;
581 }
582
583 info->fix.type = FB_TYPE_PACKED_PIXELS;
584
585 /* convert from ps to kHz */
586 freq = PICOS2KHZ(var->pixclock);
587
588 dev_dbg(info->device, "desired pixclock: %ld kHz\n", freq);
589
590 maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
591 cinfo->multiplexing = 0;
592
593 /* If the frequency is greater than we can support, we might be able
594 * to use multiplexing for the video mode */
595 if (freq > maxclock) {
596 switch (cinfo->btype) {
597 case BT_ALPINE:
598 case BT_GD5480:
599 cinfo->multiplexing = 1;
600 break;
601 595
602 default:
603 dev_err(info->device,
604 "Frequency greater than maxclock (%ld kHz)\n",
605 maxclock);
606 return -EINVAL;
607 }
608 }
609#if 0
610 /* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where
611 * the VCLK is double the pixel clock. */
612 switch (var->bits_per_pixel) {
613 case 16:
614 case 32:
615 if (var->xres <= 800)
616 /* Xbh has this type of clock for 32-bit */
617 freq /= 2;
618 break;
619 }
620#endif
621 return 0; 596 return 0;
622} 597}
623 598
@@ -653,7 +628,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
653 struct fb_var_screeninfo *var = &info->var; 628 struct fb_var_screeninfo *var = &info->var;
654 u8 __iomem *regbase = cinfo->regbase; 629 u8 __iomem *regbase = cinfo->regbase;
655 unsigned char tmp; 630 unsigned char tmp;
656 int err;
657 int pitch; 631 int pitch;
658 const struct cirrusfb_board_info_rec *bi; 632 const struct cirrusfb_board_info_rec *bi;
659 int hdispend, hsyncstart, hsyncend, htotal; 633 int hdispend, hsyncstart, hsyncend, htotal;
@@ -664,16 +638,28 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
664 638
665 dev_dbg(info->device, "Requested mode: %dx%dx%d\n", 639 dev_dbg(info->device, "Requested mode: %dx%dx%d\n",
666 var->xres, var->yres, var->bits_per_pixel); 640 var->xres, var->yres, var->bits_per_pixel);
667 dev_dbg(info->device, "pixclock: %d\n", var->pixclock);
668 641
669 init_vgachip(info); 642 switch (var->bits_per_pixel) {
643 case 1:
644 info->fix.line_length = var->xres_virtual / 8;
645 info->fix.visual = FB_VISUAL_MONO10;
646 break;
670 647
671 err = cirrusfb_decode_var(var, info); 648 case 8:
672 if (err) { 649 info->fix.line_length = var->xres_virtual;
673 /* should never happen */ 650 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
674 dev_dbg(info->device, "mode change aborted. invalid var.\n"); 651 break;
675 return -EINVAL; 652
653 case 16:
654 case 32:
655 info->fix.line_length = var->xres_virtual *
656 var->bits_per_pixel >> 3;
657 info->fix.visual = FB_VISUAL_TRUECOLOR;
658 break;
676 } 659 }
660 info->fix.type = FB_TYPE_PACKED_PIXELS;
661
662 init_vgachip(info);
677 663
678 bi = &cirrusfb_board_info[cinfo->btype]; 664 bi = &cirrusfb_board_info[cinfo->btype];
679 665
@@ -873,9 +859,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
873 * address wrap, no compat. */ 859 * address wrap, no compat. */
874 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3); 860 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3);
875 861
876/* HAEH? vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20);
877 * previously: 0x00 unlock VGA_CRTC_H_TOTAL..CRT7 */
878
879 /* don't know if it would hurt to also program this if no interlaced */ 862 /* don't know if it would hurt to also program this if no interlaced */
880 /* mode is used, but I feel better this way.. :-) */ 863 /* mode is used, but I feel better this way.. :-) */
881 if (var->vmode & FB_VMODE_INTERLACED) 864 if (var->vmode & FB_VMODE_INTERLACED)
@@ -883,8 +866,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
883 else 866 else
884 vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */ 867 vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
885 868
886 vga_wseq(regbase, VGA_SEQ_CHARACTER_MAP, 0);
887
888 /* adjust horizontal/vertical sync type (low/high) */ 869 /* adjust horizontal/vertical sync type (low/high) */
889 /* enable display memory & CRTC I/O address for color mode */ 870 /* enable display memory & CRTC I/O address for color mode */
890 tmp = 0x03; 871 tmp = 0x03;
@@ -896,8 +877,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
896 tmp |= 0xc; 877 tmp |= 0xc;
897 WGen(cinfo, VGA_MIS_W, tmp); 878 WGen(cinfo, VGA_MIS_W, tmp);
898 879
899 /* Screen A Preset Row-Scan register */
900 vga_wcrt(regbase, VGA_CRTC_PRESET_ROW, 0);
901 /* text cursor on and start line */ 880 /* text cursor on and start line */
902 vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0); 881 vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0);
903 /* text cursor end line */ 882 /* text cursor end line */
@@ -1248,7 +1227,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
1248 dev_dbg(info->device, "CRT1e: %d\n", tmp); 1227 dev_dbg(info->device, "CRT1e: %d\n", tmp);
1249 } 1228 }
1250 1229
1251
1252 /* pixel panning */ 1230 /* pixel panning */
1253 vga_wattr(regbase, CL_AR33, 0); 1231 vga_wattr(regbase, CL_AR33, 0);
1254 1232
@@ -1274,9 +1252,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
1274 vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp); 1252 vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp);
1275 dev_dbg(info->device, "CL_SEQR1: %d\n", tmp); 1253 dev_dbg(info->device, "CL_SEQR1: %d\n", tmp);
1276 1254
1277 /* pan to requested offset */
1278 cirrusfb_pan_display(var, info);
1279
1280#ifdef CIRRUSFB_DEBUG 1255#ifdef CIRRUSFB_DEBUG
1281 cirrusfb_dbg_reg_dump(info, NULL); 1256 cirrusfb_dbg_reg_dump(info, NULL);
1282#endif 1257#endif
@@ -1332,8 +1307,7 @@ static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1332static int cirrusfb_pan_display(struct fb_var_screeninfo *var, 1307static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
1333 struct fb_info *info) 1308 struct fb_info *info)
1334{ 1309{
1335 int xoffset = 0; 1310 int xoffset;
1336 int yoffset = 0;
1337 unsigned long base; 1311 unsigned long base;
1338 unsigned char tmp, xpix; 1312 unsigned char tmp, xpix;
1339 struct cirrusfb_info *cinfo = info->par; 1313 struct cirrusfb_info *cinfo = info->par;
@@ -1347,9 +1321,8 @@ static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
1347 return -EINVAL; 1321 return -EINVAL;
1348 1322
1349 xoffset = var->xoffset * info->var.bits_per_pixel / 8; 1323 xoffset = var->xoffset * info->var.bits_per_pixel / 8;
1350 yoffset = var->yoffset;
1351 1324
1352 base = yoffset * info->fix.line_length + xoffset; 1325 base = var->yoffset * info->fix.line_length + xoffset;
1353 1326
1354 if (info->var.bits_per_pixel == 1) { 1327 if (info->var.bits_per_pixel == 1) {
1355 /* base is already correct */ 1328 /* base is already correct */
@@ -1363,10 +1336,8 @@ static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
1363 cirrusfb_WaitBLT(cinfo->regbase); 1336 cirrusfb_WaitBLT(cinfo->regbase);
1364 1337
1365 /* lower 8 + 8 bits of screen start address */ 1338 /* lower 8 + 8 bits of screen start address */
1366 vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, 1339 vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, base & 0xff);
1367 (unsigned char) (base & 0xff)); 1340 vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, (base >> 8) & 0xff);
1368 vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI,
1369 (unsigned char) (base >> 8));
1370 1341
1371 /* 0xf2 is %11110010, exclude tmp bits */ 1342 /* 0xf2 is %11110010, exclude tmp bits */
1372 tmp = vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2; 1343 tmp = vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2;
@@ -1544,10 +1515,6 @@ static void init_vgachip(struct fb_info *info)
1544 1515
1545 /* FullBandwidth (video off) and 8/9 dot clock */ 1516 /* FullBandwidth (video off) and 8/9 dot clock */
1546 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21); 1517 vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21);
1547 /* polarity (-/-), disable access to display memory,
1548 * VGA_CRTC_START_HI base address: color
1549 */
1550 WGen(cinfo, VGA_MIS_W, 0xc1);
1551 1518
1552 /* "magic cookie" - doesn't make any sense to me.. */ 1519 /* "magic cookie" - doesn't make any sense to me.. */
1553/* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */ 1520/* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */
@@ -1614,10 +1581,6 @@ static void init_vgachip(struct fb_info *info)
1614 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20); 1581 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20);
1615 /* Text cursor end: - */ 1582 /* Text cursor end: - */
1616 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00); 1583 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00);
1617 /* Screen start address high: 0 */
1618 vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, 0x00);
1619 /* Screen start address low: 0 */
1620 vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, 0x00);
1621 /* text cursor location high: 0 */ 1584 /* text cursor location high: 0 */
1622 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00); 1585 vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00);
1623 /* text cursor location low: 0 */ 1586 /* text cursor location low: 0 */
@@ -1625,10 +1588,6 @@ static void init_vgachip(struct fb_info *info)
1625 1588
1626 /* Underline Row scanline: - */ 1589 /* Underline Row scanline: - */
1627 vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00); 1590 vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00);
1628 /* mode control: timing enable, byte mode, no compat modes */
1629 vga_wcrt(cinfo->regbase, VGA_CRTC_MODE, 0xc3);
1630 /* Line Compare: not needed */
1631 vga_wcrt(cinfo->regbase, VGA_CRTC_LINE_COMPARE, 0x00);
1632 /* ### add 0x40 for text modes with > 30 MHz pixclock */ 1591 /* ### add 0x40 for text modes with > 30 MHz pixclock */
1633 /* ext. display controls: ext.adr. wrap */ 1592 /* ext. display controls: ext.adr. wrap */
1634 vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02); 1593 vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02);
@@ -1697,12 +1656,6 @@ static void init_vgachip(struct fb_info *info)
1697 1656
1698 WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */ 1657 WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */
1699 1658
1700 if (cinfo->btype != BT_ALPINE && cinfo->btype != BT_GD5480)
1701 /* polarity (-/-), enable display mem,
1702 * VGA_CRTC_START_HI i/o base = color
1703 */
1704 WGen(cinfo, VGA_MIS_W, 0xc3);
1705
1706 /* BLT Start/status: Blitter reset */ 1659 /* BLT Start/status: Blitter reset */
1707 vga_wgfx(cinfo->regbase, CL_GR31, 0x04); 1660 vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
1708 /* - " - : "end-of-reset" */ 1661 /* - " - : "end-of-reset" */
@@ -2052,7 +2005,7 @@ static int __devinit cirrusfb_register(struct fb_info *info)
2052 2005
2053 info->var.activate = FB_ACTIVATE_NOW; 2006 info->var.activate = FB_ACTIVATE_NOW;
2054 2007
2055 err = cirrusfb_decode_var(&info->var, info); 2008 err = cirrusfb_check_var(&info->var, info);
2056 if (err < 0) { 2009 if (err < 0) {
2057 /* should never happen */ 2010 /* should never happen */
2058 dev_dbg(info->device, 2011 dev_dbg(info->device,