aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/nvidia
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/nvidia')
-rw-r--r--drivers/video/nvidia/nv_of.c64
-rw-r--r--drivers/video/nvidia/nv_proto.h14
-rw-r--r--drivers/video/nvidia/nv_setup.c16
-rw-r--r--drivers/video/nvidia/nvidia.c84
4 files changed, 136 insertions, 42 deletions
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
30void nvidia_create_i2c_busses(struct nvidia_par *par) {} 30#include "../edid.h"
31void nvidia_delete_i2c_busses(struct nvidia_par *par) {}
32 31
33int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid) 32int 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);
31void NVLockUnlock(struct nvidia_par *par, int); 31void 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
35void nvidia_create_i2c_busses(struct nvidia_par *par); 35void nvidia_create_i2c_busses(struct nvidia_par *par);
36void nvidia_delete_i2c_busses(struct nvidia_par *par); 36void nvidia_delete_i2c_busses(struct nvidia_par *par);
37int nvidia_probe_i2c_connector(struct fb_info *info, int conn, 37int 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)
43do { \ 43#endif
44 *(edid) = NULL; \ 44
45} while(0) 45#ifdef CONFIG_FB_OF
46int 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
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;