* [PATCH] 2.5.59 for ATI Mach64(port from Daniel code for 2.5.59)
@ 2003-01-17 21:27 Alexander Kern
2003-01-18 11:01 ` Alexander Kern
0 siblings, 1 reply; 3+ messages in thread
From: Alexander Kern @ 2003-01-17 21:27 UTC (permalink / raw)
To: Linux-fbdev-devel
[-- Attachment #1: Type: text/plain, Size: 105 bytes --]
Hi, tested with ATI RAGE 3D MOBILITY M1 (P/M). 1400x1050 works, i assume all
others must work too.
[-- Attachment #2: aty_rage_mobility.2.5.59-2.patch --]
[-- Type: text/x-diff, Size: 3820 bytes --]
diff -u -r /usr/src/linux-2.5.orig/include/video/mach64.h /usr/src/linux-2.5.XX/include/video/mach64.h
--- /usr/src/linux-2.5.orig/include/video/mach64.h 2003-01-02 04:22:23.000000000 +0100
+++ /usr/src/linux-2.5.XX/include/video/mach64.h 2003-01-11 00:40:00.000000000 +0100
@@ -558,7 +558,7 @@
#define CRTC_CSYNC_EN 0x00000010
#define CRTC_PIX_BY_2_EN 0x00000020 /* unused on RAGE */
#define CRTC_DISPLAY_DIS 0x00000040
-#define CRTC_VGA_XOVERSCAN 0x00000040
+#define CRTC_VGA_XOVERSCAN 0x00000080
#define CRTC_PIX_WIDTH_MASK 0x00000700
#define CRTC_PIX_WIDTH_4BPP 0x00000100
@@ -1148,6 +1148,65 @@
#define APC_LUT_MN 0x39
#define APC_LUT_OP 0x3A
+/* Values in LCD_GEN_CTRL */
+#define CRT_ON 0x00000001ul
+#define LCD_ON 0x00000002ul
+#define HORZ_DIVBY2_EN 0x00000004ul
+#define DONT_DS_ICON 0x00000008ul
+#define LOCK_8DOT 0x00000010ul
+#define ICON_ENABLE 0x00000020ul
+#define DONT_SHADOW_VPAR 0x00000040ul
+#define V2CLK_PM_EN 0x00000080ul
+#define RST_FM 0x00000100ul
+#define DISABLE_PCLK_RESET 0x00000200ul /* XC/XL */
+#define DIS_HOR_CRT_DIVBY2 0x00000400ul
+#define SCLK_SEL 0x00000800ul
+#define SCLK_DELAY 0x0000f000ul
+#define TVCLK_PM_EN 0x00010000ul
+#define VCLK_DAC_PM_EN 0x00020000ul
+#define VCLK_LCD_OFF 0x00040000ul
+#define SELECT_WAIT_4MS 0x00080000ul
+#define XTALIN_PM_EN 0x00080000ul /* XC/XL */
+#define V2CLK_DAC_PM_EN 0x00100000ul
+#define LVDS_EN 0x00200000ul
+#define LVDS_PLL_EN 0x00400000ul
+#define LVDS_PLL_RESET 0x00800000ul
+#define LVDS_RESERVED_BITS 0x07000000ul
+#define CRTC_RW_SELECT 0x08000000ul /* LTPro */
+#define USE_SHADOWED_VEND 0x10000000ul
+#define USE_SHADOWED_ROWCUR 0x20000000ul
+#define SHADOW_EN 0x40000000ul
+#define SHADOW_RW_EN 0x80000000ul
+
+/* Values in HORZ_STRETCHING */
+#define HORZ_STRETCH_BLEND 0x00000ffful
+#define HORZ_STRETCH_RATIO 0x0000fffful
+#define HORZ_STRETCH_LOOP 0x00070000ul
+#define HORZ_STRETCH_LOOP09 0x00000000ul
+#define HORZ_STRETCH_LOOP11 0x00010000ul
+#define HORZ_STRETCH_LOOP12 0x00020000ul
+#define HORZ_STRETCH_LOOP14 0x00030000ul
+#define HORZ_STRETCH_LOOP15 0x00040000ul
+/* ? 0x00050000ul */
+/* ? 0x00060000ul */
+/* ? 0x00070000ul */
+/* ? 0x00080000ul */
+#define HORZ_PANEL_SIZE 0x0ff00000ul /* XC/XL */
+/* ? 0x10000000ul */
+#define AUTO_HORZ_RATIO 0x20000000ul /* XC/XL */
+#define HORZ_STRETCH_MODE 0x40000000ul
+#define HORZ_STRETCH_EN 0x80000000ul
+
+/* Values in VERT_STRETCHING */
+#define VERT_STRETCH_RATIO0 0x000003fful
+#define VERT_STRETCH_RATIO1 0x000ffc00ul
+#define VERT_STRETCH_RATIO2 0x3ff00000ul
+#define VERT_STRETCH_USE0 0x40000000ul
+#define VERT_STRETCH_EN 0x80000000ul
+
+/* Values in EXT_VERT_STRETCH */
+#define AUTO_VERT_RATIO 0x00400000ul
+#define VERT_STRETCH_MODE 0x00000400ul
/* Values in LCD_MISC_CNTL */
#define BIAS_MOD_LEVEL_MASK 0x0000ff00
[-- Attachment #3: aty_rage_mobility.2.5.59-1b.patch --]
[-- Type: text/x-diff, Size: 72675 bytes --]
diff -u -r /usr/src/linux-2.5.orig/drivers/video/Kconfig /usr/src/linux-2.5.XX/drivers/video/Kconfig
--- /usr/src/linux-2.5.orig/drivers/video/Kconfig 2003-01-17 16:13:53.000000000 +0100
+++ /usr/src/linux-2.5.XX/drivers/video/Kconfig 2003-01-17 16:15:59.000000000 +0100
@@ -704,6 +704,13 @@
framebuffer device. The ATI product support page for these boards
is at <http://support.ati.com/products/pc/mach64/>.
+config FB_ATY_GENERIC_LCD
+ bool "generic LCD support (EXPERIMENTAL)"
+ depends on FB_ATY_CT
+ help
+ say Y here to support ATI Rage 3D MOBILITY M1 or others flawours
+ of Mach64 on Notebooks
+
config FB_ATY_GX
bool "Mach64 GX support" if PCI
depends on FB_ATY
diff -u -r /usr/src/linux-2.5.orig/drivers/video/Makefile /usr/src/linux-2.5.XX/drivers/video/Makefile
--- /usr/src/linux-2.5.orig/drivers/video/Makefile 2003-01-17 16:13:53.000000000 +0100
+++ /usr/src/linux-2.5.XX/drivers/video/Makefile 2003-01-17 16:19:00.000000000 +0100
@@ -71,7 +71,7 @@
obj-$(CONFIG_FB_MATROX) += matrox/
obj-$(CONFIG_FB_RIVA) += riva/ cfbimgblt.o vgastate.o
obj-$(CONFIG_FB_SIS) += sis/
-obj-$(CONFIG_FB_ATY) += aty/ cfbimgblt.o cfbfillrect.o cfbimgblt.o
+obj-$(CONFIG_FB_ATY) += aty/ cfbimgblt.o cfbfillrect.o cfbcopyarea.o
obj-$(CONFIG_FB_I810) += i810/ cfbfillrect.o cfbcopyarea.o \
cfbimgblt.o vgastate.o
diff -u -r /usr/src/linux-2.5.orig/drivers/video/aty/atyfb.h /usr/src/linux-2.5.XX/drivers/video/aty/atyfb.h
--- /usr/src/linux-2.5.orig/drivers/video/aty/atyfb.h 2003-01-17 16:13:53.000000000 +0100
+++ /usr/src/linux-2.5.XX/drivers/video/aty/atyfb.h 2003-01-17 17:54:54.000000000 +0100
@@ -10,6 +10,9 @@
struct crtc {
u32 vxres;
u32 vyres;
+ u32 xoffset;
+ u32 yoffset;
+ u32 bpp;
u32 h_tot_disp;
u32 h_sync_strt_wid;
u32 v_tot_disp;
@@ -18,6 +21,11 @@
u32 gen_cntl;
u32 dp_pix_width; /* acceleration */
u32 dp_chain_mask; /* acceleration */
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+ u32 monitors_enabled; /* LCD monitor support */
+ u16 h_stretching; /* LCD monitor support */
+ u16 v_stretching; /* LCD monitor support */
+#endif
};
struct pll_514 {
@@ -33,16 +41,16 @@
};
struct pll_ct {
- u8 pll_ref_div;
+/* u8 pll_ref_div;
u8 pll_gen_cntl;
- u8 mclk_fb_div;
+ u8 mclk_fb_div; */
u8 pll_vclk_cntl;
u8 vclk_post_div;
u8 vclk_fb_div;
- u8 pll_ext_cntl;
+/* u8 pll_ext_cntl; */
u32 dsp_config; /* Mach64 GTB DSP */
u32 dsp_on_off; /* Mach64 GTB DSP */
- u8 mclk_post_div_real;
+/* u8 mclk_post_div_real; */
u8 vclk_post_div_real;
};
@@ -75,23 +83,54 @@
u32 ref_clk_per;
u32 pll_per;
u32 mclk_per;
+ u32 xclk_per;
u8 bus_type;
u8 ram_type;
u8 mem_refresh_rate;
u8 blitter_may_be_busy;
+ unsigned char clock;
u32 accel_flags;
#ifdef __sparc__
struct pci_mmap_map *mmap_map;
u8 mmaped;
int open;
#endif
+#ifdef CONFIG_FB_ATY_CT
+ u8 pll_ref_div;
+ u8 xclk_post_div_real;
+ u16 mclk_fb_div;
+ u8 fifo_size;
+ u8 dsp_loop_latency;
+ u8 page_size;
+#endif
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+ unsigned long bios_base_phys;
+ unsigned long bios_base;
+ unsigned long lcd_table;
+ u16 lcd_width;
+ u16 lcd_height;
+ u32 lcd_pixclock;
+ u16 lcd_htotal;
+ u16 lcd_hdisp;
+ u16 lcd_hsync_start;
+ u16 lcd_hsync_delay;
+ u16 lcd_hsync_width;
+ u16 lcd_vtotal;
+ u16 lcd_vdisp;
+ u16 lcd_vsync_start;
+ u16 lcd_vsync_width;
+ u16 lcd_right;
+ u16 lcd_lower;
+ u16 lcd_hblank_width;
+ u16 lcd_vblank_width;
+#endif
#ifdef CONFIG_PMAC_PBOOK
struct fb_info *next;
unsigned char *save_framebuffer;
unsigned long save_pll[64];
#endif
};
-
+
/*
* ATI Mach64 features
*/
@@ -211,11 +250,12 @@
struct aty_pll_ops {
int (*var_to_pll) (const struct fb_info * info, u32 vclk_per,
- u8 bpp, union aty_pll * pll);
+ u32 bpp, u32 width, 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 (*init_pll)(struct fb_info * info);
};
extern const struct aty_pll_ops aty_pll_ati18818_1; /* ATI 18818 */
@@ -229,8 +269,8 @@
extern void aty_set_pll_ct(const struct fb_info *info,
const union aty_pll *pll);
-extern void aty_calc_pll_ct(const struct fb_info *info,
- struct pll_ct *pll);
+/* extern void aty_calc_pll_ct(const struct fb_info *info,
+ struct pll_ct *pll); */
/*
diff -u -r /usr/src/linux-2.5.orig/drivers/video/aty/atyfb_base.c /usr/src/linux-2.5.XX/drivers/video/aty/atyfb_base.c
--- /usr/src/linux-2.5.orig/drivers/video/aty/atyfb_base.c 2003-01-17 16:13:53.000000000 +0100
+++ /usr/src/linux-2.5.XX/drivers/video/aty/atyfb_base.c 2003-01-17 18:04:46.000000000 +0100
@@ -24,6 +24,8 @@
* Harry AC Eaton
* Anthony Tong <atong@uiuc.edu>
*
+ * Generic LCD support written by Daniel Mantione, ported from 2.4.20 by Alex Kern
+ *
* 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
* more details.
@@ -93,7 +95,7 @@
* Debug flags.
*/
#undef DEBUG
-
+#define DEBUG
/* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */
/* - must be large enough to catch all GUI-Regs */
/* - must be aligned to a PAGE boundary */
@@ -103,7 +105,6 @@
/* FIXME: remove the FAIL definition */
#define FAIL(x) do { printk(x "\n"); return -EINVAL; } while (0)
-
/*
* The Hardware parameters for each card
*/
@@ -140,7 +141,7 @@
static int atyfb_release(struct fb_info *info, int user);
static int atyfb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info);
-static int atyfb_set_par(struct fb_info *info);
+static int atyfb_set_par(struct fb_info *info);
static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info);
static int atyfb_pan_display(struct fb_var_screeninfo *var,
@@ -214,6 +215,7 @@
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;
@@ -257,134 +259,135 @@
static char m64n_xl[] __initdata = "3D RAGE (XL)";
static char m64n_ltp_a[] __initdata = "3D RAGE LT PRO (AGP)";
static char m64n_ltp_p[] __initdata = "3D RAGE LT PRO (PCI)";
-static char m64n_mob_p[] __initdata = "3D RAGE Mobility (PCI)";
-static char m64n_mob_a[] __initdata = "3D RAGE Mobility (AGP)";
+static char m64n_mob_p[] __initdata = "3D RAGE Mobility P/M (AGP 2x)";
+static char m64n_mob_a[] __initdata = "3D RAGE Mobility L (AGP 2x)";
#endif /* CONFIG_FB_ATY_CT */
static struct {
u16 pci_id, chip_type;
u8 rev_mask, rev_val;
const char *name;
- int pll, mclk;
+ int pll, mclk, xclk;
u32 features;
} aty_chips[] __initdata = {
#ifdef CONFIG_FB_ATY_GX
/* Mach64 GX */
{
- 0x4758, 0x00d7, 0x00, 0x00, m64n_gx, 135, 50, M64F_GX}, {
- 0x4358, 0x0057, 0x00, 0x00, m64n_cx, 135, 50, M64F_GX},
+ 0x4758, 0x00d7, 0x00, 0x00, m64n_gx, 135, 50, 50, M64F_GX}, {
+ 0x4358, 0x0057, 0x00, 0x00, m64n_cx, 135, 50, 50, M64F_GX},
#endif /* CONFIG_FB_ATY_GX */
#ifdef CONFIG_FB_ATY_CT
/* Mach64 CT */
{
- 0x4354, 0x4354, 0x00, 0x00, m64n_ct, 135, 60,
+ 0x4354, 0x4354, 0x00, 0x00, m64n_ct, 135, 60, 60,
M64F_CT | M64F_INTEGRATED | M64F_CT_BUS |
M64F_MAGIC_FIFO}, {
- 0x4554, 0x4554, 0x00, 0x00, m64n_et, 135, 60,
+ 0x4554, 0x4554, 0x00, 0x00, m64n_et, 135, 60, 60,
M64F_CT | M64F_INTEGRATED | M64F_CT_BUS |
M64F_MAGIC_FIFO},
/* Mach64 VT */
{
- 0x5654, 0x5654, 0xc7, 0x00, m64n_vta3, 170, 67,
+ 0x5654, 0x5654, 0xc7, 0x00, m64n_vta3, 170, 67, 67,
M64F_VT | M64F_INTEGRATED | M64F_VT_BUS |
M64F_MAGIC_FIFO | M64F_FIFO_24}, {
- 0x5654, 0x5654, 0xc7, 0x40, m64n_vta4, 200, 67,
+ 0x5654, 0x5654, 0xc7, 0x40, m64n_vta4, 200, 67, 67,
M64F_VT | M64F_INTEGRATED | M64F_VT_BUS |
M64F_MAGIC_FIFO | M64F_FIFO_24 | M64F_MAGIC_POSTDIV}, {
- 0x5654, 0x5654, 0x00, 0x00, m64n_vtb, 200, 67,
+ 0x5654, 0x5654, 0x00, 0x00, m64n_vtb, 200, 67, 67,
M64F_VT | M64F_INTEGRATED | M64F_VT_BUS |
M64F_GTB_DSP | M64F_FIFO_24}, {
- 0x5655, 0x5655, 0x00, 0x00, m64n_vtb, 200, 67,
+ 0x5655, 0x5655, 0x00, 0x00, m64n_vtb, 200, 67, 67,
M64F_VT | M64F_INTEGRATED | M64F_VT_BUS |
M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL}, {
- 0x5656, 0x5656, 0x00, 0x00, m64n_vt4, 230, 83,
+ 0x5656, 0x5656, 0x00, 0x00, m64n_vt4, 230, 83, 83,
M64F_VT | M64F_INTEGRATED | M64F_GTB_DSP},
/* Mach64 GT (3D RAGE) */
{
- 0x4754, 0x4754, 0x07, 0x00, m64n_gt, 135, 63,
+ 0x4754, 0x4754, 0x07, 0x00, m64n_gt, 135, 63, 63,
M64F_GT | M64F_INTEGRATED | M64F_MAGIC_FIFO |
M64F_FIFO_24 | M64F_EXTRA_BRIGHT}, {
- 0x4754, 0x4754, 0x07, 0x01, m64n_gt, 170, 67,
+ 0x4754, 0x4754, 0x07, 0x01, m64n_gt, 170, 67, 67,
M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP |
M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL |
M64F_EXTRA_BRIGHT}, {
- 0x4754, 0x4754, 0x07, 0x02, m64n_gt, 200, 67,
+ 0x4754, 0x4754, 0x07, 0x02, m64n_gt, 200, 67, 67,
M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP |
M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL |
M64F_EXTRA_BRIGHT}, {
- 0x4755, 0x4755, 0x00, 0x00, m64n_gtb, 200, 67,
+ 0x4755, 0x4755, 0x00, 0x00, m64n_gtb, 200, 67, 67,
M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP |
M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL |
M64F_EXTRA_BRIGHT}, {
- 0x4756, 0x4756, 0x00, 0x00, m64n_iic_p, 230, 83,
+ 0x4756, 0x4756, 0x00, 0x00, m64n_iic_p, 230, 83, 83,
M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP |
M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL |
M64F_EXTRA_BRIGHT}, {
- 0x4757, 0x4757, 0x00, 0x00, m64n_iic_a, 230, 83,
+ 0x4757, 0x4757, 0x00, 0x00, m64n_iic_a, 230, 83, 83,
M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP |
M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL |
M64F_EXTRA_BRIGHT}, {
- 0x475a, 0x475a, 0x00, 0x00, m64n_iic_a, 230, 83,
+ 0x475a, 0x475a, 0x00, 0x00, m64n_iic_a, 230, 83, 83,
M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP |
M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL |
M64F_EXTRA_BRIGHT},
/* Mach64 LT */
{
- 0x4c54, 0x4c54, 0x00, 0x00, m64n_lt, 135, 63,
+ 0x4c54, 0x4c54, 0x00, 0x00, m64n_lt, 135, 63, 63,
M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP}, {
- 0x4c47, 0x4c47, 0x00, 0x00, m64n_ltg, 230, 63,
+ 0x4c47, 0x4c47, 0x00, 0x00, m64n_ltg, 230, 63, 63,
M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP |
M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT |
M64F_LT_SLEEP | M64F_G3_PB_1024x768},
/* Mach64 GTC (3D RAGE PRO) */
{
- 0x4742, 0x4742, 0x00, 0x00, m64n_gtc_ba, 230, 100,
+ 0x4742, 0x4742, 0x00, 0x00, m64n_gtc_ba, 230, 100, 100,
M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL |
M64F_EXTRA_BRIGHT}, {
- 0x4744, 0x4744, 0x00, 0x00, m64n_gtc_ba1, 230, 100,
+ 0x4744, 0x4744, 0x00, 0x00, m64n_gtc_ba1, 230, 100, 100,
M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL |
M64F_EXTRA_BRIGHT}, {
- 0x4749, 0x4749, 0x00, 0x00, m64n_gtc_bp, 230, 100,
+ 0x4749, 0x4749, 0x00, 0x00, m64n_gtc_bp, 230, 100, 100,
M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL |
M64F_EXTRA_BRIGHT | M64F_MAGIC_VRAM_SIZE}, {
- 0x4750, 0x4750, 0x00, 0x00, m64n_gtc_pp, 230, 100,
+ 0x4750, 0x4750, 0x00, 0x00, m64n_gtc_pp, 230, 100, 100,
M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL |
M64F_EXTRA_BRIGHT}, {
- 0x4751, 0x4751, 0x00, 0x00, m64n_gtc_ppl, 230, 100,
+ 0x4751, 0x4751, 0x00, 0x00, m64n_gtc_ppl, 230, 100, 100,
M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL |
M64F_EXTRA_BRIGHT},
/* 3D RAGE XL */
{
- 0x4752, 0x4752, 0x00, 0x00, m64n_xl, 230, 100,
+ 0x4752, 0x4752, 0x00, 0x00, m64n_xl, 235, 83, 63,
M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL |
M64F_EXTRA_BRIGHT | M64F_XL_DLL},
/* Mach64 LT PRO */
{
- 0x4c42, 0x4c42, 0x00, 0x00, m64n_ltp_a, 230, 100,
+ 0x4c42, 0x4c42, 0x00, 0x00, m64n_ltp_a, 236, 75, 100,
M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
- M64F_GTB_DSP}, {
- 0x4c44, 0x4c44, 0x00, 0x00, m64n_ltp_p, 230, 100,
+ M64F_GTB_DSP | M64F_EXTRA_BRIGHT}, {
+ 0x4c44, 0x4c44, 0x00, 0x00, m64n_ltp_p, 230, 100, 100,
M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
- M64F_GTB_DSP}, {
- 0x4c49, 0x4c49, 0x00, 0x00, m64n_ltp_p, 230, 100,
+ M64F_GTB_DSP | M64F_EXTRA_BRIGHT}, {
+ 0x4c49, 0x4c49, 0x00, 0x00, m64n_ltp_p, 230, 100, 100,
M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
M64F_GTB_DSP | M64F_EXTRA_BRIGHT |
M64F_G3_PB_1_1 | M64F_G3_PB_1024x768}, {
- 0x4c50, 0x4c50, 0x00, 0x00, m64n_ltp_p, 230, 100,
+ 0x4c50, 0x4c50, 0x00, 0x00, m64n_ltp_p, 230, 100, 100,
M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
- M64F_GTB_DSP},
+ M64F_GTB_DSP | M64F_EXTRA_BRIGHT},
/* 3D RAGE Mobility */
{
- 0x4c4d, 0x4c4d, 0x00, 0x00, m64n_mob_p, 230, 50,
+ 0x4c4d, 0x4c4d, 0x00, 0x00, m64n_mob_p, 230, 83, 125,
M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
- M64F_GTB_DSP | M64F_MOBIL_BUS}, {
- 0x4c4e, 0x4c4e, 0x00, 0x00, m64n_mob_a, 230, 50,
+ M64F_GTB_DSP | M64F_MOBIL_BUS | M64F_XL_DLL |
+ M64F_EXTRA_BRIGHT}, {
+ 0x4c4e, 0x4c4e, 0x00, 0x00, m64n_mob_a, 230, 83, 125,
M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
M64F_GTB_DSP | M64F_MOBIL_BUS},
#endif /* CONFIG_FB_ATY_CT */
@@ -461,7 +464,7 @@
#endif /* defined(CONFIG_PPC) */
-#if defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_PMAC_BACKLIGHT)
+#if defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD)
static void aty_st_lcd(int index, u32 val, const struct atyfb_par *par)
{
unsigned long temp;
@@ -483,7 +486,15 @@
/* read the register value */
return aty_ld_le32(LCD_DATA, par);
}
-#endif /* CONFIG_PMAC_PBOOK || CONFIG_PMAC_BACKLIGHT */
+#endif /* CONFIG_PMAC_PBOOK || CONFIG_PMAC_BACKLIGHT || CONFIG_FB_ATY_GENERIC_LCD */
+
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+static void atyfb_monitors_enabled(struct atyfb_par *par, struct crtc *crtc) {
+ if (par->lcd_table != 0) {
+ crtc->monitors_enabled = aty_ld_lcd(LCD_GEN_CTRL, par) & 3;
+ }
+}
+#endif
/* ------------------------------------------------------------------------- */
@@ -494,6 +505,8 @@
static void aty_set_crtc(const struct atyfb_par *par,
const struct crtc *crtc)
{
+ u32 v;
+
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);
@@ -501,6 +514,63 @@
aty_st_le32(CRTC_VLINE_CRNT_VLINE, 0, par);
aty_st_le32(CRTC_OFF_PITCH, crtc->off_pitch, 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);
+#endif
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+ /* After setting the CRTC registers we should set the LCD
+ * registers.
+ */
+ if (par->lcd_table != 0) {
+ /* Enable/disable horizontal stretching */
+ v = aty_ld_lcd(HORZ_STRETCHING, par);
+ v = v & ~(HORZ_STRETCH_RATIO | HORZ_STRETCH_EN | AUTO_HORZ_RATIO);
+ v = v | HORZ_STRETCH_MODE; /* Use interpolation instead of duplication. */
+ if (crtc->h_stretching != 0)
+ v = v | HORZ_STRETCH_EN | crtc->h_stretching;
+ aty_st_lcd(HORZ_STRETCHING, v, par);
+#ifdef DEBUG
+ printk(KERN_INFO "HORZ_STRETCHING: %x\n", v);
+#endif
+
+ /* Enable/disable vertital stretching */
+ v = aty_ld_lcd(VERT_STRETCHING, par);
+ v = v & ~(VERT_STRETCH_RATIO0 | VERT_STRETCH_EN);
+ v = v | VERT_STRETCH_USE0; /* Use VERT_STRETCH_RATIO0. */
+ if (crtc->v_stretching != 0)
+ v = v | VERT_STRETCH_EN | crtc->v_stretching;
+ aty_st_lcd(VERT_STRETCHING, v, par);
+#ifdef DEBUG
+ printk(KERN_INFO "VERT_STRETCHING: %x\n", v);
+#endif
+ v = aty_ld_lcd(EXT_VERT_STRETCH, par);
+ v = v & ~AUTO_VERT_RATIO; /* Forbit the chip to guess the vertical
+ expansion (used for vga compatibility) */
+ v = v | VERT_STRETCH_MODE; /* Use interpolation instead of duplication. */
+ aty_st_lcd(EXT_VERT_STRETCH, v, par);
+#ifdef DEBUG
+ printk(KERN_INFO "EXT_VERT_STRETCH: %x\n", v);
+#endif
+
+ /* Don't use shadowing. Don't divide the horizontal paramters.
+ (VGA compatibility junk that might be enabled.)
+ Enable only the monitors that were enabled before we switched the
+ video mode.
+ */
+ v = aty_ld_lcd(LCD_GEN_CTRL, par);
+ v = v & ~(HORZ_DIVBY2_EN | SCLK_SEL | USE_SHADOWED_VEND | SHADOW_EN | LCD_ON | CRT_ON);
+ v = v | DONT_SHADOW_VPAR | crtc->monitors_enabled;
+ aty_st_lcd(LCD_GEN_CTRL, v, par);
+#ifdef DEBUG
+ printk(KERN_INFO "LCD_GEN_CTRL: %x\n", v);
+#endif
+ }
+#endif /* CONFIG_FB_ATY_GENERIC_LCD */
}
static int aty_var_to_crtc(const struct fb_info *info,
@@ -508,16 +578,18 @@
struct crtc *crtc)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
- u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
+ u32 xres, yres, ryres, vxres, vyres, xoffset, yoffset, bpp;
u32 left, right, upper, lower, hslen, vslen, sync, vmode;
- u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid,
- h_sync_pol;
+ u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
u32 pix_width, dp_pix_width, dp_chain_mask;
-
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+ u32 lcd_hsync_start, lcd_htotal, lcd_vsync_start, lcd_vtotal;
+#endif
/* input */
xres = var->xres;
yres = var->yres;
+ ryres = yres;
vxres = var->xres_virtual;
vyres = var->yres_virtual;
xoffset = var->xoffset;
@@ -568,6 +640,18 @@
if (v_total > 0x7ff)
FAIL("v_total too large");
v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
+ /* In double scan mode, the vertical parameters need to be doubled.
+ But in interlaced mode, there is no need to half the vertical parameters.
+ Code has been tested in 1024x768, 43 Hz interlaced and 640x480, 60 Hz
+ double scan.
+ */
+ if ((vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+ ryres <<= 1;
+ v_total <<= 1;
+ v_disp <<= 1;
+ v_sync_strt <<= 1;
+ v_sync_wid <<= 1;
+ }
c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;
@@ -603,28 +687,106 @@
if (vxres * vyres * bpp / 8 > info->fix.smem_len)
FAIL("not enough video RAM");
- if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
- FAIL("invalid vmode");
+/* if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+ FAIL("invalid vmode"); */
/* output */
crtc->vxres = vxres;
crtc->vyres = vyres;
- crtc->h_tot_disp = h_total | (h_disp << 16);
- crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly << 8) |
- ((h_sync_strt & 0x100) << 4) | (h_sync_wid << 16) |
- (h_sync_pol << 21);
- crtc->v_tot_disp = v_total | (v_disp << 16);
- crtc->v_sync_strt_wid =
- v_sync_strt | (v_sync_wid << 16) | (v_sync_pol << 21);
- crtc->off_pitch =
- ((yoffset * vxres + xoffset) * bpp / 64) | (vxres << 19);
- crtc->gen_cntl =
- pix_width | c_sync | CRTC_EXT_DISP_EN | CRTC_ENABLE;
+ crtc->xoffset = xoffset;
+ crtc->yoffset = yoffset;
+ crtc->bpp = bpp;
+ crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19);
+ crtc->gen_cntl = pix_width | c_sync | CRTC_EXT_DISP_EN | CRTC_ENABLE;
+ /* Enable doublescan mode if requested */
+ if ((vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
+ crtc->gen_cntl|=CRTC_DBL_SCAN_EN;
+ /* Enable interlaced mode if requested */
+ if ((vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
+ crtc->gen_cntl|=CRTC_INTERLACE_EN;
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+ /* We can only program the real mode parameters to the CRTC
+ if the LCD monitor is switched off. Otherwise we will have to
+ use the parameters the LCD monitor prefers, effectively setting
+ a completely different mode which simulates the requested
+ video mode.
+ */
+ atyfb_monitors_enabled(par, crtc);
+ if ((par->lcd_table != 0) && ((crtc->monitors_enabled & LCD_ON) != 0) &&
+ ((xres > par->lcd_width) || (ryres > 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 (crtc->monitors_enabled & CRT_ON) {
+ printk(KERN_INFO "Disabling lcd monitor because video mode does not fit.\n");
+ crtc->monitors_enabled &= (~LCD_ON);
+ } else {
+ FAIL("Video mode exceeds size of lcd monitor.\nConnect this computer to a conventional monitor if you really need this mode.");
+ }
+ }
+
+ if ((par->lcd_table == 0) || ((crtc->monitors_enabled & LCD_ON) == 0)) {
+#endif /* CONFIG_FB_ATY_GENERIC_LCD */
+ crtc->h_tot_disp = h_total | (h_disp<<16);
+ crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly<<8) |
+ ((h_sync_strt & 0x100)<<4) | (h_sync_wid<<16) | (h_sync_pol<<21);
+ crtc->v_tot_disp = v_total | (v_disp<<16);
+ crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid<<16) | (v_sync_pol<<21);
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+ /* No hardware stretching please! */
+ crtc->h_stretching = 0;
+ crtc->v_stretching = 0;
+ } else {
+ /* This is horror! When we simulate, say 640x480 on an 800x600
+ lcd monitor, the CRTC should be programmed 800x600 values for
+ the non visible part, but 640x480 for the visible part.
+ This code has been tested on a laptop with it's 800x600 lcd
+ monitor and a conventional monitor both switched on.
+ Tested modes: 640x400, 720x400, 800x600, 320x200-doublescan,
+ 800x600-interlaced
+ */
+ lcd_htotal = h_disp + par->lcd_hblank_width;
+ lcd_hsync_start = h_disp + par->lcd_right;
+ lcd_vtotal = v_disp + par->lcd_vblank_width;
+ lcd_vsync_start = v_disp + par->lcd_lower;
+
+ crtc->h_tot_disp = (lcd_htotal) | (h_disp<<16);
+ crtc->h_sync_strt_wid = (lcd_hsync_start & 0xff) |
+ (par->lcd_hsync_delay<<8) | ((lcd_hsync_start & 0x100)<<4) |
+ (par->lcd_hsync_width<<16);
+ crtc->v_tot_disp = lcd_vtotal | (v_disp<<16);
+ crtc->v_sync_strt_wid = lcd_vsync_start | (par->lcd_vsync_width<<16);
+ /* To simulate the requested video mode, we use the hardware stretcher,
+ which zooms the image to the dimensions of the LCD screen. It has
+ two modes; replication and blending. Replication duplicates some
+ pixels, blending interpolates between pixels. We use blending.
+ The formula for blending is:
+ h_stretching=(source_with/dest_width)*4096
+ v_stretching=(source_lines/dest_lines)*1024
+ */
+ if (xres != par->lcd_width)
+ crtc->h_stretching = (xres*4096)/par->lcd_width;
+ else
+ crtc->h_stretching = 0;
+
+ if (ryres != par->lcd_height)
+ crtc->v_stretching = (ryres*1024)/par->lcd_height;
+ else
+ crtc->v_stretching = 0;
+ /* 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
+ compensate for it in the hardware stretching (we stretch half as much)
+ */
+ crtc->gen_cntl&=~CRTC_INTERLACE_EN;
+ }
+
+#endif /* CONFIG_FB_ATY_GENERIC_LCD */
if (M64_HAS(MAGIC_FIFO)) {
/* Not VTB/GTB */
/* FIXME: magic FIFO values */
- crtc->gen_cntl |=
- aty_ld_le32(CRTC_GEN_CNTL, par) & 0x000e0000;
+ crtc->gen_cntl |= aty_ld_le32(CRTC_GEN_CNTL, par) & 0x000e0000;
}
crtc->dp_pix_width = dp_pix_width;
crtc->dp_chain_mask = dp_chain_mask;
@@ -641,12 +803,12 @@
h_sync_pol;
u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
u32 pix_width;
+ u32 double_scan, interlace;
/* input */
h_total = crtc->h_tot_disp & 0x1ff;
h_disp = (crtc->h_tot_disp >> 16) & 0xff;
- h_sync_strt = (crtc->h_sync_strt_wid & 0xff) |
- ((crtc->h_sync_strt_wid >> 4) & 0x100);
+ h_sync_strt = (crtc->h_sync_strt_wid & 0xff) | ((crtc->h_sync_strt_wid >> 4) & 0x100);
h_sync_dly = (crtc->h_sync_strt_wid >> 8) & 0x7;
h_sync_wid = (crtc->h_sync_strt_wid >> 16) & 0x1f;
h_sync_pol = (crtc->h_sync_strt_wid >> 21) & 0x1;
@@ -657,6 +819,8 @@
v_sync_pol = (crtc->v_sync_strt_wid >> 21) & 0x1;
c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
+ double_scan = crtc->gen_cntl & CRTC_DBL_SCAN_EN;
+ interlace = crtc->gen_cntl & CRTC_INTERLACE_EN;
/* convert */
xres = (h_disp + 1) * 8;
@@ -760,6 +924,23 @@
var->vsync_len = vslen;
var->sync = sync;
var->vmode = FB_VMODE_NONINTERLACED;
+ /* In double scan mode, the vertical parameters are doubled, so we need to
+ half them to get the right values.
+ In interlaced mode the values are already correct, so no correction is
+ necessary.
+ Code has been tested in 1024x768, 43 Hz interlaced and 640x480, 60 Hz
+ doublesscan.
+ */
+ if (interlace)
+ var->vmode = FB_VMODE_INTERLACED;
+
+ if (double_scan) {
+ var->vmode = FB_VMODE_DOUBLE;
+ var->yres>>=1;
+ var->upper_margin>>=1;
+ var->lower_margin>>=1;
+ var->vsync_len>>=1;
+ }
return 0;
}
@@ -771,12 +952,21 @@
struct atyfb_par *par = (struct atyfb_par *) info->par;
struct fb_var_screeninfo *var = &info->var;
u8 tmp;
- u32 i;
+ u32 i, xres, pixclock;
int err;
- if ((err = aty_var_to_crtc(info, var, &par->crtc)) ||
- (err = par->pll_ops->var_to_pll(info, var->pixclock,
- var->bits_per_pixel, &par->pll)))
+ if ((err = aty_var_to_crtc(info, var, &par->crtc)))
+ return err;
+
+ pixclock = var->pixclock;
+ xres = 0;
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+ if ((par->lcd_table != 0) && ((par->crtc.monitors_enabled & LCD_ON) != 0)) {
+ pixclock = par->lcd_pixclock;
+ xres = var->xres;
+ }
+#endif
+ if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, xres, &par->pll)))
return err;
par->accel_flags = var->accel_flags; /* hack */
@@ -785,9 +975,16 @@
wait_for_idle(par);
tmp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
aty_set_crtc(par, &par->crtc);
- aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 0, par);
- /* better call aty_StrobeClock ?? */
- aty_st_8(CLOCK_CNTL + par->clk_wr_offset, CLOCK_STROBE, par);
+
+ aty_st_8(CLOCK_CNTL, 0, par);
+#if 1
+ aty_st_8(CLOCK_CNTL, CLOCK_STROBE | CLOCK_DIV, par);
+#else
+ if (M64_HAS(MOBIL_BUS)&&M64_HAS(XL_DLL))
+ aty_st_8(CLOCK_CNTL + par->clk_wr_offset, CLOCK_STROBE | CLOCK_DIV | (par->clock & CLOCK_SEL), par);
+ else
+ aty_st_8(CLOCK_CNTL + par->clk_wr_offset, CLOCK_STROBE, par);
+#endif
par->dac_ops->set_dac(info, &par->pll, var->bits_per_pixel,
par->accel_flags);
@@ -867,17 +1064,40 @@
struct fb_info *info)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
+ int err;
struct crtc crtc;
union aty_pll pll;
- int err;
+ u32 pixclock, xres;
- if ((err = aty_var_to_crtc(info, var, &crtc)) ||
- (err = par->pll_ops->var_to_pll(info, var->pixclock,
- var->bits_per_pixel, &pll)))
+ err = aty_var_to_crtc(info, var, &crtc);
+ if (err == 0) {
+ /* Alert! aty_var_to_crtc can modify monitors_enabled which is
+ important for the pixclock decision */
+ pixclock = var->pixclock;
+ xres = 0; /* non LCD */
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+ if ((par->lcd_table != 0) && ((crtc.monitors_enabled & LCD_ON) != 0)) {
+ pixclock = par->lcd_pixclock;
+ xres = var->xres;
+ }
+#endif
+ if (pixclock == 0) {
+ FAIL("Invalid pixclock");
+ } else {
+ err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, xres, &pll);
+ }
+ }
+
+ if (err != 0)
return err;
-#if 0 /* fbmon is not done. uncomment for 2.5.x -brad */
- if (!fbmon_valid_timings(var->pixclock, htotal, vtotal, info))
+ if (var->accel_flags & FB_ACCELF_TEXT)
+ info->var.accel_flags = FB_ACCELF_TEXT;
+ else
+ info->var.accel_flags = 0;
+
+#if 0 /* fbmon is not done. uncomment for 2.5.x -brad */
+ if (!fbmon_valid_timings(pixclock, htotal, vtotal, info))
return -EINVAL;
#endif
aty_crtc_to_var(&crtc, var);
@@ -885,20 +1105,37 @@
return 0;
}
-static void set_off_pitch(struct atyfb_par *par,
- const struct fb_info *info)
+ /* In the display mode set code we need to make desisions depending on
+ * wether the LCD or CRT monitor is enabled.
+ * This is going to give problems in the unlikely case that someone
+ * for example turns on the LCD monitor just after we tested what
+ * monitors are enabled. Since the consequences are very serious
+ * (the graphic card crashes and sends the wrong signals to the lcd
+ * monitor which gets brighter and brighter; to prevent it from
+ * damage the computer must be switched off as soon as possible)
+ * we need to prevent this.
+ *
+ * As far as I know there is no way to prevent people switching on the
+ * LCD monitor while we are programming the video card. So the best way
+ * to do it, is detect what monitors are enabled before programming the
+ * video chip. After programming the video chip, we write this information
+ * back to the video chip, switching the LCD off again if someone enabled
+ * it. But isn't the card already crashed before we have the chance to
+ * turn the display back off? I don't think so because the CRTC is disabled
+ * while we program it.
+ */
+
+static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info)
{
u32 xoffset = info->var.xoffset;
u32 yoffset = info->var.yoffset;
u32 vxres = par->crtc.vxres;
u32 bpp = info->var.bits_per_pixel;
- par->crtc.off_pitch =
- ((yoffset * vxres + xoffset) * bpp / 64) | (vxres << 19);
+ par->crtc.off_pitch = ((yoffset * vxres + xoffset) * bpp / 64) | (vxres << 19);
aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
}
-
/*
* Open/Release the frame buffer device
*/
@@ -965,7 +1202,7 @@
}
}
}
- }
+ }
#endif
return (0);
}
@@ -1045,13 +1282,13 @@
case ATYIO_CLKR:
if (M64_HAS(INTEGRATED)) {
struct atyclk clk;
- union aty_pll *pll = par->pll;
+ union aty_pll *pll = &(par->pll);
u32 dsp_config = pll->ct.dsp_config;
u32 dsp_on_off = pll->ct.dsp_on_off;
clk.ref_clk_per = par->ref_clk_per;
- clk.pll_ref_div = pll->ct.pll_ref_div;
- clk.mclk_fb_div = pll->ct.mclk_fb_div;
- clk.mclk_post_div = pll->ct.mclk_post_div_real;
+ clk.pll_ref_div = par->pll_ref_div;
+ clk.mclk_fb_div = par->mclk_fb_div;
+ /* clk.mclk_post_div = pll->ct.mclk_post_div_real; */
clk.vclk_fb_div = pll->ct.vclk_fb_div;
clk.vclk_post_div = pll->ct.vclk_post_div_real;
clk.dsp_xclks_per_row = dsp_config & 0x3fff;
@@ -1068,14 +1305,14 @@
case ATYIO_CLKW:
if (M64_HAS(INTEGRATED)) {
struct atyclk clk;
- union aty_pll *pll = par->pll;
+ union aty_pll *pll = &(par->pll);
if (copy_from_user
(&clk, (struct atyclk *) arg, sizeof(clk)))
return -EFAULT;
par->ref_clk_per = clk.ref_clk_per;
- pll->ct.pll_ref_div = clk.pll_ref_div;
- pll->ct.mclk_fb_div = clk.mclk_fb_div;
- pll->ct.mclk_post_div_real = clk.mclk_post_div;
+ par->pll_ref_div = clk.pll_ref_div;
+ par->mclk_fb_div = clk.mclk_fb_div;
+ /* pll->ct.mclk_post_div_real = clk.mclk_post_div; */
pll->ct.vclk_fb_div = clk.vclk_fb_div;
pll->ct.vclk_post_div_real = clk.vclk_post_div;
pll->ct.dsp_config =
@@ -1088,7 +1325,7 @@
(clk.
dsp_on & 0x7ff) | ((clk.
dsp_off & 0x7ff) << 16);
- aty_calc_pll_ct(info, &pll->ct);
+ /* aty_calc_pll_ct(info, &pll->ct); */
aty_set_pll_ct(info, pll);
} else
return -EINVAL;
@@ -1506,7 +1743,7 @@
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
const char *chipname = NULL, *ramname = NULL, *xtal;
- int j, pll, mclk, gtb_memsize;
+ int j, pll, mclk, xclk, gtb_memsize;
struct fb_var_screeninfo var;
u32 chip_id, i;
u16 type;
@@ -1528,6 +1765,7 @@
chipname = aty_chips[j].name;
pll = aty_chips[j].pll;
mclk = aty_chips[j].mclk;
+ xclk = aty_chips[j].xclk;
par->features = aty_chips[j].features;
goto found;
}
@@ -1573,8 +1811,7 @@
par->dac_ops = &aty_dac_att21c498;
break;
default:
- printk
- (" atyfb_set_par: DAC type not implemented yet!\n");
+ printk(" atyfb_set_par: DAC type not implemented yet!\n");
par->dac_ops = &aty_dac_unsupported;
break;
}
@@ -1595,8 +1832,7 @@
par->pll_ops = &aty_pll_ibm514;
break;
default:
- printk
- (" atyfb_set_par: CLK type not implemented yet!");
+ printk(" atyfb_set_par: CLK type not implemented yet!");
par->pll_ops = &aty_pll_unsupported;
break;
}
@@ -1610,8 +1846,8 @@
par->dac_ops = &aty_dac_ct;
par->pll_ops = &aty_pll_ct;
/* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
- if (mclk == 67 && par->ram_type < SDRAM)
- mclk = 63;
+ if (xclk == 67 && par->ram_type < SDRAM)
+ xclk = 63;
}
#endif /* CONFIG_FB_ATY_CT */
@@ -1728,47 +1964,70 @@
pll = default_pll;
if (default_mclk)
mclk = default_mclk;
+ if (default_xclk)
+ xclk = default_xclk;
- printk("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK\n",
- info->fix.smem_len ==
- 0x80000 ? 512 : (info->fix.smem_len >> 20),
- info->fix.smem_len == 0x80000 ? 'K' : 'M', ramname,
- xtal, pll, mclk);
+ printk("%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, pll, mclk, xclk);
- if (mclk < 44)
+ if (xclk < 44)
par->mem_refresh_rate = 0; /* 000 = 10 Mhz - 43 Mhz */
- else if (mclk < 50)
+ else if (xclk < 50)
par->mem_refresh_rate = 1; /* 001 = 44 Mhz - 49 Mhz */
- else if (mclk < 55)
+ else if (xclk < 55)
par->mem_refresh_rate = 2; /* 010 = 50 Mhz - 54 Mhz */
- else if (mclk < 66)
+ else if (xclk < 66)
par->mem_refresh_rate = 3; /* 011 = 55 Mhz - 65 Mhz */
- else if (mclk < 75)
+ else if (xclk < 75)
par->mem_refresh_rate = 4; /* 100 = 66 Mhz - 74 Mhz */
- else if (mclk < 80)
+ else if (xclk < 80)
par->mem_refresh_rate = 5; /* 101 = 75 Mhz - 79 Mhz */
- else if (mclk < 100)
+ else if (xclk < 100)
par->mem_refresh_rate = 6; /* 110 = 80 Mhz - 100 Mhz */
else
par->mem_refresh_rate = 7; /* 111 = 100 Mhz and above */
par->pll_per = 1000000 / pll;
- par->mclk_per = 1000000 / mclk;
+ if ((mclk < 0) || (xclk < 0)) {
+ par->mclk_per = 0;
+ par->xclk_per = 0;
+ } else {
+ par->mclk_per = 1000000/mclk;
+ par->xclk_per = 1000000/xclk;
+ }
#ifdef DEBUG
if (M64_HAS(INTEGRATED)) {
int i;
- printk
- ("BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
- "DSP_CONFIG DSP_ON_OFF\n"
- "%08x %08x %08x %08x %08x %08x %08x\n"
- "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), aty_ld_le32(DSP_ON_OFF,
- par));
- for (i = 0; i < 16; i++)
+ printk("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",
+ 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),
+ aty_ld_le32(DSP_ON_OFF, par), aty_ld_le32(CLOCK_CNTL, par));
+ for (i = 0; i < 40; i++)
+ printk(" %02x", aty_ld_pll(i, par));
+ printk("\n");
+ }
+#endif
+ printk("vor init_pll\n");
+ par->pll_ops->init_pll(info);
+ printk("after init_pll\n");
+
+#ifdef DEBUG
+ if (M64_HAS(INTEGRATED)) {
+ int i;
+ printk("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",
+ 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),
+ aty_ld_le32(DSP_ON_OFF, par), aty_ld_le32(CLOCK_CNTL, par));
+ for (i = 0; i < 40; i++)
printk(" %02x", aty_ld_pll(i, par));
printk("\n");
}
@@ -1780,7 +2039,7 @@
* the full 8 MB of video RAM on 8 MB boards
*/
if (info->fix.smem_len == 0x800000 ||
- (par->bus_type == ISA
+ (par->bus_type == ISA
&& info->fix.smem_len == 0x400000))
info->fix.smem_len -= GUI_RESERVE;
@@ -1855,14 +2114,12 @@
#else /* !CONFIG_PPC */
#ifdef __sparc__
if (mode_option) {
- if (!fb_find_mode
- (&var, info, mode_option, NULL, 0, NULL, 8))
+ if (!fb_find_mode(&var, info, mode_option, NULL, 0, NULL, 8))
var = default_var;
} else
var = default_var;
#else
- if (!fb_find_mode
- (&var, info, mode_option, NULL, 0, NULL, 8))
+ if (!fb_find_mode(&var, info, mode_option, NULL, 0, NULL, 8))
var = default_var;
#endif /* !__sparc__ */
#endif /* !CONFIG_PPC */
@@ -1900,9 +2157,45 @@
return 0;
fb_list = info;
-
+#ifdef DEBUG
+{
+ /* dump non shadow CRTC, pll, LCD registers */
+ int i; u32 base;
+ /* CRTC registers */
+ base = 0x2000;
+ printk("Mach64 non-shadow register values:");
+ for (i = 0; i < 256; i = i+4) {
+ if(i%16 == 0) printk("\n0x%04X: ", base + i);
+ printk(" %08X", aty_ld_le32(i, par));
+ }
+ printk("\n\n");
+
+ /* PLL registers */
+ base = 0x00;
+ printk("Mach64 PLL register values:");
+ for (i = 0; i < 64; i++) {
+ if(i%16 == 0) printk("\n0x%02X: ", base + i);
+ if(i%4 == 0) printk(" ");
+ printk("%02X", aty_ld_pll(i, par));
+ }
+ printk("\n\n");
+
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+ 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(" %08X", aty_ld_lcd(i, par));
+ }
+ printk("\n\n");
+ }
+#endif /* CONFIG_FB_ATY_GENERIC_LCD */
+}
+#endif
printk("fb%d: %s frame buffer device on %s\n",
- minor(info->node), info->fix.id, name);
+ minor(info->node), info->fix.id, name);
return 1;
}
@@ -1928,9 +2221,11 @@
#else
u16 tmp;
#endif
-
- while ((pdev =
- pci_find_device(PCI_VENDOR_ID_ATI, PCI_ANY_ID, pdev))) {
+#if defined(CONFIG_FB_ATY_GENERIC_LCD)
+ u16 lcd_ofs;
+ u32 driv_inf_tab, sig, rom_addr;
+#endif
+ while ((pdev = pci_find_device(PCI_VENDOR_ID_ATI, PCI_ANY_ID, pdev))) {
if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
struct resource *rp;
@@ -1942,11 +2237,9 @@
if (i < 0)
continue;
- info =
- kmalloc(sizeof(struct fb_info), GFP_ATOMIC);
+ info = kmalloc(sizeof(struct fb_info), GFP_ATOMIC);
if (!info) {
- printk
- ("atyfb_init: can't alloc fb_info\n");
+ printk("atyfb_init: can't alloc fb_info\n");
return -ENXIO;
}
memset(info, 0, sizeof(struct fb_info));
@@ -1954,8 +2247,7 @@
default_par =
kmalloc(sizeof(struct atyfb_par), GFP_ATOMIC);
if (!default_par) {
- printk
- ("atyfb_init: can't alloc atyfb_par\n");
+ printk("atyfb_init: can't alloc atyfb_par\n");
kfree(info);
return -ENXIO;
}
@@ -1987,7 +2279,7 @@
/*
* Map in big-endian aperture.
*/
- info->screen_base = (char *) (addr + 0x800000UL);
+ info->screen_base = (char *)(addr + 0x800000UL);
info->fix.smem_start = addr + 0x800000UL;
/*
@@ -2002,8 +2294,7 @@
kmalloc(j * sizeof(*default_par->mmap_map),
GFP_ATOMIC);
if (!default_par->mmap_map) {
- printk
- ("atyfb_init: can't alloc mmap_map\n");
+ printk("atyfb_init: can't alloc mmap_map\n");
kfree(info);
release_mem_region(res_start, res_size);
return -ENXIO;
@@ -2014,15 +2305,12 @@
for (i = 0, j = 2;
i < 6 && pdev->resource[i].start; i++) {
struct resource *rp = &pdev->resource[i];
- int io, breg =
- PCI_BASE_ADDRESS_0 + (i << 2);
+ int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
unsigned long base;
u32 size, pbase;
base = rp->start;
-
io = (rp->flags & IORESOURCE_IO);
-
size = rp->end - base + 1;
pci_read_config_dword(pdev, breg, &pbase);
@@ -2037,18 +2325,11 @@
* to stay compatible with older ones...
*/
if (base == addr) {
- default_par->mmap_map[j].voff =
- (pbase +
- 0x10000000) & PAGE_MASK;
- default_par->mmap_map[j].poff =
- base & PAGE_MASK;
- default_par->mmap_map[j].size =
- (size +
- ~PAGE_MASK) & PAGE_MASK;
- default_par->mmap_map[j].prot_mask =
- _PAGE_CACHE;
- default_par->mmap_map[j].prot_flag =
- _PAGE_E;
+ default_par->mmap_map[j].voff = (pbase + 0x10000000) & PAGE_MASK;
+ default_par->mmap_map[j].poff = base & PAGE_MASK;
+ default_par->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
+ default_par->mmap_map[j].prot_mask = _PAGE_CACHE;
+ default_par->mmap_map[j].prot_flag = _PAGE_E;
j++;
}
@@ -2057,23 +2338,18 @@
* set for the big endian half of the framebuffer...
*/
if (base == addr) {
- default_par->mmap_map[j].voff =
- (pbase + 0x800000) & PAGE_MASK;
- default_par->mmap_map[j].poff =
- (base + 0x800000) & PAGE_MASK;
+ default_par->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK;
+ default_par->mmap_map[j].poff = (base + 0x800000) & PAGE_MASK;
default_par->mmap_map[j].size = 0x800000;
- default_par->mmap_map[j].prot_mask =
- _PAGE_CACHE;
- default_par->mmap_map[j].prot_flag =
- _PAGE_E | _PAGE_IE;
+ default_par->mmap_map[j].prot_mask = _PAGE_CACHE;
+ default_par->mmap_map[j].prot_flag = _PAGE_E | _PAGE_IE;
size -= 0x800000;
j++;
}
default_par->mmap_map[j].voff = pbase & PAGE_MASK;
default_par->mmap_map[j].poff = base & PAGE_MASK;
- default_par->mmap_map[j].size =
- (size + ~PAGE_MASK) & PAGE_MASK;
+ default_par->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
default_par->mmap_map[j].prot_mask = _PAGE_CACHE;
default_par->mmap_map[j].prot_flag = _PAGE_E;
j++;
@@ -2085,8 +2361,7 @@
*/
mem = aty_ld_le32(MEM_CNTL, default_par);
chip_id = aty_ld_le32(CONFIG_CHIP_ID, default_par);
- if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID)
- && !((chip_id >> 24) & 1)) {
+ if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) && !((chip_id >> 24) & 1)) {
switch (mem & 0x0f) {
case 3:
mem = (mem & ~(0x0f)) | 2;
@@ -2117,9 +2392,7 @@
node = prom_getchild(prom_root_node);
node = prom_searchsiblings(node, "aliases");
if (node) {
- len =
- prom_getproperty(node, "screen", prop,
- sizeof(prop));
+ len = prom_getproperty(node, "screen", prop, sizeof(prop));
if (len > 0) {
prop[len] = '\0';
node = prom_finddevice(prop);
@@ -2131,41 +2404,26 @@
pcp = pdev->sysdata;
if (node == pcp->prom_node) {
- struct fb_var_screeninfo *var =
- &default_var;
+ struct fb_var_screeninfo *var = &default_var;
unsigned int N, P, Q, M, T, R;
u32 v_total, h_total;
struct crtc crtc;
u8 pll_regs[16];
u8 clock_cntl;
- crtc.vxres =
- prom_getintdefault(node, "width",
- 1024);
- crtc.vyres =
- prom_getintdefault(node, "height",
- 768);
- var->bits_per_pixel =
- prom_getintdefault(node, "depth", 8);
+ crtc.vxres = prom_getintdefault(node, "width", 1024);
+ crtc.vyres = prom_getintdefault(node, "height", 768);
+ var->bits_per_pixel = prom_getintdefault(node, "depth", 8);
var->xoffset = var->yoffset = 0;
- crtc.h_tot_disp =
- aty_ld_le32(CRTC_H_TOTAL_DISP, default_par);
- crtc.h_sync_strt_wid =
- aty_ld_le32(CRTC_H_SYNC_STRT_WID,
- default_par);
- crtc.v_tot_disp =
- aty_ld_le32(CRTC_V_TOTAL_DISP, default_par);
- crtc.v_sync_strt_wid =
- aty_ld_le32(CRTC_V_SYNC_STRT_WID,
- default_par);
- crtc.gen_cntl =
- aty_ld_le32(CRTC_GEN_CNTL, default_par);
+ crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, default_par);
+ crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, default_par);
+ crtc.v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, default_par);
+ crtc.v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, default_par);
+ crtc.gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, default_par);
aty_crtc_to_var(&crtc, var);
- h_total = var->xres + var->right_margin +
- var->hsync_len + var->left_margin;
- v_total = var->yres + var->lower_margin +
- var->vsync_len + var->upper_margin;
+ h_total = var->xres + var->right_margin + var->hsync_len + var->left_margin;
+ v_total = var->yres + var->lower_margin + var->vsync_len + var->upper_margin;
/*
* Read the PLL to figure actual Refresh Rate.
@@ -2188,8 +2446,7 @@
/*
* PLL Post Divider P (Dependant on CLOCK_CNTL):
*/
- P = 1 << (pll_regs[6] >>
- ((clock_cntl & 3) << 1));
+ P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
/*
* PLL Divider Q:
@@ -2217,8 +2474,7 @@
#else /* __sparc__ */
info->fix.mmio_start = 0x7ff000 + addr;
- default_par->ati_regbase = (unsigned long)
- ioremap(info->fix.mmio_start, 0x1000);
+ default_par->ati_regbase = (unsigned long)ioremap(info->fix.mmio_start, 0x1000);
if (!default_par->ati_regbase) {
kfree(default_par);
@@ -2237,8 +2493,7 @@
pci_read_config_word(pdev, PCI_COMMAND, &tmp);
if (!(tmp & PCI_COMMAND_MEMORY)) {
tmp |= PCI_COMMAND_MEMORY;
- pci_write_config_word(pdev, PCI_COMMAND,
- tmp);
+ pci_write_config_word(pdev, PCI_COMMAND, tmp);
}
#ifdef __BIG_ENDIAN
/* Use the big-endian aperture */
@@ -2247,8 +2502,207 @@
/* Map in frame buffer */
info->fix.smem_start = addr;
- info->screen_base =
- (char *) ioremap(addr, 0x800000);
+ info->screen_base = (char *)ioremap(addr, 0x800000);
+
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+ /* To support an LCD panel, we should know it's dimensions and
+ it's desired pixel clock.
+ There are two ways to do it:
+ - Check the startup video mode and calculate the panel
+ size from it. This is unreliable.
+ - Read it from the driver information table in the video BIOS.
+
+ So, we try to find a BIOS and get access to it.
+ */
+ rom_addr = 0xc0000 + ((aty_ld_le32(SCRATCH_REG1, default_par) & 0x7f) << 11);
+ default_par->bios_base_phys = rom_addr;
+ default_par->bios_base = (unsigned long)ioremap(rom_addr, 0x10000);
+
+ /* The BIOS starts with 0xaa55. */
+ if (*((u16 *)default_par->bios_base) == 0xaa55) {
+ printk(KERN_INFO "atyfb: Mach64 BIOS is located at %x, mapped at %x.\n",
+ (u32)default_par->bios_base_phys, (u32)default_par->bios_base);
+
+ /* Address of driver information table is at offset 0x78. */
+ driv_inf_tab = default_par->bios_base + *((u16 *)(default_par->bios_base+0x78));
+
+ /* Check for the driver information table signature. */
+ sig = (*(u32 *)driv_inf_tab);
+ if ((sig == 0x54504c24) || /* Rage LT pro */
+ (sig == 0x544d5224) || /* Rage mobility */
+ (sig == 0x54435824) || /* Rage XC */
+ (sig == 0x544c5824)) { /* Rage XL */
+ printk(KERN_INFO "atyfb: BIOS contains driver information table.\n");
+ lcd_ofs = (*(u16 *)(driv_inf_tab + 10));
+ default_par->lcd_table = 0;
+ if (lcd_ofs != 0) {
+ default_par->lcd_table = default_par->bios_base + lcd_ofs;
+ }
+ }
+ }
+ if (default_par->lcd_table != 0) {
+ char model[24];
+ char strbuf[16];
+ char refresh_rates_buf[100];
+ int id, tech, f, i, m, default_refresh_rate;
+ char *txtcolour;
+ char *txtmonitor;
+ char *txtdual;
+ char *txtformat;
+ u16 width, height, panel_type, refresh_rates;
+ u16 *lcdmodeptr;
+ u32 format;
+ u8 lcd_refresh_rates[16] = {50,56,60,67,70,72,75,76,85,90,100,120,140,150,160,200};
+ /* The most important information is the panel size at
+ offset 25 and 27, but there's some other nice information
+ which we print to the screen.
+ */
+ id = *(u8 *)default_par->lcd_table;
+ strncpy(model,(char *)default_par->lcd_table+1,24);
+ model[23]=0;
+
+ width = default_par->lcd_width = *(u16 *)(default_par->lcd_table+25);
+ height = default_par->lcd_height = *(u16 *)(default_par->lcd_table+27);
+ panel_type = *(u16 *)(default_par->lcd_table+29);
+ if (panel_type & 1)
+ txtcolour = "colour";
+ else
+ txtcolour = "monochrome";
+ if (panel_type & 2)
+ txtdual = "dual (split) ";
+ else
+ txtdual = "";
+ tech = (panel_type>>2) & 63;
+ switch (tech) {
+ case 0:
+ txtmonitor = "passive matrix";
+ break;
+ case 1:
+ txtmonitor = "active matrix";
+ break;
+ case 2:
+ txtmonitor = "active addressed STN";
+ break;
+ case 3:
+ txtmonitor = "EL";
+ break;
+ case 4:
+ txtmonitor = "plasma";
+ break;
+ default:
+ txtmonitor = "unknown";
+ }
+ format = *(u32 *)(default_par->lcd_table+57);
+ if (tech == 0 || tech == 2) {
+ switch (format & 7) {
+ case 0:
+ txtformat = "12 bit interface";
+ break;
+ case 1:
+ txtformat = "16 bit interface";
+ break;
+ case 2:
+ txtformat = "24 bit interface";
+ break;
+ default:
+ txtformat = "unkown format";
+ }
+ } else {
+ switch (format & 7) {
+ case 0:
+ txtformat = "8 colours";
+ break;
+ case 1:
+ txtformat = "512 colours";
+ break;
+ case 2:
+ txtformat = "4096 colours";
+ break;
+ case 4:
+ txtformat = "262144 colours (LT mode)";
+ break;
+ case 5:
+ txtformat = "16777216 colours";
+ break;
+ case 6:
+ txtformat = "262144 colours (FDPI-2 mode)";
+ break;
+ default:
+ 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);
+ refresh_rates_buf[0] = 0;
+ refresh_rates = *(u16 *)(default_par->lcd_table+62);
+ m = 1;
+ f = 0;
+ for (i=0;i<16;i++) {
+ if (refresh_rates & m) {
+ if (f == 0) {
+ sprintf(strbuf, "%d", lcd_refresh_rates[i]);
+ f++;
+ } else {
+ sprintf(strbuf, ",%d", lcd_refresh_rates[i]);
+ }
+ strcat(refresh_rates_buf,strbuf);
+ }
+ m = m << 1;
+ }
+ default_refresh_rate = (*(u8 *)(default_par->lcd_table+61) & 0xf0) >> 4;
+ printk(KERN_INFO " supports %s Hz refresh rates, default %d Hz\n",
+ refresh_rates_buf, lcd_refresh_rates[default_refresh_rate]);
+ /* We now need to determine the crtc parameters for the
+ lcd monitor. This is tricky, because they are not stored
+ individually in the BIOS. Instead, the BIOS contains a
+ table of display modes that work for this monitor.
+
+ The idea is that we search for a mode of the same dimensions
+ as the dimensions of the lcd monitor. Say our lcd monitor
+ is 800x600 pixels, we search for a 800x600 monitor.
+ The CRTC parameters we find here are the ones that we need
+ to use to simulate other resolutions on the lcd screen.
+ */
+ lcdmodeptr = (u16 *)(default_par->lcd_table + 64);
+ while (*lcdmodeptr != 0) {
+ u32 modeptr;
+ u16 mwidth,mheight;
+ modeptr = default_par->bios_base + *lcdmodeptr;
+
+ mwidth = *((u16 *)(modeptr+0));
+ mheight = *((u16 *)(modeptr+2));
+
+ if (mwidth == width && mheight == height) {
+ default_par->lcd_pixclock = 100000000 / *((u16 *)(modeptr+9));
+ default_par->lcd_htotal = *((u16 *)(modeptr+17)) & 511;
+ default_par->lcd_hdisp = *((u16 *)(modeptr+19)) & 511;
+ default_par->lcd_hsync_start = *((u16 *)(modeptr+21)) & 511;
+ default_par->lcd_hsync_delay = (*((u16 *)(modeptr+21)) >> 9) & 7;
+ default_par->lcd_hsync_width = *((u8 *)(modeptr+23)) & 63;
+ default_par->lcd_vtotal = *((u16 *)(modeptr+24)) & 2047;
+ default_par->lcd_vdisp = *((u16 *)(modeptr+26)) & 2047;
+ default_par->lcd_vsync_start = *((u16 *)(modeptr+28)) & 2047;
+ default_par->lcd_vsync_width = (*((u16 *)(modeptr+28)) >> 11) & 31;
+ default_par->lcd_right = default_par->lcd_hsync_start - default_par->lcd_hdisp;
+ default_par->lcd_lower = default_par->lcd_vsync_start - default_par->lcd_vdisp;
+ default_par->lcd_hblank_width = default_par->lcd_htotal - default_par->lcd_hdisp;
+ default_par->lcd_vblank_width = default_par->lcd_vtotal - default_par->lcd_vdisp;
+ break;
+ }
+
+ lcdmodeptr++;
+ }
+ if (*lcdmodeptr == 0) {
+ printk(KERN_WARNING "atyfb: 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",
+ default_par->lcd_pixclock, default_par->lcd_htotal, default_par->lcd_hdisp, default_par->lcd_hsync_start,
+ default_par->lcd_hsync_delay, default_par->lcd_hsync_width, default_par->lcd_vtotal, default_par->lcd_vdisp,
+ default_par->lcd_vsync_start, default_par->lcd_vsync_width);
+ }
+ }
+#endif /* CONFIG_FB_ATY_GENERIC_LCD */
if (!info->screen_base) {
kfree(info);
@@ -2377,11 +2831,11 @@
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);
+ 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);
+ 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 =
diff -u -r /usr/src/linux-2.5.orig/drivers/video/aty/mach64_ct.c /usr/src/linux-2.5.XX/drivers/video/aty/mach64_ct.c
--- /usr/src/linux-2.5.orig/drivers/video/aty/mach64_ct.c 2003-01-02 04:20:50.000000000 +0100
+++ /usr/src/linux-2.5.XX/drivers/video/aty/mach64_ct.c 2003-01-17 17:54:53.000000000 +0100
@@ -13,18 +13,19 @@
/* FIXME: remove the FAIL definition */
#define FAIL(x) do { printk(x "\n"); return -EINVAL; } while (0)
+#define DENBUG
static void aty_st_pll(int offset, u8 val, const struct atyfb_par *par);
static int aty_valid_pll_ct(const struct fb_info *info, u32 vclk_per,
struct pll_ct *pll);
-static int aty_dsp_gt(const struct fb_info *info, u8 bpp,
+static int aty_dsp_gt(const struct fb_info *info, u32 bpp, u32 stretch,
struct pll_ct *pll);
static int aty_var_to_pll_ct(const struct fb_info *info, u32 vclk_per,
- u8 bpp, union aty_pll *pll);
+ u32 bpp, u32 stretch, union aty_pll *pll);
static u32 aty_pll_ct_to_var(const struct fb_info *info,
const union aty_pll *pll);
-
+static u8 postdividers[] = {1,2,4,8,3};
static void aty_st_pll(int offset, u8 val, const struct atyfb_par *par)
{
@@ -32,7 +33,7 @@
aty_st_8(CLOCK_CNTL + 1, (offset << 2) | PLL_WR_EN, par);
/* write the register value */
aty_st_8(CLOCK_CNTL + 2, val, par);
- aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, par);
+ aty_st_8(CLOCK_CNTL + 1, (offset << 2), par);
}
@@ -42,58 +43,39 @@
* PLL programming (Mach64 CT family)
*/
-static int aty_dsp_gt(const struct fb_info *info, u8 bpp,
- struct pll_ct *pll)
+static int aty_dsp_gt(const struct fb_info *info, u32 bpp,
+ u32 width, struct pll_ct *pll)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
- u32 dsp_xclks_per_row, dsp_loop_latency, dsp_precision, dsp_off,
- dsp_on;
- u32 xclks_per_row, fifo_off, fifo_on, y, fifo_size, page_size;
+ u32 dsp_xclks_per_row, dsp_precision, dsp_off, dsp_on;
+ u32 xclks_per_row, fifo_off, fifo_on, y, page_size;
/* xclocks_per_row<<11 */
xclks_per_row =
- (pll->mclk_fb_div * pll->vclk_post_div_real * 64 << 11) /
- (pll->vclk_fb_div * pll->mclk_post_div_real * bpp);
+ (par->mclk_fb_div * pll->vclk_post_div_real * 64 << 11) /
+ (pll->vclk_fb_div * par->xclk_post_div_real * bpp);
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+ if (width != 0)
+ xclks_per_row = (xclks_per_row * par->lcd_width) / width;
+#endif
if (xclks_per_row < (1 << 11))
FAIL("Dotclock to high");
- if (M64_HAS(FIFO_24)) {
- fifo_size = 24;
- dsp_loop_latency = 0;
- } else {
- fifo_size = 32;
- dsp_loop_latency = 2;
- }
+
dsp_precision = 0;
- y = (xclks_per_row * fifo_size) >> 11;
+ y = (xclks_per_row * par->fifo_size) >> 11;
while (y) {
y >>= 1;
dsp_precision++;
}
dsp_precision -= 5;
/* fifo_off<<6 */
- fifo_off = ((xclks_per_row * (fifo_size - 1)) >> 5) + (3 << 6);
+ fifo_off = ((xclks_per_row * (par->fifo_size - 1)) >> 5) + (3 << 6);
- if (info->fix.smem_len > 1 * 1024 * 1024) {
- if (par->ram_type >= SDRAM) {
- /* >1 MB SDRAM */
- dsp_loop_latency += 8;
- page_size = 8;
- } else {
- /* >1 MB DRAM */
- dsp_loop_latency += 6;
- page_size = 9;
- }
- } else {
- if (par->ram_type >= SDRAM) {
- /* <2 MB SDRAM */
- dsp_loop_latency += 9;
- page_size = 10;
- } else {
- /* <2 MB DRAM */
- dsp_loop_latency += 8;
- page_size = 10;
- }
- }
+ page_size = par->page_size;
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+ if (width != 0)
+ page_size = (page_size * par->lcd_width) / width;
+#endif
/* fifo_on<<6 */
if (xclks_per_row >= (page_size << 11))
fifo_on =
@@ -106,7 +88,7 @@
dsp_off = fifo_off >> dsp_precision;
pll->dsp_config = (dsp_xclks_per_row & 0x3fff) |
- ((dsp_loop_latency & 0xf) << 16) | ((dsp_precision & 7) << 20);
+ ((par->dsp_loop_latency & 0xf) << 16) | ((dsp_precision & 7) << 20);
pll->dsp_on_off = (dsp_on & 0x7ff) | ((dsp_off & 0x7ff) << 16);
return 0;
}
@@ -118,109 +100,40 @@
u32 q, x; /* x is a workaround for sparc64-linux-gcc */
x = x; /* x is a workaround for sparc64-linux-gcc */
- pll->pll_ref_div = par->pll_per * 2 * 255 / par->ref_clk_per;
-
- /* FIXME: use the VTB/GTB /3 post divider if it's better suited */
- q = par->ref_clk_per * pll->pll_ref_div * 4 / par->mclk_per; /* actually 8*q */
- if (q < 16 * 8 || q > 255 * 8)
- FAIL("mclk out of range");
- else if (q < 32 * 8)
- pll->mclk_post_div_real = 8;
- else if (q < 64 * 8)
- pll->mclk_post_div_real = 4;
- else if (q < 128 * 8)
- pll->mclk_post_div_real = 2;
- else
- pll->mclk_post_div_real = 1;
- pll->mclk_fb_div = q * pll->mclk_post_div_real / 8;
+ par->pll_ref_div = par->pll_per * 2 * 255 / par->ref_clk_per;
/* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
- q = par->ref_clk_per * pll->pll_ref_div * 4 / vclk_per; /* actually 8*q */
- if (q < 16 * 8 || q > 255 * 8)
+ q = par->ref_clk_per * par->pll_ref_div * 4 / vclk_per; /* actually 8*q */
+ if (q < 16*8 || q > 255*8)
FAIL("vclk out of range");
- else if (q < 32 * 8)
- pll->vclk_post_div_real = 8;
- else if (q < 64 * 8)
- pll->vclk_post_div_real = 4;
- else if (q < 128 * 8)
- pll->vclk_post_div_real = 2;
- else
- pll->vclk_post_div_real = 1;
- pll->vclk_fb_div = q * pll->vclk_post_div_real / 8;
- return 0;
-}
-
-void aty_calc_pll_ct(const struct fb_info *info, struct pll_ct *pll)
-{
- struct atyfb_par *par = (struct atyfb_par *) info->par;
- u8 mpostdiv = 0;
- u8 vpostdiv = 0;
-
- if (M64_HAS(SDRAM_MAGIC_PLL) && (par->ram_type >= SDRAM))
- pll->pll_gen_cntl = 0x04;
- else
- pll->pll_gen_cntl = 0x84;
-
- switch (pll->mclk_post_div_real) {
- case 1:
- mpostdiv = 0;
- break;
- case 2:
- mpostdiv = 1;
- break;
- case 3:
- mpostdiv = 4;
- break;
- case 4:
- mpostdiv = 2;
- break;
- case 8:
- mpostdiv = 3;
- break;
+ else {
+ pll->vclk_post_div = 0;
+ if (q < 128*8)
+ pll->vclk_post_div++;
+ if (q < 64*8)
+ pll->vclk_post_div++;
+ if (q < 32*8)
+ pll->vclk_post_div++;
}
- pll->pll_gen_cntl |= mpostdiv << 4; /* mclk */
-
- if (M64_HAS(MAGIC_POSTDIV))
- pll->pll_ext_cntl = 0;
- else
- pll->pll_ext_cntl = mpostdiv; /* xclk == mclk */
-
- switch (pll->vclk_post_div_real) {
- case 2:
- vpostdiv = 1;
- break;
- case 3:
- pll->pll_ext_cntl |= 0x10;
- case 1:
- vpostdiv = 0;
- break;
- case 6:
- pll->pll_ext_cntl |= 0x10;
- case 4:
- vpostdiv = 2;
- break;
- case 12:
- pll->pll_ext_cntl |= 0x10;
- case 8:
- vpostdiv = 3;
- break;
- }
-
+ pll->vclk_post_div_real = postdividers[pll->vclk_post_div];
+ pll->vclk_fb_div = q*pll->vclk_post_div_real/8;
pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */
- pll->vclk_post_div = vpostdiv;
+
+ return 0;
}
static int aty_var_to_pll_ct(const struct fb_info *info, u32 vclk_per,
- u8 bpp, union aty_pll *pll)
+ u32 bpp, u32 width, union aty_pll *pll)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
int err;
if ((err = aty_valid_pll_ct(info, vclk_per, &pll->ct)))
return err;
- if (M64_HAS(GTB_DSP) && (err = aty_dsp_gt(info, bpp, &pll->ct)))
+// aty_dsp_gt2(info,bpp,width,vclk_per,&pll->ct);
+ if (M64_HAS(GTB_DSP) && (err = aty_dsp_gt(info, bpp, width, &pll->ct)))
return err;
- aty_calc_pll_ct(info, &pll->ct);
+// aty_calc_pll_ct(info, &pll->ct);
return 0;
}
@@ -230,7 +143,7 @@
struct atyfb_par *par = (struct atyfb_par *) info->par;
u32 ref_clk_per = par->ref_clk_per;
- u8 pll_ref_div = pll->ct.pll_ref_div;
+ u8 pll_ref_div = par->pll_ref_div;
u8 vclk_fb_div = pll->ct.vclk_fb_div;
u8 vclk_post_div = pll->ct.vclk_post_div_real;
@@ -240,16 +153,181 @@
void aty_set_pll_ct(const struct fb_info *info,
const union aty_pll *pll)
{
- struct atyfb_par *par = (struct atyfb_par *) info->par;
+ struct atyfb_par *par = (struct atyfb_par *)info->par;
+
+ u8 tmp, tmp2; u32 crtc_gen_cntl;
+#ifdef DEBUG
+ printk("aty_set_pll_ct: setting clock %i for FeedBackDivider %i, ReferenceDivider %i, PostDivider %i\n",
+ par->clock, pll->ct.vclk_fb_div, par->pll_ref_div, pll->ct.vclk_post_div);
+#endif
+ /* Temporarily switch to accelerator mode */
+ crtc_gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
+ if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
+ aty_st_le32(CRTC_GEN_CNTL, crtc_gen_cntl | CRTC_EXT_DISP_EN, par);
+
+ /* Reset VCLK generator */
+ aty_st_pll(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl, par);
+
+ /* Set post-divider */
+ tmp2 = par->clock << 1;
+ tmp = aty_ld_pll(VCLK_POST_DIV, par);
+ tmp &= ~(0x03U << tmp2);
+ tmp |= ((pll->ct.vclk_post_div & 0x03U) << tmp2);
+ aty_st_pll(VCLK_POST_DIV, tmp, par);
+
+ /* Set extended post-divider */
+ tmp = aty_ld_pll(PLL_EXT_CNTL, par);
+ tmp &= ~(0x10U << par->clock);
+ tmp |= (((pll->ct.vclk_post_div >> 2) & 0x10U) << par->clock);
+ aty_st_pll(PLL_EXT_CNTL, tmp, par);
+
+ /* Set feedback divider */
+ tmp = VCLK0_FB_DIV + par->clock;
+ aty_st_pll(tmp, (pll->ct.vclk_fb_div & 0xFFU), par);
+
+ /* End VCLK generator reset */
+ aty_st_pll(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl & ~(0x04U), par);
+
+ /* Reset write bit */
+ /* ATIAccessMach64PLLReg(pATI, 0, FALSE); */
+
+ /* Restore register */
+ if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
+ aty_st_le32(CRTC_GEN_CNTL, crtc_gen_cntl, par);
+
+ if (M64_HAS(GTB_DSP)) {
+ aty_st_le32(DSP_CONFIG, pll->ct.dsp_config, par);
+ aty_st_le32(DSP_ON_OFF, pll->ct.dsp_on_off, par);
+ }
+}
+
+
+static void __init aty_init_pll_ct(struct fb_info *info) {
+ struct atyfb_par *par = (struct atyfb_par *)info->par;
+ u8 pll_ref_div, pll_gen_cntl, pll_ext_cntl;
+ u8 mpost_div, xpost_div;
+ u8 sclk_post_div_real, sclk_fb_div, spll_cntl2;
+ u32 q;
- aty_st_pll(PLL_REF_DIV, pll->ct.pll_ref_div, par);
- aty_st_pll(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par);
- aty_st_pll(MCLK_FB_DIV, pll->ct.mclk_fb_div, par);
- aty_st_pll(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl, par);
- aty_st_pll(VCLK_POST_DIV, pll->ct.vclk_post_div, par);
- aty_st_pll(VCLK0_FB_DIV, pll->ct.vclk_fb_div, par);
- aty_st_pll(PLL_EXT_CNTL, pll->ct.pll_ext_cntl, par);
+ if (M64_HAS(FIFO_24)) {
+ par->fifo_size = 24;
+ par->dsp_loop_latency = 0;
+ } else {
+ par->fifo_size = 32;
+ par->dsp_loop_latency = 2;
+ }
+ if (info->fix.smem_len > 1*1024*1024) {
+ if (par->ram_type >= SDRAM) {
+ /* >1 MB SDRAM */
+ par->dsp_loop_latency += 8;
+ par->page_size = 8;
+ } else {
+ /* >1 MB DRAM */
+ par->dsp_loop_latency += 6;
+ par->page_size = 9;
+ }
+ } else {
+ if (par->ram_type >= SDRAM) {
+ /* <2 MB SDRAM */
+ par->dsp_loop_latency += 9;
+ par->page_size = 10;
+ } else {
+ /* <2 MB DRAM */
+ par->dsp_loop_latency += 8;
+ par->page_size = 10;
+ }
+ }
+
+ /* Exit if the user does not want us to play with the clock
+ rates of her chip. */
+ if (par->mclk_per == 0) {
+ u16 mclk_fb_div;
+ u8 pll_ext_cntl;
+
+ par->pll_ref_div = aty_ld_pll(PLL_REF_DIV, par);
+ pll_ext_cntl = aty_ld_pll(PLL_EXT_CNTL, par);
+ par->xclk_post_div_real = postdividers[pll_ext_cntl & 7];
+ mclk_fb_div = aty_ld_pll(MCLK_FB_DIV, par);
+ if (pll_ext_cntl & 8)
+ mclk_fb_div <<= 1;
+ par->mclk_fb_div = mclk_fb_div;
+ return;
+ }
+
+ pll_ref_div = par->pll_per * 2 * 255 / par->ref_clk_per;
+ par->pll_ref_div = pll_ref_div;
+
+ /* FIXME: use the VTB/GTB /3 post divider if it's better suited */
+ q = par->ref_clk_per * pll_ref_div * 4 / par->xclk_per; /* actually 8*q */
+ if (q < 16*8 || q > 255*8) {
+ printk(KERN_CRIT "xclk out of range\n");
+ return;
+ } else {
+ xpost_div = 0;
+ if (q < 128*8)
+ xpost_div++;
+ if (q < 64*8)
+ xpost_div++;
+ if (q < 32*8)
+ xpost_div++;
+ }
+ par->xclk_post_div_real = postdividers[xpost_div];
+ par->mclk_fb_div = q * par->xclk_post_div_real / 8;
+
+ if (M64_HAS(SDRAM_MAGIC_PLL) && (par->ram_type >= SDRAM))
+ pll_gen_cntl = 0x04;
+ else
+ pll_gen_cntl = 0x84;
+
+ if (M64_HAS(MAGIC_POSTDIV))
+ pll_ext_cntl = 0;
+ else
+ pll_ext_cntl = xpost_div;
+
+ if (par->mclk_per == par->xclk_per)
+ pll_gen_cntl |= xpost_div<<4; /* mclk == xclk */
+ else {
+ pll_gen_cntl |= 6<<4; /* mclk == sclk*/
+
+ q = par->ref_clk_per * pll_ref_div * 4 / par->mclk_per; /* actually 8*q */
+ if (q < 16 * 8 || q > 255 * 8) {
+ printk(KERN_CRIT "mclk out of range\n");
+ return;
+ } else {
+ mpost_div = 0;
+ if (q < 128*8)
+ mpost_div++;
+ if (q < 64*8)
+ mpost_div++;
+ if (q < 32*8)
+ mpost_div++;
+ }
+ sclk_post_div_real = postdividers[mpost_div];
+ sclk_fb_div = q * sclk_post_div_real / 8;
+ spll_cntl2 = mpost_div << 4;
+/*
+ This disables the sclk, crashes the computer as reported:
+ aty_st_pll(SPLL_CNTL2, 3, info);
+
+ So it seems the sclk must be enabled before it is used;
+ so PLL_GEN_CNTL must be programmed *after* the sclk.
+*/
+#ifdef DEBUG
+ printk(KERN_INFO "sclk_fb_div: %x spll_cntl2:%x\n",
+ sclk_fb_div, spll_cntl2);
+#endif
+ aty_st_pll(SPLL_CNTL2, spll_cntl2, par);
+ aty_st_pll(SCLK_FB_DIV, sclk_fb_div, par);
+ }
+#ifdef DEBUG
+ printk(KERN_INFO "pll_ref_div: %x pll_gencntl: %x mclk_fb_div: %x pll_ext_cntl: %x\n",
+ pll_ref_div, pll_gen_cntl, par->mclk_fb_div, pll_ext_cntl);
+#endif
+ aty_st_pll(PLL_REF_DIV, pll_ref_div, par);
+ aty_st_pll(PLL_GEN_CNTL, pll_gen_cntl, par);
+ aty_st_pll(MCLK_FB_DIV, par->mclk_fb_div, par);
+ aty_st_pll(PLL_EXT_CNTL, pll_ext_cntl, par);
if (M64_HAS(GTB_DSP)) {
if (M64_HAS(XL_DLL))
aty_st_pll(DLL_CNTL, 0x80, par);
@@ -258,8 +336,6 @@
else
aty_st_pll(DLL_CNTL, 0xa0, par);
aty_st_pll(VFC_CNTL, 0x1b, par);
- aty_st_le32(DSP_CONFIG, pll->ct.dsp_config, par);
- aty_st_le32(DSP_ON_OFF, pll->ct.dsp_on_off, par);
}
}
@@ -269,11 +345,12 @@
}
const struct aty_dac_ops aty_dac_ct = {
- .set_dac = (void *) dummy,
+ set_dac: (void *)dummy,
};
const struct aty_pll_ops aty_pll_ct = {
- .var_to_pll = aty_var_to_pll_ct,
- .pll_to_var = aty_pll_ct_to_var,
- .set_pll = aty_set_pll_ct,
+ var_to_pll: aty_var_to_pll_ct,
+ pll_to_var: aty_pll_ct_to_var,
+ set_pll: aty_set_pll_ct,
+ init_pll: aty_init_pll_ct
};
diff -u -r /usr/src/linux-2.5.orig/drivers/video/aty/mach64_cursor.c /usr/src/linux-2.5.XX/drivers/video/aty/mach64_cursor.c
--- /usr/src/linux-2.5.orig/drivers/video/aty/mach64_cursor.c 2003-01-02 04:23:09.000000000 +0100
+++ /usr/src/linux-2.5.XX/drivers/video/aty/mach64_cursor.c 2003-01-17 18:40:50.000000000 +0100
@@ -135,6 +135,10 @@
yoff = 0;
}
+ /* In doublescan mode, the cursor location also needs to be
+ doubled. */
+ if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN)
+ y<<=1;
wait_for_fifo(4, par);
aty_st_le32(CUR_OFFSET, (info->fix.smem_len >> 3) + (yoff << 1),
par);
diff -u -r /usr/src/linux-2.5.orig/drivers/video/aty/mach64_gx.c /usr/src/linux-2.5.XX/drivers/video/aty/mach64_gx.c
--- /usr/src/linux-2.5.orig/drivers/video/aty/mach64_gx.c 2003-01-02 04:21:12.000000000 +0100
+++ /usr/src/linux-2.5.XX/drivers/video/aty/mach64_gx.c 2003-01-17 19:04:58.000000000 +0100
@@ -5,7 +5,6 @@
#include <linux/delay.h>
#include <linux/fb.h>
-#include <linux/sched.h>
#include <asm/io.h>
@@ -35,7 +34,11 @@
#define MIN_N 35
#define MAX_N 255-8
-
+static int dummy(void)
+{
+ return 0;
+}
+
/*
* Support Functions
*/
@@ -189,13 +192,14 @@
}
const struct aty_dac_ops aty_dac_ibm514 = {
- .set_dac = aty_set_dac_514,
+ set_dac: aty_set_dac_514,
};
const struct aty_pll_ops aty_pll_ibm514 = {
- .var_to_pll = aty_var_to_pll_514,
- .pll_to_var = aty_pll_514_to_var,
- .set_pll = aty_set_pll_514,
+ var_to_pll: aty_var_to_pll_514,
+ pll_to_var: aty_pll_514_to_var,
+ set_pll: aty_set_pll_514,
+ init_pll: (void *) dummy
};
@@ -278,7 +282,7 @@
}
const struct aty_dac_ops aty_dac_ati68860b = {
- .set_dac = aty_set_dac_ATI68860_B,
+ set_dac: aty_set_dac_ATI68860_B,
};
@@ -331,7 +335,7 @@
}
const struct aty_dac_ops aty_dac_att21c498 = {
- .set_dac = aty_set_dac_ATT21C498,
+ set_dac: aty_set_dac_ATT21C498,
};
@@ -485,9 +489,10 @@
}
const struct aty_pll_ops aty_pll_ati18818_1 = {
- .var_to_pll = aty_var_to_pll_18818,
- .pll_to_var = aty_pll_18818_to_var,
- .set_pll = aty_set_pll18818,
+ var_to_pll: aty_var_to_pll_18818,
+ pll_to_var: aty_pll_18818_to_var,
+ set_pll: aty_set_pll18818,
+ init_pll: (void *) dummy
};
@@ -601,9 +606,10 @@
}
const struct aty_pll_ops aty_pll_stg1703 = {
- .var_to_pll = aty_var_to_pll_1703,
- .pll_to_var = aty_pll_1703_to_var,
- .set_pll = aty_set_pll_1703,
+ var_to_pll: aty_var_to_pll_1703,
+ pll_to_var: aty_pll_1703_to_var,
+ set_pll: aty_set_pll_1703,
+ init_pll: (void *) dummy
};
@@ -725,9 +731,10 @@
}
const struct aty_pll_ops aty_pll_ch8398 = {
- .var_to_pll = aty_var_to_pll_8398,
- .pll_to_var = aty_pll_8398_to_var,
- .set_pll = aty_set_pll_8398,
+ var_to_pll: aty_var_to_pll_8398,
+ pll_to_var: aty_pll_8398_to_var,
+ set_pll: aty_set_pll_8398,
+ init_pll: (void *) dummy
};
@@ -872,9 +879,10 @@
}
const struct aty_pll_ops aty_pll_att20c408 = {
- .var_to_pll = aty_var_to_pll_408,
- .pll_to_var = aty_pll_408_to_var,
- .set_pll = aty_set_pll_408,
+ var_to_pll: aty_var_to_pll_408,
+ pll_to_var: aty_pll_408_to_var,
+ set_pll: aty_set_pll_408,
+ init_pll: (void *) dummy
};
@@ -896,17 +904,13 @@
return 0;
}
-static int dummy(void)
-{
- return 0;
-}
-
const struct aty_dac_ops aty_dac_unsupported = {
- .set_dac = aty_set_dac_unsupported,
+ set_dac: aty_set_dac_unsupported,
};
const struct aty_pll_ops aty_pll_unsupported = {
- .var_to_pll = (void *) dummy,
- .pll_to_var = (void *) dummy,
- .set_pll = (void *) dummy,
+ var_to_pll: (void *) dummy,
+ pll_to_var: (void *) dummy,
+ set_pll: (void *) dummy,
+ init_pll: (void *) dummy
};
diff -u -r /usr/src/linux-2.5.orig/drivers/video/modedb.c /usr/src/linux-2.5.XX/drivers/video/modedb.c
--- /usr/src/linux-2.5.orig/drivers/video/modedb.c 2003-01-02 04:21:55.000000000 +0100
+++ /usr/src/linux-2.5.XX/drivers/video/modedb.c 2003-01-17 18:33:32.000000000 +0100
@@ -129,6 +129,14 @@
NULL, 68, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3,
0, FB_VMODE_NONINTERLACED
}, {
+ /* 1400x1050 @ 75,107 Hz, 82,392 kHz +hsync +vsync*/
+ "LCD_XGA_75", 75, 1400, 1050, 9271, 120, 56, 13, 0, 112, 3,
+ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ }, {
+ /* 1400x1050 @ 60 Hz, ? kHz +hsync +vsync*/
+ "LCD_XGA_60", 60, 1400, 1050, 9259, 128, 40, 12, 0, 112, 3,
+ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ }, {
/* 1024x768 @ 85 Hz, 70.24 kHz hsync */
NULL, 85, 1024, 768, 10111, 192, 32, 34, 14, 160, 6,
0, FB_VMODE_NONINTERLACED
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] 2.5.59 for ATI Mach64(port from Daniel code for 2.5.59)
2003-01-17 21:27 [PATCH] 2.5.59 for ATI Mach64(port from Daniel code for 2.5.59) Alexander Kern
@ 2003-01-18 11:01 ` Alexander Kern
2003-01-24 19:07 ` James Simmons
0 siblings, 1 reply; 3+ messages in thread
From: Alexander Kern @ 2003-01-18 11:01 UTC (permalink / raw)
To: Linux-fbdev-devel
Am Freitag, 17. Januar 2003 22:27 schrieb Alexander Kern:
> Hi, tested with ATI RAGE 3D MOBILITY M1 (P/M). 1400x1050 works, i assume
> all others must work too.
Arrrrh, full speed back.
Please don't beat me, it works only with 1400x1050 on exetern CRT, image
timing for LCD is incorrect
-------------------------------------------------------
This SF.NET email is sponsored by: Thawte.com - A 128-bit supercerts will
allow you to extend the highest allowed 128 bit encryption to all your
clients even if they use browsers that are limited to 40 bit encryption.
Get a guide here:http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0030en
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] 2.5.59 for ATI Mach64(port from Daniel code for 2.5.59)
2003-01-18 11:01 ` Alexander Kern
@ 2003-01-24 19:07 ` James Simmons
0 siblings, 0 replies; 3+ messages in thread
From: James Simmons @ 2003-01-24 19:07 UTC (permalink / raw)
To: Alexander Kern; +Cc: Linux-fbdev-devel
> Am Freitag, 17. Januar 2003 22:27 schrieb Alexander Kern:
> > Hi, tested with ATI RAGE 3D MOBILITY M1 (P/M). 1400x1050 works, i assume
> > all others must work too.
>
> Arrrrh, full speed back.
>
> Please don't beat me, it works only with 1400x1050 on exetern CRT, image
> timing for LCD is incorrect
Do you want me to applied the changes still?
-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2003-01-24 19:08 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-01-17 21:27 [PATCH] 2.5.59 for ATI Mach64(port from Daniel code for 2.5.59) Alexander Kern
2003-01-18 11:01 ` Alexander Kern
2003-01-24 19:07 ` James Simmons
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).