* better
[mascara-docs.git] / i386 / linux-2.3.21 / drivers / video / atyfb.c
blobedba704a3f7b1f33cc33624b9d5274afc674b0f5
1 /* $Id: atyfb.c,v 1.126 1999/09/16 18:46:23 geert 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 <linux/pmu.h>
67 #include <asm/prom.h>
68 #include <asm/pci-bridge.h>
69 #include <video/macmodes.h>
70 #endif
71 #ifdef CONFIG_NVRAM
72 #include <linux/nvram.h>
73 #endif
74 #ifdef __sparc__
75 #include <asm/pbm.h>
76 #include <asm/fbio.h>
77 #endif
78 #include <asm/uaccess.h>
80 #include <video/fbcon.h>
81 #include <video/fbcon-cfb8.h>
82 #include <video/fbcon-cfb16.h>
83 #include <video/fbcon-cfb24.h>
84 #include <video/fbcon-cfb32.h>
86 #include "aty.h"
90 * Debug flags.
92 #undef DEBUG
94 /* Definitions for the ICS 2595 == ATI 18818_1 Clockchip */
96 #define REF_FREQ_2595 1432 /* 14.33 MHz (exact 14.31818) */
97 #define REF_DIV_2595 46 /* really 43 on ICS 2595 !!! */
98 /* ohne Prescaler */
99 #define MAX_FREQ_2595 15938 /* 159.38 MHz (really 170.486) */
100 #define MIN_FREQ_2595 8000 /* 80.00 MHz ( 85.565) */
101 /* mit Prescaler 2, 4, 8 */
102 #define ABS_MIN_FREQ_2595 1000 /* 10.00 MHz (really 10.697) */
103 #define N_ADJ_2595 257
105 #define STOP_BITS_2595 0x1800
108 #define MIN_N_408 2
110 #define MIN_N_1703 6
112 #define MIN_M 2
113 #define MAX_M 30
114 #define MIN_N 35
115 #define MAX_N 255-8
118 /* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */
119 /* - must be large enough to catch all GUI-Regs */
120 /* - must be aligned to a PAGE boundary */
121 #define GUI_RESERVE (1 * PAGE_SIZE)
124 #ifndef __powerpc__
125 #define eieio() /* Enforce In-order Execution of I/O */
126 #endif
128 /* FIXME: remove the FAIL definition */
129 #define FAIL(x) do { printk(x "\n"); return -EINVAL; } while (0)
133 * Elements of the Hardware specific atyfb_par structure
136 struct crtc {
137 u32 vxres;
138 u32 vyres;
139 u32 xoffset;
140 u32 yoffset;
141 u32 bpp;
142 u32 h_tot_disp;
143 u32 h_sync_strt_wid;
144 u32 v_tot_disp;
145 u32 v_sync_strt_wid;
146 u32 off_pitch;
147 u32 gen_cntl;
148 u32 dp_pix_width; /* acceleration */
149 u32 dp_chain_mask; /* acceleration */
152 struct pll_gx {
153 u8 m;
154 u8 n;
157 struct pll_18818
159 u32 program_bits;
160 u32 locationAddr;
161 u32 period_in_ps;
162 u32 post_divider;
165 struct pll_ct {
166 u8 pll_ref_div;
167 u8 pll_gen_cntl;
168 u8 mclk_fb_div;
169 u8 pll_vclk_cntl;
170 u8 vclk_post_div;
171 u8 vclk_fb_div;
172 u8 pll_ext_cntl;
173 u32 dsp_config; /* Mach64 GTB DSP */
174 u32 dsp_on_off; /* Mach64 GTB DSP */
175 u8 mclk_post_div_real;
176 u8 vclk_post_div_real;
181 * The Hardware parameters for each card
184 struct atyfb_par {
185 struct crtc crtc;
186 union {
187 struct pll_gx gx;
188 struct pll_ct ct;
189 struct pll_18818 ics2595;
190 } pll;
191 u32 accel_flags;
194 struct aty_cmap_regs {
195 u8 windex;
196 u8 lut;
197 u8 mask;
198 u8 rindex;
199 u8 cntl;
202 struct pci_mmap_map {
203 unsigned long voff;
204 unsigned long poff;
205 unsigned long size;
206 unsigned long prot_flag;
207 unsigned long prot_mask;
210 #define DEFAULT_CURSOR_BLINK_RATE (20)
211 #define CURSOR_DRAW_DELAY (2)
213 struct aty_cursor {
214 int enable;
215 int on;
216 int vbl_cnt;
217 int blink_rate;
218 u32 offset;
219 struct {
220 u16 x, y;
221 } pos, hot, size;
222 u32 color[2];
223 u8 bits[8][64];
224 u8 mask[8][64];
225 u8 *ram;
226 struct timer_list *timer;
229 struct fb_info_aty {
230 struct fb_info fb_info;
231 struct fb_info_aty *next;
232 unsigned long ati_regbase_phys;
233 unsigned long ati_regbase;
234 unsigned long frame_buffer_phys;
235 unsigned long frame_buffer;
236 unsigned long clk_wr_offset;
237 struct pci_mmap_map *mmap_map;
238 struct aty_cursor *cursor;
239 struct aty_cmap_regs *aty_cmap_regs;
240 struct { u8 red, green, blue, pad; } palette[256];
241 struct atyfb_par default_par;
242 struct atyfb_par current_par;
243 u32 total_vram;
244 u32 ref_clk_per;
245 u32 pll_per;
246 u32 mclk_per;
247 u16 chip_type;
248 #define Gx info->chip_type
249 u8 chip_rev;
250 #define Rev info->chip_rev
251 u8 bus_type;
252 u8 ram_type;
253 u8 dac_type;
254 u8 dac_subtype;
255 u8 clk_type;
256 u8 mem_refresh_rate;
257 struct display disp;
258 struct display_switch dispsw;
259 union {
260 #ifdef FBCON_HAS_CFB16
261 u16 cfb16[16];
262 #endif
263 #ifdef FBCON_HAS_CFB24
264 u32 cfb24[16];
265 #endif
266 #ifdef FBCON_HAS_CFB32
267 u32 cfb32[16];
268 #endif
269 } fbcon_cmap;
270 u8 blitter_may_be_busy;
271 #ifdef __sparc__
272 u8 open;
273 u8 mmaped;
274 int vtconsole;
275 int consolecnt;
276 #endif
277 #ifdef CONFIG_PMAC_PBOOK
278 unsigned char *save_framebuffer;
279 unsigned long save_pll[64];
280 #endif
283 #ifdef CONFIG_PMAC_PBOOK
284 int aty_sleep_notify(struct pmu_sleep_notifier *self, int when);
285 static struct pmu_sleep_notifier aty_sleep_notifier = {
286 aty_sleep_notify, SLEEP_LEVEL_VIDEO,
288 static struct fb_info_aty* first_display = NULL;
289 #endif
293 * Frame buffer device API
296 static int atyfb_open(struct fb_info *info, int user);
297 static int atyfb_release(struct fb_info *info, int user);
298 static int atyfb_get_fix(struct fb_fix_screeninfo *fix, int con,
299 struct fb_info *fb);
300 static int atyfb_get_var(struct fb_var_screeninfo *var, int con,
301 struct fb_info *fb);
302 static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
303 struct fb_info *fb);
304 static int atyfb_pan_display(struct fb_var_screeninfo *var, int con,
305 struct fb_info *fb);
306 static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
307 struct fb_info *info);
308 static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
309 struct fb_info *info);
310 static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
311 u_long arg, int con, struct fb_info *info);
312 #ifdef __sparc__
313 static int atyfb_mmap(struct fb_info *info, struct file *file,
314 struct vm_area_struct *vma);
315 #endif
316 static int atyfb_rasterimg(struct fb_info *info, int start);
320 * Interface to the low level console driver
323 static int atyfbcon_switch(int con, struct fb_info *fb);
324 static int atyfbcon_updatevar(int con, struct fb_info *fb);
325 static void atyfbcon_blank(int blank, struct fb_info *fb);
329 * Text console acceleration
332 static void fbcon_aty_bmove(struct display *p, int sy, int sx, int dy, int dx,
333 int height, int width);
334 static void fbcon_aty_clear(struct vc_data *conp, struct display *p, int sy,
335 int sx, int height, int width);
336 #ifdef FBCON_HAS_CFB8
337 static struct display_switch fbcon_aty8;
338 static void fbcon_aty8_putc(struct vc_data *conp, struct display *p, int c,
339 int yy, int xx);
340 static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p,
341 const unsigned short *s, int count, int yy,
342 int xx);
343 #endif
344 #ifdef FBCON_HAS_CFB16
345 static struct display_switch fbcon_aty16;
346 static void fbcon_aty16_putc(struct vc_data *conp, struct display *p, int c,
347 int yy, int xx);
348 static void fbcon_aty16_putcs(struct vc_data *conp, struct display *p,
349 const unsigned short *s, int count, int yy,
350 int xx);
351 #endif
352 #ifdef FBCON_HAS_CFB24
353 static struct display_switch fbcon_aty24;
354 static void fbcon_aty24_putc(struct vc_data *conp, struct display *p, int c,
355 int yy, int xx);
356 static void fbcon_aty24_putcs(struct vc_data *conp, struct display *p,
357 const unsigned short *s, int count, int yy,
358 int xx);
359 #endif
360 #ifdef FBCON_HAS_CFB32
361 static struct display_switch fbcon_aty32;
362 static void fbcon_aty32_putc(struct vc_data *conp, struct display *p, int c,
363 int yy, int xx);
364 static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p,
365 const unsigned short *s, int count, int yy,
366 int xx);
367 #endif
371 * Internal routines
374 static int aty_init(struct fb_info_aty *info, const char *name);
375 static struct aty_cursor *aty_init_cursor(struct fb_info_aty *fb);
376 #ifdef CONFIG_ATARI
377 static int store_video_par(char *videopar, unsigned char m64_num);
378 static char *strtoke(char *s, const char *ct);
379 #endif
381 static void reset_engine(const struct fb_info_aty *info);
382 static void init_engine(const struct atyfb_par *par, struct fb_info_aty *info);
384 static void aty_st_514(int offset, u8 val, const struct fb_info_aty *info);
385 static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info);
386 static u8 aty_ld_pll(int offset, const struct fb_info_aty *info);
387 static void aty_set_crtc(const struct fb_info_aty *info,
388 const struct crtc *crtc);
389 static int aty_var_to_crtc(const struct fb_info_aty *info,
390 const struct fb_var_screeninfo *var,
391 struct crtc *crtc);
392 static void aty_set_dac_514(const struct fb_info_aty *info, u32 bpp);
393 static int aty_crtc_to_var(const struct crtc *crtc,
394 struct fb_var_screeninfo *var);
395 static void aty_set_pll_gx(const struct fb_info_aty *info,
396 const struct pll_gx *pll);
398 static int aty_set_dac_ATI68860_B(const struct fb_info_aty *info, u32 bpp,
399 u32 AccelMode);
400 static int aty_set_dac_ATT21C498(const struct fb_info_aty *info,
401 const struct pll_18818 *pll, u32 bpp);
402 void aty_dac_waste4(const struct fb_info_aty *info);
404 static int aty_var_to_pll_18818(u32 period_in_ps, struct pll_18818 *pll);
405 static u32 aty_pll_18818_to_var(const struct pll_18818 *pll);
406 static void aty_set_pll18818(const struct fb_info_aty *info,
407 const struct pll_18818 *pll);
409 static void aty_StrobeClock(const struct fb_info_aty *info);
411 static void aty_ICS2595_put1bit(u8 data, const struct fb_info_aty *info);
413 static int aty_var_to_pll_408(u32 period_in_ps, struct pll_18818 *pll);
414 static u32 aty_pll_408_to_var(const struct pll_18818 *pll);
415 static void aty_set_pll_408(const struct fb_info_aty *info,
416 const struct pll_18818 *pll);
418 static int aty_var_to_pll_1703(u32 period_in_ps, struct pll_18818 *pll);
419 static u32 aty_pll_1703_to_var(const struct pll_18818 *pll);
420 static void aty_set_pll_1703(const struct fb_info_aty *info,
421 const struct pll_18818 *pll);
423 static int aty_var_to_pll_8398(u32 period_in_ps, struct pll_18818 *pll);
424 static u32 aty_pll_8398_to_var(const struct pll_18818 *pll);
425 static void aty_set_pll_8398(const struct fb_info_aty *info,
426 const struct pll_18818 *pll);
428 static int aty_var_to_pll_514(u32 vclk_per, struct pll_gx *pll);
429 static u32 aty_pll_gx_to_var(const struct pll_gx *pll,
430 const struct fb_info_aty *info);
431 static void aty_set_pll_ct(const struct fb_info_aty *info,
432 const struct pll_ct *pll);
433 static int aty_valid_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
434 struct pll_ct *pll);
435 static int aty_dsp_gt(const struct fb_info_aty *info, u8 bpp,
436 struct pll_ct *pll);
437 static void aty_calc_pll_ct(const struct fb_info_aty *info,
438 struct pll_ct *pll);
439 static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
440 u8 bpp, struct pll_ct *pll);
441 static u32 aty_pll_ct_to_var(const struct pll_ct *pll,
442 const struct fb_info_aty *info);
443 static void atyfb_set_par(const struct atyfb_par *par,
444 struct fb_info_aty *info);
445 static int atyfb_decode_var(const struct fb_var_screeninfo *var,
446 struct atyfb_par *par,
447 const struct fb_info_aty *info);
448 static int atyfb_encode_var(struct fb_var_screeninfo *var,
449 const struct atyfb_par *par,
450 const struct fb_info_aty *info);
451 static void set_off_pitch(struct atyfb_par *par,
452 const struct fb_info_aty *info);
453 static int encode_fix(struct fb_fix_screeninfo *fix,
454 const struct atyfb_par *par,
455 const struct fb_info_aty *info);
456 static void atyfb_set_disp(struct display *disp, struct fb_info_aty *info,
457 int bpp, int accel);
458 static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
459 u_int *transp, struct fb_info *fb);
460 static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
461 u_int transp, struct fb_info *fb);
462 static void do_install_cmap(int con, struct fb_info *info);
463 #ifdef CONFIG_PMAC
464 static int read_aty_sense(const struct fb_info_aty *info);
465 #endif
469 * Interface used by the world
472 int atyfb_init(void);
473 #ifdef CONFIG_FB_OF
474 void atyfb_of_init(struct device_node *dp);
475 #endif
476 #ifndef MODULE
477 int atyfb_setup(char*);
478 #endif
480 static int currcon = 0;
482 static struct fb_ops atyfb_ops = {
483 atyfb_open, atyfb_release, atyfb_get_fix, atyfb_get_var, atyfb_set_var,
484 atyfb_get_cmap, atyfb_set_cmap, atyfb_pan_display, atyfb_ioctl,
485 #ifdef __sparc__
486 atyfb_mmap,
487 #else
488 NULL,
489 #endif
490 atyfb_rasterimg
493 static char atyfb_name[16] = "ATY Mach64";
494 static char fontname[40] __initdata = { 0 };
495 static char curblink __initdata = 1;
496 static char noaccel __initdata = 0;
497 static u32 default_vram __initdata = 0;
498 static int default_pll __initdata = 0;
499 static int default_mclk __initdata = 0;
501 #ifndef MODULE
502 static const char *mode_option __initdata = NULL;
503 #endif
505 #ifdef CONFIG_PMAC
506 #ifdef CONFIG_NVRAM
507 static int default_vmode __initdata = VMODE_NVRAM;
508 static int default_cmode __initdata = CMODE_NVRAM;
509 #else
510 static int default_vmode __initdata = VMODE_CHOOSE;
511 static int default_cmode __initdata = CMODE_CHOOSE;
512 #endif
513 #endif
515 #ifdef CONFIG_ATARI
516 static unsigned int mach64_count __initdata = 0;
517 static unsigned long phys_vmembase[FB_MAX] __initdata = { 0, };
518 static unsigned long phys_size[FB_MAX] __initdata = { 0, };
519 static unsigned long phys_guiregbase[FB_MAX] __initdata = { 0, };
520 #endif
523 static struct aty_features {
524 u16 pci_id;
525 u16 chip_type;
526 const char *name;
527 } aty_features[] __initdata = {
528 /* mach64GX family */
529 { 0x4758, 0x00d7, "mach64GX (ATI888GX00)" },
530 { 0x4358, 0x0057, "mach64CX (ATI888CX00)" },
532 /* mach64CT family */
533 { 0x4354, 0x4354, "mach64CT (ATI264CT)" },
534 { 0x4554, 0x4554, "mach64ET (ATI264ET)" },
536 /* mach64CT family / mach64VT class */
537 { 0x5654, 0x5654, "mach64VT (ATI264VT)" },
538 { 0x5655, 0x5655, "mach64VTB (ATI264VTB)" },
539 { 0x5656, 0x5656, "mach64VT4 (ATI264VT4)" },
541 /* mach64CT family / mach64GT (3D RAGE) class */
542 { 0x4c42, 0x4c42, "3D RAGE LT PRO (AGP)" },
543 { 0x4c44, 0x4c44, "3D RAGE LT PRO" },
544 { 0x4c47, 0x4c47, "3D RAGE LT PRO" },
545 { 0x4c49, 0x4c49, "3D RAGE LT PRO" },
546 { 0x4c50, 0x4c50, "3D RAGE LT PRO" },
547 { 0x4c54, 0x4c54, "3D RAGE LT" },
548 { 0x4754, 0x4754, "3D RAGE (GT)" },
549 { 0x4755, 0x4755, "3D RAGE II+ (GTB)" },
550 { 0x4756, 0x4756, "3D RAGE IIC (PCI)" },
551 { 0x4757, 0x4757, "3D RAGE IIC (AGP)" },
552 { 0x475a, 0x475a, "3D RAGE IIC (AGP)" },
553 { 0x4742, 0x4742, "3D RAGE PRO (BGA, AGP)" },
554 { 0x4744, 0x4744, "3D RAGE PRO (BGA, AGP, 1x only)" },
555 { 0x4749, 0x4749, "3D RAGE PRO (BGA, PCI)" },
556 { 0x4750, 0x4750, "3D RAGE PRO (PQFP, PCI)" },
557 { 0x4751, 0x4751, "3D RAGE PRO (PQFP, PCI, limited 3D)" },
560 static const char *aty_gx_ram[8] __initdata = {
561 "DRAM", "VRAM", "VRAM", "DRAM", "DRAM", "VRAM", "VRAM", "RESV"
564 static const char *aty_ct_ram[8] __initdata = {
565 "OFF", "DRAM", "EDO", "EDO", "SDRAM", "SGRAM", "WRAM", "RESV"
569 static inline u32 aty_ld_le32(unsigned int regindex,
570 const struct fb_info_aty *info)
572 #if defined(__powerpc__)
573 unsigned long temp;
574 u32 val;
576 temp = info->ati_regbase;
577 asm volatile("lwbrx %0,%1,%2" : "=r"(val) : "b" (regindex), "r" (temp));
578 return val;
579 #elif defined(__mc68000__)
580 return le32_to_cpu(*((volatile u32 *)(info->ati_regbase+regindex)));
581 #else
582 return readl (info->ati_regbase + regindex);
583 #endif
586 static inline void aty_st_le32(unsigned int regindex, u32 val,
587 const struct fb_info_aty *info)
589 #if defined(__powerpc__)
590 unsigned long temp;
592 temp = info->ati_regbase;
593 asm volatile("stwbrx %0,%1,%2" : : "r" (val), "b" (regindex), "r" (temp) :
594 "memory");
595 #elif defined(__mc68000__)
596 *((volatile u32 *)(info->ati_regbase+regindex)) = cpu_to_le32(val);
597 #else
598 writel (val, info->ati_regbase + regindex);
599 #endif
602 static inline u8 aty_ld_8(unsigned int regindex,
603 const struct fb_info_aty *info)
605 return readb (info->ati_regbase + regindex);
608 static inline void aty_st_8(unsigned int regindex, u8 val,
609 const struct fb_info_aty *info)
611 writeb (val, info->ati_regbase + regindex);
616 * Generic Mach64 routines
620 * All writes to draw engine registers are automatically routed through a
621 * 32-bit-wide, 16-entry-deep command FIFO ...
622 * Register writes to registers with DWORD offsets less than 40h are not
623 * FIFOed.
624 * (from Chapter 5 of the Mach64 Programmer's Guide)
627 static inline void wait_for_fifo(u16 entries, const struct fb_info_aty *info)
629 while ((aty_ld_le32(FIFO_STAT, info) & 0xffff) >
630 ((u32)(0x8000 >> entries)));
633 static inline void wait_for_idle(struct fb_info_aty *info)
635 wait_for_fifo(16, info);
636 while ((aty_ld_le32(GUI_STAT, info) & 1)!= 0);
637 info->blitter_may_be_busy = 0;
640 static void reset_engine(const struct fb_info_aty *info)
642 /* reset engine */
643 aty_st_le32(GEN_TEST_CNTL,
644 aty_ld_le32(GEN_TEST_CNTL, info) & ~GUI_ENGINE_ENABLE, info);
645 /* enable engine */
646 aty_st_le32(GEN_TEST_CNTL,
647 aty_ld_le32(GEN_TEST_CNTL, info) | GUI_ENGINE_ENABLE, info);
648 /* ensure engine is not locked up by clearing any FIFO or */
649 /* HOST errors */
650 aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, info) | BUS_HOST_ERR_ACK |
651 BUS_FIFO_ERR_ACK, info);
654 static void init_engine(const struct atyfb_par *par, struct fb_info_aty *info)
656 u32 pitch_value;
658 /* determine modal information from global mode structure */
659 pitch_value = par->crtc.vxres;
661 if (par->crtc.bpp == 24) {
662 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
663 /* horizontal coordinates and widths must be adjusted */
664 pitch_value = pitch_value * 3;
667 /* Reset engine, enable, and clear any engine errors */
668 reset_engine(info);
669 /* Ensure that vga page pointers are set to zero - the upper */
670 /* page pointers are set to 1 to handle overflows in the */
671 /* lower page */
672 aty_st_le32(MEM_VGA_WP_SEL, 0x00010000, info);
673 aty_st_le32(MEM_VGA_RP_SEL, 0x00010000, info);
675 /* ---- Setup standard engine context ---- */
677 /* All GUI registers here are FIFOed - therefore, wait for */
678 /* the appropriate number of empty FIFO entries */
679 wait_for_fifo(14, info);
681 /* enable all registers to be loaded for context loads */
682 aty_st_le32(CONTEXT_MASK, 0xFFFFFFFF, info);
684 /* set destination pitch to modal pitch, set offset to zero */
685 aty_st_le32(DST_OFF_PITCH, (pitch_value / 8) << 22, info);
687 /* zero these registers (set them to a known state) */
688 aty_st_le32(DST_Y_X, 0, info);
689 aty_st_le32(DST_HEIGHT, 0, info);
690 aty_st_le32(DST_BRES_ERR, 0, info);
691 aty_st_le32(DST_BRES_INC, 0, info);
692 aty_st_le32(DST_BRES_DEC, 0, info);
694 /* set destination drawing attributes */
695 aty_st_le32(DST_CNTL, DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM |
696 DST_X_LEFT_TO_RIGHT, info);
698 /* set source pitch to modal pitch, set offset to zero */
699 aty_st_le32(SRC_OFF_PITCH, (pitch_value / 8) << 22, info);
701 /* set these registers to a known state */
702 aty_st_le32(SRC_Y_X, 0, info);
703 aty_st_le32(SRC_HEIGHT1_WIDTH1, 1, info);
704 aty_st_le32(SRC_Y_X_START, 0, info);
705 aty_st_le32(SRC_HEIGHT2_WIDTH2, 1, info);
707 /* set source pixel retrieving attributes */
708 aty_st_le32(SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT, info);
710 /* set host attributes */
711 wait_for_fifo(13, info);
712 aty_st_le32(HOST_CNTL, 0, info);
714 /* set pattern attributes */
715 aty_st_le32(PAT_REG0, 0, info);
716 aty_st_le32(PAT_REG1, 0, info);
717 aty_st_le32(PAT_CNTL, 0, info);
719 /* set scissors to modal size */
720 aty_st_le32(SC_LEFT, 0, info);
721 aty_st_le32(SC_TOP, 0, info);
722 aty_st_le32(SC_BOTTOM, par->crtc.vyres-1, info);
723 aty_st_le32(SC_RIGHT, pitch_value-1, info);
725 /* set background color to minimum value (usually BLACK) */
726 aty_st_le32(DP_BKGD_CLR, 0, info);
728 /* set foreground color to maximum value (usually WHITE) */
729 aty_st_le32(DP_FRGD_CLR, 0xFFFFFFFF, info);
731 /* set write mask to effect all pixel bits */
732 aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF, info);
734 /* set foreground mix to overpaint and background mix to */
735 /* no-effect */
736 aty_st_le32(DP_MIX, FRGD_MIX_S | BKGD_MIX_D, info);
738 /* set primary source pixel channel to foreground color */
739 /* register */
740 aty_st_le32(DP_SRC, FRGD_SRC_FRGD_CLR, info);
742 /* set compare functionality to false (no-effect on */
743 /* destination) */
744 wait_for_fifo(3, info);
745 aty_st_le32(CLR_CMP_CLR, 0, info);
746 aty_st_le32(CLR_CMP_MASK, 0xFFFFFFFF, info);
747 aty_st_le32(CLR_CMP_CNTL, 0, info);
749 /* set pixel depth */
750 wait_for_fifo(2, info);
751 aty_st_le32(DP_PIX_WIDTH, par->crtc.dp_pix_width, info);
752 aty_st_le32(DP_CHAIN_MASK, par->crtc.dp_chain_mask, info);
754 wait_for_fifo(5, info);
755 aty_st_le32(SCALE_3D_CNTL, 0, info);
756 aty_st_le32(Z_CNTL, 0, info);
757 aty_st_le32(CRTC_INT_CNTL, aty_ld_le32(CRTC_INT_CNTL, info) & ~0x20, info);
758 aty_st_le32(GUI_TRAJ_CNTL, 0x100023, info);
760 /* insure engine is idle before leaving */
761 wait_for_idle(info);
764 static void aty_st_514(int offset, u8 val, const struct fb_info_aty *info)
766 aty_st_8(DAC_CNTL, 1, info);
767 /* right addr byte */
768 aty_st_8(DAC_W_INDEX, offset & 0xff, info);
769 /* left addr byte */
770 aty_st_8(DAC_DATA, (offset >> 8) & 0xff, info);
771 eieio();
772 aty_st_8(DAC_MASK, val, info);
773 eieio();
774 aty_st_8(DAC_CNTL, 0, info);
777 static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info)
779 /* write addr byte */
780 aty_st_8(CLOCK_CNTL + 1, (offset << 2) | PLL_WR_EN, info);
781 eieio();
782 /* write the register value */
783 aty_st_8(CLOCK_CNTL + 2, val, info);
784 eieio();
785 aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, info);
788 static u8 aty_ld_pll(int offset, const struct fb_info_aty *info)
790 u8 res;
792 /* write addr byte */
793 aty_st_8(CLOCK_CNTL + 1, (offset << 2), info);
794 eieio();
795 /* read the register value */
796 res = aty_ld_8(CLOCK_CNTL + 2, info);
797 eieio();
798 return res;
801 #ifdef CONFIG_PMAC
804 * Apple monitor sense
807 static int read_aty_sense(const struct fb_info_aty *info)
809 int sense, i;
811 aty_st_le32(GP_IO, 0x31003100, info); /* drive outputs high */
812 __delay(200);
813 aty_st_le32(GP_IO, 0, info); /* turn off outputs */
814 __delay(2000);
815 i = aty_ld_le32(GP_IO, info); /* get primary sense value */
816 sense = ((i & 0x3000) >> 3) | (i & 0x100);
818 /* drive each sense line low in turn and collect the other 2 */
819 aty_st_le32(GP_IO, 0x20000000, info); /* drive A low */
820 __delay(2000);
821 i = aty_ld_le32(GP_IO, info);
822 sense |= ((i & 0x1000) >> 7) | ((i & 0x100) >> 4);
823 aty_st_le32(GP_IO, 0x20002000, info); /* drive A high again */
824 __delay(200);
826 aty_st_le32(GP_IO, 0x10000000, info); /* drive B low */
827 __delay(2000);
828 i = aty_ld_le32(GP_IO, info);
829 sense |= ((i & 0x2000) >> 10) | ((i & 0x100) >> 6);
830 aty_st_le32(GP_IO, 0x10001000, info); /* drive B high again */
831 __delay(200);
833 aty_st_le32(GP_IO, 0x01000000, info); /* drive C low */
834 __delay(2000);
835 sense |= (aty_ld_le32(GP_IO, info) & 0x3000) >> 12;
836 aty_st_le32(GP_IO, 0, info); /* turn off outputs */
838 return sense;
841 #endif /* CONFIG_PMAC */
843 /* ------------------------------------------------------------------------- */
846 * Hardware Cursor support.
849 static u8 cursor_pixel_map[2] = { 0, 15 };
850 static u8 cursor_color_map[2] = { 0, 0xff };
852 static u8 cursor_bits_lookup[16] =
854 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
855 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
858 static u8 cursor_mask_lookup[16] =
860 0xaa, 0x2a, 0x8a, 0x0a, 0xa2, 0x22, 0x82, 0x02,
861 0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00
864 static void
865 aty_set_cursor_color(struct fb_info_aty *fb, u8 *pixel,
866 u8 *red, u8 *green, u8 *blue)
868 struct aty_cursor *c = fb->cursor;
869 int i;
871 if (!c)
872 return;
874 #ifdef __sparc__
875 if (fb->mmaped && (!fb->fb_info.display_fg
876 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
877 return;
878 #endif
880 for (i = 0; i < 2; i++) {
881 c->color[i] = (u32)red[i] << 24;
882 c->color[i] |= (u32)green[i] << 16;
883 c->color[i] |= (u32)blue[i] << 8;
884 c->color[i] |= (u32)pixel[i];
887 wait_for_fifo(2, fb);
888 aty_st_le32(CUR_CLR0, c->color[0], fb);
889 aty_st_le32(CUR_CLR1, c->color[1], fb);
892 static void
893 aty_set_cursor_shape(struct fb_info_aty *fb)
895 struct aty_cursor *c = fb->cursor;
896 u8 *ram, m, b;
897 int x, y;
899 if (!c)
900 return;
902 #ifdef __sparc__
903 if (fb->mmaped && (!fb->fb_info.display_fg
904 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
905 return;
906 #endif
908 ram = c->ram;
909 for (y = 0; y < c->size.y; y++) {
910 for (x = 0; x < c->size.x >> 2; x++) {
911 m = c->mask[x][y];
912 b = c->bits[x][y];
913 fb_writeb (cursor_mask_lookup[m >> 4] |
914 cursor_bits_lookup[(b & m) >> 4],
915 ram++);
916 fb_writeb (cursor_mask_lookup[m & 0x0f] |
917 cursor_bits_lookup[(b & m) & 0x0f],
918 ram++);
920 for ( ; x < 8; x++) {
921 fb_writeb (0xaa, ram++);
922 fb_writeb (0xaa, ram++);
925 fb_memset (ram, 0xaa, (64 - c->size.y) * 16);
928 static void
929 aty_set_cursor(struct fb_info_aty *fb, int on)
931 struct atyfb_par *par = &fb->current_par;
932 struct aty_cursor *c = fb->cursor;
933 u16 xoff, yoff;
934 int x, y;
936 if (!c)
937 return;
939 #ifdef __sparc__
940 if (fb->mmaped && (!fb->fb_info.display_fg
941 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
942 return;
943 #endif
945 if (on) {
946 x = c->pos.x - c->hot.x - par->crtc.xoffset;
947 if (x < 0) {
948 xoff = -x;
949 x = 0;
950 } else {
951 xoff = 0;
954 y = c->pos.y - c->hot.y - par->crtc.yoffset;
955 if (y < 0) {
956 yoff = -y;
957 y = 0;
958 } else {
959 yoff = 0;
962 wait_for_fifo(4, fb);
963 aty_st_le32(CUR_OFFSET, (c->offset >> 3) + (yoff << 1), fb);
964 aty_st_le32(CUR_HORZ_VERT_OFF,
965 ((u32)(64 - c->size.y + yoff) << 16) | xoff, fb);
966 aty_st_le32(CUR_HORZ_VERT_POSN, ((u32)y << 16) | x, fb);
967 aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, fb)
968 | HWCURSOR_ENABLE, fb);
969 } else {
970 wait_for_fifo(1, fb);
971 aty_st_le32(GEN_TEST_CNTL,
972 aty_ld_le32(GEN_TEST_CNTL, fb) & ~HWCURSOR_ENABLE,
973 fb);
975 if (fb->blitter_may_be_busy)
976 wait_for_idle(fb);
979 static void
980 aty_cursor_timer_handler(unsigned long dev_addr)
982 struct fb_info_aty *fb = (struct fb_info_aty *)dev_addr;
984 if (!fb->cursor)
985 return;
987 if (!fb->cursor->enable)
988 goto out;
990 if (fb->cursor->vbl_cnt && --fb->cursor->vbl_cnt == 0) {
991 fb->cursor->on ^= 1;
992 aty_set_cursor(fb, fb->cursor->on);
993 fb->cursor->vbl_cnt = fb->cursor->blink_rate;
996 out:
997 fb->cursor->timer->expires = jiffies + (HZ / 50);
998 add_timer(fb->cursor->timer);
1001 static void
1002 atyfb_cursor(struct display *p, int mode, int x, int y)
1004 struct fb_info_aty *fb = (struct fb_info_aty *)p->fb_info;
1005 struct aty_cursor *c = fb->cursor;
1007 if (!c)
1008 return;
1010 #ifdef __sparc__
1011 if (fb->mmaped && (!fb->fb_info.display_fg
1012 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
1013 return;
1014 #endif
1016 x *= fontwidth(p);
1017 y *= fontheight(p);
1018 if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->enable)
1019 return;
1021 c->enable = 0;
1022 if (c->on)
1023 aty_set_cursor(fb, 0);
1024 c->pos.x = x;
1025 c->pos.y = y;
1027 switch (mode) {
1028 case CM_ERASE:
1029 c->on = 0;
1030 break;
1032 case CM_DRAW:
1033 case CM_MOVE:
1034 if (c->on)
1035 aty_set_cursor(fb, 1);
1036 else
1037 c->vbl_cnt = CURSOR_DRAW_DELAY;
1038 c->enable = 1;
1039 break;
1043 static struct fb_info_aty *fb_list = NULL;
1045 static struct aty_cursor * __init
1046 aty_init_cursor(struct fb_info_aty *fb)
1048 struct aty_cursor *cursor;
1049 unsigned long addr;
1051 cursor = kmalloc(sizeof(struct aty_cursor), GFP_ATOMIC);
1052 if (!cursor)
1053 return 0;
1054 memset(cursor, 0, sizeof(*cursor));
1056 cursor->timer = kmalloc(sizeof(*cursor->timer), GFP_KERNEL);
1057 if (!cursor->timer) {
1058 kfree(cursor);
1059 return 0;
1061 memset(cursor->timer, 0, sizeof(*cursor->timer));
1063 cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE;
1064 fb->total_vram -= PAGE_SIZE;
1065 cursor->offset = fb->total_vram;
1067 #ifdef __sparc__
1068 addr = fb->frame_buffer - 0x800000 + cursor->offset;
1069 cursor->ram = (u8 *)addr;
1070 #else
1071 #ifdef __BIG_ENDIAN
1072 addr = fb->frame_buffer_phys - 0x800000 + cursor->offset;
1073 cursor->ram = (u8 *)ioremap(addr, 1024);
1074 #else
1075 addr = fb->frame_buffer + cursor->offset;
1076 cursor->ram = (u8 *)addr;
1077 #endif
1078 #endif
1080 if (! cursor->ram) {
1081 kfree(cursor);
1082 return NULL;
1085 if (curblink) {
1086 init_timer(cursor->timer);
1087 cursor->timer->expires = jiffies + (HZ / 50);
1088 cursor->timer->data = (unsigned long)fb;
1089 cursor->timer->function = aty_cursor_timer_handler;
1090 add_timer(cursor->timer);
1093 return cursor;
1096 static int
1097 atyfb_set_font(struct display *d, int width, int height)
1099 struct fb_info_aty *fb = (struct fb_info_aty *)d->fb_info;
1100 struct aty_cursor *c = fb->cursor;
1101 int i, j;
1103 if (c) {
1104 if (!width || !height) {
1105 width = 8;
1106 height = 16;
1109 c->hot.x = 0;
1110 c->hot.y = 0;
1111 c->size.x = width;
1112 c->size.y = height;
1114 memset(c->bits, 0xff, sizeof(c->bits));
1115 memset(c->mask, 0, sizeof(c->mask));
1117 for (i = 0, j = width; j >= 0; j -= 8, i++) {
1118 c->mask[i][height-2] = (j >= 8) ? 0xff : (0xff << (8 - j));
1119 c->mask[i][height-1] = (j >= 8) ? 0xff : (0xff << (8 - j));
1122 aty_set_cursor_color(fb, cursor_pixel_map, cursor_color_map,
1123 cursor_color_map, cursor_color_map);
1124 aty_set_cursor_shape(fb);
1126 return 1;
1132 /* ------------------------------------------------------------------------- */
1135 * CRTC programming
1138 static void aty_set_crtc(const struct fb_info_aty *info,
1139 const struct crtc *crtc)
1141 aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, info);
1142 aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, info);
1143 aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_tot_disp, info);
1144 aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid, info);
1145 aty_st_le32(CRTC_VLINE_CRNT_VLINE, 0, info);
1146 aty_st_le32(CRTC_OFF_PITCH, crtc->off_pitch, info);
1147 aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl, info);
1150 static int aty_var_to_crtc(const struct fb_info_aty *info,
1151 const struct fb_var_screeninfo *var,
1152 struct crtc *crtc)
1154 u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
1155 u32 left, right, upper, lower, hslen, vslen, sync, vmode;
1156 u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
1157 u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
1158 u32 pix_width, dp_pix_width, dp_chain_mask;
1160 /* input */
1161 xres = var->xres;
1162 yres = var->yres;
1163 vxres = var->xres_virtual;
1164 vyres = var->yres_virtual;
1165 xoffset = var->xoffset;
1166 yoffset = var->yoffset;
1167 bpp = var->bits_per_pixel;
1168 left = var->left_margin;
1169 right = var->right_margin;
1170 upper = var->upper_margin;
1171 lower = var->lower_margin;
1172 hslen = var->hsync_len;
1173 vslen = var->vsync_len;
1174 sync = var->sync;
1175 vmode = var->vmode;
1177 /* convert (and round up) and validate */
1178 xres = (xres+7) & ~7;
1179 xoffset = (xoffset+7) & ~7;
1180 vxres = (vxres+7) & ~7;
1181 if (vxres < xres+xoffset)
1182 vxres = xres+xoffset;
1183 h_disp = xres/8-1;
1184 if (h_disp > 0xff)
1185 FAIL("h_disp too large");
1186 h_sync_strt = h_disp+(right/8);
1187 if (h_sync_strt > 0x1ff)
1188 FAIL("h_sync_start too large");
1189 h_sync_dly = right & 7;
1190 h_sync_wid = (hslen+7)/8;
1191 if (h_sync_wid > 0x1f)
1192 FAIL("h_sync_wid too large");
1193 h_total = h_sync_strt+h_sync_wid+(h_sync_dly+left+7)/8;
1194 if (h_total > 0x1ff)
1195 FAIL("h_total too large");
1196 h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
1198 if (vyres < yres+yoffset)
1199 vyres = yres+yoffset;
1200 v_disp = yres-1;
1201 if (v_disp > 0x7ff)
1202 FAIL("v_disp too large");
1203 v_sync_strt = v_disp+lower;
1204 if (v_sync_strt > 0x7ff)
1205 FAIL("v_sync_strt too large");
1206 v_sync_wid = vslen;
1207 if (v_sync_wid > 0x1f)
1208 FAIL("v_sync_wid too large");
1209 v_total = v_sync_strt+v_sync_wid+upper;
1210 if (v_total > 0x7ff)
1211 FAIL("v_total too large");
1212 v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
1214 c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;
1216 if (bpp <= 8) {
1217 bpp = 8;
1218 pix_width = CRTC_PIX_WIDTH_8BPP;
1219 dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB;
1220 dp_chain_mask = 0x8080;
1221 } else if (bpp <= 16) {
1222 bpp = 16;
1223 pix_width = CRTC_PIX_WIDTH_15BPP;
1224 dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP |
1225 BYTE_ORDER_LSB_TO_MSB;
1226 dp_chain_mask = 0x4210;
1227 } else if ((bpp <= 24) && (Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
1228 bpp = 24;
1229 pix_width = CRTC_PIX_WIDTH_24BPP;
1230 dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB;
1231 dp_chain_mask = 0x8080;
1232 } else if (bpp <= 32) {
1233 bpp = 32;
1234 pix_width = CRTC_PIX_WIDTH_32BPP;
1235 dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP |
1236 BYTE_ORDER_LSB_TO_MSB;
1237 dp_chain_mask = 0x8080;
1238 } else
1239 FAIL("invalid bpp");
1241 if (vxres*vyres*bpp/8 > info->total_vram)
1242 FAIL("not enough video RAM");
1244 if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
1245 FAIL("invalid vmode");
1247 /* output */
1248 crtc->vxres = vxres;
1249 crtc->vyres = vyres;
1250 crtc->xoffset = xoffset;
1251 crtc->yoffset = yoffset;
1252 crtc->bpp = bpp;
1253 crtc->h_tot_disp = h_total | (h_disp<<16);
1254 crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly<<8) |
1255 ((h_sync_strt & 0x100)<<4) | (h_sync_wid<<16) |
1256 (h_sync_pol<<21);
1257 crtc->v_tot_disp = v_total | (v_disp<<16);
1258 crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid<<16) | (v_sync_pol<<21);
1259 crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19);
1260 crtc->gen_cntl = pix_width | c_sync | CRTC_EXT_DISP_EN | CRTC_ENABLE;
1261 if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID) ||
1262 ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07))) {
1263 /* Not VTB/GTB */
1264 /* FIXME: magic FIFO values */
1265 crtc->gen_cntl |= aty_ld_le32(CRTC_GEN_CNTL, info) & 0x000e0000;
1267 crtc->dp_pix_width = dp_pix_width;
1268 crtc->dp_chain_mask = dp_chain_mask;
1270 return 0;
1274 static int aty_set_dac_ATI68860_B(const struct fb_info_aty *info, u32 bpp,
1275 u32 AccelMode)
1277 u32 gModeReg, devSetupRegA, temp, mask;
1279 gModeReg = 0;
1280 devSetupRegA = 0;
1282 switch (bpp) {
1283 case 8:
1284 gModeReg = 0x83;
1285 devSetupRegA = 0x60 | 0x00 /*(info->mach64DAC8Bit ? 0x00 : 0x01) */;
1286 break;
1287 case 15:
1288 gModeReg = 0xA0;
1289 devSetupRegA = 0x60;
1290 break;
1291 case 16:
1292 gModeReg = 0xA1;
1293 devSetupRegA = 0x60;
1294 break;
1295 case 24:
1296 gModeReg = 0xC0;
1297 devSetupRegA = 0x60;
1298 break;
1299 case 32:
1300 gModeReg = 0xE3;
1301 devSetupRegA = 0x60;
1302 break;
1305 if (!AccelMode) {
1306 gModeReg = 0x80;
1307 devSetupRegA = 0x61;
1310 temp = aty_ld_8(DAC_CNTL, info);
1311 aty_st_8(DAC_CNTL, (temp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3, info);
1313 aty_st_8(DAC_REGS + 2, 0x1D, info);
1314 aty_st_8(DAC_REGS + 3, gModeReg, info);
1315 aty_st_8(DAC_REGS, 0x02, info);
1317 temp = aty_ld_8(DAC_CNTL, info);
1318 aty_st_8(DAC_CNTL, temp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, info);
1320 if (info->total_vram < MEM_SIZE_1M)
1321 mask = 0x04;
1322 else if (info->total_vram == MEM_SIZE_1M)
1323 mask = 0x08;
1324 else
1325 mask = 0x0C;
1327 /* The following assumes that the BIOS has correctly set R7 of the
1328 * Device Setup Register A at boot time.
1330 #define A860_DELAY_L 0x80
1332 temp = aty_ld_8(DAC_REGS, info);
1333 aty_st_8(DAC_REGS, (devSetupRegA | mask) | (temp & A860_DELAY_L), info);
1334 temp = aty_ld_8(DAC_CNTL, info);
1335 aty_st_8(DAC_CNTL, (temp & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3)), info);
1337 return 0;
1340 static int aty_set_dac_ATT21C498(const struct fb_info_aty *info,
1341 const struct pll_18818 *pll, u32 bpp)
1343 u32 dotClock;
1344 int muxmode = 0;
1345 int DACMask = 0;
1347 dotClock = 100000000 / pll->period_in_ps;
1349 switch (bpp) {
1350 case 8:
1351 if (dotClock > 8000) {
1352 DACMask = 0x24;
1353 muxmode = 1;
1354 } else
1355 DACMask = 0x04;
1356 break;
1357 case 15:
1358 DACMask = 0x16;
1359 break;
1360 case 16:
1361 DACMask = 0x36;
1362 break;
1363 case 24:
1364 DACMask = 0xE6;
1365 break;
1366 case 32:
1367 DACMask = 0xE6;
1368 break;
1371 if (1 /* info->mach64DAC8Bit */)
1372 DACMask |= 0x02;
1374 aty_dac_waste4(info);
1375 aty_st_8(DAC_REGS + 2, DACMask, info);
1377 return muxmode;
1380 void aty_dac_waste4(const struct fb_info_aty *info)
1382 (void)aty_ld_8(DAC_REGS, info);
1384 (void)aty_ld_8(DAC_REGS + 2, info);
1385 (void)aty_ld_8(DAC_REGS + 2, info);
1386 (void)aty_ld_8(DAC_REGS + 2, info);
1387 (void)aty_ld_8(DAC_REGS + 2, info);
1391 static void aty_set_dac_514(const struct fb_info_aty *info, u32 bpp)
1393 static struct {
1394 u8 pixel_dly;
1395 u8 misc2_cntl;
1396 u8 pixel_rep;
1397 u8 pixel_cntl_index;
1398 u8 pixel_cntl_v1;
1399 } tab[3] = {
1400 { 0, 0x41, 0x03, 0x71, 0x45 }, /* 8 bpp */
1401 { 0, 0x45, 0x04, 0x0c, 0x01 }, /* 555 */
1402 { 0, 0x45, 0x06, 0x0e, 0x00 }, /* XRGB */
1404 int i;
1406 switch (bpp) {
1407 case 8:
1408 default:
1409 i = 0;
1410 break;
1411 case 16:
1412 i = 1;
1413 break;
1414 case 32:
1415 i = 2;
1416 break;
1418 aty_st_514(0x90, 0x00, info); /* VRAM Mask Low */
1419 aty_st_514(0x04, tab[i].pixel_dly, info); /* Horizontal Sync Control */
1420 aty_st_514(0x05, 0x00, info); /* Power Management */
1421 aty_st_514(0x02, 0x01, info); /* Misc Clock Control */
1422 aty_st_514(0x71, tab[i].misc2_cntl, info); /* Misc Control 2 */
1423 aty_st_514(0x0a, tab[i].pixel_rep, info); /* Pixel Format */
1424 aty_st_514(tab[i].pixel_cntl_index, tab[i].pixel_cntl_v1, info);
1425 /* Misc Control 2 / 16 BPP Control / 32 BPP Control */
1428 static int aty_crtc_to_var(const struct crtc *crtc,
1429 struct fb_var_screeninfo *var)
1431 u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync;
1432 u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
1433 u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
1434 u32 pix_width;
1436 /* input */
1437 h_total = crtc->h_tot_disp & 0x1ff;
1438 h_disp = (crtc->h_tot_disp>>16) & 0xff;
1439 h_sync_strt = (crtc->h_sync_strt_wid & 0xff) |
1440 ((crtc->h_sync_strt_wid>>4) & 0x100);
1441 h_sync_dly = (crtc->h_sync_strt_wid>>8) & 0x7;
1442 h_sync_wid = (crtc->h_sync_strt_wid>>16) & 0x1f;
1443 h_sync_pol = (crtc->h_sync_strt_wid>>21) & 0x1;
1444 v_total = crtc->v_tot_disp & 0x7ff;
1445 v_disp = (crtc->v_tot_disp>>16) & 0x7ff;
1446 v_sync_strt = crtc->v_sync_strt_wid & 0x7ff;
1447 v_sync_wid = (crtc->v_sync_strt_wid>>16) & 0x1f;
1448 v_sync_pol = (crtc->v_sync_strt_wid>>21) & 0x1;
1449 c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
1450 pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
1452 /* convert */
1453 xres = (h_disp+1)*8;
1454 yres = v_disp+1;
1455 left = (h_total-h_sync_strt-h_sync_wid)*8-h_sync_dly;
1456 right = (h_sync_strt-h_disp)*8+h_sync_dly;
1457 hslen = h_sync_wid*8;
1458 upper = v_total-v_sync_strt-v_sync_wid;
1459 lower = v_sync_strt-v_disp;
1460 vslen = v_sync_wid;
1461 sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) |
1462 (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
1463 (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
1465 switch (pix_width) {
1466 #if 0
1467 case CRTC_PIX_WIDTH_4BPP:
1468 bpp = 4;
1469 var->red.offset = 0;
1470 var->red.length = 8;
1471 var->green.offset = 0;
1472 var->green.length = 8;
1473 var->blue.offset = 0;
1474 var->blue.length = 8;
1475 var->transp.offset = 0;
1476 var->transp.length = 0;
1477 break;
1478 #endif
1479 case CRTC_PIX_WIDTH_8BPP:
1480 bpp = 8;
1481 var->red.offset = 0;
1482 var->red.length = 8;
1483 var->green.offset = 0;
1484 var->green.length = 8;
1485 var->blue.offset = 0;
1486 var->blue.length = 8;
1487 var->transp.offset = 0;
1488 var->transp.length = 0;
1489 break;
1490 case CRTC_PIX_WIDTH_15BPP: /* RGB 555 */
1491 bpp = 16;
1492 var->red.offset = 10;
1493 var->red.length = 5;
1494 var->green.offset = 5;
1495 var->green.length = 5;
1496 var->blue.offset = 0;
1497 var->blue.length = 5;
1498 var->transp.offset = 0;
1499 var->transp.length = 0;
1500 break;
1501 #if 0
1502 case CRTC_PIX_WIDTH_16BPP: /* RGB 565 */
1503 bpp = 16;
1504 var->red.offset = 11;
1505 var->red.length = 5;
1506 var->green.offset = 5;
1507 var->green.length = 6;
1508 var->blue.offset = 0;
1509 var->blue.length = 5;
1510 var->transp.offset = 0;
1511 var->transp.length = 0;
1512 break;
1513 #endif
1514 case CRTC_PIX_WIDTH_24BPP: /* RGB 888 */
1515 bpp = 24;
1516 var->red.offset = 16;
1517 var->red.length = 8;
1518 var->green.offset = 8;
1519 var->green.length = 8;
1520 var->blue.offset = 0;
1521 var->blue.length = 8;
1522 var->transp.offset = 0;
1523 var->transp.length = 0;
1524 break;
1525 case CRTC_PIX_WIDTH_32BPP: /* ARGB 8888 */
1526 bpp = 32;
1527 var->red.offset = 16;
1528 var->red.length = 8;
1529 var->green.offset = 8;
1530 var->green.length = 8;
1531 var->blue.offset = 0;
1532 var->blue.length = 8;
1533 var->transp.offset = 24;
1534 var->transp.length = 8;
1535 break;
1536 default:
1537 FAIL("Invalid pixel width");
1540 /* output */
1541 var->xres = xres;
1542 var->yres = yres;
1543 var->xres_virtual = crtc->vxres;
1544 var->yres_virtual = crtc->vyres;
1545 var->bits_per_pixel = bpp;
1546 var->xoffset = crtc->xoffset;
1547 var->yoffset = crtc->yoffset;
1548 var->left_margin = left;
1549 var->right_margin = right;
1550 var->upper_margin = upper;
1551 var->lower_margin = lower;
1552 var->hsync_len = hslen;
1553 var->vsync_len = vslen;
1554 var->sync = sync;
1555 var->vmode = FB_VMODE_NONINTERLACED;
1557 return 0;
1560 /* ------------------------------------------------------------------------- */
1563 * PLL programming (Mach64 GX family)
1565 * FIXME: use function pointer tables instead of switch statements
1568 static void aty_set_pll_gx(const struct fb_info_aty *info,
1569 const struct pll_gx *pll)
1571 switch (info->clk_type) {
1572 case CLK_ATI18818_1:
1573 aty_st_8(CLOCK_CNTL, pll->m, info);
1574 break;
1575 case CLK_IBMRGB514:
1576 aty_st_514(0x06, 0x02, info); /* DAC Operation */
1577 aty_st_514(0x10, 0x01, info); /* PLL Control 1 */
1578 aty_st_514(0x70, 0x01, info); /* Misc Control 1 */
1579 aty_st_514(0x8f, 0x1f, info); /* PLL Ref. Divider Input */
1580 aty_st_514(0x03, 0x00, info); /* Sync Control */
1581 aty_st_514(0x05, 0x00, info); /* Power Management */
1582 aty_st_514(0x20, pll->m, info); /* F0 / M0 */
1583 aty_st_514(0x21, pll->n, info); /* F1 / N0 */
1584 break;
1589 static int aty_var_to_pll_18818(u32 period_in_ps, struct pll_18818 *pll)
1591 u32 MHz100; /* in 0.01 MHz */
1592 u32 program_bits;
1593 u32 post_divider;
1595 /* Calculate the programming word */
1596 MHz100 = 100000000 / period_in_ps;
1598 program_bits = -1;
1599 post_divider = 1;
1601 if (MHz100 > MAX_FREQ_2595) {
1602 MHz100 = MAX_FREQ_2595;
1603 return -EINVAL;
1604 } else if (MHz100 < ABS_MIN_FREQ_2595) {
1605 program_bits = 0; /* MHz100 = 257 */
1606 return -EINVAL;
1607 } else {
1608 while (MHz100 < MIN_FREQ_2595) {
1609 MHz100 *= 2;
1610 post_divider *= 2;
1613 MHz100 *= 1000;
1614 MHz100 = (REF_DIV_2595 * MHz100) / REF_FREQ_2595;
1616 MHz100 += 500; /* + 0.5 round */
1617 MHz100 /= 1000;
1619 if (program_bits == -1) {
1620 program_bits = MHz100 - N_ADJ_2595;
1621 switch (post_divider) {
1622 case 1:
1623 program_bits |= 0x0600;
1624 break;
1625 case 2:
1626 program_bits |= 0x0400;
1627 break;
1628 case 4:
1629 program_bits |= 0x0200;
1630 break;
1631 case 8:
1632 default:
1633 break;
1637 program_bits |= STOP_BITS_2595;
1639 pll->program_bits = program_bits;
1640 pll->locationAddr = 0;
1641 pll->post_divider = post_divider;
1642 pll->period_in_ps = period_in_ps;
1644 return 0;
1647 static u32 aty_pll_18818_to_var(const struct pll_18818 *pll)
1649 return(pll->period_in_ps); /* default for now */
1652 static void aty_set_pll18818(const struct fb_info_aty *info,
1653 const struct pll_18818 *pll)
1655 u32 program_bits;
1656 u32 locationAddr;
1658 u32 i;
1660 u8 old_clock_cntl;
1661 u8 old_crtc_ext_disp;
1663 old_clock_cntl = aty_ld_8(CLOCK_CNTL, info);
1664 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info);
1666 old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
1667 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24),
1668 info);
1670 udelay(15000); /* delay for 50 (15) ms */
1672 program_bits = pll->program_bits;
1673 locationAddr = pll->locationAddr;
1675 /* Program the clock chip */
1676 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info); /* Strobe = 0 */
1677 aty_StrobeClock(info);
1678 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 1, info); /* Strobe = 0 */
1679 aty_StrobeClock(info);
1681 aty_ICS2595_put1bit(1, info); /* Send start bits */
1682 aty_ICS2595_put1bit(0, info); /* Start bit */
1683 aty_ICS2595_put1bit(0, info); /* Read / ~Write */
1685 for (i = 0; i < 5; i++) { /* Location 0..4 */
1686 aty_ICS2595_put1bit(locationAddr & 1, info);
1687 locationAddr >>= 1;
1690 for (i = 0; i < 8 + 1 + 2 + 2; i++) {
1691 aty_ICS2595_put1bit(program_bits & 1, info);
1692 program_bits >>= 1;
1695 udelay(1000); /* delay for 1 ms */
1697 (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */
1698 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info);
1699 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, old_clock_cntl | CLOCK_STROBE,
1700 info);
1702 udelay(50000); /* delay for 50 (15) ms */
1703 aty_st_8(CLOCK_CNTL + info->clk_wr_offset,
1704 ((pll->locationAddr & 0x0F) | CLOCK_STROBE), info);
1706 return;
1710 static int aty_var_to_pll_408(u32 period_in_ps, struct pll_18818 *pll)
1712 u32 mhz100; /* in 0.01 MHz */
1713 u32 program_bits;
1714 /* u32 post_divider; */
1715 u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
1716 u32 temp, tempB;
1717 u16 remainder, preRemainder;
1718 short divider = 0, tempA;
1720 /* Calculate the programming word */
1721 mhz100 = 100000000 / period_in_ps;
1722 mach64MinFreq = MIN_FREQ_2595;
1723 mach64MaxFreq = MAX_FREQ_2595;
1724 mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */
1726 /* Calculate program word */
1727 if (mhz100 == 0)
1728 program_bits = 0xFF;
1729 else {
1730 if (mhz100 < mach64MinFreq)
1731 mhz100 = mach64MinFreq;
1732 if (mhz100 > mach64MaxFreq)
1733 mhz100 = mach64MaxFreq;
1735 while (mhz100 < (mach64MinFreq << 3)) {
1736 mhz100 <<= 1;
1737 divider += 0x40;
1740 temp = (unsigned int)mhz100;
1741 temp = (unsigned int)(temp * (MIN_N_408 + 2));
1742 temp -= ((short)(mach64RefFreq << 1));
1744 tempA = MIN_N_408;
1745 preRemainder = 0xFFFF;
1747 do {
1748 tempB = temp;
1749 remainder = tempB % mach64RefFreq;
1750 tempB = tempB / mach64RefFreq;
1751 if (((tempB & 0xFFFF) <= 255) && (remainder <= preRemainder)) {
1752 preRemainder = remainder;
1753 divider &= ~0x3f;
1754 divider |= tempA;
1755 divider = (divider & 0x00FF) + ((tempB & 0xFF) << 8);
1757 temp += mhz100;
1758 tempA++;
1759 } while(tempA <= 32);
1761 program_bits = divider;
1764 pll->program_bits = program_bits;
1765 pll->locationAddr = 0;
1766 pll->post_divider = divider; /* fuer nix */
1767 pll->period_in_ps = period_in_ps;
1769 return 0;
1772 static u32 aty_pll_408_to_var(const struct pll_18818 *pll)
1774 return(pll->period_in_ps); /* default for now */
1777 static void aty_set_pll_408(const struct fb_info_aty *info,
1778 const struct pll_18818 *pll)
1780 u32 program_bits;
1781 u32 locationAddr;
1783 u8 tmpA, tmpB, tmpC;
1784 char old_crtc_ext_disp;
1786 old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
1787 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24),
1788 info);
1790 program_bits = pll->program_bits;
1791 locationAddr = pll->locationAddr;
1793 /* Program clock */
1794 aty_dac_waste4(info);
1795 tmpB = aty_ld_8(DAC_REGS + 2, info) | 1;
1796 aty_dac_waste4(info);
1797 aty_st_8(DAC_REGS + 2, tmpB, info);
1799 tmpA = tmpB;
1800 tmpC = tmpA;
1801 tmpA |= 8;
1802 tmpB = 1;
1804 aty_st_8(DAC_REGS, tmpB, info);
1805 aty_st_8(DAC_REGS + 2, tmpA, info);
1807 udelay(400); /* delay for 400 us */
1809 locationAddr = (locationAddr << 2) + 0x40;
1810 tmpB = locationAddr;
1811 tmpA = program_bits >> 8;
1813 aty_st_8(DAC_REGS, tmpB, info);
1814 aty_st_8(DAC_REGS + 2, tmpA, info);
1816 tmpB = locationAddr + 1;
1817 tmpA = (u8)program_bits;
1819 aty_st_8(DAC_REGS, tmpB, info);
1820 aty_st_8(DAC_REGS + 2, tmpA, info);
1822 tmpB = locationAddr + 2;
1823 tmpA = 0x77;
1825 aty_st_8(DAC_REGS, tmpB, info);
1826 aty_st_8(DAC_REGS + 2, tmpA, info);
1828 udelay(400); /* delay for 400 us */
1829 tmpA = tmpC & (~(1 | 8));
1830 tmpB = 1;
1832 aty_st_8(DAC_REGS, tmpB, info);
1833 aty_st_8(DAC_REGS + 2, tmpA, info);
1835 (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */
1836 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info);
1838 return;
1842 static int aty_var_to_pll_1703(u32 period_in_ps, struct pll_18818 *pll)
1844 u32 mhz100; /* in 0.01 MHz */
1845 u32 program_bits;
1846 /* u32 post_divider; */
1847 u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
1848 u32 temp, tempB;
1849 u16 remainder, preRemainder;
1850 short divider = 0, tempA;
1852 /* Calculate the programming word */
1853 mhz100 = 100000000 / period_in_ps;
1854 mach64MinFreq = MIN_FREQ_2595;
1855 mach64MaxFreq = MAX_FREQ_2595;
1856 mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */
1858 /* Calculate program word */
1859 if (mhz100 == 0)
1860 program_bits = 0xE0;
1861 else {
1862 if (mhz100 < mach64MinFreq)
1863 mhz100 = mach64MinFreq;
1864 if (mhz100 > mach64MaxFreq)
1865 mhz100 = mach64MaxFreq;
1867 divider = 0;
1868 while (mhz100 < (mach64MinFreq << 3)) {
1869 mhz100 <<= 1;
1870 divider += 0x20;
1873 temp = (unsigned int)(mhz100);
1874 temp = (unsigned int)(temp * (MIN_N_1703 + 2));
1875 temp -= (short)(mach64RefFreq << 1);
1877 tempA = MIN_N_1703;
1878 preRemainder = 0xffff;
1880 do {
1881 tempB = temp;
1882 remainder = tempB % mach64RefFreq;
1883 tempB = tempB / mach64RefFreq;
1885 if ((tempB & 0xffff) <= 127 && (remainder <= preRemainder)) {
1886 preRemainder = remainder;
1887 divider &= ~0x1f;
1888 divider |= tempA;
1889 divider = (divider & 0x00ff) + ((tempB & 0xff) << 8);
1892 temp += mhz100;
1893 tempA++;
1894 } while (tempA <= (MIN_N_1703 << 1));
1896 program_bits = divider;
1899 pll->program_bits = program_bits;
1900 pll->locationAddr = 0;
1901 pll->post_divider = divider; /* fuer nix */
1902 pll->period_in_ps = period_in_ps;
1904 return 0;
1907 static u32 aty_pll_1703_to_var(const struct pll_18818 *pll)
1909 return(pll->period_in_ps); /* default for now */
1912 static void aty_set_pll_1703(const struct fb_info_aty *info,
1913 const struct pll_18818 *pll)
1915 u32 program_bits;
1916 u32 locationAddr;
1918 char old_crtc_ext_disp;
1920 old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
1921 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24),
1922 info);
1924 program_bits = pll->program_bits;
1925 locationAddr = pll->locationAddr;
1927 /* Program clock */
1928 aty_dac_waste4(info);
1930 (void)aty_ld_8(DAC_REGS + 2, info);
1931 aty_st_8(DAC_REGS+2, (locationAddr << 1) + 0x20, info);
1932 aty_st_8(DAC_REGS+2, 0, info);
1933 aty_st_8(DAC_REGS+2, (program_bits & 0xFF00) >> 8, info);
1934 aty_st_8(DAC_REGS+2, (program_bits & 0xFF), info);
1936 (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */
1937 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info);
1939 return;
1943 static int aty_var_to_pll_8398(u32 period_in_ps, struct pll_18818 *pll)
1946 u32 tempA, tempB, fOut, longMHz100, diff, preDiff;
1948 u32 mhz100; /* in 0.01 MHz */
1949 u32 program_bits;
1950 /* u32 post_divider; */
1951 u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
1952 u16 m, n, k=0, save_m, save_n, twoToKth;
1954 /* Calculate the programming word */
1955 mhz100 = 100000000 / period_in_ps;
1956 mach64MinFreq = MIN_FREQ_2595;
1957 mach64MaxFreq = MAX_FREQ_2595;
1958 mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */
1960 save_m = 0;
1961 save_n = 0;
1963 /* Calculate program word */
1964 if (mhz100 == 0)
1965 program_bits = 0xE0;
1966 else
1968 if (mhz100 < mach64MinFreq)
1969 mhz100 = mach64MinFreq;
1970 if (mhz100 > mach64MaxFreq)
1971 mhz100 = mach64MaxFreq;
1973 longMHz100 = mhz100 * 256 / 100; /* 8 bit scale this */
1975 while (mhz100 < (mach64MinFreq << 3))
1977 mhz100 <<= 1;
1978 k++;
1981 twoToKth = 1 << k;
1982 diff = 0;
1983 preDiff = 0xFFFFFFFF;
1985 for (m = MIN_M; m <= MAX_M; m++)
1987 for (n = MIN_N; n <= MAX_N; n++)
1989 tempA = (14.31818 * 65536);
1990 tempA *= (n + 8); /* 43..256 */
1991 tempB = twoToKth * 256;
1992 tempB *= (m + 2); /* 4..32 */
1993 fOut = tempA / tempB; /* 8 bit scale */
1995 if (longMHz100 > fOut)
1996 diff = longMHz100 - fOut;
1997 else
1998 diff = fOut - longMHz100;
2000 if (diff < preDiff)
2002 save_m = m;
2003 save_n = n;
2004 preDiff = diff;
2009 program_bits = (k << 6) + (save_m) + (save_n << 8);
2012 pll->program_bits = program_bits;
2013 pll->locationAddr = 0;
2014 pll->post_divider = 0;
2015 pll->period_in_ps = period_in_ps;
2017 return 0;
2020 static u32 aty_pll_8398_to_var(const struct pll_18818 *pll)
2022 return(pll->period_in_ps); /* default for now */
2025 static void aty_set_pll_8398(const struct fb_info_aty *info,
2026 const struct pll_18818 *pll)
2028 u32 program_bits;
2029 u32 locationAddr;
2031 char old_crtc_ext_disp;
2032 char tmp;
2034 old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
2035 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24),
2036 info);
2038 program_bits = pll->program_bits;
2039 locationAddr = pll->locationAddr;
2041 /* Program clock */
2042 tmp = aty_ld_8(DAC_CNTL, info);
2043 aty_st_8(DAC_CNTL, tmp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, info);
2045 aty_st_8(DAC_REGS, locationAddr, info);
2046 aty_st_8(DAC_REGS+1, (program_bits & 0xff00) >> 8, info);
2047 aty_st_8(DAC_REGS+1, (program_bits & 0xff), info);
2049 tmp = aty_ld_8(DAC_CNTL, info);
2050 aty_st_8(DAC_CNTL, (tmp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3, info);
2052 (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */
2053 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info);
2055 return;
2059 static int aty_var_to_pll_514(u32 vclk_per, struct pll_gx *pll)
2062 * FIXME: use real calculations instead of using fixed values from the old
2063 * driver
2065 static struct {
2066 u32 limit; /* pixlock rounding limit (arbitrary) */
2067 u8 m; /* (df<<6) | vco_div_count */
2068 u8 n; /* ref_div_count */
2069 } RGB514_clocks[7] = {
2070 { 8000, (3<<6) | 20, 9 }, /* 7395 ps / 135.2273 MHz */
2071 { 10000, (1<<6) | 19, 3 }, /* 9977 ps / 100.2273 MHz */
2072 { 13000, (1<<6) | 2, 3 }, /* 12509 ps / 79.9432 MHz */
2073 { 14000, (2<<6) | 8, 7 }, /* 13394 ps / 74.6591 MHz */
2074 { 16000, (1<<6) | 44, 6 }, /* 15378 ps / 65.0284 MHz */
2075 { 25000, (1<<6) | 15, 5 }, /* 17460 ps / 57.2727 MHz */
2076 { 50000, (0<<6) | 53, 7 }, /* 33145 ps / 30.1705 MHz */
2078 int i;
2080 for (i = 0; i < sizeof(RGB514_clocks)/sizeof(*RGB514_clocks); i++)
2081 if (vclk_per <= RGB514_clocks[i].limit) {
2082 pll->m = RGB514_clocks[i].m;
2083 pll->n = RGB514_clocks[i].n;
2084 return 0;
2086 return -EINVAL;
2090 static void aty_StrobeClock(const struct fb_info_aty *info)
2092 u8 tmp;
2094 udelay(26);
2096 tmp = aty_ld_8(CLOCK_CNTL, info);
2097 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, tmp | CLOCK_STROBE, info);
2099 return;
2103 static void aty_ICS2595_put1bit(u8 data, const struct fb_info_aty *info)
2105 u8 tmp;
2107 data &= 0x01;
2108 tmp = aty_ld_8(CLOCK_CNTL, info);
2109 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, (tmp & ~0x04) | (data << 2),
2110 info);
2112 tmp = aty_ld_8(CLOCK_CNTL, info);
2113 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, (tmp & ~0x08) | (0 << 3), info);
2115 aty_StrobeClock(info);
2117 tmp = aty_ld_8(CLOCK_CNTL, info);
2118 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, (tmp & ~0x08) | (1 << 3), info);
2120 aty_StrobeClock(info);
2122 return;
2126 static u32 aty_pll_gx_to_var(const struct pll_gx *pll,
2127 const struct fb_info_aty *info)
2129 u8 df, vco_div_count, ref_div_count;
2131 df = pll->m >> 6;
2132 vco_div_count = pll->m & 0x3f;
2133 ref_div_count = pll->n;
2135 return ((info->ref_clk_per*ref_div_count)<<(3-df))/(vco_div_count+65);
2140 * PLL programming (Mach64 CT family)
2143 static void aty_set_pll_ct(const struct fb_info_aty *info,
2144 const struct pll_ct *pll)
2146 aty_st_pll(PLL_REF_DIV, pll->pll_ref_div, info);
2147 aty_st_pll(PLL_GEN_CNTL, pll->pll_gen_cntl, info);
2148 aty_st_pll(MCLK_FB_DIV, pll->mclk_fb_div, info);
2149 aty_st_pll(PLL_VCLK_CNTL, pll->pll_vclk_cntl, info);
2150 aty_st_pll(VCLK_POST_DIV, pll->vclk_post_div, info);
2151 aty_st_pll(VCLK0_FB_DIV, pll->vclk_fb_div, info);
2152 aty_st_pll(PLL_EXT_CNTL, pll->pll_ext_cntl, info);
2154 if (!(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
2155 Gx == ET_CHIP_ID ||
2156 ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07)))) {
2157 if (info->ram_type >= SDRAM)
2158 aty_st_pll(DLL_CNTL, 0xa6, info);
2159 else
2160 aty_st_pll(DLL_CNTL, 0xa0, info);
2161 aty_st_pll(VFC_CNTL, 0x1b, info);
2162 aty_st_le32(DSP_CONFIG, pll->dsp_config, info);
2163 aty_st_le32(DSP_ON_OFF, pll->dsp_on_off, info);
2167 static int aty_dsp_gt(const struct fb_info_aty *info, u8 bpp,
2168 struct pll_ct *pll)
2170 u32 dsp_xclks_per_row, dsp_loop_latency, dsp_precision, dsp_off, dsp_on;
2171 u32 xclks_per_row, fifo_off, fifo_on, y, fifo_size, page_size;
2173 /* xclocks_per_row<<11 */
2174 xclks_per_row = (pll->mclk_fb_div*pll->vclk_post_div_real*64<<11)/
2175 (pll->vclk_fb_div*pll->mclk_post_div_real*bpp);
2176 if (xclks_per_row < (1<<11))
2177 FAIL("Dotclock to high");
2178 if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == VT_CHIP_ID ||
2179 Gx == VU_CHIP_ID || Gx == GV_CHIP_ID || Gx == GW_CHIP_ID ||
2180 Gx == GZ_CHIP_ID) {
2181 fifo_size = 24;
2182 dsp_loop_latency = 0;
2183 } else {
2184 fifo_size = 32;
2185 dsp_loop_latency = 2;
2187 dsp_precision = 0;
2188 y = (xclks_per_row*fifo_size)>>11;
2189 while (y) {
2190 y >>= 1;
2191 dsp_precision++;
2193 dsp_precision -= 5;
2194 /* fifo_off<<6 */
2195 fifo_off = ((xclks_per_row*(fifo_size-1))>>5)+(1<<6);
2197 if (info->total_vram > 1*1024*1024) {
2198 if (info->ram_type >= SDRAM) {
2199 /* >1 MB SDRAM */
2200 dsp_loop_latency += 8;
2201 page_size = 8;
2202 } else {
2203 /* >1 MB DRAM */
2204 dsp_loop_latency += 6;
2205 page_size = 9;
2207 } else {
2208 if (info->ram_type >= SDRAM) {
2209 /* <2 MB SDRAM */
2210 dsp_loop_latency += 9;
2211 page_size = 10;
2212 } else {
2213 /* <2 MB DRAM */
2214 dsp_loop_latency += 8;
2215 page_size = 10;
2218 /* fifo_on<<6 */
2219 if (xclks_per_row >= (page_size<<11))
2220 fifo_on = ((2*page_size+1)<<6)+(xclks_per_row>>5);
2221 else
2222 fifo_on = (3*page_size)<<6;
2224 dsp_xclks_per_row = xclks_per_row>>dsp_precision;
2225 dsp_on = fifo_on>>dsp_precision;
2226 dsp_off = fifo_off>>dsp_precision;
2228 pll->dsp_config = (dsp_xclks_per_row & 0x3fff) |
2229 ((dsp_loop_latency & 0xf)<<16) |
2230 ((dsp_precision & 7)<<20);
2231 pll->dsp_on_off = (dsp_on & 0x7ff) | ((dsp_off & 0x7ff)<<16);
2232 return 0;
2235 static int aty_valid_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
2236 struct pll_ct *pll)
2238 u32 q, x; /* x is a workaround for sparc64-linux-gcc */
2239 x = x; /* x is a workaround for sparc64-linux-gcc */
2241 pll->pll_ref_div = info->pll_per*2*255/info->ref_clk_per;
2243 /* FIXME: use the VTB/GTB /3 post divider if it's better suited */
2244 q = info->ref_clk_per*pll->pll_ref_div*4/info->mclk_per; /* actually 8*q */
2245 if (q < 16*8 || q > 255*8)
2246 FAIL("mclk out of range");
2247 else if (q < 32*8)
2248 pll->mclk_post_div_real = 8;
2249 else if (q < 64*8)
2250 pll->mclk_post_div_real = 4;
2251 else if (q < 128*8)
2252 pll->mclk_post_div_real = 2;
2253 else
2254 pll->mclk_post_div_real = 1;
2255 pll->mclk_fb_div = q*pll->mclk_post_div_real/8;
2257 /* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
2258 q = info->ref_clk_per*pll->pll_ref_div*4/vclk_per; /* actually 8*q */
2259 if (q < 16*8 || q > 255*8)
2260 FAIL("vclk out of range");
2261 else if (q < 32*8)
2262 pll->vclk_post_div_real = 8;
2263 else if (q < 64*8)
2264 pll->vclk_post_div_real = 4;
2265 else if (q < 128*8)
2266 pll->vclk_post_div_real = 2;
2267 else
2268 pll->vclk_post_div_real = 1;
2269 pll->vclk_fb_div = q*pll->vclk_post_div_real/8;
2270 return 0;
2273 static void aty_calc_pll_ct(const struct fb_info_aty *info, struct pll_ct *pll)
2275 u8 mpostdiv = 0;
2276 u8 vpostdiv = 0;
2278 if ((((Gx == GT_CHIP_ID) && (Rev & 0x03)) || (Gx == GU_CHIP_ID) ||
2279 (Gx == GV_CHIP_ID) || (Gx == GW_CHIP_ID) || (Gx == GZ_CHIP_ID) ||
2280 (Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) ||
2281 (Gx == GI_CHIP_ID) || (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID) ||
2282 (Gx == VU_CHIP_ID)) && (info->ram_type >= SDRAM))
2283 pll->pll_gen_cntl = 0x04;
2284 else
2285 pll->pll_gen_cntl = 0x84;
2287 switch (pll->mclk_post_div_real) {
2288 case 1:
2289 mpostdiv = 0;
2290 break;
2291 case 2:
2292 mpostdiv = 1;
2293 break;
2294 case 3:
2295 mpostdiv = 4;
2296 break;
2297 case 4:
2298 mpostdiv = 2;
2299 break;
2300 case 8:
2301 mpostdiv = 3;
2302 break;
2304 pll->pll_gen_cntl |= mpostdiv<<4; /* mclk */
2306 if (Gx == VT_CHIP_ID && (Rev == 0x40 || Rev == 0x48))
2307 pll->pll_ext_cntl = 0;
2308 else
2309 pll->pll_ext_cntl = mpostdiv; /* xclk == mclk */
2311 switch (pll->vclk_post_div_real) {
2312 case 2:
2313 vpostdiv = 1;
2314 break;
2315 case 3:
2316 pll->pll_ext_cntl |= 0x10;
2317 case 1:
2318 vpostdiv = 0;
2319 break;
2320 case 6:
2321 pll->pll_ext_cntl |= 0x10;
2322 case 4:
2323 vpostdiv = 2;
2324 break;
2325 case 12:
2326 pll->pll_ext_cntl |= 0x10;
2327 case 8:
2328 vpostdiv = 3;
2329 break;
2332 pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */
2333 pll->vclk_post_div = vpostdiv;
2336 static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
2337 u8 bpp, struct pll_ct *pll)
2339 int err;
2341 if ((err = aty_valid_pll_ct(info, vclk_per, pll)))
2342 return err;
2343 if (!(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
2344 Gx == ET_CHIP_ID ||
2345 ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07)))) {
2346 if ((err = aty_dsp_gt(info, bpp, pll)))
2347 return err;
2349 aty_calc_pll_ct(info, pll);
2350 return 0;
2353 static u32 aty_pll_ct_to_var(const struct pll_ct *pll,
2354 const struct fb_info_aty *info)
2356 u32 ref_clk_per = info->ref_clk_per;
2357 u8 pll_ref_div = pll->pll_ref_div;
2358 u8 vclk_fb_div = pll->vclk_fb_div;
2359 u8 vclk_post_div = pll->vclk_post_div_real;
2361 return ref_clk_per*pll_ref_div*vclk_post_div/vclk_fb_div/2;
2364 /* ------------------------------------------------------------------------- */
2366 static void atyfb_set_par(const struct atyfb_par *par,
2367 struct fb_info_aty *info)
2369 u32 i;
2370 int accelmode;
2371 int muxmode;
2372 u8 tmp;
2374 accelmode = par->accel_flags; /* hack */
2376 info->current_par = *par;
2378 if (info->blitter_may_be_busy)
2379 wait_for_idle(info);
2380 tmp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
2381 aty_set_crtc(info, &par->crtc);
2382 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info);
2383 /* better call aty_StrobeClock ?? */
2384 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, CLOCK_STROBE, info);
2386 if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID)) {
2387 switch (info->dac_subtype) {
2388 case DAC_IBMRGB514:
2389 aty_set_dac_514(info, par->crtc.bpp);
2390 break;
2391 case DAC_ATI68860_B:
2392 case DAC_ATI68860_C:
2393 muxmode = aty_set_dac_ATI68860_B(info, par->crtc.bpp,
2394 accelmode);
2395 aty_st_le32(BUS_CNTL, 0x890e20f1, info);
2396 aty_st_le32(DAC_CNTL, 0x47052100, info);
2397 break;
2398 case DAC_ATT20C408:
2399 muxmode = aty_set_dac_ATT21C498(info, &par->pll.ics2595,
2400 par->crtc.bpp);
2401 aty_st_le32(BUS_CNTL, 0x890e20f1, info);
2402 aty_st_le32(DAC_CNTL, 0x00072000, info);
2403 break;
2404 case DAC_ATT21C498:
2405 muxmode = aty_set_dac_ATT21C498(info, &par->pll.ics2595,
2406 par->crtc.bpp);
2407 aty_st_le32(BUS_CNTL, 0x890e20f1, info);
2408 aty_st_le32(DAC_CNTL, 0x00072000, info);
2409 break;
2410 default:
2411 printk(" atyfb_set_par: DAC type not implemented yet!\n");
2412 aty_st_le32(BUS_CNTL, 0x890e20f1, info);
2413 aty_st_le32(DAC_CNTL, 0x47052100, info);
2414 /* new in 2.2.3p1 from Geert. ???????? */
2415 aty_st_le32(BUS_CNTL, 0x590e10ff, info);
2416 aty_st_le32(DAC_CNTL, 0x47012100, info);
2417 break;
2420 switch (info->clk_type) {
2421 case CLK_ATI18818_1:
2422 aty_set_pll18818(info, &par->pll.ics2595);
2423 break;
2424 case CLK_STG1703:
2425 aty_set_pll_1703(info, &par->pll.ics2595);
2426 break;
2427 case CLK_CH8398:
2428 aty_set_pll_8398(info, &par->pll.ics2595);
2429 break;
2430 case CLK_ATT20C408:
2431 aty_set_pll_408(info, &par->pll.ics2595);
2432 break;
2433 case CLK_IBMRGB514:
2434 aty_set_pll_gx(info, &par->pll.gx);
2435 break;
2436 default:
2437 printk(" atyfb_set_par: CLK type not implemented yet!");
2438 break;
2441 /* Don't forget MEM_CNTL */
2442 i = aty_ld_le32(MEM_CNTL, info) & 0xf0ffffff;
2443 switch (par->crtc.bpp) {
2444 case 8:
2445 i |= 0x02000000;
2446 break;
2447 case 16:
2448 i |= 0x03000000;
2449 break;
2450 case 32:
2451 i |= 0x06000000;
2452 break;
2454 aty_st_le32(MEM_CNTL, i, info);
2456 } else {
2457 aty_set_pll_ct(info, &par->pll.ct);
2458 i = aty_ld_le32(MEM_CNTL, info) & 0xf00fffff;
2459 if (!(Gx == VT_CHIP_ID && (Rev == 0x40 || Rev == 0x48)))
2460 i |= info->mem_refresh_rate << 20;
2461 switch (par->crtc.bpp) {
2462 case 8:
2463 case 24:
2464 i |= 0x00000000;
2465 break;
2466 case 16:
2467 i |= 0x04000000;
2468 break;
2469 case 32:
2470 i |= 0x08000000;
2471 break;
2473 if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID)) {
2474 aty_st_le32(DAC_CNTL, 0x87010184, info);
2475 aty_st_le32(BUS_CNTL, 0x680000f9, info);
2476 } else if ((Gx == VT_CHIP_ID) || (Gx == VU_CHIP_ID)) {
2477 aty_st_le32(DAC_CNTL, 0x87010184, info);
2478 aty_st_le32(BUS_CNTL, 0x680000f9, info);
2479 } else {
2480 /* GT */
2481 aty_st_le32(DAC_CNTL, 0x86010102, info);
2482 aty_st_le32(BUS_CNTL, 0x7b23a040, info);
2483 aty_st_le32(EXT_MEM_CNTL,
2484 aty_ld_le32(EXT_MEM_CNTL, info) | 0x5000001, info);
2486 aty_st_le32(MEM_CNTL, i, info);
2488 aty_st_8(DAC_MASK, 0xff, info);
2490 /* Initialize the graphics engine */
2491 if (par->accel_flags & FB_ACCELF_TEXT)
2492 init_engine(par, info);
2494 #ifdef CONFIG_FB_COMPAT_XPMAC
2495 if (console_fb_info == &info->fb_info) {
2496 struct fb_var_screeninfo var;
2497 int vmode, cmode;
2498 display_info.height = ((par->crtc.v_tot_disp>>16) & 0x7ff)+1;
2499 display_info.width = (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8;
2500 display_info.depth = par->crtc.bpp;
2501 display_info.pitch = par->crtc.vxres*par->crtc.bpp/8;
2502 atyfb_encode_var(&var, par, info);
2503 if (mac_var_to_vmode(&var, &vmode, &cmode))
2504 display_info.mode = 0;
2505 else
2506 display_info.mode = vmode;
2507 strcpy(display_info.name, atyfb_name);
2508 display_info.fb_address = info->frame_buffer_phys;
2509 display_info.cmap_adr_address = info->ati_regbase_phys+0xc0;
2510 display_info.cmap_data_address = info->ati_regbase_phys+0xc1;
2511 display_info.disp_reg_address = info->ati_regbase_phys;
2513 #endif /* CONFIG_FB_COMPAT_XPMAC */
2516 static int atyfb_decode_var(const struct fb_var_screeninfo *var,
2517 struct atyfb_par *par,
2518 const struct fb_info_aty *info)
2520 int err;
2522 if ((err = aty_var_to_crtc(info, var, &par->crtc)))
2523 return err;
2524 if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID))
2525 switch (info->clk_type) {
2526 case CLK_ATI18818_1:
2527 err = aty_var_to_pll_18818(var->pixclock, &par->pll.ics2595);
2528 break;
2529 case CLK_STG1703:
2530 err = aty_var_to_pll_1703(var->pixclock, &par->pll.ics2595);
2531 break;
2532 case CLK_CH8398:
2533 err = aty_var_to_pll_8398(var->pixclock, &par->pll.ics2595);
2534 break;
2535 case CLK_ATT20C408:
2536 err = aty_var_to_pll_408(var->pixclock, &par->pll.ics2595);
2537 break;
2538 case CLK_IBMRGB514:
2539 err = aty_var_to_pll_514(var->pixclock, &par->pll.gx);
2540 break;
2542 else
2543 err = aty_var_to_pll_ct(info, var->pixclock, par->crtc.bpp,
2544 &par->pll.ct);
2545 if (err)
2546 return err;
2548 if (var->accel_flags & FB_ACCELF_TEXT)
2549 par->accel_flags = FB_ACCELF_TEXT;
2550 else
2551 par->accel_flags = 0;
2553 #if 0
2554 if (!fbmon_valid_timings(var->pixclock, htotal, vtotal, info))
2555 return -EINVAL;
2556 #endif
2558 return 0;
2561 static int atyfb_encode_var(struct fb_var_screeninfo *var,
2562 const struct atyfb_par *par,
2563 const struct fb_info_aty *info)
2565 int err;
2567 memset(var, 0, sizeof(struct fb_var_screeninfo));
2569 if ((err = aty_crtc_to_var(&par->crtc, var)))
2570 return err;
2571 if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID))
2572 switch (info->clk_type) {
2573 case CLK_ATI18818_1:
2574 var->pixclock = aty_pll_18818_to_var(&par->pll.ics2595);
2575 break;
2576 case CLK_STG1703:
2577 var->pixclock = aty_pll_1703_to_var(&par->pll.ics2595);
2578 break;
2579 case CLK_CH8398:
2580 var->pixclock = aty_pll_8398_to_var(&par->pll.ics2595);
2581 break;
2582 case CLK_ATT20C408:
2583 var->pixclock = aty_pll_408_to_var(&par->pll.ics2595);
2584 break;
2585 case CLK_IBMRGB514:
2586 var->pixclock = aty_pll_gx_to_var(&par->pll.gx, info);
2587 break;
2589 else
2590 var->pixclock = aty_pll_ct_to_var(&par->pll.ct, info);
2592 var->height = -1;
2593 var->width = -1;
2594 var->accel_flags = par->accel_flags;
2596 return 0;
2601 static void set_off_pitch(struct atyfb_par *par,
2602 const struct fb_info_aty *info)
2604 u32 xoffset = par->crtc.xoffset;
2605 u32 yoffset = par->crtc.yoffset;
2606 u32 vxres = par->crtc.vxres;
2607 u32 bpp = par->crtc.bpp;
2609 par->crtc.off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19);
2610 aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, info);
2615 * Open/Release the frame buffer device
2618 static int atyfb_open(struct fb_info *info, int user)
2621 #ifdef __sparc__
2622 struct fb_info_aty *fb = (struct fb_info_aty *)info;
2624 if (user) {
2625 if (fb->open)
2626 return -EBUSY;
2627 fb->mmaped = 0;
2628 fb->open = 1;
2629 fb->vtconsole = -1;
2630 } else {
2631 fb->consolecnt++;
2633 #endif
2634 MOD_INC_USE_COUNT;
2635 return(0);
2638 static int atyfb_release(struct fb_info *info, int user)
2640 #ifdef __sparc__
2641 struct fb_info_aty *fb = (struct fb_info_aty *)info;
2643 if (user) {
2644 if (fb->vtconsole != -1)
2645 vt_cons[fb->vtconsole]->vc_mode = KD_TEXT;
2646 fb->open = 0;
2647 fb->mmaped = 0;
2648 fb->vtconsole = -1;
2649 } else {
2650 fb->consolecnt--;
2652 #endif
2653 MOD_DEC_USE_COUNT;
2654 return(0);
2658 static int encode_fix(struct fb_fix_screeninfo *fix,
2659 const struct atyfb_par *par,
2660 const struct fb_info_aty *info)
2662 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
2664 strcpy(fix->id, atyfb_name);
2665 fix->smem_start = info->frame_buffer_phys;
2666 fix->smem_len = (u32)info->total_vram;
2668 #ifdef __LITTLE_ENDIAN
2670 * Last page of 8 MB little-endian aperture is MMIO
2671 * FIXME: we should use the auxiliary aperture instead so we can acces the
2672 * full 8 MB of video RAM on 8 MB boards
2674 if (fix->smem_len > 0x800000-GUI_RESERVE)
2675 fix->smem_len = 0x800000-GUI_RESERVE;
2676 #endif
2678 * Reg Block 0 (CT-compatible block) is at ati_regbase_phys
2679 * Reg Block 1 (multimedia extensions) is at ati_regbase_phys-0x400
2681 if (Gx == GX_CHIP_ID || Gx == CX_CHIP_ID) {
2682 fix->mmio_start = info->ati_regbase_phys;
2683 fix->mmio_len = 0x400;
2684 fix->accel = FB_ACCEL_ATI_MACH64GX;
2685 } else if (Gx == CT_CHIP_ID || Gx == ET_CHIP_ID) {
2686 fix->mmio_start = info->ati_regbase_phys;
2687 fix->mmio_len = 0x400;
2688 fix->accel = FB_ACCEL_ATI_MACH64CT;
2689 } else if (Gx == VT_CHIP_ID || Gx == VU_CHIP_ID || Gx == VV_CHIP_ID) {
2690 fix->mmio_start = info->ati_regbase_phys-0x400;
2691 fix->mmio_len = 0x800;
2692 fix->accel = FB_ACCEL_ATI_MACH64VT;
2693 } else {
2694 fix->mmio_start = info->ati_regbase_phys-0x400;
2695 fix->mmio_len = 0x800;
2696 fix->accel = FB_ACCEL_ATI_MACH64GT;
2698 fix->type = FB_TYPE_PACKED_PIXELS;
2699 fix->type_aux = 0;
2700 fix->line_length = par->crtc.vxres*par->crtc.bpp/8;
2701 fix->visual = par->crtc.bpp <= 8 ? FB_VISUAL_PSEUDOCOLOR
2702 : FB_VISUAL_DIRECTCOLOR;
2703 fix->ywrapstep = 0;
2704 fix->xpanstep = 8;
2705 fix->ypanstep = 1;
2707 return 0;
2711 struct fb_var_screeninfo default_var = {
2712 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
2713 640, 480, 640, 480, 0, 0, 8, 0,
2714 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
2715 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
2716 0, FB_VMODE_NONINTERLACED
2721 * Get the Fixed Part of the Display
2724 static int atyfb_get_fix(struct fb_fix_screeninfo *fix, int con,
2725 struct fb_info *fb)
2727 const struct fb_info_aty *info = (struct fb_info_aty *)fb;
2728 struct atyfb_par par;
2730 if (con == -1)
2731 par = info->default_par;
2732 else
2733 atyfb_decode_var(&fb_display[con].var, &par, info);
2734 encode_fix(fix, &par, info);
2735 return 0;
2740 * Get the User Defined Part of the Display
2743 static int atyfb_get_var(struct fb_var_screeninfo *var, int con,
2744 struct fb_info *fb)
2746 const struct fb_info_aty *info = (struct fb_info_aty *)fb;
2748 if (con == -1)
2749 atyfb_encode_var(var, &info->default_par, info);
2750 else
2751 *var = fb_display[con].var;
2752 return 0;
2756 static void atyfb_set_disp(struct display *disp, struct fb_info_aty *info,
2757 int bpp, int accel)
2759 switch (bpp) {
2760 #ifdef FBCON_HAS_CFB8
2761 case 8:
2762 info->dispsw = accel ? fbcon_aty8 : fbcon_cfb8;
2763 disp->dispsw = &info->dispsw;
2764 break;
2765 #endif
2766 #ifdef FBCON_HAS_CFB16
2767 case 16:
2768 info->dispsw = accel ? fbcon_aty16 : fbcon_cfb16;
2769 disp->dispsw = &info->dispsw;
2770 disp->dispsw_data = info->fbcon_cmap.cfb16;
2771 break;
2772 #endif
2773 #ifdef FBCON_HAS_CFB24
2774 case 24:
2775 info->dispsw = accel ? fbcon_aty24 : fbcon_cfb24;
2776 disp->dispsw = &info->dispsw;
2777 disp->dispsw_data = info->fbcon_cmap.cfb24;
2778 break;
2779 #endif
2780 #ifdef FBCON_HAS_CFB32
2781 case 32:
2782 info->dispsw = accel ? fbcon_aty32 : fbcon_cfb32;
2783 disp->dispsw = &info->dispsw;
2784 disp->dispsw_data = info->fbcon_cmap.cfb32;
2785 break;
2786 #endif
2787 default:
2788 disp->dispsw = &fbcon_dummy;
2790 if (info->cursor) {
2791 info->dispsw.cursor = atyfb_cursor;
2792 info->dispsw.set_font = atyfb_set_font;
2798 * Set the User Defined Part of the Display
2801 static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
2802 struct fb_info *fb)
2804 struct fb_info_aty *info = (struct fb_info_aty *)fb;
2805 struct atyfb_par par;
2806 struct display *display;
2807 int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel, accel, err;
2808 int activate = var->activate;
2810 if (con >= 0)
2811 display = &fb_display[con];
2812 else
2813 display = fb->disp; /* used during initialization */
2815 if ((err = atyfb_decode_var(var, &par, info)))
2816 return err;
2818 atyfb_encode_var(var, &par, (struct fb_info_aty *)info);
2820 if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
2821 oldxres = display->var.xres;
2822 oldyres = display->var.yres;
2823 oldvxres = display->var.xres_virtual;
2824 oldvyres = display->var.yres_virtual;
2825 oldbpp = display->var.bits_per_pixel;
2826 oldaccel = display->var.accel_flags;
2827 display->var = *var;
2828 if (oldxres != var->xres || oldyres != var->yres ||
2829 oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
2830 oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) {
2831 struct fb_fix_screeninfo fix;
2833 encode_fix(&fix, &par, info);
2834 display->screen_base = (char *)info->frame_buffer;
2835 display->visual = fix.visual;
2836 display->type = fix.type;
2837 display->type_aux = fix.type_aux;
2838 display->ypanstep = fix.ypanstep;
2839 display->ywrapstep = fix.ywrapstep;
2840 display->line_length = fix.line_length;
2841 display->can_soft_blank = 1;
2842 display->inverse = 0;
2843 accel = var->accel_flags & FB_ACCELF_TEXT;
2844 atyfb_set_disp(display, info, par.crtc.bpp, accel);
2845 if (accel)
2846 display->scrollmode = (info->bus_type == PCI) ? SCROLL_YNOMOVE : 0;
2847 else
2848 display->scrollmode = SCROLL_YREDRAW;
2849 if (info->fb_info.changevar)
2850 (*info->fb_info.changevar)(con);
2852 if (!info->fb_info.display_fg ||
2853 info->fb_info.display_fg->vc_num == con)
2854 atyfb_set_par(&par, info);
2855 if (oldbpp != var->bits_per_pixel) {
2856 if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
2857 return err;
2858 do_install_cmap(con, &info->fb_info);
2862 return 0;
2867 * Pan or Wrap the Display
2869 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
2872 static int atyfb_pan_display(struct fb_var_screeninfo *var, int con,
2873 struct fb_info *fb)
2875 struct fb_info_aty *info = (struct fb_info_aty *)fb;
2876 u32 xres, yres, xoffset, yoffset;
2877 struct atyfb_par *par = &info->current_par;
2879 xres = (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8;
2880 yres = ((par->crtc.v_tot_disp>>16) & 0x7ff)+1;
2881 xoffset = (var->xoffset+7) & ~7;
2882 yoffset = var->yoffset;
2883 if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres)
2884 return -EINVAL;
2885 par->crtc.xoffset = xoffset;
2886 par->crtc.yoffset = yoffset;
2887 set_off_pitch(par, info);
2888 return 0;
2892 * Get the Colormap
2895 static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
2896 struct fb_info *info)
2898 if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */
2899 return fb_get_cmap(cmap, kspc, atyfb_getcolreg, info);
2900 else if (fb_display[con].cmap.len) /* non default colormap? */
2901 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
2902 else {
2903 int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
2904 fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
2906 return 0;
2910 * Set the Colormap
2913 static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
2914 struct fb_info *info)
2916 int err;
2917 struct display *disp;
2919 if (con >= 0)
2920 disp = &fb_display[con];
2921 else
2922 disp = info->disp;
2923 if (!disp->cmap.len) { /* no colormap allocated? */
2924 int size = disp->var.bits_per_pixel == 16 ? 32 : 256;
2925 if ((err = fb_alloc_cmap(&disp->cmap, size, 0)))
2926 return err;
2928 if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */
2929 return fb_set_cmap(cmap, kspc, atyfb_setcolreg, info);
2930 else
2931 fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
2932 return 0;
2936 #ifdef DEBUG
2937 #define ATYIO_CLKR 0x41545900 /* ATY\00 */
2938 #define ATYIO_CLKW 0x41545901 /* ATY\01 */
2940 struct atyclk {
2941 u32 ref_clk_per;
2942 u8 pll_ref_div;
2943 u8 mclk_fb_div;
2944 u8 mclk_post_div; /* 1,2,3,4,8 */
2945 u8 vclk_fb_div;
2946 u8 vclk_post_div; /* 1,2,3,4,6,8,12 */
2947 u32 dsp_xclks_per_row; /* 0-16383 */
2948 u32 dsp_loop_latency; /* 0-15 */
2949 u32 dsp_precision; /* 0-7 */
2950 u32 dsp_on; /* 0-2047 */
2951 u32 dsp_off; /* 0-2047 */
2953 #endif
2955 static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
2956 u_long arg, int con, struct fb_info *info2)
2958 #if defined(__sparc__) || defined(DEBUG)
2959 struct fb_info_aty *info = (struct fb_info_aty *)info2;
2960 #endif /* __sparc__ || DEBUG */
2961 #ifdef __sparc__
2962 struct fbtype fbtyp;
2963 struct display *disp;
2965 if (con >= 0)
2966 disp = &fb_display[con];
2967 else
2968 disp = info2->disp;
2969 #endif
2971 switch (cmd) {
2972 #ifdef __sparc__
2973 case FBIOGTYPE:
2974 fbtyp.fb_type = FBTYPE_PCI_GENERIC;
2975 fbtyp.fb_width = info->current_par.crtc.vxres;
2976 fbtyp.fb_height = info->current_par.crtc.vyres;
2977 fbtyp.fb_depth = info->current_par.crtc.bpp;
2978 fbtyp.fb_cmsize = disp->cmap.len;
2979 fbtyp.fb_size = info->total_vram;
2980 copy_to_user_ret((struct fbtype *)arg, &fbtyp, sizeof(fbtyp), -EFAULT);
2981 break;
2982 #endif /* __sparc__ */
2983 #ifdef DEBUG
2984 case ATYIO_CLKR:
2985 if ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
2986 struct atyclk clk;
2987 struct pll_ct *pll = &info->current_par.pll.ct;
2988 u32 dsp_config = pll->dsp_config;
2989 u32 dsp_on_off = pll->dsp_on_off;
2990 clk.ref_clk_per = info->ref_clk_per;
2991 clk.pll_ref_div = pll->pll_ref_div;
2992 clk.mclk_fb_div = pll->mclk_fb_div;
2993 clk.mclk_post_div = pll->mclk_post_div_real;
2994 clk.vclk_fb_div = pll->vclk_fb_div;
2995 clk.vclk_post_div = pll->vclk_post_div_real;
2996 clk.dsp_xclks_per_row = dsp_config & 0x3fff;
2997 clk.dsp_loop_latency = (dsp_config>>16) & 0xf;
2998 clk.dsp_precision = (dsp_config>>20) & 7;
2999 clk.dsp_on = dsp_on_off & 0x7ff;
3000 clk.dsp_off = (dsp_on_off>>16) & 0x7ff;
3001 copy_to_user_ret((struct atyclk *)arg, &clk, sizeof(clk),
3002 -EFAULT);
3003 } else
3004 return -EINVAL;
3005 break;
3006 case ATYIO_CLKW:
3007 if ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
3008 struct atyclk clk;
3009 struct pll_ct *pll = &info->current_par.pll.ct;
3010 copy_from_user_ret(&clk, (struct atyclk *)arg, sizeof(clk),
3011 -EFAULT);
3012 info->ref_clk_per = clk.ref_clk_per;
3013 pll->pll_ref_div = clk.pll_ref_div;
3014 pll->mclk_fb_div = clk.mclk_fb_div;
3015 pll->mclk_post_div_real = clk.mclk_post_div;
3016 pll->vclk_fb_div = clk.vclk_fb_div;
3017 pll->vclk_post_div_real = clk.vclk_post_div;
3018 pll->dsp_config = (clk.dsp_xclks_per_row & 0x3fff) |
3019 ((clk.dsp_loop_latency & 0xf)<<16) |
3020 ((clk.dsp_precision & 7)<<20);
3021 pll->dsp_on_off = (clk.dsp_on & 0x7ff) |
3022 ((clk.dsp_off & 0x7ff)<<16);
3023 aty_calc_pll_ct(info, pll);
3024 aty_set_pll_ct(info, pll);
3025 } else
3026 return -EINVAL;
3027 break;
3028 #endif /* DEBUG */
3029 default:
3030 return -EINVAL;
3032 return 0;
3035 static int atyfb_rasterimg(struct fb_info *info, int start)
3037 struct fb_info_aty *fb = (struct fb_info_aty *)info;
3039 if (fb->blitter_may_be_busy)
3040 wait_for_idle(fb);
3041 return 0;
3044 #ifdef __sparc__
3045 static int atyfb_mmap(struct fb_info *info, struct file *file,
3046 struct vm_area_struct *vma)
3048 struct fb_info_aty *fb = (struct fb_info_aty *)info;
3049 unsigned int size, page, map_size = 0;
3050 unsigned long map_offset = 0;
3051 int i;
3053 if (!fb->mmap_map)
3054 return -ENXIO;
3056 size = vma->vm_end - vma->vm_start;
3057 if (vma->vm_offset & ~PAGE_MASK)
3058 return -ENXIO;
3060 /* To stop the swapper from even considering these pages. */
3061 vma->vm_flags |= (VM_SHM | VM_LOCKED);
3063 if (((vma->vm_offset == 0) && (size == fb->total_vram)) ||
3064 ((vma->vm_offset == fb->total_vram) && (size == PAGE_SIZE)))
3065 vma->vm_offset += 0x8000000000000000UL;
3067 #ifdef __sparc_v9__
3068 /* Align it as much as desirable */
3070 unsigned long j, align;
3071 int max = -1;
3073 map_offset = vma->vm_offset+size;
3074 for (i = 0; fb->mmap_map[i].size; i++) {
3075 if (fb->mmap_map[i].voff < vma->vm_offset)
3076 continue;
3077 if (fb->mmap_map[i].voff >= map_offset)
3078 break;
3079 if (max < 0 ||
3080 fb->mmap_map[i].size > fb->mmap_map[max].size)
3081 max = i;
3083 if (max >= 0) {
3084 j = fb->mmap_map[max].size;
3085 if (fb->mmap_map[max].voff + j > map_offset)
3086 j = map_offset - fb->mmap_map[max].voff;
3087 for (align = 0x400000; align > PAGE_SIZE; align >>= 3)
3088 if (j >= align &&
3089 !(fb->mmap_map[max].poff & (align - 1)))
3090 break;
3091 if (align > PAGE_SIZE) {
3092 j = align;
3093 align = j - ((vma->vm_start
3094 + fb->mmap_map[max].voff
3095 - vma->vm_offset) & (j - 1));
3096 if (align != j) {
3097 struct vm_area_struct *vmm;
3099 vmm = find_vma(current->mm,
3100 vma->vm_start);
3101 if (!vmm || vmm->vm_start
3102 >= vma->vm_end + align) {
3103 vma->vm_start += align;
3104 vma->vm_end += align;
3110 #endif
3112 /* Each page, see which map applies */
3113 for (page = 0; page < size; ) {
3114 map_size = 0;
3115 for (i = 0; fb->mmap_map[i].size; i++) {
3116 unsigned long start = fb->mmap_map[i].voff;
3117 unsigned long end = start + fb->mmap_map[i].size;
3118 unsigned long offset = vma->vm_offset + page;
3120 if (start > offset)
3121 continue;
3122 if (offset >= end)
3123 continue;
3125 map_size = fb->mmap_map[i].size - (offset - start);
3126 map_offset = fb->mmap_map[i].poff + (offset - start);
3127 break;
3129 if (!map_size) {
3130 page += PAGE_SIZE;
3131 continue;
3133 if (page + map_size > size)
3134 map_size = size - page;
3136 pgprot_val(vma->vm_page_prot) &= ~(fb->mmap_map[i].prot_mask);
3137 pgprot_val(vma->vm_page_prot) |= fb->mmap_map[i].prot_flag;
3139 if (remap_page_range(vma->vm_start + page, map_offset,
3140 map_size, vma->vm_page_prot))
3141 return -EAGAIN;
3143 page += map_size;
3146 if (!map_size)
3147 return -EINVAL;
3149 vma->vm_flags |= VM_IO;
3151 if (!fb->mmaped) {
3152 int lastconsole = 0;
3154 if (info->display_fg)
3155 lastconsole = info->display_fg->vc_num;
3156 fb->mmaped = 1;
3157 if (fb->consolecnt && fb_display[lastconsole].fb_info == info) {
3158 fb->vtconsole = lastconsole;
3159 vt_cons[lastconsole]->vc_mode = KD_GRAPHICS;
3162 return 0;
3165 static struct {
3166 u32 yoffset;
3167 u8 r[2][256];
3168 u8 g[2][256];
3169 u8 b[2][256];
3170 } atyfb_save;
3172 static void atyfb_save_palette(struct fb_info *fb, int enter)
3174 struct fb_info_aty *info = (struct fb_info_aty *)fb;
3175 int i, tmp, scale;
3177 for (i = 0; i < 256; i++) {
3178 tmp = aty_ld_8(DAC_CNTL, info) & 0xfc;
3179 if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == GV_CHIP_ID ||
3180 Gx == GW_CHIP_ID || Gx == GZ_CHIP_ID || Gx == LG_CHIP_ID ||
3181 Gx == GB_CHIP_ID || Gx == GD_CHIP_ID || Gx == GI_CHIP_ID ||
3182 Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID)
3183 tmp |= 0x2;
3184 aty_st_8(DAC_CNTL, tmp, info);
3185 aty_st_8(DAC_MASK, 0xff, info);
3186 eieio();
3187 scale = ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID) &&
3188 (info->current_par.crtc.bpp == 16)) ? 3 : 0;
3189 info->aty_cmap_regs->rindex = i << scale;
3190 eieio();
3191 atyfb_save.r[enter][i] = info->aty_cmap_regs->lut;
3192 eieio();
3193 atyfb_save.g[enter][i] = info->aty_cmap_regs->lut;
3194 eieio();
3195 atyfb_save.b[enter][i] = info->aty_cmap_regs->lut;
3196 eieio();
3197 info->aty_cmap_regs->windex = i << scale;
3198 eieio();
3199 info->aty_cmap_regs->lut = atyfb_save.r[1-enter][i];
3200 eieio();
3201 info->aty_cmap_regs->lut = atyfb_save.g[1-enter][i];
3202 eieio();
3203 info->aty_cmap_regs->lut = atyfb_save.b[1-enter][i];
3204 eieio();
3208 static void atyfb_palette(int enter)
3210 struct fb_info_aty *info;
3211 struct atyfb_par *par;
3212 struct display *d;
3213 int i;
3215 for (i = 0; i < MAX_NR_CONSOLES; i++) {
3216 d = &fb_display[i];
3217 if (d->fb_info &&
3218 d->fb_info->fbops == &atyfb_ops &&
3219 d->fb_info->display_fg &&
3220 d->fb_info->display_fg->vc_num == i) {
3221 atyfb_save_palette(d->fb_info, enter);
3222 info = (struct fb_info_aty *)d->fb_info;
3223 par = &info->current_par;
3224 if (enter) {
3225 atyfb_save.yoffset = par->crtc.yoffset;
3226 par->crtc.yoffset = 0;
3227 set_off_pitch(par, info);
3228 } else {
3229 par->crtc.yoffset = atyfb_save.yoffset;
3230 set_off_pitch(par, info);
3232 break;
3236 #endif /* __sparc__ */
3239 * Initialisation
3242 static int __init aty_init(struct fb_info_aty *info, const char *name)
3244 u32 chip_id;
3245 u32 i;
3246 int j, k;
3247 struct fb_var_screeninfo var;
3248 struct display *disp;
3249 const char *chipname = NULL, *ramname = NULL, *xtal;
3250 int pll, mclk, gtb_memsize;
3251 #ifdef CONFIG_PMAC
3252 int sense;
3253 #endif
3254 u8 pll_ref_div;
3256 info->aty_cmap_regs = (struct aty_cmap_regs *)(info->ati_regbase+0xc0);
3257 #ifdef __sparc_v9__
3258 info->aty_cmap_regs = __va(info->aty_cmap_regs);
3259 #endif
3260 chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
3261 Gx = chip_id & CFG_CHIP_TYPE;
3262 Rev = (chip_id & CFG_CHIP_REV)>>24;
3263 for (j = 0; j < (sizeof(aty_features)/sizeof(*aty_features)); j++)
3264 if (aty_features[j].chip_type == Gx) {
3265 chipname = aty_features[j].name;
3266 info->dac_type = (aty_ld_le32(DAC_CNTL, info) >> 16) & 0x07;
3267 break;
3269 if (!chipname) {
3270 printk("atyfb: Unknown mach64 0x%04x\n", Gx);
3271 return 0;
3272 } else
3273 printk("atyfb: %s [0x%04x rev 0x%02x] ", chipname, Gx, Rev);
3274 if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID)) {
3275 info->bus_type = (aty_ld_le32(CONFIG_STAT0, info) >> 0) & 0x07;
3276 info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) >> 3) & 0x07;
3277 ramname = aty_gx_ram[info->ram_type];
3278 /* FIXME: clockchip/RAMDAC probing? */
3279 #ifdef CONFIG_ATARI
3280 info->clk_type = CLK_ATI18818_1;
3281 info->dac_type = (aty_ld_le32(CONFIG_STAT0, info) >> 9) & 0x07;
3282 if (info->dac_type == 0x07)
3283 info->dac_subtype = DAC_ATT20C408;
3284 else
3285 info->dac_subtype = (aty_ld_8(SCRATCH_REG1 + 1, info) & 0xF0) |
3286 info->dac_type;
3287 #else
3288 info->dac_type = DAC_IBMRGB514;
3289 info->dac_subtype = DAC_IBMRGB514;
3290 info->clk_type = CLK_IBMRGB514;
3291 #endif
3292 /* FIXME */
3293 pll = 135;
3294 mclk = 50;
3295 } else {
3296 info->bus_type = PCI;
3297 info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) & 0x07);
3298 ramname = aty_ct_ram[info->ram_type];
3299 info->dac_type = DAC_INTERNAL;
3300 info->dac_subtype = DAC_INTERNAL;
3301 info->clk_type = CLK_INTERNAL;
3302 if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID)) {
3303 pll = 135;
3304 mclk = 60;
3305 } else {
3306 mclk = info->ram_type >= SDRAM ? 67 : 63;
3307 if ((Gx == VT_CHIP_ID) && (Rev == 0x08)) {
3308 /* VTA3 */
3309 pll = 170;
3310 } else if (((Gx == VT_CHIP_ID) && ((Rev == 0x40) ||
3311 (Rev == 0x48))) ||
3312 ((Gx == VT_CHIP_ID) && ((Rev == 0x01) ||
3313 (Rev == 0x9a))) ||
3314 Gx == VU_CHIP_ID) {
3315 /* VTA4 or VTB */
3316 pll = 200;
3317 } else if (Gx == VV_CHIP_ID) {
3318 /* VT4 */
3319 pll = 230;
3320 mclk = 83;
3321 } else if (Gx == VT_CHIP_ID) {
3322 /* other VT */
3323 pll = 135;
3324 mclk = 63;
3325 } else if ((Gx == GT_CHIP_ID) && (Rev & 0x01)) {
3326 /* RAGE II */
3327 pll = 170;
3328 } else if (((Gx == GT_CHIP_ID) && (Rev & 0x02)) ||
3329 (Gx == GU_CHIP_ID)) {
3330 /* RAGE II+ */
3331 pll = 200;
3332 } else if (Gx == GV_CHIP_ID || Gx == GW_CHIP_ID ||
3333 Gx == GZ_CHIP_ID) {
3334 /* RAGE IIC */
3335 pll = 230;
3336 mclk = 83;
3337 } else if (Gx == GB_CHIP_ID || Gx == GD_CHIP_ID ||
3338 Gx == GI_CHIP_ID || Gx == GP_CHIP_ID ||
3339 Gx == GQ_CHIP_ID || Gx == LB_CHIP_ID ||
3340 Gx == LD_CHIP_ID || Gx == LG_CHIP_ID ||
3341 Gx == LI_CHIP_ID || Gx == LP_CHIP_ID) {
3342 /* RAGE PRO or LT PRO */
3343 pll = 230;
3344 mclk = 100;
3345 } else {
3346 /* other RAGE */
3347 pll = 135;
3348 mclk = 63;
3353 info->ref_clk_per = 1000000000000ULL/14318180;
3354 xtal = "14.31818";
3355 if (!(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
3356 Gx == ET_CHIP_ID ||
3357 ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07))) &&
3358 (pll_ref_div = aty_ld_pll(PLL_REF_DIV, info))) {
3359 int diff1, diff2;
3360 diff1 = 510*14/pll_ref_div-pll;
3361 diff2 = 510*29/pll_ref_div-pll;
3362 if (diff1 < 0)
3363 diff1 = -diff1;
3364 if (diff2 < 0)
3365 diff2 = -diff2;
3366 if (diff2 < diff1) {
3367 info->ref_clk_per = 1000000000000ULL/29498928;
3368 xtal = "29.498928";
3372 i = aty_ld_le32(MEM_CNTL, info);
3373 gtb_memsize = !(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
3374 Gx == ET_CHIP_ID ||
3375 ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07)));
3376 if (gtb_memsize)
3377 switch (i & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */
3378 case MEM_SIZE_512K:
3379 info->total_vram = 0x80000;
3380 break;
3381 case MEM_SIZE_1M:
3382 info->total_vram = 0x100000;
3383 break;
3384 case MEM_SIZE_2M_GTB:
3385 info->total_vram = 0x200000;
3386 break;
3387 case MEM_SIZE_4M_GTB:
3388 info->total_vram = 0x400000;
3389 break;
3390 case MEM_SIZE_6M_GTB:
3391 info->total_vram = 0x600000;
3392 break;
3393 case MEM_SIZE_8M_GTB:
3394 info->total_vram = 0x800000;
3395 break;
3396 default:
3397 info->total_vram = 0x80000;
3399 else
3400 switch (i & MEM_SIZE_ALIAS) {
3401 case MEM_SIZE_512K:
3402 info->total_vram = 0x80000;
3403 break;
3404 case MEM_SIZE_1M:
3405 info->total_vram = 0x100000;
3406 break;
3407 case MEM_SIZE_2M:
3408 info->total_vram = 0x200000;
3409 break;
3410 case MEM_SIZE_4M:
3411 info->total_vram = 0x400000;
3412 break;
3413 case MEM_SIZE_6M:
3414 info->total_vram = 0x600000;
3415 break;
3416 case MEM_SIZE_8M:
3417 info->total_vram = 0x800000;
3418 break;
3419 default:
3420 info->total_vram = 0x80000;
3423 if (Gx == GI_CHIP_ID) {
3424 if (aty_ld_le32(CONFIG_STAT1, info) & 0x40000000)
3425 info->total_vram += 0x400000;
3428 if (default_vram) {
3429 info->total_vram = default_vram*1024;
3430 i = i & ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS);
3431 if (info->total_vram <= 0x80000)
3432 i |= MEM_SIZE_512K;
3433 else if (info->total_vram <= 0x100000)
3434 i |= MEM_SIZE_1M;
3435 else if (info->total_vram <= 0x200000)
3436 i |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M;
3437 else if (info->total_vram <= 0x400000)
3438 i |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M;
3439 else if (info->total_vram <= 0x600000)
3440 i |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M;
3441 else
3442 i |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M;
3443 aty_st_le32(MEM_CNTL, i, info);
3445 if (default_pll)
3446 pll = default_pll;
3447 if (default_mclk)
3448 mclk = default_mclk;
3450 printk("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK\n",
3451 info->total_vram == 0x80000 ? 512 : (info->total_vram >> 20),
3452 info->total_vram == 0x80000 ? 'K' : 'M', ramname, xtal, pll, mclk);
3454 if (mclk < 44)
3455 info->mem_refresh_rate = 0; /* 000 = 10 Mhz - 43 Mhz */
3456 else if (mclk < 50)
3457 info->mem_refresh_rate = 1; /* 001 = 44 Mhz - 49 Mhz */
3458 else if (mclk < 55)
3459 info->mem_refresh_rate = 2; /* 010 = 50 Mhz - 54 Mhz */
3460 else if (mclk < 66)
3461 info->mem_refresh_rate = 3; /* 011 = 55 Mhz - 65 Mhz */
3462 else if (mclk < 75)
3463 info->mem_refresh_rate = 4; /* 100 = 66 Mhz - 74 Mhz */
3464 else if (mclk < 80)
3465 info->mem_refresh_rate = 5; /* 101 = 75 Mhz - 79 Mhz */
3466 else if (mclk < 100)
3467 info->mem_refresh_rate = 6; /* 110 = 80 Mhz - 100 Mhz */
3468 else
3469 info->mem_refresh_rate = 7; /* 111 = 100 Mhz and above */
3470 info->pll_per = 1000000/pll;
3471 info->mclk_per = 1000000/mclk;
3473 #ifdef DEBUG
3474 if ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
3475 int i;
3476 printk("BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
3477 "DSP_CONFIG DSP_ON_OFF\n"
3478 "%08x %08x %08x %08x %08x %08x %08x\n"
3479 "PLL",
3480 aty_ld_le32(BUS_CNTL, info), aty_ld_le32(DAC_CNTL, info),
3481 aty_ld_le32(MEM_CNTL, info), aty_ld_le32(EXT_MEM_CNTL, info),
3482 aty_ld_le32(CRTC_GEN_CNTL, info), aty_ld_le32(DSP_CONFIG, info),
3483 aty_ld_le32(DSP_ON_OFF, info));
3484 for (i = 0; i < 16; i++)
3485 printk(" %02x", aty_ld_pll(i, info));
3486 printk("\n");
3488 #endif
3490 if (info->bus_type == ISA)
3491 if ((info->total_vram == 0x400000) || (info->total_vram == 0x800000)) {
3492 /* protect GUI-regs if complete Aperture is VRAM */
3493 info->total_vram -= GUI_RESERVE;
3496 disp = &info->disp;
3498 strcpy(info->fb_info.modename, atyfb_name);
3499 info->fb_info.node = -1;
3500 info->fb_info.fbops = &atyfb_ops;
3501 info->fb_info.disp = disp;
3502 strcpy(info->fb_info.fontname, fontname);
3503 info->fb_info.changevar = NULL;
3504 info->fb_info.switch_con = &atyfbcon_switch;
3505 info->fb_info.updatevar = &atyfbcon_updatevar;
3506 info->fb_info.blank = &atyfbcon_blank;
3507 info->fb_info.flags = FBINFO_FLAG_DEFAULT;
3509 #ifdef MODULE
3510 var = default_var;
3511 #else /* !MODULE */
3512 memset(&var, 0, sizeof(var));
3513 #ifdef CONFIG_PMAC
3515 * FIXME: The NVRAM stuff should be put in a Mac-specific file, as it
3516 * applies to all Mac video cards
3518 if (mode_option) {
3519 if (!mac_find_mode(&var, &info->fb_info, mode_option, 8))
3520 var = default_var;
3521 } else {
3522 #ifdef CONFIG_NVRAM
3523 if (default_vmode == VMODE_NVRAM) {
3524 default_vmode = nvram_read_byte(NV_VMODE);
3525 if (default_vmode <= 0 || default_vmode > VMODE_MAX)
3526 default_vmode = VMODE_CHOOSE;
3528 #endif
3529 if (default_vmode == VMODE_CHOOSE) {
3530 if (Gx == LG_CHIP_ID)
3531 /* G3 PowerBook with 1024x768 LCD */
3532 default_vmode = VMODE_1024_768_60;
3533 else {
3534 sense = read_aty_sense(info);
3535 default_vmode = mac_map_monitor_sense(sense);
3538 if (default_vmode <= 0 || default_vmode > VMODE_MAX)
3539 default_vmode = VMODE_640_480_60;
3540 #ifdef CONFIG_NVRAM
3541 if (default_cmode == CMODE_NVRAM)
3542 default_cmode = nvram_read_byte(NV_CMODE);
3543 #endif
3544 if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
3545 default_cmode = CMODE_8;
3546 if (mac_vmode_to_var(default_vmode, default_cmode, &var))
3547 var = default_var;
3549 #else /* !CONFIG_PMAC */
3550 #ifdef __sparc__
3551 if (mode_option) {
3552 if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
3553 var = default_var;
3554 } else
3555 var = default_var;
3556 #else
3557 if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
3558 var = default_var;
3559 #endif /* !__sparc__ */
3560 #endif /* !CONFIG_PMAC */
3561 #endif /* !MODULE */
3562 if (noaccel)
3563 var.accel_flags &= ~FB_ACCELF_TEXT;
3564 else
3565 var.accel_flags |= FB_ACCELF_TEXT;
3567 if (var.yres == var.yres_virtual) {
3568 u32 vram = (info->total_vram - (PAGE_SIZE << 2));
3569 var.yres_virtual = ((vram * 8) / var.bits_per_pixel) / var.xres_virtual;
3570 if (var.yres_virtual < var.yres)
3571 var.yres_virtual = var.yres;
3574 if (atyfb_decode_var(&var, &info->default_par, info)) {
3575 printk("atyfb: can't set default video mode\n");
3576 return 0;
3579 #ifdef __sparc__
3580 atyfb_save_palette(&info->fb_info, 0);
3581 #endif
3582 for (j = 0; j < 16; j++) {
3583 k = color_table[j];
3584 info->palette[j].red = default_red[k];
3585 info->palette[j].green = default_grn[k];
3586 info->palette[j].blue = default_blu[k];
3589 if (Gx != GX_CHIP_ID && Gx != CX_CHIP_ID) {
3590 info->cursor = aty_init_cursor(info);
3591 if (info->cursor) {
3592 info->dispsw.cursor = atyfb_cursor;
3593 info->dispsw.set_font = atyfb_set_font;
3597 atyfb_set_var(&var, -1, &info->fb_info);
3599 if (register_framebuffer(&info->fb_info) < 0)
3600 return 0;
3602 info->next = fb_list;
3603 fb_list = info;
3605 printk("fb%d: %s frame buffer device on %s\n",
3606 GET_FB_IDX(info->fb_info.node), atyfb_name, name);
3607 return 1;
3610 int __init atyfb_init(void)
3612 #if defined(CONFIG_FB_OF)
3613 /* We don't want to be called like this. */
3614 /* We rely on Open Firmware (offb) instead. */
3615 #elif defined(CONFIG_PCI)
3616 struct pci_dev *pdev;
3617 struct fb_info_aty *info;
3618 unsigned long addr;
3619 #ifdef __sparc__
3620 extern void (*prom_palette) (int);
3621 extern int con_is_present(void);
3622 struct pcidev_cookie *pcp;
3623 char prop[128];
3624 int node, len;
3625 u32 mem, chip_id;
3626 int i, j;
3628 /* Do not attach when we have a serial console. */
3629 if (!con_is_present())
3630 return -ENXIO;
3631 #else
3632 u16 tmp;
3633 #endif
3635 for (pdev = pci_devices; pdev; pdev = pdev->next) {
3636 if (((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) &&
3637 (pdev->vendor == PCI_VENDOR_ID_ATI)) {
3638 struct resource *rp;
3640 info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
3641 if (!info) {
3642 printk("atyfb_init: can't alloc fb_info_aty\n");
3643 return -ENXIO;
3645 memset(info, 0, sizeof(struct fb_info_aty));
3647 rp = &pdev->resource[0];
3648 if (rp->flags & IORESOURCE_IO)
3649 rp = &pdev->resource[1];
3650 addr = rp->start;
3651 if (!addr)
3652 continue;
3654 #ifdef __sparc__
3656 * Map memory-mapped registers.
3658 info->ati_regbase = addr + 0x7ffc00UL;
3659 info->ati_regbase_phys = addr + 0x7ffc00UL;
3662 * Map in big-endian aperture.
3664 info->frame_buffer = (unsigned long) __va(addr + 0x800000UL);
3665 info->frame_buffer_phys = addr + 0x800000UL;
3668 * Figure mmap addresses from PCI config space.
3669 * Split Framebuffer in big- and little-endian halfs.
3671 for (i = 0; i < 6 && pdev->resource[i].start; i++)
3672 /* nothing */;
3673 j = i + 4;
3675 info->mmap_map = kmalloc(j * sizeof(*info->mmap_map), GFP_ATOMIC);
3676 if (!info->mmap_map) {
3677 printk("atyfb_init: can't alloc mmap_map\n");
3678 kfree(info);
3679 return -ENXIO;
3681 memset(info->mmap_map, 0, j * sizeof(*info->mmap_map));
3683 for (i = 0, j = 2; i < 6 && pdev->resource[i].start; i++) {
3684 struct resource *rp = &pdev->resource[i];
3685 int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
3686 unsigned long base;
3687 u32 size, pbase;
3689 base = rp->start;
3691 io = (rp->flags & IORESOURCE_IO);
3693 size = rp->end - base + 1;
3695 pci_read_config_dword(pdev, breg, &pbase);
3697 if (io)
3698 size &= ~1;
3701 * Map the framebuffer a second time, this time without
3702 * the braindead _PAGE_IE setting. This is used by the
3703 * fixed Xserver, but we need to maintain the old mapping
3704 * to stay compatible with older ones...
3706 if (base == addr) {
3707 info->mmap_map[j].voff = (pbase + 0x10000000) & PAGE_MASK;
3708 info->mmap_map[j].poff = base & PAGE_MASK;
3709 info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
3710 info->mmap_map[j].prot_mask = _PAGE_CACHE;
3711 info->mmap_map[j].prot_flag = _PAGE_E;
3712 j++;
3716 * Here comes the old framebuffer mapping with _PAGE_IE
3717 * set for the big endian half of the framebuffer...
3719 if (base == addr) {
3720 info->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK;
3721 info->mmap_map[j].poff = (base+0x800000) & PAGE_MASK;
3722 info->mmap_map[j].size = 0x800000;
3723 info->mmap_map[j].prot_mask = _PAGE_CACHE;
3724 info->mmap_map[j].prot_flag = _PAGE_E|_PAGE_IE;
3725 size -= 0x800000;
3726 j++;
3729 info->mmap_map[j].voff = pbase & PAGE_MASK;
3730 info->mmap_map[j].poff = base & PAGE_MASK;
3731 info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
3732 info->mmap_map[j].prot_mask = _PAGE_CACHE;
3733 info->mmap_map[j].prot_flag = _PAGE_E;
3734 j++;
3738 * Fix PROMs idea of MEM_CNTL settings...
3740 mem = aty_ld_le32(MEM_CNTL, info);
3741 chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
3742 if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) &&
3743 !((chip_id >> 24) & 1)) {
3744 switch (mem & 0x0f) {
3745 case 3:
3746 mem = (mem & ~(0x0f)) | 2;
3747 break;
3748 case 7:
3749 mem = (mem & ~(0x0f)) | 3;
3750 break;
3751 case 9:
3752 mem = (mem & ~(0x0f)) | 4;
3753 break;
3754 case 11:
3755 mem = (mem & ~(0x0f)) | 5;
3756 break;
3757 default:
3758 break;
3760 if ((aty_ld_le32(CONFIG_STAT0, info) & 7) >= SDRAM)
3761 mem &= ~(0x00700000);
3763 mem &= ~(0xcf80e000); /* Turn off all undocumented bits. */
3764 aty_st_le32(MEM_CNTL, mem, info);
3767 * If this is the console device, we will set default video
3768 * settings to what the PROM left us with.
3770 node = prom_getchild(prom_root_node);
3771 node = prom_searchsiblings(node, "aliases");
3772 if (node) {
3773 len = prom_getproperty(node, "screen", prop, sizeof(prop));
3774 if (len > 0) {
3775 prop[len] = '\0';
3776 node = prom_finddevice(prop);
3777 } else {
3778 node = 0;
3782 pcp = pdev->sysdata;
3783 if (node == pcp->prom_node) {
3785 struct fb_var_screeninfo *var = &default_var;
3786 unsigned int N, P, Q, M, T;
3787 u32 v_total, h_total;
3788 struct crtc crtc;
3789 u8 pll_regs[16];
3790 u8 clock_cntl;
3792 crtc.vxres = prom_getintdefault(node, "width", 1024);
3793 crtc.vyres = prom_getintdefault(node, "height", 768);
3794 crtc.bpp = prom_getintdefault(node, "depth", 8);
3795 crtc.xoffset = crtc.yoffset = 0;
3796 crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, info);
3797 crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, info);
3798 crtc.v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, info);
3799 crtc.v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, info);
3800 crtc.gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, info);
3801 aty_crtc_to_var(&crtc, var);
3803 h_total = var->xres + var->right_margin +
3804 var->hsync_len + var->left_margin;
3805 v_total = var->yres + var->lower_margin +
3806 var->vsync_len + var->upper_margin;
3809 * Read the PLL to figure actual Refresh Rate.
3811 clock_cntl = aty_ld_8(CLOCK_CNTL, info);
3812 /* printk("atyfb: CLOCK_CNTL: %02x\n", clock_cntl); */
3813 for (i = 0; i < 16; i++)
3814 pll_regs[i] = aty_ld_pll(i, info);
3817 * PLL Reference Devider M:
3819 M = pll_regs[2];
3822 * PLL Feedback Devider N (Dependant on CLOCK_CNTL):
3824 N = pll_regs[7 + (clock_cntl & 3)];
3827 * PLL Post Devider P (Dependant on CLOCK_CNTL):
3829 P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
3832 * PLL Devider Q:
3834 Q = N / P;
3837 * Target Frequency:
3839 * T * M
3840 * Q = -------
3841 * 2 * R
3843 * where R is XTALIN (= 14318 kHz).
3845 T = 2 * Q * 14318 / M;
3847 default_var.pixclock = 1000000000 / T;
3850 #else /* __sparc__ */
3852 info->ati_regbase_phys = 0x7ff000 + addr;
3853 info->ati_regbase = (unsigned long)
3854 ioremap(info->ati_regbase_phys, 0x1000);
3856 if(!info->ati_regbase) {
3857 kfree(info);
3858 return -ENOMEM;
3861 info->ati_regbase_phys += 0xc00;
3862 info->ati_regbase += 0xc00;
3865 * Enable memory-space accesses using config-space
3866 * command register.
3868 pci_read_config_word(pdev, PCI_COMMAND, &tmp);
3869 if (!(tmp & PCI_COMMAND_MEMORY)) {
3870 tmp |= PCI_COMMAND_MEMORY;
3871 pci_write_config_word(pdev, PCI_COMMAND, tmp);
3874 #ifdef __BIG_ENDIAN
3875 /* Use the big-endian aperture */
3876 addr += 0x800000;
3877 #endif
3879 /* Map in frame buffer */
3880 info->frame_buffer_phys = addr;
3881 info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
3883 if(!info->frame_buffer) {
3884 kfree(info);
3885 return -ENXIO;
3888 #endif /* __sparc__ */
3890 if (!aty_init(info, "PCI")) {
3891 if (info->mmap_map)
3892 kfree(info->mmap_map);
3893 kfree(info);
3894 return -ENXIO;
3897 #ifdef __sparc__
3898 if (!prom_palette)
3899 prom_palette = atyfb_palette;
3902 * Add /dev/fb mmap values.
3904 info->mmap_map[0].voff = 0x8000000000000000UL;
3905 info->mmap_map[0].poff = __pa(info->frame_buffer & PAGE_MASK);
3906 info->mmap_map[0].size = info->total_vram;
3907 info->mmap_map[0].prot_mask = _PAGE_CACHE;
3908 info->mmap_map[0].prot_flag = _PAGE_E;
3909 info->mmap_map[1].voff = info->mmap_map[0].voff + info->total_vram;
3910 info->mmap_map[1].poff = info->ati_regbase & PAGE_MASK;
3911 info->mmap_map[1].size = PAGE_SIZE;
3912 info->mmap_map[1].prot_mask = _PAGE_CACHE;
3913 info->mmap_map[1].prot_flag = _PAGE_E;
3914 #endif /* __sparc__ */
3918 #elif defined(CONFIG_ATARI)
3919 u32 clock_r;
3920 int m64_num;
3921 struct fb_info_aty *info;
3923 for (m64_num = 0; m64_num < mach64_count; m64_num++) {
3924 if (!phys_vmembase[m64_num] || !phys_size[m64_num] ||
3925 !phys_guiregbase[m64_num]) {
3926 printk(" phys_*[%d] parameters not set => returning early. \n",
3927 m64_num);
3928 continue;
3931 info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
3932 if (!info) {
3933 printk("atyfb_init: can't alloc fb_info_aty\n");
3934 return -ENOMEM;
3936 memset(info, 0, sizeof(struct fb_info_aty));
3939 * Map the video memory (physical address given) to somewhere in the
3940 * kernel address space.
3942 info->frame_buffer = ioremap(phys_vmembase[m64_num], phys_size[m64_num]);
3943 info->frame_buffer_phys = info->frame_buffer; /* Fake! */
3944 info->ati_regbase = ioremap(phys_guiregbase[m64_num], 0x10000)+0xFC00ul;
3945 info->ati_regbase_phys = info->ati_regbase; /* Fake! */
3947 aty_st_le32(CLOCK_CNTL, 0x12345678, info);
3948 clock_r = aty_ld_le32(CLOCK_CNTL, info);
3950 switch (clock_r & 0x003F) {
3951 case 0x12:
3952 info->clk_wr_offset = 3; /* */
3953 break;
3954 case 0x34:
3955 info->clk_wr_offset = 2; /* Medusa ST-IO ISA Adapter etc. */
3956 break;
3957 case 0x16:
3958 info->clk_wr_offset = 1; /* */
3959 break;
3960 case 0x38:
3961 info->clk_wr_offset = 0; /* Panther 1 ISA Adapter (Gerald) */
3962 break;
3965 if (!aty_init(info, "ISA bus")) {
3966 kfree(info);
3967 /* This is insufficient! kernel_map has added two large chunks!! */
3968 return -ENXIO;
3971 #endif /* CONFIG_ATARI */
3972 return 0;
3975 #ifdef CONFIG_FB_OF
3976 void __init atyfb_of_init(struct device_node *dp)
3978 unsigned long addr;
3979 u8 bus, devfn;
3980 u16 cmd;
3981 struct fb_info_aty *info;
3982 int i;
3984 if (device_is_compatible(dp, "ATY,264LTPro")) {
3985 /* XXX kludge for now */
3986 if (dp->name == 0 || strcmp(dp->name, "ATY,264LTProA") != 0
3987 || dp->parent == 0)
3988 return;
3989 dp = dp->parent;
3991 switch (dp->n_addrs) {
3992 case 1:
3993 case 2:
3994 case 3:
3995 addr = dp->addrs[0].address;
3996 break;
3997 case 4:
3998 addr = dp->addrs[1].address;
3999 break;
4000 default:
4001 printk("Warning: got %d adresses for ATY:\n", dp->n_addrs);
4002 for (i = 0; i < dp->n_addrs; i++)
4003 printk(" %08x-%08x", dp->addrs[i].address,
4004 dp->addrs[i].address+dp->addrs[i].size-1);
4005 if (dp->n_addrs)
4006 printk("\n");
4007 return;
4010 info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
4011 if (!info) {
4012 printk("atyfb_of_init: can't alloc fb_info_aty\n");
4013 return;
4015 memset(info, 0, sizeof(struct fb_info_aty));
4017 info->ati_regbase_phys = 0x7ff000+addr;
4018 info->ati_regbase = (unsigned long)ioremap(info->ati_regbase_phys,
4019 0x1000);
4021 if(! info->ati_regbase) {
4022 printk("atyfb_of_init: ioremap() returned NULL\n");
4023 kfree(info);
4024 return;
4027 info->ati_regbase_phys += 0xc00;
4028 info->ati_regbase += 0xc00;
4030 /* enable memory-space accesses using config-space command register */
4031 if (pci_device_loc(dp, &bus, &devfn) == 0) {
4032 pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd);
4033 if (cmd != 0xffff) {
4034 cmd |= PCI_COMMAND_MEMORY;
4035 pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
4039 #ifdef __BIG_ENDIAN
4040 /* Use the big-endian aperture */
4041 addr += 0x800000;
4042 #endif
4044 /* Map in frame buffer */
4045 info->frame_buffer_phys = addr;
4046 info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
4048 if(! info->frame_buffer) {
4049 printk("atyfb_of_init: ioremap() returned NULL\n");
4050 kfree(info);
4051 return;
4054 if (!aty_init(info, dp->full_name)) {
4055 kfree(info);
4056 return;
4059 #ifdef CONFIG_PMAC_PBOOK
4060 if (first_display == NULL)
4061 pmu_register_sleep_notifier(&aty_sleep_notifier);
4062 info->next = first_display;
4063 first_display = info;
4064 #endif
4067 #ifdef CONFIG_FB_COMPAT_XPMAC
4068 if (!console_fb_info)
4069 console_fb_info = &info->fb_info;
4070 #endif /* CONFIG_FB_COMPAT_XPMAC */
4072 #endif /* CONFIG_FB_OF */
4075 #ifndef MODULE
4076 int __init atyfb_setup(char *options)
4078 char *this_opt;
4080 if (!options || !*options)
4081 return 0;
4083 for (this_opt = strtok(options, ","); this_opt;
4084 this_opt = strtok(NULL, ",")) {
4085 if (!strncmp(this_opt, "font:", 5)) {
4086 char *p;
4087 int i;
4089 p = this_opt + 5;
4090 for (i = 0; i < sizeof(fontname) - 1; i++)
4091 if (!*p || *p == ' ' || *p == ',')
4092 break;
4093 memcpy(fontname, this_opt + 5, i);
4094 fontname[i] = 0;
4095 } else if (!strncmp(this_opt, "noblink", 7)) {
4096 curblink = 0;
4097 } else if (!strncmp(this_opt, "noaccel", 7)) {
4098 noaccel = 1;
4099 } else if (!strncmp(this_opt, "vram:", 5))
4100 default_vram = simple_strtoul(this_opt+5, NULL, 0);
4101 else if (!strncmp(this_opt, "pll:", 4))
4102 default_pll = simple_strtoul(this_opt+4, NULL, 0);
4103 else if (!strncmp(this_opt, "mclk:", 5))
4104 default_mclk = simple_strtoul(this_opt+5, NULL, 0);
4105 #ifdef CONFIG_PMAC
4106 else if (!strncmp(this_opt, "vmode:", 6)) {
4107 unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
4108 if (vmode > 0 && vmode <= VMODE_MAX)
4109 default_vmode = vmode;
4110 } else if (!strncmp(this_opt, "cmode:", 6)) {
4111 unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0);
4112 switch (cmode) {
4113 case 0:
4114 case 8:
4115 default_cmode = CMODE_8;
4116 break;
4117 case 15:
4118 case 16:
4119 default_cmode = CMODE_16;
4120 break;
4121 case 24:
4122 case 32:
4123 default_cmode = CMODE_32;
4124 break;
4127 #endif
4128 #ifdef CONFIG_ATARI
4130 * Why do we need this silly Mach64 argument?
4131 * We are already here because of mach64= so its redundant.
4133 else if (MACH_IS_ATARI && (!strncmp(this_opt, "Mach64:", 7))) {
4134 static unsigned char m64_num;
4135 static char mach64_str[80];
4136 strncpy(mach64_str, this_opt+7, 80);
4137 if (!store_video_par(mach64_str, m64_num)) {
4138 m64_num++;
4139 mach64_count = m64_num;
4142 #endif
4143 else
4144 mode_option = this_opt;
4146 return 0;
4148 #endif /* !MODULE */
4150 #ifdef CONFIG_ATARI
4151 static int __init store_video_par(char *video_str, unsigned char m64_num)
4153 char *p;
4154 unsigned long vmembase, size, guiregbase;
4156 printk("store_video_par() '%s' \n", video_str);
4158 if (!(p = strtoke(video_str, ";")) || !*p)
4159 goto mach64_invalid;
4160 vmembase = simple_strtoul(p, NULL, 0);
4161 if (!(p = strtoke(NULL, ";")) || !*p)
4162 goto mach64_invalid;
4163 size = simple_strtoul(p, NULL, 0);
4164 if (!(p = strtoke(NULL, ";")) || !*p)
4165 goto mach64_invalid;
4166 guiregbase = simple_strtoul(p, NULL, 0);
4168 phys_vmembase[m64_num] = vmembase;
4169 phys_size[m64_num] = size;
4170 phys_guiregbase[m64_num] = guiregbase;
4171 printk(" stored them all: $%08lX $%08lX $%08lX \n", vmembase, size,
4172 guiregbase);
4173 return 0;
4175 mach64_invalid:
4176 phys_vmembase[m64_num] = 0;
4177 return -1;
4180 static char __init *strtoke(char *s, const char *ct)
4182 static char *ssave = NULL;
4183 char *sbegin, *send;
4185 sbegin = s ? s : ssave;
4186 if (!sbegin)
4187 return NULL;
4188 if (*sbegin == '\0') {
4189 ssave = NULL;
4190 return NULL;
4192 send = strpbrk(sbegin, ct);
4193 if (send && *send != '\0')
4194 *send++ = '\0';
4195 ssave = send;
4196 return sbegin;
4198 #endif /* CONFIG_ATARI */
4200 static int atyfbcon_switch(int con, struct fb_info *fb)
4202 struct fb_info_aty *info = (struct fb_info_aty *)fb;
4203 struct atyfb_par par;
4205 /* Do we have to save the colormap? */
4206 if (fb_display[currcon].cmap.len)
4207 fb_get_cmap(&fb_display[currcon].cmap, 1, atyfb_getcolreg, fb);
4209 /* Erase HW Cursor */
4210 if (info->cursor)
4211 atyfb_cursor(&fb_display[currcon], CM_ERASE,
4212 info->cursor->pos.x, info->cursor->pos.y);
4214 currcon = con;
4216 atyfb_decode_var(&fb_display[con].var, &par, info);
4217 atyfb_set_par(&par, info);
4218 atyfb_set_disp(&fb_display[con], info, par.crtc.bpp,
4219 par.accel_flags & FB_ACCELF_TEXT);
4221 /* Install new colormap */
4222 do_install_cmap(con, fb);
4224 /* Install hw cursor */
4225 if (info->cursor) {
4226 aty_set_cursor_color(info, cursor_pixel_map, cursor_color_map,
4227 cursor_color_map, cursor_color_map);
4228 aty_set_cursor_shape(info);
4230 return 1;
4234 * Blank the display.
4237 static void atyfbcon_blank(int blank, struct fb_info *fb)
4239 struct fb_info_aty *info = (struct fb_info_aty *)fb;
4240 u8 gen_cntl;
4242 #ifdef CONFIG_PMAC
4243 if ((_machine == _MACH_Pmac) && blank)
4244 pmu_enable_backlight(0);
4245 #endif
4247 gen_cntl = aty_ld_8(CRTC_GEN_CNTL, info);
4248 if (blank > 0)
4249 switch (blank-1) {
4250 case VESA_NO_BLANKING:
4251 gen_cntl |= 0x40;
4252 break;
4253 case VESA_VSYNC_SUSPEND:
4254 gen_cntl |= 0x8;
4255 break;
4256 case VESA_HSYNC_SUSPEND:
4257 gen_cntl |= 0x4;
4258 break;
4259 case VESA_POWERDOWN:
4260 gen_cntl |= 0x4c;
4261 break;
4263 else
4264 gen_cntl &= ~(0x4c);
4265 aty_st_8(CRTC_GEN_CNTL, gen_cntl, info);
4267 #ifdef CONFIG_PMAC
4268 if ((_machine == _MACH_Pmac) && !blank)
4269 pmu_enable_backlight(1);
4270 #endif
4275 * Read a single color register and split it into
4276 * colors/transparent. Return != 0 for invalid regno.
4279 static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
4280 u_int *transp, struct fb_info *fb)
4282 struct fb_info_aty *info = (struct fb_info_aty *)fb;
4284 if (regno > 255)
4285 return 1;
4286 *red = (info->palette[regno].red<<8) | info->palette[regno].red;
4287 *green = (info->palette[regno].green<<8) | info->palette[regno].green;
4288 *blue = (info->palette[regno].blue<<8) | info->palette[regno].blue;
4289 *transp = 0;
4290 return 0;
4295 * Set a single color register. The values supplied are already
4296 * rounded down to the hardware's capabilities (according to the
4297 * entries in the var structure). Return != 0 for invalid regno.
4300 static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
4301 u_int transp, struct fb_info *fb)
4303 struct fb_info_aty *info = (struct fb_info_aty *)fb;
4304 int i, scale;
4306 if (regno > 255)
4307 return 1;
4308 red >>= 8;
4309 green >>= 8;
4310 blue >>= 8;
4311 info->palette[regno].red = red;
4312 info->palette[regno].green = green;
4313 info->palette[regno].blue = blue;
4314 i = aty_ld_8(DAC_CNTL, info) & 0xfc;
4315 if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == GV_CHIP_ID ||
4316 Gx == GW_CHIP_ID || Gx == GZ_CHIP_ID || Gx == LG_CHIP_ID ||
4317 Gx == GB_CHIP_ID || Gx == GD_CHIP_ID || Gx == GI_CHIP_ID ||
4318 Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID)
4319 i |= 0x2; /*DAC_CNTL|0x2 turns off the extra brightness for gt*/
4320 aty_st_8(DAC_CNTL, i, info);
4321 aty_st_8(DAC_MASK, 0xff, info);
4322 eieio();
4323 scale = ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID) &&
4324 (info->current_par.crtc.bpp == 16)) ? 3 : 0;
4325 info->aty_cmap_regs->windex = regno << scale;
4326 eieio();
4327 info->aty_cmap_regs->lut = red;
4328 eieio();
4329 info->aty_cmap_regs->lut = green;
4330 eieio();
4331 info->aty_cmap_regs->lut = blue;
4332 eieio();
4333 if (regno < 16)
4334 switch (info->current_par.crtc.bpp) {
4335 #ifdef FBCON_HAS_CFB16
4336 case 16:
4337 info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) |
4338 regno;
4339 break;
4340 #endif
4341 #ifdef FBCON_HAS_CFB24
4342 case 24:
4343 info->fbcon_cmap.cfb24[regno] = (regno << 16) | (regno << 8) |
4344 regno;
4345 break;
4346 #endif
4347 #ifdef FBCON_HAS_CFB32
4348 case 32:
4349 i = (regno << 8) | regno;
4350 info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
4351 break;
4352 #endif
4354 return 0;
4358 static void do_install_cmap(int con, struct fb_info *info)
4360 if (con != currcon)
4361 return;
4362 if (fb_display[con].cmap.len)
4363 fb_set_cmap(&fb_display[con].cmap, 1, atyfb_setcolreg, info);
4364 else {
4365 int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
4366 fb_set_cmap(fb_default_cmap(size), 1, atyfb_setcolreg, info);
4372 * Accelerated functions
4375 static inline void draw_rect(s16 x, s16 y, u16 width, u16 height,
4376 struct fb_info_aty *info)
4378 /* perform rectangle fill */
4379 wait_for_fifo(2, info);
4380 aty_st_le32(DST_Y_X, (x << 16) | y, info);
4381 aty_st_le32(DST_HEIGHT_WIDTH, (width << 16) | height, info);
4382 info->blitter_may_be_busy = 1;
4385 static inline void aty_rectcopy(int srcx, int srcy, int dstx, int dsty,
4386 u_int width, u_int height,
4387 struct fb_info_aty *info)
4389 u32 direction = DST_LAST_PEL;
4390 u32 pitch_value;
4392 if (!width || !height)
4393 return;
4395 pitch_value = info->current_par.crtc.vxres;
4396 if (info->current_par.crtc.bpp == 24) {
4397 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
4398 /* horizontal coordinates and widths must be adjusted */
4399 pitch_value *= 3;
4400 srcx *= 3;
4401 dstx *= 3;
4402 width *= 3;
4405 if (srcy < dsty) {
4406 dsty += height - 1;
4407 srcy += height - 1;
4408 } else
4409 direction |= DST_Y_TOP_TO_BOTTOM;
4411 if (srcx < dstx) {
4412 dstx += width - 1;
4413 srcx += width - 1;
4414 } else
4415 direction |= DST_X_LEFT_TO_RIGHT;
4417 wait_for_fifo(4, info);
4418 aty_st_le32(DP_SRC, FRGD_SRC_BLIT, info);
4419 aty_st_le32(SRC_Y_X, (srcx << 16) | srcy, info);
4420 aty_st_le32(SRC_HEIGHT1_WIDTH1, (width << 16) | height, info);
4421 aty_st_le32(DST_CNTL, direction, info);
4422 draw_rect(dstx, dsty, width, height, info);
4425 static inline void aty_rectfill(int dstx, int dsty, u_int width, u_int height,
4426 u_int color, struct fb_info_aty *info)
4428 if (!width || !height)
4429 return;
4431 if (info->current_par.crtc.bpp == 24) {
4432 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
4433 /* horizontal coordinates and widths must be adjusted */
4434 dstx *= 3;
4435 width *= 3;
4438 wait_for_fifo(3, info);
4439 aty_st_le32(DP_FRGD_CLR, color, info);
4440 aty_st_le32(DP_SRC, BKGD_SRC_BKGD_CLR | FRGD_SRC_FRGD_CLR | MONO_SRC_ONE,
4441 info);
4442 aty_st_le32(DST_CNTL, DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM |
4443 DST_X_LEFT_TO_RIGHT, info);
4444 draw_rect(dstx, dsty, width, height, info);
4448 * Update the `var' structure (called by fbcon.c)
4451 static int atyfbcon_updatevar(int con, struct fb_info *fb)
4453 struct fb_info_aty *info = (struct fb_info_aty *)fb;
4454 struct atyfb_par *par = &info->current_par;
4455 struct display *p = &fb_display[con];
4456 struct vc_data *conp = p->conp;
4457 u32 yres, yoffset, sy, height;
4459 yres = ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1;
4460 yoffset = fb_display[con].var.yoffset;
4462 sy = (conp->vc_rows + p->yscroll) * fontheight(p);
4463 height = yres - conp->vc_rows * fontheight(p);
4465 if (height && (yoffset + yres > sy)) {
4466 u32 xres, xoffset;
4467 u32 bgx;
4469 xres = (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8;
4470 xoffset = fb_display[con].var.xoffset;
4473 bgx = attr_bgcol_ec(p, conp);
4474 bgx |= (bgx << 8);
4475 bgx |= (bgx << 16);
4477 if (sy + height > par->crtc.vyres) {
4478 wait_for_fifo(1, info);
4479 aty_st_le32(SC_BOTTOM, sy + height - 1, info);
4481 aty_rectfill(xoffset, sy, xres, height, bgx, info);
4484 if (info->cursor && (yoffset + yres <= sy))
4485 atyfb_cursor(p, CM_ERASE, info->cursor->pos.x, info->cursor->pos.y);
4487 info->current_par.crtc.yoffset = yoffset;
4488 set_off_pitch(&info->current_par, info);
4489 return 0;
4493 * Text console acceleration
4496 static void fbcon_aty_bmove(struct display *p, int sy, int sx, int dy, int dx,
4497 int height, int width)
4499 #ifdef __sparc__
4500 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4502 if (fb->mmaped && (!fb->fb_info.display_fg
4503 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4504 return;
4505 #endif
4507 sx *= fontwidth(p);
4508 sy *= fontheight(p);
4509 dx *= fontwidth(p);
4510 dy *= fontheight(p);
4511 width *= fontwidth(p);
4512 height *= fontheight(p);
4514 aty_rectcopy(sx, sy, dx, dy, width, height,
4515 (struct fb_info_aty *)p->fb_info);
4518 static void fbcon_aty_clear(struct vc_data *conp, struct display *p, int sy,
4519 int sx, int height, int width)
4521 u32 bgx;
4522 #ifdef __sparc__
4523 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4525 if (fb->mmaped && (!fb->fb_info.display_fg
4526 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4527 return;
4528 #endif
4530 bgx = attr_bgcol_ec(p, conp);
4531 bgx |= (bgx << 8);
4532 bgx |= (bgx << 16);
4534 sx *= fontwidth(p);
4535 sy *= fontheight(p);
4536 width *= fontwidth(p);
4537 height *= fontheight(p);
4539 aty_rectfill(sx, sy, width, height, bgx,
4540 (struct fb_info_aty *)p->fb_info);
4543 #ifdef FBCON_HAS_CFB8
4544 static void fbcon_aty8_putc(struct vc_data *conp, struct display *p, int c,
4545 int yy, int xx)
4547 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4549 #ifdef __sparc__
4550 if (fb->mmaped && (!fb->fb_info.display_fg
4551 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4552 return;
4553 #endif
4555 if (fb->blitter_may_be_busy)
4556 wait_for_idle((struct fb_info_aty *)p->fb_info);
4557 fbcon_cfb8_putc(conp, p, c, yy, xx);
4560 static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p,
4561 const unsigned short *s, int count, int yy,
4562 int xx)
4564 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4566 #ifdef __sparc__
4567 if (fb->mmaped && (!fb->fb_info.display_fg
4568 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4569 return;
4570 #endif
4572 if (fb->blitter_may_be_busy)
4573 wait_for_idle((struct fb_info_aty *)p->fb_info);
4574 fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
4577 static void fbcon_aty8_clear_margins(struct vc_data *conp, struct display *p,
4578 int bottom_only)
4580 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4582 #ifdef __sparc__
4583 if (fb->mmaped && (!fb->fb_info.display_fg
4584 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4585 return;
4586 #endif
4588 if (fb->blitter_may_be_busy)
4589 wait_for_idle((struct fb_info_aty *)p->fb_info);
4590 fbcon_cfb8_clear_margins(conp, p, bottom_only);
4593 static struct display_switch fbcon_aty8 = {
4594 fbcon_cfb8_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty8_putc,
4595 fbcon_aty8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_aty8_clear_margins,
4596 FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4598 #endif
4600 #ifdef FBCON_HAS_CFB16
4601 static void fbcon_aty16_putc(struct vc_data *conp, struct display *p, int c,
4602 int yy, int xx)
4604 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4606 #ifdef __sparc__
4607 if (fb->mmaped && (!fb->fb_info.display_fg
4608 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4609 return;
4610 #endif
4612 if (fb->blitter_may_be_busy)
4613 wait_for_idle((struct fb_info_aty *)p->fb_info);
4614 fbcon_cfb16_putc(conp, p, c, yy, xx);
4617 static void fbcon_aty16_putcs(struct vc_data *conp, struct display *p,
4618 const unsigned short *s, int count, int yy,
4619 int xx)
4621 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4623 #ifdef __sparc__
4624 if (fb->mmaped && (!fb->fb_info.display_fg
4625 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4626 return;
4627 #endif
4629 if (fb->blitter_may_be_busy)
4630 wait_for_idle((struct fb_info_aty *)p->fb_info);
4631 fbcon_cfb16_putcs(conp, p, s, count, yy, xx);
4634 static void fbcon_aty16_clear_margins(struct vc_data *conp, struct display *p,
4635 int bottom_only)
4637 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4639 #ifdef __sparc__
4640 if (fb->mmaped && (!fb->fb_info.display_fg
4641 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4642 return;
4643 #endif
4645 if (fb->blitter_may_be_busy)
4646 wait_for_idle((struct fb_info_aty *)p->fb_info);
4647 fbcon_cfb16_clear_margins(conp, p, bottom_only);
4650 static struct display_switch fbcon_aty16 = {
4651 fbcon_cfb16_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty16_putc,
4652 fbcon_aty16_putcs, fbcon_cfb16_revc, NULL, NULL, fbcon_aty16_clear_margins,
4653 FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4655 #endif
4657 #ifdef FBCON_HAS_CFB24
4658 static void fbcon_aty24_putc(struct vc_data *conp, struct display *p, int c,
4659 int yy, int xx)
4661 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4663 #ifdef __sparc__
4664 if (fb->mmaped && (!fb->fb_info.display_fg
4665 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4666 return;
4667 #endif
4669 if (fb->blitter_may_be_busy)
4670 wait_for_idle((struct fb_info_aty *)p->fb_info);
4671 fbcon_cfb24_putc(conp, p, c, yy, xx);
4674 static void fbcon_aty24_putcs(struct vc_data *conp, struct display *p,
4675 const unsigned short *s, int count, int yy,
4676 int xx)
4678 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4680 #ifdef __sparc__
4681 if (fb->mmaped && (!fb->fb_info.display_fg
4682 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4683 return;
4684 #endif
4686 if (fb->blitter_may_be_busy)
4687 wait_for_idle((struct fb_info_aty *)p->fb_info);
4688 fbcon_cfb24_putcs(conp, p, s, count, yy, xx);
4691 static void fbcon_aty24_clear_margins(struct vc_data *conp, struct display *p,
4692 int bottom_only)
4694 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4696 #ifdef __sparc__
4697 if (fb->mmaped && (!fb->fb_info.display_fg
4698 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4699 return;
4700 #endif
4702 if (fb->blitter_may_be_busy)
4703 wait_for_idle((struct fb_info_aty *)p->fb_info);
4704 fbcon_cfb24_clear_margins(conp, p, bottom_only);
4707 static struct display_switch fbcon_aty24 = {
4708 fbcon_cfb24_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty24_putc,
4709 fbcon_aty24_putcs, fbcon_cfb24_revc, NULL, NULL, fbcon_aty24_clear_margins,
4710 FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4712 #endif
4714 #ifdef FBCON_HAS_CFB32
4715 static void fbcon_aty32_putc(struct vc_data *conp, struct display *p, int c,
4716 int yy, int xx)
4718 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4720 #ifdef __sparc__
4721 if (fb->mmaped && (!fb->fb_info.display_fg
4722 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4723 return;
4724 #endif
4726 if (fb->blitter_may_be_busy)
4727 wait_for_idle((struct fb_info_aty *)p->fb_info);
4728 fbcon_cfb32_putc(conp, p, c, yy, xx);
4731 static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p,
4732 const unsigned short *s, int count, int yy,
4733 int xx)
4735 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4737 #ifdef __sparc__
4738 if (fb->mmaped && (!fb->fb_info.display_fg
4739 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4740 return;
4741 #endif
4743 if (fb->blitter_may_be_busy)
4744 wait_for_idle((struct fb_info_aty *)p->fb_info);
4745 fbcon_cfb32_putcs(conp, p, s, count, yy, xx);
4748 static void fbcon_aty32_clear_margins(struct vc_data *conp, struct display *p,
4749 int bottom_only)
4751 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4753 #ifdef __sparc__
4754 if (fb->mmaped && (!fb->fb_info.display_fg
4755 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4756 return;
4757 #endif
4759 if (fb->blitter_may_be_busy)
4760 wait_for_idle((struct fb_info_aty *)p->fb_info);
4761 fbcon_cfb32_clear_margins(conp, p, bottom_only);
4764 static struct display_switch fbcon_aty32 = {
4765 fbcon_cfb32_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty32_putc,
4766 fbcon_aty32_putcs, fbcon_cfb32_revc, NULL, NULL, fbcon_aty32_clear_margins,
4767 FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4769 #endif
4771 #ifdef CONFIG_PMAC_PBOOK
4773 * Save the contents of the frame buffer when we go to sleep,
4774 * and restore it when we wake up again.
4777 aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
4779 struct fb_info_aty *info;
4780 unsigned int pm;
4782 for (info = first_display; info != NULL; info = info->next) {
4783 struct fb_fix_screeninfo fix;
4784 int nb;
4786 atyfb_get_fix(&fix, fg_console, (struct fb_info *)info);
4787 nb = fb_display[fg_console].var.yres * fix.line_length;
4789 switch (when) {
4790 case PBOOK_SLEEP_NOW:
4791 /* Stop accel engine (stop bus mastering) */
4792 if (info->current_par.accel_flags & FB_ACCELF_TEXT)
4793 reset_engine(info);
4794 #if 1
4795 /* Backup fb content */
4796 info->save_framebuffer = vmalloc(nb);
4797 if (info->save_framebuffer)
4798 memcpy(info->save_framebuffer,
4799 (void *)info->frame_buffer, nb);
4800 #endif
4801 /* Blank display and LCD */
4802 atyfbcon_blank(VESA_POWERDOWN+1, (struct fb_info *)info);
4804 /* Set chip to "suspend" mode. Note: There's an HW bug in the
4805 chip which prevents proper resync on wakeup with automatic
4806 power management, we handle suspend manually using the
4807 following (weird) sequence described by ATI. Note2:
4808 We could enable this for all Rage LT Pro chip ids */
4809 if ((Gx == LG_CHIP_ID) || (Gx == LT_CHIP_ID) || (Gx == LP_CHIP_ID)) {
4810 pm = aty_ld_le32(POWER_MANAGEMENT, info);
4811 pm &= ~PWR_MGT_ON;
4812 aty_st_le32(POWER_MANAGEMENT, pm, info);
4813 pm = aty_ld_le32(POWER_MANAGEMENT, info);
4814 pm &= ~(PWR_BLON | AUTO_PWR_UP);
4815 pm |= SUSPEND_NOW;
4816 aty_st_le32(POWER_MANAGEMENT, pm, info);
4817 pm = aty_ld_le32(POWER_MANAGEMENT, info);
4818 pm |= PWR_MGT_ON;
4819 aty_st_le32(POWER_MANAGEMENT, pm, info);
4820 do {
4821 pm = aty_ld_le32(POWER_MANAGEMENT, info);
4822 } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
4823 mdelay(500);
4825 break;
4826 case PBOOK_WAKE:
4827 /* Wakeup chip */
4828 if ((Gx == LG_CHIP_ID) || (Gx == LT_CHIP_ID) || (Gx == LP_CHIP_ID)) {
4829 pm = aty_ld_le32(POWER_MANAGEMENT, info);
4830 pm &= ~PWR_MGT_ON;
4831 aty_st_le32(POWER_MANAGEMENT, pm, info);
4832 pm = aty_ld_le32(POWER_MANAGEMENT, info);
4833 pm |= (PWR_BLON | AUTO_PWR_UP);
4834 pm &= ~SUSPEND_NOW;
4835 aty_st_le32(POWER_MANAGEMENT, pm, info);
4836 pm = aty_ld_le32(POWER_MANAGEMENT, info);
4837 pm |= PWR_MGT_ON;
4838 aty_st_le32(POWER_MANAGEMENT, pm, info);
4839 do {
4840 pm = aty_ld_le32(POWER_MANAGEMENT, info);
4841 } while ((pm & PWR_MGT_STATUS_MASK) != 0);
4842 mdelay(500);
4844 #if 1
4845 /* Restore fb content */
4846 if (info->save_framebuffer) {
4847 memcpy((void *)info->frame_buffer,
4848 info->save_framebuffer, nb);
4849 vfree(info->save_framebuffer);
4850 info->save_framebuffer = 0;
4852 #endif
4853 /* Restore display */
4854 atyfb_set_par(&info->current_par, info);
4855 atyfbcon_blank(0, (struct fb_info *)info);
4856 break;
4859 return PBOOK_SLEEP_OK;
4861 #endif /* CONFIG_PMAC_PBOOK */
4863 #ifdef MODULE
4864 int __init init_module(void)
4866 atyfb_init();
4867 return fb_list ? 0 : -ENXIO;
4870 void cleanup_module(void)
4872 while (fb_list) {
4873 struct fb_info_aty *info = fb_list;
4874 fb_list = info->next;
4876 unregister_framebuffer(&info->fb_info);
4878 #ifndef __sparc__
4879 if (info->ati_regbase)
4880 iounmap((void *)info->ati_regbase);
4881 if (info->frame_buffer)
4882 iounmap((void *)info->frame_buffer);
4883 #ifdef __BIG_ENDIAN
4884 if (info->cursor && info->cursor->ram)
4885 iounmap(info->cursor->ram);
4886 #endif
4887 #endif
4889 if (info->cursor) {
4890 if (info->cursor->timer)
4891 kfree(info->cursor->timer);
4892 kfree(info->cursor);
4894 #ifdef __sparc__
4895 if (info->mmap_map)
4896 kfree(info->mmap_map);
4897 #endif
4898 kfree(info);
4902 #endif