patch-2.3.35 linux/drivers/video/igafb.c

Next file: linux/drivers/video/leofb.c
Previous file: linux/drivers/video/iga.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.34/linux/drivers/video/igafb.c linux/drivers/video/igafb.c
@@ -23,11 +23,9 @@
        Support for video modes and acceleration must be added
        together with accelerated X-Windows driver implementation.
 
-                                                (Anyone to help with this?)
-
        Most important thing at this moment is that we have working
        JavaEngine1  console & X  with new console interface.
-       
+
 ******************************************************************************/
 
 #include <linux/module.h>
@@ -78,7 +76,7 @@
 struct fb_info_iga {
     struct fb_info fb_info;
     unsigned long frame_buffer_phys;
-    unsigned long frame_buffer;
+    char *frame_buffer;
     unsigned long io_base_phys;
     unsigned long io_base;
     u32 total_vram;
@@ -142,23 +140,19 @@
 
 /*
  *   Memory-mapped I/O functions for Sparc PCI
+ *
+ * On sparc we happen to access I/O with memory mapped functions too.
  */ 
-static inline unsigned char pci_inb (struct fb_info_iga *info, 
-				     unsigned int reg) 
-{
-	return *(volatile unsigned char*)(info->io_base + reg);
-}
-static inline void pci_outb (struct fb_info_iga *info, unsigned char c,
-			     unsigned int reg) 
-{
-	*(volatile unsigned char*)(info->io_base + reg) = c;
-}
+#define pci_inb(info, reg)        readb(info->io_base+(reg))
+#define pci_outb(info, val, reg)  writeb(val, info->io_base+(reg))
+
 static inline unsigned int iga_inb(struct fb_info_iga *info,
 				   unsigned int reg, unsigned int idx )
 {
         pci_outb(info, idx, reg);
         return pci_inb(info, reg + 1);
 }
+
 static inline void iga_outb(struct fb_info_iga *info, unsigned char val,
 			    unsigned int reg, unsigned int idx )
 {
@@ -176,8 +170,24 @@
 {
         int i;
 
-        for (i=0; i < 3; i++) 
-                iga_outb(info, 0, IGA_EXT_CNTRL, IGA_IDX_OVERSCAN_COLOR + i);
+#if 0
+	/*
+	 * PROM does this for us, so keep this code as a reminder
+	 * about required read from 0x3DA and writing of 0x20 in the end.
+	 */
+	(void) pci_inb(info, 0x3DA);		/* required for every access */
+	pci_outb(info, IGA_IDX_VGA_OVERSCAN, IGA_ATTR_CTL);
+	(void) pci_inb(info, IGA_ATTR_CTL+1);
+	pci_outb(info, 0x38, IGA_ATTR_CTL);
+	pci_outb(info, 0x20, IGA_ATTR_CTL);	/* re-enable visual */
+#endif
+	/*
+	 * This does not work as it was designed because the overscan
+	 * color is looked up in the palette. Therefore, under X11
+	 * overscan changes color.
+	 */
+	for (i=0; i < 3; i++)
+		iga_outb(info, 0, IGA_EXT_CNTRL, IGA_IDX_OVERSCAN_COLOR + i);
 }
 
 
@@ -217,7 +227,7 @@
         memset(fix, 0, sizeof(struct fb_fix_screeninfo));
         strcpy(fix->id, igafb_name);
 
-        fix->smem_start = fb->frame_buffer;
+        fix->smem_start = (unsigned long) fb->frame_buffer;
         fix->smem_len = fb->total_vram;
         fix->xpanstep = 0;
         fix->ypanstep = 0;
@@ -269,17 +279,17 @@
 	for (page = 0; page < size; ) {
 		map_size = 0;
 		for (i = 0; fb->mmap_map[i].size; i++) {
-			unsigned long start = (fb->mmap_map[i].voff) >> PAGE_SHIFT;
-			unsigned long end = start + (fb->mmap_map[i].size) >> PAGE_SHIFT;
-			unsigned long offset = vma->vm_pgoff + (page >> PAGE_SHIFT);
+			unsigned long start = fb->mmap_map[i].voff;
+			unsigned long end = start + fb->mmap_map[i].size;
+			unsigned long offset = (vma->vm_pgoff << PAGE_SHIFT) + page;
 
 			if (start > offset)
 				continue;
 			if (offset >= end)
 				continue;
 
-			map_size = fb->mmap_map[i].size - ((offset - start) << PAGE_SHIFT);
-			map_offset = fb->mmap_map[i].poff + ((offset - start) << PAGE_SHIFT);
+			map_size = fb->mmap_map[i].size - (offset - start);
+			map_offset = fb->mmap_map[i].poff + (offset - start);
 			break;
 		}
 		if (!map_size) {
@@ -359,13 +369,13 @@
         info->palette[regno].red   = red;
         info->palette[regno].green = green;
         info->palette[regno].blue  = blue;
-        
+
 	pci_outb(info, regno, DAC_W_INDEX);
 	pci_outb(info, red,   DAC_DATA);
 	pci_outb(info, green, DAC_DATA);
 	pci_outb(info, blue,  DAC_DATA);
 
-	if (regno << 16)
+	if (regno < 16)
 		switch (default_var.bits_per_pixel) {
 #ifdef FBCON_HAS_CFB16
 		case 16:
@@ -475,7 +485,7 @@
         struct fb_fix_screeninfo fix;
         struct display *display;
         struct display_switch *sw;
-        
+
         if (con >= 0)
                 display = &fb_display[con];
         else 
@@ -484,7 +494,7 @@
         igafb_get_fix(&fix, con, &info->fb_info);
 
         memset(display, 0, sizeof(struct display));
-        display->screen_base = (char*)info->frame_buffer;
+        display->screen_base = info->frame_buffer;
         display->visual = fix.visual;
         display->type = fix.type;
         display->type_aux = fix.type_aux;
@@ -506,19 +516,19 @@
         case 15:
         case 16:
                 sw = &fbcon_cfb16;
-		display->dispsw_data = fbcon_cmap.cfb16;
+		display->dispsw_data = info->fbcon_cmap.cfb16;
                 break;
 #endif
 #ifdef FBCON_HAS_CFB24
 	case 24:
 		sw = &fbcon_cfb24;
-		display->dispsw_data = fbcon_cmap.cfb24;
+		display->dispsw_data = info->fbcon_cmap.cfb24;
 		break;
 #endif
 #ifdef FBCON_HAS_CFB32
         case 32:
                 sw = &fbcon_cfb32;
-		display->dispsw_data = fbcon_cmap.cfb32;
+		display->dispsw_data = info->fbcon_cmap.cfb32;
                 break;
 #endif
         default:
@@ -534,15 +544,15 @@
 static int igafb_switch(int con, struct fb_info *fb_info)
 {
 	struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
-	
+
         /* Do we have to save the colormap? */
         if (fb_display[info->currcon].cmap.len)
                 fb_get_cmap(&fb_display[info->currcon].cmap, 1,
                             iga_getcolreg, fb_info);
-        
-        info->currcon = con;
-        /* Install new colormap */
-        do_install_cmap(con, fb_info);
+
+	info->currcon = con;
+	/* Install new colormap */
+	do_install_cmap(con, fb_info);
 	igafb_update_var(con, fb_info);
         return 1;
 }
@@ -577,15 +587,17 @@
         if (default_var.bits_per_pixel > 8) {
                 info->video_cmap_len = 16;
         } else {
-		int i, j;
-                for(i = 0; i < 16; i++) {
-                        j = color_table[i];
-                        info->palette[i].red   = default_red[j];
-                        info->palette[i].green = default_grn[j];
-                        info->palette[i].blue  = default_blu[j];
-                }
                 info->video_cmap_len = 256;
         }
+	{
+		int j, k;
+		for (j = 0; j < 16; j++) {
+			k = color_table[j];
+			info->palette[j].red = default_red[k];
+			info->palette[j].green = default_grn[k];
+			info->palette[j].blue = default_blu[k];
+		}
+	}
 
 	strcpy(info->fb_info.modename, igafb_name);
 	info->fb_info.node = -1;
@@ -598,16 +610,6 @@
 	info->fb_info.blank = &igafb_blank;
 	info->fb_info.flags=FBINFO_FLAG_DEFAULT;
 
-	{
-		int j, k;
-		for (j = 0; j < 16; j++) {
-			k = color_table[j];
-			info->palette[j].red = default_red[k];
-			info->palette[j].green = default_grn[k];
-			info->palette[j].blue = default_blu[k];
-		}
-	}
-
 	igafb_set_disp(-1, info);
 
 	if (register_framebuffer(&info->fb_info) < 0)
@@ -619,7 +621,7 @@
 
 	iga_blank_border(info); 
 	return 1;
-}	
+}
 
 
 int __init igafb_init(void)
@@ -637,6 +639,10 @@
         pdev = pci_find_device(PCI_VENDOR_ID_INTERG, 
                                PCI_DEVICE_ID_INTERG_1682, 0);
 	if (pdev == NULL) {
+		/*
+		 * XXX We tried to use cyber2000fb.c for IGS 2000.
+		 * But it does not initialize the chip in JavaStation-E, alas.
+		 */
         	pdev = pci_find_device(PCI_VENDOR_ID_INTERG, 
                                0x2000, 0);
         	if(pdev == NULL)
@@ -651,35 +657,43 @@
         }
         memset(info, 0, sizeof(struct fb_info_iga));
 
-	info->frame_buffer = pdev->resource[0].start;
+	info->frame_buffer = ioremap(pdev->resource[0].start, 1024*1024*2);
 	if (!info->frame_buffer) {
 		kfree(info);
 		return -ENXIO;
 	}
 
-        pcibios_read_config_dword(0, pdev->devfn,
-                                  PCI_BASE_ADDRESS_0, 
-                                  (unsigned int*)&addr);
+	addr = pdev->resource[0].start;
 	if (!addr)
 		return -ENXIO;
 	info->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK;
 
 #ifdef __sparc__
-
-	info->io_base_phys = info->frame_buffer_phys;
-
 	/*
-	 * The right test would be to look if there is a base I/O address.
-	 * But it appears that IGA 1682 reuses _memory_ address as a base
-	 * for I/O accesses.
+	 * The following is sparc specific and this is why:
+	 *
+	 * IGS2000 has its I/O memory mapped and we want
+	 * to generate memory cycles on PCI, e.g. do ioremap(),
+	 * then readb/writeb() as in Documentation/IO-mapping.txt.
+	 *
+	 * IGS1682 is more traditional, it responds to PCI I/O
+	 * cycles, so we want to access it with inb()/outb().
+	 *
+	 * On sparc, PCIC converts CPU memory access within
+	 * phys window 0x3000xxxx into PCI I/O cycles. Therefore
+	 * we may use readb/writeb to access them with IGS1682.
+	 *
+	 * We do not take io_base_phys from resource[n].start
+	 * on IGS1682 because that chip is BROKEN. It does not
+	 * have a base register for I/O. We just "know" what its
+	 * I/O addresses are.
 	 */
 	if (iga2000) {
-		info->io_base = (int) sparc_alloc_io(info->frame_buffer_phys |
-		    0x00800000, NULL, 0x1000, "iga", 0, 0);
+		info->io_base_phys = info->frame_buffer_phys | 0x00800000;
 	} else {
-		/* Obtain virtual address and correct physical by PCIC shift */
-		info->io_base = pcic_alloc_io(&info->io_base_phys);
+		info->io_base_phys = 0x30000000;	/* XXX */
 	}
+	info->io_base = (int) ioremap(info->io_base_phys, 0x1000);
 	if (!info->io_base) {
                 kfree(info);
 		return -ENXIO;
@@ -748,6 +762,7 @@
             }
 
 #endif
+
         if (!iga_init(info)) {
 		if (info->mmap_map)
 			kfree(info->mmap_map);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)