[PATCH] Kprobes: preempt_disable/enable() simplification
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / video / w100fb.c
blobcf8cdb108fd95c0d1eb2f3be7e947804e6a5abb8
1 /*
2 * linux/drivers/video/w100fb.c
4 * Frame Buffer Device for ATI Imageon w100 (Wallaby)
6 * Copyright (C) 2002, ATI Corp.
7 * Copyright (C) 2004-2005 Richard Purdie
8 * Copyright (c) 2005 Ian Molton
10 * Rewritten for 2.6 by Richard Purdie <rpurdie@rpsys.net>
12 * Generic platform support by Ian Molton <spyro@f2s.com>
13 * and Richard Purdie <rpurdie@rpsys.net>
15 * w32xx support by Ian Molton
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.
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"
37 * Prototypes
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);
52 /* Pseudo palette size */
53 #define MAX_PALETTES 16
55 #define W100_SUSPEND_EXTMEM 0
56 #define W100_SUSPEND_ALL 1
58 #define BITS_PER_PIXEL 16
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;
65 #define REMAPPED_FB_LEN 0x15ffff
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
74 * Sysfs functions
76 static ssize_t flip_show(struct device *dev, struct device_attribute *attr, char *buf)
78 struct fb_info *info = dev_get_drvdata(dev);
79 struct w100fb_par *par=info->par;
81 return sprintf(buf, "%d\n",par->flip);
84 static ssize_t flip_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
86 unsigned int flip;
87 struct fb_info *info = dev_get_drvdata(dev);
88 struct w100fb_par *par=info->par;
90 flip = simple_strtoul(buf, NULL, 10);
92 if (flip > 0)
93 par->flip = 1;
94 else
95 par->flip = 0;
97 w100_update_disable();
98 w100_set_dispregs(par);
99 w100_update_enable();
101 calc_hsync(par);
103 return count;
106 static DEVICE_ATTR(flip, 0644, flip_show, flip_store);
108 static ssize_t w100fb_reg_read(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
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;
117 static DEVICE_ATTR(reg_read, 0200, NULL, w100fb_reg_read);
119 static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
121 unsigned long regs, param;
122 sscanf(buf, "%lx %lx", &regs, &param);
124 if (regs <= 0x2000) {
125 printk("Write Register 0x%08lX: 0x%08lX\n", regs, param);
126 writel(param, remapped_regs + regs);
129 return count;
132 static DEVICE_ATTR(reg_write, 0200, NULL, w100fb_reg_write);
135 static ssize_t fastpllclk_show(struct device *dev, struct device_attribute *attr, char *buf)
137 struct fb_info *info = dev_get_drvdata(dev);
138 struct w100fb_par *par=info->par;
140 return sprintf(buf, "%d\n",par->fastpll_mode);
143 static ssize_t fastpllclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
145 struct fb_info *info = dev_get_drvdata(dev);
146 struct w100fb_par *par=info->par;
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");
156 w100_init_clocks(par);
157 calc_hsync(par);
159 return count;
162 static DEVICE_ATTR(fastpllclk, 0644, fastpllclk_show, fastpllclk_store);
165 * Some touchscreens need hsync information from the video driver to
166 * function correctly. We export it here.
168 unsigned long w100fb_get_hsynclen(struct device *dev)
170 struct fb_info *info = dev_get_drvdata(dev);
171 struct w100fb_par *par=info->par;
173 /* If display is blanked/suspended, hsync isn't active */
174 if (par->blanked)
175 return 0;
176 else
177 return par->hsync_len;
179 EXPORT_SYMBOL(w100fb_get_hsynclen);
181 static void w100fb_clear_screen(struct w100fb_par *par)
183 memset_io(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), 0, (par->xres * par->yres * BITS_PER_PIXEL/8));
188 * Set a palette value from rgb components
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)
193 unsigned int val;
194 int ret = 1;
197 * If greyscale is true, then we convert the RGB value
198 * to greyscale no matter what visual we are using.
200 if (info->var.grayscale)
201 red = green = blue = (19595 * red + 38470 * green + 7471 * blue) >> 16;
204 * 16-bit True Colour. We encode the RGB value
205 * according to the RGB bitfield information.
207 if (regno < MAX_PALETTES) {
208 u32 *pal = info->pseudo_palette;
210 val = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
211 pal[regno] = val;
212 ret = 0;
214 return ret;
219 * Blank the display based on value in blank_mode
221 static int w100fb_blank(int blank_mode, struct fb_info *info)
223 struct w100fb_par *par = info->par;
224 struct w100_tg_info *tg = par->mach->tg;
226 switch(blank_mode) {
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;
237 break;
239 case FB_BLANK_UNBLANK: /* Unblanking */
240 if (par->blanked != 0) {
241 if(tg && tg->resume)
242 tg->resume(par);
243 par->blanked = 0;
245 break;
247 return 0;
252 * Change the resolution by calling the appropriate hardware functions
254 static void w100fb_activate_var(struct w100fb_par *par)
256 struct w100_tg_info *tg = par->mach->tg;
258 w100_pwm_setup(par);
259 w100_setup_memory(par);
260 w100_init_clocks(par);
261 w100fb_clear_screen(par);
262 w100_vsync();
264 w100_update_disable();
265 w100_init_lcd(par);
266 w100_set_dispregs(par);
267 w100_update_enable();
269 calc_hsync(par);
271 if (!par->blanked && tg && tg->change)
272 tg->change(par);
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.
280 static struct w100_mode *w100fb_get_mode(struct w100fb_par *par, unsigned int *x, unsigned int *y, int saveval)
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;
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];
301 if (mode && saveval) {
302 *x = best_x;
303 *y = best_y;
306 return mode;
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.
315 static int w100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
317 struct w100fb_par *par=info->par;
319 if(!w100fb_get_mode(par, &var->xres, &var->yres, 1))
320 return -EINVAL;
322 if (par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (par->mach->mem->size+1)))
323 return -EINVAL;
325 if (!par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)))
326 return -EINVAL;
328 var->xres_virtual = max(var->xres_virtual, var->xres);
329 var->yres_virtual = max(var->yres_virtual, var->yres);
331 if (var->bits_per_pixel > BITS_PER_PIXEL)
332 return -EINVAL;
333 else
334 var->bits_per_pixel = BITS_PER_PIXEL;
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;
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; */
351 return 0;
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
360 static int w100fb_set_par(struct fb_info *info)
362 struct w100fb_par *par=info->par;
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);
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;
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;
382 w100fb_activate_var(par);
384 return 0;
389 * Frame buffer operations
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,
403 #ifdef CONFIG_PM
404 static void w100fb_save_vidmem(struct w100fb_par *par)
406 int memsize;
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);
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);
422 static void w100fb_restore_vidmem(struct w100fb_par *par)
424 int memsize;
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);
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);
441 static int w100fb_suspend(struct device *dev, pm_message_t state)
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;
447 w100fb_save_vidmem(par);
448 if(tg && tg->suspend)
449 tg->suspend(par);
450 w100_suspend(W100_SUSPEND_ALL);
451 par->blanked = 1;
453 return 0;
456 static int w100fb_resume(struct device *dev)
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;
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;
469 return 0;
471 #else
472 #define w100fb_suspend NULL
473 #define w100fb_resume NULL
474 #endif
477 int __init w100fb_probe(struct device *dev)
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;
487 if (!mem)
488 return -EINVAL;
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;
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;
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;
512 printk(" at 0x%08lx.\n", mem->start+W100_CFG_BASE);
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;
519 info=framebuffer_alloc(sizeof(struct w100fb_par), dev);
520 if (!info) {
521 err = -ENOMEM;
522 goto out;
525 par = info->par;
526 dev_set_drvdata(dev, info);
528 inf = dev->platform_data;
529 par->chip_id = chip_id;
530 par->mach = inf;
531 par->fastpll_mode = 0;
532 par->blanked = 0;
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;
541 info->pseudo_palette = kmalloc(sizeof (u32) * MAX_PALETTES, GFP_KERNEL);
542 if (!info->pseudo_palette) {
543 err = -ENOMEM;
544 goto out;
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;
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;
561 if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
562 err = -ENOMEM;
563 goto out;
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;
571 else {
572 info->var.xres = par->mode->xres;
573 info->var.yres = par->mode->yres;
576 if(inf->init_mode &= INIT_MODE_FLIPPED)
577 par->flip = 1;
578 else
579 par->flip = 0;
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;
590 w100_hw_init(par);
592 if (w100fb_check_var(&info->var, info) < 0) {
593 err = -EINVAL;
594 goto out;
597 w100fb_set_par(info);
599 if (register_framebuffer(info) < 0) {
600 err = -EINVAL;
601 goto out;
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);
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;
626 static int w100fb_remove(struct device *dev)
628 struct fb_info *info = dev_get_drvdata(dev);
629 struct w100fb_par *par=info->par;
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);
636 unregister_framebuffer(info);
638 vfree(par->saved_intmem);
639 vfree(par->saved_extmem);
640 kfree(info->pseudo_palette);
641 fb_dealloc_cmap(&info->cmap);
643 iounmap(remapped_base);
644 iounmap(remapped_regs);
645 iounmap(remapped_fbuf);
647 framebuffer_release(info);
649 return 0;
653 /* ------------------- chipset specific functions -------------------------- */
656 static void w100_soft_reset(void)
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);
665 static void w100_update_disable(void)
667 union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
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);
676 static void w100_update_enable(void)
678 union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
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);
687 unsigned long w100fb_gpio_read(int port)
689 unsigned long value;
691 if (port==W100_GPIO_PORT_A)
692 value = readl(remapped_regs + mmGPIO_DATA);
693 else
694 value = readl(remapped_regs + mmGPIO_DATA2);
696 return value;
699 void w100fb_gpio_write(int port, unsigned long value)
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);
706 EXPORT_SYMBOL(w100fb_gpio_read);
707 EXPORT_SYMBOL(w100fb_gpio_write);
710 * Initialization of critical w100 hardware
712 static void w100_hw_init(struct w100fb_par *par)
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;
726 w100_soft_reset();
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);
735 /* Set up CIF */
736 cif_io.val = defCIF_IO;
737 writel((u32)(cif_io.val), remapped_regs + mmCIF_IO);
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);
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);
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);
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);
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);
772 /* set up the apertures */
773 writeb((u8) (W100_REG_BASE >> 16), remapped_base + cfgREG_BASE);
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);
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);
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);
787 writel((u32) 0x2440, remapped_regs + mmRBBM_CNTL);
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);
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);
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? */
818 static struct power_state w100_pwr_state;
820 /* The PLL Fout is determined by (XtalFreq/(M+1)) * ((N_int+1) + (N_fac/8)) */
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 */
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},
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},
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 },
863 struct w100_pll_info *w100_get_xtal_table(unsigned int freq)
865 struct pll_entries *pll_entry = w100_pll_tables;
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;
876 static unsigned int w100_get_testcount(unsigned int testclk_sel)
878 union clk_test_cntl_u clk_test_cntl;
880 udelay(5);
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);
888 clk_test_cntl.f.tstcount_rst = 0x0; /* clear reset */
889 writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
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);
895 /* Give the test time to complete */
896 udelay(20);
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);
903 return clk_test_cntl.f.test_count;
907 static int w100_pll_adjust(struct w100_pll_info *pll)
909 unsigned int tf80;
910 unsigned int tf20;
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;
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
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);
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);
936 tf20 = w100_get_testcount(TESTCLK_SRC_PLL);
937 if (tf20 <= (pll->tfgoal))
938 return 1; /* Success */
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;
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 */
958 } while(1);
963 * w100_pll_calibration
965 static int w100_pll_calibration(struct w100_pll_info *pll)
967 int status;
969 status = w100_pll_adjust(pll);
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);
976 udelay(1); /* reset time */
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);
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);
986 udelay(400); /* lock time */
988 /* PLL locked */
990 return status;
994 static int w100_pll_set_clk(struct w100_pll_info *pll)
996 int status;
998 if (w100_pwr_state.auto_mode == 1) /* auto mode */
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);
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);
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);
1015 w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0;
1016 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1018 status = w100_pll_calibration(pll);
1020 if (w100_pwr_state.auto_mode == 1) /* auto mode */
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);
1026 return status;
1029 /* freq = target frequency of the PLL */
1030 static int w100_set_pll_freq(struct w100fb_par *par, unsigned int freq)
1032 struct w100_pll_info *pll = par->pll_table;
1034 do {
1035 if (freq == pll->freq) {
1036 return w100_pll_set_clk(pll);
1038 pll++;
1039 } while(pll->freq);
1040 return 0;
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)
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);
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);
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);
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);
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);
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);
1118 w100_pwr_state.auto_mode = 0; /* manual mode */
1123 * Setup the w100 clocks for the specified mode
1125 static void w100_init_clocks(struct w100fb_par *par)
1127 struct w100_mode *mode = par->mode;
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);
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);
1138 static void w100_init_lcd(struct w100fb_par *par)
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;
1149 /* w3200 doesnt like undefined bits being set so zero register values first */
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);
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);
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);
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);
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);
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);
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);
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);
1198 /* Hack for overlay in ext memory */
1199 temp32 = readl(remapped_regs + mmDISP_DEBUG2);
1200 temp32 |= 0xc0000000;
1201 writel(temp32, remapped_regs + mmDISP_DEBUG2);
1205 static void w100_setup_memory(struct w100fb_par *par)
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;
1212 if (!par->extmem_active) {
1213 w100_suspend(W100_SUSPEND_EXTMEM);
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);
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);
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);
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);
1258 static void w100_set_dispregs(struct w100fb_par *par)
1260 unsigned long rot=0, divider, offset=0;
1261 union graphic_ctrl_u graphic_ctrl;
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);
1278 divider = par->mode->pixclk_divider_rotated;
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;
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;
1316 graphic_ctrl.f_w100.total_req_graphic=0xf0;
1317 break;
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;
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);
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);
1347 * Work out how long the sync pulse lasts
1348 * Value is 1/(time in seconds)
1350 static void calc_hsync(struct w100fb_par *par)
1352 unsigned long hsync;
1353 struct w100_mode *mode = par->mode;
1354 union crtc_ss_u crtc_ss;
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;
1361 hsync /= (w100_pwr_state.pclk_cntl.f.pclk_post_div + 1);
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;
1370 static void w100_suspend(u32 mode)
1372 u32 val;
1374 writel(0x7FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION);
1375 writel(0x00FF0000, remapped_regs + mmMC_PERF_MON_CNTL);
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);
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);
1387 udelay(1); /* wait 1us */
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);
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);
1404 udelay(5);
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);
1413 static void w100_vsync(void)
1415 u32 tmp;
1416 int timeout = 30000; /* VSync timeout = 30[ms] > 16.8[ms] */
1418 tmp = readl(remapped_regs + mmACTIVE_V_DISP);
1420 /* set vline pos */
1421 writel((tmp >> 16) & 0x3ff, remapped_regs + mmDISP_INT_CNTL);
1423 /* disable vline irq */
1424 tmp = readl(remapped_regs + mmGEN_INT_CNTL);
1426 tmp &= ~0x00000002;
1427 writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1429 /* clear vline irq status */
1430 writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1432 /* enable vline irq */
1433 writel((tmp | 0x00000002), remapped_regs + mmGEN_INT_CNTL);
1435 /* clear vline irq status */
1436 writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1438 while(timeout > 0) {
1439 if (readl(remapped_regs + mmGEN_INT_STATUS) & 0x00000002)
1440 break;
1441 udelay(1);
1442 timeout--;
1445 /* disable vline irq */
1446 writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1448 /* clear vline irq status */
1449 writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
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,
1461 int __devinit w100fb_init(void)
1463 return driver_register(&w100fb_driver);
1466 void __exit w100fb_cleanup(void)
1468 driver_unregister(&w100fb_driver);
1471 module_init(w100fb_init);
1472 module_exit(w100fb_cleanup);
1474 MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
1475 MODULE_LICENSE("GPL");