blob: 4c46706188fe1a22a64a106ffe48577a22e2a5a5 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * ATI Frame Buffer Device Driver Core
3 *
4 * Copyright (C) 2004 Alex Kern <alex.kern@gmx.de>
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 * Generic LCD support written by Daniel Mantione, ported from 2.4.20 by Alex Kern
29 * Many Thanks to Ville Syrjälä for patches and fixing nasting 16 bit color bug.
30 *
31 * This file is subject to the terms and conditions of the GNU General Public
32 * License. See the file COPYING in the main directory of this archive for
33 * more details.
34 *
35 * Many thanks to Nitya from ATI devrel for support and patience !
36 */
37
38/******************************************************************************
39
40 TODO:
41
42 - cursor support on all cards and all ramdacs.
43 - cursor parameters controlable via ioctl()s.
44 - guess PLL and MCLK based on the original PLL register values initialized
45 by Open Firmware (if they are initialized). BIOS is done
46
47 (Anyone with Mac to help with this?)
48
49******************************************************************************/
50
51
52#include <linux/config.h>
53#include <linux/module.h>
54#include <linux/moduleparam.h>
55#include <linux/kernel.h>
56#include <linux/errno.h>
57#include <linux/string.h>
58#include <linux/mm.h>
59#include <linux/slab.h>
60#include <linux/vmalloc.h>
61#include <linux/delay.h>
62#include <linux/console.h>
63#include <linux/fb.h>
64#include <linux/init.h>
65#include <linux/pci.h>
66#include <linux/interrupt.h>
67#include <linux/spinlock.h>
68#include <linux/wait.h>
69
70#include <asm/io.h>
71#include <asm/uaccess.h>
72
73#include <video/mach64.h>
74#include "atyfb.h"
75#include "ati_ids.h"
76
77#ifdef __powerpc__
78#include <asm/prom.h>
79#include "../macmodes.h"
80#endif
81#ifdef __sparc__
82#include <asm/pbm.h>
83#include <asm/fbio.h>
84#endif
85
86#ifdef CONFIG_ADB_PMU
87#include <linux/adb.h>
88#include <linux/pmu.h>
89#endif
90#ifdef CONFIG_BOOTX_TEXT
91#include <asm/btext.h>
92#endif
93#ifdef CONFIG_PMAC_BACKLIGHT
94#include <asm/backlight.h>
95#endif
96#ifdef CONFIG_MTRR
97#include <asm/mtrr.h>
98#endif
99
100/*
101 * Debug flags.
102 */
103#undef DEBUG
104/*#define DEBUG*/
105
106/* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */
107/* - must be large enough to catch all GUI-Regs */
108/* - must be aligned to a PAGE boundary */
109#define GUI_RESERVE (1 * PAGE_SIZE)
110
111/* FIXME: remove the FAIL definition */
Ville Syrjälä866d84c2006-01-09 20:53:22 -0800112#define FAIL(msg) do { \
113 if (!(var->activate & FB_ACTIVATE_TEST)) \
114 printk(KERN_CRIT "atyfb: " msg "\n"); \
115 return -EINVAL; \
116} while (0)
117#define FAIL_MAX(msg, x, _max_) do { \
118 if (x > _max_) { \
119 if (!(var->activate & FB_ACTIVATE_TEST)) \
120 printk(KERN_CRIT "atyfb: " msg " %x(%x)\n", x, _max_); \
121 return -EINVAL; \
122 } \
123} while (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124#ifdef DEBUG
125#define DPRINTK(fmt, args...) printk(KERN_DEBUG "atyfb: " fmt, ## args)
126#else
127#define DPRINTK(fmt, args...)
128#endif
129
130#define PRINTKI(fmt, args...) printk(KERN_INFO "atyfb: " fmt, ## args)
131#define PRINTKE(fmt, args...) printk(KERN_ERR "atyfb: " fmt, ## args)
132
133#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD)
134static const u32 lt_lcd_regs[] = {
135 CONFIG_PANEL_LG,
136 LCD_GEN_CNTL_LG,
137 DSTN_CONTROL_LG,
138 HFB_PITCH_ADDR_LG,
139 HORZ_STRETCHING_LG,
140 VERT_STRETCHING_LG,
141 0, /* EXT_VERT_STRETCH */
142 LT_GIO_LG,
143 POWER_MANAGEMENT_LG
144};
145
146void aty_st_lcd(int index, u32 val, const struct atyfb_par *par)
147{
148 if (M64_HAS(LT_LCD_REGS)) {
149 aty_st_le32(lt_lcd_regs[index], val, par);
150 } else {
151 unsigned long temp;
152
153 /* write addr byte */
154 temp = aty_ld_le32(LCD_INDEX, par);
155 aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par);
156 /* write the register value */
157 aty_st_le32(LCD_DATA, val, par);
158 }
159}
160
161u32 aty_ld_lcd(int index, const struct atyfb_par *par)
162{
163 if (M64_HAS(LT_LCD_REGS)) {
164 return aty_ld_le32(lt_lcd_regs[index], par);
165 } else {
166 unsigned long temp;
167
168 /* write addr byte */
169 temp = aty_ld_le32(LCD_INDEX, par);
170 aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par);
171 /* read the register value */
172 return aty_ld_le32(LCD_DATA, par);
173 }
174}
175#endif /* defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD) */
176
177#ifdef CONFIG_FB_ATY_GENERIC_LCD
178/*
179 * ATIReduceRatio --
180 *
181 * Reduce a fraction by factoring out the largest common divider of the
182 * fraction's numerator and denominator.
183 */
184static void ATIReduceRatio(int *Numerator, int *Denominator)
185{
186 int Multiplier, Divider, Remainder;
187
188 Multiplier = *Numerator;
189 Divider = *Denominator;
190
191 while ((Remainder = Multiplier % Divider))
192 {
193 Multiplier = Divider;
194 Divider = Remainder;
195 }
196
197 *Numerator /= Divider;
198 *Denominator /= Divider;
199}
200#endif
201 /*
202 * The Hardware parameters for each card
203 */
204
205struct aty_cmap_regs {
206 u8 windex;
207 u8 lut;
208 u8 mask;
209 u8 rindex;
210 u8 cntl;
211};
212
213struct pci_mmap_map {
214 unsigned long voff;
215 unsigned long poff;
216 unsigned long size;
217 unsigned long prot_flag;
218 unsigned long prot_mask;
219};
220
221static struct fb_fix_screeninfo atyfb_fix __devinitdata = {
222 .id = "ATY Mach64",
223 .type = FB_TYPE_PACKED_PIXELS,
224 .visual = FB_VISUAL_PSEUDOCOLOR,
225 .xpanstep = 8,
226 .ypanstep = 1,
227};
228
229 /*
230 * Frame buffer device API
231 */
232
233static int atyfb_open(struct fb_info *info, int user);
234static int atyfb_release(struct fb_info *info, int user);
235static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
236static int atyfb_set_par(struct fb_info *info);
237static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
238 u_int transp, struct fb_info *info);
239static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
240static int atyfb_blank(int blank, struct fb_info *info);
241static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
242 u_long arg, struct fb_info *info);
243extern void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
244extern void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
245extern void atyfb_imageblit(struct fb_info *info, const struct fb_image *image);
246#ifdef __sparc__
247static int atyfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma);
248#endif
249static int atyfb_sync(struct fb_info *info);
250
251 /*
252 * Internal routines
253 */
254
255static int aty_init(struct fb_info *info, const char *name);
256#ifdef CONFIG_ATARI
257static int store_video_par(char *videopar, unsigned char m64_num);
258#endif
259
260static struct crtc saved_crtc;
261static union aty_pll saved_pll;
262static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc);
263
264static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc);
265static int aty_var_to_crtc(const struct fb_info *info, const struct fb_var_screeninfo *var, struct crtc *crtc);
266static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *var);
267static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info);
268#ifdef CONFIG_PPC
269static int read_aty_sense(const struct atyfb_par *par);
270#endif
271
272
273 /*
274 * Interface used by the world
275 */
276
277static struct fb_var_screeninfo default_var = {
278 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
279 640, 480, 640, 480, 0, 0, 8, 0,
280 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
281 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
282 0, FB_VMODE_NONINTERLACED
283};
284
285static struct fb_videomode defmode = {
286 /* 640x480 @ 60 Hz, 31.5 kHz hsync */
287 NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
288 0, FB_VMODE_NONINTERLACED
289};
290
291static struct fb_ops atyfb_ops = {
292 .owner = THIS_MODULE,
293 .fb_open = atyfb_open,
294 .fb_release = atyfb_release,
295 .fb_check_var = atyfb_check_var,
296 .fb_set_par = atyfb_set_par,
297 .fb_setcolreg = atyfb_setcolreg,
298 .fb_pan_display = atyfb_pan_display,
299 .fb_blank = atyfb_blank,
300 .fb_ioctl = atyfb_ioctl,
301 .fb_fillrect = atyfb_fillrect,
302 .fb_copyarea = atyfb_copyarea,
303 .fb_imageblit = atyfb_imageblit,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304#ifdef __sparc__
305 .fb_mmap = atyfb_mmap,
306#endif
307 .fb_sync = atyfb_sync,
308};
309
310static int noaccel;
311#ifdef CONFIG_MTRR
312static int nomtrr;
313#endif
314static int vram;
315static int pll;
316static int mclk;
317static int xclk;
318static int comp_sync __initdata = -1;
319static char *mode;
320
321#ifdef CONFIG_PPC
322static int default_vmode __initdata = VMODE_CHOOSE;
323static int default_cmode __initdata = CMODE_CHOOSE;
324
325module_param_named(vmode, default_vmode, int, 0);
326MODULE_PARM_DESC(vmode, "int: video mode for mac");
327module_param_named(cmode, default_cmode, int, 0);
328MODULE_PARM_DESC(cmode, "int: color mode for mac");
329#endif
330
331#ifdef CONFIG_ATARI
332static unsigned int mach64_count __initdata = 0;
333static unsigned long phys_vmembase[FB_MAX] __initdata = { 0, };
334static unsigned long phys_size[FB_MAX] __initdata = { 0, };
335static unsigned long phys_guiregbase[FB_MAX] __initdata = { 0, };
336#endif
337
338/* top -> down is an evolution of mach64 chipset, any corrections? */
339#define ATI_CHIP_88800GX (M64F_GX)
340#define ATI_CHIP_88800CX (M64F_GX)
341
342#define ATI_CHIP_264CT (M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO)
343#define ATI_CHIP_264ET (M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO)
344
345#define ATI_CHIP_264VT (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO)
346#define ATI_CHIP_264GT (M64F_GT | M64F_INTEGRATED | M64F_MAGIC_FIFO | M64F_EXTRA_BRIGHT)
347
348#define ATI_CHIP_264VTB (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP)
349#define ATI_CHIP_264VT3 (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL)
350#define ATI_CHIP_264VT4 (M64F_VT | M64F_INTEGRATED | M64F_GTB_DSP)
351
352#define ATI_CHIP_264LT (M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP)
353
354/* make sets shorter */
355#define ATI_MODERN_SET (M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_EXTRA_BRIGHT)
356
357#define ATI_CHIP_264GTB (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL)
358/*#define ATI_CHIP_264GTDVD ?*/
359#define ATI_CHIP_264LTG (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL)
360
361#define ATI_CHIP_264GT2C (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE)
362#define ATI_CHIP_264GTPRO (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
363#define ATI_CHIP_264LTPRO (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
364
365#define ATI_CHIP_264XL (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4)
366#define ATI_CHIP_MOBILITY (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_MOBIL_BUS)
367
368static struct {
369 u16 pci_id;
370 const char *name;
371 int pll, mclk, xclk;
372 u32 features;
373} aty_chips[] __devinitdata = {
374#ifdef CONFIG_FB_ATY_GX
375 /* Mach64 GX */
376 { PCI_CHIP_MACH64GX, "ATI888GX00 (Mach64 GX)", 135, 50, 50, ATI_CHIP_88800GX },
377 { PCI_CHIP_MACH64CX, "ATI888CX00 (Mach64 CX)", 135, 50, 50, ATI_CHIP_88800CX },
378#endif /* CONFIG_FB_ATY_GX */
379
380#ifdef CONFIG_FB_ATY_CT
381 { PCI_CHIP_MACH64CT, "ATI264CT (Mach64 CT)", 135, 60, 60, ATI_CHIP_264CT },
382 { PCI_CHIP_MACH64ET, "ATI264ET (Mach64 ET)", 135, 60, 60, ATI_CHIP_264ET },
383 { PCI_CHIP_MACH64VT, "ATI264VT? (Mach64 VT)", 170, 67, 67, ATI_CHIP_264VT },
384 { PCI_CHIP_MACH64GT, "3D RAGE (Mach64 GT)", 135, 63, 63, ATI_CHIP_264GT },
385 /* FIXME { ...ATI_264GU, maybe ATI_CHIP_264GTDVD }, */
386 { PCI_CHIP_MACH64GU, "3D RAGE II+ (Mach64 GTB)", 200, 67, 67, ATI_CHIP_264GTB },
387 { PCI_CHIP_MACH64VU, "ATI264VTB (Mach64 VU)", 200, 67, 67, ATI_CHIP_264VT3 },
388
389 { PCI_CHIP_MACH64LT, "3D RAGE LT (Mach64 LT)", 135, 63, 63, ATI_CHIP_264LT },
390 /* FIXME chipset maybe ATI_CHIP_264LTPRO ? */
391 { PCI_CHIP_MACH64LG, "3D RAGE LT-G (Mach64 LG)", 230, 63, 63, ATI_CHIP_264LTG | M64F_LT_LCD_REGS | M64F_G3_PB_1024x768 },
392
393 { PCI_CHIP_MACH64VV, "ATI264VT4 (Mach64 VV)", 230, 83, 83, ATI_CHIP_264VT4 },
394
395 { PCI_CHIP_MACH64GV, "3D RAGE IIC (Mach64 GV, PCI)", 230, 83, 83, ATI_CHIP_264GT2C },
396 { PCI_CHIP_MACH64GW, "3D RAGE IIC (Mach64 GW, AGP)", 230, 83, 83, ATI_CHIP_264GT2C },
397 { PCI_CHIP_MACH64GY, "3D RAGE IIC (Mach64 GY, PCI)", 230, 83, 83, ATI_CHIP_264GT2C },
398 { PCI_CHIP_MACH64GZ, "3D RAGE IIC (Mach64 GZ, AGP)", 230, 83, 83, ATI_CHIP_264GT2C },
399
400 { PCI_CHIP_MACH64GB, "3D RAGE PRO (Mach64 GB, BGA, AGP)", 230, 100, 100, ATI_CHIP_264GTPRO },
401 { PCI_CHIP_MACH64GD, "3D RAGE PRO (Mach64 GD, BGA, AGP 1x)", 230, 100, 100, ATI_CHIP_264GTPRO },
402 { PCI_CHIP_MACH64GI, "3D RAGE PRO (Mach64 GI, BGA, PCI)", 230, 100, 100, ATI_CHIP_264GTPRO | M64F_MAGIC_VRAM_SIZE },
403 { PCI_CHIP_MACH64GP, "3D RAGE PRO (Mach64 GP, PQFP, PCI)", 230, 100, 100, ATI_CHIP_264GTPRO },
404 { PCI_CHIP_MACH64GQ, "3D RAGE PRO (Mach64 GQ, PQFP, PCI, limited 3D)", 230, 100, 100, ATI_CHIP_264GTPRO },
405
406 { PCI_CHIP_MACH64LB, "3D RAGE LT PRO (Mach64 LB, AGP)", 236, 75, 100, ATI_CHIP_264LTPRO },
407 { PCI_CHIP_MACH64LD, "3D RAGE LT PRO (Mach64 LD, AGP)", 230, 100, 100, ATI_CHIP_264LTPRO },
408 { PCI_CHIP_MACH64LI, "3D RAGE LT PRO (Mach64 LI, PCI)", 230, 100, 100, ATI_CHIP_264LTPRO | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 },
409 { PCI_CHIP_MACH64LP, "3D RAGE LT PRO (Mach64 LP, PCI)", 230, 100, 100, ATI_CHIP_264LTPRO },
410 { PCI_CHIP_MACH64LQ, "3D RAGE LT PRO (Mach64 LQ, PCI)", 230, 100, 100, ATI_CHIP_264LTPRO },
411
412 { PCI_CHIP_MACH64GM, "3D RAGE XL (Mach64 GM, AGP)", 230, 83, 63, ATI_CHIP_264XL },
413 { PCI_CHIP_MACH64GN, "3D RAGE XL (Mach64 GN, AGP)", 230, 83, 63, ATI_CHIP_264XL },
414 { PCI_CHIP_MACH64GO, "3D RAGE XL (Mach64 GO, PCI-66/BGA)", 230, 83, 63, ATI_CHIP_264XL },
Luis F. Ortiz5b373e12006-01-05 13:12:41 -0800415 { PCI_CHIP_MACH64GR, "3D RAGE XL (Mach64 GR, PCI-33MHz)", 235, 83, 63, ATI_CHIP_264XL | M64F_SDRAM_MAGIC_PLL },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 { PCI_CHIP_MACH64GL, "3D RAGE XL (Mach64 GL, PCI)", 230, 83, 63, ATI_CHIP_264XL },
417 { PCI_CHIP_MACH64GS, "3D RAGE XL (Mach64 GS, PCI)", 230, 83, 63, ATI_CHIP_264XL },
418
419 { PCI_CHIP_MACH64LM, "3D RAGE Mobility P/M (Mach64 LM, AGP 2x)", 230, 83, 125, ATI_CHIP_MOBILITY },
420 { PCI_CHIP_MACH64LN, "3D RAGE Mobility L (Mach64 LN, AGP 2x)", 230, 83, 125, ATI_CHIP_MOBILITY },
421 { PCI_CHIP_MACH64LR, "3D RAGE Mobility P/M (Mach64 LR, PCI)", 230, 83, 125, ATI_CHIP_MOBILITY },
422 { PCI_CHIP_MACH64LS, "3D RAGE Mobility L (Mach64 LS, PCI)", 230, 83, 125, ATI_CHIP_MOBILITY },
423#endif /* CONFIG_FB_ATY_CT */
424};
425
426/* can not fail */
427static int __devinit correct_chipset(struct atyfb_par *par)
428{
429 u8 rev;
430 u16 type;
431 u32 chip_id;
432 const char *name;
433 int i;
434
435 for (i = sizeof(aty_chips) / sizeof(*aty_chips) - 1; i >= 0; i--)
436 if (par->pci_id == aty_chips[i].pci_id)
437 break;
438
439 name = aty_chips[i].name;
440 par->pll_limits.pll_max = aty_chips[i].pll;
441 par->pll_limits.mclk = aty_chips[i].mclk;
442 par->pll_limits.xclk = aty_chips[i].xclk;
443 par->features = aty_chips[i].features;
444
445 chip_id = aty_ld_le32(CONFIG_CHIP_ID, par);
446 type = chip_id & CFG_CHIP_TYPE;
447 rev = (chip_id & CFG_CHIP_REV) >> 24;
448
449 switch(par->pci_id) {
450#ifdef CONFIG_FB_ATY_GX
451 case PCI_CHIP_MACH64GX:
452 if(type != 0x00d7)
453 return -ENODEV;
454 break;
455 case PCI_CHIP_MACH64CX:
456 if(type != 0x0057)
457 return -ENODEV;
458 break;
459#endif
460#ifdef CONFIG_FB_ATY_CT
461 case PCI_CHIP_MACH64VT:
462 rev &= 0xc7;
463 if(rev == 0x00) {
464 name = "ATI264VTA3 (Mach64 VT)";
465 par->pll_limits.pll_max = 170;
466 par->pll_limits.mclk = 67;
467 par->pll_limits.xclk = 67;
468 par->features = ATI_CHIP_264VT;
469 } else if(rev == 0x40) {
470 name = "ATI264VTA4 (Mach64 VT)";
471 par->pll_limits.pll_max = 200;
472 par->pll_limits.mclk = 67;
473 par->pll_limits.xclk = 67;
474 par->features = ATI_CHIP_264VT | M64F_MAGIC_POSTDIV;
475 } else {
476 name = "ATI264VTB (Mach64 VT)";
477 par->pll_limits.pll_max = 200;
478 par->pll_limits.mclk = 67;
479 par->pll_limits.xclk = 67;
480 par->features = ATI_CHIP_264VTB;
481 }
482 break;
483 case PCI_CHIP_MACH64GT:
484 rev &= 0x07;
485 if(rev == 0x01) {
486 par->pll_limits.pll_max = 170;
487 par->pll_limits.mclk = 67;
488 par->pll_limits.xclk = 67;
489 par->features = ATI_CHIP_264GTB;
490 } else if(rev == 0x02) {
491 par->pll_limits.pll_max = 200;
492 par->pll_limits.mclk = 67;
493 par->pll_limits.xclk = 67;
494 par->features = ATI_CHIP_264GTB;
495 }
496 break;
497#endif
498 }
499
500 PRINTKI("%s [0x%04x rev 0x%02x]\n", name, type, rev);
501 return 0;
502}
503
504static char ram_dram[] __devinitdata = "DRAM";
505static char ram_resv[] __devinitdata = "RESV";
506#ifdef CONFIG_FB_ATY_GX
507static char ram_vram[] __devinitdata = "VRAM";
508#endif /* CONFIG_FB_ATY_GX */
509#ifdef CONFIG_FB_ATY_CT
510static char ram_edo[] __devinitdata = "EDO";
511static char ram_sdram[] __devinitdata = "SDRAM (1:1)";
512static char ram_sgram[] __devinitdata = "SGRAM (1:1)";
513static char ram_sdram32[] __devinitdata = "SDRAM (2:1) (32-bit)";
514static char ram_off[] __devinitdata = "OFF";
515#endif /* CONFIG_FB_ATY_CT */
516
517
518static u32 pseudo_palette[17];
519
520#ifdef CONFIG_FB_ATY_GX
521static char *aty_gx_ram[8] __devinitdata = {
522 ram_dram, ram_vram, ram_vram, ram_dram,
523 ram_dram, ram_vram, ram_vram, ram_resv
524};
525#endif /* CONFIG_FB_ATY_GX */
526
527#ifdef CONFIG_FB_ATY_CT
528static char *aty_ct_ram[8] __devinitdata = {
529 ram_off, ram_dram, ram_edo, ram_edo,
530 ram_sdram, ram_sgram, ram_sdram32, ram_resv
531};
532#endif /* CONFIG_FB_ATY_CT */
533
534static u32 atyfb_get_pixclock(struct fb_var_screeninfo *var, struct atyfb_par *par)
535{
536 u32 pixclock = var->pixclock;
537#ifdef CONFIG_FB_ATY_GENERIC_LCD
538 u32 lcd_on_off;
539 par->pll.ct.xres = 0;
540 if (par->lcd_table != 0) {
541 lcd_on_off = aty_ld_lcd(LCD_GEN_CNTL, par);
542 if(lcd_on_off & LCD_ON) {
543 par->pll.ct.xres = var->xres;
544 pixclock = par->lcd_pixclock;
545 }
546 }
547#endif
548 return pixclock;
549}
550
551#if defined(CONFIG_PPC)
552
553/*
554 * Apple monitor sense
555 */
556
557static int __init read_aty_sense(const struct atyfb_par *par)
558{
559 int sense, i;
560
561 aty_st_le32(GP_IO, 0x31003100, par); /* drive outputs high */
562 __delay(200);
563 aty_st_le32(GP_IO, 0, par); /* turn off outputs */
564 __delay(2000);
565 i = aty_ld_le32(GP_IO, par); /* get primary sense value */
566 sense = ((i & 0x3000) >> 3) | (i & 0x100);
567
568 /* drive each sense line low in turn and collect the other 2 */
569 aty_st_le32(GP_IO, 0x20000000, par); /* drive A low */
570 __delay(2000);
571 i = aty_ld_le32(GP_IO, par);
572 sense |= ((i & 0x1000) >> 7) | ((i & 0x100) >> 4);
573 aty_st_le32(GP_IO, 0x20002000, par); /* drive A high again */
574 __delay(200);
575
576 aty_st_le32(GP_IO, 0x10000000, par); /* drive B low */
577 __delay(2000);
578 i = aty_ld_le32(GP_IO, par);
579 sense |= ((i & 0x2000) >> 10) | ((i & 0x100) >> 6);
580 aty_st_le32(GP_IO, 0x10001000, par); /* drive B high again */
581 __delay(200);
582
583 aty_st_le32(GP_IO, 0x01000000, par); /* drive C low */
584 __delay(2000);
585 sense |= (aty_ld_le32(GP_IO, par) & 0x3000) >> 12;
586 aty_st_le32(GP_IO, 0, par); /* turn off outputs */
587 return sense;
588}
589
590#endif /* defined(CONFIG_PPC) */
591
592/* ------------------------------------------------------------------------- */
593
594/*
595 * CRTC programming
596 */
597
598static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc)
599{
600#ifdef CONFIG_FB_ATY_GENERIC_LCD
601 if (par->lcd_table != 0) {
602 if(!M64_HAS(LT_LCD_REGS)) {
603 crtc->lcd_index = aty_ld_le32(LCD_INDEX, par);
604 aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
605 }
606 crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par);
607 crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par);
608
609
610 /* switch to non shadow registers */
611 aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
612 ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
613
614 /* save stretching */
615 crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par);
616 crtc->vert_stretching = aty_ld_lcd(VERT_STRETCHING, par);
617 if (!M64_HAS(LT_LCD_REGS))
618 crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par);
619 }
620#endif
621 crtc->h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
622 crtc->h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
623 crtc->v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
624 crtc->v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
625 crtc->vline_crnt_vline = aty_ld_le32(CRTC_VLINE_CRNT_VLINE, par);
626 crtc->off_pitch = aty_ld_le32(CRTC_OFF_PITCH, par);
627 crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
628
629#ifdef CONFIG_FB_ATY_GENERIC_LCD
630 if (par->lcd_table != 0) {
631 /* switch to shadow registers */
632 aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |
633 SHADOW_EN | SHADOW_RW_EN, par);
634
635 crtc->shadow_h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
636 crtc->shadow_h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
637 crtc->shadow_v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
638 crtc->shadow_v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
639
640 aty_st_le32(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);
641 }
642#endif /* CONFIG_FB_ATY_GENERIC_LCD */
643}
644
645static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc)
646{
647#ifdef CONFIG_FB_ATY_GENERIC_LCD
648 if (par->lcd_table != 0) {
649 /* stop CRTC */
650 aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~(CRTC_EXT_DISP_EN | CRTC_EN), par);
651
652 /* update non-shadow registers first */
653 aty_st_lcd(CONFIG_PANEL, crtc->lcd_config_panel, par);
654 aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
655 ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
656
657 /* temporarily disable stretching */
658 aty_st_lcd(HORZ_STRETCHING,
659 crtc->horz_stretching &
660 ~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN), par);
661 aty_st_lcd(VERT_STRETCHING,
662 crtc->vert_stretching &
663 ~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 |
664 VERT_STRETCH_USE0 | VERT_STRETCH_EN), par);
665 }
666#endif
667 /* turn off CRT */
668 aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~CRTC_EN, par);
669
670 DPRINTK("setting up CRTC\n");
671 DPRINTK("set primary CRT to %ix%i %c%c composite %c\n",
672 ((((crtc->h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->v_tot_disp>>16) & 0x7ff) + 1),
673 (crtc->h_sync_strt_wid & 0x200000)?'N':'P', (crtc->v_sync_strt_wid & 0x200000)?'N':'P',
674 (crtc->gen_cntl & CRTC_CSYNC_EN)?'P':'N');
675
676 DPRINTK("CRTC_H_TOTAL_DISP: %x\n",crtc->h_tot_disp);
677 DPRINTK("CRTC_H_SYNC_STRT_WID: %x\n",crtc->h_sync_strt_wid);
678 DPRINTK("CRTC_V_TOTAL_DISP: %x\n",crtc->v_tot_disp);
679 DPRINTK("CRTC_V_SYNC_STRT_WID: %x\n",crtc->v_sync_strt_wid);
680 DPRINTK("CRTC_OFF_PITCH: %x\n", crtc->off_pitch);
681 DPRINTK("CRTC_VLINE_CRNT_VLINE: %x\n", crtc->vline_crnt_vline);
682 DPRINTK("CRTC_GEN_CNTL: %x\n",crtc->gen_cntl);
683
684 aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, par);
685 aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, par);
686 aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_tot_disp, par);
687 aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid, par);
688 aty_st_le32(CRTC_OFF_PITCH, crtc->off_pitch, par);
689 aty_st_le32(CRTC_VLINE_CRNT_VLINE, crtc->vline_crnt_vline, par);
690
691 aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl, par);
692#if 0
693 FIXME
694 if (par->accel_flags & FB_ACCELF_TEXT)
695 aty_init_engine(par, info);
696#endif
697#ifdef CONFIG_FB_ATY_GENERIC_LCD
698 /* after setting the CRTC registers we should set the LCD registers. */
699 if (par->lcd_table != 0) {
700 /* switch to shadow registers */
701 aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |
702 (SHADOW_EN | SHADOW_RW_EN), par);
703
Ville Syrjäläcd4617b2006-01-09 20:53:21 -0800704 DPRINTK("set shadow CRT to %ix%i %c%c\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 ((((crtc->shadow_h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->shadow_v_tot_disp>>16) & 0x7ff) + 1),
706 (crtc->shadow_h_sync_strt_wid & 0x200000)?'N':'P', (crtc->shadow_v_sync_strt_wid & 0x200000)?'N':'P');
707
708 DPRINTK("SHADOW CRTC_H_TOTAL_DISP: %x\n", crtc->shadow_h_tot_disp);
709 DPRINTK("SHADOW CRTC_H_SYNC_STRT_WID: %x\n", crtc->shadow_h_sync_strt_wid);
710 DPRINTK("SHADOW CRTC_V_TOTAL_DISP: %x\n", crtc->shadow_v_tot_disp);
711 DPRINTK("SHADOW CRTC_V_SYNC_STRT_WID: %x\n", crtc->shadow_v_sync_strt_wid);
712
713 aty_st_le32(CRTC_H_TOTAL_DISP, crtc->shadow_h_tot_disp, par);
714 aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->shadow_h_sync_strt_wid, par);
715 aty_st_le32(CRTC_V_TOTAL_DISP, crtc->shadow_v_tot_disp, par);
716 aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->shadow_v_sync_strt_wid, par);
717
718 /* restore CRTC selection & shadow state and enable stretching */
719 DPRINTK("LCD_GEN_CNTL: %x\n", crtc->lcd_gen_cntl);
720 DPRINTK("HORZ_STRETCHING: %x\n", crtc->horz_stretching);
721 DPRINTK("VERT_STRETCHING: %x\n", crtc->vert_stretching);
722 if(!M64_HAS(LT_LCD_REGS))
723 DPRINTK("EXT_VERT_STRETCH: %x\n", crtc->ext_vert_stretch);
724
725 aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);
726 aty_st_lcd(HORZ_STRETCHING, crtc->horz_stretching, par);
727 aty_st_lcd(VERT_STRETCHING, crtc->vert_stretching, par);
728 if(!M64_HAS(LT_LCD_REGS)) {
729 aty_st_lcd(EXT_VERT_STRETCH, crtc->ext_vert_stretch, par);
730 aty_ld_le32(LCD_INDEX, par);
731 aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
732 }
733 }
734#endif /* CONFIG_FB_ATY_GENERIC_LCD */
735}
736
737static int aty_var_to_crtc(const struct fb_info *info,
738 const struct fb_var_screeninfo *var, struct crtc *crtc)
739{
740 struct atyfb_par *par = (struct atyfb_par *) info->par;
741 u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
742 u32 sync, vmode, vdisplay;
743 u32 h_total, h_disp, h_sync_strt, h_sync_end, h_sync_dly, h_sync_wid, h_sync_pol;
744 u32 v_total, v_disp, v_sync_strt, v_sync_end, v_sync_wid, v_sync_pol, c_sync;
745 u32 pix_width, dp_pix_width, dp_chain_mask;
746
747 /* input */
748 xres = var->xres;
749 yres = var->yres;
750 vxres = var->xres_virtual;
751 vyres = var->yres_virtual;
752 xoffset = var->xoffset;
753 yoffset = var->yoffset;
754 bpp = var->bits_per_pixel;
755 if (bpp == 16)
756 bpp = (var->green.length == 5) ? 15 : 16;
757 sync = var->sync;
758 vmode = var->vmode;
759
760 /* convert (and round up) and validate */
761 if (vxres < xres + xoffset)
762 vxres = xres + xoffset;
763 h_disp = xres;
764
765 if (vyres < yres + yoffset)
766 vyres = yres + yoffset;
767 v_disp = yres;
768
769 if (bpp <= 8) {
770 bpp = 8;
771 pix_width = CRTC_PIX_WIDTH_8BPP;
772 dp_pix_width =
773 HOST_8BPP | SRC_8BPP | DST_8BPP |
774 BYTE_ORDER_LSB_TO_MSB;
775 dp_chain_mask = DP_CHAIN_8BPP;
776 } else if (bpp <= 15) {
777 bpp = 16;
778 pix_width = CRTC_PIX_WIDTH_15BPP;
779 dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP |
780 BYTE_ORDER_LSB_TO_MSB;
781 dp_chain_mask = DP_CHAIN_15BPP;
782 } else if (bpp <= 16) {
783 bpp = 16;
784 pix_width = CRTC_PIX_WIDTH_16BPP;
785 dp_pix_width = HOST_16BPP | SRC_16BPP | DST_16BPP |
786 BYTE_ORDER_LSB_TO_MSB;
787 dp_chain_mask = DP_CHAIN_16BPP;
788 } else if (bpp <= 24 && M64_HAS(INTEGRATED)) {
789 bpp = 24;
790 pix_width = CRTC_PIX_WIDTH_24BPP;
791 dp_pix_width =
792 HOST_8BPP | SRC_8BPP | DST_8BPP |
793 BYTE_ORDER_LSB_TO_MSB;
794 dp_chain_mask = DP_CHAIN_24BPP;
795 } else if (bpp <= 32) {
796 bpp = 32;
797 pix_width = CRTC_PIX_WIDTH_32BPP;
798 dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP |
799 BYTE_ORDER_LSB_TO_MSB;
800 dp_chain_mask = DP_CHAIN_32BPP;
801 } else
802 FAIL("invalid bpp");
803
804 if (vxres * vyres * bpp / 8 > info->fix.smem_len)
805 FAIL("not enough video RAM");
806
807 h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
808 v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
809
810 if((xres > 1600) || (yres > 1200)) {
811 FAIL("MACH64 chips are designed for max 1600x1200\n"
812 "select anoter resolution.");
813 }
814 h_sync_strt = h_disp + var->right_margin;
815 h_sync_end = h_sync_strt + var->hsync_len;
816 h_sync_dly = var->right_margin & 7;
817 h_total = h_sync_end + h_sync_dly + var->left_margin;
818
819 v_sync_strt = v_disp + var->lower_margin;
820 v_sync_end = v_sync_strt + var->vsync_len;
821 v_total = v_sync_end + var->upper_margin;
822
823#ifdef CONFIG_FB_ATY_GENERIC_LCD
824 if (par->lcd_table != 0) {
825 if(!M64_HAS(LT_LCD_REGS)) {
826 u32 lcd_index = aty_ld_le32(LCD_INDEX, par);
827 crtc->lcd_index = lcd_index &
828 ~(LCD_INDEX_MASK | LCD_DISPLAY_DIS | LCD_SRC_SEL | CRTC2_DISPLAY_DIS);
829 aty_st_le32(LCD_INDEX, lcd_index, par);
830 }
831
832 if (!M64_HAS(MOBIL_BUS))
833 crtc->lcd_index |= CRTC2_DISPLAY_DIS;
834
835 crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par) | 0x4000;
836 crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par) & ~CRTC_RW_SELECT;
837
838 crtc->lcd_gen_cntl &=
839 ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 | TVCLK_PM_EN |
840 /*VCLK_DAC_PM_EN | USE_SHADOWED_VEND |*/
841 USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN);
842 crtc->lcd_gen_cntl |= DONT_SHADOW_VPAR | LOCK_8DOT;
843
844 if((crtc->lcd_gen_cntl & LCD_ON) &&
845 ((xres > par->lcd_width) || (yres > par->lcd_height))) {
846 /* We cannot display the mode on the LCD. If the CRT is enabled
847 we can turn off the LCD.
848 If the CRT is off, it isn't a good idea to switch it on; we don't
849 know if one is connected. So it's better to fail then.
850 */
851 if (crtc->lcd_gen_cntl & CRT_ON) {
Ville Syrjälä866d84c2006-01-09 20:53:22 -0800852 if (!(var->activate & FB_ACTIVATE_TEST))
853 PRINTKI("Disable LCD panel, because video mode does not fit.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 crtc->lcd_gen_cntl &= ~LCD_ON;
855 /*aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);*/
856 } else {
Ville Syrjälä866d84c2006-01-09 20:53:22 -0800857 if (!(var->activate & FB_ACTIVATE_TEST))
858 PRINTKE("Video mode exceeds size of LCD panel.\nConnect this computer to a conventional monitor if you really need this mode.\n");
859 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 }
861 }
862 }
863
864 if ((par->lcd_table != 0) && (crtc->lcd_gen_cntl & LCD_ON)) {
865 int VScan = 1;
866 /* bpp -> bytespp, 1,4 -> 0; 8 -> 2; 15,16 -> 1; 24 -> 6; 32 -> 5
867 const u8 DFP_h_sync_dly_LT[] = { 0, 2, 1, 6, 5 };
868 const u8 ADD_to_strt_wid_and_dly_LT_DAC[] = { 0, 5, 6, 9, 9, 12, 12 }; */
869
870 vmode &= ~(FB_VMODE_DOUBLE | FB_VMODE_INTERLACED);
871
872 /* This is horror! When we simulate, say 640x480 on an 800x600
Ville Syrjäläcd4617b2006-01-09 20:53:21 -0800873 LCD monitor, the CRTC should be programmed 800x600 values for
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 the non visible part, but 640x480 for the visible part.
Ville Syrjäläcd4617b2006-01-09 20:53:21 -0800875 This code has been tested on a laptop with it's 1400x1050 LCD
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 monitor and a conventional monitor both switched on.
877 Tested modes: 1280x1024, 1152x864, 1024x768, 800x600,
878 works with little glitches also with DOUBLESCAN modes
879 */
880 if (yres < par->lcd_height) {
881 VScan = par->lcd_height / yres;
882 if(VScan > 1) {
883 VScan = 2;
884 vmode |= FB_VMODE_DOUBLE;
885 }
886 }
887
888 h_sync_strt = h_disp + par->lcd_right_margin;
889 h_sync_end = h_sync_strt + par->lcd_hsync_len;
890 h_sync_dly = /*DFP_h_sync_dly[ ( bpp + 1 ) / 3 ]; */par->lcd_hsync_dly;
891 h_total = h_disp + par->lcd_hblank_len;
892
893 v_sync_strt = v_disp + par->lcd_lower_margin / VScan;
894 v_sync_end = v_sync_strt + par->lcd_vsync_len / VScan;
895 v_total = v_disp + par->lcd_vblank_len / VScan;
896 }
897#endif /* CONFIG_FB_ATY_GENERIC_LCD */
898
899 h_disp = (h_disp >> 3) - 1;
900 h_sync_strt = (h_sync_strt >> 3) - 1;
901 h_sync_end = (h_sync_end >> 3) - 1;
902 h_total = (h_total >> 3) - 1;
903 h_sync_wid = h_sync_end - h_sync_strt;
904
905 FAIL_MAX("h_disp too large", h_disp, 0xff);
906 FAIL_MAX("h_sync_strt too large", h_sync_strt, 0x1ff);
907 /*FAIL_MAX("h_sync_wid too large", h_sync_wid, 0x1f);*/
908 if(h_sync_wid > 0x1f)
909 h_sync_wid = 0x1f;
910 FAIL_MAX("h_total too large", h_total, 0x1ff);
911
912 if (vmode & FB_VMODE_DOUBLE) {
913 v_disp <<= 1;
914 v_sync_strt <<= 1;
915 v_sync_end <<= 1;
916 v_total <<= 1;
917 }
918
919 vdisplay = yres;
920#ifdef CONFIG_FB_ATY_GENERIC_LCD
921 if ((par->lcd_table != 0) && (crtc->lcd_gen_cntl & LCD_ON))
922 vdisplay = par->lcd_height;
923#endif
924
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 v_disp--;
926 v_sync_strt--;
927 v_sync_end--;
928 v_total--;
929 v_sync_wid = v_sync_end - v_sync_strt;
930
931 FAIL_MAX("v_disp too large", v_disp, 0x7ff);
932 FAIL_MAX("v_sync_stsrt too large", v_sync_strt, 0x7ff);
933 /*FAIL_MAX("v_sync_wid too large", v_sync_wid, 0x1f);*/
934 if(v_sync_wid > 0x1f)
935 v_sync_wid = 0x1f;
936 FAIL_MAX("v_total too large", v_total, 0x7ff);
937
938 c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;
939
940 /* output */
941 crtc->vxres = vxres;
942 crtc->vyres = vyres;
943 crtc->xoffset = xoffset;
944 crtc->yoffset = yoffset;
945 crtc->bpp = bpp;
946 crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19);
947 crtc->vline_crnt_vline = 0;
948
949 crtc->h_tot_disp = h_total | (h_disp<<16);
950 crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly<<8) |
951 ((h_sync_strt & 0x100)<<4) | (h_sync_wid<<16) | (h_sync_pol<<21);
952 crtc->v_tot_disp = v_total | (v_disp<<16);
953 crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid<<16) | (v_sync_pol<<21);
954
955 /* crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_PRESERVED_MASK; */
956 crtc->gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN | pix_width | c_sync;
957 crtc->gen_cntl |= CRTC_VGA_LINEAR;
958
959 /* Enable doublescan mode if requested */
960 if (vmode & FB_VMODE_DOUBLE)
961 crtc->gen_cntl |= CRTC_DBL_SCAN_EN;
962 /* Enable interlaced mode if requested */
963 if (vmode & FB_VMODE_INTERLACED)
964 crtc->gen_cntl |= CRTC_INTERLACE_EN;
965#ifdef CONFIG_FB_ATY_GENERIC_LCD
966 if (par->lcd_table != 0) {
967 vdisplay = yres;
968 if(vmode & FB_VMODE_DOUBLE)
969 vdisplay <<= 1;
970 if(vmode & FB_VMODE_INTERLACED) {
971 vdisplay >>= 1;
972
Ville Syrjäläcd4617b2006-01-09 20:53:21 -0800973 /* The prefered mode for the LCD is not interlaced, so disable it if
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 it was enabled. For doublescan there is no problem, because we can
975 compensate for it in the hardware stretching (we stretch half as much)
976 */
977 vmode &= ~FB_VMODE_INTERLACED;
978 /*crtc->gen_cntl &= ~CRTC_INTERLACE_EN;*/
979 }
980 crtc->gen_cntl &= ~(CRTC2_EN | CRTC2_PIX_WIDTH);
981 crtc->lcd_gen_cntl &= ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 |
982 /*TVCLK_PM_EN | VCLK_DAC_PM_EN |*/
983 USE_SHADOWED_VEND | USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN);
984 crtc->lcd_gen_cntl |= (DONT_SHADOW_VPAR/* | LOCK_8DOT*/);
985
986 /* MOBILITY M1 tested, FIXME: LT */
987 crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par);
988 if (!M64_HAS(LT_LCD_REGS))
989 crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par) &
990 ~(AUTO_VERT_RATIO | VERT_STRETCH_MODE | VERT_STRETCH_RATIO3);
991
992 crtc->horz_stretching &=
993 ~(HORZ_STRETCH_RATIO | HORZ_STRETCH_LOOP | AUTO_HORZ_RATIO |
994 HORZ_STRETCH_MODE | HORZ_STRETCH_EN);
995 if (xres < par->lcd_width) {
996 do {
997 /*
998 * The horizontal blender misbehaves when HDisplay is less than a
999 * a certain threshold (440 for a 1024-wide panel). It doesn't
1000 * stretch such modes enough. Use pixel replication instead of
1001 * blending to stretch modes that can be made to exactly fit the
1002 * panel width. The undocumented "NoLCDBlend" option allows the
1003 * pixel-replicated mode to be slightly wider or narrower than the
1004 * panel width. It also causes a mode that is exactly half as wide
1005 * as the panel to be pixel-replicated, rather than blended.
1006 */
1007 int HDisplay = xres & ~7;
1008 int nStretch = par->lcd_width / HDisplay;
1009 int Remainder = par->lcd_width % HDisplay;
1010
1011 if ((!Remainder && ((nStretch > 2))) ||
1012 (((HDisplay * 16) / par->lcd_width) < 7)) {
1013 static const char StretchLoops[] = {10, 12, 13, 15, 16};
1014 int horz_stretch_loop = -1, BestRemainder;
1015 int Numerator = HDisplay, Denominator = par->lcd_width;
1016 int Index = 5;
1017 ATIReduceRatio(&Numerator, &Denominator);
1018
1019 BestRemainder = (Numerator * 16) / Denominator;
1020 while (--Index >= 0) {
1021 Remainder = ((Denominator - Numerator) * StretchLoops[Index]) %
1022 Denominator;
1023 if (Remainder < BestRemainder) {
1024 horz_stretch_loop = Index;
1025 if (!(BestRemainder = Remainder))
1026 break;
1027 }
1028 }
1029
1030 if ((horz_stretch_loop >= 0) && !BestRemainder) {
1031 int horz_stretch_ratio = 0, Accumulator = 0;
1032 int reuse_previous = 1;
1033
1034 Index = StretchLoops[horz_stretch_loop];
1035
1036 while (--Index >= 0) {
1037 if (Accumulator > 0)
1038 horz_stretch_ratio |= reuse_previous;
1039 else
1040 Accumulator += Denominator;
1041 Accumulator -= Numerator;
1042 reuse_previous <<= 1;
1043 }
1044
1045 crtc->horz_stretching |= (HORZ_STRETCH_EN |
1046 ((horz_stretch_loop & HORZ_STRETCH_LOOP) << 16) |
1047 (horz_stretch_ratio & HORZ_STRETCH_RATIO));
1048 break; /* Out of the do { ... } while (0) */
1049 }
1050 }
1051
1052 crtc->horz_stretching |= (HORZ_STRETCH_MODE | HORZ_STRETCH_EN |
1053 (((HDisplay * (HORZ_STRETCH_BLEND + 1)) / par->lcd_width) & HORZ_STRETCH_BLEND));
1054 } while (0);
1055 }
1056
1057 if (vdisplay < par->lcd_height) {
1058 crtc->vert_stretching = (VERT_STRETCH_USE0 | VERT_STRETCH_EN |
1059 (((vdisplay * (VERT_STRETCH_RATIO0 + 1)) / par->lcd_height) & VERT_STRETCH_RATIO0));
1060
1061 if (!M64_HAS(LT_LCD_REGS) &&
1062 xres <= (M64_HAS(MOBIL_BUS)?1024:800))
1063 crtc->ext_vert_stretch |= VERT_STRETCH_MODE;
1064 } else {
1065 /*
1066 * Don't use vertical blending if the mode is too wide or not
1067 * vertically stretched.
1068 */
1069 crtc->vert_stretching = 0;
1070 }
1071 /* copy to shadow crtc */
1072 crtc->shadow_h_tot_disp = crtc->h_tot_disp;
1073 crtc->shadow_h_sync_strt_wid = crtc->h_sync_strt_wid;
1074 crtc->shadow_v_tot_disp = crtc->v_tot_disp;
1075 crtc->shadow_v_sync_strt_wid = crtc->v_sync_strt_wid;
1076 }
1077#endif /* CONFIG_FB_ATY_GENERIC_LCD */
1078
1079 if (M64_HAS(MAGIC_FIFO)) {
1080 /* Not VTB/GTB */
1081 /* FIXME: magic FIFO values */
1082 crtc->gen_cntl |= (aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC2_PIX_WIDTH);
1083 }
1084 crtc->dp_pix_width = dp_pix_width;
1085 crtc->dp_chain_mask = dp_chain_mask;
1086
1087 return 0;
1088}
1089
1090static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *var)
1091{
1092 u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync;
1093 u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid,
1094 h_sync_pol;
1095 u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
1096 u32 pix_width;
1097 u32 double_scan, interlace;
1098
1099 /* input */
1100 h_total = crtc->h_tot_disp & 0x1ff;
1101 h_disp = (crtc->h_tot_disp >> 16) & 0xff;
1102 h_sync_strt = (crtc->h_sync_strt_wid & 0xff) | ((crtc->h_sync_strt_wid >> 4) & 0x100);
1103 h_sync_dly = (crtc->h_sync_strt_wid >> 8) & 0x7;
1104 h_sync_wid = (crtc->h_sync_strt_wid >> 16) & 0x1f;
1105 h_sync_pol = (crtc->h_sync_strt_wid >> 21) & 0x1;
1106 v_total = crtc->v_tot_disp & 0x7ff;
1107 v_disp = (crtc->v_tot_disp >> 16) & 0x7ff;
1108 v_sync_strt = crtc->v_sync_strt_wid & 0x7ff;
1109 v_sync_wid = (crtc->v_sync_strt_wid >> 16) & 0x1f;
1110 v_sync_pol = (crtc->v_sync_strt_wid >> 21) & 0x1;
1111 c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
1112 pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
1113 double_scan = crtc->gen_cntl & CRTC_DBL_SCAN_EN;
1114 interlace = crtc->gen_cntl & CRTC_INTERLACE_EN;
1115
1116 /* convert */
1117 xres = (h_disp + 1) * 8;
1118 yres = v_disp + 1;
1119 left = (h_total - h_sync_strt - h_sync_wid) * 8 - h_sync_dly;
1120 right = (h_sync_strt - h_disp) * 8 + h_sync_dly;
1121 hslen = h_sync_wid * 8;
1122 upper = v_total - v_sync_strt - v_sync_wid;
1123 lower = v_sync_strt - v_disp;
1124 vslen = v_sync_wid;
1125 sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) |
1126 (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
1127 (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
1128
1129 switch (pix_width) {
1130#if 0
1131 case CRTC_PIX_WIDTH_4BPP:
1132 bpp = 4;
1133 var->red.offset = 0;
1134 var->red.length = 8;
1135 var->green.offset = 0;
1136 var->green.length = 8;
1137 var->blue.offset = 0;
1138 var->blue.length = 8;
1139 var->transp.offset = 0;
1140 var->transp.length = 0;
1141 break;
1142#endif
1143 case CRTC_PIX_WIDTH_8BPP:
1144 bpp = 8;
1145 var->red.offset = 0;
1146 var->red.length = 8;
1147 var->green.offset = 0;
1148 var->green.length = 8;
1149 var->blue.offset = 0;
1150 var->blue.length = 8;
1151 var->transp.offset = 0;
1152 var->transp.length = 0;
1153 break;
1154 case CRTC_PIX_WIDTH_15BPP: /* RGB 555 */
1155 bpp = 16;
1156 var->red.offset = 10;
1157 var->red.length = 5;
1158 var->green.offset = 5;
1159 var->green.length = 5;
1160 var->blue.offset = 0;
1161 var->blue.length = 5;
1162 var->transp.offset = 0;
1163 var->transp.length = 0;
1164 break;
1165 case CRTC_PIX_WIDTH_16BPP: /* RGB 565 */
1166 bpp = 16;
1167 var->red.offset = 11;
1168 var->red.length = 5;
1169 var->green.offset = 5;
1170 var->green.length = 6;
1171 var->blue.offset = 0;
1172 var->blue.length = 5;
1173 var->transp.offset = 0;
1174 var->transp.length = 0;
1175 break;
1176 case CRTC_PIX_WIDTH_24BPP: /* RGB 888 */
1177 bpp = 24;
1178 var->red.offset = 16;
1179 var->red.length = 8;
1180 var->green.offset = 8;
1181 var->green.length = 8;
1182 var->blue.offset = 0;
1183 var->blue.length = 8;
1184 var->transp.offset = 0;
1185 var->transp.length = 0;
1186 break;
1187 case CRTC_PIX_WIDTH_32BPP: /* ARGB 8888 */
1188 bpp = 32;
1189 var->red.offset = 16;
1190 var->red.length = 8;
1191 var->green.offset = 8;
1192 var->green.length = 8;
1193 var->blue.offset = 0;
1194 var->blue.length = 8;
1195 var->transp.offset = 24;
1196 var->transp.length = 8;
1197 break;
1198 default:
Ville Syrjälä866d84c2006-01-09 20:53:22 -08001199 PRINTKE("Invalid pixel width\n");
1200 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 }
1202
1203 /* output */
1204 var->xres = xres;
1205 var->yres = yres;
1206 var->xres_virtual = crtc->vxres;
1207 var->yres_virtual = crtc->vyres;
1208 var->bits_per_pixel = bpp;
1209 var->left_margin = left;
1210 var->right_margin = right;
1211 var->upper_margin = upper;
1212 var->lower_margin = lower;
1213 var->hsync_len = hslen;
1214 var->vsync_len = vslen;
1215 var->sync = sync;
1216 var->vmode = FB_VMODE_NONINTERLACED;
1217 /* In double scan mode, the vertical parameters are doubled, so we need to
1218 half them to get the right values.
1219 In interlaced mode the values are already correct, so no correction is
1220 necessary.
1221 */
1222 if (interlace)
1223 var->vmode = FB_VMODE_INTERLACED;
1224
1225 if (double_scan) {
1226 var->vmode = FB_VMODE_DOUBLE;
1227 var->yres>>=1;
1228 var->upper_margin>>=1;
1229 var->lower_margin>>=1;
1230 var->vsync_len>>=1;
1231 }
1232
1233 return 0;
1234}
1235
1236/* ------------------------------------------------------------------------- */
1237
1238static int atyfb_set_par(struct fb_info *info)
1239{
1240 struct atyfb_par *par = (struct atyfb_par *) info->par;
1241 struct fb_var_screeninfo *var = &info->var;
1242 u32 tmp, pixclock;
1243 int err;
1244#ifdef DEBUG
1245 struct fb_var_screeninfo debug;
1246 u32 pixclock_in_ps;
1247#endif
1248 if (par->asleep)
1249 return 0;
1250
1251 if ((err = aty_var_to_crtc(info, var, &par->crtc)))
1252 return err;
1253
1254 pixclock = atyfb_get_pixclock(var, par);
1255
1256 if (pixclock == 0) {
Ville Syrjälä866d84c2006-01-09 20:53:22 -08001257 PRINTKE("Invalid pixclock\n");
1258 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 } else {
1260 if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &par->pll)))
1261 return err;
1262 }
1263
1264 par->accel_flags = var->accel_flags; /* hack */
1265
1266 if (par->blitter_may_be_busy)
1267 wait_for_idle(par);
1268
1269 aty_set_crtc(par, &par->crtc);
1270 par->dac_ops->set_dac(info, &par->pll, var->bits_per_pixel, par->accel_flags);
1271 par->pll_ops->set_pll(info, &par->pll);
1272
1273#ifdef DEBUG
1274 if(par->pll_ops && par->pll_ops->pll_to_var)
1275 pixclock_in_ps = par->pll_ops->pll_to_var(info, &(par->pll));
1276 else
1277 pixclock_in_ps = 0;
1278
1279 if(0 == pixclock_in_ps) {
1280 PRINTKE("ALERT ops->pll_to_var get 0\n");
1281 pixclock_in_ps = pixclock;
1282 }
1283
1284 memset(&debug, 0, sizeof(debug));
1285 if(!aty_crtc_to_var(&(par->crtc), &debug)) {
1286 u32 hSync, vRefresh;
1287 u32 h_disp, h_sync_strt, h_sync_end, h_total;
1288 u32 v_disp, v_sync_strt, v_sync_end, v_total;
1289
1290 h_disp = debug.xres;
1291 h_sync_strt = h_disp + debug.right_margin;
1292 h_sync_end = h_sync_strt + debug.hsync_len;
1293 h_total = h_sync_end + debug.left_margin;
1294 v_disp = debug.yres;
1295 v_sync_strt = v_disp + debug.lower_margin;
1296 v_sync_end = v_sync_strt + debug.vsync_len;
1297 v_total = v_sync_end + debug.upper_margin;
1298
1299 hSync = 1000000000 / (pixclock_in_ps * h_total);
1300 vRefresh = (hSync * 1000) / v_total;
1301 if (par->crtc.gen_cntl & CRTC_INTERLACE_EN)
1302 vRefresh *= 2;
1303 if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN)
1304 vRefresh /= 2;
1305
1306 DPRINTK("atyfb_set_par\n");
1307 DPRINTK(" Set Visible Mode to %ix%i-%i\n", var->xres, var->yres, var->bits_per_pixel);
1308 DPRINTK(" Virtual resolution %ix%i, pixclock_in_ps %i (calculated %i)\n",
1309 var->xres_virtual, var->yres_virtual, pixclock, pixclock_in_ps);
1310 DPRINTK(" Dot clock: %i MHz\n", 1000000 / pixclock_in_ps);
1311 DPRINTK(" Horizontal sync: %i kHz\n", hSync);
1312 DPRINTK(" Vertical refresh: %i Hz\n", vRefresh);
1313 DPRINTK(" x style: %i.%03i %i %i %i %i %i %i %i %i\n",
1314 1000000 / pixclock_in_ps, 1000000 % pixclock_in_ps,
1315 h_disp, h_sync_strt, h_sync_end, h_total,
1316 v_disp, v_sync_strt, v_sync_end, v_total);
1317 DPRINTK(" fb style: %i %i %i %i %i %i %i %i %i\n",
1318 pixclock_in_ps,
1319 debug.left_margin, h_disp, debug.right_margin, debug.hsync_len,
1320 debug.upper_margin, v_disp, debug.lower_margin, debug.vsync_len);
1321 }
1322#endif /* DEBUG */
1323
1324 if (!M64_HAS(INTEGRATED)) {
1325 /* Don't forget MEM_CNTL */
1326 tmp = aty_ld_le32(MEM_CNTL, par) & 0xf0ffffff;
1327 switch (var->bits_per_pixel) {
1328 case 8:
1329 tmp |= 0x02000000;
1330 break;
1331 case 16:
1332 tmp |= 0x03000000;
1333 break;
1334 case 32:
1335 tmp |= 0x06000000;
1336 break;
1337 }
1338 aty_st_le32(MEM_CNTL, tmp, par);
1339 } else {
1340 tmp = aty_ld_le32(MEM_CNTL, par) & 0xf00fffff;
1341 if (!M64_HAS(MAGIC_POSTDIV))
1342 tmp |= par->mem_refresh_rate << 20;
1343 switch (var->bits_per_pixel) {
1344 case 8:
1345 case 24:
1346 tmp |= 0x00000000;
1347 break;
1348 case 16:
1349 tmp |= 0x04000000;
1350 break;
1351 case 32:
1352 tmp |= 0x08000000;
1353 break;
1354 }
1355 if (M64_HAS(CT_BUS)) {
1356 aty_st_le32(DAC_CNTL, 0x87010184, par);
1357 aty_st_le32(BUS_CNTL, 0x680000f9, par);
1358 } else if (M64_HAS(VT_BUS)) {
1359 aty_st_le32(DAC_CNTL, 0x87010184, par);
1360 aty_st_le32(BUS_CNTL, 0x680000f9, par);
1361 } else if (M64_HAS(MOBIL_BUS)) {
1362 aty_st_le32(DAC_CNTL, 0x80010102, par);
1363 aty_st_le32(BUS_CNTL, 0x7b33a040 | (par->aux_start ? BUS_APER_REG_DIS : 0), par);
1364 } else {
1365 /* GT */
1366 aty_st_le32(DAC_CNTL, 0x86010102, par);
1367 aty_st_le32(BUS_CNTL, 0x7b23a040 | (par->aux_start ? BUS_APER_REG_DIS : 0), par);
1368 aty_st_le32(EXT_MEM_CNTL, aty_ld_le32(EXT_MEM_CNTL, par) | 0x5000001, par);
1369 }
1370 aty_st_le32(MEM_CNTL, tmp, par);
1371 }
1372 aty_st_8(DAC_MASK, 0xff, par);
1373
1374 info->fix.line_length = var->xres_virtual * var->bits_per_pixel/8;
1375 info->fix.visual = var->bits_per_pixel <= 8 ?
1376 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
1377
1378 /* Initialize the graphics engine */
1379 if (par->accel_flags & FB_ACCELF_TEXT)
1380 aty_init_engine(par, info);
1381
1382#ifdef CONFIG_BOOTX_TEXT
1383 btext_update_display(info->fix.smem_start,
1384 (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8,
1385 ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1,
1386 var->bits_per_pixel,
1387 par->crtc.vxres * var->bits_per_pixel / 8);
1388#endif /* CONFIG_BOOTX_TEXT */
1389#if 0
1390 /* switch to accelerator mode */
1391 if (!(par->crtc.gen_cntl & CRTC_EXT_DISP_EN))
1392 aty_st_le32(CRTC_GEN_CNTL, par->crtc.gen_cntl | CRTC_EXT_DISP_EN, par);
1393#endif
1394#ifdef DEBUG
1395{
1396 /* dump non shadow CRTC, pll, LCD registers */
1397 int i; u32 base;
1398
1399 /* CRTC registers */
1400 base = 0x2000;
1401 printk("debug atyfb: Mach64 non-shadow register values:");
1402 for (i = 0; i < 256; i = i+4) {
1403 if(i%16 == 0) printk("\ndebug atyfb: 0x%04X: ", base + i);
1404 printk(" %08X", aty_ld_le32(i, par));
1405 }
1406 printk("\n\n");
1407
1408#ifdef CONFIG_FB_ATY_CT
1409 /* PLL registers */
1410 base = 0x00;
1411 printk("debug atyfb: Mach64 PLL register values:");
1412 for (i = 0; i < 64; i++) {
1413 if(i%16 == 0) printk("\ndebug atyfb: 0x%02X: ", base + i);
1414 if(i%4 == 0) printk(" ");
1415 printk("%02X", aty_ld_pll_ct(i, par));
1416 }
1417 printk("\n\n");
1418#endif /* CONFIG_FB_ATY_CT */
1419
1420#ifdef CONFIG_FB_ATY_GENERIC_LCD
1421 if (par->lcd_table != 0) {
1422 /* LCD registers */
1423 base = 0x00;
1424 printk("debug atyfb: LCD register values:");
1425 if(M64_HAS(LT_LCD_REGS)) {
1426 for(i = 0; i <= POWER_MANAGEMENT; i++) {
1427 if(i == EXT_VERT_STRETCH)
1428 continue;
1429 printk("\ndebug atyfb: 0x%04X: ", lt_lcd_regs[i]);
1430 printk(" %08X", aty_ld_lcd(i, par));
1431 }
1432
1433 } else {
1434 for (i = 0; i < 64; i++) {
1435 if(i%4 == 0) printk("\ndebug atyfb: 0x%02X: ", base + i);
1436 printk(" %08X", aty_ld_lcd(i, par));
1437 }
1438 }
1439 printk("\n\n");
1440 }
1441#endif /* CONFIG_FB_ATY_GENERIC_LCD */
1442}
1443#endif /* DEBUG */
1444 return 0;
1445}
1446
1447static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1448{
1449 struct atyfb_par *par = (struct atyfb_par *) info->par;
1450 int err;
1451 struct crtc crtc;
1452 union aty_pll pll;
1453 u32 pixclock;
1454
1455 memcpy(&pll, &(par->pll), sizeof(pll));
1456
1457 if((err = aty_var_to_crtc(info, var, &crtc)))
1458 return err;
1459
1460 pixclock = atyfb_get_pixclock(var, par);
1461
1462 if (pixclock == 0) {
Ville Syrjälä866d84c2006-01-09 20:53:22 -08001463 if (!(var->activate & FB_ACTIVATE_TEST))
1464 PRINTKE("Invalid pixclock\n");
1465 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 } else {
1467 if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &pll)))
1468 return err;
1469 }
1470
1471 if (var->accel_flags & FB_ACCELF_TEXT)
1472 info->var.accel_flags = FB_ACCELF_TEXT;
1473 else
1474 info->var.accel_flags = 0;
1475
1476#if 0 /* fbmon is not done. uncomment for 2.5.x -brad */
1477 if (!fbmon_valid_timings(pixclock, htotal, vtotal, info))
1478 return -EINVAL;
1479#endif
1480 aty_crtc_to_var(&crtc, var);
1481 var->pixclock = par->pll_ops->pll_to_var(info, &pll);
1482 return 0;
1483}
1484
1485static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info)
1486{
1487 u32 xoffset = info->var.xoffset;
1488 u32 yoffset = info->var.yoffset;
1489 u32 vxres = par->crtc.vxres;
1490 u32 bpp = info->var.bits_per_pixel;
1491
1492 par->crtc.off_pitch = ((yoffset * vxres + xoffset) * bpp / 64) | (vxres << 19);
1493}
1494
1495
1496 /*
1497 * Open/Release the frame buffer device
1498 */
1499
1500static int atyfb_open(struct fb_info *info, int user)
1501{
1502 struct atyfb_par *par = (struct atyfb_par *) info->par;
1503
1504 if (user) {
1505 par->open++;
1506#ifdef __sparc__
1507 par->mmaped = 0;
1508#endif
1509 }
1510 return (0);
1511}
1512
1513static irqreturn_t aty_irq(int irq, void *dev_id, struct pt_regs *fp)
1514{
1515 struct atyfb_par *par = dev_id;
1516 int handled = 0;
1517 u32 int_cntl;
1518
1519 spin_lock(&par->int_lock);
1520
1521 int_cntl = aty_ld_le32(CRTC_INT_CNTL, par);
1522
1523 if (int_cntl & CRTC_VBLANK_INT) {
1524 /* clear interrupt */
1525 aty_st_le32(CRTC_INT_CNTL, (int_cntl & CRTC_INT_EN_MASK) | CRTC_VBLANK_INT_AK, par);
1526 par->vblank.count++;
1527 if (par->vblank.pan_display) {
1528 par->vblank.pan_display = 0;
1529 aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
1530 }
1531 wake_up_interruptible(&par->vblank.wait);
1532 handled = 1;
1533 }
1534
1535 spin_unlock(&par->int_lock);
1536
1537 return IRQ_RETVAL(handled);
1538}
1539
1540static int aty_enable_irq(struct atyfb_par *par, int reenable)
1541{
1542 u32 int_cntl;
1543
1544 if (!test_and_set_bit(0, &par->irq_flags)) {
1545 if (request_irq(par->irq, aty_irq, SA_SHIRQ, "atyfb", par)) {
1546 clear_bit(0, &par->irq_flags);
1547 return -EINVAL;
1548 }
1549 spin_lock_irq(&par->int_lock);
1550 int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
1551 /* clear interrupt */
1552 aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_AK, par);
1553 /* enable interrupt */
1554 aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_EN, par);
1555 spin_unlock_irq(&par->int_lock);
1556 } else if (reenable) {
1557 spin_lock_irq(&par->int_lock);
1558 int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
1559 if (!(int_cntl & CRTC_VBLANK_INT_EN)) {
1560 printk("atyfb: someone disabled IRQ [%08x]\n", int_cntl);
1561 /* re-enable interrupt */
1562 aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_EN, par );
1563 }
1564 spin_unlock_irq(&par->int_lock);
1565 }
1566
1567 return 0;
1568}
1569
1570static int aty_disable_irq(struct atyfb_par *par)
1571{
1572 u32 int_cntl;
1573
1574 if (test_and_clear_bit(0, &par->irq_flags)) {
1575 if (par->vblank.pan_display) {
1576 par->vblank.pan_display = 0;
1577 aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
1578 }
1579 spin_lock_irq(&par->int_lock);
1580 int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
1581 /* disable interrupt */
1582 aty_st_le32(CRTC_INT_CNTL, int_cntl & ~CRTC_VBLANK_INT_EN, par );
1583 spin_unlock_irq(&par->int_lock);
1584 free_irq(par->irq, par);
1585 }
1586
1587 return 0;
1588}
1589
1590static int atyfb_release(struct fb_info *info, int user)
1591{
1592 struct atyfb_par *par = (struct atyfb_par *) info->par;
1593 if (user) {
1594 par->open--;
1595 mdelay(1);
1596 wait_for_idle(par);
1597 if (!par->open) {
1598#ifdef __sparc__
1599 int was_mmaped = par->mmaped;
1600
1601 par->mmaped = 0;
1602
1603 if (was_mmaped) {
1604 struct fb_var_screeninfo var;
1605
1606 /* Now reset the default display config, we have no
1607 * idea what the program(s) which mmap'd the chip did
1608 * to the configuration, nor whether it restored it
1609 * correctly.
1610 */
1611 var = default_var;
1612 if (noaccel)
1613 var.accel_flags &= ~FB_ACCELF_TEXT;
1614 else
1615 var.accel_flags |= FB_ACCELF_TEXT;
1616 if (var.yres == var.yres_virtual) {
1617 u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2));
1618 var.yres_virtual = ((videoram * 8) / var.bits_per_pixel) / var.xres_virtual;
1619 if (var.yres_virtual < var.yres)
1620 var.yres_virtual = var.yres;
1621 }
1622 }
1623#endif
1624 aty_disable_irq(par);
1625 }
1626 }
1627 return (0);
1628}
1629
1630 /*
1631 * Pan or Wrap the Display
1632 *
1633 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
1634 */
1635
1636static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
1637{
1638 struct atyfb_par *par = (struct atyfb_par *) info->par;
1639 u32 xres, yres, xoffset, yoffset;
1640
1641 xres = (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8;
1642 yres = ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1;
1643 if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN)
1644 yres >>= 1;
1645 xoffset = (var->xoffset + 7) & ~7;
1646 yoffset = var->yoffset;
1647 if (xoffset + xres > par->crtc.vxres || yoffset + yres > par->crtc.vyres)
1648 return -EINVAL;
1649 info->var.xoffset = xoffset;
1650 info->var.yoffset = yoffset;
1651 if (par->asleep)
1652 return 0;
1653
1654 set_off_pitch(par, info);
1655 if ((var->activate & FB_ACTIVATE_VBL) && !aty_enable_irq(par, 0)) {
1656 par->vblank.pan_display = 1;
1657 } else {
1658 par->vblank.pan_display = 0;
1659 aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
1660 }
1661
1662 return 0;
1663}
1664
1665static int aty_waitforvblank(struct atyfb_par *par, u32 crtc)
1666{
1667 struct aty_interrupt *vbl;
1668 unsigned int count;
1669 int ret;
1670
1671 switch (crtc) {
1672 case 0:
1673 vbl = &par->vblank;
1674 break;
1675 default:
1676 return -ENODEV;
1677 }
1678
1679 ret = aty_enable_irq(par, 0);
1680 if (ret)
1681 return ret;
1682
1683 count = vbl->count;
1684 ret = wait_event_interruptible_timeout(vbl->wait, count != vbl->count, HZ/10);
1685 if (ret < 0) {
1686 return ret;
1687 }
1688 if (ret == 0) {
1689 aty_enable_irq(par, 1);
1690 return -ETIMEDOUT;
1691 }
1692
1693 return 0;
1694}
1695
1696
1697#ifdef DEBUG
1698#define ATYIO_CLKR 0x41545900 /* ATY\00 */
1699#define ATYIO_CLKW 0x41545901 /* ATY\01 */
1700
1701struct atyclk {
1702 u32 ref_clk_per;
1703 u8 pll_ref_div;
1704 u8 mclk_fb_div;
1705 u8 mclk_post_div; /* 1,2,3,4,8 */
1706 u8 mclk_fb_mult; /* 2 or 4 */
1707 u8 xclk_post_div; /* 1,2,3,4,8 */
1708 u8 vclk_fb_div;
1709 u8 vclk_post_div; /* 1,2,3,4,6,8,12 */
1710 u32 dsp_xclks_per_row; /* 0-16383 */
1711 u32 dsp_loop_latency; /* 0-15 */
1712 u32 dsp_precision; /* 0-7 */
1713 u32 dsp_on; /* 0-2047 */
1714 u32 dsp_off; /* 0-2047 */
1715};
1716
1717#define ATYIO_FEATR 0x41545902 /* ATY\02 */
1718#define ATYIO_FEATW 0x41545903 /* ATY\03 */
1719#endif
1720
1721#ifndef FBIO_WAITFORVSYNC
1722#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
1723#endif
1724
1725static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
1726 u_long arg, struct fb_info *info)
1727{
1728 struct atyfb_par *par = (struct atyfb_par *) info->par;
1729#ifdef __sparc__
1730 struct fbtype fbtyp;
1731#endif
1732
1733 switch (cmd) {
1734#ifdef __sparc__
1735 case FBIOGTYPE:
1736 fbtyp.fb_type = FBTYPE_PCI_GENERIC;
1737 fbtyp.fb_width = par->crtc.vxres;
1738 fbtyp.fb_height = par->crtc.vyres;
1739 fbtyp.fb_depth = info->var.bits_per_pixel;
1740 fbtyp.fb_cmsize = info->cmap.len;
1741 fbtyp.fb_size = info->fix.smem_len;
1742 if (copy_to_user((struct fbtype __user *) arg, &fbtyp, sizeof(fbtyp)))
1743 return -EFAULT;
1744 break;
1745#endif /* __sparc__ */
1746
1747 case FBIO_WAITFORVSYNC:
1748 {
1749 u32 crtc;
1750
1751 if (get_user(crtc, (__u32 __user *) arg))
1752 return -EFAULT;
1753
1754 return aty_waitforvblank(par, crtc);
1755 }
1756 break;
1757
1758#if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)
1759 case ATYIO_CLKR:
1760 if (M64_HAS(INTEGRATED)) {
1761 struct atyclk clk;
1762 union aty_pll *pll = &(par->pll);
1763 u32 dsp_config = pll->ct.dsp_config;
1764 u32 dsp_on_off = pll->ct.dsp_on_off;
1765 clk.ref_clk_per = par->ref_clk_per;
1766 clk.pll_ref_div = pll->ct.pll_ref_div;
1767 clk.mclk_fb_div = pll->ct.mclk_fb_div;
1768 clk.mclk_post_div = pll->ct.mclk_post_div_real;
1769 clk.mclk_fb_mult = pll->ct.mclk_fb_mult;
1770 clk.xclk_post_div = pll->ct.xclk_post_div_real;
1771 clk.vclk_fb_div = pll->ct.vclk_fb_div;
1772 clk.vclk_post_div = pll->ct.vclk_post_div_real;
1773 clk.dsp_xclks_per_row = dsp_config & 0x3fff;
1774 clk.dsp_loop_latency = (dsp_config >> 16) & 0xf;
1775 clk.dsp_precision = (dsp_config >> 20) & 7;
1776 clk.dsp_off = dsp_on_off & 0x7ff;
1777 clk.dsp_on = (dsp_on_off >> 16) & 0x7ff;
1778 if (copy_to_user((struct atyclk __user *) arg, &clk,
1779 sizeof(clk)))
1780 return -EFAULT;
1781 } else
1782 return -EINVAL;
1783 break;
1784 case ATYIO_CLKW:
1785 if (M64_HAS(INTEGRATED)) {
1786 struct atyclk clk;
1787 union aty_pll *pll = &(par->pll);
1788 if (copy_from_user(&clk, (struct atyclk __user *) arg, sizeof(clk)))
1789 return -EFAULT;
1790 par->ref_clk_per = clk.ref_clk_per;
1791 pll->ct.pll_ref_div = clk.pll_ref_div;
1792 pll->ct.mclk_fb_div = clk.mclk_fb_div;
1793 pll->ct.mclk_post_div_real = clk.mclk_post_div;
1794 pll->ct.mclk_fb_mult = clk.mclk_fb_mult;
1795 pll->ct.xclk_post_div_real = clk.xclk_post_div;
1796 pll->ct.vclk_fb_div = clk.vclk_fb_div;
1797 pll->ct.vclk_post_div_real = clk.vclk_post_div;
1798 pll->ct.dsp_config = (clk.dsp_xclks_per_row & 0x3fff) |
1799 ((clk.dsp_loop_latency & 0xf)<<16)| ((clk.dsp_precision & 7)<<20);
1800 pll->ct.dsp_on_off = (clk.dsp_off & 0x7ff) | ((clk.dsp_on & 0x7ff)<<16);
1801 /*aty_calc_pll_ct(info, &pll->ct);*/
1802 aty_set_pll_ct(info, pll);
1803 } else
1804 return -EINVAL;
1805 break;
1806 case ATYIO_FEATR:
1807 if (get_user(par->features, (u32 __user *) arg))
1808 return -EFAULT;
1809 break;
1810 case ATYIO_FEATW:
1811 if (put_user(par->features, (u32 __user *) arg))
1812 return -EFAULT;
1813 break;
1814#endif /* DEBUG && CONFIG_FB_ATY_CT */
1815 default:
1816 return -EINVAL;
1817 }
1818 return 0;
1819}
1820
1821static int atyfb_sync(struct fb_info *info)
1822{
1823 struct atyfb_par *par = (struct atyfb_par *) info->par;
1824
1825 if (par->blitter_may_be_busy)
1826 wait_for_idle(par);
1827 return 0;
1828}
1829
1830#ifdef __sparc__
1831static int atyfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
1832{
1833 struct atyfb_par *par = (struct atyfb_par *) info->par;
1834 unsigned int size, page, map_size = 0;
1835 unsigned long map_offset = 0;
1836 unsigned long off;
1837 int i;
1838
1839 if (!par->mmap_map)
1840 return -ENXIO;
1841
1842 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
1843 return -EINVAL;
1844
1845 off = vma->vm_pgoff << PAGE_SHIFT;
1846 size = vma->vm_end - vma->vm_start;
1847
1848 /* To stop the swapper from even considering these pages. */
1849 vma->vm_flags |= (VM_IO | VM_RESERVED);
1850
1851 if (((vma->vm_pgoff == 0) && (size == info->fix.smem_len)) ||
1852 ((off == info->fix.smem_len) && (size == PAGE_SIZE)))
1853 off += 0x8000000000000000UL;
1854
1855 vma->vm_pgoff = off >> PAGE_SHIFT; /* propagate off changes */
1856
1857 /* Each page, see which map applies */
1858 for (page = 0; page < size;) {
1859 map_size = 0;
1860 for (i = 0; par->mmap_map[i].size; i++) {
1861 unsigned long start = par->mmap_map[i].voff;
1862 unsigned long end = start + par->mmap_map[i].size;
1863 unsigned long offset = off + page;
1864
1865 if (start > offset)
1866 continue;
1867 if (offset >= end)
1868 continue;
1869
1870 map_size = par->mmap_map[i].size - (offset - start);
1871 map_offset =
1872 par->mmap_map[i].poff + (offset - start);
1873 break;
1874 }
1875 if (!map_size) {
1876 page += PAGE_SIZE;
1877 continue;
1878 }
1879 if (page + map_size > size)
1880 map_size = size - page;
1881
1882 pgprot_val(vma->vm_page_prot) &=
1883 ~(par->mmap_map[i].prot_mask);
1884 pgprot_val(vma->vm_page_prot) |= par->mmap_map[i].prot_flag;
1885
1886 if (remap_pfn_range(vma, vma->vm_start + page,
1887 map_offset >> PAGE_SHIFT, map_size, vma->vm_page_prot))
1888 return -EAGAIN;
1889
1890 page += map_size;
1891 }
1892
1893 if (!map_size)
1894 return -EINVAL;
1895
1896 if (!par->mmaped)
1897 par->mmaped = 1;
1898 return 0;
1899}
1900
1901static struct {
1902 u32 yoffset;
1903 u8 r[2][256];
1904 u8 g[2][256];
1905 u8 b[2][256];
1906} atyfb_save;
1907
1908static void atyfb_save_palette(struct atyfb_par *par, int enter)
1909{
1910 int i, tmp;
1911
1912 for (i = 0; i < 256; i++) {
1913 tmp = aty_ld_8(DAC_CNTL, par) & 0xfc;
1914 if (M64_HAS(EXTRA_BRIGHT))
1915 tmp |= 0x2;
1916 aty_st_8(DAC_CNTL, tmp, par);
1917 aty_st_8(DAC_MASK, 0xff, par);
1918
1919 writeb(i, &par->aty_cmap_regs->rindex);
1920 atyfb_save.r[enter][i] = readb(&par->aty_cmap_regs->lut);
1921 atyfb_save.g[enter][i] = readb(&par->aty_cmap_regs->lut);
1922 atyfb_save.b[enter][i] = readb(&par->aty_cmap_regs->lut);
1923 writeb(i, &par->aty_cmap_regs->windex);
1924 writeb(atyfb_save.r[1 - enter][i],
1925 &par->aty_cmap_regs->lut);
1926 writeb(atyfb_save.g[1 - enter][i],
1927 &par->aty_cmap_regs->lut);
1928 writeb(atyfb_save.b[1 - enter][i],
1929 &par->aty_cmap_regs->lut);
1930 }
1931}
1932
1933static void atyfb_palette(int enter)
1934{
1935 struct atyfb_par *par;
1936 struct fb_info *info;
1937 int i;
1938
1939 for (i = 0; i < FB_MAX; i++) {
1940 info = registered_fb[i];
1941 if (info && info->fbops == &atyfb_ops) {
1942 par = (struct atyfb_par *) info->par;
1943
1944 atyfb_save_palette(par, enter);
1945 if (enter) {
1946 atyfb_save.yoffset = info->var.yoffset;
1947 info->var.yoffset = 0;
1948 set_off_pitch(par, info);
1949 } else {
1950 info->var.yoffset = atyfb_save.yoffset;
1951 set_off_pitch(par, info);
1952 }
1953 aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
1954 break;
1955 }
1956 }
1957}
1958#endif /* __sparc__ */
1959
1960
1961
1962#if defined(CONFIG_PM) && defined(CONFIG_PCI)
1963
1964/* Power management routines. Those are used for PowerBook sleep.
1965 */
1966static int aty_power_mgmt(int sleep, struct atyfb_par *par)
1967{
1968 u32 pm;
1969 int timeout;
1970
1971 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
1972 pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;
1973 aty_st_lcd(POWER_MANAGEMENT, pm, par);
1974 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
1975
1976 timeout = 2000;
1977 if (sleep) {
1978 /* Sleep */
1979 pm &= ~PWR_MGT_ON;
1980 aty_st_lcd(POWER_MANAGEMENT, pm, par);
1981 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
1982 udelay(10);
1983 pm &= ~(PWR_BLON | AUTO_PWR_UP);
1984 pm |= SUSPEND_NOW;
1985 aty_st_lcd(POWER_MANAGEMENT, pm, par);
1986 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
1987 udelay(10);
1988 pm |= PWR_MGT_ON;
1989 aty_st_lcd(POWER_MANAGEMENT, pm, par);
1990 do {
1991 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
1992 mdelay(1);
1993 if ((--timeout) == 0)
1994 break;
1995 } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
1996 } else {
1997 /* Wakeup */
1998 pm &= ~PWR_MGT_ON;
1999 aty_st_lcd(POWER_MANAGEMENT, pm, par);
2000 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2001 udelay(10);
2002 pm &= ~SUSPEND_NOW;
2003 pm |= (PWR_BLON | AUTO_PWR_UP);
2004 aty_st_lcd(POWER_MANAGEMENT, pm, par);
2005 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2006 udelay(10);
2007 pm |= PWR_MGT_ON;
2008 aty_st_lcd(POWER_MANAGEMENT, pm, par);
2009 do {
2010 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2011 mdelay(1);
2012 if ((--timeout) == 0)
2013 break;
2014 } while ((pm & PWR_MGT_STATUS_MASK) != 0);
2015 }
2016 mdelay(500);
2017
2018 return timeout ? 0 : -EIO;
2019}
2020
2021static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
2022{
2023 struct fb_info *info = pci_get_drvdata(pdev);
2024 struct atyfb_par *par = (struct atyfb_par *) info->par;
2025
Pavel Machekca078ba2005-09-03 15:56:57 -07002026#ifndef CONFIG_PPC_PMAC
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 /* HACK ALERT ! Once I find a proper way to say to each driver
2028 * individually what will happen with it's PCI slot, I'll change
2029 * that. On laptops, the AGP slot is just unclocked, so D2 is
2030 * expected, while on desktops, the card is powered off
2031 */
Pavel Machekca078ba2005-09-03 15:56:57 -07002032 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033#endif /* CONFIG_PPC_PMAC */
2034
Pavel Machekca078ba2005-09-03 15:56:57 -07002035 if (state.event == pdev->dev.power.power_state.event)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 return 0;
2037
2038 acquire_console_sem();
2039
2040 fb_set_suspend(info, 1);
2041
2042 /* Idle & reset engine */
2043 wait_for_idle(par);
2044 aty_reset_engine(par);
2045
2046 /* Blank display and LCD */
2047 atyfb_blank(FB_BLANK_POWERDOWN, info);
2048
2049 par->asleep = 1;
2050 par->lock_blank = 1;
2051
2052 /* Set chip to "suspend" mode */
2053 if (aty_power_mgmt(1, par)) {
2054 par->asleep = 0;
2055 par->lock_blank = 0;
2056 atyfb_blank(FB_BLANK_UNBLANK, info);
2057 fb_set_suspend(info, 0);
2058 release_console_sem();
2059 return -EIO;
2060 }
2061
2062 release_console_sem();
2063
2064 pdev->dev.power.power_state = state;
2065
2066 return 0;
2067}
2068
2069static int atyfb_pci_resume(struct pci_dev *pdev)
2070{
2071 struct fb_info *info = pci_get_drvdata(pdev);
2072 struct atyfb_par *par = (struct atyfb_par *) info->par;
2073
Pavel Machekca078ba2005-09-03 15:56:57 -07002074 if (pdev->dev.power.power_state.event == PM_EVENT_ON)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075 return 0;
2076
2077 acquire_console_sem();
2078
Pavel Machekca078ba2005-09-03 15:56:57 -07002079 if (pdev->dev.power.power_state.event == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 aty_power_mgmt(0, par);
2081 par->asleep = 0;
2082
2083 /* Restore display */
2084 atyfb_set_par(info);
2085
2086 /* Refresh */
2087 fb_set_suspend(info, 0);
2088
2089 /* Unblank */
2090 par->lock_blank = 0;
2091 atyfb_blank(FB_BLANK_UNBLANK, info);
2092
2093 release_console_sem();
2094
2095 pdev->dev.power.power_state = PMSG_ON;
2096
2097 return 0;
2098}
2099
2100#endif /* defined(CONFIG_PM) && defined(CONFIG_PCI) */
2101
2102#ifdef CONFIG_PMAC_BACKLIGHT
2103
2104 /*
2105 * LCD backlight control
2106 */
2107
2108static int backlight_conv[] = {
2109 0x00, 0x3f, 0x4c, 0x59, 0x66, 0x73, 0x80, 0x8d,
2110 0x9a, 0xa7, 0xb4, 0xc1, 0xcf, 0xdc, 0xe9, 0xff
2111};
2112
2113static int aty_set_backlight_enable(int on, int level, void *data)
2114{
2115 struct fb_info *info = (struct fb_info *) data;
2116 struct atyfb_par *par = (struct atyfb_par *) info->par;
2117 unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par);
2118
2119 reg |= (BLMOD_EN | BIASMOD_EN);
2120 if (on && level > BACKLIGHT_OFF) {
2121 reg &= ~BIAS_MOD_LEVEL_MASK;
2122 reg |= (backlight_conv[level] << BIAS_MOD_LEVEL_SHIFT);
2123 } else {
2124 reg &= ~BIAS_MOD_LEVEL_MASK;
2125 reg |= (backlight_conv[0] << BIAS_MOD_LEVEL_SHIFT);
2126 }
2127 aty_st_lcd(LCD_MISC_CNTL, reg, par);
2128 return 0;
2129}
2130
2131static int aty_set_backlight_level(int level, void *data)
2132{
2133 return aty_set_backlight_enable(1, level, data);
2134}
2135
2136static struct backlight_controller aty_backlight_controller = {
2137 aty_set_backlight_enable,
2138 aty_set_backlight_level
2139};
2140#endif /* CONFIG_PMAC_BACKLIGHT */
2141
2142static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
2143{
2144 const int ragepro_tbl[] = {
2145 44, 50, 55, 66, 75, 80, 100
2146 };
2147 const int ragexl_tbl[] = {
2148 50, 66, 75, 83, 90, 95, 100, 105,
2149 110, 115, 120, 125, 133, 143, 166
2150 };
2151 const int *refresh_tbl;
2152 int i, size;
2153
2154 if (IS_XL(par->pci_id) || IS_MOBILITY(par->pci_id)) {
2155 refresh_tbl = ragexl_tbl;
2156 size = sizeof(ragexl_tbl)/sizeof(int);
2157 } else {
2158 refresh_tbl = ragepro_tbl;
2159 size = sizeof(ragepro_tbl)/sizeof(int);
2160 }
2161
2162 for (i=0; i < size; i++) {
2163 if (xclk < refresh_tbl[i])
2164 break;
2165 }
2166 par->mem_refresh_rate = i;
2167}
2168
2169 /*
2170 * Initialisation
2171 */
2172
2173static struct fb_info *fb_list = NULL;
2174
Antonino A. Daplas1013d262005-11-07 01:00:41 -08002175#if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD)
2176static int __devinit atyfb_get_timings_from_lcd(struct atyfb_par *par,
2177 struct fb_var_screeninfo *var)
2178{
2179 int ret = -EINVAL;
2180
2181 if (par->lcd_table != 0 && (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
2182 *var = default_var;
2183 var->xres = var->xres_virtual = par->lcd_hdisp;
2184 var->right_margin = par->lcd_right_margin;
2185 var->left_margin = par->lcd_hblank_len -
2186 (par->lcd_right_margin + par->lcd_hsync_dly +
2187 par->lcd_hsync_len);
2188 var->hsync_len = par->lcd_hsync_len + par->lcd_hsync_dly;
2189 var->yres = var->yres_virtual = par->lcd_vdisp;
2190 var->lower_margin = par->lcd_lower_margin;
2191 var->upper_margin = par->lcd_vblank_len -
2192 (par->lcd_lower_margin + par->lcd_vsync_len);
2193 var->vsync_len = par->lcd_vsync_len;
2194 var->pixclock = par->lcd_pixclock;
2195 ret = 0;
2196 }
2197
2198 return ret;
2199}
2200#endif /* defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) */
2201
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202static int __init aty_init(struct fb_info *info, const char *name)
2203{
2204 struct atyfb_par *par = (struct atyfb_par *) info->par;
2205 const char *ramname = NULL, *xtal;
Antonino A. Daplas1013d262005-11-07 01:00:41 -08002206 int gtb_memsize, has_var = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 struct fb_var_screeninfo var;
2208 u8 pll_ref_div;
2209 u32 i;
2210#if defined(CONFIG_PPC)
2211 int sense;
2212#endif
2213
2214 init_waitqueue_head(&par->vblank.wait);
2215 spin_lock_init(&par->int_lock);
2216
2217 par->aty_cmap_regs =
2218 (struct aty_cmap_regs __iomem *) (par->ati_regbase + 0xc0);
2219
2220#ifdef CONFIG_PPC_PMAC
2221 /* The Apple iBook1 uses non-standard memory frequencies. We detect it
2222 * and set the frequency manually. */
2223 if (machine_is_compatible("PowerBook2,1")) {
2224 par->pll_limits.mclk = 70;
2225 par->pll_limits.xclk = 53;
2226 }
2227#endif
2228 if (pll)
2229 par->pll_limits.pll_max = pll;
2230 if (mclk)
2231 par->pll_limits.mclk = mclk;
2232 if (xclk)
2233 par->pll_limits.xclk = xclk;
2234
2235 aty_calc_mem_refresh(par, par->pll_limits.xclk);
2236 par->pll_per = 1000000/par->pll_limits.pll_max;
2237 par->mclk_per = 1000000/par->pll_limits.mclk;
2238 par->xclk_per = 1000000/par->pll_limits.xclk;
2239
2240 par->ref_clk_per = 1000000000000ULL / 14318180;
2241 xtal = "14.31818";
2242
2243#ifdef CONFIG_FB_ATY_GX
2244 if (!M64_HAS(INTEGRATED)) {
2245 u32 stat0;
2246 u8 dac_type, dac_subtype, clk_type;
2247 stat0 = aty_ld_le32(CONFIG_STAT0, par);
2248 par->bus_type = (stat0 >> 0) & 0x07;
2249 par->ram_type = (stat0 >> 3) & 0x07;
2250 ramname = aty_gx_ram[par->ram_type];
2251 /* FIXME: clockchip/RAMDAC probing? */
2252 dac_type = (aty_ld_le32(DAC_CNTL, par) >> 16) & 0x07;
2253#ifdef CONFIG_ATARI
2254 clk_type = CLK_ATI18818_1;
2255 dac_type = (stat0 >> 9) & 0x07;
2256 if (dac_type == 0x07)
2257 dac_subtype = DAC_ATT20C408;
2258 else
2259 dac_subtype = (aty_ld_8(SCRATCH_REG1 + 1, par) & 0xF0) | dac_type;
2260#else
2261 dac_type = DAC_IBMRGB514;
2262 dac_subtype = DAC_IBMRGB514;
2263 clk_type = CLK_IBMRGB514;
2264#endif
2265 switch (dac_subtype) {
2266 case DAC_IBMRGB514:
2267 par->dac_ops = &aty_dac_ibm514;
2268 break;
2269 case DAC_ATI68860_B:
2270 case DAC_ATI68860_C:
2271 par->dac_ops = &aty_dac_ati68860b;
2272 break;
2273 case DAC_ATT20C408:
2274 case DAC_ATT21C498:
2275 par->dac_ops = &aty_dac_att21c498;
2276 break;
2277 default:
2278 PRINTKI("aty_init: DAC type not implemented yet!\n");
2279 par->dac_ops = &aty_dac_unsupported;
2280 break;
2281 }
2282 switch (clk_type) {
2283 case CLK_ATI18818_1:
2284 par->pll_ops = &aty_pll_ati18818_1;
2285 break;
2286 case CLK_STG1703:
2287 par->pll_ops = &aty_pll_stg1703;
2288 break;
2289 case CLK_CH8398:
2290 par->pll_ops = &aty_pll_ch8398;
2291 break;
2292 case CLK_ATT20C408:
2293 par->pll_ops = &aty_pll_att20c408;
2294 break;
2295 case CLK_IBMRGB514:
2296 par->pll_ops = &aty_pll_ibm514;
2297 break;
2298 default:
2299 PRINTKI("aty_init: CLK type not implemented yet!");
2300 par->pll_ops = &aty_pll_unsupported;
2301 break;
2302 }
2303 }
2304#endif /* CONFIG_FB_ATY_GX */
2305#ifdef CONFIG_FB_ATY_CT
2306 if (M64_HAS(INTEGRATED)) {
2307 par->dac_ops = &aty_dac_ct;
2308 par->pll_ops = &aty_pll_ct;
2309 par->bus_type = PCI;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 par->ram_type = (aty_ld_le32(CONFIG_STAT0, par) & 0x07);
2311 ramname = aty_ct_ram[par->ram_type];
2312 /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
2313 if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM)
2314 par->pll_limits.mclk = 63;
2315 }
2316
2317 if (M64_HAS(GTB_DSP)
2318 && (pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par))) {
2319 int diff1, diff2;
2320 diff1 = 510 * 14 / pll_ref_div - par->pll_limits.pll_max;
2321 diff2 = 510 * 29 / pll_ref_div - par->pll_limits.pll_max;
2322 if (diff1 < 0)
2323 diff1 = -diff1;
2324 if (diff2 < 0)
2325 diff2 = -diff2;
2326 if (diff2 < diff1) {
2327 par->ref_clk_per = 1000000000000ULL / 29498928;
2328 xtal = "29.498928";
2329 }
2330 }
2331#endif /* CONFIG_FB_ATY_CT */
2332
2333 /* save previous video mode */
2334 aty_get_crtc(par, &saved_crtc);
2335 if(par->pll_ops->get_pll)
2336 par->pll_ops->get_pll(info, &saved_pll);
2337
2338 i = aty_ld_le32(MEM_CNTL, par);
2339 gtb_memsize = M64_HAS(GTB_DSP);
2340 if (gtb_memsize)
2341 switch (i & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */
2342 case MEM_SIZE_512K:
2343 info->fix.smem_len = 0x80000;
2344 break;
2345 case MEM_SIZE_1M:
2346 info->fix.smem_len = 0x100000;
2347 break;
2348 case MEM_SIZE_2M_GTB:
2349 info->fix.smem_len = 0x200000;
2350 break;
2351 case MEM_SIZE_4M_GTB:
2352 info->fix.smem_len = 0x400000;
2353 break;
2354 case MEM_SIZE_6M_GTB:
2355 info->fix.smem_len = 0x600000;
2356 break;
2357 case MEM_SIZE_8M_GTB:
2358 info->fix.smem_len = 0x800000;
2359 break;
2360 default:
2361 info->fix.smem_len = 0x80000;
2362 } else
2363 switch (i & MEM_SIZE_ALIAS) {
2364 case MEM_SIZE_512K:
2365 info->fix.smem_len = 0x80000;
2366 break;
2367 case MEM_SIZE_1M:
2368 info->fix.smem_len = 0x100000;
2369 break;
2370 case MEM_SIZE_2M:
2371 info->fix.smem_len = 0x200000;
2372 break;
2373 case MEM_SIZE_4M:
2374 info->fix.smem_len = 0x400000;
2375 break;
2376 case MEM_SIZE_6M:
2377 info->fix.smem_len = 0x600000;
2378 break;
2379 case MEM_SIZE_8M:
2380 info->fix.smem_len = 0x800000;
2381 break;
2382 default:
2383 info->fix.smem_len = 0x80000;
2384 }
2385
2386 if (M64_HAS(MAGIC_VRAM_SIZE)) {
2387 if (aty_ld_le32(CONFIG_STAT1, par) & 0x40000000)
2388 info->fix.smem_len += 0x400000;
2389 }
2390
2391 if (vram) {
2392 info->fix.smem_len = vram * 1024;
2393 i = i & ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS);
2394 if (info->fix.smem_len <= 0x80000)
2395 i |= MEM_SIZE_512K;
2396 else if (info->fix.smem_len <= 0x100000)
2397 i |= MEM_SIZE_1M;
2398 else if (info->fix.smem_len <= 0x200000)
2399 i |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M;
2400 else if (info->fix.smem_len <= 0x400000)
2401 i |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M;
2402 else if (info->fix.smem_len <= 0x600000)
2403 i |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M;
2404 else
2405 i |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M;
2406 aty_st_le32(MEM_CNTL, i, par);
2407 }
2408
2409 /*
2410 * Reg Block 0 (CT-compatible block) is at mmio_start
2411 * Reg Block 1 (multimedia extensions) is at mmio_start - 0x400
2412 */
2413 if (M64_HAS(GX)) {
2414 info->fix.mmio_len = 0x400;
2415 info->fix.accel = FB_ACCEL_ATI_MACH64GX;
2416 } else if (M64_HAS(CT)) {
2417 info->fix.mmio_len = 0x400;
2418 info->fix.accel = FB_ACCEL_ATI_MACH64CT;
2419 } else if (M64_HAS(VT)) {
2420 info->fix.mmio_start -= 0x400;
2421 info->fix.mmio_len = 0x800;
2422 info->fix.accel = FB_ACCEL_ATI_MACH64VT;
2423 } else {/* GT */
2424 info->fix.mmio_start -= 0x400;
2425 info->fix.mmio_len = 0x800;
2426 info->fix.accel = FB_ACCEL_ATI_MACH64GT;
2427 }
2428
2429 PRINTKI("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK, %d MHz XCLK\n",
2430 info->fix.smem_len == 0x80000 ? 512 : (info->fix.smem_len >> 20),
2431 info->fix.smem_len == 0x80000 ? 'K' : 'M', ramname, xtal, par->pll_limits.pll_max,
2432 par->pll_limits.mclk, par->pll_limits.xclk);
2433
2434#if defined(DEBUG) && defined(CONFIG_ATY_CT)
2435 if (M64_HAS(INTEGRATED)) {
2436 int i;
2437 printk("debug atyfb: BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
2438 "DSP_CONFIG DSP_ON_OFF CLOCK_CNTL\n"
2439 "debug atyfb: %08x %08x %08x %08x %08x %08x %08x %08x\n"
2440 "debug atyfb: PLL",
2441 aty_ld_le32(BUS_CNTL, par), aty_ld_le32(DAC_CNTL, par),
2442 aty_ld_le32(MEM_CNTL, par), aty_ld_le32(EXT_MEM_CNTL, par),
2443 aty_ld_le32(CRTC_GEN_CNTL, par), aty_ld_le32(DSP_CONFIG, par),
2444 aty_ld_le32(DSP_ON_OFF, par), aty_ld_le32(CLOCK_CNTL, par));
2445 for (i = 0; i < 40; i++)
2446 printk(" %02x", aty_ld_pll_ct(i, par));
2447 printk("\n");
2448 }
2449#endif
2450 if(par->pll_ops->init_pll)
2451 par->pll_ops->init_pll(info, &par->pll);
2452
2453 /*
2454 * Last page of 8 MB (4 MB on ISA) aperture is MMIO
2455 * FIXME: we should use the auxiliary aperture instead so we can access
2456 * the full 8 MB of video RAM on 8 MB boards
2457 */
2458
2459 if (!par->aux_start &&
2460 (info->fix.smem_len == 0x800000 || (par->bus_type == ISA && info->fix.smem_len == 0x400000)))
2461 info->fix.smem_len -= GUI_RESERVE;
2462
2463 /*
2464 * Disable register access through the linear aperture
2465 * if the auxiliary aperture is used so we can access
2466 * the full 8 MB of video RAM on 8 MB boards.
2467 */
2468 if (par->aux_start)
2469 aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par);
2470
2471#ifdef CONFIG_MTRR
2472 par->mtrr_aper = -1;
2473 par->mtrr_reg = -1;
2474 if (!nomtrr) {
2475 /* Cover the whole resource. */
2476 par->mtrr_aper = mtrr_add(par->res_start, par->res_size, MTRR_TYPE_WRCOMB, 1);
2477 if (par->mtrr_aper >= 0 && !par->aux_start) {
2478 /* Make a hole for mmio. */
2479 par->mtrr_reg = mtrr_add(par->res_start + 0x800000 - GUI_RESERVE,
2480 GUI_RESERVE, MTRR_TYPE_UNCACHABLE, 1);
2481 if (par->mtrr_reg < 0) {
2482 mtrr_del(par->mtrr_aper, 0, 0);
2483 par->mtrr_aper = -1;
2484 }
2485 }
2486 }
2487#endif
2488
2489 info->fbops = &atyfb_ops;
2490 info->pseudo_palette = pseudo_palette;
2491 info->flags = FBINFO_FLAG_DEFAULT;
2492
2493#ifdef CONFIG_PMAC_BACKLIGHT
2494 if (M64_HAS(G3_PB_1_1) && machine_is_compatible("PowerBook1,1")) {
2495 /* these bits let the 101 powerbook wake up from sleep -- paulus */
2496 aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par)
2497 | (USE_F32KHZ | TRISTATE_MEM_EN), par);
2498 } else if (M64_HAS(MOBIL_BUS))
2499 register_backlight_controller(&aty_backlight_controller, info, "ati");
2500#endif /* CONFIG_PMAC_BACKLIGHT */
2501
2502 memset(&var, 0, sizeof(var));
2503#ifdef CONFIG_PPC
2504 if (_machine == _MACH_Pmac) {
2505 /*
2506 * FIXME: The NVRAM stuff should be put in a Mac-specific file, as it
2507 * applies to all Mac video cards
2508 */
2509 if (mode) {
Antonino A. Daplas1013d262005-11-07 01:00:41 -08002510 if (mac_find_mode(&var, info, mode, 8))
2511 has_var = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512 } else {
2513 if (default_vmode == VMODE_CHOOSE) {
2514 if (M64_HAS(G3_PB_1024x768))
2515 /* G3 PowerBook with 1024x768 LCD */
2516 default_vmode = VMODE_1024_768_60;
2517 else if (machine_is_compatible("iMac"))
2518 default_vmode = VMODE_1024_768_75;
2519 else if (machine_is_compatible
2520 ("PowerBook2,1"))
2521 /* iBook with 800x600 LCD */
2522 default_vmode = VMODE_800_600_60;
2523 else
2524 default_vmode = VMODE_640_480_67;
2525 sense = read_aty_sense(par);
2526 PRINTKI("monitor sense=%x, mode %d\n",
2527 sense, mac_map_monitor_sense(sense));
2528 }
2529 if (default_vmode <= 0 || default_vmode > VMODE_MAX)
2530 default_vmode = VMODE_640_480_60;
2531 if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
2532 default_cmode = CMODE_8;
Antonino A. Daplas1013d262005-11-07 01:00:41 -08002533 if (!mac_vmode_to_var(default_vmode, default_cmode,
2534 &var))
2535 has_var = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536 }
Antonino A. Daplas1013d262005-11-07 01:00:41 -08002537 }
2538
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539#endif /* !CONFIG_PPC */
Antonino A. Daplas1013d262005-11-07 01:00:41 -08002540
2541#if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD)
2542 if (!atyfb_get_timings_from_lcd(par, &var))
2543 has_var = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544#endif
Antonino A. Daplas1013d262005-11-07 01:00:41 -08002545
2546 if (mode && fb_find_mode(&var, info, mode, NULL, 0, &defmode, 8))
2547 has_var = 1;
2548
2549 if (!has_var)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550 var = default_var;
2551
2552 if (noaccel)
2553 var.accel_flags &= ~FB_ACCELF_TEXT;
2554 else
2555 var.accel_flags |= FB_ACCELF_TEXT;
2556
2557 if (comp_sync != -1) {
2558 if (!comp_sync)
2559 var.sync &= ~FB_SYNC_COMP_HIGH_ACT;
2560 else
2561 var.sync |= FB_SYNC_COMP_HIGH_ACT;
2562 }
2563
2564 if (var.yres == var.yres_virtual) {
2565 u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2));
2566 var.yres_virtual = ((videoram * 8) / var.bits_per_pixel) / var.xres_virtual;
2567 if (var.yres_virtual < var.yres)
2568 var.yres_virtual = var.yres;
2569 }
2570
2571 if (atyfb_check_var(&var, info)) {
2572 PRINTKE("can't set default video mode\n");
2573 goto aty_init_exit;
2574 }
2575
2576#ifdef __sparc__
2577 atyfb_save_palette(par, 0);
2578#endif
2579
2580#ifdef CONFIG_FB_ATY_CT
2581 if (!noaccel && M64_HAS(INTEGRATED))
2582 aty_init_cursor(info);
2583#endif /* CONFIG_FB_ATY_CT */
2584 info->var = var;
2585
2586 fb_alloc_cmap(&info->cmap, 256, 0);
2587
2588 if (register_framebuffer(info) < 0)
2589 goto aty_init_exit;
2590
2591 fb_list = info;
2592
2593 PRINTKI("fb%d: %s frame buffer device on %s\n",
2594 info->node, info->fix.id, name);
2595 return 0;
2596
2597aty_init_exit:
2598 /* restore video mode */
2599 aty_set_crtc(par, &saved_crtc);
2600 par->pll_ops->set_pll(info, &saved_pll);
2601
2602#ifdef CONFIG_MTRR
2603 if (par->mtrr_reg >= 0) {
2604 mtrr_del(par->mtrr_reg, 0, 0);
2605 par->mtrr_reg = -1;
2606 }
2607 if (par->mtrr_aper >= 0) {
2608 mtrr_del(par->mtrr_aper, 0, 0);
2609 par->mtrr_aper = -1;
2610 }
2611#endif
2612 return -1;
2613}
2614
2615#ifdef CONFIG_ATARI
2616static int __init store_video_par(char *video_str, unsigned char m64_num)
2617{
2618 char *p;
2619 unsigned long vmembase, size, guiregbase;
2620
2621 PRINTKI("store_video_par() '%s' \n", video_str);
2622
2623 if (!(p = strsep(&video_str, ";")) || !*p)
2624 goto mach64_invalid;
2625 vmembase = simple_strtoul(p, NULL, 0);
2626 if (!(p = strsep(&video_str, ";")) || !*p)
2627 goto mach64_invalid;
2628 size = simple_strtoul(p, NULL, 0);
2629 if (!(p = strsep(&video_str, ";")) || !*p)
2630 goto mach64_invalid;
2631 guiregbase = simple_strtoul(p, NULL, 0);
2632
2633 phys_vmembase[m64_num] = vmembase;
2634 phys_size[m64_num] = size;
2635 phys_guiregbase[m64_num] = guiregbase;
2636 PRINTKI("stored them all: $%08lX $%08lX $%08lX \n", vmembase, size,
2637 guiregbase);
2638 return 0;
2639
2640 mach64_invalid:
2641 phys_vmembase[m64_num] = 0;
2642 return -1;
2643}
2644#endif /* CONFIG_ATARI */
2645
2646 /*
2647 * Blank the display.
2648 */
2649
2650static int atyfb_blank(int blank, struct fb_info *info)
2651{
2652 struct atyfb_par *par = (struct atyfb_par *) info->par;
2653 u8 gen_cntl;
2654
2655 if (par->lock_blank || par->asleep)
2656 return 0;
2657
2658#ifdef CONFIG_PMAC_BACKLIGHT
2659 if ((_machine == _MACH_Pmac) && blank)
2660 set_backlight_enable(0);
2661#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
2662 if (par->lcd_table && blank &&
2663 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
2664 u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2665 pm &= ~PWR_BLON;
2666 aty_st_lcd(POWER_MANAGEMENT, pm, par);
2667 }
2668#endif
2669
2670 gen_cntl = aty_ld_8(CRTC_GEN_CNTL, par);
2671 switch (blank) {
2672 case FB_BLANK_UNBLANK:
2673 gen_cntl &= ~(0x4c);
2674 break;
2675 case FB_BLANK_NORMAL:
2676 gen_cntl |= 0x40;
2677 break;
2678 case FB_BLANK_VSYNC_SUSPEND:
2679 gen_cntl |= 0x8;
2680 break;
2681 case FB_BLANK_HSYNC_SUSPEND:
2682 gen_cntl |= 0x4;
2683 break;
2684 case FB_BLANK_POWERDOWN:
2685 gen_cntl |= 0x4c;
2686 break;
2687 }
2688 aty_st_8(CRTC_GEN_CNTL, gen_cntl, par);
2689
2690#ifdef CONFIG_PMAC_BACKLIGHT
2691 if ((_machine == _MACH_Pmac) && !blank)
2692 set_backlight_enable(1);
2693#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
2694 if (par->lcd_table && !blank &&
2695 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
2696 u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2697 pm |= PWR_BLON;
2698 aty_st_lcd(POWER_MANAGEMENT, pm, par);
2699 }
2700#endif
2701
2702 return 0;
2703}
2704
2705static void aty_st_pal(u_int regno, u_int red, u_int green, u_int blue,
2706 const struct atyfb_par *par)
2707{
2708#ifdef CONFIG_ATARI
2709 out_8(&par->aty_cmap_regs->windex, regno);
2710 out_8(&par->aty_cmap_regs->lut, red);
2711 out_8(&par->aty_cmap_regs->lut, green);
2712 out_8(&par->aty_cmap_regs->lut, blue);
2713#else
2714 writeb(regno, &par->aty_cmap_regs->windex);
2715 writeb(red, &par->aty_cmap_regs->lut);
2716 writeb(green, &par->aty_cmap_regs->lut);
2717 writeb(blue, &par->aty_cmap_regs->lut);
2718#endif
2719}
2720
2721 /*
2722 * Set a single color register. The values supplied are already
2723 * rounded down to the hardware's capabilities (according to the
2724 * entries in the var structure). Return != 0 for invalid regno.
2725 * !! 4 & 8 = PSEUDO, > 8 = DIRECTCOLOR
2726 */
2727
2728static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
2729 u_int transp, struct fb_info *info)
2730{
2731 struct atyfb_par *par = (struct atyfb_par *) info->par;
2732 int i, depth;
2733 u32 *pal = info->pseudo_palette;
2734
2735 depth = info->var.bits_per_pixel;
2736 if (depth == 16)
2737 depth = (info->var.green.length == 5) ? 15 : 16;
2738
2739 if (par->asleep)
2740 return 0;
2741
2742 if (regno > 255 ||
2743 (depth == 16 && regno > 63) ||
2744 (depth == 15 && regno > 31))
2745 return 1;
2746
2747 red >>= 8;
2748 green >>= 8;
2749 blue >>= 8;
2750
2751 par->palette[regno].red = red;
2752 par->palette[regno].green = green;
2753 par->palette[regno].blue = blue;
2754
2755 if (regno < 16) {
2756 switch (depth) {
2757 case 15:
2758 pal[regno] = (regno << 10) | (regno << 5) | regno;
2759 break;
2760 case 16:
2761 pal[regno] = (regno << 11) | (regno << 5) | regno;
2762 break;
2763 case 24:
2764 pal[regno] = (regno << 16) | (regno << 8) | regno;
2765 break;
2766 case 32:
2767 i = (regno << 8) | regno;
2768 pal[regno] = (i << 16) | i;
2769 break;
2770 }
2771 }
2772
2773 i = aty_ld_8(DAC_CNTL, par) & 0xfc;
2774 if (M64_HAS(EXTRA_BRIGHT))
2775 i |= 0x2; /* DAC_CNTL | 0x2 turns off the extra brightness for gt */
2776 aty_st_8(DAC_CNTL, i, par);
2777 aty_st_8(DAC_MASK, 0xff, par);
2778
2779 if (M64_HAS(INTEGRATED)) {
2780 if (depth == 16) {
2781 if (regno < 32)
2782 aty_st_pal(regno << 3, red,
2783 par->palette[regno<<1].green,
2784 blue, par);
2785 red = par->palette[regno>>1].red;
2786 blue = par->palette[regno>>1].blue;
2787 regno <<= 2;
2788 } else if (depth == 15) {
2789 regno <<= 3;
2790 for(i = 0; i < 8; i++) {
2791 aty_st_pal(regno + i, red, green, blue, par);
2792 }
2793 }
2794 }
2795 aty_st_pal(regno, red, green, blue, par);
2796
2797 return 0;
2798}
2799
2800#ifdef CONFIG_PCI
2801
2802#ifdef __sparc__
2803
2804extern void (*prom_palette) (int);
2805
2806static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
2807 struct fb_info *info, unsigned long addr)
2808{
2809 extern int con_is_present(void);
2810
2811 struct atyfb_par *par = info->par;
2812 struct pcidev_cookie *pcp;
2813 char prop[128];
2814 int node, len, i, j, ret;
2815 u32 mem, chip_id;
2816
2817 /* Do not attach when we have a serial console. */
2818 if (!con_is_present())
2819 return -ENXIO;
2820
2821 /*
2822 * Map memory-mapped registers.
2823 */
2824 par->ati_regbase = (void *)addr + 0x7ffc00UL;
2825 info->fix.mmio_start = addr + 0x7ffc00UL;
2826
2827 /*
2828 * Map in big-endian aperture.
2829 */
2830 info->screen_base = (char *) (addr + 0x800000UL);
2831 info->fix.smem_start = addr + 0x800000UL;
2832
2833 /*
2834 * Figure mmap addresses from PCI config space.
2835 * Split Framebuffer in big- and little-endian halfs.
2836 */
2837 for (i = 0; i < 6 && pdev->resource[i].start; i++)
2838 /* nothing */ ;
2839 j = i + 4;
2840
2841 par->mmap_map = kmalloc(j * sizeof(*par->mmap_map), GFP_ATOMIC);
2842 if (!par->mmap_map) {
2843 PRINTKE("atyfb_setup_sparc() can't alloc mmap_map\n");
2844 return -ENOMEM;
2845 }
2846 memset(par->mmap_map, 0, j * sizeof(*par->mmap_map));
2847
2848 for (i = 0, j = 2; i < 6 && pdev->resource[i].start; i++) {
2849 struct resource *rp = &pdev->resource[i];
2850 int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
2851 unsigned long base;
2852 u32 size, pbase;
2853
2854 base = rp->start;
2855
2856 io = (rp->flags & IORESOURCE_IO);
2857
2858 size = rp->end - base + 1;
2859
2860 pci_read_config_dword(pdev, breg, &pbase);
2861
2862 if (io)
2863 size &= ~1;
2864
2865 /*
2866 * Map the framebuffer a second time, this time without
2867 * the braindead _PAGE_IE setting. This is used by the
2868 * fixed Xserver, but we need to maintain the old mapping
2869 * to stay compatible with older ones...
2870 */
2871 if (base == addr) {
2872 par->mmap_map[j].voff = (pbase + 0x10000000) & PAGE_MASK;
2873 par->mmap_map[j].poff = base & PAGE_MASK;
2874 par->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
2875 par->mmap_map[j].prot_mask = _PAGE_CACHE;
2876 par->mmap_map[j].prot_flag = _PAGE_E;
2877 j++;
2878 }
2879
2880 /*
2881 * Here comes the old framebuffer mapping with _PAGE_IE
2882 * set for the big endian half of the framebuffer...
2883 */
2884 if (base == addr) {
2885 par->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK;
2886 par->mmap_map[j].poff = (base + 0x800000) & PAGE_MASK;
2887 par->mmap_map[j].size = 0x800000;
2888 par->mmap_map[j].prot_mask = _PAGE_CACHE;
2889 par->mmap_map[j].prot_flag = _PAGE_E | _PAGE_IE;
2890 size -= 0x800000;
2891 j++;
2892 }
2893
2894 par->mmap_map[j].voff = pbase & PAGE_MASK;
2895 par->mmap_map[j].poff = base & PAGE_MASK;
2896 par->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
2897 par->mmap_map[j].prot_mask = _PAGE_CACHE;
2898 par->mmap_map[j].prot_flag = _PAGE_E;
2899 j++;
2900 }
2901
2902 if((ret = correct_chipset(par)))
2903 return ret;
2904
2905 if (IS_XL(pdev->device)) {
2906 /*
2907 * Fix PROMs idea of MEM_CNTL settings...
2908 */
2909 mem = aty_ld_le32(MEM_CNTL, par);
2910 chip_id = aty_ld_le32(CONFIG_CHIP_ID, par);
2911 if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) && !((chip_id >> 24) & 1)) {
2912 switch (mem & 0x0f) {
2913 case 3:
2914 mem = (mem & ~(0x0f)) | 2;
2915 break;
2916 case 7:
2917 mem = (mem & ~(0x0f)) | 3;
2918 break;
2919 case 9:
2920 mem = (mem & ~(0x0f)) | 4;
2921 break;
2922 case 11:
2923 mem = (mem & ~(0x0f)) | 5;
2924 break;
2925 default:
2926 break;
2927 }
2928 if ((aty_ld_le32(CONFIG_STAT0, par) & 7) >= SDRAM)
2929 mem &= ~(0x00700000);
2930 }
2931 mem &= ~(0xcf80e000); /* Turn off all undocumented bits. */
2932 aty_st_le32(MEM_CNTL, mem, par);
2933 }
2934
2935 /*
2936 * If this is the console device, we will set default video
2937 * settings to what the PROM left us with.
2938 */
2939 node = prom_getchild(prom_root_node);
2940 node = prom_searchsiblings(node, "aliases");
2941 if (node) {
2942 len = prom_getproperty(node, "screen", prop, sizeof(prop));
2943 if (len > 0) {
2944 prop[len] = '\0';
2945 node = prom_finddevice(prop);
2946 } else
2947 node = 0;
2948 }
2949
2950 pcp = pdev->sysdata;
2951 if (node == pcp->prom_node) {
2952 struct fb_var_screeninfo *var = &default_var;
2953 unsigned int N, P, Q, M, T, R;
2954 u32 v_total, h_total;
2955 struct crtc crtc;
2956 u8 pll_regs[16];
2957 u8 clock_cntl;
2958
2959 crtc.vxres = prom_getintdefault(node, "width", 1024);
2960 crtc.vyres = prom_getintdefault(node, "height", 768);
2961 var->bits_per_pixel = prom_getintdefault(node, "depth", 8);
2962 var->xoffset = var->yoffset = 0;
2963 crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
2964 crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
2965 crtc.v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
2966 crtc.v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
2967 crtc.gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
2968 aty_crtc_to_var(&crtc, var);
2969
2970 h_total = var->xres + var->right_margin + var->hsync_len + var->left_margin;
2971 v_total = var->yres + var->lower_margin + var->vsync_len + var->upper_margin;
2972
2973 /*
2974 * Read the PLL to figure actual Refresh Rate.
2975 */
2976 clock_cntl = aty_ld_8(CLOCK_CNTL, par);
2977 /* DPRINTK("CLOCK_CNTL %02x\n", clock_cntl); */
2978 for (i = 0; i < 16; i++)
2979 pll_regs[i] = aty_ld_pll_ct(i, par);
2980
2981 /*
2982 * PLL Reference Divider M:
2983 */
2984 M = pll_regs[2];
2985
2986 /*
2987 * PLL Feedback Divider N (Dependant on CLOCK_CNTL):
2988 */
2989 N = pll_regs[7 + (clock_cntl & 3)];
2990
2991 /*
2992 * PLL Post Divider P (Dependant on CLOCK_CNTL):
2993 */
2994 P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
2995
2996 /*
2997 * PLL Divider Q:
2998 */
2999 Q = N / P;
3000
3001 /*
3002 * Target Frequency:
3003 *
3004 * T * M
3005 * Q = -------
3006 * 2 * R
3007 *
3008 * where R is XTALIN (= 14318 or 29498 kHz).
3009 */
3010 if (IS_XL(pdev->device))
3011 R = 29498;
3012 else
3013 R = 14318;
3014
3015 T = 2 * Q * R / M;
3016
3017 default_var.pixclock = 1000000000 / T;
3018 }
3019
3020 return 0;
3021}
3022
3023#else /* __sparc__ */
3024
3025#ifdef __i386__
3026#ifdef CONFIG_FB_ATY_GENERIC_LCD
3027static void aty_init_lcd(struct atyfb_par *par, u32 bios_base)
3028{
3029 u32 driv_inf_tab, sig;
3030 u16 lcd_ofs;
3031
3032 /* To support an LCD panel, we should know it's dimensions and
3033 * it's desired pixel clock.
3034 * There are two ways to do it:
3035 * - Check the startup video mode and calculate the panel
3036 * size from it. This is unreliable.
3037 * - Read it from the driver information table in the video BIOS.
3038 */
3039 /* Address of driver information table is at offset 0x78. */
3040 driv_inf_tab = bios_base + *((u16 *)(bios_base+0x78));
3041
3042 /* Check for the driver information table signature. */
3043 sig = (*(u32 *)driv_inf_tab);
3044 if ((sig == 0x54504c24) || /* Rage LT pro */
3045 (sig == 0x544d5224) || /* Rage mobility */
3046 (sig == 0x54435824) || /* Rage XC */
3047 (sig == 0x544c5824)) { /* Rage XL */
3048 PRINTKI("BIOS contains driver information table.\n");
3049 lcd_ofs = (*(u16 *)(driv_inf_tab + 10));
3050 par->lcd_table = 0;
3051 if (lcd_ofs != 0) {
3052 par->lcd_table = bios_base + lcd_ofs;
3053 }
3054 }
3055
3056 if (par->lcd_table != 0) {
3057 char model[24];
3058 char strbuf[16];
3059 char refresh_rates_buf[100];
3060 int id, tech, f, i, m, default_refresh_rate;
3061 char *txtcolour;
3062 char *txtmonitor;
3063 char *txtdual;
3064 char *txtformat;
3065 u16 width, height, panel_type, refresh_rates;
3066 u16 *lcdmodeptr;
3067 u32 format;
3068 u8 lcd_refresh_rates[16] = {50,56,60,67,70,72,75,76,85,90,100,120,140,150,160,200};
3069 /* The most important information is the panel size at
3070 * offset 25 and 27, but there's some other nice information
3071 * which we print to the screen.
3072 */
3073 id = *(u8 *)par->lcd_table;
3074 strncpy(model,(char *)par->lcd_table+1,24);
3075 model[23]=0;
3076
3077 width = par->lcd_width = *(u16 *)(par->lcd_table+25);
3078 height = par->lcd_height = *(u16 *)(par->lcd_table+27);
3079 panel_type = *(u16 *)(par->lcd_table+29);
3080 if (panel_type & 1)
3081 txtcolour = "colour";
3082 else
3083 txtcolour = "monochrome";
3084 if (panel_type & 2)
3085 txtdual = "dual (split) ";
3086 else
3087 txtdual = "";
3088 tech = (panel_type>>2) & 63;
3089 switch (tech) {
3090 case 0:
3091 txtmonitor = "passive matrix";
3092 break;
3093 case 1:
3094 txtmonitor = "active matrix";
3095 break;
3096 case 2:
3097 txtmonitor = "active addressed STN";
3098 break;
3099 case 3:
3100 txtmonitor = "EL";
3101 break;
3102 case 4:
3103 txtmonitor = "plasma";
3104 break;
3105 default:
3106 txtmonitor = "unknown";
3107 }
3108 format = *(u32 *)(par->lcd_table+57);
3109 if (tech == 0 || tech == 2) {
3110 switch (format & 7) {
3111 case 0:
3112 txtformat = "12 bit interface";
3113 break;
3114 case 1:
3115 txtformat = "16 bit interface";
3116 break;
3117 case 2:
3118 txtformat = "24 bit interface";
3119 break;
3120 default:
3121 txtformat = "unkown format";
3122 }
3123 } else {
3124 switch (format & 7) {
3125 case 0:
3126 txtformat = "8 colours";
3127 break;
3128 case 1:
3129 txtformat = "512 colours";
3130 break;
3131 case 2:
3132 txtformat = "4096 colours";
3133 break;
3134 case 4:
3135 txtformat = "262144 colours (LT mode)";
3136 break;
3137 case 5:
3138 txtformat = "16777216 colours";
3139 break;
3140 case 6:
3141 txtformat = "262144 colours (FDPI-2 mode)";
3142 break;
3143 default:
3144 txtformat = "unkown format";
3145 }
3146 }
3147 PRINTKI("%s%s %s monitor detected: %s\n",
3148 txtdual ,txtcolour, txtmonitor, model);
3149 PRINTKI(" id=%d, %dx%d pixels, %s\n",
3150 id, width, height, txtformat);
3151 refresh_rates_buf[0] = 0;
3152 refresh_rates = *(u16 *)(par->lcd_table+62);
3153 m = 1;
3154 f = 0;
3155 for (i=0;i<16;i++) {
3156 if (refresh_rates & m) {
3157 if (f == 0) {
3158 sprintf(strbuf, "%d", lcd_refresh_rates[i]);
3159 f++;
3160 } else {
3161 sprintf(strbuf, ",%d", lcd_refresh_rates[i]);
3162 }
3163 strcat(refresh_rates_buf,strbuf);
3164 }
3165 m = m << 1;
3166 }
3167 default_refresh_rate = (*(u8 *)(par->lcd_table+61) & 0xf0) >> 4;
3168 PRINTKI(" supports refresh rates [%s], default %d Hz\n",
3169 refresh_rates_buf, lcd_refresh_rates[default_refresh_rate]);
3170 par->lcd_refreshrate = lcd_refresh_rates[default_refresh_rate];
3171 /* We now need to determine the crtc parameters for the
Ville Syrjäläcd4617b2006-01-09 20:53:21 -08003172 * LCD monitor. This is tricky, because they are not stored
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173 * individually in the BIOS. Instead, the BIOS contains a
3174 * table of display modes that work for this monitor.
3175 *
3176 * The idea is that we search for a mode of the same dimensions
Ville Syrjäläcd4617b2006-01-09 20:53:21 -08003177 * as the dimensions of the LCD monitor. Say our LCD monitor
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178 * is 800x600 pixels, we search for a 800x600 monitor.
3179 * The CRTC parameters we find here are the ones that we need
Ville Syrjäläcd4617b2006-01-09 20:53:21 -08003180 * to use to simulate other resolutions on the LCD screen.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003181 */
3182 lcdmodeptr = (u16 *)(par->lcd_table + 64);
3183 while (*lcdmodeptr != 0) {
3184 u32 modeptr;
3185 u16 mwidth, mheight, lcd_hsync_start, lcd_vsync_start;
3186 modeptr = bios_base + *lcdmodeptr;
3187
3188 mwidth = *((u16 *)(modeptr+0));
3189 mheight = *((u16 *)(modeptr+2));
3190
3191 if (mwidth == width && mheight == height) {
3192 par->lcd_pixclock = 100000000 / *((u16 *)(modeptr+9));
3193 par->lcd_htotal = *((u16 *)(modeptr+17)) & 511;
3194 par->lcd_hdisp = *((u16 *)(modeptr+19)) & 511;
3195 lcd_hsync_start = *((u16 *)(modeptr+21)) & 511;
3196 par->lcd_hsync_dly = (*((u16 *)(modeptr+21)) >> 9) & 7;
3197 par->lcd_hsync_len = *((u8 *)(modeptr+23)) & 63;
3198
3199 par->lcd_vtotal = *((u16 *)(modeptr+24)) & 2047;
3200 par->lcd_vdisp = *((u16 *)(modeptr+26)) & 2047;
3201 lcd_vsync_start = *((u16 *)(modeptr+28)) & 2047;
3202 par->lcd_vsync_len = (*((u16 *)(modeptr+28)) >> 11) & 31;
3203
3204 par->lcd_htotal = (par->lcd_htotal + 1) * 8;
3205 par->lcd_hdisp = (par->lcd_hdisp + 1) * 8;
3206 lcd_hsync_start = (lcd_hsync_start + 1) * 8;
3207 par->lcd_hsync_len = par->lcd_hsync_len * 8;
3208
3209 par->lcd_vtotal++;
3210 par->lcd_vdisp++;
3211 lcd_vsync_start++;
3212
3213 par->lcd_right_margin = lcd_hsync_start - par->lcd_hdisp;
3214 par->lcd_lower_margin = lcd_vsync_start - par->lcd_vdisp;
3215 par->lcd_hblank_len = par->lcd_htotal - par->lcd_hdisp;
3216 par->lcd_vblank_len = par->lcd_vtotal - par->lcd_vdisp;
3217 break;
3218 }
3219
3220 lcdmodeptr++;
3221 }
3222 if (*lcdmodeptr == 0) {
3223 PRINTKE("LCD monitor CRTC parameters not found!!!\n");
3224 /* To do: Switch to CRT if possible. */
3225 } else {
3226 PRINTKI(" LCD CRTC parameters: %d.%d %d %d %d %d %d %d %d %d\n",
3227 1000000 / par->lcd_pixclock, 1000000 % par->lcd_pixclock,
3228 par->lcd_hdisp,
3229 par->lcd_hdisp + par->lcd_right_margin,
3230 par->lcd_hdisp + par->lcd_right_margin
3231 + par->lcd_hsync_dly + par->lcd_hsync_len,
3232 par->lcd_htotal,
3233 par->lcd_vdisp,
3234 par->lcd_vdisp + par->lcd_lower_margin,
3235 par->lcd_vdisp + par->lcd_lower_margin + par->lcd_vsync_len,
3236 par->lcd_vtotal);
3237 PRINTKI(" : %d %d %d %d %d %d %d %d %d\n",
3238 par->lcd_pixclock,
3239 par->lcd_hblank_len - (par->lcd_right_margin +
3240 par->lcd_hsync_dly + par->lcd_hsync_len),
3241 par->lcd_hdisp,
3242 par->lcd_right_margin,
3243 par->lcd_hsync_len,
3244 par->lcd_vblank_len - (par->lcd_lower_margin + par->lcd_vsync_len),
3245 par->lcd_vdisp,
3246 par->lcd_lower_margin,
3247 par->lcd_vsync_len);
3248 }
3249 }
3250}
3251#endif /* CONFIG_FB_ATY_GENERIC_LCD */
3252
3253static int __devinit init_from_bios(struct atyfb_par *par)
3254{
3255 u32 bios_base, rom_addr;
3256 int ret;
3257
3258 rom_addr = 0xc0000 + ((aty_ld_le32(SCRATCH_REG1, par) & 0x7f) << 11);
3259 bios_base = (unsigned long)ioremap(rom_addr, 0x10000);
3260
3261 /* The BIOS starts with 0xaa55. */
3262 if (*((u16 *)bios_base) == 0xaa55) {
3263
3264 u8 *bios_ptr;
3265 u16 rom_table_offset, freq_table_offset;
3266 PLL_BLOCK_MACH64 pll_block;
3267
3268 PRINTKI("Mach64 BIOS is located at %x, mapped at %x.\n", rom_addr, bios_base);
3269
3270 /* check for frequncy table */
3271 bios_ptr = (u8*)bios_base;
3272 rom_table_offset = (u16)(bios_ptr[0x48] | (bios_ptr[0x49] << 8));
3273 freq_table_offset = bios_ptr[rom_table_offset + 16] | (bios_ptr[rom_table_offset + 17] << 8);
3274 memcpy(&pll_block, bios_ptr + freq_table_offset, sizeof(PLL_BLOCK_MACH64));
3275
3276 PRINTKI("BIOS frequency table:\n");
3277 PRINTKI("PCLK_min_freq %d, PCLK_max_freq %d, ref_freq %d, ref_divider %d\n",
3278 pll_block.PCLK_min_freq, pll_block.PCLK_max_freq,
3279 pll_block.ref_freq, pll_block.ref_divider);
3280 PRINTKI("MCLK_pwd %d, MCLK_max_freq %d, XCLK_max_freq %d, SCLK_freq %d\n",
3281 pll_block.MCLK_pwd, pll_block.MCLK_max_freq,
3282 pll_block.XCLK_max_freq, pll_block.SCLK_freq);
3283
3284 par->pll_limits.pll_min = pll_block.PCLK_min_freq/100;
3285 par->pll_limits.pll_max = pll_block.PCLK_max_freq/100;
3286 par->pll_limits.ref_clk = pll_block.ref_freq/100;
3287 par->pll_limits.ref_div = pll_block.ref_divider;
3288 par->pll_limits.sclk = pll_block.SCLK_freq/100;
3289 par->pll_limits.mclk = pll_block.MCLK_max_freq/100;
3290 par->pll_limits.mclk_pm = pll_block.MCLK_pwd/100;
3291 par->pll_limits.xclk = pll_block.XCLK_max_freq/100;
3292#ifdef CONFIG_FB_ATY_GENERIC_LCD
3293 aty_init_lcd(par, bios_base);
3294#endif
3295 ret = 0;
3296 } else {
3297 PRINTKE("no BIOS frequency table found, use parameters\n");
3298 ret = -ENXIO;
3299 }
3300 iounmap((void* __iomem )bios_base);
3301
3302 return ret;
3303}
3304#endif /* __i386__ */
3305
3306static int __devinit atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info, unsigned long addr)
3307{
3308 struct atyfb_par *par = info->par;
3309 u16 tmp;
3310 unsigned long raddr;
3311 struct resource *rrp;
3312 int ret = 0;
3313
3314 raddr = addr + 0x7ff000UL;
3315 rrp = &pdev->resource[2];
3316 if ((rrp->flags & IORESOURCE_MEM) && request_mem_region(rrp->start, rrp->end - rrp->start + 1, "atyfb")) {
3317 par->aux_start = rrp->start;
3318 par->aux_size = rrp->end - rrp->start + 1;
3319 raddr = rrp->start;
3320 PRINTKI("using auxiliary register aperture\n");
3321 }
3322
3323 info->fix.mmio_start = raddr;
3324 par->ati_regbase = ioremap(info->fix.mmio_start, 0x1000);
3325 if (par->ati_regbase == 0)
3326 return -ENOMEM;
3327
3328 info->fix.mmio_start += par->aux_start ? 0x400 : 0xc00;
3329 par->ati_regbase += par->aux_start ? 0x400 : 0xc00;
3330
3331 /*
3332 * Enable memory-space accesses using config-space
3333 * command register.
3334 */
3335 pci_read_config_word(pdev, PCI_COMMAND, &tmp);
3336 if (!(tmp & PCI_COMMAND_MEMORY)) {
3337 tmp |= PCI_COMMAND_MEMORY;
3338 pci_write_config_word(pdev, PCI_COMMAND, tmp);
3339 }
3340#ifdef __BIG_ENDIAN
3341 /* Use the big-endian aperture */
3342 addr += 0x800000;
3343#endif
3344
3345 /* Map in frame buffer */
3346 info->fix.smem_start = addr;
3347 info->screen_base = ioremap(addr, 0x800000);
3348 if (info->screen_base == NULL) {
3349 ret = -ENOMEM;
3350 goto atyfb_setup_generic_fail;
3351 }
3352
3353 if((ret = correct_chipset(par)))
3354 goto atyfb_setup_generic_fail;
3355#ifdef __i386__
3356 if((ret = init_from_bios(par)))
3357 goto atyfb_setup_generic_fail;
3358#endif
3359 if (!(aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_EXT_DISP_EN))
3360 par->clk_wr_offset = (inb(R_GENMO) & 0x0CU) >> 2;
3361 else
3362 par->clk_wr_offset = aty_ld_8(CLOCK_CNTL, par) & 0x03U;
3363
3364 /* according to ATI, we should use clock 3 for acelerated mode */
3365 par->clk_wr_offset = 3;
3366
3367 return 0;
3368
3369atyfb_setup_generic_fail:
3370 iounmap(par->ati_regbase);
3371 par->ati_regbase = NULL;
3372 return ret;
3373}
3374
3375#endif /* !__sparc__ */
3376
3377static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
3378{
3379 unsigned long addr, res_start, res_size;
3380 struct fb_info *info;
3381 struct resource *rp;
3382 struct atyfb_par *par;
3383 int i, rc = -ENOMEM;
3384
3385 for (i = sizeof(aty_chips) / sizeof(*aty_chips) - 1; i >= 0; i--)
3386 if (pdev->device == aty_chips[i].pci_id)
3387 break;
3388
3389 if (i < 0)
3390 return -ENODEV;
3391
3392 /* Enable device in PCI config */
3393 if (pci_enable_device(pdev)) {
3394 PRINTKE("Cannot enable PCI device\n");
3395 return -ENXIO;
3396 }
3397
3398 /* Find which resource to use */
3399 rp = &pdev->resource[0];
3400 if (rp->flags & IORESOURCE_IO)
3401 rp = &pdev->resource[1];
3402 addr = rp->start;
3403 if (!addr)
3404 return -ENXIO;
3405
3406 /* Reserve space */
3407 res_start = rp->start;
3408 res_size = rp->end - rp->start + 1;
3409 if (!request_mem_region (res_start, res_size, "atyfb"))
3410 return -EBUSY;
3411
3412 /* Allocate framebuffer */
3413 info = framebuffer_alloc(sizeof(struct atyfb_par), &pdev->dev);
3414 if (!info) {
3415 PRINTKE("atyfb_pci_probe() can't alloc fb_info\n");
3416 return -ENOMEM;
3417 }
3418 par = info->par;
3419 info->fix = atyfb_fix;
3420 info->device = &pdev->dev;
3421 par->pci_id = aty_chips[i].pci_id;
3422 par->res_start = res_start;
3423 par->res_size = res_size;
3424 par->irq = pdev->irq;
3425
3426 /* Setup "info" structure */
3427#ifdef __sparc__
3428 rc = atyfb_setup_sparc(pdev, info, addr);
3429#else
3430 rc = atyfb_setup_generic(pdev, info, addr);
3431#endif
3432 if (rc)
3433 goto err_release_mem;
3434
3435 pci_set_drvdata(pdev, info);
3436
3437 /* Init chip & register framebuffer */
3438 if (aty_init(info, "PCI"))
3439 goto err_release_io;
3440
3441#ifdef __sparc__
3442 if (!prom_palette)
3443 prom_palette = atyfb_palette;
3444
3445 /*
3446 * Add /dev/fb mmap values.
3447 */
3448 par->mmap_map[0].voff = 0x8000000000000000UL;
3449 par->mmap_map[0].poff = (unsigned long) info->screen_base & PAGE_MASK;
3450 par->mmap_map[0].size = info->fix.smem_len;
3451 par->mmap_map[0].prot_mask = _PAGE_CACHE;
3452 par->mmap_map[0].prot_flag = _PAGE_E;
3453 par->mmap_map[1].voff = par->mmap_map[0].voff + info->fix.smem_len;
3454 par->mmap_map[1].poff = (long)par->ati_regbase & PAGE_MASK;
3455 par->mmap_map[1].size = PAGE_SIZE;
3456 par->mmap_map[1].prot_mask = _PAGE_CACHE;
3457 par->mmap_map[1].prot_flag = _PAGE_E;
3458#endif /* __sparc__ */
3459
3460 return 0;
3461
3462err_release_io:
3463#ifdef __sparc__
3464 kfree(par->mmap_map);
3465#else
3466 if (par->ati_regbase)
3467 iounmap(par->ati_regbase);
3468 if (info->screen_base)
3469 iounmap(info->screen_base);
3470#endif
3471err_release_mem:
3472 if (par->aux_start)
3473 release_mem_region(par->aux_start, par->aux_size);
3474
3475 release_mem_region(par->res_start, par->res_size);
3476 framebuffer_release(info);
3477
3478 return rc;
3479}
3480
3481#endif /* CONFIG_PCI */
3482
3483#ifdef CONFIG_ATARI
3484
3485static int __devinit atyfb_atari_probe(void)
3486{
3487 struct aty_par *par;
3488 struct fb_info *info;
3489 int m64_num;
3490 u32 clock_r;
3491
3492 for (m64_num = 0; m64_num < mach64_count; m64_num++) {
3493 if (!phys_vmembase[m64_num] || !phys_size[m64_num] ||
3494 !phys_guiregbase[m64_num]) {
3495 PRINTKI("phys_*[%d] parameters not set => returning early. \n", m64_num);
3496 continue;
3497 }
3498
3499 info = framebuffer_alloc(sizeof(struct atyfb_par), NULL);
3500 if (!info) {
3501 PRINTKE("atyfb_atari_probe() can't alloc fb_info\n");
3502 return -ENOMEM;
3503 }
3504 par = info->par;
3505
3506 info->fix = atyfb_fix;
3507
3508 par->irq = (unsigned int) -1; /* something invalid */
3509
3510 /*
3511 * Map the video memory (physical address given) to somewhere in the
3512 * kernel address space.
3513 */
3514 info->screen_base = ioremap(phys_vmembase[m64_num], phys_size[m64_num]);
3515 info->fix.smem_start = (unsigned long)info->screen_base; /* Fake! */
3516 par->ati_regbase = ioremap(phys_guiregbase[m64_num], 0x10000) +
3517 0xFC00ul;
3518 info->fix.mmio_start = (unsigned long)par->ati_regbase; /* Fake! */
3519
3520 aty_st_le32(CLOCK_CNTL, 0x12345678, par);
3521 clock_r = aty_ld_le32(CLOCK_CNTL, par);
3522
3523 switch (clock_r & 0x003F) {
3524 case 0x12:
3525 par->clk_wr_offset = 3; /* */
3526 break;
3527 case 0x34:
3528 par->clk_wr_offset = 2; /* Medusa ST-IO ISA Adapter etc. */
3529 break;
3530 case 0x16:
3531 par->clk_wr_offset = 1; /* */
3532 break;
3533 case 0x38:
3534 par->clk_wr_offset = 0; /* Panther 1 ISA Adapter (Gerald) */
3535 break;
3536 }
3537
3538 if (aty_init(info, "ISA bus")) {
3539 framebuffer_release(info);
3540 /* This is insufficient! kernel_map has added two large chunks!! */
3541 return -ENXIO;
3542 }
3543 }
3544}
3545
3546#endif /* CONFIG_ATARI */
3547
3548static void __devexit atyfb_remove(struct fb_info *info)
3549{
3550 struct atyfb_par *par = (struct atyfb_par *) info->par;
3551
3552 /* restore video mode */
3553 aty_set_crtc(par, &saved_crtc);
3554 par->pll_ops->set_pll(info, &saved_pll);
3555
3556 unregister_framebuffer(info);
3557
3558#ifdef CONFIG_MTRR
3559 if (par->mtrr_reg >= 0) {
3560 mtrr_del(par->mtrr_reg, 0, 0);
3561 par->mtrr_reg = -1;
3562 }
3563 if (par->mtrr_aper >= 0) {
3564 mtrr_del(par->mtrr_aper, 0, 0);
3565 par->mtrr_aper = -1;
3566 }
3567#endif
3568#ifndef __sparc__
3569 if (par->ati_regbase)
3570 iounmap(par->ati_regbase);
3571 if (info->screen_base)
3572 iounmap(info->screen_base);
3573#ifdef __BIG_ENDIAN
3574 if (info->sprite.addr)
3575 iounmap(info->sprite.addr);
3576#endif
3577#endif
3578#ifdef __sparc__
3579 kfree(par->mmap_map);
3580#endif
3581 if (par->aux_start)
3582 release_mem_region(par->aux_start, par->aux_size);
3583
3584 if (par->res_start)
3585 release_mem_region(par->res_start, par->res_size);
3586
3587 framebuffer_release(info);
3588}
3589
3590#ifdef CONFIG_PCI
3591
3592static void __devexit atyfb_pci_remove(struct pci_dev *pdev)
3593{
3594 struct fb_info *info = pci_get_drvdata(pdev);
3595
3596 atyfb_remove(info);
3597}
3598
3599/*
3600 * This driver uses its own matching table. That will be more difficult
3601 * to fix, so for now, we just match against any ATI ID and let the
3602 * probe() function find out what's up. That also mean we don't have
3603 * a module ID table though.
3604 */
3605static struct pci_device_id atyfb_pci_tbl[] = {
3606 { PCI_VENDOR_ID_ATI, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
3607 PCI_BASE_CLASS_DISPLAY << 16, 0xff0000, 0 },
3608 { 0, }
3609};
3610
3611static struct pci_driver atyfb_driver = {
3612 .name = "atyfb",
3613 .id_table = atyfb_pci_tbl,
3614 .probe = atyfb_pci_probe,
3615 .remove = __devexit_p(atyfb_pci_remove),
3616#ifdef CONFIG_PM
3617 .suspend = atyfb_pci_suspend,
3618 .resume = atyfb_pci_resume,
3619#endif /* CONFIG_PM */
3620};
3621
3622#endif /* CONFIG_PCI */
3623
3624#ifndef MODULE
3625static int __init atyfb_setup(char *options)
3626{
3627 char *this_opt;
3628
3629 if (!options || !*options)
3630 return 0;
3631
3632 while ((this_opt = strsep(&options, ",")) != NULL) {
3633 if (!strncmp(this_opt, "noaccel", 7)) {
3634 noaccel = 1;
3635#ifdef CONFIG_MTRR
3636 } else if (!strncmp(this_opt, "nomtrr", 6)) {
3637 nomtrr = 1;
3638#endif
3639 } else if (!strncmp(this_opt, "vram:", 5))
3640 vram = simple_strtoul(this_opt + 5, NULL, 0);
3641 else if (!strncmp(this_opt, "pll:", 4))
3642 pll = simple_strtoul(this_opt + 4, NULL, 0);
3643 else if (!strncmp(this_opt, "mclk:", 5))
3644 mclk = simple_strtoul(this_opt + 5, NULL, 0);
3645 else if (!strncmp(this_opt, "xclk:", 5))
3646 xclk = simple_strtoul(this_opt+5, NULL, 0);
3647 else if (!strncmp(this_opt, "comp_sync:", 10))
3648 comp_sync = simple_strtoul(this_opt+10, NULL, 0);
3649#ifdef CONFIG_PPC
3650 else if (!strncmp(this_opt, "vmode:", 6)) {
3651 unsigned int vmode =
3652 simple_strtoul(this_opt + 6, NULL, 0);
3653 if (vmode > 0 && vmode <= VMODE_MAX)
3654 default_vmode = vmode;
3655 } else if (!strncmp(this_opt, "cmode:", 6)) {
3656 unsigned int cmode =
3657 simple_strtoul(this_opt + 6, NULL, 0);
3658 switch (cmode) {
3659 case 0:
3660 case 8:
3661 default_cmode = CMODE_8;
3662 break;
3663 case 15:
3664 case 16:
3665 default_cmode = CMODE_16;
3666 break;
3667 case 24:
3668 case 32:
3669 default_cmode = CMODE_32;
3670 break;
3671 }
3672 }
3673#endif
3674#ifdef CONFIG_ATARI
3675 /*
3676 * Why do we need this silly Mach64 argument?
3677 * We are already here because of mach64= so its redundant.
3678 */
3679 else if (MACH_IS_ATARI
3680 && (!strncmp(this_opt, "Mach64:", 7))) {
3681 static unsigned char m64_num;
3682 static char mach64_str[80];
3683 strlcpy(mach64_str, this_opt + 7, sizeof(mach64_str));
3684 if (!store_video_par(mach64_str, m64_num)) {
3685 m64_num++;
3686 mach64_count = m64_num;
3687 }
3688 }
3689#endif
3690 else
3691 mode = this_opt;
3692 }
3693 return 0;
3694}
3695#endif /* MODULE */
3696
3697static int __init atyfb_init(void)
3698{
3699#ifndef MODULE
3700 char *option = NULL;
3701
3702 if (fb_get_options("atyfb", &option))
3703 return -ENODEV;
3704 atyfb_setup(option);
3705#endif
3706
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707 pci_register_driver(&atyfb_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708#ifdef CONFIG_ATARI
3709 atyfb_atari_probe();
3710#endif
3711 return 0;
3712}
3713
3714static void __exit atyfb_exit(void)
3715{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003716 pci_unregister_driver(&atyfb_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003717}
3718
3719module_init(atyfb_init);
3720module_exit(atyfb_exit);
3721
3722MODULE_DESCRIPTION("FBDev driver for ATI Mach64 cards");
3723MODULE_LICENSE("GPL");
3724module_param(noaccel, bool, 0);
3725MODULE_PARM_DESC(noaccel, "bool: disable acceleration");
3726module_param(vram, int, 0);
3727MODULE_PARM_DESC(vram, "int: override size of video ram");
3728module_param(pll, int, 0);
3729MODULE_PARM_DESC(pll, "int: override video clock");
3730module_param(mclk, int, 0);
3731MODULE_PARM_DESC(mclk, "int: override memory clock");
3732module_param(xclk, int, 0);
3733MODULE_PARM_DESC(xclk, "int: override accelerated engine clock");
3734module_param(comp_sync, int, 0);
3735MODULE_PARM_DESC(comp_sync,
3736 "Set composite sync signal to low (0) or high (1)");
3737module_param(mode, charp, 0);
3738MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
3739#ifdef CONFIG_MTRR
3740module_param(nomtrr, bool, 0);
3741MODULE_PARM_DESC(nomtrr, "bool: disable use of MTRR registers");
3742#endif