2 * ATI Frame Buffer Device Driver Core
4 * Copyright (C) 2004 Alex Kern <alex.kern@gmx.de>
5 * Copyright (C) 1997-2001 Geert Uytterhoeven
6 * Copyright (C) 1998 Bernd Harries
7 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
9 * This driver supports the following ATI graphics chips:
12 * To do: add support for
13 * - ATI Rage128 (from aty128fb.c)
14 * - ATI Radeon (from radeonfb.c)
16 * This driver is partly based on the PowerMac console driver:
18 * Copyright (C) 1996 Paul Mackerras
20 * and on the PowerMac ATI/mach64 display driver:
22 * Copyright (C) 1997 Michael AK Tesch
24 * with work by Jon Howell
26 * Anthony Tong <atong@uiuc.edu>
28 * Generic LCD support written by Daniel Mantione, ported from 2.4.20 by Alex Kern
29 * Many Thanks to Ville Syrjälä for patches and fixing nasting 16 bit color bug.
31 * This file is subject to the terms and conditions of the GNU General Public
32 * License. See the file COPYING in the main directory of this archive for
35 * Many thanks to Nitya from ATI devrel for support and patience !
38 /******************************************************************************
42 - cursor support on all cards and all ramdacs.
43 - cursor parameters controlable via ioctl()s.
44 - guess PLL and MCLK based on the original PLL register values initialized
45 by Open Firmware (if they are initialized). BIOS is done
47 (Anyone with Mac to help with this?)
49 ******************************************************************************/
51 #include <linux/aperture.h>
52 #include <linux/compat.h>
53 #include <linux/module.h>
54 #include <linux/moduleparam.h>
55 #include <linux/kernel.h>
56 #include <linux/errno.h>
57 #include <linux/string.h>
59 #include <linux/slab.h>
60 #include <linux/vmalloc.h>
61 #include <linux/delay.h>
62 #include <linux/compiler.h>
63 #include <linux/console.h>
65 #include <linux/init.h>
66 #include <linux/pci.h>
67 #include <linux/interrupt.h>
68 #include <linux/spinlock.h>
69 #include <linux/wait.h>
70 #include <linux/backlight.h>
71 #include <linux/reboot.h>
72 #include <linux/dmi.h>
75 #include <linux/uaccess.h>
77 #include <video/mach64.h>
82 #include <asm/machdep.h>
83 #include "../macmodes.h"
87 #include <asm/oplib.h>
92 #include <linux/adb.h>
93 #include <linux/pmu.h>
95 #ifdef CONFIG_BOOTX_TEXT
96 #include <asm/btext.h>
98 #ifdef CONFIG_PMAC_BACKLIGHT
99 #include <asm/backlight.h>
108 /* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */
109 /* - must be large enough to catch all GUI-Regs */
110 /* - must be aligned to a PAGE boundary */
111 #define GUI_RESERVE (1 * PAGE_SIZE)
113 /* FIXME: remove the FAIL definition */
114 #define FAIL(msg) do { \
115 if (!(var->activate & FB_ACTIVATE_TEST)) \
116 printk(KERN_CRIT "atyfb: " msg "\n"); \
119 #define FAIL_MAX(msg, x, _max_) do { \
121 if (!(var->activate & FB_ACTIVATE_TEST)) \
122 printk(KERN_CRIT "atyfb: " msg " %x(%x)\n", x, _max_); \
127 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "atyfb: " fmt, ## args)
129 #define DPRINTK(fmt, args...) no_printk(fmt, ##args)
132 #define PRINTKI(fmt, args...) printk(KERN_INFO "atyfb: " fmt, ## args)
133 #define PRINTKE(fmt, args...) printk(KERN_ERR "atyfb: " fmt, ## args)
135 #if defined(CONFIG_PMAC_BACKLIGHT) || defined(CONFIG_FB_ATY_GENERIC_LCD) || \
136 defined(CONFIG_FB_ATY_BACKLIGHT) || defined (CONFIG_PPC_PMAC)
137 static const u32 lt_lcd_regs
[] = {
144 0, /* EXT_VERT_STRETCH */
149 void aty_st_lcd(int index
, u32 val
, const struct atyfb_par
*par
)
151 if (M64_HAS(LT_LCD_REGS
)) {
152 aty_st_le32(lt_lcd_regs
[index
], val
, par
);
156 /* write addr byte */
157 temp
= aty_ld_le32(LCD_INDEX
, par
);
158 aty_st_le32(LCD_INDEX
, (temp
& ~LCD_INDEX_MASK
) | index
, par
);
159 /* write the register value */
160 aty_st_le32(LCD_DATA
, val
, par
);
164 u32
aty_ld_lcd(int index
, const struct atyfb_par
*par
)
166 if (M64_HAS(LT_LCD_REGS
)) {
167 return aty_ld_le32(lt_lcd_regs
[index
], par
);
171 /* write addr byte */
172 temp
= aty_ld_le32(LCD_INDEX
, par
);
173 aty_st_le32(LCD_INDEX
, (temp
& ~LCD_INDEX_MASK
) | index
, par
);
174 /* read the register value */
175 return aty_ld_le32(LCD_DATA
, par
);
178 #else /* defined(CONFIG_PMAC_BACKLIGHT) || defined(CONFIG_FB_ATY_BACKLIGHT) ||
179 defined(CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_PPC_PMAC) */
180 void aty_st_lcd(int index
, u32 val
, const struct atyfb_par
*par
)
183 u32
aty_ld_lcd(int index
, const struct atyfb_par
*par
)
187 #endif /* defined(CONFIG_PMAC_BACKLIGHT) || defined(CONFIG_FB_ATY_BACKLIGHT) ||
188 defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_PPC_PMAC) */
190 #ifdef CONFIG_FB_ATY_GENERIC_LCD
194 * Reduce a fraction by factoring out the largest common divider of the
195 * fraction's numerator and denominator.
197 static void ATIReduceRatio(int *Numerator
, int *Denominator
)
199 int Multiplier
, Divider
, Remainder
;
201 Multiplier
= *Numerator
;
202 Divider
= *Denominator
;
204 while ((Remainder
= Multiplier
% Divider
)) {
205 Multiplier
= Divider
;
209 *Numerator
/= Divider
;
210 *Denominator
/= Divider
;
214 * The Hardware parameters for each card
217 struct pci_mmap_map
{
221 unsigned long prot_flag
;
222 unsigned long prot_mask
;
225 static const struct fb_fix_screeninfo atyfb_fix
= {
227 .type
= FB_TYPE_PACKED_PIXELS
,
228 .visual
= FB_VISUAL_PSEUDOCOLOR
,
234 * Frame buffer device API
237 static int atyfb_open(struct fb_info
*info
, int user
);
238 static int atyfb_release(struct fb_info
*info
, int user
);
239 static int atyfb_check_var(struct fb_var_screeninfo
*var
,
240 struct fb_info
*info
);
241 static int atyfb_set_par(struct fb_info
*info
);
242 static int atyfb_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
243 u_int transp
, struct fb_info
*info
);
244 static int atyfb_pan_display(struct fb_var_screeninfo
*var
,
245 struct fb_info
*info
);
246 static int atyfb_blank(int blank
, struct fb_info
*info
);
247 static int atyfb_ioctl(struct fb_info
*info
, u_int cmd
, u_long arg
);
249 static int atyfb_compat_ioctl(struct fb_info
*info
, u_int cmd
, u_long arg
)
251 return atyfb_ioctl(info
, cmd
, (u_long
)compat_ptr(arg
));
256 static int atyfb_mmap(struct fb_info
*info
, struct vm_area_struct
*vma
);
258 static int atyfb_sync(struct fb_info
*info
);
264 static int aty_init(struct fb_info
*info
);
266 static void aty_get_crtc(const struct atyfb_par
*par
, struct crtc
*crtc
);
268 static void aty_set_crtc(const struct atyfb_par
*par
, const struct crtc
*crtc
);
269 static int aty_var_to_crtc(const struct fb_info
*info
,
270 const struct fb_var_screeninfo
*var
,
272 static int aty_crtc_to_var(const struct crtc
*crtc
,
273 struct fb_var_screeninfo
*var
);
274 static void set_off_pitch(struct atyfb_par
*par
, const struct fb_info
*info
);
276 static int read_aty_sense(const struct atyfb_par
*par
);
279 static DEFINE_MUTEX(reboot_lock
);
280 static struct fb_info
*reboot_info
;
283 * Interface used by the world
286 static struct fb_var_screeninfo default_var
= {
287 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
288 640, 480, 640, 480, 0, 0, 8, 0,
289 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
290 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
291 0, FB_VMODE_NONINTERLACED
294 static const struct fb_videomode defmode
= {
295 /* 640x480 @ 60 Hz, 31.5 kHz hsync */
296 NULL
, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
297 0, FB_VMODE_NONINTERLACED
300 static struct fb_ops atyfb_ops
= {
301 .owner
= THIS_MODULE
,
302 .fb_open
= atyfb_open
,
303 .fb_release
= atyfb_release
,
304 __FB_DEFAULT_IOMEM_OPS_RDWR
,
305 .fb_check_var
= atyfb_check_var
,
306 .fb_set_par
= atyfb_set_par
,
307 .fb_setcolreg
= atyfb_setcolreg
,
308 .fb_pan_display
= atyfb_pan_display
,
309 .fb_blank
= atyfb_blank
,
310 .fb_ioctl
= atyfb_ioctl
,
312 .fb_compat_ioctl
= atyfb_compat_ioctl
,
314 .fb_fillrect
= atyfb_fillrect
,
315 .fb_copyarea
= atyfb_copyarea
,
316 .fb_imageblit
= atyfb_imageblit
,
318 .fb_mmap
= atyfb_mmap
,
320 __FB_DEFAULT_IOMEM_OPS_MMAP
,
322 .fb_sync
= atyfb_sync
,
331 static int comp_sync
= -1;
333 static int backlight
= IS_BUILTIN(CONFIG_PMAC_BACKLIGHT
);
336 static int default_vmode
= VMODE_CHOOSE
;
337 static int default_cmode
= CMODE_CHOOSE
;
339 module_param_named(vmode
, default_vmode
, int, 0);
340 MODULE_PARM_DESC(vmode
, "int: video mode for mac");
341 module_param_named(cmode
, default_cmode
, int, 0);
342 MODULE_PARM_DESC(cmode
, "int: color mode for mac");
346 static unsigned int mach64_count
= 0;
347 static unsigned long phys_vmembase
[FB_MAX
] = { 0, };
348 static unsigned long phys_size
[FB_MAX
] = { 0, };
349 static unsigned long phys_guiregbase
[FB_MAX
] = { 0, };
352 /* top -> down is an evolution of mach64 chipset, any corrections? */
353 #define ATI_CHIP_88800GX (M64F_GX)
354 #define ATI_CHIP_88800CX (M64F_GX)
356 #define ATI_CHIP_264CT (M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO)
357 #define ATI_CHIP_264ET (M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO)
359 #define ATI_CHIP_264VT (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO)
360 #define ATI_CHIP_264GT (M64F_GT | M64F_INTEGRATED | M64F_MAGIC_FIFO | M64F_EXTRA_BRIGHT)
362 #define ATI_CHIP_264VTB (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP)
363 #define ATI_CHIP_264VT3 (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL)
364 #define ATI_CHIP_264VT4 (M64F_VT | M64F_INTEGRATED | M64F_GTB_DSP)
366 /* FIXME what is this chip? */
367 #define ATI_CHIP_264LT (M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP)
369 /* make sets shorter */
370 #define ATI_MODERN_SET (M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_EXTRA_BRIGHT)
372 #define ATI_CHIP_264GTB (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL)
373 /*#define ATI_CHIP_264GTDVD ?*/
374 #define ATI_CHIP_264LTG (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL)
376 #define ATI_CHIP_264GT2C (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE)
377 #define ATI_CHIP_264GTPRO (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
378 #define ATI_CHIP_264LTPRO (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
380 #define ATI_CHIP_264XL (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_XL_MEM)
381 #define ATI_CHIP_MOBILITY (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_XL_MEM | M64F_MOBIL_BUS)
386 int pll
, mclk
, xclk
, ecp_max
;
389 #ifdef CONFIG_FB_ATY_GX
391 { PCI_CHIP_MACH64GX
, "ATI888GX00 (Mach64 GX)", 135, 50, 50, 0, ATI_CHIP_88800GX
},
392 { PCI_CHIP_MACH64CX
, "ATI888CX00 (Mach64 CX)", 135, 50, 50, 0, ATI_CHIP_88800CX
},
393 #endif /* CONFIG_FB_ATY_GX */
395 #ifdef CONFIG_FB_ATY_CT
396 { PCI_CHIP_MACH64CT
, "ATI264CT (Mach64 CT)", 135, 60, 60, 0, ATI_CHIP_264CT
},
397 { PCI_CHIP_MACH64ET
, "ATI264ET (Mach64 ET)", 135, 60, 60, 0, ATI_CHIP_264ET
},
399 /* FIXME what is this chip? */
400 { PCI_CHIP_MACH64LT
, "ATI264LT (Mach64 LT)", 135, 63, 63, 0, ATI_CHIP_264LT
},
402 { PCI_CHIP_MACH64VT
, "ATI264VT (Mach64 VT)", 170, 67, 67, 80, ATI_CHIP_264VT
},
403 { PCI_CHIP_MACH64GT
, "3D RAGE (Mach64 GT)", 135, 63, 63, 80, ATI_CHIP_264GT
},
405 { PCI_CHIP_MACH64VU
, "ATI264VT3 (Mach64 VU)", 200, 67, 67, 80, ATI_CHIP_264VT3
},
406 { PCI_CHIP_MACH64GU
, "3D RAGE II+ (Mach64 GU)", 200, 67, 67, 100, ATI_CHIP_264GTB
},
408 { PCI_CHIP_MACH64LG
, "3D RAGE LT (Mach64 LG)", 230, 63, 63, 100, ATI_CHIP_264LTG
| M64F_LT_LCD_REGS
| M64F_G3_PB_1024x768
},
410 { PCI_CHIP_MACH64VV
, "ATI264VT4 (Mach64 VV)", 230, 83, 83, 100, ATI_CHIP_264VT4
},
412 { PCI_CHIP_MACH64GV
, "3D RAGE IIC (Mach64 GV, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C
},
413 { PCI_CHIP_MACH64GW
, "3D RAGE IIC (Mach64 GW, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C
},
414 { PCI_CHIP_MACH64GY
, "3D RAGE IIC (Mach64 GY, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C
},
415 { PCI_CHIP_MACH64GZ
, "3D RAGE IIC (Mach64 GZ, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C
},
417 { PCI_CHIP_MACH64GB
, "3D RAGE PRO (Mach64 GB, BGA, AGP)", 230, 100, 100, 125, ATI_CHIP_264GTPRO
},
418 { PCI_CHIP_MACH64GD
, "3D RAGE PRO (Mach64 GD, BGA, AGP 1x)", 230, 100, 100, 125, ATI_CHIP_264GTPRO
},
419 { PCI_CHIP_MACH64GI
, "3D RAGE PRO (Mach64 GI, BGA, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO
| M64F_MAGIC_VRAM_SIZE
},
420 { PCI_CHIP_MACH64GP
, "3D RAGE PRO (Mach64 GP, PQFP, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO
},
421 { PCI_CHIP_MACH64GQ
, "3D RAGE PRO (Mach64 GQ, PQFP, PCI, limited 3D)", 230, 100, 100, 125, ATI_CHIP_264GTPRO
},
423 { PCI_CHIP_MACH64LB
, "3D RAGE LT PRO (Mach64 LB, AGP)", 236, 75, 100, 135, ATI_CHIP_264LTPRO
},
424 { PCI_CHIP_MACH64LD
, "3D RAGE LT PRO (Mach64 LD, AGP)", 230, 100, 100, 135, ATI_CHIP_264LTPRO
},
425 { PCI_CHIP_MACH64LI
, "3D RAGE LT PRO (Mach64 LI, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO
| M64F_G3_PB_1_1
| M64F_G3_PB_1024x768
},
426 { PCI_CHIP_MACH64LP
, "3D RAGE LT PRO (Mach64 LP, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO
| M64F_G3_PB_1024x768
},
427 { PCI_CHIP_MACH64LQ
, "3D RAGE LT PRO (Mach64 LQ, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO
},
429 { PCI_CHIP_MACH64GM
, "3D RAGE XL (Mach64 GM, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL
},
430 { PCI_CHIP_MACH64GN
, "3D RAGE XC (Mach64 GN, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL
},
431 { PCI_CHIP_MACH64GO
, "3D RAGE XL (Mach64 GO, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL
},
432 { PCI_CHIP_MACH64GL
, "3D RAGE XC (Mach64 GL, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL
},
433 { PCI_CHIP_MACH64GR
, "3D RAGE XL (Mach64 GR, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL
| M64F_SDRAM_MAGIC_PLL
},
434 { PCI_CHIP_MACH64GS
, "3D RAGE XC (Mach64 GS, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL
},
436 { PCI_CHIP_MACH64LM
, "3D RAGE Mobility P/M (Mach64 LM, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY
},
437 { PCI_CHIP_MACH64LN
, "3D RAGE Mobility L (Mach64 LN, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY
},
438 { PCI_CHIP_MACH64LR
, "3D RAGE Mobility P/M (Mach64 LR, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY
},
439 { PCI_CHIP_MACH64LS
, "3D RAGE Mobility L (Mach64 LS, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY
},
440 #endif /* CONFIG_FB_ATY_CT */
444 * Last page of 8 MB (4 MB on ISA) aperture is MMIO,
445 * unless the auxiliary register aperture is used.
447 static void aty_fudge_framebuffer_len(struct fb_info
*info
)
449 struct atyfb_par
*par
= (struct atyfb_par
*) info
->par
;
451 if (!par
->aux_start
&&
452 (info
->fix
.smem_len
== 0x800000 ||
453 (par
->bus_type
== ISA
&& info
->fix
.smem_len
== 0x400000)))
454 info
->fix
.smem_len
-= GUI_RESERVE
;
457 static int correct_chipset(struct atyfb_par
*par
)
465 for (i
= (int)ARRAY_SIZE(aty_chips
) - 1; i
>= 0; i
--)
466 if (par
->pci_id
== aty_chips
[i
].pci_id
)
472 name
= aty_chips
[i
].name
;
473 par
->pll_limits
.pll_max
= aty_chips
[i
].pll
;
474 par
->pll_limits
.mclk
= aty_chips
[i
].mclk
;
475 par
->pll_limits
.xclk
= aty_chips
[i
].xclk
;
476 par
->pll_limits
.ecp_max
= aty_chips
[i
].ecp_max
;
477 par
->features
= aty_chips
[i
].features
;
479 chip_id
= aty_ld_le32(CNFG_CHIP_ID
, par
);
480 type
= chip_id
& CFG_CHIP_TYPE
;
481 rev
= (chip_id
& CFG_CHIP_REV
) >> 24;
483 switch (par
->pci_id
) {
484 #ifdef CONFIG_FB_ATY_GX
485 case PCI_CHIP_MACH64GX
:
489 case PCI_CHIP_MACH64CX
:
494 #ifdef CONFIG_FB_ATY_CT
495 case PCI_CHIP_MACH64VT
:
496 switch (rev
& 0x07) {
498 switch (rev
& 0xc0) {
500 name
= "ATI264VT (A3) (Mach64 VT)";
501 par
->pll_limits
.pll_max
= 170;
502 par
->pll_limits
.mclk
= 67;
503 par
->pll_limits
.xclk
= 67;
504 par
->pll_limits
.ecp_max
= 80;
505 par
->features
= ATI_CHIP_264VT
;
508 name
= "ATI264VT2 (A4) (Mach64 VT)";
509 par
->pll_limits
.pll_max
= 200;
510 par
->pll_limits
.mclk
= 67;
511 par
->pll_limits
.xclk
= 67;
512 par
->pll_limits
.ecp_max
= 80;
513 par
->features
= ATI_CHIP_264VT
| M64F_MAGIC_POSTDIV
;
518 name
= "ATI264VT3 (B1) (Mach64 VT)";
519 par
->pll_limits
.pll_max
= 200;
520 par
->pll_limits
.mclk
= 67;
521 par
->pll_limits
.xclk
= 67;
522 par
->pll_limits
.ecp_max
= 80;
523 par
->features
= ATI_CHIP_264VTB
;
526 name
= "ATI264VT3 (B2) (Mach64 VT)";
527 par
->pll_limits
.pll_max
= 200;
528 par
->pll_limits
.mclk
= 67;
529 par
->pll_limits
.xclk
= 67;
530 par
->pll_limits
.ecp_max
= 80;
531 par
->features
= ATI_CHIP_264VT3
;
535 case PCI_CHIP_MACH64GT
:
536 switch (rev
& 0x07) {
538 name
= "3D RAGE II (Mach64 GT)";
539 par
->pll_limits
.pll_max
= 170;
540 par
->pll_limits
.mclk
= 67;
541 par
->pll_limits
.xclk
= 67;
542 par
->pll_limits
.ecp_max
= 80;
543 par
->features
= ATI_CHIP_264GTB
;
546 name
= "3D RAGE II+ (Mach64 GT)";
547 par
->pll_limits
.pll_max
= 200;
548 par
->pll_limits
.mclk
= 67;
549 par
->pll_limits
.xclk
= 67;
550 par
->pll_limits
.ecp_max
= 100;
551 par
->features
= ATI_CHIP_264GTB
;
558 PRINTKI("%s [0x%04x rev 0x%02x]\n", name
, type
, rev
);
562 static char ram_dram
[] __maybe_unused
= "DRAM";
563 static char ram_resv
[] __maybe_unused
= "RESV";
564 #ifdef CONFIG_FB_ATY_GX
565 static char ram_vram
[] = "VRAM";
566 #endif /* CONFIG_FB_ATY_GX */
567 #ifdef CONFIG_FB_ATY_CT
568 static char ram_edo
[] = "EDO";
569 static char ram_sdram
[] = "SDRAM (1:1)";
570 static char ram_sgram
[] = "SGRAM (1:1)";
571 static char ram_sdram32
[] = "SDRAM (2:1) (32-bit)";
572 static char ram_wram
[] = "WRAM";
573 static char ram_off
[] = "OFF";
574 #endif /* CONFIG_FB_ATY_CT */
577 #ifdef CONFIG_FB_ATY_GX
578 static char *aty_gx_ram
[8] = {
579 ram_dram
, ram_vram
, ram_vram
, ram_dram
,
580 ram_dram
, ram_vram
, ram_vram
, ram_resv
582 #endif /* CONFIG_FB_ATY_GX */
584 #ifdef CONFIG_FB_ATY_CT
585 static char *aty_ct_ram
[8] = {
586 ram_off
, ram_dram
, ram_edo
, ram_edo
,
587 ram_sdram
, ram_sgram
, ram_wram
, ram_resv
589 static char *aty_xl_ram
[8] = {
590 ram_off
, ram_dram
, ram_edo
, ram_edo
,
591 ram_sdram
, ram_sgram
, ram_sdram32
, ram_resv
593 #endif /* CONFIG_FB_ATY_CT */
595 static u32
atyfb_get_pixclock(struct fb_var_screeninfo
*var
,
596 struct atyfb_par
*par
)
598 u32 pixclock
= var
->pixclock
;
599 #ifdef CONFIG_FB_ATY_GENERIC_LCD
601 par
->pll
.ct
.xres
= 0;
602 if (par
->lcd_table
!= 0) {
603 lcd_on_off
= aty_ld_lcd(LCD_GEN_CNTL
, par
);
604 if (lcd_on_off
& LCD_ON
) {
605 par
->pll
.ct
.xres
= var
->xres
;
606 pixclock
= par
->lcd_pixclock
;
613 #if defined(CONFIG_PPC)
616 * Apple monitor sense
619 static int read_aty_sense(const struct atyfb_par
*par
)
623 aty_st_le32(GP_IO
, 0x31003100, par
); /* drive outputs high */
625 aty_st_le32(GP_IO
, 0, par
); /* turn off outputs */
627 i
= aty_ld_le32(GP_IO
, par
); /* get primary sense value */
628 sense
= ((i
& 0x3000) >> 3) | (i
& 0x100);
630 /* drive each sense line low in turn and collect the other 2 */
631 aty_st_le32(GP_IO
, 0x20000000, par
); /* drive A low */
633 i
= aty_ld_le32(GP_IO
, par
);
634 sense
|= ((i
& 0x1000) >> 7) | ((i
& 0x100) >> 4);
635 aty_st_le32(GP_IO
, 0x20002000, par
); /* drive A high again */
638 aty_st_le32(GP_IO
, 0x10000000, par
); /* drive B low */
640 i
= aty_ld_le32(GP_IO
, par
);
641 sense
|= ((i
& 0x2000) >> 10) | ((i
& 0x100) >> 6);
642 aty_st_le32(GP_IO
, 0x10001000, par
); /* drive B high again */
645 aty_st_le32(GP_IO
, 0x01000000, par
); /* drive C low */
647 sense
|= (aty_ld_le32(GP_IO
, par
) & 0x3000) >> 12;
648 aty_st_le32(GP_IO
, 0, par
); /* turn off outputs */
652 #endif /* defined(CONFIG_PPC) */
654 /* ------------------------------------------------------------------------- */
660 static void aty_get_crtc(const struct atyfb_par
*par
, struct crtc
*crtc
)
662 #ifdef CONFIG_FB_ATY_GENERIC_LCD
663 if (par
->lcd_table
!= 0) {
664 if (!M64_HAS(LT_LCD_REGS
)) {
665 crtc
->lcd_index
= aty_ld_le32(LCD_INDEX
, par
);
666 aty_st_le32(LCD_INDEX
, crtc
->lcd_index
, par
);
668 crtc
->lcd_config_panel
= aty_ld_lcd(CNFG_PANEL
, par
);
669 crtc
->lcd_gen_cntl
= aty_ld_lcd(LCD_GEN_CNTL
, par
);
672 /* switch to non shadow registers */
673 aty_st_lcd(LCD_GEN_CNTL
, crtc
->lcd_gen_cntl
&
674 ~(CRTC_RW_SELECT
| SHADOW_EN
| SHADOW_RW_EN
), par
);
676 /* save stretching */
677 crtc
->horz_stretching
= aty_ld_lcd(HORZ_STRETCHING
, par
);
678 crtc
->vert_stretching
= aty_ld_lcd(VERT_STRETCHING
, par
);
679 if (!M64_HAS(LT_LCD_REGS
))
680 crtc
->ext_vert_stretch
= aty_ld_lcd(EXT_VERT_STRETCH
, par
);
683 crtc
->h_tot_disp
= aty_ld_le32(CRTC_H_TOTAL_DISP
, par
);
684 crtc
->h_sync_strt_wid
= aty_ld_le32(CRTC_H_SYNC_STRT_WID
, par
);
685 crtc
->v_tot_disp
= aty_ld_le32(CRTC_V_TOTAL_DISP
, par
);
686 crtc
->v_sync_strt_wid
= aty_ld_le32(CRTC_V_SYNC_STRT_WID
, par
);
687 crtc
->vline_crnt_vline
= aty_ld_le32(CRTC_VLINE_CRNT_VLINE
, par
);
688 crtc
->off_pitch
= aty_ld_le32(CRTC_OFF_PITCH
, par
);
689 crtc
->gen_cntl
= aty_ld_le32(CRTC_GEN_CNTL
, par
);
691 #ifdef CONFIG_FB_ATY_GENERIC_LCD
692 if (par
->lcd_table
!= 0) {
693 /* switch to shadow registers */
694 aty_st_lcd(LCD_GEN_CNTL
, (crtc
->lcd_gen_cntl
& ~CRTC_RW_SELECT
) |
695 SHADOW_EN
| SHADOW_RW_EN
, par
);
697 crtc
->shadow_h_tot_disp
= aty_ld_le32(CRTC_H_TOTAL_DISP
, par
);
698 crtc
->shadow_h_sync_strt_wid
= aty_ld_le32(CRTC_H_SYNC_STRT_WID
, par
);
699 crtc
->shadow_v_tot_disp
= aty_ld_le32(CRTC_V_TOTAL_DISP
, par
);
700 crtc
->shadow_v_sync_strt_wid
= aty_ld_le32(CRTC_V_SYNC_STRT_WID
, par
);
702 aty_st_le32(LCD_GEN_CNTL
, crtc
->lcd_gen_cntl
, par
);
704 #endif /* CONFIG_FB_ATY_GENERIC_LCD */
707 static void aty_set_crtc(const struct atyfb_par
*par
, const struct crtc
*crtc
)
709 #ifdef CONFIG_FB_ATY_GENERIC_LCD
710 if (par
->lcd_table
!= 0) {
712 aty_st_le32(CRTC_GEN_CNTL
, crtc
->gen_cntl
&
713 ~(CRTC_EXT_DISP_EN
| CRTC_EN
), par
);
715 /* update non-shadow registers first */
716 aty_st_lcd(CNFG_PANEL
, crtc
->lcd_config_panel
, par
);
717 aty_st_lcd(LCD_GEN_CNTL
, crtc
->lcd_gen_cntl
&
718 ~(CRTC_RW_SELECT
| SHADOW_EN
| SHADOW_RW_EN
), par
);
720 /* temporarily disable stretching */
721 aty_st_lcd(HORZ_STRETCHING
, crtc
->horz_stretching
&
722 ~(HORZ_STRETCH_MODE
| HORZ_STRETCH_EN
), par
);
723 aty_st_lcd(VERT_STRETCHING
, crtc
->vert_stretching
&
724 ~(VERT_STRETCH_RATIO1
| VERT_STRETCH_RATIO2
|
725 VERT_STRETCH_USE0
| VERT_STRETCH_EN
), par
);
729 aty_st_le32(CRTC_GEN_CNTL
, crtc
->gen_cntl
& ~CRTC_EN
, par
);
731 DPRINTK("setting up CRTC\n");
732 DPRINTK("set primary CRT to %ix%i %c%c composite %c\n",
733 ((((crtc
->h_tot_disp
>> 16) & 0xff) + 1) << 3),
734 (((crtc
->v_tot_disp
>> 16) & 0x7ff) + 1),
735 (crtc
->h_sync_strt_wid
& 0x200000) ? 'N' : 'P',
736 (crtc
->v_sync_strt_wid
& 0x200000) ? 'N' : 'P',
737 (crtc
->gen_cntl
& CRTC_CSYNC_EN
) ? 'P' : 'N');
739 DPRINTK("CRTC_H_TOTAL_DISP: %x\n", crtc
->h_tot_disp
);
740 DPRINTK("CRTC_H_SYNC_STRT_WID: %x\n", crtc
->h_sync_strt_wid
);
741 DPRINTK("CRTC_V_TOTAL_DISP: %x\n", crtc
->v_tot_disp
);
742 DPRINTK("CRTC_V_SYNC_STRT_WID: %x\n", crtc
->v_sync_strt_wid
);
743 DPRINTK("CRTC_OFF_PITCH: %x\n", crtc
->off_pitch
);
744 DPRINTK("CRTC_VLINE_CRNT_VLINE: %x\n", crtc
->vline_crnt_vline
);
745 DPRINTK("CRTC_GEN_CNTL: %x\n", crtc
->gen_cntl
);
747 aty_st_le32(CRTC_H_TOTAL_DISP
, crtc
->h_tot_disp
, par
);
748 aty_st_le32(CRTC_H_SYNC_STRT_WID
, crtc
->h_sync_strt_wid
, par
);
749 aty_st_le32(CRTC_V_TOTAL_DISP
, crtc
->v_tot_disp
, par
);
750 aty_st_le32(CRTC_V_SYNC_STRT_WID
, crtc
->v_sync_strt_wid
, par
);
751 aty_st_le32(CRTC_OFF_PITCH
, crtc
->off_pitch
, par
);
752 aty_st_le32(CRTC_VLINE_CRNT_VLINE
, crtc
->vline_crnt_vline
, par
);
754 aty_st_le32(CRTC_GEN_CNTL
, crtc
->gen_cntl
, par
);
757 if (par
->accel_flags
& FB_ACCELF_TEXT
)
758 aty_init_engine(par
, info
);
760 #ifdef CONFIG_FB_ATY_GENERIC_LCD
761 /* after setting the CRTC registers we should set the LCD registers. */
762 if (par
->lcd_table
!= 0) {
763 /* switch to shadow registers */
764 aty_st_lcd(LCD_GEN_CNTL
, (crtc
->lcd_gen_cntl
& ~CRTC_RW_SELECT
) |
765 SHADOW_EN
| SHADOW_RW_EN
, par
);
767 DPRINTK("set shadow CRT to %ix%i %c%c\n",
768 ((((crtc
->shadow_h_tot_disp
>> 16) & 0xff) + 1) << 3),
769 (((crtc
->shadow_v_tot_disp
>> 16) & 0x7ff) + 1),
770 (crtc
->shadow_h_sync_strt_wid
& 0x200000) ? 'N' : 'P',
771 (crtc
->shadow_v_sync_strt_wid
& 0x200000) ? 'N' : 'P');
773 DPRINTK("SHADOW CRTC_H_TOTAL_DISP: %x\n",
774 crtc
->shadow_h_tot_disp
);
775 DPRINTK("SHADOW CRTC_H_SYNC_STRT_WID: %x\n",
776 crtc
->shadow_h_sync_strt_wid
);
777 DPRINTK("SHADOW CRTC_V_TOTAL_DISP: %x\n",
778 crtc
->shadow_v_tot_disp
);
779 DPRINTK("SHADOW CRTC_V_SYNC_STRT_WID: %x\n",
780 crtc
->shadow_v_sync_strt_wid
);
782 aty_st_le32(CRTC_H_TOTAL_DISP
, crtc
->shadow_h_tot_disp
, par
);
783 aty_st_le32(CRTC_H_SYNC_STRT_WID
, crtc
->shadow_h_sync_strt_wid
, par
);
784 aty_st_le32(CRTC_V_TOTAL_DISP
, crtc
->shadow_v_tot_disp
, par
);
785 aty_st_le32(CRTC_V_SYNC_STRT_WID
, crtc
->shadow_v_sync_strt_wid
, par
);
787 /* restore CRTC selection & shadow state and enable stretching */
788 DPRINTK("LCD_GEN_CNTL: %x\n", crtc
->lcd_gen_cntl
);
789 DPRINTK("HORZ_STRETCHING: %x\n", crtc
->horz_stretching
);
790 DPRINTK("VERT_STRETCHING: %x\n", crtc
->vert_stretching
);
791 if (!M64_HAS(LT_LCD_REGS
))
792 DPRINTK("EXT_VERT_STRETCH: %x\n", crtc
->ext_vert_stretch
);
794 aty_st_lcd(LCD_GEN_CNTL
, crtc
->lcd_gen_cntl
, par
);
795 aty_st_lcd(HORZ_STRETCHING
, crtc
->horz_stretching
, par
);
796 aty_st_lcd(VERT_STRETCHING
, crtc
->vert_stretching
, par
);
797 if (!M64_HAS(LT_LCD_REGS
)) {
798 aty_st_lcd(EXT_VERT_STRETCH
, crtc
->ext_vert_stretch
, par
);
799 aty_ld_le32(LCD_INDEX
, par
);
800 aty_st_le32(LCD_INDEX
, crtc
->lcd_index
, par
);
803 #endif /* CONFIG_FB_ATY_GENERIC_LCD */
806 static u32
calc_line_length(struct atyfb_par
*par
, u32 vxres
, u32 bpp
)
808 u32 line_length
= vxres
* bpp
/ 8;
810 if (par
->ram_type
== SGRAM
||
811 (!M64_HAS(XL_MEM
) && par
->ram_type
== WRAM
))
812 line_length
= (line_length
+ 63) & ~63;
817 static int aty_var_to_crtc(const struct fb_info
*info
,
818 const struct fb_var_screeninfo
*var
,
821 struct atyfb_par
*par
= (struct atyfb_par
*) info
->par
;
822 u32 xres
, yres
, vxres
, vyres
, xoffset
, yoffset
, bpp
;
824 u32 h_total
, h_disp
, h_sync_strt
, h_sync_end
, h_sync_dly
, h_sync_wid
, h_sync_pol
;
825 u32 v_total
, v_disp
, v_sync_strt
, v_sync_end
, v_sync_wid
, v_sync_pol
, c_sync
;
826 u32 pix_width
, dp_pix_width
, dp_chain_mask
;
830 xres
= (var
->xres
+ 7) & ~7;
832 vxres
= (var
->xres_virtual
+ 7) & ~7;
833 vyres
= var
->yres_virtual
;
834 xoffset
= (var
->xoffset
+ 7) & ~7;
835 yoffset
= var
->yoffset
;
836 bpp
= var
->bits_per_pixel
;
838 bpp
= (var
->green
.length
== 5) ? 15 : 16;
842 /* convert (and round up) and validate */
843 if (vxres
< xres
+ xoffset
)
844 vxres
= xres
+ xoffset
;
847 if (vyres
< yres
+ yoffset
)
848 vyres
= yres
+ yoffset
;
853 pix_width
= CRTC_PIX_WIDTH_8BPP
;
854 dp_pix_width
= HOST_8BPP
| SRC_8BPP
| DST_8BPP
|
855 BYTE_ORDER_LSB_TO_MSB
;
856 dp_chain_mask
= DP_CHAIN_8BPP
;
857 } else if (bpp
<= 15) {
859 pix_width
= CRTC_PIX_WIDTH_15BPP
;
860 dp_pix_width
= HOST_15BPP
| SRC_15BPP
| DST_15BPP
|
861 BYTE_ORDER_LSB_TO_MSB
;
862 dp_chain_mask
= DP_CHAIN_15BPP
;
863 } else if (bpp
<= 16) {
865 pix_width
= CRTC_PIX_WIDTH_16BPP
;
866 dp_pix_width
= HOST_16BPP
| SRC_16BPP
| DST_16BPP
|
867 BYTE_ORDER_LSB_TO_MSB
;
868 dp_chain_mask
= DP_CHAIN_16BPP
;
869 } else if (bpp
<= 24 && M64_HAS(INTEGRATED
)) {
871 pix_width
= CRTC_PIX_WIDTH_24BPP
;
872 dp_pix_width
= HOST_8BPP
| SRC_8BPP
| DST_8BPP
|
873 BYTE_ORDER_LSB_TO_MSB
;
874 dp_chain_mask
= DP_CHAIN_24BPP
;
875 } else if (bpp
<= 32) {
877 pix_width
= CRTC_PIX_WIDTH_32BPP
;
878 dp_pix_width
= HOST_32BPP
| SRC_32BPP
| DST_32BPP
|
879 BYTE_ORDER_LSB_TO_MSB
;
880 dp_chain_mask
= DP_CHAIN_32BPP
;
884 line_length
= calc_line_length(par
, vxres
, bpp
);
886 if (vyres
* line_length
> info
->fix
.smem_len
)
887 FAIL("not enough video RAM");
889 h_sync_pol
= sync
& FB_SYNC_HOR_HIGH_ACT
? 0 : 1;
890 v_sync_pol
= sync
& FB_SYNC_VERT_HIGH_ACT
? 0 : 1;
892 if ((xres
> 1920) || (yres
> 1200)) {
893 FAIL("MACH64 chips are designed for max 1920x1200\n"
894 "select another resolution.");
896 h_sync_strt
= h_disp
+ var
->right_margin
;
897 h_sync_end
= h_sync_strt
+ var
->hsync_len
;
898 h_sync_dly
= var
->right_margin
& 7;
899 h_total
= h_sync_end
+ h_sync_dly
+ var
->left_margin
;
901 v_sync_strt
= v_disp
+ var
->lower_margin
;
902 v_sync_end
= v_sync_strt
+ var
->vsync_len
;
903 v_total
= v_sync_end
+ var
->upper_margin
;
905 #ifdef CONFIG_FB_ATY_GENERIC_LCD
906 if (par
->lcd_table
!= 0) {
907 if (!M64_HAS(LT_LCD_REGS
)) {
908 u32 lcd_index
= aty_ld_le32(LCD_INDEX
, par
);
909 crtc
->lcd_index
= lcd_index
&
910 ~(LCD_INDEX_MASK
| LCD_DISPLAY_DIS
|
911 LCD_SRC_SEL
| CRTC2_DISPLAY_DIS
);
912 aty_st_le32(LCD_INDEX
, lcd_index
, par
);
915 if (!M64_HAS(MOBIL_BUS
))
916 crtc
->lcd_index
|= CRTC2_DISPLAY_DIS
;
918 crtc
->lcd_config_panel
= aty_ld_lcd(CNFG_PANEL
, par
) | 0x4000;
919 crtc
->lcd_gen_cntl
= aty_ld_lcd(LCD_GEN_CNTL
, par
) & ~CRTC_RW_SELECT
;
921 crtc
->lcd_gen_cntl
&=
922 ~(HORZ_DIVBY2_EN
| DIS_HOR_CRT_DIVBY2
| TVCLK_PM_EN
|
923 /*VCLK_DAC_PM_EN | USE_SHADOWED_VEND |*/
924 USE_SHADOWED_ROWCUR
| SHADOW_EN
| SHADOW_RW_EN
);
925 crtc
->lcd_gen_cntl
|= DONT_SHADOW_VPAR
| LOCK_8DOT
;
927 if ((crtc
->lcd_gen_cntl
& LCD_ON
) &&
928 ((xres
> par
->lcd_width
) || (yres
> par
->lcd_height
))) {
930 * We cannot display the mode on the LCD. If the CRT is
931 * enabled we can turn off the LCD.
932 * If the CRT is off, it isn't a good idea to switch it
933 * on; we don't know if one is connected. So it's better
936 if (crtc
->lcd_gen_cntl
& CRT_ON
) {
937 if (!(var
->activate
& FB_ACTIVATE_TEST
))
938 PRINTKI("Disable LCD panel, because video mode does not fit.\n");
939 crtc
->lcd_gen_cntl
&= ~LCD_ON
;
940 /*aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);*/
942 if (!(var
->activate
& FB_ACTIVATE_TEST
))
943 PRINTKE("Video mode exceeds size of LCD panel.\nConnect this computer to a conventional monitor if you really need this mode.\n");
949 if ((par
->lcd_table
!= 0) && (crtc
->lcd_gen_cntl
& LCD_ON
)) {
951 /* bpp -> bytespp, 1,4 -> 0; 8 -> 2; 15,16 -> 1; 24 -> 6; 32 -> 5
952 const u8 DFP_h_sync_dly_LT[] = { 0, 2, 1, 6, 5 };
953 const u8 ADD_to_strt_wid_and_dly_LT_DAC[] = { 0, 5, 6, 9, 9, 12, 12 }; */
955 vmode
&= ~(FB_VMODE_DOUBLE
| FB_VMODE_INTERLACED
);
958 * This is horror! When we simulate, say 640x480 on an 800x600
959 * LCD monitor, the CRTC should be programmed 800x600 values for
960 * the non visible part, but 640x480 for the visible part.
961 * This code has been tested on a laptop with it's 1400x1050 LCD
962 * monitor and a conventional monitor both switched on.
963 * Tested modes: 1280x1024, 1152x864, 1024x768, 800x600,
964 * works with little glitches also with DOUBLESCAN modes
966 if (yres
< par
->lcd_height
) {
967 VScan
= par
->lcd_height
/ yres
;
970 vmode
|= FB_VMODE_DOUBLE
;
974 h_sync_strt
= h_disp
+ par
->lcd_right_margin
;
975 h_sync_end
= h_sync_strt
+ par
->lcd_hsync_len
;
976 h_sync_dly
= /*DFP_h_sync_dly[ ( bpp + 1 ) / 3 ]; */par
->lcd_hsync_dly
;
977 h_total
= h_disp
+ par
->lcd_hblank_len
;
979 v_sync_strt
= v_disp
+ par
->lcd_lower_margin
/ VScan
;
980 v_sync_end
= v_sync_strt
+ par
->lcd_vsync_len
/ VScan
;
981 v_total
= v_disp
+ par
->lcd_vblank_len
/ VScan
;
983 #endif /* CONFIG_FB_ATY_GENERIC_LCD */
985 h_disp
= (h_disp
>> 3) - 1;
986 h_sync_strt
= (h_sync_strt
>> 3) - 1;
987 h_sync_end
= (h_sync_end
>> 3) - 1;
988 h_total
= (h_total
>> 3) - 1;
989 h_sync_wid
= h_sync_end
- h_sync_strt
;
991 FAIL_MAX("h_disp too large", h_disp
, 0xff);
992 FAIL_MAX("h_sync_strt too large", h_sync_strt
, 0x1ff);
993 /*FAIL_MAX("h_sync_wid too large", h_sync_wid, 0x1f);*/
994 if (h_sync_wid
> 0x1f)
996 FAIL_MAX("h_total too large", h_total
, 0x1ff);
998 if (vmode
& FB_VMODE_DOUBLE
) {
1009 v_sync_wid
= v_sync_end
- v_sync_strt
;
1011 FAIL_MAX("v_disp too large", v_disp
, 0x7ff);
1012 FAIL_MAX("v_sync_stsrt too large", v_sync_strt
, 0x7ff);
1013 /*FAIL_MAX("v_sync_wid too large", v_sync_wid, 0x1f);*/
1014 if (v_sync_wid
> 0x1f)
1016 FAIL_MAX("v_total too large", v_total
, 0x7ff);
1018 c_sync
= sync
& FB_SYNC_COMP_HIGH_ACT
? CRTC_CSYNC_EN
: 0;
1021 crtc
->vxres
= vxres
;
1022 crtc
->vyres
= vyres
;
1023 crtc
->xoffset
= xoffset
;
1024 crtc
->yoffset
= yoffset
;
1027 ((yoffset
* line_length
+ xoffset
* bpp
/ 8) / 8) |
1028 ((line_length
/ bpp
) << 22);
1029 crtc
->vline_crnt_vline
= 0;
1031 crtc
->h_tot_disp
= h_total
| (h_disp
<< 16);
1032 crtc
->h_sync_strt_wid
= (h_sync_strt
& 0xff) | (h_sync_dly
<< 8) |
1033 ((h_sync_strt
& 0x100) << 4) | (h_sync_wid
<< 16) |
1035 crtc
->v_tot_disp
= v_total
| (v_disp
<< 16);
1036 crtc
->v_sync_strt_wid
= v_sync_strt
| (v_sync_wid
<< 16) |
1039 /* crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_PRESERVED_MASK; */
1040 crtc
->gen_cntl
= CRTC_EXT_DISP_EN
| CRTC_EN
| pix_width
| c_sync
;
1041 crtc
->gen_cntl
|= CRTC_VGA_LINEAR
;
1043 /* Enable doublescan mode if requested */
1044 if (vmode
& FB_VMODE_DOUBLE
)
1045 crtc
->gen_cntl
|= CRTC_DBL_SCAN_EN
;
1046 /* Enable interlaced mode if requested */
1047 if (vmode
& FB_VMODE_INTERLACED
)
1048 crtc
->gen_cntl
|= CRTC_INTERLACE_EN
;
1049 #ifdef CONFIG_FB_ATY_GENERIC_LCD
1050 if (par
->lcd_table
!= 0) {
1051 u32 vdisplay
= yres
;
1052 if (vmode
& FB_VMODE_DOUBLE
)
1054 crtc
->gen_cntl
&= ~(CRTC2_EN
| CRTC2_PIX_WIDTH
);
1055 crtc
->lcd_gen_cntl
&= ~(HORZ_DIVBY2_EN
| DIS_HOR_CRT_DIVBY2
|
1056 /*TVCLK_PM_EN | VCLK_DAC_PM_EN |*/
1058 USE_SHADOWED_ROWCUR
|
1059 SHADOW_EN
| SHADOW_RW_EN
);
1060 crtc
->lcd_gen_cntl
|= DONT_SHADOW_VPAR
/* | LOCK_8DOT*/;
1062 /* MOBILITY M1 tested, FIXME: LT */
1063 crtc
->horz_stretching
= aty_ld_lcd(HORZ_STRETCHING
, par
);
1064 if (!M64_HAS(LT_LCD_REGS
))
1065 crtc
->ext_vert_stretch
= aty_ld_lcd(EXT_VERT_STRETCH
, par
) &
1066 ~(AUTO_VERT_RATIO
| VERT_STRETCH_MODE
| VERT_STRETCH_RATIO3
);
1068 crtc
->horz_stretching
&= ~(HORZ_STRETCH_RATIO
|
1069 HORZ_STRETCH_LOOP
| AUTO_HORZ_RATIO
|
1070 HORZ_STRETCH_MODE
| HORZ_STRETCH_EN
);
1071 if (xres
< par
->lcd_width
&& crtc
->lcd_gen_cntl
& LCD_ON
) {
1074 * The horizontal blender misbehaves when
1075 * HDisplay is less than a certain threshold
1076 * (440 for a 1024-wide panel). It doesn't
1077 * stretch such modes enough. Use pixel
1078 * replication instead of blending to stretch
1079 * modes that can be made to exactly fit the
1080 * panel width. The undocumented "NoLCDBlend"
1081 * option allows the pixel-replicated mode to
1082 * be slightly wider or narrower than the
1083 * panel width. It also causes a mode that is
1084 * exactly half as wide as the panel to be
1085 * pixel-replicated, rather than blended.
1087 int HDisplay
= xres
& ~7;
1088 int nStretch
= par
->lcd_width
/ HDisplay
;
1089 int Remainder
= par
->lcd_width
% HDisplay
;
1091 if ((!Remainder
&& ((nStretch
> 2))) ||
1092 (((HDisplay
* 16) / par
->lcd_width
) < 7)) {
1093 static const char StretchLoops
[] = { 10, 12, 13, 15, 16 };
1094 int horz_stretch_loop
= -1, BestRemainder
;
1095 int Numerator
= HDisplay
, Denominator
= par
->lcd_width
;
1097 ATIReduceRatio(&Numerator
, &Denominator
);
1099 BestRemainder
= (Numerator
* 16) / Denominator
;
1100 while (--Index
>= 0) {
1101 Remainder
= ((Denominator
- Numerator
) * StretchLoops
[Index
]) %
1103 if (Remainder
< BestRemainder
) {
1104 horz_stretch_loop
= Index
;
1105 if (!(BestRemainder
= Remainder
))
1110 if ((horz_stretch_loop
>= 0) && !BestRemainder
) {
1111 int horz_stretch_ratio
= 0, Accumulator
= 0;
1112 int reuse_previous
= 1;
1114 Index
= StretchLoops
[horz_stretch_loop
];
1116 while (--Index
>= 0) {
1117 if (Accumulator
> 0)
1118 horz_stretch_ratio
|= reuse_previous
;
1120 Accumulator
+= Denominator
;
1121 Accumulator
-= Numerator
;
1122 reuse_previous
<<= 1;
1125 crtc
->horz_stretching
|= (HORZ_STRETCH_EN
|
1126 ((horz_stretch_loop
& HORZ_STRETCH_LOOP
) << 16) |
1127 (horz_stretch_ratio
& HORZ_STRETCH_RATIO
));
1128 break; /* Out of the do { ... } while (0) */
1132 crtc
->horz_stretching
|= (HORZ_STRETCH_MODE
| HORZ_STRETCH_EN
|
1133 (((HDisplay
* (HORZ_STRETCH_BLEND
+ 1)) / par
->lcd_width
) & HORZ_STRETCH_BLEND
));
1137 if (vdisplay
< par
->lcd_height
&& crtc
->lcd_gen_cntl
& LCD_ON
) {
1138 crtc
->vert_stretching
= (VERT_STRETCH_USE0
| VERT_STRETCH_EN
|
1139 (((vdisplay
* (VERT_STRETCH_RATIO0
+ 1)) / par
->lcd_height
) & VERT_STRETCH_RATIO0
));
1141 if (!M64_HAS(LT_LCD_REGS
) &&
1142 xres
<= (M64_HAS(MOBIL_BUS
) ? 1024 : 800))
1143 crtc
->ext_vert_stretch
|= VERT_STRETCH_MODE
;
1146 * Don't use vertical blending if the mode is too wide
1147 * or not vertically stretched.
1149 crtc
->vert_stretching
= 0;
1151 /* copy to shadow crtc */
1152 crtc
->shadow_h_tot_disp
= crtc
->h_tot_disp
;
1153 crtc
->shadow_h_sync_strt_wid
= crtc
->h_sync_strt_wid
;
1154 crtc
->shadow_v_tot_disp
= crtc
->v_tot_disp
;
1155 crtc
->shadow_v_sync_strt_wid
= crtc
->v_sync_strt_wid
;
1157 #endif /* CONFIG_FB_ATY_GENERIC_LCD */
1159 if (M64_HAS(MAGIC_FIFO
)) {
1160 /* FIXME: display FIFO low watermark values */
1161 crtc
->gen_cntl
|= (aty_ld_le32(CRTC_GEN_CNTL
, par
) & CRTC_FIFO_LWM
);
1163 crtc
->dp_pix_width
= dp_pix_width
;
1164 crtc
->dp_chain_mask
= dp_chain_mask
;
1169 static int aty_crtc_to_var(const struct crtc
*crtc
,
1170 struct fb_var_screeninfo
*var
)
1172 u32 xres
, yres
, bpp
, left
, right
, upper
, lower
, hslen
, vslen
, sync
;
1173 u32 h_total
, h_disp
, h_sync_strt
, h_sync_dly
, h_sync_wid
, h_sync_pol
;
1174 u32 v_total
, v_disp
, v_sync_strt
, v_sync_wid
, v_sync_pol
, c_sync
;
1176 u32 double_scan
, interlace
;
1179 h_total
= crtc
->h_tot_disp
& 0x1ff;
1180 h_disp
= (crtc
->h_tot_disp
>> 16) & 0xff;
1181 h_sync_strt
= (crtc
->h_sync_strt_wid
& 0xff) | ((crtc
->h_sync_strt_wid
>> 4) & 0x100);
1182 h_sync_dly
= (crtc
->h_sync_strt_wid
>> 8) & 0x7;
1183 h_sync_wid
= (crtc
->h_sync_strt_wid
>> 16) & 0x1f;
1184 h_sync_pol
= (crtc
->h_sync_strt_wid
>> 21) & 0x1;
1185 v_total
= crtc
->v_tot_disp
& 0x7ff;
1186 v_disp
= (crtc
->v_tot_disp
>> 16) & 0x7ff;
1187 v_sync_strt
= crtc
->v_sync_strt_wid
& 0x7ff;
1188 v_sync_wid
= (crtc
->v_sync_strt_wid
>> 16) & 0x1f;
1189 v_sync_pol
= (crtc
->v_sync_strt_wid
>> 21) & 0x1;
1190 c_sync
= crtc
->gen_cntl
& CRTC_CSYNC_EN
? 1 : 0;
1191 pix_width
= crtc
->gen_cntl
& CRTC_PIX_WIDTH_MASK
;
1192 double_scan
= crtc
->gen_cntl
& CRTC_DBL_SCAN_EN
;
1193 interlace
= crtc
->gen_cntl
& CRTC_INTERLACE_EN
;
1196 xres
= (h_disp
+ 1) * 8;
1198 left
= (h_total
- h_sync_strt
- h_sync_wid
) * 8 - h_sync_dly
;
1199 right
= (h_sync_strt
- h_disp
) * 8 + h_sync_dly
;
1200 hslen
= h_sync_wid
* 8;
1201 upper
= v_total
- v_sync_strt
- v_sync_wid
;
1202 lower
= v_sync_strt
- v_disp
;
1204 sync
= (h_sync_pol
? 0 : FB_SYNC_HOR_HIGH_ACT
) |
1205 (v_sync_pol
? 0 : FB_SYNC_VERT_HIGH_ACT
) |
1206 (c_sync
? FB_SYNC_COMP_HIGH_ACT
: 0);
1208 switch (pix_width
) {
1209 case CRTC_PIX_WIDTH_8BPP
:
1211 var
->red
.offset
= 0;
1212 var
->red
.length
= 8;
1213 var
->green
.offset
= 0;
1214 var
->green
.length
= 8;
1215 var
->blue
.offset
= 0;
1216 var
->blue
.length
= 8;
1217 var
->transp
.offset
= 0;
1218 var
->transp
.length
= 0;
1220 case CRTC_PIX_WIDTH_15BPP
: /* RGB 555 */
1222 var
->red
.offset
= 10;
1223 var
->red
.length
= 5;
1224 var
->green
.offset
= 5;
1225 var
->green
.length
= 5;
1226 var
->blue
.offset
= 0;
1227 var
->blue
.length
= 5;
1228 var
->transp
.offset
= 0;
1229 var
->transp
.length
= 0;
1231 case CRTC_PIX_WIDTH_16BPP
: /* RGB 565 */
1233 var
->red
.offset
= 11;
1234 var
->red
.length
= 5;
1235 var
->green
.offset
= 5;
1236 var
->green
.length
= 6;
1237 var
->blue
.offset
= 0;
1238 var
->blue
.length
= 5;
1239 var
->transp
.offset
= 0;
1240 var
->transp
.length
= 0;
1242 case CRTC_PIX_WIDTH_24BPP
: /* RGB 888 */
1244 var
->red
.offset
= 16;
1245 var
->red
.length
= 8;
1246 var
->green
.offset
= 8;
1247 var
->green
.length
= 8;
1248 var
->blue
.offset
= 0;
1249 var
->blue
.length
= 8;
1250 var
->transp
.offset
= 0;
1251 var
->transp
.length
= 0;
1253 case CRTC_PIX_WIDTH_32BPP
: /* ARGB 8888 */
1255 var
->red
.offset
= 16;
1256 var
->red
.length
= 8;
1257 var
->green
.offset
= 8;
1258 var
->green
.length
= 8;
1259 var
->blue
.offset
= 0;
1260 var
->blue
.length
= 8;
1261 var
->transp
.offset
= 24;
1262 var
->transp
.length
= 8;
1265 PRINTKE("Invalid pixel width\n");
1272 var
->xres_virtual
= crtc
->vxres
;
1273 var
->yres_virtual
= crtc
->vyres
;
1274 var
->bits_per_pixel
= bpp
;
1275 var
->left_margin
= left
;
1276 var
->right_margin
= right
;
1277 var
->upper_margin
= upper
;
1278 var
->lower_margin
= lower
;
1279 var
->hsync_len
= hslen
;
1280 var
->vsync_len
= vslen
;
1282 var
->vmode
= FB_VMODE_NONINTERLACED
;
1284 * In double scan mode, the vertical parameters are doubled,
1285 * so we need to halve them to get the right values.
1286 * In interlaced mode the values are already correct,
1287 * so no correction is necessary.
1290 var
->vmode
= FB_VMODE_INTERLACED
;
1293 var
->vmode
= FB_VMODE_DOUBLE
;
1295 var
->upper_margin
>>= 1;
1296 var
->lower_margin
>>= 1;
1297 var
->vsync_len
>>= 1;
1303 /* ------------------------------------------------------------------------- */
1305 static int atyfb_set_par(struct fb_info
*info
)
1307 struct atyfb_par
*par
= (struct atyfb_par
*) info
->par
;
1308 struct fb_var_screeninfo
*var
= &info
->var
;
1312 struct fb_var_screeninfo debug
;
1318 err
= aty_var_to_crtc(info
, var
, &par
->crtc
);
1322 pixclock
= atyfb_get_pixclock(var
, par
);
1324 if (pixclock
== 0) {
1325 PRINTKE("Invalid pixclock\n");
1328 err
= par
->pll_ops
->var_to_pll(info
, pixclock
,
1329 var
->bits_per_pixel
, &par
->pll
);
1334 par
->accel_flags
= var
->accel_flags
; /* hack */
1336 if (var
->accel_flags
) {
1337 atyfb_ops
.fb_sync
= atyfb_sync
;
1338 info
->flags
&= ~FBINFO_HWACCEL_DISABLED
;
1340 atyfb_ops
.fb_sync
= NULL
;
1341 info
->flags
|= FBINFO_HWACCEL_DISABLED
;
1344 if (par
->blitter_may_be_busy
)
1347 aty_set_crtc(par
, &par
->crtc
);
1348 par
->dac_ops
->set_dac(info
, &par
->pll
,
1349 var
->bits_per_pixel
, par
->accel_flags
);
1350 par
->pll_ops
->set_pll(info
, &par
->pll
);
1353 if (par
->pll_ops
&& par
->pll_ops
->pll_to_var
)
1354 pixclock_in_ps
= par
->pll_ops
->pll_to_var(info
, &par
->pll
);
1358 if (0 == pixclock_in_ps
) {
1359 PRINTKE("ALERT ops->pll_to_var get 0\n");
1360 pixclock_in_ps
= pixclock
;
1363 memset(&debug
, 0, sizeof(debug
));
1364 if (!aty_crtc_to_var(&par
->crtc
, &debug
)) {
1365 u32 hSync
, vRefresh
;
1366 u32 h_disp
, h_sync_strt
, h_sync_end
, h_total
;
1367 u32 v_disp
, v_sync_strt
, v_sync_end
, v_total
;
1369 h_disp
= debug
.xres
;
1370 h_sync_strt
= h_disp
+ debug
.right_margin
;
1371 h_sync_end
= h_sync_strt
+ debug
.hsync_len
;
1372 h_total
= h_sync_end
+ debug
.left_margin
;
1373 v_disp
= debug
.yres
;
1374 v_sync_strt
= v_disp
+ debug
.lower_margin
;
1375 v_sync_end
= v_sync_strt
+ debug
.vsync_len
;
1376 v_total
= v_sync_end
+ debug
.upper_margin
;
1378 hSync
= 1000000000 / (pixclock_in_ps
* h_total
);
1379 vRefresh
= (hSync
* 1000) / v_total
;
1380 if (par
->crtc
.gen_cntl
& CRTC_INTERLACE_EN
)
1382 if (par
->crtc
.gen_cntl
& CRTC_DBL_SCAN_EN
)
1385 DPRINTK("atyfb_set_par\n");
1386 DPRINTK(" Set Visible Mode to %ix%i-%i\n",
1387 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1388 DPRINTK(" Virtual resolution %ix%i, "
1389 "pixclock_in_ps %i (calculated %i)\n",
1390 var
->xres_virtual
, var
->yres_virtual
,
1391 pixclock
, pixclock_in_ps
);
1392 DPRINTK(" Dot clock: %i MHz\n",
1393 1000000 / pixclock_in_ps
);
1394 DPRINTK(" Horizontal sync: %i kHz\n", hSync
);
1395 DPRINTK(" Vertical refresh: %i Hz\n", vRefresh
);
1396 DPRINTK(" x style: %i.%03i %i %i %i %i %i %i %i %i\n",
1397 1000000 / pixclock_in_ps
, 1000000 % pixclock_in_ps
,
1398 h_disp
, h_sync_strt
, h_sync_end
, h_total
,
1399 v_disp
, v_sync_strt
, v_sync_end
, v_total
);
1400 DPRINTK(" fb style: %i %i %i %i %i %i %i %i %i\n",
1402 debug
.left_margin
, h_disp
, debug
.right_margin
, debug
.hsync_len
,
1403 debug
.upper_margin
, v_disp
, debug
.lower_margin
, debug
.vsync_len
);
1407 if (!M64_HAS(INTEGRATED
)) {
1408 /* Don't forget MEM_CNTL */
1409 tmp
= aty_ld_le32(MEM_CNTL
, par
) & 0xf0ffffff;
1410 switch (var
->bits_per_pixel
) {
1421 aty_st_le32(MEM_CNTL
, tmp
, par
);
1423 tmp
= aty_ld_le32(MEM_CNTL
, par
) & 0xf00fffff;
1424 if (!M64_HAS(MAGIC_POSTDIV
))
1425 tmp
|= par
->mem_refresh_rate
<< 20;
1426 switch (var
->bits_per_pixel
) {
1438 if (M64_HAS(CT_BUS
)) {
1439 aty_st_le32(DAC_CNTL
, 0x87010184, par
);
1440 aty_st_le32(BUS_CNTL
, 0x680000f9, par
);
1441 } else if (M64_HAS(VT_BUS
)) {
1442 aty_st_le32(DAC_CNTL
, 0x87010184, par
);
1443 aty_st_le32(BUS_CNTL
, 0x680000f9, par
);
1444 } else if (M64_HAS(MOBIL_BUS
)) {
1445 aty_st_le32(DAC_CNTL
, 0x80010102, par
);
1446 aty_st_le32(BUS_CNTL
, 0x7b33a040 | (par
->aux_start
? BUS_APER_REG_DIS
: 0), par
);
1449 aty_st_le32(DAC_CNTL
, 0x86010102, par
);
1450 aty_st_le32(BUS_CNTL
, 0x7b23a040 | (par
->aux_start
? BUS_APER_REG_DIS
: 0), par
);
1451 aty_st_le32(EXT_MEM_CNTL
, aty_ld_le32(EXT_MEM_CNTL
, par
) | 0x5000001, par
);
1453 aty_st_le32(MEM_CNTL
, tmp
, par
);
1455 aty_st_8(DAC_MASK
, 0xff, par
);
1457 info
->fix
.line_length
= calc_line_length(par
, var
->xres_virtual
,
1458 var
->bits_per_pixel
);
1460 info
->fix
.visual
= var
->bits_per_pixel
<= 8 ?
1461 FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_DIRECTCOLOR
;
1463 /* Initialize the graphics engine */
1464 if (par
->accel_flags
& FB_ACCELF_TEXT
)
1465 aty_init_engine(par
, info
);
1467 #ifdef CONFIG_BOOTX_TEXT
1468 btext_update_display(info
->fix
.smem_start
,
1469 (((par
->crtc
.h_tot_disp
>> 16) & 0xff) + 1) * 8,
1470 ((par
->crtc
.v_tot_disp
>> 16) & 0x7ff) + 1,
1471 var
->bits_per_pixel
,
1472 par
->crtc
.vxres
* var
->bits_per_pixel
/ 8);
1473 #endif /* CONFIG_BOOTX_TEXT */
1476 /* dump non shadow CRTC, pll, LCD registers */
1479 /* CRTC registers */
1481 printk("debug atyfb: Mach64 non-shadow register values:");
1482 for (i
= 0; i
< 256; i
= i
+4) {
1485 printk("debug atyfb: 0x%04X: ", base
+ i
);
1487 pr_cont(" %08X", aty_ld_le32(i
, par
));
1491 #ifdef CONFIG_FB_ATY_CT
1494 printk("debug atyfb: Mach64 PLL register values:");
1495 for (i
= 0; i
< 64; i
++) {
1498 printk("debug atyfb: 0x%02X: ", base
+ i
);
1502 pr_cont("%02X", aty_ld_pll_ct(i
, par
));
1505 #endif /* CONFIG_FB_ATY_CT */
1507 #ifdef CONFIG_FB_ATY_GENERIC_LCD
1508 if (par
->lcd_table
!= 0) {
1511 printk("debug atyfb: LCD register values:");
1512 if (M64_HAS(LT_LCD_REGS
)) {
1513 for (i
= 0; i
<= POWER_MANAGEMENT
; i
++) {
1514 if (i
== EXT_VERT_STRETCH
)
1516 pr_cont("\ndebug atyfb: 0x%04X: ",
1518 pr_cont(" %08X", aty_ld_lcd(i
, par
));
1521 for (i
= 0; i
< 64; i
++) {
1523 pr_cont("\ndebug atyfb: 0x%02X: ",
1525 pr_cont(" %08X", aty_ld_lcd(i
, par
));
1530 #endif /* CONFIG_FB_ATY_GENERIC_LCD */
1536 static int atyfb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
1538 struct atyfb_par
*par
= (struct atyfb_par
*) info
->par
;
1544 memcpy(&pll
, &par
->pll
, sizeof(pll
));
1546 err
= aty_var_to_crtc(info
, var
, &crtc
);
1550 pixclock
= atyfb_get_pixclock(var
, par
);
1552 if (pixclock
== 0) {
1553 if (!(var
->activate
& FB_ACTIVATE_TEST
))
1554 PRINTKE("Invalid pixclock\n");
1557 err
= par
->pll_ops
->var_to_pll(info
, pixclock
,
1558 var
->bits_per_pixel
, &pll
);
1563 if (var
->accel_flags
& FB_ACCELF_TEXT
)
1564 info
->var
.accel_flags
= FB_ACCELF_TEXT
;
1566 info
->var
.accel_flags
= 0;
1568 aty_crtc_to_var(&crtc
, var
);
1569 var
->pixclock
= par
->pll_ops
->pll_to_var(info
, &pll
);
1573 static void set_off_pitch(struct atyfb_par
*par
, const struct fb_info
*info
)
1575 u32 xoffset
= info
->var
.xoffset
;
1576 u32 yoffset
= info
->var
.yoffset
;
1577 u32 line_length
= info
->fix
.line_length
;
1578 u32 bpp
= info
->var
.bits_per_pixel
;
1580 par
->crtc
.off_pitch
=
1581 ((yoffset
* line_length
+ xoffset
* bpp
/ 8) / 8) |
1582 ((line_length
/ bpp
) << 22);
1587 * Open/Release the frame buffer device
1590 static int atyfb_open(struct fb_info
*info
, int user
)
1592 struct atyfb_par
*par
= (struct atyfb_par
*) info
->par
;
1603 static irqreturn_t
aty_irq(int irq
, void *dev_id
)
1605 struct atyfb_par
*par
= dev_id
;
1609 spin_lock(&par
->int_lock
);
1611 int_cntl
= aty_ld_le32(CRTC_INT_CNTL
, par
);
1613 if (int_cntl
& CRTC_VBLANK_INT
) {
1614 /* clear interrupt */
1615 aty_st_le32(CRTC_INT_CNTL
, (int_cntl
& CRTC_INT_EN_MASK
) |
1616 CRTC_VBLANK_INT_AK
, par
);
1617 par
->vblank
.count
++;
1618 if (par
->vblank
.pan_display
) {
1619 par
->vblank
.pan_display
= 0;
1620 aty_st_le32(CRTC_OFF_PITCH
, par
->crtc
.off_pitch
, par
);
1622 wake_up_interruptible(&par
->vblank
.wait
);
1626 spin_unlock(&par
->int_lock
);
1628 return IRQ_RETVAL(handled
);
1631 static int aty_enable_irq(struct atyfb_par
*par
, int reenable
)
1635 if (!test_and_set_bit(0, &par
->irq_flags
)) {
1636 if (request_irq(par
->irq
, aty_irq
, IRQF_SHARED
, "atyfb", par
)) {
1637 clear_bit(0, &par
->irq_flags
);
1640 spin_lock_irq(&par
->int_lock
);
1641 int_cntl
= aty_ld_le32(CRTC_INT_CNTL
, par
) & CRTC_INT_EN_MASK
;
1642 /* clear interrupt */
1643 aty_st_le32(CRTC_INT_CNTL
, int_cntl
| CRTC_VBLANK_INT_AK
, par
);
1644 /* enable interrupt */
1645 aty_st_le32(CRTC_INT_CNTL
, int_cntl
| CRTC_VBLANK_INT_EN
, par
);
1646 spin_unlock_irq(&par
->int_lock
);
1647 } else if (reenable
) {
1648 spin_lock_irq(&par
->int_lock
);
1649 int_cntl
= aty_ld_le32(CRTC_INT_CNTL
, par
) & CRTC_INT_EN_MASK
;
1650 if (!(int_cntl
& CRTC_VBLANK_INT_EN
)) {
1651 printk("atyfb: someone disabled IRQ [%08x]\n",
1653 /* re-enable interrupt */
1654 aty_st_le32(CRTC_INT_CNTL
, int_cntl
|
1655 CRTC_VBLANK_INT_EN
, par
);
1657 spin_unlock_irq(&par
->int_lock
);
1663 static int aty_disable_irq(struct atyfb_par
*par
)
1667 if (test_and_clear_bit(0, &par
->irq_flags
)) {
1668 if (par
->vblank
.pan_display
) {
1669 par
->vblank
.pan_display
= 0;
1670 aty_st_le32(CRTC_OFF_PITCH
, par
->crtc
.off_pitch
, par
);
1672 spin_lock_irq(&par
->int_lock
);
1673 int_cntl
= aty_ld_le32(CRTC_INT_CNTL
, par
) & CRTC_INT_EN_MASK
;
1674 /* disable interrupt */
1675 aty_st_le32(CRTC_INT_CNTL
, int_cntl
& ~CRTC_VBLANK_INT_EN
, par
);
1676 spin_unlock_irq(&par
->int_lock
);
1677 free_irq(par
->irq
, par
);
1683 static int atyfb_release(struct fb_info
*info
, int user
)
1685 struct atyfb_par
*par
= (struct atyfb_par
*) info
->par
;
1701 was_mmaped
= par
->mmaped
;
1706 struct fb_var_screeninfo var
;
1709 * Now reset the default display config, we have
1710 * no idea what the program(s) which mmap'd the
1711 * chip did to the configuration, nor whether it
1712 * restored it correctly.
1716 var
.accel_flags
&= ~FB_ACCELF_TEXT
;
1718 var
.accel_flags
|= FB_ACCELF_TEXT
;
1719 if (var
.yres
== var
.yres_virtual
) {
1720 u32 videoram
= (info
->fix
.smem_len
- (PAGE_SIZE
<< 2));
1722 ((videoram
* 8) / var
.bits_per_pixel
) /
1724 if (var
.yres_virtual
< var
.yres
)
1725 var
.yres_virtual
= var
.yres
;
1729 aty_disable_irq(par
);
1735 * Pan or Wrap the Display
1737 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
1740 static int atyfb_pan_display(struct fb_var_screeninfo
*var
,
1741 struct fb_info
*info
)
1743 struct atyfb_par
*par
= (struct atyfb_par
*) info
->par
;
1744 u32 xres
, yres
, xoffset
, yoffset
;
1746 xres
= (((par
->crtc
.h_tot_disp
>> 16) & 0xff) + 1) * 8;
1747 yres
= ((par
->crtc
.v_tot_disp
>> 16) & 0x7ff) + 1;
1748 if (par
->crtc
.gen_cntl
& CRTC_DBL_SCAN_EN
)
1750 xoffset
= (var
->xoffset
+ 7) & ~7;
1751 yoffset
= var
->yoffset
;
1752 if (xoffset
+ xres
> par
->crtc
.vxres
||
1753 yoffset
+ yres
> par
->crtc
.vyres
)
1755 info
->var
.xoffset
= xoffset
;
1756 info
->var
.yoffset
= yoffset
;
1760 set_off_pitch(par
, info
);
1761 if ((var
->activate
& FB_ACTIVATE_VBL
) && !aty_enable_irq(par
, 0)) {
1762 par
->vblank
.pan_display
= 1;
1764 par
->vblank
.pan_display
= 0;
1765 aty_st_le32(CRTC_OFF_PITCH
, par
->crtc
.off_pitch
, par
);
1771 static int aty_waitforvblank(struct atyfb_par
*par
, u32 crtc
)
1773 struct aty_interrupt
*vbl
;
1785 ret
= aty_enable_irq(par
, 0);
1790 ret
= wait_event_interruptible_timeout(vbl
->wait
,
1791 count
!= vbl
->count
, HZ
/10);
1795 aty_enable_irq(par
, 1);
1804 #define ATYIO_CLKR 0x41545900 /* ATY\00 */
1805 #define ATYIO_CLKW 0x41545901 /* ATY\01 */
1811 u8 mclk_post_div
; /* 1,2,3,4,8 */
1812 u8 mclk_fb_mult
; /* 2 or 4 */
1813 u8 xclk_post_div
; /* 1,2,3,4,8 */
1815 u8 vclk_post_div
; /* 1,2,3,4,6,8,12 */
1816 u32 dsp_xclks_per_row
; /* 0-16383 */
1817 u32 dsp_loop_latency
; /* 0-15 */
1818 u32 dsp_precision
; /* 0-7 */
1819 u32 dsp_on
; /* 0-2047 */
1820 u32 dsp_off
; /* 0-2047 */
1823 #define ATYIO_FEATR 0x41545902 /* ATY\02 */
1824 #define ATYIO_FEATW 0x41545903 /* ATY\03 */
1827 static int atyfb_ioctl(struct fb_info
*info
, u_int cmd
, u_long arg
)
1829 struct atyfb_par
*par
= (struct atyfb_par
*) info
->par
;
1831 struct fbtype fbtyp
;
1837 fbtyp
.fb_type
= FBTYPE_PCI_GENERIC
;
1838 fbtyp
.fb_width
= par
->crtc
.vxres
;
1839 fbtyp
.fb_height
= par
->crtc
.vyres
;
1840 fbtyp
.fb_depth
= info
->var
.bits_per_pixel
;
1841 fbtyp
.fb_cmsize
= info
->cmap
.len
;
1842 fbtyp
.fb_size
= info
->fix
.smem_len
;
1843 if (copy_to_user((struct fbtype __user
*) arg
, &fbtyp
,
1847 #endif /* __sparc__ */
1849 case FBIO_WAITFORVSYNC
:
1853 if (get_user(crtc
, (__u32 __user
*) arg
))
1856 return aty_waitforvblank(par
, crtc
);
1859 #if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)
1861 if (M64_HAS(INTEGRATED
)) {
1862 struct atyclk clk
= { 0 };
1863 union aty_pll
*pll
= &par
->pll
;
1864 u32 dsp_config
= pll
->ct
.dsp_config
;
1865 u32 dsp_on_off
= pll
->ct
.dsp_on_off
;
1866 clk
.ref_clk_per
= par
->ref_clk_per
;
1867 clk
.pll_ref_div
= pll
->ct
.pll_ref_div
;
1868 clk
.mclk_fb_div
= pll
->ct
.mclk_fb_div
;
1869 clk
.mclk_post_div
= pll
->ct
.mclk_post_div_real
;
1870 clk
.mclk_fb_mult
= pll
->ct
.mclk_fb_mult
;
1871 clk
.xclk_post_div
= pll
->ct
.xclk_post_div_real
;
1872 clk
.vclk_fb_div
= pll
->ct
.vclk_fb_div
;
1873 clk
.vclk_post_div
= pll
->ct
.vclk_post_div_real
;
1874 clk
.dsp_xclks_per_row
= dsp_config
& 0x3fff;
1875 clk
.dsp_loop_latency
= (dsp_config
>> 16) & 0xf;
1876 clk
.dsp_precision
= (dsp_config
>> 20) & 7;
1877 clk
.dsp_off
= dsp_on_off
& 0x7ff;
1878 clk
.dsp_on
= (dsp_on_off
>> 16) & 0x7ff;
1879 if (copy_to_user((struct atyclk __user
*) arg
, &clk
,
1886 if (M64_HAS(INTEGRATED
)) {
1888 union aty_pll
*pll
= &par
->pll
;
1889 if (copy_from_user(&clk
, (struct atyclk __user
*) arg
,
1892 par
->ref_clk_per
= clk
.ref_clk_per
;
1893 pll
->ct
.pll_ref_div
= clk
.pll_ref_div
;
1894 pll
->ct
.mclk_fb_div
= clk
.mclk_fb_div
;
1895 pll
->ct
.mclk_post_div_real
= clk
.mclk_post_div
;
1896 pll
->ct
.mclk_fb_mult
= clk
.mclk_fb_mult
;
1897 pll
->ct
.xclk_post_div_real
= clk
.xclk_post_div
;
1898 pll
->ct
.vclk_fb_div
= clk
.vclk_fb_div
;
1899 pll
->ct
.vclk_post_div_real
= clk
.vclk_post_div
;
1900 pll
->ct
.dsp_config
= (clk
.dsp_xclks_per_row
& 0x3fff) |
1901 ((clk
.dsp_loop_latency
& 0xf) << 16) |
1902 ((clk
.dsp_precision
& 7) << 20);
1903 pll
->ct
.dsp_on_off
= (clk
.dsp_off
& 0x7ff) |
1904 ((clk
.dsp_on
& 0x7ff) << 16);
1905 /*aty_calc_pll_ct(info, &pll->ct);*/
1906 aty_set_pll_ct(info
, pll
);
1911 if (get_user(par
->features
, (u32 __user
*) arg
))
1915 if (put_user(par
->features
, (u32 __user
*) arg
))
1918 #endif /* DEBUG && CONFIG_FB_ATY_CT */
1925 static int atyfb_sync(struct fb_info
*info
)
1927 struct atyfb_par
*par
= (struct atyfb_par
*) info
->par
;
1929 if (par
->blitter_may_be_busy
)
1935 static int atyfb_mmap(struct fb_info
*info
, struct vm_area_struct
*vma
)
1937 struct atyfb_par
*par
= (struct atyfb_par
*) info
->par
;
1938 unsigned int size
, page
, map_size
= 0;
1939 unsigned long map_offset
= 0;
1946 if (vma
->vm_pgoff
> (~0UL >> PAGE_SHIFT
))
1949 off
= vma
->vm_pgoff
<< PAGE_SHIFT
;
1950 size
= vma
->vm_end
- vma
->vm_start
;
1952 /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
1954 if (((vma
->vm_pgoff
== 0) && (size
== info
->fix
.smem_len
)) ||
1955 ((off
== info
->fix
.smem_len
) && (size
== PAGE_SIZE
)))
1956 off
+= 0x8000000000000000UL
;
1958 vma
->vm_pgoff
= off
>> PAGE_SHIFT
; /* propagate off changes */
1960 /* Each page, see which map applies */
1961 for (page
= 0; page
< size
;) {
1963 for (i
= 0; par
->mmap_map
[i
].size
; i
++) {
1964 unsigned long start
= par
->mmap_map
[i
].voff
;
1965 unsigned long end
= start
+ par
->mmap_map
[i
].size
;
1966 unsigned long offset
= off
+ page
;
1973 map_size
= par
->mmap_map
[i
].size
- (offset
- start
);
1974 map_offset
= par
->mmap_map
[i
].poff
+ (offset
- start
);
1981 if (page
+ map_size
> size
)
1982 map_size
= size
- page
;
1984 pgprot_val(vma
->vm_page_prot
) &= ~(par
->mmap_map
[i
].prot_mask
);
1985 pgprot_val(vma
->vm_page_prot
) |= par
->mmap_map
[i
].prot_flag
;
1987 if (remap_pfn_range(vma
, vma
->vm_start
+ page
,
1988 map_offset
>> PAGE_SHIFT
, map_size
, vma
->vm_page_prot
))
2001 #endif /* __sparc__ */
2005 #if defined(CONFIG_PCI)
2007 #ifdef CONFIG_PPC_PMAC
2008 /* Power management routines. Those are used for PowerBook sleep.
2010 static int aty_power_mgmt(int sleep
, struct atyfb_par
*par
)
2015 pm
= aty_ld_lcd(POWER_MANAGEMENT
, par
);
2016 pm
= (pm
& ~PWR_MGT_MODE_MASK
) | PWR_MGT_MODE_REG
;
2017 aty_st_lcd(POWER_MANAGEMENT
, pm
, par
);
2018 pm
= aty_ld_lcd(POWER_MANAGEMENT
, par
);
2024 aty_st_lcd(POWER_MANAGEMENT
, pm
, par
);
2025 pm
= aty_ld_lcd(POWER_MANAGEMENT
, par
);
2027 pm
&= ~(PWR_BLON
| AUTO_PWR_UP
);
2029 aty_st_lcd(POWER_MANAGEMENT
, pm
, par
);
2030 pm
= aty_ld_lcd(POWER_MANAGEMENT
, par
);
2033 aty_st_lcd(POWER_MANAGEMENT
, pm
, par
);
2035 pm
= aty_ld_lcd(POWER_MANAGEMENT
, par
);
2037 if ((--timeout
) == 0)
2039 } while ((pm
& PWR_MGT_STATUS_MASK
) != PWR_MGT_STATUS_SUSPEND
);
2043 aty_st_lcd(POWER_MANAGEMENT
, pm
, par
);
2044 pm
= aty_ld_lcd(POWER_MANAGEMENT
, par
);
2047 pm
|= (PWR_BLON
| AUTO_PWR_UP
);
2048 aty_st_lcd(POWER_MANAGEMENT
, pm
, par
);
2049 pm
= aty_ld_lcd(POWER_MANAGEMENT
, par
);
2052 aty_st_lcd(POWER_MANAGEMENT
, pm
, par
);
2054 pm
= aty_ld_lcd(POWER_MANAGEMENT
, par
);
2056 if ((--timeout
) == 0)
2058 } while ((pm
& PWR_MGT_STATUS_MASK
) != 0);
2062 return timeout
? 0 : -EIO
;
2064 #endif /* CONFIG_PPC_PMAC */
2066 static int atyfb_pci_suspend_late(struct device
*dev
, pm_message_t state
)
2068 struct pci_dev
*pdev
= to_pci_dev(dev
);
2069 struct fb_info
*info
= pci_get_drvdata(pdev
);
2070 struct atyfb_par
*par
= (struct atyfb_par
*) info
->par
;
2072 if (state
.event
== pdev
->dev
.power
.power_state
.event
)
2077 fb_set_suspend(info
, 1);
2079 /* Idle & reset engine */
2081 aty_reset_engine(par
);
2083 /* Blank display and LCD */
2084 atyfb_blank(FB_BLANK_POWERDOWN
, info
);
2087 par
->lock_blank
= 1;
2090 * Because we may change PCI D state ourselves, we need to
2091 * first save the config space content so the core can
2092 * restore it properly on resume.
2095 #ifdef CONFIG_PPC_PMAC
2096 /* Set chip to "suspend" mode */
2097 if (machine_is(powermac
) && aty_power_mgmt(1, par
)) {
2099 par
->lock_blank
= 0;
2100 atyfb_blank(FB_BLANK_UNBLANK
, info
);
2101 fb_set_suspend(info
, 0);
2109 pdev
->dev
.power
.power_state
= state
;
2114 static int __maybe_unused
atyfb_pci_suspend(struct device
*dev
)
2116 return atyfb_pci_suspend_late(dev
, PMSG_SUSPEND
);
2119 static int __maybe_unused
atyfb_pci_hibernate(struct device
*dev
)
2121 return atyfb_pci_suspend_late(dev
, PMSG_HIBERNATE
);
2124 static int __maybe_unused
atyfb_pci_freeze(struct device
*dev
)
2126 return atyfb_pci_suspend_late(dev
, PMSG_FREEZE
);
2129 static void aty_resume_chip(struct fb_info
*info
)
2131 struct atyfb_par
*par
= info
->par
;
2133 aty_st_le32(MEM_CNTL
, par
->mem_cntl
, par
);
2135 if (par
->pll_ops
->resume_pll
)
2136 par
->pll_ops
->resume_pll(info
, &par
->pll
);
2139 aty_st_le32(BUS_CNTL
,
2140 aty_ld_le32(BUS_CNTL
, par
) | BUS_APER_REG_DIS
, par
);
2143 static int __maybe_unused
atyfb_pci_resume(struct device
*dev
)
2145 struct pci_dev
*pdev
= to_pci_dev(dev
);
2146 struct fb_info
*info
= pci_get_drvdata(pdev
);
2147 struct atyfb_par
*par
= (struct atyfb_par
*) info
->par
;
2149 if (pdev
->dev
.power
.power_state
.event
== PM_EVENT_ON
)
2155 * PCI state will have been restored by the core, so
2156 * we should be in D0 now with our config space fully
2160 #ifdef CONFIG_PPC_PMAC
2161 if (machine_is(powermac
) &&
2162 pdev
->dev
.power
.power_state
.event
== PM_EVENT_SUSPEND
)
2163 aty_power_mgmt(0, par
);
2166 aty_resume_chip(info
);
2170 /* Restore display */
2171 atyfb_set_par(info
);
2174 fb_set_suspend(info
, 0);
2177 par
->lock_blank
= 0;
2178 atyfb_blank(FB_BLANK_UNBLANK
, info
);
2182 pdev
->dev
.power
.power_state
= PMSG_ON
;
2187 static const struct dev_pm_ops atyfb_pci_pm_ops
= {
2188 #ifdef CONFIG_PM_SLEEP
2189 .suspend
= atyfb_pci_suspend
,
2190 .resume
= atyfb_pci_resume
,
2191 .freeze
= atyfb_pci_freeze
,
2192 .thaw
= atyfb_pci_resume
,
2193 .poweroff
= atyfb_pci_hibernate
,
2194 .restore
= atyfb_pci_resume
,
2195 #endif /* CONFIG_PM_SLEEP */
2198 #endif /* defined(CONFIG_PCI) */
2201 #ifdef CONFIG_FB_ATY_BACKLIGHT
2202 #define MAX_LEVEL 0xFF
2204 static int aty_bl_get_level_brightness(struct atyfb_par
*par
, int level
)
2206 struct fb_info
*info
= pci_get_drvdata(par
->pdev
);
2209 /* Get and convert the value */
2210 /* No locking of bl_curve since we read a single value */
2211 atylevel
= info
->bl_curve
[level
] * FB_BACKLIGHT_MAX
/ MAX_LEVEL
;
2215 else if (atylevel
> MAX_LEVEL
)
2216 atylevel
= MAX_LEVEL
;
2221 static int aty_bl_update_status(struct backlight_device
*bd
)
2223 struct atyfb_par
*par
= bl_get_data(bd
);
2224 unsigned int reg
= aty_ld_lcd(LCD_MISC_CNTL
, par
);
2225 int level
= backlight_get_brightness(bd
);
2227 reg
|= (BLMOD_EN
| BIASMOD_EN
);
2229 reg
&= ~BIAS_MOD_LEVEL_MASK
;
2230 reg
|= (aty_bl_get_level_brightness(par
, level
) << BIAS_MOD_LEVEL_SHIFT
);
2232 reg
&= ~BIAS_MOD_LEVEL_MASK
;
2233 reg
|= (aty_bl_get_level_brightness(par
, 0) << BIAS_MOD_LEVEL_SHIFT
);
2235 aty_st_lcd(LCD_MISC_CNTL
, reg
, par
);
2240 static const struct backlight_ops aty_bl_data
= {
2241 .update_status
= aty_bl_update_status
,
2244 static void aty_bl_init(struct atyfb_par
*par
)
2246 struct backlight_properties props
;
2247 struct fb_info
*info
= pci_get_drvdata(par
->pdev
);
2248 struct backlight_device
*bd
;
2251 #ifdef CONFIG_PMAC_BACKLIGHT
2252 if (!pmac_has_backlight_type("ati"))
2256 snprintf(name
, sizeof(name
), "atybl%d", info
->node
);
2258 memset(&props
, 0, sizeof(struct backlight_properties
));
2259 props
.type
= BACKLIGHT_RAW
;
2260 props
.max_brightness
= FB_BACKLIGHT_LEVELS
- 1;
2261 bd
= backlight_device_register(name
, info
->device
, par
, &aty_bl_data
,
2264 info
->bl_dev
= NULL
;
2265 printk(KERN_WARNING
"aty: Backlight registration failed\n");
2270 fb_bl_default_curve(info
, 0,
2271 0x3F * FB_BACKLIGHT_MAX
/ MAX_LEVEL
,
2272 0xFF * FB_BACKLIGHT_MAX
/ MAX_LEVEL
);
2274 bd
->props
.brightness
= bd
->props
.max_brightness
;
2275 bd
->props
.power
= BACKLIGHT_POWER_ON
;
2276 backlight_update_status(bd
);
2278 printk("aty: Backlight initialized (%s)\n", name
);
2287 static void aty_bl_exit(struct backlight_device
*bd
)
2289 backlight_device_unregister(bd
);
2290 printk("aty: Backlight unloaded\n");
2292 #endif /* CONFIG_PCI */
2294 #endif /* CONFIG_FB_ATY_BACKLIGHT */
2296 static void aty_calc_mem_refresh(struct atyfb_par
*par
, int xclk
)
2298 static const int ragepro_tbl
[] = {
2299 44, 50, 55, 66, 75, 80, 100
2301 static const int ragexl_tbl
[] = {
2302 50, 66, 75, 83, 90, 95, 100, 105,
2303 110, 115, 120, 125, 133, 143, 166
2305 const int *refresh_tbl
;
2308 if (M64_HAS(XL_MEM
)) {
2309 refresh_tbl
= ragexl_tbl
;
2310 size
= ARRAY_SIZE(ragexl_tbl
);
2312 refresh_tbl
= ragepro_tbl
;
2313 size
= ARRAY_SIZE(ragepro_tbl
);
2316 for (i
= 0; i
< size
; i
++) {
2317 if (xclk
< refresh_tbl
[i
])
2320 par
->mem_refresh_rate
= i
;
2327 static struct fb_info
*fb_list
= NULL
;
2329 #if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD)
2330 static int atyfb_get_timings_from_lcd(struct atyfb_par
*par
,
2331 struct fb_var_screeninfo
*var
)
2335 if (par
->lcd_table
!= 0 && (aty_ld_lcd(LCD_GEN_CNTL
, par
) & LCD_ON
)) {
2337 var
->xres
= var
->xres_virtual
= par
->lcd_hdisp
;
2338 var
->right_margin
= par
->lcd_right_margin
;
2339 var
->left_margin
= par
->lcd_hblank_len
-
2340 (par
->lcd_right_margin
+ par
->lcd_hsync_dly
+
2341 par
->lcd_hsync_len
);
2342 var
->hsync_len
= par
->lcd_hsync_len
+ par
->lcd_hsync_dly
;
2343 var
->yres
= var
->yres_virtual
= par
->lcd_vdisp
;
2344 var
->lower_margin
= par
->lcd_lower_margin
;
2345 var
->upper_margin
= par
->lcd_vblank_len
-
2346 (par
->lcd_lower_margin
+ par
->lcd_vsync_len
);
2347 var
->vsync_len
= par
->lcd_vsync_len
;
2348 var
->pixclock
= par
->lcd_pixclock
;
2354 #endif /* defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) */
2356 static int aty_init(struct fb_info
*info
)
2358 struct atyfb_par
*par
= (struct atyfb_par
*) info
->par
;
2359 const char *ramname
= NULL
, *xtal
;
2360 int gtb_memsize
, has_var
= 0;
2361 struct fb_var_screeninfo var
;
2367 init_waitqueue_head(&par
->vblank
.wait
);
2368 spin_lock_init(&par
->int_lock
);
2370 #ifdef CONFIG_FB_ATY_GX
2371 if (!M64_HAS(INTEGRATED
)) {
2373 u8 dac_subtype
, clk_type
;
2374 stat0
= aty_ld_le32(CNFG_STAT0
, par
);
2375 par
->bus_type
= (stat0
>> 0) & 0x07;
2376 par
->ram_type
= (stat0
>> 3) & 0x07;
2377 ramname
= aty_gx_ram
[par
->ram_type
];
2378 /* FIXME: clockchip/RAMDAC probing? */
2380 clk_type
= CLK_ATI18818_1
;
2381 dac_type
= (stat0
>> 9) & 0x07;
2382 if (dac_type
== 0x07)
2383 dac_subtype
= DAC_ATT20C408
;
2385 dac_subtype
= (aty_ld_8(SCRATCH_REG1
+ 1, par
) & 0xF0) | dac_type
;
2387 dac_subtype
= DAC_IBMRGB514
;
2388 clk_type
= CLK_IBMRGB514
;
2390 switch (dac_subtype
) {
2392 par
->dac_ops
= &aty_dac_ibm514
;
2395 case DAC_ATI68860_B
:
2396 case DAC_ATI68860_C
:
2397 par
->dac_ops
= &aty_dac_ati68860b
;
2401 par
->dac_ops
= &aty_dac_att21c498
;
2405 PRINTKI("aty_init: DAC type not implemented yet!\n");
2406 par
->dac_ops
= &aty_dac_unsupported
;
2411 case CLK_ATI18818_1
:
2412 par
->pll_ops
= &aty_pll_ati18818_1
;
2416 par
->pll_ops
= &aty_pll_ibm514
;
2420 PRINTKI("aty_init: CLK type not implemented yet!");
2421 par
->pll_ops
= &aty_pll_unsupported
;
2425 #endif /* CONFIG_FB_ATY_GX */
2426 #ifdef CONFIG_FB_ATY_CT
2427 if (M64_HAS(INTEGRATED
)) {
2428 par
->dac_ops
= &aty_dac_ct
;
2429 par
->pll_ops
= &aty_pll_ct
;
2430 par
->bus_type
= PCI
;
2431 par
->ram_type
= (aty_ld_le32(CNFG_STAT0
, par
) & 0x07);
2432 if (M64_HAS(XL_MEM
))
2433 ramname
= aty_xl_ram
[par
->ram_type
];
2435 ramname
= aty_ct_ram
[par
->ram_type
];
2436 /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
2437 if (par
->pll_limits
.mclk
== 67 && par
->ram_type
< SDRAM
)
2438 par
->pll_limits
.mclk
= 63;
2439 /* Mobility + 32bit memory interface need halved XCLK. */
2440 if (M64_HAS(MOBIL_BUS
) && par
->ram_type
== SDRAM32
)
2441 par
->pll_limits
.xclk
= (par
->pll_limits
.xclk
+ 1) >> 1;
2444 #ifdef CONFIG_PPC_PMAC
2446 * The Apple iBook1 uses non-standard memory frequencies.
2447 * We detect it and set the frequency manually.
2449 if (of_machine_is_compatible("PowerBook2,1")) {
2450 par
->pll_limits
.mclk
= 70;
2451 par
->pll_limits
.xclk
= 53;
2455 /* Allow command line to override clocks. */
2457 par
->pll_limits
.pll_max
= pll
;
2459 par
->pll_limits
.mclk
= mclk
;
2461 par
->pll_limits
.xclk
= xclk
;
2463 aty_calc_mem_refresh(par
, par
->pll_limits
.xclk
);
2464 par
->pll_per
= 1000000/par
->pll_limits
.pll_max
;
2465 par
->mclk_per
= 1000000/par
->pll_limits
.mclk
;
2466 par
->xclk_per
= 1000000/par
->pll_limits
.xclk
;
2468 par
->ref_clk_per
= 1000000000000ULL / 14318180;
2471 #ifdef CONFIG_FB_ATY_CT
2472 if (M64_HAS(GTB_DSP
)) {
2473 u8 pll_ref_div
= aty_ld_pll_ct(PLL_REF_DIV
, par
);
2477 diff1
= 510 * 14 / pll_ref_div
- par
->pll_limits
.pll_max
;
2478 diff2
= 510 * 29 / pll_ref_div
- par
->pll_limits
.pll_max
;
2483 if (diff2
< diff1
) {
2484 par
->ref_clk_per
= 1000000000000ULL / 29498928;
2489 #endif /* CONFIG_FB_ATY_CT */
2491 /* save previous video mode */
2492 aty_get_crtc(par
, &par
->saved_crtc
);
2493 if (par
->pll_ops
->get_pll
)
2494 par
->pll_ops
->get_pll(info
, &par
->saved_pll
);
2496 par
->mem_cntl
= aty_ld_le32(MEM_CNTL
, par
);
2497 gtb_memsize
= M64_HAS(GTB_DSP
);
2499 /* 0xF used instead of MEM_SIZE_ALIAS */
2500 switch (par
->mem_cntl
& 0xF) {
2502 info
->fix
.smem_len
= 0x80000;
2505 info
->fix
.smem_len
= 0x100000;
2507 case MEM_SIZE_2M_GTB
:
2508 info
->fix
.smem_len
= 0x200000;
2510 case MEM_SIZE_4M_GTB
:
2511 info
->fix
.smem_len
= 0x400000;
2513 case MEM_SIZE_6M_GTB
:
2514 info
->fix
.smem_len
= 0x600000;
2516 case MEM_SIZE_8M_GTB
:
2517 info
->fix
.smem_len
= 0x800000;
2520 info
->fix
.smem_len
= 0x80000;
2522 switch (par
->mem_cntl
& MEM_SIZE_ALIAS
) {
2524 info
->fix
.smem_len
= 0x80000;
2527 info
->fix
.smem_len
= 0x100000;
2530 info
->fix
.smem_len
= 0x200000;
2533 info
->fix
.smem_len
= 0x400000;
2536 info
->fix
.smem_len
= 0x600000;
2539 info
->fix
.smem_len
= 0x800000;
2542 info
->fix
.smem_len
= 0x80000;
2545 if (M64_HAS(MAGIC_VRAM_SIZE
)) {
2546 if (aty_ld_le32(CNFG_STAT1
, par
) & 0x40000000)
2547 info
->fix
.smem_len
+= 0x400000;
2551 info
->fix
.smem_len
= vram
* 1024;
2552 par
->mem_cntl
&= ~(gtb_memsize
? 0xF : MEM_SIZE_ALIAS
);
2553 if (info
->fix
.smem_len
<= 0x80000)
2554 par
->mem_cntl
|= MEM_SIZE_512K
;
2555 else if (info
->fix
.smem_len
<= 0x100000)
2556 par
->mem_cntl
|= MEM_SIZE_1M
;
2557 else if (info
->fix
.smem_len
<= 0x200000)
2558 par
->mem_cntl
|= gtb_memsize
? MEM_SIZE_2M_GTB
: MEM_SIZE_2M
;
2559 else if (info
->fix
.smem_len
<= 0x400000)
2560 par
->mem_cntl
|= gtb_memsize
? MEM_SIZE_4M_GTB
: MEM_SIZE_4M
;
2561 else if (info
->fix
.smem_len
<= 0x600000)
2562 par
->mem_cntl
|= gtb_memsize
? MEM_SIZE_6M_GTB
: MEM_SIZE_6M
;
2564 par
->mem_cntl
|= gtb_memsize
? MEM_SIZE_8M_GTB
: MEM_SIZE_8M
;
2565 aty_st_le32(MEM_CNTL
, par
->mem_cntl
, par
);
2569 * Reg Block 0 (CT-compatible block) is at mmio_start
2570 * Reg Block 1 (multimedia extensions) is at mmio_start - 0x400
2573 info
->fix
.mmio_len
= 0x400;
2574 info
->fix
.accel
= FB_ACCEL_ATI_MACH64GX
;
2575 } else if (M64_HAS(CT
)) {
2576 info
->fix
.mmio_len
= 0x400;
2577 info
->fix
.accel
= FB_ACCEL_ATI_MACH64CT
;
2578 } else if (M64_HAS(VT
)) {
2579 info
->fix
.mmio_start
-= 0x400;
2580 info
->fix
.mmio_len
= 0x800;
2581 info
->fix
.accel
= FB_ACCEL_ATI_MACH64VT
;
2583 info
->fix
.mmio_start
-= 0x400;
2584 info
->fix
.mmio_len
= 0x800;
2585 info
->fix
.accel
= FB_ACCEL_ATI_MACH64GT
;
2588 PRINTKI("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK, %d MHz XCLK\n",
2589 info
->fix
.smem_len
== 0x80000 ? 512 : (info
->fix
.smem_len
>>20),
2590 info
->fix
.smem_len
== 0x80000 ? 'K' : 'M', ramname
, xtal
,
2591 par
->pll_limits
.pll_max
, par
->pll_limits
.mclk
,
2592 par
->pll_limits
.xclk
);
2594 #if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)
2595 if (M64_HAS(INTEGRATED
)) {
2597 printk("debug atyfb: BUS_CNTL DAC_CNTL MEM_CNTL "
2598 "EXT_MEM_CNTL CRTC_GEN_CNTL DSP_CONFIG "
2599 "DSP_ON_OFF CLOCK_CNTL\n"
2600 "debug atyfb: %08x %08x %08x "
2604 aty_ld_le32(BUS_CNTL
, par
),
2605 aty_ld_le32(DAC_CNTL
, par
),
2606 aty_ld_le32(MEM_CNTL
, par
),
2607 aty_ld_le32(EXT_MEM_CNTL
, par
),
2608 aty_ld_le32(CRTC_GEN_CNTL
, par
),
2609 aty_ld_le32(DSP_CONFIG
, par
),
2610 aty_ld_le32(DSP_ON_OFF
, par
),
2611 aty_ld_le32(CLOCK_CNTL
, par
));
2612 for (i
= 0; i
< 40; i
++)
2613 pr_cont(" %02x", aty_ld_pll_ct(i
, par
));
2617 if (par
->pll_ops
->init_pll
)
2618 par
->pll_ops
->init_pll(info
, &par
->pll
);
2619 if (par
->pll_ops
->resume_pll
)
2620 par
->pll_ops
->resume_pll(info
, &par
->pll
);
2622 aty_fudge_framebuffer_len(info
);
2625 * Disable register access through the linear aperture
2626 * if the auxiliary aperture is used so we can access
2627 * the full 8 MB of video RAM on 8 MB boards.
2630 aty_st_le32(BUS_CNTL
, aty_ld_le32(BUS_CNTL
, par
) |
2631 BUS_APER_REG_DIS
, par
);
2635 * Only the ioremap_wc()'d area will get WC here
2636 * since ioremap_uc() was used on the entire PCI BAR.
2638 par
->wc_cookie
= arch_phys_wc_add(par
->res_start
,
2641 info
->fbops
= &atyfb_ops
;
2642 info
->pseudo_palette
= par
->pseudo_palette
;
2643 info
->flags
= FBINFO_HWACCEL_IMAGEBLIT
|
2644 FBINFO_HWACCEL_FILLRECT
|
2645 FBINFO_HWACCEL_COPYAREA
|
2646 FBINFO_HWACCEL_YPAN
|
2649 #ifdef CONFIG_PMAC_BACKLIGHT
2650 if (M64_HAS(G3_PB_1_1
) && of_machine_is_compatible("PowerBook1,1")) {
2652 * these bits let the 101 powerbook
2653 * wake up from sleep -- paulus
2655 aty_st_lcd(POWER_MANAGEMENT
, aty_ld_lcd(POWER_MANAGEMENT
, par
) |
2656 USE_F32KHZ
| TRISTATE_MEM_EN
, par
);
2660 memset(&var
, 0, sizeof(var
));
2662 if (machine_is(powermac
)) {
2664 * FIXME: The NVRAM stuff should be put in a Mac-specific file,
2665 * as it applies to all Mac video cards
2668 if (mac_find_mode(&var
, info
, mode
, 8))
2671 if (default_vmode
== VMODE_CHOOSE
) {
2673 if (M64_HAS(G3_PB_1024x768
))
2674 /* G3 PowerBook with 1024x768 LCD */
2675 default_vmode
= VMODE_1024_768_60
;
2676 else if (of_machine_is_compatible("iMac"))
2677 default_vmode
= VMODE_1024_768_75
;
2678 else if (of_machine_is_compatible("PowerBook2,1"))
2679 /* iBook with 800x600 LCD */
2680 default_vmode
= VMODE_800_600_60
;
2682 default_vmode
= VMODE_640_480_67
;
2683 sense
= read_aty_sense(par
);
2684 PRINTKI("monitor sense=%x, mode %d\n",
2685 sense
, mac_map_monitor_sense(sense
));
2687 if (default_vmode
<= 0 || default_vmode
> VMODE_MAX
)
2688 default_vmode
= VMODE_640_480_60
;
2689 if (default_cmode
< CMODE_8
|| default_cmode
> CMODE_32
)
2690 default_cmode
= CMODE_8
;
2691 if (!mac_vmode_to_var(default_vmode
, default_cmode
,
2697 #endif /* !CONFIG_PPC */
2699 #if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD)
2700 if (!atyfb_get_timings_from_lcd(par
, &var
))
2704 if (mode
&& fb_find_mode(&var
, info
, mode
, NULL
, 0, &defmode
, 8))
2711 var
.accel_flags
&= ~FB_ACCELF_TEXT
;
2713 var
.accel_flags
|= FB_ACCELF_TEXT
;
2715 if (comp_sync
!= -1) {
2717 var
.sync
&= ~FB_SYNC_COMP_HIGH_ACT
;
2719 var
.sync
|= FB_SYNC_COMP_HIGH_ACT
;
2722 if (var
.yres
== var
.yres_virtual
) {
2723 u32 videoram
= (info
->fix
.smem_len
- (PAGE_SIZE
<< 2));
2724 var
.yres_virtual
= ((videoram
* 8) / var
.bits_per_pixel
) / var
.xres_virtual
;
2725 if (var
.yres_virtual
< var
.yres
)
2726 var
.yres_virtual
= var
.yres
;
2729 ret
= atyfb_check_var(&var
, info
);
2731 PRINTKE("can't set default video mode\n");
2735 #ifdef CONFIG_FB_ATY_CT
2736 if (!noaccel
&& M64_HAS(INTEGRATED
))
2737 aty_init_cursor(info
, &atyfb_ops
);
2738 #endif /* CONFIG_FB_ATY_CT */
2741 ret
= fb_alloc_cmap(&info
->cmap
, 256, 0);
2745 ret
= register_framebuffer(info
);
2747 fb_dealloc_cmap(&info
->cmap
);
2751 if (M64_HAS(MOBIL_BUS
) && backlight
) {
2752 #ifdef CONFIG_FB_ATY_BACKLIGHT
2759 PRINTKI("fb%d: %s frame buffer device on %s\n",
2760 info
->node
, info
->fix
.id
, par
->bus_type
== ISA
? "ISA" : "PCI");
2764 /* restore video mode */
2765 aty_set_crtc(par
, &par
->saved_crtc
);
2766 par
->pll_ops
->set_pll(info
, &par
->saved_pll
);
2767 arch_phys_wc_del(par
->wc_cookie
);
2772 #if defined(CONFIG_ATARI) && !defined(MODULE)
2773 static int store_video_par(char *video_str
, unsigned char m64_num
)
2776 unsigned long vmembase
, size
, guiregbase
;
2778 PRINTKI("store_video_par() '%s' \n", video_str
);
2780 if (!(p
= strsep(&video_str
, ";")) || !*p
)
2781 goto mach64_invalid
;
2782 vmembase
= simple_strtoul(p
, NULL
, 0);
2783 if (!(p
= strsep(&video_str
, ";")) || !*p
)
2784 goto mach64_invalid
;
2785 size
= simple_strtoul(p
, NULL
, 0);
2786 if (!(p
= strsep(&video_str
, ";")) || !*p
)
2787 goto mach64_invalid
;
2788 guiregbase
= simple_strtoul(p
, NULL
, 0);
2790 phys_vmembase
[m64_num
] = vmembase
;
2791 phys_size
[m64_num
] = size
;
2792 phys_guiregbase
[m64_num
] = guiregbase
;
2793 PRINTKI("stored them all: $%08lX $%08lX $%08lX \n", vmembase
, size
,
2798 phys_vmembase
[m64_num
] = 0;
2801 #endif /* CONFIG_ATARI && !MODULE */
2804 * Blank the display.
2807 static int atyfb_blank(int blank
, struct fb_info
*info
)
2809 struct atyfb_par
*par
= (struct atyfb_par
*) info
->par
;
2812 if (par
->lock_blank
|| par
->asleep
)
2815 #ifdef CONFIG_FB_ATY_GENERIC_LCD
2816 if (par
->lcd_table
&& blank
> FB_BLANK_NORMAL
&&
2817 (aty_ld_lcd(LCD_GEN_CNTL
, par
) & LCD_ON
)) {
2818 u32 pm
= aty_ld_lcd(POWER_MANAGEMENT
, par
);
2820 aty_st_lcd(POWER_MANAGEMENT
, pm
, par
);
2824 gen_cntl
= aty_ld_le32(CRTC_GEN_CNTL
, par
);
2825 gen_cntl
&= ~0x400004c;
2827 case FB_BLANK_UNBLANK
:
2829 case FB_BLANK_NORMAL
:
2830 gen_cntl
|= 0x4000040;
2832 case FB_BLANK_VSYNC_SUSPEND
:
2833 gen_cntl
|= 0x4000048;
2835 case FB_BLANK_HSYNC_SUSPEND
:
2836 gen_cntl
|= 0x4000044;
2838 case FB_BLANK_POWERDOWN
:
2839 gen_cntl
|= 0x400004c;
2842 aty_st_le32(CRTC_GEN_CNTL
, gen_cntl
, par
);
2844 #ifdef CONFIG_FB_ATY_GENERIC_LCD
2845 if (par
->lcd_table
&& blank
<= FB_BLANK_NORMAL
&&
2846 (aty_ld_lcd(LCD_GEN_CNTL
, par
) & LCD_ON
)) {
2847 u32 pm
= aty_ld_lcd(POWER_MANAGEMENT
, par
);
2849 aty_st_lcd(POWER_MANAGEMENT
, pm
, par
);
2856 static void aty_st_pal(u_int regno
, u_int red
, u_int green
, u_int blue
,
2857 const struct atyfb_par
*par
)
2859 aty_st_8(DAC_W_INDEX
, regno
, par
);
2860 aty_st_8(DAC_DATA
, red
, par
);
2861 aty_st_8(DAC_DATA
, green
, par
);
2862 aty_st_8(DAC_DATA
, blue
, par
);
2866 * Set a single color register. The values supplied are already
2867 * rounded down to the hardware's capabilities (according to the
2868 * entries in the var structure). Return != 0 for invalid regno.
2869 * !! 4 & 8 = PSEUDO, > 8 = DIRECTCOLOR
2872 static int atyfb_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
2873 u_int transp
, struct fb_info
*info
)
2875 struct atyfb_par
*par
= (struct atyfb_par
*) info
->par
;
2877 u32
*pal
= info
->pseudo_palette
;
2879 depth
= info
->var
.bits_per_pixel
;
2881 depth
= (info
->var
.green
.length
== 5) ? 15 : 16;
2887 (depth
== 16 && regno
> 63) ||
2888 (depth
== 15 && regno
> 31))
2895 par
->palette
[regno
].red
= red
;
2896 par
->palette
[regno
].green
= green
;
2897 par
->palette
[regno
].blue
= blue
;
2902 pal
[regno
] = (regno
<< 10) | (regno
<< 5) | regno
;
2905 pal
[regno
] = (regno
<< 11) | (regno
<< 5) | regno
;
2908 pal
[regno
] = (regno
<< 16) | (regno
<< 8) | regno
;
2911 i
= (regno
<< 8) | regno
;
2912 pal
[regno
] = (i
<< 16) | i
;
2917 i
= aty_ld_8(DAC_CNTL
, par
) & 0xfc;
2918 if (M64_HAS(EXTRA_BRIGHT
))
2919 i
|= 0x2; /* DAC_CNTL | 0x2 turns off the extra brightness for gt */
2920 aty_st_8(DAC_CNTL
, i
, par
);
2921 aty_st_8(DAC_MASK
, 0xff, par
);
2923 if (M64_HAS(INTEGRATED
)) {
2926 aty_st_pal(regno
<< 3, red
,
2927 par
->palette
[regno
<< 1].green
,
2929 red
= par
->palette
[regno
>> 1].red
;
2930 blue
= par
->palette
[regno
>> 1].blue
;
2932 } else if (depth
== 15) {
2934 for (i
= 0; i
< 8; i
++)
2935 aty_st_pal(regno
+ i
, red
, green
, blue
, par
);
2938 aty_st_pal(regno
, red
, green
, blue
, par
);
2947 static int atyfb_setup_sparc(struct pci_dev
*pdev
, struct fb_info
*info
,
2950 struct atyfb_par
*par
= info
->par
;
2951 struct device_node
*dp
;
2956 * Map memory-mapped registers.
2958 par
->ati_regbase
= (void *)addr
+ 0x7ffc00UL
;
2959 info
->fix
.mmio_start
= addr
+ 0x7ffc00UL
;
2962 * Map in big-endian aperture.
2964 info
->screen_base
= (char *) (addr
+ 0x800000UL
);
2965 info
->fix
.smem_start
= addr
+ 0x800000UL
;
2968 * Figure mmap addresses from PCI config space.
2969 * Split Framebuffer in big- and little-endian halfs.
2971 for (i
= 0; i
< 6 && pdev
->resource
[i
].start
; i
++)
2975 par
->mmap_map
= kcalloc(j
, sizeof(*par
->mmap_map
), GFP_ATOMIC
);
2976 if (!par
->mmap_map
) {
2977 PRINTKE("atyfb_setup_sparc() can't alloc mmap_map\n");
2981 for (i
= 0, j
= 2; i
< 6 && pdev
->resource
[i
].start
; i
++) {
2982 struct resource
*rp
= &pdev
->resource
[i
];
2983 int io
, breg
= PCI_BASE_ADDRESS_0
+ (i
<< 2);
2989 io
= (rp
->flags
& IORESOURCE_IO
);
2991 size
= rp
->end
- base
+ 1;
2993 pci_read_config_dword(pdev
, breg
, &pbase
);
2999 * Map the framebuffer a second time, this time without
3000 * the braindead _PAGE_IE setting. This is used by the
3001 * fixed Xserver, but we need to maintain the old mapping
3002 * to stay compatible with older ones...
3005 par
->mmap_map
[j
].voff
= (pbase
+ 0x10000000) & PAGE_MASK
;
3006 par
->mmap_map
[j
].poff
= base
& PAGE_MASK
;
3007 par
->mmap_map
[j
].size
= (size
+ ~PAGE_MASK
) & PAGE_MASK
;
3008 par
->mmap_map
[j
].prot_mask
= _PAGE_CACHE
;
3009 par
->mmap_map
[j
].prot_flag
= _PAGE_E
;
3014 * Here comes the old framebuffer mapping with _PAGE_IE
3015 * set for the big endian half of the framebuffer...
3018 par
->mmap_map
[j
].voff
= (pbase
+ 0x800000) & PAGE_MASK
;
3019 par
->mmap_map
[j
].poff
= (base
+ 0x800000) & PAGE_MASK
;
3020 par
->mmap_map
[j
].size
= 0x800000;
3021 par
->mmap_map
[j
].prot_mask
= _PAGE_CACHE
;
3022 par
->mmap_map
[j
].prot_flag
= _PAGE_E
| _PAGE_IE
;
3027 par
->mmap_map
[j
].voff
= pbase
& PAGE_MASK
;
3028 par
->mmap_map
[j
].poff
= base
& PAGE_MASK
;
3029 par
->mmap_map
[j
].size
= (size
+ ~PAGE_MASK
) & PAGE_MASK
;
3030 par
->mmap_map
[j
].prot_mask
= _PAGE_CACHE
;
3031 par
->mmap_map
[j
].prot_flag
= _PAGE_E
;
3035 ret
= correct_chipset(par
);
3039 if (IS_XL(pdev
->device
)) {
3041 * Fix PROMs idea of MEM_CNTL settings...
3043 mem
= aty_ld_le32(MEM_CNTL
, par
);
3044 chip_id
= aty_ld_le32(CNFG_CHIP_ID
, par
);
3045 if (((chip_id
& CFG_CHIP_TYPE
) == VT_CHIP_ID
) && !((chip_id
>> 24) & 1)) {
3046 switch (mem
& 0x0f) {
3048 mem
= (mem
& ~(0x0f)) | 2;
3051 mem
= (mem
& ~(0x0f)) | 3;
3054 mem
= (mem
& ~(0x0f)) | 4;
3057 mem
= (mem
& ~(0x0f)) | 5;
3062 if ((aty_ld_le32(CNFG_STAT0
, par
) & 7) >= SDRAM
)
3063 mem
&= ~(0x00700000);
3065 mem
&= ~(0xcf80e000); /* Turn off all undocumented bits. */
3066 aty_st_le32(MEM_CNTL
, mem
, par
);
3069 dp
= pci_device_to_OF_node(pdev
);
3070 if (dp
== of_console_device
) {
3071 struct fb_var_screeninfo
*var
= &default_var
;
3072 unsigned int N
, P
, Q
, M
, T
, R
;
3077 crtc
.vxres
= of_getintprop_default(dp
, "width", 1024);
3078 crtc
.vyres
= of_getintprop_default(dp
, "height", 768);
3079 var
->bits_per_pixel
= of_getintprop_default(dp
, "depth", 8);
3080 var
->xoffset
= var
->yoffset
= 0;
3081 crtc
.h_tot_disp
= aty_ld_le32(CRTC_H_TOTAL_DISP
, par
);
3082 crtc
.h_sync_strt_wid
= aty_ld_le32(CRTC_H_SYNC_STRT_WID
, par
);
3083 crtc
.v_tot_disp
= aty_ld_le32(CRTC_V_TOTAL_DISP
, par
);
3084 crtc
.v_sync_strt_wid
= aty_ld_le32(CRTC_V_SYNC_STRT_WID
, par
);
3085 crtc
.gen_cntl
= aty_ld_le32(CRTC_GEN_CNTL
, par
);
3086 aty_crtc_to_var(&crtc
, var
);
3089 * Read the PLL to figure actual Refresh Rate.
3091 clock_cntl
= aty_ld_8(CLOCK_CNTL
, par
);
3092 /* DPRINTK("CLOCK_CNTL %02x\n", clock_cntl); */
3093 for (i
= 0; i
< 16; i
++)
3094 pll_regs
[i
] = aty_ld_pll_ct(i
, par
);
3097 * PLL Reference Divider M:
3099 M
= pll_regs
[PLL_REF_DIV
];
3102 * PLL Feedback Divider N (Dependent on CLOCK_CNTL):
3104 N
= pll_regs
[VCLK0_FB_DIV
+ (clock_cntl
& 3)];
3107 * PLL Post Divider P (Dependent on CLOCK_CNTL):
3109 P
= aty_postdividers
[((pll_regs
[VCLK_POST_DIV
] >> ((clock_cntl
& 3) << 1)) & 3) |
3110 ((pll_regs
[PLL_EXT_CNTL
] >> (2 + (clock_cntl
& 3))) & 4)];
3124 * where R is XTALIN (= 14318 or 29498 kHz).
3126 if (IS_XL(pdev
->device
))
3133 default_var
.pixclock
= 1000000000 / T
;
3139 #else /* __sparc__ */
3142 #ifdef CONFIG_FB_ATY_GENERIC_LCD
3143 static void aty_init_lcd(struct atyfb_par
*par
, u32 bios_base
)
3145 u32 driv_inf_tab
, sig
;
3149 * To support an LCD panel, we should know it's dimensions and
3150 * it's desired pixel clock.
3151 * There are two ways to do it:
3152 * - Check the startup video mode and calculate the panel
3153 * size from it. This is unreliable.
3154 * - Read it from the driver information table in the video BIOS.
3156 /* Address of driver information table is at offset 0x78. */
3157 driv_inf_tab
= bios_base
+ *((u16
*)(bios_base
+0x78));
3159 /* Check for the driver information table signature. */
3160 sig
= *(u32
*)driv_inf_tab
;
3161 if ((sig
== 0x54504c24) || /* Rage LT pro */
3162 (sig
== 0x544d5224) || /* Rage mobility */
3163 (sig
== 0x54435824) || /* Rage XC */
3164 (sig
== 0x544c5824)) { /* Rage XL */
3165 PRINTKI("BIOS contains driver information table.\n");
3166 lcd_ofs
= *(u16
*)(driv_inf_tab
+ 10);
3169 par
->lcd_table
= bios_base
+ lcd_ofs
;
3172 if (par
->lcd_table
!= 0) {
3175 char refresh_rates_buf
[100];
3176 int id
, tech
, f
, i
, m
, default_refresh_rate
;
3181 u16 width
, height
, panel_type
, refresh_rates
;
3184 u8 lcd_refresh_rates
[16] = { 50, 56, 60, 67, 70, 72, 75, 76, 85,
3185 90, 100, 120, 140, 150, 160, 200 };
3187 * The most important information is the panel size at
3188 * offset 25 and 27, but there's some other nice information
3189 * which we print to the screen.
3191 id
= *(u8
*)par
->lcd_table
;
3192 strscpy(model
, (char *)par
->lcd_table
+1, sizeof(model
));
3194 width
= par
->lcd_width
= *(u16
*)(par
->lcd_table
+25);
3195 height
= par
->lcd_height
= *(u16
*)(par
->lcd_table
+27);
3196 panel_type
= *(u16
*)(par
->lcd_table
+29);
3198 txtcolour
= "colour";
3200 txtcolour
= "monochrome";
3202 txtdual
= "dual (split) ";
3205 tech
= (panel_type
>> 2) & 63;
3208 txtmonitor
= "passive matrix";
3211 txtmonitor
= "active matrix";
3214 txtmonitor
= "active addressed STN";
3220 txtmonitor
= "plasma";
3223 txtmonitor
= "unknown";
3225 format
= *(u32
*)(par
->lcd_table
+57);
3226 if (tech
== 0 || tech
== 2) {
3227 switch (format
& 7) {
3229 txtformat
= "12 bit interface";
3232 txtformat
= "16 bit interface";
3235 txtformat
= "24 bit interface";
3238 txtformat
= "unknown format";
3241 switch (format
& 7) {
3243 txtformat
= "8 colours";
3246 txtformat
= "512 colours";
3249 txtformat
= "4096 colours";
3252 txtformat
= "262144 colours (LT mode)";
3255 txtformat
= "16777216 colours";
3258 txtformat
= "262144 colours (FDPI-2 mode)";
3261 txtformat
= "unknown format";
3264 PRINTKI("%s%s %s monitor detected: %s\n",
3265 txtdual
, txtcolour
, txtmonitor
, model
);
3266 PRINTKI(" id=%d, %dx%d pixels, %s\n",
3267 id
, width
, height
, txtformat
);
3268 refresh_rates_buf
[0] = 0;
3269 refresh_rates
= *(u16
*)(par
->lcd_table
+62);
3272 for (i
= 0; i
< 16; i
++) {
3273 if (refresh_rates
& m
) {
3275 sprintf(strbuf
, "%d",
3276 lcd_refresh_rates
[i
]);
3279 sprintf(strbuf
, ",%d",
3280 lcd_refresh_rates
[i
]);
3282 strcat(refresh_rates_buf
, strbuf
);
3286 default_refresh_rate
= (*(u8
*)(par
->lcd_table
+61) & 0xf0) >> 4;
3287 PRINTKI(" supports refresh rates [%s], default %d Hz\n",
3288 refresh_rates_buf
, lcd_refresh_rates
[default_refresh_rate
]);
3289 par
->lcd_refreshrate
= lcd_refresh_rates
[default_refresh_rate
];
3291 * We now need to determine the crtc parameters for the
3292 * LCD monitor. This is tricky, because they are not stored
3293 * individually in the BIOS. Instead, the BIOS contains a
3294 * table of display modes that work for this monitor.
3296 * The idea is that we search for a mode of the same dimensions
3297 * as the dimensions of the LCD monitor. Say our LCD monitor
3298 * is 800x600 pixels, we search for a 800x600 monitor.
3299 * The CRTC parameters we find here are the ones that we need
3300 * to use to simulate other resolutions on the LCD screen.
3302 lcdmodeptr
= (u16
*)(par
->lcd_table
+ 64);
3303 while (*lcdmodeptr
!= 0) {
3305 u16 mwidth
, mheight
, lcd_hsync_start
, lcd_vsync_start
;
3306 modeptr
= bios_base
+ *lcdmodeptr
;
3308 mwidth
= *((u16
*)(modeptr
+0));
3309 mheight
= *((u16
*)(modeptr
+2));
3311 if (mwidth
== width
&& mheight
== height
) {
3312 par
->lcd_pixclock
= 100000000 / *((u16
*)(modeptr
+9));
3313 par
->lcd_htotal
= *((u16
*)(modeptr
+17)) & 511;
3314 par
->lcd_hdisp
= *((u16
*)(modeptr
+19)) & 511;
3315 lcd_hsync_start
= *((u16
*)(modeptr
+21)) & 511;
3316 par
->lcd_hsync_dly
= (*((u16
*)(modeptr
+21)) >> 9) & 7;
3317 par
->lcd_hsync_len
= *((u8
*)(modeptr
+23)) & 63;
3319 par
->lcd_vtotal
= *((u16
*)(modeptr
+24)) & 2047;
3320 par
->lcd_vdisp
= *((u16
*)(modeptr
+26)) & 2047;
3321 lcd_vsync_start
= *((u16
*)(modeptr
+28)) & 2047;
3322 par
->lcd_vsync_len
= (*((u16
*)(modeptr
+28)) >> 11) & 31;
3324 par
->lcd_htotal
= (par
->lcd_htotal
+ 1) * 8;
3325 par
->lcd_hdisp
= (par
->lcd_hdisp
+ 1) * 8;
3326 lcd_hsync_start
= (lcd_hsync_start
+ 1) * 8;
3327 par
->lcd_hsync_len
= par
->lcd_hsync_len
* 8;
3333 par
->lcd_right_margin
= lcd_hsync_start
- par
->lcd_hdisp
;
3334 par
->lcd_lower_margin
= lcd_vsync_start
- par
->lcd_vdisp
;
3335 par
->lcd_hblank_len
= par
->lcd_htotal
- par
->lcd_hdisp
;
3336 par
->lcd_vblank_len
= par
->lcd_vtotal
- par
->lcd_vdisp
;
3342 if (*lcdmodeptr
== 0) {
3343 PRINTKE("LCD monitor CRTC parameters not found!!!\n");
3344 /* To do: Switch to CRT if possible. */
3346 PRINTKI(" LCD CRTC parameters: %d.%d %d %d %d %d %d %d %d %d\n",
3347 1000000 / par
->lcd_pixclock
, 1000000 % par
->lcd_pixclock
,
3349 par
->lcd_hdisp
+ par
->lcd_right_margin
,
3350 par
->lcd_hdisp
+ par
->lcd_right_margin
3351 + par
->lcd_hsync_dly
+ par
->lcd_hsync_len
,
3354 par
->lcd_vdisp
+ par
->lcd_lower_margin
,
3355 par
->lcd_vdisp
+ par
->lcd_lower_margin
+ par
->lcd_vsync_len
,
3357 PRINTKI(" : %d %d %d %d %d %d %d %d %d\n",
3359 par
->lcd_hblank_len
- (par
->lcd_right_margin
+
3360 par
->lcd_hsync_dly
+ par
->lcd_hsync_len
),
3362 par
->lcd_right_margin
,
3364 par
->lcd_vblank_len
- (par
->lcd_lower_margin
+ par
->lcd_vsync_len
),
3366 par
->lcd_lower_margin
,
3367 par
->lcd_vsync_len
);
3371 #endif /* CONFIG_FB_ATY_GENERIC_LCD */
3373 static int init_from_bios(struct atyfb_par
*par
)
3375 u32 bios_base
, rom_addr
;
3378 rom_addr
= 0xc0000 + ((aty_ld_le32(SCRATCH_REG1
, par
) & 0x7f) << 11);
3379 bios_base
= (unsigned long)ioremap(rom_addr
, 0x10000);
3381 /* The BIOS starts with 0xaa55. */
3382 if (*((u16
*)bios_base
) == 0xaa55) {
3385 u16 rom_table_offset
, freq_table_offset
;
3386 PLL_BLOCK_MACH64 pll_block
;
3388 PRINTKI("Mach64 BIOS is located at %x, mapped at %x.\n", rom_addr
, bios_base
);
3390 /* check for frequncy table */
3391 bios_ptr
= (u8
*)bios_base
;
3392 rom_table_offset
= (u16
)(bios_ptr
[0x48] | (bios_ptr
[0x49] << 8));
3393 freq_table_offset
= bios_ptr
[rom_table_offset
+ 16] | (bios_ptr
[rom_table_offset
+ 17] << 8);
3394 memcpy(&pll_block
, bios_ptr
+ freq_table_offset
, sizeof(PLL_BLOCK_MACH64
));
3396 PRINTKI("BIOS frequency table:\n");
3397 PRINTKI("PCLK_min_freq %d, PCLK_max_freq %d, ref_freq %d, ref_divider %d\n",
3398 pll_block
.PCLK_min_freq
, pll_block
.PCLK_max_freq
,
3399 pll_block
.ref_freq
, pll_block
.ref_divider
);
3400 PRINTKI("MCLK_pwd %d, MCLK_max_freq %d, XCLK_max_freq %d, SCLK_freq %d\n",
3401 pll_block
.MCLK_pwd
, pll_block
.MCLK_max_freq
,
3402 pll_block
.XCLK_max_freq
, pll_block
.SCLK_freq
);
3404 par
->pll_limits
.pll_min
= pll_block
.PCLK_min_freq
/100;
3405 par
->pll_limits
.pll_max
= pll_block
.PCLK_max_freq
/100;
3406 par
->pll_limits
.ref_clk
= pll_block
.ref_freq
/100;
3407 par
->pll_limits
.ref_div
= pll_block
.ref_divider
;
3408 par
->pll_limits
.sclk
= pll_block
.SCLK_freq
/100;
3409 par
->pll_limits
.mclk
= pll_block
.MCLK_max_freq
/100;
3410 par
->pll_limits
.mclk_pm
= pll_block
.MCLK_pwd
/100;
3411 par
->pll_limits
.xclk
= pll_block
.XCLK_max_freq
/100;
3412 #ifdef CONFIG_FB_ATY_GENERIC_LCD
3413 aty_init_lcd(par
, bios_base
);
3417 PRINTKE("no BIOS frequency table found, use parameters\n");
3420 iounmap((void __iomem
*)bios_base
);
3424 #endif /* __i386__ */
3426 static int atyfb_setup_generic(struct pci_dev
*pdev
, struct fb_info
*info
,
3429 struct atyfb_par
*par
= info
->par
;
3431 unsigned long raddr
;
3432 struct resource
*rrp
;
3435 raddr
= addr
+ 0x7ff000UL
;
3436 rrp
= &pdev
->resource
[2];
3437 if ((rrp
->flags
& IORESOURCE_MEM
) &&
3438 request_mem_region(rrp
->start
, resource_size(rrp
), "atyfb")) {
3439 par
->aux_start
= rrp
->start
;
3440 par
->aux_size
= resource_size(rrp
);
3442 PRINTKI("using auxiliary register aperture\n");
3445 info
->fix
.mmio_start
= raddr
;
3446 #if defined(__i386__) || defined(__ia64__)
3448 * By using strong UC we force the MTRR to never have an
3449 * effect on the MMIO region on both non-PAT and PAT systems.
3451 par
->ati_regbase
= ioremap_uc(info
->fix
.mmio_start
, 0x1000);
3453 par
->ati_regbase
= ioremap(info
->fix
.mmio_start
, 0x1000);
3455 if (par
->ati_regbase
== NULL
)
3458 info
->fix
.mmio_start
+= par
->aux_start
? 0x400 : 0xc00;
3459 par
->ati_regbase
+= par
->aux_start
? 0x400 : 0xc00;
3462 * Enable memory-space accesses using config-space
3465 pci_read_config_word(pdev
, PCI_COMMAND
, &tmp
);
3466 if (!(tmp
& PCI_COMMAND_MEMORY
)) {
3467 tmp
|= PCI_COMMAND_MEMORY
;
3468 pci_write_config_word(pdev
, PCI_COMMAND
, tmp
);
3471 /* Use the big-endian aperture */
3475 /* Map in frame buffer */
3476 info
->fix
.smem_start
= addr
;
3479 * The framebuffer is not always 8 MiB, that's just the size of the
3480 * PCI BAR. We temporarily abuse smem_len here to store the size
3481 * of the BAR. aty_init() will later correct it to match the actual
3484 * On devices that don't have the auxiliary register aperture, the
3485 * registers are housed at the top end of the framebuffer PCI BAR.
3486 * aty_fudge_framebuffer_len() is used to reduce smem_len to not
3487 * overlap with the registers.
3489 info
->fix
.smem_len
= 0x800000;
3491 aty_fudge_framebuffer_len(info
);
3493 info
->screen_base
= ioremap_wc(info
->fix
.smem_start
,
3494 info
->fix
.smem_len
);
3495 if (info
->screen_base
== NULL
) {
3497 goto atyfb_setup_generic_fail
;
3500 ret
= correct_chipset(par
);
3502 goto atyfb_setup_generic_fail
;
3504 ret
= init_from_bios(par
);
3506 goto atyfb_setup_generic_fail
;
3508 /* according to ATI, we should use clock 3 for acelerated mode */
3509 par
->clk_wr_offset
= 3;
3513 atyfb_setup_generic_fail
:
3514 iounmap(par
->ati_regbase
);
3515 par
->ati_regbase
= NULL
;
3516 if (info
->screen_base
) {
3517 iounmap(info
->screen_base
);
3518 info
->screen_base
= NULL
;
3523 #endif /* !__sparc__ */
3525 static int atyfb_pci_probe(struct pci_dev
*pdev
,
3526 const struct pci_device_id
*ent
)
3528 unsigned long addr
, res_start
, res_size
;
3529 struct fb_info
*info
;
3530 struct resource
*rp
;
3531 struct atyfb_par
*par
;
3534 rc
= aperture_remove_conflicting_pci_devices(pdev
, "atyfb");
3538 /* Enable device in PCI config */
3539 if (pci_enable_device(pdev
)) {
3540 PRINTKE("Cannot enable PCI device\n");
3544 /* Find which resource to use */
3545 rp
= &pdev
->resource
[0];
3546 if (rp
->flags
& IORESOURCE_IO
)
3547 rp
= &pdev
->resource
[1];
3553 res_start
= rp
->start
;
3554 res_size
= resource_size(rp
);
3555 if (!request_mem_region(res_start
, res_size
, "atyfb"))
3558 /* Allocate framebuffer */
3559 info
= framebuffer_alloc(sizeof(struct atyfb_par
), &pdev
->dev
);
3564 par
->bus_type
= PCI
;
3565 info
->fix
= atyfb_fix
;
3566 info
->device
= &pdev
->dev
;
3567 par
->pci_id
= pdev
->device
;
3568 par
->res_start
= res_start
;
3569 par
->res_size
= res_size
;
3570 par
->irq
= pdev
->irq
;
3573 /* Setup "info" structure */
3575 rc
= atyfb_setup_sparc(pdev
, info
, addr
);
3577 rc
= atyfb_setup_generic(pdev
, info
, addr
);
3580 goto err_release_mem
;
3582 pci_set_drvdata(pdev
, info
);
3584 /* Init chip & register framebuffer */
3585 rc
= aty_init(info
);
3587 goto err_release_io
;
3591 * Add /dev/fb mmap values.
3593 par
->mmap_map
[0].voff
= 0x8000000000000000UL
;
3594 par
->mmap_map
[0].poff
= (unsigned long) info
->screen_base
& PAGE_MASK
;
3595 par
->mmap_map
[0].size
= info
->fix
.smem_len
;
3596 par
->mmap_map
[0].prot_mask
= _PAGE_CACHE
;
3597 par
->mmap_map
[0].prot_flag
= _PAGE_E
;
3598 par
->mmap_map
[1].voff
= par
->mmap_map
[0].voff
+ info
->fix
.smem_len
;
3599 par
->mmap_map
[1].poff
= (long)par
->ati_regbase
& PAGE_MASK
;
3600 par
->mmap_map
[1].size
= PAGE_SIZE
;
3601 par
->mmap_map
[1].prot_mask
= _PAGE_CACHE
;
3602 par
->mmap_map
[1].prot_flag
= _PAGE_E
;
3603 #endif /* __sparc__ */
3605 mutex_lock(&reboot_lock
);
3608 mutex_unlock(&reboot_lock
);
3614 kfree(par
->mmap_map
);
3616 if (par
->ati_regbase
)
3617 iounmap(par
->ati_regbase
);
3618 if (info
->screen_base
)
3619 iounmap(info
->screen_base
);
3623 release_mem_region(par
->aux_start
, par
->aux_size
);
3625 release_mem_region(par
->res_start
, par
->res_size
);
3626 framebuffer_release(info
);
3631 #endif /* CONFIG_PCI */
3635 static int __init
atyfb_atari_probe(void)
3637 struct atyfb_par
*par
;
3638 struct fb_info
*info
;
3643 for (m64_num
= 0; m64_num
< mach64_count
; m64_num
++) {
3644 if (!phys_vmembase
[m64_num
] || !phys_size
[m64_num
] ||
3645 !phys_guiregbase
[m64_num
]) {
3646 PRINTKI("phys_*[%d] parameters not set => "
3647 "returning early. \n", m64_num
);
3651 info
= framebuffer_alloc(sizeof(struct atyfb_par
), NULL
);
3657 info
->fix
= atyfb_fix
;
3659 par
->irq
= (unsigned int) -1; /* something invalid */
3662 * Map the video memory (physical address given)
3663 * to somewhere in the kernel address space.
3665 info
->screen_base
= ioremap_wc(phys_vmembase
[m64_num
],
3666 phys_size
[m64_num
]);
3667 info
->fix
.smem_start
= (unsigned long)info
->screen_base
; /* Fake! */
3668 par
->ati_regbase
= ioremap(phys_guiregbase
[m64_num
], 0x10000) +
3670 info
->fix
.mmio_start
= (unsigned long)par
->ati_regbase
; /* Fake! */
3672 aty_st_le32(CLOCK_CNTL
, 0x12345678, par
);
3673 clock_r
= aty_ld_le32(CLOCK_CNTL
, par
);
3675 switch (clock_r
& 0x003F) {
3677 par
->clk_wr_offset
= 3; /* */
3680 par
->clk_wr_offset
= 2; /* Medusa ST-IO ISA Adapter etc. */
3683 par
->clk_wr_offset
= 1; /* */
3686 par
->clk_wr_offset
= 0; /* Panther 1 ISA Adapter (Gerald) */
3690 /* Fake pci_id for correct_chipset() */
3691 switch (aty_ld_le32(CNFG_CHIP_ID
, par
) & CFG_CHIP_TYPE
) {
3693 par
->pci_id
= PCI_CHIP_MACH64GX
;
3696 par
->pci_id
= PCI_CHIP_MACH64CX
;
3702 if (correct_chipset(par
) || aty_init(info
)) {
3703 iounmap(info
->screen_base
);
3704 iounmap(par
->ati_regbase
);
3705 framebuffer_release(info
);
3711 return num_found
? 0 : -ENXIO
;
3714 #endif /* CONFIG_ATARI */
3718 static void atyfb_remove(struct fb_info
*info
)
3720 struct atyfb_par
*par
= (struct atyfb_par
*) info
->par
;
3722 /* restore video mode */
3723 aty_set_crtc(par
, &par
->saved_crtc
);
3724 par
->pll_ops
->set_pll(info
, &par
->saved_pll
);
3726 #ifdef CONFIG_FB_ATY_BACKLIGHT
3727 if (M64_HAS(MOBIL_BUS
))
3728 aty_bl_exit(info
->bl_dev
);
3731 unregister_framebuffer(info
);
3733 arch_phys_wc_del(par
->wc_cookie
);
3736 if (par
->ati_regbase
)
3737 iounmap(par
->ati_regbase
);
3738 if (info
->screen_base
)
3739 iounmap(info
->screen_base
);
3741 if (info
->sprite
.addr
)
3742 iounmap(info
->sprite
.addr
);
3746 kfree(par
->mmap_map
);
3749 release_mem_region(par
->aux_start
, par
->aux_size
);
3752 release_mem_region(par
->res_start
, par
->res_size
);
3754 framebuffer_release(info
);
3758 static void atyfb_pci_remove(struct pci_dev
*pdev
)
3760 struct fb_info
*info
= pci_get_drvdata(pdev
);
3762 mutex_lock(&reboot_lock
);
3763 if (reboot_info
== info
)
3765 mutex_unlock(&reboot_lock
);
3770 static const struct pci_device_id atyfb_pci_tbl
[] = {
3771 #ifdef CONFIG_FB_ATY_GX
3772 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64GX
) },
3773 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64CX
) },
3774 #endif /* CONFIG_FB_ATY_GX */
3776 #ifdef CONFIG_FB_ATY_CT
3777 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64CT
) },
3778 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64ET
) },
3780 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64LT
) },
3782 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64VT
) },
3783 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64GT
) },
3785 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64VU
) },
3786 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64GU
) },
3788 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64LG
) },
3790 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64VV
) },
3792 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64GV
) },
3793 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64GW
) },
3794 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64GY
) },
3795 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64GZ
) },
3797 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64GB
) },
3798 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64GD
) },
3799 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64GI
) },
3800 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64GP
) },
3801 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64GQ
) },
3803 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64LB
) },
3804 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64LD
) },
3805 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64LI
) },
3806 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64LP
) },
3807 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64LQ
) },
3809 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64GM
) },
3810 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64GN
) },
3811 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64GO
) },
3812 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64GL
) },
3813 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64GR
) },
3814 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64GS
) },
3816 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64LM
) },
3817 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64LN
) },
3818 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64LR
) },
3819 { PCI_DEVICE(PCI_VENDOR_ID_ATI
, PCI_CHIP_MACH64LS
) },
3820 #endif /* CONFIG_FB_ATY_CT */
3824 MODULE_DEVICE_TABLE(pci
, atyfb_pci_tbl
);
3826 static struct pci_driver atyfb_driver
= {
3828 .id_table
= atyfb_pci_tbl
,
3829 .probe
= atyfb_pci_probe
,
3830 .remove
= atyfb_pci_remove
,
3831 .driver
.pm
= &atyfb_pci_pm_ops
,
3834 #endif /* CONFIG_PCI */
3837 static int __init
atyfb_setup(char *options
)
3841 if (!options
|| !*options
)
3844 while ((this_opt
= strsep(&options
, ",")) != NULL
) {
3845 if (!strncmp(this_opt
, "noaccel", 7)) {
3847 } else if (!strncmp(this_opt
, "nomtrr", 6)) {
3849 } else if (!strncmp(this_opt
, "vram:", 5))
3850 vram
= simple_strtoul(this_opt
+ 5, NULL
, 0);
3851 else if (!strncmp(this_opt
, "pll:", 4))
3852 pll
= simple_strtoul(this_opt
+ 4, NULL
, 0);
3853 else if (!strncmp(this_opt
, "mclk:", 5))
3854 mclk
= simple_strtoul(this_opt
+ 5, NULL
, 0);
3855 else if (!strncmp(this_opt
, "xclk:", 5))
3856 xclk
= simple_strtoul(this_opt
+5, NULL
, 0);
3857 else if (!strncmp(this_opt
, "comp_sync:", 10))
3858 comp_sync
= simple_strtoul(this_opt
+10, NULL
, 0);
3859 else if (!strncmp(this_opt
, "backlight:", 10))
3860 backlight
= simple_strtoul(this_opt
+10, NULL
, 0);
3862 else if (!strncmp(this_opt
, "vmode:", 6)) {
3863 unsigned int vmode
=
3864 simple_strtoul(this_opt
+ 6, NULL
, 0);
3865 if (vmode
> 0 && vmode
<= VMODE_MAX
)
3866 default_vmode
= vmode
;
3867 } else if (!strncmp(this_opt
, "cmode:", 6)) {
3868 unsigned int cmode
=
3869 simple_strtoul(this_opt
+ 6, NULL
, 0);
3873 default_cmode
= CMODE_8
;
3877 default_cmode
= CMODE_16
;
3881 default_cmode
= CMODE_32
;
3888 * Why do we need this silly Mach64 argument?
3889 * We are already here because of mach64= so its redundant.
3891 else if (MACH_IS_ATARI
3892 && (!strncmp(this_opt
, "Mach64:", 7))) {
3893 static unsigned char m64_num
;
3894 static char mach64_str
[80];
3895 strscpy(mach64_str
, this_opt
+ 7, sizeof(mach64_str
));
3896 if (!store_video_par(mach64_str
, m64_num
)) {
3898 mach64_count
= m64_num
;
3909 static int atyfb_reboot_notify(struct notifier_block
*nb
,
3910 unsigned long code
, void *unused
)
3912 struct atyfb_par
*par
;
3914 if (code
!= SYS_RESTART
)
3917 mutex_lock(&reboot_lock
);
3922 lock_fb_info(reboot_info
);
3924 par
= reboot_info
->par
;
3927 * HP OmniBook 500's BIOS doesn't like the state of the
3928 * hardware after atyfb has been used. Restore the hardware
3929 * to the original state to allow successful reboots.
3931 aty_set_crtc(par
, &par
->saved_crtc
);
3932 par
->pll_ops
->set_pll(reboot_info
, &par
->saved_pll
);
3934 unlock_fb_info(reboot_info
);
3936 mutex_unlock(&reboot_lock
);
3941 static struct notifier_block atyfb_reboot_notifier
= {
3942 .notifier_call
= atyfb_reboot_notify
,
3945 static const struct dmi_system_id atyfb_reboot_ids
[] __initconst
= {
3947 .ident
= "HP OmniBook 500",
3949 DMI_MATCH(DMI_SYS_VENDOR
, "Hewlett-Packard"),
3950 DMI_MATCH(DMI_PRODUCT_NAME
, "HP OmniBook PC"),
3951 DMI_MATCH(DMI_PRODUCT_VERSION
, "HP OmniBook 500 FA"),
3957 static bool registered_notifier
= false;
3959 static int __init
atyfb_init(void)
3961 int err1
= 1, err2
= 1;
3963 char *option
= NULL
;
3966 if (fb_modesetting_disabled("atyfb"))
3970 if (fb_get_options("atyfb", &option
))
3972 atyfb_setup(option
);
3976 err1
= pci_register_driver(&atyfb_driver
);
3979 err2
= atyfb_atari_probe();
3985 if (dmi_check_system(atyfb_reboot_ids
)) {
3986 register_reboot_notifier(&atyfb_reboot_notifier
);
3987 registered_notifier
= true;
3993 static void __exit
atyfb_exit(void)
3995 if (registered_notifier
)
3996 unregister_reboot_notifier(&atyfb_reboot_notifier
);
3999 pci_unregister_driver(&atyfb_driver
);
4003 module_init(atyfb_init
);
4004 module_exit(atyfb_exit
);
4006 MODULE_DESCRIPTION("FBDev driver for ATI Mach64 cards");
4007 MODULE_LICENSE("GPL");
4008 module_param(noaccel
, bool, 0);
4009 MODULE_PARM_DESC(noaccel
, "bool: disable acceleration");
4010 module_param(vram
, int, 0);
4011 MODULE_PARM_DESC(vram
, "int: override size of video ram");
4012 module_param(pll
, int, 0);
4013 MODULE_PARM_DESC(pll
, "int: override video clock");
4014 module_param(mclk
, int, 0);
4015 MODULE_PARM_DESC(mclk
, "int: override memory clock");
4016 module_param(xclk
, int, 0);
4017 MODULE_PARM_DESC(xclk
, "int: override accelerated engine clock");
4018 module_param(comp_sync
, int, 0);
4019 MODULE_PARM_DESC(comp_sync
, "Set composite sync signal to low (0) or high (1)");
4020 module_param(mode
, charp
, 0);
4021 MODULE_PARM_DESC(mode
, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
4022 module_param(nomtrr
, bool, 0);
4023 MODULE_PARM_DESC(nomtrr
, "bool: disable use of MTRR registers");