root/drivers/video/fbdev/w100fb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. flip_show
  2. flip_store
  3. w100fb_reg_read
  4. w100fb_reg_write
  5. fastpllclk_show
  6. fastpllclk_store
  7. w100fb_get_hsynclen
  8. w100fb_clear_screen
  9. w100fb_setcolreg
  10. w100fb_blank
  11. w100_fifo_wait
  12. w100fb_sync
  13. w100_init_graphic_engine
  14. w100fb_fillrect
  15. w100fb_copyarea
  16. w100fb_activate_var
  17. w100fb_get_mode
  18. w100fb_check_var
  19. w100fb_set_par
  20. w100fb_save_vidmem
  21. w100fb_restore_vidmem
  22. w100fb_suspend
  23. w100fb_resume
  24. w100fb_probe
  25. w100fb_remove
  26. w100_soft_reset
  27. w100_update_disable
  28. w100_update_enable
  29. w100fb_gpio_read
  30. w100fb_gpio_write
  31. w100_hw_init
  32. w100_get_xtal_table
  33. w100_get_testcount
  34. w100_pll_adjust
  35. w100_pll_calibration
  36. w100_pll_set_clk
  37. w100_set_pll_freq
  38. w100_pwm_setup
  39. w100_init_clocks
  40. w100_init_lcd
  41. w100_setup_memory
  42. w100_set_dispregs
  43. calc_hsync
  44. w100_suspend
  45. w100_vsync

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

/* [<][>][^][v][top][bottom][index][help] */