2 * ATI Frame Buffer Device Driver Core
4 * Copyright (C) 2004 Alex Kern <alex.kern@gmx.de>
5 * Copyright (C) 1997-2001 Geert Uytterhoeven
6 * Copyright (C) 1998 Bernd Harries
7 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
9 * This driver supports the following ATI graphics chips:
12 * To do: add support for
13 * - ATI Rage128 (from aty128fb.c)
14 * - ATI Radeon (from radeonfb.c)
16 * This driver is partly based on the PowerMac console driver:
18 * Copyright (C) 1996 Paul Mackerras
20 * and on the PowerMac ATI/mach64 display driver:
22 * Copyright (C) 1997 Michael AK Tesch
24 * with work by Jon Howell
26 * Anthony Tong <atong@uiuc.edu>
28 * Generic LCD support written by Daniel Mantione, ported from 2.4.20 by Alex Kern
29 * Many Thanks to Ville Syrjälä for patches and fixing nasting 16 bit color bug.
31 * This file is subject to the terms and conditions of the GNU General Public
32 * License. See the file COPYING in the main directory of this archive for
35 * Many thanks to Nitya from ATI devrel for support and patience !
38 /******************************************************************************
42 - cursor support on all cards and all ramdacs.
43 - cursor parameters controlable via ioctl()s.
44 - guess PLL and MCLK based on the original PLL register values initialized
45 by Open Firmware (if they are initialized). BIOS is done
47 (Anyone with Mac to help with this?)
49 ******************************************************************************/
51 #include <linux/compat.h>
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>
58 #include <linux/slab.h>
59 #include <linux/vmalloc.h>
60 #include <linux/delay.h>
61 #include <linux/compiler.h>
62 #include <linux/console.h>
64 #include <linux/init.h>
65 #include <linux/pci.h>
66 #include <linux/interrupt.h>
67 #include <linux/spinlock.h>
68 #include <linux/wait.h>
69 #include <linux/backlight.h>
70 #include <linux/reboot.h>
71 #include <linux/dmi.h>
74 #include <linux/uaccess.h>
76 #include <video/mach64.h>
81 #include <asm/machdep.h>
83 #include "../macmodes.h"
87 #include <asm/oplib.h>
92 #include <linux/adb.h>
93 #include <linux/pmu.h>
95 #ifdef CONFIG_BOOTX_TEXT
96 #include <asm/btext.h>
98 #ifdef CONFIG_PMAC_BACKLIGHT
99 #include <asm/backlight.h>
108 /* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */
109 /* - must be large enough to catch all GUI-Regs */
110 /* - must be aligned to a PAGE boundary */
111 #define GUI_RESERVE (1 * PAGE_SIZE)
113 /* FIXME: remove the FAIL definition */
114 #define FAIL(msg) do { \
115 if (!(var->activate & FB_ACTIVATE_TEST)) \
116 printk(KERN_CRIT "atyfb: " msg "\n"); \
119 #define FAIL_MAX(msg, x, _max_) do { \
121 if (!(var->activate & FB_ACTIVATE_TEST)) \
122 printk(KERN_CRIT "atyfb: " msg " %x(%x)\n", x, _max_); \
127 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "atyfb: " fmt, ## args)
129 #define DPRINTK(fmt, args...)
132 #define PRINTKI(fmt, args...) printk(KERN_INFO "atyfb: " fmt, ## args)
133 #define PRINTKE(fmt, args...) printk(KERN_ERR "atyfb: " fmt, ## args)
135 #if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \
136 defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT)
137 static const u32 lt_lcd_regs[] = {
144 0, /* EXT_VERT_STRETCH */
149 void aty_st_lcd(int index, u32 val, const struct atyfb_par *par)
151 if (M64_HAS(LT_LCD_REGS)) {
152 aty_st_le32(lt_lcd_regs[index], val, par);
156 /* write addr byte */
157 temp = aty_ld_le32(LCD_INDEX, par);
158 aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par);
159 /* write the register value */
160 aty_st_le32(LCD_DATA, val, par);
164 u32 aty_ld_lcd(int index, const struct atyfb_par *par)
166 if (M64_HAS(LT_LCD_REGS)) {
167 return aty_ld_le32(lt_lcd_regs[index], par);
171 /* write addr byte */
172 temp = aty_ld_le32(LCD_INDEX, par);
173 aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par);
174 /* read the register value */
175 return aty_ld_le32(LCD_DATA, par);
178 #endif /* defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD) */
180 #ifdef CONFIG_FB_ATY_GENERIC_LCD
184 * Reduce a fraction by factoring out the largest common divider of the
185 * fraction's numerator and denominator.
187 static void ATIReduceRatio(int *Numerator, int *Denominator)
189 int Multiplier, Divider, Remainder;
191 Multiplier = *Numerator;
192 Divider = *Denominator;
194 while ((Remainder = Multiplier % Divider)) {
195 Multiplier = Divider;
199 *Numerator /= Divider;
200 *Denominator /= Divider;
204 * The Hardware parameters for each card
207 struct pci_mmap_map {
211 unsigned long prot_flag;
212 unsigned long prot_mask;
215 static const struct fb_fix_screeninfo atyfb_fix = {
217 .type = FB_TYPE_PACKED_PIXELS,
218 .visual = FB_VISUAL_PSEUDOCOLOR,
224 * Frame buffer device API
227 static int atyfb_open(struct fb_info *info, int user);
228 static int atyfb_release(struct fb_info *info, int user);
229 static int atyfb_check_var(struct fb_var_screeninfo *var,
230 struct fb_info *info);
231 static int atyfb_set_par(struct fb_info *info);
232 static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
233 u_int transp, struct fb_info *info);
234 static int atyfb_pan_display(struct fb_var_screeninfo *var,
235 struct fb_info *info);
236 static int atyfb_blank(int blank, struct fb_info *info);
237 static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg);
239 static int atyfb_compat_ioctl(struct fb_info *info, u_int cmd, u_long arg)
241 return atyfb_ioctl(info, cmd, (u_long)compat_ptr(arg));
246 static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma);
248 static int atyfb_sync(struct fb_info *info);
254 static int aty_init(struct fb_info *info);
256 static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc);
258 static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc);
259 static int aty_var_to_crtc(const struct fb_info *info,
260 const struct fb_var_screeninfo *var,
262 static int aty_crtc_to_var(const struct crtc *crtc,
263 struct fb_var_screeninfo *var);
264 static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info);
266 static int read_aty_sense(const struct atyfb_par *par);
269 static DEFINE_MUTEX(reboot_lock);
270 static struct fb_info *reboot_info;
273 * Interface used by the world
276 static struct fb_var_screeninfo default_var = {
277 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
278 640, 480, 640, 480, 0, 0, 8, 0,
279 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
280 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
281 0, FB_VMODE_NONINTERLACED
284 static const struct fb_videomode defmode = {
285 /* 640x480 @ 60 Hz, 31.5 kHz hsync */
286 NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
287 0, FB_VMODE_NONINTERLACED
290 static struct fb_ops atyfb_ops = {
291 .owner = THIS_MODULE,
292 .fb_open = atyfb_open,
293 .fb_release = atyfb_release,
294 .fb_check_var = atyfb_check_var,
295 .fb_set_par = atyfb_set_par,
296 .fb_setcolreg = atyfb_setcolreg,
297 .fb_pan_display = atyfb_pan_display,
298 .fb_blank = atyfb_blank,
299 .fb_ioctl = atyfb_ioctl,
301 .fb_compat_ioctl = atyfb_compat_ioctl,
303 .fb_fillrect = atyfb_fillrect,
304 .fb_copyarea = atyfb_copyarea,
305 .fb_imageblit = atyfb_imageblit,
307 .fb_mmap = atyfb_mmap,
309 .fb_sync = atyfb_sync,
318 static int comp_sync = -1;
321 #ifdef CONFIG_PMAC_BACKLIGHT
322 static int backlight = 1;
324 static int backlight = 0;
328 static int default_vmode = VMODE_CHOOSE;
329 static int default_cmode = CMODE_CHOOSE;
331 module_param_named(vmode, default_vmode, int, 0);
332 MODULE_PARM_DESC(vmode, "int: video mode for mac");
333 module_param_named(cmode, default_cmode, int, 0);
334 MODULE_PARM_DESC(cmode, "int: color mode for mac");
338 static unsigned int mach64_count = 0;
339 static unsigned long phys_vmembase[FB_MAX] = { 0, };
340 static unsigned long phys_size[FB_MAX] = { 0, };
341 static unsigned long phys_guiregbase[FB_MAX] = { 0, };
344 /* top -> down is an evolution of mach64 chipset, any corrections? */
345 #define ATI_CHIP_88800GX (M64F_GX)
346 #define ATI_CHIP_88800CX (M64F_GX)
348 #define ATI_CHIP_264CT (M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO)
349 #define ATI_CHIP_264ET (M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO)
351 #define ATI_CHIP_264VT (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO)
352 #define ATI_CHIP_264GT (M64F_GT | M64F_INTEGRATED | M64F_MAGIC_FIFO | M64F_EXTRA_BRIGHT)
354 #define ATI_CHIP_264VTB (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP)
355 #define ATI_CHIP_264VT3 (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL)
356 #define ATI_CHIP_264VT4 (M64F_VT | M64F_INTEGRATED | M64F_GTB_DSP)
358 /* FIXME what is this chip? */
359 #define ATI_CHIP_264LT (M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP)
361 /* make sets shorter */
362 #define ATI_MODERN_SET (M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_EXTRA_BRIGHT)
364 #define ATI_CHIP_264GTB (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL)
365 /*#define ATI_CHIP_264GTDVD ?*/
366 #define ATI_CHIP_264LTG (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL)
368 #define ATI_CHIP_264GT2C (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE)
369 #define ATI_CHIP_264GTPRO (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
370 #define ATI_CHIP_264LTPRO (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
372 #define ATI_CHIP_264XL (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_XL_MEM)
373 #define ATI_CHIP_MOBILITY (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_XL_MEM | M64F_MOBIL_BUS)
378 int pll, mclk, xclk, ecp_max;
381 #ifdef CONFIG_FB_ATY_GX
383 { PCI_CHIP_MACH64GX, "ATI888GX00 (Mach64 GX)", 135, 50, 50, 0, ATI_CHIP_88800GX },
384 { PCI_CHIP_MACH64CX, "ATI888CX00 (Mach64 CX)", 135, 50, 50, 0, ATI_CHIP_88800CX },
385 #endif /* CONFIG_FB_ATY_GX */
387 #ifdef CONFIG_FB_ATY_CT
388 { PCI_CHIP_MACH64CT, "ATI264CT (Mach64 CT)", 135, 60, 60, 0, ATI_CHIP_264CT },
389 { PCI_CHIP_MACH64ET, "ATI264ET (Mach64 ET)", 135, 60, 60, 0, ATI_CHIP_264ET },
391 /* FIXME what is this chip? */
392 { PCI_CHIP_MACH64LT, "ATI264LT (Mach64 LT)", 135, 63, 63, 0, ATI_CHIP_264LT },
394 { PCI_CHIP_MACH64VT, "ATI264VT (Mach64 VT)", 170, 67, 67, 80, ATI_CHIP_264VT },
395 { PCI_CHIP_MACH64GT, "3D RAGE (Mach64 GT)", 135, 63, 63, 80, ATI_CHIP_264GT },
397 { PCI_CHIP_MACH64VU, "ATI264VT3 (Mach64 VU)", 200, 67, 67, 80, ATI_CHIP_264VT3 },
398 { PCI_CHIP_MACH64GU, "3D RAGE II+ (Mach64 GU)", 200, 67, 67, 100, ATI_CHIP_264GTB },
400 { PCI_CHIP_MACH64LG, "3D RAGE LT (Mach64 LG)", 230, 63, 63, 100, ATI_CHIP_264LTG | M64F_LT_LCD_REGS | M64F_G3_PB_1024x768 },
402 { PCI_CHIP_MACH64VV, "ATI264VT4 (Mach64 VV)", 230, 83, 83, 100, ATI_CHIP_264VT4 },
404 { PCI_CHIP_MACH64GV, "3D RAGE IIC (Mach64 GV, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
405 { PCI_CHIP_MACH64GW, "3D RAGE IIC (Mach64 GW, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
406 { PCI_CHIP_MACH64GY, "3D RAGE IIC (Mach64 GY, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
407 { PCI_CHIP_MACH64GZ, "3D RAGE IIC (Mach64 GZ, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
409 { PCI_CHIP_MACH64GB, "3D RAGE PRO (Mach64 GB, BGA, AGP)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
410 { PCI_CHIP_MACH64GD, "3D RAGE PRO (Mach64 GD, BGA, AGP 1x)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
411 { PCI_CHIP_MACH64GI, "3D RAGE PRO (Mach64 GI, BGA, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO | M64F_MAGIC_VRAM_SIZE },
412 { PCI_CHIP_MACH64GP, "3D RAGE PRO (Mach64 GP, PQFP, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
413 { PCI_CHIP_MACH64GQ, "3D RAGE PRO (Mach64 GQ, PQFP, PCI, limited 3D)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
415 { PCI_CHIP_MACH64LB, "3D RAGE LT PRO (Mach64 LB, AGP)", 236, 75, 100, 135, ATI_CHIP_264LTPRO },
416 { PCI_CHIP_MACH64LD, "3D RAGE LT PRO (Mach64 LD, AGP)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
417 { 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 },
418 { PCI_CHIP_MACH64LP, "3D RAGE LT PRO (Mach64 LP, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO | M64F_G3_PB_1024x768 },
419 { PCI_CHIP_MACH64LQ, "3D RAGE LT PRO (Mach64 LQ, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
421 { PCI_CHIP_MACH64GM, "3D RAGE XL (Mach64 GM, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL },
422 { PCI_CHIP_MACH64GN, "3D RAGE XC (Mach64 GN, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL },
423 { PCI_CHIP_MACH64GO, "3D RAGE XL (Mach64 GO, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL },
424 { PCI_CHIP_MACH64GL, "3D RAGE XC (Mach64 GL, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL },
425 { PCI_CHIP_MACH64GR, "3D RAGE XL (Mach64 GR, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL | M64F_SDRAM_MAGIC_PLL },
426 { PCI_CHIP_MACH64GS, "3D RAGE XC (Mach64 GS, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL },
428 { PCI_CHIP_MACH64LM, "3D RAGE Mobility P/M (Mach64 LM, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
429 { PCI_CHIP_MACH64LN, "3D RAGE Mobility L (Mach64 LN, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
430 { PCI_CHIP_MACH64LR, "3D RAGE Mobility P/M (Mach64 LR, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
431 { PCI_CHIP_MACH64LS, "3D RAGE Mobility L (Mach64 LS, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
432 #endif /* CONFIG_FB_ATY_CT */
436 * Last page of 8 MB (4 MB on ISA) aperture is MMIO,
437 * unless the auxiliary register aperture is used.
439 static void aty_fudge_framebuffer_len(struct fb_info *info)
441 struct atyfb_par *par = (struct atyfb_par *) info->par;
443 if (!par->aux_start &&
444 (info->fix.smem_len == 0x800000 ||
445 (par->bus_type == ISA && info->fix.smem_len == 0x400000)))
446 info->fix.smem_len -= GUI_RESERVE;
449 static int correct_chipset(struct atyfb_par *par)
457 for (i = (int)ARRAY_SIZE(aty_chips) - 1; i >= 0; i--)
458 if (par->pci_id == aty_chips[i].pci_id)
464 name = aty_chips[i].name;
465 par->pll_limits.pll_max = aty_chips[i].pll;
466 par->pll_limits.mclk = aty_chips[i].mclk;
467 par->pll_limits.xclk = aty_chips[i].xclk;
468 par->pll_limits.ecp_max = aty_chips[i].ecp_max;
469 par->features = aty_chips[i].features;
471 chip_id = aty_ld_le32(CNFG_CHIP_ID, par);
472 type = chip_id & CFG_CHIP_TYPE;
473 rev = (chip_id & CFG_CHIP_REV) >> 24;
475 switch (par->pci_id) {
476 #ifdef CONFIG_FB_ATY_GX
477 case PCI_CHIP_MACH64GX:
481 case PCI_CHIP_MACH64CX:
486 #ifdef CONFIG_FB_ATY_CT
487 case PCI_CHIP_MACH64VT:
488 switch (rev & 0x07) {
490 switch (rev & 0xc0) {
492 name = "ATI264VT (A3) (Mach64 VT)";
493 par->pll_limits.pll_max = 170;
494 par->pll_limits.mclk = 67;
495 par->pll_limits.xclk = 67;
496 par->pll_limits.ecp_max = 80;
497 par->features = ATI_CHIP_264VT;
500 name = "ATI264VT2 (A4) (Mach64 VT)";
501 par->pll_limits.pll_max = 200;
502 par->pll_limits.mclk = 67;
503 par->pll_limits.xclk = 67;
504 par->pll_limits.ecp_max = 80;
505 par->features = ATI_CHIP_264VT | M64F_MAGIC_POSTDIV;
510 name = "ATI264VT3 (B1) (Mach64 VT)";
511 par->pll_limits.pll_max = 200;
512 par->pll_limits.mclk = 67;
513 par->pll_limits.xclk = 67;
514 par->pll_limits.ecp_max = 80;
515 par->features = ATI_CHIP_264VTB;
518 name = "ATI264VT3 (B2) (Mach64 VT)";
519 par->pll_limits.pll_max = 200;
520 par->pll_limits.mclk = 67;
521 par->pll_limits.xclk = 67;
522 par->pll_limits.ecp_max = 80;
523 par->features = ATI_CHIP_264VT3;
527 case PCI_CHIP_MACH64GT:
528 switch (rev & 0x07) {
530 name = "3D RAGE II (Mach64 GT)";
531 par->pll_limits.pll_max = 170;
532 par->pll_limits.mclk = 67;
533 par->pll_limits.xclk = 67;
534 par->pll_limits.ecp_max = 80;
535 par->features = ATI_CHIP_264GTB;
538 name = "3D RAGE II+ (Mach64 GT)";
539 par->pll_limits.pll_max = 200;
540 par->pll_limits.mclk = 67;
541 par->pll_limits.xclk = 67;
542 par->pll_limits.ecp_max = 100;
543 par->features = ATI_CHIP_264GTB;
550 PRINTKI("%s [0x%04x rev 0x%02x]\n", name, type, rev);
554 static char ram_dram[] __maybe_unused = "DRAM";
555 static char ram_resv[] __maybe_unused = "RESV";
556 #ifdef CONFIG_FB_ATY_GX
557 static char ram_vram[] = "VRAM";
558 #endif /* CONFIG_FB_ATY_GX */
559 #ifdef CONFIG_FB_ATY_CT
560 static char ram_edo[] = "EDO";
561 static char ram_sdram[] = "SDRAM (1:1)";
562 static char ram_sgram[] = "SGRAM (1:1)";
563 static char ram_sdram32[] = "SDRAM (2:1) (32-bit)";
564 static char ram_wram[] = "WRAM";
565 static char ram_off[] = "OFF";
566 #endif /* CONFIG_FB_ATY_CT */
569 #ifdef CONFIG_FB_ATY_GX
570 static char *aty_gx_ram[8] = {
571 ram_dram, ram_vram, ram_vram, ram_dram,
572 ram_dram, ram_vram, ram_vram, ram_resv
574 #endif /* CONFIG_FB_ATY_GX */
576 #ifdef CONFIG_FB_ATY_CT
577 static char *aty_ct_ram[8] = {
578 ram_off, ram_dram, ram_edo, ram_edo,
579 ram_sdram, ram_sgram, ram_wram, ram_resv
581 static char *aty_xl_ram[8] = {
582 ram_off, ram_dram, ram_edo, ram_edo,
583 ram_sdram, ram_sgram, ram_sdram32, ram_resv
585 #endif /* CONFIG_FB_ATY_CT */
587 static u32 atyfb_get_pixclock(struct fb_var_screeninfo *var,
588 struct atyfb_par *par)
590 u32 pixclock = var->pixclock;
591 #ifdef CONFIG_FB_ATY_GENERIC_LCD
593 par->pll.ct.xres = 0;
594 if (par->lcd_table != 0) {
595 lcd_on_off = aty_ld_lcd(LCD_GEN_CNTL, par);
596 if (lcd_on_off & LCD_ON) {
597 par->pll.ct.xres = var->xres;
598 pixclock = par->lcd_pixclock;
605 #if defined(CONFIG_PPC)
608 * Apple monitor sense
611 static int read_aty_sense(const struct atyfb_par *par)
615 aty_st_le32(GP_IO, 0x31003100, par); /* drive outputs high */
617 aty_st_le32(GP_IO, 0, par); /* turn off outputs */
619 i = aty_ld_le32(GP_IO, par); /* get primary sense value */
620 sense = ((i & 0x3000) >> 3) | (i & 0x100);
622 /* drive each sense line low in turn and collect the other 2 */
623 aty_st_le32(GP_IO, 0x20000000, par); /* drive A low */
625 i = aty_ld_le32(GP_IO, par);
626 sense |= ((i & 0x1000) >> 7) | ((i & 0x100) >> 4);
627 aty_st_le32(GP_IO, 0x20002000, par); /* drive A high again */
630 aty_st_le32(GP_IO, 0x10000000, par); /* drive B low */
632 i = aty_ld_le32(GP_IO, par);
633 sense |= ((i & 0x2000) >> 10) | ((i & 0x100) >> 6);
634 aty_st_le32(GP_IO, 0x10001000, par); /* drive B high again */
637 aty_st_le32(GP_IO, 0x01000000, par); /* drive C low */
639 sense |= (aty_ld_le32(GP_IO, par) & 0x3000) >> 12;
640 aty_st_le32(GP_IO, 0, par); /* turn off outputs */
644 #endif /* defined(CONFIG_PPC) */
646 /* ------------------------------------------------------------------------- */
652 static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc)
654 #ifdef CONFIG_FB_ATY_GENERIC_LCD
655 if (par->lcd_table != 0) {
656 if (!M64_HAS(LT_LCD_REGS)) {
657 crtc->lcd_index = aty_ld_le32(LCD_INDEX, par);
658 aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
660 crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par);
661 crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par);
664 /* switch to non shadow registers */
665 aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
666 ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
668 /* save stretching */
669 crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par);
670 crtc->vert_stretching = aty_ld_lcd(VERT_STRETCHING, par);
671 if (!M64_HAS(LT_LCD_REGS))
672 crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par);
675 crtc->h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
676 crtc->h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
677 crtc->v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
678 crtc->v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
679 crtc->vline_crnt_vline = aty_ld_le32(CRTC_VLINE_CRNT_VLINE, par);
680 crtc->off_pitch = aty_ld_le32(CRTC_OFF_PITCH, par);
681 crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
683 #ifdef CONFIG_FB_ATY_GENERIC_LCD
684 if (par->lcd_table != 0) {
685 /* switch to shadow registers */
686 aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |
687 SHADOW_EN | SHADOW_RW_EN, par);
689 crtc->shadow_h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
690 crtc->shadow_h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
691 crtc->shadow_v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
692 crtc->shadow_v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
694 aty_st_le32(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);
696 #endif /* CONFIG_FB_ATY_GENERIC_LCD */
699 static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc)
701 #ifdef CONFIG_FB_ATY_GENERIC_LCD
702 if (par->lcd_table != 0) {
704 aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl &
705 ~(CRTC_EXT_DISP_EN | CRTC_EN), par);
707 /* update non-shadow registers first */
708 aty_st_lcd(CNFG_PANEL, crtc->lcd_config_panel, par);
709 aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
710 ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
712 /* temporarily disable stretching */
713 aty_st_lcd(HORZ_STRETCHING, crtc->horz_stretching &
714 ~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN), par);
715 aty_st_lcd(VERT_STRETCHING, crtc->vert_stretching &
716 ~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 |
717 VERT_STRETCH_USE0 | VERT_STRETCH_EN), par);
721 aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~CRTC_EN, par);
723 DPRINTK("setting up CRTC\n");
724 DPRINTK("set primary CRT to %ix%i %c%c composite %c\n",
725 ((((crtc->h_tot_disp >> 16) & 0xff) + 1) << 3),
726 (((crtc->v_tot_disp >> 16) & 0x7ff) + 1),
727 (crtc->h_sync_strt_wid & 0x200000) ? 'N' : 'P',
728 (crtc->v_sync_strt_wid & 0x200000) ? 'N' : 'P',
729 (crtc->gen_cntl & CRTC_CSYNC_EN) ? 'P' : 'N');
731 DPRINTK("CRTC_H_TOTAL_DISP: %x\n", crtc->h_tot_disp);
732 DPRINTK("CRTC_H_SYNC_STRT_WID: %x\n", crtc->h_sync_strt_wid);
733 DPRINTK("CRTC_V_TOTAL_DISP: %x\n", crtc->v_tot_disp);
734 DPRINTK("CRTC_V_SYNC_STRT_WID: %x\n", crtc->v_sync_strt_wid);
735 DPRINTK("CRTC_OFF_PITCH: %x\n", crtc->off_pitch);
736 DPRINTK("CRTC_VLINE_CRNT_VLINE: %x\n", crtc->vline_crnt_vline);
737 DPRINTK("CRTC_GEN_CNTL: %x\n", crtc->gen_cntl);
739 aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, par);
740 aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, par);
741 aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_tot_disp, par);
742 aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid, par);
743 aty_st_le32(CRTC_OFF_PITCH, crtc->off_pitch, par);
744 aty_st_le32(CRTC_VLINE_CRNT_VLINE, crtc->vline_crnt_vline, par);
746 aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl, par);
749 if (par->accel_flags & FB_ACCELF_TEXT)
750 aty_init_engine(par, info);
752 #ifdef CONFIG_FB_ATY_GENERIC_LCD
753 /* after setting the CRTC registers we should set the LCD registers. */
754 if (par->lcd_table != 0) {
755 /* switch to shadow registers */
756 aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |
757 SHADOW_EN | SHADOW_RW_EN, par);
759 DPRINTK("set shadow CRT to %ix%i %c%c\n",
760 ((((crtc->shadow_h_tot_disp >> 16) & 0xff) + 1) << 3),
761 (((crtc->shadow_v_tot_disp >> 16) & 0x7ff) + 1),
762 (crtc->shadow_h_sync_strt_wid & 0x200000) ? 'N' : 'P',
763 (crtc->shadow_v_sync_strt_wid & 0x200000) ? 'N' : 'P');
765 DPRINTK("SHADOW CRTC_H_TOTAL_DISP: %x\n",
766 crtc->shadow_h_tot_disp);
767 DPRINTK("SHADOW CRTC_H_SYNC_STRT_WID: %x\n",
768 crtc->shadow_h_sync_strt_wid);
769 DPRINTK("SHADOW CRTC_V_TOTAL_DISP: %x\n",
770 crtc->shadow_v_tot_disp);
771 DPRINTK("SHADOW CRTC_V_SYNC_STRT_WID: %x\n",
772 crtc->shadow_v_sync_strt_wid);
774 aty_st_le32(CRTC_H_TOTAL_DISP, crtc->shadow_h_tot_disp, par);
775 aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->shadow_h_sync_strt_wid, par);
776 aty_st_le32(CRTC_V_TOTAL_DISP, crtc->shadow_v_tot_disp, par);
777 aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->shadow_v_sync_strt_wid, par);
779 /* restore CRTC selection & shadow state and enable stretching */
780 DPRINTK("LCD_GEN_CNTL: %x\n", crtc->lcd_gen_cntl);
781 DPRINTK("HORZ_STRETCHING: %x\n", crtc->horz_stretching);
782 DPRINTK("VERT_STRETCHING: %x\n", crtc->vert_stretching);
783 if (!M64_HAS(LT_LCD_REGS))
784 DPRINTK("EXT_VERT_STRETCH: %x\n", crtc->ext_vert_stretch);
786 aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);
787 aty_st_lcd(HORZ_STRETCHING, crtc->horz_stretching, par);
788 aty_st_lcd(VERT_STRETCHING, crtc->vert_stretching, par);
789 if (!M64_HAS(LT_LCD_REGS)) {
790 aty_st_lcd(EXT_VERT_STRETCH, crtc->ext_vert_stretch, par);
791 aty_ld_le32(LCD_INDEX, par);
792 aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
795 #endif /* CONFIG_FB_ATY_GENERIC_LCD */
798 static u32 calc_line_length(struct atyfb_par *par, u32 vxres, u32 bpp)
800 u32 line_length = vxres * bpp / 8;
802 if (par->ram_type == SGRAM ||
803 (!M64_HAS(XL_MEM) && par->ram_type == WRAM))
804 line_length = (line_length + 63) & ~63;
809 static int aty_var_to_crtc(const struct fb_info *info,
810 const struct fb_var_screeninfo *var,
813 struct atyfb_par *par = (struct atyfb_par *) info->par;
814 u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
816 u32 h_total, h_disp, h_sync_strt, h_sync_end, h_sync_dly, h_sync_wid, h_sync_pol;
817 u32 v_total, v_disp, v_sync_strt, v_sync_end, v_sync_wid, v_sync_pol, c_sync;
818 u32 pix_width, dp_pix_width, dp_chain_mask;
822 xres = (var->xres + 7) & ~7;
824 vxres = (var->xres_virtual + 7) & ~7;
825 vyres = var->yres_virtual;
826 xoffset = (var->xoffset + 7) & ~7;
827 yoffset = var->yoffset;
828 bpp = var->bits_per_pixel;
830 bpp = (var->green.length == 5) ? 15 : 16;
834 /* convert (and round up) and validate */
835 if (vxres < xres + xoffset)
836 vxres = xres + xoffset;
839 if (vyres < yres + yoffset)
840 vyres = yres + yoffset;
845 pix_width = CRTC_PIX_WIDTH_8BPP;
846 dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP |
847 BYTE_ORDER_LSB_TO_MSB;
848 dp_chain_mask = DP_CHAIN_8BPP;
849 } else if (bpp <= 15) {
851 pix_width = CRTC_PIX_WIDTH_15BPP;
852 dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP |
853 BYTE_ORDER_LSB_TO_MSB;
854 dp_chain_mask = DP_CHAIN_15BPP;
855 } else if (bpp <= 16) {
857 pix_width = CRTC_PIX_WIDTH_16BPP;
858 dp_pix_width = HOST_16BPP | SRC_16BPP | DST_16BPP |
859 BYTE_ORDER_LSB_TO_MSB;
860 dp_chain_mask = DP_CHAIN_16BPP;
861 } else if (bpp <= 24 && M64_HAS(INTEGRATED)) {
863 pix_width = CRTC_PIX_WIDTH_24BPP;
864 dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP |
865 BYTE_ORDER_LSB_TO_MSB;
866 dp_chain_mask = DP_CHAIN_24BPP;
867 } else if (bpp <= 32) {
869 pix_width = CRTC_PIX_WIDTH_32BPP;
870 dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP |
871 BYTE_ORDER_LSB_TO_MSB;
872 dp_chain_mask = DP_CHAIN_32BPP;
876 line_length = calc_line_length(par, vxres, bpp);
878 if (vyres * line_length > info->fix.smem_len)
879 FAIL("not enough video RAM");
881 h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
882 v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
884 if ((xres > 1920) || (yres > 1200)) {
885 FAIL("MACH64 chips are designed for max 1920x1200\n"
886 "select another resolution.");
888 h_sync_strt = h_disp + var->right_margin;
889 h_sync_end = h_sync_strt + var->hsync_len;
890 h_sync_dly = var->right_margin & 7;
891 h_total = h_sync_end + h_sync_dly + var->left_margin;
893 v_sync_strt = v_disp + var->lower_margin;
894 v_sync_end = v_sync_strt + var->vsync_len;
895 v_total = v_sync_end + var->upper_margin;
897 #ifdef CONFIG_FB_ATY_GENERIC_LCD
898 if (par->lcd_table != 0) {
899 if (!M64_HAS(LT_LCD_REGS)) {
900 u32 lcd_index = aty_ld_le32(LCD_INDEX, par);
901 crtc->lcd_index = lcd_index &
902 ~(LCD_INDEX_MASK | LCD_DISPLAY_DIS |
903 LCD_SRC_SEL | CRTC2_DISPLAY_DIS);
904 aty_st_le32(LCD_INDEX, lcd_index, par);
907 if (!M64_HAS(MOBIL_BUS))
908 crtc->lcd_index |= CRTC2_DISPLAY_DIS;
910 crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par) | 0x4000;
911 crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par) & ~CRTC_RW_SELECT;
913 crtc->lcd_gen_cntl &=
914 ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 | TVCLK_PM_EN |
915 /*VCLK_DAC_PM_EN | USE_SHADOWED_VEND |*/
916 USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN);
917 crtc->lcd_gen_cntl |= DONT_SHADOW_VPAR | LOCK_8DOT;
919 if ((crtc->lcd_gen_cntl & LCD_ON) &&
920 ((xres > par->lcd_width) || (yres > par->lcd_height))) {
922 * We cannot display the mode on the LCD. If the CRT is
923 * enabled we can turn off the LCD.
924 * If the CRT is off, it isn't a good idea to switch it
925 * on; we don't know if one is connected. So it's better
928 if (crtc->lcd_gen_cntl & CRT_ON) {
929 if (!(var->activate & FB_ACTIVATE_TEST))
930 PRINTKI("Disable LCD panel, because video mode does not fit.\n");
931 crtc->lcd_gen_cntl &= ~LCD_ON;
932 /*aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);*/
934 if (!(var->activate & FB_ACTIVATE_TEST))
935 PRINTKE("Video mode exceeds size of LCD panel.\nConnect this computer to a conventional monitor if you really need this mode.\n");
941 if ((par->lcd_table != 0) && (crtc->lcd_gen_cntl & LCD_ON)) {
943 /* bpp -> bytespp, 1,4 -> 0; 8 -> 2; 15,16 -> 1; 24 -> 6; 32 -> 5
944 const u8 DFP_h_sync_dly_LT[] = { 0, 2, 1, 6, 5 };
945 const u8 ADD_to_strt_wid_and_dly_LT_DAC[] = { 0, 5, 6, 9, 9, 12, 12 }; */
947 vmode &= ~(FB_VMODE_DOUBLE | FB_VMODE_INTERLACED);
950 * This is horror! When we simulate, say 640x480 on an 800x600
951 * LCD monitor, the CRTC should be programmed 800x600 values for
952 * the non visible part, but 640x480 for the visible part.
953 * This code has been tested on a laptop with it's 1400x1050 LCD
954 * monitor and a conventional monitor both switched on.
955 * Tested modes: 1280x1024, 1152x864, 1024x768, 800x600,
956 * works with little glitches also with DOUBLESCAN modes
958 if (yres < par->lcd_height) {
959 VScan = par->lcd_height / yres;
962 vmode |= FB_VMODE_DOUBLE;
966 h_sync_strt = h_disp + par->lcd_right_margin;
967 h_sync_end = h_sync_strt + par->lcd_hsync_len;
968 h_sync_dly = /*DFP_h_sync_dly[ ( bpp + 1 ) / 3 ]; */par->lcd_hsync_dly;
969 h_total = h_disp + par->lcd_hblank_len;
971 v_sync_strt = v_disp + par->lcd_lower_margin / VScan;
972 v_sync_end = v_sync_strt + par->lcd_vsync_len / VScan;
973 v_total = v_disp + par->lcd_vblank_len / VScan;
975 #endif /* CONFIG_FB_ATY_GENERIC_LCD */
977 h_disp = (h_disp >> 3) - 1;
978 h_sync_strt = (h_sync_strt >> 3) - 1;
979 h_sync_end = (h_sync_end >> 3) - 1;
980 h_total = (h_total >> 3) - 1;
981 h_sync_wid = h_sync_end - h_sync_strt;
983 FAIL_MAX("h_disp too large", h_disp, 0xff);
984 FAIL_MAX("h_sync_strt too large", h_sync_strt, 0x1ff);
985 /*FAIL_MAX("h_sync_wid too large", h_sync_wid, 0x1f);*/
986 if (h_sync_wid > 0x1f)
988 FAIL_MAX("h_total too large", h_total, 0x1ff);
990 if (vmode & FB_VMODE_DOUBLE) {
1001 v_sync_wid = v_sync_end - v_sync_strt;
1003 FAIL_MAX("v_disp too large", v_disp, 0x7ff);
1004 FAIL_MAX("v_sync_stsrt too large", v_sync_strt, 0x7ff);
1005 /*FAIL_MAX("v_sync_wid too large", v_sync_wid, 0x1f);*/
1006 if (v_sync_wid > 0x1f)
1008 FAIL_MAX("v_total too large", v_total, 0x7ff);
1010 c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;
1013 crtc->vxres = vxres;
1014 crtc->vyres = vyres;
1015 crtc->xoffset = xoffset;
1016 crtc->yoffset = yoffset;
1019 ((yoffset * line_length + xoffset * bpp / 8) / 8) |
1020 ((line_length / bpp) << 22);
1021 crtc->vline_crnt_vline = 0;
1023 crtc->h_tot_disp = h_total | (h_disp << 16);
1024 crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly << 8) |
1025 ((h_sync_strt & 0x100) << 4) | (h_sync_wid << 16) |
1027 crtc->v_tot_disp = v_total | (v_disp << 16);
1028 crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid << 16) |
1031 /* crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_PRESERVED_MASK; */
1032 crtc->gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN | pix_width | c_sync;
1033 crtc->gen_cntl |= CRTC_VGA_LINEAR;
1035 /* Enable doublescan mode if requested */
1036 if (vmode & FB_VMODE_DOUBLE)
1037 crtc->gen_cntl |= CRTC_DBL_SCAN_EN;
1038 /* Enable interlaced mode if requested */
1039 if (vmode & FB_VMODE_INTERLACED)
1040 crtc->gen_cntl |= CRTC_INTERLACE_EN;
1041 #ifdef CONFIG_FB_ATY_GENERIC_LCD
1042 if (par->lcd_table != 0) {
1043 u32 vdisplay = yres;
1044 if (vmode & FB_VMODE_DOUBLE)
1046 crtc->gen_cntl &= ~(CRTC2_EN | CRTC2_PIX_WIDTH);
1047 crtc->lcd_gen_cntl &= ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 |
1048 /*TVCLK_PM_EN | VCLK_DAC_PM_EN |*/
1050 USE_SHADOWED_ROWCUR |
1051 SHADOW_EN | SHADOW_RW_EN);
1052 crtc->lcd_gen_cntl |= DONT_SHADOW_VPAR/* | LOCK_8DOT*/;
1054 /* MOBILITY M1 tested, FIXME: LT */
1055 crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par);
1056 if (!M64_HAS(LT_LCD_REGS))
1057 crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par) &
1058 ~(AUTO_VERT_RATIO | VERT_STRETCH_MODE | VERT_STRETCH_RATIO3);
1060 crtc->horz_stretching &= ~(HORZ_STRETCH_RATIO |
1061 HORZ_STRETCH_LOOP | AUTO_HORZ_RATIO |
1062 HORZ_STRETCH_MODE | HORZ_STRETCH_EN);
1063 if (xres < par->lcd_width && crtc->lcd_gen_cntl & LCD_ON) {
1066 * The horizontal blender misbehaves when
1067 * HDisplay is less than a certain threshold
1068 * (440 for a 1024-wide panel). It doesn't
1069 * stretch such modes enough. Use pixel
1070 * replication instead of blending to stretch
1071 * modes that can be made to exactly fit the
1072 * panel width. The undocumented "NoLCDBlend"
1073 * option allows the pixel-replicated mode to
1074 * be slightly wider or narrower than the
1075 * panel width. It also causes a mode that is
1076 * exactly half as wide as the panel to be
1077 * pixel-replicated, rather than blended.
1079 int HDisplay = xres & ~7;
1080 int nStretch = par->lcd_width / HDisplay;
1081 int Remainder = par->lcd_width % HDisplay;
1083 if ((!Remainder && ((nStretch > 2))) ||
1084 (((HDisplay * 16) / par->lcd_width) < 7)) {
1085 static const char StretchLoops[] = { 10, 12, 13, 15, 16 };
1086 int horz_stretch_loop = -1, BestRemainder;
1087 int Numerator = HDisplay, Denominator = par->lcd_width;
1089 ATIReduceRatio(&Numerator, &Denominator);
1091 BestRemainder = (Numerator * 16) / Denominator;
1092 while (--Index >= 0) {
1093 Remainder = ((Denominator - Numerator) * StretchLoops[Index]) %
1095 if (Remainder < BestRemainder) {
1096 horz_stretch_loop = Index;
1097 if (!(BestRemainder = Remainder))
1102 if ((horz_stretch_loop >= 0) && !BestRemainder) {
1103 int horz_stretch_ratio = 0, Accumulator = 0;
1104 int reuse_previous = 1;
1106 Index = StretchLoops[horz_stretch_loop];
1108 while (--Index >= 0) {
1109 if (Accumulator > 0)
1110 horz_stretch_ratio |= reuse_previous;
1112 Accumulator += Denominator;
1113 Accumulator -= Numerator;
1114 reuse_previous <<= 1;
1117 crtc->horz_stretching |= (HORZ_STRETCH_EN |
1118 ((horz_stretch_loop & HORZ_STRETCH_LOOP) << 16) |
1119 (horz_stretch_ratio & HORZ_STRETCH_RATIO));
1120 break; /* Out of the do { ... } while (0) */
1124 crtc->horz_stretching |= (HORZ_STRETCH_MODE | HORZ_STRETCH_EN |
1125 (((HDisplay * (HORZ_STRETCH_BLEND + 1)) / par->lcd_width) & HORZ_STRETCH_BLEND));
1129 if (vdisplay < par->lcd_height && crtc->lcd_gen_cntl & LCD_ON) {
1130 crtc->vert_stretching = (VERT_STRETCH_USE0 | VERT_STRETCH_EN |
1131 (((vdisplay * (VERT_STRETCH_RATIO0 + 1)) / par->lcd_height) & VERT_STRETCH_RATIO0));
1133 if (!M64_HAS(LT_LCD_REGS) &&
1134 xres <= (M64_HAS(MOBIL_BUS) ? 1024 : 800))
1135 crtc->ext_vert_stretch |= VERT_STRETCH_MODE;
1138 * Don't use vertical blending if the mode is too wide
1139 * or not vertically stretched.
1141 crtc->vert_stretching = 0;
1143 /* copy to shadow crtc */
1144 crtc->shadow_h_tot_disp = crtc->h_tot_disp;
1145 crtc->shadow_h_sync_strt_wid = crtc->h_sync_strt_wid;
1146 crtc->shadow_v_tot_disp = crtc->v_tot_disp;
1147 crtc->shadow_v_sync_strt_wid = crtc->v_sync_strt_wid;
1149 #endif /* CONFIG_FB_ATY_GENERIC_LCD */
1151 if (M64_HAS(MAGIC_FIFO)) {
1152 /* FIXME: display FIFO low watermark values */
1153 crtc->gen_cntl |= (aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_FIFO_LWM);
1155 crtc->dp_pix_width = dp_pix_width;
1156 crtc->dp_chain_mask = dp_chain_mask;
1161 static int aty_crtc_to_var(const struct crtc *crtc,
1162 struct fb_var_screeninfo *var)
1164 u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync;
1165 u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
1166 u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
1168 u32 double_scan, interlace;
1171 h_total = crtc->h_tot_disp & 0x1ff;
1172 h_disp = (crtc->h_tot_disp >> 16) & 0xff;
1173 h_sync_strt = (crtc->h_sync_strt_wid & 0xff) | ((crtc->h_sync_strt_wid >> 4) & 0x100);
1174 h_sync_dly = (crtc->h_sync_strt_wid >> 8) & 0x7;
1175 h_sync_wid = (crtc->h_sync_strt_wid >> 16) & 0x1f;
1176 h_sync_pol = (crtc->h_sync_strt_wid >> 21) & 0x1;
1177 v_total = crtc->v_tot_disp & 0x7ff;
1178 v_disp = (crtc->v_tot_disp >> 16) & 0x7ff;
1179 v_sync_strt = crtc->v_sync_strt_wid & 0x7ff;
1180 v_sync_wid = (crtc->v_sync_strt_wid >> 16) & 0x1f;
1181 v_sync_pol = (crtc->v_sync_strt_wid >> 21) & 0x1;
1182 c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
1183 pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
1184 double_scan = crtc->gen_cntl & CRTC_DBL_SCAN_EN;
1185 interlace = crtc->gen_cntl & CRTC_INTERLACE_EN;
1188 xres = (h_disp + 1) * 8;
1190 left = (h_total - h_sync_strt - h_sync_wid) * 8 - h_sync_dly;
1191 right = (h_sync_strt - h_disp) * 8 + h_sync_dly;
1192 hslen = h_sync_wid * 8;
1193 upper = v_total - v_sync_strt - v_sync_wid;
1194 lower = v_sync_strt - v_disp;
1196 sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) |
1197 (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
1198 (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
1200 switch (pix_width) {
1201 case CRTC_PIX_WIDTH_8BPP:
1203 var->red.offset = 0;
1204 var->red.length = 8;
1205 var->green.offset = 0;
1206 var->green.length = 8;
1207 var->blue.offset = 0;
1208 var->blue.length = 8;
1209 var->transp.offset = 0;
1210 var->transp.length = 0;
1212 case CRTC_PIX_WIDTH_15BPP: /* RGB 555 */
1214 var->red.offset = 10;
1215 var->red.length = 5;
1216 var->green.offset = 5;
1217 var->green.length = 5;
1218 var->blue.offset = 0;
1219 var->blue.length = 5;
1220 var->transp.offset = 0;
1221 var->transp.length = 0;
1223 case CRTC_PIX_WIDTH_16BPP: /* RGB 565 */
1225 var->red.offset = 11;
1226 var->red.length = 5;
1227 var->green.offset = 5;
1228 var->green.length = 6;
1229 var->blue.offset = 0;
1230 var->blue.length = 5;
1231 var->transp.offset = 0;
1232 var->transp.length = 0;
1234 case CRTC_PIX_WIDTH_24BPP: /* RGB 888 */
1236 var->red.offset = 16;
1237 var->red.length = 8;
1238 var->green.offset = 8;
1239 var->green.length = 8;
1240 var->blue.offset = 0;
1241 var->blue.length = 8;
1242 var->transp.offset = 0;
1243 var->transp.length = 0;
1245 case CRTC_PIX_WIDTH_32BPP: /* ARGB 8888 */
1247 var->red.offset = 16;
1248 var->red.length = 8;
1249 var->green.offset = 8;
1250 var->green.length = 8;
1251 var->blue.offset = 0;
1252 var->blue.length = 8;
1253 var->transp.offset = 24;
1254 var->transp.length = 8;
1257 PRINTKE("Invalid pixel width\n");
1264 var->xres_virtual = crtc->vxres;
1265 var->yres_virtual = crtc->vyres;
1266 var->bits_per_pixel = bpp;
1267 var->left_margin = left;
1268 var->right_margin = right;
1269 var->upper_margin = upper;
1270 var->lower_margin = lower;
1271 var->hsync_len = hslen;
1272 var->vsync_len = vslen;
1274 var->vmode = FB_VMODE_NONINTERLACED;
1276 * In double scan mode, the vertical parameters are doubled,
1277 * so we need to halve them to get the right values.
1278 * In interlaced mode the values are already correct,
1279 * so no correction is necessary.
1282 var->vmode = FB_VMODE_INTERLACED;
1285 var->vmode = FB_VMODE_DOUBLE;
1287 var->upper_margin >>= 1;
1288 var->lower_margin >>= 1;
1289 var->vsync_len >>= 1;
1295 /* ------------------------------------------------------------------------- */
1297 static int atyfb_set_par(struct fb_info *info)
1299 struct atyfb_par *par = (struct atyfb_par *) info->par;
1300 struct fb_var_screeninfo *var = &info->var;
1304 struct fb_var_screeninfo debug;
1310 err = aty_var_to_crtc(info, var, &par->crtc);
1314 pixclock = atyfb_get_pixclock(var, par);
1316 if (pixclock == 0) {
1317 PRINTKE("Invalid pixclock\n");
1320 err = par->pll_ops->var_to_pll(info, pixclock,
1321 var->bits_per_pixel, &par->pll);
1326 par->accel_flags = var->accel_flags; /* hack */
1328 if (var->accel_flags) {
1329 atyfb_ops.fb_sync = atyfb_sync;
1330 info->flags &= ~FBINFO_HWACCEL_DISABLED;
1332 atyfb_ops.fb_sync = NULL;
1333 info->flags |= FBINFO_HWACCEL_DISABLED;
1336 if (par->blitter_may_be_busy)
1339 aty_set_crtc(par, &par->crtc);
1340 par->dac_ops->set_dac(info, &par->pll,
1341 var->bits_per_pixel, par->accel_flags);
1342 par->pll_ops->set_pll(info, &par->pll);
1345 if (par->pll_ops && par->pll_ops->pll_to_var)
1346 pixclock_in_ps = par->pll_ops->pll_to_var(info, &par->pll);
1350 if (0 == pixclock_in_ps) {
1351 PRINTKE("ALERT ops->pll_to_var get 0\n");
1352 pixclock_in_ps = pixclock;
1355 memset(&debug, 0, sizeof(debug));
1356 if (!aty_crtc_to_var(&par->crtc, &debug)) {
1357 u32 hSync, vRefresh;
1358 u32 h_disp, h_sync_strt, h_sync_end, h_total;
1359 u32 v_disp, v_sync_strt, v_sync_end, v_total;
1361 h_disp = debug.xres;
1362 h_sync_strt = h_disp + debug.right_margin;
1363 h_sync_end = h_sync_strt + debug.hsync_len;
1364 h_total = h_sync_end + debug.left_margin;
1365 v_disp = debug.yres;
1366 v_sync_strt = v_disp + debug.lower_margin;
1367 v_sync_end = v_sync_strt + debug.vsync_len;
1368 v_total = v_sync_end + debug.upper_margin;
1370 hSync = 1000000000 / (pixclock_in_ps * h_total);
1371 vRefresh = (hSync * 1000) / v_total;
1372 if (par->crtc.gen_cntl & CRTC_INTERLACE_EN)
1374 if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN)
1377 DPRINTK("atyfb_set_par\n");
1378 DPRINTK(" Set Visible Mode to %ix%i-%i\n",
1379 var->xres, var->yres, var->bits_per_pixel);
1380 DPRINTK(" Virtual resolution %ix%i, "
1381 "pixclock_in_ps %i (calculated %i)\n",
1382 var->xres_virtual, var->yres_virtual,
1383 pixclock, pixclock_in_ps);
1384 DPRINTK(" Dot clock: %i MHz\n",
1385 1000000 / pixclock_in_ps);
1386 DPRINTK(" Horizontal sync: %i kHz\n", hSync);
1387 DPRINTK(" Vertical refresh: %i Hz\n", vRefresh);
1388 DPRINTK(" x style: %i.%03i %i %i %i %i %i %i %i %i\n",
1389 1000000 / pixclock_in_ps, 1000000 % pixclock_in_ps,
1390 h_disp, h_sync_strt, h_sync_end, h_total,
1391 v_disp, v_sync_strt, v_sync_end, v_total);
1392 DPRINTK(" fb style: %i %i %i %i %i %i %i %i %i\n",
1394 debug.left_margin, h_disp, debug.right_margin, debug.hsync_len,
1395 debug.upper_margin, v_disp, debug.lower_margin, debug.vsync_len);
1399 if (!M64_HAS(INTEGRATED)) {
1400 /* Don't forget MEM_CNTL */
1401 tmp = aty_ld_le32(MEM_CNTL, par) & 0xf0ffffff;
1402 switch (var->bits_per_pixel) {
1413 aty_st_le32(MEM_CNTL, tmp, par);
1415 tmp = aty_ld_le32(MEM_CNTL, par) & 0xf00fffff;
1416 if (!M64_HAS(MAGIC_POSTDIV))
1417 tmp |= par->mem_refresh_rate << 20;
1418 switch (var->bits_per_pixel) {
1430 if (M64_HAS(CT_BUS)) {
1431 aty_st_le32(DAC_CNTL, 0x87010184, par);
1432 aty_st_le32(BUS_CNTL, 0x680000f9, par);
1433 } else if (M64_HAS(VT_BUS)) {
1434 aty_st_le32(DAC_CNTL, 0x87010184, par);
1435 aty_st_le32(BUS_CNTL, 0x680000f9, par);
1436 } else if (M64_HAS(MOBIL_BUS)) {
1437 aty_st_le32(DAC_CNTL, 0x80010102, par);
1438 aty_st_le32(BUS_CNTL, 0x7b33a040 | (par->aux_start ? BUS_APER_REG_DIS : 0), par);
1441 aty_st_le32(DAC_CNTL, 0x86010102, par);
1442 aty_st_le32(BUS_CNTL, 0x7b23a040 | (par->aux_start ? BUS_APER_REG_DIS : 0), par);
1443 aty_st_le32(EXT_MEM_CNTL, aty_ld_le32(EXT_MEM_CNTL, par) | 0x5000001, par);
1445 aty_st_le32(MEM_CNTL, tmp, par);
1447 aty_st_8(DAC_MASK, 0xff, par);
1449 info->fix.line_length = calc_line_length(par, var->xres_virtual,
1450 var->bits_per_pixel);
1452 info->fix.visual = var->bits_per_pixel <= 8 ?
1453 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
1455 /* Initialize the graphics engine */
1456 if (par->accel_flags & FB_ACCELF_TEXT)
1457 aty_init_engine(par, info);
1459 #ifdef CONFIG_BOOTX_TEXT
1460 btext_update_display(info->fix.smem_start,
1461 (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8,
1462 ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1,
1463 var->bits_per_pixel,
1464 par->crtc.vxres * var->bits_per_pixel / 8);
1465 #endif /* CONFIG_BOOTX_TEXT */
1468 /* dump non shadow CRTC, pll, LCD registers */
1471 /* CRTC registers */
1473 printk("debug atyfb: Mach64 non-shadow register values:");
1474 for (i = 0; i < 256; i = i+4) {
1477 printk("debug atyfb: 0x%04X: ", base + i);
1479 pr_cont(" %08X", aty_ld_le32(i, par));
1483 #ifdef CONFIG_FB_ATY_CT
1486 printk("debug atyfb: Mach64 PLL register values:");
1487 for (i = 0; i < 64; i++) {
1490 printk("debug atyfb: 0x%02X: ", base + i);
1494 pr_cont("%02X", aty_ld_pll_ct(i, par));
1497 #endif /* CONFIG_FB_ATY_CT */
1499 #ifdef CONFIG_FB_ATY_GENERIC_LCD
1500 if (par->lcd_table != 0) {
1503 printk("debug atyfb: LCD register values:");
1504 if (M64_HAS(LT_LCD_REGS)) {
1505 for (i = 0; i <= POWER_MANAGEMENT; i++) {
1506 if (i == EXT_VERT_STRETCH)
1508 pr_cont("\ndebug atyfb: 0x%04X: ",
1510 pr_cont(" %08X", aty_ld_lcd(i, par));
1513 for (i = 0; i < 64; i++) {
1515 pr_cont("\ndebug atyfb: 0x%02X: ",
1517 pr_cont(" %08X", aty_ld_lcd(i, par));
1522 #endif /* CONFIG_FB_ATY_GENERIC_LCD */
1528 static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1530 struct atyfb_par *par = (struct atyfb_par *) info->par;
1536 memcpy(&pll, &par->pll, sizeof(pll));
1538 err = aty_var_to_crtc(info, var, &crtc);
1542 pixclock = atyfb_get_pixclock(var, par);
1544 if (pixclock == 0) {
1545 if (!(var->activate & FB_ACTIVATE_TEST))
1546 PRINTKE("Invalid pixclock\n");
1549 err = par->pll_ops->var_to_pll(info, pixclock,
1550 var->bits_per_pixel, &pll);
1555 if (var->accel_flags & FB_ACCELF_TEXT)
1556 info->var.accel_flags = FB_ACCELF_TEXT;
1558 info->var.accel_flags = 0;
1560 aty_crtc_to_var(&crtc, var);
1561 var->pixclock = par->pll_ops->pll_to_var(info, &pll);
1565 static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info)
1567 u32 xoffset = info->var.xoffset;
1568 u32 yoffset = info->var.yoffset;
1569 u32 line_length = info->fix.line_length;
1570 u32 bpp = info->var.bits_per_pixel;
1572 par->crtc.off_pitch =
1573 ((yoffset * line_length + xoffset * bpp / 8) / 8) |
1574 ((line_length / bpp) << 22);
1579 * Open/Release the frame buffer device
1582 static int atyfb_open(struct fb_info *info, int user)
1584 struct atyfb_par *par = (struct atyfb_par *) info->par;
1595 static irqreturn_t aty_irq(int irq, void *dev_id)
1597 struct atyfb_par *par = dev_id;
1601 spin_lock(&par->int_lock);
1603 int_cntl = aty_ld_le32(CRTC_INT_CNTL, par);
1605 if (int_cntl & CRTC_VBLANK_INT) {
1606 /* clear interrupt */
1607 aty_st_le32(CRTC_INT_CNTL, (int_cntl & CRTC_INT_EN_MASK) |
1608 CRTC_VBLANK_INT_AK, par);
1609 par->vblank.count++;
1610 if (par->vblank.pan_display) {
1611 par->vblank.pan_display = 0;
1612 aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
1614 wake_up_interruptible(&par->vblank.wait);
1618 spin_unlock(&par->int_lock);
1620 return IRQ_RETVAL(handled);
1623 static int aty_enable_irq(struct atyfb_par *par, int reenable)
1627 if (!test_and_set_bit(0, &par->irq_flags)) {
1628 if (request_irq(par->irq, aty_irq, IRQF_SHARED, "atyfb", par)) {
1629 clear_bit(0, &par->irq_flags);
1632 spin_lock_irq(&par->int_lock);
1633 int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
1634 /* clear interrupt */
1635 aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_AK, par);
1636 /* enable interrupt */
1637 aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_EN, par);
1638 spin_unlock_irq(&par->int_lock);
1639 } else if (reenable) {
1640 spin_lock_irq(&par->int_lock);
1641 int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
1642 if (!(int_cntl & CRTC_VBLANK_INT_EN)) {
1643 printk("atyfb: someone disabled IRQ [%08x]\n",
1645 /* re-enable interrupt */
1646 aty_st_le32(CRTC_INT_CNTL, int_cntl |
1647 CRTC_VBLANK_INT_EN, par);
1649 spin_unlock_irq(&par->int_lock);
1655 static int aty_disable_irq(struct atyfb_par *par)
1659 if (test_and_clear_bit(0, &par->irq_flags)) {
1660 if (par->vblank.pan_display) {
1661 par->vblank.pan_display = 0;
1662 aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
1664 spin_lock_irq(&par->int_lock);
1665 int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
1666 /* disable interrupt */
1667 aty_st_le32(CRTC_INT_CNTL, int_cntl & ~CRTC_VBLANK_INT_EN, par);
1668 spin_unlock_irq(&par->int_lock);
1669 free_irq(par->irq, par);
1675 static int atyfb_release(struct fb_info *info, int user)
1677 struct atyfb_par *par = (struct atyfb_par *) info->par;
1693 was_mmaped = par->mmaped;
1698 struct fb_var_screeninfo var;
1701 * Now reset the default display config, we have
1702 * no idea what the program(s) which mmap'd the
1703 * chip did to the configuration, nor whether it
1704 * restored it correctly.
1708 var.accel_flags &= ~FB_ACCELF_TEXT;
1710 var.accel_flags |= FB_ACCELF_TEXT;
1711 if (var.yres == var.yres_virtual) {
1712 u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2));
1714 ((videoram * 8) / var.bits_per_pixel) /
1716 if (var.yres_virtual < var.yres)
1717 var.yres_virtual = var.yres;
1721 aty_disable_irq(par);
1727 * Pan or Wrap the Display
1729 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
1732 static int atyfb_pan_display(struct fb_var_screeninfo *var,
1733 struct fb_info *info)
1735 struct atyfb_par *par = (struct atyfb_par *) info->par;
1736 u32 xres, yres, xoffset, yoffset;
1738 xres = (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8;
1739 yres = ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1;
1740 if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN)
1742 xoffset = (var->xoffset + 7) & ~7;
1743 yoffset = var->yoffset;
1744 if (xoffset + xres > par->crtc.vxres ||
1745 yoffset + yres > par->crtc.vyres)
1747 info->var.xoffset = xoffset;
1748 info->var.yoffset = yoffset;
1752 set_off_pitch(par, info);
1753 if ((var->activate & FB_ACTIVATE_VBL) && !aty_enable_irq(par, 0)) {
1754 par->vblank.pan_display = 1;
1756 par->vblank.pan_display = 0;
1757 aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
1763 static int aty_waitforvblank(struct atyfb_par *par, u32 crtc)
1765 struct aty_interrupt *vbl;
1777 ret = aty_enable_irq(par, 0);
1782 ret = wait_event_interruptible_timeout(vbl->wait,
1783 count != vbl->count, HZ/10);
1787 aty_enable_irq(par, 1);
1796 #define ATYIO_CLKR 0x41545900 /* ATY\00 */
1797 #define ATYIO_CLKW 0x41545901 /* ATY\01 */
1803 u8 mclk_post_div; /* 1,2,3,4,8 */
1804 u8 mclk_fb_mult; /* 2 or 4 */
1805 u8 xclk_post_div; /* 1,2,3,4,8 */
1807 u8 vclk_post_div; /* 1,2,3,4,6,8,12 */
1808 u32 dsp_xclks_per_row; /* 0-16383 */
1809 u32 dsp_loop_latency; /* 0-15 */
1810 u32 dsp_precision; /* 0-7 */
1811 u32 dsp_on; /* 0-2047 */
1812 u32 dsp_off; /* 0-2047 */
1815 #define ATYIO_FEATR 0x41545902 /* ATY\02 */
1816 #define ATYIO_FEATW 0x41545903 /* ATY\03 */
1819 static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
1821 struct atyfb_par *par = (struct atyfb_par *) info->par;
1823 struct fbtype fbtyp;
1829 fbtyp.fb_type = FBTYPE_PCI_GENERIC;
1830 fbtyp.fb_width = par->crtc.vxres;
1831 fbtyp.fb_height = par->crtc.vyres;
1832 fbtyp.fb_depth = info->var.bits_per_pixel;
1833 fbtyp.fb_cmsize = info->cmap.len;
1834 fbtyp.fb_size = info->fix.smem_len;
1835 if (copy_to_user((struct fbtype __user *) arg, &fbtyp,
1839 #endif /* __sparc__ */
1841 case FBIO_WAITFORVSYNC:
1845 if (get_user(crtc, (__u32 __user *) arg))
1848 return aty_waitforvblank(par, crtc);
1851 #if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)
1853 if (M64_HAS(INTEGRATED)) {
1854 struct atyclk clk = { 0 };
1855 union aty_pll *pll = &par->pll;
1856 u32 dsp_config = pll->ct.dsp_config;
1857 u32 dsp_on_off = pll->ct.dsp_on_off;
1858 clk.ref_clk_per = par->ref_clk_per;
1859 clk.pll_ref_div = pll->ct.pll_ref_div;
1860 clk.mclk_fb_div = pll->ct.mclk_fb_div;
1861 clk.mclk_post_div = pll->ct.mclk_post_div_real;
1862 clk.mclk_fb_mult = pll->ct.mclk_fb_mult;
1863 clk.xclk_post_div = pll->ct.xclk_post_div_real;
1864 clk.vclk_fb_div = pll->ct.vclk_fb_div;
1865 clk.vclk_post_div = pll->ct.vclk_post_div_real;
1866 clk.dsp_xclks_per_row = dsp_config & 0x3fff;
1867 clk.dsp_loop_latency = (dsp_config >> 16) & 0xf;
1868 clk.dsp_precision = (dsp_config >> 20) & 7;
1869 clk.dsp_off = dsp_on_off & 0x7ff;
1870 clk.dsp_on = (dsp_on_off >> 16) & 0x7ff;
1871 if (copy_to_user((struct atyclk __user *) arg, &clk,
1878 if (M64_HAS(INTEGRATED)) {
1880 union aty_pll *pll = &par->pll;
1881 if (copy_from_user(&clk, (struct atyclk __user *) arg,
1884 par->ref_clk_per = clk.ref_clk_per;
1885 pll->ct.pll_ref_div = clk.pll_ref_div;
1886 pll->ct.mclk_fb_div = clk.mclk_fb_div;
1887 pll->ct.mclk_post_div_real = clk.mclk_post_div;
1888 pll->ct.mclk_fb_mult = clk.mclk_fb_mult;
1889 pll->ct.xclk_post_div_real = clk.xclk_post_div;
1890 pll->ct.vclk_fb_div = clk.vclk_fb_div;
1891 pll->ct.vclk_post_div_real = clk.vclk_post_div;
1892 pll->ct.dsp_config = (clk.dsp_xclks_per_row & 0x3fff) |
1893 ((clk.dsp_loop_latency & 0xf) << 16) |
1894 ((clk.dsp_precision & 7) << 20);
1895 pll->ct.dsp_on_off = (clk.dsp_off & 0x7ff) |
1896 ((clk.dsp_on & 0x7ff) << 16);
1897 /*aty_calc_pll_ct(info, &pll->ct);*/
1898 aty_set_pll_ct(info, pll);
1903 if (get_user(par->features, (u32 __user *) arg))
1907 if (put_user(par->features, (u32 __user *) arg))
1910 #endif /* DEBUG && CONFIG_FB_ATY_CT */
1917 static int atyfb_sync(struct fb_info *info)
1919 struct atyfb_par *par = (struct atyfb_par *) info->par;
1921 if (par->blitter_may_be_busy)
1927 static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
1929 struct atyfb_par *par = (struct atyfb_par *) info->par;
1930 unsigned int size, page, map_size = 0;
1931 unsigned long map_offset = 0;
1938 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
1941 off = vma->vm_pgoff << PAGE_SHIFT;
1942 size = vma->vm_end - vma->vm_start;
1944 /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
1946 if (((vma->vm_pgoff == 0) && (size == info->fix.smem_len)) ||
1947 ((off == info->fix.smem_len) && (size == PAGE_SIZE)))
1948 off += 0x8000000000000000UL;
1950 vma->vm_pgoff = off >> PAGE_SHIFT; /* propagate off changes */
1952 /* Each page, see which map applies */
1953 for (page = 0; page < size;) {
1955 for (i = 0; par->mmap_map[i].size; i++) {
1956 unsigned long start = par->mmap_map[i].voff;
1957 unsigned long end = start + par->mmap_map[i].size;
1958 unsigned long offset = off + page;
1965 map_size = par->mmap_map[i].size - (offset - start);
1966 map_offset = par->mmap_map[i].poff + (offset - start);
1973 if (page + map_size > size)
1974 map_size = size - page;
1976 pgprot_val(vma->vm_page_prot) &= ~(par->mmap_map[i].prot_mask);
1977 pgprot_val(vma->vm_page_prot) |= par->mmap_map[i].prot_flag;
1979 if (remap_pfn_range(vma, vma->vm_start + page,
1980 map_offset >> PAGE_SHIFT, map_size, vma->vm_page_prot))
1993 #endif /* __sparc__ */
1997 #if defined(CONFIG_PM) && defined(CONFIG_PCI)
1999 #ifdef CONFIG_PPC_PMAC
2000 /* Power management routines. Those are used for PowerBook sleep.
2002 static int aty_power_mgmt(int sleep, struct atyfb_par *par)
2007 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2008 pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;
2009 aty_st_lcd(POWER_MANAGEMENT, pm, par);
2010 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2016 aty_st_lcd(POWER_MANAGEMENT, pm, par);
2017 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2019 pm &= ~(PWR_BLON | AUTO_PWR_UP);
2021 aty_st_lcd(POWER_MANAGEMENT, pm, par);
2022 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2025 aty_st_lcd(POWER_MANAGEMENT, pm, par);
2027 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2029 if ((--timeout) == 0)
2031 } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
2035 aty_st_lcd(POWER_MANAGEMENT, pm, par);
2036 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2039 pm |= (PWR_BLON | AUTO_PWR_UP);
2040 aty_st_lcd(POWER_MANAGEMENT, pm, par);
2041 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2044 aty_st_lcd(POWER_MANAGEMENT, pm, par);
2046 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2048 if ((--timeout) == 0)
2050 } while ((pm & PWR_MGT_STATUS_MASK) != 0);
2054 return timeout ? 0 : -EIO;
2056 #endif /* CONFIG_PPC_PMAC */
2058 static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
2060 struct fb_info *info = pci_get_drvdata(pdev);
2061 struct atyfb_par *par = (struct atyfb_par *) info->par;
2063 if (state.event == pdev->dev.power.power_state.event)
2068 fb_set_suspend(info, 1);
2070 /* Idle & reset engine */
2072 aty_reset_engine(par);
2074 /* Blank display and LCD */
2075 atyfb_blank(FB_BLANK_POWERDOWN, info);
2078 par->lock_blank = 1;
2081 * Because we may change PCI D state ourselves, we need to
2082 * first save the config space content so the core can
2083 * restore it properly on resume.
2085 pci_save_state(pdev);
2087 #ifdef CONFIG_PPC_PMAC
2088 /* Set chip to "suspend" mode */
2089 if (machine_is(powermac) && aty_power_mgmt(1, par)) {
2091 par->lock_blank = 0;
2092 atyfb_blank(FB_BLANK_UNBLANK, info);
2093 fb_set_suspend(info, 0);
2098 pci_set_power_state(pdev, pci_choose_state(pdev, state));
2103 pdev->dev.power.power_state = state;
2108 static void aty_resume_chip(struct fb_info *info)
2110 struct atyfb_par *par = info->par;
2112 aty_st_le32(MEM_CNTL, par->mem_cntl, par);
2114 if (par->pll_ops->resume_pll)
2115 par->pll_ops->resume_pll(info, &par->pll);
2118 aty_st_le32(BUS_CNTL,
2119 aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par);
2122 static int atyfb_pci_resume(struct pci_dev *pdev)
2124 struct fb_info *info = pci_get_drvdata(pdev);
2125 struct atyfb_par *par = (struct atyfb_par *) info->par;
2127 if (pdev->dev.power.power_state.event == PM_EVENT_ON)
2133 * PCI state will have been restored by the core, so
2134 * we should be in D0 now with our config space fully
2138 #ifdef CONFIG_PPC_PMAC
2139 if (machine_is(powermac) &&
2140 pdev->dev.power.power_state.event == PM_EVENT_SUSPEND)
2141 aty_power_mgmt(0, par);
2144 aty_resume_chip(info);
2148 /* Restore display */
2149 atyfb_set_par(info);
2152 fb_set_suspend(info, 0);
2155 par->lock_blank = 0;
2156 atyfb_blank(FB_BLANK_UNBLANK, info);
2160 pdev->dev.power.power_state = PMSG_ON;
2165 #endif /* defined(CONFIG_PM) && defined(CONFIG_PCI) */
2168 #ifdef CONFIG_FB_ATY_BACKLIGHT
2169 #define MAX_LEVEL 0xFF
2171 static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
2173 struct fb_info *info = pci_get_drvdata(par->pdev);
2176 /* Get and convert the value */
2177 /* No locking of bl_curve since we read a single value */
2178 atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
2182 else if (atylevel > MAX_LEVEL)
2183 atylevel = MAX_LEVEL;
2188 static int aty_bl_update_status(struct backlight_device *bd)
2190 struct atyfb_par *par = bl_get_data(bd);
2191 unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par);
2194 if (bd->props.power != FB_BLANK_UNBLANK ||
2195 bd->props.fb_blank != FB_BLANK_UNBLANK)
2198 level = bd->props.brightness;
2200 reg |= (BLMOD_EN | BIASMOD_EN);
2202 reg &= ~BIAS_MOD_LEVEL_MASK;
2203 reg |= (aty_bl_get_level_brightness(par, level) << BIAS_MOD_LEVEL_SHIFT);
2205 reg &= ~BIAS_MOD_LEVEL_MASK;
2206 reg |= (aty_bl_get_level_brightness(par, 0) << BIAS_MOD_LEVEL_SHIFT);
2208 aty_st_lcd(LCD_MISC_CNTL, reg, par);
2213 static const struct backlight_ops aty_bl_data = {
2214 .update_status = aty_bl_update_status,
2217 static void aty_bl_init(struct atyfb_par *par)
2219 struct backlight_properties props;
2220 struct fb_info *info = pci_get_drvdata(par->pdev);
2221 struct backlight_device *bd;
2224 #ifdef CONFIG_PMAC_BACKLIGHT
2225 if (!pmac_has_backlight_type("ati"))
2229 snprintf(name, sizeof(name), "atybl%d", info->node);
2231 memset(&props, 0, sizeof(struct backlight_properties));
2232 props.type = BACKLIGHT_RAW;
2233 props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
2234 bd = backlight_device_register(name, info->dev, par, &aty_bl_data,
2237 info->bl_dev = NULL;
2238 printk(KERN_WARNING "aty: Backlight registration failed\n");
2243 fb_bl_default_curve(info, 0,
2244 0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL,
2245 0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL);
2247 bd->props.brightness = bd->props.max_brightness;
2248 bd->props.power = FB_BLANK_UNBLANK;
2249 backlight_update_status(bd);
2251 printk("aty: Backlight initialized (%s)\n", name);
2260 static void aty_bl_exit(struct backlight_device *bd)
2262 backlight_device_unregister(bd);
2263 printk("aty: Backlight unloaded\n");
2265 #endif /* CONFIG_PCI */
2267 #endif /* CONFIG_FB_ATY_BACKLIGHT */
2269 static void aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
2271 static const int ragepro_tbl[] = {
2272 44, 50, 55, 66, 75, 80, 100
2274 static const int ragexl_tbl[] = {
2275 50, 66, 75, 83, 90, 95, 100, 105,
2276 110, 115, 120, 125, 133, 143, 166
2278 const int *refresh_tbl;
2281 if (M64_HAS(XL_MEM)) {
2282 refresh_tbl = ragexl_tbl;
2283 size = ARRAY_SIZE(ragexl_tbl);
2285 refresh_tbl = ragepro_tbl;
2286 size = ARRAY_SIZE(ragepro_tbl);
2289 for (i = 0; i < size; i++) {
2290 if (xclk < refresh_tbl[i])
2293 par->mem_refresh_rate = i;
2300 static struct fb_info *fb_list = NULL;
2302 #if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD)
2303 static int atyfb_get_timings_from_lcd(struct atyfb_par *par,
2304 struct fb_var_screeninfo *var)
2308 if (par->lcd_table != 0 && (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
2310 var->xres = var->xres_virtual = par->lcd_hdisp;
2311 var->right_margin = par->lcd_right_margin;
2312 var->left_margin = par->lcd_hblank_len -
2313 (par->lcd_right_margin + par->lcd_hsync_dly +
2314 par->lcd_hsync_len);
2315 var->hsync_len = par->lcd_hsync_len + par->lcd_hsync_dly;
2316 var->yres = var->yres_virtual = par->lcd_vdisp;
2317 var->lower_margin = par->lcd_lower_margin;
2318 var->upper_margin = par->lcd_vblank_len -
2319 (par->lcd_lower_margin + par->lcd_vsync_len);
2320 var->vsync_len = par->lcd_vsync_len;
2321 var->pixclock = par->lcd_pixclock;
2327 #endif /* defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) */
2329 static int aty_init(struct fb_info *info)
2331 struct atyfb_par *par = (struct atyfb_par *) info->par;
2332 const char *ramname = NULL, *xtal;
2333 int gtb_memsize, has_var = 0;
2334 struct fb_var_screeninfo var;
2337 init_waitqueue_head(&par->vblank.wait);
2338 spin_lock_init(&par->int_lock);
2340 #ifdef CONFIG_FB_ATY_GX
2341 if (!M64_HAS(INTEGRATED)) {
2343 u8 dac_type, dac_subtype, clk_type;
2344 stat0 = aty_ld_le32(CNFG_STAT0, par);
2345 par->bus_type = (stat0 >> 0) & 0x07;
2346 par->ram_type = (stat0 >> 3) & 0x07;
2347 ramname = aty_gx_ram[par->ram_type];
2348 /* FIXME: clockchip/RAMDAC probing? */
2349 dac_type = (aty_ld_le32(DAC_CNTL, par) >> 16) & 0x07;
2351 clk_type = CLK_ATI18818_1;
2352 dac_type = (stat0 >> 9) & 0x07;
2353 if (dac_type == 0x07)
2354 dac_subtype = DAC_ATT20C408;
2356 dac_subtype = (aty_ld_8(SCRATCH_REG1 + 1, par) & 0xF0) | dac_type;
2358 dac_type = DAC_IBMRGB514;
2359 dac_subtype = DAC_IBMRGB514;
2360 clk_type = CLK_IBMRGB514;
2362 switch (dac_subtype) {
2364 par->dac_ops = &aty_dac_ibm514;
2367 case DAC_ATI68860_B:
2368 case DAC_ATI68860_C:
2369 par->dac_ops = &aty_dac_ati68860b;
2373 par->dac_ops = &aty_dac_att21c498;
2377 PRINTKI("aty_init: DAC type not implemented yet!\n");
2378 par->dac_ops = &aty_dac_unsupported;
2383 case CLK_ATI18818_1:
2384 par->pll_ops = &aty_pll_ati18818_1;
2388 par->pll_ops = &aty_pll_ibm514;
2392 PRINTKI("aty_init: CLK type not implemented yet!");
2393 par->pll_ops = &aty_pll_unsupported;
2397 #endif /* CONFIG_FB_ATY_GX */
2398 #ifdef CONFIG_FB_ATY_CT
2399 if (M64_HAS(INTEGRATED)) {
2400 par->dac_ops = &aty_dac_ct;
2401 par->pll_ops = &aty_pll_ct;
2402 par->bus_type = PCI;
2403 par->ram_type = (aty_ld_le32(CNFG_STAT0, par) & 0x07);
2404 if (M64_HAS(XL_MEM))
2405 ramname = aty_xl_ram[par->ram_type];
2407 ramname = aty_ct_ram[par->ram_type];
2408 /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
2409 if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM)
2410 par->pll_limits.mclk = 63;
2411 /* Mobility + 32bit memory interface need halved XCLK. */
2412 if (M64_HAS(MOBIL_BUS) && par->ram_type == SDRAM32)
2413 par->pll_limits.xclk = (par->pll_limits.xclk + 1) >> 1;
2416 #ifdef CONFIG_PPC_PMAC
2418 * The Apple iBook1 uses non-standard memory frequencies.
2419 * We detect it and set the frequency manually.
2421 if (of_machine_is_compatible("PowerBook2,1")) {
2422 par->pll_limits.mclk = 70;
2423 par->pll_limits.xclk = 53;
2427 /* Allow command line to override clocks. */
2429 par->pll_limits.pll_max = pll;
2431 par->pll_limits.mclk = mclk;
2433 par->pll_limits.xclk = xclk;
2435 aty_calc_mem_refresh(par, par->pll_limits.xclk);
2436 par->pll_per = 1000000/par->pll_limits.pll_max;
2437 par->mclk_per = 1000000/par->pll_limits.mclk;
2438 par->xclk_per = 1000000/par->pll_limits.xclk;
2440 par->ref_clk_per = 1000000000000ULL / 14318180;
2443 #ifdef CONFIG_FB_ATY_CT
2444 if (M64_HAS(GTB_DSP)) {
2445 u8 pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par);
2449 diff1 = 510 * 14 / pll_ref_div - par->pll_limits.pll_max;
2450 diff2 = 510 * 29 / pll_ref_div - par->pll_limits.pll_max;
2455 if (diff2 < diff1) {
2456 par->ref_clk_per = 1000000000000ULL / 29498928;
2461 #endif /* CONFIG_FB_ATY_CT */
2463 /* save previous video mode */
2464 aty_get_crtc(par, &par->saved_crtc);
2465 if (par->pll_ops->get_pll)
2466 par->pll_ops->get_pll(info, &par->saved_pll);
2468 par->mem_cntl = aty_ld_le32(MEM_CNTL, par);
2469 gtb_memsize = M64_HAS(GTB_DSP);
2471 /* 0xF used instead of MEM_SIZE_ALIAS */
2472 switch (par->mem_cntl & 0xF) {
2474 info->fix.smem_len = 0x80000;
2477 info->fix.smem_len = 0x100000;
2479 case MEM_SIZE_2M_GTB:
2480 info->fix.smem_len = 0x200000;
2482 case MEM_SIZE_4M_GTB:
2483 info->fix.smem_len = 0x400000;
2485 case MEM_SIZE_6M_GTB:
2486 info->fix.smem_len = 0x600000;
2488 case MEM_SIZE_8M_GTB:
2489 info->fix.smem_len = 0x800000;
2492 info->fix.smem_len = 0x80000;
2494 switch (par->mem_cntl & MEM_SIZE_ALIAS) {
2496 info->fix.smem_len = 0x80000;
2499 info->fix.smem_len = 0x100000;
2502 info->fix.smem_len = 0x200000;
2505 info->fix.smem_len = 0x400000;
2508 info->fix.smem_len = 0x600000;
2511 info->fix.smem_len = 0x800000;
2514 info->fix.smem_len = 0x80000;
2517 if (M64_HAS(MAGIC_VRAM_SIZE)) {
2518 if (aty_ld_le32(CNFG_STAT1, par) & 0x40000000)
2519 info->fix.smem_len += 0x400000;
2523 info->fix.smem_len = vram * 1024;
2524 par->mem_cntl &= ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS);
2525 if (info->fix.smem_len <= 0x80000)
2526 par->mem_cntl |= MEM_SIZE_512K;
2527 else if (info->fix.smem_len <= 0x100000)
2528 par->mem_cntl |= MEM_SIZE_1M;
2529 else if (info->fix.smem_len <= 0x200000)
2530 par->mem_cntl |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M;
2531 else if (info->fix.smem_len <= 0x400000)
2532 par->mem_cntl |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M;
2533 else if (info->fix.smem_len <= 0x600000)
2534 par->mem_cntl |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M;
2536 par->mem_cntl |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M;
2537 aty_st_le32(MEM_CNTL, par->mem_cntl, par);
2541 * Reg Block 0 (CT-compatible block) is at mmio_start
2542 * Reg Block 1 (multimedia extensions) is at mmio_start - 0x400
2545 info->fix.mmio_len = 0x400;
2546 info->fix.accel = FB_ACCEL_ATI_MACH64GX;
2547 } else if (M64_HAS(CT)) {
2548 info->fix.mmio_len = 0x400;
2549 info->fix.accel = FB_ACCEL_ATI_MACH64CT;
2550 } else if (M64_HAS(VT)) {
2551 info->fix.mmio_start -= 0x400;
2552 info->fix.mmio_len = 0x800;
2553 info->fix.accel = FB_ACCEL_ATI_MACH64VT;
2555 info->fix.mmio_start -= 0x400;
2556 info->fix.mmio_len = 0x800;
2557 info->fix.accel = FB_ACCEL_ATI_MACH64GT;
2560 PRINTKI("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK, %d MHz XCLK\n",
2561 info->fix.smem_len == 0x80000 ? 512 : (info->fix.smem_len>>20),
2562 info->fix.smem_len == 0x80000 ? 'K' : 'M', ramname, xtal,
2563 par->pll_limits.pll_max, par->pll_limits.mclk,
2564 par->pll_limits.xclk);
2566 #if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)
2567 if (M64_HAS(INTEGRATED)) {
2569 printk("debug atyfb: BUS_CNTL DAC_CNTL MEM_CNTL "
2570 "EXT_MEM_CNTL CRTC_GEN_CNTL DSP_CONFIG "
2571 "DSP_ON_OFF CLOCK_CNTL\n"
2572 "debug atyfb: %08x %08x %08x "
2576 aty_ld_le32(BUS_CNTL, par),
2577 aty_ld_le32(DAC_CNTL, par),
2578 aty_ld_le32(MEM_CNTL, par),
2579 aty_ld_le32(EXT_MEM_CNTL, par),
2580 aty_ld_le32(CRTC_GEN_CNTL, par),
2581 aty_ld_le32(DSP_CONFIG, par),
2582 aty_ld_le32(DSP_ON_OFF, par),
2583 aty_ld_le32(CLOCK_CNTL, par));
2584 for (i = 0; i < 40; i++)
2585 pr_cont(" %02x", aty_ld_pll_ct(i, par));
2589 if (par->pll_ops->init_pll)
2590 par->pll_ops->init_pll(info, &par->pll);
2591 if (par->pll_ops->resume_pll)
2592 par->pll_ops->resume_pll(info, &par->pll);
2594 aty_fudge_framebuffer_len(info);
2597 * Disable register access through the linear aperture
2598 * if the auxiliary aperture is used so we can access
2599 * the full 8 MB of video RAM on 8 MB boards.
2602 aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) |
2603 BUS_APER_REG_DIS, par);
2607 * Only the ioremap_wc()'d area will get WC here
2608 * since ioremap_uc() was used on the entire PCI BAR.
2610 par->wc_cookie = arch_phys_wc_add(par->res_start,
2613 info->fbops = &atyfb_ops;
2614 info->pseudo_palette = par->pseudo_palette;
2615 info->flags = FBINFO_DEFAULT |
2616 FBINFO_HWACCEL_IMAGEBLIT |
2617 FBINFO_HWACCEL_FILLRECT |
2618 FBINFO_HWACCEL_COPYAREA |
2619 FBINFO_HWACCEL_YPAN |
2622 #ifdef CONFIG_PMAC_BACKLIGHT
2623 if (M64_HAS(G3_PB_1_1) && of_machine_is_compatible("PowerBook1,1")) {
2625 * these bits let the 101 powerbook
2626 * wake up from sleep -- paulus
2628 aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par) |
2629 USE_F32KHZ | TRISTATE_MEM_EN, par);
2632 if (M64_HAS(MOBIL_BUS) && backlight) {
2633 #ifdef CONFIG_FB_ATY_BACKLIGHT
2638 memset(&var, 0, sizeof(var));
2640 if (machine_is(powermac)) {
2642 * FIXME: The NVRAM stuff should be put in a Mac-specific file,
2643 * as it applies to all Mac video cards
2646 if (mac_find_mode(&var, info, mode, 8))
2649 if (default_vmode == VMODE_CHOOSE) {
2651 if (M64_HAS(G3_PB_1024x768))
2652 /* G3 PowerBook with 1024x768 LCD */
2653 default_vmode = VMODE_1024_768_60;
2654 else if (of_machine_is_compatible("iMac"))
2655 default_vmode = VMODE_1024_768_75;
2656 else if (of_machine_is_compatible("PowerBook2,1"))
2657 /* iBook with 800x600 LCD */
2658 default_vmode = VMODE_800_600_60;
2660 default_vmode = VMODE_640_480_67;
2661 sense = read_aty_sense(par);
2662 PRINTKI("monitor sense=%x, mode %d\n",
2663 sense, mac_map_monitor_sense(sense));
2665 if (default_vmode <= 0 || default_vmode > VMODE_MAX)
2666 default_vmode = VMODE_640_480_60;
2667 if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
2668 default_cmode = CMODE_8;
2669 if (!mac_vmode_to_var(default_vmode, default_cmode,
2675 #endif /* !CONFIG_PPC */
2677 #if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD)
2678 if (!atyfb_get_timings_from_lcd(par, &var))
2682 if (mode && fb_find_mode(&var, info, mode, NULL, 0, &defmode, 8))
2689 var.accel_flags &= ~FB_ACCELF_TEXT;
2691 var.accel_flags |= FB_ACCELF_TEXT;
2693 if (comp_sync != -1) {
2695 var.sync &= ~FB_SYNC_COMP_HIGH_ACT;
2697 var.sync |= FB_SYNC_COMP_HIGH_ACT;
2700 if (var.yres == var.yres_virtual) {
2701 u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2));
2702 var.yres_virtual = ((videoram * 8) / var.bits_per_pixel) / var.xres_virtual;
2703 if (var.yres_virtual < var.yres)
2704 var.yres_virtual = var.yres;
2707 ret = atyfb_check_var(&var, info);
2709 PRINTKE("can't set default video mode\n");
2713 #ifdef CONFIG_FB_ATY_CT
2714 if (!noaccel && M64_HAS(INTEGRATED))
2715 aty_init_cursor(info, &atyfb_ops);
2716 #endif /* CONFIG_FB_ATY_CT */
2719 ret = fb_alloc_cmap(&info->cmap, 256, 0);
2723 ret = register_framebuffer(info);
2725 fb_dealloc_cmap(&info->cmap);
2731 PRINTKI("fb%d: %s frame buffer device on %s\n",
2732 info->node, info->fix.id, par->bus_type == ISA ? "ISA" : "PCI");
2736 /* restore video mode */
2737 aty_set_crtc(par, &par->saved_crtc);
2738 par->pll_ops->set_pll(info, &par->saved_pll);
2739 arch_phys_wc_del(par->wc_cookie);
2744 #if defined(CONFIG_ATARI) && !defined(MODULE)
2745 static int store_video_par(char *video_str, unsigned char m64_num)
2748 unsigned long vmembase, size, guiregbase;
2750 PRINTKI("store_video_par() '%s' \n", video_str);
2752 if (!(p = strsep(&video_str, ";")) || !*p)
2753 goto mach64_invalid;
2754 vmembase = simple_strtoul(p, NULL, 0);
2755 if (!(p = strsep(&video_str, ";")) || !*p)
2756 goto mach64_invalid;
2757 size = simple_strtoul(p, NULL, 0);
2758 if (!(p = strsep(&video_str, ";")) || !*p)
2759 goto mach64_invalid;
2760 guiregbase = simple_strtoul(p, NULL, 0);
2762 phys_vmembase[m64_num] = vmembase;
2763 phys_size[m64_num] = size;
2764 phys_guiregbase[m64_num] = guiregbase;
2765 PRINTKI("stored them all: $%08lX $%08lX $%08lX \n", vmembase, size,
2770 phys_vmembase[m64_num] = 0;
2773 #endif /* CONFIG_ATARI && !MODULE */
2776 * Blank the display.
2779 static int atyfb_blank(int blank, struct fb_info *info)
2781 struct atyfb_par *par = (struct atyfb_par *) info->par;
2784 if (par->lock_blank || par->asleep)
2787 #ifdef CONFIG_FB_ATY_GENERIC_LCD
2788 if (par->lcd_table && blank > FB_BLANK_NORMAL &&
2789 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
2790 u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2792 aty_st_lcd(POWER_MANAGEMENT, pm, par);
2796 gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
2797 gen_cntl &= ~0x400004c;
2799 case FB_BLANK_UNBLANK:
2801 case FB_BLANK_NORMAL:
2802 gen_cntl |= 0x4000040;
2804 case FB_BLANK_VSYNC_SUSPEND:
2805 gen_cntl |= 0x4000048;
2807 case FB_BLANK_HSYNC_SUSPEND:
2808 gen_cntl |= 0x4000044;
2810 case FB_BLANK_POWERDOWN:
2811 gen_cntl |= 0x400004c;
2814 aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
2816 #ifdef CONFIG_FB_ATY_GENERIC_LCD
2817 if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
2818 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
2819 u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2821 aty_st_lcd(POWER_MANAGEMENT, pm, par);
2828 static void aty_st_pal(u_int regno, u_int red, u_int green, u_int blue,
2829 const struct atyfb_par *par)
2831 aty_st_8(DAC_W_INDEX, regno, par);
2832 aty_st_8(DAC_DATA, red, par);
2833 aty_st_8(DAC_DATA, green, par);
2834 aty_st_8(DAC_DATA, blue, par);
2838 * Set a single color register. The values supplied are already
2839 * rounded down to the hardware's capabilities (according to the
2840 * entries in the var structure). Return != 0 for invalid regno.
2841 * !! 4 & 8 = PSEUDO, > 8 = DIRECTCOLOR
2844 static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
2845 u_int transp, struct fb_info *info)
2847 struct atyfb_par *par = (struct atyfb_par *) info->par;
2849 u32 *pal = info->pseudo_palette;
2851 depth = info->var.bits_per_pixel;
2853 depth = (info->var.green.length == 5) ? 15 : 16;
2859 (depth == 16 && regno > 63) ||
2860 (depth == 15 && regno > 31))
2867 par->palette[regno].red = red;
2868 par->palette[regno].green = green;
2869 par->palette[regno].blue = blue;
2874 pal[regno] = (regno << 10) | (regno << 5) | regno;
2877 pal[regno] = (regno << 11) | (regno << 5) | regno;
2880 pal[regno] = (regno << 16) | (regno << 8) | regno;
2883 i = (regno << 8) | regno;
2884 pal[regno] = (i << 16) | i;
2889 i = aty_ld_8(DAC_CNTL, par) & 0xfc;
2890 if (M64_HAS(EXTRA_BRIGHT))
2891 i |= 0x2; /* DAC_CNTL | 0x2 turns off the extra brightness for gt */
2892 aty_st_8(DAC_CNTL, i, par);
2893 aty_st_8(DAC_MASK, 0xff, par);
2895 if (M64_HAS(INTEGRATED)) {
2898 aty_st_pal(regno << 3, red,
2899 par->palette[regno << 1].green,
2901 red = par->palette[regno >> 1].red;
2902 blue = par->palette[regno >> 1].blue;
2904 } else if (depth == 15) {
2906 for (i = 0; i < 8; i++)
2907 aty_st_pal(regno + i, red, green, blue, par);
2910 aty_st_pal(regno, red, green, blue, par);
2919 static int atyfb_setup_sparc(struct pci_dev *pdev, struct fb_info *info,
2922 struct atyfb_par *par = info->par;
2923 struct device_node *dp;
2928 * Map memory-mapped registers.
2930 par->ati_regbase = (void *)addr + 0x7ffc00UL;
2931 info->fix.mmio_start = addr + 0x7ffc00UL;
2934 * Map in big-endian aperture.
2936 info->screen_base = (char *) (addr + 0x800000UL);
2937 info->fix.smem_start = addr + 0x800000UL;
2940 * Figure mmap addresses from PCI config space.
2941 * Split Framebuffer in big- and little-endian halfs.
2943 for (i = 0; i < 6 && pdev->resource[i].start; i++)
2947 par->mmap_map = kcalloc(j, sizeof(*par->mmap_map), GFP_ATOMIC);
2948 if (!par->mmap_map) {
2949 PRINTKE("atyfb_setup_sparc() can't alloc mmap_map\n");
2953 for (i = 0, j = 2; i < 6 && pdev->resource[i].start; i++) {
2954 struct resource *rp = &pdev->resource[i];
2955 int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
2961 io = (rp->flags & IORESOURCE_IO);
2963 size = rp->end - base + 1;
2965 pci_read_config_dword(pdev, breg, &pbase);
2971 * Map the framebuffer a second time, this time without
2972 * the braindead _PAGE_IE setting. This is used by the
2973 * fixed Xserver, but we need to maintain the old mapping
2974 * to stay compatible with older ones...
2977 par->mmap_map[j].voff = (pbase + 0x10000000) & PAGE_MASK;
2978 par->mmap_map[j].poff = base & PAGE_MASK;
2979 par->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
2980 par->mmap_map[j].prot_mask = _PAGE_CACHE;
2981 par->mmap_map[j].prot_flag = _PAGE_E;
2986 * Here comes the old framebuffer mapping with _PAGE_IE
2987 * set for the big endian half of the framebuffer...
2990 par->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK;
2991 par->mmap_map[j].poff = (base + 0x800000) & PAGE_MASK;
2992 par->mmap_map[j].size = 0x800000;
2993 par->mmap_map[j].prot_mask = _PAGE_CACHE;
2994 par->mmap_map[j].prot_flag = _PAGE_E | _PAGE_IE;
2999 par->mmap_map[j].voff = pbase & PAGE_MASK;
3000 par->mmap_map[j].poff = base & PAGE_MASK;
3001 par->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
3002 par->mmap_map[j].prot_mask = _PAGE_CACHE;
3003 par->mmap_map[j].prot_flag = _PAGE_E;
3007 ret = correct_chipset(par);
3011 if (IS_XL(pdev->device)) {
3013 * Fix PROMs idea of MEM_CNTL settings...
3015 mem = aty_ld_le32(MEM_CNTL, par);
3016 chip_id = aty_ld_le32(CNFG_CHIP_ID, par);
3017 if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) && !((chip_id >> 24) & 1)) {
3018 switch (mem & 0x0f) {
3020 mem = (mem & ~(0x0f)) | 2;
3023 mem = (mem & ~(0x0f)) | 3;
3026 mem = (mem & ~(0x0f)) | 4;
3029 mem = (mem & ~(0x0f)) | 5;
3034 if ((aty_ld_le32(CNFG_STAT0, par) & 7) >= SDRAM)
3035 mem &= ~(0x00700000);
3037 mem &= ~(0xcf80e000); /* Turn off all undocumented bits. */
3038 aty_st_le32(MEM_CNTL, mem, par);
3041 dp = pci_device_to_OF_node(pdev);
3042 if (dp == of_console_device) {
3043 struct fb_var_screeninfo *var = &default_var;
3044 unsigned int N, P, Q, M, T, R;
3045 u32 v_total, h_total;
3050 crtc.vxres = of_getintprop_default(dp, "width", 1024);
3051 crtc.vyres = of_getintprop_default(dp, "height", 768);
3052 var->bits_per_pixel = of_getintprop_default(dp, "depth", 8);
3053 var->xoffset = var->yoffset = 0;
3054 crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
3055 crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
3056 crtc.v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
3057 crtc.v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
3058 crtc.gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
3059 aty_crtc_to_var(&crtc, var);
3061 h_total = var->xres + var->right_margin + var->hsync_len + var->left_margin;
3062 v_total = var->yres + var->lower_margin + var->vsync_len + var->upper_margin;
3065 * Read the PLL to figure actual Refresh Rate.
3067 clock_cntl = aty_ld_8(CLOCK_CNTL, par);
3068 /* DPRINTK("CLOCK_CNTL %02x\n", clock_cntl); */
3069 for (i = 0; i < 16; i++)
3070 pll_regs[i] = aty_ld_pll_ct(i, par);
3073 * PLL Reference Divider M:
3075 M = pll_regs[PLL_REF_DIV];
3078 * PLL Feedback Divider N (Dependent on CLOCK_CNTL):
3080 N = pll_regs[VCLK0_FB_DIV + (clock_cntl & 3)];
3083 * PLL Post Divider P (Dependent on CLOCK_CNTL):
3085 P = aty_postdividers[((pll_regs[VCLK_POST_DIV] >> ((clock_cntl & 3) << 1)) & 3) |
3086 ((pll_regs[PLL_EXT_CNTL] >> (2 + (clock_cntl & 3))) & 4)];
3100 * where R is XTALIN (= 14318 or 29498 kHz).
3102 if (IS_XL(pdev->device))
3109 default_var.pixclock = 1000000000 / T;
3115 #else /* __sparc__ */
3118 #ifdef CONFIG_FB_ATY_GENERIC_LCD
3119 static void aty_init_lcd(struct atyfb_par *par, u32 bios_base)
3121 u32 driv_inf_tab, sig;
3125 * To support an LCD panel, we should know it's dimensions and
3126 * it's desired pixel clock.
3127 * There are two ways to do it:
3128 * - Check the startup video mode and calculate the panel
3129 * size from it. This is unreliable.
3130 * - Read it from the driver information table in the video BIOS.
3132 /* Address of driver information table is at offset 0x78. */
3133 driv_inf_tab = bios_base + *((u16 *)(bios_base+0x78));
3135 /* Check for the driver information table signature. */
3136 sig = *(u32 *)driv_inf_tab;
3137 if ((sig == 0x54504c24) || /* Rage LT pro */
3138 (sig == 0x544d5224) || /* Rage mobility */
3139 (sig == 0x54435824) || /* Rage XC */
3140 (sig == 0x544c5824)) { /* Rage XL */
3141 PRINTKI("BIOS contains driver information table.\n");
3142 lcd_ofs = *(u16 *)(driv_inf_tab + 10);
3145 par->lcd_table = bios_base + lcd_ofs;
3148 if (par->lcd_table != 0) {
3151 char refresh_rates_buf[100];
3152 int id, tech, f, i, m, default_refresh_rate;
3157 u16 width, height, panel_type, refresh_rates;
3160 u8 lcd_refresh_rates[16] = { 50, 56, 60, 67, 70, 72, 75, 76, 85,
3161 90, 100, 120, 140, 150, 160, 200 };
3163 * The most important information is the panel size at
3164 * offset 25 and 27, but there's some other nice information
3165 * which we print to the screen.
3167 id = *(u8 *)par->lcd_table;
3168 strncpy(model, (char *)par->lcd_table+1, 24);
3171 width = par->lcd_width = *(u16 *)(par->lcd_table+25);
3172 height = par->lcd_height = *(u16 *)(par->lcd_table+27);
3173 panel_type = *(u16 *)(par->lcd_table+29);
3175 txtcolour = "colour";
3177 txtcolour = "monochrome";
3179 txtdual = "dual (split) ";
3182 tech = (panel_type >> 2) & 63;
3185 txtmonitor = "passive matrix";
3188 txtmonitor = "active matrix";
3191 txtmonitor = "active addressed STN";
3197 txtmonitor = "plasma";
3200 txtmonitor = "unknown";
3202 format = *(u32 *)(par->lcd_table+57);
3203 if (tech == 0 || tech == 2) {
3204 switch (format & 7) {
3206 txtformat = "12 bit interface";
3209 txtformat = "16 bit interface";
3212 txtformat = "24 bit interface";
3215 txtformat = "unknown format";
3218 switch (format & 7) {
3220 txtformat = "8 colours";
3223 txtformat = "512 colours";
3226 txtformat = "4096 colours";
3229 txtformat = "262144 colours (LT mode)";
3232 txtformat = "16777216 colours";
3235 txtformat = "262144 colours (FDPI-2 mode)";
3238 txtformat = "unknown format";
3241 PRINTKI("%s%s %s monitor detected: %s\n",
3242 txtdual, txtcolour, txtmonitor, model);
3243 PRINTKI(" id=%d, %dx%d pixels, %s\n",
3244 id, width, height, txtformat);
3245 refresh_rates_buf[0] = 0;
3246 refresh_rates = *(u16 *)(par->lcd_table+62);
3249 for (i = 0; i < 16; i++) {
3250 if (refresh_rates & m) {
3252 sprintf(strbuf, "%d",
3253 lcd_refresh_rates[i]);
3256 sprintf(strbuf, ",%d",
3257 lcd_refresh_rates[i]);
3259 strcat(refresh_rates_buf, strbuf);
3263 default_refresh_rate = (*(u8 *)(par->lcd_table+61) & 0xf0) >> 4;
3264 PRINTKI(" supports refresh rates [%s], default %d Hz\n",
3265 refresh_rates_buf, lcd_refresh_rates[default_refresh_rate]);
3266 par->lcd_refreshrate = lcd_refresh_rates[default_refresh_rate];
3268 * We now need to determine the crtc parameters for the
3269 * LCD monitor. This is tricky, because they are not stored
3270 * individually in the BIOS. Instead, the BIOS contains a
3271 * table of display modes that work for this monitor.
3273 * The idea is that we search for a mode of the same dimensions
3274 * as the dimensions of the LCD monitor. Say our LCD monitor
3275 * is 800x600 pixels, we search for a 800x600 monitor.
3276 * The CRTC parameters we find here are the ones that we need
3277 * to use to simulate other resolutions on the LCD screen.
3279 lcdmodeptr = (u16 *)(par->lcd_table + 64);
3280 while (*lcdmodeptr != 0) {
3282 u16 mwidth, mheight, lcd_hsync_start, lcd_vsync_start;
3283 modeptr = bios_base + *lcdmodeptr;
3285 mwidth = *((u16 *)(modeptr+0));
3286 mheight = *((u16 *)(modeptr+2));
3288 if (mwidth == width && mheight == height) {
3289 par->lcd_pixclock = 100000000 / *((u16 *)(modeptr+9));
3290 par->lcd_htotal = *((u16 *)(modeptr+17)) & 511;
3291 par->lcd_hdisp = *((u16 *)(modeptr+19)) & 511;
3292 lcd_hsync_start = *((u16 *)(modeptr+21)) & 511;
3293 par->lcd_hsync_dly = (*((u16 *)(modeptr+21)) >> 9) & 7;
3294 par->lcd_hsync_len = *((u8 *)(modeptr+23)) & 63;
3296 par->lcd_vtotal = *((u16 *)(modeptr+24)) & 2047;
3297 par->lcd_vdisp = *((u16 *)(modeptr+26)) & 2047;
3298 lcd_vsync_start = *((u16 *)(modeptr+28)) & 2047;
3299 par->lcd_vsync_len = (*((u16 *)(modeptr+28)) >> 11) & 31;
3301 par->lcd_htotal = (par->lcd_htotal + 1) * 8;
3302 par->lcd_hdisp = (par->lcd_hdisp + 1) * 8;
3303 lcd_hsync_start = (lcd_hsync_start + 1) * 8;
3304 par->lcd_hsync_len = par->lcd_hsync_len * 8;
3310 par->lcd_right_margin = lcd_hsync_start - par->lcd_hdisp;
3311 par->lcd_lower_margin = lcd_vsync_start - par->lcd_vdisp;
3312 par->lcd_hblank_len = par->lcd_htotal - par->lcd_hdisp;
3313 par->lcd_vblank_len = par->lcd_vtotal - par->lcd_vdisp;
3319 if (*lcdmodeptr == 0) {
3320 PRINTKE("LCD monitor CRTC parameters not found!!!\n");
3321 /* To do: Switch to CRT if possible. */
3323 PRINTKI(" LCD CRTC parameters: %d.%d %d %d %d %d %d %d %d %d\n",
3324 1000000 / par->lcd_pixclock, 1000000 % par->lcd_pixclock,
3326 par->lcd_hdisp + par->lcd_right_margin,
3327 par->lcd_hdisp + par->lcd_right_margin
3328 + par->lcd_hsync_dly + par->lcd_hsync_len,
3331 par->lcd_vdisp + par->lcd_lower_margin,
3332 par->lcd_vdisp + par->lcd_lower_margin + par->lcd_vsync_len,
3334 PRINTKI(" : %d %d %d %d %d %d %d %d %d\n",
3336 par->lcd_hblank_len - (par->lcd_right_margin +
3337 par->lcd_hsync_dly + par->lcd_hsync_len),
3339 par->lcd_right_margin,
3341 par->lcd_vblank_len - (par->lcd_lower_margin + par->lcd_vsync_len),
3343 par->lcd_lower_margin,
3344 par->lcd_vsync_len);
3348 #endif /* CONFIG_FB_ATY_GENERIC_LCD */
3350 static int init_from_bios(struct atyfb_par *par)
3352 u32 bios_base, rom_addr;
3355 rom_addr = 0xc0000 + ((aty_ld_le32(SCRATCH_REG1, par) & 0x7f) << 11);
3356 bios_base = (unsigned long)ioremap(rom_addr, 0x10000);
3358 /* The BIOS starts with 0xaa55. */
3359 if (*((u16 *)bios_base) == 0xaa55) {
3362 u16 rom_table_offset, freq_table_offset;
3363 PLL_BLOCK_MACH64 pll_block;
3365 PRINTKI("Mach64 BIOS is located at %x, mapped at %x.\n", rom_addr, bios_base);
3367 /* check for frequncy table */
3368 bios_ptr = (u8*)bios_base;
3369 rom_table_offset = (u16)(bios_ptr[0x48] | (bios_ptr[0x49] << 8));
3370 freq_table_offset = bios_ptr[rom_table_offset + 16] | (bios_ptr[rom_table_offset + 17] << 8);
3371 memcpy(&pll_block, bios_ptr + freq_table_offset, sizeof(PLL_BLOCK_MACH64));
3373 PRINTKI("BIOS frequency table:\n");
3374 PRINTKI("PCLK_min_freq %d, PCLK_max_freq %d, ref_freq %d, ref_divider %d\n",
3375 pll_block.PCLK_min_freq, pll_block.PCLK_max_freq,
3376 pll_block.ref_freq, pll_block.ref_divider);
3377 PRINTKI("MCLK_pwd %d, MCLK_max_freq %d, XCLK_max_freq %d, SCLK_freq %d\n",
3378 pll_block.MCLK_pwd, pll_block.MCLK_max_freq,
3379 pll_block.XCLK_max_freq, pll_block.SCLK_freq);
3381 par->pll_limits.pll_min = pll_block.PCLK_min_freq/100;
3382 par->pll_limits.pll_max = pll_block.PCLK_max_freq/100;
3383 par->pll_limits.ref_clk = pll_block.ref_freq/100;
3384 par->pll_limits.ref_div = pll_block.ref_divider;
3385 par->pll_limits.sclk = pll_block.SCLK_freq/100;
3386 par->pll_limits.mclk = pll_block.MCLK_max_freq/100;
3387 par->pll_limits.mclk_pm = pll_block.MCLK_pwd/100;
3388 par->pll_limits.xclk = pll_block.XCLK_max_freq/100;
3389 #ifdef CONFIG_FB_ATY_GENERIC_LCD
3390 aty_init_lcd(par, bios_base);
3394 PRINTKE("no BIOS frequency table found, use parameters\n");
3397 iounmap((void __iomem *)bios_base);
3401 #endif /* __i386__ */
3403 static int atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info,
3406 struct atyfb_par *par = info->par;
3408 unsigned long raddr;
3409 struct resource *rrp;
3412 raddr = addr + 0x7ff000UL;
3413 rrp = &pdev->resource[2];
3414 if ((rrp->flags & IORESOURCE_MEM) &&
3415 request_mem_region(rrp->start, resource_size(rrp), "atyfb")) {
3416 par->aux_start = rrp->start;
3417 par->aux_size = resource_size(rrp);
3419 PRINTKI("using auxiliary register aperture\n");
3422 info->fix.mmio_start = raddr;
3424 * By using strong UC we force the MTRR to never have an
3425 * effect on the MMIO region on both non-PAT and PAT systems.
3427 par->ati_regbase = ioremap_uc(info->fix.mmio_start, 0x1000);
3428 if (par->ati_regbase == NULL)
3431 info->fix.mmio_start += par->aux_start ? 0x400 : 0xc00;
3432 par->ati_regbase += par->aux_start ? 0x400 : 0xc00;
3435 * Enable memory-space accesses using config-space
3438 pci_read_config_word(pdev, PCI_COMMAND, &tmp);
3439 if (!(tmp & PCI_COMMAND_MEMORY)) {
3440 tmp |= PCI_COMMAND_MEMORY;
3441 pci_write_config_word(pdev, PCI_COMMAND, tmp);
3444 /* Use the big-endian aperture */
3448 /* Map in frame buffer */
3449 info->fix.smem_start = addr;
3452 * The framebuffer is not always 8 MiB, that's just the size of the
3453 * PCI BAR. We temporarily abuse smem_len here to store the size
3454 * of the BAR. aty_init() will later correct it to match the actual
3457 * On devices that don't have the auxiliary register aperture, the
3458 * registers are housed at the top end of the framebuffer PCI BAR.
3459 * aty_fudge_framebuffer_len() is used to reduce smem_len to not
3460 * overlap with the registers.
3462 info->fix.smem_len = 0x800000;
3464 aty_fudge_framebuffer_len(info);
3466 info->screen_base = ioremap_wc(info->fix.smem_start,
3467 info->fix.smem_len);
3468 if (info->screen_base == NULL) {
3470 goto atyfb_setup_generic_fail;
3473 ret = correct_chipset(par);
3475 goto atyfb_setup_generic_fail;
3477 ret = init_from_bios(par);
3479 goto atyfb_setup_generic_fail;
3481 if (!(aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_EXT_DISP_EN))
3482 par->clk_wr_offset = (inb(R_GENMO) & 0x0CU) >> 2;
3484 par->clk_wr_offset = aty_ld_8(CLOCK_CNTL, par) & 0x03U;
3486 /* according to ATI, we should use clock 3 for acelerated mode */
3487 par->clk_wr_offset = 3;
3491 atyfb_setup_generic_fail:
3492 iounmap(par->ati_regbase);
3493 par->ati_regbase = NULL;
3494 if (info->screen_base) {
3495 iounmap(info->screen_base);
3496 info->screen_base = NULL;
3501 #endif /* !__sparc__ */
3503 static int atyfb_pci_probe(struct pci_dev *pdev,
3504 const struct pci_device_id *ent)
3506 unsigned long addr, res_start, res_size;
3507 struct fb_info *info;
3508 struct resource *rp;
3509 struct atyfb_par *par;
3512 /* Enable device in PCI config */
3513 if (pci_enable_device(pdev)) {
3514 PRINTKE("Cannot enable PCI device\n");
3518 /* Find which resource to use */
3519 rp = &pdev->resource[0];
3520 if (rp->flags & IORESOURCE_IO)
3521 rp = &pdev->resource[1];
3527 res_start = rp->start;
3528 res_size = resource_size(rp);
3529 if (!request_mem_region(res_start, res_size, "atyfb"))
3532 /* Allocate framebuffer */
3533 info = framebuffer_alloc(sizeof(struct atyfb_par), &pdev->dev);
3538 par->bus_type = PCI;
3539 info->fix = atyfb_fix;
3540 info->device = &pdev->dev;
3541 par->pci_id = pdev->device;
3542 par->res_start = res_start;
3543 par->res_size = res_size;
3544 par->irq = pdev->irq;
3547 /* Setup "info" structure */
3549 rc = atyfb_setup_sparc(pdev, info, addr);
3551 rc = atyfb_setup_generic(pdev, info, addr);
3554 goto err_release_mem;
3556 pci_set_drvdata(pdev, info);
3558 /* Init chip & register framebuffer */
3559 rc = aty_init(info);
3561 goto err_release_io;
3565 * Add /dev/fb mmap values.
3567 par->mmap_map[0].voff = 0x8000000000000000UL;
3568 par->mmap_map[0].poff = (unsigned long) info->screen_base & PAGE_MASK;
3569 par->mmap_map[0].size = info->fix.smem_len;
3570 par->mmap_map[0].prot_mask = _PAGE_CACHE;
3571 par->mmap_map[0].prot_flag = _PAGE_E;
3572 par->mmap_map[1].voff = par->mmap_map[0].voff + info->fix.smem_len;
3573 par->mmap_map[1].poff = (long)par->ati_regbase & PAGE_MASK;
3574 par->mmap_map[1].size = PAGE_SIZE;
3575 par->mmap_map[1].prot_mask = _PAGE_CACHE;
3576 par->mmap_map[1].prot_flag = _PAGE_E;
3577 #endif /* __sparc__ */
3579 mutex_lock(&reboot_lock);
3582 mutex_unlock(&reboot_lock);
3588 kfree(par->mmap_map);
3590 if (par->ati_regbase)
3591 iounmap(par->ati_regbase);
3592 if (info->screen_base)
3593 iounmap(info->screen_base);
3597 release_mem_region(par->aux_start, par->aux_size);
3599 release_mem_region(par->res_start, par->res_size);
3600 framebuffer_release(info);
3605 #endif /* CONFIG_PCI */
3609 static int __init atyfb_atari_probe(void)
3611 struct atyfb_par *par;
3612 struct fb_info *info;
3617 for (m64_num = 0; m64_num < mach64_count; m64_num++) {
3618 if (!phys_vmembase[m64_num] || !phys_size[m64_num] ||
3619 !phys_guiregbase[m64_num]) {
3620 PRINTKI("phys_*[%d] parameters not set => "
3621 "returning early. \n", m64_num);
3625 info = framebuffer_alloc(sizeof(struct atyfb_par), NULL);
3631 info->fix = atyfb_fix;
3633 par->irq = (unsigned int) -1; /* something invalid */
3636 * Map the video memory (physical address given)
3637 * to somewhere in the kernel address space.
3639 info->screen_base = ioremap_wc(phys_vmembase[m64_num],
3640 phys_size[m64_num]);
3641 info->fix.smem_start = (unsigned long)info->screen_base; /* Fake! */
3642 par->ati_regbase = ioremap(phys_guiregbase[m64_num], 0x10000) +
3644 info->fix.mmio_start = (unsigned long)par->ati_regbase; /* Fake! */
3646 aty_st_le32(CLOCK_CNTL, 0x12345678, par);
3647 clock_r = aty_ld_le32(CLOCK_CNTL, par);
3649 switch (clock_r & 0x003F) {
3651 par->clk_wr_offset = 3; /* */
3654 par->clk_wr_offset = 2; /* Medusa ST-IO ISA Adapter etc. */
3657 par->clk_wr_offset = 1; /* */
3660 par->clk_wr_offset = 0; /* Panther 1 ISA Adapter (Gerald) */
3664 /* Fake pci_id for correct_chipset() */
3665 switch (aty_ld_le32(CNFG_CHIP_ID, par) & CFG_CHIP_TYPE) {
3667 par->pci_id = PCI_CHIP_MACH64GX;
3670 par->pci_id = PCI_CHIP_MACH64CX;
3676 if (correct_chipset(par) || aty_init(info)) {
3677 iounmap(info->screen_base);
3678 iounmap(par->ati_regbase);
3679 framebuffer_release(info);
3685 return num_found ? 0 : -ENXIO;
3688 #endif /* CONFIG_ATARI */
3692 static void atyfb_remove(struct fb_info *info)
3694 struct atyfb_par *par = (struct atyfb_par *) info->par;
3696 /* restore video mode */
3697 aty_set_crtc(par, &par->saved_crtc);
3698 par->pll_ops->set_pll(info, &par->saved_pll);
3700 unregister_framebuffer(info);
3702 #ifdef CONFIG_FB_ATY_BACKLIGHT
3703 if (M64_HAS(MOBIL_BUS))
3704 aty_bl_exit(info->bl_dev);
3706 arch_phys_wc_del(par->wc_cookie);
3709 if (par->ati_regbase)
3710 iounmap(par->ati_regbase);
3711 if (info->screen_base)
3712 iounmap(info->screen_base);
3714 if (info->sprite.addr)
3715 iounmap(info->sprite.addr);
3719 kfree(par->mmap_map);
3722 release_mem_region(par->aux_start, par->aux_size);
3725 release_mem_region(par->res_start, par->res_size);
3727 framebuffer_release(info);
3731 static void atyfb_pci_remove(struct pci_dev *pdev)
3733 struct fb_info *info = pci_get_drvdata(pdev);
3735 mutex_lock(&reboot_lock);
3736 if (reboot_info == info)
3738 mutex_unlock(&reboot_lock);
3743 static const struct pci_device_id atyfb_pci_tbl[] = {
3744 #ifdef CONFIG_FB_ATY_GX
3745 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GX) },
3746 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64CX) },
3747 #endif /* CONFIG_FB_ATY_GX */
3749 #ifdef CONFIG_FB_ATY_CT
3750 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64CT) },
3751 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64ET) },
3753 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LT) },
3755 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VT) },
3756 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GT) },
3758 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VU) },
3759 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GU) },
3761 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LG) },
3763 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VV) },
3765 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GV) },
3766 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GW) },
3767 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GY) },
3768 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GZ) },
3770 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GB) },
3771 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GD) },
3772 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GI) },
3773 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GP) },
3774 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GQ) },
3776 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LB) },
3777 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LD) },
3778 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LI) },
3779 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LP) },
3780 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LQ) },
3782 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GM) },
3783 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GN) },
3784 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GO) },
3785 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GL) },
3786 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GR) },
3787 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GS) },
3789 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LM) },
3790 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LN) },
3791 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LR) },
3792 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LS) },
3793 #endif /* CONFIG_FB_ATY_CT */
3797 MODULE_DEVICE_TABLE(pci, atyfb_pci_tbl);
3799 static struct pci_driver atyfb_driver = {
3801 .id_table = atyfb_pci_tbl,
3802 .probe = atyfb_pci_probe,
3803 .remove = atyfb_pci_remove,
3805 .suspend = atyfb_pci_suspend,
3806 .resume = atyfb_pci_resume,
3807 #endif /* CONFIG_PM */
3810 #endif /* CONFIG_PCI */
3813 static int __init atyfb_setup(char *options)
3817 if (!options || !*options)
3820 while ((this_opt = strsep(&options, ",")) != NULL) {
3821 if (!strncmp(this_opt, "noaccel", 7)) {
3823 } else if (!strncmp(this_opt, "nomtrr", 6)) {
3825 } else if (!strncmp(this_opt, "vram:", 5))
3826 vram = simple_strtoul(this_opt + 5, NULL, 0);
3827 else if (!strncmp(this_opt, "pll:", 4))
3828 pll = simple_strtoul(this_opt + 4, NULL, 0);
3829 else if (!strncmp(this_opt, "mclk:", 5))
3830 mclk = simple_strtoul(this_opt + 5, NULL, 0);
3831 else if (!strncmp(this_opt, "xclk:", 5))
3832 xclk = simple_strtoul(this_opt+5, NULL, 0);
3833 else if (!strncmp(this_opt, "comp_sync:", 10))
3834 comp_sync = simple_strtoul(this_opt+10, NULL, 0);
3835 else if (!strncmp(this_opt, "backlight:", 10))
3836 backlight = simple_strtoul(this_opt+10, NULL, 0);
3838 else if (!strncmp(this_opt, "vmode:", 6)) {
3839 unsigned int vmode =
3840 simple_strtoul(this_opt + 6, NULL, 0);
3841 if (vmode > 0 && vmode <= VMODE_MAX)
3842 default_vmode = vmode;
3843 } else if (!strncmp(this_opt, "cmode:", 6)) {
3844 unsigned int cmode =
3845 simple_strtoul(this_opt + 6, NULL, 0);
3849 default_cmode = CMODE_8;
3853 default_cmode = CMODE_16;
3857 default_cmode = CMODE_32;
3864 * Why do we need this silly Mach64 argument?
3865 * We are already here because of mach64= so its redundant.
3867 else if (MACH_IS_ATARI
3868 && (!strncmp(this_opt, "Mach64:", 7))) {
3869 static unsigned char m64_num;
3870 static char mach64_str[80];
3871 strlcpy(mach64_str, this_opt + 7, sizeof(mach64_str));
3872 if (!store_video_par(mach64_str, m64_num)) {
3874 mach64_count = m64_num;
3885 static int atyfb_reboot_notify(struct notifier_block *nb,
3886 unsigned long code, void *unused)
3888 struct atyfb_par *par;
3890 if (code != SYS_RESTART)
3893 mutex_lock(&reboot_lock);
3898 lock_fb_info(reboot_info);
3900 par = reboot_info->par;
3903 * HP OmniBook 500's BIOS doesn't like the state of the
3904 * hardware after atyfb has been used. Restore the hardware
3905 * to the original state to allow successful reboots.
3907 aty_set_crtc(par, &par->saved_crtc);
3908 par->pll_ops->set_pll(reboot_info, &par->saved_pll);
3910 unlock_fb_info(reboot_info);
3912 mutex_unlock(&reboot_lock);
3917 static struct notifier_block atyfb_reboot_notifier = {
3918 .notifier_call = atyfb_reboot_notify,
3921 static const struct dmi_system_id atyfb_reboot_ids[] __initconst = {
3923 .ident = "HP OmniBook 500",
3925 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
3926 DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
3927 DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 500 FA"),
3933 static bool registered_notifier = false;
3935 static int __init atyfb_init(void)
3937 int err1 = 1, err2 = 1;
3939 char *option = NULL;
3941 if (fb_get_options("atyfb", &option))
3943 atyfb_setup(option);
3947 err1 = pci_register_driver(&atyfb_driver);
3950 err2 = atyfb_atari_probe();
3956 if (dmi_check_system(atyfb_reboot_ids)) {
3957 register_reboot_notifier(&atyfb_reboot_notifier);
3958 registered_notifier = true;
3964 static void __exit atyfb_exit(void)
3966 if (registered_notifier)
3967 unregister_reboot_notifier(&atyfb_reboot_notifier);
3970 pci_unregister_driver(&atyfb_driver);
3974 module_init(atyfb_init);
3975 module_exit(atyfb_exit);
3977 MODULE_DESCRIPTION("FBDev driver for ATI Mach64 cards");
3978 MODULE_LICENSE("GPL");
3979 module_param(noaccel, bool, 0);
3980 MODULE_PARM_DESC(noaccel, "bool: disable acceleration");
3981 module_param(vram, int, 0);
3982 MODULE_PARM_DESC(vram, "int: override size of video ram");
3983 module_param(pll, int, 0);
3984 MODULE_PARM_DESC(pll, "int: override video clock");
3985 module_param(mclk, int, 0);
3986 MODULE_PARM_DESC(mclk, "int: override memory clock");
3987 module_param(xclk, int, 0);
3988 MODULE_PARM_DESC(xclk, "int: override accelerated engine clock");
3989 module_param(comp_sync, int, 0);
3990 MODULE_PARM_DESC(comp_sync, "Set composite sync signal to low (0) or high (1)");
3991 module_param(mode, charp, 0);
3992 MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
3993 module_param(nomtrr, bool, 0);
3994 MODULE_PARM_DESC(nomtrr, "bool: disable use of MTRR registers");