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