2 * linux/drivers/video/w100fb.c
4 * Frame Buffer Device for ATI Imageon w100 (Wallaby)
6 * Copyright (C) 2002, ATI Corp.
7 * Copyright (C) 2004-2006 Richard Purdie
8 * Copyright (c) 2005 Ian Molton
9 * Copyright (c) 2006 Alberto Mardegan
11 * Rewritten for 2.6 by Richard Purdie <rpurdie@rpsys.net>
13 * Generic platform support by Ian Molton <spyro@f2s.com>
14 * and Richard Purdie <rpurdie@rpsys.net>
16 * w32xx support by Ian Molton
18 * Hardware acceleration support by Alberto Mardegan
19 * <mardy@users.sourceforge.net>
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License version 2 as
23 * published by the Free Software Foundation.
27 #include <linux/delay.h>
29 #include <linux/init.h>
30 #include <linux/kernel.h>
32 #include <linux/platform_device.h>
33 #include <linux/string.h>
34 #include <linux/vmalloc.h>
36 #include <asm/uaccess.h>
37 #include <video/w100fb.h>
43 static void w100_suspend(u32 mode
);
44 static void w100_vsync(void);
45 static void w100_hw_init(struct w100fb_par
*);
46 static void w100_pwm_setup(struct w100fb_par
*);
47 static void w100_init_clocks(struct w100fb_par
*);
48 static void w100_setup_memory(struct w100fb_par
*);
49 static void w100_init_lcd(struct w100fb_par
*);
50 static void w100_set_dispregs(struct w100fb_par
*);
51 static void w100_update_enable(void);
52 static void w100_update_disable(void);
53 static void calc_hsync(struct w100fb_par
*par
);
54 static void w100_init_graphic_engine(struct w100fb_par
*par
);
55 struct w100_pll_info
*w100_get_xtal_table(unsigned int freq
);
57 /* Pseudo palette size */
58 #define MAX_PALETTES 16
60 #define W100_SUSPEND_EXTMEM 0
61 #define W100_SUSPEND_ALL 1
63 #define BITS_PER_PIXEL 16
65 /* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */
66 static void *remapped_base
;
67 static void *remapped_regs
;
68 static void *remapped_fbuf
;
70 #define REMAPPED_FB_LEN 0x15ffff
72 /* This is the offset in the w100's address space we map the current
73 framebuffer memory to. We use the position of external memory as
74 we can remap internal memory to there if external isn't present. */
75 #define W100_FB_BASE MEM_EXT_BASE_VALUE
81 static ssize_t
flip_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
83 struct platform_device
*pdev
= to_platform_device(dev
);
84 struct fb_info
*info
= platform_get_drvdata(pdev
);
85 struct w100fb_par
*par
=info
->par
;
87 return sprintf(buf
, "%d\n",par
->flip
);
90 static ssize_t
flip_store(struct device
*dev
, struct device_attribute
*attr
, const char *buf
, size_t count
)
92 struct platform_device
*pdev
= to_platform_device(dev
);
94 struct fb_info
*info
= dev_get_drvdata(pdev
);
95 struct w100fb_par
*par
=info
->par
;
97 flip
= simple_strtoul(buf
, NULL
, 10);
104 w100_update_disable();
105 w100_set_dispregs(par
);
106 w100_update_enable();
113 static DEVICE_ATTR(flip
, 0644, flip_show
, flip_store
);
115 static ssize_t
w100fb_reg_read(struct device
*dev
, struct device_attribute
*attr
, const char *buf
, size_t count
)
117 unsigned long regs
, param
;
118 regs
= simple_strtoul(buf
, NULL
, 16);
119 param
= readl(remapped_regs
+ regs
);
120 printk("Read Register 0x%08lX: 0x%08lX\n", regs
, param
);
124 static DEVICE_ATTR(reg_read
, 0200, NULL
, w100fb_reg_read
);
126 static ssize_t
w100fb_reg_write(struct device
*dev
, struct device_attribute
*attr
, const char *buf
, size_t count
)
128 unsigned long regs
, param
;
129 sscanf(buf
, "%lx %lx", ®s
, ¶m
);
131 if (regs
<= 0x2000) {
132 printk("Write Register 0x%08lX: 0x%08lX\n", regs
, param
);
133 writel(param
, remapped_regs
+ regs
);
139 static DEVICE_ATTR(reg_write
, 0200, NULL
, w100fb_reg_write
);
142 static ssize_t
fastpllclk_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
144 struct platform_device
*pdev
= to_platform_device(dev
);
145 struct fb_info
*info
= platform_get_drvdata(pdev
);
146 struct w100fb_par
*par
=info
->par
;
148 return sprintf(buf
, "%d\n",par
->fastpll_mode
);
151 static ssize_t
fastpllclk_store(struct device
*dev
, struct device_attribute
*attr
, const char *buf
, size_t count
)
153 struct platform_device
*pdev
= to_platform_device(dev
);
154 struct fb_info
*info
= platform_get_drvdata(pdev
);
155 struct w100fb_par
*par
=info
->par
;
157 if (simple_strtoul(buf
, NULL
, 10) > 0) {
159 printk("w100fb: Using fast system clock (if possible)\n");
162 printk("w100fb: Using normal system clock\n");
165 w100_init_clocks(par
);
171 static DEVICE_ATTR(fastpllclk
, 0644, fastpllclk_show
, fastpllclk_store
);
174 * Some touchscreens need hsync information from the video driver to
175 * function correctly. We export it here.
177 unsigned long w100fb_get_hsynclen(struct device
*dev
)
179 struct platform_device
*pdev
= to_platform_device(dev
);
180 struct fb_info
*info
= platform_get_drvdata(pdev
);
181 struct w100fb_par
*par
=info
->par
;
183 /* If display is blanked/suspended, hsync isn't active */
187 return par
->hsync_len
;
189 EXPORT_SYMBOL(w100fb_get_hsynclen
);
191 static void w100fb_clear_screen(struct w100fb_par
*par
)
193 memset_io(remapped_fbuf
+ (W100_FB_BASE
-MEM_WINDOW_BASE
), 0, (par
->xres
* par
->yres
* BITS_PER_PIXEL
/8));
198 * Set a palette value from rgb components
200 static int w100fb_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
201 u_int trans
, struct fb_info
*info
)
207 * If greyscale is true, then we convert the RGB value
208 * to greyscale no matter what visual we are using.
210 if (info
->var
.grayscale
)
211 red
= green
= blue
= (19595 * red
+ 38470 * green
+ 7471 * blue
) >> 16;
214 * 16-bit True Colour. We encode the RGB value
215 * according to the RGB bitfield information.
217 if (regno
< MAX_PALETTES
) {
218 u32
*pal
= info
->pseudo_palette
;
220 val
= (red
& 0xf800) | ((green
& 0xfc00) >> 5) | ((blue
& 0xf800) >> 11);
229 * Blank the display based on value in blank_mode
231 static int w100fb_blank(int blank_mode
, struct fb_info
*info
)
233 struct w100fb_par
*par
= info
->par
;
234 struct w100_tg_info
*tg
= par
->mach
->tg
;
238 case FB_BLANK_NORMAL
: /* Normal blanking */
239 case FB_BLANK_VSYNC_SUSPEND
: /* VESA blank (vsync off) */
240 case FB_BLANK_HSYNC_SUSPEND
: /* VESA blank (hsync off) */
241 case FB_BLANK_POWERDOWN
: /* Poweroff */
242 if (par
->blanked
== 0) {
243 if(tg
&& tg
->suspend
)
249 case FB_BLANK_UNBLANK
: /* Unblanking */
250 if (par
->blanked
!= 0) {
261 static void w100_fifo_wait(int entries
)
263 union rbbm_status_u status
;
266 for (i
= 0; i
< 2000000; i
++) {
267 status
.val
= readl(remapped_regs
+ mmRBBM_STATUS
);
268 if (status
.f
.cmdfifo_avail
>= entries
)
272 printk(KERN_ERR
"w100fb: FIFO Timeout!\n");
276 static int w100fb_sync(struct fb_info
*info
)
278 union rbbm_status_u status
;
281 for (i
= 0; i
< 2000000; i
++) {
282 status
.val
= readl(remapped_regs
+ mmRBBM_STATUS
);
283 if (!status
.f
.gui_active
)
287 printk(KERN_ERR
"w100fb: Graphic engine timeout!\n");
292 static void w100_init_graphic_engine(struct w100fb_par
*par
)
294 union dp_gui_master_cntl_u gmc
;
295 union dp_mix_u dp_mix
;
296 union dp_datatype_u dp_datatype
;
297 union dp_cntl_u dp_cntl
;
300 writel(W100_FB_BASE
, remapped_regs
+ mmDST_OFFSET
);
301 writel(par
->xres
, remapped_regs
+ mmDST_PITCH
);
302 writel(W100_FB_BASE
, remapped_regs
+ mmSRC_OFFSET
);
303 writel(par
->xres
, remapped_regs
+ mmSRC_PITCH
);
306 writel(0, remapped_regs
+ mmSC_TOP_LEFT
);
307 writel((par
->yres
<< 16) | par
->xres
, remapped_regs
+ mmSC_BOTTOM_RIGHT
);
308 writel(0x1fff1fff, remapped_regs
+ mmSRC_SC_BOTTOM_RIGHT
);
312 dp_cntl
.f
.dst_x_dir
= 1;
313 dp_cntl
.f
.dst_y_dir
= 1;
314 dp_cntl
.f
.src_x_dir
= 1;
315 dp_cntl
.f
.src_y_dir
= 1;
316 dp_cntl
.f
.dst_major_x
= 1;
317 dp_cntl
.f
.src_major_x
= 1;
318 writel(dp_cntl
.val
, remapped_regs
+ mmDP_CNTL
);
321 gmc
.f
.gmc_src_pitch_offset_cntl
= 1;
322 gmc
.f
.gmc_dst_pitch_offset_cntl
= 1;
323 gmc
.f
.gmc_src_clipping
= 1;
324 gmc
.f
.gmc_dst_clipping
= 1;
325 gmc
.f
.gmc_brush_datatype
= GMC_BRUSH_NONE
;
326 gmc
.f
.gmc_dst_datatype
= 3; /* from DstType_16Bpp_444 */
327 gmc
.f
.gmc_src_datatype
= SRC_DATATYPE_EQU_DST
;
328 gmc
.f
.gmc_byte_pix_order
= 1;
329 gmc
.f
.gmc_default_sel
= 0;
330 gmc
.f
.gmc_rop3
= ROP3_SRCCOPY
;
331 gmc
.f
.gmc_dp_src_source
= DP_SRC_MEM_RECTANGULAR
;
332 gmc
.f
.gmc_clr_cmp_fcn_dis
= 1;
333 gmc
.f
.gmc_wr_msk_dis
= 1;
334 gmc
.f
.gmc_dp_op
= DP_OP_ROP
;
335 writel(gmc
.val
, remapped_regs
+ mmDP_GUI_MASTER_CNTL
);
337 dp_datatype
.val
= dp_mix
.val
= 0;
338 dp_datatype
.f
.dp_dst_datatype
= gmc
.f
.gmc_dst_datatype
;
339 dp_datatype
.f
.dp_brush_datatype
= gmc
.f
.gmc_brush_datatype
;
340 dp_datatype
.f
.dp_src2_type
= 0;
341 dp_datatype
.f
.dp_src2_datatype
= gmc
.f
.gmc_src_datatype
;
342 dp_datatype
.f
.dp_src_datatype
= gmc
.f
.gmc_src_datatype
;
343 dp_datatype
.f
.dp_byte_pix_order
= gmc
.f
.gmc_byte_pix_order
;
344 writel(dp_datatype
.val
, remapped_regs
+ mmDP_DATATYPE
);
346 dp_mix
.f
.dp_src_source
= gmc
.f
.gmc_dp_src_source
;
347 dp_mix
.f
.dp_src2_source
= 1;
348 dp_mix
.f
.dp_rop3
= gmc
.f
.gmc_rop3
;
349 dp_mix
.f
.dp_op
= gmc
.f
.gmc_dp_op
;
350 writel(dp_mix
.val
, remapped_regs
+ mmDP_MIX
);
354 static void w100fb_fillrect(struct fb_info
*info
,
355 const struct fb_fillrect
*rect
)
357 union dp_gui_master_cntl_u gmc
;
359 if (info
->state
!= FBINFO_STATE_RUNNING
)
361 if (info
->flags
& FBINFO_HWACCEL_DISABLED
) {
362 cfb_fillrect(info
, rect
);
366 gmc
.val
= readl(remapped_regs
+ mmDP_GUI_MASTER_CNTL
);
367 gmc
.f
.gmc_rop3
= ROP3_PATCOPY
;
368 gmc
.f
.gmc_brush_datatype
= GMC_BRUSH_SOLID_COLOR
;
370 writel(gmc
.val
, remapped_regs
+ mmDP_GUI_MASTER_CNTL
);
371 writel(rect
->color
, remapped_regs
+ mmDP_BRUSH_FRGD_CLR
);
374 writel((rect
->dy
<< 16) | (rect
->dx
& 0xffff), remapped_regs
+ mmDST_Y_X
);
375 writel((rect
->width
<< 16) | (rect
->height
& 0xffff),
376 remapped_regs
+ mmDST_WIDTH_HEIGHT
);
380 static void w100fb_copyarea(struct fb_info
*info
,
381 const struct fb_copyarea
*area
)
383 u32 dx
= area
->dx
, dy
= area
->dy
, sx
= area
->sx
, sy
= area
->sy
;
384 u32 h
= area
->height
, w
= area
->width
;
385 union dp_gui_master_cntl_u gmc
;
387 if (info
->state
!= FBINFO_STATE_RUNNING
)
389 if (info
->flags
& FBINFO_HWACCEL_DISABLED
) {
390 cfb_copyarea(info
, area
);
394 gmc
.val
= readl(remapped_regs
+ mmDP_GUI_MASTER_CNTL
);
395 gmc
.f
.gmc_rop3
= ROP3_SRCCOPY
;
396 gmc
.f
.gmc_brush_datatype
= GMC_BRUSH_NONE
;
398 writel(gmc
.val
, remapped_regs
+ mmDP_GUI_MASTER_CNTL
);
401 writel((sy
<< 16) | (sx
& 0xffff), remapped_regs
+ mmSRC_Y_X
);
402 writel((dy
<< 16) | (dx
& 0xffff), remapped_regs
+ mmDST_Y_X
);
403 writel((w
<< 16) | (h
& 0xffff), remapped_regs
+ mmDST_WIDTH_HEIGHT
);
408 * Change the resolution by calling the appropriate hardware functions
410 static void w100fb_activate_var(struct w100fb_par
*par
)
412 struct w100_tg_info
*tg
= par
->mach
->tg
;
415 w100_setup_memory(par
);
416 w100_init_clocks(par
);
417 w100fb_clear_screen(par
);
420 w100_update_disable();
422 w100_set_dispregs(par
);
423 w100_update_enable();
424 w100_init_graphic_engine(par
);
428 if (!par
->blanked
&& tg
&& tg
->change
)
433 /* Select the smallest mode that allows the desired resolution to be
434 * displayed. If desired, the x and y parameters can be rounded up to
435 * match the selected mode.
437 static struct w100_mode
*w100fb_get_mode(struct w100fb_par
*par
, unsigned int *x
, unsigned int *y
, int saveval
)
439 struct w100_mode
*mode
= NULL
;
440 struct w100_mode
*modelist
= par
->mach
->modelist
;
441 unsigned int best_x
= 0xffffffff, best_y
= 0xffffffff;
444 for (i
= 0 ; i
< par
->mach
->num_modes
; i
++) {
445 if (modelist
[i
].xres
>= *x
&& modelist
[i
].yres
>= *y
&&
446 modelist
[i
].xres
< best_x
&& modelist
[i
].yres
< best_y
) {
447 best_x
= modelist
[i
].xres
;
448 best_y
= modelist
[i
].yres
;
450 } else if(modelist
[i
].xres
>= *y
&& modelist
[i
].yres
>= *x
&&
451 modelist
[i
].xres
< best_y
&& modelist
[i
].yres
< best_x
) {
452 best_x
= modelist
[i
].yres
;
453 best_y
= modelist
[i
].xres
;
458 if (mode
&& saveval
) {
468 * w100fb_check_var():
469 * Get the video params out of 'var'. If a value doesn't fit, round it up,
470 * if it's too big, return -EINVAL.
472 static int w100fb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
474 struct w100fb_par
*par
=info
->par
;
476 if(!w100fb_get_mode(par
, &var
->xres
, &var
->yres
, 1))
479 if (par
->mach
->mem
&& ((var
->xres
*var
->yres
*BITS_PER_PIXEL
/8) > (par
->mach
->mem
->size
+1)))
482 if (!par
->mach
->mem
&& ((var
->xres
*var
->yres
*BITS_PER_PIXEL
/8) > (MEM_INT_SIZE
+1)))
485 var
->xres_virtual
= max(var
->xres_virtual
, var
->xres
);
486 var
->yres_virtual
= max(var
->yres_virtual
, var
->yres
);
488 if (var
->bits_per_pixel
> BITS_PER_PIXEL
)
491 var
->bits_per_pixel
= BITS_PER_PIXEL
;
493 var
->red
.offset
= 11;
495 var
->green
.offset
= 5;
496 var
->green
.length
= 6;
497 var
->blue
.offset
= 0;
498 var
->blue
.length
= 5;
499 var
->transp
.offset
= var
->transp
.length
= 0;
504 var
->vmode
= FB_VMODE_NONINTERLACED
;
506 var
->pixclock
= 0x04; /* 171521; */
514 * Set the user defined part of the display for the specified console
515 * by looking at the values in info.var
517 static int w100fb_set_par(struct fb_info
*info
)
519 struct w100fb_par
*par
=info
->par
;
521 if (par
->xres
!= info
->var
.xres
|| par
->yres
!= info
->var
.yres
) {
522 par
->xres
= info
->var
.xres
;
523 par
->yres
= info
->var
.yres
;
524 par
->mode
= w100fb_get_mode(par
, &par
->xres
, &par
->yres
, 0);
526 info
->fix
.visual
= FB_VISUAL_TRUECOLOR
;
527 info
->fix
.ypanstep
= 0;
528 info
->fix
.ywrapstep
= 0;
529 info
->fix
.line_length
= par
->xres
* BITS_PER_PIXEL
/ 8;
531 if ((par
->xres
*par
->yres
*BITS_PER_PIXEL
/8) > (MEM_INT_SIZE
+1)) {
532 par
->extmem_active
= 1;
533 info
->fix
.smem_len
= par
->mach
->mem
->size
+1;
535 par
->extmem_active
= 0;
536 info
->fix
.smem_len
= MEM_INT_SIZE
+1;
539 w100fb_activate_var(par
);
546 * Frame buffer operations
548 static struct fb_ops w100fb_ops
= {
549 .owner
= THIS_MODULE
,
550 .fb_check_var
= w100fb_check_var
,
551 .fb_set_par
= w100fb_set_par
,
552 .fb_setcolreg
= w100fb_setcolreg
,
553 .fb_blank
= w100fb_blank
,
554 .fb_fillrect
= w100fb_fillrect
,
555 .fb_copyarea
= w100fb_copyarea
,
556 .fb_imageblit
= cfb_imageblit
,
557 .fb_sync
= w100fb_sync
,
561 static void w100fb_save_vidmem(struct w100fb_par
*par
)
565 if (par
->extmem_active
) {
566 memsize
=par
->mach
->mem
->size
;
567 par
->saved_extmem
= vmalloc(memsize
);
568 if (par
->saved_extmem
)
569 memcpy_fromio(par
->saved_extmem
, remapped_fbuf
+ (W100_FB_BASE
-MEM_WINDOW_BASE
), memsize
);
571 memsize
=MEM_INT_SIZE
;
572 par
->saved_intmem
= vmalloc(memsize
);
573 if (par
->saved_intmem
&& par
->extmem_active
)
574 memcpy_fromio(par
->saved_intmem
, remapped_fbuf
+ (W100_FB_BASE
-MEM_INT_BASE_VALUE
), memsize
);
575 else if (par
->saved_intmem
)
576 memcpy_fromio(par
->saved_intmem
, remapped_fbuf
+ (W100_FB_BASE
-MEM_WINDOW_BASE
), memsize
);
579 static void w100fb_restore_vidmem(struct w100fb_par
*par
)
583 if (par
->extmem_active
&& par
->saved_extmem
) {
584 memsize
=par
->mach
->mem
->size
;
585 memcpy_toio(remapped_fbuf
+ (W100_FB_BASE
-MEM_WINDOW_BASE
), par
->saved_extmem
, memsize
);
586 vfree(par
->saved_extmem
);
588 if (par
->saved_intmem
) {
589 memsize
=MEM_INT_SIZE
;
590 if (par
->extmem_active
)
591 memcpy_toio(remapped_fbuf
+ (W100_FB_BASE
-MEM_INT_BASE_VALUE
), par
->saved_intmem
, memsize
);
593 memcpy_toio(remapped_fbuf
+ (W100_FB_BASE
-MEM_WINDOW_BASE
), par
->saved_intmem
, memsize
);
594 vfree(par
->saved_intmem
);
598 static int w100fb_suspend(struct platform_device
*dev
, pm_message_t state
)
600 struct fb_info
*info
= platform_get_drvdata(dev
);
601 struct w100fb_par
*par
=info
->par
;
602 struct w100_tg_info
*tg
= par
->mach
->tg
;
604 w100fb_save_vidmem(par
);
605 if(tg
&& tg
->suspend
)
607 w100_suspend(W100_SUSPEND_ALL
);
613 static int w100fb_resume(struct platform_device
*dev
)
615 struct fb_info
*info
= platform_get_drvdata(dev
);
616 struct w100fb_par
*par
=info
->par
;
617 struct w100_tg_info
*tg
= par
->mach
->tg
;
620 w100fb_activate_var(par
);
621 w100fb_restore_vidmem(par
);
629 #define w100fb_suspend NULL
630 #define w100fb_resume NULL
634 int __init
w100fb_probe(struct platform_device
*pdev
)
637 struct w100fb_mach_info
*inf
;
638 struct fb_info
*info
= NULL
;
639 struct w100fb_par
*par
;
640 struct resource
*mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
641 unsigned int chip_id
;
646 /* Remap the chip base address */
647 remapped_base
= ioremap_nocache(mem
->start
+W100_CFG_BASE
, W100_CFG_LEN
);
648 if (remapped_base
== NULL
)
651 /* Map the register space */
652 remapped_regs
= ioremap_nocache(mem
->start
+W100_REG_BASE
, W100_REG_LEN
);
653 if (remapped_regs
== NULL
)
656 /* Identify the chip */
658 chip_id
= readl(remapped_regs
+ mmCHIP_ID
);
660 case CHIP_ID_W100
: printk("w100"); break;
661 case CHIP_ID_W3200
: printk("w3200"); break;
662 case CHIP_ID_W3220
: printk("w3220"); break;
664 printk("Unknown imageon chip ID\n");
668 printk(" at 0x%08lx.\n", mem
->start
+W100_CFG_BASE
);
670 /* Remap the framebuffer */
671 remapped_fbuf
= ioremap_nocache(mem
->start
+MEM_WINDOW_BASE
, MEM_WINDOW_SIZE
);
672 if (remapped_fbuf
== NULL
)
675 info
=framebuffer_alloc(sizeof(struct w100fb_par
), &pdev
->dev
);
682 platform_set_drvdata(pdev
, info
);
684 inf
= pdev
->dev
.platform_data
;
685 par
->chip_id
= chip_id
;
687 par
->fastpll_mode
= 0;
690 par
->pll_table
=w100_get_xtal_table(inf
->xtal_freq
);
691 if (!par
->pll_table
) {
692 printk(KERN_ERR
"No matching Xtal definition found\n");
697 info
->pseudo_palette
= kmalloc(sizeof (u32
) * MAX_PALETTES
, GFP_KERNEL
);
698 if (!info
->pseudo_palette
) {
703 info
->fbops
= &w100fb_ops
;
704 info
->flags
= FBINFO_DEFAULT
| FBINFO_HWACCEL_COPYAREA
|
705 FBINFO_HWACCEL_FILLRECT
;
707 info
->screen_base
= remapped_fbuf
+ (W100_FB_BASE
-MEM_WINDOW_BASE
);
708 info
->screen_size
= REMAPPED_FB_LEN
;
710 strcpy(info
->fix
.id
, "w100fb");
711 info
->fix
.type
= FB_TYPE_PACKED_PIXELS
;
712 info
->fix
.type_aux
= 0;
713 info
->fix
.accel
= FB_ACCEL_NONE
;
714 info
->fix
.smem_start
= mem
->start
+W100_FB_BASE
;
715 info
->fix
.mmio_start
= mem
->start
+W100_REG_BASE
;
716 info
->fix
.mmio_len
= W100_REG_LEN
;
718 if (fb_alloc_cmap(&info
->cmap
, 256, 0) < 0) {
723 par
->mode
= &inf
->modelist
[0];
724 if(inf
->init_mode
& INIT_MODE_ROTATED
) {
725 info
->var
.xres
= par
->mode
->yres
;
726 info
->var
.yres
= par
->mode
->xres
;
729 info
->var
.xres
= par
->mode
->xres
;
730 info
->var
.yres
= par
->mode
->yres
;
733 if(inf
->init_mode
&= INIT_MODE_FLIPPED
)
738 info
->var
.xres_virtual
= info
->var
.xres
;
739 info
->var
.yres_virtual
= info
->var
.yres
;
740 info
->var
.pixclock
= 0x04; /* 171521; */
742 info
->var
.grayscale
= 0;
743 info
->var
.xoffset
= info
->var
.yoffset
= 0;
744 info
->var
.accel_flags
= 0;
745 info
->var
.activate
= FB_ACTIVATE_NOW
;
749 if (w100fb_check_var(&info
->var
, info
) < 0) {
754 w100fb_set_par(info
);
756 if (register_framebuffer(info
) < 0) {
761 device_create_file(&pdev
->dev
, &dev_attr_fastpllclk
);
762 device_create_file(&pdev
->dev
, &dev_attr_reg_read
);
763 device_create_file(&pdev
->dev
, &dev_attr_reg_write
);
764 device_create_file(&pdev
->dev
, &dev_attr_flip
);
766 printk(KERN_INFO
"fb%d: %s frame buffer device\n", info
->node
, info
->fix
.id
);
769 fb_dealloc_cmap(&info
->cmap
);
770 kfree(info
->pseudo_palette
);
771 if (remapped_fbuf
!= NULL
)
772 iounmap(remapped_fbuf
);
773 if (remapped_regs
!= NULL
)
774 iounmap(remapped_regs
);
775 if (remapped_base
!= NULL
)
776 iounmap(remapped_base
);
778 framebuffer_release(info
);
783 static int w100fb_remove(struct platform_device
*pdev
)
785 struct fb_info
*info
= platform_get_drvdata(pdev
);
786 struct w100fb_par
*par
=info
->par
;
788 device_remove_file(&pdev
->dev
, &dev_attr_fastpllclk
);
789 device_remove_file(&pdev
->dev
, &dev_attr_reg_read
);
790 device_remove_file(&pdev
->dev
, &dev_attr_reg_write
);
791 device_remove_file(&pdev
->dev
, &dev_attr_flip
);
793 unregister_framebuffer(info
);
795 vfree(par
->saved_intmem
);
796 vfree(par
->saved_extmem
);
797 kfree(info
->pseudo_palette
);
798 fb_dealloc_cmap(&info
->cmap
);
800 iounmap(remapped_base
);
801 iounmap(remapped_regs
);
802 iounmap(remapped_fbuf
);
804 framebuffer_release(info
);
810 /* ------------------- chipset specific functions -------------------------- */
813 static void w100_soft_reset(void)
815 u16 val
= readw((u16
*) remapped_base
+ cfgSTATUS
);
816 writew(val
| 0x08, (u16
*) remapped_base
+ cfgSTATUS
);
818 writew(0x00, (u16
*) remapped_base
+ cfgSTATUS
);
822 static void w100_update_disable(void)
824 union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl
;
826 /* Prevent display updates */
827 disp_db_buf_wr_cntl
.f
.db_buf_cntl
= 0x1e;
828 disp_db_buf_wr_cntl
.f
.update_db_buf
= 0;
829 disp_db_buf_wr_cntl
.f
.en_db_buf
= 0;
830 writel((u32
) (disp_db_buf_wr_cntl
.val
), remapped_regs
+ mmDISP_DB_BUF_CNTL
);
833 static void w100_update_enable(void)
835 union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl
;
837 /* Enable display updates */
838 disp_db_buf_wr_cntl
.f
.db_buf_cntl
= 0x1e;
839 disp_db_buf_wr_cntl
.f
.update_db_buf
= 1;
840 disp_db_buf_wr_cntl
.f
.en_db_buf
= 1;
841 writel((u32
) (disp_db_buf_wr_cntl
.val
), remapped_regs
+ mmDISP_DB_BUF_CNTL
);
844 unsigned long w100fb_gpio_read(int port
)
848 if (port
==W100_GPIO_PORT_A
)
849 value
= readl(remapped_regs
+ mmGPIO_DATA
);
851 value
= readl(remapped_regs
+ mmGPIO_DATA2
);
856 void w100fb_gpio_write(int port
, unsigned long value
)
858 if (port
==W100_GPIO_PORT_A
)
859 writel(value
, remapped_regs
+ mmGPIO_DATA
);
861 writel(value
, remapped_regs
+ mmGPIO_DATA2
);
863 EXPORT_SYMBOL(w100fb_gpio_read
);
864 EXPORT_SYMBOL(w100fb_gpio_write
);
866 unsigned long w100fb_gpcntl_read(int port
)
870 if (port
==W100_GPIO_PORT_A
)
871 value
= readl(remapped_regs
+ mmGPIO_CNTL1
);
873 value
= readl(remapped_regs
+ mmGPIO_CNTL3
);
878 void w100fb_gpcntl_write(int port
, unsigned long value
)
880 if (port
==W100_GPIO_PORT_A
)
881 writel(value
, remapped_regs
+ mmGPIO_CNTL1
);
883 writel(value
, remapped_regs
+ mmGPIO_CNTL3
);
885 EXPORT_SYMBOL(w100fb_gpcntl_read
);
886 EXPORT_SYMBOL(w100fb_gpcntl_write
);
889 * Initialization of critical w100 hardware
891 static void w100_hw_init(struct w100fb_par
*par
)
894 union cif_cntl_u cif_cntl
;
895 union intf_cntl_u intf_cntl
;
896 union cfgreg_base_u cfgreg_base
;
897 union wrap_top_dir_u wrap_top_dir
;
898 union cif_read_dbg_u cif_read_dbg
;
899 union cpu_defaults_u cpu_default
;
900 union cif_write_dbg_u cif_write_dbg
;
901 union wrap_start_dir_u wrap_start_dir
;
902 union cif_io_u cif_io
;
903 struct w100_gpio_regs
*gpio
= par
->mach
->gpio
;
907 /* This is what the fpga_init code does on reset. May be wrong
908 but there is little info available */
909 writel(0x31, remapped_regs
+ mmSCRATCH_UMSK
);
910 for (temp32
= 0; temp32
< 10000; temp32
++)
911 readl(remapped_regs
+ mmSCRATCH_UMSK
);
912 writel(0x30, remapped_regs
+ mmSCRATCH_UMSK
);
915 cif_io
.val
= defCIF_IO
;
916 writel((u32
)(cif_io
.val
), remapped_regs
+ mmCIF_IO
);
918 cif_write_dbg
.val
= readl(remapped_regs
+ mmCIF_WRITE_DBG
);
919 cif_write_dbg
.f
.dis_packer_ful_during_rbbm_timeout
= 0;
920 cif_write_dbg
.f
.en_dword_split_to_rbbm
= 1;
921 cif_write_dbg
.f
.dis_timeout_during_rbbm
= 1;
922 writel((u32
) (cif_write_dbg
.val
), remapped_regs
+ mmCIF_WRITE_DBG
);
924 cif_read_dbg
.val
= readl(remapped_regs
+ mmCIF_READ_DBG
);
925 cif_read_dbg
.f
.dis_rd_same_byte_to_trig_fetch
= 1;
926 writel((u32
) (cif_read_dbg
.val
), remapped_regs
+ mmCIF_READ_DBG
);
928 cif_cntl
.val
= readl(remapped_regs
+ mmCIF_CNTL
);
929 cif_cntl
.f
.dis_system_bits
= 1;
930 cif_cntl
.f
.dis_mr
= 1;
931 cif_cntl
.f
.en_wait_to_compensate_dq_prop_dly
= 0;
932 cif_cntl
.f
.intb_oe
= 1;
933 cif_cntl
.f
.interrupt_active_high
= 1;
934 writel((u32
) (cif_cntl
.val
), remapped_regs
+ mmCIF_CNTL
);
936 /* Setup cfgINTF_CNTL and cfgCPU defaults */
937 intf_cntl
.val
= defINTF_CNTL
;
938 intf_cntl
.f
.ad_inc_a
= 1;
939 intf_cntl
.f
.ad_inc_b
= 1;
940 intf_cntl
.f
.rd_data_rdy_a
= 0;
941 intf_cntl
.f
.rd_data_rdy_b
= 0;
942 writeb((u8
) (intf_cntl
.val
), remapped_base
+ cfgINTF_CNTL
);
944 cpu_default
.val
= defCPU_DEFAULTS
;
945 cpu_default
.f
.access_ind_addr_a
= 1;
946 cpu_default
.f
.access_ind_addr_b
= 1;
947 cpu_default
.f
.access_scratch_reg
= 1;
948 cpu_default
.f
.transition_size
= 0;
949 writeb((u8
) (cpu_default
.val
), remapped_base
+ cfgCPU_DEFAULTS
);
951 /* set up the apertures */
952 writeb((u8
) (W100_REG_BASE
>> 16), remapped_base
+ cfgREG_BASE
);
954 cfgreg_base
.val
= defCFGREG_BASE
;
955 cfgreg_base
.f
.cfgreg_base
= W100_CFG_BASE
;
956 writel((u32
) (cfgreg_base
.val
), remapped_regs
+ mmCFGREG_BASE
);
958 wrap_start_dir
.val
= defWRAP_START_DIR
;
959 wrap_start_dir
.f
.start_addr
= WRAP_BUF_BASE_VALUE
>> 1;
960 writel((u32
) (wrap_start_dir
.val
), remapped_regs
+ mmWRAP_START_DIR
);
962 wrap_top_dir
.val
= defWRAP_TOP_DIR
;
963 wrap_top_dir
.f
.top_addr
= WRAP_BUF_TOP_VALUE
>> 1;
964 writel((u32
) (wrap_top_dir
.val
), remapped_regs
+ mmWRAP_TOP_DIR
);
966 writel((u32
) 0x2440, remapped_regs
+ mmRBBM_CNTL
);
968 /* Set the hardware to 565 colour */
969 temp32
= readl(remapped_regs
+ mmDISP_DEBUG2
);
970 temp32
&= 0xff7fffff;
971 temp32
|= 0x00800000;
972 writel(temp32
, remapped_regs
+ mmDISP_DEBUG2
);
974 /* Initialise the GPIO lines */
976 writel(gpio
->init_data1
, remapped_regs
+ mmGPIO_DATA
);
977 writel(gpio
->init_data2
, remapped_regs
+ mmGPIO_DATA2
);
978 writel(gpio
->gpio_dir1
, remapped_regs
+ mmGPIO_CNTL1
);
979 writel(gpio
->gpio_oe1
, remapped_regs
+ mmGPIO_CNTL2
);
980 writel(gpio
->gpio_dir2
, remapped_regs
+ mmGPIO_CNTL3
);
981 writel(gpio
->gpio_oe2
, remapped_regs
+ mmGPIO_CNTL4
);
987 union clk_pin_cntl_u clk_pin_cntl
;
988 union pll_ref_fb_div_u pll_ref_fb_div
;
989 union pll_cntl_u pll_cntl
;
990 union sclk_cntl_u sclk_cntl
;
991 union pclk_cntl_u pclk_cntl
;
992 union pwrmgt_cntl_u pwrmgt_cntl
;
993 int auto_mode
; /* system clock auto changing? */
997 static struct power_state w100_pwr_state
;
999 /* The PLL Fout is determined by (XtalFreq/(M+1)) * ((N_int+1) + (N_fac/8)) */
1001 /* 12.5MHz Crystal PLL Table */
1002 static struct w100_pll_info xtal_12500000
[] = {
1003 /*freq M N_int N_fac tfgoal lock_time */
1004 { 50, 0, 1, 0, 0xe0, 56}, /* 50.00 MHz */
1005 { 75, 0, 5, 0, 0xde, 37}, /* 75.00 MHz */
1006 {100, 0, 7, 0, 0xe0, 28}, /* 100.00 MHz */
1007 {125, 0, 9, 0, 0xe0, 22}, /* 125.00 MHz */
1008 {150, 0, 11, 0, 0xe0, 17}, /* 150.00 MHz */
1009 { 0, 0, 0, 0, 0, 0}, /* Terminator */
1012 /* 14.318MHz Crystal PLL Table */
1013 static struct w100_pll_info xtal_14318000
[] = {
1014 /*freq M N_int N_fac tfgoal lock_time */
1015 { 40, 4, 13, 0, 0xe0, 80}, /* tfgoal guessed */
1016 { 50, 1, 6, 0, 0xe0, 64}, /* 50.05 MHz */
1017 { 57, 2, 11, 0, 0xe0, 53}, /* 57.272 MHz tfgoal guessed */
1018 { 75, 0, 4, 3, 0xe0, 43}, /* 75.08 MHz */
1019 {100, 0, 6, 0, 0xe0, 32}, /* 100.10 MHz */
1020 { 0, 0, 0, 0, 0, 0},
1023 /* 16MHz Crystal PLL Table */
1024 // Commented out values are untested, and often incorrect. these come from docs
1025 // Be sure to check they actually generate the right frequencies (eg. the
1026 // commented out 100 MHz entry appears to generate 97MHz
1027 static struct w100_pll_info xtal_16000000
[] = {
1028 /*freq M N_int N_fac tfgoal lock_time */
1029 // { 30, 1, 2, 7, 0xe0, 119}, /* 36.00 MHz */
1030 // { 35, 1, 3, 2, 0xe0, 102}, /* 36.00 MHz */
1031 // { 40, 1, 4, 0, 0xe0, 90}, /* 40.00 MHz */
1032 // { 45, 3, 10, 3, 0xe0, 80}, /* 45.00 MHz */
1033 { 45, 4, 13, 0, 0xe0, 80}, /* 44.8MHz tfgoal guessed */
1034 // { 48, 1, 5, 0, 0xe0, 75}, /* 48.00 MHz */
1035 // { 50, 3, 11, 1, 0xe0, 72}, /* 50.29 MHz */
1036 // { 55, 3, 12, 7, 0xe0, 65}, /* 55.00 MHz */
1037 // { 60, 0, 2, 7, 0xe0, 60}, /* 60.00 MHz */
1038 // { 65, 1, 7, 3, 0xe0, 55}, /* 64.00 MHz */
1039 // { 70, 1, 7, 7, 0xe0, 51}, /* 69.28 MHz */
1040 { 72, 1, 8, 0, 0xe0, 48}, /* tfgoal guessed */
1041 // { 75, 1, 8, 2, 0xe0, 48}, /* 74.67 MHz */
1042 // { 80, 1, 9, 0, 0xe0, 45}, /* 80.00 MHz */
1043 // { 85, 1, 9, 6, 0xe0, 42}, /* 85.33 MHz */
1044 // { 90, 0, 4, 6, 0xe0, 40}, /* 89.60 MHz */
1045 { 95, 1, 10, 7, 0xe0, 38}, /* 96.00 MHz */
1046 // { 96, 1, 11, 0, 0xe0, 36}, /* tfgoal guessed */
1047 // {100, 1, 11, 1, 0xe0, 36}, /* 100.00 MHz */
1048 {100, 1, 11, 4, 0xe0, 36}, /* tfgoal guessed */
1049 // {105, 1, 12, 7, 0xe0, 34}, /* 100.00 MHz */
1050 // {110, 1, 12, 7, 0xe0, 33}, /* 112.00 MHz */
1051 // {115, 1, 13, 2, 0xe0, 31}, /* 112.00 MHz */
1052 // {120, 1, 14, 0, 0xe0, 30}, /* 120.00 MHz */
1053 // {125, 1, 14, 6, 0xe0, 29}, /* 120.00 MHz */
1054 {128, 1, 16, 0, 0xe0, 48}, /* tfgoal guessed */
1055 // {130, 1, 15, 3, 0xe0, 28}, /* 128.00 MHz */
1056 // {135, 1, 15, 7, 0xe0, 27}, /* 128.00 MHz */
1057 // {140, 0, 7, 7, 0xe0, 26}, /* 140.00 MHz */
1058 // {145, 0, 8, 0, 0xe0, 25}, /* 140.00 MHz */
1059 // {150, 0, 8, 2, 0xe0, 24}, /* 149.28 MHz */
1060 // {155, 0, 8, 6, 0xe0, 23}, /* 149.28 MHz */
1061 // {160, 0, 9, 0, 0xe0, 22}, /* 160.00 MHz */
1062 { 0, 0, 0, 0, 0, 0},
1065 static struct pll_entries
{
1067 struct w100_pll_info
*pll_table
;
1068 } w100_pll_tables
[] = {
1069 { 12500000, &xtal_12500000
[0] },
1070 { 14318000, &xtal_14318000
[0] },
1071 { 16000000, &xtal_16000000
[0] },
1075 struct w100_pll_info
*w100_get_xtal_table(unsigned int freq
)
1077 struct pll_entries
*pll_entry
= w100_pll_tables
;
1080 if (freq
== pll_entry
->xtal_freq
)
1081 return pll_entry
->pll_table
;
1083 } while (pll_entry
->xtal_freq
);
1088 static unsigned int w100_get_testcount(unsigned int testclk_sel
)
1090 union clk_test_cntl_u clk_test_cntl
;
1094 /* Select the test clock source and reset */
1095 clk_test_cntl
.f
.start_check_freq
= 0x0;
1096 clk_test_cntl
.f
.testclk_sel
= testclk_sel
;
1097 clk_test_cntl
.f
.tstcount_rst
= 0x1; /* set reset */
1098 writel((u32
) (clk_test_cntl
.val
), remapped_regs
+ mmCLK_TEST_CNTL
);
1100 clk_test_cntl
.f
.tstcount_rst
= 0x0; /* clear reset */
1101 writel((u32
) (clk_test_cntl
.val
), remapped_regs
+ mmCLK_TEST_CNTL
);
1103 /* Run clock test */
1104 clk_test_cntl
.f
.start_check_freq
= 0x1;
1105 writel((u32
) (clk_test_cntl
.val
), remapped_regs
+ mmCLK_TEST_CNTL
);
1107 /* Give the test time to complete */
1110 /* Return the result */
1111 clk_test_cntl
.val
= readl(remapped_regs
+ mmCLK_TEST_CNTL
);
1112 clk_test_cntl
.f
.start_check_freq
= 0x0;
1113 writel((u32
) (clk_test_cntl
.val
), remapped_regs
+ mmCLK_TEST_CNTL
);
1115 return clk_test_cntl
.f
.test_count
;
1119 static int w100_pll_adjust(struct w100_pll_info
*pll
)
1124 /* Initial Settings */
1125 w100_pwr_state
.pll_cntl
.f
.pll_pwdn
= 0x0; /* power down */
1126 w100_pwr_state
.pll_cntl
.f
.pll_reset
= 0x0; /* not reset */
1127 w100_pwr_state
.pll_cntl
.f
.pll_tcpoff
= 0x1; /* Hi-Z */
1128 w100_pwr_state
.pll_cntl
.f
.pll_pvg
= 0x0; /* VCO gain = 0 */
1129 w100_pwr_state
.pll_cntl
.f
.pll_vcofr
= 0x0; /* VCO frequency range control = off */
1130 w100_pwr_state
.pll_cntl
.f
.pll_ioffset
= 0x0; /* current offset inside VCO = 0 */
1131 w100_pwr_state
.pll_cntl
.f
.pll_ring_off
= 0x0;
1133 /* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V
1134 * therefore, commented out the following lines
1138 /* set VCO input = 0.8 * VDD */
1139 w100_pwr_state
.pll_cntl
.f
.pll_dactal
= 0xd;
1140 writel((u32
) (w100_pwr_state
.pll_cntl
.val
), remapped_regs
+ mmPLL_CNTL
);
1142 tf80
= w100_get_testcount(TESTCLK_SRC_PLL
);
1143 if (tf80
>= (pll
->tfgoal
)) {
1144 /* set VCO input = 0.2 * VDD */
1145 w100_pwr_state
.pll_cntl
.f
.pll_dactal
= 0x7;
1146 writel((u32
) (w100_pwr_state
.pll_cntl
.val
), remapped_regs
+ mmPLL_CNTL
);
1148 tf20
= w100_get_testcount(TESTCLK_SRC_PLL
);
1149 if (tf20
<= (pll
->tfgoal
))
1150 return 1; /* Success */
1152 if ((w100_pwr_state
.pll_cntl
.f
.pll_vcofr
== 0x0) &&
1153 ((w100_pwr_state
.pll_cntl
.f
.pll_pvg
== 0x7) ||
1154 (w100_pwr_state
.pll_cntl
.f
.pll_ioffset
== 0x0))) {
1155 /* slow VCO config */
1156 w100_pwr_state
.pll_cntl
.f
.pll_vcofr
= 0x1;
1157 w100_pwr_state
.pll_cntl
.f
.pll_pvg
= 0x0;
1158 w100_pwr_state
.pll_cntl
.f
.pll_ioffset
= 0x0;
1162 if ((w100_pwr_state
.pll_cntl
.f
.pll_ioffset
) < 0x3) {
1163 w100_pwr_state
.pll_cntl
.f
.pll_ioffset
+= 0x1;
1164 } else if ((w100_pwr_state
.pll_cntl
.f
.pll_pvg
) < 0x7) {
1165 w100_pwr_state
.pll_cntl
.f
.pll_ioffset
= 0x0;
1166 w100_pwr_state
.pll_cntl
.f
.pll_pvg
+= 0x1;
1168 return 0; /* Error */
1175 * w100_pll_calibration
1177 static int w100_pll_calibration(struct w100_pll_info
*pll
)
1181 status
= w100_pll_adjust(pll
);
1183 /* PLL Reset And Lock */
1184 /* set VCO input = 0.5 * VDD */
1185 w100_pwr_state
.pll_cntl
.f
.pll_dactal
= 0xa;
1186 writel((u32
) (w100_pwr_state
.pll_cntl
.val
), remapped_regs
+ mmPLL_CNTL
);
1188 udelay(1); /* reset time */
1190 /* enable charge pump */
1191 w100_pwr_state
.pll_cntl
.f
.pll_tcpoff
= 0x0; /* normal */
1192 writel((u32
) (w100_pwr_state
.pll_cntl
.val
), remapped_regs
+ mmPLL_CNTL
);
1194 /* set VCO input = Hi-Z, disable DAC */
1195 w100_pwr_state
.pll_cntl
.f
.pll_dactal
= 0x0;
1196 writel((u32
) (w100_pwr_state
.pll_cntl
.val
), remapped_regs
+ mmPLL_CNTL
);
1198 udelay(400); /* lock time */
1206 static int w100_pll_set_clk(struct w100_pll_info
*pll
)
1210 if (w100_pwr_state
.auto_mode
== 1) /* auto mode */
1212 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_fast_noml_hw_en
= 0x0; /* disable fast to normal */
1213 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_noml_fast_hw_en
= 0x0; /* disable normal to fast */
1214 writel((u32
) (w100_pwr_state
.pwrmgt_cntl
.val
), remapped_regs
+ mmPWRMGT_CNTL
);
1217 /* Set system clock source to XTAL whilst adjusting the PLL! */
1218 w100_pwr_state
.sclk_cntl
.f
.sclk_src_sel
= CLK_SRC_XTAL
;
1219 writel((u32
) (w100_pwr_state
.sclk_cntl
.val
), remapped_regs
+ mmSCLK_CNTL
);
1221 w100_pwr_state
.pll_ref_fb_div
.f
.pll_ref_div
= pll
->M
;
1222 w100_pwr_state
.pll_ref_fb_div
.f
.pll_fb_div_int
= pll
->N_int
;
1223 w100_pwr_state
.pll_ref_fb_div
.f
.pll_fb_div_frac
= pll
->N_fac
;
1224 w100_pwr_state
.pll_ref_fb_div
.f
.pll_lock_time
= pll
->lock_time
;
1225 writel((u32
) (w100_pwr_state
.pll_ref_fb_div
.val
), remapped_regs
+ mmPLL_REF_FB_DIV
);
1227 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_mode_req
= 0;
1228 writel((u32
) (w100_pwr_state
.pwrmgt_cntl
.val
), remapped_regs
+ mmPWRMGT_CNTL
);
1230 status
= w100_pll_calibration(pll
);
1232 if (w100_pwr_state
.auto_mode
== 1) /* auto mode */
1234 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_fast_noml_hw_en
= 0x1; /* reenable fast to normal */
1235 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_noml_fast_hw_en
= 0x1; /* reenable normal to fast */
1236 writel((u32
) (w100_pwr_state
.pwrmgt_cntl
.val
), remapped_regs
+ mmPWRMGT_CNTL
);
1241 /* freq = target frequency of the PLL */
1242 static int w100_set_pll_freq(struct w100fb_par
*par
, unsigned int freq
)
1244 struct w100_pll_info
*pll
= par
->pll_table
;
1247 if (freq
== pll
->freq
) {
1248 return w100_pll_set_clk(pll
);
1255 /* Set up an initial state. Some values/fields set
1256 here will be overwritten. */
1257 static void w100_pwm_setup(struct w100fb_par
*par
)
1259 w100_pwr_state
.clk_pin_cntl
.f
.osc_en
= 0x1;
1260 w100_pwr_state
.clk_pin_cntl
.f
.osc_gain
= 0x1f;
1261 w100_pwr_state
.clk_pin_cntl
.f
.dont_use_xtalin
= 0x0;
1262 w100_pwr_state
.clk_pin_cntl
.f
.xtalin_pm_en
= 0x0;
1263 w100_pwr_state
.clk_pin_cntl
.f
.xtalin_dbl_en
= par
->mach
->xtal_dbl
? 1 : 0;
1264 w100_pwr_state
.clk_pin_cntl
.f
.cg_debug
= 0x0;
1265 writel((u32
) (w100_pwr_state
.clk_pin_cntl
.val
), remapped_regs
+ mmCLK_PIN_CNTL
);
1267 w100_pwr_state
.sclk_cntl
.f
.sclk_src_sel
= CLK_SRC_XTAL
;
1268 w100_pwr_state
.sclk_cntl
.f
.sclk_post_div_fast
= 0x0; /* Pfast = 1 */
1269 w100_pwr_state
.sclk_cntl
.f
.sclk_clkon_hys
= 0x3;
1270 w100_pwr_state
.sclk_cntl
.f
.sclk_post_div_slow
= 0x0; /* Pslow = 1 */
1271 w100_pwr_state
.sclk_cntl
.f
.disp_cg_ok2switch_en
= 0x0;
1272 w100_pwr_state
.sclk_cntl
.f
.sclk_force_reg
= 0x0; /* Dynamic */
1273 w100_pwr_state
.sclk_cntl
.f
.sclk_force_disp
= 0x0; /* Dynamic */
1274 w100_pwr_state
.sclk_cntl
.f
.sclk_force_mc
= 0x0; /* Dynamic */
1275 w100_pwr_state
.sclk_cntl
.f
.sclk_force_extmc
= 0x0; /* Dynamic */
1276 w100_pwr_state
.sclk_cntl
.f
.sclk_force_cp
= 0x0; /* Dynamic */
1277 w100_pwr_state
.sclk_cntl
.f
.sclk_force_e2
= 0x0; /* Dynamic */
1278 w100_pwr_state
.sclk_cntl
.f
.sclk_force_e3
= 0x0; /* Dynamic */
1279 w100_pwr_state
.sclk_cntl
.f
.sclk_force_idct
= 0x0; /* Dynamic */
1280 w100_pwr_state
.sclk_cntl
.f
.sclk_force_bist
= 0x0; /* Dynamic */
1281 w100_pwr_state
.sclk_cntl
.f
.busy_extend_cp
= 0x0;
1282 w100_pwr_state
.sclk_cntl
.f
.busy_extend_e2
= 0x0;
1283 w100_pwr_state
.sclk_cntl
.f
.busy_extend_e3
= 0x0;
1284 w100_pwr_state
.sclk_cntl
.f
.busy_extend_idct
= 0x0;
1285 writel((u32
) (w100_pwr_state
.sclk_cntl
.val
), remapped_regs
+ mmSCLK_CNTL
);
1287 w100_pwr_state
.pclk_cntl
.f
.pclk_src_sel
= CLK_SRC_XTAL
;
1288 w100_pwr_state
.pclk_cntl
.f
.pclk_post_div
= 0x1; /* P = 2 */
1289 w100_pwr_state
.pclk_cntl
.f
.pclk_force_disp
= 0x0; /* Dynamic */
1290 writel((u32
) (w100_pwr_state
.pclk_cntl
.val
), remapped_regs
+ mmPCLK_CNTL
);
1292 w100_pwr_state
.pll_ref_fb_div
.f
.pll_ref_div
= 0x0; /* M = 1 */
1293 w100_pwr_state
.pll_ref_fb_div
.f
.pll_fb_div_int
= 0x0; /* N = 1.0 */
1294 w100_pwr_state
.pll_ref_fb_div
.f
.pll_fb_div_frac
= 0x0;
1295 w100_pwr_state
.pll_ref_fb_div
.f
.pll_reset_time
= 0x5;
1296 w100_pwr_state
.pll_ref_fb_div
.f
.pll_lock_time
= 0xff;
1297 writel((u32
) (w100_pwr_state
.pll_ref_fb_div
.val
), remapped_regs
+ mmPLL_REF_FB_DIV
);
1299 w100_pwr_state
.pll_cntl
.f
.pll_pwdn
= 0x1;
1300 w100_pwr_state
.pll_cntl
.f
.pll_reset
= 0x1;
1301 w100_pwr_state
.pll_cntl
.f
.pll_pm_en
= 0x0;
1302 w100_pwr_state
.pll_cntl
.f
.pll_mode
= 0x0; /* uses VCO clock */
1303 w100_pwr_state
.pll_cntl
.f
.pll_refclk_sel
= 0x0;
1304 w100_pwr_state
.pll_cntl
.f
.pll_fbclk_sel
= 0x0;
1305 w100_pwr_state
.pll_cntl
.f
.pll_tcpoff
= 0x0;
1306 w100_pwr_state
.pll_cntl
.f
.pll_pcp
= 0x4;
1307 w100_pwr_state
.pll_cntl
.f
.pll_pvg
= 0x0;
1308 w100_pwr_state
.pll_cntl
.f
.pll_vcofr
= 0x0;
1309 w100_pwr_state
.pll_cntl
.f
.pll_ioffset
= 0x0;
1310 w100_pwr_state
.pll_cntl
.f
.pll_pecc_mode
= 0x0;
1311 w100_pwr_state
.pll_cntl
.f
.pll_pecc_scon
= 0x0;
1312 w100_pwr_state
.pll_cntl
.f
.pll_dactal
= 0x0; /* Hi-Z */
1313 w100_pwr_state
.pll_cntl
.f
.pll_cp_clip
= 0x3;
1314 w100_pwr_state
.pll_cntl
.f
.pll_conf
= 0x2;
1315 w100_pwr_state
.pll_cntl
.f
.pll_mbctrl
= 0x2;
1316 w100_pwr_state
.pll_cntl
.f
.pll_ring_off
= 0x0;
1317 writel((u32
) (w100_pwr_state
.pll_cntl
.val
), remapped_regs
+ mmPLL_CNTL
);
1319 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_enable
= 0x0;
1320 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_mode_req
= 0x1; /* normal mode (0, 1, 3) */
1321 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_wakeup_cond
= 0x0;
1322 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_fast_noml_hw_en
= 0x0;
1323 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_noml_fast_hw_en
= 0x0;
1324 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_fast_noml_cond
= 0x1; /* PM4,ENG */
1325 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_noml_fast_cond
= 0x1; /* PM4,ENG */
1326 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_idle_timer
= 0xFF;
1327 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_busy_timer
= 0xFF;
1328 writel((u32
) (w100_pwr_state
.pwrmgt_cntl
.val
), remapped_regs
+ mmPWRMGT_CNTL
);
1330 w100_pwr_state
.auto_mode
= 0; /* manual mode */
1335 * Setup the w100 clocks for the specified mode
1337 static void w100_init_clocks(struct w100fb_par
*par
)
1339 struct w100_mode
*mode
= par
->mode
;
1341 if (mode
->pixclk_src
== CLK_SRC_PLL
|| mode
->sysclk_src
== CLK_SRC_PLL
)
1342 w100_set_pll_freq(par
, (par
->fastpll_mode
&& mode
->fast_pll_freq
) ? mode
->fast_pll_freq
: mode
->pll_freq
);
1344 w100_pwr_state
.sclk_cntl
.f
.sclk_src_sel
= mode
->sysclk_src
;
1345 w100_pwr_state
.sclk_cntl
.f
.sclk_post_div_fast
= mode
->sysclk_divider
;
1346 w100_pwr_state
.sclk_cntl
.f
.sclk_post_div_slow
= mode
->sysclk_divider
;
1347 writel((u32
) (w100_pwr_state
.sclk_cntl
.val
), remapped_regs
+ mmSCLK_CNTL
);
1350 static void w100_init_lcd(struct w100fb_par
*par
)
1353 struct w100_mode
*mode
= par
->mode
;
1354 struct w100_gen_regs
*regs
= par
->mach
->regs
;
1355 union active_h_disp_u active_h_disp
;
1356 union active_v_disp_u active_v_disp
;
1357 union graphic_h_disp_u graphic_h_disp
;
1358 union graphic_v_disp_u graphic_v_disp
;
1359 union crtc_total_u crtc_total
;
1361 /* w3200 doesnt like undefined bits being set so zero register values first */
1363 active_h_disp
.val
= 0;
1364 active_h_disp
.f
.active_h_start
=mode
->left_margin
;
1365 active_h_disp
.f
.active_h_end
=mode
->left_margin
+ mode
->xres
;
1366 writel(active_h_disp
.val
, remapped_regs
+ mmACTIVE_H_DISP
);
1368 active_v_disp
.val
= 0;
1369 active_v_disp
.f
.active_v_start
=mode
->upper_margin
;
1370 active_v_disp
.f
.active_v_end
=mode
->upper_margin
+ mode
->yres
;
1371 writel(active_v_disp
.val
, remapped_regs
+ mmACTIVE_V_DISP
);
1373 graphic_h_disp
.val
= 0;
1374 graphic_h_disp
.f
.graphic_h_start
=mode
->left_margin
;
1375 graphic_h_disp
.f
.graphic_h_end
=mode
->left_margin
+ mode
->xres
;
1376 writel(graphic_h_disp
.val
, remapped_regs
+ mmGRAPHIC_H_DISP
);
1378 graphic_v_disp
.val
= 0;
1379 graphic_v_disp
.f
.graphic_v_start
=mode
->upper_margin
;
1380 graphic_v_disp
.f
.graphic_v_end
=mode
->upper_margin
+ mode
->yres
;
1381 writel(graphic_v_disp
.val
, remapped_regs
+ mmGRAPHIC_V_DISP
);
1384 crtc_total
.f
.crtc_h_total
=mode
->left_margin
+ mode
->xres
+ mode
->right_margin
;
1385 crtc_total
.f
.crtc_v_total
=mode
->upper_margin
+ mode
->yres
+ mode
->lower_margin
;
1386 writel(crtc_total
.val
, remapped_regs
+ mmCRTC_TOTAL
);
1388 writel(mode
->crtc_ss
, remapped_regs
+ mmCRTC_SS
);
1389 writel(mode
->crtc_ls
, remapped_regs
+ mmCRTC_LS
);
1390 writel(mode
->crtc_gs
, remapped_regs
+ mmCRTC_GS
);
1391 writel(mode
->crtc_vpos_gs
, remapped_regs
+ mmCRTC_VPOS_GS
);
1392 writel(mode
->crtc_rev
, remapped_regs
+ mmCRTC_REV
);
1393 writel(mode
->crtc_dclk
, remapped_regs
+ mmCRTC_DCLK
);
1394 writel(mode
->crtc_gclk
, remapped_regs
+ mmCRTC_GCLK
);
1395 writel(mode
->crtc_goe
, remapped_regs
+ mmCRTC_GOE
);
1396 writel(mode
->crtc_ps1_active
, remapped_regs
+ mmCRTC_PS1_ACTIVE
);
1398 writel(regs
->lcd_format
, remapped_regs
+ mmLCD_FORMAT
);
1399 writel(regs
->lcdd_cntl1
, remapped_regs
+ mmLCDD_CNTL1
);
1400 writel(regs
->lcdd_cntl2
, remapped_regs
+ mmLCDD_CNTL2
);
1401 writel(regs
->genlcd_cntl1
, remapped_regs
+ mmGENLCD_CNTL1
);
1402 writel(regs
->genlcd_cntl2
, remapped_regs
+ mmGENLCD_CNTL2
);
1403 writel(regs
->genlcd_cntl3
, remapped_regs
+ mmGENLCD_CNTL3
);
1405 writel(0x00000000, remapped_regs
+ mmCRTC_FRAME
);
1406 writel(0x00000000, remapped_regs
+ mmCRTC_FRAME_VPOS
);
1407 writel(0x00000000, remapped_regs
+ mmCRTC_DEFAULT_COUNT
);
1408 writel(0x0000FF00, remapped_regs
+ mmLCD_BACKGROUND_COLOR
);
1410 /* Hack for overlay in ext memory */
1411 temp32
= readl(remapped_regs
+ mmDISP_DEBUG2
);
1412 temp32
|= 0xc0000000;
1413 writel(temp32
, remapped_regs
+ mmDISP_DEBUG2
);
1417 static void w100_setup_memory(struct w100fb_par
*par
)
1419 union mc_ext_mem_location_u extmem_location
;
1420 union mc_fb_location_u intmem_location
;
1421 struct w100_mem_info
*mem
= par
->mach
->mem
;
1422 struct w100_bm_mem_info
*bm_mem
= par
->mach
->bm_mem
;
1424 if (!par
->extmem_active
) {
1425 w100_suspend(W100_SUSPEND_EXTMEM
);
1427 /* Map Internal Memory at FB Base */
1428 intmem_location
.f
.mc_fb_start
= W100_FB_BASE
>> 8;
1429 intmem_location
.f
.mc_fb_top
= (W100_FB_BASE
+MEM_INT_SIZE
) >> 8;
1430 writel((u32
) (intmem_location
.val
), remapped_regs
+ mmMC_FB_LOCATION
);
1432 /* Unmap External Memory - value is *probably* irrelevant but may have meaning
1433 to acceleration libraries */
1434 extmem_location
.f
.mc_ext_mem_start
= MEM_EXT_BASE_VALUE
>> 8;
1435 extmem_location
.f
.mc_ext_mem_top
= (MEM_EXT_BASE_VALUE
-1) >> 8;
1436 writel((u32
) (extmem_location
.val
), remapped_regs
+ mmMC_EXT_MEM_LOCATION
);
1438 /* Map Internal Memory to its default location */
1439 intmem_location
.f
.mc_fb_start
= MEM_INT_BASE_VALUE
>> 8;
1440 intmem_location
.f
.mc_fb_top
= (MEM_INT_BASE_VALUE
+MEM_INT_SIZE
) >> 8;
1441 writel((u32
) (intmem_location
.val
), remapped_regs
+ mmMC_FB_LOCATION
);
1443 /* Map External Memory at FB Base */
1444 extmem_location
.f
.mc_ext_mem_start
= W100_FB_BASE
>> 8;
1445 extmem_location
.f
.mc_ext_mem_top
= (W100_FB_BASE
+par
->mach
->mem
->size
) >> 8;
1446 writel((u32
) (extmem_location
.val
), remapped_regs
+ mmMC_EXT_MEM_LOCATION
);
1448 writel(0x00007800, remapped_regs
+ mmMC_BIST_CTRL
);
1449 writel(mem
->ext_cntl
, remapped_regs
+ mmMEM_EXT_CNTL
);
1450 writel(0x00200021, remapped_regs
+ mmMEM_SDRAM_MODE_REG
);
1452 writel(0x80200021, remapped_regs
+ mmMEM_SDRAM_MODE_REG
);
1454 writel(mem
->sdram_mode_reg
, remapped_regs
+ mmMEM_SDRAM_MODE_REG
);
1456 writel(mem
->ext_timing_cntl
, remapped_regs
+ mmMEM_EXT_TIMING_CNTL
);
1457 writel(mem
->io_cntl
, remapped_regs
+ mmMEM_IO_CNTL
);
1459 writel(bm_mem
->ext_mem_bw
, remapped_regs
+ mmBM_EXT_MEM_BANDWIDTH
);
1460 writel(bm_mem
->offset
, remapped_regs
+ mmBM_OFFSET
);
1461 writel(bm_mem
->ext_timing_ctl
, remapped_regs
+ mmBM_MEM_EXT_TIMING_CNTL
);
1462 writel(bm_mem
->ext_cntl
, remapped_regs
+ mmBM_MEM_EXT_CNTL
);
1463 writel(bm_mem
->mode_reg
, remapped_regs
+ mmBM_MEM_MODE_REG
);
1464 writel(bm_mem
->io_cntl
, remapped_regs
+ mmBM_MEM_IO_CNTL
);
1465 writel(bm_mem
->config
, remapped_regs
+ mmBM_CONFIG
);
1470 static void w100_set_dispregs(struct w100fb_par
*par
)
1472 unsigned long rot
=0, divider
, offset
=0;
1473 union graphic_ctrl_u graphic_ctrl
;
1475 /* See if the mode has been rotated */
1476 if (par
->xres
== par
->mode
->xres
) {
1478 rot
=3; /* 180 degree */
1479 offset
=(par
->xres
* par
->yres
) - 1;
1480 } /* else 0 degree */
1481 divider
= par
->mode
->pixclk_divider
;
1484 rot
=2; /* 270 degree */
1485 offset
=par
->xres
- 1;
1487 rot
=1; /* 90 degree */
1488 offset
=par
->xres
* (par
->yres
- 1);
1490 divider
= par
->mode
->pixclk_divider_rotated
;
1493 graphic_ctrl
.val
= 0; /* w32xx doesn't like undefined bits */
1494 switch (par
->chip_id
) {
1496 graphic_ctrl
.f_w100
.color_depth
=6;
1497 graphic_ctrl
.f_w100
.en_crtc
=1;
1498 graphic_ctrl
.f_w100
.en_graphic_req
=1;
1499 graphic_ctrl
.f_w100
.en_graphic_crtc
=1;
1500 graphic_ctrl
.f_w100
.lcd_pclk_on
=1;
1501 graphic_ctrl
.f_w100
.lcd_sclk_on
=1;
1502 graphic_ctrl
.f_w100
.low_power_on
=0;
1503 graphic_ctrl
.f_w100
.req_freq
=0;
1504 graphic_ctrl
.f_w100
.total_req_graphic
=par
->mode
->xres
>> 1; // panel xres, not mode
1505 graphic_ctrl
.f_w100
.portrait_mode
=rot
;
1507 /* Zaurus needs this */
1512 graphic_ctrl
.f_w100
.total_req_graphic
=0xa0;
1519 graphic_ctrl
.f_w100
.low_power_on
=1;
1520 graphic_ctrl
.f_w100
.req_freq
=5;
1524 graphic_ctrl
.f_w100
.req_freq
=4;
1529 graphic_ctrl
.f_w100
.total_req_graphic
=0xf0;
1535 graphic_ctrl
.f_w32xx
.color_depth
=6;
1536 graphic_ctrl
.f_w32xx
.en_crtc
=1;
1537 graphic_ctrl
.f_w32xx
.en_graphic_req
=1;
1538 graphic_ctrl
.f_w32xx
.en_graphic_crtc
=1;
1539 graphic_ctrl
.f_w32xx
.lcd_pclk_on
=1;
1540 graphic_ctrl
.f_w32xx
.lcd_sclk_on
=1;
1541 graphic_ctrl
.f_w32xx
.low_power_on
=0;
1542 graphic_ctrl
.f_w32xx
.req_freq
=0;
1543 graphic_ctrl
.f_w32xx
.total_req_graphic
=par
->mode
->xres
>> 1; /* panel xres, not mode */
1544 graphic_ctrl
.f_w32xx
.portrait_mode
=rot
;
1548 /* Set the pixel clock source and divider */
1549 w100_pwr_state
.pclk_cntl
.f
.pclk_src_sel
= par
->mode
->pixclk_src
;
1550 w100_pwr_state
.pclk_cntl
.f
.pclk_post_div
= divider
;
1551 writel((u32
) (w100_pwr_state
.pclk_cntl
.val
), remapped_regs
+ mmPCLK_CNTL
);
1553 writel(graphic_ctrl
.val
, remapped_regs
+ mmGRAPHIC_CTRL
);
1554 writel(W100_FB_BASE
+ ((offset
* BITS_PER_PIXEL
/8)&~0x03UL
), remapped_regs
+ mmGRAPHIC_OFFSET
);
1555 writel((par
->xres
*BITS_PER_PIXEL
/8), remapped_regs
+ mmGRAPHIC_PITCH
);
1560 * Work out how long the sync pulse lasts
1561 * Value is 1/(time in seconds)
1563 static void calc_hsync(struct w100fb_par
*par
)
1565 unsigned long hsync
;
1566 struct w100_mode
*mode
= par
->mode
;
1567 union crtc_ss_u crtc_ss
;
1569 if (mode
->pixclk_src
== CLK_SRC_XTAL
)
1570 hsync
=par
->mach
->xtal_freq
;
1572 hsync
=((par
->fastpll_mode
&& mode
->fast_pll_freq
) ? mode
->fast_pll_freq
: mode
->pll_freq
)*100000;
1574 hsync
/= (w100_pwr_state
.pclk_cntl
.f
.pclk_post_div
+ 1);
1576 crtc_ss
.val
= readl(remapped_regs
+ mmCRTC_SS
);
1578 par
->hsync_len
= hsync
/ (crtc_ss
.f
.ss_end
-crtc_ss
.f
.ss_start
);
1583 static void w100_suspend(u32 mode
)
1587 writel(0x7FFF8000, remapped_regs
+ mmMC_EXT_MEM_LOCATION
);
1588 writel(0x00FF0000, remapped_regs
+ mmMC_PERF_MON_CNTL
);
1590 val
= readl(remapped_regs
+ mmMEM_EXT_TIMING_CNTL
);
1591 val
&= ~(0x00100000); /* bit20=0 */
1592 val
|= 0xFF000000; /* bit31:24=0xff */
1593 writel(val
, remapped_regs
+ mmMEM_EXT_TIMING_CNTL
);
1595 val
= readl(remapped_regs
+ mmMEM_EXT_CNTL
);
1596 val
&= ~(0x00040000); /* bit18=0 */
1597 val
|= 0x00080000; /* bit19=1 */
1598 writel(val
, remapped_regs
+ mmMEM_EXT_CNTL
);
1600 udelay(1); /* wait 1us */
1602 if (mode
== W100_SUSPEND_EXTMEM
) {
1603 /* CKE: Tri-State */
1604 val
= readl(remapped_regs
+ mmMEM_EXT_CNTL
);
1605 val
|= 0x40000000; /* bit30=1 */
1606 writel(val
, remapped_regs
+ mmMEM_EXT_CNTL
);
1609 val
= readl(remapped_regs
+ mmMEM_EXT_CNTL
);
1610 val
&= ~(0x00000001); /* bit0=0 */
1611 writel(val
, remapped_regs
+ mmMEM_EXT_CNTL
);
1613 writel(0x00000000, remapped_regs
+ mmSCLK_CNTL
);
1614 writel(0x000000BF, remapped_regs
+ mmCLK_PIN_CNTL
);
1615 writel(0x00000015, remapped_regs
+ mmPWRMGT_CNTL
);
1619 val
= readl(remapped_regs
+ mmPLL_CNTL
);
1620 val
|= 0x00000004; /* bit2=1 */
1621 writel(val
, remapped_regs
+ mmPLL_CNTL
);
1622 writel(0x0000001d, remapped_regs
+ mmPWRMGT_CNTL
);
1626 static void w100_vsync(void)
1629 int timeout
= 30000; /* VSync timeout = 30[ms] > 16.8[ms] */
1631 tmp
= readl(remapped_regs
+ mmACTIVE_V_DISP
);
1634 writel((tmp
>> 16) & 0x3ff, remapped_regs
+ mmDISP_INT_CNTL
);
1636 /* disable vline irq */
1637 tmp
= readl(remapped_regs
+ mmGEN_INT_CNTL
);
1640 writel(tmp
, remapped_regs
+ mmGEN_INT_CNTL
);
1642 /* clear vline irq status */
1643 writel(0x00000002, remapped_regs
+ mmGEN_INT_STATUS
);
1645 /* enable vline irq */
1646 writel((tmp
| 0x00000002), remapped_regs
+ mmGEN_INT_CNTL
);
1648 /* clear vline irq status */
1649 writel(0x00000002, remapped_regs
+ mmGEN_INT_STATUS
);
1651 while(timeout
> 0) {
1652 if (readl(remapped_regs
+ mmGEN_INT_STATUS
) & 0x00000002)
1658 /* disable vline irq */
1659 writel(tmp
, remapped_regs
+ mmGEN_INT_CNTL
);
1661 /* clear vline irq status */
1662 writel(0x00000002, remapped_regs
+ mmGEN_INT_STATUS
);
1665 static struct platform_driver w100fb_driver
= {
1666 .probe
= w100fb_probe
,
1667 .remove
= w100fb_remove
,
1668 .suspend
= w100fb_suspend
,
1669 .resume
= w100fb_resume
,
1675 int __devinit
w100fb_init(void)
1677 return platform_driver_register(&w100fb_driver
);
1680 void __exit
w100fb_cleanup(void)
1682 platform_driver_unregister(&w100fb_driver
);
1685 module_init(w100fb_init
);
1686 module_exit(w100fb_cleanup
);
1688 MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
1689 MODULE_LICENSE("GPL");