aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/i810
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/video/i810
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/video/i810')
-rw-r--r--drivers/video/i810/Makefile14
-rw-r--r--drivers/video/i810/i810.h285
-rw-r--r--drivers/video/i810/i810_accel.c449
-rw-r--r--drivers/video/i810/i810_dvt.c307
-rw-r--r--drivers/video/i810/i810_gtf.c275
-rw-r--r--drivers/video/i810/i810_main.c2062
-rw-r--r--drivers/video/i810/i810_main.h127
-rw-r--r--drivers/video/i810/i810_regs.h274
8 files changed, 3793 insertions, 0 deletions
diff --git a/drivers/video/i810/Makefile b/drivers/video/i810/Makefile
new file mode 100644
index 000000000000..794ae76c7c4b
--- /dev/null
+++ b/drivers/video/i810/Makefile
@@ -0,0 +1,14 @@
1#
2# Makefile for the Intel 810/815 framebuffer driver
3#
4
5obj-$(CONFIG_FB_I810) += i810fb.o
6
7
8i810fb-objs := i810_main.o i810_accel.o
9
10ifdef CONFIG_FB_I810_GTF
11i810fb-objs += i810_gtf.o
12else
13i810fb-objs += i810_dvt.o
14endif
diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h
new file mode 100644
index 000000000000..fe3b75794756
--- /dev/null
+++ b/drivers/video/i810/i810.h
@@ -0,0 +1,285 @@
1/*-*- linux-c -*-
2 * linux/drivers/video/i810.h -- Intel 810 General Definitions/Declarations
3 *
4 * Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
5 * All Rights Reserved
6 *
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file COPYING in the main directory of this archive for
10 * more details.
11 */
12
13#ifndef __I810_H__
14#define __I810_H__
15
16#include <linux/list.h>
17#include <linux/agp_backend.h>
18#include <linux/fb.h>
19#include <video/vga.h>
20
21/* Fence */
22#define TILEWALK_X (0 << 12)
23#define TILEWALK_Y (1 << 12)
24
25/* Raster ops */
26#define COLOR_COPY_ROP 0xF0
27#define PAT_COPY_ROP 0xCC
28#define CLEAR_ROP 0x00
29#define WHITE_ROP 0xFF
30#define INVERT_ROP 0x55
31#define XOR_ROP 0x5A
32
33/* 2D Engine definitions */
34#define SOLIDPATTERN 0x80000000
35#define NONSOLID 0x00000000
36#define BPP8 (0 << 24)
37#define BPP16 (1 << 24)
38#define BPP24 (2 << 24)
39
40#define PIXCONF8 (2 << 16)
41#define PIXCONF15 (4 << 16)
42#define PIXCONF16 (5 << 16)
43#define PIXCONF24 (6 << 16)
44#define PIXCONF32 (7 << 16)
45
46#define DYN_COLOR_EN (1 << 26)
47#define DYN_COLOR_DIS (0 << 26)
48#define INCREMENT 0x00000000
49#define DECREMENT (0x01 << 30)
50#define ARB_ON 0x00000001
51#define ARB_OFF 0x00000000
52#define SYNC_FLIP 0x00000000
53#define ASYNC_FLIP 0x00000040
54#define OPTYPE_MASK 0xE0000000
55#define PARSER_MASK 0x001F8000
56#define D2_MASK 0x001FC000 /* 2D mask */
57
58/* Instruction type */
59/* There are more but pertains to 3D */
60#define PARSER 0x00000000
61#define BLIT (0x02 << 29)
62#define RENDER (0x03 << 29)
63
64/* Parser */
65#define NOP 0x00 /* No operation, padding */
66#define BP_INT (0x01 << 23) /* Breakpoint interrupt */
67#define USR_INT (0x02 << 23) /* User interrupt */
68#define WAIT_FOR_EVNT (0x03 << 23) /* Wait for event */
69#define FLUSH (0x04 << 23)
70#define CONTEXT_SEL (0x05 << 23)
71#define REPORT_HEAD (0x07 << 23)
72#define ARB_ON_OFF (0x08 << 23)
73#define OVERLAY_FLIP (0x11 << 23)
74#define LOAD_SCAN_INC (0x12 << 23)
75#define LOAD_SCAN_EX (0x13 << 23)
76#define FRONT_BUFFER (0x14 << 23)
77#define DEST_BUFFER (0x15 << 23)
78#define Z_BUFFER (0x16 << 23)
79
80#define STORE_DWORD_IMM (0x20 << 23)
81#define STORE_DWORD_IDX (0x21 << 23)
82#define BATCH_BUFFER (0x30 << 23)
83
84/* Blit */
85#define SETUP_BLIT 0x00
86#define SETUP_MONO_PATTERN_SL_BLT (0x10 << 22)
87#define PIXEL_BLT (0x20 << 22)
88#define SCANLINE_BLT (0x21 << 22)
89#define TEXT_BLT (0x22 << 22)
90#define TEXT_IMM_BLT (0x30 << 22)
91#define COLOR_BLT (0x40 << 22)
92#define MONO_PAT_BLIT (0x42 << 22)
93#define SOURCE_COPY_BLIT (0x43 << 22)
94#define MONO_SOURCE_COPY_BLIT (0x44 << 22)
95#define SOURCE_COPY_IMMEDIATE (0x60 << 22)
96#define MONO_SOURCE_COPY_IMMEDIATE (0x61 << 22)
97
98#define VERSION_MAJOR 0
99#define VERSION_MINOR 9
100#define VERSION_TEENIE 0
101#define BRANCH_VERSION ""
102
103
104/* mvo: intel i815 */
105#ifndef PCI_DEVICE_ID_INTEL_82815_100
106 #define PCI_DEVICE_ID_INTEL_82815_100 0x1102
107#endif
108#ifndef PCI_DEVICE_ID_INTEL_82815_NOAGP
109 #define PCI_DEVICE_ID_INTEL_82815_NOAGP 0x1112
110#endif
111#ifndef PCI_DEVICE_ID_INTEL_82815_FULL_CTRL
112 #define PCI_DEVICE_ID_INTEL_82815_FULL_CTRL 0x1130
113#endif
114
115/* General Defines */
116#define I810_PAGESIZE 4096
117#define MAX_DMA_SIZE (1024 * 4096)
118#define SAREA_SIZE 4096
119#define PCI_I810_MISCC 0x72
120#define MMIO_SIZE (512*1024)
121#define GTT_SIZE (16*1024)
122#define RINGBUFFER_SIZE (64*1024)
123#define CURSOR_SIZE 4096
124#define OFF 0
125#define ON 1
126#define MAX_KEY 256
127#define WAIT_COUNT 10000000
128#define IRING_PAD 8
129#define FONTDATAMAX 8192
130/* Masks (AND ops) and OR's */
131#define FB_START_MASK (0x3f << (32 - 6))
132#define MMIO_ADDR_MASK (0x1FFF << (32 - 13))
133#define FREQ_MASK 0x1EF
134#define SCR_OFF 0x20
135#define DRAM_ON 0x08
136#define DRAM_OFF 0xE7
137#define PG_ENABLE_MASK 0x01
138#define RING_SIZE_MASK (RINGBUFFER_SIZE - 1);
139
140/* defines for restoring registers partially */
141#define ADDR_MAP_MASK (0x07 << 5)
142#define DISP_CTRL ~0
143#define PIXCONF_0 (0x64 << 8)
144#define PIXCONF_2 (0xF3 << 24)
145#define PIXCONF_1 (0xF0 << 16)
146#define MN_MASK 0x3FF03FF
147#define P_OR (0x7 << 4)
148#define DAC_BIT (1 << 16)
149#define INTERLACE_BIT (1 << 7)
150#define IER_MASK (3 << 13)
151#define IMR_MASK (3 << 13)
152
153/* Power Management */
154#define DPMS_MASK 0xF0000
155#define POWERON 0x00000
156#define STANDBY 0x20000
157#define SUSPEND 0x80000
158#define POWERDOWN 0xA0000
159#define EMR_MASK ~0x3F
160#define FW_BLC_MASK ~(0x3F|(7 << 8)|(0x3F << 12)|(7 << 20))
161
162/* Ringbuffer */
163#define RBUFFER_START_MASK 0xFFFFF000
164#define RBUFFER_SIZE_MASK 0x001FF000
165#define RBUFFER_HEAD_MASK 0x001FFFFC
166#define RBUFFER_TAIL_MASK 0x001FFFF8
167
168/* Video Timings */
169#define REF_FREQ 24000000
170#define TARGET_N_MAX 30
171
172#define MAX_PIXELCLOCK 230000000
173#define MIN_PIXELCLOCK 15000000
174#define VFMAX 60
175#define VFMIN 60
176#define HFMAX 30000
177#define HFMIN 29000
178
179/* Cursor */
180#define CURSOR_ENABLE_MASK 0x1000
181#define CURSOR_MODE_64_TRANS 4
182#define CURSOR_MODE_64_XOR 5
183#define CURSOR_MODE_64_3C 6
184#define COORD_INACTIVE 0
185#define COORD_ACTIVE (1 << 4)
186#define EXTENDED_PALETTE 1
187
188/* AGP Memory Types*/
189#define AGP_NORMAL_MEMORY 0
190#define AGP_DCACHE_MEMORY 1
191#define AGP_PHYSICAL_MEMORY 2
192
193/* Allocated resource Flags */
194#define FRAMEBUFFER_REQ 1
195#define MMIO_REQ 2
196#define PCI_DEVICE_ENABLED 4
197#define HAS_FONTCACHE 8
198
199/* driver flags */
200#define HAS_MTRR 1
201#define HAS_ACCELERATION 2
202#define ALWAYS_SYNC 4
203#define LOCKUP 8
204#define USE_HWCUR 16
205
206struct gtt_data {
207 struct agp_memory *i810_fb_memory;
208 struct agp_memory *i810_cursor_memory;
209};
210
211struct mode_registers {
212 u32 pixclock, M, N, P;
213 u8 cr00, cr01, cr02, cr03;
214 u8 cr04, cr05, cr06, cr07;
215 u8 cr09, cr10, cr11, cr12;
216 u8 cr13, cr15, cr16, cr30;
217 u8 cr31, cr32, cr33, cr35, cr39;
218 u32 bpp8_100, bpp16_100;
219 u32 bpp24_100, bpp8_133;
220 u32 bpp16_133, bpp24_133;
221 u8 msr;
222};
223
224struct heap_data {
225 unsigned long physical;
226 __u8 __iomem *virtual;
227 u32 offset;
228 u32 size;
229};
230
231struct state_registers {
232 u32 dclk_1d, dclk_2d, dclk_0ds;
233 u32 pixconf, fw_blc, pgtbl_ctl;
234 u32 fence0, hws_pga, dplystas;
235 u16 bltcntl, hwstam, ier, iir, imr;
236 u8 cr00, cr01, cr02, cr03, cr04;
237 u8 cr05, cr06, cr07, cr08, cr09;
238 u8 cr10, cr11, cr12, cr13, cr14;
239 u8 cr15, cr16, cr17, cr80, gr10;
240 u8 cr30, cr31, cr32, cr33, cr35;
241 u8 cr39, cr41, cr70, sr01, msr;
242};
243
244struct i810fb_par {
245 struct mode_registers regs;
246 struct state_registers hw_state;
247 struct gtt_data i810_gtt;
248 struct fb_ops i810fb_ops;
249 struct pci_dev *dev;
250 struct heap_data aperture;
251 struct heap_data fb;
252 struct heap_data iring;
253 struct heap_data cursor_heap;
254 struct vgastate state;
255 atomic_t use_count;
256 u32 pseudo_palette[17];
257 unsigned long mmio_start_phys;
258 u8 __iomem *mmio_start_virtual;
259 u32 pitch;
260 u32 pixconf;
261 u32 watermark;
262 u32 mem_freq;
263 u32 res_flags;
264 u32 dev_flags;
265 u32 cur_tail;
266 u32 depth;
267 u32 blit_bpp;
268 u32 ovract;
269 u32 cur_state;
270 int mtrr_reg;
271 u16 bltcntl;
272 u8 interlace;
273};
274
275/*
276 * Register I/O
277 */
278#define i810_readb(where, mmio) readb(mmio + where)
279#define i810_readw(where, mmio) readw(mmio + where)
280#define i810_readl(where, mmio) readl(mmio + where)
281#define i810_writeb(where, mmio, val) writeb(val, mmio + where)
282#define i810_writew(where, mmio, val) writew(val, mmio + where)
283#define i810_writel(where, mmio, val) writel(val, mmio + where)
284
285#endif /* __I810_H__ */
diff --git a/drivers/video/i810/i810_accel.c b/drivers/video/i810/i810_accel.c
new file mode 100644
index 000000000000..64cd1c827cf0
--- /dev/null
+++ b/drivers/video/i810/i810_accel.c
@@ -0,0 +1,449 @@
1/*-*- linux-c -*-
2 * linux/drivers/video/i810_accel.c -- Hardware Acceleration
3 *
4 * Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
5 * All Rights Reserved
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file COPYING in the main directory of this archive for
9 * more details.
10 */
11#include <linux/kernel.h>
12#include <linux/string.h>
13#include <linux/fb.h>
14
15#include "i810_regs.h"
16#include "i810.h"
17
18static u32 i810fb_rop[] = {
19 COLOR_COPY_ROP, /* ROP_COPY */
20 XOR_ROP /* ROP_XOR */
21};
22
23/* Macros */
24#define PUT_RING(n) { \
25 i810_writel(par->cur_tail, par->iring.virtual, n); \
26 par->cur_tail += 4; \
27 par->cur_tail &= RING_SIZE_MASK; \
28}
29
30extern void flush_cache(void);
31
32/************************************************************/
33
34/* BLT Engine Routines */
35static inline void i810_report_error(u8 __iomem *mmio)
36{
37 printk("IIR : 0x%04x\n"
38 "EIR : 0x%04x\n"
39 "PGTBL_ER: 0x%04x\n"
40 "IPEIR : 0x%04x\n"
41 "IPEHR : 0x%04x\n",
42 i810_readw(IIR, mmio),
43 i810_readb(EIR, mmio),
44 i810_readl(PGTBL_ER, mmio),
45 i810_readl(IPEIR, mmio),
46 i810_readl(IPEHR, mmio));
47}
48
49/**
50 * wait_for_space - check ring buffer free space
51 * @space: amount of ringbuffer space needed in bytes
52 * @par: pointer to i810fb_par structure
53 *
54 * DESCRIPTION:
55 * The function waits until a free space from the ringbuffer
56 * is available
57 */
58static inline int wait_for_space(struct fb_info *info, u32 space)
59{
60 struct i810fb_par *par = (struct i810fb_par *) info->par;
61 u32 head, count = WAIT_COUNT, tail;
62 u8 __iomem *mmio = par->mmio_start_virtual;
63
64 tail = par->cur_tail;
65 while (count--) {
66 head = i810_readl(IRING + 4, mmio) & RBUFFER_HEAD_MASK;
67 if ((tail == head) ||
68 (tail > head &&
69 (par->iring.size - tail + head) >= space) ||
70 (tail < head && (head - tail) >= space)) {
71 return 0;
72 }
73 }
74 printk("ringbuffer lockup!!!\n");
75 i810_report_error(mmio);
76 par->dev_flags |= LOCKUP;
77 info->pixmap.scan_align = 1;
78 return 1;
79}
80
81/**
82 * wait_for_engine_idle - waits for all hardware engines to finish
83 * @par: pointer to i810fb_par structure
84 *
85 * DESCRIPTION:
86 * This waits for lring(0), iring(1), and batch(3), etc to finish and
87 * waits until ringbuffer is empty.
88 */
89static inline int wait_for_engine_idle(struct fb_info *info)
90{
91 struct i810fb_par *par = (struct i810fb_par *) info->par;
92 u8 __iomem *mmio = par->mmio_start_virtual;
93 int count = WAIT_COUNT;
94
95 if (wait_for_space(info, par->iring.size)) /* flush */
96 return 1;
97
98 while((i810_readw(INSTDONE, mmio) & 0x7B) != 0x7B && --count);
99 if (count) return 0;
100
101 printk("accel engine lockup!!!\n");
102 printk("INSTDONE: 0x%04x\n", i810_readl(INSTDONE, mmio));
103 i810_report_error(mmio);
104 par->dev_flags |= LOCKUP;
105 info->pixmap.scan_align = 1;
106 return 1;
107}
108
109/* begin_iring - prepares the ringbuffer
110 * @space: length of sequence in dwords
111 * @par: pointer to i810fb_par structure
112 *
113 * DESCRIPTION:
114 * Checks/waits for sufficent space in ringbuffer of size
115 * space. Returns the tail of the buffer
116 */
117static inline u32 begin_iring(struct fb_info *info, u32 space)
118{
119 struct i810fb_par *par = (struct i810fb_par *) info->par;
120
121 if (par->dev_flags & ALWAYS_SYNC)
122 wait_for_engine_idle(info);
123 return wait_for_space(info, space);
124}
125
126/**
127 * end_iring - advances the buffer
128 * @par: pointer to i810fb_par structure
129 *
130 * DESCRIPTION:
131 * This advances the tail of the ringbuffer, effectively
132 * beginning the execution of the graphics instruction sequence.
133 */
134static inline void end_iring(struct i810fb_par *par)
135{
136 u8 __iomem *mmio = par->mmio_start_virtual;
137
138 i810_writel(IRING, mmio, par->cur_tail);
139}
140
141/**
142 * source_copy_blit - BLIT transfer operation
143 * @dwidth: width of rectangular graphics data
144 * @dheight: height of rectangular graphics data
145 * @dpitch: bytes per line of destination buffer
146 * @xdir: direction of copy (left to right or right to left)
147 * @src: address of first pixel to read from
148 * @dest: address of first pixel to write to
149 * @from: source address
150 * @where: destination address
151 * @rop: raster operation
152 * @blit_bpp: pixel format which can be different from the
153 * framebuffer's pixelformat
154 * @par: pointer to i810fb_par structure
155 *
156 * DESCRIPTION:
157 * This is a BLIT operation typically used when doing
158 * a 'Copy and Paste'
159 */
160static inline void source_copy_blit(int dwidth, int dheight, int dpitch,
161 int xdir, int src, int dest, int rop,
162 int blit_bpp, struct fb_info *info)
163{
164 struct i810fb_par *par = (struct i810fb_par *) info->par;
165
166 if (begin_iring(info, 24 + IRING_PAD)) return;
167
168 PUT_RING(BLIT | SOURCE_COPY_BLIT | 4);
169 PUT_RING(xdir | rop << 16 | dpitch | DYN_COLOR_EN | blit_bpp);
170 PUT_RING(dheight << 16 | dwidth);
171 PUT_RING(dest);
172 PUT_RING(dpitch);
173 PUT_RING(src);
174
175 end_iring(par);
176}
177
178/**
179 * color_blit - solid color BLIT operation
180 * @width: width of destination
181 * @height: height of destination
182 * @pitch: pixels per line of the buffer
183 * @dest: address of first pixel to write to
184 * @where: destination
185 * @rop: raster operation
186 * @what: color to transfer
187 * @blit_bpp: pixel format which can be different from the
188 * framebuffer's pixelformat
189 * @par: pointer to i810fb_par structure
190 *
191 * DESCRIPTION:
192 * A BLIT operation which can be used for color fill/rectangular fill
193 */
194static inline void color_blit(int width, int height, int pitch, int dest,
195 int rop, int what, int blit_bpp,
196 struct fb_info *info)
197{
198 struct i810fb_par *par = (struct i810fb_par *) info->par;
199
200 if (begin_iring(info, 24 + IRING_PAD)) return;
201
202 PUT_RING(BLIT | COLOR_BLT | 3);
203 PUT_RING(rop << 16 | pitch | SOLIDPATTERN | DYN_COLOR_EN | blit_bpp);
204 PUT_RING(height << 16 | width);
205 PUT_RING(dest);
206 PUT_RING(what);
207 PUT_RING(NOP);
208
209 end_iring(par);
210}
211
212/**
213 * mono_src_copy_imm_blit - color expand from system memory to framebuffer
214 * @dwidth: width of destination
215 * @dheight: height of destination
216 * @dpitch: pixels per line of the buffer
217 * @dsize: size of bitmap in double words
218 * @dest: address of first byte of pixel;
219 * @rop: raster operation
220 * @blit_bpp: pixelformat to use which can be different from the
221 * framebuffer's pixelformat
222 * @src: address of image data
223 * @bg: backgound color
224 * @fg: forground color
225 * @par: pointer to i810fb_par structure
226 *
227 * DESCRIPTION:
228 * A color expand operation where the source data is placed in the
229 * ringbuffer itself. Useful for drawing text.
230 *
231 * REQUIREMENT:
232 * The end of a scanline must be padded to the next word.
233 */
234static inline void mono_src_copy_imm_blit(int dwidth, int dheight, int dpitch,
235 int dsize, int blit_bpp, int rop,
236 int dest, const u32 *src, int bg,
237 int fg, struct fb_info *info)
238{
239 struct i810fb_par *par = (struct i810fb_par *) info->par;
240
241 if (begin_iring(info, 24 + (dsize << 2) + IRING_PAD)) return;
242
243 PUT_RING(BLIT | MONO_SOURCE_COPY_IMMEDIATE | (4 + dsize));
244 PUT_RING(DYN_COLOR_EN | blit_bpp | rop << 16 | dpitch);
245 PUT_RING(dheight << 16 | dwidth);
246 PUT_RING(dest);
247 PUT_RING(bg);
248 PUT_RING(fg);
249 while (dsize--)
250 PUT_RING(*src++);
251
252 end_iring(par);
253}
254
255static inline void load_front(int offset, struct fb_info *info)
256{
257 struct i810fb_par *par = (struct i810fb_par *) info->par;
258
259 if (begin_iring(info, 8 + IRING_PAD)) return;
260
261 PUT_RING(PARSER | FLUSH);
262 PUT_RING(NOP);
263
264 end_iring(par);
265
266 if (begin_iring(info, 8 + IRING_PAD)) return;
267
268 PUT_RING(PARSER | FRONT_BUFFER | ((par->pitch >> 3) << 8));
269 PUT_RING((par->fb.offset << 12) + offset);
270
271 end_iring(par);
272}
273
274/**
275 * i810fb_iring_enable - enables/disables the ringbuffer
276 * @mode: enable or disable
277 * @par: pointer to i810fb_par structure
278 *
279 * DESCRIPTION:
280 * Enables or disables the ringbuffer, effectively enabling or
281 * disabling the instruction/acceleration engine.
282 */
283static inline void i810fb_iring_enable(struct i810fb_par *par, u32 mode)
284{
285 u32 tmp;
286 u8 __iomem *mmio = par->mmio_start_virtual;
287
288 tmp = i810_readl(IRING + 12, mmio);
289 if (mode == OFF)
290 tmp &= ~1;
291 else
292 tmp |= 1;
293 flush_cache();
294 i810_writel(IRING + 12, mmio, tmp);
295}
296
297void i810fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
298{
299 struct i810fb_par *par = (struct i810fb_par *) info->par;
300 u32 dx, dy, width, height, dest, rop = 0, color = 0;
301
302 if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
303 par->depth == 4)
304 return cfb_fillrect(info, rect);
305
306 if (par->depth == 1)
307 color = rect->color;
308 else
309 color = ((u32 *) (info->pseudo_palette))[rect->color];
310
311 rop = i810fb_rop[rect->rop];
312
313 dx = rect->dx * par->depth;
314 width = rect->width * par->depth;
315 dy = rect->dy;
316 height = rect->height;
317
318 dest = info->fix.smem_start + (dy * info->fix.line_length) + dx;
319 color_blit(width, height, info->fix.line_length, dest, rop, color,
320 par->blit_bpp, info);
321}
322
323void i810fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
324{
325 struct i810fb_par *par = (struct i810fb_par *) info->par;
326 u32 sx, sy, dx, dy, pitch, width, height, src, dest, xdir;
327
328 if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
329 par->depth == 4)
330 return cfb_copyarea(info, region);
331
332 dx = region->dx * par->depth;
333 sx = region->sx * par->depth;
334 width = region->width * par->depth;
335 sy = region->sy;
336 dy = region->dy;
337 height = region->height;
338
339 if (dx <= sx) {
340 xdir = INCREMENT;
341 }
342 else {
343 xdir = DECREMENT;
344 sx += width - 1;
345 dx += width - 1;
346 }
347 if (dy <= sy) {
348 pitch = info->fix.line_length;
349 }
350 else {
351 pitch = (-(info->fix.line_length)) & 0xFFFF;
352 sy += height - 1;
353 dy += height - 1;
354 }
355 src = info->fix.smem_start + (sy * info->fix.line_length) + sx;
356 dest = info->fix.smem_start + (dy * info->fix.line_length) + dx;
357
358 source_copy_blit(width, height, pitch, xdir, src, dest,
359 PAT_COPY_ROP, par->blit_bpp, info);
360}
361
362void i810fb_imageblit(struct fb_info *info, const struct fb_image *image)
363{
364 struct i810fb_par *par = (struct i810fb_par *) info->par;
365 u32 fg = 0, bg = 0, size, dst;
366
367 if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
368 par->depth == 4 || image->depth != 1)
369 return cfb_imageblit(info, image);
370
371 switch (info->var.bits_per_pixel) {
372 case 8:
373 fg = image->fg_color;
374 bg = image->bg_color;
375 break;
376 case 16:
377 case 24:
378 fg = ((u32 *)(info->pseudo_palette))[image->fg_color];
379 bg = ((u32 *)(info->pseudo_palette))[image->bg_color];
380 break;
381 }
382
383 dst = info->fix.smem_start + (image->dy * info->fix.line_length) +
384 (image->dx * par->depth);
385
386 size = (image->width+7)/8 + 1;
387 size &= ~1;
388 size *= image->height;
389 size += 7;
390 size &= ~7;
391 mono_src_copy_imm_blit(image->width * par->depth,
392 image->height, info->fix.line_length,
393 size/4, par->blit_bpp,
394 PAT_COPY_ROP, dst, (u32 *) image->data,
395 bg, fg, info);
396}
397
398int i810fb_sync(struct fb_info *info)
399{
400 struct i810fb_par *par = (struct i810fb_par *) info->par;
401
402 if (!info->var.accel_flags || par->dev_flags & LOCKUP)
403 return 0;
404
405 return wait_for_engine_idle(info);
406}
407
408void i810fb_load_front(u32 offset, struct fb_info *info)
409{
410 struct i810fb_par *par = (struct i810fb_par *) info->par;
411 u8 __iomem *mmio = par->mmio_start_virtual;
412
413 if (!info->var.accel_flags || par->dev_flags & LOCKUP)
414 i810_writel(DPLYBASE, mmio, par->fb.physical + offset);
415 else
416 load_front(offset, info);
417}
418
419/**
420 * i810fb_init_ringbuffer - initialize the ringbuffer
421 * @par: pointer to i810fb_par structure
422 *
423 * DESCRIPTION:
424 * Initializes the ringbuffer by telling the device the
425 * size and location of the ringbuffer. It also sets
426 * the head and tail pointers = 0
427 */
428void i810fb_init_ringbuffer(struct fb_info *info)
429{
430 struct i810fb_par *par = (struct i810fb_par *) info->par;
431 u32 tmp1, tmp2;
432 u8 __iomem *mmio = par->mmio_start_virtual;
433
434 wait_for_engine_idle(info);
435 i810fb_iring_enable(par, OFF);
436 i810_writel(IRING, mmio, 0);
437 i810_writel(IRING + 4, mmio, 0);
438 par->cur_tail = 0;
439
440 tmp2 = i810_readl(IRING + 8, mmio) & ~RBUFFER_START_MASK;
441 tmp1 = par->iring.physical;
442 i810_writel(IRING + 8, mmio, tmp2 | tmp1);
443
444 tmp1 = i810_readl(IRING + 12, mmio);
445 tmp1 &= ~RBUFFER_SIZE_MASK;
446 tmp2 = (par->iring.size - I810_PAGESIZE) & RBUFFER_SIZE_MASK;
447 i810_writel(IRING + 12, mmio, tmp1 | tmp2);
448 i810fb_iring_enable(par, ON);
449}
diff --git a/drivers/video/i810/i810_dvt.c b/drivers/video/i810/i810_dvt.c
new file mode 100644
index 000000000000..27fa703a2e0a
--- /dev/null
+++ b/drivers/video/i810/i810_dvt.c
@@ -0,0 +1,307 @@
1/*-*- linux-c -*-
2 * linux/drivers/video/i810_dvt.c -- Intel 810 Discrete Video Timings (Intel)
3 *
4 * Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
5 * All Rights Reserved
6 *
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file COPYING in the main directory of this archive for
10 * more details.
11 */
12
13#include <linux/kernel.h>
14
15#include "i810_regs.h"
16#include "i810.h"
17
18struct mode_registers std_modes[] = {
19 /* 640x480 @ 60Hz */
20 { 25000, 0x0013, 0x0003, 0x40, 0x5F, 0x4F, 0x50, 0x82, 0x51, 0x9D,
21 0x0B, 0x10, 0x40, 0xE9, 0x0B, 0xDF, 0x50, 0xE7, 0x04, 0x02,
22 0x01, 0x01, 0x01, 0x00, 0x01, 0x22002000, 0x22004000, 0x22006000,
23 0x22002000, 0x22004000, 0x22006000, 0xC0 },
24
25 /* 640x480 @ 70Hz */
26 { 28000, 0x0053, 0x0010, 0x40, 0x61, 0x4F, 0x4F, 0x85, 0x52, 0x9A,
27 0xF2, 0x10, 0x40, 0xE0, 0x03, 0xDF, 0x50, 0xDF, 0xF3, 0x01,
28 0x01, 0x01, 0x01, 0x00, 0x01, 0x22002000, 0x22004000, 0x22005000,
29 0x22002000, 0x22004000, 0x22005000, 0xC0 },
30
31 /* 640x480 @ 72Hz */
32 { 31000, 0x0013, 0x0002, 0x40, 0x63, 0x4F, 0x4F, 0x87, 0x52, 0x97,
33 0x06, 0x0F, 0x40, 0xE8, 0x0B, 0xDF, 0x50, 0xDF, 0x07, 0x02,
34 0x01, 0x01, 0x01, 0x00, 0x01, 0x22003000, 0x22005000, 0x22007000,
35 0x22003000, 0x22005000, 0x22007000, 0xC0 },
36
37 /* 640x480 @ 75Hz */
38 { 31000, 0x0013, 0x0002, 0x40, 0x64, 0x4F, 0x4F, 0x88, 0x51, 0x99,
39 0xF2, 0x10, 0x40, 0xE0, 0x03, 0xDF, 0x50, 0xDF, 0xF3, 0x01,
40 0x01, 0x01, 0x01, 0x00, 0x01, 0x22003000, 0x22005000, 0x22007000,
41 0x22003000, 0x22005000, 0x22007000, 0xC0 },
42
43 /* 640x480 @ 85Hz */
44 { 36000, 0x0010, 0x0001, 0x40, 0x63, 0x4F, 0x4F, 0x87, 0x56, 0x9D,
45 0xFB, 0x10, 0x40, 0xE0, 0x03, 0xDF, 0x50, 0xDF, 0xFC, 0x01,
46 0x01, 0x01, 0x01, 0x00, 0x01, 0x22003000, 0x22005000, 0x22107000,
47 0x22003000, 0x22005000, 0x22107000, 0xC0 },
48
49 /* 800x600 @ 56Hz */
50 { 36000, 0x0010, 0x0001, 0x40, 0x7B, 0x63, 0x63, 0x9F, 0x66, 0x8F,
51 0x6F, 0x10, 0x40, 0x58, 0x0A, 0x57, 0xC8, 0x57, 0x70, 0x02,
52 0x02, 0x02, 0x02, 0x00, 0x01, 0x22003000, 0x22005000, 0x22107000,
53 0x22003000, 0x22005000, 0x22107000, 0x00 },
54
55 /* 800x600 @ 60Hz */
56 { 40000, 0x0008, 0x0001, 0x30, 0x7F, 0x63, 0x63, 0x83, 0x68, 0x18,
57 0x72, 0x10, 0x40, 0x58, 0x0C, 0x57, 0xC8, 0x57, 0x73, 0x02,
58 0x02, 0x02, 0x02, 0x00, 0x00, 0x22003000, 0x22006000, 0x22108000,
59 0x22003000, 0x22006000, 0x22108000, 0x00 },
60
61 /* 800x600 @ 70Hz */
62 { 45000, 0x0054, 0x0015, 0x30, 0x7D, 0x63, 0x63, 0x81, 0x68, 0x12,
63 0x6f, 0x10, 0x40, 0x58, 0x0b, 0x57, 0x64, 0x57, 0x70, 0x02,
64 0x02, 0x02, 0x02, 0x00, 0x00, 0x22004000, 0x22007000, 0x2210A000,
65 0x22004000, 0x22007000, 0x2210A000, 0x00 },
66
67 /* 800x600 @ 72Hz */
68 { 50000, 0x0017, 0x0004, 0x30, 0x7D, 0x63, 0x63, 0x81, 0x6A, 0x19,
69 0x98, 0x10, 0x40, 0x7C, 0x02, 0x57, 0xC8, 0x57, 0x99, 0x02,
70 0x02, 0x02, 0x02, 0x00, 0x00, 0x22004000, 0x22007000, 0x2210A000,
71 0x22004000, 0x22007000, 0x2210A000, 0x00 },
72
73 /* 800x600 @ 75Hz */
74 { 49000, 0x001F, 0x0006, 0x30, 0x7F, 0x63, 0x63, 0x83, 0x65, 0x0F,
75 0x6F, 0x10, 0x40, 0x58, 0x0B, 0x57, 0xC8, 0x57, 0x70, 0x02,
76 0x02, 0x02, 0x02, 0x00, 0x00, 0x22004000, 0x22007000, 0x2210B000,
77 0x22004000, 0x22007000, 0x2210B000, 0x00 },
78
79 /* 800x600 @ 85Hz */
80 { 56000, 0x0049, 0x000E, 0x30, 0x7E, 0x63, 0x63, 0x82, 0x67, 0x0F,
81 0x75, 0x10, 0x40, 0x58, 0x0B, 0x57, 0xC8, 0x57, 0x76, 0x02,
82 0x02, 0x02, 0x02, 0x00, 0x00, 0x22004000, 0x22108000, 0x2210b000,
83 0x22004000, 0x22108000, 0x2210b000, 0x00 },
84
85 /* 1024x768 @ 60Hz */
86 { 65000, 0x003F, 0x000A, 0x30, 0xA3, 0x7F, 0x7F, 0x87, 0x83, 0x94,
87 0x24, 0x10, 0x40, 0x02, 0x08, 0xFF, 0x80, 0xFF, 0x25, 0x03,
88 0x02, 0x03, 0x02, 0x00, 0x00, 0x22005000, 0x22109000, 0x2220D000,
89 0x22005000, 0x22109000, 0x2220D000, 0xC0 },
90
91 /* 1024x768 @ 70Hz */
92 { 75000, 0x0017, 0x0002, 0x30, 0xA1, 0x7F, 0x7F, 0x85, 0x82, 0x93,
93 0x24, 0x10, 0x40, 0x02, 0x08, 0xFF, 0x80, 0xFF, 0x25, 0x03,
94 0x02, 0x03, 0x02, 0x00, 0x00, 0x22005000, 0x2210A000, 0x2220F000,
95 0x22005000, 0x2210A000, 0x2220F000, 0xC0 },
96
97 /* 1024x768 @ 75Hz */
98 { 78000, 0x0050, 0x0017, 0x20, 0x9F, 0x7F, 0x7F, 0x83, 0x81, 0x8D,
99 0x1E, 0x10, 0x40, 0x00, 0x03, 0xFF, 0x80, 0xFF, 0x1F, 0x03,
100 0x02, 0x03, 0x02, 0x00, 0x00, 0x22006000, 0x2210B000, 0x22210000,
101 0x22006000, 0x2210B000, 0x22210000, 0x00 },
102
103 /* 1024x768 @ 85Hz */
104 { 94000, 0x003D, 0x000E, 0x20, 0xA7, 0x7F, 0x7F, 0x8B, 0x85, 0x91,
105 0x26, 0x10, 0x40, 0x00, 0x03, 0xFF, 0x80, 0xFF, 0x27, 0x03,
106 0x02, 0x03, 0x02, 0x00, 0x00, 0x22007000, 0x2220E000, 0x22212000,
107 0x22007000, 0x2220E000, 0x22212000, 0x00 },
108
109 /* 1152x864 @ 60Hz */
110 { 80000, 0x0008, 0x0001, 0x20, 0xB3, 0x8F, 0x8F, 0x97, 0x93, 0x9f,
111 0x87, 0x10, 0x40, 0x60, 0x03, 0x5F, 0x90, 0x5f, 0x88, 0x03,
112 0x03, 0x03, 0x03, 0x00, 0x00, 0x2220C000, 0x22210000, 0x22415000,
113 0x2220C000, 0x22210000, 0x22415000, 0x00 },
114
115 /* 1152x864 @ 70Hz */
116 { 96000, 0x000a, 0x0001, 0x20, 0xbb, 0x8F, 0x8F, 0x9f, 0x98, 0x87,
117 0x82, 0x10, 0x40, 0x60, 0x03, 0x5F, 0x90, 0x5F, 0x83, 0x03,
118 0x03, 0x03, 0x03, 0x00, 0x00, 0x22107000, 0x22210000, 0x22415000,
119 0x22107000, 0x22210000, 0x22415000, 0x00 },
120
121 /* 1152x864 @ 72Hz */
122 { 99000, 0x001f, 0x0006, 0x20, 0xbb, 0x8F, 0x8F, 0x9f, 0x98, 0x87,
123 0x83, 0x10, 0x40, 0x60, 0x03, 0x5F, 0x90, 0x5F, 0x84, 0x03,
124 0x03, 0x03, 0x03, 0x00, 0x00, 0x22107000, 0x22210000, 0x22415000,
125 0x22107000, 0x22210000, 0x22415000, 0x00 },
126
127 /* 1152x864 @ 75Hz */
128 { 108000, 0x0010, 0x0002, 0x20, 0xC3, 0x8F, 0x8F, 0x87, 0x97, 0x07,
129 0x82, 0x10, 0x40, 0x60, 0x03, 0x5F, 0x90, 0x5F, 0x83, 0x03,
130 0x03, 0x03, 0x03, 0x00, 0x01, 0x22107000, 0x22210000, 0x22415000,
131 0x22107000, 0x22210000, 0x22415000, 0x00 },
132
133 /* 1152x864 @ 85Hz */
134 { 121000, 0x006D, 0x0014, 0x20, 0xc0, 0x8F, 0x8F, 0x84, 0x97, 0x07,
135 0x93, 0x10, 0x40, 0x60, 0x03, 0x5F, 0x90, 0x5F, 0x94, 0x03,
136 0x03, 0x03, 0x03, 0x00, 0x01, 0x2220C000, 0x22210000, 0x22415000,
137 0x2220C000, 0x22210000, 0x22415000, 0x0 },
138
139 /* 1280x960 @ 60Hz */
140 { 108000, 0x0010, 0x0002, 0x20, 0xDC, 0x9F, 0x9F, 0x80, 0xAB, 0x99,
141 0xE6, 0x10, 0x40, 0xC0, 0x03, 0xBF, 0xA0, 0xBF, 0xE7, 0x03,
142 0x03, 0x03, 0x03, 0x00, 0x01, 0x2210A000, 0x22210000, 0x22415000,
143 0x2210A000, 0x22210000, 0x22415000, 0x00 },
144
145 /* 1280x960 @ 75Hz */
146 { 129000, 0x0029, 0x0006, 0x20, 0xD3, 0x9F, 0x9F, 0x97, 0xaa, 0x1b,
147 0xE8, 0x10, 0x40, 0xC0, 0x03, 0xBF, 0xA0, 0xBF, 0xE9, 0x03,
148 0x03, 0x03, 0x03, 0x00, 0x01, 0x2210A000, 0x22210000, 0x2241B000,
149 0x2210A000, 0x22210000, 0x2241B000, 0x00 },
150
151 /* 1280x960 @ 85Hz */
152 { 148000, 0x0042, 0x0009, 0x20, 0xD3, 0x9F, 0x9F, 0x97, 0xA7, 0x1B,
153 0xF1, 0x10, 0x40, 0xC0, 0x03, 0xBF, 0xA0, 0xBF, 0xF2, 0x03,
154 0x03, 0x03, 0x03, 0x00, 0x01, 0x2210A000, 0x22220000, 0x2241D000,
155 0x2210A000, 0x22220000, 0x2241D000, 0x00 },
156
157 /* 1600x1200 @ 60Hz */
158 { 162000, 0x0019, 0x0006, 0x10, 0x09, 0xC7, 0xC7, 0x8D, 0xcf, 0x07,
159 0xE0, 0x10, 0x40, 0xB0, 0x03, 0xAF, 0xC8, 0xAF, 0xE1, 0x04,
160 0x04, 0x04, 0x04, 0x01, 0x00, 0x2210b000, 0x22416000, 0x44419000,
161 0x2210b000, 0x22416000, 0x44419000, 0x00 },
162
163 /* 1600x1200 @ 65 Hz */
164 { 175000, 0x005d, 0x0018, 0x10, 0x09, 0xC7, 0xC7, 0x8D, 0xcf, 0x07,
165 0xE0, 0x10, 0x40, 0xB0, 0x03, 0xAF, 0xC8, 0xAF, 0xE1, 0x04,
166 0x04, 0x04, 0x04, 0x01, 0x00, 0x2210c000, 0x22416000, 0x44419000,
167 0x2210c000, 0x22416000, 0x44419000, 0x00 },
168
169 /* 1600x1200 @ 70 Hz */
170 { 189000, 0x003D, 0x000e, 0x10, 0x09, 0xC7, 0xC7, 0x8d, 0xcf, 0x07,
171 0xE0, 0x10, 0x40, 0xb0, 0x03, 0xAF, 0xC8, 0xaf, 0xE1, 0x04,
172 0x04, 0x04, 0x04, 0x01, 0x00, 0x2220e000, 0x22416000, 0x44419000,
173 0x2220e000, 0x22416000, 0x44419000, 0x00 },
174
175 /* 1600x1200 @ 72 Hz */
176 { 195000, 0x003f, 0x000e, 0x10, 0x0b, 0xC7, 0xC7, 0x8f, 0xd5, 0x0b,
177 0xE1, 0x10, 0x40, 0xb0, 0x03, 0xAF, 0xC8, 0xaf, 0xe2, 0x04, 0x04,
178 0x04, 0x04, 0x01, 0x00, 0x2220e000, 0x22416000, 0x44419000,
179 0x2220e000, 0x22416000, 0x44419000, 0x00 },
180
181 /* 1600x1200 @ 75 Hz */
182 { 202000, 0x0024, 0x0007, 0x10, 0x09, 0xC7, 0xC7, 0x8d, 0xcf, 0x07,
183 0xE0, 0x10, 0x40, 0xb0, 0x03, 0xAF, 0xC8, 0xaf, 0xE1, 0x04, 0x04,
184 0x04, 0x04, 0x01, 0x00, 0x2220e000, 0x22416000, 0x44419000,
185 0x2220e000, 0x22416000, 0x44419000, 0x00 },
186
187 /* 1600x1200 @ 85 Hz */
188 { 229000, 0x0029, 0x0007, 0x10, 0x09, 0xC7, 0xC7, 0x8d, 0xcf, 0x07,
189 0xE0, 0x10, 0x40, 0xb0, 0x03, 0xAF, 0xC8, 0xaf, 0xE1, 0x04, 0x04,
190 0x04, 0x04, 0x01, 0x00, 0x22210000, 0x22416000, 0x0,
191 0x22210000, 0x22416000, 0x0, 0x00 },
192};
193
194void round_off_xres(u32 *xres)
195{
196 if (*xres <= 640)
197 *xres = 640;
198 else if (*xres <= 800)
199 *xres = 800;
200 else if (*xres <= 1024)
201 *xres = 1024;
202 else if (*xres <= 1152)
203 *xres = 1152;
204 else if (*xres <= 1280)
205 *xres = 1280;
206 else
207 *xres = 1600;
208}
209
210inline void round_off_yres(u32 *xres, u32 *yres)
211{
212 *yres = (*xres * 3) >> 2;
213}
214
215void i810fb_encode_registers(const struct fb_var_screeninfo *var,
216 struct i810fb_par *par, u32 xres, u32 yres)
217{
218 u32 diff = 0, diff_best = 0xFFFFFFFF, i = 0, i_best = 0;
219 u8 hfl;
220
221 hfl = (u8) ((xres >> 3) - 1);
222 for (i = 0; i < ARRAY_SIZE(std_modes); i++) {
223 if (std_modes[i].cr01 == hfl) {
224 if (std_modes[i].pixclock <= par->regs.pixclock)
225 diff = par->regs.pixclock -
226 std_modes[i].pixclock;
227 if (diff < diff_best) {
228 i_best = i;
229 diff_best = diff;
230 }
231 }
232 }
233 par->regs = std_modes[i_best];
234
235 /* overlay */
236 par->ovract = ((xres + var->right_margin + var->hsync_len +
237 var->left_margin - 32) | ((xres - 32) << 16));
238}
239
240void i810fb_fill_var_timings(struct fb_var_screeninfo *var)
241{
242 struct i810fb_par par;
243 u32 total, xres, yres;
244
245 xres = var->xres;
246 yres = var->yres;
247
248 par.regs.pixclock = 1000000000/var->pixclock;
249 i810fb_encode_registers(var, &par, xres, yres);
250
251 total = ((par.regs.cr00 | (par.regs.cr35 & 1) << 8) + 3) << 3;
252
253 var->pixclock = 1000000000/par.regs.pixclock;
254 var->right_margin = (par.regs.cr04 << 3) - xres;
255 var->hsync_len = ((par.regs.cr05 & 0x1F) -
256 (par.regs.cr04 & 0x1F)) << 3;
257 var->left_margin = (total - (xres + var->right_margin +
258 var->hsync_len));
259 var->sync = FB_SYNC_ON_GREEN;
260 if (~(par.regs.msr & (1 << 6)))
261 var->sync |= FB_SYNC_HOR_HIGH_ACT;
262 if (~(par.regs.msr & (1 << 7)))
263 var->sync |= FB_SYNC_VERT_HIGH_ACT;
264
265
266 total = ((par.regs.cr06 | (par.regs.cr30 & 0x0F) << 8)) + 2;
267 var->lower_margin = (par.regs.cr10 |
268 (par.regs.cr32 & 0x0F) << 8) - yres;
269 var->vsync_len = (par.regs.cr11 & 0x0F) - (var->lower_margin & 0x0F);
270 var->upper_margin = total - (yres + var->lower_margin +
271 var->vsync_len);
272}
273
274u32 i810_get_watermark(struct fb_var_screeninfo *var,
275 struct i810fb_par *par)
276{
277 struct mode_registers *params = &par->regs;
278 u32 wmark = 0;
279
280 if (par->mem_freq == 100) {
281 switch (var->bits_per_pixel) {
282 case 8:
283 wmark = params->bpp8_100;
284 break;
285 case 16:
286 wmark = params->bpp16_100;
287 break;
288 case 24:
289 case 32:
290 wmark = params->bpp24_100;
291 }
292 } else {
293 switch (var->bits_per_pixel) {
294 case 8:
295 wmark = params->bpp8_133;
296 break;
297 case 16:
298 wmark = params->bpp16_133;
299 break;
300 case 24:
301 case 32:
302 wmark = params->bpp24_133;
303 }
304 }
305 return wmark;
306}
307
diff --git a/drivers/video/i810/i810_gtf.c b/drivers/video/i810/i810_gtf.c
new file mode 100644
index 000000000000..64f087a4466b
--- /dev/null
+++ b/drivers/video/i810/i810_gtf.c
@@ -0,0 +1,275 @@
1/*-*- linux-c -*-
2 * linux/drivers/video/i810_main.h -- Intel 810 Non-discrete Video Timings
3 * (VESA GTF)
4 *
5 * Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
6 * All Rights Reserved
7 *
8 *
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file COPYING in the main directory of this archive for
11 * more details.
12 */
13#include <linux/kernel.h>
14
15#include "i810_regs.h"
16#include "i810.h"
17
18/*
19 * FIFO and Watermark tables - based almost wholly on i810_wmark.c in
20 * XFree86 v4.03 by Precision Insight. Slightly modified for integer
21 * operation, instead of float
22 */
23
24struct wm_info {
25 u32 freq;
26 u32 wm;
27};
28
29static struct wm_info i810_wm_8_100[] = {
30 { 15, 0x0070c000 }, { 19, 0x0070c000 }, { 25, 0x22003000 },
31 { 28, 0x22003000 }, { 31, 0x22003000 }, { 36, 0x22007000 },
32 { 40, 0x22007000 }, { 45, 0x22007000 }, { 49, 0x22008000 },
33 { 50, 0x22008000 }, { 56, 0x22008000 }, { 65, 0x22008000 },
34 { 75, 0x22008000 }, { 78, 0x22008000 }, { 80, 0x22008000 },
35 { 94, 0x22008000 }, { 96, 0x22107000 }, { 99, 0x22107000 },
36 { 108, 0x22107000 }, { 121, 0x22107000 }, { 128, 0x22107000 },
37 { 132, 0x22109000 }, { 135, 0x22109000 }, { 157, 0x2210b000 },
38 { 162, 0x2210b000 }, { 175, 0x2210b000 }, { 189, 0x2220e000 },
39 { 195, 0x2220e000 }, { 202, 0x2220e000 }, { 204, 0x2220e000 },
40 { 218, 0x2220f000 }, { 229, 0x22210000 }, { 234, 0x22210000 },
41};
42
43static struct wm_info i810_wm_16_100[] = {
44 { 15, 0x0070c000 }, { 19, 0x0020c000 }, { 25, 0x22006000 },
45 { 28, 0x22006000 }, { 31, 0x22007000 }, { 36, 0x22007000 },
46 { 40, 0x22007000 }, { 45, 0x22007000 }, { 49, 0x22009000 },
47 { 50, 0x22009000 }, { 56, 0x22108000 }, { 65, 0x2210e000 },
48 { 75, 0x2210e000 }, { 78, 0x2210e000 }, { 80, 0x22210000 },
49 { 94, 0x22210000 }, { 96, 0x22210000 }, { 99, 0x22210000 },
50 { 108, 0x22210000 }, { 121, 0x22210000 }, { 128, 0x22210000 },
51 { 132, 0x22314000 }, { 135, 0x22314000 }, { 157, 0x22415000 },
52 { 162, 0x22416000 }, { 175, 0x22416000 }, { 189, 0x22416000 },
53 { 195, 0x22416000 }, { 202, 0x22416000 }, { 204, 0x22416000 },
54 { 218, 0x22416000 }, { 229, 0x22416000 },
55};
56
57static struct wm_info i810_wm_24_100[] = {
58 { 15, 0x0020c000 }, { 19, 0x0040c000 }, { 25, 0x22009000 },
59 { 28, 0x22009000 }, { 31, 0x2200a000 }, { 36, 0x2210c000 },
60 { 40, 0x2210c000 }, { 45, 0x2210c000 }, { 49, 0x22111000 },
61 { 50, 0x22111000 }, { 56, 0x22111000 }, { 65, 0x22214000 },
62 { 75, 0x22214000 }, { 78, 0x22215000 }, { 80, 0x22216000 },
63 { 94, 0x22218000 }, { 96, 0x22418000 }, { 99, 0x22418000 },
64 { 108, 0x22418000 }, { 121, 0x22418000 }, { 128, 0x22419000 },
65 { 132, 0x22519000 }, { 135, 0x4441d000 }, { 157, 0x44419000 },
66 { 162, 0x44419000 }, { 175, 0x44419000 }, { 189, 0x44419000 },
67 { 195, 0x44419000 }, { 202, 0x44419000 }, { 204, 0x44419000 },
68};
69
70static struct wm_info i810_wm_8_133[] = {
71 { 15, 0x0070c000 }, { 19, 0x0070c000 }, { 25, 0x22003000 },
72 { 28, 0x22003000 }, { 31, 0x22003000 }, { 36, 0x22007000 },
73 { 40, 0x22007000 }, { 45, 0x22007000 }, { 49, 0x22008000 },
74 { 50, 0x22008000 }, { 56, 0x22008000 }, { 65, 0x22008000 },
75 { 75, 0x22008000 }, { 78, 0x22008000 }, { 80, 0x22008000 },
76 { 94, 0x22008000 }, { 96, 0x22107000 }, { 99, 0x22107000 },
77 { 108, 0x22107000 }, { 121, 0x22107000 }, { 128, 0x22107000 },
78 { 132, 0x22109000 }, { 135, 0x22109000 }, { 157, 0x2210b000 },
79 { 162, 0x2210b000 }, { 175, 0x2210b000 }, { 189, 0x2220e000 },
80 { 195, 0x2220e000 }, { 202, 0x2220e000 }, { 204, 0x2220e000 },
81 { 218, 0x2220f000 }, { 229, 0x22210000 }, { 234, 0x22210000 },
82};
83
84static struct wm_info i810_wm_16_133[] = {
85 { 15, 0x0020c000 }, { 19, 0x0020c000 }, { 25, 0x22006000 },
86 { 28, 0x22006000 }, { 31, 0x22007000 }, { 36, 0x22007000 },
87 { 40, 0x22007000 }, { 45, 0x22007000 }, { 49, 0x22009000 },
88 { 50, 0x22009000 }, { 56, 0x22108000 }, { 65, 0x2210e000 },
89 { 75, 0x2210e000 }, { 78, 0x2210e000 }, { 80, 0x22210000 },
90 { 94, 0x22210000 }, { 96, 0x22210000 }, { 99, 0x22210000 },
91 { 108, 0x22210000 }, { 121, 0x22210000 }, { 128, 0x22210000 },
92 { 132, 0x22314000 }, { 135, 0x22314000 }, { 157, 0x22415000 },
93 { 162, 0x22416000 }, { 175, 0x22416000 }, { 189, 0x22416000 },
94 { 195, 0x22416000 }, { 202, 0x22416000 }, { 204, 0x22416000 },
95 { 218, 0x22416000 }, { 229, 0x22416000 },
96};
97
98static struct wm_info i810_wm_24_133[] = {
99 { 15, 0x0020c000 }, { 19, 0x00408000 }, { 25, 0x22009000 },
100 { 28, 0x22009000 }, { 31, 0x2200a000 }, { 36, 0x2210c000 },
101 { 40, 0x2210c000 }, { 45, 0x2210c000 }, { 49, 0x22111000 },
102 { 50, 0x22111000 }, { 56, 0x22111000 }, { 65, 0x22214000 },
103 { 75, 0x22214000 }, { 78, 0x22215000 }, { 80, 0x22216000 },
104 { 94, 0x22218000 }, { 96, 0x22418000 }, { 99, 0x22418000 },
105 { 108, 0x22418000 }, { 121, 0x22418000 }, { 128, 0x22419000 },
106 { 132, 0x22519000 }, { 135, 0x4441d000 }, { 157, 0x44419000 },
107 { 162, 0x44419000 }, { 175, 0x44419000 }, { 189, 0x44419000 },
108 { 195, 0x44419000 }, { 202, 0x44419000 }, { 204, 0x44419000 },
109};
110
111void round_off_xres(u32 *xres) { }
112void round_off_yres(u32 *xres, u32 *yres) { }
113
114/**
115 * i810fb_encode_registers - encode @var to hardware register values
116 * @var: pointer to var structure
117 * @par: pointer to hardware par structure
118 *
119 * DESCRIPTION:
120 * Timing values in @var will be converted to appropriate
121 * register values of @par.
122 */
123void i810fb_encode_registers(const struct fb_var_screeninfo *var,
124 struct i810fb_par *par, u32 xres, u32 yres)
125{
126 int n, blank_s, blank_e;
127 u8 __iomem *mmio = par->mmio_start_virtual;
128 u8 msr = 0;
129
130 /* Horizontal */
131 /* htotal */
132 n = ((xres + var->right_margin + var->hsync_len +
133 var->left_margin) >> 3) - 5;
134 par->regs.cr00 = (u8) n;
135 par->regs.cr35 = (u8) ((n >> 8) & 1);
136
137 /* xres */
138 par->regs.cr01 = (u8) ((xres >> 3) - 1);
139
140 /* hblank */
141 blank_e = (xres + var->right_margin + var->hsync_len +
142 var->left_margin) >> 3;
143 blank_e--;
144 blank_s = blank_e - 127;
145 if (blank_s < (xres >> 3))
146 blank_s = xres >> 3;
147 par->regs.cr02 = (u8) blank_s;
148 par->regs.cr03 = (u8) (blank_e & 0x1F);
149 par->regs.cr05 = (u8) ((blank_e & (1 << 5)) << 2);
150 par->regs.cr39 = (u8) ((blank_e >> 6) & 1);
151
152 /* hsync */
153 par->regs.cr04 = (u8) ((xres + var->right_margin) >> 3);
154 par->regs.cr05 |= (u8) (((xres + var->right_margin +
155 var->hsync_len) >> 3) & 0x1F);
156
157 /* Vertical */
158 /* vtotal */
159 n = yres + var->lower_margin + var->vsync_len + var->upper_margin - 2;
160 par->regs.cr06 = (u8) (n & 0xFF);
161 par->regs.cr30 = (u8) ((n >> 8) & 0x0F);
162
163 /* vsync */
164 n = yres + var->lower_margin;
165 par->regs.cr10 = (u8) (n & 0xFF);
166 par->regs.cr32 = (u8) ((n >> 8) & 0x0F);
167 par->regs.cr11 = i810_readb(CR11, mmio) & ~0x0F;
168 par->regs.cr11 |= (u8) ((yres + var->lower_margin +
169 var->vsync_len) & 0x0F);
170
171 /* yres */
172 n = yres - 1;
173 par->regs.cr12 = (u8) (n & 0xFF);
174 par->regs.cr31 = (u8) ((n >> 8) & 0x0F);
175
176 /* vblank */
177 blank_e = yres + var->lower_margin + var->vsync_len +
178 var->upper_margin;
179 blank_e--;
180 blank_s = blank_e - 127;
181 if (blank_s < yres)
182 blank_s = yres;
183 par->regs.cr15 = (u8) (blank_s & 0xFF);
184 par->regs.cr33 = (u8) ((blank_s >> 8) & 0x0F);
185 par->regs.cr16 = (u8) (blank_e & 0xFF);
186 par->regs.cr09 = 0;
187
188 /* sync polarity */
189 if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
190 msr |= 1 << 6;
191 if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
192 msr |= 1 << 7;
193 par->regs.msr = msr;
194
195 /* interlace */
196 if (var->vmode & FB_VMODE_INTERLACED)
197 par->interlace = (1 << 7) | ((u8) (var->yres >> 4));
198 else
199 par->interlace = 0;
200
201 if (var->vmode & FB_VMODE_DOUBLE)
202 par->regs.cr09 |= 1 << 7;
203
204 /* overlay */
205 par->ovract = ((var->xres + var->right_margin + var->hsync_len +
206 var->left_margin - 32) | ((var->xres - 32) << 16));
207}
208
209void i810fb_fill_var_timings(struct fb_var_screeninfo *var) { }
210
211/**
212 * i810_get_watermark - gets watermark
213 * @var: pointer to fb_var_screeninfo
214 * @par: pointer to i810fb_par structure
215 *
216 * DESCRIPTION:
217 * Gets the required watermark based on
218 * pixelclock and RAMBUS frequency.
219 *
220 * RETURNS:
221 * watermark
222 */
223u32 i810_get_watermark(const struct fb_var_screeninfo *var,
224 struct i810fb_par *par)
225{
226 struct wm_info *wmark = NULL;
227 u32 i, size = 0, pixclock, wm_best = 0, min, diff;
228
229 if (par->mem_freq == 100) {
230 switch (var->bits_per_pixel) {
231 case 8:
232 wmark = i810_wm_8_100;
233 size = ARRAY_SIZE(i810_wm_8_100);
234 break;
235 case 16:
236 wmark = i810_wm_16_100;
237 size = ARRAY_SIZE(i810_wm_16_100);
238 break;
239 case 24:
240 case 32:
241 wmark = i810_wm_24_100;
242 size = ARRAY_SIZE(i810_wm_24_100);
243 }
244 } else {
245 switch(var->bits_per_pixel) {
246 case 8:
247 wmark = i810_wm_8_133;
248 size = ARRAY_SIZE(i810_wm_8_133);
249 break;
250 case 16:
251 wmark = i810_wm_16_133;
252 size = ARRAY_SIZE(i810_wm_16_133);
253 break;
254 case 24:
255 case 32:
256 wmark = i810_wm_24_133;
257 size = ARRAY_SIZE(i810_wm_24_133);
258 }
259 }
260
261 pixclock = 1000000/var->pixclock;
262 min = ~0;
263 for (i = 0; i < size; i++) {
264 if (pixclock <= wmark[i].freq)
265 diff = wmark[i].freq - pixclock;
266 else
267 diff = pixclock - wmark[i].freq;
268 if (diff < min) {
269 wm_best = wmark[i].wm;
270 min = diff;
271 }
272 }
273 return wm_best;
274}
275
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
new file mode 100644
index 000000000000..9ec8781794c0
--- /dev/null
+++ b/drivers/video/i810/i810_main.c
@@ -0,0 +1,2062 @@
1 /*-*- linux-c -*-
2 * linux/drivers/video/i810_main.c -- Intel 810 frame buffer device
3 *
4 * Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
5 * All Rights Reserved
6 *
7 * Contributors:
8 * Michael Vogt <mvogt@acm.org> - added support for Intel 815 chipsets
9 * and enabling the power-on state of
10 * external VGA connectors for
11 * secondary displays
12 *
13 * Fredrik Andersson <krueger@shell.linux.se> - alpha testing of
14 * the VESA GTF
15 *
16 * Brad Corrion <bcorrion@web-co.com> - alpha testing of customized
17 * timings support
18 *
19 * The code framework is a modification of vfb.c by Geert Uytterhoeven.
20 * DotClock and PLL calculations are partly based on i810_driver.c
21 * in xfree86 v4.0.3 by Precision Insight.
22 * Watermark calculation and tables are based on i810_wmark.c
23 * in xfre86 v4.0.3 by Precision Insight. Slight modifications
24 * only to allow for integer operations instead of floating point.
25 *
26 * This file is subject to the terms and conditions of the GNU General Public
27 * License. See the file COPYING in the main directory of this archive for
28 * more details.
29 */
30
31#include <linux/module.h>
32#include <linux/config.h>
33#include <linux/kernel.h>
34#include <linux/errno.h>
35#include <linux/string.h>
36#include <linux/mm.h>
37#include <linux/tty.h>
38#include <linux/slab.h>
39#include <linux/fb.h>
40#include <linux/init.h>
41#include <linux/pci.h>
42#include <linux/pci_ids.h>
43#include <linux/resource.h>
44#include <linux/unistd.h>
45
46#include <asm/io.h>
47#include <asm/div64.h>
48
49#ifdef CONFIG_MTRR
50#include <asm/mtrr.h>
51#endif
52
53#include <asm/page.h>
54
55#include "i810_regs.h"
56#include "i810.h"
57#include "i810_main.h"
58
59/* PCI */
60static const char *i810_pci_list[] __devinitdata = {
61 "Intel(R) 810 Framebuffer Device" ,
62 "Intel(R) 810-DC100 Framebuffer Device" ,
63 "Intel(R) 810E Framebuffer Device" ,
64 "Intel(R) 815 (Internal Graphics 100Mhz FSB) Framebuffer Device" ,
65 "Intel(R) 815 (Internal Graphics only) Framebuffer Device" ,
66 "Intel(R) 815 (Internal Graphics with AGP) Framebuffer Device"
67};
68
69static struct pci_device_id i810fb_pci_tbl[] = {
70 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG1,
71 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
72 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3,
73 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
74 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810E_IG,
75 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
76 /* mvo: added i815 PCI-ID */
77 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_100,
78 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
79 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_NOAGP,
80 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
81 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC,
82 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 },
83 { 0 },
84};
85
86static struct pci_driver i810fb_driver = {
87 .name = "i810fb",
88 .id_table = i810fb_pci_tbl,
89 .probe = i810fb_init_pci,
90 .remove = __exit_p(i810fb_remove_pci),
91 .suspend = i810fb_suspend,
92 .resume = i810fb_resume,
93};
94
95static int vram __initdata = 4;
96static int bpp __initdata = 8;
97static int mtrr __initdata = 0;
98static int accel __initdata = 0;
99static int hsync1 __initdata = 0;
100static int hsync2 __initdata = 0;
101static int vsync1 __initdata = 0;
102static int vsync2 __initdata = 0;
103static int xres __initdata = 640;
104static int yres __initdata = 480;
105static int vyres __initdata = 0;
106static int sync __initdata = 0;
107static int ext_vga __initdata = 0;
108static int dcolor __initdata = 0;
109
110/*------------------------------------------------------------*/
111
112/**************************************************************
113 * Hardware Low Level Routines *
114 **************************************************************/
115
116/**
117 * i810_screen_off - turns off/on display
118 * @mmio: address of register space
119 * @mode: on or off
120 *
121 * DESCRIPTION:
122 * Blanks/unblanks the display
123 */
124static void i810_screen_off(u8 __iomem *mmio, u8 mode)
125{
126 u32 count = WAIT_COUNT;
127 u8 val;
128
129 i810_writeb(SR_INDEX, mmio, SR01);
130 val = i810_readb(SR_DATA, mmio);
131 val = (mode == OFF) ? val | SCR_OFF :
132 val & ~SCR_OFF;
133
134 while((i810_readw(DISP_SL, mmio) & 0xFFF) && count--);
135 i810_writeb(SR_INDEX, mmio, SR01);
136 i810_writeb(SR_DATA, mmio, val);
137}
138
139/**
140 * i810_dram_off - turns off/on dram refresh
141 * @mmio: address of register space
142 * @mode: on or off
143 *
144 * DESCRIPTION:
145 * Turns off DRAM refresh. Must be off for only 2 vsyncs
146 * before data becomes corrupt
147 */
148static void i810_dram_off(u8 __iomem *mmio, u8 mode)
149{
150 u8 val;
151
152 val = i810_readb(DRAMCH, mmio);
153 val &= DRAM_OFF;
154 val = (mode == OFF) ? val : val | DRAM_ON;
155 i810_writeb(DRAMCH, mmio, val);
156}
157
158/**
159 * i810_protect_regs - allows rw/ro mode of certain VGA registers
160 * @mmio: address of register space
161 * @mode: protect/unprotect
162 *
163 * DESCRIPTION:
164 * The IBM VGA standard allows protection of certain VGA registers.
165 * This will protect or unprotect them.
166 */
167static void i810_protect_regs(u8 __iomem *mmio, int mode)
168{
169 u8 reg;
170
171 i810_writeb(CR_INDEX_CGA, mmio, CR11);
172 reg = i810_readb(CR_DATA_CGA, mmio);
173 reg = (mode == OFF) ? reg & ~0x80 :
174 reg | 0x80;
175
176 i810_writeb(CR_INDEX_CGA, mmio, CR11);
177 i810_writeb(CR_DATA_CGA, mmio, reg);
178}
179
180/**
181 * i810_load_pll - loads values for the hardware PLL clock
182 * @par: pointer to i810fb_par structure
183 *
184 * DESCRIPTION:
185 * Loads the P, M, and N registers.
186 */
187static void i810_load_pll(struct i810fb_par *par)
188{
189 u32 tmp1, tmp2;
190 u8 __iomem *mmio = par->mmio_start_virtual;
191
192 tmp1 = par->regs.M | par->regs.N << 16;
193 tmp2 = i810_readl(DCLK_2D, mmio);
194 tmp2 &= ~MN_MASK;
195 i810_writel(DCLK_2D, mmio, tmp1 | tmp2);
196
197 tmp1 = par->regs.P;
198 tmp2 = i810_readl(DCLK_0DS, mmio);
199 tmp2 &= ~(P_OR << 16);
200 i810_writel(DCLK_0DS, mmio, (tmp1 << 16) | tmp2);
201
202 i810_writeb(MSR_WRITE, mmio, par->regs.msr | 0xC8 | 1);
203
204}
205
206/**
207 * i810_load_vga - load standard VGA registers
208 * @par: pointer to i810fb_par structure
209 *
210 * DESCRIPTION:
211 * Load values to VGA registers
212 */
213static void i810_load_vga(struct i810fb_par *par)
214{
215 u8 __iomem *mmio = par->mmio_start_virtual;
216
217 /* interlace */
218 i810_writeb(CR_INDEX_CGA, mmio, CR70);
219 i810_writeb(CR_DATA_CGA, mmio, par->interlace);
220
221 i810_writeb(CR_INDEX_CGA, mmio, CR00);
222 i810_writeb(CR_DATA_CGA, mmio, par->regs.cr00);
223 i810_writeb(CR_INDEX_CGA, mmio, CR01);
224 i810_writeb(CR_DATA_CGA, mmio, par->regs.cr01);
225 i810_writeb(CR_INDEX_CGA, mmio, CR02);
226 i810_writeb(CR_DATA_CGA, mmio, par->regs.cr02);
227 i810_writeb(CR_INDEX_CGA, mmio, CR03);
228 i810_writeb(CR_DATA_CGA, mmio, par->regs.cr03);
229 i810_writeb(CR_INDEX_CGA, mmio, CR04);
230 i810_writeb(CR_DATA_CGA, mmio, par->regs.cr04);
231 i810_writeb(CR_INDEX_CGA, mmio, CR05);
232 i810_writeb(CR_DATA_CGA, mmio, par->regs.cr05);
233 i810_writeb(CR_INDEX_CGA, mmio, CR06);
234 i810_writeb(CR_DATA_CGA, mmio, par->regs.cr06);
235 i810_writeb(CR_INDEX_CGA, mmio, CR09);
236 i810_writeb(CR_DATA_CGA, mmio, par->regs.cr09);
237 i810_writeb(CR_INDEX_CGA, mmio, CR10);
238 i810_writeb(CR_DATA_CGA, mmio, par->regs.cr10);
239 i810_writeb(CR_INDEX_CGA, mmio, CR11);
240 i810_writeb(CR_DATA_CGA, mmio, par->regs.cr11);
241 i810_writeb(CR_INDEX_CGA, mmio, CR12);
242 i810_writeb(CR_DATA_CGA, mmio, par->regs.cr12);
243 i810_writeb(CR_INDEX_CGA, mmio, CR15);
244 i810_writeb(CR_DATA_CGA, mmio, par->regs.cr15);
245 i810_writeb(CR_INDEX_CGA, mmio, CR16);
246 i810_writeb(CR_DATA_CGA, mmio, par->regs.cr16);
247}
248
249/**
250 * i810_load_vgax - load extended VGA registers
251 * @par: pointer to i810fb_par structure
252 *
253 * DESCRIPTION:
254 * Load values to extended VGA registers
255 */
256static void i810_load_vgax(struct i810fb_par *par)
257{
258 u8 __iomem *mmio = par->mmio_start_virtual;
259
260 i810_writeb(CR_INDEX_CGA, mmio, CR30);
261 i810_writeb(CR_DATA_CGA, mmio, par->regs.cr30);
262 i810_writeb(CR_INDEX_CGA, mmio, CR31);
263 i810_writeb(CR_DATA_CGA, mmio, par->regs.cr31);
264 i810_writeb(CR_INDEX_CGA, mmio, CR32);
265 i810_writeb(CR_DATA_CGA, mmio, par->regs.cr32);
266 i810_writeb(CR_INDEX_CGA, mmio, CR33);
267 i810_writeb(CR_DATA_CGA, mmio, par->regs.cr33);
268 i810_writeb(CR_INDEX_CGA, mmio, CR35);
269 i810_writeb(CR_DATA_CGA, mmio, par->regs.cr35);
270 i810_writeb(CR_INDEX_CGA, mmio, CR39);
271 i810_writeb(CR_DATA_CGA, mmio, par->regs.cr39);
272}
273
274/**
275 * i810_load_2d - load grahics registers
276 * @par: pointer to i810fb_par structure
277 *
278 * DESCRIPTION:
279 * Load values to graphics registers
280 */
281static void i810_load_2d(struct i810fb_par *par)
282{
283 u32 tmp;
284 u8 tmp8;
285 u8 __iomem *mmio = par->mmio_start_virtual;
286
287 i810_writel(FW_BLC, mmio, par->watermark);
288 tmp = i810_readl(PIXCONF, mmio);
289 tmp |= 1 | 1 << 20;
290 i810_writel(PIXCONF, mmio, tmp);
291
292 i810_writel(OVRACT, mmio, par->ovract);
293
294 i810_writeb(GR_INDEX, mmio, GR10);
295 tmp8 = i810_readb(GR_DATA, mmio);
296 tmp8 |= 2;
297 i810_writeb(GR_INDEX, mmio, GR10);
298 i810_writeb(GR_DATA, mmio, tmp8);
299}
300
301/**
302 * i810_hires - enables high resolution mode
303 * @mmio: address of register space
304 */
305static void i810_hires(u8 __iomem *mmio)
306{
307 u8 val;
308
309 i810_writeb(CR_INDEX_CGA, mmio, CR80);
310 val = i810_readb(CR_DATA_CGA, mmio);
311 i810_writeb(CR_INDEX_CGA, mmio, CR80);
312 i810_writeb(CR_DATA_CGA, mmio, val | 1);
313}
314
315/**
316 * i810_load_pitch - loads the characters per line of the display
317 * @par: pointer to i810fb_par structure
318 *
319 * DESCRIPTION:
320 * Loads the characters per line
321 */
322static void i810_load_pitch(struct i810fb_par *par)
323{
324 u32 tmp, pitch;
325 u8 val;
326 u8 __iomem *mmio = par->mmio_start_virtual;
327
328 pitch = par->pitch >> 3;
329 i810_writeb(SR_INDEX, mmio, SR01);
330 val = i810_readb(SR_DATA, mmio);
331 val &= 0xE0;
332 val |= 1 | 1 << 2;
333 i810_writeb(SR_INDEX, mmio, SR01);
334 i810_writeb(SR_DATA, mmio, val);
335
336 tmp = pitch & 0xFF;
337 i810_writeb(CR_INDEX_CGA, mmio, CR13);
338 i810_writeb(CR_DATA_CGA, mmio, (u8) tmp);
339
340 tmp = pitch >> 8;
341 i810_writeb(CR_INDEX_CGA, mmio, CR41);
342 val = i810_readb(CR_DATA_CGA, mmio) & ~0x0F;
343 i810_writeb(CR_INDEX_CGA, mmio, CR41);
344 i810_writeb(CR_DATA_CGA, mmio, (u8) tmp | val);
345}
346
347/**
348 * i810_load_color - loads the color depth of the display
349 * @par: pointer to i810fb_par structure
350 *
351 * DESCRIPTION:
352 * Loads the color depth of the display and the graphics engine
353 */
354static void i810_load_color(struct i810fb_par *par)
355{
356 u8 __iomem *mmio = par->mmio_start_virtual;
357 u32 reg1;
358 u16 reg2;
359
360 reg1 = i810_readl(PIXCONF, mmio) & ~(0xF0000 | 1 << 27);
361 reg2 = i810_readw(BLTCNTL, mmio) & ~0x30;
362
363 reg1 |= 0x8000 | par->pixconf;
364 reg2 |= par->bltcntl;
365 i810_writel(PIXCONF, mmio, reg1);
366 i810_writew(BLTCNTL, mmio, reg2);
367}
368
369/**
370 * i810_load_regs - loads all registers for the mode
371 * @par: pointer to i810fb_par structure
372 *
373 * DESCRIPTION:
374 * Loads registers
375 */
376static void i810_load_regs(struct i810fb_par *par)
377{
378 u8 __iomem *mmio = par->mmio_start_virtual;
379
380 i810_screen_off(mmio, OFF);
381 i810_protect_regs(mmio, OFF);
382 i810_dram_off(mmio, OFF);
383 i810_load_pll(par);
384 i810_load_vga(par);
385 i810_load_vgax(par);
386 i810_dram_off(mmio, ON);
387 i810_load_2d(par);
388 i810_hires(mmio);
389 i810_screen_off(mmio, ON);
390 i810_protect_regs(mmio, ON);
391 i810_load_color(par);
392 i810_load_pitch(par);
393}
394
395static void i810_write_dac(u8 regno, u8 red, u8 green, u8 blue,
396 u8 __iomem *mmio)
397{
398 i810_writeb(CLUT_INDEX_WRITE, mmio, regno);
399 i810_writeb(CLUT_DATA, mmio, red);
400 i810_writeb(CLUT_DATA, mmio, green);
401 i810_writeb(CLUT_DATA, mmio, blue);
402}
403
404static void i810_read_dac(u8 regno, u8 *red, u8 *green, u8 *blue,
405 u8 __iomem *mmio)
406{
407 i810_writeb(CLUT_INDEX_READ, mmio, regno);
408 *red = i810_readb(CLUT_DATA, mmio);
409 *green = i810_readb(CLUT_DATA, mmio);
410 *blue = i810_readb(CLUT_DATA, mmio);
411}
412
413/************************************************************
414 * VGA State Restore *
415 ************************************************************/
416static void i810_restore_pll(struct i810fb_par *par)
417{
418 u32 tmp1, tmp2;
419 u8 __iomem *mmio = par->mmio_start_virtual;
420
421 tmp1 = par->hw_state.dclk_2d;
422 tmp2 = i810_readl(DCLK_2D, mmio);
423 tmp1 &= ~MN_MASK;
424 tmp2 &= MN_MASK;
425 i810_writel(DCLK_2D, mmio, tmp1 | tmp2);
426
427 tmp1 = par->hw_state.dclk_1d;
428 tmp2 = i810_readl(DCLK_1D, mmio);
429 tmp1 &= ~MN_MASK;
430 tmp2 &= MN_MASK;
431 i810_writel(DCLK_1D, mmio, tmp1 | tmp2);
432
433 i810_writel(DCLK_0DS, mmio, par->hw_state.dclk_0ds);
434}
435
436static void i810_restore_dac(struct i810fb_par *par)
437{
438 u32 tmp1, tmp2;
439 u8 __iomem *mmio = par->mmio_start_virtual;
440
441 tmp1 = par->hw_state.pixconf;
442 tmp2 = i810_readl(PIXCONF, mmio);
443 tmp1 &= DAC_BIT;
444 tmp2 &= ~DAC_BIT;
445 i810_writel(PIXCONF, mmio, tmp1 | tmp2);
446}
447
448static void i810_restore_vgax(struct i810fb_par *par)
449{
450 u8 i, j;
451 u8 __iomem *mmio = par->mmio_start_virtual;
452
453 for (i = 0; i < 4; i++) {
454 i810_writeb(CR_INDEX_CGA, mmio, CR30+i);
455 i810_writeb(CR_DATA_CGA, mmio, *(&(par->hw_state.cr30) + i));
456 }
457 i810_writeb(CR_INDEX_CGA, mmio, CR35);
458 i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr35);
459 i810_writeb(CR_INDEX_CGA, mmio, CR39);
460 i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr39);
461 i810_writeb(CR_INDEX_CGA, mmio, CR41);
462 i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr39);
463
464 /*restore interlace*/
465 i810_writeb(CR_INDEX_CGA, mmio, CR70);
466 i = par->hw_state.cr70;
467 i &= INTERLACE_BIT;
468 j = i810_readb(CR_DATA_CGA, mmio);
469 i810_writeb(CR_INDEX_CGA, mmio, CR70);
470 i810_writeb(CR_DATA_CGA, mmio, j | i);
471
472 i810_writeb(CR_INDEX_CGA, mmio, CR80);
473 i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr80);
474 i810_writeb(MSR_WRITE, mmio, par->hw_state.msr);
475 i810_writeb(SR_INDEX, mmio, SR01);
476 i = (par->hw_state.sr01) & ~0xE0 ;
477 j = i810_readb(SR_DATA, mmio) & 0xE0;
478 i810_writeb(SR_INDEX, mmio, SR01);
479 i810_writeb(SR_DATA, mmio, i | j);
480}
481
482static void i810_restore_vga(struct i810fb_par *par)
483{
484 u8 i;
485 u8 __iomem *mmio = par->mmio_start_virtual;
486
487 for (i = 0; i < 10; i++) {
488 i810_writeb(CR_INDEX_CGA, mmio, CR00 + i);
489 i810_writeb(CR_DATA_CGA, mmio, *((&par->hw_state.cr00) + i));
490 }
491 for (i = 0; i < 8; i++) {
492 i810_writeb(CR_INDEX_CGA, mmio, CR10 + i);
493 i810_writeb(CR_DATA_CGA, mmio, *((&par->hw_state.cr10) + i));
494 }
495}
496
497static void i810_restore_addr_map(struct i810fb_par *par)
498{
499 u8 tmp;
500 u8 __iomem *mmio = par->mmio_start_virtual;
501
502 i810_writeb(GR_INDEX, mmio, GR10);
503 tmp = i810_readb(GR_DATA, mmio);
504 tmp &= ADDR_MAP_MASK;
505 tmp |= par->hw_state.gr10;
506 i810_writeb(GR_INDEX, mmio, GR10);
507 i810_writeb(GR_DATA, mmio, tmp);
508}
509
510static void i810_restore_2d(struct i810fb_par *par)
511{
512 u32 tmp_long;
513 u16 tmp_word;
514 u8 __iomem *mmio = par->mmio_start_virtual;
515
516 tmp_word = i810_readw(BLTCNTL, mmio);
517 tmp_word &= ~(3 << 4);
518 tmp_word |= par->hw_state.bltcntl;
519 i810_writew(BLTCNTL, mmio, tmp_word);
520
521 i810_dram_off(mmio, OFF);
522 i810_writel(PIXCONF, mmio, par->hw_state.pixconf);
523 i810_dram_off(mmio, ON);
524
525 tmp_word = i810_readw(HWSTAM, mmio);
526 tmp_word &= 3 << 13;
527 tmp_word |= par->hw_state.hwstam;
528 i810_writew(HWSTAM, mmio, tmp_word);
529
530 tmp_long = i810_readl(FW_BLC, mmio);
531 tmp_long &= FW_BLC_MASK;
532 tmp_long |= par->hw_state.fw_blc;
533 i810_writel(FW_BLC, mmio, tmp_long);
534
535 i810_writel(HWS_PGA, mmio, par->hw_state.hws_pga);
536 i810_writew(IER, mmio, par->hw_state.ier);
537 i810_writew(IMR, mmio, par->hw_state.imr);
538 i810_writel(DPLYSTAS, mmio, par->hw_state.dplystas);
539}
540
541static void i810_restore_vga_state(struct i810fb_par *par)
542{
543 u8 __iomem *mmio = par->mmio_start_virtual;
544
545 i810_screen_off(mmio, OFF);
546 i810_protect_regs(mmio, OFF);
547 i810_dram_off(mmio, OFF);
548 i810_restore_pll(par);
549 i810_restore_dac(par);
550 i810_restore_vga(par);
551 i810_restore_vgax(par);
552 i810_restore_addr_map(par);
553 i810_dram_off(mmio, ON);
554 i810_restore_2d(par);
555 i810_screen_off(mmio, ON);
556 i810_protect_regs(mmio, ON);
557}
558
559/***********************************************************************
560 * VGA State Save *
561 ***********************************************************************/
562
563static void i810_save_vgax(struct i810fb_par *par)
564{
565 u8 i;
566 u8 __iomem *mmio = par->mmio_start_virtual;
567
568 for (i = 0; i < 4; i++) {
569 i810_writeb(CR_INDEX_CGA, mmio, CR30 + i);
570 *(&(par->hw_state.cr30) + i) = i810_readb(CR_DATA_CGA, mmio);
571 }
572 i810_writeb(CR_INDEX_CGA, mmio, CR35);
573 par->hw_state.cr35 = i810_readb(CR_DATA_CGA, mmio);
574 i810_writeb(CR_INDEX_CGA, mmio, CR39);
575 par->hw_state.cr39 = i810_readb(CR_DATA_CGA, mmio);
576 i810_writeb(CR_INDEX_CGA, mmio, CR41);
577 par->hw_state.cr41 = i810_readb(CR_DATA_CGA, mmio);
578 i810_writeb(CR_INDEX_CGA, mmio, CR70);
579 par->hw_state.cr70 = i810_readb(CR_DATA_CGA, mmio);
580 par->hw_state.msr = i810_readb(MSR_READ, mmio);
581 i810_writeb(CR_INDEX_CGA, mmio, CR80);
582 par->hw_state.cr80 = i810_readb(CR_DATA_CGA, mmio);
583 i810_writeb(SR_INDEX, mmio, SR01);
584 par->hw_state.sr01 = i810_readb(SR_DATA, mmio);
585}
586
587static void i810_save_vga(struct i810fb_par *par)
588{
589 u8 i;
590 u8 __iomem *mmio = par->mmio_start_virtual;
591
592 for (i = 0; i < 10; i++) {
593 i810_writeb(CR_INDEX_CGA, mmio, CR00 + i);
594 *((&par->hw_state.cr00) + i) = i810_readb(CR_DATA_CGA, mmio);
595 }
596 for (i = 0; i < 8; i++) {
597 i810_writeb(CR_INDEX_CGA, mmio, CR10 + i);
598 *((&par->hw_state.cr10) + i) = i810_readb(CR_DATA_CGA, mmio);
599 }
600}
601
602static void i810_save_2d(struct i810fb_par *par)
603{
604 u8 __iomem *mmio = par->mmio_start_virtual;
605
606 par->hw_state.dclk_2d = i810_readl(DCLK_2D, mmio);
607 par->hw_state.dclk_1d = i810_readl(DCLK_1D, mmio);
608 par->hw_state.dclk_0ds = i810_readl(DCLK_0DS, mmio);
609 par->hw_state.pixconf = i810_readl(PIXCONF, mmio);
610 par->hw_state.fw_blc = i810_readl(FW_BLC, mmio);
611 par->hw_state.bltcntl = i810_readw(BLTCNTL, mmio);
612 par->hw_state.hwstam = i810_readw(HWSTAM, mmio);
613 par->hw_state.hws_pga = i810_readl(HWS_PGA, mmio);
614 par->hw_state.ier = i810_readw(IER, mmio);
615 par->hw_state.imr = i810_readw(IMR, mmio);
616 par->hw_state.dplystas = i810_readl(DPLYSTAS, mmio);
617}
618
619static void i810_save_vga_state(struct i810fb_par *par)
620{
621 i810_save_vga(par);
622 i810_save_vgax(par);
623 i810_save_2d(par);
624}
625
626/************************************************************
627 * Helpers *
628 ************************************************************/
629/**
630 * get_line_length - calculates buffer pitch in bytes
631 * @par: pointer to i810fb_par structure
632 * @xres_virtual: virtual resolution of the frame
633 * @bpp: bits per pixel
634 *
635 * DESCRIPTION:
636 * Calculates buffer pitch in bytes.
637 */
638static u32 get_line_length(struct i810fb_par *par, int xres_virtual, int bpp)
639{
640 u32 length;
641
642 length = xres_virtual*bpp;
643 length = (length+31)&-32;
644 length >>= 3;
645 return length;
646}
647
648/**
649 * i810_calc_dclk - calculates the P, M, and N values of a pixelclock value
650 * @freq: target pixelclock in picoseconds
651 * @m: where to write M register
652 * @n: where to write N register
653 * @p: where to write P register
654 *
655 * DESCRIPTION:
656 * Based on the formula Freq_actual = (4*M*Freq_ref)/(N^P)
657 * Repeatedly computes the Freq until the actual Freq is equal to
658 * the target Freq or until the loop count is zero. In the latter
659 * case, the actual frequency nearest the target will be used.
660 */
661static void i810_calc_dclk(u32 freq, u32 *m, u32 *n, u32 *p)
662{
663 u32 m_reg, n_reg, p_divisor, n_target_max;
664 u32 m_target, n_target, p_target, n_best, m_best, mod;
665 u32 f_out, target_freq, diff = 0, mod_min, diff_min;
666
667 diff_min = mod_min = 0xFFFFFFFF;
668 n_best = m_best = m_target = f_out = 0;
669
670 target_freq = freq;
671 n_target_max = 30;
672
673 /*
674 * find P such that target freq is 16x reference freq (Hz).
675 */
676 p_divisor = 1;
677 p_target = 0;
678 while(!((1000000 * p_divisor)/(16 * 24 * target_freq)) &&
679 p_divisor <= 32) {
680 p_divisor <<= 1;
681 p_target++;
682 }
683
684 n_reg = m_reg = n_target = 3;
685 while (diff_min && mod_min && (n_target < n_target_max)) {
686 f_out = (p_divisor * n_reg * 1000000)/(4 * 24 * m_reg);
687 mod = (p_divisor * n_reg * 1000000) % (4 * 24 * m_reg);
688 m_target = m_reg;
689 n_target = n_reg;
690 if (f_out <= target_freq) {
691 n_reg++;
692 diff = target_freq - f_out;
693 } else {
694 m_reg++;
695 diff = f_out - target_freq;
696 }
697
698 if (diff_min > diff) {
699 diff_min = diff;
700 n_best = n_target;
701 m_best = m_target;
702 }
703
704 if (!diff && mod_min > mod) {
705 mod_min = mod;
706 n_best = n_target;
707 m_best = m_target;
708 }
709 }
710 if (m) *m = (m_best - 2) & 0x3FF;
711 if (n) *n = (n_best - 2) & 0x3FF;
712 if (p) *p = (p_target << 4);
713}
714
715/*************************************************************
716 * Hardware Cursor Routines *
717 *************************************************************/
718
719/**
720 * i810_enable_cursor - show or hide the hardware cursor
721 * @mmio: address of register space
722 * @mode: show (1) or hide (0)
723 *
724 * Description:
725 * Shows or hides the hardware cursor
726 */
727static void i810_enable_cursor(u8 __iomem *mmio, int mode)
728{
729 u32 temp;
730
731 temp = i810_readl(PIXCONF, mmio);
732 temp = (mode == ON) ? temp | CURSOR_ENABLE_MASK :
733 temp & ~CURSOR_ENABLE_MASK;
734
735 i810_writel(PIXCONF, mmio, temp);
736}
737
738static void i810_reset_cursor_image(struct i810fb_par *par)
739{
740 u8 __iomem *addr = par->cursor_heap.virtual;
741 int i, j;
742
743 for (i = 64; i--; ) {
744 for (j = 0; j < 8; j++) {
745 i810_writeb(j, addr, 0xff);
746 i810_writeb(j+8, addr, 0x00);
747 }
748 addr +=16;
749 }
750}
751
752static void i810_load_cursor_image(int width, int height, u8 *data,
753 struct i810fb_par *par)
754{
755 u8 __iomem *addr = par->cursor_heap.virtual;
756 int i, j, w = width/8;
757 int mod = width % 8, t_mask, d_mask;
758
759 t_mask = 0xff >> mod;
760 d_mask = ~(0xff >> mod);
761 for (i = height; i--; ) {
762 for (j = 0; j < w; j++) {
763 i810_writeb(j+0, addr, 0x00);
764 i810_writeb(j+8, addr, *data++);
765 }
766 if (mod) {
767 i810_writeb(j+0, addr, t_mask);
768 i810_writeb(j+8, addr, *data++ & d_mask);
769 }
770 addr += 16;
771 }
772}
773
774static void i810_load_cursor_colors(int fg, int bg, struct fb_info *info)
775{
776 struct i810fb_par *par = (struct i810fb_par *) info->par;
777 u8 __iomem *mmio = par->mmio_start_virtual;
778 u8 red, green, blue, trans, temp;
779
780 i810fb_getcolreg(bg, &red, &green, &blue, &trans, info);
781
782 temp = i810_readb(PIXCONF1, mmio);
783 i810_writeb(PIXCONF1, mmio, temp | EXTENDED_PALETTE);
784
785 i810_write_dac(4, red, green, blue, mmio);
786
787 i810_writeb(PIXCONF1, mmio, temp);
788
789 i810fb_getcolreg(fg, &red, &green, &blue, &trans, info);
790 temp = i810_readb(PIXCONF1, mmio);
791 i810_writeb(PIXCONF1, mmio, temp | EXTENDED_PALETTE);
792
793 i810_write_dac(5, red, green, blue, mmio);
794
795 i810_writeb(PIXCONF1, mmio, temp);
796}
797
798/**
799 * i810_init_cursor - initializes the cursor
800 * @par: pointer to i810fb_par structure
801 *
802 * DESCRIPTION:
803 * Initializes the cursor registers
804 */
805static void i810_init_cursor(struct i810fb_par *par)
806{
807 u8 __iomem *mmio = par->mmio_start_virtual;
808
809 i810_enable_cursor(mmio, OFF);
810 i810_writel(CURBASE, mmio, par->cursor_heap.physical);
811 i810_writew(CURCNTR, mmio, COORD_ACTIVE | CURSOR_MODE_64_XOR);
812}
813
814/*********************************************************************
815 * Framebuffer hook helpers *
816 *********************************************************************/
817/**
818 * i810_round_off - Round off values to capability of hardware
819 * @var: pointer to fb_var_screeninfo structure
820 *
821 * DESCRIPTION:
822 * @var contains user-defined information for the mode to be set.
823 * This will try modify those values to ones nearest the
824 * capability of the hardware
825 */
826static void i810_round_off(struct fb_var_screeninfo *var)
827{
828 u32 xres, yres, vxres, vyres;
829
830 /*
831 * Presently supports only these configurations
832 */
833
834 xres = var->xres;
835 yres = var->yres;
836 vxres = var->xres_virtual;
837 vyres = var->yres_virtual;
838
839 var->bits_per_pixel += 7;
840 var->bits_per_pixel &= ~7;
841
842 if (var->bits_per_pixel < 8)
843 var->bits_per_pixel = 8;
844 if (var->bits_per_pixel > 32)
845 var->bits_per_pixel = 32;
846
847 round_off_xres(&xres);
848 if (xres < 40)
849 xres = 40;
850 if (xres > 2048)
851 xres = 2048;
852 xres = (xres + 7) & ~7;
853
854 if (vxres < xres)
855 vxres = xres;
856
857 round_off_yres(&xres, &yres);
858 if (yres < 1)
859 yres = 1;
860 if (yres >= 2048)
861 yres = 2048;
862
863 if (vyres < yres)
864 vyres = yres;
865
866 if (var->bits_per_pixel == 32)
867 var->accel_flags = 0;
868
869 /* round of horizontal timings to nearest 8 pixels */
870 var->left_margin = (var->left_margin + 4) & ~7;
871 var->right_margin = (var->right_margin + 4) & ~7;
872 var->hsync_len = (var->hsync_len + 4) & ~7;
873
874 if (var->vmode & FB_VMODE_INTERLACED) {
875 if (!((yres + var->upper_margin + var->vsync_len +
876 var->lower_margin) & 1))
877 var->upper_margin++;
878 }
879
880 var->xres = xres;
881 var->yres = yres;
882 var->xres_virtual = vxres;
883 var->yres_virtual = vyres;
884}
885
886/**
887 * set_color_bitfields - sets rgba fields
888 * @var: pointer to fb_var_screeninfo
889 *
890 * DESCRIPTION:
891 * The length, offset and ordering for each color field
892 * (red, green, blue) will be set as specified
893 * by the hardware
894 */
895static void set_color_bitfields(struct fb_var_screeninfo *var)
896{
897 switch (var->bits_per_pixel) {
898 case 8:
899 var->red.offset = 0;
900 var->red.length = 8;
901 var->green.offset = 0;
902 var->green.length = 8;
903 var->blue.offset = 0;
904 var->blue.length = 8;
905 var->transp.offset = 0;
906 var->transp.length = 0;
907 break;
908 case 16:
909 var->green.length = (var->green.length == 5) ? 5 : 6;
910 var->red.length = 5;
911 var->blue.length = 5;
912 var->transp.length = 6 - var->green.length;
913 var->blue.offset = 0;
914 var->green.offset = 5;
915 var->red.offset = 5 + var->green.length;
916 var->transp.offset = (5 + var->red.offset) & 15;
917 break;
918 case 24: /* RGB 888 */
919 case 32: /* RGBA 8888 */
920 var->red.offset = 16;
921 var->red.length = 8;
922 var->green.offset = 8;
923 var->green.length = 8;
924 var->blue.offset = 0;
925 var->blue.length = 8;
926 var->transp.length = var->bits_per_pixel - 24;
927 var->transp.offset = (var->transp.length) ? 24 : 0;
928 break;
929 }
930 var->red.msb_right = 0;
931 var->green.msb_right = 0;
932 var->blue.msb_right = 0;
933 var->transp.msb_right = 0;
934}
935
936/**
937 * i810_check_params - check if contents in var are valid
938 * @var: pointer to fb_var_screeninfo
939 * @info: pointer to fb_info
940 *
941 * DESCRIPTION:
942 * This will check if the framebuffer size is sufficient
943 * for the current mode and if the user's monitor has the
944 * required specifications to display the current mode.
945 */
946static int i810_check_params(struct fb_var_screeninfo *var,
947 struct fb_info *info)
948{
949 struct i810fb_par *par = (struct i810fb_par *) info->par;
950 int line_length, vidmem;
951 u32 xres, yres, vxres, vyres;
952
953 xres = var->xres;
954 yres = var->yres;
955 vxres = var->xres_virtual;
956 vyres = var->yres_virtual;
957
958 /*
959 * Memory limit
960 */
961 line_length = get_line_length(par, vxres,
962 var->bits_per_pixel);
963
964 vidmem = line_length*vyres;
965 if (vidmem > par->fb.size) {
966 vyres = par->fb.size/line_length;
967 if (vyres < yres) {
968 vyres = yres;
969 vxres = par->fb.size/vyres;
970 vxres /= var->bits_per_pixel >> 3;
971 line_length = get_line_length(par, vxres,
972 var->bits_per_pixel);
973 vidmem = line_length * yres;
974 if (vxres < xres) {
975 printk("i810fb: required video memory, "
976 "%d bytes, for %dx%d-%d (virtual) "
977 "is out of range\n",
978 vidmem, vxres, vyres,
979 var->bits_per_pixel);
980 return -ENOMEM;
981 }
982 }
983 }
984 /*
985 * Monitor limit
986 */
987 switch (var->bits_per_pixel) {
988 case 8:
989 info->monspecs.dclkmax = 234000000;
990 break;
991 case 16:
992 info->monspecs.dclkmax = 229000000;
993 break;
994 case 24:
995 case 32:
996 info->monspecs.dclkmax = 204000000;
997 break;
998 }
999 info->monspecs.dclkmin = 15000000;
1000
1001 if (fb_validate_mode(var, info)) {
1002 if (fb_get_mode(FB_MAXTIMINGS, 0, var, info))
1003 return -EINVAL;
1004 }
1005
1006 var->xres = xres;
1007 var->yres = yres;
1008 var->xres_virtual = vxres;
1009 var->yres_virtual = vyres;
1010 return 0;
1011}
1012
1013/**
1014 * encode_fix - fill up fb_fix_screeninfo structure
1015 * @fix: pointer to fb_fix_screeninfo
1016 * @info: pointer to fb_info
1017 *
1018 * DESCRIPTION:
1019 * This will set up parameters that are unmodifiable by the user.
1020 */
1021static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
1022{
1023 struct i810fb_par *par = (struct i810fb_par *) info->par;
1024
1025 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1026
1027 strcpy(fix->id, "I810");
1028 fix->smem_start = par->fb.physical;
1029 fix->smem_len = par->fb.size;
1030 fix->type = FB_TYPE_PACKED_PIXELS;
1031 fix->type_aux = 0;
1032 fix->xpanstep = 8;
1033 fix->ypanstep = 1;
1034
1035 switch (info->var.bits_per_pixel) {
1036 case 8:
1037 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1038 break;
1039 case 16:
1040 case 24:
1041 case 32:
1042 if (info->var.nonstd)
1043 fix->visual = FB_VISUAL_DIRECTCOLOR;
1044 else
1045 fix->visual = FB_VISUAL_TRUECOLOR;
1046 break;
1047 default:
1048 return -EINVAL;
1049 }
1050 fix->ywrapstep = 0;
1051 fix->line_length = par->pitch;
1052 fix->mmio_start = par->mmio_start_phys;
1053 fix->mmio_len = MMIO_SIZE;
1054 fix->accel = FB_ACCEL_I810;
1055
1056 return 0;
1057}
1058
1059/**
1060 * decode_var - modify par according to contents of var
1061 * @var: pointer to fb_var_screeninfo
1062 * @par: pointer to i810fb_par
1063 *
1064 * DESCRIPTION:
1065 * Based on the contents of @var, @par will be dynamically filled up.
1066 * @par contains all information necessary to modify the hardware.
1067*/
1068static void decode_var(const struct fb_var_screeninfo *var,
1069 struct i810fb_par *par)
1070{
1071 u32 xres, yres, vxres, vyres;
1072
1073 xres = var->xres;
1074 yres = var->yres;
1075 vxres = var->xres_virtual;
1076 vyres = var->yres_virtual;
1077
1078 switch (var->bits_per_pixel) {
1079 case 8:
1080 par->pixconf = PIXCONF8;
1081 par->bltcntl = 0;
1082 par->depth = 1;
1083 par->blit_bpp = BPP8;
1084 break;
1085 case 16:
1086 if (var->green.length == 5)
1087 par->pixconf = PIXCONF15;
1088 else
1089 par->pixconf = PIXCONF16;
1090 par->bltcntl = 16;
1091 par->depth = 2;
1092 par->blit_bpp = BPP16;
1093 break;
1094 case 24:
1095 par->pixconf = PIXCONF24;
1096 par->bltcntl = 32;
1097 par->depth = 3;
1098 par->blit_bpp = BPP24;
1099 break;
1100 case 32:
1101 par->pixconf = PIXCONF32;
1102 par->bltcntl = 0;
1103 par->depth = 4;
1104 par->blit_bpp = 3 << 24;
1105 break;
1106 }
1107 if (var->nonstd && var->bits_per_pixel != 8)
1108 par->pixconf |= 1 << 27;
1109
1110 i810_calc_dclk(var->pixclock, &par->regs.M,
1111 &par->regs.N, &par->regs.P);
1112 i810fb_encode_registers(var, par, xres, yres);
1113
1114 par->watermark = i810_get_watermark(var, par);
1115 par->pitch = get_line_length(par, vxres, var->bits_per_pixel);
1116}
1117
1118/**
1119 * i810fb_getcolreg - gets red, green and blue values of the hardware DAC
1120 * @regno: DAC index
1121 * @red: red
1122 * @green: green
1123 * @blue: blue
1124 * @transp: transparency (alpha)
1125 * @info: pointer to fb_info
1126 *
1127 * DESCRIPTION:
1128 * Gets the red, green and blue values of the hardware DAC as pointed by @regno
1129 * and writes them to @red, @green and @blue respectively
1130 */
1131static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue,
1132 u8 *transp, struct fb_info *info)
1133{
1134 struct i810fb_par *par = (struct i810fb_par *) info->par;
1135 u8 __iomem *mmio = par->mmio_start_virtual;
1136 u8 temp;
1137
1138 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
1139 if ((info->var.green.length == 5 && regno > 31) ||
1140 (info->var.green.length == 6 && regno > 63))
1141 return 1;
1142 }
1143
1144 temp = i810_readb(PIXCONF1, mmio);
1145 i810_writeb(PIXCONF1, mmio, temp & ~EXTENDED_PALETTE);
1146
1147 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR &&
1148 info->var.green.length == 5)
1149 i810_read_dac(regno * 8, red, green, blue, mmio);
1150
1151 else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR &&
1152 info->var.green.length == 6) {
1153 u8 tmp;
1154
1155 i810_read_dac(regno * 8, red, &tmp, blue, mmio);
1156 i810_read_dac(regno * 4, &tmp, green, &tmp, mmio);
1157 }
1158 else
1159 i810_read_dac(regno, red, green, blue, mmio);
1160
1161 *transp = 0;
1162 i810_writeb(PIXCONF1, mmio, temp);
1163
1164 return 0;
1165}
1166
1167/******************************************************************
1168 * Framebuffer device-specific hooks *
1169 ******************************************************************/
1170
1171static int i810fb_open(struct fb_info *info, int user)
1172{
1173 struct i810fb_par *par = (struct i810fb_par *) info->par;
1174 u32 count = atomic_read(&par->use_count);
1175
1176 if (count == 0) {
1177 memset(&par->state, 0, sizeof(struct vgastate));
1178 par->state.flags = VGA_SAVE_CMAP;
1179 par->state.vgabase = par->mmio_start_virtual;
1180 save_vga(&par->state);
1181
1182 i810_save_vga_state(par);
1183 }
1184
1185 atomic_inc(&par->use_count);
1186
1187 return 0;
1188}
1189
1190static int i810fb_release(struct fb_info *info, int user)
1191{
1192 struct i810fb_par *par = (struct i810fb_par *) info->par;
1193 u32 count;
1194
1195 count = atomic_read(&par->use_count);
1196 if (count == 0)
1197 return -EINVAL;
1198
1199 if (count == 1) {
1200 i810_restore_vga_state(par);
1201 restore_vga(&par->state);
1202 }
1203
1204 atomic_dec(&par->use_count);
1205
1206 return 0;
1207}
1208
1209
1210static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green,
1211 unsigned blue, unsigned transp,
1212 struct fb_info *info)
1213{
1214 struct i810fb_par *par = (struct i810fb_par *) info->par;
1215 u8 __iomem *mmio = par->mmio_start_virtual;
1216 u8 temp;
1217 int i;
1218
1219 if (regno > 255) return 1;
1220
1221 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
1222 if ((info->var.green.length == 5 && regno > 31) ||
1223 (info->var.green.length == 6 && regno > 63))
1224 return 1;
1225 }
1226
1227 if (info->var.grayscale)
1228 red = green = blue = (19595 * red + 38470 * green +
1229 7471 * blue) >> 16;
1230
1231 temp = i810_readb(PIXCONF1, mmio);
1232 i810_writeb(PIXCONF1, mmio, temp & ~EXTENDED_PALETTE);
1233
1234 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR &&
1235 info->var.green.length == 5) {
1236 for (i = 0; i < 8; i++)
1237 i810_write_dac((u8) (regno * 8) + i, (u8) red,
1238 (u8) green, (u8) blue, mmio);
1239 } else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR &&
1240 info->var.green.length == 6) {
1241 u8 r, g, b;
1242
1243 if (regno < 32) {
1244 for (i = 0; i < 8; i++)
1245 i810_write_dac((u8) (regno * 8) + i,
1246 (u8) red, (u8) green,
1247 (u8) blue, mmio);
1248 }
1249 i810_read_dac((u8) (regno*4), &r, &g, &b, mmio);
1250 for (i = 0; i < 4; i++)
1251 i810_write_dac((u8) (regno*4) + i, r, (u8) green,
1252 b, mmio);
1253 } else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
1254 i810_write_dac((u8) regno, (u8) red, (u8) green,
1255 (u8) blue, mmio);
1256 }
1257
1258 i810_writeb(PIXCONF1, mmio, temp);
1259
1260 if (regno < 16) {
1261 switch (info->var.bits_per_pixel) {
1262 case 16:
1263 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
1264 if (info->var.green.length == 5)
1265 ((u32 *)info->pseudo_palette)[regno] =
1266 (regno << 10) | (regno << 5) |
1267 regno;
1268 else
1269 ((u32 *)info->pseudo_palette)[regno] =
1270 (regno << 11) | (regno << 5) |
1271 regno;
1272 } else {
1273 if (info->var.green.length == 5) {
1274 /* RGB 555 */
1275 ((u32 *)info->pseudo_palette)[regno] =
1276 ((red & 0xf800) >> 1) |
1277 ((green & 0xf800) >> 6) |
1278 ((blue & 0xf800) >> 11);
1279 } else {
1280 /* RGB 565 */
1281 ((u32 *)info->pseudo_palette)[regno] =
1282 (red & 0xf800) |
1283 ((green & 0xf800) >> 5) |
1284 ((blue & 0xf800) >> 11);
1285 }
1286 }
1287 break;
1288 case 24: /* RGB 888 */
1289 case 32: /* RGBA 8888 */
1290 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR)
1291 ((u32 *)info->pseudo_palette)[regno] =
1292 (regno << 16) | (regno << 8) |
1293 regno;
1294 else
1295 ((u32 *)info->pseudo_palette)[regno] =
1296 ((red & 0xff00) << 8) |
1297 (green & 0xff00) |
1298 ((blue & 0xff00) >> 8);
1299 break;
1300 }
1301 }
1302 return 0;
1303}
1304
1305static int i810fb_pan_display(struct fb_var_screeninfo *var,
1306 struct fb_info *info)
1307{
1308 struct i810fb_par *par = (struct i810fb_par *) info->par;
1309 u32 total;
1310
1311 total = var->xoffset * par->depth +
1312 var->yoffset * info->fix.line_length;
1313 i810fb_load_front(total, info);
1314
1315 return 0;
1316}
1317
1318static int i810fb_blank (int blank_mode, struct fb_info *info)
1319{
1320 struct i810fb_par *par = (struct i810fb_par *) info->par;
1321 u8 __iomem *mmio = par->mmio_start_virtual;
1322 int mode = 0, pwr, scr_off = 0;
1323
1324 pwr = i810_readl(PWR_CLKC, mmio);
1325
1326 switch (blank_mode) {
1327 case FB_BLANK_UNBLANK:
1328 mode = POWERON;
1329 pwr |= 1;
1330 scr_off = ON;
1331 break;
1332 case FB_BLANK_NORMAL:
1333 mode = POWERON;
1334 pwr |= 1;
1335 scr_off = OFF;
1336 break;
1337 case FB_BLANK_VSYNC_SUSPEND:
1338 mode = STANDBY;
1339 pwr |= 1;
1340 scr_off = OFF;
1341 break;
1342 case FB_BLANK_HSYNC_SUSPEND:
1343 mode = SUSPEND;
1344 pwr |= 1;
1345 scr_off = OFF;
1346 break;
1347 case FB_BLANK_POWERDOWN:
1348 mode = POWERDOWN;
1349 pwr &= ~1;
1350 scr_off = OFF;
1351 break;
1352 default:
1353 return -EINVAL;
1354 }
1355
1356 i810_screen_off(mmio, scr_off);
1357 i810_writel(HVSYNC, mmio, mode);
1358 i810_writel(PWR_CLKC, mmio, pwr);
1359
1360 return 0;
1361}
1362
1363static int i810fb_set_par(struct fb_info *info)
1364{
1365 struct i810fb_par *par = (struct i810fb_par *) info->par;
1366
1367 decode_var(&info->var, par);
1368 i810_load_regs(par);
1369 i810_init_cursor(par);
1370
1371 encode_fix(&info->fix, info);
1372
1373 if (info->var.accel_flags && !(par->dev_flags & LOCKUP)) {
1374 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
1375 FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
1376 FBINFO_HWACCEL_IMAGEBLIT;
1377 info->pixmap.scan_align = 2;
1378 } else {
1379 info->pixmap.scan_align = 1;
1380 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1381 }
1382 return 0;
1383}
1384
1385static int i810fb_check_var(struct fb_var_screeninfo *var,
1386 struct fb_info *info)
1387{
1388 int err;
1389
1390 if (IS_DVT) {
1391 var->vmode &= ~FB_VMODE_MASK;
1392 var->vmode |= FB_VMODE_NONINTERLACED;
1393 }
1394 if (var->vmode & FB_VMODE_DOUBLE) {
1395 var->vmode &= ~FB_VMODE_MASK;
1396 var->vmode |= FB_VMODE_NONINTERLACED;
1397 }
1398
1399 i810_round_off(var);
1400 if ((err = i810_check_params(var, info)))
1401 return err;
1402
1403 i810fb_fill_var_timings(var);
1404 set_color_bitfields(var);
1405 return 0;
1406}
1407
1408static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1409{
1410 struct i810fb_par *par = (struct i810fb_par *)info->par;
1411 u8 __iomem *mmio = par->mmio_start_virtual;
1412
1413 if (!(par->dev_flags & USE_HWCUR) || !info->var.accel_flags ||
1414 par->dev_flags & LOCKUP)
1415 return soft_cursor(info, cursor);
1416
1417 if (cursor->image.width > 64 || cursor->image.height > 64)
1418 return -ENXIO;
1419
1420 if ((i810_readl(CURBASE, mmio) & 0xf) != par->cursor_heap.physical) {
1421 i810_init_cursor(par);
1422 cursor->set |= FB_CUR_SETALL;
1423 }
1424
1425 i810_enable_cursor(mmio, OFF);
1426
1427 if (cursor->set & FB_CUR_SETPOS) {
1428 u32 tmp;
1429
1430 tmp = (cursor->image.dx - info->var.xoffset) & 0xffff;
1431 tmp |= (cursor->image.dy - info->var.yoffset) << 16;
1432 i810_writel(CURPOS, mmio, tmp);
1433 }
1434
1435 if (cursor->set & FB_CUR_SETSIZE)
1436 i810_reset_cursor_image(par);
1437
1438 if (cursor->set & FB_CUR_SETCMAP)
1439 i810_load_cursor_colors(cursor->image.fg_color,
1440 cursor->image.bg_color,
1441 info);
1442
1443 if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
1444 int size = ((cursor->image.width + 7) >> 3) *
1445 cursor->image.height;
1446 int i;
1447 u8 *data = kmalloc(64 * 8, GFP_KERNEL);
1448
1449 if (data == NULL)
1450 return -ENOMEM;
1451
1452 switch (cursor->rop) {
1453 case ROP_XOR:
1454 for (i = 0; i < size; i++)
1455 data[i] = cursor->image.data[i] ^ cursor->mask[i];
1456 break;
1457 case ROP_COPY:
1458 default:
1459 for (i = 0; i < size; i++)
1460 data[i] = cursor->image.data[i] & cursor->mask[i];
1461 break;
1462 }
1463
1464 i810_load_cursor_image(cursor->image.width,
1465 cursor->image.height, data,
1466 par);
1467 kfree(data);
1468 }
1469
1470 if (cursor->enable)
1471 i810_enable_cursor(mmio, ON);
1472
1473 return 0;
1474}
1475
1476static struct fb_ops i810fb_ops __devinitdata = {
1477 .owner = THIS_MODULE,
1478 .fb_open = i810fb_open,
1479 .fb_release = i810fb_release,
1480 .fb_check_var = i810fb_check_var,
1481 .fb_set_par = i810fb_set_par,
1482 .fb_setcolreg = i810fb_setcolreg,
1483 .fb_blank = i810fb_blank,
1484 .fb_pan_display = i810fb_pan_display,
1485 .fb_fillrect = i810fb_fillrect,
1486 .fb_copyarea = i810fb_copyarea,
1487 .fb_imageblit = i810fb_imageblit,
1488 .fb_cursor = i810fb_cursor,
1489 .fb_sync = i810fb_sync,
1490};
1491
1492/***********************************************************************
1493 * Power Management *
1494 ***********************************************************************/
1495static int i810fb_suspend(struct pci_dev *dev, pm_message_t state)
1496{
1497 struct fb_info *info = pci_get_drvdata(dev);
1498 struct i810fb_par *par = (struct i810fb_par *) info->par;
1499 int blank = 0, prev_state = par->cur_state;
1500
1501 if (state == prev_state)
1502 return 0;
1503
1504 par->cur_state = state;
1505
1506 switch (state) {
1507 case 1:
1508 blank = VESA_VSYNC_SUSPEND;
1509 break;
1510 case 2:
1511 blank = VESA_HSYNC_SUSPEND;
1512 break;
1513 case 3:
1514 blank = VESA_POWERDOWN;
1515 break;
1516 default:
1517 return -EINVAL;
1518 }
1519 info->fbops->fb_blank(blank, info);
1520
1521 if (!prev_state) {
1522 agp_unbind_memory(par->i810_gtt.i810_fb_memory);
1523 agp_unbind_memory(par->i810_gtt.i810_cursor_memory);
1524 pci_disable_device(dev);
1525 }
1526 pci_save_state(dev);
1527 pci_set_power_state(dev, pci_choose_state(dev, state));
1528
1529 return 0;
1530}
1531
1532static int i810fb_resume(struct pci_dev *dev)
1533{
1534 struct fb_info *info = pci_get_drvdata(dev);
1535 struct i810fb_par *par = (struct i810fb_par *) info->par;
1536
1537 if (par->cur_state == 0)
1538 return 0;
1539
1540 pci_restore_state(dev);
1541 pci_set_power_state(dev, PCI_D0);
1542 pci_enable_device(dev);
1543 agp_bind_memory(par->i810_gtt.i810_fb_memory,
1544 par->fb.offset);
1545 agp_bind_memory(par->i810_gtt.i810_cursor_memory,
1546 par->cursor_heap.offset);
1547
1548 info->fbops->fb_blank(VESA_NO_BLANKING, info);
1549
1550 par->cur_state = 0;
1551
1552 return 0;
1553}
1554/***********************************************************************
1555 * AGP resource allocation *
1556 ***********************************************************************/
1557
1558static void __devinit i810_fix_pointers(struct i810fb_par *par)
1559{
1560 par->fb.physical = par->aperture.physical+(par->fb.offset << 12);
1561 par->fb.virtual = par->aperture.virtual+(par->fb.offset << 12);
1562 par->iring.physical = par->aperture.physical +
1563 (par->iring.offset << 12);
1564 par->iring.virtual = par->aperture.virtual +
1565 (par->iring.offset << 12);
1566 par->cursor_heap.virtual = par->aperture.virtual+
1567 (par->cursor_heap.offset << 12);
1568}
1569
1570static void __devinit i810_fix_offsets(struct i810fb_par *par)
1571{
1572 if (vram + 1 > par->aperture.size >> 20)
1573 vram = (par->aperture.size >> 20) - 1;
1574 if (v_offset_default > (par->aperture.size >> 20))
1575 v_offset_default = (par->aperture.size >> 20);
1576 if (vram + v_offset_default + 1 > par->aperture.size >> 20)
1577 v_offset_default = (par->aperture.size >> 20) - (vram + 1);
1578
1579 par->fb.size = vram << 20;
1580 par->fb.offset = v_offset_default << 20;
1581 par->fb.offset >>= 12;
1582
1583 par->iring.offset = par->fb.offset + (par->fb.size >> 12);
1584 par->iring.size = RINGBUFFER_SIZE;
1585
1586 par->cursor_heap.offset = par->iring.offset + (RINGBUFFER_SIZE >> 12);
1587 par->cursor_heap.size = 4096;
1588}
1589
1590static int __devinit i810_alloc_agp_mem(struct fb_info *info)
1591{
1592 struct i810fb_par *par = (struct i810fb_par *) info->par;
1593 int size;
1594 struct agp_bridge_data *bridge;
1595
1596 i810_fix_offsets(par);
1597 size = par->fb.size + par->iring.size;
1598
1599 if (!(bridge = agp_backend_acquire(par->dev))) {
1600 printk("i810fb_alloc_fbmem: cannot acquire agpgart\n");
1601 return -ENODEV;
1602 }
1603 if (!(par->i810_gtt.i810_fb_memory =
1604 agp_allocate_memory(bridge, size >> 12, AGP_NORMAL_MEMORY))) {
1605 printk("i810fb_alloc_fbmem: can't allocate framebuffer "
1606 "memory\n");
1607 agp_backend_release(bridge);
1608 return -ENOMEM;
1609 }
1610 if (agp_bind_memory(par->i810_gtt.i810_fb_memory,
1611 par->fb.offset)) {
1612 printk("i810fb_alloc_fbmem: can't bind framebuffer memory\n");
1613 agp_backend_release(bridge);
1614 return -EBUSY;
1615 }
1616
1617 if (!(par->i810_gtt.i810_cursor_memory =
1618 agp_allocate_memory(bridge, par->cursor_heap.size >> 12,
1619 AGP_PHYSICAL_MEMORY))) {
1620 printk("i810fb_alloc_cursormem: can't allocate"
1621 "cursor memory\n");
1622 agp_backend_release(bridge);
1623 return -ENOMEM;
1624 }
1625 if (agp_bind_memory(par->i810_gtt.i810_cursor_memory,
1626 par->cursor_heap.offset)) {
1627 printk("i810fb_alloc_cursormem: cannot bind cursor memory\n");
1628 agp_backend_release(bridge);
1629 return -EBUSY;
1630 }
1631
1632 par->cursor_heap.physical = par->i810_gtt.i810_cursor_memory->physical;
1633
1634 i810_fix_pointers(par);
1635
1636 agp_backend_release(bridge);
1637
1638 return 0;
1639}
1640
1641/***************************************************************
1642 * Initialization *
1643 ***************************************************************/
1644
1645/**
1646 * i810_init_monspecs
1647 * @info: pointer to device specific info structure
1648 *
1649 * DESCRIPTION:
1650 * Sets the the user monitor's horizontal and vertical
1651 * frequency limits
1652 */
1653static void __devinit i810_init_monspecs(struct fb_info *info)
1654{
1655 if (!hsync1)
1656 hsync1 = HFMIN;
1657 if (!hsync2)
1658 hsync2 = HFMAX;
1659 if (!info->monspecs.hfmax)
1660 info->monspecs.hfmax = hsync2;
1661 if (!info->monspecs.hfmin)
1662 info->monspecs.hfmin = hsync1;
1663 if (hsync2 < hsync1)
1664 info->monspecs.hfmin = hsync2;
1665
1666 if (!vsync1)
1667 vsync1 = VFMIN;
1668 if (!vsync2)
1669 vsync2 = VFMAX;
1670 if (IS_DVT && vsync1 < 60)
1671 vsync1 = 60;
1672 if (!info->monspecs.vfmax)
1673 info->monspecs.vfmax = vsync2;
1674 if (!info->monspecs.vfmin)
1675 info->monspecs.vfmin = vsync1;
1676 if (vsync2 < vsync1)
1677 info->monspecs.vfmin = vsync2;
1678}
1679
1680/**
1681 * i810_init_defaults - initializes default values to use
1682 * @par: pointer to i810fb_par structure
1683 * @info: pointer to current fb_info structure
1684 */
1685static void __devinit i810_init_defaults(struct i810fb_par *par,
1686 struct fb_info *info)
1687{
1688 if (voffset)
1689 v_offset_default = voffset;
1690 else if (par->aperture.size > 32 * 1024 * 1024)
1691 v_offset_default = 16;
1692 else
1693 v_offset_default = 8;
1694
1695 if (!vram)
1696 vram = 1;
1697
1698 if (accel)
1699 par->dev_flags |= HAS_ACCELERATION;
1700
1701 if (sync)
1702 par->dev_flags |= ALWAYS_SYNC;
1703
1704 if (bpp < 8)
1705 bpp = 8;
1706
1707 if (!vyres)
1708 vyres = (vram << 20)/(xres*bpp >> 3);
1709
1710 par->i810fb_ops = i810fb_ops;
1711 info->var.xres = xres;
1712 info->var.yres = yres;
1713 info->var.yres_virtual = vyres;
1714 info->var.bits_per_pixel = bpp;
1715
1716 if (dcolor)
1717 info->var.nonstd = 1;
1718
1719 if (par->dev_flags & HAS_ACCELERATION)
1720 info->var.accel_flags = 1;
1721
1722 i810_init_monspecs(info);
1723}
1724
1725/**
1726 * i810_init_device - initialize device
1727 * @par: pointer to i810fb_par structure
1728 */
1729static void __devinit i810_init_device(struct i810fb_par *par)
1730{
1731 u8 reg;
1732 u8 __iomem *mmio = par->mmio_start_virtual;
1733
1734 if (mtrr) set_mtrr(par);
1735
1736 i810_init_cursor(par);
1737
1738 /* mvo: enable external vga-connector (for laptops) */
1739 if (ext_vga) {
1740 i810_writel(HVSYNC, mmio, 0);
1741 i810_writel(PWR_CLKC, mmio, 3);
1742 }
1743
1744 pci_read_config_byte(par->dev, 0x50, &reg);
1745 reg &= FREQ_MASK;
1746 par->mem_freq = (reg) ? 133 : 100;
1747
1748}
1749
1750static int __devinit
1751i810_allocate_pci_resource(struct i810fb_par *par,
1752 const struct pci_device_id *entry)
1753{
1754 int err;
1755
1756 if ((err = pci_enable_device(par->dev))) {
1757 printk("i810fb_init: cannot enable device\n");
1758 return err;
1759 }
1760 par->res_flags |= PCI_DEVICE_ENABLED;
1761
1762 if (pci_resource_len(par->dev, 0) > 512 * 1024) {
1763 par->aperture.physical = pci_resource_start(par->dev, 0);
1764 par->aperture.size = pci_resource_len(par->dev, 0);
1765 par->mmio_start_phys = pci_resource_start(par->dev, 1);
1766 } else {
1767 par->aperture.physical = pci_resource_start(par->dev, 1);
1768 par->aperture.size = pci_resource_len(par->dev, 1);
1769 par->mmio_start_phys = pci_resource_start(par->dev, 0);
1770 }
1771 if (!par->aperture.size) {
1772 printk("i810fb_init: device is disabled\n");
1773 return -ENOMEM;
1774 }
1775
1776 if (!request_mem_region(par->aperture.physical,
1777 par->aperture.size,
1778 i810_pci_list[entry->driver_data])) {
1779 printk("i810fb_init: cannot request framebuffer region\n");
1780 return -ENODEV;
1781 }
1782 par->res_flags |= FRAMEBUFFER_REQ;
1783
1784 par->aperture.virtual = ioremap_nocache(par->aperture.physical,
1785 par->aperture.size);
1786 if (!par->aperture.virtual) {
1787 printk("i810fb_init: cannot remap framebuffer region\n");
1788 return -ENODEV;
1789 }
1790
1791 if (!request_mem_region(par->mmio_start_phys,
1792 MMIO_SIZE,
1793 i810_pci_list[entry->driver_data])) {
1794 printk("i810fb_init: cannot request mmio region\n");
1795 return -ENODEV;
1796 }
1797 par->res_flags |= MMIO_REQ;
1798
1799 par->mmio_start_virtual = ioremap_nocache(par->mmio_start_phys,
1800 MMIO_SIZE);
1801 if (!par->mmio_start_virtual) {
1802 printk("i810fb_init: cannot remap mmio region\n");
1803 return -ENODEV;
1804 }
1805
1806 return 0;
1807}
1808
1809#ifndef MODULE
1810static int __init i810fb_setup(char *options)
1811{
1812 char *this_opt, *suffix = NULL;
1813
1814 if (!options || !*options)
1815 return 0;
1816
1817 while ((this_opt = strsep(&options, ",")) != NULL) {
1818 if (!strncmp(this_opt, "mtrr", 4))
1819 mtrr = 1;
1820 else if (!strncmp(this_opt, "accel", 5))
1821 accel = 1;
1822 else if (!strncmp(this_opt, "ext_vga", 7))
1823 ext_vga = 1;
1824 else if (!strncmp(this_opt, "sync", 4))
1825 sync = 1;
1826 else if (!strncmp(this_opt, "vram:", 5))
1827 vram = (simple_strtoul(this_opt+5, NULL, 0));
1828 else if (!strncmp(this_opt, "voffset:", 8))
1829 voffset = (simple_strtoul(this_opt+8, NULL, 0));
1830 else if (!strncmp(this_opt, "xres:", 5))
1831 xres = simple_strtoul(this_opt+5, NULL, 0);
1832 else if (!strncmp(this_opt, "yres:", 5))
1833 yres = simple_strtoul(this_opt+5, NULL, 0);
1834 else if (!strncmp(this_opt, "vyres:", 6))
1835 vyres = simple_strtoul(this_opt+6, NULL, 0);
1836 else if (!strncmp(this_opt, "bpp:", 4))
1837 bpp = simple_strtoul(this_opt+4, NULL, 0);
1838 else if (!strncmp(this_opt, "hsync1:", 7)) {
1839 hsync1 = simple_strtoul(this_opt+7, &suffix, 0);
1840 if (strncmp(suffix, "H", 1))
1841 hsync1 *= 1000;
1842 } else if (!strncmp(this_opt, "hsync2:", 7)) {
1843 hsync2 = simple_strtoul(this_opt+7, &suffix, 0);
1844 if (strncmp(suffix, "H", 1))
1845 hsync2 *= 1000;
1846 } else if (!strncmp(this_opt, "vsync1:", 7))
1847 vsync1 = simple_strtoul(this_opt+7, NULL, 0);
1848 else if (!strncmp(this_opt, "vsync2:", 7))
1849 vsync2 = simple_strtoul(this_opt+7, NULL, 0);
1850 else if (!strncmp(this_opt, "dcolor", 6))
1851 dcolor = 1;
1852 }
1853 return 0;
1854}
1855#endif
1856
1857static int __devinit i810fb_init_pci (struct pci_dev *dev,
1858 const struct pci_device_id *entry)
1859{
1860 struct fb_info *info;
1861 struct i810fb_par *par = NULL;
1862 int i, err = -1, vfreq, hfreq, pixclock;
1863
1864 i = 0;
1865
1866 info = framebuffer_alloc(sizeof(struct i810fb_par), &dev->dev);
1867 if (!info)
1868 return -ENOMEM;
1869
1870 par = (struct i810fb_par *) info->par;
1871 par->dev = dev;
1872
1873 if (!(info->pixmap.addr = kmalloc(8*1024, GFP_KERNEL))) {
1874 i810fb_release_resource(info, par);
1875 return -ENOMEM;
1876 }
1877 memset(info->pixmap.addr, 0, 8*1024);
1878 info->pixmap.size = 8*1024;
1879 info->pixmap.buf_align = 8;
1880 info->pixmap.flags = FB_PIXMAP_SYSTEM;
1881
1882 if ((err = i810_allocate_pci_resource(par, entry))) {
1883 i810fb_release_resource(info, par);
1884 return err;
1885 }
1886
1887 i810_init_defaults(par, info);
1888
1889 if ((err = i810_alloc_agp_mem(info))) {
1890 i810fb_release_resource(info, par);
1891 return err;
1892 }
1893
1894 i810_init_device(par);
1895
1896 info->screen_base = par->fb.virtual;
1897 info->fbops = &par->i810fb_ops;
1898 info->pseudo_palette = par->pseudo_palette;
1899 fb_alloc_cmap(&info->cmap, 256, 0);
1900
1901 if ((err = info->fbops->fb_check_var(&info->var, info))) {
1902 i810fb_release_resource(info, par);
1903 return err;
1904 }
1905 encode_fix(&info->fix, info);
1906
1907 i810fb_init_ringbuffer(info);
1908 err = register_framebuffer(info);
1909 if (err < 0) {
1910 i810fb_release_resource(info, par);
1911 printk("i810fb_init: cannot register framebuffer device\n");
1912 return err;
1913 }
1914
1915 pci_set_drvdata(dev, info);
1916 pixclock = 1000000000/(info->var.pixclock);
1917 pixclock *= 1000;
1918 hfreq = pixclock/(info->var.xres + info->var.left_margin +
1919 info->var.hsync_len + info->var.right_margin);
1920 vfreq = hfreq/(info->var.yres + info->var.upper_margin +
1921 info->var.vsync_len + info->var.lower_margin);
1922
1923 printk("I810FB: fb%d : %s v%d.%d.%d%s\n"
1924 "I810FB: Video RAM : %dK\n"
1925 "I810FB: Monitor : H: %d-%d KHz V: %d-%d Hz\n"
1926 "I810FB: Mode : %dx%d-%dbpp@%dHz\n",
1927 info->node,
1928 i810_pci_list[entry->driver_data],
1929 VERSION_MAJOR, VERSION_MINOR, VERSION_TEENIE, BRANCH_VERSION,
1930 (int) par->fb.size>>10, info->monspecs.hfmin/1000,
1931 info->monspecs.hfmax/1000, info->monspecs.vfmin,
1932 info->monspecs.vfmax, info->var.xres,
1933 info->var.yres, info->var.bits_per_pixel, vfreq);
1934 return 0;
1935}
1936
1937/***************************************************************
1938 * De-initialization *
1939 ***************************************************************/
1940
1941static void i810fb_release_resource(struct fb_info *info,
1942 struct i810fb_par *par)
1943{
1944 struct gtt_data *gtt = &par->i810_gtt;
1945 unset_mtrr(par);
1946
1947 if (par->i810_gtt.i810_cursor_memory)
1948 agp_free_memory(gtt->i810_cursor_memory);
1949 if (par->i810_gtt.i810_fb_memory)
1950 agp_free_memory(gtt->i810_fb_memory);
1951
1952 if (par->mmio_start_virtual)
1953 iounmap(par->mmio_start_virtual);
1954 if (par->aperture.virtual)
1955 iounmap(par->aperture.virtual);
1956
1957 if (par->res_flags & FRAMEBUFFER_REQ)
1958 release_mem_region(par->aperture.physical,
1959 par->aperture.size);
1960 if (par->res_flags & MMIO_REQ)
1961 release_mem_region(par->mmio_start_phys, MMIO_SIZE);
1962
1963 if (par->res_flags & PCI_DEVICE_ENABLED)
1964 pci_disable_device(par->dev);
1965
1966 framebuffer_release(info);
1967
1968}
1969
1970static void __exit i810fb_remove_pci(struct pci_dev *dev)
1971{
1972 struct fb_info *info = pci_get_drvdata(dev);
1973 struct i810fb_par *par = (struct i810fb_par *) info->par;
1974
1975 unregister_framebuffer(info);
1976 i810fb_release_resource(info, par);
1977 pci_set_drvdata(dev, NULL);
1978 printk("cleanup_module: unloaded i810 framebuffer device\n");
1979}
1980
1981#ifndef MODULE
1982static int __init i810fb_init(void)
1983{
1984 char *option = NULL;
1985
1986 if (fb_get_options("i810fb", &option))
1987 return -ENODEV;
1988 i810fb_setup(option);
1989
1990 return pci_register_driver(&i810fb_driver);
1991}
1992#endif
1993
1994/*********************************************************************
1995 * Modularization *
1996 *********************************************************************/
1997
1998#ifdef MODULE
1999
2000static int __init i810fb_init(void)
2001{
2002 hsync1 *= 1000;
2003 hsync2 *= 1000;
2004
2005 return pci_register_driver(&i810fb_driver);
2006}
2007
2008module_param(vram, int, 0);
2009MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB"
2010 " (default=4)");
2011module_param(voffset, int, 0);
2012MODULE_PARM_DESC(voffset, "at what offset to place start of framebuffer "
2013 "memory (0 to maximum aperture size), in MiB (default = 48)");
2014module_param(bpp, int, 0);
2015MODULE_PARM_DESC(bpp, "Color depth for display in bits per pixel"
2016 " (default = 8)");
2017module_param(xres, int, 0);
2018MODULE_PARM_DESC(xres, "Horizontal resolution in pixels (default = 640)");
2019module_param(yres, int, 0);
2020MODULE_PARM_DESC(yres, "Vertical resolution in scanlines (default = 480)");
2021module_param(vyres,int, 0);
2022MODULE_PARM_DESC(vyres, "Virtual vertical resolution in scanlines"
2023 " (default = 480)");
2024module_param(hsync1, int, 0);
2025MODULE_PARM_DESC(hsync1, "Minimum horizontal frequency of monitor in KHz"
2026 " (default = 31)");
2027module_param(hsync2, int, 0);
2028MODULE_PARM_DESC(hsync2, "Maximum horizontal frequency of monitor in KHz"
2029 " (default = 31)");
2030module_param(vsync1, int, 0);
2031MODULE_PARM_DESC(vsync1, "Minimum vertical frequency of monitor in Hz"
2032 " (default = 50)");
2033module_param(vsync2, int, 0);
2034MODULE_PARM_DESC(vsync2, "Maximum vertical frequency of monitor in Hz"
2035 " (default = 60)");
2036module_param(accel, bool, 0);
2037MODULE_PARM_DESC(accel, "Use Acceleration (BLIT) engine (default = 0)");
2038module_param(mtrr, bool, 0);
2039MODULE_PARM_DESC(mtrr, "Use MTRR (default = 0)");
2040module_param(ext_vga, bool, 0);
2041MODULE_PARM_DESC(ext_vga, "Enable external VGA connector (default = 0)");
2042module_param(sync, bool, 0);
2043MODULE_PARM_DESC(sync, "wait for accel engine to finish drawing"
2044 " (default = 0)");
2045module_param(dcolor, bool, 0);
2046MODULE_PARM_DESC(dcolor, "use DirectColor visuals"
2047 " (default = 0 = TrueColor)");
2048
2049MODULE_AUTHOR("Tony A. Daplas");
2050MODULE_DESCRIPTION("Framebuffer device for the Intel 810/815 and"
2051 " compatible cards");
2052MODULE_LICENSE("GPL");
2053
2054static void __exit i810fb_exit(void)
2055{
2056 pci_unregister_driver(&i810fb_driver);
2057}
2058module_exit(i810fb_exit);
2059
2060#endif /* MODULE */
2061
2062module_init(i810fb_init);
diff --git a/drivers/video/i810/i810_main.h b/drivers/video/i810/i810_main.h
new file mode 100644
index 000000000000..43b4297b4d48
--- /dev/null
+++ b/drivers/video/i810/i810_main.h
@@ -0,0 +1,127 @@
1/*-*- linux-c -*-
2 * linux/drivers/video/i810fb_main.h -- Intel 810 frame buffer device
3 * main header file
4 *
5 * Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
6 * All Rights Reserved
7 *
8 *
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file COPYING in the main directory of this archive for
11 * more details.
12 */
13
14#ifndef __I810_MAIN_H__
15#define __I810_MAIN_H__
16
17static int __devinit i810fb_init_pci (struct pci_dev *dev,
18 const struct pci_device_id *entry);
19static void __exit i810fb_remove_pci(struct pci_dev *dev);
20static int i810fb_resume(struct pci_dev *dev);
21static int i810fb_suspend(struct pci_dev *dev, pm_message_t state);
22
23/*
24 * voffset - framebuffer offset in MiB from aperture start address. In order for
25 * the driver to work with X, we must try to use memory holes left untouched by X. The
26 * following table lists where X's different surfaces start at.
27 *
28 * ---------------------------------------------
29 * : : 64 MiB : 32 MiB :
30 * ----------------------------------------------
31 * : FrontBuffer : 0 : 0 :
32 * : DepthBuffer : 48 : 16 :
33 * : BackBuffer : 56 : 24 :
34 * ----------------------------------------------
35 *
36 * So for chipsets with 64 MiB Aperture sizes, 32 MiB for v_offset is okay, allowing up to
37 * 15 + 1 MiB of Framebuffer memory. For 32 MiB Aperture sizes, a v_offset of 8 MiB should
38 * work, allowing 7 + 1 MiB of Framebuffer memory.
39 * Note, the size of the hole may change depending on how much memory you allocate to X,
40 * and how the memory is split up between these surfaces.
41 *
42 * Note: Anytime the DepthBuffer or FrontBuffer is overlapped, X would still run but with
43 * DRI disabled. But if the Frontbuffer is overlapped, X will fail to load.
44 *
45 * Experiment with v_offset to find out which works best for you.
46 */
47static u32 v_offset_default __initdata; /* For 32 MiB Aper size, 8 should be the default */
48static u32 voffset __initdata = 0;
49
50static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
51
52/* Chipset Specific Functions */
53static int i810fb_set_par (struct fb_info *info);
54static int i810fb_getcolreg (u8 regno, u8 *red, u8 *green, u8 *blue,
55 u8 *transp, struct fb_info *info);
56static int i810fb_setcolreg (unsigned regno, unsigned red, unsigned green, unsigned blue,
57 unsigned transp, struct fb_info *info);
58static int i810fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
59static int i810fb_blank (int blank_mode, struct fb_info *info);
60
61/* Initialization */
62static void i810fb_release_resource (struct fb_info *info, struct i810fb_par *par);
63extern int __init agp_intel_init(void);
64
65
66/* Video Timings */
67extern void round_off_xres (u32 *xres);
68extern void round_off_yres (u32 *xres, u32 *yres);
69extern u32 i810_get_watermark (const struct fb_var_screeninfo *var,
70 struct i810fb_par *par);
71extern void i810fb_encode_registers(const struct fb_var_screeninfo *var,
72 struct i810fb_par *par, u32 xres, u32 yres);
73extern void i810fb_fill_var_timings(struct fb_var_screeninfo *var);
74
75/* Accelerated Functions */
76extern void i810fb_fillrect (struct fb_info *p,
77 const struct fb_fillrect *rect);
78extern void i810fb_copyarea (struct fb_info *p,
79 const struct fb_copyarea *region);
80extern void i810fb_imageblit(struct fb_info *p, const struct fb_image *image);
81extern int i810fb_sync (struct fb_info *p);
82
83extern void i810fb_init_ringbuffer(struct fb_info *info);
84extern void i810fb_load_front (u32 offset, struct fb_info *info);
85
86/* Conditionals */
87#ifdef CONFIG_X86
88inline void flush_cache(void)
89{
90 asm volatile ("wbinvd":::"memory");
91}
92#else
93#define flush_cache() do { } while(0)
94#endif
95
96#ifdef CONFIG_MTRR
97#define KERNEL_HAS_MTRR 1
98static inline void __devinit set_mtrr(struct i810fb_par *par)
99{
100 par->mtrr_reg = mtrr_add((u32) par->aperture.physical,
101 par->aperture.size, MTRR_TYPE_WRCOMB, 1);
102 if (par->mtrr_reg < 0) {
103 printk(KERN_ERR "set_mtrr: unable to set MTRR\n");
104 return;
105 }
106 par->dev_flags |= HAS_MTRR;
107}
108static inline void unset_mtrr(struct i810fb_par *par)
109{
110 if (par->dev_flags & HAS_MTRR)
111 mtrr_del(par->mtrr_reg, (u32) par->aperture.physical,
112 par->aperture.size);
113}
114#else
115#define KERNEL_HAS_MTRR 0
116#define set_mtrr(x) printk("set_mtrr: MTRR is disabled in the kernel\n")
117
118#define unset_mtrr(x) do { } while (0)
119#endif /* CONFIG_MTRR */
120
121#ifdef CONFIG_FB_I810_GTF
122#define IS_DVT (0)
123#else
124#define IS_DVT (1)
125#endif
126
127#endif /* __I810_MAIN_H__ */
diff --git a/drivers/video/i810/i810_regs.h b/drivers/video/i810/i810_regs.h
new file mode 100644
index 000000000000..6e4b9afa4d98
--- /dev/null
+++ b/drivers/video/i810/i810_regs.h
@@ -0,0 +1,274 @@
1/*-*- linux-c -*-
2 * linux/drivers/video/i810_regs.h -- Intel 810/815 Register List
3 *
4 * Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
5 * All Rights Reserved
6 *
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file COPYING in the main directory of this archive for
10 * more details.
11 */
12
13
14/*
15 * Intel 810 Chipset Family PRM 15 3.1
16 * GC Register Memory Address Map
17 *
18 * Based on:
19 * Intel (R) 810 Chipset Family
20 * Programmer s Reference Manual
21 * November 1999
22 * Revision 1.0
23 * Order Number: 298026-001 R
24 *
25 * All GC registers are memory-mapped. In addition, the VGA and extended VGA registers
26 * are I/O mapped.
27 */
28
29#ifndef __I810_REGS_H__
30#define __I810_REGS_H__
31
32/* Instruction and Interrupt Control Registers (01000h 02FFFh) */
33#define FENCE 0x02000
34#define PGTBL_CTL 0x02020
35#define PGTBL_ER 0x02024
36#define LRING 0x02030
37#define IRING 0x02040
38#define HWS_PGA 0x02080
39#define IPEIR 0x02088
40#define IPEHR 0x0208C
41#define INSTDONE 0x02090
42#define NOPID 0x02094
43#define HWSTAM 0x02098
44#define IER 0x020A0
45#define IIR 0x020A4
46#define IMR 0x020A8
47#define ISR 0x020AC
48#define EIR 0x020B0
49#define EMR 0x020B4
50#define ESR 0x020B8
51#define INSTPM 0x020C0
52#define INSTPS 0x020C4
53#define BBP_PTR 0x020C8
54#define ABB_SRT 0x020CC
55#define ABB_END 0x020D0
56#define DMA_FADD 0x020D4
57#define FW_BLC 0x020D8
58#define MEM_MODE 0x020DC
59
60/* Memory Control Registers (03000h 03FFFh) */
61#define DRT 0x03000
62#define DRAMCL 0x03001
63#define DRAMCH 0x03002
64
65
66/* Span Cursor Registers (04000h 04FFFh) */
67#define UI_SC_CTL 0x04008
68
69/* I/O Control Registers (05000h 05FFFh) */
70#define HVSYNC 0x05000
71#define GPIOA 0x05010
72#define GPIOB 0x05014
73
74/* Clock Control and Power Management Registers (06000h 06FFFh) */
75#define DCLK_0D 0x06000
76#define DCLK_1D 0x06004
77#define DCLK_2D 0x06008
78#define LCD_CLKD 0x0600C
79#define DCLK_0DS 0x06010
80#define PWR_CLKC 0x06014
81
82/* Graphics Translation Table Range Definition (10000h 1FFFFh) */
83#define GTT 0x10000
84
85/* Overlay Registers (30000h 03FFFFh) */
86#define OVOADDR 0x30000
87#define DOVOSTA 0x30008
88#define GAMMA 0x30010
89#define OBUF_0Y 0x30100
90#define OBUF_1Y 0x30104
91#define OBUF_0U 0x30108
92#define OBUF_0V 0x3010C
93#define OBUF_1U 0x30110
94#define OBUF_1V 0x30114
95#define OVOSTRIDE 0x30118
96#define YRGB_VPH 0x3011C
97#define UV_VPH 0x30120
98#define HORZ_PH 0x30124
99#define INIT_PH 0x30128
100#define DWINPOS 0x3012C
101#define DWINSZ 0x30130
102#define SWID 0x30134
103#define SWIDQW 0x30138
104#define SHEIGHT 0x3013F
105#define YRGBSCALE 0x30140
106#define UVSCALE 0x30144
107#define OVOCLRCO 0x30148
108#define OVOCLRC1 0x3014C
109#define DCLRKV 0x30150
110#define DLCRKM 0x30154
111#define SCLRKVH 0x30158
112#define SCLRKVL 0x3015C
113#define SCLRKM 0x30160
114#define OVOCONF 0x30164
115#define OVOCMD 0x30168
116#define AWINPOS 0x30170
117#define AWINZ 0x30174
118
119/* BLT Engine Status (40000h 4FFFFh) (Software Debug) */
120#define BR00 0x40000
121#define BRO1 0x40004
122#define BR02 0x40008
123#define BR03 0x4000C
124#define BR04 0x40010
125#define BR05 0x40014
126#define BR06 0x40018
127#define BR07 0x4001C
128#define BR08 0x40020
129#define BR09 0x40024
130#define BR10 0x40028
131#define BR11 0x4002C
132#define BR12 0x40030
133#define BR13 0x40034
134#define BR14 0x40038
135#define BR15 0x4003C
136#define BR16 0x40040
137#define BR17 0x40044
138#define BR18 0x40048
139#define BR19 0x4004C
140#define SSLADD 0x40074
141#define DSLH 0x40078
142#define DSLRADD 0x4007C
143
144
145/* LCD/TV-Out and HW DVD Registers (60000h 6FFFFh) */
146/* LCD/TV-Out */
147#define HTOTAL 0x60000
148#define HBLANK 0x60004
149#define HSYNC 0x60008
150#define VTOTAL 0x6000C
151#define VBLANK 0x60010
152#define VSYNC 0x60014
153#define LCDTV_C 0x60018
154#define OVRACT 0x6001C
155#define BCLRPAT 0x60020
156
157/* Display and Cursor Control Registers (70000h 7FFFFh) */
158#define DISP_SL 0x70000
159#define DISP_SLC 0x70004
160#define PIXCONF 0x70008
161#define PIXCONF1 0x70009
162#define BLTCNTL 0x7000C
163#define SWF 0x70014
164#define DPLYBASE 0x70020
165#define DPLYSTAS 0x70024
166#define CURCNTR 0x70080
167#define CURBASE 0x70084
168#define CURPOS 0x70088
169
170
171/* VGA Registers */
172
173/* SMRAM Registers */
174#define SMRAM 0x10
175
176/* Graphics Control Registers */
177#define GR_INDEX 0x3CE
178#define GR_DATA 0x3CF
179
180#define GR10 0x10
181#define GR11 0x11
182
183/* CRT Controller Registers */
184#define CR_INDEX_MDA 0x3B4
185#define CR_INDEX_CGA 0x3D4
186#define CR_DATA_MDA 0x3B5
187#define CR_DATA_CGA 0x3D5
188
189#define CR30 0x30
190#define CR31 0x31
191#define CR32 0x32
192#define CR33 0x33
193#define CR35 0x35
194#define CR39 0x39
195#define CR40 0x40
196#define CR41 0x41
197#define CR42 0x42
198#define CR70 0x70
199#define CR80 0x80
200#define CR81 0x82
201
202/* Extended VGA Registers */
203
204/* General Control and Status Registers */
205#define ST00 0x3C2
206#define ST01_MDA 0x3BA
207#define ST01_CGA 0x3DA
208#define FRC_READ 0x3CA
209#define FRC_WRITE_MDA 0x3BA
210#define FRC_WRITE_CGA 0x3DA
211#define MSR_READ 0x3CC
212#define MSR_WRITE 0x3C2
213
214/* Sequencer Registers */
215#define SR_INDEX 0x3C4
216#define SR_DATA 0x3C5
217
218#define SR01 0x01
219#define SR02 0x02
220#define SR03 0x03
221#define SR04 0x04
222#define SR07 0x07
223
224/* Graphics Controller Registers */
225#define GR00 0x00
226#define GR01 0x01
227#define GR02 0x02
228#define GR03 0x03
229#define GR04 0x04
230#define GR05 0x05
231#define GR06 0x06
232#define GR07 0x07
233#define GR08 0x08
234
235/* Attribute Controller Registers */
236#define ATTR_WRITE 0x3C0
237#define ATTR_READ 0x3C1
238
239/* VGA Color Palette Registers */
240
241/* CLUT */
242#define CLUT_DATA 0x3C9 /* DACDATA */
243#define CLUT_INDEX_READ 0x3C7 /* DACRX */
244#define CLUT_INDEX_WRITE 0x3C8 /* DACWX */
245#define DACMASK 0x3C6
246
247/* CRT Controller Registers */
248#define CR00 0x00
249#define CR01 0x01
250#define CR02 0x02
251#define CR03 0x03
252#define CR04 0x04
253#define CR05 0x05
254#define CR06 0x06
255#define CR07 0x07
256#define CR08 0x08
257#define CR09 0x09
258#define CR0A 0x0A
259#define CR0B 0x0B
260#define CR0C 0x0C
261#define CR0D 0x0D
262#define CR0E 0x0E
263#define CR0F 0x0F
264#define CR10 0x10
265#define CR11 0x11
266#define CR12 0x12
267#define CR13 0x13
268#define CR14 0x14
269#define CR15 0x15
270#define CR16 0x16
271#define CR17 0x17
272#define CR18 0x18
273
274#endif /* __I810_REGS_H__ */