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