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-2006 Richard Purdie
8 * Copyright (c) 2005 Ian Molton
9 * Copyright (c) 2006 Alberto Mardegan
11 * Rewritten for 2.6 by Richard Purdie <rpurdie@rpsys.net>
13 * Generic platform support by Ian Molton <spyro@f2s.com>
14 * and Richard Purdie <rpurdie@rpsys.net>
16 * w32xx support by Ian Molton
18 * Hardware acceleration support by Alberto Mardegan
19 * <mardy@users.sourceforge.net>
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License version 2 as
23 * published by the Free Software Foundation.
27 #include <linux/delay.h>
29 #include <linux/init.h>
30 #include <linux/kernel.h>
32 #include <linux/platform_device.h>
33 #include <linux/slab.h>
34 #include <linux/string.h>
35 #include <linux/vmalloc.h>
36 #include <linux/module.h>
38 #include <linux/uaccess.h>
39 #include <video/w100fb.h>
45 static void w100_suspend(u32 mode);
46 static void w100_vsync(void);
47 static void w100_hw_init(struct w100fb_par*);
48 static void w100_pwm_setup(struct w100fb_par*);
49 static void w100_init_clocks(struct w100fb_par*);
50 static void w100_setup_memory(struct w100fb_par*);
51 static void w100_init_lcd(struct w100fb_par*);
52 static void w100_set_dispregs(struct w100fb_par*);
53 static void w100_update_enable(void);
54 static void w100_update_disable(void);
55 static void calc_hsync(struct w100fb_par *par);
56 static void w100_init_graphic_engine(struct w100fb_par *par);
57 struct w100_pll_info *w100_get_xtal_table(unsigned int freq);
59 /* Pseudo palette size */
60 #define MAX_PALETTES 16
62 #define W100_SUSPEND_EXTMEM 0
63 #define W100_SUSPEND_ALL 1
65 #define BITS_PER_PIXEL 16
67 /* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */
68 static void *remapped_base;
69 static void *remapped_regs;
70 static void *remapped_fbuf;
72 #define REMAPPED_FB_LEN 0x15ffff
74 /* This is the offset in the w100's address space we map the current
75 framebuffer memory to. We use the position of external memory as
76 we can remap internal memory to there if external isn't present. */
77 #define W100_FB_BASE MEM_EXT_BASE_VALUE
83 static ssize_t flip_show(struct device *dev, struct device_attribute *attr, char *buf)
85 struct fb_info *info = dev_get_drvdata(dev);
86 struct w100fb_par *par=info->par;
88 return sprintf(buf, "%d\n",par->flip);
91 static ssize_t flip_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
94 struct fb_info *info = dev_get_drvdata(dev);
95 struct w100fb_par *par=info->par;
97 flip = simple_strtoul(buf, NULL, 10);
104 w100_update_disable();
105 w100_set_dispregs(par);
106 w100_update_enable();
113 static DEVICE_ATTR(flip, 0644, flip_show, flip_store);
115 static ssize_t w100fb_reg_read(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
117 unsigned long regs, param;
118 regs = simple_strtoul(buf, NULL, 16);
119 param = readl(remapped_regs + regs);
120 printk("Read Register 0x%08lX: 0x%08lX\n", regs, param);
124 static DEVICE_ATTR(reg_read, 0200, NULL, w100fb_reg_read);
126 static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
128 unsigned long regs, param;
129 sscanf(buf, "%lx %lx", ®s, ¶m);
131 if (regs <= 0x2000) {
132 printk("Write Register 0x%08lX: 0x%08lX\n", regs, param);
133 writel(param, remapped_regs + regs);
139 static DEVICE_ATTR(reg_write, 0200, NULL, w100fb_reg_write);
142 static ssize_t fastpllclk_show(struct device *dev, struct device_attribute *attr, char *buf)
144 struct fb_info *info = dev_get_drvdata(dev);
145 struct w100fb_par *par=info->par;
147 return sprintf(buf, "%d\n",par->fastpll_mode);
150 static ssize_t fastpllclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
152 struct fb_info *info = dev_get_drvdata(dev);
153 struct w100fb_par *par=info->par;
155 if (simple_strtoul(buf, NULL, 10) > 0) {
157 printk("w100fb: Using fast system clock (if possible)\n");
160 printk("w100fb: Using normal system clock\n");
163 w100_init_clocks(par);
169 static DEVICE_ATTR(fastpllclk, 0644, fastpllclk_show, fastpllclk_store);
172 * Some touchscreens need hsync information from the video driver to
173 * function correctly. We export it here.
175 unsigned long w100fb_get_hsynclen(struct device *dev)
177 struct fb_info *info = dev_get_drvdata(dev);
178 struct w100fb_par *par=info->par;
180 /* If display is blanked/suspended, hsync isn't active */
184 return par->hsync_len;
186 EXPORT_SYMBOL(w100fb_get_hsynclen);
188 static void w100fb_clear_screen(struct w100fb_par *par)
190 memset_io(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), 0, (par->xres * par->yres * BITS_PER_PIXEL/8));
195 * Set a palette value from rgb components
197 static int w100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
198 u_int trans, struct fb_info *info)
204 * If greyscale is true, then we convert the RGB value
205 * to greyscale no matter what visual we are using.
207 if (info->var.grayscale)
208 red = green = blue = (19595 * red + 38470 * green + 7471 * blue) >> 16;
211 * 16-bit True Colour. We encode the RGB value
212 * according to the RGB bitfield information.
214 if (regno < MAX_PALETTES) {
215 u32 *pal = info->pseudo_palette;
217 val = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
226 * Blank the display based on value in blank_mode
228 static int w100fb_blank(int blank_mode, struct fb_info *info)
230 struct w100fb_par *par = info->par;
231 struct w100_tg_info *tg = par->mach->tg;
235 case FB_BLANK_NORMAL: /* Normal blanking */
236 case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
237 case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
238 case FB_BLANK_POWERDOWN: /* Poweroff */
239 if (par->blanked == 0) {
240 if(tg && tg->suspend)
246 case FB_BLANK_UNBLANK: /* Unblanking */
247 if (par->blanked != 0) {
258 static void w100_fifo_wait(int entries)
260 union rbbm_status_u status;
263 for (i = 0; i < 2000000; i++) {
264 status.val = readl(remapped_regs + mmRBBM_STATUS);
265 if (status.f.cmdfifo_avail >= entries)
269 printk(KERN_ERR "w100fb: FIFO Timeout!\n");
273 static int w100fb_sync(struct fb_info *info)
275 union rbbm_status_u status;
278 for (i = 0; i < 2000000; i++) {
279 status.val = readl(remapped_regs + mmRBBM_STATUS);
280 if (!status.f.gui_active)
284 printk(KERN_ERR "w100fb: Graphic engine timeout!\n");
289 static void w100_init_graphic_engine(struct w100fb_par *par)
291 union dp_gui_master_cntl_u gmc;
292 union dp_mix_u dp_mix;
293 union dp_datatype_u dp_datatype;
294 union dp_cntl_u dp_cntl;
297 writel(W100_FB_BASE, remapped_regs + mmDST_OFFSET);
298 writel(par->xres, remapped_regs + mmDST_PITCH);
299 writel(W100_FB_BASE, remapped_regs + mmSRC_OFFSET);
300 writel(par->xres, remapped_regs + mmSRC_PITCH);
303 writel(0, remapped_regs + mmSC_TOP_LEFT);
304 writel((par->yres << 16) | par->xres, remapped_regs + mmSC_BOTTOM_RIGHT);
305 writel(0x1fff1fff, remapped_regs + mmSRC_SC_BOTTOM_RIGHT);
309 dp_cntl.f.dst_x_dir = 1;
310 dp_cntl.f.dst_y_dir = 1;
311 dp_cntl.f.src_x_dir = 1;
312 dp_cntl.f.src_y_dir = 1;
313 dp_cntl.f.dst_major_x = 1;
314 dp_cntl.f.src_major_x = 1;
315 writel(dp_cntl.val, remapped_regs + mmDP_CNTL);
318 gmc.f.gmc_src_pitch_offset_cntl = 1;
319 gmc.f.gmc_dst_pitch_offset_cntl = 1;
320 gmc.f.gmc_src_clipping = 1;
321 gmc.f.gmc_dst_clipping = 1;
322 gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
323 gmc.f.gmc_dst_datatype = 3; /* from DstType_16Bpp_444 */
324 gmc.f.gmc_src_datatype = SRC_DATATYPE_EQU_DST;
325 gmc.f.gmc_byte_pix_order = 1;
326 gmc.f.gmc_default_sel = 0;
327 gmc.f.gmc_rop3 = ROP3_SRCCOPY;
328 gmc.f.gmc_dp_src_source = DP_SRC_MEM_RECTANGULAR;
329 gmc.f.gmc_clr_cmp_fcn_dis = 1;
330 gmc.f.gmc_wr_msk_dis = 1;
331 gmc.f.gmc_dp_op = DP_OP_ROP;
332 writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
334 dp_datatype.val = dp_mix.val = 0;
335 dp_datatype.f.dp_dst_datatype = gmc.f.gmc_dst_datatype;
336 dp_datatype.f.dp_brush_datatype = gmc.f.gmc_brush_datatype;
337 dp_datatype.f.dp_src2_type = 0;
338 dp_datatype.f.dp_src2_datatype = gmc.f.gmc_src_datatype;
339 dp_datatype.f.dp_src_datatype = gmc.f.gmc_src_datatype;
340 dp_datatype.f.dp_byte_pix_order = gmc.f.gmc_byte_pix_order;
341 writel(dp_datatype.val, remapped_regs + mmDP_DATATYPE);
343 dp_mix.f.dp_src_source = gmc.f.gmc_dp_src_source;
344 dp_mix.f.dp_src2_source = 1;
345 dp_mix.f.dp_rop3 = gmc.f.gmc_rop3;
346 dp_mix.f.dp_op = gmc.f.gmc_dp_op;
347 writel(dp_mix.val, remapped_regs + mmDP_MIX);
351 static void w100fb_fillrect(struct fb_info *info,
352 const struct fb_fillrect *rect)
354 union dp_gui_master_cntl_u gmc;
356 if (info->state != FBINFO_STATE_RUNNING)
358 if (info->flags & FBINFO_HWACCEL_DISABLED) {
359 cfb_fillrect(info, rect);
363 gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
364 gmc.f.gmc_rop3 = ROP3_PATCOPY;
365 gmc.f.gmc_brush_datatype = GMC_BRUSH_SOLID_COLOR;
367 writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
368 writel(rect->color, remapped_regs + mmDP_BRUSH_FRGD_CLR);
371 writel((rect->dy << 16) | (rect->dx & 0xffff), remapped_regs + mmDST_Y_X);
372 writel((rect->width << 16) | (rect->height & 0xffff),
373 remapped_regs + mmDST_WIDTH_HEIGHT);
377 static void w100fb_copyarea(struct fb_info *info,
378 const struct fb_copyarea *area)
380 u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
381 u32 h = area->height, w = area->width;
382 union dp_gui_master_cntl_u gmc;
384 if (info->state != FBINFO_STATE_RUNNING)
386 if (info->flags & FBINFO_HWACCEL_DISABLED) {
387 cfb_copyarea(info, area);
391 gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
392 gmc.f.gmc_rop3 = ROP3_SRCCOPY;
393 gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
395 writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
398 writel((sy << 16) | (sx & 0xffff), remapped_regs + mmSRC_Y_X);
399 writel((dy << 16) | (dx & 0xffff), remapped_regs + mmDST_Y_X);
400 writel((w << 16) | (h & 0xffff), remapped_regs + mmDST_WIDTH_HEIGHT);
405 * Change the resolution by calling the appropriate hardware functions
407 static void w100fb_activate_var(struct w100fb_par *par)
409 struct w100_tg_info *tg = par->mach->tg;
412 w100_setup_memory(par);
413 w100_init_clocks(par);
414 w100fb_clear_screen(par);
417 w100_update_disable();
419 w100_set_dispregs(par);
420 w100_update_enable();
421 w100_init_graphic_engine(par);
425 if (!par->blanked && tg && tg->change)
430 /* Select the smallest mode that allows the desired resolution to be
431 * displayed. If desired, the x and y parameters can be rounded up to
432 * match the selected mode.
434 static struct w100_mode *w100fb_get_mode(struct w100fb_par *par, unsigned int *x, unsigned int *y, int saveval)
436 struct w100_mode *mode = NULL;
437 struct w100_mode *modelist = par->mach->modelist;
438 unsigned int best_x = 0xffffffff, best_y = 0xffffffff;
441 for (i = 0 ; i < par->mach->num_modes ; i++) {
442 if (modelist[i].xres >= *x && modelist[i].yres >= *y &&
443 modelist[i].xres < best_x && modelist[i].yres < best_y) {
444 best_x = modelist[i].xres;
445 best_y = modelist[i].yres;
447 } else if(modelist[i].xres >= *y && modelist[i].yres >= *x &&
448 modelist[i].xres < best_y && modelist[i].yres < best_x) {
449 best_x = modelist[i].yres;
450 best_y = modelist[i].xres;
455 if (mode && saveval) {
465 * w100fb_check_var():
466 * Get the video params out of 'var'. If a value doesn't fit, round it up,
467 * if it's too big, return -EINVAL.
469 static int w100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
471 struct w100fb_par *par=info->par;
473 if(!w100fb_get_mode(par, &var->xres, &var->yres, 1))
476 if (par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (par->mach->mem->size+1)))
479 if (!par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)))
482 var->xres_virtual = max(var->xres_virtual, var->xres);
483 var->yres_virtual = max(var->yres_virtual, var->yres);
485 if (var->bits_per_pixel > BITS_PER_PIXEL)
488 var->bits_per_pixel = BITS_PER_PIXEL;
490 var->red.offset = 11;
492 var->green.offset = 5;
493 var->green.length = 6;
494 var->blue.offset = 0;
495 var->blue.length = 5;
496 var->transp.offset = var->transp.length = 0;
501 var->vmode = FB_VMODE_NONINTERLACED;
503 var->pixclock = 0x04; /* 171521; */
511 * Set the user defined part of the display for the specified console
512 * by looking at the values in info.var
514 static int w100fb_set_par(struct fb_info *info)
516 struct w100fb_par *par=info->par;
518 if (par->xres != info->var.xres || par->yres != info->var.yres) {
519 par->xres = info->var.xres;
520 par->yres = info->var.yres;
521 par->mode = w100fb_get_mode(par, &par->xres, &par->yres, 0);
523 info->fix.visual = FB_VISUAL_TRUECOLOR;
524 info->fix.ypanstep = 0;
525 info->fix.ywrapstep = 0;
526 info->fix.line_length = par->xres * BITS_PER_PIXEL / 8;
528 mutex_lock(&info->mm_lock);
529 if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) {
530 par->extmem_active = 1;
531 info->fix.smem_len = par->mach->mem->size+1;
533 par->extmem_active = 0;
534 info->fix.smem_len = MEM_INT_SIZE+1;
536 mutex_unlock(&info->mm_lock);
538 w100fb_activate_var(par);
545 * Frame buffer operations
547 static struct fb_ops w100fb_ops = {
548 .owner = THIS_MODULE,
549 .fb_check_var = w100fb_check_var,
550 .fb_set_par = w100fb_set_par,
551 .fb_setcolreg = w100fb_setcolreg,
552 .fb_blank = w100fb_blank,
553 .fb_fillrect = w100fb_fillrect,
554 .fb_copyarea = w100fb_copyarea,
555 .fb_imageblit = cfb_imageblit,
556 .fb_sync = w100fb_sync,
560 static void w100fb_save_vidmem(struct w100fb_par *par)
564 if (par->extmem_active) {
565 memsize=par->mach->mem->size;
566 par->saved_extmem = vmalloc(memsize);
567 if (par->saved_extmem)
568 memcpy_fromio(par->saved_extmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
570 memsize=MEM_INT_SIZE;
571 par->saved_intmem = vmalloc(memsize);
572 if (par->saved_intmem && par->extmem_active)
573 memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), memsize);
574 else if (par->saved_intmem)
575 memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
578 static void w100fb_restore_vidmem(struct w100fb_par *par)
582 if (par->extmem_active && par->saved_extmem) {
583 memsize=par->mach->mem->size;
584 memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_extmem, memsize);
585 vfree(par->saved_extmem);
586 par->saved_extmem = NULL;
588 if (par->saved_intmem) {
589 memsize=MEM_INT_SIZE;
590 if (par->extmem_active)
591 memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), par->saved_intmem, memsize);
593 memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_intmem, memsize);
594 vfree(par->saved_intmem);
595 par->saved_intmem = NULL;
599 static int w100fb_suspend(struct platform_device *dev, pm_message_t state)
601 struct fb_info *info = platform_get_drvdata(dev);
602 struct w100fb_par *par=info->par;
603 struct w100_tg_info *tg = par->mach->tg;
605 w100fb_save_vidmem(par);
606 if(tg && tg->suspend)
608 w100_suspend(W100_SUSPEND_ALL);
614 static int w100fb_resume(struct platform_device *dev)
616 struct fb_info *info = platform_get_drvdata(dev);
617 struct w100fb_par *par=info->par;
618 struct w100_tg_info *tg = par->mach->tg;
621 w100fb_activate_var(par);
622 w100fb_restore_vidmem(par);
630 #define w100fb_suspend NULL
631 #define w100fb_resume NULL
635 int w100fb_probe(struct platform_device *pdev)
638 struct w100fb_mach_info *inf;
639 struct fb_info *info = NULL;
640 struct w100fb_par *par;
641 struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
642 unsigned int chip_id;
647 /* Remap the chip base address */
648 remapped_base = ioremap_nocache(mem->start+W100_CFG_BASE, W100_CFG_LEN);
649 if (remapped_base == NULL)
652 /* Map the register space */
653 remapped_regs = ioremap_nocache(mem->start+W100_REG_BASE, W100_REG_LEN);
654 if (remapped_regs == NULL)
657 /* Identify the chip */
659 chip_id = readl(remapped_regs + mmCHIP_ID);
661 case CHIP_ID_W100: printk("w100"); break;
662 case CHIP_ID_W3200: printk("w3200"); break;
663 case CHIP_ID_W3220: printk("w3220"); break;
665 printk("Unknown imageon chip ID\n");
669 printk(" at 0x%08lx.\n", (unsigned long) mem->start+W100_CFG_BASE);
671 /* Remap the framebuffer */
672 remapped_fbuf = ioremap_nocache(mem->start+MEM_WINDOW_BASE, MEM_WINDOW_SIZE);
673 if (remapped_fbuf == NULL)
676 info=framebuffer_alloc(sizeof(struct w100fb_par), &pdev->dev);
683 platform_set_drvdata(pdev, info);
685 inf = dev_get_platdata(&pdev->dev);
686 par->chip_id = chip_id;
688 par->fastpll_mode = 0;
691 par->pll_table=w100_get_xtal_table(inf->xtal_freq);
692 if (!par->pll_table) {
693 printk(KERN_ERR "No matching Xtal definition found\n");
698 info->pseudo_palette = kmalloc(sizeof (u32) * MAX_PALETTES, GFP_KERNEL);
699 if (!info->pseudo_palette) {
704 info->fbops = &w100fb_ops;
705 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
706 FBINFO_HWACCEL_FILLRECT;
708 info->screen_base = remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE);
709 info->screen_size = REMAPPED_FB_LEN;
711 strcpy(info->fix.id, "w100fb");
712 info->fix.type = FB_TYPE_PACKED_PIXELS;
713 info->fix.type_aux = 0;
714 info->fix.accel = FB_ACCEL_NONE;
715 info->fix.smem_start = mem->start+W100_FB_BASE;
716 info->fix.mmio_start = mem->start+W100_REG_BASE;
717 info->fix.mmio_len = W100_REG_LEN;
719 if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
724 par->mode = &inf->modelist[0];
725 if(inf->init_mode & INIT_MODE_ROTATED) {
726 info->var.xres = par->mode->yres;
727 info->var.yres = par->mode->xres;
730 info->var.xres = par->mode->xres;
731 info->var.yres = par->mode->yres;
734 if(inf->init_mode &= INIT_MODE_FLIPPED)
739 info->var.xres_virtual = info->var.xres;
740 info->var.yres_virtual = info->var.yres;
741 info->var.pixclock = 0x04; /* 171521; */
743 info->var.grayscale = 0;
744 info->var.xoffset = info->var.yoffset = 0;
745 info->var.accel_flags = 0;
746 info->var.activate = FB_ACTIVATE_NOW;
750 if (w100fb_check_var(&info->var, info) < 0) {
755 if (register_framebuffer(info) < 0) {
760 err = device_create_file(&pdev->dev, &dev_attr_fastpllclk);
761 err |= device_create_file(&pdev->dev, &dev_attr_reg_read);
762 err |= device_create_file(&pdev->dev, &dev_attr_reg_write);
763 err |= device_create_file(&pdev->dev, &dev_attr_flip);
766 fb_warn(info, "failed to register attributes (%d)\n", err);
768 fb_info(info, "%s frame buffer device\n", info->fix.id);
772 fb_dealloc_cmap(&info->cmap);
773 kfree(info->pseudo_palette);
775 if (remapped_fbuf != NULL) {
776 iounmap(remapped_fbuf);
777 remapped_fbuf = NULL;
779 if (remapped_regs != NULL) {
780 iounmap(remapped_regs);
781 remapped_regs = NULL;
783 if (remapped_base != NULL) {
784 iounmap(remapped_base);
785 remapped_base = NULL;
788 framebuffer_release(info);
793 static int w100fb_remove(struct platform_device *pdev)
795 struct fb_info *info = platform_get_drvdata(pdev);
796 struct w100fb_par *par=info->par;
798 device_remove_file(&pdev->dev, &dev_attr_fastpllclk);
799 device_remove_file(&pdev->dev, &dev_attr_reg_read);
800 device_remove_file(&pdev->dev, &dev_attr_reg_write);
801 device_remove_file(&pdev->dev, &dev_attr_flip);
803 unregister_framebuffer(info);
805 vfree(par->saved_intmem);
806 vfree(par->saved_extmem);
807 kfree(info->pseudo_palette);
808 fb_dealloc_cmap(&info->cmap);
810 iounmap(remapped_base);
811 remapped_base = NULL;
812 iounmap(remapped_regs);
813 remapped_regs = NULL;
814 iounmap(remapped_fbuf);
815 remapped_fbuf = NULL;
817 framebuffer_release(info);
823 /* ------------------- chipset specific functions -------------------------- */
826 static void w100_soft_reset(void)
828 u16 val = readw((u16 *) remapped_base + cfgSTATUS);
829 writew(val | 0x08, (u16 *) remapped_base + cfgSTATUS);
831 writew(0x00, (u16 *) remapped_base + cfgSTATUS);
835 static void w100_update_disable(void)
837 union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
839 /* Prevent display updates */
840 disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
841 disp_db_buf_wr_cntl.f.update_db_buf = 0;
842 disp_db_buf_wr_cntl.f.en_db_buf = 0;
843 writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
846 static void w100_update_enable(void)
848 union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
850 /* Enable display updates */
851 disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
852 disp_db_buf_wr_cntl.f.update_db_buf = 1;
853 disp_db_buf_wr_cntl.f.en_db_buf = 1;
854 writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
857 unsigned long w100fb_gpio_read(int port)
861 if (port==W100_GPIO_PORT_A)
862 value = readl(remapped_regs + mmGPIO_DATA);
864 value = readl(remapped_regs + mmGPIO_DATA2);
869 void w100fb_gpio_write(int port, unsigned long value)
871 if (port==W100_GPIO_PORT_A)
872 writel(value, remapped_regs + mmGPIO_DATA);
874 writel(value, remapped_regs + mmGPIO_DATA2);
876 EXPORT_SYMBOL(w100fb_gpio_read);
877 EXPORT_SYMBOL(w100fb_gpio_write);
880 * Initialization of critical w100 hardware
882 static void w100_hw_init(struct w100fb_par *par)
885 union cif_cntl_u cif_cntl;
886 union intf_cntl_u intf_cntl;
887 union cfgreg_base_u cfgreg_base;
888 union wrap_top_dir_u wrap_top_dir;
889 union cif_read_dbg_u cif_read_dbg;
890 union cpu_defaults_u cpu_default;
891 union cif_write_dbg_u cif_write_dbg;
892 union wrap_start_dir_u wrap_start_dir;
893 union cif_io_u cif_io;
894 struct w100_gpio_regs *gpio = par->mach->gpio;
898 /* This is what the fpga_init code does on reset. May be wrong
899 but there is little info available */
900 writel(0x31, remapped_regs + mmSCRATCH_UMSK);
901 for (temp32 = 0; temp32 < 10000; temp32++)
902 readl(remapped_regs + mmSCRATCH_UMSK);
903 writel(0x30, remapped_regs + mmSCRATCH_UMSK);
906 cif_io.val = defCIF_IO;
907 writel((u32)(cif_io.val), remapped_regs + mmCIF_IO);
909 cif_write_dbg.val = readl(remapped_regs + mmCIF_WRITE_DBG);
910 cif_write_dbg.f.dis_packer_ful_during_rbbm_timeout = 0;
911 cif_write_dbg.f.en_dword_split_to_rbbm = 1;
912 cif_write_dbg.f.dis_timeout_during_rbbm = 1;
913 writel((u32) (cif_write_dbg.val), remapped_regs + mmCIF_WRITE_DBG);
915 cif_read_dbg.val = readl(remapped_regs + mmCIF_READ_DBG);
916 cif_read_dbg.f.dis_rd_same_byte_to_trig_fetch = 1;
917 writel((u32) (cif_read_dbg.val), remapped_regs + mmCIF_READ_DBG);
919 cif_cntl.val = readl(remapped_regs + mmCIF_CNTL);
920 cif_cntl.f.dis_system_bits = 1;
921 cif_cntl.f.dis_mr = 1;
922 cif_cntl.f.en_wait_to_compensate_dq_prop_dly = 0;
923 cif_cntl.f.intb_oe = 1;
924 cif_cntl.f.interrupt_active_high = 1;
925 writel((u32) (cif_cntl.val), remapped_regs + mmCIF_CNTL);
927 /* Setup cfgINTF_CNTL and cfgCPU defaults */
928 intf_cntl.val = defINTF_CNTL;
929 intf_cntl.f.ad_inc_a = 1;
930 intf_cntl.f.ad_inc_b = 1;
931 intf_cntl.f.rd_data_rdy_a = 0;
932 intf_cntl.f.rd_data_rdy_b = 0;
933 writeb((u8) (intf_cntl.val), remapped_base + cfgINTF_CNTL);
935 cpu_default.val = defCPU_DEFAULTS;
936 cpu_default.f.access_ind_addr_a = 1;
937 cpu_default.f.access_ind_addr_b = 1;
938 cpu_default.f.access_scratch_reg = 1;
939 cpu_default.f.transition_size = 0;
940 writeb((u8) (cpu_default.val), remapped_base + cfgCPU_DEFAULTS);
942 /* set up the apertures */
943 writeb((u8) (W100_REG_BASE >> 16), remapped_base + cfgREG_BASE);
945 cfgreg_base.val = defCFGREG_BASE;
946 cfgreg_base.f.cfgreg_base = W100_CFG_BASE;
947 writel((u32) (cfgreg_base.val), remapped_regs + mmCFGREG_BASE);
949 wrap_start_dir.val = defWRAP_START_DIR;
950 wrap_start_dir.f.start_addr = WRAP_BUF_BASE_VALUE >> 1;
951 writel((u32) (wrap_start_dir.val), remapped_regs + mmWRAP_START_DIR);
953 wrap_top_dir.val = defWRAP_TOP_DIR;
954 wrap_top_dir.f.top_addr = WRAP_BUF_TOP_VALUE >> 1;
955 writel((u32) (wrap_top_dir.val), remapped_regs + mmWRAP_TOP_DIR);
957 writel((u32) 0x2440, remapped_regs + mmRBBM_CNTL);
959 /* Set the hardware to 565 colour */
960 temp32 = readl(remapped_regs + mmDISP_DEBUG2);
961 temp32 &= 0xff7fffff;
962 temp32 |= 0x00800000;
963 writel(temp32, remapped_regs + mmDISP_DEBUG2);
965 /* Initialise the GPIO lines */
967 writel(gpio->init_data1, remapped_regs + mmGPIO_DATA);
968 writel(gpio->init_data2, remapped_regs + mmGPIO_DATA2);
969 writel(gpio->gpio_dir1, remapped_regs + mmGPIO_CNTL1);
970 writel(gpio->gpio_oe1, remapped_regs + mmGPIO_CNTL2);
971 writel(gpio->gpio_dir2, remapped_regs + mmGPIO_CNTL3);
972 writel(gpio->gpio_oe2, remapped_regs + mmGPIO_CNTL4);
978 union clk_pin_cntl_u clk_pin_cntl;
979 union pll_ref_fb_div_u pll_ref_fb_div;
980 union pll_cntl_u pll_cntl;
981 union sclk_cntl_u sclk_cntl;
982 union pclk_cntl_u pclk_cntl;
983 union pwrmgt_cntl_u pwrmgt_cntl;
984 int auto_mode; /* system clock auto changing? */
988 static struct power_state w100_pwr_state;
990 /* The PLL Fout is determined by (XtalFreq/(M+1)) * ((N_int+1) + (N_fac/8)) */
992 /* 12.5MHz Crystal PLL Table */
993 static struct w100_pll_info xtal_12500000[] = {
994 /*freq M N_int N_fac tfgoal lock_time */
995 { 50, 0, 1, 0, 0xe0, 56}, /* 50.00 MHz */
996 { 75, 0, 5, 0, 0xde, 37}, /* 75.00 MHz */
997 {100, 0, 7, 0, 0xe0, 28}, /* 100.00 MHz */
998 {125, 0, 9, 0, 0xe0, 22}, /* 125.00 MHz */
999 {150, 0, 11, 0, 0xe0, 17}, /* 150.00 MHz */
1000 { 0, 0, 0, 0, 0, 0}, /* Terminator */
1003 /* 14.318MHz Crystal PLL Table */
1004 static struct w100_pll_info xtal_14318000[] = {
1005 /*freq M N_int N_fac tfgoal lock_time */
1006 { 40, 4, 13, 0, 0xe0, 80}, /* tfgoal guessed */
1007 { 50, 1, 6, 0, 0xe0, 64}, /* 50.05 MHz */
1008 { 57, 2, 11, 0, 0xe0, 53}, /* tfgoal guessed */
1009 { 75, 0, 4, 3, 0xe0, 43}, /* 75.08 MHz */
1010 {100, 0, 6, 0, 0xe0, 32}, /* 100.10 MHz */
1011 { 0, 0, 0, 0, 0, 0},
1014 /* 16MHz Crystal PLL Table */
1015 static struct w100_pll_info xtal_16000000[] = {
1016 /*freq M N_int N_fac tfgoal lock_time */
1017 { 72, 1, 8, 0, 0xe0, 48}, /* tfgoal guessed */
1018 { 80, 1, 9, 0, 0xe0, 13}, /* tfgoal guessed */
1019 { 95, 1, 10, 7, 0xe0, 38}, /* tfgoal guessed */
1020 { 96, 1, 11, 0, 0xe0, 36}, /* tfgoal guessed */
1021 { 0, 0, 0, 0, 0, 0},
1024 static struct pll_entries {
1026 struct w100_pll_info *pll_table;
1027 } w100_pll_tables[] = {
1028 { 12500000, &xtal_12500000[0] },
1029 { 14318000, &xtal_14318000[0] },
1030 { 16000000, &xtal_16000000[0] },
1034 struct w100_pll_info *w100_get_xtal_table(unsigned int freq)
1036 struct pll_entries *pll_entry = w100_pll_tables;
1039 if (freq == pll_entry->xtal_freq)
1040 return pll_entry->pll_table;
1042 } while (pll_entry->xtal_freq);
1047 static unsigned int w100_get_testcount(unsigned int testclk_sel)
1049 union clk_test_cntl_u clk_test_cntl;
1053 /* Select the test clock source and reset */
1054 clk_test_cntl.f.start_check_freq = 0x0;
1055 clk_test_cntl.f.testclk_sel = testclk_sel;
1056 clk_test_cntl.f.tstcount_rst = 0x1; /* set reset */
1057 writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1059 clk_test_cntl.f.tstcount_rst = 0x0; /* clear reset */
1060 writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1062 /* Run clock test */
1063 clk_test_cntl.f.start_check_freq = 0x1;
1064 writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1066 /* Give the test time to complete */
1069 /* Return the result */
1070 clk_test_cntl.val = readl(remapped_regs + mmCLK_TEST_CNTL);
1071 clk_test_cntl.f.start_check_freq = 0x0;
1072 writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1074 return clk_test_cntl.f.test_count;
1078 static int w100_pll_adjust(struct w100_pll_info *pll)
1083 /* Initial Settings */
1084 w100_pwr_state.pll_cntl.f.pll_pwdn = 0x0; /* power down */
1085 w100_pwr_state.pll_cntl.f.pll_reset = 0x0; /* not reset */
1086 w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x1; /* Hi-Z */
1087 w100_pwr_state.pll_cntl.f.pll_pvg = 0x0; /* VCO gain = 0 */
1088 w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0; /* VCO frequency range control = off */
1089 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; /* current offset inside VCO = 0 */
1090 w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
1092 /* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V
1093 * therefore, commented out the following lines
1097 /* set VCO input = 0.8 * VDD */
1098 w100_pwr_state.pll_cntl.f.pll_dactal = 0xd;
1099 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1101 tf80 = w100_get_testcount(TESTCLK_SRC_PLL);
1102 if (tf80 >= (pll->tfgoal)) {
1103 /* set VCO input = 0.2 * VDD */
1104 w100_pwr_state.pll_cntl.f.pll_dactal = 0x7;
1105 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1107 tf20 = w100_get_testcount(TESTCLK_SRC_PLL);
1108 if (tf20 <= (pll->tfgoal))
1109 return 1; /* Success */
1111 if ((w100_pwr_state.pll_cntl.f.pll_vcofr == 0x0) &&
1112 ((w100_pwr_state.pll_cntl.f.pll_pvg == 0x7) ||
1113 (w100_pwr_state.pll_cntl.f.pll_ioffset == 0x0))) {
1114 /* slow VCO config */
1115 w100_pwr_state.pll_cntl.f.pll_vcofr = 0x1;
1116 w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
1117 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1121 if ((w100_pwr_state.pll_cntl.f.pll_ioffset) < 0x3) {
1122 w100_pwr_state.pll_cntl.f.pll_ioffset += 0x1;
1123 } else if ((w100_pwr_state.pll_cntl.f.pll_pvg) < 0x7) {
1124 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1125 w100_pwr_state.pll_cntl.f.pll_pvg += 0x1;
1127 return 0; /* Error */
1134 * w100_pll_calibration
1136 static int w100_pll_calibration(struct w100_pll_info *pll)
1140 status = w100_pll_adjust(pll);
1142 /* PLL Reset And Lock */
1143 /* set VCO input = 0.5 * VDD */
1144 w100_pwr_state.pll_cntl.f.pll_dactal = 0xa;
1145 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1147 udelay(1); /* reset time */
1149 /* enable charge pump */
1150 w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0; /* normal */
1151 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1153 /* set VCO input = Hi-Z, disable DAC */
1154 w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;
1155 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1157 udelay(400); /* lock time */
1165 static int w100_pll_set_clk(struct w100_pll_info *pll)
1169 if (w100_pwr_state.auto_mode == 1) /* auto mode */
1171 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0; /* disable fast to normal */
1172 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0; /* disable normal to fast */
1173 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1176 /* Set system clock source to XTAL whilst adjusting the PLL! */
1177 w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
1178 writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1180 w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = pll->M;
1181 w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = pll->N_int;
1182 w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = pll->N_fac;
1183 w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = pll->lock_time;
1184 writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
1186 w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0;
1187 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1189 status = w100_pll_calibration(pll);
1191 if (w100_pwr_state.auto_mode == 1) /* auto mode */
1193 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x1; /* reenable fast to normal */
1194 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x1; /* reenable normal to fast */
1195 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1200 /* freq = target frequency of the PLL */
1201 static int w100_set_pll_freq(struct w100fb_par *par, unsigned int freq)
1203 struct w100_pll_info *pll = par->pll_table;
1206 if (freq == pll->freq) {
1207 return w100_pll_set_clk(pll);
1214 /* Set up an initial state. Some values/fields set
1215 here will be overwritten. */
1216 static void w100_pwm_setup(struct w100fb_par *par)
1218 w100_pwr_state.clk_pin_cntl.f.osc_en = 0x1;
1219 w100_pwr_state.clk_pin_cntl.f.osc_gain = 0x1f;
1220 w100_pwr_state.clk_pin_cntl.f.dont_use_xtalin = 0x0;
1221 w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x0;
1222 w100_pwr_state.clk_pin_cntl.f.xtalin_dbl_en = par->mach->xtal_dbl ? 1 : 0;
1223 w100_pwr_state.clk_pin_cntl.f.cg_debug = 0x0;
1224 writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL);
1226 w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
1227 w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = 0x0; /* Pfast = 1 */
1228 w100_pwr_state.sclk_cntl.f.sclk_clkon_hys = 0x3;
1229 w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0; /* Pslow = 1 */
1230 w100_pwr_state.sclk_cntl.f.disp_cg_ok2switch_en = 0x0;
1231 w100_pwr_state.sclk_cntl.f.sclk_force_reg = 0x0; /* Dynamic */
1232 w100_pwr_state.sclk_cntl.f.sclk_force_disp = 0x0; /* Dynamic */
1233 w100_pwr_state.sclk_cntl.f.sclk_force_mc = 0x0; /* Dynamic */
1234 w100_pwr_state.sclk_cntl.f.sclk_force_extmc = 0x0; /* Dynamic */
1235 w100_pwr_state.sclk_cntl.f.sclk_force_cp = 0x0; /* Dynamic */
1236 w100_pwr_state.sclk_cntl.f.sclk_force_e2 = 0x0; /* Dynamic */
1237 w100_pwr_state.sclk_cntl.f.sclk_force_e3 = 0x0; /* Dynamic */
1238 w100_pwr_state.sclk_cntl.f.sclk_force_idct = 0x0; /* Dynamic */
1239 w100_pwr_state.sclk_cntl.f.sclk_force_bist = 0x0; /* Dynamic */
1240 w100_pwr_state.sclk_cntl.f.busy_extend_cp = 0x0;
1241 w100_pwr_state.sclk_cntl.f.busy_extend_e2 = 0x0;
1242 w100_pwr_state.sclk_cntl.f.busy_extend_e3 = 0x0;
1243 w100_pwr_state.sclk_cntl.f.busy_extend_idct = 0x0;
1244 writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1246 w100_pwr_state.pclk_cntl.f.pclk_src_sel = CLK_SRC_XTAL;
1247 w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1; /* P = 2 */
1248 w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0; /* Dynamic */
1249 writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
1251 w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0; /* M = 1 */
1252 w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0; /* N = 1.0 */
1253 w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = 0x0;
1254 w100_pwr_state.pll_ref_fb_div.f.pll_reset_time = 0x5;
1255 w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = 0xff;
1256 writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
1258 w100_pwr_state.pll_cntl.f.pll_pwdn = 0x1;
1259 w100_pwr_state.pll_cntl.f.pll_reset = 0x1;
1260 w100_pwr_state.pll_cntl.f.pll_pm_en = 0x0;
1261 w100_pwr_state.pll_cntl.f.pll_mode = 0x0; /* uses VCO clock */
1262 w100_pwr_state.pll_cntl.f.pll_refclk_sel = 0x0;
1263 w100_pwr_state.pll_cntl.f.pll_fbclk_sel = 0x0;
1264 w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;
1265 w100_pwr_state.pll_cntl.f.pll_pcp = 0x4;
1266 w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
1267 w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0;
1268 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1269 w100_pwr_state.pll_cntl.f.pll_pecc_mode = 0x0;
1270 w100_pwr_state.pll_cntl.f.pll_pecc_scon = 0x0;
1271 w100_pwr_state.pll_cntl.f.pll_dactal = 0x0; /* Hi-Z */
1272 w100_pwr_state.pll_cntl.f.pll_cp_clip = 0x3;
1273 w100_pwr_state.pll_cntl.f.pll_conf = 0x2;
1274 w100_pwr_state.pll_cntl.f.pll_mbctrl = 0x2;
1275 w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
1276 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1278 w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x0;
1279 w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1; /* normal mode (0, 1, 3) */
1280 w100_pwr_state.pwrmgt_cntl.f.pwm_wakeup_cond = 0x0;
1281 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;
1282 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;
1283 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1; /* PM4,ENG */
1284 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1; /* PM4,ENG */
1285 w100_pwr_state.pwrmgt_cntl.f.pwm_idle_timer = 0xFF;
1286 w100_pwr_state.pwrmgt_cntl.f.pwm_busy_timer = 0xFF;
1287 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1289 w100_pwr_state.auto_mode = 0; /* manual mode */
1294 * Setup the w100 clocks for the specified mode
1296 static void w100_init_clocks(struct w100fb_par *par)
1298 struct w100_mode *mode = par->mode;
1300 if (mode->pixclk_src == CLK_SRC_PLL || mode->sysclk_src == CLK_SRC_PLL)
1301 w100_set_pll_freq(par, (par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq);
1303 w100_pwr_state.sclk_cntl.f.sclk_src_sel = mode->sysclk_src;
1304 w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = mode->sysclk_divider;
1305 w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = mode->sysclk_divider;
1306 writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1309 static void w100_init_lcd(struct w100fb_par *par)
1312 struct w100_mode *mode = par->mode;
1313 struct w100_gen_regs *regs = par->mach->regs;
1314 union active_h_disp_u active_h_disp;
1315 union active_v_disp_u active_v_disp;
1316 union graphic_h_disp_u graphic_h_disp;
1317 union graphic_v_disp_u graphic_v_disp;
1318 union crtc_total_u crtc_total;
1320 /* w3200 doesn't like undefined bits being set so zero register values first */
1322 active_h_disp.val = 0;
1323 active_h_disp.f.active_h_start=mode->left_margin;
1324 active_h_disp.f.active_h_end=mode->left_margin + mode->xres;
1325 writel(active_h_disp.val, remapped_regs + mmACTIVE_H_DISP);
1327 active_v_disp.val = 0;
1328 active_v_disp.f.active_v_start=mode->upper_margin;
1329 active_v_disp.f.active_v_end=mode->upper_margin + mode->yres;
1330 writel(active_v_disp.val, remapped_regs + mmACTIVE_V_DISP);
1332 graphic_h_disp.val = 0;
1333 graphic_h_disp.f.graphic_h_start=mode->left_margin;
1334 graphic_h_disp.f.graphic_h_end=mode->left_margin + mode->xres;
1335 writel(graphic_h_disp.val, remapped_regs + mmGRAPHIC_H_DISP);
1337 graphic_v_disp.val = 0;
1338 graphic_v_disp.f.graphic_v_start=mode->upper_margin;
1339 graphic_v_disp.f.graphic_v_end=mode->upper_margin + mode->yres;
1340 writel(graphic_v_disp.val, remapped_regs + mmGRAPHIC_V_DISP);
1343 crtc_total.f.crtc_h_total=mode->left_margin + mode->xres + mode->right_margin;
1344 crtc_total.f.crtc_v_total=mode->upper_margin + mode->yres + mode->lower_margin;
1345 writel(crtc_total.val, remapped_regs + mmCRTC_TOTAL);
1347 writel(mode->crtc_ss, remapped_regs + mmCRTC_SS);
1348 writel(mode->crtc_ls, remapped_regs + mmCRTC_LS);
1349 writel(mode->crtc_gs, remapped_regs + mmCRTC_GS);
1350 writel(mode->crtc_vpos_gs, remapped_regs + mmCRTC_VPOS_GS);
1351 writel(mode->crtc_rev, remapped_regs + mmCRTC_REV);
1352 writel(mode->crtc_dclk, remapped_regs + mmCRTC_DCLK);
1353 writel(mode->crtc_gclk, remapped_regs + mmCRTC_GCLK);
1354 writel(mode->crtc_goe, remapped_regs + mmCRTC_GOE);
1355 writel(mode->crtc_ps1_active, remapped_regs + mmCRTC_PS1_ACTIVE);
1357 writel(regs->lcd_format, remapped_regs + mmLCD_FORMAT);
1358 writel(regs->lcdd_cntl1, remapped_regs + mmLCDD_CNTL1);
1359 writel(regs->lcdd_cntl2, remapped_regs + mmLCDD_CNTL2);
1360 writel(regs->genlcd_cntl1, remapped_regs + mmGENLCD_CNTL1);
1361 writel(regs->genlcd_cntl2, remapped_regs + mmGENLCD_CNTL2);
1362 writel(regs->genlcd_cntl3, remapped_regs + mmGENLCD_CNTL3);
1364 writel(0x00000000, remapped_regs + mmCRTC_FRAME);
1365 writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS);
1366 writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT);
1367 writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR);
1369 /* Hack for overlay in ext memory */
1370 temp32 = readl(remapped_regs + mmDISP_DEBUG2);
1371 temp32 |= 0xc0000000;
1372 writel(temp32, remapped_regs + mmDISP_DEBUG2);
1376 static void w100_setup_memory(struct w100fb_par *par)
1378 union mc_ext_mem_location_u extmem_location;
1379 union mc_fb_location_u intmem_location;
1380 struct w100_mem_info *mem = par->mach->mem;
1381 struct w100_bm_mem_info *bm_mem = par->mach->bm_mem;
1383 if (!par->extmem_active) {
1384 w100_suspend(W100_SUSPEND_EXTMEM);
1386 /* Map Internal Memory at FB Base */
1387 intmem_location.f.mc_fb_start = W100_FB_BASE >> 8;
1388 intmem_location.f.mc_fb_top = (W100_FB_BASE+MEM_INT_SIZE) >> 8;
1389 writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
1391 /* Unmap External Memory - value is *probably* irrelevant but may have meaning
1392 to acceleration libraries */
1393 extmem_location.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8;
1394 extmem_location.f.mc_ext_mem_top = (MEM_EXT_BASE_VALUE-1) >> 8;
1395 writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
1397 /* Map Internal Memory to its default location */
1398 intmem_location.f.mc_fb_start = MEM_INT_BASE_VALUE >> 8;
1399 intmem_location.f.mc_fb_top = (MEM_INT_BASE_VALUE+MEM_INT_SIZE) >> 8;
1400 writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
1402 /* Map External Memory at FB Base */
1403 extmem_location.f.mc_ext_mem_start = W100_FB_BASE >> 8;
1404 extmem_location.f.mc_ext_mem_top = (W100_FB_BASE+par->mach->mem->size) >> 8;
1405 writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
1407 writel(0x00007800, remapped_regs + mmMC_BIST_CTRL);
1408 writel(mem->ext_cntl, remapped_regs + mmMEM_EXT_CNTL);
1409 writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
1411 writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
1413 writel(mem->sdram_mode_reg, remapped_regs + mmMEM_SDRAM_MODE_REG);
1415 writel(mem->ext_timing_cntl, remapped_regs + mmMEM_EXT_TIMING_CNTL);
1416 writel(mem->io_cntl, remapped_regs + mmMEM_IO_CNTL);
1418 writel(bm_mem->ext_mem_bw, remapped_regs + mmBM_EXT_MEM_BANDWIDTH);
1419 writel(bm_mem->offset, remapped_regs + mmBM_OFFSET);
1420 writel(bm_mem->ext_timing_ctl, remapped_regs + mmBM_MEM_EXT_TIMING_CNTL);
1421 writel(bm_mem->ext_cntl, remapped_regs + mmBM_MEM_EXT_CNTL);
1422 writel(bm_mem->mode_reg, remapped_regs + mmBM_MEM_MODE_REG);
1423 writel(bm_mem->io_cntl, remapped_regs + mmBM_MEM_IO_CNTL);
1424 writel(bm_mem->config, remapped_regs + mmBM_CONFIG);
1429 static void w100_set_dispregs(struct w100fb_par *par)
1431 unsigned long rot=0, divider, offset=0;
1432 union graphic_ctrl_u graphic_ctrl;
1434 /* See if the mode has been rotated */
1435 if (par->xres == par->mode->xres) {
1437 rot=3; /* 180 degree */
1438 offset=(par->xres * par->yres) - 1;
1439 } /* else 0 degree */
1440 divider = par->mode->pixclk_divider;
1443 rot=2; /* 270 degree */
1444 offset=par->xres - 1;
1446 rot=1; /* 90 degree */
1447 offset=par->xres * (par->yres - 1);
1449 divider = par->mode->pixclk_divider_rotated;
1452 graphic_ctrl.val = 0; /* w32xx doesn't like undefined bits */
1453 switch (par->chip_id) {
1455 graphic_ctrl.f_w100.color_depth=6;
1456 graphic_ctrl.f_w100.en_crtc=1;
1457 graphic_ctrl.f_w100.en_graphic_req=1;
1458 graphic_ctrl.f_w100.en_graphic_crtc=1;
1459 graphic_ctrl.f_w100.lcd_pclk_on=1;
1460 graphic_ctrl.f_w100.lcd_sclk_on=1;
1461 graphic_ctrl.f_w100.low_power_on=0;
1462 graphic_ctrl.f_w100.req_freq=0;
1463 graphic_ctrl.f_w100.portrait_mode=rot;
1465 /* Zaurus needs this */
1470 graphic_ctrl.f_w100.total_req_graphic=0xa0;
1477 graphic_ctrl.f_w100.low_power_on=1;
1478 graphic_ctrl.f_w100.req_freq=5;
1482 graphic_ctrl.f_w100.req_freq=4;
1487 graphic_ctrl.f_w100.total_req_graphic=0xf0;
1493 graphic_ctrl.f_w32xx.color_depth=6;
1494 graphic_ctrl.f_w32xx.en_crtc=1;
1495 graphic_ctrl.f_w32xx.en_graphic_req=1;
1496 graphic_ctrl.f_w32xx.en_graphic_crtc=1;
1497 graphic_ctrl.f_w32xx.lcd_pclk_on=1;
1498 graphic_ctrl.f_w32xx.lcd_sclk_on=1;
1499 graphic_ctrl.f_w32xx.low_power_on=0;
1500 graphic_ctrl.f_w32xx.req_freq=0;
1501 graphic_ctrl.f_w32xx.total_req_graphic=par->mode->xres >> 1; /* panel xres, not mode */
1502 graphic_ctrl.f_w32xx.portrait_mode=rot;
1506 /* Set the pixel clock source and divider */
1507 w100_pwr_state.pclk_cntl.f.pclk_src_sel = par->mode->pixclk_src;
1508 w100_pwr_state.pclk_cntl.f.pclk_post_div = divider;
1509 writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
1511 writel(graphic_ctrl.val, remapped_regs + mmGRAPHIC_CTRL);
1512 writel(W100_FB_BASE + ((offset * BITS_PER_PIXEL/8)&~0x03UL), remapped_regs + mmGRAPHIC_OFFSET);
1513 writel((par->xres*BITS_PER_PIXEL/8), remapped_regs + mmGRAPHIC_PITCH);
1518 * Work out how long the sync pulse lasts
1519 * Value is 1/(time in seconds)
1521 static void calc_hsync(struct w100fb_par *par)
1523 unsigned long hsync;
1524 struct w100_mode *mode = par->mode;
1525 union crtc_ss_u crtc_ss;
1527 if (mode->pixclk_src == CLK_SRC_XTAL)
1528 hsync=par->mach->xtal_freq;
1530 hsync=((par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq)*100000;
1532 hsync /= (w100_pwr_state.pclk_cntl.f.pclk_post_div + 1);
1534 crtc_ss.val = readl(remapped_regs + mmCRTC_SS);
1536 par->hsync_len = hsync / (crtc_ss.f.ss_end-crtc_ss.f.ss_start);
1541 static void w100_suspend(u32 mode)
1545 writel(0x7FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION);
1546 writel(0x00FF0000, remapped_regs + mmMC_PERF_MON_CNTL);
1548 val = readl(remapped_regs + mmMEM_EXT_TIMING_CNTL);
1549 val &= ~(0x00100000); /* bit20=0 */
1550 val |= 0xFF000000; /* bit31:24=0xff */
1551 writel(val, remapped_regs + mmMEM_EXT_TIMING_CNTL);
1553 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1554 val &= ~(0x00040000); /* bit18=0 */
1555 val |= 0x00080000; /* bit19=1 */
1556 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1558 udelay(1); /* wait 1us */
1560 if (mode == W100_SUSPEND_EXTMEM) {
1561 /* CKE: Tri-State */
1562 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1563 val |= 0x40000000; /* bit30=1 */
1564 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1567 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1568 val &= ~(0x00000001); /* bit0=0 */
1569 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1571 writel(0x00000000, remapped_regs + mmSCLK_CNTL);
1572 writel(0x000000BF, remapped_regs + mmCLK_PIN_CNTL);
1573 writel(0x00000015, remapped_regs + mmPWRMGT_CNTL);
1577 val = readl(remapped_regs + mmPLL_CNTL);
1578 val |= 0x00000004; /* bit2=1 */
1579 writel(val, remapped_regs + mmPLL_CNTL);
1581 writel(0x00000000, remapped_regs + mmLCDD_CNTL1);
1582 writel(0x00000000, remapped_regs + mmLCDD_CNTL2);
1583 writel(0x00000000, remapped_regs + mmGENLCD_CNTL1);
1584 writel(0x00000000, remapped_regs + mmGENLCD_CNTL2);
1585 writel(0x00000000, remapped_regs + mmGENLCD_CNTL3);
1587 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1589 val &= ~(0x00000001);
1590 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1592 writel(0x0000001d, remapped_regs + mmPWRMGT_CNTL);
1596 static void w100_vsync(void)
1599 int timeout = 30000; /* VSync timeout = 30[ms] > 16.8[ms] */
1601 tmp = readl(remapped_regs + mmACTIVE_V_DISP);
1604 writel((tmp >> 16) & 0x3ff, remapped_regs + mmDISP_INT_CNTL);
1606 /* disable vline irq */
1607 tmp = readl(remapped_regs + mmGEN_INT_CNTL);
1610 writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1612 /* clear vline irq status */
1613 writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1615 /* enable vline irq */
1616 writel((tmp | 0x00000002), remapped_regs + mmGEN_INT_CNTL);
1618 /* clear vline irq status */
1619 writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1621 while(timeout > 0) {
1622 if (readl(remapped_regs + mmGEN_INT_STATUS) & 0x00000002)
1628 /* disable vline irq */
1629 writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1631 /* clear vline irq status */
1632 writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1635 static struct platform_driver w100fb_driver = {
1636 .probe = w100fb_probe,
1637 .remove = w100fb_remove,
1638 .suspend = w100fb_suspend,
1639 .resume = w100fb_resume,
1645 module_platform_driver(w100fb_driver);
1647 MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
1648 MODULE_LICENSE("GPL");