linux/drivers/video/fbdev/w100fb.c
<<
>>
Prefs
   1/*
   2 * linux/drivers/video/w100fb.c
   3 *
   4 * Frame Buffer Device for ATI Imageon w100 (Wallaby)
   5 *
   6 * Copyright (C) 2002, ATI Corp.
   7 * Copyright (C) 2004-2006 Richard Purdie
   8 * Copyright (c) 2005 Ian Molton
   9 * Copyright (c) 2006 Alberto Mardegan
  10 *
  11 * Rewritten for 2.6 by Richard Purdie <rpurdie@rpsys.net>
  12 *
  13 * Generic platform support by Ian Molton <spyro@f2s.com>
  14 * and Richard Purdie <rpurdie@rpsys.net>
  15 *
  16 * w32xx support by Ian Molton
  17 *
  18 * Hardware acceleration support by Alberto Mardegan
  19 * <mardy@users.sourceforge.net>
  20 *
  21 * This program is free software; you can redistribute it and/or modify
  22 * it under the terms of the GNU General Public License version 2 as
  23 * published by the Free Software Foundation.
  24 *
  25 */
  26
  27#include <linux/delay.h>
  28#include <linux/fb.h>
  29#include <linux/init.h>
  30#include <linux/kernel.h>
  31#include <linux/mm.h>
  32#include <linux/platform_device.h>
  33#include <linux/slab.h>
  34#include <linux/string.h>
  35#include <linux/vmalloc.h>
  36#include <linux/module.h>
  37#include <asm/io.h>
  38#include <asm/uaccess.h>
  39#include <video/w100fb.h>
  40#include "w100fb.h"
  41
  42/*
  43 * Prototypes
  44 */
  45static void w100_suspend(u32 mode);
  46static void w100_vsync(void);
  47static void w100_hw_init(struct w100fb_par*);
  48static void w100_pwm_setup(struct w100fb_par*);
  49static void w100_init_clocks(struct w100fb_par*);
  50static void w100_setup_memory(struct w100fb_par*);
  51static void w100_init_lcd(struct w100fb_par*);
  52static void w100_set_dispregs(struct w100fb_par*);
  53static void w100_update_enable(void);
  54static void w100_update_disable(void);
  55static void calc_hsync(struct w100fb_par *par);
  56static void w100_init_graphic_engine(struct w100fb_par *par);
  57struct w100_pll_info *w100_get_xtal_table(unsigned int freq);
  58
  59/* Pseudo palette size */
  60#define MAX_PALETTES      16
  61
  62#define W100_SUSPEND_EXTMEM 0
  63#define W100_SUSPEND_ALL    1
  64
  65#define BITS_PER_PIXEL    16
  66
  67/* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */
  68static void *remapped_base;
  69static void *remapped_regs;
  70static void *remapped_fbuf;
  71
  72#define REMAPPED_FB_LEN   0x15ffff
  73
  74/* This is the offset in the w100's address space we map the current
  75   framebuffer memory to. We use the position of external memory as
  76   we can remap internal memory to there if external isn't present. */
  77#define W100_FB_BASE MEM_EXT_BASE_VALUE
  78
  79
  80/*
  81 * Sysfs functions
  82 */
  83static ssize_t flip_show(struct device *dev, struct device_attribute *attr, char *buf)
  84{
  85        struct fb_info *info = dev_get_drvdata(dev);
  86        struct w100fb_par *par=info->par;
  87
  88        return sprintf(buf, "%d\n",par->flip);
  89}
  90
  91static ssize_t flip_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  92{
  93        unsigned int flip;
  94        struct fb_info *info = dev_get_drvdata(dev);
  95        struct w100fb_par *par=info->par;
  96
  97        flip = simple_strtoul(buf, NULL, 10);
  98
  99        if (flip > 0)
 100                par->flip = 1;
 101        else
 102                par->flip = 0;
 103
 104        w100_update_disable();
 105        w100_set_dispregs(par);
 106        w100_update_enable();
 107
 108        calc_hsync(par);
 109
 110        return count;
 111}
 112
 113static DEVICE_ATTR(flip, 0644, flip_show, flip_store);
 114
 115static ssize_t w100fb_reg_read(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 116{
 117        unsigned long regs, param;
 118        regs = simple_strtoul(buf, NULL, 16);
 119        param = readl(remapped_regs + regs);
 120        printk("Read Register 0x%08lX: 0x%08lX\n", regs, param);
 121        return count;
 122}
 123
 124static DEVICE_ATTR(reg_read, 0200, NULL, w100fb_reg_read);
 125
 126static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 127{
 128        unsigned long regs, param;
 129        sscanf(buf, "%lx %lx", &regs, &param);
 130
 131        if (regs <= 0x2000) {
 132                printk("Write Register 0x%08lX: 0x%08lX\n", regs, param);
 133                writel(param, remapped_regs + regs);
 134        }
 135
 136        return count;
 137}
 138
 139static DEVICE_ATTR(reg_write, 0200, NULL, w100fb_reg_write);
 140
 141
 142static ssize_t fastpllclk_show(struct device *dev, struct device_attribute *attr, char *buf)
 143{
 144        struct fb_info *info = dev_get_drvdata(dev);
 145        struct w100fb_par *par=info->par;
 146
 147        return sprintf(buf, "%d\n",par->fastpll_mode);
 148}
 149
 150static ssize_t fastpllclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 151{
 152        struct fb_info *info = dev_get_drvdata(dev);
 153        struct w100fb_par *par=info->par;
 154
 155        if (simple_strtoul(buf, NULL, 10) > 0) {
 156                par->fastpll_mode=1;
 157                printk("w100fb: Using fast system clock (if possible)\n");
 158        } else {
 159                par->fastpll_mode=0;
 160                printk("w100fb: Using normal system clock\n");
 161        }
 162
 163        w100_init_clocks(par);
 164        calc_hsync(par);
 165
 166        return count;
 167}
 168
 169static DEVICE_ATTR(fastpllclk, 0644, fastpllclk_show, fastpllclk_store);
 170
 171/*
 172 * Some touchscreens need hsync information from the video driver to
 173 * function correctly. We export it here.
 174 */
 175unsigned long w100fb_get_hsynclen(struct device *dev)
 176{
 177        struct fb_info *info = dev_get_drvdata(dev);
 178        struct w100fb_par *par=info->par;
 179
 180        /* If display is blanked/suspended, hsync isn't active */
 181        if (par->blanked)
 182                return 0;
 183        else
 184                return par->hsync_len;
 185}
 186EXPORT_SYMBOL(w100fb_get_hsynclen);
 187
 188static void w100fb_clear_screen(struct w100fb_par *par)
 189{
 190        memset_io(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), 0, (par->xres * par->yres * BITS_PER_PIXEL/8));
 191}
 192
 193
 194/*
 195 * Set a palette value from rgb components
 196 */
 197static int w100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 198                             u_int trans, struct fb_info *info)
 199{
 200        unsigned int val;
 201        int ret = 1;
 202
 203        /*
 204         * If greyscale is true, then we convert the RGB value
 205         * to greyscale no matter what visual we are using.
 206         */
 207        if (info->var.grayscale)
 208                red = green = blue = (19595 * red + 38470 * green + 7471 * blue) >> 16;
 209
 210        /*
 211         * 16-bit True Colour.  We encode the RGB value
 212         * according to the RGB bitfield information.
 213         */
 214        if (regno < MAX_PALETTES) {
 215                u32 *pal = info->pseudo_palette;
 216
 217                val = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
 218                pal[regno] = val;
 219                ret = 0;
 220        }
 221        return ret;
 222}
 223
 224
 225/*
 226 * Blank the display based on value in blank_mode
 227 */
 228static int w100fb_blank(int blank_mode, struct fb_info *info)
 229{
 230        struct w100fb_par *par = info->par;
 231        struct w100_tg_info *tg = par->mach->tg;
 232
 233        switch(blank_mode) {
 234
 235        case FB_BLANK_NORMAL:         /* Normal blanking */
 236        case FB_BLANK_VSYNC_SUSPEND:  /* VESA blank (vsync off) */
 237        case FB_BLANK_HSYNC_SUSPEND:  /* VESA blank (hsync off) */
 238        case FB_BLANK_POWERDOWN:      /* Poweroff */
 239                if (par->blanked == 0) {
 240                        if(tg && tg->suspend)
 241                                tg->suspend(par);
 242                        par->blanked = 1;
 243                }
 244                break;
 245
 246        case FB_BLANK_UNBLANK: /* Unblanking */
 247                if (par->blanked != 0) {
 248                        if(tg && tg->resume)
 249                                tg->resume(par);
 250                        par->blanked = 0;
 251                }
 252                break;
 253        }
 254        return 0;
 255}
 256
 257
 258static void w100_fifo_wait(int entries)
 259{
 260        union rbbm_status_u status;
 261        int i;
 262
 263        for (i = 0; i < 2000000; i++) {
 264                status.val = readl(remapped_regs + mmRBBM_STATUS);
 265                if (status.f.cmdfifo_avail >= entries)
 266                        return;
 267                udelay(1);
 268        }
 269        printk(KERN_ERR "w100fb: FIFO Timeout!\n");
 270}
 271
 272
 273static int w100fb_sync(struct fb_info *info)
 274{
 275        union rbbm_status_u status;
 276        int i;
 277
 278        for (i = 0; i < 2000000; i++) {
 279                status.val = readl(remapped_regs + mmRBBM_STATUS);
 280                if (!status.f.gui_active)
 281                        return 0;
 282                udelay(1);
 283        }
 284        printk(KERN_ERR "w100fb: Graphic engine timeout!\n");
 285        return -EBUSY;
 286}
 287
 288
 289static void w100_init_graphic_engine(struct w100fb_par *par)
 290{
 291        union dp_gui_master_cntl_u gmc;
 292        union dp_mix_u dp_mix;
 293        union dp_datatype_u dp_datatype;
 294        union dp_cntl_u dp_cntl;
 295
 296        w100_fifo_wait(4);
 297        writel(W100_FB_BASE, remapped_regs + mmDST_OFFSET);
 298        writel(par->xres, remapped_regs + mmDST_PITCH);
 299        writel(W100_FB_BASE, remapped_regs + mmSRC_OFFSET);
 300        writel(par->xres, remapped_regs + mmSRC_PITCH);
 301
 302        w100_fifo_wait(3);
 303        writel(0, remapped_regs + mmSC_TOP_LEFT);
 304        writel((par->yres << 16) | par->xres, remapped_regs + mmSC_BOTTOM_RIGHT);
 305        writel(0x1fff1fff, remapped_regs + mmSRC_SC_BOTTOM_RIGHT);
 306
 307        w100_fifo_wait(4);
 308        dp_cntl.val = 0;
 309        dp_cntl.f.dst_x_dir = 1;
 310        dp_cntl.f.dst_y_dir = 1;
 311        dp_cntl.f.src_x_dir = 1;
 312        dp_cntl.f.src_y_dir = 1;
 313        dp_cntl.f.dst_major_x = 1;
 314        dp_cntl.f.src_major_x = 1;
 315        writel(dp_cntl.val, remapped_regs + mmDP_CNTL);
 316
 317        gmc.val = 0;
 318        gmc.f.gmc_src_pitch_offset_cntl = 1;
 319        gmc.f.gmc_dst_pitch_offset_cntl = 1;
 320        gmc.f.gmc_src_clipping = 1;
 321        gmc.f.gmc_dst_clipping = 1;
 322        gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
 323        gmc.f.gmc_dst_datatype = 3; /* from DstType_16Bpp_444 */
 324        gmc.f.gmc_src_datatype = SRC_DATATYPE_EQU_DST;
 325        gmc.f.gmc_byte_pix_order = 1;
 326        gmc.f.gmc_default_sel = 0;
 327        gmc.f.gmc_rop3 = ROP3_SRCCOPY;
 328        gmc.f.gmc_dp_src_source = DP_SRC_MEM_RECTANGULAR;
 329        gmc.f.gmc_clr_cmp_fcn_dis = 1;
 330        gmc.f.gmc_wr_msk_dis = 1;
 331        gmc.f.gmc_dp_op = DP_OP_ROP;
 332        writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
 333
 334        dp_datatype.val = dp_mix.val = 0;
 335        dp_datatype.f.dp_dst_datatype = gmc.f.gmc_dst_datatype;
 336        dp_datatype.f.dp_brush_datatype = gmc.f.gmc_brush_datatype;
 337        dp_datatype.f.dp_src2_type = 0;
 338        dp_datatype.f.dp_src2_datatype = gmc.f.gmc_src_datatype;
 339        dp_datatype.f.dp_src_datatype = gmc.f.gmc_src_datatype;
 340        dp_datatype.f.dp_byte_pix_order = gmc.f.gmc_byte_pix_order;
 341        writel(dp_datatype.val, remapped_regs + mmDP_DATATYPE);
 342
 343        dp_mix.f.dp_src_source = gmc.f.gmc_dp_src_source;
 344        dp_mix.f.dp_src2_source = 1;
 345        dp_mix.f.dp_rop3 = gmc.f.gmc_rop3;
 346        dp_mix.f.dp_op = gmc.f.gmc_dp_op;
 347        writel(dp_mix.val, remapped_regs + mmDP_MIX);
 348}
 349
 350
 351static void w100fb_fillrect(struct fb_info *info,
 352                            const struct fb_fillrect *rect)
 353{
 354        union dp_gui_master_cntl_u gmc;
 355
 356        if (info->state != FBINFO_STATE_RUNNING)
 357                return;
 358        if (info->flags & FBINFO_HWACCEL_DISABLED) {
 359                cfb_fillrect(info, rect);
 360                return;
 361        }
 362
 363        gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
 364        gmc.f.gmc_rop3 = ROP3_PATCOPY;
 365        gmc.f.gmc_brush_datatype = GMC_BRUSH_SOLID_COLOR;
 366        w100_fifo_wait(2);
 367        writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
 368        writel(rect->color, remapped_regs + mmDP_BRUSH_FRGD_CLR);
 369
 370        w100_fifo_wait(2);
 371        writel((rect->dy << 16) | (rect->dx & 0xffff), remapped_regs + mmDST_Y_X);
 372        writel((rect->width << 16) | (rect->height & 0xffff),
 373               remapped_regs + mmDST_WIDTH_HEIGHT);
 374}
 375
 376
 377static void w100fb_copyarea(struct fb_info *info,
 378                            const struct fb_copyarea *area)
 379{
 380        u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
 381        u32 h = area->height, w = area->width;
 382        union dp_gui_master_cntl_u gmc;
 383
 384        if (info->state != FBINFO_STATE_RUNNING)
 385                return;
 386        if (info->flags & FBINFO_HWACCEL_DISABLED) {
 387                cfb_copyarea(info, area);
 388                return;
 389        }
 390
 391        gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
 392        gmc.f.gmc_rop3 = ROP3_SRCCOPY;
 393        gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
 394        w100_fifo_wait(1);
 395        writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
 396
 397        w100_fifo_wait(3);
 398        writel((sy << 16) | (sx & 0xffff), remapped_regs + mmSRC_Y_X);
 399        writel((dy << 16) | (dx & 0xffff), remapped_regs + mmDST_Y_X);
 400        writel((w << 16) | (h & 0xffff), remapped_regs + mmDST_WIDTH_HEIGHT);
 401}
 402
 403
 404/*
 405 *  Change the resolution by calling the appropriate hardware functions
 406 */
 407static void w100fb_activate_var(struct w100fb_par *par)
 408{
 409        struct w100_tg_info *tg = par->mach->tg;
 410
 411        w100_pwm_setup(par);
 412        w100_setup_memory(par);
 413        w100_init_clocks(par);
 414        w100fb_clear_screen(par);
 415        w100_vsync();
 416
 417        w100_update_disable();
 418        w100_init_lcd(par);
 419        w100_set_dispregs(par);
 420        w100_update_enable();
 421        w100_init_graphic_engine(par);
 422
 423        calc_hsync(par);
 424
 425        if (!par->blanked && tg && tg->change)
 426                tg->change(par);
 427}
 428
 429
 430/* Select the smallest mode that allows the desired resolution to be
 431 * displayed. If desired, the x and y parameters can be rounded up to
 432 * match the selected mode.
 433 */
 434static struct w100_mode *w100fb_get_mode(struct w100fb_par *par, unsigned int *x, unsigned int *y, int saveval)
 435{
 436        struct w100_mode *mode = NULL;
 437        struct w100_mode *modelist = par->mach->modelist;
 438        unsigned int best_x = 0xffffffff, best_y = 0xffffffff;
 439        unsigned int i;
 440
 441        for (i = 0 ; i < par->mach->num_modes ; i++) {
 442                if (modelist[i].xres >= *x && modelist[i].yres >= *y &&
 443                                modelist[i].xres < best_x && modelist[i].yres < best_y) {
 444                        best_x = modelist[i].xres;
 445                        best_y = modelist[i].yres;
 446                        mode = &modelist[i];
 447                } else if(modelist[i].xres >= *y && modelist[i].yres >= *x &&
 448                        modelist[i].xres < best_y && modelist[i].yres < best_x) {
 449                        best_x = modelist[i].yres;
 450                        best_y = modelist[i].xres;
 451                        mode = &modelist[i];
 452                }
 453        }
 454
 455        if (mode && saveval) {
 456                *x = best_x;
 457                *y = best_y;
 458        }
 459
 460        return mode;
 461}
 462
 463
 464/*
 465 *  w100fb_check_var():
 466 *  Get the video params out of 'var'. If a value doesn't fit, round it up,
 467 *  if it's too big, return -EINVAL.
 468 */
 469static int w100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 470{
 471        struct w100fb_par *par=info->par;
 472
 473        if(!w100fb_get_mode(par, &var->xres, &var->yres, 1))
 474                return -EINVAL;
 475
 476        if (par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (par->mach->mem->size+1)))
 477                return -EINVAL;
 478
 479        if (!par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)))
 480                return -EINVAL;
 481
 482        var->xres_virtual = max(var->xres_virtual, var->xres);
 483        var->yres_virtual = max(var->yres_virtual, var->yres);
 484
 485        if (var->bits_per_pixel > BITS_PER_PIXEL)
 486                return -EINVAL;
 487        else
 488                var->bits_per_pixel = BITS_PER_PIXEL;
 489
 490        var->red.offset = 11;
 491        var->red.length = 5;
 492        var->green.offset = 5;
 493        var->green.length = 6;
 494        var->blue.offset = 0;
 495        var->blue.length = 5;
 496        var->transp.offset = var->transp.length = 0;
 497
 498        var->nonstd = 0;
 499        var->height = -1;
 500        var->width = -1;
 501        var->vmode = FB_VMODE_NONINTERLACED;
 502        var->sync = 0;
 503        var->pixclock = 0x04;  /* 171521; */
 504
 505        return 0;
 506}
 507
 508
 509/*
 510 * w100fb_set_par():
 511 *      Set the user defined part of the display for the specified console
 512 *  by looking at the values in info.var
 513 */
 514static int w100fb_set_par(struct fb_info *info)
 515{
 516        struct w100fb_par *par=info->par;
 517
 518        if (par->xres != info->var.xres || par->yres != info->var.yres) {
 519                par->xres = info->var.xres;
 520                par->yres = info->var.yres;
 521                par->mode = w100fb_get_mode(par, &par->xres, &par->yres, 0);
 522
 523                info->fix.visual = FB_VISUAL_TRUECOLOR;
 524                info->fix.ypanstep = 0;
 525                info->fix.ywrapstep = 0;
 526                info->fix.line_length = par->xres * BITS_PER_PIXEL / 8;
 527
 528                mutex_lock(&info->mm_lock);
 529                if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) {
 530                        par->extmem_active = 1;
 531                        info->fix.smem_len = par->mach->mem->size+1;
 532                } else {
 533                        par->extmem_active = 0;
 534                        info->fix.smem_len = MEM_INT_SIZE+1;
 535                }
 536                mutex_unlock(&info->mm_lock);
 537
 538                w100fb_activate_var(par);
 539        }
 540        return 0;
 541}
 542
 543
 544/*
 545 *  Frame buffer operations
 546 */
 547static struct fb_ops w100fb_ops = {
 548        .owner        = THIS_MODULE,
 549        .fb_check_var = w100fb_check_var,
 550        .fb_set_par   = w100fb_set_par,
 551        .fb_setcolreg = w100fb_setcolreg,
 552        .fb_blank     = w100fb_blank,
 553        .fb_fillrect  = w100fb_fillrect,
 554        .fb_copyarea  = w100fb_copyarea,
 555        .fb_imageblit = cfb_imageblit,
 556        .fb_sync      = w100fb_sync,
 557};
 558
 559#ifdef CONFIG_PM
 560static void w100fb_save_vidmem(struct w100fb_par *par)
 561{
 562        int memsize;
 563
 564        if (par->extmem_active) {
 565                memsize=par->mach->mem->size;
 566                par->saved_extmem = vmalloc(memsize);
 567                if (par->saved_extmem)
 568                        memcpy_fromio(par->saved_extmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
 569        }
 570        memsize=MEM_INT_SIZE;
 571        par->saved_intmem = vmalloc(memsize);
 572        if (par->saved_intmem && par->extmem_active)
 573                memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), memsize);
 574        else if (par->saved_intmem)
 575                memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
 576}
 577
 578static void w100fb_restore_vidmem(struct w100fb_par *par)
 579{
 580        int memsize;
 581
 582        if (par->extmem_active && par->saved_extmem) {
 583                memsize=par->mach->mem->size;
 584                memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_extmem, memsize);
 585                vfree(par->saved_extmem);
 586        }
 587        if (par->saved_intmem) {
 588                memsize=MEM_INT_SIZE;
 589                if (par->extmem_active)
 590                        memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), par->saved_intmem, memsize);
 591                else
 592                        memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_intmem, memsize);
 593                vfree(par->saved_intmem);
 594        }
 595}
 596
 597static int w100fb_suspend(struct platform_device *dev, pm_message_t state)
 598{
 599        struct fb_info *info = platform_get_drvdata(dev);
 600        struct w100fb_par *par=info->par;
 601        struct w100_tg_info *tg = par->mach->tg;
 602
 603        w100fb_save_vidmem(par);
 604        if(tg && tg->suspend)
 605                tg->suspend(par);
 606        w100_suspend(W100_SUSPEND_ALL);
 607        par->blanked = 1;
 608
 609        return 0;
 610}
 611
 612static int w100fb_resume(struct platform_device *dev)
 613{
 614        struct fb_info *info = platform_get_drvdata(dev);
 615        struct w100fb_par *par=info->par;
 616        struct w100_tg_info *tg = par->mach->tg;
 617
 618        w100_hw_init(par);
 619        w100fb_activate_var(par);
 620        w100fb_restore_vidmem(par);
 621        if(tg && tg->resume)
 622                tg->resume(par);
 623        par->blanked = 0;
 624
 625        return 0;
 626}
 627#else
 628#define w100fb_suspend  NULL
 629#define w100fb_resume   NULL
 630#endif
 631
 632
 633int w100fb_probe(struct platform_device *pdev)
 634{
 635        int err = -EIO;
 636        struct w100fb_mach_info *inf;
 637        struct fb_info *info = NULL;
 638        struct w100fb_par *par;
 639        struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 640        unsigned int chip_id;
 641
 642        if (!mem)
 643                return -EINVAL;
 644
 645        /* Remap the chip base address */
 646        remapped_base = ioremap_nocache(mem->start+W100_CFG_BASE, W100_CFG_LEN);
 647        if (remapped_base == NULL)
 648                goto out;
 649
 650        /* Map the register space */
 651        remapped_regs = ioremap_nocache(mem->start+W100_REG_BASE, W100_REG_LEN);
 652        if (remapped_regs == NULL)
 653                goto out;
 654
 655        /* Identify the chip */
 656        printk("Found ");
 657        chip_id = readl(remapped_regs + mmCHIP_ID);
 658        switch(chip_id) {
 659                case CHIP_ID_W100:  printk("w100");  break;
 660                case CHIP_ID_W3200: printk("w3200"); break;
 661                case CHIP_ID_W3220: printk("w3220"); break;
 662                default:
 663                        printk("Unknown imageon chip ID\n");
 664                        err = -ENODEV;
 665                        goto out;
 666        }
 667        printk(" at 0x%08lx.\n", (unsigned long) mem->start+W100_CFG_BASE);
 668
 669        /* Remap the framebuffer */
 670        remapped_fbuf = ioremap_nocache(mem->start+MEM_WINDOW_BASE, MEM_WINDOW_SIZE);
 671        if (remapped_fbuf == NULL)
 672                goto out;
 673
 674        info=framebuffer_alloc(sizeof(struct w100fb_par), &pdev->dev);
 675        if (!info) {
 676                err = -ENOMEM;
 677                goto out;
 678        }
 679
 680        par = info->par;
 681        platform_set_drvdata(pdev, info);
 682
 683        inf = dev_get_platdata(&pdev->dev);
 684        par->chip_id = chip_id;
 685        par->mach = inf;
 686        par->fastpll_mode = 0;
 687        par->blanked = 0;
 688
 689        par->pll_table=w100_get_xtal_table(inf->xtal_freq);
 690        if (!par->pll_table) {
 691                printk(KERN_ERR "No matching Xtal definition found\n");
 692                err = -EINVAL;
 693                goto out;
 694        }
 695
 696        info->pseudo_palette = kmalloc(sizeof (u32) * MAX_PALETTES, GFP_KERNEL);
 697        if (!info->pseudo_palette) {
 698                err = -ENOMEM;
 699                goto out;
 700        }
 701
 702        info->fbops = &w100fb_ops;
 703        info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
 704                FBINFO_HWACCEL_FILLRECT;
 705        info->node = -1;
 706        info->screen_base = remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE);
 707        info->screen_size = REMAPPED_FB_LEN;
 708
 709        strcpy(info->fix.id, "w100fb");
 710        info->fix.type = FB_TYPE_PACKED_PIXELS;
 711        info->fix.type_aux = 0;
 712        info->fix.accel = FB_ACCEL_NONE;
 713        info->fix.smem_start = mem->start+W100_FB_BASE;
 714        info->fix.mmio_start = mem->start+W100_REG_BASE;
 715        info->fix.mmio_len = W100_REG_LEN;
 716
 717        if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
 718                err = -ENOMEM;
 719                goto out;
 720        }
 721
 722        par->mode = &inf->modelist[0];
 723        if(inf->init_mode & INIT_MODE_ROTATED) {
 724                info->var.xres = par->mode->yres;
 725                info->var.yres = par->mode->xres;
 726        }
 727        else {
 728                info->var.xres = par->mode->xres;
 729                info->var.yres = par->mode->yres;
 730        }
 731
 732        if(inf->init_mode &= INIT_MODE_FLIPPED)
 733                par->flip = 1;
 734        else
 735                par->flip = 0;
 736
 737        info->var.xres_virtual = info->var.xres;
 738        info->var.yres_virtual = info->var.yres;
 739        info->var.pixclock = 0x04;  /* 171521; */
 740        info->var.sync = 0;
 741        info->var.grayscale = 0;
 742        info->var.xoffset = info->var.yoffset = 0;
 743        info->var.accel_flags = 0;
 744        info->var.activate = FB_ACTIVATE_NOW;
 745
 746        w100_hw_init(par);
 747
 748        if (w100fb_check_var(&info->var, info) < 0) {
 749                err = -EINVAL;
 750                goto out;
 751        }
 752
 753        if (register_framebuffer(info) < 0) {
 754                err = -EINVAL;
 755                goto out;
 756        }
 757
 758        err = device_create_file(&pdev->dev, &dev_attr_fastpllclk);
 759        err |= device_create_file(&pdev->dev, &dev_attr_reg_read);
 760        err |= device_create_file(&pdev->dev, &dev_attr_reg_write);
 761        err |= device_create_file(&pdev->dev, &dev_attr_flip);
 762
 763        if (err != 0)
 764                fb_warn(info, "failed to register attributes (%d)\n", err);
 765
 766        fb_info(info, "%s frame buffer device\n", info->fix.id);
 767        return 0;
 768out:
 769        if (info) {
 770                fb_dealloc_cmap(&info->cmap);
 771                kfree(info->pseudo_palette);
 772        }
 773        if (remapped_fbuf != NULL)
 774                iounmap(remapped_fbuf);
 775        if (remapped_regs != NULL)
 776                iounmap(remapped_regs);
 777        if (remapped_base != NULL)
 778                iounmap(remapped_base);
 779        if (info)
 780                framebuffer_release(info);
 781        return err;
 782}
 783
 784
 785static int w100fb_remove(struct platform_device *pdev)
 786{
 787        struct fb_info *info = platform_get_drvdata(pdev);
 788        struct w100fb_par *par=info->par;
 789
 790        device_remove_file(&pdev->dev, &dev_attr_fastpllclk);
 791        device_remove_file(&pdev->dev, &dev_attr_reg_read);
 792        device_remove_file(&pdev->dev, &dev_attr_reg_write);
 793        device_remove_file(&pdev->dev, &dev_attr_flip);
 794
 795        unregister_framebuffer(info);
 796
 797        vfree(par->saved_intmem);
 798        vfree(par->saved_extmem);
 799        kfree(info->pseudo_palette);
 800        fb_dealloc_cmap(&info->cmap);
 801
 802        iounmap(remapped_base);
 803        iounmap(remapped_regs);
 804        iounmap(remapped_fbuf);
 805
 806        framebuffer_release(info);
 807
 808        return 0;
 809}
 810
 811
 812/* ------------------- chipset specific functions -------------------------- */
 813
 814
 815static void w100_soft_reset(void)
 816{
 817        u16 val = readw((u16 *) remapped_base + cfgSTATUS);
 818        writew(val | 0x08, (u16 *) remapped_base + cfgSTATUS);
 819        udelay(100);
 820        writew(0x00, (u16 *) remapped_base + cfgSTATUS);
 821        udelay(100);
 822}
 823
 824static void w100_update_disable(void)
 825{
 826        union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
 827
 828        /* Prevent display updates */
 829        disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
 830        disp_db_buf_wr_cntl.f.update_db_buf = 0;
 831        disp_db_buf_wr_cntl.f.en_db_buf = 0;
 832        writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
 833}
 834
 835static void w100_update_enable(void)
 836{
 837        union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
 838
 839        /* Enable display updates */
 840        disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
 841        disp_db_buf_wr_cntl.f.update_db_buf = 1;
 842        disp_db_buf_wr_cntl.f.en_db_buf = 1;
 843        writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
 844}
 845
 846unsigned long w100fb_gpio_read(int port)
 847{
 848        unsigned long value;
 849
 850        if (port==W100_GPIO_PORT_A)
 851                value = readl(remapped_regs + mmGPIO_DATA);
 852        else
 853                value = readl(remapped_regs + mmGPIO_DATA2);
 854
 855        return value;
 856}
 857
 858void w100fb_gpio_write(int port, unsigned long value)
 859{
 860        if (port==W100_GPIO_PORT_A)
 861                writel(value, remapped_regs + mmGPIO_DATA);
 862        else
 863                writel(value, remapped_regs + mmGPIO_DATA2);
 864}
 865EXPORT_SYMBOL(w100fb_gpio_read);
 866EXPORT_SYMBOL(w100fb_gpio_write);
 867
 868/*
 869 * Initialization of critical w100 hardware
 870 */
 871static void w100_hw_init(struct w100fb_par *par)
 872{
 873        u32 temp32;
 874        union cif_cntl_u cif_cntl;
 875        union intf_cntl_u intf_cntl;
 876        union cfgreg_base_u cfgreg_base;
 877        union wrap_top_dir_u wrap_top_dir;
 878        union cif_read_dbg_u cif_read_dbg;
 879        union cpu_defaults_u cpu_default;
 880        union cif_write_dbg_u cif_write_dbg;
 881        union wrap_start_dir_u wrap_start_dir;
 882        union cif_io_u cif_io;
 883        struct w100_gpio_regs *gpio = par->mach->gpio;
 884
 885        w100_soft_reset();
 886
 887        /* This is what the fpga_init code does on reset. May be wrong
 888           but there is little info available */
 889        writel(0x31, remapped_regs + mmSCRATCH_UMSK);
 890        for (temp32 = 0; temp32 < 10000; temp32++)
 891                readl(remapped_regs + mmSCRATCH_UMSK);
 892        writel(0x30, remapped_regs + mmSCRATCH_UMSK);
 893
 894        /* Set up CIF */
 895        cif_io.val = defCIF_IO;
 896        writel((u32)(cif_io.val), remapped_regs + mmCIF_IO);
 897
 898        cif_write_dbg.val = readl(remapped_regs + mmCIF_WRITE_DBG);
 899        cif_write_dbg.f.dis_packer_ful_during_rbbm_timeout = 0;
 900        cif_write_dbg.f.en_dword_split_to_rbbm = 1;
 901        cif_write_dbg.f.dis_timeout_during_rbbm = 1;
 902        writel((u32) (cif_write_dbg.val), remapped_regs + mmCIF_WRITE_DBG);
 903
 904        cif_read_dbg.val = readl(remapped_regs + mmCIF_READ_DBG);
 905        cif_read_dbg.f.dis_rd_same_byte_to_trig_fetch = 1;
 906        writel((u32) (cif_read_dbg.val), remapped_regs + mmCIF_READ_DBG);
 907
 908        cif_cntl.val = readl(remapped_regs + mmCIF_CNTL);
 909        cif_cntl.f.dis_system_bits = 1;
 910        cif_cntl.f.dis_mr = 1;
 911        cif_cntl.f.en_wait_to_compensate_dq_prop_dly = 0;
 912        cif_cntl.f.intb_oe = 1;
 913        cif_cntl.f.interrupt_active_high = 1;
 914        writel((u32) (cif_cntl.val), remapped_regs + mmCIF_CNTL);
 915
 916        /* Setup cfgINTF_CNTL and cfgCPU defaults */
 917        intf_cntl.val = defINTF_CNTL;
 918        intf_cntl.f.ad_inc_a = 1;
 919        intf_cntl.f.ad_inc_b = 1;
 920        intf_cntl.f.rd_data_rdy_a = 0;
 921        intf_cntl.f.rd_data_rdy_b = 0;
 922        writeb((u8) (intf_cntl.val), remapped_base + cfgINTF_CNTL);
 923
 924        cpu_default.val = defCPU_DEFAULTS;
 925        cpu_default.f.access_ind_addr_a = 1;
 926        cpu_default.f.access_ind_addr_b = 1;
 927        cpu_default.f.access_scratch_reg = 1;
 928        cpu_default.f.transition_size = 0;
 929        writeb((u8) (cpu_default.val), remapped_base + cfgCPU_DEFAULTS);
 930
 931        /* set up the apertures */
 932        writeb((u8) (W100_REG_BASE >> 16), remapped_base + cfgREG_BASE);
 933
 934        cfgreg_base.val = defCFGREG_BASE;
 935        cfgreg_base.f.cfgreg_base = W100_CFG_BASE;
 936        writel((u32) (cfgreg_base.val), remapped_regs + mmCFGREG_BASE);
 937
 938        wrap_start_dir.val = defWRAP_START_DIR;
 939        wrap_start_dir.f.start_addr = WRAP_BUF_BASE_VALUE >> 1;
 940        writel((u32) (wrap_start_dir.val), remapped_regs + mmWRAP_START_DIR);
 941
 942        wrap_top_dir.val = defWRAP_TOP_DIR;
 943        wrap_top_dir.f.top_addr = WRAP_BUF_TOP_VALUE >> 1;
 944        writel((u32) (wrap_top_dir.val), remapped_regs + mmWRAP_TOP_DIR);
 945
 946        writel((u32) 0x2440, remapped_regs + mmRBBM_CNTL);
 947
 948        /* Set the hardware to 565 colour */
 949        temp32 = readl(remapped_regs + mmDISP_DEBUG2);
 950        temp32 &= 0xff7fffff;
 951        temp32 |= 0x00800000;
 952        writel(temp32, remapped_regs + mmDISP_DEBUG2);
 953
 954        /* Initialise the GPIO lines */
 955        if (gpio) {
 956                writel(gpio->init_data1, remapped_regs + mmGPIO_DATA);
 957                writel(gpio->init_data2, remapped_regs + mmGPIO_DATA2);
 958                writel(gpio->gpio_dir1,  remapped_regs + mmGPIO_CNTL1);
 959                writel(gpio->gpio_oe1,   remapped_regs + mmGPIO_CNTL2);
 960                writel(gpio->gpio_dir2,  remapped_regs + mmGPIO_CNTL3);
 961                writel(gpio->gpio_oe2,   remapped_regs + mmGPIO_CNTL4);
 962        }
 963}
 964
 965
 966struct power_state {
 967        union clk_pin_cntl_u clk_pin_cntl;
 968        union pll_ref_fb_div_u pll_ref_fb_div;
 969        union pll_cntl_u pll_cntl;
 970        union sclk_cntl_u sclk_cntl;
 971        union pclk_cntl_u pclk_cntl;
 972        union pwrmgt_cntl_u pwrmgt_cntl;
 973        int auto_mode;  /* system clock auto changing? */
 974};
 975
 976
 977static struct power_state w100_pwr_state;
 978
 979/* The PLL Fout is determined by (XtalFreq/(M+1)) * ((N_int+1) + (N_fac/8)) */
 980
 981/* 12.5MHz Crystal PLL Table */
 982static struct w100_pll_info xtal_12500000[] = {
 983        /*freq     M   N_int    N_fac  tfgoal  lock_time */
 984        { 50,      0,   1,       0,     0xe0,        56},  /*  50.00 MHz */
 985        { 75,      0,   5,       0,     0xde,        37},  /*  75.00 MHz */
 986        {100,      0,   7,       0,     0xe0,        28},  /* 100.00 MHz */
 987        {125,      0,   9,       0,     0xe0,        22},  /* 125.00 MHz */
 988        {150,      0,   11,      0,     0xe0,        17},  /* 150.00 MHz */
 989        {  0,      0,   0,       0,        0,         0},  /* Terminator */
 990};
 991
 992/* 14.318MHz Crystal PLL Table */
 993static struct w100_pll_info xtal_14318000[] = {
 994        /*freq     M   N_int    N_fac  tfgoal  lock_time */
 995        { 40,      4,   13,      0,     0xe0,        80}, /* tfgoal guessed */
 996        { 50,      1,   6,       0,     0xe0,        64}, /*  50.05 MHz */
 997        { 57,      2,   11,      0,     0xe0,        53}, /* tfgoal guessed */
 998        { 75,      0,   4,       3,     0xe0,        43}, /*  75.08 MHz */
 999        {100,      0,   6,       0,     0xe0,        32}, /* 100.10 MHz */
1000        {  0,      0,   0,       0,        0,         0},
1001};
1002
1003/* 16MHz Crystal PLL Table */
1004static struct w100_pll_info xtal_16000000[] = {
1005        /*freq     M   N_int    N_fac  tfgoal  lock_time */
1006        { 72,      1,   8,       0,     0xe0,        48}, /* tfgoal guessed */
1007        { 80,      1,   9,       0,     0xe0,        13}, /* tfgoal guessed */
1008        { 95,      1,   10,      7,     0xe0,        38}, /* tfgoal guessed */
1009        { 96,      1,   11,      0,     0xe0,        36}, /* tfgoal guessed */
1010        {  0,      0,   0,       0,        0,         0},
1011};
1012
1013static struct pll_entries {
1014        int xtal_freq;
1015        struct w100_pll_info *pll_table;
1016} w100_pll_tables[] = {
1017        { 12500000, &xtal_12500000[0] },
1018        { 14318000, &xtal_14318000[0] },
1019        { 16000000, &xtal_16000000[0] },
1020        { 0 },
1021};
1022
1023struct w100_pll_info *w100_get_xtal_table(unsigned int freq)
1024{
1025        struct pll_entries *pll_entry = w100_pll_tables;
1026
1027        do {
1028                if (freq == pll_entry->xtal_freq)
1029                        return pll_entry->pll_table;
1030                pll_entry++;
1031        } while (pll_entry->xtal_freq);
1032        return 0;
1033}
1034
1035
1036static unsigned int w100_get_testcount(unsigned int testclk_sel)
1037{
1038        union clk_test_cntl_u clk_test_cntl;
1039
1040        udelay(5);
1041
1042        /* Select the test clock source and reset */
1043        clk_test_cntl.f.start_check_freq = 0x0;
1044        clk_test_cntl.f.testclk_sel = testclk_sel;
1045        clk_test_cntl.f.tstcount_rst = 0x1; /* set reset */
1046        writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1047
1048        clk_test_cntl.f.tstcount_rst = 0x0; /* clear reset */
1049        writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1050
1051        /* Run clock test */
1052        clk_test_cntl.f.start_check_freq = 0x1;
1053        writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1054
1055        /* Give the test time to complete */
1056        udelay(20);
1057
1058        /* Return the result */
1059        clk_test_cntl.val = readl(remapped_regs + mmCLK_TEST_CNTL);
1060        clk_test_cntl.f.start_check_freq = 0x0;
1061        writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1062
1063        return clk_test_cntl.f.test_count;
1064}
1065
1066
1067static int w100_pll_adjust(struct w100_pll_info *pll)
1068{
1069        unsigned int tf80;
1070        unsigned int tf20;
1071
1072        /* Initial Settings */
1073        w100_pwr_state.pll_cntl.f.pll_pwdn = 0x0;     /* power down */
1074        w100_pwr_state.pll_cntl.f.pll_reset = 0x0;    /* not reset */
1075        w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x1;   /* Hi-Z */
1076        w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;      /* VCO gain = 0 */
1077        w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0;    /* VCO frequency range control = off */
1078        w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;  /* current offset inside VCO = 0 */
1079        w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
1080
1081        /* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V
1082         * therefore, commented out the following lines
1083         * tf80 meant tf100
1084         */
1085        do {
1086                /* set VCO input = 0.8 * VDD */
1087                w100_pwr_state.pll_cntl.f.pll_dactal = 0xd;
1088                writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1089
1090                tf80 = w100_get_testcount(TESTCLK_SRC_PLL);
1091                if (tf80 >= (pll->tfgoal)) {
1092                        /* set VCO input = 0.2 * VDD */
1093                        w100_pwr_state.pll_cntl.f.pll_dactal = 0x7;
1094                        writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1095
1096                        tf20 = w100_get_testcount(TESTCLK_SRC_PLL);
1097                        if (tf20 <= (pll->tfgoal))
1098                                return 1;  /* Success */
1099
1100                        if ((w100_pwr_state.pll_cntl.f.pll_vcofr == 0x0) &&
1101                                ((w100_pwr_state.pll_cntl.f.pll_pvg == 0x7) ||
1102                                (w100_pwr_state.pll_cntl.f.pll_ioffset == 0x0))) {
1103                                /* slow VCO config */
1104                                w100_pwr_state.pll_cntl.f.pll_vcofr = 0x1;
1105                                w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
1106                                w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1107                                continue;
1108                        }
1109                }
1110                if ((w100_pwr_state.pll_cntl.f.pll_ioffset) < 0x3) {
1111                        w100_pwr_state.pll_cntl.f.pll_ioffset += 0x1;
1112                } else if ((w100_pwr_state.pll_cntl.f.pll_pvg) < 0x7) {
1113                        w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1114                        w100_pwr_state.pll_cntl.f.pll_pvg += 0x1;
1115                } else {
1116                        return 0;  /* Error */
1117                }
1118        } while(1);
1119}
1120
1121
1122/*
1123 * w100_pll_calibration
1124 */
1125static int w100_pll_calibration(struct w100_pll_info *pll)
1126{
1127        int status;
1128
1129        status = w100_pll_adjust(pll);
1130
1131        /* PLL Reset And Lock */
1132        /* set VCO input = 0.5 * VDD */
1133        w100_pwr_state.pll_cntl.f.pll_dactal = 0xa;
1134        writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1135
1136        udelay(1);  /* reset time */
1137
1138        /* enable charge pump */
1139        w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;  /* normal */
1140        writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1141
1142        /* set VCO input = Hi-Z, disable DAC */
1143        w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;
1144        writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1145
1146        udelay(400);  /* lock time */
1147
1148        /* PLL locked */
1149
1150        return status;
1151}
1152
1153
1154static int w100_pll_set_clk(struct w100_pll_info *pll)
1155{
1156        int status;
1157
1158        if (w100_pwr_state.auto_mode == 1)  /* auto mode */
1159        {
1160                w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;  /* disable fast to normal */
1161                w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;  /* disable normal to fast */
1162                writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1163        }
1164
1165        /* Set system clock source to XTAL whilst adjusting the PLL! */
1166        w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
1167        writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1168
1169        w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = pll->M;
1170        w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = pll->N_int;
1171        w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = pll->N_fac;
1172        w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = pll->lock_time;
1173        writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
1174
1175        w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0;
1176        writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1177
1178        status = w100_pll_calibration(pll);
1179
1180        if (w100_pwr_state.auto_mode == 1)  /* auto mode */
1181        {
1182                w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x1;  /* reenable fast to normal */
1183                w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x1;  /* reenable normal to fast  */
1184                writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1185        }
1186        return status;
1187}
1188
1189/* freq = target frequency of the PLL */
1190static int w100_set_pll_freq(struct w100fb_par *par, unsigned int freq)
1191{
1192        struct w100_pll_info *pll = par->pll_table;
1193
1194        do {
1195                if (freq == pll->freq) {
1196                        return w100_pll_set_clk(pll);
1197                }
1198                pll++;
1199        } while(pll->freq);
1200        return 0;
1201}
1202
1203/* Set up an initial state.  Some values/fields set
1204   here will be overwritten. */
1205static void w100_pwm_setup(struct w100fb_par *par)
1206{
1207        w100_pwr_state.clk_pin_cntl.f.osc_en = 0x1;
1208        w100_pwr_state.clk_pin_cntl.f.osc_gain = 0x1f;
1209        w100_pwr_state.clk_pin_cntl.f.dont_use_xtalin = 0x0;
1210        w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x0;
1211        w100_pwr_state.clk_pin_cntl.f.xtalin_dbl_en = par->mach->xtal_dbl ? 1 : 0;
1212        w100_pwr_state.clk_pin_cntl.f.cg_debug = 0x0;
1213        writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL);
1214
1215        w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
1216        w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = 0x0;  /* Pfast = 1 */
1217        w100_pwr_state.sclk_cntl.f.sclk_clkon_hys = 0x3;
1218        w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0;  /* Pslow = 1 */
1219        w100_pwr_state.sclk_cntl.f.disp_cg_ok2switch_en = 0x0;
1220        w100_pwr_state.sclk_cntl.f.sclk_force_reg = 0x0;    /* Dynamic */
1221        w100_pwr_state.sclk_cntl.f.sclk_force_disp = 0x0;   /* Dynamic */
1222        w100_pwr_state.sclk_cntl.f.sclk_force_mc = 0x0;     /* Dynamic */
1223        w100_pwr_state.sclk_cntl.f.sclk_force_extmc = 0x0;  /* Dynamic */
1224        w100_pwr_state.sclk_cntl.f.sclk_force_cp = 0x0;     /* Dynamic */
1225        w100_pwr_state.sclk_cntl.f.sclk_force_e2 = 0x0;     /* Dynamic */
1226        w100_pwr_state.sclk_cntl.f.sclk_force_e3 = 0x0;     /* Dynamic */
1227        w100_pwr_state.sclk_cntl.f.sclk_force_idct = 0x0;   /* Dynamic */
1228        w100_pwr_state.sclk_cntl.f.sclk_force_bist = 0x0;   /* Dynamic */
1229        w100_pwr_state.sclk_cntl.f.busy_extend_cp = 0x0;
1230        w100_pwr_state.sclk_cntl.f.busy_extend_e2 = 0x0;
1231        w100_pwr_state.sclk_cntl.f.busy_extend_e3 = 0x0;
1232        w100_pwr_state.sclk_cntl.f.busy_extend_idct = 0x0;
1233        writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1234
1235        w100_pwr_state.pclk_cntl.f.pclk_src_sel = CLK_SRC_XTAL;
1236        w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1;    /* P = 2 */
1237        w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0;  /* Dynamic */
1238        writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
1239
1240        w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0;     /* M = 1 */
1241        w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0;  /* N = 1.0 */
1242        w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = 0x0;
1243        w100_pwr_state.pll_ref_fb_div.f.pll_reset_time = 0x5;
1244        w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = 0xff;
1245        writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
1246
1247        w100_pwr_state.pll_cntl.f.pll_pwdn = 0x1;
1248        w100_pwr_state.pll_cntl.f.pll_reset = 0x1;
1249        w100_pwr_state.pll_cntl.f.pll_pm_en = 0x0;
1250        w100_pwr_state.pll_cntl.f.pll_mode = 0x0;  /* uses VCO clock */
1251        w100_pwr_state.pll_cntl.f.pll_refclk_sel = 0x0;
1252        w100_pwr_state.pll_cntl.f.pll_fbclk_sel = 0x0;
1253        w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;
1254        w100_pwr_state.pll_cntl.f.pll_pcp = 0x4;
1255        w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
1256        w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0;
1257        w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1258        w100_pwr_state.pll_cntl.f.pll_pecc_mode = 0x0;
1259        w100_pwr_state.pll_cntl.f.pll_pecc_scon = 0x0;
1260        w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;  /* Hi-Z */
1261        w100_pwr_state.pll_cntl.f.pll_cp_clip = 0x3;
1262        w100_pwr_state.pll_cntl.f.pll_conf = 0x2;
1263        w100_pwr_state.pll_cntl.f.pll_mbctrl = 0x2;
1264        w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
1265        writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1266
1267        w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x0;
1268        w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1;  /* normal mode (0, 1, 3) */
1269        w100_pwr_state.pwrmgt_cntl.f.pwm_wakeup_cond = 0x0;
1270        w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;
1271        w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;
1272        w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1;  /* PM4,ENG */
1273        w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1;  /* PM4,ENG */
1274        w100_pwr_state.pwrmgt_cntl.f.pwm_idle_timer = 0xFF;
1275        w100_pwr_state.pwrmgt_cntl.f.pwm_busy_timer = 0xFF;
1276        writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1277
1278        w100_pwr_state.auto_mode = 0;  /* manual mode */
1279}
1280
1281
1282/*
1283 * Setup the w100 clocks for the specified mode
1284 */
1285static void w100_init_clocks(struct w100fb_par *par)
1286{
1287        struct w100_mode *mode = par->mode;
1288
1289        if (mode->pixclk_src == CLK_SRC_PLL || mode->sysclk_src == CLK_SRC_PLL)
1290                w100_set_pll_freq(par, (par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq);
1291
1292        w100_pwr_state.sclk_cntl.f.sclk_src_sel = mode->sysclk_src;
1293        w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = mode->sysclk_divider;
1294        w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = mode->sysclk_divider;
1295        writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1296}
1297
1298static void w100_init_lcd(struct w100fb_par *par)
1299{
1300        u32 temp32;
1301        struct w100_mode *mode = par->mode;
1302        struct w100_gen_regs *regs = par->mach->regs;
1303        union active_h_disp_u active_h_disp;
1304        union active_v_disp_u active_v_disp;
1305        union graphic_h_disp_u graphic_h_disp;
1306        union graphic_v_disp_u graphic_v_disp;
1307        union crtc_total_u crtc_total;
1308
1309        /* w3200 doesn't like undefined bits being set so zero register values first */
1310
1311        active_h_disp.val = 0;
1312        active_h_disp.f.active_h_start=mode->left_margin;
1313        active_h_disp.f.active_h_end=mode->left_margin + mode->xres;
1314        writel(active_h_disp.val, remapped_regs + mmACTIVE_H_DISP);
1315
1316        active_v_disp.val = 0;
1317        active_v_disp.f.active_v_start=mode->upper_margin;
1318        active_v_disp.f.active_v_end=mode->upper_margin + mode->yres;
1319        writel(active_v_disp.val, remapped_regs + mmACTIVE_V_DISP);
1320
1321        graphic_h_disp.val = 0;
1322        graphic_h_disp.f.graphic_h_start=mode->left_margin;
1323        graphic_h_disp.f.graphic_h_end=mode->left_margin + mode->xres;
1324        writel(graphic_h_disp.val, remapped_regs + mmGRAPHIC_H_DISP);
1325
1326        graphic_v_disp.val = 0;
1327        graphic_v_disp.f.graphic_v_start=mode->upper_margin;
1328        graphic_v_disp.f.graphic_v_end=mode->upper_margin + mode->yres;
1329        writel(graphic_v_disp.val, remapped_regs + mmGRAPHIC_V_DISP);
1330
1331        crtc_total.val = 0;
1332        crtc_total.f.crtc_h_total=mode->left_margin  + mode->xres + mode->right_margin;
1333        crtc_total.f.crtc_v_total=mode->upper_margin + mode->yres + mode->lower_margin;
1334        writel(crtc_total.val, remapped_regs + mmCRTC_TOTAL);
1335
1336        writel(mode->crtc_ss, remapped_regs + mmCRTC_SS);
1337        writel(mode->crtc_ls, remapped_regs + mmCRTC_LS);
1338        writel(mode->crtc_gs, remapped_regs + mmCRTC_GS);
1339        writel(mode->crtc_vpos_gs, remapped_regs + mmCRTC_VPOS_GS);
1340        writel(mode->crtc_rev, remapped_regs + mmCRTC_REV);
1341        writel(mode->crtc_dclk, remapped_regs + mmCRTC_DCLK);
1342        writel(mode->crtc_gclk, remapped_regs + mmCRTC_GCLK);
1343        writel(mode->crtc_goe, remapped_regs + mmCRTC_GOE);
1344        writel(mode->crtc_ps1_active, remapped_regs + mmCRTC_PS1_ACTIVE);
1345
1346        writel(regs->lcd_format, remapped_regs + mmLCD_FORMAT);
1347        writel(regs->lcdd_cntl1, remapped_regs + mmLCDD_CNTL1);
1348        writel(regs->lcdd_cntl2, remapped_regs + mmLCDD_CNTL2);
1349        writel(regs->genlcd_cntl1, remapped_regs + mmGENLCD_CNTL1);
1350        writel(regs->genlcd_cntl2, remapped_regs + mmGENLCD_CNTL2);
1351        writel(regs->genlcd_cntl3, remapped_regs + mmGENLCD_CNTL3);
1352
1353        writel(0x00000000, remapped_regs + mmCRTC_FRAME);
1354        writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS);
1355        writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT);
1356        writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR);
1357
1358        /* Hack for overlay in ext memory */
1359        temp32 = readl(remapped_regs + mmDISP_DEBUG2);
1360        temp32 |= 0xc0000000;
1361        writel(temp32, remapped_regs + mmDISP_DEBUG2);
1362}
1363
1364
1365static void w100_setup_memory(struct w100fb_par *par)
1366{
1367        union mc_ext_mem_location_u extmem_location;
1368        union mc_fb_location_u intmem_location;
1369        struct w100_mem_info *mem = par->mach->mem;
1370        struct w100_bm_mem_info *bm_mem = par->mach->bm_mem;
1371
1372        if (!par->extmem_active) {
1373                w100_suspend(W100_SUSPEND_EXTMEM);
1374
1375                /* Map Internal Memory at FB Base */
1376                intmem_location.f.mc_fb_start = W100_FB_BASE >> 8;
1377                intmem_location.f.mc_fb_top = (W100_FB_BASE+MEM_INT_SIZE) >> 8;
1378                writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
1379
1380                /* Unmap External Memory - value is *probably* irrelevant but may have meaning
1381                   to acceleration libraries */
1382                extmem_location.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8;
1383                extmem_location.f.mc_ext_mem_top = (MEM_EXT_BASE_VALUE-1) >> 8;
1384                writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
1385        } else {
1386                /* Map Internal Memory to its default location */
1387                intmem_location.f.mc_fb_start = MEM_INT_BASE_VALUE >> 8;
1388                intmem_location.f.mc_fb_top = (MEM_INT_BASE_VALUE+MEM_INT_SIZE) >> 8;
1389                writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
1390
1391                /* Map External Memory at FB Base */
1392                extmem_location.f.mc_ext_mem_start = W100_FB_BASE >> 8;
1393                extmem_location.f.mc_ext_mem_top = (W100_FB_BASE+par->mach->mem->size) >> 8;
1394                writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
1395
1396                writel(0x00007800, remapped_regs + mmMC_BIST_CTRL);
1397                writel(mem->ext_cntl, remapped_regs + mmMEM_EXT_CNTL);
1398                writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
1399                udelay(100);
1400                writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
1401                udelay(100);
1402                writel(mem->sdram_mode_reg, remapped_regs + mmMEM_SDRAM_MODE_REG);
1403                udelay(100);
1404                writel(mem->ext_timing_cntl, remapped_regs + mmMEM_EXT_TIMING_CNTL);
1405                writel(mem->io_cntl, remapped_regs + mmMEM_IO_CNTL);
1406                if (bm_mem) {
1407                        writel(bm_mem->ext_mem_bw, remapped_regs + mmBM_EXT_MEM_BANDWIDTH);
1408                        writel(bm_mem->offset, remapped_regs + mmBM_OFFSET);
1409                        writel(bm_mem->ext_timing_ctl, remapped_regs + mmBM_MEM_EXT_TIMING_CNTL);
1410                        writel(bm_mem->ext_cntl, remapped_regs + mmBM_MEM_EXT_CNTL);
1411                        writel(bm_mem->mode_reg, remapped_regs + mmBM_MEM_MODE_REG);
1412                        writel(bm_mem->io_cntl, remapped_regs + mmBM_MEM_IO_CNTL);
1413                        writel(bm_mem->config, remapped_regs + mmBM_CONFIG);
1414                }
1415        }
1416}
1417
1418static void w100_set_dispregs(struct w100fb_par *par)
1419{
1420        unsigned long rot=0, divider, offset=0;
1421        union graphic_ctrl_u graphic_ctrl;
1422
1423        /* See if the mode has been rotated */
1424        if (par->xres == par->mode->xres) {
1425                if (par->flip) {
1426                        rot=3; /* 180 degree */
1427                        offset=(par->xres * par->yres) - 1;
1428                } /* else 0 degree */
1429                divider = par->mode->pixclk_divider;
1430        } else {
1431                if (par->flip) {
1432                        rot=2; /* 270 degree */
1433                        offset=par->xres - 1;
1434                } else {
1435                        rot=1; /* 90 degree */
1436                        offset=par->xres * (par->yres - 1);
1437                }
1438                divider = par->mode->pixclk_divider_rotated;
1439        }
1440
1441        graphic_ctrl.val = 0; /* w32xx doesn't like undefined bits */
1442        switch (par->chip_id) {
1443                case CHIP_ID_W100:
1444                        graphic_ctrl.f_w100.color_depth=6;
1445                        graphic_ctrl.f_w100.en_crtc=1;
1446                        graphic_ctrl.f_w100.en_graphic_req=1;
1447                        graphic_ctrl.f_w100.en_graphic_crtc=1;
1448                        graphic_ctrl.f_w100.lcd_pclk_on=1;
1449                        graphic_ctrl.f_w100.lcd_sclk_on=1;
1450                        graphic_ctrl.f_w100.low_power_on=0;
1451                        graphic_ctrl.f_w100.req_freq=0;
1452                        graphic_ctrl.f_w100.portrait_mode=rot;
1453
1454                        /* Zaurus needs this */
1455                        switch(par->xres) {
1456                                case 240:
1457                                case 320:
1458                                default:
1459                                        graphic_ctrl.f_w100.total_req_graphic=0xa0;
1460                                        break;
1461                                case 480:
1462                                case 640:
1463                                        switch(rot) {
1464                                                case 0:  /* 0 */
1465                                                case 3:  /* 180 */
1466                                                        graphic_ctrl.f_w100.low_power_on=1;
1467                                                        graphic_ctrl.f_w100.req_freq=5;
1468                                                break;
1469                                                case 1:  /* 90 */
1470                                                case 2:  /* 270 */
1471                                                        graphic_ctrl.f_w100.req_freq=4;
1472                                                        break;
1473                                                default:
1474                                                        break;
1475                                        }
1476                                        graphic_ctrl.f_w100.total_req_graphic=0xf0;
1477                                        break;
1478                        }
1479                        break;
1480                case CHIP_ID_W3200:
1481                case CHIP_ID_W3220:
1482                        graphic_ctrl.f_w32xx.color_depth=6;
1483                        graphic_ctrl.f_w32xx.en_crtc=1;
1484                        graphic_ctrl.f_w32xx.en_graphic_req=1;
1485                        graphic_ctrl.f_w32xx.en_graphic_crtc=1;
1486                        graphic_ctrl.f_w32xx.lcd_pclk_on=1;
1487                        graphic_ctrl.f_w32xx.lcd_sclk_on=1;
1488                        graphic_ctrl.f_w32xx.low_power_on=0;
1489                        graphic_ctrl.f_w32xx.req_freq=0;
1490                        graphic_ctrl.f_w32xx.total_req_graphic=par->mode->xres >> 1; /* panel xres, not mode */
1491                        graphic_ctrl.f_w32xx.portrait_mode=rot;
1492                        break;
1493        }
1494
1495        /* Set the pixel clock source and divider */
1496        w100_pwr_state.pclk_cntl.f.pclk_src_sel = par->mode->pixclk_src;
1497        w100_pwr_state.pclk_cntl.f.pclk_post_div = divider;
1498        writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
1499
1500        writel(graphic_ctrl.val, remapped_regs + mmGRAPHIC_CTRL);
1501        writel(W100_FB_BASE + ((offset * BITS_PER_PIXEL/8)&~0x03UL), remapped_regs + mmGRAPHIC_OFFSET);
1502        writel((par->xres*BITS_PER_PIXEL/8), remapped_regs + mmGRAPHIC_PITCH);
1503}
1504
1505
1506/*
1507 * Work out how long the sync pulse lasts
1508 * Value is 1/(time in seconds)
1509 */
1510static void calc_hsync(struct w100fb_par *par)
1511{
1512        unsigned long hsync;
1513        struct w100_mode *mode = par->mode;
1514        union crtc_ss_u crtc_ss;
1515
1516        if (mode->pixclk_src == CLK_SRC_XTAL)
1517                hsync=par->mach->xtal_freq;
1518        else
1519                hsync=((par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq)*100000;
1520
1521        hsync /= (w100_pwr_state.pclk_cntl.f.pclk_post_div + 1);
1522
1523        crtc_ss.val = readl(remapped_regs + mmCRTC_SS);
1524        if (crtc_ss.val)
1525                par->hsync_len = hsync / (crtc_ss.f.ss_end-crtc_ss.f.ss_start);
1526        else
1527                par->hsync_len = 0;
1528}
1529
1530static void w100_suspend(u32 mode)
1531{
1532        u32 val;
1533
1534        writel(0x7FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION);
1535        writel(0x00FF0000, remapped_regs + mmMC_PERF_MON_CNTL);
1536
1537        val = readl(remapped_regs + mmMEM_EXT_TIMING_CNTL);
1538        val &= ~(0x00100000);  /* bit20=0 */
1539        val |= 0xFF000000;     /* bit31:24=0xff */
1540        writel(val, remapped_regs + mmMEM_EXT_TIMING_CNTL);
1541
1542        val = readl(remapped_regs + mmMEM_EXT_CNTL);
1543        val &= ~(0x00040000);  /* bit18=0 */
1544        val |= 0x00080000;     /* bit19=1 */
1545        writel(val, remapped_regs + mmMEM_EXT_CNTL);
1546
1547        udelay(1);  /* wait 1us */
1548
1549        if (mode == W100_SUSPEND_EXTMEM) {
1550                /* CKE: Tri-State */
1551                val = readl(remapped_regs + mmMEM_EXT_CNTL);
1552                val |= 0x40000000;  /* bit30=1 */
1553                writel(val, remapped_regs + mmMEM_EXT_CNTL);
1554
1555                /* CLK: Stop */
1556                val = readl(remapped_regs + mmMEM_EXT_CNTL);
1557                val &= ~(0x00000001);  /* bit0=0 */
1558                writel(val, remapped_regs + mmMEM_EXT_CNTL);
1559        } else {
1560                writel(0x00000000, remapped_regs + mmSCLK_CNTL);
1561                writel(0x000000BF, remapped_regs + mmCLK_PIN_CNTL);
1562                writel(0x00000015, remapped_regs + mmPWRMGT_CNTL);
1563
1564                udelay(5);
1565
1566                val = readl(remapped_regs + mmPLL_CNTL);
1567                val |= 0x00000004;  /* bit2=1 */
1568                writel(val, remapped_regs + mmPLL_CNTL);
1569
1570                writel(0x00000000, remapped_regs + mmLCDD_CNTL1);
1571                writel(0x00000000, remapped_regs + mmLCDD_CNTL2);
1572                writel(0x00000000, remapped_regs + mmGENLCD_CNTL1);
1573                writel(0x00000000, remapped_regs + mmGENLCD_CNTL2);
1574                writel(0x00000000, remapped_regs + mmGENLCD_CNTL3);
1575
1576                val = readl(remapped_regs + mmMEM_EXT_CNTL);
1577                val |= 0xF0000000;
1578                val &= ~(0x00000001);
1579                writel(val, remapped_regs + mmMEM_EXT_CNTL);
1580
1581                writel(0x0000001d, remapped_regs + mmPWRMGT_CNTL);
1582        }
1583}
1584
1585static void w100_vsync(void)
1586{
1587        u32 tmp;
1588        int timeout = 30000;  /* VSync timeout = 30[ms] > 16.8[ms] */
1589
1590        tmp = readl(remapped_regs + mmACTIVE_V_DISP);
1591
1592        /* set vline pos  */
1593        writel((tmp >> 16) & 0x3ff, remapped_regs + mmDISP_INT_CNTL);
1594
1595        /* disable vline irq */
1596        tmp = readl(remapped_regs + mmGEN_INT_CNTL);
1597
1598        tmp &= ~0x00000002;
1599        writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1600
1601        /* clear vline irq status */
1602        writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1603
1604        /* enable vline irq */
1605        writel((tmp | 0x00000002), remapped_regs + mmGEN_INT_CNTL);
1606
1607        /* clear vline irq status */
1608        writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1609
1610        while(timeout > 0) {
1611                if (readl(remapped_regs + mmGEN_INT_STATUS) & 0x00000002)
1612                        break;
1613                udelay(1);
1614                timeout--;
1615        }
1616
1617        /* disable vline irq */
1618        writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1619
1620        /* clear vline irq status */
1621        writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1622}
1623
1624static struct platform_driver w100fb_driver = {
1625        .probe          = w100fb_probe,
1626        .remove         = w100fb_remove,
1627        .suspend        = w100fb_suspend,
1628        .resume         = w100fb_resume,
1629        .driver         = {
1630                .name   = "w100fb",
1631        },
1632};
1633
1634module_platform_driver(w100fb_driver);
1635
1636MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
1637MODULE_LICENSE("GPL");
1638