Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * linux/drivers/video/w100fb.c
0004  *
0005  * Frame Buffer Device for ATI Imageon w100 (Wallaby)
0006  *
0007  * Copyright (C) 2002, ATI Corp.
0008  * Copyright (C) 2004-2006 Richard Purdie
0009  * Copyright (c) 2005 Ian Molton
0010  * Copyright (c) 2006 Alberto Mardegan
0011  *
0012  * Rewritten for 2.6 by Richard Purdie <rpurdie@rpsys.net>
0013  *
0014  * Generic platform support by Ian Molton <spyro@f2s.com>
0015  * and Richard Purdie <rpurdie@rpsys.net>
0016  *
0017  * w32xx support by Ian Molton
0018  *
0019  * Hardware acceleration support by Alberto Mardegan
0020  * <mardy@users.sourceforge.net>
0021  */
0022 
0023 #include <linux/delay.h>
0024 #include <linux/fb.h>
0025 #include <linux/init.h>
0026 #include <linux/kernel.h>
0027 #include <linux/mm.h>
0028 #include <linux/platform_device.h>
0029 #include <linux/slab.h>
0030 #include <linux/string.h>
0031 #include <linux/vmalloc.h>
0032 #include <linux/module.h>
0033 #include <asm/io.h>
0034 #include <linux/uaccess.h>
0035 #include <video/w100fb.h>
0036 #include "w100fb.h"
0037 
0038 /*
0039  * Prototypes
0040  */
0041 static void w100_suspend(u32 mode);
0042 static void w100_vsync(void);
0043 static void w100_hw_init(struct w100fb_par*);
0044 static void w100_pwm_setup(struct w100fb_par*);
0045 static void w100_init_clocks(struct w100fb_par*);
0046 static void w100_setup_memory(struct w100fb_par*);
0047 static void w100_init_lcd(struct w100fb_par*);
0048 static void w100_set_dispregs(struct w100fb_par*);
0049 static void w100_update_enable(void);
0050 static void w100_update_disable(void);
0051 static void calc_hsync(struct w100fb_par *par);
0052 static void w100_init_graphic_engine(struct w100fb_par *par);
0053 struct w100_pll_info *w100_get_xtal_table(unsigned int freq);
0054 
0055 /* Pseudo palette size */
0056 #define MAX_PALETTES      16
0057 
0058 #define W100_SUSPEND_EXTMEM 0
0059 #define W100_SUSPEND_ALL    1
0060 
0061 #define BITS_PER_PIXEL    16
0062 
0063 /* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */
0064 static void __iomem *remapped_base;
0065 static void __iomem *remapped_regs;
0066 static void __iomem *remapped_fbuf;
0067 
0068 #define REMAPPED_FB_LEN   0x15ffff
0069 
0070 /* This is the offset in the w100's address space we map the current
0071    framebuffer memory to. We use the position of external memory as
0072    we can remap internal memory to there if external isn't present. */
0073 #define W100_FB_BASE MEM_EXT_BASE_VALUE
0074 
0075 
0076 /*
0077  * Sysfs functions
0078  */
0079 static ssize_t flip_show(struct device *dev, struct device_attribute *attr, char *buf)
0080 {
0081     struct fb_info *info = dev_get_drvdata(dev);
0082     struct w100fb_par *par=info->par;
0083 
0084     return sprintf(buf, "%d\n",par->flip);
0085 }
0086 
0087 static ssize_t flip_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
0088 {
0089     unsigned int flip;
0090     struct fb_info *info = dev_get_drvdata(dev);
0091     struct w100fb_par *par=info->par;
0092 
0093     flip = simple_strtoul(buf, NULL, 10);
0094 
0095     if (flip > 0)
0096         par->flip = 1;
0097     else
0098         par->flip = 0;
0099 
0100     w100_update_disable();
0101     w100_set_dispregs(par);
0102     w100_update_enable();
0103 
0104     calc_hsync(par);
0105 
0106     return count;
0107 }
0108 
0109 static DEVICE_ATTR_RW(flip);
0110 
0111 static ssize_t w100fb_reg_read(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
0112 {
0113     unsigned long regs, param;
0114     regs = simple_strtoul(buf, NULL, 16);
0115     param = readl(remapped_regs + regs);
0116     printk("Read Register 0x%08lX: 0x%08lX\n", regs, param);
0117     return count;
0118 }
0119 
0120 static DEVICE_ATTR(reg_read, 0200, NULL, w100fb_reg_read);
0121 
0122 static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
0123 {
0124     unsigned long regs, param;
0125     sscanf(buf, "%lx %lx", &regs, &param);
0126 
0127     if (regs <= 0x2000) {
0128         printk("Write Register 0x%08lX: 0x%08lX\n", regs, param);
0129         writel(param, remapped_regs + regs);
0130     }
0131 
0132     return count;
0133 }
0134 
0135 static DEVICE_ATTR(reg_write, 0200, NULL, w100fb_reg_write);
0136 
0137 
0138 static ssize_t fastpllclk_show(struct device *dev, struct device_attribute *attr, char *buf)
0139 {
0140     struct fb_info *info = dev_get_drvdata(dev);
0141     struct w100fb_par *par=info->par;
0142 
0143     return sprintf(buf, "%d\n",par->fastpll_mode);
0144 }
0145 
0146 static ssize_t fastpllclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
0147 {
0148     struct fb_info *info = dev_get_drvdata(dev);
0149     struct w100fb_par *par=info->par;
0150 
0151     if (simple_strtoul(buf, NULL, 10) > 0) {
0152         par->fastpll_mode=1;
0153         printk("w100fb: Using fast system clock (if possible)\n");
0154     } else {
0155         par->fastpll_mode=0;
0156         printk("w100fb: Using normal system clock\n");
0157     }
0158 
0159     w100_init_clocks(par);
0160     calc_hsync(par);
0161 
0162     return count;
0163 }
0164 
0165 static DEVICE_ATTR_RW(fastpllclk);
0166 
0167 static struct attribute *w100fb_attrs[] = {
0168     &dev_attr_fastpllclk.attr,
0169     &dev_attr_reg_read.attr,
0170     &dev_attr_reg_write.attr,
0171     &dev_attr_flip.attr,
0172     NULL,
0173 };
0174 ATTRIBUTE_GROUPS(w100fb);
0175 
0176 /*
0177  * Some touchscreens need hsync information from the video driver to
0178  * function correctly. We export it here.
0179  */
0180 unsigned long w100fb_get_hsynclen(struct device *dev)
0181 {
0182     struct fb_info *info = dev_get_drvdata(dev);
0183     struct w100fb_par *par=info->par;
0184 
0185     /* If display is blanked/suspended, hsync isn't active */
0186     if (par->blanked)
0187         return 0;
0188     else
0189         return par->hsync_len;
0190 }
0191 EXPORT_SYMBOL(w100fb_get_hsynclen);
0192 
0193 static void w100fb_clear_screen(struct w100fb_par *par)
0194 {
0195     memset_io(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), 0, (par->xres * par->yres * BITS_PER_PIXEL/8));
0196 }
0197 
0198 
0199 /*
0200  * Set a palette value from rgb components
0201  */
0202 static int w100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
0203                  u_int trans, struct fb_info *info)
0204 {
0205     unsigned int val;
0206     int ret = 1;
0207 
0208     /*
0209      * If greyscale is true, then we convert the RGB value
0210      * to greyscale no matter what visual we are using.
0211      */
0212     if (info->var.grayscale)
0213         red = green = blue = (19595 * red + 38470 * green + 7471 * blue) >> 16;
0214 
0215     /*
0216      * 16-bit True Colour.  We encode the RGB value
0217      * according to the RGB bitfield information.
0218      */
0219     if (regno < MAX_PALETTES) {
0220         u32 *pal = info->pseudo_palette;
0221 
0222         val = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
0223         pal[regno] = val;
0224         ret = 0;
0225     }
0226     return ret;
0227 }
0228 
0229 
0230 /*
0231  * Blank the display based on value in blank_mode
0232  */
0233 static int w100fb_blank(int blank_mode, struct fb_info *info)
0234 {
0235     struct w100fb_par *par = info->par;
0236     struct w100_tg_info *tg = par->mach->tg;
0237 
0238     switch(blank_mode) {
0239 
0240     case FB_BLANK_NORMAL:         /* Normal blanking */
0241     case FB_BLANK_VSYNC_SUSPEND:  /* VESA blank (vsync off) */
0242     case FB_BLANK_HSYNC_SUSPEND:  /* VESA blank (hsync off) */
0243     case FB_BLANK_POWERDOWN:      /* Poweroff */
0244         if (par->blanked == 0) {
0245             if(tg && tg->suspend)
0246                 tg->suspend(par);
0247             par->blanked = 1;
0248         }
0249         break;
0250 
0251     case FB_BLANK_UNBLANK: /* Unblanking */
0252         if (par->blanked != 0) {
0253             if(tg && tg->resume)
0254                 tg->resume(par);
0255             par->blanked = 0;
0256         }
0257         break;
0258     }
0259     return 0;
0260 }
0261 
0262 
0263 static void w100_fifo_wait(int entries)
0264 {
0265     union rbbm_status_u status;
0266     int i;
0267 
0268     for (i = 0; i < 2000000; i++) {
0269         status.val = readl(remapped_regs + mmRBBM_STATUS);
0270         if (status.f.cmdfifo_avail >= entries)
0271             return;
0272         udelay(1);
0273     }
0274     printk(KERN_ERR "w100fb: FIFO Timeout!\n");
0275 }
0276 
0277 
0278 static int w100fb_sync(struct fb_info *info)
0279 {
0280     union rbbm_status_u status;
0281     int i;
0282 
0283     for (i = 0; i < 2000000; i++) {
0284         status.val = readl(remapped_regs + mmRBBM_STATUS);
0285         if (!status.f.gui_active)
0286             return 0;
0287         udelay(1);
0288     }
0289     printk(KERN_ERR "w100fb: Graphic engine timeout!\n");
0290     return -EBUSY;
0291 }
0292 
0293 
0294 static void w100_init_graphic_engine(struct w100fb_par *par)
0295 {
0296     union dp_gui_master_cntl_u gmc;
0297     union dp_mix_u dp_mix;
0298     union dp_datatype_u dp_datatype;
0299     union dp_cntl_u dp_cntl;
0300 
0301     w100_fifo_wait(4);
0302     writel(W100_FB_BASE, remapped_regs + mmDST_OFFSET);
0303     writel(par->xres, remapped_regs + mmDST_PITCH);
0304     writel(W100_FB_BASE, remapped_regs + mmSRC_OFFSET);
0305     writel(par->xres, remapped_regs + mmSRC_PITCH);
0306 
0307     w100_fifo_wait(3);
0308     writel(0, remapped_regs + mmSC_TOP_LEFT);
0309     writel((par->yres << 16) | par->xres, remapped_regs + mmSC_BOTTOM_RIGHT);
0310     writel(0x1fff1fff, remapped_regs + mmSRC_SC_BOTTOM_RIGHT);
0311 
0312     w100_fifo_wait(4);
0313     dp_cntl.val = 0;
0314     dp_cntl.f.dst_x_dir = 1;
0315     dp_cntl.f.dst_y_dir = 1;
0316     dp_cntl.f.src_x_dir = 1;
0317     dp_cntl.f.src_y_dir = 1;
0318     dp_cntl.f.dst_major_x = 1;
0319     dp_cntl.f.src_major_x = 1;
0320     writel(dp_cntl.val, remapped_regs + mmDP_CNTL);
0321 
0322     gmc.val = 0;
0323     gmc.f.gmc_src_pitch_offset_cntl = 1;
0324     gmc.f.gmc_dst_pitch_offset_cntl = 1;
0325     gmc.f.gmc_src_clipping = 1;
0326     gmc.f.gmc_dst_clipping = 1;
0327     gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
0328     gmc.f.gmc_dst_datatype = 3; /* from DstType_16Bpp_444 */
0329     gmc.f.gmc_src_datatype = SRC_DATATYPE_EQU_DST;
0330     gmc.f.gmc_byte_pix_order = 1;
0331     gmc.f.gmc_default_sel = 0;
0332     gmc.f.gmc_rop3 = ROP3_SRCCOPY;
0333     gmc.f.gmc_dp_src_source = DP_SRC_MEM_RECTANGULAR;
0334     gmc.f.gmc_clr_cmp_fcn_dis = 1;
0335     gmc.f.gmc_wr_msk_dis = 1;
0336     gmc.f.gmc_dp_op = DP_OP_ROP;
0337     writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
0338 
0339     dp_datatype.val = dp_mix.val = 0;
0340     dp_datatype.f.dp_dst_datatype = gmc.f.gmc_dst_datatype;
0341     dp_datatype.f.dp_brush_datatype = gmc.f.gmc_brush_datatype;
0342     dp_datatype.f.dp_src2_type = 0;
0343     dp_datatype.f.dp_src2_datatype = gmc.f.gmc_src_datatype;
0344     dp_datatype.f.dp_src_datatype = gmc.f.gmc_src_datatype;
0345     dp_datatype.f.dp_byte_pix_order = gmc.f.gmc_byte_pix_order;
0346     writel(dp_datatype.val, remapped_regs + mmDP_DATATYPE);
0347 
0348     dp_mix.f.dp_src_source = gmc.f.gmc_dp_src_source;
0349     dp_mix.f.dp_src2_source = 1;
0350     dp_mix.f.dp_rop3 = gmc.f.gmc_rop3;
0351     dp_mix.f.dp_op = gmc.f.gmc_dp_op;
0352     writel(dp_mix.val, remapped_regs + mmDP_MIX);
0353 }
0354 
0355 
0356 static void w100fb_fillrect(struct fb_info *info,
0357                             const struct fb_fillrect *rect)
0358 {
0359     union dp_gui_master_cntl_u gmc;
0360 
0361     if (info->state != FBINFO_STATE_RUNNING)
0362         return;
0363     if (info->flags & FBINFO_HWACCEL_DISABLED) {
0364         cfb_fillrect(info, rect);
0365         return;
0366     }
0367 
0368     gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
0369     gmc.f.gmc_rop3 = ROP3_PATCOPY;
0370     gmc.f.gmc_brush_datatype = GMC_BRUSH_SOLID_COLOR;
0371     w100_fifo_wait(2);
0372     writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
0373     writel(rect->color, remapped_regs + mmDP_BRUSH_FRGD_CLR);
0374 
0375     w100_fifo_wait(2);
0376     writel((rect->dy << 16) | (rect->dx & 0xffff), remapped_regs + mmDST_Y_X);
0377     writel((rect->width << 16) | (rect->height & 0xffff),
0378            remapped_regs + mmDST_WIDTH_HEIGHT);
0379 }
0380 
0381 
0382 static void w100fb_copyarea(struct fb_info *info,
0383                             const struct fb_copyarea *area)
0384 {
0385     u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
0386     u32 h = area->height, w = area->width;
0387     union dp_gui_master_cntl_u gmc;
0388 
0389     if (info->state != FBINFO_STATE_RUNNING)
0390         return;
0391     if (info->flags & FBINFO_HWACCEL_DISABLED) {
0392         cfb_copyarea(info, area);
0393         return;
0394     }
0395 
0396     gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
0397     gmc.f.gmc_rop3 = ROP3_SRCCOPY;
0398     gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
0399     w100_fifo_wait(1);
0400     writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
0401 
0402     w100_fifo_wait(3);
0403     writel((sy << 16) | (sx & 0xffff), remapped_regs + mmSRC_Y_X);
0404     writel((dy << 16) | (dx & 0xffff), remapped_regs + mmDST_Y_X);
0405     writel((w << 16) | (h & 0xffff), remapped_regs + mmDST_WIDTH_HEIGHT);
0406 }
0407 
0408 
0409 /*
0410  *  Change the resolution by calling the appropriate hardware functions
0411  */
0412 static void w100fb_activate_var(struct w100fb_par *par)
0413 {
0414     struct w100_tg_info *tg = par->mach->tg;
0415 
0416     w100_pwm_setup(par);
0417     w100_setup_memory(par);
0418     w100_init_clocks(par);
0419     w100fb_clear_screen(par);
0420     w100_vsync();
0421 
0422     w100_update_disable();
0423     w100_init_lcd(par);
0424     w100_set_dispregs(par);
0425     w100_update_enable();
0426     w100_init_graphic_engine(par);
0427 
0428     calc_hsync(par);
0429 
0430     if (!par->blanked && tg && tg->change)
0431         tg->change(par);
0432 }
0433 
0434 
0435 /* Select the smallest mode that allows the desired resolution to be
0436  * displayed. If desired, the x and y parameters can be rounded up to
0437  * match the selected mode.
0438  */
0439 static struct w100_mode *w100fb_get_mode(struct w100fb_par *par, unsigned int *x, unsigned int *y, int saveval)
0440 {
0441     struct w100_mode *mode = NULL;
0442     struct w100_mode *modelist = par->mach->modelist;
0443     unsigned int best_x = 0xffffffff, best_y = 0xffffffff;
0444     unsigned int i;
0445 
0446     for (i = 0 ; i < par->mach->num_modes ; i++) {
0447         if (modelist[i].xres >= *x && modelist[i].yres >= *y &&
0448                 modelist[i].xres < best_x && modelist[i].yres < best_y) {
0449             best_x = modelist[i].xres;
0450             best_y = modelist[i].yres;
0451             mode = &modelist[i];
0452         } else if(modelist[i].xres >= *y && modelist[i].yres >= *x &&
0453                 modelist[i].xres < best_y && modelist[i].yres < best_x) {
0454             best_x = modelist[i].yres;
0455             best_y = modelist[i].xres;
0456             mode = &modelist[i];
0457         }
0458     }
0459 
0460     if (mode && saveval) {
0461         *x = best_x;
0462         *y = best_y;
0463     }
0464 
0465     return mode;
0466 }
0467 
0468 
0469 /*
0470  *  w100fb_check_var():
0471  *  Get the video params out of 'var'. If a value doesn't fit, round it up,
0472  *  if it's too big, return -EINVAL.
0473  */
0474 static int w100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
0475 {
0476     struct w100fb_par *par=info->par;
0477 
0478     if(!w100fb_get_mode(par, &var->xres, &var->yres, 1))
0479         return -EINVAL;
0480 
0481     if (par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (par->mach->mem->size+1)))
0482         return -EINVAL;
0483 
0484     if (!par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)))
0485         return -EINVAL;
0486 
0487     var->xres_virtual = max(var->xres_virtual, var->xres);
0488     var->yres_virtual = max(var->yres_virtual, var->yres);
0489 
0490     if (var->bits_per_pixel > BITS_PER_PIXEL)
0491         return -EINVAL;
0492     else
0493         var->bits_per_pixel = BITS_PER_PIXEL;
0494 
0495     var->red.offset = 11;
0496     var->red.length = 5;
0497     var->green.offset = 5;
0498     var->green.length = 6;
0499     var->blue.offset = 0;
0500     var->blue.length = 5;
0501     var->transp.offset = var->transp.length = 0;
0502 
0503     var->nonstd = 0;
0504     var->height = -1;
0505     var->width = -1;
0506     var->vmode = FB_VMODE_NONINTERLACED;
0507     var->sync = 0;
0508     var->pixclock = 0x04;  /* 171521; */
0509 
0510     return 0;
0511 }
0512 
0513 
0514 /*
0515  * w100fb_set_par():
0516  *  Set the user defined part of the display for the specified console
0517  *  by looking at the values in info.var
0518  */
0519 static int w100fb_set_par(struct fb_info *info)
0520 {
0521     struct w100fb_par *par=info->par;
0522 
0523     if (par->xres != info->var.xres || par->yres != info->var.yres) {
0524         par->xres = info->var.xres;
0525         par->yres = info->var.yres;
0526         par->mode = w100fb_get_mode(par, &par->xres, &par->yres, 0);
0527 
0528         info->fix.visual = FB_VISUAL_TRUECOLOR;
0529         info->fix.ypanstep = 0;
0530         info->fix.ywrapstep = 0;
0531         info->fix.line_length = par->xres * BITS_PER_PIXEL / 8;
0532 
0533         mutex_lock(&info->mm_lock);
0534         if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) {
0535             par->extmem_active = 1;
0536             info->fix.smem_len = par->mach->mem->size+1;
0537         } else {
0538             par->extmem_active = 0;
0539             info->fix.smem_len = MEM_INT_SIZE+1;
0540         }
0541         mutex_unlock(&info->mm_lock);
0542 
0543         w100fb_activate_var(par);
0544     }
0545     return 0;
0546 }
0547 
0548 
0549 /*
0550  *  Frame buffer operations
0551  */
0552 static const struct fb_ops w100fb_ops = {
0553     .owner        = THIS_MODULE,
0554     .fb_check_var = w100fb_check_var,
0555     .fb_set_par   = w100fb_set_par,
0556     .fb_setcolreg = w100fb_setcolreg,
0557     .fb_blank     = w100fb_blank,
0558     .fb_fillrect  = w100fb_fillrect,
0559     .fb_copyarea  = w100fb_copyarea,
0560     .fb_imageblit = cfb_imageblit,
0561     .fb_sync      = w100fb_sync,
0562 };
0563 
0564 #ifdef CONFIG_PM
0565 static void w100fb_save_vidmem(struct w100fb_par *par)
0566 {
0567     int memsize;
0568 
0569     if (par->extmem_active) {
0570         memsize=par->mach->mem->size;
0571         par->saved_extmem = vmalloc(memsize);
0572         if (par->saved_extmem)
0573             memcpy_fromio(par->saved_extmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
0574     }
0575     memsize=MEM_INT_SIZE;
0576     par->saved_intmem = vmalloc(memsize);
0577     if (par->saved_intmem && par->extmem_active)
0578         memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), memsize);
0579     else if (par->saved_intmem)
0580         memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
0581 }
0582 
0583 static void w100fb_restore_vidmem(struct w100fb_par *par)
0584 {
0585     int memsize;
0586 
0587     if (par->extmem_active && par->saved_extmem) {
0588         memsize=par->mach->mem->size;
0589         memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_extmem, memsize);
0590         vfree(par->saved_extmem);
0591         par->saved_extmem = NULL;
0592     }
0593     if (par->saved_intmem) {
0594         memsize=MEM_INT_SIZE;
0595         if (par->extmem_active)
0596             memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), par->saved_intmem, memsize);
0597         else
0598             memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_intmem, memsize);
0599         vfree(par->saved_intmem);
0600         par->saved_intmem = NULL;
0601     }
0602 }
0603 
0604 static int w100fb_suspend(struct platform_device *dev, pm_message_t state)
0605 {
0606     struct fb_info *info = platform_get_drvdata(dev);
0607     struct w100fb_par *par=info->par;
0608     struct w100_tg_info *tg = par->mach->tg;
0609 
0610     w100fb_save_vidmem(par);
0611     if(tg && tg->suspend)
0612         tg->suspend(par);
0613     w100_suspend(W100_SUSPEND_ALL);
0614     par->blanked = 1;
0615 
0616     return 0;
0617 }
0618 
0619 static int w100fb_resume(struct platform_device *dev)
0620 {
0621     struct fb_info *info = platform_get_drvdata(dev);
0622     struct w100fb_par *par=info->par;
0623     struct w100_tg_info *tg = par->mach->tg;
0624 
0625     w100_hw_init(par);
0626     w100fb_activate_var(par);
0627     w100fb_restore_vidmem(par);
0628     if(tg && tg->resume)
0629         tg->resume(par);
0630     par->blanked = 0;
0631 
0632     return 0;
0633 }
0634 #else
0635 #define w100fb_suspend  NULL
0636 #define w100fb_resume   NULL
0637 #endif
0638 
0639 
0640 static int w100fb_probe(struct platform_device *pdev)
0641 {
0642     int err = -EIO;
0643     struct w100fb_mach_info *inf;
0644     struct fb_info *info = NULL;
0645     struct w100fb_par *par;
0646     struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0647     unsigned int chip_id;
0648 
0649     if (!mem)
0650         return -EINVAL;
0651 
0652     /* Remap the chip base address */
0653     remapped_base = ioremap(mem->start+W100_CFG_BASE, W100_CFG_LEN);
0654     if (remapped_base == NULL)
0655         goto out;
0656 
0657     /* Map the register space */
0658     remapped_regs = ioremap(mem->start+W100_REG_BASE, W100_REG_LEN);
0659     if (remapped_regs == NULL)
0660         goto out;
0661 
0662     /* Identify the chip */
0663     printk("Found ");
0664     chip_id = readl(remapped_regs + mmCHIP_ID);
0665     switch(chip_id) {
0666         case CHIP_ID_W100:  printk("w100");  break;
0667         case CHIP_ID_W3200: printk("w3200"); break;
0668         case CHIP_ID_W3220: printk("w3220"); break;
0669         default:
0670             printk("Unknown imageon chip ID\n");
0671             err = -ENODEV;
0672             goto out;
0673     }
0674     printk(" at 0x%08lx.\n", (unsigned long) mem->start+W100_CFG_BASE);
0675 
0676     /* Remap the framebuffer */
0677     remapped_fbuf = ioremap(mem->start+MEM_WINDOW_BASE, MEM_WINDOW_SIZE);
0678     if (remapped_fbuf == NULL)
0679         goto out;
0680 
0681     info=framebuffer_alloc(sizeof(struct w100fb_par), &pdev->dev);
0682     if (!info) {
0683         err = -ENOMEM;
0684         goto out;
0685     }
0686 
0687     par = info->par;
0688     platform_set_drvdata(pdev, info);
0689 
0690     inf = dev_get_platdata(&pdev->dev);
0691     par->chip_id = chip_id;
0692     par->mach = inf;
0693     par->fastpll_mode = 0;
0694     par->blanked = 0;
0695 
0696     par->pll_table=w100_get_xtal_table(inf->xtal_freq);
0697     if (!par->pll_table) {
0698         printk(KERN_ERR "No matching Xtal definition found\n");
0699         err = -EINVAL;
0700         goto out;
0701     }
0702 
0703     info->pseudo_palette = kmalloc_array(MAX_PALETTES, sizeof(u32),
0704                          GFP_KERNEL);
0705     if (!info->pseudo_palette) {
0706         err = -ENOMEM;
0707         goto out;
0708     }
0709 
0710     info->fbops = &w100fb_ops;
0711     info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
0712         FBINFO_HWACCEL_FILLRECT;
0713     info->node = -1;
0714     info->screen_base = remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE);
0715     info->screen_size = REMAPPED_FB_LEN;
0716 
0717     strcpy(info->fix.id, "w100fb");
0718     info->fix.type = FB_TYPE_PACKED_PIXELS;
0719     info->fix.type_aux = 0;
0720     info->fix.accel = FB_ACCEL_NONE;
0721     info->fix.smem_start = mem->start+W100_FB_BASE;
0722     info->fix.mmio_start = mem->start+W100_REG_BASE;
0723     info->fix.mmio_len = W100_REG_LEN;
0724 
0725     if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
0726         err = -ENOMEM;
0727         goto out;
0728     }
0729 
0730     par->mode = &inf->modelist[0];
0731     if(inf->init_mode & INIT_MODE_ROTATED) {
0732         info->var.xres = par->mode->yres;
0733         info->var.yres = par->mode->xres;
0734     }
0735     else {
0736         info->var.xres = par->mode->xres;
0737         info->var.yres = par->mode->yres;
0738     }
0739 
0740     if(inf->init_mode &= INIT_MODE_FLIPPED)
0741         par->flip = 1;
0742     else
0743         par->flip = 0;
0744 
0745     info->var.xres_virtual = info->var.xres;
0746     info->var.yres_virtual = info->var.yres;
0747     info->var.pixclock = 0x04;  /* 171521; */
0748     info->var.sync = 0;
0749     info->var.grayscale = 0;
0750     info->var.xoffset = info->var.yoffset = 0;
0751     info->var.accel_flags = 0;
0752     info->var.activate = FB_ACTIVATE_NOW;
0753 
0754     w100_hw_init(par);
0755 
0756     if (w100fb_check_var(&info->var, info) < 0) {
0757         err = -EINVAL;
0758         goto out;
0759     }
0760 
0761     if (register_framebuffer(info) < 0) {
0762         err = -EINVAL;
0763         goto out;
0764     }
0765 
0766     fb_info(info, "%s frame buffer device\n", info->fix.id);
0767     return 0;
0768 out:
0769     if (info) {
0770         fb_dealloc_cmap(&info->cmap);
0771         kfree(info->pseudo_palette);
0772     }
0773     if (remapped_fbuf != NULL) {
0774         iounmap(remapped_fbuf);
0775         remapped_fbuf = NULL;
0776     }
0777     if (remapped_regs != NULL) {
0778         iounmap(remapped_regs);
0779         remapped_regs = NULL;
0780     }
0781     if (remapped_base != NULL) {
0782         iounmap(remapped_base);
0783         remapped_base = NULL;
0784     }
0785     if (info)
0786         framebuffer_release(info);
0787     return err;
0788 }
0789 
0790 
0791 static int w100fb_remove(struct platform_device *pdev)
0792 {
0793     struct fb_info *info = platform_get_drvdata(pdev);
0794     struct w100fb_par *par=info->par;
0795 
0796     unregister_framebuffer(info);
0797 
0798     vfree(par->saved_intmem);
0799     vfree(par->saved_extmem);
0800     kfree(info->pseudo_palette);
0801     fb_dealloc_cmap(&info->cmap);
0802 
0803     iounmap(remapped_base);
0804     remapped_base = NULL;
0805     iounmap(remapped_regs);
0806     remapped_regs = NULL;
0807     iounmap(remapped_fbuf);
0808     remapped_fbuf = NULL;
0809 
0810     framebuffer_release(info);
0811 
0812     return 0;
0813 }
0814 
0815 
0816 /* ------------------- chipset specific functions -------------------------- */
0817 
0818 
0819 static void w100_soft_reset(void)
0820 {
0821     u16 val = readw((u16 __iomem *)remapped_base + cfgSTATUS);
0822 
0823     writew(val | 0x08, (u16 __iomem *)remapped_base + cfgSTATUS);
0824     udelay(100);
0825     writew(0x00, (u16 __iomem *)remapped_base + cfgSTATUS);
0826     udelay(100);
0827 }
0828 
0829 static void w100_update_disable(void)
0830 {
0831     union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
0832 
0833     /* Prevent display updates */
0834     disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
0835     disp_db_buf_wr_cntl.f.update_db_buf = 0;
0836     disp_db_buf_wr_cntl.f.en_db_buf = 0;
0837     writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
0838 }
0839 
0840 static void w100_update_enable(void)
0841 {
0842     union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
0843 
0844     /* Enable display updates */
0845     disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
0846     disp_db_buf_wr_cntl.f.update_db_buf = 1;
0847     disp_db_buf_wr_cntl.f.en_db_buf = 1;
0848     writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
0849 }
0850 
0851 unsigned long w100fb_gpio_read(int port)
0852 {
0853     unsigned long value;
0854 
0855     if (port==W100_GPIO_PORT_A)
0856         value = readl(remapped_regs + mmGPIO_DATA);
0857     else
0858         value = readl(remapped_regs + mmGPIO_DATA2);
0859 
0860     return value;
0861 }
0862 
0863 void w100fb_gpio_write(int port, unsigned long value)
0864 {
0865     if (port==W100_GPIO_PORT_A)
0866         writel(value, remapped_regs + mmGPIO_DATA);
0867     else
0868         writel(value, remapped_regs + mmGPIO_DATA2);
0869 }
0870 EXPORT_SYMBOL(w100fb_gpio_read);
0871 EXPORT_SYMBOL(w100fb_gpio_write);
0872 
0873 /*
0874  * Initialization of critical w100 hardware
0875  */
0876 static void w100_hw_init(struct w100fb_par *par)
0877 {
0878     u32 temp32;
0879     union cif_cntl_u cif_cntl;
0880     union intf_cntl_u intf_cntl;
0881     union cfgreg_base_u cfgreg_base;
0882     union wrap_top_dir_u wrap_top_dir;
0883     union cif_read_dbg_u cif_read_dbg;
0884     union cpu_defaults_u cpu_default;
0885     union cif_write_dbg_u cif_write_dbg;
0886     union wrap_start_dir_u wrap_start_dir;
0887     union cif_io_u cif_io;
0888     struct w100_gpio_regs *gpio = par->mach->gpio;
0889 
0890     w100_soft_reset();
0891 
0892     /* This is what the fpga_init code does on reset. May be wrong
0893        but there is little info available */
0894     writel(0x31, remapped_regs + mmSCRATCH_UMSK);
0895     for (temp32 = 0; temp32 < 10000; temp32++)
0896         readl(remapped_regs + mmSCRATCH_UMSK);
0897     writel(0x30, remapped_regs + mmSCRATCH_UMSK);
0898 
0899     /* Set up CIF */
0900     cif_io.val = defCIF_IO;
0901     writel((u32)(cif_io.val), remapped_regs + mmCIF_IO);
0902 
0903     cif_write_dbg.val = readl(remapped_regs + mmCIF_WRITE_DBG);
0904     cif_write_dbg.f.dis_packer_ful_during_rbbm_timeout = 0;
0905     cif_write_dbg.f.en_dword_split_to_rbbm = 1;
0906     cif_write_dbg.f.dis_timeout_during_rbbm = 1;
0907     writel((u32) (cif_write_dbg.val), remapped_regs + mmCIF_WRITE_DBG);
0908 
0909     cif_read_dbg.val = readl(remapped_regs + mmCIF_READ_DBG);
0910     cif_read_dbg.f.dis_rd_same_byte_to_trig_fetch = 1;
0911     writel((u32) (cif_read_dbg.val), remapped_regs + mmCIF_READ_DBG);
0912 
0913     cif_cntl.val = readl(remapped_regs + mmCIF_CNTL);
0914     cif_cntl.f.dis_system_bits = 1;
0915     cif_cntl.f.dis_mr = 1;
0916     cif_cntl.f.en_wait_to_compensate_dq_prop_dly = 0;
0917     cif_cntl.f.intb_oe = 1;
0918     cif_cntl.f.interrupt_active_high = 1;
0919     writel((u32) (cif_cntl.val), remapped_regs + mmCIF_CNTL);
0920 
0921     /* Setup cfgINTF_CNTL and cfgCPU defaults */
0922     intf_cntl.val = defINTF_CNTL;
0923     intf_cntl.f.ad_inc_a = 1;
0924     intf_cntl.f.ad_inc_b = 1;
0925     intf_cntl.f.rd_data_rdy_a = 0;
0926     intf_cntl.f.rd_data_rdy_b = 0;
0927     writeb((u8) (intf_cntl.val), remapped_base + cfgINTF_CNTL);
0928 
0929     cpu_default.val = defCPU_DEFAULTS;
0930     cpu_default.f.access_ind_addr_a = 1;
0931     cpu_default.f.access_ind_addr_b = 1;
0932     cpu_default.f.access_scratch_reg = 1;
0933     cpu_default.f.transition_size = 0;
0934     writeb((u8) (cpu_default.val), remapped_base + cfgCPU_DEFAULTS);
0935 
0936     /* set up the apertures */
0937     writeb((u8) (W100_REG_BASE >> 16), remapped_base + cfgREG_BASE);
0938 
0939     cfgreg_base.val = defCFGREG_BASE;
0940     cfgreg_base.f.cfgreg_base = W100_CFG_BASE;
0941     writel((u32) (cfgreg_base.val), remapped_regs + mmCFGREG_BASE);
0942 
0943     wrap_start_dir.val = defWRAP_START_DIR;
0944     wrap_start_dir.f.start_addr = WRAP_BUF_BASE_VALUE >> 1;
0945     writel((u32) (wrap_start_dir.val), remapped_regs + mmWRAP_START_DIR);
0946 
0947     wrap_top_dir.val = defWRAP_TOP_DIR;
0948     wrap_top_dir.f.top_addr = WRAP_BUF_TOP_VALUE >> 1;
0949     writel((u32) (wrap_top_dir.val), remapped_regs + mmWRAP_TOP_DIR);
0950 
0951     writel((u32) 0x2440, remapped_regs + mmRBBM_CNTL);
0952 
0953     /* Set the hardware to 565 colour */
0954     temp32 = readl(remapped_regs + mmDISP_DEBUG2);
0955     temp32 &= 0xff7fffff;
0956     temp32 |= 0x00800000;
0957     writel(temp32, remapped_regs + mmDISP_DEBUG2);
0958 
0959     /* Initialise the GPIO lines */
0960     if (gpio) {
0961         writel(gpio->init_data1, remapped_regs + mmGPIO_DATA);
0962         writel(gpio->init_data2, remapped_regs + mmGPIO_DATA2);
0963         writel(gpio->gpio_dir1,  remapped_regs + mmGPIO_CNTL1);
0964         writel(gpio->gpio_oe1,   remapped_regs + mmGPIO_CNTL2);
0965         writel(gpio->gpio_dir2,  remapped_regs + mmGPIO_CNTL3);
0966         writel(gpio->gpio_oe2,   remapped_regs + mmGPIO_CNTL4);
0967     }
0968 }
0969 
0970 
0971 struct power_state {
0972     union clk_pin_cntl_u clk_pin_cntl;
0973     union pll_ref_fb_div_u pll_ref_fb_div;
0974     union pll_cntl_u pll_cntl;
0975     union sclk_cntl_u sclk_cntl;
0976     union pclk_cntl_u pclk_cntl;
0977     union pwrmgt_cntl_u pwrmgt_cntl;
0978     int auto_mode;  /* system clock auto changing? */
0979 };
0980 
0981 
0982 static struct power_state w100_pwr_state;
0983 
0984 /* The PLL Fout is determined by (XtalFreq/(M+1)) * ((N_int+1) + (N_fac/8)) */
0985 
0986 /* 12.5MHz Crystal PLL Table */
0987 static struct w100_pll_info xtal_12500000[] = {
0988     /*freq     M   N_int    N_fac  tfgoal  lock_time */
0989     { 50,      0,   1,       0,     0xe0,        56},  /*  50.00 MHz */
0990     { 75,      0,   5,       0,     0xde,        37},  /*  75.00 MHz */
0991     {100,      0,   7,       0,     0xe0,        28},  /* 100.00 MHz */
0992     {125,      0,   9,       0,     0xe0,        22},  /* 125.00 MHz */
0993     {150,      0,   11,      0,     0xe0,        17},  /* 150.00 MHz */
0994     {  0,      0,   0,       0,        0,         0},  /* Terminator */
0995 };
0996 
0997 /* 14.318MHz Crystal PLL Table */
0998 static struct w100_pll_info xtal_14318000[] = {
0999     /*freq     M   N_int    N_fac  tfgoal  lock_time */
1000     { 40,      4,   13,      0,     0xe0,        80}, /* tfgoal guessed */
1001     { 50,      1,   6,       0,     0xe0,        64}, /*  50.05 MHz */
1002     { 57,      2,   11,      0,     0xe0,        53}, /* tfgoal guessed */
1003     { 75,      0,   4,       3,     0xe0,        43}, /*  75.08 MHz */
1004     {100,      0,   6,       0,     0xe0,        32}, /* 100.10 MHz */
1005     {  0,      0,   0,       0,        0,         0},
1006 };
1007 
1008 /* 16MHz Crystal PLL Table */
1009 static struct w100_pll_info xtal_16000000[] = {
1010     /*freq     M   N_int    N_fac  tfgoal  lock_time */
1011     { 72,      1,   8,       0,     0xe0,        48}, /* tfgoal guessed */
1012     { 80,      1,   9,       0,     0xe0,        13}, /* tfgoal guessed */
1013     { 95,      1,   10,      7,     0xe0,        38}, /* tfgoal guessed */
1014     { 96,      1,   11,      0,     0xe0,        36}, /* tfgoal guessed */
1015     {  0,      0,   0,       0,        0,         0},
1016 };
1017 
1018 static struct pll_entries {
1019     int xtal_freq;
1020     struct w100_pll_info *pll_table;
1021 } w100_pll_tables[] = {
1022     { 12500000, &xtal_12500000[0] },
1023     { 14318000, &xtal_14318000[0] },
1024     { 16000000, &xtal_16000000[0] },
1025     { 0 },
1026 };
1027 
1028 struct w100_pll_info *w100_get_xtal_table(unsigned int freq)
1029 {
1030     struct pll_entries *pll_entry = w100_pll_tables;
1031 
1032     do {
1033         if (freq == pll_entry->xtal_freq)
1034             return pll_entry->pll_table;
1035         pll_entry++;
1036     } while (pll_entry->xtal_freq);
1037 
1038     return NULL;
1039 }
1040 
1041 
1042 static unsigned int w100_get_testcount(unsigned int testclk_sel)
1043 {
1044     union clk_test_cntl_u clk_test_cntl;
1045 
1046     udelay(5);
1047 
1048     /* Select the test clock source and reset */
1049     clk_test_cntl.f.start_check_freq = 0x0;
1050     clk_test_cntl.f.testclk_sel = testclk_sel;
1051     clk_test_cntl.f.tstcount_rst = 0x1; /* set reset */
1052     writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1053 
1054     clk_test_cntl.f.tstcount_rst = 0x0; /* clear reset */
1055     writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1056 
1057     /* Run clock test */
1058     clk_test_cntl.f.start_check_freq = 0x1;
1059     writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1060 
1061     /* Give the test time to complete */
1062     udelay(20);
1063 
1064     /* Return the result */
1065     clk_test_cntl.val = readl(remapped_regs + mmCLK_TEST_CNTL);
1066     clk_test_cntl.f.start_check_freq = 0x0;
1067     writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1068 
1069     return clk_test_cntl.f.test_count;
1070 }
1071 
1072 
1073 static int w100_pll_adjust(struct w100_pll_info *pll)
1074 {
1075     unsigned int tf80;
1076     unsigned int tf20;
1077 
1078     /* Initial Settings */
1079     w100_pwr_state.pll_cntl.f.pll_pwdn = 0x0;     /* power down */
1080     w100_pwr_state.pll_cntl.f.pll_reset = 0x0;    /* not reset */
1081     w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x1;   /* Hi-Z */
1082     w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;      /* VCO gain = 0 */
1083     w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0;    /* VCO frequency range control = off */
1084     w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;  /* current offset inside VCO = 0 */
1085     w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
1086 
1087     /* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V
1088      * therefore, commented out the following lines
1089      * tf80 meant tf100
1090      */
1091     do {
1092         /* set VCO input = 0.8 * VDD */
1093         w100_pwr_state.pll_cntl.f.pll_dactal = 0xd;
1094         writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1095 
1096         tf80 = w100_get_testcount(TESTCLK_SRC_PLL);
1097         if (tf80 >= (pll->tfgoal)) {
1098             /* set VCO input = 0.2 * VDD */
1099             w100_pwr_state.pll_cntl.f.pll_dactal = 0x7;
1100             writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1101 
1102             tf20 = w100_get_testcount(TESTCLK_SRC_PLL);
1103             if (tf20 <= (pll->tfgoal))
1104                 return 1;  /* Success */
1105 
1106             if ((w100_pwr_state.pll_cntl.f.pll_vcofr == 0x0) &&
1107                 ((w100_pwr_state.pll_cntl.f.pll_pvg == 0x7) ||
1108                 (w100_pwr_state.pll_cntl.f.pll_ioffset == 0x0))) {
1109                 /* slow VCO config */
1110                 w100_pwr_state.pll_cntl.f.pll_vcofr = 0x1;
1111                 w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
1112                 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1113                 continue;
1114             }
1115         }
1116         if ((w100_pwr_state.pll_cntl.f.pll_ioffset) < 0x3) {
1117             w100_pwr_state.pll_cntl.f.pll_ioffset += 0x1;
1118         } else if ((w100_pwr_state.pll_cntl.f.pll_pvg) < 0x7) {
1119             w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1120             w100_pwr_state.pll_cntl.f.pll_pvg += 0x1;
1121         } else {
1122             return 0;  /* Error */
1123         }
1124     } while(1);
1125 }
1126 
1127 
1128 /*
1129  * w100_pll_calibration
1130  */
1131 static int w100_pll_calibration(struct w100_pll_info *pll)
1132 {
1133     int status;
1134 
1135     status = w100_pll_adjust(pll);
1136 
1137     /* PLL Reset And Lock */
1138     /* set VCO input = 0.5 * VDD */
1139     w100_pwr_state.pll_cntl.f.pll_dactal = 0xa;
1140     writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1141 
1142     udelay(1);  /* reset time */
1143 
1144     /* enable charge pump */
1145     w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;  /* normal */
1146     writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1147 
1148     /* set VCO input = Hi-Z, disable DAC */
1149     w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;
1150     writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1151 
1152     udelay(400);  /* lock time */
1153 
1154     /* PLL locked */
1155 
1156     return status;
1157 }
1158 
1159 
1160 static int w100_pll_set_clk(struct w100_pll_info *pll)
1161 {
1162     int status;
1163 
1164     if (w100_pwr_state.auto_mode == 1)  /* auto mode */
1165     {
1166         w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;  /* disable fast to normal */
1167         w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;  /* disable normal to fast */
1168         writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1169     }
1170 
1171     /* Set system clock source to XTAL whilst adjusting the PLL! */
1172     w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
1173     writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1174 
1175     w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = pll->M;
1176     w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = pll->N_int;
1177     w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = pll->N_fac;
1178     w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = pll->lock_time;
1179     writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
1180 
1181     w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0;
1182     writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1183 
1184     status = w100_pll_calibration(pll);
1185 
1186     if (w100_pwr_state.auto_mode == 1)  /* auto mode */
1187     {
1188         w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x1;  /* reenable fast to normal */
1189         w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x1;  /* reenable normal to fast  */
1190         writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1191     }
1192     return status;
1193 }
1194 
1195 /* freq = target frequency of the PLL */
1196 static int w100_set_pll_freq(struct w100fb_par *par, unsigned int freq)
1197 {
1198     struct w100_pll_info *pll = par->pll_table;
1199 
1200     do {
1201         if (freq == pll->freq) {
1202             return w100_pll_set_clk(pll);
1203         }
1204         pll++;
1205     } while(pll->freq);
1206     return 0;
1207 }
1208 
1209 /* Set up an initial state.  Some values/fields set
1210    here will be overwritten. */
1211 static void w100_pwm_setup(struct w100fb_par *par)
1212 {
1213     w100_pwr_state.clk_pin_cntl.f.osc_en = 0x1;
1214     w100_pwr_state.clk_pin_cntl.f.osc_gain = 0x1f;
1215     w100_pwr_state.clk_pin_cntl.f.dont_use_xtalin = 0x0;
1216     w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x0;
1217     w100_pwr_state.clk_pin_cntl.f.xtalin_dbl_en = par->mach->xtal_dbl ? 1 : 0;
1218     w100_pwr_state.clk_pin_cntl.f.cg_debug = 0x0;
1219     writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL);
1220 
1221     w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
1222     w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = 0x0;  /* Pfast = 1 */
1223     w100_pwr_state.sclk_cntl.f.sclk_clkon_hys = 0x3;
1224     w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0;  /* Pslow = 1 */
1225     w100_pwr_state.sclk_cntl.f.disp_cg_ok2switch_en = 0x0;
1226     w100_pwr_state.sclk_cntl.f.sclk_force_reg = 0x0;    /* Dynamic */
1227     w100_pwr_state.sclk_cntl.f.sclk_force_disp = 0x0;   /* Dynamic */
1228     w100_pwr_state.sclk_cntl.f.sclk_force_mc = 0x0;     /* Dynamic */
1229     w100_pwr_state.sclk_cntl.f.sclk_force_extmc = 0x0;  /* Dynamic */
1230     w100_pwr_state.sclk_cntl.f.sclk_force_cp = 0x0;     /* Dynamic */
1231     w100_pwr_state.sclk_cntl.f.sclk_force_e2 = 0x0;     /* Dynamic */
1232     w100_pwr_state.sclk_cntl.f.sclk_force_e3 = 0x0;     /* Dynamic */
1233     w100_pwr_state.sclk_cntl.f.sclk_force_idct = 0x0;   /* Dynamic */
1234     w100_pwr_state.sclk_cntl.f.sclk_force_bist = 0x0;   /* Dynamic */
1235     w100_pwr_state.sclk_cntl.f.busy_extend_cp = 0x0;
1236     w100_pwr_state.sclk_cntl.f.busy_extend_e2 = 0x0;
1237     w100_pwr_state.sclk_cntl.f.busy_extend_e3 = 0x0;
1238     w100_pwr_state.sclk_cntl.f.busy_extend_idct = 0x0;
1239     writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1240 
1241     w100_pwr_state.pclk_cntl.f.pclk_src_sel = CLK_SRC_XTAL;
1242     w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1;    /* P = 2 */
1243     w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0;  /* Dynamic */
1244     writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
1245 
1246     w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0;     /* M = 1 */
1247     w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0;  /* N = 1.0 */
1248     w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = 0x0;
1249     w100_pwr_state.pll_ref_fb_div.f.pll_reset_time = 0x5;
1250     w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = 0xff;
1251     writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
1252 
1253     w100_pwr_state.pll_cntl.f.pll_pwdn = 0x1;
1254     w100_pwr_state.pll_cntl.f.pll_reset = 0x1;
1255     w100_pwr_state.pll_cntl.f.pll_pm_en = 0x0;
1256     w100_pwr_state.pll_cntl.f.pll_mode = 0x0;  /* uses VCO clock */
1257     w100_pwr_state.pll_cntl.f.pll_refclk_sel = 0x0;
1258     w100_pwr_state.pll_cntl.f.pll_fbclk_sel = 0x0;
1259     w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;
1260     w100_pwr_state.pll_cntl.f.pll_pcp = 0x4;
1261     w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
1262     w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0;
1263     w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1264     w100_pwr_state.pll_cntl.f.pll_pecc_mode = 0x0;
1265     w100_pwr_state.pll_cntl.f.pll_pecc_scon = 0x0;
1266     w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;  /* Hi-Z */
1267     w100_pwr_state.pll_cntl.f.pll_cp_clip = 0x3;
1268     w100_pwr_state.pll_cntl.f.pll_conf = 0x2;
1269     w100_pwr_state.pll_cntl.f.pll_mbctrl = 0x2;
1270     w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
1271     writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1272 
1273     w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x0;
1274     w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1;  /* normal mode (0, 1, 3) */
1275     w100_pwr_state.pwrmgt_cntl.f.pwm_wakeup_cond = 0x0;
1276     w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;
1277     w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;
1278     w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1;  /* PM4,ENG */
1279     w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1;  /* PM4,ENG */
1280     w100_pwr_state.pwrmgt_cntl.f.pwm_idle_timer = 0xFF;
1281     w100_pwr_state.pwrmgt_cntl.f.pwm_busy_timer = 0xFF;
1282     writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1283 
1284     w100_pwr_state.auto_mode = 0;  /* manual mode */
1285 }
1286 
1287 
1288 /*
1289  * Setup the w100 clocks for the specified mode
1290  */
1291 static void w100_init_clocks(struct w100fb_par *par)
1292 {
1293     struct w100_mode *mode = par->mode;
1294 
1295     if (mode->pixclk_src == CLK_SRC_PLL || mode->sysclk_src == CLK_SRC_PLL)
1296         w100_set_pll_freq(par, (par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq);
1297 
1298     w100_pwr_state.sclk_cntl.f.sclk_src_sel = mode->sysclk_src;
1299     w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = mode->sysclk_divider;
1300     w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = mode->sysclk_divider;
1301     writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1302 }
1303 
1304 static void w100_init_lcd(struct w100fb_par *par)
1305 {
1306     u32 temp32;
1307     struct w100_mode *mode = par->mode;
1308     struct w100_gen_regs *regs = par->mach->regs;
1309     union active_h_disp_u active_h_disp;
1310     union active_v_disp_u active_v_disp;
1311     union graphic_h_disp_u graphic_h_disp;
1312     union graphic_v_disp_u graphic_v_disp;
1313     union crtc_total_u crtc_total;
1314 
1315     /* w3200 doesn't like undefined bits being set so zero register values first */
1316 
1317     active_h_disp.val = 0;
1318     active_h_disp.f.active_h_start=mode->left_margin;
1319     active_h_disp.f.active_h_end=mode->left_margin + mode->xres;
1320     writel(active_h_disp.val, remapped_regs + mmACTIVE_H_DISP);
1321 
1322     active_v_disp.val = 0;
1323     active_v_disp.f.active_v_start=mode->upper_margin;
1324     active_v_disp.f.active_v_end=mode->upper_margin + mode->yres;
1325     writel(active_v_disp.val, remapped_regs + mmACTIVE_V_DISP);
1326 
1327     graphic_h_disp.val = 0;
1328     graphic_h_disp.f.graphic_h_start=mode->left_margin;
1329     graphic_h_disp.f.graphic_h_end=mode->left_margin + mode->xres;
1330     writel(graphic_h_disp.val, remapped_regs + mmGRAPHIC_H_DISP);
1331 
1332     graphic_v_disp.val = 0;
1333     graphic_v_disp.f.graphic_v_start=mode->upper_margin;
1334     graphic_v_disp.f.graphic_v_end=mode->upper_margin + mode->yres;
1335     writel(graphic_v_disp.val, remapped_regs + mmGRAPHIC_V_DISP);
1336 
1337     crtc_total.val = 0;
1338     crtc_total.f.crtc_h_total=mode->left_margin  + mode->xres + mode->right_margin;
1339     crtc_total.f.crtc_v_total=mode->upper_margin + mode->yres + mode->lower_margin;
1340     writel(crtc_total.val, remapped_regs + mmCRTC_TOTAL);
1341 
1342     writel(mode->crtc_ss, remapped_regs + mmCRTC_SS);
1343     writel(mode->crtc_ls, remapped_regs + mmCRTC_LS);
1344     writel(mode->crtc_gs, remapped_regs + mmCRTC_GS);
1345     writel(mode->crtc_vpos_gs, remapped_regs + mmCRTC_VPOS_GS);
1346     writel(mode->crtc_rev, remapped_regs + mmCRTC_REV);
1347     writel(mode->crtc_dclk, remapped_regs + mmCRTC_DCLK);
1348     writel(mode->crtc_gclk, remapped_regs + mmCRTC_GCLK);
1349     writel(mode->crtc_goe, remapped_regs + mmCRTC_GOE);
1350     writel(mode->crtc_ps1_active, remapped_regs + mmCRTC_PS1_ACTIVE);
1351 
1352     writel(regs->lcd_format, remapped_regs + mmLCD_FORMAT);
1353     writel(regs->lcdd_cntl1, remapped_regs + mmLCDD_CNTL1);
1354     writel(regs->lcdd_cntl2, remapped_regs + mmLCDD_CNTL2);
1355     writel(regs->genlcd_cntl1, remapped_regs + mmGENLCD_CNTL1);
1356     writel(regs->genlcd_cntl2, remapped_regs + mmGENLCD_CNTL2);
1357     writel(regs->genlcd_cntl3, remapped_regs + mmGENLCD_CNTL3);
1358 
1359     writel(0x00000000, remapped_regs + mmCRTC_FRAME);
1360     writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS);
1361     writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT);
1362     writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR);
1363 
1364     /* Hack for overlay in ext memory */
1365     temp32 = readl(remapped_regs + mmDISP_DEBUG2);
1366     temp32 |= 0xc0000000;
1367     writel(temp32, remapped_regs + mmDISP_DEBUG2);
1368 }
1369 
1370 
1371 static void w100_setup_memory(struct w100fb_par *par)
1372 {
1373     union mc_ext_mem_location_u extmem_location;
1374     union mc_fb_location_u intmem_location;
1375     struct w100_mem_info *mem = par->mach->mem;
1376     struct w100_bm_mem_info *bm_mem = par->mach->bm_mem;
1377 
1378     if (!par->extmem_active) {
1379         w100_suspend(W100_SUSPEND_EXTMEM);
1380 
1381         /* Map Internal Memory at FB Base */
1382         intmem_location.f.mc_fb_start = W100_FB_BASE >> 8;
1383         intmem_location.f.mc_fb_top = (W100_FB_BASE+MEM_INT_SIZE) >> 8;
1384         writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
1385 
1386         /* Unmap External Memory - value is *probably* irrelevant but may have meaning
1387            to acceleration libraries */
1388         extmem_location.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8;
1389         extmem_location.f.mc_ext_mem_top = (MEM_EXT_BASE_VALUE-1) >> 8;
1390         writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
1391     } else {
1392         /* Map Internal Memory to its default location */
1393         intmem_location.f.mc_fb_start = MEM_INT_BASE_VALUE >> 8;
1394         intmem_location.f.mc_fb_top = (MEM_INT_BASE_VALUE+MEM_INT_SIZE) >> 8;
1395         writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
1396 
1397         /* Map External Memory at FB Base */
1398         extmem_location.f.mc_ext_mem_start = W100_FB_BASE >> 8;
1399         extmem_location.f.mc_ext_mem_top = (W100_FB_BASE+par->mach->mem->size) >> 8;
1400         writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
1401 
1402         writel(0x00007800, remapped_regs + mmMC_BIST_CTRL);
1403         writel(mem->ext_cntl, remapped_regs + mmMEM_EXT_CNTL);
1404         writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
1405         udelay(100);
1406         writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
1407         udelay(100);
1408         writel(mem->sdram_mode_reg, remapped_regs + mmMEM_SDRAM_MODE_REG);
1409         udelay(100);
1410         writel(mem->ext_timing_cntl, remapped_regs + mmMEM_EXT_TIMING_CNTL);
1411         writel(mem->io_cntl, remapped_regs + mmMEM_IO_CNTL);
1412         if (bm_mem) {
1413             writel(bm_mem->ext_mem_bw, remapped_regs + mmBM_EXT_MEM_BANDWIDTH);
1414             writel(bm_mem->offset, remapped_regs + mmBM_OFFSET);
1415             writel(bm_mem->ext_timing_ctl, remapped_regs + mmBM_MEM_EXT_TIMING_CNTL);
1416             writel(bm_mem->ext_cntl, remapped_regs + mmBM_MEM_EXT_CNTL);
1417             writel(bm_mem->mode_reg, remapped_regs + mmBM_MEM_MODE_REG);
1418             writel(bm_mem->io_cntl, remapped_regs + mmBM_MEM_IO_CNTL);
1419             writel(bm_mem->config, remapped_regs + mmBM_CONFIG);
1420         }
1421     }
1422 }
1423 
1424 static void w100_set_dispregs(struct w100fb_par *par)
1425 {
1426     unsigned long rot=0, divider, offset=0;
1427     union graphic_ctrl_u graphic_ctrl;
1428 
1429     /* See if the mode has been rotated */
1430     if (par->xres == par->mode->xres) {
1431         if (par->flip) {
1432             rot=3; /* 180 degree */
1433             offset=(par->xres * par->yres) - 1;
1434         } /* else 0 degree */
1435         divider = par->mode->pixclk_divider;
1436     } else {
1437         if (par->flip) {
1438             rot=2; /* 270 degree */
1439             offset=par->xres - 1;
1440         } else {
1441             rot=1; /* 90 degree */
1442             offset=par->xres * (par->yres - 1);
1443         }
1444         divider = par->mode->pixclk_divider_rotated;
1445     }
1446 
1447     graphic_ctrl.val = 0; /* w32xx doesn't like undefined bits */
1448     switch (par->chip_id) {
1449         case CHIP_ID_W100:
1450             graphic_ctrl.f_w100.color_depth=6;
1451             graphic_ctrl.f_w100.en_crtc=1;
1452             graphic_ctrl.f_w100.en_graphic_req=1;
1453             graphic_ctrl.f_w100.en_graphic_crtc=1;
1454             graphic_ctrl.f_w100.lcd_pclk_on=1;
1455             graphic_ctrl.f_w100.lcd_sclk_on=1;
1456             graphic_ctrl.f_w100.low_power_on=0;
1457             graphic_ctrl.f_w100.req_freq=0;
1458             graphic_ctrl.f_w100.portrait_mode=rot;
1459 
1460             /* Zaurus needs this */
1461             switch(par->xres) {
1462                 case 240:
1463                 case 320:
1464                 default:
1465                     graphic_ctrl.f_w100.total_req_graphic=0xa0;
1466                     break;
1467                 case 480:
1468                 case 640:
1469                     switch(rot) {
1470                         case 0:  /* 0 */
1471                         case 3:  /* 180 */
1472                             graphic_ctrl.f_w100.low_power_on=1;
1473                             graphic_ctrl.f_w100.req_freq=5;
1474                         break;
1475                         case 1:  /* 90 */
1476                         case 2:  /* 270 */
1477                             graphic_ctrl.f_w100.req_freq=4;
1478                             break;
1479                         default:
1480                             break;
1481                     }
1482                     graphic_ctrl.f_w100.total_req_graphic=0xf0;
1483                     break;
1484             }
1485             break;
1486         case CHIP_ID_W3200:
1487         case CHIP_ID_W3220:
1488             graphic_ctrl.f_w32xx.color_depth=6;
1489             graphic_ctrl.f_w32xx.en_crtc=1;
1490             graphic_ctrl.f_w32xx.en_graphic_req=1;
1491             graphic_ctrl.f_w32xx.en_graphic_crtc=1;
1492             graphic_ctrl.f_w32xx.lcd_pclk_on=1;
1493             graphic_ctrl.f_w32xx.lcd_sclk_on=1;
1494             graphic_ctrl.f_w32xx.low_power_on=0;
1495             graphic_ctrl.f_w32xx.req_freq=0;
1496             graphic_ctrl.f_w32xx.total_req_graphic=par->mode->xres >> 1; /* panel xres, not mode */
1497             graphic_ctrl.f_w32xx.portrait_mode=rot;
1498             break;
1499     }
1500 
1501     /* Set the pixel clock source and divider */
1502     w100_pwr_state.pclk_cntl.f.pclk_src_sel = par->mode->pixclk_src;
1503     w100_pwr_state.pclk_cntl.f.pclk_post_div = divider;
1504     writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
1505 
1506     writel(graphic_ctrl.val, remapped_regs + mmGRAPHIC_CTRL);
1507     writel(W100_FB_BASE + ((offset * BITS_PER_PIXEL/8)&~0x03UL), remapped_regs + mmGRAPHIC_OFFSET);
1508     writel((par->xres*BITS_PER_PIXEL/8), remapped_regs + mmGRAPHIC_PITCH);
1509 }
1510 
1511 
1512 /*
1513  * Work out how long the sync pulse lasts
1514  * Value is 1/(time in seconds)
1515  */
1516 static void calc_hsync(struct w100fb_par *par)
1517 {
1518     unsigned long hsync;
1519     struct w100_mode *mode = par->mode;
1520     union crtc_ss_u crtc_ss;
1521 
1522     if (mode->pixclk_src == CLK_SRC_XTAL)
1523         hsync=par->mach->xtal_freq;
1524     else
1525         hsync=((par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq)*100000;
1526 
1527     hsync /= (w100_pwr_state.pclk_cntl.f.pclk_post_div + 1);
1528 
1529     crtc_ss.val = readl(remapped_regs + mmCRTC_SS);
1530     if (crtc_ss.val)
1531         par->hsync_len = hsync / (crtc_ss.f.ss_end-crtc_ss.f.ss_start);
1532     else
1533         par->hsync_len = 0;
1534 }
1535 
1536 static void w100_suspend(u32 mode)
1537 {
1538     u32 val;
1539 
1540     writel(0x7FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION);
1541     writel(0x00FF0000, remapped_regs + mmMC_PERF_MON_CNTL);
1542 
1543     val = readl(remapped_regs + mmMEM_EXT_TIMING_CNTL);
1544     val &= ~(0x00100000);  /* bit20=0 */
1545     val |= 0xFF000000;     /* bit31:24=0xff */
1546     writel(val, remapped_regs + mmMEM_EXT_TIMING_CNTL);
1547 
1548     val = readl(remapped_regs + mmMEM_EXT_CNTL);
1549     val &= ~(0x00040000);  /* bit18=0 */
1550     val |= 0x00080000;     /* bit19=1 */
1551     writel(val, remapped_regs + mmMEM_EXT_CNTL);
1552 
1553     udelay(1);  /* wait 1us */
1554 
1555     if (mode == W100_SUSPEND_EXTMEM) {
1556         /* CKE: Tri-State */
1557         val = readl(remapped_regs + mmMEM_EXT_CNTL);
1558         val |= 0x40000000;  /* bit30=1 */
1559         writel(val, remapped_regs + mmMEM_EXT_CNTL);
1560 
1561         /* CLK: Stop */
1562         val = readl(remapped_regs + mmMEM_EXT_CNTL);
1563         val &= ~(0x00000001);  /* bit0=0 */
1564         writel(val, remapped_regs + mmMEM_EXT_CNTL);
1565     } else {
1566         writel(0x00000000, remapped_regs + mmSCLK_CNTL);
1567         writel(0x000000BF, remapped_regs + mmCLK_PIN_CNTL);
1568         writel(0x00000015, remapped_regs + mmPWRMGT_CNTL);
1569 
1570         udelay(5);
1571 
1572         val = readl(remapped_regs + mmPLL_CNTL);
1573         val |= 0x00000004;  /* bit2=1 */
1574         writel(val, remapped_regs + mmPLL_CNTL);
1575 
1576         writel(0x00000000, remapped_regs + mmLCDD_CNTL1);
1577         writel(0x00000000, remapped_regs + mmLCDD_CNTL2);
1578         writel(0x00000000, remapped_regs + mmGENLCD_CNTL1);
1579         writel(0x00000000, remapped_regs + mmGENLCD_CNTL2);
1580         writel(0x00000000, remapped_regs + mmGENLCD_CNTL3);
1581 
1582         val = readl(remapped_regs + mmMEM_EXT_CNTL);
1583         val |= 0xF0000000;
1584         val &= ~(0x00000001);
1585         writel(val, remapped_regs + mmMEM_EXT_CNTL);
1586 
1587         writel(0x0000001d, remapped_regs + mmPWRMGT_CNTL);
1588     }
1589 }
1590 
1591 static void w100_vsync(void)
1592 {
1593     u32 tmp;
1594     int timeout = 30000;  /* VSync timeout = 30[ms] > 16.8[ms] */
1595 
1596     tmp = readl(remapped_regs + mmACTIVE_V_DISP);
1597 
1598     /* set vline pos  */
1599     writel((tmp >> 16) & 0x3ff, remapped_regs + mmDISP_INT_CNTL);
1600 
1601     /* disable vline irq */
1602     tmp = readl(remapped_regs + mmGEN_INT_CNTL);
1603 
1604     tmp &= ~0x00000002;
1605     writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1606 
1607     /* clear vline irq status */
1608     writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1609 
1610     /* enable vline irq */
1611     writel((tmp | 0x00000002), remapped_regs + mmGEN_INT_CNTL);
1612 
1613     /* clear vline irq status */
1614     writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1615 
1616     while(timeout > 0) {
1617         if (readl(remapped_regs + mmGEN_INT_STATUS) & 0x00000002)
1618             break;
1619         udelay(1);
1620         timeout--;
1621     }
1622 
1623     /* disable vline irq */
1624     writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1625 
1626     /* clear vline irq status */
1627     writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1628 }
1629 
1630 static struct platform_driver w100fb_driver = {
1631     .probe      = w100fb_probe,
1632     .remove     = w100fb_remove,
1633     .suspend    = w100fb_suspend,
1634     .resume     = w100fb_resume,
1635     .driver     = {
1636         .name   = "w100fb",
1637         .dev_groups = w100fb_groups,
1638     },
1639 };
1640 
1641 module_platform_driver(w100fb_driver);
1642 
1643 MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
1644 MODULE_LICENSE("GPL");