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-2005 Richard Purdie
8 * Copyright (c) 2005 Ian Molton
10 * Rewritten for 2.6 by Richard Purdie <rpurdie@rpsys.net>
12 * Generic platform support by Ian Molton <spyro@f2s.com>
13 * and Richard Purdie <rpurdie@rpsys.net>
15 * w32xx support by Ian Molton
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License version 2 as
19 * published by the Free Software Foundation.
23 #include <linux/delay.h>
25 #include <linux/init.h>
26 #include <linux/kernel.h>
28 #include <linux/device.h>
29 #include <linux/string.h>
30 #include <linux/vmalloc.h>
32 #include <asm/uaccess.h>
33 #include <video/w100fb.h>
39 static void w100_suspend(u32 mode
);
40 static void w100_vsync(void);
41 static void w100_hw_init(struct w100fb_par
*);
42 static void w100_pwm_setup(struct w100fb_par
*);
43 static void w100_init_clocks(struct w100fb_par
*);
44 static void w100_setup_memory(struct w100fb_par
*);
45 static void w100_init_lcd(struct w100fb_par
*);
46 static void w100_set_dispregs(struct w100fb_par
*);
47 static void w100_update_enable(void);
48 static void w100_update_disable(void);
49 static void calc_hsync(struct w100fb_par
*par
);
50 struct w100_pll_info
*w100_get_xtal_table(unsigned int freq
);
52 /* Pseudo palette size */
53 #define MAX_PALETTES 16
55 #define W100_SUSPEND_EXTMEM 0
56 #define W100_SUSPEND_ALL 1
58 #define BITS_PER_PIXEL 16
60 /* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */
61 static void *remapped_base
;
62 static void *remapped_regs
;
63 static void *remapped_fbuf
;
65 #define REMAPPED_FB_LEN 0x15ffff
67 /* This is the offset in the w100's address space we map the current
68 framebuffer memory to. We use the position of external memory as
69 we can remap internal memory to there if external isn't present. */
70 #define W100_FB_BASE MEM_EXT_BASE_VALUE
76 static ssize_t
flip_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
78 struct fb_info
*info
= dev_get_drvdata(dev
);
79 struct w100fb_par
*par
=info
->par
;
81 return sprintf(buf
, "%d\n",par
->flip
);
84 static ssize_t
flip_store(struct device
*dev
, struct device_attribute
*attr
, const char *buf
, size_t count
)
87 struct fb_info
*info
= dev_get_drvdata(dev
);
88 struct w100fb_par
*par
=info
->par
;
90 flip
= simple_strtoul(buf
, NULL
, 10);
97 w100_update_disable();
98 w100_set_dispregs(par
);
106 static DEVICE_ATTR(flip
, 0644, flip_show
, flip_store
);
108 static ssize_t
w100fb_reg_read(struct device
*dev
, struct device_attribute
*attr
, const char *buf
, size_t count
)
110 unsigned long regs
, param
;
111 regs
= simple_strtoul(buf
, NULL
, 16);
112 param
= readl(remapped_regs
+ regs
);
113 printk("Read Register 0x%08lX: 0x%08lX\n", regs
, param
);
117 static DEVICE_ATTR(reg_read
, 0200, NULL
, w100fb_reg_read
);
119 static ssize_t
w100fb_reg_write(struct device
*dev
, struct device_attribute
*attr
, const char *buf
, size_t count
)
121 unsigned long regs
, param
;
122 sscanf(buf
, "%lx %lx", ®s
, ¶m
);
124 if (regs
<= 0x2000) {
125 printk("Write Register 0x%08lX: 0x%08lX\n", regs
, param
);
126 writel(param
, remapped_regs
+ regs
);
132 static DEVICE_ATTR(reg_write
, 0200, NULL
, w100fb_reg_write
);
135 static ssize_t
fastpllclk_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
137 struct fb_info
*info
= dev_get_drvdata(dev
);
138 struct w100fb_par
*par
=info
->par
;
140 return sprintf(buf
, "%d\n",par
->fastpll_mode
);
143 static ssize_t
fastpllclk_store(struct device
*dev
, struct device_attribute
*attr
, const char *buf
, size_t count
)
145 struct fb_info
*info
= dev_get_drvdata(dev
);
146 struct w100fb_par
*par
=info
->par
;
148 if (simple_strtoul(buf
, NULL
, 10) > 0) {
150 printk("w100fb: Using fast system clock (if possible)\n");
153 printk("w100fb: Using normal system clock\n");
156 w100_init_clocks(par
);
162 static DEVICE_ATTR(fastpllclk
, 0644, fastpllclk_show
, fastpllclk_store
);
165 * Some touchscreens need hsync information from the video driver to
166 * function correctly. We export it here.
168 unsigned long w100fb_get_hsynclen(struct device
*dev
)
170 struct fb_info
*info
= dev_get_drvdata(dev
);
171 struct w100fb_par
*par
=info
->par
;
173 /* If display is blanked/suspended, hsync isn't active */
177 return par
->hsync_len
;
179 EXPORT_SYMBOL(w100fb_get_hsynclen
);
181 static void w100fb_clear_screen(struct w100fb_par
*par
)
183 memset_io(remapped_fbuf
+ (W100_FB_BASE
-MEM_WINDOW_BASE
), 0, (par
->xres
* par
->yres
* BITS_PER_PIXEL
/8));
188 * Set a palette value from rgb components
190 static int w100fb_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
191 u_int trans
, struct fb_info
*info
)
197 * If greyscale is true, then we convert the RGB value
198 * to greyscale no matter what visual we are using.
200 if (info
->var
.grayscale
)
201 red
= green
= blue
= (19595 * red
+ 38470 * green
+ 7471 * blue
) >> 16;
204 * 16-bit True Colour. We encode the RGB value
205 * according to the RGB bitfield information.
207 if (regno
< MAX_PALETTES
) {
208 u32
*pal
= info
->pseudo_palette
;
210 val
= (red
& 0xf800) | ((green
& 0xfc00) >> 5) | ((blue
& 0xf800) >> 11);
219 * Blank the display based on value in blank_mode
221 static int w100fb_blank(int blank_mode
, struct fb_info
*info
)
223 struct w100fb_par
*par
= info
->par
;
224 struct w100_tg_info
*tg
= par
->mach
->tg
;
228 case FB_BLANK_NORMAL
: /* Normal blanking */
229 case FB_BLANK_VSYNC_SUSPEND
: /* VESA blank (vsync off) */
230 case FB_BLANK_HSYNC_SUSPEND
: /* VESA blank (hsync off) */
231 case FB_BLANK_POWERDOWN
: /* Poweroff */
232 if (par
->blanked
== 0) {
233 if(tg
&& tg
->suspend
)
239 case FB_BLANK_UNBLANK
: /* Unblanking */
240 if (par
->blanked
!= 0) {
252 * Change the resolution by calling the appropriate hardware functions
254 static void w100fb_activate_var(struct w100fb_par
*par
)
256 struct w100_tg_info
*tg
= par
->mach
->tg
;
259 w100_setup_memory(par
);
260 w100_init_clocks(par
);
261 w100fb_clear_screen(par
);
264 w100_update_disable();
266 w100_set_dispregs(par
);
267 w100_update_enable();
271 if (!par
->blanked
&& tg
&& tg
->change
)
276 /* Select the smallest mode that allows the desired resolution to be
277 * displayed. If desired, the x and y parameters can be rounded up to
278 * match the selected mode.
280 static struct w100_mode
*w100fb_get_mode(struct w100fb_par
*par
, unsigned int *x
, unsigned int *y
, int saveval
)
282 struct w100_mode
*mode
= NULL
;
283 struct w100_mode
*modelist
= par
->mach
->modelist
;
284 unsigned int best_x
= 0xffffffff, best_y
= 0xffffffff;
287 for (i
= 0 ; i
< par
->mach
->num_modes
; i
++) {
288 if (modelist
[i
].xres
>= *x
&& modelist
[i
].yres
>= *y
&&
289 modelist
[i
].xres
< best_x
&& modelist
[i
].yres
< best_y
) {
290 best_x
= modelist
[i
].xres
;
291 best_y
= modelist
[i
].yres
;
293 } else if(modelist
[i
].xres
>= *y
&& modelist
[i
].yres
>= *x
&&
294 modelist
[i
].xres
< best_y
&& modelist
[i
].yres
< best_x
) {
295 best_x
= modelist
[i
].yres
;
296 best_y
= modelist
[i
].xres
;
301 if (mode
&& saveval
) {
311 * w100fb_check_var():
312 * Get the video params out of 'var'. If a value doesn't fit, round it up,
313 * if it's too big, return -EINVAL.
315 static int w100fb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
317 struct w100fb_par
*par
=info
->par
;
319 if(!w100fb_get_mode(par
, &var
->xres
, &var
->yres
, 1))
322 if (par
->mach
->mem
&& ((var
->xres
*var
->yres
*BITS_PER_PIXEL
/8) > (par
->mach
->mem
->size
+1)))
325 if (!par
->mach
->mem
&& ((var
->xres
*var
->yres
*BITS_PER_PIXEL
/8) > (MEM_INT_SIZE
+1)))
328 var
->xres_virtual
= max(var
->xres_virtual
, var
->xres
);
329 var
->yres_virtual
= max(var
->yres_virtual
, var
->yres
);
331 if (var
->bits_per_pixel
> BITS_PER_PIXEL
)
334 var
->bits_per_pixel
= BITS_PER_PIXEL
;
336 var
->red
.offset
= 11;
338 var
->green
.offset
= 5;
339 var
->green
.length
= 6;
340 var
->blue
.offset
= 0;
341 var
->blue
.length
= 5;
342 var
->transp
.offset
= var
->transp
.length
= 0;
347 var
->vmode
= FB_VMODE_NONINTERLACED
;
349 var
->pixclock
= 0x04; /* 171521; */
357 * Set the user defined part of the display for the specified console
358 * by looking at the values in info.var
360 static int w100fb_set_par(struct fb_info
*info
)
362 struct w100fb_par
*par
=info
->par
;
364 if (par
->xres
!= info
->var
.xres
|| par
->yres
!= info
->var
.yres
) {
365 par
->xres
= info
->var
.xres
;
366 par
->yres
= info
->var
.yres
;
367 par
->mode
= w100fb_get_mode(par
, &par
->xres
, &par
->yres
, 0);
369 info
->fix
.visual
= FB_VISUAL_TRUECOLOR
;
370 info
->fix
.ypanstep
= 0;
371 info
->fix
.ywrapstep
= 0;
372 info
->fix
.line_length
= par
->xres
* BITS_PER_PIXEL
/ 8;
374 if ((par
->xres
*par
->yres
*BITS_PER_PIXEL
/8) > (MEM_INT_SIZE
+1)) {
375 par
->extmem_active
= 1;
376 info
->fix
.smem_len
= par
->mach
->mem
->size
+1;
378 par
->extmem_active
= 0;
379 info
->fix
.smem_len
= MEM_INT_SIZE
+1;
382 w100fb_activate_var(par
);
389 * Frame buffer operations
391 static struct fb_ops w100fb_ops
= {
392 .owner
= THIS_MODULE
,
393 .fb_check_var
= w100fb_check_var
,
394 .fb_set_par
= w100fb_set_par
,
395 .fb_setcolreg
= w100fb_setcolreg
,
396 .fb_blank
= w100fb_blank
,
397 .fb_fillrect
= cfb_fillrect
,
398 .fb_copyarea
= cfb_copyarea
,
399 .fb_imageblit
= cfb_imageblit
,
400 .fb_cursor
= soft_cursor
,
404 static void w100fb_save_vidmem(struct w100fb_par
*par
)
408 if (par
->extmem_active
) {
409 memsize
=par
->mach
->mem
->size
;
410 par
->saved_extmem
= vmalloc(memsize
);
411 if (par
->saved_extmem
)
412 memcpy_fromio(par
->saved_extmem
, remapped_fbuf
+ (W100_FB_BASE
-MEM_WINDOW_BASE
), memsize
);
414 memsize
=MEM_INT_SIZE
;
415 par
->saved_intmem
= vmalloc(memsize
);
416 if (par
->saved_intmem
&& par
->extmem_active
)
417 memcpy_fromio(par
->saved_intmem
, remapped_fbuf
+ (W100_FB_BASE
-MEM_INT_BASE_VALUE
), memsize
);
418 else if (par
->saved_intmem
)
419 memcpy_fromio(par
->saved_intmem
, remapped_fbuf
+ (W100_FB_BASE
-MEM_WINDOW_BASE
), memsize
);
422 static void w100fb_restore_vidmem(struct w100fb_par
*par
)
426 if (par
->extmem_active
&& par
->saved_extmem
) {
427 memsize
=par
->mach
->mem
->size
;
428 memcpy_toio(remapped_fbuf
+ (W100_FB_BASE
-MEM_WINDOW_BASE
), par
->saved_extmem
, memsize
);
429 vfree(par
->saved_extmem
);
431 if (par
->saved_intmem
) {
432 memsize
=MEM_INT_SIZE
;
433 if (par
->extmem_active
)
434 memcpy_toio(remapped_fbuf
+ (W100_FB_BASE
-MEM_INT_BASE_VALUE
), par
->saved_intmem
, memsize
);
436 memcpy_toio(remapped_fbuf
+ (W100_FB_BASE
-MEM_WINDOW_BASE
), par
->saved_intmem
, memsize
);
437 vfree(par
->saved_intmem
);
441 static int w100fb_suspend(struct device
*dev
, pm_message_t state
, uint32_t level
)
443 if (level
== SUSPEND_POWER_DOWN
) {
444 struct fb_info
*info
= dev_get_drvdata(dev
);
445 struct w100fb_par
*par
=info
->par
;
446 struct w100_tg_info
*tg
= par
->mach
->tg
;
448 w100fb_save_vidmem(par
);
449 if(tg
&& tg
->suspend
)
451 w100_suspend(W100_SUSPEND_ALL
);
457 static int w100fb_resume(struct device
*dev
, uint32_t level
)
459 if (level
== RESUME_POWER_ON
) {
460 struct fb_info
*info
= dev_get_drvdata(dev
);
461 struct w100fb_par
*par
=info
->par
;
462 struct w100_tg_info
*tg
= par
->mach
->tg
;
465 w100fb_activate_var(par
);
466 w100fb_restore_vidmem(par
);
474 #define w100fb_suspend NULL
475 #define w100fb_resume NULL
479 int __init
w100fb_probe(struct device
*dev
)
482 struct w100fb_mach_info
*inf
;
483 struct fb_info
*info
= NULL
;
484 struct w100fb_par
*par
;
485 struct platform_device
*pdev
= to_platform_device(dev
);
486 struct resource
*mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
487 unsigned int chip_id
;
492 /* Remap the chip base address */
493 remapped_base
= ioremap_nocache(mem
->start
+W100_CFG_BASE
, W100_CFG_LEN
);
494 if (remapped_base
== NULL
)
497 /* Map the register space */
498 remapped_regs
= ioremap_nocache(mem
->start
+W100_REG_BASE
, W100_REG_LEN
);
499 if (remapped_regs
== NULL
)
502 /* Identify the chip */
504 chip_id
= readl(remapped_regs
+ mmCHIP_ID
);
506 case CHIP_ID_W100
: printk("w100"); break;
507 case CHIP_ID_W3200
: printk("w3200"); break;
508 case CHIP_ID_W3220
: printk("w3220"); break;
510 printk("Unknown imageon chip ID\n");
514 printk(" at 0x%08lx.\n", mem
->start
+W100_CFG_BASE
);
516 /* Remap the framebuffer */
517 remapped_fbuf
= ioremap_nocache(mem
->start
+MEM_WINDOW_BASE
, MEM_WINDOW_SIZE
);
518 if (remapped_fbuf
== NULL
)
521 info
=framebuffer_alloc(sizeof(struct w100fb_par
), dev
);
528 dev_set_drvdata(dev
, info
);
530 inf
= dev
->platform_data
;
531 par
->chip_id
= chip_id
;
533 par
->fastpll_mode
= 0;
536 par
->pll_table
=w100_get_xtal_table(inf
->xtal_freq
);
537 if (!par
->pll_table
) {
538 printk(KERN_ERR
"No matching Xtal definition found\n");
543 info
->pseudo_palette
= kmalloc(sizeof (u32
) * MAX_PALETTES
, GFP_KERNEL
);
544 if (!info
->pseudo_palette
) {
549 info
->fbops
= &w100fb_ops
;
550 info
->flags
= FBINFO_DEFAULT
;
552 info
->screen_base
= remapped_fbuf
+ (W100_FB_BASE
-MEM_WINDOW_BASE
);
553 info
->screen_size
= REMAPPED_FB_LEN
;
555 strcpy(info
->fix
.id
, "w100fb");
556 info
->fix
.type
= FB_TYPE_PACKED_PIXELS
;
557 info
->fix
.type_aux
= 0;
558 info
->fix
.accel
= FB_ACCEL_NONE
;
559 info
->fix
.smem_start
= mem
->start
+W100_FB_BASE
;
560 info
->fix
.mmio_start
= mem
->start
+W100_REG_BASE
;
561 info
->fix
.mmio_len
= W100_REG_LEN
;
563 if (fb_alloc_cmap(&info
->cmap
, 256, 0) < 0) {
568 par
->mode
= &inf
->modelist
[0];
569 if(inf
->init_mode
& INIT_MODE_ROTATED
) {
570 info
->var
.xres
= par
->mode
->yres
;
571 info
->var
.yres
= par
->mode
->xres
;
574 info
->var
.xres
= par
->mode
->xres
;
575 info
->var
.yres
= par
->mode
->yres
;
578 if(inf
->init_mode
&= INIT_MODE_FLIPPED
)
583 info
->var
.xres_virtual
= info
->var
.xres
;
584 info
->var
.yres_virtual
= info
->var
.yres
;
585 info
->var
.pixclock
= 0x04; /* 171521; */
587 info
->var
.grayscale
= 0;
588 info
->var
.xoffset
= info
->var
.yoffset
= 0;
589 info
->var
.accel_flags
= 0;
590 info
->var
.activate
= FB_ACTIVATE_NOW
;
594 if (w100fb_check_var(&info
->var
, info
) < 0) {
599 w100fb_set_par(info
);
601 if (register_framebuffer(info
) < 0) {
606 device_create_file(dev
, &dev_attr_fastpllclk
);
607 device_create_file(dev
, &dev_attr_reg_read
);
608 device_create_file(dev
, &dev_attr_reg_write
);
609 device_create_file(dev
, &dev_attr_flip
);
611 printk(KERN_INFO
"fb%d: %s frame buffer device\n", info
->node
, info
->fix
.id
);
614 fb_dealloc_cmap(&info
->cmap
);
615 kfree(info
->pseudo_palette
);
616 if (remapped_fbuf
!= NULL
)
617 iounmap(remapped_fbuf
);
618 if (remapped_regs
!= NULL
)
619 iounmap(remapped_regs
);
620 if (remapped_base
!= NULL
)
621 iounmap(remapped_base
);
623 framebuffer_release(info
);
628 static int w100fb_remove(struct device
*dev
)
630 struct fb_info
*info
= dev_get_drvdata(dev
);
631 struct w100fb_par
*par
=info
->par
;
633 device_remove_file(dev
, &dev_attr_fastpllclk
);
634 device_remove_file(dev
, &dev_attr_reg_read
);
635 device_remove_file(dev
, &dev_attr_reg_write
);
636 device_remove_file(dev
, &dev_attr_flip
);
638 unregister_framebuffer(info
);
640 vfree(par
->saved_intmem
);
641 vfree(par
->saved_extmem
);
642 kfree(info
->pseudo_palette
);
643 fb_dealloc_cmap(&info
->cmap
);
645 iounmap(remapped_base
);
646 iounmap(remapped_regs
);
647 iounmap(remapped_fbuf
);
649 framebuffer_release(info
);
655 /* ------------------- chipset specific functions -------------------------- */
658 static void w100_soft_reset(void)
660 u16 val
= readw((u16
*) remapped_base
+ cfgSTATUS
);
661 writew(val
| 0x08, (u16
*) remapped_base
+ cfgSTATUS
);
663 writew(0x00, (u16
*) remapped_base
+ cfgSTATUS
);
667 static void w100_update_disable(void)
669 union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl
;
671 /* Prevent display updates */
672 disp_db_buf_wr_cntl
.f
.db_buf_cntl
= 0x1e;
673 disp_db_buf_wr_cntl
.f
.update_db_buf
= 0;
674 disp_db_buf_wr_cntl
.f
.en_db_buf
= 0;
675 writel((u32
) (disp_db_buf_wr_cntl
.val
), remapped_regs
+ mmDISP_DB_BUF_CNTL
);
678 static void w100_update_enable(void)
680 union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl
;
682 /* Enable display updates */
683 disp_db_buf_wr_cntl
.f
.db_buf_cntl
= 0x1e;
684 disp_db_buf_wr_cntl
.f
.update_db_buf
= 1;
685 disp_db_buf_wr_cntl
.f
.en_db_buf
= 1;
686 writel((u32
) (disp_db_buf_wr_cntl
.val
), remapped_regs
+ mmDISP_DB_BUF_CNTL
);
689 unsigned long w100fb_gpio_read(int port
)
693 if (port
==W100_GPIO_PORT_A
)
694 value
= readl(remapped_regs
+ mmGPIO_DATA
);
696 value
= readl(remapped_regs
+ mmGPIO_DATA2
);
701 void w100fb_gpio_write(int port
, unsigned long value
)
703 if (port
==W100_GPIO_PORT_A
)
704 value
= writel(value
, remapped_regs
+ mmGPIO_DATA
);
706 value
= writel(value
, remapped_regs
+ mmGPIO_DATA2
);
708 EXPORT_SYMBOL(w100fb_gpio_read
);
709 EXPORT_SYMBOL(w100fb_gpio_write
);
712 * Initialization of critical w100 hardware
714 static void w100_hw_init(struct w100fb_par
*par
)
717 union cif_cntl_u cif_cntl
;
718 union intf_cntl_u intf_cntl
;
719 union cfgreg_base_u cfgreg_base
;
720 union wrap_top_dir_u wrap_top_dir
;
721 union cif_read_dbg_u cif_read_dbg
;
722 union cpu_defaults_u cpu_default
;
723 union cif_write_dbg_u cif_write_dbg
;
724 union wrap_start_dir_u wrap_start_dir
;
725 union cif_io_u cif_io
;
726 struct w100_gpio_regs
*gpio
= par
->mach
->gpio
;
730 /* This is what the fpga_init code does on reset. May be wrong
731 but there is little info available */
732 writel(0x31, remapped_regs
+ mmSCRATCH_UMSK
);
733 for (temp32
= 0; temp32
< 10000; temp32
++)
734 readl(remapped_regs
+ mmSCRATCH_UMSK
);
735 writel(0x30, remapped_regs
+ mmSCRATCH_UMSK
);
738 cif_io
.val
= defCIF_IO
;
739 writel((u32
)(cif_io
.val
), remapped_regs
+ mmCIF_IO
);
741 cif_write_dbg
.val
= readl(remapped_regs
+ mmCIF_WRITE_DBG
);
742 cif_write_dbg
.f
.dis_packer_ful_during_rbbm_timeout
= 0;
743 cif_write_dbg
.f
.en_dword_split_to_rbbm
= 1;
744 cif_write_dbg
.f
.dis_timeout_during_rbbm
= 1;
745 writel((u32
) (cif_write_dbg
.val
), remapped_regs
+ mmCIF_WRITE_DBG
);
747 cif_read_dbg
.val
= readl(remapped_regs
+ mmCIF_READ_DBG
);
748 cif_read_dbg
.f
.dis_rd_same_byte_to_trig_fetch
= 1;
749 writel((u32
) (cif_read_dbg
.val
), remapped_regs
+ mmCIF_READ_DBG
);
751 cif_cntl
.val
= readl(remapped_regs
+ mmCIF_CNTL
);
752 cif_cntl
.f
.dis_system_bits
= 1;
753 cif_cntl
.f
.dis_mr
= 1;
754 cif_cntl
.f
.en_wait_to_compensate_dq_prop_dly
= 0;
755 cif_cntl
.f
.intb_oe
= 1;
756 cif_cntl
.f
.interrupt_active_high
= 1;
757 writel((u32
) (cif_cntl
.val
), remapped_regs
+ mmCIF_CNTL
);
759 /* Setup cfgINTF_CNTL and cfgCPU defaults */
760 intf_cntl
.val
= defINTF_CNTL
;
761 intf_cntl
.f
.ad_inc_a
= 1;
762 intf_cntl
.f
.ad_inc_b
= 1;
763 intf_cntl
.f
.rd_data_rdy_a
= 0;
764 intf_cntl
.f
.rd_data_rdy_b
= 0;
765 writeb((u8
) (intf_cntl
.val
), remapped_base
+ cfgINTF_CNTL
);
767 cpu_default
.val
= defCPU_DEFAULTS
;
768 cpu_default
.f
.access_ind_addr_a
= 1;
769 cpu_default
.f
.access_ind_addr_b
= 1;
770 cpu_default
.f
.access_scratch_reg
= 1;
771 cpu_default
.f
.transition_size
= 0;
772 writeb((u8
) (cpu_default
.val
), remapped_base
+ cfgCPU_DEFAULTS
);
774 /* set up the apertures */
775 writeb((u8
) (W100_REG_BASE
>> 16), remapped_base
+ cfgREG_BASE
);
777 cfgreg_base
.val
= defCFGREG_BASE
;
778 cfgreg_base
.f
.cfgreg_base
= W100_CFG_BASE
;
779 writel((u32
) (cfgreg_base
.val
), remapped_regs
+ mmCFGREG_BASE
);
781 wrap_start_dir
.val
= defWRAP_START_DIR
;
782 wrap_start_dir
.f
.start_addr
= WRAP_BUF_BASE_VALUE
>> 1;
783 writel((u32
) (wrap_start_dir
.val
), remapped_regs
+ mmWRAP_START_DIR
);
785 wrap_top_dir
.val
= defWRAP_TOP_DIR
;
786 wrap_top_dir
.f
.top_addr
= WRAP_BUF_TOP_VALUE
>> 1;
787 writel((u32
) (wrap_top_dir
.val
), remapped_regs
+ mmWRAP_TOP_DIR
);
789 writel((u32
) 0x2440, remapped_regs
+ mmRBBM_CNTL
);
791 /* Set the hardware to 565 colour */
792 temp32
= readl(remapped_regs
+ mmDISP_DEBUG2
);
793 temp32
&= 0xff7fffff;
794 temp32
|= 0x00800000;
795 writel(temp32
, remapped_regs
+ mmDISP_DEBUG2
);
797 /* Initialise the GPIO lines */
799 writel(gpio
->init_data1
, remapped_regs
+ mmGPIO_DATA
);
800 writel(gpio
->init_data2
, remapped_regs
+ mmGPIO_DATA2
);
801 writel(gpio
->gpio_dir1
, remapped_regs
+ mmGPIO_CNTL1
);
802 writel(gpio
->gpio_oe1
, remapped_regs
+ mmGPIO_CNTL2
);
803 writel(gpio
->gpio_dir2
, remapped_regs
+ mmGPIO_CNTL3
);
804 writel(gpio
->gpio_oe2
, remapped_regs
+ mmGPIO_CNTL4
);
810 union clk_pin_cntl_u clk_pin_cntl
;
811 union pll_ref_fb_div_u pll_ref_fb_div
;
812 union pll_cntl_u pll_cntl
;
813 union sclk_cntl_u sclk_cntl
;
814 union pclk_cntl_u pclk_cntl
;
815 union pwrmgt_cntl_u pwrmgt_cntl
;
816 int auto_mode
; /* system clock auto changing? */
820 static struct power_state w100_pwr_state
;
822 /* The PLL Fout is determined by (XtalFreq/(M+1)) * ((N_int+1) + (N_fac/8)) */
824 /* 12.5MHz Crystal PLL Table */
825 static struct w100_pll_info xtal_12500000
[] = {
826 /*freq M N_int N_fac tfgoal lock_time */
827 { 50, 0, 1, 0, 0xe0, 56}, /* 50.00 MHz */
828 { 75, 0, 5, 0, 0xde, 37}, /* 75.00 MHz */
829 {100, 0, 7, 0, 0xe0, 28}, /* 100.00 MHz */
830 {125, 0, 9, 0, 0xe0, 22}, /* 125.00 MHz */
831 {150, 0, 11, 0, 0xe0, 17}, /* 150.00 MHz */
832 { 0, 0, 0, 0, 0, 0}, /* Terminator */
835 /* 14.318MHz Crystal PLL Table */
836 static struct w100_pll_info xtal_14318000
[] = {
837 /*freq M N_int N_fac tfgoal lock_time */
838 { 40, 4, 13, 0, 0xe0, 80}, /* tfgoal guessed */
839 { 50, 1, 6, 0, 0xe0, 64}, /* 50.05 MHz */
840 { 57, 2, 11, 0, 0xe0, 53}, /* tfgoal guessed */
841 { 75, 0, 4, 3, 0xe0, 43}, /* 75.08 MHz */
842 {100, 0, 6, 0, 0xe0, 32}, /* 100.10 MHz */
846 /* 16MHz Crystal PLL Table */
847 static struct w100_pll_info xtal_16000000
[] = {
848 /*freq M N_int N_fac tfgoal lock_time */
849 { 72, 1, 8, 0, 0xe0, 48}, /* tfgoal guessed */
850 { 95, 1, 10, 7, 0xe0, 38}, /* tfgoal guessed */
851 { 96, 1, 11, 0, 0xe0, 36}, /* tfgoal guessed */
855 static struct pll_entries
{
857 struct w100_pll_info
*pll_table
;
858 } w100_pll_tables
[] = {
859 { 12500000, &xtal_12500000
[0] },
860 { 14318000, &xtal_14318000
[0] },
861 { 16000000, &xtal_16000000
[0] },
865 struct w100_pll_info
*w100_get_xtal_table(unsigned int freq
)
867 struct pll_entries
*pll_entry
= w100_pll_tables
;
870 if (freq
== pll_entry
->xtal_freq
)
871 return pll_entry
->pll_table
;
873 } while (pll_entry
->xtal_freq
);
878 static unsigned int w100_get_testcount(unsigned int testclk_sel
)
880 union clk_test_cntl_u clk_test_cntl
;
884 /* Select the test clock source and reset */
885 clk_test_cntl
.f
.start_check_freq
= 0x0;
886 clk_test_cntl
.f
.testclk_sel
= testclk_sel
;
887 clk_test_cntl
.f
.tstcount_rst
= 0x1; /* set reset */
888 writel((u32
) (clk_test_cntl
.val
), remapped_regs
+ mmCLK_TEST_CNTL
);
890 clk_test_cntl
.f
.tstcount_rst
= 0x0; /* clear reset */
891 writel((u32
) (clk_test_cntl
.val
), remapped_regs
+ mmCLK_TEST_CNTL
);
894 clk_test_cntl
.f
.start_check_freq
= 0x1;
895 writel((u32
) (clk_test_cntl
.val
), remapped_regs
+ mmCLK_TEST_CNTL
);
897 /* Give the test time to complete */
900 /* Return the result */
901 clk_test_cntl
.val
= readl(remapped_regs
+ mmCLK_TEST_CNTL
);
902 clk_test_cntl
.f
.start_check_freq
= 0x0;
903 writel((u32
) (clk_test_cntl
.val
), remapped_regs
+ mmCLK_TEST_CNTL
);
905 return clk_test_cntl
.f
.test_count
;
909 static int w100_pll_adjust(struct w100_pll_info
*pll
)
914 /* Initial Settings */
915 w100_pwr_state
.pll_cntl
.f
.pll_pwdn
= 0x0; /* power down */
916 w100_pwr_state
.pll_cntl
.f
.pll_reset
= 0x0; /* not reset */
917 w100_pwr_state
.pll_cntl
.f
.pll_tcpoff
= 0x1; /* Hi-Z */
918 w100_pwr_state
.pll_cntl
.f
.pll_pvg
= 0x0; /* VCO gain = 0 */
919 w100_pwr_state
.pll_cntl
.f
.pll_vcofr
= 0x0; /* VCO frequency range control = off */
920 w100_pwr_state
.pll_cntl
.f
.pll_ioffset
= 0x0; /* current offset inside VCO = 0 */
921 w100_pwr_state
.pll_cntl
.f
.pll_ring_off
= 0x0;
923 /* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V
924 * therefore, commented out the following lines
928 /* set VCO input = 0.8 * VDD */
929 w100_pwr_state
.pll_cntl
.f
.pll_dactal
= 0xd;
930 writel((u32
) (w100_pwr_state
.pll_cntl
.val
), remapped_regs
+ mmPLL_CNTL
);
932 tf80
= w100_get_testcount(TESTCLK_SRC_PLL
);
933 if (tf80
>= (pll
->tfgoal
)) {
934 /* set VCO input = 0.2 * VDD */
935 w100_pwr_state
.pll_cntl
.f
.pll_dactal
= 0x7;
936 writel((u32
) (w100_pwr_state
.pll_cntl
.val
), remapped_regs
+ mmPLL_CNTL
);
938 tf20
= w100_get_testcount(TESTCLK_SRC_PLL
);
939 if (tf20
<= (pll
->tfgoal
))
940 return 1; /* Success */
942 if ((w100_pwr_state
.pll_cntl
.f
.pll_vcofr
== 0x0) &&
943 ((w100_pwr_state
.pll_cntl
.f
.pll_pvg
== 0x7) ||
944 (w100_pwr_state
.pll_cntl
.f
.pll_ioffset
== 0x0))) {
945 /* slow VCO config */
946 w100_pwr_state
.pll_cntl
.f
.pll_vcofr
= 0x1;
947 w100_pwr_state
.pll_cntl
.f
.pll_pvg
= 0x0;
948 w100_pwr_state
.pll_cntl
.f
.pll_ioffset
= 0x0;
952 if ((w100_pwr_state
.pll_cntl
.f
.pll_ioffset
) < 0x3) {
953 w100_pwr_state
.pll_cntl
.f
.pll_ioffset
+= 0x1;
954 } else if ((w100_pwr_state
.pll_cntl
.f
.pll_pvg
) < 0x7) {
955 w100_pwr_state
.pll_cntl
.f
.pll_ioffset
= 0x0;
956 w100_pwr_state
.pll_cntl
.f
.pll_pvg
+= 0x1;
958 return 0; /* Error */
965 * w100_pll_calibration
967 static int w100_pll_calibration(struct w100_pll_info
*pll
)
971 status
= w100_pll_adjust(pll
);
973 /* PLL Reset And Lock */
974 /* set VCO input = 0.5 * VDD */
975 w100_pwr_state
.pll_cntl
.f
.pll_dactal
= 0xa;
976 writel((u32
) (w100_pwr_state
.pll_cntl
.val
), remapped_regs
+ mmPLL_CNTL
);
978 udelay(1); /* reset time */
980 /* enable charge pump */
981 w100_pwr_state
.pll_cntl
.f
.pll_tcpoff
= 0x0; /* normal */
982 writel((u32
) (w100_pwr_state
.pll_cntl
.val
), remapped_regs
+ mmPLL_CNTL
);
984 /* set VCO input = Hi-Z, disable DAC */
985 w100_pwr_state
.pll_cntl
.f
.pll_dactal
= 0x0;
986 writel((u32
) (w100_pwr_state
.pll_cntl
.val
), remapped_regs
+ mmPLL_CNTL
);
988 udelay(400); /* lock time */
996 static int w100_pll_set_clk(struct w100_pll_info
*pll
)
1000 if (w100_pwr_state
.auto_mode
== 1) /* auto mode */
1002 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_fast_noml_hw_en
= 0x0; /* disable fast to normal */
1003 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_noml_fast_hw_en
= 0x0; /* disable normal to fast */
1004 writel((u32
) (w100_pwr_state
.pwrmgt_cntl
.val
), remapped_regs
+ mmPWRMGT_CNTL
);
1007 /* Set system clock source to XTAL whilst adjusting the PLL! */
1008 w100_pwr_state
.sclk_cntl
.f
.sclk_src_sel
= CLK_SRC_XTAL
;
1009 writel((u32
) (w100_pwr_state
.sclk_cntl
.val
), remapped_regs
+ mmSCLK_CNTL
);
1011 w100_pwr_state
.pll_ref_fb_div
.f
.pll_ref_div
= pll
->M
;
1012 w100_pwr_state
.pll_ref_fb_div
.f
.pll_fb_div_int
= pll
->N_int
;
1013 w100_pwr_state
.pll_ref_fb_div
.f
.pll_fb_div_frac
= pll
->N_fac
;
1014 w100_pwr_state
.pll_ref_fb_div
.f
.pll_lock_time
= pll
->lock_time
;
1015 writel((u32
) (w100_pwr_state
.pll_ref_fb_div
.val
), remapped_regs
+ mmPLL_REF_FB_DIV
);
1017 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_mode_req
= 0;
1018 writel((u32
) (w100_pwr_state
.pwrmgt_cntl
.val
), remapped_regs
+ mmPWRMGT_CNTL
);
1020 status
= w100_pll_calibration(pll
);
1022 if (w100_pwr_state
.auto_mode
== 1) /* auto mode */
1024 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_fast_noml_hw_en
= 0x1; /* reenable fast to normal */
1025 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_noml_fast_hw_en
= 0x1; /* reenable normal to fast */
1026 writel((u32
) (w100_pwr_state
.pwrmgt_cntl
.val
), remapped_regs
+ mmPWRMGT_CNTL
);
1031 /* freq = target frequency of the PLL */
1032 static int w100_set_pll_freq(struct w100fb_par
*par
, unsigned int freq
)
1034 struct w100_pll_info
*pll
= par
->pll_table
;
1037 if (freq
== pll
->freq
) {
1038 return w100_pll_set_clk(pll
);
1045 /* Set up an initial state. Some values/fields set
1046 here will be overwritten. */
1047 static void w100_pwm_setup(struct w100fb_par
*par
)
1049 w100_pwr_state
.clk_pin_cntl
.f
.osc_en
= 0x1;
1050 w100_pwr_state
.clk_pin_cntl
.f
.osc_gain
= 0x1f;
1051 w100_pwr_state
.clk_pin_cntl
.f
.dont_use_xtalin
= 0x0;
1052 w100_pwr_state
.clk_pin_cntl
.f
.xtalin_pm_en
= 0x0;
1053 w100_pwr_state
.clk_pin_cntl
.f
.xtalin_dbl_en
= par
->mach
->xtal_dbl
? 1 : 0;
1054 w100_pwr_state
.clk_pin_cntl
.f
.cg_debug
= 0x0;
1055 writel((u32
) (w100_pwr_state
.clk_pin_cntl
.val
), remapped_regs
+ mmCLK_PIN_CNTL
);
1057 w100_pwr_state
.sclk_cntl
.f
.sclk_src_sel
= CLK_SRC_XTAL
;
1058 w100_pwr_state
.sclk_cntl
.f
.sclk_post_div_fast
= 0x0; /* Pfast = 1 */
1059 w100_pwr_state
.sclk_cntl
.f
.sclk_clkon_hys
= 0x3;
1060 w100_pwr_state
.sclk_cntl
.f
.sclk_post_div_slow
= 0x0; /* Pslow = 1 */
1061 w100_pwr_state
.sclk_cntl
.f
.disp_cg_ok2switch_en
= 0x0;
1062 w100_pwr_state
.sclk_cntl
.f
.sclk_force_reg
= 0x0; /* Dynamic */
1063 w100_pwr_state
.sclk_cntl
.f
.sclk_force_disp
= 0x0; /* Dynamic */
1064 w100_pwr_state
.sclk_cntl
.f
.sclk_force_mc
= 0x0; /* Dynamic */
1065 w100_pwr_state
.sclk_cntl
.f
.sclk_force_extmc
= 0x0; /* Dynamic */
1066 w100_pwr_state
.sclk_cntl
.f
.sclk_force_cp
= 0x0; /* Dynamic */
1067 w100_pwr_state
.sclk_cntl
.f
.sclk_force_e2
= 0x0; /* Dynamic */
1068 w100_pwr_state
.sclk_cntl
.f
.sclk_force_e3
= 0x0; /* Dynamic */
1069 w100_pwr_state
.sclk_cntl
.f
.sclk_force_idct
= 0x0; /* Dynamic */
1070 w100_pwr_state
.sclk_cntl
.f
.sclk_force_bist
= 0x0; /* Dynamic */
1071 w100_pwr_state
.sclk_cntl
.f
.busy_extend_cp
= 0x0;
1072 w100_pwr_state
.sclk_cntl
.f
.busy_extend_e2
= 0x0;
1073 w100_pwr_state
.sclk_cntl
.f
.busy_extend_e3
= 0x0;
1074 w100_pwr_state
.sclk_cntl
.f
.busy_extend_idct
= 0x0;
1075 writel((u32
) (w100_pwr_state
.sclk_cntl
.val
), remapped_regs
+ mmSCLK_CNTL
);
1077 w100_pwr_state
.pclk_cntl
.f
.pclk_src_sel
= CLK_SRC_XTAL
;
1078 w100_pwr_state
.pclk_cntl
.f
.pclk_post_div
= 0x1; /* P = 2 */
1079 w100_pwr_state
.pclk_cntl
.f
.pclk_force_disp
= 0x0; /* Dynamic */
1080 writel((u32
) (w100_pwr_state
.pclk_cntl
.val
), remapped_regs
+ mmPCLK_CNTL
);
1082 w100_pwr_state
.pll_ref_fb_div
.f
.pll_ref_div
= 0x0; /* M = 1 */
1083 w100_pwr_state
.pll_ref_fb_div
.f
.pll_fb_div_int
= 0x0; /* N = 1.0 */
1084 w100_pwr_state
.pll_ref_fb_div
.f
.pll_fb_div_frac
= 0x0;
1085 w100_pwr_state
.pll_ref_fb_div
.f
.pll_reset_time
= 0x5;
1086 w100_pwr_state
.pll_ref_fb_div
.f
.pll_lock_time
= 0xff;
1087 writel((u32
) (w100_pwr_state
.pll_ref_fb_div
.val
), remapped_regs
+ mmPLL_REF_FB_DIV
);
1089 w100_pwr_state
.pll_cntl
.f
.pll_pwdn
= 0x1;
1090 w100_pwr_state
.pll_cntl
.f
.pll_reset
= 0x1;
1091 w100_pwr_state
.pll_cntl
.f
.pll_pm_en
= 0x0;
1092 w100_pwr_state
.pll_cntl
.f
.pll_mode
= 0x0; /* uses VCO clock */
1093 w100_pwr_state
.pll_cntl
.f
.pll_refclk_sel
= 0x0;
1094 w100_pwr_state
.pll_cntl
.f
.pll_fbclk_sel
= 0x0;
1095 w100_pwr_state
.pll_cntl
.f
.pll_tcpoff
= 0x0;
1096 w100_pwr_state
.pll_cntl
.f
.pll_pcp
= 0x4;
1097 w100_pwr_state
.pll_cntl
.f
.pll_pvg
= 0x0;
1098 w100_pwr_state
.pll_cntl
.f
.pll_vcofr
= 0x0;
1099 w100_pwr_state
.pll_cntl
.f
.pll_ioffset
= 0x0;
1100 w100_pwr_state
.pll_cntl
.f
.pll_pecc_mode
= 0x0;
1101 w100_pwr_state
.pll_cntl
.f
.pll_pecc_scon
= 0x0;
1102 w100_pwr_state
.pll_cntl
.f
.pll_dactal
= 0x0; /* Hi-Z */
1103 w100_pwr_state
.pll_cntl
.f
.pll_cp_clip
= 0x3;
1104 w100_pwr_state
.pll_cntl
.f
.pll_conf
= 0x2;
1105 w100_pwr_state
.pll_cntl
.f
.pll_mbctrl
= 0x2;
1106 w100_pwr_state
.pll_cntl
.f
.pll_ring_off
= 0x0;
1107 writel((u32
) (w100_pwr_state
.pll_cntl
.val
), remapped_regs
+ mmPLL_CNTL
);
1109 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_enable
= 0x0;
1110 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_mode_req
= 0x1; /* normal mode (0, 1, 3) */
1111 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_wakeup_cond
= 0x0;
1112 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_fast_noml_hw_en
= 0x0;
1113 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_noml_fast_hw_en
= 0x0;
1114 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_fast_noml_cond
= 0x1; /* PM4,ENG */
1115 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_noml_fast_cond
= 0x1; /* PM4,ENG */
1116 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_idle_timer
= 0xFF;
1117 w100_pwr_state
.pwrmgt_cntl
.f
.pwm_busy_timer
= 0xFF;
1118 writel((u32
) (w100_pwr_state
.pwrmgt_cntl
.val
), remapped_regs
+ mmPWRMGT_CNTL
);
1120 w100_pwr_state
.auto_mode
= 0; /* manual mode */
1125 * Setup the w100 clocks for the specified mode
1127 static void w100_init_clocks(struct w100fb_par
*par
)
1129 struct w100_mode
*mode
= par
->mode
;
1131 if (mode
->pixclk_src
== CLK_SRC_PLL
|| mode
->sysclk_src
== CLK_SRC_PLL
)
1132 w100_set_pll_freq(par
, (par
->fastpll_mode
&& mode
->fast_pll_freq
) ? mode
->fast_pll_freq
: mode
->pll_freq
);
1134 w100_pwr_state
.sclk_cntl
.f
.sclk_src_sel
= mode
->sysclk_src
;
1135 w100_pwr_state
.sclk_cntl
.f
.sclk_post_div_fast
= mode
->sysclk_divider
;
1136 w100_pwr_state
.sclk_cntl
.f
.sclk_post_div_slow
= mode
->sysclk_divider
;
1137 writel((u32
) (w100_pwr_state
.sclk_cntl
.val
), remapped_regs
+ mmSCLK_CNTL
);
1140 static void w100_init_lcd(struct w100fb_par
*par
)
1143 struct w100_mode
*mode
= par
->mode
;
1144 struct w100_gen_regs
*regs
= par
->mach
->regs
;
1145 union active_h_disp_u active_h_disp
;
1146 union active_v_disp_u active_v_disp
;
1147 union graphic_h_disp_u graphic_h_disp
;
1148 union graphic_v_disp_u graphic_v_disp
;
1149 union crtc_total_u crtc_total
;
1151 /* w3200 doesnt like undefined bits being set so zero register values first */
1153 active_h_disp
.val
= 0;
1154 active_h_disp
.f
.active_h_start
=mode
->left_margin
;
1155 active_h_disp
.f
.active_h_end
=mode
->left_margin
+ mode
->xres
;
1156 writel(active_h_disp
.val
, remapped_regs
+ mmACTIVE_H_DISP
);
1158 active_v_disp
.val
= 0;
1159 active_v_disp
.f
.active_v_start
=mode
->upper_margin
;
1160 active_v_disp
.f
.active_v_end
=mode
->upper_margin
+ mode
->yres
;
1161 writel(active_v_disp
.val
, remapped_regs
+ mmACTIVE_V_DISP
);
1163 graphic_h_disp
.val
= 0;
1164 graphic_h_disp
.f
.graphic_h_start
=mode
->left_margin
;
1165 graphic_h_disp
.f
.graphic_h_end
=mode
->left_margin
+ mode
->xres
;
1166 writel(graphic_h_disp
.val
, remapped_regs
+ mmGRAPHIC_H_DISP
);
1168 graphic_v_disp
.val
= 0;
1169 graphic_v_disp
.f
.graphic_v_start
=mode
->upper_margin
;
1170 graphic_v_disp
.f
.graphic_v_end
=mode
->upper_margin
+ mode
->yres
;
1171 writel(graphic_v_disp
.val
, remapped_regs
+ mmGRAPHIC_V_DISP
);
1174 crtc_total
.f
.crtc_h_total
=mode
->left_margin
+ mode
->xres
+ mode
->right_margin
;
1175 crtc_total
.f
.crtc_v_total
=mode
->upper_margin
+ mode
->yres
+ mode
->lower_margin
;
1176 writel(crtc_total
.val
, remapped_regs
+ mmCRTC_TOTAL
);
1178 writel(mode
->crtc_ss
, remapped_regs
+ mmCRTC_SS
);
1179 writel(mode
->crtc_ls
, remapped_regs
+ mmCRTC_LS
);
1180 writel(mode
->crtc_gs
, remapped_regs
+ mmCRTC_GS
);
1181 writel(mode
->crtc_vpos_gs
, remapped_regs
+ mmCRTC_VPOS_GS
);
1182 writel(mode
->crtc_rev
, remapped_regs
+ mmCRTC_REV
);
1183 writel(mode
->crtc_dclk
, remapped_regs
+ mmCRTC_DCLK
);
1184 writel(mode
->crtc_gclk
, remapped_regs
+ mmCRTC_GCLK
);
1185 writel(mode
->crtc_goe
, remapped_regs
+ mmCRTC_GOE
);
1186 writel(mode
->crtc_ps1_active
, remapped_regs
+ mmCRTC_PS1_ACTIVE
);
1188 writel(regs
->lcd_format
, remapped_regs
+ mmLCD_FORMAT
);
1189 writel(regs
->lcdd_cntl1
, remapped_regs
+ mmLCDD_CNTL1
);
1190 writel(regs
->lcdd_cntl2
, remapped_regs
+ mmLCDD_CNTL2
);
1191 writel(regs
->genlcd_cntl1
, remapped_regs
+ mmGENLCD_CNTL1
);
1192 writel(regs
->genlcd_cntl2
, remapped_regs
+ mmGENLCD_CNTL2
);
1193 writel(regs
->genlcd_cntl3
, remapped_regs
+ mmGENLCD_CNTL3
);
1195 writel(0x00000000, remapped_regs
+ mmCRTC_FRAME
);
1196 writel(0x00000000, remapped_regs
+ mmCRTC_FRAME_VPOS
);
1197 writel(0x00000000, remapped_regs
+ mmCRTC_DEFAULT_COUNT
);
1198 writel(0x0000FF00, remapped_regs
+ mmLCD_BACKGROUND_COLOR
);
1200 /* Hack for overlay in ext memory */
1201 temp32
= readl(remapped_regs
+ mmDISP_DEBUG2
);
1202 temp32
|= 0xc0000000;
1203 writel(temp32
, remapped_regs
+ mmDISP_DEBUG2
);
1207 static void w100_setup_memory(struct w100fb_par
*par
)
1209 union mc_ext_mem_location_u extmem_location
;
1210 union mc_fb_location_u intmem_location
;
1211 struct w100_mem_info
*mem
= par
->mach
->mem
;
1212 struct w100_bm_mem_info
*bm_mem
= par
->mach
->bm_mem
;
1214 if (!par
->extmem_active
) {
1215 w100_suspend(W100_SUSPEND_EXTMEM
);
1217 /* Map Internal Memory at FB Base */
1218 intmem_location
.f
.mc_fb_start
= W100_FB_BASE
>> 8;
1219 intmem_location
.f
.mc_fb_top
= (W100_FB_BASE
+MEM_INT_SIZE
) >> 8;
1220 writel((u32
) (intmem_location
.val
), remapped_regs
+ mmMC_FB_LOCATION
);
1222 /* Unmap External Memory - value is *probably* irrelevant but may have meaning
1223 to acceleration libraries */
1224 extmem_location
.f
.mc_ext_mem_start
= MEM_EXT_BASE_VALUE
>> 8;
1225 extmem_location
.f
.mc_ext_mem_top
= (MEM_EXT_BASE_VALUE
-1) >> 8;
1226 writel((u32
) (extmem_location
.val
), remapped_regs
+ mmMC_EXT_MEM_LOCATION
);
1228 /* Map Internal Memory to its default location */
1229 intmem_location
.f
.mc_fb_start
= MEM_INT_BASE_VALUE
>> 8;
1230 intmem_location
.f
.mc_fb_top
= (MEM_INT_BASE_VALUE
+MEM_INT_SIZE
) >> 8;
1231 writel((u32
) (intmem_location
.val
), remapped_regs
+ mmMC_FB_LOCATION
);
1233 /* Map External Memory at FB Base */
1234 extmem_location
.f
.mc_ext_mem_start
= W100_FB_BASE
>> 8;
1235 extmem_location
.f
.mc_ext_mem_top
= (W100_FB_BASE
+par
->mach
->mem
->size
) >> 8;
1236 writel((u32
) (extmem_location
.val
), remapped_regs
+ mmMC_EXT_MEM_LOCATION
);
1238 writel(0x00007800, remapped_regs
+ mmMC_BIST_CTRL
);
1239 writel(mem
->ext_cntl
, remapped_regs
+ mmMEM_EXT_CNTL
);
1240 writel(0x00200021, remapped_regs
+ mmMEM_SDRAM_MODE_REG
);
1242 writel(0x80200021, remapped_regs
+ mmMEM_SDRAM_MODE_REG
);
1244 writel(mem
->sdram_mode_reg
, remapped_regs
+ mmMEM_SDRAM_MODE_REG
);
1246 writel(mem
->ext_timing_cntl
, remapped_regs
+ mmMEM_EXT_TIMING_CNTL
);
1247 writel(mem
->io_cntl
, remapped_regs
+ mmMEM_IO_CNTL
);
1249 writel(bm_mem
->ext_mem_bw
, remapped_regs
+ mmBM_EXT_MEM_BANDWIDTH
);
1250 writel(bm_mem
->offset
, remapped_regs
+ mmBM_OFFSET
);
1251 writel(bm_mem
->ext_timing_ctl
, remapped_regs
+ mmBM_MEM_EXT_TIMING_CNTL
);
1252 writel(bm_mem
->ext_cntl
, remapped_regs
+ mmBM_MEM_EXT_CNTL
);
1253 writel(bm_mem
->mode_reg
, remapped_regs
+ mmBM_MEM_MODE_REG
);
1254 writel(bm_mem
->io_cntl
, remapped_regs
+ mmBM_MEM_IO_CNTL
);
1255 writel(bm_mem
->config
, remapped_regs
+ mmBM_CONFIG
);
1260 static void w100_set_dispregs(struct w100fb_par
*par
)
1262 unsigned long rot
=0, divider
, offset
=0;
1263 union graphic_ctrl_u graphic_ctrl
;
1265 /* See if the mode has been rotated */
1266 if (par
->xres
== par
->mode
->xres
) {
1268 rot
=3; /* 180 degree */
1269 offset
=(par
->xres
* par
->yres
) - 1;
1270 } /* else 0 degree */
1271 divider
= par
->mode
->pixclk_divider
;
1274 rot
=2; /* 270 degree */
1275 offset
=par
->xres
- 1;
1277 rot
=1; /* 90 degree */
1278 offset
=par
->xres
* (par
->yres
- 1);
1280 divider
= par
->mode
->pixclk_divider_rotated
;
1283 graphic_ctrl
.val
= 0; /* w32xx doesn't like undefined bits */
1284 switch (par
->chip_id
) {
1286 graphic_ctrl
.f_w100
.color_depth
=6;
1287 graphic_ctrl
.f_w100
.en_crtc
=1;
1288 graphic_ctrl
.f_w100
.en_graphic_req
=1;
1289 graphic_ctrl
.f_w100
.en_graphic_crtc
=1;
1290 graphic_ctrl
.f_w100
.lcd_pclk_on
=1;
1291 graphic_ctrl
.f_w100
.lcd_sclk_on
=1;
1292 graphic_ctrl
.f_w100
.low_power_on
=0;
1293 graphic_ctrl
.f_w100
.req_freq
=0;
1294 graphic_ctrl
.f_w100
.portrait_mode
=rot
;
1296 /* Zaurus needs this */
1301 graphic_ctrl
.f_w100
.total_req_graphic
=0xa0;
1308 graphic_ctrl
.f_w100
.low_power_on
=1;
1309 graphic_ctrl
.f_w100
.req_freq
=5;
1313 graphic_ctrl
.f_w100
.req_freq
=4;
1318 graphic_ctrl
.f_w100
.total_req_graphic
=0xf0;
1324 graphic_ctrl
.f_w32xx
.color_depth
=6;
1325 graphic_ctrl
.f_w32xx
.en_crtc
=1;
1326 graphic_ctrl
.f_w32xx
.en_graphic_req
=1;
1327 graphic_ctrl
.f_w32xx
.en_graphic_crtc
=1;
1328 graphic_ctrl
.f_w32xx
.lcd_pclk_on
=1;
1329 graphic_ctrl
.f_w32xx
.lcd_sclk_on
=1;
1330 graphic_ctrl
.f_w32xx
.low_power_on
=0;
1331 graphic_ctrl
.f_w32xx
.req_freq
=0;
1332 graphic_ctrl
.f_w32xx
.total_req_graphic
=par
->mode
->xres
>> 1; /* panel xres, not mode */
1333 graphic_ctrl
.f_w32xx
.portrait_mode
=rot
;
1337 /* Set the pixel clock source and divider */
1338 w100_pwr_state
.pclk_cntl
.f
.pclk_src_sel
= par
->mode
->pixclk_src
;
1339 w100_pwr_state
.pclk_cntl
.f
.pclk_post_div
= divider
;
1340 writel((u32
) (w100_pwr_state
.pclk_cntl
.val
), remapped_regs
+ mmPCLK_CNTL
);
1342 writel(graphic_ctrl
.val
, remapped_regs
+ mmGRAPHIC_CTRL
);
1343 writel(W100_FB_BASE
+ ((offset
* BITS_PER_PIXEL
/8)&~0x03UL
), remapped_regs
+ mmGRAPHIC_OFFSET
);
1344 writel((par
->xres
*BITS_PER_PIXEL
/8), remapped_regs
+ mmGRAPHIC_PITCH
);
1349 * Work out how long the sync pulse lasts
1350 * Value is 1/(time in seconds)
1352 static void calc_hsync(struct w100fb_par
*par
)
1354 unsigned long hsync
;
1355 struct w100_mode
*mode
= par
->mode
;
1356 union crtc_ss_u crtc_ss
;
1358 if (mode
->pixclk_src
== CLK_SRC_XTAL
)
1359 hsync
=par
->mach
->xtal_freq
;
1361 hsync
=((par
->fastpll_mode
&& mode
->fast_pll_freq
) ? mode
->fast_pll_freq
: mode
->pll_freq
)*100000;
1363 hsync
/= (w100_pwr_state
.pclk_cntl
.f
.pclk_post_div
+ 1);
1365 crtc_ss
.val
= readl(remapped_regs
+ mmCRTC_SS
);
1367 par
->hsync_len
= hsync
/ (crtc_ss
.f
.ss_end
-crtc_ss
.f
.ss_start
);
1372 static void w100_suspend(u32 mode
)
1376 writel(0x7FFF8000, remapped_regs
+ mmMC_EXT_MEM_LOCATION
);
1377 writel(0x00FF0000, remapped_regs
+ mmMC_PERF_MON_CNTL
);
1379 val
= readl(remapped_regs
+ mmMEM_EXT_TIMING_CNTL
);
1380 val
&= ~(0x00100000); /* bit20=0 */
1381 val
|= 0xFF000000; /* bit31:24=0xff */
1382 writel(val
, remapped_regs
+ mmMEM_EXT_TIMING_CNTL
);
1384 val
= readl(remapped_regs
+ mmMEM_EXT_CNTL
);
1385 val
&= ~(0x00040000); /* bit18=0 */
1386 val
|= 0x00080000; /* bit19=1 */
1387 writel(val
, remapped_regs
+ mmMEM_EXT_CNTL
);
1389 udelay(1); /* wait 1us */
1391 if (mode
== W100_SUSPEND_EXTMEM
) {
1392 /* CKE: Tri-State */
1393 val
= readl(remapped_regs
+ mmMEM_EXT_CNTL
);
1394 val
|= 0x40000000; /* bit30=1 */
1395 writel(val
, remapped_regs
+ mmMEM_EXT_CNTL
);
1398 val
= readl(remapped_regs
+ mmMEM_EXT_CNTL
);
1399 val
&= ~(0x00000001); /* bit0=0 */
1400 writel(val
, remapped_regs
+ mmMEM_EXT_CNTL
);
1402 writel(0x00000000, remapped_regs
+ mmSCLK_CNTL
);
1403 writel(0x000000BF, remapped_regs
+ mmCLK_PIN_CNTL
);
1404 writel(0x00000015, remapped_regs
+ mmPWRMGT_CNTL
);
1408 val
= readl(remapped_regs
+ mmPLL_CNTL
);
1409 val
|= 0x00000004; /* bit2=1 */
1410 writel(val
, remapped_regs
+ mmPLL_CNTL
);
1411 writel(0x0000001d, remapped_regs
+ mmPWRMGT_CNTL
);
1415 static void w100_vsync(void)
1418 int timeout
= 30000; /* VSync timeout = 30[ms] > 16.8[ms] */
1420 tmp
= readl(remapped_regs
+ mmACTIVE_V_DISP
);
1423 writel((tmp
>> 16) & 0x3ff, remapped_regs
+ mmDISP_INT_CNTL
);
1425 /* disable vline irq */
1426 tmp
= readl(remapped_regs
+ mmGEN_INT_CNTL
);
1429 writel(tmp
, remapped_regs
+ mmGEN_INT_CNTL
);
1431 /* clear vline irq status */
1432 writel(0x00000002, remapped_regs
+ mmGEN_INT_STATUS
);
1434 /* enable vline irq */
1435 writel((tmp
| 0x00000002), remapped_regs
+ mmGEN_INT_CNTL
);
1437 /* clear vline irq status */
1438 writel(0x00000002, remapped_regs
+ mmGEN_INT_STATUS
);
1440 while(timeout
> 0) {
1441 if (readl(remapped_regs
+ mmGEN_INT_STATUS
) & 0x00000002)
1447 /* disable vline irq */
1448 writel(tmp
, remapped_regs
+ mmGEN_INT_CNTL
);
1450 /* clear vline irq status */
1451 writel(0x00000002, remapped_regs
+ mmGEN_INT_STATUS
);
1454 static struct device_driver w100fb_driver
= {
1456 .bus
= &platform_bus_type
,
1457 .probe
= w100fb_probe
,
1458 .remove
= w100fb_remove
,
1459 .suspend
= w100fb_suspend
,
1460 .resume
= w100fb_resume
,
1463 int __devinit
w100fb_init(void)
1465 return driver_register(&w100fb_driver
);
1468 void __exit
w100fb_cleanup(void)
1470 driver_unregister(&w100fb_driver
);
1473 module_init(w100fb_init
);
1474 module_exit(w100fb_cleanup
);
1476 MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
1477 MODULE_LICENSE("GPL");