2 * linux/drivers/video/w100fb.c
4 * Frame Buffer Device for ATI Imageon w100 (Wallaby)
6 * Copyright (C) 2002, ATI Corp.
7 * Copyright (C) 2004-2006 Richard Purdie
8 * Copyright (c) 2005 Ian Molton
9 * Copyright (c) 2006 Alberto Mardegan
11 * Rewritten for 2.6 by Richard Purdie <rpurdie@rpsys.net>
13 * Generic platform support by Ian Molton <spyro@f2s.com>
14 * and Richard Purdie <rpurdie@rpsys.net>
16 * w32xx support by Ian Molton
18 * Hardware acceleration support by Alberto Mardegan
19 * <mardy@users.sourceforge.net>
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License version 2 as
23 * published by the Free Software Foundation.
27 #include <linux/delay.h>
29 #include <linux/init.h>
30 #include <linux/kernel.h>
32 #include <linux/platform_device.h>
33 #include <linux/slab.h>
34 #include <linux/string.h>
35 #include <linux/vmalloc.h>
37 #include <asm/uaccess.h>
38 #include <video/w100fb.h>
44 static void w100_suspend(u32 mode
);
45 static void w100_vsync(void);
46 static void w100_hw_init(struct w100fb_par
*);
47 static void w100_pwm_setup(struct w100fb_par
*);
48 static void w100_init_clocks(struct w100fb_par
*);
49 static void w100_setup_memory(struct w100fb_par
*);
50 static void w100_init_lcd(struct w100fb_par
*);
51 static void w100_set_dispregs(struct w100fb_par
*);
52 static void w100_update_enable(void);
53 static void w100_update_disable(void);
54 static void calc_hsync(struct w100fb_par
*par
);
55 static void w100_init_graphic_engine(struct w100fb_par
*par
);
56 struct w100_pll_info
*w100_get_xtal_table(unsigned int freq
);
58 /* Pseudo palette size */
59 #define MAX_PALETTES 16
61 #define W100_SUSPEND_EXTMEM 0
62 #define W100_SUSPEND_ALL 1
64 #define BITS_PER_PIXEL 16
66 /* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */
67 static void *remapped_base
;
68 static void *remapped_regs
;
69 static void *remapped_fbuf
;
71 #define REMAPPED_FB_LEN 0x15ffff
73 /* This is the offset in the w100's address space we map the current
74 framebuffer memory to. We use the position of external memory as
75 we can remap internal memory to there if external isn't present. */
76 #define W100_FB_BASE MEM_EXT_BASE_VALUE
82 static ssize_t
flip_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
84 struct fb_info
*info
= dev_get_drvdata(dev
);
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
)
93 struct fb_info
*info
= dev_get_drvdata(dev
);
94 struct w100fb_par
*par
=info
->par
;
96 flip
= simple_strtoul(buf
, NULL
, 10);
103 w100_update_disable();
104 w100_set_dispregs(par
);
105 w100_update_enable();
112 static DEVICE_ATTR(flip
, 0644, flip_show
, flip_store
);
114 static ssize_t
w100fb_reg_read(struct device
*dev
, struct device_attribute
*attr
, const char *buf
, size_t count
)
116 unsigned long regs
, param
;
117 regs
= simple_strtoul(buf
, NULL
, 16);
118 param
= readl(remapped_regs
+ regs
);
119 printk("Read Register 0x%08lX: 0x%08lX\n", regs
, param
);
123 static DEVICE_ATTR(reg_read
, 0200, NULL
, w100fb_reg_read
);
125 static ssize_t
w100fb_reg_write(struct device
*dev
, struct device_attribute
*attr
, const char *buf
, size_t count
)
127 unsigned long regs
, param
;
128 sscanf(buf
, "%lx %lx", ®s
, ¶m
);
130 if (regs
<= 0x2000) {
131 printk("Write Register 0x%08lX: 0x%08lX\n", regs
, param
);
132 writel(param
, remapped_regs
+ regs
);
138 static DEVICE_ATTR(reg_write
, 0200, NULL
, w100fb_reg_write
);
141 static ssize_t
fastpllclk_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
143 struct fb_info
*info
= dev_get_drvdata(dev
);
144 struct w100fb_par
*par
=info
->par
;
146 return sprintf(buf
, "%d\n",par
->fastpll_mode
);
149 static ssize_t
fastpllclk_store(struct device
*dev
, struct device_attribute
*attr
, const char *buf
, size_t count
)
151 struct fb_info
*info
= dev_get_drvdata(dev
);
152 struct w100fb_par
*par
=info
->par
;
154 if (simple_strtoul(buf
, NULL
, 10) > 0) {
156 printk("w100fb: Using fast system clock (if possible)\n");
159 printk("w100fb: Using normal system clock\n");
162 w100_init_clocks(par
);
168 static DEVICE_ATTR(fastpllclk
, 0644, fastpllclk_show
, fastpllclk_store
);
171 * Some touchscreens need hsync information from the video driver to
172 * function correctly. We export it here.
174 unsigned long w100fb_get_hsynclen(struct device
*dev
)
176 struct fb_info
*info
= dev_get_drvdata(dev
);
177 struct w100fb_par
*par
=info
->par
;
179 /* If display is blanked/suspended, hsync isn't active */
183 return par
->hsync_len
;
185 EXPORT_SYMBOL(w100fb_get_hsynclen
);
187 static void w100fb_clear_screen(struct w100fb_par
*par
)
189 memset_io(remapped_fbuf
+ (W100_FB_BASE
-MEM_WINDOW_BASE
), 0, (par
->xres
* par
->yres
* BITS_PER_PIXEL
/8));
194 * Set a palette value from rgb components
196 static int w100fb_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
197 u_int trans
, struct fb_info
*info
)
203 * If greyscale is true, then we convert the RGB value
204 * to greyscale no matter what visual we are using.
206 if (info
->var
.grayscale
)
207 red
= green
= blue
= (19595 * red
+ 38470 * green
+ 7471 * blue
) >> 16;
210 * 16-bit True Colour. We encode the RGB value
211 * according to the RGB bitfield information.
213 if (regno
< MAX_PALETTES
) {
214 u32
*pal
= info
->pseudo_palette
;
216 val
= (red
& 0xf800) | ((green
& 0xfc00) >> 5) | ((blue
& 0xf800) >> 11);
225 * Blank the display based on value in blank_mode
227 static int w100fb_blank(int blank_mode
, struct fb_info
*info
)
229 struct w100fb_par
*par
= info
->par
;
230 struct w100_tg_info
*tg
= par
->mach
->tg
;
234 case FB_BLANK_NORMAL
: /* Normal blanking */
235 case FB_BLANK_VSYNC_SUSPEND
: /* VESA blank (vsync off) */
236 case FB_BLANK_HSYNC_SUSPEND
: /* VESA blank (hsync off) */
237 case FB_BLANK_POWERDOWN
: /* Poweroff */
238 if (par
->blanked
== 0) {
239 if(tg
&& tg
->suspend
)
245 case FB_BLANK_UNBLANK
: /* Unblanking */
246 if (par
->blanked
!= 0) {
257 static void w100_fifo_wait(int entries
)
259 union rbbm_status_u status
;
262 for (i
= 0; i
< 2000000; i
++) {
263 status
.val
= readl(remapped_regs
+ mmRBBM_STATUS
);
264 if (status
.f
.cmdfifo_avail
>= entries
)
268 printk(KERN_ERR
"w100fb: FIFO Timeout!\n");
272 static int w100fb_sync(struct fb_info
*info
)
274 union rbbm_status_u status
;
277 for (i
= 0; i
< 2000000; i
++) {
278 status
.val
= readl(remapped_regs
+ mmRBBM_STATUS
);
279 if (!status
.f
.gui_active
)
283 printk(KERN_ERR
"w100fb: Graphic engine timeout!\n");
288 static void w100_init_graphic_engine(struct w100fb_par
*par
)
290 union dp_gui_master_cntl_u gmc
;
291 union dp_mix_u dp_mix
;
292 union dp_datatype_u dp_datatype
;
293 union dp_cntl_u dp_cntl
;
296 writel(W100_FB_BASE
, remapped_regs
+ mmDST_OFFSET
);
297 writel(par
->xres
, remapped_regs
+ mmDST_PITCH
);
298 writel(W100_FB_BASE
, remapped_regs
+ mmSRC_OFFSET
);
299 writel(par
->xres
, remapped_regs
+ mmSRC_PITCH
);
302 writel(0, remapped_regs
+ mmSC_TOP_LEFT
);
303 writel((par
->yres
<< 16) | par
->xres
, remapped_regs
+ mmSC_BOTTOM_RIGHT
);
304 writel(0x1fff1fff, remapped_regs
+ mmSRC_SC_BOTTOM_RIGHT
);
308 dp_cntl
.f
.dst_x_dir
= 1;
309 dp_cntl
.f
.dst_y_dir
= 1;
310 dp_cntl
.f
.src_x_dir
= 1;
311 dp_cntl
.f
.src_y_dir
= 1;
312 dp_cntl
.f
.dst_major_x
= 1;
313 dp_cntl
.f
.src_major_x
= 1;
314 writel(dp_cntl
.val
, remapped_regs
+ mmDP_CNTL
);
317 gmc
.f
.gmc_src_pitch_offset_cntl
= 1;
318 gmc
.f
.gmc_dst_pitch_offset_cntl
= 1;
319 gmc
.f
.gmc_src_clipping
= 1;
320 gmc
.f
.gmc_dst_clipping
= 1;
321 gmc
.f
.gmc_brush_datatype
= GMC_BRUSH_NONE
;
322 gmc
.f
.gmc_dst_datatype
= 3; /* from DstType_16Bpp_444 */
323 gmc
.f
.gmc_src_datatype
= SRC_DATATYPE_EQU_DST
;
324 gmc
.f
.gmc_byte_pix_order
= 1;
325 gmc
.f
.gmc_default_sel
= 0;
326 gmc
.f
.gmc_rop3
= ROP3_SRCCOPY
;
327 gmc
.f
.gmc_dp_src_source
= DP_SRC_MEM_RECTANGULAR
;
328 gmc
.f
.gmc_clr_cmp_fcn_dis
= 1;
329 gmc
.f
.gmc_wr_msk_dis
= 1;
330 gmc
.f
.gmc_dp_op
= DP_OP_ROP
;
331 writel(gmc
.val
, remapped_regs
+ mmDP_GUI_MASTER_CNTL
);
333 dp_datatype
.val
= dp_mix
.val
= 0;
334 dp_datatype
.f
.dp_dst_datatype
= gmc
.f
.gmc_dst_datatype
;
335 dp_datatype
.f
.dp_brush_datatype
= gmc
.f
.gmc_brush_datatype
;
336 dp_datatype
.f
.dp_src2_type
= 0;
337 dp_datatype
.f
.dp_src2_datatype
= gmc
.f
.gmc_src_datatype
;
338 dp_datatype
.f
.dp_src_datatype
= gmc
.f
.gmc_src_datatype
;
339 dp_datatype
.f
.dp_byte_pix_order
= gmc
.f
.gmc_byte_pix_order
;
340 writel(dp_datatype
.val
, remapped_regs
+ mmDP_DATATYPE
);
342 dp_mix
.f
.dp_src_source
= gmc
.f
.gmc_dp_src_source
;
343 dp_mix
.f
.dp_src2_source
= 1;
344 dp_mix
.f
.dp_rop3
= gmc
.f
.gmc_rop3
;
345 dp_mix
.f
.dp_op
= gmc
.f
.gmc_dp_op
;
346 writel(dp_mix
.val
, remapped_regs
+ mmDP_MIX
);
350 static void w100fb_fillrect(struct fb_info
*info
,
351 const struct fb_fillrect
*rect
)
353 union dp_gui_master_cntl_u gmc
;
355 if (info
->state
!= FBINFO_STATE_RUNNING
)
357 if (info
->flags
& FBINFO_HWACCEL_DISABLED
) {
358 cfb_fillrect(info
, rect
);
362 gmc
.val
= readl(remapped_regs
+ mmDP_GUI_MASTER_CNTL
);
363 gmc
.f
.gmc_rop3
= ROP3_PATCOPY
;
364 gmc
.f
.gmc_brush_datatype
= GMC_BRUSH_SOLID_COLOR
;
366 writel(gmc
.val
, remapped_regs
+ mmDP_GUI_MASTER_CNTL
);
367 writel(rect
->color
, remapped_regs
+ mmDP_BRUSH_FRGD_CLR
);
370 writel((rect
->dy
<< 16) | (rect
->dx
& 0xffff), remapped_regs
+ mmDST_Y_X
);
371 writel((rect
->width
<< 16) | (rect
->height
& 0xffff),
372 remapped_regs
+ mmDST_WIDTH_HEIGHT
);
376 static void w100fb_copyarea(struct fb_info
*info
,
377 const struct fb_copyarea
*area
)
379 u32 dx
= area
->dx
, dy
= area
->dy
, sx
= area
->sx
, sy
= area
->sy
;
380 u32 h
= area
->height
, w
= area
->width
;
381 union dp_gui_master_cntl_u gmc
;
383 if (info
->state
!= FBINFO_STATE_RUNNING
)
385 if (info
->flags
& FBINFO_HWACCEL_DISABLED
) {
386 cfb_copyarea(info
, area
);
390 gmc
.val
= readl(remapped_regs
+ mmDP_GUI_MASTER_CNTL
);
391 gmc
.f
.gmc_rop3
= ROP3_SRCCOPY
;
392 gmc
.f
.gmc_brush_datatype
= GMC_BRUSH_NONE
;
394 writel(gmc
.val
, remapped_regs
+ mmDP_GUI_MASTER_CNTL
);
397 writel((sy
<< 16) | (sx
& 0xffff), remapped_regs
+ mmSRC_Y_X
);
398 writel((dy
<< 16) | (dx
& 0xffff), remapped_regs
+ mmDST_Y_X
);
399 writel((w
<< 16) | (h
& 0xffff), remapped_regs
+ mmDST_WIDTH_HEIGHT
);
404 * Change the resolution by calling the appropriate hardware functions
406 static void w100fb_activate_var(struct w100fb_par
*par
)
408 struct w100_tg_info
*tg
= par
->mach
->tg
;
411 w100_setup_memory(par
);
412 w100_init_clocks(par
);
413 w100fb_clear_screen(par
);
416 w100_update_disable();
418 w100_set_dispregs(par
);
419 w100_update_enable();
420 w100_init_graphic_engine(par
);
424 if (!par
->blanked
&& tg
&& tg
->change
)
429 /* Select the smallest mode that allows the desired resolution to be
430 * displayed. If desired, the x and y parameters can be rounded up to
431 * match the selected mode.
433 static struct w100_mode
*w100fb_get_mode(struct w100fb_par
*par
, unsigned int *x
, unsigned int *y
, int saveval
)
435 struct w100_mode
*mode
= NULL
;
436 struct w100_mode
*modelist
= par
->mach
->modelist
;
437 unsigned int best_x
= 0xffffffff, best_y
= 0xffffffff;
440 for (i
= 0 ; i
< par
->mach
->num_modes
; i
++) {
441 if (modelist
[i
].xres
>= *x
&& modelist
[i
].yres
>= *y
&&
442 modelist
[i
].xres
< best_x
&& modelist
[i
].yres
< best_y
) {
443 best_x
= modelist
[i
].xres
;
444 best_y
= modelist
[i
].yres
;
446 } else if(modelist
[i
].xres
>= *y
&& modelist
[i
].yres
>= *x
&&
447 modelist
[i
].xres
< best_y
&& modelist
[i
].yres
< best_x
) {
448 best_x
= modelist
[i
].yres
;
449 best_y
= modelist
[i
].xres
;
454 if (mode
&& saveval
) {
464 * w100fb_check_var():
465 * Get the video params out of 'var'. If a value doesn't fit, round it up,
466 * if it's too big, return -EINVAL.
468 static int w100fb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
470 struct w100fb_par
*par
=info
->par
;
472 if(!w100fb_get_mode(par
, &var
->xres
, &var
->yres
, 1))
475 if (par
->mach
->mem
&& ((var
->xres
*var
->yres
*BITS_PER_PIXEL
/8) > (par
->mach
->mem
->size
+1)))
478 if (!par
->mach
->mem
&& ((var
->xres
*var
->yres
*BITS_PER_PIXEL
/8) > (MEM_INT_SIZE
+1)))
481 var
->xres_virtual
= max(var
->xres_virtual
, var
->xres
);
482 var
->yres_virtual
= max(var
->yres_virtual
, var
->yres
);
484 if (var
->bits_per_pixel
> BITS_PER_PIXEL
)
487 var
->bits_per_pixel
= BITS_PER_PIXEL
;
489 var
->red
.offset
= 11;
491 var
->green
.offset
= 5;
492 var
->green
.length
= 6;
493 var
->blue
.offset
= 0;
494 var
->blue
.length
= 5;
495 var
->transp
.offset
= var
->transp
.length
= 0;
500 var
->vmode
= FB_VMODE_NONINTERLACED
;
502 var
->pixclock
= 0x04; /* 171521; */
510 * Set the user defined part of the display for the specified console
511 * by looking at the values in info.var
513 static int w100fb_set_par(struct fb_info
*info
)
515 struct w100fb_par
*par
=info
->par
;
517 if (par
->xres
!= info
->var
.xres
|| par
->yres
!= info
->var
.yres
) {
518 par
->xres
= info
->var
.xres
;
519 par
->yres
= info
->var
.yres
;
520 par
->mode
= w100fb_get_mode(par
, &par
->xres
, &par
->yres
, 0);
522 info
->fix
.visual
= FB_VISUAL_TRUECOLOR
;
523 info
->fix
.ypanstep
= 0;
524 info
->fix
.ywrapstep
= 0;
525 info
->fix
.line_length
= par
->xres
* BITS_PER_PIXEL
/ 8;
527 mutex_lock(&info
->mm_lock
);
528 if ((par
->xres
*par
->yres
*BITS_PER_PIXEL
/8) > (MEM_INT_SIZE
+1)) {
529 par
->extmem_active
= 1;
530 info
->fix
.smem_len
= par
->mach
->mem
->size
+1;
532 par
->extmem_active
= 0;
533 info
->fix
.smem_len
= MEM_INT_SIZE
+1;
535 mutex_unlock(&info
->mm_lock
);
537 w100fb_activate_var(par
);
544 * Frame buffer operations
546 static struct fb_ops w100fb_ops
= {
547 .owner
= THIS_MODULE
,
548 .fb_check_var
= w100fb_check_var
,
549 .fb_set_par
= w100fb_set_par
,
550 .fb_setcolreg
= w100fb_setcolreg
,
551 .fb_blank
= w100fb_blank
,
552 .fb_fillrect
= w100fb_fillrect
,
553 .fb_copyarea
= w100fb_copyarea
,
554 .fb_imageblit
= cfb_imageblit
,
555 .fb_sync
= w100fb_sync
,
559 static void w100fb_save_vidmem(struct w100fb_par
*par
)
563 if (par
->extmem_active
) {
564 memsize
=par
->mach
->mem
->size
;
565 par
->saved_extmem
= vmalloc(memsize
);
566 if (par
->saved_extmem
)
567 memcpy_fromio(par
->saved_extmem
, remapped_fbuf
+ (W100_FB_BASE
-MEM_WINDOW_BASE
), memsize
);
569 memsize
=MEM_INT_SIZE
;
570 par
->saved_intmem
= vmalloc(memsize
);
571 if (par
->saved_intmem
&& par
->extmem_active
)
572 memcpy_fromio(par
->saved_intmem
, remapped_fbuf
+ (W100_FB_BASE
-MEM_INT_BASE_VALUE
), memsize
);
573 else if (par
->saved_intmem
)
574 memcpy_fromio(par
->saved_intmem
, remapped_fbuf
+ (W100_FB_BASE
-MEM_WINDOW_BASE
), memsize
);
577 static void w100fb_restore_vidmem(struct w100fb_par
*par
)
581 if (par
->extmem_active
&& par
->saved_extmem
) {
582 memsize
=par
->mach
->mem
->size
;
583 memcpy_toio(remapped_fbuf
+ (W100_FB_BASE
-MEM_WINDOW_BASE
), par
->saved_extmem
, memsize
);
584 vfree(par
->saved_extmem
);
586 if (par
->saved_intmem
) {
587 memsize
=MEM_INT_SIZE
;
588 if (par
->extmem_active
)
589 memcpy_toio(remapped_fbuf
+ (W100_FB_BASE
-MEM_INT_BASE_VALUE
), par
->saved_intmem
, memsize
);
591 memcpy_toio(remapped_fbuf
+ (W100_FB_BASE
-MEM_WINDOW_BASE
), par
->saved_intmem
, memsize
);
592 vfree(par
->saved_intmem
);
596 static int w100fb_suspend(struct platform_device
*dev
, pm_message_t state
)
598 struct fb_info
*info
= platform_get_drvdata(dev
);
599 struct w100fb_par
*par
=info
->par
;
600 struct w100_tg_info
*tg
= par
->mach
->tg
;
602 w100fb_save_vidmem(par
);
603 if(tg
&& tg
->suspend
)
605 w100_suspend(W100_SUSPEND_ALL
);
611 static int w100fb_resume(struct platform_device
*dev
)
613 struct fb_info
*info
= platform_get_drvdata(dev
);
614 struct w100fb_par
*par
=info
->par
;
615 struct w100_tg_info
*tg
= par
->mach
->tg
;
618 w100fb_activate_var(par
);
619 w100fb_restore_vidmem(par
);
627 #define w100fb_suspend NULL
628 #define w100fb_resume NULL
632 int __devinit
w100fb_probe(struct platform_device
*pdev
)
635 struct w100fb_mach_info
*inf
;
636 struct fb_info
*info
= NULL
;
637 struct w100fb_par
*par
;
638 struct resource
*mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
639 unsigned int chip_id
;
644 /* Remap the chip base address */
645 remapped_base
= ioremap_nocache(mem
->start
+W100_CFG_BASE
, W100_CFG_LEN
);
646 if (remapped_base
== NULL
)
649 /* Map the register space */
650 remapped_regs
= ioremap_nocache(mem
->start
+W100_REG_BASE
, W100_REG_LEN
);
651 if (remapped_regs
== NULL
)
654 /* Identify the chip */
656 chip_id
= readl(remapped_regs
+ mmCHIP_ID
);
658 case CHIP_ID_W100
: printk("w100"); break;
659 case CHIP_ID_W3200
: printk("w3200"); break;
660 case CHIP_ID_W3220
: printk("w3220"); break;
662 printk("Unknown imageon chip ID\n");
666 printk(" at 0x%08lx.\n", (unsigned long) mem
->start
+W100_CFG_BASE
);
668 /* Remap the framebuffer */
669 remapped_fbuf
= ioremap_nocache(mem
->start
+MEM_WINDOW_BASE
, MEM_WINDOW_SIZE
);
670 if (remapped_fbuf
== NULL
)
673 info
=framebuffer_alloc(sizeof(struct w100fb_par
), &pdev
->dev
);
680 platform_set_drvdata(pdev
, info
);
682 inf
= pdev
->dev
.platform_data
;
683 par
->chip_id
= chip_id
;
685 par
->fastpll_mode
= 0;
688 par
->pll_table
=w100_get_xtal_table(inf
->xtal_freq
);
689 if (!par
->pll_table
) {
690 printk(KERN_ERR
"No matching Xtal definition found\n");
695 info
->pseudo_palette
= kmalloc(sizeof (u32
) * MAX_PALETTES
, GFP_KERNEL
);
696 if (!info
->pseudo_palette
) {
701 info
->fbops
= &w100fb_ops
;
702 info
->flags
= FBINFO_DEFAULT
| FBINFO_HWACCEL_COPYAREA
|
703 FBINFO_HWACCEL_FILLRECT
;
705 info
->screen_base
= remapped_fbuf
+ (W100_FB_BASE
-MEM_WINDOW_BASE
);
706 info
->screen_size
= REMAPPED_FB_LEN
;
708 strcpy(info
->fix
.id
, "w100fb");
709 info
->fix
.type
= FB_TYPE_PACKED_PIXELS
;
710 info
->fix
.type_aux
= 0;
711 info
->fix
.accel
= FB_ACCEL_NONE
;
712 info
->fix
.smem_start
= mem
->start
+W100_FB_BASE
;
713 info
->fix
.mmio_start
= mem
->start
+W100_REG_BASE
;
714 info
->fix
.mmio_len
= W100_REG_LEN
;
716 if (fb_alloc_cmap(&info
->cmap
, 256, 0) < 0) {
721 par
->mode
= &inf
->modelist
[0];
722 if(inf
->init_mode
& INIT_MODE_ROTATED
) {
723 info
->var
.xres
= par
->mode
->yres
;
724 info
->var
.yres
= par
->mode
->xres
;
727 info
->var
.xres
= par
->mode
->xres
;
728 info
->var
.yres
= par
->mode
->yres
;
731 if(inf
->init_mode
&= INIT_MODE_FLIPPED
)
736 info
->var
.xres_virtual
= info
->var
.xres
;
737 info
->var
.yres_virtual
= info
->var
.yres
;
738 info
->var
.pixclock
= 0x04; /* 171521; */
740 info
->var
.grayscale
= 0;
741 info
->var
.xoffset
= info
->var
.yoffset
= 0;
742 info
->var
.accel_flags
= 0;
743 info
->var
.activate
= FB_ACTIVATE_NOW
;
747 if (w100fb_check_var(&info
->var
, info
) < 0) {
752 if (register_framebuffer(info
) < 0) {
757 err
= device_create_file(&pdev
->dev
, &dev_attr_fastpllclk
);
758 err
|= device_create_file(&pdev
->dev
, &dev_attr_reg_read
);
759 err
|= device_create_file(&pdev
->dev
, &dev_attr_reg_write
);
760 err
|= device_create_file(&pdev
->dev
, &dev_attr_flip
);
763 printk(KERN_WARNING
"fb%d: failed to register attributes (%d)\n",
766 printk(KERN_INFO
"fb%d: %s frame buffer device\n", info
->node
, info
->fix
.id
);
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
);
780 framebuffer_release(info
);
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 device_remove_file(&pdev
->dev
, &dev_attr_fastpllclk
);
791 device_remove_file(&pdev
->dev
, &dev_attr_reg_read
);
792 device_remove_file(&pdev
->dev
, &dev_attr_reg_write
);
793 device_remove_file(&pdev
->dev
, &dev_attr_flip
);
795 unregister_framebuffer(info
);
797 vfree(par
->saved_intmem
);
798 vfree(par
->saved_extmem
);
799 kfree(info
->pseudo_palette
);
800 fb_dealloc_cmap(&info
->cmap
);
802 iounmap(remapped_base
);
803 iounmap(remapped_regs
);
804 iounmap(remapped_fbuf
);
806 framebuffer_release(info
);
812 /* ------------------- chipset specific functions -------------------------- */
815 static void w100_soft_reset(void)
817 u16 val
= readw((u16
*) remapped_base
+ cfgSTATUS
);
818 writew(val
| 0x08, (u16
*) remapped_base
+ cfgSTATUS
);
820 writew(0x00, (u16
*) remapped_base
+ cfgSTATUS
);
824 static void w100_update_disable(void)
826 union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl
;
828 /* Prevent display updates */
829 disp_db_buf_wr_cntl
.f
.db_buf_cntl
= 0x1e;
830 disp_db_buf_wr_cntl
.f
.update_db_buf
= 0;
831 disp_db_buf_wr_cntl
.f
.en_db_buf
= 0;
832 writel((u32
) (disp_db_buf_wr_cntl
.val
), remapped_regs
+ mmDISP_DB_BUF_CNTL
);
835 static void w100_update_enable(void)
837 union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl
;
839 /* Enable display updates */
840 disp_db_buf_wr_cntl
.f
.db_buf_cntl
= 0x1e;
841 disp_db_buf_wr_cntl
.f
.update_db_buf
= 1;
842 disp_db_buf_wr_cntl
.f
.en_db_buf
= 1;
843 writel((u32
) (disp_db_buf_wr_cntl
.val
), remapped_regs
+ mmDISP_DB_BUF_CNTL
);
846 unsigned long w100fb_gpio_read(int port
)
850 if (port
==W100_GPIO_PORT_A
)
851 value
= readl(remapped_regs
+ mmGPIO_DATA
);
853 value
= readl(remapped_regs
+ mmGPIO_DATA2
);
858 void w100fb_gpio_write(int port
, unsigned long value
)
860 if (port
==W100_GPIO_PORT_A
)
861 value
= writel(value
, remapped_regs
+ mmGPIO_DATA
);
863 value
= writel(value
, remapped_regs
+ mmGPIO_DATA2
);
865 EXPORT_SYMBOL(w100fb_gpio_read
);
866 EXPORT_SYMBOL(w100fb_gpio_write
);
869 * Initialization of critical w100 hardware
871 static void w100_hw_init(struct w100fb_par
*par
)
874 union cif_cntl_u cif_cntl
;
875 union intf_cntl_u intf_cntl
;
876 union cfgreg_base_u cfgreg_base
;
877 union wrap_top_dir_u wrap_top_dir
;
878 union cif_read_dbg_u cif_read_dbg
;
879 union cpu_defaults_u cpu_default
;
880 union cif_write_dbg_u cif_write_dbg
;
881 union wrap_start_dir_u wrap_start_dir
;
882 union cif_io_u cif_io
;
883 struct w100_gpio_regs
*gpio
= par
->mach
->gpio
;
887 /* This is what the fpga_init code does on reset. May be wrong
888 but there is little info available */
889 writel(0x31, remapped_regs
+ mmSCRATCH_UMSK
);
890 for (temp32
= 0; temp32
< 10000; temp32
++)
891 readl(remapped_regs
+ mmSCRATCH_UMSK
);
892 writel(0x30, remapped_regs
+ mmSCRATCH_UMSK
);
895 cif_io
.val
= defCIF_IO
;
896 writel((u32
)(cif_io
.val
), remapped_regs
+ mmCIF_IO
);
898 cif_write_dbg
.val
= readl(remapped_regs
+ mmCIF_WRITE_DBG
);
899 cif_write_dbg
.f
.dis_packer_ful_during_rbbm_timeout
= 0;
900 cif_write_dbg
.f
.en_dword_split_to_rbbm
= 1;
901 cif_write_dbg
.f
.dis_timeout_during_rbbm
= 1;
902 writel((u32
) (cif_write_dbg
.val
), remapped_regs
+ mmCIF_WRITE_DBG
);
904 cif_read_dbg
.val
= readl(remapped_regs
+ mmCIF_READ_DBG
);
905 cif_read_dbg
.f
.dis_rd_same_byte_to_trig_fetch
= 1;
906 writel((u32
) (cif_read_dbg
.val
), remapped_regs
+ mmCIF_READ_DBG
);
908 cif_cntl
.val
= readl(remapped_regs
+ mmCIF_CNTL
);
909 cif_cntl
.f
.dis_system_bits
= 1;
910 cif_cntl
.f
.dis_mr
= 1;
911 cif_cntl
.f
.en_wait_to_compensate_dq_prop_dly
= 0;
912 cif_cntl
.f
.intb_oe
= 1;
913 cif_cntl
.f
.interrupt_active_high
= 1;
914 writel((u32
) (cif_cntl
.val
), remapped_regs
+ mmCIF_CNTL
);
916 /* Setup cfgINTF_CNTL and cfgCPU defaults */
917 intf_cntl
.val
= defINTF_CNTL
;
918 intf_cntl
.f
.ad_inc_a
= 1;
919 intf_cntl
.f
.ad_inc_b
= 1;
920 intf_cntl
.f
.rd_data_rdy_a
= 0;
921 intf_cntl
.f
.rd_data_rdy_b
= 0;
922 writeb((u8
) (intf_cntl
.val
), remapped_base
+ cfgINTF_CNTL
);
924 cpu_default
.val
= defCPU_DEFAULTS
;
925 cpu_default
.f
.access_ind_addr_a
= 1;
926 cpu_default
.f
.access_ind_addr_b
= 1;
927 cpu_default
.f
.access_scratch_reg
= 1;
928 cpu_default
.f
.transition_size
= 0;
929 writeb((u8
) (cpu_default
.val
), remapped_base
+ cfgCPU_DEFAULTS
);
931 /* set up the apertures */
932 writeb((u8
) (W100_REG_BASE
>> 16), remapped_base
+ cfgREG_BASE
);
934 cfgreg_base
.val
= defCFGREG_BASE
;
935 cfgreg_base
.f
.cfgreg_base
= W100_CFG_BASE
;
936 writel((u32
) (cfgreg_base
.val
), remapped_regs
+ mmCFGREG_BASE
);
938 wrap_start_dir
.val
= defWRAP_START_DIR
;
939 wrap_start_dir
.f
.start_addr
= WRAP_BUF_BASE_VALUE
>> 1;
940 writel((u32
) (wrap_start_dir
.val
), remapped_regs
+ mmWRAP_START_DIR
);
942 wrap_top_dir
.val
= defWRAP_TOP_DIR
;
943 wrap_top_dir
.f
.top_addr
= WRAP_BUF_TOP_VALUE
>> 1;
944 writel((u32
) (wrap_top_dir
.val
), remapped_regs
+ mmWRAP_TOP_DIR
);
946 writel((u32
) 0x2440, remapped_regs
+ mmRBBM_CNTL
);
948 /* Set the hardware to 565 colour */
949 temp32
= readl(remapped_regs
+ mmDISP_DEBUG2
);
950 temp32
&= 0xff7fffff;
951 temp32
|= 0x00800000;
952 writel(temp32
, remapped_regs
+ mmDISP_DEBUG2
);
954 /* Initialise the GPIO lines */
956 writel(gpio
->init_data1
, remapped_regs
+ mmGPIO_DATA
);
957 writel(gpio
->init_data2
, remapped_regs
+ mmGPIO_DATA2
);
958 writel(gpio
->gpio_dir1
, remapped_regs
+ mmGPIO_CNTL1
);
959 writel(gpio
->gpio_oe1
, remapped_regs
+ mmGPIO_CNTL2
);
960 writel(gpio
->gpio_dir2
, remapped_regs
+ mmGPIO_CNTL3
);
961 writel(gpio
->gpio_oe2
, remapped_regs
+ mmGPIO_CNTL4
);
967 union clk_pin_cntl_u clk_pin_cntl
;
968 union pll_ref_fb_div_u pll_ref_fb_div
;
969 union pll_cntl_u pll_cntl
;
970 union sclk_cntl_u sclk_cntl
;
971 union pclk_cntl_u pclk_cntl
;
972 union pwrmgt_cntl_u pwrmgt_cntl
;
973 int auto_mode
; /* system clock auto changing? */
977 static struct power_state w100_pwr_state
;
979 /* The PLL Fout is determined by (XtalFreq/(M+1)) * ((N_int+1) + (N_fac/8)) */
981 /* 12.5MHz Crystal PLL Table */
982 static struct w100_pll_info xtal_12500000
[] = {
983 /*freq M N_int N_fac tfgoal lock_time */
984 { 50, 0, 1, 0, 0xe0, 56}, /* 50.00 MHz */
985 { 75, 0, 5, 0, 0xde, 37}, /* 75.00 MHz */
986 {100, 0, 7, 0, 0xe0, 28}, /* 100.00 MHz */
987 {125, 0, 9, 0, 0xe0, 22}, /* 125.00 MHz */
988 {150, 0, 11, 0, 0xe0, 17}, /* 150.00 MHz */
989 { 0, 0, 0, 0, 0, 0}, /* Terminator */
992 /* 14.318MHz Crystal PLL Table */
993 static struct w100_pll_info xtal_14318000
[] = {
994 /*freq M N_int N_fac tfgoal lock_time */
995 { 40, 4, 13, 0, 0xe0, 80}, /* tfgoal guessed */
996 { 50, 1, 6, 0, 0xe0, 64}, /* 50.05 MHz */
997 { 57, 2, 11, 0, 0xe0, 53}, /* tfgoal guessed */
998 { 75, 0, 4, 3, 0xe0, 43}, /* 75.08 MHz */
999 {100, 0, 6, 0, 0xe0, 32}, /* 100.10 MHz */
1000 { 0, 0, 0, 0, 0, 0},
1003 /* 16MHz Crystal PLL Table */
1004 static struct w100_pll_info xtal_16000000
[] = {
1005 /*freq M N_int N_fac tfgoal lock_time */
1006 { 72, 1, 8, 0, 0xe0, 48}, /* tfgoal guessed */
1007 { 80, 1, 9, 0, 0xe0, 13}, /* tfgoal guessed */
1008 { 95, 1, 10, 7, 0xe0, 38}, /* tfgoal guessed */
1009 { 96, 1, 11, 0, 0xe0, 36}, /* tfgoal guessed */
1010 { 0, 0, 0, 0, 0, 0},
1013 static struct pll_entries
{
1015 struct w100_pll_info
*pll_table
;
1016 } w100_pll_tables
[] = {
1017 { 12500000, &xtal_12500000
[0] },
1018 { 14318000, &xtal_14318000
[0] },
1019 { 16000000, &xtal_16000000
[0] },
1023 struct w100_pll_info
*w100_get_xtal_table(unsigned int freq
)
1025 struct pll_entries
*pll_entry
= w100_pll_tables
;
1028 if (freq
== pll_entry
->xtal_freq
)
1029 return pll_entry
->pll_table
;
1031 } while (pll_entry
->xtal_freq
);
1036 static unsigned int w100_get_testcount(unsigned int testclk_sel
)
1038 union clk_test_cntl_u clk_test_cntl
;
1042 /* Select the test clock source and reset */
1043 clk_test_cntl
.f
.start_check_freq
= 0x0;
1044 clk_test_cntl
.f
.testclk_sel
= testclk_sel
;
1045 clk_test_cntl
.f
.tstcount_rst
= 0x1; /* set reset */
1046 writel((u32
) (clk_test_cntl
.val
), remapped_regs
+ mmCLK_TEST_CNTL
);
1048 clk_test_cntl
.f
.tstcount_rst
= 0x0; /* clear reset */
1049 writel((u32
) (clk_test_cntl
.val
), remapped_regs
+ mmCLK_TEST_CNTL
);
1051 /* Run clock test */
1052 clk_test_cntl
.f
.start_check_freq
= 0x1;
1053 writel((u32
) (clk_test_cntl
.val
), remapped_regs
+ mmCLK_TEST_CNTL
);
1055 /* Give the test time to complete */
1058 /* Return the result */
1059 clk_test_cntl
.val
= readl(remapped_regs
+ mmCLK_TEST_CNTL
);
1060 clk_test_cntl
.f
.start_check_freq
= 0x0;
1061 writel((u32
) (clk_test_cntl
.val
), remapped_regs
+ mmCLK_TEST_CNTL
);
1063 return clk_test_cntl
.f
.test_count
;
1067 static int w100_pll_adjust(struct w100_pll_info
*pll
)
1072 /* Initial Settings */
1073 w100_pwr_state
.pll_cntl
.f
.pll_pwdn
= 0x0; /* power down */
1074 w100_pwr_state
.pll_cntl
.f
.pll_reset
= 0x0; /* not reset */
1075 w100_pwr_state
.pll_cntl
.f
.pll_tcpoff
= 0x1; /* Hi-Z */
1076 w100_pwr_state
.pll_cntl
.f
.pll_pvg
= 0x0; /* VCO gain = 0 */
1077 w100_pwr_state
.pll_cntl
.f
.pll_vcofr
= 0x0; /* VCO frequency range control = off */
1078 w100_pwr_state
.pll_cntl
.f
.pll_ioffset
= 0x0; /* current offset inside VCO = 0 */
1079 w100_pwr_state
.pll_cntl
.f
.pll_ring_off
= 0x0;
1081 /* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V
1082 * therefore, commented out the following lines
1086 /* set VCO input = 0.8 * VDD */
1087 w100_pwr_state
.pll_cntl
.f
.pll_dactal
= 0xd;
1088 writel((u32
) (w100_pwr_state
.pll_cntl
.val
), remapped_regs
+ mmPLL_CNTL
);
1090 tf80
= w100_get_testcount(TESTCLK_SRC_PLL
);
1091 if (tf80
>= (pll
->tfgoal
)) {
1092 /* set VCO input = 0.2 * VDD */
1093 w100_pwr_state
.pll_cntl
.f
.pll_dactal
= 0x7;
1094 writel((u32
) (w100_pwr_state
.pll_cntl
.val
), remapped_regs
+ mmPLL_CNTL
);
1096 tf20
= w100_get_testcount(TESTCLK_SRC_PLL
);
1097 if (tf20
<= (pll
->tfgoal
))
1098 return 1; /* Success */
1100 if ((w100_pwr_state
.pll_cntl
.f
.pll_vcofr
== 0x0) &&
1101 ((w100_pwr_state
.pll_cntl
.f
.pll_pvg
== 0x7) ||
1102 (w100_pwr_state
.pll_cntl
.f
.pll_ioffset
== 0x0))) {
1103 /* slow VCO config */
1104 w100_pwr_state
.pll_cntl
.f
.pll_vcofr
= 0x1;
1105 w100_pwr_state
.pll_cntl
.f
.pll_pvg
= 0x0;
1106 w100_pwr_state
.pll_cntl
.f
.pll_ioffset
= 0x0;
1110 if ((w100_pwr_state
.pll_cntl
.f
.pll_ioffset
) < 0x3) {
1111 w100_pwr_state
.pll_cntl
.f
.pll_ioffset
+= 0x1;
1112 } else if ((w100_pwr_state
.pll_cntl
.f
.pll_pvg
) < 0x7) {
1113 w100_pwr_state
.pll_cntl
.f
.pll_ioffset
= 0x0;
1114 w100_pwr_state
.pll_cntl
.f
.pll_pvg
+= 0x1;
1116 return 0; /* Error */
1123 * w100_pll_calibration
1125 static int w100_pll_calibration(struct w100_pll_info
*pll
)
1129 status
= w100_pll_adjust(pll
);
1131 /* PLL Reset And Lock */
1132 /* set VCO input = 0.5 * VDD */
1133 w100_pwr_state
.pll_cntl
.f
.pll_dactal
= 0xa;
1134 writel((u32
) (w100_pwr_state
.pll_cntl
.val
), remapped_regs
+ mmPLL_CNTL
);
1136 udelay(1); /* reset time */
1138 /* enable charge pump */
1139 w100_pwr_state
.pll_cntl
.f
.pll_tcpoff
= 0x0; /* normal */
1140 writel((u32
) (w100_pwr_state
.pll_cntl
.val
), remapped_regs
+ mmPLL_CNTL
);
1142 /* set VCO input = Hi-Z, disable DAC */
1143 w100_pwr_state
.pll_cntl
.f
.pll_dactal
= 0x0;
1144 writel((u32
) (w100_pwr_state
.pll_cntl
.val
), remapped_regs
+ mmPLL_CNTL
);
1146 udelay(400); /* lock time */
1154 static int w100_pll_set_clk(struct w100_pll_info
*pll
)
1158 if (w100_pwr_state
.auto_mode
== 1) /* auto mode */
1160 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_fast_noml_hw_en
= 0x0; /* disable fast to normal */
1161 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_noml_fast_hw_en
= 0x0; /* disable normal to fast */
1162 writel((u32
) (w100_pwr_state
.pwrmgt_cntl
.val
), remapped_regs
+ mmPWRMGT_CNTL
);
1165 /* Set system clock source to XTAL whilst adjusting the PLL! */
1166 w100_pwr_state
.sclk_cntl
.f
.sclk_src_sel
= CLK_SRC_XTAL
;
1167 writel((u32
) (w100_pwr_state
.sclk_cntl
.val
), remapped_regs
+ mmSCLK_CNTL
);
1169 w100_pwr_state
.pll_ref_fb_div
.f
.pll_ref_div
= pll
->M
;
1170 w100_pwr_state
.pll_ref_fb_div
.f
.pll_fb_div_int
= pll
->N_int
;
1171 w100_pwr_state
.pll_ref_fb_div
.f
.pll_fb_div_frac
= pll
->N_fac
;
1172 w100_pwr_state
.pll_ref_fb_div
.f
.pll_lock_time
= pll
->lock_time
;
1173 writel((u32
) (w100_pwr_state
.pll_ref_fb_div
.val
), remapped_regs
+ mmPLL_REF_FB_DIV
);
1175 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_mode_req
= 0;
1176 writel((u32
) (w100_pwr_state
.pwrmgt_cntl
.val
), remapped_regs
+ mmPWRMGT_CNTL
);
1178 status
= w100_pll_calibration(pll
);
1180 if (w100_pwr_state
.auto_mode
== 1) /* auto mode */
1182 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_fast_noml_hw_en
= 0x1; /* reenable fast to normal */
1183 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_noml_fast_hw_en
= 0x1; /* reenable normal to fast */
1184 writel((u32
) (w100_pwr_state
.pwrmgt_cntl
.val
), remapped_regs
+ mmPWRMGT_CNTL
);
1189 /* freq = target frequency of the PLL */
1190 static int w100_set_pll_freq(struct w100fb_par
*par
, unsigned int freq
)
1192 struct w100_pll_info
*pll
= par
->pll_table
;
1195 if (freq
== pll
->freq
) {
1196 return w100_pll_set_clk(pll
);
1203 /* Set up an initial state. Some values/fields set
1204 here will be overwritten. */
1205 static void w100_pwm_setup(struct w100fb_par
*par
)
1207 w100_pwr_state
.clk_pin_cntl
.f
.osc_en
= 0x1;
1208 w100_pwr_state
.clk_pin_cntl
.f
.osc_gain
= 0x1f;
1209 w100_pwr_state
.clk_pin_cntl
.f
.dont_use_xtalin
= 0x0;
1210 w100_pwr_state
.clk_pin_cntl
.f
.xtalin_pm_en
= 0x0;
1211 w100_pwr_state
.clk_pin_cntl
.f
.xtalin_dbl_en
= par
->mach
->xtal_dbl
? 1 : 0;
1212 w100_pwr_state
.clk_pin_cntl
.f
.cg_debug
= 0x0;
1213 writel((u32
) (w100_pwr_state
.clk_pin_cntl
.val
), remapped_regs
+ mmCLK_PIN_CNTL
);
1215 w100_pwr_state
.sclk_cntl
.f
.sclk_src_sel
= CLK_SRC_XTAL
;
1216 w100_pwr_state
.sclk_cntl
.f
.sclk_post_div_fast
= 0x0; /* Pfast = 1 */
1217 w100_pwr_state
.sclk_cntl
.f
.sclk_clkon_hys
= 0x3;
1218 w100_pwr_state
.sclk_cntl
.f
.sclk_post_div_slow
= 0x0; /* Pslow = 1 */
1219 w100_pwr_state
.sclk_cntl
.f
.disp_cg_ok2switch_en
= 0x0;
1220 w100_pwr_state
.sclk_cntl
.f
.sclk_force_reg
= 0x0; /* Dynamic */
1221 w100_pwr_state
.sclk_cntl
.f
.sclk_force_disp
= 0x0; /* Dynamic */
1222 w100_pwr_state
.sclk_cntl
.f
.sclk_force_mc
= 0x0; /* Dynamic */
1223 w100_pwr_state
.sclk_cntl
.f
.sclk_force_extmc
= 0x0; /* Dynamic */
1224 w100_pwr_state
.sclk_cntl
.f
.sclk_force_cp
= 0x0; /* Dynamic */
1225 w100_pwr_state
.sclk_cntl
.f
.sclk_force_e2
= 0x0; /* Dynamic */
1226 w100_pwr_state
.sclk_cntl
.f
.sclk_force_e3
= 0x0; /* Dynamic */
1227 w100_pwr_state
.sclk_cntl
.f
.sclk_force_idct
= 0x0; /* Dynamic */
1228 w100_pwr_state
.sclk_cntl
.f
.sclk_force_bist
= 0x0; /* Dynamic */
1229 w100_pwr_state
.sclk_cntl
.f
.busy_extend_cp
= 0x0;
1230 w100_pwr_state
.sclk_cntl
.f
.busy_extend_e2
= 0x0;
1231 w100_pwr_state
.sclk_cntl
.f
.busy_extend_e3
= 0x0;
1232 w100_pwr_state
.sclk_cntl
.f
.busy_extend_idct
= 0x0;
1233 writel((u32
) (w100_pwr_state
.sclk_cntl
.val
), remapped_regs
+ mmSCLK_CNTL
);
1235 w100_pwr_state
.pclk_cntl
.f
.pclk_src_sel
= CLK_SRC_XTAL
;
1236 w100_pwr_state
.pclk_cntl
.f
.pclk_post_div
= 0x1; /* P = 2 */
1237 w100_pwr_state
.pclk_cntl
.f
.pclk_force_disp
= 0x0; /* Dynamic */
1238 writel((u32
) (w100_pwr_state
.pclk_cntl
.val
), remapped_regs
+ mmPCLK_CNTL
);
1240 w100_pwr_state
.pll_ref_fb_div
.f
.pll_ref_div
= 0x0; /* M = 1 */
1241 w100_pwr_state
.pll_ref_fb_div
.f
.pll_fb_div_int
= 0x0; /* N = 1.0 */
1242 w100_pwr_state
.pll_ref_fb_div
.f
.pll_fb_div_frac
= 0x0;
1243 w100_pwr_state
.pll_ref_fb_div
.f
.pll_reset_time
= 0x5;
1244 w100_pwr_state
.pll_ref_fb_div
.f
.pll_lock_time
= 0xff;
1245 writel((u32
) (w100_pwr_state
.pll_ref_fb_div
.val
), remapped_regs
+ mmPLL_REF_FB_DIV
);
1247 w100_pwr_state
.pll_cntl
.f
.pll_pwdn
= 0x1;
1248 w100_pwr_state
.pll_cntl
.f
.pll_reset
= 0x1;
1249 w100_pwr_state
.pll_cntl
.f
.pll_pm_en
= 0x0;
1250 w100_pwr_state
.pll_cntl
.f
.pll_mode
= 0x0; /* uses VCO clock */
1251 w100_pwr_state
.pll_cntl
.f
.pll_refclk_sel
= 0x0;
1252 w100_pwr_state
.pll_cntl
.f
.pll_fbclk_sel
= 0x0;
1253 w100_pwr_state
.pll_cntl
.f
.pll_tcpoff
= 0x0;
1254 w100_pwr_state
.pll_cntl
.f
.pll_pcp
= 0x4;
1255 w100_pwr_state
.pll_cntl
.f
.pll_pvg
= 0x0;
1256 w100_pwr_state
.pll_cntl
.f
.pll_vcofr
= 0x0;
1257 w100_pwr_state
.pll_cntl
.f
.pll_ioffset
= 0x0;
1258 w100_pwr_state
.pll_cntl
.f
.pll_pecc_mode
= 0x0;
1259 w100_pwr_state
.pll_cntl
.f
.pll_pecc_scon
= 0x0;
1260 w100_pwr_state
.pll_cntl
.f
.pll_dactal
= 0x0; /* Hi-Z */
1261 w100_pwr_state
.pll_cntl
.f
.pll_cp_clip
= 0x3;
1262 w100_pwr_state
.pll_cntl
.f
.pll_conf
= 0x2;
1263 w100_pwr_state
.pll_cntl
.f
.pll_mbctrl
= 0x2;
1264 w100_pwr_state
.pll_cntl
.f
.pll_ring_off
= 0x0;
1265 writel((u32
) (w100_pwr_state
.pll_cntl
.val
), remapped_regs
+ mmPLL_CNTL
);
1267 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_enable
= 0x0;
1268 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_mode_req
= 0x1; /* normal mode (0, 1, 3) */
1269 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_wakeup_cond
= 0x0;
1270 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_fast_noml_hw_en
= 0x0;
1271 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_noml_fast_hw_en
= 0x0;
1272 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_fast_noml_cond
= 0x1; /* PM4,ENG */
1273 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_noml_fast_cond
= 0x1; /* PM4,ENG */
1274 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_idle_timer
= 0xFF;
1275 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_busy_timer
= 0xFF;
1276 writel((u32
) (w100_pwr_state
.pwrmgt_cntl
.val
), remapped_regs
+ mmPWRMGT_CNTL
);
1278 w100_pwr_state
.auto_mode
= 0; /* manual mode */
1283 * Setup the w100 clocks for the specified mode
1285 static void w100_init_clocks(struct w100fb_par
*par
)
1287 struct w100_mode
*mode
= par
->mode
;
1289 if (mode
->pixclk_src
== CLK_SRC_PLL
|| mode
->sysclk_src
== CLK_SRC_PLL
)
1290 w100_set_pll_freq(par
, (par
->fastpll_mode
&& mode
->fast_pll_freq
) ? mode
->fast_pll_freq
: mode
->pll_freq
);
1292 w100_pwr_state
.sclk_cntl
.f
.sclk_src_sel
= mode
->sysclk_src
;
1293 w100_pwr_state
.sclk_cntl
.f
.sclk_post_div_fast
= mode
->sysclk_divider
;
1294 w100_pwr_state
.sclk_cntl
.f
.sclk_post_div_slow
= mode
->sysclk_divider
;
1295 writel((u32
) (w100_pwr_state
.sclk_cntl
.val
), remapped_regs
+ mmSCLK_CNTL
);
1298 static void w100_init_lcd(struct w100fb_par
*par
)
1301 struct w100_mode
*mode
= par
->mode
;
1302 struct w100_gen_regs
*regs
= par
->mach
->regs
;
1303 union active_h_disp_u active_h_disp
;
1304 union active_v_disp_u active_v_disp
;
1305 union graphic_h_disp_u graphic_h_disp
;
1306 union graphic_v_disp_u graphic_v_disp
;
1307 union crtc_total_u crtc_total
;
1309 /* w3200 doesnt like undefined bits being set so zero register values first */
1311 active_h_disp
.val
= 0;
1312 active_h_disp
.f
.active_h_start
=mode
->left_margin
;
1313 active_h_disp
.f
.active_h_end
=mode
->left_margin
+ mode
->xres
;
1314 writel(active_h_disp
.val
, remapped_regs
+ mmACTIVE_H_DISP
);
1316 active_v_disp
.val
= 0;
1317 active_v_disp
.f
.active_v_start
=mode
->upper_margin
;
1318 active_v_disp
.f
.active_v_end
=mode
->upper_margin
+ mode
->yres
;
1319 writel(active_v_disp
.val
, remapped_regs
+ mmACTIVE_V_DISP
);
1321 graphic_h_disp
.val
= 0;
1322 graphic_h_disp
.f
.graphic_h_start
=mode
->left_margin
;
1323 graphic_h_disp
.f
.graphic_h_end
=mode
->left_margin
+ mode
->xres
;
1324 writel(graphic_h_disp
.val
, remapped_regs
+ mmGRAPHIC_H_DISP
);
1326 graphic_v_disp
.val
= 0;
1327 graphic_v_disp
.f
.graphic_v_start
=mode
->upper_margin
;
1328 graphic_v_disp
.f
.graphic_v_end
=mode
->upper_margin
+ mode
->yres
;
1329 writel(graphic_v_disp
.val
, remapped_regs
+ mmGRAPHIC_V_DISP
);
1332 crtc_total
.f
.crtc_h_total
=mode
->left_margin
+ mode
->xres
+ mode
->right_margin
;
1333 crtc_total
.f
.crtc_v_total
=mode
->upper_margin
+ mode
->yres
+ mode
->lower_margin
;
1334 writel(crtc_total
.val
, remapped_regs
+ mmCRTC_TOTAL
);
1336 writel(mode
->crtc_ss
, remapped_regs
+ mmCRTC_SS
);
1337 writel(mode
->crtc_ls
, remapped_regs
+ mmCRTC_LS
);
1338 writel(mode
->crtc_gs
, remapped_regs
+ mmCRTC_GS
);
1339 writel(mode
->crtc_vpos_gs
, remapped_regs
+ mmCRTC_VPOS_GS
);
1340 writel(mode
->crtc_rev
, remapped_regs
+ mmCRTC_REV
);
1341 writel(mode
->crtc_dclk
, remapped_regs
+ mmCRTC_DCLK
);
1342 writel(mode
->crtc_gclk
, remapped_regs
+ mmCRTC_GCLK
);
1343 writel(mode
->crtc_goe
, remapped_regs
+ mmCRTC_GOE
);
1344 writel(mode
->crtc_ps1_active
, remapped_regs
+ mmCRTC_PS1_ACTIVE
);
1346 writel(regs
->lcd_format
, remapped_regs
+ mmLCD_FORMAT
);
1347 writel(regs
->lcdd_cntl1
, remapped_regs
+ mmLCDD_CNTL1
);
1348 writel(regs
->lcdd_cntl2
, remapped_regs
+ mmLCDD_CNTL2
);
1349 writel(regs
->genlcd_cntl1
, remapped_regs
+ mmGENLCD_CNTL1
);
1350 writel(regs
->genlcd_cntl2
, remapped_regs
+ mmGENLCD_CNTL2
);
1351 writel(regs
->genlcd_cntl3
, remapped_regs
+ mmGENLCD_CNTL3
);
1353 writel(0x00000000, remapped_regs
+ mmCRTC_FRAME
);
1354 writel(0x00000000, remapped_regs
+ mmCRTC_FRAME_VPOS
);
1355 writel(0x00000000, remapped_regs
+ mmCRTC_DEFAULT_COUNT
);
1356 writel(0x0000FF00, remapped_regs
+ mmLCD_BACKGROUND_COLOR
);
1358 /* Hack for overlay in ext memory */
1359 temp32
= readl(remapped_regs
+ mmDISP_DEBUG2
);
1360 temp32
|= 0xc0000000;
1361 writel(temp32
, remapped_regs
+ mmDISP_DEBUG2
);
1365 static void w100_setup_memory(struct w100fb_par
*par
)
1367 union mc_ext_mem_location_u extmem_location
;
1368 union mc_fb_location_u intmem_location
;
1369 struct w100_mem_info
*mem
= par
->mach
->mem
;
1370 struct w100_bm_mem_info
*bm_mem
= par
->mach
->bm_mem
;
1372 if (!par
->extmem_active
) {
1373 w100_suspend(W100_SUSPEND_EXTMEM
);
1375 /* Map Internal Memory at FB Base */
1376 intmem_location
.f
.mc_fb_start
= W100_FB_BASE
>> 8;
1377 intmem_location
.f
.mc_fb_top
= (W100_FB_BASE
+MEM_INT_SIZE
) >> 8;
1378 writel((u32
) (intmem_location
.val
), remapped_regs
+ mmMC_FB_LOCATION
);
1380 /* Unmap External Memory - value is *probably* irrelevant but may have meaning
1381 to acceleration libraries */
1382 extmem_location
.f
.mc_ext_mem_start
= MEM_EXT_BASE_VALUE
>> 8;
1383 extmem_location
.f
.mc_ext_mem_top
= (MEM_EXT_BASE_VALUE
-1) >> 8;
1384 writel((u32
) (extmem_location
.val
), remapped_regs
+ mmMC_EXT_MEM_LOCATION
);
1386 /* Map Internal Memory to its default location */
1387 intmem_location
.f
.mc_fb_start
= MEM_INT_BASE_VALUE
>> 8;
1388 intmem_location
.f
.mc_fb_top
= (MEM_INT_BASE_VALUE
+MEM_INT_SIZE
) >> 8;
1389 writel((u32
) (intmem_location
.val
), remapped_regs
+ mmMC_FB_LOCATION
);
1391 /* Map External Memory at FB Base */
1392 extmem_location
.f
.mc_ext_mem_start
= W100_FB_BASE
>> 8;
1393 extmem_location
.f
.mc_ext_mem_top
= (W100_FB_BASE
+par
->mach
->mem
->size
) >> 8;
1394 writel((u32
) (extmem_location
.val
), remapped_regs
+ mmMC_EXT_MEM_LOCATION
);
1396 writel(0x00007800, remapped_regs
+ mmMC_BIST_CTRL
);
1397 writel(mem
->ext_cntl
, remapped_regs
+ mmMEM_EXT_CNTL
);
1398 writel(0x00200021, remapped_regs
+ mmMEM_SDRAM_MODE_REG
);
1400 writel(0x80200021, remapped_regs
+ mmMEM_SDRAM_MODE_REG
);
1402 writel(mem
->sdram_mode_reg
, remapped_regs
+ mmMEM_SDRAM_MODE_REG
);
1404 writel(mem
->ext_timing_cntl
, remapped_regs
+ mmMEM_EXT_TIMING_CNTL
);
1405 writel(mem
->io_cntl
, remapped_regs
+ mmMEM_IO_CNTL
);
1407 writel(bm_mem
->ext_mem_bw
, remapped_regs
+ mmBM_EXT_MEM_BANDWIDTH
);
1408 writel(bm_mem
->offset
, remapped_regs
+ mmBM_OFFSET
);
1409 writel(bm_mem
->ext_timing_ctl
, remapped_regs
+ mmBM_MEM_EXT_TIMING_CNTL
);
1410 writel(bm_mem
->ext_cntl
, remapped_regs
+ mmBM_MEM_EXT_CNTL
);
1411 writel(bm_mem
->mode_reg
, remapped_regs
+ mmBM_MEM_MODE_REG
);
1412 writel(bm_mem
->io_cntl
, remapped_regs
+ mmBM_MEM_IO_CNTL
);
1413 writel(bm_mem
->config
, remapped_regs
+ mmBM_CONFIG
);
1418 static void w100_set_dispregs(struct w100fb_par
*par
)
1420 unsigned long rot
=0, divider
, offset
=0;
1421 union graphic_ctrl_u graphic_ctrl
;
1423 /* See if the mode has been rotated */
1424 if (par
->xres
== par
->mode
->xres
) {
1426 rot
=3; /* 180 degree */
1427 offset
=(par
->xres
* par
->yres
) - 1;
1428 } /* else 0 degree */
1429 divider
= par
->mode
->pixclk_divider
;
1432 rot
=2; /* 270 degree */
1433 offset
=par
->xres
- 1;
1435 rot
=1; /* 90 degree */
1436 offset
=par
->xres
* (par
->yres
- 1);
1438 divider
= par
->mode
->pixclk_divider_rotated
;
1441 graphic_ctrl
.val
= 0; /* w32xx doesn't like undefined bits */
1442 switch (par
->chip_id
) {
1444 graphic_ctrl
.f_w100
.color_depth
=6;
1445 graphic_ctrl
.f_w100
.en_crtc
=1;
1446 graphic_ctrl
.f_w100
.en_graphic_req
=1;
1447 graphic_ctrl
.f_w100
.en_graphic_crtc
=1;
1448 graphic_ctrl
.f_w100
.lcd_pclk_on
=1;
1449 graphic_ctrl
.f_w100
.lcd_sclk_on
=1;
1450 graphic_ctrl
.f_w100
.low_power_on
=0;
1451 graphic_ctrl
.f_w100
.req_freq
=0;
1452 graphic_ctrl
.f_w100
.portrait_mode
=rot
;
1454 /* Zaurus needs this */
1459 graphic_ctrl
.f_w100
.total_req_graphic
=0xa0;
1466 graphic_ctrl
.f_w100
.low_power_on
=1;
1467 graphic_ctrl
.f_w100
.req_freq
=5;
1471 graphic_ctrl
.f_w100
.req_freq
=4;
1476 graphic_ctrl
.f_w100
.total_req_graphic
=0xf0;
1482 graphic_ctrl
.f_w32xx
.color_depth
=6;
1483 graphic_ctrl
.f_w32xx
.en_crtc
=1;
1484 graphic_ctrl
.f_w32xx
.en_graphic_req
=1;
1485 graphic_ctrl
.f_w32xx
.en_graphic_crtc
=1;
1486 graphic_ctrl
.f_w32xx
.lcd_pclk_on
=1;
1487 graphic_ctrl
.f_w32xx
.lcd_sclk_on
=1;
1488 graphic_ctrl
.f_w32xx
.low_power_on
=0;
1489 graphic_ctrl
.f_w32xx
.req_freq
=0;
1490 graphic_ctrl
.f_w32xx
.total_req_graphic
=par
->mode
->xres
>> 1; /* panel xres, not mode */
1491 graphic_ctrl
.f_w32xx
.portrait_mode
=rot
;
1495 /* Set the pixel clock source and divider */
1496 w100_pwr_state
.pclk_cntl
.f
.pclk_src_sel
= par
->mode
->pixclk_src
;
1497 w100_pwr_state
.pclk_cntl
.f
.pclk_post_div
= divider
;
1498 writel((u32
) (w100_pwr_state
.pclk_cntl
.val
), remapped_regs
+ mmPCLK_CNTL
);
1500 writel(graphic_ctrl
.val
, remapped_regs
+ mmGRAPHIC_CTRL
);
1501 writel(W100_FB_BASE
+ ((offset
* BITS_PER_PIXEL
/8)&~0x03UL
), remapped_regs
+ mmGRAPHIC_OFFSET
);
1502 writel((par
->xres
*BITS_PER_PIXEL
/8), remapped_regs
+ mmGRAPHIC_PITCH
);
1507 * Work out how long the sync pulse lasts
1508 * Value is 1/(time in seconds)
1510 static void calc_hsync(struct w100fb_par
*par
)
1512 unsigned long hsync
;
1513 struct w100_mode
*mode
= par
->mode
;
1514 union crtc_ss_u crtc_ss
;
1516 if (mode
->pixclk_src
== CLK_SRC_XTAL
)
1517 hsync
=par
->mach
->xtal_freq
;
1519 hsync
=((par
->fastpll_mode
&& mode
->fast_pll_freq
) ? mode
->fast_pll_freq
: mode
->pll_freq
)*100000;
1521 hsync
/= (w100_pwr_state
.pclk_cntl
.f
.pclk_post_div
+ 1);
1523 crtc_ss
.val
= readl(remapped_regs
+ mmCRTC_SS
);
1525 par
->hsync_len
= hsync
/ (crtc_ss
.f
.ss_end
-crtc_ss
.f
.ss_start
);
1530 static void w100_suspend(u32 mode
)
1534 writel(0x7FFF8000, remapped_regs
+ mmMC_EXT_MEM_LOCATION
);
1535 writel(0x00FF0000, remapped_regs
+ mmMC_PERF_MON_CNTL
);
1537 val
= readl(remapped_regs
+ mmMEM_EXT_TIMING_CNTL
);
1538 val
&= ~(0x00100000); /* bit20=0 */
1539 val
|= 0xFF000000; /* bit31:24=0xff */
1540 writel(val
, remapped_regs
+ mmMEM_EXT_TIMING_CNTL
);
1542 val
= readl(remapped_regs
+ mmMEM_EXT_CNTL
);
1543 val
&= ~(0x00040000); /* bit18=0 */
1544 val
|= 0x00080000; /* bit19=1 */
1545 writel(val
, remapped_regs
+ mmMEM_EXT_CNTL
);
1547 udelay(1); /* wait 1us */
1549 if (mode
== W100_SUSPEND_EXTMEM
) {
1550 /* CKE: Tri-State */
1551 val
= readl(remapped_regs
+ mmMEM_EXT_CNTL
);
1552 val
|= 0x40000000; /* bit30=1 */
1553 writel(val
, remapped_regs
+ mmMEM_EXT_CNTL
);
1556 val
= readl(remapped_regs
+ mmMEM_EXT_CNTL
);
1557 val
&= ~(0x00000001); /* bit0=0 */
1558 writel(val
, remapped_regs
+ mmMEM_EXT_CNTL
);
1560 writel(0x00000000, remapped_regs
+ mmSCLK_CNTL
);
1561 writel(0x000000BF, remapped_regs
+ mmCLK_PIN_CNTL
);
1562 writel(0x00000015, remapped_regs
+ mmPWRMGT_CNTL
);
1566 val
= readl(remapped_regs
+ mmPLL_CNTL
);
1567 val
|= 0x00000004; /* bit2=1 */
1568 writel(val
, remapped_regs
+ mmPLL_CNTL
);
1569 writel(0x0000001d, remapped_regs
+ mmPWRMGT_CNTL
);
1573 static void w100_vsync(void)
1576 int timeout
= 30000; /* VSync timeout = 30[ms] > 16.8[ms] */
1578 tmp
= readl(remapped_regs
+ mmACTIVE_V_DISP
);
1581 writel((tmp
>> 16) & 0x3ff, remapped_regs
+ mmDISP_INT_CNTL
);
1583 /* disable vline irq */
1584 tmp
= readl(remapped_regs
+ mmGEN_INT_CNTL
);
1587 writel(tmp
, remapped_regs
+ mmGEN_INT_CNTL
);
1589 /* clear vline irq status */
1590 writel(0x00000002, remapped_regs
+ mmGEN_INT_STATUS
);
1592 /* enable vline irq */
1593 writel((tmp
| 0x00000002), remapped_regs
+ mmGEN_INT_CNTL
);
1595 /* clear vline irq status */
1596 writel(0x00000002, remapped_regs
+ mmGEN_INT_STATUS
);
1598 while(timeout
> 0) {
1599 if (readl(remapped_regs
+ mmGEN_INT_STATUS
) & 0x00000002)
1605 /* disable vline irq */
1606 writel(tmp
, remapped_regs
+ mmGEN_INT_CNTL
);
1608 /* clear vline irq status */
1609 writel(0x00000002, remapped_regs
+ mmGEN_INT_STATUS
);
1612 static struct platform_driver w100fb_driver
= {
1613 .probe
= w100fb_probe
,
1614 .remove
= w100fb_remove
,
1615 .suspend
= w100fb_suspend
,
1616 .resume
= w100fb_resume
,
1622 int __devinit
w100fb_init(void)
1624 return platform_driver_register(&w100fb_driver
);
1627 void __exit
w100fb_cleanup(void)
1629 platform_driver_unregister(&w100fb_driver
);
1632 module_init(w100fb_init
);
1633 module_exit(w100fb_cleanup
);
1635 MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
1636 MODULE_LICENSE("GPL");