Commit ba7d0db1 authored by Antonino Daplas's avatar Antonino Daplas Committed by Linus Torvalds

[PATCH] fbdev: Various mach64 changes

  Alexander Kern <alex.kern@gmx.de>
  [PATCH] port Daniel Mantione 2.4 driver to 2.6
  [PATCH] add more pci_id number
  [PATCH] add accelerated imgblit
  [PATCH] revert SDRAM_MAGIC_PLL to old behaviour
  [PATCH] do a "from BIOS" initialisation only by __i386__

  Arnaud FONTAINE <arnaud.fontaine@free.fr>
  [PATCH atyfb] correction for 3D Rage Mobility L

  Geert Uytterhoeven <geert@linux-m68k.org>
  [PATCH atyfb] Atari Atyfb fixes
  [PATCH atyfb] Atyfb on Mach64 GX or Atari
  [PATCH 468] m68k sparse floating point

  James Simmons <jsimmons@infradead.org>
  [PATCH add] port to framebuffer_alloc api

  Nicolas Souchu <nsouch@free.fr>
  [PATCH] I do not found a copy, but it was incorporated too

  Ville Syrjälä <syrjala@sci.fi>
  [PATCH] fix pan with doublescan
  [PATCH] another double scan fix
  [PATCH] disable linear aperture register access
  [PATCH] Memory type correction
  [PATCH] atyfb (2.6): Fix mmio_start
  [PATCH] atyfb (2.6): Fix mem_refresh_rate for Mobility
  [PATCH] atyfb (2.6): Add RGB565 support
  [PATCH] atyfb: Blank LCD by turning off backlight voltage
  [PATCH] atyfb: Rage LT LCD register access
  [PATCH] atyfb: vblank irq support
  [PATCH] atyfb: MTRR support


Antonino Daplas <adaplas@pol.net>
   remove/modify all references to info->cursor
