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

source code of linux/drivers/video/fbdev/aty/atyfb_base.c