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