1 /* $Id: aty128fb.c,v 1.1.1.1.36.1 1999/12/11 09:03:05 Exp $
2 * linux/drivers/video/aty128fb.c -- Frame buffer device for ATI Rage128
4 * Copyright (C) 1999-2000, Brad Douglas <brad@neruo.com>
5 * Copyright (C) 1999, Anthony Tong <atong@uiuc.edu>
7 * Ani Joshi / Jeff Garzik
10 * Based off of Geert's atyfb.c and vfb.c.
14 * - monitor sensing (DDC)
16 * - other platform support (only ppc/x86 supported)
17 * - hardware cursor support
20 * Please cc: your patches to brad@neruo.com.
24 * A special note of gratitude to ATI's devrel for providing documentation,
25 * example code and hardware. Thanks Nitya. -atong and brad
29 #include <linux/config.h>
30 #include <linux/module.h>
31 #include <linux/kernel.h>
32 #include <linux/errno.h>
33 #include <linux/string.h>
35 #include <linux/tty.h>
36 #include <linux/malloc.h>
37 #include <linux/vmalloc.h>
38 #include <linux/delay.h>
39 #include <linux/interrupt.h>
40 #include <asm/uaccess.h>
42 #include <linux/init.h>
43 #include <linux/selection.h>
44 #include <linux/console.h>
45 #include <linux/pci.h>
46 #include <linux/ioport.h>
51 #include <asm/pci-bridge.h>
52 #include <video/macmodes.h>
54 #include <linux/nvram.h>
58 #ifdef CONFIG_FB_COMPAT_XPMAC
59 #include <asm/vc_ioctl.h>
62 #include <video/fbcon.h>
63 #include <video/fbcon-cfb8.h>
64 #include <video/fbcon-cfb16.h>
65 #include <video/fbcon-cfb24.h>
66 #include <video/fbcon-cfb32.h>
78 #define DBG(fmt, args...) printk(KERN_DEBUG "aty128fb: %s " fmt, __FUNCTION__, ##args);
80 #define DBG(fmt, args...)
85 static struct fb_var_screeninfo default_var __initdata
= {
86 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
87 640, 480, 640, 480, 0, 0, 8, 0,
88 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
89 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
90 0, FB_VMODE_NONINTERLACED
93 #else /* CONFIG_PPC */
94 /* default to 1024x768 at 75Hz on PPC - this will work
95 * on the iMac, the usual 640x480 @ 60Hz doesn't. */
96 static struct fb_var_screeninfo default_var
= {
97 /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
98 1024, 768, 1024, 768, 0, 0, 8, 0,
99 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
100 0, 0, -1, -1, 0, 12699, 160, 32, 28, 1, 96, 3,
101 FB_SYNC_HOR_HIGH_ACT
|FB_SYNC_VERT_HIGH_ACT
, FB_VMODE_NONINTERLACED
103 #endif /* CONFIG_PPC */
106 /* default modedb mode */
107 /* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
108 static struct fb_videomode defaultmode __initdata
= {
120 vmode
: FB_VMODE_NONINTERLACED
124 /* struct to hold chip description information */
125 struct aty128_chip_info
{
127 unsigned short device
;
131 /* Chip generations */
138 /* supported Rage128 chipsets */
139 static const struct aty128_chip_info aty128_pci_probe_list
[] __initdata
=
141 {"Rage128 RE (PCI)", PCI_DEVICE_ID_ATI_RAGE128_RE
, rage_128
},
142 {"Rage128 RF (AGP)", PCI_DEVICE_ID_ATI_RAGE128_RF
, rage_128
},
143 {"Rage128 RK (PCI)", PCI_DEVICE_ID_ATI_RAGE128_RK
, rage_128
},
144 {"Rage128 RL (AGP)", PCI_DEVICE_ID_ATI_RAGE128_RL
, rage_128
},
145 {"Rage128 Pro PF (AGP)", PCI_DEVICE_ID_ATI_RAGE128_PF
, rage_128_pro
},
146 {"Rage128 Pro PR (PCI)", PCI_DEVICE_ID_ATI_RAGE128_PR
, rage_128_pro
},
147 {"Rage Mobility M3 (PCI)", PCI_DEVICE_ID_ATI_RAGE128_LE
, rage_M3
},
148 {"Rage Mobility M3 (AGP)", PCI_DEVICE_ID_ATI_RAGE128_LF
, rage_M3
},
152 /* packed BIOS settings */
157 u8 accelerator_entry
;
159 u16 VGA_table_offset
;
160 u16 POST_table_offset
;
166 u16 PCLK_ref_divider
;
170 u16 MCLK_ref_divider
;
174 u16 XCLK_ref_divider
;
177 } __attribute__ ((packed
)) PLL_BLOCK
;
178 #endif /* !CONFIG_PPC */
180 /* onboard memory information */
181 struct aty128_meminfo
{
195 /* various memory configurations */
196 static const struct aty128_meminfo sdr_128
=
197 { 4, 4, 3, 3, 1, 3, 1, 16, 30, 16, "128-bit SDR SGRAM (1:1)" };
198 static const struct aty128_meminfo sdr_64
=
199 { 4, 8, 3, 3, 1, 3, 1, 17, 46, 17, "64-bit SDR SGRAM (1:1)" };
200 static const struct aty128_meminfo sdr_sgram
=
201 { 4, 4, 1, 2, 1, 2, 1, 16, 24, 16, "64-bit SDR SGRAM (2:1)" };
202 static const struct aty128_meminfo ddr_sgram
=
203 { 4, 4, 3, 3, 2, 3, 1, 16, 31, 16, "64-bit DDR SGRAM" };
205 static const char *aty128fb_name
= "ATY Rage128";
206 static char fontname
[40] __initdata
= { 0 };
207 static int noaccel __initdata
= 0;
210 static const char *mode_option __initdata
= NULL
;
214 #ifdef CONFIG_NVRAM_NOT_DEFINED
215 static int default_vmode __initdata
= VMODE_640_480_60
;
216 static int default_cmode __initdata
= CMODE_8
;
218 static int default_vmode __initdata
= VMODE_NVRAM
;
219 static int default_cmode __initdata
= CMODE_NVRAM
;
228 struct aty128_constants
{
241 u32 h_total
, h_sync_strt_wid
;
242 u32 v_total
, v_sync_strt_wid
;
244 u32 offset
, offset_cntl
;
245 u32 xoffset
, yoffset
;
252 u32 feedback_divider
;
256 struct aty128_ddafifo
{
261 /* register values for a specific mode */
262 struct aty128fb_par
{
263 struct aty128_crtc crtc
;
264 struct aty128_pll pll
;
265 struct aty128_ddafifo fifo_reg
;
269 struct fb_info_aty128
{
270 struct fb_info fb_info
;
271 struct fb_info_aty128
*next
;
272 struct aty128_constants constants
; /* PLL and others */
273 u32 regbase_phys
; /* physical mmio */
274 void *regbase
; /* remapped mmio */
275 u32 frame_buffer_phys
; /* physical fb memory */
276 u32 frame_buffer
; /* remaped framebuffer */
277 u32 vram_size
; /* onboard video ram */
279 const struct aty128_meminfo
*mem
; /* onboard mem info */
280 struct aty128fb_par default_par
, current_par
;
282 struct display_switch dispsw
; /* for cursor and font */
283 struct { u8 red
, green
, blue
, pad
; } palette
[256];
285 #ifdef FBCON_HAS_CFB16
288 #ifdef FBCON_HAS_CFB24
291 #ifdef FBCON_HAS_CFB32
296 struct pci_dev
*pdev
;
299 struct { int vram
; int vram_valid
; } mtrr
;
302 int blitter_may_be_busy
;
303 int fifo_slots
; /* free slots in FIFO (64 max) */
306 static struct fb_info_aty128
*board_list
= NULL
;
308 #define round_div(n, d) ((n+(d/2))/d)
311 * Interface used by the world
314 int aty128fb_setup(char *options
);
316 static int aty128fb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
317 struct fb_info
*info
);
318 static int aty128fb_get_var(struct fb_var_screeninfo
*var
, int con
,
319 struct fb_info
*info
);
320 static int aty128fb_set_var(struct fb_var_screeninfo
*var
, int con
,
321 struct fb_info
*info
);
322 static int aty128fb_get_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
323 struct fb_info
*info
);
324 static int aty128fb_set_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
325 struct fb_info
*info
);
326 static int aty128fb_pan_display(struct fb_var_screeninfo
*var
, int con
,
328 static int aty128fb_rasterimg(struct fb_info
*info
, int start
);
332 * Interface to the low level console driver
335 int aty128fb_init(void);
336 static int aty128fbcon_switch(int con
, struct fb_info
*fb
);
337 static void aty128fbcon_blank(int blank
, struct fb_info
*fb
);
343 static void aty128_encode_fix(struct fb_fix_screeninfo
*fix
,
344 struct aty128fb_par
*par
,
345 const struct fb_info_aty128
*info
);
346 static void aty128_set_disp(struct display
*disp
,
347 struct fb_info_aty128
*info
, int bpp
, int accel
);
348 static int aty128_getcolreg(u_int regno
, u_int
*red
, u_int
*green
, u_int
*blue
,
349 u_int
*transp
, struct fb_info
*info
);
350 static int aty128_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
351 u_int transp
, struct fb_info
*info
);
352 static void do_install_cmap(int con
, struct fb_info
*info
);
353 static int aty128_encode_var(struct fb_var_screeninfo
*var
,
354 const struct aty128fb_par
*par
,
355 const struct fb_info_aty128
*info
);
356 static int aty128_decode_var(struct fb_var_screeninfo
*var
,
357 struct aty128fb_par
*par
,
358 const struct fb_info_aty128
*info
);
359 static int aty128_pci_register(struct pci_dev
*pdev
,
360 const struct aty128_chip_info
*aci
);
361 static struct fb_info_aty128
*aty128_board_list_add(struct fb_info_aty128
362 *board_list
, struct fb_info_aty128
*new_node
);
363 #if !defined(CONFIG_PPC) && !defined(__sparc__)
364 static void __init
aty128_get_pllinfo(struct fb_info_aty128
*info
,
366 static char __init
*aty128find_ROM(struct fb_info_aty128
*info
);
368 static void aty128_timings(struct fb_info_aty128
*info
);
369 static void aty128_init_engine(const struct aty128fb_par
*par
,
370 struct fb_info_aty128
*info
);
371 static void aty128_reset_engine(const struct fb_info_aty128
*info
);
372 static void aty128_flush_pixel_cache(const struct fb_info_aty128
*info
);
373 static void do_wait_for_fifo(u16 entries
, struct fb_info_aty128
*info
);
374 static void wait_for_fifo(u16 entries
, struct fb_info_aty128
*info
);
375 static void wait_for_idle(struct fb_info_aty128
*info
);
376 static u32
bpp_to_depth(u32 bpp
);
378 #ifdef FBCON_HAS_CFB8
379 static struct display_switch fbcon_aty128_8
;
380 static void fbcon_aty8_putc(struct vc_data
*conp
, struct display
*p
,
381 int c
, int yy
, int xx
);
382 static void fbcon_aty8_putcs(struct vc_data
*conp
, struct display
*p
,
383 const unsigned short *s
, int count
,
386 #ifdef FBCON_HAS_CFB16
387 static struct display_switch fbcon_aty128_16
;
388 static void fbcon_aty16_putc(struct vc_data
*conp
, struct display
*p
,
389 int c
, int yy
, int xx
);
390 static void fbcon_aty16_putcs(struct vc_data
*conp
, struct display
*p
,
391 const unsigned short *s
, int count
,
394 #ifdef FBCON_HAS_CFB24
395 static struct display_switch fbcon_aty128_24
;
396 static void fbcon_aty24_putc(struct vc_data
*conp
, struct display
*p
,
397 int c
, int yy
, int xx
);
398 static void fbcon_aty24_putcs(struct vc_data
*conp
, struct display
*p
,
399 const unsigned short *s
, int count
,
402 #ifdef FBCON_HAS_CFB32
403 static struct display_switch fbcon_aty128_32
;
404 static void fbcon_aty32_putc(struct vc_data
*conp
, struct display
*p
,
405 int c
, int yy
, int xx
);
406 static void fbcon_aty32_putcs(struct vc_data
*conp
, struct display
*p
,
407 const unsigned short *s
, int count
,
411 static struct fb_ops aty128fb_ops
= {
413 fb_get_fix
: aty128fb_get_fix
,
414 fb_get_var
: aty128fb_get_var
,
415 fb_set_var
: aty128fb_set_var
,
416 fb_get_cmap
: aty128fb_get_cmap
,
417 fb_set_cmap
: aty128fb_set_cmap
,
418 fb_pan_display
: aty128fb_pan_display
,
419 fb_rasterimg
: aty128fb_rasterimg
,
424 * Functions to read from/write to the mmio registers
425 * - endian conversions may possibly be avoided by
426 * using the other register aperture. TODO.
429 _aty_ld_le32(volatile unsigned int regindex
,
430 const struct fb_info_aty128
*info
)
434 #if defined(__powerpc__)
435 asm("lwbrx %0,%1,%2;eieio" : "=r"(val
) : "b"(regindex
), "r"(info
->regbase
));
437 val
= readl (info
->regbase
+ regindex
);
444 _aty_st_le32(volatile unsigned int regindex
, u32 val
,
445 const struct fb_info_aty128
*info
)
447 #if defined(__powerpc__)
448 asm("stwbrx %0,%1,%2;eieio" : : "r"(val
), "b"(regindex
),
449 "r"(info
->regbase
) : "memory");
451 writel (val
, info
->regbase
+ regindex
);
456 _aty_ld_8(unsigned int regindex
, const struct fb_info_aty128
*info
)
458 return readb (info
->regbase
+ regindex
);
462 _aty_st_8(unsigned int regindex
, u8 val
, const struct fb_info_aty128
*info
)
464 writeb (val
, info
->regbase
+ regindex
);
467 #define aty_ld_le32(regindex) _aty_ld_le32(regindex, info)
468 #define aty_st_le32(regindex, val) _aty_st_le32(regindex, val, info)
469 #define aty_ld_8(regindex) _aty_ld_8(regindex, info)
470 #define aty_st_8(regindex, val) _aty_st_8(regindex, val, info)
473 * Functions to read from/write to the pll registers
476 #define aty_ld_pll(pll_index) _aty_ld_pll(pll_index, info)
477 #define aty_st_pll(pll_index, val) _aty_st_pll(pll_index, val, info)
481 _aty_ld_pll(unsigned int pll_index
,
482 const struct fb_info_aty128
*info
)
484 aty_st_8(CLOCK_CNTL_INDEX
, pll_index
& 0x1F);
485 return aty_ld_le32(CLOCK_CNTL_DATA
);
490 _aty_st_pll(unsigned int pll_index
, u32 val
,
491 const struct fb_info_aty128
*info
)
493 aty_st_8(CLOCK_CNTL_INDEX
, (pll_index
& 0x1F) | PLL_WR_EN
);
494 aty_st_le32(CLOCK_CNTL_DATA
, val
);
498 /* return true when the PLL has completed an atomic update */
500 aty_pll_readupdate(const struct fb_info_aty128
*info
)
502 return !(aty_ld_pll(PPLL_REF_DIV
) & PPLL_ATOMIC_UPDATE_R
);
507 aty_pll_wait_readupdate(const struct fb_info_aty128
*info
)
509 unsigned long timeout
= jiffies
+ HZ
/100; // should be more than enough
512 while (time_before(jiffies
, timeout
))
513 if (aty_pll_readupdate(info
)) {
518 if (reset
) /* reset engine?? */
519 printk(KERN_DEBUG
"aty128fb: PLL write timeout!");
523 /* tell PLL to update */
525 aty_pll_writeupdate(const struct fb_info_aty128
*info
)
527 aty_pll_wait_readupdate(info
);
529 aty_st_pll(PPLL_REF_DIV
,
530 aty_ld_pll(PPLL_REF_DIV
) | PPLL_ATOMIC_UPDATE_W
);
534 /* write to the scratch register to test r/w functionality */
536 register_test(const struct fb_info_aty128
*info
)
541 val
= aty_ld_le32(BIOS_0_SCRATCH
);
543 aty_st_le32(BIOS_0_SCRATCH
, 0x55555555);
544 if (aty_ld_le32(BIOS_0_SCRATCH
) == 0x55555555) {
545 aty_st_le32(BIOS_0_SCRATCH
, 0xAAAAAAAA);
547 if (aty_ld_le32(BIOS_0_SCRATCH
) == 0xAAAAAAAA)
551 aty_st_le32(BIOS_0_SCRATCH
, val
); // restore value
557 * Accelerator engine functions
560 do_wait_for_fifo(u16 entries
, struct fb_info_aty128
*info
)
565 for (i
= 0; i
< 2000000; i
++) {
566 info
->fifo_slots
= aty_ld_le32(GUI_STAT
) & 0x0fff;
567 if (info
->fifo_slots
>= entries
)
570 aty128_reset_engine(info
);
576 wait_for_idle(struct fb_info_aty128
*info
)
580 do_wait_for_fifo(64, info
);
583 for (i
= 0; i
< 2000000; i
++) {
584 if (!(aty_ld_le32(GUI_STAT
) & (1 << 31))) {
585 aty128_flush_pixel_cache(info
);
586 info
->blitter_may_be_busy
= 0;
590 aty128_reset_engine(info
);
596 wait_for_fifo(u16 entries
, struct fb_info_aty128
*info
)
598 if (info
->fifo_slots
< entries
)
599 do_wait_for_fifo(64, info
);
600 info
->fifo_slots
-= entries
;
605 aty128_flush_pixel_cache(const struct fb_info_aty128
*info
)
610 tmp
= aty_ld_le32(PC_NGUI_CTLSTAT
);
613 aty_st_le32(PC_NGUI_CTLSTAT
, tmp
);
615 for (i
= 0; i
< 2000000; i
++)
616 if (!(aty_ld_le32(PC_NGUI_CTLSTAT
) & PC_BUSY
))
622 aty128_reset_engine(const struct fb_info_aty128
*info
)
624 u32 gen_reset_cntl
, clock_cntl_index
, mclk_cntl
;
626 aty128_flush_pixel_cache(info
);
628 clock_cntl_index
= aty_ld_le32(CLOCK_CNTL_INDEX
);
629 mclk_cntl
= aty_ld_pll(MCLK_CNTL
);
631 aty_st_pll(MCLK_CNTL
, mclk_cntl
| 0x00030000);
633 gen_reset_cntl
= aty_ld_le32(GEN_RESET_CNTL
);
634 aty_st_le32(GEN_RESET_CNTL
, gen_reset_cntl
| SOFT_RESET_GUI
);
635 aty_ld_le32(GEN_RESET_CNTL
);
636 aty_st_le32(GEN_RESET_CNTL
, gen_reset_cntl
& ~(SOFT_RESET_GUI
));
637 aty_ld_le32(GEN_RESET_CNTL
);
639 aty_st_pll(MCLK_CNTL
, mclk_cntl
);
640 aty_st_le32(CLOCK_CNTL_INDEX
, clock_cntl_index
);
641 aty_st_le32(GEN_RESET_CNTL
, gen_reset_cntl
);
643 /* use old pio mode */
644 aty_st_le32(PM4_BUFFER_CNTL
, PM4_BUFFER_CNTL_NONPM4
);
651 aty128_init_engine(const struct aty128fb_par
*par
,
652 struct fb_info_aty128
*info
)
658 /* 3D scaler not spoken here */
659 wait_for_fifo(1, info
);
660 aty_st_le32(SCALE_3D_CNTL
, 0x00000000);
662 aty128_reset_engine(info
);
664 pitch_value
= par
->crtc
.pitch
;
665 if (par
->crtc
.bpp
== 24) {
666 pitch_value
= pitch_value
* 3;
669 wait_for_fifo(4, info
);
670 /* setup engine offset registers */
671 aty_st_le32(DEFAULT_OFFSET
, 0x00000000);
673 /* setup engine pitch registers */
674 aty_st_le32(DEFAULT_PITCH
, pitch_value
);
676 /* set the default scissor register to max dimensions */
677 aty_st_le32(DEFAULT_SC_BOTTOM_RIGHT
, (0x1FFF << 16) | 0x1FFF);
679 /* set the drawing controls registers */
680 aty_st_le32(DP_GUI_MASTER_CNTL
,
681 GMC_SRC_PITCH_OFFSET_DEFAULT
|
682 GMC_DST_PITCH_OFFSET_DEFAULT
|
683 GMC_SRC_CLIP_DEFAULT
|
684 GMC_DST_CLIP_DEFAULT
|
685 GMC_BRUSH_SOLIDCOLOR
|
686 (bpp_to_depth(par
->crtc
.bpp
) << 8) |
688 GMC_BYTE_ORDER_MSB_TO_LSB
|
689 GMC_DP_CONVERSION_TEMP_6500
|
693 GMC_DST_CLR_CMP_FCN_CLEAR
|
697 wait_for_fifo(8, info
);
698 /* clear the line drawing registers */
699 aty_st_le32(DST_BRES_ERR
, 0);
700 aty_st_le32(DST_BRES_INC
, 0);
701 aty_st_le32(DST_BRES_DEC
, 0);
703 /* set brush color registers */
704 aty_st_le32(DP_BRUSH_FRGD_CLR
, 0xFFFFFFFF); /* white */
705 aty_st_le32(DP_BRUSH_BKGD_CLR
, 0x00000000); /* black */
707 /* set source color registers */
708 aty_st_le32(DP_SRC_FRGD_CLR
, 0xFFFFFFFF); /* white */
709 aty_st_le32(DP_SRC_BKGD_CLR
, 0x00000000); /* black */
711 /* default write mask */
712 aty_st_le32(DP_WRITE_MASK
, 0xFFFFFFFF);
714 /* Wait for all the writes to be completed before returning */
719 /* convert bpp values to their register representation */
721 bpp_to_depth(u32 bpp
)
740 /* Program the CRTC registers */
742 aty128_set_crtc(const struct aty128_crtc
*crtc
,
743 const struct fb_info_aty128
*info
)
745 aty_st_le32(CRTC_GEN_CNTL
, crtc
->gen_cntl
);
746 aty_st_le32(CRTC_H_TOTAL_DISP
, crtc
->h_total
);
747 aty_st_le32(CRTC_H_SYNC_STRT_WID
, crtc
->h_sync_strt_wid
);
748 aty_st_le32(CRTC_V_TOTAL_DISP
, crtc
->v_total
);
749 aty_st_le32(CRTC_V_SYNC_STRT_WID
, crtc
->v_sync_strt_wid
);
750 aty_st_le32(CRTC_PITCH
, crtc
->pitch
);
751 aty_st_le32(CRTC_OFFSET
, crtc
->offset
);
752 aty_st_le32(CRTC_OFFSET_CNTL
, crtc
->offset_cntl
);
753 /* Disable ATOMIC updating. Is this the right place?
754 * -- BenH: Breaks on my G4
757 aty_st_le32(PPLL_CNTL
, aty_ld_le32(PPLL_CNTL
) & ~(0x00030000));
763 aty128_var_to_crtc(const struct fb_var_screeninfo
*var
,
764 struct aty128_crtc
*crtc
,
765 const struct fb_info_aty128
*info
)
767 u32 xres
, yres
, vxres
, vyres
, xoffset
, yoffset
, bpp
;
768 u32 left
, right
, upper
, lower
, hslen
, vslen
, sync
, vmode
;
769 u32 h_total
, h_disp
, h_sync_strt
, h_sync_wid
, h_sync_pol
;
770 u32 v_total
, v_disp
, v_sync_strt
, v_sync_wid
, v_sync_pol
, c_sync
;
772 u8 hsync_strt_pix
[5] = { 0, 0x12, 9, 6, 5 };
773 u8 mode_bytpp
[7] = { 0, 0, 1, 2, 2, 3, 4 };
778 vxres
= var
->xres_virtual
;
779 vyres
= var
->yres_virtual
;
780 xoffset
= var
->xoffset
;
781 yoffset
= var
->yoffset
;
782 bpp
= var
->bits_per_pixel
;
783 left
= var
->left_margin
;
784 right
= var
->right_margin
;
785 upper
= var
->upper_margin
;
786 lower
= var
->lower_margin
;
787 hslen
= var
->hsync_len
;
788 vslen
= var
->vsync_len
;
792 /* check for mode eligibility
793 * accept only non interlaced modes */
794 if ((vmode
& FB_VMODE_MASK
) != FB_VMODE_NONINTERLACED
)
797 /* convert (and round up) and validate */
798 xres
= (xres
+ 7) & ~7;
799 xoffset
= (xoffset
+ 7) & ~7;
801 if (vxres
< xres
+ xoffset
)
802 vxres
= xres
+ xoffset
;
804 if (vyres
< yres
+ yoffset
)
805 vyres
= yres
+ yoffset
;
807 /* convert bpp into ATI register depth */
808 depth
= bpp_to_depth(bpp
);
810 /* make sure we didn't get an invalid depth */
811 if (depth
== -EINVAL
) {
812 printk(KERN_ERR
"aty128fb: Invalid depth\n");
816 /* convert depth to bpp */
817 bytpp
= mode_bytpp
[depth
];
819 /* make sure there is enough video ram for the mode */
820 if ((u32
)(vxres
* vyres
* bytpp
) > info
->vram_size
) {
821 printk(KERN_ERR
"aty128fb: Not enough memory for mode\n");
825 h_disp
= (xres
>> 3) - 1;
826 h_total
= (((xres
+ right
+ hslen
+ left
) >> 3) - 1) & 0xFFFFL
;
829 v_total
= (yres
+ upper
+ vslen
+ lower
- 1) & 0xFFFFL
;
831 /* check to make sure h_total and v_total are in range */
832 if (((h_total
>> 3) - 1) > 0x1ff || (v_total
- 1) > 0x7FF) {
833 printk(KERN_ERR
"aty128fb: invalid width ranges\n");
837 h_sync_wid
= (hslen
+ 7) >> 3;
840 else if (h_sync_wid
> 0x3f) /* 0x3f = max hwidth */
843 h_sync_strt
= h_disp
+ (right
>> 3);
848 else if (v_sync_wid
> 0x1f) /* 0x1f = max vwidth */
851 v_sync_strt
= v_disp
+ lower
;
853 h_sync_pol
= sync
& FB_SYNC_HOR_HIGH_ACT
? 0 : 1;
854 v_sync_pol
= sync
& FB_SYNC_VERT_HIGH_ACT
? 0 : 1;
856 c_sync
= sync
& FB_SYNC_COMP_HIGH_ACT
? (1 << 4) : 0;
858 crtc
->gen_cntl
= 0x3000000L
| c_sync
| (depth
<< 8);
860 crtc
->h_total
= h_total
| (h_disp
<< 16);
861 crtc
->v_total
= v_total
| (v_disp
<< 16);
863 crtc
->h_sync_strt_wid
= hsync_strt_pix
[bytpp
] | (h_sync_strt
<< 3) |
864 (h_sync_wid
<< 16) | (h_sync_pol
<< 23);
865 crtc
->v_sync_strt_wid
= v_sync_strt
| (v_sync_wid
<< 16) |
868 crtc
->pitch
= vxres
>> 3;
871 crtc
->offset_cntl
= 0;
875 crtc
->xoffset
= xoffset
;
876 crtc
->yoffset
= yoffset
;
884 aty128_bpp_to_var(int pix_width
, struct fb_var_screeninfo
*var
)
887 /* fill in pixel info */
889 case CRTC_PIX_WIDTH_8BPP
:
890 var
->bits_per_pixel
= 8;
893 var
->green
.offset
= 0;
894 var
->green
.length
= 8;
895 var
->blue
.offset
= 0;
896 var
->blue
.length
= 8;
897 var
->transp
.offset
= 0;
898 var
->transp
.length
= 0;
900 case CRTC_PIX_WIDTH_15BPP
:
901 case CRTC_PIX_WIDTH_16BPP
:
902 var
->bits_per_pixel
= 16;
903 var
->red
.offset
= 10;
905 var
->green
.offset
= 5;
906 var
->green
.length
= 5;
907 var
->blue
.offset
= 0;
908 var
->blue
.length
= 5;
909 var
->transp
.offset
= 0;
910 var
->transp
.length
= 0;
912 case CRTC_PIX_WIDTH_24BPP
:
913 var
->bits_per_pixel
= 24;
914 var
->red
.offset
= 16;
916 var
->green
.offset
= 8;
917 var
->green
.length
= 8;
918 var
->blue
.offset
= 0;
919 var
->blue
.length
= 8;
920 var
->transp
.offset
= 0;
921 var
->transp
.length
= 0;
923 case CRTC_PIX_WIDTH_32BPP
:
924 var
->bits_per_pixel
= 32;
925 var
->red
.offset
= 16;
927 var
->green
.offset
= 8;
928 var
->green
.length
= 8;
929 var
->blue
.offset
= 0;
930 var
->blue
.length
= 8;
931 var
->transp
.offset
= 24;
932 var
->transp
.length
= 8;
935 printk(KERN_ERR
"aty128fb: Invalid pixel width\n");
944 aty128_crtc_to_var(const struct aty128_crtc
*crtc
,
945 struct fb_var_screeninfo
*var
)
947 u32 xres
, yres
, left
, right
, upper
, lower
, hslen
, vslen
, sync
;
948 u32 h_total
, h_disp
, h_sync_strt
, h_sync_dly
, h_sync_wid
, h_sync_pol
;
949 u32 v_total
, v_disp
, v_sync_strt
, v_sync_wid
, v_sync_pol
, c_sync
;
952 /* fun with masking */
953 h_total
= crtc
->h_total
& 0x1ff;
954 h_disp
= (crtc
->h_total
>> 16) & 0xff;
955 h_sync_strt
= (crtc
->h_sync_strt_wid
>> 3) & 0x1ff;
956 h_sync_dly
= crtc
->h_sync_strt_wid
& 0x7;
957 h_sync_wid
= (crtc
->h_sync_strt_wid
>> 16) & 0x3f;
958 h_sync_pol
= (crtc
->h_sync_strt_wid
>> 23) & 0x1;
959 v_total
= crtc
->v_total
& 0x7ff;
960 v_disp
= (crtc
->v_total
>> 16) & 0x7ff;
961 v_sync_strt
= crtc
->v_sync_strt_wid
& 0x7ff;
962 v_sync_wid
= (crtc
->v_sync_strt_wid
>> 16) & 0x1f;
963 v_sync_pol
= (crtc
->v_sync_strt_wid
>> 23) & 0x1;
964 c_sync
= crtc
->gen_cntl
& CRTC_CSYNC_EN
? 1 : 0;
965 pix_width
= crtc
->gen_cntl
& CRTC_PIX_WIDTH_MASK
;
968 xres
= (h_disp
+ 1) << 3;
970 left
= ((h_total
- h_sync_strt
- h_sync_wid
) << 3) - h_sync_dly
;
971 right
= ((h_sync_strt
- h_disp
) << 3) + h_sync_dly
;
972 hslen
= h_sync_wid
<< 3;
973 upper
= v_total
- v_sync_strt
- v_sync_wid
;
974 lower
= v_sync_strt
- v_disp
;
976 sync
= (h_sync_pol
? 0 : FB_SYNC_HOR_HIGH_ACT
) |
977 (v_sync_pol
? 0 : FB_SYNC_VERT_HIGH_ACT
) |
978 (c_sync
? FB_SYNC_COMP_HIGH_ACT
: 0);
980 aty128_bpp_to_var(pix_width
, var
);
984 var
->xres_virtual
= crtc
->vxres
;
985 var
->yres_virtual
= crtc
->vyres
;
986 var
->xoffset
= crtc
->xoffset
;
987 var
->yoffset
= crtc
->yoffset
;
988 var
->left_margin
= left
;
989 var
->right_margin
= right
;
990 var
->upper_margin
= upper
;
991 var
->lower_margin
= lower
;
992 var
->hsync_len
= hslen
;
993 var
->vsync_len
= vslen
;
995 var
->vmode
= FB_VMODE_NONINTERLACED
;
1001 aty128_set_pll(struct aty128_pll
*pll
, const struct fb_info_aty128
*info
)
1005 unsigned char post_conv
[] = /* register values for post dividers */
1006 { 2, 0, 1, 4, 2, 2, 6, 2, 3, 2, 2, 2, 7 };
1008 /* select PPLL_DIV_3 */
1009 aty_st_le32(CLOCK_CNTL_INDEX
, aty_ld_le32(CLOCK_CNTL_INDEX
) | (3 << 8));
1012 aty_st_pll(PPLL_CNTL
,
1013 aty_ld_pll(PPLL_CNTL
) | PPLL_RESET
| PPLL_ATOMIC_UPDATE_EN
);
1015 /* write the reference divider */
1016 aty_pll_wait_readupdate(info
);
1017 aty_st_pll(PPLL_REF_DIV
, info
->constants
.ref_divider
& 0x3ff);
1018 aty_pll_writeupdate(info
);
1020 div3
= aty_ld_pll(PPLL_DIV_3
);
1021 div3
&= ~PPLL_FB3_DIV_MASK
;
1022 div3
|= pll
->feedback_divider
;
1023 div3
&= ~PPLL_POST3_DIV_MASK
;
1024 div3
|= post_conv
[pll
->post_divider
] << 16;
1026 /* write feedback and post dividers */
1027 aty_pll_wait_readupdate(info
);
1028 aty_st_pll(PPLL_DIV_3
, div3
);
1029 aty_pll_writeupdate(info
);
1031 aty_pll_wait_readupdate(info
);
1032 aty_st_pll(HTOTAL_CNTL
, 0); /* no horiz crtc adjustment */
1033 aty_pll_writeupdate(info
);
1035 /* clear the reset, just in case */
1036 aty_st_pll(PPLL_CNTL
, aty_ld_pll(PPLL_CNTL
) & ~PPLL_RESET
);
1041 aty128_var_to_pll(u32 period_in_ps
, struct aty128_pll
*pll
,
1042 const struct fb_info_aty128
*info
)
1044 const struct aty128_constants c
= info
->constants
;
1045 unsigned char post_dividers
[] = {1,2,4,8,3,6,12};
1047 u32 vclk
; /* in .01 MHz */
1051 vclk
= 100000000 / period_in_ps
; /* convert units to 10 kHz */
1053 /* adjust pixel clock if necessary */
1054 if (vclk
> c
.ppll_max
)
1056 if (vclk
* 12 < c
.ppll_min
)
1057 vclk
= c
.ppll_min
/12;
1059 /* now, find an acceptable divider */
1060 for (i
= 0; i
< sizeof(post_dividers
); i
++) {
1061 output_freq
= post_dividers
[i
] * vclk
;
1062 if (output_freq
>= c
.ppll_min
&& output_freq
<= c
.ppll_max
)
1066 /* calculate feedback divider */
1067 n
= c
.ref_divider
* output_freq
;
1070 pll
->post_divider
= post_dividers
[i
];
1071 pll
->feedback_divider
= round_div(n
, d
);
1074 DBG("post %d feedback %d vlck %d output %d ref_divider %d "
1075 "vclk_per: %d\n", pll
->post_divider
,
1076 pll
->feedback_divider
, vclk
, output_freq
,
1077 c
.ref_divider
, period_in_ps
);
1084 aty128_pll_to_var(const struct aty128_pll
*pll
, struct fb_var_screeninfo
*var
,
1085 const struct fb_info_aty128
*info
)
1087 var
->pixclock
= 100000000 / pll
->vclk
;
1094 aty128_set_fifo(const struct aty128_ddafifo
*dsp
,
1095 const struct fb_info_aty128
*info
)
1097 aty_st_le32(DDA_CONFIG
, dsp
->dda_config
);
1098 aty_st_le32(DDA_ON_OFF
, dsp
->dda_on_off
);
1103 aty128_ddafifo(struct aty128_ddafifo
*dsp
,
1104 const struct aty128_pll
*pll
,
1106 const struct fb_info_aty128
*info
)
1108 const struct aty128_meminfo
*m
= info
->mem
;
1109 u32 xclk
= info
->constants
.xclk
;
1110 u32 fifo_width
= info
->constants
.fifo_width
;
1111 u32 fifo_depth
= info
->constants
.fifo_depth
;
1112 s32 x
, b
, p
, ron
, roff
;
1115 /* 15bpp is really 16bpp */
1119 n
= xclk
* fifo_width
;
1120 d
= pll
->vclk
* bpp
;
1121 x
= round_div(n
, d
);
1124 3 * ((m
->Trcd
- 2 > 0) ? m
->Trcd
- 2 : 0) +
1143 x
= round_div(n
, d
);
1144 roff
= x
* (fifo_depth
- 4);
1146 if ((ron
+ m
->Rloop
) >= roff
) {
1147 printk(KERN_ERR
"aty128fb: Mode out of range!\n");
1151 DBG("p: %x rloop: %x x: %x ron: %x roff: %x\n",
1152 p
, m
->Rloop
, x
, ron
, roff
);
1154 dsp
->dda_config
= p
<< 16 | m
->Rloop
<< 20 | x
;
1155 dsp
->dda_on_off
= ron
<< 16 | roff
;
1162 * This actually sets the video mode.
1165 aty128_set_par(struct aty128fb_par
*par
,
1166 struct fb_info_aty128
*info
)
1170 info
->current_par
= *par
;
1172 if (info
->blitter_may_be_busy
)
1173 wait_for_idle(info
);
1175 /* clear all registers that may interfere with mode setting */
1176 aty_st_le32(OVR_CLR
, 0);
1177 aty_st_le32(OVR_WID_LEFT_RIGHT
, 0);
1178 aty_st_le32(OVR_WID_TOP_BOTTOM
, 0);
1179 aty_st_le32(OV0_SCALE_CNTL
, 0);
1180 aty_st_le32(MPP_TB_CONFIG
, 0);
1181 aty_st_le32(MPP_GP_CONFIG
, 0);
1182 aty_st_le32(SUBPIC_CNTL
, 0);
1183 aty_st_le32(VIPH_CONTROL
, 0);
1184 aty_st_le32(I2C_CNTL_1
, 0); /* turn off i2c */
1185 aty_st_le32(GEN_INT_CNTL
, 0); /* turn off interrupts */
1186 aty_st_le32(CAP0_TRIG_CNTL
, 0);
1187 aty_st_le32(CAP1_TRIG_CNTL
, 0);
1189 aty_st_8(CRTC_EXT_CNTL
+ 1, 4); /* turn video off */
1191 aty128_set_crtc(&par
->crtc
, info
);
1192 aty128_set_pll(&par
->pll
, info
);
1193 aty128_set_fifo(&par
->fifo_reg
, info
);
1195 config
= aty_ld_le32(CONFIG_CNTL
) & ~3;
1197 #if defined(__BIG_ENDIAN)
1198 if (par
->crtc
.bpp
>= 24)
1199 config
|= 2; /* make aperture do 32 byte swapping */
1200 else if (par
->crtc
.bpp
> 8)
1201 config
|= 1; /* make aperture do 16 byte swapping */
1204 aty_st_le32(CONFIG_CNTL
, config
);
1205 aty_st_8(CRTC_EXT_CNTL
+ 1, 0); /* turn the video back on */
1207 if (par
->accel_flags
& FB_ACCELF_TEXT
)
1208 aty128_init_engine(par
, info
);
1210 #ifdef CONFIG_FB_COMPAT_XPMAC
1211 if (!console_fb_info
|| console_fb_info
== &info
->fb_info
) {
1212 struct fb_var_screeninfo var
;
1215 display_info
.height
= ((par
->crtc
.v_total
>> 16) & 0x7ff) + 1;
1216 display_info
.width
= (((par
->crtc
.h_total
>> 16) & 0xff) + 1) << 3;
1217 display_info
.depth
= par
->crtc
.bpp
;
1218 display_info
.pitch
= (par
->crtc
.vxres
* par
->crtc
.bpp
) >> 3;
1219 aty128_encode_var(&var
, par
, info
);
1220 if (mac_var_to_vmode(&var
, &vmode
, &cmode
))
1221 display_info
.mode
= 0;
1223 display_info
.mode
= vmode
;
1224 strcpy(display_info
.name
, aty128fb_name
);
1225 display_info
.fb_address
= info
->frame_buffer_phys
;
1226 display_info
.cmap_adr_address
= 0;
1227 display_info
.cmap_data_address
= 0;
1228 display_info
.disp_reg_address
= info
->regbase_phys
;
1230 #endif /* CONFIG_FB_COMPAT_XPMAC */
1234 * encode/decode the User Defined Part of the Display
1238 aty128_decode_var(struct fb_var_screeninfo
*var
, struct aty128fb_par
*par
,
1239 const struct fb_info_aty128
*info
)
1243 if ((err
= aty128_var_to_crtc(var
, &par
->crtc
, info
)))
1246 if ((err
= aty128_var_to_pll(var
->pixclock
, &par
->pll
, info
)))
1249 if ((err
= aty128_ddafifo(&par
->fifo_reg
, &par
->pll
, par
->crtc
.bpp
, info
)))
1252 if (var
->accel_flags
& FB_ACCELF_TEXT
)
1253 par
->accel_flags
= FB_ACCELF_TEXT
;
1255 par
->accel_flags
= 0;
1262 aty128_encode_var(struct fb_var_screeninfo
*var
,
1263 const struct aty128fb_par
*par
,
1264 const struct fb_info_aty128
*info
)
1268 if ((err
= aty128_crtc_to_var(&par
->crtc
, var
)))
1271 if ((err
= aty128_pll_to_var(&par
->pll
, var
, info
)))
1274 var
->red
.msb_right
= 0;
1275 var
->green
.msb_right
= 0;
1276 var
->blue
.msb_right
= 0;
1277 var
->transp
.msb_right
= 0;
1284 var
->accel_flags
= par
->accel_flags
;
1291 * Get the User Defined Part of the Display
1295 aty128fb_get_var(struct fb_var_screeninfo
*var
, int con
, struct fb_info
*fb
)
1297 const struct fb_info_aty128
*info
= (struct fb_info_aty128
*)fb
;
1300 aty128_encode_var(var
, &info
->default_par
, info
);
1302 *var
= fb_display
[con
].var
;
1308 * Set the User Defined Part of the Display
1312 aty128fb_set_var(struct fb_var_screeninfo
*var
, int con
, struct fb_info
*fb
)
1314 struct fb_info_aty128
*info
= (struct fb_info_aty128
*)fb
;
1315 struct aty128fb_par par
;
1316 struct display
*display
;
1317 int oldxres
, oldyres
, oldvxres
, oldvyres
, oldbpp
, oldaccel
;
1320 display
= (con
>= 0) ? &fb_display
[con
] : fb
->disp
;
1322 /* basic (in)sanity checks */
1327 if (var
->xres
> var
->xres_virtual
)
1328 var
->xres_virtual
= var
->xres
;
1329 if (var
->yres
> var
->yres_virtual
)
1330 var
->yres_virtual
= var
->yres
;
1332 switch (var
->bits_per_pixel
) {
1334 var
->bits_per_pixel
= 8;
1337 var
->bits_per_pixel
= 16;
1340 var
->bits_per_pixel
= 24;
1343 var
->bits_per_pixel
= 32;
1349 if ((err
= aty128_decode_var(var
, &par
, info
)))
1352 aty128_encode_var(var
, &par
, info
);
1354 if ((var
->activate
& FB_ACTIVATE_MASK
) != FB_ACTIVATE_NOW
)
1357 oldxres
= display
->var
.xres
;
1358 oldyres
= display
->var
.yres
;
1359 oldvxres
= display
->var
.xres_virtual
;
1360 oldvyres
= display
->var
.yres_virtual
;
1361 oldbpp
= display
->var
.bits_per_pixel
;
1362 oldaccel
= display
->var
.accel_flags
;
1363 display
->var
= *var
;
1364 if (oldxres
!= var
->xres
|| oldyres
!= var
->yres
||
1365 oldvxres
!= var
->xres_virtual
|| oldvyres
!= var
->yres_virtual
||
1366 oldbpp
!= var
->bits_per_pixel
|| oldaccel
!= var
->accel_flags
) {
1368 struct fb_fix_screeninfo fix
;
1370 aty128_encode_fix(&fix
, &par
, info
);
1371 display
->screen_base
= (char *)info
->frame_buffer
;
1372 display
->visual
= fix
.visual
;
1373 display
->type
= fix
.type
;
1374 display
->type_aux
= fix
.type_aux
;
1375 display
->ypanstep
= fix
.ypanstep
;
1376 display
->ywrapstep
= fix
.ywrapstep
;
1377 display
->line_length
= fix
.line_length
;
1378 display
->can_soft_blank
= 1;
1379 display
->inverse
= 0;
1381 accel
= var
->accel_flags
& FB_ACCELF_TEXT
;
1382 aty128_set_disp(display
, info
, par
.crtc
.bpp
, accel
);
1385 display
->scrollmode
= SCROLL_YNOMOVE
;
1387 display
->scrollmode
= SCROLL_YREDRAW
;
1389 if (info
->fb_info
.changevar
)
1390 (*info
->fb_info
.changevar
)(con
);
1393 if (!info
->fb_info
.display_fg
|| info
->fb_info
.display_fg
->vc_num
== con
)
1394 aty128_set_par(&par
, info
);
1396 if (oldbpp
!= var
->bits_per_pixel
) {
1397 if ((err
= fb_alloc_cmap(&display
->cmap
, 0, 0)))
1399 do_install_cmap(con
, &info
->fb_info
);
1407 aty128_set_disp(struct display
*disp
,
1408 struct fb_info_aty128
*info
, int bpp
, int accel
)
1411 #ifdef FBCON_HAS_CFB8
1413 info
->dispsw
= accel
? fbcon_aty128_8
: fbcon_cfb8
;
1414 disp
->dispsw
= &info
->dispsw
;
1417 #ifdef FBCON_HAS_CFB16
1420 info
->dispsw
= accel
? fbcon_aty128_16
: fbcon_cfb16
;
1421 disp
->dispsw
= &info
->dispsw
;
1422 disp
->dispsw_data
= info
->fbcon_cmap
.cfb16
;
1425 #ifdef FBCON_HAS_CFB24
1427 info
->dispsw
= accel
? fbcon_aty128_24
: fbcon_cfb24
;
1428 disp
->dispsw
= &info
->dispsw
;
1429 disp
->dispsw_data
= info
->fbcon_cmap
.cfb24
;
1432 #ifdef FBCON_HAS_CFB32
1434 info
->dispsw
= accel
? fbcon_aty128_32
: fbcon_cfb32
;
1435 disp
->dispsw
= &info
->dispsw
;
1436 disp
->dispsw_data
= info
->fbcon_cmap
.cfb32
;
1440 disp
->dispsw
= &fbcon_dummy
;
1446 aty128_encode_fix(struct fb_fix_screeninfo
*fix
,
1447 struct aty128fb_par
*par
,
1448 const struct fb_info_aty128
*info
)
1450 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
1452 strcpy(fix
->id
, aty128fb_name
);
1454 fix
->smem_start
= (unsigned long)info
->frame_buffer_phys
;
1455 fix
->mmio_start
= (unsigned long)info
->regbase_phys
;
1457 fix
->smem_len
= info
->vram_size
;
1458 fix
->mmio_len
= 0x1fff;
1460 fix
->type
= FB_TYPE_PACKED_PIXELS
;
1462 fix
->line_length
= (par
->crtc
.vxres
* par
->crtc
.bpp
) >> 3;
1463 fix
->visual
= par
->crtc
.bpp
<= 8 ? FB_VISUAL_PSEUDOCOLOR
1464 : FB_VISUAL_DIRECTCOLOR
;
1469 fix
->accel
= FB_ACCEL_ATI_RAGE128
;
1476 * Get the Fixed Part of the Display
1479 aty128fb_get_fix(struct fb_fix_screeninfo
*fix
, int con
, struct fb_info
*fb
)
1481 const struct fb_info_aty128
*info
= (struct fb_info_aty128
*)fb
;
1482 struct aty128fb_par par
;
1485 par
= info
->default_par
;
1487 aty128_decode_var(&fb_display
[con
].var
, &par
, info
);
1489 aty128_encode_fix(fix
, &par
, info
);
1496 * Pan or Wrap the Display
1498 * Not supported (yet!)
1501 aty128fb_pan_display(struct fb_var_screeninfo
*var
, int con
,
1504 struct fb_info_aty128
*info
= (struct fb_info_aty128
*)fb
;
1505 struct aty128fb_par
*par
= &info
->current_par
;
1506 u32 xoffset
, yoffset
;
1510 xres
= (((par
->crtc
.h_total
>> 16) & 0xff) + 1) << 3;
1511 yres
= ((par
->crtc
.v_total
>> 16) & 0x7ff) + 1;
1513 xoffset
= (var
->xoffset
+7) & ~7;
1514 yoffset
= var
->yoffset
;
1516 if (xoffset
+xres
> par
->crtc
.vxres
|| yoffset
+yres
> par
->crtc
.vyres
)
1519 par
->crtc
.xoffset
= xoffset
;
1520 par
->crtc
.yoffset
= yoffset
;
1522 offset
= ((yoffset
* par
->crtc
.vxres
+ xoffset
) * par
->crtc
.bpp
) >> 6;
1524 aty_st_le32(CRTC_OFFSET
, offset
);
1535 aty128fb_get_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
1536 struct fb_info
*info
)
1539 fb_copy_cmap(&info
->cmap
, cmap
, kspc
? 0 : 2);
1541 struct fb_info_aty128 fb
= (struct fb_info_aty128
*)info
;
1543 if (con
== fb
->currcon
) /* current console? */
1544 return fb_get_cmap(cmap
, kspc
, aty128_getcolreg
, info
);
1545 else if (fb_display
[con
].cmap
.len
) /* non default colormap? */
1546 fb_copy_cmap(&fb_display
[con
].cmap
, cmap
, kspc
? 0 : 2);
1548 int size
= (fb_display
[con
].var
.bits_per_pixel
<= 8) ? 256 : 32;
1549 fb_copy_cmap(fb_default_cmap(size
), cmap
, kspc
? 0 : 2);
1561 aty128fb_set_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
1562 struct fb_info
*info
)
1565 struct fb_info_aty128
*fb
= (struct fb_info_aty128
*)info
;
1566 struct display
*disp
;
1569 disp
= &fb_display
[con
];
1573 if (!disp
->cmap
.len
) { /* no colormap allocated? */
1574 int size
= (disp
->var
.bits_per_pixel
<= 8) ? 256 : 32;
1575 if ((err
= fb_alloc_cmap(&disp
->cmap
, size
, 0)))
1579 if (con
== fb
->currcon
) /* current console? */
1580 return fb_set_cmap(cmap
, kspc
, aty128_setcolreg
, info
);
1582 fb_copy_cmap(cmap
, &disp
->cmap
, kspc
? 0 : 1);
1589 aty128fb_rasterimg(struct fb_info
*info
, int start
)
1591 struct fb_info_aty128
*fb
= (struct fb_info_aty128
*)info
;
1593 if (fb
->blitter_may_be_busy
)
1602 aty128fb_setup(char *options
)
1606 if (!options
|| !*options
)
1609 for (this_opt
= strtok(options
, ","); this_opt
;
1610 this_opt
= strtok(NULL
, ",")) {
1611 if (!strncmp(this_opt
, "font:", 5)) {
1616 for (i
= 0; i
< sizeof(fontname
) - 1; i
++)
1617 if (!*p
|| *p
== ' ' || *p
== ',')
1619 memcpy(fontname
, this_opt
+ 5, i
);
1621 } else if (!strncmp(this_opt
, "noaccel", 7)) {
1625 else if(!strncmp(this_opt
, "nomtrr", 6)) {
1630 /* vmode and cmode depreciated */
1631 else if (!strncmp(this_opt
, "vmode:", 6)) {
1632 unsigned int vmode
= simple_strtoul(this_opt
+6, NULL
, 0);
1633 if (vmode
> 0 && vmode
<= VMODE_MAX
)
1634 default_vmode
= vmode
;
1635 } else if (!strncmp(this_opt
, "cmode:", 6)) {
1636 unsigned int cmode
= simple_strtoul(this_opt
+6, NULL
, 0);
1640 default_cmode
= CMODE_8
;
1644 default_cmode
= CMODE_16
;
1648 default_cmode
= CMODE_32
;
1652 #endif /* CONFIG_PPC */
1654 mode_option
= this_opt
;
1658 #endif /* !MODULE */
1666 aty128_init(struct fb_info_aty128
*info
, const char *name
)
1668 struct fb_var_screeninfo var
;
1672 const struct aty128_chip_info
*aci
= &aty128_pci_probe_list
[0];
1673 char *video_card
= "Rage128";
1675 if (!info
->vram_size
) /* may have already been probed */
1676 info
->vram_size
= aty_ld_le32(CONFIG_MEMSIZE
) & 0x03FFFFFF;
1678 /* Get the chip revision */
1679 chip_rev
= (aty_ld_le32(CONFIG_CNTL
) >> 16) & 0x1F;
1681 /* put a name with the face */
1682 while (aci
->name
&& info
->pdev
->device
!= aci
->device
) { aci
++; }
1683 video_card
= (char *)aci
->name
;
1684 info
->chip_gen
= aci
->chip_gen
;
1686 printk(KERN_INFO
"aty128fb: %s [chip rev 0x%x] ", video_card
, chip_rev
);
1688 if (info
->vram_size
% (1024 * 1024) == 0)
1689 printk("%dM %s\n", info
->vram_size
/ (1024*1024), info
->mem
->name
);
1691 printk("%dk %s\n", info
->vram_size
/ 1024, info
->mem
->name
);
1694 strcpy(info
->fb_info
.modename
, aty128fb_name
);
1695 info
->fb_info
.node
= -1;
1696 info
->fb_info
.fbops
= &aty128fb_ops
;
1697 info
->fb_info
.disp
= &info
->disp
;
1698 strcpy(info
->fb_info
.fontname
, fontname
);
1699 info
->fb_info
.changevar
= NULL
;
1700 info
->fb_info
.switch_con
= &aty128fbcon_switch
;
1701 info
->fb_info
.updatevar
= NULL
;
1702 info
->fb_info
.blank
= &aty128fbcon_blank
;
1703 info
->fb_info
.flags
= FBINFO_FLAG_DEFAULT
;
1708 memset(&var
, 0, sizeof(var
));
1710 if (_machine
== _MACH_Pmac
) {
1712 if (!mac_find_mode(&var
, &info
->fb_info
, mode_option
, 8))
1716 if (default_vmode
== VMODE_NVRAM
)
1717 default_vmode
= nvram_read_byte(NV_VMODE
);
1719 if (default_cmode
== CMODE_NVRAM
)
1720 default_cmode
= nvram_read_byte(NV_CMODE
);
1722 if (default_vmode
<= 0 || default_vmode
> VMODE_MAX
)
1723 default_vmode
= VMODE_640_480_60
;
1725 if (default_cmode
< CMODE_8
|| default_cmode
> CMODE_32
)
1726 default_cmode
= CMODE_8
;
1728 if (mac_vmode_to_var(default_vmode
, default_cmode
, &var
))
1732 #endif /* CONFIG_PPC */
1734 if (fb_find_mode(&var
, &info
->fb_info
, mode_option
, NULL
, 0,
1735 &defaultmode
, 8) == 0)
1741 var
.accel_flags
&= ~FB_ACCELF_TEXT
;
1743 var
.accel_flags
|= FB_ACCELF_TEXT
;
1745 if (aty128_decode_var(&var
, &info
->default_par
, info
)) {
1746 printk(KERN_ERR
"aty128fb: Cannot set default mode.\n");
1750 /* load up the palette with default colors */
1751 for (j
= 0; j
< 16; j
++) {
1753 info
->palette
[j
].red
= default_red
[k
];
1754 info
->palette
[j
].green
= default_grn
[k
];
1755 info
->palette
[j
].blue
= default_blu
[k
];
1758 /* setup the DAC the way we like it */
1759 dac
= aty_ld_le32(DAC_CNTL
);
1760 dac
|= (DAC_8BIT_EN
| DAC_RANGE_CNTL
);
1762 aty_st_le32(DAC_CNTL
, dac
);
1764 /* turn off bus mastering, just in case */
1765 aty_st_le32(BUS_CNTL
, aty_ld_le32(BUS_CNTL
) | BUS_MASTER_DIS
);
1767 aty128fb_set_var(&var
, -1, &info
->fb_info
);
1768 aty128_init_engine(&info
->default_par
, info
);
1770 board_list
= aty128_board_list_add(board_list
, info
);
1772 if (register_framebuffer(&info
->fb_info
) < 0)
1775 printk(KERN_INFO
"fb%d: %s frame buffer device on %s\n",
1776 GET_FB_IDX(info
->fb_info
.node
), aty128fb_name
, name
);
1778 return 1; /* success! */
1782 /* add a new card to the list ++ajoshi */
1784 fb_info_aty128
*aty128_board_list_add(struct fb_info_aty128
*board_list
,
1785 struct fb_info_aty128
*new_node
)
1787 struct fb_info_aty128
*i_p
= board_list
;
1789 new_node
->next
= NULL
;
1790 if(board_list
== NULL
)
1792 while(i_p
->next
!= NULL
)
1794 i_p
->next
= new_node
;
1804 struct pci_dev
*pdev
= NULL
;
1805 const struct aty128_chip_info
*aci
= &aty128_pci_probe_list
[0];
1807 while (aci
->name
!= NULL
) {
1808 pdev
= pci_find_device(PCI_VENDOR_ID_ATI
, aci
->device
, pdev
);
1809 while (pdev
!= NULL
) {
1810 if (aty128_pci_register(pdev
, aci
) == 0)
1812 pdev
= pci_find_device(PCI_VENDOR_ID_ATI
, aci
->device
, pdev
);
1823 /* register a card ++ajoshi */
1825 aty128_pci_register(struct pci_dev
*pdev
,
1826 const struct aty128_chip_info
*aci
)
1828 struct fb_info_aty128
*info
= NULL
;
1829 u32 fb_addr
, reg_addr
;
1831 #if !defined(CONFIG_PPC) && !defined(__sparc__)
1832 char *bios_seg
= NULL
;
1835 /* Enable device in PCI config */
1836 if ((err
= pci_enable_device(pdev
))) {
1837 printk(KERN_ERR
"aty128fb: Cannot enable PCI device: %d\n",
1842 fb_addr
= pci_resource_start(pdev
, 0);
1843 if (!request_mem_region(fb_addr
, pci_resource_len(pdev
, 0),
1845 printk(KERN_ERR
"aty128fb: cannot reserve frame "
1850 reg_addr
= pci_resource_start(pdev
, 2);
1851 if (!request_mem_region(reg_addr
, pci_resource_len(pdev
, 2),
1853 printk(KERN_ERR
"aty128fb: cannot reserve MMIO region\n");
1857 /* We have the resources. Now virtualize them */
1858 if (!(info
= kmalloc(sizeof(struct fb_info_aty128
), GFP_ATOMIC
))) {
1859 printk(KERN_ERR
"aty128fb: can't alloc fb_info_aty128\n");
1862 memset(info
, 0, sizeof(struct fb_info_aty128
));
1864 /* Copy PCI device info into info->pdev */
1869 /* Virtualize mmio region */
1870 info
->regbase_phys
= reg_addr
;
1871 info
->regbase
= ioremap(reg_addr
, 0x1FFF);
1876 /* Grab memory size from the card */
1877 info
->vram_size
= aty_ld_le32(CONFIG_MEMSIZE
) & 0x03FFFFFF;
1879 /* Virtualize the framebuffer */
1880 info
->frame_buffer_phys
= fb_addr
;
1881 info
->frame_buffer
= (u32
)ioremap(fb_addr
, info
->vram_size
);
1883 if (!info
->frame_buffer
) {
1884 iounmap((void *)info
->regbase
);
1888 /* If we can't test scratch registers, something is seriously wrong */
1889 if (!register_test(info
)) {
1890 printk(KERN_ERR
"aty128fb: Can't write to video register!\n");
1894 #if !defined(CONFIG_PPC) && !defined(__sparc__)
1895 if (!(bios_seg
= aty128find_ROM(info
)))
1896 printk(KERN_INFO
"aty128fb: Rage128 BIOS not located. "
1899 printk(KERN_INFO
"aty128fb: Rage128 BIOS located at "
1900 "segment %4.4X\n", (unsigned int)bios_seg
);
1901 aty128_get_pllinfo(info
, bios_seg
);
1904 aty128_timings(info
);
1906 if (!aty128_init(info
, "PCI"))
1911 info
->mtrr
.vram
= mtrr_add(info
->frame_buffer_phys
,
1912 info
->vram_size
, MTRR_TYPE_WRCOMB
, 1);
1913 info
->mtrr
.vram_valid
= 1;
1914 /* let there be speed */
1915 printk(KERN_INFO
"aty128fb: Rage128 MTRR set to ON\n");
1917 #endif /* CONFIG_MTRR */
1922 iounmap((void *)info
->frame_buffer
);
1923 iounmap((void *)info
->regbase
);
1927 release_mem_region(pci_resource_start(pdev
, 2),
1928 pci_resource_len(pdev
, 2));
1930 release_mem_region(pci_resource_start(pdev
, 0),
1931 pci_resource_len(pdev
, 0));
1933 release_mem_region(pci_resource_start(pdev
, 1),
1934 pci_resource_len(pdev
, 1));
1937 #endif /* CONFIG_PCI */
1940 /* PPC and Sparc cannot read video ROM */
1941 #if !defined(CONFIG_PPC) && !defined(__sparc__)
1943 *aty128find_ROM(struct fb_info_aty128
*info
)
1950 char aty_rom_sig
[] = "761295520"; /* ATI ROM Signature */
1951 char R128_sig
[] = "R128"; /* Rage128 ROM identifier */
1953 for (segstart
=0x000c0000; segstart
<0x000f0000; segstart
+=0x00001000) {
1956 rom_base
= (char *)ioremap(segstart
, 0x1000);
1958 if ((*rom_base
== 0x55) && (((*(rom_base
+ 1)) & 0xff) == 0xaa))
1967 for (i
= 0; (i
< 128 - strlen(aty_rom_sig
)) && (stage
!= 3); i
++) {
1968 if (aty_rom_sig
[0] == *rom
)
1969 if (strncmp(aty_rom_sig
, rom
,
1970 strlen(aty_rom_sig
)) == 0)
1980 /* ATI signature found. Let's see if it's a Rage128 */
1981 for (i
= 0; (i
< 512) && (stage
!= 4); i
++) {
1982 if (R128_sig
[0] == *rom
)
1983 if (strncmp(R128_sig
, rom
,
1984 strlen(R128_sig
)) == 0)
2001 aty128_get_pllinfo(struct fb_info_aty128
*info
, char *bios_seg
)
2005 u16 bios_header_offset
, pll_info_offset
;
2008 bios_header
= bios_seg
+ 0x48L
;
2009 header_ptr
= bios_header
;
2011 bios_header_offset
= readw(header_ptr
);
2012 bios_header
= bios_seg
+ bios_header_offset
;
2013 bios_header
+= 0x30;
2015 header_ptr
= bios_header
;
2016 pll_info_offset
= readw(header_ptr
);
2017 header_ptr
= bios_seg
+ pll_info_offset
;
2019 memcpy_fromio(&pll
, header_ptr
, 50);
2021 info
->constants
.ppll_max
= pll
.PCLK_max_freq
;
2022 info
->constants
.ppll_min
= pll
.PCLK_min_freq
;
2023 info
->constants
.xclk
= (u32
)pll
.XCLK
;
2024 info
->constants
.ref_divider
= (u32
)pll
.PCLK_ref_divider
;
2025 info
->constants
.dotclock
= (u32
)pll
.PCLK_ref_freq
;
2027 DBG("ppll_max %d ppll_min %d xclk %d ref_divider %d dotclock %d\n",
2028 info
->constants
.ppll_max
, info
->constants
.ppll_min
,
2029 info
->constants
.xclk
, info
->constants
.ref_divider
,
2030 info
->constants
.dotclock
);
2033 #endif /* !CONFIG_PPC */
2036 /* fill in known card constants if pll_block is not available */
2038 aty128_timings(struct fb_info_aty128
*info
)
2041 /* instead of a table lookup, assume OF has properly
2042 * setup the PLL registers and use their values
2043 * to set the XCLK values and reference divider values */
2045 u32 x_mpll_ref_fb_div
;
2048 unsigned PostDivSet
[] =
2049 { 0, 1, 2, 4, 8, 3, 6, 12 };
2052 if (!info
->constants
.dotclock
)
2053 info
->constants
.dotclock
= 2950;
2056 x_mpll_ref_fb_div
= aty_ld_pll(X_MPLL_REF_FB_DIV
);
2057 xclk_cntl
= aty_ld_pll(XCLK_CNTL
) & 0x7;
2058 Nx
= (x_mpll_ref_fb_div
& 0x00ff00) >> 8;
2059 M
= x_mpll_ref_fb_div
& 0x0000ff;
2061 info
->constants
.xclk
= round_div((2 * Nx
*
2062 info
->constants
.dotclock
), (M
* PostDivSet
[xclk_cntl
]));
2064 info
->constants
.ref_divider
=
2065 aty_ld_pll(PPLL_REF_DIV
) & PPLL_REF_DIV_MASK
;
2068 if (!info
->constants
.ref_divider
) {
2069 info
->constants
.ref_divider
= 0x3b;
2071 aty_st_pll(X_MPLL_REF_FB_DIV
, 0x004c4c1e);
2072 aty_pll_writeupdate(info
);
2074 aty_st_pll(PPLL_REF_DIV
, info
->constants
.ref_divider
);
2075 aty_pll_writeupdate(info
);
2077 /* from documentation */
2078 if (!info
->constants
.ppll_min
)
2079 info
->constants
.ppll_min
= 12500;
2080 if (!info
->constants
.ppll_max
)
2081 info
->constants
.ppll_max
= 25000; /* 23000 on some cards? */
2082 if (!info
->constants
.xclk
)
2083 info
->constants
.xclk
= 0x1d4d; /* same as mclk */
2085 info
->constants
.fifo_width
= 128;
2086 info
->constants
.fifo_depth
= 32;
2088 switch (aty_ld_le32(MEM_CNTL
) & 0x3) {
2090 info
->mem
= &sdr_128
;
2093 info
->mem
= &sdr_sgram
;
2096 info
->mem
= &ddr_sgram
;
2099 info
->mem
= &sdr_sgram
;
2105 aty128fbcon_switch(int con
, struct fb_info
*fb
)
2107 struct fb_info_aty128
*info
= (struct fb_info_aty128
*)fb
;
2108 struct aty128fb_par par
;
2110 /* Do we have to save the colormap? */
2111 if (fb_display
[info
->currcon
].cmap
.len
)
2112 fb_get_cmap(&fb_display
[info
->currcon
].cmap
, 1,
2113 aty128_getcolreg
, fb
);
2115 /* set the current console */
2116 info
->currcon
= con
;
2118 aty128_decode_var(&fb_display
[con
].var
, &par
, info
);
2119 aty128_set_par(&par
, info
);
2121 aty128_set_disp(&fb_display
[con
], info
, par
.crtc
.bpp
,
2122 par
.accel_flags
& FB_ACCELF_TEXT
);
2124 do_install_cmap(con
, fb
);
2131 * Blank the display.
2134 aty128fbcon_blank(int blank
, struct fb_info
*fb
)
2136 struct fb_info_aty128
*info
= (struct fb_info_aty128
*)fb
;
2139 if (blank
& VESA_VSYNC_SUSPEND
)
2141 if (blank
& VESA_HSYNC_SUSPEND
)
2143 if (blank
& VESA_POWERDOWN
)
2146 aty_st_8(CRTC_EXT_CNTL
+1, state
);
2151 * Read a single color register and split it into
2152 * colors/transparent. Return != 0 for invalid regno.
2155 aty128_getcolreg(u_int regno
, u_int
*red
, u_int
*green
, u_int
*blue
,
2156 u_int
*transp
, struct fb_info
*fb
)
2158 struct fb_info_aty128
*info
= (struct fb_info_aty128
*) fb
;
2163 *red
= (info
->palette
[regno
].red
<<8) | info
->palette
[regno
].red
;
2164 *green
= (info
->palette
[regno
].green
<<8) | info
->palette
[regno
].green
;
2165 *blue
= (info
->palette
[regno
].blue
<<8) | info
->palette
[regno
].blue
;
2172 * Set a single color register. The values supplied are already
2173 * rounded down to the hardware's capabilities (according to the
2174 * entries in the var structure). Return != 0 for invalid regno.
2177 aty128_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
2178 u_int transp
, struct fb_info
*fb
)
2180 struct fb_info_aty128
*info
= (struct fb_info_aty128
*)fb
;
2189 info
->palette
[regno
].red
= red
;
2190 info
->palette
[regno
].green
= green
;
2191 info
->palette
[regno
].blue
= blue
;
2193 /* Note: For now, on M3, we set palette on both heads, which may
2194 * be useless. Can someone with a M3 check this ? */
2196 /* initialize gamma ramp for hi-color+ */
2198 if ((info
->current_par
.crtc
.bpp
> 8) && (regno
== 0)) {
2201 if (info
->chip_gen
== rage_M3
)
2202 aty_st_le32(DAC_CNTL
, aty_ld_le32(DAC_CNTL
) & ~PALETTE_ACCESS_CNTL
);
2204 for (i
=16; i
<256; i
++) {
2205 aty_st_8(PALETTE_INDEX
, i
);
2206 col
= (i
<< 16) | (i
<< 8) | i
;
2207 aty_st_le32(PALETTE_DATA
, col
);
2210 if (info
->chip_gen
== rage_M3
) {
2211 aty_st_le32(DAC_CNTL
, aty_ld_le32(DAC_CNTL
) | PALETTE_ACCESS_CNTL
);
2213 for (i
=16; i
<256; i
++) {
2214 aty_st_8(PALETTE_INDEX
, i
);
2215 col
= (i
<< 16) | (i
<< 8) | i
;
2216 aty_st_le32(PALETTE_DATA
, col
);
2221 /* initialize palette */
2223 if (info
->chip_gen
== rage_M3
)
2224 aty_st_le32(DAC_CNTL
, aty_ld_le32(DAC_CNTL
) & ~PALETTE_ACCESS_CNTL
);
2226 if (info
->current_par
.crtc
.bpp
== 16)
2227 aty_st_8(PALETTE_INDEX
, (regno
<< 3));
2229 aty_st_8(PALETTE_INDEX
, regno
);
2230 col
= (red
<< 16) | (green
<< 8) | blue
;
2231 aty_st_le32(PALETTE_DATA
, col
);
2232 if (info
->chip_gen
== rage_M3
) {
2233 aty_st_le32(DAC_CNTL
, aty_ld_le32(DAC_CNTL
) | PALETTE_ACCESS_CNTL
);
2234 if (info
->current_par
.crtc
.bpp
== 16)
2235 aty_st_8(PALETTE_INDEX
, (regno
<< 3));
2237 aty_st_8(PALETTE_INDEX
, regno
);
2238 aty_st_le32(PALETTE_DATA
, col
);
2242 switch (info
->current_par
.crtc
.bpp
) {
2243 #ifdef FBCON_HAS_CFB16
2245 info
->fbcon_cmap
.cfb16
[regno
] = (regno
<< 10) | (regno
<< 5) |
2249 #ifdef FBCON_HAS_CFB24
2251 info
->fbcon_cmap
.cfb24
[regno
] = (regno
<< 16) | (regno
<< 8) |
2255 #ifdef FBCON_HAS_CFB32
2259 i
= (regno
<< 8) | regno
;
2260 info
->fbcon_cmap
.cfb32
[regno
] = (i
<< 16) | i
;
2270 do_install_cmap(int con
, struct fb_info
*info
)
2272 struct fb_info_aty128
*fb
= (struct fb_info_aty128
*)info
;
2274 if (con
!= fb
->currcon
)
2277 if (fb_display
[con
].cmap
.len
)
2278 fb_set_cmap(&fb_display
[con
].cmap
, 1, aty128_setcolreg
, info
);
2280 int size
= (fb_display
[con
].var
.bits_per_pixel
<= 8) ? 256 : 16;
2281 fb_set_cmap(fb_default_cmap(size
), 1, aty128_setcolreg
, info
);
2287 * Accelerated functions
2291 aty128_rectcopy(int srcx
, int srcy
, int dstx
, int dsty
,
2292 u_int width
, u_int height
,
2293 struct fb_info_aty128
*info
)
2295 u32 save_dp_datatype
, save_dp_cntl
, bppval
;
2297 if (!width
|| !height
)
2300 bppval
= bpp_to_depth(info
->current_par
.crtc
.bpp
);
2301 if (bppval
== DST_24BPP
) {
2305 } else if (bppval
== -EINVAL
) {
2306 printk("aty128fb: invalid depth\n");
2310 wait_for_fifo(2, info
);
2311 save_dp_datatype
= aty_ld_le32(DP_DATATYPE
);
2312 save_dp_cntl
= aty_ld_le32(DP_CNTL
);
2314 wait_for_fifo(6, info
);
2315 aty_st_le32(SRC_Y_X
, (srcy
<< 16) | srcx
);
2316 aty_st_le32(DP_MIX
, ROP3_SRCCOPY
| DP_SRC_RECT
);
2317 aty_st_le32(DP_CNTL
, DST_X_LEFT_TO_RIGHT
| DST_Y_TOP_TO_BOTTOM
);
2318 aty_st_le32(DP_DATATYPE
, save_dp_datatype
| bppval
| SRC_DSTCOLOR
);
2320 aty_st_le32(DST_Y_X
, (dsty
<< 16) | dstx
);
2321 aty_st_le32(DST_HEIGHT_WIDTH
, (height
<< 16) | width
);
2323 info
->blitter_may_be_busy
= 1;
2325 wait_for_fifo(2, info
);
2326 aty_st_le32(DP_DATATYPE
, save_dp_datatype
);
2327 aty_st_le32(DP_CNTL
, save_dp_cntl
);
2332 * Text mode accelerated functions
2336 fbcon_aty128_bmove(struct display
*p
, int sy
, int sx
, int dy
, int dx
,
2337 int height
, int width
)
2340 sy
*= fontheight(p
);
2342 dy
*= fontheight(p
);
2343 width
*= fontwidth(p
);
2344 height
*= fontheight(p
);
2346 aty128_rectcopy(sx
, sy
, dx
, dy
, width
, height
,
2347 (struct fb_info_aty128
*)p
->fb_info
);
2351 #ifdef FBCON_HAS_CFB8
2352 static void fbcon_aty8_putc(struct vc_data
*conp
, struct display
*p
,
2353 int c
, int yy
, int xx
)
2355 struct fb_info_aty128
*fb
= (struct fb_info_aty128
*)(p
->fb_info
);
2357 if (fb
->blitter_may_be_busy
)
2360 fbcon_cfb8_putc(conp
, p
, c
, yy
, xx
);
2364 static void fbcon_aty8_putcs(struct vc_data
*conp
, struct display
*p
,
2365 const unsigned short *s
, int count
,
2368 struct fb_info_aty128
*fb
= (struct fb_info_aty128
*)(p
->fb_info
);
2370 if (fb
->blitter_may_be_busy
)
2373 fbcon_cfb8_putcs(conp
, p
, s
, count
, yy
, xx
);
2377 static void fbcon_aty8_clear_margins(struct vc_data
*conp
,
2378 struct display
*p
, int bottom_only
)
2380 struct fb_info_aty128
*fb
= (struct fb_info_aty128
*)(p
->fb_info
);
2382 if (fb
->blitter_may_be_busy
)
2385 fbcon_cfb8_clear_margins(conp
, p
, bottom_only
);
2388 static struct display_switch fbcon_aty128_8
= {
2389 setup
: fbcon_cfb8_setup
,
2390 bmove
: fbcon_aty128_bmove
,
2391 clear
: fbcon_cfb8_clear
,
2392 putc
: fbcon_aty8_putc
,
2393 putcs
: fbcon_aty8_putcs
,
2394 revc
: fbcon_cfb8_revc
,
2395 clear_margins
: fbcon_aty8_clear_margins
,
2396 fontwidthmask
: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
2399 #ifdef FBCON_HAS_CFB16
2400 static void fbcon_aty16_putc(struct vc_data
*conp
, struct display
*p
,
2401 int c
, int yy
, int xx
)
2403 struct fb_info_aty128
*fb
= (struct fb_info_aty128
*)(p
->fb_info
);
2405 if (fb
->blitter_may_be_busy
)
2408 fbcon_cfb16_putc(conp
, p
, c
, yy
, xx
);
2412 static void fbcon_aty16_putcs(struct vc_data
*conp
, struct display
*p
,
2413 const unsigned short *s
, int count
,
2416 struct fb_info_aty128
*fb
= (struct fb_info_aty128
*)(p
->fb_info
);
2418 if (fb
->blitter_may_be_busy
)
2421 fbcon_cfb16_putcs(conp
, p
, s
, count
, yy
, xx
);
2425 static void fbcon_aty16_clear_margins(struct vc_data
*conp
,
2426 struct display
*p
, int bottom_only
)
2428 struct fb_info_aty128
*fb
= (struct fb_info_aty128
*)(p
->fb_info
);
2430 if (fb
->blitter_may_be_busy
)
2433 fbcon_cfb16_clear_margins(conp
, p
, bottom_only
);
2436 static struct display_switch fbcon_aty128_16
= {
2437 setup
: fbcon_cfb16_setup
,
2438 bmove
: fbcon_aty128_bmove
,
2439 clear
: fbcon_cfb16_clear
,
2440 putc
: fbcon_aty16_putc
,
2441 putcs
: fbcon_aty16_putcs
,
2442 revc
: fbcon_cfb16_revc
,
2443 clear_margins
: fbcon_aty16_clear_margins
,
2444 fontwidthmask
: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
2447 #ifdef FBCON_HAS_CFB24
2448 static void fbcon_aty24_putc(struct vc_data
*conp
, struct display
*p
,
2449 int c
, int yy
, int xx
)
2451 struct fb_info_aty128
*fb
= (struct fb_info_aty128
*)(p
->fb_info
);
2453 if (fb
->blitter_may_be_busy
)
2456 fbcon_cfb24_putc(conp
, p
, c
, yy
, xx
);
2460 static void fbcon_aty24_putcs(struct vc_data
*conp
, struct display
*p
,
2461 const unsigned short *s
, int count
,
2464 struct fb_info_aty128
*fb
= (struct fb_info_aty128
*)(p
->fb_info
);
2466 if (fb
->blitter_may_be_busy
)
2469 fbcon_cfb24_putcs(conp
, p
, s
, count
, yy
, xx
);
2473 static void fbcon_aty24_clear_margins(struct vc_data
*conp
,
2474 struct display
*p
, int bottom_only
)
2476 struct fb_info_aty128
*fb
= (struct fb_info_aty128
*)(p
->fb_info
);
2478 if (fb
->blitter_may_be_busy
)
2481 fbcon_cfb24_clear_margins(conp
, p
, bottom_only
);
2484 static struct display_switch fbcon_aty128_24
= {
2485 setup
: fbcon_cfb24_setup
,
2486 bmove
: fbcon_aty128_bmove
,
2487 clear
: fbcon_cfb24_clear
,
2488 putc
: fbcon_aty24_putc
,
2489 putcs
: fbcon_aty24_putcs
,
2490 revc
: fbcon_cfb24_revc
,
2491 clear_margins
: fbcon_aty24_clear_margins
,
2492 fontwidthmask
: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
2495 #ifdef FBCON_HAS_CFB32
2496 static void fbcon_aty32_putc(struct vc_data
*conp
, struct display
*p
,
2497 int c
, int yy
, int xx
)
2499 struct fb_info_aty128
*fb
= (struct fb_info_aty128
*)(p
->fb_info
);
2501 if (fb
->blitter_may_be_busy
)
2504 fbcon_cfb32_putc(conp
, p
, c
, yy
, xx
);
2508 static void fbcon_aty32_putcs(struct vc_data
*conp
, struct display
*p
,
2509 const unsigned short *s
, int count
,
2512 struct fb_info_aty128
*fb
= (struct fb_info_aty128
*)(p
->fb_info
);
2514 if (fb
->blitter_may_be_busy
)
2517 fbcon_cfb32_putcs(conp
, p
, s
, count
, yy
, xx
);
2521 static void fbcon_aty32_clear_margins(struct vc_data
*conp
,
2522 struct display
*p
, int bottom_only
)
2524 struct fb_info_aty128
*fb
= (struct fb_info_aty128
*)(p
->fb_info
);
2526 if (fb
->blitter_may_be_busy
)
2529 fbcon_cfb32_clear_margins(conp
, p
, bottom_only
);
2532 static struct display_switch fbcon_aty128_32
= {
2533 setup
: fbcon_cfb32_setup
,
2534 bmove
: fbcon_aty128_bmove
,
2535 clear
: fbcon_cfb32_clear
,
2536 putc
: fbcon_aty32_putc
,
2537 putcs
: fbcon_aty32_putcs
,
2538 revc
: fbcon_cfb32_revc
,
2539 clear_margins
: fbcon_aty32_clear_margins
,
2540 fontwidthmask
: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
2545 MODULE_AUTHOR("(c)1999-2000 Brad Douglas <brad@neruo.com>");
2546 MODULE_DESCRIPTION("FBDev driver for ATI Rage128 / Pro cards");
2556 cleanup_module(void)
2558 struct fb_info_aty128
*info
= board_list
;
2560 while (board_list
) {
2562 board_list
= board_list
->next
;
2564 unregister_framebuffer(&info
->fb_info
);
2566 if (info
->mtrr
.vram_valid
)
2567 mtrr_del(info
->mtrr
.vram
, info
->frame_buffer_phys
,
2569 #endif /* CONFIG_MTRR */
2570 iounmap(info
->regbase
);
2571 iounmap(&info
->frame_buffer
);
2573 release_mem_region(pci_resource_start(info
->pdev
, 0),
2574 pci_resource_len(info
->pdev
, 0));
2575 release_mem_region(pci_resource_start(info
->pdev
, 1),
2576 pci_resource_len(info
->pdev
, 1));
2577 release_mem_region(pci_resource_start(info
->pdev
, 2),
2578 pci_resource_len(info
->pdev
, 2));