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>
25 #include <linux/init.h>
26 #include <linux/kernel.h>
28 #include <linux/platform_device.h>
29 #include <linux/string.h>
30 #include <linux/vmalloc.h>
32 #include <asm/uaccess.h>
33 #include <video/w100fb.h>
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
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)
87 struct fb_info *info = dev_get_drvdata(dev);
88 struct w100fb_par *par=info->par;
90 flip = simple_strtoul(buf, NULL, 10);
97 w100_update_disable();
98 w100_set_dispregs(par);
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);
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", ®s, ¶m);
124 if (regs <= 0x2000) {
125 printk("Write Register 0x%08lX: 0x%08lX\n", regs, param);
126 writel(param, remapped_regs + regs);
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) {
150 printk("w100fb: Using fast system clock (if possible)\n");
153 printk("w100fb: Using normal system clock\n");
156 w100_init_clocks(par);
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 */
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)
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);
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;
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)
239 case FB_BLANK_UNBLANK: /* Unblanking */
240 if (par->blanked != 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;
259 w100_setup_memory(par);
260 w100_init_clocks(par);
261 w100fb_clear_screen(par);
264 w100_update_disable();
266 w100_set_dispregs(par);
267 w100_update_enable();
271 if (!par->blanked && tg && tg->change)
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;
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;
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;
301 if (mode && saveval) {
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))
322 if (par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (par->mach->mem->size+1)))
325 if (!par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)))
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)
334 var->bits_per_pixel = BITS_PER_PIXEL;
336 var->red.offset = 11;
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;
347 var->vmode = FB_VMODE_NONINTERLACED;
349 var->pixclock = 0x04; /* 171521; */
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;
378 par->extmem_active = 0;
379 info->fix.smem_len = MEM_INT_SIZE+1;
382 w100fb_activate_var(par);
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,
403 static void w100fb_save_vidmem(struct w100fb_par *par)
407 if (par->extmem_active) {
408 memsize=par->mach->mem->size;
409 par->saved_extmem = vmalloc(memsize);
410 if (par->saved_extmem)
411 memcpy_fromio(par->saved_extmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
413 memsize=MEM_INT_SIZE;
414 par->saved_intmem = vmalloc(memsize);
415 if (par->saved_intmem && par->extmem_active)
416 memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), memsize);
417 else if (par->saved_intmem)
418 memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
421 static void w100fb_restore_vidmem(struct w100fb_par *par)
425 if (par->extmem_active && par->saved_extmem) {
426 memsize=par->mach->mem->size;
427 memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_extmem, memsize);
428 vfree(par->saved_extmem);
430 if (par->saved_intmem) {
431 memsize=MEM_INT_SIZE;
432 if (par->extmem_active)
433 memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), par->saved_intmem, memsize);
435 memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_intmem, memsize);
436 vfree(par->saved_intmem);
440 static int w100fb_suspend(struct device *dev, pm_message_t state)
442 struct fb_info *info = dev_get_drvdata(dev);
443 struct w100fb_par *par=info->par;
444 struct w100_tg_info *tg = par->mach->tg;
446 w100fb_save_vidmem(par);
447 if(tg && tg->suspend)
449 w100_suspend(W100_SUSPEND_ALL);
455 static int w100fb_resume(struct device *dev)
457 struct fb_info *info = dev_get_drvdata(dev);
458 struct w100fb_par *par=info->par;
459 struct w100_tg_info *tg = par->mach->tg;
462 w100fb_activate_var(par);
463 w100fb_restore_vidmem(par);
471 #define w100fb_suspend NULL
472 #define w100fb_resume NULL
476 int __init w100fb_probe(struct device *dev)
479 struct w100fb_mach_info *inf;
480 struct fb_info *info = NULL;
481 struct w100fb_par *par;
482 struct platform_device *pdev = to_platform_device(dev);
483 struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
484 unsigned int chip_id;
489 /* Remap the chip base address */
490 remapped_base = ioremap_nocache(mem->start+W100_CFG_BASE, W100_CFG_LEN);
491 if (remapped_base == NULL)
494 /* Map the register space */
495 remapped_regs = ioremap_nocache(mem->start+W100_REG_BASE, W100_REG_LEN);
496 if (remapped_regs == NULL)
499 /* Identify the chip */
501 chip_id = readl(remapped_regs + mmCHIP_ID);
503 case CHIP_ID_W100: printk("w100"); break;
504 case CHIP_ID_W3200: printk("w3200"); break;
505 case CHIP_ID_W3220: printk("w3220"); break;
507 printk("Unknown imageon chip ID\n");
511 printk(" at 0x%08lx.\n", mem->start+W100_CFG_BASE);
513 /* Remap the framebuffer */
514 remapped_fbuf = ioremap_nocache(mem->start+MEM_WINDOW_BASE, MEM_WINDOW_SIZE);
515 if (remapped_fbuf == NULL)
518 info=framebuffer_alloc(sizeof(struct w100fb_par), dev);
525 dev_set_drvdata(dev, info);
527 inf = dev->platform_data;
528 par->chip_id = chip_id;
530 par->fastpll_mode = 0;
533 par->pll_table=w100_get_xtal_table(inf->xtal_freq);
534 if (!par->pll_table) {
535 printk(KERN_ERR "No matching Xtal definition found\n");
540 info->pseudo_palette = kmalloc(sizeof (u32) * MAX_PALETTES, GFP_KERNEL);
541 if (!info->pseudo_palette) {
546 info->fbops = &w100fb_ops;
547 info->flags = FBINFO_DEFAULT;
549 info->screen_base = remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE);
550 info->screen_size = REMAPPED_FB_LEN;
552 strcpy(info->fix.id, "w100fb");
553 info->fix.type = FB_TYPE_PACKED_PIXELS;
554 info->fix.type_aux = 0;
555 info->fix.accel = FB_ACCEL_NONE;
556 info->fix.smem_start = mem->start+W100_FB_BASE;
557 info->fix.mmio_start = mem->start+W100_REG_BASE;
558 info->fix.mmio_len = W100_REG_LEN;
560 if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
565 par->mode = &inf->modelist[0];
566 if(inf->init_mode & INIT_MODE_ROTATED) {
567 info->var.xres = par->mode->yres;
568 info->var.yres = par->mode->xres;
571 info->var.xres = par->mode->xres;
572 info->var.yres = par->mode->yres;
575 if(inf->init_mode &= INIT_MODE_FLIPPED)
580 info->var.xres_virtual = info->var.xres;
581 info->var.yres_virtual = info->var.yres;
582 info->var.pixclock = 0x04; /* 171521; */
584 info->var.grayscale = 0;
585 info->var.xoffset = info->var.yoffset = 0;
586 info->var.accel_flags = 0;
587 info->var.activate = FB_ACTIVATE_NOW;
591 if (w100fb_check_var(&info->var, info) < 0) {
596 w100fb_set_par(info);
598 if (register_framebuffer(info) < 0) {
603 device_create_file(dev, &dev_attr_fastpllclk);
604 device_create_file(dev, &dev_attr_reg_read);
605 device_create_file(dev, &dev_attr_reg_write);
606 device_create_file(dev, &dev_attr_flip);
608 printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
611 fb_dealloc_cmap(&info->cmap);
612 kfree(info->pseudo_palette);
613 if (remapped_fbuf != NULL)
614 iounmap(remapped_fbuf);
615 if (remapped_regs != NULL)
616 iounmap(remapped_regs);
617 if (remapped_base != NULL)
618 iounmap(remapped_base);
620 framebuffer_release(info);
625 static int w100fb_remove(struct device *dev)
627 struct fb_info *info = dev_get_drvdata(dev);
628 struct w100fb_par *par=info->par;
630 device_remove_file(dev, &dev_attr_fastpllclk);
631 device_remove_file(dev, &dev_attr_reg_read);
632 device_remove_file(dev, &dev_attr_reg_write);
633 device_remove_file(dev, &dev_attr_flip);
635 unregister_framebuffer(info);
637 vfree(par->saved_intmem);
638 vfree(par->saved_extmem);
639 kfree(info->pseudo_palette);
640 fb_dealloc_cmap(&info->cmap);
642 iounmap(remapped_base);
643 iounmap(remapped_regs);
644 iounmap(remapped_fbuf);
646 framebuffer_release(info);
652 /* ------------------- chipset specific functions -------------------------- */
655 static void w100_soft_reset(void)
657 u16 val = readw((u16 *) remapped_base + cfgSTATUS);
658 writew(val | 0x08, (u16 *) remapped_base + cfgSTATUS);
660 writew(0x00, (u16 *) remapped_base + cfgSTATUS);
664 static void w100_update_disable(void)
666 union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
668 /* Prevent display updates */
669 disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
670 disp_db_buf_wr_cntl.f.update_db_buf = 0;
671 disp_db_buf_wr_cntl.f.en_db_buf = 0;
672 writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
675 static void w100_update_enable(void)
677 union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
679 /* Enable display updates */
680 disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
681 disp_db_buf_wr_cntl.f.update_db_buf = 1;
682 disp_db_buf_wr_cntl.f.en_db_buf = 1;
683 writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
686 unsigned long w100fb_gpio_read(int port)
690 if (port==W100_GPIO_PORT_A)
691 value = readl(remapped_regs + mmGPIO_DATA);
693 value = readl(remapped_regs + mmGPIO_DATA2);
698 void w100fb_gpio_write(int port, unsigned long value)
700 if (port==W100_GPIO_PORT_A)
701 value = writel(value, remapped_regs + mmGPIO_DATA);
703 value = writel(value, remapped_regs + mmGPIO_DATA2);
705 EXPORT_SYMBOL(w100fb_gpio_read);
706 EXPORT_SYMBOL(w100fb_gpio_write);
709 * Initialization of critical w100 hardware
711 static void w100_hw_init(struct w100fb_par *par)
714 union cif_cntl_u cif_cntl;
715 union intf_cntl_u intf_cntl;
716 union cfgreg_base_u cfgreg_base;
717 union wrap_top_dir_u wrap_top_dir;
718 union cif_read_dbg_u cif_read_dbg;
719 union cpu_defaults_u cpu_default;
720 union cif_write_dbg_u cif_write_dbg;
721 union wrap_start_dir_u wrap_start_dir;
722 union cif_io_u cif_io;
723 struct w100_gpio_regs *gpio = par->mach->gpio;
727 /* This is what the fpga_init code does on reset. May be wrong
728 but there is little info available */
729 writel(0x31, remapped_regs + mmSCRATCH_UMSK);
730 for (temp32 = 0; temp32 < 10000; temp32++)
731 readl(remapped_regs + mmSCRATCH_UMSK);
732 writel(0x30, remapped_regs + mmSCRATCH_UMSK);
735 cif_io.val = defCIF_IO;
736 writel((u32)(cif_io.val), remapped_regs + mmCIF_IO);
738 cif_write_dbg.val = readl(remapped_regs + mmCIF_WRITE_DBG);
739 cif_write_dbg.f.dis_packer_ful_during_rbbm_timeout = 0;
740 cif_write_dbg.f.en_dword_split_to_rbbm = 1;
741 cif_write_dbg.f.dis_timeout_during_rbbm = 1;
742 writel((u32) (cif_write_dbg.val), remapped_regs + mmCIF_WRITE_DBG);
744 cif_read_dbg.val = readl(remapped_regs + mmCIF_READ_DBG);
745 cif_read_dbg.f.dis_rd_same_byte_to_trig_fetch = 1;
746 writel((u32) (cif_read_dbg.val), remapped_regs + mmCIF_READ_DBG);
748 cif_cntl.val = readl(remapped_regs + mmCIF_CNTL);
749 cif_cntl.f.dis_system_bits = 1;
750 cif_cntl.f.dis_mr = 1;
751 cif_cntl.f.en_wait_to_compensate_dq_prop_dly = 0;
752 cif_cntl.f.intb_oe = 1;
753 cif_cntl.f.interrupt_active_high = 1;
754 writel((u32) (cif_cntl.val), remapped_regs + mmCIF_CNTL);
756 /* Setup cfgINTF_CNTL and cfgCPU defaults */
757 intf_cntl.val = defINTF_CNTL;
758 intf_cntl.f.ad_inc_a = 1;
759 intf_cntl.f.ad_inc_b = 1;
760 intf_cntl.f.rd_data_rdy_a = 0;
761 intf_cntl.f.rd_data_rdy_b = 0;
762 writeb((u8) (intf_cntl.val), remapped_base + cfgINTF_CNTL);
764 cpu_default.val = defCPU_DEFAULTS;
765 cpu_default.f.access_ind_addr_a = 1;
766 cpu_default.f.access_ind_addr_b = 1;
767 cpu_default.f.access_scratch_reg = 1;
768 cpu_default.f.transition_size = 0;
769 writeb((u8) (cpu_default.val), remapped_base + cfgCPU_DEFAULTS);
771 /* set up the apertures */
772 writeb((u8) (W100_REG_BASE >> 16), remapped_base + cfgREG_BASE);
774 cfgreg_base.val = defCFGREG_BASE;
775 cfgreg_base.f.cfgreg_base = W100_CFG_BASE;
776 writel((u32) (cfgreg_base.val), remapped_regs + mmCFGREG_BASE);
778 wrap_start_dir.val = defWRAP_START_DIR;
779 wrap_start_dir.f.start_addr = WRAP_BUF_BASE_VALUE >> 1;
780 writel((u32) (wrap_start_dir.val), remapped_regs + mmWRAP_START_DIR);
782 wrap_top_dir.val = defWRAP_TOP_DIR;
783 wrap_top_dir.f.top_addr = WRAP_BUF_TOP_VALUE >> 1;
784 writel((u32) (wrap_top_dir.val), remapped_regs + mmWRAP_TOP_DIR);
786 writel((u32) 0x2440, remapped_regs + mmRBBM_CNTL);
788 /* Set the hardware to 565 colour */
789 temp32 = readl(remapped_regs + mmDISP_DEBUG2);
790 temp32 &= 0xff7fffff;
791 temp32 |= 0x00800000;
792 writel(temp32, remapped_regs + mmDISP_DEBUG2);
794 /* Initialise the GPIO lines */
796 writel(gpio->init_data1, remapped_regs + mmGPIO_DATA);
797 writel(gpio->init_data2, remapped_regs + mmGPIO_DATA2);
798 writel(gpio->gpio_dir1, remapped_regs + mmGPIO_CNTL1);
799 writel(gpio->gpio_oe1, remapped_regs + mmGPIO_CNTL2);
800 writel(gpio->gpio_dir2, remapped_regs + mmGPIO_CNTL3);
801 writel(gpio->gpio_oe2, remapped_regs + mmGPIO_CNTL4);
807 union clk_pin_cntl_u clk_pin_cntl;
808 union pll_ref_fb_div_u pll_ref_fb_div;
809 union pll_cntl_u pll_cntl;
810 union sclk_cntl_u sclk_cntl;
811 union pclk_cntl_u pclk_cntl;
812 union pwrmgt_cntl_u pwrmgt_cntl;
813 int auto_mode; /* system clock auto changing? */
817 static struct power_state w100_pwr_state;
819 /* The PLL Fout is determined by (XtalFreq/(M+1)) * ((N_int+1) + (N_fac/8)) */
821 /* 12.5MHz Crystal PLL Table */
822 static struct w100_pll_info xtal_12500000[] = {
823 /*freq M N_int N_fac tfgoal lock_time */
824 { 50, 0, 1, 0, 0xe0, 56}, /* 50.00 MHz */
825 { 75, 0, 5, 0, 0xde, 37}, /* 75.00 MHz */
826 {100, 0, 7, 0, 0xe0, 28}, /* 100.00 MHz */
827 {125, 0, 9, 0, 0xe0, 22}, /* 125.00 MHz */
828 {150, 0, 11, 0, 0xe0, 17}, /* 150.00 MHz */
829 { 0, 0, 0, 0, 0, 0}, /* Terminator */
832 /* 14.318MHz Crystal PLL Table */
833 static struct w100_pll_info xtal_14318000[] = {
834 /*freq M N_int N_fac tfgoal lock_time */
835 { 40, 4, 13, 0, 0xe0, 80}, /* tfgoal guessed */
836 { 50, 1, 6, 0, 0xe0, 64}, /* 50.05 MHz */
837 { 57, 2, 11, 0, 0xe0, 53}, /* tfgoal guessed */
838 { 75, 0, 4, 3, 0xe0, 43}, /* 75.08 MHz */
839 {100, 0, 6, 0, 0xe0, 32}, /* 100.10 MHz */
843 /* 16MHz Crystal PLL Table */
844 static struct w100_pll_info xtal_16000000[] = {
845 /*freq M N_int N_fac tfgoal lock_time */
846 { 72, 1, 8, 0, 0xe0, 48}, /* tfgoal guessed */
847 { 95, 1, 10, 7, 0xe0, 38}, /* tfgoal guessed */
848 { 96, 1, 11, 0, 0xe0, 36}, /* tfgoal guessed */
852 static struct pll_entries {
854 struct w100_pll_info *pll_table;
855 } w100_pll_tables[] = {
856 { 12500000, &xtal_12500000[0] },
857 { 14318000, &xtal_14318000[0] },
858 { 16000000, &xtal_16000000[0] },
862 struct w100_pll_info *w100_get_xtal_table(unsigned int freq)
864 struct pll_entries *pll_entry = w100_pll_tables;
867 if (freq == pll_entry->xtal_freq)
868 return pll_entry->pll_table;
870 } while (pll_entry->xtal_freq);
875 static unsigned int w100_get_testcount(unsigned int testclk_sel)
877 union clk_test_cntl_u clk_test_cntl;
881 /* Select the test clock source and reset */
882 clk_test_cntl.f.start_check_freq = 0x0;
883 clk_test_cntl.f.testclk_sel = testclk_sel;
884 clk_test_cntl.f.tstcount_rst = 0x1; /* set reset */
885 writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
887 clk_test_cntl.f.tstcount_rst = 0x0; /* clear reset */
888 writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
891 clk_test_cntl.f.start_check_freq = 0x1;
892 writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
894 /* Give the test time to complete */
897 /* Return the result */
898 clk_test_cntl.val = readl(remapped_regs + mmCLK_TEST_CNTL);
899 clk_test_cntl.f.start_check_freq = 0x0;
900 writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
902 return clk_test_cntl.f.test_count;
906 static int w100_pll_adjust(struct w100_pll_info *pll)
911 /* Initial Settings */
912 w100_pwr_state.pll_cntl.f.pll_pwdn = 0x0; /* power down */
913 w100_pwr_state.pll_cntl.f.pll_reset = 0x0; /* not reset */
914 w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x1; /* Hi-Z */
915 w100_pwr_state.pll_cntl.f.pll_pvg = 0x0; /* VCO gain = 0 */
916 w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0; /* VCO frequency range control = off */
917 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; /* current offset inside VCO = 0 */
918 w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
920 /* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V
921 * therefore, commented out the following lines
925 /* set VCO input = 0.8 * VDD */
926 w100_pwr_state.pll_cntl.f.pll_dactal = 0xd;
927 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
929 tf80 = w100_get_testcount(TESTCLK_SRC_PLL);
930 if (tf80 >= (pll->tfgoal)) {
931 /* set VCO input = 0.2 * VDD */
932 w100_pwr_state.pll_cntl.f.pll_dactal = 0x7;
933 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
935 tf20 = w100_get_testcount(TESTCLK_SRC_PLL);
936 if (tf20 <= (pll->tfgoal))
937 return 1; /* Success */
939 if ((w100_pwr_state.pll_cntl.f.pll_vcofr == 0x0) &&
940 ((w100_pwr_state.pll_cntl.f.pll_pvg == 0x7) ||
941 (w100_pwr_state.pll_cntl.f.pll_ioffset == 0x0))) {
942 /* slow VCO config */
943 w100_pwr_state.pll_cntl.f.pll_vcofr = 0x1;
944 w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
945 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
949 if ((w100_pwr_state.pll_cntl.f.pll_ioffset) < 0x3) {
950 w100_pwr_state.pll_cntl.f.pll_ioffset += 0x1;
951 } else if ((w100_pwr_state.pll_cntl.f.pll_pvg) < 0x7) {
952 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
953 w100_pwr_state.pll_cntl.f.pll_pvg += 0x1;
955 return 0; /* Error */
962 * w100_pll_calibration
964 static int w100_pll_calibration(struct w100_pll_info *pll)
968 status = w100_pll_adjust(pll);
970 /* PLL Reset And Lock */
971 /* set VCO input = 0.5 * VDD */
972 w100_pwr_state.pll_cntl.f.pll_dactal = 0xa;
973 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
975 udelay(1); /* reset time */
977 /* enable charge pump */
978 w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0; /* normal */
979 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
981 /* set VCO input = Hi-Z, disable DAC */
982 w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;
983 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
985 udelay(400); /* lock time */
993 static int w100_pll_set_clk(struct w100_pll_info *pll)
997 if (w100_pwr_state.auto_mode == 1) /* auto mode */
999 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0; /* disable fast to normal */
1000 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0; /* disable normal to fast */
1001 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1004 /* Set system clock source to XTAL whilst adjusting the PLL! */
1005 w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
1006 writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1008 w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = pll->M;
1009 w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = pll->N_int;
1010 w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = pll->N_fac;
1011 w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = pll->lock_time;
1012 writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
1014 w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0;
1015 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1017 status = w100_pll_calibration(pll);
1019 if (w100_pwr_state.auto_mode == 1) /* auto mode */
1021 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x1; /* reenable fast to normal */
1022 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x1; /* reenable normal to fast */
1023 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1028 /* freq = target frequency of the PLL */
1029 static int w100_set_pll_freq(struct w100fb_par *par, unsigned int freq)
1031 struct w100_pll_info *pll = par->pll_table;
1034 if (freq == pll->freq) {
1035 return w100_pll_set_clk(pll);
1042 /* Set up an initial state. Some values/fields set
1043 here will be overwritten. */
1044 static void w100_pwm_setup(struct w100fb_par *par)
1046 w100_pwr_state.clk_pin_cntl.f.osc_en = 0x1;
1047 w100_pwr_state.clk_pin_cntl.f.osc_gain = 0x1f;
1048 w100_pwr_state.clk_pin_cntl.f.dont_use_xtalin = 0x0;
1049 w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x0;
1050 w100_pwr_state.clk_pin_cntl.f.xtalin_dbl_en = par->mach->xtal_dbl ? 1 : 0;
1051 w100_pwr_state.clk_pin_cntl.f.cg_debug = 0x0;
1052 writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL);
1054 w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
1055 w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = 0x0; /* Pfast = 1 */
1056 w100_pwr_state.sclk_cntl.f.sclk_clkon_hys = 0x3;
1057 w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0; /* Pslow = 1 */
1058 w100_pwr_state.sclk_cntl.f.disp_cg_ok2switch_en = 0x0;
1059 w100_pwr_state.sclk_cntl.f.sclk_force_reg = 0x0; /* Dynamic */
1060 w100_pwr_state.sclk_cntl.f.sclk_force_disp = 0x0; /* Dynamic */
1061 w100_pwr_state.sclk_cntl.f.sclk_force_mc = 0x0; /* Dynamic */
1062 w100_pwr_state.sclk_cntl.f.sclk_force_extmc = 0x0; /* Dynamic */
1063 w100_pwr_state.sclk_cntl.f.sclk_force_cp = 0x0; /* Dynamic */
1064 w100_pwr_state.sclk_cntl.f.sclk_force_e2 = 0x0; /* Dynamic */
1065 w100_pwr_state.sclk_cntl.f.sclk_force_e3 = 0x0; /* Dynamic */
1066 w100_pwr_state.sclk_cntl.f.sclk_force_idct = 0x0; /* Dynamic */
1067 w100_pwr_state.sclk_cntl.f.sclk_force_bist = 0x0; /* Dynamic */
1068 w100_pwr_state.sclk_cntl.f.busy_extend_cp = 0x0;
1069 w100_pwr_state.sclk_cntl.f.busy_extend_e2 = 0x0;
1070 w100_pwr_state.sclk_cntl.f.busy_extend_e3 = 0x0;
1071 w100_pwr_state.sclk_cntl.f.busy_extend_idct = 0x0;
1072 writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1074 w100_pwr_state.pclk_cntl.f.pclk_src_sel = CLK_SRC_XTAL;
1075 w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1; /* P = 2 */
1076 w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0; /* Dynamic */
1077 writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
1079 w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0; /* M = 1 */
1080 w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0; /* N = 1.0 */
1081 w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = 0x0;
1082 w100_pwr_state.pll_ref_fb_div.f.pll_reset_time = 0x5;
1083 w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = 0xff;
1084 writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
1086 w100_pwr_state.pll_cntl.f.pll_pwdn = 0x1;
1087 w100_pwr_state.pll_cntl.f.pll_reset = 0x1;
1088 w100_pwr_state.pll_cntl.f.pll_pm_en = 0x0;
1089 w100_pwr_state.pll_cntl.f.pll_mode = 0x0; /* uses VCO clock */
1090 w100_pwr_state.pll_cntl.f.pll_refclk_sel = 0x0;
1091 w100_pwr_state.pll_cntl.f.pll_fbclk_sel = 0x0;
1092 w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;
1093 w100_pwr_state.pll_cntl.f.pll_pcp = 0x4;
1094 w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
1095 w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0;
1096 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1097 w100_pwr_state.pll_cntl.f.pll_pecc_mode = 0x0;
1098 w100_pwr_state.pll_cntl.f.pll_pecc_scon = 0x0;
1099 w100_pwr_state.pll_cntl.f.pll_dactal = 0x0; /* Hi-Z */
1100 w100_pwr_state.pll_cntl.f.pll_cp_clip = 0x3;
1101 w100_pwr_state.pll_cntl.f.pll_conf = 0x2;
1102 w100_pwr_state.pll_cntl.f.pll_mbctrl = 0x2;
1103 w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
1104 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1106 w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x0;
1107 w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1; /* normal mode (0, 1, 3) */
1108 w100_pwr_state.pwrmgt_cntl.f.pwm_wakeup_cond = 0x0;
1109 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;
1110 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;
1111 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1; /* PM4,ENG */
1112 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1; /* PM4,ENG */
1113 w100_pwr_state.pwrmgt_cntl.f.pwm_idle_timer = 0xFF;
1114 w100_pwr_state.pwrmgt_cntl.f.pwm_busy_timer = 0xFF;
1115 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1117 w100_pwr_state.auto_mode = 0; /* manual mode */
1122 * Setup the w100 clocks for the specified mode
1124 static void w100_init_clocks(struct w100fb_par *par)
1126 struct w100_mode *mode = par->mode;
1128 if (mode->pixclk_src == CLK_SRC_PLL || mode->sysclk_src == CLK_SRC_PLL)
1129 w100_set_pll_freq(par, (par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq);
1131 w100_pwr_state.sclk_cntl.f.sclk_src_sel = mode->sysclk_src;
1132 w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = mode->sysclk_divider;
1133 w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = mode->sysclk_divider;
1134 writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1137 static void w100_init_lcd(struct w100fb_par *par)
1140 struct w100_mode *mode = par->mode;
1141 struct w100_gen_regs *regs = par->mach->regs;
1142 union active_h_disp_u active_h_disp;
1143 union active_v_disp_u active_v_disp;
1144 union graphic_h_disp_u graphic_h_disp;
1145 union graphic_v_disp_u graphic_v_disp;
1146 union crtc_total_u crtc_total;
1148 /* w3200 doesnt like undefined bits being set so zero register values first */
1150 active_h_disp.val = 0;
1151 active_h_disp.f.active_h_start=mode->left_margin;
1152 active_h_disp.f.active_h_end=mode->left_margin + mode->xres;
1153 writel(active_h_disp.val, remapped_regs + mmACTIVE_H_DISP);
1155 active_v_disp.val = 0;
1156 active_v_disp.f.active_v_start=mode->upper_margin;
1157 active_v_disp.f.active_v_end=mode->upper_margin + mode->yres;
1158 writel(active_v_disp.val, remapped_regs + mmACTIVE_V_DISP);
1160 graphic_h_disp.val = 0;
1161 graphic_h_disp.f.graphic_h_start=mode->left_margin;
1162 graphic_h_disp.f.graphic_h_end=mode->left_margin + mode->xres;
1163 writel(graphic_h_disp.val, remapped_regs + mmGRAPHIC_H_DISP);
1165 graphic_v_disp.val = 0;
1166 graphic_v_disp.f.graphic_v_start=mode->upper_margin;
1167 graphic_v_disp.f.graphic_v_end=mode->upper_margin + mode->yres;
1168 writel(graphic_v_disp.val, remapped_regs + mmGRAPHIC_V_DISP);
1171 crtc_total.f.crtc_h_total=mode->left_margin + mode->xres + mode->right_margin;
1172 crtc_total.f.crtc_v_total=mode->upper_margin + mode->yres + mode->lower_margin;
1173 writel(crtc_total.val, remapped_regs + mmCRTC_TOTAL);
1175 writel(mode->crtc_ss, remapped_regs + mmCRTC_SS);
1176 writel(mode->crtc_ls, remapped_regs + mmCRTC_LS);
1177 writel(mode->crtc_gs, remapped_regs + mmCRTC_GS);
1178 writel(mode->crtc_vpos_gs, remapped_regs + mmCRTC_VPOS_GS);
1179 writel(mode->crtc_rev, remapped_regs + mmCRTC_REV);
1180 writel(mode->crtc_dclk, remapped_regs + mmCRTC_DCLK);
1181 writel(mode->crtc_gclk, remapped_regs + mmCRTC_GCLK);
1182 writel(mode->crtc_goe, remapped_regs + mmCRTC_GOE);
1183 writel(mode->crtc_ps1_active, remapped_regs + mmCRTC_PS1_ACTIVE);
1185 writel(regs->lcd_format, remapped_regs + mmLCD_FORMAT);
1186 writel(regs->lcdd_cntl1, remapped_regs + mmLCDD_CNTL1);
1187 writel(regs->lcdd_cntl2, remapped_regs + mmLCDD_CNTL2);
1188 writel(regs->genlcd_cntl1, remapped_regs + mmGENLCD_CNTL1);
1189 writel(regs->genlcd_cntl2, remapped_regs + mmGENLCD_CNTL2);
1190 writel(regs->genlcd_cntl3, remapped_regs + mmGENLCD_CNTL3);
1192 writel(0x00000000, remapped_regs + mmCRTC_FRAME);
1193 writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS);
1194 writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT);
1195 writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR);
1197 /* Hack for overlay in ext memory */
1198 temp32 = readl(remapped_regs + mmDISP_DEBUG2);
1199 temp32 |= 0xc0000000;
1200 writel(temp32, remapped_regs + mmDISP_DEBUG2);
1204 static void w100_setup_memory(struct w100fb_par *par)
1206 union mc_ext_mem_location_u extmem_location;
1207 union mc_fb_location_u intmem_location;
1208 struct w100_mem_info *mem = par->mach->mem;
1209 struct w100_bm_mem_info *bm_mem = par->mach->bm_mem;
1211 if (!par->extmem_active) {
1212 w100_suspend(W100_SUSPEND_EXTMEM);
1214 /* Map Internal Memory at FB Base */
1215 intmem_location.f.mc_fb_start = W100_FB_BASE >> 8;
1216 intmem_location.f.mc_fb_top = (W100_FB_BASE+MEM_INT_SIZE) >> 8;
1217 writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
1219 /* Unmap External Memory - value is *probably* irrelevant but may have meaning
1220 to acceleration libraries */
1221 extmem_location.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8;
1222 extmem_location.f.mc_ext_mem_top = (MEM_EXT_BASE_VALUE-1) >> 8;
1223 writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
1225 /* Map Internal Memory to its default location */
1226 intmem_location.f.mc_fb_start = MEM_INT_BASE_VALUE >> 8;
1227 intmem_location.f.mc_fb_top = (MEM_INT_BASE_VALUE+MEM_INT_SIZE) >> 8;
1228 writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
1230 /* Map External Memory at FB Base */
1231 extmem_location.f.mc_ext_mem_start = W100_FB_BASE >> 8;
1232 extmem_location.f.mc_ext_mem_top = (W100_FB_BASE+par->mach->mem->size) >> 8;
1233 writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
1235 writel(0x00007800, remapped_regs + mmMC_BIST_CTRL);
1236 writel(mem->ext_cntl, remapped_regs + mmMEM_EXT_CNTL);
1237 writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
1239 writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
1241 writel(mem->sdram_mode_reg, remapped_regs + mmMEM_SDRAM_MODE_REG);
1243 writel(mem->ext_timing_cntl, remapped_regs + mmMEM_EXT_TIMING_CNTL);
1244 writel(mem->io_cntl, remapped_regs + mmMEM_IO_CNTL);
1246 writel(bm_mem->ext_mem_bw, remapped_regs + mmBM_EXT_MEM_BANDWIDTH);
1247 writel(bm_mem->offset, remapped_regs + mmBM_OFFSET);
1248 writel(bm_mem->ext_timing_ctl, remapped_regs + mmBM_MEM_EXT_TIMING_CNTL);
1249 writel(bm_mem->ext_cntl, remapped_regs + mmBM_MEM_EXT_CNTL);
1250 writel(bm_mem->mode_reg, remapped_regs + mmBM_MEM_MODE_REG);
1251 writel(bm_mem->io_cntl, remapped_regs + mmBM_MEM_IO_CNTL);
1252 writel(bm_mem->config, remapped_regs + mmBM_CONFIG);
1257 static void w100_set_dispregs(struct w100fb_par *par)
1259 unsigned long rot=0, divider, offset=0;
1260 union graphic_ctrl_u graphic_ctrl;
1262 /* See if the mode has been rotated */
1263 if (par->xres == par->mode->xres) {
1265 rot=3; /* 180 degree */
1266 offset=(par->xres * par->yres) - 1;
1267 } /* else 0 degree */
1268 divider = par->mode->pixclk_divider;
1271 rot=2; /* 270 degree */
1272 offset=par->xres - 1;
1274 rot=1; /* 90 degree */
1275 offset=par->xres * (par->yres - 1);
1277 divider = par->mode->pixclk_divider_rotated;
1280 graphic_ctrl.val = 0; /* w32xx doesn't like undefined bits */
1281 switch (par->chip_id) {
1283 graphic_ctrl.f_w100.color_depth=6;
1284 graphic_ctrl.f_w100.en_crtc=1;
1285 graphic_ctrl.f_w100.en_graphic_req=1;
1286 graphic_ctrl.f_w100.en_graphic_crtc=1;
1287 graphic_ctrl.f_w100.lcd_pclk_on=1;
1288 graphic_ctrl.f_w100.lcd_sclk_on=1;
1289 graphic_ctrl.f_w100.low_power_on=0;
1290 graphic_ctrl.f_w100.req_freq=0;
1291 graphic_ctrl.f_w100.portrait_mode=rot;
1293 /* Zaurus needs this */
1298 graphic_ctrl.f_w100.total_req_graphic=0xa0;
1305 graphic_ctrl.f_w100.low_power_on=1;
1306 graphic_ctrl.f_w100.req_freq=5;
1310 graphic_ctrl.f_w100.req_freq=4;
1315 graphic_ctrl.f_w100.total_req_graphic=0xf0;
1321 graphic_ctrl.f_w32xx.color_depth=6;
1322 graphic_ctrl.f_w32xx.en_crtc=1;
1323 graphic_ctrl.f_w32xx.en_graphic_req=1;
1324 graphic_ctrl.f_w32xx.en_graphic_crtc=1;
1325 graphic_ctrl.f_w32xx.lcd_pclk_on=1;
1326 graphic_ctrl.f_w32xx.lcd_sclk_on=1;
1327 graphic_ctrl.f_w32xx.low_power_on=0;
1328 graphic_ctrl.f_w32xx.req_freq=0;
1329 graphic_ctrl.f_w32xx.total_req_graphic=par->mode->xres >> 1; /* panel xres, not mode */
1330 graphic_ctrl.f_w32xx.portrait_mode=rot;
1334 /* Set the pixel clock source and divider */
1335 w100_pwr_state.pclk_cntl.f.pclk_src_sel = par->mode->pixclk_src;
1336 w100_pwr_state.pclk_cntl.f.pclk_post_div = divider;
1337 writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
1339 writel(graphic_ctrl.val, remapped_regs + mmGRAPHIC_CTRL);
1340 writel(W100_FB_BASE + ((offset * BITS_PER_PIXEL/8)&~0x03UL), remapped_regs + mmGRAPHIC_OFFSET);
1341 writel((par->xres*BITS_PER_PIXEL/8), remapped_regs + mmGRAPHIC_PITCH);
1346 * Work out how long the sync pulse lasts
1347 * Value is 1/(time in seconds)
1349 static void calc_hsync(struct w100fb_par *par)
1351 unsigned long hsync;
1352 struct w100_mode *mode = par->mode;
1353 union crtc_ss_u crtc_ss;
1355 if (mode->pixclk_src == CLK_SRC_XTAL)
1356 hsync=par->mach->xtal_freq;
1358 hsync=((par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq)*100000;
1360 hsync /= (w100_pwr_state.pclk_cntl.f.pclk_post_div + 1);
1362 crtc_ss.val = readl(remapped_regs + mmCRTC_SS);
1364 par->hsync_len = hsync / (crtc_ss.f.ss_end-crtc_ss.f.ss_start);
1369 static void w100_suspend(u32 mode)
1373 writel(0x7FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION);
1374 writel(0x00FF0000, remapped_regs + mmMC_PERF_MON_CNTL);
1376 val = readl(remapped_regs + mmMEM_EXT_TIMING_CNTL);
1377 val &= ~(0x00100000); /* bit20=0 */
1378 val |= 0xFF000000; /* bit31:24=0xff */
1379 writel(val, remapped_regs + mmMEM_EXT_TIMING_CNTL);
1381 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1382 val &= ~(0x00040000); /* bit18=0 */
1383 val |= 0x00080000; /* bit19=1 */
1384 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1386 udelay(1); /* wait 1us */
1388 if (mode == W100_SUSPEND_EXTMEM) {
1389 /* CKE: Tri-State */
1390 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1391 val |= 0x40000000; /* bit30=1 */
1392 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1395 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1396 val &= ~(0x00000001); /* bit0=0 */
1397 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1399 writel(0x00000000, remapped_regs + mmSCLK_CNTL);
1400 writel(0x000000BF, remapped_regs + mmCLK_PIN_CNTL);
1401 writel(0x00000015, remapped_regs + mmPWRMGT_CNTL);
1405 val = readl(remapped_regs + mmPLL_CNTL);
1406 val |= 0x00000004; /* bit2=1 */
1407 writel(val, remapped_regs + mmPLL_CNTL);
1408 writel(0x0000001d, remapped_regs + mmPWRMGT_CNTL);
1412 static void w100_vsync(void)
1415 int timeout = 30000; /* VSync timeout = 30[ms] > 16.8[ms] */
1417 tmp = readl(remapped_regs + mmACTIVE_V_DISP);
1420 writel((tmp >> 16) & 0x3ff, remapped_regs + mmDISP_INT_CNTL);
1422 /* disable vline irq */
1423 tmp = readl(remapped_regs + mmGEN_INT_CNTL);
1426 writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1428 /* clear vline irq status */
1429 writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1431 /* enable vline irq */
1432 writel((tmp | 0x00000002), remapped_regs + mmGEN_INT_CNTL);
1434 /* clear vline irq status */
1435 writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1437 while(timeout > 0) {
1438 if (readl(remapped_regs + mmGEN_INT_STATUS) & 0x00000002)
1444 /* disable vline irq */
1445 writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1447 /* clear vline irq status */
1448 writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1451 static struct device_driver w100fb_driver = {
1453 .bus = &platform_bus_type,
1454 .probe = w100fb_probe,
1455 .remove = w100fb_remove,
1456 .suspend = w100fb_suspend,
1457 .resume = w100fb_resume,
1460 int __devinit w100fb_init(void)
1462 return driver_register(&w100fb_driver);
1465 void __exit w100fb_cleanup(void)
1467 driver_unregister(&w100fb_driver);
1470 module_init(w100fb_init);
1471 module_exit(w100fb_cleanup);
1473 MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
1474 MODULE_LICENSE("GPL");