1 /* $Id: atyfb.c,v 1.147 2000/08/29 07:01:56 davem 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
24 * Many thanks to Nitya from ATI devrel for support and patience !
27 /******************************************************************************
31 - cursor support on all cards and all ramdacs.
32 - cursor parameters controlable via ioctl()s.
33 - guess PLL and MCLK based on the original PLL register values initialized
34 by the BIOS or Open Firmware (if they are initialized).
36 (Anyone to help with this?)
38 ******************************************************************************/
41 #include <linux/config.h>
42 #include <linux/module.h>
43 #include <linux/kernel.h>
44 #include <linux/errno.h>
45 #include <linux/string.h>
47 #include <linux/tty.h>
48 #include <linux/malloc.h>
49 #include <linux/vmalloc.h>
50 #include <linux/delay.h>
51 #include <linux/interrupt.h>
53 #include <linux/selection.h>
54 #include <linux/console.h>
55 #include <linux/init.h>
56 #include <linux/pci.h>
58 #include <linux/vt_kern.h>
60 #ifdef CONFIG_FB_COMPAT_XPMAC
61 #include <asm/vc_ioctl.h>
67 #include <linux/adb.h>
69 #include <asm/pci-bridge.h>
70 #include <video/macmodes.h>
73 #include <linux/pmu.h>
76 #include <linux/nvram.h>
78 #ifdef CONFIG_PMAC_BACKLIGHT
79 #include <asm/backlight.h>
86 #include <asm/uaccess.h>
88 #include <video/fbcon.h>
89 #include <video/fbcon-cfb8.h>
90 #include <video/fbcon-cfb16.h>
91 #include <video/fbcon-cfb24.h>
92 #include <video/fbcon-cfb32.h>
102 /* Definitions for the ICS 2595 == ATI 18818_1 Clockchip */
104 #define REF_FREQ_2595 1432 /* 14.33 MHz (exact 14.31818) */
105 #define REF_DIV_2595 46 /* really 43 on ICS 2595 !!! */
107 #define MAX_FREQ_2595 15938 /* 159.38 MHz (really 170.486) */
108 #define MIN_FREQ_2595 8000 /* 80.00 MHz ( 85.565) */
109 /* mit Prescaler 2, 4, 8 */
110 #define ABS_MIN_FREQ_2595 1000 /* 10.00 MHz (really 10.697) */
111 #define N_ADJ_2595 257
113 #define STOP_BITS_2595 0x1800
126 /* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */
127 /* - must be large enough to catch all GUI-Regs */
128 /* - must be aligned to a PAGE boundary */
129 #define GUI_RESERVE (1 * PAGE_SIZE)
132 /* FIXME: remove the FAIL definition */
133 #define FAIL(x) do { printk(x "\n"); return -EINVAL; } while (0)
137 * Elements of the Hardware specific atyfb_par structure
152 u32 dp_pix_width
; /* acceleration */
153 u32 dp_chain_mask
; /* acceleration */
177 u32 dsp_config
; /* Mach64 GTB DSP */
178 u32 dsp_on_off
; /* Mach64 GTB DSP */
179 u8 mclk_post_div_real
;
180 u8 vclk_post_div_real
;
185 * The Hardware parameters for each card
193 struct pll_18818 ics2595
;
198 struct aty_cmap_regs
{
206 struct pci_mmap_map
{
210 unsigned long prot_flag
;
211 unsigned long prot_mask
;
214 #define DEFAULT_CURSOR_BLINK_RATE (20)
215 #define CURSOR_DRAW_DELAY (2)
230 struct timer_list
*timer
;
234 struct fb_info fb_info
;
235 struct fb_info_aty
*next
;
236 unsigned long ati_regbase_phys
;
237 unsigned long ati_regbase
;
238 unsigned long frame_buffer_phys
;
239 unsigned long frame_buffer
;
240 unsigned long clk_wr_offset
;
241 struct pci_mmap_map
*mmap_map
;
242 struct aty_cursor
*cursor
;
243 struct aty_cmap_regs
*aty_cmap_regs
;
244 struct { u8 red
, green
, blue
, pad
; } palette
[256];
245 struct atyfb_par default_par
;
246 struct atyfb_par current_par
;
252 #define Gx info->chip_type
254 #define Rev info->chip_rev
262 struct display_switch dispsw
;
264 #ifdef FBCON_HAS_CFB16
267 #ifdef FBCON_HAS_CFB24
270 #ifdef FBCON_HAS_CFB32
274 u8 blitter_may_be_busy
;
281 #ifdef CONFIG_PMAC_PBOOK
282 unsigned char *save_framebuffer
;
283 unsigned long save_pll
[64];
287 #ifdef CONFIG_PMAC_PBOOK
288 int aty_sleep_notify(struct pmu_sleep_notifier
*self
, int when
);
289 static struct pmu_sleep_notifier aty_sleep_notifier
= {
290 aty_sleep_notify
, SLEEP_LEVEL_VIDEO
,
292 static struct fb_info_aty
* first_display
= NULL
;
295 #ifdef CONFIG_PMAC_BACKLIGHT
296 static int aty_set_backlight_enable(int on
, int level
, void* data
);
297 static int aty_set_backlight_level(int level
, void* data
);
299 static struct backlight_controller aty_backlight_controller
= {
300 aty_set_backlight_enable
,
301 aty_set_backlight_level
303 #endif /* CONFIG_PMAC_BACKLIGHT */
306 * Frame buffer device API
309 static int atyfb_open(struct fb_info
*info
, int user
);
310 static int atyfb_release(struct fb_info
*info
, int user
);
311 static int atyfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
313 static int atyfb_get_var(struct fb_var_screeninfo
*var
, int con
,
315 static int atyfb_set_var(struct fb_var_screeninfo
*var
, int con
,
317 static int atyfb_pan_display(struct fb_var_screeninfo
*var
, int con
,
319 static int atyfb_get_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
320 struct fb_info
*info
);
321 static int atyfb_set_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
322 struct fb_info
*info
);
323 static int atyfb_ioctl(struct inode
*inode
, struct file
*file
, u_int cmd
,
324 u_long arg
, int con
, struct fb_info
*info
);
326 static int atyfb_mmap(struct fb_info
*info
, struct file
*file
,
327 struct vm_area_struct
*vma
);
329 static int atyfb_rasterimg(struct fb_info
*info
, int start
);
333 * Interface to the low level console driver
336 static int atyfbcon_switch(int con
, struct fb_info
*fb
);
337 static int atyfbcon_updatevar(int con
, struct fb_info
*fb
);
338 static void atyfbcon_blank(int blank
, struct fb_info
*fb
);
342 * Text console acceleration
345 static void fbcon_aty_bmove(struct display
*p
, int sy
, int sx
, int dy
, int dx
,
346 int height
, int width
);
347 static void fbcon_aty_clear(struct vc_data
*conp
, struct display
*p
, int sy
,
348 int sx
, int height
, int width
);
349 #ifdef FBCON_HAS_CFB8
350 static struct display_switch fbcon_aty8
;
351 static void fbcon_aty8_putc(struct vc_data
*conp
, struct display
*p
, int c
,
353 static void fbcon_aty8_putcs(struct vc_data
*conp
, struct display
*p
,
354 const unsigned short *s
, int count
, int yy
,
357 #ifdef FBCON_HAS_CFB16
358 static struct display_switch fbcon_aty16
;
359 static void fbcon_aty16_putc(struct vc_data
*conp
, struct display
*p
, int c
,
361 static void fbcon_aty16_putcs(struct vc_data
*conp
, struct display
*p
,
362 const unsigned short *s
, int count
, int yy
,
365 #ifdef FBCON_HAS_CFB24
366 static struct display_switch fbcon_aty24
;
367 static void fbcon_aty24_putc(struct vc_data
*conp
, struct display
*p
, int c
,
369 static void fbcon_aty24_putcs(struct vc_data
*conp
, struct display
*p
,
370 const unsigned short *s
, int count
, int yy
,
373 #ifdef FBCON_HAS_CFB32
374 static struct display_switch fbcon_aty32
;
375 static void fbcon_aty32_putc(struct vc_data
*conp
, struct display
*p
, int c
,
377 static void fbcon_aty32_putcs(struct vc_data
*conp
, struct display
*p
,
378 const unsigned short *s
, int count
, int yy
,
387 static int aty_init(struct fb_info_aty
*info
, const char *name
);
388 static struct aty_cursor
*aty_init_cursor(struct fb_info_aty
*fb
);
390 static int store_video_par(char *videopar
, unsigned char m64_num
);
391 static char *strtoke(char *s
, const char *ct
);
394 static void reset_engine(const struct fb_info_aty
*info
);
395 static void init_engine(const struct atyfb_par
*par
, struct fb_info_aty
*info
);
397 static void aty_st_514(int offset
, u8 val
, const struct fb_info_aty
*info
);
398 static void aty_st_pll(int offset
, u8 val
, const struct fb_info_aty
*info
);
399 static u8
aty_ld_pll(int offset
, const struct fb_info_aty
*info
);
400 static void aty_set_crtc(const struct fb_info_aty
*info
,
401 const struct crtc
*crtc
);
402 static int aty_var_to_crtc(const struct fb_info_aty
*info
,
403 const struct fb_var_screeninfo
*var
,
405 static void aty_set_dac_514(const struct fb_info_aty
*info
, u32 bpp
);
406 static int aty_crtc_to_var(const struct crtc
*crtc
,
407 struct fb_var_screeninfo
*var
);
408 static void aty_set_pll_gx(const struct fb_info_aty
*info
,
409 const struct pll_gx
*pll
);
411 static int aty_set_dac_ATI68860_B(const struct fb_info_aty
*info
, u32 bpp
,
413 static int aty_set_dac_ATT21C498(const struct fb_info_aty
*info
,
414 const struct pll_18818
*pll
, u32 bpp
);
415 void aty_dac_waste4(const struct fb_info_aty
*info
);
417 static int aty_var_to_pll_18818(u32 period_in_ps
, struct pll_18818
*pll
);
418 static u32
aty_pll_18818_to_var(const struct pll_18818
*pll
);
419 static void aty_set_pll18818(const struct fb_info_aty
*info
,
420 const struct pll_18818
*pll
);
422 static void aty_StrobeClock(const struct fb_info_aty
*info
);
424 static void aty_ICS2595_put1bit(u8 data
, const struct fb_info_aty
*info
);
426 static int aty_var_to_pll_408(u32 period_in_ps
, struct pll_18818
*pll
);
427 static u32
aty_pll_408_to_var(const struct pll_18818
*pll
);
428 static void aty_set_pll_408(const struct fb_info_aty
*info
,
429 const struct pll_18818
*pll
);
431 static int aty_var_to_pll_1703(u32 period_in_ps
, struct pll_18818
*pll
);
432 static u32
aty_pll_1703_to_var(const struct pll_18818
*pll
);
433 static void aty_set_pll_1703(const struct fb_info_aty
*info
,
434 const struct pll_18818
*pll
);
436 static int aty_var_to_pll_8398(u32 period_in_ps
, struct pll_18818
*pll
);
437 static u32
aty_pll_8398_to_var(const struct pll_18818
*pll
);
438 static void aty_set_pll_8398(const struct fb_info_aty
*info
,
439 const struct pll_18818
*pll
);
441 static int aty_var_to_pll_514(u32 vclk_per
, struct pll_gx
*pll
);
442 static u32
aty_pll_gx_to_var(const struct pll_gx
*pll
,
443 const struct fb_info_aty
*info
);
444 static void aty_set_pll_ct(const struct fb_info_aty
*info
,
445 const struct pll_ct
*pll
);
446 static int aty_valid_pll_ct(const struct fb_info_aty
*info
, u32 vclk_per
,
448 static int aty_dsp_gt(const struct fb_info_aty
*info
, u8 bpp
,
450 static void aty_calc_pll_ct(const struct fb_info_aty
*info
,
452 static int aty_var_to_pll_ct(const struct fb_info_aty
*info
, u32 vclk_per
,
453 u8 bpp
, struct pll_ct
*pll
);
454 static u32
aty_pll_ct_to_var(const struct pll_ct
*pll
,
455 const struct fb_info_aty
*info
);
456 static void atyfb_set_par(const struct atyfb_par
*par
,
457 struct fb_info_aty
*info
);
458 static int atyfb_decode_var(const struct fb_var_screeninfo
*var
,
459 struct atyfb_par
*par
,
460 const struct fb_info_aty
*info
);
461 static int atyfb_encode_var(struct fb_var_screeninfo
*var
,
462 const struct atyfb_par
*par
,
463 const struct fb_info_aty
*info
);
464 static void set_off_pitch(struct atyfb_par
*par
,
465 const struct fb_info_aty
*info
);
466 static int encode_fix(struct fb_fix_screeninfo
*fix
,
467 const struct atyfb_par
*par
,
468 const struct fb_info_aty
*info
);
469 static void atyfb_set_dispsw(struct display
*disp
, struct fb_info_aty
*info
,
471 static int atyfb_getcolreg(u_int regno
, u_int
*red
, u_int
*green
, u_int
*blue
,
472 u_int
*transp
, struct fb_info
*fb
);
473 static int atyfb_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
474 u_int transp
, struct fb_info
*fb
);
475 static void do_install_cmap(int con
, struct fb_info
*info
);
477 static int read_aty_sense(const struct fb_info_aty
*info
);
482 * Interface used by the world
485 int atyfb_init(void);
487 int atyfb_setup(char*);
490 static int currcon
= 0;
492 static struct fb_ops atyfb_ops
= {
495 fb_release
: atyfb_release
,
496 fb_get_fix
: atyfb_get_fix
,
497 fb_get_var
: atyfb_get_var
,
498 fb_set_var
: atyfb_set_var
,
499 fb_get_cmap
: atyfb_get_cmap
,
500 fb_set_cmap
: atyfb_set_cmap
,
501 fb_pan_display
: atyfb_pan_display
,
502 fb_ioctl
: atyfb_ioctl
,
506 fb_rasterimg
: atyfb_rasterimg
,
509 static char atyfb_name
[16] = "ATY Mach64";
510 static char fontname
[40] __initdata
= { 0 };
511 static char curblink __initdata
= 1;
512 static char noaccel __initdata
= 0;
513 static u32 default_vram __initdata
= 0;
514 static int default_pll __initdata
= 0;
515 static int default_mclk __initdata
= 0;
518 static const char *mode_option __initdata
= NULL
;
522 #ifdef CONFIG_NVRAM_NOT_DEFINED
523 static int default_vmode __initdata
= VMODE_NVRAM
;
524 static int default_cmode __initdata
= CMODE_NVRAM
;
526 static int default_vmode __initdata
= VMODE_CHOOSE
;
527 static int default_cmode __initdata
= CMODE_CHOOSE
;
532 static unsigned int mach64_count __initdata
= 0;
533 static unsigned long phys_vmembase
[FB_MAX
] __initdata
= { 0, };
534 static unsigned long phys_size
[FB_MAX
] __initdata
= { 0, };
535 static unsigned long phys_guiregbase
[FB_MAX
] __initdata
= { 0, };
539 static struct aty_features
{
543 } aty_features
[] __initdata
= {
544 /* mach64GX family */
545 { 0x4758, 0x00d7, "mach64GX (ATI888GX00)" },
546 { 0x4358, 0x0057, "mach64CX (ATI888CX00)" },
548 /* mach64CT family */
549 { 0x4354, 0x4354, "mach64CT (ATI264CT)" },
550 { 0x4554, 0x4554, "mach64ET (ATI264ET)" },
552 /* mach64CT family / mach64VT class */
553 { 0x5654, 0x5654, "mach64VT (ATI264VT)" },
554 { 0x5655, 0x5655, "mach64VTB (ATI264VTB)" },
555 { 0x5656, 0x5656, "mach64VT4 (ATI264VT4)" },
557 /* mach64CT family / mach64GT (3D RAGE) class */
558 { 0x4c42, 0x4c42, "3D RAGE LT PRO (AGP)" },
559 { 0x4c44, 0x4c44, "3D RAGE LT PRO" },
560 { 0x4c47, 0x4c47, "3D RAGE LT-G" },
561 { 0x4c49, 0x4c49, "3D RAGE LT PRO" },
562 { 0x4c50, 0x4c50, "3D RAGE LT PRO" },
563 { 0x4c54, 0x4c54, "3D RAGE LT" },
564 { 0x4754, 0x4754, "3D RAGE (GT)" },
565 { 0x4755, 0x4755, "3D RAGE II+ (GTB)" },
566 { 0x4756, 0x4756, "3D RAGE IIC (PCI)" },
567 { 0x4757, 0x4757, "3D RAGE IIC (AGP)" },
568 { 0x475a, 0x475a, "3D RAGE IIC (AGP)" },
569 { 0x4742, 0x4742, "3D RAGE PRO (BGA, AGP)" },
570 { 0x4744, 0x4744, "3D RAGE PRO (BGA, AGP, 1x only)" },
571 { 0x4749, 0x4749, "3D RAGE PRO (BGA, PCI)" },
572 { 0x4750, 0x4750, "3D RAGE PRO (PQFP, PCI)" },
573 { 0x4751, 0x4751, "3D RAGE PRO (PQFP, PCI, limited 3D)" },
574 { 0x4c4d, 0x4c4d, "3D RAGE Mobility (PCI)" },
575 { 0x4c4e, 0x4c4e, "3D RAGE Mobility (AGP)" },
578 static const char *aty_gx_ram
[8] __initdata
= {
579 "DRAM", "VRAM", "VRAM", "DRAM", "DRAM", "VRAM", "VRAM", "RESV"
582 static const char *aty_ct_ram
[8] __initdata
= {
583 "OFF", "DRAM", "EDO", "EDO", "SDRAM", "SGRAM", "WRAM", "RESV"
587 static inline u32
aty_ld_le32(int regindex
,
588 const struct fb_info_aty
*info
)
590 /* Hack for bloc 1, should be cleanly optimized by compiler */
591 if (regindex
>= 0x400)
594 #if defined(__mc68000__)
595 return le32_to_cpu(*((volatile u32
*)(info
->ati_regbase
+regindex
)));
597 return readl (info
->ati_regbase
+ regindex
);
601 static inline void aty_st_le32(int regindex
, u32 val
,
602 const struct fb_info_aty
*info
)
604 /* Hack for bloc 1, should be cleanly optimized by compiler */
605 if (regindex
>= 0x400)
608 #if defined(__mc68000__)
609 *((volatile u32
*)(info
->ati_regbase
+regindex
)) = cpu_to_le32(val
);
611 writel (val
, info
->ati_regbase
+ regindex
);
615 static inline u8
aty_ld_8(int regindex
,
616 const struct fb_info_aty
*info
)
618 /* Hack for bloc 1, should be cleanly optimized by compiler */
619 if (regindex
>= 0x400)
622 return readb (info
->ati_regbase
+ regindex
);
625 static inline void aty_st_8(int regindex
, u8 val
,
626 const struct fb_info_aty
*info
)
628 /* Hack for bloc 1, should be cleanly optimized by compiler */
629 if (regindex
>= 0x400)
632 writeb (val
, info
->ati_regbase
+ regindex
);
635 #if defined(CONFIG_PPC) || defined(CONFIG_PMAC_PBOOK)
636 static void aty_st_lcd(int index
, u32 val
, const struct fb_info_aty
*info
)
640 /* write addr byte */
641 temp
= aty_ld_le32(LCD_INDEX
, info
);
642 aty_st_le32(LCD_INDEX
, (temp
& ~LCD_INDEX_MASK
) | index
, info
);
643 /* write the register value */
644 aty_st_le32(LCD_DATA
, val
, info
);
647 static u32
aty_ld_lcd(int index
, const struct fb_info_aty
*info
)
651 /* write addr byte */
652 temp
= aty_ld_le32(LCD_INDEX
, info
);
653 aty_st_le32(LCD_INDEX
, (temp
& ~LCD_INDEX_MASK
) | index
, info
);
654 /* read the register value */
655 return aty_ld_le32(LCD_DATA
, info
);
660 * Generic Mach64 routines
664 * All writes to draw engine registers are automatically routed through a
665 * 32-bit-wide, 16-entry-deep command FIFO ...
666 * Register writes to registers with DWORD offsets less than 40h are not
668 * (from Chapter 5 of the Mach64 Programmer's Guide)
671 static inline void wait_for_fifo(u16 entries
, const struct fb_info_aty
*info
)
673 while ((aty_ld_le32(FIFO_STAT
, info
) & 0xffff) >
674 ((u32
)(0x8000 >> entries
)));
677 static inline void wait_for_idle(struct fb_info_aty
*info
)
679 wait_for_fifo(16, info
);
680 while ((aty_ld_le32(GUI_STAT
, info
) & 1)!= 0);
681 info
->blitter_may_be_busy
= 0;
684 static void reset_engine(const struct fb_info_aty
*info
)
687 aty_st_le32(GEN_TEST_CNTL
,
688 aty_ld_le32(GEN_TEST_CNTL
, info
) & ~GUI_ENGINE_ENABLE
, info
);
690 aty_st_le32(GEN_TEST_CNTL
,
691 aty_ld_le32(GEN_TEST_CNTL
, info
) | GUI_ENGINE_ENABLE
, info
);
692 /* ensure engine is not locked up by clearing any FIFO or */
694 aty_st_le32(BUS_CNTL
, aty_ld_le32(BUS_CNTL
, info
) | BUS_HOST_ERR_ACK
|
695 BUS_FIFO_ERR_ACK
, info
);
698 static void reset_GTC_3D_engine(const struct fb_info_aty
*info
)
700 aty_st_le32(SCALE_3D_CNTL
, 0xc0, info
);
701 mdelay(GTC_3D_RESET_DELAY
);
702 aty_st_le32(SETUP_CNTL
, 0x00, info
);
703 mdelay(GTC_3D_RESET_DELAY
);
704 aty_st_le32(SCALE_3D_CNTL
, 0x00, info
);
705 mdelay(GTC_3D_RESET_DELAY
);
708 static void init_engine(const struct atyfb_par
*par
, struct fb_info_aty
*info
)
712 /* determine modal information from global mode structure */
713 pitch_value
= par
->crtc
.vxres
;
715 if (par
->crtc
.bpp
== 24) {
716 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
717 /* horizontal coordinates and widths must be adjusted */
718 pitch_value
= pitch_value
* 3;
721 /* On GTC (RagePro), we need to reset the 3D engine before */
722 if (Gx
== LB_CHIP_ID
|| Gx
== LD_CHIP_ID
|| Gx
== LI_CHIP_ID
||
723 Gx
== LP_CHIP_ID
|| Gx
== GB_CHIP_ID
|| Gx
== GD_CHIP_ID
||
724 Gx
== GI_CHIP_ID
|| Gx
== GP_CHIP_ID
|| Gx
== GQ_CHIP_ID
||
725 Gx
== LM_CHIP_ID
|| Gx
== LN_CHIP_ID
)
726 reset_GTC_3D_engine(info
);
728 /* Reset engine, enable, and clear any engine errors */
730 /* Ensure that vga page pointers are set to zero - the upper */
731 /* page pointers are set to 1 to handle overflows in the */
733 aty_st_le32(MEM_VGA_WP_SEL
, 0x00010000, info
);
734 aty_st_le32(MEM_VGA_RP_SEL
, 0x00010000, info
);
736 /* ---- Setup standard engine context ---- */
738 /* All GUI registers here are FIFOed - therefore, wait for */
739 /* the appropriate number of empty FIFO entries */
740 wait_for_fifo(14, info
);
742 /* enable all registers to be loaded for context loads */
743 aty_st_le32(CONTEXT_MASK
, 0xFFFFFFFF, info
);
745 /* set destination pitch to modal pitch, set offset to zero */
746 aty_st_le32(DST_OFF_PITCH
, (pitch_value
/ 8) << 22, info
);
748 /* zero these registers (set them to a known state) */
749 aty_st_le32(DST_Y_X
, 0, info
);
750 aty_st_le32(DST_HEIGHT
, 0, info
);
751 aty_st_le32(DST_BRES_ERR
, 0, info
);
752 aty_st_le32(DST_BRES_INC
, 0, info
);
753 aty_st_le32(DST_BRES_DEC
, 0, info
);
755 /* set destination drawing attributes */
756 aty_st_le32(DST_CNTL
, DST_LAST_PEL
| DST_Y_TOP_TO_BOTTOM
|
757 DST_X_LEFT_TO_RIGHT
, info
);
759 /* set source pitch to modal pitch, set offset to zero */
760 aty_st_le32(SRC_OFF_PITCH
, (pitch_value
/ 8) << 22, info
);
762 /* set these registers to a known state */
763 aty_st_le32(SRC_Y_X
, 0, info
);
764 aty_st_le32(SRC_HEIGHT1_WIDTH1
, 1, info
);
765 aty_st_le32(SRC_Y_X_START
, 0, info
);
766 aty_st_le32(SRC_HEIGHT2_WIDTH2
, 1, info
);
768 /* set source pixel retrieving attributes */
769 aty_st_le32(SRC_CNTL
, SRC_LINE_X_LEFT_TO_RIGHT
, info
);
771 /* set host attributes */
772 wait_for_fifo(13, info
);
773 aty_st_le32(HOST_CNTL
, 0, info
);
775 /* set pattern attributes */
776 aty_st_le32(PAT_REG0
, 0, info
);
777 aty_st_le32(PAT_REG1
, 0, info
);
778 aty_st_le32(PAT_CNTL
, 0, info
);
780 /* set scissors to modal size */
781 aty_st_le32(SC_LEFT
, 0, info
);
782 aty_st_le32(SC_TOP
, 0, info
);
783 aty_st_le32(SC_BOTTOM
, par
->crtc
.vyres
-1, info
);
784 aty_st_le32(SC_RIGHT
, pitch_value
-1, info
);
786 /* set background color to minimum value (usually BLACK) */
787 aty_st_le32(DP_BKGD_CLR
, 0, info
);
789 /* set foreground color to maximum value (usually WHITE) */
790 aty_st_le32(DP_FRGD_CLR
, 0xFFFFFFFF, info
);
792 /* set write mask to effect all pixel bits */
793 aty_st_le32(DP_WRITE_MASK
, 0xFFFFFFFF, info
);
795 /* set foreground mix to overpaint and background mix to */
797 aty_st_le32(DP_MIX
, FRGD_MIX_S
| BKGD_MIX_D
, info
);
799 /* set primary source pixel channel to foreground color */
801 aty_st_le32(DP_SRC
, FRGD_SRC_FRGD_CLR
, info
);
803 /* set compare functionality to false (no-effect on */
805 wait_for_fifo(3, info
);
806 aty_st_le32(CLR_CMP_CLR
, 0, info
);
807 aty_st_le32(CLR_CMP_MASK
, 0xFFFFFFFF, info
);
808 aty_st_le32(CLR_CMP_CNTL
, 0, info
);
810 /* set pixel depth */
811 wait_for_fifo(2, info
);
812 aty_st_le32(DP_PIX_WIDTH
, par
->crtc
.dp_pix_width
, info
);
813 aty_st_le32(DP_CHAIN_MASK
, par
->crtc
.dp_chain_mask
, info
);
815 wait_for_fifo(5, info
);
816 aty_st_le32(SCALE_3D_CNTL
, 0, info
);
817 aty_st_le32(Z_CNTL
, 0, info
);
818 aty_st_le32(CRTC_INT_CNTL
, aty_ld_le32(CRTC_INT_CNTL
, info
) & ~0x20, info
);
819 aty_st_le32(GUI_TRAJ_CNTL
, 0x100023, info
);
821 /* insure engine is idle before leaving */
825 static void aty_st_514(int offset
, u8 val
, const struct fb_info_aty
*info
)
827 aty_st_8(DAC_CNTL
, 1, info
);
828 /* right addr byte */
829 aty_st_8(DAC_W_INDEX
, offset
& 0xff, info
);
831 aty_st_8(DAC_DATA
, (offset
>> 8) & 0xff, info
);
832 aty_st_8(DAC_MASK
, val
, info
);
833 aty_st_8(DAC_CNTL
, 0, info
);
836 static void aty_st_pll(int offset
, u8 val
, const struct fb_info_aty
*info
)
838 /* write addr byte */
839 aty_st_8(CLOCK_CNTL
+ 1, (offset
<< 2) | PLL_WR_EN
, info
);
840 /* write the register value */
841 aty_st_8(CLOCK_CNTL
+ 2, val
, info
);
842 aty_st_8(CLOCK_CNTL
+ 1, (offset
<< 2) & ~PLL_WR_EN
, info
);
845 static u8
aty_ld_pll(int offset
, const struct fb_info_aty
*info
)
849 /* write addr byte */
850 aty_st_8(CLOCK_CNTL
+ 1, (offset
<< 2), info
);
851 /* read the register value */
852 res
= aty_ld_8(CLOCK_CNTL
+ 2, info
);
856 #if defined(CONFIG_PPC)
859 * Apple monitor sense
862 static int read_aty_sense(const struct fb_info_aty
*info
)
866 aty_st_le32(GP_IO
, 0x31003100, info
); /* drive outputs high */
868 aty_st_le32(GP_IO
, 0, info
); /* turn off outputs */
870 i
= aty_ld_le32(GP_IO
, info
); /* get primary sense value */
871 sense
= ((i
& 0x3000) >> 3) | (i
& 0x100);
873 /* drive each sense line low in turn and collect the other 2 */
874 aty_st_le32(GP_IO
, 0x20000000, info
); /* drive A low */
876 i
= aty_ld_le32(GP_IO
, info
);
877 sense
|= ((i
& 0x1000) >> 7) | ((i
& 0x100) >> 4);
878 aty_st_le32(GP_IO
, 0x20002000, info
); /* drive A high again */
881 aty_st_le32(GP_IO
, 0x10000000, info
); /* drive B low */
883 i
= aty_ld_le32(GP_IO
, info
);
884 sense
|= ((i
& 0x2000) >> 10) | ((i
& 0x100) >> 6);
885 aty_st_le32(GP_IO
, 0x10001000, info
); /* drive B high again */
888 aty_st_le32(GP_IO
, 0x01000000, info
); /* drive C low */
890 sense
|= (aty_ld_le32(GP_IO
, info
) & 0x3000) >> 12;
891 aty_st_le32(GP_IO
, 0, info
); /* turn off outputs */
896 #endif /* defined(CONFIG_PPC) */
898 /* ------------------------------------------------------------------------- */
901 * Hardware Cursor support.
904 static u8 cursor_pixel_map
[2] = { 0, 15 };
905 static u8 cursor_color_map
[2] = { 0, 0xff };
907 static u8 cursor_bits_lookup
[16] =
909 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
910 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
913 static u8 cursor_mask_lookup
[16] =
915 0xaa, 0x2a, 0x8a, 0x0a, 0xa2, 0x22, 0x82, 0x02,
916 0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00
920 aty_set_cursor_color(struct fb_info_aty
*fb
, u8
*pixel
,
921 u8
*red
, u8
*green
, u8
*blue
)
923 struct aty_cursor
*c
= fb
->cursor
;
930 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
931 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
935 for (i
= 0; i
< 2; i
++) {
936 c
->color
[i
] = (u32
)red
[i
] << 24;
937 c
->color
[i
] |= (u32
)green
[i
] << 16;
938 c
->color
[i
] |= (u32
)blue
[i
] << 8;
939 c
->color
[i
] |= (u32
)pixel
[i
];
942 wait_for_fifo(2, fb
);
943 aty_st_le32(CUR_CLR0
, c
->color
[0], fb
);
944 aty_st_le32(CUR_CLR1
, c
->color
[1], fb
);
948 aty_set_cursor_shape(struct fb_info_aty
*fb
)
950 struct aty_cursor
*c
= fb
->cursor
;
958 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
959 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
964 for (y
= 0; y
< c
->size
.y
; y
++) {
965 for (x
= 0; x
< c
->size
.x
>> 2; x
++) {
968 fb_writeb (cursor_mask_lookup
[m
>> 4] |
969 cursor_bits_lookup
[(b
& m
) >> 4],
971 fb_writeb (cursor_mask_lookup
[m
& 0x0f] |
972 cursor_bits_lookup
[(b
& m
) & 0x0f],
975 for ( ; x
< 8; x
++) {
976 fb_writeb (0xaa, ram
++);
977 fb_writeb (0xaa, ram
++);
980 fb_memset (ram
, 0xaa, (64 - c
->size
.y
) * 16);
984 aty_set_cursor(struct fb_info_aty
*fb
, int on
)
986 struct atyfb_par
*par
= &fb
->current_par
;
987 struct aty_cursor
*c
= fb
->cursor
;
995 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
996 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
1001 x
= c
->pos
.x
- c
->hot
.x
- par
->crtc
.xoffset
;
1009 y
= c
->pos
.y
- c
->hot
.y
- par
->crtc
.yoffset
;
1017 wait_for_fifo(4, fb
);
1018 aty_st_le32(CUR_OFFSET
, (c
->offset
>> 3) + (yoff
<< 1), fb
);
1019 aty_st_le32(CUR_HORZ_VERT_OFF
,
1020 ((u32
)(64 - c
->size
.y
+ yoff
) << 16) | xoff
, fb
);
1021 aty_st_le32(CUR_HORZ_VERT_POSN
, ((u32
)y
<< 16) | x
, fb
);
1022 aty_st_le32(GEN_TEST_CNTL
, aty_ld_le32(GEN_TEST_CNTL
, fb
)
1023 | HWCURSOR_ENABLE
, fb
);
1025 wait_for_fifo(1, fb
);
1026 aty_st_le32(GEN_TEST_CNTL
,
1027 aty_ld_le32(GEN_TEST_CNTL
, fb
) & ~HWCURSOR_ENABLE
,
1030 if (fb
->blitter_may_be_busy
)
1035 aty_cursor_timer_handler(unsigned long dev_addr
)
1037 struct fb_info_aty
*fb
= (struct fb_info_aty
*)dev_addr
;
1042 if (!fb
->cursor
->enable
)
1045 if (fb
->cursor
->vbl_cnt
&& --fb
->cursor
->vbl_cnt
== 0) {
1046 fb
->cursor
->on
^= 1;
1047 aty_set_cursor(fb
, fb
->cursor
->on
);
1048 fb
->cursor
->vbl_cnt
= fb
->cursor
->blink_rate
;
1052 fb
->cursor
->timer
->expires
= jiffies
+ (HZ
/ 50);
1053 add_timer(fb
->cursor
->timer
);
1057 atyfb_cursor(struct display
*p
, int mode
, int x
, int y
)
1059 struct fb_info_aty
*fb
= (struct fb_info_aty
*)p
->fb_info
;
1060 struct aty_cursor
*c
= fb
->cursor
;
1066 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
1067 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
1073 if (c
->pos
.x
== x
&& c
->pos
.y
== y
&& (mode
== CM_ERASE
) == !c
->enable
)
1078 aty_set_cursor(fb
, 0);
1090 aty_set_cursor(fb
, 1);
1092 c
->vbl_cnt
= CURSOR_DRAW_DELAY
;
1098 static struct fb_info_aty
*fb_list
= NULL
;
1100 static struct aty_cursor
* __init
1101 aty_init_cursor(struct fb_info_aty
*fb
)
1103 struct aty_cursor
*cursor
;
1106 cursor
= kmalloc(sizeof(struct aty_cursor
), GFP_ATOMIC
);
1109 memset(cursor
, 0, sizeof(*cursor
));
1111 cursor
->timer
= kmalloc(sizeof(*cursor
->timer
), GFP_KERNEL
);
1112 if (!cursor
->timer
) {
1116 memset(cursor
->timer
, 0, sizeof(*cursor
->timer
));
1118 cursor
->blink_rate
= DEFAULT_CURSOR_BLINK_RATE
;
1119 fb
->total_vram
-= PAGE_SIZE
;
1120 cursor
->offset
= fb
->total_vram
;
1123 addr
= fb
->frame_buffer
- 0x800000 + cursor
->offset
;
1124 cursor
->ram
= (u8
*)addr
;
1127 addr
= fb
->frame_buffer_phys
- 0x800000 + cursor
->offset
;
1128 cursor
->ram
= (u8
*)ioremap(addr
, 1024);
1130 addr
= fb
->frame_buffer
+ cursor
->offset
;
1131 cursor
->ram
= (u8
*)addr
;
1135 if (! cursor
->ram
) {
1141 init_timer(cursor
->timer
);
1142 cursor
->timer
->expires
= jiffies
+ (HZ
/ 50);
1143 cursor
->timer
->data
= (unsigned long)fb
;
1144 cursor
->timer
->function
= aty_cursor_timer_handler
;
1145 add_timer(cursor
->timer
);
1152 atyfb_set_font(struct display
*d
, int width
, int height
)
1154 struct fb_info_aty
*fb
= (struct fb_info_aty
*)d
->fb_info
;
1155 struct aty_cursor
*c
= fb
->cursor
;
1159 if (!width
|| !height
) {
1169 memset(c
->bits
, 0xff, sizeof(c
->bits
));
1170 memset(c
->mask
, 0, sizeof(c
->mask
));
1172 for (i
= 0, j
= width
; j
>= 0; j
-= 8, i
++) {
1173 c
->mask
[i
][height
-2] = (j
>= 8) ? 0xff : (0xff << (8 - j
));
1174 c
->mask
[i
][height
-1] = (j
>= 8) ? 0xff : (0xff << (8 - j
));
1177 aty_set_cursor_color(fb
, cursor_pixel_map
, cursor_color_map
,
1178 cursor_color_map
, cursor_color_map
);
1179 aty_set_cursor_shape(fb
);
1187 /* ------------------------------------------------------------------------- */
1193 static void aty_set_crtc(const struct fb_info_aty
*info
,
1194 const struct crtc
*crtc
)
1196 aty_st_le32(CRTC_H_TOTAL_DISP
, crtc
->h_tot_disp
, info
);
1197 aty_st_le32(CRTC_H_SYNC_STRT_WID
, crtc
->h_sync_strt_wid
, info
);
1198 aty_st_le32(CRTC_V_TOTAL_DISP
, crtc
->v_tot_disp
, info
);
1199 aty_st_le32(CRTC_V_SYNC_STRT_WID
, crtc
->v_sync_strt_wid
, info
);
1200 aty_st_le32(CRTC_VLINE_CRNT_VLINE
, 0, info
);
1201 aty_st_le32(CRTC_OFF_PITCH
, crtc
->off_pitch
, info
);
1202 aty_st_le32(CRTC_GEN_CNTL
, crtc
->gen_cntl
, info
);
1205 static int aty_var_to_crtc(const struct fb_info_aty
*info
,
1206 const struct fb_var_screeninfo
*var
,
1209 u32 xres
, yres
, vxres
, vyres
, xoffset
, yoffset
, bpp
;
1210 u32 left
, right
, upper
, lower
, hslen
, vslen
, sync
, vmode
;
1211 u32 h_total
, h_disp
, h_sync_strt
, h_sync_dly
, h_sync_wid
, h_sync_pol
;
1212 u32 v_total
, v_disp
, v_sync_strt
, v_sync_wid
, v_sync_pol
, c_sync
;
1213 u32 pix_width
, dp_pix_width
, dp_chain_mask
;
1218 vxres
= var
->xres_virtual
;
1219 vyres
= var
->yres_virtual
;
1220 xoffset
= var
->xoffset
;
1221 yoffset
= var
->yoffset
;
1222 bpp
= var
->bits_per_pixel
;
1223 left
= var
->left_margin
;
1224 right
= var
->right_margin
;
1225 upper
= var
->upper_margin
;
1226 lower
= var
->lower_margin
;
1227 hslen
= var
->hsync_len
;
1228 vslen
= var
->vsync_len
;
1232 /* convert (and round up) and validate */
1233 xres
= (xres
+7) & ~7;
1234 xoffset
= (xoffset
+7) & ~7;
1235 vxres
= (vxres
+7) & ~7;
1236 if (vxres
< xres
+xoffset
)
1237 vxres
= xres
+xoffset
;
1240 FAIL("h_disp too large");
1241 h_sync_strt
= h_disp
+(right
/8);
1242 if (h_sync_strt
> 0x1ff)
1243 FAIL("h_sync_start too large");
1244 h_sync_dly
= right
& 7;
1245 h_sync_wid
= (hslen
+7)/8;
1246 if (h_sync_wid
> 0x1f)
1247 FAIL("h_sync_wid too large");
1248 h_total
= h_sync_strt
+h_sync_wid
+(h_sync_dly
+left
+7)/8;
1249 if (h_total
> 0x1ff)
1250 FAIL("h_total too large");
1251 h_sync_pol
= sync
& FB_SYNC_HOR_HIGH_ACT
? 0 : 1;
1253 if (vyres
< yres
+yoffset
)
1254 vyres
= yres
+yoffset
;
1257 FAIL("v_disp too large");
1258 v_sync_strt
= v_disp
+lower
;
1259 if (v_sync_strt
> 0x7ff)
1260 FAIL("v_sync_strt too large");
1262 if (v_sync_wid
> 0x1f)
1263 FAIL("v_sync_wid too large");
1264 v_total
= v_sync_strt
+v_sync_wid
+upper
;
1265 if (v_total
> 0x7ff)
1266 FAIL("v_total too large");
1267 v_sync_pol
= sync
& FB_SYNC_VERT_HIGH_ACT
? 0 : 1;
1269 c_sync
= sync
& FB_SYNC_COMP_HIGH_ACT
? CRTC_CSYNC_EN
: 0;
1273 pix_width
= CRTC_PIX_WIDTH_8BPP
;
1274 dp_pix_width
= HOST_8BPP
| SRC_8BPP
| DST_8BPP
| BYTE_ORDER_LSB_TO_MSB
;
1275 dp_chain_mask
= 0x8080;
1276 } else if (bpp
<= 16) {
1278 pix_width
= CRTC_PIX_WIDTH_15BPP
;
1279 dp_pix_width
= HOST_15BPP
| SRC_15BPP
| DST_15BPP
|
1280 BYTE_ORDER_LSB_TO_MSB
;
1281 dp_chain_mask
= 0x4210;
1282 } else if ((bpp
<= 24) && (Gx
!= GX_CHIP_ID
) && (Gx
!= CX_CHIP_ID
)) {
1284 pix_width
= CRTC_PIX_WIDTH_24BPP
;
1285 dp_pix_width
= HOST_8BPP
| SRC_8BPP
| DST_8BPP
| BYTE_ORDER_LSB_TO_MSB
;
1286 dp_chain_mask
= 0x8080;
1287 } else if (bpp
<= 32) {
1289 pix_width
= CRTC_PIX_WIDTH_32BPP
;
1290 dp_pix_width
= HOST_32BPP
| SRC_32BPP
| DST_32BPP
|
1291 BYTE_ORDER_LSB_TO_MSB
;
1292 dp_chain_mask
= 0x8080;
1294 FAIL("invalid bpp");
1296 if (vxres
*vyres
*bpp
/8 > info
->total_vram
)
1297 FAIL("not enough video RAM");
1299 if ((vmode
& FB_VMODE_MASK
) != FB_VMODE_NONINTERLACED
)
1300 FAIL("invalid vmode");
1303 crtc
->vxres
= vxres
;
1304 crtc
->vyres
= vyres
;
1305 crtc
->xoffset
= xoffset
;
1306 crtc
->yoffset
= yoffset
;
1308 crtc
->h_tot_disp
= h_total
| (h_disp
<<16);
1309 crtc
->h_sync_strt_wid
= (h_sync_strt
& 0xff) | (h_sync_dly
<<8) |
1310 ((h_sync_strt
& 0x100)<<4) | (h_sync_wid
<<16) |
1312 crtc
->v_tot_disp
= v_total
| (v_disp
<<16);
1313 crtc
->v_sync_strt_wid
= v_sync_strt
| (v_sync_wid
<<16) | (v_sync_pol
<<21);
1314 crtc
->off_pitch
= ((yoffset
*vxres
+xoffset
)*bpp
/64) | (vxres
<<19);
1315 crtc
->gen_cntl
= pix_width
| c_sync
| CRTC_EXT_DISP_EN
| CRTC_ENABLE
;
1316 if ((Gx
== CT_CHIP_ID
) || (Gx
== ET_CHIP_ID
) ||
1317 ((Gx
== VT_CHIP_ID
|| Gx
== GT_CHIP_ID
) && !(Rev
& 0x07))) {
1319 /* FIXME: magic FIFO values */
1320 crtc
->gen_cntl
|= aty_ld_le32(CRTC_GEN_CNTL
, info
) & 0x000e0000;
1322 crtc
->dp_pix_width
= dp_pix_width
;
1323 crtc
->dp_chain_mask
= dp_chain_mask
;
1329 static int aty_set_dac_ATI68860_B(const struct fb_info_aty
*info
, u32 bpp
,
1332 u32 gModeReg
, devSetupRegA
, temp
, mask
;
1340 devSetupRegA
= 0x60 | 0x00 /*(info->mach64DAC8Bit ? 0x00 : 0x01) */;
1344 devSetupRegA
= 0x60;
1348 devSetupRegA
= 0x60;
1352 devSetupRegA
= 0x60;
1356 devSetupRegA
= 0x60;
1362 devSetupRegA
= 0x61;
1365 temp
= aty_ld_8(DAC_CNTL
, info
);
1366 aty_st_8(DAC_CNTL
, (temp
& ~DAC_EXT_SEL_RS2
) | DAC_EXT_SEL_RS3
, info
);
1368 aty_st_8(DAC_REGS
+ 2, 0x1D, info
);
1369 aty_st_8(DAC_REGS
+ 3, gModeReg
, info
);
1370 aty_st_8(DAC_REGS
, 0x02, info
);
1372 temp
= aty_ld_8(DAC_CNTL
, info
);
1373 aty_st_8(DAC_CNTL
, temp
| DAC_EXT_SEL_RS2
| DAC_EXT_SEL_RS3
, info
);
1375 if (info
->total_vram
< MEM_SIZE_1M
)
1377 else if (info
->total_vram
== MEM_SIZE_1M
)
1382 /* The following assumes that the BIOS has correctly set R7 of the
1383 * Device Setup Register A at boot time.
1385 #define A860_DELAY_L 0x80
1387 temp
= aty_ld_8(DAC_REGS
, info
);
1388 aty_st_8(DAC_REGS
, (devSetupRegA
| mask
) | (temp
& A860_DELAY_L
), info
);
1389 temp
= aty_ld_8(DAC_CNTL
, info
);
1390 aty_st_8(DAC_CNTL
, (temp
& ~(DAC_EXT_SEL_RS2
| DAC_EXT_SEL_RS3
)), info
);
1395 static int aty_set_dac_ATT21C498(const struct fb_info_aty
*info
,
1396 const struct pll_18818
*pll
, u32 bpp
)
1402 dotClock
= 100000000 / pll
->period_in_ps
;
1406 if (dotClock
> 8000) {
1426 if (1 /* info->mach64DAC8Bit */)
1429 aty_dac_waste4(info
);
1430 aty_st_8(DAC_REGS
+ 2, DACMask
, info
);
1435 void aty_dac_waste4(const struct fb_info_aty
*info
)
1437 (void)aty_ld_8(DAC_REGS
, info
);
1439 (void)aty_ld_8(DAC_REGS
+ 2, info
);
1440 (void)aty_ld_8(DAC_REGS
+ 2, info
);
1441 (void)aty_ld_8(DAC_REGS
+ 2, info
);
1442 (void)aty_ld_8(DAC_REGS
+ 2, info
);
1446 static void aty_set_dac_514(const struct fb_info_aty
*info
, u32 bpp
)
1452 u8 pixel_cntl_index
;
1455 { 0, 0x41, 0x03, 0x71, 0x45 }, /* 8 bpp */
1456 { 0, 0x45, 0x04, 0x0c, 0x01 }, /* 555 */
1457 { 0, 0x45, 0x06, 0x0e, 0x00 }, /* XRGB */
1473 aty_st_514(0x90, 0x00, info
); /* VRAM Mask Low */
1474 aty_st_514(0x04, tab
[i
].pixel_dly
, info
); /* Horizontal Sync Control */
1475 aty_st_514(0x05, 0x00, info
); /* Power Management */
1476 aty_st_514(0x02, 0x01, info
); /* Misc Clock Control */
1477 aty_st_514(0x71, tab
[i
].misc2_cntl
, info
); /* Misc Control 2 */
1478 aty_st_514(0x0a, tab
[i
].pixel_rep
, info
); /* Pixel Format */
1479 aty_st_514(tab
[i
].pixel_cntl_index
, tab
[i
].pixel_cntl_v1
, info
);
1480 /* Misc Control 2 / 16 BPP Control / 32 BPP Control */
1483 static int aty_crtc_to_var(const struct crtc
*crtc
,
1484 struct fb_var_screeninfo
*var
)
1486 u32 xres
, yres
, bpp
, left
, right
, upper
, lower
, hslen
, vslen
, sync
;
1487 u32 h_total
, h_disp
, h_sync_strt
, h_sync_dly
, h_sync_wid
, h_sync_pol
;
1488 u32 v_total
, v_disp
, v_sync_strt
, v_sync_wid
, v_sync_pol
, c_sync
;
1492 h_total
= crtc
->h_tot_disp
& 0x1ff;
1493 h_disp
= (crtc
->h_tot_disp
>>16) & 0xff;
1494 h_sync_strt
= (crtc
->h_sync_strt_wid
& 0xff) |
1495 ((crtc
->h_sync_strt_wid
>>4) & 0x100);
1496 h_sync_dly
= (crtc
->h_sync_strt_wid
>>8) & 0x7;
1497 h_sync_wid
= (crtc
->h_sync_strt_wid
>>16) & 0x1f;
1498 h_sync_pol
= (crtc
->h_sync_strt_wid
>>21) & 0x1;
1499 v_total
= crtc
->v_tot_disp
& 0x7ff;
1500 v_disp
= (crtc
->v_tot_disp
>>16) & 0x7ff;
1501 v_sync_strt
= crtc
->v_sync_strt_wid
& 0x7ff;
1502 v_sync_wid
= (crtc
->v_sync_strt_wid
>>16) & 0x1f;
1503 v_sync_pol
= (crtc
->v_sync_strt_wid
>>21) & 0x1;
1504 c_sync
= crtc
->gen_cntl
& CRTC_CSYNC_EN
? 1 : 0;
1505 pix_width
= crtc
->gen_cntl
& CRTC_PIX_WIDTH_MASK
;
1508 xres
= (h_disp
+1)*8;
1510 left
= (h_total
-h_sync_strt
-h_sync_wid
)*8-h_sync_dly
;
1511 right
= (h_sync_strt
-h_disp
)*8+h_sync_dly
;
1512 hslen
= h_sync_wid
*8;
1513 upper
= v_total
-v_sync_strt
-v_sync_wid
;
1514 lower
= v_sync_strt
-v_disp
;
1516 sync
= (h_sync_pol
? 0 : FB_SYNC_HOR_HIGH_ACT
) |
1517 (v_sync_pol
? 0 : FB_SYNC_VERT_HIGH_ACT
) |
1518 (c_sync
? FB_SYNC_COMP_HIGH_ACT
: 0);
1520 switch (pix_width
) {
1522 case CRTC_PIX_WIDTH_4BPP
:
1524 var
->red
.offset
= 0;
1525 var
->red
.length
= 8;
1526 var
->green
.offset
= 0;
1527 var
->green
.length
= 8;
1528 var
->blue
.offset
= 0;
1529 var
->blue
.length
= 8;
1530 var
->transp
.offset
= 0;
1531 var
->transp
.length
= 0;
1534 case CRTC_PIX_WIDTH_8BPP
:
1536 var
->red
.offset
= 0;
1537 var
->red
.length
= 8;
1538 var
->green
.offset
= 0;
1539 var
->green
.length
= 8;
1540 var
->blue
.offset
= 0;
1541 var
->blue
.length
= 8;
1542 var
->transp
.offset
= 0;
1543 var
->transp
.length
= 0;
1545 case CRTC_PIX_WIDTH_15BPP
: /* RGB 555 */
1547 var
->red
.offset
= 10;
1548 var
->red
.length
= 5;
1549 var
->green
.offset
= 5;
1550 var
->green
.length
= 5;
1551 var
->blue
.offset
= 0;
1552 var
->blue
.length
= 5;
1553 var
->transp
.offset
= 0;
1554 var
->transp
.length
= 0;
1557 case CRTC_PIX_WIDTH_16BPP
: /* RGB 565 */
1559 var
->red
.offset
= 11;
1560 var
->red
.length
= 5;
1561 var
->green
.offset
= 5;
1562 var
->green
.length
= 6;
1563 var
->blue
.offset
= 0;
1564 var
->blue
.length
= 5;
1565 var
->transp
.offset
= 0;
1566 var
->transp
.length
= 0;
1569 case CRTC_PIX_WIDTH_24BPP
: /* RGB 888 */
1571 var
->red
.offset
= 16;
1572 var
->red
.length
= 8;
1573 var
->green
.offset
= 8;
1574 var
->green
.length
= 8;
1575 var
->blue
.offset
= 0;
1576 var
->blue
.length
= 8;
1577 var
->transp
.offset
= 0;
1578 var
->transp
.length
= 0;
1580 case CRTC_PIX_WIDTH_32BPP
: /* ARGB 8888 */
1582 var
->red
.offset
= 16;
1583 var
->red
.length
= 8;
1584 var
->green
.offset
= 8;
1585 var
->green
.length
= 8;
1586 var
->blue
.offset
= 0;
1587 var
->blue
.length
= 8;
1588 var
->transp
.offset
= 24;
1589 var
->transp
.length
= 8;
1592 FAIL("Invalid pixel width");
1598 var
->xres_virtual
= crtc
->vxres
;
1599 var
->yres_virtual
= crtc
->vyres
;
1600 var
->bits_per_pixel
= bpp
;
1601 var
->xoffset
= crtc
->xoffset
;
1602 var
->yoffset
= crtc
->yoffset
;
1603 var
->left_margin
= left
;
1604 var
->right_margin
= right
;
1605 var
->upper_margin
= upper
;
1606 var
->lower_margin
= lower
;
1607 var
->hsync_len
= hslen
;
1608 var
->vsync_len
= vslen
;
1610 var
->vmode
= FB_VMODE_NONINTERLACED
;
1615 /* ------------------------------------------------------------------------- */
1618 * PLL programming (Mach64 GX family)
1620 * FIXME: use function pointer tables instead of switch statements
1623 static void aty_set_pll_gx(const struct fb_info_aty
*info
,
1624 const struct pll_gx
*pll
)
1626 switch (info
->clk_type
) {
1627 case CLK_ATI18818_1
:
1628 aty_st_8(CLOCK_CNTL
, pll
->m
, info
);
1631 aty_st_514(0x06, 0x02, info
); /* DAC Operation */
1632 aty_st_514(0x10, 0x01, info
); /* PLL Control 1 */
1633 aty_st_514(0x70, 0x01, info
); /* Misc Control 1 */
1634 aty_st_514(0x8f, 0x1f, info
); /* PLL Ref. Divider Input */
1635 aty_st_514(0x03, 0x00, info
); /* Sync Control */
1636 aty_st_514(0x05, 0x00, info
); /* Power Management */
1637 aty_st_514(0x20, pll
->m
, info
); /* F0 / M0 */
1638 aty_st_514(0x21, pll
->n
, info
); /* F1 / N0 */
1644 static int aty_var_to_pll_18818(u32 period_in_ps
, struct pll_18818
*pll
)
1646 u32 MHz100
; /* in 0.01 MHz */
1650 /* Calculate the programming word */
1651 MHz100
= 100000000 / period_in_ps
;
1656 if (MHz100
> MAX_FREQ_2595
) {
1657 MHz100
= MAX_FREQ_2595
;
1659 } else if (MHz100
< ABS_MIN_FREQ_2595
) {
1660 program_bits
= 0; /* MHz100 = 257 */
1663 while (MHz100
< MIN_FREQ_2595
) {
1669 MHz100
= (REF_DIV_2595
* MHz100
) / REF_FREQ_2595
;
1671 MHz100
+= 500; /* + 0.5 round */
1674 if (program_bits
== -1) {
1675 program_bits
= MHz100
- N_ADJ_2595
;
1676 switch (post_divider
) {
1678 program_bits
|= 0x0600;
1681 program_bits
|= 0x0400;
1684 program_bits
|= 0x0200;
1692 program_bits
|= STOP_BITS_2595
;
1694 pll
->program_bits
= program_bits
;
1695 pll
->locationAddr
= 0;
1696 pll
->post_divider
= post_divider
;
1697 pll
->period_in_ps
= period_in_ps
;
1702 static u32
aty_pll_18818_to_var(const struct pll_18818
*pll
)
1704 return(pll
->period_in_ps
); /* default for now */
1707 static void aty_set_pll18818(const struct fb_info_aty
*info
,
1708 const struct pll_18818
*pll
)
1716 u8 old_crtc_ext_disp
;
1718 old_clock_cntl
= aty_ld_8(CLOCK_CNTL
, info
);
1719 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, 0, info
);
1721 old_crtc_ext_disp
= aty_ld_8(CRTC_GEN_CNTL
+ 3, info
);
1722 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
| (CRTC_EXT_DISP_EN
>> 24),
1725 udelay(15000); /* delay for 50 (15) ms */
1727 program_bits
= pll
->program_bits
;
1728 locationAddr
= pll
->locationAddr
;
1730 /* Program the clock chip */
1731 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, 0, info
); /* Strobe = 0 */
1732 aty_StrobeClock(info
);
1733 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, 1, info
); /* Strobe = 0 */
1734 aty_StrobeClock(info
);
1736 aty_ICS2595_put1bit(1, info
); /* Send start bits */
1737 aty_ICS2595_put1bit(0, info
); /* Start bit */
1738 aty_ICS2595_put1bit(0, info
); /* Read / ~Write */
1740 for (i
= 0; i
< 5; i
++) { /* Location 0..4 */
1741 aty_ICS2595_put1bit(locationAddr
& 1, info
);
1745 for (i
= 0; i
< 8 + 1 + 2 + 2; i
++) {
1746 aty_ICS2595_put1bit(program_bits
& 1, info
);
1750 udelay(1000); /* delay for 1 ms */
1752 (void)aty_ld_8(DAC_REGS
, info
); /* Clear DAC Counter */
1753 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
, info
);
1754 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, old_clock_cntl
| CLOCK_STROBE
,
1757 udelay(50000); /* delay for 50 (15) ms */
1758 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
,
1759 ((pll
->locationAddr
& 0x0F) | CLOCK_STROBE
), info
);
1765 static int aty_var_to_pll_408(u32 period_in_ps
, struct pll_18818
*pll
)
1767 u32 mhz100
; /* in 0.01 MHz */
1769 /* u32 post_divider; */
1770 u32 mach64MinFreq
, mach64MaxFreq
, mach64RefFreq
;
1772 u16 remainder
, preRemainder
;
1773 short divider
= 0, tempA
;
1775 /* Calculate the programming word */
1776 mhz100
= 100000000 / period_in_ps
;
1777 mach64MinFreq
= MIN_FREQ_2595
;
1778 mach64MaxFreq
= MAX_FREQ_2595
;
1779 mach64RefFreq
= REF_FREQ_2595
; /* 14.32 MHz */
1781 /* Calculate program word */
1783 program_bits
= 0xFF;
1785 if (mhz100
< mach64MinFreq
)
1786 mhz100
= mach64MinFreq
;
1787 if (mhz100
> mach64MaxFreq
)
1788 mhz100
= mach64MaxFreq
;
1790 while (mhz100
< (mach64MinFreq
<< 3)) {
1795 temp
= (unsigned int)mhz100
;
1796 temp
= (unsigned int)(temp
* (MIN_N_408
+ 2));
1797 temp
-= ((short)(mach64RefFreq
<< 1));
1800 preRemainder
= 0xFFFF;
1804 remainder
= tempB
% mach64RefFreq
;
1805 tempB
= tempB
/ mach64RefFreq
;
1806 if (((tempB
& 0xFFFF) <= 255) && (remainder
<= preRemainder
)) {
1807 preRemainder
= remainder
;
1810 divider
= (divider
& 0x00FF) + ((tempB
& 0xFF) << 8);
1814 } while(tempA
<= 32);
1816 program_bits
= divider
;
1819 pll
->program_bits
= program_bits
;
1820 pll
->locationAddr
= 0;
1821 pll
->post_divider
= divider
; /* fuer nix */
1822 pll
->period_in_ps
= period_in_ps
;
1827 static u32
aty_pll_408_to_var(const struct pll_18818
*pll
)
1829 return(pll
->period_in_ps
); /* default for now */
1832 static void aty_set_pll_408(const struct fb_info_aty
*info
,
1833 const struct pll_18818
*pll
)
1838 u8 tmpA
, tmpB
, tmpC
;
1839 char old_crtc_ext_disp
;
1841 old_crtc_ext_disp
= aty_ld_8(CRTC_GEN_CNTL
+ 3, info
);
1842 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
| (CRTC_EXT_DISP_EN
>> 24),
1845 program_bits
= pll
->program_bits
;
1846 locationAddr
= pll
->locationAddr
;
1849 aty_dac_waste4(info
);
1850 tmpB
= aty_ld_8(DAC_REGS
+ 2, info
) | 1;
1851 aty_dac_waste4(info
);
1852 aty_st_8(DAC_REGS
+ 2, tmpB
, info
);
1859 aty_st_8(DAC_REGS
, tmpB
, info
);
1860 aty_st_8(DAC_REGS
+ 2, tmpA
, info
);
1862 udelay(400); /* delay for 400 us */
1864 locationAddr
= (locationAddr
<< 2) + 0x40;
1865 tmpB
= locationAddr
;
1866 tmpA
= program_bits
>> 8;
1868 aty_st_8(DAC_REGS
, tmpB
, info
);
1869 aty_st_8(DAC_REGS
+ 2, tmpA
, info
);
1871 tmpB
= locationAddr
+ 1;
1872 tmpA
= (u8
)program_bits
;
1874 aty_st_8(DAC_REGS
, tmpB
, info
);
1875 aty_st_8(DAC_REGS
+ 2, tmpA
, info
);
1877 tmpB
= locationAddr
+ 2;
1880 aty_st_8(DAC_REGS
, tmpB
, info
);
1881 aty_st_8(DAC_REGS
+ 2, tmpA
, info
);
1883 udelay(400); /* delay for 400 us */
1884 tmpA
= tmpC
& (~(1 | 8));
1887 aty_st_8(DAC_REGS
, tmpB
, info
);
1888 aty_st_8(DAC_REGS
+ 2, tmpA
, info
);
1890 (void)aty_ld_8(DAC_REGS
, info
); /* Clear DAC Counter */
1891 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
, info
);
1897 static int aty_var_to_pll_1703(u32 period_in_ps
, struct pll_18818
*pll
)
1899 u32 mhz100
; /* in 0.01 MHz */
1901 /* u32 post_divider; */
1902 u32 mach64MinFreq
, mach64MaxFreq
, mach64RefFreq
;
1904 u16 remainder
, preRemainder
;
1905 short divider
= 0, tempA
;
1907 /* Calculate the programming word */
1908 mhz100
= 100000000 / period_in_ps
;
1909 mach64MinFreq
= MIN_FREQ_2595
;
1910 mach64MaxFreq
= MAX_FREQ_2595
;
1911 mach64RefFreq
= REF_FREQ_2595
; /* 14.32 MHz */
1913 /* Calculate program word */
1915 program_bits
= 0xE0;
1917 if (mhz100
< mach64MinFreq
)
1918 mhz100
= mach64MinFreq
;
1919 if (mhz100
> mach64MaxFreq
)
1920 mhz100
= mach64MaxFreq
;
1923 while (mhz100
< (mach64MinFreq
<< 3)) {
1928 temp
= (unsigned int)(mhz100
);
1929 temp
= (unsigned int)(temp
* (MIN_N_1703
+ 2));
1930 temp
-= (short)(mach64RefFreq
<< 1);
1933 preRemainder
= 0xffff;
1937 remainder
= tempB
% mach64RefFreq
;
1938 tempB
= tempB
/ mach64RefFreq
;
1940 if ((tempB
& 0xffff) <= 127 && (remainder
<= preRemainder
)) {
1941 preRemainder
= remainder
;
1944 divider
= (divider
& 0x00ff) + ((tempB
& 0xff) << 8);
1949 } while (tempA
<= (MIN_N_1703
<< 1));
1951 program_bits
= divider
;
1954 pll
->program_bits
= program_bits
;
1955 pll
->locationAddr
= 0;
1956 pll
->post_divider
= divider
; /* fuer nix */
1957 pll
->period_in_ps
= period_in_ps
;
1962 static u32
aty_pll_1703_to_var(const struct pll_18818
*pll
)
1964 return(pll
->period_in_ps
); /* default for now */
1967 static void aty_set_pll_1703(const struct fb_info_aty
*info
,
1968 const struct pll_18818
*pll
)
1973 char old_crtc_ext_disp
;
1975 old_crtc_ext_disp
= aty_ld_8(CRTC_GEN_CNTL
+ 3, info
);
1976 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
| (CRTC_EXT_DISP_EN
>> 24),
1979 program_bits
= pll
->program_bits
;
1980 locationAddr
= pll
->locationAddr
;
1983 aty_dac_waste4(info
);
1985 (void)aty_ld_8(DAC_REGS
+ 2, info
);
1986 aty_st_8(DAC_REGS
+2, (locationAddr
<< 1) + 0x20, info
);
1987 aty_st_8(DAC_REGS
+2, 0, info
);
1988 aty_st_8(DAC_REGS
+2, (program_bits
& 0xFF00) >> 8, info
);
1989 aty_st_8(DAC_REGS
+2, (program_bits
& 0xFF), info
);
1991 (void)aty_ld_8(DAC_REGS
, info
); /* Clear DAC Counter */
1992 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
, info
);
1998 static int aty_var_to_pll_8398(u32 period_in_ps
, struct pll_18818
*pll
)
2001 u32 tempA
, tempB
, fOut
, longMHz100
, diff
, preDiff
;
2003 u32 mhz100
; /* in 0.01 MHz */
2005 /* u32 post_divider; */
2006 u32 mach64MinFreq
, mach64MaxFreq
, mach64RefFreq
;
2007 u16 m
, n
, k
=0, save_m
, save_n
, twoToKth
;
2009 /* Calculate the programming word */
2010 mhz100
= 100000000 / period_in_ps
;
2011 mach64MinFreq
= MIN_FREQ_2595
;
2012 mach64MaxFreq
= MAX_FREQ_2595
;
2013 mach64RefFreq
= REF_FREQ_2595
; /* 14.32 MHz */
2018 /* Calculate program word */
2020 program_bits
= 0xE0;
2023 if (mhz100
< mach64MinFreq
)
2024 mhz100
= mach64MinFreq
;
2025 if (mhz100
> mach64MaxFreq
)
2026 mhz100
= mach64MaxFreq
;
2028 longMHz100
= mhz100
* 256 / 100; /* 8 bit scale this */
2030 while (mhz100
< (mach64MinFreq
<< 3))
2038 preDiff
= 0xFFFFFFFF;
2040 for (m
= MIN_M
; m
<= MAX_M
; m
++)
2042 for (n
= MIN_N
; n
<= MAX_N
; n
++)
2044 tempA
= (14.31818 * 65536);
2045 tempA
*= (n
+ 8); /* 43..256 */
2046 tempB
= twoToKth
* 256;
2047 tempB
*= (m
+ 2); /* 4..32 */
2048 fOut
= tempA
/ tempB
; /* 8 bit scale */
2050 if (longMHz100
> fOut
)
2051 diff
= longMHz100
- fOut
;
2053 diff
= fOut
- longMHz100
;
2064 program_bits
= (k
<< 6) + (save_m
) + (save_n
<< 8);
2067 pll
->program_bits
= program_bits
;
2068 pll
->locationAddr
= 0;
2069 pll
->post_divider
= 0;
2070 pll
->period_in_ps
= period_in_ps
;
2075 static u32
aty_pll_8398_to_var(const struct pll_18818
*pll
)
2077 return(pll
->period_in_ps
); /* default for now */
2080 static void aty_set_pll_8398(const struct fb_info_aty
*info
,
2081 const struct pll_18818
*pll
)
2086 char old_crtc_ext_disp
;
2089 old_crtc_ext_disp
= aty_ld_8(CRTC_GEN_CNTL
+ 3, info
);
2090 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
| (CRTC_EXT_DISP_EN
>> 24),
2093 program_bits
= pll
->program_bits
;
2094 locationAddr
= pll
->locationAddr
;
2097 tmp
= aty_ld_8(DAC_CNTL
, info
);
2098 aty_st_8(DAC_CNTL
, tmp
| DAC_EXT_SEL_RS2
| DAC_EXT_SEL_RS3
, info
);
2100 aty_st_8(DAC_REGS
, locationAddr
, info
);
2101 aty_st_8(DAC_REGS
+1, (program_bits
& 0xff00) >> 8, info
);
2102 aty_st_8(DAC_REGS
+1, (program_bits
& 0xff), info
);
2104 tmp
= aty_ld_8(DAC_CNTL
, info
);
2105 aty_st_8(DAC_CNTL
, (tmp
& ~DAC_EXT_SEL_RS2
) | DAC_EXT_SEL_RS3
, info
);
2107 (void)aty_ld_8(DAC_REGS
, info
); /* Clear DAC Counter */
2108 aty_st_8(CRTC_GEN_CNTL
+ 3, old_crtc_ext_disp
, info
);
2114 static int aty_var_to_pll_514(u32 vclk_per
, struct pll_gx
*pll
)
2117 * FIXME: use real calculations instead of using fixed values from the old
2121 u32 limit
; /* pixlock rounding limit (arbitrary) */
2122 u8 m
; /* (df<<6) | vco_div_count */
2123 u8 n
; /* ref_div_count */
2124 } RGB514_clocks
[7] = {
2125 { 8000, (3<<6) | 20, 9 }, /* 7395 ps / 135.2273 MHz */
2126 { 10000, (1<<6) | 19, 3 }, /* 9977 ps / 100.2273 MHz */
2127 { 13000, (1<<6) | 2, 3 }, /* 12509 ps / 79.9432 MHz */
2128 { 14000, (2<<6) | 8, 7 }, /* 13394 ps / 74.6591 MHz */
2129 { 16000, (1<<6) | 44, 6 }, /* 15378 ps / 65.0284 MHz */
2130 { 25000, (1<<6) | 15, 5 }, /* 17460 ps / 57.2727 MHz */
2131 { 50000, (0<<6) | 53, 7 }, /* 33145 ps / 30.1705 MHz */
2135 for (i
= 0; i
< sizeof(RGB514_clocks
)/sizeof(*RGB514_clocks
); i
++)
2136 if (vclk_per
<= RGB514_clocks
[i
].limit
) {
2137 pll
->m
= RGB514_clocks
[i
].m
;
2138 pll
->n
= RGB514_clocks
[i
].n
;
2145 static void aty_StrobeClock(const struct fb_info_aty
*info
)
2151 tmp
= aty_ld_8(CLOCK_CNTL
, info
);
2152 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, tmp
| CLOCK_STROBE
, info
);
2158 static void aty_ICS2595_put1bit(u8 data
, const struct fb_info_aty
*info
)
2163 tmp
= aty_ld_8(CLOCK_CNTL
, info
);
2164 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, (tmp
& ~0x04) | (data
<< 2),
2167 tmp
= aty_ld_8(CLOCK_CNTL
, info
);
2168 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, (tmp
& ~0x08) | (0 << 3), info
);
2170 aty_StrobeClock(info
);
2172 tmp
= aty_ld_8(CLOCK_CNTL
, info
);
2173 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, (tmp
& ~0x08) | (1 << 3), info
);
2175 aty_StrobeClock(info
);
2181 static u32
aty_pll_gx_to_var(const struct pll_gx
*pll
,
2182 const struct fb_info_aty
*info
)
2184 u8 df
, vco_div_count
, ref_div_count
;
2187 vco_div_count
= pll
->m
& 0x3f;
2188 ref_div_count
= pll
->n
;
2190 return ((info
->ref_clk_per
*ref_div_count
)<<(3-df
))/(vco_div_count
+65);
2195 * PLL programming (Mach64 CT family)
2198 static void aty_set_pll_ct(const struct fb_info_aty
*info
,
2199 const struct pll_ct
*pll
)
2201 aty_st_pll(PLL_REF_DIV
, pll
->pll_ref_div
, info
);
2202 aty_st_pll(PLL_GEN_CNTL
, pll
->pll_gen_cntl
, info
);
2203 aty_st_pll(MCLK_FB_DIV
, pll
->mclk_fb_div
, info
);
2204 aty_st_pll(PLL_VCLK_CNTL
, pll
->pll_vclk_cntl
, info
);
2205 aty_st_pll(VCLK_POST_DIV
, pll
->vclk_post_div
, info
);
2206 aty_st_pll(VCLK0_FB_DIV
, pll
->vclk_fb_div
, info
);
2207 aty_st_pll(PLL_EXT_CNTL
, pll
->pll_ext_cntl
, info
);
2209 if (!(Gx
== GX_CHIP_ID
|| Gx
== CX_CHIP_ID
|| Gx
== CT_CHIP_ID
||
2211 ((Gx
== VT_CHIP_ID
|| Gx
== GT_CHIP_ID
) && !(Rev
& 0x07)))) {
2212 if (info
->ram_type
>= SDRAM
)
2213 aty_st_pll(DLL_CNTL
, 0xa6, info
);
2215 aty_st_pll(DLL_CNTL
, 0xa0, info
);
2216 aty_st_pll(VFC_CNTL
, 0x1b, info
);
2217 aty_st_le32(DSP_CONFIG
, pll
->dsp_config
, info
);
2218 aty_st_le32(DSP_ON_OFF
, pll
->dsp_on_off
, info
);
2222 static int aty_dsp_gt(const struct fb_info_aty
*info
, u8 bpp
,
2225 u32 dsp_xclks_per_row
, dsp_loop_latency
, dsp_precision
, dsp_off
, dsp_on
;
2226 u32 xclks_per_row
, fifo_off
, fifo_on
, y
, fifo_size
, page_size
;
2228 /* xclocks_per_row<<11 */
2229 xclks_per_row
= (pll
->mclk_fb_div
*pll
->vclk_post_div_real
*64<<11)/
2230 (pll
->vclk_fb_div
*pll
->mclk_post_div_real
*bpp
);
2231 if (xclks_per_row
< (1<<11))
2232 FAIL("Dotclock to high");
2233 if (Gx
== GT_CHIP_ID
|| Gx
== GU_CHIP_ID
|| Gx
== VT_CHIP_ID
||
2234 Gx
== VU_CHIP_ID
|| Gx
== GV_CHIP_ID
|| Gx
== GW_CHIP_ID
||
2237 dsp_loop_latency
= 0;
2240 dsp_loop_latency
= 2;
2243 y
= (xclks_per_row
*fifo_size
)>>11;
2250 fifo_off
= ((xclks_per_row
*(fifo_size
-1))>>5)+(3<<6);
2252 if (info
->total_vram
> 1*1024*1024) {
2253 if (info
->ram_type
>= SDRAM
) {
2255 dsp_loop_latency
+= 8;
2259 dsp_loop_latency
+= 6;
2263 if (info
->ram_type
>= SDRAM
) {
2265 dsp_loop_latency
+= 9;
2269 dsp_loop_latency
+= 8;
2274 if (xclks_per_row
>= (page_size
<<11))
2275 fifo_on
= ((2*page_size
+1)<<6)+(xclks_per_row
>>5);
2277 fifo_on
= (3*page_size
+2)<<6;
2279 dsp_xclks_per_row
= xclks_per_row
>>dsp_precision
;
2280 dsp_on
= fifo_on
>>dsp_precision
;
2281 dsp_off
= fifo_off
>>dsp_precision
;
2283 pll
->dsp_config
= (dsp_xclks_per_row
& 0x3fff) |
2284 ((dsp_loop_latency
& 0xf)<<16) |
2285 ((dsp_precision
& 7)<<20);
2286 pll
->dsp_on_off
= (dsp_on
& 0x7ff) | ((dsp_off
& 0x7ff)<<16);
2290 static int aty_valid_pll_ct(const struct fb_info_aty
*info
, u32 vclk_per
,
2293 u32 q
, x
; /* x is a workaround for sparc64-linux-gcc */
2294 x
= x
; /* x is a workaround for sparc64-linux-gcc */
2296 pll
->pll_ref_div
= info
->pll_per
*2*255/info
->ref_clk_per
;
2298 /* FIXME: use the VTB/GTB /3 post divider if it's better suited */
2299 q
= info
->ref_clk_per
*pll
->pll_ref_div
*4/info
->mclk_per
; /* actually 8*q */
2300 if (q
< 16*8 || q
> 255*8)
2301 FAIL("mclk out of range");
2303 pll
->mclk_post_div_real
= 8;
2305 pll
->mclk_post_div_real
= 4;
2307 pll
->mclk_post_div_real
= 2;
2309 pll
->mclk_post_div_real
= 1;
2310 pll
->mclk_fb_div
= q
*pll
->mclk_post_div_real
/8;
2312 /* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
2313 q
= info
->ref_clk_per
*pll
->pll_ref_div
*4/vclk_per
; /* actually 8*q */
2314 if (q
< 16*8 || q
> 255*8)
2315 FAIL("vclk out of range");
2317 pll
->vclk_post_div_real
= 8;
2319 pll
->vclk_post_div_real
= 4;
2321 pll
->vclk_post_div_real
= 2;
2323 pll
->vclk_post_div_real
= 1;
2324 pll
->vclk_fb_div
= q
*pll
->vclk_post_div_real
/8;
2328 static void aty_calc_pll_ct(const struct fb_info_aty
*info
, struct pll_ct
*pll
)
2333 if ((((Gx
== GT_CHIP_ID
) && (Rev
& 0x03)) || (Gx
== GU_CHIP_ID
) ||
2334 (Gx
== GV_CHIP_ID
) || (Gx
== GW_CHIP_ID
) || (Gx
== GZ_CHIP_ID
) ||
2335 (Gx
== LG_CHIP_ID
) || (Gx
== GB_CHIP_ID
) || (Gx
== GD_CHIP_ID
) ||
2336 (Gx
== GI_CHIP_ID
) || (Gx
== GP_CHIP_ID
) || (Gx
== GQ_CHIP_ID
) ||
2337 (Gx
== VU_CHIP_ID
)) && (info
->ram_type
>= SDRAM
))
2338 pll
->pll_gen_cntl
= 0x04;
2340 pll
->pll_gen_cntl
= 0x84;
2342 switch (pll
->mclk_post_div_real
) {
2359 pll
->pll_gen_cntl
|= mpostdiv
<<4; /* mclk */
2361 if (Gx
== VT_CHIP_ID
&& (Rev
== 0x40 || Rev
== 0x48))
2362 pll
->pll_ext_cntl
= 0;
2364 pll
->pll_ext_cntl
= mpostdiv
; /* xclk == mclk */
2366 switch (pll
->vclk_post_div_real
) {
2371 pll
->pll_ext_cntl
|= 0x10;
2376 pll
->pll_ext_cntl
|= 0x10;
2381 pll
->pll_ext_cntl
|= 0x10;
2387 pll
->pll_vclk_cntl
= 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */
2388 pll
->vclk_post_div
= vpostdiv
;
2391 static int aty_var_to_pll_ct(const struct fb_info_aty
*info
, u32 vclk_per
,
2392 u8 bpp
, struct pll_ct
*pll
)
2396 if ((err
= aty_valid_pll_ct(info
, vclk_per
, pll
)))
2398 if (!(Gx
== GX_CHIP_ID
|| Gx
== CX_CHIP_ID
|| Gx
== CT_CHIP_ID
||
2400 ((Gx
== VT_CHIP_ID
|| Gx
== GT_CHIP_ID
) && !(Rev
& 0x07)))) {
2401 if ((err
= aty_dsp_gt(info
, bpp
, pll
)))
2404 aty_calc_pll_ct(info
, pll
);
2408 static u32
aty_pll_ct_to_var(const struct pll_ct
*pll
,
2409 const struct fb_info_aty
*info
)
2411 u32 ref_clk_per
= info
->ref_clk_per
;
2412 u8 pll_ref_div
= pll
->pll_ref_div
;
2413 u8 vclk_fb_div
= pll
->vclk_fb_div
;
2414 u8 vclk_post_div
= pll
->vclk_post_div_real
;
2416 return ref_clk_per
*pll_ref_div
*vclk_post_div
/vclk_fb_div
/2;
2419 /* ------------------------------------------------------------------------- */
2421 static void atyfb_set_par(const struct atyfb_par
*par
,
2422 struct fb_info_aty
*info
)
2429 accelmode
= par
->accel_flags
; /* hack */
2431 info
->current_par
= *par
;
2433 if (info
->blitter_may_be_busy
)
2434 wait_for_idle(info
);
2435 tmp
= aty_ld_8(CRTC_GEN_CNTL
+ 3, info
);
2436 aty_set_crtc(info
, &par
->crtc
);
2437 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, 0, info
);
2438 /* better call aty_StrobeClock ?? */
2439 aty_st_8(CLOCK_CNTL
+ info
->clk_wr_offset
, CLOCK_STROBE
, info
);
2441 if ((Gx
== GX_CHIP_ID
) || (Gx
== CX_CHIP_ID
)) {
2442 switch (info
->dac_subtype
) {
2444 aty_set_dac_514(info
, par
->crtc
.bpp
);
2446 case DAC_ATI68860_B
:
2447 case DAC_ATI68860_C
:
2448 muxmode
= aty_set_dac_ATI68860_B(info
, par
->crtc
.bpp
,
2450 aty_st_le32(BUS_CNTL
, 0x890e20f1, info
);
2451 aty_st_le32(DAC_CNTL
, 0x47052100, info
);
2454 muxmode
= aty_set_dac_ATT21C498(info
, &par
->pll
.ics2595
,
2456 aty_st_le32(BUS_CNTL
, 0x890e20f1, info
);
2457 aty_st_le32(DAC_CNTL
, 0x00072000, info
);
2460 muxmode
= aty_set_dac_ATT21C498(info
, &par
->pll
.ics2595
,
2462 aty_st_le32(BUS_CNTL
, 0x890e20f1, info
);
2463 aty_st_le32(DAC_CNTL
, 0x00072000, info
);
2466 printk(" atyfb_set_par: DAC type not implemented yet!\n");
2467 aty_st_le32(BUS_CNTL
, 0x890e20f1, info
);
2468 aty_st_le32(DAC_CNTL
, 0x47052100, info
);
2469 /* new in 2.2.3p1 from Geert. ???????? */
2470 aty_st_le32(BUS_CNTL
, 0x590e10ff, info
);
2471 aty_st_le32(DAC_CNTL
, 0x47012100, info
);
2475 switch (info
->clk_type
) {
2476 case CLK_ATI18818_1
:
2477 aty_set_pll18818(info
, &par
->pll
.ics2595
);
2480 aty_set_pll_1703(info
, &par
->pll
.ics2595
);
2483 aty_set_pll_8398(info
, &par
->pll
.ics2595
);
2486 aty_set_pll_408(info
, &par
->pll
.ics2595
);
2489 aty_set_pll_gx(info
, &par
->pll
.gx
);
2492 printk(" atyfb_set_par: CLK type not implemented yet!");
2496 /* Don't forget MEM_CNTL */
2497 i
= aty_ld_le32(MEM_CNTL
, info
) & 0xf0ffffff;
2498 switch (par
->crtc
.bpp
) {
2509 aty_st_le32(MEM_CNTL
, i
, info
);
2512 aty_set_pll_ct(info
, &par
->pll
.ct
);
2513 i
= aty_ld_le32(MEM_CNTL
, info
) & 0xf00fffff;
2514 if (!(Gx
== VT_CHIP_ID
&& (Rev
== 0x40 || Rev
== 0x48)))
2515 i
|= info
->mem_refresh_rate
<< 20;
2516 switch (par
->crtc
.bpp
) {
2528 if ((Gx
== CT_CHIP_ID
) || (Gx
== ET_CHIP_ID
)) {
2529 aty_st_le32(DAC_CNTL
, 0x87010184, info
);
2530 aty_st_le32(BUS_CNTL
, 0x680000f9, info
);
2531 } else if ((Gx
== VT_CHIP_ID
) || (Gx
== VU_CHIP_ID
)) {
2532 aty_st_le32(DAC_CNTL
, 0x87010184, info
);
2533 aty_st_le32(BUS_CNTL
, 0x680000f9, info
);
2534 } else if ((Gx
== LN_CHIP_ID
) || (Gx
== LM_CHIP_ID
)) {
2535 aty_st_le32(DAC_CNTL
, 0x80010102, info
);
2536 aty_st_le32(BUS_CNTL
, 0x7b33a040, info
);
2539 aty_st_le32(DAC_CNTL
, 0x86010102, info
);
2540 aty_st_le32(BUS_CNTL
, 0x7b23a040, info
);
2541 aty_st_le32(EXT_MEM_CNTL
,
2542 aty_ld_le32(EXT_MEM_CNTL
, info
) | 0x5000001, info
);
2544 aty_st_le32(MEM_CNTL
, i
, info
);
2546 aty_st_8(DAC_MASK
, 0xff, info
);
2548 /* Initialize the graphics engine */
2549 if (par
->accel_flags
& FB_ACCELF_TEXT
)
2550 init_engine(par
, info
);
2552 #ifdef CONFIG_FB_COMPAT_XPMAC
2553 if (!console_fb_info
|| console_fb_info
== &info
->fb_info
) {
2554 struct fb_var_screeninfo var
;
2556 display_info
.height
= ((par
->crtc
.v_tot_disp
>>16) & 0x7ff)+1;
2557 display_info
.width
= (((par
->crtc
.h_tot_disp
>>16) & 0xff)+1)*8;
2558 display_info
.depth
= par
->crtc
.bpp
;
2559 display_info
.pitch
= par
->crtc
.vxres
*par
->crtc
.bpp
/8;
2560 atyfb_encode_var(&var
, par
, info
);
2561 if (mac_var_to_vmode(&var
, &vmode
, &cmode
))
2562 display_info
.mode
= 0;
2564 display_info
.mode
= vmode
;
2565 strcpy(display_info
.name
, atyfb_name
);
2566 display_info
.fb_address
= info
->frame_buffer_phys
;
2567 display_info
.cmap_adr_address
= info
->ati_regbase_phys
+0xc0;
2568 display_info
.cmap_data_address
= info
->ati_regbase_phys
+0xc1;
2569 display_info
.disp_reg_address
= info
->ati_regbase_phys
;
2571 #endif /* CONFIG_FB_COMPAT_XPMAC */
2574 static int atyfb_decode_var(const struct fb_var_screeninfo
*var
,
2575 struct atyfb_par
*par
,
2576 const struct fb_info_aty
*info
)
2580 if ((err
= aty_var_to_crtc(info
, var
, &par
->crtc
)))
2582 if ((Gx
== GX_CHIP_ID
) || (Gx
== CX_CHIP_ID
))
2583 switch (info
->clk_type
) {
2584 case CLK_ATI18818_1
:
2585 err
= aty_var_to_pll_18818(var
->pixclock
, &par
->pll
.ics2595
);
2588 err
= aty_var_to_pll_1703(var
->pixclock
, &par
->pll
.ics2595
);
2591 err
= aty_var_to_pll_8398(var
->pixclock
, &par
->pll
.ics2595
);
2594 err
= aty_var_to_pll_408(var
->pixclock
, &par
->pll
.ics2595
);
2597 err
= aty_var_to_pll_514(var
->pixclock
, &par
->pll
.gx
);
2601 err
= aty_var_to_pll_ct(info
, var
->pixclock
, par
->crtc
.bpp
,
2606 if (var
->accel_flags
& FB_ACCELF_TEXT
)
2607 par
->accel_flags
= FB_ACCELF_TEXT
;
2609 par
->accel_flags
= 0;
2611 #if 0 /* fbmon is not done. uncomment for 2.5.x -brad */
2612 if (!fbmon_valid_timings(var
->pixclock
, htotal
, vtotal
, info
))
2619 static int atyfb_encode_var(struct fb_var_screeninfo
*var
,
2620 const struct atyfb_par
*par
,
2621 const struct fb_info_aty
*info
)
2625 memset(var
, 0, sizeof(struct fb_var_screeninfo
));
2627 if ((err
= aty_crtc_to_var(&par
->crtc
, var
)))
2629 if ((Gx
== GX_CHIP_ID
) || (Gx
== CX_CHIP_ID
))
2630 switch (info
->clk_type
) {
2631 case CLK_ATI18818_1
:
2632 var
->pixclock
= aty_pll_18818_to_var(&par
->pll
.ics2595
);
2635 var
->pixclock
= aty_pll_1703_to_var(&par
->pll
.ics2595
);
2638 var
->pixclock
= aty_pll_8398_to_var(&par
->pll
.ics2595
);
2641 var
->pixclock
= aty_pll_408_to_var(&par
->pll
.ics2595
);
2644 var
->pixclock
= aty_pll_gx_to_var(&par
->pll
.gx
, info
);
2648 var
->pixclock
= aty_pll_ct_to_var(&par
->pll
.ct
, info
);
2652 var
->accel_flags
= par
->accel_flags
;
2659 static void set_off_pitch(struct atyfb_par
*par
,
2660 const struct fb_info_aty
*info
)
2662 u32 xoffset
= par
->crtc
.xoffset
;
2663 u32 yoffset
= par
->crtc
.yoffset
;
2664 u32 vxres
= par
->crtc
.vxres
;
2665 u32 bpp
= par
->crtc
.bpp
;
2667 par
->crtc
.off_pitch
= ((yoffset
*vxres
+xoffset
)*bpp
/64) | (vxres
<<19);
2668 aty_st_le32(CRTC_OFF_PITCH
, par
->crtc
.off_pitch
, info
);
2673 * Open/Release the frame buffer device
2676 static int atyfb_open(struct fb_info
*info
, int user
)
2680 struct fb_info_aty
*fb
= (struct fb_info_aty
*)info
;
2693 struct fb_var_screeninfo default_var
= {
2694 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
2695 640, 480, 640, 480, 0, 0, 8, 0,
2696 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
2697 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
2698 0, FB_VMODE_NONINTERLACED
2701 static int atyfb_release(struct fb_info
*info
, int user
)
2704 struct fb_info_aty
*fb
= (struct fb_info_aty
*)info
;
2711 int was_mmaped
= fb
->mmaped
;
2714 if (fb
->vtconsole
!= -1)
2715 vt_cons
[fb
->vtconsole
]->vc_mode
= KD_TEXT
;
2719 struct fb_var_screeninfo var
;
2721 /* Now reset the default display config, we have no
2722 * idea what the program(s) which mmap'd the chip did
2723 * to the configuration, nor whether it restored it
2728 var
.accel_flags
&= ~FB_ACCELF_TEXT
;
2730 var
.accel_flags
|= FB_ACCELF_TEXT
;
2731 if (var
.yres
== var
.yres_virtual
) {
2732 u32 vram
= (fb
->total_vram
- (PAGE_SIZE
<< 2));
2733 var
.yres_virtual
= ((vram
* 8) / var
.bits_per_pixel
) /
2735 if (var
.yres_virtual
< var
.yres
)
2736 var
.yres_virtual
= var
.yres
;
2738 atyfb_set_var(&var
, -1, &fb
->fb_info
);
2749 static int encode_fix(struct fb_fix_screeninfo
*fix
,
2750 const struct atyfb_par
*par
,
2751 const struct fb_info_aty
*info
)
2753 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
2755 strcpy(fix
->id
, atyfb_name
);
2756 fix
->smem_start
= info
->frame_buffer_phys
;
2757 fix
->smem_len
= (u32
)info
->total_vram
;
2760 * Reg Block 0 (CT-compatible block) is at ati_regbase_phys
2761 * Reg Block 1 (multimedia extensions) is at ati_regbase_phys-0x400
2763 if (Gx
== GX_CHIP_ID
|| Gx
== CX_CHIP_ID
) {
2764 fix
->mmio_start
= info
->ati_regbase_phys
;
2765 fix
->mmio_len
= 0x400;
2766 fix
->accel
= FB_ACCEL_ATI_MACH64GX
;
2767 } else if (Gx
== CT_CHIP_ID
|| Gx
== ET_CHIP_ID
) {
2768 fix
->mmio_start
= info
->ati_regbase_phys
;
2769 fix
->mmio_len
= 0x400;
2770 fix
->accel
= FB_ACCEL_ATI_MACH64CT
;
2771 } else if (Gx
== VT_CHIP_ID
|| Gx
== VU_CHIP_ID
|| Gx
== VV_CHIP_ID
) {
2772 fix
->mmio_start
= info
->ati_regbase_phys
-0x400;
2773 fix
->mmio_len
= 0x800;
2774 fix
->accel
= FB_ACCEL_ATI_MACH64VT
;
2776 fix
->mmio_start
= info
->ati_regbase_phys
-0x400;
2777 fix
->mmio_len
= 0x800;
2778 fix
->accel
= FB_ACCEL_ATI_MACH64GT
;
2780 fix
->type
= FB_TYPE_PACKED_PIXELS
;
2782 fix
->line_length
= par
->crtc
.vxres
*par
->crtc
.bpp
/8;
2783 fix
->visual
= par
->crtc
.bpp
<= 8 ? FB_VISUAL_PSEUDOCOLOR
2784 : FB_VISUAL_DIRECTCOLOR
;
2794 * Get the Fixed Part of the Display
2797 static int atyfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
2800 const struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
2801 struct atyfb_par par
;
2804 par
= info
->default_par
;
2806 atyfb_decode_var(&fb_display
[con
].var
, &par
, info
);
2807 encode_fix(fix
, &par
, info
);
2813 * Get the User Defined Part of the Display
2816 static int atyfb_get_var(struct fb_var_screeninfo
*var
, int con
,
2819 const struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
2822 atyfb_encode_var(var
, &info
->default_par
, info
);
2824 *var
= fb_display
[con
].var
;
2829 static void atyfb_set_dispsw(struct display
*disp
, struct fb_info_aty
*info
,
2833 #ifdef FBCON_HAS_CFB8
2835 info
->dispsw
= accel
? fbcon_aty8
: fbcon_cfb8
;
2836 disp
->dispsw
= &info
->dispsw
;
2839 #ifdef FBCON_HAS_CFB16
2841 info
->dispsw
= accel
? fbcon_aty16
: fbcon_cfb16
;
2842 disp
->dispsw
= &info
->dispsw
;
2843 disp
->dispsw_data
= info
->fbcon_cmap
.cfb16
;
2846 #ifdef FBCON_HAS_CFB24
2848 info
->dispsw
= accel
? fbcon_aty24
: fbcon_cfb24
;
2849 disp
->dispsw
= &info
->dispsw
;
2850 disp
->dispsw_data
= info
->fbcon_cmap
.cfb24
;
2853 #ifdef FBCON_HAS_CFB32
2855 info
->dispsw
= accel
? fbcon_aty32
: fbcon_cfb32
;
2856 disp
->dispsw
= &info
->dispsw
;
2857 disp
->dispsw_data
= info
->fbcon_cmap
.cfb32
;
2861 disp
->dispsw
= &fbcon_dummy
;
2864 info
->dispsw
.cursor
= atyfb_cursor
;
2865 info
->dispsw
.set_font
= atyfb_set_font
;
2871 * Set the User Defined Part of the Display
2874 static int atyfb_set_var(struct fb_var_screeninfo
*var
, int con
,
2877 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
2878 struct atyfb_par par
;
2879 struct display
*display
;
2880 int oldxres
, oldyres
, oldvxres
, oldvyres
, oldbpp
, oldaccel
, accel
, err
;
2881 int activate
= var
->activate
;
2884 display
= &fb_display
[con
];
2886 display
= fb
->disp
; /* used during initialization */
2888 if ((err
= atyfb_decode_var(var
, &par
, info
)))
2891 atyfb_encode_var(var
, &par
, (struct fb_info_aty
*)info
);
2893 if ((activate
& FB_ACTIVATE_MASK
) == FB_ACTIVATE_NOW
) {
2894 oldxres
= display
->var
.xres
;
2895 oldyres
= display
->var
.yres
;
2896 oldvxres
= display
->var
.xres_virtual
;
2897 oldvyres
= display
->var
.yres_virtual
;
2898 oldbpp
= display
->var
.bits_per_pixel
;
2899 oldaccel
= display
->var
.accel_flags
;
2900 display
->var
= *var
;
2901 accel
= var
->accel_flags
& FB_ACCELF_TEXT
;
2902 if (oldxres
!= var
->xres
|| oldyres
!= var
->yres
||
2903 oldvxres
!= var
->xres_virtual
|| oldvyres
!= var
->yres_virtual
||
2904 oldbpp
!= var
->bits_per_pixel
|| oldaccel
!= var
->accel_flags
) {
2905 struct fb_fix_screeninfo fix
;
2907 encode_fix(&fix
, &par
, info
);
2908 display
->screen_base
= (char *)info
->frame_buffer
;
2909 display
->visual
= fix
.visual
;
2910 display
->type
= fix
.type
;
2911 display
->type_aux
= fix
.type_aux
;
2912 display
->ypanstep
= fix
.ypanstep
;
2913 display
->ywrapstep
= fix
.ywrapstep
;
2914 display
->line_length
= fix
.line_length
;
2915 display
->can_soft_blank
= 1;
2916 display
->inverse
= 0;
2918 display
->scrollmode
= (info
->bus_type
== PCI
) ? SCROLL_YNOMOVE
: 0;
2920 display
->scrollmode
= SCROLL_YREDRAW
;
2921 if (info
->fb_info
.changevar
)
2922 (*info
->fb_info
.changevar
)(con
);
2924 if (!info
->fb_info
.display_fg
||
2925 info
->fb_info
.display_fg
->vc_num
== con
) {
2926 atyfb_set_par(&par
, info
);
2927 atyfb_set_dispsw(display
, info
, par
.crtc
.bpp
, accel
);
2929 if (oldbpp
!= var
->bits_per_pixel
) {
2930 if ((err
= fb_alloc_cmap(&display
->cmap
, 0, 0)))
2932 do_install_cmap(con
, &info
->fb_info
);
2941 * Pan or Wrap the Display
2943 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
2946 static int atyfb_pan_display(struct fb_var_screeninfo
*var
, int con
,
2949 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
2950 u32 xres
, yres
, xoffset
, yoffset
;
2951 struct atyfb_par
*par
= &info
->current_par
;
2953 xres
= (((par
->crtc
.h_tot_disp
>>16) & 0xff)+1)*8;
2954 yres
= ((par
->crtc
.v_tot_disp
>>16) & 0x7ff)+1;
2955 xoffset
= (var
->xoffset
+7) & ~7;
2956 yoffset
= var
->yoffset
;
2957 if (xoffset
+xres
> par
->crtc
.vxres
|| yoffset
+yres
> par
->crtc
.vyres
)
2959 par
->crtc
.xoffset
= xoffset
;
2960 par
->crtc
.yoffset
= yoffset
;
2961 set_off_pitch(par
, info
);
2969 static int atyfb_get_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
2970 struct fb_info
*info
)
2972 if (!info
->display_fg
|| con
== info
->display_fg
->vc_num
) /* current console? */
2973 return fb_get_cmap(cmap
, kspc
, atyfb_getcolreg
, info
);
2974 else if (fb_display
[con
].cmap
.len
) /* non default colormap? */
2975 fb_copy_cmap(&fb_display
[con
].cmap
, cmap
, kspc
? 0 : 2);
2977 int size
= fb_display
[con
].var
.bits_per_pixel
== 16 ? 32 : 256;
2978 fb_copy_cmap(fb_default_cmap(size
), cmap
, kspc
? 0 : 2);
2987 static int atyfb_set_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
2988 struct fb_info
*info
)
2991 struct display
*disp
;
2994 disp
= &fb_display
[con
];
2997 if (!disp
->cmap
.len
) { /* no colormap allocated? */
2998 int size
= disp
->var
.bits_per_pixel
== 16 ? 32 : 256;
2999 if ((err
= fb_alloc_cmap(&disp
->cmap
, size
, 0)))
3002 if (!info
->display_fg
|| con
== info
->display_fg
->vc_num
) /* current console? */
3003 return fb_set_cmap(cmap
, kspc
, atyfb_setcolreg
, info
);
3005 fb_copy_cmap(cmap
, &disp
->cmap
, kspc
? 0 : 1);
3011 #define ATYIO_CLKR 0x41545900 /* ATY\00 */
3012 #define ATYIO_CLKW 0x41545901 /* ATY\01 */
3018 u8 mclk_post_div
; /* 1,2,3,4,8 */
3020 u8 vclk_post_div
; /* 1,2,3,4,6,8,12 */
3021 u32 dsp_xclks_per_row
; /* 0-16383 */
3022 u32 dsp_loop_latency
; /* 0-15 */
3023 u32 dsp_precision
; /* 0-7 */
3024 u32 dsp_on
; /* 0-2047 */
3025 u32 dsp_off
; /* 0-2047 */
3029 static int atyfb_ioctl(struct inode
*inode
, struct file
*file
, u_int cmd
,
3030 u_long arg
, int con
, struct fb_info
*info2
)
3032 #if defined(__sparc__) || defined(DEBUG)
3033 struct fb_info_aty
*info
= (struct fb_info_aty
*)info2
;
3034 #endif /* __sparc__ || DEBUG */
3036 struct fbtype fbtyp
;
3037 struct display
*disp
;
3040 disp
= &fb_display
[con
];
3048 fbtyp
.fb_type
= FBTYPE_PCI_GENERIC
;
3049 fbtyp
.fb_width
= info
->current_par
.crtc
.vxres
;
3050 fbtyp
.fb_height
= info
->current_par
.crtc
.vyres
;
3051 fbtyp
.fb_depth
= info
->current_par
.crtc
.bpp
;
3052 fbtyp
.fb_cmsize
= disp
->cmap
.len
;
3053 fbtyp
.fb_size
= info
->total_vram
;
3054 if (copy_to_user((struct fbtype
*)arg
, &fbtyp
, sizeof(fbtyp
)))
3057 #endif /* __sparc__ */
3060 if ((Gx
!= GX_CHIP_ID
) && (Gx
!= CX_CHIP_ID
)) {
3062 struct pll_ct
*pll
= &info
->current_par
.pll
.ct
;
3063 u32 dsp_config
= pll
->dsp_config
;
3064 u32 dsp_on_off
= pll
->dsp_on_off
;
3065 clk
.ref_clk_per
= info
->ref_clk_per
;
3066 clk
.pll_ref_div
= pll
->pll_ref_div
;
3067 clk
.mclk_fb_div
= pll
->mclk_fb_div
;
3068 clk
.mclk_post_div
= pll
->mclk_post_div_real
;
3069 clk
.vclk_fb_div
= pll
->vclk_fb_div
;
3070 clk
.vclk_post_div
= pll
->vclk_post_div_real
;
3071 clk
.dsp_xclks_per_row
= dsp_config
& 0x3fff;
3072 clk
.dsp_loop_latency
= (dsp_config
>>16) & 0xf;
3073 clk
.dsp_precision
= (dsp_config
>>20) & 7;
3074 clk
.dsp_on
= dsp_on_off
& 0x7ff;
3075 clk
.dsp_off
= (dsp_on_off
>>16) & 0x7ff;
3076 if (copy_to_user((struct atyclk
*)arg
, &clk
, sizeof(clk
)))
3082 if ((Gx
!= GX_CHIP_ID
) && (Gx
!= CX_CHIP_ID
)) {
3084 struct pll_ct
*pll
= &info
->current_par
.pll
.ct
;
3085 if (copy_from_user(&clk
, (struct atyclk
*)arg
, sizeof(clk
)))
3087 info
->ref_clk_per
= clk
.ref_clk_per
;
3088 pll
->pll_ref_div
= clk
.pll_ref_div
;
3089 pll
->mclk_fb_div
= clk
.mclk_fb_div
;
3090 pll
->mclk_post_div_real
= clk
.mclk_post_div
;
3091 pll
->vclk_fb_div
= clk
.vclk_fb_div
;
3092 pll
->vclk_post_div_real
= clk
.vclk_post_div
;
3093 pll
->dsp_config
= (clk
.dsp_xclks_per_row
& 0x3fff) |
3094 ((clk
.dsp_loop_latency
& 0xf)<<16) |
3095 ((clk
.dsp_precision
& 7)<<20);
3096 pll
->dsp_on_off
= (clk
.dsp_on
& 0x7ff) |
3097 ((clk
.dsp_off
& 0x7ff)<<16);
3098 aty_calc_pll_ct(info
, pll
);
3099 aty_set_pll_ct(info
, pll
);
3110 static int atyfb_rasterimg(struct fb_info
*info
, int start
)
3112 struct fb_info_aty
*fb
= (struct fb_info_aty
*)info
;
3114 if (fb
->blitter_may_be_busy
)
3120 static int atyfb_mmap(struct fb_info
*info
, struct file
*file
,
3121 struct vm_area_struct
*vma
)
3123 struct fb_info_aty
*fb
= (struct fb_info_aty
*)info
;
3124 unsigned int size
, page
, map_size
= 0;
3125 unsigned long map_offset
= 0;
3132 if (vma
->vm_pgoff
> (~0UL >> PAGE_SHIFT
))
3135 off
= vma
->vm_pgoff
<< PAGE_SHIFT
;
3136 size
= vma
->vm_end
- vma
->vm_start
;
3138 /* To stop the swapper from even considering these pages. */
3139 vma
->vm_flags
|= (VM_SHM
| VM_LOCKED
);
3141 if (((vma
->vm_pgoff
== 0) && (size
== fb
->total_vram
)) ||
3142 ((off
== fb
->total_vram
) && (size
== PAGE_SIZE
)))
3143 off
+= 0x8000000000000000UL
;
3145 vma
->vm_pgoff
= off
>> PAGE_SHIFT
; /* propagate off changes */
3148 /* Align it as much as desirable */
3150 unsigned long j
, align
;
3153 map_offset
= off
+ size
;
3154 for (i
= 0; fb
->mmap_map
[i
].size
; i
++) {
3155 if (fb
->mmap_map
[i
].voff
< off
)
3157 if (fb
->mmap_map
[i
].voff
>= map_offset
)
3160 fb
->mmap_map
[i
].size
> fb
->mmap_map
[max
].size
)
3164 j
= fb
->mmap_map
[max
].size
;
3165 if (fb
->mmap_map
[max
].voff
+ j
> map_offset
)
3166 j
= map_offset
- fb
->mmap_map
[max
].voff
;
3167 for (align
= 0x400000; align
> PAGE_SIZE
; align
>>= 3)
3169 !(fb
->mmap_map
[max
].poff
& (align
- 1)))
3171 if (align
> PAGE_SIZE
) {
3173 align
= j
- ((vma
->vm_start
3174 + fb
->mmap_map
[max
].voff
3177 struct vm_area_struct
*vmm
;
3179 vmm
= find_vma(current
->mm
,
3181 if (!vmm
|| vmm
->vm_start
3182 >= vma
->vm_end
+ align
) {
3183 vma
->vm_start
+= align
;
3184 vma
->vm_end
+= align
;
3192 /* Each page, see which map applies */
3193 for (page
= 0; page
< size
; ) {
3195 for (i
= 0; fb
->mmap_map
[i
].size
; i
++) {
3196 unsigned long start
= fb
->mmap_map
[i
].voff
;
3197 unsigned long end
= start
+ fb
->mmap_map
[i
].size
;
3198 unsigned long offset
= off
+ page
;
3205 map_size
= fb
->mmap_map
[i
].size
- (offset
- start
);
3206 map_offset
= fb
->mmap_map
[i
].poff
+ (offset
- start
);
3213 if (page
+ map_size
> size
)
3214 map_size
= size
- page
;
3216 pgprot_val(vma
->vm_page_prot
) &= ~(fb
->mmap_map
[i
].prot_mask
);
3217 pgprot_val(vma
->vm_page_prot
) |= fb
->mmap_map
[i
].prot_flag
;
3219 if (remap_page_range(vma
->vm_start
+ page
, map_offset
,
3220 map_size
, vma
->vm_page_prot
))
3229 vma
->vm_flags
|= VM_IO
;
3232 int lastconsole
= 0;
3234 if (info
->display_fg
)
3235 lastconsole
= info
->display_fg
->vc_num
;
3237 if (fb
->consolecnt
&& fb_display
[lastconsole
].fb_info
== info
) {
3238 fb
->vtconsole
= lastconsole
;
3239 vt_cons
[lastconsole
]->vc_mode
= KD_GRAPHICS
;
3252 static void atyfb_save_palette(struct fb_info
*fb
, int enter
)
3254 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
3257 for (i
= 0; i
< 256; i
++) {
3258 tmp
= aty_ld_8(DAC_CNTL
, info
) & 0xfc;
3259 if (Gx
== GT_CHIP_ID
|| Gx
== GU_CHIP_ID
|| Gx
== GV_CHIP_ID
||
3260 Gx
== GW_CHIP_ID
|| Gx
== GZ_CHIP_ID
|| Gx
== LG_CHIP_ID
||
3261 Gx
== GB_CHIP_ID
|| Gx
== GD_CHIP_ID
|| Gx
== GI_CHIP_ID
||
3262 Gx
== GP_CHIP_ID
|| Gx
== GQ_CHIP_ID
)
3264 aty_st_8(DAC_CNTL
, tmp
, info
);
3265 aty_st_8(DAC_MASK
, 0xff, info
);
3267 scale
= ((Gx
!= GX_CHIP_ID
) && (Gx
!= CX_CHIP_ID
) &&
3268 (info
->current_par
.crtc
.bpp
== 16)) ? 3 : 0;
3269 writeb(i
<< scale
, &info
->aty_cmap_regs
->rindex
);
3271 atyfb_save
.r
[enter
][i
] = readb(&info
->aty_cmap_regs
->lut
);
3272 atyfb_save
.g
[enter
][i
] = readb(&info
->aty_cmap_regs
->lut
);
3273 atyfb_save
.b
[enter
][i
] = readb(&info
->aty_cmap_regs
->lut
);
3274 writeb(i
<< scale
, &info
->aty_cmap_regs
->windex
);
3275 writeb(atyfb_save
.r
[1-enter
][i
], &info
->aty_cmap_regs
->lut
);
3276 writeb(atyfb_save
.g
[1-enter
][i
], &info
->aty_cmap_regs
->lut
);
3277 writeb(atyfb_save
.b
[1-enter
][i
], &info
->aty_cmap_regs
->lut
);
3281 static void atyfb_palette(int enter
)
3283 struct fb_info_aty
*info
;
3284 struct atyfb_par
*par
;
3288 for (i
= 0; i
< MAX_NR_CONSOLES
; i
++) {
3291 d
->fb_info
->fbops
== &atyfb_ops
&&
3292 d
->fb_info
->display_fg
&&
3293 d
->fb_info
->display_fg
->vc_num
== i
) {
3294 atyfb_save_palette(d
->fb_info
, enter
);
3295 info
= (struct fb_info_aty
*)d
->fb_info
;
3296 par
= &info
->current_par
;
3298 atyfb_save
.yoffset
= par
->crtc
.yoffset
;
3299 par
->crtc
.yoffset
= 0;
3300 set_off_pitch(par
, info
);
3302 par
->crtc
.yoffset
= atyfb_save
.yoffset
;
3303 set_off_pitch(par
, info
);
3309 #endif /* __sparc__ */
3315 static int __init
aty_init(struct fb_info_aty
*info
, const char *name
)
3320 struct fb_var_screeninfo var
;
3321 struct display
*disp
;
3322 const char *chipname
= NULL
, *ramname
= NULL
, *xtal
;
3323 int pll
, mclk
, gtb_memsize
;
3324 #if defined(CONFIG_PPC)
3329 info
->aty_cmap_regs
= (struct aty_cmap_regs
*)(info
->ati_regbase
+0xc0);
3330 chip_id
= aty_ld_le32(CONFIG_CHIP_ID
, info
);
3331 Gx
= chip_id
& CFG_CHIP_TYPE
;
3332 Rev
= (chip_id
& CFG_CHIP_REV
)>>24;
3333 for (j
= 0; j
< (sizeof(aty_features
)/sizeof(*aty_features
)); j
++)
3334 if (aty_features
[j
].chip_type
== Gx
) {
3335 chipname
= aty_features
[j
].name
;
3336 info
->dac_type
= (aty_ld_le32(DAC_CNTL
, info
) >> 16) & 0x07;
3340 printk("atyfb: Unknown mach64 0x%04x\n", Gx
);
3343 printk("atyfb: %s [0x%04x rev 0x%02x] ", chipname
, Gx
, Rev
);
3344 if ((Gx
== GX_CHIP_ID
) || (Gx
== CX_CHIP_ID
)) {
3345 info
->bus_type
= (aty_ld_le32(CONFIG_STAT0
, info
) >> 0) & 0x07;
3346 info
->ram_type
= (aty_ld_le32(CONFIG_STAT0
, info
) >> 3) & 0x07;
3347 ramname
= aty_gx_ram
[info
->ram_type
];
3348 /* FIXME: clockchip/RAMDAC probing? */
3350 info
->clk_type
= CLK_ATI18818_1
;
3351 info
->dac_type
= (aty_ld_le32(CONFIG_STAT0
, info
) >> 9) & 0x07;
3352 if (info
->dac_type
== 0x07)
3353 info
->dac_subtype
= DAC_ATT20C408
;
3355 info
->dac_subtype
= (aty_ld_8(SCRATCH_REG1
+ 1, info
) & 0xF0) |
3358 info
->dac_type
= DAC_IBMRGB514
;
3359 info
->dac_subtype
= DAC_IBMRGB514
;
3360 info
->clk_type
= CLK_IBMRGB514
;
3366 info
->bus_type
= PCI
;
3367 info
->ram_type
= (aty_ld_le32(CONFIG_STAT0
, info
) & 0x07);
3368 ramname
= aty_ct_ram
[info
->ram_type
];
3369 info
->dac_type
= DAC_INTERNAL
;
3370 info
->dac_subtype
= DAC_INTERNAL
;
3371 info
->clk_type
= CLK_INTERNAL
;
3372 if ((Gx
== CT_CHIP_ID
) || (Gx
== ET_CHIP_ID
)) {
3376 mclk
= info
->ram_type
>= SDRAM
? 67 : 63;
3377 if ((Gx
== VT_CHIP_ID
) && (Rev
== 0x08)) {
3380 } else if (((Gx
== VT_CHIP_ID
) && ((Rev
== 0x40) ||
3382 ((Gx
== VT_CHIP_ID
) && ((Rev
== 0x01) ||
3387 } else if (Gx
== VV_CHIP_ID
) {
3391 } else if (Gx
== VT_CHIP_ID
) {
3395 } else if ((Gx
== GT_CHIP_ID
) && (Rev
& 0x01)) {
3398 } else if (((Gx
== GT_CHIP_ID
) && (Rev
& 0x02)) ||
3399 (Gx
== GU_CHIP_ID
)) {
3402 } else if (Gx
== GV_CHIP_ID
|| Gx
== GW_CHIP_ID
||
3407 } else if (Gx
== GB_CHIP_ID
|| Gx
== GD_CHIP_ID
||
3408 Gx
== GI_CHIP_ID
|| Gx
== GP_CHIP_ID
||
3409 Gx
== GQ_CHIP_ID
|| Gx
== LB_CHIP_ID
||
3411 Gx
== LI_CHIP_ID
|| Gx
== LP_CHIP_ID
) {
3412 /* RAGE PRO or LT PRO */
3415 } else if (Gx
== LG_CHIP_ID
) {
3419 } else if ((Gx
== LN_CHIP_ID
) || (Gx
== LM_CHIP_ID
)) {
3420 /* Rage mobility M1 */
3431 info
->ref_clk_per
= 1000000000000ULL/14318180;
3433 if (!(Gx
== GX_CHIP_ID
|| Gx
== CX_CHIP_ID
|| Gx
== CT_CHIP_ID
||
3435 ((Gx
== VT_CHIP_ID
|| Gx
== GT_CHIP_ID
) && !(Rev
& 0x07))) &&
3436 (pll_ref_div
= aty_ld_pll(PLL_REF_DIV
, info
))) {
3438 diff1
= 510*14/pll_ref_div
-pll
;
3439 diff2
= 510*29/pll_ref_div
-pll
;
3444 if (diff2
< diff1
) {
3445 info
->ref_clk_per
= 1000000000000ULL/29498928;
3450 i
= aty_ld_le32(MEM_CNTL
, info
);
3451 gtb_memsize
= !(Gx
== GX_CHIP_ID
|| Gx
== CX_CHIP_ID
|| Gx
== CT_CHIP_ID
||
3453 ((Gx
== VT_CHIP_ID
|| Gx
== GT_CHIP_ID
) && !(Rev
& 0x07)));
3455 switch (i
& 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */
3457 info
->total_vram
= 0x80000;
3460 info
->total_vram
= 0x100000;
3462 case MEM_SIZE_2M_GTB
:
3463 info
->total_vram
= 0x200000;
3465 case MEM_SIZE_4M_GTB
:
3466 info
->total_vram
= 0x400000;
3468 case MEM_SIZE_6M_GTB
:
3469 info
->total_vram
= 0x600000;
3471 case MEM_SIZE_8M_GTB
:
3472 info
->total_vram
= 0x800000;
3475 info
->total_vram
= 0x80000;
3478 switch (i
& MEM_SIZE_ALIAS
) {
3480 info
->total_vram
= 0x80000;
3483 info
->total_vram
= 0x100000;
3486 info
->total_vram
= 0x200000;
3489 info
->total_vram
= 0x400000;
3492 info
->total_vram
= 0x600000;
3495 info
->total_vram
= 0x800000;
3498 info
->total_vram
= 0x80000;
3501 if (Gx
== GI_CHIP_ID
) {
3502 if (aty_ld_le32(CONFIG_STAT1
, info
) & 0x40000000)
3503 info
->total_vram
+= 0x400000;
3507 info
->total_vram
= default_vram
*1024;
3508 i
= i
& ~(gtb_memsize
? 0xF : MEM_SIZE_ALIAS
);
3509 if (info
->total_vram
<= 0x80000)
3511 else if (info
->total_vram
<= 0x100000)
3513 else if (info
->total_vram
<= 0x200000)
3514 i
|= gtb_memsize
? MEM_SIZE_2M_GTB
: MEM_SIZE_2M
;
3515 else if (info
->total_vram
<= 0x400000)
3516 i
|= gtb_memsize
? MEM_SIZE_4M_GTB
: MEM_SIZE_4M
;
3517 else if (info
->total_vram
<= 0x600000)
3518 i
|= gtb_memsize
? MEM_SIZE_6M_GTB
: MEM_SIZE_6M
;
3520 i
|= gtb_memsize
? MEM_SIZE_8M_GTB
: MEM_SIZE_8M
;
3521 aty_st_le32(MEM_CNTL
, i
, info
);
3526 mclk
= default_mclk
;
3528 printk("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK\n",
3529 info
->total_vram
== 0x80000 ? 512 : (info
->total_vram
>> 20),
3530 info
->total_vram
== 0x80000 ? 'K' : 'M', ramname
, xtal
, pll
, mclk
);
3533 info
->mem_refresh_rate
= 0; /* 000 = 10 Mhz - 43 Mhz */
3535 info
->mem_refresh_rate
= 1; /* 001 = 44 Mhz - 49 Mhz */
3537 info
->mem_refresh_rate
= 2; /* 010 = 50 Mhz - 54 Mhz */
3539 info
->mem_refresh_rate
= 3; /* 011 = 55 Mhz - 65 Mhz */
3541 info
->mem_refresh_rate
= 4; /* 100 = 66 Mhz - 74 Mhz */
3543 info
->mem_refresh_rate
= 5; /* 101 = 75 Mhz - 79 Mhz */
3544 else if (mclk
< 100)
3545 info
->mem_refresh_rate
= 6; /* 110 = 80 Mhz - 100 Mhz */
3547 info
->mem_refresh_rate
= 7; /* 111 = 100 Mhz and above */
3548 info
->pll_per
= 1000000/pll
;
3549 info
->mclk_per
= 1000000/mclk
;
3552 if ((Gx
!= GX_CHIP_ID
) && (Gx
!= CX_CHIP_ID
)) {
3554 printk("BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
3555 "DSP_CONFIG DSP_ON_OFF\n"
3556 "%08x %08x %08x %08x %08x %08x %08x\n"
3558 aty_ld_le32(BUS_CNTL
, info
), aty_ld_le32(DAC_CNTL
, info
),
3559 aty_ld_le32(MEM_CNTL
, info
), aty_ld_le32(EXT_MEM_CNTL
, info
),
3560 aty_ld_le32(CRTC_GEN_CNTL
, info
), aty_ld_le32(DSP_CONFIG
, info
),
3561 aty_ld_le32(DSP_ON_OFF
, info
));
3562 for (i
= 0; i
< 16; i
++)
3563 printk(" %02x", aty_ld_pll(i
, info
));
3569 * Last page of 8 MB (4 MB on ISA) aperture is MMIO
3570 * FIXME: we should use the auxiliary aperture instead so we can acces the
3571 * full 8 MB of video RAM on 8 MB boards
3573 if (info
->total_vram
== 0x800000 ||
3574 (info
->bus_type
== ISA
&& info
->total_vram
== 0x400000))
3575 info
->total_vram
-= GUI_RESERVE
;
3577 /* Clear the video memory */
3578 fb_memset((void *)info
->frame_buffer
, 0, info
->total_vram
);
3582 strcpy(info
->fb_info
.modename
, atyfb_name
);
3583 info
->fb_info
.node
= -1;
3584 info
->fb_info
.fbops
= &atyfb_ops
;
3585 info
->fb_info
.disp
= disp
;
3586 strcpy(info
->fb_info
.fontname
, fontname
);
3587 info
->fb_info
.changevar
= NULL
;
3588 info
->fb_info
.switch_con
= &atyfbcon_switch
;
3589 info
->fb_info
.updatevar
= &atyfbcon_updatevar
;
3590 info
->fb_info
.blank
= &atyfbcon_blank
;
3591 info
->fb_info
.flags
= FBINFO_FLAG_DEFAULT
;
3593 #ifdef CONFIG_PMAC_BACKLIGHT
3594 if (Gx
== LI_CHIP_ID
&& machine_is_compatible("PowerBook1,1")) {
3595 /* these bits let the 101 powerbook wake up from sleep -- paulus */
3596 aty_st_lcd(LCD_POWER_MANAGEMENT
, aty_ld_lcd(LCD_POWER_MANAGEMENT
, info
)
3597 | (USE_F32KHZ
| TRISTATE_MEM_EN
), info
);
3599 if ((Gx
== LN_CHIP_ID
) || (Gx
== LM_CHIP_ID
))
3600 register_backlight_controller(&aty_backlight_controller
, info
, "ati");
3601 #endif /* CONFIG_PMAC_BACKLIGHT */
3606 memset(&var
, 0, sizeof(var
));
3608 if (_machine
== _MACH_Pmac
) {
3610 * FIXME: The NVRAM stuff should be put in a Mac-specific file, as it
3611 * applies to all Mac video cards
3614 if (!mac_find_mode(&var
, &info
->fb_info
, mode_option
, 8))
3618 if (default_vmode
== VMODE_NVRAM
) {
3619 default_vmode
= nvram_read_byte(NV_VMODE
);
3620 if (default_vmode
<= 0 || default_vmode
> VMODE_MAX
)
3621 default_vmode
= VMODE_CHOOSE
;
3624 if (default_vmode
== VMODE_CHOOSE
) {
3625 if (Gx
== LG_CHIP_ID
|| Gx
== LI_CHIP_ID
)
3626 /* G3 PowerBook with 1024x768 LCD */
3627 default_vmode
= VMODE_1024_768_60
;
3628 else if (machine_is_compatible("iMac"))
3629 default_vmode
= VMODE_1024_768_75
;
3630 else if (machine_is_compatible("PowerBook2,1"))
3631 /* iBook with 800x600 LCD */
3632 default_vmode
= VMODE_800_600_60
;
3634 default_vmode
= VMODE_640_480_67
;
3635 sense
= read_aty_sense(info
);
3636 printk(KERN_INFO
"atyfb: monitor sense=%x, mode %d\n",
3637 sense
, mac_map_monitor_sense(sense
));
3639 if (default_vmode
<= 0 || default_vmode
> VMODE_MAX
)
3640 default_vmode
= VMODE_640_480_60
;
3642 if (default_cmode
== CMODE_NVRAM
)
3643 default_cmode
= nvram_read_byte(NV_CMODE
);
3645 if (default_cmode
< CMODE_8
|| default_cmode
> CMODE_32
)
3646 default_cmode
= CMODE_8
;
3647 if (mac_vmode_to_var(default_vmode
, default_cmode
, &var
))
3651 else if (!fb_find_mode(&var
, &info
->fb_info
, mode_option
, NULL
, 0, NULL
, 8))
3653 #else /* !CONFIG_PPC */
3656 if (!fb_find_mode(&var
, &info
->fb_info
, mode_option
, NULL
, 0, NULL
, 8))
3661 if (!fb_find_mode(&var
, &info
->fb_info
, mode_option
, NULL
, 0, NULL
, 8))
3663 #endif /* !__sparc__ */
3664 #endif /* !CONFIG_PPC */
3665 #endif /* !MODULE */
3667 var
.accel_flags
&= ~FB_ACCELF_TEXT
;
3669 var
.accel_flags
|= FB_ACCELF_TEXT
;
3671 if (var
.yres
== var
.yres_virtual
) {
3672 u32 vram
= (info
->total_vram
- (PAGE_SIZE
<< 2));
3673 var
.yres_virtual
= ((vram
* 8) / var
.bits_per_pixel
) / var
.xres_virtual
;
3674 if (var
.yres_virtual
< var
.yres
)
3675 var
.yres_virtual
= var
.yres
;
3678 if (atyfb_decode_var(&var
, &info
->default_par
, info
)) {
3679 printk("atyfb: can't set default video mode\n");
3684 atyfb_save_palette(&info
->fb_info
, 0);
3686 for (j
= 0; j
< 16; j
++) {
3688 info
->palette
[j
].red
= default_red
[k
];
3689 info
->palette
[j
].green
= default_grn
[k
];
3690 info
->palette
[j
].blue
= default_blu
[k
];
3693 if (Gx
!= GX_CHIP_ID
&& Gx
!= CX_CHIP_ID
) {
3694 info
->cursor
= aty_init_cursor(info
);
3696 info
->dispsw
.cursor
= atyfb_cursor
;
3697 info
->dispsw
.set_font
= atyfb_set_font
;
3701 atyfb_set_var(&var
, -1, &info
->fb_info
);
3703 if (register_framebuffer(&info
->fb_info
) < 0)
3706 info
->next
= fb_list
;
3709 printk("fb%d: %s frame buffer device on %s\n",
3710 GET_FB_IDX(info
->fb_info
.node
), atyfb_name
, name
);
3714 int __init
atyfb_init(void)
3716 #if defined(CONFIG_PCI)
3717 struct pci_dev
*pdev
= NULL
;
3718 struct fb_info_aty
*info
;
3719 unsigned long addr
, res_start
, res_size
;
3722 extern void (*prom_palette
) (int);
3723 extern int con_is_present(void);
3724 struct pcidev_cookie
*pcp
;
3729 /* Do not attach when we have a serial console. */
3730 if (!con_is_present())
3736 while ((pdev
= pci_find_device(PCI_VENDOR_ID_ATI
, PCI_ANY_ID
, pdev
))) {
3737 if ((pdev
->class >> 16) == PCI_BASE_CLASS_DISPLAY
) {
3738 struct resource
*rp
;
3740 for (i
= sizeof(aty_features
)/sizeof(*aty_features
)-1; i
>= 0; i
--)
3741 if (pdev
->device
== aty_features
[i
].pci_id
)
3746 info
= kmalloc(sizeof(struct fb_info_aty
), GFP_ATOMIC
);
3748 printk("atyfb_init: can't alloc fb_info_aty\n");
3751 memset(info
, 0, sizeof(struct fb_info_aty
));
3753 rp
= &pdev
->resource
[0];
3754 if (rp
->flags
& IORESOURCE_IO
)
3755 rp
= &pdev
->resource
[1];
3760 res_start
= rp
->start
;
3761 res_size
= rp
->end
-rp
->start
+1;
3762 if (!request_mem_region(res_start
, res_size
, "atyfb"))
3767 * Map memory-mapped registers.
3769 info
->ati_regbase
= addr
+ 0x7ffc00UL
;
3770 info
->ati_regbase_phys
= addr
+ 0x7ffc00UL
;
3773 * Map in big-endian aperture.
3775 info
->frame_buffer
= (unsigned long) addr
+ 0x800000UL
;
3776 info
->frame_buffer_phys
= addr
+ 0x800000UL
;
3779 * Figure mmap addresses from PCI config space.
3780 * Split Framebuffer in big- and little-endian halfs.
3782 for (i
= 0; i
< 6 && pdev
->resource
[i
].start
; i
++)
3786 info
->mmap_map
= kmalloc(j
* sizeof(*info
->mmap_map
), GFP_ATOMIC
);
3787 if (!info
->mmap_map
) {
3788 printk("atyfb_init: can't alloc mmap_map\n");
3790 release_mem_region(res_start
, res_size
);
3793 memset(info
->mmap_map
, 0, j
* sizeof(*info
->mmap_map
));
3795 for (i
= 0, j
= 2; i
< 6 && pdev
->resource
[i
].start
; i
++) {
3796 struct resource
*rp
= &pdev
->resource
[i
];
3797 int io
, breg
= PCI_BASE_ADDRESS_0
+ (i
<< 2);
3803 io
= (rp
->flags
& IORESOURCE_IO
);
3805 size
= rp
->end
- base
+ 1;
3807 pci_read_config_dword(pdev
, breg
, &pbase
);
3813 * Map the framebuffer a second time, this time without
3814 * the braindead _PAGE_IE setting. This is used by the
3815 * fixed Xserver, but we need to maintain the old mapping
3816 * to stay compatible with older ones...
3819 info
->mmap_map
[j
].voff
= (pbase
+ 0x10000000) & PAGE_MASK
;
3820 info
->mmap_map
[j
].poff
= base
& PAGE_MASK
;
3821 info
->mmap_map
[j
].size
= (size
+ ~PAGE_MASK
) & PAGE_MASK
;
3822 info
->mmap_map
[j
].prot_mask
= _PAGE_CACHE
;
3823 info
->mmap_map
[j
].prot_flag
= _PAGE_E
;
3828 * Here comes the old framebuffer mapping with _PAGE_IE
3829 * set for the big endian half of the framebuffer...
3832 info
->mmap_map
[j
].voff
= (pbase
+ 0x800000) & PAGE_MASK
;
3833 info
->mmap_map
[j
].poff
= (base
+0x800000) & PAGE_MASK
;
3834 info
->mmap_map
[j
].size
= 0x800000;
3835 info
->mmap_map
[j
].prot_mask
= _PAGE_CACHE
;
3836 info
->mmap_map
[j
].prot_flag
= _PAGE_E
|_PAGE_IE
;
3841 info
->mmap_map
[j
].voff
= pbase
& PAGE_MASK
;
3842 info
->mmap_map
[j
].poff
= base
& PAGE_MASK
;
3843 info
->mmap_map
[j
].size
= (size
+ ~PAGE_MASK
) & PAGE_MASK
;
3844 info
->mmap_map
[j
].prot_mask
= _PAGE_CACHE
;
3845 info
->mmap_map
[j
].prot_flag
= _PAGE_E
;
3850 * Fix PROMs idea of MEM_CNTL settings...
3852 mem
= aty_ld_le32(MEM_CNTL
, info
);
3853 chip_id
= aty_ld_le32(CONFIG_CHIP_ID
, info
);
3854 if (((chip_id
& CFG_CHIP_TYPE
) == VT_CHIP_ID
) &&
3855 !((chip_id
>> 24) & 1)) {
3856 switch (mem
& 0x0f) {
3858 mem
= (mem
& ~(0x0f)) | 2;
3861 mem
= (mem
& ~(0x0f)) | 3;
3864 mem
= (mem
& ~(0x0f)) | 4;
3867 mem
= (mem
& ~(0x0f)) | 5;
3872 if ((aty_ld_le32(CONFIG_STAT0
, info
) & 7) >= SDRAM
)
3873 mem
&= ~(0x00700000);
3875 mem
&= ~(0xcf80e000); /* Turn off all undocumented bits. */
3876 aty_st_le32(MEM_CNTL
, mem
, info
);
3879 * If this is the console device, we will set default video
3880 * settings to what the PROM left us with.
3882 node
= prom_getchild(prom_root_node
);
3883 node
= prom_searchsiblings(node
, "aliases");
3885 len
= prom_getproperty(node
, "screen", prop
, sizeof(prop
));
3888 node
= prom_finddevice(prop
);
3894 pcp
= pdev
->sysdata
;
3895 if (node
== pcp
->prom_node
) {
3897 struct fb_var_screeninfo
*var
= &default_var
;
3898 unsigned int N
, P
, Q
, M
, T
;
3899 u32 v_total
, h_total
;
3904 crtc
.vxres
= prom_getintdefault(node
, "width", 1024);
3905 crtc
.vyres
= prom_getintdefault(node
, "height", 768);
3906 crtc
.bpp
= prom_getintdefault(node
, "depth", 8);
3907 crtc
.xoffset
= crtc
.yoffset
= 0;
3908 crtc
.h_tot_disp
= aty_ld_le32(CRTC_H_TOTAL_DISP
, info
);
3909 crtc
.h_sync_strt_wid
= aty_ld_le32(CRTC_H_SYNC_STRT_WID
, info
);
3910 crtc
.v_tot_disp
= aty_ld_le32(CRTC_V_TOTAL_DISP
, info
);
3911 crtc
.v_sync_strt_wid
= aty_ld_le32(CRTC_V_SYNC_STRT_WID
, info
);
3912 crtc
.gen_cntl
= aty_ld_le32(CRTC_GEN_CNTL
, info
);
3913 aty_crtc_to_var(&crtc
, var
);
3915 h_total
= var
->xres
+ var
->right_margin
+
3916 var
->hsync_len
+ var
->left_margin
;
3917 v_total
= var
->yres
+ var
->lower_margin
+
3918 var
->vsync_len
+ var
->upper_margin
;
3921 * Read the PLL to figure actual Refresh Rate.
3923 clock_cntl
= aty_ld_8(CLOCK_CNTL
, info
);
3924 /* printk("atyfb: CLOCK_CNTL: %02x\n", clock_cntl); */
3925 for (i
= 0; i
< 16; i
++)
3926 pll_regs
[i
] = aty_ld_pll(i
, info
);
3929 * PLL Reference Devider M:
3934 * PLL Feedback Devider N (Dependant on CLOCK_CNTL):
3936 N
= pll_regs
[7 + (clock_cntl
& 3)];
3939 * PLL Post Devider P (Dependant on CLOCK_CNTL):
3941 P
= 1 << (pll_regs
[6] >> ((clock_cntl
& 3) << 1));
3955 * where R is XTALIN (= 14318 kHz).
3957 T
= 2 * Q
* 14318 / M
;
3959 default_var
.pixclock
= 1000000000 / T
;
3962 #else /* __sparc__ */
3964 info
->ati_regbase_phys
= 0x7ff000 + addr
;
3965 info
->ati_regbase
= (unsigned long)
3966 ioremap(info
->ati_regbase_phys
, 0x1000);
3968 if(!info
->ati_regbase
) {
3970 release_mem_region(res_start
, res_size
);
3974 info
->ati_regbase_phys
+= 0xc00;
3975 info
->ati_regbase
+= 0xc00;
3978 * Enable memory-space accesses using config-space
3981 pci_read_config_word(pdev
, PCI_COMMAND
, &tmp
);
3982 if (!(tmp
& PCI_COMMAND_MEMORY
)) {
3983 tmp
|= PCI_COMMAND_MEMORY
;
3984 pci_write_config_word(pdev
, PCI_COMMAND
, tmp
);
3988 /* Use the big-endian aperture */
3992 /* Map in frame buffer */
3993 info
->frame_buffer_phys
= addr
;
3994 info
->frame_buffer
= (unsigned long)ioremap(addr
, 0x800000);
3996 if(!info
->frame_buffer
) {
3998 release_mem_region(res_start
, res_size
);
4002 #endif /* __sparc__ */
4004 if (!aty_init(info
, "PCI")) {
4006 kfree(info
->mmap_map
);
4008 release_mem_region(res_start
, res_size
);
4014 prom_palette
= atyfb_palette
;
4017 * Add /dev/fb mmap values.
4019 info
->mmap_map
[0].voff
= 0x8000000000000000UL
;
4020 info
->mmap_map
[0].poff
= info
->frame_buffer
& PAGE_MASK
;
4021 info
->mmap_map
[0].size
= info
->total_vram
;
4022 info
->mmap_map
[0].prot_mask
= _PAGE_CACHE
;
4023 info
->mmap_map
[0].prot_flag
= _PAGE_E
;
4024 info
->mmap_map
[1].voff
= info
->mmap_map
[0].voff
+ info
->total_vram
;
4025 info
->mmap_map
[1].poff
= info
->ati_regbase
& PAGE_MASK
;
4026 info
->mmap_map
[1].size
= PAGE_SIZE
;
4027 info
->mmap_map
[1].prot_mask
= _PAGE_CACHE
;
4028 info
->mmap_map
[1].prot_flag
= _PAGE_E
;
4029 #endif /* __sparc__ */
4031 #ifdef CONFIG_PMAC_PBOOK
4032 if (first_display
== NULL
)
4033 pmu_register_sleep_notifier(&aty_sleep_notifier
);
4034 info
->next
= first_display
;
4035 first_display
= info
;
4038 #ifdef CONFIG_FB_COMPAT_XPMAC
4039 if (!console_fb_info
)
4040 console_fb_info
= &info
->fb_info
;
4041 #endif /* CONFIG_FB_COMPAT_XPMAC */
4045 #elif defined(CONFIG_ATARI)
4048 struct fb_info_aty
*info
;
4050 for (m64_num
= 0; m64_num
< mach64_count
; m64_num
++) {
4051 if (!phys_vmembase
[m64_num
] || !phys_size
[m64_num
] ||
4052 !phys_guiregbase
[m64_num
]) {
4053 printk(" phys_*[%d] parameters not set => returning early. \n",
4058 info
= kmalloc(sizeof(struct fb_info_aty
), GFP_ATOMIC
);
4060 printk("atyfb_init: can't alloc fb_info_aty\n");
4063 memset(info
, 0, sizeof(struct fb_info_aty
));
4066 * Map the video memory (physical address given) to somewhere in the
4067 * kernel address space.
4069 info
->frame_buffer
= ioremap(phys_vmembase
[m64_num
], phys_size
[m64_num
]);
4070 info
->frame_buffer_phys
= info
->frame_buffer
; /* Fake! */
4071 info
->ati_regbase
= ioremap(phys_guiregbase
[m64_num
], 0x10000)+0xFC00ul
;
4072 info
->ati_regbase_phys
= info
->ati_regbase
; /* Fake! */
4074 aty_st_le32(CLOCK_CNTL
, 0x12345678, info
);
4075 clock_r
= aty_ld_le32(CLOCK_CNTL
, info
);
4077 switch (clock_r
& 0x003F) {
4079 info
->clk_wr_offset
= 3; /* */
4082 info
->clk_wr_offset
= 2; /* Medusa ST-IO ISA Adapter etc. */
4085 info
->clk_wr_offset
= 1; /* */
4088 info
->clk_wr_offset
= 0; /* Panther 1 ISA Adapter (Gerald) */
4092 if (!aty_init(info
, "ISA bus")) {
4094 /* This is insufficient! kernel_map has added two large chunks!! */
4098 #endif /* CONFIG_ATARI */
4103 int __init
atyfb_setup(char *options
)
4107 if (!options
|| !*options
)
4110 for (this_opt
= strtok(options
, ","); this_opt
;
4111 this_opt
= strtok(NULL
, ",")) {
4112 if (!strncmp(this_opt
, "font:", 5)) {
4117 for (i
= 0; i
< sizeof(fontname
) - 1; i
++)
4118 if (!*p
|| *p
== ' ' || *p
== ',')
4120 memcpy(fontname
, this_opt
+ 5, i
);
4122 } else if (!strncmp(this_opt
, "noblink", 7)) {
4124 } else if (!strncmp(this_opt
, "noaccel", 7)) {
4126 } else if (!strncmp(this_opt
, "vram:", 5))
4127 default_vram
= simple_strtoul(this_opt
+5, NULL
, 0);
4128 else if (!strncmp(this_opt
, "pll:", 4))
4129 default_pll
= simple_strtoul(this_opt
+4, NULL
, 0);
4130 else if (!strncmp(this_opt
, "mclk:", 5))
4131 default_mclk
= simple_strtoul(this_opt
+5, NULL
, 0);
4133 else if (!strncmp(this_opt
, "vmode:", 6)) {
4134 unsigned int vmode
= simple_strtoul(this_opt
+6, NULL
, 0);
4135 if (vmode
> 0 && vmode
<= VMODE_MAX
)
4136 default_vmode
= vmode
;
4137 } else if (!strncmp(this_opt
, "cmode:", 6)) {
4138 unsigned int cmode
= simple_strtoul(this_opt
+6, NULL
, 0);
4142 default_cmode
= CMODE_8
;
4146 default_cmode
= CMODE_16
;
4150 default_cmode
= CMODE_32
;
4157 * Why do we need this silly Mach64 argument?
4158 * We are already here because of mach64= so its redundant.
4160 else if (MACH_IS_ATARI
&& (!strncmp(this_opt
, "Mach64:", 7))) {
4161 static unsigned char m64_num
;
4162 static char mach64_str
[80];
4163 strncpy(mach64_str
, this_opt
+7, 80);
4164 if (!store_video_par(mach64_str
, m64_num
)) {
4166 mach64_count
= m64_num
;
4171 mode_option
= this_opt
;
4175 #endif /* !MODULE */
4178 static int __init
store_video_par(char *video_str
, unsigned char m64_num
)
4181 unsigned long vmembase
, size
, guiregbase
;
4183 printk("store_video_par() '%s' \n", video_str
);
4185 if (!(p
= strtoke(video_str
, ";")) || !*p
)
4186 goto mach64_invalid
;
4187 vmembase
= simple_strtoul(p
, NULL
, 0);
4188 if (!(p
= strtoke(NULL
, ";")) || !*p
)
4189 goto mach64_invalid
;
4190 size
= simple_strtoul(p
, NULL
, 0);
4191 if (!(p
= strtoke(NULL
, ";")) || !*p
)
4192 goto mach64_invalid
;
4193 guiregbase
= simple_strtoul(p
, NULL
, 0);
4195 phys_vmembase
[m64_num
] = vmembase
;
4196 phys_size
[m64_num
] = size
;
4197 phys_guiregbase
[m64_num
] = guiregbase
;
4198 printk(" stored them all: $%08lX $%08lX $%08lX \n", vmembase
, size
,
4203 phys_vmembase
[m64_num
] = 0;
4207 static char __init
*strtoke(char *s
, const char *ct
)
4209 static char *ssave
= NULL
;
4210 char *sbegin
, *send
;
4212 sbegin
= s
? s
: ssave
;
4215 if (*sbegin
== '\0') {
4219 send
= strpbrk(sbegin
, ct
);
4220 if (send
&& *send
!= '\0')
4225 #endif /* CONFIG_ATARI */
4227 static int atyfbcon_switch(int con
, struct fb_info
*fb
)
4229 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
4230 struct atyfb_par par
;
4232 /* Do we have to save the colormap? */
4233 if (fb_display
[currcon
].cmap
.len
)
4234 fb_get_cmap(&fb_display
[currcon
].cmap
, 1, atyfb_getcolreg
, fb
);
4236 /* Erase HW Cursor */
4238 atyfb_cursor(&fb_display
[currcon
], CM_ERASE
,
4239 info
->cursor
->pos
.x
, info
->cursor
->pos
.y
);
4243 atyfb_decode_var(&fb_display
[con
].var
, &par
, info
);
4244 atyfb_set_par(&par
, info
);
4245 atyfb_set_dispsw(&fb_display
[con
], info
, par
.crtc
.bpp
,
4246 par
.accel_flags
& FB_ACCELF_TEXT
);
4248 /* Install new colormap */
4249 do_install_cmap(con
, fb
);
4251 /* Install hw cursor */
4253 aty_set_cursor_color(info
, cursor_pixel_map
, cursor_color_map
,
4254 cursor_color_map
, cursor_color_map
);
4255 aty_set_cursor_shape(info
);
4261 * Blank the display.
4264 static void atyfbcon_blank(int blank
, struct fb_info
*fb
)
4266 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
4269 #ifdef CONFIG_PMAC_BACKLIGHT
4270 if ((_machine
== _MACH_Pmac
) && blank
)
4271 set_backlight_enable(0);
4272 #endif /* CONFIG_PMAC_BACKLIGHT */
4274 gen_cntl
= aty_ld_8(CRTC_GEN_CNTL
, info
);
4277 case VESA_NO_BLANKING
:
4280 case VESA_VSYNC_SUSPEND
:
4283 case VESA_HSYNC_SUSPEND
:
4286 case VESA_POWERDOWN
:
4291 gen_cntl
&= ~(0x4c);
4292 aty_st_8(CRTC_GEN_CNTL
, gen_cntl
, info
);
4294 #ifdef CONFIG_PMAC_BACKLIGHT
4295 if ((_machine
== _MACH_Pmac
) && !blank
)
4296 set_backlight_enable(1);
4297 #endif /* CONFIG_PMAC_BACKLIGHT */
4302 * Read a single color register and split it into
4303 * colors/transparent. Return != 0 for invalid regno.
4306 static int atyfb_getcolreg(u_int regno
, u_int
*red
, u_int
*green
, u_int
*blue
,
4307 u_int
*transp
, struct fb_info
*fb
)
4309 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
4313 *red
= (info
->palette
[regno
].red
<<8) | info
->palette
[regno
].red
;
4314 *green
= (info
->palette
[regno
].green
<<8) | info
->palette
[regno
].green
;
4315 *blue
= (info
->palette
[regno
].blue
<<8) | info
->palette
[regno
].blue
;
4322 * Set a single color register. The values supplied are already
4323 * rounded down to the hardware's capabilities (according to the
4324 * entries in the var structure). Return != 0 for invalid regno.
4327 static int atyfb_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
4328 u_int transp
, struct fb_info
*fb
)
4330 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
4338 info
->palette
[regno
].red
= red
;
4339 info
->palette
[regno
].green
= green
;
4340 info
->palette
[regno
].blue
= blue
;
4341 i
= aty_ld_8(DAC_CNTL
, info
) & 0xfc;
4342 if (Gx
== GT_CHIP_ID
|| Gx
== GU_CHIP_ID
|| Gx
== GV_CHIP_ID
||
4343 Gx
== GW_CHIP_ID
|| Gx
== GZ_CHIP_ID
|| Gx
== LG_CHIP_ID
||
4344 Gx
== GB_CHIP_ID
|| Gx
== GD_CHIP_ID
|| Gx
== GI_CHIP_ID
||
4345 Gx
== GP_CHIP_ID
|| Gx
== GQ_CHIP_ID
|| Gx
== LI_CHIP_ID
)
4346 i
|= 0x2; /*DAC_CNTL|0x2 turns off the extra brightness for gt*/
4347 aty_st_8(DAC_CNTL
, i
, info
);
4348 aty_st_8(DAC_MASK
, 0xff, info
);
4349 scale
= ((Gx
!= GX_CHIP_ID
) && (Gx
!= CX_CHIP_ID
) &&
4350 (info
->current_par
.crtc
.bpp
== 16)) ? 3 : 0;
4351 writeb(regno
<< scale
, &info
->aty_cmap_regs
->windex
);
4352 writeb(red
, &info
->aty_cmap_regs
->lut
);
4353 writeb(green
, &info
->aty_cmap_regs
->lut
);
4354 writeb(blue
, &info
->aty_cmap_regs
->lut
);
4356 switch (info
->current_par
.crtc
.bpp
) {
4357 #ifdef FBCON_HAS_CFB16
4359 info
->fbcon_cmap
.cfb16
[regno
] = (regno
<< 10) | (regno
<< 5) |
4363 #ifdef FBCON_HAS_CFB24
4365 info
->fbcon_cmap
.cfb24
[regno
] = (regno
<< 16) | (regno
<< 8) |
4369 #ifdef FBCON_HAS_CFB32
4371 i
= (regno
<< 8) | regno
;
4372 info
->fbcon_cmap
.cfb32
[regno
] = (i
<< 16) | i
;
4380 static void do_install_cmap(int con
, struct fb_info
*info
)
4384 if (fb_display
[con
].cmap
.len
)
4385 fb_set_cmap(&fb_display
[con
].cmap
, 1, atyfb_setcolreg
, info
);
4387 int size
= fb_display
[con
].var
.bits_per_pixel
== 16 ? 32 : 256;
4388 fb_set_cmap(fb_default_cmap(size
), 1, atyfb_setcolreg
, info
);
4394 * Accelerated functions
4397 static inline void draw_rect(s16 x
, s16 y
, u16 width
, u16 height
,
4398 struct fb_info_aty
*info
)
4400 /* perform rectangle fill */
4401 wait_for_fifo(2, info
);
4402 aty_st_le32(DST_Y_X
, (x
<< 16) | y
, info
);
4403 aty_st_le32(DST_HEIGHT_WIDTH
, (width
<< 16) | height
, info
);
4404 info
->blitter_may_be_busy
= 1;
4407 static inline void aty_rectcopy(int srcx
, int srcy
, int dstx
, int dsty
,
4408 u_int width
, u_int height
,
4409 struct fb_info_aty
*info
)
4411 u32 direction
= DST_LAST_PEL
;
4414 if (!width
|| !height
)
4417 pitch_value
= info
->current_par
.crtc
.vxres
;
4418 if (info
->current_par
.crtc
.bpp
== 24) {
4419 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
4420 /* horizontal coordinates and widths must be adjusted */
4431 direction
|= DST_Y_TOP_TO_BOTTOM
;
4437 direction
|= DST_X_LEFT_TO_RIGHT
;
4439 wait_for_fifo(4, info
);
4440 aty_st_le32(DP_SRC
, FRGD_SRC_BLIT
, info
);
4441 aty_st_le32(SRC_Y_X
, (srcx
<< 16) | srcy
, info
);
4442 aty_st_le32(SRC_HEIGHT1_WIDTH1
, (width
<< 16) | height
, info
);
4443 aty_st_le32(DST_CNTL
, direction
, info
);
4444 draw_rect(dstx
, dsty
, width
, height
, info
);
4447 static inline void aty_rectfill(int dstx
, int dsty
, u_int width
, u_int height
,
4448 u_int color
, struct fb_info_aty
*info
)
4450 if (!width
|| !height
)
4453 if (info
->current_par
.crtc
.bpp
== 24) {
4454 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
4455 /* horizontal coordinates and widths must be adjusted */
4460 wait_for_fifo(3, info
);
4461 aty_st_le32(DP_FRGD_CLR
, color
, info
);
4462 aty_st_le32(DP_SRC
, BKGD_SRC_BKGD_CLR
| FRGD_SRC_FRGD_CLR
| MONO_SRC_ONE
,
4464 aty_st_le32(DST_CNTL
, DST_LAST_PEL
| DST_Y_TOP_TO_BOTTOM
|
4465 DST_X_LEFT_TO_RIGHT
, info
);
4466 draw_rect(dstx
, dsty
, width
, height
, info
);
4470 * Update the `var' structure (called by fbcon.c)
4473 static int atyfbcon_updatevar(int con
, struct fb_info
*fb
)
4475 struct fb_info_aty
*info
= (struct fb_info_aty
*)fb
;
4476 struct atyfb_par
*par
= &info
->current_par
;
4477 struct display
*p
= &fb_display
[con
];
4478 struct vc_data
*conp
= p
->conp
;
4479 u32 yres
, yoffset
, sy
, height
;
4481 yres
= ((par
->crtc
.v_tot_disp
>> 16) & 0x7ff) + 1;
4482 yoffset
= fb_display
[con
].var
.yoffset
;
4484 sy
= (conp
->vc_rows
+ p
->yscroll
) * fontheight(p
);
4485 height
= yres
- conp
->vc_rows
* fontheight(p
);
4487 if (height
&& (yoffset
+ yres
> sy
)) {
4491 xres
= (((par
->crtc
.h_tot_disp
>> 16) & 0xff) + 1) * 8;
4492 xoffset
= fb_display
[con
].var
.xoffset
;
4495 bgx
= attr_bgcol_ec(p
, conp
);
4499 if (sy
+ height
> par
->crtc
.vyres
) {
4500 wait_for_fifo(1, info
);
4501 aty_st_le32(SC_BOTTOM
, sy
+ height
- 1, info
);
4503 aty_rectfill(xoffset
, sy
, xres
, height
, bgx
, info
);
4506 if (info
->cursor
&& (yoffset
+ yres
<= sy
))
4507 atyfb_cursor(p
, CM_ERASE
, info
->cursor
->pos
.x
, info
->cursor
->pos
.y
);
4509 info
->current_par
.crtc
.yoffset
= yoffset
;
4510 set_off_pitch(&info
->current_par
, info
);
4515 * Text console acceleration
4518 static void fbcon_aty_bmove(struct display
*p
, int sy
, int sx
, int dy
, int dx
,
4519 int height
, int width
)
4522 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4524 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4525 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4530 sy
*= fontheight(p
);
4532 dy
*= fontheight(p
);
4533 width
*= fontwidth(p
);
4534 height
*= fontheight(p
);
4536 aty_rectcopy(sx
, sy
, dx
, dy
, width
, height
,
4537 (struct fb_info_aty
*)p
->fb_info
);
4540 static void fbcon_aty_clear(struct vc_data
*conp
, struct display
*p
, int sy
,
4541 int sx
, int height
, int width
)
4545 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4547 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4548 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4552 bgx
= attr_bgcol_ec(p
, conp
);
4557 sy
*= fontheight(p
);
4558 width
*= fontwidth(p
);
4559 height
*= fontheight(p
);
4561 aty_rectfill(sx
, sy
, width
, height
, bgx
,
4562 (struct fb_info_aty
*)p
->fb_info
);
4565 #ifdef FBCON_HAS_CFB8
4566 static void fbcon_aty8_putc(struct vc_data
*conp
, struct display
*p
, int c
,
4569 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4572 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4573 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4577 if (fb
->blitter_may_be_busy
)
4578 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4579 fbcon_cfb8_putc(conp
, p
, c
, yy
, xx
);
4582 static void fbcon_aty8_putcs(struct vc_data
*conp
, struct display
*p
,
4583 const unsigned short *s
, int count
, int yy
,
4586 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4589 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4590 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4594 if (fb
->blitter_may_be_busy
)
4595 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4596 fbcon_cfb8_putcs(conp
, p
, s
, count
, yy
, xx
);
4599 static void fbcon_aty8_clear_margins(struct vc_data
*conp
, struct display
*p
,
4602 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4605 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4606 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4610 if (fb
->blitter_may_be_busy
)
4611 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4612 fbcon_cfb8_clear_margins(conp
, p
, bottom_only
);
4615 static struct display_switch fbcon_aty8
= {
4616 setup
: fbcon_cfb8_setup
,
4617 bmove
: fbcon_aty_bmove
,
4618 clear
: fbcon_aty_clear
,
4619 putc
: fbcon_aty8_putc
,
4620 putcs
: fbcon_aty8_putcs
,
4621 revc
: fbcon_cfb8_revc
,
4622 clear_margins
: fbcon_aty8_clear_margins
,
4623 fontwidthmask
: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4627 #ifdef FBCON_HAS_CFB16
4628 static void fbcon_aty16_putc(struct vc_data
*conp
, struct display
*p
, int c
,
4631 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4634 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4635 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4639 if (fb
->blitter_may_be_busy
)
4640 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4641 fbcon_cfb16_putc(conp
, p
, c
, yy
, xx
);
4644 static void fbcon_aty16_putcs(struct vc_data
*conp
, struct display
*p
,
4645 const unsigned short *s
, int count
, int yy
,
4648 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4651 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4652 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4656 if (fb
->blitter_may_be_busy
)
4657 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4658 fbcon_cfb16_putcs(conp
, p
, s
, count
, yy
, xx
);
4661 static void fbcon_aty16_clear_margins(struct vc_data
*conp
, struct display
*p
,
4664 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4667 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4668 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4672 if (fb
->blitter_may_be_busy
)
4673 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4674 fbcon_cfb16_clear_margins(conp
, p
, bottom_only
);
4677 static struct display_switch fbcon_aty16
= {
4678 setup
: fbcon_cfb16_setup
,
4679 bmove
: fbcon_aty_bmove
,
4680 clear
: fbcon_aty_clear
,
4681 putc
: fbcon_aty16_putc
,
4682 putcs
: fbcon_aty16_putcs
,
4683 revc
: fbcon_cfb16_revc
,
4684 clear_margins
: fbcon_aty16_clear_margins
,
4685 fontwidthmask
: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4689 #ifdef FBCON_HAS_CFB24
4690 static void fbcon_aty24_putc(struct vc_data
*conp
, struct display
*p
, int c
,
4693 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4696 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4697 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4701 if (fb
->blitter_may_be_busy
)
4702 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4703 fbcon_cfb24_putc(conp
, p
, c
, yy
, xx
);
4706 static void fbcon_aty24_putcs(struct vc_data
*conp
, struct display
*p
,
4707 const unsigned short *s
, int count
, int yy
,
4710 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4713 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4714 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4718 if (fb
->blitter_may_be_busy
)
4719 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4720 fbcon_cfb24_putcs(conp
, p
, s
, count
, yy
, xx
);
4723 static void fbcon_aty24_clear_margins(struct vc_data
*conp
, struct display
*p
,
4726 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4729 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4730 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4734 if (fb
->blitter_may_be_busy
)
4735 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4736 fbcon_cfb24_clear_margins(conp
, p
, bottom_only
);
4739 static struct display_switch fbcon_aty24
= {
4740 setup
: fbcon_cfb24_setup
,
4741 bmove
: fbcon_aty_bmove
,
4742 clear
: fbcon_aty_clear
,
4743 putc
: fbcon_aty24_putc
,
4744 putcs
: fbcon_aty24_putcs
,
4745 revc
: fbcon_cfb24_revc
,
4746 clear_margins
: fbcon_aty24_clear_margins
,
4747 fontwidthmask
: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4751 #ifdef FBCON_HAS_CFB32
4752 static void fbcon_aty32_putc(struct vc_data
*conp
, struct display
*p
, int c
,
4755 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4758 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4759 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4763 if (fb
->blitter_may_be_busy
)
4764 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4765 fbcon_cfb32_putc(conp
, p
, c
, yy
, xx
);
4768 static void fbcon_aty32_putcs(struct vc_data
*conp
, struct display
*p
,
4769 const unsigned short *s
, int count
, int yy
,
4772 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4775 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4776 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4780 if (fb
->blitter_may_be_busy
)
4781 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4782 fbcon_cfb32_putcs(conp
, p
, s
, count
, yy
, xx
);
4785 static void fbcon_aty32_clear_margins(struct vc_data
*conp
, struct display
*p
,
4788 struct fb_info_aty
*fb
= (struct fb_info_aty
*)(p
->fb_info
);
4791 if (fb
->mmaped
&& (!fb
->fb_info
.display_fg
4792 || fb
->fb_info
.display_fg
->vc_num
== fb
->vtconsole
))
4796 if (fb
->blitter_may_be_busy
)
4797 wait_for_idle((struct fb_info_aty
*)p
->fb_info
);
4798 fbcon_cfb32_clear_margins(conp
, p
, bottom_only
);
4801 static struct display_switch fbcon_aty32
= {
4802 setup
: fbcon_cfb32_setup
,
4803 bmove
: fbcon_aty_bmove
,
4804 clear
: fbcon_aty_clear
,
4805 putc
: fbcon_aty32_putc
,
4806 putcs
: fbcon_aty32_putcs
,
4807 revc
: fbcon_cfb32_revc
,
4808 clear_margins
: fbcon_aty32_clear_margins
,
4809 fontwidthmask
: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4813 #ifdef CONFIG_PMAC_PBOOK
4815 /* Power management routines. Those are used for PowerBook sleep.
4817 * It appears that Rage LT and Rage LT Pro have different power
4818 * management registers. There's is some confusion about which
4819 * chipID is a Rage LT or LT pro :(
4822 aty_power_mgmt_LT(int sleep
, struct fb_info_aty
*info
)
4827 pm
= aty_ld_le32(POWER_MANAGEMENT_LG
, info
);
4828 pm
= (pm
& ~PWR_MGT_MODE_MASK
) | PWR_MGT_MODE_REG
;
4829 aty_st_le32(POWER_MANAGEMENT_LG
, pm
, info
);
4830 pm
= aty_ld_le32(POWER_MANAGEMENT_LG
, info
);
4836 aty_st_le32(POWER_MANAGEMENT_LG
, pm
, info
);
4837 pm
= aty_ld_le32(POWER_MANAGEMENT_LG
, info
);
4839 pm
&= ~(PWR_BLON
| AUTO_PWR_UP
);
4841 aty_st_le32(POWER_MANAGEMENT_LG
, pm
, info
);
4842 pm
= aty_ld_le32(POWER_MANAGEMENT_LG
, info
);
4845 aty_st_le32(POWER_MANAGEMENT_LG
, pm
, info
);
4847 pm
= aty_ld_le32(POWER_MANAGEMENT_LG
, info
);
4849 if ((--timeout
) == 0)
4851 } while ((pm
& PWR_MGT_STATUS_MASK
) != PWR_MGT_STATUS_SUSPEND
);
4855 aty_st_le32(POWER_MANAGEMENT_LG
, pm
, info
);
4856 pm
= aty_ld_le32(POWER_MANAGEMENT_LG
, info
);
4858 pm
|= (PWR_BLON
| AUTO_PWR_UP
);
4860 aty_st_le32(POWER_MANAGEMENT_LG
, pm
, info
);
4861 pm
= aty_ld_le32(POWER_MANAGEMENT_LG
, info
);
4864 aty_st_le32(POWER_MANAGEMENT_LG
, pm
, info
);
4866 pm
= aty_ld_le32(POWER_MANAGEMENT_LG
, info
);
4868 if ((--timeout
) == 0)
4870 } while ((pm
& PWR_MGT_STATUS_MASK
) != 0);
4874 return timeout
? PBOOK_SLEEP_OK
: PBOOK_SLEEP_REFUSE
;
4878 aty_power_mgmt_LTPro(int sleep
, struct fb_info_aty
*info
)
4883 pm
= aty_ld_lcd(LCD_POWER_MANAGEMENT
, info
);
4884 pm
= (pm
& ~PWR_MGT_MODE_MASK
) | PWR_MGT_MODE_REG
;
4885 aty_st_lcd(LCD_POWER_MANAGEMENT
, pm
, info
);
4886 pm
= aty_ld_lcd(LCD_POWER_MANAGEMENT
, info
);
4892 aty_st_lcd(LCD_POWER_MANAGEMENT
, pm
, info
);
4893 pm
= aty_ld_lcd(LCD_POWER_MANAGEMENT
, info
);
4895 pm
&= ~(PWR_BLON
| AUTO_PWR_UP
);
4897 aty_st_lcd(LCD_POWER_MANAGEMENT
, pm
, info
);
4898 pm
= aty_ld_lcd(LCD_POWER_MANAGEMENT
, info
);
4901 aty_st_lcd(LCD_POWER_MANAGEMENT
, pm
, info
);
4903 pm
= aty_ld_lcd(LCD_POWER_MANAGEMENT
, info
);
4905 if ((--timeout
) == 0)
4907 } while ((pm
& PWR_MGT_STATUS_MASK
) != PWR_MGT_STATUS_SUSPEND
);
4911 aty_st_lcd(LCD_POWER_MANAGEMENT
, pm
, info
);
4912 pm
= aty_ld_lcd(LCD_POWER_MANAGEMENT
, info
);
4915 pm
|= (PWR_BLON
| AUTO_PWR_UP
);
4916 aty_st_lcd(LCD_POWER_MANAGEMENT
, pm
, info
);
4917 pm
= aty_ld_lcd(LCD_POWER_MANAGEMENT
, info
);
4920 aty_st_lcd(LCD_POWER_MANAGEMENT
, pm
, info
);
4922 pm
= aty_ld_lcd(LCD_POWER_MANAGEMENT
, info
);
4924 if ((--timeout
) == 0)
4926 } while ((pm
& PWR_MGT_STATUS_MASK
) != 0);
4929 return timeout
? PBOOK_SLEEP_OK
: PBOOK_SLEEP_REFUSE
;
4933 * Save the contents of the frame buffer when we go to sleep,
4934 * and restore it when we wake up again.
4937 aty_sleep_notify(struct pmu_sleep_notifier
*self
, int when
)
4939 struct fb_info_aty
*info
;
4942 result
= PBOOK_SLEEP_OK
;
4944 for (info
= first_display
; info
!= NULL
; info
= info
->next
) {
4945 struct fb_fix_screeninfo fix
;
4948 atyfb_get_fix(&fix
, fg_console
, (struct fb_info
*)info
);
4949 nb
= fb_display
[fg_console
].var
.yres
* fix
.line_length
;
4952 case PBOOK_SLEEP_REQUEST
:
4953 info
->save_framebuffer
= vmalloc(nb
);
4954 if (info
->save_framebuffer
== NULL
)
4955 return PBOOK_SLEEP_REFUSE
;
4957 case PBOOK_SLEEP_REJECT
:
4958 if (info
->save_framebuffer
) {
4959 vfree(info
->save_framebuffer
);
4960 info
->save_framebuffer
= 0;
4963 case PBOOK_SLEEP_NOW
:
4964 if (info
->blitter_may_be_busy
)
4965 wait_for_idle(info
);
4966 /* Stop accel engine (stop bus mastering) */
4967 if (info
->current_par
.accel_flags
& FB_ACCELF_TEXT
)
4970 /* Backup fb content */
4971 if (info
->save_framebuffer
)
4972 memcpy_fromio(info
->save_framebuffer
,
4973 (void *)info
->frame_buffer
, nb
);
4975 /* Blank display and LCD */
4976 atyfbcon_blank(VESA_POWERDOWN
+1, (struct fb_info
*)info
);
4978 /* Set chip to "suspend" mode */
4979 if (Gx
== LG_CHIP_ID
)
4980 result
= aty_power_mgmt_LT(1, info
);
4982 result
= aty_power_mgmt_LTPro(1, info
);
4986 if (Gx
== LG_CHIP_ID
)
4987 result
= aty_power_mgmt_LT(0, info
);
4989 result
= aty_power_mgmt_LTPro(0, info
);
4991 /* Restore fb content */
4992 if (info
->save_framebuffer
) {
4993 memcpy_toio((void *)info
->frame_buffer
,
4994 info
->save_framebuffer
, nb
);
4995 vfree(info
->save_framebuffer
);
4996 info
->save_framebuffer
= 0;
4998 /* Restore display */
4999 atyfb_set_par(&info
->current_par
, info
);
5000 atyfbcon_blank(0, (struct fb_info
*)info
);
5006 #endif /* CONFIG_PMAC_PBOOK */
5008 #ifdef CONFIG_PMAC_BACKLIGHT
5009 static int backlight_conv
[] = {
5010 0x00, 0x3f, 0x4c, 0x59, 0x66, 0x73, 0x80, 0x8d,
5011 0x9a, 0xa7, 0xb4, 0xc1, 0xcf, 0xdc, 0xe9, 0xff
5015 aty_set_backlight_enable(int on
, int level
, void* data
)
5017 struct fb_info_aty
*info
= (struct fb_info_aty
*)data
;
5018 unsigned int reg
= aty_ld_lcd(LCD_MISC_CNTL
, info
);
5020 reg
|= (BLMOD_EN
| BIASMOD_EN
);
5021 if (on
&& level
> BACKLIGHT_OFF
) {
5022 reg
&= ~BIAS_MOD_LEVEL_MASK
;
5023 reg
|= (backlight_conv
[level
] << BIAS_MOD_LEVEL_SHIFT
);
5025 reg
&= ~BIAS_MOD_LEVEL_MASK
;
5026 reg
|= (backlight_conv
[0] << BIAS_MOD_LEVEL_SHIFT
);
5028 aty_st_lcd(LCD_MISC_CNTL
, reg
, info
);
5034 aty_set_backlight_level(int level
, void* data
)
5036 return aty_set_backlight_enable(1, level
, data
);
5039 #endif /* CONFIG_PMAC_BACKLIGHT */
5043 int __init
init_module(void)
5046 return fb_list
? 0 : -ENXIO
;
5049 void cleanup_module(void)
5052 struct fb_info_aty
*info
= fb_list
;
5053 fb_list
= info
->next
;
5055 unregister_framebuffer(&info
->fb_info
);
5058 if (info
->ati_regbase
)
5059 iounmap((void *)info
->ati_regbase
);
5060 if (info
->frame_buffer
)
5061 iounmap((void *)info
->frame_buffer
);
5063 if (info
->cursor
&& info
->cursor
->ram
)
5064 iounmap(info
->cursor
->ram
);
5069 if (info
->cursor
->timer
)
5070 kfree(info
->cursor
->timer
);
5071 kfree(info
->cursor
);
5075 kfree(info
->mmap_map
);