[PATCH] atyfb: Improve atyfb_atari_probe()
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / video / aty / atyfb_base.c
bloba9c73c257f3ab446a5ea1e15b2557530b2d47425
1 /*
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:
10 * - ATI Mach64
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
25 * Harry AC Eaton
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
33 * more details.
35 * Many thanks to Nitya from ATI devrel for support and patience !
38 /******************************************************************************
40 TODO:
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 ******************************************************************************/
52 #include <linux/module.h>
53 #include <linux/moduleparam.h>
54 #include <linux/kernel.h>
55 #include <linux/errno.h>
56 #include <linux/string.h>
57 #include <linux/mm.h>
58 #include <linux/slab.h>
59 #include <linux/vmalloc.h>
60 #include <linux/delay.h>
61 #include <linux/console.h>
62 #include <linux/fb.h>
63 #include <linux/init.h>
64 #include <linux/pci.h>
65 #include <linux/interrupt.h>
66 #include <linux/spinlock.h>
67 #include <linux/wait.h>
68 #include <linux/backlight.h>
70 #include <asm/io.h>
71 #include <asm/uaccess.h>
73 #include <video/mach64.h>
74 #include "atyfb.h"
75 #include "ati_ids.h"
77 #ifdef __powerpc__
78 #include <asm/machdep.h>
79 #include <asm/prom.h>
80 #include "../macmodes.h"
81 #endif
82 #ifdef __sparc__
83 #include <asm/pbm.h>
84 #include <asm/fbio.h>
85 #endif
87 #ifdef CONFIG_ADB_PMU
88 #include <linux/adb.h>
89 #include <linux/pmu.h>
90 #endif
91 #ifdef CONFIG_BOOTX_TEXT
92 #include <asm/btext.h>
93 #endif
94 #ifdef CONFIG_PMAC_BACKLIGHT
95 #include <asm/backlight.h>
96 #endif
97 #ifdef CONFIG_MTRR
98 #include <asm/mtrr.h>
99 #endif
102 * Debug flags.
104 #undef DEBUG
105 /*#define DEBUG*/
107 /* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */
108 /* - must be large enough to catch all GUI-Regs */
109 /* - must be aligned to a PAGE boundary */
110 #define GUI_RESERVE (1 * PAGE_SIZE)
112 /* FIXME: remove the FAIL definition */
113 #define FAIL(msg) do { \
114 if (!(var->activate & FB_ACTIVATE_TEST)) \
115 printk(KERN_CRIT "atyfb: " msg "\n"); \
116 return -EINVAL; \
117 } while (0)
118 #define FAIL_MAX(msg, x, _max_) do { \
119 if (x > _max_) { \
120 if (!(var->activate & FB_ACTIVATE_TEST)) \
121 printk(KERN_CRIT "atyfb: " msg " %x(%x)\n", x, _max_); \
122 return -EINVAL; \
124 } while (0)
125 #ifdef DEBUG
126 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "atyfb: " fmt, ## args)
127 #else
128 #define DPRINTK(fmt, args...)
129 #endif
131 #define PRINTKI(fmt, args...) printk(KERN_INFO "atyfb: " fmt, ## args)
132 #define PRINTKE(fmt, args...) printk(KERN_ERR "atyfb: " fmt, ## args)
134 #if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD)
135 static const u32 lt_lcd_regs[] = {
136 CONFIG_PANEL_LG,
137 LCD_GEN_CNTL_LG,
138 DSTN_CONTROL_LG,
139 HFB_PITCH_ADDR_LG,
140 HORZ_STRETCHING_LG,
141 VERT_STRETCHING_LG,
142 0, /* EXT_VERT_STRETCH */
143 LT_GIO_LG,
144 POWER_MANAGEMENT_LG
147 void aty_st_lcd(int index, u32 val, const struct atyfb_par *par)
149 if (M64_HAS(LT_LCD_REGS)) {
150 aty_st_le32(lt_lcd_regs[index], val, par);
151 } else {
152 unsigned long temp;
154 /* write addr byte */
155 temp = aty_ld_le32(LCD_INDEX, par);
156 aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par);
157 /* write the register value */
158 aty_st_le32(LCD_DATA, val, par);
162 u32 aty_ld_lcd(int index, const struct atyfb_par *par)
164 if (M64_HAS(LT_LCD_REGS)) {
165 return aty_ld_le32(lt_lcd_regs[index], par);
166 } else {
167 unsigned long temp;
169 /* write addr byte */
170 temp = aty_ld_le32(LCD_INDEX, par);
171 aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par);
172 /* read the register value */
173 return aty_ld_le32(LCD_DATA, par);
176 #endif /* defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD) */
178 #ifdef CONFIG_FB_ATY_GENERIC_LCD
180 * ATIReduceRatio --
182 * Reduce a fraction by factoring out the largest common divider of the
183 * fraction's numerator and denominator.
185 static void ATIReduceRatio(int *Numerator, int *Denominator)
187 int Multiplier, Divider, Remainder;
189 Multiplier = *Numerator;
190 Divider = *Denominator;
192 while ((Remainder = Multiplier % Divider))
194 Multiplier = Divider;
195 Divider = Remainder;
198 *Numerator /= Divider;
199 *Denominator /= Divider;
201 #endif
203 * The Hardware parameters for each card
206 struct pci_mmap_map {
207 unsigned long voff;
208 unsigned long poff;
209 unsigned long size;
210 unsigned long prot_flag;
211 unsigned long prot_mask;
214 static struct fb_fix_screeninfo atyfb_fix __devinitdata = {
215 .id = "ATY Mach64",
216 .type = FB_TYPE_PACKED_PIXELS,
217 .visual = FB_VISUAL_PSEUDOCOLOR,
218 .xpanstep = 8,
219 .ypanstep = 1,
223 * Frame buffer device API
226 static int atyfb_open(struct fb_info *info, int user);
227 static int atyfb_release(struct fb_info *info, int user);
228 static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
229 static int atyfb_set_par(struct fb_info *info);
230 static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
231 u_int transp, struct fb_info *info);
232 static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
233 static int atyfb_blank(int blank, struct fb_info *info);
234 static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg);
235 #ifdef __sparc__
236 static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma);
237 #endif
238 static int atyfb_sync(struct fb_info *info);
241 * Internal routines
244 static int aty_init(struct fb_info *info);
245 #ifdef CONFIG_ATARI
246 static int store_video_par(char *videopar, unsigned char m64_num);
247 #endif
249 static struct crtc saved_crtc;
250 static union aty_pll saved_pll;
251 static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc);
253 static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc);
254 static int aty_var_to_crtc(const struct fb_info *info, const struct fb_var_screeninfo *var, struct crtc *crtc);
255 static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *var);
256 static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info);
257 #ifdef CONFIG_PPC
258 static int read_aty_sense(const struct atyfb_par *par);
259 #endif
263 * Interface used by the world
266 static struct fb_var_screeninfo default_var = {
267 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
268 640, 480, 640, 480, 0, 0, 8, 0,
269 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
270 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
271 0, FB_VMODE_NONINTERLACED
274 static struct fb_videomode defmode = {
275 /* 640x480 @ 60 Hz, 31.5 kHz hsync */
276 NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
277 0, FB_VMODE_NONINTERLACED
280 static struct fb_ops atyfb_ops = {
281 .owner = THIS_MODULE,
282 .fb_open = atyfb_open,
283 .fb_release = atyfb_release,
284 .fb_check_var = atyfb_check_var,
285 .fb_set_par = atyfb_set_par,
286 .fb_setcolreg = atyfb_setcolreg,
287 .fb_pan_display = atyfb_pan_display,
288 .fb_blank = atyfb_blank,
289 .fb_ioctl = atyfb_ioctl,
290 .fb_fillrect = atyfb_fillrect,
291 .fb_copyarea = atyfb_copyarea,
292 .fb_imageblit = atyfb_imageblit,
293 #ifdef __sparc__
294 .fb_mmap = atyfb_mmap,
295 #endif
296 .fb_sync = atyfb_sync,
299 static int noaccel;
300 #ifdef CONFIG_MTRR
301 static int nomtrr;
302 #endif
303 static int vram;
304 static int pll;
305 static int mclk;
306 static int xclk;
307 static int comp_sync __devinitdata = -1;
308 static char *mode;
310 #ifdef CONFIG_PPC
311 static int default_vmode __devinitdata = VMODE_CHOOSE;
312 static int default_cmode __devinitdata = CMODE_CHOOSE;
314 module_param_named(vmode, default_vmode, int, 0);
315 MODULE_PARM_DESC(vmode, "int: video mode for mac");
316 module_param_named(cmode, default_cmode, int, 0);
317 MODULE_PARM_DESC(cmode, "int: color mode for mac");
318 #endif
320 #ifdef CONFIG_ATARI
321 static unsigned int mach64_count __devinitdata = 0;
322 static unsigned long phys_vmembase[FB_MAX] __devinitdata = { 0, };
323 static unsigned long phys_size[FB_MAX] __devinitdata = { 0, };
324 static unsigned long phys_guiregbase[FB_MAX] __devinitdata = { 0, };
325 #endif
327 /* top -> down is an evolution of mach64 chipset, any corrections? */
328 #define ATI_CHIP_88800GX (M64F_GX)
329 #define ATI_CHIP_88800CX (M64F_GX)
331 #define ATI_CHIP_264CT (M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO)
332 #define ATI_CHIP_264ET (M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO)
334 #define ATI_CHIP_264VT (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO)
335 #define ATI_CHIP_264GT (M64F_GT | M64F_INTEGRATED | M64F_MAGIC_FIFO | M64F_EXTRA_BRIGHT)
337 #define ATI_CHIP_264VTB (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP)
338 #define ATI_CHIP_264VT3 (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL)
339 #define ATI_CHIP_264VT4 (M64F_VT | M64F_INTEGRATED | M64F_GTB_DSP)
341 /* FIXME what is this chip? */
342 #define ATI_CHIP_264LT (M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP)
344 /* make sets shorter */
345 #define ATI_MODERN_SET (M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_EXTRA_BRIGHT)
347 #define ATI_CHIP_264GTB (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL)
348 /*#define ATI_CHIP_264GTDVD ?*/
349 #define ATI_CHIP_264LTG (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL)
351 #define ATI_CHIP_264GT2C (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE)
352 #define ATI_CHIP_264GTPRO (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
353 #define ATI_CHIP_264LTPRO (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
355 #define ATI_CHIP_264XL (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4)
356 #define ATI_CHIP_MOBILITY (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_MOBIL_BUS)
358 static struct {
359 u16 pci_id;
360 const char *name;
361 int pll, mclk, xclk, ecp_max;
362 u32 features;
363 } aty_chips[] __devinitdata = {
364 #ifdef CONFIG_FB_ATY_GX
365 /* Mach64 GX */
366 { PCI_CHIP_MACH64GX, "ATI888GX00 (Mach64 GX)", 135, 50, 50, 0, ATI_CHIP_88800GX },
367 { PCI_CHIP_MACH64CX, "ATI888CX00 (Mach64 CX)", 135, 50, 50, 0, ATI_CHIP_88800CX },
368 #endif /* CONFIG_FB_ATY_GX */
370 #ifdef CONFIG_FB_ATY_CT
371 { PCI_CHIP_MACH64CT, "ATI264CT (Mach64 CT)", 135, 60, 60, 0, ATI_CHIP_264CT },
372 { PCI_CHIP_MACH64ET, "ATI264ET (Mach64 ET)", 135, 60, 60, 0, ATI_CHIP_264ET },
374 /* FIXME what is this chip? */
375 { PCI_CHIP_MACH64LT, "ATI264LT (Mach64 LT)", 135, 63, 63, 0, ATI_CHIP_264LT },
377 { PCI_CHIP_MACH64VT, "ATI264VT (Mach64 VT)", 170, 67, 67, 80, ATI_CHIP_264VT },
378 { PCI_CHIP_MACH64GT, "3D RAGE (Mach64 GT)", 135, 63, 63, 80, ATI_CHIP_264GT },
380 { PCI_CHIP_MACH64VU, "ATI264VT3 (Mach64 VU)", 200, 67, 67, 80, ATI_CHIP_264VT3 },
381 { PCI_CHIP_MACH64GU, "3D RAGE II+ (Mach64 GU)", 200, 67, 67, 100, ATI_CHIP_264GTB },
383 { PCI_CHIP_MACH64LG, "3D RAGE LT (Mach64 LG)", 230, 63, 63, 100, ATI_CHIP_264LTG | M64F_LT_LCD_REGS | M64F_G3_PB_1024x768 },
385 { PCI_CHIP_MACH64VV, "ATI264VT4 (Mach64 VV)", 230, 83, 83, 100, ATI_CHIP_264VT4 },
387 { PCI_CHIP_MACH64GV, "3D RAGE IIC (Mach64 GV, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
388 { PCI_CHIP_MACH64GW, "3D RAGE IIC (Mach64 GW, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
389 { PCI_CHIP_MACH64GY, "3D RAGE IIC (Mach64 GY, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
390 { PCI_CHIP_MACH64GZ, "3D RAGE IIC (Mach64 GZ, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
392 { PCI_CHIP_MACH64GB, "3D RAGE PRO (Mach64 GB, BGA, AGP)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
393 { PCI_CHIP_MACH64GD, "3D RAGE PRO (Mach64 GD, BGA, AGP 1x)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
394 { PCI_CHIP_MACH64GI, "3D RAGE PRO (Mach64 GI, BGA, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO | M64F_MAGIC_VRAM_SIZE },
395 { PCI_CHIP_MACH64GP, "3D RAGE PRO (Mach64 GP, PQFP, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
396 { PCI_CHIP_MACH64GQ, "3D RAGE PRO (Mach64 GQ, PQFP, PCI, limited 3D)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
398 { PCI_CHIP_MACH64LB, "3D RAGE LT PRO (Mach64 LB, AGP)", 236, 75, 100, 135, ATI_CHIP_264LTPRO },
399 { PCI_CHIP_MACH64LD, "3D RAGE LT PRO (Mach64 LD, AGP)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
400 { 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 },
401 { PCI_CHIP_MACH64LP, "3D RAGE LT PRO (Mach64 LP, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO | M64F_G3_PB_1024x768 },
402 { PCI_CHIP_MACH64LQ, "3D RAGE LT PRO (Mach64 LQ, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
404 { PCI_CHIP_MACH64GM, "3D RAGE XL (Mach64 GM, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL },
405 { PCI_CHIP_MACH64GN, "3D RAGE XC (Mach64 GN, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL },
406 { PCI_CHIP_MACH64GO, "3D RAGE XL (Mach64 GO, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL },
407 { PCI_CHIP_MACH64GL, "3D RAGE XC (Mach64 GL, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL },
408 { PCI_CHIP_MACH64GR, "3D RAGE XL (Mach64 GR, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL | M64F_SDRAM_MAGIC_PLL },
409 { PCI_CHIP_MACH64GS, "3D RAGE XC (Mach64 GS, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL },
411 { PCI_CHIP_MACH64LM, "3D RAGE Mobility P/M (Mach64 LM, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
412 { PCI_CHIP_MACH64LN, "3D RAGE Mobility L (Mach64 LN, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
413 { PCI_CHIP_MACH64LR, "3D RAGE Mobility P/M (Mach64 LR, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
414 { PCI_CHIP_MACH64LS, "3D RAGE Mobility L (Mach64 LS, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
415 #endif /* CONFIG_FB_ATY_CT */
418 /* can not fail */
419 static int __devinit correct_chipset(struct atyfb_par *par)
421 u8 rev;
422 u16 type;
423 u32 chip_id;
424 const char *name;
425 int i;
427 for (i = ARRAY_SIZE(aty_chips) - 1; i >= 0; i--)
428 if (par->pci_id == aty_chips[i].pci_id)
429 break;
431 name = aty_chips[i].name;
432 par->pll_limits.pll_max = aty_chips[i].pll;
433 par->pll_limits.mclk = aty_chips[i].mclk;
434 par->pll_limits.xclk = aty_chips[i].xclk;
435 par->pll_limits.ecp_max = aty_chips[i].ecp_max;
436 par->features = aty_chips[i].features;
438 chip_id = aty_ld_le32(CONFIG_CHIP_ID, par);
439 type = chip_id & CFG_CHIP_TYPE;
440 rev = (chip_id & CFG_CHIP_REV) >> 24;
442 switch(par->pci_id) {
443 #ifdef CONFIG_FB_ATY_GX
444 case PCI_CHIP_MACH64GX:
445 if(type != 0x00d7)
446 return -ENODEV;
447 break;
448 case PCI_CHIP_MACH64CX:
449 if(type != 0x0057)
450 return -ENODEV;
451 break;
452 #endif
453 #ifdef CONFIG_FB_ATY_CT
454 case PCI_CHIP_MACH64VT:
455 switch (rev & 0x07) {
456 case 0x00:
457 switch (rev & 0xc0) {
458 case 0x00:
459 name = "ATI264VT (A3) (Mach64 VT)";
460 par->pll_limits.pll_max = 170;
461 par->pll_limits.mclk = 67;
462 par->pll_limits.xclk = 67;
463 par->pll_limits.ecp_max = 80;
464 par->features = ATI_CHIP_264VT;
465 break;
466 case 0x40:
467 name = "ATI264VT2 (A4) (Mach64 VT)";
468 par->pll_limits.pll_max = 200;
469 par->pll_limits.mclk = 67;
470 par->pll_limits.xclk = 67;
471 par->pll_limits.ecp_max = 80;
472 par->features = ATI_CHIP_264VT | M64F_MAGIC_POSTDIV;
473 break;
475 break;
476 case 0x01:
477 name = "ATI264VT3 (B1) (Mach64 VT)";
478 par->pll_limits.pll_max = 200;
479 par->pll_limits.mclk = 67;
480 par->pll_limits.xclk = 67;
481 par->pll_limits.ecp_max = 80;
482 par->features = ATI_CHIP_264VTB;
483 break;
484 case 0x02:
485 name = "ATI264VT3 (B2) (Mach64 VT)";
486 par->pll_limits.pll_max = 200;
487 par->pll_limits.mclk = 67;
488 par->pll_limits.xclk = 67;
489 par->pll_limits.ecp_max = 80;
490 par->features = ATI_CHIP_264VT3;
491 break;
493 break;
494 case PCI_CHIP_MACH64GT:
495 switch (rev & 0x07) {
496 case 0x01:
497 name = "3D RAGE II (Mach64 GT)";
498 par->pll_limits.pll_max = 170;
499 par->pll_limits.mclk = 67;
500 par->pll_limits.xclk = 67;
501 par->pll_limits.ecp_max = 80;
502 par->features = ATI_CHIP_264GTB;
503 break;
504 case 0x02:
505 name = "3D RAGE II+ (Mach64 GT)";
506 par->pll_limits.pll_max = 200;
507 par->pll_limits.mclk = 67;
508 par->pll_limits.xclk = 67;
509 par->pll_limits.ecp_max = 100;
510 par->features = ATI_CHIP_264GTB;
511 break;
513 break;
514 #endif
517 PRINTKI("%s [0x%04x rev 0x%02x]\n", name, type, rev);
518 return 0;
521 static char ram_dram[] __devinitdata = "DRAM";
522 static char ram_resv[] __devinitdata = "RESV";
523 #ifdef CONFIG_FB_ATY_GX
524 static char ram_vram[] __devinitdata = "VRAM";
525 #endif /* CONFIG_FB_ATY_GX */
526 #ifdef CONFIG_FB_ATY_CT
527 static char ram_edo[] __devinitdata = "EDO";
528 static char ram_sdram[] __devinitdata = "SDRAM (1:1)";
529 static char ram_sgram[] __devinitdata = "SGRAM (1:1)";
530 static char ram_sdram32[] __devinitdata = "SDRAM (2:1) (32-bit)";
531 static char ram_off[] __devinitdata = "OFF";
532 #endif /* CONFIG_FB_ATY_CT */
535 static u32 pseudo_palette[17];
537 #ifdef CONFIG_FB_ATY_GX
538 static char *aty_gx_ram[8] __devinitdata = {
539 ram_dram, ram_vram, ram_vram, ram_dram,
540 ram_dram, ram_vram, ram_vram, ram_resv
542 #endif /* CONFIG_FB_ATY_GX */
544 #ifdef CONFIG_FB_ATY_CT
545 static char *aty_ct_ram[8] __devinitdata = {
546 ram_off, ram_dram, ram_edo, ram_edo,
547 ram_sdram, ram_sgram, ram_sdram32, ram_resv
549 #endif /* CONFIG_FB_ATY_CT */
551 static u32 atyfb_get_pixclock(struct fb_var_screeninfo *var, struct atyfb_par *par)
553 u32 pixclock = var->pixclock;
554 #ifdef CONFIG_FB_ATY_GENERIC_LCD
555 u32 lcd_on_off;
556 par->pll.ct.xres = 0;
557 if (par->lcd_table != 0) {
558 lcd_on_off = aty_ld_lcd(LCD_GEN_CNTL, par);
559 if(lcd_on_off & LCD_ON) {
560 par->pll.ct.xres = var->xres;
561 pixclock = par->lcd_pixclock;
564 #endif
565 return pixclock;
568 #if defined(CONFIG_PPC)
571 * Apple monitor sense
574 static int __devinit read_aty_sense(const struct atyfb_par *par)
576 int sense, i;
578 aty_st_le32(GP_IO, 0x31003100, par); /* drive outputs high */
579 __delay(200);
580 aty_st_le32(GP_IO, 0, par); /* turn off outputs */
581 __delay(2000);
582 i = aty_ld_le32(GP_IO, par); /* get primary sense value */
583 sense = ((i & 0x3000) >> 3) | (i & 0x100);
585 /* drive each sense line low in turn and collect the other 2 */
586 aty_st_le32(GP_IO, 0x20000000, par); /* drive A low */
587 __delay(2000);
588 i = aty_ld_le32(GP_IO, par);
589 sense |= ((i & 0x1000) >> 7) | ((i & 0x100) >> 4);
590 aty_st_le32(GP_IO, 0x20002000, par); /* drive A high again */
591 __delay(200);
593 aty_st_le32(GP_IO, 0x10000000, par); /* drive B low */
594 __delay(2000);
595 i = aty_ld_le32(GP_IO, par);
596 sense |= ((i & 0x2000) >> 10) | ((i & 0x100) >> 6);
597 aty_st_le32(GP_IO, 0x10001000, par); /* drive B high again */
598 __delay(200);
600 aty_st_le32(GP_IO, 0x01000000, par); /* drive C low */
601 __delay(2000);
602 sense |= (aty_ld_le32(GP_IO, par) & 0x3000) >> 12;
603 aty_st_le32(GP_IO, 0, par); /* turn off outputs */
604 return sense;
607 #endif /* defined(CONFIG_PPC) */
609 /* ------------------------------------------------------------------------- */
612 * CRTC programming
615 static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc)
617 #ifdef CONFIG_FB_ATY_GENERIC_LCD
618 if (par->lcd_table != 0) {
619 if(!M64_HAS(LT_LCD_REGS)) {
620 crtc->lcd_index = aty_ld_le32(LCD_INDEX, par);
621 aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
623 crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par);
624 crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par);
627 /* switch to non shadow registers */
628 aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
629 ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
631 /* save stretching */
632 crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par);
633 crtc->vert_stretching = aty_ld_lcd(VERT_STRETCHING, par);
634 if (!M64_HAS(LT_LCD_REGS))
635 crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par);
637 #endif
638 crtc->h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
639 crtc->h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
640 crtc->v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
641 crtc->v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
642 crtc->vline_crnt_vline = aty_ld_le32(CRTC_VLINE_CRNT_VLINE, par);
643 crtc->off_pitch = aty_ld_le32(CRTC_OFF_PITCH, par);
644 crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
646 #ifdef CONFIG_FB_ATY_GENERIC_LCD
647 if (par->lcd_table != 0) {
648 /* switch to shadow registers */
649 aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |
650 SHADOW_EN | SHADOW_RW_EN, par);
652 crtc->shadow_h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
653 crtc->shadow_h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
654 crtc->shadow_v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
655 crtc->shadow_v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
657 aty_st_le32(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);
659 #endif /* CONFIG_FB_ATY_GENERIC_LCD */
662 static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc)
664 #ifdef CONFIG_FB_ATY_GENERIC_LCD
665 if (par->lcd_table != 0) {
666 /* stop CRTC */
667 aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~(CRTC_EXT_DISP_EN | CRTC_EN), par);
669 /* update non-shadow registers first */
670 aty_st_lcd(CONFIG_PANEL, crtc->lcd_config_panel, par);
671 aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
672 ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
674 /* temporarily disable stretching */
675 aty_st_lcd(HORZ_STRETCHING,
676 crtc->horz_stretching &
677 ~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN), par);
678 aty_st_lcd(VERT_STRETCHING,
679 crtc->vert_stretching &
680 ~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 |
681 VERT_STRETCH_USE0 | VERT_STRETCH_EN), par);
683 #endif
684 /* turn off CRT */
685 aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~CRTC_EN, par);
687 DPRINTK("setting up CRTC\n");
688 DPRINTK("set primary CRT to %ix%i %c%c composite %c\n",
689 ((((crtc->h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->v_tot_disp>>16) & 0x7ff) + 1),
690 (crtc->h_sync_strt_wid & 0x200000)?'N':'P', (crtc->v_sync_strt_wid & 0x200000)?'N':'P',
691 (crtc->gen_cntl & CRTC_CSYNC_EN)?'P':'N');
693 DPRINTK("CRTC_H_TOTAL_DISP: %x\n",crtc->h_tot_disp);
694 DPRINTK("CRTC_H_SYNC_STRT_WID: %x\n",crtc->h_sync_strt_wid);
695 DPRINTK("CRTC_V_TOTAL_DISP: %x\n",crtc->v_tot_disp);
696 DPRINTK("CRTC_V_SYNC_STRT_WID: %x\n",crtc->v_sync_strt_wid);
697 DPRINTK("CRTC_OFF_PITCH: %x\n", crtc->off_pitch);
698 DPRINTK("CRTC_VLINE_CRNT_VLINE: %x\n", crtc->vline_crnt_vline);
699 DPRINTK("CRTC_GEN_CNTL: %x\n",crtc->gen_cntl);
701 aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, par);
702 aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, par);
703 aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_tot_disp, par);
704 aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid, par);
705 aty_st_le32(CRTC_OFF_PITCH, crtc->off_pitch, par);
706 aty_st_le32(CRTC_VLINE_CRNT_VLINE, crtc->vline_crnt_vline, par);
708 aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl, par);
709 #if 0
710 FIXME
711 if (par->accel_flags & FB_ACCELF_TEXT)
712 aty_init_engine(par, info);
713 #endif
714 #ifdef CONFIG_FB_ATY_GENERIC_LCD
715 /* after setting the CRTC registers we should set the LCD registers. */
716 if (par->lcd_table != 0) {
717 /* switch to shadow registers */
718 aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |
719 (SHADOW_EN | SHADOW_RW_EN), par);
721 DPRINTK("set shadow CRT to %ix%i %c%c\n",
722 ((((crtc->shadow_h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->shadow_v_tot_disp>>16) & 0x7ff) + 1),
723 (crtc->shadow_h_sync_strt_wid & 0x200000)?'N':'P', (crtc->shadow_v_sync_strt_wid & 0x200000)?'N':'P');
725 DPRINTK("SHADOW CRTC_H_TOTAL_DISP: %x\n", crtc->shadow_h_tot_disp);
726 DPRINTK("SHADOW CRTC_H_SYNC_STRT_WID: %x\n", crtc->shadow_h_sync_strt_wid);
727 DPRINTK("SHADOW CRTC_V_TOTAL_DISP: %x\n", crtc->shadow_v_tot_disp);
728 DPRINTK("SHADOW CRTC_V_SYNC_STRT_WID: %x\n", crtc->shadow_v_sync_strt_wid);
730 aty_st_le32(CRTC_H_TOTAL_DISP, crtc->shadow_h_tot_disp, par);
731 aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->shadow_h_sync_strt_wid, par);
732 aty_st_le32(CRTC_V_TOTAL_DISP, crtc->shadow_v_tot_disp, par);
733 aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->shadow_v_sync_strt_wid, par);
735 /* restore CRTC selection & shadow state and enable stretching */
736 DPRINTK("LCD_GEN_CNTL: %x\n", crtc->lcd_gen_cntl);
737 DPRINTK("HORZ_STRETCHING: %x\n", crtc->horz_stretching);
738 DPRINTK("VERT_STRETCHING: %x\n", crtc->vert_stretching);
739 if(!M64_HAS(LT_LCD_REGS))
740 DPRINTK("EXT_VERT_STRETCH: %x\n", crtc->ext_vert_stretch);
742 aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);
743 aty_st_lcd(HORZ_STRETCHING, crtc->horz_stretching, par);
744 aty_st_lcd(VERT_STRETCHING, crtc->vert_stretching, par);
745 if(!M64_HAS(LT_LCD_REGS)) {
746 aty_st_lcd(EXT_VERT_STRETCH, crtc->ext_vert_stretch, par);
747 aty_ld_le32(LCD_INDEX, par);
748 aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
751 #endif /* CONFIG_FB_ATY_GENERIC_LCD */
754 static int aty_var_to_crtc(const struct fb_info *info,
755 const struct fb_var_screeninfo *var, struct crtc *crtc)
757 struct atyfb_par *par = (struct atyfb_par *) info->par;
758 u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
759 u32 sync, vmode, vdisplay;
760 u32 h_total, h_disp, h_sync_strt, h_sync_end, h_sync_dly, h_sync_wid, h_sync_pol;
761 u32 v_total, v_disp, v_sync_strt, v_sync_end, v_sync_wid, v_sync_pol, c_sync;
762 u32 pix_width, dp_pix_width, dp_chain_mask;
764 /* input */
765 xres = var->xres;
766 yres = var->yres;
767 vxres = var->xres_virtual;
768 vyres = var->yres_virtual;
769 xoffset = var->xoffset;
770 yoffset = var->yoffset;
771 bpp = var->bits_per_pixel;
772 if (bpp == 16)
773 bpp = (var->green.length == 5) ? 15 : 16;
774 sync = var->sync;
775 vmode = var->vmode;
777 /* convert (and round up) and validate */
778 if (vxres < xres + xoffset)
779 vxres = xres + xoffset;
780 h_disp = xres;
782 if (vyres < yres + yoffset)
783 vyres = yres + yoffset;
784 v_disp = yres;
786 if (bpp <= 8) {
787 bpp = 8;
788 pix_width = CRTC_PIX_WIDTH_8BPP;
789 dp_pix_width =
790 HOST_8BPP | SRC_8BPP | DST_8BPP |
791 BYTE_ORDER_LSB_TO_MSB;
792 dp_chain_mask = DP_CHAIN_8BPP;
793 } else if (bpp <= 15) {
794 bpp = 16;
795 pix_width = CRTC_PIX_WIDTH_15BPP;
796 dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP |
797 BYTE_ORDER_LSB_TO_MSB;
798 dp_chain_mask = DP_CHAIN_15BPP;
799 } else if (bpp <= 16) {
800 bpp = 16;
801 pix_width = CRTC_PIX_WIDTH_16BPP;
802 dp_pix_width = HOST_16BPP | SRC_16BPP | DST_16BPP |
803 BYTE_ORDER_LSB_TO_MSB;
804 dp_chain_mask = DP_CHAIN_16BPP;
805 } else if (bpp <= 24 && M64_HAS(INTEGRATED)) {
806 bpp = 24;
807 pix_width = CRTC_PIX_WIDTH_24BPP;
808 dp_pix_width =
809 HOST_8BPP | SRC_8BPP | DST_8BPP |
810 BYTE_ORDER_LSB_TO_MSB;
811 dp_chain_mask = DP_CHAIN_24BPP;
812 } else if (bpp <= 32) {
813 bpp = 32;
814 pix_width = CRTC_PIX_WIDTH_32BPP;
815 dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP |
816 BYTE_ORDER_LSB_TO_MSB;
817 dp_chain_mask = DP_CHAIN_32BPP;
818 } else
819 FAIL("invalid bpp");
821 if (vxres * vyres * bpp / 8 > info->fix.smem_len)
822 FAIL("not enough video RAM");
824 h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
825 v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
827 if((xres > 1600) || (yres > 1200)) {
828 FAIL("MACH64 chips are designed for max 1600x1200\n"
829 "select anoter resolution.");
831 h_sync_strt = h_disp + var->right_margin;
832 h_sync_end = h_sync_strt + var->hsync_len;
833 h_sync_dly = var->right_margin & 7;
834 h_total = h_sync_end + h_sync_dly + var->left_margin;
836 v_sync_strt = v_disp + var->lower_margin;
837 v_sync_end = v_sync_strt + var->vsync_len;
838 v_total = v_sync_end + var->upper_margin;
840 #ifdef CONFIG_FB_ATY_GENERIC_LCD
841 if (par->lcd_table != 0) {
842 if(!M64_HAS(LT_LCD_REGS)) {
843 u32 lcd_index = aty_ld_le32(LCD_INDEX, par);
844 crtc->lcd_index = lcd_index &
845 ~(LCD_INDEX_MASK | LCD_DISPLAY_DIS | LCD_SRC_SEL | CRTC2_DISPLAY_DIS);
846 aty_st_le32(LCD_INDEX, lcd_index, par);
849 if (!M64_HAS(MOBIL_BUS))
850 crtc->lcd_index |= CRTC2_DISPLAY_DIS;
852 crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par) | 0x4000;
853 crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par) & ~CRTC_RW_SELECT;
855 crtc->lcd_gen_cntl &=
856 ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 | TVCLK_PM_EN |
857 /*VCLK_DAC_PM_EN | USE_SHADOWED_VEND |*/
858 USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN);
859 crtc->lcd_gen_cntl |= DONT_SHADOW_VPAR | LOCK_8DOT;
861 if((crtc->lcd_gen_cntl & LCD_ON) &&
862 ((xres > par->lcd_width) || (yres > par->lcd_height))) {
863 /* We cannot display the mode on the LCD. If the CRT is enabled
864 we can turn off the LCD.
865 If the CRT is off, it isn't a good idea to switch it on; we don't
866 know if one is connected. So it's better to fail then.
868 if (crtc->lcd_gen_cntl & CRT_ON) {
869 if (!(var->activate & FB_ACTIVATE_TEST))
870 PRINTKI("Disable LCD panel, because video mode does not fit.\n");
871 crtc->lcd_gen_cntl &= ~LCD_ON;
872 /*aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);*/
873 } else {
874 if (!(var->activate & FB_ACTIVATE_TEST))
875 PRINTKE("Video mode exceeds size of LCD panel.\nConnect this computer to a conventional monitor if you really need this mode.\n");
876 return -EINVAL;
881 if ((par->lcd_table != 0) && (crtc->lcd_gen_cntl & LCD_ON)) {
882 int VScan = 1;
883 /* bpp -> bytespp, 1,4 -> 0; 8 -> 2; 15,16 -> 1; 24 -> 6; 32 -> 5
884 const u8 DFP_h_sync_dly_LT[] = { 0, 2, 1, 6, 5 };
885 const u8 ADD_to_strt_wid_and_dly_LT_DAC[] = { 0, 5, 6, 9, 9, 12, 12 }; */
887 vmode &= ~(FB_VMODE_DOUBLE | FB_VMODE_INTERLACED);
889 /* This is horror! When we simulate, say 640x480 on an 800x600
890 LCD monitor, the CRTC should be programmed 800x600 values for
891 the non visible part, but 640x480 for the visible part.
892 This code has been tested on a laptop with it's 1400x1050 LCD
893 monitor and a conventional monitor both switched on.
894 Tested modes: 1280x1024, 1152x864, 1024x768, 800x600,
895 works with little glitches also with DOUBLESCAN modes
897 if (yres < par->lcd_height) {
898 VScan = par->lcd_height / yres;
899 if(VScan > 1) {
900 VScan = 2;
901 vmode |= FB_VMODE_DOUBLE;
905 h_sync_strt = h_disp + par->lcd_right_margin;
906 h_sync_end = h_sync_strt + par->lcd_hsync_len;
907 h_sync_dly = /*DFP_h_sync_dly[ ( bpp + 1 ) / 3 ]; */par->lcd_hsync_dly;
908 h_total = h_disp + par->lcd_hblank_len;
910 v_sync_strt = v_disp + par->lcd_lower_margin / VScan;
911 v_sync_end = v_sync_strt + par->lcd_vsync_len / VScan;
912 v_total = v_disp + par->lcd_vblank_len / VScan;
914 #endif /* CONFIG_FB_ATY_GENERIC_LCD */
916 h_disp = (h_disp >> 3) - 1;
917 h_sync_strt = (h_sync_strt >> 3) - 1;
918 h_sync_end = (h_sync_end >> 3) - 1;
919 h_total = (h_total >> 3) - 1;
920 h_sync_wid = h_sync_end - h_sync_strt;
922 FAIL_MAX("h_disp too large", h_disp, 0xff);
923 FAIL_MAX("h_sync_strt too large", h_sync_strt, 0x1ff);
924 /*FAIL_MAX("h_sync_wid too large", h_sync_wid, 0x1f);*/
925 if(h_sync_wid > 0x1f)
926 h_sync_wid = 0x1f;
927 FAIL_MAX("h_total too large", h_total, 0x1ff);
929 if (vmode & FB_VMODE_DOUBLE) {
930 v_disp <<= 1;
931 v_sync_strt <<= 1;
932 v_sync_end <<= 1;
933 v_total <<= 1;
936 vdisplay = yres;
937 #ifdef CONFIG_FB_ATY_GENERIC_LCD
938 if ((par->lcd_table != 0) && (crtc->lcd_gen_cntl & LCD_ON))
939 vdisplay = par->lcd_height;
940 #endif
942 v_disp--;
943 v_sync_strt--;
944 v_sync_end--;
945 v_total--;
946 v_sync_wid = v_sync_end - v_sync_strt;
948 FAIL_MAX("v_disp too large", v_disp, 0x7ff);
949 FAIL_MAX("v_sync_stsrt too large", v_sync_strt, 0x7ff);
950 /*FAIL_MAX("v_sync_wid too large", v_sync_wid, 0x1f);*/
951 if(v_sync_wid > 0x1f)
952 v_sync_wid = 0x1f;
953 FAIL_MAX("v_total too large", v_total, 0x7ff);
955 c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;
957 /* output */
958 crtc->vxres = vxres;
959 crtc->vyres = vyres;
960 crtc->xoffset = xoffset;
961 crtc->yoffset = yoffset;
962 crtc->bpp = bpp;
963 crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19);
964 crtc->vline_crnt_vline = 0;
966 crtc->h_tot_disp = h_total | (h_disp<<16);
967 crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly<<8) |
968 ((h_sync_strt & 0x100)<<4) | (h_sync_wid<<16) | (h_sync_pol<<21);
969 crtc->v_tot_disp = v_total | (v_disp<<16);
970 crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid<<16) | (v_sync_pol<<21);
972 /* crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_PRESERVED_MASK; */
973 crtc->gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN | pix_width | c_sync;
974 crtc->gen_cntl |= CRTC_VGA_LINEAR;
976 /* Enable doublescan mode if requested */
977 if (vmode & FB_VMODE_DOUBLE)
978 crtc->gen_cntl |= CRTC_DBL_SCAN_EN;
979 /* Enable interlaced mode if requested */
980 if (vmode & FB_VMODE_INTERLACED)
981 crtc->gen_cntl |= CRTC_INTERLACE_EN;
982 #ifdef CONFIG_FB_ATY_GENERIC_LCD
983 if (par->lcd_table != 0) {
984 vdisplay = yres;
985 if(vmode & FB_VMODE_DOUBLE)
986 vdisplay <<= 1;
987 crtc->gen_cntl &= ~(CRTC2_EN | CRTC2_PIX_WIDTH);
988 crtc->lcd_gen_cntl &= ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 |
989 /*TVCLK_PM_EN | VCLK_DAC_PM_EN |*/
990 USE_SHADOWED_VEND | USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN);
991 crtc->lcd_gen_cntl |= (DONT_SHADOW_VPAR/* | LOCK_8DOT*/);
993 /* MOBILITY M1 tested, FIXME: LT */
994 crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par);
995 if (!M64_HAS(LT_LCD_REGS))
996 crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par) &
997 ~(AUTO_VERT_RATIO | VERT_STRETCH_MODE | VERT_STRETCH_RATIO3);
999 crtc->horz_stretching &=
1000 ~(HORZ_STRETCH_RATIO | HORZ_STRETCH_LOOP | AUTO_HORZ_RATIO |
1001 HORZ_STRETCH_MODE | HORZ_STRETCH_EN);
1002 if (xres < par->lcd_width && crtc->lcd_gen_cntl & LCD_ON) {
1003 do {
1005 * The horizontal blender misbehaves when HDisplay is less than a
1006 * a certain threshold (440 for a 1024-wide panel). It doesn't
1007 * stretch such modes enough. Use pixel replication instead of
1008 * blending to stretch modes that can be made to exactly fit the
1009 * panel width. The undocumented "NoLCDBlend" option allows the
1010 * pixel-replicated mode to be slightly wider or narrower than the
1011 * panel width. It also causes a mode that is exactly half as wide
1012 * as the panel to be pixel-replicated, rather than blended.
1014 int HDisplay = xres & ~7;
1015 int nStretch = par->lcd_width / HDisplay;
1016 int Remainder = par->lcd_width % HDisplay;
1018 if ((!Remainder && ((nStretch > 2))) ||
1019 (((HDisplay * 16) / par->lcd_width) < 7)) {
1020 static const char StretchLoops[] = {10, 12, 13, 15, 16};
1021 int horz_stretch_loop = -1, BestRemainder;
1022 int Numerator = HDisplay, Denominator = par->lcd_width;
1023 int Index = 5;
1024 ATIReduceRatio(&Numerator, &Denominator);
1026 BestRemainder = (Numerator * 16) / Denominator;
1027 while (--Index >= 0) {
1028 Remainder = ((Denominator - Numerator) * StretchLoops[Index]) %
1029 Denominator;
1030 if (Remainder < BestRemainder) {
1031 horz_stretch_loop = Index;
1032 if (!(BestRemainder = Remainder))
1033 break;
1037 if ((horz_stretch_loop >= 0) && !BestRemainder) {
1038 int horz_stretch_ratio = 0, Accumulator = 0;
1039 int reuse_previous = 1;
1041 Index = StretchLoops[horz_stretch_loop];
1043 while (--Index >= 0) {
1044 if (Accumulator > 0)
1045 horz_stretch_ratio |= reuse_previous;
1046 else
1047 Accumulator += Denominator;
1048 Accumulator -= Numerator;
1049 reuse_previous <<= 1;
1052 crtc->horz_stretching |= (HORZ_STRETCH_EN |
1053 ((horz_stretch_loop & HORZ_STRETCH_LOOP) << 16) |
1054 (horz_stretch_ratio & HORZ_STRETCH_RATIO));
1055 break; /* Out of the do { ... } while (0) */
1059 crtc->horz_stretching |= (HORZ_STRETCH_MODE | HORZ_STRETCH_EN |
1060 (((HDisplay * (HORZ_STRETCH_BLEND + 1)) / par->lcd_width) & HORZ_STRETCH_BLEND));
1061 } while (0);
1064 if (vdisplay < par->lcd_height && crtc->lcd_gen_cntl & LCD_ON) {
1065 crtc->vert_stretching = (VERT_STRETCH_USE0 | VERT_STRETCH_EN |
1066 (((vdisplay * (VERT_STRETCH_RATIO0 + 1)) / par->lcd_height) & VERT_STRETCH_RATIO0));
1068 if (!M64_HAS(LT_LCD_REGS) &&
1069 xres <= (M64_HAS(MOBIL_BUS)?1024:800))
1070 crtc->ext_vert_stretch |= VERT_STRETCH_MODE;
1071 } else {
1073 * Don't use vertical blending if the mode is too wide or not
1074 * vertically stretched.
1076 crtc->vert_stretching = 0;
1078 /* copy to shadow crtc */
1079 crtc->shadow_h_tot_disp = crtc->h_tot_disp;
1080 crtc->shadow_h_sync_strt_wid = crtc->h_sync_strt_wid;
1081 crtc->shadow_v_tot_disp = crtc->v_tot_disp;
1082 crtc->shadow_v_sync_strt_wid = crtc->v_sync_strt_wid;
1084 #endif /* CONFIG_FB_ATY_GENERIC_LCD */
1086 if (M64_HAS(MAGIC_FIFO)) {
1087 /* FIXME: display FIFO low watermark values */
1088 crtc->gen_cntl |= (aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_FIFO_LWM);
1090 crtc->dp_pix_width = dp_pix_width;
1091 crtc->dp_chain_mask = dp_chain_mask;
1093 return 0;
1096 static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *var)
1098 u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync;
1099 u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid,
1100 h_sync_pol;
1101 u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
1102 u32 pix_width;
1103 u32 double_scan, interlace;
1105 /* input */
1106 h_total = crtc->h_tot_disp & 0x1ff;
1107 h_disp = (crtc->h_tot_disp >> 16) & 0xff;
1108 h_sync_strt = (crtc->h_sync_strt_wid & 0xff) | ((crtc->h_sync_strt_wid >> 4) & 0x100);
1109 h_sync_dly = (crtc->h_sync_strt_wid >> 8) & 0x7;
1110 h_sync_wid = (crtc->h_sync_strt_wid >> 16) & 0x1f;
1111 h_sync_pol = (crtc->h_sync_strt_wid >> 21) & 0x1;
1112 v_total = crtc->v_tot_disp & 0x7ff;
1113 v_disp = (crtc->v_tot_disp >> 16) & 0x7ff;
1114 v_sync_strt = crtc->v_sync_strt_wid & 0x7ff;
1115 v_sync_wid = (crtc->v_sync_strt_wid >> 16) & 0x1f;
1116 v_sync_pol = (crtc->v_sync_strt_wid >> 21) & 0x1;
1117 c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
1118 pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
1119 double_scan = crtc->gen_cntl & CRTC_DBL_SCAN_EN;
1120 interlace = crtc->gen_cntl & CRTC_INTERLACE_EN;
1122 /* convert */
1123 xres = (h_disp + 1) * 8;
1124 yres = v_disp + 1;
1125 left = (h_total - h_sync_strt - h_sync_wid) * 8 - h_sync_dly;
1126 right = (h_sync_strt - h_disp) * 8 + h_sync_dly;
1127 hslen = h_sync_wid * 8;
1128 upper = v_total - v_sync_strt - v_sync_wid;
1129 lower = v_sync_strt - v_disp;
1130 vslen = v_sync_wid;
1131 sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) |
1132 (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
1133 (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
1135 switch (pix_width) {
1136 #if 0
1137 case CRTC_PIX_WIDTH_4BPP:
1138 bpp = 4;
1139 var->red.offset = 0;
1140 var->red.length = 8;
1141 var->green.offset = 0;
1142 var->green.length = 8;
1143 var->blue.offset = 0;
1144 var->blue.length = 8;
1145 var->transp.offset = 0;
1146 var->transp.length = 0;
1147 break;
1148 #endif
1149 case CRTC_PIX_WIDTH_8BPP:
1150 bpp = 8;
1151 var->red.offset = 0;
1152 var->red.length = 8;
1153 var->green.offset = 0;
1154 var->green.length = 8;
1155 var->blue.offset = 0;
1156 var->blue.length = 8;
1157 var->transp.offset = 0;
1158 var->transp.length = 0;
1159 break;
1160 case CRTC_PIX_WIDTH_15BPP: /* RGB 555 */
1161 bpp = 16;
1162 var->red.offset = 10;
1163 var->red.length = 5;
1164 var->green.offset = 5;
1165 var->green.length = 5;
1166 var->blue.offset = 0;
1167 var->blue.length = 5;
1168 var->transp.offset = 0;
1169 var->transp.length = 0;
1170 break;
1171 case CRTC_PIX_WIDTH_16BPP: /* RGB 565 */
1172 bpp = 16;
1173 var->red.offset = 11;
1174 var->red.length = 5;
1175 var->green.offset = 5;
1176 var->green.length = 6;
1177 var->blue.offset = 0;
1178 var->blue.length = 5;
1179 var->transp.offset = 0;
1180 var->transp.length = 0;
1181 break;
1182 case CRTC_PIX_WIDTH_24BPP: /* RGB 888 */
1183 bpp = 24;
1184 var->red.offset = 16;
1185 var->red.length = 8;
1186 var->green.offset = 8;
1187 var->green.length = 8;
1188 var->blue.offset = 0;
1189 var->blue.length = 8;
1190 var->transp.offset = 0;
1191 var->transp.length = 0;
1192 break;
1193 case CRTC_PIX_WIDTH_32BPP: /* ARGB 8888 */
1194 bpp = 32;
1195 var->red.offset = 16;
1196 var->red.length = 8;
1197 var->green.offset = 8;
1198 var->green.length = 8;
1199 var->blue.offset = 0;
1200 var->blue.length = 8;
1201 var->transp.offset = 24;
1202 var->transp.length = 8;
1203 break;
1204 default:
1205 PRINTKE("Invalid pixel width\n");
1206 return -EINVAL;
1209 /* output */
1210 var->xres = xres;
1211 var->yres = yres;
1212 var->xres_virtual = crtc->vxres;
1213 var->yres_virtual = crtc->vyres;
1214 var->bits_per_pixel = bpp;
1215 var->left_margin = left;
1216 var->right_margin = right;
1217 var->upper_margin = upper;
1218 var->lower_margin = lower;
1219 var->hsync_len = hslen;
1220 var->vsync_len = vslen;
1221 var->sync = sync;
1222 var->vmode = FB_VMODE_NONINTERLACED;
1223 /* In double scan mode, the vertical parameters are doubled, so we need to
1224 half them to get the right values.
1225 In interlaced mode the values are already correct, so no correction is
1226 necessary.
1228 if (interlace)
1229 var->vmode = FB_VMODE_INTERLACED;
1231 if (double_scan) {
1232 var->vmode = FB_VMODE_DOUBLE;
1233 var->yres>>=1;
1234 var->upper_margin>>=1;
1235 var->lower_margin>>=1;
1236 var->vsync_len>>=1;
1239 return 0;
1242 /* ------------------------------------------------------------------------- */
1244 static int atyfb_set_par(struct fb_info *info)
1246 struct atyfb_par *par = (struct atyfb_par *) info->par;
1247 struct fb_var_screeninfo *var = &info->var;
1248 u32 tmp, pixclock;
1249 int err;
1250 #ifdef DEBUG
1251 struct fb_var_screeninfo debug;
1252 u32 pixclock_in_ps;
1253 #endif
1254 if (par->asleep)
1255 return 0;
1257 if ((err = aty_var_to_crtc(info, var, &par->crtc)))
1258 return err;
1260 pixclock = atyfb_get_pixclock(var, par);
1262 if (pixclock == 0) {
1263 PRINTKE("Invalid pixclock\n");
1264 return -EINVAL;
1265 } else {
1266 if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &par->pll)))
1267 return err;
1270 par->accel_flags = var->accel_flags; /* hack */
1272 if (var->accel_flags) {
1273 info->fbops->fb_sync = atyfb_sync;
1274 info->flags &= ~FBINFO_HWACCEL_DISABLED;
1275 } else {
1276 info->fbops->fb_sync = NULL;
1277 info->flags |= FBINFO_HWACCEL_DISABLED;
1280 if (par->blitter_may_be_busy)
1281 wait_for_idle(par);
1283 aty_set_crtc(par, &par->crtc);
1284 par->dac_ops->set_dac(info, &par->pll, var->bits_per_pixel, par->accel_flags);
1285 par->pll_ops->set_pll(info, &par->pll);
1287 #ifdef DEBUG
1288 if(par->pll_ops && par->pll_ops->pll_to_var)
1289 pixclock_in_ps = par->pll_ops->pll_to_var(info, &(par->pll));
1290 else
1291 pixclock_in_ps = 0;
1293 if(0 == pixclock_in_ps) {
1294 PRINTKE("ALERT ops->pll_to_var get 0\n");
1295 pixclock_in_ps = pixclock;
1298 memset(&debug, 0, sizeof(debug));
1299 if(!aty_crtc_to_var(&(par->crtc), &debug)) {
1300 u32 hSync, vRefresh;
1301 u32 h_disp, h_sync_strt, h_sync_end, h_total;
1302 u32 v_disp, v_sync_strt, v_sync_end, v_total;
1304 h_disp = debug.xres;
1305 h_sync_strt = h_disp + debug.right_margin;
1306 h_sync_end = h_sync_strt + debug.hsync_len;
1307 h_total = h_sync_end + debug.left_margin;
1308 v_disp = debug.yres;
1309 v_sync_strt = v_disp + debug.lower_margin;
1310 v_sync_end = v_sync_strt + debug.vsync_len;
1311 v_total = v_sync_end + debug.upper_margin;
1313 hSync = 1000000000 / (pixclock_in_ps * h_total);
1314 vRefresh = (hSync * 1000) / v_total;
1315 if (par->crtc.gen_cntl & CRTC_INTERLACE_EN)
1316 vRefresh *= 2;
1317 if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN)
1318 vRefresh /= 2;
1320 DPRINTK("atyfb_set_par\n");
1321 DPRINTK(" Set Visible Mode to %ix%i-%i\n", var->xres, var->yres, var->bits_per_pixel);
1322 DPRINTK(" Virtual resolution %ix%i, pixclock_in_ps %i (calculated %i)\n",
1323 var->xres_virtual, var->yres_virtual, pixclock, pixclock_in_ps);
1324 DPRINTK(" Dot clock: %i MHz\n", 1000000 / pixclock_in_ps);
1325 DPRINTK(" Horizontal sync: %i kHz\n", hSync);
1326 DPRINTK(" Vertical refresh: %i Hz\n", vRefresh);
1327 DPRINTK(" x style: %i.%03i %i %i %i %i %i %i %i %i\n",
1328 1000000 / pixclock_in_ps, 1000000 % pixclock_in_ps,
1329 h_disp, h_sync_strt, h_sync_end, h_total,
1330 v_disp, v_sync_strt, v_sync_end, v_total);
1331 DPRINTK(" fb style: %i %i %i %i %i %i %i %i %i\n",
1332 pixclock_in_ps,
1333 debug.left_margin, h_disp, debug.right_margin, debug.hsync_len,
1334 debug.upper_margin, v_disp, debug.lower_margin, debug.vsync_len);
1336 #endif /* DEBUG */
1338 if (!M64_HAS(INTEGRATED)) {
1339 /* Don't forget MEM_CNTL */
1340 tmp = aty_ld_le32(MEM_CNTL, par) & 0xf0ffffff;
1341 switch (var->bits_per_pixel) {
1342 case 8:
1343 tmp |= 0x02000000;
1344 break;
1345 case 16:
1346 tmp |= 0x03000000;
1347 break;
1348 case 32:
1349 tmp |= 0x06000000;
1350 break;
1352 aty_st_le32(MEM_CNTL, tmp, par);
1353 } else {
1354 tmp = aty_ld_le32(MEM_CNTL, par) & 0xf00fffff;
1355 if (!M64_HAS(MAGIC_POSTDIV))
1356 tmp |= par->mem_refresh_rate << 20;
1357 switch (var->bits_per_pixel) {
1358 case 8:
1359 case 24:
1360 tmp |= 0x00000000;
1361 break;
1362 case 16:
1363 tmp |= 0x04000000;
1364 break;
1365 case 32:
1366 tmp |= 0x08000000;
1367 break;
1369 if (M64_HAS(CT_BUS)) {
1370 aty_st_le32(DAC_CNTL, 0x87010184, par);
1371 aty_st_le32(BUS_CNTL, 0x680000f9, par);
1372 } else if (M64_HAS(VT_BUS)) {
1373 aty_st_le32(DAC_CNTL, 0x87010184, par);
1374 aty_st_le32(BUS_CNTL, 0x680000f9, par);
1375 } else if (M64_HAS(MOBIL_BUS)) {
1376 aty_st_le32(DAC_CNTL, 0x80010102, par);
1377 aty_st_le32(BUS_CNTL, 0x7b33a040 | (par->aux_start ? BUS_APER_REG_DIS : 0), par);
1378 } else {
1379 /* GT */
1380 aty_st_le32(DAC_CNTL, 0x86010102, par);
1381 aty_st_le32(BUS_CNTL, 0x7b23a040 | (par->aux_start ? BUS_APER_REG_DIS : 0), par);
1382 aty_st_le32(EXT_MEM_CNTL, aty_ld_le32(EXT_MEM_CNTL, par) | 0x5000001, par);
1384 aty_st_le32(MEM_CNTL, tmp, par);
1386 aty_st_8(DAC_MASK, 0xff, par);
1388 info->fix.line_length = var->xres_virtual * var->bits_per_pixel/8;
1389 info->fix.visual = var->bits_per_pixel <= 8 ?
1390 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
1392 /* Initialize the graphics engine */
1393 if (par->accel_flags & FB_ACCELF_TEXT)
1394 aty_init_engine(par, info);
1396 #ifdef CONFIG_BOOTX_TEXT
1397 btext_update_display(info->fix.smem_start,
1398 (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8,
1399 ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1,
1400 var->bits_per_pixel,
1401 par->crtc.vxres * var->bits_per_pixel / 8);
1402 #endif /* CONFIG_BOOTX_TEXT */
1403 #if 0
1404 /* switch to accelerator mode */
1405 if (!(par->crtc.gen_cntl & CRTC_EXT_DISP_EN))
1406 aty_st_le32(CRTC_GEN_CNTL, par->crtc.gen_cntl | CRTC_EXT_DISP_EN, par);
1407 #endif
1408 #ifdef DEBUG
1410 /* dump non shadow CRTC, pll, LCD registers */
1411 int i; u32 base;
1413 /* CRTC registers */
1414 base = 0x2000;
1415 printk("debug atyfb: Mach64 non-shadow register values:");
1416 for (i = 0; i < 256; i = i+4) {
1417 if(i%16 == 0) printk("\ndebug atyfb: 0x%04X: ", base + i);
1418 printk(" %08X", aty_ld_le32(i, par));
1420 printk("\n\n");
1422 #ifdef CONFIG_FB_ATY_CT
1423 /* PLL registers */
1424 base = 0x00;
1425 printk("debug atyfb: Mach64 PLL register values:");
1426 for (i = 0; i < 64; i++) {
1427 if(i%16 == 0) printk("\ndebug atyfb: 0x%02X: ", base + i);
1428 if(i%4 == 0) printk(" ");
1429 printk("%02X", aty_ld_pll_ct(i, par));
1431 printk("\n\n");
1432 #endif /* CONFIG_FB_ATY_CT */
1434 #ifdef CONFIG_FB_ATY_GENERIC_LCD
1435 if (par->lcd_table != 0) {
1436 /* LCD registers */
1437 base = 0x00;
1438 printk("debug atyfb: LCD register values:");
1439 if(M64_HAS(LT_LCD_REGS)) {
1440 for(i = 0; i <= POWER_MANAGEMENT; i++) {
1441 if(i == EXT_VERT_STRETCH)
1442 continue;
1443 printk("\ndebug atyfb: 0x%04X: ", lt_lcd_regs[i]);
1444 printk(" %08X", aty_ld_lcd(i, par));
1447 } else {
1448 for (i = 0; i < 64; i++) {
1449 if(i%4 == 0) printk("\ndebug atyfb: 0x%02X: ", base + i);
1450 printk(" %08X", aty_ld_lcd(i, par));
1453 printk("\n\n");
1455 #endif /* CONFIG_FB_ATY_GENERIC_LCD */
1457 #endif /* DEBUG */
1458 return 0;
1461 static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1463 struct atyfb_par *par = (struct atyfb_par *) info->par;
1464 int err;
1465 struct crtc crtc;
1466 union aty_pll pll;
1467 u32 pixclock;
1469 memcpy(&pll, &(par->pll), sizeof(pll));
1471 if((err = aty_var_to_crtc(info, var, &crtc)))
1472 return err;
1474 pixclock = atyfb_get_pixclock(var, par);
1476 if (pixclock == 0) {
1477 if (!(var->activate & FB_ACTIVATE_TEST))
1478 PRINTKE("Invalid pixclock\n");
1479 return -EINVAL;
1480 } else {
1481 if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &pll)))
1482 return err;
1485 if (var->accel_flags & FB_ACCELF_TEXT)
1486 info->var.accel_flags = FB_ACCELF_TEXT;
1487 else
1488 info->var.accel_flags = 0;
1490 #if 0 /* fbmon is not done. uncomment for 2.5.x -brad */
1491 if (!fbmon_valid_timings(pixclock, htotal, vtotal, info))
1492 return -EINVAL;
1493 #endif
1494 aty_crtc_to_var(&crtc, var);
1495 var->pixclock = par->pll_ops->pll_to_var(info, &pll);
1496 return 0;
1499 static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info)
1501 u32 xoffset = info->var.xoffset;
1502 u32 yoffset = info->var.yoffset;
1503 u32 vxres = par->crtc.vxres;
1504 u32 bpp = info->var.bits_per_pixel;
1506 par->crtc.off_pitch = ((yoffset * vxres + xoffset) * bpp / 64) | (vxres << 19);
1511 * Open/Release the frame buffer device
1514 static int atyfb_open(struct fb_info *info, int user)
1516 struct atyfb_par *par = (struct atyfb_par *) info->par;
1518 if (user) {
1519 par->open++;
1520 #ifdef __sparc__
1521 par->mmaped = 0;
1522 #endif
1524 return (0);
1527 static irqreturn_t aty_irq(int irq, void *dev_id)
1529 struct atyfb_par *par = dev_id;
1530 int handled = 0;
1531 u32 int_cntl;
1533 spin_lock(&par->int_lock);
1535 int_cntl = aty_ld_le32(CRTC_INT_CNTL, par);
1537 if (int_cntl & CRTC_VBLANK_INT) {
1538 /* clear interrupt */
1539 aty_st_le32(CRTC_INT_CNTL, (int_cntl & CRTC_INT_EN_MASK) | CRTC_VBLANK_INT_AK, par);
1540 par->vblank.count++;
1541 if (par->vblank.pan_display) {
1542 par->vblank.pan_display = 0;
1543 aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
1545 wake_up_interruptible(&par->vblank.wait);
1546 handled = 1;
1549 spin_unlock(&par->int_lock);
1551 return IRQ_RETVAL(handled);
1554 static int aty_enable_irq(struct atyfb_par *par, int reenable)
1556 u32 int_cntl;
1558 if (!test_and_set_bit(0, &par->irq_flags)) {
1559 if (request_irq(par->irq, aty_irq, IRQF_SHARED, "atyfb", par)) {
1560 clear_bit(0, &par->irq_flags);
1561 return -EINVAL;
1563 spin_lock_irq(&par->int_lock);
1564 int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
1565 /* clear interrupt */
1566 aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_AK, par);
1567 /* enable interrupt */
1568 aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_EN, par);
1569 spin_unlock_irq(&par->int_lock);
1570 } else if (reenable) {
1571 spin_lock_irq(&par->int_lock);
1572 int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
1573 if (!(int_cntl & CRTC_VBLANK_INT_EN)) {
1574 printk("atyfb: someone disabled IRQ [%08x]\n", int_cntl);
1575 /* re-enable interrupt */
1576 aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_EN, par );
1578 spin_unlock_irq(&par->int_lock);
1581 return 0;
1584 static int aty_disable_irq(struct atyfb_par *par)
1586 u32 int_cntl;
1588 if (test_and_clear_bit(0, &par->irq_flags)) {
1589 if (par->vblank.pan_display) {
1590 par->vblank.pan_display = 0;
1591 aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
1593 spin_lock_irq(&par->int_lock);
1594 int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
1595 /* disable interrupt */
1596 aty_st_le32(CRTC_INT_CNTL, int_cntl & ~CRTC_VBLANK_INT_EN, par );
1597 spin_unlock_irq(&par->int_lock);
1598 free_irq(par->irq, par);
1601 return 0;
1604 static int atyfb_release(struct fb_info *info, int user)
1606 struct atyfb_par *par = (struct atyfb_par *) info->par;
1607 if (user) {
1608 par->open--;
1609 mdelay(1);
1610 wait_for_idle(par);
1611 if (!par->open) {
1612 #ifdef __sparc__
1613 int was_mmaped = par->mmaped;
1615 par->mmaped = 0;
1617 if (was_mmaped) {
1618 struct fb_var_screeninfo var;
1620 /* Now reset the default display config, we have no
1621 * idea what the program(s) which mmap'd the chip did
1622 * to the configuration, nor whether it restored it
1623 * correctly.
1625 var = default_var;
1626 if (noaccel)
1627 var.accel_flags &= ~FB_ACCELF_TEXT;
1628 else
1629 var.accel_flags |= FB_ACCELF_TEXT;
1630 if (var.yres == var.yres_virtual) {
1631 u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2));
1632 var.yres_virtual = ((videoram * 8) / var.bits_per_pixel) / var.xres_virtual;
1633 if (var.yres_virtual < var.yres)
1634 var.yres_virtual = var.yres;
1637 #endif
1638 aty_disable_irq(par);
1641 return (0);
1645 * Pan or Wrap the Display
1647 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
1650 static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
1652 struct atyfb_par *par = (struct atyfb_par *) info->par;
1653 u32 xres, yres, xoffset, yoffset;
1655 xres = (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8;
1656 yres = ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1;
1657 if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN)
1658 yres >>= 1;
1659 xoffset = (var->xoffset + 7) & ~7;
1660 yoffset = var->yoffset;
1661 if (xoffset + xres > par->crtc.vxres || yoffset + yres > par->crtc.vyres)
1662 return -EINVAL;
1663 info->var.xoffset = xoffset;
1664 info->var.yoffset = yoffset;
1665 if (par->asleep)
1666 return 0;
1668 set_off_pitch(par, info);
1669 if ((var->activate & FB_ACTIVATE_VBL) && !aty_enable_irq(par, 0)) {
1670 par->vblank.pan_display = 1;
1671 } else {
1672 par->vblank.pan_display = 0;
1673 aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
1676 return 0;
1679 static int aty_waitforvblank(struct atyfb_par *par, u32 crtc)
1681 struct aty_interrupt *vbl;
1682 unsigned int count;
1683 int ret;
1685 switch (crtc) {
1686 case 0:
1687 vbl = &par->vblank;
1688 break;
1689 default:
1690 return -ENODEV;
1693 ret = aty_enable_irq(par, 0);
1694 if (ret)
1695 return ret;
1697 count = vbl->count;
1698 ret = wait_event_interruptible_timeout(vbl->wait, count != vbl->count, HZ/10);
1699 if (ret < 0) {
1700 return ret;
1702 if (ret == 0) {
1703 aty_enable_irq(par, 1);
1704 return -ETIMEDOUT;
1707 return 0;
1711 #ifdef DEBUG
1712 #define ATYIO_CLKR 0x41545900 /* ATY\00 */
1713 #define ATYIO_CLKW 0x41545901 /* ATY\01 */
1715 struct atyclk {
1716 u32 ref_clk_per;
1717 u8 pll_ref_div;
1718 u8 mclk_fb_div;
1719 u8 mclk_post_div; /* 1,2,3,4,8 */
1720 u8 mclk_fb_mult; /* 2 or 4 */
1721 u8 xclk_post_div; /* 1,2,3,4,8 */
1722 u8 vclk_fb_div;
1723 u8 vclk_post_div; /* 1,2,3,4,6,8,12 */
1724 u32 dsp_xclks_per_row; /* 0-16383 */
1725 u32 dsp_loop_latency; /* 0-15 */
1726 u32 dsp_precision; /* 0-7 */
1727 u32 dsp_on; /* 0-2047 */
1728 u32 dsp_off; /* 0-2047 */
1731 #define ATYIO_FEATR 0x41545902 /* ATY\02 */
1732 #define ATYIO_FEATW 0x41545903 /* ATY\03 */
1733 #endif
1735 #ifndef FBIO_WAITFORVSYNC
1736 #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
1737 #endif
1739 static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
1741 struct atyfb_par *par = (struct atyfb_par *) info->par;
1742 #ifdef __sparc__
1743 struct fbtype fbtyp;
1744 #endif
1746 switch (cmd) {
1747 #ifdef __sparc__
1748 case FBIOGTYPE:
1749 fbtyp.fb_type = FBTYPE_PCI_GENERIC;
1750 fbtyp.fb_width = par->crtc.vxres;
1751 fbtyp.fb_height = par->crtc.vyres;
1752 fbtyp.fb_depth = info->var.bits_per_pixel;
1753 fbtyp.fb_cmsize = info->cmap.len;
1754 fbtyp.fb_size = info->fix.smem_len;
1755 if (copy_to_user((struct fbtype __user *) arg, &fbtyp, sizeof(fbtyp)))
1756 return -EFAULT;
1757 break;
1758 #endif /* __sparc__ */
1760 case FBIO_WAITFORVSYNC:
1762 u32 crtc;
1764 if (get_user(crtc, (__u32 __user *) arg))
1765 return -EFAULT;
1767 return aty_waitforvblank(par, crtc);
1769 break;
1771 #if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)
1772 case ATYIO_CLKR:
1773 if (M64_HAS(INTEGRATED)) {
1774 struct atyclk clk;
1775 union aty_pll *pll = &(par->pll);
1776 u32 dsp_config = pll->ct.dsp_config;
1777 u32 dsp_on_off = pll->ct.dsp_on_off;
1778 clk.ref_clk_per = par->ref_clk_per;
1779 clk.pll_ref_div = pll->ct.pll_ref_div;
1780 clk.mclk_fb_div = pll->ct.mclk_fb_div;
1781 clk.mclk_post_div = pll->ct.mclk_post_div_real;
1782 clk.mclk_fb_mult = pll->ct.mclk_fb_mult;
1783 clk.xclk_post_div = pll->ct.xclk_post_div_real;
1784 clk.vclk_fb_div = pll->ct.vclk_fb_div;
1785 clk.vclk_post_div = pll->ct.vclk_post_div_real;
1786 clk.dsp_xclks_per_row = dsp_config & 0x3fff;
1787 clk.dsp_loop_latency = (dsp_config >> 16) & 0xf;
1788 clk.dsp_precision = (dsp_config >> 20) & 7;
1789 clk.dsp_off = dsp_on_off & 0x7ff;
1790 clk.dsp_on = (dsp_on_off >> 16) & 0x7ff;
1791 if (copy_to_user((struct atyclk __user *) arg, &clk,
1792 sizeof(clk)))
1793 return -EFAULT;
1794 } else
1795 return -EINVAL;
1796 break;
1797 case ATYIO_CLKW:
1798 if (M64_HAS(INTEGRATED)) {
1799 struct atyclk clk;
1800 union aty_pll *pll = &(par->pll);
1801 if (copy_from_user(&clk, (struct atyclk __user *) arg, sizeof(clk)))
1802 return -EFAULT;
1803 par->ref_clk_per = clk.ref_clk_per;
1804 pll->ct.pll_ref_div = clk.pll_ref_div;
1805 pll->ct.mclk_fb_div = clk.mclk_fb_div;
1806 pll->ct.mclk_post_div_real = clk.mclk_post_div;
1807 pll->ct.mclk_fb_mult = clk.mclk_fb_mult;
1808 pll->ct.xclk_post_div_real = clk.xclk_post_div;
1809 pll->ct.vclk_fb_div = clk.vclk_fb_div;
1810 pll->ct.vclk_post_div_real = clk.vclk_post_div;
1811 pll->ct.dsp_config = (clk.dsp_xclks_per_row & 0x3fff) |
1812 ((clk.dsp_loop_latency & 0xf)<<16)| ((clk.dsp_precision & 7)<<20);
1813 pll->ct.dsp_on_off = (clk.dsp_off & 0x7ff) | ((clk.dsp_on & 0x7ff)<<16);
1814 /*aty_calc_pll_ct(info, &pll->ct);*/
1815 aty_set_pll_ct(info, pll);
1816 } else
1817 return -EINVAL;
1818 break;
1819 case ATYIO_FEATR:
1820 if (get_user(par->features, (u32 __user *) arg))
1821 return -EFAULT;
1822 break;
1823 case ATYIO_FEATW:
1824 if (put_user(par->features, (u32 __user *) arg))
1825 return -EFAULT;
1826 break;
1827 #endif /* DEBUG && CONFIG_FB_ATY_CT */
1828 default:
1829 return -EINVAL;
1831 return 0;
1834 static int atyfb_sync(struct fb_info *info)
1836 struct atyfb_par *par = (struct atyfb_par *) info->par;
1838 if (par->blitter_may_be_busy)
1839 wait_for_idle(par);
1840 return 0;
1843 #ifdef __sparc__
1844 static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
1846 struct atyfb_par *par = (struct atyfb_par *) info->par;
1847 unsigned int size, page, map_size = 0;
1848 unsigned long map_offset = 0;
1849 unsigned long off;
1850 int i;
1852 if (!par->mmap_map)
1853 return -ENXIO;
1855 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
1856 return -EINVAL;
1858 off = vma->vm_pgoff << PAGE_SHIFT;
1859 size = vma->vm_end - vma->vm_start;
1861 /* To stop the swapper from even considering these pages. */
1862 vma->vm_flags |= (VM_IO | VM_RESERVED);
1864 if (((vma->vm_pgoff == 0) && (size == info->fix.smem_len)) ||
1865 ((off == info->fix.smem_len) && (size == PAGE_SIZE)))
1866 off += 0x8000000000000000UL;
1868 vma->vm_pgoff = off >> PAGE_SHIFT; /* propagate off changes */
1870 /* Each page, see which map applies */
1871 for (page = 0; page < size;) {
1872 map_size = 0;
1873 for (i = 0; par->mmap_map[i].size; i++) {
1874 unsigned long start = par->mmap_map[i].voff;
1875 unsigned long end = start + par->mmap_map[i].size;
1876 unsigned long offset = off + page;
1878 if (start > offset)
1879 continue;
1880 if (offset >= end)
1881 continue;
1883 map_size = par->mmap_map[i].size - (offset - start);
1884 map_offset =
1885 par->mmap_map[i].poff + (offset - start);
1886 break;
1888 if (!map_size) {
1889 page += PAGE_SIZE;
1890 continue;
1892 if (page + map_size > size)
1893 map_size = size - page;
1895 pgprot_val(vma->vm_page_prot) &=
1896 ~(par->mmap_map[i].prot_mask);
1897 pgprot_val(vma->vm_page_prot) |= par->mmap_map[i].prot_flag;
1899 if (remap_pfn_range(vma, vma->vm_start + page,
1900 map_offset >> PAGE_SHIFT, map_size, vma->vm_page_prot))
1901 return -EAGAIN;
1903 page += map_size;
1906 if (!map_size)
1907 return -EINVAL;
1909 if (!par->mmaped)
1910 par->mmaped = 1;
1911 return 0;
1914 static struct {
1915 u32 yoffset;
1916 u8 r[2][256];
1917 u8 g[2][256];
1918 u8 b[2][256];
1919 } atyfb_save;
1921 static void atyfb_save_palette(struct atyfb_par *par, int enter)
1923 int i, tmp;
1925 for (i = 0; i < 256; i++) {
1926 tmp = aty_ld_8(DAC_CNTL, par) & 0xfc;
1927 if (M64_HAS(EXTRA_BRIGHT))
1928 tmp |= 0x2;
1929 aty_st_8(DAC_CNTL, tmp, par);
1930 aty_st_8(DAC_MASK, 0xff, par);
1932 aty_st_8(DAC_R_INDEX, i, par);
1933 atyfb_save.r[enter][i] = aty_ld_8(DAC_DATA, par);
1934 atyfb_save.g[enter][i] = aty_ld_8(DAC_DATA, par);
1935 atyfb_save.b[enter][i] = aty_ld_8(DAC_DATA, par);
1936 aty_st_8(DAC_W_INDEX, i, par);
1937 aty_st_8(DAC_DATA, atyfb_save.r[1 - enter][i], par);
1938 aty_st_8(DAC_DATA, atyfb_save.g[1 - enter][i], par);
1939 aty_st_8(DAC_DATA, atyfb_save.b[1 - enter][i], par);
1943 static void atyfb_palette(int enter)
1945 struct atyfb_par *par;
1946 struct fb_info *info;
1947 int i;
1949 for (i = 0; i < FB_MAX; i++) {
1950 info = registered_fb[i];
1951 if (info && info->fbops == &atyfb_ops) {
1952 par = (struct atyfb_par *) info->par;
1954 atyfb_save_palette(par, enter);
1955 if (enter) {
1956 atyfb_save.yoffset = info->var.yoffset;
1957 info->var.yoffset = 0;
1958 set_off_pitch(par, info);
1959 } else {
1960 info->var.yoffset = atyfb_save.yoffset;
1961 set_off_pitch(par, info);
1963 aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
1964 break;
1968 #endif /* __sparc__ */
1972 #if defined(CONFIG_PM) && defined(CONFIG_PCI)
1974 /* Power management routines. Those are used for PowerBook sleep.
1976 static int aty_power_mgmt(int sleep, struct atyfb_par *par)
1978 u32 pm;
1979 int timeout;
1981 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
1982 pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;
1983 aty_st_lcd(POWER_MANAGEMENT, pm, par);
1984 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
1986 timeout = 2000;
1987 if (sleep) {
1988 /* Sleep */
1989 pm &= ~PWR_MGT_ON;
1990 aty_st_lcd(POWER_MANAGEMENT, pm, par);
1991 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
1992 udelay(10);
1993 pm &= ~(PWR_BLON | AUTO_PWR_UP);
1994 pm |= SUSPEND_NOW;
1995 aty_st_lcd(POWER_MANAGEMENT, pm, par);
1996 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
1997 udelay(10);
1998 pm |= PWR_MGT_ON;
1999 aty_st_lcd(POWER_MANAGEMENT, pm, par);
2000 do {
2001 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2002 mdelay(1);
2003 if ((--timeout) == 0)
2004 break;
2005 } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
2006 } else {
2007 /* Wakeup */
2008 pm &= ~PWR_MGT_ON;
2009 aty_st_lcd(POWER_MANAGEMENT, pm, par);
2010 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2011 udelay(10);
2012 pm &= ~SUSPEND_NOW;
2013 pm |= (PWR_BLON | AUTO_PWR_UP);
2014 aty_st_lcd(POWER_MANAGEMENT, pm, par);
2015 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2016 udelay(10);
2017 pm |= PWR_MGT_ON;
2018 aty_st_lcd(POWER_MANAGEMENT, pm, par);
2019 do {
2020 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2021 mdelay(1);
2022 if ((--timeout) == 0)
2023 break;
2024 } while ((pm & PWR_MGT_STATUS_MASK) != 0);
2026 mdelay(500);
2028 return timeout ? 0 : -EIO;
2031 static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
2033 struct fb_info *info = pci_get_drvdata(pdev);
2034 struct atyfb_par *par = (struct atyfb_par *) info->par;
2036 #ifndef CONFIG_PPC_PMAC
2037 /* HACK ALERT ! Once I find a proper way to say to each driver
2038 * individually what will happen with it's PCI slot, I'll change
2039 * that. On laptops, the AGP slot is just unclocked, so D2 is
2040 * expected, while on desktops, the card is powered off
2042 return 0;
2043 #endif /* CONFIG_PPC_PMAC */
2045 if (state.event == pdev->dev.power.power_state.event)
2046 return 0;
2048 acquire_console_sem();
2050 fb_set_suspend(info, 1);
2052 /* Idle & reset engine */
2053 wait_for_idle(par);
2054 aty_reset_engine(par);
2056 /* Blank display and LCD */
2057 atyfb_blank(FB_BLANK_POWERDOWN, info);
2059 par->asleep = 1;
2060 par->lock_blank = 1;
2062 /* Set chip to "suspend" mode */
2063 if (aty_power_mgmt(1, par)) {
2064 par->asleep = 0;
2065 par->lock_blank = 0;
2066 atyfb_blank(FB_BLANK_UNBLANK, info);
2067 fb_set_suspend(info, 0);
2068 release_console_sem();
2069 return -EIO;
2072 release_console_sem();
2074 pdev->dev.power.power_state = state;
2076 return 0;
2079 static int atyfb_pci_resume(struct pci_dev *pdev)
2081 struct fb_info *info = pci_get_drvdata(pdev);
2082 struct atyfb_par *par = (struct atyfb_par *) info->par;
2084 if (pdev->dev.power.power_state.event == PM_EVENT_ON)
2085 return 0;
2087 acquire_console_sem();
2089 if (pdev->dev.power.power_state.event == 2)
2090 aty_power_mgmt(0, par);
2091 par->asleep = 0;
2093 /* Restore display */
2094 atyfb_set_par(info);
2096 /* Refresh */
2097 fb_set_suspend(info, 0);
2099 /* Unblank */
2100 par->lock_blank = 0;
2101 atyfb_blank(FB_BLANK_UNBLANK, info);
2103 release_console_sem();
2105 pdev->dev.power.power_state = PMSG_ON;
2107 return 0;
2110 #endif /* defined(CONFIG_PM) && defined(CONFIG_PCI) */
2112 /* Backlight */
2113 #ifdef CONFIG_FB_ATY_BACKLIGHT
2114 #define MAX_LEVEL 0xFF
2116 static struct backlight_properties aty_bl_data;
2118 /* Call with fb_info->bl_mutex held */
2119 static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
2121 struct fb_info *info = pci_get_drvdata(par->pdev);
2122 int atylevel;
2124 /* Get and convert the value */
2125 atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
2127 if (atylevel < 0)
2128 atylevel = 0;
2129 else if (atylevel > MAX_LEVEL)
2130 atylevel = MAX_LEVEL;
2132 return atylevel;
2135 /* Call with fb_info->bl_mutex held */
2136 static int __aty_bl_update_status(struct backlight_device *bd)
2138 struct atyfb_par *par = class_get_devdata(&bd->class_dev);
2139 unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par);
2140 int level;
2142 if (bd->props->power != FB_BLANK_UNBLANK ||
2143 bd->props->fb_blank != FB_BLANK_UNBLANK)
2144 level = 0;
2145 else
2146 level = bd->props->brightness;
2148 reg |= (BLMOD_EN | BIASMOD_EN);
2149 if (level > 0) {
2150 reg &= ~BIAS_MOD_LEVEL_MASK;
2151 reg |= (aty_bl_get_level_brightness(par, level) << BIAS_MOD_LEVEL_SHIFT);
2152 } else {
2153 reg &= ~BIAS_MOD_LEVEL_MASK;
2154 reg |= (aty_bl_get_level_brightness(par, 0) << BIAS_MOD_LEVEL_SHIFT);
2156 aty_st_lcd(LCD_MISC_CNTL, reg, par);
2158 return 0;
2161 static int aty_bl_update_status(struct backlight_device *bd)
2163 struct atyfb_par *par = class_get_devdata(&bd->class_dev);
2164 struct fb_info *info = pci_get_drvdata(par->pdev);
2165 int ret;
2167 mutex_lock(&info->bl_mutex);
2168 ret = __aty_bl_update_status(bd);
2169 mutex_unlock(&info->bl_mutex);
2171 return ret;
2174 static int aty_bl_get_brightness(struct backlight_device *bd)
2176 return bd->props->brightness;
2179 static struct backlight_properties aty_bl_data = {
2180 .owner = THIS_MODULE,
2181 .get_brightness = aty_bl_get_brightness,
2182 .update_status = aty_bl_update_status,
2183 .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
2186 static void aty_bl_set_power(struct fb_info *info, int power)
2188 mutex_lock(&info->bl_mutex);
2190 if (info->bl_dev) {
2191 down(&info->bl_dev->sem);
2192 info->bl_dev->props->power = power;
2193 __aty_bl_update_status(info->bl_dev);
2194 up(&info->bl_dev->sem);
2197 mutex_unlock(&info->bl_mutex);
2200 static void aty_bl_init(struct atyfb_par *par)
2202 struct fb_info *info = pci_get_drvdata(par->pdev);
2203 struct backlight_device *bd;
2204 char name[12];
2206 #ifdef CONFIG_PMAC_BACKLIGHT
2207 if (!pmac_has_backlight_type("ati"))
2208 return;
2209 #endif
2211 snprintf(name, sizeof(name), "atybl%d", info->node);
2213 bd = backlight_device_register(name, par, &aty_bl_data);
2214 if (IS_ERR(bd)) {
2215 info->bl_dev = NULL;
2216 printk(KERN_WARNING "aty: Backlight registration failed\n");
2217 goto error;
2220 mutex_lock(&info->bl_mutex);
2221 info->bl_dev = bd;
2222 fb_bl_default_curve(info, 0,
2223 0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL,
2224 0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL);
2225 mutex_unlock(&info->bl_mutex);
2227 down(&bd->sem);
2228 bd->props->brightness = aty_bl_data.max_brightness;
2229 bd->props->power = FB_BLANK_UNBLANK;
2230 bd->props->update_status(bd);
2231 up(&bd->sem);
2233 #ifdef CONFIG_PMAC_BACKLIGHT
2234 mutex_lock(&pmac_backlight_mutex);
2235 if (!pmac_backlight)
2236 pmac_backlight = bd;
2237 mutex_unlock(&pmac_backlight_mutex);
2238 #endif
2240 printk("aty: Backlight initialized (%s)\n", name);
2242 return;
2244 error:
2245 return;
2248 static void aty_bl_exit(struct atyfb_par *par)
2250 struct fb_info *info = pci_get_drvdata(par->pdev);
2252 #ifdef CONFIG_PMAC_BACKLIGHT
2253 mutex_lock(&pmac_backlight_mutex);
2254 #endif
2256 mutex_lock(&info->bl_mutex);
2257 if (info->bl_dev) {
2258 #ifdef CONFIG_PMAC_BACKLIGHT
2259 if (pmac_backlight == info->bl_dev)
2260 pmac_backlight = NULL;
2261 #endif
2263 backlight_device_unregister(info->bl_dev);
2265 printk("aty: Backlight unloaded\n");
2267 mutex_unlock(&info->bl_mutex);
2269 #ifdef CONFIG_PMAC_BACKLIGHT
2270 mutex_unlock(&pmac_backlight_mutex);
2271 #endif
2274 #endif /* CONFIG_FB_ATY_BACKLIGHT */
2276 static void __devinit aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
2278 const int ragepro_tbl[] = {
2279 44, 50, 55, 66, 75, 80, 100
2281 const int ragexl_tbl[] = {
2282 50, 66, 75, 83, 90, 95, 100, 105,
2283 110, 115, 120, 125, 133, 143, 166
2285 const int *refresh_tbl;
2286 int i, size;
2288 if (IS_XL(par->pci_id) || IS_MOBILITY(par->pci_id)) {
2289 refresh_tbl = ragexl_tbl;
2290 size = ARRAY_SIZE(ragexl_tbl);
2291 } else {
2292 refresh_tbl = ragepro_tbl;
2293 size = ARRAY_SIZE(ragepro_tbl);
2296 for (i=0; i < size; i++) {
2297 if (xclk < refresh_tbl[i])
2298 break;
2300 par->mem_refresh_rate = i;
2304 * Initialisation
2307 static struct fb_info *fb_list = NULL;
2309 #if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD)
2310 static int __devinit atyfb_get_timings_from_lcd(struct atyfb_par *par,
2311 struct fb_var_screeninfo *var)
2313 int ret = -EINVAL;
2315 if (par->lcd_table != 0 && (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
2316 *var = default_var;
2317 var->xres = var->xres_virtual = par->lcd_hdisp;
2318 var->right_margin = par->lcd_right_margin;
2319 var->left_margin = par->lcd_hblank_len -
2320 (par->lcd_right_margin + par->lcd_hsync_dly +
2321 par->lcd_hsync_len);
2322 var->hsync_len = par->lcd_hsync_len + par->lcd_hsync_dly;
2323 var->yres = var->yres_virtual = par->lcd_vdisp;
2324 var->lower_margin = par->lcd_lower_margin;
2325 var->upper_margin = par->lcd_vblank_len -
2326 (par->lcd_lower_margin + par->lcd_vsync_len);
2327 var->vsync_len = par->lcd_vsync_len;
2328 var->pixclock = par->lcd_pixclock;
2329 ret = 0;
2332 return ret;
2334 #endif /* defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) */
2336 static int __devinit aty_init(struct fb_info *info)
2338 struct atyfb_par *par = (struct atyfb_par *) info->par;
2339 const char *ramname = NULL, *xtal;
2340 int gtb_memsize, has_var = 0;
2341 struct fb_var_screeninfo var;
2342 u32 i;
2344 init_waitqueue_head(&par->vblank.wait);
2345 spin_lock_init(&par->int_lock);
2347 #ifdef CONFIG_PPC_PMAC
2348 /* The Apple iBook1 uses non-standard memory frequencies. We detect it
2349 * and set the frequency manually. */
2350 if (machine_is_compatible("PowerBook2,1")) {
2351 par->pll_limits.mclk = 70;
2352 par->pll_limits.xclk = 53;
2354 #endif
2355 if (pll)
2356 par->pll_limits.pll_max = pll;
2357 if (mclk)
2358 par->pll_limits.mclk = mclk;
2359 if (xclk)
2360 par->pll_limits.xclk = xclk;
2362 aty_calc_mem_refresh(par, par->pll_limits.xclk);
2363 par->pll_per = 1000000/par->pll_limits.pll_max;
2364 par->mclk_per = 1000000/par->pll_limits.mclk;
2365 par->xclk_per = 1000000/par->pll_limits.xclk;
2367 par->ref_clk_per = 1000000000000ULL / 14318180;
2368 xtal = "14.31818";
2370 #ifdef CONFIG_FB_ATY_GX
2371 if (!M64_HAS(INTEGRATED)) {
2372 u32 stat0;
2373 u8 dac_type, dac_subtype, clk_type;
2374 stat0 = aty_ld_le32(CONFIG_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? */
2379 dac_type = (aty_ld_le32(DAC_CNTL, par) >> 16) & 0x07;
2380 #ifdef CONFIG_ATARI
2381 clk_type = CLK_ATI18818_1;
2382 dac_type = (stat0 >> 9) & 0x07;
2383 if (dac_type == 0x07)
2384 dac_subtype = DAC_ATT20C408;
2385 else
2386 dac_subtype = (aty_ld_8(SCRATCH_REG1 + 1, par) & 0xF0) | dac_type;
2387 #else
2388 dac_type = DAC_IBMRGB514;
2389 dac_subtype = DAC_IBMRGB514;
2390 clk_type = CLK_IBMRGB514;
2391 #endif
2392 switch (dac_subtype) {
2393 case DAC_IBMRGB514:
2394 par->dac_ops = &aty_dac_ibm514;
2395 break;
2396 case DAC_ATI68860_B:
2397 case DAC_ATI68860_C:
2398 par->dac_ops = &aty_dac_ati68860b;
2399 break;
2400 case DAC_ATT20C408:
2401 case DAC_ATT21C498:
2402 par->dac_ops = &aty_dac_att21c498;
2403 break;
2404 default:
2405 PRINTKI("aty_init: DAC type not implemented yet!\n");
2406 par->dac_ops = &aty_dac_unsupported;
2407 break;
2409 switch (clk_type) {
2410 #ifdef CONFIG_ATARI
2411 case CLK_ATI18818_1:
2412 par->pll_ops = &aty_pll_ati18818_1;
2413 break;
2414 #else
2415 case CLK_IBMRGB514:
2416 par->pll_ops = &aty_pll_ibm514;
2417 break;
2418 #endif
2419 #if 0 /* dead code */
2420 case CLK_STG1703:
2421 par->pll_ops = &aty_pll_stg1703;
2422 break;
2423 case CLK_CH8398:
2424 par->pll_ops = &aty_pll_ch8398;
2425 break;
2426 case CLK_ATT20C408:
2427 par->pll_ops = &aty_pll_att20c408;
2428 break;
2429 #endif
2430 default:
2431 PRINTKI("aty_init: CLK type not implemented yet!");
2432 par->pll_ops = &aty_pll_unsupported;
2433 break;
2436 #endif /* CONFIG_FB_ATY_GX */
2437 #ifdef CONFIG_FB_ATY_CT
2438 if (M64_HAS(INTEGRATED)) {
2439 par->dac_ops = &aty_dac_ct;
2440 par->pll_ops = &aty_pll_ct;
2441 par->bus_type = PCI;
2442 par->ram_type = (aty_ld_le32(CONFIG_STAT0, par) & 0x07);
2443 ramname = aty_ct_ram[par->ram_type];
2444 /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
2445 if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM)
2446 par->pll_limits.mclk = 63;
2449 if (M64_HAS(GTB_DSP)) {
2450 u8 pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par);
2452 if (pll_ref_div) {
2453 int diff1, diff2;
2454 diff1 = 510 * 14 / pll_ref_div - par->pll_limits.pll_max;
2455 diff2 = 510 * 29 / pll_ref_div - par->pll_limits.pll_max;
2456 if (diff1 < 0)
2457 diff1 = -diff1;
2458 if (diff2 < 0)
2459 diff2 = -diff2;
2460 if (diff2 < diff1) {
2461 par->ref_clk_per = 1000000000000ULL / 29498928;
2462 xtal = "29.498928";
2466 #endif /* CONFIG_FB_ATY_CT */
2468 /* save previous video mode */
2469 aty_get_crtc(par, &saved_crtc);
2470 if(par->pll_ops->get_pll)
2471 par->pll_ops->get_pll(info, &saved_pll);
2473 i = aty_ld_le32(MEM_CNTL, par);
2474 gtb_memsize = M64_HAS(GTB_DSP);
2475 if (gtb_memsize)
2476 switch (i & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */
2477 case MEM_SIZE_512K:
2478 info->fix.smem_len = 0x80000;
2479 break;
2480 case MEM_SIZE_1M:
2481 info->fix.smem_len = 0x100000;
2482 break;
2483 case MEM_SIZE_2M_GTB:
2484 info->fix.smem_len = 0x200000;
2485 break;
2486 case MEM_SIZE_4M_GTB:
2487 info->fix.smem_len = 0x400000;
2488 break;
2489 case MEM_SIZE_6M_GTB:
2490 info->fix.smem_len = 0x600000;
2491 break;
2492 case MEM_SIZE_8M_GTB:
2493 info->fix.smem_len = 0x800000;
2494 break;
2495 default:
2496 info->fix.smem_len = 0x80000;
2497 } else
2498 switch (i & MEM_SIZE_ALIAS) {
2499 case MEM_SIZE_512K:
2500 info->fix.smem_len = 0x80000;
2501 break;
2502 case MEM_SIZE_1M:
2503 info->fix.smem_len = 0x100000;
2504 break;
2505 case MEM_SIZE_2M:
2506 info->fix.smem_len = 0x200000;
2507 break;
2508 case MEM_SIZE_4M:
2509 info->fix.smem_len = 0x400000;
2510 break;
2511 case MEM_SIZE_6M:
2512 info->fix.smem_len = 0x600000;
2513 break;
2514 case MEM_SIZE_8M:
2515 info->fix.smem_len = 0x800000;
2516 break;
2517 default:
2518 info->fix.smem_len = 0x80000;
2521 if (M64_HAS(MAGIC_VRAM_SIZE)) {
2522 if (aty_ld_le32(CONFIG_STAT1, par) & 0x40000000)
2523 info->fix.smem_len += 0x400000;
2526 if (vram) {
2527 info->fix.smem_len = vram * 1024;
2528 i = i & ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS);
2529 if (info->fix.smem_len <= 0x80000)
2530 i |= MEM_SIZE_512K;
2531 else if (info->fix.smem_len <= 0x100000)
2532 i |= MEM_SIZE_1M;
2533 else if (info->fix.smem_len <= 0x200000)
2534 i |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M;
2535 else if (info->fix.smem_len <= 0x400000)
2536 i |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M;
2537 else if (info->fix.smem_len <= 0x600000)
2538 i |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M;
2539 else
2540 i |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M;
2541 aty_st_le32(MEM_CNTL, i, par);
2545 * Reg Block 0 (CT-compatible block) is at mmio_start
2546 * Reg Block 1 (multimedia extensions) is at mmio_start - 0x400
2548 if (M64_HAS(GX)) {
2549 info->fix.mmio_len = 0x400;
2550 info->fix.accel = FB_ACCEL_ATI_MACH64GX;
2551 } else if (M64_HAS(CT)) {
2552 info->fix.mmio_len = 0x400;
2553 info->fix.accel = FB_ACCEL_ATI_MACH64CT;
2554 } else if (M64_HAS(VT)) {
2555 info->fix.mmio_start -= 0x400;
2556 info->fix.mmio_len = 0x800;
2557 info->fix.accel = FB_ACCEL_ATI_MACH64VT;
2558 } else {/* GT */
2559 info->fix.mmio_start -= 0x400;
2560 info->fix.mmio_len = 0x800;
2561 info->fix.accel = FB_ACCEL_ATI_MACH64GT;
2564 PRINTKI("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK, %d MHz XCLK\n",
2565 info->fix.smem_len == 0x80000 ? 512 : (info->fix.smem_len >> 20),
2566 info->fix.smem_len == 0x80000 ? 'K' : 'M', ramname, xtal, par->pll_limits.pll_max,
2567 par->pll_limits.mclk, par->pll_limits.xclk);
2569 #if defined(DEBUG) && defined(CONFIG_ATY_CT)
2570 if (M64_HAS(INTEGRATED)) {
2571 int i;
2572 printk("debug atyfb: BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
2573 "DSP_CONFIG DSP_ON_OFF CLOCK_CNTL\n"
2574 "debug atyfb: %08x %08x %08x %08x %08x %08x %08x %08x\n"
2575 "debug atyfb: PLL",
2576 aty_ld_le32(BUS_CNTL, par), aty_ld_le32(DAC_CNTL, par),
2577 aty_ld_le32(MEM_CNTL, par), aty_ld_le32(EXT_MEM_CNTL, par),
2578 aty_ld_le32(CRTC_GEN_CNTL, par), aty_ld_le32(DSP_CONFIG, par),
2579 aty_ld_le32(DSP_ON_OFF, par), aty_ld_le32(CLOCK_CNTL, par));
2580 for (i = 0; i < 40; i++)
2581 printk(" %02x", aty_ld_pll_ct(i, par));
2582 printk("\n");
2584 #endif
2585 if(par->pll_ops->init_pll)
2586 par->pll_ops->init_pll(info, &par->pll);
2589 * Last page of 8 MB (4 MB on ISA) aperture is MMIO,
2590 * unless the auxiliary register aperture is used.
2593 if (!par->aux_start &&
2594 (info->fix.smem_len == 0x800000 || (par->bus_type == ISA && info->fix.smem_len == 0x400000)))
2595 info->fix.smem_len -= GUI_RESERVE;
2598 * Disable register access through the linear aperture
2599 * if the auxiliary aperture is used so we can access
2600 * the full 8 MB of video RAM on 8 MB boards.
2602 if (par->aux_start)
2603 aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par);
2605 #ifdef CONFIG_MTRR
2606 par->mtrr_aper = -1;
2607 par->mtrr_reg = -1;
2608 if (!nomtrr) {
2609 /* Cover the whole resource. */
2610 par->mtrr_aper = mtrr_add(par->res_start, par->res_size, MTRR_TYPE_WRCOMB, 1);
2611 if (par->mtrr_aper >= 0 && !par->aux_start) {
2612 /* Make a hole for mmio. */
2613 par->mtrr_reg = mtrr_add(par->res_start + 0x800000 - GUI_RESERVE,
2614 GUI_RESERVE, MTRR_TYPE_UNCACHABLE, 1);
2615 if (par->mtrr_reg < 0) {
2616 mtrr_del(par->mtrr_aper, 0, 0);
2617 par->mtrr_aper = -1;
2621 #endif
2623 info->fbops = &atyfb_ops;
2624 info->pseudo_palette = pseudo_palette;
2625 info->flags = FBINFO_DEFAULT |
2626 FBINFO_HWACCEL_IMAGEBLIT |
2627 FBINFO_HWACCEL_FILLRECT |
2628 FBINFO_HWACCEL_COPYAREA |
2629 FBINFO_HWACCEL_YPAN;
2631 #ifdef CONFIG_PMAC_BACKLIGHT
2632 if (M64_HAS(G3_PB_1_1) && machine_is_compatible("PowerBook1,1")) {
2633 /* these bits let the 101 powerbook wake up from sleep -- paulus */
2634 aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par)
2635 | (USE_F32KHZ | TRISTATE_MEM_EN), par);
2636 } else
2637 #endif
2638 if (M64_HAS(MOBIL_BUS)) {
2639 #ifdef CONFIG_FB_ATY_BACKLIGHT
2640 aty_bl_init (par);
2641 #endif
2644 memset(&var, 0, sizeof(var));
2645 #ifdef CONFIG_PPC
2646 if (machine_is(powermac)) {
2648 * FIXME: The NVRAM stuff should be put in a Mac-specific file, as it
2649 * applies to all Mac video cards
2651 if (mode) {
2652 if (mac_find_mode(&var, info, mode, 8))
2653 has_var = 1;
2654 } else {
2655 if (default_vmode == VMODE_CHOOSE) {
2656 int sense;
2657 if (M64_HAS(G3_PB_1024x768))
2658 /* G3 PowerBook with 1024x768 LCD */
2659 default_vmode = VMODE_1024_768_60;
2660 else if (machine_is_compatible("iMac"))
2661 default_vmode = VMODE_1024_768_75;
2662 else if (machine_is_compatible
2663 ("PowerBook2,1"))
2664 /* iBook with 800x600 LCD */
2665 default_vmode = VMODE_800_600_60;
2666 else
2667 default_vmode = VMODE_640_480_67;
2668 sense = read_aty_sense(par);
2669 PRINTKI("monitor sense=%x, mode %d\n",
2670 sense, mac_map_monitor_sense(sense));
2672 if (default_vmode <= 0 || default_vmode > VMODE_MAX)
2673 default_vmode = VMODE_640_480_60;
2674 if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
2675 default_cmode = CMODE_8;
2676 if (!mac_vmode_to_var(default_vmode, default_cmode,
2677 &var))
2678 has_var = 1;
2682 #endif /* !CONFIG_PPC */
2684 #if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD)
2685 if (!atyfb_get_timings_from_lcd(par, &var))
2686 has_var = 1;
2687 #endif
2689 if (mode && fb_find_mode(&var, info, mode, NULL, 0, &defmode, 8))
2690 has_var = 1;
2692 if (!has_var)
2693 var = default_var;
2695 if (noaccel)
2696 var.accel_flags &= ~FB_ACCELF_TEXT;
2697 else
2698 var.accel_flags |= FB_ACCELF_TEXT;
2700 if (comp_sync != -1) {
2701 if (!comp_sync)
2702 var.sync &= ~FB_SYNC_COMP_HIGH_ACT;
2703 else
2704 var.sync |= FB_SYNC_COMP_HIGH_ACT;
2707 if (var.yres == var.yres_virtual) {
2708 u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2));
2709 var.yres_virtual = ((videoram * 8) / var.bits_per_pixel) / var.xres_virtual;
2710 if (var.yres_virtual < var.yres)
2711 var.yres_virtual = var.yres;
2714 if (atyfb_check_var(&var, info)) {
2715 PRINTKE("can't set default video mode\n");
2716 goto aty_init_exit;
2719 #ifdef __sparc__
2720 atyfb_save_palette(par, 0);
2721 #endif
2723 #ifdef CONFIG_FB_ATY_CT
2724 if (!noaccel && M64_HAS(INTEGRATED))
2725 aty_init_cursor(info);
2726 #endif /* CONFIG_FB_ATY_CT */
2727 info->var = var;
2729 fb_alloc_cmap(&info->cmap, 256, 0);
2731 if (register_framebuffer(info) < 0)
2732 goto aty_init_exit;
2734 fb_list = info;
2736 PRINTKI("fb%d: %s frame buffer device on %s\n",
2737 info->node, info->fix.id, par->bus_type == ISA ? "ISA" : "PCI");
2738 return 0;
2740 aty_init_exit:
2741 /* restore video mode */
2742 aty_set_crtc(par, &saved_crtc);
2743 par->pll_ops->set_pll(info, &saved_pll);
2745 #ifdef CONFIG_MTRR
2746 if (par->mtrr_reg >= 0) {
2747 mtrr_del(par->mtrr_reg, 0, 0);
2748 par->mtrr_reg = -1;
2750 if (par->mtrr_aper >= 0) {
2751 mtrr_del(par->mtrr_aper, 0, 0);
2752 par->mtrr_aper = -1;
2754 #endif
2755 return -1;
2758 #ifdef CONFIG_ATARI
2759 static int __devinit store_video_par(char *video_str, unsigned char m64_num)
2761 char *p;
2762 unsigned long vmembase, size, guiregbase;
2764 PRINTKI("store_video_par() '%s' \n", video_str);
2766 if (!(p = strsep(&video_str, ";")) || !*p)
2767 goto mach64_invalid;
2768 vmembase = simple_strtoul(p, NULL, 0);
2769 if (!(p = strsep(&video_str, ";")) || !*p)
2770 goto mach64_invalid;
2771 size = simple_strtoul(p, NULL, 0);
2772 if (!(p = strsep(&video_str, ";")) || !*p)
2773 goto mach64_invalid;
2774 guiregbase = simple_strtoul(p, NULL, 0);
2776 phys_vmembase[m64_num] = vmembase;
2777 phys_size[m64_num] = size;
2778 phys_guiregbase[m64_num] = guiregbase;
2779 PRINTKI("stored them all: $%08lX $%08lX $%08lX \n", vmembase, size,
2780 guiregbase);
2781 return 0;
2783 mach64_invalid:
2784 phys_vmembase[m64_num] = 0;
2785 return -1;
2787 #endif /* CONFIG_ATARI */
2790 * Blank the display.
2793 static int atyfb_blank(int blank, struct fb_info *info)
2795 struct atyfb_par *par = (struct atyfb_par *) info->par;
2796 u32 gen_cntl;
2798 if (par->lock_blank || par->asleep)
2799 return 0;
2801 #ifdef CONFIG_FB_ATY_BACKLIGHT
2802 if (machine_is(powermac) && blank > FB_BLANK_NORMAL)
2803 aty_bl_set_power(info, FB_BLANK_POWERDOWN);
2804 #elif defined(CONFIG_FB_ATY_GENERIC_LCD)
2805 if (par->lcd_table && blank > FB_BLANK_NORMAL &&
2806 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
2807 u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2808 pm &= ~PWR_BLON;
2809 aty_st_lcd(POWER_MANAGEMENT, pm, par);
2811 #endif
2813 gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
2814 gen_cntl &= ~0x400004c;
2815 switch (blank) {
2816 case FB_BLANK_UNBLANK:
2817 break;
2818 case FB_BLANK_NORMAL:
2819 gen_cntl |= 0x4000040;
2820 break;
2821 case FB_BLANK_VSYNC_SUSPEND:
2822 gen_cntl |= 0x4000048;
2823 break;
2824 case FB_BLANK_HSYNC_SUSPEND:
2825 gen_cntl |= 0x4000044;
2826 break;
2827 case FB_BLANK_POWERDOWN:
2828 gen_cntl |= 0x400004c;
2829 break;
2831 aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
2833 #ifdef CONFIG_FB_ATY_BACKLIGHT
2834 if (machine_is(powermac) && blank <= FB_BLANK_NORMAL)
2835 aty_bl_set_power(info, FB_BLANK_UNBLANK);
2836 #elif defined(CONFIG_FB_ATY_GENERIC_LCD)
2837 if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
2838 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
2839 u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2840 pm |= PWR_BLON;
2841 aty_st_lcd(POWER_MANAGEMENT, pm, par);
2843 #endif
2845 return 0;
2848 static void aty_st_pal(u_int regno, u_int red, u_int green, u_int blue,
2849 const struct atyfb_par *par)
2851 aty_st_8(DAC_W_INDEX, regno, par);
2852 aty_st_8(DAC_DATA, red, par);
2853 aty_st_8(DAC_DATA, green, par);
2854 aty_st_8(DAC_DATA, blue, par);
2858 * Set a single color register. The values supplied are already
2859 * rounded down to the hardware's capabilities (according to the
2860 * entries in the var structure). Return != 0 for invalid regno.
2861 * !! 4 & 8 = PSEUDO, > 8 = DIRECTCOLOR
2864 static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
2865 u_int transp, struct fb_info *info)
2867 struct atyfb_par *par = (struct atyfb_par *) info->par;
2868 int i, depth;
2869 u32 *pal = info->pseudo_palette;
2871 depth = info->var.bits_per_pixel;
2872 if (depth == 16)
2873 depth = (info->var.green.length == 5) ? 15 : 16;
2875 if (par->asleep)
2876 return 0;
2878 if (regno > 255 ||
2879 (depth == 16 && regno > 63) ||
2880 (depth == 15 && regno > 31))
2881 return 1;
2883 red >>= 8;
2884 green >>= 8;
2885 blue >>= 8;
2887 par->palette[regno].red = red;
2888 par->palette[regno].green = green;
2889 par->palette[regno].blue = blue;
2891 if (regno < 16) {
2892 switch (depth) {
2893 case 15:
2894 pal[regno] = (regno << 10) | (regno << 5) | regno;
2895 break;
2896 case 16:
2897 pal[regno] = (regno << 11) | (regno << 5) | regno;
2898 break;
2899 case 24:
2900 pal[regno] = (regno << 16) | (regno << 8) | regno;
2901 break;
2902 case 32:
2903 i = (regno << 8) | regno;
2904 pal[regno] = (i << 16) | i;
2905 break;
2909 i = aty_ld_8(DAC_CNTL, par) & 0xfc;
2910 if (M64_HAS(EXTRA_BRIGHT))
2911 i |= 0x2; /* DAC_CNTL | 0x2 turns off the extra brightness for gt */
2912 aty_st_8(DAC_CNTL, i, par);
2913 aty_st_8(DAC_MASK, 0xff, par);
2915 if (M64_HAS(INTEGRATED)) {
2916 if (depth == 16) {
2917 if (regno < 32)
2918 aty_st_pal(regno << 3, red,
2919 par->palette[regno<<1].green,
2920 blue, par);
2921 red = par->palette[regno>>1].red;
2922 blue = par->palette[regno>>1].blue;
2923 regno <<= 2;
2924 } else if (depth == 15) {
2925 regno <<= 3;
2926 for(i = 0; i < 8; i++) {
2927 aty_st_pal(regno + i, red, green, blue, par);
2931 aty_st_pal(regno, red, green, blue, par);
2933 return 0;
2936 #ifdef CONFIG_PCI
2938 #ifdef __sparc__
2940 extern void (*prom_palette) (int);
2942 static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
2943 struct fb_info *info, unsigned long addr)
2945 extern int con_is_present(void);
2947 struct atyfb_par *par = info->par;
2948 struct pcidev_cookie *pcp;
2949 char prop[128];
2950 int node, len, i, j, ret;
2951 u32 mem, chip_id;
2953 /* Do not attach when we have a serial console. */
2954 if (!con_is_present())
2955 return -ENXIO;
2958 * Map memory-mapped registers.
2960 par->ati_regbase = (void *)addr + 0x7ffc00UL;
2961 info->fix.mmio_start = addr + 0x7ffc00UL;
2964 * Map in big-endian aperture.
2966 info->screen_base = (char *) (addr + 0x800000UL);
2967 info->fix.smem_start = addr + 0x800000UL;
2970 * Figure mmap addresses from PCI config space.
2971 * Split Framebuffer in big- and little-endian halfs.
2973 for (i = 0; i < 6 && pdev->resource[i].start; i++)
2974 /* nothing */ ;
2975 j = i + 4;
2977 par->mmap_map = kmalloc(j * sizeof(*par->mmap_map), GFP_ATOMIC);
2978 if (!par->mmap_map) {
2979 PRINTKE("atyfb_setup_sparc() can't alloc mmap_map\n");
2980 return -ENOMEM;
2982 memset(par->mmap_map, 0, j * sizeof(*par->mmap_map));
2984 for (i = 0, j = 2; i < 6 && pdev->resource[i].start; i++) {
2985 struct resource *rp = &pdev->resource[i];
2986 int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
2987 unsigned long base;
2988 u32 size, pbase;
2990 base = rp->start;
2992 io = (rp->flags & IORESOURCE_IO);
2994 size = rp->end - base + 1;
2996 pci_read_config_dword(pdev, breg, &pbase);
2998 if (io)
2999 size &= ~1;
3002 * Map the framebuffer a second time, this time without
3003 * the braindead _PAGE_IE setting. This is used by the
3004 * fixed Xserver, but we need to maintain the old mapping
3005 * to stay compatible with older ones...
3007 if (base == addr) {
3008 par->mmap_map[j].voff = (pbase + 0x10000000) & PAGE_MASK;
3009 par->mmap_map[j].poff = base & PAGE_MASK;
3010 par->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
3011 par->mmap_map[j].prot_mask = _PAGE_CACHE;
3012 par->mmap_map[j].prot_flag = _PAGE_E;
3013 j++;
3017 * Here comes the old framebuffer mapping with _PAGE_IE
3018 * set for the big endian half of the framebuffer...
3020 if (base == addr) {
3021 par->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK;
3022 par->mmap_map[j].poff = (base + 0x800000) & PAGE_MASK;
3023 par->mmap_map[j].size = 0x800000;
3024 par->mmap_map[j].prot_mask = _PAGE_CACHE;
3025 par->mmap_map[j].prot_flag = _PAGE_E | _PAGE_IE;
3026 size -= 0x800000;
3027 j++;
3030 par->mmap_map[j].voff = pbase & PAGE_MASK;
3031 par->mmap_map[j].poff = base & PAGE_MASK;
3032 par->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
3033 par->mmap_map[j].prot_mask = _PAGE_CACHE;
3034 par->mmap_map[j].prot_flag = _PAGE_E;
3035 j++;
3038 if((ret = correct_chipset(par)))
3039 return ret;
3041 if (IS_XL(pdev->device)) {
3043 * Fix PROMs idea of MEM_CNTL settings...
3045 mem = aty_ld_le32(MEM_CNTL, par);
3046 chip_id = aty_ld_le32(CONFIG_CHIP_ID, par);
3047 if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) && !((chip_id >> 24) & 1)) {
3048 switch (mem & 0x0f) {
3049 case 3:
3050 mem = (mem & ~(0x0f)) | 2;
3051 break;
3052 case 7:
3053 mem = (mem & ~(0x0f)) | 3;
3054 break;
3055 case 9:
3056 mem = (mem & ~(0x0f)) | 4;
3057 break;
3058 case 11:
3059 mem = (mem & ~(0x0f)) | 5;
3060 break;
3061 default:
3062 break;
3064 if ((aty_ld_le32(CONFIG_STAT0, par) & 7) >= SDRAM)
3065 mem &= ~(0x00700000);
3067 mem &= ~(0xcf80e000); /* Turn off all undocumented bits. */
3068 aty_st_le32(MEM_CNTL, mem, par);
3072 * If this is the console device, we will set default video
3073 * settings to what the PROM left us with.
3075 node = prom_getchild(prom_root_node);
3076 node = prom_searchsiblings(node, "aliases");
3077 if (node) {
3078 len = prom_getproperty(node, "screen", prop, sizeof(prop));
3079 if (len > 0) {
3080 prop[len] = '\0';
3081 node = prom_finddevice(prop);
3082 } else
3083 node = 0;
3086 pcp = pdev->sysdata;
3087 if (node == pcp->prom_node->node) {
3088 struct fb_var_screeninfo *var = &default_var;
3089 unsigned int N, P, Q, M, T, R;
3090 u32 v_total, h_total;
3091 struct crtc crtc;
3092 u8 pll_regs[16];
3093 u8 clock_cntl;
3095 crtc.vxres = prom_getintdefault(node, "width", 1024);
3096 crtc.vyres = prom_getintdefault(node, "height", 768);
3097 var->bits_per_pixel = prom_getintdefault(node, "depth", 8);
3098 var->xoffset = var->yoffset = 0;
3099 crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
3100 crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
3101 crtc.v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
3102 crtc.v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
3103 crtc.gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
3104 aty_crtc_to_var(&crtc, var);
3106 h_total = var->xres + var->right_margin + var->hsync_len + var->left_margin;
3107 v_total = var->yres + var->lower_margin + var->vsync_len + var->upper_margin;
3110 * Read the PLL to figure actual Refresh Rate.
3112 clock_cntl = aty_ld_8(CLOCK_CNTL, par);
3113 /* DPRINTK("CLOCK_CNTL %02x\n", clock_cntl); */
3114 for (i = 0; i < 16; i++)
3115 pll_regs[i] = aty_ld_pll_ct(i, par);
3118 * PLL Reference Divider M:
3120 M = pll_regs[2];
3123 * PLL Feedback Divider N (Dependant on CLOCK_CNTL):
3125 N = pll_regs[7 + (clock_cntl & 3)];
3128 * PLL Post Divider P (Dependant on CLOCK_CNTL):
3130 P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
3133 * PLL Divider Q:
3135 Q = N / P;
3138 * Target Frequency:
3140 * T * M
3141 * Q = -------
3142 * 2 * R
3144 * where R is XTALIN (= 14318 or 29498 kHz).
3146 if (IS_XL(pdev->device))
3147 R = 29498;
3148 else
3149 R = 14318;
3151 T = 2 * Q * R / M;
3153 default_var.pixclock = 1000000000 / T;
3156 return 0;
3159 #else /* __sparc__ */
3161 #ifdef __i386__
3162 #ifdef CONFIG_FB_ATY_GENERIC_LCD
3163 static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base)
3165 u32 driv_inf_tab, sig;
3166 u16 lcd_ofs;
3168 /* To support an LCD panel, we should know it's dimensions and
3169 * it's desired pixel clock.
3170 * There are two ways to do it:
3171 * - Check the startup video mode and calculate the panel
3172 * size from it. This is unreliable.
3173 * - Read it from the driver information table in the video BIOS.
3175 /* Address of driver information table is at offset 0x78. */
3176 driv_inf_tab = bios_base + *((u16 *)(bios_base+0x78));
3178 /* Check for the driver information table signature. */
3179 sig = (*(u32 *)driv_inf_tab);
3180 if ((sig == 0x54504c24) || /* Rage LT pro */
3181 (sig == 0x544d5224) || /* Rage mobility */
3182 (sig == 0x54435824) || /* Rage XC */
3183 (sig == 0x544c5824)) { /* Rage XL */
3184 PRINTKI("BIOS contains driver information table.\n");
3185 lcd_ofs = (*(u16 *)(driv_inf_tab + 10));
3186 par->lcd_table = 0;
3187 if (lcd_ofs != 0) {
3188 par->lcd_table = bios_base + lcd_ofs;
3192 if (par->lcd_table != 0) {
3193 char model[24];
3194 char strbuf[16];
3195 char refresh_rates_buf[100];
3196 int id, tech, f, i, m, default_refresh_rate;
3197 char *txtcolour;
3198 char *txtmonitor;
3199 char *txtdual;
3200 char *txtformat;
3201 u16 width, height, panel_type, refresh_rates;
3202 u16 *lcdmodeptr;
3203 u32 format;
3204 u8 lcd_refresh_rates[16] = {50,56,60,67,70,72,75,76,85,90,100,120,140,150,160,200};
3205 /* The most important information is the panel size at
3206 * offset 25 and 27, but there's some other nice information
3207 * which we print to the screen.
3209 id = *(u8 *)par->lcd_table;
3210 strncpy(model,(char *)par->lcd_table+1,24);
3211 model[23]=0;
3213 width = par->lcd_width = *(u16 *)(par->lcd_table+25);
3214 height = par->lcd_height = *(u16 *)(par->lcd_table+27);
3215 panel_type = *(u16 *)(par->lcd_table+29);
3216 if (panel_type & 1)
3217 txtcolour = "colour";
3218 else
3219 txtcolour = "monochrome";
3220 if (panel_type & 2)
3221 txtdual = "dual (split) ";
3222 else
3223 txtdual = "";
3224 tech = (panel_type>>2) & 63;
3225 switch (tech) {
3226 case 0:
3227 txtmonitor = "passive matrix";
3228 break;
3229 case 1:
3230 txtmonitor = "active matrix";
3231 break;
3232 case 2:
3233 txtmonitor = "active addressed STN";
3234 break;
3235 case 3:
3236 txtmonitor = "EL";
3237 break;
3238 case 4:
3239 txtmonitor = "plasma";
3240 break;
3241 default:
3242 txtmonitor = "unknown";
3244 format = *(u32 *)(par->lcd_table+57);
3245 if (tech == 0 || tech == 2) {
3246 switch (format & 7) {
3247 case 0:
3248 txtformat = "12 bit interface";
3249 break;
3250 case 1:
3251 txtformat = "16 bit interface";
3252 break;
3253 case 2:
3254 txtformat = "24 bit interface";
3255 break;
3256 default:
3257 txtformat = "unkown format";
3259 } else {
3260 switch (format & 7) {
3261 case 0:
3262 txtformat = "8 colours";
3263 break;
3264 case 1:
3265 txtformat = "512 colours";
3266 break;
3267 case 2:
3268 txtformat = "4096 colours";
3269 break;
3270 case 4:
3271 txtformat = "262144 colours (LT mode)";
3272 break;
3273 case 5:
3274 txtformat = "16777216 colours";
3275 break;
3276 case 6:
3277 txtformat = "262144 colours (FDPI-2 mode)";
3278 break;
3279 default:
3280 txtformat = "unkown format";
3283 PRINTKI("%s%s %s monitor detected: %s\n",
3284 txtdual ,txtcolour, txtmonitor, model);
3285 PRINTKI(" id=%d, %dx%d pixels, %s\n",
3286 id, width, height, txtformat);
3287 refresh_rates_buf[0] = 0;
3288 refresh_rates = *(u16 *)(par->lcd_table+62);
3289 m = 1;
3290 f = 0;
3291 for (i=0;i<16;i++) {
3292 if (refresh_rates & m) {
3293 if (f == 0) {
3294 sprintf(strbuf, "%d", lcd_refresh_rates[i]);
3295 f++;
3296 } else {
3297 sprintf(strbuf, ",%d", lcd_refresh_rates[i]);
3299 strcat(refresh_rates_buf,strbuf);
3301 m = m << 1;
3303 default_refresh_rate = (*(u8 *)(par->lcd_table+61) & 0xf0) >> 4;
3304 PRINTKI(" supports refresh rates [%s], default %d Hz\n",
3305 refresh_rates_buf, lcd_refresh_rates[default_refresh_rate]);
3306 par->lcd_refreshrate = lcd_refresh_rates[default_refresh_rate];
3307 /* We now need to determine the crtc parameters for the
3308 * LCD monitor. This is tricky, because they are not stored
3309 * individually in the BIOS. Instead, the BIOS contains a
3310 * table of display modes that work for this monitor.
3312 * The idea is that we search for a mode of the same dimensions
3313 * as the dimensions of the LCD monitor. Say our LCD monitor
3314 * is 800x600 pixels, we search for a 800x600 monitor.
3315 * The CRTC parameters we find here are the ones that we need
3316 * to use to simulate other resolutions on the LCD screen.
3318 lcdmodeptr = (u16 *)(par->lcd_table + 64);
3319 while (*lcdmodeptr != 0) {
3320 u32 modeptr;
3321 u16 mwidth, mheight, lcd_hsync_start, lcd_vsync_start;
3322 modeptr = bios_base + *lcdmodeptr;
3324 mwidth = *((u16 *)(modeptr+0));
3325 mheight = *((u16 *)(modeptr+2));
3327 if (mwidth == width && mheight == height) {
3328 par->lcd_pixclock = 100000000 / *((u16 *)(modeptr+9));
3329 par->lcd_htotal = *((u16 *)(modeptr+17)) & 511;
3330 par->lcd_hdisp = *((u16 *)(modeptr+19)) & 511;
3331 lcd_hsync_start = *((u16 *)(modeptr+21)) & 511;
3332 par->lcd_hsync_dly = (*((u16 *)(modeptr+21)) >> 9) & 7;
3333 par->lcd_hsync_len = *((u8 *)(modeptr+23)) & 63;
3335 par->lcd_vtotal = *((u16 *)(modeptr+24)) & 2047;
3336 par->lcd_vdisp = *((u16 *)(modeptr+26)) & 2047;
3337 lcd_vsync_start = *((u16 *)(modeptr+28)) & 2047;
3338 par->lcd_vsync_len = (*((u16 *)(modeptr+28)) >> 11) & 31;
3340 par->lcd_htotal = (par->lcd_htotal + 1) * 8;
3341 par->lcd_hdisp = (par->lcd_hdisp + 1) * 8;
3342 lcd_hsync_start = (lcd_hsync_start + 1) * 8;
3343 par->lcd_hsync_len = par->lcd_hsync_len * 8;
3345 par->lcd_vtotal++;
3346 par->lcd_vdisp++;
3347 lcd_vsync_start++;
3349 par->lcd_right_margin = lcd_hsync_start - par->lcd_hdisp;
3350 par->lcd_lower_margin = lcd_vsync_start - par->lcd_vdisp;
3351 par->lcd_hblank_len = par->lcd_htotal - par->lcd_hdisp;
3352 par->lcd_vblank_len = par->lcd_vtotal - par->lcd_vdisp;
3353 break;
3356 lcdmodeptr++;
3358 if (*lcdmodeptr == 0) {
3359 PRINTKE("LCD monitor CRTC parameters not found!!!\n");
3360 /* To do: Switch to CRT if possible. */
3361 } else {
3362 PRINTKI(" LCD CRTC parameters: %d.%d %d %d %d %d %d %d %d %d\n",
3363 1000000 / par->lcd_pixclock, 1000000 % par->lcd_pixclock,
3364 par->lcd_hdisp,
3365 par->lcd_hdisp + par->lcd_right_margin,
3366 par->lcd_hdisp + par->lcd_right_margin
3367 + par->lcd_hsync_dly + par->lcd_hsync_len,
3368 par->lcd_htotal,
3369 par->lcd_vdisp,
3370 par->lcd_vdisp + par->lcd_lower_margin,
3371 par->lcd_vdisp + par->lcd_lower_margin + par->lcd_vsync_len,
3372 par->lcd_vtotal);
3373 PRINTKI(" : %d %d %d %d %d %d %d %d %d\n",
3374 par->lcd_pixclock,
3375 par->lcd_hblank_len - (par->lcd_right_margin +
3376 par->lcd_hsync_dly + par->lcd_hsync_len),
3377 par->lcd_hdisp,
3378 par->lcd_right_margin,
3379 par->lcd_hsync_len,
3380 par->lcd_vblank_len - (par->lcd_lower_margin + par->lcd_vsync_len),
3381 par->lcd_vdisp,
3382 par->lcd_lower_margin,
3383 par->lcd_vsync_len);
3387 #endif /* CONFIG_FB_ATY_GENERIC_LCD */
3389 static int __devinit init_from_bios(struct atyfb_par *par)
3391 u32 bios_base, rom_addr;
3392 int ret;
3394 rom_addr = 0xc0000 + ((aty_ld_le32(SCRATCH_REG1, par) & 0x7f) << 11);
3395 bios_base = (unsigned long)ioremap(rom_addr, 0x10000);
3397 /* The BIOS starts with 0xaa55. */
3398 if (*((u16 *)bios_base) == 0xaa55) {
3400 u8 *bios_ptr;
3401 u16 rom_table_offset, freq_table_offset;
3402 PLL_BLOCK_MACH64 pll_block;
3404 PRINTKI("Mach64 BIOS is located at %x, mapped at %x.\n", rom_addr, bios_base);
3406 /* check for frequncy table */
3407 bios_ptr = (u8*)bios_base;
3408 rom_table_offset = (u16)(bios_ptr[0x48] | (bios_ptr[0x49] << 8));
3409 freq_table_offset = bios_ptr[rom_table_offset + 16] | (bios_ptr[rom_table_offset + 17] << 8);
3410 memcpy(&pll_block, bios_ptr + freq_table_offset, sizeof(PLL_BLOCK_MACH64));
3412 PRINTKI("BIOS frequency table:\n");
3413 PRINTKI("PCLK_min_freq %d, PCLK_max_freq %d, ref_freq %d, ref_divider %d\n",
3414 pll_block.PCLK_min_freq, pll_block.PCLK_max_freq,
3415 pll_block.ref_freq, pll_block.ref_divider);
3416 PRINTKI("MCLK_pwd %d, MCLK_max_freq %d, XCLK_max_freq %d, SCLK_freq %d\n",
3417 pll_block.MCLK_pwd, pll_block.MCLK_max_freq,
3418 pll_block.XCLK_max_freq, pll_block.SCLK_freq);
3420 par->pll_limits.pll_min = pll_block.PCLK_min_freq/100;
3421 par->pll_limits.pll_max = pll_block.PCLK_max_freq/100;
3422 par->pll_limits.ref_clk = pll_block.ref_freq/100;
3423 par->pll_limits.ref_div = pll_block.ref_divider;
3424 par->pll_limits.sclk = pll_block.SCLK_freq/100;
3425 par->pll_limits.mclk = pll_block.MCLK_max_freq/100;
3426 par->pll_limits.mclk_pm = pll_block.MCLK_pwd/100;
3427 par->pll_limits.xclk = pll_block.XCLK_max_freq/100;
3428 #ifdef CONFIG_FB_ATY_GENERIC_LCD
3429 aty_init_lcd(par, bios_base);
3430 #endif
3431 ret = 0;
3432 } else {
3433 PRINTKE("no BIOS frequency table found, use parameters\n");
3434 ret = -ENXIO;
3436 iounmap((void* __iomem )bios_base);
3438 return ret;
3440 #endif /* __i386__ */
3442 static int __devinit atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info, unsigned long addr)
3444 struct atyfb_par *par = info->par;
3445 u16 tmp;
3446 unsigned long raddr;
3447 struct resource *rrp;
3448 int ret = 0;
3450 raddr = addr + 0x7ff000UL;
3451 rrp = &pdev->resource[2];
3452 if ((rrp->flags & IORESOURCE_MEM) && request_mem_region(rrp->start, rrp->end - rrp->start + 1, "atyfb")) {
3453 par->aux_start = rrp->start;
3454 par->aux_size = rrp->end - rrp->start + 1;
3455 raddr = rrp->start;
3456 PRINTKI("using auxiliary register aperture\n");
3459 info->fix.mmio_start = raddr;
3460 par->ati_regbase = ioremap(info->fix.mmio_start, 0x1000);
3461 if (par->ati_regbase == 0)
3462 return -ENOMEM;
3464 info->fix.mmio_start += par->aux_start ? 0x400 : 0xc00;
3465 par->ati_regbase += par->aux_start ? 0x400 : 0xc00;
3468 * Enable memory-space accesses using config-space
3469 * command register.
3471 pci_read_config_word(pdev, PCI_COMMAND, &tmp);
3472 if (!(tmp & PCI_COMMAND_MEMORY)) {
3473 tmp |= PCI_COMMAND_MEMORY;
3474 pci_write_config_word(pdev, PCI_COMMAND, tmp);
3476 #ifdef __BIG_ENDIAN
3477 /* Use the big-endian aperture */
3478 addr += 0x800000;
3479 #endif
3481 /* Map in frame buffer */
3482 info->fix.smem_start = addr;
3483 info->screen_base = ioremap(addr, 0x800000);
3484 if (info->screen_base == NULL) {
3485 ret = -ENOMEM;
3486 goto atyfb_setup_generic_fail;
3489 if((ret = correct_chipset(par)))
3490 goto atyfb_setup_generic_fail;
3491 #ifdef __i386__
3492 if((ret = init_from_bios(par)))
3493 goto atyfb_setup_generic_fail;
3494 #endif
3495 if (!(aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_EXT_DISP_EN))
3496 par->clk_wr_offset = (inb(R_GENMO) & 0x0CU) >> 2;
3497 else
3498 par->clk_wr_offset = aty_ld_8(CLOCK_CNTL, par) & 0x03U;
3500 /* according to ATI, we should use clock 3 for acelerated mode */
3501 par->clk_wr_offset = 3;
3503 return 0;
3505 atyfb_setup_generic_fail:
3506 iounmap(par->ati_regbase);
3507 par->ati_regbase = NULL;
3508 if (info->screen_base) {
3509 iounmap(info->screen_base);
3510 info->screen_base = NULL;
3512 return ret;
3515 #endif /* !__sparc__ */
3517 static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
3519 unsigned long addr, res_start, res_size;
3520 struct fb_info *info;
3521 struct resource *rp;
3522 struct atyfb_par *par;
3523 int i, rc = -ENOMEM;
3525 for (i = ARRAY_SIZE(aty_chips) - 1; i >= 0; i--)
3526 if (pdev->device == aty_chips[i].pci_id)
3527 break;
3529 if (i < 0)
3530 return -ENODEV;
3532 /* Enable device in PCI config */
3533 if (pci_enable_device(pdev)) {
3534 PRINTKE("Cannot enable PCI device\n");
3535 return -ENXIO;
3538 /* Find which resource to use */
3539 rp = &pdev->resource[0];
3540 if (rp->flags & IORESOURCE_IO)
3541 rp = &pdev->resource[1];
3542 addr = rp->start;
3543 if (!addr)
3544 return -ENXIO;
3546 /* Reserve space */
3547 res_start = rp->start;
3548 res_size = rp->end - rp->start + 1;
3549 if (!request_mem_region (res_start, res_size, "atyfb"))
3550 return -EBUSY;
3552 /* Allocate framebuffer */
3553 info = framebuffer_alloc(sizeof(struct atyfb_par), &pdev->dev);
3554 if (!info) {
3555 PRINTKE("atyfb_pci_probe() can't alloc fb_info\n");
3556 return -ENOMEM;
3558 par = info->par;
3559 info->fix = atyfb_fix;
3560 info->device = &pdev->dev;
3561 par->pci_id = aty_chips[i].pci_id;
3562 par->res_start = res_start;
3563 par->res_size = res_size;
3564 par->irq = pdev->irq;
3565 par->pdev = pdev;
3567 /* Setup "info" structure */
3568 #ifdef __sparc__
3569 rc = atyfb_setup_sparc(pdev, info, addr);
3570 #else
3571 rc = atyfb_setup_generic(pdev, info, addr);
3572 #endif
3573 if (rc)
3574 goto err_release_mem;
3576 pci_set_drvdata(pdev, info);
3578 /* Init chip & register framebuffer */
3579 if (aty_init(info))
3580 goto err_release_io;
3582 #ifdef __sparc__
3583 if (!prom_palette)
3584 prom_palette = atyfb_palette;
3587 * Add /dev/fb mmap values.
3589 par->mmap_map[0].voff = 0x8000000000000000UL;
3590 par->mmap_map[0].poff = (unsigned long) info->screen_base & PAGE_MASK;
3591 par->mmap_map[0].size = info->fix.smem_len;
3592 par->mmap_map[0].prot_mask = _PAGE_CACHE;
3593 par->mmap_map[0].prot_flag = _PAGE_E;
3594 par->mmap_map[1].voff = par->mmap_map[0].voff + info->fix.smem_len;
3595 par->mmap_map[1].poff = (long)par->ati_regbase & PAGE_MASK;
3596 par->mmap_map[1].size = PAGE_SIZE;
3597 par->mmap_map[1].prot_mask = _PAGE_CACHE;
3598 par->mmap_map[1].prot_flag = _PAGE_E;
3599 #endif /* __sparc__ */
3601 return 0;
3603 err_release_io:
3604 #ifdef __sparc__
3605 kfree(par->mmap_map);
3606 #else
3607 if (par->ati_regbase)
3608 iounmap(par->ati_regbase);
3609 if (info->screen_base)
3610 iounmap(info->screen_base);
3611 #endif
3612 err_release_mem:
3613 if (par->aux_start)
3614 release_mem_region(par->aux_start, par->aux_size);
3616 release_mem_region(par->res_start, par->res_size);
3617 framebuffer_release(info);
3619 return rc;
3622 #endif /* CONFIG_PCI */
3624 #ifdef CONFIG_ATARI
3626 static int __init atyfb_atari_probe(void)
3628 struct atyfb_par *par;
3629 struct fb_info *info;
3630 int m64_num;
3631 u32 clock_r;
3632 int num_found = 0;
3634 for (m64_num = 0; m64_num < mach64_count; m64_num++) {
3635 if (!phys_vmembase[m64_num] || !phys_size[m64_num] ||
3636 !phys_guiregbase[m64_num]) {
3637 PRINTKI("phys_*[%d] parameters not set => returning early. \n", m64_num);
3638 continue;
3641 info = framebuffer_alloc(sizeof(struct atyfb_par), NULL);
3642 if (!info) {
3643 PRINTKE("atyfb_atari_probe() can't alloc fb_info\n");
3644 return -ENOMEM;
3646 par = info->par;
3648 info->fix = atyfb_fix;
3650 par->irq = (unsigned int) -1; /* something invalid */
3653 * Map the video memory (physical address given) to somewhere in the
3654 * kernel address space.
3656 info->screen_base = ioremap(phys_vmembase[m64_num], phys_size[m64_num]);
3657 info->fix.smem_start = (unsigned long)info->screen_base; /* Fake! */
3658 par->ati_regbase = ioremap(phys_guiregbase[m64_num], 0x10000) +
3659 0xFC00ul;
3660 info->fix.mmio_start = (unsigned long)par->ati_regbase; /* Fake! */
3662 aty_st_le32(CLOCK_CNTL, 0x12345678, par);
3663 clock_r = aty_ld_le32(CLOCK_CNTL, par);
3665 switch (clock_r & 0x003F) {
3666 case 0x12:
3667 par->clk_wr_offset = 3; /* */
3668 break;
3669 case 0x34:
3670 par->clk_wr_offset = 2; /* Medusa ST-IO ISA Adapter etc. */
3671 break;
3672 case 0x16:
3673 par->clk_wr_offset = 1; /* */
3674 break;
3675 case 0x38:
3676 par->clk_wr_offset = 0; /* Panther 1 ISA Adapter (Gerald) */
3677 break;
3680 /* Fake pci_id for correct_chipset() */
3681 switch (aty_ld_le32(CONFIG_CHIP_ID, par) & CFG_CHIP_TYPE) {
3682 case 0x00d7:
3683 par->pci_id = PCI_CHIP_MACH64GX;
3684 break;
3685 case 0x0057:
3686 par->pci_id = PCI_CHIP_MACH64CX;
3687 break;
3688 default:
3689 break;
3692 if (correct_chipset(par) || aty_init(info)) {
3693 iounmap(info->screen_base);
3694 iounmap(par->ati_regbase);
3695 framebuffer_release(info);
3696 } else {
3697 num_found++;
3701 return num_found ? 0 : -ENXIO;
3704 #endif /* CONFIG_ATARI */
3706 #ifdef CONFIG_PCI
3708 static void __devexit atyfb_remove(struct fb_info *info)
3710 struct atyfb_par *par = (struct atyfb_par *) info->par;
3712 /* restore video mode */
3713 aty_set_crtc(par, &saved_crtc);
3714 par->pll_ops->set_pll(info, &saved_pll);
3716 #ifdef CONFIG_FB_ATY_BACKLIGHT
3717 if (M64_HAS(MOBIL_BUS))
3718 aty_bl_exit(par);
3719 #endif
3721 unregister_framebuffer(info);
3723 #ifdef CONFIG_MTRR
3724 if (par->mtrr_reg >= 0) {
3725 mtrr_del(par->mtrr_reg, 0, 0);
3726 par->mtrr_reg = -1;
3728 if (par->mtrr_aper >= 0) {
3729 mtrr_del(par->mtrr_aper, 0, 0);
3730 par->mtrr_aper = -1;
3732 #endif
3733 #ifndef __sparc__
3734 if (par->ati_regbase)
3735 iounmap(par->ati_regbase);
3736 if (info->screen_base)
3737 iounmap(info->screen_base);
3738 #ifdef __BIG_ENDIAN
3739 if (info->sprite.addr)
3740 iounmap(info->sprite.addr);
3741 #endif
3742 #endif
3743 #ifdef __sparc__
3744 kfree(par->mmap_map);
3745 #endif
3746 if (par->aux_start)
3747 release_mem_region(par->aux_start, par->aux_size);
3749 if (par->res_start)
3750 release_mem_region(par->res_start, par->res_size);
3752 framebuffer_release(info);
3756 static void __devexit atyfb_pci_remove(struct pci_dev *pdev)
3758 struct fb_info *info = pci_get_drvdata(pdev);
3760 atyfb_remove(info);
3764 * This driver uses its own matching table. That will be more difficult
3765 * to fix, so for now, we just match against any ATI ID and let the
3766 * probe() function find out what's up. That also mean we don't have
3767 * a module ID table though.
3769 static struct pci_device_id atyfb_pci_tbl[] = {
3770 { PCI_VENDOR_ID_ATI, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
3771 PCI_BASE_CLASS_DISPLAY << 16, 0xff0000, 0 },
3772 { 0, }
3775 static struct pci_driver atyfb_driver = {
3776 .name = "atyfb",
3777 .id_table = atyfb_pci_tbl,
3778 .probe = atyfb_pci_probe,
3779 .remove = __devexit_p(atyfb_pci_remove),
3780 #ifdef CONFIG_PM
3781 .suspend = atyfb_pci_suspend,
3782 .resume = atyfb_pci_resume,
3783 #endif /* CONFIG_PM */
3786 #endif /* CONFIG_PCI */
3788 #ifndef MODULE
3789 static int __init atyfb_setup(char *options)
3791 char *this_opt;
3793 if (!options || !*options)
3794 return 0;
3796 while ((this_opt = strsep(&options, ",")) != NULL) {
3797 if (!strncmp(this_opt, "noaccel", 7)) {
3798 noaccel = 1;
3799 #ifdef CONFIG_MTRR
3800 } else if (!strncmp(this_opt, "nomtrr", 6)) {
3801 nomtrr = 1;
3802 #endif
3803 } else if (!strncmp(this_opt, "vram:", 5))
3804 vram = simple_strtoul(this_opt + 5, NULL, 0);
3805 else if (!strncmp(this_opt, "pll:", 4))
3806 pll = simple_strtoul(this_opt + 4, NULL, 0);
3807 else if (!strncmp(this_opt, "mclk:", 5))
3808 mclk = simple_strtoul(this_opt + 5, NULL, 0);
3809 else if (!strncmp(this_opt, "xclk:", 5))
3810 xclk = simple_strtoul(this_opt+5, NULL, 0);
3811 else if (!strncmp(this_opt, "comp_sync:", 10))
3812 comp_sync = simple_strtoul(this_opt+10, NULL, 0);
3813 #ifdef CONFIG_PPC
3814 else if (!strncmp(this_opt, "vmode:", 6)) {
3815 unsigned int vmode =
3816 simple_strtoul(this_opt + 6, NULL, 0);
3817 if (vmode > 0 && vmode <= VMODE_MAX)
3818 default_vmode = vmode;
3819 } else if (!strncmp(this_opt, "cmode:", 6)) {
3820 unsigned int cmode =
3821 simple_strtoul(this_opt + 6, NULL, 0);
3822 switch (cmode) {
3823 case 0:
3824 case 8:
3825 default_cmode = CMODE_8;
3826 break;
3827 case 15:
3828 case 16:
3829 default_cmode = CMODE_16;
3830 break;
3831 case 24:
3832 case 32:
3833 default_cmode = CMODE_32;
3834 break;
3837 #endif
3838 #ifdef CONFIG_ATARI
3840 * Why do we need this silly Mach64 argument?
3841 * We are already here because of mach64= so its redundant.
3843 else if (MACH_IS_ATARI
3844 && (!strncmp(this_opt, "Mach64:", 7))) {
3845 static unsigned char m64_num;
3846 static char mach64_str[80];
3847 strlcpy(mach64_str, this_opt + 7, sizeof(mach64_str));
3848 if (!store_video_par(mach64_str, m64_num)) {
3849 m64_num++;
3850 mach64_count = m64_num;
3853 #endif
3854 else
3855 mode = this_opt;
3857 return 0;
3859 #endif /* MODULE */
3861 static int __init atyfb_init(void)
3863 int err1 = 1, err2 = 1;
3864 #ifndef MODULE
3865 char *option = NULL;
3867 if (fb_get_options("atyfb", &option))
3868 return -ENODEV;
3869 atyfb_setup(option);
3870 #endif
3872 #ifdef CONFIG_PCI
3873 err1 = pci_register_driver(&atyfb_driver);
3874 #endif
3875 #ifdef CONFIG_ATARI
3876 err2 = atyfb_atari_probe();
3877 #endif
3879 return (err1 && err2) ? -ENODEV : 0;
3882 static void __exit atyfb_exit(void)
3884 #ifdef CONFIG_PCI
3885 pci_unregister_driver(&atyfb_driver);
3886 #endif
3889 module_init(atyfb_init);
3890 module_exit(atyfb_exit);
3892 MODULE_DESCRIPTION("FBDev driver for ATI Mach64 cards");
3893 MODULE_LICENSE("GPL");
3894 module_param(noaccel, bool, 0);
3895 MODULE_PARM_DESC(noaccel, "bool: disable acceleration");
3896 module_param(vram, int, 0);
3897 MODULE_PARM_DESC(vram, "int: override size of video ram");
3898 module_param(pll, int, 0);
3899 MODULE_PARM_DESC(pll, "int: override video clock");
3900 module_param(mclk, int, 0);
3901 MODULE_PARM_DESC(mclk, "int: override memory clock");
3902 module_param(xclk, int, 0);
3903 MODULE_PARM_DESC(xclk, "int: override accelerated engine clock");
3904 module_param(comp_sync, int, 0);
3905 MODULE_PARM_DESC(comp_sync,
3906 "Set composite sync signal to low (0) or high (1)");
3907 module_param(mode, charp, 0);
3908 MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
3909 #ifdef CONFIG_MTRR
3910 module_param(nomtrr, bool, 0);
3911 MODULE_PARM_DESC(nomtrr, "bool: disable use of MTRR registers");
3912 #endif