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;
u32 dsp_config; /* Mach64 GTB DSP */
u32 dsp_on_off; /* Mach64 GTB DSP */
/* 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,42 +125,68 @@ 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
};
/*
* ATI Mach64 features
*/
......@@ -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
......@@ -195,14 +282,14 @@ static inline u8 aty_ld_pll(int offset, const struct atyfb_par *par)
struct aty_dac_ops {
int (*set_dac) (const struct fb_info * info,
const union aty_pll * pll, u32 bpp, u32 accel);
const union aty_pll * pll, u32 bpp, u32 accel);
};
extern const struct aty_dac_ops aty_dac_ibm514; /* IBM RGB514 */
extern const struct aty_dac_ops aty_dac_ati68860b; /* ATI 68860-B */
extern const struct aty_dac_ops aty_dac_att21c498; /* AT&T 21C498 */
extern const struct aty_dac_ops aty_dac_unsupported; /* unsupported */
extern const struct aty_dac_ops aty_dac_ct; /* Integrated */
extern const struct aty_dac_ops aty_dac_ibm514; /* IBM RGB514 */
extern const struct aty_dac_ops aty_dac_ati68860b; /* ATI 68860-B */
extern const struct aty_dac_ops aty_dac_att21c498; /* AT&T 21C498 */
extern const struct aty_dac_ops aty_dac_unsupported; /* unsupported */
extern const struct aty_dac_ops aty_dac_ct; /* Integrated */
/*
......@@ -210,37 +297,32 @@ 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 */
extern const struct aty_pll_ops aty_pll_stg1703; /* STG 1703 */
extern const struct aty_pll_ops aty_pll_ch8398; /* Chrontel 8398 */
extern const struct aty_pll_ops aty_pll_att20c408; /* AT&T 20C408 */
extern const struct aty_pll_ops aty_pll_ibm514; /* IBM RGB514 */
extern const struct aty_pll_ops aty_pll_unsupported; /* unsupported */
extern const struct aty_pll_ops aty_pll_ct; /* Integrated */
extern const struct aty_pll_ops aty_pll_ati18818_1; /* ATI 18818 */
extern const struct aty_pll_ops aty_pll_stg1703; /* STG 1703 */
extern const struct aty_pll_ops aty_pll_ch8398; /* Chrontel 8398 */
extern const struct aty_pll_ops aty_pll_att20c408; /* AT&T 20C408 */
extern const struct aty_pll_ops aty_pll_ibm514; /* IBM RGB514 */
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 */
......@@ -146,7 +165,7 @@ void aty_init_engine(struct atyfb_par *par, struct fb_info *info)
aty_st_le32(DP_CHAIN_MASK, par->crtc.dp_chain_mask, par);
wait_for_fifo(5, par);
aty_st_le32(SCALE_3D_CNTL, 0, par);
aty_st_le32(SCALE_3D_CNTL, 0, par);
aty_st_le32(Z_CNTL, 0, par);
aty_st_le32(CRTC_INT_CNTL, aty_ld_le32(CRTC_INT_CNTL, par) & ~0x20,
par);
......@@ -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;
if (par->blitter_may_be_busy)
wait_for_idle(par);
cfb_imageblit(info, image);
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);
}
This diff is collapsed.
/*
* 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;
}
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));
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;
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));
}
info->fbops->fb_cursor = atyfb_cursor;
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);
......
This diff is collapsed.
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