Merge tag 'trace-v5.11-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
[linux/fpc-iii.git] / drivers / video / fbdev / w100fb.c
blobd96ab28f8ce4ae54b384c3a4d8f2b9bfa085187e
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
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>
24 #include <linux/fb.h>
25 #include <linux/init.h>
26 #include <linux/kernel.h>
27 #include <linux/mm.h>
28 #include <linux/platform_device.h>
29 #include <linux/slab.h>
30 #include <linux/string.h>
31 #include <linux/vmalloc.h>
32 #include <linux/module.h>
33 #include <asm/io.h>
34 #include <linux/uaccess.h>
35 #include <video/w100fb.h>
36 #include "w100fb.h"
39 * Prototypes
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
77 * Sysfs functions
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)
89 unsigned int flip;
90 struct fb_info *info = dev_get_drvdata(dev);
91 struct w100fb_par *par=info->par;
93 flip = simple_strtoul(buf, NULL, 10);
95 if (flip > 0)
96 par->flip = 1;
97 else
98 par->flip = 0;
100 w100_update_disable();
101 w100_set_dispregs(par);
102 w100_update_enable();
104 calc_hsync(par);
106 return count;
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);
117 return count;
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", &regs, &param);
127 if (regs <= 0x2000) {
128 printk("Write Register 0x%08lX: 0x%08lX\n", regs, param);
129 writel(param, remapped_regs + regs);
132 return count;
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) {
152 par->fastpll_mode=1;
153 printk("w100fb: Using fast system clock (if possible)\n");
154 } else {
155 par->fastpll_mode=0;
156 printk("w100fb: Using normal system clock\n");
159 w100_init_clocks(par);
160 calc_hsync(par);
162 return count;
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,
171 &dev_attr_flip.attr,
172 NULL,
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 */
186 if (par->blanked)
187 return 0;
188 else
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)
205 unsigned int val;
206 int ret = 1;
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);
223 pal[regno] = val;
224 ret = 0;
226 return ret;
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;
238 switch(blank_mode) {
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)
246 tg->suspend(par);
247 par->blanked = 1;
249 break;
251 case FB_BLANK_UNBLANK: /* Unblanking */
252 if (par->blanked != 0) {
253 if(tg && tg->resume)
254 tg->resume(par);
255 par->blanked = 0;
257 break;
259 return 0;
263 static void w100_fifo_wait(int entries)
265 union rbbm_status_u status;
266 int i;
268 for (i = 0; i < 2000000; i++) {
269 status.val = readl(remapped_regs + mmRBBM_STATUS);
270 if (status.f.cmdfifo_avail >= entries)
271 return;
272 udelay(1);
274 printk(KERN_ERR "w100fb: FIFO Timeout!\n");
278 static int w100fb_sync(struct fb_info *info)
280 union rbbm_status_u status;
281 int i;
283 for (i = 0; i < 2000000; i++) {
284 status.val = readl(remapped_regs + mmRBBM_STATUS);
285 if (!status.f.gui_active)
286 return 0;
287 udelay(1);
289 printk(KERN_ERR "w100fb: Graphic engine timeout!\n");
290 return -EBUSY;
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;
301 w100_fifo_wait(4);
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);
307 w100_fifo_wait(3);
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);
312 w100_fifo_wait(4);
313 dp_cntl.val = 0;
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);
322 gmc.val = 0;
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)
362 return;
363 if (info->flags & FBINFO_HWACCEL_DISABLED) {
364 cfb_fillrect(info, rect);
365 return;
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;
371 w100_fifo_wait(2);
372 writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
373 writel(rect->color, remapped_regs + mmDP_BRUSH_FRGD_CLR);
375 w100_fifo_wait(2);
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)
390 return;
391 if (info->flags & FBINFO_HWACCEL_DISABLED) {
392 cfb_copyarea(info, area);
393 return;
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;
399 w100_fifo_wait(1);
400 writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL);
402 w100_fifo_wait(3);
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;
416 w100_pwm_setup(par);
417 w100_setup_memory(par);
418 w100_init_clocks(par);
419 w100fb_clear_screen(par);
420 w100_vsync();
422 w100_update_disable();
423 w100_init_lcd(par);
424 w100_set_dispregs(par);
425 w100_update_enable();
426 w100_init_graphic_engine(par);
428 calc_hsync(par);
430 if (!par->blanked && tg && tg->change)
431 tg->change(par);
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;
444 unsigned int i;
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;
451 mode = &modelist[i];
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;
456 mode = &modelist[i];
460 if (mode && saveval) {
461 *x = best_x;
462 *y = best_y;
465 return mode;
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))
479 return -EINVAL;
481 if (par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (par->mach->mem->size+1)))
482 return -EINVAL;
484 if (!par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)))
485 return -EINVAL;
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)
491 return -EINVAL;
492 else
493 var->bits_per_pixel = BITS_PER_PIXEL;
495 var->red.offset = 11;
496 var->red.length = 5;
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;
503 var->nonstd = 0;
504 var->height = -1;
505 var->width = -1;
506 var->vmode = FB_VMODE_NONINTERLACED;
507 var->sync = 0;
508 var->pixclock = 0x04; /* 171521; */
510 return 0;
515 * w100fb_set_par():
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;
537 } else {
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);
545 return 0;
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,
564 #ifdef CONFIG_PM
565 static void w100fb_save_vidmem(struct w100fb_par *par)
567 int memsize;
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)
585 int memsize;
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);
597 else
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)
612 tg->suspend(par);
613 w100_suspend(W100_SUSPEND_ALL);
614 par->blanked = 1;
616 return 0;
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;
625 w100_hw_init(par);
626 w100fb_activate_var(par);
627 w100fb_restore_vidmem(par);
628 if(tg && tg->resume)
629 tg->resume(par);
630 par->blanked = 0;
632 return 0;
634 #else
635 #define w100fb_suspend NULL
636 #define w100fb_resume NULL
637 #endif
640 static int w100fb_probe(struct platform_device *pdev)
642 int err = -EIO;
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;
649 if (!mem)
650 return -EINVAL;
652 /* Remap the chip base address */
653 remapped_base = ioremap(mem->start+W100_CFG_BASE, W100_CFG_LEN);
654 if (remapped_base == NULL)
655 goto out;
657 /* Map the register space */
658 remapped_regs = ioremap(mem->start+W100_REG_BASE, W100_REG_LEN);
659 if (remapped_regs == NULL)
660 goto out;
662 /* Identify the chip */
663 printk("Found ");
664 chip_id = readl(remapped_regs + mmCHIP_ID);
665 switch(chip_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;
669 default:
670 printk("Unknown imageon chip ID\n");
671 err = -ENODEV;
672 goto out;
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)
679 goto out;
681 info=framebuffer_alloc(sizeof(struct w100fb_par), &pdev->dev);
682 if (!info) {
683 err = -ENOMEM;
684 goto out;
687 par = info->par;
688 platform_set_drvdata(pdev, info);
690 inf = dev_get_platdata(&pdev->dev);
691 par->chip_id = chip_id;
692 par->mach = inf;
693 par->fastpll_mode = 0;
694 par->blanked = 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");
699 err = -EINVAL;
700 goto out;
703 info->pseudo_palette = kmalloc_array(MAX_PALETTES, sizeof(u32),
704 GFP_KERNEL);
705 if (!info->pseudo_palette) {
706 err = -ENOMEM;
707 goto out;
710 info->fbops = &w100fb_ops;
711 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
712 FBINFO_HWACCEL_FILLRECT;
713 info->node = -1;
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) {
726 err = -ENOMEM;
727 goto out;
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;
735 else {
736 info->var.xres = par->mode->xres;
737 info->var.yres = par->mode->yres;
740 if(inf->init_mode &= INIT_MODE_FLIPPED)
741 par->flip = 1;
742 else
743 par->flip = 0;
745 info->var.xres_virtual = info->var.xres;
746 info->var.yres_virtual = info->var.yres;
747 info->var.pixclock = 0x04; /* 171521; */
748 info->var.sync = 0;
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;
754 w100_hw_init(par);
756 if (w100fb_check_var(&info->var, info) < 0) {
757 err = -EINVAL;
758 goto out;
761 if (register_framebuffer(info) < 0) {
762 err = -EINVAL;
763 goto out;
766 fb_info(info, "%s frame buffer device\n", info->fix.id);
767 return 0;
768 out:
769 if (info) {
770 fb_dealloc_cmap(&info->cmap);
771 kfree(info->pseudo_palette);
773 if (remapped_fbuf != NULL)
774 iounmap(remapped_fbuf);
775 if (remapped_regs != NULL)
776 iounmap(remapped_regs);
777 if (remapped_base != NULL)
778 iounmap(remapped_base);
779 if (info)
780 framebuffer_release(info);
781 return err;
785 static int w100fb_remove(struct platform_device *pdev)
787 struct fb_info *info = platform_get_drvdata(pdev);
788 struct w100fb_par *par=info->par;
790 unregister_framebuffer(info);
792 vfree(par->saved_intmem);
793 vfree(par->saved_extmem);
794 kfree(info->pseudo_palette);
795 fb_dealloc_cmap(&info->cmap);
797 iounmap(remapped_base);
798 iounmap(remapped_regs);
799 iounmap(remapped_fbuf);
801 framebuffer_release(info);
803 return 0;
807 /* ------------------- chipset specific functions -------------------------- */
810 static void w100_soft_reset(void)
812 u16 val = readw((u16 __iomem *)remapped_base + cfgSTATUS);
814 writew(val | 0x08, (u16 __iomem *)remapped_base + cfgSTATUS);
815 udelay(100);
816 writew(0x00, (u16 __iomem *)remapped_base + cfgSTATUS);
817 udelay(100);
820 static void w100_update_disable(void)
822 union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
824 /* Prevent display updates */
825 disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
826 disp_db_buf_wr_cntl.f.update_db_buf = 0;
827 disp_db_buf_wr_cntl.f.en_db_buf = 0;
828 writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
831 static void w100_update_enable(void)
833 union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl;
835 /* Enable display updates */
836 disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e;
837 disp_db_buf_wr_cntl.f.update_db_buf = 1;
838 disp_db_buf_wr_cntl.f.en_db_buf = 1;
839 writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL);
842 unsigned long w100fb_gpio_read(int port)
844 unsigned long value;
846 if (port==W100_GPIO_PORT_A)
847 value = readl(remapped_regs + mmGPIO_DATA);
848 else
849 value = readl(remapped_regs + mmGPIO_DATA2);
851 return value;
854 void w100fb_gpio_write(int port, unsigned long value)
856 if (port==W100_GPIO_PORT_A)
857 writel(value, remapped_regs + mmGPIO_DATA);
858 else
859 writel(value, remapped_regs + mmGPIO_DATA2);
861 EXPORT_SYMBOL(w100fb_gpio_read);
862 EXPORT_SYMBOL(w100fb_gpio_write);
865 * Initialization of critical w100 hardware
867 static void w100_hw_init(struct w100fb_par *par)
869 u32 temp32;
870 union cif_cntl_u cif_cntl;
871 union intf_cntl_u intf_cntl;
872 union cfgreg_base_u cfgreg_base;
873 union wrap_top_dir_u wrap_top_dir;
874 union cif_read_dbg_u cif_read_dbg;
875 union cpu_defaults_u cpu_default;
876 union cif_write_dbg_u cif_write_dbg;
877 union wrap_start_dir_u wrap_start_dir;
878 union cif_io_u cif_io;
879 struct w100_gpio_regs *gpio = par->mach->gpio;
881 w100_soft_reset();
883 /* This is what the fpga_init code does on reset. May be wrong
884 but there is little info available */
885 writel(0x31, remapped_regs + mmSCRATCH_UMSK);
886 for (temp32 = 0; temp32 < 10000; temp32++)
887 readl(remapped_regs + mmSCRATCH_UMSK);
888 writel(0x30, remapped_regs + mmSCRATCH_UMSK);
890 /* Set up CIF */
891 cif_io.val = defCIF_IO;
892 writel((u32)(cif_io.val), remapped_regs + mmCIF_IO);
894 cif_write_dbg.val = readl(remapped_regs + mmCIF_WRITE_DBG);
895 cif_write_dbg.f.dis_packer_ful_during_rbbm_timeout = 0;
896 cif_write_dbg.f.en_dword_split_to_rbbm = 1;
897 cif_write_dbg.f.dis_timeout_during_rbbm = 1;
898 writel((u32) (cif_write_dbg.val), remapped_regs + mmCIF_WRITE_DBG);
900 cif_read_dbg.val = readl(remapped_regs + mmCIF_READ_DBG);
901 cif_read_dbg.f.dis_rd_same_byte_to_trig_fetch = 1;
902 writel((u32) (cif_read_dbg.val), remapped_regs + mmCIF_READ_DBG);
904 cif_cntl.val = readl(remapped_regs + mmCIF_CNTL);
905 cif_cntl.f.dis_system_bits = 1;
906 cif_cntl.f.dis_mr = 1;
907 cif_cntl.f.en_wait_to_compensate_dq_prop_dly = 0;
908 cif_cntl.f.intb_oe = 1;
909 cif_cntl.f.interrupt_active_high = 1;
910 writel((u32) (cif_cntl.val), remapped_regs + mmCIF_CNTL);
912 /* Setup cfgINTF_CNTL and cfgCPU defaults */
913 intf_cntl.val = defINTF_CNTL;
914 intf_cntl.f.ad_inc_a = 1;
915 intf_cntl.f.ad_inc_b = 1;
916 intf_cntl.f.rd_data_rdy_a = 0;
917 intf_cntl.f.rd_data_rdy_b = 0;
918 writeb((u8) (intf_cntl.val), remapped_base + cfgINTF_CNTL);
920 cpu_default.val = defCPU_DEFAULTS;
921 cpu_default.f.access_ind_addr_a = 1;
922 cpu_default.f.access_ind_addr_b = 1;
923 cpu_default.f.access_scratch_reg = 1;
924 cpu_default.f.transition_size = 0;
925 writeb((u8) (cpu_default.val), remapped_base + cfgCPU_DEFAULTS);
927 /* set up the apertures */
928 writeb((u8) (W100_REG_BASE >> 16), remapped_base + cfgREG_BASE);
930 cfgreg_base.val = defCFGREG_BASE;
931 cfgreg_base.f.cfgreg_base = W100_CFG_BASE;
932 writel((u32) (cfgreg_base.val), remapped_regs + mmCFGREG_BASE);
934 wrap_start_dir.val = defWRAP_START_DIR;
935 wrap_start_dir.f.start_addr = WRAP_BUF_BASE_VALUE >> 1;
936 writel((u32) (wrap_start_dir.val), remapped_regs + mmWRAP_START_DIR);
938 wrap_top_dir.val = defWRAP_TOP_DIR;
939 wrap_top_dir.f.top_addr = WRAP_BUF_TOP_VALUE >> 1;
940 writel((u32) (wrap_top_dir.val), remapped_regs + mmWRAP_TOP_DIR);
942 writel((u32) 0x2440, remapped_regs + mmRBBM_CNTL);
944 /* Set the hardware to 565 colour */
945 temp32 = readl(remapped_regs + mmDISP_DEBUG2);
946 temp32 &= 0xff7fffff;
947 temp32 |= 0x00800000;
948 writel(temp32, remapped_regs + mmDISP_DEBUG2);
950 /* Initialise the GPIO lines */
951 if (gpio) {
952 writel(gpio->init_data1, remapped_regs + mmGPIO_DATA);
953 writel(gpio->init_data2, remapped_regs + mmGPIO_DATA2);
954 writel(gpio->gpio_dir1, remapped_regs + mmGPIO_CNTL1);
955 writel(gpio->gpio_oe1, remapped_regs + mmGPIO_CNTL2);
956 writel(gpio->gpio_dir2, remapped_regs + mmGPIO_CNTL3);
957 writel(gpio->gpio_oe2, remapped_regs + mmGPIO_CNTL4);
962 struct power_state {
963 union clk_pin_cntl_u clk_pin_cntl;
964 union pll_ref_fb_div_u pll_ref_fb_div;
965 union pll_cntl_u pll_cntl;
966 union sclk_cntl_u sclk_cntl;
967 union pclk_cntl_u pclk_cntl;
968 union pwrmgt_cntl_u pwrmgt_cntl;
969 int auto_mode; /* system clock auto changing? */
973 static struct power_state w100_pwr_state;
975 /* The PLL Fout is determined by (XtalFreq/(M+1)) * ((N_int+1) + (N_fac/8)) */
977 /* 12.5MHz Crystal PLL Table */
978 static struct w100_pll_info xtal_12500000[] = {
979 /*freq M N_int N_fac tfgoal lock_time */
980 { 50, 0, 1, 0, 0xe0, 56}, /* 50.00 MHz */
981 { 75, 0, 5, 0, 0xde, 37}, /* 75.00 MHz */
982 {100, 0, 7, 0, 0xe0, 28}, /* 100.00 MHz */
983 {125, 0, 9, 0, 0xe0, 22}, /* 125.00 MHz */
984 {150, 0, 11, 0, 0xe0, 17}, /* 150.00 MHz */
985 { 0, 0, 0, 0, 0, 0}, /* Terminator */
988 /* 14.318MHz Crystal PLL Table */
989 static struct w100_pll_info xtal_14318000[] = {
990 /*freq M N_int N_fac tfgoal lock_time */
991 { 40, 4, 13, 0, 0xe0, 80}, /* tfgoal guessed */
992 { 50, 1, 6, 0, 0xe0, 64}, /* 50.05 MHz */
993 { 57, 2, 11, 0, 0xe0, 53}, /* tfgoal guessed */
994 { 75, 0, 4, 3, 0xe0, 43}, /* 75.08 MHz */
995 {100, 0, 6, 0, 0xe0, 32}, /* 100.10 MHz */
996 { 0, 0, 0, 0, 0, 0},
999 /* 16MHz Crystal PLL Table */
1000 static struct w100_pll_info xtal_16000000[] = {
1001 /*freq M N_int N_fac tfgoal lock_time */
1002 { 72, 1, 8, 0, 0xe0, 48}, /* tfgoal guessed */
1003 { 80, 1, 9, 0, 0xe0, 13}, /* tfgoal guessed */
1004 { 95, 1, 10, 7, 0xe0, 38}, /* tfgoal guessed */
1005 { 96, 1, 11, 0, 0xe0, 36}, /* tfgoal guessed */
1006 { 0, 0, 0, 0, 0, 0},
1009 static struct pll_entries {
1010 int xtal_freq;
1011 struct w100_pll_info *pll_table;
1012 } w100_pll_tables[] = {
1013 { 12500000, &xtal_12500000[0] },
1014 { 14318000, &xtal_14318000[0] },
1015 { 16000000, &xtal_16000000[0] },
1016 { 0 },
1019 struct w100_pll_info *w100_get_xtal_table(unsigned int freq)
1021 struct pll_entries *pll_entry = w100_pll_tables;
1023 do {
1024 if (freq == pll_entry->xtal_freq)
1025 return pll_entry->pll_table;
1026 pll_entry++;
1027 } while (pll_entry->xtal_freq);
1029 return NULL;
1033 static unsigned int w100_get_testcount(unsigned int testclk_sel)
1035 union clk_test_cntl_u clk_test_cntl;
1037 udelay(5);
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 */
1053 udelay(20);
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)
1066 unsigned int tf80;
1067 unsigned int tf20;
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
1080 * tf80 meant tf100
1082 do {
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;
1104 continue;
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;
1112 } else {
1113 return 0; /* Error */
1115 } while(1);
1120 * w100_pll_calibration
1122 static int w100_pll_calibration(struct w100_pll_info *pll)
1124 int status;
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 */
1145 /* PLL locked */
1147 return status;
1151 static int w100_pll_set_clk(struct w100_pll_info *pll)
1153 int status;
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);
1183 return status;
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;
1191 do {
1192 if (freq == pll->freq) {
1193 return w100_pll_set_clk(pll);
1195 pll++;
1196 } while(pll->freq);
1197 return 0;
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)
1297 u32 temp32;
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);
1328 crtc_total.val = 0;
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);
1382 } else {
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);
1396 udelay(100);
1397 writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG);
1398 udelay(100);
1399 writel(mem->sdram_mode_reg, remapped_regs + mmMEM_SDRAM_MODE_REG);
1400 udelay(100);
1401 writel(mem->ext_timing_cntl, remapped_regs + mmMEM_EXT_TIMING_CNTL);
1402 writel(mem->io_cntl, remapped_regs + mmMEM_IO_CNTL);
1403 if (bm_mem) {
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) {
1422 if (par->flip) {
1423 rot=3; /* 180 degree */
1424 offset=(par->xres * par->yres) - 1;
1425 } /* else 0 degree */
1426 divider = par->mode->pixclk_divider;
1427 } else {
1428 if (par->flip) {
1429 rot=2; /* 270 degree */
1430 offset=par->xres - 1;
1431 } else {
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) {
1440 case CHIP_ID_W100:
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 */
1452 switch(par->xres) {
1453 case 240:
1454 case 320:
1455 default:
1456 graphic_ctrl.f_w100.total_req_graphic=0xa0;
1457 break;
1458 case 480:
1459 case 640:
1460 switch(rot) {
1461 case 0: /* 0 */
1462 case 3: /* 180 */
1463 graphic_ctrl.f_w100.low_power_on=1;
1464 graphic_ctrl.f_w100.req_freq=5;
1465 break;
1466 case 1: /* 90 */
1467 case 2: /* 270 */
1468 graphic_ctrl.f_w100.req_freq=4;
1469 break;
1470 default:
1471 break;
1473 graphic_ctrl.f_w100.total_req_graphic=0xf0;
1474 break;
1476 break;
1477 case CHIP_ID_W3200:
1478 case CHIP_ID_W3220:
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;
1489 break;
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;
1515 else
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);
1521 if (crtc_ss.val)
1522 par->hsync_len = hsync / (crtc_ss.f.ss_end-crtc_ss.f.ss_start);
1523 else
1524 par->hsync_len = 0;
1527 static void w100_suspend(u32 mode)
1529 u32 val;
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);
1552 /* CLK: Stop */
1553 val = readl(remapped_regs + mmMEM_EXT_CNTL);
1554 val &= ~(0x00000001); /* bit0=0 */
1555 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1556 } else {
1557 writel(0x00000000, remapped_regs + mmSCLK_CNTL);
1558 writel(0x000000BF, remapped_regs + mmCLK_PIN_CNTL);
1559 writel(0x00000015, remapped_regs + mmPWRMGT_CNTL);
1561 udelay(5);
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);
1574 val |= 0xF0000000;
1575 val &= ~(0x00000001);
1576 writel(val, remapped_regs + mmMEM_EXT_CNTL);
1578 writel(0x0000001d, remapped_regs + mmPWRMGT_CNTL);
1582 static void w100_vsync(void)
1584 u32 tmp;
1585 int timeout = 30000; /* VSync timeout = 30[ms] > 16.8[ms] */
1587 tmp = readl(remapped_regs + mmACTIVE_V_DISP);
1589 /* set vline pos */
1590 writel((tmp >> 16) & 0x3ff, remapped_regs + mmDISP_INT_CNTL);
1592 /* disable vline irq */
1593 tmp = readl(remapped_regs + mmGEN_INT_CNTL);
1595 tmp &= ~0x00000002;
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)
1609 break;
1610 udelay(1);
1611 timeout--;
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,
1626 .driver = {
1627 .name = "w100fb",
1628 .dev_groups = w100fb_groups,
1632 module_platform_driver(w100fb_driver);
1634 MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
1635 MODULE_LICENSE("GPL");