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