* Re: URGENT: status of atyfb
2004-08-03 21:25 ` Benjamin Herrenschmidt
2004-08-03 22:05 ` Ville Syrjälä
@ 2004-08-06 6:09 ` Alexander Kern
2004-08-06 8:10 ` Benjamin Herrenschmidt
1 sibling, 1 reply; 7+ messages in thread
From: Alexander Kern @ 2004-08-06 6:09 UTC (permalink / raw)
To: linux-fbdev-devel; +Cc: Benjamin Herrenschmidt, Ville Syrjälä
[-- Attachment #1: Type: text/plain, Size: 1519 bytes --]
Am Dienstag, 3. August 2004 23:25 schrieb Benjamin Herrenschmidt:
> > Hi, I do not have any information or hardware about PPC. Should it own
> > something like OpenFirmware? In this case it is possible to read clock
> > information from this.
>
> On some models, yes, on some no. Older machines have a firmware that
> won't tell you anything, the MacOS driver back then was hard coding the
> values.
>
> Anyway, the clocks are ok, apparently (maybe not the engine one though,
> see later), the problem was that the DLL magic was reverted for the
> LT-G, plus some minor issues with the driver blowing up on non-BIOS
> machines that I can fix.
>
> The engine tends to lockup quickly though, I'll do experiments.
>
> > I found, that we change a little behaviour. Please give a try for this
> > patch...
>
> Your patch seem to address the DLL issue, I did that too, fixes the
> display, I'll toy around and let you know.
>
> Also, when just dropping the existing driver into the current linus tree,
> the cursor code is blowing up, I don't know why yet, I suppose some changes
> to the common code in the fbdev tree. I'll have a look.
>
> I really want this new driver to be sent upstream ASAP. What I may do is
> once I get it working well enough, I'll send it to andrew for the -mm tree
> and leave it there for a while to get it properly tested.
>
> Ben.
Hi, here a snapshot from my tree over 2.6.7 + js3
Changes:
revert SDRAM_MAGIC_PLL to old behaviour
do a "from BIOS" initialisation only by __i386__
Regards
Alex
[-- Attachment #2: mach64-js3-ak6a.diff --]
[-- Type: text/x-diff, Size: 78050 bytes --]
diff -ur -X patches/exclude linux-2.6.7.js3/drivers/video/aty/atyfb.h linux-2.6.7.ak/drivers/video/aty/atyfb.h
--- linux-2.6.7.js3/drivers/video/aty/atyfb.h 2004-06-27 01:35:27.000000000 +0200
+++ linux-2.6.7.ak/drivers/video/aty/atyfb.h 2004-08-04 22:25:21.000000000 +0200
@@ -3,6 +3,8 @@
*/
#include <linux/config.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
/*
* Elements of the hardware specific atyfb_par structure
*/
@@ -30,9 +32,18 @@
u32 shadow_h_sync_strt_wid;
u32 shadow_v_tot_disp;
u32 shadow_v_sync_strt_wid;
+ u32 lcd_gen_cntl;
+ u32 lcd_config_panel;
+ u32 lcd_index;
#endif
};
+struct aty_interrupt {
+ wait_queue_head_t wait;
+ unsigned int count;
+ int pan_display;
+};
+
struct pll_info {
int pll_max;
int pll_min;
@@ -116,6 +127,7 @@
struct atyfb_par {
struct aty_cmap_regs *aty_cmap_regs;
+ struct { u8 red, green, blue; } palette[256];
const struct aty_dac_ops *dac_ops;
const struct aty_pll_ops *pll_ops;
unsigned long ati_regbase;
@@ -141,8 +153,8 @@
#ifdef __sparc__
struct pci_mmap_map *mmap_map;
u8 mmaped;
- int open;
#endif
+ int open;
#ifdef CONFIG_FB_ATY_GENERIC_LCD
unsigned long bios_base_phys;
unsigned long bios_base;
@@ -165,6 +177,10 @@
#endif
unsigned long aux_start; /* auxiliary aperture */
unsigned long aux_size;
+ struct aty_interrupt vblank;
+ unsigned long irq_flags;
+ unsigned int irq;
+ spinlock_t int_lock;
};
/*
@@ -177,7 +193,7 @@
#define M64F_MAGIC_FIFO 0x00000002
#define M64F_GTB_DSP 0x00000004
#define M64F_FIFO_32 0x00000008
-#define M64F_NO_EXT_PLL 0x00000010
+#define M64F_SDRAM_MAGIC_PLL 0x00000010
#define M64F_MAGIC_POSTDIV 0x00000020
#define M64F_INTEGRATED 0x00000040
#define M64F_CT_BUS 0x00000080
@@ -191,7 +207,7 @@
#define M64F_G3_PB_1_1 0x00008000
#define M64F_G3_PB_1024x768 0x00010000
#define M64F_EXTRA_BRIGHT 0x00020000
-#define M64F_LT_SLEEP 0x00040000
+#define M64F_LT_LCD_REGS 0x00040000
#define M64F_XL_DLL 0x00080000
#define M64F_MFB_FORCE_4 0x00100000
#define M64F_HW_TRIPLE 0x00200000
@@ -251,6 +267,11 @@
#endif
}
+#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD)
+extern void aty_st_lcd(int index, u32 val, const struct atyfb_par *par);
+extern u32 aty_ld_lcd(int index, const struct atyfb_par *par);
+#endif
+
/*
* DAC operations
*/
@@ -275,6 +296,7 @@
int (*var_to_pll) (const struct fb_info * info, u32 vclk_per, u32 bpp, union aty_pll * pll);
u32 (*pll_to_var) (const struct fb_info * info, const union aty_pll * pll);
void (*set_pll) (const struct fb_info * info, const union aty_pll * pll);
+ void (*get_pll) (const struct fb_info *info, union aty_pll * pll);
int (*init_pll) (const struct fb_info * info, union aty_pll * pll);
};
diff -ur -X patches/exclude linux-2.6.7.js3/drivers/video/aty/atyfb_base.c linux-2.6.7.ak/drivers/video/aty/atyfb_base.c
--- linux-2.6.7.js3/drivers/video/aty/atyfb_base.c 2004-06-27 01:35:27.000000000 +0200
+++ linux-2.6.7.ak/drivers/video/aty/atyfb_base.c 2004-08-04 22:57:50.000000000 +0200
@@ -26,6 +26,7 @@
* Anthony Tong <atong@uiuc.edu>
*
* Generic LCD support written by Daniel Mantione, ported from 2.4.20 by Alex Kern
+ * Many Thanks to Ville Syrjälä for patches and fixing nasting 16 bit color bug.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
@@ -41,15 +42,16 @@
- cursor support on all cards and all ramdacs.
- cursor parameters controlable via ioctl()s.
- guess PLL and MCLK based on the original PLL register values initialized
- by the BIOS or Open Firmware (if they are initialized).
+ by Open Firmware (if they are initialized). BIOS is done
- (Anyone to help with this?)
+ (Anyone with Mac to help with this?)
******************************************************************************/
#include <linux/config.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
@@ -61,6 +63,9 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -101,33 +106,63 @@
#define GUI_RESERVE (1 * PAGE_SIZE)
/* FIXME: remove the FAIL definition */
-#define FAIL(msg) do { printk(KERN_CRIT msg "\n"); return -EINVAL; } while (0)
-#define FAIL_MAX(msg, x, _max_) do { if(x > _max_) { printk(KERN_CRIT msg " %x(%x)\n", x, _max_); return -EINVAL; } } while (0)
+#define FAIL(msg) do { printk(KERN_CRIT "atyfb: " msg "\n"); return -EINVAL; } while (0)
+#define FAIL_MAX(msg, x, _max_) do { if(x > _max_) { printk(KERN_CRIT "atyfb: " msg " %x(%x)\n", x, _max_); return -EINVAL; } } while (0)
+
+#ifdef DEBUG
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "atyfb: " fmt, ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#define PRINTKI(fmt, args...) printk(KERN_INFO "atyfb: " fmt, ## args)
+#define PRINTKE(fmt, args...) printk(KERN_ERR "atyfb: " fmt, ## args)
#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD)
-static void aty_st_lcd(int index, u32 val, const struct atyfb_par *par)
+static const u32 lt_lcd_regs[] = {
+ CONFIG_PANEL_LG,
+ LCD_GEN_CNTL_LG,
+ DSTN_CONTROL_LG,
+ HFB_PITCH_ADDR_LG,
+ HORZ_STRETCHING_LG,
+ VERT_STRETCHING_LG,
+ 0, /* EXT_VERT_STRETCH */
+ LT_GIO_LG,
+ POWER_MANAGEMENT_LG
+};
+
+void aty_st_lcd(int index, u32 val, const struct atyfb_par *par)
{
- unsigned long temp;
+ if (M64_HAS(LT_LCD_REGS)) {
+ aty_st_le32(lt_lcd_regs[index], val, par);
+ } else {
+ unsigned long temp;
- /* write addr byte */
- temp = aty_ld_le32(LCD_INDEX, par);
- aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par);
- /* write the register value */
- aty_st_le32(LCD_DATA, val, par);
+ /* write addr byte */
+ temp = aty_ld_le32(LCD_INDEX, par);
+ aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par);
+ /* write the register value */
+ aty_st_le32(LCD_DATA, val, par);
+ }
}
-static u32 aty_ld_lcd(int index, const struct atyfb_par *par)
+u32 aty_ld_lcd(int index, const struct atyfb_par *par)
{
- unsigned long temp;
+ if (M64_HAS(LT_LCD_REGS)) {
+ return aty_ld_le32(lt_lcd_regs[index], par);
+ } else {
+ unsigned long temp;
- /* write addr byte */
- temp = aty_ld_le32(LCD_INDEX, par);
- aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par);
- /* read the register value */
- return aty_ld_le32(LCD_DATA, par);
+ /* write addr byte */
+ temp = aty_ld_le32(LCD_INDEX, par);
+ aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par);
+ /* read the register value */
+ return aty_ld_le32(LCD_DATA, par);
+ }
}
#endif /* defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD) */
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
/*
* ATIReduceRatio --
*
@@ -150,7 +185,7 @@
*Numerator /= Divider;
*Denominator /= Divider;
}
-
+#endif
/*
* The Hardware parameters for each card
*/
@@ -209,11 +244,11 @@
#ifdef CONFIG_ATARI
static int store_video_par(char *videopar, unsigned char m64_num);
#endif
-#if 0
+
static struct crtc saved_crtc;
static union aty_pll saved_pll;
static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc);
-#endif
+
static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc);
static int aty_var_to_crtc(const struct fb_info *info, const struct fb_var_screeninfo *var, struct crtc *crtc);
static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *var);
@@ -254,22 +289,19 @@
.fb_fillrect = atyfb_fillrect,
.fb_copyarea = atyfb_copyarea,
.fb_imageblit = atyfb_imageblit,
- .fb_cursor = atyfb_cursor,
+ .fb_cursor = soft_cursor,
#ifdef __sparc__
.fb_mmap = atyfb_mmap,
#endif
.fb_sync = atyfb_sync,
};
-static char noaccel __initdata = 0;
-static u32 default_vram __initdata = 0;
-static int default_pll __initdata = 0;
-static int default_mclk __initdata = 0;
-static int default_xclk __initdata = 0;
-
-#ifndef MODULE
-static char *mode_option __initdata = NULL;
-#endif
+static int noaccel;
+static int vram;
+static int pll;
+static int mclk;
+static int xclk;
+static char *mode;
#ifdef CONFIG_PPC
static int default_vmode __initdata = VMODE_CHOOSE;
@@ -294,20 +326,20 @@
#define ATI_CHIP_264GT (M64F_GT | M64F_INTEGRATED | M64F_MAGIC_FIFO | M64F_EXTRA_BRIGHT)
#define ATI_CHIP_264VTB (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP)
-#define ATI_CHIP_264VT3 (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP)
-#define ATI_CHIP_264VT4 (M64F_VT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_NO_EXT_PLL)
+#define ATI_CHIP_264VT3 (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL)
+#define ATI_CHIP_264VT4 (M64F_VT | M64F_INTEGRATED | M64F_GTB_DSP)
-#define ATI_CHIP_264LT (M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_NO_EXT_PLL)
+#define ATI_CHIP_264LT (M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP)
/* make sets shorter */
-#define ATI_MODERN_SET (M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_EXTRA_BRIGHT | M64F_NO_EXT_PLL)
+#define ATI_MODERN_SET (M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_EXTRA_BRIGHT)
-#define ATI_CHIP_264GTB (ATI_MODERN_SET)
+#define ATI_CHIP_264GTB (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL)
/*#define ATI_CHIP_264GTDVD ?*/
-#define ATI_CHIP_264LTG (ATI_MODERN_SET)
+#define ATI_CHIP_264LTG (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL)
-#define ATI_CHIP_264GT2C (ATI_MODERN_SET | M64F_HW_TRIPLE)
-#define ATI_CHIP_264GTPRO (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
+#define ATI_CHIP_264GT2C (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE)
+#define ATI_CHIP_264GTPRO (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
#define ATI_CHIP_264LTPRO (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
#define ATI_CHIP_264XL (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4)
@@ -336,7 +368,7 @@
{ PCI_CHIP_MACH64LT, "3D RAGE LT (Mach64 LT)", 135, 63, 63, ATI_CHIP_264LT },
/* FIXME chipset maybe ATI_CHIP_264LTPRO ? */
- { PCI_CHIP_MACH64LG, "3D RAGE LT-G (Mach64 LG)", 230, 63, 63, ATI_CHIP_264LTG | M64F_LT_SLEEP | M64F_G3_PB_1024x768 },
+ { PCI_CHIP_MACH64LG, "3D RAGE LT-G (Mach64 LG)", 230, 63, 63, ATI_CHIP_264LTG | M64F_LT_LCD_REGS | M64F_G3_PB_1024x768 },
{ PCI_CHIP_MACH64VV, "ATI264VT4 (Mach64 VV)", 230, 83, 83, ATI_CHIP_264VT4 },
@@ -365,19 +397,20 @@
{ PCI_CHIP_MACH64GS, "3D RAGE XL (Mach64 GS, PCI)", 230, 83, 63, ATI_CHIP_264XL },
{ PCI_CHIP_MACH64LM, "3D RAGE Mobility P/M (Mach64 LM, AGP 2x)", 230, 83, 125, ATI_CHIP_MOBILITY },
- { PCI_CHIP_MACH64LN, "3D RAGE Mobility (Mach64 LN, AGP 2x)", 230, 83, 125, ATI_CHIP_MOBILITY },
- { PCI_CHIP_MACH64LR, "3D RAGE Mobility (Mach64 LR, PCI)", 230, 83, 125, ATI_CHIP_MOBILITY },
- { PCI_CHIP_MACH64LS, "3D RAGE Mobility (Mach64 LS, PCI)", 230, 83, 125, ATI_CHIP_MOBILITY },
+ { PCI_CHIP_MACH64LN, "3D RAGE Mobility L (Mach64 LN, AGP 2x)", 230, 83, 125, ATI_CHIP_MOBILITY },
+ { PCI_CHIP_MACH64LR, "3D RAGE Mobility P/M (Mach64 LR, PCI)", 230, 83, 125, ATI_CHIP_MOBILITY },
+ { PCI_CHIP_MACH64LS, "3D RAGE Mobility L (Mach64 LS, PCI)", 230, 83, 125, ATI_CHIP_MOBILITY },
#endif /* CONFIG_FB_ATY_CT */
};
+/* can not fail */
static int __devinit correct_chipset(struct atyfb_par *par)
{
- const char *name;
- int i, err = 0;
- u32 chip_id;
- u16 type;
u8 rev;
+ u16 type;
+ u32 chip_id;
+ const char *name;
+ int i;
for (i = sizeof(aty_chips) / sizeof(*aty_chips) - 1; i >= 0; i--)
if (par->pci_id == aty_chips[i].pci_id)
@@ -396,12 +429,12 @@
switch(par->pci_id) {
#ifdef CONFIG_FB_ATY_GX
case PCI_CHIP_MACH64GX:
- if (type != 0x00d7)
- err = -ENXIO;
+ if(type != 0x00d7);
+ return -ENODEV;
break;
case PCI_CHIP_MACH64CX:
- if (type == 0x0057)
- err = -ENXIO;
+ if(type != 0x0057);
+ return -ENODEV;
break;
#endif
#ifdef CONFIG_FB_ATY_CT
@@ -443,11 +476,9 @@
break;
#endif
}
- if (!err)
- printk("atyfb: %s [0x%04x rev 0x%02x]\n", name, type, rev);
- else
- printk(KERN_INFO "atyfb: Unknown mach64 0x%04x rev 0x%04x\n", type, rev);
- return err;
+
+ PRINTKI("%s [0x%04x rev 0x%02x]\n", name, type, rev);
+ return 0;
}
static char ram_dram[] __initdata = "DRAM";
@@ -457,9 +488,9 @@
#endif /* CONFIG_FB_ATY_GX */
#ifdef CONFIG_FB_ATY_CT
static char ram_edo[] __initdata = "EDO";
-static char ram_sdram[] __initdata = "SDRAM";
-static char ram_sgram[] __initdata = "SGRAM";
-static char ram_wram[] __initdata = "WRAM";
+static char ram_sdram[] __initdata = "SDRAM (1:1)";
+static char ram_sgram[] __initdata = "SGRAM (1:1)";
+static char ram_sdram32[] __initdata = "SDRAM (2:1) (32-bit)";
static char ram_off[] __initdata = "OFF";
#endif /* CONFIG_FB_ATY_CT */
@@ -476,7 +507,7 @@
#ifdef CONFIG_FB_ATY_CT
static char *aty_ct_ram[8] __initdata = {
ram_off, ram_dram, ram_edo, ram_edo,
- ram_sdram, ram_sgram, ram_wram, ram_resv
+ ram_sdram, ram_sgram, ram_sdram32, ram_resv
};
#endif /* CONFIG_FB_ATY_CT */
@@ -543,9 +574,30 @@
/*
* CRTC programming
*/
-#if 0
+
static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc)
{
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+ if (par->lcd_table != 0) {
+ if(!M64_HAS(LT_LCD_REGS)) {
+ crtc->lcd_index = aty_ld_le32(LCD_INDEX, par);
+ aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
+ }
+ crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par);
+ crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par);
+
+
+ /* switch to non shadow registers */
+ aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
+ ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
+
+ /* save stretching */
+ crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par);
+ crtc->vert_stretching = aty_ld_lcd(VERT_STRETCHING, par);
+ if (!M64_HAS(LT_LCD_REGS))
+ crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par);
+ }
+#endif
crtc->h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
crtc->h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
crtc->v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
@@ -555,51 +607,34 @@
crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
#ifdef CONFIG_FB_ATY_GENERIC_LCD
-
if (par->lcd_table != 0) {
/* switch to shadow registers */
- u32 temp = aty_ld_lcd(LCD_GEN_CNTL, par);
- aty_st_lcd(LCD_GEN_CNTL, temp | SHADOW_EN | SHADOW_RW_EN, par);
+ aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |
+ SHADOW_EN | SHADOW_RW_EN, par);
- /* get shadow registers */
crtc->shadow_h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
crtc->shadow_h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
crtc->shadow_v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
crtc->shadow_v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
- aty_st_le32(LCD_GEN_CNTL, temp & ~(SHADOW_EN | SHADOW_RW_EN), par);
-
- /* get stretching */
- crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par);
- crtc->vert_stretching = aty_ld_lcd(VERT_STRETCHING, par);
- crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par);
+ aty_st_le32(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);
}
#endif /* CONFIG_FB_ATY_GENERIC_LCD */
}
-#endif
+
static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc)
{
#ifdef CONFIG_FB_ATY_GENERIC_LCD
- u32 temp;
-
- /* Load LCD registers */
if (par->lcd_table != 0) {
- // Set the CRTC to primary, and make the registers writeable
- temp = aty_ld_lcd(LCD_GEN_CNTL, par);
- temp &= LCD_SET_PRIMARY_MASK;
- temp |= DONT_SHADOW_VPAR;
- aty_st_lcd(LCD_GEN_CNTL, temp, par);
-#if 0
- /* Stop CRTC */
- aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl &
- ~(CRTC_EXT_DISP_EN | CRTC_EN), par);
+ /* stop CRTC */
+ aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~(CRTC_EXT_DISP_EN | CRTC_EN), par);
- /* Update non-shadow registers first */
- /*aty_st_lcd(LCD_CONFIG_PANEL, pATIHW->config_panel);*/
+ /* update non-shadow registers first */
+ aty_st_lcd(CONFIG_PANEL, crtc->lcd_config_panel, par);
aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
-#endif
- /* Temporarily disable stretching */
+
+ /* temporarily disable stretching */
aty_st_lcd(HORZ_STRETCHING,
crtc->horz_stretching &
~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN), par);
@@ -609,55 +644,72 @@
VERT_STRETCH_USE0 | VERT_STRETCH_EN), par);
}
#endif
+ /* turn off CRT */
aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~CRTC_EN, par);
+
+ DPRINTK("setting up CRTC\n");
+ PRINTKI("set primary CRT to %ix%i %c%c composite %c\n",
+ ((((crtc->h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->v_tot_disp>>16) & 0x7ff) + 1),
+ (crtc->h_sync_strt_wid & 0x200000)?'N':'P', (crtc->v_sync_strt_wid & 0x200000)?'N':'P',
+ (crtc->gen_cntl & CRTC_CSYNC_EN)?'P':'N');
+
+ DPRINTK("CRTC_H_TOTAL_DISP: %x\n",crtc->h_tot_disp);
+ DPRINTK("CRTC_H_SYNC_STRT_WID: %x\n",crtc->h_sync_strt_wid);
+ DPRINTK("CRTC_V_TOTAL_DISP: %x\n",crtc->v_tot_disp);
+ DPRINTK("CRTC_V_SYNC_STRT_WID: %x\n",crtc->v_sync_strt_wid);
+ DPRINTK("CRTC_OFF_PITCH: %x\n", crtc->off_pitch);
+ DPRINTK("CRTC_VLINE_CRNT_VLINE: %x\n", crtc->vline_crnt_vline);
+ DPRINTK("CRTC_GEN_CNTL: %x\n",crtc->gen_cntl);
+
aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, par);
aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, par);
aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_tot_disp, par);
aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid, par);
- aty_st_le32(CRTC_VLINE_CRNT_VLINE, crtc->vline_crnt_vline, par);
aty_st_le32(CRTC_OFF_PITCH, crtc->off_pitch, par);
+ aty_st_le32(CRTC_VLINE_CRNT_VLINE, crtc->vline_crnt_vline, par);
+
aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl, par);
-#ifdef DEBUG
- printk(KERN_INFO "setting up CRTC\n");
- printk(KERN_INFO "CRTC_GEN_CNTL: %x\n",crtc->gen_cntl);
- printk(KERN_INFO "CRTC_H_TOTAL_DISP: %x\n",crtc->h_tot_disp);
- printk(KERN_INFO "CRTC_H_SYNC_STRT_WID: %x\n",crtc->h_sync_strt_wid);
- printk(KERN_INFO "CRTC_V_TOTAL_DISP: %x\n",crtc->v_tot_disp);
- printk(KERN_INFO "CRTC_V_SYNC_STRT_WID: %x\n",crtc->v_sync_strt_wid);
+#if 0
+ FIXME
+ if (par->accel_flags & FB_ACCELF_TEXT)
+ aty_init_engine(par, info);
#endif
#ifdef CONFIG_FB_ATY_GENERIC_LCD
- /* After setting the CRTC registers we should set the LCD
- * registers.
- */
+ /* after setting the CRTC registers we should set the LCD registers. */
if (par->lcd_table != 0) {
/* switch to shadow registers */
- temp = aty_ld_lcd(LCD_GEN_CNTL, par);
- aty_st_lcd(LCD_GEN_CNTL, temp | SHADOW_EN | SHADOW_RW_EN, par);
+ aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |
+ (SHADOW_EN | SHADOW_RW_EN), par);
+
+ PRINTKI("set secondary CRT to %ix%i %c%c\n",
+ ((((crtc->shadow_h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->shadow_v_tot_disp>>16) & 0x7ff) + 1),
+ (crtc->shadow_h_sync_strt_wid & 0x200000)?'N':'P', (crtc->shadow_v_sync_strt_wid & 0x200000)?'N':'P');
+
+ DPRINTK("SHADOW CRTC_H_TOTAL_DISP: %x\n", crtc->shadow_h_tot_disp);
+ DPRINTK("SHADOW CRTC_H_SYNC_STRT_WID: %x\n", crtc->shadow_h_sync_strt_wid);
+ DPRINTK("SHADOW CRTC_V_TOTAL_DISP: %x\n", crtc->shadow_v_tot_disp);
+ DPRINTK("SHADOW CRTC_V_SYNC_STRT_WID: %x\n", crtc->shadow_v_sync_strt_wid);
- /* set shadow registers */
aty_st_le32(CRTC_H_TOTAL_DISP, crtc->shadow_h_tot_disp, par);
aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->shadow_h_sync_strt_wid, par);
aty_st_le32(CRTC_V_TOTAL_DISP, crtc->shadow_v_tot_disp, par);
aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->shadow_v_sync_strt_wid, par);
- aty_st_lcd(LCD_GEN_CNTL, temp & ~(SHADOW_EN | SHADOW_RW_EN), par);
+ /* restore CRTC selection & shadow state and enable stretching */
+ DPRINTK("LCD_GEN_CNTL: %x\n", crtc->lcd_gen_cntl);
+ DPRINTK("HORZ_STRETCHING: %x\n", crtc->horz_stretching);
+ DPRINTK("VERT_STRETCHING: %x\n", crtc->vert_stretching);
+ if(!M64_HAS(LT_LCD_REGS))
+ DPRINTK("EXT_VERT_STRETCH: %x\n", crtc->ext_vert_stretch);
-#ifdef DEBUG
- printk(KERN_INFO "LCD_GEN_CNTL: %x\n", temp);
- printk(KERN_INFO "HORZ_STRETCHING: %x\n", crtc->horz_stretching);
- printk(KERN_INFO "VERT_STRETCHING: %x\n", crtc->vert_stretching);
- printk(KERN_INFO "EXT_VERT_STRETCH: %x\n", crtc->ext_vert_stretch);
-#endif
- /* Restore CRTC selection & shadow state */
- /*aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);*/
-
- /* Enable/disable stretching */
+ aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);
aty_st_lcd(HORZ_STRETCHING, crtc->horz_stretching, par);
aty_st_lcd(VERT_STRETCHING, crtc->vert_stretching, par);
- aty_st_lcd(EXT_VERT_STRETCH, crtc->ext_vert_stretch, par);
- /*
- outr(LCD_INDEX, pATIHW->lcd_index);
- */
+ if(!M64_HAS(LT_LCD_REGS)) {
+ aty_st_lcd(EXT_VERT_STRETCH, crtc->ext_vert_stretch, par);
+ aty_ld_le32(LCD_INDEX, par);
+ aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
+ }
}
#endif /* CONFIG_FB_ATY_GENERIC_LCD */
}
@@ -667,14 +719,11 @@
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
- u32 sync, vmode;
+ u32 sync, vmode, vdisplay;
u32 h_total, h_disp, h_sync_strt, h_sync_end, h_sync_dly, h_sync_wid, h_sync_pol;
u32 v_total, v_disp, v_sync_strt, v_sync_end, v_sync_wid, v_sync_pol, c_sync;
u32 pix_width, dp_pix_width, dp_chain_mask;
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
- int VScan = 1;
- u32 lcd_on_off = 0;
-#endif
+
/* input */
xres = var->xres;
yres = var->yres;
@@ -683,6 +732,8 @@
xoffset = var->xoffset;
yoffset = var->yoffset;
bpp = var->bits_per_pixel;
+ if (bpp == 16)
+ bpp = (var->green.length == 5) ? 15 : 16;
sync = var->sync;
vmode = var->vmode;
@@ -702,12 +753,18 @@
HOST_8BPP | SRC_8BPP | DST_8BPP |
BYTE_ORDER_LSB_TO_MSB;
dp_chain_mask = DP_CHAIN_8BPP;
- } else if (bpp <= 16) {
+ } else if (bpp <= 15) {
bpp = 16;
pix_width = CRTC_PIX_WIDTH_15BPP;
dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP |
BYTE_ORDER_LSB_TO_MSB;
dp_chain_mask = DP_CHAIN_15BPP;
+ } else if (bpp <= 16) {
+ bpp = 16;
+ pix_width = CRTC_PIX_WIDTH_16BPP;
+ dp_pix_width = HOST_16BPP | SRC_16BPP | DST_16BPP |
+ BYTE_ORDER_LSB_TO_MSB;
+ dp_chain_mask = DP_CHAIN_16BPP;
} else if (bpp <= 24 && M64_HAS(INTEGRATED)) {
bpp = 24;
pix_width = CRTC_PIX_WIDTH_24BPP;
@@ -730,30 +787,59 @@
h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
+ if((xres > 1600) || (yres > 1200)) {
+ FAIL("MACH64 chips are designed for max 1600x1200\n"
+ "select anoter resolution.");
+ }
+ h_sync_strt = h_disp + var->right_margin;
+ h_sync_end = h_sync_strt + var->hsync_len;
+ h_sync_dly = var->right_margin & 7;
+ h_total = h_sync_end + h_sync_dly + var->left_margin;
+
+ v_sync_strt = v_disp + var->lower_margin;
+ v_sync_end = v_sync_strt + var->vsync_len;
+ v_total = v_sync_end + var->upper_margin;
+
#ifdef CONFIG_FB_ATY_GENERIC_LCD
if (par->lcd_table != 0) {
- u32 lcd_index = aty_ld_le32(LCD_INDEX, par);
- lcd_on_off = aty_ld_lcd(LCD_GEN_CNTL, par);
+ if(!M64_HAS(LT_LCD_REGS)) {
+ u32 lcd_index = aty_ld_le32(LCD_INDEX, par);
+ crtc->lcd_index = lcd_index &
+ ~(LCD_INDEX_MASK | LCD_DISPLAY_DIS | LCD_SRC_SEL | CRTC2_DISPLAY_DIS);
+ aty_st_le32(LCD_INDEX, lcd_index, par);
+ }
+
+ if (!M64_HAS(MOBIL_BUS))
+ crtc->lcd_index |= CRTC2_DISPLAY_DIS;
- if((lcd_on_off & LCD_ON) &&
+ crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par) | 0x4000;
+ crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par) & ~CRTC_RW_SELECT;
+
+ crtc->lcd_gen_cntl &=
+ ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 | TVCLK_PM_EN |
+ /*VCLK_DAC_PM_EN | USE_SHADOWED_VEND |*/
+ USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN);
+ crtc->lcd_gen_cntl |= DONT_SHADOW_VPAR | LOCK_8DOT;
+
+ if((crtc->lcd_gen_cntl & LCD_ON) &&
((xres > par->lcd_width) || (yres > par->lcd_height))) {
/* We cannot display the mode on the LCD. If the CRT is enabled
we can turn off the LCD.
If the CRT is off, it isn't a good idea to switch it on; we don't
know if one is connected. So it's better to fail then.
*/
- if (lcd_on_off & CRT_ON) {
- printk(KERN_INFO "Disable lcd panel, because video mode does not fit.\n");
- lcd_on_off &= ~LCD_ON;
- aty_st_lcd(LCD_GEN_CNTL, lcd_on_off, par);
+ if (crtc->lcd_gen_cntl & CRT_ON) {
+ PRINTKI("Disable lcd panel, because video mode does not fit.\n");
+ crtc->lcd_gen_cntl &= ~LCD_ON;
+ /*aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);*/
} else {
FAIL("Video mode exceeds size of lcd panel.\nConnect this computer to a conventional monitor if you really need this mode.");
}
}
- aty_st_le32(LCD_INDEX, lcd_index, par);
}
- if ((par->lcd_table != 0) && (lcd_on_off & LCD_ON)) {
+ if ((par->lcd_table != 0) && (crtc->lcd_gen_cntl & LCD_ON)) {
+ int VScan = 1;
/* bpp -> bytespp, 1,4 -> 0; 8 -> 2; 15,16 -> 1; 24 -> 6; 32 -> 5
const u8 DFP_h_sync_dly_LT[] = { 0, 2, 1, 6, 5 };
const u8 ADD_to_strt_wid_and_dly_LT_DAC[] = { 0, 5, 6, 9, 9, 12, 12 }; */
@@ -784,24 +870,9 @@
v_sync_strt = v_disp + par->lcd_lower_margin / VScan;
v_sync_end = v_sync_strt + par->lcd_vsync_len / VScan;
v_total = v_disp + par->lcd_vblank_len / VScan;
- } else {
+ }
#endif /* CONFIG_FB_ATY_GENERIC_LCD */
- if((xres > 1600) || (yres > 1200)) {
- FAIL("MACH64 chips are designed for max 1600x1200\n"
- "select anoter resolution.");
- }
- h_sync_strt = h_disp + var->right_margin;
- h_sync_end = h_sync_strt + var->hsync_len;
- h_sync_dly = var->right_margin & 7;
- h_total = h_sync_end + h_sync_dly + var->left_margin;
-
- v_sync_strt = v_disp + var->lower_margin;
- v_sync_end = v_sync_strt + var->vsync_len;
- v_total = v_sync_end + var->upper_margin;
-#ifdef CONFIG_FB_ATY_GENERIC_LCD
- }
-#endif
h_disp = (h_disp >> 3) - 1;
h_sync_strt = (h_sync_strt >> 3) - 1;
h_sync_end = (h_sync_end >> 3) - 1;
@@ -810,7 +881,9 @@
FAIL_MAX("h_disp too large", h_disp, 0xff);
FAIL_MAX("h_sync_strt too large", h_sync_strt, 0x1ff);
- FAIL_MAX("h_sync_wid too large", h_sync_wid, 0x1f);
+ /*FAIL_MAX("h_sync_wid too large", h_sync_wid, 0x1f);*/
+ if(h_sync_wid > 0x1f)
+ h_sync_wid = 0x1f;
FAIL_MAX("h_total too large", h_total, 0x1ff);
if (vmode & FB_VMODE_DOUBLE) {
@@ -820,26 +893,24 @@
v_total <<= 1;
}
- if(1) {
- int VDisplay = yres;
+ vdisplay = yres;
#ifdef CONFIG_FB_ATY_GENERIC_LCD
- if ((par->lcd_table != 0) && (lcd_on_off & LCD_ON))
- VDisplay = par->lcd_height;
+ if ((par->lcd_table != 0) && (crtc->lcd_gen_cntl & LCD_ON))
+ vdisplay = par->lcd_height;
#endif
- if(VDisplay < 400) {
- h_sync_pol = 1;
- v_sync_pol = 0;
- } else if(VDisplay < 480) {
- h_sync_pol = 0;
- v_sync_pol = 1;
- } else if(VDisplay < 768) {
- h_sync_pol = 0;
- v_sync_pol = 0;
- } else {
- h_sync_pol = 1;
- v_sync_pol = 1;
- }
+ if(vdisplay < 400) {
+ h_sync_pol = 1;
+ v_sync_pol = 0;
+ } else if(vdisplay < 480) {
+ h_sync_pol = 0;
+ v_sync_pol = 1;
+ } else if(vdisplay < 768) {
+ h_sync_pol = 0;
+ v_sync_pol = 0;
+ } else {
+ h_sync_pol = 1;
+ v_sync_pol = 1;
}
v_disp--;
@@ -850,7 +921,9 @@
FAIL_MAX("v_disp too large", v_disp, 0x7ff);
FAIL_MAX("v_sync_stsrt too large", v_sync_strt, 0x7ff);
- FAIL_MAX("v_sync_wid too large", v_sync_wid, 0x1f);
+ /*FAIL_MAX("v_sync_wid too large", v_sync_wid, 0x1f);*/
+ if(v_sync_wid > 0x1f)
+ v_sync_wid = 0x1f;
FAIL_MAX("v_total too large", v_total, 0x7ff);
c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;
@@ -881,12 +954,12 @@
if (vmode & FB_VMODE_INTERLACED)
crtc->gen_cntl |= CRTC_INTERLACE_EN;
#ifdef CONFIG_FB_ATY_GENERIC_LCD
- if ((par->lcd_table != 0) && (lcd_on_off & LCD_ON)) {
- int VDisplay = yres;
+ if (par->lcd_table != 0) {
+ vdisplay = yres;
if(vmode & FB_VMODE_DOUBLE)
- VDisplay <<= 1;
+ vdisplay <<= 1;
if(vmode & FB_VMODE_INTERLACED) {
- VDisplay >>= 1;
+ vdisplay >>= 1;
/* The prefered mode for the lcd is not interlaced, so disable it if
it was enabled. For doublescan there is no problem, because we can
@@ -896,14 +969,16 @@
/*crtc->gen_cntl &= ~CRTC_INTERLACE_EN;*/
}
crtc->gen_cntl &= ~(CRTC2_EN | CRTC2_PIX_WIDTH);
-/*
- crtc->lcd_gen_cntl &= ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 | SCLK_SEL | USE_SHADOWED_VEND | SHADOW_EN);
- crtc->lcd_gen_cntl |= (DONT_SHADOW_VPAR);
-*/
+ crtc->lcd_gen_cntl &= ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 |
+ /*TVCLK_PM_EN | VCLK_DAC_PM_EN |*/
+ USE_SHADOWED_VEND | USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN);
+ crtc->lcd_gen_cntl |= (DONT_SHADOW_VPAR/* | LOCK_8DOT*/);
+
/* MOBILITY M1 tested, FIXME: LT */
crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par);
- crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par) &
- ~(AUTO_VERT_RATIO | VERT_STRETCH_MODE | VERT_STRETCH_RATIO3);
+ if (!M64_HAS(LT_LCD_REGS))
+ crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par) &
+ ~(AUTO_VERT_RATIO | VERT_STRETCH_MODE | VERT_STRETCH_RATIO3);
crtc->horz_stretching &=
~(HORZ_STRETCH_RATIO | HORZ_STRETCH_LOOP | AUTO_HORZ_RATIO |
@@ -970,11 +1045,12 @@
} while (0);
}
- if (VDisplay < par->lcd_height) {
+ if (vdisplay < par->lcd_height) {
crtc->vert_stretching = (VERT_STRETCH_USE0 | VERT_STRETCH_EN |
- (((VDisplay * (VERT_STRETCH_RATIO0 + 1)) / par->lcd_height) & VERT_STRETCH_RATIO0));
+ (((vdisplay * (VERT_STRETCH_RATIO0 + 1)) / par->lcd_height) & VERT_STRETCH_RATIO0));
- if (xres <= (M64_HAS(MOBIL_BUS)?1024:800))
+ if (!M64_HAS(LT_LCD_REGS) &&
+ xres <= (M64_HAS(MOBIL_BUS)?1024:800))
crtc->ext_vert_stretch |= VERT_STRETCH_MODE;
} else {
/*
@@ -983,13 +1059,12 @@
*/
crtc->vert_stretching = 0;
}
+ /* copy to shadow crtc */
+ crtc->shadow_h_tot_disp = crtc->h_tot_disp;
+ crtc->shadow_h_sync_strt_wid = crtc->h_sync_strt_wid;
+ crtc->shadow_v_tot_disp = crtc->v_tot_disp;
+ crtc->shadow_v_sync_strt_wid = crtc->v_sync_strt_wid;
}
-
- /* copy to shadow crtc */
- crtc->shadow_h_tot_disp = crtc->h_tot_disp;
- crtc->shadow_h_sync_strt_wid = crtc->h_sync_strt_wid;
- crtc->shadow_v_tot_disp = crtc->v_tot_disp;
- crtc->shadow_v_sync_strt_wid = crtc->v_sync_strt_wid;
#endif /* CONFIG_FB_ATY_GENERIC_LCD */
if (M64_HAS(MAGIC_FIFO)) {
@@ -1078,7 +1153,6 @@
var->transp.offset = 0;
var->transp.length = 0;
break;
-#if 0
case CRTC_PIX_WIDTH_16BPP: /* RGB 565 */
bpp = 16;
var->red.offset = 11;
@@ -1090,7 +1164,6 @@
var->transp.offset = 0;
var->transp.length = 0;
break;
-#endif
case CRTC_PIX_WIDTH_24BPP: /* RGB 888 */
bpp = 24;
var->red.offset = 16;
@@ -1183,7 +1256,6 @@
wait_for_idle(par);
aty_set_crtc(par, &par->crtc);
-
par->dac_ops->set_dac(info, &par->pll, var->bits_per_pixel, par->accel_flags);
par->pll_ops->set_pll(info, &par->pll);
@@ -1194,7 +1266,7 @@
pixclock_in_ps = 0;
if(0 == pixclock_in_ps) {
- printk(KERN_CRIT "ALERT ops->pll_to_var get 0\n");
+ PRINTKE("ALERT ops->pll_to_var get 0\n");
pixclock_in_ps = pixclock;
}
@@ -1220,23 +1292,23 @@
if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN)
vRefresh /= 2;
- printk("atyfb: atyfb_set_par\n");
- printk(" Set Visible Mode to %ix%i-%i\n", var->xres, var->yres, var->bits_per_pixel);
- printk(" Virtual resolution %ix%i, pixclock_in_ps %i (calculated %i)\n",
+ DPRINTK("atyfb_set_par\n");
+ DPRINTK(" Set Visible Mode to %ix%i-%i\n", var->xres, var->yres, var->bits_per_pixel);
+ DPRINTK(" Virtual resolution %ix%i, pixclock_in_ps %i (calculated %i)\n",
var->xres_virtual, var->yres_virtual, pixclock, pixclock_in_ps);
- printk(" Dot clock: %i MHz\n", 1000000 / pixclock_in_ps);
- printk(" Horizontal sync: %i kHz\n", hSync);
- printk(" Vertical refresh: %i Hz\n", vRefresh);
- printk(" x style: %i.%03i %i %i %i %i %i %i %i %i\n",
+ DPRINTK(" Dot clock: %i MHz\n", 1000000 / pixclock_in_ps);
+ DPRINTK(" Horizontal sync: %i kHz\n", hSync);
+ DPRINTK(" Vertical refresh: %i Hz\n", vRefresh);
+ DPRINTK(" x style: %i.%03i %i %i %i %i %i %i %i %i\n",
1000000 / pixclock_in_ps, 1000000 % pixclock_in_ps,
h_disp, h_sync_strt, h_sync_end, h_total,
v_disp, v_sync_strt, v_sync_end, v_total);
- printk( " fb style:%i %i %i %i %i %i %i %i %i\n",
+ DPRINTK(" fb style: %i %i %i %i %i %i %i %i %i\n",
pixclock_in_ps,
debug.left_margin, h_disp, debug.right_margin, debug.hsync_len,
debug.upper_margin, v_disp, debug.lower_margin, debug.vsync_len);
}
-#endif
+#endif /* DEBUG */
if (!M64_HAS(INTEGRATED)) {
/* Don't forget MEM_CNTL */
@@ -1315,9 +1387,9 @@
/* CRTC registers */
base = 0x2000;
- printk("Mach64 non-shadow register values:");
+ printk("debug atyfb: Mach64 non-shadow register values:");
for (i = 0; i < 256; i = i+4) {
- if(i%16 == 0) printk("\n0x%04X: ", base + i);
+ if(i%16 == 0) printk("\ndebug atyfb: 0x%04X: ", base + i);
printk(" %08X", aty_ld_le32(i, par));
}
printk("\n\n");
@@ -1325,9 +1397,9 @@
#ifdef CONFIG_FB_ATY_CT
/* PLL registers */
base = 0x00;
- printk("Mach64 PLL register values:");
+ printk("debug atyfb: Mach64 PLL register values:");
for (i = 0; i < 64; i++) {
- if(i%16 == 0) printk("\n0x%02X: ", base + i);
+ if(i%16 == 0) printk("\ndebug atyfb: 0x%02X: ", base + i);
if(i%4 == 0) printk(" ");
printk("%02X", aty_ld_pll_ct(i, par));
}
@@ -1338,10 +1410,20 @@
if (par->lcd_table != 0) {
/* LCD registers */
base = 0x00;
- printk("LCD register values:");
- for (i = 0; i < 64; i++) {
- if(i%4 == 0) printk("\n0x%02X: ", base + i);
+ printk("debug atyfb: LCD register values:");
+ if(M64_HAS(LT_LCD_REGS)) {
+ for(i = 0; i <= POWER_MANAGEMENT; i++) {
+ if(i == EXT_VERT_STRETCH)
+ continue;
+ printk("\ndebug atyfb: 0x%04X: ", lt_lcd_regs[i]);
+ printk(" %08X", aty_ld_lcd(i, par));
+ }
+
+ } else {
+ for (i = 0; i < 64; i++) {
+ if(i%4 == 0) printk("\ndebug atyfb: 0x%02X: ", base + i);
printk(" %08X", aty_ld_lcd(i, par));
+ }
}
printk("\n\n");
}
@@ -1395,7 +1477,6 @@
u32 bpp = info->var.bits_per_pixel;
par->crtc.off_pitch = ((yoffset * vxres + xoffset) * bpp / 64) | (vxres << 19);
- aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
}
@@ -1405,26 +1486,103 @@
static int atyfb_open(struct fb_info *info, int user)
{
-#ifdef __sparc__
struct atyfb_par *par = (struct atyfb_par *) info->par;
if (user) {
par->open++;
+#ifdef __sparc__
par->mmaped = 0;
- }
#endif
+ }
return (0);
}
+static irqreturn_t aty_irq(int irq, void *dev_id, struct pt_regs *fp)
+{
+ struct atyfb_par *par = dev_id;
+ int handled = 0;
+ u32 int_cntl;
+
+ spin_lock(&par->int_lock);
+
+ int_cntl = aty_ld_le32(CRTC_INT_CNTL, par);
+
+ if (int_cntl & CRTC_VBLANK_INT) {
+ /* clear interrupt */
+ aty_st_le32(CRTC_INT_CNTL, (int_cntl & CRTC_INT_EN_MASK) | CRTC_VBLANK_INT_AK, par);
+ par->vblank.count++;
+ if (par->vblank.pan_display) {
+ par->vblank.pan_display = 0;
+ aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
+ }
+ wake_up_interruptible(&par->vblank.wait);
+ handled = 1;
+ }
+
+ spin_unlock(&par->int_lock);
+
+ return IRQ_RETVAL(handled);
+}
+
+static int aty_enable_irq(struct atyfb_par *par, int reenable)
+{
+ u32 int_cntl;
+
+ if (!test_and_set_bit(0, &par->irq_flags)) {
+ if (request_irq(par->irq, aty_irq, SA_SHIRQ, "atyfb", par)) {
+ clear_bit(0, &par->irq_flags);
+ return -EINVAL;
+ }
+ spin_lock_irq(&par->int_lock);
+ int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
+ /* clear interrupt */
+ aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_AK, par);
+ /* enable interrupt */
+ aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_EN, par);
+ spin_unlock_irq(&par->int_lock);
+ } else if (reenable) {
+ spin_lock_irq(&par->int_lock);
+ int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
+ if (!(int_cntl & CRTC_VBLANK_INT_EN)) {
+ printk("atyfb: someone disabled IRQ [%08x]\n", int_cntl);
+ /* re-enable interrupt */
+ aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_EN, par );
+ }
+ spin_unlock_irq(&par->int_lock);
+ }
+
+ return 0;
+}
+
+static int aty_disable_irq(struct atyfb_par *par)
+{
+ u32 int_cntl;
+
+ if (test_and_clear_bit(0, &par->irq_flags)) {
+ if (par->vblank.pan_display) {
+ par->vblank.pan_display = 0;
+ aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
+ }
+ spin_lock_irq(&par->int_lock);
+ int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
+ /* disable interrupt */
+ aty_st_le32(CRTC_INT_CNTL, int_cntl & ~CRTC_VBLANK_INT_EN, par );
+ spin_unlock_irq(&par->int_lock);
+ free_irq(par->irq, par);
+ }
+
+ return 0;
+}
+
static int atyfb_release(struct fb_info *info, int user)
{
-#ifdef __sparc__
struct atyfb_par *par = (struct atyfb_par *) info->par;
if (user) {
par->open--;
mdelay(1);
wait_for_idle(par);
if (!par->open) {
+#ifdef __sparc__
int was_mmaped = par->mmaped;
par->mmaped = 0;
@@ -1443,15 +1601,16 @@
else
var.accel_flags |= FB_ACCELF_TEXT;
if (var.yres == var.yres_virtual) {
- u32 vram = (info->fix.smem_len - (PAGE_SIZE << 2));
- var.yres_virtual = ((vram * 8) / var.bits_per_pixel) / var.xres_virtual;
+ u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2));
+ var.yres_virtual = ((videoram * 8) / var.bits_per_pixel) / var.xres_virtual;
if (var.yres_virtual < var.yres)
var.yres_virtual = var.yres;
}
}
+#endif
+ aty_disable_irq(par);
}
}
-#endif
return (0);
}
@@ -1478,10 +1637,50 @@
info->var.yoffset = yoffset;
if (par->asleep)
return 0;
+
set_off_pitch(par, info);
+ if ((var->activate & FB_ACTIVATE_VBL) && !aty_enable_irq(par, 0)) {
+ par->vblank.pan_display = 1;
+ } else {
+ par->vblank.pan_display = 0;
+ aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
+ }
+
return 0;
}
+static int aty_waitforvblank(struct atyfb_par *par, u32 crtc)
+{
+ struct aty_interrupt *vbl;
+ unsigned int count;
+ int ret;
+
+ switch (crtc) {
+ case 0:
+ vbl = &par->vblank;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ ret = aty_enable_irq(par, 0);
+ if (ret)
+ return ret;
+
+ count = vbl->count;
+ ret = wait_event_interruptible_timeout(vbl->wait, count != vbl->count, HZ/10);
+ if (ret < 0) {
+ return ret;
+ }
+ if (ret == 0) {
+ aty_enable_irq(par, 1);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+
#ifdef DEBUG
#define ATYIO_CLKR 0x41545900 /* ATY\00 */
#define ATYIO_CLKW 0x41545901 /* ATY\01 */
@@ -1506,12 +1705,14 @@
#define ATYIO_FEATW 0x41545903 /* ATY\03 */
#endif
+#ifndef FBIO_WAITFORVSYNC
+#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
+#endif
+
static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
u_long arg, struct fb_info *info)
{
-#if defined(__sparc__) || (defined(DEBUG) && defined(CONFIG_FB_ATY_CT))
struct atyfb_par *par = (struct atyfb_par *) info->par;
-#endif /* __sparc__ || DEBUG */
#ifdef __sparc__
struct fbtype fbtyp;
#endif
@@ -1529,6 +1730,18 @@
return -EFAULT;
break;
#endif /* __sparc__ */
+
+ case FBIO_WAITFORVSYNC:
+ {
+ u32 crtc;
+
+ if (get_user(crtc, (__u32 *) arg))
+ return -EFAULT;
+
+ return aty_waitforvblank(par, crtc);
+ }
+ break;
+
#if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)
case ATYIO_CLKR:
if (M64_HAS(INTEGRATED)) {
@@ -1725,6 +1938,7 @@
info->var.yoffset = atyfb_save.yoffset;
set_off_pitch(par, info);
}
+ aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
break;
}
}
@@ -1736,69 +1950,10 @@
#if defined(CONFIG_PM) && defined(CONFIG_PCI)
/* Power management routines. Those are used for PowerBook sleep.
- *
- * It appears that Rage LT and Rage LT Pro have different power
- * management registers. There's is some confusion about which
- * chipID is a Rage LT or LT pro :(
*/
-static int aty_power_mgmt_LT(int sleep, struct atyfb_par *par)
-{
- unsigned int pm;
- int timeout;
-
- pm = aty_ld_le32(POWER_MANAGEMENT_LG, par);
- pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;
- aty_st_le32(POWER_MANAGEMENT_LG, pm, par);
- pm = aty_ld_le32(POWER_MANAGEMENT_LG, par);
-
- timeout = 200000;
- if (sleep) {
- /* Sleep */
- pm &= ~PWR_MGT_ON;
- aty_st_le32(POWER_MANAGEMENT_LG, pm, par);
- pm = aty_ld_le32(POWER_MANAGEMENT_LG, par);
- udelay(10);
- pm &= ~(PWR_BLON | AUTO_PWR_UP);
- pm |= SUSPEND_NOW;
- aty_st_le32(POWER_MANAGEMENT_LG, pm, par);
- pm = aty_ld_le32(POWER_MANAGEMENT_LG, par);
- udelay(10);
- pm |= PWR_MGT_ON;
- aty_st_le32(POWER_MANAGEMENT_LG, pm, par);
- do {
- pm = aty_ld_le32(POWER_MANAGEMENT_LG, par);
- udelay(10);
- if ((--timeout) == 0)
- break;
- } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
- } else {
- /* Wakeup */
- pm &= ~PWR_MGT_ON;
- aty_st_le32(POWER_MANAGEMENT_LG, pm, par);
- pm = aty_ld_le32(POWER_MANAGEMENT_LG, par);
- udelay(10);
- pm |= (PWR_BLON | AUTO_PWR_UP);
- pm &= ~SUSPEND_NOW;
- aty_st_le32(POWER_MANAGEMENT_LG, pm, par);
- pm = aty_ld_le32(POWER_MANAGEMENT_LG, par);
- udelay(10);
- pm |= PWR_MGT_ON;
- aty_st_le32(POWER_MANAGEMENT_LG, pm, par);
- do {
- pm = aty_ld_le32(POWER_MANAGEMENT_LG, par);
- udelay(10);
- if ((--timeout) == 0)
- break;
- } while ((pm & PWR_MGT_STATUS_MASK) != 0);
- }
- mdelay(500);
-
- return timeout ? -1 : 0;
-}
-
-static int aty_power_mgmt_LTPro(int sleep, struct atyfb_par *par)
+static int aty_power_mgmt(int sleep, struct atyfb_par *par)
{
- unsigned int pm;
+ u32 pm;
int timeout;
pm = aty_ld_lcd(POWER_MANAGEMENT, par);
@@ -1806,7 +1961,7 @@
aty_st_lcd(POWER_MANAGEMENT, pm, par);
pm = aty_ld_lcd(POWER_MANAGEMENT, par);
- timeout = 200;
+ timeout = 2000;
if (sleep) {
/* Sleep */
pm &= ~PWR_MGT_ON;
@@ -1846,16 +2001,11 @@
break;
} while ((pm & PWR_MGT_STATUS_MASK) != 0);
}
+ mdelay(500);
return timeout ? -1 : 0;
}
-static int aty_power_mgmt(int sleep, struct atyfb_par *par)
-{
- return M64_HAS(LT_SLEEP) ? aty_power_mgmt_LT(sleep, par)
- : aty_power_mgmt_LTPro(sleep, par);
-}
-
static int atyfb_pci_suspend(struct pci_dev *pdev, u32 state)
{
struct fb_info *info = pci_get_drvdata(pdev);
@@ -1990,7 +2140,7 @@
const int *refresh_tbl;
int i, size;
- if (IS_XL(par->pci_id)) {
+ if (IS_XL(par->pci_id) || IS_MOBILITY(par->pci_id)) {
refresh_tbl = ragexl_tbl;
size = sizeof(ragexl_tbl)/sizeof(int);
} else {
@@ -2023,15 +2173,18 @@
int sense;
#endif
+ init_waitqueue_head(&par->vblank.wait);
+ spin_lock_init(&par->int_lock);
+
par->aty_cmap_regs =
(struct aty_cmap_regs *) (par->ati_regbase + 0xc0);
- if (default_pll)
- par->pll_limits.pll_max = default_pll;
- if (default_mclk)
- par->pll_limits.mclk = default_mclk;
- if (default_xclk)
- par->pll_limits.xclk = default_xclk;
+ if (pll)
+ par->pll_limits.pll_max = pll;
+ if (mclk)
+ par->pll_limits.mclk = mclk;
+ if (xclk)
+ par->pll_limits.xclk = xclk;
aty_calc_mem_refresh(par, par->pll_limits.xclk);
par->pll_per = 1000000/par->pll_limits.pll_max;
@@ -2076,7 +2229,7 @@
par->dac_ops = &aty_dac_att21c498;
break;
default:
- printk(" aty_init: DAC type not implemented yet!\n");
+ PRINTKI("aty_init: DAC type not implemented yet!\n");
par->dac_ops = &aty_dac_unsupported;
break;
}
@@ -2097,7 +2250,7 @@
par->pll_ops = &aty_pll_ibm514;
break;
default:
- printk(" aty_init: CLK type not implemented yet!");
+ PRINTKI("aty_init: CLK type not implemented yet!");
par->pll_ops = &aty_pll_unsupported;
break;
}
@@ -2131,11 +2284,12 @@
}
}
#endif /* CONFIG_FB_ATY_CT */
-#if 0
+
+ /* save previous video mode */
aty_get_crtc(par, &saved_crtc);
if(par->pll_ops->get_pll)
par->pll_ops->get_pll(info, &saved_pll);
-#endif
+
i = aty_ld_le32(MEM_CNTL, par);
gtb_memsize = M64_HAS(GTB_DSP);
if (gtb_memsize)
@@ -2189,8 +2343,8 @@
info->fix.smem_len += 0x400000;
}
- if (default_vram) {
- info->fix.smem_len = default_vram * 1024;
+ if (vram) {
+ info->fix.smem_len = vram * 1024;
i = i & ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS);
if (info->fix.smem_len <= 0x80000)
i |= MEM_SIZE_512K;
@@ -2218,16 +2372,16 @@
info->fix.mmio_len = 0x400;
info->fix.accel = FB_ACCEL_ATI_MACH64CT;
} else if (M64_HAS(VT)) {
- info->fix.mmio_start = -0x400;
+ info->fix.mmio_start -= 0x400;
info->fix.mmio_len = 0x800;
info->fix.accel = FB_ACCEL_ATI_MACH64VT;
} else {/* GT */
- info->fix.mmio_start = -0x400;
+ info->fix.mmio_start -= 0x400;
info->fix.mmio_len = 0x800;
info->fix.accel = FB_ACCEL_ATI_MACH64GT;
}
- printk("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK, %d MHz XCLK\n",
+ PRINTKI("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK, %d MHz XCLK\n",
info->fix.smem_len == 0x80000 ? 512 : (info->fix.smem_len >> 20),
info->fix.smem_len == 0x80000 ? 'K' : 'M', ramname, xtal, par->pll_limits.pll_max,
par->pll_limits.mclk, par->pll_limits.xclk);
@@ -2235,10 +2389,10 @@
#if defined(DEBUG) && defined(CONFIG_ATY_CT)
if (M64_HAS(INTEGRATED)) {
int i;
- printk("BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
+ printk("debug atyfb: BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
"DSP_CONFIG DSP_ON_OFF CLOCK_CNTL\n"
- "%08x %08x %08x %08x %08x %08x %08x %08x\n"
- "PLL",
+ "debug atyfb: %08x %08x %08x %08x %08x %08x %08x %08x\n"
+ "debug atyfb: PLL",
aty_ld_le32(BUS_CNTL, par), aty_ld_le32(DAC_CNTL, par),
aty_ld_le32(MEM_CNTL, par), aty_ld_le32(EXT_MEM_CNTL, par),
aty_ld_le32(CRTC_GEN_CNTL, par), aty_ld_le32(DSP_CONFIG, par),
@@ -2292,8 +2446,8 @@
* FIXME: The NVRAM stuff should be put in a Mac-specific file, as it
* applies to all Mac video cards
*/
- if (mode_option) {
- if (!mac_find_mode(&var, info, mode_option, 8))
+ if (mode) {
+ if (!mac_find_mode(&var, info, mode, 8))
var = default_var;
} else {
if (default_vmode == VMODE_CHOOSE) {
@@ -2309,7 +2463,7 @@
else
default_vmode = VMODE_640_480_67;
sense = read_aty_sense(par);
- printk(KERN_INFO "atyfb: monitor sense=%x, mode %d\n",
+ PRINTKI("monitor sense=%x, mode %d\n",
sense, mac_map_monitor_sense(sense));
}
if (default_vmode <= 0 || default_vmode > VMODE_MAX)
@@ -2321,7 +2475,7 @@
}
} else
#endif /* !CONFIG_PPC */
- if (!fb_find_mode(&var, info, mode_option, NULL, 0, &defmode, 8))
+ if (!fb_find_mode(&var, info, mode, NULL, 0, &defmode, 8))
var = default_var;
if (noaccel)
@@ -2330,15 +2484,15 @@
var.accel_flags |= FB_ACCELF_TEXT;
if (var.yres == var.yres_virtual) {
- u32 vram = (info->fix.smem_len - (PAGE_SIZE << 2));
- var.yres_virtual = ((vram * 8) / var.bits_per_pixel) / var.xres_virtual;
+ u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2));
+ var.yres_virtual = ((videoram * 8) / var.bits_per_pixel) / var.xres_virtual;
if (var.yres_virtual < var.yres)
var.yres_virtual = var.yres;
}
if (atyfb_check_var(&var, info)) {
- printk(KERN_CRIT "atyfb: can't set default video mode\n");
- return 0;
+ PRINTKE("can't set default video mode\n");
+ goto aty_init_exit;
}
#ifdef __sparc__
@@ -2346,7 +2500,7 @@
#endif
#ifdef CONFIG_FB_ATY_CT
- if (M64_HAS(INTEGRATED))
+ if (!noaccel && M64_HAS(INTEGRATED))
aty_init_cursor(info);
#endif /* CONFIG_FB_ATY_CT */
info->var = var;
@@ -2354,85 +2508,21 @@
fb_alloc_cmap(&info->cmap, 256, 0);
if (register_framebuffer(info) < 0)
- return 0;
+ goto aty_init_exit;
fb_list = info;
- printk("fb%d: %s frame buffer device on %s\n",
+ PRINTKI("fb%d: %s frame buffer device on %s\n",
info->node, info->fix.id, name);
return 1;
-}
-
-#ifndef MODULE
-int __init atyfb_setup(char *options)
-{
- char *this_opt;
-
- if (!options || !*options)
- return 0;
+
+aty_init_exit:
+ /* restore video mode */
+ aty_set_crtc(par, &saved_crtc);
+ par->pll_ops->set_pll(info, &saved_pll);
- while ((this_opt = strsep(&options, ",")) != NULL) {
- if (!strncmp(this_opt, "noaccel", 7)) {
- noaccel = 1;
- } else if (!strncmp(this_opt, "vram:", 5))
- default_vram =
- simple_strtoul(this_opt + 5, NULL, 0);
- else if (!strncmp(this_opt, "pll:", 4))
- default_pll =
- simple_strtoul(this_opt + 4, NULL, 0);
- else if (!strncmp(this_opt, "mclk:", 5))
- default_mclk =
- simple_strtoul(this_opt + 5, NULL, 0);
- else if (!strncmp(this_opt, "xclk:", 5))
- default_xclk =
- simple_strtoul(this_opt+5, NULL, 0);
-#ifdef CONFIG_PPC
- else if (!strncmp(this_opt, "vmode:", 6)) {
- unsigned int vmode =
- simple_strtoul(this_opt + 6, NULL, 0);
- if (vmode > 0 && vmode <= VMODE_MAX)
- default_vmode = vmode;
- } else if (!strncmp(this_opt, "cmode:", 6)) {
- unsigned int cmode =
- simple_strtoul(this_opt + 6, NULL, 0);
- switch (cmode) {
- case 0:
- case 8:
- default_cmode = CMODE_8;
- break;
- case 15:
- case 16:
- default_cmode = CMODE_16;
- break;
- case 24:
- case 32:
- default_cmode = CMODE_32;
- break;
- }
- }
-#endif
-#ifdef CONFIG_ATARI
- /*
- * Why do we need this silly Mach64 argument?
- * We are already here because of mach64= so its redundant.
- */
- else if (MACH_IS_ATARI
- && (!strncmp(this_opt, "Mach64:", 7))) {
- static unsigned char m64_num;
- static char mach64_str[80];
- strlcpy(mach64_str, this_opt + 7, sizeof(mach64_str));
- if (!store_video_par(mach64_str, m64_num)) {
- m64_num++;
- mach64_count = m64_num;
- }
- }
-#endif
- else
- mode_option = this_opt;
- }
return 0;
}
-#endif /* !MODULE */
#ifdef CONFIG_ATARI
static int __init store_video_par(char *video_str, unsigned char m64_num)
@@ -2440,7 +2530,7 @@
char *p;
unsigned long vmembase, size, guiregbase;
- printk("store_video_par() '%s' \n", video_str);
+ PRINTKI("store_video_par() '%s' \n", video_str);
if (!(p = strsep(&video_str, ";")) || !*p)
goto mach64_invalid;
@@ -2455,7 +2545,7 @@
phys_vmembase[m64_num] = vmembase;
phys_size[m64_num] = size;
phys_guiregbase[m64_num] = guiregbase;
- printk(" stored them all: $%08lX $%08lX $%08lX \n", vmembase, size,
+ PRINTKI("stored them all: $%08lX $%08lX $%08lX \n", vmembase, size,
guiregbase);
return 0;
@@ -2480,7 +2570,14 @@
#ifdef CONFIG_PMAC_BACKLIGHT
if ((_machine == _MACH_Pmac) && blank)
set_backlight_enable(0);
-#endif /* CONFIG_PMAC_BACKLIGHT */
+#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
+ if (par->lcd_table && blank &&
+ (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
+ u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
+ pm &= ~PWR_BLON;
+ aty_st_lcd(POWER_MANAGEMENT, pm, par);
+ }
+#endif
gen_cntl = aty_ld_8(CRTC_GEN_CNTL, par);
if (blank > 0)
@@ -2504,52 +2601,76 @@
#ifdef CONFIG_PMAC_BACKLIGHT
if ((_machine == _MACH_Pmac) && !blank)
set_backlight_enable(1);
-#endif /* CONFIG_PMAC_BACKLIGHT */
+#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
+ if (par->lcd_table && !blank &&
+ (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
+ u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
+ pm |= PWR_BLON;
+ aty_st_lcd(POWER_MANAGEMENT, pm, par);
+ }
+#endif
+
return 0;
}
+static void aty_st_pal(u_int regno, u_int red, u_int green, u_int blue,
+ const struct atyfb_par *par)
+{
+#ifdef CONFIG_ATARI
+ out_8(&par->aty_cmap_regs->windex, regno);
+ out_8(&par->aty_cmap_regs->lut, red);
+ out_8(&par->aty_cmap_regs->lut, green);
+ out_8(&par->aty_cmap_regs->lut, blue);
+#else
+ writeb(regno, &par->aty_cmap_regs->windex);
+ writeb(red, &par->aty_cmap_regs->lut);
+ writeb(green, &par->aty_cmap_regs->lut);
+ writeb(blue, &par->aty_cmap_regs->lut);
+#endif
+}
+
/*
* Set a single color register. The values supplied are already
* rounded down to the hardware's capabilities (according to the
* entries in the var structure). Return != 0 for invalid regno.
+ * !! 4 & 8 = PSEUDO, > 8 = DIRECTCOLOR
*/
static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
- int i, scale;
+ int i, depth;
u32 *pal = info->pseudo_palette;
+ depth = info->var.bits_per_pixel;
+ if (depth == 16)
+ depth = (info->var.green.length == 5) ? 15 : 16;
+
if (par->asleep)
return 0;
- if (regno > 255)
+
+ if (regno > 255 ||
+ (depth == 16 && regno > 63) ||
+ (depth == 15 && regno > 31))
return 1;
+
red >>= 8;
green >>= 8;
blue >>= 8;
- i = aty_ld_8(DAC_CNTL, par) & 0xfc;
- if (M64_HAS(EXTRA_BRIGHT))
- i |= 0x2; /* DAC_CNTL | 0x2 turns off the extra brightness for gt */
- aty_st_8(DAC_CNTL, i, par);
- aty_st_8(DAC_MASK, 0xff, par);
- scale = (M64_HAS(INTEGRATED) && info->var.bits_per_pixel == 16) ? 3 : 0;
-#ifdef CONFIG_ATARI
- out_8(&par->aty_cmap_regs->windex, regno << scale);
- out_8(&par->aty_cmap_regs->lut, red);
- out_8(&par->aty_cmap_regs->lut, green);
- out_8(&par->aty_cmap_regs->lut, blue);
-#else
- writeb(regno << scale, &par->aty_cmap_regs->windex);
- writeb(red, &par->aty_cmap_regs->lut);
- writeb(green, &par->aty_cmap_regs->lut);
- writeb(blue, &par->aty_cmap_regs->lut);
-#endif
- if (regno < 16)
- switch (info->var.bits_per_pixel) {
- case 16:
+
+ par->palette[regno].red = red;
+ par->palette[regno].green = green;
+ par->palette[regno].blue = blue;
+
+ if (regno < 16) {
+ switch (depth) {
+ case 15:
pal[regno] = (regno << 10) | (regno << 5) | regno;
break;
+ case 16:
+ pal[regno] = (regno << 11) | (regno << 5) | regno;
+ break;
case 24:
pal[regno] = (regno << 16) | (regno << 8) | regno;
break;
@@ -2558,6 +2679,32 @@
pal[regno] = (i << 16) | i;
break;
}
+ }
+
+ i = aty_ld_8(DAC_CNTL, par) & 0xfc;
+ if (M64_HAS(EXTRA_BRIGHT))
+ i |= 0x2; /* DAC_CNTL | 0x2 turns off the extra brightness for gt */
+ aty_st_8(DAC_CNTL, i, par);
+ aty_st_8(DAC_MASK, 0xff, par);
+
+ if (M64_HAS(INTEGRATED)) {
+ if (depth == 16) {
+ if (regno < 32)
+ aty_st_pal(regno << 3, red,
+ par->palette[regno<<1].green,
+ blue, par);
+ red = par->palette[regno>>1].red;
+ blue = par->palette[regno>>1].blue;
+ regno <<= 2;
+ } else if (depth == 15) {
+ regno <<= 3;
+ for(i = 0; i < 8; i++) {
+ aty_st_pal(regno + i, red, green, blue, par);
+ }
+ }
+ }
+ aty_st_pal(regno, red, green, blue, par);
+
return 0;
}
@@ -2573,7 +2720,7 @@
struct atyfb_par *par = info->par;
struct pcidev_cookie *pcp;
char prop[128];
- int node, len, i, j;
+ int node, len, i, j, ret;
u32 mem, chip_id;
/* Do not attach when we have a serial console. */
@@ -2602,7 +2749,7 @@
par->mmap_map = kmalloc(j * sizeof(*par->mmap_map), GFP_ATOMIC);
if (!_par->mmap_map) {
- printk(KERN_ERR "atyfb_init: can't alloc mmap_map\n");
+ PRINTKE("atyfb_setup_sparc() can't alloc mmap_map\n");
return -ENOMEM;
}
memset(par->mmap_map, 0, j * sizeof(*par->mmap_map));
@@ -2661,7 +2808,8 @@
j++;
}
- correct_chipset(par);
+ if((ret = correct_chipset(par)))
+ return ret;
if (IS_XL(pdev->device)) {
/*
@@ -2735,7 +2883,7 @@
* Read the PLL to figure actual Refresh Rate.
*/
clock_cntl = aty_ld_8(CLOCK_CNTL, par);
- /* printk("atyfb: CLOCK_CNTL: %02x\n", clock_cntl); */
+ /* DPRINTK("CLOCK_CNTL %02x\n", clock_cntl); */
for (i = 0; i < 16; i++)
pll_regs[i] = aty_ld_pll_ct(i, par);
@@ -2783,6 +2931,7 @@
#else /* __sparc__ */
+#ifdef __i386__
#ifdef CONFIG_FB_ATY_GENERIC_LCD
void aty_init_lcd(struct atyfb_par *par, u32 bios_base)
{
@@ -2805,7 +2954,7 @@
(sig == 0x544d5224) || /* Rage mobility */
(sig == 0x54435824) || /* Rage XC */
(sig == 0x544c5824)) { /* Rage XL */
- printk(KERN_INFO "atyfb: BIOS contains driver information table.\n");
+ PRINTKI("BIOS contains driver information table.\n");
lcd_ofs = (*(u16 *)(driv_inf_tab + 10));
par->lcd_table = 0;
if (lcd_ofs != 0) {
@@ -2904,8 +3053,10 @@
txtformat = "unkown format";
}
}
- printk(KERN_INFO "atyfb: %s%s %s monitor detected: %s\n id=%d, %dx%d pixels, %s\n",
- txtdual ,txtcolour, txtmonitor, model, id, width, height, txtformat);
+ PRINTKI("%s%s %s monitor detected: %s\n",
+ txtdual ,txtcolour, txtmonitor, model);
+ PRINTKI(" id=%d, %dx%d pixels, %s\n",
+ id, width, height, txtformat);
refresh_rates_buf[0] = 0;
refresh_rates = *(u16 *)(par->lcd_table+62);
m = 1;
@@ -2923,7 +3074,7 @@
m = m << 1;
}
default_refresh_rate = (*(u8 *)(par->lcd_table+61) & 0xf0) >> 4;
- printk(KERN_INFO " supports refresh rates [%s], default %d Hz\n",
+ PRINTKI(" supports refresh rates [%s], default %d Hz\n",
refresh_rates_buf, lcd_refresh_rates[default_refresh_rate]);
par->lcd_refreshrate = lcd_refresh_rates[default_refresh_rate];
/* We now need to determine the crtc parameters for the
@@ -2978,10 +3129,10 @@
lcdmodeptr++;
}
if (*lcdmodeptr == 0) {
- printk(KERN_WARNING "atyfb: LCD monitor CRTC parameters not found!!!\n");
+ PRINTKE("LCD monitor CRTC parameters not found!!!\n");
/* To do: Switch to CRT if possible. */
} else {
- printk(KERN_INFO " LCD CRTC parameters: %d.%d %d %d %d %d %d %d %d %d\n",
+ PRINTKI(" LCD CRTC parameters: %d.%d %d %d %d %d %d %d %d %d\n",
1000000 / par->lcd_pixclock, 1000000 % par->lcd_pixclock,
par->lcd_hdisp,
par->lcd_hdisp + par->lcd_right_margin,
@@ -2992,7 +3143,7 @@
par->lcd_vdisp + par->lcd_lower_margin,
par->lcd_vdisp + par->lcd_lower_margin + par->lcd_vsync_len,
par->lcd_vtotal);
- printk(KERN_INFO " : %d %d %d %d %d %d %d %d %d\n",
+ PRINTKI(" : %d %d %d %d %d %d %d %d %d\n",
par->lcd_pixclock,
par->lcd_hblank_len - (par->lcd_right_margin +
par->lcd_hsync_dly + par->lcd_hsync_len),
@@ -3023,7 +3174,7 @@
u16 rom_table_offset, freq_table_offset;
PLL_BLOCK_MACH64 pll_block;
- printk(KERN_INFO "atyfb: Mach64 BIOS is located at %x, mapped at %x.\n", rom_addr, bios_base);
+ PRINTKI("Mach64 BIOS is located at %x, mapped at %x.\n", rom_addr, bios_base);
/* check for frequncy table */
bios_ptr = (u8*)bios_base;
@@ -3031,11 +3182,11 @@
freq_table_offset = bios_ptr[rom_table_offset + 16] | (bios_ptr[rom_table_offset + 17] << 8);
memcpy(&pll_block, bios_ptr + freq_table_offset, sizeof(PLL_BLOCK_MACH64));
- printk(KERN_INFO "atyfb: BIOS frequency table:\n");
- printk(KERN_INFO " PCLK_min_freq %d, PCLK_max_freq %d, ref_freq %d, ref_divider %d\n",
+ PRINTKI("BIOS frequency table:\n");
+ PRINTKI("PCLK_min_freq %d, PCLK_max_freq %d, ref_freq %d, ref_divider %d\n",
pll_block.PCLK_min_freq, pll_block.PCLK_max_freq,
pll_block.ref_freq, pll_block.ref_divider);
- printk(KERN_INFO " MCLK_pwd %d, MCLK_max_freq %d, XCLK_max_freq %d, SCLK_freq %d\n",
+ PRINTKI("MCLK_pwd %d, MCLK_max_freq %d, XCLK_max_freq %d, SCLK_freq %d\n",
pll_block.MCLK_pwd, pll_block.MCLK_max_freq,
pll_block.XCLK_max_freq, pll_block.SCLK_freq);
@@ -3052,13 +3203,14 @@
#endif
ret = 0;
} else {
- printk(KERN_CRIT "atyfb: no BIOS frequency table found, use parameters\n");
+ PRINTKE("no BIOS frequency table found, use parameters\n");
ret = -ENXIO;
}
iounmap((void*)bios_base);
return ret;
}
+#endif /* __i386__ */
static int __devinit atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info, unsigned long addr)
{
@@ -3066,6 +3218,7 @@
u16 tmp;
unsigned long raddr;
struct resource *rrp;
+ int ret = 0;
raddr = addr + 0x7ff000UL;
rrp = &pdev->resource[2];
@@ -3073,7 +3226,7 @@
par->aux_start = rrp->start;
par->aux_size = rrp->end - rrp->start + 1;
raddr = rrp->start;
- printk(KERN_INFO "atyfb: using auxiliary register aperture\n");
+ PRINTKI("using auxiliary register aperture\n");
}
info->fix.mmio_start = raddr;
@@ -3102,16 +3255,16 @@
info->fix.smem_start = addr;
info->screen_base = (char *)ioremap(addr, 0x800000);
if (info->screen_base == NULL) {
- iounmap((void *)par->ati_regbase);
- par->ati_regbase = 0;
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto atyfb_setup_generic_fail;
}
- /* always succeeded ? */
- if (correct_chipset(par) < 0)
- return -ENXIO;
- init_from_bios(par);
-
+ if((ret = correct_chipset(par)))
+ goto atyfb_setup_generic_fail;
+#ifdef __i386__
+ if((ret = init_from_bios(par)))
+ goto atyfb_setup_generic_fail;
+#endif
if (!(aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_EXT_DISP_EN))
par->clk_wr_offset = (inb(R_GENMO) & 0x0CU) >> 2;
else
@@ -3121,16 +3274,21 @@
par->clk_wr_offset = 3;
return 0;
+
+atyfb_setup_generic_fail:
+ iounmap((void *)par->ati_regbase);
+ par->ati_regbase = 0;
+ return ret;
}
#endif /* !__sparc__ */
static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- unsigned long addr;
+ unsigned long addr, res_start, res_size;
struct fb_info *info;
struct resource *rp;
- struct atyfb_par *par = info->par;
+ struct atyfb_par *par;
int i, rc = -ENOMEM;
for (i = sizeof(aty_chips) / sizeof(*aty_chips) - 1; i >= 0; i--)
@@ -3142,7 +3300,7 @@
/* Enable device in PCI config */
if (pci_enable_device(pdev)) {
- printk(KERN_ERR "atyfb: Cannot enable PCI device\n");
+ PRINTKE("Cannot enable PCI device\n");
return -ENXIO;
}
@@ -3154,23 +3312,24 @@
if (!addr)
return -ENXIO;
- /* Allocate framebuffer */
+ /* Reserve space */
+ res_start = rp->start;
+ res_size = rp->end - rp->start + 1;
+ if (!request_mem_region (res_start, res_size, "atyfb"))
+ return -EBUSY;
+
+ /* Allocate framebuffer */
info = framebuffer_alloc(sizeof(struct atyfb_par), &pdev->dev);
if (!info) {
- printk(KERN_ERR "atyfb_init: can't alloc fb_info\n");
+ PRINTKE("atyfb_pci_probe() can't alloc fb_info\n");
return -ENOMEM;
}
par = info->par;
info->fix = atyfb_fix;
par->pci_id = aty_chips[i].pci_id;
-
- /* Reserve space */
- par->res_start = rp->start;
- par->res_size = rp->end - rp->start + 1;
- if (!request_mem_region (par->res_start, par->res_size, "atyfb")) {
- rc = -EBUSY;
- goto err_free;
- }
+ par->res_start = res_start;
+ par->res_size = res_size;
+ par->irq = pdev->irq;
/* Setup "info" structure */
#ifdef __sparc__
@@ -3224,7 +3383,6 @@
release_mem_region(par->aux_start, par->aux_size);
release_mem_region(par->res_start, par->res_size);
-err_free:
framebuffer_release(info);
return rc;
@@ -3244,19 +3402,21 @@
for (m64_num = 0; m64_num < mach64_count; m64_num++) {
if (!phys_vmembase[m64_num] || !phys_size[m64_num] ||
!phys_guiregbase[m64_num]) {
- printk(" phys_*[%d] parameters not set => returning early. \n", m64_num);
+ PRINTKI("phys_*[%d] parameters not set => returning early. \n", m64_num);
continue;
}
info = framebuffer_alloc(sizeof(struct atyfb_par), NULL);
if (!info) {
- printk("atyfb_init: can't alloc fb_info\n");
+ PRINTKE("atyfb_atari_probe() can't alloc fb_info\n");
return -ENOMEM;
}
par = info->par;
info->fix = atyfb_fix;
+ par->irq = (unsigned int) -1; /* something invalid */
+
/*
* Map the video memory (physical address given) to somewhere in the
* kernel address space.
@@ -3298,6 +3458,10 @@
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
+ /* restore video mode */
+ aty_set_crtc(par, &saved_crtc);
+ par->pll_ops->set_pll(info, &saved_pll);
+
unregister_framebuffer(info);
#ifndef __sparc__
@@ -3375,4 +3539,93 @@
#endif
}
+int __init atyfb_setup(char *options)
+{
+ char *this_opt;
+
+ if (!options || !*options)
+ return 0;
+
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+ if (!strncmp(this_opt, "noaccel", 7)) {
+ noaccel = 1;
+ } else if (!strncmp(this_opt, "vram:", 5))
+ vram = simple_strtoul(this_opt + 5, NULL, 0);
+ else if (!strncmp(this_opt, "pll:", 4))
+ pll = simple_strtoul(this_opt + 4, NULL, 0);
+ else if (!strncmp(this_opt, "mclk:", 5))
+ mclk = simple_strtoul(this_opt + 5, NULL, 0);
+ else if (!strncmp(this_opt, "xclk:", 5))
+ xclk = simple_strtoul(this_opt+5, NULL, 0);
+#ifdef CONFIG_PPC
+ else if (!strncmp(this_opt, "vmode:", 6)) {
+ unsigned int vmode =
+ simple_strtoul(this_opt + 6, NULL, 0);
+ if (vmode > 0 && vmode <= VMODE_MAX)
+ default_vmode = vmode;
+ } else if (!strncmp(this_opt, "cmode:", 6)) {
+ unsigned int cmode =
+ simple_strtoul(this_opt + 6, NULL, 0);
+ switch (cmode) {
+ case 0:
+ case 8:
+ default_cmode = CMODE_8;
+ break;
+ case 15:
+ case 16:
+ default_cmode = CMODE_16;
+ break;
+ case 24:
+ case 32:
+ default_cmode = CMODE_32;
+ break;
+ }
+ }
+#endif
+#ifdef CONFIG_ATARI
+ /*
+ * Why do we need this silly Mach64 argument?
+ * We are already here because of mach64= so its redundant.
+ */
+ else if (MACH_IS_ATARI
+ && (!strncmp(this_opt, "Mach64:", 7))) {
+ static unsigned char m64_num;
+ static char mach64_str[80];
+ strlcpy(mach64_str, this_opt + 7, sizeof(mach64_str));
+ if (!store_video_par(mach64_str, m64_num)) {
+ m64_num++;
+ mach64_count = m64_num;
+ }
+ }
+#endif
+ else
+ mode = this_opt;
+ }
+ return 0;
+}
+
+#ifdef MODULE
+module_init(atyfb_init);
+module_exit(atyfb_exit);
+#endif
+
+MODULE_DESCRIPTION("FBDev driver for ATI Mach64 cards");
MODULE_LICENSE("GPL");
+module_param(noaccel, bool, 0);
+MODULE_PARM_DESC(noaccel, "bool: disable acceleration");
+module_param(vram, int, 0);
+MODULE_PARM_DESC(vram, "int: override size of video ram");
+module_param(pll, int, 0);
+MODULE_PARM_DESC(pll, "int: override video clock");
+module_param(mclk, int, 0);
+MODULE_PARM_DESC(mclk, "int: override memory clock");
+module_param(xclk, int, 0);
+MODULE_PARM_DESC(xclk, "int: override accelerated engine clock");
+#ifdef CONFIG_PPC
+module_param(vmode, int, 0);
+MODULE_PARM_DESC(vmode, "int: video mode for mac");
+module_param(cmode, int, 0);
+MODULE_PARM_DESC(cmode, "int: color mode for mac");
+#endif
+module_param(mode, charp, 0);
+MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
diff -ur -X patches/exclude linux-2.6.7.js3/drivers/video/aty/mach64_ct.c linux-2.6.7.ak/drivers/video/aty/mach64_ct.c
--- linux-2.6.7.js3/drivers/video/aty/mach64_ct.c 2004-06-27 01:35:27.000000000 +0200
+++ linux-2.6.7.ak/drivers/video/aty/mach64_ct.c 2004-08-04 22:32:10.000000000 +0200
@@ -115,7 +115,6 @@
static int aty_dsp_gt(const struct fb_info *info, u32 bpp, struct pll_ct *pll)
{
- struct atyfb_par *par = (struct atyfb_par *) info->par;
u32 dsp_off, dsp_on, dsp_xclks;
u32 multiplier, divider, ras_multiplier, ras_divider, tmp;
u8 vshift, xshift;
@@ -137,6 +136,8 @@
#ifdef CONFIG_FB_ATY_GENERIC_LCD
if (pll->xres != 0) {
+ struct atyfb_par *par = (struct atyfb_par *) info->par;
+
multiplier = multiplier * par->lcd_width;
divider = divider * pll->xres & ~7;
@@ -281,8 +282,8 @@
#ifdef CONFIG_FB_ATY_GENERIC_LCD
if (par->lcd_table != 0) {
/* turn off LCD */
- lcd_gen_cntrl = aty_ld_le32(LCD_GEN_CNTL, par);
- aty_st_le32(LCD_GEN_CNTL, lcd_gen_cntrl & ~LCD_ON, par);
+ lcd_gen_cntrl = aty_ld_lcd(LCD_GEN_CNTL, par);
+ aty_st_lcd(LCD_GEN_CNTL, lcd_gen_cntrl & ~LCD_ON, par);
}
#endif
aty_st_8(CLOCK_CNTL, par->clk_wr_offset | CLOCK_STROBE, par);
@@ -351,12 +352,12 @@
#ifdef CONFIG_FB_ATY_GENERIC_LCD
if (par->lcd_table != 0) {
/* restore LCD */
- aty_st_le32(LCD_GEN_CNTL, lcd_gen_cntrl, par);
+ aty_st_lcd(LCD_GEN_CNTL, lcd_gen_cntrl, par);
}
#endif
}
-#if 0
-void aty_get_pll_ct(const struct fb_info *info, union aty_pll *pll)
+
+void __init aty_get_pll_ct(const struct fb_info *info, union aty_pll *pll)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
u8 tmp, clock;
@@ -378,7 +379,7 @@
pll->ct.dsp_on_off = aty_ld_le32(DSP_ON_OFF, par);
}
}
-#endif
+
int __init aty_init_pll_ct(const struct fb_info *info, union aty_pll *pll) {
struct atyfb_par *par = (struct atyfb_par *) info->par;
u8 mpost_div, xpost_div, sclk_post_div_real, sclk_fb_div, spll_cntl2;
@@ -526,10 +527,10 @@
__FUNCTION__, pllmclk, pllmclk / pll->ct.xclk_post_div_real);
#endif
- pll->ct.pll_gen_cntl = OSC_EN;
-
- if (M64_HAS(NO_EXT_PLL))
- pll->ct.pll_gen_cntl |= (DLL_PWDN | FORCE_DCLK_TRI_STATE);
+ if (M64_HAS(SDRAM_MAGIC_PLL) && (par->ram_type >= SDRAM))
+ pll->ct.pll_gen_cntl = OSC_EN;
+ else
+ pll->ct.pll_gen_cntl = OSC_EN | DLL_PWDN /* | FORCE_DCLK_TRI_STATE */;
if (M64_HAS(MAGIC_POSTDIV))
pll->ct.pll_ext_cntl = 0;
@@ -608,5 +609,6 @@
.var_to_pll = aty_var_to_pll_ct,
.pll_to_var = aty_pll_to_var_ct,
.set_pll = aty_set_pll_ct,
+ .get_pll = aty_get_pll_ct,
.init_pll = aty_init_pll_ct
};
diff -ur -X patches/exclude linux-2.6.7.js3/drivers/video/aty/mach64_cursor.c linux-2.6.7.ak/drivers/video/aty/mach64_cursor.c
--- linux-2.6.7.js3/drivers/video/aty/mach64_cursor.c 2004-06-27 01:35:27.000000000 +0200
+++ linux-2.6.7.ak/drivers/video/aty/mach64_cursor.c 2004-07-23 23:51:53.000000000 +0200
@@ -71,26 +71,6 @@
0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00
};
-void aty_set_cursor_shape(struct fb_info *info, u8 *dst, u8 *src, unsigned int width)
-{
- int i, j, offset = info->sprite.scan_align - width*2;
- u8 *mask = info->cursor.mask, m, b;
-
- for (i = 0; i < info->cursor.image.height; i++) {
- for (j = 0; j < width; j++) {
- b = *src++;
- m = *mask++;
- // Upper 4 bits of mask data
- fb_writeb(cursor_mask_lookup[m >> 4 ] |
- cursor_bits_lookup[(b & m) >> 4], dst++);
- // Lower 4 bits of mask
- fb_writeb(cursor_mask_lookup[m & 0x0f ] |
- cursor_bits_lookup[(b & m) & 0x0f], dst++);
- }
- dst += offset;
- }
-}
-
int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
@@ -176,9 +156,46 @@
}
if (cursor->set & FB_CUR_SETSHAPE) {
- // Clear cursor image with 1010101010...
- fb_memset(info->sprite.addr, 0xaa, 1024);
- fb_load_cursor_image(info);
+ u8 *src = (u8 *)cursor->image.data;
+ u8 *msk = (u8 *)info->cursor.mask;
+ u8 *dst = (u8 *)info->sprite.addr;
+ unsigned int width = (info->cursor.image.width + 7) >> 3;
+ unsigned int height = info->cursor.image.height;
+ unsigned int align = info->sprite.scan_align;
+
+ unsigned int i, j, offset;
+ u8 m, b;
+
+ // Clear cursor image with 1010101010...
+ fb_memset(dst, 0xaa, 1024);
+
+ offset = align - width*2;
+
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j++) {
+ b = *src++;
+ m = *msk++;
+ switch (info->cursor.rop) {
+ case ROP_XOR:
+ // Upper 4 bits of mask data
+ fb_writeb(cursor_mask_lookup[m >> 4 ] |
+ cursor_bits_lookup[(b ^ m) >> 4], dst++);
+ // Lower 4 bits of mask
+ fb_writeb(cursor_mask_lookup[m & 0x0f ] |
+ cursor_bits_lookup[(b ^ m) & 0x0f], dst++);
+ break;
+ case ROP_COPY:
+ // Upper 4 bits of mask data
+ fb_writeb(cursor_mask_lookup[m >> 4 ] |
+ cursor_bits_lookup[(b & m) >> 4], dst++);
+ // Lower 4 bits of mask
+ fb_writeb(cursor_mask_lookup[m & 0x0f ] |
+ cursor_bits_lookup[(b & m) & 0x0f], dst++);
+ break;
+ }
+ }
+ dst += offset;
+ }
}
if (cursor->enable) {
@@ -210,10 +227,12 @@
if (!info->sprite.addr)
return -ENXIO;
info->sprite.size = PAGE_SIZE;
- info->sprite.scan_align = 16; // Scratch pad 64 bytes wide
- info->sprite.buf_align = 16; // *64; // and 64 lines tall.
+ info->sprite.scan_align = 16; /* Scratch pad 64 bytes wide */
+ info->sprite.buf_align = 16; /* and 64 lines tall. */
info->sprite.flags = FB_PIXMAP_IO;
- info->sprite.outbuf = aty_set_cursor_shape;
+
+ info->fbops->fb_cursor = atyfb_cursor;
+
return 0;
}
diff -ur -X patches/exclude linux-2.6.7.js3/drivers/video/modedb.c linux-2.6.7.ak/drivers/video/modedb.c
--- linux-2.6.7.js3/drivers/video/modedb.c 2004-06-16 07:19:22.000000000 +0200
+++ linux-2.6.7.ak/drivers/video/modedb.c 2004-07-21 22:05:06.000000000 +0200
@@ -16,12 +16,14 @@
#include <linux/fb.h>
#include <linux/sched.h>
-#undef DEBUG
+#define DEBUG
#define name_matches(v, s, l) \
((v).name && !strncmp((s), (v).name, (l)) && strlen((v).name) == (l))
#define res_matches(v, x, y) \
((v).xres == (x) && (v).yres == (y))
+#define refresh_closest_to(v, x, y) \
+ ((!y || (abs((x)->refresh - (v)) < abs((y)->refresh - (v))))?x:y)
#ifdef DEBUG
#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
@@ -126,16 +128,16 @@
0, FB_VMODE_NONINTERLACED
}, {
/* 1400x1050 @ 60Hz, 63.9 kHz hsync */
- NULL, 68, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3,
- 0, FB_VMODE_NONINTERLACED
+ NULL, 60, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3,
+ 0, FB_VMODE_NONINTERLACED
}, {
- /* 1400x1050 @ 75,107 Hz, 82,392 kHz +hsync +vsync*/
- NULL, 75, 1400, 1050, 9271, 120, 56, 13, 0, 112, 3,
- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ /* 1400x1050 @ 64 Hz, 68.8 kHz */
+ NULL, 64, 1400, 1050, 8197, 184, 28, 10, 2, 152, 12,
+ 0, FB_VMODE_NONINTERLACED
}, {
- /* 1400x1050 @ 60 Hz, ? kHz +hsync +vsync*/
- NULL, 60, 1400, 1050, 9259, 128, 40, 12, 0, 112, 3,
- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ /* 1400x1050 @ 75 Hz, 81,3 kHz */
+ NULL, 75, 1400, 1050, 6418, 128, 64, 26, 2, 320, 12,
+ 0, FB_VMODE_NONINTERLACED
}, {
/* 1024x768 @ 85 Hz, 70.24 kHz hsync */
NULL, 85, 1024, 768, 10111, 192, 32, 34, 14, 160, 6,
@@ -528,25 +530,44 @@
res_specified = 1;
}
done:
- for (i = refresh_specified; i >= 0; i--) {
- DPRINTK("Trying specified video mode%s\n",
- i ? "" : " (ignoring refresh rate)");
- for (j = 0; j < dbsize; j++)
- if ((name_matches(db[j], name, namelen) ||
- (res_specified && res_matches(db[j], xres, yres))) &&
- (!i || db[j].refresh == refresh) &&
- !fb_try_mode(var, info, &db[j], bpp))
- return 2-i;
+ {
+ if(refresh_specified) {
+ const struct fb_videomode *na = 0; /* nearest accepted with given refreshrate */
+
+ DPRINTK("Trying all video modes with refresh rate %i\n", refresh);
+
+ for(j = 0; j < dbsize; j++) {
+ if((name_matches(db[j], name, namelen) || (res_specified && res_matches(db[j], xres, yres)))) {
+ if(!fb_try_mode(var, info, &db[j], bpp)) {
+ na = refresh_closest_to(refresh, &db[j], na);
+ }
+ }
+ }
+ if(na) {
+ DPRINTK("Try the winner %ix%i@%i one more time\n", na->xres, na->yres, na->refresh);
+ if(!fb_try_mode(var, info, na, bpp))
+ return 1;
+ }
+ } else {
+ DPRINTK("Trying specified video mode(ignoring refresh rate), first win\n");
+ for(j = 0; j < dbsize; j++) {
+ if((name_matches(db[j], name, namelen) || (res_specified && res_matches(db[j], xres, yres)))) {
+ if(!fb_try_mode(var, info, &db[j], bpp)) {
+ return 2;
+ }
+ }
+ }
+ }
}
}
DPRINTK("Trying default video mode\n");
- if (!fb_try_mode(var, info, default_mode, default_bpp))
+ if(!fb_try_mode(var, info, default_mode, default_bpp))
return 3;
DPRINTK("Trying all modes\n");
- for (i = 0; i < dbsize; i++)
- if (!fb_try_mode(var, info, &db[i], default_bpp))
+ for(i = 0; i < dbsize; i++)
+ if(!fb_try_mode(var, info, &db[i], default_bpp))
return 4;
DPRINTK("No valid mode found\n");
[-- Attachment #3: mach64-js3-ak6b.diff --]
[-- Type: text/x-diff, Size: 6580 bytes --]
diff -ur -X patches/exclude linux-2.6.7.js3/include/video/mach64.h linux-2.6.7.ak/include/video/mach64.h
--- linux-2.6.7.js3/include/video/mach64.h 2004-06-27 01:35:27.000000000 +0200
+++ linux-2.6.7.ak/include/video/mach64.h 2004-07-28 21:55:35.000000000 +0200
@@ -68,6 +68,8 @@
#define I2C_CNTL_0 0x003C /* Dword offset 0_0F */
+#define DSTN_CONTROL_LG 0x003C /* Dword offset 0_0F (LG) */
+
/* Overscan */
#define OVR_CLR 0x0040 /* Dword offset 0_10 */
#define OVR2_CLR 0x0040 /* Dword offset 0_10 */
@@ -101,7 +103,7 @@
#define CUR_HORZ_VERT_OFF 0x0070 /* Dword offset 0_1C */
#define CUR2_HORZ_VERT_OFF 0x0070 /* Dword offset 0_1C */
-#define CONFIG_PANEL_LG 0x0074 /* Dword offset 0_1D */
+#define CONFIG_PANEL_LG 0x0074 /* Dword offset 0_1D (LG) */
/* General I/O Control */
#define GP_IO 0x0078 /* Dword offset 0_1E */
@@ -153,6 +155,8 @@
#define LCD_INDEX 0x00A4 /* Dword offset 0_29 */
#define LCD_DATA 0x00A8 /* Dword offset 0_2A */
+#define HFB_PITCH_ADDR_LG 0x00A8 /* Dword offset 0_2A (LG) */
+
/* Memory Control */
#define EXT_MEM_CNTL 0x00AC /* Dword offset 0_2B */
#define MEM_CNTL 0x00B0 /* Dword offset 0_2C */
@@ -161,6 +165,8 @@
#define I2C_CNTL_1 0x00BC /* Dword offset 0_2F */
+#define LT_GIO_LG 0x00BC /* Dword offset 0_2F (LG) */
+
/* DAC Control */
#define DAC_REGS 0x00C0 /* Dword offset 0_30 */
#define DAC_W_INDEX 0x00C0 /* Dword offset 0_30 */
@@ -171,14 +177,16 @@
#define EXT_DAC_REGS 0x00C8 /* Dword offset 0_32 */
+#define HORZ_STRETCHING_LG 0x00C8 /* Dword offset 0_32 (LG) */
+#define VERT_STRETCHING_LG 0x00CC /* Dword offset 0_33 (LG) */
+
/* Test and Debug */
#define GEN_TEST_CNTL 0x00D0 /* Dword offset 0_34 */
/* Custom Macros */
#define CUSTOM_MACRO_CNTL 0x00D4 /* Dword offset 0_35 */
-#define LCD_GEN_CNTL_LG 0x00D4 /* Dword offset 0_35 */
-
+#define LCD_GEN_CNTL_LG 0x00D4 /* Dword offset 0_35 (LG) */
#define POWER_MANAGEMENT_LG 0x00D8 /* Dword offset 0_36 (LG) */
/* Configuration */
@@ -508,7 +516,7 @@
#define SCALER_BUF0_OFFSET_V 0x05D8 /* Dword offset 1_76 */
#define SCALER_BUF1_OFFSET_U 0x05DC /* Dword offset 1_77 */
#define SCALER_BUF1_OFFSET_V 0x05E0 /* Dword offset 1_78 */
-
+
/* Setup Engine */
#define VERTEX_1_S 0x0640 /* Dword offset 1_90 */
#define VERTEX_1_T 0x0644 /* Dword offset 1_91 */
@@ -622,10 +630,70 @@
#define CRTC_CUR_B_TEST 0x80000000
#define CRTC_CRNT_VLINE 0x07f00000
-#define CRTC_VBLANK 0x00000001
#define CRTC_PRESERVED_MASK 0x0001f000
+#define CRTC_VBLANK 0x00000001
+#define CRTC_VBLANK_INT_EN 0x00000002
+#define CRTC_VBLANK_INT 0x00000004
+#define CRTC_VBLANK_INT_AK CRTC_VBLANK_INT
+#define CRTC_VLINE_INT_EN 0x00000008
+#define CRTC_VLINE_INT 0x00000010
+#define CRTC_VLINE_INT_AK CRTC_VLINE_INT
+#define CRTC_VLINE_SYNC 0x00000020
+#define CRTC_FRAME 0x00000040
+#define SNAPSHOT_INT_EN 0x00000080
+#define SNAPSHOT_INT 0x00000100
+#define SNAPSHOT_INT_AK SNAPSHOT_INT
+#define I2C_INT_EN 0x00000200
+#define I2C_INT 0x00000400
+#define I2C_INT_AK I2C_INT
+#define CRTC2_VBLANK 0x00000800
+#define CRTC2_VBLANK_INT_EN 0x00001000
+#define CRTC2_VBLANK_INT 0x00002000
+#define CRTC2_VBLANK_INT_AK CRTC2_VBLANK_INT
+#define CRTC2_VLINE_INT_EN 0x00004000
+#define CRTC2_VLINE_INT 0x00008000
+#define CRTC2_VLINE_INT_AK CRTC2_VLINE_INT
+#define CAPBUF0_INT_EN 0x00010000
+#define CAPBUF0_INT 0x00020000
+#define CAPBUF0_INT_AK CAPBUF0_INT
+#define CAPBUF1_INT_EN 0x00040000
+#define CAPBUF1_INT 0x00080000
+#define CAPBUF1_INT_AK CAPBUF1_INT
+#define OVERLAY_EOF_INT_EN 0x00100000
+#define OVERLAY_EOF_INT 0x00200000
+#define OVERLAY_EOF_INT_AK OVERLAY_EOF_INT
+#define ONESHOT_CAP_INT_EN 0x00400000
+#define ONESHOT_CAP_INT 0x00800000
+#define ONESHOT_CAP_INT_AK ONESHOT_CAP_INT
+#define BUSMASTER_EOL_INT_EN 0x01000000
+#define BUSMASTER_EOL_INT 0x02000000
+#define BUSMASTER_EOL_INT_AK BUSMASTER_EOL_INT
+#define GP_INT_EN 0x04000000
+#define GP_INT 0x08000000
+#define GP_INT_AK GP_INT
+#define CRTC2_VLINE_SYNC 0x10000000
+#define SNAPSHOT2_INT_EN 0x20000000
+#define SNAPSHOT2_INT 0x40000000
+#define SNAPSHOT2_INT_AK SNAPSHOT2_INT
+#define VBLANK_BIT2_INT 0x80000000
+#define VBLANK_BIT2_INT_AK VBLANK_BIT2_INT
+
+#define CRTC_INT_EN_MASK (CRTC_VBLANK_INT_EN | \
+ CRTC_VLINE_INT_EN | \
+ SNAPSHOT_INT_EN | \
+ I2C_INT_EN | \
+ CRTC2_VBLANK_INT_EN | \
+ CRTC2_VLINE_INT_EN | \
+ CAPBUF0_INT_EN | \
+ CAPBUF1_INT_EN | \
+ OVERLAY_EOF_INT_EN | \
+ ONESHOT_CAP_INT_EN | \
+ BUSMASTER_EOL_INT_EN | \
+ GP_INT_EN | \
+ SNAPSHOT2_INT_EN)
+
/* DAC control values */
#define DAC_EXT_SEL_RS2 0x01
@@ -640,6 +708,24 @@
#define DAC_BLANK_ADJ_1 0x00000800
#define DAC_BLANK_ADJ_2 0x00001000
+/* DAC control values (my source XL/XC Register reference) */
+#define DAC_OUTPUT_MASK 0x00000001 /* 0 - PAL, 1 - NTSC */
+#define DAC_MISTERY_BIT 0x00000002 /* PS2 ? RS343 ?, EXTRA_BRIGHT for GT */
+#define DAC_BLANKING 0x00000004
+#define DAC_CMP_DISABLE 0x00000008
+#define DAC1_CLK_SEL 0x00000010
+#define PALETTE_ACCESS_CNTL 0x00000020
+#define PALETTE2_SNOOP_EN 0x00000040
+#define DAC_CMP_OUTPUT 0x00000080 /* read only */
+/* #define DAC_8BIT_EN is ok */
+#define CRT_SENSE 0x00000800 /* read only */
+#define CRT_DETECTION_ON 0x00001000
+#define DAC_VGA_ADR_EN 0x00002000
+#define DAC_FEA_CON_EN 0x00004000
+#define DAC_PDWN 0x00008000
+#define DAC_TYPE_MASK 0x00070000 /* read only */
+
+
/* Mix control values */
@@ -912,10 +998,14 @@
#define GI_CHIP_ID 0x4749 /* RAGE PRO, BGA, PCI33 only */
#define GP_CHIP_ID 0x4750 /* RAGE PRO, PQFP, PCI33, full 3D */
#define GQ_CHIP_ID 0x4751 /* RAGE PRO, PQFP, PCI33, limited 3D */
-#define LM_CHIP_ID 0x4c4d /* RAGE Mobility PCI */
-#define LN_CHIP_ID 0x4c4e /* RAGE Mobility AGP */
+#define LM_CHIP_ID 0x4c4d /* RAGE Mobility AGP, full function */
+#define LN_CHIP_ID 0x4c4e /* RAGE Mobility AGP */
+#define LR_CHIP_ID 0x4c52 /* RAGE Mobility PCI, full function */
+#define LS_CHIP_ID 0x4c53 /* RAGE Mobility PCI */
+#define IS_MOBILITY(id) ((id)==LM_CHIP_ID || (id)==LN_CHIP_ID || \
+ (id)==LR_CHIP_ID || (id)==LS_CHIP_ID)
/* Mach64 major ASIC revisions */
#define MACH64_ASIC_NEC_VT_A3 0x08
#define MACH64_ASIC_NEC_VT_A4 0x48
^ permalink raw reply [flat|nested] 7+ messages in thread