linux/drivers/video/gbefb.c
<<
>>
Prefs
   1/*
   2 *  SGI GBE frame buffer driver
   3 *
   4 *  Copyright (C) 1999 Silicon Graphics, Inc. - Jeffrey Newquist
   5 *  Copyright (C) 2002 Vivien Chappelier <vivien.chappelier@linux-mips.org>
   6 *
   7 *  This file is subject to the terms and conditions of the GNU General Public
   8 *  License. See the file COPYING in the main directory of this archive for
   9 *  more details.
  10 */
  11
  12#include <linux/delay.h>
  13#include <linux/platform_device.h>
  14#include <linux/dma-mapping.h>
  15#include <linux/errno.h>
  16#include <linux/gfp.h>
  17#include <linux/fb.h>
  18#include <linux/init.h>
  19#include <linux/interrupt.h>
  20#include <linux/kernel.h>
  21#include <linux/mm.h>
  22#include <linux/module.h>
  23
  24#ifdef CONFIG_X86
  25#include <asm/mtrr.h>
  26#endif
  27#ifdef CONFIG_MIPS
  28#include <asm/addrspace.h>
  29#endif
  30#include <asm/byteorder.h>
  31#include <asm/io.h>
  32#include <asm/tlbflush.h>
  33
  34#include <video/gbe.h>
  35
  36static struct sgi_gbe *gbe;
  37
  38struct gbefb_par {
  39        struct fb_var_screeninfo var;
  40        struct gbe_timing_info timing;
  41        int valid;
  42};
  43
  44#ifdef CONFIG_SGI_IP32
  45#define GBE_BASE        0x16000000 /* SGI O2 */
  46#endif
  47
  48#ifdef CONFIG_X86_VISWS
  49#define GBE_BASE        0xd0000000 /* SGI Visual Workstation */
  50#endif
  51
  52/* macro for fastest write-though access to the framebuffer */
  53#ifdef CONFIG_MIPS
  54#ifdef CONFIG_CPU_R10000
  55#define pgprot_fb(_prot) (((_prot) & (~_CACHE_MASK)) | _CACHE_UNCACHED_ACCELERATED)
  56#else
  57#define pgprot_fb(_prot) (((_prot) & (~_CACHE_MASK)) | _CACHE_CACHABLE_NO_WA)
  58#endif
  59#endif
  60#ifdef CONFIG_X86
  61#define pgprot_fb(_prot) ((_prot) | _PAGE_PCD)
  62#endif
  63
  64/*
  65 *  RAM we reserve for the frame buffer. This defines the maximum screen
  66 *  size
  67 */
  68#if CONFIG_FB_GBE_MEM > 8
  69#error GBE Framebuffer cannot use more than 8MB of memory
  70#endif
  71
  72#define TILE_SHIFT 16
  73#define TILE_SIZE (1 << TILE_SHIFT)
  74#define TILE_MASK (TILE_SIZE - 1)
  75
  76static unsigned int gbe_mem_size = CONFIG_FB_GBE_MEM * 1024*1024;
  77static void *gbe_mem;
  78static dma_addr_t gbe_dma_addr;
  79static unsigned long gbe_mem_phys;
  80
  81static struct {
  82        uint16_t *cpu;
  83        dma_addr_t dma;
  84} gbe_tiles;
  85
  86static int gbe_revision;
  87
  88static int ypan, ywrap;
  89
  90static uint32_t pseudo_palette[16];
  91static uint32_t gbe_cmap[256];
  92static int gbe_turned_on; /* 0 turned off, 1 turned on */
  93
  94static char *mode_option __devinitdata = NULL;
  95
  96/* default CRT mode */
  97static struct fb_var_screeninfo default_var_CRT __devinitdata = {
  98        /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
  99        .xres           = 640,
 100        .yres           = 480,
 101        .xres_virtual   = 640,
 102        .yres_virtual   = 480,
 103        .xoffset        = 0,
 104        .yoffset        = 0,
 105        .bits_per_pixel = 8,
 106        .grayscale      = 0,
 107        .red            = { 0, 8, 0 },
 108        .green          = { 0, 8, 0 },
 109        .blue           = { 0, 8, 0 },
 110        .transp         = { 0, 0, 0 },
 111        .nonstd         = 0,
 112        .activate       = 0,
 113        .height         = -1,
 114        .width          = -1,
 115        .accel_flags    = 0,
 116        .pixclock       = 39722,        /* picoseconds */
 117        .left_margin    = 48,
 118        .right_margin   = 16,
 119        .upper_margin   = 33,
 120        .lower_margin   = 10,
 121        .hsync_len      = 96,
 122        .vsync_len      = 2,
 123        .sync           = 0,
 124        .vmode          = FB_VMODE_NONINTERLACED,
 125};
 126
 127/* default LCD mode */
 128static struct fb_var_screeninfo default_var_LCD __devinitdata = {
 129        /* 1600x1024, 8 bpp */
 130        .xres           = 1600,
 131        .yres           = 1024,
 132        .xres_virtual   = 1600,
 133        .yres_virtual   = 1024,
 134        .xoffset        = 0,
 135        .yoffset        = 0,
 136        .bits_per_pixel = 8,
 137        .grayscale      = 0,
 138        .red            = { 0, 8, 0 },
 139        .green          = { 0, 8, 0 },
 140        .blue           = { 0, 8, 0 },
 141        .transp         = { 0, 0, 0 },
 142        .nonstd         = 0,
 143        .activate       = 0,
 144        .height         = -1,
 145        .width          = -1,
 146        .accel_flags    = 0,
 147        .pixclock       = 9353,
 148        .left_margin    = 20,
 149        .right_margin   = 30,
 150        .upper_margin   = 37,
 151        .lower_margin   = 3,
 152        .hsync_len      = 20,
 153        .vsync_len      = 3,
 154        .sync           = 0,
 155        .vmode          = FB_VMODE_NONINTERLACED
 156};
 157
 158/* default modedb mode */
 159/* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
 160static struct fb_videomode default_mode_CRT __devinitdata = {
 161        .refresh        = 60,
 162        .xres           = 640,
 163        .yres           = 480,
 164        .pixclock       = 39722,
 165        .left_margin    = 48,
 166        .right_margin   = 16,
 167        .upper_margin   = 33,
 168        .lower_margin   = 10,
 169        .hsync_len      = 96,
 170        .vsync_len      = 2,
 171        .sync           = 0,
 172        .vmode          = FB_VMODE_NONINTERLACED,
 173};
 174/* 1600x1024 SGI flatpanel 1600sw */
 175static struct fb_videomode default_mode_LCD __devinitdata = {
 176        /* 1600x1024, 8 bpp */
 177        .xres           = 1600,
 178        .yres           = 1024,
 179        .pixclock       = 9353,
 180        .left_margin    = 20,
 181        .right_margin   = 30,
 182        .upper_margin   = 37,
 183        .lower_margin   = 3,
 184        .hsync_len      = 20,
 185        .vsync_len      = 3,
 186        .vmode          = FB_VMODE_NONINTERLACED,
 187};
 188
 189static struct fb_videomode *default_mode __devinitdata = &default_mode_CRT;
 190static struct fb_var_screeninfo *default_var __devinitdata = &default_var_CRT;
 191
 192static int flat_panel_enabled = 0;
 193
 194static void gbe_reset(void)
 195{
 196        /* Turn on dotclock PLL */
 197        gbe->ctrlstat = 0x300aa000;
 198}
 199
 200
 201/*
 202 * Function:    gbe_turn_off
 203 * Parameters:  (None)
 204 * Description: This should turn off the monitor and gbe.  This is used
 205 *              when switching between the serial console and the graphics
 206 *              console.
 207 */
 208
 209static void gbe_turn_off(void)
 210{
 211        int i;
 212        unsigned int val, x, y, vpixen_off;
 213
 214        gbe_turned_on = 0;
 215
 216        /* check if pixel counter is on */
 217        val = gbe->vt_xy;
 218        if (GET_GBE_FIELD(VT_XY, FREEZE, val) == 1)
 219                return;
 220
 221        /* turn off DMA */
 222        val = gbe->ovr_control;
 223        SET_GBE_FIELD(OVR_CONTROL, OVR_DMA_ENABLE, val, 0);
 224        gbe->ovr_control = val;
 225        udelay(1000);
 226        val = gbe->frm_control;
 227        SET_GBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, val, 0);
 228        gbe->frm_control = val;
 229        udelay(1000);
 230        val = gbe->did_control;
 231        SET_GBE_FIELD(DID_CONTROL, DID_DMA_ENABLE, val, 0);
 232        gbe->did_control = val;
 233        udelay(1000);
 234
 235        /* We have to wait through two vertical retrace periods before
 236         * the pixel DMA is turned off for sure. */
 237        for (i = 0; i < 10000; i++) {
 238                val = gbe->frm_inhwctrl;
 239                if (GET_GBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, val)) {
 240                        udelay(10);
 241                } else {
 242                        val = gbe->ovr_inhwctrl;
 243                        if (GET_GBE_FIELD(OVR_INHWCTRL, OVR_DMA_ENABLE, val)) {
 244                                udelay(10);
 245                        } else {
 246                                val = gbe->did_inhwctrl;
 247                                if (GET_GBE_FIELD(DID_INHWCTRL, DID_DMA_ENABLE, val)) {
 248                                        udelay(10);
 249                                } else
 250                                        break;
 251                        }
 252                }
 253        }
 254        if (i == 10000)
 255                printk(KERN_ERR "gbefb: turn off DMA timed out\n");
 256
 257        /* wait for vpixen_off */
 258        val = gbe->vt_vpixen;
 259        vpixen_off = GET_GBE_FIELD(VT_VPIXEN, VPIXEN_OFF, val);
 260
 261        for (i = 0; i < 100000; i++) {
 262                val = gbe->vt_xy;
 263                x = GET_GBE_FIELD(VT_XY, X, val);
 264                y = GET_GBE_FIELD(VT_XY, Y, val);
 265                if (y < vpixen_off)
 266                        break;
 267                udelay(1);
 268        }
 269        if (i == 100000)
 270                printk(KERN_ERR
 271                       "gbefb: wait for vpixen_off timed out\n");
 272        for (i = 0; i < 10000; i++) {
 273                val = gbe->vt_xy;
 274                x = GET_GBE_FIELD(VT_XY, X, val);
 275                y = GET_GBE_FIELD(VT_XY, Y, val);
 276                if (y > vpixen_off)
 277                        break;
 278                udelay(1);
 279        }
 280        if (i == 10000)
 281                printk(KERN_ERR "gbefb: wait for vpixen_off timed out\n");
 282
 283        /* turn off pixel counter */
 284        val = 0;
 285        SET_GBE_FIELD(VT_XY, FREEZE, val, 1);
 286        gbe->vt_xy = val;
 287        udelay(10000);
 288        for (i = 0; i < 10000; i++) {
 289                val = gbe->vt_xy;
 290                if (GET_GBE_FIELD(VT_XY, FREEZE, val) != 1)
 291                        udelay(10);
 292                else
 293                        break;
 294        }
 295        if (i == 10000)
 296                printk(KERN_ERR "gbefb: turn off pixel clock timed out\n");
 297
 298        /* turn off dot clock */
 299        val = gbe->dotclock;
 300        SET_GBE_FIELD(DOTCLK, RUN, val, 0);
 301        gbe->dotclock = val;
 302        udelay(10000);
 303        for (i = 0; i < 10000; i++) {
 304                val = gbe->dotclock;
 305                if (GET_GBE_FIELD(DOTCLK, RUN, val))
 306                        udelay(10);
 307                else
 308                        break;
 309        }
 310        if (i == 10000)
 311                printk(KERN_ERR "gbefb: turn off dotclock timed out\n");
 312
 313        /* reset the frame DMA FIFO */
 314        val = gbe->frm_size_tile;
 315        SET_GBE_FIELD(FRM_SIZE_TILE, FRM_FIFO_RESET, val, 1);
 316        gbe->frm_size_tile = val;
 317        SET_GBE_FIELD(FRM_SIZE_TILE, FRM_FIFO_RESET, val, 0);
 318        gbe->frm_size_tile = val;
 319}
 320
 321static void gbe_turn_on(void)
 322{
 323        unsigned int val, i;
 324
 325        /*
 326         * Check if pixel counter is off, for unknown reason this
 327         * code hangs Visual Workstations
 328         */
 329        if (gbe_revision < 2) {
 330                val = gbe->vt_xy;
 331                if (GET_GBE_FIELD(VT_XY, FREEZE, val) == 0)
 332                        return;
 333        }
 334
 335        /* turn on dot clock */
 336        val = gbe->dotclock;
 337        SET_GBE_FIELD(DOTCLK, RUN, val, 1);
 338        gbe->dotclock = val;
 339        udelay(10000);
 340        for (i = 0; i < 10000; i++) {
 341                val = gbe->dotclock;
 342                if (GET_GBE_FIELD(DOTCLK, RUN, val) != 1)
 343                        udelay(10);
 344                else
 345                        break;
 346        }
 347        if (i == 10000)
 348                printk(KERN_ERR "gbefb: turn on dotclock timed out\n");
 349
 350        /* turn on pixel counter */
 351        val = 0;
 352        SET_GBE_FIELD(VT_XY, FREEZE, val, 0);
 353        gbe->vt_xy = val;
 354        udelay(10000);
 355        for (i = 0; i < 10000; i++) {
 356                val = gbe->vt_xy;
 357                if (GET_GBE_FIELD(VT_XY, FREEZE, val))
 358                        udelay(10);
 359                else
 360                        break;
 361        }
 362        if (i == 10000)
 363                printk(KERN_ERR "gbefb: turn on pixel clock timed out\n");
 364
 365        /* turn on DMA */
 366        val = gbe->frm_control;
 367        SET_GBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, val, 1);
 368        gbe->frm_control = val;
 369        udelay(1000);
 370        for (i = 0; i < 10000; i++) {
 371                val = gbe->frm_inhwctrl;
 372                if (GET_GBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, val) != 1)
 373                        udelay(10);
 374                else
 375                        break;
 376        }
 377        if (i == 10000)
 378                printk(KERN_ERR "gbefb: turn on DMA timed out\n");
 379
 380        gbe_turned_on = 1;
 381}
 382
 383static void gbe_loadcmap(void)
 384{
 385        int i, j;
 386
 387        for (i = 0; i < 256; i++) {
 388                for (j = 0; j < 1000 && gbe->cm_fifo >= 63; j++)
 389                        udelay(10);
 390                if (j == 1000)
 391                        printk(KERN_ERR "gbefb: cmap FIFO timeout\n");
 392
 393                gbe->cmap[i] = gbe_cmap[i];
 394        }
 395}
 396
 397/*
 398 *  Blank the display.
 399 */
 400static int gbefb_blank(int blank, struct fb_info *info)
 401{
 402        /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
 403        switch (blank) {
 404        case FB_BLANK_UNBLANK:          /* unblank */
 405                gbe_turn_on();
 406                gbe_loadcmap();
 407                break;
 408
 409        case FB_BLANK_NORMAL:           /* blank */
 410                gbe_turn_off();
 411                break;
 412
 413        default:
 414                /* Nothing */
 415                break;
 416        }
 417        return 0;
 418}
 419
 420/*
 421 *  Setup flatpanel related registers.
 422 */
 423static void gbefb_setup_flatpanel(struct gbe_timing_info *timing)
 424{
 425        int fp_wid, fp_hgt, fp_vbs, fp_vbe;
 426        u32 outputVal = 0;
 427
 428        SET_GBE_FIELD(VT_FLAGS, HDRV_INVERT, outputVal,
 429                (timing->flags & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1);
 430        SET_GBE_FIELD(VT_FLAGS, VDRV_INVERT, outputVal,
 431                (timing->flags & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1);
 432        gbe->vt_flags = outputVal;
 433
 434        /* Turn on the flat panel */
 435        fp_wid = 1600;
 436        fp_hgt = 1024;
 437        fp_vbs = 0;
 438        fp_vbe = 1600;
 439        timing->pll_m = 4;
 440        timing->pll_n = 1;
 441        timing->pll_p = 0;
 442
 443        outputVal = 0;
 444        SET_GBE_FIELD(FP_DE, ON, outputVal, fp_vbs);
 445        SET_GBE_FIELD(FP_DE, OFF, outputVal, fp_vbe);
 446        gbe->fp_de = outputVal;
 447        outputVal = 0;
 448        SET_GBE_FIELD(FP_HDRV, OFF, outputVal, fp_wid);
 449        gbe->fp_hdrv = outputVal;
 450        outputVal = 0;
 451        SET_GBE_FIELD(FP_VDRV, ON, outputVal, 1);
 452        SET_GBE_FIELD(FP_VDRV, OFF, outputVal, fp_hgt + 1);
 453        gbe->fp_vdrv = outputVal;
 454}
 455
 456struct gbe_pll_info {
 457        int clock_rate;
 458        int fvco_min;
 459        int fvco_max;
 460};
 461
 462static struct gbe_pll_info gbe_pll_table[2] = {
 463        { 20, 80, 220 },
 464        { 27, 80, 220 },
 465};
 466
 467static int compute_gbe_timing(struct fb_var_screeninfo *var,
 468                              struct gbe_timing_info *timing)
 469{
 470        int pll_m, pll_n, pll_p, error, best_m, best_n, best_p, best_error;
 471        int pixclock;
 472        struct gbe_pll_info *gbe_pll;
 473
 474        if (gbe_revision < 2)
 475                gbe_pll = &gbe_pll_table[0];
 476        else
 477                gbe_pll = &gbe_pll_table[1];
 478
 479        /* Determine valid resolution and timing
 480         * GBE crystal runs at 20Mhz or 27Mhz
 481         * pll_m, pll_n, pll_p define the following frequencies
 482         * fvco = pll_m * 20Mhz / pll_n
 483         * fout = fvco / (2**pll_p) */
 484        best_error = 1000000000;
 485        best_n = best_m = best_p = 0;
 486        for (pll_p = 0; pll_p < 4; pll_p++)
 487                for (pll_m = 1; pll_m < 256; pll_m++)
 488                        for (pll_n = 1; pll_n < 64; pll_n++) {
 489                                pixclock = (1000000 / gbe_pll->clock_rate) *
 490                                                (pll_n << pll_p) / pll_m;
 491
 492                                error = var->pixclock - pixclock;
 493
 494                                if (error < 0)
 495                                        error = -error;
 496
 497                                if (error < best_error &&
 498                                    pll_m / pll_n >
 499                                    gbe_pll->fvco_min / gbe_pll->clock_rate &&
 500                                    pll_m / pll_n <
 501                                    gbe_pll->fvco_max / gbe_pll->clock_rate) {
 502                                        best_error = error;
 503                                        best_m = pll_m;
 504                                        best_n = pll_n;
 505                                        best_p = pll_p;
 506                                }
 507                        }
 508
 509        if (!best_n || !best_m)
 510                return -EINVAL; /* Resolution to high */
 511
 512        pixclock = (1000000 / gbe_pll->clock_rate) *
 513                (best_n << best_p) / best_m;
 514
 515        /* set video timing information */
 516        if (timing) {
 517                timing->width = var->xres;
 518                timing->height = var->yres;
 519                timing->pll_m = best_m;
 520                timing->pll_n = best_n;
 521                timing->pll_p = best_p;
 522                timing->cfreq = gbe_pll->clock_rate * 1000 * timing->pll_m /
 523                        (timing->pll_n << timing->pll_p);
 524                timing->htotal = var->left_margin + var->xres +
 525                                var->right_margin + var->hsync_len;
 526                timing->vtotal = var->upper_margin + var->yres +
 527                                var->lower_margin + var->vsync_len;
 528                timing->fields_sec = 1000 * timing->cfreq / timing->htotal *
 529                                1000 / timing->vtotal;
 530                timing->hblank_start = var->xres;
 531                timing->vblank_start = var->yres;
 532                timing->hblank_end = timing->htotal;
 533                timing->hsync_start = var->xres + var->right_margin + 1;
 534                timing->hsync_end = timing->hsync_start + var->hsync_len;
 535                timing->vblank_end = timing->vtotal;
 536                timing->vsync_start = var->yres + var->lower_margin + 1;
 537                timing->vsync_end = timing->vsync_start + var->vsync_len;
 538        }
 539
 540        return pixclock;
 541}
 542
 543static void gbe_set_timing_info(struct gbe_timing_info *timing)
 544{
 545        int temp;
 546        unsigned int val;
 547
 548        /* setup dot clock PLL */
 549        val = 0;
 550        SET_GBE_FIELD(DOTCLK, M, val, timing->pll_m - 1);
 551        SET_GBE_FIELD(DOTCLK, N, val, timing->pll_n - 1);
 552        SET_GBE_FIELD(DOTCLK, P, val, timing->pll_p);
 553        SET_GBE_FIELD(DOTCLK, RUN, val, 0);     /* do not start yet */
 554        gbe->dotclock = val;
 555        udelay(10000);
 556
 557        /* setup pixel counter */
 558        val = 0;
 559        SET_GBE_FIELD(VT_XYMAX, MAXX, val, timing->htotal);
 560        SET_GBE_FIELD(VT_XYMAX, MAXY, val, timing->vtotal);
 561        gbe->vt_xymax = val;
 562
 563        /* setup video timing signals */
 564        val = 0;
 565        SET_GBE_FIELD(VT_VSYNC, VSYNC_ON, val, timing->vsync_start);
 566        SET_GBE_FIELD(VT_VSYNC, VSYNC_OFF, val, timing->vsync_end);
 567        gbe->vt_vsync = val;
 568        val = 0;
 569        SET_GBE_FIELD(VT_HSYNC, HSYNC_ON, val, timing->hsync_start);
 570        SET_GBE_FIELD(VT_HSYNC, HSYNC_OFF, val, timing->hsync_end);
 571        gbe->vt_hsync = val;
 572        val = 0;
 573        SET_GBE_FIELD(VT_VBLANK, VBLANK_ON, val, timing->vblank_start);
 574        SET_GBE_FIELD(VT_VBLANK, VBLANK_OFF, val, timing->vblank_end);
 575        gbe->vt_vblank = val;
 576        val = 0;
 577        SET_GBE_FIELD(VT_HBLANK, HBLANK_ON, val,
 578                      timing->hblank_start - 5);
 579        SET_GBE_FIELD(VT_HBLANK, HBLANK_OFF, val,
 580                      timing->hblank_end - 3);
 581        gbe->vt_hblank = val;
 582
 583        /* setup internal timing signals */
 584        val = 0;
 585        SET_GBE_FIELD(VT_VCMAP, VCMAP_ON, val, timing->vblank_start);
 586        SET_GBE_FIELD(VT_VCMAP, VCMAP_OFF, val, timing->vblank_end);
 587        gbe->vt_vcmap = val;
 588        val = 0;
 589        SET_GBE_FIELD(VT_HCMAP, HCMAP_ON, val, timing->hblank_start);
 590        SET_GBE_FIELD(VT_HCMAP, HCMAP_OFF, val, timing->hblank_end);
 591        gbe->vt_hcmap = val;
 592
 593        val = 0;
 594        temp = timing->vblank_start - timing->vblank_end - 1;
 595        if (temp > 0)
 596                temp = -temp;
 597
 598        if (flat_panel_enabled)
 599                gbefb_setup_flatpanel(timing);
 600
 601        SET_GBE_FIELD(DID_START_XY, DID_STARTY, val, (u32) temp);
 602        if (timing->hblank_end >= 20)
 603                SET_GBE_FIELD(DID_START_XY, DID_STARTX, val,
 604                              timing->hblank_end - 20);
 605        else
 606                SET_GBE_FIELD(DID_START_XY, DID_STARTX, val,
 607                              timing->htotal - (20 - timing->hblank_end));
 608        gbe->did_start_xy = val;
 609
 610        val = 0;
 611        SET_GBE_FIELD(CRS_START_XY, CRS_STARTY, val, (u32) (temp + 1));
 612        if (timing->hblank_end >= GBE_CRS_MAGIC)
 613                SET_GBE_FIELD(CRS_START_XY, CRS_STARTX, val,
 614                              timing->hblank_end - GBE_CRS_MAGIC);
 615        else
 616                SET_GBE_FIELD(CRS_START_XY, CRS_STARTX, val,
 617                              timing->htotal - (GBE_CRS_MAGIC -
 618                                                timing->hblank_end));
 619        gbe->crs_start_xy = val;
 620
 621        val = 0;
 622        SET_GBE_FIELD(VC_START_XY, VC_STARTY, val, (u32) temp);
 623        SET_GBE_FIELD(VC_START_XY, VC_STARTX, val, timing->hblank_end - 4);
 624        gbe->vc_start_xy = val;
 625
 626        val = 0;
 627        temp = timing->hblank_end - GBE_PIXEN_MAGIC_ON;
 628        if (temp < 0)
 629                temp += timing->htotal; /* allow blank to wrap around */
 630
 631        SET_GBE_FIELD(VT_HPIXEN, HPIXEN_ON, val, temp);
 632        SET_GBE_FIELD(VT_HPIXEN, HPIXEN_OFF, val,
 633                      ((temp + timing->width -
 634                        GBE_PIXEN_MAGIC_OFF) % timing->htotal));
 635        gbe->vt_hpixen = val;
 636
 637        val = 0;
 638        SET_GBE_FIELD(VT_VPIXEN, VPIXEN_ON, val, timing->vblank_end);
 639        SET_GBE_FIELD(VT_VPIXEN, VPIXEN_OFF, val, timing->vblank_start);
 640        gbe->vt_vpixen = val;
 641
 642        /* turn off sync on green */
 643        val = 0;
 644        SET_GBE_FIELD(VT_FLAGS, SYNC_LOW, val, 1);
 645        gbe->vt_flags = val;
 646}
 647
 648/*
 649 *  Set the hardware according to 'par'.
 650 */
 651
 652static int gbefb_set_par(struct fb_info *info)
 653{
 654        int i;
 655        unsigned int val;
 656        int wholeTilesX, partTilesX, maxPixelsPerTileX;
 657        int height_pix;
 658        int xpmax, ypmax;       /* Monitor resolution */
 659        int bytesPerPixel;      /* Bytes per pixel */
 660        struct gbefb_par *par = (struct gbefb_par *) info->par;
 661
 662        compute_gbe_timing(&info->var, &par->timing);
 663
 664        bytesPerPixel = info->var.bits_per_pixel / 8;
 665        info->fix.line_length = info->var.xres_virtual * bytesPerPixel;
 666        xpmax = par->timing.width;
 667        ypmax = par->timing.height;
 668
 669        /* turn off GBE */
 670        gbe_turn_off();
 671
 672        /* set timing info */
 673        gbe_set_timing_info(&par->timing);
 674
 675        /* initialize DIDs */
 676        val = 0;
 677        switch (bytesPerPixel) {
 678        case 1:
 679                SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_I8);
 680                info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
 681                break;
 682        case 2:
 683                SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_ARGB5);
 684                info->fix.visual = FB_VISUAL_TRUECOLOR;
 685                break;
 686        case 4:
 687                SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_RGB8);
 688                info->fix.visual = FB_VISUAL_TRUECOLOR;
 689                break;
 690        }
 691        SET_GBE_FIELD(WID, BUF, val, GBE_BMODE_BOTH);
 692
 693        for (i = 0; i < 32; i++)
 694                gbe->mode_regs[i] = val;
 695
 696        /* Initialize interrupts */
 697        gbe->vt_intr01 = 0xffffffff;
 698        gbe->vt_intr23 = 0xffffffff;
 699
 700        /* HACK:
 701           The GBE hardware uses a tiled memory to screen mapping. Tiles are
 702           blocks of 512x128, 256x128 or 128x128 pixels, respectively for 8bit,
 703           16bit and 32 bit modes (64 kB). They cover the screen with partial
 704           tiles on the right and/or bottom of the screen if needed.
 705           For example in 640x480 8 bit mode the mapping is:
 706
 707           <-------- 640 ----->
 708           <---- 512 ----><128|384 offscreen>
 709           ^  ^
 710           | 128    [tile 0]        [tile 1]
 711           |  v
 712           ^
 713           4 128    [tile 2]        [tile 3]
 714           8  v
 715           0  ^
 716           128    [tile 4]        [tile 5]
 717           |  v
 718           |  ^
 719           v  96    [tile 6]        [tile 7]
 720           32 offscreen
 721
 722           Tiles have the advantage that they can be allocated individually in
 723           memory. However, this mapping is not linear at all, which is not
 724           really convenient. In order to support linear addressing, the GBE
 725           DMA hardware is fooled into thinking the screen is only one tile
 726           large and but has a greater height, so that the DMA transfer covers
 727           the same region.
 728           Tiles are still allocated as independent chunks of 64KB of
 729           continuous physical memory and remapped so that the kernel sees the
 730           framebuffer as a continuous virtual memory. The GBE tile table is
 731           set up so that each tile references one of these 64k blocks:
 732
 733           GBE -> tile list    framebuffer           TLB   <------------ CPU
 734                  [ tile 0 ] -> [ 64KB ]  <- [ 16x 4KB page entries ]     ^
 735                     ...           ...              ...       linear virtual FB
 736                  [ tile n ] -> [ 64KB ]  <- [ 16x 4KB page entries ]     v
 737
 738
 739           The GBE hardware is then told that the buffer is 512*tweaked_height,
 740           with tweaked_height = real_width*real_height/pixels_per_tile.
 741           Thus the GBE hardware will scan the first tile, filing the first 64k
 742           covered region of the screen, and then will proceed to the next
 743           tile, until the whole screen is covered.
 744
 745           Here is what would happen at 640x480 8bit:
 746
 747           normal tiling               linear
 748           ^   11111111111111112222    11111111111111111111  ^
 749           128 11111111111111112222    11111111111111111111 102 lines
 750               11111111111111112222    11111111111111111111  v
 751           V   11111111111111112222    11111111222222222222
 752               33333333333333334444    22222222222222222222
 753               33333333333333334444    22222222222222222222
 754               <      512     >        <  256 >               102*640+256 = 64k
 755
 756           NOTE: The only mode for which this is not working is 800x600 8bit,
 757           as 800*600/512 = 937.5 which is not integer and thus causes
 758           flickering.
 759           I guess this is not so important as one can use 640x480 8bit or
 760           800x600 16bit anyway.
 761         */
 762
 763        /* Tell gbe about the tiles table location */
 764        /* tile_ptr -> [ tile 1 ] -> FB mem */
 765        /*             [ tile 2 ] -> FB mem */
 766        /*               ...                */
 767        val = 0;
 768        SET_GBE_FIELD(FRM_CONTROL, FRM_TILE_PTR, val, gbe_tiles.dma >> 9);
 769        SET_GBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, val, 0); /* do not start */
 770        SET_GBE_FIELD(FRM_CONTROL, FRM_LINEAR, val, 0);
 771        gbe->frm_control = val;
 772
 773        maxPixelsPerTileX = 512 / bytesPerPixel;
 774        wholeTilesX = 1;
 775        partTilesX = 0;
 776
 777        /* Initialize the framebuffer */
 778        val = 0;
 779        SET_GBE_FIELD(FRM_SIZE_TILE, FRM_WIDTH_TILE, val, wholeTilesX);
 780        SET_GBE_FIELD(FRM_SIZE_TILE, FRM_RHS, val, partTilesX);
 781
 782        switch (bytesPerPixel) {
 783        case 1:
 784                SET_GBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, val,
 785                              GBE_FRM_DEPTH_8);
 786                break;
 787        case 2:
 788                SET_GBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, val,
 789                              GBE_FRM_DEPTH_16);
 790                break;
 791        case 4:
 792                SET_GBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, val,
 793                              GBE_FRM_DEPTH_32);
 794                break;
 795        }
 796        gbe->frm_size_tile = val;
 797
 798        /* compute tweaked height */
 799        height_pix = xpmax * ypmax / maxPixelsPerTileX;
 800
 801        val = 0;
 802        SET_GBE_FIELD(FRM_SIZE_PIXEL, FB_HEIGHT_PIX, val, height_pix);
 803        gbe->frm_size_pixel = val;
 804
 805        /* turn off DID and overlay DMA */
 806        gbe->did_control = 0;
 807        gbe->ovr_width_tile = 0;
 808
 809        /* Turn off mouse cursor */
 810        gbe->crs_ctl = 0;
 811
 812        /* Turn on GBE */
 813        gbe_turn_on();
 814
 815        /* Initialize the gamma map */
 816        udelay(10);
 817        for (i = 0; i < 256; i++)
 818                gbe->gmap[i] = (i << 24) | (i << 16) | (i << 8);
 819
 820        /* Initialize the color map */
 821        for (i = 0; i < 256; i++)
 822                gbe_cmap[i] = (i << 8) | (i << 16) | (i << 24);
 823
 824        gbe_loadcmap();
 825
 826        return 0;
 827}
 828
 829static void gbefb_encode_fix(struct fb_fix_screeninfo *fix,
 830                             struct fb_var_screeninfo *var)
 831{
 832        memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 833        strcpy(fix->id, "SGI GBE");
 834        fix->smem_start = (unsigned long) gbe_mem;
 835        fix->smem_len = gbe_mem_size;
 836        fix->type = FB_TYPE_PACKED_PIXELS;
 837        fix->type_aux = 0;
 838        fix->accel = FB_ACCEL_NONE;
 839        switch (var->bits_per_pixel) {
 840        case 8:
 841                fix->visual = FB_VISUAL_PSEUDOCOLOR;
 842                break;
 843        default:
 844                fix->visual = FB_VISUAL_TRUECOLOR;
 845                break;
 846        }
 847        fix->ywrapstep = 0;
 848        fix->xpanstep = 0;
 849        fix->ypanstep = 0;
 850        fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
 851        fix->mmio_start = GBE_BASE;
 852        fix->mmio_len = sizeof(struct sgi_gbe);
 853}
 854
 855/*
 856 *  Set a single color register. The values supplied are already
 857 *  rounded down to the hardware's capabilities (according to the
 858 *  entries in the var structure). Return != 0 for invalid regno.
 859 */
 860
 861static int gbefb_setcolreg(unsigned regno, unsigned red, unsigned green,
 862                             unsigned blue, unsigned transp,
 863                             struct fb_info *info)
 864{
 865        int i;
 866
 867        if (regno > 255)
 868                return 1;
 869        red >>= 8;
 870        green >>= 8;
 871        blue >>= 8;
 872
 873        if (info->var.bits_per_pixel <= 8) {
 874                gbe_cmap[regno] = (red << 24) | (green << 16) | (blue << 8);
 875                if (gbe_turned_on) {
 876                        /* wait for the color map FIFO to have a free entry */
 877                        for (i = 0; i < 1000 && gbe->cm_fifo >= 63; i++)
 878                                udelay(10);
 879                        if (i == 1000) {
 880                                printk(KERN_ERR "gbefb: cmap FIFO timeout\n");
 881                                return 1;
 882                        }
 883                        gbe->cmap[regno] = gbe_cmap[regno];
 884                }
 885        } else if (regno < 16) {
 886                switch (info->var.bits_per_pixel) {
 887                case 15:
 888                case 16:
 889                        red >>= 3;
 890                        green >>= 3;
 891                        blue >>= 3;
 892                        pseudo_palette[regno] =
 893                                (red << info->var.red.offset) |
 894                                (green << info->var.green.offset) |
 895                                (blue << info->var.blue.offset);
 896                        break;
 897                case 32:
 898                        pseudo_palette[regno] =
 899                                (red << info->var.red.offset) |
 900                                (green << info->var.green.offset) |
 901                                (blue << info->var.blue.offset);
 902                        break;
 903                }
 904        }
 905
 906        return 0;
 907}
 908
 909/*
 910 *  Check video mode validity, eventually modify var to best match.
 911 */
 912static int gbefb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 913{
 914        unsigned int line_length;
 915        struct gbe_timing_info timing;
 916        int ret;
 917
 918        /* Limit bpp to 8, 16, and 32 */
 919        if (var->bits_per_pixel <= 8)
 920                var->bits_per_pixel = 8;
 921        else if (var->bits_per_pixel <= 16)
 922                var->bits_per_pixel = 16;
 923        else if (var->bits_per_pixel <= 32)
 924                var->bits_per_pixel = 32;
 925        else
 926                return -EINVAL;
 927
 928        /* Check the mode can be mapped linearly with the tile table trick. */
 929        /* This requires width x height x bytes/pixel be a multiple of 512 */
 930        if ((var->xres * var->yres * var->bits_per_pixel) & 4095)
 931                return -EINVAL;
 932
 933        var->grayscale = 0;     /* No grayscale for now */
 934
 935        ret = compute_gbe_timing(var, &timing);
 936        var->pixclock = ret;
 937        if (ret < 0)
 938                return -EINVAL;
 939
 940        /* Adjust virtual resolution, if necessary */
 941        if (var->xres > var->xres_virtual || (!ywrap && !ypan))
 942                var->xres_virtual = var->xres;
 943        if (var->yres > var->yres_virtual || (!ywrap && !ypan))
 944                var->yres_virtual = var->yres;
 945
 946        if (var->vmode & FB_VMODE_CONUPDATE) {
 947                var->vmode |= FB_VMODE_YWRAP;
 948                var->xoffset = info->var.xoffset;
 949                var->yoffset = info->var.yoffset;
 950        }
 951
 952        /* No grayscale for now */
 953        var->grayscale = 0;
 954
 955        /* Memory limit */
 956        line_length = var->xres_virtual * var->bits_per_pixel / 8;
 957        if (line_length * var->yres_virtual > gbe_mem_size)
 958                return -ENOMEM; /* Virtual resolution too high */
 959
 960        switch (var->bits_per_pixel) {
 961        case 8:
 962                var->red.offset = 0;
 963                var->red.length = 8;
 964                var->green.offset = 0;
 965                var->green.length = 8;
 966                var->blue.offset = 0;
 967                var->blue.length = 8;
 968                var->transp.offset = 0;
 969                var->transp.length = 0;
 970                break;
 971        case 16:                /* RGB 1555 */
 972                var->red.offset = 10;
 973                var->red.length = 5;
 974                var->green.offset = 5;
 975                var->green.length = 5;
 976                var->blue.offset = 0;
 977                var->blue.length = 5;
 978                var->transp.offset = 0;
 979                var->transp.length = 0;
 980                break;
 981        case 32:                /* RGB 8888 */
 982                var->red.offset = 24;
 983                var->red.length = 8;
 984                var->green.offset = 16;
 985                var->green.length = 8;
 986                var->blue.offset = 8;
 987                var->blue.length = 8;
 988                var->transp.offset = 0;
 989                var->transp.length = 8;
 990                break;
 991        }
 992        var->red.msb_right = 0;
 993        var->green.msb_right = 0;
 994        var->blue.msb_right = 0;
 995        var->transp.msb_right = 0;
 996
 997        var->left_margin = timing.htotal - timing.hsync_end;
 998        var->right_margin = timing.hsync_start - timing.width;
 999        var->upper_margin = timing.vtotal - timing.vsync_end;
1000        var->lower_margin = timing.vsync_start - timing.height;
1001        var->hsync_len = timing.hsync_end - timing.hsync_start;
1002        var->vsync_len = timing.vsync_end - timing.vsync_start;
1003
1004        return 0;
1005}
1006
1007static int gbefb_mmap(struct fb_info *info,
1008                        struct vm_area_struct *vma)
1009{
1010        unsigned long size = vma->vm_end - vma->vm_start;
1011        unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
1012        unsigned long addr;
1013        unsigned long phys_addr, phys_size;
1014        u16 *tile;
1015
1016        /* check range */
1017        if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
1018                return -EINVAL;
1019        if (offset + size > gbe_mem_size)
1020                return -EINVAL;
1021
1022        /* remap using the fastest write-through mode on architecture */
1023        /* try not polluting the cache when possible */
1024        pgprot_val(vma->vm_page_prot) =
1025                pgprot_fb(pgprot_val(vma->vm_page_prot));
1026
1027        vma->vm_flags |= VM_IO | VM_RESERVED;
1028
1029        /* look for the starting tile */
1030        tile = &gbe_tiles.cpu[offset >> TILE_SHIFT];
1031        addr = vma->vm_start;
1032        offset &= TILE_MASK;
1033
1034        /* remap each tile separately */
1035        do {
1036                phys_addr = (((unsigned long) (*tile)) << TILE_SHIFT) + offset;
1037                if ((offset + size) < TILE_SIZE)
1038                        phys_size = size;
1039                else
1040                        phys_size = TILE_SIZE - offset;
1041
1042                if (remap_pfn_range(vma, addr, phys_addr >> PAGE_SHIFT,
1043                                                phys_size, vma->vm_page_prot))
1044                        return -EAGAIN;
1045
1046                offset = 0;
1047                size -= phys_size;
1048                addr += phys_size;
1049                tile++;
1050        } while (size);
1051
1052        return 0;
1053}
1054
1055static struct fb_ops gbefb_ops = {
1056        .owner          = THIS_MODULE,
1057        .fb_check_var   = gbefb_check_var,
1058        .fb_set_par     = gbefb_set_par,
1059        .fb_setcolreg   = gbefb_setcolreg,
1060        .fb_mmap        = gbefb_mmap,
1061        .fb_blank       = gbefb_blank,
1062        .fb_fillrect    = cfb_fillrect,
1063        .fb_copyarea    = cfb_copyarea,
1064        .fb_imageblit   = cfb_imageblit,
1065};
1066
1067/*
1068 * sysfs
1069 */
1070
1071static ssize_t gbefb_show_memsize(struct device *dev, struct device_attribute *attr, char *buf)
1072{
1073        return snprintf(buf, PAGE_SIZE, "%d\n", gbe_mem_size);
1074}
1075
1076static DEVICE_ATTR(size, S_IRUGO, gbefb_show_memsize, NULL);
1077
1078static ssize_t gbefb_show_rev(struct device *device, struct device_attribute *attr, char *buf)
1079{
1080        return snprintf(buf, PAGE_SIZE, "%d\n", gbe_revision);
1081}
1082
1083static DEVICE_ATTR(revision, S_IRUGO, gbefb_show_rev, NULL);
1084
1085static void __devexit gbefb_remove_sysfs(struct device *dev)
1086{
1087        device_remove_file(dev, &dev_attr_size);
1088        device_remove_file(dev, &dev_attr_revision);
1089}
1090
1091static void gbefb_create_sysfs(struct device *dev)
1092{
1093        device_create_file(dev, &dev_attr_size);
1094        device_create_file(dev, &dev_attr_revision);
1095}
1096
1097/*
1098 * Initialization
1099 */
1100
1101static int __devinit gbefb_setup(char *options)
1102{
1103        char *this_opt;
1104
1105        if (!options || !*options)
1106                return 0;
1107
1108        while ((this_opt = strsep(&options, ",")) != NULL) {
1109                if (!strncmp(this_opt, "monitor:", 8)) {
1110                        if (!strncmp(this_opt + 8, "crt", 3)) {
1111                                flat_panel_enabled = 0;
1112                                default_var = &default_var_CRT;
1113                                default_mode = &default_mode_CRT;
1114                        } else if (!strncmp(this_opt + 8, "1600sw", 6) ||
1115                                   !strncmp(this_opt + 8, "lcd", 3)) {
1116                                flat_panel_enabled = 1;
1117                                default_var = &default_var_LCD;
1118                                default_mode = &default_mode_LCD;
1119                        }
1120                } else if (!strncmp(this_opt, "mem:", 4)) {
1121                        gbe_mem_size = memparse(this_opt + 4, &this_opt);
1122                        if (gbe_mem_size > CONFIG_FB_GBE_MEM * 1024 * 1024)
1123                                gbe_mem_size = CONFIG_FB_GBE_MEM * 1024 * 1024;
1124                        if (gbe_mem_size < TILE_SIZE)
1125                                gbe_mem_size = TILE_SIZE;
1126                } else
1127                        mode_option = this_opt;
1128        }
1129        return 0;
1130}
1131
1132static int __devinit gbefb_probe(struct platform_device *p_dev)
1133{
1134        int i, ret = 0;
1135        struct fb_info *info;
1136        struct gbefb_par *par;
1137#ifndef MODULE
1138        char *options = NULL;
1139#endif
1140
1141        info = framebuffer_alloc(sizeof(struct gbefb_par), &p_dev->dev);
1142        if (!info)
1143                return -ENOMEM;
1144
1145#ifndef MODULE
1146        if (fb_get_options("gbefb", &options)) {
1147                ret = -ENODEV;
1148                goto out_release_framebuffer;
1149        }
1150        gbefb_setup(options);
1151#endif
1152
1153        if (!request_mem_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) {
1154                printk(KERN_ERR "gbefb: couldn't reserve mmio region\n");
1155                ret = -EBUSY;
1156                goto out_release_framebuffer;
1157        }
1158
1159        gbe = (struct sgi_gbe *) ioremap(GBE_BASE, sizeof(struct sgi_gbe));
1160        if (!gbe) {
1161                printk(KERN_ERR "gbefb: couldn't map mmio region\n");
1162                ret = -ENXIO;
1163                goto out_release_mem_region;
1164        }
1165        gbe_revision = gbe->ctrlstat & 15;
1166
1167        gbe_tiles.cpu =
1168                dma_alloc_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),
1169                                   &gbe_tiles.dma, GFP_KERNEL);
1170        if (!gbe_tiles.cpu) {
1171                printk(KERN_ERR "gbefb: couldn't allocate tiles table\n");
1172                ret = -ENOMEM;
1173                goto out_unmap;
1174        }
1175
1176        if (gbe_mem_phys) {
1177                /* memory was allocated at boot time */
1178                gbe_mem = ioremap_nocache(gbe_mem_phys, gbe_mem_size);
1179                if (!gbe_mem) {
1180                        printk(KERN_ERR "gbefb: couldn't map framebuffer\n");
1181                        ret = -ENOMEM;
1182                        goto out_tiles_free;
1183                }
1184
1185                gbe_dma_addr = 0;
1186        } else {
1187                /* try to allocate memory with the classical allocator
1188                 * this has high chance to fail on low memory machines */
1189                gbe_mem = dma_alloc_coherent(NULL, gbe_mem_size, &gbe_dma_addr,
1190                                             GFP_KERNEL);
1191                if (!gbe_mem) {
1192                        printk(KERN_ERR "gbefb: couldn't allocate framebuffer memory\n");
1193                        ret = -ENOMEM;
1194                        goto out_tiles_free;
1195                }
1196
1197                gbe_mem_phys = (unsigned long) gbe_dma_addr;
1198        }
1199
1200#ifdef CONFIG_X86
1201        mtrr_add(gbe_mem_phys, gbe_mem_size, MTRR_TYPE_WRCOMB, 1);
1202#endif
1203
1204        /* map framebuffer memory into tiles table */
1205        for (i = 0; i < (gbe_mem_size >> TILE_SHIFT); i++)
1206                gbe_tiles.cpu[i] = (gbe_mem_phys >> TILE_SHIFT) + i;
1207
1208        info->fbops = &gbefb_ops;
1209        info->pseudo_palette = pseudo_palette;
1210        info->flags = FBINFO_DEFAULT;
1211        info->screen_base = gbe_mem;
1212        fb_alloc_cmap(&info->cmap, 256, 0);
1213
1214        /* reset GBE */
1215        gbe_reset();
1216
1217        par = info->par;
1218        /* turn on default video mode */
1219        if (fb_find_mode(&par->var, info, mode_option, NULL, 0,
1220                         default_mode, 8) == 0)
1221                par->var = *default_var;
1222        info->var = par->var;
1223        gbefb_check_var(&par->var, info);
1224        gbefb_encode_fix(&info->fix, &info->var);
1225
1226        if (register_framebuffer(info) < 0) {
1227                printk(KERN_ERR "gbefb: couldn't register framebuffer\n");
1228                ret = -ENXIO;
1229                goto out_gbe_unmap;
1230        }
1231
1232        platform_set_drvdata(p_dev, info);
1233        gbefb_create_sysfs(&p_dev->dev);
1234
1235        printk(KERN_INFO "fb%d: %s rev %d @ 0x%08x using %dkB memory\n",
1236               info->node, info->fix.id, gbe_revision, (unsigned) GBE_BASE,
1237               gbe_mem_size >> 10);
1238
1239        return 0;
1240
1241out_gbe_unmap:
1242        if (gbe_dma_addr)
1243                dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys);
1244        else
1245                iounmap(gbe_mem);
1246out_tiles_free:
1247        dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),
1248                          (void *)gbe_tiles.cpu, gbe_tiles.dma);
1249out_unmap:
1250        iounmap(gbe);
1251out_release_mem_region:
1252        release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
1253out_release_framebuffer:
1254        framebuffer_release(info);
1255
1256        return ret;
1257}
1258
1259static int __devexit gbefb_remove(struct platform_device* p_dev)
1260{
1261        struct fb_info *info = platform_get_drvdata(p_dev);
1262
1263        unregister_framebuffer(info);
1264        gbe_turn_off();
1265        if (gbe_dma_addr)
1266                dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys);
1267        else
1268                iounmap(gbe_mem);
1269        dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),
1270                          (void *)gbe_tiles.cpu, gbe_tiles.dma);
1271        release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
1272        iounmap(gbe);
1273        gbefb_remove_sysfs(&p_dev->dev);
1274        framebuffer_release(info);
1275
1276        return 0;
1277}
1278
1279static struct platform_driver gbefb_driver = {
1280        .probe = gbefb_probe,
1281        .remove = __devexit_p(gbefb_remove),
1282        .driver = {
1283                .name = "gbefb",
1284        },
1285};
1286
1287static struct platform_device *gbefb_device;
1288
1289static int __init gbefb_init(void)
1290{
1291        int ret = platform_driver_register(&gbefb_driver);
1292        if (!ret) {
1293                gbefb_device = platform_device_alloc("gbefb", 0);
1294                if (gbefb_device) {
1295                        ret = platform_device_add(gbefb_device);
1296                } else {
1297                        ret = -ENOMEM;
1298                }
1299                if (ret) {
1300                        platform_device_put(gbefb_device);
1301                        platform_driver_unregister(&gbefb_driver);
1302                }
1303        }
1304        return ret;
1305}
1306
1307static void __exit gbefb_exit(void)
1308{
1309        platform_device_unregister(gbefb_device);
1310        platform_driver_unregister(&gbefb_driver);
1311}
1312
1313module_init(gbefb_init);
1314module_exit(gbefb_exit);
1315
1316MODULE_LICENSE("GPL");
1317
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.