1 // SPDX-License-Identifier: GPL-2.0-only
3 * linux/drivers/video/w100fb.c
5 * Frame Buffer Device for ATI Imageon w100 (Wallaby)
7 * Copyright (C) 2002, ATI Corp.
8 * Copyright (C) 2004-2006 Richard Purdie
9 * Copyright (c) 2005 Ian Molton
10 * Copyright (c) 2006 Alberto Mardegan
12 * Rewritten for 2.6 by Richard Purdie <rpurdie@rpsys.net>
14 * Generic platform support by Ian Molton <spyro@f2s.com>
15 * and Richard Purdie <rpurdie@rpsys.net>
17 * w32xx support by Ian Molton
19 * Hardware acceleration support by Alberto Mardegan
20 * <mardy@users.sourceforge.net>
23 #include <linux/delay.h>
25 #include <linux/init.h>
26 #include <linux/kernel.h>
28 #include <linux/platform_device.h>
29 #include <linux/slab.h>
30 #include <linux/string.h>
31 #include <linux/vmalloc.h>
32 #include <linux/module.h>
34 #include <linux/uaccess.h>
35 #include <video/w100fb.h>
41 static void w100_suspend(u32 mode);
42 static void w100_vsync(void);
43 static void w100_hw_init(struct w100fb_par*);
44 static void w100_pwm_setup(struct w100fb_par*);
45 static void w100_init_clocks(struct w100fb_par*);
46 static void w100_setup_memory(struct w100fb_par*);
47 static void w100_init_lcd(struct w100fb_par*);
48 static void w100_set_dispregs(struct w100fb_par*);
49 static void w100_update_enable(void);
50 static void w100_update_disable(void);
51 static void calc_hsync(struct w100fb_par *par);
52 static void w100_init_graphic_engine(struct w100fb_par *par);
53 struct w100_pll_info *w100_get_xtal_table(unsigned int freq);
55 /* Pseudo palette size */
56 #define MAX_PALETTES 16
58 #define W100_SUSPEND_EXTMEM 0
59 #define W100_SUSPEND_ALL 1
61 #define BITS_PER_PIXEL 16
63 /* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */
64 static void *remapped_base;
65 static void *remapped_regs;
66 static void *remapped_fbuf;
68 #define REMAPPED_FB_LEN 0x15ffff
70 /* This is the offset in the w100's address space we map the current
71 framebuffer memory to. We use the position of external memory as
72 we can remap internal memory to there if external isn't present. */
73 #define W100_FB_BASE MEM_EXT_BASE_VALUE
79 static ssize_t flip_show(struct device *dev, struct device_attribute *attr, char *buf)
81 struct fb_info *info = dev_get_drvdata(dev);
82 struct w100fb_par *par=info->par;
84 return sprintf(buf, "%d\n",par->flip);
87 static ssize_t flip_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
90 struct fb_info *info = dev_get_drvdata(dev);
91 struct w100fb_par *par=info->par;
93 flip = simple_strtoul(buf, NULL, 10);
100 w100_update_disable();
101 w100_set_dispregs(par);
102 w100_update_enable();
109 static DEVICE_ATTR_RW(flip);
111 static ssize_t w100fb_reg_read(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
113 unsigned long regs, param;
114 regs = simple_strtoul(buf, NULL, 16);
115 param = readl(remapped_regs + regs);
116 printk("Read Register 0x%08lX: 0x%08lX\n", regs, param);
120 static DEVICE_ATTR(reg_read, 0200, NULL, w100fb_reg_read);
122 static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
124 unsigned long regs, param;
125 sscanf(buf, "%lx %lx", ®s, ¶m);
127 if (regs <= 0x2000) {
128 printk("Write Register 0x%08lX: 0x%08lX\n", regs, param);
129 writel(param, remapped_regs + regs);
135 static DEVICE_ATTR(reg_write, 0200, NULL, w100fb_reg_write);
138 static ssize_t fastpllclk_show(struct device *dev, struct device_attribute *attr, char *buf)
140 struct fb_info *info = dev_get_drvdata(dev);
141 struct w100fb_par *par=info->par;
143 return sprintf(buf, "%d\n",par->fastpll_mode);
146 static ssize_t fastpllclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
148 struct fb_info *info = dev_get_drvdata(dev);
149 struct w100fb_par *par=info->par;
151 if (simple_strtoul(buf, NULL, 10) > 0) {
153 printk("w100fb: Using fast system clock (if possible)\n");
156 printk("w100fb: Using normal system clock\n");
159 w100_init_clocks(par);
165 static DEVICE_ATTR_RW(fastpllclk);
168 * Some touchscreens need hsync information from the video driver to
169 * function correctly. We export it here.
171 unsigned long w100fb_get_hsynclen(struct device *dev)
173 struct fb_info *info = dev_get_drvdata(dev);
174 struct w100fb_par *par=info->par;
176 /* If display is blanked/suspended, hsync isn't active */
180 return par->hsync_len;
182 EXPORT_SYMBOL(w100fb_get_hsynclen);
184 static void w100fb_clear_screen(struct w100fb_par *par)
186 memset_io(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), 0, (par->xres * par->yres * BITS_PER_PIXEL/8));
191 * Set a palette value from rgb components
193 static int w100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
194 u_int trans, struct fb_info *info)
200 * If greyscale is true, then we convert the RGB value
201 * to greyscale no matter what visual we are using.
203 if (info->var.grayscale)
204 red = green = blue = (19595 * red + 38470 * green + 7471 * blue) >> 16;
207 * 16-bit True Colour. We encode the RGB value
208 * according to the RGB bitfield information.
210 if (regno < MAX_PALETTES) {
211 u32 *pal = info->pseudo_palette;
213 val = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
222 * Blank the display based on value in blank_mode
224 static int w100fb_blank(int blank_mode, struct fb_info *info)
226 struct w100fb_par *par = info->par;
227 struct w100_tg_info *tg = par->mach->tg;
231 case FB_BLANK_NORMAL: /* Normal blanking */
232 case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
233 case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
234 case FB_BLANK_POWERDOWN: /* Poweroff */
235 if (par->blanked == 0) {
236 if(tg && tg->suspend)
242 case FB_BLANK_UNBLANK: /* Unblanking */
243 if (par->blanked != 0) {
254 static void w100_fifo_wait(int entries)
256 union rbbm_status_u status;
259 for (i = 0; i < 2000000; i++) {
260 status.val = readl(remapped_regs + mmRBBM_STATUS);
261 if (status.f.cmdfifo_avail >= entries)
265 printk(KERN_ERR "w100fb: FIFO Timeout!\n");
269 static int w100fb_sync(struct fb_info *info)
271 union rbbm_status_u status;
274 for (i = 0; i < 2000000; i++) {
275 status.val = readl(remapped_regs + mmRBBM_STATUS);
276 if (!status.f.gui_active)
280 printk(KERN_ERR "w100fb: Graphic engine timeout!\n");
285 static void w100_init_graphic_engine(struct w100fb_par *par)
287 union dp_gui_master_cntl_u gmc;
288 union dp_mix_u dp_mix;
289 union dp_datatype_u dp_datatype;
290 union dp_cntl_u dp_cntl;
293 writel(W100_FB_BASE, remapped_regs + mmDST_OFFSET);
294 writel(par->xres, remapped_regs + mmDST_PITCH);
295 writel(W100_FB_BASE, remapped_regs + mmSRC_OFFSET);
296 writel(par->xres, remapped_regs + mmSRC_PITCH);
299 writel(0, remapped_regs + mmSC_TOP_LEFT);
300 writel((par->yres << 16) | par->xres, remapped_regs + mmSC_BOTTOM_RIGHT);
301 writel(0x1fff1fff, remapped_regs + mmSRC_SC_BOTTOM_RIGHT);
305 dp_cntl.f.dst_x_dir = 1;
306 dp_cntl.f.dst_y_dir = 1;
307 dp_cntl.f.src_x_dir = 1;
308 dp_cntl.f.src_y_dir = 1;
309 dp_cntl.f.dst_major_x = 1;
310 dp_cntl.f.src_major_x = 1;
311 writel(dp_cntl.val, remapped_regs + mmDP_CNTL);
314 gmc.f.gmc_src_pitch_offset_cntl = 1;
315 gmc.f.gmc_dst_pitch_offset_cntl = 1;
316 gmc.f.gmc_src_clipping = 1;
317 gmc.f.gmc_dst_clipping = 1;
318 gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
319 gmc.f.gmc_dst_datatype = 3; /* from DstType_16Bpp_444 */
320 gmc.f.gmc_src_datatype = SRC_DATATYPE_EQU_DST;
321 gmc.f.gmc_byte_pix_order = 1;
322 gmc.f.gmc_default_sel = 0;
323 gmc.f.gmc_rop3 = ROP3_SRCCOPY;
324 gmc.f.gmc_dp_src_source = DP_SRC_MEM_RECTANGULAR;
325 gmc.f.gmc_clr_cmp_fcn_dis = 1;
326 gmc.f.gmc_wr_msk_dis = 1;
327 gmc.f.gmc_dp_op = DP_OP_ROP;
328 writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
330 dp_datatype.val = dp_mix.val = 0;
331 dp_datatype.f.dp_dst_datatype = gmc.f.gmc_dst_datatype;
332 dp_datatype.f.dp_brush_datatype = gmc.f.gmc_brush_datatype;
333 dp_datatype.f.dp_src2_type = 0;
334 dp_datatype.f.dp_src2_datatype = gmc.f.gmc_src_datatype;
335 dp_datatype.f.dp_src_datatype = gmc.f.gmc_src_datatype;
336 dp_datatype.f.dp_byte_pix_order = gmc.f.gmc_byte_pix_order;
337 writel(dp_datatype.val, remapped_regs + mmDP_DATATYPE);
339 dp_mix.f.dp_src_source = gmc.f.gmc_dp_src_source;
340 dp_mix.f.dp_src2_source = 1;
341 dp_mix.f.dp_rop3 = gmc.f.gmc_rop3;
342 dp_mix.f.dp_op = gmc.f.gmc_dp_op;
343 writel(dp_mix.val, remapped_regs + mmDP_MIX);
347 static void w100fb_fillrect(struct fb_info *info,
348 const struct fb_fillrect *rect)
350 union dp_gui_master_cntl_u gmc;
352 if (info->state != FBINFO_STATE_RUNNING)
354 if (info->flags & FBINFO_HWACCEL_DISABLED) {
355 cfb_fillrect(info, rect);
359 gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
360 gmc.f.gmc_rop3 = ROP3_PATCOPY;
361 gmc.f.gmc_brush_datatype = GMC_BRUSH_SOLID_COLOR;
363 writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
364 writel(rect->color, remapped_regs + mmDP_BRUSH_FRGD_CLR);
367 writel((rect->dy << 16) | (rect->dx & 0xffff), remapped_regs + mmDST_Y_X);
368 writel((rect->width << 16) | (rect->height & 0xffff),
369 remapped_regs + mmDST_WIDTH_HEIGHT);
373 static void w100fb_copyarea(struct fb_info *info,
374 const struct fb_copyarea *area)
376 u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
377 u32 h = area->height, w = area->width;
378 union dp_gui_master_cntl_u gmc;
380 if (info->state != FBINFO_STATE_RUNNING)
382 if (info->flags & FBINFO_HWACCEL_DISABLED) {
383 cfb_copyarea(info, area);
387 gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
388 gmc.f.gmc_rop3 = ROP3_SRCCOPY;
389 gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
391 writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
394 writel((sy << 16) | (sx & 0xffff), remapped_regs + mmSRC_Y_X);
395 writel((dy << 16) | (dx & 0xffff), remapped_regs + mmDST_Y_X);
396 writel((w << 16) | (h & 0xffff), remapped_regs + mmDST_WIDTH_HEIGHT);
401 * Change the resolution by calling the appropriate hardware functions
403 static void w100fb_activate_var(struct w100fb_par *par)
405 struct w100_tg_info *tg = par->mach->tg;
408 w100_setup_memory(par);
409 w100_init_clocks(par);
410 w100fb_clear_screen(par);
413 w100_update_disable();
415 w100_set_dispregs(par);
416 w100_update_enable();
417 w100_init_graphic_engine(par);
421 if (!par->blanked && tg && tg->change)
426 /* Select the smallest mode that allows the desired resolution to be
427 * displayed. If desired, the x and y parameters can be rounded up to
428 * match the selected mode.
430 static struct w100_mode *w100fb_get_mode(struct w100fb_par *par, unsigned int *x, unsigned int *y, int saveval)
432 struct w100_mode *mode = NULL;
433 struct w100_mode *modelist = par->mach->modelist;
434 unsigned int best_x = 0xffffffff, best_y = 0xffffffff;
437 for (i = 0 ; i < par->mach->num_modes ; i++) {
438 if (modelist[i].xres >= *x && modelist[i].yres >= *y &&
439 modelist[i].xres < best_x && modelist[i].yres < best_y) {
440 best_x = modelist[i].xres;
441 best_y = modelist[i].yres;
443 } else if(modelist[i].xres >= *y && modelist[i].yres >= *x &&
444 modelist[i].xres < best_y && modelist[i].yres < best_x) {
445 best_x = modelist[i].yres;
446 best_y = modelist[i].xres;
451 if (mode && saveval) {
461 * w100fb_check_var():
462 * Get the video params out of 'var'. If a value doesn't fit, round it up,
463 * if it's too big, return -EINVAL.
465 static int w100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
467 struct w100fb_par *par=info->par;
469 if(!w100fb_get_mode(par, &var->xres, &var->yres, 1))
472 if (par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (par->mach->mem->size+1)))
475 if (!par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)))
478 var->xres_virtual = max(var->xres_virtual, var->xres);
479 var->yres_virtual = max(var->yres_virtual, var->yres);
481 if (var->bits_per_pixel > BITS_PER_PIXEL)
484 var->bits_per_pixel = BITS_PER_PIXEL;
486 var->red.offset = 11;
488 var->green.offset = 5;
489 var->green.length = 6;
490 var->blue.offset = 0;
491 var->blue.length = 5;
492 var->transp.offset = var->transp.length = 0;
497 var->vmode = FB_VMODE_NONINTERLACED;
499 var->pixclock = 0x04; /* 171521; */
507 * Set the user defined part of the display for the specified console
508 * by looking at the values in info.var
510 static int w100fb_set_par(struct fb_info *info)
512 struct w100fb_par *par=info->par;
514 if (par->xres != info->var.xres || par->yres != info->var.yres) {
515 par->xres = info->var.xres;
516 par->yres = info->var.yres;
517 par->mode = w100fb_get_mode(par, &par->xres, &par->yres, 0);
519 info->fix.visual = FB_VISUAL_TRUECOLOR;
520 info->fix.ypanstep = 0;
521 info->fix.ywrapstep = 0;
522 info->fix.line_length = par->xres * BITS_PER_PIXEL / 8;
524 mutex_lock(&info->mm_lock);
525 if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) {
526 par->extmem_active = 1;
527 info->fix.smem_len = par->mach->mem->size+1;
529 par->extmem_active = 0;
530 info->fix.smem_len = MEM_INT_SIZE+1;
532 mutex_unlock(&info->mm_lock);
534 w100fb_activate_var(par);
541 * Frame buffer operations
543 static struct fb_ops w100fb_ops = {
544 .owner = THIS_MODULE,
545 .fb_check_var = w100fb_check_var,
546 .fb_set_par = w100fb_set_par,
547 .fb_setcolreg = w100fb_setcolreg,
548 .fb_blank = w100fb_blank,
549 .fb_fillrect = w100fb_fillrect,
550 .fb_copyarea = w100fb_copyarea,
551 .fb_imageblit = cfb_imageblit,
552 .fb_sync = w100fb_sync,
556 static void w100fb_save_vidmem(struct w100fb_par *par)
560 if (par->extmem_active) {
561 memsize=par->mach->mem->size;
562 par->saved_extmem = vmalloc(memsize);
563 if (par->saved_extmem)
564 memcpy_fromio(par->saved_extmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
566 memsize=MEM_INT_SIZE;
567 par->saved_intmem = vmalloc(memsize);
568 if (par->saved_intmem && par->extmem_active)
569 memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), memsize);
570 else if (par->saved_intmem)
571 memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
574 static void w100fb_restore_vidmem(struct w100fb_par *par)
578 if (par->extmem_active && par->saved_extmem) {
579 memsize=par->mach->mem->size;
580 memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_extmem, memsize);
581 vfree(par->saved_extmem);
583 if (par->saved_intmem) {
584 memsize=MEM_INT_SIZE;
585 if (par->extmem_active)
586 memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), par->saved_intmem, memsize);
588 memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_intmem, memsize);
589 vfree(par->saved_intmem);
593 static int w100fb_suspend(struct platform_device *dev, pm_message_t state)
595 struct fb_info *info = platform_get_drvdata(dev);
596 struct w100fb_par *par=info->par;
597 struct w100_tg_info *tg = par->mach->tg;
599 w100fb_save_vidmem(par);
600 if(tg && tg->suspend)
602 w100_suspend(W100_SUSPEND_ALL);
608 static int w100fb_resume(struct platform_device *dev)
610 struct fb_info *info = platform_get_drvdata(dev);
611 struct w100fb_par *par=info->par;
612 struct w100_tg_info *tg = par->mach->tg;
615 w100fb_activate_var(par);
616 w100fb_restore_vidmem(par);
624 #define w100fb_suspend NULL
625 #define w100fb_resume NULL
629 int w100fb_probe(struct platform_device *pdev)
632 struct w100fb_mach_info *inf;
633 struct fb_info *info = NULL;
634 struct w100fb_par *par;
635 struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
636 unsigned int chip_id;
641 /* Remap the chip base address */
642 remapped_base = ioremap_nocache(mem->start+W100_CFG_BASE, W100_CFG_LEN);
643 if (remapped_base == NULL)
646 /* Map the register space */
647 remapped_regs = ioremap_nocache(mem->start+W100_REG_BASE, W100_REG_LEN);
648 if (remapped_regs == NULL)
651 /* Identify the chip */
653 chip_id = readl(remapped_regs + mmCHIP_ID);
655 case CHIP_ID_W100: printk("w100"); break;
656 case CHIP_ID_W3200: printk("w3200"); break;
657 case CHIP_ID_W3220: printk("w3220"); break;
659 printk("Unknown imageon chip ID\n");
663 printk(" at 0x%08lx.\n", (unsigned long) mem->start+W100_CFG_BASE);
665 /* Remap the framebuffer */
666 remapped_fbuf = ioremap_nocache(mem->start+MEM_WINDOW_BASE, MEM_WINDOW_SIZE);
667 if (remapped_fbuf == NULL)
670 info=framebuffer_alloc(sizeof(struct w100fb_par), &pdev->dev);
677 platform_set_drvdata(pdev, info);
679 inf = dev_get_platdata(&pdev->dev);
680 par->chip_id = chip_id;
682 par->fastpll_mode = 0;
685 par->pll_table=w100_get_xtal_table(inf->xtal_freq);
686 if (!par->pll_table) {
687 printk(KERN_ERR "No matching Xtal definition found\n");
692 info->pseudo_palette = kmalloc_array(MAX_PALETTES, sizeof(u32),
694 if (!info->pseudo_palette) {
699 info->fbops = &w100fb_ops;
700 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
701 FBINFO_HWACCEL_FILLRECT;
703 info->screen_base = remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE);
704 info->screen_size = REMAPPED_FB_LEN;
706 strcpy(info->fix.id, "w100fb");
707 info->fix.type = FB_TYPE_PACKED_PIXELS;
708 info->fix.type_aux = 0;
709 info->fix.accel = FB_ACCEL_NONE;
710 info->fix.smem_start = mem->start+W100_FB_BASE;
711 info->fix.mmio_start = mem->start+W100_REG_BASE;
712 info->fix.mmio_len = W100_REG_LEN;
714 if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
719 par->mode = &inf->modelist[0];
720 if(inf->init_mode & INIT_MODE_ROTATED) {
721 info->var.xres = par->mode->yres;
722 info->var.yres = par->mode->xres;
725 info->var.xres = par->mode->xres;
726 info->var.yres = par->mode->yres;
729 if(inf->init_mode &= INIT_MODE_FLIPPED)
734 info->var.xres_virtual = info->var.xres;
735 info->var.yres_virtual = info->var.yres;
736 info->var.pixclock = 0x04; /* 171521; */
738 info->var.grayscale = 0;
739 info->var.xoffset = info->var.yoffset = 0;
740 info->var.accel_flags = 0;
741 info->var.activate = FB_ACTIVATE_NOW;
745 if (w100fb_check_var(&info->var, info) < 0) {
750 if (register_framebuffer(info) < 0) {
755 err = device_create_file(&pdev->dev, &dev_attr_fastpllclk);
756 err |= device_create_file(&pdev->dev, &dev_attr_reg_read);
757 err |= device_create_file(&pdev->dev, &dev_attr_reg_write);
758 err |= device_create_file(&pdev->dev, &dev_attr_flip);
761 fb_warn(info, "failed to register attributes (%d)\n", err);
763 fb_info(info, "%s frame buffer device\n", info->fix.id);
767 fb_dealloc_cmap(&info->cmap);
768 kfree(info->pseudo_palette);
770 if (remapped_fbuf != NULL)
771 iounmap(remapped_fbuf);
772 if (remapped_regs != NULL)
773 iounmap(remapped_regs);
774 if (remapped_base != NULL)
775 iounmap(remapped_base);
777 framebuffer_release(info);
782 static int w100fb_remove(struct platform_device *pdev)
784 struct fb_info *info = platform_get_drvdata(pdev);
785 struct w100fb_par *par=info->par;
787 device_remove_file(&pdev->dev, &dev_attr_fastpllclk);
788 device_remove_file(&pdev->dev, &dev_attr_reg_read);
789 device_remove_file(&pdev->dev, &dev_attr_reg_write);
790 device_remove_file(&pdev->dev, &dev_attr_flip);
792 unregister_framebuffer(info);
794 vfree(par->saved_intmem);
795 vfree(par->saved_extmem);
796 kfree(info->pseudo_palette);
797 fb_dealloc_cmap(&info->cmap);
799 iounmap(remapped_base);
800 iounmap(remapped_regs);
801 iounmap(remapped_fbuf);
803 framebuffer_release(info);
809 /* ------------------- chipset specific functions -------------------------- */
812 static void w100_soft_reset(void)
814 u16 val = readw((u16 *) remapped_base + cfgSTATUS);
815 writew(val | 0x08, (u16 *) remapped_base + cfgSTATUS);
817 writew(0x00, (u16 *) remapped_base + cfgSTATUS);
821 static void w100_update_disable(void)
823 union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
825 /* Prevent display updates */
826 disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
827 disp_db_buf_wr_cntl.f.update_db_buf = 0;
828 disp_db_buf_wr_cntl.f.en_db_buf = 0;
829 writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
832 static void w100_update_enable(void)
834 union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
836 /* Enable display updates */
837 disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
838 disp_db_buf_wr_cntl.f.update_db_buf = 1;
839 disp_db_buf_wr_cntl.f.en_db_buf = 1;
840 writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
843 unsigned long w100fb_gpio_read(int port)
847 if (port==W100_GPIO_PORT_A)
848 value = readl(remapped_regs + mmGPIO_DATA);
850 value = readl(remapped_regs + mmGPIO_DATA2);
855 void w100fb_gpio_write(int port, unsigned long value)
857 if (port==W100_GPIO_PORT_A)
858 writel(value, remapped_regs + mmGPIO_DATA);
860 writel(value, remapped_regs + mmGPIO_DATA2);
862 EXPORT_SYMBOL(w100fb_gpio_read);
863 EXPORT_SYMBOL(w100fb_gpio_write);
866 * Initialization of critical w100 hardware
868 static void w100_hw_init(struct w100fb_par *par)
871 union cif_cntl_u cif_cntl;
872 union intf_cntl_u intf_cntl;
873 union cfgreg_base_u cfgreg_base;
874 union wrap_top_dir_u wrap_top_dir;
875 union cif_read_dbg_u cif_read_dbg;
876 union cpu_defaults_u cpu_default;
877 union cif_write_dbg_u cif_write_dbg;
878 union wrap_start_dir_u wrap_start_dir;
879 union cif_io_u cif_io;
880 struct w100_gpio_regs *gpio = par->mach->gpio;
884 /* This is what the fpga_init code does on reset. May be wrong
885 but there is little info available */
886 writel(0x31, remapped_regs + mmSCRATCH_UMSK);
887 for (temp32 = 0; temp32 < 10000; temp32++)
888 readl(remapped_regs + mmSCRATCH_UMSK);
889 writel(0x30, remapped_regs + mmSCRATCH_UMSK);
892 cif_io.val = defCIF_IO;
893 writel((u32)(cif_io.val), remapped_regs + mmCIF_IO);
895 cif_write_dbg.val = readl(remapped_regs + mmCIF_WRITE_DBG);
896 cif_write_dbg.f.dis_packer_ful_during_rbbm_timeout = 0;
897 cif_write_dbg.f.en_dword_split_to_rbbm = 1;
898 cif_write_dbg.f.dis_timeout_during_rbbm = 1;
899 writel((u32) (cif_write_dbg.val), remapped_regs + mmCIF_WRITE_DBG);
901 cif_read_dbg.val = readl(remapped_regs + mmCIF_READ_DBG);
902 cif_read_dbg.f.dis_rd_same_byte_to_trig_fetch = 1;
903 writel((u32) (cif_read_dbg.val), remapped_regs + mmCIF_READ_DBG);
905 cif_cntl.val = readl(remapped_regs + mmCIF_CNTL);
906 cif_cntl.f.dis_system_bits = 1;
907 cif_cntl.f.dis_mr = 1;
908 cif_cntl.f.en_wait_to_compensate_dq_prop_dly = 0;
909 cif_cntl.f.intb_oe = 1;
910 cif_cntl.f.interrupt_active_high = 1;
911 writel((u32) (cif_cntl.val), remapped_regs + mmCIF_CNTL);
913 /* Setup cfgINTF_CNTL and cfgCPU defaults */
914 intf_cntl.val = defINTF_CNTL;
915 intf_cntl.f.ad_inc_a = 1;
916 intf_cntl.f.ad_inc_b = 1;
917 intf_cntl.f.rd_data_rdy_a = 0;
918 intf_cntl.f.rd_data_rdy_b = 0;
919 writeb((u8) (intf_cntl.val), remapped_base + cfgINTF_CNTL);
921 cpu_default.val = defCPU_DEFAULTS;
922 cpu_default.f.access_ind_addr_a = 1;
923 cpu_default.f.access_ind_addr_b = 1;
924 cpu_default.f.access_scratch_reg = 1;
925 cpu_default.f.transition_size = 0;
926 writeb((u8) (cpu_default.val), remapped_base + cfgCPU_DEFAULTS);
928 /* set up the apertures */
929 writeb((u8) (W100_REG_BASE >> 16), remapped_base + cfgREG_BASE);
931 cfgreg_base.val = defCFGREG_BASE;
932 cfgreg_base.f.cfgreg_base = W100_CFG_BASE;
933 writel((u32) (cfgreg_base.val), remapped_regs + mmCFGREG_BASE);
935 wrap_start_dir.val = defWRAP_START_DIR;
936 wrap_start_dir.f.start_addr = WRAP_BUF_BASE_VALUE >> 1;
937 writel((u32) (wrap_start_dir.val), remapped_regs + mmWRAP_START_DIR);
939 wrap_top_dir.val = defWRAP_TOP_DIR;
940 wrap_top_dir.f.top_addr = WRAP_BUF_TOP_VALUE >> 1;
941 writel((u32) (wrap_top_dir.val), remapped_regs + mmWRAP_TOP_DIR);
943 writel((u32) 0x2440, remapped_regs + mmRBBM_CNTL);
945 /* Set the hardware to 565 colour */
946 temp32 = readl(remapped_regs + mmDISP_DEBUG2);
947 temp32 &= 0xff7fffff;
948 temp32 |= 0x00800000;
949 writel(temp32, remapped_regs + mmDISP_DEBUG2);
951 /* Initialise the GPIO lines */
953 writel(gpio->init_data1, remapped_regs + mmGPIO_DATA);
954 writel(gpio->init_data2, remapped_regs + mmGPIO_DATA2);
955 writel(gpio->gpio_dir1, remapped_regs + mmGPIO_CNTL1);
956 writel(gpio->gpio_oe1, remapped_regs + mmGPIO_CNTL2);
957 writel(gpio->gpio_dir2, remapped_regs + mmGPIO_CNTL3);
958 writel(gpio->gpio_oe2, remapped_regs + mmGPIO_CNTL4);
964 union clk_pin_cntl_u clk_pin_cntl;
965 union pll_ref_fb_div_u pll_ref_fb_div;
966 union pll_cntl_u pll_cntl;
967 union sclk_cntl_u sclk_cntl;
968 union pclk_cntl_u pclk_cntl;
969 union pwrmgt_cntl_u pwrmgt_cntl;
970 int auto_mode; /* system clock auto changing? */
974 static struct power_state w100_pwr_state;
976 /* The PLL Fout is determined by (XtalFreq/(M+1)) * ((N_int+1) + (N_fac/8)) */
978 /* 12.5MHz Crystal PLL Table */
979 static struct w100_pll_info xtal_12500000[] = {
980 /*freq M N_int N_fac tfgoal lock_time */
981 { 50, 0, 1, 0, 0xe0, 56}, /* 50.00 MHz */
982 { 75, 0, 5, 0, 0xde, 37}, /* 75.00 MHz */
983 {100, 0, 7, 0, 0xe0, 28}, /* 100.00 MHz */
984 {125, 0, 9, 0, 0xe0, 22}, /* 125.00 MHz */
985 {150, 0, 11, 0, 0xe0, 17}, /* 150.00 MHz */
986 { 0, 0, 0, 0, 0, 0}, /* Terminator */
989 /* 14.318MHz Crystal PLL Table */
990 static struct w100_pll_info xtal_14318000[] = {
991 /*freq M N_int N_fac tfgoal lock_time */
992 { 40, 4, 13, 0, 0xe0, 80}, /* tfgoal guessed */
993 { 50, 1, 6, 0, 0xe0, 64}, /* 50.05 MHz */
994 { 57, 2, 11, 0, 0xe0, 53}, /* tfgoal guessed */
995 { 75, 0, 4, 3, 0xe0, 43}, /* 75.08 MHz */
996 {100, 0, 6, 0, 0xe0, 32}, /* 100.10 MHz */
1000 /* 16MHz Crystal PLL Table */
1001 static struct w100_pll_info xtal_16000000[] = {
1002 /*freq M N_int N_fac tfgoal lock_time */
1003 { 72, 1, 8, 0, 0xe0, 48}, /* tfgoal guessed */
1004 { 80, 1, 9, 0, 0xe0, 13}, /* tfgoal guessed */
1005 { 95, 1, 10, 7, 0xe0, 38}, /* tfgoal guessed */
1006 { 96, 1, 11, 0, 0xe0, 36}, /* tfgoal guessed */
1007 { 0, 0, 0, 0, 0, 0},
1010 static struct pll_entries {
1012 struct w100_pll_info *pll_table;
1013 } w100_pll_tables[] = {
1014 { 12500000, &xtal_12500000[0] },
1015 { 14318000, &xtal_14318000[0] },
1016 { 16000000, &xtal_16000000[0] },
1020 struct w100_pll_info *w100_get_xtal_table(unsigned int freq)
1022 struct pll_entries *pll_entry = w100_pll_tables;
1025 if (freq == pll_entry->xtal_freq)
1026 return pll_entry->pll_table;
1028 } while (pll_entry->xtal_freq);
1033 static unsigned int w100_get_testcount(unsigned int testclk_sel)
1035 union clk_test_cntl_u clk_test_cntl;
1039 /* Select the test clock source and reset */
1040 clk_test_cntl.f.start_check_freq = 0x0;
1041 clk_test_cntl.f.testclk_sel = testclk_sel;
1042 clk_test_cntl.f.tstcount_rst = 0x1; /* set reset */
1043 writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1045 clk_test_cntl.f.tstcount_rst = 0x0; /* clear reset */
1046 writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1048 /* Run clock test */
1049 clk_test_cntl.f.start_check_freq = 0x1;
1050 writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1052 /* Give the test time to complete */
1055 /* Return the result */
1056 clk_test_cntl.val = readl(remapped_regs + mmCLK_TEST_CNTL);
1057 clk_test_cntl.f.start_check_freq = 0x0;
1058 writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1060 return clk_test_cntl.f.test_count;
1064 static int w100_pll_adjust(struct w100_pll_info *pll)
1069 /* Initial Settings */
1070 w100_pwr_state.pll_cntl.f.pll_pwdn = 0x0; /* power down */
1071 w100_pwr_state.pll_cntl.f.pll_reset = 0x0; /* not reset */
1072 w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x1; /* Hi-Z */
1073 w100_pwr_state.pll_cntl.f.pll_pvg = 0x0; /* VCO gain = 0 */
1074 w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0; /* VCO frequency range control = off */
1075 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; /* current offset inside VCO = 0 */
1076 w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
1078 /* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V
1079 * therefore, commented out the following lines
1083 /* set VCO input = 0.8 * VDD */
1084 w100_pwr_state.pll_cntl.f.pll_dactal = 0xd;
1085 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1087 tf80 = w100_get_testcount(TESTCLK_SRC_PLL);
1088 if (tf80 >= (pll->tfgoal)) {
1089 /* set VCO input = 0.2 * VDD */
1090 w100_pwr_state.pll_cntl.f.pll_dactal = 0x7;
1091 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1093 tf20 = w100_get_testcount(TESTCLK_SRC_PLL);
1094 if (tf20 <= (pll->tfgoal))
1095 return 1; /* Success */
1097 if ((w100_pwr_state.pll_cntl.f.pll_vcofr == 0x0) &&
1098 ((w100_pwr_state.pll_cntl.f.pll_pvg == 0x7) ||
1099 (w100_pwr_state.pll_cntl.f.pll_ioffset == 0x0))) {
1100 /* slow VCO config */
1101 w100_pwr_state.pll_cntl.f.pll_vcofr = 0x1;
1102 w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
1103 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1107 if ((w100_pwr_state.pll_cntl.f.pll_ioffset) < 0x3) {
1108 w100_pwr_state.pll_cntl.f.pll_ioffset += 0x1;
1109 } else if ((w100_pwr_state.pll_cntl.f.pll_pvg) < 0x7) {
1110 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1111 w100_pwr_state.pll_cntl.f.pll_pvg += 0x1;
1113 return 0; /* Error */
1120 * w100_pll_calibration
1122 static int w100_pll_calibration(struct w100_pll_info *pll)
1126 status = w100_pll_adjust(pll);
1128 /* PLL Reset And Lock */
1129 /* set VCO input = 0.5 * VDD */
1130 w100_pwr_state.pll_cntl.f.pll_dactal = 0xa;
1131 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1133 udelay(1); /* reset time */
1135 /* enable charge pump */
1136 w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0; /* normal */
1137 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1139 /* set VCO input = Hi-Z, disable DAC */
1140 w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;
1141 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1143 udelay(400); /* lock time */
1151 static int w100_pll_set_clk(struct w100_pll_info *pll)
1155 if (w100_pwr_state.auto_mode == 1) /* auto mode */
1157 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0; /* disable fast to normal */
1158 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0; /* disable normal to fast */
1159 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1162 /* Set system clock source to XTAL whilst adjusting the PLL! */
1163 w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
1164 writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1166 w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = pll->M;
1167 w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = pll->N_int;
1168 w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = pll->N_fac;
1169 w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = pll->lock_time;
1170 writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
1172 w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0;
1173 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1175 status = w100_pll_calibration(pll);
1177 if (w100_pwr_state.auto_mode == 1) /* auto mode */
1179 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x1; /* reenable fast to normal */
1180 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x1; /* reenable normal to fast */
1181 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1186 /* freq = target frequency of the PLL */
1187 static int w100_set_pll_freq(struct w100fb_par *par, unsigned int freq)
1189 struct w100_pll_info *pll = par->pll_table;
1192 if (freq == pll->freq) {
1193 return w100_pll_set_clk(pll);
1200 /* Set up an initial state. Some values/fields set
1201 here will be overwritten. */
1202 static void w100_pwm_setup(struct w100fb_par *par)
1204 w100_pwr_state.clk_pin_cntl.f.osc_en = 0x1;
1205 w100_pwr_state.clk_pin_cntl.f.osc_gain = 0x1f;
1206 w100_pwr_state.clk_pin_cntl.f.dont_use_xtalin = 0x0;
1207 w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x0;
1208 w100_pwr_state.clk_pin_cntl.f.xtalin_dbl_en = par->mach->xtal_dbl ? 1 : 0;
1209 w100_pwr_state.clk_pin_cntl.f.cg_debug = 0x0;
1210 writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL);
1212 w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
1213 w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = 0x0; /* Pfast = 1 */
1214 w100_pwr_state.sclk_cntl.f.sclk_clkon_hys = 0x3;
1215 w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0; /* Pslow = 1 */
1216 w100_pwr_state.sclk_cntl.f.disp_cg_ok2switch_en = 0x0;
1217 w100_pwr_state.sclk_cntl.f.sclk_force_reg = 0x0; /* Dynamic */
1218 w100_pwr_state.sclk_cntl.f.sclk_force_disp = 0x0; /* Dynamic */
1219 w100_pwr_state.sclk_cntl.f.sclk_force_mc = 0x0; /* Dynamic */
1220 w100_pwr_state.sclk_cntl.f.sclk_force_extmc = 0x0; /* Dynamic */
1221 w100_pwr_state.sclk_cntl.f.sclk_force_cp = 0x0; /* Dynamic */
1222 w100_pwr_state.sclk_cntl.f.sclk_force_e2 = 0x0; /* Dynamic */
1223 w100_pwr_state.sclk_cntl.f.sclk_force_e3 = 0x0; /* Dynamic */
1224 w100_pwr_state.sclk_cntl.f.sclk_force_idct = 0x0; /* Dynamic */
1225 w100_pwr_state.sclk_cntl.f.sclk_force_bist = 0x0; /* Dynamic */
1226 w100_pwr_state.sclk_cntl.f.busy_extend_cp = 0x0;
1227 w100_pwr_state.sclk_cntl.f.busy_extend_e2 = 0x0;
1228 w100_pwr_state.sclk_cntl.f.busy_extend_e3 = 0x0;
1229 w100_pwr_state.sclk_cntl.f.busy_extend_idct = 0x0;
1230 writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1232 w100_pwr_state.pclk_cntl.f.pclk_src_sel = CLK_SRC_XTAL;
1233 w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1; /* P = 2 */
1234 w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0; /* Dynamic */
1235 writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
1237 w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0; /* M = 1 */
1238 w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0; /* N = 1.0 */
1239 w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = 0x0;
1240 w100_pwr_state.pll_ref_fb_div.f.pll_reset_time = 0x5;
1241 w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = 0xff;
1242 writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
1244 w100_pwr_state.pll_cntl.f.pll_pwdn = 0x1;
1245 w100_pwr_state.pll_cntl.f.pll_reset = 0x1;
1246 w100_pwr_state.pll_cntl.f.pll_pm_en = 0x0;
1247 w100_pwr_state.pll_cntl.f.pll_mode = 0x0; /* uses VCO clock */
1248 w100_pwr_state.pll_cntl.f.pll_refclk_sel = 0x0;
1249 w100_pwr_state.pll_cntl.f.pll_fbclk_sel = 0x0;
1250 w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;
1251 w100_pwr_state.pll_cntl.f.pll_pcp = 0x4;
1252 w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
1253 w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0;
1254 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1255 w100_pwr_state.pll_cntl.f.pll_pecc_mode = 0x0;
1256 w100_pwr_state.pll_cntl.f.pll_pecc_scon = 0x0;
1257 w100_pwr_state.pll_cntl.f.pll_dactal = 0x0; /* Hi-Z */
1258 w100_pwr_state.pll_cntl.f.pll_cp_clip = 0x3;
1259 w100_pwr_state.pll_cntl.f.pll_conf = 0x2;
1260 w100_pwr_state.pll_cntl.f.pll_mbctrl = 0x2;
1261 w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
1262 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1264 w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x0;
1265 w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1; /* normal mode (0, 1, 3) */
1266 w100_pwr_state.pwrmgt_cntl.f.pwm_wakeup_cond = 0x0;
1267 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;
1268 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;
1269 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1; /* PM4,ENG */
1270 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1; /* PM4,ENG */
1271 w100_pwr_state.pwrmgt_cntl.f.pwm_idle_timer = 0xFF;
1272 w100_pwr_state.pwrmgt_cntl.f.pwm_busy_timer = 0xFF;
1273 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1275 w100_pwr_state.auto_mode = 0; /* manual mode */
1280 * Setup the w100 clocks for the specified mode
1282 static void w100_init_clocks(struct w100fb_par *par)
1284 struct w100_mode *mode = par->mode;
1286 if (mode->pixclk_src == CLK_SRC_PLL || mode->sysclk_src == CLK_SRC_PLL)
1287 w100_set_pll_freq(par, (par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq);
1289 w100_pwr_state.sclk_cntl.f.sclk_src_sel = mode->sysclk_src;
1290 w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = mode->sysclk_divider;
1291 w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = mode->sysclk_divider;
1292 writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1295 static void w100_init_lcd(struct w100fb_par *par)
1298 struct w100_mode *mode = par->mode;
1299 struct w100_gen_regs *regs = par->mach->regs;
1300 union active_h_disp_u active_h_disp;
1301 union active_v_disp_u active_v_disp;
1302 union graphic_h_disp_u graphic_h_disp;
1303 union graphic_v_disp_u graphic_v_disp;
1304 union crtc_total_u crtc_total;
1306 /* w3200 doesn't like undefined bits being set so zero register values first */
1308 active_h_disp.val = 0;
1309 active_h_disp.f.active_h_start=mode->left_margin;
1310 active_h_disp.f.active_h_end=mode->left_margin + mode->xres;
1311 writel(active_h_disp.val, remapped_regs + mmACTIVE_H_DISP);
1313 active_v_disp.val = 0;
1314 active_v_disp.f.active_v_start=mode->upper_margin;
1315 active_v_disp.f.active_v_end=mode->upper_margin + mode->yres;
1316 writel(active_v_disp.val, remapped_regs + mmACTIVE_V_DISP);
1318 graphic_h_disp.val = 0;
1319 graphic_h_disp.f.graphic_h_start=mode->left_margin;
1320 graphic_h_disp.f.graphic_h_end=mode->left_margin + mode->xres;
1321 writel(graphic_h_disp.val, remapped_regs + mmGRAPHIC_H_DISP);
1323 graphic_v_disp.val = 0;
1324 graphic_v_disp.f.graphic_v_start=mode->upper_margin;
1325 graphic_v_disp.f.graphic_v_end=mode->upper_margin + mode->yres;
1326 writel(graphic_v_disp.val, remapped_regs + mmGRAPHIC_V_DISP);
1329 crtc_total.f.crtc_h_total=mode->left_margin + mode->xres + mode->right_margin;
1330 crtc_total.f.crtc_v_total=mode->upper_margin + mode->yres + mode->lower_margin;
1331 writel(crtc_total.val, remapped_regs + mmCRTC_TOTAL);
1333 writel(mode->crtc_ss, remapped_regs + mmCRTC_SS);
1334 writel(mode->crtc_ls, remapped_regs + mmCRTC_LS);
1335 writel(mode->crtc_gs, remapped_regs + mmCRTC_GS);
1336 writel(mode->crtc_vpos_gs, remapped_regs + mmCRTC_VPOS_GS);
1337 writel(mode->crtc_rev, remapped_regs + mmCRTC_REV);
1338 writel(mode->crtc_dclk, remapped_regs + mmCRTC_DCLK);
1339 writel(mode->crtc_gclk, remapped_regs + mmCRTC_GCLK);
1340 writel(mode->crtc_goe, remapped_regs + mmCRTC_GOE);
1341 writel(mode->crtc_ps1_active, remapped_regs + mmCRTC_PS1_ACTIVE);
1343 writel(regs->lcd_format, remapped_regs + mmLCD_FORMAT);
1344 writel(regs->lcdd_cntl1, remapped_regs + mmLCDD_CNTL1);
1345 writel(regs->lcdd_cntl2, remapped_regs + mmLCDD_CNTL2);
1346 writel(regs->genlcd_cntl1, remapped_regs + mmGENLCD_CNTL1);
1347 writel(regs->genlcd_cntl2, remapped_regs + mmGENLCD_CNTL2);
1348 writel(regs->genlcd_cntl3, remapped_regs + mmGENLCD_CNTL3);
1350 writel(0x00000000, remapped_regs + mmCRTC_FRAME);
1351 writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS);
1352 writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT);
1353 writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR);
1355 /* Hack for overlay in ext memory */
1356 temp32 = readl(remapped_regs + mmDISP_DEBUG2);
1357 temp32 |= 0xc0000000;
1358 writel(temp32, remapped_regs + mmDISP_DEBUG2);
1362 static void w100_setup_memory(struct w100fb_par *par)
1364 union mc_ext_mem_location_u extmem_location;
1365 union mc_fb_location_u intmem_location;
1366 struct w100_mem_info *mem = par->mach->mem;
1367 struct w100_bm_mem_info *bm_mem = par->mach->bm_mem;
1369 if (!par->extmem_active) {
1370 w100_suspend(W100_SUSPEND_EXTMEM);
1372 /* Map Internal Memory at FB Base */
1373 intmem_location.f.mc_fb_start = W100_FB_BASE >> 8;
1374 intmem_location.f.mc_fb_top = (W100_FB_BASE+MEM_INT_SIZE) >> 8;
1375 writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
1377 /* Unmap External Memory - value is *probably* irrelevant but may have meaning
1378 to acceleration libraries */
1379 extmem_location.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8;
1380 extmem_location.f.mc_ext_mem_top = (MEM_EXT_BASE_VALUE-1) >> 8;
1381 writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
1383 /* Map Internal Memory to its default location */
1384 intmem_location.f.mc_fb_start = MEM_INT_BASE_VALUE >> 8;
1385 intmem_location.f.mc_fb_top = (MEM_INT_BASE_VALUE+MEM_INT_SIZE) >> 8;
1386 writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
1388 /* Map External Memory at FB Base */
1389 extmem_location.f.mc_ext_mem_start = W100_FB_BASE >> 8;
1390 extmem_location.f.mc_ext_mem_top = (W100_FB_BASE+par->mach->mem->size) >> 8;
1391 writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
1393 writel(0x00007800, remapped_regs + mmMC_BIST_CTRL);
1394 writel(mem->ext_cntl, remapped_regs + mmMEM_EXT_CNTL);
1395 writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
1397 writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
1399 writel(mem->sdram_mode_reg, remapped_regs + mmMEM_SDRAM_MODE_REG);
1401 writel(mem->ext_timing_cntl, remapped_regs + mmMEM_EXT_TIMING_CNTL);
1402 writel(mem->io_cntl, remapped_regs + mmMEM_IO_CNTL);
1404 writel(bm_mem->ext_mem_bw, remapped_regs + mmBM_EXT_MEM_BANDWIDTH);
1405 writel(bm_mem->offset, remapped_regs + mmBM_OFFSET);
1406 writel(bm_mem->ext_timing_ctl, remapped_regs + mmBM_MEM_EXT_TIMING_CNTL);
1407 writel(bm_mem->ext_cntl, remapped_regs + mmBM_MEM_EXT_CNTL);
1408 writel(bm_mem->mode_reg, remapped_regs + mmBM_MEM_MODE_REG);
1409 writel(bm_mem->io_cntl, remapped_regs + mmBM_MEM_IO_CNTL);
1410 writel(bm_mem->config, remapped_regs + mmBM_CONFIG);
1415 static void w100_set_dispregs(struct w100fb_par *par)
1417 unsigned long rot=0, divider, offset=0;
1418 union graphic_ctrl_u graphic_ctrl;
1420 /* See if the mode has been rotated */
1421 if (par->xres == par->mode->xres) {
1423 rot=3; /* 180 degree */
1424 offset=(par->xres * par->yres) - 1;
1425 } /* else 0 degree */
1426 divider = par->mode->pixclk_divider;
1429 rot=2; /* 270 degree */
1430 offset=par->xres - 1;
1432 rot=1; /* 90 degree */
1433 offset=par->xres * (par->yres - 1);
1435 divider = par->mode->pixclk_divider_rotated;
1438 graphic_ctrl.val = 0; /* w32xx doesn't like undefined bits */
1439 switch (par->chip_id) {
1441 graphic_ctrl.f_w100.color_depth=6;
1442 graphic_ctrl.f_w100.en_crtc=1;
1443 graphic_ctrl.f_w100.en_graphic_req=1;
1444 graphic_ctrl.f_w100.en_graphic_crtc=1;
1445 graphic_ctrl.f_w100.lcd_pclk_on=1;
1446 graphic_ctrl.f_w100.lcd_sclk_on=1;
1447 graphic_ctrl.f_w100.low_power_on=0;
1448 graphic_ctrl.f_w100.req_freq=0;
1449 graphic_ctrl.f_w100.portrait_mode=rot;
1451 /* Zaurus needs this */
1456 graphic_ctrl.f_w100.total_req_graphic=0xa0;
1463 graphic_ctrl.f_w100.low_power_on=1;
1464 graphic_ctrl.f_w100.req_freq=5;
1468 graphic_ctrl.f_w100.req_freq=4;
1473 graphic_ctrl.f_w100.total_req_graphic=0xf0;
1479 graphic_ctrl.f_w32xx.color_depth=6;
1480 graphic_ctrl.f_w32xx.en_crtc=1;
1481 graphic_ctrl.f_w32xx.en_graphic_req=1;
1482 graphic_ctrl.f_w32xx.en_graphic_crtc=1;
1483 graphic_ctrl.f_w32xx.lcd_pclk_on=1;
1484 graphic_ctrl.f_w32xx.lcd_sclk_on=1;
1485 graphic_ctrl.f_w32xx.low_power_on=0;
1486 graphic_ctrl.f_w32xx.req_freq=0;
1487 graphic_ctrl.f_w32xx.total_req_graphic=par->mode->xres >> 1; /* panel xres, not mode */
1488 graphic_ctrl.f_w32xx.portrait_mode=rot;
1492 /* Set the pixel clock source and divider */
1493 w100_pwr_state.pclk_cntl.f.pclk_src_sel = par->mode->pixclk_src;
1494 w100_pwr_state.pclk_cntl.f.pclk_post_div = divider;
1495 writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
1497 writel(graphic_ctrl.val, remapped_regs + mmGRAPHIC_CTRL);
1498 writel(W100_FB_BASE + ((offset * BITS_PER_PIXEL/8)&~0x03UL), remapped_regs + mmGRAPHIC_OFFSET);
1499 writel((par->xres*BITS_PER_PIXEL/8), remapped_regs + mmGRAPHIC_PITCH);
1504 * Work out how long the sync pulse lasts
1505 * Value is 1/(time in seconds)
1507 static void calc_hsync(struct w100fb_par *par)
1509 unsigned long hsync;
1510 struct w100_mode *mode = par->mode;
1511 union crtc_ss_u crtc_ss;
1513 if (mode->pixclk_src == CLK_SRC_XTAL)
1514 hsync=par->mach->xtal_freq;
1516 hsync=((par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq)*100000;
1518 hsync /= (w100_pwr_state.pclk_cntl.f.pclk_post_div + 1);
1520 crtc_ss.val = readl(remapped_regs + mmCRTC_SS);
1522 par->hsync_len = hsync / (crtc_ss.f.ss_end-crtc_ss.f.ss_start);
1527 static void w100_suspend(u32 mode)
1531 writel(0x7FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION);
1532 writel(0x00FF0000, remapped_regs + mmMC_PERF_MON_CNTL);
1534 val = readl(remapped_regs + mmMEM_EXT_TIMING_CNTL);
1535 val &= ~(0x00100000); /* bit20=0 */
1536 val |= 0xFF000000; /* bit31:24=0xff */
1537 writel(val, remapped_regs + mmMEM_EXT_TIMING_CNTL);
1539 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1540 val &= ~(0x00040000); /* bit18=0 */
1541 val |= 0x00080000; /* bit19=1 */
1542 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1544 udelay(1); /* wait 1us */
1546 if (mode == W100_SUSPEND_EXTMEM) {
1547 /* CKE: Tri-State */
1548 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1549 val |= 0x40000000; /* bit30=1 */
1550 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1553 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1554 val &= ~(0x00000001); /* bit0=0 */
1555 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1557 writel(0x00000000, remapped_regs + mmSCLK_CNTL);
1558 writel(0x000000BF, remapped_regs + mmCLK_PIN_CNTL);
1559 writel(0x00000015, remapped_regs + mmPWRMGT_CNTL);
1563 val = readl(remapped_regs + mmPLL_CNTL);
1564 val |= 0x00000004; /* bit2=1 */
1565 writel(val, remapped_regs + mmPLL_CNTL);
1567 writel(0x00000000, remapped_regs + mmLCDD_CNTL1);
1568 writel(0x00000000, remapped_regs + mmLCDD_CNTL2);
1569 writel(0x00000000, remapped_regs + mmGENLCD_CNTL1);
1570 writel(0x00000000, remapped_regs + mmGENLCD_CNTL2);
1571 writel(0x00000000, remapped_regs + mmGENLCD_CNTL3);
1573 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1575 val &= ~(0x00000001);
1576 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1578 writel(0x0000001d, remapped_regs + mmPWRMGT_CNTL);
1582 static void w100_vsync(void)
1585 int timeout = 30000; /* VSync timeout = 30[ms] > 16.8[ms] */
1587 tmp = readl(remapped_regs + mmACTIVE_V_DISP);
1590 writel((tmp >> 16) & 0x3ff, remapped_regs + mmDISP_INT_CNTL);
1592 /* disable vline irq */
1593 tmp = readl(remapped_regs + mmGEN_INT_CNTL);
1596 writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1598 /* clear vline irq status */
1599 writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1601 /* enable vline irq */
1602 writel((tmp | 0x00000002), remapped_regs + mmGEN_INT_CNTL);
1604 /* clear vline irq status */
1605 writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1607 while(timeout > 0) {
1608 if (readl(remapped_regs + mmGEN_INT_STATUS) & 0x00000002)
1614 /* disable vline irq */
1615 writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1617 /* clear vline irq status */
1618 writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1621 static struct platform_driver w100fb_driver = {
1622 .probe = w100fb_probe,
1623 .remove = w100fb_remove,
1624 .suspend = w100fb_suspend,
1625 .resume = w100fb_resume,
1631 module_platform_driver(w100fb_driver);
1633 MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
1634 MODULE_LICENSE("GPL");