diff options
-rw-r--r-- | drivers/video/Kconfig | 2 | ||||
-rw-r--r-- | drivers/video/nvidia/nv_of.c | 64 | ||||
-rw-r--r-- | drivers/video/nvidia/nv_proto.h | 14 | ||||
-rw-r--r-- | drivers/video/nvidia/nv_setup.c | 16 | ||||
-rw-r--r-- | drivers/video/nvidia/nvidia.c | 84 |
5 files changed, 137 insertions, 43 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 1eec03a9b102..9c54695911c1 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -703,7 +703,7 @@ config FB_NVIDIA | |||
703 | 703 | ||
704 | config FB_NVIDIA_I2C | 704 | config FB_NVIDIA_I2C |
705 | bool "Enable DDC Support" | 705 | bool "Enable DDC Support" |
706 | depends on FB_NVIDIA && !PPC_OF | 706 | depends on FB_NVIDIA |
707 | help | 707 | help |
708 | This enables I2C support for nVidia Chipsets. This is used | 708 | This enables I2C support for nVidia Chipsets. This is used |
709 | only for getting EDID information from the attached display | 709 | only for getting EDID information from the attached display |
diff --git a/drivers/video/nvidia/nv_of.c b/drivers/video/nvidia/nv_of.c index 4fa2cf9a8af2..7a03d040b1a3 100644 --- a/drivers/video/nvidia/nv_of.c +++ b/drivers/video/nvidia/nv_of.c | |||
@@ -27,34 +27,60 @@ | |||
27 | #include "nv_local.h" | 27 | #include "nv_local.h" |
28 | #include "nv_proto.h" | 28 | #include "nv_proto.h" |
29 | 29 | ||
30 | void nvidia_create_i2c_busses(struct nvidia_par *par) {} | 30 | #include "../edid.h" |
31 | void nvidia_delete_i2c_busses(struct nvidia_par *par) {} | ||
32 | 31 | ||
33 | int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid) | 32 | int nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid) |
34 | { | 33 | { |
35 | struct nvidia_par *par = info->par; | 34 | struct nvidia_par *par = info->par; |
36 | struct device_node *dp; | 35 | struct device_node *parent, *dp; |
37 | unsigned char *pedid = NULL; | 36 | unsigned char *pedid = NULL; |
38 | unsigned char *disptype = NULL; | ||
39 | static char *propnames[] = { | 37 | static char *propnames[] = { |
40 | "DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID,B", "EDID,A", NULL }; | 38 | "DFP,EDID", "LCD,EDID", "EDID", "EDID1", |
39 | "EDID,B", "EDID,A", NULL }; | ||
41 | int i; | 40 | int i; |
42 | 41 | ||
43 | dp = pci_device_to_OF_node(par->pci_dev); | 42 | parent = pci_device_to_OF_node(par->pci_dev); |
44 | for (; dp != NULL; dp = dp->child) { | 43 | if (parent == NULL) |
45 | disptype = (unsigned char *)get_property(dp, "display-type", NULL); | 44 | return -1; |
46 | if (disptype == NULL) | 45 | if (par->twoHeads) { |
47 | continue; | 46 | char *pname; |
48 | if (strncmp(disptype, "LCD", 3) != 0) | 47 | int len; |
49 | continue; | 48 | |
49 | for (dp = NULL; | ||
50 | (dp = of_get_next_child(parent, dp)) != NULL;) { | ||
51 | pname = (char *)get_property(dp, "name", NULL); | ||
52 | if (!pname) | ||
53 | continue; | ||
54 | len = strlen(pname); | ||
55 | if ((pname[len-1] == 'A' && conn == 1) || | ||
56 | (pname[len-1] == 'B' && conn == 2)) { | ||
57 | for (i = 0; propnames[i] != NULL; ++i) { | ||
58 | pedid = (unsigned char *) | ||
59 | get_property(dp, propnames[i], | ||
60 | NULL); | ||
61 | if (pedid != NULL) | ||
62 | break; | ||
63 | } | ||
64 | of_node_put(dp); | ||
65 | break; | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | if (pedid == NULL) { | ||
50 | for (i = 0; propnames[i] != NULL; ++i) { | 70 | for (i = 0; propnames[i] != NULL; ++i) { |
51 | pedid = (unsigned char *) | 71 | pedid = (unsigned char *) |
52 | get_property(dp, propnames[i], NULL); | 72 | get_property(parent, propnames[i], NULL); |
53 | if (pedid != NULL) { | 73 | if (pedid != NULL) |
54 | *out_edid = pedid; | 74 | break; |
55 | return 0; | ||
56 | } | ||
57 | } | 75 | } |
58 | } | 76 | } |
59 | return 1; | 77 | if (pedid) { |
78 | *out_edid = kmalloc(EDID_LENGTH, GFP_KERNEL); | ||
79 | if (*out_edid == NULL) | ||
80 | return -1; | ||
81 | memcpy(*out_edid, pedid, EDID_LENGTH); | ||
82 | printk(KERN_DEBUG "nvidiafb: Found OF EDID for head %d\n", conn); | ||
83 | return 0; | ||
84 | } | ||
85 | return -1; | ||
60 | } | 86 | } |
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h index cac44fc7f587..3d35b77a4af5 100644 --- a/drivers/video/nvidia/nv_proto.h +++ b/drivers/video/nvidia/nv_proto.h | |||
@@ -31,7 +31,7 @@ int NVShowHideCursor(struct nvidia_par *par, int); | |||
31 | void NVLockUnlock(struct nvidia_par *par, int); | 31 | void NVLockUnlock(struct nvidia_par *par, int); |
32 | 32 | ||
33 | /* in nvidia-i2c.c */ | 33 | /* in nvidia-i2c.c */ |
34 | #if defined(CONFIG_FB_NVIDIA_I2C) || defined (CONFIG_PPC_OF) | 34 | #ifdef CONFIG_FB_NVIDIA_I2C |
35 | void nvidia_create_i2c_busses(struct nvidia_par *par); | 35 | void nvidia_create_i2c_busses(struct nvidia_par *par); |
36 | void nvidia_delete_i2c_busses(struct nvidia_par *par); | 36 | void nvidia_delete_i2c_busses(struct nvidia_par *par); |
37 | int nvidia_probe_i2c_connector(struct fb_info *info, int conn, | 37 | int nvidia_probe_i2c_connector(struct fb_info *info, int conn, |
@@ -39,10 +39,14 @@ int nvidia_probe_i2c_connector(struct fb_info *info, int conn, | |||
39 | #else | 39 | #else |
40 | #define nvidia_create_i2c_busses(...) | 40 | #define nvidia_create_i2c_busses(...) |
41 | #define nvidia_delete_i2c_busses(...) | 41 | #define nvidia_delete_i2c_busses(...) |
42 | #define nvidia_probe_i2c_connector(p, c, edid) \ | 42 | #define nvidia_probe_i2c_connector(p, c, edid) (-1) |
43 | do { \ | 43 | #endif |
44 | *(edid) = NULL; \ | 44 | |
45 | } while(0) | 45 | #ifdef CONFIG_FB_OF |
46 | int nvidia_probe_of_connector(struct fb_info *info, int conn, | ||
47 | u8 ** out_edid); | ||
48 | #else | ||
49 | #define nvidia_probe_of_connector(p, c, edid) (-1) | ||
46 | #endif | 50 | #endif |
47 | 51 | ||
48 | /* in nv_accel.c */ | 52 | /* in nv_accel.c */ |
diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c index 11c84178f420..1f06a9f1bd0f 100644 --- a/drivers/video/nvidia/nv_setup.c +++ b/drivers/video/nvidia/nv_setup.c | |||
@@ -190,9 +190,9 @@ static int NVIsConnected(struct nvidia_par *par, int output) | |||
190 | present = (NV_RD32(PRAMDAC, 0x0608) & (1 << 28)) ? 1 : 0; | 190 | present = (NV_RD32(PRAMDAC, 0x0608) & (1 << 28)) ? 1 : 0; |
191 | 191 | ||
192 | if (present) | 192 | if (present) |
193 | printk("nvidiafb: CRTC%i found\n", output); | 193 | printk("nvidiafb: CRTC%i analog found\n", output); |
194 | else | 194 | else |
195 | printk("nvidiafb: CRTC%i not found\n", output); | 195 | printk("nvidiafb: CRTC%i analog not found\n", output); |
196 | 196 | ||
197 | NV_WR32(par->PRAMDAC0, 0x0608, NV_RD32(par->PRAMDAC0, 0x0608) & | 197 | NV_WR32(par->PRAMDAC0, 0x0608, NV_RD32(par->PRAMDAC0, 0x0608) & |
198 | 0x0000EFFF); | 198 | 0x0000EFFF); |
@@ -305,6 +305,9 @@ void NVCommonSetup(struct fb_info *info) | |||
305 | int FlatPanel = -1; /* really means the CRTC is slaved */ | 305 | int FlatPanel = -1; /* really means the CRTC is slaved */ |
306 | int Television = 0; | 306 | int Television = 0; |
307 | 307 | ||
308 | memset(&monitorA, 0, sizeof(struct fb_monspecs)); | ||
309 | memset(&monitorB, 0, sizeof(struct fb_monspecs)); | ||
310 | |||
308 | par->PRAMIN = par->REGS + (0x00710000 / 4); | 311 | par->PRAMIN = par->REGS + (0x00710000 / 4); |
309 | par->PCRTC0 = par->REGS + (0x00600000 / 4); | 312 | par->PCRTC0 = par->REGS + (0x00600000 / 4); |
310 | par->PRAMDAC0 = par->REGS + (0x00680000 / 4); | 313 | par->PRAMDAC0 = par->REGS + (0x00680000 / 4); |
@@ -401,7 +404,8 @@ void NVCommonSetup(struct fb_info *info) | |||
401 | nvidia_create_i2c_busses(par); | 404 | nvidia_create_i2c_busses(par); |
402 | if (!par->twoHeads) { | 405 | if (!par->twoHeads) { |
403 | par->CRTCnumber = 0; | 406 | par->CRTCnumber = 0; |
404 | nvidia_probe_i2c_connector(info, 1, &edidA); | 407 | if (nvidia_probe_i2c_connector(info, 1, &edidA)) |
408 | nvidia_probe_of_connector(info, 1, &edidA); | ||
405 | if (edidA && !fb_parse_edid(edidA, &var)) { | 409 | if (edidA && !fb_parse_edid(edidA, &var)) { |
406 | printk("nvidiafb: EDID found from BUS1\n"); | 410 | printk("nvidiafb: EDID found from BUS1\n"); |
407 | monA = &monitorA; | 411 | monA = &monitorA; |
@@ -488,14 +492,16 @@ void NVCommonSetup(struct fb_info *info) | |||
488 | oldhead = NV_RD32(par->PCRTC0, 0x00000860); | 492 | oldhead = NV_RD32(par->PCRTC0, 0x00000860); |
489 | NV_WR32(par->PCRTC0, 0x00000860, oldhead | 0x00000010); | 493 | NV_WR32(par->PCRTC0, 0x00000860, oldhead | 0x00000010); |
490 | 494 | ||
491 | nvidia_probe_i2c_connector(info, 1, &edidA); | 495 | if (nvidia_probe_i2c_connector(info, 1, &edidA)) |
496 | nvidia_probe_of_connector(info, 1, &edidA); | ||
492 | if (edidA && !fb_parse_edid(edidA, &var)) { | 497 | if (edidA && !fb_parse_edid(edidA, &var)) { |
493 | printk("nvidiafb: EDID found from BUS1\n"); | 498 | printk("nvidiafb: EDID found from BUS1\n"); |
494 | monA = &monitorA; | 499 | monA = &monitorA; |
495 | fb_edid_to_monspecs(edidA, monA); | 500 | fb_edid_to_monspecs(edidA, monA); |
496 | } | 501 | } |
497 | 502 | ||
498 | nvidia_probe_i2c_connector(info, 2, &edidB); | 503 | if (nvidia_probe_i2c_connector(info, 2, &edidB)) |
504 | nvidia_probe_of_connector(info, 2, &edidB); | ||
499 | if (edidB && !fb_parse_edid(edidB, &var)) { | 505 | if (edidB && !fb_parse_edid(edidB, &var)) { |
500 | printk("nvidiafb: EDID found from BUS2\n"); | 506 | printk("nvidiafb: EDID found from BUS2\n"); |
501 | monB = &monitorB; | 507 | monB = &monitorB; |
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 | |||
630 | static void nvidia_write_regs(struct nvidia_par *par) | 632 | static 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 | ||
683 | static 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 | |||
665 | static int nvidia_calc_regs(struct fb_info *info) | 709 | static 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; |