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