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