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