2 * controlfb.c -- frame buffer device for the PowerMac 'control' display
4 * Created 12 July 1998 by Dan Jacobowitz <dan@debian.org>
5 * Copyright (C) 1998 Dan Jacobowitz
6 * Copyright (C) 2001 Takashi Oe
8 * Mmap code by Michel Lanners <mlan@cpu.lu>
10 * Frame buffer structure from:
11 * drivers/video/chipsfb.c -- frame buffer device for
12 * Chips & Technologies 65550 chip.
14 * Copyright (C) 1998 Paul Mackerras
16 * This file is derived from the Powermac "chips" driver:
17 * Copyright (C) 1997 Fabio Riccardi.
18 * And from the frame buffer device for Open Firmware-initialized devices:
19 * Copyright (C) 1997 Geert Uytterhoeven.
21 * Hardware information from:
22 * control.c: Console support for PowerMac "control" display adaptor.
23 * Copyright (C) 1996 Paul Mackerras
25 * Updated to 2.5 framebuffer API by Ben Herrenschmidt
26 * <benh@kernel.crashing.org>, Paul Mackerras <paulus@samba.org>,
27 * and James Simmons <jsimmons@infradead.org>.
29 * This file is subject to the terms and conditions of the GNU General Public
30 * License. See the file COPYING in the main directory of this archive for
34 #include <linux/config.h>
35 #include <linux/module.h>
36 #include <linux/kernel.h>
37 #include <linux/errno.h>
38 #include <linux/string.h>
40 #include <linux/tty.h>
41 #include <linux/slab.h>
42 #include <linux/vmalloc.h>
43 #include <linux/delay.h>
44 #include <linux/interrupt.h>
46 #include <linux/init.h>
47 #include <linux/pci.h>
48 #include <linux/nvram.h>
49 #include <linux/adb.h>
50 #include <linux/cuda.h>
53 #include <asm/pgtable.h>
54 #include <asm/btext.h>
57 #include "controlfb.h"
59 struct fb_par_control
{
65 struct control_regvals regvals
;
70 #define DIRTY(z) ((x)->z != (y)->z)
71 #define DIRTY_CMAP(z) (memcmp(&((x)->z), &((y)->z), sizeof((y)->z)))
72 static inline int PAR_EQUAL(struct fb_par_control
*x
, struct fb_par_control
*y
)
77 for (i
= 0; i
< 3; i
++)
78 results
&= !DIRTY(regvals
.clock_params
[i
]);
81 for (i
= 0; i
< 16; i
++)
82 results
&= !DIRTY(regvals
.regs
[i
]);
85 return (!DIRTY(cmode
) && !DIRTY(xres
) && !DIRTY(yres
)
86 && !DIRTY(vxres
) && !DIRTY(vyres
));
88 static inline int VAR_MATCH(struct fb_var_screeninfo
*x
, struct fb_var_screeninfo
*y
)
90 return (!DIRTY(bits_per_pixel
) && !DIRTY(xres
)
91 && !DIRTY(yres
) && !DIRTY(xres_virtual
)
92 && !DIRTY(yres_virtual
)
93 && !DIRTY_CMAP(red
) && !DIRTY_CMAP(green
) && !DIRTY_CMAP(blue
));
96 struct fb_info_control
{
98 struct fb_par_control par
;
99 u32 pseudo_palette
[17];
101 struct cmap_regs __iomem
*cmap_regs
;
102 unsigned long cmap_regs_phys
;
104 struct control_regs __iomem
*control_regs
;
105 unsigned long control_regs_phys
;
106 unsigned long control_regs_size
;
108 __u8 __iomem
*frame_buffer
;
109 unsigned long frame_buffer_phys
;
110 unsigned long fb_orig_base
;
111 unsigned long fb_orig_size
;
113 int control_use_bank2
;
114 unsigned long total_vram
;
115 unsigned char vram_attr
;
118 /* control register access macro */
119 #define CNTRL_REG(INFO,REG) (&(((INFO)->control_regs->REG).r))
122 /******************** Prototypes for exported functions ********************/
126 static int controlfb_pan_display(struct fb_var_screeninfo
*var
,
127 struct fb_info
*info
);
128 static int controlfb_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
129 u_int transp
, struct fb_info
*info
);
130 static int controlfb_blank(int blank_mode
, struct fb_info
*info
);
131 static int controlfb_mmap(struct fb_info
*info
, struct file
*file
,
132 struct vm_area_struct
*vma
);
133 static int controlfb_set_par (struct fb_info
*info
);
134 static int controlfb_check_var (struct fb_var_screeninfo
*var
, struct fb_info
*info
);
139 int control_init(void);
140 void control_setup(char *);
142 /******************** Prototypes for internal functions **********************/
144 static void set_control_clock(unsigned char *params
);
145 static int init_control(struct fb_info_control
*p
);
146 static void control_set_hardware(struct fb_info_control
*p
,
147 struct fb_par_control
*par
);
148 static int control_of_init(struct device_node
*dp
);
149 static void find_vram_size(struct fb_info_control
*p
);
150 static int read_control_sense(struct fb_info_control
*p
);
151 static int calc_clock_params(unsigned long clk
, unsigned char *param
);
152 static int control_var_to_par(struct fb_var_screeninfo
*var
,
153 struct fb_par_control
*par
, const struct fb_info
*fb_info
);
154 static inline void control_par_to_var(struct fb_par_control
*par
,
155 struct fb_var_screeninfo
*var
);
156 static void control_init_info(struct fb_info
*info
, struct fb_info_control
*p
);
157 static void control_cleanup(void);
160 /************************** Internal variables *******************************/
162 static struct fb_info_control
*control_fb
;
164 static int default_vmode __initdata
= VMODE_NVRAM
;
165 static int default_cmode __initdata
= CMODE_NVRAM
;
168 static struct fb_ops controlfb_ops
= {
169 .owner
= THIS_MODULE
,
170 .fb_check_var
= controlfb_check_var
,
171 .fb_set_par
= controlfb_set_par
,
172 .fb_setcolreg
= controlfb_setcolreg
,
173 .fb_pan_display
= controlfb_pan_display
,
174 .fb_blank
= controlfb_blank
,
175 .fb_mmap
= controlfb_mmap
,
176 .fb_fillrect
= cfb_fillrect
,
177 .fb_copyarea
= cfb_copyarea
,
178 .fb_imageblit
= cfb_imageblit
,
179 .fb_cursor
= soft_cursor
,
183 /******************** The functions for controlfb_ops ********************/
186 MODULE_LICENSE("GPL");
188 int init_module(void)
190 struct device_node
*dp
;
192 dp
= find_devices("control");
193 if (dp
!= 0 && !control_of_init(dp
))
199 void cleanup_module(void)
206 * Checks a var structure
208 static int controlfb_check_var (struct fb_var_screeninfo
*var
, struct fb_info
*info
)
210 struct fb_par_control par
;
213 err
= control_var_to_par(var
, &par
, info
);
216 control_par_to_var(&par
, var
);
222 * Applies current var to display
224 static int controlfb_set_par (struct fb_info
*info
)
226 struct fb_info_control
*p
= (struct fb_info_control
*) info
;
227 struct fb_par_control par
;
230 if((err
= control_var_to_par(&info
->var
, &par
, info
))) {
231 printk (KERN_ERR
"controlfb_set_par: error calling"
232 " control_var_to_par: %d.\n", err
);
236 control_set_hardware(p
, &par
);
238 info
->fix
.visual
= (p
->par
.cmode
== CMODE_8
) ?
239 FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_DIRECTCOLOR
;
240 info
->fix
.line_length
= p
->par
.pitch
;
241 info
->fix
.xpanstep
= 32 >> p
->par
.cmode
;
242 info
->fix
.ypanstep
= 1;
248 * Set screen start address according to var offset values
250 static inline void set_screen_start(int xoffset
, int yoffset
,
251 struct fb_info_control
*p
)
253 struct fb_par_control
*par
= &p
->par
;
255 par
->xoffset
= xoffset
;
256 par
->yoffset
= yoffset
;
257 out_le32(CNTRL_REG(p
,start_addr
),
258 par
->yoffset
* par
->pitch
+ (par
->xoffset
<< par
->cmode
));
262 static int controlfb_pan_display(struct fb_var_screeninfo
*var
,
263 struct fb_info
*info
)
265 unsigned int xoffset
, hstep
;
266 struct fb_info_control
*p
= (struct fb_info_control
*)info
;
267 struct fb_par_control
*par
= &p
->par
;
270 * make sure start addr will be 32-byte aligned
272 hstep
= 0x1f >> par
->cmode
;
273 xoffset
= (var
->xoffset
+ hstep
) & ~hstep
;
275 if (xoffset
+par
->xres
> par
->vxres
||
276 var
->yoffset
+par
->yres
> par
->vyres
)
279 set_screen_start(xoffset
, var
->yoffset
, p
);
286 * Private mmap since we want to have a different caching on the framebuffer
288 * Note there's no locking in here; it's done in fb_mmap() in fbmem.c.
290 static int controlfb_mmap(struct fb_info
*info
, struct file
*file
,
291 struct vm_area_struct
*vma
)
293 unsigned long off
, start
;
296 off
= vma
->vm_pgoff
<< PAGE_SHIFT
;
298 /* frame buffer memory */
299 start
= info
->fix
.smem_start
;
300 len
= PAGE_ALIGN((start
& ~PAGE_MASK
)+info
->fix
.smem_len
);
302 /* memory mapped io */
304 if (info
->var
.accel_flags
)
306 start
= info
->fix
.mmio_start
;
307 len
= PAGE_ALIGN((start
& ~PAGE_MASK
)+info
->fix
.mmio_len
);
308 pgprot_val(vma
->vm_page_prot
) |= _PAGE_NO_CACHE
|_PAGE_GUARDED
;
311 pgprot_val(vma
->vm_page_prot
) |= _PAGE_WRITETHRU
;
314 if ((vma
->vm_end
- vma
->vm_start
+ off
) > len
)
317 vma
->vm_pgoff
= off
>> PAGE_SHIFT
;
318 if (io_remap_pfn_range(vma
, vma
->vm_start
, off
>> PAGE_SHIFT
,
319 vma
->vm_end
- vma
->vm_start
, vma
->vm_page_prot
))
325 static int controlfb_blank(int blank_mode
, struct fb_info
*info
)
327 struct fb_info_control
*p
= (struct fb_info_control
*) info
;
330 ctrl
= ld_le32(CNTRL_REG(p
,ctrl
));
332 switch (blank_mode
) {
333 case FB_BLANK_VSYNC_SUSPEND
:
336 case FB_BLANK_HSYNC_SUSPEND
:
339 case FB_BLANK_POWERDOWN
:
342 case FB_BLANK_NORMAL
:
352 out_le32(CNTRL_REG(p
,ctrl
), ctrl
);
357 static int controlfb_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
358 u_int transp
, struct fb_info
*info
)
360 struct fb_info_control
*p
= (struct fb_info_control
*) info
;
370 out_8(&p
->cmap_regs
->addr
, regno
); /* tell clut what addr to fill */
371 out_8(&p
->cmap_regs
->lut
, r
); /* send one color channel at */
372 out_8(&p
->cmap_regs
->lut
, g
); /* a time... */
373 out_8(&p
->cmap_regs
->lut
, b
);
377 switch (p
->par
.cmode
) {
379 p
->pseudo_palette
[regno
] =
380 (regno
<< 10) | (regno
<< 5) | regno
;
383 i
= (regno
<< 8) | regno
;
384 p
->pseudo_palette
[regno
] = (i
<< 16) | i
;
393 /******************** End of controlfb_ops implementation ******************/
397 static void set_control_clock(unsigned char *params
)
399 #ifdef CONFIG_ADB_CUDA
400 struct adb_request req
;
403 for (i
= 0; i
< 3; ++i
) {
404 cuda_request(&req
, NULL
, 5, CUDA_PACKET
, CUDA_GET_SET_IIC
,
405 0x50, i
+ 1, params
[i
]);
406 while (!req
.complete
)
414 * finish off the driver initialization and register
416 static int __init
init_control(struct fb_info_control
*p
)
418 int full
, sense
, vmode
, cmode
, vyres
;
419 struct fb_var_screeninfo var
;
422 printk(KERN_INFO
"controlfb: ");
424 full
= p
->total_vram
== 0x400000;
426 /* Try to pick a video mode out of NVRAM if we have one. */
427 if (default_cmode
== CMODE_NVRAM
){
428 cmode
= nvram_read_byte(NV_CMODE
);
429 if(cmode
< CMODE_8
|| cmode
> CMODE_32
)
434 if (default_vmode
== VMODE_NVRAM
) {
435 vmode
= nvram_read_byte(NV_VMODE
);
436 if (vmode
< 1 || vmode
> VMODE_MAX
||
437 control_mac_modes
[vmode
- 1].m
[full
] < cmode
) {
438 sense
= read_control_sense(p
);
439 printk("Monitor sense value = 0x%x, ", sense
);
440 vmode
= mac_map_monitor_sense(sense
);
441 if (control_mac_modes
[vmode
- 1].m
[full
] < cmode
)
442 vmode
= VMODE_640_480_60
;
446 if (control_mac_modes
[vmode
- 1].m
[full
] < cmode
) {
450 vmode
= VMODE_640_480_60
;
454 /* Initialize info structure */
455 control_init_info(&p
->info
, p
);
457 /* Setup default var */
458 if (mac_vmode_to_var(vmode
, cmode
, &var
) < 0) {
459 /* This shouldn't happen! */
460 printk("mac_vmode_to_var(%d, %d,) failed\n", vmode
, cmode
);
462 vmode
= VMODE_640_480_60
;
464 if (mac_vmode_to_var(vmode
, cmode
, &var
) < 0) {
465 printk(KERN_ERR
"controlfb: mac_vmode_to_var() failed\n");
468 printk(KERN_INFO
"controlfb: ");
470 printk("using video mode %d and color mode %d.\n", vmode
, cmode
);
472 vyres
= (p
->total_vram
- CTRLFB_OFF
) / (var
.xres
<< cmode
);
473 if (vyres
> var
.yres
)
474 var
.yres_virtual
= vyres
;
476 /* Apply default var */
477 var
.activate
= FB_ACTIVATE_NOW
;
478 rc
= fb_set_var(&p
->info
, &var
);
479 if (rc
&& (vmode
!= VMODE_640_480_60
|| cmode
!= CMODE_8
))
482 /* Register with fbdev layer */
483 if (register_framebuffer(&p
->info
) < 0)
486 printk(KERN_INFO
"fb%d: control display adapter\n", p
->info
.node
);
491 #define RADACAL_WRITE(a,d) \
492 out_8(&p->cmap_regs->addr, (a)); \
493 out_8(&p->cmap_regs->dat, (d))
495 /* Now how about actually saying, Make it so! */
496 /* Some things in here probably don't need to be done each time. */
497 static void control_set_hardware(struct fb_info_control
*p
, struct fb_par_control
*par
)
499 struct control_regvals
*r
;
500 volatile struct preg __iomem
*rp
;
503 if (PAR_EQUAL(&p
->par
, par
)) {
505 * check if only xoffset or yoffset differs.
506 * this prevents flickers in typical VT switch case.
508 if (p
->par
.xoffset
!= par
->xoffset
||
509 p
->par
.yoffset
!= par
->yoffset
)
510 set_screen_start(par
->xoffset
, par
->yoffset
, p
);
516 cmode
= p
->par
.cmode
;
519 /* Turn off display */
520 out_le32(CNTRL_REG(p
,ctrl
), 0x400 | par
->ctrl
);
522 set_control_clock(r
->clock_params
);
524 RADACAL_WRITE(0x20, r
->radacal_ctrl
);
525 RADACAL_WRITE(0x21, p
->control_use_bank2
? 0 : 1);
526 RADACAL_WRITE(0x10, 0);
527 RADACAL_WRITE(0x11, 0);
529 rp
= &p
->control_regs
->vswin
;
530 for (i
= 0; i
< 16; ++i
, ++rp
)
531 out_le32(&rp
->r
, r
->regs
[i
]);
533 out_le32(CNTRL_REG(p
,pitch
), par
->pitch
);
534 out_le32(CNTRL_REG(p
,mode
), r
->mode
);
535 out_le32(CNTRL_REG(p
,vram_attr
), p
->vram_attr
);
536 out_le32(CNTRL_REG(p
,start_addr
), par
->yoffset
* par
->pitch
537 + (par
->xoffset
<< cmode
));
538 out_le32(CNTRL_REG(p
,rfrcnt
), 0x1e5);
539 out_le32(CNTRL_REG(p
,intr_ena
), 0);
541 /* Turn on display */
542 out_le32(CNTRL_REG(p
,ctrl
), par
->ctrl
);
544 #ifdef CONFIG_BOOTX_TEXT
545 btext_update_display(p
->frame_buffer_phys
+ CTRLFB_OFF
,
546 p
->par
.xres
, p
->par
.yres
,
547 (cmode
== CMODE_32
? 32: cmode
== CMODE_16
? 16: 8),
549 #endif /* CONFIG_BOOTX_TEXT */
554 * Called from fbmem.c for probing & initializing
556 int __init
control_init(void)
558 struct device_node
*dp
;
561 if (fb_get_options("controlfb", &option
))
563 control_setup(option
);
565 dp
= find_devices("control");
566 if (dp
!= 0 && !control_of_init(dp
))
572 module_init(control_init
);
574 /* Work out which banks of VRAM we have installed. */
575 /* danj: I guess the card just ignores writes to nonexistant VRAM... */
577 static void __init
find_vram_size(struct fb_info_control
*p
)
582 * Set VRAM in 2MB (bank 1) mode
583 * VRAM Bank 2 will be accessible through offset 0x600000 if present
584 * and VRAM Bank 1 will not respond at that offset even if present
586 out_le32(CNTRL_REG(p
,vram_attr
), 0x31);
588 out_8(&p
->frame_buffer
[0x600000], 0xb3);
589 out_8(&p
->frame_buffer
[0x600001], 0x71);
590 asm volatile("eieio; dcbf 0,%0" : : "r" (&p
->frame_buffer
[0x600000])
593 asm volatile("eieio; dcbi 0,%0" : : "r" (&p
->frame_buffer
[0x600000])
597 bank2
= (in_8(&p
->frame_buffer
[0x600000]) == 0xb3)
598 && (in_8(&p
->frame_buffer
[0x600001]) == 0x71);
601 * Set VRAM in 2MB (bank 2) mode
602 * VRAM Bank 1 will be accessible through offset 0x000000 if present
603 * and VRAM Bank 2 will not respond at that offset even if present
605 out_le32(CNTRL_REG(p
,vram_attr
), 0x39);
607 out_8(&p
->frame_buffer
[0], 0x5a);
608 out_8(&p
->frame_buffer
[1], 0xc7);
609 asm volatile("eieio; dcbf 0,%0" : : "r" (&p
->frame_buffer
[0])
612 asm volatile("eieio; dcbi 0,%0" : : "r" (&p
->frame_buffer
[0])
616 bank1
= (in_8(&p
->frame_buffer
[0]) == 0x5a)
617 && (in_8(&p
->frame_buffer
[1]) == 0xc7);
624 p
->control_use_bank2
= 1;
626 p
->frame_buffer
+= 0x600000;
627 p
->frame_buffer_phys
+= 0x600000;
641 p
->total_vram
= (bank1
+ bank2
) * 0x200000;
643 printk(KERN_INFO
"controlfb: VRAM Total = %dMB "
644 "(%dMB @ bank 1, %dMB @ bank 2)\n",
645 (bank1
+ bank2
) << 1, bank1
<< 1, bank2
<< 1);
650 * find "control" and initialize
652 static int __init
control_of_init(struct device_node
*dp
)
654 struct fb_info_control
*p
;
659 printk(KERN_ERR
"controlfb: only one control is supported\n");
662 if(dp
->n_addrs
!= 2) {
663 printk(KERN_ERR
"expecting 2 address for control (got %d)", dp
->n_addrs
);
666 p
= kmalloc(sizeof(*p
), GFP_KERNEL
);
669 control_fb
= p
; /* save it for cleanups */
670 memset(p
, 0, sizeof(*p
));
672 /* Map in frame buffer and registers */
673 for (i
= 0; i
< dp
->n_addrs
; ++i
) {
674 addr
= dp
->addrs
[i
].address
;
675 if (dp
->addrs
[i
].size
>= 0x800000) {
676 p
->fb_orig_base
= addr
;
677 p
->fb_orig_size
= dp
->addrs
[i
].size
;
678 /* use the big-endian aperture (??) */
679 p
->frame_buffer_phys
= addr
+ 0x800000;
681 p
->control_regs_phys
= addr
;
682 p
->control_regs_size
= dp
->addrs
[i
].size
;
686 if (!p
->fb_orig_base
||
687 !request_mem_region(p
->fb_orig_base
,p
->fb_orig_size
,"controlfb")) {
691 /* map at most 8MB for the frame buffer */
692 p
->frame_buffer
= __ioremap(p
->frame_buffer_phys
, 0x800000,
695 if (!p
->control_regs_phys
||
696 !request_mem_region(p
->control_regs_phys
, p
->control_regs_size
,
698 p
->control_regs_phys
= 0;
701 p
->control_regs
= ioremap(p
->control_regs_phys
, p
->control_regs_size
);
703 p
->cmap_regs_phys
= 0xf301b000; /* XXX not in prom? */
704 if (!request_mem_region(p
->cmap_regs_phys
, 0x1000, "controlfb cmap")) {
705 p
->cmap_regs_phys
= 0;
708 p
->cmap_regs
= ioremap(p
->cmap_regs_phys
, 0x1000);
710 if (!p
->cmap_regs
|| !p
->control_regs
|| !p
->frame_buffer
)
717 if (init_control(p
) < 0)
728 * Get the monitor sense value.
729 * Note that this can be called before calibrate_delay,
730 * so we can't use udelay.
732 static int read_control_sense(struct fb_info_control
*p
)
736 out_le32(CNTRL_REG(p
,mon_sense
), 7); /* drive all lines high */
738 out_le32(CNTRL_REG(p
,mon_sense
), 077); /* turn off drivers */
740 sense
= (in_le32(CNTRL_REG(p
,mon_sense
)) & 0x1c0) << 2;
742 /* drive each sense line low in turn and collect the other 2 */
743 out_le32(CNTRL_REG(p
,mon_sense
), 033); /* drive A low */
745 sense
|= (in_le32(CNTRL_REG(p
,mon_sense
)) & 0xc0) >> 2;
746 out_le32(CNTRL_REG(p
,mon_sense
), 055); /* drive B low */
748 sense
|= ((in_le32(CNTRL_REG(p
,mon_sense
)) & 0x100) >> 5)
749 | ((in_le32(CNTRL_REG(p
,mon_sense
)) & 0x40) >> 4);
750 out_le32(CNTRL_REG(p
,mon_sense
), 066); /* drive C low */
752 sense
|= (in_le32(CNTRL_REG(p
,mon_sense
)) & 0x180) >> 7;
754 out_le32(CNTRL_REG(p
,mon_sense
), 077); /* turn off drivers */
759 /********************** Various translation functions **********************/
761 #define CONTROL_PIXCLOCK_BASE 256016
762 #define CONTROL_PIXCLOCK_MIN 5000 /* ~ 200 MHz dot clock */
765 * calculate the clock paramaters to be sent to CUDA according to given
766 * pixclock in pico second.
768 static int calc_clock_params(unsigned long clk
, unsigned char *param
)
770 unsigned long p0
, p1
, p2
, k
, l
, m
, n
, min
;
772 if (clk
> (CONTROL_PIXCLOCK_BASE
<< 3))
775 p2
= ((clk
<< 4) < CONTROL_PIXCLOCK_BASE
)? 3: 2;
779 for (k
= 1, min
= l
; k
< 32; k
++) {
782 m
= CONTROL_PIXCLOCK_BASE
* k
;
785 if (n
&& (n
< 128) && rem
< min
) {
803 * This routine takes a user-supplied var, and picks the best vmode/cmode
807 static int control_var_to_par(struct fb_var_screeninfo
*var
,
808 struct fb_par_control
*par
, const struct fb_info
*fb_info
)
810 int cmode
, piped_diff
, hstep
;
811 unsigned hperiod
, hssync
, hsblank
, hesync
, heblank
, piped
, heq
, hlfln
,
812 hserr
, vperiod
, vssync
, vesync
, veblank
, vsblank
, vswin
, vewin
;
813 unsigned long pixclock
;
814 struct fb_info_control
*p
= (struct fb_info_control
*) fb_info
;
815 struct control_regvals
*r
= &par
->regvals
;
817 switch (var
->bits_per_pixel
) {
819 par
->cmode
= CMODE_8
;
820 if (p
->total_vram
> 0x200000) {
822 r
->radacal_ctrl
= 0x20;
826 r
->radacal_ctrl
= 0x10;
832 par
->cmode
= CMODE_16
;
833 if (p
->total_vram
> 0x200000) {
835 r
->radacal_ctrl
= 0x24;
839 r
->radacal_ctrl
= 0x14;
844 par
->cmode
= CMODE_32
;
845 if (p
->total_vram
> 0x200000) {
847 r
->radacal_ctrl
= 0x28;
850 r
->radacal_ctrl
= 0x18;
859 * adjust xres and vxres so that the corresponding memory widths are
862 hstep
= 31 >> par
->cmode
;
863 par
->xres
= (var
->xres
+ hstep
) & ~hstep
;
864 par
->vxres
= (var
->xres_virtual
+ hstep
) & ~hstep
;
865 par
->xoffset
= (var
->xoffset
+ hstep
) & ~hstep
;
866 if (par
->vxres
< par
->xres
)
867 par
->vxres
= par
->xres
;
868 par
->pitch
= par
->vxres
<< par
->cmode
;
870 par
->yres
= var
->yres
;
871 par
->vyres
= var
->yres_virtual
;
872 par
->yoffset
= var
->yoffset
;
873 if (par
->vyres
< par
->yres
)
874 par
->vyres
= par
->yres
;
876 par
->sync
= var
->sync
;
878 if (par
->pitch
* par
->vyres
+ CTRLFB_OFF
> p
->total_vram
)
881 if (par
->xoffset
+ par
->xres
> par
->vxres
)
882 par
->xoffset
= par
->vxres
- par
->xres
;
883 if (par
->yoffset
+ par
->yres
> par
->vyres
)
884 par
->yoffset
= par
->vyres
- par
->yres
;
886 pixclock
= (var
->pixclock
< CONTROL_PIXCLOCK_MIN
)? CONTROL_PIXCLOCK_MIN
:
888 if (calc_clock_params(pixclock
, r
->clock_params
))
891 hperiod
= ((var
->left_margin
+ par
->xres
+ var
->right_margin
892 + var
->hsync_len
) >> 1) - 2;
893 hssync
= hperiod
+ 1;
894 hsblank
= hssync
- (var
->right_margin
>> 1);
895 hesync
= (var
->hsync_len
>> 1) - 1;
896 heblank
= (var
->left_margin
>> 1) + hesync
;
897 piped
= heblank
- piped_diff
;
898 heq
= var
->hsync_len
>> 2;
899 hlfln
= (hperiod
+2) >> 1;
900 hserr
= hssync
-hesync
;
901 vperiod
= (var
->vsync_len
+ var
->lower_margin
+ par
->yres
902 + var
->upper_margin
) << 1;
903 vssync
= vperiod
- 2;
904 vesync
= (var
->vsync_len
<< 1) - vperiod
+ vssync
;
905 veblank
= (var
->upper_margin
<< 1) + vesync
;
906 vsblank
= vssync
- (var
->lower_margin
<< 1);
907 vswin
= (vsblank
+vssync
) >> 1;
908 vewin
= (vesync
+veblank
) >> 1;
911 r
->regs
[1] = vsblank
;
912 r
->regs
[2] = veblank
;
916 r
->regs
[6] = vperiod
;
918 r
->regs
[8] = hperiod
;
919 r
->regs
[9] = hsblank
;
920 r
->regs
[10] = heblank
;
921 r
->regs
[11] = hesync
;
922 r
->regs
[12] = hssync
;
927 if (par
->xres
>= 1280 && par
->cmode
>= CMODE_16
)
932 if (mac_var_to_vmode(var
, &par
->vmode
, &cmode
))
940 * Convert hardware data in par to an fb_var_screeninfo
943 static void control_par_to_var(struct fb_par_control
*par
, struct fb_var_screeninfo
*var
)
945 struct control_regints
*rv
;
947 rv
= (struct control_regints
*) par
->regvals
.regs
;
949 memset(var
, 0, sizeof(*var
));
950 var
->xres
= par
->xres
;
951 var
->yres
= par
->yres
;
952 var
->xres_virtual
= par
->vxres
;
953 var
->yres_virtual
= par
->vyres
;
954 var
->xoffset
= par
->xoffset
;
955 var
->yoffset
= par
->yoffset
;
960 var
->bits_per_pixel
= 8;
962 var
->green
.length
= 8;
963 var
->blue
.length
= 8;
965 case CMODE_16
: /* RGB 555 */
966 var
->bits_per_pixel
= 16;
967 var
->red
.offset
= 10;
969 var
->green
.offset
= 5;
970 var
->green
.length
= 5;
971 var
->blue
.length
= 5;
973 case CMODE_32
: /* RGB 888 */
974 var
->bits_per_pixel
= 32;
975 var
->red
.offset
= 16;
977 var
->green
.offset
= 8;
978 var
->green
.length
= 8;
979 var
->blue
.length
= 8;
980 var
->transp
.offset
= 24;
981 var
->transp
.length
= 8;
986 var
->vmode
= FB_VMODE_NONINTERLACED
;
988 var
->left_margin
= (rv
->heblank
- rv
->hesync
) << 1;
989 var
->right_margin
= (rv
->hssync
- rv
->hsblank
) << 1;
990 var
->hsync_len
= (rv
->hperiod
+ 2 - rv
->hssync
+ rv
->hesync
) << 1;
992 var
->upper_margin
= (rv
->veblank
- rv
->vesync
) >> 1;
993 var
->lower_margin
= (rv
->vssync
- rv
->vsblank
) >> 1;
994 var
->vsync_len
= (rv
->vperiod
- rv
->vssync
+ rv
->vesync
) >> 1;
996 var
->sync
= par
->sync
;
999 * 10^12 * clock_params[0] / (3906400 * clock_params[1]
1000 * * 2^clock_params[2])
1001 * (10^12 * clock_params[0] / (3906400 * clock_params[1]))
1002 * >> clock_params[2]
1004 /* (255990.17 * clock_params[0] / clock_params[1]) >> clock_params[2] */
1005 var
->pixclock
= CONTROL_PIXCLOCK_BASE
* par
->regvals
.clock_params
[0];
1006 var
->pixclock
/= par
->regvals
.clock_params
[1];
1007 var
->pixclock
>>= par
->regvals
.clock_params
[2];
1011 * Set misc info vars for this driver
1013 static void __init
control_init_info(struct fb_info
*info
, struct fb_info_control
*p
)
1016 info
->par
= &p
->par
;
1017 info
->fbops
= &controlfb_ops
;
1018 info
->pseudo_palette
= p
->pseudo_palette
;
1019 info
->flags
= FBINFO_DEFAULT
| FBINFO_HWACCEL_YPAN
;
1020 info
->screen_base
= p
->frame_buffer
+ CTRLFB_OFF
;
1022 fb_alloc_cmap(&info
->cmap
, 256, 0);
1024 /* Fill fix common fields */
1025 strcpy(info
->fix
.id
, "control");
1026 info
->fix
.mmio_start
= p
->control_regs_phys
;
1027 info
->fix
.mmio_len
= sizeof(struct control_regs
);
1028 info
->fix
.type
= FB_TYPE_PACKED_PIXELS
;
1029 info
->fix
.smem_start
= p
->frame_buffer_phys
+ CTRLFB_OFF
;
1030 info
->fix
.smem_len
= p
->total_vram
- CTRLFB_OFF
;
1031 info
->fix
.ywrapstep
= 0;
1032 info
->fix
.type_aux
= 0;
1033 info
->fix
.accel
= FB_ACCEL_NONE
;
1037 static void control_cleanup(void)
1039 struct fb_info_control
*p
= control_fb
;
1045 iounmap(p
->cmap_regs
);
1046 if (p
->control_regs
)
1047 iounmap(p
->control_regs
);
1048 if (p
->frame_buffer
) {
1049 if (p
->control_use_bank2
)
1050 p
->frame_buffer
-= 0x600000;
1051 iounmap(p
->frame_buffer
);
1053 if (p
->cmap_regs_phys
)
1054 release_mem_region(p
->cmap_regs_phys
, 0x1000);
1055 if (p
->control_regs_phys
)
1056 release_mem_region(p
->control_regs_phys
, p
->control_regs_size
);
1057 if (p
->fb_orig_base
)
1058 release_mem_region(p
->fb_orig_base
, p
->fb_orig_size
);
1064 * Parse user speficied options (`video=controlfb:')
1066 void __init
control_setup(char *options
)
1070 if (!options
|| !*options
)
1073 while ((this_opt
= strsep(&options
, ",")) != NULL
) {
1074 if (!strncmp(this_opt
, "vmode:", 6)) {
1075 int vmode
= simple_strtoul(this_opt
+6, NULL
, 0);
1076 if (vmode
> 0 && vmode
<= VMODE_MAX
&&
1077 control_mac_modes
[vmode
- 1].m
[1] >= 0)
1078 default_vmode
= vmode
;
1079 } else if (!strncmp(this_opt
, "cmode:", 6)) {
1080 int depth
= simple_strtoul(this_opt
+6, NULL
, 0);
1085 default_cmode
= depth
;
1088 default_cmode
= CMODE_8
;
1092 default_cmode
= CMODE_16
;
1096 default_cmode
= CMODE_32
;