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 __iomem *remapped_base;
65 static void __iomem *remapped_regs;
66 static void __iomem *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);
167 static struct attribute *w100fb_attrs[] = {
168 &dev_attr_fastpllclk.attr,
169 &dev_attr_reg_read.attr,
170 &dev_attr_reg_write.attr,
174 ATTRIBUTE_GROUPS(w100fb);
177 * Some touchscreens need hsync information from the video driver to
178 * function correctly. We export it here.
180 unsigned long w100fb_get_hsynclen(struct device *dev)
182 struct fb_info *info = dev_get_drvdata(dev);
183 struct w100fb_par *par=info->par;
185 /* If display is blanked/suspended, hsync isn't active */
189 return par->hsync_len;
191 EXPORT_SYMBOL(w100fb_get_hsynclen);
193 static void w100fb_clear_screen(struct w100fb_par *par)
195 memset_io(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), 0, (par->xres * par->yres * BITS_PER_PIXEL/8));
200 * Set a palette value from rgb components
202 static int w100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
203 u_int trans, struct fb_info *info)
209 * If greyscale is true, then we convert the RGB value
210 * to greyscale no matter what visual we are using.
212 if (info->var.grayscale)
213 red = green = blue = (19595 * red + 38470 * green + 7471 * blue) >> 16;
216 * 16-bit True Colour. We encode the RGB value
217 * according to the RGB bitfield information.
219 if (regno < MAX_PALETTES) {
220 u32 *pal = info->pseudo_palette;
222 val = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
231 * Blank the display based on value in blank_mode
233 static int w100fb_blank(int blank_mode, struct fb_info *info)
235 struct w100fb_par *par = info->par;
236 struct w100_tg_info *tg = par->mach->tg;
240 case FB_BLANK_NORMAL: /* Normal blanking */
241 case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
242 case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
243 case FB_BLANK_POWERDOWN: /* Poweroff */
244 if (par->blanked == 0) {
245 if(tg && tg->suspend)
251 case FB_BLANK_UNBLANK: /* Unblanking */
252 if (par->blanked != 0) {
263 static void w100_fifo_wait(int entries)
265 union rbbm_status_u status;
268 for (i = 0; i < 2000000; i++) {
269 status.val = readl(remapped_regs + mmRBBM_STATUS);
270 if (status.f.cmdfifo_avail >= entries)
274 printk(KERN_ERR "w100fb: FIFO Timeout!\n");
278 static int w100fb_sync(struct fb_info *info)
280 union rbbm_status_u status;
283 for (i = 0; i < 2000000; i++) {
284 status.val = readl(remapped_regs + mmRBBM_STATUS);
285 if (!status.f.gui_active)
289 printk(KERN_ERR "w100fb: Graphic engine timeout!\n");
294 static void w100_init_graphic_engine(struct w100fb_par *par)
296 union dp_gui_master_cntl_u gmc;
297 union dp_mix_u dp_mix;
298 union dp_datatype_u dp_datatype;
299 union dp_cntl_u dp_cntl;
302 writel(W100_FB_BASE, remapped_regs + mmDST_OFFSET);
303 writel(par->xres, remapped_regs + mmDST_PITCH);
304 writel(W100_FB_BASE, remapped_regs + mmSRC_OFFSET);
305 writel(par->xres, remapped_regs + mmSRC_PITCH);
308 writel(0, remapped_regs + mmSC_TOP_LEFT);
309 writel((par->yres << 16) | par->xres, remapped_regs + mmSC_BOTTOM_RIGHT);
310 writel(0x1fff1fff, remapped_regs + mmSRC_SC_BOTTOM_RIGHT);
314 dp_cntl.f.dst_x_dir = 1;
315 dp_cntl.f.dst_y_dir = 1;
316 dp_cntl.f.src_x_dir = 1;
317 dp_cntl.f.src_y_dir = 1;
318 dp_cntl.f.dst_major_x = 1;
319 dp_cntl.f.src_major_x = 1;
320 writel(dp_cntl.val, remapped_regs + mmDP_CNTL);
323 gmc.f.gmc_src_pitch_offset_cntl = 1;
324 gmc.f.gmc_dst_pitch_offset_cntl = 1;
325 gmc.f.gmc_src_clipping = 1;
326 gmc.f.gmc_dst_clipping = 1;
327 gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
328 gmc.f.gmc_dst_datatype = 3; /* from DstType_16Bpp_444 */
329 gmc.f.gmc_src_datatype = SRC_DATATYPE_EQU_DST;
330 gmc.f.gmc_byte_pix_order = 1;
331 gmc.f.gmc_default_sel = 0;
332 gmc.f.gmc_rop3 = ROP3_SRCCOPY;
333 gmc.f.gmc_dp_src_source = DP_SRC_MEM_RECTANGULAR;
334 gmc.f.gmc_clr_cmp_fcn_dis = 1;
335 gmc.f.gmc_wr_msk_dis = 1;
336 gmc.f.gmc_dp_op = DP_OP_ROP;
337 writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
339 dp_datatype.val = dp_mix.val = 0;
340 dp_datatype.f.dp_dst_datatype = gmc.f.gmc_dst_datatype;
341 dp_datatype.f.dp_brush_datatype = gmc.f.gmc_brush_datatype;
342 dp_datatype.f.dp_src2_type = 0;
343 dp_datatype.f.dp_src2_datatype = gmc.f.gmc_src_datatype;
344 dp_datatype.f.dp_src_datatype = gmc.f.gmc_src_datatype;
345 dp_datatype.f.dp_byte_pix_order = gmc.f.gmc_byte_pix_order;
346 writel(dp_datatype.val, remapped_regs + mmDP_DATATYPE);
348 dp_mix.f.dp_src_source = gmc.f.gmc_dp_src_source;
349 dp_mix.f.dp_src2_source = 1;
350 dp_mix.f.dp_rop3 = gmc.f.gmc_rop3;
351 dp_mix.f.dp_op = gmc.f.gmc_dp_op;
352 writel(dp_mix.val, remapped_regs + mmDP_MIX);
356 static void w100fb_fillrect(struct fb_info *info,
357 const struct fb_fillrect *rect)
359 union dp_gui_master_cntl_u gmc;
361 if (info->state != FBINFO_STATE_RUNNING)
363 if (info->flags & FBINFO_HWACCEL_DISABLED) {
364 cfb_fillrect(info, rect);
368 gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
369 gmc.f.gmc_rop3 = ROP3_PATCOPY;
370 gmc.f.gmc_brush_datatype = GMC_BRUSH_SOLID_COLOR;
372 writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
373 writel(rect->color, remapped_regs + mmDP_BRUSH_FRGD_CLR);
376 writel((rect->dy << 16) | (rect->dx & 0xffff), remapped_regs + mmDST_Y_X);
377 writel((rect->width << 16) | (rect->height & 0xffff),
378 remapped_regs + mmDST_WIDTH_HEIGHT);
382 static void w100fb_copyarea(struct fb_info *info,
383 const struct fb_copyarea *area)
385 u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
386 u32 h = area->height, w = area->width;
387 union dp_gui_master_cntl_u gmc;
389 if (info->state != FBINFO_STATE_RUNNING)
391 if (info->flags & FBINFO_HWACCEL_DISABLED) {
392 cfb_copyarea(info, area);
396 gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL);
397 gmc.f.gmc_rop3 = ROP3_SRCCOPY;
398 gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE;
400 writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
403 writel((sy << 16) | (sx & 0xffff), remapped_regs + mmSRC_Y_X);
404 writel((dy << 16) | (dx & 0xffff), remapped_regs + mmDST_Y_X);
405 writel((w << 16) | (h & 0xffff), remapped_regs + mmDST_WIDTH_HEIGHT);
410 * Change the resolution by calling the appropriate hardware functions
412 static void w100fb_activate_var(struct w100fb_par *par)
414 struct w100_tg_info *tg = par->mach->tg;
417 w100_setup_memory(par);
418 w100_init_clocks(par);
419 w100fb_clear_screen(par);
422 w100_update_disable();
424 w100_set_dispregs(par);
425 w100_update_enable();
426 w100_init_graphic_engine(par);
430 if (!par->blanked && tg && tg->change)
435 /* Select the smallest mode that allows the desired resolution to be
436 * displayed. If desired, the x and y parameters can be rounded up to
437 * match the selected mode.
439 static struct w100_mode *w100fb_get_mode(struct w100fb_par *par, unsigned int *x, unsigned int *y, int saveval)
441 struct w100_mode *mode = NULL;
442 struct w100_mode *modelist = par->mach->modelist;
443 unsigned int best_x = 0xffffffff, best_y = 0xffffffff;
446 for (i = 0 ; i < par->mach->num_modes ; i++) {
447 if (modelist[i].xres >= *x && modelist[i].yres >= *y &&
448 modelist[i].xres < best_x && modelist[i].yres < best_y) {
449 best_x = modelist[i].xres;
450 best_y = modelist[i].yres;
452 } else if(modelist[i].xres >= *y && modelist[i].yres >= *x &&
453 modelist[i].xres < best_y && modelist[i].yres < best_x) {
454 best_x = modelist[i].yres;
455 best_y = modelist[i].xres;
460 if (mode && saveval) {
470 * w100fb_check_var():
471 * Get the video params out of 'var'. If a value doesn't fit, round it up,
472 * if it's too big, return -EINVAL.
474 static int w100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
476 struct w100fb_par *par=info->par;
478 if(!w100fb_get_mode(par, &var->xres, &var->yres, 1))
481 if (par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (par->mach->mem->size+1)))
484 if (!par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)))
487 var->xres_virtual = max(var->xres_virtual, var->xres);
488 var->yres_virtual = max(var->yres_virtual, var->yres);
490 if (var->bits_per_pixel > BITS_PER_PIXEL)
493 var->bits_per_pixel = BITS_PER_PIXEL;
495 var->red.offset = 11;
497 var->green.offset = 5;
498 var->green.length = 6;
499 var->blue.offset = 0;
500 var->blue.length = 5;
501 var->transp.offset = var->transp.length = 0;
506 var->vmode = FB_VMODE_NONINTERLACED;
508 var->pixclock = 0x04; /* 171521; */
516 * Set the user defined part of the display for the specified console
517 * by looking at the values in info.var
519 static int w100fb_set_par(struct fb_info *info)
521 struct w100fb_par *par=info->par;
523 if (par->xres != info->var.xres || par->yres != info->var.yres) {
524 par->xres = info->var.xres;
525 par->yres = info->var.yres;
526 par->mode = w100fb_get_mode(par, &par->xres, &par->yres, 0);
528 info->fix.visual = FB_VISUAL_TRUECOLOR;
529 info->fix.ypanstep = 0;
530 info->fix.ywrapstep = 0;
531 info->fix.line_length = par->xres * BITS_PER_PIXEL / 8;
533 mutex_lock(&info->mm_lock);
534 if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) {
535 par->extmem_active = 1;
536 info->fix.smem_len = par->mach->mem->size+1;
538 par->extmem_active = 0;
539 info->fix.smem_len = MEM_INT_SIZE+1;
541 mutex_unlock(&info->mm_lock);
543 w100fb_activate_var(par);
550 * Frame buffer operations
552 static const struct fb_ops w100fb_ops = {
553 .owner = THIS_MODULE,
554 .fb_check_var = w100fb_check_var,
555 .fb_set_par = w100fb_set_par,
556 .fb_setcolreg = w100fb_setcolreg,
557 .fb_blank = w100fb_blank,
558 .fb_fillrect = w100fb_fillrect,
559 .fb_copyarea = w100fb_copyarea,
560 .fb_imageblit = cfb_imageblit,
561 .fb_sync = w100fb_sync,
565 static void w100fb_save_vidmem(struct w100fb_par *par)
569 if (par->extmem_active) {
570 memsize=par->mach->mem->size;
571 par->saved_extmem = vmalloc(memsize);
572 if (par->saved_extmem)
573 memcpy_fromio(par->saved_extmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
575 memsize=MEM_INT_SIZE;
576 par->saved_intmem = vmalloc(memsize);
577 if (par->saved_intmem && par->extmem_active)
578 memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), memsize);
579 else if (par->saved_intmem)
580 memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize);
583 static void w100fb_restore_vidmem(struct w100fb_par *par)
587 if (par->extmem_active && par->saved_extmem) {
588 memsize=par->mach->mem->size;
589 memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_extmem, memsize);
590 vfree(par->saved_extmem);
591 par->saved_extmem = NULL;
593 if (par->saved_intmem) {
594 memsize=MEM_INT_SIZE;
595 if (par->extmem_active)
596 memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), par->saved_intmem, memsize);
598 memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_intmem, memsize);
599 vfree(par->saved_intmem);
600 par->saved_intmem = NULL;
604 static int w100fb_suspend(struct platform_device *dev, pm_message_t state)
606 struct fb_info *info = platform_get_drvdata(dev);
607 struct w100fb_par *par=info->par;
608 struct w100_tg_info *tg = par->mach->tg;
610 w100fb_save_vidmem(par);
611 if(tg && tg->suspend)
613 w100_suspend(W100_SUSPEND_ALL);
619 static int w100fb_resume(struct platform_device *dev)
621 struct fb_info *info = platform_get_drvdata(dev);
622 struct w100fb_par *par=info->par;
623 struct w100_tg_info *tg = par->mach->tg;
626 w100fb_activate_var(par);
627 w100fb_restore_vidmem(par);
635 #define w100fb_suspend NULL
636 #define w100fb_resume NULL
640 static int w100fb_probe(struct platform_device *pdev)
643 struct w100fb_mach_info *inf;
644 struct fb_info *info = NULL;
645 struct w100fb_par *par;
646 struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
647 unsigned int chip_id;
652 /* Remap the chip base address */
653 remapped_base = ioremap(mem->start+W100_CFG_BASE, W100_CFG_LEN);
654 if (remapped_base == NULL)
657 /* Map the register space */
658 remapped_regs = ioremap(mem->start+W100_REG_BASE, W100_REG_LEN);
659 if (remapped_regs == NULL)
662 /* Identify the chip */
664 chip_id = readl(remapped_regs + mmCHIP_ID);
666 case CHIP_ID_W100: printk("w100"); break;
667 case CHIP_ID_W3200: printk("w3200"); break;
668 case CHIP_ID_W3220: printk("w3220"); break;
670 printk("Unknown imageon chip ID\n");
674 printk(" at 0x%08lx.\n", (unsigned long) mem->start+W100_CFG_BASE);
676 /* Remap the framebuffer */
677 remapped_fbuf = ioremap(mem->start+MEM_WINDOW_BASE, MEM_WINDOW_SIZE);
678 if (remapped_fbuf == NULL)
681 info=framebuffer_alloc(sizeof(struct w100fb_par), &pdev->dev);
688 platform_set_drvdata(pdev, info);
690 inf = dev_get_platdata(&pdev->dev);
691 par->chip_id = chip_id;
693 par->fastpll_mode = 0;
696 par->pll_table=w100_get_xtal_table(inf->xtal_freq);
697 if (!par->pll_table) {
698 printk(KERN_ERR "No matching Xtal definition found\n");
703 info->pseudo_palette = kmalloc_array(MAX_PALETTES, sizeof(u32),
705 if (!info->pseudo_palette) {
710 info->fbops = &w100fb_ops;
711 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
712 FBINFO_HWACCEL_FILLRECT;
714 info->screen_base = remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE);
715 info->screen_size = REMAPPED_FB_LEN;
717 strcpy(info->fix.id, "w100fb");
718 info->fix.type = FB_TYPE_PACKED_PIXELS;
719 info->fix.type_aux = 0;
720 info->fix.accel = FB_ACCEL_NONE;
721 info->fix.smem_start = mem->start+W100_FB_BASE;
722 info->fix.mmio_start = mem->start+W100_REG_BASE;
723 info->fix.mmio_len = W100_REG_LEN;
725 if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
730 par->mode = &inf->modelist[0];
731 if(inf->init_mode & INIT_MODE_ROTATED) {
732 info->var.xres = par->mode->yres;
733 info->var.yres = par->mode->xres;
736 info->var.xres = par->mode->xres;
737 info->var.yres = par->mode->yres;
740 if(inf->init_mode &= INIT_MODE_FLIPPED)
745 info->var.xres_virtual = info->var.xres;
746 info->var.yres_virtual = info->var.yres;
747 info->var.pixclock = 0x04; /* 171521; */
749 info->var.grayscale = 0;
750 info->var.xoffset = info->var.yoffset = 0;
751 info->var.accel_flags = 0;
752 info->var.activate = FB_ACTIVATE_NOW;
756 if (w100fb_check_var(&info->var, info) < 0) {
761 if (register_framebuffer(info) < 0) {
766 fb_info(info, "%s frame buffer device\n", info->fix.id);
770 fb_dealloc_cmap(&info->cmap);
771 kfree(info->pseudo_palette);
773 if (remapped_fbuf != NULL) {
774 iounmap(remapped_fbuf);
775 remapped_fbuf = NULL;
777 if (remapped_regs != NULL) {
778 iounmap(remapped_regs);
779 remapped_regs = NULL;
781 if (remapped_base != NULL) {
782 iounmap(remapped_base);
783 remapped_base = NULL;
786 framebuffer_release(info);
791 static int w100fb_remove(struct platform_device *pdev)
793 struct fb_info *info = platform_get_drvdata(pdev);
794 struct w100fb_par *par=info->par;
796 unregister_framebuffer(info);
798 vfree(par->saved_intmem);
799 vfree(par->saved_extmem);
800 kfree(info->pseudo_palette);
801 fb_dealloc_cmap(&info->cmap);
803 iounmap(remapped_base);
804 remapped_base = NULL;
805 iounmap(remapped_regs);
806 remapped_regs = NULL;
807 iounmap(remapped_fbuf);
808 remapped_fbuf = NULL;
810 framebuffer_release(info);
816 /* ------------------- chipset specific functions -------------------------- */
819 static void w100_soft_reset(void)
821 u16 val = readw((u16 __iomem *)remapped_base + cfgSTATUS);
823 writew(val | 0x08, (u16 __iomem *)remapped_base + cfgSTATUS);
825 writew(0x00, (u16 __iomem *)remapped_base + cfgSTATUS);
829 static void w100_update_disable(void)
831 union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
833 /* Prevent display updates */
834 disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
835 disp_db_buf_wr_cntl.f.update_db_buf = 0;
836 disp_db_buf_wr_cntl.f.en_db_buf = 0;
837 writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
840 static void w100_update_enable(void)
842 union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
844 /* Enable display updates */
845 disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
846 disp_db_buf_wr_cntl.f.update_db_buf = 1;
847 disp_db_buf_wr_cntl.f.en_db_buf = 1;
848 writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
851 unsigned long w100fb_gpio_read(int port)
855 if (port==W100_GPIO_PORT_A)
856 value = readl(remapped_regs + mmGPIO_DATA);
858 value = readl(remapped_regs + mmGPIO_DATA2);
863 void w100fb_gpio_write(int port, unsigned long value)
865 if (port==W100_GPIO_PORT_A)
866 writel(value, remapped_regs + mmGPIO_DATA);
868 writel(value, remapped_regs + mmGPIO_DATA2);
870 EXPORT_SYMBOL(w100fb_gpio_read);
871 EXPORT_SYMBOL(w100fb_gpio_write);
874 * Initialization of critical w100 hardware
876 static void w100_hw_init(struct w100fb_par *par)
879 union cif_cntl_u cif_cntl;
880 union intf_cntl_u intf_cntl;
881 union cfgreg_base_u cfgreg_base;
882 union wrap_top_dir_u wrap_top_dir;
883 union cif_read_dbg_u cif_read_dbg;
884 union cpu_defaults_u cpu_default;
885 union cif_write_dbg_u cif_write_dbg;
886 union wrap_start_dir_u wrap_start_dir;
887 union cif_io_u cif_io;
888 struct w100_gpio_regs *gpio = par->mach->gpio;
892 /* This is what the fpga_init code does on reset. May be wrong
893 but there is little info available */
894 writel(0x31, remapped_regs + mmSCRATCH_UMSK);
895 for (temp32 = 0; temp32 < 10000; temp32++)
896 readl(remapped_regs + mmSCRATCH_UMSK);
897 writel(0x30, remapped_regs + mmSCRATCH_UMSK);
900 cif_io.val = defCIF_IO;
901 writel((u32)(cif_io.val), remapped_regs + mmCIF_IO);
903 cif_write_dbg.val = readl(remapped_regs + mmCIF_WRITE_DBG);
904 cif_write_dbg.f.dis_packer_ful_during_rbbm_timeout = 0;
905 cif_write_dbg.f.en_dword_split_to_rbbm = 1;
906 cif_write_dbg.f.dis_timeout_during_rbbm = 1;
907 writel((u32) (cif_write_dbg.val), remapped_regs + mmCIF_WRITE_DBG);
909 cif_read_dbg.val = readl(remapped_regs + mmCIF_READ_DBG);
910 cif_read_dbg.f.dis_rd_same_byte_to_trig_fetch = 1;
911 writel((u32) (cif_read_dbg.val), remapped_regs + mmCIF_READ_DBG);
913 cif_cntl.val = readl(remapped_regs + mmCIF_CNTL);
914 cif_cntl.f.dis_system_bits = 1;
915 cif_cntl.f.dis_mr = 1;
916 cif_cntl.f.en_wait_to_compensate_dq_prop_dly = 0;
917 cif_cntl.f.intb_oe = 1;
918 cif_cntl.f.interrupt_active_high = 1;
919 writel((u32) (cif_cntl.val), remapped_regs + mmCIF_CNTL);
921 /* Setup cfgINTF_CNTL and cfgCPU defaults */
922 intf_cntl.val = defINTF_CNTL;
923 intf_cntl.f.ad_inc_a = 1;
924 intf_cntl.f.ad_inc_b = 1;
925 intf_cntl.f.rd_data_rdy_a = 0;
926 intf_cntl.f.rd_data_rdy_b = 0;
927 writeb((u8) (intf_cntl.val), remapped_base + cfgINTF_CNTL);
929 cpu_default.val = defCPU_DEFAULTS;
930 cpu_default.f.access_ind_addr_a = 1;
931 cpu_default.f.access_ind_addr_b = 1;
932 cpu_default.f.access_scratch_reg = 1;
933 cpu_default.f.transition_size = 0;
934 writeb((u8) (cpu_default.val), remapped_base + cfgCPU_DEFAULTS);
936 /* set up the apertures */
937 writeb((u8) (W100_REG_BASE >> 16), remapped_base + cfgREG_BASE);
939 cfgreg_base.val = defCFGREG_BASE;
940 cfgreg_base.f.cfgreg_base = W100_CFG_BASE;
941 writel((u32) (cfgreg_base.val), remapped_regs + mmCFGREG_BASE);
943 wrap_start_dir.val = defWRAP_START_DIR;
944 wrap_start_dir.f.start_addr = WRAP_BUF_BASE_VALUE >> 1;
945 writel((u32) (wrap_start_dir.val), remapped_regs + mmWRAP_START_DIR);
947 wrap_top_dir.val = defWRAP_TOP_DIR;
948 wrap_top_dir.f.top_addr = WRAP_BUF_TOP_VALUE >> 1;
949 writel((u32) (wrap_top_dir.val), remapped_regs + mmWRAP_TOP_DIR);
951 writel((u32) 0x2440, remapped_regs + mmRBBM_CNTL);
953 /* Set the hardware to 565 colour */
954 temp32 = readl(remapped_regs + mmDISP_DEBUG2);
955 temp32 &= 0xff7fffff;
956 temp32 |= 0x00800000;
957 writel(temp32, remapped_regs + mmDISP_DEBUG2);
959 /* Initialise the GPIO lines */
961 writel(gpio->init_data1, remapped_regs + mmGPIO_DATA);
962 writel(gpio->init_data2, remapped_regs + mmGPIO_DATA2);
963 writel(gpio->gpio_dir1, remapped_regs + mmGPIO_CNTL1);
964 writel(gpio->gpio_oe1, remapped_regs + mmGPIO_CNTL2);
965 writel(gpio->gpio_dir2, remapped_regs + mmGPIO_CNTL3);
966 writel(gpio->gpio_oe2, remapped_regs + mmGPIO_CNTL4);
972 union clk_pin_cntl_u clk_pin_cntl;
973 union pll_ref_fb_div_u pll_ref_fb_div;
974 union pll_cntl_u pll_cntl;
975 union sclk_cntl_u sclk_cntl;
976 union pclk_cntl_u pclk_cntl;
977 union pwrmgt_cntl_u pwrmgt_cntl;
978 int auto_mode; /* system clock auto changing? */
982 static struct power_state w100_pwr_state;
984 /* The PLL Fout is determined by (XtalFreq/(M+1)) * ((N_int+1) + (N_fac/8)) */
986 /* 12.5MHz Crystal PLL Table */
987 static struct w100_pll_info xtal_12500000[] = {
988 /*freq M N_int N_fac tfgoal lock_time */
989 { 50, 0, 1, 0, 0xe0, 56}, /* 50.00 MHz */
990 { 75, 0, 5, 0, 0xde, 37}, /* 75.00 MHz */
991 {100, 0, 7, 0, 0xe0, 28}, /* 100.00 MHz */
992 {125, 0, 9, 0, 0xe0, 22}, /* 125.00 MHz */
993 {150, 0, 11, 0, 0xe0, 17}, /* 150.00 MHz */
994 { 0, 0, 0, 0, 0, 0}, /* Terminator */
997 /* 14.318MHz Crystal PLL Table */
998 static struct w100_pll_info xtal_14318000[] = {
999 /*freq M N_int N_fac tfgoal lock_time */
1000 { 40, 4, 13, 0, 0xe0, 80}, /* tfgoal guessed */
1001 { 50, 1, 6, 0, 0xe0, 64}, /* 50.05 MHz */
1002 { 57, 2, 11, 0, 0xe0, 53}, /* tfgoal guessed */
1003 { 75, 0, 4, 3, 0xe0, 43}, /* 75.08 MHz */
1004 {100, 0, 6, 0, 0xe0, 32}, /* 100.10 MHz */
1005 { 0, 0, 0, 0, 0, 0},
1008 /* 16MHz Crystal PLL Table */
1009 static struct w100_pll_info xtal_16000000[] = {
1010 /*freq M N_int N_fac tfgoal lock_time */
1011 { 72, 1, 8, 0, 0xe0, 48}, /* tfgoal guessed */
1012 { 80, 1, 9, 0, 0xe0, 13}, /* tfgoal guessed */
1013 { 95, 1, 10, 7, 0xe0, 38}, /* tfgoal guessed */
1014 { 96, 1, 11, 0, 0xe0, 36}, /* tfgoal guessed */
1015 { 0, 0, 0, 0, 0, 0},
1018 static struct pll_entries {
1020 struct w100_pll_info *pll_table;
1021 } w100_pll_tables[] = {
1022 { 12500000, &xtal_12500000[0] },
1023 { 14318000, &xtal_14318000[0] },
1024 { 16000000, &xtal_16000000[0] },
1028 struct w100_pll_info *w100_get_xtal_table(unsigned int freq)
1030 struct pll_entries *pll_entry = w100_pll_tables;
1033 if (freq == pll_entry->xtal_freq)
1034 return pll_entry->pll_table;
1036 } while (pll_entry->xtal_freq);
1042 static unsigned int w100_get_testcount(unsigned int testclk_sel)
1044 union clk_test_cntl_u clk_test_cntl;
1048 /* Select the test clock source and reset */
1049 clk_test_cntl.f.start_check_freq = 0x0;
1050 clk_test_cntl.f.testclk_sel = testclk_sel;
1051 clk_test_cntl.f.tstcount_rst = 0x1; /* set reset */
1052 writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1054 clk_test_cntl.f.tstcount_rst = 0x0; /* clear reset */
1055 writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1057 /* Run clock test */
1058 clk_test_cntl.f.start_check_freq = 0x1;
1059 writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1061 /* Give the test time to complete */
1064 /* Return the result */
1065 clk_test_cntl.val = readl(remapped_regs + mmCLK_TEST_CNTL);
1066 clk_test_cntl.f.start_check_freq = 0x0;
1067 writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL);
1069 return clk_test_cntl.f.test_count;
1073 static int w100_pll_adjust(struct w100_pll_info *pll)
1078 /* Initial Settings */
1079 w100_pwr_state.pll_cntl.f.pll_pwdn = 0x0; /* power down */
1080 w100_pwr_state.pll_cntl.f.pll_reset = 0x0; /* not reset */
1081 w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x1; /* Hi-Z */
1082 w100_pwr_state.pll_cntl.f.pll_pvg = 0x0; /* VCO gain = 0 */
1083 w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0; /* VCO frequency range control = off */
1084 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; /* current offset inside VCO = 0 */
1085 w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
1087 /* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V
1088 * therefore, commented out the following lines
1092 /* set VCO input = 0.8 * VDD */
1093 w100_pwr_state.pll_cntl.f.pll_dactal = 0xd;
1094 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1096 tf80 = w100_get_testcount(TESTCLK_SRC_PLL);
1097 if (tf80 >= (pll->tfgoal)) {
1098 /* set VCO input = 0.2 * VDD */
1099 w100_pwr_state.pll_cntl.f.pll_dactal = 0x7;
1100 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1102 tf20 = w100_get_testcount(TESTCLK_SRC_PLL);
1103 if (tf20 <= (pll->tfgoal))
1104 return 1; /* Success */
1106 if ((w100_pwr_state.pll_cntl.f.pll_vcofr == 0x0) &&
1107 ((w100_pwr_state.pll_cntl.f.pll_pvg == 0x7) ||
1108 (w100_pwr_state.pll_cntl.f.pll_ioffset == 0x0))) {
1109 /* slow VCO config */
1110 w100_pwr_state.pll_cntl.f.pll_vcofr = 0x1;
1111 w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
1112 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1116 if ((w100_pwr_state.pll_cntl.f.pll_ioffset) < 0x3) {
1117 w100_pwr_state.pll_cntl.f.pll_ioffset += 0x1;
1118 } else if ((w100_pwr_state.pll_cntl.f.pll_pvg) < 0x7) {
1119 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1120 w100_pwr_state.pll_cntl.f.pll_pvg += 0x1;
1122 return 0; /* Error */
1129 * w100_pll_calibration
1131 static int w100_pll_calibration(struct w100_pll_info *pll)
1135 status = w100_pll_adjust(pll);
1137 /* PLL Reset And Lock */
1138 /* set VCO input = 0.5 * VDD */
1139 w100_pwr_state.pll_cntl.f.pll_dactal = 0xa;
1140 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1142 udelay(1); /* reset time */
1144 /* enable charge pump */
1145 w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0; /* normal */
1146 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1148 /* set VCO input = Hi-Z, disable DAC */
1149 w100_pwr_state.pll_cntl.f.pll_dactal = 0x0;
1150 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1152 udelay(400); /* lock time */
1160 static int w100_pll_set_clk(struct w100_pll_info *pll)
1164 if (w100_pwr_state.auto_mode == 1) /* auto mode */
1166 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0; /* disable fast to normal */
1167 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0; /* disable normal to fast */
1168 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1171 /* Set system clock source to XTAL whilst adjusting the PLL! */
1172 w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
1173 writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1175 w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = pll->M;
1176 w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = pll->N_int;
1177 w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = pll->N_fac;
1178 w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = pll->lock_time;
1179 writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
1181 w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0;
1182 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1184 status = w100_pll_calibration(pll);
1186 if (w100_pwr_state.auto_mode == 1) /* auto mode */
1188 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x1; /* reenable fast to normal */
1189 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x1; /* reenable normal to fast */
1190 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1195 /* freq = target frequency of the PLL */
1196 static int w100_set_pll_freq(struct w100fb_par *par, unsigned int freq)
1198 struct w100_pll_info *pll = par->pll_table;
1201 if (freq == pll->freq) {
1202 return w100_pll_set_clk(pll);
1209 /* Set up an initial state. Some values/fields set
1210 here will be overwritten. */
1211 static void w100_pwm_setup(struct w100fb_par *par)
1213 w100_pwr_state.clk_pin_cntl.f.osc_en = 0x1;
1214 w100_pwr_state.clk_pin_cntl.f.osc_gain = 0x1f;
1215 w100_pwr_state.clk_pin_cntl.f.dont_use_xtalin = 0x0;
1216 w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x0;
1217 w100_pwr_state.clk_pin_cntl.f.xtalin_dbl_en = par->mach->xtal_dbl ? 1 : 0;
1218 w100_pwr_state.clk_pin_cntl.f.cg_debug = 0x0;
1219 writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL);
1221 w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL;
1222 w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = 0x0; /* Pfast = 1 */
1223 w100_pwr_state.sclk_cntl.f.sclk_clkon_hys = 0x3;
1224 w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0; /* Pslow = 1 */
1225 w100_pwr_state.sclk_cntl.f.disp_cg_ok2switch_en = 0x0;
1226 w100_pwr_state.sclk_cntl.f.sclk_force_reg = 0x0; /* Dynamic */
1227 w100_pwr_state.sclk_cntl.f.sclk_force_disp = 0x0; /* Dynamic */
1228 w100_pwr_state.sclk_cntl.f.sclk_force_mc = 0x0; /* Dynamic */
1229 w100_pwr_state.sclk_cntl.f.sclk_force_extmc = 0x0; /* Dynamic */
1230 w100_pwr_state.sclk_cntl.f.sclk_force_cp = 0x0; /* Dynamic */
1231 w100_pwr_state.sclk_cntl.f.sclk_force_e2 = 0x0; /* Dynamic */
1232 w100_pwr_state.sclk_cntl.f.sclk_force_e3 = 0x0; /* Dynamic */
1233 w100_pwr_state.sclk_cntl.f.sclk_force_idct = 0x0; /* Dynamic */
1234 w100_pwr_state.sclk_cntl.f.sclk_force_bist = 0x0; /* Dynamic */
1235 w100_pwr_state.sclk_cntl.f.busy_extend_cp = 0x0;
1236 w100_pwr_state.sclk_cntl.f.busy_extend_e2 = 0x0;
1237 w100_pwr_state.sclk_cntl.f.busy_extend_e3 = 0x0;
1238 w100_pwr_state.sclk_cntl.f.busy_extend_idct = 0x0;
1239 writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1241 w100_pwr_state.pclk_cntl.f.pclk_src_sel = CLK_SRC_XTAL;
1242 w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1; /* P = 2 */
1243 w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0; /* Dynamic */
1244 writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
1246 w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0; /* M = 1 */
1247 w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0; /* N = 1.0 */
1248 w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = 0x0;
1249 w100_pwr_state.pll_ref_fb_div.f.pll_reset_time = 0x5;
1250 w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = 0xff;
1251 writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV);
1253 w100_pwr_state.pll_cntl.f.pll_pwdn = 0x1;
1254 w100_pwr_state.pll_cntl.f.pll_reset = 0x1;
1255 w100_pwr_state.pll_cntl.f.pll_pm_en = 0x0;
1256 w100_pwr_state.pll_cntl.f.pll_mode = 0x0; /* uses VCO clock */
1257 w100_pwr_state.pll_cntl.f.pll_refclk_sel = 0x0;
1258 w100_pwr_state.pll_cntl.f.pll_fbclk_sel = 0x0;
1259 w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0;
1260 w100_pwr_state.pll_cntl.f.pll_pcp = 0x4;
1261 w100_pwr_state.pll_cntl.f.pll_pvg = 0x0;
1262 w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0;
1263 w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0;
1264 w100_pwr_state.pll_cntl.f.pll_pecc_mode = 0x0;
1265 w100_pwr_state.pll_cntl.f.pll_pecc_scon = 0x0;
1266 w100_pwr_state.pll_cntl.f.pll_dactal = 0x0; /* Hi-Z */
1267 w100_pwr_state.pll_cntl.f.pll_cp_clip = 0x3;
1268 w100_pwr_state.pll_cntl.f.pll_conf = 0x2;
1269 w100_pwr_state.pll_cntl.f.pll_mbctrl = 0x2;
1270 w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0;
1271 writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL);
1273 w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x0;
1274 w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1; /* normal mode (0, 1, 3) */
1275 w100_pwr_state.pwrmgt_cntl.f.pwm_wakeup_cond = 0x0;
1276 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0;
1277 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0;
1278 w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1; /* PM4,ENG */
1279 w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1; /* PM4,ENG */
1280 w100_pwr_state.pwrmgt_cntl.f.pwm_idle_timer = 0xFF;
1281 w100_pwr_state.pwrmgt_cntl.f.pwm_busy_timer = 0xFF;
1282 writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL);
1284 w100_pwr_state.auto_mode = 0; /* manual mode */
1289 * Setup the w100 clocks for the specified mode
1291 static void w100_init_clocks(struct w100fb_par *par)
1293 struct w100_mode *mode = par->mode;
1295 if (mode->pixclk_src == CLK_SRC_PLL || mode->sysclk_src == CLK_SRC_PLL)
1296 w100_set_pll_freq(par, (par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq);
1298 w100_pwr_state.sclk_cntl.f.sclk_src_sel = mode->sysclk_src;
1299 w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = mode->sysclk_divider;
1300 w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = mode->sysclk_divider;
1301 writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);
1304 static void w100_init_lcd(struct w100fb_par *par)
1307 struct w100_mode *mode = par->mode;
1308 struct w100_gen_regs *regs = par->mach->regs;
1309 union active_h_disp_u active_h_disp;
1310 union active_v_disp_u active_v_disp;
1311 union graphic_h_disp_u graphic_h_disp;
1312 union graphic_v_disp_u graphic_v_disp;
1313 union crtc_total_u crtc_total;
1315 /* w3200 doesn't like undefined bits being set so zero register values first */
1317 active_h_disp.val = 0;
1318 active_h_disp.f.active_h_start=mode->left_margin;
1319 active_h_disp.f.active_h_end=mode->left_margin + mode->xres;
1320 writel(active_h_disp.val, remapped_regs + mmACTIVE_H_DISP);
1322 active_v_disp.val = 0;
1323 active_v_disp.f.active_v_start=mode->upper_margin;
1324 active_v_disp.f.active_v_end=mode->upper_margin + mode->yres;
1325 writel(active_v_disp.val, remapped_regs + mmACTIVE_V_DISP);
1327 graphic_h_disp.val = 0;
1328 graphic_h_disp.f.graphic_h_start=mode->left_margin;
1329 graphic_h_disp.f.graphic_h_end=mode->left_margin + mode->xres;
1330 writel(graphic_h_disp.val, remapped_regs + mmGRAPHIC_H_DISP);
1332 graphic_v_disp.val = 0;
1333 graphic_v_disp.f.graphic_v_start=mode->upper_margin;
1334 graphic_v_disp.f.graphic_v_end=mode->upper_margin + mode->yres;
1335 writel(graphic_v_disp.val, remapped_regs + mmGRAPHIC_V_DISP);
1338 crtc_total.f.crtc_h_total=mode->left_margin + mode->xres + mode->right_margin;
1339 crtc_total.f.crtc_v_total=mode->upper_margin + mode->yres + mode->lower_margin;
1340 writel(crtc_total.val, remapped_regs + mmCRTC_TOTAL);
1342 writel(mode->crtc_ss, remapped_regs + mmCRTC_SS);
1343 writel(mode->crtc_ls, remapped_regs + mmCRTC_LS);
1344 writel(mode->crtc_gs, remapped_regs + mmCRTC_GS);
1345 writel(mode->crtc_vpos_gs, remapped_regs + mmCRTC_VPOS_GS);
1346 writel(mode->crtc_rev, remapped_regs + mmCRTC_REV);
1347 writel(mode->crtc_dclk, remapped_regs + mmCRTC_DCLK);
1348 writel(mode->crtc_gclk, remapped_regs + mmCRTC_GCLK);
1349 writel(mode->crtc_goe, remapped_regs + mmCRTC_GOE);
1350 writel(mode->crtc_ps1_active, remapped_regs + mmCRTC_PS1_ACTIVE);
1352 writel(regs->lcd_format, remapped_regs + mmLCD_FORMAT);
1353 writel(regs->lcdd_cntl1, remapped_regs + mmLCDD_CNTL1);
1354 writel(regs->lcdd_cntl2, remapped_regs + mmLCDD_CNTL2);
1355 writel(regs->genlcd_cntl1, remapped_regs + mmGENLCD_CNTL1);
1356 writel(regs->genlcd_cntl2, remapped_regs + mmGENLCD_CNTL2);
1357 writel(regs->genlcd_cntl3, remapped_regs + mmGENLCD_CNTL3);
1359 writel(0x00000000, remapped_regs + mmCRTC_FRAME);
1360 writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS);
1361 writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT);
1362 writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR);
1364 /* Hack for overlay in ext memory */
1365 temp32 = readl(remapped_regs + mmDISP_DEBUG2);
1366 temp32 |= 0xc0000000;
1367 writel(temp32, remapped_regs + mmDISP_DEBUG2);
1371 static void w100_setup_memory(struct w100fb_par *par)
1373 union mc_ext_mem_location_u extmem_location;
1374 union mc_fb_location_u intmem_location;
1375 struct w100_mem_info *mem = par->mach->mem;
1376 struct w100_bm_mem_info *bm_mem = par->mach->bm_mem;
1378 if (!par->extmem_active) {
1379 w100_suspend(W100_SUSPEND_EXTMEM);
1381 /* Map Internal Memory at FB Base */
1382 intmem_location.f.mc_fb_start = W100_FB_BASE >> 8;
1383 intmem_location.f.mc_fb_top = (W100_FB_BASE+MEM_INT_SIZE) >> 8;
1384 writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
1386 /* Unmap External Memory - value is *probably* irrelevant but may have meaning
1387 to acceleration libraries */
1388 extmem_location.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8;
1389 extmem_location.f.mc_ext_mem_top = (MEM_EXT_BASE_VALUE-1) >> 8;
1390 writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
1392 /* Map Internal Memory to its default location */
1393 intmem_location.f.mc_fb_start = MEM_INT_BASE_VALUE >> 8;
1394 intmem_location.f.mc_fb_top = (MEM_INT_BASE_VALUE+MEM_INT_SIZE) >> 8;
1395 writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION);
1397 /* Map External Memory at FB Base */
1398 extmem_location.f.mc_ext_mem_start = W100_FB_BASE >> 8;
1399 extmem_location.f.mc_ext_mem_top = (W100_FB_BASE+par->mach->mem->size) >> 8;
1400 writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION);
1402 writel(0x00007800, remapped_regs + mmMC_BIST_CTRL);
1403 writel(mem->ext_cntl, remapped_regs + mmMEM_EXT_CNTL);
1404 writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
1406 writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
1408 writel(mem->sdram_mode_reg, remapped_regs + mmMEM_SDRAM_MODE_REG);
1410 writel(mem->ext_timing_cntl, remapped_regs + mmMEM_EXT_TIMING_CNTL);
1411 writel(mem->io_cntl, remapped_regs + mmMEM_IO_CNTL);
1413 writel(bm_mem->ext_mem_bw, remapped_regs + mmBM_EXT_MEM_BANDWIDTH);
1414 writel(bm_mem->offset, remapped_regs + mmBM_OFFSET);
1415 writel(bm_mem->ext_timing_ctl, remapped_regs + mmBM_MEM_EXT_TIMING_CNTL);
1416 writel(bm_mem->ext_cntl, remapped_regs + mmBM_MEM_EXT_CNTL);
1417 writel(bm_mem->mode_reg, remapped_regs + mmBM_MEM_MODE_REG);
1418 writel(bm_mem->io_cntl, remapped_regs + mmBM_MEM_IO_CNTL);
1419 writel(bm_mem->config, remapped_regs + mmBM_CONFIG);
1424 static void w100_set_dispregs(struct w100fb_par *par)
1426 unsigned long rot=0, divider, offset=0;
1427 union graphic_ctrl_u graphic_ctrl;
1429 /* See if the mode has been rotated */
1430 if (par->xres == par->mode->xres) {
1432 rot=3; /* 180 degree */
1433 offset=(par->xres * par->yres) - 1;
1434 } /* else 0 degree */
1435 divider = par->mode->pixclk_divider;
1438 rot=2; /* 270 degree */
1439 offset=par->xres - 1;
1441 rot=1; /* 90 degree */
1442 offset=par->xres * (par->yres - 1);
1444 divider = par->mode->pixclk_divider_rotated;
1447 graphic_ctrl.val = 0; /* w32xx doesn't like undefined bits */
1448 switch (par->chip_id) {
1450 graphic_ctrl.f_w100.color_depth=6;
1451 graphic_ctrl.f_w100.en_crtc=1;
1452 graphic_ctrl.f_w100.en_graphic_req=1;
1453 graphic_ctrl.f_w100.en_graphic_crtc=1;
1454 graphic_ctrl.f_w100.lcd_pclk_on=1;
1455 graphic_ctrl.f_w100.lcd_sclk_on=1;
1456 graphic_ctrl.f_w100.low_power_on=0;
1457 graphic_ctrl.f_w100.req_freq=0;
1458 graphic_ctrl.f_w100.portrait_mode=rot;
1460 /* Zaurus needs this */
1465 graphic_ctrl.f_w100.total_req_graphic=0xa0;
1472 graphic_ctrl.f_w100.low_power_on=1;
1473 graphic_ctrl.f_w100.req_freq=5;
1477 graphic_ctrl.f_w100.req_freq=4;
1482 graphic_ctrl.f_w100.total_req_graphic=0xf0;
1488 graphic_ctrl.f_w32xx.color_depth=6;
1489 graphic_ctrl.f_w32xx.en_crtc=1;
1490 graphic_ctrl.f_w32xx.en_graphic_req=1;
1491 graphic_ctrl.f_w32xx.en_graphic_crtc=1;
1492 graphic_ctrl.f_w32xx.lcd_pclk_on=1;
1493 graphic_ctrl.f_w32xx.lcd_sclk_on=1;
1494 graphic_ctrl.f_w32xx.low_power_on=0;
1495 graphic_ctrl.f_w32xx.req_freq=0;
1496 graphic_ctrl.f_w32xx.total_req_graphic=par->mode->xres >> 1; /* panel xres, not mode */
1497 graphic_ctrl.f_w32xx.portrait_mode=rot;
1501 /* Set the pixel clock source and divider */
1502 w100_pwr_state.pclk_cntl.f.pclk_src_sel = par->mode->pixclk_src;
1503 w100_pwr_state.pclk_cntl.f.pclk_post_div = divider;
1504 writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL);
1506 writel(graphic_ctrl.val, remapped_regs + mmGRAPHIC_CTRL);
1507 writel(W100_FB_BASE + ((offset * BITS_PER_PIXEL/8)&~0x03UL), remapped_regs + mmGRAPHIC_OFFSET);
1508 writel((par->xres*BITS_PER_PIXEL/8), remapped_regs + mmGRAPHIC_PITCH);
1513 * Work out how long the sync pulse lasts
1514 * Value is 1/(time in seconds)
1516 static void calc_hsync(struct w100fb_par *par)
1518 unsigned long hsync;
1519 struct w100_mode *mode = par->mode;
1520 union crtc_ss_u crtc_ss;
1522 if (mode->pixclk_src == CLK_SRC_XTAL)
1523 hsync=par->mach->xtal_freq;
1525 hsync=((par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq)*100000;
1527 hsync /= (w100_pwr_state.pclk_cntl.f.pclk_post_div + 1);
1529 crtc_ss.val = readl(remapped_regs + mmCRTC_SS);
1531 par->hsync_len = hsync / (crtc_ss.f.ss_end-crtc_ss.f.ss_start);
1536 static void w100_suspend(u32 mode)
1540 writel(0x7FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION);
1541 writel(0x00FF0000, remapped_regs + mmMC_PERF_MON_CNTL);
1543 val = readl(remapped_regs + mmMEM_EXT_TIMING_CNTL);
1544 val &= ~(0x00100000); /* bit20=0 */
1545 val |= 0xFF000000; /* bit31:24=0xff */
1546 writel(val, remapped_regs + mmMEM_EXT_TIMING_CNTL);
1548 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1549 val &= ~(0x00040000); /* bit18=0 */
1550 val |= 0x00080000; /* bit19=1 */
1551 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1553 udelay(1); /* wait 1us */
1555 if (mode == W100_SUSPEND_EXTMEM) {
1556 /* CKE: Tri-State */
1557 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1558 val |= 0x40000000; /* bit30=1 */
1559 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1562 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1563 val &= ~(0x00000001); /* bit0=0 */
1564 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1566 writel(0x00000000, remapped_regs + mmSCLK_CNTL);
1567 writel(0x000000BF, remapped_regs + mmCLK_PIN_CNTL);
1568 writel(0x00000015, remapped_regs + mmPWRMGT_CNTL);
1572 val = readl(remapped_regs + mmPLL_CNTL);
1573 val |= 0x00000004; /* bit2=1 */
1574 writel(val, remapped_regs + mmPLL_CNTL);
1576 writel(0x00000000, remapped_regs + mmLCDD_CNTL1);
1577 writel(0x00000000, remapped_regs + mmLCDD_CNTL2);
1578 writel(0x00000000, remapped_regs + mmGENLCD_CNTL1);
1579 writel(0x00000000, remapped_regs + mmGENLCD_CNTL2);
1580 writel(0x00000000, remapped_regs + mmGENLCD_CNTL3);
1582 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1584 val &= ~(0x00000001);
1585 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1587 writel(0x0000001d, remapped_regs + mmPWRMGT_CNTL);
1591 static void w100_vsync(void)
1594 int timeout = 30000; /* VSync timeout = 30[ms] > 16.8[ms] */
1596 tmp = readl(remapped_regs + mmACTIVE_V_DISP);
1599 writel((tmp >> 16) & 0x3ff, remapped_regs + mmDISP_INT_CNTL);
1601 /* disable vline irq */
1602 tmp = readl(remapped_regs + mmGEN_INT_CNTL);
1605 writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1607 /* clear vline irq status */
1608 writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1610 /* enable vline irq */
1611 writel((tmp | 0x00000002), remapped_regs + mmGEN_INT_CNTL);
1613 /* clear vline irq status */
1614 writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1616 while(timeout > 0) {
1617 if (readl(remapped_regs + mmGEN_INT_STATUS) & 0x00000002)
1623 /* disable vline irq */
1624 writel(tmp, remapped_regs + mmGEN_INT_CNTL);
1626 /* clear vline irq status */
1627 writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);
1630 static struct platform_driver w100fb_driver = {
1631 .probe = w100fb_probe,
1632 .remove = w100fb_remove,
1633 .suspend = w100fb_suspend,
1634 .resume = w100fb_resume,
1637 .dev_groups = w100fb_groups,
1641 module_platform_driver(w100fb_driver);
1643 MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
1644 MODULE_LICENSE("GPL");