1 /* $Id: atyfb.c,v 1.122 1999/09/06 20:44:08 geert Exp $
2 * linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
4 * Copyright (C) 1997-1998 Geert Uytterhoeven
5 * Copyright (C) 1998 Bernd Harries
6 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
8 * This driver is partly based on the PowerMac console driver:
10 * Copyright (C) 1996 Paul Mackerras
12 * and on the PowerMac ATI/mach64 display driver:
14 * Copyright (C) 1997 Michael AK Tesch
16 * with work by Jon Howell
18 * Anthony Tong <atong@uiuc.edu>
20 * This file is subject to the terms and conditions of the GNU General Public
21 * License. See the file COPYING in the main directory of this archive for
25 /******************************************************************************
29 - cursor support on all cards and all ramdacs.
30 - cursor parameters controlable via ioctl()s.
31 - guess PLL and MCLK based on the original PLL register values initialized
32 by the BIOS or Open Firmware (if they are initialized).
34 (Anyone to help with this?)
36 ******************************************************************************/
39 #include <linux/config.h>
40 #include <linux/module.h>
41 #include <linux/kernel.h>
42 #include <linux/errno.h>
43 #include <linux/string.h>
45 #include <linux/tty.h>
46 #include <linux/malloc.h>
47 #include <linux/vmalloc.h>
48 #include <linux/delay.h>
49 #include <linux/interrupt.h>
51 #include <linux/selection.h>
52 #include <linux/console.h>
53 #include <linux/init.h>
54 #include <linux/pci.h>
55 #include <linux/nvram.h>
57 #include <linux/vt_kern.h>
59 #ifdef CONFIG_FB_COMPAT_XPMAC
60 #include <asm/vc_ioctl.h>
65 #if defined(CONFIG_PPC)
67 #include <asm/pci-bridge.h>
68 #include <video/macmodes.h>
76 #include <asm/uaccess.h>
78 #include <video/fbcon.h>
79 #include <video/fbcon-cfb8.h>
80 #include <video/fbcon-cfb16.h>
81 #include <video/fbcon-cfb24.h>
82 #include <video/fbcon-cfb32.h>
92 /* Definitions for the ICS 2595 == ATI 18818_1 Clockchip */
94 #define REF_FREQ_2595 1432 /* 14.33 MHz (exact 14.31818) */
95 #define REF_DIV_2595 46 /* really 43 on ICS 2595 !!! */
97 #define MAX_FREQ_2595 15938 /* 159.38 MHz (really 170.486) */
98 #define MIN_FREQ_2595 8000 /* 80.00 MHz ( 85.565) */
99 /* mit Prescaler 2, 4, 8 */
100 #define ABS_MIN_FREQ_2595 1000 /* 10.00 MHz (really 10.697) */
101 #define N_ADJ_2595 257
103 #define STOP_BITS_2595 0x1800
116 /* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */
117 /* - must be large enough to catch all GUI-Regs */
118 /* - must be aligned to a PAGE boundary */
119 #define GUI_RESERVE (1 * PAGE_SIZE)
123 #define eieio() /* Enforce In-order Execution of I/O */
126 /* FIXME: remove the FAIL definition */
127 #define FAIL(x) do { printk(x "\n"); return -EINVAL; } while (0)
131 * Elements of the Hardware specific atyfb_par structure
146 u32 dp_pix_width
; /* acceleration */
147 u32 dp_chain_mask
; /* acceleration */
171 u32 dsp_config
; /* Mach64 GTB DSP */
172 u32 dsp_on_off
; /* Mach64 GTB DSP */
173 u8 mclk_post_div_real
;
174 u8 vclk_post_div_real
;
179 * The Hardware parameters for each card
187 struct pll_18818 ics2595
;
192 struct aty_cmap_regs
{
200 struct pci_mmap_map
{
204 unsigned long prot_flag
;
205 unsigned long prot_mask
;
208 #define DEFAULT_CURSOR_BLINK_RATE (20)
209 #define CURSOR_DRAW_DELAY (2)
224 struct timer_list
*timer
;
228 struct fb_info fb_info
;
229 struct fb_info_aty
*next
;
230 unsigned long ati_regbase_phys
;
231 unsigned long ati_regbase
;
232 unsigned long frame_buffer_phys
;
233 unsigned long frame_buffer
;
234 unsigned long clk_wr_offset
;
235 struct pci_mmap_map
*mmap_map
;
236 struct aty_cursor
*cursor
;
237 struct aty_cmap_regs
*aty_cmap_regs
;
238 struct { u8 red
, green
, blue
, pad
; } palette
[256];
239 struct atyfb_par default_par
;
240 struct atyfb_par current_par
;
246 #define Gx info->chip_type
248 #define Rev info->chip_rev
256 struct display_switch dispsw
;
258 #ifdef FBCON_HAS_CFB16
261 #ifdef FBCON_HAS_CFB24
264 #ifdef FBCON_HAS_CFB32
268 u8 blitter_may_be_busy
;
279 * Frame buffer device API
282 static int atyfb_open(struct fb_info
*info
, int user
);
283 static int atyfb_release(struct fb_info
*info
, int user
);
284 static int atyfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
286 static int atyfb_get_var(struct fb_var_screeninfo
*var
, int con
,
288 static int atyfb_set_var(struct fb_var_screeninfo
*var
, int con
,
290 static int atyfb_pan_display(struct fb_var_screeninfo
*var
, int con
,
292 static int atyfb_get_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
293 struct fb_info
*info
);
294 static int atyfb_set_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
295 struct fb_info
*info
);
296 static int atyfb_ioctl(struct inode
*inode
, struct file
*file
, u_int cmd
,
297 u_long arg
, int con
, struct fb_info
*info
);
299 static int atyfb_mmap(struct fb_info
*info
, struct file
*file
,
300 struct vm_area_struct
*vma
);
302 static int atyfb_rasterimg(struct fb_info
*info
, int start
);
306 * Interface to the low level console driver
309 static int atyfbcon_switch(int con
, struct fb_info
*fb
);
310 static int atyfbcon_updatevar(int con
, struct fb_info
*fb
);
311 static void atyfbcon_blank(int blank
, struct fb_info
*fb
);
315 * Text console acceleration
318 static void fbcon_aty_bmove(struct display
*p
, int sy
, int sx
, int dy
, int dx
,
319 int height
, int width
);
320 static void fbcon_aty_clear(struct vc_data
*conp
, struct display
*p
, int sy
,
321 int sx
, int height
, int width
);
322 #ifdef FBCON_HAS_CFB8
323 static struct display_switch fbcon_aty8
;
324 static void fbcon_aty8_putc(struct vc_data
*conp
, struct display
*p
, int c
,
326 static void fbcon_aty8_putcs(struct vc_data
*conp
, struct display
*p
,
327 const unsigned short *s
, int count
, int yy
,
330 #ifdef FBCON_HAS_CFB16
331 static struct display_switch fbcon_aty16
;
332 static void fbcon_aty16_putc(struct vc_data
*conp
, struct display
*p
, int c
,
334 static void fbcon_aty16_putcs(struct vc_data
*conp
, struct display
*p
,
335 const unsigned short *s
, int count
, int yy
,
338 #ifdef FBCON_HAS_CFB24
339 static struct display_switch fbcon_aty24
;
340 static void fbcon_aty24_putc(struct vc_data
*conp
, struct display
*p
, int c
,
342 static void fbcon_aty24_putcs(struct vc_data
*conp
, struct display
*p
,
343 const unsigned short *s
, int count
, int yy
,
346 #ifdef FBCON_HAS_CFB32
347 static struct display_switch fbcon_aty32
;
348 static void fbcon_aty32_putc(struct vc_data
*conp
, struct display
*p
, int c
,
350 static void fbcon_aty32_putcs(struct vc_data
*conp
, struct display
*p
,
351 const unsigned short *s
, int count
, int yy
,
360 static int aty_init(struct fb_info_aty
*info
, const char *name
);
361 static struct aty_cursor
*aty_init_cursor(struct fb_info_aty
*fb
);
363 static int store_video_par(char *videopar
, unsigned char m64_num
);
364 static char *strtoke(char *s
, const char *ct
);
367 static void reset_engine(const struct fb_info_aty
*info
);
368 static void init_engine(const struct atyfb_par
*par
, struct fb_info_aty
*info
);
370 static void aty_st_514(int offset
, u8 val
, const struct fb_info_aty
*info
);
371 static void aty_st_pll(int offset
, u8 val
, const struct fb_info_aty
*info
);
372 static u8
aty_ld_pll(int offset
, const struct fb_info_aty
*info
);
373 static void aty_set_crtc(const struct fb_info_aty
*info
,
374 const struct crtc
*crtc
);
375 static int aty_var_to_crtc(const struct fb_info_aty
*info
,
376 const struct fb_var_screeninfo
*var
,
378 static void aty_set_dac_514(const struct fb_info_aty
*info
, u32 bpp
);
379 static int aty_crtc_to_var(const struct crtc
*crtc
,
380 struct fb_var_screeninfo
*var
);
381 static void aty_set_pll_gx(const struct fb_info_aty
*info
,
382 const struct pll_gx
*pll
);
384 static int aty_set_dac_ATI68860_B(const struct fb_info_aty
*info
, u32 bpp
,
386 static int aty_set_dac_ATT21C498(const struct fb_info_aty
*info
,
387 const struct pll_18818
*pll
, u32 bpp
);
388 void aty_dac_waste4(const struct fb_info_aty
*info
);
390 static int aty_var_to_pll_18818(u32 period_in_ps
, struct pll_18818
*pll
);
391 static u32
aty_pll_18818_to_var(const struct pll_18818
*pll
);
392 static void aty_set_pll18818(const struct fb_info_aty
*info
,
393 const struct pll_18818
*pll
);
395 static void aty_StrobeClock(const struct fb_info_aty
*info
);
397 static void aty_ICS2595_put1bit(u8 data
, const struct fb_info_aty
*info
);
399 static int aty_var_to_pll_408(u32 period_in_ps
, struct pll_18818
*pll
);
400 static u32
aty_pll_408_to_var(const struct pll_18818
*pll
);
401 static void aty_set_pll_408(const struct fb_info_aty
*info
,
402 const struct pll_18818
*pll
);
404 static int aty_var_to_pll_1703(u32 period_in_ps
, struct pll_18818
*pll
);
405 static u32
aty_pll_1703_to_var(const struct pll_18818
*pll
);
406 static void aty_set_pll_1703(const struct fb_info_aty
*info
,
407 const struct pll_18818
*pll
);
409 static int aty_var_to_pll_8398(u32 period_in_ps
, struct pll_18818
*pll
);
410 static u32
aty_pll_8398_to_var(const struct pll_18818
*pll
);
411 static void aty_set_pll_8398(const struct fb_info_aty
*info
,
412 const struct pll_18818
*pll
);
414 static int aty_var_to_pll_514(u32 vclk_per
, struct pll_gx
*pll
);
415 static u32
aty_pll_gx_to_var(const struct pll_gx
*pll
,
416 const struct fb_info_aty
*info
);
417 static void aty_set_pll_ct(const struct fb_info_aty
*info
,
418 const struct pll_ct
*pll
);
419 static int aty_valid_pll_ct(const struct fb_info_aty
*info
, u32 vclk_per
,
421 static int aty_dsp_gt(const struct fb_info_aty
*info
, u8 bpp
,
423 static void aty_calc_pll_ct(const struct fb_info_aty
*info
,
425 static int aty_var_to_pll_ct(const struct fb_info_aty
*info
, u32 vclk_per
,
426 u8 bpp
, struct pll_ct
*pll
);
427 static u32
aty_pll_ct_to_var(const struct pll_ct
*pll
,
428 const struct fb_info_aty
*info
);
429 static void atyfb_set_par(const struct atyfb_par
*par
,
430 struct fb_info_aty
*info
);
431 static int atyfb_decode_var(const struct fb_var_screeninfo
*var
,
432 struct atyfb_par
*par
,
433 const struct fb_info_aty
*info
);
434 static int atyfb_encode_var(struct fb_var_screeninfo
*var
,
435 const struct atyfb_par
*par
,
436 const struct fb_info_aty
*info
);
437 static void set_off_pitch(struct atyfb_par
*par
,
438 const struct fb_info_aty
*info
);
439 static int encode_fix(struct fb_fix_screeninfo
*fix
,
440 const struct atyfb_par
*par
,
441 const struct fb_info_aty
*info
);
442 static void atyfb_set_disp(struct display
*disp
, struct fb_info_aty
*info
,
444 static int atyfb_getcolreg(u_int regno
, u_int
*red
, u_int
*green
, u_int
*blue
,
445 u_int
*transp
, struct fb_info
*fb
);
446 static int atyfb_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
447 u_int transp
, struct fb_info
*fb
);
448 static void do_install_cmap(int con
, struct fb_info
*info
);
449 #if defined(CONFIG_PPC)
450 static int read_aty_sense(const struct fb_info_aty
*info
);
455 * Interface used by the world
458 int atyfb_init(void);
460 void atyfb_of_init(struct device_node
*dp
);
463 int atyfb_setup(char*);
466 static int currcon
= 0;
468 static struct fb_ops atyfb_ops
= {
469 atyfb_open
, atyfb_release
, atyfb_get_fix
, atyfb_get_var
, atyfb_set_var
,
470 atyfb_get_cmap
, atyfb_set_cmap
, atyfb_pan_display
, atyfb_ioctl
,
479 static char atyfb_name
[16] = "ATY Mach64";
480 static char fontname
[40] __initdata
= { 0 };
481 static char curblink __initdata
= 1;
482 static char noaccel __initdata
= 0;
483 static u32 default_vram __initdata
= 0;
484 static int default_pll __initdata
= 0;
485 static int default_mclk __initdata
= 0;
488 static const char *mode_option __initdata
= NULL
;
491 #if defined(CONFIG_PPC)
492 static int default_vmode __initdata
= VMODE_NVRAM
;
493 static int default_cmode __initdata
= CMODE_NVRAM
;
497 static unsigned int mach64_count __initdata
= 0;
498 static unsigned long phys_vmembase
[FB_MAX
] __initdata
= { 0, };
499 static unsigned long phys_size
[FB_MAX
] __initdata
= { 0, };
500 static unsigned long phys_guiregbase
[FB_MAX
] __initdata
= { 0, };
504 static struct aty_features
{
508 } aty_features
[] __initdata
= {
509 /* mach64GX family */
510 { 0x4758, 0x00d7, "mach64GX (ATI888GX00)" },
511 { 0x4358, 0x0057, "mach64CX (ATI888CX00)" },
513 /* mach64CT family */
514 { 0x4354, 0x4354, "mach64CT (ATI264CT)" },
515 { 0x4554, 0x4554, "mach64ET (ATI264ET)" },
517 /* mach64CT family / mach64VT class */
518 { 0x5654, 0x5654, "mach64VT (ATI264VT)" },
519 { 0x5655, 0x5655, "mach64VTB (ATI264VTB)" },
520 { 0x5656, 0x5656, "mach64VT4 (ATI264VT4)" },
522 /* mach64CT family / mach64GT (3D RAGE) class */
523 { 0x4c42, 0x4c42, "3D RAGE LT PRO (AGP)" },
524 { 0x4c44, 0x4c44, "3D RAGE LT PRO" },
525 { 0x4c47, 0x4c47, "3D RAGE LT PRO" },
526 { 0x4c49, 0x4c49, "3D RAGE LT PRO" },
527 { 0x4c50, 0x4c50, "3D RAGE LT PRO" },
528 { 0x4c54, 0x4c54, "3D RAGE LT" },
529 { 0x4754, 0x4754, "3D RAGE (GT)" },
530 { 0x4755, 0x4755, "3D RAGE II+ (GTB)" },
531 { 0x4756, 0x4756, "3D RAGE IIC (PCI)" },
532 { 0x4757, 0x4757, "3D RAGE IIC (AGP)" },
533 { 0x475a, 0x475a, "3D RAGE IIC (AGP)" },
534 { 0x4742, 0x4742, "3D RAGE PRO (BGA, AGP)" },
535 { 0x4744, 0x4744, "3D RAGE PRO (BGA, AGP, 1x only)" },
536 { 0x4749, 0x4749, "3D RAGE PRO (BGA, PCI)" },
537 { 0x4750, 0x4750, "3D RAGE PRO (PQFP, PCI)" },
538 { 0x4751, 0x4751, "3D RAGE PRO (PQFP, PCI, limited 3D)" },
541 static const char *aty_gx_ram
[8] __initdata
= {
542 "DRAM", "VRAM", "VRAM", "DRAM", "DRAM", "VRAM", "VRAM", "RESV"
545 static const char *aty_ct_ram
[8] __initdata
= {
546 "OFF", "DRAM", "EDO", "EDO", "SDRAM", "SGRAM", "WRAM", "RESV"
550 static inline u32
aty_ld_le32(unsigned int regindex
,
551 const struct fb_info_aty
*info
)
556 #if defined(__powerpc__)
557 temp
= info
->ati_regbase
;
558 asm volatile("lwbrx %0,%1,%2" : "=r"(val
) : "b" (regindex
), "r" (temp
));
559 #elif defined(__sparc_v9__)
560 temp
= info
->ati_regbase
+ regindex
;
563 temp
= info
->ati_regbase
+regindex
;
564 val
= le32_to_cpu(*((volatile u32
*)(temp
)));
569 static inline void aty_st_le32(unsigned int regindex
, u32 val
,
570 const struct fb_info_aty
*info
)
574 #if defined(__powerpc__)
575 temp
= info
->ati_regbase
;
576 asm volatile("stwbrx %0,%1,%2" : : "r" (val
), "b" (regindex
), "r" (temp
) :
578 #elif defined(__sparc_v9__)
579 temp
= info
->ati_regbase
+ regindex
;
582 temp
= info
->ati_regbase
+regindex
;
583 *((volatile u32
*)(temp
)) = cpu_to_le32(val
);
587 static inline u8
aty_ld_8(unsigned int regindex
,
588 const struct fb_info_aty
*info
)
591 return readb(info
->ati_regbase
+ regindex
);
593 return *(volatile u8
*)(info
->ati_regbase
+regindex
);
597 static inline void aty_st_8(unsigned int regindex
, u8 val
,
598 const struct fb_info_aty
*info
)
601 writeb(val
, info
->ati_regbase
+ regindex
);
603 *(volatile u8
*)(info
->ati_regbase
+regindex
) = val
;
609 * Generic Mach64 routines
613 * All writes to draw engine registers are automatically routed through a
614 * 32-bit-wide, 16-entry-deep command FIFO ...
615 * Register writes to registers with DWORD offsets less than 40h are not
617 * (from Chapter 5 of the Mach64 Programmer's Guide)
620 static inline void wait_for_fifo(u16 entries
, const struct fb_info_aty
*info
)
622 while ((aty_ld_le32(FIFO_STAT
, info
) & 0xffff) >
623 ((u32
)(0x8000 >> entries
)));
626 static inline void wait_for_idle(struct fb_info_aty
*info
)
628 wait_for_fifo(16, info
);
629 while ((aty_ld_le32(GUI_STAT
, info
) & 1)!= 0);
630 info
->blitter_may_be_busy
= 0;
633 static void reset_engine(const struct fb_info_aty
*info
)
636 aty_st_le32(GEN_TEST_CNTL
,
637 aty_ld_le32(GEN_TEST_CNTL
, info
) & ~GUI_ENGINE_ENABLE
, info
);
639 aty_st_le32(GEN_TEST_CNTL
,
640 aty_ld_le32(GEN_TEST_CNTL
, info
) | GUI_ENGINE_ENABLE
, info
);
641 /* ensure engine is not locked up by clearing any FIFO or */
643 aty_st_le32(BUS_CNTL
, aty_ld_le32(BUS_CNTL
, info
) | BUS_HOST_ERR_ACK
|
644 BUS_FIFO_ERR_ACK
, info
);
647 static void init_engine(const struct atyfb_par
*par
, struct fb_info_aty
*info
)
651 /* determine modal information from global mode structure */
652 pitch_value
= par
->crtc
.vxres
;
654 if (par
->crtc
.bpp
== 24) {
655 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
656 /* horizontal coordinates and widths must be adjusted */
657 pitch_value
= pitch_value
* 3;
660 /* Reset engine, enable, and clear any engine errors */
662 /* Ensure that vga page pointers are set to zero - the upper */
663 /* page pointers are set to 1 to handle overflows in the */
665 aty_st_le32(MEM_VGA_WP_SEL
, 0x00010000, info
);
666 aty_st_le32(MEM_VGA_RP_SEL
, 0x00010000, info
);
668 /* ---- Setup standard engine context ---- */
670 /* All GUI registers here are FIFOed - therefore, wait for */
671 /* the appropriate number of empty FIFO entries */
672 wait_for_fifo(14, info
);
674 /* enable all registers to be loaded for context loads */
675 aty_st_le32(CONTEXT_MASK
, 0xFFFFFFFF, info
);
677 /* set destination pitch to modal pitch, set offset to zero */
678 aty_st_le32(DST_OFF_PITCH
, (pitch_value
/ 8) << 22, info
);
680 /* zero these registers (set them to a known state) */
681 aty_st_le32(DST_Y_X
, 0, info
);
682 aty_st_le32(DST_HEIGHT
, 0, info
);
683 aty_st_le32(DST_BRES_ERR
, 0, info
);
684 aty_st_le32(DST_BRES_INC
, 0, info
);
685 aty_st_le32(DST_BRES_DEC
, 0, info
);
687 /* set destination drawing attributes */
688 aty_st_le32(DST_CNTL
, DST_LAST_PEL
| DST_Y_TOP_TO_BOTTOM
|
689 DST_X_LEFT_TO_RIGHT
, info
);
691 /* set source pitch to modal pitch, set offset to zero */
692 aty_st_le32(SRC_OFF_PITCH
, (pitch_value
/ 8) << 22, info
);
694 /* set these registers to a known state */
695 aty_st_le32(SRC_Y_X
, 0, info
);
696 aty_st_le32(SRC_HEIGHT1_WIDTH1
, 1, info
);
697 aty_st_le32(SRC_Y_X_START
, 0, info
);
698 aty_st_le32(SRC_HEIGHT2_WIDTH2
, 1, info
);
700 /* set source pixel retrieving attributes */
701 aty_st_le32(SRC_CNTL
, SRC_LINE_X_LEFT_TO_RIGHT
, info
);
703 /* set host attributes */
704 wait_for_fifo(13, info
);
705 aty_st_le32(HOST_CNTL
, 0, info
);
707 /* set pattern attributes */
708 aty_st_le32(PAT_REG0
, 0, info
);
709 aty_st_le32(PAT_REG1
, 0, info
);
710 aty_st_le32(PAT_CNTL
, 0, info
);
712 /* set scissors to modal size */
713 aty_st_le32(SC_LEFT
, 0, info
);
714 aty_st_le32(SC_TOP
, 0, info
);
715 aty_st_le32(SC_BOTTOM
, par
->crtc
.vyres
-1, info
);
716 aty_st_le32(SC_RIGHT
, pitch_value
-1, info
);
718 /* set background color to minimum value (usually BLACK) */
719 aty_st_le32(DP_BKGD_CLR
, 0, info
);
721 /* set foreground color to maximum value (usually WHITE) */
722 aty_st_le32(DP_FRGD_CLR
, 0xFFFFFFFF, info
);
724 /* set write mask to effect all pixel bits */
725 aty_st_le32(DP_WRITE_MASK
, 0xFFFFFFFF, info
);
727 /* set foreground mix to overpaint and background mix to */
729 aty_st_le32(DP_MIX
, FRGD_MIX_S
| BKGD_MIX_D
, info
);
731 /* set primary source pixel channel to foreground color */
733 aty_st_le32(DP_SRC
, FRGD_SRC_FRGD_CLR
, info
);
735 /* set compare functionality to false (no-effect on */
737 wait_for_fifo(3, info
);
738 aty_st_le32(CLR_CMP_CLR
, 0, info
);
739 aty_st_le32(CLR_CMP_MASK
, 0xFFFFFFFF, info
);
740 aty_st_le32(CLR_CMP_CNTL
, 0, info
);
742 /* set pixel depth */
743 wait_for_fifo(2, info
);
744 aty_st_le32(DP_PIX_WIDTH
, par
->crtc
.dp_pix_width
, info
);
745 aty_st_le32(DP_CHAIN_MASK
, par
->crtc
.dp_chain_mask
, info
);
747 wait_for_fifo(5, info
);
748 aty_st_le32(SCALE_3D_CNTL
, 0, info
);
749 aty_st_le32(Z_CNTL
, 0, info
);
750 aty_st_le32(CRTC_INT_CNTL
, aty_ld_le32(CRTC_INT_CNTL
, info
) & ~0x20, info
);
751 aty_st_le32(GUI_TRAJ_CNTL
, 0x100023, info
);
753 /* insure engine is idle before leaving */
757 static void aty_st_514(int offset
, u8 val
, const struct fb_info_aty
*info
)
759 aty_st_8(DAC_CNTL
, 1, info
);
760 /* right addr byte */
761 aty_st_8(DAC_W_INDEX
, offset
& 0xff, info
);
763 aty_st_8(DAC_DATA
, (offset
>> 8) & 0xff, info
);
765 aty_st_8(DAC_MASK
, val
, info
);
767 aty_st_8(DAC_CNTL
, 0, info
);
770 static void aty_st_pll(int offset
, u8 val
, const struct fb_info_aty
*info
)
772 /* write addr byte */
773 aty_st_8(CLOCK_CNTL
+ 1, (offset
<< 2) | PLL_WR_EN
, info
);
775 /* write the register value */
776 aty_st_8(CLOCK_CNTL
+ 2, val
, info
);
778 aty_st_8(CLOCK_CNTL
+ 1, (offset
<< 2) & ~PLL_WR_EN
, info
);
781 static u8
aty_ld_pll(int offset
, const struct fb_info_aty
*info
)
785 /* write addr byte */
786 aty_st_8(CLOCK_CNTL
+ 1, (offset
<< 2), info
);
788 /* read the register value */
789 res
= aty_ld_8(CLOCK_CNTL
+ 2, info
);
794 #if defined(CONFIG_PPC)
797 * Apple monitor sense
800 static int read_aty_sense(const struct fb_info_aty
*info
)
804 aty_st_le32(GP_IO
, 0x31003100, info
); /* drive outputs high */
806 aty_st_le32(GP_IO
, 0, info
); /* turn off outputs */
808 i
= aty_ld_le32(GP_IO
, info
); /* get primary sense value */
809 sense
= ((i
& 0x3000) >> 3) | (i
& 0x100);
811 /* drive each sense line low in turn and collect the other 2 */
812 aty_st_le32(GP_IO
, 0x20000000, info
); /* drive A low */
814 i
= aty_ld_le32(GP_IO
, info
);
815 sense
|= ((i
& 0x1000) >> 7) | ((i
& 0x100) >> 4);
816 aty_st_le32(GP_IO
, 0x20002000, info
); /* drive A high again */
819 aty_st_le32(GP_IO
, 0x10000000, info
); /* drive B low */
821 i
= aty_ld_le32(GP_IO
, info
);
822 sense
|= ((i
& 0x2000) >> 10) | ((i
& 0x100) >> 6);
823 aty_st_le32(GP_IO
, 0x10001000, info
); /* drive B high again */
826 aty_st_le32(GP_IO
, 0x01000000, info
); /* drive C low */
828 sense
|= (aty_ld_le32(GP_IO
, info
) & 0x3000) >> 12;
829 aty_st_le32(GP_IO
, 0, info
); /* turn off outputs */
834 #endif /* defined(CONFIG_PPC) */
836 /* ------------------------------------------------------------------------- */
839 * Hardware Cursor support.
842 static u8 cursor_pixel_map
[2] = { 0, 15 };
843 static u8 cursor_color_map
[2] = { 0, 0xff };
845 static u8 cursor_bits_lookup
[16] =
847 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
848 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
851 static u8 cursor_mask_lookup
[16] =
853 0xaa, 0x2a, 0x8a, 0x0a, 0xa2, 0x22, 0x82, 0x02,
854 0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00
858 aty_set_cursor_color(struct fb_info_aty
*fb
, u8
*pixel
,
859 u8
*red
, u8
*green
, u8
*blue
)
861 struct aty_cursor
*c
= fb
->cursor
;
868 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
869 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
873 for (i
= 0; i
< 2; i
++) {
874 c
->color
[i
] = (u32
)red
[i
] << 24;
875 c
->color
[i
] |= (u32
)green
[i
] << 16;
876 c
->color
[i
] |= (u32
)blue
[i
] << 8;
877 c
->color
[i
] |= (u32
)pixel
[i
];
880 wait_for_fifo(2, fb
);
881 aty_st_le32(CUR_CLR0
, c
->color
[0], fb
);
882 aty_st_le32(CUR_CLR1
, c
->color
[1], fb
);
886 aty_set_cursor_shape(struct fb_info_aty
*fb
)
888 struct aty_cursor
*c
= fb
->cursor
;
896 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
897 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
902 for (y
= 0; y
< c
->size
.y
; y
++) {
903 for (x
= 0; x
< c
->size
.x
>> 2; x
++) {
906 *ram
++ = cursor_mask_lookup
[m
>> 4] |
907 cursor_bits_lookup
[(b
& m
) >> 4];
908 *ram
++ = cursor_mask_lookup
[m
& 0x0f] |
909 cursor_bits_lookup
[(b
& m
) & 0x0f];
911 for ( ; x
< 8; x
++) {
916 memset(ram
, 0xaa, (64 - c
->size
.y
) * 16);
920 aty_set_cursor(struct fb_info_aty
*fb
, int on
)
922 struct atyfb_par
*par
= &fb
->current_par
;
923 struct aty_cursor
*c
= fb
->cursor
;
931 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
932 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
937 x
= c
->pos
.x
- c
->hot
.x
- par
->crtc
.xoffset
;
945 y
= c
->pos
.y
- c
->hot
.y
- par
->crtc
.yoffset
;
953 wait_for_fifo(4, fb
);
954 aty_st_le32(CUR_OFFSET
, (c
->offset
>> 3) + (yoff
<< 1), fb
);
955 aty_st_le32(CUR_HORZ_VERT_OFF
,
956 ((u32
)(64 - c
->size
.y
+ yoff
) << 16) | xoff
, fb
);
957 aty_st_le32(CUR_HORZ_VERT_POSN
, ((u32
)y
<< 16) | x
, fb
);
958 aty_st_le32(GEN_TEST_CNTL
, aty_ld_le32(GEN_TEST_CNTL
, fb
)
959 | HWCURSOR_ENABLE
, fb
);
961 wait_for_fifo(1, fb
);
962 aty_st_le32(GEN_TEST_CNTL
,
963 aty_ld_le32(GEN_TEST_CNTL
, fb
) & ~HWCURSOR_ENABLE
,
966 if (fb
->blitter_may_be_busy
)
971 aty_cursor_timer_handler(unsigned long dev_addr
)
973 struct fb_info_aty
*fb
= (struct fb_info_aty
*)dev_addr
;
978 if (!fb
->cursor
->enable
)
981 if (fb
->cursor
->vbl_cnt
&& --fb
->cursor
->vbl_cnt
== 0) {
983 aty_set_cursor(fb
, fb
->cursor
->on
);
984 fb
->cursor
->vbl_cnt
= fb
->cursor
->blink_rate
;
988 fb
->cursor
->timer
->expires
= jiffies
+ (HZ
/ 50);
989 add_timer(fb
->cursor
->timer
);
993 atyfb_cursor(struct display
*p
, int mode
, int x
, int y
)
995 struct fb_info_aty
*fb
= (struct fb_info_aty
*)p
->fb_info
;
996 struct aty_cursor
*c
= fb
->cursor
;
1002 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
1003 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
1009 if (c
->pos
.x
== x
&& c
->pos
.y
== y
&& (mode
== CM_ERASE
) == !c
->enable
)
1014 aty_set_cursor(fb
, 0);
1026 aty_set_cursor(fb
, 1);
1028 c
->vbl_cnt
= CURSOR_DRAW_DELAY
;
1034 static struct fb_info_aty
*fb_list
= NULL
;
1036 static struct aty_cursor
* __init
1037 aty_init_cursor(struct fb_info_aty
*fb
)
1039 struct aty_cursor
*cursor
;
1042 cursor
= kmalloc(sizeof(struct aty_cursor
), GFP_ATOMIC
);
1045 memset(cursor
, 0, sizeof(*cursor
));
1047 cursor
->timer
= kmalloc(sizeof(*cursor
->timer
), GFP_KERNEL
);
1048 if (!cursor
->timer
) {
1052 memset(cursor
->timer
, 0, sizeof(*cursor
->timer
));
1054 cursor
->blink_rate
= DEFAULT_CURSOR_BLINK_RATE
;
1055 fb
->total_vram
-= PAGE_SIZE
;
1056 cursor
->offset
= fb
->total_vram
;
1059 addr
= fb
->frame_buffer
- 0x800000 + cursor
->offset
;
1060 cursor
->ram
= (u8
*)addr
;
1063 addr
= fb
->frame_buffer_phys
- 0x800000 + cursor
->offset
;
1064 cursor
->ram
= (u8
*)ioremap(addr
, 1024);
1066 addr
= fb
->frame_buffer
+ cursor
->offset
;
1067 cursor
->ram
= (u8
*)addr
;
1071 if (! cursor
->ram
) {
1077 init_timer(cursor
->timer
);
1078 cursor
->timer
->expires
= jiffies
+ (HZ
/ 50);
1079 cursor
->timer
->data
= (unsigned long)fb
;
1080 cursor
->timer
->function
= aty_cursor_timer_handler
;
1081 add_timer(cursor
->timer
);
1088 atyfb_set_font(struct display
*d
, int width
, int height
)
1090 struct fb_info_aty
*fb
= (struct fb_info_aty
*)d
->fb_info
;
1091 struct aty_cursor
*c
= fb
->cursor
;
1095 if (!width
|| !height
) {
1105 memset(c
->bits
, 0xff, sizeof(c
->bits
));
1106 memset(c
->mask
, 0, sizeof(c
->mask
));
1108 for (i
= 0, j
= width
; j
>= 0; j
-= 8, i
++) {
1109 c
->mask
[i
][height
-2] = (j
>= 8) ? 0xff : (0xff << (8 - j
));
1110 c
->mask
[i
][height
-1] = (j
>= 8) ? 0xff : (0xff << (8 - j
));
1113 aty_set_cursor_color(fb
, cursor_pixel_map
, cursor_color_map
,
1114 cursor_color_map
, cursor_color_map
);
1115 aty_set_cursor_shape(fb
);
1123 /* ------------------------------------------------------------------------- */
1129 static void aty_set_crtc(const struct fb_info_aty
*info
,
1130 const struct crtc
*crtc
)
1132 aty_st_le32(CRTC_H_TOTAL_DISP
, crtc
->h_tot_disp
, info
);
1133 aty_st_le32(CRTC_H_SYNC_STRT_WID
, crtc
->h_sync_strt_wid
, info
);
1134 aty_st_le32(CRTC_V_TOTAL_DISP
, crtc
->v_tot_disp
, info
);
1135 aty_st_le32(CRTC_V_SYNC_STRT_WID
, crtc
->v_sync_strt_wid
, info
);
1136 aty_st_le32(CRTC_VLINE_CRNT_VLINE
, 0, info
);
1137 aty_st_le32(CRTC_OFF_PITCH
, crtc
->off_pitch
, info
);
1138 aty_st_le32(CRTC_GEN_CNTL
, crtc
->gen_cntl
, info
);
1141 static int aty_var_to_crtc(const struct fb_info_aty
*info
,
1142 const struct fb_var_screeninfo
*var
,
1145 u32 xres
, yres
, vxres
, vyres
, xoffset
, yoffset
, bpp
;
1146 u32 left
, right
, upper
, lower
, hslen
, vslen
, sync
, vmode
;
1147 u32 h_total
, h_disp
, h_sync_strt
, h_sync_dly
, h_sync_wid
, h_sync_pol
;
1148 u32 v_total
, v_disp
, v_sync_strt
, v_sync_wid
, v_sync_pol
, c_sync
;
1149 u32 pix_width
, dp_pix_width
, dp_chain_mask
;
1154 vxres
= var
->xres_virtual
;
1155 vyres
= var
->yres_virtual
;
1156 xoffset
= var
->xoffset
;
1157 yoffset
= var
->yoffset
;
1158 bpp
= var
->bits_per_pixel
;
1159 left
= var
->left_margin
;
1160 right
= var
->right_margin
;
1161 upper
= var
->upper_margin
;
1162 lower
= var
->lower_margin
;
1163 hslen
= var
->hsync_len
;
1164 vslen
= var
->vsync_len
;
1168 /* convert (and round up) and validate */
1169 xres
= (xres
+7) & ~7;
1170 xoffset
= (xoffset
+7) & ~7;
1171 vxres
= (vxres
+7) & ~7;
1172 if (vxres
< xres
+xoffset
)
1173 vxres
= xres
+xoffset
;
1176 FAIL("h_disp too large");
1177 h_sync_strt
= h_disp
+(right
/8);
1178 if (h_sync_strt
> 0x1ff)
1179 FAIL("h_sync_start too large");
1180 h_sync_dly
= right
& 7;
1181 h_sync_wid
= (hslen
+7)/8;
1182 if (h_sync_wid
> 0x1f)
1183 FAIL("h_sync_wid too large");
1184 h_total
= h_sync_strt
+h_sync_wid
+(h_sync_dly
+left
+7)/8;
1185 if (h_total
> 0x1ff)
1186 FAIL("h_total too large");
1187 h_sync_pol
= sync
& FB_SYNC_HOR_HIGH_ACT
? 0 : 1;
1189 if (vyres
< yres
+yoffset
)
1190 vyres
= yres
+yoffset
;
1193 FAIL("v_disp too large");
1194 v_sync_strt
= v_disp
+lower
;
1195 if (v_sync_strt
> 0x7ff)
1196 FAIL("v_sync_strt too large");
1198 if (v_sync_wid
> 0x1f)
1199 FAIL("v_sync_wid too large");
1200 v_total
= v_sync_strt
+v_sync_wid
+upper
;
1201 if (v_total
> 0x7ff)
1202 FAIL("v_total too large");
1203 v_sync_pol
= sync
& FB_SYNC_VERT_HIGH_ACT
? 0 : 1;
1205 c_sync
= sync
& FB_SYNC_COMP_HIGH_ACT
? CRTC_CSYNC_EN
: 0;
1209 pix_width
= CRTC_PIX_WIDTH_8BPP
;
1210 dp_pix_width
= HOST_8BPP
| SRC_8BPP
| DST_8BPP
| BYTE_ORDER_LSB_TO_MSB
;
1211 dp_chain_mask
= 0x8080;
1212 } else if (bpp
<= 16) {
1214 pix_width
= CRTC_PIX_WIDTH_15BPP
;
1215 dp_pix_width
= HOST_15BPP
| SRC_15BPP
| DST_15BPP
|
1216 BYTE_ORDER_LSB_TO_MSB
;
1217 dp_chain_mask
= 0x4210;
1218 } else if ((bpp
<= 24) && (Gx
!= GX_CHIP_ID
) && (Gx
!= CX_CHIP_ID
)) {
1220 pix_width
= CRTC_PIX_WIDTH_24BPP
;
1221 dp_pix_width
= HOST_8BPP
| SRC_8BPP
| DST_8BPP
| BYTE_ORDER_LSB_TO_MSB
;
1222 dp_chain_mask
= 0x8080;
1223 } else if (bpp
<= 32) {
1225 pix_width
= CRTC_PIX_WIDTH_32BPP
;
1226 dp_pix_width
= HOST_32BPP
| SRC_32BPP
| DST_32BPP
|
1227 BYTE_ORDER_LSB_TO_MSB
;
1228 dp_chain_mask
= 0x8080;
1230 FAIL("invalid bpp");
1232 if (vxres
*vyres
*bpp
/8 > info
->total_vram
)
1233 FAIL("not enough video RAM");
1235 if ((vmode
& FB_VMODE_MASK
) != FB_VMODE_NONINTERLACED
)
1236 FAIL("invalid vmode");
1239 crtc
->vxres
= vxres
;
1240 crtc
->vyres
= vyres
;
1241 crtc
->xoffset
= xoffset
;
1242 crtc
->yoffset
= yoffset
;
1244 crtc
->h_tot_disp
= h_total
| (h_disp
<<16);
1245 crtc
->h_sync_strt_wid
= (h_sync_strt
& 0xff) | (h_sync_dly
<<8) |
1246 ((h_sync_strt
& 0x100)<<4) | (h_sync_wid
<<16) |
1248 crtc
->v_tot_disp
= v_total
| (v_disp
<<16);
1249 crtc
->v_sync_strt_wid
= v_sync_strt
| (v_sync_wid
<<16) | (v_sync_pol
<<21);
1250 crtc
->off_pitch
= ((yoffset
*vxres
+xoffset
)*bpp
/64) | (vxres
<<19);
1251 crtc
->gen_cntl
= pix_width
| c_sync
| CRTC_EXT_DISP_EN
| CRTC_ENABLE
;
1252 if ((Gx
== CT_CHIP_ID
) || (Gx
== ET_CHIP_ID
) ||
1253 ((Gx
== VT_CHIP_ID
|| Gx
== GT_CHIP_ID
) && !(Rev
& 0x07))) {
1255 /* FIXME: magic FIFO values */
1256 crtc
->gen_cntl
|= aty_ld_le32(CRTC_GEN_CNTL
, info
) & 0x000e0000;
1258 crtc
->dp_pix_width
= dp_pix_width
;
1259 crtc
->dp_chain_mask
= dp_chain_mask
;
1265 static int aty_set_dac_ATI68860_B(const struct fb_info_aty
*info
, u32 bpp
,
1268 u32 gModeReg
, devSetupRegA
, temp
, mask
;
1276 devSetupRegA
= 0x60 | 0x00 /*(info->mach64DAC8Bit ? 0x00 : 0x01) */;
1280 devSetupRegA
= 0x60;
1284 devSetupRegA
= 0x60;
1288 devSetupRegA
= 0x60;
1292 devSetupRegA
= 0x60;
1298 devSetupRegA
= 0x61;
1301 temp
= aty_ld_8(DAC_CNTL
, info
);
1302 aty_st_8(DAC_CNTL
, (temp
& ~DAC_EXT_SEL_RS2
) | DAC_EXT_SEL_RS3
, info
);
1304 aty_st_8(DAC_REGS
+ 2, 0x1D, info
);
1305 aty_st_8(DAC_REGS
+ 3, gModeReg
, info
);
1306 aty_st_8(DAC_REGS
, 0x02, info
);
1308 temp
= aty_ld_8(DAC_CNTL
, info
);
1309 aty_st_8(DAC_CNTL
, temp
| DAC_EXT_SEL_RS2
| DAC_EXT_SEL_RS3
, info
);
1311 if (info
->total_vram
< MEM_SIZE_1M
)
1313 else if (info
->total_vram
== MEM_SIZE_1M
)
1318 /* The following assumes that the BIOS has correctly set R7 of the
1319 * Device Setup Register A at boot time.
1321 #define A860_DELAY_L 0x80
1323 temp
= aty_ld_8(DAC_REGS
, info
);
1324 aty_st_8(DAC_REGS
, (devSetupRegA
| mask
) | (temp
& A860_DELAY_L
), info
);
1325 temp
= aty_ld_8(DAC_CNTL
, info
);
1326 aty_st_8(DAC_CNTL
, (temp
& ~(DAC_EXT_SEL_RS2
| DAC_EXT_SEL_RS3
)), info
);
1331 static int aty_set_dac_ATT21C498(const struct fb_info_aty
*info
,
1332 const struct pll_18818
*pll
, u32 bpp
)
1338 dotClock
= 100000000 / pll
->period_in_ps
;
1342 if (dotClock
> 8000) {
1362 if (1 /* info->mach64DAC8Bit */)
1365 aty_dac_waste4(info
);
1366 aty_st_8(DAC_REGS
+ 2, DACMask
, info
);
1371 void aty_dac_waste4(const struct fb_info_aty
*info
)
1373 (void)aty_ld_8(DAC_REGS
, info
);
1375 (void)aty_ld_8(DAC_REGS
+ 2, info
);
1376 (void)aty_ld_8(DAC_REGS
+ 2, info
);
1377 (void)aty_ld_8(DAC_REGS
+ 2, info
);
1378 (void)aty_ld_8(DAC_REGS
+ 2, info
);
1382 static void aty_set_dac_514(const struct fb_info_aty
*info
, u32 bpp
)
1388 u8 pixel_cntl_index
;
1391 { 0, 0x41, 0x03, 0x71, 0x45 }, /* 8 bpp */
1392 { 0, 0x45, 0x04, 0x0c, 0x01 }, /* 555 */
1393 { 0, 0x45, 0x06, 0x0e, 0x00 }, /* XRGB */
1409 aty_st_514(0x90, 0x00, info
); /* VRAM Mask Low */
1410 aty_st_514(0x04, tab
[i
].pixel_dly
, info
); /* Horizontal Sync Control */
1411 aty_st_514(0x05, 0x00, info
); /* Power Management */
1412 aty_st_514(0x02, 0x01, info
); /* Misc Clock Control */
1413 aty_st_514(0x71, tab
[i
].misc2_cntl
, info
); /* Misc Control 2 */
1414 aty_st_514(0x0a, tab
[i
].pixel_rep
, info
); /* Pixel Format */
1415 aty_st_514(tab
[i
].pixel_cntl_index
, tab
[i
].pixel_cntl_v1
, info
);
1416 /* Misc Control 2 / 16 BPP Control / 32 BPP Control */
1419 static int aty_crtc_to_var(const struct crtc
*crtc
,
1420 struct fb_var_screeninfo
*var
)
1422 u32 xres
, yres
, bpp
, left
, right
, upper
, lower
, hslen
, vslen
, sync
;
1423 u32 h_total
, h_disp
, h_sync_strt
, h_sync_dly
, h_sync_wid
, h_sync_pol
;
1424 u32 v_total
, v_disp
, v_sync_strt
, v_sync_wid
, v_sync_pol
, c_sync
;
1428 h_total
= crtc
->h_tot_disp
& 0x1ff;
1429 h_disp
= (crtc
->h_tot_disp
>>16) & 0xff;
1430 h_sync_strt
= (crtc
->h_sync_strt_wid
& 0xff) |
1431 ((crtc
->h_sync_strt_wid
>>4) & 0x100);
1432 h_sync_dly
= (crtc
->h_sync_strt_wid
>>8) & 0x7;
1433 h_sync_wid
= (crtc
->h_sync_strt_wid
>>16) & 0x1f;
1434 h_sync_pol
= (crtc
->h_sync_strt_wid
>>21) & 0x1;
1435 v_total
= crtc
->v_tot_disp
& 0x7ff;
1436 v_disp
= (crtc
->v_tot_disp
>>16) & 0x7ff;
1437 v_sync_strt
= crtc
->v_sync_strt_wid
& 0x7ff;
1438 v_sync_wid
= (crtc
->v_sync_strt_wid
>>16) & 0x1f;
1439 v_sync_pol
= (crtc
->v_sync_strt_wid
>>21) & 0x1;
1440 c_sync
= crtc
->gen_cntl
& CRTC_CSYNC_EN
? 1 : 0;
1441 pix_width
= crtc
->gen_cntl
& CRTC_PIX_WIDTH_MASK
;
1444 xres
= (h_disp
+1)*8;
1446 left
= (h_total
-h_sync_strt
-h_sync_wid
)*8-h_sync_dly
;
1447 right
= (h_sync_strt
-h_disp
)*8+h_sync_dly
;
1448 hslen
= h_sync_wid
*8;
1449 upper
= v_total
-v_sync_strt
-v_sync_wid
;
1450 lower
= v_sync_strt
-v_disp
;
1452 sync
= (h_sync_pol
? 0 : FB_SYNC_HOR_HIGH_ACT
) |
1453 (v_sync_pol
? 0 : FB_SYNC_VERT_HIGH_ACT
) |
1454 (c_sync
? FB_SYNC_COMP_HIGH_ACT
: 0);
1456 switch (pix_width
) {
1458 case CRTC_PIX_WIDTH_4BPP
:
1460 var
->red
.offset
= 0;
1461 var
->red
.length
= 8;
1462 var
->green
.offset
= 0;
1463 var
->green
.length
= 8;
1464 var
->blue
.offset
= 0;
1465 var
->blue
.length
= 8;
1466 var
->transp
.offset
= 0;
1467 var
->transp
.length
= 0;
1470 case CRTC_PIX_WIDTH_8BPP
:
1472 var
->red
.offset
= 0;
1473 var
->red
.length
= 8;
1474 var
->green
.offset
= 0;
1475 var
->green
.length
= 8;
1476 var
->blue
.offset
= 0;
1477 var
->blue
.length
= 8;
1478 var
->transp
.offset
= 0;
1479 var
->transp
.length
= 0;
1481 case CRTC_PIX_WIDTH_15BPP
: /* RGB 555 */
1483 var
->red
.offset
= 10;
1484 var
->red
.length
= 5;
1485 var
->green
.offset
= 5;
1486 var
->green
.length
= 5;
1487 var
->blue
.offset
= 0;
1488 var
->blue
.length
= 5;
1489 var
->transp
.offset
= 0;
1490 var
->transp
.length
= 0;
1493 case CRTC_PIX_WIDTH_16BPP
: /* RGB 565 */
1495 var
->red
.offset
= 11;
1496 var
->red
.length
= 5;
1497 var
->green
.offset
= 5;
1498 var
->green
.length
= 6;
1499 var
->blue
.offset
= 0;
1500 var
->blue
.length
= 5;
1501 var
->transp
.offset
= 0;
1502 var
->transp
.length
= 0;
1505 case CRTC_PIX_WIDTH_24BPP
: /* RGB 888 */
1507 var
->red
.offset
= 16;
1508 var
->red
.length
= 8;
1509 var
->green
.offset
= 8;
1510 var
->green
.length
= 8;
1511 var
->blue
.offset
= 0;
1512 var
->blue
.length
= 8;
1513 var
->transp
.offset
= 0;
1514 var
->transp
.length
= 0;
1516 case CRTC_PIX_WIDTH_32BPP
: /* ARGB 8888 */
1518 var
->red
.offset
= 16;
1519 var
->red
.length
= 8;
1520 var
->green
.offset
= 8;
1521 var
->green
.length
= 8;
1522 var
->blue
.offset
= 0;
1523 var
->blue
.length
= 8;
1524 var
->transp
.offset
= 24;
1525 var
->transp
.length
= 8;
1528 FAIL("Invalid pixel width");
1534 var
->xres_virtual
= crtc
->vxres
;
1535 var
->yres_virtual
= crtc
->vyres
;
1536 var
->bits_per_pixel
= bpp
;
1537 var
->xoffset
= crtc
->xoffset
;
1538 var
->yoffset
= crtc
->yoffset
;
1539 var
->left_margin
= left
;
1540 var
->right_margin
= right
;
1541 var
->upper_margin
= upper
;
1542 var
->lower_margin
= lower
;
1543 var
->hsync_len
= hslen
;
1544 var
->vsync_len
= vslen
;
1546 var
->vmode
= FB_VMODE_NONINTERLACED
;
1551 /* ------------------------------------------------------------------------- */
1554 * PLL programming (Mach64 GX family)
1556 * FIXME: use function pointer tables instead of switch statements
1559 static void aty_set_pll_gx(const struct fb_info_aty
*info
,
1560 const struct pll_gx
*pll
)
1562 switch (info
->clk_type
) {
1563 case CLK_ATI18818_1
:
1564 aty_st_8(CLOCK_CNTL
, pll
->m
, info
);
1567 aty_st_514(0x06, 0x02, info
); /* DAC Operation */
1568 aty_st_514(0x10, 0x01, info
); /* PLL Control 1 */
1569 aty_st_514(0x70, 0x01, info
); /* Misc Control 1 */
1570 aty_st_514(0x8f, 0x1f, info
); /* PLL Ref. Divider Input */
1571 aty_st_514(0x03, 0x00, info
); /* Sync Control */
1572 aty_st_514(0x05, 0x00, info
); /* Power Management */
1573 aty_st_514(0x20, pll
->m
, info
); /* F0 / M0 */
1574 aty_st_514(0x21, pll
->n
, info
); /* F1 / N0 */
1580 static int aty_var_to_pll_18818(u32 period_in_ps
, struct pll_18818
*pll
)
1582 u32 MHz100
; /* in 0.01 MHz */
1586 /* Calculate the programming word */
1587 MHz100
= 100000000 / period_in_ps
;
1592 if (MHz100
> MAX_FREQ_2595
) {
1593 MHz100
= MAX_FREQ_2595
;
1595 } else if (MHz100
< ABS_MIN_FREQ_2595
) {
1596 program_bits
= 0; /* MHz100 = 257 */
1599 while (MHz100
< MIN_FREQ_2595
) {
1605 MHz100
= (REF_DIV_2595
* MHz100
) / REF_FREQ_2595
;
1607 MHz100
+= 500; /* + 0.5 round */
1610 if (program_bits
== -1) {
1611 program_bits
= MHz100
- N_ADJ_2595
;
1612 switch (post_divider
) {
1614 program_bits
|= 0x0600;
1617 program_bits
|= 0x0400;
1620 program_bits
|= 0x0200;
1628 program_bits
|= STOP_BITS_2595
;
1630 pll
->program_bits
= program_bits
;
1631 pll
->locationAddr
= 0;
1632 pll
->post_divider
= post_divider
;
1633 pll
->period_in_ps
= period_in_ps
;
1638 static u32
aty_pll_18818_to_var(const struct pll_18818
*pll
)
1640 return(pll
->period_in_ps
); /* default for now */
1643 static void aty_set_pll18818(const struct fb_info_aty
*info
,
1644 const struct pll_18818
*pll
)
1652 u8 old_crtc_ext_disp
;
1654 old_clock_cntl
= aty_ld_8(CLOCK_CNTL
, info
);
1655 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, 0, info
);
1657 old_crtc_ext_disp
= aty_ld_8(CRTC_GEN_CNTL
+ 3, info
);
1658 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
| (CRTC_EXT_DISP_EN
>> 24),
1661 udelay(15000); /* delay for 50 (15) ms */
1663 program_bits
= pll
->program_bits
;
1664 locationAddr
= pll
->locationAddr
;
1666 /* Program the clock chip */
1667 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, 0, info
); /* Strobe = 0 */
1668 aty_StrobeClock(info
);
1669 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, 1, info
); /* Strobe = 0 */
1670 aty_StrobeClock(info
);
1672 aty_ICS2595_put1bit(1, info
); /* Send start bits */
1673 aty_ICS2595_put1bit(0, info
); /* Start bit */
1674 aty_ICS2595_put1bit(0, info
); /* Read / ~Write */
1676 for (i
= 0; i
< 5; i
++) { /* Location 0..4 */
1677 aty_ICS2595_put1bit(locationAddr
& 1, info
);
1681 for (i
= 0; i
< 8 + 1 + 2 + 2; i
++) {
1682 aty_ICS2595_put1bit(program_bits
& 1, info
);
1686 udelay(1000); /* delay for 1 ms */
1688 (void)aty_ld_8(DAC_REGS
, info
); /* Clear DAC Counter */
1689 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
, info
);
1690 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, old_clock_cntl
| CLOCK_STROBE
,
1693 udelay(50000); /* delay for 50 (15) ms */
1694 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
,
1695 ((pll
->locationAddr
& 0x0F) | CLOCK_STROBE
), info
);
1701 static int aty_var_to_pll_408(u32 period_in_ps
, struct pll_18818
*pll
)
1703 u32 mhz100
; /* in 0.01 MHz */
1705 /* u32 post_divider; */
1706 u32 mach64MinFreq
, mach64MaxFreq
, mach64RefFreq
;
1708 u16 remainder
, preRemainder
;
1709 short divider
= 0, tempA
;
1711 /* Calculate the programming word */
1712 mhz100
= 100000000 / period_in_ps
;
1713 mach64MinFreq
= MIN_FREQ_2595
;
1714 mach64MaxFreq
= MAX_FREQ_2595
;
1715 mach64RefFreq
= REF_FREQ_2595
; /* 14.32 MHz */
1717 /* Calculate program word */
1719 program_bits
= 0xFF;
1721 if (mhz100
< mach64MinFreq
)
1722 mhz100
= mach64MinFreq
;
1723 if (mhz100
> mach64MaxFreq
)
1724 mhz100
= mach64MaxFreq
;
1726 while (mhz100
< (mach64MinFreq
<< 3)) {
1731 temp
= (unsigned int)mhz100
;
1732 temp
= (unsigned int)(temp
* (MIN_N_408
+ 2));
1733 temp
-= ((short)(mach64RefFreq
<< 1));
1736 preRemainder
= 0xFFFF;
1740 remainder
= tempB
% mach64RefFreq
;
1741 tempB
= tempB
/ mach64RefFreq
;
1742 if (((tempB
& 0xFFFF) <= 255) && (remainder
<= preRemainder
)) {
1743 preRemainder
= remainder
;
1746 divider
= (divider
& 0x00FF) + ((tempB
& 0xFF) << 8);
1750 } while(tempA
<= 32);
1752 program_bits
= divider
;
1755 pll
->program_bits
= program_bits
;
1756 pll
->locationAddr
= 0;
1757 pll
->post_divider
= divider
; /* fuer nix */
1758 pll
->period_in_ps
= period_in_ps
;
1763 static u32
aty_pll_408_to_var(const struct pll_18818
*pll
)
1765 return(pll
->period_in_ps
); /* default for now */
1768 static void aty_set_pll_408(const struct fb_info_aty
*info
,
1769 const struct pll_18818
*pll
)
1774 u8 tmpA
, tmpB
, tmpC
;
1775 char old_crtc_ext_disp
;
1777 old_crtc_ext_disp
= aty_ld_8(CRTC_GEN_CNTL
+ 3, info
);
1778 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
| (CRTC_EXT_DISP_EN
>> 24),
1781 program_bits
= pll
->program_bits
;
1782 locationAddr
= pll
->locationAddr
;
1785 aty_dac_waste4(info
);
1786 tmpB
= aty_ld_8(DAC_REGS
+ 2, info
) | 1;
1787 aty_dac_waste4(info
);
1788 aty_st_8(DAC_REGS
+ 2, tmpB
, info
);
1795 aty_st_8(DAC_REGS
, tmpB
, info
);
1796 aty_st_8(DAC_REGS
+ 2, tmpA
, info
);
1798 udelay(400); /* delay for 400 us */
1800 locationAddr
= (locationAddr
<< 2) + 0x40;
1801 tmpB
= locationAddr
;
1802 tmpA
= program_bits
>> 8;
1804 aty_st_8(DAC_REGS
, tmpB
, info
);
1805 aty_st_8(DAC_REGS
+ 2, tmpA
, info
);
1807 tmpB
= locationAddr
+ 1;
1808 tmpA
= (u8
)program_bits
;
1810 aty_st_8(DAC_REGS
, tmpB
, info
);
1811 aty_st_8(DAC_REGS
+ 2, tmpA
, info
);
1813 tmpB
= locationAddr
+ 2;
1816 aty_st_8(DAC_REGS
, tmpB
, info
);
1817 aty_st_8(DAC_REGS
+ 2, tmpA
, info
);
1819 udelay(400); /* delay for 400 us */
1820 tmpA
= tmpC
& (~(1 | 8));
1823 aty_st_8(DAC_REGS
, tmpB
, info
);
1824 aty_st_8(DAC_REGS
+ 2, tmpA
, info
);
1826 (void)aty_ld_8(DAC_REGS
, info
); /* Clear DAC Counter */
1827 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
, info
);
1833 static int aty_var_to_pll_1703(u32 period_in_ps
, struct pll_18818
*pll
)
1835 u32 mhz100
; /* in 0.01 MHz */
1837 /* u32 post_divider; */
1838 u32 mach64MinFreq
, mach64MaxFreq
, mach64RefFreq
;
1840 u16 remainder
, preRemainder
;
1841 short divider
= 0, tempA
;
1843 /* Calculate the programming word */
1844 mhz100
= 100000000 / period_in_ps
;
1845 mach64MinFreq
= MIN_FREQ_2595
;
1846 mach64MaxFreq
= MAX_FREQ_2595
;
1847 mach64RefFreq
= REF_FREQ_2595
; /* 14.32 MHz */
1849 /* Calculate program word */
1851 program_bits
= 0xE0;
1853 if (mhz100
< mach64MinFreq
)
1854 mhz100
= mach64MinFreq
;
1855 if (mhz100
> mach64MaxFreq
)
1856 mhz100
= mach64MaxFreq
;
1859 while (mhz100
< (mach64MinFreq
<< 3)) {
1864 temp
= (unsigned int)(mhz100
);
1865 temp
= (unsigned int)(temp
* (MIN_N_1703
+ 2));
1866 temp
-= (short)(mach64RefFreq
<< 1);
1869 preRemainder
= 0xffff;
1873 remainder
= tempB
% mach64RefFreq
;
1874 tempB
= tempB
/ mach64RefFreq
;
1876 if ((tempB
& 0xffff) <= 127 && (remainder
<= preRemainder
)) {
1877 preRemainder
= remainder
;
1880 divider
= (divider
& 0x00ff) + ((tempB
& 0xff) << 8);
1885 } while (tempA
<= (MIN_N_1703
<< 1));
1887 program_bits
= divider
;
1890 pll
->program_bits
= program_bits
;
1891 pll
->locationAddr
= 0;
1892 pll
->post_divider
= divider
; /* fuer nix */
1893 pll
->period_in_ps
= period_in_ps
;
1898 static u32
aty_pll_1703_to_var(const struct pll_18818
*pll
)
1900 return(pll
->period_in_ps
); /* default for now */
1903 static void aty_set_pll_1703(const struct fb_info_aty
*info
,
1904 const struct pll_18818
*pll
)
1909 char old_crtc_ext_disp
;
1911 old_crtc_ext_disp
= aty_ld_8(CRTC_GEN_CNTL
+ 3, info
);
1912 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
| (CRTC_EXT_DISP_EN
>> 24),
1915 program_bits
= pll
->program_bits
;
1916 locationAddr
= pll
->locationAddr
;
1919 aty_dac_waste4(info
);
1921 (void)aty_ld_8(DAC_REGS
+ 2, info
);
1922 aty_st_8(DAC_REGS
+2, (locationAddr
<< 1) + 0x20, info
);
1923 aty_st_8(DAC_REGS
+2, 0, info
);
1924 aty_st_8(DAC_REGS
+2, (program_bits
& 0xFF00) >> 8, info
);
1925 aty_st_8(DAC_REGS
+2, (program_bits
& 0xFF), info
);
1927 (void)aty_ld_8(DAC_REGS
, info
); /* Clear DAC Counter */
1928 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
, info
);
1934 static int aty_var_to_pll_8398(u32 period_in_ps
, struct pll_18818
*pll
)
1937 u32 tempA
, tempB
, fOut
, longMHz100
, diff
, preDiff
;
1939 u32 mhz100
; /* in 0.01 MHz */
1941 /* u32 post_divider; */
1942 u32 mach64MinFreq
, mach64MaxFreq
, mach64RefFreq
;
1943 u16 m
, n
, k
=0, save_m
, save_n
, twoToKth
;
1945 /* Calculate the programming word */
1946 mhz100
= 100000000 / period_in_ps
;
1947 mach64MinFreq
= MIN_FREQ_2595
;
1948 mach64MaxFreq
= MAX_FREQ_2595
;
1949 mach64RefFreq
= REF_FREQ_2595
; /* 14.32 MHz */
1954 /* Calculate program word */
1956 program_bits
= 0xE0;
1959 if (mhz100
< mach64MinFreq
)
1960 mhz100
= mach64MinFreq
;
1961 if (mhz100
> mach64MaxFreq
)
1962 mhz100
= mach64MaxFreq
;
1964 longMHz100
= mhz100
* 256 / 100; /* 8 bit scale this */
1966 while (mhz100
< (mach64MinFreq
<< 3))
1974 preDiff
= 0xFFFFFFFF;
1976 for (m
= MIN_M
; m
<= MAX_M
; m
++)
1978 for (n
= MIN_N
; n
<= MAX_N
; n
++)
1980 tempA
= (14.31818 * 65536);
1981 tempA
*= (n
+ 8); /* 43..256 */
1982 tempB
= twoToKth
* 256;
1983 tempB
*= (m
+ 2); /* 4..32 */
1984 fOut
= tempA
/ tempB
; /* 8 bit scale */
1986 if (longMHz100
> fOut
)
1987 diff
= longMHz100
- fOut
;
1989 diff
= fOut
- longMHz100
;
2000 program_bits
= (k
<< 6) + (save_m
) + (save_n
<< 8);
2003 pll
->program_bits
= program_bits
;
2004 pll
->locationAddr
= 0;
2005 pll
->post_divider
= 0;
2006 pll
->period_in_ps
= period_in_ps
;
2011 static u32
aty_pll_8398_to_var(const struct pll_18818
*pll
)
2013 return(pll
->period_in_ps
); /* default for now */
2016 static void aty_set_pll_8398(const struct fb_info_aty
*info
,
2017 const struct pll_18818
*pll
)
2022 char old_crtc_ext_disp
;
2025 old_crtc_ext_disp
= aty_ld_8(CRTC_GEN_CNTL
+ 3, info
);
2026 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
| (CRTC_EXT_DISP_EN
>> 24),
2029 program_bits
= pll
->program_bits
;
2030 locationAddr
= pll
->locationAddr
;
2033 tmp
= aty_ld_8(DAC_CNTL
, info
);
2034 aty_st_8(DAC_CNTL
, tmp
| DAC_EXT_SEL_RS2
| DAC_EXT_SEL_RS3
, info
);
2036 aty_st_8(DAC_REGS
, locationAddr
, info
);
2037 aty_st_8(DAC_REGS
+1, (program_bits
& 0xff00) >> 8, info
);
2038 aty_st_8(DAC_REGS
+1, (program_bits
& 0xff), info
);
2040 tmp
= aty_ld_8(DAC_CNTL
, info
);
2041 aty_st_8(DAC_CNTL
, (tmp
& ~DAC_EXT_SEL_RS2
) | DAC_EXT_SEL_RS3
, info
);
2043 (void)aty_ld_8(DAC_REGS
, info
); /* Clear DAC Counter */
2044 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
, info
);
2050 static int aty_var_to_pll_514(u32 vclk_per
, struct pll_gx
*pll
)
2053 * FIXME: use real calculations instead of using fixed values from the old
2057 u32 limit
; /* pixlock rounding limit (arbitrary) */
2058 u8 m
; /* (df<<6) | vco_div_count */
2059 u8 n
; /* ref_div_count */
2060 } RGB514_clocks
[7] = {
2061 { 8000, (3<<6) | 20, 9 }, /* 7395 ps / 135.2273 MHz */
2062 { 10000, (1<<6) | 19, 3 }, /* 9977 ps / 100.2273 MHz */
2063 { 13000, (1<<6) | 2, 3 }, /* 12509 ps / 79.9432 MHz */
2064 { 14000, (2<<6) | 8, 7 }, /* 13394 ps / 74.6591 MHz */
2065 { 16000, (1<<6) | 44, 6 }, /* 15378 ps / 65.0284 MHz */
2066 { 25000, (1<<6) | 15, 5 }, /* 17460 ps / 57.2727 MHz */
2067 { 50000, (0<<6) | 53, 7 }, /* 33145 ps / 30.1705 MHz */
2071 for (i
= 0; i
< sizeof(RGB514_clocks
)/sizeof(*RGB514_clocks
); i
++)
2072 if (vclk_per
<= RGB514_clocks
[i
].limit
) {
2073 pll
->m
= RGB514_clocks
[i
].m
;
2074 pll
->n
= RGB514_clocks
[i
].n
;
2081 static void aty_StrobeClock(const struct fb_info_aty
*info
)
2087 tmp
= aty_ld_8(CLOCK_CNTL
, info
);
2088 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, tmp
| CLOCK_STROBE
, info
);
2094 static void aty_ICS2595_put1bit(u8 data
, const struct fb_info_aty
*info
)
2099 tmp
= aty_ld_8(CLOCK_CNTL
, info
);
2100 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, (tmp
& ~0x04) | (data
<< 2),
2103 tmp
= aty_ld_8(CLOCK_CNTL
, info
);
2104 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, (tmp
& ~0x08) | (0 << 3), info
);
2106 aty_StrobeClock(info
);
2108 tmp
= aty_ld_8(CLOCK_CNTL
, info
);
2109 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, (tmp
& ~0x08) | (1 << 3), info
);
2111 aty_StrobeClock(info
);
2117 static u32
aty_pll_gx_to_var(const struct pll_gx
*pll
,
2118 const struct fb_info_aty
*info
)
2120 u8 df
, vco_div_count
, ref_div_count
;
2123 vco_div_count
= pll
->m
& 0x3f;
2124 ref_div_count
= pll
->n
;
2126 return ((info
->ref_clk_per
*ref_div_count
)<<(3-df
))/(vco_div_count
+65);
2131 * PLL programming (Mach64 CT family)
2134 static void aty_set_pll_ct(const struct fb_info_aty
*info
,
2135 const struct pll_ct
*pll
)
2137 aty_st_pll(PLL_REF_DIV
, pll
->pll_ref_div
, info
);
2138 aty_st_pll(PLL_GEN_CNTL
, pll
->pll_gen_cntl
, info
);
2139 aty_st_pll(MCLK_FB_DIV
, pll
->mclk_fb_div
, info
);
2140 aty_st_pll(PLL_VCLK_CNTL
, pll
->pll_vclk_cntl
, info
);
2141 aty_st_pll(VCLK_POST_DIV
, pll
->vclk_post_div
, info
);
2142 aty_st_pll(VCLK0_FB_DIV
, pll
->vclk_fb_div
, info
);
2143 aty_st_pll(PLL_EXT_CNTL
, pll
->pll_ext_cntl
, info
);
2145 if (!(Gx
== GX_CHIP_ID
|| Gx
== CX_CHIP_ID
|| Gx
== CT_CHIP_ID
||
2147 ((Gx
== VT_CHIP_ID
|| Gx
== GT_CHIP_ID
) && !(Rev
& 0x07)))) {
2148 if (info
->ram_type
>= SDRAM
)
2149 aty_st_pll(DLL_CNTL
, 0xa6, info
);
2151 aty_st_pll(DLL_CNTL
, 0xa0, info
);
2152 aty_st_pll(VFC_CNTL
, 0x1b, info
);
2153 aty_st_le32(DSP_CONFIG
, pll
->dsp_config
, info
);
2154 aty_st_le32(DSP_ON_OFF
, pll
->dsp_on_off
, info
);
2158 static int aty_dsp_gt(const struct fb_info_aty
*info
, u8 bpp
,
2161 u32 dsp_xclks_per_row
, dsp_loop_latency
, dsp_precision
, dsp_off
, dsp_on
;
2162 u32 xclks_per_row
, fifo_off
, fifo_on
, y
, fifo_size
, page_size
;
2164 /* xclocks_per_row<<11 */
2165 xclks_per_row
= (pll
->mclk_fb_div
*pll
->vclk_post_div_real
*64<<11)/
2166 (pll
->vclk_fb_div
*pll
->mclk_post_div_real
*bpp
);
2167 if (xclks_per_row
< (1<<11))
2168 FAIL("Dotclock to high");
2169 if (Gx
== GT_CHIP_ID
|| Gx
== GU_CHIP_ID
|| Gx
== VT_CHIP_ID
||
2170 Gx
== VU_CHIP_ID
|| Gx
== GV_CHIP_ID
|| Gx
== GW_CHIP_ID
||
2173 dsp_loop_latency
= 0;
2176 dsp_loop_latency
= 2;
2179 y
= (xclks_per_row
*fifo_size
)>>11;
2186 fifo_off
= ((xclks_per_row
*(fifo_size
-1))>>5)+(1<<6);
2188 if (info
->total_vram
> 1*1024*1024) {
2189 if (info
->ram_type
>= SDRAM
) {
2191 dsp_loop_latency
+= 8;
2195 dsp_loop_latency
+= 6;
2199 if (info
->ram_type
>= SDRAM
) {
2201 dsp_loop_latency
+= 9;
2205 dsp_loop_latency
+= 8;
2210 if (xclks_per_row
>= (page_size
<<11))
2211 fifo_on
= ((2*page_size
+1)<<6)+(xclks_per_row
>>5);
2213 fifo_on
= (3*page_size
)<<6;
2215 dsp_xclks_per_row
= xclks_per_row
>>dsp_precision
;
2216 dsp_on
= fifo_on
>>dsp_precision
;
2217 dsp_off
= fifo_off
>>dsp_precision
;
2219 pll
->dsp_config
= (dsp_xclks_per_row
& 0x3fff) |
2220 ((dsp_loop_latency
& 0xf)<<16) |
2221 ((dsp_precision
& 7)<<20);
2222 pll
->dsp_on_off
= (dsp_on
& 0x7ff) | ((dsp_off
& 0x7ff)<<16);
2226 static int aty_valid_pll_ct(const struct fb_info_aty
*info
, u32 vclk_per
,
2229 u32 q
, x
; /* x is a workaround for sparc64-linux-gcc */
2230 x
= x
; /* x is a workaround for sparc64-linux-gcc */
2232 pll
->pll_ref_div
= info
->pll_per
*2*255/info
->ref_clk_per
;
2234 /* FIXME: use the VTB/GTB /3 post divider if it's better suited */
2235 q
= info
->ref_clk_per
*pll
->pll_ref_div
*4/info
->mclk_per
; /* actually 8*q */
2236 if (q
< 16*8 || q
> 255*8)
2237 FAIL("mclk out of range");
2239 pll
->mclk_post_div_real
= 8;
2241 pll
->mclk_post_div_real
= 4;
2243 pll
->mclk_post_div_real
= 2;
2245 pll
->mclk_post_div_real
= 1;
2246 pll
->mclk_fb_div
= q
*pll
->mclk_post_div_real
/8;
2248 /* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
2249 q
= info
->ref_clk_per
*pll
->pll_ref_div
*4/vclk_per
; /* actually 8*q */
2250 if (q
< 16*8 || q
> 255*8)
2251 FAIL("vclk out of range");
2253 pll
->vclk_post_div_real
= 8;
2255 pll
->vclk_post_div_real
= 4;
2257 pll
->vclk_post_div_real
= 2;
2259 pll
->vclk_post_div_real
= 1;
2260 pll
->vclk_fb_div
= q
*pll
->vclk_post_div_real
/8;
2264 static void aty_calc_pll_ct(const struct fb_info_aty
*info
, struct pll_ct
*pll
)
2269 if ((((Gx
== GT_CHIP_ID
) && (Rev
& 0x03)) || (Gx
== GU_CHIP_ID
) ||
2270 (Gx
== GV_CHIP_ID
) || (Gx
== GW_CHIP_ID
) || (Gx
== GZ_CHIP_ID
) ||
2271 (Gx
== LG_CHIP_ID
) || (Gx
== GB_CHIP_ID
) || (Gx
== GD_CHIP_ID
) ||
2272 (Gx
== GI_CHIP_ID
) || (Gx
== GP_CHIP_ID
) || (Gx
== GQ_CHIP_ID
) ||
2273 (Gx
== VU_CHIP_ID
)) && (info
->ram_type
>= SDRAM
))
2274 pll
->pll_gen_cntl
= 0x04;
2276 pll
->pll_gen_cntl
= 0x84;
2278 switch (pll
->mclk_post_div_real
) {
2295 pll
->pll_gen_cntl
|= mpostdiv
<<4; /* mclk */
2297 if (Gx
== VT_CHIP_ID
&& (Rev
== 0x40 || Rev
== 0x48))
2298 pll
->pll_ext_cntl
= 0;
2300 pll
->pll_ext_cntl
= mpostdiv
; /* xclk == mclk */
2302 switch (pll
->vclk_post_div_real
) {
2307 pll
->pll_ext_cntl
|= 0x10;
2312 pll
->pll_ext_cntl
|= 0x10;
2317 pll
->pll_ext_cntl
|= 0x10;
2323 pll
->pll_vclk_cntl
= 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */
2324 pll
->vclk_post_div
= vpostdiv
;
2327 static int aty_var_to_pll_ct(const struct fb_info_aty
*info
, u32 vclk_per
,
2328 u8 bpp
, struct pll_ct
*pll
)
2332 if ((err
= aty_valid_pll_ct(info
, vclk_per
, pll
)))
2334 if (!(Gx
== GX_CHIP_ID
|| Gx
== CX_CHIP_ID
|| Gx
== CT_CHIP_ID
||
2336 ((Gx
== VT_CHIP_ID
|| Gx
== GT_CHIP_ID
) && !(Rev
& 0x07)))) {
2337 if ((err
= aty_dsp_gt(info
, bpp
, pll
)))
2340 aty_calc_pll_ct(info
, pll
);
2344 static u32
aty_pll_ct_to_var(const struct pll_ct
*pll
,
2345 const struct fb_info_aty
*info
)
2347 u32 ref_clk_per
= info
->ref_clk_per
;
2348 u8 pll_ref_div
= pll
->pll_ref_div
;
2349 u8 vclk_fb_div
= pll
->vclk_fb_div
;
2350 u8 vclk_post_div
= pll
->vclk_post_div_real
;
2352 return ref_clk_per
*pll_ref_div
*vclk_post_div
/vclk_fb_div
/2;
2355 /* ------------------------------------------------------------------------- */
2357 static void atyfb_set_par(const struct atyfb_par
*par
,
2358 struct fb_info_aty
*info
)
2365 accelmode
= par
->accel_flags
; /* hack */
2367 info
->current_par
= *par
;
2369 if (info
->blitter_may_be_busy
)
2370 wait_for_idle(info
);
2371 tmp
= aty_ld_8(CRTC_GEN_CNTL
+ 3, info
);
2372 aty_set_crtc(info
, &par
->crtc
);
2373 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, 0, info
);
2374 /* better call aty_StrobeClock ?? */
2375 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, CLOCK_STROBE
, info
);
2377 if ((Gx
== GX_CHIP_ID
) || (Gx
== CX_CHIP_ID
)) {
2378 switch (info
->dac_subtype
) {
2380 aty_set_dac_514(info
, par
->crtc
.bpp
);
2382 case DAC_ATI68860_B
:
2383 case DAC_ATI68860_C
:
2384 muxmode
= aty_set_dac_ATI68860_B(info
, par
->crtc
.bpp
,
2386 aty_st_le32(BUS_CNTL
, 0x890e20f1, info
);
2387 aty_st_le32(DAC_CNTL
, 0x47052100, info
);
2390 muxmode
= aty_set_dac_ATT21C498(info
, &par
->pll
.ics2595
,
2392 aty_st_le32(BUS_CNTL
, 0x890e20f1, info
);
2393 aty_st_le32(DAC_CNTL
, 0x00072000, info
);
2396 muxmode
= aty_set_dac_ATT21C498(info
, &par
->pll
.ics2595
,
2398 aty_st_le32(BUS_CNTL
, 0x890e20f1, info
);
2399 aty_st_le32(DAC_CNTL
, 0x00072000, info
);
2402 printk(" atyfb_set_par: DAC type not implemented yet!\n");
2403 aty_st_le32(BUS_CNTL
, 0x890e20f1, info
);
2404 aty_st_le32(DAC_CNTL
, 0x47052100, info
);
2405 /* new in 2.2.3p1 from Geert. ???????? */
2406 aty_st_le32(BUS_CNTL
, 0x590e10ff, info
);
2407 aty_st_le32(DAC_CNTL
, 0x47012100, info
);
2411 switch (info
->clk_type
) {
2412 case CLK_ATI18818_1
:
2413 aty_set_pll18818(info
, &par
->pll
.ics2595
);
2416 aty_set_pll_1703(info
, &par
->pll
.ics2595
);
2419 aty_set_pll_8398(info
, &par
->pll
.ics2595
);
2422 aty_set_pll_408(info
, &par
->pll
.ics2595
);
2425 aty_set_pll_gx(info
, &par
->pll
.gx
);
2428 printk(" atyfb_set_par: CLK type not implemented yet!");
2432 /* Don't forget MEM_CNTL */
2433 i
= aty_ld_le32(MEM_CNTL
, info
) & 0xf0ffffff;
2434 switch (par
->crtc
.bpp
) {
2445 aty_st_le32(MEM_CNTL
, i
, info
);
2448 aty_set_pll_ct(info
, &par
->pll
.ct
);
2449 i
= aty_ld_le32(MEM_CNTL
, info
) & 0xf00fffff;
2450 if (!(Gx
== VT_CHIP_ID
&& (Rev
== 0x40 || Rev
== 0x48)))
2451 i
|= info
->mem_refresh_rate
<< 20;
2452 switch (par
->crtc
.bpp
) {
2464 if ((Gx
== CT_CHIP_ID
) || (Gx
== ET_CHIP_ID
)) {
2465 aty_st_le32(DAC_CNTL
, 0x87010184, info
);
2466 aty_st_le32(BUS_CNTL
, 0x680000f9, info
);
2467 } else if ((Gx
== VT_CHIP_ID
) || (Gx
== VU_CHIP_ID
)) {
2468 aty_st_le32(DAC_CNTL
, 0x87010184, info
);
2469 aty_st_le32(BUS_CNTL
, 0x680000f9, info
);
2472 aty_st_le32(DAC_CNTL
, 0x86010102, info
);
2473 aty_st_le32(BUS_CNTL
, 0x7b23a040, info
);
2474 aty_st_le32(EXT_MEM_CNTL
,
2475 aty_ld_le32(EXT_MEM_CNTL
, info
) | 0x5000001, info
);
2477 aty_st_le32(MEM_CNTL
, i
, info
);
2479 aty_st_8(DAC_MASK
, 0xff, info
);
2481 /* Initialize the graphics engine */
2482 if (par
->accel_flags
& FB_ACCELF_TEXT
)
2483 init_engine(par
, info
);
2485 #ifdef CONFIG_FB_COMPAT_XPMAC
2486 if (console_fb_info
== &info
->fb_info
) {
2487 struct fb_var_screeninfo var
;
2489 display_info
.height
= ((par
->crtc
.v_tot_disp
>>16) & 0x7ff)+1;
2490 display_info
.width
= (((par
->crtc
.h_tot_disp
>>16) & 0xff)+1)*8;
2491 display_info
.depth
= par
->crtc
.bpp
;
2492 display_info
.pitch
= par
->crtc
.vxres
*par
->crtc
.bpp
/8;
2493 atyfb_encode_var(&var
, par
, info
);
2494 if (mac_var_to_vmode(&var
, &vmode
, &cmode
))
2495 display_info
.mode
= 0;
2497 display_info
.mode
= vmode
;
2498 strcpy(display_info
.name
, atyfb_name
);
2499 display_info
.fb_address
= info
->frame_buffer_phys
;
2500 display_info
.cmap_adr_address
= info
->ati_regbase_phys
+0xc0;
2501 display_info
.cmap_data_address
= info
->ati_regbase_phys
+0xc1;
2502 display_info
.disp_reg_address
= info
->ati_regbase_phys
;
2504 #endif /* CONFIG_FB_COMPAT_XPMAC */
2507 static int atyfb_decode_var(const struct fb_var_screeninfo
*var
,
2508 struct atyfb_par
*par
,
2509 const struct fb_info_aty
*info
)
2513 if ((err
= aty_var_to_crtc(info
, var
, &par
->crtc
)))
2515 if ((Gx
== GX_CHIP_ID
) || (Gx
== CX_CHIP_ID
))
2516 switch (info
->clk_type
) {
2517 case CLK_ATI18818_1
:
2518 err
= aty_var_to_pll_18818(var
->pixclock
, &par
->pll
.ics2595
);
2521 err
= aty_var_to_pll_1703(var
->pixclock
, &par
->pll
.ics2595
);
2524 err
= aty_var_to_pll_8398(var
->pixclock
, &par
->pll
.ics2595
);
2527 err
= aty_var_to_pll_408(var
->pixclock
, &par
->pll
.ics2595
);
2530 err
= aty_var_to_pll_514(var
->pixclock
, &par
->pll
.gx
);
2534 err
= aty_var_to_pll_ct(info
, var
->pixclock
, par
->crtc
.bpp
,
2539 if (var
->accel_flags
& FB_ACCELF_TEXT
)
2540 par
->accel_flags
= FB_ACCELF_TEXT
;
2542 par
->accel_flags
= 0;
2545 if (!fbmon_valid_timings(var
->pixclock
, htotal
, vtotal
, info
))
2552 static int atyfb_encode_var(struct fb_var_screeninfo
*var
,
2553 const struct atyfb_par
*par
,
2554 const struct fb_info_aty
*info
)
2558 memset(var
, 0, sizeof(struct fb_var_screeninfo
));
2560 if ((err
= aty_crtc_to_var(&par
->crtc
, var
)))
2562 if ((Gx
== GX_CHIP_ID
) || (Gx
== CX_CHIP_ID
))
2563 switch (info
->clk_type
) {
2564 case CLK_ATI18818_1
:
2565 var
->pixclock
= aty_pll_18818_to_var(&par
->pll
.ics2595
);
2568 var
->pixclock
= aty_pll_1703_to_var(&par
->pll
.ics2595
);
2571 var
->pixclock
= aty_pll_8398_to_var(&par
->pll
.ics2595
);
2574 var
->pixclock
= aty_pll_408_to_var(&par
->pll
.ics2595
);
2577 var
->pixclock
= aty_pll_gx_to_var(&par
->pll
.gx
, info
);
2581 var
->pixclock
= aty_pll_ct_to_var(&par
->pll
.ct
, info
);
2585 var
->accel_flags
= par
->accel_flags
;
2592 static void set_off_pitch(struct atyfb_par
*par
,
2593 const struct fb_info_aty
*info
)
2595 u32 xoffset
= par
->crtc
.xoffset
;
2596 u32 yoffset
= par
->crtc
.yoffset
;
2597 u32 vxres
= par
->crtc
.vxres
;
2598 u32 bpp
= par
->crtc
.bpp
;
2600 par
->crtc
.off_pitch
= ((yoffset
*vxres
+xoffset
)*bpp
/64) | (vxres
<<19);
2601 aty_st_le32(CRTC_OFF_PITCH
, par
->crtc
.off_pitch
, info
);
2606 * Open/Release the frame buffer device
2609 static int atyfb_open(struct fb_info
*info
, int user
)
2613 struct fb_info_aty
*fb
= (struct fb_info_aty
*)info
;
2629 static int atyfb_release(struct fb_info
*info
, int user
)
2632 struct fb_info_aty
*fb
= (struct fb_info_aty
*)info
;
2635 if (fb
->vtconsole
!= -1)
2636 vt_cons
[fb
->vtconsole
]->vc_mode
= KD_TEXT
;
2649 static int encode_fix(struct fb_fix_screeninfo
*fix
,
2650 const struct atyfb_par
*par
,
2651 const struct fb_info_aty
*info
)
2653 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
2655 strcpy(fix
->id
, atyfb_name
);
2656 fix
->smem_start
= info
->frame_buffer_phys
;
2657 fix
->smem_len
= (u32
)info
->total_vram
;
2659 #ifdef __LITTLE_ENDIAN
2661 * Last page of 8 MB little-endian aperture is MMIO
2662 * FIXME: we should use the auxiliary aperture instead so we can acces the
2663 * full 8 MB of video RAM on 8 MB boards
2665 if (fix
->smem_len
> 0x800000-GUI_RESERVE
)
2666 fix
->smem_len
= 0x800000-GUI_RESERVE
;
2669 * Reg Block 0 (CT-compatible block) is at ati_regbase_phys
2670 * Reg Block 1 (multimedia extensions) is at ati_regbase_phys-0x400
2672 if (Gx
== GX_CHIP_ID
|| Gx
== CX_CHIP_ID
) {
2673 fix
->mmio_start
= info
->ati_regbase_phys
;
2674 fix
->mmio_len
= 0x400;
2675 fix
->accel
= FB_ACCEL_ATI_MACH64GX
;
2676 } else if (Gx
== CT_CHIP_ID
|| Gx
== ET_CHIP_ID
) {
2677 fix
->mmio_start
= info
->ati_regbase_phys
;
2678 fix
->mmio_len
= 0x400;
2679 fix
->accel
= FB_ACCEL_ATI_MACH64CT
;
2680 } else if (Gx
== VT_CHIP_ID
|| Gx
== VU_CHIP_ID
|| Gx
== VV_CHIP_ID
) {
2681 fix
->mmio_start
= info
->ati_regbase_phys
-0x400;
2682 fix
->mmio_len
= 0x800;
2683 fix
->accel
= FB_ACCEL_ATI_MACH64VT
;
2685 fix
->mmio_start
= info
->ati_regbase_phys
-0x400;
2686 fix
->mmio_len
= 0x800;
2687 fix
->accel
= FB_ACCEL_ATI_MACH64GT
;
2689 fix
->type
= FB_TYPE_PACKED_PIXELS
;
2691 fix
->line_length
= par
->crtc
.vxres
*par
->crtc
.bpp
/8;
2692 fix
->visual
= par
->crtc
.bpp
<= 8 ? FB_VISUAL_PSEUDOCOLOR
2693 : FB_VISUAL_DIRECTCOLOR
;
2702 struct fb_var_screeninfo default_var
= {
2703 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
2704 640, 480, 640, 480, 0, 0, 8, 0,
2705 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
2706 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
2707 0, FB_VMODE_NONINTERLACED
2712 * Get the Fixed Part of the Display
2715 static int atyfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
2718 const struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
2719 struct atyfb_par par
;
2722 par
= info
->default_par
;
2724 atyfb_decode_var(&fb_display
[con
].var
, &par
, info
);
2725 encode_fix(fix
, &par
, info
);
2731 * Get the User Defined Part of the Display
2734 static int atyfb_get_var(struct fb_var_screeninfo
*var
, int con
,
2737 const struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
2740 atyfb_encode_var(var
, &info
->default_par
, info
);
2742 *var
= fb_display
[con
].var
;
2747 static void atyfb_set_disp(struct display
*disp
, struct fb_info_aty
*info
,
2751 #ifdef FBCON_HAS_CFB8
2753 info
->dispsw
= accel
? fbcon_aty8
: fbcon_cfb8
;
2754 disp
->dispsw
= &info
->dispsw
;
2757 #ifdef FBCON_HAS_CFB16
2759 info
->dispsw
= accel
? fbcon_aty16
: fbcon_cfb16
;
2760 disp
->dispsw
= &info
->dispsw
;
2761 disp
->dispsw_data
= info
->fbcon_cmap
.cfb16
;
2764 #ifdef FBCON_HAS_CFB24
2766 info
->dispsw
= accel
? fbcon_aty24
: fbcon_cfb24
;
2767 disp
->dispsw
= &info
->dispsw
;
2768 disp
->dispsw_data
= info
->fbcon_cmap
.cfb24
;
2771 #ifdef FBCON_HAS_CFB32
2773 info
->dispsw
= accel
? fbcon_aty32
: fbcon_cfb32
;
2774 disp
->dispsw
= &info
->dispsw
;
2775 disp
->dispsw_data
= info
->fbcon_cmap
.cfb32
;
2779 disp
->dispsw
= &fbcon_dummy
;
2782 info
->dispsw
.cursor
= atyfb_cursor
;
2783 info
->dispsw
.set_font
= atyfb_set_font
;
2789 * Set the User Defined Part of the Display
2792 static int atyfb_set_var(struct fb_var_screeninfo
*var
, int con
,
2795 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
2796 struct atyfb_par par
;
2797 struct display
*display
;
2798 int oldxres
, oldyres
, oldvxres
, oldvyres
, oldbpp
, oldaccel
, accel
, err
;
2799 int activate
= var
->activate
;
2802 display
= &fb_display
[con
];
2804 display
= fb
->disp
; /* used during initialization */
2806 if ((err
= atyfb_decode_var(var
, &par
, info
)))
2809 atyfb_encode_var(var
, &par
, (struct fb_info_aty
*)info
);
2811 if ((activate
& FB_ACTIVATE_MASK
) == FB_ACTIVATE_NOW
) {
2812 oldxres
= display
->var
.xres
;
2813 oldyres
= display
->var
.yres
;
2814 oldvxres
= display
->var
.xres_virtual
;
2815 oldvyres
= display
->var
.yres_virtual
;
2816 oldbpp
= display
->var
.bits_per_pixel
;
2817 oldaccel
= display
->var
.accel_flags
;
2818 display
->var
= *var
;
2819 if (oldxres
!= var
->xres
|| oldyres
!= var
->yres
||
2820 oldvxres
!= var
->xres_virtual
|| oldvyres
!= var
->yres_virtual
||
2821 oldbpp
!= var
->bits_per_pixel
|| oldaccel
!= var
->accel_flags
) {
2822 struct fb_fix_screeninfo fix
;
2824 encode_fix(&fix
, &par
, info
);
2825 display
->screen_base
= (char *)info
->frame_buffer
;
2826 display
->visual
= fix
.visual
;
2827 display
->type
= fix
.type
;
2828 display
->type_aux
= fix
.type_aux
;
2829 display
->ypanstep
= fix
.ypanstep
;
2830 display
->ywrapstep
= fix
.ywrapstep
;
2831 display
->line_length
= fix
.line_length
;
2832 display
->can_soft_blank
= 1;
2833 display
->inverse
= 0;
2834 accel
= var
->accel_flags
& FB_ACCELF_TEXT
;
2835 atyfb_set_disp(display
, info
, par
.crtc
.bpp
, accel
);
2837 display
->scrollmode
= (info
->bus_type
== PCI
) ? SCROLL_YNOMOVE
: 0;
2839 display
->scrollmode
= SCROLL_YREDRAW
;
2840 if (info
->fb_info
.changevar
)
2841 (*info
->fb_info
.changevar
)(con
);
2843 if (!info
->fb_info
.display_fg
||
2844 info
->fb_info
.display_fg
->vc_num
== con
)
2845 atyfb_set_par(&par
, info
);
2846 if (oldbpp
!= var
->bits_per_pixel
) {
2847 if ((err
= fb_alloc_cmap(&display
->cmap
, 0, 0)))
2849 do_install_cmap(con
, &info
->fb_info
);
2858 * Pan or Wrap the Display
2860 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
2863 static int atyfb_pan_display(struct fb_var_screeninfo
*var
, int con
,
2866 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
2867 u32 xres
, yres
, xoffset
, yoffset
;
2868 struct atyfb_par
*par
= &info
->current_par
;
2870 xres
= (((par
->crtc
.h_tot_disp
>>16) & 0xff)+1)*8;
2871 yres
= ((par
->crtc
.v_tot_disp
>>16) & 0x7ff)+1;
2872 xoffset
= (var
->xoffset
+7) & ~7;
2873 yoffset
= var
->yoffset
;
2874 if (xoffset
+xres
> par
->crtc
.vxres
|| yoffset
+yres
> par
->crtc
.vyres
)
2876 par
->crtc
.xoffset
= xoffset
;
2877 par
->crtc
.yoffset
= yoffset
;
2878 set_off_pitch(par
, info
);
2886 static int atyfb_get_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
2887 struct fb_info
*info
)
2889 if (!info
->display_fg
|| con
== info
->display_fg
->vc_num
) /* current console? */
2890 return fb_get_cmap(cmap
, kspc
, atyfb_getcolreg
, info
);
2891 else if (fb_display
[con
].cmap
.len
) /* non default colormap? */
2892 fb_copy_cmap(&fb_display
[con
].cmap
, cmap
, kspc
? 0 : 2);
2894 int size
= fb_display
[con
].var
.bits_per_pixel
== 16 ? 32 : 256;
2895 fb_copy_cmap(fb_default_cmap(size
), cmap
, kspc
? 0 : 2);
2904 static int atyfb_set_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
2905 struct fb_info
*info
)
2908 struct display
*disp
;
2911 disp
= &fb_display
[con
];
2914 if (!disp
->cmap
.len
) { /* no colormap allocated? */
2915 int size
= disp
->var
.bits_per_pixel
== 16 ? 32 : 256;
2916 if ((err
= fb_alloc_cmap(&disp
->cmap
, size
, 0)))
2919 if (!info
->display_fg
|| con
== info
->display_fg
->vc_num
) /* current console? */
2920 return fb_set_cmap(cmap
, kspc
, atyfb_setcolreg
, info
);
2922 fb_copy_cmap(cmap
, &disp
->cmap
, kspc
? 0 : 1);
2928 #define ATYIO_CLKR 0x41545900 /* ATY\00 */
2929 #define ATYIO_CLKW 0x41545901 /* ATY\01 */
2935 u8 mclk_post_div
; /* 1,2,3,4,8 */
2937 u8 vclk_post_div
; /* 1,2,3,4,6,8,12 */
2938 u32 dsp_xclks_per_row
; /* 0-16383 */
2939 u32 dsp_loop_latency
; /* 0-15 */
2940 u32 dsp_precision
; /* 0-7 */
2941 u32 dsp_on
; /* 0-2047 */
2942 u32 dsp_off
; /* 0-2047 */
2946 static int atyfb_ioctl(struct inode
*inode
, struct file
*file
, u_int cmd
,
2947 u_long arg
, int con
, struct fb_info
*info2
)
2949 #if defined(__sparc__) || defined(DEBUG)
2950 struct fb_info_aty
*info
= (struct fb_info_aty
*)info2
;
2951 #endif /* __sparc__ || DEBUG */
2953 struct fbtype fbtyp
;
2954 struct display
*disp
;
2957 disp
= &fb_display
[con
];
2965 fbtyp
.fb_type
= FBTYPE_PCI_GENERIC
;
2966 fbtyp
.fb_width
= info
->current_par
.crtc
.vxres
;
2967 fbtyp
.fb_height
= info
->current_par
.crtc
.vyres
;
2968 fbtyp
.fb_depth
= info
->current_par
.crtc
.bpp
;
2969 fbtyp
.fb_cmsize
= disp
->cmap
.len
;
2970 fbtyp
.fb_size
= info
->total_vram
;
2971 copy_to_user_ret((struct fbtype
*)arg
, &fbtyp
, sizeof(fbtyp
), -EFAULT
);
2973 #endif /* __sparc__ */
2976 if ((Gx
!= GX_CHIP_ID
) && (Gx
!= CX_CHIP_ID
)) {
2978 struct pll_ct
*pll
= &info
->current_par
.pll
.ct
;
2979 u32 dsp_config
= pll
->dsp_config
;
2980 u32 dsp_on_off
= pll
->dsp_on_off
;
2981 clk
.ref_clk_per
= info
->ref_clk_per
;
2982 clk
.pll_ref_div
= pll
->pll_ref_div
;
2983 clk
.mclk_fb_div
= pll
->mclk_fb_div
;
2984 clk
.mclk_post_div
= pll
->mclk_post_div_real
;
2985 clk
.vclk_fb_div
= pll
->vclk_fb_div
;
2986 clk
.vclk_post_div
= pll
->vclk_post_div_real
;
2987 clk
.dsp_xclks_per_row
= dsp_config
& 0x3fff;
2988 clk
.dsp_loop_latency
= (dsp_config
>>16) & 0xf;
2989 clk
.dsp_precision
= (dsp_config
>>20) & 7;
2990 clk
.dsp_on
= dsp_on_off
& 0x7ff;
2991 clk
.dsp_off
= (dsp_on_off
>>16) & 0x7ff;
2992 copy_to_user_ret((struct atyclk
*)arg
, &clk
, sizeof(clk
),
2998 if ((Gx
!= GX_CHIP_ID
) && (Gx
!= CX_CHIP_ID
)) {
3000 struct pll_ct
*pll
= &info
->current_par
.pll
.ct
;
3001 copy_from_user_ret(&clk
, (struct atyclk
*)arg
, sizeof(clk
),
3003 info
->ref_clk_per
= clk
.ref_clk_per
;
3004 pll
->pll_ref_div
= clk
.pll_ref_div
;
3005 pll
->mclk_fb_div
= clk
.mclk_fb_div
;
3006 pll
->mclk_post_div_real
= clk
.mclk_post_div
;
3007 pll
->vclk_fb_div
= clk
.vclk_fb_div
;
3008 pll
->vclk_post_div_real
= clk
.vclk_post_div
;
3009 pll
->dsp_config
= (clk
.dsp_xclks_per_row
& 0x3fff) |
3010 ((clk
.dsp_loop_latency
& 0xf)<<16) |
3011 ((clk
.dsp_precision
& 7)<<20);
3012 pll
->dsp_on_off
= (clk
.dsp_on
& 0x7ff) |
3013 ((clk
.dsp_off
& 0x7ff)<<16);
3014 aty_calc_pll_ct(info
, pll
);
3015 aty_set_pll_ct(info
, pll
);
3026 static int atyfb_rasterimg(struct fb_info
*info
, int start
)
3028 struct fb_info_aty
*fb
= (struct fb_info_aty
*)info
;
3030 if (fb
->blitter_may_be_busy
)
3036 static int atyfb_mmap(struct fb_info
*info
, struct file
*file
,
3037 struct vm_area_struct
*vma
)
3039 struct fb_info_aty
*fb
= (struct fb_info_aty
*)info
;
3040 unsigned int size
, page
, map_size
= 0;
3041 unsigned long map_offset
= 0;
3047 size
= vma
->vm_end
- vma
->vm_start
;
3048 if (vma
->vm_offset
& ~PAGE_MASK
)
3051 /* To stop the swapper from even considering these pages. */
3052 vma
->vm_flags
|= (VM_SHM
| VM_LOCKED
);
3054 if (((vma
->vm_offset
== 0) && (size
== fb
->total_vram
)) ||
3055 ((vma
->vm_offset
== fb
->total_vram
) && (size
== PAGE_SIZE
)))
3056 vma
->vm_offset
+= 0x8000000000000000UL
;
3059 /* Align it as much as desirable */
3061 unsigned long j
, align
;
3064 map_offset
= vma
->vm_offset
+size
;
3065 for (i
= 0; fb
->mmap_map
[i
].size
; i
++) {
3066 if (fb
->mmap_map
[i
].voff
< vma
->vm_offset
)
3068 if (fb
->mmap_map
[i
].voff
>= map_offset
)
3071 fb
->mmap_map
[i
].size
> fb
->mmap_map
[max
].size
)
3075 j
= fb
->mmap_map
[max
].size
;
3076 if (fb
->mmap_map
[max
].voff
+ j
> map_offset
)
3077 j
= map_offset
- fb
->mmap_map
[max
].voff
;
3078 for (align
= 0x400000; align
> PAGE_SIZE
; align
>>= 3)
3080 !(fb
->mmap_map
[max
].poff
& (align
- 1)))
3082 if (align
> PAGE_SIZE
) {
3084 align
= j
- ((vma
->vm_start
3085 + fb
->mmap_map
[max
].voff
3086 - vma
->vm_offset
) & (j
- 1));
3088 struct vm_area_struct
*vmm
;
3090 vmm
= find_vma(current
->mm
,
3092 if (!vmm
|| vmm
->vm_start
3093 >= vma
->vm_end
+ align
) {
3094 vma
->vm_start
+= align
;
3095 vma
->vm_end
+= align
;
3103 /* Each page, see which map applies */
3104 for (page
= 0; page
< size
; ) {
3106 for (i
= 0; fb
->mmap_map
[i
].size
; i
++) {
3107 unsigned long start
= fb
->mmap_map
[i
].voff
;
3108 unsigned long end
= start
+ fb
->mmap_map
[i
].size
;
3109 unsigned long offset
= vma
->vm_offset
+ page
;
3116 map_size
= fb
->mmap_map
[i
].size
- (offset
- start
);
3117 map_offset
= fb
->mmap_map
[i
].poff
+ (offset
- start
);
3124 if (page
+ map_size
> size
)
3125 map_size
= size
- page
;
3127 pgprot_val(vma
->vm_page_prot
) &= ~(fb
->mmap_map
[i
].prot_mask
);
3128 pgprot_val(vma
->vm_page_prot
) |= fb
->mmap_map
[i
].prot_flag
;
3130 if (remap_page_range(vma
->vm_start
+ page
, map_offset
,
3131 map_size
, vma
->vm_page_prot
))
3140 vma
->vm_flags
|= VM_IO
;
3143 int lastconsole
= 0;
3145 if (info
->display_fg
)
3146 lastconsole
= info
->display_fg
->vc_num
;
3148 if (fb
->consolecnt
&& fb_display
[lastconsole
].fb_info
== info
) {
3149 fb
->vtconsole
= lastconsole
;
3150 vt_cons
[lastconsole
]->vc_mode
= KD_GRAPHICS
;
3163 static void atyfb_save_palette(struct fb_info
*fb
, int enter
)
3165 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
3168 for (i
= 0; i
< 256; i
++) {
3169 tmp
= aty_ld_8(DAC_CNTL
, info
) & 0xfc;
3170 if (Gx
== GT_CHIP_ID
|| Gx
== GU_CHIP_ID
|| Gx
== GV_CHIP_ID
||
3171 Gx
== GW_CHIP_ID
|| Gx
== GZ_CHIP_ID
|| Gx
== LG_CHIP_ID
||
3172 Gx
== GB_CHIP_ID
|| Gx
== GD_CHIP_ID
|| Gx
== GI_CHIP_ID
||
3173 Gx
== GP_CHIP_ID
|| Gx
== GQ_CHIP_ID
)
3175 aty_st_8(DAC_CNTL
, tmp
, info
);
3176 aty_st_8(DAC_MASK
, 0xff, info
);
3178 scale
= ((Gx
!= GX_CHIP_ID
) && (Gx
!= CX_CHIP_ID
) &&
3179 (info
->current_par
.crtc
.bpp
== 16)) ? 3 : 0;
3180 info
->aty_cmap_regs
->rindex
= i
<< scale
;
3182 atyfb_save
.r
[enter
][i
] = info
->aty_cmap_regs
->lut
;
3184 atyfb_save
.g
[enter
][i
] = info
->aty_cmap_regs
->lut
;
3186 atyfb_save
.b
[enter
][i
] = info
->aty_cmap_regs
->lut
;
3188 info
->aty_cmap_regs
->windex
= i
<< scale
;
3190 info
->aty_cmap_regs
->lut
= atyfb_save
.r
[1-enter
][i
];
3192 info
->aty_cmap_regs
->lut
= atyfb_save
.g
[1-enter
][i
];
3194 info
->aty_cmap_regs
->lut
= atyfb_save
.b
[1-enter
][i
];
3199 static void atyfb_palette(int enter
)
3201 struct fb_info_aty
*info
;
3202 struct atyfb_par
*par
;
3206 for (i
= 0; i
< MAX_NR_CONSOLES
; i
++) {
3209 d
->fb_info
->fbops
== &atyfb_ops
&&
3210 d
->fb_info
->display_fg
&&
3211 d
->fb_info
->display_fg
->vc_num
== i
) {
3212 atyfb_save_palette(d
->fb_info
, enter
);
3213 info
= (struct fb_info_aty
*)d
->fb_info
;
3214 par
= &info
->current_par
;
3216 atyfb_save
.yoffset
= par
->crtc
.yoffset
;
3217 par
->crtc
.yoffset
= 0;
3218 set_off_pitch(par
, info
);
3220 par
->crtc
.yoffset
= atyfb_save
.yoffset
;
3221 set_off_pitch(par
, info
);
3227 #endif /* __sparc__ */
3233 static int __init
aty_init(struct fb_info_aty
*info
, const char *name
)
3238 struct fb_var_screeninfo var
;
3239 struct display
*disp
;
3240 const char *chipname
= NULL
, *ramname
= NULL
, *xtal
;
3241 int pll
, mclk
, gtb_memsize
;
3242 #if defined(CONFIG_PPC)
3247 info
->aty_cmap_regs
= (struct aty_cmap_regs
*)(info
->ati_regbase
+0xc0);
3249 info
->aty_cmap_regs
= __va(info
->aty_cmap_regs
);
3251 chip_id
= aty_ld_le32(CONFIG_CHIP_ID
, info
);
3252 Gx
= chip_id
& CFG_CHIP_TYPE
;
3253 Rev
= (chip_id
& CFG_CHIP_REV
)>>24;
3254 for (j
= 0; j
< (sizeof(aty_features
)/sizeof(*aty_features
)); j
++)
3255 if (aty_features
[j
].chip_type
== Gx
) {
3256 chipname
= aty_features
[j
].name
;
3257 info
->dac_type
= (aty_ld_le32(DAC_CNTL
, info
) >> 16) & 0x07;
3261 printk("atyfb: Unknown mach64 0x%04x\n", Gx
);
3264 printk("atyfb: %s [0x%04x rev 0x%02x] ", chipname
, Gx
, Rev
);
3265 if ((Gx
== GX_CHIP_ID
) || (Gx
== CX_CHIP_ID
)) {
3266 info
->bus_type
= (aty_ld_le32(CONFIG_STAT0
, info
) >> 0) & 0x07;
3267 info
->ram_type
= (aty_ld_le32(CONFIG_STAT0
, info
) >> 3) & 0x07;
3268 ramname
= aty_gx_ram
[info
->ram_type
];
3269 /* FIXME: clockchip/RAMDAC probing? */
3271 info
->clk_type
= CLK_ATI18818_1
;
3272 info
->dac_type
= (aty_ld_le32(CONFIG_STAT0
, info
) >> 9) & 0x07;
3273 if (info
->dac_type
== 0x07)
3274 info
->dac_subtype
= DAC_ATT20C408
;
3276 info
->dac_subtype
= (aty_ld_8(SCRATCH_REG1
+ 1, info
) & 0xF0) |
3279 info
->dac_type
= DAC_IBMRGB514
;
3280 info
->dac_subtype
= DAC_IBMRGB514
;
3281 info
->clk_type
= CLK_IBMRGB514
;
3287 info
->bus_type
= PCI
;
3288 info
->ram_type
= (aty_ld_le32(CONFIG_STAT0
, info
) & 0x07);
3289 ramname
= aty_ct_ram
[info
->ram_type
];
3290 info
->dac_type
= DAC_INTERNAL
;
3291 info
->dac_subtype
= DAC_INTERNAL
;
3292 info
->clk_type
= CLK_INTERNAL
;
3293 if ((Gx
== CT_CHIP_ID
) || (Gx
== ET_CHIP_ID
)) {
3297 mclk
= info
->ram_type
>= SDRAM
? 67 : 63;
3298 if ((Gx
== VT_CHIP_ID
) && (Rev
== 0x08)) {
3301 } else if (((Gx
== VT_CHIP_ID
) && ((Rev
== 0x40) ||
3303 ((Gx
== VT_CHIP_ID
) && ((Rev
== 0x01) ||
3308 } else if (Gx
== VV_CHIP_ID
) {
3312 } else if (Gx
== VT_CHIP_ID
) {
3316 } else if ((Gx
== GT_CHIP_ID
) && (Rev
& 0x01)) {
3319 } else if (((Gx
== GT_CHIP_ID
) && (Rev
& 0x02)) ||
3320 (Gx
== GU_CHIP_ID
)) {
3323 } else if (Gx
== GV_CHIP_ID
|| Gx
== GW_CHIP_ID
||
3328 } else if (Gx
== GB_CHIP_ID
|| Gx
== GD_CHIP_ID
||
3329 Gx
== GI_CHIP_ID
|| Gx
== GP_CHIP_ID
||
3330 Gx
== GQ_CHIP_ID
|| Gx
== LB_CHIP_ID
||
3331 Gx
== LD_CHIP_ID
|| Gx
== LG_CHIP_ID
||
3332 Gx
== LI_CHIP_ID
|| Gx
== LP_CHIP_ID
) {
3333 /* RAGE PRO or LT PRO */
3344 info
->ref_clk_per
= 1000000000000ULL/14318180;
3346 if (!(Gx
== GX_CHIP_ID
|| Gx
== CX_CHIP_ID
|| Gx
== CT_CHIP_ID
||
3348 ((Gx
== VT_CHIP_ID
|| Gx
== GT_CHIP_ID
) && !(Rev
& 0x07))) &&
3349 (pll_ref_div
= aty_ld_pll(PLL_REF_DIV
, info
))) {
3351 diff1
= 510*14/pll_ref_div
-pll
;
3352 diff2
= 510*29/pll_ref_div
-pll
;
3357 if (diff2
< diff1
) {
3358 info
->ref_clk_per
= 1000000000000ULL/29498928;
3363 i
= aty_ld_le32(MEM_CNTL
, info
);
3364 gtb_memsize
= !(Gx
== GX_CHIP_ID
|| Gx
== CX_CHIP_ID
|| Gx
== CT_CHIP_ID
||
3366 ((Gx
== VT_CHIP_ID
|| Gx
== GT_CHIP_ID
) && !(Rev
& 0x07)));
3368 switch (i
& 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */
3370 info
->total_vram
= 0x80000;
3373 info
->total_vram
= 0x100000;
3375 case MEM_SIZE_2M_GTB
:
3376 info
->total_vram
= 0x200000;
3378 case MEM_SIZE_4M_GTB
:
3379 info
->total_vram
= 0x400000;
3381 case MEM_SIZE_6M_GTB
:
3382 info
->total_vram
= 0x600000;
3384 case MEM_SIZE_8M_GTB
:
3385 info
->total_vram
= 0x800000;
3388 info
->total_vram
= 0x80000;
3391 switch (i
& MEM_SIZE_ALIAS
) {
3393 info
->total_vram
= 0x80000;
3396 info
->total_vram
= 0x100000;
3399 info
->total_vram
= 0x200000;
3402 info
->total_vram
= 0x400000;
3405 info
->total_vram
= 0x600000;
3408 info
->total_vram
= 0x800000;
3411 info
->total_vram
= 0x80000;
3414 if (Gx
== GI_CHIP_ID
) {
3415 if (aty_ld_le32(CONFIG_STAT1
, info
) & 0x40000000)
3416 info
->total_vram
+= 0x400000;
3420 info
->total_vram
= default_vram
*1024;
3421 i
= i
& ~(gtb_memsize
? 0xF : MEM_SIZE_ALIAS
);
3422 if (info
->total_vram
<= 0x80000)
3424 else if (info
->total_vram
<= 0x100000)
3426 else if (info
->total_vram
<= 0x200000)
3427 i
|= gtb_memsize
? MEM_SIZE_2M_GTB
: MEM_SIZE_2M
;
3428 else if (info
->total_vram
<= 0x400000)
3429 i
|= gtb_memsize
? MEM_SIZE_4M_GTB
: MEM_SIZE_4M
;
3430 else if (info
->total_vram
<= 0x600000)
3431 i
|= gtb_memsize
? MEM_SIZE_6M_GTB
: MEM_SIZE_6M
;
3433 i
|= gtb_memsize
? MEM_SIZE_8M_GTB
: MEM_SIZE_8M
;
3434 aty_st_le32(MEM_CNTL
, i
, info
);
3439 mclk
= default_mclk
;
3441 printk("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK\n",
3442 info
->total_vram
== 0x80000 ? 512 : (info
->total_vram
>> 20),
3443 info
->total_vram
== 0x80000 ? 'K' : 'M', ramname
, xtal
, pll
, mclk
);
3446 info
->mem_refresh_rate
= 0; /* 000 = 10 Mhz - 43 Mhz */
3448 info
->mem_refresh_rate
= 1; /* 001 = 44 Mhz - 49 Mhz */
3450 info
->mem_refresh_rate
= 2; /* 010 = 50 Mhz - 54 Mhz */
3452 info
->mem_refresh_rate
= 3; /* 011 = 55 Mhz - 65 Mhz */
3454 info
->mem_refresh_rate
= 4; /* 100 = 66 Mhz - 74 Mhz */
3456 info
->mem_refresh_rate
= 5; /* 101 = 75 Mhz - 79 Mhz */
3457 else if (mclk
< 100)
3458 info
->mem_refresh_rate
= 6; /* 110 = 80 Mhz - 100 Mhz */
3460 info
->mem_refresh_rate
= 7; /* 111 = 100 Mhz and above */
3461 info
->pll_per
= 1000000/pll
;
3462 info
->mclk_per
= 1000000/mclk
;
3465 if ((Gx
!= GX_CHIP_ID
) && (Gx
!= CX_CHIP_ID
)) {
3467 printk("BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
3468 "DSP_CONFIG DSP_ON_OFF\n"
3469 "%08x %08x %08x %08x %08x %08x %08x\n"
3471 aty_ld_le32(BUS_CNTL
, info
), aty_ld_le32(DAC_CNTL
, info
),
3472 aty_ld_le32(MEM_CNTL
, info
), aty_ld_le32(EXT_MEM_CNTL
, info
),
3473 aty_ld_le32(CRTC_GEN_CNTL
, info
), aty_ld_le32(DSP_CONFIG
, info
),
3474 aty_ld_le32(DSP_ON_OFF
, info
));
3475 for (i
= 0; i
< 16; i
++)
3476 printk(" %02x", aty_ld_pll(i
, info
));
3481 if (info
->bus_type
== ISA
)
3482 if ((info
->total_vram
== 0x400000) || (info
->total_vram
== 0x800000)) {
3483 /* protect GUI-regs if complete Aperture is VRAM */
3484 info
->total_vram
-= GUI_RESERVE
;
3489 strcpy(info
->fb_info
.modename
, atyfb_name
);
3490 info
->fb_info
.node
= -1;
3491 info
->fb_info
.fbops
= &atyfb_ops
;
3492 info
->fb_info
.disp
= disp
;
3493 strcpy(info
->fb_info
.fontname
, fontname
);
3494 info
->fb_info
.changevar
= NULL
;
3495 info
->fb_info
.switch_con
= &atyfbcon_switch
;
3496 info
->fb_info
.updatevar
= &atyfbcon_updatevar
;
3497 info
->fb_info
.blank
= &atyfbcon_blank
;
3498 info
->fb_info
.flags
= FBINFO_FLAG_DEFAULT
;
3503 memset(&var
, 0, sizeof(var
));
3504 #if defined(CONFIG_PPC)
3506 if (!mac_find_mode(&var
, &info
->fb_info
, mode_option
, 8))
3509 if (default_vmode
== VMODE_NVRAM
) {
3510 default_vmode
= nvram_read_byte(NV_VMODE
);
3511 if (default_vmode
<= 0 || default_vmode
> VMODE_MAX
)
3512 default_vmode
= VMODE_CHOOSE
;
3514 if (default_vmode
== VMODE_CHOOSE
) {
3515 if (Gx
== LG_CHIP_ID
)
3516 /* G3 PowerBook with 1024x768 LCD */
3517 default_vmode
= VMODE_1024_768_60
;
3519 sense
= read_aty_sense(info
);
3520 default_vmode
= mac_map_monitor_sense(sense
);
3523 if (default_vmode
<= 0 || default_vmode
> VMODE_MAX
)
3524 default_vmode
= VMODE_640_480_60
;
3525 if (default_cmode
== CMODE_NVRAM
)
3526 default_cmode
= nvram_read_byte(NV_CMODE
);
3527 if (default_cmode
< CMODE_8
|| default_cmode
> CMODE_32
)
3528 default_cmode
= CMODE_8
;
3529 if (mac_vmode_to_var(default_vmode
, default_cmode
, &var
))
3532 #else /* !CONFIG_PPC */
3535 if (!fb_find_mode(&var
, &info
->fb_info
, mode_option
, NULL
, 0, NULL
, 8))
3540 if (!fb_find_mode(&var
, &info
->fb_info
, mode_option
, NULL
, 0, NULL
, 8))
3542 #endif /* !__sparc__ */
3543 #endif /* !CONFIG_PPC */
3544 #endif /* !MODULE */
3546 var
.accel_flags
&= ~FB_ACCELF_TEXT
;
3548 var
.accel_flags
|= FB_ACCELF_TEXT
;
3550 if (var
.yres
== var
.yres_virtual
) {
3551 u32 vram
= (info
->total_vram
- (PAGE_SIZE
<< 2));
3552 var
.yres_virtual
= ((vram
* 8) / var
.bits_per_pixel
) / var
.xres_virtual
;
3553 if (var
.yres_virtual
< var
.yres
)
3554 var
.yres_virtual
= var
.yres
;
3557 if (atyfb_decode_var(&var
, &info
->default_par
, info
)) {
3558 printk("atyfb: can't set default video mode\n");
3563 atyfb_save_palette(&info
->fb_info
, 0);
3565 for (j
= 0; j
< 16; j
++) {
3567 info
->palette
[j
].red
= default_red
[k
];
3568 info
->palette
[j
].green
= default_grn
[k
];
3569 info
->palette
[j
].blue
= default_blu
[k
];
3572 if (Gx
!= GX_CHIP_ID
&& Gx
!= CX_CHIP_ID
) {
3573 info
->cursor
= aty_init_cursor(info
);
3575 info
->dispsw
.cursor
= atyfb_cursor
;
3576 info
->dispsw
.set_font
= atyfb_set_font
;
3580 atyfb_set_var(&var
, -1, &info
->fb_info
);
3582 if (register_framebuffer(&info
->fb_info
) < 0)
3585 info
->next
= fb_list
;
3588 printk("fb%d: %s frame buffer device on %s\n",
3589 GET_FB_IDX(info
->fb_info
.node
), atyfb_name
, name
);
3593 int __init
atyfb_init(void)
3595 #if defined(CONFIG_FB_OF)
3596 /* We don't want to be called like this. */
3597 /* We rely on Open Firmware (offb) instead. */
3598 #elif defined(CONFIG_PCI)
3599 struct pci_dev
*pdev
;
3600 struct fb_info_aty
*info
;
3603 extern void (*prom_palette
) (int);
3604 extern int con_is_present(void);
3605 struct pcidev_cookie
*pcp
;
3611 /* Do not attach when we have a serial console. */
3612 if (!con_is_present())
3618 for (pdev
= pci_devices
; pdev
; pdev
= pdev
->next
) {
3619 if (((pdev
->class >> 16) == PCI_BASE_CLASS_DISPLAY
) &&
3620 (pdev
->vendor
== PCI_VENDOR_ID_ATI
)) {
3621 struct resource
*rp
;
3623 info
= kmalloc(sizeof(struct fb_info_aty
), GFP_ATOMIC
);
3625 printk("atyfb_init: can't alloc fb_info_aty\n");
3628 memset(info
, 0, sizeof(struct fb_info_aty
));
3630 rp
= &pdev
->resource
[0];
3631 if (rp
->flags
& IORESOURCE_IO
)
3632 rp
= &pdev
->resource
[1];
3639 * Map memory-mapped registers.
3641 info
->ati_regbase
= addr
+ 0x7ffc00UL
;
3642 info
->ati_regbase_phys
= addr
+ 0x7ffc00UL
;
3645 * Map in big-endian aperture.
3647 info
->frame_buffer
= (unsigned long) __va(addr
+ 0x800000UL
);
3648 info
->frame_buffer_phys
= addr
+ 0x800000UL
;
3651 * Figure mmap addresses from PCI config space.
3652 * Split Framebuffer in big- and little-endian halfs.
3654 for (i
= 0; i
< 6 && pdev
->resource
[i
].start
; i
++)
3658 info
->mmap_map
= kmalloc(j
* sizeof(*info
->mmap_map
), GFP_ATOMIC
);
3659 if (!info
->mmap_map
) {
3660 printk("atyfb_init: can't alloc mmap_map\n");
3664 memset(info
->mmap_map
, 0, j
* sizeof(*info
->mmap_map
));
3666 for (i
= 0, j
= 2; i
< 6 && pdev
->resource
[i
].start
; i
++) {
3667 struct resource
*rp
= &pdev
->resource
[i
];
3668 int io
, breg
= PCI_BASE_ADDRESS_0
+ (i
<< 2);
3674 io
= (rp
->flags
& IORESOURCE_IO
);
3676 size
= rp
->end
- base
+ 1;
3678 pci_read_config_dword(pdev
, breg
, &pbase
);
3684 * Map the framebuffer a second time, this time without
3685 * the braindead _PAGE_IE setting. This is used by the
3686 * fixed Xserver, but we need to maintain the old mapping
3687 * to stay compatible with older ones...
3690 info
->mmap_map
[j
].voff
= (pbase
+ 0x10000000) & PAGE_MASK
;
3691 info
->mmap_map
[j
].poff
= base
& PAGE_MASK
;
3692 info
->mmap_map
[j
].size
= (size
+ ~PAGE_MASK
) & PAGE_MASK
;
3693 info
->mmap_map
[j
].prot_mask
= _PAGE_CACHE
;
3694 info
->mmap_map
[j
].prot_flag
= _PAGE_E
;
3699 * Here comes the old framebuffer mapping with _PAGE_IE
3700 * set for the big endian half of the framebuffer...
3703 info
->mmap_map
[j
].voff
= (pbase
+ 0x800000) & PAGE_MASK
;
3704 info
->mmap_map
[j
].poff
= (base
+0x800000) & PAGE_MASK
;
3705 info
->mmap_map
[j
].size
= 0x800000;
3706 info
->mmap_map
[j
].prot_mask
= _PAGE_CACHE
;
3707 info
->mmap_map
[j
].prot_flag
= _PAGE_E
|_PAGE_IE
;
3712 info
->mmap_map
[j
].voff
= pbase
& PAGE_MASK
;
3713 info
->mmap_map
[j
].poff
= base
& PAGE_MASK
;
3714 info
->mmap_map
[j
].size
= (size
+ ~PAGE_MASK
) & PAGE_MASK
;
3715 info
->mmap_map
[j
].prot_mask
= _PAGE_CACHE
;
3716 info
->mmap_map
[j
].prot_flag
= _PAGE_E
;
3721 * Fix PROMs idea of MEM_CNTL settings...
3723 mem
= aty_ld_le32(MEM_CNTL
, info
);
3724 chip_id
= aty_ld_le32(CONFIG_CHIP_ID
, info
);
3725 if (((chip_id
& CFG_CHIP_TYPE
) == VT_CHIP_ID
) &&
3726 !((chip_id
>> 24) & 1)) {
3727 switch (mem
& 0x0f) {
3729 mem
= (mem
& ~(0x0f)) | 2;
3732 mem
= (mem
& ~(0x0f)) | 3;
3735 mem
= (mem
& ~(0x0f)) | 4;
3738 mem
= (mem
& ~(0x0f)) | 5;
3743 if ((aty_ld_le32(CONFIG_STAT0
, info
) & 7) >= SDRAM
)
3744 mem
&= ~(0x00700000);
3746 mem
&= ~(0xcf80e000); /* Turn off all undocumented bits. */
3747 aty_st_le32(MEM_CNTL
, mem
, info
);
3750 * If this is the console device, we will set default video
3751 * settings to what the PROM left us with.
3753 node
= prom_getchild(prom_root_node
);
3754 node
= prom_searchsiblings(node
, "aliases");
3756 len
= prom_getproperty(node
, "screen", prop
, sizeof(prop
));
3759 node
= prom_finddevice(prop
);
3765 pcp
= pdev
->sysdata
;
3766 if (node
== pcp
->prom_node
) {
3768 struct fb_var_screeninfo
*var
= &default_var
;
3769 unsigned int N
, P
, Q
, M
, T
;
3770 u32 v_total
, h_total
;
3775 crtc
.vxres
= prom_getintdefault(node
, "width", 1024);
3776 crtc
.vyres
= prom_getintdefault(node
, "height", 768);
3777 crtc
.bpp
= prom_getintdefault(node
, "depth", 8);
3778 crtc
.xoffset
= crtc
.yoffset
= 0;
3779 crtc
.h_tot_disp
= aty_ld_le32(CRTC_H_TOTAL_DISP
, info
);
3780 crtc
.h_sync_strt_wid
= aty_ld_le32(CRTC_H_SYNC_STRT_WID
, info
);
3781 crtc
.v_tot_disp
= aty_ld_le32(CRTC_V_TOTAL_DISP
, info
);
3782 crtc
.v_sync_strt_wid
= aty_ld_le32(CRTC_V_SYNC_STRT_WID
, info
);
3783 crtc
.gen_cntl
= aty_ld_le32(CRTC_GEN_CNTL
, info
);
3784 aty_crtc_to_var(&crtc
, var
);
3786 h_total
= var
->xres
+ var
->right_margin
+
3787 var
->hsync_len
+ var
->left_margin
;
3788 v_total
= var
->yres
+ var
->lower_margin
+
3789 var
->vsync_len
+ var
->upper_margin
;
3792 * Read the PLL to figure actual Refresh Rate.
3794 clock_cntl
= aty_ld_8(CLOCK_CNTL
, info
);
3795 /* printk("atyfb: CLOCK_CNTL: %02x\n", clock_cntl); */
3796 for (i
= 0; i
< 16; i
++)
3797 pll_regs
[i
] = aty_ld_pll(i
, info
);
3800 * PLL Reference Devider M:
3805 * PLL Feedback Devider N (Dependant on CLOCK_CNTL):
3807 N
= pll_regs
[7 + (clock_cntl
& 3)];
3810 * PLL Post Devider P (Dependant on CLOCK_CNTL):
3812 P
= 1 << (pll_regs
[6] >> ((clock_cntl
& 3) << 1));
3826 * where R is XTALIN (= 14318 kHz).
3828 T
= 2 * Q
* 14318 / M
;
3830 default_var
.pixclock
= 1000000000 / T
;
3833 #else /* __sparc__ */
3835 info
->ati_regbase_phys
= 0x7ff000 + addr
;
3836 info
->ati_regbase
= (unsigned long)
3837 ioremap(info
->ati_regbase_phys
, 0x1000);
3839 if(!info
->ati_regbase
) {
3844 info
->ati_regbase_phys
+= 0xc00;
3845 info
->ati_regbase
+= 0xc00;
3848 * Enable memory-space accesses using config-space
3851 pci_read_config_word(pdev
, PCI_COMMAND
, &tmp
);
3852 if (!(tmp
& PCI_COMMAND_MEMORY
)) {
3853 tmp
|= PCI_COMMAND_MEMORY
;
3854 pci_write_config_word(pdev
, PCI_COMMAND
, tmp
);
3858 /* Use the big-endian aperture */
3862 /* Map in frame buffer */
3863 info
->frame_buffer_phys
= addr
;
3864 info
->frame_buffer
= (unsigned long)ioremap(addr
, 0x800000);
3866 if(!info
->frame_buffer
) {
3871 #endif /* __sparc__ */
3873 if (!aty_init(info
, "PCI")) {
3875 kfree(info
->mmap_map
);
3882 prom_palette
= atyfb_palette
;
3885 * Add /dev/fb mmap values.
3887 info
->mmap_map
[0].voff
= 0x8000000000000000UL
;
3888 info
->mmap_map
[0].poff
= __pa(info
->frame_buffer
& PAGE_MASK
);
3889 info
->mmap_map
[0].size
= info
->total_vram
;
3890 info
->mmap_map
[0].prot_mask
= _PAGE_CACHE
;
3891 info
->mmap_map
[0].prot_flag
= _PAGE_E
;
3892 info
->mmap_map
[1].voff
= info
->mmap_map
[0].voff
+ info
->total_vram
;
3893 info
->mmap_map
[1].poff
= info
->ati_regbase
& PAGE_MASK
;
3894 info
->mmap_map
[1].size
= PAGE_SIZE
;
3895 info
->mmap_map
[1].prot_mask
= _PAGE_CACHE
;
3896 info
->mmap_map
[1].prot_flag
= _PAGE_E
;
3897 #endif /* __sparc__ */
3901 #elif defined(CONFIG_ATARI)
3904 struct fb_info_aty
*info
;
3906 for (m64_num
= 0; m64_num
< mach64_count
; m64_num
++) {
3907 if (!phys_vmembase
[m64_num
] || !phys_size
[m64_num
] ||
3908 !phys_guiregbase
[m64_num
]) {
3909 printk(" phys_*[%d] parameters not set => returning early. \n",
3914 info
= kmalloc(sizeof(struct fb_info_aty
), GFP_ATOMIC
);
3916 printk("atyfb_init: can't alloc fb_info_aty\n");
3919 memset(info
, 0, sizeof(struct fb_info_aty
));
3922 * Map the video memory (physical address given) to somewhere in the
3923 * kernel address space.
3925 info
->frame_buffer
= ioremap(phys_vmembase
[m64_num
], phys_size
[m64_num
]);
3926 info
->frame_buffer_phys
= info
->frame_buffer
; /* Fake! */
3927 info
->ati_regbase
= ioremap(phys_guiregbase
[m64_num
], 0x10000)+0xFC00ul
;
3928 info
->ati_regbase_phys
= info
->ati_regbase
; /* Fake! */
3930 aty_st_le32(CLOCK_CNTL
, 0x12345678, info
);
3931 clock_r
= aty_ld_le32(CLOCK_CNTL
, info
);
3933 switch (clock_r
& 0x003F) {
3935 info
->clk_wr_offset
= 3; /* */
3938 info
->clk_wr_offset
= 2; /* Medusa ST-IO ISA Adapter etc. */
3941 info
->clk_wr_offset
= 1; /* */
3944 info
->clk_wr_offset
= 0; /* Panther 1 ISA Adapter (Gerald) */
3948 if (!aty_init(info
, "ISA bus")) {
3950 /* This is insufficient! kernel_map has added two large chunks!! */
3954 #endif /* CONFIG_ATARI */
3959 void __init
atyfb_of_init(struct device_node
*dp
)
3964 struct fb_info_aty
*info
;
3967 switch (dp
->n_addrs
) {
3971 addr
= dp
->addrs
[0].address
;
3974 addr
= dp
->addrs
[1].address
;
3977 printk("Warning: got %d adresses for ATY:\n", dp
->n_addrs
);
3978 for (i
= 0; i
< dp
->n_addrs
; i
++)
3979 printk(" %08x-%08x", dp
->addrs
[i
].address
,
3980 dp
->addrs
[i
].address
+dp
->addrs
[i
].size
-1);
3986 info
= kmalloc(sizeof(struct fb_info_aty
), GFP_ATOMIC
);
3988 printk("atyfb_of_init: can't alloc fb_info_aty\n");
3991 memset(info
, 0, sizeof(struct fb_info_aty
));
3993 info
->ati_regbase_phys
= 0x7ff000+addr
;
3994 info
->ati_regbase
= (unsigned long)ioremap(info
->ati_regbase_phys
,
3997 if(! info
->ati_regbase
) {
3998 printk("atyfb_of_init: ioremap() returned NULL\n");
4003 info
->ati_regbase_phys
+= 0xc00;
4004 info
->ati_regbase
+= 0xc00;
4006 /* enable memory-space accesses using config-space command register */
4007 if (pci_device_loc(dp
, &bus
, &devfn
) == 0) {
4008 pcibios_read_config_word(bus
, devfn
, PCI_COMMAND
, &cmd
);
4009 if (cmd
!= 0xffff) {
4010 cmd
|= PCI_COMMAND_MEMORY
;
4011 pcibios_write_config_word(bus
, devfn
, PCI_COMMAND
, cmd
);
4016 /* Use the big-endian aperture */
4020 /* Map in frame buffer */
4021 info
->frame_buffer_phys
= addr
;
4022 info
->frame_buffer
= (unsigned long)ioremap(addr
, 0x800000);
4024 if(! info
->frame_buffer
) {
4025 printk("atyfb_of_init: ioremap() returned NULL\n");
4030 if (!aty_init(info
, dp
->full_name
)) {
4035 #ifdef CONFIG_FB_COMPAT_XPMAC
4036 if (!console_fb_info
)
4037 console_fb_info
= &info
->fb_info
;
4038 #endif /* CONFIG_FB_COMPAT_XPMAC */
4040 #endif /* CONFIG_FB_OF */
4044 int __init
atyfb_setup(char *options
)
4048 if (!options
|| !*options
)
4051 for (this_opt
= strtok(options
, ","); this_opt
;
4052 this_opt
= strtok(NULL
, ",")) {
4053 if (!strncmp(this_opt
, "font:", 5)) {
4058 for (i
= 0; i
< sizeof(fontname
) - 1; i
++)
4059 if (!*p
|| *p
== ' ' || *p
== ',')
4061 memcpy(fontname
, this_opt
+ 5, i
);
4063 } else if (!strncmp(this_opt
, "noblink", 7)) {
4065 } else if (!strncmp(this_opt
, "noaccel", 7)) {
4067 } else if (!strncmp(this_opt
, "vram:", 5))
4068 default_vram
= simple_strtoul(this_opt
+5, NULL
, 0);
4069 else if (!strncmp(this_opt
, "pll:", 4))
4070 default_pll
= simple_strtoul(this_opt
+4, NULL
, 0);
4071 else if (!strncmp(this_opt
, "mclk:", 5))
4072 default_mclk
= simple_strtoul(this_opt
+5, NULL
, 0);
4073 #if defined(CONFIG_PPC)
4074 else if (!strncmp(this_opt
, "vmode:", 6)) {
4075 unsigned int vmode
= simple_strtoul(this_opt
+6, NULL
, 0);
4076 if (vmode
> 0 && vmode
<= VMODE_MAX
)
4077 default_vmode
= vmode
;
4078 } else if (!strncmp(this_opt
, "cmode:", 6)) {
4079 unsigned int cmode
= simple_strtoul(this_opt
+6, NULL
, 0);
4083 default_cmode
= CMODE_8
;
4087 default_cmode
= CMODE_16
;
4091 default_cmode
= CMODE_32
;
4098 * Why do we need this silly Mach64 argument?
4099 * We are already here because of mach64= so its redundant.
4101 else if (MACH_IS_ATARI
&& (!strncmp(this_opt
, "Mach64:", 7))) {
4102 static unsigned char m64_num
;
4103 static char mach64_str
[80];
4104 strncpy(mach64_str
, this_opt
+7, 80);
4105 if (!store_video_par(mach64_str
, m64_num
)) {
4107 mach64_count
= m64_num
;
4112 mode_option
= this_opt
;
4116 #endif /* !MODULE */
4119 static int __init
store_video_par(char *video_str
, unsigned char m64_num
)
4122 unsigned long vmembase
, size
, guiregbase
;
4124 printk("store_video_par() '%s' \n", video_str
);
4126 if (!(p
= strtoke(video_str
, ";")) || !*p
)
4127 goto mach64_invalid
;
4128 vmembase
= simple_strtoul(p
, NULL
, 0);
4129 if (!(p
= strtoke(NULL
, ";")) || !*p
)
4130 goto mach64_invalid
;
4131 size
= simple_strtoul(p
, NULL
, 0);
4132 if (!(p
= strtoke(NULL
, ";")) || !*p
)
4133 goto mach64_invalid
;
4134 guiregbase
= simple_strtoul(p
, NULL
, 0);
4136 phys_vmembase
[m64_num
] = vmembase
;
4137 phys_size
[m64_num
] = size
;
4138 phys_guiregbase
[m64_num
] = guiregbase
;
4139 printk(" stored them all: $%08lX $%08lX $%08lX \n", vmembase
, size
,
4144 phys_vmembase
[m64_num
] = 0;
4148 static char __init
*strtoke(char *s
, const char *ct
)
4150 static char *ssave
= NULL
;
4151 char *sbegin
, *send
;
4153 sbegin
= s
? s
: ssave
;
4156 if (*sbegin
== '\0') {
4160 send
= strpbrk(sbegin
, ct
);
4161 if (send
&& *send
!= '\0')
4166 #endif /* CONFIG_ATARI */
4168 static int atyfbcon_switch(int con
, struct fb_info
*fb
)
4170 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
4171 struct atyfb_par par
;
4173 /* Do we have to save the colormap? */
4174 if (fb_display
[currcon
].cmap
.len
)
4175 fb_get_cmap(&fb_display
[currcon
].cmap
, 1, atyfb_getcolreg
, fb
);
4177 /* Erase HW Cursor */
4179 atyfb_cursor(&fb_display
[currcon
], CM_ERASE
,
4180 info
->cursor
->pos
.x
, info
->cursor
->pos
.y
);
4184 atyfb_decode_var(&fb_display
[con
].var
, &par
, info
);
4185 atyfb_set_par(&par
, info
);
4186 atyfb_set_disp(&fb_display
[con
], info
, par
.crtc
.bpp
,
4187 par
.accel_flags
& FB_ACCELF_TEXT
);
4189 /* Install new colormap */
4190 do_install_cmap(con
, fb
);
4192 /* Install hw cursor */
4194 aty_set_cursor_color(info
, cursor_pixel_map
, cursor_color_map
,
4195 cursor_color_map
, cursor_color_map
);
4196 aty_set_cursor_shape(info
);
4202 * Blank the display.
4205 static void atyfbcon_blank(int blank
, struct fb_info
*fb
)
4207 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
4210 #if defined(CONFIG_PPC)
4211 if ((_machine
== _MACH_Pmac
) && blank
)
4212 pmu_enable_backlight(0);
4215 gen_cntl
= aty_ld_8(CRTC_GEN_CNTL
, info
);
4218 case VESA_NO_BLANKING
:
4221 case VESA_VSYNC_SUSPEND
:
4224 case VESA_HSYNC_SUSPEND
:
4227 case VESA_POWERDOWN
:
4232 gen_cntl
&= ~(0x4c);
4233 aty_st_8(CRTC_GEN_CNTL
, gen_cntl
, info
);
4235 #if defined(CONFIG_PPC)
4236 if ((_machine
== _MACH_Pmac
) && !blank
)
4237 pmu_enable_backlight(1);
4243 * Read a single color register and split it into
4244 * colors/transparent. Return != 0 for invalid regno.
4247 static int atyfb_getcolreg(u_int regno
, u_int
*red
, u_int
*green
, u_int
*blue
,
4248 u_int
*transp
, struct fb_info
*fb
)
4250 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
4254 *red
= (info
->palette
[regno
].red
<<8) | info
->palette
[regno
].red
;
4255 *green
= (info
->palette
[regno
].green
<<8) | info
->palette
[regno
].green
;
4256 *blue
= (info
->palette
[regno
].blue
<<8) | info
->palette
[regno
].blue
;
4263 * Set a single color register. The values supplied are already
4264 * rounded down to the hardware's capabilities (according to the
4265 * entries in the var structure). Return != 0 for invalid regno.
4268 static int atyfb_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
4269 u_int transp
, struct fb_info
*fb
)
4271 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
4279 info
->palette
[regno
].red
= red
;
4280 info
->palette
[regno
].green
= green
;
4281 info
->palette
[regno
].blue
= blue
;
4282 i
= aty_ld_8(DAC_CNTL
, info
) & 0xfc;
4283 if (Gx
== GT_CHIP_ID
|| Gx
== GU_CHIP_ID
|| Gx
== GV_CHIP_ID
||
4284 Gx
== GW_CHIP_ID
|| Gx
== GZ_CHIP_ID
|| Gx
== LG_CHIP_ID
||
4285 Gx
== GB_CHIP_ID
|| Gx
== GD_CHIP_ID
|| Gx
== GI_CHIP_ID
||
4286 Gx
== GP_CHIP_ID
|| Gx
== GQ_CHIP_ID
)
4287 i
|= 0x2; /*DAC_CNTL|0x2 turns off the extra brightness for gt*/
4288 aty_st_8(DAC_CNTL
, i
, info
);
4289 aty_st_8(DAC_MASK
, 0xff, info
);
4291 scale
= ((Gx
!= GX_CHIP_ID
) && (Gx
!= CX_CHIP_ID
) &&
4292 (info
->current_par
.crtc
.bpp
== 16)) ? 3 : 0;
4293 info
->aty_cmap_regs
->windex
= regno
<< scale
;
4295 info
->aty_cmap_regs
->lut
= red
;
4297 info
->aty_cmap_regs
->lut
= green
;
4299 info
->aty_cmap_regs
->lut
= blue
;
4302 switch (info
->current_par
.crtc
.bpp
) {
4303 #ifdef FBCON_HAS_CFB16
4305 info
->fbcon_cmap
.cfb16
[regno
] = (regno
<< 10) | (regno
<< 5) |
4309 #ifdef FBCON_HAS_CFB24
4311 info
->fbcon_cmap
.cfb24
[regno
] = (regno
<< 16) | (regno
<< 8) |
4315 #ifdef FBCON_HAS_CFB32
4317 i
= (regno
<< 8) | regno
;
4318 info
->fbcon_cmap
.cfb32
[regno
] = (i
<< 16) | i
;
4326 static void do_install_cmap(int con
, struct fb_info
*info
)
4330 if (fb_display
[con
].cmap
.len
)
4331 fb_set_cmap(&fb_display
[con
].cmap
, 1, atyfb_setcolreg
, info
);
4333 int size
= fb_display
[con
].var
.bits_per_pixel
== 16 ? 32 : 256;
4334 fb_set_cmap(fb_default_cmap(size
), 1, atyfb_setcolreg
, info
);
4340 * Accelerated functions
4343 static inline void draw_rect(s16 x
, s16 y
, u16 width
, u16 height
,
4344 struct fb_info_aty
*info
)
4346 /* perform rectangle fill */
4347 wait_for_fifo(2, info
);
4348 aty_st_le32(DST_Y_X
, (x
<< 16) | y
, info
);
4349 aty_st_le32(DST_HEIGHT_WIDTH
, (width
<< 16) | height
, info
);
4350 info
->blitter_may_be_busy
= 1;
4353 static inline void aty_rectcopy(int srcx
, int srcy
, int dstx
, int dsty
,
4354 u_int width
, u_int height
,
4355 struct fb_info_aty
*info
)
4357 u32 direction
= DST_LAST_PEL
;
4360 if (!width
|| !height
)
4363 pitch_value
= info
->current_par
.crtc
.vxres
;
4364 if (info
->current_par
.crtc
.bpp
== 24) {
4365 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
4366 /* horizontal coordinates and widths must be adjusted */
4377 direction
|= DST_Y_TOP_TO_BOTTOM
;
4383 direction
|= DST_X_LEFT_TO_RIGHT
;
4385 wait_for_fifo(4, info
);
4386 aty_st_le32(DP_SRC
, FRGD_SRC_BLIT
, info
);
4387 aty_st_le32(SRC_Y_X
, (srcx
<< 16) | srcy
, info
);
4388 aty_st_le32(SRC_HEIGHT1_WIDTH1
, (width
<< 16) | height
, info
);
4389 aty_st_le32(DST_CNTL
, direction
, info
);
4390 draw_rect(dstx
, dsty
, width
, height
, info
);
4393 static inline void aty_rectfill(int dstx
, int dsty
, u_int width
, u_int height
,
4394 u_int color
, struct fb_info_aty
*info
)
4396 if (!width
|| !height
)
4399 if (info
->current_par
.crtc
.bpp
== 24) {
4400 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
4401 /* horizontal coordinates and widths must be adjusted */
4406 wait_for_fifo(3, info
);
4407 aty_st_le32(DP_FRGD_CLR
, color
, info
);
4408 aty_st_le32(DP_SRC
, BKGD_SRC_BKGD_CLR
| FRGD_SRC_FRGD_CLR
| MONO_SRC_ONE
,
4410 aty_st_le32(DST_CNTL
, DST_LAST_PEL
| DST_Y_TOP_TO_BOTTOM
|
4411 DST_X_LEFT_TO_RIGHT
, info
);
4412 draw_rect(dstx
, dsty
, width
, height
, info
);
4416 * Update the `var' structure (called by fbcon.c)
4419 static int atyfbcon_updatevar(int con
, struct fb_info
*fb
)
4421 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
4422 struct atyfb_par
*par
= &info
->current_par
;
4423 struct display
*p
= &fb_display
[con
];
4424 struct vc_data
*conp
= p
->conp
;
4425 u32 yres
, yoffset
, sy
, height
;
4427 yres
= ((par
->crtc
.v_tot_disp
>> 16) & 0x7ff) + 1;
4428 yoffset
= fb_display
[con
].var
.yoffset
;
4430 sy
= (conp
->vc_rows
+ p
->yscroll
) * fontheight(p
);
4431 height
= yres
- conp
->vc_rows
* fontheight(p
);
4433 if (height
&& (yoffset
+ yres
> sy
)) {
4437 xres
= (((par
->crtc
.h_tot_disp
>> 16) & 0xff) + 1) * 8;
4438 xoffset
= fb_display
[con
].var
.xoffset
;
4441 bgx
= attr_bgcol_ec(p
, conp
);
4445 if (sy
+ height
> par
->crtc
.vyres
) {
4446 wait_for_fifo(1, info
);
4447 aty_st_le32(SC_BOTTOM
, sy
+ height
- 1, info
);
4449 aty_rectfill(xoffset
, sy
, xres
, height
, bgx
, info
);
4452 if (info
->cursor
&& (yoffset
+ yres
<= sy
))
4453 atyfb_cursor(p
, CM_ERASE
, info
->cursor
->pos
.x
, info
->cursor
->pos
.y
);
4455 info
->current_par
.crtc
.yoffset
= yoffset
;
4456 set_off_pitch(&info
->current_par
, info
);
4461 * Text console acceleration
4464 static void fbcon_aty_bmove(struct display
*p
, int sy
, int sx
, int dy
, int dx
,
4465 int height
, int width
)
4468 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4470 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4471 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4476 sy
*= fontheight(p
);
4478 dy
*= fontheight(p
);
4479 width
*= fontwidth(p
);
4480 height
*= fontheight(p
);
4482 aty_rectcopy(sx
, sy
, dx
, dy
, width
, height
,
4483 (struct fb_info_aty
*)p
->fb_info
);
4486 static void fbcon_aty_clear(struct vc_data
*conp
, struct display
*p
, int sy
,
4487 int sx
, int height
, int width
)
4491 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4493 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4494 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4498 bgx
= attr_bgcol_ec(p
, conp
);
4503 sy
*= fontheight(p
);
4504 width
*= fontwidth(p
);
4505 height
*= fontheight(p
);
4507 aty_rectfill(sx
, sy
, width
, height
, bgx
,
4508 (struct fb_info_aty
*)p
->fb_info
);
4511 #ifdef FBCON_HAS_CFB8
4512 static void fbcon_aty8_putc(struct vc_data
*conp
, struct display
*p
, int c
,
4515 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4518 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4519 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4523 if (fb
->blitter_may_be_busy
)
4524 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4525 fbcon_cfb8_putc(conp
, p
, c
, yy
, xx
);
4528 static void fbcon_aty8_putcs(struct vc_data
*conp
, struct display
*p
,
4529 const unsigned short *s
, int count
, int yy
,
4532 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4535 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4536 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4540 if (fb
->blitter_may_be_busy
)
4541 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4542 fbcon_cfb8_putcs(conp
, p
, s
, count
, yy
, xx
);
4545 static void fbcon_aty8_clear_margins(struct vc_data
*conp
, struct display
*p
,
4548 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4551 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4552 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4556 if (fb
->blitter_may_be_busy
)
4557 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4558 fbcon_cfb8_clear_margins(conp
, p
, bottom_only
);
4561 static struct display_switch fbcon_aty8
= {
4562 fbcon_cfb8_setup
, fbcon_aty_bmove
, fbcon_aty_clear
, fbcon_aty8_putc
,
4563 fbcon_aty8_putcs
, fbcon_cfb8_revc
, NULL
, NULL
, fbcon_aty8_clear_margins
,
4564 FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4568 #ifdef FBCON_HAS_CFB16
4569 static void fbcon_aty16_putc(struct vc_data
*conp
, struct display
*p
, int c
,
4572 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4575 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4576 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4580 if (fb
->blitter_may_be_busy
)
4581 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4582 fbcon_cfb16_putc(conp
, p
, c
, yy
, xx
);
4585 static void fbcon_aty16_putcs(struct vc_data
*conp
, struct display
*p
,
4586 const unsigned short *s
, int count
, int yy
,
4589 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4592 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4593 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4597 if (fb
->blitter_may_be_busy
)
4598 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4599 fbcon_cfb16_putcs(conp
, p
, s
, count
, yy
, xx
);
4602 static void fbcon_aty16_clear_margins(struct vc_data
*conp
, struct display
*p
,
4605 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4608 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4609 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4613 if (fb
->blitter_may_be_busy
)
4614 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4615 fbcon_cfb16_clear_margins(conp
, p
, bottom_only
);
4618 static struct display_switch fbcon_aty16
= {
4619 fbcon_cfb16_setup
, fbcon_aty_bmove
, fbcon_aty_clear
, fbcon_aty16_putc
,
4620 fbcon_aty16_putcs
, fbcon_cfb16_revc
, NULL
, NULL
, fbcon_aty16_clear_margins
,
4621 FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4625 #ifdef FBCON_HAS_CFB24
4626 static void fbcon_aty24_putc(struct vc_data
*conp
, struct display
*p
, int c
,
4629 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4632 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4633 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4637 if (fb
->blitter_may_be_busy
)
4638 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4639 fbcon_cfb24_putc(conp
, p
, c
, yy
, xx
);
4642 static void fbcon_aty24_putcs(struct vc_data
*conp
, struct display
*p
,
4643 const unsigned short *s
, int count
, int yy
,
4646 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4649 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4650 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4654 if (fb
->blitter_may_be_busy
)
4655 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4656 fbcon_cfb24_putcs(conp
, p
, s
, count
, yy
, xx
);
4659 static void fbcon_aty24_clear_margins(struct vc_data
*conp
, struct display
*p
,
4662 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4665 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4666 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4670 if (fb
->blitter_may_be_busy
)
4671 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4672 fbcon_cfb24_clear_margins(conp
, p
, bottom_only
);
4675 static struct display_switch fbcon_aty24
= {
4676 fbcon_cfb24_setup
, fbcon_aty_bmove
, fbcon_aty_clear
, fbcon_aty24_putc
,
4677 fbcon_aty24_putcs
, fbcon_cfb24_revc
, NULL
, NULL
, fbcon_aty24_clear_margins
,
4678 FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4682 #ifdef FBCON_HAS_CFB32
4683 static void fbcon_aty32_putc(struct vc_data
*conp
, struct display
*p
, int c
,
4686 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4689 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4690 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4694 if (fb
->blitter_may_be_busy
)
4695 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4696 fbcon_cfb32_putc(conp
, p
, c
, yy
, xx
);
4699 static void fbcon_aty32_putcs(struct vc_data
*conp
, struct display
*p
,
4700 const unsigned short *s
, int count
, int yy
,
4703 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4706 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4707 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4711 if (fb
->blitter_may_be_busy
)
4712 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4713 fbcon_cfb32_putcs(conp
, p
, s
, count
, yy
, xx
);
4716 static void fbcon_aty32_clear_margins(struct vc_data
*conp
, struct display
*p
,
4719 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4722 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4723 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4727 if (fb
->blitter_may_be_busy
)
4728 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4729 fbcon_cfb32_clear_margins(conp
, p
, bottom_only
);
4732 static struct display_switch fbcon_aty32
= {
4733 fbcon_cfb32_setup
, fbcon_aty_bmove
, fbcon_aty_clear
, fbcon_aty32_putc
,
4734 fbcon_aty32_putcs
, fbcon_cfb32_revc
, NULL
, NULL
, fbcon_aty32_clear_margins
,
4735 FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4740 int __init
init_module(void)
4743 return fb_list
? 0 : -ENXIO
;
4746 void cleanup_module(void)
4749 struct fb_info_aty
*info
= fb_list
;
4750 fb_list
= info
->next
;
4752 unregister_framebuffer(&info
->fb_info
);
4755 if (info
->ati_regbase
)
4756 iounmap((void *)info
->ati_regbase
);
4757 if (info
->frame_buffer
)
4758 iounmap((void *)info
->frame_buffer
);
4760 if (info
->cursor
&& info
->cursor
->ram
)
4761 iounmap(info
->cursor
->ram
);
4766 if (info
->cursor
->timer
)
4767 kfree(info
->cursor
->timer
);
4768 kfree(info
->cursor
);
4772 kfree(info
->mmap_map
);