File: /usr/src/linux/drivers/video/aty/atyfb_base.c

1     
2     /*
3      *  ATI Frame Buffer Device Driver Core
4      *
5      *	Copyright (C) 1997-2001  Geert Uytterhoeven
6      *	Copyright (C) 1998  Bernd Harries
7      *	Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
8      *
9      *  This driver supports the following ATI graphics chips:
10      *    - ATI Mach64
11      *
12      *  To do: add support for
13      *    - ATI Rage128 (from aty128fb.c)
14      *    - ATI Radeon (from radeonfb.c)
15      *
16      *  This driver is partly based on the PowerMac console driver:
17      *
18      *	Copyright (C) 1996 Paul Mackerras
19      *
20      *  and on the PowerMac ATI/mach64 display driver:
21      *
22      *	Copyright (C) 1997 Michael AK Tesch
23      *
24      *	      with work by Jon Howell
25      *			   Harry AC Eaton
26      *			   Anthony Tong <atong@uiuc.edu>
27      *
28      *  This file is subject to the terms and conditions of the GNU General Public
29      *  License. See the file COPYING in the main directory of this archive for
30      *  more details.
31      *  
32      *  Many thanks to Nitya from ATI devrel for support and patience !
33      */
34     
35     /******************************************************************************
36     
37       TODO:
38     
39         - cursor support on all cards and all ramdacs.
40         - cursor parameters controlable via ioctl()s.
41         - guess PLL and MCLK based on the original PLL register values initialized
42           by the BIOS or Open Firmware (if they are initialized).
43     
44     						(Anyone to help with this?)
45     
46     ******************************************************************************/
47     
48     
49     #include <linux/config.h>
50     #include <linux/module.h>
51     #include <linux/kernel.h>
52     #include <linux/errno.h>
53     #include <linux/string.h>
54     #include <linux/mm.h>
55     #include <linux/slab.h>
56     #include <linux/vmalloc.h>
57     #include <linux/delay.h>
58     #include <linux/selection.h>
59     #include <linux/console.h>
60     #include <linux/fb.h>
61     #include <linux/init.h>
62     #include <linux/pci.h>
63     #include <linux/vt_kern.h>
64     #include <linux/kd.h>
65     
66     #include <asm/io.h>
67     #include <asm/uaccess.h>
68     
69     #include <video/fbcon.h>
70     #include <video/fbcon-cfb8.h>
71     #include <video/fbcon-cfb16.h>
72     #include <video/fbcon-cfb24.h>
73     #include <video/fbcon-cfb32.h>
74     
75     #include "mach64.h"
76     #include "atyfb.h"
77     
78     #ifdef __powerpc__
79     #include <asm/prom.h>
80     #include <video/macmodes.h>
81     #endif
82     #ifdef __sparc__
83     #include <asm/pbm.h>
84     #include <asm/fbio.h>
85     #endif
86     
87     #ifdef CONFIG_ADB_PMU
88     #include <linux/adb.h>
89     #include <linux/pmu.h>
90     #endif
91     #ifdef CONFIG_NVRAM
92     #include <linux/nvram.h>
93     #endif
94     #ifdef CONFIG_FB_COMPAT_XPMAC
95     #include <asm/vc_ioctl.h>
96     #endif
97     #ifdef CONFIG_PMAC_BACKLIGHT
98     #include <asm/backlight.h>
99     #endif
100     
101     
102     /*
103      * Debug flags.
104      */
105     #undef DEBUG
106     
107     /* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */
108     /*  - must be large enough to catch all GUI-Regs   */
109     /*  - must be aligned to a PAGE boundary           */
110     #define GUI_RESERVE	(1 * PAGE_SIZE)
111     
112     
113     /* FIXME: remove the FAIL definition */
114     #define FAIL(x) do { printk(x "\n"); return -EINVAL; } while (0)
115     
116     
117         /*
118          *  The Hardware parameters for each card
119          */
120     
121     struct aty_cmap_regs {
122         u8 windex;
123         u8 lut;
124         u8 mask;
125         u8 rindex;
126         u8 cntl;
127     };
128     
129     struct pci_mmap_map {
130         unsigned long voff;
131         unsigned long poff;
132         unsigned long size;
133         unsigned long prot_flag;
134         unsigned long prot_mask;
135     };
136     
137     
138         /*
139          *  Frame buffer device API
140          */
141     
142     static int atyfb_open(struct fb_info *info, int user);
143     static int atyfb_release(struct fb_info *info, int user);
144     static int atyfb_get_fix(struct fb_fix_screeninfo *fix, int con,
145     			 struct fb_info *fb);
146     static int atyfb_get_var(struct fb_var_screeninfo *var, int con,
147     			 struct fb_info *fb);
148     static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
149     			 struct fb_info *fb);
150     static int atyfb_pan_display(struct fb_var_screeninfo *var, int con,
151     			     struct fb_info *fb);
152     static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
153     			  struct fb_info *info);
154     static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
155     			  struct fb_info *info);
156     static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
157     		       u_long arg, int con, struct fb_info *info);
158     #ifdef __sparc__
159     static int atyfb_mmap(struct fb_info *info, struct file *file,
160     		      struct vm_area_struct *vma);
161     #endif
162     static int atyfb_rasterimg(struct fb_info *info, int start);
163     
164     
165         /*
166          *  Interface to the low level console driver
167          */
168     
169     static int atyfbcon_switch(int con, struct fb_info *fb);
170     static int atyfbcon_updatevar(int con, struct fb_info *fb);
171     static void atyfbcon_blank(int blank, struct fb_info *fb);
172     
173     
174         /*
175          *  Internal routines
176          */
177     
178     static int aty_init(struct fb_info_aty *info, const char *name);
179     #ifdef CONFIG_ATARI
180     static int store_video_par(char *videopar, unsigned char m64_num);
181     static char *strtoke(char *s, const char *ct);
182     #endif
183     
184     static void aty_set_crtc(const struct fb_info_aty *info,
185     			 const struct crtc *crtc);
186     static int aty_var_to_crtc(const struct fb_info_aty *info,
187     			   const struct fb_var_screeninfo *var,
188     			   struct crtc *crtc);
189     static int aty_crtc_to_var(const struct crtc *crtc,
190     			   struct fb_var_screeninfo *var);
191     
192     static void atyfb_set_par(const struct atyfb_par *par,
193     			  struct fb_info_aty *info);
194     static int atyfb_decode_var(const struct fb_var_screeninfo *var,
195     			    struct atyfb_par *par,
196     			    const struct fb_info_aty *info);
197     static int atyfb_encode_var(struct fb_var_screeninfo *var,
198     			    const struct atyfb_par *par,
199     			    const struct fb_info_aty *info);
200     static void set_off_pitch(struct atyfb_par *par,
201     			  const struct fb_info_aty *info);
202     static int encode_fix(struct fb_fix_screeninfo *fix,
203     		      const struct atyfb_par *par,
204     		      const struct fb_info_aty *info);
205     static void atyfb_set_dispsw(struct display *disp, struct fb_info_aty *info,
206     			     int bpp, int accel);
207     static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
208     			 u_int *transp, struct fb_info *fb);
209     static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
210     			 u_int transp, struct fb_info *fb);
211     static void do_install_cmap(int con, struct fb_info *info);
212     #ifdef CONFIG_PPC
213     static int read_aty_sense(const struct fb_info_aty *info);
214     #endif
215     
216     
217         /*
218          *  Interface used by the world
219          */
220     
221     int atyfb_init(void);
222     #ifndef MODULE
223     int atyfb_setup(char*);
224     #endif
225     
226     static int currcon = 0;
227     
228     static struct fb_ops atyfb_ops = {
229     	owner:		THIS_MODULE,
230     	fb_open:	atyfb_open,
231     	fb_release:	atyfb_release,
232     	fb_get_fix:	atyfb_get_fix,
233     	fb_get_var:	atyfb_get_var,
234     	fb_set_var:	atyfb_set_var,
235     	fb_get_cmap:	atyfb_get_cmap,
236     	fb_set_cmap:	atyfb_set_cmap,
237     	fb_pan_display:	atyfb_pan_display,
238     	fb_ioctl:	atyfb_ioctl,
239     #ifdef __sparc__
240     	fb_mmap:	atyfb_mmap,
241     #endif
242     	fb_rasterimg:	atyfb_rasterimg,
243     };
244     
245     static char atyfb_name[16] = "ATY Mach64";
246     static char fontname[40] __initdata = { 0 };
247     static char curblink __initdata = 1;
248     static char noaccel __initdata = 0;
249     static u32 default_vram __initdata = 0;
250     static int default_pll __initdata = 0;
251     static int default_mclk __initdata = 0;
252     
253     #ifndef MODULE
254     static const char *mode_option __initdata = NULL;
255     #endif
256     
257     #ifdef CONFIG_PPC
258     #ifdef CONFIG_NVRAM_NOT_DEFINED
259     static int default_vmode __initdata = VMODE_NVRAM;
260     static int default_cmode __initdata = CMODE_NVRAM;
261     #else
262     static int default_vmode __initdata = VMODE_CHOOSE;
263     static int default_cmode __initdata = CMODE_CHOOSE;
264     #endif
265     #endif
266     
267     #ifdef CONFIG_ATARI
268     static unsigned int mach64_count __initdata = 0;
269     static unsigned long phys_vmembase[FB_MAX] __initdata = { 0, };
270     static unsigned long phys_size[FB_MAX] __initdata = { 0, };
271     static unsigned long phys_guiregbase[FB_MAX] __initdata = { 0, };
272     #endif
273     
274     static const char m64n_gx[] __initdata = "mach64GX (ATI888GX00)";
275     static const char m64n_cx[] __initdata = "mach64CX (ATI888CX00)";
276     static const char m64n_ct[] __initdata = "mach64CT (ATI264CT)";
277     static const char m64n_et[] __initdata = "mach64ET (ATI264ET)";
278     static const char m64n_vta3[] __initdata = "mach64VTA3 (ATI264VT)";
279     static const char m64n_vta4[] __initdata = "mach64VTA4 (ATI264VT)";
280     static const char m64n_vtb[] __initdata = "mach64VTB (ATI264VTB)";
281     static const char m64n_vt4[] __initdata = "mach64VT4 (ATI264VT4)";
282     static const char m64n_gt[] __initdata = "3D RAGE (GT)";
283     static const char m64n_gtb[] __initdata = "3D RAGE II+ (GTB)";
284     static const char m64n_iic_p[] __initdata = "3D RAGE IIC (PCI)";
285     static const char m64n_iic_a[] __initdata = "3D RAGE IIC (AGP)";
286     static const char m64n_lt[] __initdata = "3D RAGE LT";
287     static const char m64n_ltg[] __initdata = "3D RAGE LT-G";
288     static const char m64n_gtc_ba[] __initdata = "3D RAGE PRO (BGA, AGP)";
289     static const char m64n_gtc_ba1[] __initdata = "3D RAGE PRO (BGA, AGP, 1x only)";
290     static const char m64n_gtc_bp[] __initdata = "3D RAGE PRO (BGA, PCI)";
291     static const char m64n_gtc_pp[] __initdata = "3D RAGE PRO (PQFP, PCI)";
292     static const char m64n_gtc_ppl[] __initdata = "3D RAGE PRO (PQFP, PCI, limited 3D)";
293     static const char m64n_xl[] __initdata = "3D RAGE (XL)";
294     static const char m64n_ltp_a[] __initdata = "3D RAGE LT PRO (AGP)";
295     static const char m64n_ltp_p[] __initdata = "3D RAGE LT PRO (PCI)";
296     static const char m64n_mob_p[] __initdata = "3D RAGE Mobility (PCI)";
297     static const char m64n_mob_a[] __initdata = "3D RAGE Mobility (AGP)";
298     
299     
300     static const struct {
301         u16 pci_id, chip_type;
302         u8 rev_mask, rev_val;
303         const char *name;
304         int pll, mclk;
305         u32 features;
306     } aty_chips[] __initdata = {
307     #ifdef CONFIG_FB_ATY_GX
308         /* Mach64 GX */
309         { 0x4758, 0x00d7, 0x00, 0x00, m64n_gx,      135,  50, M64F_GX },
310         { 0x4358, 0x0057, 0x00, 0x00, m64n_cx,      135,  50, M64F_GX },
311     #endif /* CONFIG_FB_ATY_GX */
312     
313     #ifdef CONFIG_FB_ATY_CT
314         /* Mach64 CT */
315         { 0x4354, 0x4354, 0x00, 0x00, m64n_ct,      135,  60, M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO },
316         { 0x4554, 0x4554, 0x00, 0x00, m64n_et,      135,  60, M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO },
317     
318         /* Mach64 VT */
319         { 0x5654, 0x5654, 0xc7, 0x00, m64n_vta3,    170,  67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO | M64F_FIFO_24 },
320         { 0x5654, 0x5654, 0xc7, 0x40, m64n_vta4,    200,  67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO | M64F_FIFO_24 | M64F_MAGIC_POSTDIV },
321         { 0x5654, 0x5654, 0x00, 0x00, m64n_vtb,     200,  67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_FIFO_24 },
322         { 0x5655, 0x5655, 0x00, 0x00, m64n_vtb,     200,  67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL },
323         { 0x5656, 0x5656, 0x00, 0x00, m64n_vt4,     230,  83, M64F_VT | M64F_INTEGRATED | M64F_GTB_DSP },
324     
325         /* Mach64 GT (3D RAGE) */
326         { 0x4754, 0x4754, 0x07, 0x00, m64n_gt,      135,  63, M64F_GT | M64F_INTEGRATED | M64F_MAGIC_FIFO | M64F_FIFO_24 | M64F_EXTRA_BRIGHT },
327         { 0x4754, 0x4754, 0x07, 0x01, m64n_gt,      170,  67, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
328         { 0x4754, 0x4754, 0x07, 0x02, m64n_gt,      200,  67, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
329         { 0x4755, 0x4755, 0x00, 0x00, m64n_gtb,     200,  67, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
330         { 0x4756, 0x4756, 0x00, 0x00, m64n_iic_p,   230,  83, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
331         { 0x4757, 0x4757, 0x00, 0x00, m64n_iic_a,   230,  83, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
332         { 0x475a, 0x475a, 0x00, 0x00, m64n_iic_a,   230,  83, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
333     
334         /* Mach64 LT */
335         { 0x4c54, 0x4c54, 0x00, 0x00, m64n_lt,      135,  63, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP },
336         { 0x4c47, 0x4c47, 0x00, 0x00, m64n_ltg,     230,  63, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_LT_SLEEP | M64F_G3_PB_1024x768 },
337     
338         /* Mach64 GTC (3D RAGE PRO) */
339         { 0x4742, 0x4742, 0x00, 0x00, m64n_gtc_ba,  230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
340         { 0x4744, 0x4744, 0x00, 0x00, m64n_gtc_ba1, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
341         { 0x4749, 0x4749, 0x00, 0x00, m64n_gtc_bp,  230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_MAGIC_VRAM_SIZE },
342         { 0x4750, 0x4750, 0x00, 0x00, m64n_gtc_pp,  230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
343         { 0x4751, 0x4751, 0x00, 0x00, m64n_gtc_ppl, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
344     
345         /* 3D RAGE XL */
346         { 0x4752, 0x4752, 0x00, 0x00, m64n_xl, 230, 120, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_XL_DLL },
347     
348         /* Mach64 LT PRO */
349         { 0x4c42, 0x4c42, 0x00, 0x00, m64n_ltp_a,   230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP },
350         { 0x4c44, 0x4c44, 0x00, 0x00, m64n_ltp_p,   230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP },
351         { 0x4c49, 0x4c49, 0x00, 0x00, m64n_ltp_p,   230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_EXTRA_BRIGHT | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 },
352         { 0x4c50, 0x4c50, 0x00, 0x00, m64n_ltp_p,   230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP },
353     
354         /* 3D RAGE Mobility */
355         { 0x4c4d, 0x4c4d, 0x00, 0x00, m64n_mob_p,   230,  50, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_MOBIL_BUS },
356         { 0x4c4e, 0x4c4e, 0x00, 0x00, m64n_mob_a,   230,  50, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_MOBIL_BUS },
357     #endif /* CONFIG_FB_ATY_CT */
358     };
359     
360     static const char ram_dram[] __initdata = "DRAM";
361     static const char ram_vram[] __initdata = "VRAM";
362     static const char ram_edo[] __initdata = "EDO";
363     static const char ram_sdram[] __initdata = "SDRAM";
364     static const char ram_sgram[] __initdata = "SGRAM";
365     static const char ram_wram[] __initdata = "WRAM";
366     static const char ram_off[] __initdata = "OFF";
367     static const char ram_resv[] __initdata = "RESV";
368     
369     #ifdef CONFIG_FB_ATY_GX
370     static const char *aty_gx_ram[8] __initdata = {
371         ram_dram, ram_vram, ram_vram, ram_dram,
372         ram_dram, ram_vram, ram_vram, ram_resv
373     };
374     #endif /* CONFIG_FB_ATY_GX */
375     
376     #ifdef CONFIG_FB_ATY_CT
377     static const char *aty_ct_ram[8] __initdata = {
378         ram_off, ram_dram, ram_edo, ram_edo,
379         ram_sdram, ram_sgram, ram_wram, ram_resv
380     };
381     #endif /* CONFIG_FB_ATY_CT */
382     
383     
384     #if defined(CONFIG_PPC)
385     
386         /*
387          *  Apple monitor sense
388          */
389     
390     static int __init read_aty_sense(const struct fb_info_aty *info)
391     {
392         int sense, i;
393     
394         aty_st_le32(GP_IO, 0x31003100, info);	/* drive outputs high */
395         __delay(200);
396         aty_st_le32(GP_IO, 0, info);		/* turn off outputs */
397         __delay(2000);
398         i = aty_ld_le32(GP_IO, info);		/* get primary sense value */
399         sense = ((i & 0x3000) >> 3) | (i & 0x100);
400     
401         /* drive each sense line low in turn and collect the other 2 */
402         aty_st_le32(GP_IO, 0x20000000, info);	/* drive A low */
403         __delay(2000);
404         i = aty_ld_le32(GP_IO, info);
405         sense |= ((i & 0x1000) >> 7) | ((i & 0x100) >> 4);
406         aty_st_le32(GP_IO, 0x20002000, info);	/* drive A high again */
407         __delay(200);
408     
409         aty_st_le32(GP_IO, 0x10000000, info);	/* drive B low */
410         __delay(2000);
411         i = aty_ld_le32(GP_IO, info);
412         sense |= ((i & 0x2000) >> 10) | ((i & 0x100) >> 6);
413         aty_st_le32(GP_IO, 0x10001000, info);	/* drive B high again */
414         __delay(200);
415     
416         aty_st_le32(GP_IO, 0x01000000, info);	/* drive C low */
417         __delay(2000);
418         sense |= (aty_ld_le32(GP_IO, info) & 0x3000) >> 12;
419         aty_st_le32(GP_IO, 0, info);		/* turn off outputs */
420     
421         return sense;
422     }
423     
424     #endif /* defined(CONFIG_PPC) */
425     
426     #if defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_PMAC_BACKLIGHT)
427     static void aty_st_lcd(int index, u32 val, const struct fb_info_aty *info)
428     {
429         unsigned long temp;
430     
431         /* write addr byte */
432         temp = aty_ld_le32(LCD_INDEX, info);
433         aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, info);
434         /* write the register value */
435         aty_st_le32(LCD_DATA, val, info);
436     }
437     
438     static u32 aty_ld_lcd(int index, const struct fb_info_aty *info)
439     {
440         unsigned long temp;
441     
442         /* write addr byte */
443         temp = aty_ld_le32(LCD_INDEX, info);
444         aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, info);
445         /* read the register value */
446         return aty_ld_le32(LCD_DATA, info);
447     }
448     #endif /* CONFIG_PMAC_PBOOK || CONFIG_PMAC_BACKLIGHT */
449     
450     /* ------------------------------------------------------------------------- */
451     
452         /*
453          *  CRTC programming
454          */
455     
456     static void aty_set_crtc(const struct fb_info_aty *info,
457     			 const struct crtc *crtc)
458     {
459         aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, info);
460         aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, info);
461         aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_tot_disp, info);
462         aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid, info);
463         aty_st_le32(CRTC_VLINE_CRNT_VLINE, 0, info);
464         aty_st_le32(CRTC_OFF_PITCH, crtc->off_pitch, info);
465         aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl, info);
466     }
467     
468     static int aty_var_to_crtc(const struct fb_info_aty *info,
469     			   const struct fb_var_screeninfo *var,
470     			   struct crtc *crtc)
471     {
472         u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
473         u32 left, right, upper, lower, hslen, vslen, sync, vmode;
474         u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
475         u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
476         u32 pix_width, dp_pix_width, dp_chain_mask;
477     
478         /* input */
479         xres = var->xres;
480         yres = var->yres;
481         vxres = var->xres_virtual;
482         vyres = var->yres_virtual;
483         xoffset = var->xoffset;
484         yoffset = var->yoffset;
485         bpp = var->bits_per_pixel;
486         left = var->left_margin;
487         right = var->right_margin;
488         upper = var->upper_margin;
489         lower = var->lower_margin;
490         hslen = var->hsync_len;
491         vslen = var->vsync_len;
492         sync = var->sync;
493         vmode = var->vmode;
494     
495         /* convert (and round up) and validate */
496         xres = (xres+7) & ~7;
497         xoffset = (xoffset+7) & ~7;
498         vxres = (vxres+7) & ~7;
499         if (vxres < xres+xoffset)
500     	vxres = xres+xoffset;
501         h_disp = xres/8-1;
502         if (h_disp > 0xff)
503     	FAIL("h_disp too large");
504         h_sync_strt = h_disp+(right/8);
505         if (h_sync_strt > 0x1ff)
506     	FAIL("h_sync_start too large");
507         h_sync_dly = right & 7;
508         h_sync_wid = (hslen+7)/8;
509         if (h_sync_wid > 0x1f)
510     	FAIL("h_sync_wid too large");
511         h_total = h_sync_strt+h_sync_wid+(h_sync_dly+left+7)/8;
512         if (h_total > 0x1ff)
513     	FAIL("h_total too large");
514         h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
515     
516         if (vyres < yres+yoffset)
517     	vyres = yres+yoffset;
518         v_disp = yres-1;
519         if (v_disp > 0x7ff)
520     	FAIL("v_disp too large");
521         v_sync_strt = v_disp+lower;
522         if (v_sync_strt > 0x7ff)
523     	FAIL("v_sync_strt too large");
524         v_sync_wid = vslen;
525         if (v_sync_wid > 0x1f)
526     	FAIL("v_sync_wid too large");
527         v_total = v_sync_strt+v_sync_wid+upper;
528         if (v_total > 0x7ff)
529     	FAIL("v_total too large");
530         v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
531     
532         c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;
533     
534         if (bpp <= 8) {
535     	bpp = 8;
536     	pix_width = CRTC_PIX_WIDTH_8BPP;
537     	dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB;
538     	dp_chain_mask = 0x8080;
539         } else if (bpp <= 16) {
540     	bpp = 16;
541     	pix_width = CRTC_PIX_WIDTH_15BPP;
542     	dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP |
543     		       BYTE_ORDER_LSB_TO_MSB;
544     	dp_chain_mask = 0x4210;
545         } else if (bpp <= 24 && M64_HAS(INTEGRATED)) {
546     	bpp = 24;
547     	pix_width = CRTC_PIX_WIDTH_24BPP;
548     	dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB;
549     	dp_chain_mask = 0x8080;
550         } else if (bpp <= 32) {
551     	bpp = 32;
552     	pix_width = CRTC_PIX_WIDTH_32BPP;
553     	dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP |
554     		       BYTE_ORDER_LSB_TO_MSB;
555     	dp_chain_mask = 0x8080;
556         } else
557     	FAIL("invalid bpp");
558     
559         if (vxres*vyres*bpp/8 > info->total_vram)
560     	FAIL("not enough video RAM");
561     
562         if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
563     	FAIL("invalid vmode");
564     
565         /* output */
566         crtc->vxres = vxres;
567         crtc->vyres = vyres;
568         crtc->xoffset = xoffset;
569         crtc->yoffset = yoffset;
570         crtc->bpp = bpp;
571         crtc->h_tot_disp = h_total | (h_disp<<16);
572         crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly<<8) |
573     			    ((h_sync_strt & 0x100)<<4) | (h_sync_wid<<16) |
574     			    (h_sync_pol<<21);
575         crtc->v_tot_disp = v_total | (v_disp<<16);
576         crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid<<16) | (v_sync_pol<<21);
577         crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19);
578         crtc->gen_cntl = pix_width | c_sync | CRTC_EXT_DISP_EN | CRTC_ENABLE;
579         if (M64_HAS(MAGIC_FIFO)) {
580     	/* Not VTB/GTB */
581     	/* FIXME: magic FIFO values */
582     	crtc->gen_cntl |= aty_ld_le32(CRTC_GEN_CNTL, info) & 0x000e0000;
583         }
584         crtc->dp_pix_width = dp_pix_width;
585         crtc->dp_chain_mask = dp_chain_mask;
586     
587         return 0;
588     }
589     
590     
591     static int aty_crtc_to_var(const struct crtc *crtc,
592     			   struct fb_var_screeninfo *var)
593     {
594         u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync;
595         u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
596         u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
597         u32 pix_width;
598     
599         /* input */
600         h_total = crtc->h_tot_disp & 0x1ff;
601         h_disp = (crtc->h_tot_disp>>16) & 0xff;
602         h_sync_strt = (crtc->h_sync_strt_wid & 0xff) |
603     		  ((crtc->h_sync_strt_wid>>4) & 0x100);
604         h_sync_dly = (crtc->h_sync_strt_wid>>8) & 0x7;
605         h_sync_wid = (crtc->h_sync_strt_wid>>16) & 0x1f;
606         h_sync_pol = (crtc->h_sync_strt_wid>>21) & 0x1;
607         v_total = crtc->v_tot_disp & 0x7ff;
608         v_disp = (crtc->v_tot_disp>>16) & 0x7ff;
609         v_sync_strt = crtc->v_sync_strt_wid & 0x7ff;
610         v_sync_wid = (crtc->v_sync_strt_wid>>16) & 0x1f;
611         v_sync_pol = (crtc->v_sync_strt_wid>>21) & 0x1;
612         c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
613         pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
614     
615         /* convert */
616         xres = (h_disp+1)*8;
617         yres = v_disp+1;
618         left = (h_total-h_sync_strt-h_sync_wid)*8-h_sync_dly;
619         right = (h_sync_strt-h_disp)*8+h_sync_dly;
620         hslen = h_sync_wid*8;
621         upper = v_total-v_sync_strt-v_sync_wid;
622         lower = v_sync_strt-v_disp;
623         vslen = v_sync_wid;
624         sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) |
625     	   (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
626     	   (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
627     
628         switch (pix_width) {
629     #if 0
630     	case CRTC_PIX_WIDTH_4BPP:
631     	    bpp = 4;
632     	    var->red.offset = 0;
633     	    var->red.length = 8;
634     	    var->green.offset = 0;
635     	    var->green.length = 8;
636     	    var->blue.offset = 0;
637     	    var->blue.length = 8;
638     	    var->transp.offset = 0;
639     	    var->transp.length = 0;
640     	    break;
641     #endif
642     	case CRTC_PIX_WIDTH_8BPP:
643     	    bpp = 8;
644     	    var->red.offset = 0;
645     	    var->red.length = 8;
646     	    var->green.offset = 0;
647     	    var->green.length = 8;
648     	    var->blue.offset = 0;
649     	    var->blue.length = 8;
650     	    var->transp.offset = 0;
651     	    var->transp.length = 0;
652     	    break;
653     	case CRTC_PIX_WIDTH_15BPP:	/* RGB 555 */
654     	    bpp = 16;
655     	    var->red.offset = 10;
656     	    var->red.length = 5;
657     	    var->green.offset = 5;
658     	    var->green.length = 5;
659     	    var->blue.offset = 0;
660     	    var->blue.length = 5;
661     	    var->transp.offset = 0;
662     	    var->transp.length = 0;
663     	    break;
664     #if 0
665     	case CRTC_PIX_WIDTH_16BPP:	/* RGB 565 */
666     	    bpp = 16;
667     	    var->red.offset = 11;
668     	    var->red.length = 5;
669     	    var->green.offset = 5;
670     	    var->green.length = 6;
671     	    var->blue.offset = 0;
672     	    var->blue.length = 5;
673     	    var->transp.offset = 0;
674     	    var->transp.length = 0;
675     	    break;
676     #endif
677     	case CRTC_PIX_WIDTH_24BPP:	/* RGB 888 */
678     	    bpp = 24;
679     	    var->red.offset = 16;
680     	    var->red.length = 8;
681     	    var->green.offset = 8;
682     	    var->green.length = 8;
683     	    var->blue.offset = 0;
684     	    var->blue.length = 8;
685     	    var->transp.offset = 0;
686     	    var->transp.length = 0;
687     	    break;
688     	case CRTC_PIX_WIDTH_32BPP:	/* ARGB 8888 */
689     	    bpp = 32;
690     	    var->red.offset = 16;
691     	    var->red.length = 8;
692     	    var->green.offset = 8;
693     	    var->green.length = 8;
694     	    var->blue.offset = 0;
695     	    var->blue.length = 8;
696     	    var->transp.offset = 24;
697     	    var->transp.length = 8;
698     	    break;
699     	default:
700     	    FAIL("Invalid pixel width");
701         }
702     
703         /* output */
704         var->xres = xres;
705         var->yres = yres;
706         var->xres_virtual = crtc->vxres;
707         var->yres_virtual = crtc->vyres;
708         var->bits_per_pixel = bpp;
709         var->xoffset = crtc->xoffset;
710         var->yoffset = crtc->yoffset;
711         var->left_margin = left;
712         var->right_margin = right;
713         var->upper_margin = upper;
714         var->lower_margin = lower;
715         var->hsync_len = hslen;
716         var->vsync_len = vslen;
717         var->sync = sync;
718         var->vmode = FB_VMODE_NONINTERLACED;
719     
720         return 0;
721     }
722     
723     /* ------------------------------------------------------------------------- */
724     
725     static void atyfb_set_par(const struct atyfb_par *par,
726     			  struct fb_info_aty *info)
727     {
728         u32 i;
729         int accelmode;
730         u8 tmp;
731     
732         accelmode = par->accel_flags;  /* hack */
733     
734         info->current_par = *par;
735     
736         if (info->blitter_may_be_busy)
737     	wait_for_idle(info);
738         tmp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
739         aty_set_crtc(info, &par->crtc);
740         aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info);
741     					/* better call aty_StrobeClock ?? */
742         aty_st_8(CLOCK_CNTL + info->clk_wr_offset, CLOCK_STROBE, info);
743     
744         info->dac_ops->set_dac(info, &par->pll, par->crtc.bpp, accelmode);
745         info->pll_ops->set_pll(info, &par->pll);
746     
747         if (!M64_HAS(INTEGRATED)) {
748     	/* Don't forget MEM_CNTL */
749     	i = aty_ld_le32(MEM_CNTL, info) & 0xf0ffffff;
750     	switch (par->crtc.bpp) {
751     	    case 8:
752     		i |= 0x02000000;
753     		break;
754     	    case 16:
755     		i |= 0x03000000;
756     		break;
757     	    case 32:
758     		i |= 0x06000000;
759     		break;
760     	}
761     	aty_st_le32(MEM_CNTL, i, info);
762         } else {
763     	i = aty_ld_le32(MEM_CNTL, info) & 0xf00fffff;
764     	if (!M64_HAS(MAGIC_POSTDIV))
765     	    i |= info->mem_refresh_rate << 20;
766     	switch (par->crtc.bpp) {
767     	    case 8:
768     	    case 24:
769     		i |= 0x00000000;
770     		break;
771     	    case 16:
772     		i |= 0x04000000;
773     		break;
774     	    case 32:
775     		i |= 0x08000000;
776     		break;
777     	}
778     	if (M64_HAS(CT_BUS)) {
779     	    aty_st_le32(DAC_CNTL, 0x87010184, info);
780     	    aty_st_le32(BUS_CNTL, 0x680000f9, info);
781     	} else if (M64_HAS(VT_BUS)) {
782     	    aty_st_le32(DAC_CNTL, 0x87010184, info);
783     	    aty_st_le32(BUS_CNTL, 0x680000f9, info);
784     	}  else if (M64_HAS(MOBIL_BUS)) {
785     	    aty_st_le32(DAC_CNTL, 0x80010102, info);
786     	    aty_st_le32(BUS_CNTL, 0x7b33a040, info);
787     	} else {
788     	    /* GT */
789     	    aty_st_le32(DAC_CNTL, 0x86010102, info);
790     	    aty_st_le32(BUS_CNTL, 0x7b23a040, info);
791     	    aty_st_le32(EXT_MEM_CNTL,
792     			aty_ld_le32(EXT_MEM_CNTL, info) | 0x5000001, info);
793     	}
794     	aty_st_le32(MEM_CNTL, i, info);
795         }
796         aty_st_8(DAC_MASK, 0xff, info);
797     
798         /* Initialize the graphics engine */
799         if (par->accel_flags & FB_ACCELF_TEXT)
800     	aty_init_engine(par, info);
801     
802     #ifdef CONFIG_FB_COMPAT_XPMAC
803         if (!console_fb_info || console_fb_info == &info->fb_info) {
804     	struct fb_var_screeninfo var;
805     	int vmode, cmode;
806     	display_info.height = ((par->crtc.v_tot_disp>>16) & 0x7ff)+1;
807     	display_info.width = (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8;
808     	display_info.depth = par->crtc.bpp;
809     	display_info.pitch = par->crtc.vxres*par->crtc.bpp/8;
810     	atyfb_encode_var(&var, par, info);
811     	if (mac_var_to_vmode(&var, &vmode, &cmode))
812     	    display_info.mode = 0;
813     	else
814     	    display_info.mode = vmode;
815     	strcpy(display_info.name, atyfb_name);
816     	display_info.fb_address = info->frame_buffer_phys;
817     	display_info.cmap_adr_address = info->ati_regbase_phys+0xc0;
818     	display_info.cmap_data_address = info->ati_regbase_phys+0xc1;
819     	display_info.disp_reg_address = info->ati_regbase_phys;
820         }
821     #endif /* CONFIG_FB_COMPAT_XPMAC */
822     }
823     
824     static int atyfb_decode_var(const struct fb_var_screeninfo *var,
825     			    struct atyfb_par *par,
826     			    const struct fb_info_aty *info)
827     {
828         int err;
829     
830         if ((err = aty_var_to_crtc(info, var, &par->crtc)) ||
831     	(err = info->pll_ops->var_to_pll(info, var->pixclock, par->crtc.bpp,
832     		    			 &par->pll)))
833     	return err;
834     
835         if (var->accel_flags & FB_ACCELF_TEXT)
836     	par->accel_flags = FB_ACCELF_TEXT;
837         else
838     	par->accel_flags = 0;
839     
840     #if 0 /* fbmon is not done. uncomment for 2.5.x -brad */
841         if (!fbmon_valid_timings(var->pixclock, htotal, vtotal, info))
842     	return -EINVAL;
843     #endif
844     
845         return 0;
846     }
847     
848     static int atyfb_encode_var(struct fb_var_screeninfo *var,
849     			    const struct atyfb_par *par,
850     			    const struct fb_info_aty *info)
851     {
852         int err;
853     
854         memset(var, 0, sizeof(struct fb_var_screeninfo));
855     
856         if ((err = aty_crtc_to_var(&par->crtc, var)))
857     	return err;
858         var->pixclock = info->pll_ops->pll_to_var(info, &par->pll);
859     
860         var->height = -1;
861         var->width = -1;
862         var->accel_flags = par->accel_flags;
863     
864         return 0;
865     }
866     
867     
868     
869     static void set_off_pitch(struct atyfb_par *par,
870     			  const struct fb_info_aty *info)
871     {
872         u32 xoffset = par->crtc.xoffset;
873         u32 yoffset = par->crtc.yoffset;
874         u32 vxres = par->crtc.vxres;
875         u32 bpp = par->crtc.bpp;
876     
877         par->crtc.off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19);
878         aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, info);
879     }
880     
881     
882         /*
883          *  Open/Release the frame buffer device
884          */
885     
886     static int atyfb_open(struct fb_info *info, int user)
887     
888     {
889     #ifdef __sparc__
890         struct fb_info_aty *fb = (struct fb_info_aty *)info;
891     
892         if (user) {
893     	fb->open++;
894     	fb->mmaped = 0;
895     	fb->vtconsole = -1;
896         } else {
897     	fb->consolecnt++;
898         }
899     #endif
900         return(0);
901     }
902     
903     struct fb_var_screeninfo default_var = {
904         /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
905         640, 480, 640, 480, 0, 0, 8, 0,
906         {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
907         0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
908         0, FB_VMODE_NONINTERLACED
909     };
910     
911     static int atyfb_release(struct fb_info *info, int user)
912     {
913     #ifdef __sparc__
914         struct fb_info_aty *fb = (struct fb_info_aty *)info;
915     
916         if (user) {
917     	fb->open--;
918     	mdelay(1);
919     	wait_for_idle(fb);
920     	if (!fb->open) {
921     		int was_mmaped = fb->mmaped;
922     
923     		fb->mmaped = 0;
924     		if (fb->vtconsole != -1)
925     			vt_cons[fb->vtconsole]->vc_mode = KD_TEXT;
926     		fb->vtconsole = -1;
927     
928     		if (was_mmaped) {
929     			struct fb_var_screeninfo var;
930     
931     			/* Now reset the default display config, we have no
932     			 * idea what the program(s) which mmap'd the chip did
933     			 * to the configuration, nor whether it restored it
934     			 * correctly.
935     			 */
936     			var = default_var;
937     			if (noaccel)
938     				var.accel_flags &= ~FB_ACCELF_TEXT;
939     			else
940     				var.accel_flags |= FB_ACCELF_TEXT;
941     			if (var.yres == var.yres_virtual) {
942     				u32 vram = (fb->total_vram - (PAGE_SIZE << 2));
943     				var.yres_virtual = ((vram * 8) / var.bits_per_pixel) /
944     					var.xres_virtual;
945     				if (var.yres_virtual < var.yres)
946     					var.yres_virtual = var.yres;
947     			}
948     			atyfb_set_var(&var, -1, &fb->fb_info);
949     		}
950     	}
951         } else {
952     	fb->consolecnt--;
953         }
954     #endif
955         return(0);
956     }
957     
958     
959     static int encode_fix(struct fb_fix_screeninfo *fix,
960     		      const struct atyfb_par *par,
961     		      const struct fb_info_aty *info)
962     {
963         memset(fix, 0, sizeof(struct fb_fix_screeninfo));
964     
965         strcpy(fix->id, atyfb_name);
966         fix->smem_start = info->frame_buffer_phys;
967         fix->smem_len = (u32)info->total_vram;
968     
969         /*
970          *  Reg Block 0 (CT-compatible block) is at ati_regbase_phys
971          *  Reg Block 1 (multimedia extensions) is at ati_regbase_phys-0x400
972          */
973         if (M64_HAS(GX)) {
974     	fix->mmio_start = info->ati_regbase_phys;
975     	fix->mmio_len = 0x400;
976     	fix->accel = FB_ACCEL_ATI_MACH64GX;
977         } else if (M64_HAS(CT)) {
978     	fix->mmio_start = info->ati_regbase_phys;
979     	fix->mmio_len = 0x400;
980     	fix->accel = FB_ACCEL_ATI_MACH64CT;
981         } else if (M64_HAS(VT)) {
982     	fix->mmio_start = info->ati_regbase_phys-0x400;
983     	fix->mmio_len = 0x800;
984     	fix->accel = FB_ACCEL_ATI_MACH64VT;
985         } else /* if (M64_HAS(GT)) */ {
986     	fix->mmio_start = info->ati_regbase_phys-0x400;
987     	fix->mmio_len = 0x800;
988     	fix->accel = FB_ACCEL_ATI_MACH64GT;
989         }
990         fix->type = FB_TYPE_PACKED_PIXELS;
991         fix->type_aux = 0;
992         fix->line_length = par->crtc.vxres*par->crtc.bpp/8;
993         fix->visual = par->crtc.bpp <= 8 ? FB_VISUAL_PSEUDOCOLOR
994     				     : FB_VISUAL_DIRECTCOLOR;
995         fix->ywrapstep = 0;
996         fix->xpanstep = 8;
997         fix->ypanstep = 1;
998     
999         return 0;
1000     }
1001     
1002     
1003         /*
1004          *  Get the Fixed Part of the Display
1005          */
1006     
1007     static int atyfb_get_fix(struct fb_fix_screeninfo *fix, int con,
1008     			 struct fb_info *fb)
1009     {
1010         const struct fb_info_aty *info = (struct fb_info_aty *)fb;
1011         struct atyfb_par par;
1012     
1013         if (con == -1)
1014     	par = info->default_par;
1015         else
1016     	atyfb_decode_var(&fb_display[con].var, &par, info);
1017         encode_fix(fix, &par, info);
1018         return 0;
1019     }
1020     
1021     
1022         /*
1023          *  Get the User Defined Part of the Display
1024          */
1025     
1026     static int atyfb_get_var(struct fb_var_screeninfo *var, int con,
1027     			 struct fb_info *fb)
1028     {
1029         const struct fb_info_aty *info = (struct fb_info_aty *)fb;
1030     
1031         if (con == -1)
1032     	atyfb_encode_var(var, &info->default_par, info);
1033         else
1034     	*var = fb_display[con].var;
1035         return 0;
1036     }
1037     
1038     
1039     static void atyfb_set_dispsw(struct display *disp, struct fb_info_aty *info,
1040     			     int bpp, int accel)
1041     {
1042     	    switch (bpp) {
1043     #ifdef FBCON_HAS_CFB8
1044     		case 8:
1045     		    info->dispsw = accel ? fbcon_aty8 : fbcon_cfb8;
1046     		    disp->dispsw = &info->dispsw;
1047     		    break;
1048     #endif
1049     #ifdef FBCON_HAS_CFB16
1050     		case 16:
1051     		    info->dispsw = accel ? fbcon_aty16 : fbcon_cfb16;
1052     		    disp->dispsw = &info->dispsw;
1053     		    disp->dispsw_data = info->fbcon_cmap.cfb16;
1054     		    break;
1055     #endif
1056     #ifdef FBCON_HAS_CFB24
1057     		case 24:
1058     		    info->dispsw = accel ? fbcon_aty24 : fbcon_cfb24;
1059     		    disp->dispsw = &info->dispsw;
1060     		    disp->dispsw_data = info->fbcon_cmap.cfb24;
1061     		    break;
1062     #endif
1063     #ifdef FBCON_HAS_CFB32
1064     		case 32:
1065     		    info->dispsw = accel ? fbcon_aty32 : fbcon_cfb32;
1066     		    disp->dispsw = &info->dispsw;
1067     		    disp->dispsw_data = info->fbcon_cmap.cfb32;
1068     		    break;
1069     #endif
1070     		default:
1071     		    disp->dispsw = &fbcon_dummy;
1072     	    }
1073     #ifdef CONFIG_FB_ATY_CT
1074     	    if (info->cursor) {
1075     		info->dispsw.cursor = atyfb_cursor;
1076     		info->dispsw.set_font = atyfb_set_font;
1077     	    }
1078     #endif /* CONFIG_FB_ATY_CT */
1079     }
1080     
1081     
1082         /*
1083          *  Set the User Defined Part of the Display
1084          */
1085     
1086     static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
1087     			 struct fb_info *fb)
1088     {
1089         struct fb_info_aty *info = (struct fb_info_aty *)fb;
1090         struct atyfb_par par;
1091         struct display *display;
1092         int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel, accel, err;
1093         int activate = var->activate;
1094     
1095         if (con >= 0)
1096     	display = &fb_display[con];
1097         else
1098     	display = fb->disp;	/* used during initialization */
1099     
1100         if ((err = atyfb_decode_var(var, &par, info)))
1101     	return err;
1102     
1103         atyfb_encode_var(var, &par, (struct fb_info_aty *)info);
1104     
1105         if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
1106     	oldxres = display->var.xres;
1107     	oldyres = display->var.yres;
1108     	oldvxres = display->var.xres_virtual;
1109     	oldvyres = display->var.yres_virtual;
1110     	oldbpp = display->var.bits_per_pixel;
1111     	oldaccel = display->var.accel_flags;
1112     	display->var = *var;
1113     	accel = var->accel_flags & FB_ACCELF_TEXT;
1114     	if (oldxres != var->xres || oldyres != var->yres ||
1115     	    oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
1116     	    oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) {
1117     	    struct fb_fix_screeninfo fix;
1118     
1119     	    encode_fix(&fix, &par, info);
1120     	    display->screen_base = (char *)info->frame_buffer;
1121     	    display->visual = fix.visual;
1122     	    display->type = fix.type;
1123     	    display->type_aux = fix.type_aux;
1124     	    display->ypanstep = fix.ypanstep;
1125     	    display->ywrapstep = fix.ywrapstep;
1126     	    display->line_length = fix.line_length;
1127     	    display->can_soft_blank = 1;
1128     	    display->inverse = 0;
1129     	    if (accel)
1130     	    	display->scrollmode = (info->bus_type == PCI) ? SCROLL_YNOMOVE : 0;
1131     	    else
1132     	    	display->scrollmode = SCROLL_YREDRAW;
1133     	    if (info->fb_info.changevar)
1134     		(*info->fb_info.changevar)(con);
1135     	}
1136     	if (!info->fb_info.display_fg ||
1137     	    info->fb_info.display_fg->vc_num == con) {
1138     	    atyfb_set_par(&par, info);
1139     	    atyfb_set_dispsw(display, info, par.crtc.bpp, accel);
1140     	}
1141     	if (oldbpp != var->bits_per_pixel) {
1142     	    if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
1143     		return err;
1144     	    do_install_cmap(con, &info->fb_info);
1145     	}
1146         }
1147     
1148         return 0;
1149     }
1150     
1151     
1152         /*
1153          *  Pan or Wrap the Display
1154          *
1155          *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
1156          */
1157     
1158     static int atyfb_pan_display(struct fb_var_screeninfo *var, int con,
1159     			     struct fb_info *fb)
1160     {
1161         struct fb_info_aty *info = (struct fb_info_aty *)fb;
1162         u32 xres, yres, xoffset, yoffset;
1163         struct atyfb_par *par = &info->current_par;
1164     
1165         xres = (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8;
1166         yres = ((par->crtc.v_tot_disp>>16) & 0x7ff)+1;
1167         xoffset = (var->xoffset+7) & ~7;
1168         yoffset = var->yoffset;
1169         if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres)
1170     	return -EINVAL;
1171         par->crtc.xoffset = xoffset;
1172         par->crtc.yoffset = yoffset;
1173         set_off_pitch(par, info);
1174         return 0;
1175     }
1176     
1177         /*
1178          *  Get the Colormap
1179          */
1180     
1181     static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
1182     			  struct fb_info *info)
1183     {
1184         if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */
1185     	return fb_get_cmap(cmap, kspc, atyfb_getcolreg, info);
1186         else if (fb_display[con].cmap.len) /* non default colormap? */
1187     	fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
1188         else {
1189     	int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
1190     	fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
1191         }
1192         return 0;
1193     }
1194     
1195         /*
1196          *  Set the Colormap
1197          */
1198     
1199     static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
1200     			  struct fb_info *info)
1201     {
1202         int err;
1203         struct display *disp;
1204     
1205         if (con >= 0)
1206         	disp = &fb_display[con];
1207         else
1208             disp = info->disp;
1209         if (!disp->cmap.len) {	/* no colormap allocated? */
1210     	int size = disp->var.bits_per_pixel == 16 ? 32 : 256;
1211     	if ((err = fb_alloc_cmap(&disp->cmap, size, 0)))
1212     	    return err;
1213         }
1214         if (!info->display_fg || con == info->display_fg->vc_num)			/* current console? */
1215     	return fb_set_cmap(cmap, kspc, atyfb_setcolreg, info);
1216         else
1217     	fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
1218         return 0;
1219     }
1220     
1221     
1222     #ifdef DEBUG
1223     #define ATYIO_CLKR		0x41545900	/* ATY\00 */
1224     #define ATYIO_CLKW		0x41545901	/* ATY\01 */
1225     
1226     struct atyclk {
1227         u32 ref_clk_per;
1228         u8 pll_ref_div;
1229         u8 mclk_fb_div;
1230         u8 mclk_post_div;		/* 1,2,3,4,8 */
1231         u8 vclk_fb_div;
1232         u8 vclk_post_div;		/* 1,2,3,4,6,8,12 */
1233         u32 dsp_xclks_per_row;	/* 0-16383 */
1234         u32 dsp_loop_latency;	/* 0-15 */
1235         u32 dsp_precision;		/* 0-7 */
1236         u32 dsp_on;			/* 0-2047 */
1237         u32 dsp_off;		/* 0-2047 */
1238     };
1239     
1240     #define ATYIO_FEATR		0x41545902	/* ATY\02 */
1241     #define ATYIO_FEATW		0x41545903	/* ATY\03 */
1242     #endif
1243     
1244     static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
1245     		       u_long arg, int con, struct fb_info *info2)
1246     {
1247     #if defined(__sparc__) || (defined(DEBUG) && defined(CONFIG_FB_ATY_CT))
1248         struct fb_info_aty *info = (struct fb_info_aty *)info2;
1249     #endif /* __sparc__ || DEBUG */
1250     #ifdef __sparc__
1251         struct fbtype fbtyp;
1252         struct display *disp;
1253     
1254         if (con >= 0)
1255         	disp = &fb_display[con];
1256         else
1257             disp = info2->disp;
1258     #endif
1259     
1260         switch (cmd) {
1261     #ifdef __sparc__
1262         case FBIOGTYPE:
1263     	fbtyp.fb_type = FBTYPE_PCI_GENERIC;
1264     	fbtyp.fb_width = info->current_par.crtc.vxres;
1265     	fbtyp.fb_height = info->current_par.crtc.vyres;
1266     	fbtyp.fb_depth = info->current_par.crtc.bpp;
1267     	fbtyp.fb_cmsize = disp->cmap.len;
1268     	fbtyp.fb_size = info->total_vram;
1269     	if (copy_to_user((struct fbtype *)arg, &fbtyp, sizeof(fbtyp)))
1270     		return -EFAULT;
1271     	break;
1272     #endif /* __sparc__ */
1273     #if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)
1274         case ATYIO_CLKR:
1275     	if (M64_HAS(INTEGRATED)) {
1276     	    struct atyclk clk;
1277     	    union aty_pll *pll = &info->current_par.pll;
1278     	    u32 dsp_config = pll->ct.dsp_config;
1279     	    u32 dsp_on_off = pll->ct.dsp_on_off;
1280     	    clk.ref_clk_per = info->ref_clk_per;
1281     	    clk.pll_ref_div = pll->ct.pll_ref_div;
1282     	    clk.mclk_fb_div = pll->ct.mclk_fb_div;
1283     	    clk.mclk_post_div = pll->ct.mclk_post_div_real;
1284     	    clk.vclk_fb_div = pll->ct.vclk_fb_div;
1285     	    clk.vclk_post_div = pll->ct.vclk_post_div_real;
1286     	    clk.dsp_xclks_per_row = dsp_config & 0x3fff;
1287     	    clk.dsp_loop_latency = (dsp_config>>16) & 0xf;
1288     	    clk.dsp_precision = (dsp_config>>20) & 7;
1289     	    clk.dsp_on = dsp_on_off & 0x7ff;
1290     	    clk.dsp_off = (dsp_on_off>>16) & 0x7ff;
1291     	    if (copy_to_user((struct atyclk *)arg, &clk, sizeof(clk)))
1292     		    return -EFAULT;
1293     	} else
1294     	    return -EINVAL;
1295     	break;
1296         case ATYIO_CLKW:
1297     	if (M64_HAS(INTEGRATED)) {
1298     	    struct atyclk clk;
1299     	    union aty_pll *pll = &info->current_par.pll;
1300     	    if (copy_from_user(&clk, (struct atyclk *)arg, sizeof(clk)))
1301     		    return -EFAULT;
1302     	    info->ref_clk_per = clk.ref_clk_per;
1303     	    pll->ct.pll_ref_div = clk.pll_ref_div;
1304     	    pll->ct.mclk_fb_div = clk.mclk_fb_div;
1305     	    pll->ct.mclk_post_div_real = clk.mclk_post_div;
1306     	    pll->ct.vclk_fb_div = clk.vclk_fb_div;
1307     	    pll->ct.vclk_post_div_real = clk.vclk_post_div;
1308     	    pll->ct.dsp_config = (clk.dsp_xclks_per_row & 0x3fff) |
1309     				 ((clk.dsp_loop_latency & 0xf)<<16) |
1310     				 ((clk.dsp_precision & 7)<<20);
1311     	    pll->ct.dsp_on_off = (clk.dsp_on & 0x7ff) |
1312     				 ((clk.dsp_off & 0x7ff)<<16);
1313     	    aty_calc_pll_ct(info, &pll->ct);
1314     	    aty_set_pll_ct(info, pll);
1315     	} else
1316     	    return -EINVAL;
1317     	break;
1318         case ATYIO_FEATR:
1319     	if (get_user(info->features, (u32 *)arg))
1320     	    return -EFAULT;
1321     	break;
1322         case ATYIO_FEATW:
1323     	if (put_user(info->features, (u32 *)arg))
1324     	    return -EFAULT;
1325     	break;
1326     #endif /* DEBUG && CONFIG_FB_ATY_CT */
1327         default:
1328     	return -EINVAL;
1329         }
1330         return 0;
1331     }
1332     
1333     static int atyfb_rasterimg(struct fb_info *info, int start)
1334     {
1335         struct fb_info_aty *fb = (struct fb_info_aty *)info;
1336     
1337         if (fb->blitter_may_be_busy)
1338     	wait_for_idle(fb);
1339         return 0;
1340     }
1341     
1342     #ifdef __sparc__
1343     static int atyfb_mmap(struct fb_info *info, struct file *file,
1344     		      struct vm_area_struct *vma)
1345     {
1346     	struct fb_info_aty *fb = (struct fb_info_aty *)info;
1347     	unsigned int size, page, map_size = 0;
1348     	unsigned long map_offset = 0;
1349     	unsigned long off;
1350     	int i;
1351     
1352     	if (!fb->mmap_map)
1353     		return -ENXIO;
1354     
1355     	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
1356     		return -EINVAL;
1357     
1358     	off = vma->vm_pgoff << PAGE_SHIFT;
1359     	size = vma->vm_end - vma->vm_start;
1360     
1361     	/* To stop the swapper from even considering these pages. */
1362     	vma->vm_flags |= (VM_SHM | VM_LOCKED);
1363     
1364     	if (((vma->vm_pgoff == 0) && (size == fb->total_vram)) ||
1365     	    ((off == fb->total_vram) && (size == PAGE_SIZE)))
1366     		off += 0x8000000000000000UL;
1367     
1368     	vma->vm_pgoff = off >> PAGE_SHIFT;	/* propagate off changes */
1369     
1370     	/* Each page, see which map applies */
1371     	for (page = 0; page < size; ) {
1372     		map_size = 0;
1373     		for (i = 0; fb->mmap_map[i].size; i++) {
1374     			unsigned long start = fb->mmap_map[i].voff;
1375     			unsigned long end = start + fb->mmap_map[i].size;
1376     			unsigned long offset = off + page;
1377     
1378     			if (start > offset)
1379     				continue;
1380     			if (offset >= end)
1381     				continue;
1382     
1383     			map_size = fb->mmap_map[i].size - (offset - start);
1384     			map_offset = fb->mmap_map[i].poff + (offset - start);
1385     			break;
1386     		}
1387     		if (!map_size) {
1388     			page += PAGE_SIZE;
1389     			continue;
1390     		}
1391     		if (page + map_size > size)
1392     			map_size = size - page;
1393     
1394     		pgprot_val(vma->vm_page_prot) &= ~(fb->mmap_map[i].prot_mask);
1395     		pgprot_val(vma->vm_page_prot) |= fb->mmap_map[i].prot_flag;
1396     
1397     		if (remap_page_range(vma->vm_start + page, map_offset,
1398     				     map_size, vma->vm_page_prot))
1399     			return -EAGAIN;
1400     
1401     		page += map_size;
1402     	}
1403     
1404     	if (!map_size)
1405     		return -EINVAL;
1406     
1407     	vma->vm_flags |= VM_IO;
1408     
1409     	if (!fb->mmaped) {
1410     		int lastconsole = 0;
1411     
1412     		if (info->display_fg)
1413     			lastconsole = info->display_fg->vc_num;
1414     		fb->mmaped = 1;
1415     		if (fb->consolecnt && fb_display[lastconsole].fb_info == info) {
1416     			fb->vtconsole = lastconsole;
1417     			vt_cons[lastconsole]->vc_mode = KD_GRAPHICS;
1418     		}
1419     	}
1420     	return 0;
1421     }
1422     
1423     static struct {
1424     	u32	yoffset;
1425     	u8	r[2][256];
1426     	u8	g[2][256];
1427     	u8	b[2][256];
1428     } atyfb_save;
1429     
1430     static void atyfb_save_palette(struct fb_info *fb, int enter)
1431     {
1432     	struct fb_info_aty *info = (struct fb_info_aty *)fb;
1433     	int i, tmp;
1434     
1435     	for (i = 0; i < 256; i++) {
1436     		tmp = aty_ld_8(DAC_CNTL, info) & 0xfc;
1437     		if (M64_HAS(EXTRA_BRIGHT))
1438     			tmp |= 0x2;
1439     		aty_st_8(DAC_CNTL, tmp, info);
1440     		aty_st_8(DAC_MASK, 0xff, info);
1441     
1442     		writeb(i, &info->aty_cmap_regs->rindex);
1443     		atyfb_save.r[enter][i] = readb(&info->aty_cmap_regs->lut);
1444     		atyfb_save.g[enter][i] = readb(&info->aty_cmap_regs->lut);
1445     		atyfb_save.b[enter][i] = readb(&info->aty_cmap_regs->lut);
1446     		writeb(i, &info->aty_cmap_regs->windex);
1447     		writeb(atyfb_save.r[1-enter][i], &info->aty_cmap_regs->lut);
1448     		writeb(atyfb_save.g[1-enter][i], &info->aty_cmap_regs->lut);
1449     		writeb(atyfb_save.b[1-enter][i], &info->aty_cmap_regs->lut);
1450     	}
1451     }
1452     
1453     static void atyfb_palette(int enter)
1454     {
1455     	struct fb_info_aty *info;
1456     	struct atyfb_par *par;
1457     	struct display *d;
1458     	int i;
1459     
1460     	for (i = 0; i < MAX_NR_CONSOLES; i++) {
1461     		d = &fb_display[i];
1462     		if (d->fb_info &&
1463     		    d->fb_info->fbops == &atyfb_ops &&
1464     		    d->fb_info->display_fg &&
1465     		    d->fb_info->display_fg->vc_num == i) {
1466     			atyfb_save_palette(d->fb_info, enter);
1467     			info = (struct fb_info_aty *)d->fb_info;
1468     			par = &info->current_par;
1469     			if (enter) {
1470     				atyfb_save.yoffset = par->crtc.yoffset;
1471     				par->crtc.yoffset = 0;
1472     				set_off_pitch(par, info);
1473     			} else {
1474     				par->crtc.yoffset = atyfb_save.yoffset;
1475     				set_off_pitch(par, info);
1476     			}
1477     			break;
1478     		}
1479     	}
1480     }
1481     #endif /* __sparc__ */
1482     
1483     
1484     
1485     #ifdef CONFIG_PMAC_PBOOK
1486     
1487     static struct fb_info_aty* first_display = NULL;
1488     
1489     /* Power management routines. Those are used for PowerBook sleep.
1490      *
1491      * It appears that Rage LT and Rage LT Pro have different power
1492      * management registers. There's is some confusion about which
1493      * chipID is a Rage LT or LT pro :(
1494      */
1495     static int aty_power_mgmt_LT(int sleep, struct fb_info_aty *info)
1496     {
1497      	unsigned int pm;
1498     	int timeout;
1499     	
1500     	pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
1501     	pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;
1502     	aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
1503     	pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
1504     	
1505     	timeout = 200000;
1506     	if (sleep) {
1507     		/* Sleep */
1508     		pm &= ~PWR_MGT_ON;
1509     		aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
1510     		pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
1511     		udelay(10);
1512     		pm &= ~(PWR_BLON | AUTO_PWR_UP);
1513     		pm |= SUSPEND_NOW;
1514     		aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
1515     		pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
1516     		udelay(10);
1517     		pm |= PWR_MGT_ON;
1518     		aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
1519     		do {
1520     			pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
1521     			udelay(10);
1522     			if ((--timeout) == 0)
1523     				break;
1524     		} while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
1525     	} else {
1526     		/* Wakeup */
1527     		pm &= ~PWR_MGT_ON;
1528     		aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
1529     		pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
1530     		udelay(10);
1531     		pm |=  (PWR_BLON | AUTO_PWR_UP);
1532     		pm &= ~SUSPEND_NOW;
1533     		aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
1534     		pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
1535     		udelay(10);
1536     		pm |= PWR_MGT_ON;
1537     		aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
1538     		do {
1539     			pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
1540     			udelay(10);
1541     			if ((--timeout) == 0)
1542     				break;
1543     		} while ((pm & PWR_MGT_STATUS_MASK) != 0);
1544     	}
1545     	mdelay(500);
1546     
1547     	return timeout ? PBOOK_SLEEP_OK : PBOOK_SLEEP_REFUSE;
1548     }
1549     
1550     static int aty_power_mgmt_LTPro(int sleep, struct fb_info_aty *info)
1551     {
1552      	unsigned int pm;
1553     	int timeout;
1554     	
1555     	pm = aty_ld_lcd(POWER_MANAGEMENT, info);
1556     	pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;
1557     	aty_st_lcd(POWER_MANAGEMENT, pm, info);
1558     	pm = aty_ld_lcd(POWER_MANAGEMENT, info);
1559     
1560     	timeout = 200;
1561     	if (sleep) {
1562     		/* Sleep */
1563     		pm &= ~PWR_MGT_ON;
1564     		aty_st_lcd(POWER_MANAGEMENT, pm, info);
1565     		pm = aty_ld_lcd(POWER_MANAGEMENT, info);
1566     		udelay(10);
1567     		pm &= ~(PWR_BLON | AUTO_PWR_UP);
1568     		pm |= SUSPEND_NOW;
1569     		aty_st_lcd(POWER_MANAGEMENT, pm, info);
1570     		pm = aty_ld_lcd(POWER_MANAGEMENT, info);
1571     		udelay(10);
1572     		pm |= PWR_MGT_ON;
1573     		aty_st_lcd(POWER_MANAGEMENT, pm, info);
1574     		do {
1575     			pm = aty_ld_lcd(POWER_MANAGEMENT, info);
1576     			mdelay(1);
1577     			if ((--timeout) == 0)
1578     				break;
1579     		} while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
1580     	} else {
1581     		/* Wakeup */
1582     		pm &= ~PWR_MGT_ON;
1583     		aty_st_lcd(POWER_MANAGEMENT, pm, info);
1584     		pm = aty_ld_lcd(POWER_MANAGEMENT, info);
1585     		udelay(10);
1586     		pm &= ~SUSPEND_NOW;
1587     		pm |= (PWR_BLON | AUTO_PWR_UP);
1588     		aty_st_lcd(POWER_MANAGEMENT, pm, info);
1589     		pm = aty_ld_lcd(POWER_MANAGEMENT, info);
1590     		udelay(10);
1591     		pm |= PWR_MGT_ON;
1592     		aty_st_lcd(POWER_MANAGEMENT, pm, info);
1593     		do {
1594     			pm = aty_ld_lcd(POWER_MANAGEMENT, info);			
1595     			mdelay(1);
1596     			if ((--timeout) == 0)
1597     				break;
1598     		} while ((pm & PWR_MGT_STATUS_MASK) != 0);
1599     	}
1600     
1601     	return timeout ? PBOOK_SLEEP_OK : PBOOK_SLEEP_REFUSE;
1602     }
1603     
1604     static int aty_power_mgmt(int sleep, struct fb_info_aty *info)
1605     {
1606         return M64_HAS(LT_SLEEP) ? aty_power_mgmt_LT(sleep, info)
1607     			     : aty_power_mgmt_LTPro(sleep, info);
1608     }
1609     
1610     /*
1611      * Save the contents of the frame buffer when we go to sleep,
1612      * and restore it when we wake up again.
1613      */
1614     static int aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
1615     {
1616     	struct fb_info_aty *info;
1617      	int result;
1618     
1619     	result = PBOOK_SLEEP_OK;
1620     
1621     	for (info = first_display; info != NULL; info = info->next) {
1622     		struct fb_fix_screeninfo fix;
1623     		int nb;
1624     
1625     		atyfb_get_fix(&fix, fg_console, (struct fb_info *)info);
1626     		nb = fb_display[fg_console].var.yres * fix.line_length;
1627     
1628     		switch (when) {
1629     		case PBOOK_SLEEP_REQUEST:
1630     			info->save_framebuffer = vmalloc(nb);
1631     			if (info->save_framebuffer == NULL)
1632     				return PBOOK_SLEEP_REFUSE;
1633     			break;
1634     		case PBOOK_SLEEP_REJECT:
1635     			if (info->save_framebuffer) {
1636     				vfree(info->save_framebuffer);
1637     				info->save_framebuffer = 0;
1638     			}
1639     			break;
1640     		case PBOOK_SLEEP_NOW:
1641     			if (info->blitter_may_be_busy)
1642     				wait_for_idle(info);
1643     			/* Stop accel engine (stop bus mastering) */
1644     			if (info->current_par.accel_flags & FB_ACCELF_TEXT)
1645     				aty_reset_engine(info);
1646     
1647     			/* Backup fb content */	
1648     			if (info->save_framebuffer)
1649     				memcpy_fromio(info->save_framebuffer,
1650     				       (void *)info->frame_buffer, nb);
1651     
1652     			/* Blank display and LCD */
1653     			atyfbcon_blank(VESA_POWERDOWN+1, (struct fb_info *)info);
1654     
1655     			/* Set chip to "suspend" mode */
1656     			result = aty_power_mgmt(1, info);
1657     			break;
1658     		case PBOOK_WAKE:
1659     			/* Wakeup chip */
1660     			result = aty_power_mgmt(0, info);
1661     
1662     			/* Restore fb content */			
1663     			if (info->save_framebuffer) {
1664     				memcpy_toio((void *)info->frame_buffer,
1665     				       info->save_framebuffer, nb);
1666     				vfree(info->save_framebuffer);
1667     				info->save_framebuffer = 0;
1668     			}
1669     			/* Restore display */
1670     			atyfb_set_par(&info->current_par, info);
1671     			atyfbcon_blank(0, (struct fb_info *)info);
1672     			break;
1673     		}
1674     	}
1675     	return result;
1676     }
1677     
1678     static struct pmu_sleep_notifier aty_sleep_notifier = {
1679             aty_sleep_notify, SLEEP_LEVEL_VIDEO,
1680     };
1681     #endif /* CONFIG_PMAC_PBOOK */
1682     
1683     #ifdef CONFIG_PMAC_BACKLIGHT
1684     
1685         /*
1686          *   LCD backlight control
1687          */
1688     
1689     static int backlight_conv[] = {
1690     	0x00, 0x3f, 0x4c, 0x59, 0x66, 0x73, 0x80, 0x8d,
1691     	0x9a, 0xa7, 0xb4, 0xc1, 0xcf, 0xdc, 0xe9, 0xff
1692     };
1693     
1694     static int
1695     aty_set_backlight_enable(int on, int level, void* data)
1696     {
1697     	struct fb_info_aty *info = (struct fb_info_aty *)data;
1698     	unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, info);
1699     	
1700     	reg |= (BLMOD_EN | BIASMOD_EN);
1701     	if (on && level > BACKLIGHT_OFF) {
1702     		reg &= ~BIAS_MOD_LEVEL_MASK;
1703     		reg |= (backlight_conv[level] << BIAS_MOD_LEVEL_SHIFT);
1704     	} else {
1705     		reg &= ~BIAS_MOD_LEVEL_MASK;
1706     		reg |= (backlight_conv[0] << BIAS_MOD_LEVEL_SHIFT);
1707     	}
1708     	aty_st_lcd(LCD_MISC_CNTL, reg, info);
1709     
1710     	return 0;
1711     }
1712     
1713     static int
1714     aty_set_backlight_level(int level, void* data)
1715     {
1716     	return aty_set_backlight_enable(1, level, data);
1717     }
1718     
1719     static struct backlight_controller aty_backlight_controller = {
1720     	aty_set_backlight_enable,
1721     	aty_set_backlight_level
1722     };
1723     #endif /* CONFIG_PMAC_BACKLIGHT */
1724     
1725     
1726     
1727         /*
1728          *  Initialisation
1729          */
1730     
1731     static struct fb_info_aty *fb_list = NULL;
1732     
1733     static int __init aty_init(struct fb_info_aty *info, const char *name)
1734     {
1735         u32 chip_id;
1736         u32 i;
1737         int j, k;
1738         struct fb_var_screeninfo var;
1739         struct display *disp;
1740         u16 type;
1741         u8 rev;
1742         const char *chipname = NULL, *ramname = NULL, *xtal;
1743         int pll, mclk, gtb_memsize;
1744     #if defined(CONFIG_PPC)
1745         int sense;
1746     #endif
1747         u8 pll_ref_div;
1748     
1749         info->aty_cmap_regs = (struct aty_cmap_regs *)(info->ati_regbase+0xc0);
1750         chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
1751         type = chip_id & CFG_CHIP_TYPE;
1752         rev = (chip_id & CFG_CHIP_REV)>>24;
1753         for (j = 0; j < (sizeof(aty_chips)/sizeof(*aty_chips)); j++)
1754     	if (type == aty_chips[j].chip_type &&
1755     	    (rev & aty_chips[j].rev_mask) == aty_chips[j].rev_val) {
1756     	    chipname = aty_chips[j].name;
1757     	    pll = aty_chips[j].pll;
1758     	    mclk = aty_chips[j].mclk;
1759     	    info->features = aty_chips[j].features;
1760     	    goto found;
1761     	}
1762         printk("atyfb: Unknown mach64 0x%04x rev 0x%04x\n", type, rev);
1763         return 0;
1764     
1765     found:
1766         printk("atyfb: %s [0x%04x rev 0x%02x] ", chipname, type, rev);
1767     #ifdef CONFIG_FB_ATY_GX
1768         if (!M64_HAS(INTEGRATED)) {
1769     	u32 stat0;
1770     	u8 dac_type, dac_subtype, clk_type;
1771     	stat0 = aty_ld_le32(CONFIG_STAT0, info);
1772     	info->bus_type = (stat0 >> 0) & 0x07;
1773     	info->ram_type = (stat0 >> 3) & 0x07;
1774     	ramname = aty_gx_ram[info->ram_type];
1775     	/* FIXME: clockchip/RAMDAC probing? */
1776     	dac_type = (aty_ld_le32(DAC_CNTL, info) >> 16) & 0x07;
1777     #ifdef CONFIG_ATARI
1778     	clk_type = CLK_ATI18818_1;
1779     	dac_type = (stat0 >> 9) & 0x07;
1780     	if (dac_type == 0x07)
1781     	    dac_subtype = DAC_ATT20C408;
1782     	else
1783     	    dac_subtype = (aty_ld_8(SCRATCH_REG1 + 1, info) & 0xF0) | dac_type;
1784     #else
1785     	dac_type = DAC_IBMRGB514;
1786     	dac_subtype = DAC_IBMRGB514;
1787     	clk_type = CLK_IBMRGB514;
1788     #endif
1789     	switch (dac_subtype) {
1790     	    case DAC_IBMRGB514:
1791     		info->dac_ops = &aty_dac_ibm514;
1792     		break;
1793     	    case DAC_ATI68860_B:
1794     	    case DAC_ATI68860_C:
1795     		info->dac_ops = &aty_dac_ati68860b;
1796     		break;
1797     	    case DAC_ATT20C408:
1798     	    case DAC_ATT21C498:
1799     		info->dac_ops = &aty_dac_att21c498;
1800     		break;
1801     	    default:
1802     		printk(" atyfb_set_par: DAC type not implemented yet!\n");
1803     		info->dac_ops = &aty_dac_unsupported;
1804     		break;
1805     	}
1806     	switch (clk_type) {
1807     	    case CLK_ATI18818_1:
1808     		info->pll_ops = &aty_pll_ati18818_1;
1809     		break;
1810     	    case CLK_STG1703:
1811     		info->pll_ops = &aty_pll_stg1703;
1812     		break;
1813     	    case CLK_CH8398:
1814     		info->pll_ops = &aty_pll_ch8398;
1815     		break;
1816     	    case CLK_ATT20C408:
1817     		info->pll_ops = &aty_pll_att20c408;
1818     		break;
1819     	    case CLK_IBMRGB514:
1820     		info->pll_ops = &aty_pll_ibm514;
1821     		break;
1822     	    default:
1823     		printk(" atyfb_set_par: CLK type not implemented yet!");
1824     		info->pll_ops = &aty_pll_unsupported;
1825     		break;
1826     	}
1827         }
1828     #endif /* CONFIG_FB_ATY_GX */
1829     #ifdef CONFIG_FB_ATY_CT
1830         if (M64_HAS(INTEGRATED)) {
1831     	info->bus_type = PCI;
1832     	info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) & 0x07);
1833     	ramname = aty_ct_ram[info->ram_type];
1834     	info->dac_ops = &aty_dac_ct;
1835     	info->pll_ops = &aty_pll_ct;
1836     	/* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
1837     	if (mclk == 67 && info->ram_type < SDRAM)
1838     	    mclk = 63;
1839         }
1840     #endif /* CONFIG_FB_ATY_CT */
1841     
1842         info->ref_clk_per = 1000000000000ULL/14318180;
1843         xtal = "14.31818";
1844         if (M64_HAS(GTB_DSP) && (pll_ref_div = aty_ld_pll(PLL_REF_DIV, info))) {
1845     	int diff1, diff2;
1846     	diff1 = 510*14/pll_ref_div-pll;
1847     	diff2 = 510*29/pll_ref_div-pll;
1848     	if (diff1 < 0)
1849     	    diff1 = -diff1;
1850     	if (diff2 < 0)
1851     	    diff2 = -diff2;
1852     	if (diff2 < diff1) {
1853     	    info->ref_clk_per = 1000000000000ULL/29498928;
1854     	    xtal = "29.498928";
1855     	}
1856         }
1857     
1858         i = aty_ld_le32(MEM_CNTL, info);
1859         gtb_memsize = M64_HAS(GTB_DSP);
1860         if (gtb_memsize)
1861     	switch (i & 0xF) {	/* 0xF used instead of MEM_SIZE_ALIAS */
1862     	    case MEM_SIZE_512K:
1863     		info->total_vram = 0x80000;
1864     		break;
1865     	    case MEM_SIZE_1M:
1866     		info->total_vram = 0x100000;
1867     		break;
1868     	    case MEM_SIZE_2M_GTB:
1869     		info->total_vram = 0x200000;
1870     		break;
1871     	    case MEM_SIZE_4M_GTB:
1872     		info->total_vram = 0x400000;
1873     		break;
1874     	    case MEM_SIZE_6M_GTB:
1875     		info->total_vram = 0x600000;
1876     		break;
1877     	    case MEM_SIZE_8M_GTB:
1878     		info->total_vram = 0x800000;
1879     		break;
1880     	    default:
1881     		info->total_vram = 0x80000;
1882     	}
1883         else
1884     	switch (i & MEM_SIZE_ALIAS) {
1885     	    case MEM_SIZE_512K:
1886     		info->total_vram = 0x80000;
1887     		break;
1888     	    case MEM_SIZE_1M:
1889     		info->total_vram = 0x100000;
1890     		break;
1891     	    case MEM_SIZE_2M:
1892     		info->total_vram = 0x200000;
1893     		break;
1894     	    case MEM_SIZE_4M:
1895     		info->total_vram = 0x400000;
1896     		break;
1897     	    case MEM_SIZE_6M:
1898     		info->total_vram = 0x600000;
1899     		break;
1900     	    case MEM_SIZE_8M:
1901     		info->total_vram = 0x800000;
1902     		break;
1903     	    default:
1904     		info->total_vram = 0x80000;
1905     	}
1906     
1907         if (M64_HAS(MAGIC_VRAM_SIZE)) {
1908     	if (aty_ld_le32(CONFIG_STAT1, info) & 0x40000000)
1909     	  info->total_vram += 0x400000;
1910         }
1911     
1912         if (default_vram) {
1913     	info->total_vram = default_vram*1024;
1914     	i = i & ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS);
1915     	if (info->total_vram <= 0x80000)
1916     	    i |= MEM_SIZE_512K;
1917     	else if (info->total_vram <= 0x100000)
1918     	    i |= MEM_SIZE_1M;
1919     	else if (info->total_vram <= 0x200000)
1920     	    i |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M;
1921     	else if (info->total_vram <= 0x400000)
1922     	    i |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M;
1923     	else if (info->total_vram <= 0x600000)
1924     	    i |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M;
1925     	else
1926     	    i |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M;
1927     	aty_st_le32(MEM_CNTL, i, info);
1928         }
1929         if (default_pll)
1930     	pll = default_pll;
1931         if (default_mclk)
1932     	mclk = default_mclk;
1933     
1934         printk("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK\n",
1935         	   info->total_vram == 0x80000 ? 512 : (info->total_vram >> 20),
1936         	   info->total_vram == 0x80000 ? 'K' : 'M', ramname, xtal, pll, mclk);
1937     
1938         if (mclk < 44)
1939     	info->mem_refresh_rate = 0;	/* 000 = 10 Mhz - 43 Mhz */
1940         else if (mclk < 50)
1941     	info->mem_refresh_rate = 1;	/* 001 = 44 Mhz - 49 Mhz */
1942         else if (mclk < 55)
1943     	info->mem_refresh_rate = 2;	/* 010 = 50 Mhz - 54 Mhz */
1944         else if (mclk < 66)
1945     	info->mem_refresh_rate = 3;	/* 011 = 55 Mhz - 65 Mhz */
1946         else if (mclk < 75)
1947     	info->mem_refresh_rate = 4;	/* 100 = 66 Mhz - 74 Mhz */
1948         else if (mclk < 80)
1949     	info->mem_refresh_rate = 5;	/* 101 = 75 Mhz - 79 Mhz */
1950         else if (mclk < 100)
1951     	info->mem_refresh_rate = 6;	/* 110 = 80 Mhz - 100 Mhz */
1952         else
1953     	info->mem_refresh_rate = 7;	/* 111 = 100 Mhz and above */
1954         info->pll_per = 1000000/pll;
1955         info->mclk_per = 1000000/mclk;
1956     
1957     #ifdef DEBUG
1958         if (M64_HAS(INTEGRATED)) {
1959     	int i;
1960     	printk("BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
1961     	       "DSP_CONFIG DSP_ON_OFF\n"
1962     	       "%08x %08x %08x %08x     %08x      %08x   %08x\n"
1963     	       "PLL",
1964     	       aty_ld_le32(BUS_CNTL, info), aty_ld_le32(DAC_CNTL, info),
1965     	       aty_ld_le32(MEM_CNTL, info), aty_ld_le32(EXT_MEM_CNTL, info),
1966     	       aty_ld_le32(CRTC_GEN_CNTL, info), aty_ld_le32(DSP_CONFIG, info),
1967     	       aty_ld_le32(DSP_ON_OFF, info));
1968     	for (i = 0; i < 16; i++)
1969     	    printk(" %02x", aty_ld_pll(i, info));
1970     	printk("\n");
1971         }
1972     #endif
1973     
1974         /*
1975          *  Last page of 8 MB (4 MB on ISA) aperture is MMIO
1976          *  FIXME: we should use the auxiliary aperture instead so we can access
1977          *  the full 8 MB of video RAM on 8 MB boards
1978          */
1979         if (info->total_vram == 0x800000 ||
1980     	(info->bus_type == ISA && info->total_vram == 0x400000))
1981     	    info->total_vram -= GUI_RESERVE;
1982     
1983         /* Clear the video memory */
1984         fb_memset((void *)info->frame_buffer, 0, info->total_vram);
1985     
1986         disp = &info->disp;
1987     
1988         strcpy(info->fb_info.modename, atyfb_name);
1989         info->fb_info.node = -1;
1990         info->fb_info.fbops = &atyfb_ops;
1991         info->fb_info.disp = disp;
1992         strcpy(info->fb_info.fontname, fontname);
1993         info->fb_info.changevar = NULL;
1994         info->fb_info.switch_con = &atyfbcon_switch;
1995         info->fb_info.updatevar = &atyfbcon_updatevar;
1996         info->fb_info.blank = &atyfbcon_blank;
1997         info->fb_info.flags = FBINFO_FLAG_DEFAULT;
1998     
1999     #ifdef CONFIG_PMAC_BACKLIGHT
2000         if (M64_HAS(G3_PB_1_1) && machine_is_compatible("PowerBook1,1")) {
2001     	/* these bits let the 101 powerbook wake up from sleep -- paulus */
2002     	aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, info)
2003     		| (USE_F32KHZ | TRISTATE_MEM_EN), info);
2004         }
2005         if (M64_HAS(MOBIL_BUS))
2006     	register_backlight_controller(&aty_backlight_controller, info, "ati");
2007     #endif /* CONFIG_PMAC_BACKLIGHT */
2008     
2009     #ifdef MODULE
2010         var = default_var;
2011     #else /* !MODULE */
2012         memset(&var, 0, sizeof(var));
2013     #ifdef CONFIG_PPC
2014         if (_machine == _MACH_Pmac) {
2015     	    /*
2016     	     *  FIXME: The NVRAM stuff should be put in a Mac-specific file, as it
2017     	     *         applies to all Mac video cards
2018     	     */
2019     	    if (mode_option) {
2020     		if (!mac_find_mode(&var, &info->fb_info, mode_option, 8))
2021     		    var = default_var;
2022     	    } else {
2023     #ifdef CONFIG_NVRAM
2024     		if (default_vmode == VMODE_NVRAM) {
2025     		    default_vmode = nvram_read_byte(NV_VMODE);
2026     		    if (default_vmode <= 0 || default_vmode > VMODE_MAX)
2027     			default_vmode = VMODE_CHOOSE;
2028     		}
2029     #endif
2030     		if (default_vmode == VMODE_CHOOSE) {
2031     		    if (M64_HAS(G3_PB_1024x768))
2032     			/* G3 PowerBook with 1024x768 LCD */
2033     			default_vmode = VMODE_1024_768_60;
2034     		    else if (machine_is_compatible("iMac"))
2035     			default_vmode = VMODE_1024_768_75;
2036     		    else if (machine_is_compatible("PowerBook2,1"))
2037     			/* iBook with 800x600 LCD */
2038     			default_vmode = VMODE_800_600_60;
2039     		    else
2040     			default_vmode = VMODE_640_480_67;
2041     		    sense = read_aty_sense(info);
2042     		    printk(KERN_INFO "atyfb: monitor sense=%x, mode %d\n",
2043     			   sense, mac_map_monitor_sense(sense));
2044     		}
2045     		if (default_vmode <= 0 || default_vmode > VMODE_MAX)
2046     		    default_vmode = VMODE_640_480_60;
2047     #ifdef CONFIG_NVRAM
2048     		if (default_cmode == CMODE_NVRAM)
2049     		    default_cmode = nvram_read_byte(NV_CMODE);
2050     #endif
2051     		if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
2052     		    default_cmode = CMODE_8;
2053     		if (mac_vmode_to_var(default_vmode, default_cmode, &var))
2054     		    var = default_var;
2055     	    }
2056         }
2057         else if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
2058     	var = default_var;
2059     #else /* !CONFIG_PPC */
2060     #ifdef __sparc__
2061         if (mode_option) {
2062         	if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
2063     	    var = default_var;
2064         } else
2065     	var = default_var;
2066     #else
2067         if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
2068     	var = default_var;
2069     #endif /* !__sparc__ */
2070     #endif /* !CONFIG_PPC */
2071     #endif /* !MODULE */
2072         if (noaccel)
2073             var.accel_flags &= ~FB_ACCELF_TEXT;
2074         else
2075             var.accel_flags |= FB_ACCELF_TEXT;
2076     
2077         if (var.yres == var.yres_virtual) {
2078     	u32 vram = (info->total_vram - (PAGE_SIZE << 2));
2079     	var.yres_virtual = ((vram * 8) / var.bits_per_pixel) / var.xres_virtual;
2080     	if (var.yres_virtual < var.yres)
2081     		var.yres_virtual = var.yres;
2082         }
2083     
2084         if (atyfb_decode_var(&var, &info->default_par, info)) {
2085     	printk("atyfb: can't set default video mode\n");
2086     	return 0;
2087         }
2088     
2089     #ifdef __sparc__
2090         atyfb_save_palette(&info->fb_info, 0);
2091     #endif
2092         for (j = 0; j < 16; j++) {
2093     	k = color_table[j];
2094     	info->palette[j].red = default_red[k];
2095     	info->palette[j].green = default_grn[k];
2096     	info->palette[j].blue = default_blu[k];
2097         }
2098     
2099     #ifdef CONFIG_FB_ATY_CT
2100         if (curblink && M64_HAS(INTEGRATED)) {
2101     	info->cursor = aty_init_cursor(info);
2102     	if (info->cursor) {
2103     	    info->dispsw.cursor = atyfb_cursor;
2104     	    info->dispsw.set_font = atyfb_set_font;
2105     	}
2106         }
2107     #endif /* CONFIG_FB_ATY_CT */
2108     
2109         atyfb_set_var(&var, -1, &info->fb_info);
2110     
2111         if (register_framebuffer(&info->fb_info) < 0)
2112     	return 0;
2113     
2114         info->next = fb_list;
2115         fb_list = info;
2116     
2117         printk("fb%d: %s frame buffer device on %s\n",
2118     	   GET_FB_IDX(info->fb_info.node), atyfb_name, name);
2119         return 1;
2120     }
2121     
2122     int __init atyfb_init(void)
2123     {
2124     #if defined(CONFIG_PCI)
2125         struct pci_dev *pdev = NULL;
2126         struct fb_info_aty *info;
2127         unsigned long addr, res_start, res_size;
2128         int i;
2129     #ifdef __sparc__
2130         extern void (*prom_palette) (int);
2131         extern int con_is_present(void);
2132         struct pcidev_cookie *pcp;
2133         char prop[128];
2134         int node, len, j;
2135         u32 mem, chip_id;
2136     
2137         /* Do not attach when we have a serial console. */
2138         if (!con_is_present())
2139     	return -ENXIO;
2140     #else
2141         u16 tmp;
2142     #endif
2143     
2144         while ((pdev = pci_find_device(PCI_VENDOR_ID_ATI, PCI_ANY_ID, pdev))) {
2145     	if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
2146     	    struct resource *rp;
2147     
2148     	    for (i = sizeof(aty_chips)/sizeof(*aty_chips)-1; i >= 0; i--)
2149     		if (pdev->device == aty_chips[i].pci_id)
2150     		    break;
2151     	    if (i < 0)
2152     		continue;
2153     
2154     	    info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
2155     	    if (!info) {
2156     		printk("atyfb_init: can't alloc fb_info_aty\n");
2157     		return -ENXIO;
2158     	    }
2159     	    memset(info, 0, sizeof(struct fb_info_aty));
2160     
2161     	    rp = &pdev->resource[0];
2162     	    if (rp->flags & IORESOURCE_IO)
2163     		    rp = &pdev->resource[1];
2164     	    addr = rp->start;
2165     	    if (!addr)
2166     		continue;
2167     
2168     	    res_start = rp->start;
2169     	    res_size = rp->end-rp->start+1;
2170     	    if (!request_mem_region(res_start, res_size, "atyfb"))
2171     		continue;
2172     
2173     #ifdef __sparc__
2174     	    /*
2175     	     * Map memory-mapped registers.
2176     	     */
2177     	    info->ati_regbase = addr + 0x7ffc00UL;
2178     	    info->ati_regbase_phys = addr + 0x7ffc00UL;
2179     
2180     	    /*
2181     	     * Map in big-endian aperture.
2182     	     */
2183     	    info->frame_buffer = (unsigned long) addr + 0x800000UL;
2184     	    info->frame_buffer_phys = addr + 0x800000UL;
2185     
2186     	    /*
2187     	     * Figure mmap addresses from PCI config space.
2188     	     * Split Framebuffer in big- and little-endian halfs.
2189     	     */
2190     	    for (i = 0; i < 6 && pdev->resource[i].start; i++)
2191     		/* nothing */;
2192     	    j = i + 4;
2193     
2194     	    info->mmap_map = kmalloc(j * sizeof(*info->mmap_map), GFP_ATOMIC);
2195     	    if (!info->mmap_map) {
2196     		printk("atyfb_init: can't alloc mmap_map\n");
2197     		kfree(info);
2198     		release_mem_region(res_start, res_size);
2199     		return -ENXIO;
2200     	    }
2201     	    memset(info->mmap_map, 0, j * sizeof(*info->mmap_map));
2202     
2203     	    for (i = 0, j = 2; i < 6 && pdev->resource[i].start; i++) {
2204     		struct resource *rp = &pdev->resource[i];
2205     		int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
2206     		unsigned long base;
2207     		u32 size, pbase;
2208     
2209     		base = rp->start;
2210     
2211     		io = (rp->flags & IORESOURCE_IO);
2212     
2213     		size = rp->end - base + 1;
2214     
2215     		pci_read_config_dword(pdev, breg, &pbase);
2216     
2217     		if (io)
2218     			size &= ~1;
2219     
2220     		/*
2221     		 * Map the framebuffer a second time, this time without
2222     		 * the braindead _PAGE_IE setting. This is used by the
2223     		 * fixed Xserver, but we need to maintain the old mapping
2224     		 * to stay compatible with older ones...
2225     		 */
2226     		if (base == addr) {
2227     		    info->mmap_map[j].voff = (pbase + 0x10000000) & PAGE_MASK;
2228     		    info->mmap_map[j].poff = base & PAGE_MASK;
2229     		    info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
2230     		    info->mmap_map[j].prot_mask = _PAGE_CACHE;
2231     		    info->mmap_map[j].prot_flag = _PAGE_E;
2232     		    j++;
2233     		}
2234     
2235     		/*
2236     		 * Here comes the old framebuffer mapping with _PAGE_IE
2237     		 * set for the big endian half of the framebuffer...
2238     		 */
2239     		if (base == addr) {
2240     		    info->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK;
2241     		    info->mmap_map[j].poff = (base+0x800000) & PAGE_MASK;
2242     		    info->mmap_map[j].size = 0x800000;
2243     		    info->mmap_map[j].prot_mask = _PAGE_CACHE;
2244     		    info->mmap_map[j].prot_flag = _PAGE_E|_PAGE_IE;
2245     		    size -= 0x800000;
2246     		    j++;
2247     		}
2248     
2249     		info->mmap_map[j].voff = pbase & PAGE_MASK;
2250     		info->mmap_map[j].poff = base & PAGE_MASK;
2251     		info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
2252     		info->mmap_map[j].prot_mask = _PAGE_CACHE;
2253     		info->mmap_map[j].prot_flag = _PAGE_E;
2254     		j++;
2255     	    }
2256     
2257     	    if (pdev->device != XL_CHIP_ID) {
2258     		    /*
2259     		     * Fix PROMs idea of MEM_CNTL settings...
2260     		     */
2261     		    mem = aty_ld_le32(MEM_CNTL, info);
2262     		    chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
2263     		    if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) &&
2264     			!((chip_id >> 24) & 1)) {
2265     			switch (mem & 0x0f) {
2266     			    case 3:
2267     				mem = (mem & ~(0x0f)) | 2;
2268     				break;
2269     			    case 7:
2270     				mem = (mem & ~(0x0f)) | 3;
2271     				break;
2272     			    case 9:
2273     				mem = (mem & ~(0x0f)) | 4;
2274     				break;
2275     			    case 11:
2276     				mem = (mem & ~(0x0f)) | 5;
2277     				break;
2278     			    default:
2279     				break;
2280     			}
2281     			if ((aty_ld_le32(CONFIG_STAT0, info) & 7) >= SDRAM)
2282     				mem &= ~(0x00700000);
2283     		    }
2284     		    mem &= ~(0xcf80e000);	/* Turn off all undocumented bits. */
2285     		    aty_st_le32(MEM_CNTL, mem, info);
2286     	    }
2287     
2288     	    /*
2289     	     * If this is the console device, we will set default video
2290     	     * settings to what the PROM left us with.
2291     	     */
2292     	    node = prom_getchild(prom_root_node);
2293     	    node = prom_searchsiblings(node, "aliases");
2294     	    if (node) {
2295     		len = prom_getproperty(node, "screen", prop, sizeof(prop));
2296     		if (len > 0) {
2297     		    prop[len] = '\0';
2298     		    node = prom_finddevice(prop);
2299     		} else {
2300     		    node = 0;
2301     		}
2302     	    }
2303     
2304     	    pcp = pdev->sysdata;
2305     	    if (node == pcp->prom_node) {
2306     
2307     		struct fb_var_screeninfo *var = &default_var;
2308     		unsigned int N, P, Q, M, T, R;
2309     		u32 v_total, h_total;
2310     		struct crtc crtc;
2311     		u8 pll_regs[16];
2312     		u8 clock_cntl;
2313     
2314     		crtc.vxres = prom_getintdefault(node, "width", 1024);
2315     		crtc.vyres = prom_getintdefault(node, "height", 768);
2316     		crtc.bpp = prom_getintdefault(node, "depth", 8);
2317     		crtc.xoffset = crtc.yoffset = 0;
2318     		crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, info);
2319     		crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, info);
2320     		crtc.v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, info);
2321     		crtc.v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, info);
2322     		crtc.gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, info);
2323     		aty_crtc_to_var(&crtc, var);
2324     
2325     		h_total = var->xres + var->right_margin +
2326     			  var->hsync_len + var->left_margin;
2327     		v_total = var->yres + var->lower_margin +
2328     			  var->vsync_len + var->upper_margin;
2329     
2330     		/*
2331     		 * Read the PLL to figure actual Refresh Rate.
2332     		 */
2333         		clock_cntl = aty_ld_8(CLOCK_CNTL, info);
2334     		/* printk("atyfb: CLOCK_CNTL: %02x\n", clock_cntl); */
2335     		for (i = 0; i < 16; i++)
2336     			pll_regs[i] = aty_ld_pll(i, info);
2337     
2338     		/*
2339     		 * PLL Reference Divider M:
2340     		 */
2341     		M = pll_regs[2];
2342     
2343     		/*
2344     		 * PLL Feedback Divider N (Dependant on CLOCK_CNTL):
2345     		 */
2346     		N = pll_regs[7 + (clock_cntl & 3)];
2347     
2348     		/*
2349     		 * PLL Post Divider P (Dependant on CLOCK_CNTL):
2350     		 */
2351     		P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
2352     
2353     		/*
2354     		 * PLL Divider Q:
2355     		 */
2356     		Q = N / P;
2357     
2358     		/*
2359     		 * Target Frequency:
2360     		 *
2361     		 *      T * M
2362     		 * Q = -------
2363     		 *      2 * R
2364     		 *
2365     		 * where R is XTALIN (= 14318 or 29498 kHz).
2366     		 */
2367     		if (pdev->device == XL_CHIP_ID)
2368     			R = 29498;
2369     		else
2370     			R = 14318;
2371     
2372     		T = 2 * Q * R / M;
2373     
2374     		default_var.pixclock = 1000000000 / T;
2375     	    }
2376     #else /* __sparc__ */
2377     
2378     	    info->ati_regbase_phys = 0x7ff000 + addr;
2379     	    info->ati_regbase = (unsigned long)
2380     				ioremap(info->ati_regbase_phys, 0x1000);
2381     
2382     	    if(!info->ati_regbase) {
2383     		    kfree(info);
2384     		    release_mem_region(res_start, res_size);
2385     		    return -ENOMEM;
2386     	    }
2387     
2388     	    info->ati_regbase_phys += 0xc00;
2389     	    info->ati_regbase += 0xc00;
2390     
2391     	    /*
2392     	     * Enable memory-space accesses using config-space
2393     	     * command register.
2394     	     */
2395     	    pci_read_config_word(pdev, PCI_COMMAND, &tmp);
2396     	    if (!(tmp & PCI_COMMAND_MEMORY)) {
2397     		tmp |= PCI_COMMAND_MEMORY;
2398     		pci_write_config_word(pdev, PCI_COMMAND, tmp);
2399     	    }
2400     
2401     #ifdef __BIG_ENDIAN
2402     	    /* Use the big-endian aperture */
2403     	    addr += 0x800000;
2404     #endif
2405     
2406     	    /* Map in frame buffer */
2407     	    info->frame_buffer_phys = addr;
2408     	    info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
2409     
2410     	    if(!info->frame_buffer) {
2411     		    kfree(info);
2412     		    release_mem_region(res_start, res_size);
2413     		    return -ENXIO;
2414     	    }
2415     
2416     #endif /* __sparc__ */
2417     
2418     	    if (!aty_init(info, "PCI")) {
2419     		if (info->mmap_map)
2420     		    kfree(info->mmap_map);
2421     		kfree(info);
2422     		release_mem_region(res_start, res_size);
2423     		return -ENXIO;
2424     	    }
2425     
2426     #ifdef __sparc__
2427     	    if (!prom_palette)
2428     		prom_palette = atyfb_palette;
2429     
2430     	    /*
2431     	     * Add /dev/fb mmap values.
2432     	     */
2433     	    info->mmap_map[0].voff = 0x8000000000000000UL;
2434     	    info->mmap_map[0].poff = info->frame_buffer & PAGE_MASK;
2435     	    info->mmap_map[0].size = info->total_vram;
2436     	    info->mmap_map[0].prot_mask = _PAGE_CACHE;
2437     	    info->mmap_map[0].prot_flag = _PAGE_E;
2438     	    info->mmap_map[1].voff = info->mmap_map[0].voff + info->total_vram;
2439     	    info->mmap_map[1].poff = info->ati_regbase & PAGE_MASK;
2440     	    info->mmap_map[1].size = PAGE_SIZE;
2441     	    info->mmap_map[1].prot_mask = _PAGE_CACHE;
2442     	    info->mmap_map[1].prot_flag = _PAGE_E;
2443     #endif /* __sparc__ */
2444     
2445     #ifdef CONFIG_PMAC_PBOOK
2446     	    if (first_display == NULL)
2447     		    pmu_register_sleep_notifier(&aty_sleep_notifier);
2448     	    info->next = first_display;
2449     	    first_display = info;
2450     #endif
2451     
2452     #ifdef CONFIG_FB_COMPAT_XPMAC
2453     	    if (!console_fb_info)
2454     		console_fb_info = &info->fb_info;
2455     #endif /* CONFIG_FB_COMPAT_XPMAC */
2456     	}
2457         }
2458     
2459     #elif defined(CONFIG_ATARI)
2460         u32 clock_r;
2461         int m64_num;
2462         struct fb_info_aty *info;
2463     
2464         for (m64_num = 0; m64_num < mach64_count; m64_num++) {
2465     	if (!phys_vmembase[m64_num] || !phys_size[m64_num] ||
2466     	    !phys_guiregbase[m64_num]) {
2467     	    printk(" phys_*[%d] parameters not set => returning early. \n",
2468     		   m64_num);
2469     	    continue;
2470     	}
2471     
2472     	info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
2473     	if (!info) {
2474     	    printk("atyfb_init: can't alloc fb_info_aty\n");
2475     	    return -ENOMEM;
2476     	}
2477     	memset(info, 0, sizeof(struct fb_info_aty));
2478     
2479     	/*
2480     	 *  Map the video memory (physical address given) to somewhere in the
2481     	 *  kernel address space.
2482     	 */
2483     	info->frame_buffer = ioremap(phys_vmembase[m64_num], phys_size[m64_num]);
2484     	info->frame_buffer_phys = info->frame_buffer;  /* Fake! */
2485     	info->ati_regbase = ioremap(phys_guiregbase[m64_num], 0x10000)+0xFC00ul;
2486     	info->ati_regbase_phys = info->ati_regbase;  /* Fake! */
2487     
2488     	aty_st_le32(CLOCK_CNTL, 0x12345678, info);
2489     	clock_r = aty_ld_le32(CLOCK_CNTL, info);
2490     
2491     	switch (clock_r & 0x003F) {
2492     	    case 0x12:
2493     		info->clk_wr_offset = 3;  /*  */
2494     		break;
2495     	    case 0x34:
2496     		info->clk_wr_offset = 2;  /* Medusa ST-IO ISA Adapter etc. */
2497     		break;
2498     	    case 0x16:
2499     		info->clk_wr_offset = 1;  /*  */
2500     		break;
2501     	    case 0x38:
2502     		info->clk_wr_offset = 0;  /* Panther 1 ISA Adapter (Gerald) */
2503     		break;
2504     	}
2505     
2506     	if (!aty_init(info, "ISA bus")) {
2507     	    kfree(info);
2508     	    /* This is insufficient! kernel_map has added two large chunks!! */
2509     	    return -ENXIO;
2510     	}
2511         }
2512     #endif /* CONFIG_ATARI */
2513         return 0;
2514     }
2515     
2516     #ifndef MODULE
2517     int __init atyfb_setup(char *options)
2518     {
2519         char *this_opt;
2520     
2521         if (!options || !*options)
2522     	return 0;
2523     
2524         for (this_opt = strtok(options, ","); this_opt;
2525     	 this_opt = strtok(NULL, ",")) {
2526     	if (!strncmp(this_opt, "font:", 5)) {
2527     		char *p;
2528     		int i;
2529     
2530     		p = this_opt + 5;
2531     		for (i = 0; i < sizeof(fontname) - 1; i++)
2532     			if (!*p || *p == ' ' || *p == ',')
2533     				break;
2534     		memcpy(fontname, this_opt + 5, i);
2535     		fontname[i] = 0;
2536     	} else if (!strncmp(this_opt, "noblink", 7)) {
2537     		curblink = 0;
2538     	} else if (!strncmp(this_opt, "noaccel", 7)) {
2539     		noaccel = 1;
2540     	} else if (!strncmp(this_opt, "vram:", 5))
2541     		default_vram = simple_strtoul(this_opt+5, NULL, 0);
2542     	else if (!strncmp(this_opt, "pll:", 4))
2543     		default_pll = simple_strtoul(this_opt+4, NULL, 0);
2544     	else if (!strncmp(this_opt, "mclk:", 5))
2545     		default_mclk = simple_strtoul(this_opt+5, NULL, 0);
2546     #ifdef CONFIG_PPC
2547     	else if (!strncmp(this_opt, "vmode:", 6)) {
2548     	    unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
2549     	    if (vmode > 0 && vmode <= VMODE_MAX)
2550     		default_vmode = vmode;
2551     	} else if (!strncmp(this_opt, "cmode:", 6)) {
2552     	    unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0);
2553     	    switch (cmode) {
2554     		case 0:
2555     		case 8:
2556     		    default_cmode = CMODE_8;
2557     		    break;
2558     		case 15:
2559     		case 16:
2560     		    default_cmode = CMODE_16;
2561     		    break;
2562     		case 24:
2563     		case 32:
2564     		    default_cmode = CMODE_32;
2565     		    break;
2566     	    }
2567     	}
2568     #endif
2569     #ifdef CONFIG_ATARI
2570     	/*
2571     	 * Why do we need this silly Mach64 argument?
2572     	 * We are already here because of mach64= so its redundant.
2573     	 */
2574     	else if (MACH_IS_ATARI && (!strncmp(this_opt, "Mach64:", 7))) {
2575     	    static unsigned char m64_num;
2576     	    static char mach64_str[80];
2577     	    strncpy(mach64_str, this_opt+7, 80);
2578     	    if (!store_video_par(mach64_str, m64_num)) {
2579     		m64_num++;
2580     		mach64_count = m64_num;
2581     	    }
2582     	}
2583     #endif
2584     	else
2585     	    mode_option = this_opt;
2586         }
2587         return 0;
2588     }
2589     #endif /* !MODULE */
2590     
2591     #ifdef CONFIG_ATARI
2592     static int __init store_video_par(char *video_str, unsigned char m64_num)
2593     {
2594         char *p;
2595         unsigned long vmembase, size, guiregbase;
2596     
2597         printk("store_video_par() '%s' \n", video_str);
2598     
2599         if (!(p = strtoke(video_str, ";")) || !*p)
2600     	goto mach64_invalid;
2601         vmembase = simple_strtoul(p, NULL, 0);
2602         if (!(p = strtoke(NULL, ";")) || !*p)
2603     	goto mach64_invalid;
2604         size = simple_strtoul(p, NULL, 0);
2605         if (!(p = strtoke(NULL, ";")) || !*p)
2606     	goto mach64_invalid;
2607         guiregbase = simple_strtoul(p, NULL, 0);
2608     
2609         phys_vmembase[m64_num] = vmembase;
2610         phys_size[m64_num] = size;
2611         phys_guiregbase[m64_num] = guiregbase;
2612         printk(" stored them all: $%08lX $%08lX $%08lX \n", vmembase, size,
2613     	   guiregbase);
2614         return 0;
2615     
2616     mach64_invalid:
2617         phys_vmembase[m64_num]   = 0;
2618         return -1;
2619     }
2620     
2621     static char __init *strtoke(char *s, const char *ct)
2622     {
2623         static char *ssave = NULL;
2624         char *sbegin, *send;
2625     
2626         sbegin  = s ? s : ssave;
2627         if (!sbegin)
2628     	return NULL;
2629         if (*sbegin == '\0') {
2630     	ssave = NULL;
2631     	return NULL;
2632         }
2633         send = strpbrk(sbegin, ct);
2634         if (send && *send != '\0')
2635     	*send++ = '\0';
2636         ssave = send;
2637         return sbegin;
2638     }
2639     #endif /* CONFIG_ATARI */
2640     
2641     static int atyfbcon_switch(int con, struct fb_info *fb)
2642     {
2643         struct fb_info_aty *info = (struct fb_info_aty *)fb;
2644         struct atyfb_par par;
2645     
2646         /* Do we have to save the colormap? */
2647         if (fb_display[currcon].cmap.len)
2648     	fb_get_cmap(&fb_display[currcon].cmap, 1, atyfb_getcolreg, fb);
2649     
2650     #ifdef CONFIG_FB_ATY_CT
2651         /* Erase HW Cursor */
2652         if (info->cursor)
2653     	atyfb_cursor(&fb_display[currcon], CM_ERASE,
2654     		     info->cursor->pos.x, info->cursor->pos.y);
2655     #endif /* CONFIG_FB_ATY_CT */
2656     
2657         currcon = con;
2658     
2659         atyfb_decode_var(&fb_display[con].var, &par, info);
2660         atyfb_set_par(&par, info);
2661         atyfb_set_dispsw(&fb_display[con], info, par.crtc.bpp,
2662     		     par.accel_flags & FB_ACCELF_TEXT);
2663     
2664         /* Install new colormap */
2665         do_install_cmap(con, fb);
2666     
2667     #ifdef CONFIG_FB_ATY_CT
2668         /* Install hw cursor */
2669         if (info->cursor) {
2670     	aty_set_cursor_color(info);
2671     	aty_set_cursor_shape(info);
2672         }
2673     #endif /* CONFIG_FB_ATY_CT */
2674         return 1;
2675     }
2676     
2677         /*
2678          *  Blank the display.
2679          */
2680     
2681     static void atyfbcon_blank(int blank, struct fb_info *fb)
2682     {
2683         struct fb_info_aty *info = (struct fb_info_aty *)fb;
2684         u8 gen_cntl;
2685     
2686     #ifdef CONFIG_PMAC_BACKLIGHT
2687         if ((_machine == _MACH_Pmac) && blank)
2688         	set_backlight_enable(0);
2689     #endif /* CONFIG_PMAC_BACKLIGHT */
2690     
2691         gen_cntl = aty_ld_8(CRTC_GEN_CNTL, info);
2692         if (blank > 0)
2693     	switch (blank-1) {
2694     	    case VESA_NO_BLANKING:
2695     		gen_cntl |= 0x40;
2696     		break;
2697     	    case VESA_VSYNC_SUSPEND:
2698     		gen_cntl |= 0x8;
2699     		break;
2700     	    case VESA_HSYNC_SUSPEND:
2701     		gen_cntl |= 0x4;
2702     		break;
2703     	    case VESA_POWERDOWN:
2704     		gen_cntl |= 0x4c;
2705     		break;
2706     	}
2707         else
2708     	gen_cntl &= ~(0x4c);
2709         aty_st_8(CRTC_GEN_CNTL, gen_cntl, info);
2710     
2711     #ifdef CONFIG_PMAC_BACKLIGHT
2712         if ((_machine == _MACH_Pmac) && !blank)
2713         	set_backlight_enable(1);
2714     #endif /* CONFIG_PMAC_BACKLIGHT */
2715     }
2716     
2717     
2718         /*
2719          *  Read a single color register and split it into
2720          *  colors/transparent. Return != 0 for invalid regno.
2721          */
2722     
2723     static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
2724     			   u_int *transp, struct fb_info *fb)
2725     {
2726         struct fb_info_aty *info = (struct fb_info_aty *)fb;
2727     
2728         if (regno > 255)
2729     	return 1;
2730         *red = (info->palette[regno].red<<8) | info->palette[regno].red;
2731         *green = (info->palette[regno].green<<8) | info->palette[regno].green;
2732         *blue = (info->palette[regno].blue<<8) | info->palette[regno].blue;
2733         *transp = 0;
2734         return 0;
2735     }
2736     
2737     
2738         /*
2739          *  Set a single color register. The values supplied are already
2740          *  rounded down to the hardware's capabilities (according to the
2741          *  entries in the var structure). Return != 0 for invalid regno.
2742          */
2743     
2744     static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
2745     			   u_int transp, struct fb_info *fb)
2746     {
2747         struct fb_info_aty *info = (struct fb_info_aty *)fb;
2748         int i, scale;
2749     
2750         if (regno > 255)
2751     	return 1;
2752         red >>= 8;
2753         green >>= 8;
2754         blue >>= 8;
2755         info->palette[regno].red = red;
2756         info->palette[regno].green = green;
2757         info->palette[regno].blue = blue;
2758         i = aty_ld_8(DAC_CNTL, info) & 0xfc;
2759         if (M64_HAS(EXTRA_BRIGHT))
2760     	i |= 0x2;	/*DAC_CNTL|0x2 turns off the extra brightness for gt*/
2761         aty_st_8(DAC_CNTL, i, info);
2762         aty_st_8(DAC_MASK, 0xff, info);
2763         scale = (M64_HAS(INTEGRATED) && info->current_par.crtc.bpp == 16) ? 3 : 0;
2764         writeb(regno << scale, &info->aty_cmap_regs->windex);
2765         writeb(red, &info->aty_cmap_regs->lut);
2766         writeb(green, &info->aty_cmap_regs->lut);
2767         writeb(blue, &info->aty_cmap_regs->lut);
2768         if (regno < 16)
2769     	switch (info->current_par.crtc.bpp) {
2770     #ifdef FBCON_HAS_CFB16
2771     	    case 16:
2772     		info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) |
2773     						regno;
2774     		break;
2775     #endif
2776     #ifdef FBCON_HAS_CFB24
2777     	    case 24:
2778     		info->fbcon_cmap.cfb24[regno] = (regno << 16) | (regno << 8) |
2779     						regno;
2780     		break;
2781     #endif
2782     #ifdef FBCON_HAS_CFB32
2783     	    case 32:
2784     		i = (regno << 8) | regno;
2785     		info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
2786     		break;
2787     #endif
2788     	    }
2789         return 0;
2790     }
2791     
2792     
2793     static void do_install_cmap(int con, struct fb_info *info)
2794     {
2795         if (con != currcon)
2796     	return;
2797         if (fb_display[con].cmap.len)
2798     	fb_set_cmap(&fb_display[con].cmap, 1, atyfb_setcolreg, info);
2799         else {
2800     	int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
2801     	fb_set_cmap(fb_default_cmap(size), 1, atyfb_setcolreg, info);
2802         }
2803     }
2804     
2805     
2806         /*
2807          *  Update the `var' structure (called by fbcon.c)
2808          */
2809     
2810     static int atyfbcon_updatevar(int con, struct fb_info *fb)
2811     {
2812         struct fb_info_aty *info = (struct fb_info_aty *)fb;
2813         struct atyfb_par *par = &info->current_par;
2814         struct display *p = &fb_display[con];
2815         struct vc_data *conp = p->conp;
2816         u32 yres, yoffset, sy, height;
2817     
2818         yres = ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1;
2819         yoffset = fb_display[con].var.yoffset;
2820     
2821         sy = (conp->vc_rows + p->yscroll) * fontheight(p);
2822         height = yres - conp->vc_rows * fontheight(p);
2823     
2824         if (height && (yoffset + yres > sy)) {
2825     	u32 xres, xoffset;
2826     	u32 bgx;
2827     
2828     	xres = (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8;
2829     	xoffset = fb_display[con].var.xoffset;
2830     
2831     
2832     	bgx = attr_bgcol_ec(p, conp);
2833     	bgx |= (bgx << 8);
2834     	bgx |= (bgx << 16);
2835     
2836     	if (sy + height > par->crtc.vyres) {
2837     	    wait_for_fifo(1, info);
2838     	    aty_st_le32(SC_BOTTOM, sy + height - 1, info);
2839     	}
2840     	aty_rectfill(xoffset, sy, xres, height, bgx, info);
2841         }
2842     
2843     #ifdef CONFIG_FB_ATY_CT
2844         if (info->cursor && (yoffset + yres <= sy))
2845     	atyfb_cursor(p, CM_ERASE, info->cursor->pos.x, info->cursor->pos.y);
2846     #endif /* CONFIG_FB_ATY_CT */
2847     
2848         info->current_par.crtc.yoffset = yoffset;
2849         set_off_pitch(&info->current_par, info);
2850         return 0;
2851     }
2852     
2853     
2854     
2855     #ifdef MODULE
2856     int __init init_module(void)
2857     {
2858         atyfb_init();
2859         return fb_list ? 0 : -ENXIO;
2860     }
2861     
2862     void cleanup_module(void)
2863     {
2864         while (fb_list) {
2865     	struct fb_info_aty *info = fb_list;
2866     	fb_list = info->next;
2867     
2868     	unregister_framebuffer(&info->fb_info);
2869     
2870     #ifndef __sparc__
2871     	if (info->ati_regbase)
2872     	    iounmap((void *)info->ati_regbase);
2873     	if (info->frame_buffer)
2874     	    iounmap((void *)info->frame_buffer);
2875     #ifdef __BIG_ENDIAN
2876     	if (info->cursor && info->cursor->ram)
2877     	    iounmap(info->cursor->ram);
2878     #endif
2879     #endif
2880     
2881     	if (info->cursor) {
2882     	    if (info->cursor->timer)
2883     		kfree(info->cursor->timer);
2884     	    kfree(info->cursor);
2885     	}
2886     #ifdef __sparc__
2887     	if (info->mmap_map)
2888     	    kfree(info->mmap_map);
2889     #endif
2890     	kfree(info);
2891         }
2892     }
2893     
2894     #endif
2895