linux/drivers/video/fbdev/igafb.c
<<
>>
Prefs
   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#if 0
 201        /*
 202         * PROM does this for us, so keep this code as a reminder
 203         * about required read from 0x3DA and writing of 0x20 in the end.
 204         */
 205        (void) pci_inb(par, 0x3DA);             /* required for every access */
 206        pci_outb(par, IGA_IDX_VGA_OVERSCAN, IGA_ATTR_CTL);
 207        (void) pci_inb(par, IGA_ATTR_CTL+1);
 208        pci_outb(par, 0x38, IGA_ATTR_CTL);
 209        pci_outb(par, 0x20, IGA_ATTR_CTL);      /* re-enable visual */
 210#endif
 211        /*
 212         * This does not work as it was designed because the overscan
 213         * color is looked up in the palette. Therefore, under X11
 214         * overscan changes color.
 215         */
 216        for (i=0; i < 3; i++)
 217                iga_outb(par, 0, IGA_EXT_CNTRL, IGA_IDX_OVERSCAN_COLOR + i);
 218}
 219
 220#ifdef CONFIG_SPARC
 221static int igafb_mmap(struct fb_info *info,
 222                      struct vm_area_struct *vma)
 223{
 224        struct iga_par *par = (struct iga_par *)info->par;
 225        unsigned int size, page, map_size = 0;
 226        unsigned long map_offset = 0;
 227        int i;
 228
 229        if (!par->mmap_map)
 230                return -ENXIO;
 231
 232        size = vma->vm_end - vma->vm_start;
 233
 234        /* Each page, see which map applies */
 235        for (page = 0; page < size; ) {
 236                map_size = 0;
 237                for (i = 0; par->mmap_map[i].size; i++) {
 238                        unsigned long start = par->mmap_map[i].voff;
 239                        unsigned long end = start + par->mmap_map[i].size;
 240                        unsigned long offset = (vma->vm_pgoff << PAGE_SHIFT) + page;
 241
 242                        if (start > offset)
 243                                continue;
 244                        if (offset >= end)
 245                                continue;
 246
 247                        map_size = par->mmap_map[i].size - (offset - start);
 248                        map_offset = par->mmap_map[i].poff + (offset - start);
 249                        break;
 250                }
 251                if (!map_size) {
 252                        page += PAGE_SIZE;
 253                        continue;
 254                }
 255                if (page + map_size > size)
 256                        map_size = size - page;
 257
 258                pgprot_val(vma->vm_page_prot) &= ~(par->mmap_map[i].prot_mask);
 259                pgprot_val(vma->vm_page_prot) |= par->mmap_map[i].prot_flag;
 260
 261                if (remap_pfn_range(vma, vma->vm_start + page,
 262                        map_offset >> PAGE_SHIFT, map_size, vma->vm_page_prot))
 263                        return -EAGAIN;
 264
 265                page += map_size;
 266        }
 267
 268        if (!map_size)
 269                return -EINVAL;
 270
 271        vma->vm_flags |= VM_IO;
 272        return 0;
 273}
 274#endif /* CONFIG_SPARC */
 275
 276static int igafb_setcolreg(unsigned regno, unsigned red, unsigned green,
 277                           unsigned blue, unsigned transp,
 278                           struct fb_info *info)
 279{
 280        /*
 281         *  Set a single color register. The values supplied are
 282         *  already rounded down to the hardware's capabilities
 283         *  (according to the entries in the `var' structure). Return
 284         *  != 0 for invalid regno.
 285         */
 286        struct iga_par *par = (struct iga_par *)info->par;
 287
 288        if (regno >= info->cmap.len)
 289                return 1;
 290
 291        pci_outb(par, regno, DAC_W_INDEX);
 292        pci_outb(par, red,   DAC_DATA);
 293        pci_outb(par, green, DAC_DATA);
 294        pci_outb(par, blue,  DAC_DATA);
 295
 296        if (regno < 16) {
 297                switch (info->var.bits_per_pixel) {
 298                case 16:
 299                        ((u16*)(info->pseudo_palette))[regno] = 
 300                                (regno << 10) | (regno << 5) | regno;
 301                        break;
 302                case 24:
 303                        ((u32*)(info->pseudo_palette))[regno] = 
 304                                (regno << 16) | (regno << 8) | regno;
 305                break;
 306                case 32:
 307                        { int i;
 308                        i = (regno << 8) | regno;
 309                        ((u32*)(info->pseudo_palette))[regno] = (i << 16) | i;
 310                        }
 311                        break;
 312                }
 313        }
 314        return 0;
 315}
 316
 317/*
 318 * Framebuffer option structure
 319 */
 320static struct fb_ops igafb_ops = {
 321        .owner          = THIS_MODULE,
 322        .fb_setcolreg   = igafb_setcolreg,
 323        .fb_fillrect    = cfb_fillrect,
 324        .fb_copyarea    = cfb_copyarea,
 325        .fb_imageblit   = cfb_imageblit,
 326#ifdef CONFIG_SPARC
 327        .fb_mmap        = igafb_mmap,
 328#endif
 329};
 330
 331static int __init iga_init(struct fb_info *info, struct iga_par *par)
 332{
 333        char vramsz = iga_inb(par, IGA_EXT_CNTRL, IGA_IDX_EXT_BUS_CNTL) 
 334                                                         & MEM_SIZE_ALIAS;
 335        int video_cmap_len;
 336
 337        switch (vramsz) {
 338        case MEM_SIZE_1M:
 339                info->fix.smem_len = 0x100000;
 340                break;
 341        case MEM_SIZE_2M:
 342                info->fix.smem_len = 0x200000;
 343                break;
 344        case MEM_SIZE_4M:
 345        case MEM_SIZE_RESERVED:
 346                info->fix.smem_len = 0x400000;
 347                break;
 348        }
 349
 350        if (info->var.bits_per_pixel > 8) 
 351                video_cmap_len = 16;
 352        else 
 353                video_cmap_len = 256;
 354
 355        info->fbops = &igafb_ops;
 356        info->flags = FBINFO_DEFAULT;
 357
 358        fb_alloc_cmap(&info->cmap, video_cmap_len, 0);
 359
 360        if (register_framebuffer(info) < 0)
 361                return 0;
 362
 363        fb_info(info, "%s frame buffer device at 0x%08lx [%dMB VRAM]\n",
 364                info->fix.id, par->frame_buffer_phys, info->fix.smem_len >> 20);
 365
 366        iga_blank_border(par); 
 367        return 1;
 368}
 369
 370static int __init igafb_init(void)
 371{
 372        struct fb_info *info;
 373        struct pci_dev *pdev;
 374        struct iga_par *par;
 375        unsigned long addr;
 376        int size, iga2000 = 0;
 377
 378        if (fb_get_options("igafb", NULL))
 379                return -ENODEV;
 380
 381        pdev = pci_get_device(PCI_VENDOR_ID_INTERG,
 382                               PCI_DEVICE_ID_INTERG_1682, 0);
 383        if (pdev == NULL) {
 384                /*
 385                 * XXX We tried to use cyber2000fb.c for IGS 2000.
 386                 * But it does not initialize the chip in JavaStation-E, alas.
 387                 */
 388                pdev = pci_get_device(PCI_VENDOR_ID_INTERG, 0x2000, 0);
 389                if(pdev == NULL) {
 390                        return -ENXIO;
 391                }
 392                iga2000 = 1;
 393        }
 394        /* We leak a reference here but as it cannot be unloaded this is
 395           fine. If you write unload code remember to free it in unload */
 396        
 397        size = sizeof(struct iga_par) + sizeof(u32)*16;
 398
 399        info = framebuffer_alloc(size, &pdev->dev);
 400        if (!info) {
 401                printk("igafb_init: can't alloc fb_info\n");
 402                 pci_dev_put(pdev);
 403                return -ENOMEM;
 404        }
 405
 406        par = info->par;
 407
 408        if ((addr = pdev->resource[0].start) == 0) {
 409                printk("igafb_init: no memory start\n");
 410                kfree(info);
 411                pci_dev_put(pdev);
 412                return -ENXIO;
 413        }
 414
 415        if ((info->screen_base = ioremap(addr, 1024*1024*2)) == 0) {
 416                printk("igafb_init: can't remap %lx[2M]\n", addr);
 417                kfree(info);
 418                pci_dev_put(pdev);
 419                return -ENXIO;
 420        }
 421
 422        par->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK;
 423
 424#ifdef CONFIG_SPARC
 425        /*
 426         * The following is sparc specific and this is why:
 427         *
 428         * IGS2000 has its I/O memory mapped and we want
 429         * to generate memory cycles on PCI, e.g. do ioremap(),
 430         * then readb/writeb() as in Documentation/io-mapping.txt.
 431         *
 432         * IGS1682 is more traditional, it responds to PCI I/O
 433         * cycles, so we want to access it with inb()/outb().
 434         *
 435         * On sparc, PCIC converts CPU memory access within
 436         * phys window 0x3000xxxx into PCI I/O cycles. Therefore
 437         * we may use readb/writeb to access them with IGS1682.
 438         *
 439         * We do not take io_base_phys from resource[n].start
 440         * on IGS1682 because that chip is BROKEN. It does not
 441         * have a base register for I/O. We just "know" what its
 442         * I/O addresses are.
 443         */
 444        if (iga2000) {
 445                igafb_fix.mmio_start = par->frame_buffer_phys | 0x00800000;
 446        } else {
 447                igafb_fix.mmio_start = 0x30000000;      /* XXX */
 448        }
 449        if ((par->io_base = (int) ioremap(igafb_fix.mmio_start, igafb_fix.smem_len)) == 0) {
 450                printk("igafb_init: can't remap %lx[4K]\n", igafb_fix.mmio_start);
 451                iounmap((void *)info->screen_base);
 452                kfree(info);
 453                pci_dev_put(pdev);
 454                return -ENXIO;
 455        }
 456
 457        /*
 458         * Figure mmap addresses from PCI config space.
 459         * We need two regions: for video memory and for I/O ports.
 460         * Later one can add region for video coprocessor registers.
 461         * However, mmap routine loops until size != 0, so we put
 462         * one additional region with size == 0. 
 463         */
 464
 465        par->mmap_map = kzalloc(4 * sizeof(*par->mmap_map), GFP_ATOMIC);
 466        if (!par->mmap_map) {
 467                printk("igafb_init: can't alloc mmap_map\n");
 468                iounmap((void *)par->io_base);
 469                iounmap(info->screen_base);
 470                kfree(info);
 471                pci_dev_put(pdev);
 472                return -ENOMEM;
 473        }
 474
 475        /*
 476         * Set default vmode and cmode from PROM properties.
 477         */
 478        {
 479                struct device_node *dp = pci_device_to_OF_node(pdev);
 480                int node = dp->node;
 481                int width = prom_getintdefault(node, "width", 1024);
 482                int height = prom_getintdefault(node, "height", 768);
 483                int depth = prom_getintdefault(node, "depth", 8);
 484                switch (width) {
 485                    case 1024:
 486                        if (height == 768)
 487                            default_var = default_var_1024x768;
 488                        break;
 489                    case 1152:
 490                        if (height == 900)
 491                            default_var = default_var_1152x900;
 492                        break;
 493                    case 1280:
 494                        if (height == 1024)
 495                            default_var = default_var_1280x1024;
 496                        break;
 497                    default:
 498                        break;
 499                }
 500
 501                switch (depth) {
 502                    case 8:
 503                        default_var.bits_per_pixel = 8;
 504                        break;
 505                    case 16:
 506                        default_var.bits_per_pixel = 16;
 507                        break;
 508                    case 24:
 509                        default_var.bits_per_pixel = 24;
 510                        break;
 511                    case 32:
 512                        default_var.bits_per_pixel = 32;
 513                        break;
 514                    default:
 515                        break;
 516                }
 517            }
 518
 519#endif
 520        igafb_fix.smem_start = (unsigned long) info->screen_base;
 521        igafb_fix.line_length = default_var.xres*(default_var.bits_per_pixel/8);
 522        igafb_fix.visual = default_var.bits_per_pixel <= 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
 523
 524        info->var = default_var;
 525        info->fix = igafb_fix;
 526        info->pseudo_palette = (void *)(par + 1);
 527
 528        if (!iga_init(info, par)) {
 529                iounmap((void *)par->io_base);
 530                iounmap(info->screen_base);
 531                kfree(par->mmap_map);
 532                kfree(info);
 533                return -ENODEV;
 534        }
 535
 536#ifdef CONFIG_SPARC
 537            /*
 538             * Add /dev/fb mmap values.
 539             */
 540            
 541            /* First region is for video memory */
 542            par->mmap_map[0].voff = 0x0;  
 543            par->mmap_map[0].poff = par->frame_buffer_phys & PAGE_MASK;
 544            par->mmap_map[0].size = info->fix.smem_len & PAGE_MASK;
 545            par->mmap_map[0].prot_mask = SRMMU_CACHE;
 546            par->mmap_map[0].prot_flag = SRMMU_WRITE;
 547
 548            /* Second region is for I/O ports */
 549            par->mmap_map[1].voff = par->frame_buffer_phys & PAGE_MASK;
 550            par->mmap_map[1].poff = info->fix.smem_start & PAGE_MASK;
 551            par->mmap_map[1].size = PAGE_SIZE * 2; /* X wants 2 pages */
 552            par->mmap_map[1].prot_mask = SRMMU_CACHE;
 553            par->mmap_map[1].prot_flag = SRMMU_WRITE;
 554#endif /* CONFIG_SPARC */
 555
 556        return 0;
 557}
 558
 559static int __init igafb_setup(char *options)
 560{
 561    char *this_opt;
 562
 563    if (!options || !*options)
 564        return 0;
 565
 566    while ((this_opt = strsep(&options, ",")) != NULL) {
 567    }
 568    return 0;
 569}
 570
 571module_init(igafb_init);
 572MODULE_LICENSE("GPL");
 573static struct pci_device_id igafb_pci_tbl[] = {
 574        { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682,
 575          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 576        { }
 577};
 578
 579MODULE_DEVICE_TABLE(pci, igafb_pci_tbl);
 580