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