patch-2.3.10 linux/drivers/video/tgafb.c
Next file: linux/drivers/video/tgafb.h
Previous file: linux/drivers/video/fbmem.c
Back to the patch index
Back to the overall index
- Lines: 1552
- Date:
Thu Jul 1 10:57:36 1999
- Orig file:
v2.3.9/linux/drivers/video/tgafb.c
- Orig date:
Mon Dec 21 14:48:04 1998
diff -u --recursive --new-file v2.3.9/linux/drivers/video/tgafb.c linux/drivers/video/tgafb.c
@@ -1,27 +1,29 @@
/*
* linux/drivers/video/tgafb.c -- DEC 21030 TGA frame buffer device
*
- * Copyright (C) 1997 Geert Uytterhoeven
+ * Copyright (C) 1999 Martin Lucina, Tom Zerucha
+ *
+ * $Id: tgafb.c,v 1.12 1999/07/01 13:39:23 mato Exp $
*
- * This driver is partly based on the original TGA console driver
+ * This driver is partly based on the original TGA framebuffer device, which
+ * was partly based on the original TGA console driver, which are
*
- * Copyright (C) 1995 Jay Estabrook
+ * Copyright (C) 1997 Geert Uytterhoeven
+ * Copyright (C) 1995 Jay Estabrook
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*/
-
/* KNOWN PROBLEMS/TO DO ===================================================== *
*
* - How to set a single color register on 24-plane cards?
*
- * - Hardware cursor (useful for other graphics boards too)
- *
- * - Support for more resolutions
+ * - Hardware cursor/other text acceleration methods
*
* - Some redraws can stall kernel for several seconds
+ * [This should now be solved by the fast memmove() patch in 2.3.6]
*
* KNOWN PROBLEMS/TO DO ==================================================== */
@@ -45,477 +47,459 @@
#include <video/fbcon.h>
#include <video/fbcon-cfb8.h>
#include <video/fbcon-cfb32.h>
+#include "tgafb.h"
-/* TGA hardware description (minimal) */
-/*
- * Offsets within Memory Space
- */
-#define TGA_ROM_OFFSET 0x0000000
-#define TGA_REGS_OFFSET 0x0100000
-#define TGA_8PLANE_FB_OFFSET 0x0200000
-#define TGA_24PLANE_FB_OFFSET 0x0804000
-#define TGA_24PLUSZ_FB_OFFSET 0x1004000
-
-#define TGA_PLANEMASK_REG 0x0028
-#define TGA_MODE_REG 0x0030
-#define TGA_RASTEROP_REG 0x0034
-#define TGA_DEEP_REG 0x0050
-#define TGA_PIXELMASK_REG 0x005c
-#define TGA_CURSOR_BASE_REG 0x0060
-#define TGA_HORIZ_REG 0x0064
-#define TGA_VERT_REG 0x0068
-#define TGA_BASE_ADDR_REG 0x006c
-#define TGA_VALID_REG 0x0070
-#define TGA_CURSOR_XY_REG 0x0074
-#define TGA_INTR_STAT_REG 0x007c
-#define TGA_RAMDAC_SETUP_REG 0x00c0
-#define TGA_BLOCK_COLOR0_REG 0x0140
-#define TGA_BLOCK_COLOR1_REG 0x0144
-#define TGA_CLOCK_REG 0x01e8
-#define TGA_RAMDAC_REG 0x01f0
-#define TGA_CMD_STAT_REG 0x01f8
-
-/*
- * useful defines for managing the BT485 on the 8-plane TGA
- */
-#define BT485_READ_BIT 0x01
-#define BT485_WRITE_BIT 0x00
-
-#define BT485_ADDR_PAL_WRITE 0x00
-#define BT485_DATA_PAL 0x02
-#define BT485_PIXEL_MASK 0x04
-#define BT485_ADDR_PAL_READ 0x06
-#define BT485_ADDR_CUR_WRITE 0x08
-#define BT485_DATA_CUR 0x0a
-#define BT485_CMD_0 0x0c
-#define BT485_ADDR_CUR_READ 0x0e
-#define BT485_CMD_1 0x10
-#define BT485_CMD_2 0x12
-#define BT485_STATUS 0x14
-#define BT485_CMD_3 0x14
-#define BT485_CUR_RAM 0x16
-#define BT485_CUR_LOW_X 0x18
-#define BT485_CUR_HIGH_X 0x1a
-#define BT485_CUR_LOW_Y 0x1c
-#define BT485_CUR_HIGH_Y 0x1e
-
-/*
- * useful defines for managing the BT463 on the 24-plane TGAs
- */
-#define BT463_ADDR_LO 0x0
-#define BT463_ADDR_HI 0x1
-#define BT463_REG_ACC 0x2
-#define BT463_PALETTE 0x3
+ /*
+ * Global declarations
+ */
-#define BT463_CUR_CLR_0 0x0100
-#define BT463_CUR_CLR_1 0x0101
+static struct tgafb_info fb_info;
+static struct tgafb_par current_par;
+static int current_par_valid = 0;
+static struct display disp;
-#define BT463_CMD_REG_0 0x0201
-#define BT463_CMD_REG_1 0x0202
-#define BT463_CMD_REG_2 0x0203
+static char __initdata default_fontname[40] = { 0 };
+static struct fb_var_screeninfo default_var;
+static int default_var_valid = 0;
-#define BT463_READ_MASK_0 0x0205
-#define BT463_READ_MASK_1 0x0206
-#define BT463_READ_MASK_2 0x0207
-#define BT463_READ_MASK_3 0x0208
+static int currcon = 0;
-#define BT463_BLINK_MASK_0 0x0209
-#define BT463_BLINK_MASK_1 0x020a
-#define BT463_BLINK_MASK_2 0x020b
-#define BT463_BLINK_MASK_3 0x020c
+#define arraysize(x) (sizeof(x)/sizeof(*(x)))
-#define BT463_WINDOW_TYPE_BASE 0x0300
+static struct { u_char red, green, blue, pad; } palette[256];
+#ifdef FBCON_HAS_CFB32
+static u32 fbcon_cfb32_cmap[16];
+#endif
-int tga_type;
-unsigned int tga_mem_base;
-unsigned long tga_fb_base;
-unsigned long tga_regs_base;
+ /*
+ * Hardware presets
+ */
-static unsigned int fb_offset_presets[4] __initdata = {
+static unsigned int fb_offset_presets[4] = {
TGA_8PLANE_FB_OFFSET,
TGA_24PLANE_FB_OFFSET,
0xffffffff,
TGA_24PLUSZ_FB_OFFSET
};
-static unsigned int deep_presets[4] __initdata = {
+static unsigned int deep_presets[4] = {
0x00014000,
0x0001440d,
0xffffffff,
0x0001441d
};
-static unsigned int rasterop_presets[4] __initdata = {
+static unsigned int rasterop_presets[4] = {
0x00000003,
0x00000303,
0xffffffff,
0x00000303
};
-static unsigned int mode_presets[4] __initdata = {
+static unsigned int mode_presets[4] = {
0x00002000,
0x00002300,
0xffffffff,
0x00002300
};
-static unsigned int base_addr_presets[4] __initdata = {
+static unsigned int base_addr_presets[4] = {
0x00000000,
0x00000001,
0xffffffff,
0x00000001
};
-#define TGA_WRITE_REG(v,r) \
- { writel((v), tga_regs_base+(r)); mb(); }
-
-#define TGA_READ_REG(r) readl(tga_regs_base+(r))
-
-#define BT485_WRITE(v,r) \
- TGA_WRITE_REG((r),TGA_RAMDAC_SETUP_REG); \
- TGA_WRITE_REG(((v)&0xff)|((r)<<8),TGA_RAMDAC_REG);
-
-#define BT463_LOAD_ADDR(a) \
- TGA_WRITE_REG(BT463_ADDR_LO<<2, TGA_RAMDAC_SETUP_REG); \
- TGA_WRITE_REG((BT463_ADDR_LO<<10)|((a)&0xff), TGA_RAMDAC_REG); \
- TGA_WRITE_REG(BT463_ADDR_HI<<2, TGA_RAMDAC_SETUP_REG); \
- TGA_WRITE_REG((BT463_ADDR_HI<<10)|(((a)>>8)&0xff), TGA_RAMDAC_REG);
+const unsigned int bt463_cursor_source[4] = {
+ 0xffff0000, 0x00000000, 0x00000000, 0x00000000
+};
-#define BT463_WRITE(m,a,v) \
- BT463_LOAD_ADDR((a)); \
- TGA_WRITE_REG(((m)<<2),TGA_RAMDAC_SETUP_REG); \
- TGA_WRITE_REG(((m)<<10)|((v)&0xff),TGA_RAMDAC_REG);
+ /*
+ * Predefined video modes
+ * This is a subset of the standard VESA modes, recalculated from XFree86.
+ *
+ * XXX Should we store these in terms of the encoded par structs? Even better,
+ * fbcon should provide a general mechanism for doing something like this.
+ */
-unsigned char PLLbits[7] __initdata = { 0x80, 0x04, 0x00, 0x24, 0x44, 0x80, 0xb8 };
+static struct fb_videomode tgafb_predefined[] __initdata = {
+ { "640x480-60", {
+ 640, 480, 640, 480, 0, 0, 0, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
+ 0,
+ FB_VMODE_NONINTERLACED
+ }},
+ { "800x600-56", {
+ 800, 600, 800, 600, 0, 0, 0, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, 27777, 128, 24, 22, 1, 72, 2,
+ 0,
+ FB_VMODE_NONINTERLACED
+ }},
+ { "640x480-72", {
+ 640, 480, 640, 480, 0, 0, 0, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, 31746, 144, 40, 30, 8, 40, 3,
+ 0,
+ FB_VMODE_NONINTERLACED
+ }},
+ { "800x600-60", {
+ 800, 600, 800, 600, 0, 0, 0, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, 25000, 88, 40, 23, 1, 128, 4,
+ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED
+ }},
+ { "800x600-72", {
+ 800, 600, 800, 600, 0, 0, 0, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, 20000, 64, 56, 23, 37, 120, 6,
+ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED
+ }},
+ { "1024x768-60", {
+ 1024, 768, 1024, 768, 0, 0, 0, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, 15384, 168, 8, 29, 3, 144, 6,
+ 0,
+ FB_VMODE_NONINTERLACED
+ }},
+ { "1152x864-60", {
+ 1152, 864, 1152, 864, 0, 0, 0, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, 11123, 208, 64, 16, 4, 256, 8,
+ 0,
+ FB_VMODE_NONINTERLACED
+ }},
+ { "1024x768-70", {
+ 1024, 768, 1024, 768, 0, 0, 0, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, 13333, 144, 24, 29, 3, 136, 6,
+ 0,
+ FB_VMODE_NONINTERLACED
+ }},
+ { "1024x768-76", {
+ 1024, 768, 1024, 768, 0, 0, 0, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, 11764, 208, 8, 36, 16, 120, 3,
+ 0,
+ FB_VMODE_NONINTERLACED
+ }},
+ { "1152x864-70", {
+ 1152, 864, 1152, 864, 0, 0, 0, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, 10869, 106, 56, 20, 1, 160, 10,
+ 0,
+ FB_VMODE_NONINTERLACED
+ }},
+ { "1280x1024-61", {
+ 1280, 1024, 1280, 1024, 0, 0, 0, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, 9090, 200, 48, 26, 1, 184, 3,
+ 0,
+ FB_VMODE_NONINTERLACED
+ }},
+ { "1024x768-85", {
+ 1024, 768, 1024, 768, 0, 0, 0, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, 10111, 192, 32, 34, 14, 160, 6,
+ 0,
+ FB_VMODE_NONINTERLACED
+ }},
+ { "1280x1024-70", {
+ 1280, 1024, 1280, 1024, 0, 0, 0, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, 7905, 224, 32, 28, 8, 160, 8,
+ 0,
+ FB_VMODE_NONINTERLACED
+ }},
+ { "1152x864-84", {
+ 1152, 864, 1152, 864, 0, 0, 0, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, 7407, 184, 312, 32, 0, 128, 12,
+ 0,
+ FB_VMODE_NONINTERLACED
+ }},
+ { "1280x1024-76", {
+ 1280, 1024, 1280, 1024, 0, 0, 0, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, 7407, 248, 32, 34, 3, 104, 3,
+ 0,
+ FB_VMODE_NONINTERLACED
+ }},
+ { "1280x1024-85", {
+ 1280, 1024, 1280, 1024, 0, 0, 0, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, 6349, 224, 64, 44, 1, 160, 3,
+ 0,
+ FB_VMODE_NONINTERLACED
+ }},
-const unsigned long bt485_cursor_source[64] __initdata = {
-#if 1
- 0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,
- 0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,
- 0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,
- 0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,
-#else
- 0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,
- 0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,
- 0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,
- 0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,
-#endif
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-};
+ /* These are modes used by the two fixed-frequency monitors I have at home.
+ * You may or may not find these useful.
+ */
-const unsigned int bt463_cursor_source[256] __initdata = {
- 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
- 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
- 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
- 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
- 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
- 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
- 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
- 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
- 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
- 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
- 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
- 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
- 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
- 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
- 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
- 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ { "WYSE1", { /* 1280x1024 @ 72 Hz, 130 Mhz clock */
+ 1280, 1024, 1280, 1024, 0, 0, 0, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, 7692, 192, 32, 47, 0, 192, 5,
+ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED
+ }},
+ { "IBM3", { /* 1280x1024 @ 70 Hz, 120 Mhz clock */
+ 1280, 1024, 1280, 1024, 0, 0, 0, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, 8333, 192, 32, 47, 0, 192, 5,
+ 0,
+ FB_VMODE_NONINTERLACED
+ }}
};
-
-#define arraysize(x) (sizeof(x)/sizeof(*(x)))
-
-static int currcon = 0;
-static struct display disp;
-static struct fb_info fb_info;
-static struct { u_char red, green, blue, pad; } palette[256];
-#ifdef FBCON_HAS_CFB32
-static u32 fbcon_cfb32_cmap[16];
-#endif
-
-static struct fb_fix_screeninfo fb_fix = { { "DEC TGA ", } };
-static struct fb_var_screeninfo fb_var = { 0, };
+#define NUM_TOTAL_MODES arraysize(tgafb_predefined)
/*
* Interface used by the world
*/
+static void tgafb_detect(void);
+static int tgafb_encode_fix(struct fb_fix_screeninfo *fix, const void *fb_par,
+ struct fb_info_gen *info);
+static int tgafb_decode_var(const struct fb_var_screeninfo *var, void *fb_par,
+ struct fb_info_gen *info);
+static int tgafb_encode_var(struct fb_var_screeninfo *var, const void *fb_par,
+ struct fb_info_gen *info);
+static void tgafb_get_par(void *fb_par, struct fb_info_gen *info);
+static void tgafb_set_par(const void *fb_par, struct fb_info_gen *info);
+static int tgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+ u_int *transp, struct fb_info *info);
+static int tgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info);
+static int tgafb_pan_display(const struct fb_var_screeninfo *var,
+ struct fb_info_gen *info);
+static int tgafb_blank(int blank, struct fb_info_gen *info);
+static void tgafb_set_disp(const void *fb_par, struct display *disp,
+ struct fb_info_gen *info);
+
static int tgafb_open(struct fb_info *info, int user);
static int tgafb_release(struct fb_info *info, int user);
-static int tgafb_get_fix(struct fb_fix_screeninfo *fix, int con,
- struct fb_info *info);
-static int tgafb_get_var(struct fb_var_screeninfo *var, int con,
- struct fb_info *info);
-static int tgafb_set_var(struct fb_var_screeninfo *var, int con,
- struct fb_info *info);
-static int tgafb_pan_display(struct fb_var_screeninfo *var, int con,
- struct fb_info *info);
-static int tgafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
- struct fb_info *info);
-static int tgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
- struct fb_info *info);
-static int tgafb_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg, int con, struct fb_info *info);
-
-
- /*
- * Interface to the low level console driver
- */
-
+void tgafb_setup(char *options, int *ints);
void tgafb_init(void);
-static int tgafbcon_switch(int con, struct fb_info *info);
-static int tgafbcon_updatevar(int con, struct fb_info *info);
-static void tgafbcon_blank(int blank, struct fb_info *info);
+void tgafb_cleanup(struct fb_info *info);
-
- /*
- * Internal routines
- */
-
-static int tgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
- u_int *transp, struct fb_info *info);
-static int tgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
- u_int transp, struct fb_info *info);
+static void tgafb_set_pll(int f);
#if 1
-static void tga_update_palette(void);
+static int tgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info);
+static void tgafb_update_palette(void);
#endif
-static void do_install_cmap(int con, struct fb_info *info);
-
-
-static struct fb_ops tgafb_ops = {
- tgafb_open, tgafb_release, tgafb_get_fix, tgafb_get_var, tgafb_set_var,
- tgafb_get_cmap, tgafb_set_cmap, tgafb_pan_display, tgafb_ioctl
-};
/*
- * Open/Release the frame buffer device
+ * Chipset specific functions
*/
-static int tgafb_open(struct fb_info *info, int user)
-{
- /*
- * Nothing, only a usage count for the moment
- */
- MOD_INC_USE_COUNT;
- return(0);
-}
-
-static int tgafb_release(struct fb_info *info, int user)
+static void tgafb_detect(void)
{
- MOD_DEC_USE_COUNT;
- return(0);
+ return;
}
- /*
- * Get the Fixed Part of the Display
- */
-
-static int tgafb_get_fix(struct fb_fix_screeninfo *fix, int con,
- struct fb_info *info)
+static int tgafb_encode_fix(struct fb_fix_screeninfo *fix, const void *fb_par,
+ struct fb_info_gen *info)
{
- memcpy(fix, &fb_fix, sizeof(fb_fix));
- return 0;
-}
+ struct tgafb_par *par = (struct tgafb_par *)fb_par;
+ strcpy(fix->id, fb_info.gen.info.modename);
- /*
- * Get the User Defined Part of the Display
- */
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->type_aux = 0;
+ if (fb_info.tga_type == 0) /* 8-plane */
+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
+ else /* 24-plane or 24plusZ */
+ fix->visual = FB_VISUAL_TRUECOLOR;
+
+ fix->line_length = par->xres * (par->bits_per_pixel >> 3);
+ fix->smem_start = (char *)__pa(fb_info.tga_fb_base + dense_mem(fb_info.tga_fb_base));
+ fix->smem_len = fix->line_length * par->yres;
+ fix->mmio_start = (char *)__pa(fb_info.tga_regs_base);
+ fix->mmio_len = 0x1000; /* Is this sufficient? */
+ fix->xpanstep = fix->ypanstep = fix->ywrapstep = 0;
+ fix->accel = FB_ACCEL_DEC_TGA;
-static int tgafb_get_var(struct fb_var_screeninfo *var, int con,
- struct fb_info *info)
-{
- memcpy(var, &fb_var, sizeof(fb_var));
return 0;
}
- /*
- * Set the User Defined Part of the Display
- */
-
-static int tgafb_set_var(struct fb_var_screeninfo *var, int con,
- struct fb_info *info)
+static int tgafb_decode_var(const struct fb_var_screeninfo *var, void *fb_par,
+ struct fb_info_gen *info)
{
- struct display *display;
- int oldbpp = -1, err;
-
- if (con >= 0)
- display = &fb_display[con];
- else
- display = &disp; /* used during initialization */
+ struct tgafb_par *par = (struct tgafb_par *)fb_par;
- if (var->xres > fb_var.xres || var->yres > fb_var.yres ||
- var->xres_virtual > fb_var.xres_virtual ||
- var->yres_virtual > fb_var.yres_virtual ||
- var->bits_per_pixel > fb_var.bits_per_pixel ||
- var->nonstd ||
- (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
- return -EINVAL;
- memcpy(var, &fb_var, sizeof(fb_var));
-
- if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
- oldbpp = display->var.bits_per_pixel;
- display->var = *var;
- }
- if (oldbpp != var->bits_per_pixel) {
- if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
- return err;
- do_install_cmap(con, info);
+ /* round up some */
+ if (fb_info.tga_type == 0) {
+ if (var->bits_per_pixel > 8) {
+ return -EINVAL;
+ }
+ par->bits_per_pixel = 8;
+ } else {
+ if (var->bits_per_pixel > 32) {
+ return -EINVAL;
+ }
+ par->bits_per_pixel = 32;
}
- return 0;
-}
-
- /*
- * Pan or Wrap the Display
- *
- * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
- */
-
-static int tgafb_pan_display(struct fb_var_screeninfo *var, int con,
- struct fb_info *info)
-{
- if (var->xoffset || var->yoffset)
+ /* check the values for sanity */
+ if (var->xres_virtual != var->xres ||
+ var->yres_virtual != var->yres ||
+ var->nonstd || (1000000000/var->pixclock) > TGA_PLL_MAX_FREQ ||
+ (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED
+#if 0
+ || !fbmon_valid_timings(var->pixclock, var->htotal, var->vtotal, info))
+#else
+ )
+#endif
return -EINVAL;
- else
- return 0;
-}
- /*
- * Get the Colormap
- */
+ /* encode video timings */
+ par->htimings = ((var->xres/4) & TGA_HORIZ_ACT_LSB) |
+ (((var->xres/4) & 0x600 << 19) & TGA_HORIZ_ACT_MSB);
+ par->vtimings = (var->yres & TGA_VERT_ACTIVE);
+ par->htimings |= ((var->right_margin/4) << 9) & TGA_HORIZ_FP;
+ par->vtimings |= (var->lower_margin << 11) & TGA_VERT_FP;
+ par->htimings |= ((var->hsync_len/4) << 14) & TGA_HORIZ_SYNC;
+ par->vtimings |= (var->vsync_len << 16) & TGA_VERT_SYNC;
+ par->htimings |= ((var->left_margin/4) << 21) & TGA_HORIZ_BP;
+ par->vtimings |= (var->upper_margin << 22) & TGA_VERT_BP;
+
+ if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+ par->htimings |= TGA_HORIZ_POLARITY;
+ if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+ par->vtimings |= TGA_VERT_POLARITY;
+ /* what about sync on green? */
+
+ /* store other useful values in par */
+ par->xres = var->xres;
+ par->yres = var->yres;
+ par->pll_freq = 1000000000/var->pixclock;
+ par->bits_per_pixel = var->bits_per_pixel;
-static int tgafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
- struct fb_info *info)
-{
- if (con == currcon) /* current console? */
- return fb_get_cmap(cmap, kspc, tgafb_getcolreg, info);
- else if (fb_display[con].cmap.len) /* non default colormap? */
- fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
- else
- fb_copy_cmap(fb_default_cmap(256), cmap, kspc ? 0 : 2);
return 0;
}
- /*
- * Set the Colormap
- */
-static int tgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
- struct fb_info *info)
+static int tgafb_encode_var(struct fb_var_screeninfo *var, const void *fb_par,
+ struct fb_info_gen *info)
{
- int err;
+ struct tgafb_par *par = (struct tgafb_par *)fb_par;
- if (!fb_display[con].cmap.len) { /* no colormap allocated? */
- if ((err = fb_alloc_cmap(&fb_display[con].cmap, 256, 0)))
- return err;
+ /* decode video timings */
+ var->xres = ((par->htimings & TGA_HORIZ_ACT_LSB) | ((par->htimings & TGA_HORIZ_ACT_MSB) >> 19)) * 4;
+ var->yres = (par->vtimings & TGA_VERT_ACTIVE);
+ var->right_margin = ((par->htimings & TGA_HORIZ_FP) >> 9) * 4;
+ var->lower_margin = ((par->vtimings & TGA_VERT_FP) >> 11);
+ var->hsync_len = ((par->htimings & TGA_HORIZ_SYNC) >> 14) * 4;
+ var->vsync_len = ((par->vtimings & TGA_VERT_SYNC) >> 16);
+ var->left_margin = ((par->htimings & TGA_HORIZ_BP) >> 21) * 4;
+ var->upper_margin = ((par->vtimings & TGA_VERT_BP) >> 22);
+
+ if (par->htimings & TGA_HORIZ_POLARITY)
+ var->sync |= FB_SYNC_HOR_HIGH_ACT;
+ if (par->vtimings & TGA_VERT_POLARITY)
+ var->sync |= FB_SYNC_VERT_HIGH_ACT;
+
+ var->xres_virtual = var->xres;
+ var->yres_virtual = var->yres;
+ var->xoffset = var->yoffset = 0;
+
+ /* depth-related */
+ if (fb_info.tga_type == 0) {
+ var->red.offset = 0;
+ var->green.offset = 0;
+ var->blue.offset = 0;
+ } else {
+ /* XXX: is this correct? */
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
}
- if (con == currcon) { /* current console? */
- err = fb_set_cmap(cmap, kspc, tgafb_setcolreg, info);
-#if 1
- if (tga_type != 0)
- tga_update_palette();
-#endif
- return err;
- } else
- fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+ var->bits_per_pixel = par->bits_per_pixel;
+ var->grayscale = 0;
+ var->red.length = var->green.length = var->blue.length = 8;
+ var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0;
+ var->transp.offset = var->transp.length = var->transp.msb_right = 0;
+
+ /* others */
+ var->xoffset = var->yoffset = 0;
+ var->pixclock = 1000000000/par->pll_freq;
+ var->nonstd = 0;
+ var->activate = 0;
+ var->height = var->width = -1;
+ var->accel_flags = 0;
+
return 0;
}
-static int tgafb_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg, int con, struct fb_info *info)
+static void tgafb_get_par(void *fb_par, struct fb_info_gen *info)
{
- return -EINVAL;
-}
+ struct tgafb_par *par = (struct tgafb_par *)fb_par;
+ if (current_par_valid)
+ *par = current_par;
+ else {
+ if (fb_info.tga_type == 0)
+ default_var.bits_per_pixel = 8;
+ else
+ default_var.bits_per_pixel = 32;
- /*
- * Initialisation
- */
+ tgafb_decode_var(&default_var, par, info);
+ }
+}
-__initfunc(void tgafb_init(void))
+
+static void tgafb_set_par(const void *fb_par, struct fb_info_gen *info)
{
int i, j, temp;
- unsigned char *cbp;
- struct pci_dev *pdev;
-
- pdev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, NULL);
- if (!pdev)
- return;
- tga_mem_base = pdev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
-#ifdef DEBUG
- printk("tgafb_init: mem_base 0x%x\n", tga_mem_base);
-#endif /* DEBUG */
+ struct tgafb_par *par = (struct tgafb_par *)fb_par;
- tga_type = (readl((unsigned long)tga_mem_base) >> 12) & 0x0f;
- switch (tga_type) {
- case 0:
- strcat(fb_fix.id, "8plane");
- break;
- case 1:
- strcat(fb_fix.id, "24plane");
- break;
- case 3:
- strcat(fb_fix.id, "24plusZ");
- break;
- default:
- printk("TGA type (0x%x) unrecognized!\n", tga_type);
+#if 0
+ /* XXX this will break console switching with X11, maybe I need to test KD_GRAPHICS? */
+ /* if current_par is valid, check to see if we need to change anything */
+ if (current_par_valid) {
+ if (!memcmp(par, ¤t_par, sizeof current_par)) {
return;
+ }
}
-
- tga_regs_base = ((unsigned long)tga_mem_base + TGA_REGS_OFFSET);
- tga_fb_base = ((unsigned long)tga_mem_base + fb_offset_presets[tga_type]);
+#endif
+ current_par = *par;
+ current_par_valid = 1;
/* first, disable video timing */
TGA_WRITE_REG(0x03, TGA_VALID_REG); /* SCANNING and BLANK */
-
+
/* write the DEEP register */
while (TGA_READ_REG(TGA_CMD_STAT_REG) & 1) /* wait for not busy */
continue;
mb();
- TGA_WRITE_REG(deep_presets[tga_type], TGA_DEEP_REG);
+ TGA_WRITE_REG(deep_presets[fb_info.tga_type], TGA_DEEP_REG);
while (TGA_READ_REG(TGA_CMD_STAT_REG) & 1) /* wait for not busy */
continue;
mb();
/* write some more registers */
- TGA_WRITE_REG(rasterop_presets[tga_type], TGA_RASTEROP_REG);
- TGA_WRITE_REG(mode_presets[tga_type], TGA_MODE_REG);
- TGA_WRITE_REG(base_addr_presets[tga_type], TGA_BASE_ADDR_REG);
-
- /* write the PLL for 640x480 @ 60Hz */
- for (i = 0; i <= 6; i++) {
- for (j = 0; j <= 7; j++) {
- temp = (PLLbits[i] >> (7-j)) & 1;
- if (i == 6 && j == 7)
- temp |= 2;
- TGA_WRITE_REG(temp, TGA_CLOCK_REG);
- }
- }
+ TGA_WRITE_REG(rasterop_presets[fb_info.tga_type], TGA_RASTEROP_REG);
+ TGA_WRITE_REG(mode_presets[fb_info.tga_type], TGA_MODE_REG);
+ TGA_WRITE_REG(base_addr_presets[fb_info.tga_type], TGA_BASE_ADDR_REG);
+
+ /* calculate & write the PLL */
+ tgafb_set_pll(par->pll_freq);
/* write some more registers */
TGA_WRITE_REG(0xffffffff, TGA_PLANEMASK_REG);
@@ -523,21 +507,19 @@
TGA_WRITE_REG(0x12345678, TGA_BLOCK_COLOR0_REG);
TGA_WRITE_REG(0x12345678, TGA_BLOCK_COLOR1_REG);
- /* init video timing regs for 640x480 @ 60 Hz */
- TGA_WRITE_REG(0x018608a0, TGA_HORIZ_REG);
- TGA_WRITE_REG(0x084251e0, TGA_VERT_REG);
-
- if (tga_type == 0) { /* 8-plane */
+ /* init video timing regs */
+ TGA_WRITE_REG(par->htimings, TGA_HORIZ_REG);
+ TGA_WRITE_REG(par->vtimings, TGA_VERT_REG);
- fb_var.bits_per_pixel = 8;
- fb_fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ /* initalise RAMDAC */
+ if (fb_info.tga_type == 0) { /* 8-plane */
/* init BT485 RAMDAC registers */
BT485_WRITE(0xa2, BT485_CMD_0);
BT485_WRITE(0x01, BT485_ADDR_PAL_WRITE);
BT485_WRITE(0x14, BT485_CMD_3); /* cursor 64x64 */
BT485_WRITE(0x40, BT485_CMD_1);
- BT485_WRITE(0x22, BT485_CMD_2); /* WIN cursor type */
+ BT485_WRITE(0x20, BT485_CMD_2); /* cursor off, for now */
BT485_WRITE(0xff, BT485_PIXEL_MASK);
/* fill palette registers */
@@ -560,6 +542,7 @@
TGA_WRITE_REG(0x00|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
}
+#if 0
/* initialize RAMDAC cursor colors */
BT485_WRITE(0, BT485_ADDR_CUR_WRITE);
@@ -581,19 +564,39 @@
/* initialize RAMDAC cursor RAM */
BT485_WRITE(0x00, BT485_ADDR_PAL_WRITE);
- cbp = (unsigned char *)bt485_cursor_source;
- for (i = 0; i < 512; i++) {
- BT485_WRITE(*cbp++, BT485_CUR_RAM);
- }
+
+ for (i = 0; i < tga_font_height_padded; i++)
+ for (j = 7; j >= 0; j--) {
+#if 0
+ /* note that this is for a top-right alignment
+ * - top left is commented out */
+ if( j > /*<*/ ((tga_font_width - 1) >> 3) ) {
+ BT485_WRITE(0, BT485_CUR_RAM);
+ }
+ else if( j == ((tga_font_width - 1) >> 3) ) {
+ BT485_WRITE((0xff >> /*<<*/
+ (7 - ((tga_font_width - 1)&7))) , BT485_CUR_RAM);
+ }
+ else {
+ BT485_WRITE(0xff, BT485_CUR_RAM);
+ }
+#else
+ BT485_WRITE(0, BT485_CUR_RAM);
+#endif
+ }
+ for (i = tga_font_height_padded; i < 64; i++)
+ for (j = 0; j < 8; j++) {
+ BT485_WRITE(0, BT485_CUR_RAM);
+ }
+ /* mask? */
+
for (i = 0; i < 512; i++) {
BT485_WRITE(0xff, BT485_CUR_RAM);
}
+#endif
} else { /* 24-plane or 24plusZ */
- fb_var.bits_per_pixel = 32;
- fb_fix.visual = FB_VISUAL_TRUECOLOR;
-
TGA_WRITE_REG(0x01, TGA_VALID_REG); /* SCANNING */
/*
@@ -652,6 +655,7 @@
TGA_WRITE_REG(0x80|(BT463_REG_ACC<<10), TGA_RAMDAC_REG);
}
+#if 0
/*
* init cursor colors
*/
@@ -679,135 +683,204 @@
temp = tga_fb_base - 1024; /* this assumes video starts at base
and base is beyond memory start*/
- for (i = 0; i < 256; i++) {
- writel(bt463_cursor_source[i], temp + i*4);
- }
+ for (i = 0; i < tga_font_height_padded*4; i++)
+ writel(bt463_cursor_source[i&3], temp + i*4);
+ for (i = tga_font_height_padded*4; i < 256; i++)
+ writel(0, temp + i*4);
TGA_WRITE_REG(temp & 0x000fffff, TGA_CURSOR_BASE_REG);
+#endif
}
/* finally, enable video scan
- (and pray for the monitor... :-) */
+ (and pray for the monitor... :-) */
TGA_WRITE_REG(0x01, TGA_VALID_REG); /* SCANNING */
+}
- fb_var.xres = fb_var.xres_virtual = 640;
- fb_var.yres = fb_var.yres_virtual = 480;
- fb_fix.line_length = 80*fb_var.bits_per_pixel;
- fb_fix.smem_start = (char *)__pa(tga_fb_base + dense_mem(tga_fb_base));
- fb_fix.smem_len = fb_fix.line_length*fb_var.yres;
- fb_fix.type = FB_TYPE_PACKED_PIXELS;
- fb_fix.type_aux = 0;
- fb_fix.mmio_start = (char *)__pa(tga_regs_base);
- fb_fix.mmio_len = 0x1000; /* Is this sufficient? */
- fb_fix.accel = FB_ACCEL_DEC_TGA;
-
- fb_var.xoffset = fb_var.yoffset = 0;
- fb_var.grayscale = 0;
- if (tga_type == 0) { /* 8-plane */
- fb_var.red.offset = 0;
- fb_var.green.offset = 0;
- fb_var.blue.offset = 0;
- } else { /* 24-plane or 24plusZ */
- /* XXX: is this correct?? */
- fb_var.red.offset = 16;
- fb_var.green.offset = 8;
- fb_var.blue.offset = 0;
- }
- fb_var.red.length = fb_var.green.length = fb_var.blue.length = 8;
- fb_var.red.msb_right = fb_var.green.msb_right = fb_var.blue.msb_right = 0;
- fb_var.transp.offset = fb_var.transp.length = fb_var.transp.msb_right = 0;
- fb_var.nonstd = 0;
- fb_var.activate = 0;
- fb_var.height = fb_var.width = -1;
- fb_var.accel_flags = 0;
- fb_var.pixclock = 39722;
- fb_var.left_margin = 40;
- fb_var.right_margin = 24;
- fb_var.upper_margin = 32;
- fb_var.lower_margin = 11;
- fb_var.hsync_len = 96;
- fb_var.vsync_len = 2;
- fb_var.sync = 0;
- fb_var.vmode = FB_VMODE_NONINTERLACED;
-
- disp.var = fb_var;
- disp.cmap.start = 0;
- disp.cmap.len = 0;
- disp.cmap.red = disp.cmap.green = disp.cmap.blue = disp.cmap.transp = NULL;
- disp.screen_base = (char *)tga_fb_base + dense_mem(tga_fb_base);
- disp.visual = fb_fix.visual;
- disp.type = fb_fix.type;
- disp.type_aux = fb_fix.type_aux;
- disp.ypanstep = 0;
- disp.ywrapstep = 0;
- disp.line_length = fb_fix.line_length;
- disp.can_soft_blank = 1;
- disp.inverse = 0;
- switch (tga_type) {
-#ifdef FBCON_HAS_CFB8
- case 0: /* 8-plane */
- disp.dispsw = &fbcon_cfb8;
- break;
-#endif
-#ifdef FBCON_HAS_CFB32
- case 1: /* 24-plane */
- case 3: /* 24plusZ */
- disp.dispsw = &fbcon_cfb32;
- disp.dispsw_data = &fbcon_cfb32_cmap;
- break;
-#endif
- default:
- disp.dispsw = &fbcon_dummy;
+
+#define DIFFCHECK(x) { if( m <= 0x3f ) { \
+ int delta = f - (TGA_PLL_BASE_FREQ * (x)) / (r << shift); \
+ if (delta < 0) delta = -delta; \
+ if (delta < min_diff) min_diff = delta, vm = m, va = a, vr = r; } }
+
+static void tgafb_set_pll(int f)
+{
+ int n, shift, base, min_diff, target;
+ int r,a,m,vm = 34, va = 1, vr = 30;
+
+ for( r = 0 ; r < 12 ; r++ )
+ TGA_WRITE_REG(!r, TGA_CLOCK_REG);
+
+ if (f > TGA_PLL_MAX_FREQ)
+ f = TGA_PLL_MAX_FREQ;
+
+ if (f >= TGA_PLL_MAX_FREQ / 2)
+ shift = 0;
+ else if (f >= TGA_PLL_MAX_FREQ / 4)
+ shift = 1;
+ else
+ shift = 2;
+
+ TGA_WRITE_REG(shift & 1, TGA_CLOCK_REG);
+ TGA_WRITE_REG(shift >> 1, TGA_CLOCK_REG);
+
+ for( r = 0 ; r < 10 ; r++ ) {
+ TGA_WRITE_REG(0, TGA_CLOCK_REG);
}
- disp.scrollmode = SCROLL_YREDRAW;
- strcpy(fb_info.modename, fb_fix.id);
- fb_info.node = -1;
- fb_info.fbops = &tgafb_ops;
- fb_info.disp = &disp;
- fb_info.fontname[0] = '\0';
- fb_info.changevar = NULL;
- fb_info.switch_con = &tgafbcon_switch;
- fb_info.updatevar = &tgafbcon_updatevar;
- fb_info.blank = &tgafbcon_blank;
- fb_info.flags = FBINFO_FLAG_DEFAULT;
+ if (f <= 120000) {
+ TGA_WRITE_REG(0, TGA_CLOCK_REG);
+ TGA_WRITE_REG(0, TGA_CLOCK_REG);
+ }
+ else if (f <= 200000) {
+ TGA_WRITE_REG(1, TGA_CLOCK_REG);
+ TGA_WRITE_REG(0, TGA_CLOCK_REG);
+ }
+ else {
+ TGA_WRITE_REG(0, TGA_CLOCK_REG);
+ TGA_WRITE_REG(1, TGA_CLOCK_REG);
+ }
- tgafb_set_var(&fb_var, -1, &fb_info);
+ TGA_WRITE_REG(1, TGA_CLOCK_REG);
+ TGA_WRITE_REG(0, TGA_CLOCK_REG);
+ TGA_WRITE_REG(0, TGA_CLOCK_REG);
+ TGA_WRITE_REG(1, TGA_CLOCK_REG);
+ TGA_WRITE_REG(0, TGA_CLOCK_REG);
+ TGA_WRITE_REG(1, TGA_CLOCK_REG);
+
+ target = (f << shift) / TGA_PLL_BASE_FREQ;
+ min_diff = TGA_PLL_MAX_FREQ;
+
+ r = 7 / target;
+ if (!r)
+ r = 1;
+
+ base = target * r;
+ while (base < 449) {
+ for (n = base < 7 ? 7 : base ; n < base + target && n < 449; n++) {
+ m = ((n + 3) / 7) - 1;
+ a = 0;
+ DIFFCHECK((m + 1) * 7);
+ m++;
+ DIFFCHECK((m + 1) * 7);
+ m = (n / 6) - 1;
+ if( (a = n % 6))
+ DIFFCHECK( n );
+ }
+ r++;
+ base += target;
+ }
- if (register_framebuffer(&fb_info) < 0)
- return;
+ vr--;
- printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node),
- fb_fix.id);
+ for( r=0; r<8 ; r++) {
+ TGA_WRITE_REG((vm >> r) & 1, TGA_CLOCK_REG);
+ }
+ for( r=0; r<8 ; r++) {
+ TGA_WRITE_REG((va >> r) & 1, TGA_CLOCK_REG);
+ }
+ for( r=0; r<7 ; r++) {
+ TGA_WRITE_REG((vr >> r) & 1, TGA_CLOCK_REG);
+ }
+ TGA_WRITE_REG(((vr >> 7) & 1)|2, TGA_CLOCK_REG);
}
-static int tgafbcon_switch(int con, struct fb_info *info)
+static int tgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+ u_int *transp, struct fb_info *info)
{
- /* Do we have to save the colormap? */
- if (fb_display[currcon].cmap.len)
- fb_get_cmap(&fb_display[currcon].cmap, 1, tgafb_getcolreg, info);
+ if (regno > 255)
+ return 1;
+ *red = (palette[regno].red<<8) | palette[regno].red;
+ *green = (palette[regno].green<<8) | palette[regno].green;
+ *blue = (palette[regno].blue<<8) | palette[regno].blue;
+ *transp = 0;
+ return 0;
+}
+
+
+static int tgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info)
+{
+ if (regno > 255)
+ return 1;
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ palette[regno].red = red;
+ palette[regno].green = green;
+ palette[regno].blue = blue;
+
+#ifdef FBCON_HAS_CFB32
+ if (regno < 16 && fb_info.tga_type != 0)
+ fbcon_cfb32_cmap[regno] = (red << 16) | (green << 8) | blue;
+#endif
+
+ if (fb_info.tga_type == 0) { /* 8-plane */
+ BT485_WRITE(regno, BT485_ADDR_PAL_WRITE);
+ TGA_WRITE_REG(BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
+ TGA_WRITE_REG(red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+ TGA_WRITE_REG(green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+ TGA_WRITE_REG(blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+ }
+ /* How to set a single color register on 24-plane cards?? */
- currcon = con;
- /* Install new colormap */
- do_install_cmap(con, info);
return 0;
}
+#if 1
/*
- * Update the `var' structure (called by fbcon.c)
+ * FIXME: since I don't know how to set a single arbitrary color register
+ * on 24-plane cards, all color palette registers have to be updated
*/
-static int tgafbcon_updatevar(int con, struct fb_info *info)
+static int tgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
{
- /* Nothing */
+ int err;
+
+ if (!fb_display[con].cmap.len) { /* no colormap allocated? */
+ if ((err = fb_alloc_cmap(&fb_display[con].cmap, 256, 0)))
+ return err;
+ }
+ if (con == currcon) { /* current console? */
+ err = fb_set_cmap(cmap, kspc, tgafb_setcolreg, info);
+#if 1
+ if (fb_info.tga_type != 0)
+ tgafb_update_palette();
+#endif
+ return err;
+ } else
+ fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
return 0;
}
- /*
- * Blank and unblank the display.
- */
+static void tgafb_update_palette(void)
+{
+ int i;
+
+ BT463_LOAD_ADDR(0x0000);
+ TGA_WRITE_REG((BT463_PALETTE<<2), TGA_RAMDAC_REG);
+
+ for (i = 0; i < 256; i++) {
+ TGA_WRITE_REG(palette[i].red|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
+ TGA_WRITE_REG(palette[i].green|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
+ TGA_WRITE_REG(palette[i].blue|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
+ }
+}
+#endif
+
+
+static int tgafb_pan_display(const struct fb_var_screeninfo *var,
+ struct fb_info_gen *info)
+{
+ if (var->xoffset || var->yoffset)
+ return -EINVAL;
+ else
+ return 0;
+}
-static void tgafbcon_blank(int blank, struct fb_info *info)
+
+static int tgafb_blank(int blank, struct fb_info_gen *info)
{
static int tga_vesa_blanked = 0;
u32 vhcr, vvcr;
@@ -854,158 +927,187 @@
}
restore_flags(flags);
-}
-
- /*
- * Read a single color register and split it into
- * colors/transparent. Return != 0 for invalid regno.
- */
-
-static int tgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
- u_int *transp, struct fb_info *info)
-{
- if (regno > 255)
- return 1;
- *red = (palette[regno].red<<8) | palette[regno].red;
- *green = (palette[regno].green<<8) | palette[regno].green;
- *blue = (palette[regno].blue<<8) | palette[regno].blue;
- *transp = 0;
return 0;
}
- /*
- * Set a single color register. The values supplied are already
- * rounded down to the hardware's capabilities (according to the
- * entries in the var structure). Return != 0 for invalid regno.
- */
-
-static int tgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
- u_int transp, struct fb_info *info)
+static void tgafb_set_disp(const void *fb_par, struct display *disp,
+ struct fb_info_gen *info)
{
- if (regno > 255)
- return 1;
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- palette[regno].red = red;
- palette[regno].green = green;
- palette[regno].blue = blue;
-
+ disp->screen_base = (char *)fb_info.tga_fb_base + dense_mem(fb_info.tga_fb_base);
+ switch (fb_info.tga_type) {
+#ifdef FBCON_HAS_CFB8
+ case 0: /* 8-plane */
+ disp->dispsw = &fbcon_cfb8;
+ break;
+#endif
#ifdef FBCON_HAS_CFB32
- if (regno < 16 && tga_type != 0)
- fbcon_cfb32_cmap[regno] = (red << 16) | (green << 8) | blue;
+ case 1: /* 24-plane */
+ case 3: /* 24plusZ */
+ disp->dispsw = &fbcon_cfb32;
+ disp->dispsw_data = &fbcon_cfb32_cmap;
+ break;
#endif
+ default:
+ disp->dispsw = &fbcon_dummy;
+ }
- if (tga_type == 0) { /* 8-plane */
- BT485_WRITE(regno, BT485_ADDR_PAL_WRITE);
- TGA_WRITE_REG(BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
- TGA_WRITE_REG(red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
- TGA_WRITE_REG(green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
- TGA_WRITE_REG(blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
- }
- /* How to set a single color register on 24-plane cards?? */
-
- return 0;
+ disp->scrollmode = SCROLL_YREDRAW;
}
-#if 1
+struct fbgen_hwswitch tgafb_hwswitch = {
+ tgafb_detect, tgafb_encode_fix, tgafb_decode_var, tgafb_encode_var, tgafb_get_par,
+ tgafb_set_par, tgafb_getcolreg, tgafb_setcolreg, tgafb_pan_display, tgafb_blank,
+ tgafb_set_disp
+};
+
+
/*
- * FIXME: since I don't know how to set a single arbitrary color register
- * on 24-plane cards, all color palette registers have to be updated
+ * Hardware Independent functions
*/
-static void tga_update_palette(void)
-{
- int i;
- BT463_LOAD_ADDR(0x0000);
- TGA_WRITE_REG((BT463_PALETTE<<2), TGA_RAMDAC_REG);
+ /*
+ * Frame buffer operations
+ */
- for (i = 0; i < 256; i++) {
- TGA_WRITE_REG(palette[i].red|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
- TGA_WRITE_REG(palette[i].green|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
- TGA_WRITE_REG(palette[i].blue|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
- }
+static int tgafb_open(struct fb_info *info, int user)
+{
+ MOD_INC_USE_COUNT;
+ return(0);
}
-#endif
+
-static void do_install_cmap(int con, struct fb_info *info)
+static int tgafb_release(struct fb_info *info, int user)
{
- if (con != currcon)
- return;
- if (fb_display[con].cmap.len)
- fb_set_cmap(&fb_display[con].cmap, 1, tgafb_setcolreg, info);
- else
- fb_set_cmap(fb_default_cmap(256), 1, tgafb_setcolreg, info);
-#if 1
- if (tga_type != 0)
- tga_update_palette();
-#endif
+ MOD_DEC_USE_COUNT;
+ return(0);
}
-#if 0 /* No cursor stuff yet */
-/*
- * Hide the cursor from view, during blanking, usually...
- */
-void
-hide_cursor(void)
-{
- unsigned long flags;
- save_flags(flags); cli();
+static struct fb_ops tgafb_ops = {
+ tgafb_open, tgafb_release, fbgen_get_fix, fbgen_get_var, fbgen_set_var,
+ fbgen_get_cmap, tgafb_set_cmap, fbgen_pan_display, fbgen_ioctl
+};
- if (tga_type == 0) {
- BT485_WRITE(0x20, BT485_CMD_2);
- } else {
- TGA_WRITE_REG(0x03, TGA_VALID_REG); /* SCANNING and BLANK */
- }
- restore_flags(flags);
+ /*
+ * Setup
+ */
+
+__initfunc(void tgafb_setup(char *options, int *ints)) {
+ char *this_opt;
+ int i;
+
+ if (options && *options)
+ for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) {
+ if (!*this_opt) continue;
+
+ if (!strncmp(this_opt, "font:", 5))
+ strncpy(default_fontname, this_opt+5, sizeof default_fontname);
+ else if (!strncmp(this_opt, "mode:", 5)) {
+ for (i = 0; i < NUM_TOTAL_MODES; i++) {
+ if (!strcmp(this_opt+5, tgafb_predefined[i].name))
+ default_var = tgafb_predefined[i].var;
+ default_var_valid = 1;
+ }
+ } else {
+ printk(KERN_ERR "tgafb: unknown parameter %s\n", this_opt);
+ }
+ }
}
-void
-set_cursor(int currcons)
+
+ /*
+ * Initialisation
+ */
+
+__initfunc(void tgafb_init(void))
{
- unsigned int idx, xt, yt, row, col;
- unsigned long flags;
+ struct pci_dev *pdev;
- if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
- return;
+ pdev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, NULL);
+ if (!pdev)
+ return;
+ fb_info.tga_mem_base = pdev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
+#ifdef DEBUG
+ printk("tgafb_init: mem_base 0x%x\n", fb_info.tga_mem_base);
+#endif /* DEBUG */
+
+ fb_info.tga_type = (readl((unsigned long)fb_info.tga_mem_base) >> 12) & 0x0f;
+ fb_info.tga_regs_base = ((unsigned long)fb_info.tga_mem_base + TGA_REGS_OFFSET);
+ fb_info.tga_fb_base = ((unsigned long)fb_info.tga_mem_base + fb_offset_presets[fb_info.tga_type]);
+
+ /* XXX Why the fuck is it called modename if it identifies the board? */
+ strcpy (fb_info.gen.info.modename,"DEC 21030 TGA ");
+ switch (fb_info.tga_type)
+ {
+ case 0: /* 8-plane */
+ strcat (fb_info.gen.info.modename, "8-plane");
+ break;
- save_flags(flags); cli();
+ case 1:
+ strcat (fb_info.gen.info.modename, "24-plane");
+ break;
- if (deccm) {
- idx = (pos - video_mem_base) >> 1;
- col = idx % 80;
- row = (idx - col) / 80;
+ case 3:
+ strcat (fb_info.gen.info.modename, "24plusZ");
+ break;
+ }
- if (tga_type == 0) { /* 8-plane */
+ fb_info.gen.info.node = -1;
+ fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
+ fb_info.gen.info.fbops = &tgafb_ops;
+ fb_info.gen.info.disp = &disp;
+ fb_info.gen.info.changevar = NULL;
+ fb_info.gen.info.switch_con = &fbgen_switch;
+ fb_info.gen.info.updatevar = &fbgen_update_var;
+ fb_info.gen.info.blank = &fbgen_blank;
+ strcpy(fb_info.gen.info.fontname, default_fontname);
+ fb_info.gen.parsize = sizeof (struct tgafb_par);
+ fb_info.gen.fbhw = &tgafb_hwswitch;
+ fb_info.gen.fbhw->detect();
+
+ /* This should give a reasonable default video mode */
+ if (!default_var_valid)
+ default_var = tgafb_predefined[0].var;
+ fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
+ disp.var.activate = FB_ACTIVATE_NOW;
+ fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
+ fbgen_set_disp(-1, &fb_info.gen);
+ fbgen_install_cmap(0, &fb_info.gen);
+ if (register_framebuffer(&fb_info.gen.info) < 0)
+ return;
+ printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node),
+ fb_info.gen.info.modename);
+}
- xt = col * TGA_F_WIDTH + 64;
- yt = row * TGA_F_HEIGHT_PADDED + 64;
- /* make sure it's enabled */
- BT485_WRITE(0x22, BT485_CMD_2); /* WIN cursor type */
+ /*
+ * Cleanup
+ */
- BT485_WRITE(xt, BT485_CUR_LOW_X);
- BT485_WRITE((xt >> 8), BT485_CUR_HIGH_X);
- BT485_WRITE(yt, BT485_CUR_LOW_Y);
- BT485_WRITE((yt >> 8), BT485_CUR_HIGH_Y);
+void tgafb_cleanup(struct fb_info *info)
+{
+ unregister_framebuffer(info);
+}
- } else {
- xt = col * TGA_F_WIDTH + 144;
- yt = row * TGA_F_HEIGHT_PADDED + 35;
+ /*
+ * Modularisation
+ */
- TGA_WRITE_REG(0x05, TGA_VALID_REG); /* SCANNING and CURSOR */
- TGA_WRITE_REG(xt | (yt << 12), TGA_CURSOR_XY_REG);
- }
+#ifdef MODULE
+int init_module(void)
+{
+ tgafb_init();
+ return 0;
+}
- } else
- hide_cursor();
- restore_flags(flags);
+void cleanup_module(void)
+{
+ tgafb_cleanup(void);
}
+#endif /* MODULE */
-#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)