Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / drivers / video / atyfb.c
blobfb3b09bc95c9cae1245777c51ea1b62b4cefd9a5
1 /* $Id: atyfb.c,v 1.147 2000/08/29 07:01:56 davem Exp $
2 * linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
4 * Copyright (C) 1997-1998 Geert Uytterhoeven
5 * Copyright (C) 1998 Bernd Harries
6 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
8 * This driver is partly based on the PowerMac console driver:
10 * Copyright (C) 1996 Paul Mackerras
12 * and on the PowerMac ATI/mach64 display driver:
14 * Copyright (C) 1997 Michael AK Tesch
16 * with work by Jon Howell
17 * Harry AC Eaton
18 * Anthony Tong <atong@uiuc.edu>
20 * This file is subject to the terms and conditions of the GNU General Public
21 * License. See the file COPYING in the main directory of this archive for
22 * more details.
24 * Many thanks to Nitya from ATI devrel for support and patience !
27 /******************************************************************************
29 TODO:
31 - cursor support on all cards and all ramdacs.
32 - cursor parameters controlable via ioctl()s.
33 - guess PLL and MCLK based on the original PLL register values initialized
34 by the BIOS or Open Firmware (if they are initialized).
36 (Anyone to help with this?)
38 ******************************************************************************/
41 #include <linux/config.h>
42 #include <linux/module.h>
43 #include <linux/kernel.h>
44 #include <linux/errno.h>
45 #include <linux/string.h>
46 #include <linux/mm.h>
47 #include <linux/tty.h>
48 #include <linux/malloc.h>
49 #include <linux/vmalloc.h>
50 #include <linux/delay.h>
51 #include <linux/interrupt.h>
52 #include <linux/fb.h>
53 #include <linux/selection.h>
54 #include <linux/console.h>
55 #include <linux/init.h>
56 #include <linux/pci.h>
57 #include <linux/kd.h>
58 #include <linux/vt_kern.h>
60 #ifdef CONFIG_FB_COMPAT_XPMAC
61 #include <asm/vc_ioctl.h>
62 #endif
64 #include <asm/io.h>
66 #ifdef __powerpc__
67 #include <linux/adb.h>
68 #include <asm/prom.h>
69 #include <asm/pci-bridge.h>
70 #include <video/macmodes.h>
71 #endif
72 #ifdef CONFIG_ADB_PMU
73 #include <linux/pmu.h>
74 #endif
75 #ifdef CONFIG_NVRAM
76 #include <linux/nvram.h>
77 #endif
78 #ifdef CONFIG_PMAC_BACKLIGHT
79 #include <asm/backlight.h>
80 #endif
82 #ifdef __sparc__
83 #include <asm/pbm.h>
84 #include <asm/fbio.h>
85 #endif
86 #include <asm/uaccess.h>
88 #include <video/fbcon.h>
89 #include <video/fbcon-cfb8.h>
90 #include <video/fbcon-cfb16.h>
91 #include <video/fbcon-cfb24.h>
92 #include <video/fbcon-cfb32.h>
94 #include "aty.h"
98 * Debug flags.
100 #undef DEBUG
102 /* Definitions for the ICS 2595 == ATI 18818_1 Clockchip */
104 #define REF_FREQ_2595 1432 /* 14.33 MHz (exact 14.31818) */
105 #define REF_DIV_2595 46 /* really 43 on ICS 2595 !!! */
106 /* ohne Prescaler */
107 #define MAX_FREQ_2595 15938 /* 159.38 MHz (really 170.486) */
108 #define MIN_FREQ_2595 8000 /* 80.00 MHz ( 85.565) */
109 /* mit Prescaler 2, 4, 8 */
110 #define ABS_MIN_FREQ_2595 1000 /* 10.00 MHz (really 10.697) */
111 #define N_ADJ_2595 257
113 #define STOP_BITS_2595 0x1800
116 #define MIN_N_408 2
118 #define MIN_N_1703 6
120 #define MIN_M 2
121 #define MAX_M 30
122 #define MIN_N 35
123 #define MAX_N 255-8
126 /* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */
127 /* - must be large enough to catch all GUI-Regs */
128 /* - must be aligned to a PAGE boundary */
129 #define GUI_RESERVE (1 * PAGE_SIZE)
132 /* FIXME: remove the FAIL definition */
133 #define FAIL(x) do { printk(x "\n"); return -EINVAL; } while (0)
137 * Elements of the Hardware specific atyfb_par structure
140 struct crtc {
141 u32 vxres;
142 u32 vyres;
143 u32 xoffset;
144 u32 yoffset;
145 u32 bpp;
146 u32 h_tot_disp;
147 u32 h_sync_strt_wid;
148 u32 v_tot_disp;
149 u32 v_sync_strt_wid;
150 u32 off_pitch;
151 u32 gen_cntl;
152 u32 dp_pix_width; /* acceleration */
153 u32 dp_chain_mask; /* acceleration */
156 struct pll_gx {
157 u8 m;
158 u8 n;
161 struct pll_18818
163 u32 program_bits;
164 u32 locationAddr;
165 u32 period_in_ps;
166 u32 post_divider;
169 struct pll_ct {
170 u8 pll_ref_div;
171 u8 pll_gen_cntl;
172 u8 mclk_fb_div;
173 u8 pll_vclk_cntl;
174 u8 vclk_post_div;
175 u8 vclk_fb_div;
176 u8 pll_ext_cntl;
177 u32 dsp_config; /* Mach64 GTB DSP */
178 u32 dsp_on_off; /* Mach64 GTB DSP */
179 u8 mclk_post_div_real;
180 u8 vclk_post_div_real;
185 * The Hardware parameters for each card
188 struct atyfb_par {
189 struct crtc crtc;
190 union {
191 struct pll_gx gx;
192 struct pll_ct ct;
193 struct pll_18818 ics2595;
194 } pll;
195 u32 accel_flags;
198 struct aty_cmap_regs {
199 u8 windex;
200 u8 lut;
201 u8 mask;
202 u8 rindex;
203 u8 cntl;
206 struct pci_mmap_map {
207 unsigned long voff;
208 unsigned long poff;
209 unsigned long size;
210 unsigned long prot_flag;
211 unsigned long prot_mask;
214 #define DEFAULT_CURSOR_BLINK_RATE (20)
215 #define CURSOR_DRAW_DELAY (2)
217 struct aty_cursor {
218 int enable;
219 int on;
220 int vbl_cnt;
221 int blink_rate;
222 u32 offset;
223 struct {
224 u16 x, y;
225 } pos, hot, size;
226 u32 color[2];
227 u8 bits[8][64];
228 u8 mask[8][64];
229 u8 *ram;
230 struct timer_list *timer;
233 struct fb_info_aty {
234 struct fb_info fb_info;
235 struct fb_info_aty *next;
236 unsigned long ati_regbase_phys;
237 unsigned long ati_regbase;
238 unsigned long frame_buffer_phys;
239 unsigned long frame_buffer;
240 unsigned long clk_wr_offset;
241 struct pci_mmap_map *mmap_map;
242 struct aty_cursor *cursor;
243 struct aty_cmap_regs *aty_cmap_regs;
244 struct { u8 red, green, blue, pad; } palette[256];
245 struct atyfb_par default_par;
246 struct atyfb_par current_par;
247 u32 total_vram;
248 u32 ref_clk_per;
249 u32 pll_per;
250 u32 mclk_per;
251 u16 chip_type;
252 #define Gx info->chip_type
253 u8 chip_rev;
254 #define Rev info->chip_rev
255 u8 bus_type;
256 u8 ram_type;
257 u8 dac_type;
258 u8 dac_subtype;
259 u8 clk_type;
260 u8 mem_refresh_rate;
261 struct display disp;
262 struct display_switch dispsw;
263 union {
264 #ifdef FBCON_HAS_CFB16
265 u16 cfb16[16];
266 #endif
267 #ifdef FBCON_HAS_CFB24
268 u32 cfb24[16];
269 #endif
270 #ifdef FBCON_HAS_CFB32
271 u32 cfb32[16];
272 #endif
273 } fbcon_cmap;
274 u8 blitter_may_be_busy;
275 #ifdef __sparc__
276 u8 mmaped;
277 int open;
278 int vtconsole;
279 int consolecnt;
280 #endif
281 #ifdef CONFIG_PMAC_PBOOK
282 unsigned char *save_framebuffer;
283 unsigned long save_pll[64];
284 #endif
287 #ifdef CONFIG_PMAC_PBOOK
288 int aty_sleep_notify(struct pmu_sleep_notifier *self, int when);
289 static struct pmu_sleep_notifier aty_sleep_notifier = {
290 aty_sleep_notify, SLEEP_LEVEL_VIDEO,
292 static struct fb_info_aty* first_display = NULL;
293 #endif
295 #ifdef CONFIG_PMAC_BACKLIGHT
296 static int aty_set_backlight_enable(int on, int level, void* data);
297 static int aty_set_backlight_level(int level, void* data);
299 static struct backlight_controller aty_backlight_controller = {
300 aty_set_backlight_enable,
301 aty_set_backlight_level
303 #endif /* CONFIG_PMAC_BACKLIGHT */
306 * Frame buffer device API
309 static int atyfb_open(struct fb_info *info, int user);
310 static int atyfb_release(struct fb_info *info, int user);
311 static int atyfb_get_fix(struct fb_fix_screeninfo *fix, int con,
312 struct fb_info *fb);
313 static int atyfb_get_var(struct fb_var_screeninfo *var, int con,
314 struct fb_info *fb);
315 static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
316 struct fb_info *fb);
317 static int atyfb_pan_display(struct fb_var_screeninfo *var, int con,
318 struct fb_info *fb);
319 static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
320 struct fb_info *info);
321 static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
322 struct fb_info *info);
323 static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
324 u_long arg, int con, struct fb_info *info);
325 #ifdef __sparc__
326 static int atyfb_mmap(struct fb_info *info, struct file *file,
327 struct vm_area_struct *vma);
328 #endif
329 static int atyfb_rasterimg(struct fb_info *info, int start);
333 * Interface to the low level console driver
336 static int atyfbcon_switch(int con, struct fb_info *fb);
337 static int atyfbcon_updatevar(int con, struct fb_info *fb);
338 static void atyfbcon_blank(int blank, struct fb_info *fb);
342 * Text console acceleration
345 static void fbcon_aty_bmove(struct display *p, int sy, int sx, int dy, int dx,
346 int height, int width);
347 static void fbcon_aty_clear(struct vc_data *conp, struct display *p, int sy,
348 int sx, int height, int width);
349 #ifdef FBCON_HAS_CFB8
350 static struct display_switch fbcon_aty8;
351 static void fbcon_aty8_putc(struct vc_data *conp, struct display *p, int c,
352 int yy, int xx);
353 static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p,
354 const unsigned short *s, int count, int yy,
355 int xx);
356 #endif
357 #ifdef FBCON_HAS_CFB16
358 static struct display_switch fbcon_aty16;
359 static void fbcon_aty16_putc(struct vc_data *conp, struct display *p, int c,
360 int yy, int xx);
361 static void fbcon_aty16_putcs(struct vc_data *conp, struct display *p,
362 const unsigned short *s, int count, int yy,
363 int xx);
364 #endif
365 #ifdef FBCON_HAS_CFB24
366 static struct display_switch fbcon_aty24;
367 static void fbcon_aty24_putc(struct vc_data *conp, struct display *p, int c,
368 int yy, int xx);
369 static void fbcon_aty24_putcs(struct vc_data *conp, struct display *p,
370 const unsigned short *s, int count, int yy,
371 int xx);
372 #endif
373 #ifdef FBCON_HAS_CFB32
374 static struct display_switch fbcon_aty32;
375 static void fbcon_aty32_putc(struct vc_data *conp, struct display *p, int c,
376 int yy, int xx);
377 static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p,
378 const unsigned short *s, int count, int yy,
379 int xx);
380 #endif
384 * Internal routines
387 static int aty_init(struct fb_info_aty *info, const char *name);
388 static struct aty_cursor *aty_init_cursor(struct fb_info_aty *fb);
389 #ifdef CONFIG_ATARI
390 static int store_video_par(char *videopar, unsigned char m64_num);
391 static char *strtoke(char *s, const char *ct);
392 #endif
394 static void reset_engine(const struct fb_info_aty *info);
395 static void init_engine(const struct atyfb_par *par, struct fb_info_aty *info);
397 static void aty_st_514(int offset, u8 val, const struct fb_info_aty *info);
398 static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info);
399 static u8 aty_ld_pll(int offset, const struct fb_info_aty *info);
400 static void aty_set_crtc(const struct fb_info_aty *info,
401 const struct crtc *crtc);
402 static int aty_var_to_crtc(const struct fb_info_aty *info,
403 const struct fb_var_screeninfo *var,
404 struct crtc *crtc);
405 static void aty_set_dac_514(const struct fb_info_aty *info, u32 bpp);
406 static int aty_crtc_to_var(const struct crtc *crtc,
407 struct fb_var_screeninfo *var);
408 static void aty_set_pll_gx(const struct fb_info_aty *info,
409 const struct pll_gx *pll);
411 static int aty_set_dac_ATI68860_B(const struct fb_info_aty *info, u32 bpp,
412 u32 AccelMode);
413 static int aty_set_dac_ATT21C498(const struct fb_info_aty *info,
414 const struct pll_18818 *pll, u32 bpp);
415 void aty_dac_waste4(const struct fb_info_aty *info);
417 static int aty_var_to_pll_18818(u32 period_in_ps, struct pll_18818 *pll);
418 static u32 aty_pll_18818_to_var(const struct pll_18818 *pll);
419 static void aty_set_pll18818(const struct fb_info_aty *info,
420 const struct pll_18818 *pll);
422 static void aty_StrobeClock(const struct fb_info_aty *info);
424 static void aty_ICS2595_put1bit(u8 data, const struct fb_info_aty *info);
426 static int aty_var_to_pll_408(u32 period_in_ps, struct pll_18818 *pll);
427 static u32 aty_pll_408_to_var(const struct pll_18818 *pll);
428 static void aty_set_pll_408(const struct fb_info_aty *info,
429 const struct pll_18818 *pll);
431 static int aty_var_to_pll_1703(u32 period_in_ps, struct pll_18818 *pll);
432 static u32 aty_pll_1703_to_var(const struct pll_18818 *pll);
433 static void aty_set_pll_1703(const struct fb_info_aty *info,
434 const struct pll_18818 *pll);
436 static int aty_var_to_pll_8398(u32 period_in_ps, struct pll_18818 *pll);
437 static u32 aty_pll_8398_to_var(const struct pll_18818 *pll);
438 static void aty_set_pll_8398(const struct fb_info_aty *info,
439 const struct pll_18818 *pll);
441 static int aty_var_to_pll_514(u32 vclk_per, struct pll_gx *pll);
442 static u32 aty_pll_gx_to_var(const struct pll_gx *pll,
443 const struct fb_info_aty *info);
444 static void aty_set_pll_ct(const struct fb_info_aty *info,
445 const struct pll_ct *pll);
446 static int aty_valid_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
447 struct pll_ct *pll);
448 static int aty_dsp_gt(const struct fb_info_aty *info, u8 bpp,
449 struct pll_ct *pll);
450 static void aty_calc_pll_ct(const struct fb_info_aty *info,
451 struct pll_ct *pll);
452 static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
453 u8 bpp, struct pll_ct *pll);
454 static u32 aty_pll_ct_to_var(const struct pll_ct *pll,
455 const struct fb_info_aty *info);
456 static void atyfb_set_par(const struct atyfb_par *par,
457 struct fb_info_aty *info);
458 static int atyfb_decode_var(const struct fb_var_screeninfo *var,
459 struct atyfb_par *par,
460 const struct fb_info_aty *info);
461 static int atyfb_encode_var(struct fb_var_screeninfo *var,
462 const struct atyfb_par *par,
463 const struct fb_info_aty *info);
464 static void set_off_pitch(struct atyfb_par *par,
465 const struct fb_info_aty *info);
466 static int encode_fix(struct fb_fix_screeninfo *fix,
467 const struct atyfb_par *par,
468 const struct fb_info_aty *info);
469 static void atyfb_set_dispsw(struct display *disp, struct fb_info_aty *info,
470 int bpp, int accel);
471 static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
472 u_int *transp, struct fb_info *fb);
473 static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
474 u_int transp, struct fb_info *fb);
475 static void do_install_cmap(int con, struct fb_info *info);
476 #ifdef CONFIG_PPC
477 static int read_aty_sense(const struct fb_info_aty *info);
478 #endif
482 * Interface used by the world
485 int atyfb_init(void);
486 #ifndef MODULE
487 int atyfb_setup(char*);
488 #endif
490 static int currcon = 0;
492 static struct fb_ops atyfb_ops = {
493 owner: THIS_MODULE,
494 fb_open: atyfb_open,
495 fb_release: atyfb_release,
496 fb_get_fix: atyfb_get_fix,
497 fb_get_var: atyfb_get_var,
498 fb_set_var: atyfb_set_var,
499 fb_get_cmap: atyfb_get_cmap,
500 fb_set_cmap: atyfb_set_cmap,
501 fb_pan_display: atyfb_pan_display,
502 fb_ioctl: atyfb_ioctl,
503 #ifdef __sparc__
504 fb_mmap: atyfb_mmap,
505 #endif
506 fb_rasterimg: atyfb_rasterimg,
509 static char atyfb_name[16] = "ATY Mach64";
510 static char fontname[40] __initdata = { 0 };
511 static char curblink __initdata = 1;
512 static char noaccel __initdata = 0;
513 static u32 default_vram __initdata = 0;
514 static int default_pll __initdata = 0;
515 static int default_mclk __initdata = 0;
517 #ifndef MODULE
518 static const char *mode_option __initdata = NULL;
519 #endif
521 #ifdef CONFIG_PPC
522 #ifdef CONFIG_NVRAM_NOT_DEFINED
523 static int default_vmode __initdata = VMODE_NVRAM;
524 static int default_cmode __initdata = CMODE_NVRAM;
525 #else
526 static int default_vmode __initdata = VMODE_CHOOSE;
527 static int default_cmode __initdata = CMODE_CHOOSE;
528 #endif
529 #endif
531 #ifdef CONFIG_ATARI
532 static unsigned int mach64_count __initdata = 0;
533 static unsigned long phys_vmembase[FB_MAX] __initdata = { 0, };
534 static unsigned long phys_size[FB_MAX] __initdata = { 0, };
535 static unsigned long phys_guiregbase[FB_MAX] __initdata = { 0, };
536 #endif
539 static struct aty_features {
540 u16 pci_id;
541 u16 chip_type;
542 const char *name;
543 } aty_features[] __initdata = {
544 /* mach64GX family */
545 { 0x4758, 0x00d7, "mach64GX (ATI888GX00)" },
546 { 0x4358, 0x0057, "mach64CX (ATI888CX00)" },
548 /* mach64CT family */
549 { 0x4354, 0x4354, "mach64CT (ATI264CT)" },
550 { 0x4554, 0x4554, "mach64ET (ATI264ET)" },
552 /* mach64CT family / mach64VT class */
553 { 0x5654, 0x5654, "mach64VT (ATI264VT)" },
554 { 0x5655, 0x5655, "mach64VTB (ATI264VTB)" },
555 { 0x5656, 0x5656, "mach64VT4 (ATI264VT4)" },
557 /* mach64CT family / mach64GT (3D RAGE) class */
558 { 0x4c42, 0x4c42, "3D RAGE LT PRO (AGP)" },
559 { 0x4c44, 0x4c44, "3D RAGE LT PRO" },
560 { 0x4c47, 0x4c47, "3D RAGE LT-G" },
561 { 0x4c49, 0x4c49, "3D RAGE LT PRO" },
562 { 0x4c50, 0x4c50, "3D RAGE LT PRO" },
563 { 0x4c54, 0x4c54, "3D RAGE LT" },
564 { 0x4754, 0x4754, "3D RAGE (GT)" },
565 { 0x4755, 0x4755, "3D RAGE II+ (GTB)" },
566 { 0x4756, 0x4756, "3D RAGE IIC (PCI)" },
567 { 0x4757, 0x4757, "3D RAGE IIC (AGP)" },
568 { 0x475a, 0x475a, "3D RAGE IIC (AGP)" },
569 { 0x4742, 0x4742, "3D RAGE PRO (BGA, AGP)" },
570 { 0x4744, 0x4744, "3D RAGE PRO (BGA, AGP, 1x only)" },
571 { 0x4749, 0x4749, "3D RAGE PRO (BGA, PCI)" },
572 { 0x4750, 0x4750, "3D RAGE PRO (PQFP, PCI)" },
573 { 0x4751, 0x4751, "3D RAGE PRO (PQFP, PCI, limited 3D)" },
574 { 0x4c4d, 0x4c4d, "3D RAGE Mobility (PCI)" },
575 { 0x4c4e, 0x4c4e, "3D RAGE Mobility (AGP)" },
578 static const char *aty_gx_ram[8] __initdata = {
579 "DRAM", "VRAM", "VRAM", "DRAM", "DRAM", "VRAM", "VRAM", "RESV"
582 static const char *aty_ct_ram[8] __initdata = {
583 "OFF", "DRAM", "EDO", "EDO", "SDRAM", "SGRAM", "WRAM", "RESV"
587 static inline u32 aty_ld_le32(int regindex,
588 const struct fb_info_aty *info)
590 /* Hack for bloc 1, should be cleanly optimized by compiler */
591 if (regindex >= 0x400)
592 regindex -= 0x800;
594 #if defined(__mc68000__)
595 return le32_to_cpu(*((volatile u32 *)(info->ati_regbase+regindex)));
596 #else
597 return readl (info->ati_regbase + regindex);
598 #endif
601 static inline void aty_st_le32(int regindex, u32 val,
602 const struct fb_info_aty *info)
604 /* Hack for bloc 1, should be cleanly optimized by compiler */
605 if (regindex >= 0x400)
606 regindex -= 0x800;
608 #if defined(__mc68000__)
609 *((volatile u32 *)(info->ati_regbase+regindex)) = cpu_to_le32(val);
610 #else
611 writel (val, info->ati_regbase + regindex);
612 #endif
615 static inline u8 aty_ld_8(int regindex,
616 const struct fb_info_aty *info)
618 /* Hack for bloc 1, should be cleanly optimized by compiler */
619 if (regindex >= 0x400)
620 regindex -= 0x800;
622 return readb (info->ati_regbase + regindex);
625 static inline void aty_st_8(int regindex, u8 val,
626 const struct fb_info_aty *info)
628 /* Hack for bloc 1, should be cleanly optimized by compiler */
629 if (regindex >= 0x400)
630 regindex -= 0x800;
632 writeb (val, info->ati_regbase + regindex);
635 #if defined(CONFIG_PPC) || defined(CONFIG_PMAC_PBOOK)
636 static void aty_st_lcd(int index, u32 val, const struct fb_info_aty *info)
638 unsigned long temp;
640 /* write addr byte */
641 temp = aty_ld_le32(LCD_INDEX, info);
642 aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, info);
643 /* write the register value */
644 aty_st_le32(LCD_DATA, val, info);
647 static u32 aty_ld_lcd(int index, const struct fb_info_aty *info)
649 unsigned long temp;
651 /* write addr byte */
652 temp = aty_ld_le32(LCD_INDEX, info);
653 aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, info);
654 /* read the register value */
655 return aty_ld_le32(LCD_DATA, info);
657 #endif
660 * Generic Mach64 routines
664 * All writes to draw engine registers are automatically routed through a
665 * 32-bit-wide, 16-entry-deep command FIFO ...
666 * Register writes to registers with DWORD offsets less than 40h are not
667 * FIFOed.
668 * (from Chapter 5 of the Mach64 Programmer's Guide)
671 static inline void wait_for_fifo(u16 entries, const struct fb_info_aty *info)
673 while ((aty_ld_le32(FIFO_STAT, info) & 0xffff) >
674 ((u32)(0x8000 >> entries)));
677 static inline void wait_for_idle(struct fb_info_aty *info)
679 wait_for_fifo(16, info);
680 while ((aty_ld_le32(GUI_STAT, info) & 1)!= 0);
681 info->blitter_may_be_busy = 0;
684 static void reset_engine(const struct fb_info_aty *info)
686 /* reset engine */
687 aty_st_le32(GEN_TEST_CNTL,
688 aty_ld_le32(GEN_TEST_CNTL, info) & ~GUI_ENGINE_ENABLE, info);
689 /* enable engine */
690 aty_st_le32(GEN_TEST_CNTL,
691 aty_ld_le32(GEN_TEST_CNTL, info) | GUI_ENGINE_ENABLE, info);
692 /* ensure engine is not locked up by clearing any FIFO or */
693 /* HOST errors */
694 aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, info) | BUS_HOST_ERR_ACK |
695 BUS_FIFO_ERR_ACK, info);
698 static void reset_GTC_3D_engine(const struct fb_info_aty *info)
700 aty_st_le32(SCALE_3D_CNTL, 0xc0, info);
701 mdelay(GTC_3D_RESET_DELAY);
702 aty_st_le32(SETUP_CNTL, 0x00, info);
703 mdelay(GTC_3D_RESET_DELAY);
704 aty_st_le32(SCALE_3D_CNTL, 0x00, info);
705 mdelay(GTC_3D_RESET_DELAY);
708 static void init_engine(const struct atyfb_par *par, struct fb_info_aty *info)
710 u32 pitch_value;
712 /* determine modal information from global mode structure */
713 pitch_value = par->crtc.vxres;
715 if (par->crtc.bpp == 24) {
716 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
717 /* horizontal coordinates and widths must be adjusted */
718 pitch_value = pitch_value * 3;
721 /* On GTC (RagePro), we need to reset the 3D engine before */
722 if (Gx == LB_CHIP_ID || Gx == LD_CHIP_ID || Gx == LI_CHIP_ID ||
723 Gx == LP_CHIP_ID || Gx == GB_CHIP_ID || Gx == GD_CHIP_ID ||
724 Gx == GI_CHIP_ID || Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID ||
725 Gx == LM_CHIP_ID || Gx == LN_CHIP_ID)
726 reset_GTC_3D_engine(info);
728 /* Reset engine, enable, and clear any engine errors */
729 reset_engine(info);
730 /* Ensure that vga page pointers are set to zero - the upper */
731 /* page pointers are set to 1 to handle overflows in the */
732 /* lower page */
733 aty_st_le32(MEM_VGA_WP_SEL, 0x00010000, info);
734 aty_st_le32(MEM_VGA_RP_SEL, 0x00010000, info);
736 /* ---- Setup standard engine context ---- */
738 /* All GUI registers here are FIFOed - therefore, wait for */
739 /* the appropriate number of empty FIFO entries */
740 wait_for_fifo(14, info);
742 /* enable all registers to be loaded for context loads */
743 aty_st_le32(CONTEXT_MASK, 0xFFFFFFFF, info);
745 /* set destination pitch to modal pitch, set offset to zero */
746 aty_st_le32(DST_OFF_PITCH, (pitch_value / 8) << 22, info);
748 /* zero these registers (set them to a known state) */
749 aty_st_le32(DST_Y_X, 0, info);
750 aty_st_le32(DST_HEIGHT, 0, info);
751 aty_st_le32(DST_BRES_ERR, 0, info);
752 aty_st_le32(DST_BRES_INC, 0, info);
753 aty_st_le32(DST_BRES_DEC, 0, info);
755 /* set destination drawing attributes */
756 aty_st_le32(DST_CNTL, DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM |
757 DST_X_LEFT_TO_RIGHT, info);
759 /* set source pitch to modal pitch, set offset to zero */
760 aty_st_le32(SRC_OFF_PITCH, (pitch_value / 8) << 22, info);
762 /* set these registers to a known state */
763 aty_st_le32(SRC_Y_X, 0, info);
764 aty_st_le32(SRC_HEIGHT1_WIDTH1, 1, info);
765 aty_st_le32(SRC_Y_X_START, 0, info);
766 aty_st_le32(SRC_HEIGHT2_WIDTH2, 1, info);
768 /* set source pixel retrieving attributes */
769 aty_st_le32(SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT, info);
771 /* set host attributes */
772 wait_for_fifo(13, info);
773 aty_st_le32(HOST_CNTL, 0, info);
775 /* set pattern attributes */
776 aty_st_le32(PAT_REG0, 0, info);
777 aty_st_le32(PAT_REG1, 0, info);
778 aty_st_le32(PAT_CNTL, 0, info);
780 /* set scissors to modal size */
781 aty_st_le32(SC_LEFT, 0, info);
782 aty_st_le32(SC_TOP, 0, info);
783 aty_st_le32(SC_BOTTOM, par->crtc.vyres-1, info);
784 aty_st_le32(SC_RIGHT, pitch_value-1, info);
786 /* set background color to minimum value (usually BLACK) */
787 aty_st_le32(DP_BKGD_CLR, 0, info);
789 /* set foreground color to maximum value (usually WHITE) */
790 aty_st_le32(DP_FRGD_CLR, 0xFFFFFFFF, info);
792 /* set write mask to effect all pixel bits */
793 aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF, info);
795 /* set foreground mix to overpaint and background mix to */
796 /* no-effect */
797 aty_st_le32(DP_MIX, FRGD_MIX_S | BKGD_MIX_D, info);
799 /* set primary source pixel channel to foreground color */
800 /* register */
801 aty_st_le32(DP_SRC, FRGD_SRC_FRGD_CLR, info);
803 /* set compare functionality to false (no-effect on */
804 /* destination) */
805 wait_for_fifo(3, info);
806 aty_st_le32(CLR_CMP_CLR, 0, info);
807 aty_st_le32(CLR_CMP_MASK, 0xFFFFFFFF, info);
808 aty_st_le32(CLR_CMP_CNTL, 0, info);
810 /* set pixel depth */
811 wait_for_fifo(2, info);
812 aty_st_le32(DP_PIX_WIDTH, par->crtc.dp_pix_width, info);
813 aty_st_le32(DP_CHAIN_MASK, par->crtc.dp_chain_mask, info);
815 wait_for_fifo(5, info);
816 aty_st_le32(SCALE_3D_CNTL, 0, info);
817 aty_st_le32(Z_CNTL, 0, info);
818 aty_st_le32(CRTC_INT_CNTL, aty_ld_le32(CRTC_INT_CNTL, info) & ~0x20, info);
819 aty_st_le32(GUI_TRAJ_CNTL, 0x100023, info);
821 /* insure engine is idle before leaving */
822 wait_for_idle(info);
825 static void aty_st_514(int offset, u8 val, const struct fb_info_aty *info)
827 aty_st_8(DAC_CNTL, 1, info);
828 /* right addr byte */
829 aty_st_8(DAC_W_INDEX, offset & 0xff, info);
830 /* left addr byte */
831 aty_st_8(DAC_DATA, (offset >> 8) & 0xff, info);
832 aty_st_8(DAC_MASK, val, info);
833 aty_st_8(DAC_CNTL, 0, info);
836 static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info)
838 /* write addr byte */
839 aty_st_8(CLOCK_CNTL + 1, (offset << 2) | PLL_WR_EN, info);
840 /* write the register value */
841 aty_st_8(CLOCK_CNTL + 2, val, info);
842 aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, info);
845 static u8 aty_ld_pll(int offset, const struct fb_info_aty *info)
847 u8 res;
849 /* write addr byte */
850 aty_st_8(CLOCK_CNTL + 1, (offset << 2), info);
851 /* read the register value */
852 res = aty_ld_8(CLOCK_CNTL + 2, info);
853 return res;
856 #if defined(CONFIG_PPC)
859 * Apple monitor sense
862 static int read_aty_sense(const struct fb_info_aty *info)
864 int sense, i;
866 aty_st_le32(GP_IO, 0x31003100, info); /* drive outputs high */
867 __delay(200);
868 aty_st_le32(GP_IO, 0, info); /* turn off outputs */
869 __delay(2000);
870 i = aty_ld_le32(GP_IO, info); /* get primary sense value */
871 sense = ((i & 0x3000) >> 3) | (i & 0x100);
873 /* drive each sense line low in turn and collect the other 2 */
874 aty_st_le32(GP_IO, 0x20000000, info); /* drive A low */
875 __delay(2000);
876 i = aty_ld_le32(GP_IO, info);
877 sense |= ((i & 0x1000) >> 7) | ((i & 0x100) >> 4);
878 aty_st_le32(GP_IO, 0x20002000, info); /* drive A high again */
879 __delay(200);
881 aty_st_le32(GP_IO, 0x10000000, info); /* drive B low */
882 __delay(2000);
883 i = aty_ld_le32(GP_IO, info);
884 sense |= ((i & 0x2000) >> 10) | ((i & 0x100) >> 6);
885 aty_st_le32(GP_IO, 0x10001000, info); /* drive B high again */
886 __delay(200);
888 aty_st_le32(GP_IO, 0x01000000, info); /* drive C low */
889 __delay(2000);
890 sense |= (aty_ld_le32(GP_IO, info) & 0x3000) >> 12;
891 aty_st_le32(GP_IO, 0, info); /* turn off outputs */
893 return sense;
896 #endif /* defined(CONFIG_PPC) */
898 /* ------------------------------------------------------------------------- */
901 * Hardware Cursor support.
904 static u8 cursor_pixel_map[2] = { 0, 15 };
905 static u8 cursor_color_map[2] = { 0, 0xff };
907 static u8 cursor_bits_lookup[16] =
909 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
910 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
913 static u8 cursor_mask_lookup[16] =
915 0xaa, 0x2a, 0x8a, 0x0a, 0xa2, 0x22, 0x82, 0x02,
916 0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00
919 static void
920 aty_set_cursor_color(struct fb_info_aty *fb, u8 *pixel,
921 u8 *red, u8 *green, u8 *blue)
923 struct aty_cursor *c = fb->cursor;
924 int i;
926 if (!c)
927 return;
929 #ifdef __sparc__
930 if (fb->mmaped && (!fb->fb_info.display_fg
931 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
932 return;
933 #endif
935 for (i = 0; i < 2; i++) {
936 c->color[i] = (u32)red[i] << 24;
937 c->color[i] |= (u32)green[i] << 16;
938 c->color[i] |= (u32)blue[i] << 8;
939 c->color[i] |= (u32)pixel[i];
942 wait_for_fifo(2, fb);
943 aty_st_le32(CUR_CLR0, c->color[0], fb);
944 aty_st_le32(CUR_CLR1, c->color[1], fb);
947 static void
948 aty_set_cursor_shape(struct fb_info_aty *fb)
950 struct aty_cursor *c = fb->cursor;
951 u8 *ram, m, b;
952 int x, y;
954 if (!c)
955 return;
957 #ifdef __sparc__
958 if (fb->mmaped && (!fb->fb_info.display_fg
959 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
960 return;
961 #endif
963 ram = c->ram;
964 for (y = 0; y < c->size.y; y++) {
965 for (x = 0; x < c->size.x >> 2; x++) {
966 m = c->mask[x][y];
967 b = c->bits[x][y];
968 fb_writeb (cursor_mask_lookup[m >> 4] |
969 cursor_bits_lookup[(b & m) >> 4],
970 ram++);
971 fb_writeb (cursor_mask_lookup[m & 0x0f] |
972 cursor_bits_lookup[(b & m) & 0x0f],
973 ram++);
975 for ( ; x < 8; x++) {
976 fb_writeb (0xaa, ram++);
977 fb_writeb (0xaa, ram++);
980 fb_memset (ram, 0xaa, (64 - c->size.y) * 16);
983 static void
984 aty_set_cursor(struct fb_info_aty *fb, int on)
986 struct atyfb_par *par = &fb->current_par;
987 struct aty_cursor *c = fb->cursor;
988 u16 xoff, yoff;
989 int x, y;
991 if (!c)
992 return;
994 #ifdef __sparc__
995 if (fb->mmaped && (!fb->fb_info.display_fg
996 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
997 return;
998 #endif
1000 if (on) {
1001 x = c->pos.x - c->hot.x - par->crtc.xoffset;
1002 if (x < 0) {
1003 xoff = -x;
1004 x = 0;
1005 } else {
1006 xoff = 0;
1009 y = c->pos.y - c->hot.y - par->crtc.yoffset;
1010 if (y < 0) {
1011 yoff = -y;
1012 y = 0;
1013 } else {
1014 yoff = 0;
1017 wait_for_fifo(4, fb);
1018 aty_st_le32(CUR_OFFSET, (c->offset >> 3) + (yoff << 1), fb);
1019 aty_st_le32(CUR_HORZ_VERT_OFF,
1020 ((u32)(64 - c->size.y + yoff) << 16) | xoff, fb);
1021 aty_st_le32(CUR_HORZ_VERT_POSN, ((u32)y << 16) | x, fb);
1022 aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, fb)
1023 | HWCURSOR_ENABLE, fb);
1024 } else {
1025 wait_for_fifo(1, fb);
1026 aty_st_le32(GEN_TEST_CNTL,
1027 aty_ld_le32(GEN_TEST_CNTL, fb) & ~HWCURSOR_ENABLE,
1028 fb);
1030 if (fb->blitter_may_be_busy)
1031 wait_for_idle(fb);
1034 static void
1035 aty_cursor_timer_handler(unsigned long dev_addr)
1037 struct fb_info_aty *fb = (struct fb_info_aty *)dev_addr;
1039 if (!fb->cursor)
1040 return;
1042 if (!fb->cursor->enable)
1043 goto out;
1045 if (fb->cursor->vbl_cnt && --fb->cursor->vbl_cnt == 0) {
1046 fb->cursor->on ^= 1;
1047 aty_set_cursor(fb, fb->cursor->on);
1048 fb->cursor->vbl_cnt = fb->cursor->blink_rate;
1051 out:
1052 fb->cursor->timer->expires = jiffies + (HZ / 50);
1053 add_timer(fb->cursor->timer);
1056 static void
1057 atyfb_cursor(struct display *p, int mode, int x, int y)
1059 struct fb_info_aty *fb = (struct fb_info_aty *)p->fb_info;
1060 struct aty_cursor *c = fb->cursor;
1062 if (!c)
1063 return;
1065 #ifdef __sparc__
1066 if (fb->mmaped && (!fb->fb_info.display_fg
1067 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
1068 return;
1069 #endif
1071 x *= fontwidth(p);
1072 y *= fontheight(p);
1073 if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->enable)
1074 return;
1076 c->enable = 0;
1077 if (c->on)
1078 aty_set_cursor(fb, 0);
1079 c->pos.x = x;
1080 c->pos.y = y;
1082 switch (mode) {
1083 case CM_ERASE:
1084 c->on = 0;
1085 break;
1087 case CM_DRAW:
1088 case CM_MOVE:
1089 if (c->on)
1090 aty_set_cursor(fb, 1);
1091 else
1092 c->vbl_cnt = CURSOR_DRAW_DELAY;
1093 c->enable = 1;
1094 break;
1098 static struct fb_info_aty *fb_list = NULL;
1100 static struct aty_cursor * __init
1101 aty_init_cursor(struct fb_info_aty *fb)
1103 struct aty_cursor *cursor;
1104 unsigned long addr;
1106 cursor = kmalloc(sizeof(struct aty_cursor), GFP_ATOMIC);
1107 if (!cursor)
1108 return 0;
1109 memset(cursor, 0, sizeof(*cursor));
1111 cursor->timer = kmalloc(sizeof(*cursor->timer), GFP_KERNEL);
1112 if (!cursor->timer) {
1113 kfree(cursor);
1114 return 0;
1116 memset(cursor->timer, 0, sizeof(*cursor->timer));
1118 cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE;
1119 fb->total_vram -= PAGE_SIZE;
1120 cursor->offset = fb->total_vram;
1122 #ifdef __sparc__
1123 addr = fb->frame_buffer - 0x800000 + cursor->offset;
1124 cursor->ram = (u8 *)addr;
1125 #else
1126 #ifdef __BIG_ENDIAN
1127 addr = fb->frame_buffer_phys - 0x800000 + cursor->offset;
1128 cursor->ram = (u8 *)ioremap(addr, 1024);
1129 #else
1130 addr = fb->frame_buffer + cursor->offset;
1131 cursor->ram = (u8 *)addr;
1132 #endif
1133 #endif
1135 if (! cursor->ram) {
1136 kfree(cursor);
1137 return NULL;
1140 if (curblink) {
1141 init_timer(cursor->timer);
1142 cursor->timer->expires = jiffies + (HZ / 50);
1143 cursor->timer->data = (unsigned long)fb;
1144 cursor->timer->function = aty_cursor_timer_handler;
1145 add_timer(cursor->timer);
1148 return cursor;
1151 static int
1152 atyfb_set_font(struct display *d, int width, int height)
1154 struct fb_info_aty *fb = (struct fb_info_aty *)d->fb_info;
1155 struct aty_cursor *c = fb->cursor;
1156 int i, j;
1158 if (c) {
1159 if (!width || !height) {
1160 width = 8;
1161 height = 16;
1164 c->hot.x = 0;
1165 c->hot.y = 0;
1166 c->size.x = width;
1167 c->size.y = height;
1169 memset(c->bits, 0xff, sizeof(c->bits));
1170 memset(c->mask, 0, sizeof(c->mask));
1172 for (i = 0, j = width; j >= 0; j -= 8, i++) {
1173 c->mask[i][height-2] = (j >= 8) ? 0xff : (0xff << (8 - j));
1174 c->mask[i][height-1] = (j >= 8) ? 0xff : (0xff << (8 - j));
1177 aty_set_cursor_color(fb, cursor_pixel_map, cursor_color_map,
1178 cursor_color_map, cursor_color_map);
1179 aty_set_cursor_shape(fb);
1181 return 1;
1187 /* ------------------------------------------------------------------------- */
1190 * CRTC programming
1193 static void aty_set_crtc(const struct fb_info_aty *info,
1194 const struct crtc *crtc)
1196 aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, info);
1197 aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, info);
1198 aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_tot_disp, info);
1199 aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid, info);
1200 aty_st_le32(CRTC_VLINE_CRNT_VLINE, 0, info);
1201 aty_st_le32(CRTC_OFF_PITCH, crtc->off_pitch, info);
1202 aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl, info);
1205 static int aty_var_to_crtc(const struct fb_info_aty *info,
1206 const struct fb_var_screeninfo *var,
1207 struct crtc *crtc)
1209 u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
1210 u32 left, right, upper, lower, hslen, vslen, sync, vmode;
1211 u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
1212 u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
1213 u32 pix_width, dp_pix_width, dp_chain_mask;
1215 /* input */
1216 xres = var->xres;
1217 yres = var->yres;
1218 vxres = var->xres_virtual;
1219 vyres = var->yres_virtual;
1220 xoffset = var->xoffset;
1221 yoffset = var->yoffset;
1222 bpp = var->bits_per_pixel;
1223 left = var->left_margin;
1224 right = var->right_margin;
1225 upper = var->upper_margin;
1226 lower = var->lower_margin;
1227 hslen = var->hsync_len;
1228 vslen = var->vsync_len;
1229 sync = var->sync;
1230 vmode = var->vmode;
1232 /* convert (and round up) and validate */
1233 xres = (xres+7) & ~7;
1234 xoffset = (xoffset+7) & ~7;
1235 vxres = (vxres+7) & ~7;
1236 if (vxres < xres+xoffset)
1237 vxres = xres+xoffset;
1238 h_disp = xres/8-1;
1239 if (h_disp > 0xff)
1240 FAIL("h_disp too large");
1241 h_sync_strt = h_disp+(right/8);
1242 if (h_sync_strt > 0x1ff)
1243 FAIL("h_sync_start too large");
1244 h_sync_dly = right & 7;
1245 h_sync_wid = (hslen+7)/8;
1246 if (h_sync_wid > 0x1f)
1247 FAIL("h_sync_wid too large");
1248 h_total = h_sync_strt+h_sync_wid+(h_sync_dly+left+7)/8;
1249 if (h_total > 0x1ff)
1250 FAIL("h_total too large");
1251 h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
1253 if (vyres < yres+yoffset)
1254 vyres = yres+yoffset;
1255 v_disp = yres-1;
1256 if (v_disp > 0x7ff)
1257 FAIL("v_disp too large");
1258 v_sync_strt = v_disp+lower;
1259 if (v_sync_strt > 0x7ff)
1260 FAIL("v_sync_strt too large");
1261 v_sync_wid = vslen;
1262 if (v_sync_wid > 0x1f)
1263 FAIL("v_sync_wid too large");
1264 v_total = v_sync_strt+v_sync_wid+upper;
1265 if (v_total > 0x7ff)
1266 FAIL("v_total too large");
1267 v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
1269 c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;
1271 if (bpp <= 8) {
1272 bpp = 8;
1273 pix_width = CRTC_PIX_WIDTH_8BPP;
1274 dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB;
1275 dp_chain_mask = 0x8080;
1276 } else if (bpp <= 16) {
1277 bpp = 16;
1278 pix_width = CRTC_PIX_WIDTH_15BPP;
1279 dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP |
1280 BYTE_ORDER_LSB_TO_MSB;
1281 dp_chain_mask = 0x4210;
1282 } else if ((bpp <= 24) && (Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
1283 bpp = 24;
1284 pix_width = CRTC_PIX_WIDTH_24BPP;
1285 dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB;
1286 dp_chain_mask = 0x8080;
1287 } else if (bpp <= 32) {
1288 bpp = 32;
1289 pix_width = CRTC_PIX_WIDTH_32BPP;
1290 dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP |
1291 BYTE_ORDER_LSB_TO_MSB;
1292 dp_chain_mask = 0x8080;
1293 } else
1294 FAIL("invalid bpp");
1296 if (vxres*vyres*bpp/8 > info->total_vram)
1297 FAIL("not enough video RAM");
1299 if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
1300 FAIL("invalid vmode");
1302 /* output */
1303 crtc->vxres = vxres;
1304 crtc->vyres = vyres;
1305 crtc->xoffset = xoffset;
1306 crtc->yoffset = yoffset;
1307 crtc->bpp = bpp;
1308 crtc->h_tot_disp = h_total | (h_disp<<16);
1309 crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly<<8) |
1310 ((h_sync_strt & 0x100)<<4) | (h_sync_wid<<16) |
1311 (h_sync_pol<<21);
1312 crtc->v_tot_disp = v_total | (v_disp<<16);
1313 crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid<<16) | (v_sync_pol<<21);
1314 crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19);
1315 crtc->gen_cntl = pix_width | c_sync | CRTC_EXT_DISP_EN | CRTC_ENABLE;
1316 if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID) ||
1317 ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07))) {
1318 /* Not VTB/GTB */
1319 /* FIXME: magic FIFO values */
1320 crtc->gen_cntl |= aty_ld_le32(CRTC_GEN_CNTL, info) & 0x000e0000;
1322 crtc->dp_pix_width = dp_pix_width;
1323 crtc->dp_chain_mask = dp_chain_mask;
1325 return 0;
1329 static int aty_set_dac_ATI68860_B(const struct fb_info_aty *info, u32 bpp,
1330 u32 AccelMode)
1332 u32 gModeReg, devSetupRegA, temp, mask;
1334 gModeReg = 0;
1335 devSetupRegA = 0;
1337 switch (bpp) {
1338 case 8:
1339 gModeReg = 0x83;
1340 devSetupRegA = 0x60 | 0x00 /*(info->mach64DAC8Bit ? 0x00 : 0x01) */;
1341 break;
1342 case 15:
1343 gModeReg = 0xA0;
1344 devSetupRegA = 0x60;
1345 break;
1346 case 16:
1347 gModeReg = 0xA1;
1348 devSetupRegA = 0x60;
1349 break;
1350 case 24:
1351 gModeReg = 0xC0;
1352 devSetupRegA = 0x60;
1353 break;
1354 case 32:
1355 gModeReg = 0xE3;
1356 devSetupRegA = 0x60;
1357 break;
1360 if (!AccelMode) {
1361 gModeReg = 0x80;
1362 devSetupRegA = 0x61;
1365 temp = aty_ld_8(DAC_CNTL, info);
1366 aty_st_8(DAC_CNTL, (temp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3, info);
1368 aty_st_8(DAC_REGS + 2, 0x1D, info);
1369 aty_st_8(DAC_REGS + 3, gModeReg, info);
1370 aty_st_8(DAC_REGS, 0x02, info);
1372 temp = aty_ld_8(DAC_CNTL, info);
1373 aty_st_8(DAC_CNTL, temp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, info);
1375 if (info->total_vram < MEM_SIZE_1M)
1376 mask = 0x04;
1377 else if (info->total_vram == MEM_SIZE_1M)
1378 mask = 0x08;
1379 else
1380 mask = 0x0C;
1382 /* The following assumes that the BIOS has correctly set R7 of the
1383 * Device Setup Register A at boot time.
1385 #define A860_DELAY_L 0x80
1387 temp = aty_ld_8(DAC_REGS, info);
1388 aty_st_8(DAC_REGS, (devSetupRegA | mask) | (temp & A860_DELAY_L), info);
1389 temp = aty_ld_8(DAC_CNTL, info);
1390 aty_st_8(DAC_CNTL, (temp & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3)), info);
1392 return 0;
1395 static int aty_set_dac_ATT21C498(const struct fb_info_aty *info,
1396 const struct pll_18818 *pll, u32 bpp)
1398 u32 dotClock;
1399 int muxmode = 0;
1400 int DACMask = 0;
1402 dotClock = 100000000 / pll->period_in_ps;
1404 switch (bpp) {
1405 case 8:
1406 if (dotClock > 8000) {
1407 DACMask = 0x24;
1408 muxmode = 1;
1409 } else
1410 DACMask = 0x04;
1411 break;
1412 case 15:
1413 DACMask = 0x16;
1414 break;
1415 case 16:
1416 DACMask = 0x36;
1417 break;
1418 case 24:
1419 DACMask = 0xE6;
1420 break;
1421 case 32:
1422 DACMask = 0xE6;
1423 break;
1426 if (1 /* info->mach64DAC8Bit */)
1427 DACMask |= 0x02;
1429 aty_dac_waste4(info);
1430 aty_st_8(DAC_REGS + 2, DACMask, info);
1432 return muxmode;
1435 void aty_dac_waste4(const struct fb_info_aty *info)
1437 (void)aty_ld_8(DAC_REGS, info);
1439 (void)aty_ld_8(DAC_REGS + 2, info);
1440 (void)aty_ld_8(DAC_REGS + 2, info);
1441 (void)aty_ld_8(DAC_REGS + 2, info);
1442 (void)aty_ld_8(DAC_REGS + 2, info);
1446 static void aty_set_dac_514(const struct fb_info_aty *info, u32 bpp)
1448 static struct {
1449 u8 pixel_dly;
1450 u8 misc2_cntl;
1451 u8 pixel_rep;
1452 u8 pixel_cntl_index;
1453 u8 pixel_cntl_v1;
1454 } tab[3] = {
1455 { 0, 0x41, 0x03, 0x71, 0x45 }, /* 8 bpp */
1456 { 0, 0x45, 0x04, 0x0c, 0x01 }, /* 555 */
1457 { 0, 0x45, 0x06, 0x0e, 0x00 }, /* XRGB */
1459 int i;
1461 switch (bpp) {
1462 case 8:
1463 default:
1464 i = 0;
1465 break;
1466 case 16:
1467 i = 1;
1468 break;
1469 case 32:
1470 i = 2;
1471 break;
1473 aty_st_514(0x90, 0x00, info); /* VRAM Mask Low */
1474 aty_st_514(0x04, tab[i].pixel_dly, info); /* Horizontal Sync Control */
1475 aty_st_514(0x05, 0x00, info); /* Power Management */
1476 aty_st_514(0x02, 0x01, info); /* Misc Clock Control */
1477 aty_st_514(0x71, tab[i].misc2_cntl, info); /* Misc Control 2 */
1478 aty_st_514(0x0a, tab[i].pixel_rep, info); /* Pixel Format */
1479 aty_st_514(tab[i].pixel_cntl_index, tab[i].pixel_cntl_v1, info);
1480 /* Misc Control 2 / 16 BPP Control / 32 BPP Control */
1483 static int aty_crtc_to_var(const struct crtc *crtc,
1484 struct fb_var_screeninfo *var)
1486 u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync;
1487 u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
1488 u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
1489 u32 pix_width;
1491 /* input */
1492 h_total = crtc->h_tot_disp & 0x1ff;
1493 h_disp = (crtc->h_tot_disp>>16) & 0xff;
1494 h_sync_strt = (crtc->h_sync_strt_wid & 0xff) |
1495 ((crtc->h_sync_strt_wid>>4) & 0x100);
1496 h_sync_dly = (crtc->h_sync_strt_wid>>8) & 0x7;
1497 h_sync_wid = (crtc->h_sync_strt_wid>>16) & 0x1f;
1498 h_sync_pol = (crtc->h_sync_strt_wid>>21) & 0x1;
1499 v_total = crtc->v_tot_disp & 0x7ff;
1500 v_disp = (crtc->v_tot_disp>>16) & 0x7ff;
1501 v_sync_strt = crtc->v_sync_strt_wid & 0x7ff;
1502 v_sync_wid = (crtc->v_sync_strt_wid>>16) & 0x1f;
1503 v_sync_pol = (crtc->v_sync_strt_wid>>21) & 0x1;
1504 c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
1505 pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
1507 /* convert */
1508 xres = (h_disp+1)*8;
1509 yres = v_disp+1;
1510 left = (h_total-h_sync_strt-h_sync_wid)*8-h_sync_dly;
1511 right = (h_sync_strt-h_disp)*8+h_sync_dly;
1512 hslen = h_sync_wid*8;
1513 upper = v_total-v_sync_strt-v_sync_wid;
1514 lower = v_sync_strt-v_disp;
1515 vslen = v_sync_wid;
1516 sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) |
1517 (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
1518 (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
1520 switch (pix_width) {
1521 #if 0
1522 case CRTC_PIX_WIDTH_4BPP:
1523 bpp = 4;
1524 var->red.offset = 0;
1525 var->red.length = 8;
1526 var->green.offset = 0;
1527 var->green.length = 8;
1528 var->blue.offset = 0;
1529 var->blue.length = 8;
1530 var->transp.offset = 0;
1531 var->transp.length = 0;
1532 break;
1533 #endif
1534 case CRTC_PIX_WIDTH_8BPP:
1535 bpp = 8;
1536 var->red.offset = 0;
1537 var->red.length = 8;
1538 var->green.offset = 0;
1539 var->green.length = 8;
1540 var->blue.offset = 0;
1541 var->blue.length = 8;
1542 var->transp.offset = 0;
1543 var->transp.length = 0;
1544 break;
1545 case CRTC_PIX_WIDTH_15BPP: /* RGB 555 */
1546 bpp = 16;
1547 var->red.offset = 10;
1548 var->red.length = 5;
1549 var->green.offset = 5;
1550 var->green.length = 5;
1551 var->blue.offset = 0;
1552 var->blue.length = 5;
1553 var->transp.offset = 0;
1554 var->transp.length = 0;
1555 break;
1556 #if 0
1557 case CRTC_PIX_WIDTH_16BPP: /* RGB 565 */
1558 bpp = 16;
1559 var->red.offset = 11;
1560 var->red.length = 5;
1561 var->green.offset = 5;
1562 var->green.length = 6;
1563 var->blue.offset = 0;
1564 var->blue.length = 5;
1565 var->transp.offset = 0;
1566 var->transp.length = 0;
1567 break;
1568 #endif
1569 case CRTC_PIX_WIDTH_24BPP: /* RGB 888 */
1570 bpp = 24;
1571 var->red.offset = 16;
1572 var->red.length = 8;
1573 var->green.offset = 8;
1574 var->green.length = 8;
1575 var->blue.offset = 0;
1576 var->blue.length = 8;
1577 var->transp.offset = 0;
1578 var->transp.length = 0;
1579 break;
1580 case CRTC_PIX_WIDTH_32BPP: /* ARGB 8888 */
1581 bpp = 32;
1582 var->red.offset = 16;
1583 var->red.length = 8;
1584 var->green.offset = 8;
1585 var->green.length = 8;
1586 var->blue.offset = 0;
1587 var->blue.length = 8;
1588 var->transp.offset = 24;
1589 var->transp.length = 8;
1590 break;
1591 default:
1592 FAIL("Invalid pixel width");
1595 /* output */
1596 var->xres = xres;
1597 var->yres = yres;
1598 var->xres_virtual = crtc->vxres;
1599 var->yres_virtual = crtc->vyres;
1600 var->bits_per_pixel = bpp;
1601 var->xoffset = crtc->xoffset;
1602 var->yoffset = crtc->yoffset;
1603 var->left_margin = left;
1604 var->right_margin = right;
1605 var->upper_margin = upper;
1606 var->lower_margin = lower;
1607 var->hsync_len = hslen;
1608 var->vsync_len = vslen;
1609 var->sync = sync;
1610 var->vmode = FB_VMODE_NONINTERLACED;
1612 return 0;
1615 /* ------------------------------------------------------------------------- */
1618 * PLL programming (Mach64 GX family)
1620 * FIXME: use function pointer tables instead of switch statements
1623 static void aty_set_pll_gx(const struct fb_info_aty *info,
1624 const struct pll_gx *pll)
1626 switch (info->clk_type) {
1627 case CLK_ATI18818_1:
1628 aty_st_8(CLOCK_CNTL, pll->m, info);
1629 break;
1630 case CLK_IBMRGB514:
1631 aty_st_514(0x06, 0x02, info); /* DAC Operation */
1632 aty_st_514(0x10, 0x01, info); /* PLL Control 1 */
1633 aty_st_514(0x70, 0x01, info); /* Misc Control 1 */
1634 aty_st_514(0x8f, 0x1f, info); /* PLL Ref. Divider Input */
1635 aty_st_514(0x03, 0x00, info); /* Sync Control */
1636 aty_st_514(0x05, 0x00, info); /* Power Management */
1637 aty_st_514(0x20, pll->m, info); /* F0 / M0 */
1638 aty_st_514(0x21, pll->n, info); /* F1 / N0 */
1639 break;
1644 static int aty_var_to_pll_18818(u32 period_in_ps, struct pll_18818 *pll)
1646 u32 MHz100; /* in 0.01 MHz */
1647 u32 program_bits;
1648 u32 post_divider;
1650 /* Calculate the programming word */
1651 MHz100 = 100000000 / period_in_ps;
1653 program_bits = -1;
1654 post_divider = 1;
1656 if (MHz100 > MAX_FREQ_2595) {
1657 MHz100 = MAX_FREQ_2595;
1658 return -EINVAL;
1659 } else if (MHz100 < ABS_MIN_FREQ_2595) {
1660 program_bits = 0; /* MHz100 = 257 */
1661 return -EINVAL;
1662 } else {
1663 while (MHz100 < MIN_FREQ_2595) {
1664 MHz100 *= 2;
1665 post_divider *= 2;
1668 MHz100 *= 1000;
1669 MHz100 = (REF_DIV_2595 * MHz100) / REF_FREQ_2595;
1671 MHz100 += 500; /* + 0.5 round */
1672 MHz100 /= 1000;
1674 if (program_bits == -1) {
1675 program_bits = MHz100 - N_ADJ_2595;
1676 switch (post_divider) {
1677 case 1:
1678 program_bits |= 0x0600;
1679 break;
1680 case 2:
1681 program_bits |= 0x0400;
1682 break;
1683 case 4:
1684 program_bits |= 0x0200;
1685 break;
1686 case 8:
1687 default:
1688 break;
1692 program_bits |= STOP_BITS_2595;
1694 pll->program_bits = program_bits;
1695 pll->locationAddr = 0;
1696 pll->post_divider = post_divider;
1697 pll->period_in_ps = period_in_ps;
1699 return 0;
1702 static u32 aty_pll_18818_to_var(const struct pll_18818 *pll)
1704 return(pll->period_in_ps); /* default for now */
1707 static void aty_set_pll18818(const struct fb_info_aty *info,
1708 const struct pll_18818 *pll)
1710 u32 program_bits;
1711 u32 locationAddr;
1713 u32 i;
1715 u8 old_clock_cntl;
1716 u8 old_crtc_ext_disp;
1718 old_clock_cntl = aty_ld_8(CLOCK_CNTL, info);
1719 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info);
1721 old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
1722 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24),
1723 info);
1725 udelay(15000); /* delay for 50 (15) ms */
1727 program_bits = pll->program_bits;
1728 locationAddr = pll->locationAddr;
1730 /* Program the clock chip */
1731 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info); /* Strobe = 0 */
1732 aty_StrobeClock(info);
1733 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 1, info); /* Strobe = 0 */
1734 aty_StrobeClock(info);
1736 aty_ICS2595_put1bit(1, info); /* Send start bits */
1737 aty_ICS2595_put1bit(0, info); /* Start bit */
1738 aty_ICS2595_put1bit(0, info); /* Read / ~Write */
1740 for (i = 0; i < 5; i++) { /* Location 0..4 */
1741 aty_ICS2595_put1bit(locationAddr & 1, info);
1742 locationAddr >>= 1;
1745 for (i = 0; i < 8 + 1 + 2 + 2; i++) {
1746 aty_ICS2595_put1bit(program_bits & 1, info);
1747 program_bits >>= 1;
1750 udelay(1000); /* delay for 1 ms */
1752 (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */
1753 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info);
1754 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, old_clock_cntl | CLOCK_STROBE,
1755 info);
1757 udelay(50000); /* delay for 50 (15) ms */
1758 aty_st_8(CLOCK_CNTL + info->clk_wr_offset,
1759 ((pll->locationAddr & 0x0F) | CLOCK_STROBE), info);
1761 return;
1765 static int aty_var_to_pll_408(u32 period_in_ps, struct pll_18818 *pll)
1767 u32 mhz100; /* in 0.01 MHz */
1768 u32 program_bits;
1769 /* u32 post_divider; */
1770 u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
1771 u32 temp, tempB;
1772 u16 remainder, preRemainder;
1773 short divider = 0, tempA;
1775 /* Calculate the programming word */
1776 mhz100 = 100000000 / period_in_ps;
1777 mach64MinFreq = MIN_FREQ_2595;
1778 mach64MaxFreq = MAX_FREQ_2595;
1779 mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */
1781 /* Calculate program word */
1782 if (mhz100 == 0)
1783 program_bits = 0xFF;
1784 else {
1785 if (mhz100 < mach64MinFreq)
1786 mhz100 = mach64MinFreq;
1787 if (mhz100 > mach64MaxFreq)
1788 mhz100 = mach64MaxFreq;
1790 while (mhz100 < (mach64MinFreq << 3)) {
1791 mhz100 <<= 1;
1792 divider += 0x40;
1795 temp = (unsigned int)mhz100;
1796 temp = (unsigned int)(temp * (MIN_N_408 + 2));
1797 temp -= ((short)(mach64RefFreq << 1));
1799 tempA = MIN_N_408;
1800 preRemainder = 0xFFFF;
1802 do {
1803 tempB = temp;
1804 remainder = tempB % mach64RefFreq;
1805 tempB = tempB / mach64RefFreq;
1806 if (((tempB & 0xFFFF) <= 255) && (remainder <= preRemainder)) {
1807 preRemainder = remainder;
1808 divider &= ~0x3f;
1809 divider |= tempA;
1810 divider = (divider & 0x00FF) + ((tempB & 0xFF) << 8);
1812 temp += mhz100;
1813 tempA++;
1814 } while(tempA <= 32);
1816 program_bits = divider;
1819 pll->program_bits = program_bits;
1820 pll->locationAddr = 0;
1821 pll->post_divider = divider; /* fuer nix */
1822 pll->period_in_ps = period_in_ps;
1824 return 0;
1827 static u32 aty_pll_408_to_var(const struct pll_18818 *pll)
1829 return(pll->period_in_ps); /* default for now */
1832 static void aty_set_pll_408(const struct fb_info_aty *info,
1833 const struct pll_18818 *pll)
1835 u32 program_bits;
1836 u32 locationAddr;
1838 u8 tmpA, tmpB, tmpC;
1839 char old_crtc_ext_disp;
1841 old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
1842 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24),
1843 info);
1845 program_bits = pll->program_bits;
1846 locationAddr = pll->locationAddr;
1848 /* Program clock */
1849 aty_dac_waste4(info);
1850 tmpB = aty_ld_8(DAC_REGS + 2, info) | 1;
1851 aty_dac_waste4(info);
1852 aty_st_8(DAC_REGS + 2, tmpB, info);
1854 tmpA = tmpB;
1855 tmpC = tmpA;
1856 tmpA |= 8;
1857 tmpB = 1;
1859 aty_st_8(DAC_REGS, tmpB, info);
1860 aty_st_8(DAC_REGS + 2, tmpA, info);
1862 udelay(400); /* delay for 400 us */
1864 locationAddr = (locationAddr << 2) + 0x40;
1865 tmpB = locationAddr;
1866 tmpA = program_bits >> 8;
1868 aty_st_8(DAC_REGS, tmpB, info);
1869 aty_st_8(DAC_REGS + 2, tmpA, info);
1871 tmpB = locationAddr + 1;
1872 tmpA = (u8)program_bits;
1874 aty_st_8(DAC_REGS, tmpB, info);
1875 aty_st_8(DAC_REGS + 2, tmpA, info);
1877 tmpB = locationAddr + 2;
1878 tmpA = 0x77;
1880 aty_st_8(DAC_REGS, tmpB, info);
1881 aty_st_8(DAC_REGS + 2, tmpA, info);
1883 udelay(400); /* delay for 400 us */
1884 tmpA = tmpC & (~(1 | 8));
1885 tmpB = 1;
1887 aty_st_8(DAC_REGS, tmpB, info);
1888 aty_st_8(DAC_REGS + 2, tmpA, info);
1890 (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */
1891 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info);
1893 return;
1897 static int aty_var_to_pll_1703(u32 period_in_ps, struct pll_18818 *pll)
1899 u32 mhz100; /* in 0.01 MHz */
1900 u32 program_bits;
1901 /* u32 post_divider; */
1902 u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
1903 u32 temp, tempB;
1904 u16 remainder, preRemainder;
1905 short divider = 0, tempA;
1907 /* Calculate the programming word */
1908 mhz100 = 100000000 / period_in_ps;
1909 mach64MinFreq = MIN_FREQ_2595;
1910 mach64MaxFreq = MAX_FREQ_2595;
1911 mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */
1913 /* Calculate program word */
1914 if (mhz100 == 0)
1915 program_bits = 0xE0;
1916 else {
1917 if (mhz100 < mach64MinFreq)
1918 mhz100 = mach64MinFreq;
1919 if (mhz100 > mach64MaxFreq)
1920 mhz100 = mach64MaxFreq;
1922 divider = 0;
1923 while (mhz100 < (mach64MinFreq << 3)) {
1924 mhz100 <<= 1;
1925 divider += 0x20;
1928 temp = (unsigned int)(mhz100);
1929 temp = (unsigned int)(temp * (MIN_N_1703 + 2));
1930 temp -= (short)(mach64RefFreq << 1);
1932 tempA = MIN_N_1703;
1933 preRemainder = 0xffff;
1935 do {
1936 tempB = temp;
1937 remainder = tempB % mach64RefFreq;
1938 tempB = tempB / mach64RefFreq;
1940 if ((tempB & 0xffff) <= 127 && (remainder <= preRemainder)) {
1941 preRemainder = remainder;
1942 divider &= ~0x1f;
1943 divider |= tempA;
1944 divider = (divider & 0x00ff) + ((tempB & 0xff) << 8);
1947 temp += mhz100;
1948 tempA++;
1949 } while (tempA <= (MIN_N_1703 << 1));
1951 program_bits = divider;
1954 pll->program_bits = program_bits;
1955 pll->locationAddr = 0;
1956 pll->post_divider = divider; /* fuer nix */
1957 pll->period_in_ps = period_in_ps;
1959 return 0;
1962 static u32 aty_pll_1703_to_var(const struct pll_18818 *pll)
1964 return(pll->period_in_ps); /* default for now */
1967 static void aty_set_pll_1703(const struct fb_info_aty *info,
1968 const struct pll_18818 *pll)
1970 u32 program_bits;
1971 u32 locationAddr;
1973 char old_crtc_ext_disp;
1975 old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
1976 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24),
1977 info);
1979 program_bits = pll->program_bits;
1980 locationAddr = pll->locationAddr;
1982 /* Program clock */
1983 aty_dac_waste4(info);
1985 (void)aty_ld_8(DAC_REGS + 2, info);
1986 aty_st_8(DAC_REGS+2, (locationAddr << 1) + 0x20, info);
1987 aty_st_8(DAC_REGS+2, 0, info);
1988 aty_st_8(DAC_REGS+2, (program_bits & 0xFF00) >> 8, info);
1989 aty_st_8(DAC_REGS+2, (program_bits & 0xFF), info);
1991 (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */
1992 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info);
1994 return;
1998 static int aty_var_to_pll_8398(u32 period_in_ps, struct pll_18818 *pll)
2001 u32 tempA, tempB, fOut, longMHz100, diff, preDiff;
2003 u32 mhz100; /* in 0.01 MHz */
2004 u32 program_bits;
2005 /* u32 post_divider; */
2006 u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq;
2007 u16 m, n, k=0, save_m, save_n, twoToKth;
2009 /* Calculate the programming word */
2010 mhz100 = 100000000 / period_in_ps;
2011 mach64MinFreq = MIN_FREQ_2595;
2012 mach64MaxFreq = MAX_FREQ_2595;
2013 mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */
2015 save_m = 0;
2016 save_n = 0;
2018 /* Calculate program word */
2019 if (mhz100 == 0)
2020 program_bits = 0xE0;
2021 else
2023 if (mhz100 < mach64MinFreq)
2024 mhz100 = mach64MinFreq;
2025 if (mhz100 > mach64MaxFreq)
2026 mhz100 = mach64MaxFreq;
2028 longMHz100 = mhz100 * 256 / 100; /* 8 bit scale this */
2030 while (mhz100 < (mach64MinFreq << 3))
2032 mhz100 <<= 1;
2033 k++;
2036 twoToKth = 1 << k;
2037 diff = 0;
2038 preDiff = 0xFFFFFFFF;
2040 for (m = MIN_M; m <= MAX_M; m++)
2042 for (n = MIN_N; n <= MAX_N; n++)
2044 tempA = (14.31818 * 65536);
2045 tempA *= (n + 8); /* 43..256 */
2046 tempB = twoToKth * 256;
2047 tempB *= (m + 2); /* 4..32 */
2048 fOut = tempA / tempB; /* 8 bit scale */
2050 if (longMHz100 > fOut)
2051 diff = longMHz100 - fOut;
2052 else
2053 diff = fOut - longMHz100;
2055 if (diff < preDiff)
2057 save_m = m;
2058 save_n = n;
2059 preDiff = diff;
2064 program_bits = (k << 6) + (save_m) + (save_n << 8);
2067 pll->program_bits = program_bits;
2068 pll->locationAddr = 0;
2069 pll->post_divider = 0;
2070 pll->period_in_ps = period_in_ps;
2072 return 0;
2075 static u32 aty_pll_8398_to_var(const struct pll_18818 *pll)
2077 return(pll->period_in_ps); /* default for now */
2080 static void aty_set_pll_8398(const struct fb_info_aty *info,
2081 const struct pll_18818 *pll)
2083 u32 program_bits;
2084 u32 locationAddr;
2086 char old_crtc_ext_disp;
2087 char tmp;
2089 old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
2090 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24),
2091 info);
2093 program_bits = pll->program_bits;
2094 locationAddr = pll->locationAddr;
2096 /* Program clock */
2097 tmp = aty_ld_8(DAC_CNTL, info);
2098 aty_st_8(DAC_CNTL, tmp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, info);
2100 aty_st_8(DAC_REGS, locationAddr, info);
2101 aty_st_8(DAC_REGS+1, (program_bits & 0xff00) >> 8, info);
2102 aty_st_8(DAC_REGS+1, (program_bits & 0xff), info);
2104 tmp = aty_ld_8(DAC_CNTL, info);
2105 aty_st_8(DAC_CNTL, (tmp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3, info);
2107 (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */
2108 aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info);
2110 return;
2114 static int aty_var_to_pll_514(u32 vclk_per, struct pll_gx *pll)
2117 * FIXME: use real calculations instead of using fixed values from the old
2118 * driver
2120 static struct {
2121 u32 limit; /* pixlock rounding limit (arbitrary) */
2122 u8 m; /* (df<<6) | vco_div_count */
2123 u8 n; /* ref_div_count */
2124 } RGB514_clocks[7] = {
2125 { 8000, (3<<6) | 20, 9 }, /* 7395 ps / 135.2273 MHz */
2126 { 10000, (1<<6) | 19, 3 }, /* 9977 ps / 100.2273 MHz */
2127 { 13000, (1<<6) | 2, 3 }, /* 12509 ps / 79.9432 MHz */
2128 { 14000, (2<<6) | 8, 7 }, /* 13394 ps / 74.6591 MHz */
2129 { 16000, (1<<6) | 44, 6 }, /* 15378 ps / 65.0284 MHz */
2130 { 25000, (1<<6) | 15, 5 }, /* 17460 ps / 57.2727 MHz */
2131 { 50000, (0<<6) | 53, 7 }, /* 33145 ps / 30.1705 MHz */
2133 int i;
2135 for (i = 0; i < sizeof(RGB514_clocks)/sizeof(*RGB514_clocks); i++)
2136 if (vclk_per <= RGB514_clocks[i].limit) {
2137 pll->m = RGB514_clocks[i].m;
2138 pll->n = RGB514_clocks[i].n;
2139 return 0;
2141 return -EINVAL;
2145 static void aty_StrobeClock(const struct fb_info_aty *info)
2147 u8 tmp;
2149 udelay(26);
2151 tmp = aty_ld_8(CLOCK_CNTL, info);
2152 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, tmp | CLOCK_STROBE, info);
2154 return;
2158 static void aty_ICS2595_put1bit(u8 data, const struct fb_info_aty *info)
2160 u8 tmp;
2162 data &= 0x01;
2163 tmp = aty_ld_8(CLOCK_CNTL, info);
2164 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, (tmp & ~0x04) | (data << 2),
2165 info);
2167 tmp = aty_ld_8(CLOCK_CNTL, info);
2168 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, (tmp & ~0x08) | (0 << 3), info);
2170 aty_StrobeClock(info);
2172 tmp = aty_ld_8(CLOCK_CNTL, info);
2173 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, (tmp & ~0x08) | (1 << 3), info);
2175 aty_StrobeClock(info);
2177 return;
2181 static u32 aty_pll_gx_to_var(const struct pll_gx *pll,
2182 const struct fb_info_aty *info)
2184 u8 df, vco_div_count, ref_div_count;
2186 df = pll->m >> 6;
2187 vco_div_count = pll->m & 0x3f;
2188 ref_div_count = pll->n;
2190 return ((info->ref_clk_per*ref_div_count)<<(3-df))/(vco_div_count+65);
2195 * PLL programming (Mach64 CT family)
2198 static void aty_set_pll_ct(const struct fb_info_aty *info,
2199 const struct pll_ct *pll)
2201 aty_st_pll(PLL_REF_DIV, pll->pll_ref_div, info);
2202 aty_st_pll(PLL_GEN_CNTL, pll->pll_gen_cntl, info);
2203 aty_st_pll(MCLK_FB_DIV, pll->mclk_fb_div, info);
2204 aty_st_pll(PLL_VCLK_CNTL, pll->pll_vclk_cntl, info);
2205 aty_st_pll(VCLK_POST_DIV, pll->vclk_post_div, info);
2206 aty_st_pll(VCLK0_FB_DIV, pll->vclk_fb_div, info);
2207 aty_st_pll(PLL_EXT_CNTL, pll->pll_ext_cntl, info);
2209 if (!(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
2210 Gx == ET_CHIP_ID ||
2211 ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07)))) {
2212 if (info->ram_type >= SDRAM)
2213 aty_st_pll(DLL_CNTL, 0xa6, info);
2214 else
2215 aty_st_pll(DLL_CNTL, 0xa0, info);
2216 aty_st_pll(VFC_CNTL, 0x1b, info);
2217 aty_st_le32(DSP_CONFIG, pll->dsp_config, info);
2218 aty_st_le32(DSP_ON_OFF, pll->dsp_on_off, info);
2222 static int aty_dsp_gt(const struct fb_info_aty *info, u8 bpp,
2223 struct pll_ct *pll)
2225 u32 dsp_xclks_per_row, dsp_loop_latency, dsp_precision, dsp_off, dsp_on;
2226 u32 xclks_per_row, fifo_off, fifo_on, y, fifo_size, page_size;
2228 /* xclocks_per_row<<11 */
2229 xclks_per_row = (pll->mclk_fb_div*pll->vclk_post_div_real*64<<11)/
2230 (pll->vclk_fb_div*pll->mclk_post_div_real*bpp);
2231 if (xclks_per_row < (1<<11))
2232 FAIL("Dotclock to high");
2233 if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == VT_CHIP_ID ||
2234 Gx == VU_CHIP_ID || Gx == GV_CHIP_ID || Gx == GW_CHIP_ID ||
2235 Gx == GZ_CHIP_ID) {
2236 fifo_size = 24;
2237 dsp_loop_latency = 0;
2238 } else {
2239 fifo_size = 32;
2240 dsp_loop_latency = 2;
2242 dsp_precision = 0;
2243 y = (xclks_per_row*fifo_size)>>11;
2244 while (y) {
2245 y >>= 1;
2246 dsp_precision++;
2248 dsp_precision -= 5;
2249 /* fifo_off<<6 */
2250 fifo_off = ((xclks_per_row*(fifo_size-1))>>5)+(3<<6);
2252 if (info->total_vram > 1*1024*1024) {
2253 if (info->ram_type >= SDRAM) {
2254 /* >1 MB SDRAM */
2255 dsp_loop_latency += 8;
2256 page_size = 8;
2257 } else {
2258 /* >1 MB DRAM */
2259 dsp_loop_latency += 6;
2260 page_size = 9;
2262 } else {
2263 if (info->ram_type >= SDRAM) {
2264 /* <2 MB SDRAM */
2265 dsp_loop_latency += 9;
2266 page_size = 10;
2267 } else {
2268 /* <2 MB DRAM */
2269 dsp_loop_latency += 8;
2270 page_size = 10;
2273 /* fifo_on<<6 */
2274 if (xclks_per_row >= (page_size<<11))
2275 fifo_on = ((2*page_size+1)<<6)+(xclks_per_row>>5);
2276 else
2277 fifo_on = (3*page_size+2)<<6;
2279 dsp_xclks_per_row = xclks_per_row>>dsp_precision;
2280 dsp_on = fifo_on>>dsp_precision;
2281 dsp_off = fifo_off>>dsp_precision;
2283 pll->dsp_config = (dsp_xclks_per_row & 0x3fff) |
2284 ((dsp_loop_latency & 0xf)<<16) |
2285 ((dsp_precision & 7)<<20);
2286 pll->dsp_on_off = (dsp_on & 0x7ff) | ((dsp_off & 0x7ff)<<16);
2287 return 0;
2290 static int aty_valid_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
2291 struct pll_ct *pll)
2293 u32 q, x; /* x is a workaround for sparc64-linux-gcc */
2294 x = x; /* x is a workaround for sparc64-linux-gcc */
2296 pll->pll_ref_div = info->pll_per*2*255/info->ref_clk_per;
2298 /* FIXME: use the VTB/GTB /3 post divider if it's better suited */
2299 q = info->ref_clk_per*pll->pll_ref_div*4/info->mclk_per; /* actually 8*q */
2300 if (q < 16*8 || q > 255*8)
2301 FAIL("mclk out of range");
2302 else if (q < 32*8)
2303 pll->mclk_post_div_real = 8;
2304 else if (q < 64*8)
2305 pll->mclk_post_div_real = 4;
2306 else if (q < 128*8)
2307 pll->mclk_post_div_real = 2;
2308 else
2309 pll->mclk_post_div_real = 1;
2310 pll->mclk_fb_div = q*pll->mclk_post_div_real/8;
2312 /* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
2313 q = info->ref_clk_per*pll->pll_ref_div*4/vclk_per; /* actually 8*q */
2314 if (q < 16*8 || q > 255*8)
2315 FAIL("vclk out of range");
2316 else if (q < 32*8)
2317 pll->vclk_post_div_real = 8;
2318 else if (q < 64*8)
2319 pll->vclk_post_div_real = 4;
2320 else if (q < 128*8)
2321 pll->vclk_post_div_real = 2;
2322 else
2323 pll->vclk_post_div_real = 1;
2324 pll->vclk_fb_div = q*pll->vclk_post_div_real/8;
2325 return 0;
2328 static void aty_calc_pll_ct(const struct fb_info_aty *info, struct pll_ct *pll)
2330 u8 mpostdiv = 0;
2331 u8 vpostdiv = 0;
2333 if ((((Gx == GT_CHIP_ID) && (Rev & 0x03)) || (Gx == GU_CHIP_ID) ||
2334 (Gx == GV_CHIP_ID) || (Gx == GW_CHIP_ID) || (Gx == GZ_CHIP_ID) ||
2335 (Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) ||
2336 (Gx == GI_CHIP_ID) || (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID) ||
2337 (Gx == VU_CHIP_ID)) && (info->ram_type >= SDRAM))
2338 pll->pll_gen_cntl = 0x04;
2339 else
2340 pll->pll_gen_cntl = 0x84;
2342 switch (pll->mclk_post_div_real) {
2343 case 1:
2344 mpostdiv = 0;
2345 break;
2346 case 2:
2347 mpostdiv = 1;
2348 break;
2349 case 3:
2350 mpostdiv = 4;
2351 break;
2352 case 4:
2353 mpostdiv = 2;
2354 break;
2355 case 8:
2356 mpostdiv = 3;
2357 break;
2359 pll->pll_gen_cntl |= mpostdiv<<4; /* mclk */
2361 if (Gx == VT_CHIP_ID && (Rev == 0x40 || Rev == 0x48))
2362 pll->pll_ext_cntl = 0;
2363 else
2364 pll->pll_ext_cntl = mpostdiv; /* xclk == mclk */
2366 switch (pll->vclk_post_div_real) {
2367 case 2:
2368 vpostdiv = 1;
2369 break;
2370 case 3:
2371 pll->pll_ext_cntl |= 0x10;
2372 case 1:
2373 vpostdiv = 0;
2374 break;
2375 case 6:
2376 pll->pll_ext_cntl |= 0x10;
2377 case 4:
2378 vpostdiv = 2;
2379 break;
2380 case 12:
2381 pll->pll_ext_cntl |= 0x10;
2382 case 8:
2383 vpostdiv = 3;
2384 break;
2387 pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */
2388 pll->vclk_post_div = vpostdiv;
2391 static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
2392 u8 bpp, struct pll_ct *pll)
2394 int err;
2396 if ((err = aty_valid_pll_ct(info, vclk_per, pll)))
2397 return err;
2398 if (!(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
2399 Gx == ET_CHIP_ID ||
2400 ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07)))) {
2401 if ((err = aty_dsp_gt(info, bpp, pll)))
2402 return err;
2404 aty_calc_pll_ct(info, pll);
2405 return 0;
2408 static u32 aty_pll_ct_to_var(const struct pll_ct *pll,
2409 const struct fb_info_aty *info)
2411 u32 ref_clk_per = info->ref_clk_per;
2412 u8 pll_ref_div = pll->pll_ref_div;
2413 u8 vclk_fb_div = pll->vclk_fb_div;
2414 u8 vclk_post_div = pll->vclk_post_div_real;
2416 return ref_clk_per*pll_ref_div*vclk_post_div/vclk_fb_div/2;
2419 /* ------------------------------------------------------------------------- */
2421 static void atyfb_set_par(const struct atyfb_par *par,
2422 struct fb_info_aty *info)
2424 u32 i;
2425 int accelmode;
2426 int muxmode;
2427 u8 tmp;
2429 accelmode = par->accel_flags; /* hack */
2431 info->current_par = *par;
2433 if (info->blitter_may_be_busy)
2434 wait_for_idle(info);
2435 tmp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
2436 aty_set_crtc(info, &par->crtc);
2437 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info);
2438 /* better call aty_StrobeClock ?? */
2439 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, CLOCK_STROBE, info);
2441 if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID)) {
2442 switch (info->dac_subtype) {
2443 case DAC_IBMRGB514:
2444 aty_set_dac_514(info, par->crtc.bpp);
2445 break;
2446 case DAC_ATI68860_B:
2447 case DAC_ATI68860_C:
2448 muxmode = aty_set_dac_ATI68860_B(info, par->crtc.bpp,
2449 accelmode);
2450 aty_st_le32(BUS_CNTL, 0x890e20f1, info);
2451 aty_st_le32(DAC_CNTL, 0x47052100, info);
2452 break;
2453 case DAC_ATT20C408:
2454 muxmode = aty_set_dac_ATT21C498(info, &par->pll.ics2595,
2455 par->crtc.bpp);
2456 aty_st_le32(BUS_CNTL, 0x890e20f1, info);
2457 aty_st_le32(DAC_CNTL, 0x00072000, info);
2458 break;
2459 case DAC_ATT21C498:
2460 muxmode = aty_set_dac_ATT21C498(info, &par->pll.ics2595,
2461 par->crtc.bpp);
2462 aty_st_le32(BUS_CNTL, 0x890e20f1, info);
2463 aty_st_le32(DAC_CNTL, 0x00072000, info);
2464 break;
2465 default:
2466 printk(" atyfb_set_par: DAC type not implemented yet!\n");
2467 aty_st_le32(BUS_CNTL, 0x890e20f1, info);
2468 aty_st_le32(DAC_CNTL, 0x47052100, info);
2469 /* new in 2.2.3p1 from Geert. ???????? */
2470 aty_st_le32(BUS_CNTL, 0x590e10ff, info);
2471 aty_st_le32(DAC_CNTL, 0x47012100, info);
2472 break;
2475 switch (info->clk_type) {
2476 case CLK_ATI18818_1:
2477 aty_set_pll18818(info, &par->pll.ics2595);
2478 break;
2479 case CLK_STG1703:
2480 aty_set_pll_1703(info, &par->pll.ics2595);
2481 break;
2482 case CLK_CH8398:
2483 aty_set_pll_8398(info, &par->pll.ics2595);
2484 break;
2485 case CLK_ATT20C408:
2486 aty_set_pll_408(info, &par->pll.ics2595);
2487 break;
2488 case CLK_IBMRGB514:
2489 aty_set_pll_gx(info, &par->pll.gx);
2490 break;
2491 default:
2492 printk(" atyfb_set_par: CLK type not implemented yet!");
2493 break;
2496 /* Don't forget MEM_CNTL */
2497 i = aty_ld_le32(MEM_CNTL, info) & 0xf0ffffff;
2498 switch (par->crtc.bpp) {
2499 case 8:
2500 i |= 0x02000000;
2501 break;
2502 case 16:
2503 i |= 0x03000000;
2504 break;
2505 case 32:
2506 i |= 0x06000000;
2507 break;
2509 aty_st_le32(MEM_CNTL, i, info);
2511 } else {
2512 aty_set_pll_ct(info, &par->pll.ct);
2513 i = aty_ld_le32(MEM_CNTL, info) & 0xf00fffff;
2514 if (!(Gx == VT_CHIP_ID && (Rev == 0x40 || Rev == 0x48)))
2515 i |= info->mem_refresh_rate << 20;
2516 switch (par->crtc.bpp) {
2517 case 8:
2518 case 24:
2519 i |= 0x00000000;
2520 break;
2521 case 16:
2522 i |= 0x04000000;
2523 break;
2524 case 32:
2525 i |= 0x08000000;
2526 break;
2528 if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID)) {
2529 aty_st_le32(DAC_CNTL, 0x87010184, info);
2530 aty_st_le32(BUS_CNTL, 0x680000f9, info);
2531 } else if ((Gx == VT_CHIP_ID) || (Gx == VU_CHIP_ID)) {
2532 aty_st_le32(DAC_CNTL, 0x87010184, info);
2533 aty_st_le32(BUS_CNTL, 0x680000f9, info);
2534 } else if ((Gx == LN_CHIP_ID) || (Gx == LM_CHIP_ID)) {
2535 aty_st_le32(DAC_CNTL, 0x80010102, info);
2536 aty_st_le32(BUS_CNTL, 0x7b33a040, info);
2537 } else {
2538 /* GT */
2539 aty_st_le32(DAC_CNTL, 0x86010102, info);
2540 aty_st_le32(BUS_CNTL, 0x7b23a040, info);
2541 aty_st_le32(EXT_MEM_CNTL,
2542 aty_ld_le32(EXT_MEM_CNTL, info) | 0x5000001, info);
2544 aty_st_le32(MEM_CNTL, i, info);
2546 aty_st_8(DAC_MASK, 0xff, info);
2548 /* Initialize the graphics engine */
2549 if (par->accel_flags & FB_ACCELF_TEXT)
2550 init_engine(par, info);
2552 #ifdef CONFIG_FB_COMPAT_XPMAC
2553 if (!console_fb_info || console_fb_info == &info->fb_info) {
2554 struct fb_var_screeninfo var;
2555 int vmode, cmode;
2556 display_info.height = ((par->crtc.v_tot_disp>>16) & 0x7ff)+1;
2557 display_info.width = (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8;
2558 display_info.depth = par->crtc.bpp;
2559 display_info.pitch = par->crtc.vxres*par->crtc.bpp/8;
2560 atyfb_encode_var(&var, par, info);
2561 if (mac_var_to_vmode(&var, &vmode, &cmode))
2562 display_info.mode = 0;
2563 else
2564 display_info.mode = vmode;
2565 strcpy(display_info.name, atyfb_name);
2566 display_info.fb_address = info->frame_buffer_phys;
2567 display_info.cmap_adr_address = info->ati_regbase_phys+0xc0;
2568 display_info.cmap_data_address = info->ati_regbase_phys+0xc1;
2569 display_info.disp_reg_address = info->ati_regbase_phys;
2571 #endif /* CONFIG_FB_COMPAT_XPMAC */
2574 static int atyfb_decode_var(const struct fb_var_screeninfo *var,
2575 struct atyfb_par *par,
2576 const struct fb_info_aty *info)
2578 int err;
2580 if ((err = aty_var_to_crtc(info, var, &par->crtc)))
2581 return err;
2582 if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID))
2583 switch (info->clk_type) {
2584 case CLK_ATI18818_1:
2585 err = aty_var_to_pll_18818(var->pixclock, &par->pll.ics2595);
2586 break;
2587 case CLK_STG1703:
2588 err = aty_var_to_pll_1703(var->pixclock, &par->pll.ics2595);
2589 break;
2590 case CLK_CH8398:
2591 err = aty_var_to_pll_8398(var->pixclock, &par->pll.ics2595);
2592 break;
2593 case CLK_ATT20C408:
2594 err = aty_var_to_pll_408(var->pixclock, &par->pll.ics2595);
2595 break;
2596 case CLK_IBMRGB514:
2597 err = aty_var_to_pll_514(var->pixclock, &par->pll.gx);
2598 break;
2600 else
2601 err = aty_var_to_pll_ct(info, var->pixclock, par->crtc.bpp,
2602 &par->pll.ct);
2603 if (err)
2604 return err;
2606 if (var->accel_flags & FB_ACCELF_TEXT)
2607 par->accel_flags = FB_ACCELF_TEXT;
2608 else
2609 par->accel_flags = 0;
2611 #if 0 /* fbmon is not done. uncomment for 2.5.x -brad */
2612 if (!fbmon_valid_timings(var->pixclock, htotal, vtotal, info))
2613 return -EINVAL;
2614 #endif
2616 return 0;
2619 static int atyfb_encode_var(struct fb_var_screeninfo *var,
2620 const struct atyfb_par *par,
2621 const struct fb_info_aty *info)
2623 int err;
2625 memset(var, 0, sizeof(struct fb_var_screeninfo));
2627 if ((err = aty_crtc_to_var(&par->crtc, var)))
2628 return err;
2629 if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID))
2630 switch (info->clk_type) {
2631 case CLK_ATI18818_1:
2632 var->pixclock = aty_pll_18818_to_var(&par->pll.ics2595);
2633 break;
2634 case CLK_STG1703:
2635 var->pixclock = aty_pll_1703_to_var(&par->pll.ics2595);
2636 break;
2637 case CLK_CH8398:
2638 var->pixclock = aty_pll_8398_to_var(&par->pll.ics2595);
2639 break;
2640 case CLK_ATT20C408:
2641 var->pixclock = aty_pll_408_to_var(&par->pll.ics2595);
2642 break;
2643 case CLK_IBMRGB514:
2644 var->pixclock = aty_pll_gx_to_var(&par->pll.gx, info);
2645 break;
2647 else
2648 var->pixclock = aty_pll_ct_to_var(&par->pll.ct, info);
2650 var->height = -1;
2651 var->width = -1;
2652 var->accel_flags = par->accel_flags;
2654 return 0;
2659 static void set_off_pitch(struct atyfb_par *par,
2660 const struct fb_info_aty *info)
2662 u32 xoffset = par->crtc.xoffset;
2663 u32 yoffset = par->crtc.yoffset;
2664 u32 vxres = par->crtc.vxres;
2665 u32 bpp = par->crtc.bpp;
2667 par->crtc.off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19);
2668 aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, info);
2673 * Open/Release the frame buffer device
2676 static int atyfb_open(struct fb_info *info, int user)
2679 #ifdef __sparc__
2680 struct fb_info_aty *fb = (struct fb_info_aty *)info;
2682 if (user) {
2683 fb->open++;
2684 fb->mmaped = 0;
2685 fb->vtconsole = -1;
2686 } else {
2687 fb->consolecnt++;
2689 #endif
2690 return(0);
2693 struct fb_var_screeninfo default_var = {
2694 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
2695 640, 480, 640, 480, 0, 0, 8, 0,
2696 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
2697 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
2698 0, FB_VMODE_NONINTERLACED
2701 static int atyfb_release(struct fb_info *info, int user)
2703 #ifdef __sparc__
2704 struct fb_info_aty *fb = (struct fb_info_aty *)info;
2706 if (user) {
2707 fb->open--;
2708 udelay(1000);
2709 wait_for_idle(fb);
2710 if (!fb->open) {
2711 int was_mmaped = fb->mmaped;
2713 fb->mmaped = 0;
2714 if (fb->vtconsole != -1)
2715 vt_cons[fb->vtconsole]->vc_mode = KD_TEXT;
2716 fb->vtconsole = -1;
2718 if (was_mmaped) {
2719 struct fb_var_screeninfo var;
2721 /* Now reset the default display config, we have no
2722 * idea what the program(s) which mmap'd the chip did
2723 * to the configuration, nor whether it restored it
2724 * correctly.
2726 var = default_var;
2727 if (noaccel)
2728 var.accel_flags &= ~FB_ACCELF_TEXT;
2729 else
2730 var.accel_flags |= FB_ACCELF_TEXT;
2731 if (var.yres == var.yres_virtual) {
2732 u32 vram = (fb->total_vram - (PAGE_SIZE << 2));
2733 var.yres_virtual = ((vram * 8) / var.bits_per_pixel) /
2734 var.xres_virtual;
2735 if (var.yres_virtual < var.yres)
2736 var.yres_virtual = var.yres;
2738 atyfb_set_var(&var, -1, &fb->fb_info);
2741 } else {
2742 fb->consolecnt--;
2744 #endif
2745 return(0);
2749 static int encode_fix(struct fb_fix_screeninfo *fix,
2750 const struct atyfb_par *par,
2751 const struct fb_info_aty *info)
2753 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
2755 strcpy(fix->id, atyfb_name);
2756 fix->smem_start = info->frame_buffer_phys;
2757 fix->smem_len = (u32)info->total_vram;
2760 * Reg Block 0 (CT-compatible block) is at ati_regbase_phys
2761 * Reg Block 1 (multimedia extensions) is at ati_regbase_phys-0x400
2763 if (Gx == GX_CHIP_ID || Gx == CX_CHIP_ID) {
2764 fix->mmio_start = info->ati_regbase_phys;
2765 fix->mmio_len = 0x400;
2766 fix->accel = FB_ACCEL_ATI_MACH64GX;
2767 } else if (Gx == CT_CHIP_ID || Gx == ET_CHIP_ID) {
2768 fix->mmio_start = info->ati_regbase_phys;
2769 fix->mmio_len = 0x400;
2770 fix->accel = FB_ACCEL_ATI_MACH64CT;
2771 } else if (Gx == VT_CHIP_ID || Gx == VU_CHIP_ID || Gx == VV_CHIP_ID) {
2772 fix->mmio_start = info->ati_regbase_phys-0x400;
2773 fix->mmio_len = 0x800;
2774 fix->accel = FB_ACCEL_ATI_MACH64VT;
2775 } else {
2776 fix->mmio_start = info->ati_regbase_phys-0x400;
2777 fix->mmio_len = 0x800;
2778 fix->accel = FB_ACCEL_ATI_MACH64GT;
2780 fix->type = FB_TYPE_PACKED_PIXELS;
2781 fix->type_aux = 0;
2782 fix->line_length = par->crtc.vxres*par->crtc.bpp/8;
2783 fix->visual = par->crtc.bpp <= 8 ? FB_VISUAL_PSEUDOCOLOR
2784 : FB_VISUAL_DIRECTCOLOR;
2785 fix->ywrapstep = 0;
2786 fix->xpanstep = 8;
2787 fix->ypanstep = 1;
2789 return 0;
2794 * Get the Fixed Part of the Display
2797 static int atyfb_get_fix(struct fb_fix_screeninfo *fix, int con,
2798 struct fb_info *fb)
2800 const struct fb_info_aty *info = (struct fb_info_aty *)fb;
2801 struct atyfb_par par;
2803 if (con == -1)
2804 par = info->default_par;
2805 else
2806 atyfb_decode_var(&fb_display[con].var, &par, info);
2807 encode_fix(fix, &par, info);
2808 return 0;
2813 * Get the User Defined Part of the Display
2816 static int atyfb_get_var(struct fb_var_screeninfo *var, int con,
2817 struct fb_info *fb)
2819 const struct fb_info_aty *info = (struct fb_info_aty *)fb;
2821 if (con == -1)
2822 atyfb_encode_var(var, &info->default_par, info);
2823 else
2824 *var = fb_display[con].var;
2825 return 0;
2829 static void atyfb_set_dispsw(struct display *disp, struct fb_info_aty *info,
2830 int bpp, int accel)
2832 switch (bpp) {
2833 #ifdef FBCON_HAS_CFB8
2834 case 8:
2835 info->dispsw = accel ? fbcon_aty8 : fbcon_cfb8;
2836 disp->dispsw = &info->dispsw;
2837 break;
2838 #endif
2839 #ifdef FBCON_HAS_CFB16
2840 case 16:
2841 info->dispsw = accel ? fbcon_aty16 : fbcon_cfb16;
2842 disp->dispsw = &info->dispsw;
2843 disp->dispsw_data = info->fbcon_cmap.cfb16;
2844 break;
2845 #endif
2846 #ifdef FBCON_HAS_CFB24
2847 case 24:
2848 info->dispsw = accel ? fbcon_aty24 : fbcon_cfb24;
2849 disp->dispsw = &info->dispsw;
2850 disp->dispsw_data = info->fbcon_cmap.cfb24;
2851 break;
2852 #endif
2853 #ifdef FBCON_HAS_CFB32
2854 case 32:
2855 info->dispsw = accel ? fbcon_aty32 : fbcon_cfb32;
2856 disp->dispsw = &info->dispsw;
2857 disp->dispsw_data = info->fbcon_cmap.cfb32;
2858 break;
2859 #endif
2860 default:
2861 disp->dispsw = &fbcon_dummy;
2863 if (info->cursor) {
2864 info->dispsw.cursor = atyfb_cursor;
2865 info->dispsw.set_font = atyfb_set_font;
2871 * Set the User Defined Part of the Display
2874 static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
2875 struct fb_info *fb)
2877 struct fb_info_aty *info = (struct fb_info_aty *)fb;
2878 struct atyfb_par par;
2879 struct display *display;
2880 int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel, accel, err;
2881 int activate = var->activate;
2883 if (con >= 0)
2884 display = &fb_display[con];
2885 else
2886 display = fb->disp; /* used during initialization */
2888 if ((err = atyfb_decode_var(var, &par, info)))
2889 return err;
2891 atyfb_encode_var(var, &par, (struct fb_info_aty *)info);
2893 if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
2894 oldxres = display->var.xres;
2895 oldyres = display->var.yres;
2896 oldvxres = display->var.xres_virtual;
2897 oldvyres = display->var.yres_virtual;
2898 oldbpp = display->var.bits_per_pixel;
2899 oldaccel = display->var.accel_flags;
2900 display->var = *var;
2901 accel = var->accel_flags & FB_ACCELF_TEXT;
2902 if (oldxres != var->xres || oldyres != var->yres ||
2903 oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
2904 oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) {
2905 struct fb_fix_screeninfo fix;
2907 encode_fix(&fix, &par, info);
2908 display->screen_base = (char *)info->frame_buffer;
2909 display->visual = fix.visual;
2910 display->type = fix.type;
2911 display->type_aux = fix.type_aux;
2912 display->ypanstep = fix.ypanstep;
2913 display->ywrapstep = fix.ywrapstep;
2914 display->line_length = fix.line_length;
2915 display->can_soft_blank = 1;
2916 display->inverse = 0;
2917 if (accel)
2918 display->scrollmode = (info->bus_type == PCI) ? SCROLL_YNOMOVE : 0;
2919 else
2920 display->scrollmode = SCROLL_YREDRAW;
2921 if (info->fb_info.changevar)
2922 (*info->fb_info.changevar)(con);
2924 if (!info->fb_info.display_fg ||
2925 info->fb_info.display_fg->vc_num == con) {
2926 atyfb_set_par(&par, info);
2927 atyfb_set_dispsw(display, info, par.crtc.bpp, accel);
2929 if (oldbpp != var->bits_per_pixel) {
2930 if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
2931 return err;
2932 do_install_cmap(con, &info->fb_info);
2936 return 0;
2941 * Pan or Wrap the Display
2943 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
2946 static int atyfb_pan_display(struct fb_var_screeninfo *var, int con,
2947 struct fb_info *fb)
2949 struct fb_info_aty *info = (struct fb_info_aty *)fb;
2950 u32 xres, yres, xoffset, yoffset;
2951 struct atyfb_par *par = &info->current_par;
2953 xres = (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8;
2954 yres = ((par->crtc.v_tot_disp>>16) & 0x7ff)+1;
2955 xoffset = (var->xoffset+7) & ~7;
2956 yoffset = var->yoffset;
2957 if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres)
2958 return -EINVAL;
2959 par->crtc.xoffset = xoffset;
2960 par->crtc.yoffset = yoffset;
2961 set_off_pitch(par, info);
2962 return 0;
2966 * Get the Colormap
2969 static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
2970 struct fb_info *info)
2972 if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */
2973 return fb_get_cmap(cmap, kspc, atyfb_getcolreg, info);
2974 else if (fb_display[con].cmap.len) /* non default colormap? */
2975 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
2976 else {
2977 int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
2978 fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
2980 return 0;
2984 * Set the Colormap
2987 static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
2988 struct fb_info *info)
2990 int err;
2991 struct display *disp;
2993 if (con >= 0)
2994 disp = &fb_display[con];
2995 else
2996 disp = info->disp;
2997 if (!disp->cmap.len) { /* no colormap allocated? */
2998 int size = disp->var.bits_per_pixel == 16 ? 32 : 256;
2999 if ((err = fb_alloc_cmap(&disp->cmap, size, 0)))
3000 return err;
3002 if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */
3003 return fb_set_cmap(cmap, kspc, atyfb_setcolreg, info);
3004 else
3005 fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
3006 return 0;
3010 #ifdef DEBUG
3011 #define ATYIO_CLKR 0x41545900 /* ATY\00 */
3012 #define ATYIO_CLKW 0x41545901 /* ATY\01 */
3014 struct atyclk {
3015 u32 ref_clk_per;
3016 u8 pll_ref_div;
3017 u8 mclk_fb_div;
3018 u8 mclk_post_div; /* 1,2,3,4,8 */
3019 u8 vclk_fb_div;
3020 u8 vclk_post_div; /* 1,2,3,4,6,8,12 */
3021 u32 dsp_xclks_per_row; /* 0-16383 */
3022 u32 dsp_loop_latency; /* 0-15 */
3023 u32 dsp_precision; /* 0-7 */
3024 u32 dsp_on; /* 0-2047 */
3025 u32 dsp_off; /* 0-2047 */
3027 #endif
3029 static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
3030 u_long arg, int con, struct fb_info *info2)
3032 #if defined(__sparc__) || defined(DEBUG)
3033 struct fb_info_aty *info = (struct fb_info_aty *)info2;
3034 #endif /* __sparc__ || DEBUG */
3035 #ifdef __sparc__
3036 struct fbtype fbtyp;
3037 struct display *disp;
3039 if (con >= 0)
3040 disp = &fb_display[con];
3041 else
3042 disp = info2->disp;
3043 #endif
3045 switch (cmd) {
3046 #ifdef __sparc__
3047 case FBIOGTYPE:
3048 fbtyp.fb_type = FBTYPE_PCI_GENERIC;
3049 fbtyp.fb_width = info->current_par.crtc.vxres;
3050 fbtyp.fb_height = info->current_par.crtc.vyres;
3051 fbtyp.fb_depth = info->current_par.crtc.bpp;
3052 fbtyp.fb_cmsize = disp->cmap.len;
3053 fbtyp.fb_size = info->total_vram;
3054 if (copy_to_user((struct fbtype *)arg, &fbtyp, sizeof(fbtyp)))
3055 return -EFAULT;
3056 break;
3057 #endif /* __sparc__ */
3058 #ifdef DEBUG
3059 case ATYIO_CLKR:
3060 if ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
3061 struct atyclk clk;
3062 struct pll_ct *pll = &info->current_par.pll.ct;
3063 u32 dsp_config = pll->dsp_config;
3064 u32 dsp_on_off = pll->dsp_on_off;
3065 clk.ref_clk_per = info->ref_clk_per;
3066 clk.pll_ref_div = pll->pll_ref_div;
3067 clk.mclk_fb_div = pll->mclk_fb_div;
3068 clk.mclk_post_div = pll->mclk_post_div_real;
3069 clk.vclk_fb_div = pll->vclk_fb_div;
3070 clk.vclk_post_div = pll->vclk_post_div_real;
3071 clk.dsp_xclks_per_row = dsp_config & 0x3fff;
3072 clk.dsp_loop_latency = (dsp_config>>16) & 0xf;
3073 clk.dsp_precision = (dsp_config>>20) & 7;
3074 clk.dsp_on = dsp_on_off & 0x7ff;
3075 clk.dsp_off = (dsp_on_off>>16) & 0x7ff;
3076 if (copy_to_user((struct atyclk *)arg, &clk, sizeof(clk)))
3077 return -EFAULT;
3078 } else
3079 return -EINVAL;
3080 break;
3081 case ATYIO_CLKW:
3082 if ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
3083 struct atyclk clk;
3084 struct pll_ct *pll = &info->current_par.pll.ct;
3085 if (copy_from_user(&clk, (struct atyclk *)arg, sizeof(clk)))
3086 return -EFAULT;
3087 info->ref_clk_per = clk.ref_clk_per;
3088 pll->pll_ref_div = clk.pll_ref_div;
3089 pll->mclk_fb_div = clk.mclk_fb_div;
3090 pll->mclk_post_div_real = clk.mclk_post_div;
3091 pll->vclk_fb_div = clk.vclk_fb_div;
3092 pll->vclk_post_div_real = clk.vclk_post_div;
3093 pll->dsp_config = (clk.dsp_xclks_per_row & 0x3fff) |
3094 ((clk.dsp_loop_latency & 0xf)<<16) |
3095 ((clk.dsp_precision & 7)<<20);
3096 pll->dsp_on_off = (clk.dsp_on & 0x7ff) |
3097 ((clk.dsp_off & 0x7ff)<<16);
3098 aty_calc_pll_ct(info, pll);
3099 aty_set_pll_ct(info, pll);
3100 } else
3101 return -EINVAL;
3102 break;
3103 #endif /* DEBUG */
3104 default:
3105 return -EINVAL;
3107 return 0;
3110 static int atyfb_rasterimg(struct fb_info *info, int start)
3112 struct fb_info_aty *fb = (struct fb_info_aty *)info;
3114 if (fb->blitter_may_be_busy)
3115 wait_for_idle(fb);
3116 return 0;
3119 #ifdef __sparc__
3120 static int atyfb_mmap(struct fb_info *info, struct file *file,
3121 struct vm_area_struct *vma)
3123 struct fb_info_aty *fb = (struct fb_info_aty *)info;
3124 unsigned int size, page, map_size = 0;
3125 unsigned long map_offset = 0;
3126 unsigned long off;
3127 int i;
3129 if (!fb->mmap_map)
3130 return -ENXIO;
3132 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
3133 return -EINVAL;
3135 off = vma->vm_pgoff << PAGE_SHIFT;
3136 size = vma->vm_end - vma->vm_start;
3138 /* To stop the swapper from even considering these pages. */
3139 vma->vm_flags |= (VM_SHM | VM_LOCKED);
3141 if (((vma->vm_pgoff == 0) && (size == fb->total_vram)) ||
3142 ((off == fb->total_vram) && (size == PAGE_SIZE)))
3143 off += 0x8000000000000000UL;
3145 vma->vm_pgoff = off >> PAGE_SHIFT; /* propagate off changes */
3147 #ifdef __sparc_v9__
3148 /* Align it as much as desirable */
3150 unsigned long j, align;
3151 int max = -1;
3153 map_offset = off + size;
3154 for (i = 0; fb->mmap_map[i].size; i++) {
3155 if (fb->mmap_map[i].voff < off)
3156 continue;
3157 if (fb->mmap_map[i].voff >= map_offset)
3158 break;
3159 if (max < 0 ||
3160 fb->mmap_map[i].size > fb->mmap_map[max].size)
3161 max = i;
3163 if (max >= 0) {
3164 j = fb->mmap_map[max].size;
3165 if (fb->mmap_map[max].voff + j > map_offset)
3166 j = map_offset - fb->mmap_map[max].voff;
3167 for (align = 0x400000; align > PAGE_SIZE; align >>= 3)
3168 if (j >= align &&
3169 !(fb->mmap_map[max].poff & (align - 1)))
3170 break;
3171 if (align > PAGE_SIZE) {
3172 j = align;
3173 align = j - ((vma->vm_start
3174 + fb->mmap_map[max].voff
3175 - off) & (j - 1));
3176 if (align != j) {
3177 struct vm_area_struct *vmm;
3179 vmm = find_vma(current->mm,
3180 vma->vm_start);
3181 if (!vmm || vmm->vm_start
3182 >= vma->vm_end + align) {
3183 vma->vm_start += align;
3184 vma->vm_end += align;
3190 #endif
3192 /* Each page, see which map applies */
3193 for (page = 0; page < size; ) {
3194 map_size = 0;
3195 for (i = 0; fb->mmap_map[i].size; i++) {
3196 unsigned long start = fb->mmap_map[i].voff;
3197 unsigned long end = start + fb->mmap_map[i].size;
3198 unsigned long offset = off + page;
3200 if (start > offset)
3201 continue;
3202 if (offset >= end)
3203 continue;
3205 map_size = fb->mmap_map[i].size - (offset - start);
3206 map_offset = fb->mmap_map[i].poff + (offset - start);
3207 break;
3209 if (!map_size) {
3210 page += PAGE_SIZE;
3211 continue;
3213 if (page + map_size > size)
3214 map_size = size - page;
3216 pgprot_val(vma->vm_page_prot) &= ~(fb->mmap_map[i].prot_mask);
3217 pgprot_val(vma->vm_page_prot) |= fb->mmap_map[i].prot_flag;
3219 if (remap_page_range(vma->vm_start + page, map_offset,
3220 map_size, vma->vm_page_prot))
3221 return -EAGAIN;
3223 page += map_size;
3226 if (!map_size)
3227 return -EINVAL;
3229 vma->vm_flags |= VM_IO;
3231 if (!fb->mmaped) {
3232 int lastconsole = 0;
3234 if (info->display_fg)
3235 lastconsole = info->display_fg->vc_num;
3236 fb->mmaped = 1;
3237 if (fb->consolecnt && fb_display[lastconsole].fb_info == info) {
3238 fb->vtconsole = lastconsole;
3239 vt_cons[lastconsole]->vc_mode = KD_GRAPHICS;
3242 return 0;
3245 static struct {
3246 u32 yoffset;
3247 u8 r[2][256];
3248 u8 g[2][256];
3249 u8 b[2][256];
3250 } atyfb_save;
3252 static void atyfb_save_palette(struct fb_info *fb, int enter)
3254 struct fb_info_aty *info = (struct fb_info_aty *)fb;
3255 int i, tmp, scale;
3257 for (i = 0; i < 256; i++) {
3258 tmp = aty_ld_8(DAC_CNTL, info) & 0xfc;
3259 if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == GV_CHIP_ID ||
3260 Gx == GW_CHIP_ID || Gx == GZ_CHIP_ID || Gx == LG_CHIP_ID ||
3261 Gx == GB_CHIP_ID || Gx == GD_CHIP_ID || Gx == GI_CHIP_ID ||
3262 Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID)
3263 tmp |= 0x2;
3264 aty_st_8(DAC_CNTL, tmp, info);
3265 aty_st_8(DAC_MASK, 0xff, info);
3267 scale = ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID) &&
3268 (info->current_par.crtc.bpp == 16)) ? 3 : 0;
3269 writeb(i << scale, &info->aty_cmap_regs->rindex);
3271 atyfb_save.r[enter][i] = readb(&info->aty_cmap_regs->lut);
3272 atyfb_save.g[enter][i] = readb(&info->aty_cmap_regs->lut);
3273 atyfb_save.b[enter][i] = readb(&info->aty_cmap_regs->lut);
3274 writeb(i << scale, &info->aty_cmap_regs->windex);
3275 writeb(atyfb_save.r[1-enter][i], &info->aty_cmap_regs->lut);
3276 writeb(atyfb_save.g[1-enter][i], &info->aty_cmap_regs->lut);
3277 writeb(atyfb_save.b[1-enter][i], &info->aty_cmap_regs->lut);
3281 static void atyfb_palette(int enter)
3283 struct fb_info_aty *info;
3284 struct atyfb_par *par;
3285 struct display *d;
3286 int i;
3288 for (i = 0; i < MAX_NR_CONSOLES; i++) {
3289 d = &fb_display[i];
3290 if (d->fb_info &&
3291 d->fb_info->fbops == &atyfb_ops &&
3292 d->fb_info->display_fg &&
3293 d->fb_info->display_fg->vc_num == i) {
3294 atyfb_save_palette(d->fb_info, enter);
3295 info = (struct fb_info_aty *)d->fb_info;
3296 par = &info->current_par;
3297 if (enter) {
3298 atyfb_save.yoffset = par->crtc.yoffset;
3299 par->crtc.yoffset = 0;
3300 set_off_pitch(par, info);
3301 } else {
3302 par->crtc.yoffset = atyfb_save.yoffset;
3303 set_off_pitch(par, info);
3305 break;
3309 #endif /* __sparc__ */
3312 * Initialisation
3315 static int __init aty_init(struct fb_info_aty *info, const char *name)
3317 u32 chip_id;
3318 u32 i;
3319 int j, k;
3320 struct fb_var_screeninfo var;
3321 struct display *disp;
3322 const char *chipname = NULL, *ramname = NULL, *xtal;
3323 int pll, mclk, gtb_memsize;
3324 #if defined(CONFIG_PPC)
3325 int sense;
3326 #endif
3327 u8 pll_ref_div;
3329 info->aty_cmap_regs = (struct aty_cmap_regs *)(info->ati_regbase+0xc0);
3330 chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
3331 Gx = chip_id & CFG_CHIP_TYPE;
3332 Rev = (chip_id & CFG_CHIP_REV)>>24;
3333 for (j = 0; j < (sizeof(aty_features)/sizeof(*aty_features)); j++)
3334 if (aty_features[j].chip_type == Gx) {
3335 chipname = aty_features[j].name;
3336 info->dac_type = (aty_ld_le32(DAC_CNTL, info) >> 16) & 0x07;
3337 break;
3339 if (!chipname) {
3340 printk("atyfb: Unknown mach64 0x%04x\n", Gx);
3341 return 0;
3342 } else
3343 printk("atyfb: %s [0x%04x rev 0x%02x] ", chipname, Gx, Rev);
3344 if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID)) {
3345 info->bus_type = (aty_ld_le32(CONFIG_STAT0, info) >> 0) & 0x07;
3346 info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) >> 3) & 0x07;
3347 ramname = aty_gx_ram[info->ram_type];
3348 /* FIXME: clockchip/RAMDAC probing? */
3349 #ifdef CONFIG_ATARI
3350 info->clk_type = CLK_ATI18818_1;
3351 info->dac_type = (aty_ld_le32(CONFIG_STAT0, info) >> 9) & 0x07;
3352 if (info->dac_type == 0x07)
3353 info->dac_subtype = DAC_ATT20C408;
3354 else
3355 info->dac_subtype = (aty_ld_8(SCRATCH_REG1 + 1, info) & 0xF0) |
3356 info->dac_type;
3357 #else
3358 info->dac_type = DAC_IBMRGB514;
3359 info->dac_subtype = DAC_IBMRGB514;
3360 info->clk_type = CLK_IBMRGB514;
3361 #endif
3362 /* FIXME */
3363 pll = 135;
3364 mclk = 50;
3365 } else {
3366 info->bus_type = PCI;
3367 info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) & 0x07);
3368 ramname = aty_ct_ram[info->ram_type];
3369 info->dac_type = DAC_INTERNAL;
3370 info->dac_subtype = DAC_INTERNAL;
3371 info->clk_type = CLK_INTERNAL;
3372 if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID)) {
3373 pll = 135;
3374 mclk = 60;
3375 } else {
3376 mclk = info->ram_type >= SDRAM ? 67 : 63;
3377 if ((Gx == VT_CHIP_ID) && (Rev == 0x08)) {
3378 /* VTA3 */
3379 pll = 170;
3380 } else if (((Gx == VT_CHIP_ID) && ((Rev == 0x40) ||
3381 (Rev == 0x48))) ||
3382 ((Gx == VT_CHIP_ID) && ((Rev == 0x01) ||
3383 (Rev == 0x9a))) ||
3384 Gx == VU_CHIP_ID) {
3385 /* VTA4 or VTB */
3386 pll = 200;
3387 } else if (Gx == VV_CHIP_ID) {
3388 /* VT4 */
3389 pll = 230;
3390 mclk = 83;
3391 } else if (Gx == VT_CHIP_ID) {
3392 /* other VT */
3393 pll = 135;
3394 mclk = 63;
3395 } else if ((Gx == GT_CHIP_ID) && (Rev & 0x01)) {
3396 /* RAGE II */
3397 pll = 170;
3398 } else if (((Gx == GT_CHIP_ID) && (Rev & 0x02)) ||
3399 (Gx == GU_CHIP_ID)) {
3400 /* RAGE II+ */
3401 pll = 200;
3402 } else if (Gx == GV_CHIP_ID || Gx == GW_CHIP_ID ||
3403 Gx == GZ_CHIP_ID) {
3404 /* RAGE IIC */
3405 pll = 230;
3406 mclk = 83;
3407 } else if (Gx == GB_CHIP_ID || Gx == GD_CHIP_ID ||
3408 Gx == GI_CHIP_ID || Gx == GP_CHIP_ID ||
3409 Gx == GQ_CHIP_ID || Gx == LB_CHIP_ID ||
3410 Gx == LD_CHIP_ID ||
3411 Gx == LI_CHIP_ID || Gx == LP_CHIP_ID) {
3412 /* RAGE PRO or LT PRO */
3413 pll = 230;
3414 mclk = 100;
3415 } else if (Gx == LG_CHIP_ID) {
3416 /* Rage LT */
3417 pll = 230;
3418 mclk = 63;
3419 } else if ((Gx == LN_CHIP_ID) || (Gx == LM_CHIP_ID)) {
3420 /* Rage mobility M1 */
3421 pll = 230;
3422 mclk = 50;
3423 } else {
3424 /* other RAGE */
3425 pll = 135;
3426 mclk = 63;
3431 info->ref_clk_per = 1000000000000ULL/14318180;
3432 xtal = "14.31818";
3433 if (!(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
3434 Gx == ET_CHIP_ID ||
3435 ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07))) &&
3436 (pll_ref_div = aty_ld_pll(PLL_REF_DIV, info))) {
3437 int diff1, diff2;
3438 diff1 = 510*14/pll_ref_div-pll;
3439 diff2 = 510*29/pll_ref_div-pll;
3440 if (diff1 < 0)
3441 diff1 = -diff1;
3442 if (diff2 < 0)
3443 diff2 = -diff2;
3444 if (diff2 < diff1) {
3445 info->ref_clk_per = 1000000000000ULL/29498928;
3446 xtal = "29.498928";
3450 i = aty_ld_le32(MEM_CNTL, info);
3451 gtb_memsize = !(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
3452 Gx == ET_CHIP_ID ||
3453 ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07)));
3454 if (gtb_memsize)
3455 switch (i & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */
3456 case MEM_SIZE_512K:
3457 info->total_vram = 0x80000;
3458 break;
3459 case MEM_SIZE_1M:
3460 info->total_vram = 0x100000;
3461 break;
3462 case MEM_SIZE_2M_GTB:
3463 info->total_vram = 0x200000;
3464 break;
3465 case MEM_SIZE_4M_GTB:
3466 info->total_vram = 0x400000;
3467 break;
3468 case MEM_SIZE_6M_GTB:
3469 info->total_vram = 0x600000;
3470 break;
3471 case MEM_SIZE_8M_GTB:
3472 info->total_vram = 0x800000;
3473 break;
3474 default:
3475 info->total_vram = 0x80000;
3477 else
3478 switch (i & MEM_SIZE_ALIAS) {
3479 case MEM_SIZE_512K:
3480 info->total_vram = 0x80000;
3481 break;
3482 case MEM_SIZE_1M:
3483 info->total_vram = 0x100000;
3484 break;
3485 case MEM_SIZE_2M:
3486 info->total_vram = 0x200000;
3487 break;
3488 case MEM_SIZE_4M:
3489 info->total_vram = 0x400000;
3490 break;
3491 case MEM_SIZE_6M:
3492 info->total_vram = 0x600000;
3493 break;
3494 case MEM_SIZE_8M:
3495 info->total_vram = 0x800000;
3496 break;
3497 default:
3498 info->total_vram = 0x80000;
3501 if (Gx == GI_CHIP_ID) {
3502 if (aty_ld_le32(CONFIG_STAT1, info) & 0x40000000)
3503 info->total_vram += 0x400000;
3506 if (default_vram) {
3507 info->total_vram = default_vram*1024;
3508 i = i & ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS);
3509 if (info->total_vram <= 0x80000)
3510 i |= MEM_SIZE_512K;
3511 else if (info->total_vram <= 0x100000)
3512 i |= MEM_SIZE_1M;
3513 else if (info->total_vram <= 0x200000)
3514 i |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M;
3515 else if (info->total_vram <= 0x400000)
3516 i |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M;
3517 else if (info->total_vram <= 0x600000)
3518 i |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M;
3519 else
3520 i |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M;
3521 aty_st_le32(MEM_CNTL, i, info);
3523 if (default_pll)
3524 pll = default_pll;
3525 if (default_mclk)
3526 mclk = default_mclk;
3528 printk("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK\n",
3529 info->total_vram == 0x80000 ? 512 : (info->total_vram >> 20),
3530 info->total_vram == 0x80000 ? 'K' : 'M', ramname, xtal, pll, mclk);
3532 if (mclk < 44)
3533 info->mem_refresh_rate = 0; /* 000 = 10 Mhz - 43 Mhz */
3534 else if (mclk < 50)
3535 info->mem_refresh_rate = 1; /* 001 = 44 Mhz - 49 Mhz */
3536 else if (mclk < 55)
3537 info->mem_refresh_rate = 2; /* 010 = 50 Mhz - 54 Mhz */
3538 else if (mclk < 66)
3539 info->mem_refresh_rate = 3; /* 011 = 55 Mhz - 65 Mhz */
3540 else if (mclk < 75)
3541 info->mem_refresh_rate = 4; /* 100 = 66 Mhz - 74 Mhz */
3542 else if (mclk < 80)
3543 info->mem_refresh_rate = 5; /* 101 = 75 Mhz - 79 Mhz */
3544 else if (mclk < 100)
3545 info->mem_refresh_rate = 6; /* 110 = 80 Mhz - 100 Mhz */
3546 else
3547 info->mem_refresh_rate = 7; /* 111 = 100 Mhz and above */
3548 info->pll_per = 1000000/pll;
3549 info->mclk_per = 1000000/mclk;
3551 #ifdef DEBUG
3552 if ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
3553 int i;
3554 printk("BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
3555 "DSP_CONFIG DSP_ON_OFF\n"
3556 "%08x %08x %08x %08x %08x %08x %08x\n"
3557 "PLL",
3558 aty_ld_le32(BUS_CNTL, info), aty_ld_le32(DAC_CNTL, info),
3559 aty_ld_le32(MEM_CNTL, info), aty_ld_le32(EXT_MEM_CNTL, info),
3560 aty_ld_le32(CRTC_GEN_CNTL, info), aty_ld_le32(DSP_CONFIG, info),
3561 aty_ld_le32(DSP_ON_OFF, info));
3562 for (i = 0; i < 16; i++)
3563 printk(" %02x", aty_ld_pll(i, info));
3564 printk("\n");
3566 #endif
3569 * Last page of 8 MB (4 MB on ISA) aperture is MMIO
3570 * FIXME: we should use the auxiliary aperture instead so we can acces the
3571 * full 8 MB of video RAM on 8 MB boards
3573 if (info->total_vram == 0x800000 ||
3574 (info->bus_type == ISA && info->total_vram == 0x400000))
3575 info->total_vram -= GUI_RESERVE;
3577 /* Clear the video memory */
3578 fb_memset((void *)info->frame_buffer, 0, info->total_vram);
3580 disp = &info->disp;
3582 strcpy(info->fb_info.modename, atyfb_name);
3583 info->fb_info.node = -1;
3584 info->fb_info.fbops = &atyfb_ops;
3585 info->fb_info.disp = disp;
3586 strcpy(info->fb_info.fontname, fontname);
3587 info->fb_info.changevar = NULL;
3588 info->fb_info.switch_con = &atyfbcon_switch;
3589 info->fb_info.updatevar = &atyfbcon_updatevar;
3590 info->fb_info.blank = &atyfbcon_blank;
3591 info->fb_info.flags = FBINFO_FLAG_DEFAULT;
3593 #ifdef CONFIG_PMAC_BACKLIGHT
3594 if (Gx == LI_CHIP_ID && machine_is_compatible("PowerBook1,1")) {
3595 /* these bits let the 101 powerbook wake up from sleep -- paulus */
3596 aty_st_lcd(LCD_POWER_MANAGEMENT, aty_ld_lcd(LCD_POWER_MANAGEMENT, info)
3597 | (USE_F32KHZ | TRISTATE_MEM_EN), info);
3599 if ((Gx == LN_CHIP_ID) || (Gx == LM_CHIP_ID))
3600 register_backlight_controller(&aty_backlight_controller, info, "ati");
3601 #endif /* CONFIG_PMAC_BACKLIGHT */
3603 #ifdef MODULE
3604 var = default_var;
3605 #else /* !MODULE */
3606 memset(&var, 0, sizeof(var));
3607 #ifdef CONFIG_PPC
3608 if (_machine == _MACH_Pmac) {
3610 * FIXME: The NVRAM stuff should be put in a Mac-specific file, as it
3611 * applies to all Mac video cards
3613 if (mode_option) {
3614 if (!mac_find_mode(&var, &info->fb_info, mode_option, 8))
3615 var = default_var;
3616 } else {
3617 #ifdef CONFIG_NVRAM
3618 if (default_vmode == VMODE_NVRAM) {
3619 default_vmode = nvram_read_byte(NV_VMODE);
3620 if (default_vmode <= 0 || default_vmode > VMODE_MAX)
3621 default_vmode = VMODE_CHOOSE;
3623 #endif
3624 if (default_vmode == VMODE_CHOOSE) {
3625 if (Gx == LG_CHIP_ID || Gx == LI_CHIP_ID)
3626 /* G3 PowerBook with 1024x768 LCD */
3627 default_vmode = VMODE_1024_768_60;
3628 else if (machine_is_compatible("iMac"))
3629 default_vmode = VMODE_1024_768_75;
3630 else if (machine_is_compatible("PowerBook2,1"))
3631 /* iBook with 800x600 LCD */
3632 default_vmode = VMODE_800_600_60;
3633 else
3634 default_vmode = VMODE_640_480_67;
3635 sense = read_aty_sense(info);
3636 printk(KERN_INFO "atyfb: monitor sense=%x, mode %d\n",
3637 sense, mac_map_monitor_sense(sense));
3639 if (default_vmode <= 0 || default_vmode > VMODE_MAX)
3640 default_vmode = VMODE_640_480_60;
3641 #ifdef CONFIG_NVRAM
3642 if (default_cmode == CMODE_NVRAM)
3643 default_cmode = nvram_read_byte(NV_CMODE);
3644 #endif
3645 if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
3646 default_cmode = CMODE_8;
3647 if (mac_vmode_to_var(default_vmode, default_cmode, &var))
3648 var = default_var;
3651 else if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
3652 var = default_var;
3653 #else /* !CONFIG_PPC */
3654 #ifdef __sparc__
3655 if (mode_option) {
3656 if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
3657 var = default_var;
3658 } else
3659 var = default_var;
3660 #else
3661 if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
3662 var = default_var;
3663 #endif /* !__sparc__ */
3664 #endif /* !CONFIG_PPC */
3665 #endif /* !MODULE */
3666 if (noaccel)
3667 var.accel_flags &= ~FB_ACCELF_TEXT;
3668 else
3669 var.accel_flags |= FB_ACCELF_TEXT;
3671 if (var.yres == var.yres_virtual) {
3672 u32 vram = (info->total_vram - (PAGE_SIZE << 2));
3673 var.yres_virtual = ((vram * 8) / var.bits_per_pixel) / var.xres_virtual;
3674 if (var.yres_virtual < var.yres)
3675 var.yres_virtual = var.yres;
3678 if (atyfb_decode_var(&var, &info->default_par, info)) {
3679 printk("atyfb: can't set default video mode\n");
3680 return 0;
3683 #ifdef __sparc__
3684 atyfb_save_palette(&info->fb_info, 0);
3685 #endif
3686 for (j = 0; j < 16; j++) {
3687 k = color_table[j];
3688 info->palette[j].red = default_red[k];
3689 info->palette[j].green = default_grn[k];
3690 info->palette[j].blue = default_blu[k];
3693 if (Gx != GX_CHIP_ID && Gx != CX_CHIP_ID) {
3694 info->cursor = aty_init_cursor(info);
3695 if (info->cursor) {
3696 info->dispsw.cursor = atyfb_cursor;
3697 info->dispsw.set_font = atyfb_set_font;
3701 atyfb_set_var(&var, -1, &info->fb_info);
3703 if (register_framebuffer(&info->fb_info) < 0)
3704 return 0;
3706 info->next = fb_list;
3707 fb_list = info;
3709 printk("fb%d: %s frame buffer device on %s\n",
3710 GET_FB_IDX(info->fb_info.node), atyfb_name, name);
3711 return 1;
3714 int __init atyfb_init(void)
3716 #if defined(CONFIG_PCI)
3717 struct pci_dev *pdev = NULL;
3718 struct fb_info_aty *info;
3719 unsigned long addr, res_start, res_size;
3720 int i;
3721 #ifdef __sparc__
3722 extern void (*prom_palette) (int);
3723 extern int con_is_present(void);
3724 struct pcidev_cookie *pcp;
3725 char prop[128];
3726 int node, len, j;
3727 u32 mem, chip_id;
3729 /* Do not attach when we have a serial console. */
3730 if (!con_is_present())
3731 return -ENXIO;
3732 #else
3733 u16 tmp;
3734 #endif
3736 while ((pdev = pci_find_device(PCI_VENDOR_ID_ATI, PCI_ANY_ID, pdev))) {
3737 if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
3738 struct resource *rp;
3740 for (i = sizeof(aty_features)/sizeof(*aty_features)-1; i >= 0; i--)
3741 if (pdev->device == aty_features[i].pci_id)
3742 break;
3743 if (i < 0)
3744 continue;
3746 info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
3747 if (!info) {
3748 printk("atyfb_init: can't alloc fb_info_aty\n");
3749 return -ENXIO;
3751 memset(info, 0, sizeof(struct fb_info_aty));
3753 rp = &pdev->resource[0];
3754 if (rp->flags & IORESOURCE_IO)
3755 rp = &pdev->resource[1];
3756 addr = rp->start;
3757 if (!addr)
3758 continue;
3760 res_start = rp->start;
3761 res_size = rp->end-rp->start+1;
3762 if (!request_mem_region(res_start, res_size, "atyfb"))
3763 continue;
3765 #ifdef __sparc__
3767 * Map memory-mapped registers.
3769 info->ati_regbase = addr + 0x7ffc00UL;
3770 info->ati_regbase_phys = addr + 0x7ffc00UL;
3773 * Map in big-endian aperture.
3775 info->frame_buffer = (unsigned long) addr + 0x800000UL;
3776 info->frame_buffer_phys = addr + 0x800000UL;
3779 * Figure mmap addresses from PCI config space.
3780 * Split Framebuffer in big- and little-endian halfs.
3782 for (i = 0; i < 6 && pdev->resource[i].start; i++)
3783 /* nothing */;
3784 j = i + 4;
3786 info->mmap_map = kmalloc(j * sizeof(*info->mmap_map), GFP_ATOMIC);
3787 if (!info->mmap_map) {
3788 printk("atyfb_init: can't alloc mmap_map\n");
3789 kfree(info);
3790 release_mem_region(res_start, res_size);
3791 return -ENXIO;
3793 memset(info->mmap_map, 0, j * sizeof(*info->mmap_map));
3795 for (i = 0, j = 2; i < 6 && pdev->resource[i].start; i++) {
3796 struct resource *rp = &pdev->resource[i];
3797 int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
3798 unsigned long base;
3799 u32 size, pbase;
3801 base = rp->start;
3803 io = (rp->flags & IORESOURCE_IO);
3805 size = rp->end - base + 1;
3807 pci_read_config_dword(pdev, breg, &pbase);
3809 if (io)
3810 size &= ~1;
3813 * Map the framebuffer a second time, this time without
3814 * the braindead _PAGE_IE setting. This is used by the
3815 * fixed Xserver, but we need to maintain the old mapping
3816 * to stay compatible with older ones...
3818 if (base == addr) {
3819 info->mmap_map[j].voff = (pbase + 0x10000000) & PAGE_MASK;
3820 info->mmap_map[j].poff = base & PAGE_MASK;
3821 info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
3822 info->mmap_map[j].prot_mask = _PAGE_CACHE;
3823 info->mmap_map[j].prot_flag = _PAGE_E;
3824 j++;
3828 * Here comes the old framebuffer mapping with _PAGE_IE
3829 * set for the big endian half of the framebuffer...
3831 if (base == addr) {
3832 info->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK;
3833 info->mmap_map[j].poff = (base+0x800000) & PAGE_MASK;
3834 info->mmap_map[j].size = 0x800000;
3835 info->mmap_map[j].prot_mask = _PAGE_CACHE;
3836 info->mmap_map[j].prot_flag = _PAGE_E|_PAGE_IE;
3837 size -= 0x800000;
3838 j++;
3841 info->mmap_map[j].voff = pbase & PAGE_MASK;
3842 info->mmap_map[j].poff = base & PAGE_MASK;
3843 info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
3844 info->mmap_map[j].prot_mask = _PAGE_CACHE;
3845 info->mmap_map[j].prot_flag = _PAGE_E;
3846 j++;
3850 * Fix PROMs idea of MEM_CNTL settings...
3852 mem = aty_ld_le32(MEM_CNTL, info);
3853 chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
3854 if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) &&
3855 !((chip_id >> 24) & 1)) {
3856 switch (mem & 0x0f) {
3857 case 3:
3858 mem = (mem & ~(0x0f)) | 2;
3859 break;
3860 case 7:
3861 mem = (mem & ~(0x0f)) | 3;
3862 break;
3863 case 9:
3864 mem = (mem & ~(0x0f)) | 4;
3865 break;
3866 case 11:
3867 mem = (mem & ~(0x0f)) | 5;
3868 break;
3869 default:
3870 break;
3872 if ((aty_ld_le32(CONFIG_STAT0, info) & 7) >= SDRAM)
3873 mem &= ~(0x00700000);
3875 mem &= ~(0xcf80e000); /* Turn off all undocumented bits. */
3876 aty_st_le32(MEM_CNTL, mem, info);
3879 * If this is the console device, we will set default video
3880 * settings to what the PROM left us with.
3882 node = prom_getchild(prom_root_node);
3883 node = prom_searchsiblings(node, "aliases");
3884 if (node) {
3885 len = prom_getproperty(node, "screen", prop, sizeof(prop));
3886 if (len > 0) {
3887 prop[len] = '\0';
3888 node = prom_finddevice(prop);
3889 } else {
3890 node = 0;
3894 pcp = pdev->sysdata;
3895 if (node == pcp->prom_node) {
3897 struct fb_var_screeninfo *var = &default_var;
3898 unsigned int N, P, Q, M, T;
3899 u32 v_total, h_total;
3900 struct crtc crtc;
3901 u8 pll_regs[16];
3902 u8 clock_cntl;
3904 crtc.vxres = prom_getintdefault(node, "width", 1024);
3905 crtc.vyres = prom_getintdefault(node, "height", 768);
3906 crtc.bpp = prom_getintdefault(node, "depth", 8);
3907 crtc.xoffset = crtc.yoffset = 0;
3908 crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, info);
3909 crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, info);
3910 crtc.v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, info);
3911 crtc.v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, info);
3912 crtc.gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, info);
3913 aty_crtc_to_var(&crtc, var);
3915 h_total = var->xres + var->right_margin +
3916 var->hsync_len + var->left_margin;
3917 v_total = var->yres + var->lower_margin +
3918 var->vsync_len + var->upper_margin;
3921 * Read the PLL to figure actual Refresh Rate.
3923 clock_cntl = aty_ld_8(CLOCK_CNTL, info);
3924 /* printk("atyfb: CLOCK_CNTL: %02x\n", clock_cntl); */
3925 for (i = 0; i < 16; i++)
3926 pll_regs[i] = aty_ld_pll(i, info);
3929 * PLL Reference Devider M:
3931 M = pll_regs[2];
3934 * PLL Feedback Devider N (Dependant on CLOCK_CNTL):
3936 N = pll_regs[7 + (clock_cntl & 3)];
3939 * PLL Post Devider P (Dependant on CLOCK_CNTL):
3941 P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
3944 * PLL Devider Q:
3946 Q = N / P;
3949 * Target Frequency:
3951 * T * M
3952 * Q = -------
3953 * 2 * R
3955 * where R is XTALIN (= 14318 kHz).
3957 T = 2 * Q * 14318 / M;
3959 default_var.pixclock = 1000000000 / T;
3962 #else /* __sparc__ */
3964 info->ati_regbase_phys = 0x7ff000 + addr;
3965 info->ati_regbase = (unsigned long)
3966 ioremap(info->ati_regbase_phys, 0x1000);
3968 if(!info->ati_regbase) {
3969 kfree(info);
3970 release_mem_region(res_start, res_size);
3971 return -ENOMEM;
3974 info->ati_regbase_phys += 0xc00;
3975 info->ati_regbase += 0xc00;
3978 * Enable memory-space accesses using config-space
3979 * command register.
3981 pci_read_config_word(pdev, PCI_COMMAND, &tmp);
3982 if (!(tmp & PCI_COMMAND_MEMORY)) {
3983 tmp |= PCI_COMMAND_MEMORY;
3984 pci_write_config_word(pdev, PCI_COMMAND, tmp);
3987 #ifdef __BIG_ENDIAN
3988 /* Use the big-endian aperture */
3989 addr += 0x800000;
3990 #endif
3992 /* Map in frame buffer */
3993 info->frame_buffer_phys = addr;
3994 info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
3996 if(!info->frame_buffer) {
3997 kfree(info);
3998 release_mem_region(res_start, res_size);
3999 return -ENXIO;
4002 #endif /* __sparc__ */
4004 if (!aty_init(info, "PCI")) {
4005 if (info->mmap_map)
4006 kfree(info->mmap_map);
4007 kfree(info);
4008 release_mem_region(res_start, res_size);
4009 return -ENXIO;
4012 #ifdef __sparc__
4013 if (!prom_palette)
4014 prom_palette = atyfb_palette;
4017 * Add /dev/fb mmap values.
4019 info->mmap_map[0].voff = 0x8000000000000000UL;
4020 info->mmap_map[0].poff = info->frame_buffer & PAGE_MASK;
4021 info->mmap_map[0].size = info->total_vram;
4022 info->mmap_map[0].prot_mask = _PAGE_CACHE;
4023 info->mmap_map[0].prot_flag = _PAGE_E;
4024 info->mmap_map[1].voff = info->mmap_map[0].voff + info->total_vram;
4025 info->mmap_map[1].poff = info->ati_regbase & PAGE_MASK;
4026 info->mmap_map[1].size = PAGE_SIZE;
4027 info->mmap_map[1].prot_mask = _PAGE_CACHE;
4028 info->mmap_map[1].prot_flag = _PAGE_E;
4029 #endif /* __sparc__ */
4031 #ifdef CONFIG_PMAC_PBOOK
4032 if (first_display == NULL)
4033 pmu_register_sleep_notifier(&aty_sleep_notifier);
4034 info->next = first_display;
4035 first_display = info;
4036 #endif
4038 #ifdef CONFIG_FB_COMPAT_XPMAC
4039 if (!console_fb_info)
4040 console_fb_info = &info->fb_info;
4041 #endif /* CONFIG_FB_COMPAT_XPMAC */
4045 #elif defined(CONFIG_ATARI)
4046 u32 clock_r;
4047 int m64_num;
4048 struct fb_info_aty *info;
4050 for (m64_num = 0; m64_num < mach64_count; m64_num++) {
4051 if (!phys_vmembase[m64_num] || !phys_size[m64_num] ||
4052 !phys_guiregbase[m64_num]) {
4053 printk(" phys_*[%d] parameters not set => returning early. \n",
4054 m64_num);
4055 continue;
4058 info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
4059 if (!info) {
4060 printk("atyfb_init: can't alloc fb_info_aty\n");
4061 return -ENOMEM;
4063 memset(info, 0, sizeof(struct fb_info_aty));
4066 * Map the video memory (physical address given) to somewhere in the
4067 * kernel address space.
4069 info->frame_buffer = ioremap(phys_vmembase[m64_num], phys_size[m64_num]);
4070 info->frame_buffer_phys = info->frame_buffer; /* Fake! */
4071 info->ati_regbase = ioremap(phys_guiregbase[m64_num], 0x10000)+0xFC00ul;
4072 info->ati_regbase_phys = info->ati_regbase; /* Fake! */
4074 aty_st_le32(CLOCK_CNTL, 0x12345678, info);
4075 clock_r = aty_ld_le32(CLOCK_CNTL, info);
4077 switch (clock_r & 0x003F) {
4078 case 0x12:
4079 info->clk_wr_offset = 3; /* */
4080 break;
4081 case 0x34:
4082 info->clk_wr_offset = 2; /* Medusa ST-IO ISA Adapter etc. */
4083 break;
4084 case 0x16:
4085 info->clk_wr_offset = 1; /* */
4086 break;
4087 case 0x38:
4088 info->clk_wr_offset = 0; /* Panther 1 ISA Adapter (Gerald) */
4089 break;
4092 if (!aty_init(info, "ISA bus")) {
4093 kfree(info);
4094 /* This is insufficient! kernel_map has added two large chunks!! */
4095 return -ENXIO;
4098 #endif /* CONFIG_ATARI */
4099 return 0;
4102 #ifndef MODULE
4103 int __init atyfb_setup(char *options)
4105 char *this_opt;
4107 if (!options || !*options)
4108 return 0;
4110 for (this_opt = strtok(options, ","); this_opt;
4111 this_opt = strtok(NULL, ",")) {
4112 if (!strncmp(this_opt, "font:", 5)) {
4113 char *p;
4114 int i;
4116 p = this_opt + 5;
4117 for (i = 0; i < sizeof(fontname) - 1; i++)
4118 if (!*p || *p == ' ' || *p == ',')
4119 break;
4120 memcpy(fontname, this_opt + 5, i);
4121 fontname[i] = 0;
4122 } else if (!strncmp(this_opt, "noblink", 7)) {
4123 curblink = 0;
4124 } else if (!strncmp(this_opt, "noaccel", 7)) {
4125 noaccel = 1;
4126 } else if (!strncmp(this_opt, "vram:", 5))
4127 default_vram = simple_strtoul(this_opt+5, NULL, 0);
4128 else if (!strncmp(this_opt, "pll:", 4))
4129 default_pll = simple_strtoul(this_opt+4, NULL, 0);
4130 else if (!strncmp(this_opt, "mclk:", 5))
4131 default_mclk = simple_strtoul(this_opt+5, NULL, 0);
4132 #ifdef CONFIG_PPC
4133 else if (!strncmp(this_opt, "vmode:", 6)) {
4134 unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
4135 if (vmode > 0 && vmode <= VMODE_MAX)
4136 default_vmode = vmode;
4137 } else if (!strncmp(this_opt, "cmode:", 6)) {
4138 unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0);
4139 switch (cmode) {
4140 case 0:
4141 case 8:
4142 default_cmode = CMODE_8;
4143 break;
4144 case 15:
4145 case 16:
4146 default_cmode = CMODE_16;
4147 break;
4148 case 24:
4149 case 32:
4150 default_cmode = CMODE_32;
4151 break;
4154 #endif
4155 #ifdef CONFIG_ATARI
4157 * Why do we need this silly Mach64 argument?
4158 * We are already here because of mach64= so its redundant.
4160 else if (MACH_IS_ATARI && (!strncmp(this_opt, "Mach64:", 7))) {
4161 static unsigned char m64_num;
4162 static char mach64_str[80];
4163 strncpy(mach64_str, this_opt+7, 80);
4164 if (!store_video_par(mach64_str, m64_num)) {
4165 m64_num++;
4166 mach64_count = m64_num;
4169 #endif
4170 else
4171 mode_option = this_opt;
4173 return 0;
4175 #endif /* !MODULE */
4177 #ifdef CONFIG_ATARI
4178 static int __init store_video_par(char *video_str, unsigned char m64_num)
4180 char *p;
4181 unsigned long vmembase, size, guiregbase;
4183 printk("store_video_par() '%s' \n", video_str);
4185 if (!(p = strtoke(video_str, ";")) || !*p)
4186 goto mach64_invalid;
4187 vmembase = simple_strtoul(p, NULL, 0);
4188 if (!(p = strtoke(NULL, ";")) || !*p)
4189 goto mach64_invalid;
4190 size = simple_strtoul(p, NULL, 0);
4191 if (!(p = strtoke(NULL, ";")) || !*p)
4192 goto mach64_invalid;
4193 guiregbase = simple_strtoul(p, NULL, 0);
4195 phys_vmembase[m64_num] = vmembase;
4196 phys_size[m64_num] = size;
4197 phys_guiregbase[m64_num] = guiregbase;
4198 printk(" stored them all: $%08lX $%08lX $%08lX \n", vmembase, size,
4199 guiregbase);
4200 return 0;
4202 mach64_invalid:
4203 phys_vmembase[m64_num] = 0;
4204 return -1;
4207 static char __init *strtoke(char *s, const char *ct)
4209 static char *ssave = NULL;
4210 char *sbegin, *send;
4212 sbegin = s ? s : ssave;
4213 if (!sbegin)
4214 return NULL;
4215 if (*sbegin == '\0') {
4216 ssave = NULL;
4217 return NULL;
4219 send = strpbrk(sbegin, ct);
4220 if (send && *send != '\0')
4221 *send++ = '\0';
4222 ssave = send;
4223 return sbegin;
4225 #endif /* CONFIG_ATARI */
4227 static int atyfbcon_switch(int con, struct fb_info *fb)
4229 struct fb_info_aty *info = (struct fb_info_aty *)fb;
4230 struct atyfb_par par;
4232 /* Do we have to save the colormap? */
4233 if (fb_display[currcon].cmap.len)
4234 fb_get_cmap(&fb_display[currcon].cmap, 1, atyfb_getcolreg, fb);
4236 /* Erase HW Cursor */
4237 if (info->cursor)
4238 atyfb_cursor(&fb_display[currcon], CM_ERASE,
4239 info->cursor->pos.x, info->cursor->pos.y);
4241 currcon = con;
4243 atyfb_decode_var(&fb_display[con].var, &par, info);
4244 atyfb_set_par(&par, info);
4245 atyfb_set_dispsw(&fb_display[con], info, par.crtc.bpp,
4246 par.accel_flags & FB_ACCELF_TEXT);
4248 /* Install new colormap */
4249 do_install_cmap(con, fb);
4251 /* Install hw cursor */
4252 if (info->cursor) {
4253 aty_set_cursor_color(info, cursor_pixel_map, cursor_color_map,
4254 cursor_color_map, cursor_color_map);
4255 aty_set_cursor_shape(info);
4257 return 1;
4261 * Blank the display.
4264 static void atyfbcon_blank(int blank, struct fb_info *fb)
4266 struct fb_info_aty *info = (struct fb_info_aty *)fb;
4267 u8 gen_cntl;
4269 #ifdef CONFIG_PMAC_BACKLIGHT
4270 if ((_machine == _MACH_Pmac) && blank)
4271 set_backlight_enable(0);
4272 #endif /* CONFIG_PMAC_BACKLIGHT */
4274 gen_cntl = aty_ld_8(CRTC_GEN_CNTL, info);
4275 if (blank > 0)
4276 switch (blank-1) {
4277 case VESA_NO_BLANKING:
4278 gen_cntl |= 0x40;
4279 break;
4280 case VESA_VSYNC_SUSPEND:
4281 gen_cntl |= 0x8;
4282 break;
4283 case VESA_HSYNC_SUSPEND:
4284 gen_cntl |= 0x4;
4285 break;
4286 case VESA_POWERDOWN:
4287 gen_cntl |= 0x4c;
4288 break;
4290 else
4291 gen_cntl &= ~(0x4c);
4292 aty_st_8(CRTC_GEN_CNTL, gen_cntl, info);
4294 #ifdef CONFIG_PMAC_BACKLIGHT
4295 if ((_machine == _MACH_Pmac) && !blank)
4296 set_backlight_enable(1);
4297 #endif /* CONFIG_PMAC_BACKLIGHT */
4302 * Read a single color register and split it into
4303 * colors/transparent. Return != 0 for invalid regno.
4306 static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
4307 u_int *transp, struct fb_info *fb)
4309 struct fb_info_aty *info = (struct fb_info_aty *)fb;
4311 if (regno > 255)
4312 return 1;
4313 *red = (info->palette[regno].red<<8) | info->palette[regno].red;
4314 *green = (info->palette[regno].green<<8) | info->palette[regno].green;
4315 *blue = (info->palette[regno].blue<<8) | info->palette[regno].blue;
4316 *transp = 0;
4317 return 0;
4322 * Set a single color register. The values supplied are already
4323 * rounded down to the hardware's capabilities (according to the
4324 * entries in the var structure). Return != 0 for invalid regno.
4327 static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
4328 u_int transp, struct fb_info *fb)
4330 struct fb_info_aty *info = (struct fb_info_aty *)fb;
4331 int i, scale;
4333 if (regno > 255)
4334 return 1;
4335 red >>= 8;
4336 green >>= 8;
4337 blue >>= 8;
4338 info->palette[regno].red = red;
4339 info->palette[regno].green = green;
4340 info->palette[regno].blue = blue;
4341 i = aty_ld_8(DAC_CNTL, info) & 0xfc;
4342 if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == GV_CHIP_ID ||
4343 Gx == GW_CHIP_ID || Gx == GZ_CHIP_ID || Gx == LG_CHIP_ID ||
4344 Gx == GB_CHIP_ID || Gx == GD_CHIP_ID || Gx == GI_CHIP_ID ||
4345 Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID || Gx == LI_CHIP_ID)
4346 i |= 0x2; /*DAC_CNTL|0x2 turns off the extra brightness for gt*/
4347 aty_st_8(DAC_CNTL, i, info);
4348 aty_st_8(DAC_MASK, 0xff, info);
4349 scale = ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID) &&
4350 (info->current_par.crtc.bpp == 16)) ? 3 : 0;
4351 writeb(regno << scale, &info->aty_cmap_regs->windex);
4352 writeb(red, &info->aty_cmap_regs->lut);
4353 writeb(green, &info->aty_cmap_regs->lut);
4354 writeb(blue, &info->aty_cmap_regs->lut);
4355 if (regno < 16)
4356 switch (info->current_par.crtc.bpp) {
4357 #ifdef FBCON_HAS_CFB16
4358 case 16:
4359 info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) |
4360 regno;
4361 break;
4362 #endif
4363 #ifdef FBCON_HAS_CFB24
4364 case 24:
4365 info->fbcon_cmap.cfb24[regno] = (regno << 16) | (regno << 8) |
4366 regno;
4367 break;
4368 #endif
4369 #ifdef FBCON_HAS_CFB32
4370 case 32:
4371 i = (regno << 8) | regno;
4372 info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
4373 break;
4374 #endif
4376 return 0;
4380 static void do_install_cmap(int con, struct fb_info *info)
4382 if (con != currcon)
4383 return;
4384 if (fb_display[con].cmap.len)
4385 fb_set_cmap(&fb_display[con].cmap, 1, atyfb_setcolreg, info);
4386 else {
4387 int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
4388 fb_set_cmap(fb_default_cmap(size), 1, atyfb_setcolreg, info);
4394 * Accelerated functions
4397 static inline void draw_rect(s16 x, s16 y, u16 width, u16 height,
4398 struct fb_info_aty *info)
4400 /* perform rectangle fill */
4401 wait_for_fifo(2, info);
4402 aty_st_le32(DST_Y_X, (x << 16) | y, info);
4403 aty_st_le32(DST_HEIGHT_WIDTH, (width << 16) | height, info);
4404 info->blitter_may_be_busy = 1;
4407 static inline void aty_rectcopy(int srcx, int srcy, int dstx, int dsty,
4408 u_int width, u_int height,
4409 struct fb_info_aty *info)
4411 u32 direction = DST_LAST_PEL;
4412 u32 pitch_value;
4414 if (!width || !height)
4415 return;
4417 pitch_value = info->current_par.crtc.vxres;
4418 if (info->current_par.crtc.bpp == 24) {
4419 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
4420 /* horizontal coordinates and widths must be adjusted */
4421 pitch_value *= 3;
4422 srcx *= 3;
4423 dstx *= 3;
4424 width *= 3;
4427 if (srcy < dsty) {
4428 dsty += height - 1;
4429 srcy += height - 1;
4430 } else
4431 direction |= DST_Y_TOP_TO_BOTTOM;
4433 if (srcx < dstx) {
4434 dstx += width - 1;
4435 srcx += width - 1;
4436 } else
4437 direction |= DST_X_LEFT_TO_RIGHT;
4439 wait_for_fifo(4, info);
4440 aty_st_le32(DP_SRC, FRGD_SRC_BLIT, info);
4441 aty_st_le32(SRC_Y_X, (srcx << 16) | srcy, info);
4442 aty_st_le32(SRC_HEIGHT1_WIDTH1, (width << 16) | height, info);
4443 aty_st_le32(DST_CNTL, direction, info);
4444 draw_rect(dstx, dsty, width, height, info);
4447 static inline void aty_rectfill(int dstx, int dsty, u_int width, u_int height,
4448 u_int color, struct fb_info_aty *info)
4450 if (!width || !height)
4451 return;
4453 if (info->current_par.crtc.bpp == 24) {
4454 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
4455 /* horizontal coordinates and widths must be adjusted */
4456 dstx *= 3;
4457 width *= 3;
4460 wait_for_fifo(3, info);
4461 aty_st_le32(DP_FRGD_CLR, color, info);
4462 aty_st_le32(DP_SRC, BKGD_SRC_BKGD_CLR | FRGD_SRC_FRGD_CLR | MONO_SRC_ONE,
4463 info);
4464 aty_st_le32(DST_CNTL, DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM |
4465 DST_X_LEFT_TO_RIGHT, info);
4466 draw_rect(dstx, dsty, width, height, info);
4470 * Update the `var' structure (called by fbcon.c)
4473 static int atyfbcon_updatevar(int con, struct fb_info *fb)
4475 struct fb_info_aty *info = (struct fb_info_aty *)fb;
4476 struct atyfb_par *par = &info->current_par;
4477 struct display *p = &fb_display[con];
4478 struct vc_data *conp = p->conp;
4479 u32 yres, yoffset, sy, height;
4481 yres = ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1;
4482 yoffset = fb_display[con].var.yoffset;
4484 sy = (conp->vc_rows + p->yscroll) * fontheight(p);
4485 height = yres - conp->vc_rows * fontheight(p);
4487 if (height && (yoffset + yres > sy)) {
4488 u32 xres, xoffset;
4489 u32 bgx;
4491 xres = (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8;
4492 xoffset = fb_display[con].var.xoffset;
4495 bgx = attr_bgcol_ec(p, conp);
4496 bgx |= (bgx << 8);
4497 bgx |= (bgx << 16);
4499 if (sy + height > par->crtc.vyres) {
4500 wait_for_fifo(1, info);
4501 aty_st_le32(SC_BOTTOM, sy + height - 1, info);
4503 aty_rectfill(xoffset, sy, xres, height, bgx, info);
4506 if (info->cursor && (yoffset + yres <= sy))
4507 atyfb_cursor(p, CM_ERASE, info->cursor->pos.x, info->cursor->pos.y);
4509 info->current_par.crtc.yoffset = yoffset;
4510 set_off_pitch(&info->current_par, info);
4511 return 0;
4515 * Text console acceleration
4518 static void fbcon_aty_bmove(struct display *p, int sy, int sx, int dy, int dx,
4519 int height, int width)
4521 #ifdef __sparc__
4522 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4524 if (fb->mmaped && (!fb->fb_info.display_fg
4525 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4526 return;
4527 #endif
4529 sx *= fontwidth(p);
4530 sy *= fontheight(p);
4531 dx *= fontwidth(p);
4532 dy *= fontheight(p);
4533 width *= fontwidth(p);
4534 height *= fontheight(p);
4536 aty_rectcopy(sx, sy, dx, dy, width, height,
4537 (struct fb_info_aty *)p->fb_info);
4540 static void fbcon_aty_clear(struct vc_data *conp, struct display *p, int sy,
4541 int sx, int height, int width)
4543 u32 bgx;
4544 #ifdef __sparc__
4545 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4547 if (fb->mmaped && (!fb->fb_info.display_fg
4548 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4549 return;
4550 #endif
4552 bgx = attr_bgcol_ec(p, conp);
4553 bgx |= (bgx << 8);
4554 bgx |= (bgx << 16);
4556 sx *= fontwidth(p);
4557 sy *= fontheight(p);
4558 width *= fontwidth(p);
4559 height *= fontheight(p);
4561 aty_rectfill(sx, sy, width, height, bgx,
4562 (struct fb_info_aty *)p->fb_info);
4565 #ifdef FBCON_HAS_CFB8
4566 static void fbcon_aty8_putc(struct vc_data *conp, struct display *p, int c,
4567 int yy, int xx)
4569 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4571 #ifdef __sparc__
4572 if (fb->mmaped && (!fb->fb_info.display_fg
4573 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4574 return;
4575 #endif
4577 if (fb->blitter_may_be_busy)
4578 wait_for_idle((struct fb_info_aty *)p->fb_info);
4579 fbcon_cfb8_putc(conp, p, c, yy, xx);
4582 static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p,
4583 const unsigned short *s, int count, int yy,
4584 int xx)
4586 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4588 #ifdef __sparc__
4589 if (fb->mmaped && (!fb->fb_info.display_fg
4590 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4591 return;
4592 #endif
4594 if (fb->blitter_may_be_busy)
4595 wait_for_idle((struct fb_info_aty *)p->fb_info);
4596 fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
4599 static void fbcon_aty8_clear_margins(struct vc_data *conp, struct display *p,
4600 int bottom_only)
4602 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4604 #ifdef __sparc__
4605 if (fb->mmaped && (!fb->fb_info.display_fg
4606 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4607 return;
4608 #endif
4610 if (fb->blitter_may_be_busy)
4611 wait_for_idle((struct fb_info_aty *)p->fb_info);
4612 fbcon_cfb8_clear_margins(conp, p, bottom_only);
4615 static struct display_switch fbcon_aty8 = {
4616 setup: fbcon_cfb8_setup,
4617 bmove: fbcon_aty_bmove,
4618 clear: fbcon_aty_clear,
4619 putc: fbcon_aty8_putc,
4620 putcs: fbcon_aty8_putcs,
4621 revc: fbcon_cfb8_revc,
4622 clear_margins: fbcon_aty8_clear_margins,
4623 fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4625 #endif
4627 #ifdef FBCON_HAS_CFB16
4628 static void fbcon_aty16_putc(struct vc_data *conp, struct display *p, int c,
4629 int yy, int xx)
4631 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4633 #ifdef __sparc__
4634 if (fb->mmaped && (!fb->fb_info.display_fg
4635 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4636 return;
4637 #endif
4639 if (fb->blitter_may_be_busy)
4640 wait_for_idle((struct fb_info_aty *)p->fb_info);
4641 fbcon_cfb16_putc(conp, p, c, yy, xx);
4644 static void fbcon_aty16_putcs(struct vc_data *conp, struct display *p,
4645 const unsigned short *s, int count, int yy,
4646 int xx)
4648 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4650 #ifdef __sparc__
4651 if (fb->mmaped && (!fb->fb_info.display_fg
4652 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4653 return;
4654 #endif
4656 if (fb->blitter_may_be_busy)
4657 wait_for_idle((struct fb_info_aty *)p->fb_info);
4658 fbcon_cfb16_putcs(conp, p, s, count, yy, xx);
4661 static void fbcon_aty16_clear_margins(struct vc_data *conp, struct display *p,
4662 int bottom_only)
4664 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4666 #ifdef __sparc__
4667 if (fb->mmaped && (!fb->fb_info.display_fg
4668 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4669 return;
4670 #endif
4672 if (fb->blitter_may_be_busy)
4673 wait_for_idle((struct fb_info_aty *)p->fb_info);
4674 fbcon_cfb16_clear_margins(conp, p, bottom_only);
4677 static struct display_switch fbcon_aty16 = {
4678 setup: fbcon_cfb16_setup,
4679 bmove: fbcon_aty_bmove,
4680 clear: fbcon_aty_clear,
4681 putc: fbcon_aty16_putc,
4682 putcs: fbcon_aty16_putcs,
4683 revc: fbcon_cfb16_revc,
4684 clear_margins: fbcon_aty16_clear_margins,
4685 fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4687 #endif
4689 #ifdef FBCON_HAS_CFB24
4690 static void fbcon_aty24_putc(struct vc_data *conp, struct display *p, int c,
4691 int yy, int xx)
4693 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4695 #ifdef __sparc__
4696 if (fb->mmaped && (!fb->fb_info.display_fg
4697 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4698 return;
4699 #endif
4701 if (fb->blitter_may_be_busy)
4702 wait_for_idle((struct fb_info_aty *)p->fb_info);
4703 fbcon_cfb24_putc(conp, p, c, yy, xx);
4706 static void fbcon_aty24_putcs(struct vc_data *conp, struct display *p,
4707 const unsigned short *s, int count, int yy,
4708 int xx)
4710 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4712 #ifdef __sparc__
4713 if (fb->mmaped && (!fb->fb_info.display_fg
4714 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4715 return;
4716 #endif
4718 if (fb->blitter_may_be_busy)
4719 wait_for_idle((struct fb_info_aty *)p->fb_info);
4720 fbcon_cfb24_putcs(conp, p, s, count, yy, xx);
4723 static void fbcon_aty24_clear_margins(struct vc_data *conp, struct display *p,
4724 int bottom_only)
4726 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4728 #ifdef __sparc__
4729 if (fb->mmaped && (!fb->fb_info.display_fg
4730 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4731 return;
4732 #endif
4734 if (fb->blitter_may_be_busy)
4735 wait_for_idle((struct fb_info_aty *)p->fb_info);
4736 fbcon_cfb24_clear_margins(conp, p, bottom_only);
4739 static struct display_switch fbcon_aty24 = {
4740 setup: fbcon_cfb24_setup,
4741 bmove: fbcon_aty_bmove,
4742 clear: fbcon_aty_clear,
4743 putc: fbcon_aty24_putc,
4744 putcs: fbcon_aty24_putcs,
4745 revc: fbcon_cfb24_revc,
4746 clear_margins: fbcon_aty24_clear_margins,
4747 fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4749 #endif
4751 #ifdef FBCON_HAS_CFB32
4752 static void fbcon_aty32_putc(struct vc_data *conp, struct display *p, int c,
4753 int yy, int xx)
4755 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4757 #ifdef __sparc__
4758 if (fb->mmaped && (!fb->fb_info.display_fg
4759 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4760 return;
4761 #endif
4763 if (fb->blitter_may_be_busy)
4764 wait_for_idle((struct fb_info_aty *)p->fb_info);
4765 fbcon_cfb32_putc(conp, p, c, yy, xx);
4768 static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p,
4769 const unsigned short *s, int count, int yy,
4770 int xx)
4772 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4774 #ifdef __sparc__
4775 if (fb->mmaped && (!fb->fb_info.display_fg
4776 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4777 return;
4778 #endif
4780 if (fb->blitter_may_be_busy)
4781 wait_for_idle((struct fb_info_aty *)p->fb_info);
4782 fbcon_cfb32_putcs(conp, p, s, count, yy, xx);
4785 static void fbcon_aty32_clear_margins(struct vc_data *conp, struct display *p,
4786 int bottom_only)
4788 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
4790 #ifdef __sparc__
4791 if (fb->mmaped && (!fb->fb_info.display_fg
4792 || fb->fb_info.display_fg->vc_num == fb->vtconsole))
4793 return;
4794 #endif
4796 if (fb->blitter_may_be_busy)
4797 wait_for_idle((struct fb_info_aty *)p->fb_info);
4798 fbcon_cfb32_clear_margins(conp, p, bottom_only);
4801 static struct display_switch fbcon_aty32 = {
4802 setup: fbcon_cfb32_setup,
4803 bmove: fbcon_aty_bmove,
4804 clear: fbcon_aty_clear,
4805 putc: fbcon_aty32_putc,
4806 putcs: fbcon_aty32_putcs,
4807 revc: fbcon_cfb32_revc,
4808 clear_margins: fbcon_aty32_clear_margins,
4809 fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
4811 #endif
4813 #ifdef CONFIG_PMAC_PBOOK
4815 /* Power management routines. Those are used for PowerBook sleep.
4817 * It appears that Rage LT and Rage LT Pro have different power
4818 * management registers. There's is some confusion about which
4819 * chipID is a Rage LT or LT pro :(
4821 static int
4822 aty_power_mgmt_LT(int sleep, struct fb_info_aty *info)
4824 unsigned int pm;
4825 int timeout;
4827 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
4828 pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;
4829 aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
4830 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
4832 timeout = 200000;
4833 if (sleep) {
4834 /* Sleep */
4835 pm &= ~PWR_MGT_ON;
4836 aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
4837 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
4838 udelay(10);
4839 pm &= ~(PWR_BLON | AUTO_PWR_UP);
4840 pm |= SUSPEND_NOW;
4841 aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
4842 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
4843 udelay(10);
4844 pm |= PWR_MGT_ON;
4845 aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
4846 do {
4847 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
4848 udelay(10);
4849 if ((--timeout) == 0)
4850 break;
4851 } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
4852 } else {
4853 /* Wakeup */
4854 pm &= ~PWR_MGT_ON;
4855 aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
4856 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
4857 udelay(10);
4858 pm |= (PWR_BLON | AUTO_PWR_UP);
4859 pm &= ~SUSPEND_NOW;
4860 aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
4861 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
4862 udelay(10);
4863 pm |= PWR_MGT_ON;
4864 aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
4865 do {
4866 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
4867 udelay(10);
4868 if ((--timeout) == 0)
4869 break;
4870 } while ((pm & PWR_MGT_STATUS_MASK) != 0);
4872 mdelay(500);
4874 return timeout ? PBOOK_SLEEP_OK : PBOOK_SLEEP_REFUSE;
4877 static int
4878 aty_power_mgmt_LTPro(int sleep, struct fb_info_aty *info)
4880 unsigned int pm;
4881 int timeout;
4883 pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
4884 pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;
4885 aty_st_lcd(LCD_POWER_MANAGEMENT, pm, info);
4886 pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
4888 timeout = 200;
4889 if (sleep) {
4890 /* Sleep */
4891 pm &= ~PWR_MGT_ON;
4892 aty_st_lcd(LCD_POWER_MANAGEMENT, pm, info);
4893 pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
4894 udelay(10);
4895 pm &= ~(PWR_BLON | AUTO_PWR_UP);
4896 pm |= SUSPEND_NOW;
4897 aty_st_lcd(LCD_POWER_MANAGEMENT, pm, info);
4898 pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
4899 udelay(10);
4900 pm |= PWR_MGT_ON;
4901 aty_st_lcd(LCD_POWER_MANAGEMENT, pm, info);
4902 do {
4903 pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
4904 udelay(1000);
4905 if ((--timeout) == 0)
4906 break;
4907 } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
4908 } else {
4909 /* Wakeup */
4910 pm &= ~PWR_MGT_ON;
4911 aty_st_lcd(LCD_POWER_MANAGEMENT, pm, info);
4912 pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
4913 udelay(10);
4914 pm &= ~SUSPEND_NOW;
4915 pm |= (PWR_BLON | AUTO_PWR_UP);
4916 aty_st_lcd(LCD_POWER_MANAGEMENT, pm, info);
4917 pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
4918 udelay(10);
4919 pm |= PWR_MGT_ON;
4920 aty_st_lcd(LCD_POWER_MANAGEMENT, pm, info);
4921 do {
4922 pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
4923 udelay(1000);
4924 if ((--timeout) == 0)
4925 break;
4926 } while ((pm & PWR_MGT_STATUS_MASK) != 0);
4929 return timeout ? PBOOK_SLEEP_OK : PBOOK_SLEEP_REFUSE;
4933 * Save the contents of the frame buffer when we go to sleep,
4934 * and restore it when we wake up again.
4937 aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
4939 struct fb_info_aty *info;
4940 int result;
4942 result = PBOOK_SLEEP_OK;
4944 for (info = first_display; info != NULL; info = info->next) {
4945 struct fb_fix_screeninfo fix;
4946 int nb;
4948 atyfb_get_fix(&fix, fg_console, (struct fb_info *)info);
4949 nb = fb_display[fg_console].var.yres * fix.line_length;
4951 switch (when) {
4952 case PBOOK_SLEEP_REQUEST:
4953 info->save_framebuffer = vmalloc(nb);
4954 if (info->save_framebuffer == NULL)
4955 return PBOOK_SLEEP_REFUSE;
4956 break;
4957 case PBOOK_SLEEP_REJECT:
4958 if (info->save_framebuffer) {
4959 vfree(info->save_framebuffer);
4960 info->save_framebuffer = 0;
4962 break;
4963 case PBOOK_SLEEP_NOW:
4964 if (info->blitter_may_be_busy)
4965 wait_for_idle(info);
4966 /* Stop accel engine (stop bus mastering) */
4967 if (info->current_par.accel_flags & FB_ACCELF_TEXT)
4968 reset_engine(info);
4970 /* Backup fb content */
4971 if (info->save_framebuffer)
4972 memcpy_fromio(info->save_framebuffer,
4973 (void *)info->frame_buffer, nb);
4975 /* Blank display and LCD */
4976 atyfbcon_blank(VESA_POWERDOWN+1, (struct fb_info *)info);
4978 /* Set chip to "suspend" mode */
4979 if (Gx == LG_CHIP_ID)
4980 result = aty_power_mgmt_LT(1, info);
4981 else
4982 result = aty_power_mgmt_LTPro(1, info);
4983 break;
4984 case PBOOK_WAKE:
4985 /* Wakeup chip */
4986 if (Gx == LG_CHIP_ID)
4987 result = aty_power_mgmt_LT(0, info);
4988 else
4989 result = aty_power_mgmt_LTPro(0, info);
4991 /* Restore fb content */
4992 if (info->save_framebuffer) {
4993 memcpy_toio((void *)info->frame_buffer,
4994 info->save_framebuffer, nb);
4995 vfree(info->save_framebuffer);
4996 info->save_framebuffer = 0;
4998 /* Restore display */
4999 atyfb_set_par(&info->current_par, info);
5000 atyfbcon_blank(0, (struct fb_info *)info);
5001 break;
5004 return result;
5006 #endif /* CONFIG_PMAC_PBOOK */
5008 #ifdef CONFIG_PMAC_BACKLIGHT
5009 static int backlight_conv[] = {
5010 0x00, 0x3f, 0x4c, 0x59, 0x66, 0x73, 0x80, 0x8d,
5011 0x9a, 0xa7, 0xb4, 0xc1, 0xcf, 0xdc, 0xe9, 0xff
5014 static int
5015 aty_set_backlight_enable(int on, int level, void* data)
5017 struct fb_info_aty *info = (struct fb_info_aty *)data;
5018 unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, info);
5020 reg |= (BLMOD_EN | BIASMOD_EN);
5021 if (on && level > BACKLIGHT_OFF) {
5022 reg &= ~BIAS_MOD_LEVEL_MASK;
5023 reg |= (backlight_conv[level] << BIAS_MOD_LEVEL_SHIFT);
5024 } else {
5025 reg &= ~BIAS_MOD_LEVEL_MASK;
5026 reg |= (backlight_conv[0] << BIAS_MOD_LEVEL_SHIFT);
5028 aty_st_lcd(LCD_MISC_CNTL, reg, info);
5030 return 0;
5033 static int
5034 aty_set_backlight_level(int level, void* data)
5036 return aty_set_backlight_enable(1, level, data);
5039 #endif /* CONFIG_PMAC_BACKLIGHT */
5042 #ifdef MODULE
5043 int __init init_module(void)
5045 atyfb_init();
5046 return fb_list ? 0 : -ENXIO;
5049 void cleanup_module(void)
5051 while (fb_list) {
5052 struct fb_info_aty *info = fb_list;
5053 fb_list = info->next;
5055 unregister_framebuffer(&info->fb_info);
5057 #ifndef __sparc__
5058 if (info->ati_regbase)
5059 iounmap((void *)info->ati_regbase);
5060 if (info->frame_buffer)
5061 iounmap((void *)info->frame_buffer);
5062 #ifdef __BIG_ENDIAN
5063 if (info->cursor && info->cursor->ram)
5064 iounmap(info->cursor->ram);
5065 #endif
5066 #endif
5068 if (info->cursor) {
5069 if (info->cursor->timer)
5070 kfree(info->cursor->timer);
5071 kfree(info->cursor);
5073 #ifdef __sparc__
5074 if (info->mmap_map)
5075 kfree(info->mmap_map);
5076 #endif
5077 kfree(info);
5081 #endif