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