Signed-off-by: default avatarAntonino Daplas <adaplas@pol.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent b9a30828
......@@ -750,6 +750,19 @@ config FB_ATY_CT
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 "Mach64 generic LCD support (EXPERIMENTAL)"
depends on FB_ATY_CT
help
Say Y if you have a laptop with an ATI Rage LT PRO, Rage Mobility,
Rage XC, or Rage XL chipset.
config FB_ATY_XL_INIT
bool "Rage XL No-BIOS Init support"
depends on FB_ATY_CT
help
Say Y here to support booting a Rage XL without BIOS support.
config FB_ATY_GX
bool "Mach64 GX support" if PCI
depends on FB_ATY
......@@ -761,12 +774,6 @@ config FB_ATY_GX
is at
<http://support.ati.com/products/pc/mach64/graphics_xpression.html>.
config FB_ATY_XL_INIT
bool " Rage XL No-BIOS Init support" if FB_ATY_CT
depends on FB_ATY
help
Say Y here to support booting a Rage XL without BIOS support.
config FB_SIS
tristate "SiS acceleration"
depends on FB && PCI
......
......@@ -64,6 +64,7 @@
#define PCI_CHIP_MACH64LQ 0x4C51
#define PCI_CHIP_MACH64LR 0x4C52
#define PCI_CHIP_MACH64LS 0x4C53
#define PCI_CHIP_MACH64LT 0x4C54
#define PCI_CHIP_RADEON_LW 0x4C57
#define PCI_CHIP_RADEON_LX 0x4C58
#define PCI_CHIP_RADEON_LY 0x4C59
......
......@@ -3,6 +3,8 @@
*/
#include <linux/config.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
/*
* Elements of the hardware specific atyfb_par structure
*/
......@@ -10,16 +12,60 @@
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;
u32 v_sync_strt_wid;
u32 vline_crnt_vline;
u32 off_pitch;
u32 gen_cntl;
u32 dp_pix_width; /* acceleration */
u32 dp_chain_mask; /* acceleration */
#ifdef CONFIG_FB_ATY_GENERIC_LCD
u32 horz_stretching;
u32 vert_stretching;
u32 ext_vert_stretch;
u32 shadow_h_tot_disp;
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;
int sclk, mclk, mclk_pm, xclk;
int ref_div;
int ref_clk;
};
typedef struct {
u16 unknown1;
u16 PCLK_min_freq;
u16 PCLK_max_freq;
u16 unknown2;
u16 ref_freq;
u16 ref_divider;
u16 unknown3;
u16 MCLK_pwd;
u16 MCLK_max_freq;
u16 XCLK_max_freq;
u16 SCLK_freq;
} __attribute__ ((packed)) PLL_BLOCK_MACH64;
struct pll_514 {
u8 m;
u8 n;
......@@ -36,16 +82,39 @@ struct pll_ct {
u8 pll_ref_div;
u8 pll_gen_cntl;
u8 mclk_fb_div;
u8 mclk_fb_mult; /* 2 ro 4 */
/* u8 sclk_fb_div;*/
u8 pll_vclk_cntl;
u8 vclk_post_div;
u8 vclk_fb_div;
u8 pll_ext_cntl;
/* u8 ext_vpll_cntl;
u8 spll_cntl2;*/
u32 dsp_config; /* Mach64 GTB DSP */
u32 dsp_on_off; /* Mach64 GTB DSP */
u32 dsp_loop_latency;
u32 fifo_size;
u32 xclkpagefaultdelay;
u32 xclkmaxrasdelay;
u8 xclk_ref_div;
u8 xclk_post_div;
u8 mclk_post_div_real;
u8 xclk_post_div_real;
u8 vclk_post_div_real;
u8 features;
#ifdef CONFIG_FB_ATY_GENERIC_LCD
u32 xres; /* use for LCD stretching/scaling */
#endif
};
/*
for pll_ct.features
*/
#define DONT_USE_SPLL 0x1
#define DONT_USE_XDLL 0x2
#define USE_CPUCLK 0x4
#define POWERDOWN_PLL 0x8
union aty_pll {
struct pll_ct ct;
struct pll_514 ibm514;
......@@ -56,39 +125,65 @@ union aty_pll {
* The hardware parameters for each card
*/
struct aty_cursor {
u8 bits[8][64];
u8 mask[8][64];
u8 __iomem *ram;
};
struct atyfb_par {
struct aty_cmap_regs __iomem *aty_cmap_regs;
struct { u8 red, green, blue; } palette[256];
const struct aty_dac_ops *dac_ops;
const struct aty_pll_ops *pll_ops;
struct aty_cursor *cursor;
void __iomem *ati_regbase;
unsigned long clk_wr_offset;
unsigned long clk_wr_offset; /* meaning overloaded, clock id by CT */
struct crtc crtc;
union aty_pll pll;
struct pll_info pll_limits;
u32 features;
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;
u16 pci_id;
u32 accel_flags;
int blitter_may_be_busy;
int asleep;
int lock_blank;
unsigned long res_start;
unsigned long res_size;
#ifdef __sparc__
struct pci_mmap_map *mmap_map;
u8 mmaped;
#endif
int open;
#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_refreshrate;
u16 lcd_htotal;
u16 lcd_hdisp;
u16 lcd_hsync_dly;
u16 lcd_hsync_len;
u16 lcd_vtotal;
u16 lcd_vdisp;
u16 lcd_vsync_len;
u16 lcd_right_margin;
u16 lcd_lower_margin;
u16 lcd_hblank_len;
u16 lcd_vblank_len;
#endif
#ifdef CONFIG_PMAC_PBOOK
struct fb_info *next;
unsigned char *save_framebuffer;
unsigned long save_pll[64];
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;
#ifdef CONFIG_MTRR
int mtrr_aper;
int mtrr_reg;
#endif
};
......@@ -101,7 +196,7 @@ struct atyfb_par {
#define M64F_RESET_3D 0x00000001
#define M64F_MAGIC_FIFO 0x00000002
#define M64F_GTB_DSP 0x00000004
#define M64F_FIFO_24 0x00000008
#define M64F_FIFO_32 0x00000008
#define M64F_SDRAM_MAGIC_PLL 0x00000010
#define M64F_MAGIC_POSTDIV 0x00000020
#define M64F_INTEGRATED 0x00000040
......@@ -116,9 +211,10 @@ struct atyfb_par {
#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
/*
* Register access
......@@ -137,8 +233,7 @@ static inline u32 aty_ld_le32(int regindex, const struct atyfb_par *par)
#endif
}
static inline void aty_st_le32(int regindex, u32 val,
const struct atyfb_par *par)
static inline void aty_st_le32(int regindex, u32 val, const struct atyfb_par *par)
{
/* Hack for bloc 1, should be cleanly optimized by compiler */
if (regindex >= 0x400)
......@@ -163,8 +258,7 @@ static inline u8 aty_ld_8(int regindex, const struct atyfb_par *par)
#endif
}
static inline void aty_st_8(int regindex, u8 val,
const struct atyfb_par *par)
static inline void aty_st_8(int regindex, u8 val, const struct atyfb_par *par)
{
/* Hack for bloc 1, should be cleanly optimized by compiler */
if (regindex >= 0x400)
......@@ -177,17 +271,10 @@ static inline void aty_st_8(int regindex, u8 val,
#endif
}
static inline u8 aty_ld_pll(int offset, const struct atyfb_par *par)
{
u8 res;
/* write addr byte */
aty_st_8(CLOCK_CNTL + 1, (offset << 2), par);
/* read the register value */
res = aty_ld_8(CLOCK_CNTL + 2, par);
return res;
}
#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
......@@ -210,12 +297,11 @@ extern const struct aty_dac_ops aty_dac_ct; /* Integrated */
*/
struct aty_pll_ops {
int (*var_to_pll) (const struct fb_info * info, u32 vclk_per,
u8 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);
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);
};
extern const struct aty_pll_ops aty_pll_ati18818_1; /* ATI 18818 */
......@@ -227,20 +313,16 @@ extern const struct aty_pll_ops aty_pll_unsupported; /* unsupported */
extern const struct aty_pll_ops aty_pll_ct; /* Integrated */
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_set_pll_ct(const struct fb_info *info, const union aty_pll *pll);
extern u8 aty_ld_pll_ct(int offset, const struct atyfb_par *par);
/*
* Hardware cursor support
*/
extern struct aty_cursor *aty_init_cursor(struct fb_info *info);
extern int aty_init_cursor(struct fb_info *info);
extern int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor);
extern void aty_set_cursor_color(struct fb_info *info);
extern void aty_set_cursor_shape(struct fb_info *info);
/*
* Hardware acceleration
......@@ -260,6 +342,5 @@ static inline void wait_for_idle(struct atyfb_par *par)
}
extern void aty_reset_engine(const struct atyfb_par *par);
extern void aty_init_engine(struct atyfb_par *par,
struct fb_info *info);
extern void aty_init_engine(struct atyfb_par *par, struct fb_info *info);
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -13,22 +13,41 @@
* Generic Mach64 routines
*/
/* this is for DMA GUI engine! work in progress */
typedef struct {
u32 frame_buf_offset;
u32 system_mem_addr;
u32 command;
u32 reserved;
} BM_DESCRIPTOR_ENTRY;
#define LAST_DESCRIPTOR (1 << 31)
#define SYSTEM_TO_FRAME_BUFFER 0
static u32 rotation24bpp(u32 dx, u32 direction)
{
u32 rotation;
if (direction & DST_X_LEFT_TO_RIGHT) {
rotation = (dx / 4) % 6;
} else {
rotation = ((dx + 2) / 4) % 6;
}
return ((rotation << 8) | DST_24_ROTATION_ENABLE);
}
void aty_reset_engine(const struct atyfb_par *par)
{
/* reset engine */
aty_st_le32(GEN_TEST_CNTL,
aty_ld_le32(GEN_TEST_CNTL, par) & ~GUI_ENGINE_ENABLE,
par);
aty_ld_le32(GEN_TEST_CNTL, par) & ~GUI_ENGINE_ENABLE, par);
/* enable engine */
aty_st_le32(GEN_TEST_CNTL,
aty_ld_le32(GEN_TEST_CNTL, par) | GUI_ENGINE_ENABLE,
par);
aty_ld_le32(GEN_TEST_CNTL, par) | GUI_ENGINE_ENABLE, par);
/* ensure engine is not locked up by clearing any FIFO or */
/* HOST errors */
aty_st_le32(BUS_CNTL,
aty_ld_le32(BUS_CNTL,
par) | BUS_HOST_ERR_ACK | BUS_FIFO_ERR_ACK,
par);
aty_ld_le32(BUS_CNTL, par) | BUS_HOST_ERR_ACK | BUS_FIFO_ERR_ACK, par);
}
static void reset_GTC_3D_engine(const struct atyfb_par *par)
......@@ -51,7 +70,7 @@ void aty_init_engine(struct atyfb_par *par, struct fb_info *info)
if (info->var.bits_per_pixel == 24) {
/* In 24 bpp, the engine is in 8 bpp - this requires that all */
/* horizontal coordinates and widths must be adjusted */
pitch_value = pitch_value * 3;
pitch_value *= 3;
}
/* On GTC (RagePro), we need to reset the 3D engine before */
......@@ -174,9 +193,10 @@ void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
u32 dy = area->dy, sy = area->sy, direction = DST_LAST_PEL;
u32 sx = area->sx, dx = area->dx, width = area->width;
u32 pitch_value;
u32 sx = area->sx, dx = area->dx, width = area->width, rotation = 0;
if (par->asleep)
return;
if (!area->width || !area->height)
return;
if (!par->accel_flags) {
......@@ -186,11 +206,9 @@ void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
return;
}
pitch_value = info->var.xres_virtual;
if (info->var.bits_per_pixel == 24) {
/* In 24 bpp, the engine is in 8 bpp - this requires that all */
/* horizontal coordinates and widths must be adjusted */
pitch_value *= 3;
sx *= 3;
dx *= 3;
width *= 3;
......@@ -208,19 +226,25 @@ void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
} else
direction |= DST_X_LEFT_TO_RIGHT;
if (info->var.bits_per_pixel == 24) {
rotation = rotation24bpp(dx, direction);
}
wait_for_fifo(4, par);
aty_st_le32(DP_SRC, FRGD_SRC_BLIT, par);
aty_st_le32(SRC_Y_X, (sx << 16) | sy, par);
aty_st_le32(SRC_HEIGHT1_WIDTH1, (width << 16) | area->height, par);
aty_st_le32(DST_CNTL, direction, par);
aty_st_le32(DST_CNTL, direction | rotation, par);
draw_rect(dx, dy, width, area->height, par);
}
void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
u32 color = rect->color, dx = rect->dx, width = rect->width;
u32 color = rect->color, dx = rect->dx, width = rect->width, rotation = 0;
if (par->asleep)
return;
if (!rect->width || !rect->height)
return;
if (!par->accel_flags) {
......@@ -238,6 +262,7 @@ void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
/* horizontal coordinates and widths must be adjusted */
dx *= 3;
width *= 3;
rotation = rotation24bpp(dx, DST_X_LEFT_TO_RIGHT);
}
wait_for_fifo(3, par);
......@@ -247,15 +272,162 @@ void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
par);
aty_st_le32(DST_CNTL,
DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM |
DST_X_LEFT_TO_RIGHT, par);
DST_X_LEFT_TO_RIGHT | rotation, par);
draw_rect(dx, rect->dy, width, rect->height, par);
}
void atyfb_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
u32 src_bytes, dx = image->dx, dy = image->dy, width = image->width;
u32 pix_width_save, pix_width, host_cntl, rotation = 0, src, mix;
if (par->asleep)
return;
if (!image->width || !image->height)
return;
if (!par->accel_flags ||
(image->depth != 1 && info->var.bits_per_pixel != image->depth)) {
if (par->blitter_may_be_busy)
wait_for_idle(par);
cfb_imageblit(info, image);
return;
}
wait_for_idle(par);
pix_width = pix_width_save = aty_ld_le32(DP_PIX_WIDTH, par);
host_cntl = aty_ld_le32(HOST_CNTL, par) | HOST_BYTE_ALIGN;
switch (image->depth) {
case 1:
pix_width &= ~(BYTE_ORDER_MASK | HOST_MASK);
pix_width |= (BYTE_ORDER_MSB_TO_LSB | HOST_1BPP);
break;
case 4:
pix_width &= ~(BYTE_ORDER_MASK | HOST_MASK);
pix_width |= (BYTE_ORDER_MSB_TO_LSB | HOST_4BPP);
break;
case 8:
pix_width &= ~HOST_MASK;
pix_width |= HOST_8BPP;
break;
case 15:
pix_width &= ~HOST_MASK;
pix_width |= HOST_15BPP;
break;
case 16:
pix_width &= ~HOST_MASK;
pix_width |= HOST_16BPP;
break;
case 24:
pix_width &= ~HOST_MASK;
pix_width |= HOST_24BPP;
break;
case 32:
pix_width &= ~HOST_MASK;
pix_width |= HOST_32BPP;
break;
}
if (info->var.bits_per_pixel == 24) {
/* In 24 bpp, the engine is in 8 bpp - this requires that all */
/* horizontal coordinates and widths must be adjusted */
dx *= 3;
width *= 3;
rotation = rotation24bpp(dx, DST_X_LEFT_TO_RIGHT);
pix_width &= ~DST_MASK;
pix_width |= DST_8BPP;
/*
* since Rage 3D IIc we have DP_HOST_TRIPLE_EN bit
* this hwaccelerated triple has an issue with not aligned data
*/
if (M64_HAS(HW_TRIPLE) && image->width % 8 == 0)
pix_width |= DP_HOST_TRIPLE_EN;
}
if (image->depth == 1) {
u32 fg, bg;
if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
fg = ((u32*)(info->pseudo_palette))[image->fg_color];
bg = ((u32*)(info->pseudo_palette))[image->bg_color];
} else {
fg = image->fg_color;
bg = image->bg_color;
}
wait_for_fifo(2, par);
aty_st_le32(DP_BKGD_CLR, bg, par);
aty_st_le32(DP_FRGD_CLR, fg, par);
src = MONO_SRC_HOST | FRGD_SRC_FRGD_CLR | BKGD_SRC_BKGD_CLR;
mix = FRGD_MIX_S | BKGD_MIX_S;
} else {
src = MONO_SRC_ONE | FRGD_SRC_HOST;
mix = FRGD_MIX_D_XOR_S | BKGD_MIX_D;
}
wait_for_fifo(6, par);
aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF, par);
aty_st_le32(DP_PIX_WIDTH, pix_width, par);
aty_st_le32(DP_MIX, mix, par);
aty_st_le32(DP_SRC, src, par);
aty_st_le32(HOST_CNTL, host_cntl, par);
aty_st_le32(DST_CNTL, DST_Y_TOP_TO_BOTTOM | DST_X_LEFT_TO_RIGHT | rotation, par);
draw_rect(dx, dy, width, image->height, par);
src_bytes = (((image->width * image->depth) + 7) / 8) * image->height;
/* manual triple each pixel */
if (info->var.bits_per_pixel == 24 && !(pix_width & DP_HOST_TRIPLE_EN)) {
int inbit, outbit, mult24, byte_id_in_dword, width;
u8 *pbitmapin = (u8*)image->data, *pbitmapout;
u32 hostdword;
for (width = image->width, inbit = 7, mult24 = 0; src_bytes; ) {
for (hostdword = 0, pbitmapout = (u8*)&hostdword, byte_id_in_dword = 0;
byte_id_in_dword < 4 && src_bytes;
byte_id_in_dword++, pbitmapout++) {
for (outbit = 7; outbit >= 0; outbit--) {
*pbitmapout |= (((*pbitmapin >> inbit) & 1) << outbit);
mult24++;
/* next bit */
if (mult24 == 3) {
mult24 = 0;
inbit--;
width--;
}
/* next byte */
if (inbit < 0 || width == 0) {
src_bytes--;
pbitmapin++;
inbit = 7;
if (width == 0) {
width = image->width;
outbit = 0;
}
}
}
}
wait_for_fifo(1, par);
aty_st_le32(HOST_DATA0, hostdword, par);
}
} else {
u32 *pbitmap, dwords = (src_bytes + 3) / 4;
for (pbitmap = (u32*)(image->data); dwords; dwords--, pbitmap++) {
wait_for_fifo(1, par);
aty_st_le32(HOST_DATA0, le32_to_cpup(pbitmap), par);
}
}
wait_for_idle(par);
/* restore pix_width */
wait_for_fifo(1, par);
aty_st_le32(DP_PIX_WIDTH, pix_width_save, par);
}
......@@ -4,214 +4,236 @@
*/
#include <linux/fb.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <video/mach64.h>
#include "atyfb.h"
#undef DEBUG
/* FIXME: remove the FAIL definition */
#define FAIL(x) do { printk(x "\n"); return -EINVAL; } while (0)
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,
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);
static u32 aty_pll_ct_to_var(const struct fb_info *info,
const union aty_pll *pll);
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, u32 bpp, struct pll_ct *pll);
static int aty_var_to_pll_ct(const struct fb_info *info, u32 vclk_per, u32 bpp, union aty_pll *pll);
static u32 aty_pll_to_var_ct(const struct fb_info *info, const union aty_pll *pll);
u8 aty_ld_pll_ct(int offset, const struct atyfb_par *par)
{
u8 res;
/* write addr byte */
aty_st_8(CLOCK_CNTL_ADDR, (offset << 2) & PLL_ADDR, par);
/* read the register value */
res = aty_ld_8(CLOCK_CNTL_DATA, par);
return res;
}
static void aty_st_pll(int offset, u8 val, const struct atyfb_par *par)
void aty_st_pll_ct(int offset, u8 val, const struct atyfb_par *par)
{
/* write addr byte */
aty_st_8(CLOCK_CNTL + 1, (offset << 2) | PLL_WR_EN, par);
aty_st_8(CLOCK_CNTL_ADDR, ((offset << 2) & PLL_ADDR) | 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_DATA, val & PLL_DATA, par);
aty_st_8(CLOCK_CNTL_ADDR, ((offset << 2) & PLL_ADDR) & ~PLL_WR_EN, par);
}
/*
* by Daniel Mantione
* <daniel.mantione@freepascal.org>
*
*
* ATI Mach64 CT clock synthesis description.
*
* All clocks on the Mach64 can be calculated using the same principle:
*
* XTALIN * x * FB_DIV
* CLK = ----------------------
* PLL_REF_DIV * POST_DIV
*
* XTALIN is a fixed speed clock. Common speeds are 14.31 MHz and 29.50 MHz.
* PLL_REF_DIV can be set by the user, but is the same for all clocks.
* FB_DIV can be set by the user for each clock individually, it should be set
* between 128 and 255, the chip will generate a bad clock signal for too low
* values.
* x depends on the type of clock; usually it is 2, but for the MCLK it can also
* be set to 4.
* POST_DIV can be set by the user for each clock individually, Possible values
* are 1,2,4,8 and for some clocks other values are available too.
* CLK is of course the clock speed that is generated.
*
* The Mach64 has these clocks:
*
* MCLK The clock rate of the chip
* XCLK The clock rate of the on-chip memory
* VCLK0 First pixel clock of first CRT controller
* VCLK1 Second pixel clock of first CRT controller
* VCLK2 Third pixel clock of first CRT controller
* VCLK3 Fourth pixel clock of first CRT controller
* VCLK Selected pixel clock, one of VCLK0, VCLK1, VCLK2, VCLK3
* V2CLK Pixel clock of the second CRT controller.
* SCLK Multi-purpose clock
*
* - MCLK and XCLK use the same FB_DIV
* - VCLK0 .. VCLK3 use the same FB_DIV
* - V2CLK is needed when the second CRTC is used (can be used for dualhead);
* i.e. CRT monitor connected to laptop has different resolution than built
* in LCD monitor.
* - SCLK is not available on all cards; it is know to exist on the Rage LT-PRO,
* Rage XL and Rage Mobility. It is know not to exist on the Mach64 VT.
* - V2CLK is not available on all cards, most likely only the Rage LT-PRO,
* the Rage XL and the Rage Mobility
*
* SCLK can be used to:
* - Clock the chip instead of MCLK
* - Replace XTALIN with a user defined frequency
* - Generate the pixel clock for the LCD monitor (instead of VCLK)
*/
/*
* It can be quite hard to calculate XCLK and MCLK if they don't run at the
* same frequency. Luckily, until now all cards that need asynchrone clock
* speeds seem to have SCLK.
* So this driver uses SCLK to clock the chip and XCLK to clock the memory.
*/
/* ------------------------------------------------------------------------- */
/*
/*
* PLL programming (Mach64 CT family)
*
*
* This procedure sets the display fifo. The display fifo is a buffer that
* contains data read from the video memory that waits to be processed by
* the CRT controller.
*
* On the more modern Mach64 variants, the chip doesn't calculate the
* interval after which the display fifo has to be reloaded from memory
* automatically, the driver has to do it instead.
*/
static int aty_dsp_gt(const struct fb_info *info, u8 bpp,
struct pll_ct *pll)
#define Maximum_DSP_PRECISION 7
static u8 postdividers[] = {1,2,4,8,3};
static int aty_dsp_gt(const struct fb_info *info, u32 bpp, struct pll_ct *pll)
{
u32 dsp_off, dsp_on, dsp_xclks;
u32 multiplier, divider, ras_multiplier, ras_divider, tmp;
u8 vshift, xshift;
s8 dsp_precision;
multiplier = ((u32)pll->mclk_fb_div) * pll->vclk_post_div_real;
divider = ((u32)pll->vclk_fb_div) * pll->xclk_ref_div;
ras_multiplier = pll->xclkmaxrasdelay;
ras_divider = 1;
if (bpp>=8)
divider = divider * (bpp >> 2);
vshift = (6 - 2) - pll->xclk_post_div; /* FIFO is 64 bits wide in accelerator mode ... */
if (bpp == 0)
vshift--; /* ... but only 32 bits in VGA mode. */
#ifdef CONFIG_FB_ATY_GENERIC_LCD
if (pll->xres != 0) {
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;
/* 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);
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;
while (y) {
y >>= 1;
dsp_precision++;
}
dsp_precision -= 5;
/* fifo_off<<6 */
fifo_off = ((xclks_per_row * (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;
multiplier = multiplier * par->lcd_width;
divider = divider * pll->xres & ~7;
ras_multiplier = ras_multiplier * par->lcd_width;
ras_divider = ras_divider * pll->xres & ~7;
}
#endif
/* If we don't do this, 32 bits for multiplier & divider won't be
enough in certain situations! */
while (((multiplier | divider) & 1) == 0) {
multiplier = multiplier >> 1;
divider = divider >> 1;
}
/* fifo_on<<6 */
if (xclks_per_row >= (page_size << 11))
fifo_on =
((2 * page_size + 1) << 6) + (xclks_per_row >> 5);
else
fifo_on = (3 * page_size + 2) << 6;
dsp_xclks_per_row = xclks_per_row >> dsp_precision;
dsp_on = fifo_on >> dsp_precision;
dsp_off = fifo_off >> dsp_precision;
/* Determine DSP precision first */
tmp = ((multiplier * pll->fifo_size) << vshift) / divider;
pll->dsp_config = (dsp_xclks_per_row & 0x3fff) |
((dsp_loop_latency & 0xf) << 16) | ((dsp_precision & 7) << 20);
pll->dsp_on_off = (dsp_on & 0x7ff) | ((dsp_off & 0x7ff) << 16);
return 0;
}
for (dsp_precision = -5; tmp; dsp_precision++)
tmp >>= 1;
if (dsp_precision < 0)
dsp_precision = 0;
else if (dsp_precision > Maximum_DSP_PRECISION)
dsp_precision = Maximum_DSP_PRECISION;
xshift = 6 - dsp_precision;
vshift += xshift;
/* Move on to dsp_off */
dsp_off = ((multiplier * (pll->fifo_size - 1)) << vshift) / divider -
(1 << (vshift - xshift));
/* if (bpp == 0)
dsp_on = ((multiplier * 20 << vshift) + divider) / divider;
else */
{
dsp_on = ((multiplier << vshift) + divider) / divider;
tmp = ((ras_multiplier << xshift) + ras_divider) / ras_divider;
if (dsp_on < tmp)
dsp_on = tmp;
dsp_on = dsp_on + (tmp * 2) + (pll->xclkpagefaultdelay << xshift);
}
static int aty_valid_pll_ct(const struct fb_info *info, u32 vclk_per,
struct pll_ct *pll)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
u32 q, x; /* x is a workaround for sparc64-linux-gcc */
x = x; /* x is a workaround for sparc64-linux-gcc */
/* Calculate rounding factor and apply it to dsp_on */
tmp = ((1 << (Maximum_DSP_PRECISION - dsp_precision)) - 1) >> 1;
dsp_on = ((dsp_on + tmp) / (tmp + 1)) * (tmp + 1);
pll->pll_ref_div = par->pll_per * 2 * 255 / par->ref_clk_per;
if (dsp_on >= ((dsp_off / (tmp + 1)) * (tmp + 1))) {
dsp_on = dsp_off - (multiplier << vshift) / divider;
dsp_on = (dsp_on / (tmp + 1)) * (tmp + 1);
}
/* 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;
/* Last but not least: dsp_xclks */
dsp_xclks = ((multiplier << (vshift + 5)) + divider) / divider;
/* 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)
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;
/* Get register values. */
pll->dsp_on_off = (dsp_on << 16) + dsp_off;
pll->dsp_config = (dsp_precision << 20) | (pll->dsp_loop_latency << 16) | dsp_xclks;
#ifdef DEBUG
printk("atyfb(%s): dsp_config 0x%08x, dsp_on_off 0x%08x\n",
__FUNCTION__, pll->dsp_config, pll->dsp_on_off);
#endif
return 0;
}
void aty_calc_pll_ct(const struct fb_info *info, struct pll_ct *pll)
static int aty_valid_pll_ct(const struct fb_info *info, u32 vclk_per, struct pll_ct *pll)
{
u32 q;
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;
}
pll->pll_gen_cntl |= mpostdiv << 4; /* mclk */
#ifdef DEBUG
int pllvclk;
#endif
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;
/* 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;
if (q < 16*8 || q > 255*8) {
printk(KERN_CRIT "atyfb: vclk out of range\n");
return -EINVAL;
} else {
pll->vclk_post_div = (q < 128*8);
pll->vclk_post_div += (q < 64*8);
pll->vclk_post_div += (q < 32*8);
}
pll->vclk_post_div_real = postdividers[pll->vclk_post_div];
// pll->vclk_post_div <<= 6;
pll->vclk_fb_div = q * pll->vclk_post_div_real / 8;
#ifdef DEBUG
pllvclk = (1000000 * 2 * pll->vclk_fb_div) /
(par->ref_clk_per * pll->pll_ref_div);
printk("atyfb(%s): pllvclk=%d MHz, vclk=%d MHz\n",
__FUNCTION__, pllvclk, pllvclk / pll->vclk_post_div_real);
#endif
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)
static int aty_var_to_pll_ct(const struct fb_info *info, u32 vclk_per, u32 bpp, union aty_pll *pll)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
int err;
......@@ -220,47 +242,360 @@ static int aty_var_to_pll_ct(const struct fb_info *info, u32 vclk_per,
return err;
if (M64_HAS(GTB_DSP) && (err = aty_dsp_gt(info, bpp, &pll->ct)))
return err;
aty_calc_pll_ct(info, &pll->ct);
/*aty_calc_pll_ct(info, &pll->ct);*/
return 0;
}
static u32 aty_pll_ct_to_var(const struct fb_info *info,
const union aty_pll *pll)
static u32 aty_pll_to_var_ct(const struct fb_info *info, const union aty_pll *pll)
{
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 vclk_fb_div = pll->ct.vclk_fb_div;
u8 vclk_post_div = pll->ct.vclk_post_div_real;
return ref_clk_per * pll_ref_div * vclk_post_div / vclk_fb_div / 2;
u32 ret;
ret = par->ref_clk_per * pll->ct.pll_ref_div * pll->ct.vclk_post_div_real / pll->ct.vclk_fb_div / 2;
#ifdef CONFIG_FB_ATY_GENERIC_LCD
if(pll->ct.xres > 0) {
ret *= par->lcd_width;
ret /= pll->ct.xres;
}
#endif
#ifdef DEBUG
printk("atyfb(%s): calculated 0x%08X(%i)\n", __FUNCTION__, ret, ret);
#endif
return ret;
}
void aty_set_pll_ct(const struct fb_info *info,
const union aty_pll *pll)
void aty_set_pll_ct(const struct fb_info *info, const union aty_pll *pll)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
u32 crtc_gen_cntl, lcd_gen_cntrl;
u8 tmp, tmp2;
lcd_gen_cntrl = 0;
#ifdef DEBUG
printk("atyfb(%s): about to program:\n"
"pll_ext_cntl=0x%02x pll_gen_cntl=0x%02x pll_vclk_cntl=0x%02x\n",
__FUNCTION__,
pll->ct.pll_ext_cntl, pll->ct.pll_gen_cntl, pll->ct.pll_vclk_cntl);
printk("atyfb(%s): setting clock %lu for FeedBackDivider %i, ReferenceDivider %i, PostDivider %i(%i)\n",
__FUNCTION__,
par->clk_wr_offset, pll->ct.vclk_fb_div,
pll->ct.pll_ref_div, pll->ct.vclk_post_div, pll->ct.vclk_post_div_real);
#endif
#ifdef CONFIG_FB_ATY_GENERIC_LCD
if (par->lcd_table != 0) {
/* turn off LCD */
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);
/* 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_ct(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl, par);
/* Set post-divider */
tmp2 = par->clk_wr_offset << 1;
tmp = aty_ld_pll_ct(VCLK_POST_DIV, par);
tmp &= ~(0x03U << tmp2);
tmp |= ((pll->ct.vclk_post_div & 0x03U) << tmp2);
aty_st_pll_ct(VCLK_POST_DIV, tmp, par);
/* Set extended post-divider */
tmp = aty_ld_pll_ct(PLL_EXT_CNTL, par);
tmp &= ~(0x10U << par->clk_wr_offset);
tmp &= 0xF0U;
tmp |= pll->ct.pll_ext_cntl;
aty_st_pll_ct(PLL_EXT_CNTL, tmp, par);
/* Set feedback divider */
tmp = VCLK0_FB_DIV + par->clk_wr_offset;
aty_st_pll_ct(tmp, (pll->ct.vclk_fb_div & 0xFFU), par);
aty_st_pll_ct(PLL_GEN_CNTL, (pll->ct.pll_gen_cntl & (~(PLL_OVERRIDE | PLL_MCLK_RST))) | OSC_EN, par);
/* End VCLK generator reset */
aty_st_pll_ct(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl & ~(PLL_VCLK_RST), par);
mdelay(5);
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);
aty_st_pll_ct(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par);
aty_st_pll_ct(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl, par);
mdelay(1);
/* Restore mode register */
if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
aty_st_le32(CRTC_GEN_CNTL, crtc_gen_cntl, par);
if (M64_HAS(GTB_DSP)) {
u8 dll_cntl;
if (M64_HAS(XL_DLL))
aty_st_pll(DLL_CNTL, 0x80, par);
dll_cntl = 0x80;
else if (par->ram_type >= SDRAM)
aty_st_pll(DLL_CNTL, 0xa6, par);
dll_cntl = 0xa6;
else
aty_st_pll(DLL_CNTL, 0xa0, par);
aty_st_pll(VFC_CNTL, 0x1b, par);
dll_cntl = 0xa0;
aty_st_pll_ct(DLL_CNTL, dll_cntl, par);
aty_st_pll_ct(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);
mdelay(10);
aty_st_pll_ct(DLL_CNTL, dll_cntl, par);
mdelay(10);
aty_st_pll_ct(DLL_CNTL, dll_cntl | 0x40, par);
mdelay(10);
aty_st_pll_ct(DLL_CNTL, dll_cntl & ~0x40, par);
}
#ifdef CONFIG_FB_ATY_GENERIC_LCD
if (par->lcd_table != 0) {
/* restore LCD */
aty_st_lcd(LCD_GEN_CNTL, lcd_gen_cntrl, par);
}
#endif
}
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;
clock = aty_ld_8(CLOCK_CNTL, par) & 0x03U;
tmp = clock << 1;
pll->ct.vclk_post_div = (aty_ld_pll_ct(VCLK_POST_DIV, par) >> tmp) & 0x03U;
pll->ct.pll_ext_cntl = aty_ld_pll_ct(PLL_EXT_CNTL, par) & 0x0FU;
pll->ct.vclk_fb_div = aty_ld_pll_ct(VCLK0_FB_DIV + clock, par) & 0xFFU;
pll->ct.pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par);
pll->ct.mclk_fb_div = aty_ld_pll_ct(MCLK_FB_DIV, par);
pll->ct.pll_gen_cntl = aty_ld_pll_ct(PLL_GEN_CNTL, par);
pll->ct.pll_vclk_cntl = aty_ld_pll_ct(PLL_VCLK_CNTL, par);
if (M64_HAS(GTB_DSP)) {
pll->ct.dsp_config = aty_ld_le32(DSP_CONFIG, par);
pll->ct.dsp_on_off = aty_ld_le32(DSP_ON_OFF, par);
}
}
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;
u32 q, i, memcntl, trp;
u32 dsp_config, dsp_on_off, vga_dsp_config, vga_dsp_on_off;
#ifdef DEBUG
int pllmclk, pllsclk;
#endif
pll->ct.pll_ext_cntl = aty_ld_pll_ct(PLL_EXT_CNTL, par);
pll->ct.xclk_post_div = pll->ct.pll_ext_cntl & 0x07;
pll->ct.xclk_ref_div = 1;
switch (pll->ct.xclk_post_div) {
case 0: case 1: case 2: case 3:
break;
case 4:
pll->ct.xclk_ref_div = 3;
pll->ct.xclk_post_div = 0;
break;
default:
printk(KERN_CRIT "atyfb: Unsupported xclk source: %d.\n", pll->ct.xclk_post_div);
return -EINVAL;
}
pll->ct.mclk_fb_mult = 2;
if(pll->ct.pll_ext_cntl & PLL_MFB_TIMES_4_2B) {
pll->ct.mclk_fb_mult = 4;
pll->ct.xclk_post_div -= 1;
}
#ifdef DEBUG
printk("atyfb(%s): mclk_fb_mult=%d, xclk_post_div=%d\n",
__FUNCTION__, pll->ct.mclk_fb_mult, pll->ct.xclk_post_div);
#endif
memcntl = aty_ld_le32(MEM_CNTL, par);
trp = (memcntl & 0x300) >> 8;
pll->ct.xclkpagefaultdelay = ((memcntl & 0xc00) >> 10) + ((memcntl & 0x1000) >> 12) + trp + 2;
pll->ct.xclkmaxrasdelay = ((memcntl & 0x70000) >> 16) + trp + 2;
if (M64_HAS(FIFO_32)) {
pll->ct.fifo_size = 32;
} else {
pll->ct.fifo_size = 24;
pll->ct.xclkpagefaultdelay += 2;
pll->ct.xclkmaxrasdelay += 3;
}
switch (par->ram_type) {
case DRAM:
if (info->fix.smem_len<=ONE_MB) {
pll->ct.dsp_loop_latency = 10;
} else {
pll->ct.dsp_loop_latency = 8;
pll->ct.xclkpagefaultdelay += 2;
}
break;
case EDO:
case PSEUDO_EDO:
if (info->fix.smem_len<=ONE_MB) {
pll->ct.dsp_loop_latency = 9;
} else {
pll->ct.dsp_loop_latency = 8;
pll->ct.xclkpagefaultdelay += 1;
}
break;
case SDRAM:
if (info->fix.smem_len<=ONE_MB) {
pll->ct.dsp_loop_latency = 11;
} else {
pll->ct.dsp_loop_latency = 10;
pll->ct.xclkpagefaultdelay += 1;
}
break;
case SGRAM:
pll->ct.dsp_loop_latency = 8;
pll->ct.xclkpagefaultdelay += 3;
break;
default:
pll->ct.dsp_loop_latency = 11;
pll->ct.xclkpagefaultdelay += 3;
break;
}
if (pll->ct.xclkmaxrasdelay <= pll->ct.xclkpagefaultdelay)
pll->ct.xclkmaxrasdelay = pll->ct.xclkpagefaultdelay + 1;
/* Allow BIOS to override */
dsp_config = aty_ld_le32(DSP_CONFIG, par);
dsp_on_off = aty_ld_le32(DSP_ON_OFF, par);
vga_dsp_config = aty_ld_le32(VGA_DSP_CONFIG, par);
vga_dsp_on_off = aty_ld_le32(VGA_DSP_ON_OFF, par);
if (dsp_config)
pll->ct.dsp_loop_latency = (dsp_config & DSP_LOOP_LATENCY) >> 16;
#if 0
FIXME: is it relevant for us?
if ((!dsp_on_off && !M64_HAS(RESET_3D)) ||
((dsp_on_off == vga_dsp_on_off) &&
(!dsp_config || !((dsp_config ^ vga_dsp_config) & DSP_XCLKS_PER_QW)))) {
vga_dsp_on_off &= VGA_DSP_OFF;
vga_dsp_config &= VGA_DSP_XCLKS_PER_QW;
if (ATIDivide(vga_dsp_on_off, vga_dsp_config, 5, 1) > 24)
pll->ct.fifo_size = 32;
else
pll->ct.fifo_size = 24;
}
#endif
/* Exit if the user does not want us to tamper with the clock
rates of her chip. */
if (par->mclk_per == 0) {
u8 mclk_fb_div, pll_ext_cntl;
pll->ct.pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par);
pll_ext_cntl = aty_ld_pll_ct(PLL_EXT_CNTL, par);
pll->ct.xclk_post_div_real = postdividers[pll_ext_cntl & 0x07];
mclk_fb_div = aty_ld_pll_ct(MCLK_FB_DIV, par);
if (pll_ext_cntl & PLL_MFB_TIMES_4_2B)
mclk_fb_div <<= 1;
pll->ct.mclk_fb_div = mclk_fb_div;
return 0;
}
pll->ct.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->ct.pll_ref_div * 8 /
(pll->ct.mclk_fb_mult * par->xclk_per);
if (q < 16*8 || q > 255*8) {
printk(KERN_CRIT "atxfb: xclk out of range\n");
return -EINVAL;
} else {
xpost_div = (q < 128*8);
xpost_div += (q < 64*8);
xpost_div += (q < 32*8);
}
pll->ct.xclk_post_div_real = postdividers[xpost_div];
pll->ct.mclk_fb_div = q * pll->ct.xclk_post_div_real / 8;
#ifdef DEBUG
pllmclk = (1000000 * pll->ct.mclk_fb_mult * pll->ct.mclk_fb_div) /
(par->ref_clk_per * pll->ct.pll_ref_div);
printk("atyfb(%s): pllmclk=%d MHz, xclk=%d MHz\n",
__FUNCTION__, pllmclk, pllmclk / pll->ct.xclk_post_div_real);
#endif
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;
else
pll->ct.pll_ext_cntl = xpost_div;
if (pll->ct.mclk_fb_mult == 4)
pll->ct.pll_ext_cntl |= PLL_MFB_TIMES_4_2B;
if (par->mclk_per == par->xclk_per) {
pll->ct.pll_gen_cntl |= (xpost_div << 4); /* mclk == xclk */
} else {
/*
* The chip clock is not equal to the memory clock.
* Therefore we will use sclk to clock the chip.
*/
pll->ct.pll_gen_cntl |= (6 << 4); /* mclk == sclk */
q = par->ref_clk_per * pll->ct.pll_ref_div * 4 / par->mclk_per;
if (q < 16*8 || q > 255*8) {
printk(KERN_CRIT "atyfb: mclk out of range\n");
return -EINVAL;
} else {
mpost_div = (q < 128*8);
mpost_div += (q < 64*8);
mpost_div += (q < 32*8);
}
sclk_post_div_real = postdividers[mpost_div];
sclk_fb_div = q * sclk_post_div_real / 8;
spll_cntl2 = mpost_div << 4;
#ifdef DEBUG
pllsclk = (1000000 * 2 * sclk_fb_div) /
(par->ref_clk_per * pll->ct.pll_ref_div);
printk("atyfb(%s): use sclk, pllsclk=%d MHz, sclk=mclk=%d MHz\n",
__FUNCTION__, pllsclk, pllsclk / sclk_post_div_real);
#endif
/*
* This disables the sclk, crashes the computer as reported:
* aty_st_pll_ct(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.
*/
aty_st_pll_ct(SCLK_FB_DIV, sclk_fb_div, par);
aty_st_pll_ct(SPLL_CNTL2, spll_cntl2, par);
/*
* The sclk has been started. However, I believe the first clock
* ticks it generates are not very stable. Hope this primitive loop
* helps for Rage Mobilities that sometimes crash when
* we switch to sclk. (Daniel Mantione, 13-05-2003)
*/
for (i=0;i<=0x1ffff;i++);
}
aty_st_pll_ct(PLL_REF_DIV, pll->ct.pll_ref_div, par);
aty_st_pll_ct(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par);
aty_st_pll_ct(MCLK_FB_DIV, pll->ct.mclk_fb_div, par);
aty_st_pll_ct(PLL_EXT_CNTL, pll->ct.pll_ext_cntl, par);
/* Disable the extra precision pixel clock controls since we do not use them. */
aty_st_pll_ct(EXT_VPLL_CNTL, aty_ld_pll_ct(EXT_VPLL_CNTL, par) &
~(EXT_VPLL_EN | EXT_VPLL_VGA_EN | EXT_VPLL_INSYNC), par);
return 0;
}
static int dummy(void)
......@@ -274,6 +609,8 @@ const struct aty_dac_ops aty_dac_ct = {
const struct aty_pll_ops aty_pll_ct = {
.var_to_pll = aty_var_to_pll_ct,
.pll_to_var = aty_pll_ct_to_var,
.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
};
/*
* ATI Mach64 CT/VT/GT/LT Cursor Support
*/
#include <linux/slab.h>
#include <linux/console.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/string.h>
#include <asm/io.h>
#include <asm/uaccess.h>
......@@ -19,13 +18,49 @@
#include <video/mach64.h>
#include "atyfb.h"
/*
* The hardware cursor definition requires 2 bits per pixel. The
* Cursor size reguardless of the visible cursor size is 64 pixels
* by 64 lines. The total memory required to define the cursor is
* 16 bytes / line for 64 lines or 1024 bytes of data. The data
* must be in a contigiuos format. The 2 bit cursor code values are
* as follows:
*
* 00 - pixel colour = CURSOR_CLR_0
* 01 - pixel colour = CURSOR_CLR_1
* 10 - pixel colour = transparent (current display pixel)
* 11 - pixel colour = 1's complement of current display pixel
*
* Cursor Offset 64 pixels Actual Displayed Area
* \_________________________/
* | | | |
* |<--------------->| | |
* | CURS_HORZ_OFFSET| | |
* | |_______| | 64 Lines
* | ^ | |
* | | | |
* | CURS_VERT_OFFSET| |
* | | | |
* |____________________|____| |
*
*
* The Screen position of the top left corner of the displayed
* cursor is specificed by CURS_HORZ_VERT_POSN. Care must be taken
* when the cursor hot spot is not the top left corner and the
* physical cursor position becomes negative. It will be be displayed
* if either the horizontal or vertical cursor position is negative
*
* If x becomes negative the cursor manager must adjust the CURS_HORZ_OFFSET
* to a larger number and saturate CUR_HORZ_POSN to zero.
*
* if Y becomes negative, CUR_VERT_OFFSET must be adjusted to a larger number,
* CUR_OFFSET must be adjusted to a point to the appropraite line in the cursor
* definitation and CUR_VERT_POSN must be saturated to zero.
*/
/*
* Hardware Cursor support.
*/
static const u8 cursor_pixel_map[2] = { 0, 15 };
static const u8 cursor_color_map[2] = { 0, 0xff };
static const u8 cursor_bits_lookup[16] = {
0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
......@@ -36,90 +71,25 @@ static const u8 cursor_mask_lookup[16] = {
0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00
};
void aty_set_cursor_color(struct fb_info *info)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
struct aty_cursor *c = par->cursor;
const u8 *pixel = cursor_pixel_map; /* ++Geert: Why?? */
const u8 *red = cursor_color_map;
const u8 *green = cursor_color_map;
const u8 *blue = cursor_color_map;
u32 fg_color, bg_color;
if (!c)
return;
#ifdef __sparc__
if (par->mmaped)
return;
#endif
fg_color = (u32) red[0] << 24;
fg_color |= (u32) green[0] << 16;
fg_color |= (u32) blue[0] << 8;
fg_color |= (u32) pixel[0];
bg_color = (u32) red[1] << 24;
bg_color |= (u32) green[1] << 16;
bg_color |= (u32) blue[1] << 8;
bg_color |= (u32) pixel[1];
wait_for_fifo(2, par);
aty_st_le32(CUR_CLR0, fg_color, par);
aty_st_le32(CUR_CLR1, bg_color, par);
}
void aty_set_cursor_shape(struct fb_info *info)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
struct fb_cursor *cursor = &info->cursor;
struct aty_cursor *c = par->cursor;
u8 m, b;
u8 __iomem *ram;
int x, y;
if (!c)
return;
#ifdef __sparc__
if (par->mmaped)
return;
#endif
ram = c->ram;
for (y = 0; y < cursor->image.height; y++) {
for (x = 0; x < cursor->image.width >> 2; x++) {
m = c->mask[x][y];
b = c->bits[x][y];
fb_writeb(cursor_mask_lookup[m >> 4] |
cursor_bits_lookup[(b & m) >> 4], ram++);
fb_writeb(cursor_mask_lookup[m & 0x0f] |
cursor_bits_lookup[(b & m) & 0x0f],
ram++);
}
for (; x < 8; x++) {
fb_writeb(0xaa, ram++);
fb_writeb(0xaa, ram++);
}
}
fb_memset(ram, 0xaa, (64 - cursor->image.height) * 16);
}
static void aty_set_cursor(struct fb_info *info)
int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
struct fb_cursor *cursor = &info->cursor;
struct aty_cursor *c = par->cursor;
u16 xoff, yoff;
int x, y;
if (!c)
return;
#ifdef __sparc__
if (par->mmaped)
return;
return -EPERM;
#endif
if (par->asleep)
return -EPERM;
if (cursor->enable) {
/* Hide cursor */
wait_for_fifo(1, par);
aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par) & ~HWCURSOR_ENABLE, par);
/* set position */
if (cursor->set & FB_CUR_SETPOS) {
x = cursor->image.dx - cursor->hot.x - info->var.xoffset;
if (x < 0) {
xoff = -x;
......@@ -136,107 +106,118 @@ static void aty_set_cursor(struct fb_info *info)
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);
aty_st_le32(CUR_OFFSET, (info->fix.smem_len >> 3) + (yoff << 1), par);
aty_st_le32(CUR_HORZ_VERT_OFF,
((u32) (64 - cursor->image.height + yoff) << 16) | xoff,
par);
aty_st_le32(CUR_HORZ_VERT_POSN, ((u32) y << 16) | x, par);
aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par)
| HWCURSOR_ENABLE, par);
} else {
wait_for_fifo(1, par);
aty_st_le32(GEN_TEST_CNTL,
aty_ld_le32(GEN_TEST_CNTL,
par) & ~HWCURSOR_ENABLE, par);
}
if (par->blitter_may_be_busy)
wait_for_idle(par);
}
int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
struct aty_cursor *c = par->cursor;
/* Set color map */
if (cursor->set & FB_CUR_SETCMAP) {
u32 fg_idx, bg_idx, fg, bg;
if (!c)
return -1;
fg_idx = cursor->image.fg_color;
bg_idx = cursor->image.bg_color;
#ifdef __sparc__
if (par->mmaped)
return 0;
#endif
fg = (info->cmap.red[fg_idx] << 24) |
(info->cmap.green[fg_idx] << 16) |
(info->cmap.blue[fg_idx] << 8) | 15;
bg = (info->cmap.red[bg_idx] << 24) |
(info->cmap.green[bg_idx] << 16) |
(info->cmap.blue[bg_idx] << 8);
wait_for_fifo(2, par);
aty_st_le32(CUR_CLR0, bg, par);
aty_st_le32(CUR_CLR1, fg, par);
}
aty_set_cursor(info);
cursor->image.dx = info->cursor.image.dx;
cursor->image.dy = info->cursor.image.dy;
if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
u8 *src = (u8 *)cursor->image.data;
u8 *msk = (u8 *)cursor->mask;
u8 __iomem *dst = (u8 __iomem *)info->sprite.addr;
unsigned int width = (cursor->image.width + 7) >> 3;
unsigned int height = 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 (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;
}
}
aty_set_cursor(info);
if (cursor->enable) {
wait_for_fifo(1, par);
aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par)
| HWCURSOR_ENABLE, par);
}
return 0;
}
struct aty_cursor *__init aty_init_cursor(struct fb_info *info)
int __init aty_init_cursor(struct fb_info *info)
{
struct aty_cursor *cursor;
void __iomem *addr;
cursor = kmalloc(sizeof(struct aty_cursor), GFP_ATOMIC);
if (!cursor)
return NULL;
memset(cursor, 0, sizeof(*cursor));
unsigned long addr;
info->fix.smem_len -= PAGE_SIZE;
#ifdef __sparc__
addr = (unsigned long) info->screen_base - 0x800000 + info->fix.smem_len;
cursor->ram = (u8 *) addr;
info->sprite.addr = (u8 *) addr;
#else
#ifdef __BIG_ENDIAN
addr = info->fix.smem_start - 0x800000 + info->fix.smem_len;
cursor->ram = (u8 *) ioremap(addr, 1024);
info->sprite.addr = (u8 *) ioremap(addr, 1024);
#else
addr = info->screen_base + info->fix.smem_len;
cursor->ram = addr;
addr = (unsigned long) info->screen_base + info->fix.smem_len;
info->sprite.addr = (u8 *) addr;
#endif
#endif
if (!cursor->ram) {
kfree(cursor);
return NULL;
}
return cursor;
}
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; /* and 64 lines tall. */
info->sprite.flags = FB_PIXMAP_IO;
int atyfb_set_font(struct fb_info *info, int width, int height)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
struct fb_cursor *cursor = &info->cursor;
struct aty_cursor *c = par->cursor;
int i, j;
if (c) {
if (!width || !height) {
width = 8;
height = 16;
}
cursor->hot.x = 0;
cursor->hot.y = 0;
cursor->image.width = width;
cursor->image.height = height;
memset(c->bits, 0xff, sizeof(c->bits));
memset(c->mask, 0, sizeof(c->mask));
info->fbops->fb_cursor = atyfb_cursor;
for (i = 0, j = width; j >= 0; j -= 8, i++) {
c->mask[i][height - 2] =
(j >= 8) ? 0xff : (0xff << (8 - j));
c->mask[i][height - 1] =
(j >= 8) ? 0xff : (0xff << (8 - j));
}
aty_set_cursor_color(info);
aty_set_cursor_shape(info);
}
return 1;
return 0;
}
......@@ -121,7 +121,7 @@ static int aty_set_dac_514(const struct fb_info *info,
}
static int aty_var_to_pll_514(const struct fb_info *info, u32 vclk_per,
u8 bpp, union aty_pll *pll)
u32 bpp, union aty_pll *pll)
{
/*
* FIXME: use real calculations instead of using fixed values from the old
......@@ -253,9 +253,9 @@ static int aty_set_dac_ATI68860_B(const struct fb_info *info,
temp = aty_ld_8(DAC_CNTL, par);
aty_st_8(DAC_CNTL, temp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, par);
if (info->fix.smem_len < MEM_SIZE_1M)
if (info->fix.smem_len < ONE_MB)
mask = 0x04;
else if (info->fix.smem_len == MEM_SIZE_1M)
else if (info->fix.smem_len == ONE_MB)
mask = 0x08;
else
mask = 0x0C;
......@@ -339,8 +339,8 @@ const struct aty_dac_ops aty_dac_att21c498 = {
* ATI 18818 / ICS 2595 Clock Chip
*/
static int aty_var_to_pll_18818(const struct fb_info *info,
u32 vclk_per, u8 bpp, union aty_pll *pll)
static int aty_var_to_pll_18818(const struct fb_info *info, u32 vclk_per,
u32 bpp, union aty_pll *pll)
{
u32 MHz100; /* in 0.01 MHz */
u32 program_bits;
......@@ -495,8 +495,8 @@ const struct aty_pll_ops aty_pll_ati18818_1 = {
* STG 1703 Clock Chip
*/
static int aty_var_to_pll_1703(const struct fb_info *info,
u32 vclk_per, u8 bpp, union aty_pll *pll)
static int aty_var_to_pll_1703(const struct fb_info *info, u32 vclk_per,
u32 bpp, union aty_pll *pll)
{
u32 mhz100; /* in 0.01 MHz */
u32 program_bits;
......@@ -611,8 +611,8 @@ const struct aty_pll_ops aty_pll_stg1703 = {
* Chrontel 8398 Clock Chip
*/
static int aty_var_to_pll_8398(const struct fb_info *info,
u32 vclk_per, u8 bpp, union aty_pll *pll)
static int aty_var_to_pll_8398(const struct fb_info *info, u32 vclk_per,
u32 bpp, union aty_pll *pll)
{
u32 tempA, tempB, fOut, longMHz100, diff, preDiff;
......@@ -736,7 +736,7 @@ const struct aty_pll_ops aty_pll_ch8398 = {
*/
static int aty_var_to_pll_408(const struct fb_info *info, u32 vclk_per,
u8 bpp, union aty_pll *pll)
u32 bpp, union aty_pll *pll)
{
u32 mhz100; /* in 0.01 MHz */
u32 program_bits;
......
......@@ -148,15 +148,15 @@ static void reset_sdram(struct atyfb_par *par)
static void init_dll(struct atyfb_par *par)
{
// enable DLL
aty_st_pll(PLL_GEN_CNTL,
aty_ld_pll(PLL_GEN_CNTL, par) & 0x7f,
aty_st_pll_ct(PLL_GEN_CNTL,
aty_ld_pll_ct(PLL_GEN_CNTL, par) & 0x7f,
par);
// reset DLL
aty_st_pll(DLL_CNTL, 0x82, par);
aty_st_pll(DLL_CNTL, 0xE2, par);
aty_st_pll_ct(DLL_CNTL, 0x82, par);
aty_st_pll_ct(DLL_CNTL, 0xE2, par);
mdelay(5);
aty_st_pll(DLL_CNTL, 0x82, par);
aty_st_pll_ct(DLL_CNTL, 0x82, par);
mdelay(6);
}
......@@ -164,8 +164,8 @@ static void reset_clocks(struct atyfb_par *par, struct pll_ct *pll,
int hsync_enb)
{
reset_gui(par);
aty_st_pll(MCLK_FB_DIV, pll->mclk_fb_div, par);
aty_st_pll(SCLK_FB_DIV, pll->sclk_fb_div, par);
aty_st_pll_ct(MCLK_FB_DIV, pll->mclk_fb_div, par);
aty_st_pll_ct(SCLK_FB_DIV, pll->sclk_fb_div, par);
mdelay(15);
init_dll(par);
......@@ -177,9 +177,9 @@ static void reset_clocks(struct atyfb_par *par, struct pll_ct *pll,
aty_st_8(CRTC_GEN_CNTL+3,
hsync_enb ? 0x00 : 0x04, par);
aty_st_pll(SPLL_CNTL2, pll->spll_cntl2, par);
aty_st_pll(PLL_GEN_CNTL, pll->pll_gen_cntl, par);
aty_st_pll(PLL_VCLK_CNTL, pll->pll_vclk_cntl, par);
aty_st_pll_ct(SPLL_CNTL2, pll->spll_cntl2, par);
aty_st_pll_ct(PLL_GEN_CNTL, pll->pll_gen_cntl, par);
aty_st_pll_ct(PLL_VCLK_CNTL, pll->pll_vclk_cntl, par);
}
int atyfb_xl_init(struct fb_info *info)
......@@ -216,31 +216,31 @@ int atyfb_xl_init(struct fb_info *info)
if ((err = aty_pll_ct.var_to_pll(info, 39726, 8, &pll)))
return err;
aty_st_pll(LVDS_CNTL0, 0x00, par);
aty_st_pll(DLL2_CNTL, card->dll2_cntl, par);
aty_st_pll(V2PLL_CNTL, 0x10, par);
aty_st_pll(MPLL_CNTL, MPLL_GAIN, par);
aty_st_pll(VPLL_CNTL, VPLL_GAIN, par);
aty_st_pll(PLL_VCLK_CNTL, 0x00, par);
aty_st_pll(VFC_CNTL, 0x1B, par);
aty_st_pll(PLL_REF_DIV, pll.ct.pll_ref_div, par);
aty_st_pll(PLL_EXT_CNTL, pll.ct.pll_ext_cntl, par);
aty_st_pll(SPLL_CNTL2, 0x03, par);
aty_st_pll(PLL_GEN_CNTL, 0x44, par);
aty_st_pll_ct(LVDS_CNTL0, 0x00, par);
aty_st_pll_ct(DLL2_CNTL, card->dll2_cntl, par);
aty_st_pll_ct(V2PLL_CNTL, 0x10, par);
aty_st_pll_ct(MPLL_CNTL, MPLL_GAIN, par);
aty_st_pll_ct(VPLL_CNTL, VPLL_GAIN, par);
aty_st_pll_ct(PLL_VCLK_CNTL, 0x00, par);
aty_st_pll_ct(VFC_CNTL, 0x1B, par);
aty_st_pll_ct(PLL_REF_DIV, pll.ct.pll_ref_div, par);
aty_st_pll_ct(PLL_EXT_CNTL, pll.ct.pll_ext_cntl, par);
aty_st_pll_ct(SPLL_CNTL2, 0x03, par);
aty_st_pll_ct(PLL_GEN_CNTL, 0x44, par);
reset_clocks(par, &pll.ct, 0);
mdelay(10);
aty_st_pll(VCLK_POST_DIV, 0x03, par);
aty_st_pll(VCLK0_FB_DIV, 0xDA, par);
aty_st_pll(VCLK_POST_DIV, 0x0F, par);
aty_st_pll(VCLK1_FB_DIV, 0xF5, par);
aty_st_pll(VCLK_POST_DIV, 0x3F, par);
aty_st_pll(PLL_EXT_CNTL, 0x40 | pll.ct.pll_ext_cntl, par);
aty_st_pll(VCLK2_FB_DIV, 0x00, par);
aty_st_pll(VCLK_POST_DIV, 0xFF, par);
aty_st_pll(PLL_EXT_CNTL, 0xC0 | pll.ct.pll_ext_cntl, par);
aty_st_pll(VCLK3_FB_DIV, 0x00, par);
aty_st_pll_ct(VCLK_POST_DIV, 0x03, par);
aty_st_pll_ct(VCLK0_FB_DIV, 0xDA, par);
aty_st_pll_ct(VCLK_POST_DIV, 0x0F, par);
aty_st_pll_ct(VCLK1_FB_DIV, 0xF5, par);
aty_st_pll_ct(VCLK_POST_DIV, 0x3F, par);
aty_st_pll_ct(PLL_EXT_CNTL, 0x40 | pll.ct.pll_ext_cntl, par);
aty_st_pll_ct(VCLK2_FB_DIV, 0x00, par);
aty_st_pll_ct(VCLK_POST_DIV, 0xFF, par);
aty_st_pll_ct(PLL_EXT_CNTL, 0xC0 | pll.ct.pll_ext_cntl, par);
aty_st_pll_ct(VCLK3_FB_DIV, 0x00, par);
aty_st_8(BUS_CNTL, 0x01, par);
aty_st_le32(BUS_CNTL, card->bus_cntl | 0x08000000, par);
......@@ -295,7 +295,7 @@ int atyfb_xl_init(struct fb_info *info)
aty_st_8(CRTC_GEN_CNTL+3, 0x04, par);
mdelay(10);
aty_st_pll(PLL_YCLK_CNTL, 0x25, par);
aty_st_pll_ct(PLL_YCLK_CNTL, 0x25, par);
aty_st_le16(CUSTOM_MACRO_CNTL, 0x0179, par);
aty_st_le16(CUSTOM_MACRO_CNTL+2, 0x005E, par);
......@@ -309,9 +309,9 @@ int atyfb_xl_init(struct fb_info *info)
aty_st_8(CONFIG_STAT0, 0xA0 | card->mem_type, par);
aty_st_pll(PLL_YCLK_CNTL, 0x01, par);
aty_st_pll_ct(PLL_YCLK_CNTL, 0x01, par);
mdelay(15);
aty_st_pll(PLL_YCLK_CNTL, card->pll_yclk_cntl, par);
aty_st_pll_ct(PLL_YCLK_CNTL, card->pll_yclk_cntl, par);
mdelay(1);
reset_clocks(par, &pll.ct, 0);
......
......@@ -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 */
......@@ -117,6 +119,30 @@
/* Clock Control */
#define CLOCK_CNTL 0x0090 /* Dword offset 0_24 */
/* CLOCK_CNTL register constants CT LAYOUT */
#define CLOCK_SEL 0x0f
#define CLOCK_SEL_INTERNAL 0x03
#define CLOCK_SEL_EXTERNAL 0x0c
#define CLOCK_DIV 0x30
#define CLOCK_DIV1 0x00
#define CLOCK_DIV2 0x10
#define CLOCK_DIV4 0x20
#define CLOCK_STROBE 0x40
/* ? 0x80 */
/* CLOCK_CNTL register constants GX LAYOUT */
#define CLOCK_BIT 0x04 /* For ICS2595 */
#define CLOCK_PULSE 0x08 /* For ICS2595 */
/*#define CLOCK_STROBE 0x40 dito as CT */
#define CLOCK_DATA 0x80
/* For internal PLL(CT) start */
#define CLOCK_CNTL_ADDR CLOCK_CNTL + 1
#define PLL_WR_EN 0x02
#define PLL_ADDR 0xfc
#define CLOCK_CNTL_DATA CLOCK_CNTL + 2
#define PLL_DATA 0xff
/* For internal PLL(CT) end */
#define CLOCK_SEL_CNTL 0x0090 /* Dword offset 0_24 */
/* Configuration */
......@@ -129,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 */
......@@ -137,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 */
......@@ -147,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 */
......@@ -558,7 +590,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
......@@ -572,25 +604,95 @@
#define CRTC_PIX_ORDER_MSN_LSN 0x00000000
#define CRTC_PIX_ORDER_LSN_MSN 0x00000800
#define CRTC_VSYNC_INT_EN 0x00001000ul /* XC/XL */
#define CRTC_VSYNC_INT 0x00002000ul /* XC/XL */
#define CRTC_FIFO_OVERFILL 0x0000c000ul /* VT/GT */
#define CRTC2_VSYNC_INT_EN 0x00004000ul /* XC/XL */
#define CRTC2_VSYNC_INT 0x00008000ul /* XC/XL */
#define CRTC_FIFO_LWM 0x000f0000
#define CRTC_HVSYNC_IO_DRIVE 0x00010000 /* XC/XL */
#define CRTC2_PIX_WIDTH 0x000e0000 /* LTPro */
#define VGA_128KAP_PAGING 0x00100000
#define VFC_SYNC_TRISTATE 0x00200000
#define CRTC_VGA_128KAP_PAGING 0x00100000
#define CRTC_VFC_SYNC_TRISTATE 0x00200000 /* VTB/GTB/LT */
#define CRTC2_EN 0x00200000 /* LTPro */
#define CRTC_LOCK_REGS 0x00400000
#define CRTC_SYNC_TRISTATE 0x00800000
#define CRTC_EXT_DISP_EN 0x01000000
#define CRTC_ENABLE 0x02000000
#define CRTC_DISP_REQ_ENB 0x04000000
#define VGA_ATI_LINEAR 0x08000000
#define CRTC_EN 0x02000000
#define CRTC_DISP_REQ_EN 0x04000000
#define CRTC_VGA_LINEAR 0x08000000
#define CRTC_VSYNC_FALL_EDGE 0x10000000
#define VGA_TEXT_132 0x20000000
#define VGA_XCRT_CNT_EN 0x40000000
#define VGA_CUR_B_TEST 0x80000000
#define CRTC_VGA_TEXT_132 0x20000000
#define CRTC_CNT_EN 0x40000000
#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 */
......@@ -606,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 */
......@@ -635,6 +755,7 @@
/* Mach64 engine bit constants - these are typically ORed together */
/* BUS_CNTL register constants */
#define BUS_APER_REG_DIS 0x00000010
#define BUS_FIFO_ERR_ACK 0x00200000
#define BUS_HOST_ERR_ACK 0x00800000
......@@ -652,29 +773,48 @@
/* DSP_ON_OFF register constants */
#define DSP_OFF 0x000007ff
#define DSP_ON 0x07ff0000
#define VGA_DSP_OFF DSP_OFF
#define VGA_DSP_ON DSP_ON
#define VGA_DSP_XCLKS_PER_QW DSP_XCLKS_PER_QW
/* CLOCK_CNTL register constants */
#define CLOCK_SEL 0x0f
#define CLOCK_DIV 0x30
#define CLOCK_DIV1 0x00
#define CLOCK_DIV2 0x10
#define CLOCK_DIV4 0x20
#define CLOCK_STROBE 0x40
#define PLL_WR_EN 0x02
/* PLL register indices */
/* PLL register indices and fields */
#define MPLL_CNTL 0x00
#define PLL_PC_GAIN 0x07
#define PLL_VC_GAIN 0x18
#define PLL_DUTY_CYC 0xE0
#define VPLL_CNTL 0x01
#define PLL_REF_DIV 0x02
#define PLL_GEN_CNTL 0x03
#define PLL_OVERRIDE 0x01 /* PLL_SLEEP */
#define PLL_MCLK_RST 0x02 /* PLL_MRESET */
#define OSC_EN 0x04
#define EXT_CLK_EN 0x08
#define FORCE_DCLK_TRI_STATE 0x08 /* VT4 -> */
#define MCLK_SRC_SEL 0x70
#define EXT_CLK_CNTL 0x80
#define DLL_PWDN 0x80 /* VT4 -> */
#define MCLK_FB_DIV 0x04
#define PLL_VCLK_CNTL 0x05
#define PLL_VCLK_SRC_SEL 0x03
#define PLL_VCLK_RST 0x04
#define PLL_VCLK_INVERT 0x08
#define VCLK_POST_DIV 0x06
#define VCLK0_POST 0x03
#define VCLK1_POST 0x0C
#define VCLK2_POST 0x30
#define VCLK3_POST 0xC0
#define VCLK0_FB_DIV 0x07
#define VCLK1_FB_DIV 0x08
#define VCLK2_FB_DIV 0x09
#define VCLK3_FB_DIV 0x0A
#define PLL_EXT_CNTL 0x0B
#define PLL_XCLK_MCLK_RATIO 0x03
#define PLL_XCLK_SRC_SEL 0x07
#define PLL_MFB_TIMES_4_2B 0x08
#define PLL_VCLK0_XDIV 0x10
#define PLL_VCLK1_XDIV 0x20
#define PLL_VCLK2_XDIV 0x40
#define PLL_VCLK3_XDIV 0x80
#define DLL_CNTL 0x0C
#define DLL1_CNTL 0x0C
#define VFC_CNTL 0x0D
......@@ -690,6 +830,9 @@
#define SPLL_CNTL2 0x17
#define APLL_STRAPS 0x18
#define EXT_VPLL_CNTL 0x19
#define EXT_VPLL_EN 0x04
#define EXT_VPLL_VGA_EN 0x08
#define EXT_VPLL_INSYNC 0x10
#define EXT_VPLL_REF_DIV 0x1A
#define EXT_VPLL_FB_DIV 0x1B
#define EXT_VPLL_MSB 0x1C
......@@ -708,24 +851,6 @@
#define PLL_YCLK_CNTL 0x29
#define PM_DYN_CLK_CNTL 0x2A
/* Fields in PLL registers */
#define PLL_PC_GAIN 0x07
#define PLL_VC_GAIN 0x18
#define PLL_DUTY_CYC 0xE0
#define PLL_OVERRIDE 0x01
#define PLL_MCLK_RST 0x02
#define OSC_EN 0x04
#define EXT_CLK_EN 0x08
#define MCLK_SRC_SEL 0x70
#define EXT_CLK_CNTL 0x80
#define VCLK_SRC_SEL 0x03
#define PLL_VCLK_RST 0x04
#define VCLK_INVERT 0x08
#define VCLK0_POST 0x03
#define VCLK1_POST 0x0C
#define VCLK2_POST 0x30
#define VCLK3_POST 0xC0
/* CONFIG_CNTL register constants */
#define APERTURE_4M_ENABLE 1
#define APERTURE_8M_ENABLE 2
......@@ -811,6 +936,7 @@
#define MEM_BNDRY_1M 0x00030000
#define MEM_BNDRY_EN 0x00040000
#define ONE_MB 0x100000
/* ATI PCI constants */
#define PCI_ATI_VENDOR_ID 0x1002
......@@ -849,7 +975,19 @@
#define LI_CHIP_ID 0x4c49 /* RAGE LT PRO */
#define LP_CHIP_ID 0x4c50 /* RAGE LT PRO */
#define LT_CHIP_ID 0x4c54 /* RAGE LT */
#define XL_CHIP_ID 0x4752 /* RAGE (XL) */
/* mach64CT family / (Rage XL) class */
#define GR_CHIP_ID 0x4752 /* RAGE XL, BGA, PCI33 */
#define GS_CHIP_ID 0x4753 /* RAGE XL, PQFP, PCI33 */
#define GM_CHIP_ID 0x474d /* RAGE XL, BGA, AGP 1x,2x */
#define GN_CHIP_ID 0x474e /* RAGE XL, PQFP,AGP 1x,2x */
#define GO_CHIP_ID 0x474f /* RAGE XL, BGA, PCI66 */
#define GL_CHIP_ID 0x474c /* RAGE XL, PQFP, PCI66 */
#define IS_XL(id) ((id)==GR_CHIP_ID || (id)==GS_CHIP_ID || \
(id)==GM_CHIP_ID || (id)==GN_CHIP_ID || \
(id)==GO_CHIP_ID || (id)==GL_CHIP_ID)
#define GT_CHIP_ID 0x4754 /* RAGE (GT) */
#define GU_CHIP_ID 0x4755 /* RAGE II/II+ (GTB) */
#define GV_CHIP_ID 0x4756 /* RAGE IIC, PCI */
......@@ -860,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
......@@ -889,7 +1031,7 @@
#define MACH64_UNKNOWN 0
#define MACH64_GX 1
#define MACH64_CX 2
#define MACH64_CT 3
#define MACH64_CT 3Restore
#define MACH64_ET 4
#define MACH64_VT 5
#define MACH64_GT 6
......@@ -934,26 +1076,34 @@
#define DP_CHAIN_32BPP 0x8080
/* DP_PIX_WIDTH register constants */
#define DST_1BPP 0
#define DST_4BPP 1
#define DST_8BPP 2
#define DST_15BPP 3
#define DST_16BPP 4
#define DST_32BPP 6
#define SRC_1BPP 0
#define DST_1BPP 0x0
#define DST_4BPP 0x1
#define DST_8BPP 0x2
#define DST_15BPP 0x3
#define DST_16BPP 0x4
#define DST_24BPP 0x5
#define DST_32BPP 0x6
#define DST_MASK 0xF
#define SRC_1BPP 0x000
#define SRC_4BPP 0x100
#define SRC_8BPP 0x200
#define SRC_15BPP 0x300
#define SRC_16BPP 0x400
#define SRC_24BPP 0x500
#define SRC_32BPP 0x600
#define HOST_1BPP 0
#define SRC_MASK 0xF00
#define DP_HOST_TRIPLE_EN 0x2000
#define HOST_1BPP 0x00000
#define HOST_4BPP 0x10000
#define HOST_8BPP 0x20000
#define HOST_15BPP 0x30000
#define HOST_16BPP 0x40000
#define HOST_24BPP 0x50000
#define HOST_32BPP 0x60000
#define HOST_MASK 0xF0000
#define BYTE_ORDER_MSB_TO_LSB 0
#define BYTE_ORDER_LSB_TO_MSB 0x1000000
#define BYTE_ORDER_MASK 0x1000000
/* DP_MIX register constants */
#define BKGD_MIX_NOT_D 0
......@@ -1043,6 +1193,7 @@
#define ATI36 0xb6
/* VGA Graphics Controller Registers */
#define R_GENMO 0x3cc
#define VGAGRA 0x3ce
#define GRA06 0x06
......@@ -1103,7 +1254,7 @@
/* LCD register indices */
#define CONFIG_PANEL 0x00
#define LCD_GEN_CTRL 0x01
#define LCD_GEN_CNTL 0x01
#define DSTN_CONTROL 0x02
#define HFB_PITCH_ADDR 0x03
#define HORZ_STRETCHING 0x04
......@@ -1148,6 +1299,74 @@
#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
#define LCD_SET_PRIMARY_MASK 0x07FFFBFBul
/* 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 VERT_STRETCH_RATIO3 0x000003fful
#define FORCE_DAC_DATA 0x000000fful
#define FORCE_DAC_DATA_SEL 0x00000300ul
#define VERT_STRETCH_MODE 0x00000400ul
#define VERT_PANEL_SIZE 0x003ff800ul
#define AUTO_VERT_RATIO 0x00400000ul
#define USE_AUTO_FP_POS 0x00800000ul
#define USE_AUTO_LCD_VSYNC 0x01000000ul
/* ? 0xfe000000ul */
/* Values in LCD_MISC_CNTL */
#define BIAS_MOD_LEVEL_MASK 0x0000ff00
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment