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