GNU Linux-libre 4.9.318-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 <asm/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(flip, 0644, flip_show, flip_store);
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(fastpllclk, 0644, fastpllclk_show, fastpllclk_store);
170
171 /*
172  * Some touchscreens need hsync information from the video driver to
173  * function correctly. We export it here.
174  */
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(sizeof (u32) * MAX_PALETTES, GFP_KERNEL);
699         if (!info->pseudo_palette) {
700                 err = -ENOMEM;
701                 goto out;
702         }
703
704         info->fbops = &w100fb_ops;
705         info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
706                 FBINFO_HWACCEL_FILLRECT;
707         info->node = -1;
708         info->screen_base = remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE);
709         info->screen_size = REMAPPED_FB_LEN;
710
711         strcpy(info->fix.id, "w100fb");
712         info->fix.type = FB_TYPE_PACKED_PIXELS;
713         info->fix.type_aux = 0;
714         info->fix.accel = FB_ACCEL_NONE;
715         info->fix.smem_start = mem->start+W100_FB_BASE;
716         info->fix.mmio_start = mem->start+W100_REG_BASE;
717         info->fix.mmio_len = W100_REG_LEN;
718
719         if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
720                 err = -ENOMEM;
721                 goto out;
722         }
723
724         par->mode = &inf->modelist[0];
725         if(inf->init_mode & INIT_MODE_ROTATED) {
726                 info->var.xres = par->mode->yres;
727                 info->var.yres = par->mode->xres;
728         }
729         else {
730                 info->var.xres = par->mode->xres;
731                 info->var.yres = par->mode->yres;
732         }
733
734         if(inf->init_mode &= INIT_MODE_FLIPPED)
735                 par->flip = 1;
736         else
737                 par->flip = 0;
738
739         info->var.xres_virtual = info->var.xres;
740         info->var.yres_virtual = info->var.yres;
741         info->var.pixclock = 0x04;  /* 171521; */
742         info->var.sync = 0;
743         info->var.grayscale = 0;
744         info->var.xoffset = info->var.yoffset = 0;
745         info->var.accel_flags = 0;
746         info->var.activate = FB_ACTIVATE_NOW;
747
748         w100_hw_init(par);
749
750         if (w100fb_check_var(&info->var, info) < 0) {
751                 err = -EINVAL;
752                 goto out;
753         }
754
755         if (register_framebuffer(info) < 0) {
756                 err = -EINVAL;
757                 goto out;
758         }
759
760         err = device_create_file(&pdev->dev, &dev_attr_fastpllclk);
761         err |= device_create_file(&pdev->dev, &dev_attr_reg_read);
762         err |= device_create_file(&pdev->dev, &dev_attr_reg_write);
763         err |= device_create_file(&pdev->dev, &dev_attr_flip);
764
765         if (err != 0)
766                 fb_warn(info, "failed to register attributes (%d)\n", err);
767
768         fb_info(info, "%s frame buffer device\n", info->fix.id);
769         return 0;
770 out:
771         if (info) {
772                 fb_dealloc_cmap(&info->cmap);
773                 kfree(info->pseudo_palette);
774         }
775         if (remapped_fbuf != NULL) {
776                 iounmap(remapped_fbuf);
777                 remapped_fbuf = NULL;
778         }
779         if (remapped_regs != NULL) {
780                 iounmap(remapped_regs);
781                 remapped_regs = NULL;
782         }
783         if (remapped_base != NULL) {
784                 iounmap(remapped_base);
785                 remapped_base = NULL;
786         }
787         if (info)
788                 framebuffer_release(info);
789         return err;
790 }
791
792
793 static int w100fb_remove(struct platform_device *pdev)
794 {
795         struct fb_info *info = platform_get_drvdata(pdev);
796         struct w100fb_par *par=info->par;
797
798         device_remove_file(&pdev->dev, &dev_attr_fastpllclk);
799         device_remove_file(&pdev->dev, &dev_attr_reg_read);
800         device_remove_file(&pdev->dev, &dev_attr_reg_write);
801         device_remove_file(&pdev->dev, &dev_attr_flip);
802
803         unregister_framebuffer(info);
804
805         vfree(par->saved_intmem);
806         vfree(par->saved_extmem);
807         kfree(info->pseudo_palette);
808         fb_dealloc_cmap(&info->cmap);
809
810         iounmap(remapped_base);
811         remapped_base = NULL;
812         iounmap(remapped_regs);
813         remapped_regs = NULL;
814         iounmap(remapped_fbuf);
815         remapped_fbuf = NULL;
816
817         framebuffer_release(info);
818
819         return 0;
820 }
821
822
823 /* ------------------- chipset specific functions -------------------------- */
824
825
826 static void w100_soft_reset(void)
827 {
828         u16 val = readw((u16 *) remapped_base + cfgSTATUS);
829         writew(val | 0x08, (u16 *) remapped_base + cfgSTATUS);
830         udelay(100);
831         writew(0x00, (u16 *) remapped_base + cfgSTATUS);
832         udelay(100);
833 }
834
835 static void w100_update_disable(void)
836 {
837         union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
838
839         /* Prevent display updates */
840         disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
841         disp_db_buf_wr_cntl.f.update_db_buf = 0;
842         disp_db_buf_wr_cntl.f.en_db_buf = 0;
843         writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
844 }
845
846 static void w100_update_enable(void)
847 {
848         union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
849
850         /* Enable display updates */
851         disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
852         disp_db_buf_wr_cntl.f.update_db_buf = 1;
853         disp_db_buf_wr_cntl.f.en_db_buf = 1;
854         writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
855 }
856
857 unsigned long w100fb_gpio_read(int port)
858 {
859         unsigned long value;
860
861         if (port==W100_GPIO_PORT_A)
862                 value = readl(remapped_regs + mmGPIO_DATA);
863         else
864                 value = readl(remapped_regs + mmGPIO_DATA2);
865
866         return value;
867 }
868
869 void w100fb_gpio_write(int port, unsigned long value)
870 {
871         if (port==W100_GPIO_PORT_A)
872                 writel(value, remapped_regs + mmGPIO_DATA);
873         else
874                 writel(value, remapped_regs + mmGPIO_DATA2);
875 }
876 EXPORT_SYMBOL(w100fb_gpio_read);
877 EXPORT_SYMBOL(w100fb_gpio_write);
878
879 /*
880  * Initialization of critical w100 hardware
881  */
882 static void w100_hw_init(struct w100fb_par *par)
883 {
884         u32 temp32;
885         union cif_cntl_u cif_cntl;
886         union intf_cntl_u intf_cntl;
887         union cfgreg_base_u cfgreg_base;
888         union wrap_top_dir_u wrap_top_dir;
889         union cif_read_dbg_u cif_read_dbg;
890         union cpu_defaults_u cpu_default;
891         union cif_write_dbg_u cif_write_dbg;
892         union wrap_start_dir_u wrap_start_dir;
893         union cif_io_u cif_io;
894         struct w100_gpio_regs *gpio = par->mach->gpio;
895
896         w100_soft_reset();
897
898         /* This is what the fpga_init code does on reset. May be wrong
899            but there is little info available */
900         writel(0x31, remapped_regs + mmSCRATCH_UMSK);
901         for (temp32 = 0; temp32 < 10000; temp32++)
902                 readl(remapped_regs + mmSCRATCH_UMSK);
903         writel(0x30, remapped_regs + mmSCRATCH_UMSK);
904
905         /* Set up CIF */
906         cif_io.val = defCIF_IO;
907         writel((u32)(cif_io.val), remapped_regs + mmCIF_IO);
908
909         cif_write_dbg.val = readl(remapped_regs + mmCIF_WRITE_DBG);
910         cif_write_dbg.f.dis_packer_ful_during_rbbm_timeout = 0;
911         cif_write_dbg.f.en_dword_split_to_rbbm = 1;
912         cif_write_dbg.f.dis_timeout_during_rbbm = 1;
913         writel((u32) (cif_write_dbg.val), remapped_regs + mmCIF_WRITE_DBG);
914
915         cif_read_dbg.val = readl(remapped_regs + mmCIF_READ_DBG);
916         cif_read_dbg.f.dis_rd_same_byte_to_trig_fetch = 1;
917         writel((u32) (cif_read_dbg.val), remapped_regs + mmCIF_READ_DBG);
918
919         cif_cntl.val = readl(remapped_regs + mmCIF_CNTL);
920         cif_cntl.f.dis_system_bits = 1;
921         cif_cntl.f.dis_mr = 1;
922         cif_cntl.f.en_wait_to_compensate_dq_prop_dly = 0;
923         cif_cntl.f.intb_oe = 1;
924         cif_cntl.f.interrupt_active_high = 1;
925         writel((u32) (cif_cntl.val), remapped_regs + mmCIF_CNTL);
926
927         /* Setup cfgINTF_CNTL and cfgCPU defaults */
928         intf_cntl.val = defINTF_CNTL;
929         intf_cntl.f.ad_inc_a = 1;
930         intf_cntl.f.ad_inc_b = 1;
931         intf_cntl.f.rd_data_rdy_a = 0;
932         intf_cntl.f.rd_data_rdy_b = 0;
933         writeb((u8) (intf_cntl.val), remapped_base + cfgINTF_CNTL);
934
935         cpu_default.val = defCPU_DEFAULTS;
936         cpu_default.f.access_ind_addr_a = 1;
937         cpu_default.f.access_ind_addr_b = 1;
938         cpu_default.f.access_scratch_reg = 1;
939         cpu_default.f.transition_size = 0;
940         writeb((u8) (cpu_default.val), remapped_base + cfgCPU_DEFAULTS);
941
942         /* set up the apertures */
943         writeb((u8) (W100_REG_BASE >> 16), remapped_base + cfgREG_BASE);
944
945         cfgreg_base.val = defCFGREG_BASE;
946         cfgreg_base.f.cfgreg_base = W100_CFG_BASE;
947         writel((u32) (cfgreg_base.val), remapped_regs + mmCFGREG_BASE);
948
949         wrap_start_dir.val = defWRAP_START_DIR;
950         wrap_start_dir.f.start_addr = WRAP_BUF_BASE_VALUE >> 1;
951         writel((u32) (wrap_start_dir.val), remapped_regs + mmWRAP_START_DIR);
952
953         wrap_top_dir.val = defWRAP_TOP_DIR;
954         wrap_top_dir.f.top_addr = WRAP_BUF_TOP_VALUE >> 1;
955         writel((u32) (wrap_top_dir.val), remapped_regs + mmWRAP_TOP_DIR);
956
957         writel((u32) 0x2440, remapped_regs + mmRBBM_CNTL);
958
959         /* Set the hardware to 565 colour */
960         temp32 = readl(remapped_regs + mmDISP_DEBUG2);
961         temp32 &= 0xff7fffff;
962         temp32 |= 0x00800000;
963         writel(temp32, remapped_regs + mmDISP_DEBUG2);
964
965         /* Initialise the GPIO lines */
966         if (gpio) {
967                 writel(gpio->init_data1, remapped_regs + mmGPIO_DATA);
968                 writel(gpio->init_data2, remapped_regs + mmGPIO_DATA2);
969                 writel(gpio->gpio_dir1,  remapped_regs + mmGPIO_CNTL1);
970                 writel(gpio->gpio_oe1,   remapped_regs + mmGPIO_CNTL2);
971                 writel(gpio->gpio_dir2,  remapped_regs + mmGPIO_CNTL3);
972                 writel(gpio->gpio_oe2,   remapped_regs + mmGPIO_CNTL4);
973         }
974 }
975
976
977 struct power_state {
978         union clk_pin_cntl_u clk_pin_cntl;
979         union pll_ref_fb_div_u pll_ref_fb_div;
980         union pll_cntl_u pll_cntl;
981         union sclk_cntl_u sclk_cntl;
982         union pclk_cntl_u pclk_cntl;
983         union pwrmgt_cntl_u pwrmgt_cntl;
984         int auto_mode;  /* system clock auto changing? */
985 };
986
987
988 static struct power_state w100_pwr_state;
989
990 /* The PLL Fout is determined by (XtalFreq/(M+1)) * ((N_int+1) + (N_fac/8)) */
991
992 /* 12.5MHz Crystal PLL Table */
993 static struct w100_pll_info xtal_12500000[] = {
994         /*freq     M   N_int    N_fac  tfgoal  lock_time */
995         { 50,      0,   1,       0,     0xe0,        56},  /*  50.00 MHz */
996         { 75,      0,   5,       0,     0xde,        37},  /*  75.00 MHz */
997         {100,      0,   7,       0,     0xe0,        28},  /* 100.00 MHz */
998         {125,      0,   9,       0,     0xe0,        22},  /* 125.00 MHz */
999         {150,      0,   11,      0,     0xe0,        17},  /* 150.00 MHz */
1000         {  0,      0,   0,       0,        0,         0},  /* Terminator */
1001 };
1002
1003 /* 14.318MHz Crystal PLL Table */
1004 static struct w100_pll_info xtal_14318000[] = {
1005         /*freq     M   N_int    N_fac  tfgoal  lock_time */
1006         { 40,      4,   13,      0,     0xe0,        80}, /* tfgoal guessed */
1007         { 50,      1,   6,       0,     0xe0,        64}, /*  50.05 MHz */
1008         { 57,      2,   11,      0,     0xe0,        53}, /* tfgoal guessed */
1009         { 75,      0,   4,       3,     0xe0,        43}, /*  75.08 MHz */
1010         {100,      0,   6,       0,     0xe0,        32}, /* 100.10 MHz */
1011         {  0,      0,   0,       0,        0,         0},
1012 };
1013
1014 /* 16MHz Crystal PLL Table */
1015 static struct w100_pll_info xtal_16000000[] = {
1016         /*freq     M   N_int    N_fac  tfgoal  lock_time */
1017         { 72,      1,   8,       0,     0xe0,        48}, /* tfgoal guessed */
1018         { 80,      1,   9,       0,     0xe0,        13}, /* tfgoal guessed */
1019         { 95,      1,   10,      7,     0xe0,        38}, /* tfgoal guessed */
1020         { 96,      1,   11,      0,     0xe0,        36}, /* tfgoal guessed */
1021         {  0,      0,   0,       0,        0,         0},
1022 };
1023
1024 static struct pll_entries {
1025         int xtal_freq;
1026         struct w100_pll_info *pll_table;
1027 } w100_pll_tables[] = {
1028         { 12500000, &xtal_12500000[0] },
1029         { 14318000, &xtal_14318000[0] },
1030         { 16000000, &xtal_16000000[0] },
1031         { 0 },
1032 };
1033
1034 struct w100_pll_info *w100_get_xtal_table(unsigned int freq)
1035 {
1036         struct pll_entries *pll_entry = w100_pll_tables;
1037
1038         do {
1039                 if (freq == pll_entry->xtal_freq)
1040                         return pll_entry->pll_table;
1041                 pll_entry++;
1042         } while (pll_entry->xtal_freq);
1043         return 0;
1044 }
1045
1046
1047 static unsigned int w100_get_testcount(unsigned int testclk_sel)
1048 {
1049         union clk_test_cntl_u clk_test_cntl;
1050
1051         udelay(5);
1052
1053         /* Select the test clock source and reset */
1054         clk_test_cntl.f.start_check_freq = 0x0;
1055         clk_test_cntl.f.testclk_sel = testclk_sel;
1056         clk_test_cntl.f.tstcount_rst = 0x1; /* set reset */
1057         writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1058
1059         clk_test_cntl.f.tstcount_rst = 0x0; /* clear reset */
1060         writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1061
1062         /* Run clock test */
1063         clk_test_cntl.f.start_check_freq = 0x1;
1064         writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1065
1066         /* Give the test time to complete */
1067         udelay(20);
1068
1069         /* Return the result */
1070         clk_test_cntl.val = readl(remapped_regs + mmCLK_TEST_CNTL);
1071         clk_test_cntl.f.start_check_freq = 0x0;
1072         writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1073
1074         return clk_test_cntl.f.test_count;
1075 }
1076
1077
1078 static int w100_pll_adjust(struct w100_pll_info *pll)
1079 {
1080         unsigned int tf80;
1081         unsigned int tf20;
1082
1083         /* Initial Settings */
1084         w100_pwr_state.pll_cntl.f.pll_pwdn = 0x0;     /* power down */
1085         w100_pwr_state.pll_cntl.f.pll_reset = 0x0;    /* not reset */
1086         w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x1;   /* Hi-Z */
1087         w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;      /* VCO gain = 0 */
1088         w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0;    /* VCO frequency range control = off */
1089         w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;  /* current offset inside VCO = 0 */
1090         w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
1091
1092         /* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V
1093          * therefore, commented out the following lines
1094          * tf80 meant tf100
1095          */
1096         do {
1097                 /* set VCO input = 0.8 * VDD */
1098                 w100_pwr_state.pll_cntl.f.pll_dactal = 0xd;
1099                 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1100
1101                 tf80 = w100_get_testcount(TESTCLK_SRC_PLL);
1102                 if (tf80 >= (pll->tfgoal)) {
1103                         /* set VCO input = 0.2 * VDD */
1104                         w100_pwr_state.pll_cntl.f.pll_dactal = 0x7;
1105                         writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1106
1107                         tf20 = w100_get_testcount(TESTCLK_SRC_PLL);
1108                         if (tf20 <= (pll->tfgoal))
1109                                 return 1;  /* Success */
1110
1111                         if ((w100_pwr_state.pll_cntl.f.pll_vcofr == 0x0) &&
1112                                 ((w100_pwr_state.pll_cntl.f.pll_pvg == 0x7) ||
1113                                 (w100_pwr_state.pll_cntl.f.pll_ioffset == 0x0))) {
1114                                 /* slow VCO config */
1115                                 w100_pwr_state.pll_cntl.f.pll_vcofr = 0x1;
1116                                 w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
1117                                 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1118                                 continue;
1119                         }
1120                 }
1121                 if ((w100_pwr_state.pll_cntl.f.pll_ioffset) < 0x3) {
1122                         w100_pwr_state.pll_cntl.f.pll_ioffset += 0x1;
1123                 } else if ((w100_pwr_state.pll_cntl.f.pll_pvg) < 0x7) {
1124                         w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1125                         w100_pwr_state.pll_cntl.f.pll_pvg += 0x1;
1126                 } else {
1127                         return 0;  /* Error */
1128                 }
1129         } while(1);
1130 }
1131
1132
1133 /*
1134  * w100_pll_calibration
1135  */
1136 static int w100_pll_calibration(struct w100_pll_info *pll)
1137 {
1138         int status;
1139
1140         status = w100_pll_adjust(pll);
1141
1142         /* PLL Reset And Lock */
1143         /* set VCO input = 0.5 * VDD */
1144         w100_pwr_state.pll_cntl.f.pll_dactal = 0xa;
1145         writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1146
1147         udelay(1);  /* reset time */
1148
1149         /* enable charge pump */
1150         w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;  /* normal */
1151         writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1152
1153         /* set VCO input = Hi-Z, disable DAC */
1154         w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;
1155         writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1156
1157         udelay(400);  /* lock time */
1158
1159         /* PLL locked */
1160
1161         return status;
1162 }
1163
1164
1165 static int w100_pll_set_clk(struct w100_pll_info *pll)
1166 {
1167         int status;
1168
1169         if (w100_pwr_state.auto_mode == 1)  /* auto mode */
1170         {
1171                 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;  /* disable fast to normal */
1172                 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;  /* disable normal to fast */
1173                 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1174         }
1175
1176         /* Set system clock source to XTAL whilst adjusting the PLL! */
1177         w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
1178         writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1179
1180         w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = pll->M;
1181         w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = pll->N_int;
1182         w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = pll->N_fac;
1183         w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = pll->lock_time;
1184         writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
1185
1186         w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0;
1187         writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1188
1189         status = w100_pll_calibration(pll);
1190
1191         if (w100_pwr_state.auto_mode == 1)  /* auto mode */
1192         {
1193                 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x1;  /* reenable fast to normal */
1194                 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x1;  /* reenable normal to fast  */
1195                 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1196         }
1197         return status;
1198 }
1199
1200 /* freq = target frequency of the PLL */
1201 static int w100_set_pll_freq(struct w100fb_par *par, unsigned int freq)
1202 {
1203         struct w100_pll_info *pll = par->pll_table;
1204
1205         do {
1206                 if (freq == pll->freq) {
1207                         return w100_pll_set_clk(pll);
1208                 }
1209                 pll++;
1210         } while(pll->freq);
1211         return 0;
1212 }
1213
1214 /* Set up an initial state.  Some values/fields set
1215    here will be overwritten. */
1216 static void w100_pwm_setup(struct w100fb_par *par)
1217 {
1218         w100_pwr_state.clk_pin_cntl.f.osc_en = 0x1;
1219         w100_pwr_state.clk_pin_cntl.f.osc_gain = 0x1f;
1220         w100_pwr_state.clk_pin_cntl.f.dont_use_xtalin = 0x0;
1221         w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x0;
1222         w100_pwr_state.clk_pin_cntl.f.xtalin_dbl_en = par->mach->xtal_dbl ? 1 : 0;
1223         w100_pwr_state.clk_pin_cntl.f.cg_debug = 0x0;
1224         writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL);
1225
1226         w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
1227         w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = 0x0;  /* Pfast = 1 */
1228         w100_pwr_state.sclk_cntl.f.sclk_clkon_hys = 0x3;
1229         w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0;  /* Pslow = 1 */
1230         w100_pwr_state.sclk_cntl.f.disp_cg_ok2switch_en = 0x0;
1231         w100_pwr_state.sclk_cntl.f.sclk_force_reg = 0x0;    /* Dynamic */
1232         w100_pwr_state.sclk_cntl.f.sclk_force_disp = 0x0;   /* Dynamic */
1233         w100_pwr_state.sclk_cntl.f.sclk_force_mc = 0x0;     /* Dynamic */
1234         w100_pwr_state.sclk_cntl.f.sclk_force_extmc = 0x0;  /* Dynamic */
1235         w100_pwr_state.sclk_cntl.f.sclk_force_cp = 0x0;     /* Dynamic */
1236         w100_pwr_state.sclk_cntl.f.sclk_force_e2 = 0x0;     /* Dynamic */
1237         w100_pwr_state.sclk_cntl.f.sclk_force_e3 = 0x0;     /* Dynamic */
1238         w100_pwr_state.sclk_cntl.f.sclk_force_idct = 0x0;   /* Dynamic */
1239         w100_pwr_state.sclk_cntl.f.sclk_force_bist = 0x0;   /* Dynamic */
1240         w100_pwr_state.sclk_cntl.f.busy_extend_cp = 0x0;
1241         w100_pwr_state.sclk_cntl.f.busy_extend_e2 = 0x0;
1242         w100_pwr_state.sclk_cntl.f.busy_extend_e3 = 0x0;
1243         w100_pwr_state.sclk_cntl.f.busy_extend_idct = 0x0;
1244         writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1245
1246         w100_pwr_state.pclk_cntl.f.pclk_src_sel = CLK_SRC_XTAL;
1247         w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1;    /* P = 2 */
1248         w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0;  /* Dynamic */
1249         writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
1250
1251         w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0;     /* M = 1 */
1252         w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0;  /* N = 1.0 */
1253         w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = 0x0;
1254         w100_pwr_state.pll_ref_fb_div.f.pll_reset_time = 0x5;
1255         w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = 0xff;
1256         writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
1257
1258         w100_pwr_state.pll_cntl.f.pll_pwdn = 0x1;
1259         w100_pwr_state.pll_cntl.f.pll_reset = 0x1;
1260         w100_pwr_state.pll_cntl.f.pll_pm_en = 0x0;
1261         w100_pwr_state.pll_cntl.f.pll_mode = 0x0;  /* uses VCO clock */
1262         w100_pwr_state.pll_cntl.f.pll_refclk_sel = 0x0;
1263         w100_pwr_state.pll_cntl.f.pll_fbclk_sel = 0x0;
1264         w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;
1265         w100_pwr_state.pll_cntl.f.pll_pcp = 0x4;
1266         w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
1267         w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0;
1268         w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1269         w100_pwr_state.pll_cntl.f.pll_pecc_mode = 0x0;
1270         w100_pwr_state.pll_cntl.f.pll_pecc_scon = 0x0;
1271         w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;  /* Hi-Z */
1272         w100_pwr_state.pll_cntl.f.pll_cp_clip = 0x3;
1273         w100_pwr_state.pll_cntl.f.pll_conf = 0x2;
1274         w100_pwr_state.pll_cntl.f.pll_mbctrl = 0x2;
1275         w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
1276         writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1277
1278         w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x0;
1279         w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1;  /* normal mode (0, 1, 3) */
1280         w100_pwr_state.pwrmgt_cntl.f.pwm_wakeup_cond = 0x0;
1281         w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;
1282         w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;
1283         w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1;  /* PM4,ENG */
1284         w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1;  /* PM4,ENG */
1285         w100_pwr_state.pwrmgt_cntl.f.pwm_idle_timer = 0xFF;
1286         w100_pwr_state.pwrmgt_cntl.f.pwm_busy_timer = 0xFF;
1287         writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1288
1289         w100_pwr_state.auto_mode = 0;  /* manual mode */
1290 }
1291
1292
1293 /*
1294  * Setup the w100 clocks for the specified mode
1295  */
1296 static void w100_init_clocks(struct w100fb_par *par)
1297 {
1298         struct w100_mode *mode = par->mode;
1299
1300         if (mode->pixclk_src == CLK_SRC_PLL || mode->sysclk_src == CLK_SRC_PLL)
1301                 w100_set_pll_freq(par, (par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq);
1302
1303         w100_pwr_state.sclk_cntl.f.sclk_src_sel = mode->sysclk_src;
1304         w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = mode->sysclk_divider;
1305         w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = mode->sysclk_divider;
1306         writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1307 }
1308
1309 static void w100_init_lcd(struct w100fb_par *par)
1310 {
1311         u32 temp32;
1312         struct w100_mode *mode = par->mode;
1313         struct w100_gen_regs *regs = par->mach->regs;
1314         union active_h_disp_u active_h_disp;
1315         union active_v_disp_u active_v_disp;
1316         union graphic_h_disp_u graphic_h_disp;
1317         union graphic_v_disp_u graphic_v_disp;
1318         union crtc_total_u crtc_total;
1319
1320         /* w3200 doesn't like undefined bits being set so zero register values first */
1321
1322         active_h_disp.val = 0;
1323         active_h_disp.f.active_h_start=mode->left_margin;
1324         active_h_disp.f.active_h_end=mode->left_margin + mode->xres;
1325         writel(active_h_disp.val, remapped_regs + mmACTIVE_H_DISP);
1326
1327         active_v_disp.val = 0;
1328         active_v_disp.f.active_v_start=mode->upper_margin;
1329         active_v_disp.f.active_v_end=mode->upper_margin + mode->yres;
1330         writel(active_v_disp.val, remapped_regs + mmACTIVE_V_DISP);
1331
1332         graphic_h_disp.val = 0;
1333         graphic_h_disp.f.graphic_h_start=mode->left_margin;
1334         graphic_h_disp.f.graphic_h_end=mode->left_margin + mode->xres;
1335         writel(graphic_h_disp.val, remapped_regs + mmGRAPHIC_H_DISP);
1336
1337         graphic_v_disp.val = 0;
1338         graphic_v_disp.f.graphic_v_start=mode->upper_margin;
1339         graphic_v_disp.f.graphic_v_end=mode->upper_margin + mode->yres;
1340         writel(graphic_v_disp.val, remapped_regs + mmGRAPHIC_V_DISP);
1341
1342         crtc_total.val = 0;
1343         crtc_total.f.crtc_h_total=mode->left_margin  + mode->xres + mode->right_margin;
1344         crtc_total.f.crtc_v_total=mode->upper_margin + mode->yres + mode->lower_margin;
1345         writel(crtc_total.val, remapped_regs + mmCRTC_TOTAL);
1346
1347         writel(mode->crtc_ss, remapped_regs + mmCRTC_SS);
1348         writel(mode->crtc_ls, remapped_regs + mmCRTC_LS);
1349         writel(mode->crtc_gs, remapped_regs + mmCRTC_GS);
1350         writel(mode->crtc_vpos_gs, remapped_regs + mmCRTC_VPOS_GS);
1351         writel(mode->crtc_rev, remapped_regs + mmCRTC_REV);
1352         writel(mode->crtc_dclk, remapped_regs + mmCRTC_DCLK);
1353         writel(mode->crtc_gclk, remapped_regs + mmCRTC_GCLK);
1354         writel(mode->crtc_goe, remapped_regs + mmCRTC_GOE);
1355         writel(mode->crtc_ps1_active, remapped_regs + mmCRTC_PS1_ACTIVE);
1356
1357         writel(regs->lcd_format, remapped_regs + mmLCD_FORMAT);
1358         writel(regs->lcdd_cntl1, remapped_regs + mmLCDD_CNTL1);
1359         writel(regs->lcdd_cntl2, remapped_regs + mmLCDD_CNTL2);
1360         writel(regs->genlcd_cntl1, remapped_regs + mmGENLCD_CNTL1);
1361         writel(regs->genlcd_cntl2, remapped_regs + mmGENLCD_CNTL2);
1362         writel(regs->genlcd_cntl3, remapped_regs + mmGENLCD_CNTL3);
1363
1364         writel(0x00000000, remapped_regs + mmCRTC_FRAME);
1365         writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS);
1366         writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT);
1367         writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR);
1368
1369         /* Hack for overlay in ext memory */
1370         temp32 = readl(remapped_regs + mmDISP_DEBUG2);
1371         temp32 |= 0xc0000000;
1372         writel(temp32, remapped_regs + mmDISP_DEBUG2);
1373 }
1374
1375
1376 static void w100_setup_memory(struct w100fb_par *par)
1377 {
1378         union mc_ext_mem_location_u extmem_location;
1379         union mc_fb_location_u intmem_location;
1380         struct w100_mem_info *mem = par->mach->mem;
1381         struct w100_bm_mem_info *bm_mem = par->mach->bm_mem;
1382
1383         if (!par->extmem_active) {
1384                 w100_suspend(W100_SUSPEND_EXTMEM);
1385
1386                 /* Map Internal Memory at FB Base */
1387                 intmem_location.f.mc_fb_start = W100_FB_BASE >> 8;
1388                 intmem_location.f.mc_fb_top = (W100_FB_BASE+MEM_INT_SIZE) >> 8;
1389                 writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
1390
1391                 /* Unmap External Memory - value is *probably* irrelevant but may have meaning
1392                    to acceleration libraries */
1393                 extmem_location.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8;
1394                 extmem_location.f.mc_ext_mem_top = (MEM_EXT_BASE_VALUE-1) >> 8;
1395                 writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
1396         } else {
1397                 /* Map Internal Memory to its default location */
1398                 intmem_location.f.mc_fb_start = MEM_INT_BASE_VALUE >> 8;
1399                 intmem_location.f.mc_fb_top = (MEM_INT_BASE_VALUE+MEM_INT_SIZE) >> 8;
1400                 writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
1401
1402                 /* Map External Memory at FB Base */
1403                 extmem_location.f.mc_ext_mem_start = W100_FB_BASE >> 8;
1404                 extmem_location.f.mc_ext_mem_top = (W100_FB_BASE+par->mach->mem->size) >> 8;
1405                 writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
1406
1407                 writel(0x00007800, remapped_regs + mmMC_BIST_CTRL);
1408                 writel(mem->ext_cntl, remapped_regs + mmMEM_EXT_CNTL);
1409                 writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
1410                 udelay(100);
1411                 writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
1412                 udelay(100);
1413                 writel(mem->sdram_mode_reg, remapped_regs + mmMEM_SDRAM_MODE_REG);
1414                 udelay(100);
1415                 writel(mem->ext_timing_cntl, remapped_regs + mmMEM_EXT_TIMING_CNTL);
1416                 writel(mem->io_cntl, remapped_regs + mmMEM_IO_CNTL);
1417                 if (bm_mem) {
1418                         writel(bm_mem->ext_mem_bw, remapped_regs + mmBM_EXT_MEM_BANDWIDTH);
1419                         writel(bm_mem->offset, remapped_regs + mmBM_OFFSET);
1420                         writel(bm_mem->ext_timing_ctl, remapped_regs + mmBM_MEM_EXT_TIMING_CNTL);
1421                         writel(bm_mem->ext_cntl, remapped_regs + mmBM_MEM_EXT_CNTL);
1422                         writel(bm_mem->mode_reg, remapped_regs + mmBM_MEM_MODE_REG);
1423                         writel(bm_mem->io_cntl, remapped_regs + mmBM_MEM_IO_CNTL);
1424                         writel(bm_mem->config, remapped_regs + mmBM_CONFIG);
1425                 }
1426         }
1427 }
1428
1429 static void w100_set_dispregs(struct w100fb_par *par)
1430 {
1431         unsigned long rot=0, divider, offset=0;
1432         union graphic_ctrl_u graphic_ctrl;
1433
1434         /* See if the mode has been rotated */
1435         if (par->xres == par->mode->xres) {
1436                 if (par->flip) {
1437                         rot=3; /* 180 degree */
1438                         offset=(par->xres * par->yres) - 1;
1439                 } /* else 0 degree */
1440                 divider = par->mode->pixclk_divider;
1441         } else {
1442                 if (par->flip) {
1443                         rot=2; /* 270 degree */
1444                         offset=par->xres - 1;
1445                 } else {
1446                         rot=1; /* 90 degree */
1447                         offset=par->xres * (par->yres - 1);
1448                 }
1449                 divider = par->mode->pixclk_divider_rotated;
1450         }
1451
1452         graphic_ctrl.val = 0; /* w32xx doesn't like undefined bits */
1453         switch (par->chip_id) {
1454                 case CHIP_ID_W100:
1455                         graphic_ctrl.f_w100.color_depth=6;
1456                         graphic_ctrl.f_w100.en_crtc=1;
1457                         graphic_ctrl.f_w100.en_graphic_req=1;
1458                         graphic_ctrl.f_w100.en_graphic_crtc=1;
1459                         graphic_ctrl.f_w100.lcd_pclk_on=1;
1460                         graphic_ctrl.f_w100.lcd_sclk_on=1;
1461                         graphic_ctrl.f_w100.low_power_on=0;
1462                         graphic_ctrl.f_w100.req_freq=0;
1463                         graphic_ctrl.f_w100.portrait_mode=rot;
1464
1465                         /* Zaurus needs this */
1466                         switch(par->xres) {
1467                                 case 240:
1468                                 case 320:
1469                                 default:
1470                                         graphic_ctrl.f_w100.total_req_graphic=0xa0;
1471                                         break;
1472                                 case 480:
1473                                 case 640:
1474                                         switch(rot) {
1475                                                 case 0:  /* 0 */
1476                                                 case 3:  /* 180 */
1477                                                         graphic_ctrl.f_w100.low_power_on=1;
1478                                                         graphic_ctrl.f_w100.req_freq=5;
1479                                                 break;
1480                                                 case 1:  /* 90 */
1481                                                 case 2:  /* 270 */
1482                                                         graphic_ctrl.f_w100.req_freq=4;
1483                                                         break;
1484                                                 default:
1485                                                         break;
1486                                         }
1487                                         graphic_ctrl.f_w100.total_req_graphic=0xf0;
1488                                         break;
1489                         }
1490                         break;
1491                 case CHIP_ID_W3200:
1492                 case CHIP_ID_W3220:
1493                         graphic_ctrl.f_w32xx.color_depth=6;
1494                         graphic_ctrl.f_w32xx.en_crtc=1;
1495                         graphic_ctrl.f_w32xx.en_graphic_req=1;
1496                         graphic_ctrl.f_w32xx.en_graphic_crtc=1;
1497                         graphic_ctrl.f_w32xx.lcd_pclk_on=1;
1498                         graphic_ctrl.f_w32xx.lcd_sclk_on=1;
1499                         graphic_ctrl.f_w32xx.low_power_on=0;
1500                         graphic_ctrl.f_w32xx.req_freq=0;
1501                         graphic_ctrl.f_w32xx.total_req_graphic=par->mode->xres >> 1; /* panel xres, not mode */
1502                         graphic_ctrl.f_w32xx.portrait_mode=rot;
1503                         break;
1504         }
1505
1506         /* Set the pixel clock source and divider */
1507         w100_pwr_state.pclk_cntl.f.pclk_src_sel = par->mode->pixclk_src;
1508         w100_pwr_state.pclk_cntl.f.pclk_post_div = divider;
1509         writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
1510
1511         writel(graphic_ctrl.val, remapped_regs + mmGRAPHIC_CTRL);
1512         writel(W100_FB_BASE + ((offset * BITS_PER_PIXEL/8)&~0x03UL), remapped_regs + mmGRAPHIC_OFFSET);
1513         writel((par->xres*BITS_PER_PIXEL/8), remapped_regs + mmGRAPHIC_PITCH);
1514 }
1515
1516
1517 /*
1518  * Work out how long the sync pulse lasts
1519  * Value is 1/(time in seconds)
1520  */
1521 static void calc_hsync(struct w100fb_par *par)
1522 {
1523         unsigned long hsync;
1524         struct w100_mode *mode = par->mode;
1525         union crtc_ss_u crtc_ss;
1526
1527         if (mode->pixclk_src == CLK_SRC_XTAL)
1528                 hsync=par->mach->xtal_freq;
1529         else
1530                 hsync=((par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq)*100000;
1531
1532         hsync /= (w100_pwr_state.pclk_cntl.f.pclk_post_div + 1);
1533
1534         crtc_ss.val = readl(remapped_regs + mmCRTC_SS);
1535         if (crtc_ss.val)
1536                 par->hsync_len = hsync / (crtc_ss.f.ss_end-crtc_ss.f.ss_start);
1537         else
1538                 par->hsync_len = 0;
1539 }
1540
1541 static void w100_suspend(u32 mode)
1542 {
1543         u32 val;
1544
1545         writel(0x7FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION);
1546         writel(0x00FF0000, remapped_regs + mmMC_PERF_MON_CNTL);
1547
1548         val = readl(remapped_regs + mmMEM_EXT_TIMING_CNTL);
1549         val &= ~(0x00100000);  /* bit20=0 */
1550         val |= 0xFF000000;     /* bit31:24=0xff */
1551         writel(val, remapped_regs + mmMEM_EXT_TIMING_CNTL);
1552
1553         val = readl(remapped_regs + mmMEM_EXT_CNTL);
1554         val &= ~(0x00040000);  /* bit18=0 */
1555         val |= 0x00080000;     /* bit19=1 */
1556         writel(val, remapped_regs + mmMEM_EXT_CNTL);
1557
1558         udelay(1);  /* wait 1us */
1559
1560         if (mode == W100_SUSPEND_EXTMEM) {
1561                 /* CKE: Tri-State */
1562                 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1563                 val |= 0x40000000;  /* bit30=1 */
1564                 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1565
1566                 /* CLK: Stop */
1567                 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1568                 val &= ~(0x00000001);  /* bit0=0 */
1569                 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1570         } else {
1571                 writel(0x00000000, remapped_regs + mmSCLK_CNTL);
1572                 writel(0x000000BF, remapped_regs + mmCLK_PIN_CNTL);
1573                 writel(0x00000015, remapped_regs + mmPWRMGT_CNTL);
1574
1575                 udelay(5);
1576
1577                 val = readl(remapped_regs + mmPLL_CNTL);
1578                 val |= 0x00000004;  /* bit2=1 */
1579                 writel(val, remapped_regs + mmPLL_CNTL);
1580
1581                 writel(0x00000000, remapped_regs + mmLCDD_CNTL1);
1582                 writel(0x00000000, remapped_regs + mmLCDD_CNTL2);
1583                 writel(0x00000000, remapped_regs + mmGENLCD_CNTL1);
1584                 writel(0x00000000, remapped_regs + mmGENLCD_CNTL2);
1585                 writel(0x00000000, remapped_regs + mmGENLCD_CNTL3);
1586
1587                 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1588                 val |= 0xF0000000;
1589                 val &= ~(0x00000001);
1590                 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1591
1592                 writel(0x0000001d, remapped_regs + mmPWRMGT_CNTL);
1593         }
1594 }
1595
1596 static void w100_vsync(void)
1597 {
1598         u32 tmp;
1599         int timeout = 30000;  /* VSync timeout = 30[ms] > 16.8[ms] */
1600
1601         tmp = readl(remapped_regs + mmACTIVE_V_DISP);
1602
1603         /* set vline pos  */
1604         writel((tmp >> 16) & 0x3ff, remapped_regs + mmDISP_INT_CNTL);
1605
1606         /* disable vline irq */
1607         tmp = readl(remapped_regs + mmGEN_INT_CNTL);
1608
1609         tmp &= ~0x00000002;
1610         writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1611
1612         /* clear vline irq status */
1613         writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1614
1615         /* enable vline irq */
1616         writel((tmp | 0x00000002), remapped_regs + mmGEN_INT_CNTL);
1617
1618         /* clear vline irq status */
1619         writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1620
1621         while(timeout > 0) {
1622                 if (readl(remapped_regs + mmGEN_INT_STATUS) & 0x00000002)
1623                         break;
1624                 udelay(1);
1625                 timeout--;
1626         }
1627
1628         /* disable vline irq */
1629         writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1630
1631         /* clear vline irq status */
1632         writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1633 }
1634
1635 static struct platform_driver w100fb_driver = {
1636         .probe          = w100fb_probe,
1637         .remove         = w100fb_remove,
1638         .suspend        = w100fb_suspend,
1639         .resume         = w100fb_resume,
1640         .driver         = {
1641                 .name   = "w100fb",
1642         },
1643 };
1644
1645 module_platform_driver(w100fb_driver);
1646
1647 MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
1648 MODULE_LICENSE("GPL");