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