1/* 2 * linux/drivers/video/igafb.c -- Frame buffer device for IGA 1682 3 * 4 * Copyright (C) 1998 Vladimir Roganov and Gleb Raiko 5 * 6 * This driver is partly based on the Frame buffer device for ATI Mach64 7 * and partially on VESA-related code. 8 * 9 * Copyright (C) 1997-1998 Geert Uytterhoeven 10 * Copyright (C) 1998 Bernd Harries 11 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) 12 * 13 * This file is subject to the terms and conditions of the GNU General Public 14 * License. See the file COPYING in the main directory of this archive for 15 * more details. 16 */ 17 18/****************************************************************************** 19 20 TODO: 21 Despite of IGA Card has advanced graphic acceleration, 22 initial version is almost dummy and does not support it. 23 Support for video modes and acceleration must be added 24 together with accelerated X-Windows driver implementation. 25 26 Most important thing at this moment is that we have working 27 JavaEngine1 console & X with new console interface. 28 29******************************************************************************/ 30 31#include <linux/module.h> 32#include <linux/kernel.h> 33#include <linux/errno.h> 34#include <linux/string.h> 35#include <linux/mm.h> 36#include <linux/slab.h> 37#include <linux/vmalloc.h> 38#include <linux/delay.h> 39#include <linux/interrupt.h> 40#include <linux/fb.h> 41#include <linux/init.h> 42#include <linux/pci.h> 43#include <linux/nvram.h> 44 45#include <asm/io.h> 46 47#ifdef CONFIG_SPARC 48#include <asm/prom.h> 49#include <asm/pcic.h> 50#endif 51 52#include <video/iga.h> 53 54struct pci_mmap_map { 55 unsigned long voff; 56 unsigned long poff; 57 unsigned long size; 58 unsigned long prot_flag; 59 unsigned long prot_mask; 60}; 61 62struct iga_par { 63 struct pci_mmap_map *mmap_map; 64 unsigned long frame_buffer_phys; 65 unsigned long io_base; 66}; 67 68struct fb_info fb_info; 69 70struct fb_fix_screeninfo igafb_fix __initdata = { 71 .id = "IGA 1682", 72 .type = FB_TYPE_PACKED_PIXELS, 73 .mmio_len = 1000 74}; 75 76struct fb_var_screeninfo default_var = { 77 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ 78 .xres = 640, 79 .yres = 480, 80 .xres_virtual = 640, 81 .yres_virtual = 480, 82 .bits_per_pixel = 8, 83 .red = {0, 8, 0 }, 84 .green = {0, 8, 0 }, 85 .blue = {0, 8, 0 }, 86 .height = -1, 87 .width = -1, 88 .accel_flags = FB_ACCEL_NONE, 89 .pixclock = 39722, 90 .left_margin = 48, 91 .right_margin = 16, 92 .upper_margin = 33, 93 .lower_margin = 10, 94 .hsync_len = 96, 95 .vsync_len = 2, 96 .vmode = FB_VMODE_NONINTERLACED 97}; 98 99#ifdef CONFIG_SPARC 100struct fb_var_screeninfo default_var_1024x768 __initdata = { 101 /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */ 102 .xres = 1024, 103 .yres = 768, 104 .xres_virtual = 1024, 105 .yres_virtual = 768, 106 .bits_per_pixel = 8, 107 .red = {0, 8, 0 }, 108 .green = {0, 8, 0 }, 109 .blue = {0, 8, 0 }, 110 .height = -1, 111 .width = -1, 112 .accel_flags = FB_ACCEL_NONE, 113 .pixclock = 12699, 114 .left_margin = 176, 115 .right_margin = 16, 116 .upper_margin = 28, 117 .lower_margin = 1, 118 .hsync_len = 96, 119 .vsync_len = 3, 120 .vmode = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED 121}; 122 123struct fb_var_screeninfo default_var_1152x900 __initdata = { 124 /* 1152x900, 76 Hz, Non-Interlaced (110.0 MHz dotclock) */ 125 .xres = 1152, 126 .yres = 900, 127 .xres_virtual = 1152, 128 .yres_virtual = 900, 129 .bits_per_pixel = 8, 130 .red = { 0, 8, 0 }, 131 .green = { 0, 8, 0 }, 132 .blue = { 0, 8, 0 }, 133 .height = -1, 134 .width = -1, 135 .accel_flags = FB_ACCEL_NONE, 136 .pixclock = 9091, 137 .left_margin = 234, 138 .right_margin = 24, 139 .upper_margin = 34, 140 .lower_margin = 3, 141 .hsync_len = 100, 142 .vsync_len = 3, 143 .vmode = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED 144}; 145 146struct fb_var_screeninfo default_var_1280x1024 __initdata = { 147 /* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */ 148 .xres = 1280, 149 .yres = 1024, 150 .xres_virtual = 1280, 151 .yres_virtual = 1024, 152 .bits_per_pixel = 8, 153 .red = {0, 8, 0 }, 154 .green = {0, 8, 0 }, 155 .blue = {0, 8, 0 }, 156 .height = -1, 157 .width = -1, 158 .accel_flags = 0, 159 .pixclock = 7408, 160 .left_margin = 248, 161 .right_margin = 16, 162 .upper_margin = 38, 163 .lower_margin = 1, 164 .hsync_len = 144, 165 .vsync_len = 3, 166 .vmode = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED 167}; 168 169/* 170 * Memory-mapped I/O functions for Sparc PCI 171 * 172 * On sparc we happen to access I/O with memory mapped functions too. 173 */ 174#define pci_inb(par, reg) readb(par->io_base+(reg)) 175#define pci_outb(par, val, reg) writeb(val, par->io_base+(reg)) 176 177static inline unsigned int iga_inb(struct iga_par *par, unsigned int reg, 178 unsigned int idx) 179{ 180 pci_outb(par, idx, reg); 181 return pci_inb(par, reg + 1); 182} 183 184static inline void iga_outb(struct iga_par *par, unsigned char val, 185 unsigned int reg, unsigned int idx ) 186{ 187 pci_outb(par, idx, reg); 188 pci_outb(par, val, reg+1); 189} 190 191#endif /* CONFIG_SPARC */ 192 193/* 194 * Very important functionality for the JavaEngine1 computer: 195 * make screen border black (usign special IGA registers) 196 */ 197static void iga_blank_border(struct iga_par *par) 198{ 199 int i; 200 /* 201 * This does not work as it was designed because the overscan 202 * color is looked up in the palette. Therefore, under X11 203 * overscan changes color. 204 */ 205 for (i=0; i < 3; i++) 206 iga_outb(par, 0, IGA_EXT_CNTRL, IGA_IDX_OVERSCAN_COLOR + i); 207} 208 209#ifdef CONFIG_SPARC 210static int igafb_mmap(struct fb_info *info, 211 struct vm_area_struct *vma) 212{ 213 struct iga_par *par = (struct iga_par *)info->par; 214 unsigned int size, page, map_size = 0; 215 unsigned long map_offset = 0; 216 int i; 217 218 if (!par->mmap_map) 219 return -ENXIO; 220 221 size = vma->vm_end - vma->vm_start; 222 223 /* Each page, see which map applies */ 224 for (page = 0; page < size; ) { 225 map_size = 0; 226 for (i = 0; par->mmap_map[i].size; i++) { 227 unsigned long start = par->mmap_map[i].voff; 228 unsigned long end = start + par->mmap_map[i].size; 229 unsigned long offset = (vma->vm_pgoff << PAGE_SHIFT) + page; 230 231 if (start > offset) 232 continue; 233 if (offset >= end) 234 continue; 235 236 map_size = par->mmap_map[i].size - (offset - start); 237 map_offset = par->mmap_map[i].poff + (offset - start); 238 break; 239 } 240 if (!map_size) { 241 page += PAGE_SIZE; 242 continue; 243 } 244 if (page + map_size > size) 245 map_size = size - page; 246 247 pgprot_val(vma->vm_page_prot) &= ~(par->mmap_map[i].prot_mask); 248 pgprot_val(vma->vm_page_prot) |= par->mmap_map[i].prot_flag; 249 250 if (remap_pfn_range(vma, vma->vm_start + page, 251 map_offset >> PAGE_SHIFT, map_size, vma->vm_page_prot)) 252 return -EAGAIN; 253 254 page += map_size; 255 } 256 257 if (!map_size) 258 return -EINVAL; 259 260 vma->vm_flags |= VM_IO; 261 return 0; 262} 263#endif /* CONFIG_SPARC */ 264 265static int igafb_setcolreg(unsigned regno, unsigned red, unsigned green, 266 unsigned blue, unsigned transp, 267 struct fb_info *info) 268{ 269 /* 270 * Set a single color register. The values supplied are 271 * already rounded down to the hardware's capabilities 272 * (according to the entries in the `var' structure). Return 273 * != 0 for invalid regno. 274 */ 275 struct iga_par *par = (struct iga_par *)info->par; 276 277 if (regno >= info->cmap.len) 278 return 1; 279 280 pci_outb(par, regno, DAC_W_INDEX); 281 pci_outb(par, red, DAC_DATA); 282 pci_outb(par, green, DAC_DATA); 283 pci_outb(par, blue, DAC_DATA); 284 285 if (regno < 16) { 286 switch (info->var.bits_per_pixel) { 287 case 16: 288 ((u16*)(info->pseudo_palette))[regno] = 289 (regno << 10) | (regno << 5) | regno; 290 break; 291 case 24: 292 ((u32*)(info->pseudo_palette))[regno] = 293 (regno << 16) | (regno << 8) | regno; 294 break; 295 case 32: 296 { int i; 297 i = (regno << 8) | regno; 298 ((u32*)(info->pseudo_palette))[regno] = (i << 16) | i; 299 } 300 break; 301 } 302 } 303 return 0; 304} 305 306/* 307 * Framebuffer option structure 308 */ 309static struct fb_ops igafb_ops = { 310 .owner = THIS_MODULE, 311 .fb_setcolreg = igafb_setcolreg, 312 .fb_fillrect = cfb_fillrect, 313 .fb_copyarea = cfb_copyarea, 314 .fb_imageblit = cfb_imageblit, 315#ifdef CONFIG_SPARC 316 .fb_mmap = igafb_mmap, 317#endif 318}; 319 320static int __init iga_init(struct fb_info *info, struct iga_par *par) 321{ 322 char vramsz = iga_inb(par, IGA_EXT_CNTRL, IGA_IDX_EXT_BUS_CNTL) 323 & MEM_SIZE_ALIAS; 324 int video_cmap_len; 325 326 switch (vramsz) { 327 case MEM_SIZE_1M: 328 info->fix.smem_len = 0x100000; 329 break; 330 case MEM_SIZE_2M: 331 info->fix.smem_len = 0x200000; 332 break; 333 case MEM_SIZE_4M: 334 case MEM_SIZE_RESERVED: 335 info->fix.smem_len = 0x400000; 336 break; 337 } 338 339 if (info->var.bits_per_pixel > 8) 340 video_cmap_len = 16; 341 else 342 video_cmap_len = 256; 343 344 info->fbops = &igafb_ops; 345 info->flags = FBINFO_DEFAULT; 346 347 fb_alloc_cmap(&info->cmap, video_cmap_len, 0); 348 349 if (register_framebuffer(info) < 0) 350 return 0; 351 352 printk("fb%d: %s frame buffer device at 0x%08lx [%dMB VRAM]\n", 353 info->node, info->fix.id, 354 par->frame_buffer_phys, info->fix.smem_len >> 20); 355 356 iga_blank_border(par); 357 return 1; 358} 359 360static int __init igafb_init(void) 361{ 362 struct fb_info *info; 363 struct pci_dev *pdev; 364 struct iga_par *par; 365 unsigned long addr; 366 int size, iga2000 = 0; 367 368 if (fb_get_options("igafb", NULL)) 369 return -ENODEV; 370 371 pdev = pci_get_device(PCI_VENDOR_ID_INTERG, 372 PCI_DEVICE_ID_INTERG_1682, 0); 373 if (pdev == NULL) { 374 pdev = pci_get_device(PCI_VENDOR_ID_INTERG, 0x2000, 0); 375 if(pdev == NULL) { 376 return -ENXIO; 377 } 378 iga2000 = 1; 379 } 380 /* We leak a reference here but as it cannot be unloaded this is 381 fine. If you write unload code remember to free it in unload */ 382 383 size = sizeof(struct iga_par) + sizeof(u32)*16; 384 385 info = framebuffer_alloc(size, &pdev->dev); 386 if (!info) { 387 printk("igafb_init: can't alloc fb_info\n"); 388 pci_dev_put(pdev); 389 return -ENOMEM; 390 } 391 392 par = info->par; 393 394 if ((addr = pdev->resource[0].start) == 0) { 395 printk("igafb_init: no memory start\n"); 396 kfree(info); 397 pci_dev_put(pdev); 398 return -ENXIO; 399 } 400 401 if ((info->screen_base = ioremap(addr, 1024*1024*2)) == 0) { 402 printk("igafb_init: can't remap %lx[2M]\n", addr); 403 kfree(info); 404 pci_dev_put(pdev); 405 return -ENXIO; 406 } 407 408 par->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK; 409 410#ifdef CONFIG_SPARC 411 /* 412 * The following is sparc specific and this is why: 413 * 414 * IGS2000 has its I/O memory mapped and we want 415 * to generate memory cycles on PCI, e.g. do ioremap(), 416 * then readb/writeb() as in Documentation/IO-mapping.txt. 417 * 418 * IGS1682 is more traditional, it responds to PCI I/O 419 * cycles, so we want to access it with inb()/outb(). 420 * 421 * On sparc, PCIC converts CPU memory access within 422 * phys window 0x3000xxxx into PCI I/O cycles. Therefore 423 * we may use readb/writeb to access them with IGS1682. 424 * 425 * We do not take io_base_phys from resource[n].start 426 * on IGS1682 because that chip is BROKEN. It does not 427 * have a base register for I/O. We just "know" what its 428 * I/O addresses are. 429 */ 430 if (iga2000) { 431 igafb_fix.mmio_start = par->frame_buffer_phys | 0x00800000; 432 } else { 433 igafb_fix.mmio_start = 0x30000000; 434 } 435 if ((par->io_base = (int) ioremap(igafb_fix.mmio_start, igafb_fix.smem_len)) == 0) { 436 printk("igafb_init: can't remap %lx[4K]\n", igafb_fix.mmio_start); 437 iounmap((void *)info->screen_base); 438 kfree(info); 439 pci_dev_put(pdev); 440 return -ENXIO; 441 } 442 443 /* 444 * Figure mmap addresses from PCI config space. 445 * We need two regions: for video memory and for I/O ports. 446 * Later one can add region for video coprocessor registers. 447 * However, mmap routine loops until size != 0, so we put 448 * one additional region with size == 0. 449 */ 450 451 par->mmap_map = kzalloc(4 * sizeof(*par->mmap_map), GFP_ATOMIC); 452 if (!par->mmap_map) { 453 printk("igafb_init: can't alloc mmap_map\n"); 454 iounmap((void *)par->io_base); 455 iounmap(info->screen_base); 456 kfree(info); 457 pci_dev_put(pdev); 458 return -ENOMEM; 459 } 460 461 /* 462 * Set default vmode and cmode from PROM properties. 463 */ 464 { 465 struct device_node *dp = pci_device_to_OF_node(pdev); 466 int node = dp->node; 467 int width = prom_getintdefault(node, "width", 1024); 468 int height = prom_getintdefault(node, "height", 768); 469 int depth = prom_getintdefault(node, "depth", 8); 470 switch (width) { 471 case 1024: 472 if (height == 768) 473 default_var = default_var_1024x768; 474 break; 475 case 1152: 476 if (height == 900) 477 default_var = default_var_1152x900; 478 break; 479 case 1280: 480 if (height == 1024) 481 default_var = default_var_1280x1024; 482 break; 483 default: 484 break; 485 } 486 487 switch (depth) { 488 case 8: 489 default_var.bits_per_pixel = 8; 490 break; 491 case 16: 492 default_var.bits_per_pixel = 16; 493 break; 494 case 24: 495 default_var.bits_per_pixel = 24; 496 break; 497 case 32: 498 default_var.bits_per_pixel = 32; 499 break; 500 default: 501 break; 502 } 503 } 504 505#endif 506 igafb_fix.smem_start = (unsigned long) info->screen_base; 507 igafb_fix.line_length = default_var.xres*(default_var.bits_per_pixel/8); 508 igafb_fix.visual = default_var.bits_per_pixel <= 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; 509 510 info->var = default_var; 511 info->fix = igafb_fix; 512 info->pseudo_palette = (void *)(par + 1); 513 514 if (!iga_init(info, par)) { 515 iounmap((void *)par->io_base); 516 iounmap(info->screen_base); 517 kfree(par->mmap_map); 518 kfree(info); 519 return -ENODEV; 520 } 521 522#ifdef CONFIG_SPARC 523 /* 524 * Add /dev/fb mmap values. 525 */ 526 527 /* First region is for video memory */ 528 par->mmap_map[0].voff = 0x0; 529 par->mmap_map[0].poff = par->frame_buffer_phys & PAGE_MASK; 530 par->mmap_map[0].size = info->fix.smem_len & PAGE_MASK; 531 par->mmap_map[0].prot_mask = SRMMU_CACHE; 532 par->mmap_map[0].prot_flag = SRMMU_WRITE; 533 534 /* Second region is for I/O ports */ 535 par->mmap_map[1].voff = par->frame_buffer_phys & PAGE_MASK; 536 par->mmap_map[1].poff = info->fix.smem_start & PAGE_MASK; 537 par->mmap_map[1].size = PAGE_SIZE * 2; /* X wants 2 pages */ 538 par->mmap_map[1].prot_mask = SRMMU_CACHE; 539 par->mmap_map[1].prot_flag = SRMMU_WRITE; 540#endif /* CONFIG_SPARC */ 541 542 return 0; 543} 544 545static int __init igafb_setup(char *options) 546{ 547 char *this_opt; 548 549 if (!options || !*options) 550 return 0; 551 552 while ((this_opt = strsep(&options, ",")) != NULL) { 553 } 554 return 0; 555} 556 557module_init(igafb_init); 558MODULE_LICENSE("GPL"); 559static struct pci_device_id igafb_pci_tbl[] __devinitdata = { 560 { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682, 561 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 562 { } 563}; 564 565MODULE_DEVICE_TABLE(pci, igafb_pci_tbl); 566