Import 2.3.18pre1
[davej-history.git] / drivers / video / atyfb.c
blobf12fec6e11d0428ed2dbb7c08e81c9be103d5e8d
1 /* $Id: atyfb.c,v 1.122 1999/09/06 20:44:08 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/nvram.h>
56 #include <linux/kd.h>
57 #include <linux/vt_kern.h>
59 #ifdef CONFIG_FB_COMPAT_XPMAC
60 #include <asm/vc_ioctl.h>
61 #endif
63 #include <asm/io.h>
65 #if defined(CONFIG_PPC)
66 #include <asm/prom.h>
67 #include <asm/pci-bridge.h>
68 #include <video/macmodes.h>
69 #include <asm/adb.h>
70 #include <asm/pmu.h>
71 #endif
72 #ifdef __sparc__
73 #include <asm/pbm.h>
74 #include <asm/fbio.h>
75 #endif
76 #include <asm/uaccess.h>
78 #include <video/fbcon.h>
79 #include <video/fbcon-cfb8.h>
80 #include <video/fbcon-cfb16.h>
81 #include <video/fbcon-cfb24.h>
82 #include <video/fbcon-cfb32.h>
84 #include "aty.h"
88 * Debug flags.
90 #undef DEBUG
92 /* Definitions for the ICS 2595 == ATI 18818_1 Clockchip */
94 #define REF_FREQ_2595 1432 /* 14.33 MHz (exact 14.31818) */
95 #define REF_DIV_2595 46 /* really 43 on ICS 2595 !!! */
96 /* ohne Prescaler */
97 #define MAX_FREQ_2595 15938 /* 159.38 MHz (really 170.486) */
98 #define MIN_FREQ_2595 8000 /* 80.00 MHz ( 85.565) */
99 /* mit Prescaler 2, 4, 8 */
100 #define ABS_MIN_FREQ_2595 1000 /* 10.00 MHz (really 10.697) */
101 #define N_ADJ_2595 257
103 #define STOP_BITS_2595 0x1800
106 #define MIN_N_408 2
108 #define MIN_N_1703 6
110 #define MIN_M 2
111 #define MAX_M 30
112 #define MIN_N 35
113 #define MAX_N 255-8
116 /* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */
117 /* - must be large enough to catch all GUI-Regs */
118 /* - must be aligned to a PAGE boundary */
119 #define GUI_RESERVE (1 * PAGE_SIZE)
122 #ifndef __powerpc__
123 #define eieio() /* Enforce In-order Execution of I/O */
124 #endif
126 /* FIXME: remove the FAIL definition */
127 #define FAIL(x) do { printk(x "\n"); return -EINVAL; } while (0)
131 * Elements of the Hardware specific atyfb_par structure
134 struct crtc {
135 u32 vxres;
136 u32 vyres;
137 u32 xoffset;
138 u32 yoffset;
139 u32 bpp;
140 u32 h_tot_disp;
141 u32 h_sync_strt_wid;
142 u32 v_tot_disp;
143 u32 v_sync_strt_wid;
144 u32 off_pitch;
145 u32 gen_cntl;
146 u32 dp_pix_width; /* acceleration */
147 u32 dp_chain_mask; /* acceleration */
150 struct pll_gx {
151 u8 m;
152 u8 n;
155 struct pll_18818
157 u32 program_bits;
158 u32 locationAddr;
159 u32 period_in_ps;
160 u32 post_divider;
163 struct pll_ct {
164 u8 pll_ref_div;
165 u8 pll_gen_cntl;
166 u8 mclk_fb_div;
167 u8 pll_vclk_cntl;
168 u8 vclk_post_div;
169 u8 vclk_fb_div;
170 u8 pll_ext_cntl;
171 u32 dsp_config; /* Mach64 GTB DSP */
172 u32 dsp_on_off; /* Mach64 GTB DSP */
173 u8 mclk_post_div_real;
174 u8 vclk_post_div_real;
179 * The Hardware parameters for each card
182 struct atyfb_par {
183 struct crtc crtc;
184 union {
185 struct pll_gx gx;
186 struct pll_ct ct;
187 struct pll_18818 ics2595;
188 } pll;
189 u32 accel_flags;
192 struct aty_cmap_regs {
193 u8 windex;
194 u8 lut;
195 u8 mask;
196 u8 rindex;
197 u8 cntl;
200 struct pci_mmap_map {
201 unsigned long voff;
202 unsigned long poff;
203 unsigned long size;
204 unsigned long prot_flag;
205 unsigned long prot_mask;
208 #define DEFAULT_CURSOR_BLINK_RATE (20)
209 #define CURSOR_DRAW_DELAY (2)
211 struct aty_cursor {
212 int enable;
213 int on;
214 int vbl_cnt;
215 int blink_rate;
216 u32 offset;
217 struct {
218 u16 x, y;
219 } pos, hot, size;
220 u32 color[2];
221 u8 bits[8][64];
222 u8 mask[8][64];
223 u8 *ram;
224 struct timer_list *timer;
227 struct fb_info_aty {
228 struct fb_info fb_info;
229 struct fb_info_aty *next;
230 unsigned long ati_regbase_phys;
231 unsigned long ati_regbase;
232 unsigned long frame_buffer_phys;
233 unsigned long frame_buffer;
234 unsigned long clk_wr_offset;
235 struct pci_mmap_map *mmap_map;
236 struct aty_cursor *cursor;
237 struct aty_cmap_regs *aty_cmap_regs;
238 struct { u8 red, green, blue, pad; } palette[256];
239 struct atyfb_par default_par;
240 struct atyfb_par current_par;
241 u32 total_vram;
242 u32 ref_clk_per;
243 u32 pll_per;
244 u32 mclk_per;
245 u16 chip_type;
246 #define Gx info->chip_type
247 u8 chip_rev;
248 #define Rev info->chip_rev
249 u8 bus_type;
250 u8 ram_type;
251 u8 dac_type;
252 u8 dac_subtype;
253 u8 clk_type;
254 u8 mem_refresh_rate;
255 struct display disp;
256 struct display_switch dispsw;
257 union {
258 #ifdef FBCON_HAS_CFB16
259 u16 cfb16[16];
260 #endif
261 #ifdef FBCON_HAS_CFB24
262 u32 cfb24[16];
263 #endif
264 #ifdef FBCON_HAS_CFB32
265 u32 cfb32[16];
266 #endif
267 } fbcon_cmap;
268 u8 blitter_may_be_busy;
269 #ifdef __sparc__
270 u8 open;
271 u8 mmaped;
272 int vtconsole;
273 int consolecnt;
274 #endif
279 * Frame buffer device API
282 static int atyfb_open(struct fb_info *info, int user);
283 static int atyfb_release(struct fb_info *info, int user);
284 static int atyfb_get_fix(struct fb_fix_screeninfo *fix, int con,
285 struct fb_info *fb);
286 static int atyfb_get_var(struct fb_var_screeninfo *var, int con,
287 struct fb_info *fb);
288 static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
289 struct fb_info *fb);
290 static int atyfb_pan_display(struct fb_var_screeninfo *var, int con,
291 struct fb_info *fb);
292 static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
293 struct fb_info *info);
294 static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
295 struct fb_info *info);
296 static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
297 u_long arg, int con, struct fb_info *info);
298 #ifdef __sparc__
299 static int atyfb_mmap(struct fb_info *info, struct file *file,
300 struct vm_area_struct *vma);
301 #endif
302 static int atyfb_rasterimg(struct fb_info *info, int start);
306 * Interface to the low level console driver
309 static int atyfbcon_switch(int con, struct fb_info *fb);
310 static int atyfbcon_updatevar(int con, struct fb_info *fb);
311 static void atyfbcon_blank(int blank, struct fb_info *fb);
315 * Text console acceleration
318 static void fbcon_aty_bmove(struct display *p, int sy, int sx, int dy, int dx,
319 int height, int width);
320 static void fbcon_aty_clear(struct vc_data *conp, struct display *p, int sy,
321 int sx, int height, int width);
322 #ifdef FBCON_HAS_CFB8
323 static struct display_switch fbcon_aty8;
324 static void fbcon_aty8_putc(struct vc_data *conp, struct display *p, int c,
325 int yy, int xx);
326 static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p,
327 const unsigned short *s, int count, int yy,
328 int xx);
329 #endif
330 #ifdef FBCON_HAS_CFB16
331 static struct display_switch fbcon_aty16;
332 static void fbcon_aty16_putc(struct vc_data *conp, struct display *p, int c,
333 int yy, int xx);
334 static void fbcon_aty16_putcs(struct vc_data *conp, struct display *p,
335 const unsigned short *s, int count, int yy,
336 int xx);
337 #endif
338 #ifdef FBCON_HAS_CFB24
339 static struct display_switch fbcon_aty24;
340 static void fbcon_aty24_putc(struct vc_data *conp, struct display *p, int c,
341 int yy, int xx);
342 static void fbcon_aty24_putcs(struct vc_data *conp, struct display *p,
343 const unsigned short *s, int count, int yy,
344 int xx);
345 #endif
346 #ifdef FBCON_HAS_CFB32
347 static struct display_switch fbcon_aty32;
348 static void fbcon_aty32_putc(struct vc_data *conp, struct display *p, int c,
349 int yy, int xx);
350 static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p,
351 const unsigned short *s, int count, int yy,
352 int xx);
353 #endif
357 * Internal routines
360 static int aty_init(struct fb_info_aty *info, const char *name);
361 static struct aty_cursor *aty_init_cursor(struct fb_info_aty *fb);
362 #ifdef CONFIG_ATARI
363 static int store_video_par(char *videopar, unsigned char m64_num);
364 static char *strtoke(char *s, const char *ct);
365 #endif
367 static void reset_engine(const struct fb_info_aty *info);
368 static void init_engine(const struct atyfb_par *par, struct fb_info_aty *info);
370 static void aty_st_514(int offset, u8 val, const struct fb_info_aty *info);
371 static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info);
372 static u8 aty_ld_pll(int offset, const struct fb_info_aty *info);
373 static void aty_set_crtc(const struct fb_info_aty *info,
374 const struct crtc *crtc);
375 static int aty_var_to_crtc(const struct fb_info_aty *info,
376 const struct fb_var_screeninfo *var,
377 struct crtc *crtc);
378 static void aty_set_dac_514(const struct fb_info_aty *info, u32 bpp);
379 static int aty_crtc_to_var(const struct crtc *crtc,
380 struct fb_var_screeninfo *var);
381 static void aty_set_pll_gx(const struct fb_info_aty *info,
382 const struct pll_gx *pll);
384 static int aty_set_dac_ATI68860_B(const struct fb_info_aty *info, u32 bpp,
385 u32 AccelMode);
386 static int aty_set_dac_ATT21C498(const struct fb_info_aty *info,
387 const struct pll_18818 *pll, u32 bpp);
388 void aty_dac_waste4(const struct fb_info_aty *info);
390 static int aty_var_to_pll_18818(u32 period_in_ps, struct pll_18818 *pll);
391 static u32 aty_pll_18818_to_var(const struct pll_18818 *pll);
392 static void aty_set_pll18818(const struct fb_info_aty *info,
393 const struct pll_18818 *pll);
395 static void aty_StrobeClock(const struct fb_info_aty *info);
397 static void aty_ICS2595_put1bit(u8 data, const struct fb_info_aty *info);
399 static int aty_var_to_pll_408(u32 period_in_ps, struct pll_18818 *pll);
400 static u32 aty_pll_408_to_var(const struct pll_18818 *pll);
401 static void aty_set_pll_408(const struct fb_info_aty *info,
402 const struct pll_18818 *pll);
404 static int aty_var_to_pll_1703(u32 period_in_ps, struct pll_18818 *pll);
405 static u32 aty_pll_1703_to_var(const struct pll_18818 *pll);
406 static void aty_set_pll_1703(const struct fb_info_aty *info,
407 const struct pll_18818 *pll);
409 static int aty_var_to_pll_8398(u32 period_in_ps, struct pll_18818 *pll);
410 static u32 aty_pll_8398_to_var(const struct pll_18818 *pll);
411 static void aty_set_pll_8398(const struct fb_info_aty *info,
412 const struct pll_18818 *pll);
414 static int aty_var_to_pll_514(u32 vclk_per, struct pll_gx *pll);
415 static u32 aty_pll_gx_to_var(const struct pll_gx *pll,
416 const struct fb_info_aty *info);
417 static void aty_set_pll_ct(const struct fb_info_aty *info,
418 const struct pll_ct *pll);
419 static int aty_valid_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
420 struct pll_ct *pll);
421 static int aty_dsp_gt(const struct fb_info_aty *info, u8 bpp,
422 struct pll_ct *pll);
423 static void aty_calc_pll_ct(const struct fb_info_aty *info,
424 struct pll_ct *pll);
425 static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
426 u8 bpp, struct pll_ct *pll);
427 static u32 aty_pll_ct_to_var(const struct pll_ct *pll,
428 const struct fb_info_aty *info);
429 static void atyfb_set_par(const struct atyfb_par *par,
430 struct fb_info_aty *info);
431 static int atyfb_decode_var(const struct fb_var_screeninfo *var,
432 struct atyfb_par *par,
433 const struct fb_info_aty *info);
434 static int atyfb_encode_var(struct fb_var_screeninfo *var,
435 const struct atyfb_par *par,
436 const struct fb_info_aty *info);
437 static void set_off_pitch(struct atyfb_par *par,
438 const struct fb_info_aty *info);
439 static int encode_fix(struct fb_fix_screeninfo *fix,
440 const struct atyfb_par *par,
441 const struct fb_info_aty *info);
442 static void atyfb_set_disp(struct display *disp, struct fb_info_aty *info,
443 int bpp, int accel);
444 static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
445 u_int *transp, struct fb_info *fb);
446 static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
447 u_int transp, struct fb_info *fb);
448 static void do_install_cmap(int con, struct fb_info *info);
449 #if defined(CONFIG_PPC)
450 static int read_aty_sense(const struct fb_info_aty *info);
451 #endif
455 * Interface used by the world
458 int atyfb_init(void);
459 #ifdef CONFIG_FB_OF
460 void atyfb_of_init(struct device_node *dp);
461 #endif
462 #ifndef MODULE
463 int atyfb_setup(char*);
464 #endif
466 static int currcon = 0;
468 static struct fb_ops atyfb_ops = {
469 atyfb_open, atyfb_release, atyfb_get_fix, atyfb_get_var, atyfb_set_var,
470 atyfb_get_cmap, atyfb_set_cmap, atyfb_pan_display, atyfb_ioctl,
471 #ifdef __sparc__
472 atyfb_mmap,
473 #else
474 NULL,
475 #endif
476 atyfb_rasterimg
479 static char atyfb_name[16] = "ATY Mach64";
480 static char fontname[40] __initdata = { 0 };
481 static char curblink __initdata = 1;
482 static char noaccel __initdata = 0;
483 static u32 default_vram __initdata = 0;
484 static int default_pll __initdata = 0;
485 static int default_mclk __initdata = 0;
487 #ifndef MODULE
488 static const char *mode_option __initdata = NULL;
489 #endif
491 #if defined(CONFIG_PPC)
492 static int default_vmode __initdata = VMODE_NVRAM;
493 static int default_cmode __initdata = CMODE_NVRAM;
494 #endif
496 #ifdef CONFIG_ATARI
497 static unsigned int mach64_count __initdata = 0;
498 static unsigned long phys_vmembase[FB_MAX] __initdata = { 0, };
499 static unsigned long phys_size[FB_MAX] __initdata = { 0, };
500 static unsigned long phys_guiregbase[FB_MAX] __initdata = { 0, };
501 #endif
504 static struct aty_features {
505 u16 pci_id;
506 u16 chip_type;
507 const char *name;
508 } aty_features[] __initdata = {
509 /* mach64GX family */
510 { 0x4758, 0x00d7, "mach64GX (ATI888GX00)" },
511 { 0x4358, 0x0057, "mach64CX (ATI888CX00)" },
513 /* mach64CT family */
514 { 0x4354, 0x4354, "mach64CT (ATI264CT)" },
515 { 0x4554, 0x4554, "mach64ET (ATI264ET)" },
517 /* mach64CT family / mach64VT class */
518 { 0x5654, 0x5654, "mach64VT (ATI264VT)" },
519 { 0x5655, 0x5655, "mach64VTB (ATI264VTB)" },
520 { 0x5656, 0x5656, "mach64VT4 (ATI264VT4)" },
522 /* mach64CT family / mach64GT (3D RAGE) class */
523 { 0x4c42, 0x4c42, "3D RAGE LT PRO (AGP)" },
524 { 0x4c44, 0x4c44, "3D RAGE LT PRO" },
525 { 0x4c47, 0x4c47, "3D RAGE LT PRO" },
526 { 0x4c49, 0x4c49, "3D RAGE LT PRO" },
527 { 0x4c50, 0x4c50, "3D RAGE LT PRO" },
528 { 0x4c54, 0x4c54, "3D RAGE LT" },
529 { 0x4754, 0x4754, "3D RAGE (GT)" },
530 { 0x4755, 0x4755, "3D RAGE II+ (GTB)" },
531 { 0x4756, 0x4756, "3D RAGE IIC (PCI)" },
532 { 0x4757, 0x4757, "3D RAGE IIC (AGP)" },
533 { 0x475a, 0x475a, "3D RAGE IIC (AGP)" },
534 { 0x4742, 0x4742, "3D RAGE PRO (BGA, AGP)" },
535 { 0x4744, 0x4744, "3D RAGE PRO (BGA, AGP, 1x only)" },
536 { 0x4749, 0x4749, "3D RAGE PRO (BGA, PCI)" },
537 { 0x4750, 0x4750, "3D RAGE PRO (PQFP, PCI)" },
538 { 0x4751, 0x4751, "3D RAGE PRO (PQFP, PCI, limited 3D)" },
541 static const char *aty_gx_ram[8] __initdata = {
542 "DRAM", "VRAM", "VRAM", "DRAM", "DRAM", "VRAM", "VRAM", "RESV"
545 static const char *aty_ct_ram[8] __initdata = {
546 "OFF", "DRAM", "EDO", "EDO", "SDRAM", "SGRAM", "WRAM", "RESV"
550 static inline u32 aty_ld_le32(unsigned int regindex,
551 const struct fb_info_aty *info)
553 unsigned long temp;
554 u32 val;
556 #if defined(__powerpc__)
557 temp = info->ati_regbase;
558 asm volatile("lwbrx %0,%1,%2" : "=r"(val) : "b" (regindex), "r" (temp));
559 #elif defined(__sparc_v9__)
560 temp = info->ati_regbase + regindex;
561 val = readl(temp);
562 #else
563 temp = info->ati_regbase+regindex;
564 val = le32_to_cpu(*((volatile u32 *)(temp)));
565 #endif
566 return val;
569 static inline void aty_st_le32(unsigned int regindex, u32 val,
570 const struct fb_info_aty *info)
572 unsigned long temp;
574 #if defined(__powerpc__)
575 temp = info->ati_regbase;
576 asm volatile("stwbrx %0,%1,%2" : : "r" (val), "b" (regindex), "r" (temp) :
577 "memory");
578 #elif defined(__sparc_v9__)
579 temp = info->ati_regbase + regindex;
580 writel(val, temp);
581 #else
582 temp = info->ati_regbase+regindex;
583 *((volatile u32 *)(temp)) = cpu_to_le32(val);
584 #endif
587 static inline u8 aty_ld_8(unsigned int regindex,
588 const struct fb_info_aty *info)
590 #ifdef __sparc_v9__
591 return readb(info->ati_regbase + regindex);
592 #else
593 return *(volatile u8 *)(info->ati_regbase+regindex);
594 #endif
597 static inline void aty_st_8(unsigned int regindex, u8 val,
598 const struct fb_info_aty *info)
600 #ifdef __sparc_v9__
601 writeb(val, info->ati_regbase + regindex);
602 #else
603 *(volatile u8 *)(info->ati_regbase+regindex) = val;
604 #endif
609 * Generic Mach64 routines
613 * All writes to draw engine registers are automatically routed through a
614 * 32-bit-wide, 16-entry-deep command FIFO ...
615 * Register writes to registers with DWORD offsets less than 40h are not
616 * FIFOed.
617 * (from Chapter 5 of the Mach64 Programmer's Guide)
620 static inline void wait_for_fifo(u16 entries, const struct fb_info_aty *info)
622 while ((aty_ld_le32(FIFO_STAT, info) & 0xffff) >
623 ((u32)(0x8000 >> entries)));
626 static inline void wait_for_idle(struct fb_info_aty *info)
628 wait_for_fifo(16, info);
629 while ((aty_ld_le32(GUI_STAT, info) & 1)!= 0);
630 info->blitter_may_be_busy = 0;
633 static void reset_engine(const struct fb_info_aty *info)
635 /* reset engine */
636 aty_st_le32(GEN_TEST_CNTL,
637 aty_ld_le32(GEN_TEST_CNTL, info) & ~GUI_ENGINE_ENABLE, info);
638 /* enable engine */
639 aty_st_le32(GEN_TEST_CNTL,
640 aty_ld_le32(GEN_TEST_CNTL, info) | GUI_ENGINE_ENABLE, info);
641 /* ensure engine is not locked up by clearing any FIFO or */
642 /* HOST errors */
643 aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, info) | BUS_HOST_ERR_ACK |
644 BUS_FIFO_ERR_ACK, info);
647 static void init_engine(const struct atyfb_par *par, struct fb_info_aty *info)
649 u32 pitch_value;
651 /* determine modal information from global mode structure */
652 pitch_value = par->crtc.vxres;
654 if (par->crtc.bpp == 24) {
655 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
656 /* horizontal coordinates and widths must be adjusted */
657 pitch_value = pitch_value * 3;
660 /* Reset engine, enable, and clear any engine errors */
661 reset_engine(info);
662 /* Ensure that vga page pointers are set to zero - the upper */
663 /* page pointers are set to 1 to handle overflows in the */
664 /* lower page */
665 aty_st_le32(MEM_VGA_WP_SEL, 0x00010000, info);
666 aty_st_le32(MEM_VGA_RP_SEL, 0x00010000, info);
668 /* ---- Setup standard engine context ---- */
670 /* All GUI registers here are FIFOed - therefore, wait for */
671 /* the appropriate number of empty FIFO entries */
672 wait_for_fifo(14, info);
674 /* enable all registers to be loaded for context loads */
675 aty_st_le32(CONTEXT_MASK, 0xFFFFFFFF, info);
677 /* set destination pitch to modal pitch, set offset to zero */
678 aty_st_le32(DST_OFF_PITCH, (pitch_value / 8) << 22, info);
680 /* zero these registers (set them to a known state) */
681 aty_st_le32(DST_Y_X, 0, info);
682 aty_st_le32(DST_HEIGHT, 0, info);
683 aty_st_le32(DST_BRES_ERR, 0, info);
684 aty_st_le32(DST_BRES_INC, 0, info);
685 aty_st_le32(DST_BRES_DEC, 0, info);
687 /* set destination drawing attributes */
688 aty_st_le32(DST_CNTL, DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM |
689 DST_X_LEFT_TO_RIGHT, info);
691 /* set source pitch to modal pitch, set offset to zero */
692 aty_st_le32(SRC_OFF_PITCH, (pitch_value / 8) << 22, info);
694 /* set these registers to a known state */
695 aty_st_le32(SRC_Y_X, 0, info);
696 aty_st_le32(SRC_HEIGHT1_WIDTH1, 1, info);
697 aty_st_le32(SRC_Y_X_START, 0, info);
698 aty_st_le32(SRC_HEIGHT2_WIDTH2, 1, info);
700 /* set source pixel retrieving attributes */
701 aty_st_le32(SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT, info);
703 /* set host attributes */
704 wait_for_fifo(13, info);
705 aty_st_le32(HOST_CNTL, 0, info);
707 /* set pattern attributes */
708 aty_st_le32(PAT_REG0, 0, info);
709 aty_st_le32(PAT_REG1, 0, info);
710 aty_st_le32(PAT_CNTL, 0, info);
712 /* set scissors to modal size */
713 aty_st_le32(SC_LEFT, 0, info);
714 aty_st_le32(SC_TOP, 0, info);
715 aty_st_le32(SC_BOTTOM, par->crtc.vyres-1, info);
716 aty_st_le32(SC_RIGHT, pitch_value-1, info);
718 /* set background color to minimum value (usually BLACK) */
719 aty_st_le32(DP_BKGD_CLR, 0, info);
721 /* set foreground color to maximum value (usually WHITE) */
722 aty_st_le32(DP_FRGD_CLR, 0xFFFFFFFF, info);
724 /* set write mask to effect all pixel bits */
725 aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF, info);
727 /* set foreground mix to overpaint and background mix to */
728 /* no-effect */
729 aty_st_le32(DP_MIX, FRGD_MIX_S | BKGD_MIX_D, info);
731 /* set primary source pixel channel to foreground color */
732 /* register */
733 aty_st_le32(DP_SRC, FRGD_SRC_FRGD_CLR, info);
735 /* set compare functionality to false (no-effect on */
736 /* destination) */
737 wait_for_fifo(3, info);
738 aty_st_le32(CLR_CMP_CLR, 0, info);
739 aty_st_le32(CLR_CMP_MASK, 0xFFFFFFFF, info);
740 aty_st_le32(CLR_CMP_CNTL, 0, info);
742 /* set pixel depth */
743 wait_for_fifo(2, info);
744 aty_st_le32(DP_PIX_WIDTH, par->crtc.dp_pix_width, info);
745 aty_st_le32(DP_CHAIN_MASK, par->crtc.dp_chain_mask, info);
747 wait_for_fifo(5, info);
748 aty_st_le32(SCALE_3D_CNTL, 0, info);
749 aty_st_le32(Z_CNTL, 0, info);
750 aty_st_le32(CRTC_INT_CNTL, aty_ld_le32(CRTC_INT_CNTL, info) & ~0x20, info);
751 aty_st_le32(GUI_TRAJ_CNTL, 0x100023, info);
753 /* insure engine is idle before leaving */
754 wait_for_idle(info);
757 static void aty_st_514(int offset, u8 val, const struct fb_info_aty *info)
759 aty_st_8(DAC_CNTL, 1, info);
760 /* right addr byte */
761 aty_st_8(DAC_W_INDEX, offset & 0xff, info);
762 /* left addr byte */
763 aty_st_8(DAC_DATA, (offset >> 8) & 0xff, info);
764 eieio();
765 aty_st_8(DAC_MASK, val, info);
766 eieio();
767 aty_st_8(DAC_CNTL, 0, info);
770 static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info)
772 /* write addr byte */
773 aty_st_8(CLOCK_CNTL + 1, (offset << 2) | PLL_WR_EN, info);
774 eieio();
775 /* write the register value */
776 aty_st_8(CLOCK_CNTL + 2, val, info);
777 eieio();
778 aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, info);
781 static u8 aty_ld_pll(int offset, const struct fb_info_aty *info)
783 u8 res;
785 /* write addr byte */
786 aty_st_8(CLOCK_CNTL + 1, (offset << 2), info);
787 eieio();
788 /* read the register value */
789 res = aty_ld_8(CLOCK_CNTL + 2, info);
790 eieio();
791 return res;
794 #if defined(CONFIG_PPC)
797 * Apple monitor sense
800 static int read_aty_sense(const struct fb_info_aty *info)
802 int sense, i;
804 aty_st_le32(GP_IO, 0x31003100, info); /* drive outputs high */
805 __delay(200);
806 aty_st_le32(GP_IO, 0, info); /* turn off outputs */
807 __delay(2000);
808 i = aty_ld_le32(GP_IO, info); /* get primary sense value */
809 sense = ((i & 0x3000) >> 3) | (i & 0x100);
811 /* drive each sense line low in turn and collect the other 2 */
812 aty_st_le32(GP_IO, 0x20000000, info); /* drive A low */
813 __delay(2000);
814 i = aty_ld_le32(GP_IO, info);
815 sense |= ((i & 0x1000) >> 7) | ((i & 0x100) >> 4);
816 aty_st_le32(GP_IO, 0x20002000, info); /* drive A high again */
817 __delay(200);
819 aty_st_le32(GP_IO, 0x10000000, info); /* drive B low */
820 __delay(2000);
821 i = aty_ld_le32(GP_IO, info);
822 sense |= ((i & 0x2000) >> 10) | ((i & 0x100) >> 6);
823 aty_st_le32(GP_IO, 0x10001000, info); /* drive B high again */
824 __delay(200);
826 aty_st_le32(GP_IO, 0x01000000, info); /* drive C low */
827 __delay(2000);
828 sense |= (aty_ld_le32(GP_IO, info) & 0x3000) >> 12;
829 aty_st_le32(GP_IO, 0, info); /* turn off outputs */
831 return sense;
834 #endif /* defined(CONFIG_PPC) */
836 /* ------------------------------------------------------------------------- */
839 * Hardware Cursor support.
842 static u8 cursor_pixel_map[2] = { 0, 15 };
843 static u8 cursor_color_map[2] = { 0, 0xff };
845 static u8 cursor_bits_lookup[16] =
847 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
848 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
851 static u8 cursor_mask_lookup[16] =
853 0xaa, 0x2a, 0x8a, 0x0a, 0xa2, 0x22, 0x82, 0x02,
854 0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00
857 static void
858 aty_set_cursor_color(struct fb_info_aty *fb, u8 *pixel,
859 u8 *red, u8 *green, u8 *blue)
861 struct aty_cursor *c = fb->cursor;
862 int i;
864 if (!c)
865 return;
867 #ifdef __sparc__
868 if (fb->mmaped && (!fb->fb_info.display_fg
869 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
870 return;
871 #endif
873 for (i = 0; i < 2; i++) {
874 c->color[i] = (u32)red[i] << 24;
875 c->color[i] |= (u32)green[i] << 16;
876 c->color[i] |= (u32)blue[i] << 8;
877 c->color[i] |= (u32)pixel[i];
880 wait_for_fifo(2, fb);
881 aty_st_le32(CUR_CLR0, c->color[0], fb);
882 aty_st_le32(CUR_CLR1, c->color[1], fb);
885 static void
886 aty_set_cursor_shape(struct fb_info_aty *fb)
888 struct aty_cursor *c = fb->cursor;
889 u8 *ram, m, b;
890 int x, y;
892 if (!c)
893 return;
895 #ifdef __sparc__
896 if (fb->mmaped && (!fb->fb_info.display_fg
897 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
898 return;
899 #endif
901 ram = c->ram;
902 for (y = 0; y < c->size.y; y++) {
903 for (x = 0; x < c->size.x >> 2; x++) {
904 m = c->mask[x][y];
905 b = c->bits[x][y];
906 *ram++ = cursor_mask_lookup[m >> 4] |
907 cursor_bits_lookup[(b & m) >> 4];
908 *ram++ = cursor_mask_lookup[m & 0x0f] |
909 cursor_bits_lookup[(b & m) & 0x0f];
911 for ( ; x < 8; x++) {
912 *ram++ = 0xaa;
913 *ram++ = 0xaa;
916 memset(ram, 0xaa, (64 - c->size.y) * 16);
919 static void
920 aty_set_cursor(struct fb_info_aty *fb, int on)
922 struct atyfb_par *par = &fb->current_par;
923 struct aty_cursor *c = fb->cursor;
924 u16 xoff, yoff;
925 int x, y;
927 if (!c)
928 return;
930 #ifdef __sparc__
931 if (fb->mmaped && (!fb->fb_info.display_fg
932 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
933 return;
934 #endif
936 if (on) {
937 x = c->pos.x - c->hot.x - par->crtc.xoffset;
938 if (x < 0) {
939 xoff = -x;
940 x = 0;
941 } else {
942 xoff = 0;
945 y = c->pos.y - c->hot.y - par->crtc.yoffset;
946 if (y < 0) {
947 yoff = -y;
948 y = 0;
949 } else {
950 yoff = 0;
953 wait_for_fifo(4, fb);
954 aty_st_le32(CUR_OFFSET, (c->offset >> 3) + (yoff << 1), fb);
955 aty_st_le32(CUR_HORZ_VERT_OFF,
956 ((u32)(64 - c->size.y + yoff) << 16) | xoff, fb);
957 aty_st_le32(CUR_HORZ_VERT_POSN, ((u32)y << 16) | x, fb);
958 aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, fb)
959 | HWCURSOR_ENABLE, fb);
960 } else {
961 wait_for_fifo(1, fb);
962 aty_st_le32(GEN_TEST_CNTL,
963 aty_ld_le32(GEN_TEST_CNTL, fb) & ~HWCURSOR_ENABLE,
964 fb);
966 if (fb->blitter_may_be_busy)
967 wait_for_idle(fb);
970 static void
971 aty_cursor_timer_handler(unsigned long dev_addr)
973 struct fb_info_aty *fb = (struct fb_info_aty *)dev_addr;
975 if (!fb->cursor)
976 return;
978 if (!fb->cursor->enable)
979 goto out;
981 if (fb->cursor->vbl_cnt && --fb->cursor->vbl_cnt == 0) {
982 fb->cursor->on ^= 1;
983 aty_set_cursor(fb, fb->cursor->on);
984 fb->cursor->vbl_cnt = fb->cursor->blink_rate;
987 out:
988 fb->cursor->timer->expires = jiffies + (HZ / 50);
989 add_timer(fb->cursor->timer);
992 static void
993 atyfb_cursor(struct display *p, int mode, int x, int y)
995 struct fb_info_aty *fb = (struct fb_info_aty *)p->fb_info;
996 struct aty_cursor *c = fb->cursor;
998 if (!c)
999 return;
1001 #ifdef __sparc__
1002 if (fb->mmaped && (!fb->fb_info.display_fg
1003 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
1004 return;
1005 #endif
1007 x *= fontwidth(p);
1008 y *= fontheight(p);
1009 if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->enable)
1010 return;
1012 c->enable = 0;
1013 if (c->on)
1014 aty_set_cursor(fb, 0);
1015 c->pos.x = x;
1016 c->pos.y = y;
1018 switch (mode) {
1019 case CM_ERASE:
1020 c->on = 0;
1021 break;
1023 case CM_DRAW:
1024 case CM_MOVE:
1025 if (c->on)
1026 aty_set_cursor(fb, 1);
1027 else
1028 c->vbl_cnt = CURSOR_DRAW_DELAY;
1029 c->enable = 1;
1030 break;
1034 static struct fb_info_aty *fb_list = NULL;
1036 static struct aty_cursor * __init
1037 aty_init_cursor(struct fb_info_aty *fb)
1039 struct aty_cursor *cursor;
1040 unsigned long addr;
1042 cursor = kmalloc(sizeof(struct aty_cursor), GFP_ATOMIC);
1043 if (!cursor)
1044 return 0;
1045 memset(cursor, 0, sizeof(*cursor));
1047 cursor->timer = kmalloc(sizeof(*cursor->timer), GFP_KERNEL);
1048 if (!cursor->timer) {
1049 kfree(cursor);
1050 return 0;
1052 memset(cursor->timer, 0, sizeof(*cursor->timer));
1054 cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE;
1055 fb->total_vram -= PAGE_SIZE;
1056 cursor->offset = fb->total_vram;
1058 #ifdef __sparc__
1059 addr = fb->frame_buffer - 0x800000 + cursor->offset;
1060 cursor->ram = (u8 *)addr;
1061 #else
1062 #ifdef __BIG_ENDIAN
1063 addr = fb->frame_buffer_phys - 0x800000 + cursor->offset;
1064 cursor->ram = (u8 *)ioremap(addr, 1024);
1065 #else
1066 addr = fb->frame_buffer + cursor->offset;
1067 cursor->ram = (u8 *)addr;
1068 #endif
1069 #endif
1071 if (! cursor->ram) {
1072 kfree(cursor);
1073 return NULL;
1076 if (curblink) {
1077 init_timer(cursor->timer);
1078 cursor->timer->expires = jiffies + (HZ / 50);
1079 cursor->timer->data = (unsigned long)fb;
1080 cursor->timer->function = aty_cursor_timer_handler;
1081 add_timer(cursor->timer);
1084 return cursor;
1087 static int
1088 atyfb_set_font(struct display *d, int width, int height)
1090 struct fb_info_aty *fb = (struct fb_info_aty *)d->fb_info;
1091 struct aty_cursor *c = fb->cursor;
1092 int i, j;
1094 if (c) {
1095 if (!width || !height) {
1096 width = 8;
1097 height = 16;
1100 c->hot.x = 0;
1101 c->hot.y = 0;
1102 c->size.x = width;
1103 c->size.y = height;
1105 memset(c->bits, 0xff, sizeof(c->bits));
1106 memset(c->mask, 0, sizeof(c->mask));
1108 for (i = 0, j = width; j >= 0; j -= 8, i++) {
1109 c->mask[i][height-2] = (j >= 8) ? 0xff : (0xff << (8 - j));
1110 c->mask[i][height-1] = (j >= 8) ? 0xff : (0xff << (8 - j));
1113 aty_set_cursor_color(fb, cursor_pixel_map, cursor_color_map,
1114 cursor_color_map, cursor_color_map);
1115 aty_set_cursor_shape(fb);
1117 return 1;
1123 /* ------------------------------------------------------------------------- */
1126 * CRTC programming
1129 static void aty_set_crtc(const struct fb_info_aty *info,
1130 const struct crtc *crtc)
1132 aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, info);
1133 aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, info);
1134 aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_tot_disp, info);
1135 aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid, info);
1136 aty_st_le32(CRTC_VLINE_CRNT_VLINE, 0, info);
1137 aty_st_le32(CRTC_OFF_PITCH, crtc->off_pitch, info);
1138 aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl, info);
1141 static int aty_var_to_crtc(const struct fb_info_aty *info,
1142 const struct fb_var_screeninfo *var,
1143 struct crtc *crtc)
1145 u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
1146 u32 left, right, upper, lower, hslen, vslen, sync, vmode;
1147 u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
1148 u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
1149 u32 pix_width, dp_pix_width, dp_chain_mask;
1151 /* input */
1152 xres = var->xres;
1153 yres = var->yres;
1154 vxres = var->xres_virtual;
1155 vyres = var->yres_virtual;
1156 xoffset = var->xoffset;
1157 yoffset = var->yoffset;
1158 bpp = var->bits_per_pixel;
1159 left = var->left_margin;
1160 right = var->right_margin;
1161 upper = var->upper_margin;
1162 lower = var->lower_margin;
1163 hslen = var->hsync_len;
1164 vslen = var->vsync_len;
1165 sync = var->sync;
1166 vmode = var->vmode;
1168 /* convert (and round up) and validate */
1169 xres = (xres+7) & ~7;
1170 xoffset = (xoffset+7) & ~7;
1171 vxres = (vxres+7) & ~7;
1172 if (vxres < xres+xoffset)
1173 vxres = xres+xoffset;
1174 h_disp = xres/8-1;
1175 if (h_disp > 0xff)
1176 FAIL("h_disp too large");
1177 h_sync_strt = h_disp+(right/8);
1178 if (h_sync_strt > 0x1ff)
1179 FAIL("h_sync_start too large");
1180 h_sync_dly = right & 7;
1181 h_sync_wid = (hslen+7)/8;
1182 if (h_sync_wid > 0x1f)
1183 FAIL("h_sync_wid too large");
1184 h_total = h_sync_strt+h_sync_wid+(h_sync_dly+left+7)/8;
1185 if (h_total > 0x1ff)
1186 FAIL("h_total too large");
1187 h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
1189 if (vyres < yres+yoffset)
1190 vyres = yres+yoffset;
1191 v_disp = yres-1;
1192 if (v_disp > 0x7ff)
1193 FAIL("v_disp too large");
1194 v_sync_strt = v_disp+lower;
1195 if (v_sync_strt > 0x7ff)
1196 FAIL("v_sync_strt too large");
1197 v_sync_wid = vslen;
1198 if (v_sync_wid > 0x1f)
1199 FAIL("v_sync_wid too large");
1200 v_total = v_sync_strt+v_sync_wid+upper;
1201 if (v_total > 0x7ff)
1202 FAIL("v_total too large");
1203 v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
1205 c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;
1207 if (bpp <= 8) {
1208 bpp = 8;
1209 pix_width = CRTC_PIX_WIDTH_8BPP;
1210 dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB;
1211 dp_chain_mask = 0x8080;
1212 } else if (bpp <= 16) {
1213 bpp = 16;
1214 pix_width = CRTC_PIX_WIDTH_15BPP;
1215 dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP |
1216 BYTE_ORDER_LSB_TO_MSB;
1217 dp_chain_mask = 0x4210;
1218 } else if ((bpp <= 24) && (Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
1219 bpp = 24;
1220 pix_width = CRTC_PIX_WIDTH_24BPP;
1221 dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB;
1222 dp_chain_mask = 0x8080;
1223 } else if (bpp <= 32) {
1224 bpp = 32;
1225 pix_width = CRTC_PIX_WIDTH_32BPP;
1226 dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP |
1227 BYTE_ORDER_LSB_TO_MSB;
1228 dp_chain_mask = 0x8080;
1229 } else
1230 FAIL("invalid bpp");
1232 if (vxres*vyres*bpp/8 > info->total_vram)
1233 FAIL("not enough video RAM");
1235 if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
1236 FAIL("invalid vmode");
1238 /* output */
1239 crtc->vxres = vxres;
1240 crtc->vyres = vyres;
1241 crtc->xoffset = xoffset;
1242 crtc->yoffset = yoffset;
1243 crtc->bpp = bpp;
1244 crtc->h_tot_disp = h_total | (h_disp<<16);
1245 crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly<<8) |
1246 ((h_sync_strt & 0x100)<<4) | (h_sync_wid<<16) |
1247 (h_sync_pol<<21);
1248 crtc->v_tot_disp = v_total | (v_disp<<16);
1249 crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid<<16) | (v_sync_pol<<21);
1250 crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19);
1251 crtc->gen_cntl = pix_width | c_sync | CRTC_EXT_DISP_EN | CRTC_ENABLE;
1252 if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID) ||
1253 ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07))) {
1254 /* Not VTB/GTB */
1255 /* FIXME: magic FIFO values */
1256 crtc->gen_cntl |= aty_ld_le32(CRTC_GEN_CNTL, info) & 0x000e0000;
1258 crtc->dp_pix_width = dp_pix_width;
1259 crtc->dp_chain_mask = dp_chain_mask;
1261 return 0;
1265 static int aty_set_dac_ATI68860_B(const struct fb_info_aty *info, u32 bpp,
1266 u32 AccelMode)
1268 u32 gModeReg, devSetupRegA, temp, mask;
1270 gModeReg = 0;
1271 devSetupRegA = 0;
1273 switch (bpp) {
1274 case 8:
1275 gModeReg = 0x83;
1276 devSetupRegA = 0x60 | 0x00 /*(info->mach64DAC8Bit ? 0x00 : 0x01) */;
1277 break;
1278 case 15:
1279 gModeReg = 0xA0;
1280 devSetupRegA = 0x60;
1281 break;
1282 case 16:
1283 gModeReg = 0xA1;
1284 devSetupRegA = 0x60;
1285 break;
1286 case 24:
1287 gModeReg = 0xC0;
1288 devSetupRegA = 0x60;
1289 break;
1290 case 32:
1291 gModeReg = 0xE3;
1292 devSetupRegA = 0x60;
1293 break;
1296 if (!AccelMode) {
1297 gModeReg = 0x80;
1298 devSetupRegA = 0x61;
1301 temp = aty_ld_8(DAC_CNTL, info);
1302 aty_st_8(DAC_CNTL, (temp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3, info);
1304 aty_st_8(DAC_REGS + 2, 0x1D, info);
1305 aty_st_8(DAC_REGS + 3, gModeReg, info);
1306 aty_st_8(DAC_REGS, 0x02, info);
1308 temp = aty_ld_8(DAC_CNTL, info);
1309 aty_st_8(DAC_CNTL, temp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, info);
1311 if (info->total_vram < MEM_SIZE_1M)
1312 mask = 0x04;
1313 else if (info->total_vram == MEM_SIZE_1M)
1314 mask = 0x08;
1315 else
1316 mask = 0x0C;
1318 /* The following assumes that the BIOS has correctly set R7 of the
1319 * Device Setup Register A at boot time.
1321 #define A860_DELAY_L 0x80
1323 temp = aty_ld_8(DAC_REGS, info);
1324 aty_st_8(DAC_REGS, (devSetupRegA | mask) | (temp & A860_DELAY_L), info);
1325 temp = aty_ld_8(DAC_CNTL, info);
1326 aty_st_8(DAC_CNTL, (temp & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3)), info);
1328 return 0;
1331 static int aty_set_dac_ATT21C498(const struct fb_info_aty *info,
1332 const struct pll_18818 *pll, u32 bpp)
1334 u32 dotClock;
1335 int muxmode = 0;
1336 int DACMask = 0;
1338 dotClock = 100000000 / pll->period_in_ps;
1340 switch (bpp) {
1341 case 8:
1342 if (dotClock > 8000) {
1343 DACMask = 0x24;
1344 muxmode = 1;
1345 } else
1346 DACMask = 0x04;
1347 break;
1348 case 15:
1349 DACMask = 0x16;
1350 break;
1351 case 16:
1352 DACMask = 0x36;
1353 break;
1354 case 24:
1355 DACMask = 0xE6;
1356 break;
1357 case 32:
1358 DACMask = 0xE6;
1359 break;
1362 if (1 /* info->mach64DAC8Bit */)
1363 DACMask |= 0x02;
1365 aty_dac_waste4(info);
1366 aty_st_8(DAC_REGS + 2, DACMask, info);
1368 return muxmode;
1371 void aty_dac_waste4(const struct fb_info_aty *info)
1373 (void)aty_ld_8(DAC_REGS, info);
1375 (void)aty_ld_8(DAC_REGS + 2, info);
1376 (void)aty_ld_8(DAC_REGS + 2, info);
1377 (void)aty_ld_8(DAC_REGS + 2, info);
1378 (void)aty_ld_8(DAC_REGS + 2, info);
1382 static void aty_set_dac_514(const struct fb_info_aty *info, u32 bpp)
1384 static struct {
1385 u8 pixel_dly;
1386 u8 misc2_cntl;
1387 u8 pixel_rep;
1388 u8 pixel_cntl_index;
1389 u8 pixel_cntl_v1;
1390 } tab[3] = {
1391 { 0, 0x41, 0x03, 0x71, 0x45 }, /* 8 bpp */
1392 { 0, 0x45, 0x04, 0x0c, 0x01 }, /* 555 */
1393 { 0, 0x45, 0x06, 0x0e, 0x00 }, /* XRGB */
1395 int i;
1397 switch (bpp) {
1398 case 8:
1399 default:
1400 i = 0;
1401 break;
1402 case 16:
1403 i = 1;
1404 break;
1405 case 32:
1406 i = 2;
1407 break;
1409 aty_st_514(0x90, 0x00, info); /* VRAM Mask Low */
1410 aty_st_514(0x04, tab[i].pixel_dly, info); /* Horizontal Sync Control */
1411 aty_st_514(0x05, 0x00, info); /* Power Management */
1412 aty_st_514(0x02, 0x01, info); /* Misc Clock Control */
1413 aty_st_514(0x71, tab[i].misc2_cntl, info); /* Misc Control 2 */
1414 aty_st_514(0x0a, tab[i].pixel_rep, info); /* Pixel Format */
1415 aty_st_514(tab[i].pixel_cntl_index, tab[i].pixel_cntl_v1, info);
1416 /* Misc Control 2 / 16 BPP Control / 32 BPP Control */
1419 static int aty_crtc_to_var(const struct crtc *crtc,
1420 struct fb_var_screeninfo *var)
1422 u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync;
1423 u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
1424 u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
1425 u32 pix_width;
1427 /* input */
1428 h_total = crtc->h_tot_disp & 0x1ff;
1429 h_disp = (crtc->h_tot_disp>>16) & 0xff;
1430 h_sync_strt = (crtc->h_sync_strt_wid & 0xff) |
1431 ((crtc->h_sync_strt_wid>>4) & 0x100);
1432 h_sync_dly = (crtc->h_sync_strt_wid>>8) & 0x7;
1433 h_sync_wid = (crtc->h_sync_strt_wid>>16) & 0x1f;
1434 h_sync_pol = (crtc->h_sync_strt_wid>>21) & 0x1;
1435 v_total = crtc->v_tot_disp & 0x7ff;
1436 v_disp = (crtc->v_tot_disp>>16) & 0x7ff;
1437 v_sync_strt = crtc->v_sync_strt_wid & 0x7ff;
1438 v_sync_wid = (crtc->v_sync_strt_wid>>16) & 0x1f;
1439 v_sync_pol = (crtc->v_sync_strt_wid>>21) & 0x1;
1440 c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
1441 pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
1443 /* convert */
1444 xres = (h_disp+1)*8;
1445 yres = v_disp+1;
1446 left = (h_total-h_sync_strt-h_sync_wid)*8-h_sync_dly;
1447 right = (h_sync_strt-h_disp)*8+h_sync_dly;
1448 hslen = h_sync_wid*8;
1449 upper = v_total-v_sync_strt-v_sync_wid;
1450 lower = v_sync_strt-v_disp;
1451 vslen = v_sync_wid;
1452 sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) |
1453 (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
1454 (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
1456 switch (pix_width) {
1457 #if 0
1458 case CRTC_PIX_WIDTH_4BPP:
1459 bpp = 4;
1460 var->red.offset = 0;
1461 var->red.length = 8;
1462 var->green.offset = 0;
1463 var->green.length = 8;
1464 var->blue.offset = 0;
1465 var->blue.length = 8;
1466 var->transp.offset = 0;
1467 var->transp.length = 0;
1468 break;
1469 #endif
1470 case CRTC_PIX_WIDTH_8BPP:
1471 bpp = 8;
1472 var->red.offset = 0;
1473 var->red.length = 8;
1474 var->green.offset = 0;
1475 var->green.length = 8;
1476 var->blue.offset = 0;
1477 var->blue.length = 8;
1478 var->transp.offset = 0;
1479 var->transp.length = 0;
1480 break;
1481 case CRTC_PIX_WIDTH_15BPP: /* RGB 555 */
1482 bpp = 16;
1483 var->red.offset = 10;
1484 var->red.length = 5;
1485 var->green.offset = 5;
1486 var->green.length = 5;
1487 var->blue.offset = 0;
1488 var->blue.length = 5;
1489 var->transp.offset = 0;
1490 var->transp.length = 0;
1491 break;
1492 #if 0
1493 case CRTC_PIX_WIDTH_16BPP: /* RGB 565 */
1494 bpp = 16;
1495 var->red.offset = 11;
1496 var->red.length = 5;
1497 var->green.offset = 5;
1498 var->green.length = 6;
1499 var->blue.offset = 0;
1500 var->blue.length = 5;
1501 var->transp.offset = 0;
1502 var->transp.length = 0;
1503 break;
1504 #endif
1505 case CRTC_PIX_WIDTH_24BPP: /* RGB 888 */
1506 bpp = 24;
1507 var->red.offset = 16;
1508 var->red.length = 8;
1509 var->green.offset = 8;
1510 var->green.length = 8;
1511 var->blue.offset = 0;
1512 var->blue.length = 8;
1513 var->transp.offset = 0;
1514 var->transp.length = 0;
1515 break;
1516 case CRTC_PIX_WIDTH_32BPP: /* ARGB 8888 */
1517 bpp = 32;
1518 var->red.offset = 16;
1519 var->red.length = 8;
1520 var->green.offset = 8;
1521 var->green.length = 8;
1522 var->blue.offset = 0;
1523 var->blue.length = 8;
1524 var->transp.offset = 24;
1525 var->transp.length = 8;
1526 break;
1527 default:
1528 FAIL("Invalid pixel width");
1531 /* output */
1532 var->xres = xres;
1533 var->yres = yres;
1534 var->xres_virtual = crtc->vxres;
1535 var->yres_virtual = crtc->vyres;
1536 var->bits_per_pixel = bpp;
1537 var->xoffset = crtc->xoffset;
1538 var->yoffset = crtc->yoffset;
1539 var->left_margin = left;
1540 var->right_margin = right;
1541 var->upper_margin = upper;
1542 var->lower_margin = lower;
1543 var->hsync_len = hslen;
1544 var->vsync_len = vslen;
1545 var->sync = sync;
1546 var->vmode = FB_VMODE_NONINTERLACED;
1548 return 0;
1551 /* ------------------------------------------------------------------------- */
1554 * PLL programming (Mach64 GX family)
1556 * FIXME: use function pointer tables instead of switch statements
1559 static void aty_set_pll_gx(const struct fb_info_aty *info,
1560 const struct pll_gx *pll)
1562 switch (info->clk_type) {
1563 case CLK_ATI18818_1:
1564 aty_st_8(CLOCK_CNTL, pll->m, info);
1565 break;
1566 case CLK_IBMRGB514:
1567 aty_st_514(0x06, 0x02, info); /* DAC Operation */
1568 aty_st_514(0x10, 0x01, info); /* PLL Control 1 */
1569 aty_st_514(0x70, 0x01, info); /* Misc Control 1 */
1570 aty_st_514(0x8f, 0x1f, info); /* PLL Ref. Divider Input */
1571 aty_st_514(0x03, 0x00, info); /* Sync Control */
1572 aty_st_514(0x05, 0x00, info); /* Power Management */
1573 aty_st_514(0x20, pll->m, info); /* F0 / M0 */
1574 aty_st_514(0x21, pll->n, info); /* F1 / N0 */
1575 break;
1580 static int aty_var_to_pll_18818(u32 period_in_ps, struct pll_18818 *pll)
1582 u32 MHz100; /* in 0.01 MHz */
1583 u32 program_bits;
1584 u32 post_divider;
1586 /* Calculate the programming word */
1587 MHz100 = 100000000 / period_in_ps;
1589 program_bits = -1;
1590 post_divider = 1;
1592 if (MHz100 > MAX_FREQ_2595) {
1593 MHz100 = MAX_FREQ_2595;
1594 return -EINVAL;
1595 } else if (MHz100 < ABS_MIN_FREQ_2595) {
1596 program_bits = 0; /* MHz100 = 257 */
1597 return -EINVAL;
1598 } else {
1599 while (MHz100 < MIN_FREQ_2595) {
1600 MHz100 *= 2;
1601 post_divider *= 2;
1604 MHz100 *= 1000;
1605 MHz100 = (REF_DIV_2595 * MHz100) / REF_FREQ_2595;
1607 MHz100 += 500; /* + 0.5 round */
1608 MHz100 /= 1000;
1610 if (program_bits == -1) {
1611 program_bits = MHz100 - N_ADJ_2595;
1612 switch (post_divider) {
1613 case 1:
1614 program_bits |= 0x0600;
1615 break;
1616 case 2:
1617 program_bits |= 0x0400;
1618 break;
1619 case 4:
1620 program_bits |= 0x0200;
1621 break;
1622 case 8:
1623 default:
1624 break;
1628 program_bits |= STOP_BITS_2595;
1630 pll->program_bits = program_bits;
1631 pll->locationAddr = 0;
1632 pll->post_divider = post_divider;
1633 pll->period_in_ps = period_in_ps;
1635 return 0;
1638 static u32 aty_pll_18818_to_var(const struct pll_18818 *pll)
1640 return(pll->period_in_ps); /* default for now */
1643 static void aty_set_pll18818(const struct fb_info_aty *info,
1644 const struct pll_18818 *pll)
1646 u32 program_bits;
1647 u32 locationAddr;
1649 u32 i;
1651 u8 old_clock_cntl;
1652 u8 old_crtc_ext_disp;
1654 old_clock_cntl = aty_ld_8(CLOCK_CNTL, info);
1655 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info);
1657 old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
1658 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24),
1659 info);
1661 udelay(15000); /* delay for 50 (15) ms */
1663 program_bits = pll->program_bits;
1664 locationAddr = pll->locationAddr;
1666 /* Program the clock chip */
1667 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info); /* Strobe = 0 */
1668 aty_StrobeClock(info);
1669 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 1, info); /* Strobe = 0 */
1670 aty_StrobeClock(info);
1672 aty_ICS2595_put1bit(1, info); /* Send start bits */
1673 aty_ICS2595_put1bit(0, info); /* Start bit */
1674 aty_ICS2595_put1bit(0, info); /* Read / ~Write */
1676 for (i = 0; i < 5; i++) { /* Location 0..4 */
1677 aty_ICS2595_put1bit(locationAddr & 1, info);
1678 locationAddr >>= 1;
1681 for (i = 0; i < 8 + 1 + 2 + 2; i++) {
1682 aty_ICS2595_put1bit(program_bits & 1, info);
1683 program_bits >>= 1;
1686 udelay(1000); /* delay for 1 ms */
1688 (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */
1689 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info);
1690 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, old_clock_cntl | CLOCK_STROBE,
1691 info);
1693 udelay(50000); /* delay for 50 (15) ms */
1694 aty_st_8(CLOCK_CNTL + info->clk_wr_offset,
1695 ((pll->locationAddr & 0x0F) | CLOCK_STROBE), info);
1697 return;
1701 static int aty_var_to_pll_408(u32 period_in_ps, struct pll_18818 *pll)
1703 u32 mhz100; /* in 0.01 MHz */
1704 u32 program_bits;
1705 /* u32 post_divider; */
1706 u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
1707 u32 temp, tempB;
1708 u16 remainder, preRemainder;
1709 short divider = 0, tempA;
1711 /* Calculate the programming word */
1712 mhz100 = 100000000 / period_in_ps;
1713 mach64MinFreq = MIN_FREQ_2595;
1714 mach64MaxFreq = MAX_FREQ_2595;
1715 mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */
1717 /* Calculate program word */
1718 if (mhz100 == 0)
1719 program_bits = 0xFF;
1720 else {
1721 if (mhz100 < mach64MinFreq)
1722 mhz100 = mach64MinFreq;
1723 if (mhz100 > mach64MaxFreq)
1724 mhz100 = mach64MaxFreq;
1726 while (mhz100 < (mach64MinFreq << 3)) {
1727 mhz100 <<= 1;
1728 divider += 0x40;
1731 temp = (unsigned int)mhz100;
1732 temp = (unsigned int)(temp * (MIN_N_408 + 2));
1733 temp -= ((short)(mach64RefFreq << 1));
1735 tempA = MIN_N_408;
1736 preRemainder = 0xFFFF;
1738 do {
1739 tempB = temp;
1740 remainder = tempB % mach64RefFreq;
1741 tempB = tempB / mach64RefFreq;
1742 if (((tempB & 0xFFFF) <= 255) && (remainder <= preRemainder)) {
1743 preRemainder = remainder;
1744 divider &= ~0x3f;
1745 divider |= tempA;
1746 divider = (divider & 0x00FF) + ((tempB & 0xFF) << 8);
1748 temp += mhz100;
1749 tempA++;
1750 } while(tempA <= 32);
1752 program_bits = divider;
1755 pll->program_bits = program_bits;
1756 pll->locationAddr = 0;
1757 pll->post_divider = divider; /* fuer nix */
1758 pll->period_in_ps = period_in_ps;
1760 return 0;
1763 static u32 aty_pll_408_to_var(const struct pll_18818 *pll)
1765 return(pll->period_in_ps); /* default for now */
1768 static void aty_set_pll_408(const struct fb_info_aty *info,
1769 const struct pll_18818 *pll)
1771 u32 program_bits;
1772 u32 locationAddr;
1774 u8 tmpA, tmpB, tmpC;
1775 char old_crtc_ext_disp;
1777 old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
1778 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24),
1779 info);
1781 program_bits = pll->program_bits;
1782 locationAddr = pll->locationAddr;
1784 /* Program clock */
1785 aty_dac_waste4(info);
1786 tmpB = aty_ld_8(DAC_REGS + 2, info) | 1;
1787 aty_dac_waste4(info);
1788 aty_st_8(DAC_REGS + 2, tmpB, info);
1790 tmpA = tmpB;
1791 tmpC = tmpA;
1792 tmpA |= 8;
1793 tmpB = 1;
1795 aty_st_8(DAC_REGS, tmpB, info);
1796 aty_st_8(DAC_REGS + 2, tmpA, info);
1798 udelay(400); /* delay for 400 us */
1800 locationAddr = (locationAddr << 2) + 0x40;
1801 tmpB = locationAddr;
1802 tmpA = program_bits >> 8;
1804 aty_st_8(DAC_REGS, tmpB, info);
1805 aty_st_8(DAC_REGS + 2, tmpA, info);
1807 tmpB = locationAddr + 1;
1808 tmpA = (u8)program_bits;
1810 aty_st_8(DAC_REGS, tmpB, info);
1811 aty_st_8(DAC_REGS + 2, tmpA, info);
1813 tmpB = locationAddr + 2;
1814 tmpA = 0x77;
1816 aty_st_8(DAC_REGS, tmpB, info);
1817 aty_st_8(DAC_REGS + 2, tmpA, info);
1819 udelay(400); /* delay for 400 us */
1820 tmpA = tmpC & (~(1 | 8));
1821 tmpB = 1;
1823 aty_st_8(DAC_REGS, tmpB, info);
1824 aty_st_8(DAC_REGS + 2, tmpA, info);
1826 (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */
1827 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info);
1829 return;
1833 static int aty_var_to_pll_1703(u32 period_in_ps, struct pll_18818 *pll)
1835 u32 mhz100; /* in 0.01 MHz */
1836 u32 program_bits;
1837 /* u32 post_divider; */
1838 u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
1839 u32 temp, tempB;
1840 u16 remainder, preRemainder;
1841 short divider = 0, tempA;
1843 /* Calculate the programming word */
1844 mhz100 = 100000000 / period_in_ps;
1845 mach64MinFreq = MIN_FREQ_2595;
1846 mach64MaxFreq = MAX_FREQ_2595;
1847 mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */
1849 /* Calculate program word */
1850 if (mhz100 == 0)
1851 program_bits = 0xE0;
1852 else {
1853 if (mhz100 < mach64MinFreq)
1854 mhz100 = mach64MinFreq;
1855 if (mhz100 > mach64MaxFreq)
1856 mhz100 = mach64MaxFreq;
1858 divider = 0;
1859 while (mhz100 < (mach64MinFreq << 3)) {
1860 mhz100 <<= 1;
1861 divider += 0x20;
1864 temp = (unsigned int)(mhz100);
1865 temp = (unsigned int)(temp * (MIN_N_1703 + 2));
1866 temp -= (short)(mach64RefFreq << 1);
1868 tempA = MIN_N_1703;
1869 preRemainder = 0xffff;
1871 do {
1872 tempB = temp;
1873 remainder = tempB % mach64RefFreq;
1874 tempB = tempB / mach64RefFreq;
1876 if ((tempB & 0xffff) <= 127 && (remainder <= preRemainder)) {
1877 preRemainder = remainder;
1878 divider &= ~0x1f;
1879 divider |= tempA;
1880 divider = (divider & 0x00ff) + ((tempB & 0xff) << 8);
1883 temp += mhz100;
1884 tempA++;
1885 } while (tempA <= (MIN_N_1703 << 1));
1887 program_bits = divider;
1890 pll->program_bits = program_bits;
1891 pll->locationAddr = 0;
1892 pll->post_divider = divider; /* fuer nix */
1893 pll->period_in_ps = period_in_ps;
1895 return 0;
1898 static u32 aty_pll_1703_to_var(const struct pll_18818 *pll)
1900 return(pll->period_in_ps); /* default for now */
1903 static void aty_set_pll_1703(const struct fb_info_aty *info,
1904 const struct pll_18818 *pll)
1906 u32 program_bits;
1907 u32 locationAddr;
1909 char old_crtc_ext_disp;
1911 old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
1912 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24),
1913 info);
1915 program_bits = pll->program_bits;
1916 locationAddr = pll->locationAddr;
1918 /* Program clock */
1919 aty_dac_waste4(info);
1921 (void)aty_ld_8(DAC_REGS + 2, info);
1922 aty_st_8(DAC_REGS+2, (locationAddr << 1) + 0x20, info);
1923 aty_st_8(DAC_REGS+2, 0, info);
1924 aty_st_8(DAC_REGS+2, (program_bits & 0xFF00) >> 8, info);
1925 aty_st_8(DAC_REGS+2, (program_bits & 0xFF), info);
1927 (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */
1928 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info);
1930 return;
1934 static int aty_var_to_pll_8398(u32 period_in_ps, struct pll_18818 *pll)
1937 u32 tempA, tempB, fOut, longMHz100, diff, preDiff;
1939 u32 mhz100; /* in 0.01 MHz */
1940 u32 program_bits;
1941 /* u32 post_divider; */
1942 u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
1943 u16 m, n, k=0, save_m, save_n, twoToKth;
1945 /* Calculate the programming word */
1946 mhz100 = 100000000 / period_in_ps;
1947 mach64MinFreq = MIN_FREQ_2595;
1948 mach64MaxFreq = MAX_FREQ_2595;
1949 mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */
1951 save_m = 0;
1952 save_n = 0;
1954 /* Calculate program word */
1955 if (mhz100 == 0)
1956 program_bits = 0xE0;
1957 else
1959 if (mhz100 < mach64MinFreq)
1960 mhz100 = mach64MinFreq;
1961 if (mhz100 > mach64MaxFreq)
1962 mhz100 = mach64MaxFreq;
1964 longMHz100 = mhz100 * 256 / 100; /* 8 bit scale this */
1966 while (mhz100 < (mach64MinFreq << 3))
1968 mhz100 <<= 1;
1969 k++;
1972 twoToKth = 1 << k;
1973 diff = 0;
1974 preDiff = 0xFFFFFFFF;
1976 for (m = MIN_M; m <= MAX_M; m++)
1978 for (n = MIN_N; n <= MAX_N; n++)
1980 tempA = (14.31818 * 65536);
1981 tempA *= (n + 8); /* 43..256 */
1982 tempB = twoToKth * 256;
1983 tempB *= (m + 2); /* 4..32 */
1984 fOut = tempA / tempB; /* 8 bit scale */
1986 if (longMHz100 > fOut)
1987 diff = longMHz100 - fOut;
1988 else
1989 diff = fOut - longMHz100;
1991 if (diff < preDiff)
1993 save_m = m;
1994 save_n = n;
1995 preDiff = diff;
2000 program_bits = (k << 6) + (save_m) + (save_n << 8);
2003 pll->program_bits = program_bits;
2004 pll->locationAddr = 0;
2005 pll->post_divider = 0;
2006 pll->period_in_ps = period_in_ps;
2008 return 0;
2011 static u32 aty_pll_8398_to_var(const struct pll_18818 *pll)
2013 return(pll->period_in_ps); /* default for now */
2016 static void aty_set_pll_8398(const struct fb_info_aty *info,
2017 const struct pll_18818 *pll)
2019 u32 program_bits;
2020 u32 locationAddr;
2022 char old_crtc_ext_disp;
2023 char tmp;
2025 old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
2026 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24),
2027 info);
2029 program_bits = pll->program_bits;
2030 locationAddr = pll->locationAddr;
2032 /* Program clock */
2033 tmp = aty_ld_8(DAC_CNTL, info);
2034 aty_st_8(DAC_CNTL, tmp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, info);
2036 aty_st_8(DAC_REGS, locationAddr, info);
2037 aty_st_8(DAC_REGS+1, (program_bits & 0xff00) >> 8, info);
2038 aty_st_8(DAC_REGS+1, (program_bits & 0xff), info);
2040 tmp = aty_ld_8(DAC_CNTL, info);
2041 aty_st_8(DAC_CNTL, (tmp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3, info);
2043 (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */
2044 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info);
2046 return;
2050 static int aty_var_to_pll_514(u32 vclk_per, struct pll_gx *pll)
2053 * FIXME: use real calculations instead of using fixed values from the old
2054 * driver
2056 static struct {
2057 u32 limit; /* pixlock rounding limit (arbitrary) */
2058 u8 m; /* (df<<6) | vco_div_count */
2059 u8 n; /* ref_div_count */
2060 } RGB514_clocks[7] = {
2061 { 8000, (3<<6) | 20, 9 }, /* 7395 ps / 135.2273 MHz */
2062 { 10000, (1<<6) | 19, 3 }, /* 9977 ps / 100.2273 MHz */
2063 { 13000, (1<<6) | 2, 3 }, /* 12509 ps / 79.9432 MHz */
2064 { 14000, (2<<6) | 8, 7 }, /* 13394 ps / 74.6591 MHz */
2065 { 16000, (1<<6) | 44, 6 }, /* 15378 ps / 65.0284 MHz */
2066 { 25000, (1<<6) | 15, 5 }, /* 17460 ps / 57.2727 MHz */
2067 { 50000, (0<<6) | 53, 7 }, /* 33145 ps / 30.1705 MHz */
2069 int i;
2071 for (i = 0; i < sizeof(RGB514_clocks)/sizeof(*RGB514_clocks); i++)
2072 if (vclk_per <= RGB514_clocks[i].limit) {
2073 pll->m = RGB514_clocks[i].m;
2074 pll->n = RGB514_clocks[i].n;
2075 return 0;
2077 return -EINVAL;
2081 static void aty_StrobeClock(const struct fb_info_aty *info)
2083 u8 tmp;
2085 udelay(26);
2087 tmp = aty_ld_8(CLOCK_CNTL, info);
2088 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, tmp | CLOCK_STROBE, info);
2090 return;
2094 static void aty_ICS2595_put1bit(u8 data, const struct fb_info_aty *info)
2096 u8 tmp;
2098 data &= 0x01;
2099 tmp = aty_ld_8(CLOCK_CNTL, info);
2100 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, (tmp & ~0x04) | (data << 2),
2101 info);
2103 tmp = aty_ld_8(CLOCK_CNTL, info);
2104 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, (tmp & ~0x08) | (0 << 3), info);
2106 aty_StrobeClock(info);
2108 tmp = aty_ld_8(CLOCK_CNTL, info);
2109 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, (tmp & ~0x08) | (1 << 3), info);
2111 aty_StrobeClock(info);
2113 return;
2117 static u32 aty_pll_gx_to_var(const struct pll_gx *pll,
2118 const struct fb_info_aty *info)
2120 u8 df, vco_div_count, ref_div_count;
2122 df = pll->m >> 6;
2123 vco_div_count = pll->m & 0x3f;
2124 ref_div_count = pll->n;
2126 return ((info->ref_clk_per*ref_div_count)<<(3-df))/(vco_div_count+65);
2131 * PLL programming (Mach64 CT family)
2134 static void aty_set_pll_ct(const struct fb_info_aty *info,
2135 const struct pll_ct *pll)
2137 aty_st_pll(PLL_REF_DIV, pll->pll_ref_div, info);
2138 aty_st_pll(PLL_GEN_CNTL, pll->pll_gen_cntl, info);
2139 aty_st_pll(MCLK_FB_DIV, pll->mclk_fb_div, info);
2140 aty_st_pll(PLL_VCLK_CNTL, pll->pll_vclk_cntl, info);
2141 aty_st_pll(VCLK_POST_DIV, pll->vclk_post_div, info);
2142 aty_st_pll(VCLK0_FB_DIV, pll->vclk_fb_div, info);
2143 aty_st_pll(PLL_EXT_CNTL, pll->pll_ext_cntl, info);
2145 if (!(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
2146 Gx == ET_CHIP_ID ||
2147 ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07)))) {
2148 if (info->ram_type >= SDRAM)
2149 aty_st_pll(DLL_CNTL, 0xa6, info);
2150 else
2151 aty_st_pll(DLL_CNTL, 0xa0, info);
2152 aty_st_pll(VFC_CNTL, 0x1b, info);
2153 aty_st_le32(DSP_CONFIG, pll->dsp_config, info);
2154 aty_st_le32(DSP_ON_OFF, pll->dsp_on_off, info);
2158 static int aty_dsp_gt(const struct fb_info_aty *info, u8 bpp,
2159 struct pll_ct *pll)
2161 u32 dsp_xclks_per_row, dsp_loop_latency, dsp_precision, dsp_off, dsp_on;
2162 u32 xclks_per_row, fifo_off, fifo_on, y, fifo_size, page_size;
2164 /* xclocks_per_row<<11 */
2165 xclks_per_row = (pll->mclk_fb_div*pll->vclk_post_div_real*64<<11)/
2166 (pll->vclk_fb_div*pll->mclk_post_div_real*bpp);
2167 if (xclks_per_row < (1<<11))
2168 FAIL("Dotclock to high");
2169 if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == VT_CHIP_ID ||
2170 Gx == VU_CHIP_ID || Gx == GV_CHIP_ID || Gx == GW_CHIP_ID ||
2171 Gx == GZ_CHIP_ID) {
2172 fifo_size = 24;
2173 dsp_loop_latency = 0;
2174 } else {
2175 fifo_size = 32;
2176 dsp_loop_latency = 2;
2178 dsp_precision = 0;
2179 y = (xclks_per_row*fifo_size)>>11;
2180 while (y) {
2181 y >>= 1;
2182 dsp_precision++;
2184 dsp_precision -= 5;
2185 /* fifo_off<<6 */
2186 fifo_off = ((xclks_per_row*(fifo_size-1))>>5)+(1<<6);
2188 if (info->total_vram > 1*1024*1024) {
2189 if (info->ram_type >= SDRAM) {
2190 /* >1 MB SDRAM */
2191 dsp_loop_latency += 8;
2192 page_size = 8;
2193 } else {
2194 /* >1 MB DRAM */
2195 dsp_loop_latency += 6;
2196 page_size = 9;
2198 } else {
2199 if (info->ram_type >= SDRAM) {
2200 /* <2 MB SDRAM */
2201 dsp_loop_latency += 9;
2202 page_size = 10;
2203 } else {
2204 /* <2 MB DRAM */
2205 dsp_loop_latency += 8;
2206 page_size = 10;
2209 /* fifo_on<<6 */
2210 if (xclks_per_row >= (page_size<<11))
2211 fifo_on = ((2*page_size+1)<<6)+(xclks_per_row>>5);
2212 else
2213 fifo_on = (3*page_size)<<6;
2215 dsp_xclks_per_row = xclks_per_row>>dsp_precision;
2216 dsp_on = fifo_on>>dsp_precision;
2217 dsp_off = fifo_off>>dsp_precision;
2219 pll->dsp_config = (dsp_xclks_per_row & 0x3fff) |
2220 ((dsp_loop_latency & 0xf)<<16) |
2221 ((dsp_precision & 7)<<20);
2222 pll->dsp_on_off = (dsp_on & 0x7ff) | ((dsp_off & 0x7ff)<<16);
2223 return 0;
2226 static int aty_valid_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
2227 struct pll_ct *pll)
2229 u32 q, x; /* x is a workaround for sparc64-linux-gcc */
2230 x = x; /* x is a workaround for sparc64-linux-gcc */
2232 pll->pll_ref_div = info->pll_per*2*255/info->ref_clk_per;
2234 /* FIXME: use the VTB/GTB /3 post divider if it's better suited */
2235 q = info->ref_clk_per*pll->pll_ref_div*4/info->mclk_per; /* actually 8*q */
2236 if (q < 16*8 || q > 255*8)
2237 FAIL("mclk out of range");
2238 else if (q < 32*8)
2239 pll->mclk_post_div_real = 8;
2240 else if (q < 64*8)
2241 pll->mclk_post_div_real = 4;
2242 else if (q < 128*8)
2243 pll->mclk_post_div_real = 2;
2244 else
2245 pll->mclk_post_div_real = 1;
2246 pll->mclk_fb_div = q*pll->mclk_post_div_real/8;
2248 /* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
2249 q = info->ref_clk_per*pll->pll_ref_div*4/vclk_per; /* actually 8*q */
2250 if (q < 16*8 || q > 255*8)
2251 FAIL("vclk out of range");
2252 else if (q < 32*8)
2253 pll->vclk_post_div_real = 8;
2254 else if (q < 64*8)
2255 pll->vclk_post_div_real = 4;
2256 else if (q < 128*8)
2257 pll->vclk_post_div_real = 2;
2258 else
2259 pll->vclk_post_div_real = 1;
2260 pll->vclk_fb_div = q*pll->vclk_post_div_real/8;
2261 return 0;
2264 static void aty_calc_pll_ct(const struct fb_info_aty *info, struct pll_ct *pll)
2266 u8 mpostdiv = 0;
2267 u8 vpostdiv = 0;
2269 if ((((Gx == GT_CHIP_ID) && (Rev & 0x03)) || (Gx == GU_CHIP_ID) ||
2270 (Gx == GV_CHIP_ID) || (Gx == GW_CHIP_ID) || (Gx == GZ_CHIP_ID) ||
2271 (Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) ||
2272 (Gx == GI_CHIP_ID) || (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID) ||
2273 (Gx == VU_CHIP_ID)) && (info->ram_type >= SDRAM))
2274 pll->pll_gen_cntl = 0x04;
2275 else
2276 pll->pll_gen_cntl = 0x84;
2278 switch (pll->mclk_post_div_real) {
2279 case 1:
2280 mpostdiv = 0;
2281 break;
2282 case 2:
2283 mpostdiv = 1;
2284 break;
2285 case 3:
2286 mpostdiv = 4;
2287 break;
2288 case 4:
2289 mpostdiv = 2;
2290 break;
2291 case 8:
2292 mpostdiv = 3;
2293 break;
2295 pll->pll_gen_cntl |= mpostdiv<<4; /* mclk */
2297 if (Gx == VT_CHIP_ID && (Rev == 0x40 || Rev == 0x48))
2298 pll->pll_ext_cntl = 0;
2299 else
2300 pll->pll_ext_cntl = mpostdiv; /* xclk == mclk */
2302 switch (pll->vclk_post_div_real) {
2303 case 2:
2304 vpostdiv = 1;
2305 break;
2306 case 3:
2307 pll->pll_ext_cntl |= 0x10;
2308 case 1:
2309 vpostdiv = 0;
2310 break;
2311 case 6:
2312 pll->pll_ext_cntl |= 0x10;
2313 case 4:
2314 vpostdiv = 2;
2315 break;
2316 case 12:
2317 pll->pll_ext_cntl |= 0x10;
2318 case 8:
2319 vpostdiv = 3;
2320 break;
2323 pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */
2324 pll->vclk_post_div = vpostdiv;
2327 static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
2328 u8 bpp, struct pll_ct *pll)
2330 int err;
2332 if ((err = aty_valid_pll_ct(info, vclk_per, pll)))
2333 return err;
2334 if (!(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
2335 Gx == ET_CHIP_ID ||
2336 ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07)))) {
2337 if ((err = aty_dsp_gt(info, bpp, pll)))
2338 return err;
2340 aty_calc_pll_ct(info, pll);
2341 return 0;
2344 static u32 aty_pll_ct_to_var(const struct pll_ct *pll,
2345 const struct fb_info_aty *info)
2347 u32 ref_clk_per = info->ref_clk_per;
2348 u8 pll_ref_div = pll->pll_ref_div;
2349 u8 vclk_fb_div = pll->vclk_fb_div;
2350 u8 vclk_post_div = pll->vclk_post_div_real;
2352 return ref_clk_per*pll_ref_div*vclk_post_div/vclk_fb_div/2;
2355 /* ------------------------------------------------------------------------- */
2357 static void atyfb_set_par(const struct atyfb_par *par,
2358 struct fb_info_aty *info)
2360 u32 i;
2361 int accelmode;
2362 int muxmode;
2363 u8 tmp;
2365 accelmode = par->accel_flags; /* hack */
2367 info->current_par = *par;
2369 if (info->blitter_may_be_busy)
2370 wait_for_idle(info);
2371 tmp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
2372 aty_set_crtc(info, &par->crtc);
2373 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info);
2374 /* better call aty_StrobeClock ?? */
2375 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, CLOCK_STROBE, info);
2377 if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID)) {
2378 switch (info->dac_subtype) {
2379 case DAC_IBMRGB514:
2380 aty_set_dac_514(info, par->crtc.bpp);
2381 break;
2382 case DAC_ATI68860_B:
2383 case DAC_ATI68860_C:
2384 muxmode = aty_set_dac_ATI68860_B(info, par->crtc.bpp,
2385 accelmode);
2386 aty_st_le32(BUS_CNTL, 0x890e20f1, info);
2387 aty_st_le32(DAC_CNTL, 0x47052100, info);
2388 break;
2389 case DAC_ATT20C408:
2390 muxmode = aty_set_dac_ATT21C498(info, &par->pll.ics2595,
2391 par->crtc.bpp);
2392 aty_st_le32(BUS_CNTL, 0x890e20f1, info);
2393 aty_st_le32(DAC_CNTL, 0x00072000, info);
2394 break;
2395 case DAC_ATT21C498:
2396 muxmode = aty_set_dac_ATT21C498(info, &par->pll.ics2595,
2397 par->crtc.bpp);
2398 aty_st_le32(BUS_CNTL, 0x890e20f1, info);
2399 aty_st_le32(DAC_CNTL, 0x00072000, info);
2400 break;
2401 default:
2402 printk(" atyfb_set_par: DAC type not implemented yet!\n");
2403 aty_st_le32(BUS_CNTL, 0x890e20f1, info);
2404 aty_st_le32(DAC_CNTL, 0x47052100, info);
2405 /* new in 2.2.3p1 from Geert. ???????? */
2406 aty_st_le32(BUS_CNTL, 0x590e10ff, info);
2407 aty_st_le32(DAC_CNTL, 0x47012100, info);
2408 break;
2411 switch (info->clk_type) {
2412 case CLK_ATI18818_1:
2413 aty_set_pll18818(info, &par->pll.ics2595);
2414 break;
2415 case CLK_STG1703:
2416 aty_set_pll_1703(info, &par->pll.ics2595);
2417 break;
2418 case CLK_CH8398:
2419 aty_set_pll_8398(info, &par->pll.ics2595);
2420 break;
2421 case CLK_ATT20C408:
2422 aty_set_pll_408(info, &par->pll.ics2595);
2423 break;
2424 case CLK_IBMRGB514:
2425 aty_set_pll_gx(info, &par->pll.gx);
2426 break;
2427 default:
2428 printk(" atyfb_set_par: CLK type not implemented yet!");
2429 break;
2432 /* Don't forget MEM_CNTL */
2433 i = aty_ld_le32(MEM_CNTL, info) & 0xf0ffffff;
2434 switch (par->crtc.bpp) {
2435 case 8:
2436 i |= 0x02000000;
2437 break;
2438 case 16:
2439 i |= 0x03000000;
2440 break;
2441 case 32:
2442 i |= 0x06000000;
2443 break;
2445 aty_st_le32(MEM_CNTL, i, info);
2447 } else {
2448 aty_set_pll_ct(info, &par->pll.ct);
2449 i = aty_ld_le32(MEM_CNTL, info) & 0xf00fffff;
2450 if (!(Gx == VT_CHIP_ID && (Rev == 0x40 || Rev == 0x48)))
2451 i |= info->mem_refresh_rate << 20;
2452 switch (par->crtc.bpp) {
2453 case 8:
2454 case 24:
2455 i |= 0x00000000;
2456 break;
2457 case 16:
2458 i |= 0x04000000;
2459 break;
2460 case 32:
2461 i |= 0x08000000;
2462 break;
2464 if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID)) {
2465 aty_st_le32(DAC_CNTL, 0x87010184, info);
2466 aty_st_le32(BUS_CNTL, 0x680000f9, info);
2467 } else if ((Gx == VT_CHIP_ID) || (Gx == VU_CHIP_ID)) {
2468 aty_st_le32(DAC_CNTL, 0x87010184, info);
2469 aty_st_le32(BUS_CNTL, 0x680000f9, info);
2470 } else {
2471 /* GT */
2472 aty_st_le32(DAC_CNTL, 0x86010102, info);
2473 aty_st_le32(BUS_CNTL, 0x7b23a040, info);
2474 aty_st_le32(EXT_MEM_CNTL,
2475 aty_ld_le32(EXT_MEM_CNTL, info) | 0x5000001, info);
2477 aty_st_le32(MEM_CNTL, i, info);
2479 aty_st_8(DAC_MASK, 0xff, info);
2481 /* Initialize the graphics engine */
2482 if (par->accel_flags & FB_ACCELF_TEXT)
2483 init_engine(par, info);
2485 #ifdef CONFIG_FB_COMPAT_XPMAC
2486 if (console_fb_info == &info->fb_info) {
2487 struct fb_var_screeninfo var;
2488 int vmode, cmode;
2489 display_info.height = ((par->crtc.v_tot_disp>>16) & 0x7ff)+1;
2490 display_info.width = (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8;
2491 display_info.depth = par->crtc.bpp;
2492 display_info.pitch = par->crtc.vxres*par->crtc.bpp/8;
2493 atyfb_encode_var(&var, par, info);
2494 if (mac_var_to_vmode(&var, &vmode, &cmode))
2495 display_info.mode = 0;
2496 else
2497 display_info.mode = vmode;
2498 strcpy(display_info.name, atyfb_name);
2499 display_info.fb_address = info->frame_buffer_phys;
2500 display_info.cmap_adr_address = info->ati_regbase_phys+0xc0;
2501 display_info.cmap_data_address = info->ati_regbase_phys+0xc1;
2502 display_info.disp_reg_address = info->ati_regbase_phys;
2504 #endif /* CONFIG_FB_COMPAT_XPMAC */
2507 static int atyfb_decode_var(const struct fb_var_screeninfo *var,
2508 struct atyfb_par *par,
2509 const struct fb_info_aty *info)
2511 int err;
2513 if ((err = aty_var_to_crtc(info, var, &par->crtc)))
2514 return err;
2515 if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID))
2516 switch (info->clk_type) {
2517 case CLK_ATI18818_1:
2518 err = aty_var_to_pll_18818(var->pixclock, &par->pll.ics2595);
2519 break;
2520 case CLK_STG1703:
2521 err = aty_var_to_pll_1703(var->pixclock, &par->pll.ics2595);
2522 break;
2523 case CLK_CH8398:
2524 err = aty_var_to_pll_8398(var->pixclock, &par->pll.ics2595);
2525 break;
2526 case CLK_ATT20C408:
2527 err = aty_var_to_pll_408(var->pixclock, &par->pll.ics2595);
2528 break;
2529 case CLK_IBMRGB514:
2530 err = aty_var_to_pll_514(var->pixclock, &par->pll.gx);
2531 break;
2533 else
2534 err = aty_var_to_pll_ct(info, var->pixclock, par->crtc.bpp,
2535 &par->pll.ct);
2536 if (err)
2537 return err;
2539 if (var->accel_flags & FB_ACCELF_TEXT)
2540 par->accel_flags = FB_ACCELF_TEXT;
2541 else
2542 par->accel_flags = 0;
2544 #if 0
2545 if (!fbmon_valid_timings(var->pixclock, htotal, vtotal, info))
2546 return -EINVAL;
2547 #endif
2549 return 0;
2552 static int atyfb_encode_var(struct fb_var_screeninfo *var,
2553 const struct atyfb_par *par,
2554 const struct fb_info_aty *info)
2556 int err;
2558 memset(var, 0, sizeof(struct fb_var_screeninfo));
2560 if ((err = aty_crtc_to_var(&par->crtc, var)))
2561 return err;
2562 if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID))
2563 switch (info->clk_type) {
2564 case CLK_ATI18818_1:
2565 var->pixclock = aty_pll_18818_to_var(&par->pll.ics2595);
2566 break;
2567 case CLK_STG1703:
2568 var->pixclock = aty_pll_1703_to_var(&par->pll.ics2595);
2569 break;
2570 case CLK_CH8398:
2571 var->pixclock = aty_pll_8398_to_var(&par->pll.ics2595);
2572 break;
2573 case CLK_ATT20C408:
2574 var->pixclock = aty_pll_408_to_var(&par->pll.ics2595);
2575 break;
2576 case CLK_IBMRGB514:
2577 var->pixclock = aty_pll_gx_to_var(&par->pll.gx, info);
2578 break;
2580 else
2581 var->pixclock = aty_pll_ct_to_var(&par->pll.ct, info);
2583 var->height = -1;
2584 var->width = -1;
2585 var->accel_flags = par->accel_flags;
2587 return 0;
2592 static void set_off_pitch(struct atyfb_par *par,
2593 const struct fb_info_aty *info)
2595 u32 xoffset = par->crtc.xoffset;
2596 u32 yoffset = par->crtc.yoffset;
2597 u32 vxres = par->crtc.vxres;
2598 u32 bpp = par->crtc.bpp;
2600 par->crtc.off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19);
2601 aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, info);
2606 * Open/Release the frame buffer device
2609 static int atyfb_open(struct fb_info *info, int user)
2612 #ifdef __sparc__
2613 struct fb_info_aty *fb = (struct fb_info_aty *)info;
2615 if (user) {
2616 if (fb->open)
2617 return -EBUSY;
2618 fb->mmaped = 0;
2619 fb->open = 1;
2620 fb->vtconsole = -1;
2621 } else {
2622 fb->consolecnt++;
2624 #endif
2625 MOD_INC_USE_COUNT;
2626 return(0);
2629 static int atyfb_release(struct fb_info *info, int user)
2631 #ifdef __sparc__
2632 struct fb_info_aty *fb = (struct fb_info_aty *)info;
2634 if (user) {
2635 if (fb->vtconsole != -1)
2636 vt_cons[fb->vtconsole]->vc_mode = KD_TEXT;
2637 fb->open = 0;
2638 fb->mmaped = 0;
2639 fb->vtconsole = -1;
2640 } else {
2641 fb->consolecnt--;
2643 #endif
2644 MOD_DEC_USE_COUNT;
2645 return(0);
2649 static int encode_fix(struct fb_fix_screeninfo *fix,
2650 const struct atyfb_par *par,
2651 const struct fb_info_aty *info)
2653 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
2655 strcpy(fix->id, atyfb_name);
2656 fix->smem_start = info->frame_buffer_phys;
2657 fix->smem_len = (u32)info->total_vram;
2659 #ifdef __LITTLE_ENDIAN
2661 * Last page of 8 MB little-endian aperture is MMIO
2662 * FIXME: we should use the auxiliary aperture instead so we can acces the
2663 * full 8 MB of video RAM on 8 MB boards
2665 if (fix->smem_len > 0x800000-GUI_RESERVE)
2666 fix->smem_len = 0x800000-GUI_RESERVE;
2667 #endif
2669 * Reg Block 0 (CT-compatible block) is at ati_regbase_phys
2670 * Reg Block 1 (multimedia extensions) is at ati_regbase_phys-0x400
2672 if (Gx == GX_CHIP_ID || Gx == CX_CHIP_ID) {
2673 fix->mmio_start = info->ati_regbase_phys;
2674 fix->mmio_len = 0x400;
2675 fix->accel = FB_ACCEL_ATI_MACH64GX;
2676 } else if (Gx == CT_CHIP_ID || Gx == ET_CHIP_ID) {
2677 fix->mmio_start = info->ati_regbase_phys;
2678 fix->mmio_len = 0x400;
2679 fix->accel = FB_ACCEL_ATI_MACH64CT;
2680 } else if (Gx == VT_CHIP_ID || Gx == VU_CHIP_ID || Gx == VV_CHIP_ID) {
2681 fix->mmio_start = info->ati_regbase_phys-0x400;
2682 fix->mmio_len = 0x800;
2683 fix->accel = FB_ACCEL_ATI_MACH64VT;
2684 } else {
2685 fix->mmio_start = info->ati_regbase_phys-0x400;
2686 fix->mmio_len = 0x800;
2687 fix->accel = FB_ACCEL_ATI_MACH64GT;
2689 fix->type = FB_TYPE_PACKED_PIXELS;
2690 fix->type_aux = 0;
2691 fix->line_length = par->crtc.vxres*par->crtc.bpp/8;
2692 fix->visual = par->crtc.bpp <= 8 ? FB_VISUAL_PSEUDOCOLOR
2693 : FB_VISUAL_DIRECTCOLOR;
2694 fix->ywrapstep = 0;
2695 fix->xpanstep = 8;
2696 fix->ypanstep = 1;
2698 return 0;
2702 struct fb_var_screeninfo default_var = {
2703 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
2704 640, 480, 640, 480, 0, 0, 8, 0,
2705 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
2706 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
2707 0, FB_VMODE_NONINTERLACED
2712 * Get the Fixed Part of the Display
2715 static int atyfb_get_fix(struct fb_fix_screeninfo *fix, int con,
2716 struct fb_info *fb)
2718 const struct fb_info_aty *info = (struct fb_info_aty *)fb;
2719 struct atyfb_par par;
2721 if (con == -1)
2722 par = info->default_par;
2723 else
2724 atyfb_decode_var(&fb_display[con].var, &par, info);
2725 encode_fix(fix, &par, info);
2726 return 0;
2731 * Get the User Defined Part of the Display
2734 static int atyfb_get_var(struct fb_var_screeninfo *var, int con,
2735 struct fb_info *fb)
2737 const struct fb_info_aty *info = (struct fb_info_aty *)fb;
2739 if (con == -1)
2740 atyfb_encode_var(var, &info->default_par, info);
2741 else
2742 *var = fb_display[con].var;
2743 return 0;
2747 static void atyfb_set_disp(struct display *disp, struct fb_info_aty *info,
2748 int bpp, int accel)
2750 switch (bpp) {
2751 #ifdef FBCON_HAS_CFB8
2752 case 8:
2753 info->dispsw = accel ? fbcon_aty8 : fbcon_cfb8;
2754 disp->dispsw = &info->dispsw;
2755 break;
2756 #endif
2757 #ifdef FBCON_HAS_CFB16
2758 case 16:
2759 info->dispsw = accel ? fbcon_aty16 : fbcon_cfb16;
2760 disp->dispsw = &info->dispsw;
2761 disp->dispsw_data = info->fbcon_cmap.cfb16;
2762 break;
2763 #endif
2764 #ifdef FBCON_HAS_CFB24
2765 case 24:
2766 info->dispsw = accel ? fbcon_aty24 : fbcon_cfb24;
2767 disp->dispsw = &info->dispsw;
2768 disp->dispsw_data = info->fbcon_cmap.cfb24;
2769 break;
2770 #endif
2771 #ifdef FBCON_HAS_CFB32
2772 case 32:
2773 info->dispsw = accel ? fbcon_aty32 : fbcon_cfb32;
2774 disp->dispsw = &info->dispsw;
2775 disp->dispsw_data = info->fbcon_cmap.cfb32;
2776 break;
2777 #endif
2778 default:
2779 disp->dispsw = &fbcon_dummy;
2781 if (info->cursor) {
2782 info->dispsw.cursor = atyfb_cursor;
2783 info->dispsw.set_font = atyfb_set_font;
2789 * Set the User Defined Part of the Display
2792 static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
2793 struct fb_info *fb)
2795 struct fb_info_aty *info = (struct fb_info_aty *)fb;
2796 struct atyfb_par par;
2797 struct display *display;
2798 int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel, accel, err;
2799 int activate = var->activate;
2801 if (con >= 0)
2802 display = &fb_display[con];
2803 else
2804 display = fb->disp; /* used during initialization */
2806 if ((err = atyfb_decode_var(var, &par, info)))
2807 return err;
2809 atyfb_encode_var(var, &par, (struct fb_info_aty *)info);
2811 if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
2812 oldxres = display->var.xres;
2813 oldyres = display->var.yres;
2814 oldvxres = display->var.xres_virtual;
2815 oldvyres = display->var.yres_virtual;
2816 oldbpp = display->var.bits_per_pixel;
2817 oldaccel = display->var.accel_flags;
2818 display->var = *var;
2819 if (oldxres != var->xres || oldyres != var->yres ||
2820 oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
2821 oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) {
2822 struct fb_fix_screeninfo fix;
2824 encode_fix(&fix, &par, info);
2825 display->screen_base = (char *)info->frame_buffer;
2826 display->visual = fix.visual;
2827 display->type = fix.type;
2828 display->type_aux = fix.type_aux;
2829 display->ypanstep = fix.ypanstep;
2830 display->ywrapstep = fix.ywrapstep;
2831 display->line_length = fix.line_length;
2832 display->can_soft_blank = 1;
2833 display->inverse = 0;
2834 accel = var->accel_flags & FB_ACCELF_TEXT;
2835 atyfb_set_disp(display, info, par.crtc.bpp, accel);
2836 if (accel)
2837 display->scrollmode = (info->bus_type == PCI) ? SCROLL_YNOMOVE : 0;
2838 else
2839 display->scrollmode = SCROLL_YREDRAW;
2840 if (info->fb_info.changevar)
2841 (*info->fb_info.changevar)(con);
2843 if (!info->fb_info.display_fg ||
2844 info->fb_info.display_fg->vc_num == con)
2845 atyfb_set_par(&par, info);
2846 if (oldbpp != var->bits_per_pixel) {
2847 if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
2848 return err;
2849 do_install_cmap(con, &info->fb_info);
2853 return 0;
2858 * Pan or Wrap the Display
2860 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
2863 static int atyfb_pan_display(struct fb_var_screeninfo *var, int con,
2864 struct fb_info *fb)
2866 struct fb_info_aty *info = (struct fb_info_aty *)fb;
2867 u32 xres, yres, xoffset, yoffset;
2868 struct atyfb_par *par = &info->current_par;
2870 xres = (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8;
2871 yres = ((par->crtc.v_tot_disp>>16) & 0x7ff)+1;
2872 xoffset = (var->xoffset+7) & ~7;
2873 yoffset = var->yoffset;
2874 if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres)
2875 return -EINVAL;
2876 par->crtc.xoffset = xoffset;
2877 par->crtc.yoffset = yoffset;
2878 set_off_pitch(par, info);
2879 return 0;
2883 * Get the Colormap
2886 static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
2887 struct fb_info *info)
2889 if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */
2890 return fb_get_cmap(cmap, kspc, atyfb_getcolreg, info);
2891 else if (fb_display[con].cmap.len) /* non default colormap? */
2892 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
2893 else {
2894 int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
2895 fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
2897 return 0;
2901 * Set the Colormap
2904 static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
2905 struct fb_info *info)
2907 int err;
2908 struct display *disp;
2910 if (con >= 0)
2911 disp = &fb_display[con];
2912 else
2913 disp = info->disp;
2914 if (!disp->cmap.len) { /* no colormap allocated? */
2915 int size = disp->var.bits_per_pixel == 16 ? 32 : 256;
2916 if ((err = fb_alloc_cmap(&disp->cmap, size, 0)))
2917 return err;
2919 if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */
2920 return fb_set_cmap(cmap, kspc, atyfb_setcolreg, info);
2921 else
2922 fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
2923 return 0;
2927 #ifdef DEBUG
2928 #define ATYIO_CLKR 0x41545900 /* ATY\00 */
2929 #define ATYIO_CLKW 0x41545901 /* ATY\01 */
2931 struct atyclk {
2932 u32 ref_clk_per;
2933 u8 pll_ref_div;
2934 u8 mclk_fb_div;
2935 u8 mclk_post_div; /* 1,2,3,4,8 */
2936 u8 vclk_fb_div;
2937 u8 vclk_post_div; /* 1,2,3,4,6,8,12 */
2938 u32 dsp_xclks_per_row; /* 0-16383 */
2939 u32 dsp_loop_latency; /* 0-15 */
2940 u32 dsp_precision; /* 0-7 */
2941 u32 dsp_on; /* 0-2047 */
2942 u32 dsp_off; /* 0-2047 */
2944 #endif
2946 static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
2947 u_long arg, int con, struct fb_info *info2)
2949 #if defined(__sparc__) || defined(DEBUG)
2950 struct fb_info_aty *info = (struct fb_info_aty *)info2;
2951 #endif /* __sparc__ || DEBUG */
2952 #ifdef __sparc__
2953 struct fbtype fbtyp;
2954 struct display *disp;
2956 if (con >= 0)
2957 disp = &fb_display[con];
2958 else
2959 disp = info2->disp;
2960 #endif
2962 switch (cmd) {
2963 #ifdef __sparc__
2964 case FBIOGTYPE:
2965 fbtyp.fb_type = FBTYPE_PCI_GENERIC;
2966 fbtyp.fb_width = info->current_par.crtc.vxres;
2967 fbtyp.fb_height = info->current_par.crtc.vyres;
2968 fbtyp.fb_depth = info->current_par.crtc.bpp;
2969 fbtyp.fb_cmsize = disp->cmap.len;
2970 fbtyp.fb_size = info->total_vram;
2971 copy_to_user_ret((struct fbtype *)arg, &fbtyp, sizeof(fbtyp), -EFAULT);
2972 break;
2973 #endif /* __sparc__ */
2974 #ifdef DEBUG
2975 case ATYIO_CLKR:
2976 if ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
2977 struct atyclk clk;
2978 struct pll_ct *pll = &info->current_par.pll.ct;
2979 u32 dsp_config = pll->dsp_config;
2980 u32 dsp_on_off = pll->dsp_on_off;
2981 clk.ref_clk_per = info->ref_clk_per;
2982 clk.pll_ref_div = pll->pll_ref_div;
2983 clk.mclk_fb_div = pll->mclk_fb_div;
2984 clk.mclk_post_div = pll->mclk_post_div_real;
2985 clk.vclk_fb_div = pll->vclk_fb_div;
2986 clk.vclk_post_div = pll->vclk_post_div_real;
2987 clk.dsp_xclks_per_row = dsp_config & 0x3fff;
2988 clk.dsp_loop_latency = (dsp_config>>16) & 0xf;
2989 clk.dsp_precision = (dsp_config>>20) & 7;
2990 clk.dsp_on = dsp_on_off & 0x7ff;
2991 clk.dsp_off = (dsp_on_off>>16) & 0x7ff;
2992 copy_to_user_ret((struct atyclk *)arg, &clk, sizeof(clk),
2993 -EFAULT);
2994 } else
2995 return -EINVAL;
2996 break;
2997 case ATYIO_CLKW:
2998 if ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
2999 struct atyclk clk;
3000 struct pll_ct *pll = &info->current_par.pll.ct;
3001 copy_from_user_ret(&clk, (struct atyclk *)arg, sizeof(clk),
3002 -EFAULT);
3003 info->ref_clk_per = clk.ref_clk_per;
3004 pll->pll_ref_div = clk.pll_ref_div;
3005 pll->mclk_fb_div = clk.mclk_fb_div;
3006 pll->mclk_post_div_real = clk.mclk_post_div;
3007 pll->vclk_fb_div = clk.vclk_fb_div;
3008 pll->vclk_post_div_real = clk.vclk_post_div;
3009 pll->dsp_config = (clk.dsp_xclks_per_row & 0x3fff) |
3010 ((clk.dsp_loop_latency & 0xf)<<16) |
3011 ((clk.dsp_precision & 7)<<20);
3012 pll->dsp_on_off = (clk.dsp_on & 0x7ff) |
3013 ((clk.dsp_off & 0x7ff)<<16);
3014 aty_calc_pll_ct(info, pll);
3015 aty_set_pll_ct(info, pll);
3016 } else
3017 return -EINVAL;
3018 break;
3019 #endif /* DEBUG */
3020 default:
3021 return -EINVAL;
3023 return 0;
3026 static int atyfb_rasterimg(struct fb_info *info, int start)
3028 struct fb_info_aty *fb = (struct fb_info_aty *)info;
3030 if (fb->blitter_may_be_busy)
3031 wait_for_idle(fb);
3032 return 0;
3035 #ifdef __sparc__
3036 static int atyfb_mmap(struct fb_info *info, struct file *file,
3037 struct vm_area_struct *vma)
3039 struct fb_info_aty *fb = (struct fb_info_aty *)info;
3040 unsigned int size, page, map_size = 0;
3041 unsigned long map_offset = 0;
3042 int i;
3044 if (!fb->mmap_map)
3045 return -ENXIO;
3047 size = vma->vm_end - vma->vm_start;
3048 if (vma->vm_offset & ~PAGE_MASK)
3049 return -ENXIO;
3051 /* To stop the swapper from even considering these pages. */
3052 vma->vm_flags |= (VM_SHM | VM_LOCKED);
3054 if (((vma->vm_offset == 0) && (size == fb->total_vram)) ||
3055 ((vma->vm_offset == fb->total_vram) && (size == PAGE_SIZE)))
3056 vma->vm_offset += 0x8000000000000000UL;
3058 #ifdef __sparc_v9__
3059 /* Align it as much as desirable */
3061 unsigned long j, align;
3062 int max = -1;
3064 map_offset = vma->vm_offset+size;
3065 for (i = 0; fb->mmap_map[i].size; i++) {
3066 if (fb->mmap_map[i].voff < vma->vm_offset)
3067 continue;
3068 if (fb->mmap_map[i].voff >= map_offset)
3069 break;
3070 if (max < 0 ||
3071 fb->mmap_map[i].size > fb->mmap_map[max].size)
3072 max = i;
3074 if (max >= 0) {
3075 j = fb->mmap_map[max].size;
3076 if (fb->mmap_map[max].voff + j > map_offset)
3077 j = map_offset - fb->mmap_map[max].voff;
3078 for (align = 0x400000; align > PAGE_SIZE; align >>= 3)
3079 if (j >= align &&
3080 !(fb->mmap_map[max].poff & (align - 1)))
3081 break;
3082 if (align > PAGE_SIZE) {
3083 j = align;
3084 align = j - ((vma->vm_start
3085 + fb->mmap_map[max].voff
3086 - vma->vm_offset) & (j - 1));
3087 if (align != j) {
3088 struct vm_area_struct *vmm;
3090 vmm = find_vma(current->mm,
3091 vma->vm_start);
3092 if (!vmm || vmm->vm_start
3093 >= vma->vm_end + align) {
3094 vma->vm_start += align;
3095 vma->vm_end += align;
3101 #endif
3103 /* Each page, see which map applies */
3104 for (page = 0; page < size; ) {
3105 map_size = 0;
3106 for (i = 0; fb->mmap_map[i].size; i++) {
3107 unsigned long start = fb->mmap_map[i].voff;
3108 unsigned long end = start + fb->mmap_map[i].size;
3109 unsigned long offset = vma->vm_offset + page;
3111 if (start > offset)
3112 continue;
3113 if (offset >= end)
3114 continue;
3116 map_size = fb->mmap_map[i].size - (offset - start);
3117 map_offset = fb->mmap_map[i].poff + (offset - start);
3118 break;
3120 if (!map_size) {
3121 page += PAGE_SIZE;
3122 continue;
3124 if (page + map_size > size)
3125 map_size = size - page;
3127 pgprot_val(vma->vm_page_prot) &= ~(fb->mmap_map[i].prot_mask);
3128 pgprot_val(vma->vm_page_prot) |= fb->mmap_map[i].prot_flag;
3130 if (remap_page_range(vma->vm_start + page, map_offset,
3131 map_size, vma->vm_page_prot))
3132 return -EAGAIN;
3134 page += map_size;
3137 if (!map_size)
3138 return -EINVAL;
3140 vma->vm_flags |= VM_IO;
3142 if (!fb->mmaped) {
3143 int lastconsole = 0;
3145 if (info->display_fg)
3146 lastconsole = info->display_fg->vc_num;
3147 fb->mmaped = 1;
3148 if (fb->consolecnt && fb_display[lastconsole].fb_info == info) {
3149 fb->vtconsole = lastconsole;
3150 vt_cons[lastconsole]->vc_mode = KD_GRAPHICS;
3153 return 0;
3156 static struct {
3157 u32 yoffset;
3158 u8 r[2][256];
3159 u8 g[2][256];
3160 u8 b[2][256];
3161 } atyfb_save;
3163 static void atyfb_save_palette(struct fb_info *fb, int enter)
3165 struct fb_info_aty *info = (struct fb_info_aty *)fb;
3166 int i, tmp, scale;
3168 for (i = 0; i < 256; i++) {
3169 tmp = aty_ld_8(DAC_CNTL, info) & 0xfc;
3170 if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == GV_CHIP_ID ||
3171 Gx == GW_CHIP_ID || Gx == GZ_CHIP_ID || Gx == LG_CHIP_ID ||
3172 Gx == GB_CHIP_ID || Gx == GD_CHIP_ID || Gx == GI_CHIP_ID ||
3173 Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID)
3174 tmp |= 0x2;
3175 aty_st_8(DAC_CNTL, tmp, info);
3176 aty_st_8(DAC_MASK, 0xff, info);
3177 eieio();
3178 scale = ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID) &&
3179 (info->current_par.crtc.bpp == 16)) ? 3 : 0;
3180 info->aty_cmap_regs->rindex = i << scale;
3181 eieio();
3182 atyfb_save.r[enter][i] = info->aty_cmap_regs->lut;
3183 eieio();
3184 atyfb_save.g[enter][i] = info->aty_cmap_regs->lut;
3185 eieio();
3186 atyfb_save.b[enter][i] = info->aty_cmap_regs->lut;
3187 eieio();
3188 info->aty_cmap_regs->windex = i << scale;
3189 eieio();
3190 info->aty_cmap_regs->lut = atyfb_save.r[1-enter][i];
3191 eieio();
3192 info->aty_cmap_regs->lut = atyfb_save.g[1-enter][i];
3193 eieio();
3194 info->aty_cmap_regs->lut = atyfb_save.b[1-enter][i];
3195 eieio();
3199 static void atyfb_palette(int enter)
3201 struct fb_info_aty *info;
3202 struct atyfb_par *par;
3203 struct display *d;
3204 int i;
3206 for (i = 0; i < MAX_NR_CONSOLES; i++) {
3207 d = &fb_display[i];
3208 if (d->fb_info &&
3209 d->fb_info->fbops == &atyfb_ops &&
3210 d->fb_info->display_fg &&
3211 d->fb_info->display_fg->vc_num == i) {
3212 atyfb_save_palette(d->fb_info, enter);
3213 info = (struct fb_info_aty *)d->fb_info;
3214 par = &info->current_par;
3215 if (enter) {
3216 atyfb_save.yoffset = par->crtc.yoffset;
3217 par->crtc.yoffset = 0;
3218 set_off_pitch(par, info);
3219 } else {
3220 par->crtc.yoffset = atyfb_save.yoffset;
3221 set_off_pitch(par, info);
3223 break;
3227 #endif /* __sparc__ */
3230 * Initialisation
3233 static int __init aty_init(struct fb_info_aty *info, const char *name)
3235 u32 chip_id;
3236 u32 i;
3237 int j, k;
3238 struct fb_var_screeninfo var;
3239 struct display *disp;
3240 const char *chipname = NULL, *ramname = NULL, *xtal;
3241 int pll, mclk, gtb_memsize;
3242 #if defined(CONFIG_PPC)
3243 int sense;
3244 #endif
3245 u8 pll_ref_div;
3247 info->aty_cmap_regs = (struct aty_cmap_regs *)(info->ati_regbase+0xc0);
3248 #ifdef __sparc_v9__
3249 info->aty_cmap_regs = __va(info->aty_cmap_regs);
3250 #endif
3251 chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
3252 Gx = chip_id & CFG_CHIP_TYPE;
3253 Rev = (chip_id & CFG_CHIP_REV)>>24;
3254 for (j = 0; j < (sizeof(aty_features)/sizeof(*aty_features)); j++)
3255 if (aty_features[j].chip_type == Gx) {
3256 chipname = aty_features[j].name;
3257 info->dac_type = (aty_ld_le32(DAC_CNTL, info) >> 16) & 0x07;
3258 break;
3260 if (!chipname) {
3261 printk("atyfb: Unknown mach64 0x%04x\n", Gx);
3262 return 0;
3263 } else
3264 printk("atyfb: %s [0x%04x rev 0x%02x] ", chipname, Gx, Rev);
3265 if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID)) {
3266 info->bus_type = (aty_ld_le32(CONFIG_STAT0, info) >> 0) & 0x07;
3267 info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) >> 3) & 0x07;
3268 ramname = aty_gx_ram[info->ram_type];
3269 /* FIXME: clockchip/RAMDAC probing? */
3270 #ifdef CONFIG_ATARI
3271 info->clk_type = CLK_ATI18818_1;
3272 info->dac_type = (aty_ld_le32(CONFIG_STAT0, info) >> 9) & 0x07;
3273 if (info->dac_type == 0x07)
3274 info->dac_subtype = DAC_ATT20C408;
3275 else
3276 info->dac_subtype = (aty_ld_8(SCRATCH_REG1 + 1, info) & 0xF0) |
3277 info->dac_type;
3278 #else
3279 info->dac_type = DAC_IBMRGB514;
3280 info->dac_subtype = DAC_IBMRGB514;
3281 info->clk_type = CLK_IBMRGB514;
3282 #endif
3283 /* FIXME */
3284 pll = 135;
3285 mclk = 50;
3286 } else {
3287 info->bus_type = PCI;
3288 info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) & 0x07);
3289 ramname = aty_ct_ram[info->ram_type];
3290 info->dac_type = DAC_INTERNAL;
3291 info->dac_subtype = DAC_INTERNAL;
3292 info->clk_type = CLK_INTERNAL;
3293 if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID)) {
3294 pll = 135;
3295 mclk = 60;
3296 } else {
3297 mclk = info->ram_type >= SDRAM ? 67 : 63;
3298 if ((Gx == VT_CHIP_ID) && (Rev == 0x08)) {
3299 /* VTA3 */
3300 pll = 170;
3301 } else if (((Gx == VT_CHIP_ID) && ((Rev == 0x40) ||
3302 (Rev == 0x48))) ||
3303 ((Gx == VT_CHIP_ID) && ((Rev == 0x01) ||
3304 (Rev == 0x9a))) ||
3305 Gx == VU_CHIP_ID) {
3306 /* VTA4 or VTB */
3307 pll = 200;
3308 } else if (Gx == VV_CHIP_ID) {
3309 /* VT4 */
3310 pll = 230;
3311 mclk = 83;
3312 } else if (Gx == VT_CHIP_ID) {
3313 /* other VT */
3314 pll = 135;
3315 mclk = 63;
3316 } else if ((Gx == GT_CHIP_ID) && (Rev & 0x01)) {
3317 /* RAGE II */
3318 pll = 170;
3319 } else if (((Gx == GT_CHIP_ID) && (Rev & 0x02)) ||
3320 (Gx == GU_CHIP_ID)) {
3321 /* RAGE II+ */
3322 pll = 200;
3323 } else if (Gx == GV_CHIP_ID || Gx == GW_CHIP_ID ||
3324 Gx == GZ_CHIP_ID) {
3325 /* RAGE IIC */
3326 pll = 230;
3327 mclk = 83;
3328 } else if (Gx == GB_CHIP_ID || Gx == GD_CHIP_ID ||
3329 Gx == GI_CHIP_ID || Gx == GP_CHIP_ID ||
3330 Gx == GQ_CHIP_ID || Gx == LB_CHIP_ID ||
3331 Gx == LD_CHIP_ID || Gx == LG_CHIP_ID ||
3332 Gx == LI_CHIP_ID || Gx == LP_CHIP_ID) {
3333 /* RAGE PRO or LT PRO */
3334 pll = 230;
3335 mclk = 100;
3336 } else {
3337 /* other RAGE */
3338 pll = 135;
3339 mclk = 63;
3344 info->ref_clk_per = 1000000000000ULL/14318180;
3345 xtal = "14.31818";
3346 if (!(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
3347 Gx == ET_CHIP_ID ||
3348 ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07))) &&
3349 (pll_ref_div = aty_ld_pll(PLL_REF_DIV, info))) {
3350 int diff1, diff2;
3351 diff1 = 510*14/pll_ref_div-pll;
3352 diff2 = 510*29/pll_ref_div-pll;
3353 if (diff1 < 0)
3354 diff1 = -diff1;
3355 if (diff2 < 0)
3356 diff2 = -diff2;
3357 if (diff2 < diff1) {
3358 info->ref_clk_per = 1000000000000ULL/29498928;
3359 xtal = "29.498928";
3363 i = aty_ld_le32(MEM_CNTL, info);
3364 gtb_memsize = !(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
3365 Gx == ET_CHIP_ID ||
3366 ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07)));
3367 if (gtb_memsize)
3368 switch (i & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */
3369 case MEM_SIZE_512K:
3370 info->total_vram = 0x80000;
3371 break;
3372 case MEM_SIZE_1M:
3373 info->total_vram = 0x100000;
3374 break;
3375 case MEM_SIZE_2M_GTB:
3376 info->total_vram = 0x200000;
3377 break;
3378 case MEM_SIZE_4M_GTB:
3379 info->total_vram = 0x400000;
3380 break;
3381 case MEM_SIZE_6M_GTB:
3382 info->total_vram = 0x600000;
3383 break;
3384 case MEM_SIZE_8M_GTB:
3385 info->total_vram = 0x800000;
3386 break;
3387 default:
3388 info->total_vram = 0x80000;
3390 else
3391 switch (i & MEM_SIZE_ALIAS) {
3392 case MEM_SIZE_512K:
3393 info->total_vram = 0x80000;
3394 break;
3395 case MEM_SIZE_1M:
3396 info->total_vram = 0x100000;
3397 break;
3398 case MEM_SIZE_2M:
3399 info->total_vram = 0x200000;
3400 break;
3401 case MEM_SIZE_4M:
3402 info->total_vram = 0x400000;
3403 break;
3404 case MEM_SIZE_6M:
3405 info->total_vram = 0x600000;
3406 break;
3407 case MEM_SIZE_8M:
3408 info->total_vram = 0x800000;
3409 break;
3410 default:
3411 info->total_vram = 0x80000;
3414 if (Gx == GI_CHIP_ID) {
3415 if (aty_ld_le32(CONFIG_STAT1, info) & 0x40000000)
3416 info->total_vram += 0x400000;
3419 if (default_vram) {
3420 info->total_vram = default_vram*1024;
3421 i = i & ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS);
3422 if (info->total_vram <= 0x80000)
3423 i |= MEM_SIZE_512K;
3424 else if (info->total_vram <= 0x100000)
3425 i |= MEM_SIZE_1M;
3426 else if (info->total_vram <= 0x200000)
3427 i |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M;
3428 else if (info->total_vram <= 0x400000)
3429 i |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M;
3430 else if (info->total_vram <= 0x600000)
3431 i |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M;
3432 else
3433 i |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M;
3434 aty_st_le32(MEM_CNTL, i, info);
3436 if (default_pll)
3437 pll = default_pll;
3438 if (default_mclk)
3439 mclk = default_mclk;
3441 printk("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK\n",
3442 info->total_vram == 0x80000 ? 512 : (info->total_vram >> 20),
3443 info->total_vram == 0x80000 ? 'K' : 'M', ramname, xtal, pll, mclk);
3445 if (mclk < 44)
3446 info->mem_refresh_rate = 0; /* 000 = 10 Mhz - 43 Mhz */
3447 else if (mclk < 50)
3448 info->mem_refresh_rate = 1; /* 001 = 44 Mhz - 49 Mhz */
3449 else if (mclk < 55)
3450 info->mem_refresh_rate = 2; /* 010 = 50 Mhz - 54 Mhz */
3451 else if (mclk < 66)
3452 info->mem_refresh_rate = 3; /* 011 = 55 Mhz - 65 Mhz */
3453 else if (mclk < 75)
3454 info->mem_refresh_rate = 4; /* 100 = 66 Mhz - 74 Mhz */
3455 else if (mclk < 80)
3456 info->mem_refresh_rate = 5; /* 101 = 75 Mhz - 79 Mhz */
3457 else if (mclk < 100)
3458 info->mem_refresh_rate = 6; /* 110 = 80 Mhz - 100 Mhz */
3459 else
3460 info->mem_refresh_rate = 7; /* 111 = 100 Mhz and above */
3461 info->pll_per = 1000000/pll;
3462 info->mclk_per = 1000000/mclk;
3464 #ifdef DEBUG
3465 if ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
3466 int i;
3467 printk("BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
3468 "DSP_CONFIG DSP_ON_OFF\n"
3469 "%08x %08x %08x %08x %08x %08x %08x\n"
3470 "PLL",
3471 aty_ld_le32(BUS_CNTL, info), aty_ld_le32(DAC_CNTL, info),
3472 aty_ld_le32(MEM_CNTL, info), aty_ld_le32(EXT_MEM_CNTL, info),
3473 aty_ld_le32(CRTC_GEN_CNTL, info), aty_ld_le32(DSP_CONFIG, info),
3474 aty_ld_le32(DSP_ON_OFF, info));
3475 for (i = 0; i < 16; i++)
3476 printk(" %02x", aty_ld_pll(i, info));
3477 printk("\n");
3479 #endif
3481 if (info->bus_type == ISA)
3482 if ((info->total_vram == 0x400000) || (info->total_vram == 0x800000)) {
3483 /* protect GUI-regs if complete Aperture is VRAM */
3484 info->total_vram -= GUI_RESERVE;
3487 disp = &info->disp;
3489 strcpy(info->fb_info.modename, atyfb_name);
3490 info->fb_info.node = -1;
3491 info->fb_info.fbops = &atyfb_ops;
3492 info->fb_info.disp = disp;
3493 strcpy(info->fb_info.fontname, fontname);
3494 info->fb_info.changevar = NULL;
3495 info->fb_info.switch_con = &atyfbcon_switch;
3496 info->fb_info.updatevar = &atyfbcon_updatevar;
3497 info->fb_info.blank = &atyfbcon_blank;
3498 info->fb_info.flags = FBINFO_FLAG_DEFAULT;
3500 #ifdef MODULE
3501 var = default_var;
3502 #else /* !MODULE */
3503 memset(&var, 0, sizeof(var));
3504 #if defined(CONFIG_PPC)
3505 if (mode_option) {
3506 if (!mac_find_mode(&var, &info->fb_info, mode_option, 8))
3507 var = default_var;
3508 } else {
3509 if (default_vmode == VMODE_NVRAM) {
3510 default_vmode = nvram_read_byte(NV_VMODE);
3511 if (default_vmode <= 0 || default_vmode > VMODE_MAX)
3512 default_vmode = VMODE_CHOOSE;
3514 if (default_vmode == VMODE_CHOOSE) {
3515 if (Gx == LG_CHIP_ID)
3516 /* G3 PowerBook with 1024x768 LCD */
3517 default_vmode = VMODE_1024_768_60;
3518 else {
3519 sense = read_aty_sense(info);
3520 default_vmode = mac_map_monitor_sense(sense);
3523 if (default_vmode <= 0 || default_vmode > VMODE_MAX)
3524 default_vmode = VMODE_640_480_60;
3525 if (default_cmode == CMODE_NVRAM)
3526 default_cmode = nvram_read_byte(NV_CMODE);
3527 if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
3528 default_cmode = CMODE_8;
3529 if (mac_vmode_to_var(default_vmode, default_cmode, &var))
3530 var = default_var;
3532 #else /* !CONFIG_PPC */
3533 #ifdef __sparc__
3534 if (mode_option) {
3535 if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
3536 var = default_var;
3537 } else
3538 var = default_var;
3539 #else
3540 if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
3541 var = default_var;
3542 #endif /* !__sparc__ */
3543 #endif /* !CONFIG_PPC */
3544 #endif /* !MODULE */
3545 if (noaccel)
3546 var.accel_flags &= ~FB_ACCELF_TEXT;
3547 else
3548 var.accel_flags |= FB_ACCELF_TEXT;
3550 if (var.yres == var.yres_virtual) {
3551 u32 vram = (info->total_vram - (PAGE_SIZE << 2));
3552 var.yres_virtual = ((vram * 8) / var.bits_per_pixel) / var.xres_virtual;
3553 if (var.yres_virtual < var.yres)
3554 var.yres_virtual = var.yres;
3557 if (atyfb_decode_var(&var, &info->default_par, info)) {
3558 printk("atyfb: can't set default video mode\n");
3559 return 0;
3562 #ifdef __sparc__
3563 atyfb_save_palette(&info->fb_info, 0);
3564 #endif
3565 for (j = 0; j < 16; j++) {
3566 k = color_table[j];
3567 info->palette[j].red = default_red[k];
3568 info->palette[j].green = default_grn[k];
3569 info->palette[j].blue = default_blu[k];
3572 if (Gx != GX_CHIP_ID && Gx != CX_CHIP_ID) {
3573 info->cursor = aty_init_cursor(info);
3574 if (info->cursor) {
3575 info->dispsw.cursor = atyfb_cursor;
3576 info->dispsw.set_font = atyfb_set_font;
3580 atyfb_set_var(&var, -1, &info->fb_info);
3582 if (register_framebuffer(&info->fb_info) < 0)
3583 return 0;
3585 info->next = fb_list;
3586 fb_list = info;
3588 printk("fb%d: %s frame buffer device on %s\n",
3589 GET_FB_IDX(info->fb_info.node), atyfb_name, name);
3590 return 1;
3593 int __init atyfb_init(void)
3595 #if defined(CONFIG_FB_OF)
3596 /* We don't want to be called like this. */
3597 /* We rely on Open Firmware (offb) instead. */
3598 #elif defined(CONFIG_PCI)
3599 struct pci_dev *pdev;
3600 struct fb_info_aty *info;
3601 unsigned long addr;
3602 #ifdef __sparc__
3603 extern void (*prom_palette) (int);
3604 extern int con_is_present(void);
3605 struct pcidev_cookie *pcp;
3606 char prop[128];
3607 int node, len;
3608 u32 mem, chip_id;
3609 int i, j;
3611 /* Do not attach when we have a serial console. */
3612 if (!con_is_present())
3613 return -ENXIO;
3614 #else
3615 u16 tmp;
3616 #endif
3618 for (pdev = pci_devices; pdev; pdev = pdev->next) {
3619 if (((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) &&
3620 (pdev->vendor == PCI_VENDOR_ID_ATI)) {
3621 struct resource *rp;
3623 info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
3624 if (!info) {
3625 printk("atyfb_init: can't alloc fb_info_aty\n");
3626 return -ENXIO;
3628 memset(info, 0, sizeof(struct fb_info_aty));
3630 rp = &pdev->resource[0];
3631 if (rp->flags & IORESOURCE_IO)
3632 rp = &pdev->resource[1];
3633 addr = rp->start;
3634 if (!addr)
3635 continue;
3637 #ifdef __sparc__
3639 * Map memory-mapped registers.
3641 info->ati_regbase = addr + 0x7ffc00UL;
3642 info->ati_regbase_phys = addr + 0x7ffc00UL;
3645 * Map in big-endian aperture.
3647 info->frame_buffer = (unsigned long) __va(addr + 0x800000UL);
3648 info->frame_buffer_phys = addr + 0x800000UL;
3651 * Figure mmap addresses from PCI config space.
3652 * Split Framebuffer in big- and little-endian halfs.
3654 for (i = 0; i < 6 && pdev->resource[i].start; i++)
3655 /* nothing */;
3656 j = i + 4;
3658 info->mmap_map = kmalloc(j * sizeof(*info->mmap_map), GFP_ATOMIC);
3659 if (!info->mmap_map) {
3660 printk("atyfb_init: can't alloc mmap_map\n");
3661 kfree(info);
3662 return -ENXIO;
3664 memset(info->mmap_map, 0, j * sizeof(*info->mmap_map));
3666 for (i = 0, j = 2; i < 6 && pdev->resource[i].start; i++) {
3667 struct resource *rp = &pdev->resource[i];
3668 int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
3669 unsigned long base;
3670 u32 size, pbase;
3672 base = rp->start;
3674 io = (rp->flags & IORESOURCE_IO);
3676 size = rp->end - base + 1;
3678 pci_read_config_dword(pdev, breg, &pbase);
3680 if (io)
3681 size &= ~1;
3684 * Map the framebuffer a second time, this time without
3685 * the braindead _PAGE_IE setting. This is used by the
3686 * fixed Xserver, but we need to maintain the old mapping
3687 * to stay compatible with older ones...
3689 if (base == addr) {
3690 info->mmap_map[j].voff = (pbase + 0x10000000) & PAGE_MASK;
3691 info->mmap_map[j].poff = base & PAGE_MASK;
3692 info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
3693 info->mmap_map[j].prot_mask = _PAGE_CACHE;
3694 info->mmap_map[j].prot_flag = _PAGE_E;
3695 j++;
3699 * Here comes the old framebuffer mapping with _PAGE_IE
3700 * set for the big endian half of the framebuffer...
3702 if (base == addr) {
3703 info->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK;
3704 info->mmap_map[j].poff = (base+0x800000) & PAGE_MASK;
3705 info->mmap_map[j].size = 0x800000;
3706 info->mmap_map[j].prot_mask = _PAGE_CACHE;
3707 info->mmap_map[j].prot_flag = _PAGE_E|_PAGE_IE;
3708 size -= 0x800000;
3709 j++;
3712 info->mmap_map[j].voff = pbase & PAGE_MASK;
3713 info->mmap_map[j].poff = base & PAGE_MASK;
3714 info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
3715 info->mmap_map[j].prot_mask = _PAGE_CACHE;
3716 info->mmap_map[j].prot_flag = _PAGE_E;
3717 j++;
3721 * Fix PROMs idea of MEM_CNTL settings...
3723 mem = aty_ld_le32(MEM_CNTL, info);
3724 chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
3725 if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) &&
3726 !((chip_id >> 24) & 1)) {
3727 switch (mem & 0x0f) {
3728 case 3:
3729 mem = (mem & ~(0x0f)) | 2;
3730 break;
3731 case 7:
3732 mem = (mem & ~(0x0f)) | 3;
3733 break;
3734 case 9:
3735 mem = (mem & ~(0x0f)) | 4;
3736 break;
3737 case 11:
3738 mem = (mem & ~(0x0f)) | 5;
3739 break;
3740 default:
3741 break;
3743 if ((aty_ld_le32(CONFIG_STAT0, info) & 7) >= SDRAM)
3744 mem &= ~(0x00700000);
3746 mem &= ~(0xcf80e000); /* Turn off all undocumented bits. */
3747 aty_st_le32(MEM_CNTL, mem, info);
3750 * If this is the console device, we will set default video
3751 * settings to what the PROM left us with.
3753 node = prom_getchild(prom_root_node);
3754 node = prom_searchsiblings(node, "aliases");
3755 if (node) {
3756 len = prom_getproperty(node, "screen", prop, sizeof(prop));
3757 if (len > 0) {
3758 prop[len] = '\0';
3759 node = prom_finddevice(prop);
3760 } else {
3761 node = 0;
3765 pcp = pdev->sysdata;
3766 if (node == pcp->prom_node) {
3768 struct fb_var_screeninfo *var = &default_var;
3769 unsigned int N, P, Q, M, T;
3770 u32 v_total, h_total;
3771 struct crtc crtc;
3772 u8 pll_regs[16];
3773 u8 clock_cntl;
3775 crtc.vxres = prom_getintdefault(node, "width", 1024);
3776 crtc.vyres = prom_getintdefault(node, "height", 768);
3777 crtc.bpp = prom_getintdefault(node, "depth", 8);
3778 crtc.xoffset = crtc.yoffset = 0;
3779 crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, info);
3780 crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, info);
3781 crtc.v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, info);
3782 crtc.v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, info);
3783 crtc.gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, info);
3784 aty_crtc_to_var(&crtc, var);
3786 h_total = var->xres + var->right_margin +
3787 var->hsync_len + var->left_margin;
3788 v_total = var->yres + var->lower_margin +
3789 var->vsync_len + var->upper_margin;
3792 * Read the PLL to figure actual Refresh Rate.
3794 clock_cntl = aty_ld_8(CLOCK_CNTL, info);
3795 /* printk("atyfb: CLOCK_CNTL: %02x\n", clock_cntl); */
3796 for (i = 0; i < 16; i++)
3797 pll_regs[i] = aty_ld_pll(i, info);
3800 * PLL Reference Devider M:
3802 M = pll_regs[2];
3805 * PLL Feedback Devider N (Dependant on CLOCK_CNTL):
3807 N = pll_regs[7 + (clock_cntl & 3)];
3810 * PLL Post Devider P (Dependant on CLOCK_CNTL):
3812 P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
3815 * PLL Devider Q:
3817 Q = N / P;
3820 * Target Frequency:
3822 * T * M
3823 * Q = -------
3824 * 2 * R
3826 * where R is XTALIN (= 14318 kHz).
3828 T = 2 * Q * 14318 / M;
3830 default_var.pixclock = 1000000000 / T;
3833 #else /* __sparc__ */
3835 info->ati_regbase_phys = 0x7ff000 + addr;
3836 info->ati_regbase = (unsigned long)
3837 ioremap(info->ati_regbase_phys, 0x1000);
3839 if(!info->ati_regbase) {
3840 kfree(info);
3841 return -ENOMEM;
3844 info->ati_regbase_phys += 0xc00;
3845 info->ati_regbase += 0xc00;
3848 * Enable memory-space accesses using config-space
3849 * command register.
3851 pci_read_config_word(pdev, PCI_COMMAND, &tmp);
3852 if (!(tmp & PCI_COMMAND_MEMORY)) {
3853 tmp |= PCI_COMMAND_MEMORY;
3854 pci_write_config_word(pdev, PCI_COMMAND, tmp);
3857 #ifdef __BIG_ENDIAN
3858 /* Use the big-endian aperture */
3859 addr += 0x800000;
3860 #endif
3862 /* Map in frame buffer */
3863 info->frame_buffer_phys = addr;
3864 info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
3866 if(!info->frame_buffer) {
3867 kfree(info);
3868 return -ENXIO;
3871 #endif /* __sparc__ */
3873 if (!aty_init(info, "PCI")) {
3874 if (info->mmap_map)
3875 kfree(info->mmap_map);
3876 kfree(info);
3877 return -ENXIO;
3880 #ifdef __sparc__
3881 if (!prom_palette)
3882 prom_palette = atyfb_palette;
3885 * Add /dev/fb mmap values.
3887 info->mmap_map[0].voff = 0x8000000000000000UL;
3888 info->mmap_map[0].poff = __pa(info->frame_buffer & PAGE_MASK);
3889 info->mmap_map[0].size = info->total_vram;
3890 info->mmap_map[0].prot_mask = _PAGE_CACHE;
3891 info->mmap_map[0].prot_flag = _PAGE_E;
3892 info->mmap_map[1].voff = info->mmap_map[0].voff + info->total_vram;
3893 info->mmap_map[1].poff = info->ati_regbase & PAGE_MASK;
3894 info->mmap_map[1].size = PAGE_SIZE;
3895 info->mmap_map[1].prot_mask = _PAGE_CACHE;
3896 info->mmap_map[1].prot_flag = _PAGE_E;
3897 #endif /* __sparc__ */
3901 #elif defined(CONFIG_ATARI)
3902 u32 clock_r;
3903 int m64_num;
3904 struct fb_info_aty *info;
3906 for (m64_num = 0; m64_num < mach64_count; m64_num++) {
3907 if (!phys_vmembase[m64_num] || !phys_size[m64_num] ||
3908 !phys_guiregbase[m64_num]) {
3909 printk(" phys_*[%d] parameters not set => returning early. \n",
3910 m64_num);
3911 continue;
3914 info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
3915 if (!info) {
3916 printk("atyfb_init: can't alloc fb_info_aty\n");
3917 return -ENOMEM;
3919 memset(info, 0, sizeof(struct fb_info_aty));
3922 * Map the video memory (physical address given) to somewhere in the
3923 * kernel address space.
3925 info->frame_buffer = ioremap(phys_vmembase[m64_num], phys_size[m64_num]);
3926 info->frame_buffer_phys = info->frame_buffer; /* Fake! */
3927 info->ati_regbase = ioremap(phys_guiregbase[m64_num], 0x10000)+0xFC00ul;
3928 info->ati_regbase_phys = info->ati_regbase; /* Fake! */
3930 aty_st_le32(CLOCK_CNTL, 0x12345678, info);
3931 clock_r = aty_ld_le32(CLOCK_CNTL, info);
3933 switch (clock_r & 0x003F) {
3934 case 0x12:
3935 info->clk_wr_offset = 3; /* */
3936 break;
3937 case 0x34:
3938 info->clk_wr_offset = 2; /* Medusa ST-IO ISA Adapter etc. */
3939 break;
3940 case 0x16:
3941 info->clk_wr_offset = 1; /* */
3942 break;
3943 case 0x38:
3944 info->clk_wr_offset = 0; /* Panther 1 ISA Adapter (Gerald) */
3945 break;
3948 if (!aty_init(info, "ISA bus")) {
3949 kfree(info);
3950 /* This is insufficient! kernel_map has added two large chunks!! */
3951 return -ENXIO;
3954 #endif /* CONFIG_ATARI */
3955 return 0;
3958 #ifdef CONFIG_FB_OF
3959 void __init atyfb_of_init(struct device_node *dp)
3961 unsigned long addr;
3962 u8 bus, devfn;
3963 u16 cmd;
3964 struct fb_info_aty *info;
3965 int i;
3967 switch (dp->n_addrs) {
3968 case 1:
3969 case 2:
3970 case 3:
3971 addr = dp->addrs[0].address;
3972 break;
3973 case 4:
3974 addr = dp->addrs[1].address;
3975 break;
3976 default:
3977 printk("Warning: got %d adresses for ATY:\n", dp->n_addrs);
3978 for (i = 0; i < dp->n_addrs; i++)
3979 printk(" %08x-%08x", dp->addrs[i].address,
3980 dp->addrs[i].address+dp->addrs[i].size-1);
3981 if (dp->n_addrs)
3982 printk("\n");
3983 return;
3986 info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
3987 if (!info) {
3988 printk("atyfb_of_init: can't alloc fb_info_aty\n");
3989 return;
3991 memset(info, 0, sizeof(struct fb_info_aty));
3993 info->ati_regbase_phys = 0x7ff000+addr;
3994 info->ati_regbase = (unsigned long)ioremap(info->ati_regbase_phys,
3995 0x1000);
3997 if(! info->ati_regbase) {
3998 printk("atyfb_of_init: ioremap() returned NULL\n");
3999 kfree(info);
4000 return;
4003 info->ati_regbase_phys += 0xc00;
4004 info->ati_regbase += 0xc00;
4006 /* enable memory-space accesses using config-space command register */
4007 if (pci_device_loc(dp, &bus, &devfn) == 0) {
4008 pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd);
4009 if (cmd != 0xffff) {
4010 cmd |= PCI_COMMAND_MEMORY;
4011 pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
4015 #ifdef __BIG_ENDIAN
4016 /* Use the big-endian aperture */
4017 addr += 0x800000;
4018 #endif
4020 /* Map in frame buffer */
4021 info->frame_buffer_phys = addr;
4022 info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
4024 if(! info->frame_buffer) {
4025 printk("atyfb_of_init: ioremap() returned NULL\n");
4026 kfree(info);
4027 return;
4030 if (!aty_init(info, dp->full_name)) {
4031 kfree(info);
4032 return;
4035 #ifdef CONFIG_FB_COMPAT_XPMAC
4036 if (!console_fb_info)
4037 console_fb_info = &info->fb_info;
4038 #endif /* CONFIG_FB_COMPAT_XPMAC */
4040 #endif /* CONFIG_FB_OF */
4043 #ifndef MODULE
4044 int __init atyfb_setup(char *options)
4046 char *this_opt;
4048 if (!options || !*options)
4049 return 0;
4051 for (this_opt = strtok(options, ","); this_opt;
4052 this_opt = strtok(NULL, ",")) {
4053 if (!strncmp(this_opt, "font:", 5)) {
4054 char *p;
4055 int i;
4057 p = this_opt + 5;
4058 for (i = 0; i < sizeof(fontname) - 1; i++)
4059 if (!*p || *p == ' ' || *p == ',')
4060 break;
4061 memcpy(fontname, this_opt + 5, i);
4062 fontname[i] = 0;
4063 } else if (!strncmp(this_opt, "noblink", 7)) {
4064 curblink = 0;
4065 } else if (!strncmp(this_opt, "noaccel", 7)) {
4066 noaccel = 1;
4067 } else if (!strncmp(this_opt, "vram:", 5))
4068 default_vram = simple_strtoul(this_opt+5, NULL, 0);
4069 else if (!strncmp(this_opt, "pll:", 4))
4070 default_pll = simple_strtoul(this_opt+4, NULL, 0);
4071 else if (!strncmp(this_opt, "mclk:", 5))
4072 default_mclk = simple_strtoul(this_opt+5, NULL, 0);
4073 #if defined(CONFIG_PPC)
4074 else if (!strncmp(this_opt, "vmode:", 6)) {
4075 unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
4076 if (vmode > 0 && vmode <= VMODE_MAX)
4077 default_vmode = vmode;
4078 } else if (!strncmp(this_opt, "cmode:", 6)) {
4079 unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0);
4080 switch (cmode) {
4081 case 0:
4082 case 8:
4083 default_cmode = CMODE_8;
4084 break;
4085 case 15:
4086 case 16:
4087 default_cmode = CMODE_16;
4088 break;
4089 case 24:
4090 case 32:
4091 default_cmode = CMODE_32;
4092 break;
4095 #endif
4096 #ifdef CONFIG_ATARI
4098 * Why do we need this silly Mach64 argument?
4099 * We are already here because of mach64= so its redundant.
4101 else if (MACH_IS_ATARI && (!strncmp(this_opt, "Mach64:", 7))) {
4102 static unsigned char m64_num;
4103 static char mach64_str[80];
4104 strncpy(mach64_str, this_opt+7, 80);
4105 if (!store_video_par(mach64_str, m64_num)) {
4106 m64_num++;
4107 mach64_count = m64_num;
4110 #endif
4111 else
4112 mode_option = this_opt;
4114 return 0;
4116 #endif /* !MODULE */
4118 #ifdef CONFIG_ATARI
4119 static int __init store_video_par(char *video_str, unsigned char m64_num)
4121 char *p;
4122 unsigned long vmembase, size, guiregbase;
4124 printk("store_video_par() '%s' \n", video_str);
4126 if (!(p = strtoke(video_str, ";")) || !*p)
4127 goto mach64_invalid;
4128 vmembase = simple_strtoul(p, NULL, 0);
4129 if (!(p = strtoke(NULL, ";")) || !*p)
4130 goto mach64_invalid;
4131 size = simple_strtoul(p, NULL, 0);
4132 if (!(p = strtoke(NULL, ";")) || !*p)
4133 goto mach64_invalid;
4134 guiregbase = simple_strtoul(p, NULL, 0);
4136 phys_vmembase[m64_num] = vmembase;
4137 phys_size[m64_num] = size;
4138 phys_guiregbase[m64_num] = guiregbase;
4139 printk(" stored them all: $%08lX $%08lX $%08lX \n", vmembase, size,
4140 guiregbase);
4141 return 0;
4143 mach64_invalid:
4144 phys_vmembase[m64_num] = 0;
4145 return -1;
4148 static char __init *strtoke(char *s, const char *ct)
4150 static char *ssave = NULL;
4151 char *sbegin, *send;
4153 sbegin = s ? s : ssave;
4154 if (!sbegin)
4155 return NULL;
4156 if (*sbegin == '\0') {
4157 ssave = NULL;
4158 return NULL;
4160 send = strpbrk(sbegin, ct);
4161 if (send && *send != '\0')
4162 *send++ = '\0';
4163 ssave = send;
4164 return sbegin;
4166 #endif /* CONFIG_ATARI */
4168 static int atyfbcon_switch(int con, struct fb_info *fb)
4170 struct fb_info_aty *info = (struct fb_info_aty *)fb;
4171 struct atyfb_par par;
4173 /* Do we have to save the colormap? */
4174 if (fb_display[currcon].cmap.len)
4175 fb_get_cmap(&fb_display[currcon].cmap, 1, atyfb_getcolreg, fb);
4177 /* Erase HW Cursor */
4178 if (info->cursor)
4179 atyfb_cursor(&fb_display[currcon], CM_ERASE,
4180 info->cursor->pos.x, info->cursor->pos.y);
4182 currcon = con;
4184 atyfb_decode_var(&fb_display[con].var, &par, info);
4185 atyfb_set_par(&par, info);
4186 atyfb_set_disp(&fb_display[con], info, par.crtc.bpp,
4187 par.accel_flags & FB_ACCELF_TEXT);
4189 /* Install new colormap */
4190 do_install_cmap(con, fb);
4192 /* Install hw cursor */
4193 if (info->cursor) {
4194 aty_set_cursor_color(info, cursor_pixel_map, cursor_color_map,
4195 cursor_color_map, cursor_color_map);
4196 aty_set_cursor_shape(info);
4198 return 1;
4202 * Blank the display.
4205 static void atyfbcon_blank(int blank, struct fb_info *fb)
4207 struct fb_info_aty *info = (struct fb_info_aty *)fb;
4208 u8 gen_cntl;
4210 #if defined(CONFIG_PPC)
4211 if ((_machine == _MACH_Pmac) && blank)
4212 pmu_enable_backlight(0);
4213 #endif
4215 gen_cntl = aty_ld_8(CRTC_GEN_CNTL, info);
4216 if (blank > 0)
4217 switch (blank-1) {
4218 case VESA_NO_BLANKING:
4219 gen_cntl |= 0x40;
4220 break;
4221 case VESA_VSYNC_SUSPEND:
4222 gen_cntl |= 0x8;
4223 break;
4224 case VESA_HSYNC_SUSPEND:
4225 gen_cntl |= 0x4;
4226 break;
4227 case VESA_POWERDOWN:
4228 gen_cntl |= 0x4c;
4229 break;
4231 else
4232 gen_cntl &= ~(0x4c);
4233 aty_st_8(CRTC_GEN_CNTL, gen_cntl, info);
4235 #if defined(CONFIG_PPC)
4236 if ((_machine == _MACH_Pmac) && !blank)
4237 pmu_enable_backlight(1);
4238 #endif
4243 * Read a single color register and split it into
4244 * colors/transparent. Return != 0 for invalid regno.
4247 static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
4248 u_int *transp, struct fb_info *fb)
4250 struct fb_info_aty *info = (struct fb_info_aty *)fb;
4252 if (regno > 255)
4253 return 1;
4254 *red = (info->palette[regno].red<<8) | info->palette[regno].red;
4255 *green = (info->palette[regno].green<<8) | info->palette[regno].green;
4256 *blue = (info->palette[regno].blue<<8) | info->palette[regno].blue;
4257 *transp = 0;
4258 return 0;
4263 * Set a single color register. The values supplied are already
4264 * rounded down to the hardware's capabilities (according to the
4265 * entries in the var structure). Return != 0 for invalid regno.
4268 static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
4269 u_int transp, struct fb_info *fb)
4271 struct fb_info_aty *info = (struct fb_info_aty *)fb;
4272 int i, scale;
4274 if (regno > 255)
4275 return 1;
4276 red >>= 8;
4277 green >>= 8;
4278 blue >>= 8;
4279 info->palette[regno].red = red;
4280 info->palette[regno].green = green;
4281 info->palette[regno].blue = blue;
4282 i = aty_ld_8(DAC_CNTL, info) & 0xfc;
4283 if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == GV_CHIP_ID ||
4284 Gx == GW_CHIP_ID || Gx == GZ_CHIP_ID || Gx == LG_CHIP_ID ||
4285 Gx == GB_CHIP_ID || Gx == GD_CHIP_ID || Gx == GI_CHIP_ID ||
4286 Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID)
4287 i |= 0x2; /*DAC_CNTL|0x2 turns off the extra brightness for gt*/
4288 aty_st_8(DAC_CNTL, i, info);
4289 aty_st_8(DAC_MASK, 0xff, info);
4290 eieio();
4291 scale = ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID) &&
4292 (info->current_par.crtc.bpp == 16)) ? 3 : 0;
4293 info->aty_cmap_regs->windex = regno << scale;
4294 eieio();
4295 info->aty_cmap_regs->lut = red;
4296 eieio();
4297 info->aty_cmap_regs->lut = green;
4298 eieio();
4299 info->aty_cmap_regs->lut = blue;
4300 eieio();
4301 if (regno < 16)
4302 switch (info->current_par.crtc.bpp) {
4303 #ifdef FBCON_HAS_CFB16
4304 case 16:
4305 info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) |
4306 regno;
4307 break;
4308 #endif
4309 #ifdef FBCON_HAS_CFB24
4310 case 24:
4311 info->fbcon_cmap.cfb24[regno] = (regno << 16) | (regno << 8) |
4312 regno;
4313 break;
4314 #endif
4315 #ifdef FBCON_HAS_CFB32
4316 case 32:
4317 i = (regno << 8) | regno;
4318 info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
4319 break;
4320 #endif
4322 return 0;
4326 static void do_install_cmap(int con, struct fb_info *info)
4328 if (con != currcon)
4329 return;
4330 if (fb_display[con].cmap.len)
4331 fb_set_cmap(&fb_display[con].cmap, 1, atyfb_setcolreg, info);
4332 else {
4333 int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
4334 fb_set_cmap(fb_default_cmap(size), 1, atyfb_setcolreg, info);
4340 * Accelerated functions
4343 static inline void draw_rect(s16 x, s16 y, u16 width, u16 height,
4344 struct fb_info_aty *info)
4346 /* perform rectangle fill */
4347 wait_for_fifo(2, info);
4348 aty_st_le32(DST_Y_X, (x << 16) | y, info);
4349 aty_st_le32(DST_HEIGHT_WIDTH, (width << 16) | height, info);
4350 info->blitter_may_be_busy = 1;
4353 static inline void aty_rectcopy(int srcx, int srcy, int dstx, int dsty,
4354 u_int width, u_int height,
4355 struct fb_info_aty *info)
4357 u32 direction = DST_LAST_PEL;
4358 u32 pitch_value;
4360 if (!width || !height)
4361 return;
4363 pitch_value = info->current_par.crtc.vxres;
4364 if (info->current_par.crtc.bpp == 24) {
4365 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
4366 /* horizontal coordinates and widths must be adjusted */
4367 pitch_value *= 3;
4368 srcx *= 3;
4369 dstx *= 3;
4370 width *= 3;
4373 if (srcy < dsty) {
4374 dsty += height - 1;
4375 srcy += height - 1;
4376 } else
4377 direction |= DST_Y_TOP_TO_BOTTOM;
4379 if (srcx < dstx) {
4380 dstx += width - 1;
4381 srcx += width - 1;
4382 } else
4383 direction |= DST_X_LEFT_TO_RIGHT;
4385 wait_for_fifo(4, info);
4386 aty_st_le32(DP_SRC, FRGD_SRC_BLIT, info);
4387 aty_st_le32(SRC_Y_X, (srcx << 16) | srcy, info);
4388 aty_st_le32(SRC_HEIGHT1_WIDTH1, (width << 16) | height, info);
4389 aty_st_le32(DST_CNTL, direction, info);
4390 draw_rect(dstx, dsty, width, height, info);
4393 static inline void aty_rectfill(int dstx, int dsty, u_int width, u_int height,
4394 u_int color, struct fb_info_aty *info)
4396 if (!width || !height)
4397 return;
4399 if (info->current_par.crtc.bpp == 24) {
4400 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
4401 /* horizontal coordinates and widths must be adjusted */
4402 dstx *= 3;
4403 width *= 3;
4406 wait_for_fifo(3, info);
4407 aty_st_le32(DP_FRGD_CLR, color, info);
4408 aty_st_le32(DP_SRC, BKGD_SRC_BKGD_CLR | FRGD_SRC_FRGD_CLR | MONO_SRC_ONE,
4409 info);
4410 aty_st_le32(DST_CNTL, DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM |
4411 DST_X_LEFT_TO_RIGHT, info);
4412 draw_rect(dstx, dsty, width, height, info);
4416 * Update the `var' structure (called by fbcon.c)
4419 static int atyfbcon_updatevar(int con, struct fb_info *fb)
4421 struct fb_info_aty *info = (struct fb_info_aty *)fb;
4422 struct atyfb_par *par = &info->current_par;
4423 struct display *p = &fb_display[con];
4424 struct vc_data *conp = p->conp;
4425 u32 yres, yoffset, sy, height;
4427 yres = ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1;
4428 yoffset = fb_display[con].var.yoffset;
4430 sy = (conp->vc_rows + p->yscroll) * fontheight(p);
4431 height = yres - conp->vc_rows * fontheight(p);
4433 if (height && (yoffset + yres > sy)) {
4434 u32 xres, xoffset;
4435 u32 bgx;
4437 xres = (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8;
4438 xoffset = fb_display[con].var.xoffset;
4441 bgx = attr_bgcol_ec(p, conp);
4442 bgx |= (bgx << 8);
4443 bgx |= (bgx << 16);
4445 if (sy + height > par->crtc.vyres) {
4446 wait_for_fifo(1, info);
4447 aty_st_le32(SC_BOTTOM, sy + height - 1, info);
4449 aty_rectfill(xoffset, sy, xres, height, bgx, info);
4452 if (info->cursor && (yoffset + yres <= sy))
4453 atyfb_cursor(p, CM_ERASE, info->cursor->pos.x, info->cursor->pos.y);
4455 info->current_par.crtc.yoffset = yoffset;
4456 set_off_pitch(&info->current_par, info);
4457 return 0;
4461 * Text console acceleration
4464 static void fbcon_aty_bmove(struct display *p, int sy, int sx, int dy, int dx,
4465 int height, int width)
4467 #ifdef __sparc__
4468 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4470 if (fb->mmaped && (!fb->fb_info.display_fg
4471 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4472 return;
4473 #endif
4475 sx *= fontwidth(p);
4476 sy *= fontheight(p);
4477 dx *= fontwidth(p);
4478 dy *= fontheight(p);
4479 width *= fontwidth(p);
4480 height *= fontheight(p);
4482 aty_rectcopy(sx, sy, dx, dy, width, height,
4483 (struct fb_info_aty *)p->fb_info);
4486 static void fbcon_aty_clear(struct vc_data *conp, struct display *p, int sy,
4487 int sx, int height, int width)
4489 u32 bgx;
4490 #ifdef __sparc__
4491 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4493 if (fb->mmaped && (!fb->fb_info.display_fg
4494 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4495 return;
4496 #endif
4498 bgx = attr_bgcol_ec(p, conp);
4499 bgx |= (bgx << 8);
4500 bgx |= (bgx << 16);
4502 sx *= fontwidth(p);
4503 sy *= fontheight(p);
4504 width *= fontwidth(p);
4505 height *= fontheight(p);
4507 aty_rectfill(sx, sy, width, height, bgx,
4508 (struct fb_info_aty *)p->fb_info);
4511 #ifdef FBCON_HAS_CFB8
4512 static void fbcon_aty8_putc(struct vc_data *conp, struct display *p, int c,
4513 int yy, int xx)
4515 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4517 #ifdef __sparc__
4518 if (fb->mmaped && (!fb->fb_info.display_fg
4519 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4520 return;
4521 #endif
4523 if (fb->blitter_may_be_busy)
4524 wait_for_idle((struct fb_info_aty *)p->fb_info);
4525 fbcon_cfb8_putc(conp, p, c, yy, xx);
4528 static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p,
4529 const unsigned short *s, int count, int yy,
4530 int xx)
4532 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4534 #ifdef __sparc__
4535 if (fb->mmaped && (!fb->fb_info.display_fg
4536 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4537 return;
4538 #endif
4540 if (fb->blitter_may_be_busy)
4541 wait_for_idle((struct fb_info_aty *)p->fb_info);
4542 fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
4545 static void fbcon_aty8_clear_margins(struct vc_data *conp, struct display *p,
4546 int bottom_only)
4548 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4550 #ifdef __sparc__
4551 if (fb->mmaped && (!fb->fb_info.display_fg
4552 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4553 return;
4554 #endif
4556 if (fb->blitter_may_be_busy)
4557 wait_for_idle((struct fb_info_aty *)p->fb_info);
4558 fbcon_cfb8_clear_margins(conp, p, bottom_only);
4561 static struct display_switch fbcon_aty8 = {
4562 fbcon_cfb8_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty8_putc,
4563 fbcon_aty8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_aty8_clear_margins,
4564 FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4566 #endif
4568 #ifdef FBCON_HAS_CFB16
4569 static void fbcon_aty16_putc(struct vc_data *conp, struct display *p, int c,
4570 int yy, int xx)
4572 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4574 #ifdef __sparc__
4575 if (fb->mmaped && (!fb->fb_info.display_fg
4576 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4577 return;
4578 #endif
4580 if (fb->blitter_may_be_busy)
4581 wait_for_idle((struct fb_info_aty *)p->fb_info);
4582 fbcon_cfb16_putc(conp, p, c, yy, xx);
4585 static void fbcon_aty16_putcs(struct vc_data *conp, struct display *p,
4586 const unsigned short *s, int count, int yy,
4587 int xx)
4589 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4591 #ifdef __sparc__
4592 if (fb->mmaped && (!fb->fb_info.display_fg
4593 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4594 return;
4595 #endif
4597 if (fb->blitter_may_be_busy)
4598 wait_for_idle((struct fb_info_aty *)p->fb_info);
4599 fbcon_cfb16_putcs(conp, p, s, count, yy, xx);
4602 static void fbcon_aty16_clear_margins(struct vc_data *conp, struct display *p,
4603 int bottom_only)
4605 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4607 #ifdef __sparc__
4608 if (fb->mmaped && (!fb->fb_info.display_fg
4609 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4610 return;
4611 #endif
4613 if (fb->blitter_may_be_busy)
4614 wait_for_idle((struct fb_info_aty *)p->fb_info);
4615 fbcon_cfb16_clear_margins(conp, p, bottom_only);
4618 static struct display_switch fbcon_aty16 = {
4619 fbcon_cfb16_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty16_putc,
4620 fbcon_aty16_putcs, fbcon_cfb16_revc, NULL, NULL, fbcon_aty16_clear_margins,
4621 FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4623 #endif
4625 #ifdef FBCON_HAS_CFB24
4626 static void fbcon_aty24_putc(struct vc_data *conp, struct display *p, int c,
4627 int yy, int xx)
4629 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4631 #ifdef __sparc__
4632 if (fb->mmaped && (!fb->fb_info.display_fg
4633 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4634 return;
4635 #endif
4637 if (fb->blitter_may_be_busy)
4638 wait_for_idle((struct fb_info_aty *)p->fb_info);
4639 fbcon_cfb24_putc(conp, p, c, yy, xx);
4642 static void fbcon_aty24_putcs(struct vc_data *conp, struct display *p,
4643 const unsigned short *s, int count, int yy,
4644 int xx)
4646 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4648 #ifdef __sparc__
4649 if (fb->mmaped && (!fb->fb_info.display_fg
4650 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4651 return;
4652 #endif
4654 if (fb->blitter_may_be_busy)
4655 wait_for_idle((struct fb_info_aty *)p->fb_info);
4656 fbcon_cfb24_putcs(conp, p, s, count, yy, xx);
4659 static void fbcon_aty24_clear_margins(struct vc_data *conp, struct display *p,
4660 int bottom_only)
4662 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4664 #ifdef __sparc__
4665 if (fb->mmaped && (!fb->fb_info.display_fg
4666 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4667 return;
4668 #endif
4670 if (fb->blitter_may_be_busy)
4671 wait_for_idle((struct fb_info_aty *)p->fb_info);
4672 fbcon_cfb24_clear_margins(conp, p, bottom_only);
4675 static struct display_switch fbcon_aty24 = {
4676 fbcon_cfb24_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty24_putc,
4677 fbcon_aty24_putcs, fbcon_cfb24_revc, NULL, NULL, fbcon_aty24_clear_margins,
4678 FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4680 #endif
4682 #ifdef FBCON_HAS_CFB32
4683 static void fbcon_aty32_putc(struct vc_data *conp, struct display *p, int c,
4684 int yy, int xx)
4686 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4688 #ifdef __sparc__
4689 if (fb->mmaped && (!fb->fb_info.display_fg
4690 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4691 return;
4692 #endif
4694 if (fb->blitter_may_be_busy)
4695 wait_for_idle((struct fb_info_aty *)p->fb_info);
4696 fbcon_cfb32_putc(conp, p, c, yy, xx);
4699 static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p,
4700 const unsigned short *s, int count, int yy,
4701 int xx)
4703 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4705 #ifdef __sparc__
4706 if (fb->mmaped && (!fb->fb_info.display_fg
4707 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4708 return;
4709 #endif
4711 if (fb->blitter_may_be_busy)
4712 wait_for_idle((struct fb_info_aty *)p->fb_info);
4713 fbcon_cfb32_putcs(conp, p, s, count, yy, xx);
4716 static void fbcon_aty32_clear_margins(struct vc_data *conp, struct display *p,
4717 int bottom_only)
4719 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4721 #ifdef __sparc__
4722 if (fb->mmaped && (!fb->fb_info.display_fg
4723 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4724 return;
4725 #endif
4727 if (fb->blitter_may_be_busy)
4728 wait_for_idle((struct fb_info_aty *)p->fb_info);
4729 fbcon_cfb32_clear_margins(conp, p, bottom_only);
4732 static struct display_switch fbcon_aty32 = {
4733 fbcon_cfb32_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty32_putc,
4734 fbcon_aty32_putcs, fbcon_cfb32_revc, NULL, NULL, fbcon_aty32_clear_margins,
4735 FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4737 #endif
4739 #ifdef MODULE
4740 int __init init_module(void)
4742 atyfb_init();
4743 return fb_list ? 0 : -ENXIO;
4746 void cleanup_module(void)
4748 while (fb_list) {
4749 struct fb_info_aty *info = fb_list;
4750 fb_list = info->next;
4752 unregister_framebuffer(&info->fb_info);
4754 #ifndef __sparc__
4755 if (info->ati_regbase)
4756 iounmap((void *)info->ati_regbase);
4757 if (info->frame_buffer)
4758 iounmap((void *)info->frame_buffer);
4759 #ifdef __BIG_ENDIAN
4760 if (info->cursor && info->cursor->ram)
4761 iounmap(info->cursor->ram);
4762 #endif
4763 #endif
4765 if (info->cursor) {
4766 if (info->cursor->timer)
4767 kfree(info->cursor->timer);
4768 kfree(info->cursor);
4770 #ifdef __sparc__
4771 if (info->mmap_map)
4772 kfree(info->mmap_map);
4773 #endif
4774 kfree(info);
4778 #endif