aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/nvidia/nvidia.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2005-11-07 04:00:30 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-07 10:53:49 -0500
commit85f1503aff46089acd9f780b5259752839cf0162 (patch)
tree2e517636de893ec886e05981171484f655234c63 /drivers/video/nvidia/nvidia.c
parentecc41d5e0267de2c010e0fdf8da3c9e3e394f752 (diff)
[PATCH] nvidiafb: Fix mode setting & PPC support
This patch fixes nvifiafb mode setting code to be closer to what the X driver does, which actually makes it work on the 5200FX I have access to. It also fix the routine that gets the EDID from Open Firmware on PPC, it was broken in various ways and would crash at boot. Compared to the patch I posted to linux-fbdev last week, this one just changes a printk to be closer to the other ones in the driver. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: "Antonino A. Daplas" <adaplas@hotpop.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/video/nvidia/nvidia.c')
-rw-r--r--drivers/video/nvidia/nvidia.c84
1 files changed, 71 insertions, 13 deletions
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 308defc389a2..96d51144094a 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -627,41 +627,85 @@ static void nvidia_save_vga(struct nvidia_par *par,
627 NVTRACE_LEAVE(); 627 NVTRACE_LEAVE();
628} 628}
629 629
630#undef DUMP_REG
631
630static void nvidia_write_regs(struct nvidia_par *par) 632static void nvidia_write_regs(struct nvidia_par *par)
631{ 633{
632 struct _riva_hw_state *state = &par->ModeReg; 634 struct _riva_hw_state *state = &par->ModeReg;
633 int i; 635 int i;
634 636
635 NVTRACE_ENTER(); 637 NVTRACE_ENTER();
636 NVWriteCrtc(par, 0x11, 0x00);
637
638 NVLockUnlock(par, 0);
639 638
640 NVLoadStateExt(par, state); 639 NVLoadStateExt(par, state);
641 640
642 NVWriteMiscOut(par, state->misc_output); 641 NVWriteMiscOut(par, state->misc_output);
643 642
643 for (i = 1; i < NUM_SEQ_REGS; i++) {
644#ifdef DUMP_REG
645 printk(" SEQ[%02x] = %08x\n", i, state->seq[i]);
646#endif
647 NVWriteSeq(par, i, state->seq[i]);
648 }
649
650 /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */
651 NVWriteCrtc(par, 0x11, state->crtc[0x11] & ~0x80);
652
644 for (i = 0; i < NUM_CRT_REGS; i++) { 653 for (i = 0; i < NUM_CRT_REGS; i++) {
645 switch (i) { 654 switch (i) {
646 case 0x19: 655 case 0x19:
647 case 0x20 ... 0x40: 656 case 0x20 ... 0x40:
648 break; 657 break;
649 default: 658 default:
659#ifdef DUMP_REG
660 printk("CRTC[%02x] = %08x\n", i, state->crtc[i]);
661#endif
650 NVWriteCrtc(par, i, state->crtc[i]); 662 NVWriteCrtc(par, i, state->crtc[i]);
651 } 663 }
652 } 664 }
653 665
654 for (i = 0; i < NUM_ATC_REGS; i++) 666 for (i = 0; i < NUM_GRC_REGS; i++) {
655 NVWriteAttr(par, i, state->attr[i]); 667#ifdef DUMP_REG
656 668 printk(" GRA[%02x] = %08x\n", i, state->gra[i]);
657 for (i = 0; i < NUM_GRC_REGS; i++) 669#endif
658 NVWriteGr(par, i, state->gra[i]); 670 NVWriteGr(par, i, state->gra[i]);
671 }
672
673 for (i = 0; i < NUM_ATC_REGS; i++) {
674#ifdef DUMP_REG
675 printk("ATTR[%02x] = %08x\n", i, state->attr[i]);
676#endif
677 NVWriteAttr(par, i, state->attr[i]);
678 }
659 679
660 for (i = 0; i < NUM_SEQ_REGS; i++)
661 NVWriteSeq(par, i, state->seq[i]);
662 NVTRACE_LEAVE(); 680 NVTRACE_LEAVE();
663} 681}
664 682
683static void nvidia_vga_protect(struct nvidia_par *par, int on)
684{
685 unsigned char tmp;
686
687 if (on) {
688 /*
689 * Turn off screen and disable sequencer.
690 */
691 tmp = NVReadSeq(par, 0x01);
692
693 NVWriteSeq(par, 0x00, 0x01); /* Synchronous Reset */
694 NVWriteSeq(par, 0x01, tmp | 0x20); /* disable the display */
695 } else {
696 /*
697 * Reenable sequencer, then turn on screen.
698 */
699
700 tmp = NVReadSeq(par, 0x01);
701
702 NVWriteSeq(par, 0x01, tmp & ~0x20); /* reenable display */
703 NVWriteSeq(par, 0x00, 0x03); /* End Reset */
704 }
705}
706
707
708
665static int nvidia_calc_regs(struct fb_info *info) 709static int nvidia_calc_regs(struct fb_info *info)
666{ 710{
667 struct nvidia_par *par = info->par; 711 struct nvidia_par *par = info->par;
@@ -868,7 +912,7 @@ static void nvidia_init_vga(struct fb_info *info)
868 for (i = 0; i < 0x10; i++) 912 for (i = 0; i < 0x10; i++)
869 state->attr[i] = i; 913 state->attr[i] = i;
870 state->attr[0x10] = 0x41; 914 state->attr[0x10] = 0x41;
871 state->attr[0x11] = 0x01; 915 state->attr[0x11] = 0xff;
872 state->attr[0x12] = 0x0f; 916 state->attr[0x12] = 0x0f;
873 state->attr[0x13] = 0x00; 917 state->attr[0x13] = 0x00;
874 state->attr[0x14] = 0x00; 918 state->attr[0x14] = 0x00;
@@ -991,7 +1035,6 @@ static int nvidiafb_set_par(struct fb_info *info)
991 1035
992 nvidia_init_vga(info); 1036 nvidia_init_vga(info);
993 nvidia_calc_regs(info); 1037 nvidia_calc_regs(info);
994 nvidia_write_regs(par);
995 1038
996 NVLockUnlock(par, 0); 1039 NVLockUnlock(par, 0);
997 if (par->twoHeads) { 1040 if (par->twoHeads) {
@@ -1000,7 +1043,22 @@ static int nvidiafb_set_par(struct fb_info *info)
1000 NVLockUnlock(par, 0); 1043 NVLockUnlock(par, 0);
1001 } 1044 }
1002 1045
1003 NVWriteCrtc(par, 0x11, 0x00); 1046 nvidia_vga_protect(par, 1);
1047
1048 nvidia_write_regs(par);
1049
1050#if defined (__BIG_ENDIAN)
1051 /* turn on LFB swapping */
1052 {
1053 unsigned char tmp;
1054
1055 VGA_WR08(par->PCIO, 0x3d4, 0x46);
1056 tmp = VGA_RD08(par->PCIO, 0x3d5);
1057 tmp |= (1 << 7);
1058 VGA_WR08(par->PCIO, 0x3d5, tmp);
1059 }
1060#endif
1061
1004 info->fix.line_length = (info->var.xres_virtual * 1062 info->fix.line_length = (info->var.xres_virtual *
1005 info->var.bits_per_pixel) >> 3; 1063 info->var.bits_per_pixel) >> 3;
1006 if (info->var.accel_flags) { 1064 if (info->var.accel_flags) {
@@ -1022,7 +1080,7 @@ static int nvidiafb_set_par(struct fb_info *info)
1022 1080
1023 par->cursor_reset = 1; 1081 par->cursor_reset = 1;
1024 1082
1025 NVWriteCrtc(par, 0x11, 0xff); 1083 nvidia_vga_protect(par, 0);
1026 1084
1027 NVTRACE_LEAVE(); 1085 NVTRACE_LEAVE();
1028 return 0; 1086 return 0;