1 /* $Id: atyfb.c,v 1.126 1999/09/16 18:46:23 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>
56 #include <linux/vt_kern.h>
58 #ifdef CONFIG_FB_COMPAT_XPMAC
59 #include <asm/vc_ioctl.h>
65 #include <linux/adb.h>
66 #include <linux/pmu.h>
68 #include <asm/pci-bridge.h>
69 #include <video/macmodes.h>
72 #include <linux/nvram.h>
78 #include <asm/uaccess.h>
80 #include <video/fbcon.h>
81 #include <video/fbcon-cfb8.h>
82 #include <video/fbcon-cfb16.h>
83 #include <video/fbcon-cfb24.h>
84 #include <video/fbcon-cfb32.h>
94 /* Definitions for the ICS 2595 == ATI 18818_1 Clockchip */
96 #define REF_FREQ_2595 1432 /* 14.33 MHz (exact 14.31818) */
97 #define REF_DIV_2595 46 /* really 43 on ICS 2595 !!! */
99 #define MAX_FREQ_2595 15938 /* 159.38 MHz (really 170.486) */
100 #define MIN_FREQ_2595 8000 /* 80.00 MHz ( 85.565) */
101 /* mit Prescaler 2, 4, 8 */
102 #define ABS_MIN_FREQ_2595 1000 /* 10.00 MHz (really 10.697) */
103 #define N_ADJ_2595 257
105 #define STOP_BITS_2595 0x1800
118 /* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */
119 /* - must be large enough to catch all GUI-Regs */
120 /* - must be aligned to a PAGE boundary */
121 #define GUI_RESERVE (1 * PAGE_SIZE)
125 #define eieio() /* Enforce In-order Execution of I/O */
128 /* FIXME: remove the FAIL definition */
129 #define FAIL(x) do { printk(x "\n"); return -EINVAL; } while (0)
133 * Elements of the Hardware specific atyfb_par structure
148 u32 dp_pix_width
; /* acceleration */
149 u32 dp_chain_mask
; /* acceleration */
173 u32 dsp_config
; /* Mach64 GTB DSP */
174 u32 dsp_on_off
; /* Mach64 GTB DSP */
175 u8 mclk_post_div_real
;
176 u8 vclk_post_div_real
;
181 * The Hardware parameters for each card
189 struct pll_18818 ics2595
;
194 struct aty_cmap_regs
{
202 struct pci_mmap_map
{
206 unsigned long prot_flag
;
207 unsigned long prot_mask
;
210 #define DEFAULT_CURSOR_BLINK_RATE (20)
211 #define CURSOR_DRAW_DELAY (2)
226 struct timer_list
*timer
;
230 struct fb_info fb_info
;
231 struct fb_info_aty
*next
;
232 unsigned long ati_regbase_phys
;
233 unsigned long ati_regbase
;
234 unsigned long frame_buffer_phys
;
235 unsigned long frame_buffer
;
236 unsigned long clk_wr_offset
;
237 struct pci_mmap_map
*mmap_map
;
238 struct aty_cursor
*cursor
;
239 struct aty_cmap_regs
*aty_cmap_regs
;
240 struct { u8 red
, green
, blue
, pad
; } palette
[256];
241 struct atyfb_par default_par
;
242 struct atyfb_par current_par
;
248 #define Gx info->chip_type
250 #define Rev info->chip_rev
258 struct display_switch dispsw
;
260 #ifdef FBCON_HAS_CFB16
263 #ifdef FBCON_HAS_CFB24
266 #ifdef FBCON_HAS_CFB32
270 u8 blitter_may_be_busy
;
277 #ifdef CONFIG_PMAC_PBOOK
278 unsigned char *save_framebuffer
;
279 unsigned long save_pll
[64];
283 #ifdef CONFIG_PMAC_PBOOK
284 int aty_sleep_notify(struct pmu_sleep_notifier
*self
, int when
);
285 static struct pmu_sleep_notifier aty_sleep_notifier
= {
286 aty_sleep_notify
, SLEEP_LEVEL_VIDEO
,
288 static struct fb_info_aty
* first_display
= NULL
;
293 * Frame buffer device API
296 static int atyfb_open(struct fb_info
*info
, int user
);
297 static int atyfb_release(struct fb_info
*info
, int user
);
298 static int atyfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
300 static int atyfb_get_var(struct fb_var_screeninfo
*var
, int con
,
302 static int atyfb_set_var(struct fb_var_screeninfo
*var
, int con
,
304 static int atyfb_pan_display(struct fb_var_screeninfo
*var
, int con
,
306 static int atyfb_get_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
307 struct fb_info
*info
);
308 static int atyfb_set_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
309 struct fb_info
*info
);
310 static int atyfb_ioctl(struct inode
*inode
, struct file
*file
, u_int cmd
,
311 u_long arg
, int con
, struct fb_info
*info
);
313 static int atyfb_mmap(struct fb_info
*info
, struct file
*file
,
314 struct vm_area_struct
*vma
);
316 static int atyfb_rasterimg(struct fb_info
*info
, int start
);
320 * Interface to the low level console driver
323 static int atyfbcon_switch(int con
, struct fb_info
*fb
);
324 static int atyfbcon_updatevar(int con
, struct fb_info
*fb
);
325 static void atyfbcon_blank(int blank
, struct fb_info
*fb
);
329 * Text console acceleration
332 static void fbcon_aty_bmove(struct display
*p
, int sy
, int sx
, int dy
, int dx
,
333 int height
, int width
);
334 static void fbcon_aty_clear(struct vc_data
*conp
, struct display
*p
, int sy
,
335 int sx
, int height
, int width
);
336 #ifdef FBCON_HAS_CFB8
337 static struct display_switch fbcon_aty8
;
338 static void fbcon_aty8_putc(struct vc_data
*conp
, struct display
*p
, int c
,
340 static void fbcon_aty8_putcs(struct vc_data
*conp
, struct display
*p
,
341 const unsigned short *s
, int count
, int yy
,
344 #ifdef FBCON_HAS_CFB16
345 static struct display_switch fbcon_aty16
;
346 static void fbcon_aty16_putc(struct vc_data
*conp
, struct display
*p
, int c
,
348 static void fbcon_aty16_putcs(struct vc_data
*conp
, struct display
*p
,
349 const unsigned short *s
, int count
, int yy
,
352 #ifdef FBCON_HAS_CFB24
353 static struct display_switch fbcon_aty24
;
354 static void fbcon_aty24_putc(struct vc_data
*conp
, struct display
*p
, int c
,
356 static void fbcon_aty24_putcs(struct vc_data
*conp
, struct display
*p
,
357 const unsigned short *s
, int count
, int yy
,
360 #ifdef FBCON_HAS_CFB32
361 static struct display_switch fbcon_aty32
;
362 static void fbcon_aty32_putc(struct vc_data
*conp
, struct display
*p
, int c
,
364 static void fbcon_aty32_putcs(struct vc_data
*conp
, struct display
*p
,
365 const unsigned short *s
, int count
, int yy
,
374 static int aty_init(struct fb_info_aty
*info
, const char *name
);
375 static struct aty_cursor
*aty_init_cursor(struct fb_info_aty
*fb
);
377 static int store_video_par(char *videopar
, unsigned char m64_num
);
378 static char *strtoke(char *s
, const char *ct
);
381 static void reset_engine(const struct fb_info_aty
*info
);
382 static void init_engine(const struct atyfb_par
*par
, struct fb_info_aty
*info
);
384 static void aty_st_514(int offset
, u8 val
, const struct fb_info_aty
*info
);
385 static void aty_st_pll(int offset
, u8 val
, const struct fb_info_aty
*info
);
386 static u8
aty_ld_pll(int offset
, const struct fb_info_aty
*info
);
387 static void aty_set_crtc(const struct fb_info_aty
*info
,
388 const struct crtc
*crtc
);
389 static int aty_var_to_crtc(const struct fb_info_aty
*info
,
390 const struct fb_var_screeninfo
*var
,
392 static void aty_set_dac_514(const struct fb_info_aty
*info
, u32 bpp
);
393 static int aty_crtc_to_var(const struct crtc
*crtc
,
394 struct fb_var_screeninfo
*var
);
395 static void aty_set_pll_gx(const struct fb_info_aty
*info
,
396 const struct pll_gx
*pll
);
398 static int aty_set_dac_ATI68860_B(const struct fb_info_aty
*info
, u32 bpp
,
400 static int aty_set_dac_ATT21C498(const struct fb_info_aty
*info
,
401 const struct pll_18818
*pll
, u32 bpp
);
402 void aty_dac_waste4(const struct fb_info_aty
*info
);
404 static int aty_var_to_pll_18818(u32 period_in_ps
, struct pll_18818
*pll
);
405 static u32
aty_pll_18818_to_var(const struct pll_18818
*pll
);
406 static void aty_set_pll18818(const struct fb_info_aty
*info
,
407 const struct pll_18818
*pll
);
409 static void aty_StrobeClock(const struct fb_info_aty
*info
);
411 static void aty_ICS2595_put1bit(u8 data
, const struct fb_info_aty
*info
);
413 static int aty_var_to_pll_408(u32 period_in_ps
, struct pll_18818
*pll
);
414 static u32
aty_pll_408_to_var(const struct pll_18818
*pll
);
415 static void aty_set_pll_408(const struct fb_info_aty
*info
,
416 const struct pll_18818
*pll
);
418 static int aty_var_to_pll_1703(u32 period_in_ps
, struct pll_18818
*pll
);
419 static u32
aty_pll_1703_to_var(const struct pll_18818
*pll
);
420 static void aty_set_pll_1703(const struct fb_info_aty
*info
,
421 const struct pll_18818
*pll
);
423 static int aty_var_to_pll_8398(u32 period_in_ps
, struct pll_18818
*pll
);
424 static u32
aty_pll_8398_to_var(const struct pll_18818
*pll
);
425 static void aty_set_pll_8398(const struct fb_info_aty
*info
,
426 const struct pll_18818
*pll
);
428 static int aty_var_to_pll_514(u32 vclk_per
, struct pll_gx
*pll
);
429 static u32
aty_pll_gx_to_var(const struct pll_gx
*pll
,
430 const struct fb_info_aty
*info
);
431 static void aty_set_pll_ct(const struct fb_info_aty
*info
,
432 const struct pll_ct
*pll
);
433 static int aty_valid_pll_ct(const struct fb_info_aty
*info
, u32 vclk_per
,
435 static int aty_dsp_gt(const struct fb_info_aty
*info
, u8 bpp
,
437 static void aty_calc_pll_ct(const struct fb_info_aty
*info
,
439 static int aty_var_to_pll_ct(const struct fb_info_aty
*info
, u32 vclk_per
,
440 u8 bpp
, struct pll_ct
*pll
);
441 static u32
aty_pll_ct_to_var(const struct pll_ct
*pll
,
442 const struct fb_info_aty
*info
);
443 static void atyfb_set_par(const struct atyfb_par
*par
,
444 struct fb_info_aty
*info
);
445 static int atyfb_decode_var(const struct fb_var_screeninfo
*var
,
446 struct atyfb_par
*par
,
447 const struct fb_info_aty
*info
);
448 static int atyfb_encode_var(struct fb_var_screeninfo
*var
,
449 const struct atyfb_par
*par
,
450 const struct fb_info_aty
*info
);
451 static void set_off_pitch(struct atyfb_par
*par
,
452 const struct fb_info_aty
*info
);
453 static int encode_fix(struct fb_fix_screeninfo
*fix
,
454 const struct atyfb_par
*par
,
455 const struct fb_info_aty
*info
);
456 static void atyfb_set_disp(struct display
*disp
, struct fb_info_aty
*info
,
458 static int atyfb_getcolreg(u_int regno
, u_int
*red
, u_int
*green
, u_int
*blue
,
459 u_int
*transp
, struct fb_info
*fb
);
460 static int atyfb_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
461 u_int transp
, struct fb_info
*fb
);
462 static void do_install_cmap(int con
, struct fb_info
*info
);
464 static int read_aty_sense(const struct fb_info_aty
*info
);
469 * Interface used by the world
472 int atyfb_init(void);
474 void atyfb_of_init(struct device_node
*dp
);
477 int atyfb_setup(char*);
480 static int currcon
= 0;
482 static struct fb_ops atyfb_ops
= {
483 atyfb_open
, atyfb_release
, atyfb_get_fix
, atyfb_get_var
, atyfb_set_var
,
484 atyfb_get_cmap
, atyfb_set_cmap
, atyfb_pan_display
, atyfb_ioctl
,
493 static char atyfb_name
[16] = "ATY Mach64";
494 static char fontname
[40] __initdata
= { 0 };
495 static char curblink __initdata
= 1;
496 static char noaccel __initdata
= 0;
497 static u32 default_vram __initdata
= 0;
498 static int default_pll __initdata
= 0;
499 static int default_mclk __initdata
= 0;
502 static const char *mode_option __initdata
= NULL
;
507 static int default_vmode __initdata
= VMODE_NVRAM
;
508 static int default_cmode __initdata
= CMODE_NVRAM
;
510 static int default_vmode __initdata
= VMODE_CHOOSE
;
511 static int default_cmode __initdata
= CMODE_CHOOSE
;
516 static unsigned int mach64_count __initdata
= 0;
517 static unsigned long phys_vmembase
[FB_MAX
] __initdata
= { 0, };
518 static unsigned long phys_size
[FB_MAX
] __initdata
= { 0, };
519 static unsigned long phys_guiregbase
[FB_MAX
] __initdata
= { 0, };
523 static struct aty_features
{
527 } aty_features
[] __initdata
= {
528 /* mach64GX family */
529 { 0x4758, 0x00d7, "mach64GX (ATI888GX00)" },
530 { 0x4358, 0x0057, "mach64CX (ATI888CX00)" },
532 /* mach64CT family */
533 { 0x4354, 0x4354, "mach64CT (ATI264CT)" },
534 { 0x4554, 0x4554, "mach64ET (ATI264ET)" },
536 /* mach64CT family / mach64VT class */
537 { 0x5654, 0x5654, "mach64VT (ATI264VT)" },
538 { 0x5655, 0x5655, "mach64VTB (ATI264VTB)" },
539 { 0x5656, 0x5656, "mach64VT4 (ATI264VT4)" },
541 /* mach64CT family / mach64GT (3D RAGE) class */
542 { 0x4c42, 0x4c42, "3D RAGE LT PRO (AGP)" },
543 { 0x4c44, 0x4c44, "3D RAGE LT PRO" },
544 { 0x4c47, 0x4c47, "3D RAGE LT PRO" },
545 { 0x4c49, 0x4c49, "3D RAGE LT PRO" },
546 { 0x4c50, 0x4c50, "3D RAGE LT PRO" },
547 { 0x4c54, 0x4c54, "3D RAGE LT" },
548 { 0x4754, 0x4754, "3D RAGE (GT)" },
549 { 0x4755, 0x4755, "3D RAGE II+ (GTB)" },
550 { 0x4756, 0x4756, "3D RAGE IIC (PCI)" },
551 { 0x4757, 0x4757, "3D RAGE IIC (AGP)" },
552 { 0x475a, 0x475a, "3D RAGE IIC (AGP)" },
553 { 0x4742, 0x4742, "3D RAGE PRO (BGA, AGP)" },
554 { 0x4744, 0x4744, "3D RAGE PRO (BGA, AGP, 1x only)" },
555 { 0x4749, 0x4749, "3D RAGE PRO (BGA, PCI)" },
556 { 0x4750, 0x4750, "3D RAGE PRO (PQFP, PCI)" },
557 { 0x4751, 0x4751, "3D RAGE PRO (PQFP, PCI, limited 3D)" },
560 static const char *aty_gx_ram
[8] __initdata
= {
561 "DRAM", "VRAM", "VRAM", "DRAM", "DRAM", "VRAM", "VRAM", "RESV"
564 static const char *aty_ct_ram
[8] __initdata
= {
565 "OFF", "DRAM", "EDO", "EDO", "SDRAM", "SGRAM", "WRAM", "RESV"
569 static inline u32
aty_ld_le32(unsigned int regindex
,
570 const struct fb_info_aty
*info
)
572 #if defined(__powerpc__)
576 temp
= info
->ati_regbase
;
577 asm volatile("lwbrx %0,%1,%2" : "=r"(val
) : "b" (regindex
), "r" (temp
));
579 #elif defined(__mc68000__)
580 return le32_to_cpu(*((volatile u32
*)(info
->ati_regbase
+regindex
)));
582 return readl (info
->ati_regbase
+ regindex
);
586 static inline void aty_st_le32(unsigned int regindex
, u32 val
,
587 const struct fb_info_aty
*info
)
589 #if defined(__powerpc__)
592 temp
= info
->ati_regbase
;
593 asm volatile("stwbrx %0,%1,%2" : : "r" (val
), "b" (regindex
), "r" (temp
) :
595 #elif defined(__mc68000__)
596 *((volatile u32
*)(info
->ati_regbase
+regindex
)) = cpu_to_le32(val
);
598 writel (val
, info
->ati_regbase
+ regindex
);
602 static inline u8
aty_ld_8(unsigned int regindex
,
603 const struct fb_info_aty
*info
)
605 return readb (info
->ati_regbase
+ regindex
);
608 static inline void aty_st_8(unsigned int regindex
, u8 val
,
609 const struct fb_info_aty
*info
)
611 writeb (val
, info
->ati_regbase
+ regindex
);
616 * Generic Mach64 routines
620 * All writes to draw engine registers are automatically routed through a
621 * 32-bit-wide, 16-entry-deep command FIFO ...
622 * Register writes to registers with DWORD offsets less than 40h are not
624 * (from Chapter 5 of the Mach64 Programmer's Guide)
627 static inline void wait_for_fifo(u16 entries
, const struct fb_info_aty
*info
)
629 while ((aty_ld_le32(FIFO_STAT
, info
) & 0xffff) >
630 ((u32
)(0x8000 >> entries
)));
633 static inline void wait_for_idle(struct fb_info_aty
*info
)
635 wait_for_fifo(16, info
);
636 while ((aty_ld_le32(GUI_STAT
, info
) & 1)!= 0);
637 info
->blitter_may_be_busy
= 0;
640 static void reset_engine(const struct fb_info_aty
*info
)
643 aty_st_le32(GEN_TEST_CNTL
,
644 aty_ld_le32(GEN_TEST_CNTL
, info
) & ~GUI_ENGINE_ENABLE
, info
);
646 aty_st_le32(GEN_TEST_CNTL
,
647 aty_ld_le32(GEN_TEST_CNTL
, info
) | GUI_ENGINE_ENABLE
, info
);
648 /* ensure engine is not locked up by clearing any FIFO or */
650 aty_st_le32(BUS_CNTL
, aty_ld_le32(BUS_CNTL
, info
) | BUS_HOST_ERR_ACK
|
651 BUS_FIFO_ERR_ACK
, info
);
654 static void init_engine(const struct atyfb_par
*par
, struct fb_info_aty
*info
)
658 /* determine modal information from global mode structure */
659 pitch_value
= par
->crtc
.vxres
;
661 if (par
->crtc
.bpp
== 24) {
662 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
663 /* horizontal coordinates and widths must be adjusted */
664 pitch_value
= pitch_value
* 3;
667 /* Reset engine, enable, and clear any engine errors */
669 /* Ensure that vga page pointers are set to zero - the upper */
670 /* page pointers are set to 1 to handle overflows in the */
672 aty_st_le32(MEM_VGA_WP_SEL
, 0x00010000, info
);
673 aty_st_le32(MEM_VGA_RP_SEL
, 0x00010000, info
);
675 /* ---- Setup standard engine context ---- */
677 /* All GUI registers here are FIFOed - therefore, wait for */
678 /* the appropriate number of empty FIFO entries */
679 wait_for_fifo(14, info
);
681 /* enable all registers to be loaded for context loads */
682 aty_st_le32(CONTEXT_MASK
, 0xFFFFFFFF, info
);
684 /* set destination pitch to modal pitch, set offset to zero */
685 aty_st_le32(DST_OFF_PITCH
, (pitch_value
/ 8) << 22, info
);
687 /* zero these registers (set them to a known state) */
688 aty_st_le32(DST_Y_X
, 0, info
);
689 aty_st_le32(DST_HEIGHT
, 0, info
);
690 aty_st_le32(DST_BRES_ERR
, 0, info
);
691 aty_st_le32(DST_BRES_INC
, 0, info
);
692 aty_st_le32(DST_BRES_DEC
, 0, info
);
694 /* set destination drawing attributes */
695 aty_st_le32(DST_CNTL
, DST_LAST_PEL
| DST_Y_TOP_TO_BOTTOM
|
696 DST_X_LEFT_TO_RIGHT
, info
);
698 /* set source pitch to modal pitch, set offset to zero */
699 aty_st_le32(SRC_OFF_PITCH
, (pitch_value
/ 8) << 22, info
);
701 /* set these registers to a known state */
702 aty_st_le32(SRC_Y_X
, 0, info
);
703 aty_st_le32(SRC_HEIGHT1_WIDTH1
, 1, info
);
704 aty_st_le32(SRC_Y_X_START
, 0, info
);
705 aty_st_le32(SRC_HEIGHT2_WIDTH2
, 1, info
);
707 /* set source pixel retrieving attributes */
708 aty_st_le32(SRC_CNTL
, SRC_LINE_X_LEFT_TO_RIGHT
, info
);
710 /* set host attributes */
711 wait_for_fifo(13, info
);
712 aty_st_le32(HOST_CNTL
, 0, info
);
714 /* set pattern attributes */
715 aty_st_le32(PAT_REG0
, 0, info
);
716 aty_st_le32(PAT_REG1
, 0, info
);
717 aty_st_le32(PAT_CNTL
, 0, info
);
719 /* set scissors to modal size */
720 aty_st_le32(SC_LEFT
, 0, info
);
721 aty_st_le32(SC_TOP
, 0, info
);
722 aty_st_le32(SC_BOTTOM
, par
->crtc
.vyres
-1, info
);
723 aty_st_le32(SC_RIGHT
, pitch_value
-1, info
);
725 /* set background color to minimum value (usually BLACK) */
726 aty_st_le32(DP_BKGD_CLR
, 0, info
);
728 /* set foreground color to maximum value (usually WHITE) */
729 aty_st_le32(DP_FRGD_CLR
, 0xFFFFFFFF, info
);
731 /* set write mask to effect all pixel bits */
732 aty_st_le32(DP_WRITE_MASK
, 0xFFFFFFFF, info
);
734 /* set foreground mix to overpaint and background mix to */
736 aty_st_le32(DP_MIX
, FRGD_MIX_S
| BKGD_MIX_D
, info
);
738 /* set primary source pixel channel to foreground color */
740 aty_st_le32(DP_SRC
, FRGD_SRC_FRGD_CLR
, info
);
742 /* set compare functionality to false (no-effect on */
744 wait_for_fifo(3, info
);
745 aty_st_le32(CLR_CMP_CLR
, 0, info
);
746 aty_st_le32(CLR_CMP_MASK
, 0xFFFFFFFF, info
);
747 aty_st_le32(CLR_CMP_CNTL
, 0, info
);
749 /* set pixel depth */
750 wait_for_fifo(2, info
);
751 aty_st_le32(DP_PIX_WIDTH
, par
->crtc
.dp_pix_width
, info
);
752 aty_st_le32(DP_CHAIN_MASK
, par
->crtc
.dp_chain_mask
, info
);
754 wait_for_fifo(5, info
);
755 aty_st_le32(SCALE_3D_CNTL
, 0, info
);
756 aty_st_le32(Z_CNTL
, 0, info
);
757 aty_st_le32(CRTC_INT_CNTL
, aty_ld_le32(CRTC_INT_CNTL
, info
) & ~0x20, info
);
758 aty_st_le32(GUI_TRAJ_CNTL
, 0x100023, info
);
760 /* insure engine is idle before leaving */
764 static void aty_st_514(int offset
, u8 val
, const struct fb_info_aty
*info
)
766 aty_st_8(DAC_CNTL
, 1, info
);
767 /* right addr byte */
768 aty_st_8(DAC_W_INDEX
, offset
& 0xff, info
);
770 aty_st_8(DAC_DATA
, (offset
>> 8) & 0xff, info
);
772 aty_st_8(DAC_MASK
, val
, info
);
774 aty_st_8(DAC_CNTL
, 0, info
);
777 static void aty_st_pll(int offset
, u8 val
, const struct fb_info_aty
*info
)
779 /* write addr byte */
780 aty_st_8(CLOCK_CNTL
+ 1, (offset
<< 2) | PLL_WR_EN
, info
);
782 /* write the register value */
783 aty_st_8(CLOCK_CNTL
+ 2, val
, info
);
785 aty_st_8(CLOCK_CNTL
+ 1, (offset
<< 2) & ~PLL_WR_EN
, info
);
788 static u8
aty_ld_pll(int offset
, const struct fb_info_aty
*info
)
792 /* write addr byte */
793 aty_st_8(CLOCK_CNTL
+ 1, (offset
<< 2), info
);
795 /* read the register value */
796 res
= aty_ld_8(CLOCK_CNTL
+ 2, info
);
804 * Apple monitor sense
807 static int read_aty_sense(const struct fb_info_aty
*info
)
811 aty_st_le32(GP_IO
, 0x31003100, info
); /* drive outputs high */
813 aty_st_le32(GP_IO
, 0, info
); /* turn off outputs */
815 i
= aty_ld_le32(GP_IO
, info
); /* get primary sense value */
816 sense
= ((i
& 0x3000) >> 3) | (i
& 0x100);
818 /* drive each sense line low in turn and collect the other 2 */
819 aty_st_le32(GP_IO
, 0x20000000, info
); /* drive A low */
821 i
= aty_ld_le32(GP_IO
, info
);
822 sense
|= ((i
& 0x1000) >> 7) | ((i
& 0x100) >> 4);
823 aty_st_le32(GP_IO
, 0x20002000, info
); /* drive A high again */
826 aty_st_le32(GP_IO
, 0x10000000, info
); /* drive B low */
828 i
= aty_ld_le32(GP_IO
, info
);
829 sense
|= ((i
& 0x2000) >> 10) | ((i
& 0x100) >> 6);
830 aty_st_le32(GP_IO
, 0x10001000, info
); /* drive B high again */
833 aty_st_le32(GP_IO
, 0x01000000, info
); /* drive C low */
835 sense
|= (aty_ld_le32(GP_IO
, info
) & 0x3000) >> 12;
836 aty_st_le32(GP_IO
, 0, info
); /* turn off outputs */
841 #endif /* CONFIG_PMAC */
843 /* ------------------------------------------------------------------------- */
846 * Hardware Cursor support.
849 static u8 cursor_pixel_map
[2] = { 0, 15 };
850 static u8 cursor_color_map
[2] = { 0, 0xff };
852 static u8 cursor_bits_lookup
[16] =
854 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
855 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
858 static u8 cursor_mask_lookup
[16] =
860 0xaa, 0x2a, 0x8a, 0x0a, 0xa2, 0x22, 0x82, 0x02,
861 0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00
865 aty_set_cursor_color(struct fb_info_aty
*fb
, u8
*pixel
,
866 u8
*red
, u8
*green
, u8
*blue
)
868 struct aty_cursor
*c
= fb
->cursor
;
875 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
876 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
880 for (i
= 0; i
< 2; i
++) {
881 c
->color
[i
] = (u32
)red
[i
] << 24;
882 c
->color
[i
] |= (u32
)green
[i
] << 16;
883 c
->color
[i
] |= (u32
)blue
[i
] << 8;
884 c
->color
[i
] |= (u32
)pixel
[i
];
887 wait_for_fifo(2, fb
);
888 aty_st_le32(CUR_CLR0
, c
->color
[0], fb
);
889 aty_st_le32(CUR_CLR1
, c
->color
[1], fb
);
893 aty_set_cursor_shape(struct fb_info_aty
*fb
)
895 struct aty_cursor
*c
= fb
->cursor
;
903 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
904 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
909 for (y
= 0; y
< c
->size
.y
; y
++) {
910 for (x
= 0; x
< c
->size
.x
>> 2; x
++) {
913 fb_writeb (cursor_mask_lookup
[m
>> 4] |
914 cursor_bits_lookup
[(b
& m
) >> 4],
916 fb_writeb (cursor_mask_lookup
[m
& 0x0f] |
917 cursor_bits_lookup
[(b
& m
) & 0x0f],
920 for ( ; x
< 8; x
++) {
921 fb_writeb (0xaa, ram
++);
922 fb_writeb (0xaa, ram
++);
925 fb_memset (ram
, 0xaa, (64 - c
->size
.y
) * 16);
929 aty_set_cursor(struct fb_info_aty
*fb
, int on
)
931 struct atyfb_par
*par
= &fb
->current_par
;
932 struct aty_cursor
*c
= fb
->cursor
;
940 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
941 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
946 x
= c
->pos
.x
- c
->hot
.x
- par
->crtc
.xoffset
;
954 y
= c
->pos
.y
- c
->hot
.y
- par
->crtc
.yoffset
;
962 wait_for_fifo(4, fb
);
963 aty_st_le32(CUR_OFFSET
, (c
->offset
>> 3) + (yoff
<< 1), fb
);
964 aty_st_le32(CUR_HORZ_VERT_OFF
,
965 ((u32
)(64 - c
->size
.y
+ yoff
) << 16) | xoff
, fb
);
966 aty_st_le32(CUR_HORZ_VERT_POSN
, ((u32
)y
<< 16) | x
, fb
);
967 aty_st_le32(GEN_TEST_CNTL
, aty_ld_le32(GEN_TEST_CNTL
, fb
)
968 | HWCURSOR_ENABLE
, fb
);
970 wait_for_fifo(1, fb
);
971 aty_st_le32(GEN_TEST_CNTL
,
972 aty_ld_le32(GEN_TEST_CNTL
, fb
) & ~HWCURSOR_ENABLE
,
975 if (fb
->blitter_may_be_busy
)
980 aty_cursor_timer_handler(unsigned long dev_addr
)
982 struct fb_info_aty
*fb
= (struct fb_info_aty
*)dev_addr
;
987 if (!fb
->cursor
->enable
)
990 if (fb
->cursor
->vbl_cnt
&& --fb
->cursor
->vbl_cnt
== 0) {
992 aty_set_cursor(fb
, fb
->cursor
->on
);
993 fb
->cursor
->vbl_cnt
= fb
->cursor
->blink_rate
;
997 fb
->cursor
->timer
->expires
= jiffies
+ (HZ
/ 50);
998 add_timer(fb
->cursor
->timer
);
1002 atyfb_cursor(struct display
*p
, int mode
, int x
, int y
)
1004 struct fb_info_aty
*fb
= (struct fb_info_aty
*)p
->fb_info
;
1005 struct aty_cursor
*c
= fb
->cursor
;
1011 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
1012 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
1018 if (c
->pos
.x
== x
&& c
->pos
.y
== y
&& (mode
== CM_ERASE
) == !c
->enable
)
1023 aty_set_cursor(fb
, 0);
1035 aty_set_cursor(fb
, 1);
1037 c
->vbl_cnt
= CURSOR_DRAW_DELAY
;
1043 static struct fb_info_aty
*fb_list
= NULL
;
1045 static struct aty_cursor
* __init
1046 aty_init_cursor(struct fb_info_aty
*fb
)
1048 struct aty_cursor
*cursor
;
1051 cursor
= kmalloc(sizeof(struct aty_cursor
), GFP_ATOMIC
);
1054 memset(cursor
, 0, sizeof(*cursor
));
1056 cursor
->timer
= kmalloc(sizeof(*cursor
->timer
), GFP_KERNEL
);
1057 if (!cursor
->timer
) {
1061 memset(cursor
->timer
, 0, sizeof(*cursor
->timer
));
1063 cursor
->blink_rate
= DEFAULT_CURSOR_BLINK_RATE
;
1064 fb
->total_vram
-= PAGE_SIZE
;
1065 cursor
->offset
= fb
->total_vram
;
1068 addr
= fb
->frame_buffer
- 0x800000 + cursor
->offset
;
1069 cursor
->ram
= (u8
*)addr
;
1072 addr
= fb
->frame_buffer_phys
- 0x800000 + cursor
->offset
;
1073 cursor
->ram
= (u8
*)ioremap(addr
, 1024);
1075 addr
= fb
->frame_buffer
+ cursor
->offset
;
1076 cursor
->ram
= (u8
*)addr
;
1080 if (! cursor
->ram
) {
1086 init_timer(cursor
->timer
);
1087 cursor
->timer
->expires
= jiffies
+ (HZ
/ 50);
1088 cursor
->timer
->data
= (unsigned long)fb
;
1089 cursor
->timer
->function
= aty_cursor_timer_handler
;
1090 add_timer(cursor
->timer
);
1097 atyfb_set_font(struct display
*d
, int width
, int height
)
1099 struct fb_info_aty
*fb
= (struct fb_info_aty
*)d
->fb_info
;
1100 struct aty_cursor
*c
= fb
->cursor
;
1104 if (!width
|| !height
) {
1114 memset(c
->bits
, 0xff, sizeof(c
->bits
));
1115 memset(c
->mask
, 0, sizeof(c
->mask
));
1117 for (i
= 0, j
= width
; j
>= 0; j
-= 8, i
++) {
1118 c
->mask
[i
][height
-2] = (j
>= 8) ? 0xff : (0xff << (8 - j
));
1119 c
->mask
[i
][height
-1] = (j
>= 8) ? 0xff : (0xff << (8 - j
));
1122 aty_set_cursor_color(fb
, cursor_pixel_map
, cursor_color_map
,
1123 cursor_color_map
, cursor_color_map
);
1124 aty_set_cursor_shape(fb
);
1132 /* ------------------------------------------------------------------------- */
1138 static void aty_set_crtc(const struct fb_info_aty
*info
,
1139 const struct crtc
*crtc
)
1141 aty_st_le32(CRTC_H_TOTAL_DISP
, crtc
->h_tot_disp
, info
);
1142 aty_st_le32(CRTC_H_SYNC_STRT_WID
, crtc
->h_sync_strt_wid
, info
);
1143 aty_st_le32(CRTC_V_TOTAL_DISP
, crtc
->v_tot_disp
, info
);
1144 aty_st_le32(CRTC_V_SYNC_STRT_WID
, crtc
->v_sync_strt_wid
, info
);
1145 aty_st_le32(CRTC_VLINE_CRNT_VLINE
, 0, info
);
1146 aty_st_le32(CRTC_OFF_PITCH
, crtc
->off_pitch
, info
);
1147 aty_st_le32(CRTC_GEN_CNTL
, crtc
->gen_cntl
, info
);
1150 static int aty_var_to_crtc(const struct fb_info_aty
*info
,
1151 const struct fb_var_screeninfo
*var
,
1154 u32 xres
, yres
, vxres
, vyres
, xoffset
, yoffset
, bpp
;
1155 u32 left
, right
, upper
, lower
, hslen
, vslen
, sync
, vmode
;
1156 u32 h_total
, h_disp
, h_sync_strt
, h_sync_dly
, h_sync_wid
, h_sync_pol
;
1157 u32 v_total
, v_disp
, v_sync_strt
, v_sync_wid
, v_sync_pol
, c_sync
;
1158 u32 pix_width
, dp_pix_width
, dp_chain_mask
;
1163 vxres
= var
->xres_virtual
;
1164 vyres
= var
->yres_virtual
;
1165 xoffset
= var
->xoffset
;
1166 yoffset
= var
->yoffset
;
1167 bpp
= var
->bits_per_pixel
;
1168 left
= var
->left_margin
;
1169 right
= var
->right_margin
;
1170 upper
= var
->upper_margin
;
1171 lower
= var
->lower_margin
;
1172 hslen
= var
->hsync_len
;
1173 vslen
= var
->vsync_len
;
1177 /* convert (and round up) and validate */
1178 xres
= (xres
+7) & ~7;
1179 xoffset
= (xoffset
+7) & ~7;
1180 vxres
= (vxres
+7) & ~7;
1181 if (vxres
< xres
+xoffset
)
1182 vxres
= xres
+xoffset
;
1185 FAIL("h_disp too large");
1186 h_sync_strt
= h_disp
+(right
/8);
1187 if (h_sync_strt
> 0x1ff)
1188 FAIL("h_sync_start too large");
1189 h_sync_dly
= right
& 7;
1190 h_sync_wid
= (hslen
+7)/8;
1191 if (h_sync_wid
> 0x1f)
1192 FAIL("h_sync_wid too large");
1193 h_total
= h_sync_strt
+h_sync_wid
+(h_sync_dly
+left
+7)/8;
1194 if (h_total
> 0x1ff)
1195 FAIL("h_total too large");
1196 h_sync_pol
= sync
& FB_SYNC_HOR_HIGH_ACT
? 0 : 1;
1198 if (vyres
< yres
+yoffset
)
1199 vyres
= yres
+yoffset
;
1202 FAIL("v_disp too large");
1203 v_sync_strt
= v_disp
+lower
;
1204 if (v_sync_strt
> 0x7ff)
1205 FAIL("v_sync_strt too large");
1207 if (v_sync_wid
> 0x1f)
1208 FAIL("v_sync_wid too large");
1209 v_total
= v_sync_strt
+v_sync_wid
+upper
;
1210 if (v_total
> 0x7ff)
1211 FAIL("v_total too large");
1212 v_sync_pol
= sync
& FB_SYNC_VERT_HIGH_ACT
? 0 : 1;
1214 c_sync
= sync
& FB_SYNC_COMP_HIGH_ACT
? CRTC_CSYNC_EN
: 0;
1218 pix_width
= CRTC_PIX_WIDTH_8BPP
;
1219 dp_pix_width
= HOST_8BPP
| SRC_8BPP
| DST_8BPP
| BYTE_ORDER_LSB_TO_MSB
;
1220 dp_chain_mask
= 0x8080;
1221 } else if (bpp
<= 16) {
1223 pix_width
= CRTC_PIX_WIDTH_15BPP
;
1224 dp_pix_width
= HOST_15BPP
| SRC_15BPP
| DST_15BPP
|
1225 BYTE_ORDER_LSB_TO_MSB
;
1226 dp_chain_mask
= 0x4210;
1227 } else if ((bpp
<= 24) && (Gx
!= GX_CHIP_ID
) && (Gx
!= CX_CHIP_ID
)) {
1229 pix_width
= CRTC_PIX_WIDTH_24BPP
;
1230 dp_pix_width
= HOST_8BPP
| SRC_8BPP
| DST_8BPP
| BYTE_ORDER_LSB_TO_MSB
;
1231 dp_chain_mask
= 0x8080;
1232 } else if (bpp
<= 32) {
1234 pix_width
= CRTC_PIX_WIDTH_32BPP
;
1235 dp_pix_width
= HOST_32BPP
| SRC_32BPP
| DST_32BPP
|
1236 BYTE_ORDER_LSB_TO_MSB
;
1237 dp_chain_mask
= 0x8080;
1239 FAIL("invalid bpp");
1241 if (vxres
*vyres
*bpp
/8 > info
->total_vram
)
1242 FAIL("not enough video RAM");
1244 if ((vmode
& FB_VMODE_MASK
) != FB_VMODE_NONINTERLACED
)
1245 FAIL("invalid vmode");
1248 crtc
->vxres
= vxres
;
1249 crtc
->vyres
= vyres
;
1250 crtc
->xoffset
= xoffset
;
1251 crtc
->yoffset
= yoffset
;
1253 crtc
->h_tot_disp
= h_total
| (h_disp
<<16);
1254 crtc
->h_sync_strt_wid
= (h_sync_strt
& 0xff) | (h_sync_dly
<<8) |
1255 ((h_sync_strt
& 0x100)<<4) | (h_sync_wid
<<16) |
1257 crtc
->v_tot_disp
= v_total
| (v_disp
<<16);
1258 crtc
->v_sync_strt_wid
= v_sync_strt
| (v_sync_wid
<<16) | (v_sync_pol
<<21);
1259 crtc
->off_pitch
= ((yoffset
*vxres
+xoffset
)*bpp
/64) | (vxres
<<19);
1260 crtc
->gen_cntl
= pix_width
| c_sync
| CRTC_EXT_DISP_EN
| CRTC_ENABLE
;
1261 if ((Gx
== CT_CHIP_ID
) || (Gx
== ET_CHIP_ID
) ||
1262 ((Gx
== VT_CHIP_ID
|| Gx
== GT_CHIP_ID
) && !(Rev
& 0x07))) {
1264 /* FIXME: magic FIFO values */
1265 crtc
->gen_cntl
|= aty_ld_le32(CRTC_GEN_CNTL
, info
) & 0x000e0000;
1267 crtc
->dp_pix_width
= dp_pix_width
;
1268 crtc
->dp_chain_mask
= dp_chain_mask
;
1274 static int aty_set_dac_ATI68860_B(const struct fb_info_aty
*info
, u32 bpp
,
1277 u32 gModeReg
, devSetupRegA
, temp
, mask
;
1285 devSetupRegA
= 0x60 | 0x00 /*(info->mach64DAC8Bit ? 0x00 : 0x01) */;
1289 devSetupRegA
= 0x60;
1293 devSetupRegA
= 0x60;
1297 devSetupRegA
= 0x60;
1301 devSetupRegA
= 0x60;
1307 devSetupRegA
= 0x61;
1310 temp
= aty_ld_8(DAC_CNTL
, info
);
1311 aty_st_8(DAC_CNTL
, (temp
& ~DAC_EXT_SEL_RS2
) | DAC_EXT_SEL_RS3
, info
);
1313 aty_st_8(DAC_REGS
+ 2, 0x1D, info
);
1314 aty_st_8(DAC_REGS
+ 3, gModeReg
, info
);
1315 aty_st_8(DAC_REGS
, 0x02, info
);
1317 temp
= aty_ld_8(DAC_CNTL
, info
);
1318 aty_st_8(DAC_CNTL
, temp
| DAC_EXT_SEL_RS2
| DAC_EXT_SEL_RS3
, info
);
1320 if (info
->total_vram
< MEM_SIZE_1M
)
1322 else if (info
->total_vram
== MEM_SIZE_1M
)
1327 /* The following assumes that the BIOS has correctly set R7 of the
1328 * Device Setup Register A at boot time.
1330 #define A860_DELAY_L 0x80
1332 temp
= aty_ld_8(DAC_REGS
, info
);
1333 aty_st_8(DAC_REGS
, (devSetupRegA
| mask
) | (temp
& A860_DELAY_L
), info
);
1334 temp
= aty_ld_8(DAC_CNTL
, info
);
1335 aty_st_8(DAC_CNTL
, (temp
& ~(DAC_EXT_SEL_RS2
| DAC_EXT_SEL_RS3
)), info
);
1340 static int aty_set_dac_ATT21C498(const struct fb_info_aty
*info
,
1341 const struct pll_18818
*pll
, u32 bpp
)
1347 dotClock
= 100000000 / pll
->period_in_ps
;
1351 if (dotClock
> 8000) {
1371 if (1 /* info->mach64DAC8Bit */)
1374 aty_dac_waste4(info
);
1375 aty_st_8(DAC_REGS
+ 2, DACMask
, info
);
1380 void aty_dac_waste4(const struct fb_info_aty
*info
)
1382 (void)aty_ld_8(DAC_REGS
, info
);
1384 (void)aty_ld_8(DAC_REGS
+ 2, info
);
1385 (void)aty_ld_8(DAC_REGS
+ 2, info
);
1386 (void)aty_ld_8(DAC_REGS
+ 2, info
);
1387 (void)aty_ld_8(DAC_REGS
+ 2, info
);
1391 static void aty_set_dac_514(const struct fb_info_aty
*info
, u32 bpp
)
1397 u8 pixel_cntl_index
;
1400 { 0, 0x41, 0x03, 0x71, 0x45 }, /* 8 bpp */
1401 { 0, 0x45, 0x04, 0x0c, 0x01 }, /* 555 */
1402 { 0, 0x45, 0x06, 0x0e, 0x00 }, /* XRGB */
1418 aty_st_514(0x90, 0x00, info
); /* VRAM Mask Low */
1419 aty_st_514(0x04, tab
[i
].pixel_dly
, info
); /* Horizontal Sync Control */
1420 aty_st_514(0x05, 0x00, info
); /* Power Management */
1421 aty_st_514(0x02, 0x01, info
); /* Misc Clock Control */
1422 aty_st_514(0x71, tab
[i
].misc2_cntl
, info
); /* Misc Control 2 */
1423 aty_st_514(0x0a, tab
[i
].pixel_rep
, info
); /* Pixel Format */
1424 aty_st_514(tab
[i
].pixel_cntl_index
, tab
[i
].pixel_cntl_v1
, info
);
1425 /* Misc Control 2 / 16 BPP Control / 32 BPP Control */
1428 static int aty_crtc_to_var(const struct crtc
*crtc
,
1429 struct fb_var_screeninfo
*var
)
1431 u32 xres
, yres
, bpp
, left
, right
, upper
, lower
, hslen
, vslen
, sync
;
1432 u32 h_total
, h_disp
, h_sync_strt
, h_sync_dly
, h_sync_wid
, h_sync_pol
;
1433 u32 v_total
, v_disp
, v_sync_strt
, v_sync_wid
, v_sync_pol
, c_sync
;
1437 h_total
= crtc
->h_tot_disp
& 0x1ff;
1438 h_disp
= (crtc
->h_tot_disp
>>16) & 0xff;
1439 h_sync_strt
= (crtc
->h_sync_strt_wid
& 0xff) |
1440 ((crtc
->h_sync_strt_wid
>>4) & 0x100);
1441 h_sync_dly
= (crtc
->h_sync_strt_wid
>>8) & 0x7;
1442 h_sync_wid
= (crtc
->h_sync_strt_wid
>>16) & 0x1f;
1443 h_sync_pol
= (crtc
->h_sync_strt_wid
>>21) & 0x1;
1444 v_total
= crtc
->v_tot_disp
& 0x7ff;
1445 v_disp
= (crtc
->v_tot_disp
>>16) & 0x7ff;
1446 v_sync_strt
= crtc
->v_sync_strt_wid
& 0x7ff;
1447 v_sync_wid
= (crtc
->v_sync_strt_wid
>>16) & 0x1f;
1448 v_sync_pol
= (crtc
->v_sync_strt_wid
>>21) & 0x1;
1449 c_sync
= crtc
->gen_cntl
& CRTC_CSYNC_EN
? 1 : 0;
1450 pix_width
= crtc
->gen_cntl
& CRTC_PIX_WIDTH_MASK
;
1453 xres
= (h_disp
+1)*8;
1455 left
= (h_total
-h_sync_strt
-h_sync_wid
)*8-h_sync_dly
;
1456 right
= (h_sync_strt
-h_disp
)*8+h_sync_dly
;
1457 hslen
= h_sync_wid
*8;
1458 upper
= v_total
-v_sync_strt
-v_sync_wid
;
1459 lower
= v_sync_strt
-v_disp
;
1461 sync
= (h_sync_pol
? 0 : FB_SYNC_HOR_HIGH_ACT
) |
1462 (v_sync_pol
? 0 : FB_SYNC_VERT_HIGH_ACT
) |
1463 (c_sync
? FB_SYNC_COMP_HIGH_ACT
: 0);
1465 switch (pix_width
) {
1467 case CRTC_PIX_WIDTH_4BPP
:
1469 var
->red
.offset
= 0;
1470 var
->red
.length
= 8;
1471 var
->green
.offset
= 0;
1472 var
->green
.length
= 8;
1473 var
->blue
.offset
= 0;
1474 var
->blue
.length
= 8;
1475 var
->transp
.offset
= 0;
1476 var
->transp
.length
= 0;
1479 case CRTC_PIX_WIDTH_8BPP
:
1481 var
->red
.offset
= 0;
1482 var
->red
.length
= 8;
1483 var
->green
.offset
= 0;
1484 var
->green
.length
= 8;
1485 var
->blue
.offset
= 0;
1486 var
->blue
.length
= 8;
1487 var
->transp
.offset
= 0;
1488 var
->transp
.length
= 0;
1490 case CRTC_PIX_WIDTH_15BPP
: /* RGB 555 */
1492 var
->red
.offset
= 10;
1493 var
->red
.length
= 5;
1494 var
->green
.offset
= 5;
1495 var
->green
.length
= 5;
1496 var
->blue
.offset
= 0;
1497 var
->blue
.length
= 5;
1498 var
->transp
.offset
= 0;
1499 var
->transp
.length
= 0;
1502 case CRTC_PIX_WIDTH_16BPP
: /* RGB 565 */
1504 var
->red
.offset
= 11;
1505 var
->red
.length
= 5;
1506 var
->green
.offset
= 5;
1507 var
->green
.length
= 6;
1508 var
->blue
.offset
= 0;
1509 var
->blue
.length
= 5;
1510 var
->transp
.offset
= 0;
1511 var
->transp
.length
= 0;
1514 case CRTC_PIX_WIDTH_24BPP
: /* RGB 888 */
1516 var
->red
.offset
= 16;
1517 var
->red
.length
= 8;
1518 var
->green
.offset
= 8;
1519 var
->green
.length
= 8;
1520 var
->blue
.offset
= 0;
1521 var
->blue
.length
= 8;
1522 var
->transp
.offset
= 0;
1523 var
->transp
.length
= 0;
1525 case CRTC_PIX_WIDTH_32BPP
: /* ARGB 8888 */
1527 var
->red
.offset
= 16;
1528 var
->red
.length
= 8;
1529 var
->green
.offset
= 8;
1530 var
->green
.length
= 8;
1531 var
->blue
.offset
= 0;
1532 var
->blue
.length
= 8;
1533 var
->transp
.offset
= 24;
1534 var
->transp
.length
= 8;
1537 FAIL("Invalid pixel width");
1543 var
->xres_virtual
= crtc
->vxres
;
1544 var
->yres_virtual
= crtc
->vyres
;
1545 var
->bits_per_pixel
= bpp
;
1546 var
->xoffset
= crtc
->xoffset
;
1547 var
->yoffset
= crtc
->yoffset
;
1548 var
->left_margin
= left
;
1549 var
->right_margin
= right
;
1550 var
->upper_margin
= upper
;
1551 var
->lower_margin
= lower
;
1552 var
->hsync_len
= hslen
;
1553 var
->vsync_len
= vslen
;
1555 var
->vmode
= FB_VMODE_NONINTERLACED
;
1560 /* ------------------------------------------------------------------------- */
1563 * PLL programming (Mach64 GX family)
1565 * FIXME: use function pointer tables instead of switch statements
1568 static void aty_set_pll_gx(const struct fb_info_aty
*info
,
1569 const struct pll_gx
*pll
)
1571 switch (info
->clk_type
) {
1572 case CLK_ATI18818_1
:
1573 aty_st_8(CLOCK_CNTL
, pll
->m
, info
);
1576 aty_st_514(0x06, 0x02, info
); /* DAC Operation */
1577 aty_st_514(0x10, 0x01, info
); /* PLL Control 1 */
1578 aty_st_514(0x70, 0x01, info
); /* Misc Control 1 */
1579 aty_st_514(0x8f, 0x1f, info
); /* PLL Ref. Divider Input */
1580 aty_st_514(0x03, 0x00, info
); /* Sync Control */
1581 aty_st_514(0x05, 0x00, info
); /* Power Management */
1582 aty_st_514(0x20, pll
->m
, info
); /* F0 / M0 */
1583 aty_st_514(0x21, pll
->n
, info
); /* F1 / N0 */
1589 static int aty_var_to_pll_18818(u32 period_in_ps
, struct pll_18818
*pll
)
1591 u32 MHz100
; /* in 0.01 MHz */
1595 /* Calculate the programming word */
1596 MHz100
= 100000000 / period_in_ps
;
1601 if (MHz100
> MAX_FREQ_2595
) {
1602 MHz100
= MAX_FREQ_2595
;
1604 } else if (MHz100
< ABS_MIN_FREQ_2595
) {
1605 program_bits
= 0; /* MHz100 = 257 */
1608 while (MHz100
< MIN_FREQ_2595
) {
1614 MHz100
= (REF_DIV_2595
* MHz100
) / REF_FREQ_2595
;
1616 MHz100
+= 500; /* + 0.5 round */
1619 if (program_bits
== -1) {
1620 program_bits
= MHz100
- N_ADJ_2595
;
1621 switch (post_divider
) {
1623 program_bits
|= 0x0600;
1626 program_bits
|= 0x0400;
1629 program_bits
|= 0x0200;
1637 program_bits
|= STOP_BITS_2595
;
1639 pll
->program_bits
= program_bits
;
1640 pll
->locationAddr
= 0;
1641 pll
->post_divider
= post_divider
;
1642 pll
->period_in_ps
= period_in_ps
;
1647 static u32
aty_pll_18818_to_var(const struct pll_18818
*pll
)
1649 return(pll
->period_in_ps
); /* default for now */
1652 static void aty_set_pll18818(const struct fb_info_aty
*info
,
1653 const struct pll_18818
*pll
)
1661 u8 old_crtc_ext_disp
;
1663 old_clock_cntl
= aty_ld_8(CLOCK_CNTL
, info
);
1664 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, 0, info
);
1666 old_crtc_ext_disp
= aty_ld_8(CRTC_GEN_CNTL
+ 3, info
);
1667 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
| (CRTC_EXT_DISP_EN
>> 24),
1670 udelay(15000); /* delay for 50 (15) ms */
1672 program_bits
= pll
->program_bits
;
1673 locationAddr
= pll
->locationAddr
;
1675 /* Program the clock chip */
1676 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, 0, info
); /* Strobe = 0 */
1677 aty_StrobeClock(info
);
1678 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, 1, info
); /* Strobe = 0 */
1679 aty_StrobeClock(info
);
1681 aty_ICS2595_put1bit(1, info
); /* Send start bits */
1682 aty_ICS2595_put1bit(0, info
); /* Start bit */
1683 aty_ICS2595_put1bit(0, info
); /* Read / ~Write */
1685 for (i
= 0; i
< 5; i
++) { /* Location 0..4 */
1686 aty_ICS2595_put1bit(locationAddr
& 1, info
);
1690 for (i
= 0; i
< 8 + 1 + 2 + 2; i
++) {
1691 aty_ICS2595_put1bit(program_bits
& 1, info
);
1695 udelay(1000); /* delay for 1 ms */
1697 (void)aty_ld_8(DAC_REGS
, info
); /* Clear DAC Counter */
1698 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
, info
);
1699 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, old_clock_cntl
| CLOCK_STROBE
,
1702 udelay(50000); /* delay for 50 (15) ms */
1703 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
,
1704 ((pll
->locationAddr
& 0x0F) | CLOCK_STROBE
), info
);
1710 static int aty_var_to_pll_408(u32 period_in_ps
, struct pll_18818
*pll
)
1712 u32 mhz100
; /* in 0.01 MHz */
1714 /* u32 post_divider; */
1715 u32 mach64MinFreq
, mach64MaxFreq
, mach64RefFreq
;
1717 u16 remainder
, preRemainder
;
1718 short divider
= 0, tempA
;
1720 /* Calculate the programming word */
1721 mhz100
= 100000000 / period_in_ps
;
1722 mach64MinFreq
= MIN_FREQ_2595
;
1723 mach64MaxFreq
= MAX_FREQ_2595
;
1724 mach64RefFreq
= REF_FREQ_2595
; /* 14.32 MHz */
1726 /* Calculate program word */
1728 program_bits
= 0xFF;
1730 if (mhz100
< mach64MinFreq
)
1731 mhz100
= mach64MinFreq
;
1732 if (mhz100
> mach64MaxFreq
)
1733 mhz100
= mach64MaxFreq
;
1735 while (mhz100
< (mach64MinFreq
<< 3)) {
1740 temp
= (unsigned int)mhz100
;
1741 temp
= (unsigned int)(temp
* (MIN_N_408
+ 2));
1742 temp
-= ((short)(mach64RefFreq
<< 1));
1745 preRemainder
= 0xFFFF;
1749 remainder
= tempB
% mach64RefFreq
;
1750 tempB
= tempB
/ mach64RefFreq
;
1751 if (((tempB
& 0xFFFF) <= 255) && (remainder
<= preRemainder
)) {
1752 preRemainder
= remainder
;
1755 divider
= (divider
& 0x00FF) + ((tempB
& 0xFF) << 8);
1759 } while(tempA
<= 32);
1761 program_bits
= divider
;
1764 pll
->program_bits
= program_bits
;
1765 pll
->locationAddr
= 0;
1766 pll
->post_divider
= divider
; /* fuer nix */
1767 pll
->period_in_ps
= period_in_ps
;
1772 static u32
aty_pll_408_to_var(const struct pll_18818
*pll
)
1774 return(pll
->period_in_ps
); /* default for now */
1777 static void aty_set_pll_408(const struct fb_info_aty
*info
,
1778 const struct pll_18818
*pll
)
1783 u8 tmpA
, tmpB
, tmpC
;
1784 char old_crtc_ext_disp
;
1786 old_crtc_ext_disp
= aty_ld_8(CRTC_GEN_CNTL
+ 3, info
);
1787 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
| (CRTC_EXT_DISP_EN
>> 24),
1790 program_bits
= pll
->program_bits
;
1791 locationAddr
= pll
->locationAddr
;
1794 aty_dac_waste4(info
);
1795 tmpB
= aty_ld_8(DAC_REGS
+ 2, info
) | 1;
1796 aty_dac_waste4(info
);
1797 aty_st_8(DAC_REGS
+ 2, tmpB
, info
);
1804 aty_st_8(DAC_REGS
, tmpB
, info
);
1805 aty_st_8(DAC_REGS
+ 2, tmpA
, info
);
1807 udelay(400); /* delay for 400 us */
1809 locationAddr
= (locationAddr
<< 2) + 0x40;
1810 tmpB
= locationAddr
;
1811 tmpA
= program_bits
>> 8;
1813 aty_st_8(DAC_REGS
, tmpB
, info
);
1814 aty_st_8(DAC_REGS
+ 2, tmpA
, info
);
1816 tmpB
= locationAddr
+ 1;
1817 tmpA
= (u8
)program_bits
;
1819 aty_st_8(DAC_REGS
, tmpB
, info
);
1820 aty_st_8(DAC_REGS
+ 2, tmpA
, info
);
1822 tmpB
= locationAddr
+ 2;
1825 aty_st_8(DAC_REGS
, tmpB
, info
);
1826 aty_st_8(DAC_REGS
+ 2, tmpA
, info
);
1828 udelay(400); /* delay for 400 us */
1829 tmpA
= tmpC
& (~(1 | 8));
1832 aty_st_8(DAC_REGS
, tmpB
, info
);
1833 aty_st_8(DAC_REGS
+ 2, tmpA
, info
);
1835 (void)aty_ld_8(DAC_REGS
, info
); /* Clear DAC Counter */
1836 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
, info
);
1842 static int aty_var_to_pll_1703(u32 period_in_ps
, struct pll_18818
*pll
)
1844 u32 mhz100
; /* in 0.01 MHz */
1846 /* u32 post_divider; */
1847 u32 mach64MinFreq
, mach64MaxFreq
, mach64RefFreq
;
1849 u16 remainder
, preRemainder
;
1850 short divider
= 0, tempA
;
1852 /* Calculate the programming word */
1853 mhz100
= 100000000 / period_in_ps
;
1854 mach64MinFreq
= MIN_FREQ_2595
;
1855 mach64MaxFreq
= MAX_FREQ_2595
;
1856 mach64RefFreq
= REF_FREQ_2595
; /* 14.32 MHz */
1858 /* Calculate program word */
1860 program_bits
= 0xE0;
1862 if (mhz100
< mach64MinFreq
)
1863 mhz100
= mach64MinFreq
;
1864 if (mhz100
> mach64MaxFreq
)
1865 mhz100
= mach64MaxFreq
;
1868 while (mhz100
< (mach64MinFreq
<< 3)) {
1873 temp
= (unsigned int)(mhz100
);
1874 temp
= (unsigned int)(temp
* (MIN_N_1703
+ 2));
1875 temp
-= (short)(mach64RefFreq
<< 1);
1878 preRemainder
= 0xffff;
1882 remainder
= tempB
% mach64RefFreq
;
1883 tempB
= tempB
/ mach64RefFreq
;
1885 if ((tempB
& 0xffff) <= 127 && (remainder
<= preRemainder
)) {
1886 preRemainder
= remainder
;
1889 divider
= (divider
& 0x00ff) + ((tempB
& 0xff) << 8);
1894 } while (tempA
<= (MIN_N_1703
<< 1));
1896 program_bits
= divider
;
1899 pll
->program_bits
= program_bits
;
1900 pll
->locationAddr
= 0;
1901 pll
->post_divider
= divider
; /* fuer nix */
1902 pll
->period_in_ps
= period_in_ps
;
1907 static u32
aty_pll_1703_to_var(const struct pll_18818
*pll
)
1909 return(pll
->period_in_ps
); /* default for now */
1912 static void aty_set_pll_1703(const struct fb_info_aty
*info
,
1913 const struct pll_18818
*pll
)
1918 char old_crtc_ext_disp
;
1920 old_crtc_ext_disp
= aty_ld_8(CRTC_GEN_CNTL
+ 3, info
);
1921 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
| (CRTC_EXT_DISP_EN
>> 24),
1924 program_bits
= pll
->program_bits
;
1925 locationAddr
= pll
->locationAddr
;
1928 aty_dac_waste4(info
);
1930 (void)aty_ld_8(DAC_REGS
+ 2, info
);
1931 aty_st_8(DAC_REGS
+2, (locationAddr
<< 1) + 0x20, info
);
1932 aty_st_8(DAC_REGS
+2, 0, info
);
1933 aty_st_8(DAC_REGS
+2, (program_bits
& 0xFF00) >> 8, info
);
1934 aty_st_8(DAC_REGS
+2, (program_bits
& 0xFF), info
);
1936 (void)aty_ld_8(DAC_REGS
, info
); /* Clear DAC Counter */
1937 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
, info
);
1943 static int aty_var_to_pll_8398(u32 period_in_ps
, struct pll_18818
*pll
)
1946 u32 tempA
, tempB
, fOut
, longMHz100
, diff
, preDiff
;
1948 u32 mhz100
; /* in 0.01 MHz */
1950 /* u32 post_divider; */
1951 u32 mach64MinFreq
, mach64MaxFreq
, mach64RefFreq
;
1952 u16 m
, n
, k
=0, save_m
, save_n
, twoToKth
;
1954 /* Calculate the programming word */
1955 mhz100
= 100000000 / period_in_ps
;
1956 mach64MinFreq
= MIN_FREQ_2595
;
1957 mach64MaxFreq
= MAX_FREQ_2595
;
1958 mach64RefFreq
= REF_FREQ_2595
; /* 14.32 MHz */
1963 /* Calculate program word */
1965 program_bits
= 0xE0;
1968 if (mhz100
< mach64MinFreq
)
1969 mhz100
= mach64MinFreq
;
1970 if (mhz100
> mach64MaxFreq
)
1971 mhz100
= mach64MaxFreq
;
1973 longMHz100
= mhz100
* 256 / 100; /* 8 bit scale this */
1975 while (mhz100
< (mach64MinFreq
<< 3))
1983 preDiff
= 0xFFFFFFFF;
1985 for (m
= MIN_M
; m
<= MAX_M
; m
++)
1987 for (n
= MIN_N
; n
<= MAX_N
; n
++)
1989 tempA
= (14.31818 * 65536);
1990 tempA
*= (n
+ 8); /* 43..256 */
1991 tempB
= twoToKth
* 256;
1992 tempB
*= (m
+ 2); /* 4..32 */
1993 fOut
= tempA
/ tempB
; /* 8 bit scale */
1995 if (longMHz100
> fOut
)
1996 diff
= longMHz100
- fOut
;
1998 diff
= fOut
- longMHz100
;
2009 program_bits
= (k
<< 6) + (save_m
) + (save_n
<< 8);
2012 pll
->program_bits
= program_bits
;
2013 pll
->locationAddr
= 0;
2014 pll
->post_divider
= 0;
2015 pll
->period_in_ps
= period_in_ps
;
2020 static u32
aty_pll_8398_to_var(const struct pll_18818
*pll
)
2022 return(pll
->period_in_ps
); /* default for now */
2025 static void aty_set_pll_8398(const struct fb_info_aty
*info
,
2026 const struct pll_18818
*pll
)
2031 char old_crtc_ext_disp
;
2034 old_crtc_ext_disp
= aty_ld_8(CRTC_GEN_CNTL
+ 3, info
);
2035 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
| (CRTC_EXT_DISP_EN
>> 24),
2038 program_bits
= pll
->program_bits
;
2039 locationAddr
= pll
->locationAddr
;
2042 tmp
= aty_ld_8(DAC_CNTL
, info
);
2043 aty_st_8(DAC_CNTL
, tmp
| DAC_EXT_SEL_RS2
| DAC_EXT_SEL_RS3
, info
);
2045 aty_st_8(DAC_REGS
, locationAddr
, info
);
2046 aty_st_8(DAC_REGS
+1, (program_bits
& 0xff00) >> 8, info
);
2047 aty_st_8(DAC_REGS
+1, (program_bits
& 0xff), info
);
2049 tmp
= aty_ld_8(DAC_CNTL
, info
);
2050 aty_st_8(DAC_CNTL
, (tmp
& ~DAC_EXT_SEL_RS2
) | DAC_EXT_SEL_RS3
, info
);
2052 (void)aty_ld_8(DAC_REGS
, info
); /* Clear DAC Counter */
2053 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
, info
);
2059 static int aty_var_to_pll_514(u32 vclk_per
, struct pll_gx
*pll
)
2062 * FIXME: use real calculations instead of using fixed values from the old
2066 u32 limit
; /* pixlock rounding limit (arbitrary) */
2067 u8 m
; /* (df<<6) | vco_div_count */
2068 u8 n
; /* ref_div_count */
2069 } RGB514_clocks
[7] = {
2070 { 8000, (3<<6) | 20, 9 }, /* 7395 ps / 135.2273 MHz */
2071 { 10000, (1<<6) | 19, 3 }, /* 9977 ps / 100.2273 MHz */
2072 { 13000, (1<<6) | 2, 3 }, /* 12509 ps / 79.9432 MHz */
2073 { 14000, (2<<6) | 8, 7 }, /* 13394 ps / 74.6591 MHz */
2074 { 16000, (1<<6) | 44, 6 }, /* 15378 ps / 65.0284 MHz */
2075 { 25000, (1<<6) | 15, 5 }, /* 17460 ps / 57.2727 MHz */
2076 { 50000, (0<<6) | 53, 7 }, /* 33145 ps / 30.1705 MHz */
2080 for (i
= 0; i
< sizeof(RGB514_clocks
)/sizeof(*RGB514_clocks
); i
++)
2081 if (vclk_per
<= RGB514_clocks
[i
].limit
) {
2082 pll
->m
= RGB514_clocks
[i
].m
;
2083 pll
->n
= RGB514_clocks
[i
].n
;
2090 static void aty_StrobeClock(const struct fb_info_aty
*info
)
2096 tmp
= aty_ld_8(CLOCK_CNTL
, info
);
2097 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, tmp
| CLOCK_STROBE
, info
);
2103 static void aty_ICS2595_put1bit(u8 data
, const struct fb_info_aty
*info
)
2108 tmp
= aty_ld_8(CLOCK_CNTL
, info
);
2109 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, (tmp
& ~0x04) | (data
<< 2),
2112 tmp
= aty_ld_8(CLOCK_CNTL
, info
);
2113 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, (tmp
& ~0x08) | (0 << 3), info
);
2115 aty_StrobeClock(info
);
2117 tmp
= aty_ld_8(CLOCK_CNTL
, info
);
2118 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, (tmp
& ~0x08) | (1 << 3), info
);
2120 aty_StrobeClock(info
);
2126 static u32
aty_pll_gx_to_var(const struct pll_gx
*pll
,
2127 const struct fb_info_aty
*info
)
2129 u8 df
, vco_div_count
, ref_div_count
;
2132 vco_div_count
= pll
->m
& 0x3f;
2133 ref_div_count
= pll
->n
;
2135 return ((info
->ref_clk_per
*ref_div_count
)<<(3-df
))/(vco_div_count
+65);
2140 * PLL programming (Mach64 CT family)
2143 static void aty_set_pll_ct(const struct fb_info_aty
*info
,
2144 const struct pll_ct
*pll
)
2146 aty_st_pll(PLL_REF_DIV
, pll
->pll_ref_div
, info
);
2147 aty_st_pll(PLL_GEN_CNTL
, pll
->pll_gen_cntl
, info
);
2148 aty_st_pll(MCLK_FB_DIV
, pll
->mclk_fb_div
, info
);
2149 aty_st_pll(PLL_VCLK_CNTL
, pll
->pll_vclk_cntl
, info
);
2150 aty_st_pll(VCLK_POST_DIV
, pll
->vclk_post_div
, info
);
2151 aty_st_pll(VCLK0_FB_DIV
, pll
->vclk_fb_div
, info
);
2152 aty_st_pll(PLL_EXT_CNTL
, pll
->pll_ext_cntl
, info
);
2154 if (!(Gx
== GX_CHIP_ID
|| Gx
== CX_CHIP_ID
|| Gx
== CT_CHIP_ID
||
2156 ((Gx
== VT_CHIP_ID
|| Gx
== GT_CHIP_ID
) && !(Rev
& 0x07)))) {
2157 if (info
->ram_type
>= SDRAM
)
2158 aty_st_pll(DLL_CNTL
, 0xa6, info
);
2160 aty_st_pll(DLL_CNTL
, 0xa0, info
);
2161 aty_st_pll(VFC_CNTL
, 0x1b, info
);
2162 aty_st_le32(DSP_CONFIG
, pll
->dsp_config
, info
);
2163 aty_st_le32(DSP_ON_OFF
, pll
->dsp_on_off
, info
);
2167 static int aty_dsp_gt(const struct fb_info_aty
*info
, u8 bpp
,
2170 u32 dsp_xclks_per_row
, dsp_loop_latency
, dsp_precision
, dsp_off
, dsp_on
;
2171 u32 xclks_per_row
, fifo_off
, fifo_on
, y
, fifo_size
, page_size
;
2173 /* xclocks_per_row<<11 */
2174 xclks_per_row
= (pll
->mclk_fb_div
*pll
->vclk_post_div_real
*64<<11)/
2175 (pll
->vclk_fb_div
*pll
->mclk_post_div_real
*bpp
);
2176 if (xclks_per_row
< (1<<11))
2177 FAIL("Dotclock to high");
2178 if (Gx
== GT_CHIP_ID
|| Gx
== GU_CHIP_ID
|| Gx
== VT_CHIP_ID
||
2179 Gx
== VU_CHIP_ID
|| Gx
== GV_CHIP_ID
|| Gx
== GW_CHIP_ID
||
2182 dsp_loop_latency
= 0;
2185 dsp_loop_latency
= 2;
2188 y
= (xclks_per_row
*fifo_size
)>>11;
2195 fifo_off
= ((xclks_per_row
*(fifo_size
-1))>>5)+(1<<6);
2197 if (info
->total_vram
> 1*1024*1024) {
2198 if (info
->ram_type
>= SDRAM
) {
2200 dsp_loop_latency
+= 8;
2204 dsp_loop_latency
+= 6;
2208 if (info
->ram_type
>= SDRAM
) {
2210 dsp_loop_latency
+= 9;
2214 dsp_loop_latency
+= 8;
2219 if (xclks_per_row
>= (page_size
<<11))
2220 fifo_on
= ((2*page_size
+1)<<6)+(xclks_per_row
>>5);
2222 fifo_on
= (3*page_size
)<<6;
2224 dsp_xclks_per_row
= xclks_per_row
>>dsp_precision
;
2225 dsp_on
= fifo_on
>>dsp_precision
;
2226 dsp_off
= fifo_off
>>dsp_precision
;
2228 pll
->dsp_config
= (dsp_xclks_per_row
& 0x3fff) |
2229 ((dsp_loop_latency
& 0xf)<<16) |
2230 ((dsp_precision
& 7)<<20);
2231 pll
->dsp_on_off
= (dsp_on
& 0x7ff) | ((dsp_off
& 0x7ff)<<16);
2235 static int aty_valid_pll_ct(const struct fb_info_aty
*info
, u32 vclk_per
,
2238 u32 q
, x
; /* x is a workaround for sparc64-linux-gcc */
2239 x
= x
; /* x is a workaround for sparc64-linux-gcc */
2241 pll
->pll_ref_div
= info
->pll_per
*2*255/info
->ref_clk_per
;
2243 /* FIXME: use the VTB/GTB /3 post divider if it's better suited */
2244 q
= info
->ref_clk_per
*pll
->pll_ref_div
*4/info
->mclk_per
; /* actually 8*q */
2245 if (q
< 16*8 || q
> 255*8)
2246 FAIL("mclk out of range");
2248 pll
->mclk_post_div_real
= 8;
2250 pll
->mclk_post_div_real
= 4;
2252 pll
->mclk_post_div_real
= 2;
2254 pll
->mclk_post_div_real
= 1;
2255 pll
->mclk_fb_div
= q
*pll
->mclk_post_div_real
/8;
2257 /* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
2258 q
= info
->ref_clk_per
*pll
->pll_ref_div
*4/vclk_per
; /* actually 8*q */
2259 if (q
< 16*8 || q
> 255*8)
2260 FAIL("vclk out of range");
2262 pll
->vclk_post_div_real
= 8;
2264 pll
->vclk_post_div_real
= 4;
2266 pll
->vclk_post_div_real
= 2;
2268 pll
->vclk_post_div_real
= 1;
2269 pll
->vclk_fb_div
= q
*pll
->vclk_post_div_real
/8;
2273 static void aty_calc_pll_ct(const struct fb_info_aty
*info
, struct pll_ct
*pll
)
2278 if ((((Gx
== GT_CHIP_ID
) && (Rev
& 0x03)) || (Gx
== GU_CHIP_ID
) ||
2279 (Gx
== GV_CHIP_ID
) || (Gx
== GW_CHIP_ID
) || (Gx
== GZ_CHIP_ID
) ||
2280 (Gx
== LG_CHIP_ID
) || (Gx
== GB_CHIP_ID
) || (Gx
== GD_CHIP_ID
) ||
2281 (Gx
== GI_CHIP_ID
) || (Gx
== GP_CHIP_ID
) || (Gx
== GQ_CHIP_ID
) ||
2282 (Gx
== VU_CHIP_ID
)) && (info
->ram_type
>= SDRAM
))
2283 pll
->pll_gen_cntl
= 0x04;
2285 pll
->pll_gen_cntl
= 0x84;
2287 switch (pll
->mclk_post_div_real
) {
2304 pll
->pll_gen_cntl
|= mpostdiv
<<4; /* mclk */
2306 if (Gx
== VT_CHIP_ID
&& (Rev
== 0x40 || Rev
== 0x48))
2307 pll
->pll_ext_cntl
= 0;
2309 pll
->pll_ext_cntl
= mpostdiv
; /* xclk == mclk */
2311 switch (pll
->vclk_post_div_real
) {
2316 pll
->pll_ext_cntl
|= 0x10;
2321 pll
->pll_ext_cntl
|= 0x10;
2326 pll
->pll_ext_cntl
|= 0x10;
2332 pll
->pll_vclk_cntl
= 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */
2333 pll
->vclk_post_div
= vpostdiv
;
2336 static int aty_var_to_pll_ct(const struct fb_info_aty
*info
, u32 vclk_per
,
2337 u8 bpp
, struct pll_ct
*pll
)
2341 if ((err
= aty_valid_pll_ct(info
, vclk_per
, pll
)))
2343 if (!(Gx
== GX_CHIP_ID
|| Gx
== CX_CHIP_ID
|| Gx
== CT_CHIP_ID
||
2345 ((Gx
== VT_CHIP_ID
|| Gx
== GT_CHIP_ID
) && !(Rev
& 0x07)))) {
2346 if ((err
= aty_dsp_gt(info
, bpp
, pll
)))
2349 aty_calc_pll_ct(info
, pll
);
2353 static u32
aty_pll_ct_to_var(const struct pll_ct
*pll
,
2354 const struct fb_info_aty
*info
)
2356 u32 ref_clk_per
= info
->ref_clk_per
;
2357 u8 pll_ref_div
= pll
->pll_ref_div
;
2358 u8 vclk_fb_div
= pll
->vclk_fb_div
;
2359 u8 vclk_post_div
= pll
->vclk_post_div_real
;
2361 return ref_clk_per
*pll_ref_div
*vclk_post_div
/vclk_fb_div
/2;
2364 /* ------------------------------------------------------------------------- */
2366 static void atyfb_set_par(const struct atyfb_par
*par
,
2367 struct fb_info_aty
*info
)
2374 accelmode
= par
->accel_flags
; /* hack */
2376 info
->current_par
= *par
;
2378 if (info
->blitter_may_be_busy
)
2379 wait_for_idle(info
);
2380 tmp
= aty_ld_8(CRTC_GEN_CNTL
+ 3, info
);
2381 aty_set_crtc(info
, &par
->crtc
);
2382 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, 0, info
);
2383 /* better call aty_StrobeClock ?? */
2384 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, CLOCK_STROBE
, info
);
2386 if ((Gx
== GX_CHIP_ID
) || (Gx
== CX_CHIP_ID
)) {
2387 switch (info
->dac_subtype
) {
2389 aty_set_dac_514(info
, par
->crtc
.bpp
);
2391 case DAC_ATI68860_B
:
2392 case DAC_ATI68860_C
:
2393 muxmode
= aty_set_dac_ATI68860_B(info
, par
->crtc
.bpp
,
2395 aty_st_le32(BUS_CNTL
, 0x890e20f1, info
);
2396 aty_st_le32(DAC_CNTL
, 0x47052100, info
);
2399 muxmode
= aty_set_dac_ATT21C498(info
, &par
->pll
.ics2595
,
2401 aty_st_le32(BUS_CNTL
, 0x890e20f1, info
);
2402 aty_st_le32(DAC_CNTL
, 0x00072000, info
);
2405 muxmode
= aty_set_dac_ATT21C498(info
, &par
->pll
.ics2595
,
2407 aty_st_le32(BUS_CNTL
, 0x890e20f1, info
);
2408 aty_st_le32(DAC_CNTL
, 0x00072000, info
);
2411 printk(" atyfb_set_par: DAC type not implemented yet!\n");
2412 aty_st_le32(BUS_CNTL
, 0x890e20f1, info
);
2413 aty_st_le32(DAC_CNTL
, 0x47052100, info
);
2414 /* new in 2.2.3p1 from Geert. ???????? */
2415 aty_st_le32(BUS_CNTL
, 0x590e10ff, info
);
2416 aty_st_le32(DAC_CNTL
, 0x47012100, info
);
2420 switch (info
->clk_type
) {
2421 case CLK_ATI18818_1
:
2422 aty_set_pll18818(info
, &par
->pll
.ics2595
);
2425 aty_set_pll_1703(info
, &par
->pll
.ics2595
);
2428 aty_set_pll_8398(info
, &par
->pll
.ics2595
);
2431 aty_set_pll_408(info
, &par
->pll
.ics2595
);
2434 aty_set_pll_gx(info
, &par
->pll
.gx
);
2437 printk(" atyfb_set_par: CLK type not implemented yet!");
2441 /* Don't forget MEM_CNTL */
2442 i
= aty_ld_le32(MEM_CNTL
, info
) & 0xf0ffffff;
2443 switch (par
->crtc
.bpp
) {
2454 aty_st_le32(MEM_CNTL
, i
, info
);
2457 aty_set_pll_ct(info
, &par
->pll
.ct
);
2458 i
= aty_ld_le32(MEM_CNTL
, info
) & 0xf00fffff;
2459 if (!(Gx
== VT_CHIP_ID
&& (Rev
== 0x40 || Rev
== 0x48)))
2460 i
|= info
->mem_refresh_rate
<< 20;
2461 switch (par
->crtc
.bpp
) {
2473 if ((Gx
== CT_CHIP_ID
) || (Gx
== ET_CHIP_ID
)) {
2474 aty_st_le32(DAC_CNTL
, 0x87010184, info
);
2475 aty_st_le32(BUS_CNTL
, 0x680000f9, info
);
2476 } else if ((Gx
== VT_CHIP_ID
) || (Gx
== VU_CHIP_ID
)) {
2477 aty_st_le32(DAC_CNTL
, 0x87010184, info
);
2478 aty_st_le32(BUS_CNTL
, 0x680000f9, info
);
2481 aty_st_le32(DAC_CNTL
, 0x86010102, info
);
2482 aty_st_le32(BUS_CNTL
, 0x7b23a040, info
);
2483 aty_st_le32(EXT_MEM_CNTL
,
2484 aty_ld_le32(EXT_MEM_CNTL
, info
) | 0x5000001, info
);
2486 aty_st_le32(MEM_CNTL
, i
, info
);
2488 aty_st_8(DAC_MASK
, 0xff, info
);
2490 /* Initialize the graphics engine */
2491 if (par
->accel_flags
& FB_ACCELF_TEXT
)
2492 init_engine(par
, info
);
2494 #ifdef CONFIG_FB_COMPAT_XPMAC
2495 if (console_fb_info
== &info
->fb_info
) {
2496 struct fb_var_screeninfo var
;
2498 display_info
.height
= ((par
->crtc
.v_tot_disp
>>16) & 0x7ff)+1;
2499 display_info
.width
= (((par
->crtc
.h_tot_disp
>>16) & 0xff)+1)*8;
2500 display_info
.depth
= par
->crtc
.bpp
;
2501 display_info
.pitch
= par
->crtc
.vxres
*par
->crtc
.bpp
/8;
2502 atyfb_encode_var(&var
, par
, info
);
2503 if (mac_var_to_vmode(&var
, &vmode
, &cmode
))
2504 display_info
.mode
= 0;
2506 display_info
.mode
= vmode
;
2507 strcpy(display_info
.name
, atyfb_name
);
2508 display_info
.fb_address
= info
->frame_buffer_phys
;
2509 display_info
.cmap_adr_address
= info
->ati_regbase_phys
+0xc0;
2510 display_info
.cmap_data_address
= info
->ati_regbase_phys
+0xc1;
2511 display_info
.disp_reg_address
= info
->ati_regbase_phys
;
2513 #endif /* CONFIG_FB_COMPAT_XPMAC */
2516 static int atyfb_decode_var(const struct fb_var_screeninfo
*var
,
2517 struct atyfb_par
*par
,
2518 const struct fb_info_aty
*info
)
2522 if ((err
= aty_var_to_crtc(info
, var
, &par
->crtc
)))
2524 if ((Gx
== GX_CHIP_ID
) || (Gx
== CX_CHIP_ID
))
2525 switch (info
->clk_type
) {
2526 case CLK_ATI18818_1
:
2527 err
= aty_var_to_pll_18818(var
->pixclock
, &par
->pll
.ics2595
);
2530 err
= aty_var_to_pll_1703(var
->pixclock
, &par
->pll
.ics2595
);
2533 err
= aty_var_to_pll_8398(var
->pixclock
, &par
->pll
.ics2595
);
2536 err
= aty_var_to_pll_408(var
->pixclock
, &par
->pll
.ics2595
);
2539 err
= aty_var_to_pll_514(var
->pixclock
, &par
->pll
.gx
);
2543 err
= aty_var_to_pll_ct(info
, var
->pixclock
, par
->crtc
.bpp
,
2548 if (var
->accel_flags
& FB_ACCELF_TEXT
)
2549 par
->accel_flags
= FB_ACCELF_TEXT
;
2551 par
->accel_flags
= 0;
2554 if (!fbmon_valid_timings(var
->pixclock
, htotal
, vtotal
, info
))
2561 static int atyfb_encode_var(struct fb_var_screeninfo
*var
,
2562 const struct atyfb_par
*par
,
2563 const struct fb_info_aty
*info
)
2567 memset(var
, 0, sizeof(struct fb_var_screeninfo
));
2569 if ((err
= aty_crtc_to_var(&par
->crtc
, var
)))
2571 if ((Gx
== GX_CHIP_ID
) || (Gx
== CX_CHIP_ID
))
2572 switch (info
->clk_type
) {
2573 case CLK_ATI18818_1
:
2574 var
->pixclock
= aty_pll_18818_to_var(&par
->pll
.ics2595
);
2577 var
->pixclock
= aty_pll_1703_to_var(&par
->pll
.ics2595
);
2580 var
->pixclock
= aty_pll_8398_to_var(&par
->pll
.ics2595
);
2583 var
->pixclock
= aty_pll_408_to_var(&par
->pll
.ics2595
);
2586 var
->pixclock
= aty_pll_gx_to_var(&par
->pll
.gx
, info
);
2590 var
->pixclock
= aty_pll_ct_to_var(&par
->pll
.ct
, info
);
2594 var
->accel_flags
= par
->accel_flags
;
2601 static void set_off_pitch(struct atyfb_par
*par
,
2602 const struct fb_info_aty
*info
)
2604 u32 xoffset
= par
->crtc
.xoffset
;
2605 u32 yoffset
= par
->crtc
.yoffset
;
2606 u32 vxres
= par
->crtc
.vxres
;
2607 u32 bpp
= par
->crtc
.bpp
;
2609 par
->crtc
.off_pitch
= ((yoffset
*vxres
+xoffset
)*bpp
/64) | (vxres
<<19);
2610 aty_st_le32(CRTC_OFF_PITCH
, par
->crtc
.off_pitch
, info
);
2615 * Open/Release the frame buffer device
2618 static int atyfb_open(struct fb_info
*info
, int user
)
2622 struct fb_info_aty
*fb
= (struct fb_info_aty
*)info
;
2638 static int atyfb_release(struct fb_info
*info
, int user
)
2641 struct fb_info_aty
*fb
= (struct fb_info_aty
*)info
;
2644 if (fb
->vtconsole
!= -1)
2645 vt_cons
[fb
->vtconsole
]->vc_mode
= KD_TEXT
;
2658 static int encode_fix(struct fb_fix_screeninfo
*fix
,
2659 const struct atyfb_par
*par
,
2660 const struct fb_info_aty
*info
)
2662 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
2664 strcpy(fix
->id
, atyfb_name
);
2665 fix
->smem_start
= info
->frame_buffer_phys
;
2666 fix
->smem_len
= (u32
)info
->total_vram
;
2668 #ifdef __LITTLE_ENDIAN
2670 * Last page of 8 MB little-endian aperture is MMIO
2671 * FIXME: we should use the auxiliary aperture instead so we can acces the
2672 * full 8 MB of video RAM on 8 MB boards
2674 if (fix
->smem_len
> 0x800000-GUI_RESERVE
)
2675 fix
->smem_len
= 0x800000-GUI_RESERVE
;
2678 * Reg Block 0 (CT-compatible block) is at ati_regbase_phys
2679 * Reg Block 1 (multimedia extensions) is at ati_regbase_phys-0x400
2681 if (Gx
== GX_CHIP_ID
|| Gx
== CX_CHIP_ID
) {
2682 fix
->mmio_start
= info
->ati_regbase_phys
;
2683 fix
->mmio_len
= 0x400;
2684 fix
->accel
= FB_ACCEL_ATI_MACH64GX
;
2685 } else if (Gx
== CT_CHIP_ID
|| Gx
== ET_CHIP_ID
) {
2686 fix
->mmio_start
= info
->ati_regbase_phys
;
2687 fix
->mmio_len
= 0x400;
2688 fix
->accel
= FB_ACCEL_ATI_MACH64CT
;
2689 } else if (Gx
== VT_CHIP_ID
|| Gx
== VU_CHIP_ID
|| Gx
== VV_CHIP_ID
) {
2690 fix
->mmio_start
= info
->ati_regbase_phys
-0x400;
2691 fix
->mmio_len
= 0x800;
2692 fix
->accel
= FB_ACCEL_ATI_MACH64VT
;
2694 fix
->mmio_start
= info
->ati_regbase_phys
-0x400;
2695 fix
->mmio_len
= 0x800;
2696 fix
->accel
= FB_ACCEL_ATI_MACH64GT
;
2698 fix
->type
= FB_TYPE_PACKED_PIXELS
;
2700 fix
->line_length
= par
->crtc
.vxres
*par
->crtc
.bpp
/8;
2701 fix
->visual
= par
->crtc
.bpp
<= 8 ? FB_VISUAL_PSEUDOCOLOR
2702 : FB_VISUAL_DIRECTCOLOR
;
2711 struct fb_var_screeninfo default_var
= {
2712 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
2713 640, 480, 640, 480, 0, 0, 8, 0,
2714 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
2715 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
2716 0, FB_VMODE_NONINTERLACED
2721 * Get the Fixed Part of the Display
2724 static int atyfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
2727 const struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
2728 struct atyfb_par par
;
2731 par
= info
->default_par
;
2733 atyfb_decode_var(&fb_display
[con
].var
, &par
, info
);
2734 encode_fix(fix
, &par
, info
);
2740 * Get the User Defined Part of the Display
2743 static int atyfb_get_var(struct fb_var_screeninfo
*var
, int con
,
2746 const struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
2749 atyfb_encode_var(var
, &info
->default_par
, info
);
2751 *var
= fb_display
[con
].var
;
2756 static void atyfb_set_disp(struct display
*disp
, struct fb_info_aty
*info
,
2760 #ifdef FBCON_HAS_CFB8
2762 info
->dispsw
= accel
? fbcon_aty8
: fbcon_cfb8
;
2763 disp
->dispsw
= &info
->dispsw
;
2766 #ifdef FBCON_HAS_CFB16
2768 info
->dispsw
= accel
? fbcon_aty16
: fbcon_cfb16
;
2769 disp
->dispsw
= &info
->dispsw
;
2770 disp
->dispsw_data
= info
->fbcon_cmap
.cfb16
;
2773 #ifdef FBCON_HAS_CFB24
2775 info
->dispsw
= accel
? fbcon_aty24
: fbcon_cfb24
;
2776 disp
->dispsw
= &info
->dispsw
;
2777 disp
->dispsw_data
= info
->fbcon_cmap
.cfb24
;
2780 #ifdef FBCON_HAS_CFB32
2782 info
->dispsw
= accel
? fbcon_aty32
: fbcon_cfb32
;
2783 disp
->dispsw
= &info
->dispsw
;
2784 disp
->dispsw_data
= info
->fbcon_cmap
.cfb32
;
2788 disp
->dispsw
= &fbcon_dummy
;
2791 info
->dispsw
.cursor
= atyfb_cursor
;
2792 info
->dispsw
.set_font
= atyfb_set_font
;
2798 * Set the User Defined Part of the Display
2801 static int atyfb_set_var(struct fb_var_screeninfo
*var
, int con
,
2804 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
2805 struct atyfb_par par
;
2806 struct display
*display
;
2807 int oldxres
, oldyres
, oldvxres
, oldvyres
, oldbpp
, oldaccel
, accel
, err
;
2808 int activate
= var
->activate
;
2811 display
= &fb_display
[con
];
2813 display
= fb
->disp
; /* used during initialization */
2815 if ((err
= atyfb_decode_var(var
, &par
, info
)))
2818 atyfb_encode_var(var
, &par
, (struct fb_info_aty
*)info
);
2820 if ((activate
& FB_ACTIVATE_MASK
) == FB_ACTIVATE_NOW
) {
2821 oldxres
= display
->var
.xres
;
2822 oldyres
= display
->var
.yres
;
2823 oldvxres
= display
->var
.xres_virtual
;
2824 oldvyres
= display
->var
.yres_virtual
;
2825 oldbpp
= display
->var
.bits_per_pixel
;
2826 oldaccel
= display
->var
.accel_flags
;
2827 display
->var
= *var
;
2828 if (oldxres
!= var
->xres
|| oldyres
!= var
->yres
||
2829 oldvxres
!= var
->xres_virtual
|| oldvyres
!= var
->yres_virtual
||
2830 oldbpp
!= var
->bits_per_pixel
|| oldaccel
!= var
->accel_flags
) {
2831 struct fb_fix_screeninfo fix
;
2833 encode_fix(&fix
, &par
, info
);
2834 display
->screen_base
= (char *)info
->frame_buffer
;
2835 display
->visual
= fix
.visual
;
2836 display
->type
= fix
.type
;
2837 display
->type_aux
= fix
.type_aux
;
2838 display
->ypanstep
= fix
.ypanstep
;
2839 display
->ywrapstep
= fix
.ywrapstep
;
2840 display
->line_length
= fix
.line_length
;
2841 display
->can_soft_blank
= 1;
2842 display
->inverse
= 0;
2843 accel
= var
->accel_flags
& FB_ACCELF_TEXT
;
2844 atyfb_set_disp(display
, info
, par
.crtc
.bpp
, accel
);
2846 display
->scrollmode
= (info
->bus_type
== PCI
) ? SCROLL_YNOMOVE
: 0;
2848 display
->scrollmode
= SCROLL_YREDRAW
;
2849 if (info
->fb_info
.changevar
)
2850 (*info
->fb_info
.changevar
)(con
);
2852 if (!info
->fb_info
.display_fg
||
2853 info
->fb_info
.display_fg
->vc_num
== con
)
2854 atyfb_set_par(&par
, info
);
2855 if (oldbpp
!= var
->bits_per_pixel
) {
2856 if ((err
= fb_alloc_cmap(&display
->cmap
, 0, 0)))
2858 do_install_cmap(con
, &info
->fb_info
);
2867 * Pan or Wrap the Display
2869 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
2872 static int atyfb_pan_display(struct fb_var_screeninfo
*var
, int con
,
2875 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
2876 u32 xres
, yres
, xoffset
, yoffset
;
2877 struct atyfb_par
*par
= &info
->current_par
;
2879 xres
= (((par
->crtc
.h_tot_disp
>>16) & 0xff)+1)*8;
2880 yres
= ((par
->crtc
.v_tot_disp
>>16) & 0x7ff)+1;
2881 xoffset
= (var
->xoffset
+7) & ~7;
2882 yoffset
= var
->yoffset
;
2883 if (xoffset
+xres
> par
->crtc
.vxres
|| yoffset
+yres
> par
->crtc
.vyres
)
2885 par
->crtc
.xoffset
= xoffset
;
2886 par
->crtc
.yoffset
= yoffset
;
2887 set_off_pitch(par
, info
);
2895 static int atyfb_get_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
2896 struct fb_info
*info
)
2898 if (!info
->display_fg
|| con
== info
->display_fg
->vc_num
) /* current console? */
2899 return fb_get_cmap(cmap
, kspc
, atyfb_getcolreg
, info
);
2900 else if (fb_display
[con
].cmap
.len
) /* non default colormap? */
2901 fb_copy_cmap(&fb_display
[con
].cmap
, cmap
, kspc
? 0 : 2);
2903 int size
= fb_display
[con
].var
.bits_per_pixel
== 16 ? 32 : 256;
2904 fb_copy_cmap(fb_default_cmap(size
), cmap
, kspc
? 0 : 2);
2913 static int atyfb_set_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
2914 struct fb_info
*info
)
2917 struct display
*disp
;
2920 disp
= &fb_display
[con
];
2923 if (!disp
->cmap
.len
) { /* no colormap allocated? */
2924 int size
= disp
->var
.bits_per_pixel
== 16 ? 32 : 256;
2925 if ((err
= fb_alloc_cmap(&disp
->cmap
, size
, 0)))
2928 if (!info
->display_fg
|| con
== info
->display_fg
->vc_num
) /* current console? */
2929 return fb_set_cmap(cmap
, kspc
, atyfb_setcolreg
, info
);
2931 fb_copy_cmap(cmap
, &disp
->cmap
, kspc
? 0 : 1);
2937 #define ATYIO_CLKR 0x41545900 /* ATY\00 */
2938 #define ATYIO_CLKW 0x41545901 /* ATY\01 */
2944 u8 mclk_post_div
; /* 1,2,3,4,8 */
2946 u8 vclk_post_div
; /* 1,2,3,4,6,8,12 */
2947 u32 dsp_xclks_per_row
; /* 0-16383 */
2948 u32 dsp_loop_latency
; /* 0-15 */
2949 u32 dsp_precision
; /* 0-7 */
2950 u32 dsp_on
; /* 0-2047 */
2951 u32 dsp_off
; /* 0-2047 */
2955 static int atyfb_ioctl(struct inode
*inode
, struct file
*file
, u_int cmd
,
2956 u_long arg
, int con
, struct fb_info
*info2
)
2958 #if defined(__sparc__) || defined(DEBUG)
2959 struct fb_info_aty
*info
= (struct fb_info_aty
*)info2
;
2960 #endif /* __sparc__ || DEBUG */
2962 struct fbtype fbtyp
;
2963 struct display
*disp
;
2966 disp
= &fb_display
[con
];
2974 fbtyp
.fb_type
= FBTYPE_PCI_GENERIC
;
2975 fbtyp
.fb_width
= info
->current_par
.crtc
.vxres
;
2976 fbtyp
.fb_height
= info
->current_par
.crtc
.vyres
;
2977 fbtyp
.fb_depth
= info
->current_par
.crtc
.bpp
;
2978 fbtyp
.fb_cmsize
= disp
->cmap
.len
;
2979 fbtyp
.fb_size
= info
->total_vram
;
2980 copy_to_user_ret((struct fbtype
*)arg
, &fbtyp
, sizeof(fbtyp
), -EFAULT
);
2982 #endif /* __sparc__ */
2985 if ((Gx
!= GX_CHIP_ID
) && (Gx
!= CX_CHIP_ID
)) {
2987 struct pll_ct
*pll
= &info
->current_par
.pll
.ct
;
2988 u32 dsp_config
= pll
->dsp_config
;
2989 u32 dsp_on_off
= pll
->dsp_on_off
;
2990 clk
.ref_clk_per
= info
->ref_clk_per
;
2991 clk
.pll_ref_div
= pll
->pll_ref_div
;
2992 clk
.mclk_fb_div
= pll
->mclk_fb_div
;
2993 clk
.mclk_post_div
= pll
->mclk_post_div_real
;
2994 clk
.vclk_fb_div
= pll
->vclk_fb_div
;
2995 clk
.vclk_post_div
= pll
->vclk_post_div_real
;
2996 clk
.dsp_xclks_per_row
= dsp_config
& 0x3fff;
2997 clk
.dsp_loop_latency
= (dsp_config
>>16) & 0xf;
2998 clk
.dsp_precision
= (dsp_config
>>20) & 7;
2999 clk
.dsp_on
= dsp_on_off
& 0x7ff;
3000 clk
.dsp_off
= (dsp_on_off
>>16) & 0x7ff;
3001 copy_to_user_ret((struct atyclk
*)arg
, &clk
, sizeof(clk
),
3007 if ((Gx
!= GX_CHIP_ID
) && (Gx
!= CX_CHIP_ID
)) {
3009 struct pll_ct
*pll
= &info
->current_par
.pll
.ct
;
3010 copy_from_user_ret(&clk
, (struct atyclk
*)arg
, sizeof(clk
),
3012 info
->ref_clk_per
= clk
.ref_clk_per
;
3013 pll
->pll_ref_div
= clk
.pll_ref_div
;
3014 pll
->mclk_fb_div
= clk
.mclk_fb_div
;
3015 pll
->mclk_post_div_real
= clk
.mclk_post_div
;
3016 pll
->vclk_fb_div
= clk
.vclk_fb_div
;
3017 pll
->vclk_post_div_real
= clk
.vclk_post_div
;
3018 pll
->dsp_config
= (clk
.dsp_xclks_per_row
& 0x3fff) |
3019 ((clk
.dsp_loop_latency
& 0xf)<<16) |
3020 ((clk
.dsp_precision
& 7)<<20);
3021 pll
->dsp_on_off
= (clk
.dsp_on
& 0x7ff) |
3022 ((clk
.dsp_off
& 0x7ff)<<16);
3023 aty_calc_pll_ct(info
, pll
);
3024 aty_set_pll_ct(info
, pll
);
3035 static int atyfb_rasterimg(struct fb_info
*info
, int start
)
3037 struct fb_info_aty
*fb
= (struct fb_info_aty
*)info
;
3039 if (fb
->blitter_may_be_busy
)
3045 static int atyfb_mmap(struct fb_info
*info
, struct file
*file
,
3046 struct vm_area_struct
*vma
)
3048 struct fb_info_aty
*fb
= (struct fb_info_aty
*)info
;
3049 unsigned int size
, page
, map_size
= 0;
3050 unsigned long map_offset
= 0;
3056 size
= vma
->vm_end
- vma
->vm_start
;
3057 if (vma
->vm_offset
& ~PAGE_MASK
)
3060 /* To stop the swapper from even considering these pages. */
3061 vma
->vm_flags
|= (VM_SHM
| VM_LOCKED
);
3063 if (((vma
->vm_offset
== 0) && (size
== fb
->total_vram
)) ||
3064 ((vma
->vm_offset
== fb
->total_vram
) && (size
== PAGE_SIZE
)))
3065 vma
->vm_offset
+= 0x8000000000000000UL
;
3068 /* Align it as much as desirable */
3070 unsigned long j
, align
;
3073 map_offset
= vma
->vm_offset
+size
;
3074 for (i
= 0; fb
->mmap_map
[i
].size
; i
++) {
3075 if (fb
->mmap_map
[i
].voff
< vma
->vm_offset
)
3077 if (fb
->mmap_map
[i
].voff
>= map_offset
)
3080 fb
->mmap_map
[i
].size
> fb
->mmap_map
[max
].size
)
3084 j
= fb
->mmap_map
[max
].size
;
3085 if (fb
->mmap_map
[max
].voff
+ j
> map_offset
)
3086 j
= map_offset
- fb
->mmap_map
[max
].voff
;
3087 for (align
= 0x400000; align
> PAGE_SIZE
; align
>>= 3)
3089 !(fb
->mmap_map
[max
].poff
& (align
- 1)))
3091 if (align
> PAGE_SIZE
) {
3093 align
= j
- ((vma
->vm_start
3094 + fb
->mmap_map
[max
].voff
3095 - vma
->vm_offset
) & (j
- 1));
3097 struct vm_area_struct
*vmm
;
3099 vmm
= find_vma(current
->mm
,
3101 if (!vmm
|| vmm
->vm_start
3102 >= vma
->vm_end
+ align
) {
3103 vma
->vm_start
+= align
;
3104 vma
->vm_end
+= align
;
3112 /* Each page, see which map applies */
3113 for (page
= 0; page
< size
; ) {
3115 for (i
= 0; fb
->mmap_map
[i
].size
; i
++) {
3116 unsigned long start
= fb
->mmap_map
[i
].voff
;
3117 unsigned long end
= start
+ fb
->mmap_map
[i
].size
;
3118 unsigned long offset
= vma
->vm_offset
+ page
;
3125 map_size
= fb
->mmap_map
[i
].size
- (offset
- start
);
3126 map_offset
= fb
->mmap_map
[i
].poff
+ (offset
- start
);
3133 if (page
+ map_size
> size
)
3134 map_size
= size
- page
;
3136 pgprot_val(vma
->vm_page_prot
) &= ~(fb
->mmap_map
[i
].prot_mask
);
3137 pgprot_val(vma
->vm_page_prot
) |= fb
->mmap_map
[i
].prot_flag
;
3139 if (remap_page_range(vma
->vm_start
+ page
, map_offset
,
3140 map_size
, vma
->vm_page_prot
))
3149 vma
->vm_flags
|= VM_IO
;
3152 int lastconsole
= 0;
3154 if (info
->display_fg
)
3155 lastconsole
= info
->display_fg
->vc_num
;
3157 if (fb
->consolecnt
&& fb_display
[lastconsole
].fb_info
== info
) {
3158 fb
->vtconsole
= lastconsole
;
3159 vt_cons
[lastconsole
]->vc_mode
= KD_GRAPHICS
;
3172 static void atyfb_save_palette(struct fb_info
*fb
, int enter
)
3174 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
3177 for (i
= 0; i
< 256; i
++) {
3178 tmp
= aty_ld_8(DAC_CNTL
, info
) & 0xfc;
3179 if (Gx
== GT_CHIP_ID
|| Gx
== GU_CHIP_ID
|| Gx
== GV_CHIP_ID
||
3180 Gx
== GW_CHIP_ID
|| Gx
== GZ_CHIP_ID
|| Gx
== LG_CHIP_ID
||
3181 Gx
== GB_CHIP_ID
|| Gx
== GD_CHIP_ID
|| Gx
== GI_CHIP_ID
||
3182 Gx
== GP_CHIP_ID
|| Gx
== GQ_CHIP_ID
)
3184 aty_st_8(DAC_CNTL
, tmp
, info
);
3185 aty_st_8(DAC_MASK
, 0xff, info
);
3187 scale
= ((Gx
!= GX_CHIP_ID
) && (Gx
!= CX_CHIP_ID
) &&
3188 (info
->current_par
.crtc
.bpp
== 16)) ? 3 : 0;
3189 info
->aty_cmap_regs
->rindex
= i
<< scale
;
3191 atyfb_save
.r
[enter
][i
] = info
->aty_cmap_regs
->lut
;
3193 atyfb_save
.g
[enter
][i
] = info
->aty_cmap_regs
->lut
;
3195 atyfb_save
.b
[enter
][i
] = info
->aty_cmap_regs
->lut
;
3197 info
->aty_cmap_regs
->windex
= i
<< scale
;
3199 info
->aty_cmap_regs
->lut
= atyfb_save
.r
[1-enter
][i
];
3201 info
->aty_cmap_regs
->lut
= atyfb_save
.g
[1-enter
][i
];
3203 info
->aty_cmap_regs
->lut
= atyfb_save
.b
[1-enter
][i
];
3208 static void atyfb_palette(int enter
)
3210 struct fb_info_aty
*info
;
3211 struct atyfb_par
*par
;
3215 for (i
= 0; i
< MAX_NR_CONSOLES
; i
++) {
3218 d
->fb_info
->fbops
== &atyfb_ops
&&
3219 d
->fb_info
->display_fg
&&
3220 d
->fb_info
->display_fg
->vc_num
== i
) {
3221 atyfb_save_palette(d
->fb_info
, enter
);
3222 info
= (struct fb_info_aty
*)d
->fb_info
;
3223 par
= &info
->current_par
;
3225 atyfb_save
.yoffset
= par
->crtc
.yoffset
;
3226 par
->crtc
.yoffset
= 0;
3227 set_off_pitch(par
, info
);
3229 par
->crtc
.yoffset
= atyfb_save
.yoffset
;
3230 set_off_pitch(par
, info
);
3236 #endif /* __sparc__ */
3242 static int __init
aty_init(struct fb_info_aty
*info
, const char *name
)
3247 struct fb_var_screeninfo var
;
3248 struct display
*disp
;
3249 const char *chipname
= NULL
, *ramname
= NULL
, *xtal
;
3250 int pll
, mclk
, gtb_memsize
;
3256 info
->aty_cmap_regs
= (struct aty_cmap_regs
*)(info
->ati_regbase
+0xc0);
3258 info
->aty_cmap_regs
= __va(info
->aty_cmap_regs
);
3260 chip_id
= aty_ld_le32(CONFIG_CHIP_ID
, info
);
3261 Gx
= chip_id
& CFG_CHIP_TYPE
;
3262 Rev
= (chip_id
& CFG_CHIP_REV
)>>24;
3263 for (j
= 0; j
< (sizeof(aty_features
)/sizeof(*aty_features
)); j
++)
3264 if (aty_features
[j
].chip_type
== Gx
) {
3265 chipname
= aty_features
[j
].name
;
3266 info
->dac_type
= (aty_ld_le32(DAC_CNTL
, info
) >> 16) & 0x07;
3270 printk("atyfb: Unknown mach64 0x%04x\n", Gx
);
3273 printk("atyfb: %s [0x%04x rev 0x%02x] ", chipname
, Gx
, Rev
);
3274 if ((Gx
== GX_CHIP_ID
) || (Gx
== CX_CHIP_ID
)) {
3275 info
->bus_type
= (aty_ld_le32(CONFIG_STAT0
, info
) >> 0) & 0x07;
3276 info
->ram_type
= (aty_ld_le32(CONFIG_STAT0
, info
) >> 3) & 0x07;
3277 ramname
= aty_gx_ram
[info
->ram_type
];
3278 /* FIXME: clockchip/RAMDAC probing? */
3280 info
->clk_type
= CLK_ATI18818_1
;
3281 info
->dac_type
= (aty_ld_le32(CONFIG_STAT0
, info
) >> 9) & 0x07;
3282 if (info
->dac_type
== 0x07)
3283 info
->dac_subtype
= DAC_ATT20C408
;
3285 info
->dac_subtype
= (aty_ld_8(SCRATCH_REG1
+ 1, info
) & 0xF0) |
3288 info
->dac_type
= DAC_IBMRGB514
;
3289 info
->dac_subtype
= DAC_IBMRGB514
;
3290 info
->clk_type
= CLK_IBMRGB514
;
3296 info
->bus_type
= PCI
;
3297 info
->ram_type
= (aty_ld_le32(CONFIG_STAT0
, info
) & 0x07);
3298 ramname
= aty_ct_ram
[info
->ram_type
];
3299 info
->dac_type
= DAC_INTERNAL
;
3300 info
->dac_subtype
= DAC_INTERNAL
;
3301 info
->clk_type
= CLK_INTERNAL
;
3302 if ((Gx
== CT_CHIP_ID
) || (Gx
== ET_CHIP_ID
)) {
3306 mclk
= info
->ram_type
>= SDRAM
? 67 : 63;
3307 if ((Gx
== VT_CHIP_ID
) && (Rev
== 0x08)) {
3310 } else if (((Gx
== VT_CHIP_ID
) && ((Rev
== 0x40) ||
3312 ((Gx
== VT_CHIP_ID
) && ((Rev
== 0x01) ||
3317 } else if (Gx
== VV_CHIP_ID
) {
3321 } else if (Gx
== VT_CHIP_ID
) {
3325 } else if ((Gx
== GT_CHIP_ID
) && (Rev
& 0x01)) {
3328 } else if (((Gx
== GT_CHIP_ID
) && (Rev
& 0x02)) ||
3329 (Gx
== GU_CHIP_ID
)) {
3332 } else if (Gx
== GV_CHIP_ID
|| Gx
== GW_CHIP_ID
||
3337 } else if (Gx
== GB_CHIP_ID
|| Gx
== GD_CHIP_ID
||
3338 Gx
== GI_CHIP_ID
|| Gx
== GP_CHIP_ID
||
3339 Gx
== GQ_CHIP_ID
|| Gx
== LB_CHIP_ID
||
3340 Gx
== LD_CHIP_ID
|| Gx
== LG_CHIP_ID
||
3341 Gx
== LI_CHIP_ID
|| Gx
== LP_CHIP_ID
) {
3342 /* RAGE PRO or LT PRO */
3353 info
->ref_clk_per
= 1000000000000ULL/14318180;
3355 if (!(Gx
== GX_CHIP_ID
|| Gx
== CX_CHIP_ID
|| Gx
== CT_CHIP_ID
||
3357 ((Gx
== VT_CHIP_ID
|| Gx
== GT_CHIP_ID
) && !(Rev
& 0x07))) &&
3358 (pll_ref_div
= aty_ld_pll(PLL_REF_DIV
, info
))) {
3360 diff1
= 510*14/pll_ref_div
-pll
;
3361 diff2
= 510*29/pll_ref_div
-pll
;
3366 if (diff2
< diff1
) {
3367 info
->ref_clk_per
= 1000000000000ULL/29498928;
3372 i
= aty_ld_le32(MEM_CNTL
, info
);
3373 gtb_memsize
= !(Gx
== GX_CHIP_ID
|| Gx
== CX_CHIP_ID
|| Gx
== CT_CHIP_ID
||
3375 ((Gx
== VT_CHIP_ID
|| Gx
== GT_CHIP_ID
) && !(Rev
& 0x07)));
3377 switch (i
& 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */
3379 info
->total_vram
= 0x80000;
3382 info
->total_vram
= 0x100000;
3384 case MEM_SIZE_2M_GTB
:
3385 info
->total_vram
= 0x200000;
3387 case MEM_SIZE_4M_GTB
:
3388 info
->total_vram
= 0x400000;
3390 case MEM_SIZE_6M_GTB
:
3391 info
->total_vram
= 0x600000;
3393 case MEM_SIZE_8M_GTB
:
3394 info
->total_vram
= 0x800000;
3397 info
->total_vram
= 0x80000;
3400 switch (i
& MEM_SIZE_ALIAS
) {
3402 info
->total_vram
= 0x80000;
3405 info
->total_vram
= 0x100000;
3408 info
->total_vram
= 0x200000;
3411 info
->total_vram
= 0x400000;
3414 info
->total_vram
= 0x600000;
3417 info
->total_vram
= 0x800000;
3420 info
->total_vram
= 0x80000;
3423 if (Gx
== GI_CHIP_ID
) {
3424 if (aty_ld_le32(CONFIG_STAT1
, info
) & 0x40000000)
3425 info
->total_vram
+= 0x400000;
3429 info
->total_vram
= default_vram
*1024;
3430 i
= i
& ~(gtb_memsize
? 0xF : MEM_SIZE_ALIAS
);
3431 if (info
->total_vram
<= 0x80000)
3433 else if (info
->total_vram
<= 0x100000)
3435 else if (info
->total_vram
<= 0x200000)
3436 i
|= gtb_memsize
? MEM_SIZE_2M_GTB
: MEM_SIZE_2M
;
3437 else if (info
->total_vram
<= 0x400000)
3438 i
|= gtb_memsize
? MEM_SIZE_4M_GTB
: MEM_SIZE_4M
;
3439 else if (info
->total_vram
<= 0x600000)
3440 i
|= gtb_memsize
? MEM_SIZE_6M_GTB
: MEM_SIZE_6M
;
3442 i
|= gtb_memsize
? MEM_SIZE_8M_GTB
: MEM_SIZE_8M
;
3443 aty_st_le32(MEM_CNTL
, i
, info
);
3448 mclk
= default_mclk
;
3450 printk("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK\n",
3451 info
->total_vram
== 0x80000 ? 512 : (info
->total_vram
>> 20),
3452 info
->total_vram
== 0x80000 ? 'K' : 'M', ramname
, xtal
, pll
, mclk
);
3455 info
->mem_refresh_rate
= 0; /* 000 = 10 Mhz - 43 Mhz */
3457 info
->mem_refresh_rate
= 1; /* 001 = 44 Mhz - 49 Mhz */
3459 info
->mem_refresh_rate
= 2; /* 010 = 50 Mhz - 54 Mhz */
3461 info
->mem_refresh_rate
= 3; /* 011 = 55 Mhz - 65 Mhz */
3463 info
->mem_refresh_rate
= 4; /* 100 = 66 Mhz - 74 Mhz */
3465 info
->mem_refresh_rate
= 5; /* 101 = 75 Mhz - 79 Mhz */
3466 else if (mclk
< 100)
3467 info
->mem_refresh_rate
= 6; /* 110 = 80 Mhz - 100 Mhz */
3469 info
->mem_refresh_rate
= 7; /* 111 = 100 Mhz and above */
3470 info
->pll_per
= 1000000/pll
;
3471 info
->mclk_per
= 1000000/mclk
;
3474 if ((Gx
!= GX_CHIP_ID
) && (Gx
!= CX_CHIP_ID
)) {
3476 printk("BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
3477 "DSP_CONFIG DSP_ON_OFF\n"
3478 "%08x %08x %08x %08x %08x %08x %08x\n"
3480 aty_ld_le32(BUS_CNTL
, info
), aty_ld_le32(DAC_CNTL
, info
),
3481 aty_ld_le32(MEM_CNTL
, info
), aty_ld_le32(EXT_MEM_CNTL
, info
),
3482 aty_ld_le32(CRTC_GEN_CNTL
, info
), aty_ld_le32(DSP_CONFIG
, info
),
3483 aty_ld_le32(DSP_ON_OFF
, info
));
3484 for (i
= 0; i
< 16; i
++)
3485 printk(" %02x", aty_ld_pll(i
, info
));
3490 if (info
->bus_type
== ISA
)
3491 if ((info
->total_vram
== 0x400000) || (info
->total_vram
== 0x800000)) {
3492 /* protect GUI-regs if complete Aperture is VRAM */
3493 info
->total_vram
-= GUI_RESERVE
;
3498 strcpy(info
->fb_info
.modename
, atyfb_name
);
3499 info
->fb_info
.node
= -1;
3500 info
->fb_info
.fbops
= &atyfb_ops
;
3501 info
->fb_info
.disp
= disp
;
3502 strcpy(info
->fb_info
.fontname
, fontname
);
3503 info
->fb_info
.changevar
= NULL
;
3504 info
->fb_info
.switch_con
= &atyfbcon_switch
;
3505 info
->fb_info
.updatevar
= &atyfbcon_updatevar
;
3506 info
->fb_info
.blank
= &atyfbcon_blank
;
3507 info
->fb_info
.flags
= FBINFO_FLAG_DEFAULT
;
3512 memset(&var
, 0, sizeof(var
));
3515 * FIXME: The NVRAM stuff should be put in a Mac-specific file, as it
3516 * applies to all Mac video cards
3519 if (!mac_find_mode(&var
, &info
->fb_info
, mode_option
, 8))
3523 if (default_vmode
== VMODE_NVRAM
) {
3524 default_vmode
= nvram_read_byte(NV_VMODE
);
3525 if (default_vmode
<= 0 || default_vmode
> VMODE_MAX
)
3526 default_vmode
= VMODE_CHOOSE
;
3529 if (default_vmode
== VMODE_CHOOSE
) {
3530 if (Gx
== LG_CHIP_ID
)
3531 /* G3 PowerBook with 1024x768 LCD */
3532 default_vmode
= VMODE_1024_768_60
;
3534 sense
= read_aty_sense(info
);
3535 default_vmode
= mac_map_monitor_sense(sense
);
3538 if (default_vmode
<= 0 || default_vmode
> VMODE_MAX
)
3539 default_vmode
= VMODE_640_480_60
;
3541 if (default_cmode
== CMODE_NVRAM
)
3542 default_cmode
= nvram_read_byte(NV_CMODE
);
3544 if (default_cmode
< CMODE_8
|| default_cmode
> CMODE_32
)
3545 default_cmode
= CMODE_8
;
3546 if (mac_vmode_to_var(default_vmode
, default_cmode
, &var
))
3549 #else /* !CONFIG_PMAC */
3552 if (!fb_find_mode(&var
, &info
->fb_info
, mode_option
, NULL
, 0, NULL
, 8))
3557 if (!fb_find_mode(&var
, &info
->fb_info
, mode_option
, NULL
, 0, NULL
, 8))
3559 #endif /* !__sparc__ */
3560 #endif /* !CONFIG_PMAC */
3561 #endif /* !MODULE */
3563 var
.accel_flags
&= ~FB_ACCELF_TEXT
;
3565 var
.accel_flags
|= FB_ACCELF_TEXT
;
3567 if (var
.yres
== var
.yres_virtual
) {
3568 u32 vram
= (info
->total_vram
- (PAGE_SIZE
<< 2));
3569 var
.yres_virtual
= ((vram
* 8) / var
.bits_per_pixel
) / var
.xres_virtual
;
3570 if (var
.yres_virtual
< var
.yres
)
3571 var
.yres_virtual
= var
.yres
;
3574 if (atyfb_decode_var(&var
, &info
->default_par
, info
)) {
3575 printk("atyfb: can't set default video mode\n");
3580 atyfb_save_palette(&info
->fb_info
, 0);
3582 for (j
= 0; j
< 16; j
++) {
3584 info
->palette
[j
].red
= default_red
[k
];
3585 info
->palette
[j
].green
= default_grn
[k
];
3586 info
->palette
[j
].blue
= default_blu
[k
];
3589 if (Gx
!= GX_CHIP_ID
&& Gx
!= CX_CHIP_ID
) {
3590 info
->cursor
= aty_init_cursor(info
);
3592 info
->dispsw
.cursor
= atyfb_cursor
;
3593 info
->dispsw
.set_font
= atyfb_set_font
;
3597 atyfb_set_var(&var
, -1, &info
->fb_info
);
3599 if (register_framebuffer(&info
->fb_info
) < 0)
3602 info
->next
= fb_list
;
3605 printk("fb%d: %s frame buffer device on %s\n",
3606 GET_FB_IDX(info
->fb_info
.node
), atyfb_name
, name
);
3610 int __init
atyfb_init(void)
3612 #if defined(CONFIG_FB_OF)
3613 /* We don't want to be called like this. */
3614 /* We rely on Open Firmware (offb) instead. */
3615 #elif defined(CONFIG_PCI)
3616 struct pci_dev
*pdev
;
3617 struct fb_info_aty
*info
;
3620 extern void (*prom_palette
) (int);
3621 extern int con_is_present(void);
3622 struct pcidev_cookie
*pcp
;
3628 /* Do not attach when we have a serial console. */
3629 if (!con_is_present())
3635 for (pdev
= pci_devices
; pdev
; pdev
= pdev
->next
) {
3636 if (((pdev
->class >> 16) == PCI_BASE_CLASS_DISPLAY
) &&
3637 (pdev
->vendor
== PCI_VENDOR_ID_ATI
)) {
3638 struct resource
*rp
;
3640 info
= kmalloc(sizeof(struct fb_info_aty
), GFP_ATOMIC
);
3642 printk("atyfb_init: can't alloc fb_info_aty\n");
3645 memset(info
, 0, sizeof(struct fb_info_aty
));
3647 rp
= &pdev
->resource
[0];
3648 if (rp
->flags
& IORESOURCE_IO
)
3649 rp
= &pdev
->resource
[1];
3656 * Map memory-mapped registers.
3658 info
->ati_regbase
= addr
+ 0x7ffc00UL
;
3659 info
->ati_regbase_phys
= addr
+ 0x7ffc00UL
;
3662 * Map in big-endian aperture.
3664 info
->frame_buffer
= (unsigned long) __va(addr
+ 0x800000UL
);
3665 info
->frame_buffer_phys
= addr
+ 0x800000UL
;
3668 * Figure mmap addresses from PCI config space.
3669 * Split Framebuffer in big- and little-endian halfs.
3671 for (i
= 0; i
< 6 && pdev
->resource
[i
].start
; i
++)
3675 info
->mmap_map
= kmalloc(j
* sizeof(*info
->mmap_map
), GFP_ATOMIC
);
3676 if (!info
->mmap_map
) {
3677 printk("atyfb_init: can't alloc mmap_map\n");
3681 memset(info
->mmap_map
, 0, j
* sizeof(*info
->mmap_map
));
3683 for (i
= 0, j
= 2; i
< 6 && pdev
->resource
[i
].start
; i
++) {
3684 struct resource
*rp
= &pdev
->resource
[i
];
3685 int io
, breg
= PCI_BASE_ADDRESS_0
+ (i
<< 2);
3691 io
= (rp
->flags
& IORESOURCE_IO
);
3693 size
= rp
->end
- base
+ 1;
3695 pci_read_config_dword(pdev
, breg
, &pbase
);
3701 * Map the framebuffer a second time, this time without
3702 * the braindead _PAGE_IE setting. This is used by the
3703 * fixed Xserver, but we need to maintain the old mapping
3704 * to stay compatible with older ones...
3707 info
->mmap_map
[j
].voff
= (pbase
+ 0x10000000) & PAGE_MASK
;
3708 info
->mmap_map
[j
].poff
= base
& PAGE_MASK
;
3709 info
->mmap_map
[j
].size
= (size
+ ~PAGE_MASK
) & PAGE_MASK
;
3710 info
->mmap_map
[j
].prot_mask
= _PAGE_CACHE
;
3711 info
->mmap_map
[j
].prot_flag
= _PAGE_E
;
3716 * Here comes the old framebuffer mapping with _PAGE_IE
3717 * set for the big endian half of the framebuffer...
3720 info
->mmap_map
[j
].voff
= (pbase
+ 0x800000) & PAGE_MASK
;
3721 info
->mmap_map
[j
].poff
= (base
+0x800000) & PAGE_MASK
;
3722 info
->mmap_map
[j
].size
= 0x800000;
3723 info
->mmap_map
[j
].prot_mask
= _PAGE_CACHE
;
3724 info
->mmap_map
[j
].prot_flag
= _PAGE_E
|_PAGE_IE
;
3729 info
->mmap_map
[j
].voff
= pbase
& PAGE_MASK
;
3730 info
->mmap_map
[j
].poff
= base
& PAGE_MASK
;
3731 info
->mmap_map
[j
].size
= (size
+ ~PAGE_MASK
) & PAGE_MASK
;
3732 info
->mmap_map
[j
].prot_mask
= _PAGE_CACHE
;
3733 info
->mmap_map
[j
].prot_flag
= _PAGE_E
;
3738 * Fix PROMs idea of MEM_CNTL settings...
3740 mem
= aty_ld_le32(MEM_CNTL
, info
);
3741 chip_id
= aty_ld_le32(CONFIG_CHIP_ID
, info
);
3742 if (((chip_id
& CFG_CHIP_TYPE
) == VT_CHIP_ID
) &&
3743 !((chip_id
>> 24) & 1)) {
3744 switch (mem
& 0x0f) {
3746 mem
= (mem
& ~(0x0f)) | 2;
3749 mem
= (mem
& ~(0x0f)) | 3;
3752 mem
= (mem
& ~(0x0f)) | 4;
3755 mem
= (mem
& ~(0x0f)) | 5;
3760 if ((aty_ld_le32(CONFIG_STAT0
, info
) & 7) >= SDRAM
)
3761 mem
&= ~(0x00700000);
3763 mem
&= ~(0xcf80e000); /* Turn off all undocumented bits. */
3764 aty_st_le32(MEM_CNTL
, mem
, info
);
3767 * If this is the console device, we will set default video
3768 * settings to what the PROM left us with.
3770 node
= prom_getchild(prom_root_node
);
3771 node
= prom_searchsiblings(node
, "aliases");
3773 len
= prom_getproperty(node
, "screen", prop
, sizeof(prop
));
3776 node
= prom_finddevice(prop
);
3782 pcp
= pdev
->sysdata
;
3783 if (node
== pcp
->prom_node
) {
3785 struct fb_var_screeninfo
*var
= &default_var
;
3786 unsigned int N
, P
, Q
, M
, T
;
3787 u32 v_total
, h_total
;
3792 crtc
.vxres
= prom_getintdefault(node
, "width", 1024);
3793 crtc
.vyres
= prom_getintdefault(node
, "height", 768);
3794 crtc
.bpp
= prom_getintdefault(node
, "depth", 8);
3795 crtc
.xoffset
= crtc
.yoffset
= 0;
3796 crtc
.h_tot_disp
= aty_ld_le32(CRTC_H_TOTAL_DISP
, info
);
3797 crtc
.h_sync_strt_wid
= aty_ld_le32(CRTC_H_SYNC_STRT_WID
, info
);
3798 crtc
.v_tot_disp
= aty_ld_le32(CRTC_V_TOTAL_DISP
, info
);
3799 crtc
.v_sync_strt_wid
= aty_ld_le32(CRTC_V_SYNC_STRT_WID
, info
);
3800 crtc
.gen_cntl
= aty_ld_le32(CRTC_GEN_CNTL
, info
);
3801 aty_crtc_to_var(&crtc
, var
);
3803 h_total
= var
->xres
+ var
->right_margin
+
3804 var
->hsync_len
+ var
->left_margin
;
3805 v_total
= var
->yres
+ var
->lower_margin
+
3806 var
->vsync_len
+ var
->upper_margin
;
3809 * Read the PLL to figure actual Refresh Rate.
3811 clock_cntl
= aty_ld_8(CLOCK_CNTL
, info
);
3812 /* printk("atyfb: CLOCK_CNTL: %02x\n", clock_cntl); */
3813 for (i
= 0; i
< 16; i
++)
3814 pll_regs
[i
] = aty_ld_pll(i
, info
);
3817 * PLL Reference Devider M:
3822 * PLL Feedback Devider N (Dependant on CLOCK_CNTL):
3824 N
= pll_regs
[7 + (clock_cntl
& 3)];
3827 * PLL Post Devider P (Dependant on CLOCK_CNTL):
3829 P
= 1 << (pll_regs
[6] >> ((clock_cntl
& 3) << 1));
3843 * where R is XTALIN (= 14318 kHz).
3845 T
= 2 * Q
* 14318 / M
;
3847 default_var
.pixclock
= 1000000000 / T
;
3850 #else /* __sparc__ */
3852 info
->ati_regbase_phys
= 0x7ff000 + addr
;
3853 info
->ati_regbase
= (unsigned long)
3854 ioremap(info
->ati_regbase_phys
, 0x1000);
3856 if(!info
->ati_regbase
) {
3861 info
->ati_regbase_phys
+= 0xc00;
3862 info
->ati_regbase
+= 0xc00;
3865 * Enable memory-space accesses using config-space
3868 pci_read_config_word(pdev
, PCI_COMMAND
, &tmp
);
3869 if (!(tmp
& PCI_COMMAND_MEMORY
)) {
3870 tmp
|= PCI_COMMAND_MEMORY
;
3871 pci_write_config_word(pdev
, PCI_COMMAND
, tmp
);
3875 /* Use the big-endian aperture */
3879 /* Map in frame buffer */
3880 info
->frame_buffer_phys
= addr
;
3881 info
->frame_buffer
= (unsigned long)ioremap(addr
, 0x800000);
3883 if(!info
->frame_buffer
) {
3888 #endif /* __sparc__ */
3890 if (!aty_init(info
, "PCI")) {
3892 kfree(info
->mmap_map
);
3899 prom_palette
= atyfb_palette
;
3902 * Add /dev/fb mmap values.
3904 info
->mmap_map
[0].voff
= 0x8000000000000000UL
;
3905 info
->mmap_map
[0].poff
= __pa(info
->frame_buffer
& PAGE_MASK
);
3906 info
->mmap_map
[0].size
= info
->total_vram
;
3907 info
->mmap_map
[0].prot_mask
= _PAGE_CACHE
;
3908 info
->mmap_map
[0].prot_flag
= _PAGE_E
;
3909 info
->mmap_map
[1].voff
= info
->mmap_map
[0].voff
+ info
->total_vram
;
3910 info
->mmap_map
[1].poff
= info
->ati_regbase
& PAGE_MASK
;
3911 info
->mmap_map
[1].size
= PAGE_SIZE
;
3912 info
->mmap_map
[1].prot_mask
= _PAGE_CACHE
;
3913 info
->mmap_map
[1].prot_flag
= _PAGE_E
;
3914 #endif /* __sparc__ */
3918 #elif defined(CONFIG_ATARI)
3921 struct fb_info_aty
*info
;
3923 for (m64_num
= 0; m64_num
< mach64_count
; m64_num
++) {
3924 if (!phys_vmembase
[m64_num
] || !phys_size
[m64_num
] ||
3925 !phys_guiregbase
[m64_num
]) {
3926 printk(" phys_*[%d] parameters not set => returning early. \n",
3931 info
= kmalloc(sizeof(struct fb_info_aty
), GFP_ATOMIC
);
3933 printk("atyfb_init: can't alloc fb_info_aty\n");
3936 memset(info
, 0, sizeof(struct fb_info_aty
));
3939 * Map the video memory (physical address given) to somewhere in the
3940 * kernel address space.
3942 info
->frame_buffer
= ioremap(phys_vmembase
[m64_num
], phys_size
[m64_num
]);
3943 info
->frame_buffer_phys
= info
->frame_buffer
; /* Fake! */
3944 info
->ati_regbase
= ioremap(phys_guiregbase
[m64_num
], 0x10000)+0xFC00ul
;
3945 info
->ati_regbase_phys
= info
->ati_regbase
; /* Fake! */
3947 aty_st_le32(CLOCK_CNTL
, 0x12345678, info
);
3948 clock_r
= aty_ld_le32(CLOCK_CNTL
, info
);
3950 switch (clock_r
& 0x003F) {
3952 info
->clk_wr_offset
= 3; /* */
3955 info
->clk_wr_offset
= 2; /* Medusa ST-IO ISA Adapter etc. */
3958 info
->clk_wr_offset
= 1; /* */
3961 info
->clk_wr_offset
= 0; /* Panther 1 ISA Adapter (Gerald) */
3965 if (!aty_init(info
, "ISA bus")) {
3967 /* This is insufficient! kernel_map has added two large chunks!! */
3971 #endif /* CONFIG_ATARI */
3976 void __init
atyfb_of_init(struct device_node
*dp
)
3981 struct fb_info_aty
*info
;
3984 if (device_is_compatible(dp
, "ATY,264LTPro")) {
3985 /* XXX kludge for now */
3986 if (dp
->name
== 0 || strcmp(dp
->name
, "ATY,264LTProA") != 0
3991 switch (dp
->n_addrs
) {
3995 addr
= dp
->addrs
[0].address
;
3998 addr
= dp
->addrs
[1].address
;
4001 printk("Warning: got %d adresses for ATY:\n", dp
->n_addrs
);
4002 for (i
= 0; i
< dp
->n_addrs
; i
++)
4003 printk(" %08x-%08x", dp
->addrs
[i
].address
,
4004 dp
->addrs
[i
].address
+dp
->addrs
[i
].size
-1);
4010 info
= kmalloc(sizeof(struct fb_info_aty
), GFP_ATOMIC
);
4012 printk("atyfb_of_init: can't alloc fb_info_aty\n");
4015 memset(info
, 0, sizeof(struct fb_info_aty
));
4017 info
->ati_regbase_phys
= 0x7ff000+addr
;
4018 info
->ati_regbase
= (unsigned long)ioremap(info
->ati_regbase_phys
,
4021 if(! info
->ati_regbase
) {
4022 printk("atyfb_of_init: ioremap() returned NULL\n");
4027 info
->ati_regbase_phys
+= 0xc00;
4028 info
->ati_regbase
+= 0xc00;
4030 /* enable memory-space accesses using config-space command register */
4031 if (pci_device_loc(dp
, &bus
, &devfn
) == 0) {
4032 pcibios_read_config_word(bus
, devfn
, PCI_COMMAND
, &cmd
);
4033 if (cmd
!= 0xffff) {
4034 cmd
|= PCI_COMMAND_MEMORY
;
4035 pcibios_write_config_word(bus
, devfn
, PCI_COMMAND
, cmd
);
4040 /* Use the big-endian aperture */
4044 /* Map in frame buffer */
4045 info
->frame_buffer_phys
= addr
;
4046 info
->frame_buffer
= (unsigned long)ioremap(addr
, 0x800000);
4048 if(! info
->frame_buffer
) {
4049 printk("atyfb_of_init: ioremap() returned NULL\n");
4054 if (!aty_init(info
, dp
->full_name
)) {
4059 #ifdef CONFIG_PMAC_PBOOK
4060 if (first_display
== NULL
)
4061 pmu_register_sleep_notifier(&aty_sleep_notifier
);
4062 info
->next
= first_display
;
4063 first_display
= info
;
4067 #ifdef CONFIG_FB_COMPAT_XPMAC
4068 if (!console_fb_info
)
4069 console_fb_info
= &info
->fb_info
;
4070 #endif /* CONFIG_FB_COMPAT_XPMAC */
4072 #endif /* CONFIG_FB_OF */
4076 int __init
atyfb_setup(char *options
)
4080 if (!options
|| !*options
)
4083 for (this_opt
= strtok(options
, ","); this_opt
;
4084 this_opt
= strtok(NULL
, ",")) {
4085 if (!strncmp(this_opt
, "font:", 5)) {
4090 for (i
= 0; i
< sizeof(fontname
) - 1; i
++)
4091 if (!*p
|| *p
== ' ' || *p
== ',')
4093 memcpy(fontname
, this_opt
+ 5, i
);
4095 } else if (!strncmp(this_opt
, "noblink", 7)) {
4097 } else if (!strncmp(this_opt
, "noaccel", 7)) {
4099 } else if (!strncmp(this_opt
, "vram:", 5))
4100 default_vram
= simple_strtoul(this_opt
+5, NULL
, 0);
4101 else if (!strncmp(this_opt
, "pll:", 4))
4102 default_pll
= simple_strtoul(this_opt
+4, NULL
, 0);
4103 else if (!strncmp(this_opt
, "mclk:", 5))
4104 default_mclk
= simple_strtoul(this_opt
+5, NULL
, 0);
4106 else if (!strncmp(this_opt
, "vmode:", 6)) {
4107 unsigned int vmode
= simple_strtoul(this_opt
+6, NULL
, 0);
4108 if (vmode
> 0 && vmode
<= VMODE_MAX
)
4109 default_vmode
= vmode
;
4110 } else if (!strncmp(this_opt
, "cmode:", 6)) {
4111 unsigned int cmode
= simple_strtoul(this_opt
+6, NULL
, 0);
4115 default_cmode
= CMODE_8
;
4119 default_cmode
= CMODE_16
;
4123 default_cmode
= CMODE_32
;
4130 * Why do we need this silly Mach64 argument?
4131 * We are already here because of mach64= so its redundant.
4133 else if (MACH_IS_ATARI
&& (!strncmp(this_opt
, "Mach64:", 7))) {
4134 static unsigned char m64_num
;
4135 static char mach64_str
[80];
4136 strncpy(mach64_str
, this_opt
+7, 80);
4137 if (!store_video_par(mach64_str
, m64_num
)) {
4139 mach64_count
= m64_num
;
4144 mode_option
= this_opt
;
4148 #endif /* !MODULE */
4151 static int __init
store_video_par(char *video_str
, unsigned char m64_num
)
4154 unsigned long vmembase
, size
, guiregbase
;
4156 printk("store_video_par() '%s' \n", video_str
);
4158 if (!(p
= strtoke(video_str
, ";")) || !*p
)
4159 goto mach64_invalid
;
4160 vmembase
= simple_strtoul(p
, NULL
, 0);
4161 if (!(p
= strtoke(NULL
, ";")) || !*p
)
4162 goto mach64_invalid
;
4163 size
= simple_strtoul(p
, NULL
, 0);
4164 if (!(p
= strtoke(NULL
, ";")) || !*p
)
4165 goto mach64_invalid
;
4166 guiregbase
= simple_strtoul(p
, NULL
, 0);
4168 phys_vmembase
[m64_num
] = vmembase
;
4169 phys_size
[m64_num
] = size
;
4170 phys_guiregbase
[m64_num
] = guiregbase
;
4171 printk(" stored them all: $%08lX $%08lX $%08lX \n", vmembase
, size
,
4176 phys_vmembase
[m64_num
] = 0;
4180 static char __init
*strtoke(char *s
, const char *ct
)
4182 static char *ssave
= NULL
;
4183 char *sbegin
, *send
;
4185 sbegin
= s
? s
: ssave
;
4188 if (*sbegin
== '\0') {
4192 send
= strpbrk(sbegin
, ct
);
4193 if (send
&& *send
!= '\0')
4198 #endif /* CONFIG_ATARI */
4200 static int atyfbcon_switch(int con
, struct fb_info
*fb
)
4202 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
4203 struct atyfb_par par
;
4205 /* Do we have to save the colormap? */
4206 if (fb_display
[currcon
].cmap
.len
)
4207 fb_get_cmap(&fb_display
[currcon
].cmap
, 1, atyfb_getcolreg
, fb
);
4209 /* Erase HW Cursor */
4211 atyfb_cursor(&fb_display
[currcon
], CM_ERASE
,
4212 info
->cursor
->pos
.x
, info
->cursor
->pos
.y
);
4216 atyfb_decode_var(&fb_display
[con
].var
, &par
, info
);
4217 atyfb_set_par(&par
, info
);
4218 atyfb_set_disp(&fb_display
[con
], info
, par
.crtc
.bpp
,
4219 par
.accel_flags
& FB_ACCELF_TEXT
);
4221 /* Install new colormap */
4222 do_install_cmap(con
, fb
);
4224 /* Install hw cursor */
4226 aty_set_cursor_color(info
, cursor_pixel_map
, cursor_color_map
,
4227 cursor_color_map
, cursor_color_map
);
4228 aty_set_cursor_shape(info
);
4234 * Blank the display.
4237 static void atyfbcon_blank(int blank
, struct fb_info
*fb
)
4239 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
4243 if ((_machine
== _MACH_Pmac
) && blank
)
4244 pmu_enable_backlight(0);
4247 gen_cntl
= aty_ld_8(CRTC_GEN_CNTL
, info
);
4250 case VESA_NO_BLANKING
:
4253 case VESA_VSYNC_SUSPEND
:
4256 case VESA_HSYNC_SUSPEND
:
4259 case VESA_POWERDOWN
:
4264 gen_cntl
&= ~(0x4c);
4265 aty_st_8(CRTC_GEN_CNTL
, gen_cntl
, info
);
4268 if ((_machine
== _MACH_Pmac
) && !blank
)
4269 pmu_enable_backlight(1);
4275 * Read a single color register and split it into
4276 * colors/transparent. Return != 0 for invalid regno.
4279 static int atyfb_getcolreg(u_int regno
, u_int
*red
, u_int
*green
, u_int
*blue
,
4280 u_int
*transp
, struct fb_info
*fb
)
4282 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
4286 *red
= (info
->palette
[regno
].red
<<8) | info
->palette
[regno
].red
;
4287 *green
= (info
->palette
[regno
].green
<<8) | info
->palette
[regno
].green
;
4288 *blue
= (info
->palette
[regno
].blue
<<8) | info
->palette
[regno
].blue
;
4295 * Set a single color register. The values supplied are already
4296 * rounded down to the hardware's capabilities (according to the
4297 * entries in the var structure). Return != 0 for invalid regno.
4300 static int atyfb_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
4301 u_int transp
, struct fb_info
*fb
)
4303 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
4311 info
->palette
[regno
].red
= red
;
4312 info
->palette
[regno
].green
= green
;
4313 info
->palette
[regno
].blue
= blue
;
4314 i
= aty_ld_8(DAC_CNTL
, info
) & 0xfc;
4315 if (Gx
== GT_CHIP_ID
|| Gx
== GU_CHIP_ID
|| Gx
== GV_CHIP_ID
||
4316 Gx
== GW_CHIP_ID
|| Gx
== GZ_CHIP_ID
|| Gx
== LG_CHIP_ID
||
4317 Gx
== GB_CHIP_ID
|| Gx
== GD_CHIP_ID
|| Gx
== GI_CHIP_ID
||
4318 Gx
== GP_CHIP_ID
|| Gx
== GQ_CHIP_ID
)
4319 i
|= 0x2; /*DAC_CNTL|0x2 turns off the extra brightness for gt*/
4320 aty_st_8(DAC_CNTL
, i
, info
);
4321 aty_st_8(DAC_MASK
, 0xff, info
);
4323 scale
= ((Gx
!= GX_CHIP_ID
) && (Gx
!= CX_CHIP_ID
) &&
4324 (info
->current_par
.crtc
.bpp
== 16)) ? 3 : 0;
4325 info
->aty_cmap_regs
->windex
= regno
<< scale
;
4327 info
->aty_cmap_regs
->lut
= red
;
4329 info
->aty_cmap_regs
->lut
= green
;
4331 info
->aty_cmap_regs
->lut
= blue
;
4334 switch (info
->current_par
.crtc
.bpp
) {
4335 #ifdef FBCON_HAS_CFB16
4337 info
->fbcon_cmap
.cfb16
[regno
] = (regno
<< 10) | (regno
<< 5) |
4341 #ifdef FBCON_HAS_CFB24
4343 info
->fbcon_cmap
.cfb24
[regno
] = (regno
<< 16) | (regno
<< 8) |
4347 #ifdef FBCON_HAS_CFB32
4349 i
= (regno
<< 8) | regno
;
4350 info
->fbcon_cmap
.cfb32
[regno
] = (i
<< 16) | i
;
4358 static void do_install_cmap(int con
, struct fb_info
*info
)
4362 if (fb_display
[con
].cmap
.len
)
4363 fb_set_cmap(&fb_display
[con
].cmap
, 1, atyfb_setcolreg
, info
);
4365 int size
= fb_display
[con
].var
.bits_per_pixel
== 16 ? 32 : 256;
4366 fb_set_cmap(fb_default_cmap(size
), 1, atyfb_setcolreg
, info
);
4372 * Accelerated functions
4375 static inline void draw_rect(s16 x
, s16 y
, u16 width
, u16 height
,
4376 struct fb_info_aty
*info
)
4378 /* perform rectangle fill */
4379 wait_for_fifo(2, info
);
4380 aty_st_le32(DST_Y_X
, (x
<< 16) | y
, info
);
4381 aty_st_le32(DST_HEIGHT_WIDTH
, (width
<< 16) | height
, info
);
4382 info
->blitter_may_be_busy
= 1;
4385 static inline void aty_rectcopy(int srcx
, int srcy
, int dstx
, int dsty
,
4386 u_int width
, u_int height
,
4387 struct fb_info_aty
*info
)
4389 u32 direction
= DST_LAST_PEL
;
4392 if (!width
|| !height
)
4395 pitch_value
= info
->current_par
.crtc
.vxres
;
4396 if (info
->current_par
.crtc
.bpp
== 24) {
4397 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
4398 /* horizontal coordinates and widths must be adjusted */
4409 direction
|= DST_Y_TOP_TO_BOTTOM
;
4415 direction
|= DST_X_LEFT_TO_RIGHT
;
4417 wait_for_fifo(4, info
);
4418 aty_st_le32(DP_SRC
, FRGD_SRC_BLIT
, info
);
4419 aty_st_le32(SRC_Y_X
, (srcx
<< 16) | srcy
, info
);
4420 aty_st_le32(SRC_HEIGHT1_WIDTH1
, (width
<< 16) | height
, info
);
4421 aty_st_le32(DST_CNTL
, direction
, info
);
4422 draw_rect(dstx
, dsty
, width
, height
, info
);
4425 static inline void aty_rectfill(int dstx
, int dsty
, u_int width
, u_int height
,
4426 u_int color
, struct fb_info_aty
*info
)
4428 if (!width
|| !height
)
4431 if (info
->current_par
.crtc
.bpp
== 24) {
4432 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
4433 /* horizontal coordinates and widths must be adjusted */
4438 wait_for_fifo(3, info
);
4439 aty_st_le32(DP_FRGD_CLR
, color
, info
);
4440 aty_st_le32(DP_SRC
, BKGD_SRC_BKGD_CLR
| FRGD_SRC_FRGD_CLR
| MONO_SRC_ONE
,
4442 aty_st_le32(DST_CNTL
, DST_LAST_PEL
| DST_Y_TOP_TO_BOTTOM
|
4443 DST_X_LEFT_TO_RIGHT
, info
);
4444 draw_rect(dstx
, dsty
, width
, height
, info
);
4448 * Update the `var' structure (called by fbcon.c)
4451 static int atyfbcon_updatevar(int con
, struct fb_info
*fb
)
4453 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
4454 struct atyfb_par
*par
= &info
->current_par
;
4455 struct display
*p
= &fb_display
[con
];
4456 struct vc_data
*conp
= p
->conp
;
4457 u32 yres
, yoffset
, sy
, height
;
4459 yres
= ((par
->crtc
.v_tot_disp
>> 16) & 0x7ff) + 1;
4460 yoffset
= fb_display
[con
].var
.yoffset
;
4462 sy
= (conp
->vc_rows
+ p
->yscroll
) * fontheight(p
);
4463 height
= yres
- conp
->vc_rows
* fontheight(p
);
4465 if (height
&& (yoffset
+ yres
> sy
)) {
4469 xres
= (((par
->crtc
.h_tot_disp
>> 16) & 0xff) + 1) * 8;
4470 xoffset
= fb_display
[con
].var
.xoffset
;
4473 bgx
= attr_bgcol_ec(p
, conp
);
4477 if (sy
+ height
> par
->crtc
.vyres
) {
4478 wait_for_fifo(1, info
);
4479 aty_st_le32(SC_BOTTOM
, sy
+ height
- 1, info
);
4481 aty_rectfill(xoffset
, sy
, xres
, height
, bgx
, info
);
4484 if (info
->cursor
&& (yoffset
+ yres
<= sy
))
4485 atyfb_cursor(p
, CM_ERASE
, info
->cursor
->pos
.x
, info
->cursor
->pos
.y
);
4487 info
->current_par
.crtc
.yoffset
= yoffset
;
4488 set_off_pitch(&info
->current_par
, info
);
4493 * Text console acceleration
4496 static void fbcon_aty_bmove(struct display
*p
, int sy
, int sx
, int dy
, int dx
,
4497 int height
, int width
)
4500 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4502 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4503 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4508 sy
*= fontheight(p
);
4510 dy
*= fontheight(p
);
4511 width
*= fontwidth(p
);
4512 height
*= fontheight(p
);
4514 aty_rectcopy(sx
, sy
, dx
, dy
, width
, height
,
4515 (struct fb_info_aty
*)p
->fb_info
);
4518 static void fbcon_aty_clear(struct vc_data
*conp
, struct display
*p
, int sy
,
4519 int sx
, int height
, int width
)
4523 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4525 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4526 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4530 bgx
= attr_bgcol_ec(p
, conp
);
4535 sy
*= fontheight(p
);
4536 width
*= fontwidth(p
);
4537 height
*= fontheight(p
);
4539 aty_rectfill(sx
, sy
, width
, height
, bgx
,
4540 (struct fb_info_aty
*)p
->fb_info
);
4543 #ifdef FBCON_HAS_CFB8
4544 static void fbcon_aty8_putc(struct vc_data
*conp
, struct display
*p
, int c
,
4547 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4550 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4551 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4555 if (fb
->blitter_may_be_busy
)
4556 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4557 fbcon_cfb8_putc(conp
, p
, c
, yy
, xx
);
4560 static void fbcon_aty8_putcs(struct vc_data
*conp
, struct display
*p
,
4561 const unsigned short *s
, int count
, int yy
,
4564 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4567 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4568 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4572 if (fb
->blitter_may_be_busy
)
4573 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4574 fbcon_cfb8_putcs(conp
, p
, s
, count
, yy
, xx
);
4577 static void fbcon_aty8_clear_margins(struct vc_data
*conp
, struct display
*p
,
4580 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4583 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4584 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4588 if (fb
->blitter_may_be_busy
)
4589 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4590 fbcon_cfb8_clear_margins(conp
, p
, bottom_only
);
4593 static struct display_switch fbcon_aty8
= {
4594 fbcon_cfb8_setup
, fbcon_aty_bmove
, fbcon_aty_clear
, fbcon_aty8_putc
,
4595 fbcon_aty8_putcs
, fbcon_cfb8_revc
, NULL
, NULL
, fbcon_aty8_clear_margins
,
4596 FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4600 #ifdef FBCON_HAS_CFB16
4601 static void fbcon_aty16_putc(struct vc_data
*conp
, struct display
*p
, int c
,
4604 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4607 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4608 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4612 if (fb
->blitter_may_be_busy
)
4613 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4614 fbcon_cfb16_putc(conp
, p
, c
, yy
, xx
);
4617 static void fbcon_aty16_putcs(struct vc_data
*conp
, struct display
*p
,
4618 const unsigned short *s
, int count
, int yy
,
4621 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4624 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4625 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4629 if (fb
->blitter_may_be_busy
)
4630 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4631 fbcon_cfb16_putcs(conp
, p
, s
, count
, yy
, xx
);
4634 static void fbcon_aty16_clear_margins(struct vc_data
*conp
, struct display
*p
,
4637 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4640 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4641 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4645 if (fb
->blitter_may_be_busy
)
4646 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4647 fbcon_cfb16_clear_margins(conp
, p
, bottom_only
);
4650 static struct display_switch fbcon_aty16
= {
4651 fbcon_cfb16_setup
, fbcon_aty_bmove
, fbcon_aty_clear
, fbcon_aty16_putc
,
4652 fbcon_aty16_putcs
, fbcon_cfb16_revc
, NULL
, NULL
, fbcon_aty16_clear_margins
,
4653 FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4657 #ifdef FBCON_HAS_CFB24
4658 static void fbcon_aty24_putc(struct vc_data
*conp
, struct display
*p
, int c
,
4661 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4664 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4665 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4669 if (fb
->blitter_may_be_busy
)
4670 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4671 fbcon_cfb24_putc(conp
, p
, c
, yy
, xx
);
4674 static void fbcon_aty24_putcs(struct vc_data
*conp
, struct display
*p
,
4675 const unsigned short *s
, int count
, int yy
,
4678 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4681 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4682 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4686 if (fb
->blitter_may_be_busy
)
4687 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4688 fbcon_cfb24_putcs(conp
, p
, s
, count
, yy
, xx
);
4691 static void fbcon_aty24_clear_margins(struct vc_data
*conp
, struct display
*p
,
4694 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4697 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4698 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4702 if (fb
->blitter_may_be_busy
)
4703 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4704 fbcon_cfb24_clear_margins(conp
, p
, bottom_only
);
4707 static struct display_switch fbcon_aty24
= {
4708 fbcon_cfb24_setup
, fbcon_aty_bmove
, fbcon_aty_clear
, fbcon_aty24_putc
,
4709 fbcon_aty24_putcs
, fbcon_cfb24_revc
, NULL
, NULL
, fbcon_aty24_clear_margins
,
4710 FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4714 #ifdef FBCON_HAS_CFB32
4715 static void fbcon_aty32_putc(struct vc_data
*conp
, struct display
*p
, int c
,
4718 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4721 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4722 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4726 if (fb
->blitter_may_be_busy
)
4727 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4728 fbcon_cfb32_putc(conp
, p
, c
, yy
, xx
);
4731 static void fbcon_aty32_putcs(struct vc_data
*conp
, struct display
*p
,
4732 const unsigned short *s
, int count
, int yy
,
4735 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4738 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4739 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4743 if (fb
->blitter_may_be_busy
)
4744 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4745 fbcon_cfb32_putcs(conp
, p
, s
, count
, yy
, xx
);
4748 static void fbcon_aty32_clear_margins(struct vc_data
*conp
, struct display
*p
,
4751 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4754 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4755 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4759 if (fb
->blitter_may_be_busy
)
4760 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4761 fbcon_cfb32_clear_margins(conp
, p
, bottom_only
);
4764 static struct display_switch fbcon_aty32
= {
4765 fbcon_cfb32_setup
, fbcon_aty_bmove
, fbcon_aty_clear
, fbcon_aty32_putc
,
4766 fbcon_aty32_putcs
, fbcon_cfb32_revc
, NULL
, NULL
, fbcon_aty32_clear_margins
,
4767 FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4771 #ifdef CONFIG_PMAC_PBOOK
4773 * Save the contents of the frame buffer when we go to sleep,
4774 * and restore it when we wake up again.
4777 aty_sleep_notify(struct pmu_sleep_notifier
*self
, int when
)
4779 struct fb_info_aty
*info
;
4782 for (info
= first_display
; info
!= NULL
; info
= info
->next
) {
4783 struct fb_fix_screeninfo fix
;
4786 atyfb_get_fix(&fix
, fg_console
, (struct fb_info
*)info
);
4787 nb
= fb_display
[fg_console
].var
.yres
* fix
.line_length
;
4790 case PBOOK_SLEEP_NOW
:
4791 /* Stop accel engine (stop bus mastering) */
4792 if (info
->current_par
.accel_flags
& FB_ACCELF_TEXT
)
4795 /* Backup fb content */
4796 info
->save_framebuffer
= vmalloc(nb
);
4797 if (info
->save_framebuffer
)
4798 memcpy(info
->save_framebuffer
,
4799 (void *)info
->frame_buffer
, nb
);
4801 /* Blank display and LCD */
4802 atyfbcon_blank(VESA_POWERDOWN
+1, (struct fb_info
*)info
);
4804 /* Set chip to "suspend" mode. Note: There's an HW bug in the
4805 chip which prevents proper resync on wakeup with automatic
4806 power management, we handle suspend manually using the
4807 following (weird) sequence described by ATI. Note2:
4808 We could enable this for all Rage LT Pro chip ids */
4809 if ((Gx
== LG_CHIP_ID
) || (Gx
== LT_CHIP_ID
) || (Gx
== LP_CHIP_ID
)) {
4810 pm
= aty_ld_le32(POWER_MANAGEMENT
, info
);
4812 aty_st_le32(POWER_MANAGEMENT
, pm
, info
);
4813 pm
= aty_ld_le32(POWER_MANAGEMENT
, info
);
4814 pm
&= ~(PWR_BLON
| AUTO_PWR_UP
);
4816 aty_st_le32(POWER_MANAGEMENT
, pm
, info
);
4817 pm
= aty_ld_le32(POWER_MANAGEMENT
, info
);
4819 aty_st_le32(POWER_MANAGEMENT
, pm
, info
);
4821 pm
= aty_ld_le32(POWER_MANAGEMENT
, info
);
4822 } while ((pm
& PWR_MGT_STATUS_MASK
) != PWR_MGT_STATUS_SUSPEND
);
4828 if ((Gx
== LG_CHIP_ID
) || (Gx
== LT_CHIP_ID
) || (Gx
== LP_CHIP_ID
)) {
4829 pm
= aty_ld_le32(POWER_MANAGEMENT
, info
);
4831 aty_st_le32(POWER_MANAGEMENT
, pm
, info
);
4832 pm
= aty_ld_le32(POWER_MANAGEMENT
, info
);
4833 pm
|= (PWR_BLON
| AUTO_PWR_UP
);
4835 aty_st_le32(POWER_MANAGEMENT
, pm
, info
);
4836 pm
= aty_ld_le32(POWER_MANAGEMENT
, info
);
4838 aty_st_le32(POWER_MANAGEMENT
, pm
, info
);
4840 pm
= aty_ld_le32(POWER_MANAGEMENT
, info
);
4841 } while ((pm
& PWR_MGT_STATUS_MASK
) != 0);
4845 /* Restore fb content */
4846 if (info
->save_framebuffer
) {
4847 memcpy((void *)info
->frame_buffer
,
4848 info
->save_framebuffer
, nb
);
4849 vfree(info
->save_framebuffer
);
4850 info
->save_framebuffer
= 0;
4853 /* Restore display */
4854 atyfb_set_par(&info
->current_par
, info
);
4855 atyfbcon_blank(0, (struct fb_info
*)info
);
4859 return PBOOK_SLEEP_OK
;
4861 #endif /* CONFIG_PMAC_PBOOK */
4864 int __init
init_module(void)
4867 return fb_list
? 0 : -ENXIO
;
4870 void cleanup_module(void)
4873 struct fb_info_aty
*info
= fb_list
;
4874 fb_list
= info
->next
;
4876 unregister_framebuffer(&info
->fb_info
);
4879 if (info
->ati_regbase
)
4880 iounmap((void *)info
->ati_regbase
);
4881 if (info
->frame_buffer
)
4882 iounmap((void *)info
->frame_buffer
);
4884 if (info
->cursor
&& info
->cursor
->ram
)
4885 iounmap(info
->cursor
->ram
);
4890 if (info
->cursor
->timer
)
4891 kfree(info
->cursor
->timer
);
4892 kfree(info
->cursor
);
4896 kfree(info
->mmap_map
);