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