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