Merge with 2.4.0-test3-pre4.
[linux-2.6/linux-mips.git] / drivers / video / atyfb.c
blobd32a621b7bfbb25d59ab81704ad6234039f7dcff
1 /* $Id: atyfb.c,v 1.142 2000/04/12 01:39:41 davem Exp $
2 * linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
4 * Copyright (C) 1997-1998 Geert Uytterhoeven
5 * Copyright (C) 1998 Bernd Harries
6 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
8 * This driver is partly based on the PowerMac console driver:
10 * Copyright (C) 1996 Paul Mackerras
12 * and on the PowerMac ATI/mach64 display driver:
14 * Copyright (C) 1997 Michael AK Tesch
16 * with work by Jon Howell
17 * Harry AC Eaton
18 * Anthony Tong <atong@uiuc.edu>
20 * This file is subject to the terms and conditions of the GNU General Public
21 * License. See the file COPYING in the main directory of this archive for
22 * more details.
25 /******************************************************************************
27 TODO:
29 - cursor support on all cards and all ramdacs.
30 - cursor parameters controlable via ioctl()s.
31 - guess PLL and MCLK based on the original PLL register values initialized
32 by the BIOS or Open Firmware (if they are initialized).
34 (Anyone to help with this?)
36 ******************************************************************************/
39 #include <linux/config.h>
40 #include <linux/module.h>
41 #include <linux/kernel.h>
42 #include <linux/errno.h>
43 #include <linux/string.h>
44 #include <linux/mm.h>
45 #include <linux/tty.h>
46 #include <linux/malloc.h>
47 #include <linux/vmalloc.h>
48 #include <linux/delay.h>
49 #include <linux/interrupt.h>
50 #include <linux/fb.h>
51 #include <linux/selection.h>
52 #include <linux/console.h>
53 #include <linux/init.h>
54 #include <linux/pci.h>
55 #include <linux/kd.h>
56 #include <linux/vt_kern.h>
58 #ifdef CONFIG_FB_COMPAT_XPMAC
59 #include <asm/vc_ioctl.h>
60 #endif
62 #include <asm/io.h>
64 #ifdef __powerpc__
65 #include <linux/adb.h>
66 #include <asm/prom.h>
67 #include <asm/pci-bridge.h>
68 #include <video/macmodes.h>
69 #endif
70 #ifdef CONFIG_ADB_PMU
71 #include <linux/pmu.h>
72 #endif
73 #ifdef CONFIG_NVRAM
74 #include <linux/nvram.h>
75 #endif
76 #ifdef __sparc__
77 #include <asm/pbm.h>
78 #include <asm/fbio.h>
79 #endif
80 #include <asm/uaccess.h>
82 #include <video/fbcon.h>
83 #include <video/fbcon-cfb8.h>
84 #include <video/fbcon-cfb16.h>
85 #include <video/fbcon-cfb24.h>
86 #include <video/fbcon-cfb32.h>
88 #include "aty.h"
92 * Debug flags.
94 #undef DEBUG
96 /* Definitions for the ICS 2595 == ATI 18818_1 Clockchip */
98 #define REF_FREQ_2595 1432 /* 14.33 MHz (exact 14.31818) */
99 #define REF_DIV_2595 46 /* really 43 on ICS 2595 !!! */
100 /* ohne Prescaler */
101 #define MAX_FREQ_2595 15938 /* 159.38 MHz (really 170.486) */
102 #define MIN_FREQ_2595 8000 /* 80.00 MHz ( 85.565) */
103 /* mit Prescaler 2, 4, 8 */
104 #define ABS_MIN_FREQ_2595 1000 /* 10.00 MHz (really 10.697) */
105 #define N_ADJ_2595 257
107 #define STOP_BITS_2595 0x1800
110 #define MIN_N_408 2
112 #define MIN_N_1703 6
114 #define MIN_M 2
115 #define MAX_M 30
116 #define MIN_N 35
117 #define MAX_N 255-8
120 /* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */
121 /* - must be large enough to catch all GUI-Regs */
122 /* - must be aligned to a PAGE boundary */
123 #define GUI_RESERVE (1 * PAGE_SIZE)
126 /* FIXME: remove the FAIL definition */
127 #define FAIL(x) do { printk(x "\n"); return -EINVAL; } while (0)
131 * Elements of the Hardware specific atyfb_par structure
134 struct crtc {
135 u32 vxres;
136 u32 vyres;
137 u32 xoffset;
138 u32 yoffset;
139 u32 bpp;
140 u32 h_tot_disp;
141 u32 h_sync_strt_wid;
142 u32 v_tot_disp;
143 u32 v_sync_strt_wid;
144 u32 off_pitch;
145 u32 gen_cntl;
146 u32 dp_pix_width; /* acceleration */
147 u32 dp_chain_mask; /* acceleration */
150 struct pll_gx {
151 u8 m;
152 u8 n;
155 struct pll_18818
157 u32 program_bits;
158 u32 locationAddr;
159 u32 period_in_ps;
160 u32 post_divider;
163 struct pll_ct {
164 u8 pll_ref_div;
165 u8 pll_gen_cntl;
166 u8 mclk_fb_div;
167 u8 pll_vclk_cntl;
168 u8 vclk_post_div;
169 u8 vclk_fb_div;
170 u8 pll_ext_cntl;
171 u32 dsp_config; /* Mach64 GTB DSP */
172 u32 dsp_on_off; /* Mach64 GTB DSP */
173 u8 mclk_post_div_real;
174 u8 vclk_post_div_real;
179 * The Hardware parameters for each card
182 struct atyfb_par {
183 struct crtc crtc;
184 union {
185 struct pll_gx gx;
186 struct pll_ct ct;
187 struct pll_18818 ics2595;
188 } pll;
189 u32 accel_flags;
192 struct aty_cmap_regs {
193 u8 windex;
194 u8 lut;
195 u8 mask;
196 u8 rindex;
197 u8 cntl;
200 struct pci_mmap_map {
201 unsigned long voff;
202 unsigned long poff;
203 unsigned long size;
204 unsigned long prot_flag;
205 unsigned long prot_mask;
208 #define DEFAULT_CURSOR_BLINK_RATE (20)
209 #define CURSOR_DRAW_DELAY (2)
211 struct aty_cursor {
212 int enable;
213 int on;
214 int vbl_cnt;
215 int blink_rate;
216 u32 offset;
217 struct {
218 u16 x, y;
219 } pos, hot, size;
220 u32 color[2];
221 u8 bits[8][64];
222 u8 mask[8][64];
223 u8 *ram;
224 struct timer_list *timer;
227 struct fb_info_aty {
228 struct fb_info fb_info;
229 struct fb_info_aty *next;
230 unsigned long ati_regbase_phys;
231 unsigned long ati_regbase;
232 unsigned long frame_buffer_phys;
233 unsigned long frame_buffer;
234 unsigned long clk_wr_offset;
235 struct pci_mmap_map *mmap_map;
236 struct aty_cursor *cursor;
237 struct aty_cmap_regs *aty_cmap_regs;
238 struct { u8 red, green, blue, pad; } palette[256];
239 struct atyfb_par default_par;
240 struct atyfb_par current_par;
241 u32 total_vram;
242 u32 ref_clk_per;
243 u32 pll_per;
244 u32 mclk_per;
245 u16 chip_type;
246 #define Gx info->chip_type
247 u8 chip_rev;
248 #define Rev info->chip_rev
249 u8 bus_type;
250 u8 ram_type;
251 u8 dac_type;
252 u8 dac_subtype;
253 u8 clk_type;
254 u8 mem_refresh_rate;
255 struct display disp;
256 struct display_switch dispsw;
257 union {
258 #ifdef FBCON_HAS_CFB16
259 u16 cfb16[16];
260 #endif
261 #ifdef FBCON_HAS_CFB24
262 u32 cfb24[16];
263 #endif
264 #ifdef FBCON_HAS_CFB32
265 u32 cfb32[16];
266 #endif
267 } fbcon_cmap;
268 u8 blitter_may_be_busy;
269 #ifdef __sparc__
270 u8 mmaped;
271 int open;
272 int vtconsole;
273 int consolecnt;
274 #endif
275 #ifdef CONFIG_PMAC_PBOOK
276 unsigned char *save_framebuffer;
277 unsigned long save_pll[64];
278 #endif
281 #ifdef CONFIG_PMAC_PBOOK
282 int aty_sleep_notify(struct pmu_sleep_notifier *self, int when);
283 static struct pmu_sleep_notifier aty_sleep_notifier = {
284 aty_sleep_notify, SLEEP_LEVEL_VIDEO,
286 static struct fb_info_aty* first_display = NULL;
287 #endif
291 * Frame buffer device API
294 static int atyfb_open(struct fb_info *info, int user);
295 static int atyfb_release(struct fb_info *info, int user);
296 static int atyfb_get_fix(struct fb_fix_screeninfo *fix, int con,
297 struct fb_info *fb);
298 static int atyfb_get_var(struct fb_var_screeninfo *var, int con,
299 struct fb_info *fb);
300 static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
301 struct fb_info *fb);
302 static int atyfb_pan_display(struct fb_var_screeninfo *var, int con,
303 struct fb_info *fb);
304 static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
305 struct fb_info *info);
306 static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
307 struct fb_info *info);
308 static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
309 u_long arg, int con, struct fb_info *info);
310 #ifdef __sparc__
311 static int atyfb_mmap(struct fb_info *info, struct file *file,
312 struct vm_area_struct *vma);
313 #endif
314 static int atyfb_rasterimg(struct fb_info *info, int start);
318 * Interface to the low level console driver
321 static int atyfbcon_switch(int con, struct fb_info *fb);
322 static int atyfbcon_updatevar(int con, struct fb_info *fb);
323 static void atyfbcon_blank(int blank, struct fb_info *fb);
327 * Text console acceleration
330 static void fbcon_aty_bmove(struct display *p, int sy, int sx, int dy, int dx,
331 int height, int width);
332 static void fbcon_aty_clear(struct vc_data *conp, struct display *p, int sy,
333 int sx, int height, int width);
334 #ifdef FBCON_HAS_CFB8
335 static struct display_switch fbcon_aty8;
336 static void fbcon_aty8_putc(struct vc_data *conp, struct display *p, int c,
337 int yy, int xx);
338 static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p,
339 const unsigned short *s, int count, int yy,
340 int xx);
341 #endif
342 #ifdef FBCON_HAS_CFB16
343 static struct display_switch fbcon_aty16;
344 static void fbcon_aty16_putc(struct vc_data *conp, struct display *p, int c,
345 int yy, int xx);
346 static void fbcon_aty16_putcs(struct vc_data *conp, struct display *p,
347 const unsigned short *s, int count, int yy,
348 int xx);
349 #endif
350 #ifdef FBCON_HAS_CFB24
351 static struct display_switch fbcon_aty24;
352 static void fbcon_aty24_putc(struct vc_data *conp, struct display *p, int c,
353 int yy, int xx);
354 static void fbcon_aty24_putcs(struct vc_data *conp, struct display *p,
355 const unsigned short *s, int count, int yy,
356 int xx);
357 #endif
358 #ifdef FBCON_HAS_CFB32
359 static struct display_switch fbcon_aty32;
360 static void fbcon_aty32_putc(struct vc_data *conp, struct display *p, int c,
361 int yy, int xx);
362 static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p,
363 const unsigned short *s, int count, int yy,
364 int xx);
365 #endif
369 * Internal routines
372 static int aty_init(struct fb_info_aty *info, const char *name);
373 static struct aty_cursor *aty_init_cursor(struct fb_info_aty *fb);
374 #ifdef CONFIG_ATARI
375 static int store_video_par(char *videopar, unsigned char m64_num);
376 static char *strtoke(char *s, const char *ct);
377 #endif
379 static void reset_engine(const struct fb_info_aty *info);
380 static void init_engine(const struct atyfb_par *par, struct fb_info_aty *info);
382 static void aty_st_514(int offset, u8 val, const struct fb_info_aty *info);
383 static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info);
384 static u8 aty_ld_pll(int offset, const struct fb_info_aty *info);
385 static void aty_set_crtc(const struct fb_info_aty *info,
386 const struct crtc *crtc);
387 static int aty_var_to_crtc(const struct fb_info_aty *info,
388 const struct fb_var_screeninfo *var,
389 struct crtc *crtc);
390 static void aty_set_dac_514(const struct fb_info_aty *info, u32 bpp);
391 static int aty_crtc_to_var(const struct crtc *crtc,
392 struct fb_var_screeninfo *var);
393 static void aty_set_pll_gx(const struct fb_info_aty *info,
394 const struct pll_gx *pll);
396 static int aty_set_dac_ATI68860_B(const struct fb_info_aty *info, u32 bpp,
397 u32 AccelMode);
398 static int aty_set_dac_ATT21C498(const struct fb_info_aty *info,
399 const struct pll_18818 *pll, u32 bpp);
400 void aty_dac_waste4(const struct fb_info_aty *info);
402 static int aty_var_to_pll_18818(u32 period_in_ps, struct pll_18818 *pll);
403 static u32 aty_pll_18818_to_var(const struct pll_18818 *pll);
404 static void aty_set_pll18818(const struct fb_info_aty *info,
405 const struct pll_18818 *pll);
407 static void aty_StrobeClock(const struct fb_info_aty *info);
409 static void aty_ICS2595_put1bit(u8 data, const struct fb_info_aty *info);
411 static int aty_var_to_pll_408(u32 period_in_ps, struct pll_18818 *pll);
412 static u32 aty_pll_408_to_var(const struct pll_18818 *pll);
413 static void aty_set_pll_408(const struct fb_info_aty *info,
414 const struct pll_18818 *pll);
416 static int aty_var_to_pll_1703(u32 period_in_ps, struct pll_18818 *pll);
417 static u32 aty_pll_1703_to_var(const struct pll_18818 *pll);
418 static void aty_set_pll_1703(const struct fb_info_aty *info,
419 const struct pll_18818 *pll);
421 static int aty_var_to_pll_8398(u32 period_in_ps, struct pll_18818 *pll);
422 static u32 aty_pll_8398_to_var(const struct pll_18818 *pll);
423 static void aty_set_pll_8398(const struct fb_info_aty *info,
424 const struct pll_18818 *pll);
426 static int aty_var_to_pll_514(u32 vclk_per, struct pll_gx *pll);
427 static u32 aty_pll_gx_to_var(const struct pll_gx *pll,
428 const struct fb_info_aty *info);
429 static void aty_set_pll_ct(const struct fb_info_aty *info,
430 const struct pll_ct *pll);
431 static int aty_valid_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
432 struct pll_ct *pll);
433 static int aty_dsp_gt(const struct fb_info_aty *info, u8 bpp,
434 struct pll_ct *pll);
435 static void aty_calc_pll_ct(const struct fb_info_aty *info,
436 struct pll_ct *pll);
437 static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
438 u8 bpp, struct pll_ct *pll);
439 static u32 aty_pll_ct_to_var(const struct pll_ct *pll,
440 const struct fb_info_aty *info);
441 static void atyfb_set_par(const struct atyfb_par *par,
442 struct fb_info_aty *info);
443 static int atyfb_decode_var(const struct fb_var_screeninfo *var,
444 struct atyfb_par *par,
445 const struct fb_info_aty *info);
446 static int atyfb_encode_var(struct fb_var_screeninfo *var,
447 const struct atyfb_par *par,
448 const struct fb_info_aty *info);
449 static void set_off_pitch(struct atyfb_par *par,
450 const struct fb_info_aty *info);
451 static int encode_fix(struct fb_fix_screeninfo *fix,
452 const struct atyfb_par *par,
453 const struct fb_info_aty *info);
454 static void atyfb_set_disp(struct display *disp, struct fb_info_aty *info,
455 int bpp, int accel);
456 static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
457 u_int *transp, struct fb_info *fb);
458 static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
459 u_int transp, struct fb_info *fb);
460 static void do_install_cmap(int con, struct fb_info *info);
461 #ifdef CONFIG_PPC
462 static int read_aty_sense(const struct fb_info_aty *info);
463 #endif
467 * Interface used by the world
470 int atyfb_init(void);
471 #ifndef MODULE
472 int atyfb_setup(char*);
473 #endif
475 static int currcon = 0;
477 static struct fb_ops atyfb_ops = {
478 owner: THIS_MODULE,
479 fb_open: atyfb_open,
480 fb_release: atyfb_release,
481 fb_get_fix: atyfb_get_fix,
482 fb_get_var: atyfb_get_var,
483 fb_set_var: atyfb_set_var,
484 fb_get_cmap: atyfb_get_cmap,
485 fb_set_cmap: atyfb_set_cmap,
486 fb_pan_display: atyfb_pan_display,
487 fb_ioctl: atyfb_ioctl,
488 #ifdef __sparc__
489 fb_mmap: atyfb_mmap,
490 #endif
491 fb_rasterimg: atyfb_rasterimg,
494 static char atyfb_name[16] = "ATY Mach64";
495 static char fontname[40] __initdata = { 0 };
496 static char curblink __initdata = 1;
497 static char noaccel __initdata = 0;
498 static u32 default_vram __initdata = 0;
499 static int default_pll __initdata = 0;
500 static int default_mclk __initdata = 0;
502 #ifndef MODULE
503 static const char *mode_option __initdata = NULL;
504 #endif
506 #ifdef CONFIG_PPC
507 #ifdef CONFIG_NVRAM_NOT_DEFINED
508 static int default_vmode __initdata = VMODE_NVRAM;
509 static int default_cmode __initdata = CMODE_NVRAM;
510 #else
511 static int default_vmode __initdata = VMODE_CHOOSE;
512 static int default_cmode __initdata = CMODE_CHOOSE;
513 #endif
514 #endif
516 #ifdef CONFIG_ATARI
517 static unsigned int mach64_count __initdata = 0;
518 static unsigned long phys_vmembase[FB_MAX] __initdata = { 0, };
519 static unsigned long phys_size[FB_MAX] __initdata = { 0, };
520 static unsigned long phys_guiregbase[FB_MAX] __initdata = { 0, };
521 #endif
524 static struct aty_features {
525 u16 pci_id;
526 u16 chip_type;
527 const char *name;
528 } aty_features[] __initdata = {
529 /* mach64GX family */
530 { 0x4758, 0x00d7, "mach64GX (ATI888GX00)" },
531 { 0x4358, 0x0057, "mach64CX (ATI888CX00)" },
533 /* mach64CT family */
534 { 0x4354, 0x4354, "mach64CT (ATI264CT)" },
535 { 0x4554, 0x4554, "mach64ET (ATI264ET)" },
537 /* mach64CT family / mach64VT class */
538 { 0x5654, 0x5654, "mach64VT (ATI264VT)" },
539 { 0x5655, 0x5655, "mach64VTB (ATI264VTB)" },
540 { 0x5656, 0x5656, "mach64VT4 (ATI264VT4)" },
542 /* mach64CT family / mach64GT (3D RAGE) class */
543 { 0x4c42, 0x4c42, "3D RAGE LT PRO (AGP)" },
544 { 0x4c44, 0x4c44, "3D RAGE LT PRO" },
545 { 0x4c47, 0x4c47, "3D RAGE LT-G" },
546 { 0x4c49, 0x4c49, "3D RAGE LT PRO" },
547 { 0x4c50, 0x4c50, "3D RAGE LT PRO" },
548 { 0x4c54, 0x4c54, "3D RAGE LT" },
549 { 0x4754, 0x4754, "3D RAGE (GT)" },
550 { 0x4755, 0x4755, "3D RAGE II+ (GTB)" },
551 { 0x4756, 0x4756, "3D RAGE IIC (PCI)" },
552 { 0x4757, 0x4757, "3D RAGE IIC (AGP)" },
553 { 0x475a, 0x475a, "3D RAGE IIC (AGP)" },
554 { 0x4742, 0x4742, "3D RAGE PRO (BGA, AGP)" },
555 { 0x4744, 0x4744, "3D RAGE PRO (BGA, AGP, 1x only)" },
556 { 0x4749, 0x4749, "3D RAGE PRO (BGA, PCI)" },
557 { 0x4750, 0x4750, "3D RAGE PRO (PQFP, PCI)" },
558 { 0x4751, 0x4751, "3D RAGE PRO (PQFP, PCI, limited 3D)" },
561 static const char *aty_gx_ram[8] __initdata = {
562 "DRAM", "VRAM", "VRAM", "DRAM", "DRAM", "VRAM", "VRAM", "RESV"
565 static const char *aty_ct_ram[8] __initdata = {
566 "OFF", "DRAM", "EDO", "EDO", "SDRAM", "SGRAM", "WRAM", "RESV"
570 static inline u32 aty_ld_le32(unsigned int regindex,
571 const struct fb_info_aty *info)
573 #if defined(__powerpc__)
574 unsigned long temp;
575 u32 val;
577 temp = info->ati_regbase;
578 asm volatile("lwbrx %0,%1,%2;eieio" : "=r"(val) : "b" (regindex), "r" (temp));
579 return val;
580 #elif defined(__mc68000__)
581 return le32_to_cpu(*((volatile u32 *)(info->ati_regbase+regindex)));
582 #else
583 return readl (info->ati_regbase + regindex);
584 #endif
587 static inline void aty_st_le32(unsigned int regindex, u32 val,
588 const struct fb_info_aty *info)
590 #if defined(__powerpc__)
591 unsigned long temp;
593 temp = info->ati_regbase;
594 asm volatile("stwbrx %0,%1,%2;eieio" : : "r" (val), "b" (regindex), "r" (temp) :
595 "memory");
596 #elif defined(__mc68000__)
597 *((volatile u32 *)(info->ati_regbase+regindex)) = cpu_to_le32(val);
598 #else
599 writel (val, info->ati_regbase + regindex);
600 #endif
603 static inline u8 aty_ld_8(unsigned int regindex,
604 const struct fb_info_aty *info)
606 return readb (info->ati_regbase + regindex);
609 static inline void aty_st_8(unsigned int regindex, u8 val,
610 const struct fb_info_aty *info)
612 writeb (val, info->ati_regbase + regindex);
615 #if defined(CONFIG_PPC) || defined(CONFIG_PMAC_PBOOK)
616 static void aty_st_lcd(int index, u32 val, const struct fb_info_aty *info)
618 unsigned long temp;
620 /* write addr byte */
621 temp = aty_ld_le32(LCD_INDEX, info);
622 aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, info);
623 /* write the register value */
624 aty_st_le32(LCD_DATA, val, info);
627 static u32 aty_ld_lcd(int index, const struct fb_info_aty *info)
629 unsigned long temp;
631 /* write addr byte */
632 temp = aty_ld_le32(LCD_INDEX, info);
633 aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, info);
634 /* read the register value */
635 return aty_ld_le32(LCD_DATA, info);
637 #endif
640 * Generic Mach64 routines
644 * All writes to draw engine registers are automatically routed through a
645 * 32-bit-wide, 16-entry-deep command FIFO ...
646 * Register writes to registers with DWORD offsets less than 40h are not
647 * FIFOed.
648 * (from Chapter 5 of the Mach64 Programmer's Guide)
651 static inline void wait_for_fifo(u16 entries, const struct fb_info_aty *info)
653 while ((aty_ld_le32(FIFO_STAT, info) & 0xffff) >
654 ((u32)(0x8000 >> entries)));
657 static inline void wait_for_idle(struct fb_info_aty *info)
659 wait_for_fifo(16, info);
660 while ((aty_ld_le32(GUI_STAT, info) & 1)!= 0);
661 info->blitter_may_be_busy = 0;
664 static void reset_engine(const struct fb_info_aty *info)
666 /* reset engine */
667 aty_st_le32(GEN_TEST_CNTL,
668 aty_ld_le32(GEN_TEST_CNTL, info) & ~GUI_ENGINE_ENABLE, info);
669 /* enable engine */
670 aty_st_le32(GEN_TEST_CNTL,
671 aty_ld_le32(GEN_TEST_CNTL, info) | GUI_ENGINE_ENABLE, info);
672 /* ensure engine is not locked up by clearing any FIFO or */
673 /* HOST errors */
674 aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, info) | BUS_HOST_ERR_ACK |
675 BUS_FIFO_ERR_ACK, info);
678 static void init_engine(const struct atyfb_par *par, struct fb_info_aty *info)
680 u32 pitch_value;
682 /* determine modal information from global mode structure */
683 pitch_value = par->crtc.vxres;
685 if (par->crtc.bpp == 24) {
686 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
687 /* horizontal coordinates and widths must be adjusted */
688 pitch_value = pitch_value * 3;
691 /* Reset engine, enable, and clear any engine errors */
692 reset_engine(info);
693 /* Ensure that vga page pointers are set to zero - the upper */
694 /* page pointers are set to 1 to handle overflows in the */
695 /* lower page */
696 aty_st_le32(MEM_VGA_WP_SEL, 0x00010000, info);
697 aty_st_le32(MEM_VGA_RP_SEL, 0x00010000, info);
699 /* ---- Setup standard engine context ---- */
701 /* All GUI registers here are FIFOed - therefore, wait for */
702 /* the appropriate number of empty FIFO entries */
703 wait_for_fifo(14, info);
705 /* enable all registers to be loaded for context loads */
706 aty_st_le32(CONTEXT_MASK, 0xFFFFFFFF, info);
708 /* set destination pitch to modal pitch, set offset to zero */
709 aty_st_le32(DST_OFF_PITCH, (pitch_value / 8) << 22, info);
711 /* zero these registers (set them to a known state) */
712 aty_st_le32(DST_Y_X, 0, info);
713 aty_st_le32(DST_HEIGHT, 0, info);
714 aty_st_le32(DST_BRES_ERR, 0, info);
715 aty_st_le32(DST_BRES_INC, 0, info);
716 aty_st_le32(DST_BRES_DEC, 0, info);
718 /* set destination drawing attributes */
719 aty_st_le32(DST_CNTL, DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM |
720 DST_X_LEFT_TO_RIGHT, info);
722 /* set source pitch to modal pitch, set offset to zero */
723 aty_st_le32(SRC_OFF_PITCH, (pitch_value / 8) << 22, info);
725 /* set these registers to a known state */
726 aty_st_le32(SRC_Y_X, 0, info);
727 aty_st_le32(SRC_HEIGHT1_WIDTH1, 1, info);
728 aty_st_le32(SRC_Y_X_START, 0, info);
729 aty_st_le32(SRC_HEIGHT2_WIDTH2, 1, info);
731 /* set source pixel retrieving attributes */
732 aty_st_le32(SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT, info);
734 /* set host attributes */
735 wait_for_fifo(13, info);
736 aty_st_le32(HOST_CNTL, 0, info);
738 /* set pattern attributes */
739 aty_st_le32(PAT_REG0, 0, info);
740 aty_st_le32(PAT_REG1, 0, info);
741 aty_st_le32(PAT_CNTL, 0, info);
743 /* set scissors to modal size */
744 aty_st_le32(SC_LEFT, 0, info);
745 aty_st_le32(SC_TOP, 0, info);
746 aty_st_le32(SC_BOTTOM, par->crtc.vyres-1, info);
747 aty_st_le32(SC_RIGHT, pitch_value-1, info);
749 /* set background color to minimum value (usually BLACK) */
750 aty_st_le32(DP_BKGD_CLR, 0, info);
752 /* set foreground color to maximum value (usually WHITE) */
753 aty_st_le32(DP_FRGD_CLR, 0xFFFFFFFF, info);
755 /* set write mask to effect all pixel bits */
756 aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF, info);
758 /* set foreground mix to overpaint and background mix to */
759 /* no-effect */
760 aty_st_le32(DP_MIX, FRGD_MIX_S | BKGD_MIX_D, info);
762 /* set primary source pixel channel to foreground color */
763 /* register */
764 aty_st_le32(DP_SRC, FRGD_SRC_FRGD_CLR, info);
766 /* set compare functionality to false (no-effect on */
767 /* destination) */
768 wait_for_fifo(3, info);
769 aty_st_le32(CLR_CMP_CLR, 0, info);
770 aty_st_le32(CLR_CMP_MASK, 0xFFFFFFFF, info);
771 aty_st_le32(CLR_CMP_CNTL, 0, info);
773 /* set pixel depth */
774 wait_for_fifo(2, info);
775 aty_st_le32(DP_PIX_WIDTH, par->crtc.dp_pix_width, info);
776 aty_st_le32(DP_CHAIN_MASK, par->crtc.dp_chain_mask, info);
778 wait_for_fifo(5, info);
779 aty_st_le32(SCALE_3D_CNTL, 0, info);
780 aty_st_le32(Z_CNTL, 0, info);
781 aty_st_le32(CRTC_INT_CNTL, aty_ld_le32(CRTC_INT_CNTL, info) & ~0x20, info);
782 aty_st_le32(GUI_TRAJ_CNTL, 0x100023, info);
784 /* insure engine is idle before leaving */
785 wait_for_idle(info);
788 static void aty_st_514(int offset, u8 val, const struct fb_info_aty *info)
790 aty_st_8(DAC_CNTL, 1, info);
791 /* right addr byte */
792 aty_st_8(DAC_W_INDEX, offset & 0xff, info);
793 /* left addr byte */
794 aty_st_8(DAC_DATA, (offset >> 8) & 0xff, info);
795 aty_st_8(DAC_MASK, val, info);
796 aty_st_8(DAC_CNTL, 0, info);
799 static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info)
801 /* write addr byte */
802 aty_st_8(CLOCK_CNTL + 1, (offset << 2) | PLL_WR_EN, info);
803 /* write the register value */
804 aty_st_8(CLOCK_CNTL + 2, val, info);
805 aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, info);
808 static u8 aty_ld_pll(int offset, const struct fb_info_aty *info)
810 u8 res;
812 /* write addr byte */
813 aty_st_8(CLOCK_CNTL + 1, (offset << 2), info);
814 /* read the register value */
815 res = aty_ld_8(CLOCK_CNTL + 2, info);
816 return res;
819 #if defined(CONFIG_PPC)
822 * Apple monitor sense
825 static int read_aty_sense(const struct fb_info_aty *info)
827 int sense, i;
829 aty_st_le32(GP_IO, 0x31003100, info); /* drive outputs high */
830 __delay(200);
831 aty_st_le32(GP_IO, 0, info); /* turn off outputs */
832 __delay(2000);
833 i = aty_ld_le32(GP_IO, info); /* get primary sense value */
834 sense = ((i & 0x3000) >> 3) | (i & 0x100);
836 /* drive each sense line low in turn and collect the other 2 */
837 aty_st_le32(GP_IO, 0x20000000, info); /* drive A low */
838 __delay(2000);
839 i = aty_ld_le32(GP_IO, info);
840 sense |= ((i & 0x1000) >> 7) | ((i & 0x100) >> 4);
841 aty_st_le32(GP_IO, 0x20002000, info); /* drive A high again */
842 __delay(200);
844 aty_st_le32(GP_IO, 0x10000000, info); /* drive B low */
845 __delay(2000);
846 i = aty_ld_le32(GP_IO, info);
847 sense |= ((i & 0x2000) >> 10) | ((i & 0x100) >> 6);
848 aty_st_le32(GP_IO, 0x10001000, info); /* drive B high again */
849 __delay(200);
851 aty_st_le32(GP_IO, 0x01000000, info); /* drive C low */
852 __delay(2000);
853 sense |= (aty_ld_le32(GP_IO, info) & 0x3000) >> 12;
854 aty_st_le32(GP_IO, 0, info); /* turn off outputs */
856 return sense;
859 #endif /* defined(CONFIG_PPC) */
861 /* ------------------------------------------------------------------------- */
864 * Hardware Cursor support.
867 static u8 cursor_pixel_map[2] = { 0, 15 };
868 static u8 cursor_color_map[2] = { 0, 0xff };
870 static u8 cursor_bits_lookup[16] =
872 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
873 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
876 static u8 cursor_mask_lookup[16] =
878 0xaa, 0x2a, 0x8a, 0x0a, 0xa2, 0x22, 0x82, 0x02,
879 0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00
882 static void
883 aty_set_cursor_color(struct fb_info_aty *fb, u8 *pixel,
884 u8 *red, u8 *green, u8 *blue)
886 struct aty_cursor *c = fb->cursor;
887 int i;
889 if (!c)
890 return;
892 #ifdef __sparc__
893 if (fb->mmaped && (!fb->fb_info.display_fg
894 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
895 return;
896 #endif
898 for (i = 0; i < 2; i++) {
899 c->color[i] = (u32)red[i] << 24;
900 c->color[i] |= (u32)green[i] << 16;
901 c->color[i] |= (u32)blue[i] << 8;
902 c->color[i] |= (u32)pixel[i];
905 wait_for_fifo(2, fb);
906 aty_st_le32(CUR_CLR0, c->color[0], fb);
907 aty_st_le32(CUR_CLR1, c->color[1], fb);
910 static void
911 aty_set_cursor_shape(struct fb_info_aty *fb)
913 struct aty_cursor *c = fb->cursor;
914 u8 *ram, m, b;
915 int x, y;
917 if (!c)
918 return;
920 #ifdef __sparc__
921 if (fb->mmaped && (!fb->fb_info.display_fg
922 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
923 return;
924 #endif
926 ram = c->ram;
927 for (y = 0; y < c->size.y; y++) {
928 for (x = 0; x < c->size.x >> 2; x++) {
929 m = c->mask[x][y];
930 b = c->bits[x][y];
931 fb_writeb (cursor_mask_lookup[m >> 4] |
932 cursor_bits_lookup[(b & m) >> 4],
933 ram++);
934 fb_writeb (cursor_mask_lookup[m & 0x0f] |
935 cursor_bits_lookup[(b & m) & 0x0f],
936 ram++);
938 for ( ; x < 8; x++) {
939 fb_writeb (0xaa, ram++);
940 fb_writeb (0xaa, ram++);
943 fb_memset (ram, 0xaa, (64 - c->size.y) * 16);
946 static void
947 aty_set_cursor(struct fb_info_aty *fb, int on)
949 struct atyfb_par *par = &fb->current_par;
950 struct aty_cursor *c = fb->cursor;
951 u16 xoff, yoff;
952 int x, y;
954 if (!c)
955 return;
957 #ifdef __sparc__
958 if (fb->mmaped && (!fb->fb_info.display_fg
959 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
960 return;
961 #endif
963 if (on) {
964 x = c->pos.x - c->hot.x - par->crtc.xoffset;
965 if (x < 0) {
966 xoff = -x;
967 x = 0;
968 } else {
969 xoff = 0;
972 y = c->pos.y - c->hot.y - par->crtc.yoffset;
973 if (y < 0) {
974 yoff = -y;
975 y = 0;
976 } else {
977 yoff = 0;
980 wait_for_fifo(4, fb);
981 aty_st_le32(CUR_OFFSET, (c->offset >> 3) + (yoff << 1), fb);
982 aty_st_le32(CUR_HORZ_VERT_OFF,
983 ((u32)(64 - c->size.y + yoff) << 16) | xoff, fb);
984 aty_st_le32(CUR_HORZ_VERT_POSN, ((u32)y << 16) | x, fb);
985 aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, fb)
986 | HWCURSOR_ENABLE, fb);
987 } else {
988 wait_for_fifo(1, fb);
989 aty_st_le32(GEN_TEST_CNTL,
990 aty_ld_le32(GEN_TEST_CNTL, fb) & ~HWCURSOR_ENABLE,
991 fb);
993 if (fb->blitter_may_be_busy)
994 wait_for_idle(fb);
997 static void
998 aty_cursor_timer_handler(unsigned long dev_addr)
1000 struct fb_info_aty *fb = (struct fb_info_aty *)dev_addr;
1002 if (!fb->cursor)
1003 return;
1005 if (!fb->cursor->enable)
1006 goto out;
1008 if (fb->cursor->vbl_cnt && --fb->cursor->vbl_cnt == 0) {
1009 fb->cursor->on ^= 1;
1010 aty_set_cursor(fb, fb->cursor->on);
1011 fb->cursor->vbl_cnt = fb->cursor->blink_rate;
1014 out:
1015 fb->cursor->timer->expires = jiffies + (HZ / 50);
1016 add_timer(fb->cursor->timer);
1019 static void
1020 atyfb_cursor(struct display *p, int mode, int x, int y)
1022 struct fb_info_aty *fb = (struct fb_info_aty *)p->fb_info;
1023 struct aty_cursor *c = fb->cursor;
1025 if (!c)
1026 return;
1028 #ifdef __sparc__
1029 if (fb->mmaped && (!fb->fb_info.display_fg
1030 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
1031 return;
1032 #endif
1034 x *= fontwidth(p);
1035 y *= fontheight(p);
1036 if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->enable)
1037 return;
1039 c->enable = 0;
1040 if (c->on)
1041 aty_set_cursor(fb, 0);
1042 c->pos.x = x;
1043 c->pos.y = y;
1045 switch (mode) {
1046 case CM_ERASE:
1047 c->on = 0;
1048 break;
1050 case CM_DRAW:
1051 case CM_MOVE:
1052 if (c->on)
1053 aty_set_cursor(fb, 1);
1054 else
1055 c->vbl_cnt = CURSOR_DRAW_DELAY;
1056 c->enable = 1;
1057 break;
1061 static struct fb_info_aty *fb_list = NULL;
1063 static struct aty_cursor * __init
1064 aty_init_cursor(struct fb_info_aty *fb)
1066 struct aty_cursor *cursor;
1067 unsigned long addr;
1069 cursor = kmalloc(sizeof(struct aty_cursor), GFP_ATOMIC);
1070 if (!cursor)
1071 return 0;
1072 memset(cursor, 0, sizeof(*cursor));
1074 cursor->timer = kmalloc(sizeof(*cursor->timer), GFP_KERNEL);
1075 if (!cursor->timer) {
1076 kfree(cursor);
1077 return 0;
1079 memset(cursor->timer, 0, sizeof(*cursor->timer));
1081 cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE;
1082 fb->total_vram -= PAGE_SIZE;
1083 cursor->offset = fb->total_vram;
1085 #ifdef __sparc__
1086 addr = fb->frame_buffer - 0x800000 + cursor->offset;
1087 cursor->ram = (u8 *)addr;
1088 #else
1089 #ifdef __BIG_ENDIAN
1090 addr = fb->frame_buffer_phys - 0x800000 + cursor->offset;
1091 cursor->ram = (u8 *)ioremap(addr, 1024);
1092 #else
1093 addr = fb->frame_buffer + cursor->offset;
1094 cursor->ram = (u8 *)addr;
1095 #endif
1096 #endif
1098 if (! cursor->ram) {
1099 kfree(cursor);
1100 return NULL;
1103 if (curblink) {
1104 init_timer(cursor->timer);
1105 cursor->timer->expires = jiffies + (HZ / 50);
1106 cursor->timer->data = (unsigned long)fb;
1107 cursor->timer->function = aty_cursor_timer_handler;
1108 add_timer(cursor->timer);
1111 return cursor;
1114 static int
1115 atyfb_set_font(struct display *d, int width, int height)
1117 struct fb_info_aty *fb = (struct fb_info_aty *)d->fb_info;
1118 struct aty_cursor *c = fb->cursor;
1119 int i, j;
1121 if (c) {
1122 if (!width || !height) {
1123 width = 8;
1124 height = 16;
1127 c->hot.x = 0;
1128 c->hot.y = 0;
1129 c->size.x = width;
1130 c->size.y = height;
1132 memset(c->bits, 0xff, sizeof(c->bits));
1133 memset(c->mask, 0, sizeof(c->mask));
1135 for (i = 0, j = width; j >= 0; j -= 8, i++) {
1136 c->mask[i][height-2] = (j >= 8) ? 0xff : (0xff << (8 - j));
1137 c->mask[i][height-1] = (j >= 8) ? 0xff : (0xff << (8 - j));
1140 aty_set_cursor_color(fb, cursor_pixel_map, cursor_color_map,
1141 cursor_color_map, cursor_color_map);
1142 aty_set_cursor_shape(fb);
1144 return 1;
1150 /* ------------------------------------------------------------------------- */
1153 * CRTC programming
1156 static void aty_set_crtc(const struct fb_info_aty *info,
1157 const struct crtc *crtc)
1159 aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, info);
1160 aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, info);
1161 aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_tot_disp, info);
1162 aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid, info);
1163 aty_st_le32(CRTC_VLINE_CRNT_VLINE, 0, info);
1164 aty_st_le32(CRTC_OFF_PITCH, crtc->off_pitch, info);
1165 aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl, info);
1168 static int aty_var_to_crtc(const struct fb_info_aty *info,
1169 const struct fb_var_screeninfo *var,
1170 struct crtc *crtc)
1172 u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
1173 u32 left, right, upper, lower, hslen, vslen, sync, vmode;
1174 u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
1175 u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
1176 u32 pix_width, dp_pix_width, dp_chain_mask;
1178 /* input */
1179 xres = var->xres;
1180 yres = var->yres;
1181 vxres = var->xres_virtual;
1182 vyres = var->yres_virtual;
1183 xoffset = var->xoffset;
1184 yoffset = var->yoffset;
1185 bpp = var->bits_per_pixel;
1186 left = var->left_margin;
1187 right = var->right_margin;
1188 upper = var->upper_margin;
1189 lower = var->lower_margin;
1190 hslen = var->hsync_len;
1191 vslen = var->vsync_len;
1192 sync = var->sync;
1193 vmode = var->vmode;
1195 /* convert (and round up) and validate */
1196 xres = (xres+7) & ~7;
1197 xoffset = (xoffset+7) & ~7;
1198 vxres = (vxres+7) & ~7;
1199 if (vxres < xres+xoffset)
1200 vxres = xres+xoffset;
1201 h_disp = xres/8-1;
1202 if (h_disp > 0xff)
1203 FAIL("h_disp too large");
1204 h_sync_strt = h_disp+(right/8);
1205 if (h_sync_strt > 0x1ff)
1206 FAIL("h_sync_start too large");
1207 h_sync_dly = right & 7;
1208 h_sync_wid = (hslen+7)/8;
1209 if (h_sync_wid > 0x1f)
1210 FAIL("h_sync_wid too large");
1211 h_total = h_sync_strt+h_sync_wid+(h_sync_dly+left+7)/8;
1212 if (h_total > 0x1ff)
1213 FAIL("h_total too large");
1214 h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
1216 if (vyres < yres+yoffset)
1217 vyres = yres+yoffset;
1218 v_disp = yres-1;
1219 if (v_disp > 0x7ff)
1220 FAIL("v_disp too large");
1221 v_sync_strt = v_disp+lower;
1222 if (v_sync_strt > 0x7ff)
1223 FAIL("v_sync_strt too large");
1224 v_sync_wid = vslen;
1225 if (v_sync_wid > 0x1f)
1226 FAIL("v_sync_wid too large");
1227 v_total = v_sync_strt+v_sync_wid+upper;
1228 if (v_total > 0x7ff)
1229 FAIL("v_total too large");
1230 v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
1232 c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;
1234 if (bpp <= 8) {
1235 bpp = 8;
1236 pix_width = CRTC_PIX_WIDTH_8BPP;
1237 dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB;
1238 dp_chain_mask = 0x8080;
1239 } else if (bpp <= 16) {
1240 bpp = 16;
1241 pix_width = CRTC_PIX_WIDTH_15BPP;
1242 dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP |
1243 BYTE_ORDER_LSB_TO_MSB;
1244 dp_chain_mask = 0x4210;
1245 } else if ((bpp <= 24) && (Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
1246 bpp = 24;
1247 pix_width = CRTC_PIX_WIDTH_24BPP;
1248 dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB;
1249 dp_chain_mask = 0x8080;
1250 } else if (bpp <= 32) {
1251 bpp = 32;
1252 pix_width = CRTC_PIX_WIDTH_32BPP;
1253 dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP |
1254 BYTE_ORDER_LSB_TO_MSB;
1255 dp_chain_mask = 0x8080;
1256 } else
1257 FAIL("invalid bpp");
1259 if (vxres*vyres*bpp/8 > info->total_vram)
1260 FAIL("not enough video RAM");
1262 if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
1263 FAIL("invalid vmode");
1265 /* output */
1266 crtc->vxres = vxres;
1267 crtc->vyres = vyres;
1268 crtc->xoffset = xoffset;
1269 crtc->yoffset = yoffset;
1270 crtc->bpp = bpp;
1271 crtc->h_tot_disp = h_total | (h_disp<<16);
1272 crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly<<8) |
1273 ((h_sync_strt & 0x100)<<4) | (h_sync_wid<<16) |
1274 (h_sync_pol<<21);
1275 crtc->v_tot_disp = v_total | (v_disp<<16);
1276 crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid<<16) | (v_sync_pol<<21);
1277 crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19);
1278 crtc->gen_cntl = pix_width | c_sync | CRTC_EXT_DISP_EN | CRTC_ENABLE;
1279 if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID) ||
1280 ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07))) {
1281 /* Not VTB/GTB */
1282 /* FIXME: magic FIFO values */
1283 crtc->gen_cntl |= aty_ld_le32(CRTC_GEN_CNTL, info) & 0x000e0000;
1285 crtc->dp_pix_width = dp_pix_width;
1286 crtc->dp_chain_mask = dp_chain_mask;
1288 return 0;
1292 static int aty_set_dac_ATI68860_B(const struct fb_info_aty *info, u32 bpp,
1293 u32 AccelMode)
1295 u32 gModeReg, devSetupRegA, temp, mask;
1297 gModeReg = 0;
1298 devSetupRegA = 0;
1300 switch (bpp) {
1301 case 8:
1302 gModeReg = 0x83;
1303 devSetupRegA = 0x60 | 0x00 /*(info->mach64DAC8Bit ? 0x00 : 0x01) */;
1304 break;
1305 case 15:
1306 gModeReg = 0xA0;
1307 devSetupRegA = 0x60;
1308 break;
1309 case 16:
1310 gModeReg = 0xA1;
1311 devSetupRegA = 0x60;
1312 break;
1313 case 24:
1314 gModeReg = 0xC0;
1315 devSetupRegA = 0x60;
1316 break;
1317 case 32:
1318 gModeReg = 0xE3;
1319 devSetupRegA = 0x60;
1320 break;
1323 if (!AccelMode) {
1324 gModeReg = 0x80;
1325 devSetupRegA = 0x61;
1328 temp = aty_ld_8(DAC_CNTL, info);
1329 aty_st_8(DAC_CNTL, (temp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3, info);
1331 aty_st_8(DAC_REGS + 2, 0x1D, info);
1332 aty_st_8(DAC_REGS + 3, gModeReg, info);
1333 aty_st_8(DAC_REGS, 0x02, info);
1335 temp = aty_ld_8(DAC_CNTL, info);
1336 aty_st_8(DAC_CNTL, temp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, info);
1338 if (info->total_vram < MEM_SIZE_1M)
1339 mask = 0x04;
1340 else if (info->total_vram == MEM_SIZE_1M)
1341 mask = 0x08;
1342 else
1343 mask = 0x0C;
1345 /* The following assumes that the BIOS has correctly set R7 of the
1346 * Device Setup Register A at boot time.
1348 #define A860_DELAY_L 0x80
1350 temp = aty_ld_8(DAC_REGS, info);
1351 aty_st_8(DAC_REGS, (devSetupRegA | mask) | (temp & A860_DELAY_L), info);
1352 temp = aty_ld_8(DAC_CNTL, info);
1353 aty_st_8(DAC_CNTL, (temp & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3)), info);
1355 return 0;
1358 static int aty_set_dac_ATT21C498(const struct fb_info_aty *info,
1359 const struct pll_18818 *pll, u32 bpp)
1361 u32 dotClock;
1362 int muxmode = 0;
1363 int DACMask = 0;
1365 dotClock = 100000000 / pll->period_in_ps;
1367 switch (bpp) {
1368 case 8:
1369 if (dotClock > 8000) {
1370 DACMask = 0x24;
1371 muxmode = 1;
1372 } else
1373 DACMask = 0x04;
1374 break;
1375 case 15:
1376 DACMask = 0x16;
1377 break;
1378 case 16:
1379 DACMask = 0x36;
1380 break;
1381 case 24:
1382 DACMask = 0xE6;
1383 break;
1384 case 32:
1385 DACMask = 0xE6;
1386 break;
1389 if (1 /* info->mach64DAC8Bit */)
1390 DACMask |= 0x02;
1392 aty_dac_waste4(info);
1393 aty_st_8(DAC_REGS + 2, DACMask, info);
1395 return muxmode;
1398 void aty_dac_waste4(const struct fb_info_aty *info)
1400 (void)aty_ld_8(DAC_REGS, info);
1402 (void)aty_ld_8(DAC_REGS + 2, info);
1403 (void)aty_ld_8(DAC_REGS + 2, info);
1404 (void)aty_ld_8(DAC_REGS + 2, info);
1405 (void)aty_ld_8(DAC_REGS + 2, info);
1409 static void aty_set_dac_514(const struct fb_info_aty *info, u32 bpp)
1411 static struct {
1412 u8 pixel_dly;
1413 u8 misc2_cntl;
1414 u8 pixel_rep;
1415 u8 pixel_cntl_index;
1416 u8 pixel_cntl_v1;
1417 } tab[3] = {
1418 { 0, 0x41, 0x03, 0x71, 0x45 }, /* 8 bpp */
1419 { 0, 0x45, 0x04, 0x0c, 0x01 }, /* 555 */
1420 { 0, 0x45, 0x06, 0x0e, 0x00 }, /* XRGB */
1422 int i;
1424 switch (bpp) {
1425 case 8:
1426 default:
1427 i = 0;
1428 break;
1429 case 16:
1430 i = 1;
1431 break;
1432 case 32:
1433 i = 2;
1434 break;
1436 aty_st_514(0x90, 0x00, info); /* VRAM Mask Low */
1437 aty_st_514(0x04, tab[i].pixel_dly, info); /* Horizontal Sync Control */
1438 aty_st_514(0x05, 0x00, info); /* Power Management */
1439 aty_st_514(0x02, 0x01, info); /* Misc Clock Control */
1440 aty_st_514(0x71, tab[i].misc2_cntl, info); /* Misc Control 2 */
1441 aty_st_514(0x0a, tab[i].pixel_rep, info); /* Pixel Format */
1442 aty_st_514(tab[i].pixel_cntl_index, tab[i].pixel_cntl_v1, info);
1443 /* Misc Control 2 / 16 BPP Control / 32 BPP Control */
1446 static int aty_crtc_to_var(const struct crtc *crtc,
1447 struct fb_var_screeninfo *var)
1449 u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync;
1450 u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
1451 u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
1452 u32 pix_width;
1454 /* input */
1455 h_total = crtc->h_tot_disp & 0x1ff;
1456 h_disp = (crtc->h_tot_disp>>16) & 0xff;
1457 h_sync_strt = (crtc->h_sync_strt_wid & 0xff) |
1458 ((crtc->h_sync_strt_wid>>4) & 0x100);
1459 h_sync_dly = (crtc->h_sync_strt_wid>>8) & 0x7;
1460 h_sync_wid = (crtc->h_sync_strt_wid>>16) & 0x1f;
1461 h_sync_pol = (crtc->h_sync_strt_wid>>21) & 0x1;
1462 v_total = crtc->v_tot_disp & 0x7ff;
1463 v_disp = (crtc->v_tot_disp>>16) & 0x7ff;
1464 v_sync_strt = crtc->v_sync_strt_wid & 0x7ff;
1465 v_sync_wid = (crtc->v_sync_strt_wid>>16) & 0x1f;
1466 v_sync_pol = (crtc->v_sync_strt_wid>>21) & 0x1;
1467 c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
1468 pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
1470 /* convert */
1471 xres = (h_disp+1)*8;
1472 yres = v_disp+1;
1473 left = (h_total-h_sync_strt-h_sync_wid)*8-h_sync_dly;
1474 right = (h_sync_strt-h_disp)*8+h_sync_dly;
1475 hslen = h_sync_wid*8;
1476 upper = v_total-v_sync_strt-v_sync_wid;
1477 lower = v_sync_strt-v_disp;
1478 vslen = v_sync_wid;
1479 sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) |
1480 (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
1481 (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
1483 switch (pix_width) {
1484 #if 0
1485 case CRTC_PIX_WIDTH_4BPP:
1486 bpp = 4;
1487 var->red.offset = 0;
1488 var->red.length = 8;
1489 var->green.offset = 0;
1490 var->green.length = 8;
1491 var->blue.offset = 0;
1492 var->blue.length = 8;
1493 var->transp.offset = 0;
1494 var->transp.length = 0;
1495 break;
1496 #endif
1497 case CRTC_PIX_WIDTH_8BPP:
1498 bpp = 8;
1499 var->red.offset = 0;
1500 var->red.length = 8;
1501 var->green.offset = 0;
1502 var->green.length = 8;
1503 var->blue.offset = 0;
1504 var->blue.length = 8;
1505 var->transp.offset = 0;
1506 var->transp.length = 0;
1507 break;
1508 case CRTC_PIX_WIDTH_15BPP: /* RGB 555 */
1509 bpp = 16;
1510 var->red.offset = 10;
1511 var->red.length = 5;
1512 var->green.offset = 5;
1513 var->green.length = 5;
1514 var->blue.offset = 0;
1515 var->blue.length = 5;
1516 var->transp.offset = 0;
1517 var->transp.length = 0;
1518 break;
1519 #if 0
1520 case CRTC_PIX_WIDTH_16BPP: /* RGB 565 */
1521 bpp = 16;
1522 var->red.offset = 11;
1523 var->red.length = 5;
1524 var->green.offset = 5;
1525 var->green.length = 6;
1526 var->blue.offset = 0;
1527 var->blue.length = 5;
1528 var->transp.offset = 0;
1529 var->transp.length = 0;
1530 break;
1531 #endif
1532 case CRTC_PIX_WIDTH_24BPP: /* RGB 888 */
1533 bpp = 24;
1534 var->red.offset = 16;
1535 var->red.length = 8;
1536 var->green.offset = 8;
1537 var->green.length = 8;
1538 var->blue.offset = 0;
1539 var->blue.length = 8;
1540 var->transp.offset = 0;
1541 var->transp.length = 0;
1542 break;
1543 case CRTC_PIX_WIDTH_32BPP: /* ARGB 8888 */
1544 bpp = 32;
1545 var->red.offset = 16;
1546 var->red.length = 8;
1547 var->green.offset = 8;
1548 var->green.length = 8;
1549 var->blue.offset = 0;
1550 var->blue.length = 8;
1551 var->transp.offset = 24;
1552 var->transp.length = 8;
1553 break;
1554 default:
1555 FAIL("Invalid pixel width");
1558 /* output */
1559 var->xres = xres;
1560 var->yres = yres;
1561 var->xres_virtual = crtc->vxres;
1562 var->yres_virtual = crtc->vyres;
1563 var->bits_per_pixel = bpp;
1564 var->xoffset = crtc->xoffset;
1565 var->yoffset = crtc->yoffset;
1566 var->left_margin = left;
1567 var->right_margin = right;
1568 var->upper_margin = upper;
1569 var->lower_margin = lower;
1570 var->hsync_len = hslen;
1571 var->vsync_len = vslen;
1572 var->sync = sync;
1573 var->vmode = FB_VMODE_NONINTERLACED;
1575 return 0;
1578 /* ------------------------------------------------------------------------- */
1581 * PLL programming (Mach64 GX family)
1583 * FIXME: use function pointer tables instead of switch statements
1586 static void aty_set_pll_gx(const struct fb_info_aty *info,
1587 const struct pll_gx *pll)
1589 switch (info->clk_type) {
1590 case CLK_ATI18818_1:
1591 aty_st_8(CLOCK_CNTL, pll->m, info);
1592 break;
1593 case CLK_IBMRGB514:
1594 aty_st_514(0x06, 0x02, info); /* DAC Operation */
1595 aty_st_514(0x10, 0x01, info); /* PLL Control 1 */
1596 aty_st_514(0x70, 0x01, info); /* Misc Control 1 */
1597 aty_st_514(0x8f, 0x1f, info); /* PLL Ref. Divider Input */
1598 aty_st_514(0x03, 0x00, info); /* Sync Control */
1599 aty_st_514(0x05, 0x00, info); /* Power Management */
1600 aty_st_514(0x20, pll->m, info); /* F0 / M0 */
1601 aty_st_514(0x21, pll->n, info); /* F1 / N0 */
1602 break;
1607 static int aty_var_to_pll_18818(u32 period_in_ps, struct pll_18818 *pll)
1609 u32 MHz100; /* in 0.01 MHz */
1610 u32 program_bits;
1611 u32 post_divider;
1613 /* Calculate the programming word */
1614 MHz100 = 100000000 / period_in_ps;
1616 program_bits = -1;
1617 post_divider = 1;
1619 if (MHz100 > MAX_FREQ_2595) {
1620 MHz100 = MAX_FREQ_2595;
1621 return -EINVAL;
1622 } else if (MHz100 < ABS_MIN_FREQ_2595) {
1623 program_bits = 0; /* MHz100 = 257 */
1624 return -EINVAL;
1625 } else {
1626 while (MHz100 < MIN_FREQ_2595) {
1627 MHz100 *= 2;
1628 post_divider *= 2;
1631 MHz100 *= 1000;
1632 MHz100 = (REF_DIV_2595 * MHz100) / REF_FREQ_2595;
1634 MHz100 += 500; /* + 0.5 round */
1635 MHz100 /= 1000;
1637 if (program_bits == -1) {
1638 program_bits = MHz100 - N_ADJ_2595;
1639 switch (post_divider) {
1640 case 1:
1641 program_bits |= 0x0600;
1642 break;
1643 case 2:
1644 program_bits |= 0x0400;
1645 break;
1646 case 4:
1647 program_bits |= 0x0200;
1648 break;
1649 case 8:
1650 default:
1651 break;
1655 program_bits |= STOP_BITS_2595;
1657 pll->program_bits = program_bits;
1658 pll->locationAddr = 0;
1659 pll->post_divider = post_divider;
1660 pll->period_in_ps = period_in_ps;
1662 return 0;
1665 static u32 aty_pll_18818_to_var(const struct pll_18818 *pll)
1667 return(pll->period_in_ps); /* default for now */
1670 static void aty_set_pll18818(const struct fb_info_aty *info,
1671 const struct pll_18818 *pll)
1673 u32 program_bits;
1674 u32 locationAddr;
1676 u32 i;
1678 u8 old_clock_cntl;
1679 u8 old_crtc_ext_disp;
1681 old_clock_cntl = aty_ld_8(CLOCK_CNTL, info);
1682 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info);
1684 old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
1685 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24),
1686 info);
1688 udelay(15000); /* delay for 50 (15) ms */
1690 program_bits = pll->program_bits;
1691 locationAddr = pll->locationAddr;
1693 /* Program the clock chip */
1694 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info); /* Strobe = 0 */
1695 aty_StrobeClock(info);
1696 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 1, info); /* Strobe = 0 */
1697 aty_StrobeClock(info);
1699 aty_ICS2595_put1bit(1, info); /* Send start bits */
1700 aty_ICS2595_put1bit(0, info); /* Start bit */
1701 aty_ICS2595_put1bit(0, info); /* Read / ~Write */
1703 for (i = 0; i < 5; i++) { /* Location 0..4 */
1704 aty_ICS2595_put1bit(locationAddr & 1, info);
1705 locationAddr >>= 1;
1708 for (i = 0; i < 8 + 1 + 2 + 2; i++) {
1709 aty_ICS2595_put1bit(program_bits & 1, info);
1710 program_bits >>= 1;
1713 udelay(1000); /* delay for 1 ms */
1715 (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */
1716 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info);
1717 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, old_clock_cntl | CLOCK_STROBE,
1718 info);
1720 udelay(50000); /* delay for 50 (15) ms */
1721 aty_st_8(CLOCK_CNTL + info->clk_wr_offset,
1722 ((pll->locationAddr & 0x0F) | CLOCK_STROBE), info);
1724 return;
1728 static int aty_var_to_pll_408(u32 period_in_ps, struct pll_18818 *pll)
1730 u32 mhz100; /* in 0.01 MHz */
1731 u32 program_bits;
1732 /* u32 post_divider; */
1733 u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
1734 u32 temp, tempB;
1735 u16 remainder, preRemainder;
1736 short divider = 0, tempA;
1738 /* Calculate the programming word */
1739 mhz100 = 100000000 / period_in_ps;
1740 mach64MinFreq = MIN_FREQ_2595;
1741 mach64MaxFreq = MAX_FREQ_2595;
1742 mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */
1744 /* Calculate program word */
1745 if (mhz100 == 0)
1746 program_bits = 0xFF;
1747 else {
1748 if (mhz100 < mach64MinFreq)
1749 mhz100 = mach64MinFreq;
1750 if (mhz100 > mach64MaxFreq)
1751 mhz100 = mach64MaxFreq;
1753 while (mhz100 < (mach64MinFreq << 3)) {
1754 mhz100 <<= 1;
1755 divider += 0x40;
1758 temp = (unsigned int)mhz100;
1759 temp = (unsigned int)(temp * (MIN_N_408 + 2));
1760 temp -= ((short)(mach64RefFreq << 1));
1762 tempA = MIN_N_408;
1763 preRemainder = 0xFFFF;
1765 do {
1766 tempB = temp;
1767 remainder = tempB % mach64RefFreq;
1768 tempB = tempB / mach64RefFreq;
1769 if (((tempB & 0xFFFF) <= 255) && (remainder <= preRemainder)) {
1770 preRemainder = remainder;
1771 divider &= ~0x3f;
1772 divider |= tempA;
1773 divider = (divider & 0x00FF) + ((tempB & 0xFF) << 8);
1775 temp += mhz100;
1776 tempA++;
1777 } while(tempA <= 32);
1779 program_bits = divider;
1782 pll->program_bits = program_bits;
1783 pll->locationAddr = 0;
1784 pll->post_divider = divider; /* fuer nix */
1785 pll->period_in_ps = period_in_ps;
1787 return 0;
1790 static u32 aty_pll_408_to_var(const struct pll_18818 *pll)
1792 return(pll->period_in_ps); /* default for now */
1795 static void aty_set_pll_408(const struct fb_info_aty *info,
1796 const struct pll_18818 *pll)
1798 u32 program_bits;
1799 u32 locationAddr;
1801 u8 tmpA, tmpB, tmpC;
1802 char old_crtc_ext_disp;
1804 old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
1805 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24),
1806 info);
1808 program_bits = pll->program_bits;
1809 locationAddr = pll->locationAddr;
1811 /* Program clock */
1812 aty_dac_waste4(info);
1813 tmpB = aty_ld_8(DAC_REGS + 2, info) | 1;
1814 aty_dac_waste4(info);
1815 aty_st_8(DAC_REGS + 2, tmpB, info);
1817 tmpA = tmpB;
1818 tmpC = tmpA;
1819 tmpA |= 8;
1820 tmpB = 1;
1822 aty_st_8(DAC_REGS, tmpB, info);
1823 aty_st_8(DAC_REGS + 2, tmpA, info);
1825 udelay(400); /* delay for 400 us */
1827 locationAddr = (locationAddr << 2) + 0x40;
1828 tmpB = locationAddr;
1829 tmpA = program_bits >> 8;
1831 aty_st_8(DAC_REGS, tmpB, info);
1832 aty_st_8(DAC_REGS + 2, tmpA, info);
1834 tmpB = locationAddr + 1;
1835 tmpA = (u8)program_bits;
1837 aty_st_8(DAC_REGS, tmpB, info);
1838 aty_st_8(DAC_REGS + 2, tmpA, info);
1840 tmpB = locationAddr + 2;
1841 tmpA = 0x77;
1843 aty_st_8(DAC_REGS, tmpB, info);
1844 aty_st_8(DAC_REGS + 2, tmpA, info);
1846 udelay(400); /* delay for 400 us */
1847 tmpA = tmpC & (~(1 | 8));
1848 tmpB = 1;
1850 aty_st_8(DAC_REGS, tmpB, info);
1851 aty_st_8(DAC_REGS + 2, tmpA, info);
1853 (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */
1854 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info);
1856 return;
1860 static int aty_var_to_pll_1703(u32 period_in_ps, struct pll_18818 *pll)
1862 u32 mhz100; /* in 0.01 MHz */
1863 u32 program_bits;
1864 /* u32 post_divider; */
1865 u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
1866 u32 temp, tempB;
1867 u16 remainder, preRemainder;
1868 short divider = 0, tempA;
1870 /* Calculate the programming word */
1871 mhz100 = 100000000 / period_in_ps;
1872 mach64MinFreq = MIN_FREQ_2595;
1873 mach64MaxFreq = MAX_FREQ_2595;
1874 mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */
1876 /* Calculate program word */
1877 if (mhz100 == 0)
1878 program_bits = 0xE0;
1879 else {
1880 if (mhz100 < mach64MinFreq)
1881 mhz100 = mach64MinFreq;
1882 if (mhz100 > mach64MaxFreq)
1883 mhz100 = mach64MaxFreq;
1885 divider = 0;
1886 while (mhz100 < (mach64MinFreq << 3)) {
1887 mhz100 <<= 1;
1888 divider += 0x20;
1891 temp = (unsigned int)(mhz100);
1892 temp = (unsigned int)(temp * (MIN_N_1703 + 2));
1893 temp -= (short)(mach64RefFreq << 1);
1895 tempA = MIN_N_1703;
1896 preRemainder = 0xffff;
1898 do {
1899 tempB = temp;
1900 remainder = tempB % mach64RefFreq;
1901 tempB = tempB / mach64RefFreq;
1903 if ((tempB & 0xffff) <= 127 && (remainder <= preRemainder)) {
1904 preRemainder = remainder;
1905 divider &= ~0x1f;
1906 divider |= tempA;
1907 divider = (divider & 0x00ff) + ((tempB & 0xff) << 8);
1910 temp += mhz100;
1911 tempA++;
1912 } while (tempA <= (MIN_N_1703 << 1));
1914 program_bits = divider;
1917 pll->program_bits = program_bits;
1918 pll->locationAddr = 0;
1919 pll->post_divider = divider; /* fuer nix */
1920 pll->period_in_ps = period_in_ps;
1922 return 0;
1925 static u32 aty_pll_1703_to_var(const struct pll_18818 *pll)
1927 return(pll->period_in_ps); /* default for now */
1930 static void aty_set_pll_1703(const struct fb_info_aty *info,
1931 const struct pll_18818 *pll)
1933 u32 program_bits;
1934 u32 locationAddr;
1936 char old_crtc_ext_disp;
1938 old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
1939 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24),
1940 info);
1942 program_bits = pll->program_bits;
1943 locationAddr = pll->locationAddr;
1945 /* Program clock */
1946 aty_dac_waste4(info);
1948 (void)aty_ld_8(DAC_REGS + 2, info);
1949 aty_st_8(DAC_REGS+2, (locationAddr << 1) + 0x20, info);
1950 aty_st_8(DAC_REGS+2, 0, info);
1951 aty_st_8(DAC_REGS+2, (program_bits & 0xFF00) >> 8, info);
1952 aty_st_8(DAC_REGS+2, (program_bits & 0xFF), info);
1954 (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */
1955 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info);
1957 return;
1961 static int aty_var_to_pll_8398(u32 period_in_ps, struct pll_18818 *pll)
1964 u32 tempA, tempB, fOut, longMHz100, diff, preDiff;
1966 u32 mhz100; /* in 0.01 MHz */
1967 u32 program_bits;
1968 /* u32 post_divider; */
1969 u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
1970 u16 m, n, k=0, save_m, save_n, twoToKth;
1972 /* Calculate the programming word */
1973 mhz100 = 100000000 / period_in_ps;
1974 mach64MinFreq = MIN_FREQ_2595;
1975 mach64MaxFreq = MAX_FREQ_2595;
1976 mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */
1978 save_m = 0;
1979 save_n = 0;
1981 /* Calculate program word */
1982 if (mhz100 == 0)
1983 program_bits = 0xE0;
1984 else
1986 if (mhz100 < mach64MinFreq)
1987 mhz100 = mach64MinFreq;
1988 if (mhz100 > mach64MaxFreq)
1989 mhz100 = mach64MaxFreq;
1991 longMHz100 = mhz100 * 256 / 100; /* 8 bit scale this */
1993 while (mhz100 < (mach64MinFreq << 3))
1995 mhz100 <<= 1;
1996 k++;
1999 twoToKth = 1 << k;
2000 diff = 0;
2001 preDiff = 0xFFFFFFFF;
2003 for (m = MIN_M; m <= MAX_M; m++)
2005 for (n = MIN_N; n <= MAX_N; n++)
2007 tempA = (14.31818 * 65536);
2008 tempA *= (n + 8); /* 43..256 */
2009 tempB = twoToKth * 256;
2010 tempB *= (m + 2); /* 4..32 */
2011 fOut = tempA / tempB; /* 8 bit scale */
2013 if (longMHz100 > fOut)
2014 diff = longMHz100 - fOut;
2015 else
2016 diff = fOut - longMHz100;
2018 if (diff < preDiff)
2020 save_m = m;
2021 save_n = n;
2022 preDiff = diff;
2027 program_bits = (k << 6) + (save_m) + (save_n << 8);
2030 pll->program_bits = program_bits;
2031 pll->locationAddr = 0;
2032 pll->post_divider = 0;
2033 pll->period_in_ps = period_in_ps;
2035 return 0;
2038 static u32 aty_pll_8398_to_var(const struct pll_18818 *pll)
2040 return(pll->period_in_ps); /* default for now */
2043 static void aty_set_pll_8398(const struct fb_info_aty *info,
2044 const struct pll_18818 *pll)
2046 u32 program_bits;
2047 u32 locationAddr;
2049 char old_crtc_ext_disp;
2050 char tmp;
2052 old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
2053 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24),
2054 info);
2056 program_bits = pll->program_bits;
2057 locationAddr = pll->locationAddr;
2059 /* Program clock */
2060 tmp = aty_ld_8(DAC_CNTL, info);
2061 aty_st_8(DAC_CNTL, tmp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, info);
2063 aty_st_8(DAC_REGS, locationAddr, info);
2064 aty_st_8(DAC_REGS+1, (program_bits & 0xff00) >> 8, info);
2065 aty_st_8(DAC_REGS+1, (program_bits & 0xff), info);
2067 tmp = aty_ld_8(DAC_CNTL, info);
2068 aty_st_8(DAC_CNTL, (tmp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3, info);
2070 (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */
2071 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info);
2073 return;
2077 static int aty_var_to_pll_514(u32 vclk_per, struct pll_gx *pll)
2080 * FIXME: use real calculations instead of using fixed values from the old
2081 * driver
2083 static struct {
2084 u32 limit; /* pixlock rounding limit (arbitrary) */
2085 u8 m; /* (df<<6) | vco_div_count */
2086 u8 n; /* ref_div_count */
2087 } RGB514_clocks[7] = {
2088 { 8000, (3<<6) | 20, 9 }, /* 7395 ps / 135.2273 MHz */
2089 { 10000, (1<<6) | 19, 3 }, /* 9977 ps / 100.2273 MHz */
2090 { 13000, (1<<6) | 2, 3 }, /* 12509 ps / 79.9432 MHz */
2091 { 14000, (2<<6) | 8, 7 }, /* 13394 ps / 74.6591 MHz */
2092 { 16000, (1<<6) | 44, 6 }, /* 15378 ps / 65.0284 MHz */
2093 { 25000, (1<<6) | 15, 5 }, /* 17460 ps / 57.2727 MHz */
2094 { 50000, (0<<6) | 53, 7 }, /* 33145 ps / 30.1705 MHz */
2096 int i;
2098 for (i = 0; i < sizeof(RGB514_clocks)/sizeof(*RGB514_clocks); i++)
2099 if (vclk_per <= RGB514_clocks[i].limit) {
2100 pll->m = RGB514_clocks[i].m;
2101 pll->n = RGB514_clocks[i].n;
2102 return 0;
2104 return -EINVAL;
2108 static void aty_StrobeClock(const struct fb_info_aty *info)
2110 u8 tmp;
2112 udelay(26);
2114 tmp = aty_ld_8(CLOCK_CNTL, info);
2115 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, tmp | CLOCK_STROBE, info);
2117 return;
2121 static void aty_ICS2595_put1bit(u8 data, const struct fb_info_aty *info)
2123 u8 tmp;
2125 data &= 0x01;
2126 tmp = aty_ld_8(CLOCK_CNTL, info);
2127 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, (tmp & ~0x04) | (data << 2),
2128 info);
2130 tmp = aty_ld_8(CLOCK_CNTL, info);
2131 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, (tmp & ~0x08) | (0 << 3), info);
2133 aty_StrobeClock(info);
2135 tmp = aty_ld_8(CLOCK_CNTL, info);
2136 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, (tmp & ~0x08) | (1 << 3), info);
2138 aty_StrobeClock(info);
2140 return;
2144 static u32 aty_pll_gx_to_var(const struct pll_gx *pll,
2145 const struct fb_info_aty *info)
2147 u8 df, vco_div_count, ref_div_count;
2149 df = pll->m >> 6;
2150 vco_div_count = pll->m & 0x3f;
2151 ref_div_count = pll->n;
2153 return ((info->ref_clk_per*ref_div_count)<<(3-df))/(vco_div_count+65);
2158 * PLL programming (Mach64 CT family)
2161 static void aty_set_pll_ct(const struct fb_info_aty *info,
2162 const struct pll_ct *pll)
2164 aty_st_pll(PLL_REF_DIV, pll->pll_ref_div, info);
2165 aty_st_pll(PLL_GEN_CNTL, pll->pll_gen_cntl, info);
2166 aty_st_pll(MCLK_FB_DIV, pll->mclk_fb_div, info);
2167 aty_st_pll(PLL_VCLK_CNTL, pll->pll_vclk_cntl, info);
2168 aty_st_pll(VCLK_POST_DIV, pll->vclk_post_div, info);
2169 aty_st_pll(VCLK0_FB_DIV, pll->vclk_fb_div, info);
2170 aty_st_pll(PLL_EXT_CNTL, pll->pll_ext_cntl, info);
2172 if (!(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
2173 Gx == ET_CHIP_ID ||
2174 ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07)))) {
2175 if (info->ram_type >= SDRAM)
2176 aty_st_pll(DLL_CNTL, 0xa6, info);
2177 else
2178 aty_st_pll(DLL_CNTL, 0xa0, info);
2179 aty_st_pll(VFC_CNTL, 0x1b, info);
2180 aty_st_le32(DSP_CONFIG, pll->dsp_config, info);
2181 aty_st_le32(DSP_ON_OFF, pll->dsp_on_off, info);
2185 static int aty_dsp_gt(const struct fb_info_aty *info, u8 bpp,
2186 struct pll_ct *pll)
2188 u32 dsp_xclks_per_row, dsp_loop_latency, dsp_precision, dsp_off, dsp_on;
2189 u32 xclks_per_row, fifo_off, fifo_on, y, fifo_size, page_size;
2191 /* xclocks_per_row<<11 */
2192 xclks_per_row = (pll->mclk_fb_div*pll->vclk_post_div_real*64<<11)/
2193 (pll->vclk_fb_div*pll->mclk_post_div_real*bpp);
2194 if (xclks_per_row < (1<<11))
2195 FAIL("Dotclock to high");
2196 if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == VT_CHIP_ID ||
2197 Gx == VU_CHIP_ID || Gx == GV_CHIP_ID || Gx == GW_CHIP_ID ||
2198 Gx == GZ_CHIP_ID) {
2199 fifo_size = 24;
2200 dsp_loop_latency = 0;
2201 } else {
2202 fifo_size = 32;
2203 dsp_loop_latency = 2;
2205 dsp_precision = 0;
2206 y = (xclks_per_row*fifo_size)>>11;
2207 while (y) {
2208 y >>= 1;
2209 dsp_precision++;
2211 dsp_precision -= 5;
2212 /* fifo_off<<6 */
2213 fifo_off = ((xclks_per_row*(fifo_size-1))>>5)+(3<<6);
2215 if (info->total_vram > 1*1024*1024) {
2216 if (info->ram_type >= SDRAM) {
2217 /* >1 MB SDRAM */
2218 dsp_loop_latency += 8;
2219 page_size = 8;
2220 } else {
2221 /* >1 MB DRAM */
2222 dsp_loop_latency += 6;
2223 page_size = 9;
2225 } else {
2226 if (info->ram_type >= SDRAM) {
2227 /* <2 MB SDRAM */
2228 dsp_loop_latency += 9;
2229 page_size = 10;
2230 } else {
2231 /* <2 MB DRAM */
2232 dsp_loop_latency += 8;
2233 page_size = 10;
2236 /* fifo_on<<6 */
2237 if (xclks_per_row >= (page_size<<11))
2238 fifo_on = ((2*page_size+1)<<6)+(xclks_per_row>>5);
2239 else
2240 fifo_on = (3*page_size+2)<<6;
2242 dsp_xclks_per_row = xclks_per_row>>dsp_precision;
2243 dsp_on = fifo_on>>dsp_precision;
2244 dsp_off = fifo_off>>dsp_precision;
2246 pll->dsp_config = (dsp_xclks_per_row & 0x3fff) |
2247 ((dsp_loop_latency & 0xf)<<16) |
2248 ((dsp_precision & 7)<<20);
2249 pll->dsp_on_off = (dsp_on & 0x7ff) | ((dsp_off & 0x7ff)<<16);
2250 return 0;
2253 static int aty_valid_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
2254 struct pll_ct *pll)
2256 u32 q, x; /* x is a workaround for sparc64-linux-gcc */
2257 x = x; /* x is a workaround for sparc64-linux-gcc */
2259 pll->pll_ref_div = info->pll_per*2*255/info->ref_clk_per;
2261 /* FIXME: use the VTB/GTB /3 post divider if it's better suited */
2262 q = info->ref_clk_per*pll->pll_ref_div*4/info->mclk_per; /* actually 8*q */
2263 if (q < 16*8 || q > 255*8)
2264 FAIL("mclk out of range");
2265 else if (q < 32*8)
2266 pll->mclk_post_div_real = 8;
2267 else if (q < 64*8)
2268 pll->mclk_post_div_real = 4;
2269 else if (q < 128*8)
2270 pll->mclk_post_div_real = 2;
2271 else
2272 pll->mclk_post_div_real = 1;
2273 pll->mclk_fb_div = q*pll->mclk_post_div_real/8;
2275 /* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
2276 q = info->ref_clk_per*pll->pll_ref_div*4/vclk_per; /* actually 8*q */
2277 if (q < 16*8 || q > 255*8)
2278 FAIL("vclk out of range");
2279 else if (q < 32*8)
2280 pll->vclk_post_div_real = 8;
2281 else if (q < 64*8)
2282 pll->vclk_post_div_real = 4;
2283 else if (q < 128*8)
2284 pll->vclk_post_div_real = 2;
2285 else
2286 pll->vclk_post_div_real = 1;
2287 pll->vclk_fb_div = q*pll->vclk_post_div_real/8;
2288 return 0;
2291 static void aty_calc_pll_ct(const struct fb_info_aty *info, struct pll_ct *pll)
2293 u8 mpostdiv = 0;
2294 u8 vpostdiv = 0;
2296 if ((((Gx == GT_CHIP_ID) && (Rev & 0x03)) || (Gx == GU_CHIP_ID) ||
2297 (Gx == GV_CHIP_ID) || (Gx == GW_CHIP_ID) || (Gx == GZ_CHIP_ID) ||
2298 (Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) ||
2299 (Gx == GI_CHIP_ID) || (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID) ||
2300 (Gx == VU_CHIP_ID)) && (info->ram_type >= SDRAM))
2301 pll->pll_gen_cntl = 0x04;
2302 else
2303 pll->pll_gen_cntl = 0x84;
2305 switch (pll->mclk_post_div_real) {
2306 case 1:
2307 mpostdiv = 0;
2308 break;
2309 case 2:
2310 mpostdiv = 1;
2311 break;
2312 case 3:
2313 mpostdiv = 4;
2314 break;
2315 case 4:
2316 mpostdiv = 2;
2317 break;
2318 case 8:
2319 mpostdiv = 3;
2320 break;
2322 pll->pll_gen_cntl |= mpostdiv<<4; /* mclk */
2324 if (Gx == VT_CHIP_ID && (Rev == 0x40 || Rev == 0x48))
2325 pll->pll_ext_cntl = 0;
2326 else
2327 pll->pll_ext_cntl = mpostdiv; /* xclk == mclk */
2329 switch (pll->vclk_post_div_real) {
2330 case 2:
2331 vpostdiv = 1;
2332 break;
2333 case 3:
2334 pll->pll_ext_cntl |= 0x10;
2335 case 1:
2336 vpostdiv = 0;
2337 break;
2338 case 6:
2339 pll->pll_ext_cntl |= 0x10;
2340 case 4:
2341 vpostdiv = 2;
2342 break;
2343 case 12:
2344 pll->pll_ext_cntl |= 0x10;
2345 case 8:
2346 vpostdiv = 3;
2347 break;
2350 pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */
2351 pll->vclk_post_div = vpostdiv;
2354 static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
2355 u8 bpp, struct pll_ct *pll)
2357 int err;
2359 if ((err = aty_valid_pll_ct(info, vclk_per, pll)))
2360 return err;
2361 if (!(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
2362 Gx == ET_CHIP_ID ||
2363 ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07)))) {
2364 if ((err = aty_dsp_gt(info, bpp, pll)))
2365 return err;
2367 aty_calc_pll_ct(info, pll);
2368 return 0;
2371 static u32 aty_pll_ct_to_var(const struct pll_ct *pll,
2372 const struct fb_info_aty *info)
2374 u32 ref_clk_per = info->ref_clk_per;
2375 u8 pll_ref_div = pll->pll_ref_div;
2376 u8 vclk_fb_div = pll->vclk_fb_div;
2377 u8 vclk_post_div = pll->vclk_post_div_real;
2379 return ref_clk_per*pll_ref_div*vclk_post_div/vclk_fb_div/2;
2382 /* ------------------------------------------------------------------------- */
2384 static void atyfb_set_par(const struct atyfb_par *par,
2385 struct fb_info_aty *info)
2387 u32 i;
2388 int accelmode;
2389 int muxmode;
2390 u8 tmp;
2392 accelmode = par->accel_flags; /* hack */
2394 info->current_par = *par;
2396 if (info->blitter_may_be_busy)
2397 wait_for_idle(info);
2398 tmp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
2399 aty_set_crtc(info, &par->crtc);
2400 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info);
2401 /* better call aty_StrobeClock ?? */
2402 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, CLOCK_STROBE, info);
2404 if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID)) {
2405 switch (info->dac_subtype) {
2406 case DAC_IBMRGB514:
2407 aty_set_dac_514(info, par->crtc.bpp);
2408 break;
2409 case DAC_ATI68860_B:
2410 case DAC_ATI68860_C:
2411 muxmode = aty_set_dac_ATI68860_B(info, par->crtc.bpp,
2412 accelmode);
2413 aty_st_le32(BUS_CNTL, 0x890e20f1, info);
2414 aty_st_le32(DAC_CNTL, 0x47052100, info);
2415 break;
2416 case DAC_ATT20C408:
2417 muxmode = aty_set_dac_ATT21C498(info, &par->pll.ics2595,
2418 par->crtc.bpp);
2419 aty_st_le32(BUS_CNTL, 0x890e20f1, info);
2420 aty_st_le32(DAC_CNTL, 0x00072000, info);
2421 break;
2422 case DAC_ATT21C498:
2423 muxmode = aty_set_dac_ATT21C498(info, &par->pll.ics2595,
2424 par->crtc.bpp);
2425 aty_st_le32(BUS_CNTL, 0x890e20f1, info);
2426 aty_st_le32(DAC_CNTL, 0x00072000, info);
2427 break;
2428 default:
2429 printk(" atyfb_set_par: DAC type not implemented yet!\n");
2430 aty_st_le32(BUS_CNTL, 0x890e20f1, info);
2431 aty_st_le32(DAC_CNTL, 0x47052100, info);
2432 /* new in 2.2.3p1 from Geert. ???????? */
2433 aty_st_le32(BUS_CNTL, 0x590e10ff, info);
2434 aty_st_le32(DAC_CNTL, 0x47012100, info);
2435 break;
2438 switch (info->clk_type) {
2439 case CLK_ATI18818_1:
2440 aty_set_pll18818(info, &par->pll.ics2595);
2441 break;
2442 case CLK_STG1703:
2443 aty_set_pll_1703(info, &par->pll.ics2595);
2444 break;
2445 case CLK_CH8398:
2446 aty_set_pll_8398(info, &par->pll.ics2595);
2447 break;
2448 case CLK_ATT20C408:
2449 aty_set_pll_408(info, &par->pll.ics2595);
2450 break;
2451 case CLK_IBMRGB514:
2452 aty_set_pll_gx(info, &par->pll.gx);
2453 break;
2454 default:
2455 printk(" atyfb_set_par: CLK type not implemented yet!");
2456 break;
2459 /* Don't forget MEM_CNTL */
2460 i = aty_ld_le32(MEM_CNTL, info) & 0xf0ffffff;
2461 switch (par->crtc.bpp) {
2462 case 8:
2463 i |= 0x02000000;
2464 break;
2465 case 16:
2466 i |= 0x03000000;
2467 break;
2468 case 32:
2469 i |= 0x06000000;
2470 break;
2472 aty_st_le32(MEM_CNTL, i, info);
2474 } else {
2475 aty_set_pll_ct(info, &par->pll.ct);
2476 i = aty_ld_le32(MEM_CNTL, info) & 0xf00fffff;
2477 if (!(Gx == VT_CHIP_ID && (Rev == 0x40 || Rev == 0x48)))
2478 i |= info->mem_refresh_rate << 20;
2479 switch (par->crtc.bpp) {
2480 case 8:
2481 case 24:
2482 i |= 0x00000000;
2483 break;
2484 case 16:
2485 i |= 0x04000000;
2486 break;
2487 case 32:
2488 i |= 0x08000000;
2489 break;
2491 if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID)) {
2492 aty_st_le32(DAC_CNTL, 0x87010184, info);
2493 aty_st_le32(BUS_CNTL, 0x680000f9, info);
2494 } else if ((Gx == VT_CHIP_ID) || (Gx == VU_CHIP_ID)) {
2495 aty_st_le32(DAC_CNTL, 0x87010184, info);
2496 aty_st_le32(BUS_CNTL, 0x680000f9, info);
2497 } else {
2498 /* GT */
2499 aty_st_le32(DAC_CNTL, 0x86010102, info);
2500 aty_st_le32(BUS_CNTL, 0x7b23a040, info);
2501 aty_st_le32(EXT_MEM_CNTL,
2502 aty_ld_le32(EXT_MEM_CNTL, info) | 0x5000001, info);
2504 aty_st_le32(MEM_CNTL, i, info);
2506 aty_st_8(DAC_MASK, 0xff, info);
2508 /* Initialize the graphics engine */
2509 if (par->accel_flags & FB_ACCELF_TEXT)
2510 init_engine(par, info);
2512 #ifdef CONFIG_FB_COMPAT_XPMAC
2513 if (!console_fb_info || console_fb_info == &info->fb_info) {
2514 struct fb_var_screeninfo var;
2515 int vmode, cmode;
2516 display_info.height = ((par->crtc.v_tot_disp>>16) & 0x7ff)+1;
2517 display_info.width = (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8;
2518 display_info.depth = par->crtc.bpp;
2519 display_info.pitch = par->crtc.vxres*par->crtc.bpp/8;
2520 atyfb_encode_var(&var, par, info);
2521 if (mac_var_to_vmode(&var, &vmode, &cmode))
2522 display_info.mode = 0;
2523 else
2524 display_info.mode = vmode;
2525 strcpy(display_info.name, atyfb_name);
2526 display_info.fb_address = info->frame_buffer_phys;
2527 display_info.cmap_adr_address = info->ati_regbase_phys+0xc0;
2528 display_info.cmap_data_address = info->ati_regbase_phys+0xc1;
2529 display_info.disp_reg_address = info->ati_regbase_phys;
2531 #endif /* CONFIG_FB_COMPAT_XPMAC */
2534 static int atyfb_decode_var(const struct fb_var_screeninfo *var,
2535 struct atyfb_par *par,
2536 const struct fb_info_aty *info)
2538 int err;
2540 if ((err = aty_var_to_crtc(info, var, &par->crtc)))
2541 return err;
2542 if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID))
2543 switch (info->clk_type) {
2544 case CLK_ATI18818_1:
2545 err = aty_var_to_pll_18818(var->pixclock, &par->pll.ics2595);
2546 break;
2547 case CLK_STG1703:
2548 err = aty_var_to_pll_1703(var->pixclock, &par->pll.ics2595);
2549 break;
2550 case CLK_CH8398:
2551 err = aty_var_to_pll_8398(var->pixclock, &par->pll.ics2595);
2552 break;
2553 case CLK_ATT20C408:
2554 err = aty_var_to_pll_408(var->pixclock, &par->pll.ics2595);
2555 break;
2556 case CLK_IBMRGB514:
2557 err = aty_var_to_pll_514(var->pixclock, &par->pll.gx);
2558 break;
2560 else
2561 err = aty_var_to_pll_ct(info, var->pixclock, par->crtc.bpp,
2562 &par->pll.ct);
2563 if (err)
2564 return err;
2566 if (var->accel_flags & FB_ACCELF_TEXT)
2567 par->accel_flags = FB_ACCELF_TEXT;
2568 else
2569 par->accel_flags = 0;
2571 #if 0 /* fbmon is not done. uncomment for 2.5.x -brad */
2572 if (!fbmon_valid_timings(var->pixclock, htotal, vtotal, info))
2573 return -EINVAL;
2574 #endif
2576 return 0;
2579 static int atyfb_encode_var(struct fb_var_screeninfo *var,
2580 const struct atyfb_par *par,
2581 const struct fb_info_aty *info)
2583 int err;
2585 memset(var, 0, sizeof(struct fb_var_screeninfo));
2587 if ((err = aty_crtc_to_var(&par->crtc, var)))
2588 return err;
2589 if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID))
2590 switch (info->clk_type) {
2591 case CLK_ATI18818_1:
2592 var->pixclock = aty_pll_18818_to_var(&par->pll.ics2595);
2593 break;
2594 case CLK_STG1703:
2595 var->pixclock = aty_pll_1703_to_var(&par->pll.ics2595);
2596 break;
2597 case CLK_CH8398:
2598 var->pixclock = aty_pll_8398_to_var(&par->pll.ics2595);
2599 break;
2600 case CLK_ATT20C408:
2601 var->pixclock = aty_pll_408_to_var(&par->pll.ics2595);
2602 break;
2603 case CLK_IBMRGB514:
2604 var->pixclock = aty_pll_gx_to_var(&par->pll.gx, info);
2605 break;
2607 else
2608 var->pixclock = aty_pll_ct_to_var(&par->pll.ct, info);
2610 var->height = -1;
2611 var->width = -1;
2612 var->accel_flags = par->accel_flags;
2614 return 0;
2619 static void set_off_pitch(struct atyfb_par *par,
2620 const struct fb_info_aty *info)
2622 u32 xoffset = par->crtc.xoffset;
2623 u32 yoffset = par->crtc.yoffset;
2624 u32 vxres = par->crtc.vxres;
2625 u32 bpp = par->crtc.bpp;
2627 par->crtc.off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19);
2628 aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, info);
2633 * Open/Release the frame buffer device
2636 static int atyfb_open(struct fb_info *info, int user)
2639 #ifdef __sparc__
2640 struct fb_info_aty *fb = (struct fb_info_aty *)info;
2642 if (user) {
2643 fb->open++;
2644 fb->mmaped = 0;
2645 fb->vtconsole = -1;
2646 } else {
2647 fb->consolecnt++;
2649 #endif
2650 return(0);
2653 struct fb_var_screeninfo default_var = {
2654 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
2655 640, 480, 640, 480, 0, 0, 8, 0,
2656 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
2657 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
2658 0, FB_VMODE_NONINTERLACED
2661 static int atyfb_release(struct fb_info *info, int user)
2663 #ifdef __sparc__
2664 struct fb_info_aty *fb = (struct fb_info_aty *)info;
2666 if (user) {
2667 fb->open--;
2668 udelay(1000);
2669 wait_for_idle(fb);
2670 if (!fb->open) {
2671 int was_mmaped = fb->mmaped;
2673 fb->mmaped = 0;
2674 if (fb->vtconsole != -1)
2675 vt_cons[fb->vtconsole]->vc_mode = KD_TEXT;
2676 fb->vtconsole = -1;
2678 if (was_mmaped) {
2679 struct fb_var_screeninfo var;
2681 /* Now reset the default display config, we have no
2682 * idea what the program(s) which mmap'd the chip did
2683 * to the configuration, nor whether it restored it
2684 * correctly.
2686 var = default_var;
2687 if (noaccel)
2688 var.accel_flags &= ~FB_ACCELF_TEXT;
2689 else
2690 var.accel_flags |= FB_ACCELF_TEXT;
2691 if (var.yres == var.yres_virtual) {
2692 u32 vram = (fb->total_vram - (PAGE_SIZE << 2));
2693 var.yres_virtual = ((vram * 8) / var.bits_per_pixel) /
2694 var.xres_virtual;
2695 if (var.yres_virtual < var.yres)
2696 var.yres_virtual = var.yres;
2698 atyfb_set_var(&var, -1, &fb->fb_info);
2701 } else {
2702 fb->consolecnt--;
2704 #endif
2705 return(0);
2709 static int encode_fix(struct fb_fix_screeninfo *fix,
2710 const struct atyfb_par *par,
2711 const struct fb_info_aty *info)
2713 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
2715 strcpy(fix->id, atyfb_name);
2716 fix->smem_start = info->frame_buffer_phys;
2717 fix->smem_len = (u32)info->total_vram;
2720 * Reg Block 0 (CT-compatible block) is at ati_regbase_phys
2721 * Reg Block 1 (multimedia extensions) is at ati_regbase_phys-0x400
2723 if (Gx == GX_CHIP_ID || Gx == CX_CHIP_ID) {
2724 fix->mmio_start = info->ati_regbase_phys;
2725 fix->mmio_len = 0x400;
2726 fix->accel = FB_ACCEL_ATI_MACH64GX;
2727 } else if (Gx == CT_CHIP_ID || Gx == ET_CHIP_ID) {
2728 fix->mmio_start = info->ati_regbase_phys;
2729 fix->mmio_len = 0x400;
2730 fix->accel = FB_ACCEL_ATI_MACH64CT;
2731 } else if (Gx == VT_CHIP_ID || Gx == VU_CHIP_ID || Gx == VV_CHIP_ID) {
2732 fix->mmio_start = info->ati_regbase_phys-0x400;
2733 fix->mmio_len = 0x800;
2734 fix->accel = FB_ACCEL_ATI_MACH64VT;
2735 } else {
2736 fix->mmio_start = info->ati_regbase_phys-0x400;
2737 fix->mmio_len = 0x800;
2738 fix->accel = FB_ACCEL_ATI_MACH64GT;
2740 fix->type = FB_TYPE_PACKED_PIXELS;
2741 fix->type_aux = 0;
2742 fix->line_length = par->crtc.vxres*par->crtc.bpp/8;
2743 fix->visual = par->crtc.bpp <= 8 ? FB_VISUAL_PSEUDOCOLOR
2744 : FB_VISUAL_DIRECTCOLOR;
2745 fix->ywrapstep = 0;
2746 fix->xpanstep = 8;
2747 fix->ypanstep = 1;
2749 return 0;
2754 * Get the Fixed Part of the Display
2757 static int atyfb_get_fix(struct fb_fix_screeninfo *fix, int con,
2758 struct fb_info *fb)
2760 const struct fb_info_aty *info = (struct fb_info_aty *)fb;
2761 struct atyfb_par par;
2763 if (con == -1)
2764 par = info->default_par;
2765 else
2766 atyfb_decode_var(&fb_display[con].var, &par, info);
2767 encode_fix(fix, &par, info);
2768 return 0;
2773 * Get the User Defined Part of the Display
2776 static int atyfb_get_var(struct fb_var_screeninfo *var, int con,
2777 struct fb_info *fb)
2779 const struct fb_info_aty *info = (struct fb_info_aty *)fb;
2781 if (con == -1)
2782 atyfb_encode_var(var, &info->default_par, info);
2783 else
2784 *var = fb_display[con].var;
2785 return 0;
2789 static void atyfb_set_disp(struct display *disp, struct fb_info_aty *info,
2790 int bpp, int accel)
2792 switch (bpp) {
2793 #ifdef FBCON_HAS_CFB8
2794 case 8:
2795 info->dispsw = accel ? fbcon_aty8 : fbcon_cfb8;
2796 disp->dispsw = &info->dispsw;
2797 break;
2798 #endif
2799 #ifdef FBCON_HAS_CFB16
2800 case 16:
2801 info->dispsw = accel ? fbcon_aty16 : fbcon_cfb16;
2802 disp->dispsw = &info->dispsw;
2803 disp->dispsw_data = info->fbcon_cmap.cfb16;
2804 break;
2805 #endif
2806 #ifdef FBCON_HAS_CFB24
2807 case 24:
2808 info->dispsw = accel ? fbcon_aty24 : fbcon_cfb24;
2809 disp->dispsw = &info->dispsw;
2810 disp->dispsw_data = info->fbcon_cmap.cfb24;
2811 break;
2812 #endif
2813 #ifdef FBCON_HAS_CFB32
2814 case 32:
2815 info->dispsw = accel ? fbcon_aty32 : fbcon_cfb32;
2816 disp->dispsw = &info->dispsw;
2817 disp->dispsw_data = info->fbcon_cmap.cfb32;
2818 break;
2819 #endif
2820 default:
2821 disp->dispsw = &fbcon_dummy;
2823 if (info->cursor) {
2824 info->dispsw.cursor = atyfb_cursor;
2825 info->dispsw.set_font = atyfb_set_font;
2831 * Set the User Defined Part of the Display
2834 static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
2835 struct fb_info *fb)
2837 struct fb_info_aty *info = (struct fb_info_aty *)fb;
2838 struct atyfb_par par;
2839 struct display *display;
2840 int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel, accel, err;
2841 int activate = var->activate;
2843 if (con >= 0)
2844 display = &fb_display[con];
2845 else
2846 display = fb->disp; /* used during initialization */
2848 if ((err = atyfb_decode_var(var, &par, info)))
2849 return err;
2851 atyfb_encode_var(var, &par, (struct fb_info_aty *)info);
2853 if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
2854 oldxres = display->var.xres;
2855 oldyres = display->var.yres;
2856 oldvxres = display->var.xres_virtual;
2857 oldvyres = display->var.yres_virtual;
2858 oldbpp = display->var.bits_per_pixel;
2859 oldaccel = display->var.accel_flags;
2860 display->var = *var;
2861 if (oldxres != var->xres || oldyres != var->yres ||
2862 oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
2863 oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) {
2864 struct fb_fix_screeninfo fix;
2866 encode_fix(&fix, &par, info);
2867 display->screen_base = (char *)info->frame_buffer;
2868 display->visual = fix.visual;
2869 display->type = fix.type;
2870 display->type_aux = fix.type_aux;
2871 display->ypanstep = fix.ypanstep;
2872 display->ywrapstep = fix.ywrapstep;
2873 display->line_length = fix.line_length;
2874 display->can_soft_blank = 1;
2875 display->inverse = 0;
2876 accel = var->accel_flags & FB_ACCELF_TEXT;
2877 atyfb_set_disp(display, info, par.crtc.bpp, accel);
2878 if (accel)
2879 display->scrollmode = (info->bus_type == PCI) ? SCROLL_YNOMOVE : 0;
2880 else
2881 display->scrollmode = SCROLL_YREDRAW;
2882 if (info->fb_info.changevar)
2883 (*info->fb_info.changevar)(con);
2885 if (!info->fb_info.display_fg ||
2886 info->fb_info.display_fg->vc_num == con)
2887 atyfb_set_par(&par, info);
2888 if (oldbpp != var->bits_per_pixel) {
2889 if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
2890 return err;
2891 do_install_cmap(con, &info->fb_info);
2895 return 0;
2900 * Pan or Wrap the Display
2902 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
2905 static int atyfb_pan_display(struct fb_var_screeninfo *var, int con,
2906 struct fb_info *fb)
2908 struct fb_info_aty *info = (struct fb_info_aty *)fb;
2909 u32 xres, yres, xoffset, yoffset;
2910 struct atyfb_par *par = &info->current_par;
2912 xres = (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8;
2913 yres = ((par->crtc.v_tot_disp>>16) & 0x7ff)+1;
2914 xoffset = (var->xoffset+7) & ~7;
2915 yoffset = var->yoffset;
2916 if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres)
2917 return -EINVAL;
2918 par->crtc.xoffset = xoffset;
2919 par->crtc.yoffset = yoffset;
2920 set_off_pitch(par, info);
2921 return 0;
2925 * Get the Colormap
2928 static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
2929 struct fb_info *info)
2931 if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */
2932 return fb_get_cmap(cmap, kspc, atyfb_getcolreg, info);
2933 else if (fb_display[con].cmap.len) /* non default colormap? */
2934 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
2935 else {
2936 int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
2937 fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
2939 return 0;
2943 * Set the Colormap
2946 static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
2947 struct fb_info *info)
2949 int err;
2950 struct display *disp;
2952 if (con >= 0)
2953 disp = &fb_display[con];
2954 else
2955 disp = info->disp;
2956 if (!disp->cmap.len) { /* no colormap allocated? */
2957 int size = disp->var.bits_per_pixel == 16 ? 32 : 256;
2958 if ((err = fb_alloc_cmap(&disp->cmap, size, 0)))
2959 return err;
2961 if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */
2962 return fb_set_cmap(cmap, kspc, atyfb_setcolreg, info);
2963 else
2964 fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
2965 return 0;
2969 #ifdef DEBUG
2970 #define ATYIO_CLKR 0x41545900 /* ATY\00 */
2971 #define ATYIO_CLKW 0x41545901 /* ATY\01 */
2973 struct atyclk {
2974 u32 ref_clk_per;
2975 u8 pll_ref_div;
2976 u8 mclk_fb_div;
2977 u8 mclk_post_div; /* 1,2,3,4,8 */
2978 u8 vclk_fb_div;
2979 u8 vclk_post_div; /* 1,2,3,4,6,8,12 */
2980 u32 dsp_xclks_per_row; /* 0-16383 */
2981 u32 dsp_loop_latency; /* 0-15 */
2982 u32 dsp_precision; /* 0-7 */
2983 u32 dsp_on; /* 0-2047 */
2984 u32 dsp_off; /* 0-2047 */
2986 #endif
2988 static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
2989 u_long arg, int con, struct fb_info *info2)
2991 #if defined(__sparc__) || defined(DEBUG)
2992 struct fb_info_aty *info = (struct fb_info_aty *)info2;
2993 #endif /* __sparc__ || DEBUG */
2994 #ifdef __sparc__
2995 struct fbtype fbtyp;
2996 struct display *disp;
2998 if (con >= 0)
2999 disp = &fb_display[con];
3000 else
3001 disp = info2->disp;
3002 #endif
3004 switch (cmd) {
3005 #ifdef __sparc__
3006 case FBIOGTYPE:
3007 fbtyp.fb_type = FBTYPE_PCI_GENERIC;
3008 fbtyp.fb_width = info->current_par.crtc.vxres;
3009 fbtyp.fb_height = info->current_par.crtc.vyres;
3010 fbtyp.fb_depth = info->current_par.crtc.bpp;
3011 fbtyp.fb_cmsize = disp->cmap.len;
3012 fbtyp.fb_size = info->total_vram;
3013 copy_to_user_ret((struct fbtype *)arg, &fbtyp, sizeof(fbtyp), -EFAULT);
3014 break;
3015 #endif /* __sparc__ */
3016 #ifdef DEBUG
3017 case ATYIO_CLKR:
3018 if ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
3019 struct atyclk clk;
3020 struct pll_ct *pll = &info->current_par.pll.ct;
3021 u32 dsp_config = pll->dsp_config;
3022 u32 dsp_on_off = pll->dsp_on_off;
3023 clk.ref_clk_per = info->ref_clk_per;
3024 clk.pll_ref_div = pll->pll_ref_div;
3025 clk.mclk_fb_div = pll->mclk_fb_div;
3026 clk.mclk_post_div = pll->mclk_post_div_real;
3027 clk.vclk_fb_div = pll->vclk_fb_div;
3028 clk.vclk_post_div = pll->vclk_post_div_real;
3029 clk.dsp_xclks_per_row = dsp_config & 0x3fff;
3030 clk.dsp_loop_latency = (dsp_config>>16) & 0xf;
3031 clk.dsp_precision = (dsp_config>>20) & 7;
3032 clk.dsp_on = dsp_on_off & 0x7ff;
3033 clk.dsp_off = (dsp_on_off>>16) & 0x7ff;
3034 copy_to_user_ret((struct atyclk *)arg, &clk, sizeof(clk),
3035 -EFAULT);
3036 } else
3037 return -EINVAL;
3038 break;
3039 case ATYIO_CLKW:
3040 if ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
3041 struct atyclk clk;
3042 struct pll_ct *pll = &info->current_par.pll.ct;
3043 copy_from_user_ret(&clk, (struct atyclk *)arg, sizeof(clk),
3044 -EFAULT);
3045 info->ref_clk_per = clk.ref_clk_per;
3046 pll->pll_ref_div = clk.pll_ref_div;
3047 pll->mclk_fb_div = clk.mclk_fb_div;
3048 pll->mclk_post_div_real = clk.mclk_post_div;
3049 pll->vclk_fb_div = clk.vclk_fb_div;
3050 pll->vclk_post_div_real = clk.vclk_post_div;
3051 pll->dsp_config = (clk.dsp_xclks_per_row & 0x3fff) |
3052 ((clk.dsp_loop_latency & 0xf)<<16) |
3053 ((clk.dsp_precision & 7)<<20);
3054 pll->dsp_on_off = (clk.dsp_on & 0x7ff) |
3055 ((clk.dsp_off & 0x7ff)<<16);
3056 aty_calc_pll_ct(info, pll);
3057 aty_set_pll_ct(info, pll);
3058 } else
3059 return -EINVAL;
3060 break;
3061 #endif /* DEBUG */
3062 default:
3063 return -EINVAL;
3065 return 0;
3068 static int atyfb_rasterimg(struct fb_info *info, int start)
3070 struct fb_info_aty *fb = (struct fb_info_aty *)info;
3072 if (fb->blitter_may_be_busy)
3073 wait_for_idle(fb);
3074 return 0;
3077 #ifdef __sparc__
3078 static int atyfb_mmap(struct fb_info *info, struct file *file,
3079 struct vm_area_struct *vma)
3081 struct fb_info_aty *fb = (struct fb_info_aty *)info;
3082 unsigned int size, page, map_size = 0;
3083 unsigned long map_offset = 0;
3084 unsigned long off;
3085 int i;
3087 if (!fb->mmap_map)
3088 return -ENXIO;
3090 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
3091 return -EINVAL;
3093 off = vma->vm_pgoff << PAGE_SHIFT;
3094 size = vma->vm_end - vma->vm_start;
3096 /* To stop the swapper from even considering these pages. */
3097 vma->vm_flags |= (VM_SHM | VM_LOCKED);
3099 if (((vma->vm_pgoff == 0) && (size == fb->total_vram)) ||
3100 ((off == fb->total_vram) && (size == PAGE_SIZE)))
3101 off += 0x8000000000000000UL;
3103 vma->vm_pgoff = off >> PAGE_SHIFT; /* propagate off changes */
3105 #ifdef __sparc_v9__
3106 /* Align it as much as desirable */
3108 unsigned long j, align;
3109 int max = -1;
3111 map_offset = off + size;
3112 for (i = 0; fb->mmap_map[i].size; i++) {
3113 if (fb->mmap_map[i].voff < off)
3114 continue;
3115 if (fb->mmap_map[i].voff >= map_offset)
3116 break;
3117 if (max < 0 ||
3118 fb->mmap_map[i].size > fb->mmap_map[max].size)
3119 max = i;
3121 if (max >= 0) {
3122 j = fb->mmap_map[max].size;
3123 if (fb->mmap_map[max].voff + j > map_offset)
3124 j = map_offset - fb->mmap_map[max].voff;
3125 for (align = 0x400000; align > PAGE_SIZE; align >>= 3)
3126 if (j >= align &&
3127 !(fb->mmap_map[max].poff & (align - 1)))
3128 break;
3129 if (align > PAGE_SIZE) {
3130 j = align;
3131 align = j - ((vma->vm_start
3132 + fb->mmap_map[max].voff
3133 - off) & (j - 1));
3134 if (align != j) {
3135 struct vm_area_struct *vmm;
3137 vmm = find_vma(current->mm,
3138 vma->vm_start);
3139 if (!vmm || vmm->vm_start
3140 >= vma->vm_end + align) {
3141 vma->vm_start += align;
3142 vma->vm_end += align;
3148 #endif
3150 /* Each page, see which map applies */
3151 for (page = 0; page < size; ) {
3152 map_size = 0;
3153 for (i = 0; fb->mmap_map[i].size; i++) {
3154 unsigned long start = fb->mmap_map[i].voff;
3155 unsigned long end = start + fb->mmap_map[i].size;
3156 unsigned long offset = off + page;
3158 if (start > offset)
3159 continue;
3160 if (offset >= end)
3161 continue;
3163 map_size = fb->mmap_map[i].size - (offset - start);
3164 map_offset = fb->mmap_map[i].poff + (offset - start);
3165 break;
3167 if (!map_size) {
3168 page += PAGE_SIZE;
3169 continue;
3171 if (page + map_size > size)
3172 map_size = size - page;
3174 pgprot_val(vma->vm_page_prot) &= ~(fb->mmap_map[i].prot_mask);
3175 pgprot_val(vma->vm_page_prot) |= fb->mmap_map[i].prot_flag;
3177 if (remap_page_range(vma->vm_start + page, map_offset,
3178 map_size, vma->vm_page_prot))
3179 return -EAGAIN;
3181 page += map_size;
3184 if (!map_size)
3185 return -EINVAL;
3187 vma->vm_flags |= VM_IO;
3189 if (!fb->mmaped) {
3190 int lastconsole = 0;
3192 if (info->display_fg)
3193 lastconsole = info->display_fg->vc_num;
3194 fb->mmaped = 1;
3195 if (fb->consolecnt && fb_display[lastconsole].fb_info == info) {
3196 fb->vtconsole = lastconsole;
3197 vt_cons[lastconsole]->vc_mode = KD_GRAPHICS;
3200 return 0;
3203 static struct {
3204 u32 yoffset;
3205 u8 r[2][256];
3206 u8 g[2][256];
3207 u8 b[2][256];
3208 } atyfb_save;
3210 static void atyfb_save_palette(struct fb_info *fb, int enter)
3212 struct fb_info_aty *info = (struct fb_info_aty *)fb;
3213 int i, tmp, scale;
3215 for (i = 0; i < 256; i++) {
3216 tmp = aty_ld_8(DAC_CNTL, info) & 0xfc;
3217 if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == GV_CHIP_ID ||
3218 Gx == GW_CHIP_ID || Gx == GZ_CHIP_ID || Gx == LG_CHIP_ID ||
3219 Gx == GB_CHIP_ID || Gx == GD_CHIP_ID || Gx == GI_CHIP_ID ||
3220 Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID)
3221 tmp |= 0x2;
3222 aty_st_8(DAC_CNTL, tmp, info);
3223 aty_st_8(DAC_MASK, 0xff, info);
3225 scale = ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID) &&
3226 (info->current_par.crtc.bpp == 16)) ? 3 : 0;
3227 writeb(i << scale, &info->aty_cmap_regs->rindex);
3229 atyfb_save.r[enter][i] = readb(&info->aty_cmap_regs->lut);
3230 atyfb_save.g[enter][i] = readb(&info->aty_cmap_regs->lut);
3231 atyfb_save.b[enter][i] = readb(&info->aty_cmap_regs->lut);
3232 writeb(i << scale, &info->aty_cmap_regs->windex);
3233 writeb(atyfb_save.r[1-enter][i], &info->aty_cmap_regs->lut);
3234 writeb(atyfb_save.g[1-enter][i], &info->aty_cmap_regs->lut);
3235 writeb(atyfb_save.b[1-enter][i], &info->aty_cmap_regs->lut);
3239 static void atyfb_palette(int enter)
3241 struct fb_info_aty *info;
3242 struct atyfb_par *par;
3243 struct display *d;
3244 int i;
3246 for (i = 0; i < MAX_NR_CONSOLES; i++) {
3247 d = &fb_display[i];
3248 if (d->fb_info &&
3249 d->fb_info->fbops == &atyfb_ops &&
3250 d->fb_info->display_fg &&
3251 d->fb_info->display_fg->vc_num == i) {
3252 atyfb_save_palette(d->fb_info, enter);
3253 info = (struct fb_info_aty *)d->fb_info;
3254 par = &info->current_par;
3255 if (enter) {
3256 atyfb_save.yoffset = par->crtc.yoffset;
3257 par->crtc.yoffset = 0;
3258 set_off_pitch(par, info);
3259 } else {
3260 par->crtc.yoffset = atyfb_save.yoffset;
3261 set_off_pitch(par, info);
3263 break;
3267 #endif /* __sparc__ */
3270 * Initialisation
3273 static int __init aty_init(struct fb_info_aty *info, const char *name)
3275 u32 chip_id;
3276 u32 i;
3277 int j, k;
3278 struct fb_var_screeninfo var;
3279 struct display *disp;
3280 const char *chipname = NULL, *ramname = NULL, *xtal;
3281 int pll, mclk, gtb_memsize;
3282 #if defined(CONFIG_PPC)
3283 int sense;
3284 #endif
3285 u8 pll_ref_div;
3287 info->aty_cmap_regs = (struct aty_cmap_regs *)(info->ati_regbase+0xc0);
3288 chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
3289 Gx = chip_id & CFG_CHIP_TYPE;
3290 Rev = (chip_id & CFG_CHIP_REV)>>24;
3291 for (j = 0; j < (sizeof(aty_features)/sizeof(*aty_features)); j++)
3292 if (aty_features[j].chip_type == Gx) {
3293 chipname = aty_features[j].name;
3294 info->dac_type = (aty_ld_le32(DAC_CNTL, info) >> 16) & 0x07;
3295 break;
3297 if (!chipname) {
3298 printk("atyfb: Unknown mach64 0x%04x\n", Gx);
3299 return 0;
3300 } else
3301 printk("atyfb: %s [0x%04x rev 0x%02x] ", chipname, Gx, Rev);
3302 if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID)) {
3303 info->bus_type = (aty_ld_le32(CONFIG_STAT0, info) >> 0) & 0x07;
3304 info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) >> 3) & 0x07;
3305 ramname = aty_gx_ram[info->ram_type];
3306 /* FIXME: clockchip/RAMDAC probing? */
3307 #ifdef CONFIG_ATARI
3308 info->clk_type = CLK_ATI18818_1;
3309 info->dac_type = (aty_ld_le32(CONFIG_STAT0, info) >> 9) & 0x07;
3310 if (info->dac_type == 0x07)
3311 info->dac_subtype = DAC_ATT20C408;
3312 else
3313 info->dac_subtype = (aty_ld_8(SCRATCH_REG1 + 1, info) & 0xF0) |
3314 info->dac_type;
3315 #else
3316 info->dac_type = DAC_IBMRGB514;
3317 info->dac_subtype = DAC_IBMRGB514;
3318 info->clk_type = CLK_IBMRGB514;
3319 #endif
3320 /* FIXME */
3321 pll = 135;
3322 mclk = 50;
3323 } else {
3324 info->bus_type = PCI;
3325 info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) & 0x07);
3326 ramname = aty_ct_ram[info->ram_type];
3327 info->dac_type = DAC_INTERNAL;
3328 info->dac_subtype = DAC_INTERNAL;
3329 info->clk_type = CLK_INTERNAL;
3330 if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID)) {
3331 pll = 135;
3332 mclk = 60;
3333 } else {
3334 mclk = info->ram_type >= SDRAM ? 67 : 63;
3335 if ((Gx == VT_CHIP_ID) && (Rev == 0x08)) {
3336 /* VTA3 */
3337 pll = 170;
3338 } else if (((Gx == VT_CHIP_ID) && ((Rev == 0x40) ||
3339 (Rev == 0x48))) ||
3340 ((Gx == VT_CHIP_ID) && ((Rev == 0x01) ||
3341 (Rev == 0x9a))) ||
3342 Gx == VU_CHIP_ID) {
3343 /* VTA4 or VTB */
3344 pll = 200;
3345 } else if (Gx == VV_CHIP_ID) {
3346 /* VT4 */
3347 pll = 230;
3348 mclk = 83;
3349 } else if (Gx == VT_CHIP_ID) {
3350 /* other VT */
3351 pll = 135;
3352 mclk = 63;
3353 } else if ((Gx == GT_CHIP_ID) && (Rev & 0x01)) {
3354 /* RAGE II */
3355 pll = 170;
3356 } else if (((Gx == GT_CHIP_ID) && (Rev & 0x02)) ||
3357 (Gx == GU_CHIP_ID)) {
3358 /* RAGE II+ */
3359 pll = 200;
3360 } else if (Gx == GV_CHIP_ID || Gx == GW_CHIP_ID ||
3361 Gx == GZ_CHIP_ID) {
3362 /* RAGE IIC */
3363 pll = 230;
3364 mclk = 83;
3365 } else if (Gx == GB_CHIP_ID || Gx == GD_CHIP_ID ||
3366 Gx == GI_CHIP_ID || Gx == GP_CHIP_ID ||
3367 Gx == GQ_CHIP_ID || Gx == LB_CHIP_ID ||
3368 Gx == LD_CHIP_ID ||
3369 Gx == LI_CHIP_ID || Gx == LP_CHIP_ID) {
3370 /* RAGE PRO or LT PRO */
3371 pll = 230;
3372 mclk = 100;
3373 } else if (Gx == LG_CHIP_ID) {
3374 /* Rage LT */
3375 pll = 230;
3376 mclk = 63;
3377 } else {
3378 /* other RAGE */
3379 pll = 135;
3380 mclk = 63;
3385 info->ref_clk_per = 1000000000000ULL/14318180;
3386 xtal = "14.31818";
3387 if (!(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
3388 Gx == ET_CHIP_ID ||
3389 ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07))) &&
3390 (pll_ref_div = aty_ld_pll(PLL_REF_DIV, info))) {
3391 int diff1, diff2;
3392 diff1 = 510*14/pll_ref_div-pll;
3393 diff2 = 510*29/pll_ref_div-pll;
3394 if (diff1 < 0)
3395 diff1 = -diff1;
3396 if (diff2 < 0)
3397 diff2 = -diff2;
3398 if (diff2 < diff1) {
3399 info->ref_clk_per = 1000000000000ULL/29498928;
3400 xtal = "29.498928";
3404 i = aty_ld_le32(MEM_CNTL, info);
3405 gtb_memsize = !(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
3406 Gx == ET_CHIP_ID ||
3407 ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07)));
3408 if (gtb_memsize)
3409 switch (i & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */
3410 case MEM_SIZE_512K:
3411 info->total_vram = 0x80000;
3412 break;
3413 case MEM_SIZE_1M:
3414 info->total_vram = 0x100000;
3415 break;
3416 case MEM_SIZE_2M_GTB:
3417 info->total_vram = 0x200000;
3418 break;
3419 case MEM_SIZE_4M_GTB:
3420 info->total_vram = 0x400000;
3421 break;
3422 case MEM_SIZE_6M_GTB:
3423 info->total_vram = 0x600000;
3424 break;
3425 case MEM_SIZE_8M_GTB:
3426 info->total_vram = 0x800000;
3427 break;
3428 default:
3429 info->total_vram = 0x80000;
3431 else
3432 switch (i & MEM_SIZE_ALIAS) {
3433 case MEM_SIZE_512K:
3434 info->total_vram = 0x80000;
3435 break;
3436 case MEM_SIZE_1M:
3437 info->total_vram = 0x100000;
3438 break;
3439 case MEM_SIZE_2M:
3440 info->total_vram = 0x200000;
3441 break;
3442 case MEM_SIZE_4M:
3443 info->total_vram = 0x400000;
3444 break;
3445 case MEM_SIZE_6M:
3446 info->total_vram = 0x600000;
3447 break;
3448 case MEM_SIZE_8M:
3449 info->total_vram = 0x800000;
3450 break;
3451 default:
3452 info->total_vram = 0x80000;
3455 if (Gx == GI_CHIP_ID) {
3456 if (aty_ld_le32(CONFIG_STAT1, info) & 0x40000000)
3457 info->total_vram += 0x400000;
3460 if (default_vram) {
3461 info->total_vram = default_vram*1024;
3462 i = i & ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS);
3463 if (info->total_vram <= 0x80000)
3464 i |= MEM_SIZE_512K;
3465 else if (info->total_vram <= 0x100000)
3466 i |= MEM_SIZE_1M;
3467 else if (info->total_vram <= 0x200000)
3468 i |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M;
3469 else if (info->total_vram <= 0x400000)
3470 i |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M;
3471 else if (info->total_vram <= 0x600000)
3472 i |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M;
3473 else
3474 i |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M;
3475 aty_st_le32(MEM_CNTL, i, info);
3477 if (default_pll)
3478 pll = default_pll;
3479 if (default_mclk)
3480 mclk = default_mclk;
3482 printk("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK\n",
3483 info->total_vram == 0x80000 ? 512 : (info->total_vram >> 20),
3484 info->total_vram == 0x80000 ? 'K' : 'M', ramname, xtal, pll, mclk);
3486 if (mclk < 44)
3487 info->mem_refresh_rate = 0; /* 000 = 10 Mhz - 43 Mhz */
3488 else if (mclk < 50)
3489 info->mem_refresh_rate = 1; /* 001 = 44 Mhz - 49 Mhz */
3490 else if (mclk < 55)
3491 info->mem_refresh_rate = 2; /* 010 = 50 Mhz - 54 Mhz */
3492 else if (mclk < 66)
3493 info->mem_refresh_rate = 3; /* 011 = 55 Mhz - 65 Mhz */
3494 else if (mclk < 75)
3495 info->mem_refresh_rate = 4; /* 100 = 66 Mhz - 74 Mhz */
3496 else if (mclk < 80)
3497 info->mem_refresh_rate = 5; /* 101 = 75 Mhz - 79 Mhz */
3498 else if (mclk < 100)
3499 info->mem_refresh_rate = 6; /* 110 = 80 Mhz - 100 Mhz */
3500 else
3501 info->mem_refresh_rate = 7; /* 111 = 100 Mhz and above */
3502 info->pll_per = 1000000/pll;
3503 info->mclk_per = 1000000/mclk;
3505 #ifdef DEBUG
3506 if ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
3507 int i;
3508 printk("BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
3509 "DSP_CONFIG DSP_ON_OFF\n"
3510 "%08x %08x %08x %08x %08x %08x %08x\n"
3511 "PLL",
3512 aty_ld_le32(BUS_CNTL, info), aty_ld_le32(DAC_CNTL, info),
3513 aty_ld_le32(MEM_CNTL, info), aty_ld_le32(EXT_MEM_CNTL, info),
3514 aty_ld_le32(CRTC_GEN_CNTL, info), aty_ld_le32(DSP_CONFIG, info),
3515 aty_ld_le32(DSP_ON_OFF, info));
3516 for (i = 0; i < 16; i++)
3517 printk(" %02x", aty_ld_pll(i, info));
3518 printk("\n");
3520 #endif
3523 * Last page of 8 MB (4 MB on ISA) aperture is MMIO
3524 * FIXME: we should use the auxiliary aperture instead so we can acces the
3525 * full 8 MB of video RAM on 8 MB boards
3527 if (info->total_vram == 0x800000 ||
3528 (info->bus_type == ISA && info->total_vram == 0x400000))
3529 info->total_vram -= GUI_RESERVE;
3531 /* Clear the video memory */
3532 fb_memset((void *)info->frame_buffer, 0, info->total_vram);
3534 disp = &info->disp;
3536 strcpy(info->fb_info.modename, atyfb_name);
3537 info->fb_info.node = -1;
3538 info->fb_info.fbops = &atyfb_ops;
3539 info->fb_info.disp = disp;
3540 strcpy(info->fb_info.fontname, fontname);
3541 info->fb_info.changevar = NULL;
3542 info->fb_info.switch_con = &atyfbcon_switch;
3543 info->fb_info.updatevar = &atyfbcon_updatevar;
3544 info->fb_info.blank = &atyfbcon_blank;
3545 info->fb_info.flags = FBINFO_FLAG_DEFAULT;
3547 #ifdef CONFIG_PPC
3548 if (Gx == LI_CHIP_ID && machine_is_compatible("PowerBook1,1")) {
3549 /* these bits let the 101 powerbook wake up from sleep -- paulus */
3550 aty_st_lcd(LCD_POWER_MANAGEMENT, aty_ld_lcd(LCD_POWER_MANAGEMENT, info)
3551 | (USE_F32KHZ | TRISTATE_MEM_EN), info);
3553 #endif /* CONFIG_PPC */
3555 #ifdef MODULE
3556 var = default_var;
3557 #else /* !MODULE */
3558 memset(&var, 0, sizeof(var));
3559 #ifdef CONFIG_PPC
3560 if (_machine == _MACH_Pmac) {
3562 * FIXME: The NVRAM stuff should be put in a Mac-specific file, as it
3563 * applies to all Mac video cards
3565 if (mode_option) {
3566 if (!mac_find_mode(&var, &info->fb_info, mode_option, 8))
3567 var = default_var;
3568 } else {
3569 #ifdef CONFIG_NVRAM
3570 if (default_vmode == VMODE_NVRAM) {
3571 default_vmode = nvram_read_byte(NV_VMODE);
3572 if (default_vmode <= 0 || default_vmode > VMODE_MAX)
3573 default_vmode = VMODE_CHOOSE;
3575 #endif
3576 if (default_vmode == VMODE_CHOOSE) {
3577 if (Gx == LG_CHIP_ID || Gx == LI_CHIP_ID)
3578 /* G3 PowerBook with 1024x768 LCD */
3579 default_vmode = VMODE_1024_768_60;
3580 else if (machine_is_compatible("iMac"))
3581 default_vmode = VMODE_1024_768_75;
3582 else
3583 default_vmode = VMODE_640_480_67;
3584 sense = read_aty_sense(info);
3585 printk(KERN_INFO "atyfb: monitor sense=%x, mode %d\n",
3586 sense, mac_map_monitor_sense(sense));
3588 if (default_vmode <= 0 || default_vmode > VMODE_MAX)
3589 default_vmode = VMODE_640_480_60;
3590 #ifdef CONFIG_NVRAM
3591 if (default_cmode == CMODE_NVRAM)
3592 default_cmode = nvram_read_byte(NV_CMODE);
3593 #endif
3594 if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
3595 default_cmode = CMODE_8;
3596 if (mac_vmode_to_var(default_vmode, default_cmode, &var))
3597 var = default_var;
3600 else if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
3601 var = default_var;
3602 #else /* !CONFIG_PPC */
3603 #ifdef __sparc__
3604 if (mode_option) {
3605 if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
3606 var = default_var;
3607 } else
3608 var = default_var;
3609 #else
3610 if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
3611 var = default_var;
3612 #endif /* !__sparc__ */
3613 #endif /* !CONFIG_PPC */
3614 #endif /* !MODULE */
3615 if (noaccel)
3616 var.accel_flags &= ~FB_ACCELF_TEXT;
3617 else
3618 var.accel_flags |= FB_ACCELF_TEXT;
3620 if (var.yres == var.yres_virtual) {
3621 u32 vram = (info->total_vram - (PAGE_SIZE << 2));
3622 var.yres_virtual = ((vram * 8) / var.bits_per_pixel) / var.xres_virtual;
3623 if (var.yres_virtual < var.yres)
3624 var.yres_virtual = var.yres;
3627 if (atyfb_decode_var(&var, &info->default_par, info)) {
3628 printk("atyfb: can't set default video mode\n");
3629 return 0;
3632 #ifdef __sparc__
3633 atyfb_save_palette(&info->fb_info, 0);
3634 #endif
3635 for (j = 0; j < 16; j++) {
3636 k = color_table[j];
3637 info->palette[j].red = default_red[k];
3638 info->palette[j].green = default_grn[k];
3639 info->palette[j].blue = default_blu[k];
3642 if (Gx != GX_CHIP_ID && Gx != CX_CHIP_ID) {
3643 info->cursor = aty_init_cursor(info);
3644 if (info->cursor) {
3645 info->dispsw.cursor = atyfb_cursor;
3646 info->dispsw.set_font = atyfb_set_font;
3650 atyfb_set_var(&var, -1, &info->fb_info);
3652 if (register_framebuffer(&info->fb_info) < 0)
3653 return 0;
3655 info->next = fb_list;
3656 fb_list = info;
3658 printk("fb%d: %s frame buffer device on %s\n",
3659 GET_FB_IDX(info->fb_info.node), atyfb_name, name);
3660 return 1;
3663 int __init atyfb_init(void)
3665 #if defined(CONFIG_PCI)
3666 struct pci_dev *pdev = NULL;
3667 struct fb_info_aty *info;
3668 unsigned long addr, res_start, res_size;
3669 int i;
3670 #ifdef __sparc__
3671 extern void (*prom_palette) (int);
3672 extern int con_is_present(void);
3673 struct pcidev_cookie *pcp;
3674 char prop[128];
3675 int node, len, j;
3676 u32 mem, chip_id;
3678 /* Do not attach when we have a serial console. */
3679 if (!con_is_present())
3680 return -ENXIO;
3681 #else
3682 u16 tmp;
3683 #endif
3685 while ((pdev = pci_find_device(PCI_VENDOR_ID_ATI, PCI_ANY_ID, pdev))) {
3686 if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
3687 struct resource *rp;
3689 for (i = sizeof(aty_features)/sizeof(*aty_features)-1; i >= 0; i--)
3690 if (pdev->device == aty_features[i].pci_id)
3691 break;
3692 if (i < 0)
3693 continue;
3695 info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
3696 if (!info) {
3697 printk("atyfb_init: can't alloc fb_info_aty\n");
3698 return -ENXIO;
3700 memset(info, 0, sizeof(struct fb_info_aty));
3702 rp = &pdev->resource[0];
3703 if (rp->flags & IORESOURCE_IO)
3704 rp = &pdev->resource[1];
3705 addr = rp->start;
3706 if (!addr)
3707 continue;
3709 res_start = rp->start;
3710 res_size = rp->end-rp->start+1;
3711 if (!request_mem_region(res_start, res_size, "atyfb"))
3712 continue;
3714 #ifdef __sparc__
3716 * Map memory-mapped registers.
3718 info->ati_regbase = addr + 0x7ffc00UL;
3719 info->ati_regbase_phys = addr + 0x7ffc00UL;
3722 * Map in big-endian aperture.
3724 info->frame_buffer = (unsigned long) addr + 0x800000UL;
3725 info->frame_buffer_phys = addr + 0x800000UL;
3728 * Figure mmap addresses from PCI config space.
3729 * Split Framebuffer in big- and little-endian halfs.
3731 for (i = 0; i < 6 && pdev->resource[i].start; i++)
3732 /* nothing */;
3733 j = i + 4;
3735 info->mmap_map = kmalloc(j * sizeof(*info->mmap_map), GFP_ATOMIC);
3736 if (!info->mmap_map) {
3737 printk("atyfb_init: can't alloc mmap_map\n");
3738 kfree(info);
3739 release_mem_region(res_start, res_size);
3740 return -ENXIO;
3742 memset(info->mmap_map, 0, j * sizeof(*info->mmap_map));
3744 for (i = 0, j = 2; i < 6 && pdev->resource[i].start; i++) {
3745 struct resource *rp = &pdev->resource[i];
3746 int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
3747 unsigned long base;
3748 u32 size, pbase;
3750 base = rp->start;
3752 io = (rp->flags & IORESOURCE_IO);
3754 size = rp->end - base + 1;
3756 pci_read_config_dword(pdev, breg, &pbase);
3758 if (io)
3759 size &= ~1;
3762 * Map the framebuffer a second time, this time without
3763 * the braindead _PAGE_IE setting. This is used by the
3764 * fixed Xserver, but we need to maintain the old mapping
3765 * to stay compatible with older ones...
3767 if (base == addr) {
3768 info->mmap_map[j].voff = (pbase + 0x10000000) & PAGE_MASK;
3769 info->mmap_map[j].poff = base & PAGE_MASK;
3770 info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
3771 info->mmap_map[j].prot_mask = _PAGE_CACHE;
3772 info->mmap_map[j].prot_flag = _PAGE_E;
3773 j++;
3777 * Here comes the old framebuffer mapping with _PAGE_IE
3778 * set for the big endian half of the framebuffer...
3780 if (base == addr) {
3781 info->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK;
3782 info->mmap_map[j].poff = (base+0x800000) & PAGE_MASK;
3783 info->mmap_map[j].size = 0x800000;
3784 info->mmap_map[j].prot_mask = _PAGE_CACHE;
3785 info->mmap_map[j].prot_flag = _PAGE_E|_PAGE_IE;
3786 size -= 0x800000;
3787 j++;
3790 info->mmap_map[j].voff = pbase & PAGE_MASK;
3791 info->mmap_map[j].poff = base & PAGE_MASK;
3792 info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
3793 info->mmap_map[j].prot_mask = _PAGE_CACHE;
3794 info->mmap_map[j].prot_flag = _PAGE_E;
3795 j++;
3799 * Fix PROMs idea of MEM_CNTL settings...
3801 mem = aty_ld_le32(MEM_CNTL, info);
3802 chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
3803 if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) &&
3804 !((chip_id >> 24) & 1)) {
3805 switch (mem & 0x0f) {
3806 case 3:
3807 mem = (mem & ~(0x0f)) | 2;
3808 break;
3809 case 7:
3810 mem = (mem & ~(0x0f)) | 3;
3811 break;
3812 case 9:
3813 mem = (mem & ~(0x0f)) | 4;
3814 break;
3815 case 11:
3816 mem = (mem & ~(0x0f)) | 5;
3817 break;
3818 default:
3819 break;
3821 if ((aty_ld_le32(CONFIG_STAT0, info) & 7) >= SDRAM)
3822 mem &= ~(0x00700000);
3824 mem &= ~(0xcf80e000); /* Turn off all undocumented bits. */
3825 aty_st_le32(MEM_CNTL, mem, info);
3828 * If this is the console device, we will set default video
3829 * settings to what the PROM left us with.
3831 node = prom_getchild(prom_root_node);
3832 node = prom_searchsiblings(node, "aliases");
3833 if (node) {
3834 len = prom_getproperty(node, "screen", prop, sizeof(prop));
3835 if (len > 0) {
3836 prop[len] = '\0';
3837 node = prom_finddevice(prop);
3838 } else {
3839 node = 0;
3843 pcp = pdev->sysdata;
3844 if (node == pcp->prom_node) {
3846 struct fb_var_screeninfo *var = &default_var;
3847 unsigned int N, P, Q, M, T;
3848 u32 v_total, h_total;
3849 struct crtc crtc;
3850 u8 pll_regs[16];
3851 u8 clock_cntl;
3853 crtc.vxres = prom_getintdefault(node, "width", 1024);
3854 crtc.vyres = prom_getintdefault(node, "height", 768);
3855 crtc.bpp = prom_getintdefault(node, "depth", 8);
3856 crtc.xoffset = crtc.yoffset = 0;
3857 crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, info);
3858 crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, info);
3859 crtc.v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, info);
3860 crtc.v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, info);
3861 crtc.gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, info);
3862 aty_crtc_to_var(&crtc, var);
3864 h_total = var->xres + var->right_margin +
3865 var->hsync_len + var->left_margin;
3866 v_total = var->yres + var->lower_margin +
3867 var->vsync_len + var->upper_margin;
3870 * Read the PLL to figure actual Refresh Rate.
3872 clock_cntl = aty_ld_8(CLOCK_CNTL, info);
3873 /* printk("atyfb: CLOCK_CNTL: %02x\n", clock_cntl); */
3874 for (i = 0; i < 16; i++)
3875 pll_regs[i] = aty_ld_pll(i, info);
3878 * PLL Reference Devider M:
3880 M = pll_regs[2];
3883 * PLL Feedback Devider N (Dependant on CLOCK_CNTL):
3885 N = pll_regs[7 + (clock_cntl & 3)];
3888 * PLL Post Devider P (Dependant on CLOCK_CNTL):
3890 P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
3893 * PLL Devider Q:
3895 Q = N / P;
3898 * Target Frequency:
3900 * T * M
3901 * Q = -------
3902 * 2 * R
3904 * where R is XTALIN (= 14318 kHz).
3906 T = 2 * Q * 14318 / M;
3908 default_var.pixclock = 1000000000 / T;
3911 #else /* __sparc__ */
3913 info->ati_regbase_phys = 0x7ff000 + addr;
3914 info->ati_regbase = (unsigned long)
3915 ioremap(info->ati_regbase_phys, 0x1000);
3917 if(!info->ati_regbase) {
3918 kfree(info);
3919 release_mem_region(res_start, res_size);
3920 return -ENOMEM;
3923 info->ati_regbase_phys += 0xc00;
3924 info->ati_regbase += 0xc00;
3927 * Enable memory-space accesses using config-space
3928 * command register.
3930 pci_read_config_word(pdev, PCI_COMMAND, &tmp);
3931 if (!(tmp & PCI_COMMAND_MEMORY)) {
3932 tmp |= PCI_COMMAND_MEMORY;
3933 pci_write_config_word(pdev, PCI_COMMAND, tmp);
3936 #ifdef __BIG_ENDIAN
3937 /* Use the big-endian aperture */
3938 addr += 0x800000;
3939 #endif
3941 /* Map in frame buffer */
3942 info->frame_buffer_phys = addr;
3943 info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
3945 if(!info->frame_buffer) {
3946 kfree(info);
3947 release_mem_region(res_start, res_size);
3948 return -ENXIO;
3951 #endif /* __sparc__ */
3953 if (!aty_init(info, "PCI")) {
3954 if (info->mmap_map)
3955 kfree(info->mmap_map);
3956 kfree(info);
3957 release_mem_region(res_start, res_size);
3958 return -ENXIO;
3961 #ifdef __sparc__
3962 if (!prom_palette)
3963 prom_palette = atyfb_palette;
3966 * Add /dev/fb mmap values.
3968 info->mmap_map[0].voff = 0x8000000000000000UL;
3969 info->mmap_map[0].poff = info->frame_buffer & PAGE_MASK;
3970 info->mmap_map[0].size = info->total_vram;
3971 info->mmap_map[0].prot_mask = _PAGE_CACHE;
3972 info->mmap_map[0].prot_flag = _PAGE_E;
3973 info->mmap_map[1].voff = info->mmap_map[0].voff + info->total_vram;
3974 info->mmap_map[1].poff = info->ati_regbase & PAGE_MASK;
3975 info->mmap_map[1].size = PAGE_SIZE;
3976 info->mmap_map[1].prot_mask = _PAGE_CACHE;
3977 info->mmap_map[1].prot_flag = _PAGE_E;
3978 #endif /* __sparc__ */
3980 #ifdef CONFIG_PMAC_PBOOK
3981 if (first_display == NULL)
3982 pmu_register_sleep_notifier(&aty_sleep_notifier);
3983 info->next = first_display;
3984 first_display = info;
3985 #endif
3987 #ifdef CONFIG_FB_COMPAT_XPMAC
3988 if (!console_fb_info)
3989 console_fb_info = &info->fb_info;
3990 #endif /* CONFIG_FB_COMPAT_XPMAC */
3994 #elif defined(CONFIG_ATARI)
3995 u32 clock_r;
3996 int m64_num;
3997 struct fb_info_aty *info;
3999 for (m64_num = 0; m64_num < mach64_count; m64_num++) {
4000 if (!phys_vmembase[m64_num] || !phys_size[m64_num] ||
4001 !phys_guiregbase[m64_num]) {
4002 printk(" phys_*[%d] parameters not set => returning early. \n",
4003 m64_num);
4004 continue;
4007 info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
4008 if (!info) {
4009 printk("atyfb_init: can't alloc fb_info_aty\n");
4010 return -ENOMEM;
4012 memset(info, 0, sizeof(struct fb_info_aty));
4015 * Map the video memory (physical address given) to somewhere in the
4016 * kernel address space.
4018 info->frame_buffer = ioremap(phys_vmembase[m64_num], phys_size[m64_num]);
4019 info->frame_buffer_phys = info->frame_buffer; /* Fake! */
4020 info->ati_regbase = ioremap(phys_guiregbase[m64_num], 0x10000)+0xFC00ul;
4021 info->ati_regbase_phys = info->ati_regbase; /* Fake! */
4023 aty_st_le32(CLOCK_CNTL, 0x12345678, info);
4024 clock_r = aty_ld_le32(CLOCK_CNTL, info);
4026 switch (clock_r & 0x003F) {
4027 case 0x12:
4028 info->clk_wr_offset = 3; /* */
4029 break;
4030 case 0x34:
4031 info->clk_wr_offset = 2; /* Medusa ST-IO ISA Adapter etc. */
4032 break;
4033 case 0x16:
4034 info->clk_wr_offset = 1; /* */
4035 break;
4036 case 0x38:
4037 info->clk_wr_offset = 0; /* Panther 1 ISA Adapter (Gerald) */
4038 break;
4041 if (!aty_init(info, "ISA bus")) {
4042 kfree(info);
4043 /* This is insufficient! kernel_map has added two large chunks!! */
4044 return -ENXIO;
4047 #endif /* CONFIG_ATARI */
4048 return 0;
4051 #ifndef MODULE
4052 int __init atyfb_setup(char *options)
4054 char *this_opt;
4056 if (!options || !*options)
4057 return 0;
4059 for (this_opt = strtok(options, ","); this_opt;
4060 this_opt = strtok(NULL, ",")) {
4061 if (!strncmp(this_opt, "font:", 5)) {
4062 char *p;
4063 int i;
4065 p = this_opt + 5;
4066 for (i = 0; i < sizeof(fontname) - 1; i++)
4067 if (!*p || *p == ' ' || *p == ',')
4068 break;
4069 memcpy(fontname, this_opt + 5, i);
4070 fontname[i] = 0;
4071 } else if (!strncmp(this_opt, "noblink", 7)) {
4072 curblink = 0;
4073 } else if (!strncmp(this_opt, "noaccel", 7)) {
4074 noaccel = 1;
4075 } else if (!strncmp(this_opt, "vram:", 5))
4076 default_vram = simple_strtoul(this_opt+5, NULL, 0);
4077 else if (!strncmp(this_opt, "pll:", 4))
4078 default_pll = simple_strtoul(this_opt+4, NULL, 0);
4079 else if (!strncmp(this_opt, "mclk:", 5))
4080 default_mclk = simple_strtoul(this_opt+5, NULL, 0);
4081 #ifdef CONFIG_PPC
4082 else if (!strncmp(this_opt, "vmode:", 6)) {
4083 unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
4084 if (vmode > 0 && vmode <= VMODE_MAX)
4085 default_vmode = vmode;
4086 } else if (!strncmp(this_opt, "cmode:", 6)) {
4087 unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0);
4088 switch (cmode) {
4089 case 0:
4090 case 8:
4091 default_cmode = CMODE_8;
4092 break;
4093 case 15:
4094 case 16:
4095 default_cmode = CMODE_16;
4096 break;
4097 case 24:
4098 case 32:
4099 default_cmode = CMODE_32;
4100 break;
4103 #endif
4104 #ifdef CONFIG_ATARI
4106 * Why do we need this silly Mach64 argument?
4107 * We are already here because of mach64= so its redundant.
4109 else if (MACH_IS_ATARI && (!strncmp(this_opt, "Mach64:", 7))) {
4110 static unsigned char m64_num;
4111 static char mach64_str[80];
4112 strncpy(mach64_str, this_opt+7, 80);
4113 if (!store_video_par(mach64_str, m64_num)) {
4114 m64_num++;
4115 mach64_count = m64_num;
4118 #endif
4119 else
4120 mode_option = this_opt;
4122 return 0;
4124 #endif /* !MODULE */
4126 #ifdef CONFIG_ATARI
4127 static int __init store_video_par(char *video_str, unsigned char m64_num)
4129 char *p;
4130 unsigned long vmembase, size, guiregbase;
4132 printk("store_video_par() '%s' \n", video_str);
4134 if (!(p = strtoke(video_str, ";")) || !*p)
4135 goto mach64_invalid;
4136 vmembase = simple_strtoul(p, NULL, 0);
4137 if (!(p = strtoke(NULL, ";")) || !*p)
4138 goto mach64_invalid;
4139 size = simple_strtoul(p, NULL, 0);
4140 if (!(p = strtoke(NULL, ";")) || !*p)
4141 goto mach64_invalid;
4142 guiregbase = simple_strtoul(p, NULL, 0);
4144 phys_vmembase[m64_num] = vmembase;
4145 phys_size[m64_num] = size;
4146 phys_guiregbase[m64_num] = guiregbase;
4147 printk(" stored them all: $%08lX $%08lX $%08lX \n", vmembase, size,
4148 guiregbase);
4149 return 0;
4151 mach64_invalid:
4152 phys_vmembase[m64_num] = 0;
4153 return -1;
4156 static char __init *strtoke(char *s, const char *ct)
4158 static char *ssave = NULL;
4159 char *sbegin, *send;
4161 sbegin = s ? s : ssave;
4162 if (!sbegin)
4163 return NULL;
4164 if (*sbegin == '\0') {
4165 ssave = NULL;
4166 return NULL;
4168 send = strpbrk(sbegin, ct);
4169 if (send && *send != '\0')
4170 *send++ = '\0';
4171 ssave = send;
4172 return sbegin;
4174 #endif /* CONFIG_ATARI */
4176 static int atyfbcon_switch(int con, struct fb_info *fb)
4178 struct fb_info_aty *info = (struct fb_info_aty *)fb;
4179 struct atyfb_par par;
4181 /* Do we have to save the colormap? */
4182 if (fb_display[currcon].cmap.len)
4183 fb_get_cmap(&fb_display[currcon].cmap, 1, atyfb_getcolreg, fb);
4185 /* Erase HW Cursor */
4186 if (info->cursor)
4187 atyfb_cursor(&fb_display[currcon], CM_ERASE,
4188 info->cursor->pos.x, info->cursor->pos.y);
4190 currcon = con;
4192 atyfb_decode_var(&fb_display[con].var, &par, info);
4193 atyfb_set_par(&par, info);
4194 atyfb_set_disp(&fb_display[con], info, par.crtc.bpp,
4195 par.accel_flags & FB_ACCELF_TEXT);
4197 /* Install new colormap */
4198 do_install_cmap(con, fb);
4200 /* Install hw cursor */
4201 if (info->cursor) {
4202 aty_set_cursor_color(info, cursor_pixel_map, cursor_color_map,
4203 cursor_color_map, cursor_color_map);
4204 aty_set_cursor_shape(info);
4206 return 1;
4210 * Blank the display.
4213 static void atyfbcon_blank(int blank, struct fb_info *fb)
4215 struct fb_info_aty *info = (struct fb_info_aty *)fb;
4216 u8 gen_cntl;
4218 #ifdef CONFIG_ADB_PMU
4219 if ((_machine == _MACH_Pmac) && blank)
4220 pmu_enable_backlight(0);
4221 #endif
4223 gen_cntl = aty_ld_8(CRTC_GEN_CNTL, info);
4224 if (blank > 0)
4225 switch (blank-1) {
4226 case VESA_NO_BLANKING:
4227 gen_cntl |= 0x40;
4228 break;
4229 case VESA_VSYNC_SUSPEND:
4230 gen_cntl |= 0x8;
4231 break;
4232 case VESA_HSYNC_SUSPEND:
4233 gen_cntl |= 0x4;
4234 break;
4235 case VESA_POWERDOWN:
4236 gen_cntl |= 0x4c;
4237 break;
4239 else
4240 gen_cntl &= ~(0x4c);
4241 aty_st_8(CRTC_GEN_CNTL, gen_cntl, info);
4243 #ifdef CONFIG_ADB_PMU
4244 if ((_machine == _MACH_Pmac) && !blank)
4245 pmu_enable_backlight(1);
4246 #endif
4251 * Read a single color register and split it into
4252 * colors/transparent. Return != 0 for invalid regno.
4255 static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
4256 u_int *transp, struct fb_info *fb)
4258 struct fb_info_aty *info = (struct fb_info_aty *)fb;
4260 if (regno > 255)
4261 return 1;
4262 *red = (info->palette[regno].red<<8) | info->palette[regno].red;
4263 *green = (info->palette[regno].green<<8) | info->palette[regno].green;
4264 *blue = (info->palette[regno].blue<<8) | info->palette[regno].blue;
4265 *transp = 0;
4266 return 0;
4271 * Set a single color register. The values supplied are already
4272 * rounded down to the hardware's capabilities (according to the
4273 * entries in the var structure). Return != 0 for invalid regno.
4276 static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
4277 u_int transp, struct fb_info *fb)
4279 struct fb_info_aty *info = (struct fb_info_aty *)fb;
4280 int i, scale;
4282 if (regno > 255)
4283 return 1;
4284 red >>= 8;
4285 green >>= 8;
4286 blue >>= 8;
4287 info->palette[regno].red = red;
4288 info->palette[regno].green = green;
4289 info->palette[regno].blue = blue;
4290 i = aty_ld_8(DAC_CNTL, info) & 0xfc;
4291 if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == GV_CHIP_ID ||
4292 Gx == GW_CHIP_ID || Gx == GZ_CHIP_ID || Gx == LG_CHIP_ID ||
4293 Gx == GB_CHIP_ID || Gx == GD_CHIP_ID || Gx == GI_CHIP_ID ||
4294 Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID || Gx == LI_CHIP_ID)
4295 i |= 0x2; /*DAC_CNTL|0x2 turns off the extra brightness for gt*/
4296 aty_st_8(DAC_CNTL, i, info);
4297 aty_st_8(DAC_MASK, 0xff, info);
4298 scale = ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID) &&
4299 (info->current_par.crtc.bpp == 16)) ? 3 : 0;
4300 writeb(regno << scale, &info->aty_cmap_regs->windex);
4301 writeb(red, &info->aty_cmap_regs->lut);
4302 writeb(green, &info->aty_cmap_regs->lut);
4303 writeb(blue, &info->aty_cmap_regs->lut);
4304 if (regno < 16)
4305 switch (info->current_par.crtc.bpp) {
4306 #ifdef FBCON_HAS_CFB16
4307 case 16:
4308 info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) |
4309 regno;
4310 break;
4311 #endif
4312 #ifdef FBCON_HAS_CFB24
4313 case 24:
4314 info->fbcon_cmap.cfb24[regno] = (regno << 16) | (regno << 8) |
4315 regno;
4316 break;
4317 #endif
4318 #ifdef FBCON_HAS_CFB32
4319 case 32:
4320 i = (regno << 8) | regno;
4321 info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
4322 break;
4323 #endif
4325 return 0;
4329 static void do_install_cmap(int con, struct fb_info *info)
4331 if (con != currcon)
4332 return;
4333 if (fb_display[con].cmap.len)
4334 fb_set_cmap(&fb_display[con].cmap, 1, atyfb_setcolreg, info);
4335 else {
4336 int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
4337 fb_set_cmap(fb_default_cmap(size), 1, atyfb_setcolreg, info);
4343 * Accelerated functions
4346 static inline void draw_rect(s16 x, s16 y, u16 width, u16 height,
4347 struct fb_info_aty *info)
4349 /* perform rectangle fill */
4350 wait_for_fifo(2, info);
4351 aty_st_le32(DST_Y_X, (x << 16) | y, info);
4352 aty_st_le32(DST_HEIGHT_WIDTH, (width << 16) | height, info);
4353 info->blitter_may_be_busy = 1;
4356 static inline void aty_rectcopy(int srcx, int srcy, int dstx, int dsty,
4357 u_int width, u_int height,
4358 struct fb_info_aty *info)
4360 u32 direction = DST_LAST_PEL;
4361 u32 pitch_value;
4363 if (!width || !height)
4364 return;
4366 pitch_value = info->current_par.crtc.vxres;
4367 if (info->current_par.crtc.bpp == 24) {
4368 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
4369 /* horizontal coordinates and widths must be adjusted */
4370 pitch_value *= 3;
4371 srcx *= 3;
4372 dstx *= 3;
4373 width *= 3;
4376 if (srcy < dsty) {
4377 dsty += height - 1;
4378 srcy += height - 1;
4379 } else
4380 direction |= DST_Y_TOP_TO_BOTTOM;
4382 if (srcx < dstx) {
4383 dstx += width - 1;
4384 srcx += width - 1;
4385 } else
4386 direction |= DST_X_LEFT_TO_RIGHT;
4388 wait_for_fifo(4, info);
4389 aty_st_le32(DP_SRC, FRGD_SRC_BLIT, info);
4390 aty_st_le32(SRC_Y_X, (srcx << 16) | srcy, info);
4391 aty_st_le32(SRC_HEIGHT1_WIDTH1, (width << 16) | height, info);
4392 aty_st_le32(DST_CNTL, direction, info);
4393 draw_rect(dstx, dsty, width, height, info);
4396 static inline void aty_rectfill(int dstx, int dsty, u_int width, u_int height,
4397 u_int color, struct fb_info_aty *info)
4399 if (!width || !height)
4400 return;
4402 if (info->current_par.crtc.bpp == 24) {
4403 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
4404 /* horizontal coordinates and widths must be adjusted */
4405 dstx *= 3;
4406 width *= 3;
4409 wait_for_fifo(3, info);
4410 aty_st_le32(DP_FRGD_CLR, color, info);
4411 aty_st_le32(DP_SRC, BKGD_SRC_BKGD_CLR | FRGD_SRC_FRGD_CLR | MONO_SRC_ONE,
4412 info);
4413 aty_st_le32(DST_CNTL, DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM |
4414 DST_X_LEFT_TO_RIGHT, info);
4415 draw_rect(dstx, dsty, width, height, info);
4419 * Update the `var' structure (called by fbcon.c)
4422 static int atyfbcon_updatevar(int con, struct fb_info *fb)
4424 struct fb_info_aty *info = (struct fb_info_aty *)fb;
4425 struct atyfb_par *par = &info->current_par;
4426 struct display *p = &fb_display[con];
4427 struct vc_data *conp = p->conp;
4428 u32 yres, yoffset, sy, height;
4430 yres = ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1;
4431 yoffset = fb_display[con].var.yoffset;
4433 sy = (conp->vc_rows + p->yscroll) * fontheight(p);
4434 height = yres - conp->vc_rows * fontheight(p);
4436 if (height && (yoffset + yres > sy)) {
4437 u32 xres, xoffset;
4438 u32 bgx;
4440 xres = (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8;
4441 xoffset = fb_display[con].var.xoffset;
4444 bgx = attr_bgcol_ec(p, conp);
4445 bgx |= (bgx << 8);
4446 bgx |= (bgx << 16);
4448 if (sy + height > par->crtc.vyres) {
4449 wait_for_fifo(1, info);
4450 aty_st_le32(SC_BOTTOM, sy + height - 1, info);
4452 aty_rectfill(xoffset, sy, xres, height, bgx, info);
4455 if (info->cursor && (yoffset + yres <= sy))
4456 atyfb_cursor(p, CM_ERASE, info->cursor->pos.x, info->cursor->pos.y);
4458 info->current_par.crtc.yoffset = yoffset;
4459 set_off_pitch(&info->current_par, info);
4460 return 0;
4464 * Text console acceleration
4467 static void fbcon_aty_bmove(struct display *p, int sy, int sx, int dy, int dx,
4468 int height, int width)
4470 #ifdef __sparc__
4471 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4473 if (fb->mmaped && (!fb->fb_info.display_fg
4474 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4475 return;
4476 #endif
4478 sx *= fontwidth(p);
4479 sy *= fontheight(p);
4480 dx *= fontwidth(p);
4481 dy *= fontheight(p);
4482 width *= fontwidth(p);
4483 height *= fontheight(p);
4485 aty_rectcopy(sx, sy, dx, dy, width, height,
4486 (struct fb_info_aty *)p->fb_info);
4489 static void fbcon_aty_clear(struct vc_data *conp, struct display *p, int sy,
4490 int sx, int height, int width)
4492 u32 bgx;
4493 #ifdef __sparc__
4494 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4496 if (fb->mmaped && (!fb->fb_info.display_fg
4497 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4498 return;
4499 #endif
4501 bgx = attr_bgcol_ec(p, conp);
4502 bgx |= (bgx << 8);
4503 bgx |= (bgx << 16);
4505 sx *= fontwidth(p);
4506 sy *= fontheight(p);
4507 width *= fontwidth(p);
4508 height *= fontheight(p);
4510 aty_rectfill(sx, sy, width, height, bgx,
4511 (struct fb_info_aty *)p->fb_info);
4514 #ifdef FBCON_HAS_CFB8
4515 static void fbcon_aty8_putc(struct vc_data *conp, struct display *p, int c,
4516 int yy, int xx)
4518 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4520 #ifdef __sparc__
4521 if (fb->mmaped && (!fb->fb_info.display_fg
4522 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4523 return;
4524 #endif
4526 if (fb->blitter_may_be_busy)
4527 wait_for_idle((struct fb_info_aty *)p->fb_info);
4528 fbcon_cfb8_putc(conp, p, c, yy, xx);
4531 static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p,
4532 const unsigned short *s, int count, int yy,
4533 int xx)
4535 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4537 #ifdef __sparc__
4538 if (fb->mmaped && (!fb->fb_info.display_fg
4539 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4540 return;
4541 #endif
4543 if (fb->blitter_may_be_busy)
4544 wait_for_idle((struct fb_info_aty *)p->fb_info);
4545 fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
4548 static void fbcon_aty8_clear_margins(struct vc_data *conp, struct display *p,
4549 int bottom_only)
4551 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4553 #ifdef __sparc__
4554 if (fb->mmaped && (!fb->fb_info.display_fg
4555 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4556 return;
4557 #endif
4559 if (fb->blitter_may_be_busy)
4560 wait_for_idle((struct fb_info_aty *)p->fb_info);
4561 fbcon_cfb8_clear_margins(conp, p, bottom_only);
4564 static struct display_switch fbcon_aty8 = {
4565 fbcon_cfb8_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty8_putc,
4566 fbcon_aty8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_aty8_clear_margins,
4567 FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4569 #endif
4571 #ifdef FBCON_HAS_CFB16
4572 static void fbcon_aty16_putc(struct vc_data *conp, struct display *p, int c,
4573 int yy, int xx)
4575 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4577 #ifdef __sparc__
4578 if (fb->mmaped && (!fb->fb_info.display_fg
4579 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4580 return;
4581 #endif
4583 if (fb->blitter_may_be_busy)
4584 wait_for_idle((struct fb_info_aty *)p->fb_info);
4585 fbcon_cfb16_putc(conp, p, c, yy, xx);
4588 static void fbcon_aty16_putcs(struct vc_data *conp, struct display *p,
4589 const unsigned short *s, int count, int yy,
4590 int xx)
4592 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4594 #ifdef __sparc__
4595 if (fb->mmaped && (!fb->fb_info.display_fg
4596 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4597 return;
4598 #endif
4600 if (fb->blitter_may_be_busy)
4601 wait_for_idle((struct fb_info_aty *)p->fb_info);
4602 fbcon_cfb16_putcs(conp, p, s, count, yy, xx);
4605 static void fbcon_aty16_clear_margins(struct vc_data *conp, struct display *p,
4606 int bottom_only)
4608 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4610 #ifdef __sparc__
4611 if (fb->mmaped && (!fb->fb_info.display_fg
4612 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4613 return;
4614 #endif
4616 if (fb->blitter_may_be_busy)
4617 wait_for_idle((struct fb_info_aty *)p->fb_info);
4618 fbcon_cfb16_clear_margins(conp, p, bottom_only);
4621 static struct display_switch fbcon_aty16 = {
4622 fbcon_cfb16_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty16_putc,
4623 fbcon_aty16_putcs, fbcon_cfb16_revc, NULL, NULL, fbcon_aty16_clear_margins,
4624 FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4626 #endif
4628 #ifdef FBCON_HAS_CFB24
4629 static void fbcon_aty24_putc(struct vc_data *conp, struct display *p, int c,
4630 int yy, int xx)
4632 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4634 #ifdef __sparc__
4635 if (fb->mmaped && (!fb->fb_info.display_fg
4636 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4637 return;
4638 #endif
4640 if (fb->blitter_may_be_busy)
4641 wait_for_idle((struct fb_info_aty *)p->fb_info);
4642 fbcon_cfb24_putc(conp, p, c, yy, xx);
4645 static void fbcon_aty24_putcs(struct vc_data *conp, struct display *p,
4646 const unsigned short *s, int count, int yy,
4647 int xx)
4649 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4651 #ifdef __sparc__
4652 if (fb->mmaped && (!fb->fb_info.display_fg
4653 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4654 return;
4655 #endif
4657 if (fb->blitter_may_be_busy)
4658 wait_for_idle((struct fb_info_aty *)p->fb_info);
4659 fbcon_cfb24_putcs(conp, p, s, count, yy, xx);
4662 static void fbcon_aty24_clear_margins(struct vc_data *conp, struct display *p,
4663 int bottom_only)
4665 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4667 #ifdef __sparc__
4668 if (fb->mmaped && (!fb->fb_info.display_fg
4669 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4670 return;
4671 #endif
4673 if (fb->blitter_may_be_busy)
4674 wait_for_idle((struct fb_info_aty *)p->fb_info);
4675 fbcon_cfb24_clear_margins(conp, p, bottom_only);
4678 static struct display_switch fbcon_aty24 = {
4679 fbcon_cfb24_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty24_putc,
4680 fbcon_aty24_putcs, fbcon_cfb24_revc, NULL, NULL, fbcon_aty24_clear_margins,
4681 FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4683 #endif
4685 #ifdef FBCON_HAS_CFB32
4686 static void fbcon_aty32_putc(struct vc_data *conp, struct display *p, int c,
4687 int yy, int xx)
4689 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4691 #ifdef __sparc__
4692 if (fb->mmaped && (!fb->fb_info.display_fg
4693 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4694 return;
4695 #endif
4697 if (fb->blitter_may_be_busy)
4698 wait_for_idle((struct fb_info_aty *)p->fb_info);
4699 fbcon_cfb32_putc(conp, p, c, yy, xx);
4702 static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p,
4703 const unsigned short *s, int count, int yy,
4704 int xx)
4706 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4708 #ifdef __sparc__
4709 if (fb->mmaped && (!fb->fb_info.display_fg
4710 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4711 return;
4712 #endif
4714 if (fb->blitter_may_be_busy)
4715 wait_for_idle((struct fb_info_aty *)p->fb_info);
4716 fbcon_cfb32_putcs(conp, p, s, count, yy, xx);
4719 static void fbcon_aty32_clear_margins(struct vc_data *conp, struct display *p,
4720 int bottom_only)
4722 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4724 #ifdef __sparc__
4725 if (fb->mmaped && (!fb->fb_info.display_fg
4726 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4727 return;
4728 #endif
4730 if (fb->blitter_may_be_busy)
4731 wait_for_idle((struct fb_info_aty *)p->fb_info);
4732 fbcon_cfb32_clear_margins(conp, p, bottom_only);
4735 static struct display_switch fbcon_aty32 = {
4736 fbcon_cfb32_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty32_putc,
4737 fbcon_aty32_putcs, fbcon_cfb32_revc, NULL, NULL, fbcon_aty32_clear_margins,
4738 FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4740 #endif
4742 #ifdef CONFIG_PMAC_PBOOK
4744 /* Power management routines. Those are used for PowerBook sleep.
4746 * It appears that Rage LT and Rage LT Pro have different power
4747 * management registers. There's is some confusion about which
4748 * chipID is a Rage LT or LT pro :(
4750 static int
4751 aty_power_mgmt_LT(int sleep, struct fb_info_aty *info)
4753 unsigned int pm;
4754 int timeout;
4756 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
4757 pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;
4758 aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
4759 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
4761 timeout = 200000;
4762 if (sleep) {
4763 /* Sleep */
4764 pm &= ~PWR_MGT_ON;
4765 aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
4766 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
4767 udelay(10);
4768 pm &= ~(PWR_BLON | AUTO_PWR_UP);
4769 pm |= SUSPEND_NOW;
4770 aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
4771 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
4772 udelay(10);
4773 pm |= PWR_MGT_ON;
4774 aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
4775 do {
4776 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
4777 udelay(10);
4778 if ((--timeout) == 0)
4779 break;
4780 } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
4781 } else {
4782 /* Wakeup */
4783 pm &= ~PWR_MGT_ON;
4784 aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
4785 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
4786 udelay(10);
4787 pm |= (PWR_BLON | AUTO_PWR_UP);
4788 pm &= ~SUSPEND_NOW;
4789 aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
4790 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
4791 udelay(10);
4792 pm |= PWR_MGT_ON;
4793 aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
4794 do {
4795 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
4796 udelay(10);
4797 if ((--timeout) == 0)
4798 break;
4799 } while ((pm & PWR_MGT_STATUS_MASK) != 0);
4801 mdelay(500);
4803 return timeout ? PBOOK_SLEEP_OK : PBOOK_SLEEP_REFUSE;
4806 static int
4807 aty_power_mgmt_LTPro(int sleep, struct fb_info_aty *info)
4809 unsigned int pm;
4810 int timeout;
4812 pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
4813 pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;
4814 aty_st_lcd(LCD_POWER_MANAGEMENT, pm, info);
4815 pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
4817 timeout = 200;
4818 if (sleep) {
4819 /* Sleep */
4820 pm &= ~PWR_MGT_ON;
4821 aty_st_lcd(LCD_POWER_MANAGEMENT, pm, info);
4822 pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
4823 udelay(10);
4824 pm &= ~(PWR_BLON | AUTO_PWR_UP);
4825 pm |= SUSPEND_NOW;
4826 aty_st_lcd(LCD_POWER_MANAGEMENT, pm, info);
4827 pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
4828 udelay(10);
4829 pm |= PWR_MGT_ON;
4830 aty_st_lcd(LCD_POWER_MANAGEMENT, pm, info);
4831 do {
4832 pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
4833 udelay(1000);
4834 if ((--timeout) == 0)
4835 break;
4836 } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
4837 } else {
4838 /* Wakeup */
4839 pm &= ~PWR_MGT_ON;
4840 aty_st_lcd(LCD_POWER_MANAGEMENT, pm, info);
4841 pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
4842 udelay(10);
4843 pm &= ~SUSPEND_NOW;
4844 pm |= (PWR_BLON | AUTO_PWR_UP);
4845 aty_st_lcd(LCD_POWER_MANAGEMENT, pm, info);
4846 pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
4847 udelay(10);
4848 pm |= PWR_MGT_ON;
4849 aty_st_lcd(LCD_POWER_MANAGEMENT, pm, info);
4850 do {
4851 pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
4852 udelay(1000);
4853 if ((--timeout) == 0)
4854 break;
4855 } while ((pm & PWR_MGT_STATUS_MASK) != 0);
4858 return timeout ? PBOOK_SLEEP_OK : PBOOK_SLEEP_REFUSE;
4862 * Save the contents of the frame buffer when we go to sleep,
4863 * and restore it when we wake up again.
4866 aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
4868 struct fb_info_aty *info;
4869 int result;
4871 result = PBOOK_SLEEP_OK;
4873 for (info = first_display; info != NULL; info = info->next) {
4874 struct fb_fix_screeninfo fix;
4875 int nb;
4877 atyfb_get_fix(&fix, fg_console, (struct fb_info *)info);
4878 nb = fb_display[fg_console].var.yres * fix.line_length;
4880 switch (when) {
4881 case PBOOK_SLEEP_REQUEST:
4882 info->save_framebuffer = vmalloc(nb);
4883 if (info->save_framebuffer == NULL)
4884 return PBOOK_SLEEP_REFUSE;
4885 break;
4886 case PBOOK_SLEEP_REJECT:
4887 if (info->save_framebuffer) {
4888 vfree(info->save_framebuffer);
4889 info->save_framebuffer = 0;
4891 break;
4892 case PBOOK_SLEEP_NOW:
4893 if (info->blitter_may_be_busy)
4894 wait_for_idle(info);
4895 /* Stop accel engine (stop bus mastering) */
4896 if (info->current_par.accel_flags & FB_ACCELF_TEXT)
4897 reset_engine(info);
4899 /* Backup fb content */
4900 if (info->save_framebuffer)
4901 memcpy_fromio(info->save_framebuffer,
4902 (void *)info->frame_buffer, nb);
4904 /* Blank display and LCD */
4905 atyfbcon_blank(VESA_POWERDOWN+1, (struct fb_info *)info);
4907 /* Set chip to "suspend" mode */
4908 if (Gx == LG_CHIP_ID)
4909 result = aty_power_mgmt_LT(1, info);
4910 else
4911 result = aty_power_mgmt_LTPro(1, info);
4912 break;
4913 case PBOOK_WAKE:
4914 /* Wakeup chip */
4915 if (Gx == LG_CHIP_ID)
4916 result = aty_power_mgmt_LT(0, info);
4917 else
4918 result = aty_power_mgmt_LTPro(0, info);
4920 /* Restore fb content */
4921 if (info->save_framebuffer) {
4922 memcpy_toio((void *)info->frame_buffer,
4923 info->save_framebuffer, nb);
4924 vfree(info->save_framebuffer);
4925 info->save_framebuffer = 0;
4927 /* Restore display */
4928 atyfb_set_par(&info->current_par, info);
4929 atyfbcon_blank(0, (struct fb_info *)info);
4930 break;
4933 return result;
4935 #endif /* CONFIG_PMAC_PBOOK */
4937 #ifdef MODULE
4938 int __init init_module(void)
4940 atyfb_init();
4941 return fb_list ? 0 : -ENXIO;
4944 void cleanup_module(void)
4946 while (fb_list) {
4947 struct fb_info_aty *info = fb_list;
4948 fb_list = info->next;
4950 unregister_framebuffer(&info->fb_info);
4952 #ifndef __sparc__
4953 if (info->ati_regbase)
4954 iounmap((void *)info->ati_regbase);
4955 if (info->frame_buffer)
4956 iounmap((void *)info->frame_buffer);
4957 #ifdef __BIG_ENDIAN
4958 if (info->cursor && info->cursor->ram)
4959 iounmap(info->cursor->ram);
4960 #endif
4961 #endif
4963 if (info->cursor) {
4964 if (info->cursor->timer)
4965 kfree(info->cursor->timer);
4966 kfree(info->cursor);
4968 #ifdef __sparc__
4969 if (info->mmap_map)
4970 kfree(info->mmap_map);
4971 #endif
4972 kfree(info);
4976 #endif