1 2/* 3 * ATI Frame Buffer Device Driver Core 4 * 5 * Copyright (C) 1997-2001 Geert Uytterhoeven 6 * Copyright (C) 1998 Bernd Harries 7 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) 8 * 9 * This driver supports the following ATI graphics chips: 10 * - ATI Mach64 11 * 12 * To do: add support for 13 * - ATI Rage128 (from aty128fb.c) 14 * - ATI Radeon (from radeonfb.c) 15 * 16 * This driver is partly based on the PowerMac console driver: 17 * 18 * Copyright (C) 1996 Paul Mackerras 19 * 20 * and on the PowerMac ATI/mach64 display driver: 21 * 22 * Copyright (C) 1997 Michael AK Tesch 23 * 24 * with work by Jon Howell 25 * Harry AC Eaton 26 * Anthony Tong <atong@uiuc.edu> 27 * 28 * This file is subject to the terms and conditions of the GNU General Public 29 * License. See the file COPYING in the main directory of this archive for 30 * more details. 31 * 32 * Many thanks to Nitya from ATI devrel for support and patience ! 33 */ 34 35/****************************************************************************** 36 37 TODO: 38 39 - cursor support on all cards and all ramdacs. 40 - cursor parameters controlable via ioctl()s. 41 - guess PLL and MCLK based on the original PLL register values initialized 42 by the BIOS or Open Firmware (if they are initialized). 43 44 (Anyone to help with this?) 45 46******************************************************************************/ 47 48 49#include <linux/config.h> 50#include <linux/module.h> 51#include <linux/kernel.h> 52#include <linux/errno.h> 53#include <linux/string.h> 54#include <linux/mm.h> 55#include <linux/slab.h> 56#include <linux/vmalloc.h> 57#include <linux/delay.h> 58#include <linux/selection.h> 59#include <linux/console.h> 60#include <linux/fb.h> 61#include <linux/init.h> 62#include <linux/pci.h> 63#include <linux/vt_kern.h> 64#include <linux/kd.h> 65 66#include <asm/io.h> 67#include <asm/uaccess.h> 68 69#include <video/fbcon.h> 70#include <video/fbcon-cfb8.h> 71#include <video/fbcon-cfb16.h> 72#include <video/fbcon-cfb24.h> 73#include <video/fbcon-cfb32.h> 74 75#include "mach64.h" 76#include "atyfb.h" 77 78#ifdef __powerpc__ 79#include <asm/prom.h> 80#include <video/macmodes.h> 81#endif 82#ifdef __sparc__ 83#include <asm/pbm.h> 84#include <asm/fbio.h> 85#endif 86 87#ifdef CONFIG_ADB_PMU 88#include <linux/adb.h> 89#include <linux/pmu.h> 90#endif 91#ifdef CONFIG_BOOTX_TEXT 92#include <asm/btext.h> 93#endif 94#ifdef CONFIG_NVRAM 95#include <linux/nvram.h> 96#endif 97#ifdef CONFIG_FB_COMPAT_XPMAC 98#include <asm/vc_ioctl.h> 99#endif 100#ifdef CONFIG_PMAC_BACKLIGHT 101#include <asm/backlight.h> 102#endif 103 104 105/* 106 * Debug flags. 107 */ 108#undef DEBUG 109 110/* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */ 111/* - must be large enough to catch all GUI-Regs */ 112/* - must be aligned to a PAGE boundary */ 113#define GUI_RESERVE (1 * PAGE_SIZE) 114 115 116#define FAIL(x) do { printk(x "\n"); return -EINVAL; } while (0) 117 118 119 /* 120 * The Hardware parameters for each card 121 */ 122 123struct aty_cmap_regs { 124 u8 windex; 125 u8 lut; 126 u8 mask; 127 u8 rindex; 128 u8 cntl; 129}; 130 131struct pci_mmap_map { 132 unsigned long voff; 133 unsigned long poff; 134 unsigned long size; 135 unsigned long prot_flag; 136 unsigned long prot_mask; 137}; 138 139 140 /* 141 * Frame buffer device API 142 */ 143 144static int atyfb_open(struct fb_info *info, int user); 145static int atyfb_release(struct fb_info *info, int user); 146static int atyfb_get_fix(struct fb_fix_screeninfo *fix, int con, 147 struct fb_info *fb); 148static int atyfb_get_var(struct fb_var_screeninfo *var, int con, 149 struct fb_info *fb); 150static int atyfb_set_var(struct fb_var_screeninfo *var, int con, 151 struct fb_info *fb); 152static int atyfb_pan_display(struct fb_var_screeninfo *var, int con, 153 struct fb_info *fb); 154static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, 155 struct fb_info *info); 156static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, 157 struct fb_info *info); 158static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, 159 u_long arg, int con, struct fb_info *info); 160#ifdef __sparc__ 161static int atyfb_mmap(struct fb_info *info, struct file *file, 162 struct vm_area_struct *vma); 163#endif 164static int atyfb_rasterimg(struct fb_info *info, int start); 165 166 167 /* 168 * Interface to the low level console driver 169 */ 170 171static int atyfbcon_switch(int con, struct fb_info *fb); 172static int atyfbcon_updatevar(int con, struct fb_info *fb); 173static void atyfbcon_blank(int blank, struct fb_info *fb); 174 175 176 /* 177 * Internal routines 178 */ 179 180static int aty_init(struct fb_info_aty *info, const char *name); 181#ifdef CONFIG_ATARI 182static int store_video_par(char *videopar, unsigned char m64_num); 183static char *strtoke(char *s, const char *ct); 184#endif 185 186static void aty_set_crtc(const struct fb_info_aty *info, 187 const struct crtc *crtc); 188static int aty_var_to_crtc(const struct fb_info_aty *info, 189 const struct fb_var_screeninfo *var, 190 struct crtc *crtc); 191static int aty_crtc_to_var(const struct crtc *crtc, 192 struct fb_var_screeninfo *var); 193 194static void atyfb_set_par(const struct atyfb_par *par, 195 struct fb_info_aty *info); 196static int atyfb_decode_var(const struct fb_var_screeninfo *var, 197 struct atyfb_par *par, 198 const struct fb_info_aty *info); 199static int atyfb_encode_var(struct fb_var_screeninfo *var, 200 const struct atyfb_par *par, 201 const struct fb_info_aty *info); 202static void set_off_pitch(struct atyfb_par *par, 203 const struct fb_info_aty *info); 204static int encode_fix(struct fb_fix_screeninfo *fix, 205 const struct atyfb_par *par, 206 const struct fb_info_aty *info); 207static void atyfb_set_dispsw(struct display *disp, struct fb_info_aty *info, 208 int bpp, int accel); 209static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, 210 u_int *transp, struct fb_info *fb); 211static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 212 u_int transp, struct fb_info *fb); 213static void do_install_cmap(int con, struct fb_info *info); 214#ifdef CONFIG_PPC 215static int read_aty_sense(const struct fb_info_aty *info); 216#endif 217 218 219 /* 220 * Interface used by the world 221 */ 222 223int atyfb_init(void); 224#ifndef MODULE 225int atyfb_setup(char*); 226#endif 227 228static int currcon = 0; 229 230static struct fb_ops atyfb_ops = { 231 owner: THIS_MODULE, 232 fb_open: atyfb_open, 233 fb_release: atyfb_release, 234 fb_get_fix: atyfb_get_fix, 235 fb_get_var: atyfb_get_var, 236 fb_set_var: atyfb_set_var, 237 fb_get_cmap: atyfb_get_cmap, 238 fb_set_cmap: atyfb_set_cmap, 239 fb_pan_display: atyfb_pan_display, 240 fb_ioctl: atyfb_ioctl, 241#ifdef __sparc__ 242 fb_mmap: atyfb_mmap, 243#endif 244 fb_rasterimg: atyfb_rasterimg, 245}; 246 247static char atyfb_name[16] = "ATY Mach64"; 248static char fontname[40] __initdata = { 0 }; 249static char curblink __initdata = 1; 250static char noaccel __initdata = 0; 251static u32 default_vram __initdata = 0; 252static int default_pll __initdata = 0; 253static int default_mclk __initdata = 0; 254 255#ifndef MODULE 256static char *mode_option __initdata = NULL; 257#endif 258 259#ifdef CONFIG_PPC 260#ifndef CONFIG_NVRAM 261static int default_vmode __initdata = VMODE_NVRAM; 262static int default_cmode __initdata = CMODE_NVRAM; 263#else 264static int default_vmode __initdata = VMODE_CHOOSE; 265static int default_cmode __initdata = CMODE_CHOOSE; 266#endif 267#endif 268 269#ifdef CONFIG_ATARI 270static unsigned int mach64_count __initdata = 0; 271static unsigned long phys_vmembase[FB_MAX] __initdata = { 0, }; 272static unsigned long phys_size[FB_MAX] __initdata = { 0, }; 273static unsigned long phys_guiregbase[FB_MAX] __initdata = { 0, }; 274#endif 275 276#ifdef CONFIG_FB_ATY_GX 277static char m64n_gx[] __initdata = "mach64GX (ATI888GX00)"; 278static char m64n_cx[] __initdata = "mach64CX (ATI888CX00)"; 279#endif /* CONFIG_FB_ATY_GX */ 280 281#ifdef CONFIG_FB_ATY_CT 282static char m64n_ct[] __initdata = "mach64CT (ATI264CT)"; 283static char m64n_et[] __initdata = "mach64ET (ATI264ET)"; 284static char m64n_vta3[] __initdata = "mach64VTA3 (ATI264VT)"; 285static char m64n_vta4[] __initdata = "mach64VTA4 (ATI264VT)"; 286static char m64n_vtb[] __initdata = "mach64VTB (ATI264VTB)"; 287static char m64n_vt4[] __initdata = "mach64VT4 (ATI264VT4)"; 288static char m64n_gt[] __initdata = "3D RAGE (GT)"; 289static char m64n_gtb[] __initdata = "3D RAGE II+ (GTB)"; 290static char m64n_iic_p[] __initdata = "3D RAGE IIC (PCI)"; 291static char m64n_iic_a[] __initdata = "3D RAGE IIC (AGP)"; 292static char m64n_lt[] __initdata = "3D RAGE LT"; 293static char m64n_ltg[] __initdata = "3D RAGE LT-G"; 294static char m64n_gtc_ba[] __initdata = "3D RAGE PRO (BGA, AGP)"; 295static char m64n_gtc_ba1[] __initdata = "3D RAGE PRO (BGA, AGP, 1x only)"; 296static char m64n_gtc_bp[] __initdata = "3D RAGE PRO (BGA, PCI)"; 297static char m64n_gtc_pp[] __initdata = "3D RAGE PRO (PQFP, PCI)"; 298static char m64n_gtc_ppl[] __initdata = "3D RAGE PRO (PQFP, PCI, limited 3D)"; 299static char m64n_xl[] __initdata = "3D RAGE (XL)"; 300static char m64n_ltp_a[] __initdata = "3D RAGE LT PRO (AGP)"; 301static char m64n_ltp_p[] __initdata = "3D RAGE LT PRO (PCI)"; 302static char m64n_mob_p[] __initdata = "3D RAGE Mobility (PCI)"; 303static char m64n_mob_a[] __initdata = "3D RAGE Mobility (AGP)"; 304#endif /* CONFIG_FB_ATY_CT */ 305 306static struct { 307 u16 pci_id, chip_type; 308 u8 rev_mask, rev_val; 309 const char *name; 310 int pll, mclk; 311 u32 features; 312} aty_chips[] __initdata = { 313#ifdef CONFIG_FB_ATY_GX 314 /* Mach64 GX */ 315 { 0x4758, 0x00d7, 0x00, 0x00, m64n_gx, 135, 50, M64F_GX }, 316 { 0x4358, 0x0057, 0x00, 0x00, m64n_cx, 135, 50, M64F_GX }, 317#endif /* CONFIG_FB_ATY_GX */ 318 319#ifdef CONFIG_FB_ATY_CT 320 /* Mach64 CT */ 321 { 0x4354, 0x4354, 0x00, 0x00, m64n_ct, 135, 60, M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO }, 322 { 0x4554, 0x4554, 0x00, 0x00, m64n_et, 135, 60, M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO }, 323 324 /* Mach64 VT */ 325 { 0x5654, 0x5654, 0xc7, 0x00, m64n_vta3, 170, 67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO | M64F_FIFO_24 }, 326 { 0x5654, 0x5654, 0xc7, 0x40, m64n_vta4, 200, 67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO | M64F_FIFO_24 | M64F_MAGIC_POSTDIV }, 327 { 0x5654, 0x5654, 0x00, 0x00, m64n_vtb, 200, 67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_FIFO_24 }, 328 { 0x5655, 0x5655, 0x00, 0x00, m64n_vtb, 200, 67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL }, 329 { 0x5656, 0x5656, 0x00, 0x00, m64n_vt4, 230, 83, M64F_VT | M64F_INTEGRATED | M64F_GTB_DSP }, 330 331 /* Mach64 GT (3D RAGE) */ 332 { 0x4754, 0x4754, 0x07, 0x00, m64n_gt, 135, 63, M64F_GT | M64F_INTEGRATED | M64F_MAGIC_FIFO | M64F_FIFO_24 | M64F_EXTRA_BRIGHT }, 333 { 0x4754, 0x4754, 0x07, 0x01, m64n_gt, 170, 67, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT }, 334 { 0x4754, 0x4754, 0x07, 0x02, m64n_gt, 200, 67, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT }, 335 { 0x4755, 0x4755, 0x00, 0x00, m64n_gtb, 200, 67, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT }, 336 { 0x4756, 0x4756, 0x00, 0x00, m64n_iic_p, 230, 83, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT }, 337 { 0x4757, 0x4757, 0x00, 0x00, m64n_iic_a, 230, 83, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT }, 338 { 0x475a, 0x475a, 0x00, 0x00, m64n_iic_a, 230, 83, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT }, 339 340 /* Mach64 LT */ 341 { 0x4c54, 0x4c54, 0x00, 0x00, m64n_lt, 135, 63, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP }, 342 { 0x4c47, 0x4c47, 0x00, 0x00, m64n_ltg, 230, 63, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_LT_SLEEP | M64F_G3_PB_1024x768 }, 343 344 /* Mach64 GTC (3D RAGE PRO) */ 345 { 0x4742, 0x4742, 0x00, 0x00, m64n_gtc_ba, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT }, 346 { 0x4744, 0x4744, 0x00, 0x00, m64n_gtc_ba1, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT }, 347 { 0x4749, 0x4749, 0x00, 0x00, m64n_gtc_bp, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_MAGIC_VRAM_SIZE }, 348 { 0x4750, 0x4750, 0x00, 0x00, m64n_gtc_pp, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT }, 349 { 0x4751, 0x4751, 0x00, 0x00, m64n_gtc_ppl, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT }, 350 351 /* 3D RAGE XL */ 352 { 0x4752, 0x4752, 0x00, 0x00, m64n_xl, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_XL_DLL }, 353 354 /* Mach64 LT PRO */ 355 { 0x4c42, 0x4c42, 0x00, 0x00, m64n_ltp_a, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP }, 356 { 0x4c44, 0x4c44, 0x00, 0x00, m64n_ltp_p, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP }, 357 { 0x4c49, 0x4c49, 0x00, 0x00, m64n_ltp_p, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_EXTRA_BRIGHT | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 }, 358 { 0x4c50, 0x4c50, 0x00, 0x00, m64n_ltp_p, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP }, 359 360 /* 3D RAGE Mobility */ 361 { 0x4c4d, 0x4c4d, 0x00, 0x00, m64n_mob_p, 230, 50, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_MOBIL_BUS }, 362 { 0x4c4e, 0x4c4e, 0x00, 0x00, m64n_mob_a, 230, 50, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_MOBIL_BUS }, 363#endif /* CONFIG_FB_ATY_CT */ 364}; 365 366#if defined(CONFIG_FB_ATY_GX) || defined(CONFIG_FB_ATY_CT) 367static char ram_dram[] __initdata = "DRAM"; 368static char ram_resv[] __initdata = "RESV"; 369#endif /* CONFIG_FB_ATY_GX || CONFIG_FB_ATY_CT */ 370 371#ifdef CONFIG_FB_ATY_GX 372static char ram_vram[] __initdata = "VRAM"; 373#endif /* CONFIG_FB_ATY_GX */ 374 375#ifdef CONFIG_FB_ATY_CT 376static char ram_edo[] __initdata = "EDO"; 377static char ram_sdram[] __initdata = "SDRAM"; 378static char ram_sgram[] __initdata = "SGRAM"; 379static char ram_wram[] __initdata = "WRAM"; 380static char ram_off[] __initdata = "OFF"; 381#endif /* CONFIG_FB_ATY_CT */ 382 383#ifdef CONFIG_FB_ATY_GX 384static char *aty_gx_ram[8] __initdata = { 385 ram_dram, ram_vram, ram_vram, ram_dram, 386 ram_dram, ram_vram, ram_vram, ram_resv 387}; 388#endif /* CONFIG_FB_ATY_GX */ 389 390#ifdef CONFIG_FB_ATY_CT 391static char *aty_ct_ram[8] __initdata = { 392 ram_off, ram_dram, ram_edo, ram_edo, 393 ram_sdram, ram_sgram, ram_wram, ram_resv 394}; 395#endif /* CONFIG_FB_ATY_CT */ 396 397 398#if defined(CONFIG_PPC) 399 400 /* 401 * Apple monitor sense 402 */ 403 404static int __init read_aty_sense(const struct fb_info_aty *info) 405{ 406 int sense, i; 407 408 aty_st_le32(GP_IO, 0x31003100, info); /* drive outputs high */ 409 __delay(200); 410 aty_st_le32(GP_IO, 0, info); /* turn off outputs */ 411 __delay(2000); 412 i = aty_ld_le32(GP_IO, info); /* get primary sense value */ 413 sense = ((i & 0x3000) >> 3) | (i & 0x100); 414 415 /* drive each sense line low in turn and collect the other 2 */ 416 aty_st_le32(GP_IO, 0x20000000, info); /* drive A low */ 417 __delay(2000); 418 i = aty_ld_le32(GP_IO, info); 419 sense |= ((i & 0x1000) >> 7) | ((i & 0x100) >> 4); 420 aty_st_le32(GP_IO, 0x20002000, info); /* drive A high again */ 421 __delay(200); 422 423 aty_st_le32(GP_IO, 0x10000000, info); /* drive B low */ 424 __delay(2000); 425 i = aty_ld_le32(GP_IO, info); 426 sense |= ((i & 0x2000) >> 10) | ((i & 0x100) >> 6); 427 aty_st_le32(GP_IO, 0x10001000, info); /* drive B high again */ 428 __delay(200); 429 430 aty_st_le32(GP_IO, 0x01000000, info); /* drive C low */ 431 __delay(2000); 432 sense |= (aty_ld_le32(GP_IO, info) & 0x3000) >> 12; 433 aty_st_le32(GP_IO, 0, info); /* turn off outputs */ 434 435 return sense; 436} 437 438#endif /* defined(CONFIG_PPC) */ 439 440#if defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_PMAC_BACKLIGHT) 441static void aty_st_lcd(int index, u32 val, const struct fb_info_aty *info) 442{ 443 unsigned long temp; 444 445 /* write addr byte */ 446 temp = aty_ld_le32(LCD_INDEX, info); 447 aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, info); 448 /* write the register value */ 449 aty_st_le32(LCD_DATA, val, info); 450} 451 452static u32 aty_ld_lcd(int index, const struct fb_info_aty *info) 453{ 454 unsigned long temp; 455 456 /* write addr byte */ 457 temp = aty_ld_le32(LCD_INDEX, info); 458 aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, info); 459 /* read the register value */ 460 return aty_ld_le32(LCD_DATA, info); 461} 462#endif /* CONFIG_PMAC_PBOOK || CONFIG_PMAC_BACKLIGHT */ 463 464/* ------------------------------------------------------------------------- */ 465 466 /* 467 * CRTC programming 468 */ 469 470static void aty_set_crtc(const struct fb_info_aty *info, 471 const struct crtc *crtc) 472{ 473 aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, info); 474 aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, info); 475 aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_tot_disp, info); 476 aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid, info); 477 aty_st_le32(CRTC_VLINE_CRNT_VLINE, 0, info); 478 aty_st_le32(CRTC_OFF_PITCH, crtc->off_pitch, info); 479 aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl, info); 480} 481 482static int aty_var_to_crtc(const struct fb_info_aty *info, 483 const struct fb_var_screeninfo *var, 484 struct crtc *crtc) 485{ 486 u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp; 487 u32 left, right, upper, lower, hslen, vslen, sync, vmode; 488 u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol; 489 u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync; 490 u32 pix_width, dp_pix_width, dp_chain_mask; 491 492 /* input */ 493 xres = var->xres; 494 yres = var->yres; 495 vxres = var->xres_virtual; 496 vyres = var->yres_virtual; 497 xoffset = var->xoffset; 498 yoffset = var->yoffset; 499 bpp = var->bits_per_pixel; 500 left = var->left_margin; 501 right = var->right_margin; 502 upper = var->upper_margin; 503 lower = var->lower_margin; 504 hslen = var->hsync_len; 505 vslen = var->vsync_len; 506 sync = var->sync; 507 vmode = var->vmode; 508 509 /* convert (and round up) and validate */ 510 xres = (xres+7) & ~7; 511 xoffset = (xoffset+7) & ~7; 512 vxres = (vxres+7) & ~7; 513 if (vxres < xres+xoffset) 514 vxres = xres+xoffset; 515 h_disp = xres/8-1; 516 if (h_disp > 0xff) 517 FAIL("h_disp too large"); 518 h_sync_strt = h_disp+(right/8); 519 if (h_sync_strt > 0x1ff) 520 FAIL("h_sync_start too large"); 521 h_sync_dly = right & 7; 522 h_sync_wid = (hslen+7)/8; 523 if (h_sync_wid > 0x1f) 524 FAIL("h_sync_wid too large"); 525 h_total = h_sync_strt+h_sync_wid+(h_sync_dly+left+7)/8; 526 if (h_total > 0x1ff) 527 FAIL("h_total too large"); 528 h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1; 529 530 if (vyres < yres+yoffset) 531 vyres = yres+yoffset; 532 v_disp = yres-1; 533 if (v_disp > 0x7ff) 534 FAIL("v_disp too large"); 535 v_sync_strt = v_disp+lower; 536 if (v_sync_strt > 0x7ff) 537 FAIL("v_sync_strt too large"); 538 v_sync_wid = vslen; 539 if (v_sync_wid > 0x1f) 540 FAIL("v_sync_wid too large"); 541 v_total = v_sync_strt+v_sync_wid+upper; 542 if (v_total > 0x7ff) 543 FAIL("v_total too large"); 544 v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1; 545 546 c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0; 547 548 if (bpp <= 8) { 549 bpp = 8; 550 pix_width = CRTC_PIX_WIDTH_8BPP; 551 dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB; 552 dp_chain_mask = 0x8080; 553 } else if (bpp <= 16) { 554 bpp = 16; 555 pix_width = CRTC_PIX_WIDTH_15BPP; 556 dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP | 557 BYTE_ORDER_LSB_TO_MSB; 558 dp_chain_mask = 0x4210; 559 } else if (bpp <= 24 && M64_HAS(INTEGRATED)) { 560 bpp = 24; 561 pix_width = CRTC_PIX_WIDTH_24BPP; 562 dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB; 563 dp_chain_mask = 0x8080; 564 } else if (bpp <= 32) { 565 bpp = 32; 566 pix_width = CRTC_PIX_WIDTH_32BPP; 567 dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP | 568 BYTE_ORDER_LSB_TO_MSB; 569 dp_chain_mask = 0x8080; 570 } else 571 FAIL("invalid bpp"); 572 573 if (vxres*vyres*bpp/8 > info->total_vram) 574 FAIL("not enough video RAM"); 575 576 if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) 577 FAIL("invalid vmode"); 578 579 /* output */ 580 crtc->vxres = vxres; 581 crtc->vyres = vyres; 582 crtc->xoffset = xoffset; 583 crtc->yoffset = yoffset; 584 crtc->bpp = bpp; 585 crtc->h_tot_disp = h_total | (h_disp<<16); 586 crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly<<8) | 587 ((h_sync_strt & 0x100)<<4) | (h_sync_wid<<16) | 588 (h_sync_pol<<21); 589 crtc->v_tot_disp = v_total | (v_disp<<16); 590 crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid<<16) | (v_sync_pol<<21); 591 crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19); 592 crtc->gen_cntl = pix_width | c_sync | CRTC_EXT_DISP_EN | CRTC_ENABLE; 593 if (M64_HAS(MAGIC_FIFO)) { 594 /* Not VTB/GTB */ 595 crtc->gen_cntl |= aty_ld_le32(CRTC_GEN_CNTL, info) & 0x000e0000; 596 } 597 crtc->dp_pix_width = dp_pix_width; 598 crtc->dp_chain_mask = dp_chain_mask; 599 600 return 0; 601} 602 603 604static int aty_crtc_to_var(const struct crtc *crtc, 605 struct fb_var_screeninfo *var) 606{ 607 u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync; 608 u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol; 609 u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync; 610 u32 pix_width; 611 612 /* input */ 613 h_total = crtc->h_tot_disp & 0x1ff; 614 h_disp = (crtc->h_tot_disp>>16) & 0xff; 615 h_sync_strt = (crtc->h_sync_strt_wid & 0xff) | 616 ((crtc->h_sync_strt_wid>>4) & 0x100); 617 h_sync_dly = (crtc->h_sync_strt_wid>>8) & 0x7; 618 h_sync_wid = (crtc->h_sync_strt_wid>>16) & 0x1f; 619 h_sync_pol = (crtc->h_sync_strt_wid>>21) & 0x1; 620 v_total = crtc->v_tot_disp & 0x7ff; 621 v_disp = (crtc->v_tot_disp>>16) & 0x7ff; 622 v_sync_strt = crtc->v_sync_strt_wid & 0x7ff; 623 v_sync_wid = (crtc->v_sync_strt_wid>>16) & 0x1f; 624 v_sync_pol = (crtc->v_sync_strt_wid>>21) & 0x1; 625 c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0; 626 pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK; 627 628 /* convert */ 629 xres = (h_disp+1)*8; 630 yres = v_disp+1; 631 left = (h_total-h_sync_strt-h_sync_wid)*8-h_sync_dly; 632 right = (h_sync_strt-h_disp)*8+h_sync_dly; 633 hslen = h_sync_wid*8; 634 upper = v_total-v_sync_strt-v_sync_wid; 635 lower = v_sync_strt-v_disp; 636 vslen = v_sync_wid; 637 sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) | 638 (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) | 639 (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0); 640 641 switch (pix_width) { 642 case CRTC_PIX_WIDTH_8BPP: 643 bpp = 8; 644 var->red.offset = 0; 645 var->red.length = 8; 646 var->green.offset = 0; 647 var->green.length = 8; 648 var->blue.offset = 0; 649 var->blue.length = 8; 650 var->transp.offset = 0; 651 var->transp.length = 0; 652 break; 653 case CRTC_PIX_WIDTH_15BPP: /* RGB 555 */ 654 bpp = 16; 655 var->red.offset = 10; 656 var->red.length = 5; 657 var->green.offset = 5; 658 var->green.length = 5; 659 var->blue.offset = 0; 660 var->blue.length = 5; 661 var->transp.offset = 0; 662 var->transp.length = 0; 663 break; 664 case CRTC_PIX_WIDTH_24BPP: /* RGB 888 */ 665 bpp = 24; 666 var->red.offset = 16; 667 var->red.length = 8; 668 var->green.offset = 8; 669 var->green.length = 8; 670 var->blue.offset = 0; 671 var->blue.length = 8; 672 var->transp.offset = 0; 673 var->transp.length = 0; 674 break; 675 case CRTC_PIX_WIDTH_32BPP: /* ARGB 8888 */ 676 bpp = 32; 677 var->red.offset = 16; 678 var->red.length = 8; 679 var->green.offset = 8; 680 var->green.length = 8; 681 var->blue.offset = 0; 682 var->blue.length = 8; 683 var->transp.offset = 24; 684 var->transp.length = 8; 685 break; 686 default: 687 FAIL("Invalid pixel width"); 688 } 689 690 /* output */ 691 var->xres = xres; 692 var->yres = yres; 693 var->xres_virtual = crtc->vxres; 694 var->yres_virtual = crtc->vyres; 695 var->bits_per_pixel = bpp; 696 var->xoffset = crtc->xoffset; 697 var->yoffset = crtc->yoffset; 698 var->left_margin = left; 699 var->right_margin = right; 700 var->upper_margin = upper; 701 var->lower_margin = lower; 702 var->hsync_len = hslen; 703 var->vsync_len = vslen; 704 var->sync = sync; 705 var->vmode = FB_VMODE_NONINTERLACED; 706 707 return 0; 708} 709 710/* ------------------------------------------------------------------------- */ 711 712static void atyfb_set_par(const struct atyfb_par *par, 713 struct fb_info_aty *info) 714{ 715 u32 i; 716 int accelmode; 717 u8 tmp; 718 719 accelmode = par->accel_flags; /* hack */ 720 721 info->current_par = *par; 722 723 if (info->blitter_may_be_busy) 724 wait_for_idle(info); 725 tmp = aty_ld_8(CRTC_GEN_CNTL + 3, info); 726 aty_set_crtc(info, &par->crtc); 727 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info); 728 /* better call aty_StrobeClock ?? */ 729 aty_st_8(CLOCK_CNTL + info->clk_wr_offset, CLOCK_STROBE, info); 730 731 info->dac_ops->set_dac(info, &par->pll, par->crtc.bpp, accelmode); 732 info->pll_ops->set_pll(info, &par->pll); 733 734 if (!M64_HAS(INTEGRATED)) { 735 /* Don't forget MEM_CNTL */ 736 i = aty_ld_le32(MEM_CNTL, info) & 0xf0ffffff; 737 switch (par->crtc.bpp) { 738 case 8: 739 i |= 0x02000000; 740 break; 741 case 16: 742 i |= 0x03000000; 743 break; 744 case 32: 745 i |= 0x06000000; 746 break; 747 } 748 aty_st_le32(MEM_CNTL, i, info); 749 } else { 750 i = aty_ld_le32(MEM_CNTL, info) & 0xf00fffff; 751 if (!M64_HAS(MAGIC_POSTDIV)) 752 i |= info->mem_refresh_rate << 20; 753 switch (par->crtc.bpp) { 754 case 8: 755 case 24: 756 i |= 0x00000000; 757 break; 758 case 16: 759 i |= 0x04000000; 760 break; 761 case 32: 762 i |= 0x08000000; 763 break; 764 } 765 if (M64_HAS(CT_BUS)) { 766 aty_st_le32(DAC_CNTL, 0x87010184, info); 767 aty_st_le32(BUS_CNTL, 0x680000f9, info); 768 } else if (M64_HAS(VT_BUS)) { 769 aty_st_le32(DAC_CNTL, 0x87010184, info); 770 aty_st_le32(BUS_CNTL, 0x680000f9, info); 771 } else if (M64_HAS(MOBIL_BUS)) { 772 aty_st_le32(DAC_CNTL, 0x80010102, info); 773 aty_st_le32(BUS_CNTL, 0x7b33a040, info); 774 } else { 775 /* GT */ 776 aty_st_le32(DAC_CNTL, 0x86010102, info); 777 aty_st_le32(BUS_CNTL, 0x7b23a040, info); 778 aty_st_le32(EXT_MEM_CNTL, 779 aty_ld_le32(EXT_MEM_CNTL, info) | 0x5000001, info); 780 } 781 aty_st_le32(MEM_CNTL, i, info); 782 } 783 aty_st_8(DAC_MASK, 0xff, info); 784 785 /* Initialize the graphics engine */ 786 if (par->accel_flags & FB_ACCELF_TEXT) 787 aty_init_engine(par, info); 788 789#ifdef CONFIG_FB_COMPAT_XPMAC 790 if (!console_fb_info || console_fb_info == &info->fb_info) { 791 struct fb_var_screeninfo var; 792 int vmode, cmode; 793 display_info.height = ((par->crtc.v_tot_disp>>16) & 0x7ff)+1; 794 display_info.width = (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8; 795 display_info.depth = par->crtc.bpp; 796 display_info.pitch = par->crtc.vxres*par->crtc.bpp/8; 797 atyfb_encode_var(&var, par, info); 798 if (mac_var_to_vmode(&var, &vmode, &cmode)) 799 display_info.mode = 0; 800 else 801 display_info.mode = vmode; 802 strcpy(display_info.name, atyfb_name); 803 display_info.fb_address = info->frame_buffer_phys; 804 display_info.cmap_adr_address = info->ati_regbase_phys+0xc0; 805 display_info.cmap_data_address = info->ati_regbase_phys+0xc1; 806 display_info.disp_reg_address = info->ati_regbase_phys; 807 } 808#endif /* CONFIG_FB_COMPAT_XPMAC */ 809#ifdef CONFIG_BOOTX_TEXT 810 btext_update_display(info->frame_buffer_phys, 811 (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8, 812 ((par->crtc.v_tot_disp>>16) & 0x7ff)+1, 813 par->crtc.bpp, 814 par->crtc.vxres*par->crtc.bpp/8); 815#endif /* CONFIG_BOOTX_TEXT */ 816} 817 818static int atyfb_decode_var(const struct fb_var_screeninfo *var, 819 struct atyfb_par *par, 820 const struct fb_info_aty *info) 821{ 822 int err; 823 824 if ((err = aty_var_to_crtc(info, var, &par->crtc)) || 825 (err = info->pll_ops->var_to_pll(info, var->pixclock, par->crtc.bpp, 826 &par->pll))) 827 return err; 828 829 if (var->accel_flags & FB_ACCELF_TEXT) 830 par->accel_flags = FB_ACCELF_TEXT; 831 else 832 par->accel_flags = 0; 833 834 835 return 0; 836} 837 838static int atyfb_encode_var(struct fb_var_screeninfo *var, 839 const struct atyfb_par *par, 840 const struct fb_info_aty *info) 841{ 842 int err; 843 844 memset(var, 0, sizeof(struct fb_var_screeninfo)); 845 846 if ((err = aty_crtc_to_var(&par->crtc, var))) 847 return err; 848 var->pixclock = info->pll_ops->pll_to_var(info, &par->pll); 849 850 var->height = -1; 851 var->width = -1; 852 var->accel_flags = par->accel_flags; 853 854 return 0; 855} 856 857 858 859static void set_off_pitch(struct atyfb_par *par, 860 const struct fb_info_aty *info) 861{ 862 u32 xoffset = par->crtc.xoffset; 863 u32 yoffset = par->crtc.yoffset; 864 u32 vxres = par->crtc.vxres; 865 u32 bpp = par->crtc.bpp; 866 867 par->crtc.off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19); 868 aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, info); 869} 870 871 872 /* 873 * Open/Release the frame buffer device 874 */ 875 876static int atyfb_open(struct fb_info *info, int user) 877 878{ 879#ifdef __sparc__ 880 struct fb_info_aty *fb = (struct fb_info_aty *)info; 881 882 if (user) { 883 fb->open++; 884 fb->mmaped = 0; 885 fb->vtconsole = -1; 886 } else { 887 fb->consolecnt++; 888 } 889#endif 890 return(0); 891} 892 893struct fb_var_screeninfo default_var = { 894 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ 895 640, 480, 640, 480, 0, 0, 8, 0, 896 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 897 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2, 898 0, FB_VMODE_NONINTERLACED 899}; 900 901static int atyfb_release(struct fb_info *info, int user) 902{ 903#ifdef __sparc__ 904 struct fb_info_aty *fb = (struct fb_info_aty *)info; 905 906 if (user) { 907 fb->open--; 908 mdelay(1); 909 wait_for_idle(fb); 910 if (!fb->open) { 911 int was_mmaped = fb->mmaped; 912 913 fb->mmaped = 0; 914 if (fb->vtconsole != -1) 915 vt_cons[fb->vtconsole]->vc_mode = KD_TEXT; 916 fb->vtconsole = -1; 917 918 if (was_mmaped) { 919 struct fb_var_screeninfo var; 920 921 /* Now reset the default display config, we have no 922 * idea what the program(s) which mmap'd the chip did 923 * to the configuration, nor whether it restored it 924 * correctly. 925 */ 926 var = default_var; 927 if (noaccel) 928 var.accel_flags &= ~FB_ACCELF_TEXT; 929 else 930 var.accel_flags |= FB_ACCELF_TEXT; 931 if (var.yres == var.yres_virtual) { 932 u32 vram = (fb->total_vram - (PAGE_SIZE << 2)); 933 var.yres_virtual = ((vram * 8) / var.bits_per_pixel) / 934 var.xres_virtual; 935 if (var.yres_virtual < var.yres) 936 var.yres_virtual = var.yres; 937 } 938 atyfb_set_var(&var, -1, &fb->fb_info); 939 } 940 } 941 } else { 942 fb->consolecnt--; 943 } 944#endif 945 return(0); 946} 947 948 949static int encode_fix(struct fb_fix_screeninfo *fix, 950 const struct atyfb_par *par, 951 const struct fb_info_aty *info) 952{ 953 memset(fix, 0, sizeof(struct fb_fix_screeninfo)); 954 955 strcpy(fix->id, atyfb_name); 956 fix->smem_start = info->frame_buffer_phys; 957 fix->smem_len = (u32)info->total_vram; 958 959 /* 960 * Reg Block 0 (CT-compatible block) is at ati_regbase_phys 961 * Reg Block 1 (multimedia extensions) is at ati_regbase_phys-0x400 962 */ 963 if (M64_HAS(GX)) { 964 fix->mmio_start = info->ati_regbase_phys; 965 fix->mmio_len = 0x400; 966 fix->accel = FB_ACCEL_ATI_MACH64GX; 967 } else if (M64_HAS(CT)) { 968 fix->mmio_start = info->ati_regbase_phys; 969 fix->mmio_len = 0x400; 970 fix->accel = FB_ACCEL_ATI_MACH64CT; 971 } else if (M64_HAS(VT)) { 972 fix->mmio_start = info->ati_regbase_phys-0x400; 973 fix->mmio_len = 0x800; 974 fix->accel = FB_ACCEL_ATI_MACH64VT; 975 } else /* if (M64_HAS(GT)) */ { 976 fix->mmio_start = info->ati_regbase_phys-0x400; 977 fix->mmio_len = 0x800; 978 fix->accel = FB_ACCEL_ATI_MACH64GT; 979 } 980 fix->type = FB_TYPE_PACKED_PIXELS; 981 fix->type_aux = 0; 982 fix->line_length = par->crtc.vxres*par->crtc.bpp/8; 983 fix->visual = par->crtc.bpp <= 8 ? FB_VISUAL_PSEUDOCOLOR 984 : FB_VISUAL_DIRECTCOLOR; 985 fix->ywrapstep = 0; 986 fix->xpanstep = 8; 987 fix->ypanstep = 1; 988 989 return 0; 990} 991 992 993 /* 994 * Get the Fixed Part of the Display 995 */ 996 997static int atyfb_get_fix(struct fb_fix_screeninfo *fix, int con, 998 struct fb_info *fb) 999{ 1000 const struct fb_info_aty *info = (struct fb_info_aty *)fb; 1001 struct atyfb_par par; 1002 1003 if (con == -1) 1004 par = info->default_par; 1005 else 1006 atyfb_decode_var(&fb_display[con].var, &par, info); 1007 encode_fix(fix, &par, info); 1008 return 0; 1009} 1010 1011 1012 /* 1013 * Get the User Defined Part of the Display 1014 */ 1015 1016static int atyfb_get_var(struct fb_var_screeninfo *var, int con, 1017 struct fb_info *fb) 1018{ 1019 const struct fb_info_aty *info = (struct fb_info_aty *)fb; 1020 1021 if (con == -1) 1022 atyfb_encode_var(var, &info->default_par, info); 1023 else 1024 *var = fb_display[con].var; 1025 return 0; 1026} 1027 1028 1029static void atyfb_set_dispsw(struct display *disp, struct fb_info_aty *info, 1030 int bpp, int accel) 1031{ 1032 switch (bpp) { 1033#ifdef FBCON_HAS_CFB8 1034 case 8: 1035 info->dispsw = accel ? fbcon_aty8 : fbcon_cfb8; 1036 disp->dispsw = &info->dispsw; 1037 break; 1038#endif 1039#ifdef FBCON_HAS_CFB16 1040 case 16: 1041 info->dispsw = accel ? fbcon_aty16 : fbcon_cfb16; 1042 disp->dispsw = &info->dispsw; 1043 disp->dispsw_data = info->fbcon_cmap.cfb16; 1044 break; 1045#endif 1046#ifdef FBCON_HAS_CFB24 1047 case 24: 1048 info->dispsw = accel ? fbcon_aty24 : fbcon_cfb24; 1049 disp->dispsw = &info->dispsw; 1050 disp->dispsw_data = info->fbcon_cmap.cfb24; 1051 break; 1052#endif 1053#ifdef FBCON_HAS_CFB32 1054 case 32: 1055 info->dispsw = accel ? fbcon_aty32 : fbcon_cfb32; 1056 disp->dispsw = &info->dispsw; 1057 disp->dispsw_data = info->fbcon_cmap.cfb32; 1058 break; 1059#endif 1060 default: 1061 disp->dispsw = &fbcon_dummy; 1062 } 1063#ifdef CONFIG_FB_ATY_CT 1064 if (info->cursor) { 1065 info->dispsw.cursor = atyfb_cursor; 1066 info->dispsw.set_font = atyfb_set_font; 1067 } 1068#endif /* CONFIG_FB_ATY_CT */ 1069} 1070 1071 1072 /* 1073 * Set the User Defined Part of the Display 1074 */ 1075 1076static int atyfb_set_var(struct fb_var_screeninfo *var, int con, 1077 struct fb_info *fb) 1078{ 1079 struct fb_info_aty *info = (struct fb_info_aty *)fb; 1080 struct atyfb_par par; 1081 struct display *display; 1082 int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel, accel, err; 1083 int activate = var->activate; 1084 1085 if (con >= 0) 1086 display = &fb_display[con]; 1087 else 1088 display = fb->disp; /* used during initialization */ 1089 1090 if ((err = atyfb_decode_var(var, &par, info))) 1091 return err; 1092 1093 atyfb_encode_var(var, &par, (struct fb_info_aty *)info); 1094 1095 if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { 1096 oldxres = display->var.xres; 1097 oldyres = display->var.yres; 1098 oldvxres = display->var.xres_virtual; 1099 oldvyres = display->var.yres_virtual; 1100 oldbpp = display->var.bits_per_pixel; 1101 oldaccel = display->var.accel_flags; 1102 display->var = *var; 1103 accel = var->accel_flags & FB_ACCELF_TEXT; 1104 if (oldxres != var->xres || oldyres != var->yres || 1105 oldvxres != var->xres_virtual || oldvyres != var->yres_virtual || 1106 oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) { 1107 struct fb_fix_screeninfo fix; 1108 1109 encode_fix(&fix, &par, info); 1110 display->screen_base = (char *)info->frame_buffer; 1111 display->visual = fix.visual; 1112 display->type = fix.type; 1113 display->type_aux = fix.type_aux; 1114 display->ypanstep = fix.ypanstep; 1115 display->ywrapstep = fix.ywrapstep; 1116 display->line_length = fix.line_length; 1117 display->can_soft_blank = 1; 1118 display->inverse = 0; 1119 if (accel) 1120 display->scrollmode = (info->bus_type == PCI) ? SCROLL_YNOMOVE : 0; 1121 else 1122 display->scrollmode = SCROLL_YREDRAW; 1123 if (info->fb_info.changevar) 1124 (*info->fb_info.changevar)(con); 1125 } 1126 if (!info->fb_info.display_fg || 1127 info->fb_info.display_fg->vc_num == con) { 1128 atyfb_set_par(&par, info); 1129 atyfb_set_dispsw(display, info, par.crtc.bpp, accel); 1130 } 1131 if (oldbpp != var->bits_per_pixel) { 1132 if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) 1133 return err; 1134 do_install_cmap(con, &info->fb_info); 1135 } 1136 } 1137 1138 return 0; 1139} 1140 1141 1142 /* 1143 * Pan or Wrap the Display 1144 * 1145 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag 1146 */ 1147 1148static int atyfb_pan_display(struct fb_var_screeninfo *var, int con, 1149 struct fb_info *fb) 1150{ 1151 struct fb_info_aty *info = (struct fb_info_aty *)fb; 1152 u32 xres, yres, xoffset, yoffset; 1153 struct atyfb_par *par = &info->current_par; 1154 1155 xres = (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8; 1156 yres = ((par->crtc.v_tot_disp>>16) & 0x7ff)+1; 1157 xoffset = (var->xoffset+7) & ~7; 1158 yoffset = var->yoffset; 1159 if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres) 1160 return -EINVAL; 1161 par->crtc.xoffset = xoffset; 1162 par->crtc.yoffset = yoffset; 1163 set_off_pitch(par, info); 1164 return 0; 1165} 1166 1167 /* 1168 * Get the Colormap 1169 */ 1170 1171static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, 1172 struct fb_info *info) 1173{ 1174 if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */ 1175 return fb_get_cmap(cmap, kspc, atyfb_getcolreg, info); 1176 else if (fb_display[con].cmap.len) /* non default colormap? */ 1177 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); 1178 else { 1179 int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256; 1180 fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2); 1181 } 1182 return 0; 1183} 1184 1185 /* 1186 * Set the Colormap 1187 */ 1188 1189static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, 1190 struct fb_info *info) 1191{ 1192 int err; 1193 struct display *disp; 1194 1195 if (con >= 0) 1196 disp = &fb_display[con]; 1197 else 1198 disp = info->disp; 1199 if (!disp->cmap.len) { /* no colormap allocated? */ 1200 int size = disp->var.bits_per_pixel == 16 ? 32 : 256; 1201 if ((err = fb_alloc_cmap(&disp->cmap, size, 0))) 1202 return err; 1203 } 1204 if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */ 1205 return fb_set_cmap(cmap, kspc, atyfb_setcolreg, info); 1206 else 1207 fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1); 1208 return 0; 1209} 1210 1211 1212#ifdef DEBUG 1213#define ATYIO_CLKR 0x41545900 /* ATY\00 */ 1214#define ATYIO_CLKW 0x41545901 /* ATY\01 */ 1215 1216struct atyclk { 1217 u32 ref_clk_per; 1218 u8 pll_ref_div; 1219 u8 mclk_fb_div; 1220 u8 mclk_post_div; /* 1,2,3,4,8 */ 1221 u8 vclk_fb_div; 1222 u8 vclk_post_div; /* 1,2,3,4,6,8,12 */ 1223 u32 dsp_xclks_per_row; /* 0-16383 */ 1224 u32 dsp_loop_latency; /* 0-15 */ 1225 u32 dsp_precision; /* 0-7 */ 1226 u32 dsp_on; /* 0-2047 */ 1227 u32 dsp_off; /* 0-2047 */ 1228}; 1229 1230#define ATYIO_FEATR 0x41545902 /* ATY\02 */ 1231#define ATYIO_FEATW 0x41545903 /* ATY\03 */ 1232#endif 1233 1234static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, 1235 u_long arg, int con, struct fb_info *info2) 1236{ 1237#if defined(__sparc__) || (defined(DEBUG) && defined(CONFIG_FB_ATY_CT)) 1238 struct fb_info_aty *info = (struct fb_info_aty *)info2; 1239#endif /* __sparc__ || DEBUG */ 1240#ifdef __sparc__ 1241 struct fbtype fbtyp; 1242 struct display *disp; 1243 1244 if (con >= 0) 1245 disp = &fb_display[con]; 1246 else 1247 disp = info2->disp; 1248#endif 1249 1250 switch (cmd) { 1251#ifdef __sparc__ 1252 case FBIOGTYPE: 1253 fbtyp.fb_type = FBTYPE_PCI_GENERIC; 1254 fbtyp.fb_width = info->current_par.crtc.vxres; 1255 fbtyp.fb_height = info->current_par.crtc.vyres; 1256 fbtyp.fb_depth = info->current_par.crtc.bpp; 1257 fbtyp.fb_cmsize = disp->cmap.len; 1258 fbtyp.fb_size = info->total_vram; 1259 if (copy_to_user((struct fbtype *)arg, &fbtyp, sizeof(fbtyp))) 1260 return -EFAULT; 1261 break; 1262#endif /* __sparc__ */ 1263#if defined(DEBUG) && defined(CONFIG_FB_ATY_CT) 1264 case ATYIO_CLKR: 1265 if (M64_HAS(INTEGRATED)) { 1266 struct atyclk clk; 1267 union aty_pll *pll = &info->current_par.pll; 1268 u32 dsp_config = pll->ct.dsp_config; 1269 u32 dsp_on_off = pll->ct.dsp_on_off; 1270 clk.ref_clk_per = info->ref_clk_per; 1271 clk.pll_ref_div = pll->ct.pll_ref_div; 1272 clk.mclk_fb_div = pll->ct.mclk_fb_div; 1273 clk.mclk_post_div = pll->ct.mclk_post_div_real; 1274 clk.vclk_fb_div = pll->ct.vclk_fb_div; 1275 clk.vclk_post_div = pll->ct.vclk_post_div_real; 1276 clk.dsp_xclks_per_row = dsp_config & 0x3fff; 1277 clk.dsp_loop_latency = (dsp_config>>16) & 0xf; 1278 clk.dsp_precision = (dsp_config>>20) & 7; 1279 clk.dsp_on = dsp_on_off & 0x7ff; 1280 clk.dsp_off = (dsp_on_off>>16) & 0x7ff; 1281 if (copy_to_user((struct atyclk *)arg, &clk, sizeof(clk))) 1282 return -EFAULT; 1283 } else 1284 return -EINVAL; 1285 break; 1286 case ATYIO_CLKW: 1287 if (M64_HAS(INTEGRATED)) { 1288 struct atyclk clk; 1289 union aty_pll *pll = &info->current_par.pll; 1290 if (copy_from_user(&clk, (struct atyclk *)arg, sizeof(clk))) 1291 return -EFAULT; 1292 info->ref_clk_per = clk.ref_clk_per; 1293 pll->ct.pll_ref_div = clk.pll_ref_div; 1294 pll->ct.mclk_fb_div = clk.mclk_fb_div; 1295 pll->ct.mclk_post_div_real = clk.mclk_post_div; 1296 pll->ct.vclk_fb_div = clk.vclk_fb_div; 1297 pll->ct.vclk_post_div_real = clk.vclk_post_div; 1298 pll->ct.dsp_config = (clk.dsp_xclks_per_row & 0x3fff) | 1299 ((clk.dsp_loop_latency & 0xf)<<16) | 1300 ((clk.dsp_precision & 7)<<20); 1301 pll->ct.dsp_on_off = (clk.dsp_on & 0x7ff) | 1302 ((clk.dsp_off & 0x7ff)<<16); 1303 aty_calc_pll_ct(info, &pll->ct); 1304 aty_set_pll_ct(info, pll); 1305 } else 1306 return -EINVAL; 1307 break; 1308 case ATYIO_FEATR: 1309 if (get_user(info->features, (u32 *)arg)) 1310 return -EFAULT; 1311 break; 1312 case ATYIO_FEATW: 1313 if (put_user(info->features, (u32 *)arg)) 1314 return -EFAULT; 1315 break; 1316#endif /* DEBUG && CONFIG_FB_ATY_CT */ 1317 default: 1318 return -EINVAL; 1319 } 1320 return 0; 1321} 1322 1323static int atyfb_rasterimg(struct fb_info *info, int start) 1324{ 1325 struct fb_info_aty *fb = (struct fb_info_aty *)info; 1326 1327 if (fb->blitter_may_be_busy) 1328 wait_for_idle(fb); 1329 return 0; 1330} 1331 1332#ifdef __sparc__ 1333static int atyfb_mmap(struct fb_info *info, struct file *file, 1334 struct vm_area_struct *vma) 1335{ 1336 struct fb_info_aty *fb = (struct fb_info_aty *)info; 1337 unsigned int size, page, map_size = 0; 1338 unsigned long map_offset = 0; 1339 unsigned long off; 1340 int i; 1341 1342 if (!fb->mmap_map) 1343 return -ENXIO; 1344 1345 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) 1346 return -EINVAL; 1347 1348 off = vma->vm_pgoff << PAGE_SHIFT; 1349 size = vma->vm_end - vma->vm_start; 1350 1351 /* To stop the swapper from even considering these pages. */ 1352 vma->vm_flags |= (VM_SHM | VM_LOCKED); 1353 1354 if (((vma->vm_pgoff == 0) && (size == fb->total_vram)) || 1355 ((off == fb->total_vram) && (size == PAGE_SIZE))) 1356 off += 0x8000000000000000UL; 1357 1358 vma->vm_pgoff = off >> PAGE_SHIFT; /* propagate off changes */ 1359 1360 /* Each page, see which map applies */ 1361 for (page = 0; page < size; ) { 1362 map_size = 0; 1363 for (i = 0; fb->mmap_map[i].size; i++) { 1364 unsigned long start = fb->mmap_map[i].voff; 1365 unsigned long end = start + fb->mmap_map[i].size; 1366 unsigned long offset = off + page; 1367 1368 if (start > offset) 1369 continue; 1370 if (offset >= end) 1371 continue; 1372 1373 map_size = fb->mmap_map[i].size - (offset - start); 1374 map_offset = fb->mmap_map[i].poff + (offset - start); 1375 break; 1376 } 1377 if (!map_size) { 1378 page += PAGE_SIZE; 1379 continue; 1380 } 1381 if (page + map_size > size) 1382 map_size = size - page; 1383 1384 pgprot_val(vma->vm_page_prot) &= ~(fb->mmap_map[i].prot_mask); 1385 pgprot_val(vma->vm_page_prot) |= fb->mmap_map[i].prot_flag; 1386 1387 if (remap_page_range(vma->vm_start + page, map_offset, 1388 map_size, vma->vm_page_prot)) 1389 return -EAGAIN; 1390 1391 page += map_size; 1392 } 1393 1394 if (!map_size) 1395 return -EINVAL; 1396 1397 vma->vm_flags |= VM_IO; 1398 1399 if (!fb->mmaped) { 1400 int lastconsole = 0; 1401 1402 if (info->display_fg) 1403 lastconsole = info->display_fg->vc_num; 1404 fb->mmaped = 1; 1405 if (fb->consolecnt && fb_display[lastconsole].fb_info == info) { 1406 fb->vtconsole = lastconsole; 1407 vt_cons[lastconsole]->vc_mode = KD_GRAPHICS; 1408 } 1409 } 1410 return 0; 1411} 1412 1413static struct { 1414 u32 yoffset; 1415 u8 r[2][256]; 1416 u8 g[2][256]; 1417 u8 b[2][256]; 1418} atyfb_save; 1419 1420static void atyfb_save_palette(struct fb_info *fb, int enter) 1421{ 1422 struct fb_info_aty *info = (struct fb_info_aty *)fb; 1423 int i, tmp; 1424 1425 for (i = 0; i < 256; i++) { 1426 tmp = aty_ld_8(DAC_CNTL, info) & 0xfc; 1427 if (M64_HAS(EXTRA_BRIGHT)) 1428 tmp |= 0x2; 1429 aty_st_8(DAC_CNTL, tmp, info); 1430 aty_st_8(DAC_MASK, 0xff, info); 1431 1432 writeb(i, &info->aty_cmap_regs->rindex); 1433 atyfb_save.r[enter][i] = readb(&info->aty_cmap_regs->lut); 1434 atyfb_save.g[enter][i] = readb(&info->aty_cmap_regs->lut); 1435 atyfb_save.b[enter][i] = readb(&info->aty_cmap_regs->lut); 1436 writeb(i, &info->aty_cmap_regs->windex); 1437 writeb(atyfb_save.r[1-enter][i], &info->aty_cmap_regs->lut); 1438 writeb(atyfb_save.g[1-enter][i], &info->aty_cmap_regs->lut); 1439 writeb(atyfb_save.b[1-enter][i], &info->aty_cmap_regs->lut); 1440 } 1441} 1442 1443static void atyfb_palette(int enter) 1444{ 1445 struct fb_info_aty *info; 1446 struct atyfb_par *par; 1447 struct display *d; 1448 int i; 1449 1450 for (i = 0; i < MAX_NR_CONSOLES; i++) { 1451 d = &fb_display[i]; 1452 if (d->fb_info && 1453 d->fb_info->fbops == &atyfb_ops && 1454 d->fb_info->display_fg && 1455 d->fb_info->display_fg->vc_num == i) { 1456 atyfb_save_palette(d->fb_info, enter); 1457 info = (struct fb_info_aty *)d->fb_info; 1458 par = &info->current_par; 1459 if (enter) { 1460 atyfb_save.yoffset = par->crtc.yoffset; 1461 par->crtc.yoffset = 0; 1462 set_off_pitch(par, info); 1463 } else { 1464 par->crtc.yoffset = atyfb_save.yoffset; 1465 set_off_pitch(par, info); 1466 } 1467 break; 1468 } 1469 } 1470} 1471#endif /* __sparc__ */ 1472 1473 1474 1475#ifdef CONFIG_PMAC_PBOOK 1476 1477static struct fb_info_aty* first_display = NULL; 1478 1479/* Power management routines. Those are used for PowerBook sleep. 1480 * 1481 * It appears that Rage LT and Rage LT Pro have different power 1482 * management registers. There's is some confusion about which 1483 * chipID is a Rage LT or LT pro :( 1484 */ 1485static int aty_power_mgmt_LT(int sleep, struct fb_info_aty *info) 1486{ 1487 unsigned int pm; 1488 int timeout; 1489 1490 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info); 1491 pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG; 1492 aty_st_le32(POWER_MANAGEMENT_LG, pm, info); 1493 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info); 1494 1495 timeout = 200000; 1496 if (sleep) { 1497 /* Sleep */ 1498 pm &= ~PWR_MGT_ON; 1499 aty_st_le32(POWER_MANAGEMENT_LG, pm, info); 1500 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info); 1501 udelay(10); 1502 pm &= ~(PWR_BLON | AUTO_PWR_UP); 1503 pm |= SUSPEND_NOW; 1504 aty_st_le32(POWER_MANAGEMENT_LG, pm, info); 1505 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info); 1506 udelay(10); 1507 pm |= PWR_MGT_ON; 1508 aty_st_le32(POWER_MANAGEMENT_LG, pm, info); 1509 do { 1510 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info); 1511 udelay(10); 1512 if ((--timeout) == 0) 1513 break; 1514 } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND); 1515 } else { 1516 /* Wakeup */ 1517 pm &= ~PWR_MGT_ON; 1518 aty_st_le32(POWER_MANAGEMENT_LG, pm, info); 1519 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info); 1520 udelay(10); 1521 pm |= (PWR_BLON | AUTO_PWR_UP); 1522 pm &= ~SUSPEND_NOW; 1523 aty_st_le32(POWER_MANAGEMENT_LG, pm, info); 1524 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info); 1525 udelay(10); 1526 pm |= PWR_MGT_ON; 1527 aty_st_le32(POWER_MANAGEMENT_LG, pm, info); 1528 do { 1529 pm = aty_ld_le32(POWER_MANAGEMENT_LG, info); 1530 udelay(10); 1531 if ((--timeout) == 0) 1532 break; 1533 } while ((pm & PWR_MGT_STATUS_MASK) != 0); 1534 } 1535 mdelay(500); 1536 1537 return timeout ? PBOOK_SLEEP_OK : PBOOK_SLEEP_REFUSE; 1538} 1539 1540static int aty_power_mgmt_LTPro(int sleep, struct fb_info_aty *info) 1541{ 1542 unsigned int pm; 1543 int timeout; 1544 1545 pm = aty_ld_lcd(POWER_MANAGEMENT, info); 1546 pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG; 1547 aty_st_lcd(POWER_MANAGEMENT, pm, info); 1548 pm = aty_ld_lcd(POWER_MANAGEMENT, info); 1549 1550 timeout = 200; 1551 if (sleep) { 1552 /* Sleep */ 1553 pm &= ~PWR_MGT_ON; 1554 aty_st_lcd(POWER_MANAGEMENT, pm, info); 1555 pm = aty_ld_lcd(POWER_MANAGEMENT, info); 1556 udelay(10); 1557 pm &= ~(PWR_BLON | AUTO_PWR_UP); 1558 pm |= SUSPEND_NOW; 1559 aty_st_lcd(POWER_MANAGEMENT, pm, info); 1560 pm = aty_ld_lcd(POWER_MANAGEMENT, info); 1561 udelay(10); 1562 pm |= PWR_MGT_ON; 1563 aty_st_lcd(POWER_MANAGEMENT, pm, info); 1564 do { 1565 pm = aty_ld_lcd(POWER_MANAGEMENT, info); 1566 mdelay(1); 1567 if ((--timeout) == 0) 1568 break; 1569 } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND); 1570 } else { 1571 /* Wakeup */ 1572 pm &= ~PWR_MGT_ON; 1573 aty_st_lcd(POWER_MANAGEMENT, pm, info); 1574 pm = aty_ld_lcd(POWER_MANAGEMENT, info); 1575 udelay(10); 1576 pm &= ~SUSPEND_NOW; 1577 pm |= (PWR_BLON | AUTO_PWR_UP); 1578 aty_st_lcd(POWER_MANAGEMENT, pm, info); 1579 pm = aty_ld_lcd(POWER_MANAGEMENT, info); 1580 udelay(10); 1581 pm |= PWR_MGT_ON; 1582 aty_st_lcd(POWER_MANAGEMENT, pm, info); 1583 do { 1584 pm = aty_ld_lcd(POWER_MANAGEMENT, info); 1585 mdelay(1); 1586 if ((--timeout) == 0) 1587 break; 1588 } while ((pm & PWR_MGT_STATUS_MASK) != 0); 1589 } 1590 1591 return timeout ? PBOOK_SLEEP_OK : PBOOK_SLEEP_REFUSE; 1592} 1593 1594static int aty_power_mgmt(int sleep, struct fb_info_aty *info) 1595{ 1596 return M64_HAS(LT_SLEEP) ? aty_power_mgmt_LT(sleep, info) 1597 : aty_power_mgmt_LTPro(sleep, info); 1598} 1599 1600/* 1601 * Save the contents of the frame buffer when we go to sleep, 1602 * and restore it when we wake up again. 1603 */ 1604static int aty_sleep_notify(struct pmu_sleep_notifier *self, int when) 1605{ 1606 struct fb_info_aty *info; 1607 int result; 1608 1609 result = PBOOK_SLEEP_OK; 1610 1611 for (info = first_display; info != NULL; info = info->next) { 1612 struct fb_fix_screeninfo fix; 1613 int nb; 1614 1615 atyfb_get_fix(&fix, fg_console, (struct fb_info *)info); 1616 nb = fb_display[fg_console].var.yres * fix.line_length; 1617 1618 switch (when) { 1619 case PBOOK_SLEEP_REQUEST: 1620 info->save_framebuffer = vmalloc(nb); 1621 if (info->save_framebuffer == NULL) 1622 return PBOOK_SLEEP_REFUSE; 1623 break; 1624 case PBOOK_SLEEP_REJECT: 1625 if (info->save_framebuffer) { 1626 vfree(info->save_framebuffer); 1627 info->save_framebuffer = 0; 1628 } 1629 break; 1630 case PBOOK_SLEEP_NOW: 1631 if (currcon >= 0) 1632 fb_display[currcon].dispsw = &fbcon_dummy; 1633 if (info->blitter_may_be_busy) 1634 wait_for_idle(info); 1635 /* Stop accel engine (stop bus mastering) */ 1636 if (info->current_par.accel_flags & FB_ACCELF_TEXT) 1637 aty_reset_engine(info); 1638 1639 /* Backup fb content */ 1640 if (info->save_framebuffer) 1641 memcpy_fromio(info->save_framebuffer, 1642 (void *)info->frame_buffer, nb); 1643 1644 /* Blank display and LCD */ 1645 atyfbcon_blank(VESA_POWERDOWN+1, (struct fb_info *)info); 1646 1647 /* Set chip to "suspend" mode */ 1648 result = aty_power_mgmt(1, info); 1649 break; 1650 case PBOOK_WAKE: 1651 /* Wakeup chip */ 1652 result = aty_power_mgmt(0, info); 1653 1654 /* Restore fb content */ 1655 if (info->save_framebuffer) { 1656 memcpy_toio((void *)info->frame_buffer, 1657 info->save_framebuffer, nb); 1658 vfree(info->save_framebuffer); 1659 info->save_framebuffer = 0; 1660 } 1661 /* Restore display */ 1662 if (currcon >= 0) { 1663 atyfb_set_dispsw(&fb_display[currcon], 1664 info, info->current_par.crtc.bpp, 1665 info->current_par.accel_flags & FB_ACCELF_TEXT); 1666 } 1667 atyfbcon_blank(0, (struct fb_info *)info); 1668 break; 1669 } 1670 } 1671 return result; 1672} 1673 1674static struct pmu_sleep_notifier aty_sleep_notifier = { 1675 aty_sleep_notify, SLEEP_LEVEL_VIDEO, 1676}; 1677#endif /* CONFIG_PMAC_PBOOK */ 1678 1679#ifdef CONFIG_PMAC_BACKLIGHT 1680 1681 /* 1682 * LCD backlight control 1683 */ 1684 1685static int backlight_conv[] = { 1686 0x00, 0x3f, 0x4c, 0x59, 0x66, 0x73, 0x80, 0x8d, 1687 0x9a, 0xa7, 0xb4, 0xc1, 0xcf, 0xdc, 0xe9, 0xff 1688}; 1689 1690static int 1691aty_set_backlight_enable(int on, int level, void* data) 1692{ 1693 struct fb_info_aty *info = (struct fb_info_aty *)data; 1694 unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, info); 1695 1696 reg |= (BLMOD_EN | BIASMOD_EN); 1697 if (on && level > BACKLIGHT_OFF) { 1698 reg &= ~BIAS_MOD_LEVEL_MASK; 1699 reg |= (backlight_conv[level] << BIAS_MOD_LEVEL_SHIFT); 1700 } else { 1701 reg &= ~BIAS_MOD_LEVEL_MASK; 1702 reg |= (backlight_conv[0] << BIAS_MOD_LEVEL_SHIFT); 1703 } 1704 aty_st_lcd(LCD_MISC_CNTL, reg, info); 1705 1706 return 0; 1707} 1708 1709static int 1710aty_set_backlight_level(int level, void* data) 1711{ 1712 return aty_set_backlight_enable(1, level, data); 1713} 1714 1715static struct backlight_controller aty_backlight_controller = { 1716 aty_set_backlight_enable, 1717 aty_set_backlight_level 1718}; 1719#endif /* CONFIG_PMAC_BACKLIGHT */ 1720 1721 1722 1723 /* 1724 * Initialisation 1725 */ 1726 1727static struct fb_info_aty *fb_list = NULL; 1728 1729static int __init aty_init(struct fb_info_aty *info, const char *name) 1730{ 1731 u32 chip_id; 1732 u32 i; 1733 int j, k; 1734 struct fb_var_screeninfo var; 1735 struct display *disp; 1736 u16 type; 1737 u8 rev; 1738 const char *chipname = NULL, *ramname = NULL, *xtal; 1739 int pll, mclk, gtb_memsize; 1740#if defined(CONFIG_PPC) 1741 int sense; 1742#endif 1743 u8 pll_ref_div; 1744 1745 info->aty_cmap_regs = (struct aty_cmap_regs *)(info->ati_regbase+0xc0); 1746 chip_id = aty_ld_le32(CONFIG_CHIP_ID, info); 1747 type = chip_id & CFG_CHIP_TYPE; 1748 rev = (chip_id & CFG_CHIP_REV)>>24; 1749 for (j = 0; j < (sizeof(aty_chips)/sizeof(*aty_chips)); j++) 1750 if (type == aty_chips[j].chip_type && 1751 (rev & aty_chips[j].rev_mask) == aty_chips[j].rev_val) { 1752 chipname = aty_chips[j].name; 1753 pll = aty_chips[j].pll; 1754 mclk = aty_chips[j].mclk; 1755 info->features = aty_chips[j].features; 1756 goto found; 1757 } 1758 printk("atyfb: Unknown mach64 0x%04x rev 0x%04x\n", type, rev); 1759 return 0; 1760 1761found: 1762 printk("atyfb: %s [0x%04x rev 0x%02x] ", chipname, type, rev); 1763#ifdef CONFIG_FB_ATY_GX 1764 if (!M64_HAS(INTEGRATED)) { 1765 u32 stat0; 1766 u8 dac_type, dac_subtype, clk_type; 1767 stat0 = aty_ld_le32(CONFIG_STAT0, info); 1768 info->bus_type = (stat0 >> 0) & 0x07; 1769 info->ram_type = (stat0 >> 3) & 0x07; 1770 ramname = aty_gx_ram[info->ram_type]; 1771 dac_type = (aty_ld_le32(DAC_CNTL, info) >> 16) & 0x07; 1772#ifdef CONFIG_ATARI 1773 clk_type = CLK_ATI18818_1; 1774 dac_type = (stat0 >> 9) & 0x07; 1775 if (dac_type == 0x07) 1776 dac_subtype = DAC_ATT20C408; 1777 else 1778 dac_subtype = (aty_ld_8(SCRATCH_REG1 + 1, info) & 0xF0) | dac_type; 1779#else 1780 dac_type = DAC_IBMRGB514; 1781 dac_subtype = DAC_IBMRGB514; 1782 clk_type = CLK_IBMRGB514; 1783#endif 1784 switch (dac_subtype) { 1785 case DAC_IBMRGB514: 1786 info->dac_ops = &aty_dac_ibm514; 1787 break; 1788 case DAC_ATI68860_B: 1789 case DAC_ATI68860_C: 1790 info->dac_ops = &aty_dac_ati68860b; 1791 break; 1792 case DAC_ATT20C408: 1793 case DAC_ATT21C498: 1794 info->dac_ops = &aty_dac_att21c498; 1795 break; 1796 default: 1797 printk(" atyfb_set_par: DAC type not implemented yet!\n"); 1798 info->dac_ops = &aty_dac_unsupported; 1799 break; 1800 } 1801 switch (clk_type) { 1802 case CLK_ATI18818_1: 1803 info->pll_ops = &aty_pll_ati18818_1; 1804 break; 1805 case CLK_STG1703: 1806 info->pll_ops = &aty_pll_stg1703; 1807 break; 1808 case CLK_CH8398: 1809 info->pll_ops = &aty_pll_ch8398; 1810 break; 1811 case CLK_ATT20C408: 1812 info->pll_ops = &aty_pll_att20c408; 1813 break; 1814 case CLK_IBMRGB514: 1815 info->pll_ops = &aty_pll_ibm514; 1816 break; 1817 default: 1818 printk(" atyfb_set_par: CLK type not implemented yet!"); 1819 info->pll_ops = &aty_pll_unsupported; 1820 break; 1821 } 1822 } 1823#endif /* CONFIG_FB_ATY_GX */ 1824#ifdef CONFIG_FB_ATY_CT 1825 if (M64_HAS(INTEGRATED)) { 1826 info->bus_type = PCI; 1827 info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) & 0x07); 1828 ramname = aty_ct_ram[info->ram_type]; 1829 info->dac_ops = &aty_dac_ct; 1830 info->pll_ops = &aty_pll_ct; 1831 /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */ 1832 if (mclk == 67 && info->ram_type < SDRAM) 1833 mclk = 63; 1834 } 1835#endif /* CONFIG_FB_ATY_CT */ 1836 1837 info->ref_clk_per = 1000000000000ULL/14318180; 1838 xtal = "14.31818"; 1839 if (M64_HAS(GTB_DSP) && (pll_ref_div = aty_ld_pll(PLL_REF_DIV, info))) { 1840 int diff1, diff2; 1841 diff1 = 510*14/pll_ref_div-pll; 1842 diff2 = 510*29/pll_ref_div-pll; 1843 if (diff1 < 0) 1844 diff1 = -diff1; 1845 if (diff2 < 0) 1846 diff2 = -diff2; 1847 if (diff2 < diff1) { 1848 info->ref_clk_per = 1000000000000ULL/29498928; 1849 xtal = "29.498928"; 1850 } 1851 } 1852 1853 i = aty_ld_le32(MEM_CNTL, info); 1854 gtb_memsize = M64_HAS(GTB_DSP); 1855 if (gtb_memsize) 1856 switch (i & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */ 1857 case MEM_SIZE_512K: 1858 info->total_vram = 0x80000; 1859 break; 1860 case MEM_SIZE_1M: 1861 info->total_vram = 0x100000; 1862 break; 1863 case MEM_SIZE_2M_GTB: 1864 info->total_vram = 0x200000; 1865 break; 1866 case MEM_SIZE_4M_GTB: 1867 info->total_vram = 0x400000; 1868 break; 1869 case MEM_SIZE_6M_GTB: 1870 info->total_vram = 0x600000; 1871 break; 1872 case MEM_SIZE_8M_GTB: 1873 info->total_vram = 0x800000; 1874 break; 1875 default: 1876 info->total_vram = 0x80000; 1877 } 1878 else 1879 switch (i & MEM_SIZE_ALIAS) { 1880 case MEM_SIZE_512K: 1881 info->total_vram = 0x80000; 1882 break; 1883 case MEM_SIZE_1M: 1884 info->total_vram = 0x100000; 1885 break; 1886 case MEM_SIZE_2M: 1887 info->total_vram = 0x200000; 1888 break; 1889 case MEM_SIZE_4M: 1890 info->total_vram = 0x400000; 1891 break; 1892 case MEM_SIZE_6M: 1893 info->total_vram = 0x600000; 1894 break; 1895 case MEM_SIZE_8M: 1896 info->total_vram = 0x800000; 1897 break; 1898 default: 1899 info->total_vram = 0x80000; 1900 } 1901 1902 if (M64_HAS(MAGIC_VRAM_SIZE)) { 1903 if (aty_ld_le32(CONFIG_STAT1, info) & 0x40000000) 1904 info->total_vram += 0x400000; 1905 } 1906 1907 if (default_vram) { 1908 info->total_vram = default_vram*1024; 1909 i = i & ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS); 1910 if (info->total_vram <= 0x80000) 1911 i |= MEM_SIZE_512K; 1912 else if (info->total_vram <= 0x100000) 1913 i |= MEM_SIZE_1M; 1914 else if (info->total_vram <= 0x200000) 1915 i |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M; 1916 else if (info->total_vram <= 0x400000) 1917 i |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M; 1918 else if (info->total_vram <= 0x600000) 1919 i |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M; 1920 else 1921 i |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M; 1922 aty_st_le32(MEM_CNTL, i, info); 1923 } 1924 if (default_pll) 1925 pll = default_pll; 1926 if (default_mclk) 1927 mclk = default_mclk; 1928 1929 printk("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK\n", 1930 info->total_vram == 0x80000 ? 512 : (info->total_vram >> 20), 1931 info->total_vram == 0x80000 ? 'K' : 'M', ramname, xtal, pll, mclk); 1932 1933 if (mclk < 44) 1934 info->mem_refresh_rate = 0; /* 000 = 10 Mhz - 43 Mhz */ 1935 else if (mclk < 50) 1936 info->mem_refresh_rate = 1; /* 001 = 44 Mhz - 49 Mhz */ 1937 else if (mclk < 55) 1938 info->mem_refresh_rate = 2; /* 010 = 50 Mhz - 54 Mhz */ 1939 else if (mclk < 66) 1940 info->mem_refresh_rate = 3; /* 011 = 55 Mhz - 65 Mhz */ 1941 else if (mclk < 75) 1942 info->mem_refresh_rate = 4; /* 100 = 66 Mhz - 74 Mhz */ 1943 else if (mclk < 80) 1944 info->mem_refresh_rate = 5; /* 101 = 75 Mhz - 79 Mhz */ 1945 else if (mclk < 100) 1946 info->mem_refresh_rate = 6; /* 110 = 80 Mhz - 100 Mhz */ 1947 else 1948 info->mem_refresh_rate = 7; /* 111 = 100 Mhz and above */ 1949 info->pll_per = 1000000/pll; 1950 info->mclk_per = 1000000/mclk; 1951 1952#ifdef DEBUG 1953 if (M64_HAS(INTEGRATED)) { 1954 int i; 1955 printk("BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL " 1956 "DSP_CONFIG DSP_ON_OFF\n" 1957 "%08x %08x %08x %08x %08x %08x %08x\n" 1958 "PLL", 1959 aty_ld_le32(BUS_CNTL, info), aty_ld_le32(DAC_CNTL, info), 1960 aty_ld_le32(MEM_CNTL, info), aty_ld_le32(EXT_MEM_CNTL, info), 1961 aty_ld_le32(CRTC_GEN_CNTL, info), aty_ld_le32(DSP_CONFIG, info), 1962 aty_ld_le32(DSP_ON_OFF, info)); 1963 for (i = 0; i < 16; i++) 1964 printk(" %02x", aty_ld_pll(i, info)); 1965 printk("\n"); 1966 } 1967#endif 1968 1969 if (info->total_vram == 0x800000 || 1970 (info->bus_type == ISA && info->total_vram == 0x400000)) 1971 info->total_vram -= GUI_RESERVE; 1972 1973 /* Clear the video memory */ 1974 fb_memset((void *)info->frame_buffer, 0, info->total_vram); 1975 1976 disp = &info->disp; 1977 1978 strcpy(info->fb_info.modename, atyfb_name); 1979 info->fb_info.node = -1; 1980 info->fb_info.fbops = &atyfb_ops; 1981 info->fb_info.disp = disp; 1982 strcpy(info->fb_info.fontname, fontname); 1983 info->fb_info.changevar = NULL; 1984 info->fb_info.switch_con = &atyfbcon_switch; 1985 info->fb_info.updatevar = &atyfbcon_updatevar; 1986 info->fb_info.blank = &atyfbcon_blank; 1987 info->fb_info.flags = FBINFO_FLAG_DEFAULT; 1988 1989#ifdef CONFIG_PMAC_BACKLIGHT 1990 if (M64_HAS(G3_PB_1_1) && machine_is_compatible("PowerBook1,1")) { 1991 /* these bits let the 101 powerbook wake up from sleep -- paulus */ 1992 aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, info) 1993 | (USE_F32KHZ | TRISTATE_MEM_EN), info); 1994 } 1995 if (M64_HAS(MOBIL_BUS)) 1996 register_backlight_controller(&aty_backlight_controller, info, "ati"); 1997#endif /* CONFIG_PMAC_BACKLIGHT */ 1998 1999#ifdef MODULE 2000 var = default_var; 2001#else /* !MODULE */ 2002 memset(&var, 0, sizeof(var)); 2003#ifdef CONFIG_PPC 2004 if (_machine == _MACH_Pmac) { 2005 if (mode_option) { 2006 if (!mac_find_mode(&var, &info->fb_info, mode_option, 8)) 2007 var = default_var; 2008 } else { 2009 if (default_vmode == VMODE_CHOOSE) { 2010 if (M64_HAS(G3_PB_1024x768)) 2011 /* G3 PowerBook with 1024x768 LCD */ 2012 default_vmode = VMODE_1024_768_60; 2013 else if (machine_is_compatible("iMac")) 2014 default_vmode = VMODE_1024_768_75; 2015 else if (machine_is_compatible("PowerBook2,1")) 2016 /* iBook with 800x600 LCD */ 2017 default_vmode = VMODE_800_600_60; 2018 else 2019 default_vmode = VMODE_640_480_67; 2020 sense = read_aty_sense(info); 2021 printk(KERN_INFO "atyfb: monitor sense=%x, mode %d\n", 2022 sense, mac_map_monitor_sense(sense)); 2023 } 2024 if (default_vmode <= 0 || default_vmode > VMODE_MAX) 2025 default_vmode = VMODE_640_480_60; 2026#ifdef CONFIG_NVRAM 2027 if (default_cmode == CMODE_NVRAM) 2028 default_cmode = nvram_read_byte(NV_CMODE); 2029#endif 2030 if (default_cmode < CMODE_8 || default_cmode > CMODE_32) 2031 default_cmode = CMODE_8; 2032 if (mac_vmode_to_var(default_vmode, default_cmode, &var)) 2033 var = default_var; 2034 } 2035 } 2036 else if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8)) 2037 var = default_var; 2038#else /* !CONFIG_PPC */ 2039#ifdef __sparc__ 2040 if (mode_option) { 2041 if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8)) 2042 var = default_var; 2043 } else 2044 var = default_var; 2045#else 2046 if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8)) 2047 var = default_var; 2048#endif /* !__sparc__ */ 2049#endif /* !CONFIG_PPC */ 2050#endif /* !MODULE */ 2051 if (noaccel) 2052 var.accel_flags &= ~FB_ACCELF_TEXT; 2053 else 2054 var.accel_flags |= FB_ACCELF_TEXT; 2055 2056 if (var.yres == var.yres_virtual) { 2057 u32 vram = (info->total_vram - (PAGE_SIZE << 2)); 2058 var.yres_virtual = ((vram * 8) / var.bits_per_pixel) / var.xres_virtual; 2059 if (var.yres_virtual < var.yres) 2060 var.yres_virtual = var.yres; 2061 } 2062 2063 if (atyfb_decode_var(&var, &info->default_par, info)) { 2064 printk("atyfb: can't set default video mode\n"); 2065 return 0; 2066 } 2067 2068#ifdef __sparc__ 2069 atyfb_save_palette(&info->fb_info, 0); 2070#endif 2071 for (j = 0; j < 16; j++) { 2072 k = color_table[j]; 2073 info->palette[j].red = default_red[k]; 2074 info->palette[j].green = default_grn[k]; 2075 info->palette[j].blue = default_blu[k]; 2076 } 2077 2078#ifdef CONFIG_FB_ATY_CT 2079 if (curblink && M64_HAS(INTEGRATED)) { 2080 info->cursor = aty_init_cursor(info); 2081 if (info->cursor) { 2082 info->dispsw.cursor = atyfb_cursor; 2083 info->dispsw.set_font = atyfb_set_font; 2084 } 2085 } 2086#endif /* CONFIG_FB_ATY_CT */ 2087 2088 atyfb_set_var(&var, -1, &info->fb_info); 2089 2090 if (register_framebuffer(&info->fb_info) < 0) 2091 return 0; 2092 2093 info->next = fb_list; 2094 fb_list = info; 2095 2096 printk("fb%d: %s frame buffer device on %s\n", 2097 GET_FB_IDX(info->fb_info.node), atyfb_name, name); 2098 return 1; 2099} 2100 2101int __init atyfb_init(void) 2102{ 2103#if defined(CONFIG_PCI) 2104 struct pci_dev *pdev = NULL; 2105 struct fb_info_aty *info; 2106 unsigned long addr, res_start, res_size; 2107 int i; 2108#ifdef __sparc__ 2109 extern void (*prom_palette) (int); 2110 extern int con_is_present(void); 2111 struct pcidev_cookie *pcp; 2112 char prop[128]; 2113 int node, len, j; 2114 u32 mem, chip_id; 2115 2116 /* Do not attach when we have a serial console. */ 2117 if (!con_is_present()) 2118 return -ENXIO; 2119#else 2120 u16 tmp; 2121 int aux_app; 2122 unsigned long raddr; 2123#endif 2124 2125 while ((pdev = pci_find_device(PCI_VENDOR_ID_ATI, PCI_ANY_ID, pdev))) { 2126 if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { 2127 struct resource *rp; 2128#ifndef __sparc__ 2129 struct resource *rrp; 2130#endif 2131 2132 for (i = sizeof(aty_chips)/sizeof(*aty_chips)-1; i >= 0; i--) 2133 if (pdev->device == aty_chips[i].pci_id) 2134 break; 2135 if (i < 0) 2136 continue; 2137 2138 info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC); 2139 if (!info) { 2140 printk("atyfb_init: can't alloc fb_info_aty\n"); 2141 return -ENXIO; 2142 } 2143 memset(info, 0, sizeof(struct fb_info_aty)); 2144 2145 rp = &pdev->resource[0]; 2146 if (rp->flags & IORESOURCE_IO) 2147 rp = &pdev->resource[1]; 2148 addr = rp->start; 2149 if (!addr) 2150 continue; 2151 2152 res_start = rp->start; 2153 res_size = rp->end-rp->start+1; 2154 if (!request_mem_region(res_start, res_size, "atyfb")) 2155 continue; 2156 2157#ifdef __sparc__ 2158 /* 2159 * Map memory-mapped registers. 2160 */ 2161 info->ati_regbase = addr + 0x7ffc00UL; 2162 info->ati_regbase_phys = addr + 0x7ffc00UL; 2163 2164 /* 2165 * Map in big-endian aperture. 2166 */ 2167 info->frame_buffer = (unsigned long) addr + 0x800000UL; 2168 info->frame_buffer_phys = addr + 0x800000UL; 2169 2170 /* 2171 * Figure mmap addresses from PCI config space. 2172 * Split Framebuffer in big- and little-endian halfs. 2173 */ 2174 for (i = 0; i < 6 && pdev->resource[i].start; i++) 2175 /* nothing */; 2176 j = i + 4; 2177 2178 info->mmap_map = kmalloc(j * sizeof(*info->mmap_map), GFP_ATOMIC); 2179 if (!info->mmap_map) { 2180 printk("atyfb_init: can't alloc mmap_map\n"); 2181 kfree(info); 2182 release_mem_region(res_start, res_size); 2183 return -ENXIO; 2184 } 2185 memset(info->mmap_map, 0, j * sizeof(*info->mmap_map)); 2186 2187 for (i = 0, j = 2; i < 6 && pdev->resource[i].start; i++) { 2188 struct resource *rp = &pdev->resource[i]; 2189 int io, breg = PCI_BASE_ADDRESS_0 + (i << 2); 2190 unsigned long base; 2191 u32 size, pbase; 2192 2193 base = rp->start; 2194 2195 io = (rp->flags & IORESOURCE_IO); 2196 2197 size = rp->end - base + 1; 2198 2199 pci_read_config_dword(pdev, breg, &pbase); 2200 2201 if (io) 2202 size &= ~1; 2203 2204 /* 2205 * Map the framebuffer a second time, this time without 2206 * the braindead _PAGE_IE setting. This is used by the 2207 * fixed Xserver, but we need to maintain the old mapping 2208 * to stay compatible with older ones... 2209 */ 2210 if (base == addr) { 2211 info->mmap_map[j].voff = (pbase + 0x10000000) & PAGE_MASK; 2212 info->mmap_map[j].poff = base & PAGE_MASK; 2213 info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK; 2214 info->mmap_map[j].prot_mask = _PAGE_CACHE; 2215 info->mmap_map[j].prot_flag = _PAGE_E; 2216 j++; 2217 } 2218 2219 /* 2220 * Here comes the old framebuffer mapping with _PAGE_IE 2221 * set for the big endian half of the framebuffer... 2222 */ 2223 if (base == addr) { 2224 info->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK; 2225 info->mmap_map[j].poff = (base+0x800000) & PAGE_MASK; 2226 info->mmap_map[j].size = 0x800000; 2227 info->mmap_map[j].prot_mask = _PAGE_CACHE; 2228 info->mmap_map[j].prot_flag = _PAGE_E|_PAGE_IE; 2229 size -= 0x800000; 2230 j++; 2231 } 2232 2233 info->mmap_map[j].voff = pbase & PAGE_MASK; 2234 info->mmap_map[j].poff = base & PAGE_MASK; 2235 info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK; 2236 info->mmap_map[j].prot_mask = _PAGE_CACHE; 2237 info->mmap_map[j].prot_flag = _PAGE_E; 2238 j++; 2239 } 2240 2241 if (pdev->device != XL_CHIP_ID) { 2242 /* 2243 * Fix PROMs idea of MEM_CNTL settings... 2244 */ 2245 mem = aty_ld_le32(MEM_CNTL, info); 2246 chip_id = aty_ld_le32(CONFIG_CHIP_ID, info); 2247 if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) && 2248 !((chip_id >> 24) & 1)) { 2249 switch (mem & 0x0f) { 2250 case 3: 2251 mem = (mem & ~(0x0f)) | 2; 2252 break; 2253 case 7: 2254 mem = (mem & ~(0x0f)) | 3; 2255 break; 2256 case 9: 2257 mem = (mem & ~(0x0f)) | 4; 2258 break; 2259 case 11: 2260 mem = (mem & ~(0x0f)) | 5; 2261 break; 2262 default: 2263 break; 2264 } 2265 if ((aty_ld_le32(CONFIG_STAT0, info) & 7) >= SDRAM) 2266 mem &= ~(0x00700000); 2267 } 2268 mem &= ~(0xcf80e000); /* Turn off all undocumented bits. */ 2269 aty_st_le32(MEM_CNTL, mem, info); 2270 } 2271 2272 /* 2273 * If this is the console device, we will set default video 2274 * settings to what the PROM left us with. 2275 */ 2276 node = prom_getchild(prom_root_node); 2277 node = prom_searchsiblings(node, "aliases"); 2278 if (node) { 2279 len = prom_getproperty(node, "screen", prop, sizeof(prop)); 2280 if (len > 0) { 2281 prop[len] = '\0'; 2282 node = prom_finddevice(prop); 2283 } else { 2284 node = 0; 2285 } 2286 } 2287 2288 pcp = pdev->sysdata; 2289 if (node == pcp->prom_node) { 2290 2291 struct fb_var_screeninfo *var = &default_var; 2292 unsigned int N, P, Q, M, T, R; 2293 u32 v_total, h_total; 2294 struct crtc crtc; 2295 u8 pll_regs[16]; 2296 u8 clock_cntl; 2297 2298 crtc.vxres = prom_getintdefault(node, "width", 1024); 2299 crtc.vyres = prom_getintdefault(node, "height", 768); 2300 crtc.bpp = prom_getintdefault(node, "depth", 8); 2301 crtc.xoffset = crtc.yoffset = 0; 2302 crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, info); 2303 crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, info); 2304 crtc.v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, info); 2305 crtc.v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, info); 2306 crtc.gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, info); 2307 aty_crtc_to_var(&crtc, var); 2308 2309 h_total = var->xres + var->right_margin + 2310 var->hsync_len + var->left_margin; 2311 v_total = var->yres + var->lower_margin + 2312 var->vsync_len + var->upper_margin; 2313 2314 /* 2315 * Read the PLL to figure actual Refresh Rate. 2316 */ 2317 clock_cntl = aty_ld_8(CLOCK_CNTL, info); 2318 /* printk("atyfb: CLOCK_CNTL: %02x\n", clock_cntl); */ 2319 for (i = 0; i < 16; i++) 2320 pll_regs[i] = aty_ld_pll(i, info); 2321 2322 /* 2323 * PLL Reference Divider M: 2324 */ 2325 M = pll_regs[2]; 2326 2327 /* 2328 * PLL Feedback Divider N (Dependant on CLOCK_CNTL): 2329 */ 2330 N = pll_regs[7 + (clock_cntl & 3)]; 2331 2332 /* 2333 * PLL Post Divider P (Dependant on CLOCK_CNTL): 2334 */ 2335 P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1)); 2336 2337 /* 2338 * PLL Divider Q: 2339 */ 2340 Q = N / P; 2341 2342 /* 2343 * Target Frequency: 2344 * 2345 * T * M 2346 * Q = ------- 2347 * 2 * R 2348 * 2349 * where R is XTALIN (= 14318 or 29498 kHz). 2350 */ 2351 if (pdev->device == XL_CHIP_ID) 2352 R = 29498; 2353 else 2354 R = 14318; 2355 2356 T = 2 * Q * R / M; 2357 2358 default_var.pixclock = 1000000000 / T; 2359 } 2360#else /* __sparc__ */ 2361 2362 aux_app = 0; 2363 raddr = addr + 0x7ff000UL; 2364 rrp = &pdev->resource[2]; 2365 if ((rrp->flags & IORESOURCE_MEM) 2366 && request_mem_region(rrp->start, rrp->end - rrp->start + 1, 2367 "atyfb")) { 2368 aux_app = 1; 2369 raddr = rrp->start; 2370 printk(KERN_INFO "atyfb: using auxiliary register aperture\n"); 2371 } 2372 2373 info->ati_regbase_phys = raddr; 2374 info->ati_regbase = (unsigned long) ioremap(raddr, 0x1000); 2375 2376 if(!info->ati_regbase) { 2377 kfree(info); 2378 release_mem_region(res_start, res_size); 2379 return -ENOMEM; 2380 } 2381 2382 info->ati_regbase_phys += aux_app? 0x400: 0xc00; 2383 info->ati_regbase += aux_app? 0x400: 0xc00; 2384 2385 /* 2386 * Enable memory-space accesses using config-space 2387 * command register. 2388 */ 2389 pci_read_config_word(pdev, PCI_COMMAND, &tmp); 2390 if (!(tmp & PCI_COMMAND_MEMORY)) { 2391 tmp |= PCI_COMMAND_MEMORY; 2392 pci_write_config_word(pdev, PCI_COMMAND, tmp); 2393 } 2394 2395#ifdef __BIG_ENDIAN 2396 /* Use the big-endian aperture */ 2397 addr += 0x800000; 2398#endif 2399 2400 /* Map in frame buffer */ 2401 info->frame_buffer_phys = addr; 2402 info->frame_buffer = (unsigned long)ioremap(addr, 0x800000); 2403 2404 if(!info->frame_buffer) { 2405 kfree(info); 2406 release_mem_region(res_start, res_size); 2407 return -ENXIO; 2408 } 2409 2410#endif /* __sparc__ */ 2411 2412 if (!aty_init(info, "PCI")) { 2413 if (info->mmap_map) 2414 kfree(info->mmap_map); 2415 kfree(info); 2416 release_mem_region(res_start, res_size); 2417 return -ENXIO; 2418 } 2419 2420#ifdef __sparc__ 2421 if (!prom_palette) 2422 prom_palette = atyfb_palette; 2423 2424 /* 2425 * Add /dev/fb mmap values. 2426 */ 2427 info->mmap_map[0].voff = 0x8000000000000000UL; 2428 info->mmap_map[0].poff = info->frame_buffer & PAGE_MASK; 2429 info->mmap_map[0].size = info->total_vram; 2430 info->mmap_map[0].prot_mask = _PAGE_CACHE; 2431 info->mmap_map[0].prot_flag = _PAGE_E; 2432 info->mmap_map[1].voff = info->mmap_map[0].voff + info->total_vram; 2433 info->mmap_map[1].poff = info->ati_regbase & PAGE_MASK; 2434 info->mmap_map[1].size = PAGE_SIZE; 2435 info->mmap_map[1].prot_mask = _PAGE_CACHE; 2436 info->mmap_map[1].prot_flag = _PAGE_E; 2437#endif /* __sparc__ */ 2438 2439#ifdef CONFIG_PMAC_PBOOK 2440 if (first_display == NULL) 2441 pmu_register_sleep_notifier(&aty_sleep_notifier); 2442 info->next = first_display; 2443 first_display = info; 2444#endif 2445 2446#ifdef CONFIG_FB_COMPAT_XPMAC 2447 if (!console_fb_info) 2448 console_fb_info = &info->fb_info; 2449#endif /* CONFIG_FB_COMPAT_XPMAC */ 2450 } 2451 } 2452 2453#elif defined(CONFIG_ATARI) 2454 u32 clock_r; 2455 int m64_num; 2456 struct fb_info_aty *info; 2457 2458 for (m64_num = 0; m64_num < mach64_count; m64_num++) { 2459 if (!phys_vmembase[m64_num] || !phys_size[m64_num] || 2460 !phys_guiregbase[m64_num]) { 2461 printk(" phys_*[%d] parameters not set => returning early. \n", 2462 m64_num); 2463 continue; 2464 } 2465 2466 info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC); 2467 if (!info) { 2468 printk("atyfb_init: can't alloc fb_info_aty\n"); 2469 return -ENOMEM; 2470 } 2471 memset(info, 0, sizeof(struct fb_info_aty)); 2472 2473 /* 2474 * Map the video memory (physical address given) to somewhere in the 2475 * kernel address space. 2476 */ 2477 info->frame_buffer = (unsigned long)ioremap(phys_vmembase[m64_num], 2478 phys_size[m64_num]); 2479 info->frame_buffer_phys = info->frame_buffer; /* Fake! */ 2480 info->ati_regbase = (unsigned long)ioremap(phys_guiregbase[m64_num], 2481 0x10000)+0xFC00ul; 2482 info->ati_regbase_phys = info->ati_regbase; /* Fake! */ 2483 2484 aty_st_le32(CLOCK_CNTL, 0x12345678, info); 2485 clock_r = aty_ld_le32(CLOCK_CNTL, info); 2486 2487 switch (clock_r & 0x003F) { 2488 case 0x12: 2489 info->clk_wr_offset = 3; /* */ 2490 break; 2491 case 0x34: 2492 info->clk_wr_offset = 2; /* Medusa ST-IO ISA Adapter etc. */ 2493 break; 2494 case 0x16: 2495 info->clk_wr_offset = 1; /* */ 2496 break; 2497 case 0x38: 2498 info->clk_wr_offset = 0; /* Panther 1 ISA Adapter (Gerald) */ 2499 break; 2500 } 2501 2502 if (!aty_init(info, "ISA bus")) { 2503 kfree(info); 2504 /* This is insufficient! kernel_map has added two large chunks!! */ 2505 return -ENXIO; 2506 } 2507 } 2508#endif /* CONFIG_ATARI */ 2509 return 0; 2510} 2511 2512#ifndef MODULE 2513int __init atyfb_setup(char *options) 2514{ 2515 char *this_opt; 2516 2517 if (!options || !*options) 2518 return 0; 2519 2520 while ((this_opt = strsep(&options, ",")) != NULL) { 2521 if (!strncmp(this_opt, "font:", 5)) { 2522 char *p; 2523 int i; 2524 2525 p = this_opt + 5; 2526 for (i = 0; i < sizeof(fontname) - 1; i++) 2527 if (!*p || *p == ' ' || *p == ',') 2528 break; 2529 memcpy(fontname, this_opt + 5, i); 2530 fontname[i] = 0; 2531 } else if (!strncmp(this_opt, "noblink", 7)) { 2532 curblink = 0; 2533 } else if (!strncmp(this_opt, "noaccel", 7)) { 2534 noaccel = 1; 2535 } else if (!strncmp(this_opt, "vram:", 5)) 2536 default_vram = simple_strtoul(this_opt+5, NULL, 0); 2537 else if (!strncmp(this_opt, "pll:", 4)) 2538 default_pll = simple_strtoul(this_opt+4, NULL, 0); 2539 else if (!strncmp(this_opt, "mclk:", 5)) 2540 default_mclk = simple_strtoul(this_opt+5, NULL, 0); 2541#ifdef CONFIG_PPC 2542 else if (!strncmp(this_opt, "vmode:", 6)) { 2543 unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0); 2544 if (vmode > 0 && vmode <= VMODE_MAX) 2545 default_vmode = vmode; 2546 } else if (!strncmp(this_opt, "cmode:", 6)) { 2547 unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0); 2548 switch (cmode) { 2549 case 0: 2550 case 8: 2551 default_cmode = CMODE_8; 2552 break; 2553 case 15: 2554 case 16: 2555 default_cmode = CMODE_16; 2556 break; 2557 case 24: 2558 case 32: 2559 default_cmode = CMODE_32; 2560 break; 2561 } 2562 } 2563#endif 2564#ifdef CONFIG_ATARI 2565 /* 2566 * Why do we need this silly Mach64 argument? 2567 * We are already here because of mach64= so its redundant. 2568 */ 2569 else if (MACH_IS_ATARI && (!strncmp(this_opt, "Mach64:", 7))) { 2570 static unsigned char m64_num; 2571 static char mach64_str[80]; 2572 strncpy(mach64_str, this_opt+7, 80); 2573 if (!store_video_par(mach64_str, m64_num)) { 2574 m64_num++; 2575 mach64_count = m64_num; 2576 } 2577 } 2578#endif 2579 else 2580 mode_option = this_opt; 2581 } 2582 return 0; 2583} 2584#endif /* !MODULE */ 2585 2586#ifdef CONFIG_ATARI 2587static int __init store_video_par(char *video_str, unsigned char m64_num) 2588{ 2589 char *p; 2590 unsigned long vmembase, size, guiregbase; 2591 2592 printk("store_video_par() '%s' \n", video_str); 2593 2594 if (!(p = strtoke(video_str, ";")) || !*p) 2595 goto mach64_invalid; 2596 vmembase = simple_strtoul(p, NULL, 0); 2597 if (!(p = strtoke(NULL, ";")) || !*p) 2598 goto mach64_invalid; 2599 size = simple_strtoul(p, NULL, 0); 2600 if (!(p = strtoke(NULL, ";")) || !*p) 2601 goto mach64_invalid; 2602 guiregbase = simple_strtoul(p, NULL, 0); 2603 2604 phys_vmembase[m64_num] = vmembase; 2605 phys_size[m64_num] = size; 2606 phys_guiregbase[m64_num] = guiregbase; 2607 printk(" stored them all: $%08lX $%08lX $%08lX \n", vmembase, size, 2608 guiregbase); 2609 return 0; 2610 2611mach64_invalid: 2612 phys_vmembase[m64_num] = 0; 2613 return -1; 2614} 2615 2616static char __init *strtoke(char *s, const char *ct) 2617{ 2618 static char *ssave = NULL; 2619 char *sbegin, *send; 2620 2621 sbegin = s ? s : ssave; 2622 if (!sbegin) 2623 return NULL; 2624 if (*sbegin == '\0') { 2625 ssave = NULL; 2626 return NULL; 2627 } 2628 send = strpbrk(sbegin, ct); 2629 if (send && *send != '\0') 2630 *send++ = '\0'; 2631 ssave = send; 2632 return sbegin; 2633} 2634#endif /* CONFIG_ATARI */ 2635 2636static int atyfbcon_switch(int con, struct fb_info *fb) 2637{ 2638 struct fb_info_aty *info = (struct fb_info_aty *)fb; 2639 struct atyfb_par par; 2640 2641 /* Do we have to save the colormap? */ 2642 if (fb_display[currcon].cmap.len) 2643 fb_get_cmap(&fb_display[currcon].cmap, 1, atyfb_getcolreg, fb); 2644 2645#ifdef CONFIG_FB_ATY_CT 2646 /* Erase HW Cursor */ 2647 if (info->cursor) 2648 atyfb_cursor(&fb_display[currcon], CM_ERASE, 2649 info->cursor->pos.x, info->cursor->pos.y); 2650#endif /* CONFIG_FB_ATY_CT */ 2651 2652 currcon = con; 2653 2654 atyfb_decode_var(&fb_display[con].var, &par, info); 2655 atyfb_set_par(&par, info); 2656 atyfb_set_dispsw(&fb_display[con], info, par.crtc.bpp, 2657 par.accel_flags & FB_ACCELF_TEXT); 2658 2659 /* Install new colormap */ 2660 do_install_cmap(con, fb); 2661 2662#ifdef CONFIG_FB_ATY_CT 2663 /* Install hw cursor */ 2664 if (info->cursor) { 2665 aty_set_cursor_color(info); 2666 aty_set_cursor_shape(info); 2667 } 2668#endif /* CONFIG_FB_ATY_CT */ 2669 return 1; 2670} 2671 2672 /* 2673 * Blank the display. 2674 */ 2675 2676static void atyfbcon_blank(int blank, struct fb_info *fb) 2677{ 2678 struct fb_info_aty *info = (struct fb_info_aty *)fb; 2679 u8 gen_cntl; 2680 2681#ifdef CONFIG_PMAC_BACKLIGHT 2682 if ((_machine == _MACH_Pmac) && blank) 2683 set_backlight_enable(0); 2684#endif /* CONFIG_PMAC_BACKLIGHT */ 2685 2686 gen_cntl = aty_ld_8(CRTC_GEN_CNTL, info); 2687 if (blank > 0) 2688 switch (blank-1) { 2689 case VESA_NO_BLANKING: 2690 gen_cntl |= 0x40; 2691 break; 2692 case VESA_VSYNC_SUSPEND: 2693 gen_cntl |= 0x8; 2694 break; 2695 case VESA_HSYNC_SUSPEND: 2696 gen_cntl |= 0x4; 2697 break; 2698 case VESA_POWERDOWN: 2699 gen_cntl |= 0x4c; 2700 break; 2701 } 2702 else 2703 gen_cntl &= ~(0x4c); 2704 aty_st_8(CRTC_GEN_CNTL, gen_cntl, info); 2705 2706#ifdef CONFIG_PMAC_BACKLIGHT 2707 if ((_machine == _MACH_Pmac) && !blank) 2708 set_backlight_enable(1); 2709#endif /* CONFIG_PMAC_BACKLIGHT */ 2710} 2711 2712 2713 /* 2714 * Read a single color register and split it into 2715 * colors/transparent. Return != 0 for invalid regno. 2716 */ 2717 2718static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, 2719 u_int *transp, struct fb_info *fb) 2720{ 2721 struct fb_info_aty *info = (struct fb_info_aty *)fb; 2722 2723 if (regno > 255) 2724 return 1; 2725 *red = (info->palette[regno].red<<8) | info->palette[regno].red; 2726 *green = (info->palette[regno].green<<8) | info->palette[regno].green; 2727 *blue = (info->palette[regno].blue<<8) | info->palette[regno].blue; 2728 *transp = 0; 2729 return 0; 2730} 2731 2732 2733 /* 2734 * Set a single color register. The values supplied are already 2735 * rounded down to the hardware's capabilities (according to the 2736 * entries in the var structure). Return != 0 for invalid regno. 2737 */ 2738 2739static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 2740 u_int transp, struct fb_info *fb) 2741{ 2742 struct fb_info_aty *info = (struct fb_info_aty *)fb; 2743 int i, scale; 2744 2745 if (regno > 255) 2746 return 1; 2747 red >>= 8; 2748 green >>= 8; 2749 blue >>= 8; 2750 info->palette[regno].red = red; 2751 info->palette[regno].green = green; 2752 info->palette[regno].blue = blue; 2753 i = aty_ld_8(DAC_CNTL, info) & 0xfc; 2754 if (M64_HAS(EXTRA_BRIGHT)) 2755 i |= 0x2; /*DAC_CNTL|0x2 turns off the extra brightness for gt*/ 2756 aty_st_8(DAC_CNTL, i, info); 2757 aty_st_8(DAC_MASK, 0xff, info); 2758 scale = (M64_HAS(INTEGRATED) && info->current_par.crtc.bpp == 16) ? 3 : 0; 2759#ifdef CONFIG_ATARI 2760 out_8(&info->aty_cmap_regs->windex, regno << scale); 2761 out_8(&info->aty_cmap_regs->lut, red); 2762 out_8(&info->aty_cmap_regs->lut, green); 2763 out_8(&info->aty_cmap_regs->lut, blue); 2764#else 2765 writeb(regno << scale, &info->aty_cmap_regs->windex); 2766 writeb(red, &info->aty_cmap_regs->lut); 2767 writeb(green, &info->aty_cmap_regs->lut); 2768 writeb(blue, &info->aty_cmap_regs->lut); 2769#endif 2770 if (regno < 16) 2771 switch (info->current_par.crtc.bpp) { 2772#ifdef FBCON_HAS_CFB16 2773 case 16: 2774 info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) | 2775 regno; 2776 break; 2777#endif 2778#ifdef FBCON_HAS_CFB24 2779 case 24: 2780 info->fbcon_cmap.cfb24[regno] = (regno << 16) | (regno << 8) | 2781 regno; 2782 break; 2783#endif 2784#ifdef FBCON_HAS_CFB32 2785 case 32: 2786 i = (regno << 8) | regno; 2787 info->fbcon_cmap.cfb32[regno] = (i << 16) | i; 2788 break; 2789#endif 2790 } 2791 return 0; 2792} 2793 2794 2795static void do_install_cmap(int con, struct fb_info *info) 2796{ 2797 if (con != currcon) 2798 return; 2799 if (fb_display[con].cmap.len) 2800 fb_set_cmap(&fb_display[con].cmap, 1, atyfb_setcolreg, info); 2801 else { 2802 int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256; 2803 fb_set_cmap(fb_default_cmap(size), 1, atyfb_setcolreg, info); 2804 } 2805} 2806 2807 2808 /* 2809 * Update the `var' structure (called by fbcon.c) 2810 */ 2811 2812static int atyfbcon_updatevar(int con, struct fb_info *fb) 2813{ 2814 struct fb_info_aty *info = (struct fb_info_aty *)fb; 2815 struct atyfb_par *par = &info->current_par; 2816 struct display *p = &fb_display[con]; 2817 struct vc_data *conp = p->conp; 2818 u32 yres, yoffset, sy, height; 2819 2820 yres = ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1; 2821 yoffset = fb_display[con].var.yoffset; 2822 2823 sy = (conp->vc_rows + p->yscroll) * fontheight(p); 2824 height = yres - conp->vc_rows * fontheight(p); 2825 2826 if (height && (yoffset + yres > sy)) { 2827 u32 xres, xoffset; 2828 u32 bgx; 2829 2830 xres = (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8; 2831 xoffset = fb_display[con].var.xoffset; 2832 2833 2834 bgx = attr_bgcol_ec(p, conp); 2835 bgx |= (bgx << 8); 2836 bgx |= (bgx << 16); 2837 2838 if (sy + height > par->crtc.vyres) { 2839 wait_for_fifo(1, info); 2840 aty_st_le32(SC_BOTTOM, sy + height - 1, info); 2841 } 2842 aty_rectfill(xoffset, sy, xres, height, bgx, info); 2843 } 2844 2845#ifdef CONFIG_FB_ATY_CT 2846 if (info->cursor && (yoffset + yres <= sy)) 2847 atyfb_cursor(p, CM_ERASE, info->cursor->pos.x, info->cursor->pos.y); 2848#endif /* CONFIG_FB_ATY_CT */ 2849 2850 info->current_par.crtc.yoffset = yoffset; 2851 set_off_pitch(&info->current_par, info); 2852 return 0; 2853} 2854 2855 2856 2857#ifdef MODULE 2858int __init init_module(void) 2859{ 2860 atyfb_init(); 2861 return fb_list ? 0 : -ENXIO; 2862} 2863 2864void cleanup_module(void) 2865{ 2866 while (fb_list) { 2867 struct fb_info_aty *info = fb_list; 2868 fb_list = info->next; 2869 2870 unregister_framebuffer(&info->fb_info); 2871 2872#ifndef __sparc__ 2873 if (info->ati_regbase) 2874 iounmap((void *)info->ati_regbase); 2875 if (info->frame_buffer) 2876 iounmap((void *)info->frame_buffer); 2877#ifdef __BIG_ENDIAN 2878 if (info->cursor && info->cursor->ram) 2879 iounmap(info->cursor->ram); 2880#endif 2881#endif 2882 2883 if (info->cursor) { 2884 if (info->cursor->timer) 2885 kfree(info->cursor->timer); 2886 kfree(info->cursor); 2887 } 2888#ifdef __sparc__ 2889 if (info->mmap_map) 2890 kfree(info->mmap_map); 2891#endif 2892 kfree(info); 2893 } 2894} 2895 2896#endif 2897MODULE_LICENSE("GPL"); 2898