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