aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/fbdev/intelfb
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2014-02-13 08:31:38 -0500
committerTomi Valkeinen <tomi.valkeinen@ti.com>2014-04-17 01:10:19 -0400
commitf7018c21350204c4cf628462f229d44d03545254 (patch)
tree408787177164cf51cc06f7aabdb04fcff8d2b6aa /drivers/video/fbdev/intelfb
parentc26ef3eb3c11274bad1b64498d0a134f85755250 (diff)
video: move fbdev to drivers/video/fbdev
The drivers/video directory is a mess. It contains generic video related files, directories for backlight, console, linux logo, lots of fbdev device drivers, fbdev framework files. Make some order into the chaos by creating drivers/video/fbdev directory, and move all fbdev related files there. No functionality is changed, although I guess it is possible that some subtle Makefile build order related issue could be created by this patch. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Geert Uytterhoeven <geert@linux-m68k.org> Acked-by: Rob Clark <robdclark@gmail.com> Acked-by: Jingoo Han <jg1.han@samsung.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/video/fbdev/intelfb')
-rw-r--r--drivers/video/fbdev/intelfb/Makefile7
-rw-r--r--drivers/video/fbdev/intelfb/intelfb.h383
-rw-r--r--drivers/video/fbdev/intelfb/intelfb_i2c.c209
-rw-r--r--drivers/video/fbdev/intelfb/intelfbdrv.c1704
-rw-r--r--drivers/video/fbdev/intelfb/intelfbhw.c2121
-rw-r--r--drivers/video/fbdev/intelfb/intelfbhw.h609
6 files changed, 5033 insertions, 0 deletions
diff --git a/drivers/video/fbdev/intelfb/Makefile b/drivers/video/fbdev/intelfb/Makefile
new file mode 100644
index 000000000000..f7d631ebee8e
--- /dev/null
+++ b/drivers/video/fbdev/intelfb/Makefile
@@ -0,0 +1,7 @@
1obj-$(CONFIG_FB_INTEL) += intelfb.o
2
3intelfb-y := intelfbdrv.o intelfbhw.o
4intelfb-$(CONFIG_FB_INTEL_I2C) += intelfb_i2c.o
5intelfb-objs := $(intelfb-y)
6
7ccflags-$(CONFIG_FB_INTEL_DEBUG) := -DDEBUG -DREGDUMP
diff --git a/drivers/video/fbdev/intelfb/intelfb.h b/drivers/video/fbdev/intelfb/intelfb.h
new file mode 100644
index 000000000000..6b51175629c7
--- /dev/null
+++ b/drivers/video/fbdev/intelfb/intelfb.h
@@ -0,0 +1,383 @@
1#ifndef _INTELFB_H
2#define _INTELFB_H
3
4/* $DHD: intelfb/intelfb.h,v 1.40 2003/06/27 15:06:25 dawes Exp $ */
5
6#include <linux/agp_backend.h>
7#include <linux/fb.h>
8
9#ifdef CONFIG_FB_INTEL_I2C
10#include <linux/i2c.h>
11#include <linux/i2c-algo-bit.h>
12#endif
13
14/*** Version/name ***/
15#define INTELFB_VERSION "0.9.6"
16#define INTELFB_MODULE_NAME "intelfb"
17#define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/945GME/965G/965GM"
18
19
20/*** Debug/feature defines ***/
21
22#ifndef DEBUG
23#define DEBUG 0
24#endif
25
26#ifndef VERBOSE
27#define VERBOSE 0
28#endif
29
30#ifndef REGDUMP
31#define REGDUMP 0
32#endif
33
34#ifndef DETECT_VGA_CLASS_ONLY
35#define DETECT_VGA_CLASS_ONLY 1
36#endif
37
38#ifndef ALLOCATE_FOR_PANNING
39#define ALLOCATE_FOR_PANNING 1
40#endif
41
42#ifndef PREFERRED_MODE
43#define PREFERRED_MODE "1024x768-32@70"
44#endif
45
46/*** hw-related values ***/
47
48/* Resource Allocation */
49#define INTELFB_FB_ACQUIRED 1
50#define INTELFB_MMIO_ACQUIRED 2
51
52/* PCI ids for supported devices */
53#define PCI_DEVICE_ID_INTEL_830M 0x3577
54#define PCI_DEVICE_ID_INTEL_845G 0x2562
55#define PCI_DEVICE_ID_INTEL_85XGM 0x3582
56#define PCI_DEVICE_ID_INTEL_854 0x358E
57#define PCI_DEVICE_ID_INTEL_865G 0x2572
58#define PCI_DEVICE_ID_INTEL_915G 0x2582
59#define PCI_DEVICE_ID_INTEL_915GM 0x2592
60#define PCI_DEVICE_ID_INTEL_945G 0x2772
61#define PCI_DEVICE_ID_INTEL_945GM 0x27A2
62#define PCI_DEVICE_ID_INTEL_945GME 0x27AE
63#define PCI_DEVICE_ID_INTEL_965G 0x29A2
64#define PCI_DEVICE_ID_INTEL_965GM 0x2A02
65
66/* Size of MMIO region */
67#define INTEL_REG_SIZE 0x80000
68
69#define STRIDE_ALIGNMENT 16
70#define STRIDE_ALIGNMENT_I9XX 64
71
72#define PALETTE_8_ENTRIES 256
73
74
75/*** Macros ***/
76
77/* basic arithmetic */
78#define KB(x) ((x) * 1024)
79#define MB(x) ((x) * 1024 * 1024)
80#define BtoKB(x) ((x) / 1024)
81#define BtoMB(x) ((x) / 1024 / 1024)
82
83#define GTT_PAGE_SIZE KB(4)
84
85#define ROUND_UP_TO(x, y) (((x) + (y) - 1) / (y) * (y))
86#define ROUND_DOWN_TO(x, y) ((x) / (y) * (y))
87#define ROUND_UP_TO_PAGE(x) ROUND_UP_TO((x), GTT_PAGE_SIZE)
88#define ROUND_DOWN_TO_PAGE(x) ROUND_DOWN_TO((x), GTT_PAGE_SIZE)
89
90/* messages */
91#define PFX INTELFB_MODULE_NAME ": "
92
93#define ERR_MSG(fmt, args...) printk(KERN_ERR PFX fmt, ## args)
94#define WRN_MSG(fmt, args...) printk(KERN_WARNING PFX fmt, ## args)
95#define NOT_MSG(fmt, args...) printk(KERN_NOTICE PFX fmt, ## args)
96#define INF_MSG(fmt, args...) printk(KERN_INFO PFX fmt, ## args)
97#if DEBUG
98#define DBG_MSG(fmt, args...) printk(KERN_DEBUG PFX fmt, ## args)
99#else
100#define DBG_MSG(fmt, args...) while (0) printk(fmt, ## args)
101#endif
102
103/* get commonly used pointers */
104#define GET_DINFO(info) (info)->par
105
106/* misc macros */
107#define ACCEL(d, i) \
108 ((d)->accel && !(d)->ring_lockup && \
109 ((i)->var.accel_flags & FB_ACCELF_TEXT))
110
111/*#define NOACCEL_CHIPSET(d) \
112 ((d)->chipset != INTEL_865G)*/
113#define NOACCEL_CHIPSET(d) \
114 (0)
115
116#define FIXED_MODE(d) ((d)->fixed_mode)
117
118/*** Driver parameters ***/
119
120#define RINGBUFFER_SIZE KB(64)
121#define HW_CURSOR_SIZE KB(4)
122
123/* Intel agpgart driver */
124#define AGP_PHYSICAL_MEMORY 2
125
126/* store information about an Ixxx DVO */
127/* The i830->i865 use multiple DVOs with multiple i2cs */
128/* the i915, i945 have a single sDVO i2c bus - which is different */
129#define MAX_OUTPUTS 6
130
131/* these are outputs from the chip - integrated only
132 external chips are via DVO or SDVO output */
133#define INTELFB_OUTPUT_UNUSED 0
134#define INTELFB_OUTPUT_ANALOG 1
135#define INTELFB_OUTPUT_DVO 2
136#define INTELFB_OUTPUT_SDVO 3
137#define INTELFB_OUTPUT_LVDS 4
138#define INTELFB_OUTPUT_TVOUT 5
139
140#define INTELFB_DVO_CHIP_NONE 0
141#define INTELFB_DVO_CHIP_LVDS 1
142#define INTELFB_DVO_CHIP_TMDS 2
143#define INTELFB_DVO_CHIP_TVOUT 4
144
145#define INTELFB_OUTPUT_PIPE_NC 0
146#define INTELFB_OUTPUT_PIPE_A 1
147#define INTELFB_OUTPUT_PIPE_B 2
148
149/*** Data Types ***/
150
151/* supported chipsets */
152enum intel_chips {
153 INTEL_830M,
154 INTEL_845G,
155 INTEL_85XGM,
156 INTEL_852GM,
157 INTEL_852GME,
158 INTEL_854,
159 INTEL_855GM,
160 INTEL_855GME,
161 INTEL_865G,
162 INTEL_915G,
163 INTEL_915GM,
164 INTEL_945G,
165 INTEL_945GM,
166 INTEL_945GME,
167 INTEL_965G,
168 INTEL_965GM,
169};
170
171struct intelfb_hwstate {
172 u32 vga0_divisor;
173 u32 vga1_divisor;
174 u32 vga_pd;
175 u32 dpll_a;
176 u32 dpll_b;
177 u32 fpa0;
178 u32 fpa1;
179 u32 fpb0;
180 u32 fpb1;
181 u32 palette_a[PALETTE_8_ENTRIES];
182 u32 palette_b[PALETTE_8_ENTRIES];
183 u32 htotal_a;
184 u32 hblank_a;
185 u32 hsync_a;
186 u32 vtotal_a;
187 u32 vblank_a;
188 u32 vsync_a;
189 u32 src_size_a;
190 u32 bclrpat_a;
191 u32 htotal_b;
192 u32 hblank_b;
193 u32 hsync_b;
194 u32 vtotal_b;
195 u32 vblank_b;
196 u32 vsync_b;
197 u32 src_size_b;
198 u32 bclrpat_b;
199 u32 adpa;
200 u32 dvoa;
201 u32 dvob;
202 u32 dvoc;
203 u32 dvoa_srcdim;
204 u32 dvob_srcdim;
205 u32 dvoc_srcdim;
206 u32 lvds;
207 u32 pipe_a_conf;
208 u32 pipe_b_conf;
209 u32 disp_arb;
210 u32 cursor_a_control;
211 u32 cursor_b_control;
212 u32 cursor_a_base;
213 u32 cursor_b_base;
214 u32 cursor_size;
215 u32 disp_a_ctrl;
216 u32 disp_b_ctrl;
217 u32 disp_a_base;
218 u32 disp_b_base;
219 u32 cursor_a_palette[4];
220 u32 cursor_b_palette[4];
221 u32 disp_a_stride;
222 u32 disp_b_stride;
223 u32 vgacntrl;
224 u32 add_id;
225 u32 swf0x[7];
226 u32 swf1x[7];
227 u32 swf3x[3];
228 u32 fence[8];
229 u32 instpm;
230 u32 mem_mode;
231 u32 fw_blc_0;
232 u32 fw_blc_1;
233 u16 hwstam;
234 u16 ier;
235 u16 iir;
236 u16 imr;
237};
238
239struct intelfb_heap_data {
240 u32 physical;
241 u8 __iomem *virtual;
242 u32 offset; /* in GATT pages */
243 u32 size; /* in bytes */
244};
245
246#ifdef CONFIG_FB_INTEL_I2C
247struct intelfb_i2c_chan {
248 struct intelfb_info *dinfo;
249 u32 reg;
250 struct i2c_adapter adapter;
251 struct i2c_algo_bit_data algo;
252};
253#endif
254
255struct intelfb_output_rec {
256 int type;
257 int pipe;
258 int flags;
259
260#ifdef CONFIG_FB_INTEL_I2C
261 struct intelfb_i2c_chan i2c_bus;
262 struct intelfb_i2c_chan ddc_bus;
263#endif
264};
265
266struct intelfb_vsync {
267 wait_queue_head_t wait;
268 unsigned int count;
269 int pan_display;
270 u32 pan_offset;
271};
272
273struct intelfb_info {
274 struct fb_info *info;
275 struct fb_ops *fbops;
276 struct pci_dev *pdev;
277
278 struct intelfb_hwstate save_state;
279
280 /* agpgart structs */
281 struct agp_memory *gtt_fb_mem; /* use all stolen memory or vram */
282 struct agp_memory *gtt_ring_mem; /* ring buffer */
283 struct agp_memory *gtt_cursor_mem; /* hw cursor */
284
285 /* use a gart reserved fb mem */
286 u8 fbmem_gart;
287
288 /* mtrr support */
289 int mtrr_reg;
290 u32 has_mtrr;
291
292 /* heap data */
293 struct intelfb_heap_data aperture;
294 struct intelfb_heap_data fb;
295 struct intelfb_heap_data ring;
296 struct intelfb_heap_data cursor;
297
298 /* mmio regs */
299 u32 mmio_base_phys;
300 u8 __iomem *mmio_base;
301
302 /* fb start offset (in bytes) */
303 u32 fb_start;
304
305 /* ring buffer */
306 u32 ring_head;
307 u32 ring_tail;
308 u32 ring_tail_mask;
309 u32 ring_space;
310 u32 ring_lockup;
311
312 /* palette */
313 u32 pseudo_palette[16];
314
315 /* chip info */
316 int pci_chipset;
317 int chipset;
318 const char *name;
319 int mobile;
320
321 /* current mode */
322 int bpp, depth;
323 u32 visual;
324 int xres, yres, pitch;
325 int pixclock;
326
327 /* current pipe */
328 int pipe;
329
330 /* some flags */
331 int accel;
332 int hwcursor;
333 int fixed_mode;
334 int ring_active;
335 int flag;
336 unsigned long irq_flags;
337 int open;
338
339 /* vsync */
340 struct intelfb_vsync vsync;
341 spinlock_t int_lock;
342
343 /* hw cursor */
344 int cursor_on;
345 int cursor_blanked;
346 u8 cursor_src[64];
347
348 /* initial parameters */
349 int initial_vga;
350 struct fb_var_screeninfo initial_var;
351 u32 initial_fb_base;
352 u32 initial_video_ram;
353 u32 initial_pitch;
354
355 /* driver registered */
356 int registered;
357
358 /* index into plls */
359 int pll_index;
360
361 /* outputs */
362 int num_outputs;
363 struct intelfb_output_rec output[MAX_OUTPUTS];
364};
365
366#define IS_I9XX(dinfo) (((dinfo)->chipset == INTEL_915G) || \
367 ((dinfo)->chipset == INTEL_915GM) || \
368 ((dinfo)->chipset == INTEL_945G) || \
369 ((dinfo)->chipset == INTEL_945GM) || \
370 ((dinfo)->chipset == INTEL_945GME) || \
371 ((dinfo)->chipset == INTEL_965G) || \
372 ((dinfo)->chipset == INTEL_965GM))
373
374/*** function prototypes ***/
375
376extern int intelfb_var_to_depth(const struct fb_var_screeninfo *var);
377
378#ifdef CONFIG_FB_INTEL_I2C
379extern void intelfb_create_i2c_busses(struct intelfb_info *dinfo);
380extern void intelfb_delete_i2c_busses(struct intelfb_info *dinfo);
381#endif
382
383#endif /* _INTELFB_H */
diff --git a/drivers/video/fbdev/intelfb/intelfb_i2c.c b/drivers/video/fbdev/intelfb/intelfb_i2c.c
new file mode 100644
index 000000000000..3300bd31d9d7
--- /dev/null
+++ b/drivers/video/fbdev/intelfb/intelfb_i2c.c
@@ -0,0 +1,209 @@
1/**************************************************************************
2
3 Copyright 2006 Dave Airlie <airlied@linux.ie>
4
5All Rights Reserved.
6
7Permission is hereby granted, free of charge, to any person obtaining a
8copy of this software and associated documentation files (the "Software"),
9to deal in the Software without restriction, including without limitation
10on the rights to use, copy, modify, merge, publish, distribute, sub
11license, and/or sell copies of the Software, and to permit persons to whom
12the Software is furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice (including the next
15paragraph) shall be included in all copies or substantial portions of the
16Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26**************************************************************************/
27
28#include <linux/module.h>
29#include <linux/kernel.h>
30#include <linux/delay.h>
31#include <linux/pci.h>
32#include <linux/fb.h>
33
34#include <linux/i2c.h>
35#include <linux/i2c-algo-bit.h>
36
37#include <asm/io.h>
38
39#include "intelfb.h"
40#include "intelfbhw.h"
41
42/* bit locations in the registers */
43#define SCL_DIR_MASK 0x0001
44#define SCL_DIR 0x0002
45#define SCL_VAL_MASK 0x0004
46#define SCL_VAL_OUT 0x0008
47#define SCL_VAL_IN 0x0010
48#define SDA_DIR_MASK 0x0100
49#define SDA_DIR 0x0200
50#define SDA_VAL_MASK 0x0400
51#define SDA_VAL_OUT 0x0800
52#define SDA_VAL_IN 0x1000
53
54static void intelfb_gpio_setscl(void *data, int state)
55{
56 struct intelfb_i2c_chan *chan = data;
57 struct intelfb_info *dinfo = chan->dinfo;
58 u32 val;
59
60 OUTREG(chan->reg, (state ? SCL_VAL_OUT : 0) |
61 SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK);
62 val = INREG(chan->reg);
63}
64
65static void intelfb_gpio_setsda(void *data, int state)
66{
67 struct intelfb_i2c_chan *chan = data;
68 struct intelfb_info *dinfo = chan->dinfo;
69 u32 val;
70
71 OUTREG(chan->reg, (state ? SDA_VAL_OUT : 0) |
72 SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK);
73 val = INREG(chan->reg);
74}
75
76static int intelfb_gpio_getscl(void *data)
77{
78 struct intelfb_i2c_chan *chan = data;
79 struct intelfb_info *dinfo = chan->dinfo;
80 u32 val;
81
82 OUTREG(chan->reg, SCL_DIR_MASK);
83 OUTREG(chan->reg, 0);
84 val = INREG(chan->reg);
85 return ((val & SCL_VAL_IN) != 0);
86}
87
88static int intelfb_gpio_getsda(void *data)
89{
90 struct intelfb_i2c_chan *chan = data;
91 struct intelfb_info *dinfo = chan->dinfo;
92 u32 val;
93
94 OUTREG(chan->reg, SDA_DIR_MASK);
95 OUTREG(chan->reg, 0);
96 val = INREG(chan->reg);
97 return ((val & SDA_VAL_IN) != 0);
98}
99
100static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo,
101 struct intelfb_i2c_chan *chan,
102 const u32 reg, const char *name,
103 int class)
104{
105 int rc;
106
107 chan->dinfo = dinfo;
108 chan->reg = reg;
109 snprintf(chan->adapter.name, sizeof(chan->adapter.name),
110 "intelfb %s", name);
111 chan->adapter.class = class;
112 chan->adapter.owner = THIS_MODULE;
113 chan->adapter.algo_data = &chan->algo;
114 chan->adapter.dev.parent = &chan->dinfo->pdev->dev;
115 chan->algo.setsda = intelfb_gpio_setsda;
116 chan->algo.setscl = intelfb_gpio_setscl;
117 chan->algo.getsda = intelfb_gpio_getsda;
118 chan->algo.getscl = intelfb_gpio_getscl;
119 chan->algo.udelay = 40;
120 chan->algo.timeout = 20;
121 chan->algo.data = chan;
122
123 i2c_set_adapdata(&chan->adapter, chan);
124
125 /* Raise SCL and SDA */
126 intelfb_gpio_setsda(chan, 1);
127 intelfb_gpio_setscl(chan, 1);
128 udelay(20);
129
130 rc = i2c_bit_add_bus(&chan->adapter);
131 if (rc == 0)
132 DBG_MSG("I2C bus %s registered.\n", name);
133 else
134 WRN_MSG("Failed to register I2C bus %s.\n", name);
135 return rc;
136}
137
138void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
139{
140 int i = 0;
141
142 /* everyone has at least a single analog output */
143 dinfo->num_outputs = 1;
144 dinfo->output[i].type = INTELFB_OUTPUT_ANALOG;
145
146 /* setup the DDC bus for analog output */
147 intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, GPIOA,
148 "CRTDDC_A", I2C_CLASS_DDC);
149 i++;
150
151 /* need to add the output busses for each device
152 - this function is very incomplete
153 - i915GM has LVDS and TVOUT for example
154 */
155 switch(dinfo->chipset) {
156 case INTEL_830M:
157 case INTEL_845G:
158 case INTEL_854:
159 case INTEL_855GM:
160 case INTEL_865G:
161 dinfo->output[i].type = INTELFB_OUTPUT_DVO;
162 intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus,
163 GPIOD, "DVODDC_D", I2C_CLASS_DDC);
164 intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus,
165 GPIOE, "DVOI2C_E", 0);
166 i++;
167 break;
168 case INTEL_915G:
169 case INTEL_915GM:
170 /* has some LVDS + tv-out */
171 case INTEL_945G:
172 case INTEL_945GM:
173 case INTEL_945GME:
174 case INTEL_965G:
175 case INTEL_965GM:
176 /* SDVO ports have a single control bus - 2 devices */
177 dinfo->output[i].type = INTELFB_OUTPUT_SDVO;
178 intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus,
179 GPIOE, "SDVOCTRL_E", 0);
180 /* TODO: initialize the SDVO */
181 /* I830SDVOInit(pScrn, i, DVOB); */
182 i++;
183
184 /* set up SDVOC */
185 dinfo->output[i].type = INTELFB_OUTPUT_SDVO;
186 dinfo->output[i].i2c_bus = dinfo->output[i - 1].i2c_bus;
187 /* TODO: initialize the SDVO */
188 /* I830SDVOInit(pScrn, i, DVOC); */
189 i++;
190 break;
191 }
192 dinfo->num_outputs = i;
193}
194
195void intelfb_delete_i2c_busses(struct intelfb_info *dinfo)
196{
197 int i;
198
199 for (i = 0; i < MAX_OUTPUTS; i++) {
200 if (dinfo->output[i].i2c_bus.dinfo) {
201 i2c_del_adapter(&dinfo->output[i].i2c_bus.adapter);
202 dinfo->output[i].i2c_bus.dinfo = NULL;
203 }
204 if (dinfo->output[i].ddc_bus.dinfo) {
205 i2c_del_adapter(&dinfo->output[i].ddc_bus.adapter);
206 dinfo->output[i].ddc_bus.dinfo = NULL;
207 }
208 }
209}
diff --git a/drivers/video/fbdev/intelfb/intelfbdrv.c b/drivers/video/fbdev/intelfb/intelfbdrv.c
new file mode 100644
index 000000000000..b847d530471a
--- /dev/null
+++ b/drivers/video/fbdev/intelfb/intelfbdrv.c
@@ -0,0 +1,1704 @@
1/*
2 * intelfb
3 *
4 * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM/
5 * 945G/945GM/945GME/965G/965GM integrated graphics chips.
6 *
7 * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
8 * 2004 Sylvain Meyer
9 * 2006 David Airlie
10 *
11 * This driver consists of two parts. The first part (intelfbdrv.c) provides
12 * the basic fbdev interfaces, is derived in part from the radeonfb and
13 * vesafb drivers, and is covered by the GPL. The second part (intelfbhw.c)
14 * provides the code to program the hardware. Most of it is derived from
15 * the i810/i830 XFree86 driver. The HW-specific code is covered here
16 * under a dual license (GPL and MIT/XFree86 license).
17 *
18 * Author: David Dawes
19 *
20 */
21
22/* $DHD: intelfb/intelfbdrv.c,v 1.20 2003/06/27 15:17:40 dawes Exp $ */
23
24/*
25 * Changes:
26 * 01/2003 - Initial driver (0.1.0), no mode switching, no acceleration.
27 * This initial version is a basic core that works a lot like
28 * the vesafb driver. It must be built-in to the kernel,
29 * and the initial video mode must be set with vga=XXX at
30 * boot time. (David Dawes)
31 *
32 * 01/2003 - Version 0.2.0: Mode switching added, colormap support
33 * implemented, Y panning, and soft screen blanking implemented.
34 * No acceleration yet. (David Dawes)
35 *
36 * 01/2003 - Version 0.3.0: fbcon acceleration support added. Module
37 * option handling added. (David Dawes)
38 *
39 * 01/2003 - Version 0.4.0: fbcon HW cursor support added. (David Dawes)
40 *
41 * 01/2003 - Version 0.4.1: Add auto-generation of built-in modes.
42 * (David Dawes)
43 *
44 * 02/2003 - Version 0.4.2: Add check for active non-CRT devices, and
45 * mode validation checks. (David Dawes)
46 *
47 * 02/2003 - Version 0.4.3: Check when the VC is in graphics mode so that
48 * acceleration is disabled while an XFree86 server is running.
49 * (David Dawes)
50 *
51 * 02/2003 - Version 0.4.4: Monitor DPMS support. (David Dawes)
52 *
53 * 02/2003 - Version 0.4.5: Basic XFree86 + fbdev working. (David Dawes)
54 *
55 * 02/2003 - Version 0.5.0: Modify to work with the 2.5.32 kernel as well
56 * as 2.4.x kernels. (David Dawes)
57 *
58 * 02/2003 - Version 0.6.0: Split out HW-specifics into a separate file.
59 * (David Dawes)
60 *
61 * 02/2003 - Version 0.7.0: Test on 852GM/855GM. Acceleration and HW
62 * cursor are disabled on this platform. (David Dawes)
63 *
64 * 02/2003 - Version 0.7.1: Test on 845G. Acceleration is disabled
65 * on this platform. (David Dawes)
66 *
67 * 02/2003 - Version 0.7.2: Test on 830M. Acceleration and HW
68 * cursor are disabled on this platform. (David Dawes)
69 *
70 * 02/2003 - Version 0.7.3: Fix 8-bit modes for mobile platforms
71 * (David Dawes)
72 *
73 * 02/2003 - Version 0.7.4: Add checks for FB and FBCON_HAS_CFB* configured
74 * in the kernel, and add mode bpp verification and default
75 * bpp selection based on which FBCON_HAS_CFB* are configured.
76 * (David Dawes)
77 *
78 * 02/2003 - Version 0.7.5: Add basic package/install scripts based on the
79 * DRI packaging scripts. (David Dawes)
80 *
81 * 04/2003 - Version 0.7.6: Fix typo that affects builds with SMP-enabled
82 * kernels. (David Dawes, reported by Anupam).
83 *
84 * 06/2003 - Version 0.7.7:
85 * Fix Makefile.kernel build problem (Tsutomu Yasuda).
86 * Fix mis-placed #endif (2.4.21 kernel).
87 *
88 * 09/2004 - Version 0.9.0 - by Sylvain Meyer
89 * Port to linux 2.6 kernel fbdev
90 * Fix HW accel and HW cursor on i845G
91 * Use of agpgart for fb memory reservation
92 * Add mtrr support
93 *
94 * 10/2004 - Version 0.9.1
95 * Use module_param instead of old MODULE_PARM
96 * Some cleanup
97 *
98 * 11/2004 - Version 0.9.2
99 * Add vram option to reserve more memory than stolen by BIOS
100 * Fix intelfbhw_pan_display typo
101 * Add __initdata annotations
102 *
103 * 04/2008 - Version 0.9.5
104 * Add support for 965G/965GM. (Maik Broemme <mbroemme@plusserver.de>)
105 *
106 * 08/2008 - Version 0.9.6
107 * Add support for 945GME. (Phil Endecott <spam_from_intelfb@chezphil.org>)
108 */
109
110#include <linux/module.h>
111#include <linux/kernel.h>
112#include <linux/errno.h>
113#include <linux/string.h>
114#include <linux/mm.h>
115#include <linux/slab.h>
116#include <linux/delay.h>
117#include <linux/fb.h>
118#include <linux/ioport.h>
119#include <linux/init.h>
120#include <linux/pci.h>
121#include <linux/vmalloc.h>
122#include <linux/pagemap.h>
123#include <linux/screen_info.h>
124
125#include <asm/io.h>
126
127#ifdef CONFIG_MTRR
128#include <asm/mtrr.h>
129#endif
130
131#include "intelfb.h"
132#include "intelfbhw.h"
133#include "../edid.h"
134
135static void get_initial_mode(struct intelfb_info *dinfo);
136static void update_dinfo(struct intelfb_info *dinfo,
137 struct fb_var_screeninfo *var);
138static int intelfb_open(struct fb_info *info, int user);
139static int intelfb_release(struct fb_info *info, int user);
140static int intelfb_check_var(struct fb_var_screeninfo *var,
141 struct fb_info *info);
142static int intelfb_set_par(struct fb_info *info);
143static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
144 unsigned blue, unsigned transp,
145 struct fb_info *info);
146
147static int intelfb_blank(int blank, struct fb_info *info);
148static int intelfb_pan_display(struct fb_var_screeninfo *var,
149 struct fb_info *info);
150
151static void intelfb_fillrect(struct fb_info *info,
152 const struct fb_fillrect *rect);
153static void intelfb_copyarea(struct fb_info *info,
154 const struct fb_copyarea *region);
155static void intelfb_imageblit(struct fb_info *info,
156 const struct fb_image *image);
157static int intelfb_cursor(struct fb_info *info,
158 struct fb_cursor *cursor);
159
160static int intelfb_sync(struct fb_info *info);
161
162static int intelfb_ioctl(struct fb_info *info,
163 unsigned int cmd, unsigned long arg);
164
165static int intelfb_pci_register(struct pci_dev *pdev,
166 const struct pci_device_id *ent);
167static void intelfb_pci_unregister(struct pci_dev *pdev);
168static int intelfb_set_fbinfo(struct intelfb_info *dinfo);
169
170/*
171 * Limiting the class to PCI_CLASS_DISPLAY_VGA prevents function 1 of the
172 * mobile chipsets from being registered.
173 */
174#if DETECT_VGA_CLASS_ONLY
175#define INTELFB_CLASS_MASK ~0 << 8
176#else
177#define INTELFB_CLASS_MASK 0
178#endif
179
180static struct pci_device_id intelfb_pci_table[] = {
181 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_830M, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_830M },
182 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_845G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_845G },
183 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_85XGM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_85XGM },
184 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_865G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_865G },
185 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_854, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_854 },
186 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915G },
187 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM },
188 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945G },
189 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GM },
190 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GME, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GME },
191 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965G },
192 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965GM },
193 { 0, }
194};
195
196/* Global data */
197static int num_registered = 0;
198
199/* fb ops */
200static struct fb_ops intel_fb_ops = {
201 .owner = THIS_MODULE,
202 .fb_open = intelfb_open,
203 .fb_release = intelfb_release,
204 .fb_check_var = intelfb_check_var,
205 .fb_set_par = intelfb_set_par,
206 .fb_setcolreg = intelfb_setcolreg,
207 .fb_blank = intelfb_blank,
208 .fb_pan_display = intelfb_pan_display,
209 .fb_fillrect = intelfb_fillrect,
210 .fb_copyarea = intelfb_copyarea,
211 .fb_imageblit = intelfb_imageblit,
212 .fb_cursor = intelfb_cursor,
213 .fb_sync = intelfb_sync,
214 .fb_ioctl = intelfb_ioctl
215};
216
217/* PCI driver module table */
218static struct pci_driver intelfb_driver = {
219 .name = "intelfb",
220 .id_table = intelfb_pci_table,
221 .probe = intelfb_pci_register,
222 .remove = intelfb_pci_unregister,
223};
224
225/* Module description/parameters */
226MODULE_AUTHOR("David Dawes <dawes@tungstengraphics.com>, "
227 "Sylvain Meyer <sylvain.meyer@worldonline.fr>");
228MODULE_DESCRIPTION("Framebuffer driver for Intel(R) " SUPPORTED_CHIPSETS
229 " chipsets");
230MODULE_LICENSE("Dual BSD/GPL");
231MODULE_DEVICE_TABLE(pci, intelfb_pci_table);
232
233static bool accel = 1;
234static int vram = 4;
235static bool hwcursor = 0;
236static bool mtrr = 1;
237static bool fixed = 0;
238static bool noinit = 0;
239static bool noregister = 0;
240static bool probeonly = 0;
241static bool idonly = 0;
242static int bailearly = 0;
243static int voffset = 48;
244static char *mode = NULL;
245
246module_param(accel, bool, S_IRUGO);
247MODULE_PARM_DESC(accel, "Enable hardware acceleration");
248module_param(vram, int, S_IRUGO);
249MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB");
250module_param(voffset, int, S_IRUGO);
251MODULE_PARM_DESC(voffset, "Offset of framebuffer in MiB");
252module_param(hwcursor, bool, S_IRUGO);
253MODULE_PARM_DESC(hwcursor, "Enable HW cursor");
254module_param(mtrr, bool, S_IRUGO);
255MODULE_PARM_DESC(mtrr, "Enable MTRR support");
256module_param(fixed, bool, S_IRUGO);
257MODULE_PARM_DESC(fixed, "Disable mode switching");
258module_param(noinit, bool, 0);
259MODULE_PARM_DESC(noinit, "Don't initialise graphics mode when loading");
260module_param(noregister, bool, 0);
261MODULE_PARM_DESC(noregister, "Don't register, just probe and exit (debug)");
262module_param(probeonly, bool, 0);
263MODULE_PARM_DESC(probeonly, "Do a minimal probe (debug)");
264module_param(idonly, bool, 0);
265MODULE_PARM_DESC(idonly, "Just identify without doing anything else (debug)");
266module_param(bailearly, int, 0);
267MODULE_PARM_DESC(bailearly, "Bail out early, depending on value (debug)");
268module_param(mode, charp, S_IRUGO);
269MODULE_PARM_DESC(mode,
270 "Initial video mode \"<xres>x<yres>[-<depth>][@<refresh>]\"");
271
272#ifndef MODULE
273#define OPT_EQUAL(opt, name) (!strncmp(opt, name, strlen(name)))
274#define OPT_INTVAL(opt, name) simple_strtoul(opt + strlen(name) + 1, NULL, 0)
275#define OPT_STRVAL(opt, name) (opt + strlen(name))
276
277static __inline__ char * get_opt_string(const char *this_opt, const char *name)
278{
279 const char *p;
280 int i;
281 char *ret;
282
283 p = OPT_STRVAL(this_opt, name);
284 i = 0;
285 while (p[i] && p[i] != ' ' && p[i] != ',')
286 i++;
287 ret = kmalloc(i + 1, GFP_KERNEL);
288 if (ret) {
289 strncpy(ret, p, i);
290 ret[i] = '\0';
291 }
292 return ret;
293}
294
295static __inline__ int get_opt_int(const char *this_opt, const char *name,
296 int *ret)
297{
298 if (!ret)
299 return 0;
300
301 if (!OPT_EQUAL(this_opt, name))
302 return 0;
303
304 *ret = OPT_INTVAL(this_opt, name);
305 return 1;
306}
307
308static __inline__ int get_opt_bool(const char *this_opt, const char *name,
309 int *ret)
310{
311 if (!ret)
312 return 0;
313
314 if (OPT_EQUAL(this_opt, name)) {
315 if (this_opt[strlen(name)] == '=')
316 *ret = simple_strtoul(this_opt + strlen(name) + 1,
317 NULL, 0);
318 else
319 *ret = 1;
320 } else {
321 if (OPT_EQUAL(this_opt, "no") && OPT_EQUAL(this_opt + 2, name))
322 *ret = 0;
323 else
324 return 0;
325 }
326 return 1;
327}
328
329static int __init intelfb_setup(char *options)
330{
331 char *this_opt;
332
333 DBG_MSG("intelfb_setup\n");
334
335 if (!options || !*options) {
336 DBG_MSG("no options\n");
337 return 0;
338 } else
339 DBG_MSG("options: %s\n", options);
340
341 /*
342 * These are the built-in options analogous to the module parameters
343 * defined above.
344 *
345 * The syntax is:
346 *
347 * video=intelfb:[mode][,<param>=<val>] ...
348 *
349 * e.g.,
350 *
351 * video=intelfb:1024x768-16@75,accel=0
352 */
353
354 while ((this_opt = strsep(&options, ","))) {
355 if (!*this_opt)
356 continue;
357 if (get_opt_bool(this_opt, "accel", &accel))
358 ;
359 else if (get_opt_int(this_opt, "vram", &vram))
360 ;
361 else if (get_opt_bool(this_opt, "hwcursor", &hwcursor))
362 ;
363 else if (get_opt_bool(this_opt, "mtrr", &mtrr))
364 ;
365 else if (get_opt_bool(this_opt, "fixed", &fixed))
366 ;
367 else if (get_opt_bool(this_opt, "init", &noinit))
368 noinit = !noinit;
369 else if (OPT_EQUAL(this_opt, "mode="))
370 mode = get_opt_string(this_opt, "mode=");
371 else
372 mode = this_opt;
373 }
374
375 return 0;
376}
377
378#endif
379
380static int __init intelfb_init(void)
381{
382#ifndef MODULE
383 char *option = NULL;
384#endif
385
386 DBG_MSG("intelfb_init\n");
387
388 INF_MSG("Framebuffer driver for "
389 "Intel(R) " SUPPORTED_CHIPSETS " chipsets\n");
390 INF_MSG("Version " INTELFB_VERSION "\n");
391
392 if (idonly)
393 return -ENODEV;
394
395#ifndef MODULE
396 if (fb_get_options("intelfb", &option))
397 return -ENODEV;
398 intelfb_setup(option);
399#endif
400
401 return pci_register_driver(&intelfb_driver);
402}
403
404static void __exit intelfb_exit(void)
405{
406 DBG_MSG("intelfb_exit\n");
407 pci_unregister_driver(&intelfb_driver);
408}
409
410module_init(intelfb_init);
411module_exit(intelfb_exit);
412
413/***************************************************************
414 * mtrr support functions *
415 ***************************************************************/
416
417#ifdef CONFIG_MTRR
418static inline void set_mtrr(struct intelfb_info *dinfo)
419{
420 dinfo->mtrr_reg = mtrr_add(dinfo->aperture.physical,
421 dinfo->aperture.size, MTRR_TYPE_WRCOMB, 1);
422 if (dinfo->mtrr_reg < 0) {
423 ERR_MSG("unable to set MTRR\n");
424 return;
425 }
426 dinfo->has_mtrr = 1;
427}
428static inline void unset_mtrr(struct intelfb_info *dinfo)
429{
430 if (dinfo->has_mtrr)
431 mtrr_del(dinfo->mtrr_reg, dinfo->aperture.physical,
432 dinfo->aperture.size);
433}
434#else
435#define set_mtrr(x) WRN_MSG("MTRR is disabled in the kernel\n")
436
437#define unset_mtrr(x) do { } while (0)
438#endif /* CONFIG_MTRR */
439
440/***************************************************************
441 * driver init / cleanup *
442 ***************************************************************/
443
444static void cleanup(struct intelfb_info *dinfo)
445{
446 DBG_MSG("cleanup\n");
447
448 if (!dinfo)
449 return;
450
451 intelfbhw_disable_irq(dinfo);
452
453 fb_dealloc_cmap(&dinfo->info->cmap);
454 kfree(dinfo->info->pixmap.addr);
455
456 if (dinfo->registered)
457 unregister_framebuffer(dinfo->info);
458
459 unset_mtrr(dinfo);
460
461 if (dinfo->fbmem_gart && dinfo->gtt_fb_mem) {
462 agp_unbind_memory(dinfo->gtt_fb_mem);
463 agp_free_memory(dinfo->gtt_fb_mem);
464 }
465 if (dinfo->gtt_cursor_mem) {
466 agp_unbind_memory(dinfo->gtt_cursor_mem);
467 agp_free_memory(dinfo->gtt_cursor_mem);
468 }
469 if (dinfo->gtt_ring_mem) {
470 agp_unbind_memory(dinfo->gtt_ring_mem);
471 agp_free_memory(dinfo->gtt_ring_mem);
472 }
473
474#ifdef CONFIG_FB_INTEL_I2C
475 /* un-register I2C bus */
476 intelfb_delete_i2c_busses(dinfo);
477#endif
478
479 if (dinfo->mmio_base)
480 iounmap((void __iomem *)dinfo->mmio_base);
481 if (dinfo->aperture.virtual)
482 iounmap((void __iomem *)dinfo->aperture.virtual);
483
484 if (dinfo->flag & INTELFB_MMIO_ACQUIRED)
485 release_mem_region(dinfo->mmio_base_phys, INTEL_REG_SIZE);
486 if (dinfo->flag & INTELFB_FB_ACQUIRED)
487 release_mem_region(dinfo->aperture.physical,
488 dinfo->aperture.size);
489 framebuffer_release(dinfo->info);
490}
491
492#define bailout(dinfo) do { \
493 DBG_MSG("bailout\n"); \
494 cleanup(dinfo); \
495 INF_MSG("Not going to register framebuffer, exiting...\n"); \
496 return -ENODEV; \
497} while (0)
498
499
500static int intelfb_pci_register(struct pci_dev *pdev,
501 const struct pci_device_id *ent)
502{
503 struct fb_info *info;
504 struct intelfb_info *dinfo;
505 int i, err, dvo;
506 int aperture_size, stolen_size;
507 struct agp_kern_info gtt_info;
508 int agp_memtype;
509 const char *s;
510 struct agp_bridge_data *bridge;
511 int aperture_bar = 0;
512 int mmio_bar = 1;
513 int offset;
514
515 DBG_MSG("intelfb_pci_register\n");
516
517 num_registered++;
518 if (num_registered != 1) {
519 ERR_MSG("Attempted to register %d devices "
520 "(should be only 1).\n", num_registered);
521 return -ENODEV;
522 }
523
524 info = framebuffer_alloc(sizeof(struct intelfb_info), &pdev->dev);
525 if (!info) {
526 ERR_MSG("Could not allocate memory for intelfb_info.\n");
527 return -ENODEV;
528 }
529 if (fb_alloc_cmap(&info->cmap, 256, 1) < 0) {
530 ERR_MSG("Could not allocate cmap for intelfb_info.\n");
531 goto err_out_cmap;
532 }
533
534 dinfo = info->par;
535 dinfo->info = info;
536 dinfo->fbops = &intel_fb_ops;
537 dinfo->pdev = pdev;
538
539 /* Reserve pixmap space. */
540 info->pixmap.addr = kzalloc(64 * 1024, GFP_KERNEL);
541 if (info->pixmap.addr == NULL) {
542 ERR_MSG("Cannot reserve pixmap memory.\n");
543 goto err_out_pixmap;
544 }
545
546 /* set early this option because it could be changed by tv encoder
547 driver */
548 dinfo->fixed_mode = fixed;
549
550 /* Enable device. */
551 if ((err = pci_enable_device(pdev))) {
552 ERR_MSG("Cannot enable device.\n");
553 cleanup(dinfo);
554 return -ENODEV;
555 }
556
557 /* Set base addresses. */
558 if ((ent->device == PCI_DEVICE_ID_INTEL_915G) ||
559 (ent->device == PCI_DEVICE_ID_INTEL_915GM) ||
560 (ent->device == PCI_DEVICE_ID_INTEL_945G) ||
561 (ent->device == PCI_DEVICE_ID_INTEL_945GM) ||
562 (ent->device == PCI_DEVICE_ID_INTEL_945GME) ||
563 (ent->device == PCI_DEVICE_ID_INTEL_965G) ||
564 (ent->device == PCI_DEVICE_ID_INTEL_965GM)) {
565
566 aperture_bar = 2;
567 mmio_bar = 0;
568 }
569 dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar);
570 dinfo->aperture.size = pci_resource_len(pdev, aperture_bar);
571 dinfo->mmio_base_phys = pci_resource_start(pdev, mmio_bar);
572 DBG_MSG("fb aperture: 0x%llx/0x%llx, MMIO region: 0x%llx/0x%llx\n",
573 (unsigned long long)pci_resource_start(pdev, aperture_bar),
574 (unsigned long long)pci_resource_len(pdev, aperture_bar),
575 (unsigned long long)pci_resource_start(pdev, mmio_bar),
576 (unsigned long long)pci_resource_len(pdev, mmio_bar));
577
578 /* Reserve the fb and MMIO regions */
579 if (!request_mem_region(dinfo->aperture.physical, dinfo->aperture.size,
580 INTELFB_MODULE_NAME)) {
581 ERR_MSG("Cannot reserve FB region.\n");
582 cleanup(dinfo);
583 return -ENODEV;
584 }
585
586 dinfo->flag |= INTELFB_FB_ACQUIRED;
587
588 if (!request_mem_region(dinfo->mmio_base_phys,
589 INTEL_REG_SIZE,
590 INTELFB_MODULE_NAME)) {
591 ERR_MSG("Cannot reserve MMIO region.\n");
592 cleanup(dinfo);
593 return -ENODEV;
594 }
595
596 dinfo->flag |= INTELFB_MMIO_ACQUIRED;
597
598 /* Get the chipset info. */
599 dinfo->pci_chipset = pdev->device;
600
601 if (intelfbhw_get_chipset(pdev, dinfo)) {
602 cleanup(dinfo);
603 return -ENODEV;
604 }
605
606 if (intelfbhw_get_memory(pdev, &aperture_size,&stolen_size)) {
607 cleanup(dinfo);
608 return -ENODEV;
609 }
610
611 INF_MSG("%02x:%02x.%d: %s, aperture size %dMB, "
612 "stolen memory %dkB\n",
613 pdev->bus->number, PCI_SLOT(pdev->devfn),
614 PCI_FUNC(pdev->devfn), dinfo->name,
615 BtoMB(aperture_size), BtoKB(stolen_size));
616
617 /* Set these from the options. */
618 dinfo->accel = accel;
619 dinfo->hwcursor = hwcursor;
620
621 if (NOACCEL_CHIPSET(dinfo) && dinfo->accel == 1) {
622 INF_MSG("Acceleration is not supported for the %s chipset.\n",
623 dinfo->name);
624 dinfo->accel = 0;
625 }
626
627 /* Framebuffer parameters - Use all the stolen memory if >= vram */
628 if (ROUND_UP_TO_PAGE(stolen_size) >= MB(vram)) {
629 dinfo->fb.size = ROUND_UP_TO_PAGE(stolen_size);
630 dinfo->fbmem_gart = 0;
631 } else {
632 dinfo->fb.size = MB(vram);
633 dinfo->fbmem_gart = 1;
634 }
635
636 /* Allocate space for the ring buffer and HW cursor if enabled. */
637 if (dinfo->accel) {
638 dinfo->ring.size = RINGBUFFER_SIZE;
639 dinfo->ring_tail_mask = dinfo->ring.size - 1;
640 }
641 if (dinfo->hwcursor)
642 dinfo->cursor.size = HW_CURSOR_SIZE;
643
644 /* Use agpgart to manage the GATT */
645 if (!(bridge = agp_backend_acquire(pdev))) {
646 ERR_MSG("cannot acquire agp\n");
647 cleanup(dinfo);
648 return -ENODEV;
649 }
650
651 /* get the current gatt info */
652 if (agp_copy_info(bridge, &gtt_info)) {
653 ERR_MSG("cannot get agp info\n");
654 agp_backend_release(bridge);
655 cleanup(dinfo);
656 return -ENODEV;
657 }
658
659 if (MB(voffset) < stolen_size)
660 offset = (stolen_size >> 12);
661 else
662 offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE;
663
664 /* set the mem offsets - set them after the already used pages */
665 if (dinfo->accel)
666 dinfo->ring.offset = offset + gtt_info.current_memory;
667 if (dinfo->hwcursor)
668 dinfo->cursor.offset = offset +
669 + gtt_info.current_memory + (dinfo->ring.size >> 12);
670 if (dinfo->fbmem_gart)
671 dinfo->fb.offset = offset +
672 + gtt_info.current_memory + (dinfo->ring.size >> 12)
673 + (dinfo->cursor.size >> 12);
674
675 /* Allocate memories (which aren't stolen) */
676 /* Map the fb and MMIO regions */
677 /* ioremap only up to the end of used aperture */
678 dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache
679 (dinfo->aperture.physical, ((offset + dinfo->fb.offset) << 12)
680 + dinfo->fb.size);
681 if (!dinfo->aperture.virtual) {
682 ERR_MSG("Cannot remap FB region.\n");
683 agp_backend_release(bridge);
684 cleanup(dinfo);
685 return -ENODEV;
686 }
687
688 dinfo->mmio_base =
689 (u8 __iomem *)ioremap_nocache(dinfo->mmio_base_phys,
690 INTEL_REG_SIZE);
691 if (!dinfo->mmio_base) {
692 ERR_MSG("Cannot remap MMIO region.\n");
693 agp_backend_release(bridge);
694 cleanup(dinfo);
695 return -ENODEV;
696 }
697
698 if (dinfo->accel) {
699 if (!(dinfo->gtt_ring_mem =
700 agp_allocate_memory(bridge, dinfo->ring.size >> 12,
701 AGP_NORMAL_MEMORY))) {
702 ERR_MSG("cannot allocate ring buffer memory\n");
703 agp_backend_release(bridge);
704 cleanup(dinfo);
705 return -ENOMEM;
706 }
707 if (agp_bind_memory(dinfo->gtt_ring_mem,
708 dinfo->ring.offset)) {
709 ERR_MSG("cannot bind ring buffer memory\n");
710 agp_backend_release(bridge);
711 cleanup(dinfo);
712 return -EBUSY;
713 }
714 dinfo->ring.physical = dinfo->aperture.physical
715 + (dinfo->ring.offset << 12);
716 dinfo->ring.virtual = dinfo->aperture.virtual
717 + (dinfo->ring.offset << 12);
718 dinfo->ring_head = 0;
719 }
720 if (dinfo->hwcursor) {
721 agp_memtype = dinfo->mobile ? AGP_PHYSICAL_MEMORY
722 : AGP_NORMAL_MEMORY;
723 if (!(dinfo->gtt_cursor_mem =
724 agp_allocate_memory(bridge, dinfo->cursor.size >> 12,
725 agp_memtype))) {
726 ERR_MSG("cannot allocate cursor memory\n");
727 agp_backend_release(bridge);
728 cleanup(dinfo);
729 return -ENOMEM;
730 }
731 if (agp_bind_memory(dinfo->gtt_cursor_mem,
732 dinfo->cursor.offset)) {
733 ERR_MSG("cannot bind cursor memory\n");
734 agp_backend_release(bridge);
735 cleanup(dinfo);
736 return -EBUSY;
737 }
738 if (dinfo->mobile)
739 dinfo->cursor.physical
740 = dinfo->gtt_cursor_mem->physical;
741 else
742 dinfo->cursor.physical = dinfo->aperture.physical
743 + (dinfo->cursor.offset << 12);
744 dinfo->cursor.virtual = dinfo->aperture.virtual
745 + (dinfo->cursor.offset << 12);
746 }
747 if (dinfo->fbmem_gart) {
748 if (!(dinfo->gtt_fb_mem =
749 agp_allocate_memory(bridge, dinfo->fb.size >> 12,
750 AGP_NORMAL_MEMORY))) {
751 WRN_MSG("cannot allocate framebuffer memory - use "
752 "the stolen one\n");
753 dinfo->fbmem_gart = 0;
754 }
755 if (agp_bind_memory(dinfo->gtt_fb_mem,
756 dinfo->fb.offset)) {
757 WRN_MSG("cannot bind framebuffer memory - use "
758 "the stolen one\n");
759 dinfo->fbmem_gart = 0;
760 }
761 }
762
763 /* update framebuffer memory parameters */
764 if (!dinfo->fbmem_gart)
765 dinfo->fb.offset = 0; /* starts at offset 0 */
766 dinfo->fb.physical = dinfo->aperture.physical
767 + (dinfo->fb.offset << 12);
768 dinfo->fb.virtual = dinfo->aperture.virtual + (dinfo->fb.offset << 12);
769 dinfo->fb_start = dinfo->fb.offset << 12;
770
771 /* release agpgart */
772 agp_backend_release(bridge);
773
774 if (mtrr)
775 set_mtrr(dinfo);
776
777 DBG_MSG("fb: 0x%x(+ 0x%x)/0x%x (0x%p)\n",
778 dinfo->fb.physical, dinfo->fb.offset, dinfo->fb.size,
779 dinfo->fb.virtual);
780 DBG_MSG("MMIO: 0x%x/0x%x (0x%p)\n",
781 dinfo->mmio_base_phys, INTEL_REG_SIZE,
782 dinfo->mmio_base);
783 DBG_MSG("ring buffer: 0x%x/0x%x (0x%p)\n",
784 dinfo->ring.physical, dinfo->ring.size,
785 dinfo->ring.virtual);
786 DBG_MSG("HW cursor: 0x%x/0x%x (0x%p) (offset 0x%x) (phys 0x%x)\n",
787 dinfo->cursor.physical, dinfo->cursor.size,
788 dinfo->cursor.virtual, dinfo->cursor.offset,
789 dinfo->cursor.physical);
790
791 DBG_MSG("options: vram = %d, accel = %d, hwcursor = %d, fixed = %d, "
792 "noinit = %d\n", vram, accel, hwcursor, fixed, noinit);
793 DBG_MSG("options: mode = \"%s\"\n", mode ? mode : "");
794
795 if (probeonly)
796 bailout(dinfo);
797
798 /*
799 * Check if the LVDS port or any DVO ports are enabled. If so,
800 * don't allow mode switching
801 */
802 dvo = intelfbhw_check_non_crt(dinfo);
803 if (dvo) {
804 dinfo->fixed_mode = 1;
805 WRN_MSG("Non-CRT device is enabled ( ");
806 i = 0;
807 while (dvo) {
808 if (dvo & 1) {
809 s = intelfbhw_dvo_to_string(1 << i);
810 if (s)
811 printk("%s ", s);
812 }
813 dvo >>= 1;
814 ++i;
815 }
816 printk("). Disabling mode switching.\n");
817 }
818
819 if (bailearly == 1)
820 bailout(dinfo);
821
822 if (FIXED_MODE(dinfo) &&
823 screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) {
824 ERR_MSG("Video mode must be programmed at boot time.\n");
825 cleanup(dinfo);
826 return -ENODEV;
827 }
828
829 if (bailearly == 2)
830 bailout(dinfo);
831
832 /* Initialise dinfo and related data. */
833 /* If an initial mode was programmed at boot time, get its details. */
834 if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB)
835 get_initial_mode(dinfo);
836
837 if (bailearly == 3)
838 bailout(dinfo);
839
840 if (FIXED_MODE(dinfo)) /* remap fb address */
841 update_dinfo(dinfo, &dinfo->initial_var);
842
843 if (bailearly == 4)
844 bailout(dinfo);
845
846
847 if (intelfb_set_fbinfo(dinfo)) {
848 cleanup(dinfo);
849 return -ENODEV;
850 }
851
852 if (bailearly == 5)
853 bailout(dinfo);
854
855#ifdef CONFIG_FB_INTEL_I2C
856 /* register I2C bus */
857 intelfb_create_i2c_busses(dinfo);
858#endif
859
860 if (bailearly == 6)
861 bailout(dinfo);
862
863 pci_set_drvdata(pdev, dinfo);
864
865 /* Save the initial register state. */
866 i = intelfbhw_read_hw_state(dinfo, &dinfo->save_state,
867 bailearly > 6 ? bailearly - 6 : 0);
868 if (i != 0) {
869 DBG_MSG("intelfbhw_read_hw_state returned %d\n", i);
870 bailout(dinfo);
871 }
872
873 intelfbhw_print_hw_state(dinfo, &dinfo->save_state);
874
875 if (bailearly == 18)
876 bailout(dinfo);
877
878 /* read active pipe */
879 dinfo->pipe = intelfbhw_active_pipe(&dinfo->save_state);
880
881 /* Cursor initialisation */
882 if (dinfo->hwcursor) {
883 intelfbhw_cursor_init(dinfo);
884 intelfbhw_cursor_reset(dinfo);
885 }
886
887 if (bailearly == 19)
888 bailout(dinfo);
889
890 /* 2d acceleration init */
891 if (dinfo->accel)
892 intelfbhw_2d_start(dinfo);
893
894 if (bailearly == 20)
895 bailout(dinfo);
896
897 if (noregister)
898 bailout(dinfo);
899
900 if (register_framebuffer(dinfo->info) < 0) {
901 ERR_MSG("Cannot register framebuffer.\n");
902 cleanup(dinfo);
903 return -ENODEV;
904 }
905
906 dinfo->registered = 1;
907 dinfo->open = 0;
908
909 init_waitqueue_head(&dinfo->vsync.wait);
910 spin_lock_init(&dinfo->int_lock);
911 dinfo->irq_flags = 0;
912 dinfo->vsync.pan_display = 0;
913 dinfo->vsync.pan_offset = 0;
914
915 return 0;
916
917err_out_pixmap:
918 fb_dealloc_cmap(&info->cmap);
919err_out_cmap:
920 framebuffer_release(info);
921 return -ENODEV;
922}
923
924static void intelfb_pci_unregister(struct pci_dev *pdev)
925{
926 struct intelfb_info *dinfo = pci_get_drvdata(pdev);
927
928 DBG_MSG("intelfb_pci_unregister\n");
929
930 if (!dinfo)
931 return;
932
933 cleanup(dinfo);
934}
935
936/***************************************************************
937 * helper functions *
938 ***************************************************************/
939
940int __inline__ intelfb_var_to_depth(const struct fb_var_screeninfo *var)
941{
942 DBG_MSG("intelfb_var_to_depth: bpp: %d, green.length is %d\n",
943 var->bits_per_pixel, var->green.length);
944
945 switch (var->bits_per_pixel) {
946 case 16:
947 return (var->green.length == 6) ? 16 : 15;
948 case 32:
949 return 24;
950 default:
951 return var->bits_per_pixel;
952 }
953}
954
955
956static __inline__ int var_to_refresh(const struct fb_var_screeninfo *var)
957{
958 int xtot = var->xres + var->left_margin + var->right_margin +
959 var->hsync_len;
960 int ytot = var->yres + var->upper_margin + var->lower_margin +
961 var->vsync_len;
962
963 return (1000000000 / var->pixclock * 1000 + 500) / xtot / ytot;
964}
965
966/***************************************************************
967 * Various intialisation functions *
968 ***************************************************************/
969
970static void get_initial_mode(struct intelfb_info *dinfo)
971{
972 struct fb_var_screeninfo *var;
973 int xtot, ytot;
974
975 DBG_MSG("get_initial_mode\n");
976
977 dinfo->initial_vga = 1;
978 dinfo->initial_fb_base = screen_info.lfb_base;
979 dinfo->initial_video_ram = screen_info.lfb_size * KB(64);
980 dinfo->initial_pitch = screen_info.lfb_linelength;
981
982 var = &dinfo->initial_var;
983 memset(var, 0, sizeof(*var));
984 var->xres = screen_info.lfb_width;
985 var->yres = screen_info.lfb_height;
986 var->bits_per_pixel = screen_info.lfb_depth;
987 switch (screen_info.lfb_depth) {
988 case 15:
989 var->bits_per_pixel = 16;
990 break;
991 case 24:
992 var->bits_per_pixel = 32;
993 break;
994 }
995
996 DBG_MSG("Initial info: FB is 0x%x/0x%x (%d kByte)\n",
997 dinfo->initial_fb_base, dinfo->initial_video_ram,
998 BtoKB(dinfo->initial_video_ram));
999
1000 DBG_MSG("Initial info: mode is %dx%d-%d (%d)\n",
1001 var->xres, var->yres, var->bits_per_pixel,
1002 dinfo->initial_pitch);
1003
1004 /* Dummy timing values (assume 60Hz) */
1005 var->left_margin = (var->xres / 8) & 0xf8;
1006 var->right_margin = 32;
1007 var->upper_margin = 16;
1008 var->lower_margin = 4;
1009 var->hsync_len = (var->xres / 8) & 0xf8;
1010 var->vsync_len = 4;
1011
1012 xtot = var->xres + var->left_margin +
1013 var->right_margin + var->hsync_len;
1014 ytot = var->yres + var->upper_margin +
1015 var->lower_margin + var->vsync_len;
1016 var->pixclock = 10000000 / xtot * 1000 / ytot * 100 / 60;
1017
1018 var->height = -1;
1019 var->width = -1;
1020
1021 if (var->bits_per_pixel > 8) {
1022 var->red.offset = screen_info.red_pos;
1023 var->red.length = screen_info.red_size;
1024 var->green.offset = screen_info.green_pos;
1025 var->green.length = screen_info.green_size;
1026 var->blue.offset = screen_info.blue_pos;
1027 var->blue.length = screen_info.blue_size;
1028 var->transp.offset = screen_info.rsvd_pos;
1029 var->transp.length = screen_info.rsvd_size;
1030 } else {
1031 var->red.length = 8;
1032 var->green.length = 8;
1033 var->blue.length = 8;
1034 }
1035}
1036
1037static int intelfb_init_var(struct intelfb_info *dinfo)
1038{
1039 struct fb_var_screeninfo *var;
1040 int msrc = 0;
1041
1042 DBG_MSG("intelfb_init_var\n");
1043
1044 var = &dinfo->info->var;
1045 if (FIXED_MODE(dinfo)) {
1046 memcpy(var, &dinfo->initial_var,
1047 sizeof(struct fb_var_screeninfo));
1048 msrc = 5;
1049 } else {
1050 const u8 *edid_s = fb_firmware_edid(&dinfo->pdev->dev);
1051 u8 *edid_d = NULL;
1052
1053 if (edid_s) {
1054 edid_d = kmemdup(edid_s, EDID_LENGTH, GFP_KERNEL);
1055
1056 if (edid_d) {
1057 fb_edid_to_monspecs(edid_d,
1058 &dinfo->info->monspecs);
1059 kfree(edid_d);
1060 }
1061 }
1062
1063 if (mode) {
1064 printk("intelfb: Looking for mode in private "
1065 "database\n");
1066 msrc = fb_find_mode(var, dinfo->info, mode,
1067 dinfo->info->monspecs.modedb,
1068 dinfo->info->monspecs.modedb_len,
1069 NULL, 0);
1070
1071 if (msrc && msrc > 1) {
1072 printk("intelfb: No mode in private database, "
1073 "intelfb: looking for mode in global "
1074 "database ");
1075 msrc = fb_find_mode(var, dinfo->info, mode,
1076 NULL, 0, NULL, 0);
1077
1078 if (msrc)
1079 msrc |= 8;
1080 }
1081
1082 }
1083
1084 if (!msrc)
1085 msrc = fb_find_mode(var, dinfo->info, PREFERRED_MODE,
1086 NULL, 0, NULL, 0);
1087 }
1088
1089 if (!msrc) {
1090 ERR_MSG("Cannot find a suitable video mode.\n");
1091 return 1;
1092 }
1093
1094 INF_MSG("Initial video mode is %dx%d-%d@%d.\n", var->xres, var->yres,
1095 var->bits_per_pixel, var_to_refresh(var));
1096
1097 DBG_MSG("Initial video mode is from %d.\n", msrc);
1098
1099#if ALLOCATE_FOR_PANNING
1100 /* Allow use of half of the video ram for panning */
1101 var->xres_virtual = var->xres;
1102 var->yres_virtual =
1103 dinfo->fb.size / 2 / (var->bits_per_pixel * var->xres);
1104 if (var->yres_virtual < var->yres)
1105 var->yres_virtual = var->yres;
1106#else
1107 var->yres_virtual = var->yres;
1108#endif
1109
1110 if (dinfo->accel)
1111 var->accel_flags |= FB_ACCELF_TEXT;
1112 else
1113 var->accel_flags &= ~FB_ACCELF_TEXT;
1114
1115 return 0;
1116}
1117
1118static int intelfb_set_fbinfo(struct intelfb_info *dinfo)
1119{
1120 struct fb_info *info = dinfo->info;
1121
1122 DBG_MSG("intelfb_set_fbinfo\n");
1123
1124 info->flags = FBINFO_FLAG_DEFAULT;
1125 info->fbops = &intel_fb_ops;
1126 info->pseudo_palette = dinfo->pseudo_palette;
1127
1128 info->pixmap.size = 64*1024;
1129 info->pixmap.buf_align = 8;
1130 info->pixmap.access_align = 32;
1131 info->pixmap.flags = FB_PIXMAP_SYSTEM;
1132
1133 if (intelfb_init_var(dinfo))
1134 return 1;
1135
1136 info->pixmap.scan_align = 1;
1137 strcpy(info->fix.id, dinfo->name);
1138 info->fix.smem_start = dinfo->fb.physical;
1139 info->fix.smem_len = dinfo->fb.size;
1140 info->fix.type = FB_TYPE_PACKED_PIXELS;
1141 info->fix.type_aux = 0;
1142 info->fix.xpanstep = 8;
1143 info->fix.ypanstep = 1;
1144 info->fix.ywrapstep = 0;
1145 info->fix.mmio_start = dinfo->mmio_base_phys;
1146 info->fix.mmio_len = INTEL_REG_SIZE;
1147 info->fix.accel = FB_ACCEL_I830;
1148 update_dinfo(dinfo, &info->var);
1149
1150 return 0;
1151}
1152
1153/* Update dinfo to match the active video mode. */
1154static void update_dinfo(struct intelfb_info *dinfo,
1155 struct fb_var_screeninfo *var)
1156{
1157 DBG_MSG("update_dinfo\n");
1158
1159 dinfo->bpp = var->bits_per_pixel;
1160 dinfo->depth = intelfb_var_to_depth(var);
1161 dinfo->xres = var->xres;
1162 dinfo->yres = var->xres;
1163 dinfo->pixclock = var->pixclock;
1164
1165 dinfo->info->fix.visual = dinfo->visual;
1166 dinfo->info->fix.line_length = dinfo->pitch;
1167
1168 switch (dinfo->bpp) {
1169 case 8:
1170 dinfo->visual = FB_VISUAL_PSEUDOCOLOR;
1171 dinfo->pitch = var->xres_virtual;
1172 break;
1173 case 16:
1174 dinfo->visual = FB_VISUAL_TRUECOLOR;
1175 dinfo->pitch = var->xres_virtual * 2;
1176 break;
1177 case 32:
1178 dinfo->visual = FB_VISUAL_TRUECOLOR;
1179 dinfo->pitch = var->xres_virtual * 4;
1180 break;
1181 }
1182
1183 /* Make sure the line length is a aligned correctly. */
1184 if (IS_I9XX(dinfo))
1185 dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT_I9XX);
1186 else
1187 dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT);
1188
1189 if (FIXED_MODE(dinfo))
1190 dinfo->pitch = dinfo->initial_pitch;
1191
1192 dinfo->info->screen_base = (char __iomem *)dinfo->fb.virtual;
1193 dinfo->info->fix.line_length = dinfo->pitch;
1194 dinfo->info->fix.visual = dinfo->visual;
1195}
1196
1197/* fbops functions */
1198
1199/***************************************************************
1200 * fbdev interface *
1201 ***************************************************************/
1202
1203static int intelfb_open(struct fb_info *info, int user)
1204{
1205 struct intelfb_info *dinfo = GET_DINFO(info);
1206
1207 if (user)
1208 dinfo->open++;
1209
1210 return 0;
1211}
1212
1213static int intelfb_release(struct fb_info *info, int user)
1214{
1215 struct intelfb_info *dinfo = GET_DINFO(info);
1216
1217 if (user) {
1218 dinfo->open--;
1219 msleep(1);
1220 if (!dinfo->open)
1221 intelfbhw_disable_irq(dinfo);
1222 }
1223
1224 return 0;
1225}
1226
1227static int intelfb_check_var(struct fb_var_screeninfo *var,
1228 struct fb_info *info)
1229{
1230 int change_var = 0;
1231 struct fb_var_screeninfo v;
1232 struct intelfb_info *dinfo;
1233 static int first = 1;
1234 int i;
1235 /* Good pitches to allow tiling. Don't care about pitches < 1024. */
1236 static const int pitches[] = {
1237 128 * 8,
1238 128 * 16,
1239 128 * 32,
1240 128 * 64,
1241 0
1242 };
1243
1244 DBG_MSG("intelfb_check_var: accel_flags is %d\n", var->accel_flags);
1245
1246 dinfo = GET_DINFO(info);
1247
1248 /* update the pitch */
1249 if (intelfbhw_validate_mode(dinfo, var) != 0)
1250 return -EINVAL;
1251
1252 v = *var;
1253
1254 for (i = 0; pitches[i] != 0; i++) {
1255 if (pitches[i] >= v.xres_virtual) {
1256 v.xres_virtual = pitches[i];
1257 break;
1258 }
1259 }
1260
1261 /* Check for a supported bpp. */
1262 if (v.bits_per_pixel <= 8)
1263 v.bits_per_pixel = 8;
1264 else if (v.bits_per_pixel <= 16) {
1265 if (v.bits_per_pixel == 16)
1266 v.green.length = 6;
1267 v.bits_per_pixel = 16;
1268 } else if (v.bits_per_pixel <= 32)
1269 v.bits_per_pixel = 32;
1270 else
1271 return -EINVAL;
1272
1273 change_var = ((info->var.xres != var->xres) ||
1274 (info->var.yres != var->yres) ||
1275 (info->var.xres_virtual != var->xres_virtual) ||
1276 (info->var.yres_virtual != var->yres_virtual) ||
1277 (info->var.bits_per_pixel != var->bits_per_pixel) ||
1278 memcmp(&info->var.red, &var->red, sizeof(var->red)) ||
1279 memcmp(&info->var.green, &var->green,
1280 sizeof(var->green)) ||
1281 memcmp(&info->var.blue, &var->blue, sizeof(var->blue)));
1282
1283 if (FIXED_MODE(dinfo) &&
1284 (change_var ||
1285 var->yres_virtual > dinfo->initial_var.yres_virtual ||
1286 var->yres_virtual < dinfo->initial_var.yres ||
1287 var->xoffset || var->nonstd)) {
1288 if (first) {
1289 ERR_MSG("Changing the video mode is not supported.\n");
1290 first = 0;
1291 }
1292 return -EINVAL;
1293 }
1294
1295 switch (intelfb_var_to_depth(&v)) {
1296 case 8:
1297 v.red.offset = v.green.offset = v.blue.offset = 0;
1298 v.red.length = v.green.length = v.blue.length = 8;
1299 v.transp.offset = v.transp.length = 0;
1300 break;
1301 case 15:
1302 v.red.offset = 10;
1303 v.green.offset = 5;
1304 v.blue.offset = 0;
1305 v.red.length = v.green.length = v.blue.length = 5;
1306 v.transp.offset = v.transp.length = 0;
1307 break;
1308 case 16:
1309 v.red.offset = 11;
1310 v.green.offset = 5;
1311 v.blue.offset = 0;
1312 v.red.length = 5;
1313 v.green.length = 6;
1314 v.blue.length = 5;
1315 v.transp.offset = v.transp.length = 0;
1316 break;
1317 case 24:
1318 v.red.offset = 16;
1319 v.green.offset = 8;
1320 v.blue.offset = 0;
1321 v.red.length = v.green.length = v.blue.length = 8;
1322 v.transp.offset = v.transp.length = 0;
1323 break;
1324 case 32:
1325 v.red.offset = 16;
1326 v.green.offset = 8;
1327 v.blue.offset = 0;
1328 v.red.length = v.green.length = v.blue.length = 8;
1329 v.transp.offset = 24;
1330 v.transp.length = 8;
1331 break;
1332 }
1333
1334 if (v.xoffset < 0)
1335 v.xoffset = 0;
1336 if (v.yoffset < 0)
1337 v.yoffset = 0;
1338
1339 if (v.xoffset > v.xres_virtual - v.xres)
1340 v.xoffset = v.xres_virtual - v.xres;
1341 if (v.yoffset > v.yres_virtual - v.yres)
1342 v.yoffset = v.yres_virtual - v.yres;
1343
1344 v.red.msb_right = v.green.msb_right = v.blue.msb_right =
1345 v.transp.msb_right = 0;
1346
1347 *var = v;
1348
1349 return 0;
1350}
1351
1352static int intelfb_set_par(struct fb_info *info)
1353{
1354 struct intelfb_hwstate *hw;
1355 struct intelfb_info *dinfo = GET_DINFO(info);
1356
1357 if (FIXED_MODE(dinfo)) {
1358 ERR_MSG("Changing the video mode is not supported.\n");
1359 return -EINVAL;
1360 }
1361
1362 hw = kmalloc(sizeof(*hw), GFP_ATOMIC);
1363 if (!hw)
1364 return -ENOMEM;
1365
1366 DBG_MSG("intelfb_set_par (%dx%d-%d)\n", info->var.xres,
1367 info->var.yres, info->var.bits_per_pixel);
1368
1369 /*
1370 * Disable VCO prior to timing register change.
1371 */
1372 OUTREG(DPLL_A, INREG(DPLL_A) & ~DPLL_VCO_ENABLE);
1373
1374 intelfb_blank(FB_BLANK_POWERDOWN, info);
1375
1376 if (ACCEL(dinfo, info))
1377 intelfbhw_2d_stop(dinfo);
1378
1379 memcpy(hw, &dinfo->save_state, sizeof(*hw));
1380 if (intelfbhw_mode_to_hw(dinfo, hw, &info->var))
1381 goto invalid_mode;
1382 if (intelfbhw_program_mode(dinfo, hw, 0))
1383 goto invalid_mode;
1384
1385#if REGDUMP > 0
1386 intelfbhw_read_hw_state(dinfo, hw, 0);
1387 intelfbhw_print_hw_state(dinfo, hw);
1388#endif
1389
1390 update_dinfo(dinfo, &info->var);
1391
1392 if (ACCEL(dinfo, info))
1393 intelfbhw_2d_start(dinfo);
1394
1395 intelfb_pan_display(&info->var, info);
1396
1397 intelfb_blank(FB_BLANK_UNBLANK, info);
1398
1399 if (ACCEL(dinfo, info)) {
1400 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
1401 FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
1402 FBINFO_HWACCEL_IMAGEBLIT;
1403 } else
1404 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1405
1406 kfree(hw);
1407 return 0;
1408invalid_mode:
1409 kfree(hw);
1410 return -EINVAL;
1411}
1412
1413static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1414 unsigned blue, unsigned transp,
1415 struct fb_info *info)
1416{
1417 struct intelfb_info *dinfo = GET_DINFO(info);
1418
1419#if VERBOSE > 0
1420 DBG_MSG("intelfb_setcolreg: regno %d, depth %d\n", regno, dinfo->depth);
1421#endif
1422
1423 if (regno > 255)
1424 return 1;
1425
1426 if (dinfo->depth == 8) {
1427 red >>= 8;
1428 green >>= 8;
1429 blue >>= 8;
1430
1431 intelfbhw_setcolreg(dinfo, regno, red, green, blue,
1432 transp);
1433 }
1434
1435 if (regno < 16) {
1436 switch (dinfo->depth) {
1437 case 15:
1438 dinfo->pseudo_palette[regno] = ((red & 0xf800) >> 1) |
1439 ((green & 0xf800) >> 6) |
1440 ((blue & 0xf800) >> 11);
1441 break;
1442 case 16:
1443 dinfo->pseudo_palette[regno] = (red & 0xf800) |
1444 ((green & 0xfc00) >> 5) |
1445 ((blue & 0xf800) >> 11);
1446 break;
1447 case 24:
1448 dinfo->pseudo_palette[regno] = ((red & 0xff00) << 8) |
1449 (green & 0xff00) |
1450 ((blue & 0xff00) >> 8);
1451 break;
1452 }
1453 }
1454
1455 return 0;
1456}
1457
1458static int intelfb_blank(int blank, struct fb_info *info)
1459{
1460 intelfbhw_do_blank(blank, info);
1461 return 0;
1462}
1463
1464static int intelfb_pan_display(struct fb_var_screeninfo *var,
1465 struct fb_info *info)
1466{
1467 intelfbhw_pan_display(var, info);
1468 return 0;
1469}
1470
1471/* When/if we have our own ioctls. */
1472static int intelfb_ioctl(struct fb_info *info, unsigned int cmd,
1473 unsigned long arg)
1474{
1475 int retval = 0;
1476 struct intelfb_info *dinfo = GET_DINFO(info);
1477 u32 pipe = 0;
1478
1479 switch (cmd) {
1480 case FBIO_WAITFORVSYNC:
1481 if (get_user(pipe, (__u32 __user *)arg))
1482 return -EFAULT;
1483
1484 retval = intelfbhw_wait_for_vsync(dinfo, pipe);
1485 break;
1486 default:
1487 break;
1488 }
1489
1490 return retval;
1491}
1492
1493static void intelfb_fillrect (struct fb_info *info,
1494 const struct fb_fillrect *rect)
1495{
1496 struct intelfb_info *dinfo = GET_DINFO(info);
1497 u32 rop, color;
1498
1499#if VERBOSE > 0
1500 DBG_MSG("intelfb_fillrect\n");
1501#endif
1502
1503 if (!ACCEL(dinfo, info) || dinfo->depth == 4) {
1504 cfb_fillrect(info, rect);
1505 return;
1506 }
1507
1508 if (rect->rop == ROP_COPY)
1509 rop = PAT_ROP_GXCOPY;
1510 else /* ROP_XOR */
1511 rop = PAT_ROP_GXXOR;
1512
1513 if (dinfo->depth != 8)
1514 color = dinfo->pseudo_palette[rect->color];
1515 else
1516 color = rect->color;
1517
1518 intelfbhw_do_fillrect(dinfo, rect->dx, rect->dy,
1519 rect->width, rect->height, color,
1520 dinfo->pitch, info->var.bits_per_pixel,
1521 rop);
1522}
1523
1524static void intelfb_copyarea(struct fb_info *info,
1525 const struct fb_copyarea *region)
1526{
1527 struct intelfb_info *dinfo = GET_DINFO(info);
1528
1529#if VERBOSE > 0
1530 DBG_MSG("intelfb_copyarea\n");
1531#endif
1532
1533 if (!ACCEL(dinfo, info) || dinfo->depth == 4) {
1534 cfb_copyarea(info, region);
1535 return;
1536 }
1537
1538 intelfbhw_do_bitblt(dinfo, region->sx, region->sy, region->dx,
1539 region->dy, region->width, region->height,
1540 dinfo->pitch, info->var.bits_per_pixel);
1541}
1542
1543static void intelfb_imageblit(struct fb_info *info,
1544 const struct fb_image *image)
1545{
1546 struct intelfb_info *dinfo = GET_DINFO(info);
1547 u32 fgcolor, bgcolor;
1548
1549#if VERBOSE > 0
1550 DBG_MSG("intelfb_imageblit\n");
1551#endif
1552
1553 if (!ACCEL(dinfo, info) || dinfo->depth == 4
1554 || image->depth != 1) {
1555 cfb_imageblit(info, image);
1556 return;
1557 }
1558
1559 if (dinfo->depth != 8) {
1560 fgcolor = dinfo->pseudo_palette[image->fg_color];
1561 bgcolor = dinfo->pseudo_palette[image->bg_color];
1562 } else {
1563 fgcolor = image->fg_color;
1564 bgcolor = image->bg_color;
1565 }
1566
1567 if (!intelfbhw_do_drawglyph(dinfo, fgcolor, bgcolor, image->width,
1568 image->height, image->data,
1569 image->dx, image->dy,
1570 dinfo->pitch, info->var.bits_per_pixel)) {
1571 cfb_imageblit(info, image);
1572 return;
1573 }
1574}
1575
1576static int intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1577{
1578 struct intelfb_info *dinfo = GET_DINFO(info);
1579 u32 physical;
1580#if VERBOSE > 0
1581 DBG_MSG("intelfb_cursor\n");
1582#endif
1583
1584 if (!dinfo->hwcursor)
1585 return -ENODEV;
1586
1587 intelfbhw_cursor_hide(dinfo);
1588
1589 /* If XFree killed the cursor - restore it */
1590 physical = (dinfo->mobile || IS_I9XX(dinfo)) ? dinfo->cursor.physical :
1591 (dinfo->cursor.offset << 12);
1592
1593 if (INREG(CURSOR_A_BASEADDR) != physical) {
1594 u32 fg, bg;
1595
1596 DBG_MSG("the cursor was killed - restore it !!\n");
1597 DBG_MSG("size %d, %d pos %d, %d\n",
1598 cursor->image.width, cursor->image.height,
1599 cursor->image.dx, cursor->image.dy);
1600
1601 intelfbhw_cursor_init(dinfo);
1602 intelfbhw_cursor_reset(dinfo);
1603 intelfbhw_cursor_setpos(dinfo, cursor->image.dx,
1604 cursor->image.dy);
1605
1606 if (dinfo->depth != 8) {
1607 fg =dinfo->pseudo_palette[cursor->image.fg_color];
1608 bg =dinfo->pseudo_palette[cursor->image.bg_color];
1609 } else {
1610 fg = cursor->image.fg_color;
1611 bg = cursor->image.bg_color;
1612 }
1613 intelfbhw_cursor_setcolor(dinfo, bg, fg);
1614 intelfbhw_cursor_load(dinfo, cursor->image.width,
1615 cursor->image.height,
1616 dinfo->cursor_src);
1617
1618 if (cursor->enable)
1619 intelfbhw_cursor_show(dinfo);
1620 return 0;
1621 }
1622
1623 if (cursor->set & FB_CUR_SETPOS) {
1624 u32 dx, dy;
1625
1626 dx = cursor->image.dx - info->var.xoffset;
1627 dy = cursor->image.dy - info->var.yoffset;
1628
1629 intelfbhw_cursor_setpos(dinfo, dx, dy);
1630 }
1631
1632 if (cursor->set & FB_CUR_SETSIZE) {
1633 if (cursor->image.width > 64 || cursor->image.height > 64)
1634 return -ENXIO;
1635
1636 intelfbhw_cursor_reset(dinfo);
1637 }
1638
1639 if (cursor->set & FB_CUR_SETCMAP) {
1640 u32 fg, bg;
1641
1642 if (dinfo->depth != 8) {
1643 fg = dinfo->pseudo_palette[cursor->image.fg_color];
1644 bg = dinfo->pseudo_palette[cursor->image.bg_color];
1645 } else {
1646 fg = cursor->image.fg_color;
1647 bg = cursor->image.bg_color;
1648 }
1649
1650 intelfbhw_cursor_setcolor(dinfo, bg, fg);
1651 }
1652
1653 if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
1654 u32 s_pitch = (ROUND_UP_TO(cursor->image.width, 8) / 8);
1655 u32 size = s_pitch * cursor->image.height;
1656 u8 *dat = (u8 *) cursor->image.data;
1657 u8 *msk = (u8 *) cursor->mask;
1658 u8 src[64];
1659 u32 i;
1660
1661 if (cursor->image.depth != 1)
1662 return -ENXIO;
1663
1664 switch (cursor->rop) {
1665 case ROP_XOR:
1666 for (i = 0; i < size; i++)
1667 src[i] = dat[i] ^ msk[i];
1668 break;
1669 case ROP_COPY:
1670 default:
1671 for (i = 0; i < size; i++)
1672 src[i] = dat[i] & msk[i];
1673 break;
1674 }
1675
1676 /* save the bitmap to restore it when XFree will
1677 make the cursor dirty */
1678 memcpy(dinfo->cursor_src, src, size);
1679
1680 intelfbhw_cursor_load(dinfo, cursor->image.width,
1681 cursor->image.height, src);
1682 }
1683
1684 if (cursor->enable)
1685 intelfbhw_cursor_show(dinfo);
1686
1687 return 0;
1688}
1689
1690static int intelfb_sync(struct fb_info *info)
1691{
1692 struct intelfb_info *dinfo = GET_DINFO(info);
1693
1694#if VERBOSE > 0
1695 DBG_MSG("intelfb_sync\n");
1696#endif
1697
1698 if (dinfo->ring_lockup)
1699 return 0;
1700
1701 intelfbhw_do_sync(dinfo);
1702 return 0;
1703}
1704
diff --git a/drivers/video/fbdev/intelfb/intelfbhw.c b/drivers/video/fbdev/intelfb/intelfbhw.c
new file mode 100644
index 000000000000..fbad61da359f
--- /dev/null
+++ b/drivers/video/fbdev/intelfb/intelfbhw.c
@@ -0,0 +1,2121 @@
1/*
2 * intelfb
3 *
4 * Linux framebuffer driver for Intel(R) 865G integrated graphics chips.
5 *
6 * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
7 * 2004 Sylvain Meyer
8 *
9 * This driver consists of two parts. The first part (intelfbdrv.c) provides
10 * the basic fbdev interfaces, is derived in part from the radeonfb and
11 * vesafb drivers, and is covered by the GPL. The second part (intelfbhw.c)
12 * provides the code to program the hardware. Most of it is derived from
13 * the i810/i830 XFree86 driver. The HW-specific code is covered here
14 * under a dual license (GPL and MIT/XFree86 license).
15 *
16 * Author: David Dawes
17 *
18 */
19
20/* $DHD: intelfb/intelfbhw.c,v 1.9 2003/06/27 15:06:25 dawes Exp $ */
21
22#include <linux/module.h>
23#include <linux/kernel.h>
24#include <linux/errno.h>
25#include <linux/string.h>
26#include <linux/mm.h>
27#include <linux/delay.h>
28#include <linux/fb.h>
29#include <linux/ioport.h>
30#include <linux/init.h>
31#include <linux/pci.h>
32#include <linux/vmalloc.h>
33#include <linux/pagemap.h>
34#include <linux/interrupt.h>
35
36#include <asm/io.h>
37
38#include "intelfb.h"
39#include "intelfbhw.h"
40
41struct pll_min_max {
42 int min_m, max_m, min_m1, max_m1;
43 int min_m2, max_m2, min_n, max_n;
44 int min_p, max_p, min_p1, max_p1;
45 int min_vco, max_vco, p_transition_clk, ref_clk;
46 int p_inc_lo, p_inc_hi;
47};
48
49#define PLLS_I8xx 0
50#define PLLS_I9xx 1
51#define PLLS_MAX 2
52
53static struct pll_min_max plls[PLLS_MAX] = {
54 { 108, 140, 18, 26,
55 6, 16, 3, 16,
56 4, 128, 0, 31,
57 930000, 1400000, 165000, 48000,
58 4, 2 }, /* I8xx */
59
60 { 75, 120, 10, 20,
61 5, 9, 4, 7,
62 5, 80, 1, 8,
63 1400000, 2800000, 200000, 96000,
64 10, 5 } /* I9xx */
65};
66
67int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo)
68{
69 u32 tmp;
70 if (!pdev || !dinfo)
71 return 1;
72
73 switch (pdev->device) {
74 case PCI_DEVICE_ID_INTEL_830M:
75 dinfo->name = "Intel(R) 830M";
76 dinfo->chipset = INTEL_830M;
77 dinfo->mobile = 1;
78 dinfo->pll_index = PLLS_I8xx;
79 return 0;
80 case PCI_DEVICE_ID_INTEL_845G:
81 dinfo->name = "Intel(R) 845G";
82 dinfo->chipset = INTEL_845G;
83 dinfo->mobile = 0;
84 dinfo->pll_index = PLLS_I8xx;
85 return 0;
86 case PCI_DEVICE_ID_INTEL_854:
87 dinfo->mobile = 1;
88 dinfo->name = "Intel(R) 854";
89 dinfo->chipset = INTEL_854;
90 return 0;
91 case PCI_DEVICE_ID_INTEL_85XGM:
92 tmp = 0;
93 dinfo->mobile = 1;
94 dinfo->pll_index = PLLS_I8xx;
95 pci_read_config_dword(pdev, INTEL_85X_CAPID, &tmp);
96 switch ((tmp >> INTEL_85X_VARIANT_SHIFT) &
97 INTEL_85X_VARIANT_MASK) {
98 case INTEL_VAR_855GME:
99 dinfo->name = "Intel(R) 855GME";
100 dinfo->chipset = INTEL_855GME;
101 return 0;
102 case INTEL_VAR_855GM:
103 dinfo->name = "Intel(R) 855GM";
104 dinfo->chipset = INTEL_855GM;
105 return 0;
106 case INTEL_VAR_852GME:
107 dinfo->name = "Intel(R) 852GME";
108 dinfo->chipset = INTEL_852GME;
109 return 0;
110 case INTEL_VAR_852GM:
111 dinfo->name = "Intel(R) 852GM";
112 dinfo->chipset = INTEL_852GM;
113 return 0;
114 default:
115 dinfo->name = "Intel(R) 852GM/855GM";
116 dinfo->chipset = INTEL_85XGM;
117 return 0;
118 }
119 break;
120 case PCI_DEVICE_ID_INTEL_865G:
121 dinfo->name = "Intel(R) 865G";
122 dinfo->chipset = INTEL_865G;
123 dinfo->mobile = 0;
124 dinfo->pll_index = PLLS_I8xx;
125 return 0;
126 case PCI_DEVICE_ID_INTEL_915G:
127 dinfo->name = "Intel(R) 915G";
128 dinfo->chipset = INTEL_915G;
129 dinfo->mobile = 0;
130 dinfo->pll_index = PLLS_I9xx;
131 return 0;
132 case PCI_DEVICE_ID_INTEL_915GM:
133 dinfo->name = "Intel(R) 915GM";
134 dinfo->chipset = INTEL_915GM;
135 dinfo->mobile = 1;
136 dinfo->pll_index = PLLS_I9xx;
137 return 0;
138 case PCI_DEVICE_ID_INTEL_945G:
139 dinfo->name = "Intel(R) 945G";
140 dinfo->chipset = INTEL_945G;
141 dinfo->mobile = 0;
142 dinfo->pll_index = PLLS_I9xx;
143 return 0;
144 case PCI_DEVICE_ID_INTEL_945GM:
145 dinfo->name = "Intel(R) 945GM";
146 dinfo->chipset = INTEL_945GM;
147 dinfo->mobile = 1;
148 dinfo->pll_index = PLLS_I9xx;
149 return 0;
150 case PCI_DEVICE_ID_INTEL_945GME:
151 dinfo->name = "Intel(R) 945GME";
152 dinfo->chipset = INTEL_945GME;
153 dinfo->mobile = 1;
154 dinfo->pll_index = PLLS_I9xx;
155 return 0;
156 case PCI_DEVICE_ID_INTEL_965G:
157 dinfo->name = "Intel(R) 965G";
158 dinfo->chipset = INTEL_965G;
159 dinfo->mobile = 0;
160 dinfo->pll_index = PLLS_I9xx;
161 return 0;
162 case PCI_DEVICE_ID_INTEL_965GM:
163 dinfo->name = "Intel(R) 965GM";
164 dinfo->chipset = INTEL_965GM;
165 dinfo->mobile = 1;
166 dinfo->pll_index = PLLS_I9xx;
167 return 0;
168 default:
169 return 1;
170 }
171}
172
173int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
174 int *stolen_size)
175{
176 struct pci_dev *bridge_dev;
177 u16 tmp;
178 int stolen_overhead;
179
180 if (!pdev || !aperture_size || !stolen_size)
181 return 1;
182
183 /* Find the bridge device. It is always 0:0.0 */
184 if (!(bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0)))) {
185 ERR_MSG("cannot find bridge device\n");
186 return 1;
187 }
188
189 /* Get the fb aperture size and "stolen" memory amount. */
190 tmp = 0;
191 pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp);
192 pci_dev_put(bridge_dev);
193
194 switch (pdev->device) {
195 case PCI_DEVICE_ID_INTEL_915G:
196 case PCI_DEVICE_ID_INTEL_915GM:
197 case PCI_DEVICE_ID_INTEL_945G:
198 case PCI_DEVICE_ID_INTEL_945GM:
199 case PCI_DEVICE_ID_INTEL_945GME:
200 case PCI_DEVICE_ID_INTEL_965G:
201 case PCI_DEVICE_ID_INTEL_965GM:
202 /* 915, 945 and 965 chipsets support a 256MB aperture.
203 Aperture size is determined by inspected the
204 base address of the aperture. */
205 if (pci_resource_start(pdev, 2) & 0x08000000)
206 *aperture_size = MB(128);
207 else
208 *aperture_size = MB(256);
209 break;
210 default:
211 if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M)
212 *aperture_size = MB(64);
213 else
214 *aperture_size = MB(128);
215 break;
216 }
217
218 /* Stolen memory size is reduced by the GTT and the popup.
219 GTT is 1K per MB of aperture size, and popup is 4K. */
220 stolen_overhead = (*aperture_size / MB(1)) + 4;
221 switch(pdev->device) {
222 case PCI_DEVICE_ID_INTEL_830M:
223 case PCI_DEVICE_ID_INTEL_845G:
224 switch (tmp & INTEL_830_GMCH_GMS_MASK) {
225 case INTEL_830_GMCH_GMS_STOLEN_512:
226 *stolen_size = KB(512) - KB(stolen_overhead);
227 return 0;
228 case INTEL_830_GMCH_GMS_STOLEN_1024:
229 *stolen_size = MB(1) - KB(stolen_overhead);
230 return 0;
231 case INTEL_830_GMCH_GMS_STOLEN_8192:
232 *stolen_size = MB(8) - KB(stolen_overhead);
233 return 0;
234 case INTEL_830_GMCH_GMS_LOCAL:
235 ERR_MSG("only local memory found\n");
236 return 1;
237 case INTEL_830_GMCH_GMS_DISABLED:
238 ERR_MSG("video memory is disabled\n");
239 return 1;
240 default:
241 ERR_MSG("unexpected GMCH_GMS value: 0x%02x\n",
242 tmp & INTEL_830_GMCH_GMS_MASK);
243 return 1;
244 }
245 break;
246 default:
247 switch (tmp & INTEL_855_GMCH_GMS_MASK) {
248 case INTEL_855_GMCH_GMS_STOLEN_1M:
249 *stolen_size = MB(1) - KB(stolen_overhead);
250 return 0;
251 case INTEL_855_GMCH_GMS_STOLEN_4M:
252 *stolen_size = MB(4) - KB(stolen_overhead);
253 return 0;
254 case INTEL_855_GMCH_GMS_STOLEN_8M:
255 *stolen_size = MB(8) - KB(stolen_overhead);
256 return 0;
257 case INTEL_855_GMCH_GMS_STOLEN_16M:
258 *stolen_size = MB(16) - KB(stolen_overhead);
259 return 0;
260 case INTEL_855_GMCH_GMS_STOLEN_32M:
261 *stolen_size = MB(32) - KB(stolen_overhead);
262 return 0;
263 case INTEL_915G_GMCH_GMS_STOLEN_48M:
264 *stolen_size = MB(48) - KB(stolen_overhead);
265 return 0;
266 case INTEL_915G_GMCH_GMS_STOLEN_64M:
267 *stolen_size = MB(64) - KB(stolen_overhead);
268 return 0;
269 case INTEL_855_GMCH_GMS_DISABLED:
270 ERR_MSG("video memory is disabled\n");
271 return 0;
272 default:
273 ERR_MSG("unexpected GMCH_GMS value: 0x%02x\n",
274 tmp & INTEL_855_GMCH_GMS_MASK);
275 return 1;
276 }
277 }
278}
279
280int intelfbhw_check_non_crt(struct intelfb_info *dinfo)
281{
282 int dvo = 0;
283
284 if (INREG(LVDS) & PORT_ENABLE)
285 dvo |= LVDS_PORT;
286 if (INREG(DVOA) & PORT_ENABLE)
287 dvo |= DVOA_PORT;
288 if (INREG(DVOB) & PORT_ENABLE)
289 dvo |= DVOB_PORT;
290 if (INREG(DVOC) & PORT_ENABLE)
291 dvo |= DVOC_PORT;
292
293 return dvo;
294}
295
296const char * intelfbhw_dvo_to_string(int dvo)
297{
298 if (dvo & DVOA_PORT)
299 return "DVO port A";
300 else if (dvo & DVOB_PORT)
301 return "DVO port B";
302 else if (dvo & DVOC_PORT)
303 return "DVO port C";
304 else if (dvo & LVDS_PORT)
305 return "LVDS port";
306 else
307 return NULL;
308}
309
310
311int intelfbhw_validate_mode(struct intelfb_info *dinfo,
312 struct fb_var_screeninfo *var)
313{
314 int bytes_per_pixel;
315 int tmp;
316
317#if VERBOSE > 0
318 DBG_MSG("intelfbhw_validate_mode\n");
319#endif
320
321 bytes_per_pixel = var->bits_per_pixel / 8;
322 if (bytes_per_pixel == 3)
323 bytes_per_pixel = 4;
324
325 /* Check if enough video memory. */
326 tmp = var->yres_virtual * var->xres_virtual * bytes_per_pixel;
327 if (tmp > dinfo->fb.size) {
328 WRN_MSG("Not enough video ram for mode "
329 "(%d KByte vs %d KByte).\n",
330 BtoKB(tmp), BtoKB(dinfo->fb.size));
331 return 1;
332 }
333
334 /* Check if x/y limits are OK. */
335 if (var->xres - 1 > HACTIVE_MASK) {
336 WRN_MSG("X resolution too large (%d vs %d).\n",
337 var->xres, HACTIVE_MASK + 1);
338 return 1;
339 }
340 if (var->yres - 1 > VACTIVE_MASK) {
341 WRN_MSG("Y resolution too large (%d vs %d).\n",
342 var->yres, VACTIVE_MASK + 1);
343 return 1;
344 }
345 if (var->xres < 4) {
346 WRN_MSG("X resolution too small (%d vs 4).\n", var->xres);
347 return 1;
348 }
349 if (var->yres < 4) {
350 WRN_MSG("Y resolution too small (%d vs 4).\n", var->yres);
351 return 1;
352 }
353
354 /* Check for doublescan modes. */
355 if (var->vmode & FB_VMODE_DOUBLE) {
356 WRN_MSG("Mode is double-scan.\n");
357 return 1;
358 }
359
360 if ((var->vmode & FB_VMODE_INTERLACED) && (var->yres & 1)) {
361 WRN_MSG("Odd number of lines in interlaced mode\n");
362 return 1;
363 }
364
365 /* Check if clock is OK. */
366 tmp = 1000000000 / var->pixclock;
367 if (tmp < MIN_CLOCK) {
368 WRN_MSG("Pixel clock is too low (%d MHz vs %d MHz).\n",
369 (tmp + 500) / 1000, MIN_CLOCK / 1000);
370 return 1;
371 }
372 if (tmp > MAX_CLOCK) {
373 WRN_MSG("Pixel clock is too high (%d MHz vs %d MHz).\n",
374 (tmp + 500) / 1000, MAX_CLOCK / 1000);
375 return 1;
376 }
377
378 return 0;
379}
380
381int intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
382{
383 struct intelfb_info *dinfo = GET_DINFO(info);
384 u32 offset, xoffset, yoffset;
385
386#if VERBOSE > 0
387 DBG_MSG("intelfbhw_pan_display\n");
388#endif
389
390 xoffset = ROUND_DOWN_TO(var->xoffset, 8);
391 yoffset = var->yoffset;
392
393 if ((xoffset + info->var.xres > info->var.xres_virtual) ||
394 (yoffset + info->var.yres > info->var.yres_virtual))
395 return -EINVAL;
396
397 offset = (yoffset * dinfo->pitch) +
398 (xoffset * info->var.bits_per_pixel) / 8;
399
400 offset += dinfo->fb.offset << 12;
401
402 dinfo->vsync.pan_offset = offset;
403 if ((var->activate & FB_ACTIVATE_VBL) &&
404 !intelfbhw_enable_irq(dinfo))
405 dinfo->vsync.pan_display = 1;
406 else {
407 dinfo->vsync.pan_display = 0;
408 OUTREG(DSPABASE, offset);
409 }
410
411 return 0;
412}
413
414/* Blank the screen. */
415void intelfbhw_do_blank(int blank, struct fb_info *info)
416{
417 struct intelfb_info *dinfo = GET_DINFO(info);
418 u32 tmp;
419
420#if VERBOSE > 0
421 DBG_MSG("intelfbhw_do_blank: blank is %d\n", blank);
422#endif
423
424 /* Turn plane A on or off */
425 tmp = INREG(DSPACNTR);
426 if (blank)
427 tmp &= ~DISPPLANE_PLANE_ENABLE;
428 else
429 tmp |= DISPPLANE_PLANE_ENABLE;
430 OUTREG(DSPACNTR, tmp);
431 /* Flush */
432 tmp = INREG(DSPABASE);
433 OUTREG(DSPABASE, tmp);
434
435 /* Turn off/on the HW cursor */
436#if VERBOSE > 0
437 DBG_MSG("cursor_on is %d\n", dinfo->cursor_on);
438#endif
439 if (dinfo->cursor_on) {
440 if (blank)
441 intelfbhw_cursor_hide(dinfo);
442 else
443 intelfbhw_cursor_show(dinfo);
444 dinfo->cursor_on = 1;
445 }
446 dinfo->cursor_blanked = blank;
447
448 /* Set DPMS level */
449 tmp = INREG(ADPA) & ~ADPA_DPMS_CONTROL_MASK;
450 switch (blank) {
451 case FB_BLANK_UNBLANK:
452 case FB_BLANK_NORMAL:
453 tmp |= ADPA_DPMS_D0;
454 break;
455 case FB_BLANK_VSYNC_SUSPEND:
456 tmp |= ADPA_DPMS_D1;
457 break;
458 case FB_BLANK_HSYNC_SUSPEND:
459 tmp |= ADPA_DPMS_D2;
460 break;
461 case FB_BLANK_POWERDOWN:
462 tmp |= ADPA_DPMS_D3;
463 break;
464 }
465 OUTREG(ADPA, tmp);
466
467 return;
468}
469
470
471/* Check which pipe is connected to an active display plane. */
472int intelfbhw_active_pipe(const struct intelfb_hwstate *hw)
473{
474 int pipe = -1;
475
476 /* keep old default behaviour - prefer PIPE_A */
477 if (hw->disp_b_ctrl & DISPPLANE_PLANE_ENABLE) {
478 pipe = (hw->disp_b_ctrl >> DISPPLANE_SEL_PIPE_SHIFT);
479 pipe &= PIPE_MASK;
480 if (unlikely(pipe == PIPE_A))
481 return PIPE_A;
482 }
483 if (hw->disp_a_ctrl & DISPPLANE_PLANE_ENABLE) {
484 pipe = (hw->disp_a_ctrl >> DISPPLANE_SEL_PIPE_SHIFT);
485 pipe &= PIPE_MASK;
486 if (likely(pipe == PIPE_A))
487 return PIPE_A;
488 }
489 /* Impossible that no pipe is selected - return PIPE_A */
490 WARN_ON(pipe == -1);
491 if (unlikely(pipe == -1))
492 pipe = PIPE_A;
493
494 return pipe;
495}
496
497void intelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno,
498 unsigned red, unsigned green, unsigned blue,
499 unsigned transp)
500{
501 u32 palette_reg = (dinfo->pipe == PIPE_A) ?
502 PALETTE_A : PALETTE_B;
503
504#if VERBOSE > 0
505 DBG_MSG("intelfbhw_setcolreg: %d: (%d, %d, %d)\n",
506 regno, red, green, blue);
507#endif
508
509 OUTREG(palette_reg + (regno << 2),
510 (red << PALETTE_8_RED_SHIFT) |
511 (green << PALETTE_8_GREEN_SHIFT) |
512 (blue << PALETTE_8_BLUE_SHIFT));
513}
514
515
516int intelfbhw_read_hw_state(struct intelfb_info *dinfo,
517 struct intelfb_hwstate *hw, int flag)
518{
519 int i;
520
521#if VERBOSE > 0
522 DBG_MSG("intelfbhw_read_hw_state\n");
523#endif
524
525 if (!hw || !dinfo)
526 return -1;
527
528 /* Read in as much of the HW state as possible. */
529 hw->vga0_divisor = INREG(VGA0_DIVISOR);
530 hw->vga1_divisor = INREG(VGA1_DIVISOR);
531 hw->vga_pd = INREG(VGAPD);
532 hw->dpll_a = INREG(DPLL_A);
533 hw->dpll_b = INREG(DPLL_B);
534 hw->fpa0 = INREG(FPA0);
535 hw->fpa1 = INREG(FPA1);
536 hw->fpb0 = INREG(FPB0);
537 hw->fpb1 = INREG(FPB1);
538
539 if (flag == 1)
540 return flag;
541
542#if 0
543 /* This seems to be a problem with the 852GM/855GM */
544 for (i = 0; i < PALETTE_8_ENTRIES; i++) {
545 hw->palette_a[i] = INREG(PALETTE_A + (i << 2));
546 hw->palette_b[i] = INREG(PALETTE_B + (i << 2));
547 }
548#endif
549
550 if (flag == 2)
551 return flag;
552
553 hw->htotal_a = INREG(HTOTAL_A);
554 hw->hblank_a = INREG(HBLANK_A);
555 hw->hsync_a = INREG(HSYNC_A);
556 hw->vtotal_a = INREG(VTOTAL_A);
557 hw->vblank_a = INREG(VBLANK_A);
558 hw->vsync_a = INREG(VSYNC_A);
559 hw->src_size_a = INREG(SRC_SIZE_A);
560 hw->bclrpat_a = INREG(BCLRPAT_A);
561 hw->htotal_b = INREG(HTOTAL_B);
562 hw->hblank_b = INREG(HBLANK_B);
563 hw->hsync_b = INREG(HSYNC_B);
564 hw->vtotal_b = INREG(VTOTAL_B);
565 hw->vblank_b = INREG(VBLANK_B);
566 hw->vsync_b = INREG(VSYNC_B);
567 hw->src_size_b = INREG(SRC_SIZE_B);
568 hw->bclrpat_b = INREG(BCLRPAT_B);
569
570 if (flag == 3)
571 return flag;
572
573 hw->adpa = INREG(ADPA);
574 hw->dvoa = INREG(DVOA);
575 hw->dvob = INREG(DVOB);
576 hw->dvoc = INREG(DVOC);
577 hw->dvoa_srcdim = INREG(DVOA_SRCDIM);
578 hw->dvob_srcdim = INREG(DVOB_SRCDIM);
579 hw->dvoc_srcdim = INREG(DVOC_SRCDIM);
580 hw->lvds = INREG(LVDS);
581
582 if (flag == 4)
583 return flag;
584
585 hw->pipe_a_conf = INREG(PIPEACONF);
586 hw->pipe_b_conf = INREG(PIPEBCONF);
587 hw->disp_arb = INREG(DISPARB);
588
589 if (flag == 5)
590 return flag;
591
592 hw->cursor_a_control = INREG(CURSOR_A_CONTROL);
593 hw->cursor_b_control = INREG(CURSOR_B_CONTROL);
594 hw->cursor_a_base = INREG(CURSOR_A_BASEADDR);
595 hw->cursor_b_base = INREG(CURSOR_B_BASEADDR);
596
597 if (flag == 6)
598 return flag;
599
600 for (i = 0; i < 4; i++) {
601 hw->cursor_a_palette[i] = INREG(CURSOR_A_PALETTE0 + (i << 2));
602 hw->cursor_b_palette[i] = INREG(CURSOR_B_PALETTE0 + (i << 2));
603 }
604
605 if (flag == 7)
606 return flag;
607
608 hw->cursor_size = INREG(CURSOR_SIZE);
609
610 if (flag == 8)
611 return flag;
612
613 hw->disp_a_ctrl = INREG(DSPACNTR);
614 hw->disp_b_ctrl = INREG(DSPBCNTR);
615 hw->disp_a_base = INREG(DSPABASE);
616 hw->disp_b_base = INREG(DSPBBASE);
617 hw->disp_a_stride = INREG(DSPASTRIDE);
618 hw->disp_b_stride = INREG(DSPBSTRIDE);
619
620 if (flag == 9)
621 return flag;
622
623 hw->vgacntrl = INREG(VGACNTRL);
624
625 if (flag == 10)
626 return flag;
627
628 hw->add_id = INREG(ADD_ID);
629
630 if (flag == 11)
631 return flag;
632
633 for (i = 0; i < 7; i++) {
634 hw->swf0x[i] = INREG(SWF00 + (i << 2));
635 hw->swf1x[i] = INREG(SWF10 + (i << 2));
636 if (i < 3)
637 hw->swf3x[i] = INREG(SWF30 + (i << 2));
638 }
639
640 for (i = 0; i < 8; i++)
641 hw->fence[i] = INREG(FENCE + (i << 2));
642
643 hw->instpm = INREG(INSTPM);
644 hw->mem_mode = INREG(MEM_MODE);
645 hw->fw_blc_0 = INREG(FW_BLC_0);
646 hw->fw_blc_1 = INREG(FW_BLC_1);
647
648 hw->hwstam = INREG16(HWSTAM);
649 hw->ier = INREG16(IER);
650 hw->iir = INREG16(IIR);
651 hw->imr = INREG16(IMR);
652
653 return 0;
654}
655
656
657static int calc_vclock3(int index, int m, int n, int p)
658{
659 if (p == 0 || n == 0)
660 return 0;
661 return plls[index].ref_clk * m / n / p;
662}
663
664static int calc_vclock(int index, int m1, int m2, int n, int p1, int p2,
665 int lvds)
666{
667 struct pll_min_max *pll = &plls[index];
668 u32 m, vco, p;
669
670 m = (5 * (m1 + 2)) + (m2 + 2);
671 n += 2;
672 vco = pll->ref_clk * m / n;
673
674 if (index == PLLS_I8xx)
675 p = ((p1 + 2) * (1 << (p2 + 1)));
676 else
677 p = ((p1) * (p2 ? 5 : 10));
678 return vco / p;
679}
680
681#if REGDUMP
682static void intelfbhw_get_p1p2(struct intelfb_info *dinfo, int dpll,
683 int *o_p1, int *o_p2)
684{
685 int p1, p2;
686
687 if (IS_I9XX(dinfo)) {
688 if (dpll & DPLL_P1_FORCE_DIV2)
689 p1 = 1;
690 else
691 p1 = (dpll >> DPLL_P1_SHIFT) & 0xff;
692
693 p1 = ffs(p1);
694
695 p2 = (dpll >> DPLL_I9XX_P2_SHIFT) & DPLL_P2_MASK;
696 } else {
697 if (dpll & DPLL_P1_FORCE_DIV2)
698 p1 = 0;
699 else
700 p1 = (dpll >> DPLL_P1_SHIFT) & DPLL_P1_MASK;
701 p2 = (dpll >> DPLL_P2_SHIFT) & DPLL_P2_MASK;
702 }
703
704 *o_p1 = p1;
705 *o_p2 = p2;
706}
707#endif
708
709
710void intelfbhw_print_hw_state(struct intelfb_info *dinfo,
711 struct intelfb_hwstate *hw)
712{
713#if REGDUMP
714 int i, m1, m2, n, p1, p2;
715 int index = dinfo->pll_index;
716 DBG_MSG("intelfbhw_print_hw_state\n");
717
718 if (!hw)
719 return;
720 /* Read in as much of the HW state as possible. */
721 printk("hw state dump start\n");
722 printk(" VGA0_DIVISOR: 0x%08x\n", hw->vga0_divisor);
723 printk(" VGA1_DIVISOR: 0x%08x\n", hw->vga1_divisor);
724 printk(" VGAPD: 0x%08x\n", hw->vga_pd);
725 n = (hw->vga0_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
726 m1 = (hw->vga0_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
727 m2 = (hw->vga0_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
728
729 intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2);
730
731 printk(" VGA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
732 m1, m2, n, p1, p2);
733 printk(" VGA0: clock is %d\n",
734 calc_vclock(index, m1, m2, n, p1, p2, 0));
735
736 n = (hw->vga1_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
737 m1 = (hw->vga1_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
738 m2 = (hw->vga1_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
739
740 intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2);
741 printk(" VGA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
742 m1, m2, n, p1, p2);
743 printk(" VGA1: clock is %d\n",
744 calc_vclock(index, m1, m2, n, p1, p2, 0));
745
746 printk(" DPLL_A: 0x%08x\n", hw->dpll_a);
747 printk(" DPLL_B: 0x%08x\n", hw->dpll_b);
748 printk(" FPA0: 0x%08x\n", hw->fpa0);
749 printk(" FPA1: 0x%08x\n", hw->fpa1);
750 printk(" FPB0: 0x%08x\n", hw->fpb0);
751 printk(" FPB1: 0x%08x\n", hw->fpb1);
752
753 n = (hw->fpa0 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
754 m1 = (hw->fpa0 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
755 m2 = (hw->fpa0 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
756
757 intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2);
758
759 printk(" PLLA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
760 m1, m2, n, p1, p2);
761 printk(" PLLA0: clock is %d\n",
762 calc_vclock(index, m1, m2, n, p1, p2, 0));
763
764 n = (hw->fpa1 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
765 m1 = (hw->fpa1 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
766 m2 = (hw->fpa1 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
767
768 intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2);
769
770 printk(" PLLA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
771 m1, m2, n, p1, p2);
772 printk(" PLLA1: clock is %d\n",
773 calc_vclock(index, m1, m2, n, p1, p2, 0));
774
775#if 0
776 printk(" PALETTE_A:\n");
777 for (i = 0; i < PALETTE_8_ENTRIES)
778 printk(" %3d: 0x%08x\n", i, hw->palette_a[i]);
779 printk(" PALETTE_B:\n");
780 for (i = 0; i < PALETTE_8_ENTRIES)
781 printk(" %3d: 0x%08x\n", i, hw->palette_b[i]);
782#endif
783
784 printk(" HTOTAL_A: 0x%08x\n", hw->htotal_a);
785 printk(" HBLANK_A: 0x%08x\n", hw->hblank_a);
786 printk(" HSYNC_A: 0x%08x\n", hw->hsync_a);
787 printk(" VTOTAL_A: 0x%08x\n", hw->vtotal_a);
788 printk(" VBLANK_A: 0x%08x\n", hw->vblank_a);
789 printk(" VSYNC_A: 0x%08x\n", hw->vsync_a);
790 printk(" SRC_SIZE_A: 0x%08x\n", hw->src_size_a);
791 printk(" BCLRPAT_A: 0x%08x\n", hw->bclrpat_a);
792 printk(" HTOTAL_B: 0x%08x\n", hw->htotal_b);
793 printk(" HBLANK_B: 0x%08x\n", hw->hblank_b);
794 printk(" HSYNC_B: 0x%08x\n", hw->hsync_b);
795 printk(" VTOTAL_B: 0x%08x\n", hw->vtotal_b);
796 printk(" VBLANK_B: 0x%08x\n", hw->vblank_b);
797 printk(" VSYNC_B: 0x%08x\n", hw->vsync_b);
798 printk(" SRC_SIZE_B: 0x%08x\n", hw->src_size_b);
799 printk(" BCLRPAT_B: 0x%08x\n", hw->bclrpat_b);
800
801 printk(" ADPA: 0x%08x\n", hw->adpa);
802 printk(" DVOA: 0x%08x\n", hw->dvoa);
803 printk(" DVOB: 0x%08x\n", hw->dvob);
804 printk(" DVOC: 0x%08x\n", hw->dvoc);
805 printk(" DVOA_SRCDIM: 0x%08x\n", hw->dvoa_srcdim);
806 printk(" DVOB_SRCDIM: 0x%08x\n", hw->dvob_srcdim);
807 printk(" DVOC_SRCDIM: 0x%08x\n", hw->dvoc_srcdim);
808 printk(" LVDS: 0x%08x\n", hw->lvds);
809
810 printk(" PIPEACONF: 0x%08x\n", hw->pipe_a_conf);
811 printk(" PIPEBCONF: 0x%08x\n", hw->pipe_b_conf);
812 printk(" DISPARB: 0x%08x\n", hw->disp_arb);
813
814 printk(" CURSOR_A_CONTROL: 0x%08x\n", hw->cursor_a_control);
815 printk(" CURSOR_B_CONTROL: 0x%08x\n", hw->cursor_b_control);
816 printk(" CURSOR_A_BASEADDR: 0x%08x\n", hw->cursor_a_base);
817 printk(" CURSOR_B_BASEADDR: 0x%08x\n", hw->cursor_b_base);
818
819 printk(" CURSOR_A_PALETTE: ");
820 for (i = 0; i < 4; i++) {
821 printk("0x%08x", hw->cursor_a_palette[i]);
822 if (i < 3)
823 printk(", ");
824 }
825 printk("\n");
826 printk(" CURSOR_B_PALETTE: ");
827 for (i = 0; i < 4; i++) {
828 printk("0x%08x", hw->cursor_b_palette[i]);
829 if (i < 3)
830 printk(", ");
831 }
832 printk("\n");
833
834 printk(" CURSOR_SIZE: 0x%08x\n", hw->cursor_size);
835
836 printk(" DSPACNTR: 0x%08x\n", hw->disp_a_ctrl);
837 printk(" DSPBCNTR: 0x%08x\n", hw->disp_b_ctrl);
838 printk(" DSPABASE: 0x%08x\n", hw->disp_a_base);
839 printk(" DSPBBASE: 0x%08x\n", hw->disp_b_base);
840 printk(" DSPASTRIDE: 0x%08x\n", hw->disp_a_stride);
841 printk(" DSPBSTRIDE: 0x%08x\n", hw->disp_b_stride);
842
843 printk(" VGACNTRL: 0x%08x\n", hw->vgacntrl);
844 printk(" ADD_ID: 0x%08x\n", hw->add_id);
845
846 for (i = 0; i < 7; i++) {
847 printk(" SWF0%d 0x%08x\n", i,
848 hw->swf0x[i]);
849 }
850 for (i = 0; i < 7; i++) {
851 printk(" SWF1%d 0x%08x\n", i,
852 hw->swf1x[i]);
853 }
854 for (i = 0; i < 3; i++) {
855 printk(" SWF3%d 0x%08x\n", i,
856 hw->swf3x[i]);
857 }
858 for (i = 0; i < 8; i++)
859 printk(" FENCE%d 0x%08x\n", i,
860 hw->fence[i]);
861
862 printk(" INSTPM 0x%08x\n", hw->instpm);
863 printk(" MEM_MODE 0x%08x\n", hw->mem_mode);
864 printk(" FW_BLC_0 0x%08x\n", hw->fw_blc_0);
865 printk(" FW_BLC_1 0x%08x\n", hw->fw_blc_1);
866
867 printk(" HWSTAM 0x%04x\n", hw->hwstam);
868 printk(" IER 0x%04x\n", hw->ier);
869 printk(" IIR 0x%04x\n", hw->iir);
870 printk(" IMR 0x%04x\n", hw->imr);
871 printk("hw state dump end\n");
872#endif
873}
874
875
876
877/* Split the M parameter into M1 and M2. */
878static int splitm(int index, unsigned int m, unsigned int *retm1,
879 unsigned int *retm2)
880{
881 int m1, m2;
882 int testm;
883 struct pll_min_max *pll = &plls[index];
884
885 /* no point optimising too much - brute force m */
886 for (m1 = pll->min_m1; m1 < pll->max_m1 + 1; m1++) {
887 for (m2 = pll->min_m2; m2 < pll->max_m2 + 1; m2++) {
888 testm = (5 * (m1 + 2)) + (m2 + 2);
889 if (testm == m) {
890 *retm1 = (unsigned int)m1;
891 *retm2 = (unsigned int)m2;
892 return 0;
893 }
894 }
895 }
896 return 1;
897}
898
899/* Split the P parameter into P1 and P2. */
900static int splitp(int index, unsigned int p, unsigned int *retp1,
901 unsigned int *retp2)
902{
903 int p1, p2;
904 struct pll_min_max *pll = &plls[index];
905
906 if (index == PLLS_I9xx) {
907 p2 = (p % 10) ? 1 : 0;
908
909 p1 = p / (p2 ? 5 : 10);
910
911 *retp1 = (unsigned int)p1;
912 *retp2 = (unsigned int)p2;
913 return 0;
914 }
915
916 if (p % 4 == 0)
917 p2 = 1;
918 else
919 p2 = 0;
920 p1 = (p / (1 << (p2 + 1))) - 2;
921 if (p % 4 == 0 && p1 < pll->min_p1) {
922 p2 = 0;
923 p1 = (p / (1 << (p2 + 1))) - 2;
924 }
925 if (p1 < pll->min_p1 || p1 > pll->max_p1 ||
926 (p1 + 2) * (1 << (p2 + 1)) != p) {
927 return 1;
928 } else {
929 *retp1 = (unsigned int)p1;
930 *retp2 = (unsigned int)p2;
931 return 0;
932 }
933}
934
935static int calc_pll_params(int index, int clock, u32 *retm1, u32 *retm2,
936 u32 *retn, u32 *retp1, u32 *retp2, u32 *retclock)
937{
938 u32 m1, m2, n, p1, p2, n1, testm;
939 u32 f_vco, p, p_best = 0, m, f_out = 0;
940 u32 err_max, err_target, err_best = 10000000;
941 u32 n_best = 0, m_best = 0, f_best, f_err;
942 u32 p_min, p_max, p_inc, div_max;
943 struct pll_min_max *pll = &plls[index];
944
945 /* Accept 0.5% difference, but aim for 0.1% */
946 err_max = 5 * clock / 1000;
947 err_target = clock / 1000;
948
949 DBG_MSG("Clock is %d\n", clock);
950
951 div_max = pll->max_vco / clock;
952
953 p_inc = (clock <= pll->p_transition_clk) ? pll->p_inc_lo : pll->p_inc_hi;
954 p_min = p_inc;
955 p_max = ROUND_DOWN_TO(div_max, p_inc);
956 if (p_min < pll->min_p)
957 p_min = pll->min_p;
958 if (p_max > pll->max_p)
959 p_max = pll->max_p;
960
961 DBG_MSG("p range is %d-%d (%d)\n", p_min, p_max, p_inc);
962
963 p = p_min;
964 do {
965 if (splitp(index, p, &p1, &p2)) {
966 WRN_MSG("cannot split p = %d\n", p);
967 p += p_inc;
968 continue;
969 }
970 n = pll->min_n;
971 f_vco = clock * p;
972
973 do {
974 m = ROUND_UP_TO(f_vco * n, pll->ref_clk) / pll->ref_clk;
975 if (m < pll->min_m)
976 m = pll->min_m + 1;
977 if (m > pll->max_m)
978 m = pll->max_m - 1;
979 for (testm = m - 1; testm <= m; testm++) {
980 f_out = calc_vclock3(index, testm, n, p);
981 if (splitm(index, testm, &m1, &m2)) {
982 WRN_MSG("cannot split m = %d\n",
983 testm);
984 continue;
985 }
986 if (clock > f_out)
987 f_err = clock - f_out;
988 else/* slightly bias the error for bigger clocks */
989 f_err = f_out - clock + 1;
990
991 if (f_err < err_best) {
992 m_best = testm;
993 n_best = n;
994 p_best = p;
995 f_best = f_out;
996 err_best = f_err;
997 }
998 }
999 n++;
1000 } while ((n <= pll->max_n) && (f_out >= clock));
1001 p += p_inc;
1002 } while ((p <= p_max));
1003
1004 if (!m_best) {
1005 WRN_MSG("cannot find parameters for clock %d\n", clock);
1006 return 1;
1007 }
1008 m = m_best;
1009 n = n_best;
1010 p = p_best;
1011 splitm(index, m, &m1, &m2);
1012 splitp(index, p, &p1, &p2);
1013 n1 = n - 2;
1014
1015 DBG_MSG("m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), "
1016 "f: %d (%d), VCO: %d\n",
1017 m, m1, m2, n, n1, p, p1, p2,
1018 calc_vclock3(index, m, n, p),
1019 calc_vclock(index, m1, m2, n1, p1, p2, 0),
1020 calc_vclock3(index, m, n, p) * p);
1021 *retm1 = m1;
1022 *retm2 = m2;
1023 *retn = n1;
1024 *retp1 = p1;
1025 *retp2 = p2;
1026 *retclock = calc_vclock(index, m1, m2, n1, p1, p2, 0);
1027
1028 return 0;
1029}
1030
1031static __inline__ int check_overflow(u32 value, u32 limit,
1032 const char *description)
1033{
1034 if (value > limit) {
1035 WRN_MSG("%s value %d exceeds limit %d\n",
1036 description, value, limit);
1037 return 1;
1038 }
1039 return 0;
1040}
1041
1042/* It is assumed that hw is filled in with the initial state information. */
1043int intelfbhw_mode_to_hw(struct intelfb_info *dinfo,
1044 struct intelfb_hwstate *hw,
1045 struct fb_var_screeninfo *var)
1046{
1047 int pipe = intelfbhw_active_pipe(hw);
1048 u32 *dpll, *fp0, *fp1;
1049 u32 m1, m2, n, p1, p2, clock_target, clock;
1050 u32 hsync_start, hsync_end, hblank_start, hblank_end, htotal, hactive;
1051 u32 vsync_start, vsync_end, vblank_start, vblank_end, vtotal, vactive;
1052 u32 vsync_pol, hsync_pol;
1053 u32 *vs, *vb, *vt, *hs, *hb, *ht, *ss, *pipe_conf;
1054 u32 stride_alignment;
1055
1056 DBG_MSG("intelfbhw_mode_to_hw\n");
1057
1058 /* Disable VGA */
1059 hw->vgacntrl |= VGA_DISABLE;
1060
1061 /* Set which pipe's registers will be set. */
1062 if (pipe == PIPE_B) {
1063 dpll = &hw->dpll_b;
1064 fp0 = &hw->fpb0;
1065 fp1 = &hw->fpb1;
1066 hs = &hw->hsync_b;
1067 hb = &hw->hblank_b;
1068 ht = &hw->htotal_b;
1069 vs = &hw->vsync_b;
1070 vb = &hw->vblank_b;
1071 vt = &hw->vtotal_b;
1072 ss = &hw->src_size_b;
1073 pipe_conf = &hw->pipe_b_conf;
1074 } else {
1075 dpll = &hw->dpll_a;
1076 fp0 = &hw->fpa0;
1077 fp1 = &hw->fpa1;
1078 hs = &hw->hsync_a;
1079 hb = &hw->hblank_a;
1080 ht = &hw->htotal_a;
1081 vs = &hw->vsync_a;
1082 vb = &hw->vblank_a;
1083 vt = &hw->vtotal_a;
1084 ss = &hw->src_size_a;
1085 pipe_conf = &hw->pipe_a_conf;
1086 }
1087
1088 /* Use ADPA register for sync control. */
1089 hw->adpa &= ~ADPA_USE_VGA_HVPOLARITY;
1090
1091 /* sync polarity */
1092 hsync_pol = (var->sync & FB_SYNC_HOR_HIGH_ACT) ?
1093 ADPA_SYNC_ACTIVE_HIGH : ADPA_SYNC_ACTIVE_LOW;
1094 vsync_pol = (var->sync & FB_SYNC_VERT_HIGH_ACT) ?
1095 ADPA_SYNC_ACTIVE_HIGH : ADPA_SYNC_ACTIVE_LOW;
1096 hw->adpa &= ~((ADPA_SYNC_ACTIVE_MASK << ADPA_VSYNC_ACTIVE_SHIFT) |
1097 (ADPA_SYNC_ACTIVE_MASK << ADPA_HSYNC_ACTIVE_SHIFT));
1098 hw->adpa |= (hsync_pol << ADPA_HSYNC_ACTIVE_SHIFT) |
1099 (vsync_pol << ADPA_VSYNC_ACTIVE_SHIFT);
1100
1101 /* Connect correct pipe to the analog port DAC */
1102 hw->adpa &= ~(PIPE_MASK << ADPA_PIPE_SELECT_SHIFT);
1103 hw->adpa |= (pipe << ADPA_PIPE_SELECT_SHIFT);
1104
1105 /* Set DPMS state to D0 (on) */
1106 hw->adpa &= ~ADPA_DPMS_CONTROL_MASK;
1107 hw->adpa |= ADPA_DPMS_D0;
1108
1109 hw->adpa |= ADPA_DAC_ENABLE;
1110
1111 *dpll |= (DPLL_VCO_ENABLE | DPLL_VGA_MODE_DISABLE);
1112 *dpll &= ~(DPLL_RATE_SELECT_MASK | DPLL_REFERENCE_SELECT_MASK);
1113 *dpll |= (DPLL_REFERENCE_DEFAULT | DPLL_RATE_SELECT_FP0);
1114
1115 /* Desired clock in kHz */
1116 clock_target = 1000000000 / var->pixclock;
1117
1118 if (calc_pll_params(dinfo->pll_index, clock_target, &m1, &m2,
1119 &n, &p1, &p2, &clock)) {
1120 WRN_MSG("calc_pll_params failed\n");
1121 return 1;
1122 }
1123
1124 /* Check for overflow. */
1125 if (check_overflow(p1, DPLL_P1_MASK, "PLL P1 parameter"))
1126 return 1;
1127 if (check_overflow(p2, DPLL_P2_MASK, "PLL P2 parameter"))
1128 return 1;
1129 if (check_overflow(m1, FP_DIVISOR_MASK, "PLL M1 parameter"))
1130 return 1;
1131 if (check_overflow(m2, FP_DIVISOR_MASK, "PLL M2 parameter"))
1132 return 1;
1133 if (check_overflow(n, FP_DIVISOR_MASK, "PLL N parameter"))
1134 return 1;
1135
1136 *dpll &= ~DPLL_P1_FORCE_DIV2;
1137 *dpll &= ~((DPLL_P2_MASK << DPLL_P2_SHIFT) |
1138 (DPLL_P1_MASK << DPLL_P1_SHIFT));
1139
1140 if (IS_I9XX(dinfo)) {
1141 *dpll |= (p2 << DPLL_I9XX_P2_SHIFT);
1142 *dpll |= (1 << (p1 - 1)) << DPLL_P1_SHIFT;
1143 } else
1144 *dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT);
1145
1146 *fp0 = (n << FP_N_DIVISOR_SHIFT) |
1147 (m1 << FP_M1_DIVISOR_SHIFT) |
1148 (m2 << FP_M2_DIVISOR_SHIFT);
1149 *fp1 = *fp0;
1150
1151 hw->dvob &= ~PORT_ENABLE;
1152 hw->dvoc &= ~PORT_ENABLE;
1153
1154 /* Use display plane A. */
1155 hw->disp_a_ctrl |= DISPPLANE_PLANE_ENABLE;
1156 hw->disp_a_ctrl &= ~DISPPLANE_GAMMA_ENABLE;
1157 hw->disp_a_ctrl &= ~DISPPLANE_PIXFORMAT_MASK;
1158 switch (intelfb_var_to_depth(var)) {
1159 case 8:
1160 hw->disp_a_ctrl |= DISPPLANE_8BPP | DISPPLANE_GAMMA_ENABLE;
1161 break;
1162 case 15:
1163 hw->disp_a_ctrl |= DISPPLANE_15_16BPP;
1164 break;
1165 case 16:
1166 hw->disp_a_ctrl |= DISPPLANE_16BPP;
1167 break;
1168 case 24:
1169 hw->disp_a_ctrl |= DISPPLANE_32BPP_NO_ALPHA;
1170 break;
1171 }
1172 hw->disp_a_ctrl &= ~(PIPE_MASK << DISPPLANE_SEL_PIPE_SHIFT);
1173 hw->disp_a_ctrl |= (pipe << DISPPLANE_SEL_PIPE_SHIFT);
1174
1175 /* Set CRTC registers. */
1176 hactive = var->xres;
1177 hsync_start = hactive + var->right_margin;
1178 hsync_end = hsync_start + var->hsync_len;
1179 htotal = hsync_end + var->left_margin;
1180 hblank_start = hactive;
1181 hblank_end = htotal;
1182
1183 DBG_MSG("H: act %d, ss %d, se %d, tot %d bs %d, be %d\n",
1184 hactive, hsync_start, hsync_end, htotal, hblank_start,
1185 hblank_end);
1186
1187 vactive = var->yres;
1188 if (var->vmode & FB_VMODE_INTERLACED)
1189 vactive--; /* the chip adds 2 halflines automatically */
1190 vsync_start = vactive + var->lower_margin;
1191 vsync_end = vsync_start + var->vsync_len;
1192 vtotal = vsync_end + var->upper_margin;
1193 vblank_start = vactive;
1194 vblank_end = vtotal;
1195 vblank_end = vsync_end + 1;
1196
1197 DBG_MSG("V: act %d, ss %d, se %d, tot %d bs %d, be %d\n",
1198 vactive, vsync_start, vsync_end, vtotal, vblank_start,
1199 vblank_end);
1200
1201 /* Adjust for register values, and check for overflow. */
1202 hactive--;
1203 if (check_overflow(hactive, HACTIVE_MASK, "CRTC hactive"))
1204 return 1;
1205 hsync_start--;
1206 if (check_overflow(hsync_start, HSYNCSTART_MASK, "CRTC hsync_start"))
1207 return 1;
1208 hsync_end--;
1209 if (check_overflow(hsync_end, HSYNCEND_MASK, "CRTC hsync_end"))
1210 return 1;
1211 htotal--;
1212 if (check_overflow(htotal, HTOTAL_MASK, "CRTC htotal"))
1213 return 1;
1214 hblank_start--;
1215 if (check_overflow(hblank_start, HBLANKSTART_MASK, "CRTC hblank_start"))
1216 return 1;
1217 hblank_end--;
1218 if (check_overflow(hblank_end, HBLANKEND_MASK, "CRTC hblank_end"))
1219 return 1;
1220
1221 vactive--;
1222 if (check_overflow(vactive, VACTIVE_MASK, "CRTC vactive"))
1223 return 1;
1224 vsync_start--;
1225 if (check_overflow(vsync_start, VSYNCSTART_MASK, "CRTC vsync_start"))
1226 return 1;
1227 vsync_end--;
1228 if (check_overflow(vsync_end, VSYNCEND_MASK, "CRTC vsync_end"))
1229 return 1;
1230 vtotal--;
1231 if (check_overflow(vtotal, VTOTAL_MASK, "CRTC vtotal"))
1232 return 1;
1233 vblank_start--;
1234 if (check_overflow(vblank_start, VBLANKSTART_MASK, "CRTC vblank_start"))
1235 return 1;
1236 vblank_end--;
1237 if (check_overflow(vblank_end, VBLANKEND_MASK, "CRTC vblank_end"))
1238 return 1;
1239
1240 *ht = (htotal << HTOTAL_SHIFT) | (hactive << HACTIVE_SHIFT);
1241 *hb = (hblank_start << HBLANKSTART_SHIFT) |
1242 (hblank_end << HSYNCEND_SHIFT);
1243 *hs = (hsync_start << HSYNCSTART_SHIFT) | (hsync_end << HSYNCEND_SHIFT);
1244
1245 *vt = (vtotal << VTOTAL_SHIFT) | (vactive << VACTIVE_SHIFT);
1246 *vb = (vblank_start << VBLANKSTART_SHIFT) |
1247 (vblank_end << VSYNCEND_SHIFT);
1248 *vs = (vsync_start << VSYNCSTART_SHIFT) | (vsync_end << VSYNCEND_SHIFT);
1249 *ss = (hactive << SRC_SIZE_HORIZ_SHIFT) |
1250 (vactive << SRC_SIZE_VERT_SHIFT);
1251
1252 hw->disp_a_stride = dinfo->pitch;
1253 DBG_MSG("pitch is %d\n", hw->disp_a_stride);
1254
1255 hw->disp_a_base = hw->disp_a_stride * var->yoffset +
1256 var->xoffset * var->bits_per_pixel / 8;
1257
1258 hw->disp_a_base += dinfo->fb.offset << 12;
1259
1260 /* Check stride alignment. */
1261 stride_alignment = IS_I9XX(dinfo) ? STRIDE_ALIGNMENT_I9XX :
1262 STRIDE_ALIGNMENT;
1263 if (hw->disp_a_stride % stride_alignment != 0) {
1264 WRN_MSG("display stride %d has bad alignment %d\n",
1265 hw->disp_a_stride, stride_alignment);
1266 return 1;
1267 }
1268
1269 /* Set the palette to 8-bit mode. */
1270 *pipe_conf &= ~PIPECONF_GAMMA;
1271
1272 if (var->vmode & FB_VMODE_INTERLACED)
1273 *pipe_conf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
1274 else
1275 *pipe_conf &= ~PIPECONF_INTERLACE_MASK;
1276
1277 return 0;
1278}
1279
1280/* Program a (non-VGA) video mode. */
1281int intelfbhw_program_mode(struct intelfb_info *dinfo,
1282 const struct intelfb_hwstate *hw, int blank)
1283{
1284 u32 tmp;
1285 const u32 *dpll, *fp0, *fp1, *pipe_conf;
1286 const u32 *hs, *ht, *hb, *vs, *vt, *vb, *ss;
1287 u32 dpll_reg, fp0_reg, fp1_reg, pipe_conf_reg, pipe_stat_reg;
1288 u32 hsync_reg, htotal_reg, hblank_reg;
1289 u32 vsync_reg, vtotal_reg, vblank_reg;
1290 u32 src_size_reg;
1291 u32 count, tmp_val[3];
1292
1293 /* Assume single pipe */
1294
1295#if VERBOSE > 0
1296 DBG_MSG("intelfbhw_program_mode\n");
1297#endif
1298
1299 /* Disable VGA */
1300 tmp = INREG(VGACNTRL);
1301 tmp |= VGA_DISABLE;
1302 OUTREG(VGACNTRL, tmp);
1303
1304 dinfo->pipe = intelfbhw_active_pipe(hw);
1305
1306 if (dinfo->pipe == PIPE_B) {
1307 dpll = &hw->dpll_b;
1308 fp0 = &hw->fpb0;
1309 fp1 = &hw->fpb1;
1310 pipe_conf = &hw->pipe_b_conf;
1311 hs = &hw->hsync_b;
1312 hb = &hw->hblank_b;
1313 ht = &hw->htotal_b;
1314 vs = &hw->vsync_b;
1315 vb = &hw->vblank_b;
1316 vt = &hw->vtotal_b;
1317 ss = &hw->src_size_b;
1318 dpll_reg = DPLL_B;
1319 fp0_reg = FPB0;
1320 fp1_reg = FPB1;
1321 pipe_conf_reg = PIPEBCONF;
1322 pipe_stat_reg = PIPEBSTAT;
1323 hsync_reg = HSYNC_B;
1324 htotal_reg = HTOTAL_B;
1325 hblank_reg = HBLANK_B;
1326 vsync_reg = VSYNC_B;
1327 vtotal_reg = VTOTAL_B;
1328 vblank_reg = VBLANK_B;
1329 src_size_reg = SRC_SIZE_B;
1330 } else {
1331 dpll = &hw->dpll_a;
1332 fp0 = &hw->fpa0;
1333 fp1 = &hw->fpa1;
1334 pipe_conf = &hw->pipe_a_conf;
1335 hs = &hw->hsync_a;
1336 hb = &hw->hblank_a;
1337 ht = &hw->htotal_a;
1338 vs = &hw->vsync_a;
1339 vb = &hw->vblank_a;
1340 vt = &hw->vtotal_a;
1341 ss = &hw->src_size_a;
1342 dpll_reg = DPLL_A;
1343 fp0_reg = FPA0;
1344 fp1_reg = FPA1;
1345 pipe_conf_reg = PIPEACONF;
1346 pipe_stat_reg = PIPEASTAT;
1347 hsync_reg = HSYNC_A;
1348 htotal_reg = HTOTAL_A;
1349 hblank_reg = HBLANK_A;
1350 vsync_reg = VSYNC_A;
1351 vtotal_reg = VTOTAL_A;
1352 vblank_reg = VBLANK_A;
1353 src_size_reg = SRC_SIZE_A;
1354 }
1355
1356 /* turn off pipe */
1357 tmp = INREG(pipe_conf_reg);
1358 tmp &= ~PIPECONF_ENABLE;
1359 OUTREG(pipe_conf_reg, tmp);
1360
1361 count = 0;
1362 do {
1363 tmp_val[count % 3] = INREG(PIPEA_DSL);
1364 if ((tmp_val[0] == tmp_val[1]) && (tmp_val[1] == tmp_val[2]))
1365 break;
1366 count++;
1367 udelay(1);
1368 if (count % 200 == 0) {
1369 tmp = INREG(pipe_conf_reg);
1370 tmp &= ~PIPECONF_ENABLE;
1371 OUTREG(pipe_conf_reg, tmp);
1372 }
1373 } while (count < 2000);
1374
1375 OUTREG(ADPA, INREG(ADPA) & ~ADPA_DAC_ENABLE);
1376
1377 /* Disable planes A and B. */
1378 tmp = INREG(DSPACNTR);
1379 tmp &= ~DISPPLANE_PLANE_ENABLE;
1380 OUTREG(DSPACNTR, tmp);
1381 tmp = INREG(DSPBCNTR);
1382 tmp &= ~DISPPLANE_PLANE_ENABLE;
1383 OUTREG(DSPBCNTR, tmp);
1384
1385 /* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */
1386 mdelay(20);
1387
1388 OUTREG(DVOB, INREG(DVOB) & ~PORT_ENABLE);
1389 OUTREG(DVOC, INREG(DVOC) & ~PORT_ENABLE);
1390 OUTREG(ADPA, INREG(ADPA) & ~ADPA_DAC_ENABLE);
1391
1392 /* Disable Sync */
1393 tmp = INREG(ADPA);
1394 tmp &= ~ADPA_DPMS_CONTROL_MASK;
1395 tmp |= ADPA_DPMS_D3;
1396 OUTREG(ADPA, tmp);
1397
1398 /* do some funky magic - xyzzy */
1399 OUTREG(0x61204, 0xabcd0000);
1400
1401 /* turn off PLL */
1402 tmp = INREG(dpll_reg);
1403 tmp &= ~DPLL_VCO_ENABLE;
1404 OUTREG(dpll_reg, tmp);
1405
1406 /* Set PLL parameters */
1407 OUTREG(fp0_reg, *fp0);
1408 OUTREG(fp1_reg, *fp1);
1409
1410 /* Enable PLL */
1411 OUTREG(dpll_reg, *dpll);
1412
1413 /* Set DVOs B/C */
1414 OUTREG(DVOB, hw->dvob);
1415 OUTREG(DVOC, hw->dvoc);
1416
1417 /* undo funky magic */
1418 OUTREG(0x61204, 0x00000000);
1419
1420 /* Set ADPA */
1421 OUTREG(ADPA, INREG(ADPA) | ADPA_DAC_ENABLE);
1422 OUTREG(ADPA, (hw->adpa & ~(ADPA_DPMS_CONTROL_MASK)) | ADPA_DPMS_D3);
1423
1424 /* Set pipe parameters */
1425 OUTREG(hsync_reg, *hs);
1426 OUTREG(hblank_reg, *hb);
1427 OUTREG(htotal_reg, *ht);
1428 OUTREG(vsync_reg, *vs);
1429 OUTREG(vblank_reg, *vb);
1430 OUTREG(vtotal_reg, *vt);
1431 OUTREG(src_size_reg, *ss);
1432
1433 switch (dinfo->info->var.vmode & (FB_VMODE_INTERLACED |
1434 FB_VMODE_ODD_FLD_FIRST)) {
1435 case FB_VMODE_INTERLACED | FB_VMODE_ODD_FLD_FIRST:
1436 OUTREG(pipe_stat_reg, 0xFFFF | PIPESTAT_FLD_EVT_ODD_EN);
1437 break;
1438 case FB_VMODE_INTERLACED: /* even lines first */
1439 OUTREG(pipe_stat_reg, 0xFFFF | PIPESTAT_FLD_EVT_EVEN_EN);
1440 break;
1441 default: /* non-interlaced */
1442 OUTREG(pipe_stat_reg, 0xFFFF); /* clear all status bits only */
1443 }
1444 /* Enable pipe */
1445 OUTREG(pipe_conf_reg, *pipe_conf | PIPECONF_ENABLE);
1446
1447 /* Enable sync */
1448 tmp = INREG(ADPA);
1449 tmp &= ~ADPA_DPMS_CONTROL_MASK;
1450 tmp |= ADPA_DPMS_D0;
1451 OUTREG(ADPA, tmp);
1452
1453 /* setup display plane */
1454 if (dinfo->pdev->device == PCI_DEVICE_ID_INTEL_830M) {
1455 /*
1456 * i830M errata: the display plane must be enabled
1457 * to allow writes to the other bits in the plane
1458 * control register.
1459 */
1460 tmp = INREG(DSPACNTR);
1461 if ((tmp & DISPPLANE_PLANE_ENABLE) != DISPPLANE_PLANE_ENABLE) {
1462 tmp |= DISPPLANE_PLANE_ENABLE;
1463 OUTREG(DSPACNTR, tmp);
1464 OUTREG(DSPACNTR,
1465 hw->disp_a_ctrl|DISPPLANE_PLANE_ENABLE);
1466 mdelay(1);
1467 }
1468 }
1469
1470 OUTREG(DSPACNTR, hw->disp_a_ctrl & ~DISPPLANE_PLANE_ENABLE);
1471 OUTREG(DSPASTRIDE, hw->disp_a_stride);
1472 OUTREG(DSPABASE, hw->disp_a_base);
1473
1474 /* Enable plane */
1475 if (!blank) {
1476 tmp = INREG(DSPACNTR);
1477 tmp |= DISPPLANE_PLANE_ENABLE;
1478 OUTREG(DSPACNTR, tmp);
1479 OUTREG(DSPABASE, hw->disp_a_base);
1480 }
1481
1482 return 0;
1483}
1484
1485/* forward declarations */
1486static void refresh_ring(struct intelfb_info *dinfo);
1487static void reset_state(struct intelfb_info *dinfo);
1488static void do_flush(struct intelfb_info *dinfo);
1489
1490static u32 get_ring_space(struct intelfb_info *dinfo)
1491{
1492 u32 ring_space;
1493
1494 if (dinfo->ring_tail >= dinfo->ring_head)
1495 ring_space = dinfo->ring.size -
1496 (dinfo->ring_tail - dinfo->ring_head);
1497 else
1498 ring_space = dinfo->ring_head - dinfo->ring_tail;
1499
1500 if (ring_space > RING_MIN_FREE)
1501 ring_space -= RING_MIN_FREE;
1502 else
1503 ring_space = 0;
1504
1505 return ring_space;
1506}
1507
1508static int wait_ring(struct intelfb_info *dinfo, int n)
1509{
1510 int i = 0;
1511 unsigned long end;
1512 u32 last_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;
1513
1514#if VERBOSE > 0
1515 DBG_MSG("wait_ring: %d\n", n);
1516#endif
1517
1518 end = jiffies + (HZ * 3);
1519 while (dinfo->ring_space < n) {
1520 dinfo->ring_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;
1521 dinfo->ring_space = get_ring_space(dinfo);
1522
1523 if (dinfo->ring_head != last_head) {
1524 end = jiffies + (HZ * 3);
1525 last_head = dinfo->ring_head;
1526 }
1527 i++;
1528 if (time_before(end, jiffies)) {
1529 if (!i) {
1530 /* Try again */
1531 reset_state(dinfo);
1532 refresh_ring(dinfo);
1533 do_flush(dinfo);
1534 end = jiffies + (HZ * 3);
1535 i = 1;
1536 } else {
1537 WRN_MSG("ring buffer : space: %d wanted %d\n",
1538 dinfo->ring_space, n);
1539 WRN_MSG("lockup - turning off hardware "
1540 "acceleration\n");
1541 dinfo->ring_lockup = 1;
1542 break;
1543 }
1544 }
1545 udelay(1);
1546 }
1547 return i;
1548}
1549
1550static void do_flush(struct intelfb_info *dinfo)
1551{
1552 START_RING(2);
1553 OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
1554 OUT_RING(MI_NOOP);
1555 ADVANCE_RING();
1556}
1557
1558void intelfbhw_do_sync(struct intelfb_info *dinfo)
1559{
1560#if VERBOSE > 0
1561 DBG_MSG("intelfbhw_do_sync\n");
1562#endif
1563
1564 if (!dinfo->accel)
1565 return;
1566
1567 /*
1568 * Send a flush, then wait until the ring is empty. This is what
1569 * the XFree86 driver does, and actually it doesn't seem a lot worse
1570 * than the recommended method (both have problems).
1571 */
1572 do_flush(dinfo);
1573 wait_ring(dinfo, dinfo->ring.size - RING_MIN_FREE);
1574 dinfo->ring_space = dinfo->ring.size - RING_MIN_FREE;
1575}
1576
1577static void refresh_ring(struct intelfb_info *dinfo)
1578{
1579#if VERBOSE > 0
1580 DBG_MSG("refresh_ring\n");
1581#endif
1582
1583 dinfo->ring_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;
1584 dinfo->ring_tail = INREG(PRI_RING_TAIL) & RING_TAIL_MASK;
1585 dinfo->ring_space = get_ring_space(dinfo);
1586}
1587
1588static void reset_state(struct intelfb_info *dinfo)
1589{
1590 int i;
1591 u32 tmp;
1592
1593#if VERBOSE > 0
1594 DBG_MSG("reset_state\n");
1595#endif
1596
1597 for (i = 0; i < FENCE_NUM; i++)
1598 OUTREG(FENCE + (i << 2), 0);
1599
1600 /* Flush the ring buffer if it's enabled. */
1601 tmp = INREG(PRI_RING_LENGTH);
1602 if (tmp & RING_ENABLE) {
1603#if VERBOSE > 0
1604 DBG_MSG("reset_state: ring was enabled\n");
1605#endif
1606 refresh_ring(dinfo);
1607 intelfbhw_do_sync(dinfo);
1608 DO_RING_IDLE();
1609 }
1610
1611 OUTREG(PRI_RING_LENGTH, 0);
1612 OUTREG(PRI_RING_HEAD, 0);
1613 OUTREG(PRI_RING_TAIL, 0);
1614 OUTREG(PRI_RING_START, 0);
1615}
1616
1617/* Stop the 2D engine, and turn off the ring buffer. */
1618void intelfbhw_2d_stop(struct intelfb_info *dinfo)
1619{
1620#if VERBOSE > 0
1621 DBG_MSG("intelfbhw_2d_stop: accel: %d, ring_active: %d\n",
1622 dinfo->accel, dinfo->ring_active);
1623#endif
1624
1625 if (!dinfo->accel)
1626 return;
1627
1628 dinfo->ring_active = 0;
1629 reset_state(dinfo);
1630}
1631
1632/*
1633 * Enable the ring buffer, and initialise the 2D engine.
1634 * It is assumed that the graphics engine has been stopped by previously
1635 * calling intelfb_2d_stop().
1636 */
1637void intelfbhw_2d_start(struct intelfb_info *dinfo)
1638{
1639#if VERBOSE > 0
1640 DBG_MSG("intelfbhw_2d_start: accel: %d, ring_active: %d\n",
1641 dinfo->accel, dinfo->ring_active);
1642#endif
1643
1644 if (!dinfo->accel)
1645 return;
1646
1647 /* Initialise the primary ring buffer. */
1648 OUTREG(PRI_RING_LENGTH, 0);
1649 OUTREG(PRI_RING_TAIL, 0);
1650 OUTREG(PRI_RING_HEAD, 0);
1651
1652 OUTREG(PRI_RING_START, dinfo->ring.physical & RING_START_MASK);
1653 OUTREG(PRI_RING_LENGTH,
1654 ((dinfo->ring.size - GTT_PAGE_SIZE) & RING_LENGTH_MASK) |
1655 RING_NO_REPORT | RING_ENABLE);
1656 refresh_ring(dinfo);
1657 dinfo->ring_active = 1;
1658}
1659
1660/* 2D fillrect (solid fill or invert) */
1661void intelfbhw_do_fillrect(struct intelfb_info *dinfo, u32 x, u32 y, u32 w,
1662 u32 h, u32 color, u32 pitch, u32 bpp, u32 rop)
1663{
1664 u32 br00, br09, br13, br14, br16;
1665
1666#if VERBOSE > 0
1667 DBG_MSG("intelfbhw_do_fillrect: (%d,%d) %dx%d, c 0x%06x, p %d bpp %d, "
1668 "rop 0x%02x\n", x, y, w, h, color, pitch, bpp, rop);
1669#endif
1670
1671 br00 = COLOR_BLT_CMD;
1672 br09 = dinfo->fb_start + (y * pitch + x * (bpp / 8));
1673 br13 = (rop << ROP_SHIFT) | pitch;
1674 br14 = (h << HEIGHT_SHIFT) | ((w * (bpp / 8)) << WIDTH_SHIFT);
1675 br16 = color;
1676
1677 switch (bpp) {
1678 case 8:
1679 br13 |= COLOR_DEPTH_8;
1680 break;
1681 case 16:
1682 br13 |= COLOR_DEPTH_16;
1683 break;
1684 case 32:
1685 br13 |= COLOR_DEPTH_32;
1686 br00 |= WRITE_ALPHA | WRITE_RGB;
1687 break;
1688 }
1689
1690 START_RING(6);
1691 OUT_RING(br00);
1692 OUT_RING(br13);
1693 OUT_RING(br14);
1694 OUT_RING(br09);
1695 OUT_RING(br16);
1696 OUT_RING(MI_NOOP);
1697 ADVANCE_RING();
1698
1699#if VERBOSE > 0
1700 DBG_MSG("ring = 0x%08x, 0x%08x (%d)\n", dinfo->ring_head,
1701 dinfo->ring_tail, dinfo->ring_space);
1702#endif
1703}
1704
1705void
1706intelfbhw_do_bitblt(struct intelfb_info *dinfo, u32 curx, u32 cury,
1707 u32 dstx, u32 dsty, u32 w, u32 h, u32 pitch, u32 bpp)
1708{
1709 u32 br00, br09, br11, br12, br13, br22, br23, br26;
1710
1711#if VERBOSE > 0
1712 DBG_MSG("intelfbhw_do_bitblt: (%d,%d)->(%d,%d) %dx%d, p %d bpp %d\n",
1713 curx, cury, dstx, dsty, w, h, pitch, bpp);
1714#endif
1715
1716 br00 = XY_SRC_COPY_BLT_CMD;
1717 br09 = dinfo->fb_start;
1718 br11 = (pitch << PITCH_SHIFT);
1719 br12 = dinfo->fb_start;
1720 br13 = (SRC_ROP_GXCOPY << ROP_SHIFT) | (pitch << PITCH_SHIFT);
1721 br22 = (dstx << WIDTH_SHIFT) | (dsty << HEIGHT_SHIFT);
1722 br23 = ((dstx + w) << WIDTH_SHIFT) |
1723 ((dsty + h) << HEIGHT_SHIFT);
1724 br26 = (curx << WIDTH_SHIFT) | (cury << HEIGHT_SHIFT);
1725
1726 switch (bpp) {
1727 case 8:
1728 br13 |= COLOR_DEPTH_8;
1729 break;
1730 case 16:
1731 br13 |= COLOR_DEPTH_16;
1732 break;
1733 case 32:
1734 br13 |= COLOR_DEPTH_32;
1735 br00 |= WRITE_ALPHA | WRITE_RGB;
1736 break;
1737 }
1738
1739 START_RING(8);
1740 OUT_RING(br00);
1741 OUT_RING(br13);
1742 OUT_RING(br22);
1743 OUT_RING(br23);
1744 OUT_RING(br09);
1745 OUT_RING(br26);
1746 OUT_RING(br11);
1747 OUT_RING(br12);
1748 ADVANCE_RING();
1749}
1750
1751int intelfbhw_do_drawglyph(struct intelfb_info *dinfo, u32 fg, u32 bg, u32 w,
1752 u32 h, const u8* cdat, u32 x, u32 y, u32 pitch,
1753 u32 bpp)
1754{
1755 int nbytes, ndwords, pad, tmp;
1756 u32 br00, br09, br13, br18, br19, br22, br23;
1757 int dat, ix, iy, iw;
1758 int i, j;
1759
1760#if VERBOSE > 0
1761 DBG_MSG("intelfbhw_do_drawglyph: (%d,%d) %dx%d\n", x, y, w, h);
1762#endif
1763
1764 /* size in bytes of a padded scanline */
1765 nbytes = ROUND_UP_TO(w, 16) / 8;
1766
1767 /* Total bytes of padded scanline data to write out. */
1768 nbytes = nbytes * h;
1769
1770 /*
1771 * Check if the glyph data exceeds the immediate mode limit.
1772 * It would take a large font (1K pixels) to hit this limit.
1773 */
1774 if (nbytes > MAX_MONO_IMM_SIZE)
1775 return 0;
1776
1777 /* Src data is packaged a dword (32-bit) at a time. */
1778 ndwords = ROUND_UP_TO(nbytes, 4) / 4;
1779
1780 /*
1781 * Ring has to be padded to a quad word. But because the command starts
1782 with 7 bytes, pad only if there is an even number of ndwords
1783 */
1784 pad = !(ndwords % 2);
1785
1786 tmp = (XY_MONO_SRC_IMM_BLT_CMD & DW_LENGTH_MASK) + ndwords;
1787 br00 = (XY_MONO_SRC_IMM_BLT_CMD & ~DW_LENGTH_MASK) | tmp;
1788 br09 = dinfo->fb_start;
1789 br13 = (SRC_ROP_GXCOPY << ROP_SHIFT) | (pitch << PITCH_SHIFT);
1790 br18 = bg;
1791 br19 = fg;
1792 br22 = (x << WIDTH_SHIFT) | (y << HEIGHT_SHIFT);
1793 br23 = ((x + w) << WIDTH_SHIFT) | ((y + h) << HEIGHT_SHIFT);
1794
1795 switch (bpp) {
1796 case 8:
1797 br13 |= COLOR_DEPTH_8;
1798 break;
1799 case 16:
1800 br13 |= COLOR_DEPTH_16;
1801 break;
1802 case 32:
1803 br13 |= COLOR_DEPTH_32;
1804 br00 |= WRITE_ALPHA | WRITE_RGB;
1805 break;
1806 }
1807
1808 START_RING(8 + ndwords);
1809 OUT_RING(br00);
1810 OUT_RING(br13);
1811 OUT_RING(br22);
1812 OUT_RING(br23);
1813 OUT_RING(br09);
1814 OUT_RING(br18);
1815 OUT_RING(br19);
1816 ix = iy = 0;
1817 iw = ROUND_UP_TO(w, 8) / 8;
1818 while (ndwords--) {
1819 dat = 0;
1820 for (j = 0; j < 2; ++j) {
1821 for (i = 0; i < 2; ++i) {
1822 if (ix != iw || i == 0)
1823 dat |= cdat[iy*iw + ix++] << (i+j*2)*8;
1824 }
1825 if (ix == iw && iy != (h-1)) {
1826 ix = 0;
1827 ++iy;
1828 }
1829 }
1830 OUT_RING(dat);
1831 }
1832 if (pad)
1833 OUT_RING(MI_NOOP);
1834 ADVANCE_RING();
1835
1836 return 1;
1837}
1838
1839/* HW cursor functions. */
1840void intelfbhw_cursor_init(struct intelfb_info *dinfo)
1841{
1842 u32 tmp;
1843
1844#if VERBOSE > 0
1845 DBG_MSG("intelfbhw_cursor_init\n");
1846#endif
1847
1848 if (dinfo->mobile || IS_I9XX(dinfo)) {
1849 if (!dinfo->cursor.physical)
1850 return;
1851 tmp = INREG(CURSOR_A_CONTROL);
1852 tmp &= ~(CURSOR_MODE_MASK | CURSOR_MOBILE_GAMMA_ENABLE |
1853 CURSOR_MEM_TYPE_LOCAL |
1854 (1 << CURSOR_PIPE_SELECT_SHIFT));
1855 tmp |= CURSOR_MODE_DISABLE;
1856 OUTREG(CURSOR_A_CONTROL, tmp);
1857 OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
1858 } else {
1859 tmp = INREG(CURSOR_CONTROL);
1860 tmp &= ~(CURSOR_FORMAT_MASK | CURSOR_GAMMA_ENABLE |
1861 CURSOR_ENABLE | CURSOR_STRIDE_MASK);
1862 tmp = CURSOR_FORMAT_3C;
1863 OUTREG(CURSOR_CONTROL, tmp);
1864 OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.offset << 12);
1865 tmp = (64 << CURSOR_SIZE_H_SHIFT) |
1866 (64 << CURSOR_SIZE_V_SHIFT);
1867 OUTREG(CURSOR_SIZE, tmp);
1868 }
1869}
1870
1871void intelfbhw_cursor_hide(struct intelfb_info *dinfo)
1872{
1873 u32 tmp;
1874
1875#if VERBOSE > 0
1876 DBG_MSG("intelfbhw_cursor_hide\n");
1877#endif
1878
1879 dinfo->cursor_on = 0;
1880 if (dinfo->mobile || IS_I9XX(dinfo)) {
1881 if (!dinfo->cursor.physical)
1882 return;
1883 tmp = INREG(CURSOR_A_CONTROL);
1884 tmp &= ~CURSOR_MODE_MASK;
1885 tmp |= CURSOR_MODE_DISABLE;
1886 OUTREG(CURSOR_A_CONTROL, tmp);
1887 /* Flush changes */
1888 OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
1889 } else {
1890 tmp = INREG(CURSOR_CONTROL);
1891 tmp &= ~CURSOR_ENABLE;
1892 OUTREG(CURSOR_CONTROL, tmp);
1893 }
1894}
1895
1896void intelfbhw_cursor_show(struct intelfb_info *dinfo)
1897{
1898 u32 tmp;
1899
1900#if VERBOSE > 0
1901 DBG_MSG("intelfbhw_cursor_show\n");
1902#endif
1903
1904 dinfo->cursor_on = 1;
1905
1906 if (dinfo->cursor_blanked)
1907 return;
1908
1909 if (dinfo->mobile || IS_I9XX(dinfo)) {
1910 if (!dinfo->cursor.physical)
1911 return;
1912 tmp = INREG(CURSOR_A_CONTROL);
1913 tmp &= ~CURSOR_MODE_MASK;
1914 tmp |= CURSOR_MODE_64_4C_AX;
1915 OUTREG(CURSOR_A_CONTROL, tmp);
1916 /* Flush changes */
1917 OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
1918 } else {
1919 tmp = INREG(CURSOR_CONTROL);
1920 tmp |= CURSOR_ENABLE;
1921 OUTREG(CURSOR_CONTROL, tmp);
1922 }
1923}
1924
1925void intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y)
1926{
1927 u32 tmp;
1928
1929#if VERBOSE > 0
1930 DBG_MSG("intelfbhw_cursor_setpos: (%d, %d)\n", x, y);
1931#endif
1932
1933 /*
1934 * Sets the position. The coordinates are assumed to already
1935 * have any offset adjusted. Assume that the cursor is never
1936 * completely off-screen, and that x, y are always >= 0.
1937 */
1938
1939 tmp = ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) |
1940 ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
1941 OUTREG(CURSOR_A_POSITION, tmp);
1942
1943 if (IS_I9XX(dinfo))
1944 OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
1945}
1946
1947void intelfbhw_cursor_setcolor(struct intelfb_info *dinfo, u32 bg, u32 fg)
1948{
1949#if VERBOSE > 0
1950 DBG_MSG("intelfbhw_cursor_setcolor\n");
1951#endif
1952
1953 OUTREG(CURSOR_A_PALETTE0, bg & CURSOR_PALETTE_MASK);
1954 OUTREG(CURSOR_A_PALETTE1, fg & CURSOR_PALETTE_MASK);
1955 OUTREG(CURSOR_A_PALETTE2, fg & CURSOR_PALETTE_MASK);
1956 OUTREG(CURSOR_A_PALETTE3, bg & CURSOR_PALETTE_MASK);
1957}
1958
1959void intelfbhw_cursor_load(struct intelfb_info *dinfo, int width, int height,
1960 u8 *data)
1961{
1962 u8 __iomem *addr = (u8 __iomem *)dinfo->cursor.virtual;
1963 int i, j, w = width / 8;
1964 int mod = width % 8, t_mask, d_mask;
1965
1966#if VERBOSE > 0
1967 DBG_MSG("intelfbhw_cursor_load\n");
1968#endif
1969
1970 if (!dinfo->cursor.virtual)
1971 return;
1972
1973 t_mask = 0xff >> mod;
1974 d_mask = ~(0xff >> mod);
1975 for (i = height; i--; ) {
1976 for (j = 0; j < w; j++) {
1977 writeb(0x00, addr + j);
1978 writeb(*(data++), addr + j+8);
1979 }
1980 if (mod) {
1981 writeb(t_mask, addr + j);
1982 writeb(*(data++) & d_mask, addr + j+8);
1983 }
1984 addr += 16;
1985 }
1986}
1987
1988void intelfbhw_cursor_reset(struct intelfb_info *dinfo)
1989{
1990 u8 __iomem *addr = (u8 __iomem *)dinfo->cursor.virtual;
1991 int i, j;
1992
1993#if VERBOSE > 0
1994 DBG_MSG("intelfbhw_cursor_reset\n");
1995#endif
1996
1997 if (!dinfo->cursor.virtual)
1998 return;
1999
2000 for (i = 64; i--; ) {
2001 for (j = 0; j < 8; j++) {
2002 writeb(0xff, addr + j+0);
2003 writeb(0x00, addr + j+8);
2004 }
2005 addr += 16;
2006 }
2007}
2008
2009static irqreturn_t intelfbhw_irq(int irq, void *dev_id)
2010{
2011 u16 tmp;
2012 struct intelfb_info *dinfo = dev_id;
2013
2014 spin_lock(&dinfo->int_lock);
2015
2016 tmp = INREG16(IIR);
2017 if (dinfo->info->var.vmode & FB_VMODE_INTERLACED)
2018 tmp &= PIPE_A_EVENT_INTERRUPT;
2019 else
2020 tmp &= VSYNC_PIPE_A_INTERRUPT; /* non-interlaced */
2021
2022 if (tmp == 0) {
2023 spin_unlock(&dinfo->int_lock);
2024 return IRQ_RETVAL(0); /* not us */
2025 }
2026
2027 /* clear status bits 0-15 ASAP and don't touch bits 16-31 */
2028 OUTREG(PIPEASTAT, INREG(PIPEASTAT));
2029
2030 OUTREG16(IIR, tmp);
2031 if (dinfo->vsync.pan_display) {
2032 dinfo->vsync.pan_display = 0;
2033 OUTREG(DSPABASE, dinfo->vsync.pan_offset);
2034 }
2035
2036 dinfo->vsync.count++;
2037 wake_up_interruptible(&dinfo->vsync.wait);
2038
2039 spin_unlock(&dinfo->int_lock);
2040
2041 return IRQ_RETVAL(1);
2042}
2043
2044int intelfbhw_enable_irq(struct intelfb_info *dinfo)
2045{
2046 u16 tmp;
2047 if (!test_and_set_bit(0, &dinfo->irq_flags)) {
2048 if (request_irq(dinfo->pdev->irq, intelfbhw_irq, IRQF_SHARED,
2049 "intelfb", dinfo)) {
2050 clear_bit(0, &dinfo->irq_flags);
2051 return -EINVAL;
2052 }
2053
2054 spin_lock_irq(&dinfo->int_lock);
2055 OUTREG16(HWSTAM, 0xfffe); /* i830 DRM uses ffff */
2056 OUTREG16(IMR, 0);
2057 } else
2058 spin_lock_irq(&dinfo->int_lock);
2059
2060 if (dinfo->info->var.vmode & FB_VMODE_INTERLACED)
2061 tmp = PIPE_A_EVENT_INTERRUPT;
2062 else
2063 tmp = VSYNC_PIPE_A_INTERRUPT; /* non-interlaced */
2064 if (tmp != INREG16(IER)) {
2065 DBG_MSG("changing IER to 0x%X\n", tmp);
2066 OUTREG16(IER, tmp);
2067 }
2068
2069 spin_unlock_irq(&dinfo->int_lock);
2070 return 0;
2071}
2072
2073void intelfbhw_disable_irq(struct intelfb_info *dinfo)
2074{
2075 if (test_and_clear_bit(0, &dinfo->irq_flags)) {
2076 if (dinfo->vsync.pan_display) {
2077 dinfo->vsync.pan_display = 0;
2078 OUTREG(DSPABASE, dinfo->vsync.pan_offset);
2079 }
2080 spin_lock_irq(&dinfo->int_lock);
2081 OUTREG16(HWSTAM, 0xffff);
2082 OUTREG16(IMR, 0xffff);
2083 OUTREG16(IER, 0x0);
2084
2085 OUTREG16(IIR, INREG16(IIR)); /* clear IRQ requests */
2086 spin_unlock_irq(&dinfo->int_lock);
2087
2088 free_irq(dinfo->pdev->irq, dinfo);
2089 }
2090}
2091
2092int intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe)
2093{
2094 struct intelfb_vsync *vsync;
2095 unsigned int count;
2096 int ret;
2097
2098 switch (pipe) {
2099 case 0:
2100 vsync = &dinfo->vsync;
2101 break;
2102 default:
2103 return -ENODEV;
2104 }
2105
2106 ret = intelfbhw_enable_irq(dinfo);
2107 if (ret)
2108 return ret;
2109
2110 count = vsync->count;
2111 ret = wait_event_interruptible_timeout(vsync->wait,
2112 count != vsync->count, HZ / 10);
2113 if (ret < 0)
2114 return ret;
2115 if (ret == 0) {
2116 DBG_MSG("wait_for_vsync timed out!\n");
2117 return -ETIMEDOUT;
2118 }
2119
2120 return 0;
2121}
diff --git a/drivers/video/fbdev/intelfb/intelfbhw.h b/drivers/video/fbdev/intelfb/intelfbhw.h
new file mode 100644
index 000000000000..216ca20f259f
--- /dev/null
+++ b/drivers/video/fbdev/intelfb/intelfbhw.h
@@ -0,0 +1,609 @@
1#ifndef _INTELFBHW_H
2#define _INTELFBHW_H
3
4/* $DHD: intelfb/intelfbhw.h,v 1.5 2003/06/27 15:06:25 dawes Exp $ */
5
6
7/*** HW-specific data ***/
8
9/* Information about the 852GM/855GM variants */
10#define INTEL_85X_CAPID 0x44
11#define INTEL_85X_VARIANT_MASK 0x7
12#define INTEL_85X_VARIANT_SHIFT 5
13#define INTEL_VAR_855GME 0x0
14#define INTEL_VAR_855GM 0x4
15#define INTEL_VAR_852GME 0x2
16#define INTEL_VAR_852GM 0x5
17
18/* Information about DVO/LVDS Ports */
19#define DVOA_PORT 0x1
20#define DVOB_PORT 0x2
21#define DVOC_PORT 0x4
22#define LVDS_PORT 0x8
23
24/*
25 * The Bridge device's PCI config space has information about the
26 * fb aperture size and the amount of pre-reserved memory.
27 */
28#define INTEL_GMCH_CTRL 0x52
29#define INTEL_GMCH_ENABLED 0x4
30#define INTEL_GMCH_MEM_MASK 0x1
31#define INTEL_GMCH_MEM_64M 0x1
32#define INTEL_GMCH_MEM_128M 0
33
34#define INTEL_830_GMCH_GMS_MASK (0x7 << 4)
35#define INTEL_830_GMCH_GMS_DISABLED (0x0 << 4)
36#define INTEL_830_GMCH_GMS_LOCAL (0x1 << 4)
37#define INTEL_830_GMCH_GMS_STOLEN_512 (0x2 << 4)
38#define INTEL_830_GMCH_GMS_STOLEN_1024 (0x3 << 4)
39#define INTEL_830_GMCH_GMS_STOLEN_8192 (0x4 << 4)
40
41#define INTEL_855_GMCH_GMS_MASK (0x7 << 4)
42#define INTEL_855_GMCH_GMS_DISABLED (0x0 << 4)
43#define INTEL_855_GMCH_GMS_STOLEN_1M (0x1 << 4)
44#define INTEL_855_GMCH_GMS_STOLEN_4M (0x2 << 4)
45#define INTEL_855_GMCH_GMS_STOLEN_8M (0x3 << 4)
46#define INTEL_855_GMCH_GMS_STOLEN_16M (0x4 << 4)
47#define INTEL_855_GMCH_GMS_STOLEN_32M (0x5 << 4)
48
49#define INTEL_915G_GMCH_GMS_STOLEN_48M (0x6 << 4)
50#define INTEL_915G_GMCH_GMS_STOLEN_64M (0x7 << 4)
51
52/* HW registers */
53
54/* Fence registers */
55#define FENCE 0x2000
56#define FENCE_NUM 8
57
58/* Primary ring buffer */
59#define PRI_RING_TAIL 0x2030
60#define RING_TAIL_MASK 0x001ffff8
61#define RING_INUSE 0x1
62
63#define PRI_RING_HEAD 0x2034
64#define RING_HEAD_WRAP_MASK 0x7ff
65#define RING_HEAD_WRAP_SHIFT 21
66#define RING_HEAD_MASK 0x001ffffc
67
68#define PRI_RING_START 0x2038
69#define RING_START_MASK 0xfffff000
70
71#define PRI_RING_LENGTH 0x203c
72#define RING_LENGTH_MASK 0x001ff000
73#define RING_REPORT_MASK (0x3 << 1)
74#define RING_NO_REPORT (0x0 << 1)
75#define RING_REPORT_64K (0x1 << 1)
76#define RING_REPORT_4K (0x2 << 1)
77#define RING_REPORT_128K (0x3 << 1)
78#define RING_ENABLE 0x1
79
80/*
81 * Tail can't wrap to any closer than RING_MIN_FREE bytes of the head,
82 * and the last RING_MIN_FREE bytes need to be padded with MI_NOOP
83 */
84#define RING_MIN_FREE 64
85
86#define IPEHR 0x2088
87
88#define INSTDONE 0x2090
89#define PRI_RING_EMPTY 1
90
91#define HWSTAM 0x2098
92#define IER 0x20A0
93#define IIR 0x20A4
94#define IMR 0x20A8
95#define VSYNC_PIPE_A_INTERRUPT (1 << 7)
96#define PIPE_A_EVENT_INTERRUPT (1 << 6)
97#define VSYNC_PIPE_B_INTERRUPT (1 << 5)
98#define PIPE_B_EVENT_INTERRUPT (1 << 4)
99#define HOST_PORT_EVENT_INTERRUPT (1 << 3)
100#define CAPTURE_EVENT_INTERRUPT (1 << 2)
101#define USER_DEFINED_INTERRUPT (1 << 1)
102#define BREAKPOINT_INTERRUPT 1
103
104#define INSTPM 0x20c0
105#define SYNC_FLUSH_ENABLE (1 << 5)
106
107#define INSTPS 0x20c4
108
109#define MEM_MODE 0x20cc
110
111#define MASK_SHIFT 16
112
113#define FW_BLC_0 0x20d8
114#define FW_DISPA_WM_SHIFT 0
115#define FW_DISPA_WM_MASK 0x3f
116#define FW_DISPA_BL_SHIFT 8
117#define FW_DISPA_BL_MASK 0xf
118#define FW_DISPB_WM_SHIFT 16
119#define FW_DISPB_WM_MASK 0x1f
120#define FW_DISPB_BL_SHIFT 24
121#define FW_DISPB_BL_MASK 0x7
122
123#define FW_BLC_1 0x20dc
124#define FW_DISPC_WM_SHIFT 0
125#define FW_DISPC_WM_MASK 0x1f
126#define FW_DISPC_BL_SHIFT 8
127#define FW_DISPC_BL_MASK 0x7
128
129#define GPIOA 0x5010
130#define GPIOB 0x5014
131#define GPIOC 0x5018 /* this may be external DDC on i830 */
132#define GPIOD 0x501C /* this is DVO DDC */
133#define GPIOE 0x5020 /* this is DVO i2C */
134#define GPIOF 0x5024
135
136/* PLL registers */
137#define VGA0_DIVISOR 0x06000
138#define VGA1_DIVISOR 0x06004
139#define VGAPD 0x06010
140#define VGAPD_0_P1_SHIFT 0
141#define VGAPD_0_P1_FORCE_DIV2 (1 << 5)
142#define VGAPD_0_P2_SHIFT 7
143#define VGAPD_1_P1_SHIFT 8
144#define VGAPD_1_P1_FORCE_DIV2 (1 << 13)
145#define VGAPD_1_P2_SHIFT 15
146
147#define DPLL_A 0x06014
148#define DPLL_B 0x06018
149#define DPLL_VCO_ENABLE (1 << 31)
150#define DPLL_2X_CLOCK_ENABLE (1 << 30)
151#define DPLL_SYNCLOCK_ENABLE (1 << 29)
152#define DPLL_VGA_MODE_DISABLE (1 << 28)
153#define DPLL_P2_MASK 1
154#define DPLL_P2_SHIFT 23
155#define DPLL_I9XX_P2_SHIFT 24
156#define DPLL_P1_FORCE_DIV2 (1 << 21)
157#define DPLL_P1_MASK 0x1f
158#define DPLL_P1_SHIFT 16
159#define DPLL_REFERENCE_SELECT_MASK (0x3 << 13)
160#define DPLL_REFERENCE_DEFAULT (0x0 << 13)
161#define DPLL_REFERENCE_TVCLK (0x2 << 13)
162#define DPLL_RATE_SELECT_MASK (1 << 8)
163#define DPLL_RATE_SELECT_FP0 (0 << 8)
164#define DPLL_RATE_SELECT_FP1 (1 << 8)
165
166#define FPA0 0x06040
167#define FPA1 0x06044
168#define FPB0 0x06048
169#define FPB1 0x0604c
170#define FP_DIVISOR_MASK 0x3f
171#define FP_N_DIVISOR_SHIFT 16
172#define FP_M1_DIVISOR_SHIFT 8
173#define FP_M2_DIVISOR_SHIFT 0
174
175/* PLL parameters (these are for 852GM/855GM/865G, check earlier chips). */
176/* Clock values are in units of kHz */
177#define PLL_REFCLK 48000
178#define MIN_CLOCK 25000
179#define MAX_CLOCK 350000
180
181/* Two pipes */
182#define PIPE_A 0
183#define PIPE_B 1
184#define PIPE_MASK 1
185
186/* palette registers */
187#define PALETTE_A 0x0a000
188#define PALETTE_B 0x0a800
189#ifndef PALETTE_8_ENTRIES
190#define PALETTE_8_ENTRIES 256
191#endif
192#define PALETTE_8_SIZE (PALETTE_8_ENTRIES * 4)
193#define PALETTE_10_ENTRIES 128
194#define PALETTE_10_SIZE (PALETTE_10_ENTRIES * 8)
195#define PALETTE_8_MASK 0xff
196#define PALETTE_8_RED_SHIFT 16
197#define PALETTE_8_GREEN_SHIFT 8
198#define PALETTE_8_BLUE_SHIFT 0
199
200/* CRTC registers */
201#define HTOTAL_A 0x60000
202#define HBLANK_A 0x60004
203#define HSYNC_A 0x60008
204#define VTOTAL_A 0x6000c
205#define VBLANK_A 0x60010
206#define VSYNC_A 0x60014
207#define SRC_SIZE_A 0x6001c
208#define BCLRPAT_A 0x60020
209
210#define HTOTAL_B 0x61000
211#define HBLANK_B 0x61004
212#define HSYNC_B 0x61008
213#define VTOTAL_B 0x6100c
214#define VBLANK_B 0x61010
215#define VSYNC_B 0x61014
216#define SRC_SIZE_B 0x6101c
217#define BCLRPAT_B 0x61020
218
219#define HTOTAL_MASK 0xfff
220#define HTOTAL_SHIFT 16
221#define HACTIVE_MASK 0x7ff
222#define HACTIVE_SHIFT 0
223#define HBLANKEND_MASK 0xfff
224#define HBLANKEND_SHIFT 16
225#define HBLANKSTART_MASK 0xfff
226#define HBLANKSTART_SHIFT 0
227#define HSYNCEND_MASK 0xfff
228#define HSYNCEND_SHIFT 16
229#define HSYNCSTART_MASK 0xfff
230#define HSYNCSTART_SHIFT 0
231#define VTOTAL_MASK 0xfff
232#define VTOTAL_SHIFT 16
233#define VACTIVE_MASK 0x7ff
234#define VACTIVE_SHIFT 0
235#define VBLANKEND_MASK 0xfff
236#define VBLANKEND_SHIFT 16
237#define VBLANKSTART_MASK 0xfff
238#define VBLANKSTART_SHIFT 0
239#define VSYNCEND_MASK 0xfff
240#define VSYNCEND_SHIFT 16
241#define VSYNCSTART_MASK 0xfff
242#define VSYNCSTART_SHIFT 0
243#define SRC_SIZE_HORIZ_MASK 0x7ff
244#define SRC_SIZE_HORIZ_SHIFT 16
245#define SRC_SIZE_VERT_MASK 0x7ff
246#define SRC_SIZE_VERT_SHIFT 0
247
248#define ADPA 0x61100
249#define ADPA_DAC_ENABLE (1 << 31)
250#define ADPA_DAC_DISABLE 0
251#define ADPA_PIPE_SELECT_SHIFT 30
252#define ADPA_USE_VGA_HVPOLARITY (1 << 15)
253#define ADPA_SETS_HVPOLARITY 0
254#define ADPA_DPMS_CONTROL_MASK (0x3 << 10)
255#define ADPA_DPMS_D0 (0x0 << 10)
256#define ADPA_DPMS_D2 (0x1 << 10)
257#define ADPA_DPMS_D1 (0x2 << 10)
258#define ADPA_DPMS_D3 (0x3 << 10)
259#define ADPA_VSYNC_ACTIVE_SHIFT 4
260#define ADPA_HSYNC_ACTIVE_SHIFT 3
261#define ADPA_SYNC_ACTIVE_MASK 1
262#define ADPA_SYNC_ACTIVE_HIGH 1
263#define ADPA_SYNC_ACTIVE_LOW 0
264
265#define DVOA 0x61120
266#define DVOB 0x61140
267#define DVOC 0x61160
268#define LVDS 0x61180
269#define PORT_ENABLE (1 << 31)
270#define PORT_PIPE_SELECT_SHIFT 30
271#define PORT_TV_FLAGS_MASK 0xFF
272#define PORT_TV_FLAGS 0xC4 /* ripped from my BIOS
273 to understand and correct */
274
275#define DVOA_SRCDIM 0x61124
276#define DVOB_SRCDIM 0x61144
277#define DVOC_SRCDIM 0x61164
278
279#define PIPEA_DSL 0x70000
280#define PIPEB_DSL 0x71000
281#define PIPEACONF 0x70008
282#define PIPEBCONF 0x71008
283#define PIPEASTAT 0x70024 /* bits 0-15 are "write 1 to clear" */
284#define PIPEBSTAT 0x71024
285
286#define PIPECONF_ENABLE (1 << 31)
287#define PIPECONF_DISABLE 0
288#define PIPECONF_DOUBLE_WIDE (1 << 30)
289#define PIPECONF_SINGLE_WIDE 0
290#define PIPECONF_LOCKED (1 << 25)
291#define PIPECONF_UNLOCKED 0
292#define PIPECONF_GAMMA (1 << 24)
293#define PIPECONF_PALETTE 0
294#define PIPECONF_PROGRESSIVE (0 << 21)
295#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21)
296#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21)
297#define PIPECONF_INTERLACE_MASK (7 << 21)
298
299/* enable bits, write 1 to enable */
300#define PIPESTAT_FIFO_UNDERRUN (1 << 31)
301#define PIPESTAT_CRC_ERROR_EN (1 << 29)
302#define PIPESTAT_CRC_DONE_EN (1 << 28)
303#define PIPESTAT_HOTPLUG_EN (1 << 26)
304#define PIPESTAT_VERTICAL_SYNC_EN (1 << 25)
305#define PIPESTAT_DISPLINE_COMP_EN (1 << 24)
306#define PIPESTAT_FLD_EVT_ODD_EN (1 << 21)
307#define PIPESTAT_FLD_EVT_EVEN_EN (1 << 20)
308#define PIPESTAT_TV_HOTPLUG_EN (1 << 18)
309#define PIPESTAT_VBLANK_EN (1 << 17)
310#define PIPESTAT_OVL_UPDATE_EN (1 << 16)
311/* status bits, write 1 to clear */
312#define PIPESTAT_HOTPLUG_STATE (1 << 15)
313#define PIPESTAT_CRC_ERROR (1 << 13)
314#define PIPESTAT_CRC_DONE (1 << 12)
315#define PIPESTAT_HOTPLUG (1 << 10)
316#define PIPESTAT_VSYNC (1 << 9)
317#define PIPESTAT_DISPLINE_COMP (1 << 8)
318#define PIPESTAT_FLD_EVT_ODD (1 << 5)
319#define PIPESTAT_FLD_EVT_EVEN (1 << 4)
320#define PIPESTAT_TV_HOTPLUG (1 << 2)
321#define PIPESTAT_VBLANK (1 << 1)
322#define PIPESTAT_OVL_UPDATE (1 << 0)
323
324#define DISPARB 0x70030
325#define DISPARB_AEND_MASK 0x1ff
326#define DISPARB_AEND_SHIFT 0
327#define DISPARB_BEND_MASK 0x3ff
328#define DISPARB_BEND_SHIFT 9
329
330/* Desktop HW cursor */
331#define CURSOR_CONTROL 0x70080
332#define CURSOR_ENABLE (1 << 31)
333#define CURSOR_GAMMA_ENABLE (1 << 30)
334#define CURSOR_STRIDE_MASK (0x3 << 28)
335#define CURSOR_STRIDE_256 (0x0 << 28)
336#define CURSOR_STRIDE_512 (0x1 << 28)
337#define CURSOR_STRIDE_1K (0x2 << 28)
338#define CURSOR_STRIDE_2K (0x3 << 28)
339#define CURSOR_FORMAT_MASK (0x7 << 24)
340#define CURSOR_FORMAT_2C (0x0 << 24)
341#define CURSOR_FORMAT_3C (0x1 << 24)
342#define CURSOR_FORMAT_4C (0x2 << 24)
343#define CURSOR_FORMAT_ARGB (0x4 << 24)
344#define CURSOR_FORMAT_XRGB (0x5 << 24)
345
346/* Mobile HW cursor (and i810) */
347#define CURSOR_A_CONTROL CURSOR_CONTROL
348#define CURSOR_B_CONTROL 0x700c0
349#define CURSOR_MODE_MASK 0x27
350#define CURSOR_MODE_DISABLE 0
351#define CURSOR_MODE_64_3C 0x04
352#define CURSOR_MODE_64_4C_AX 0x05
353#define CURSOR_MODE_64_4C 0x06
354#define CURSOR_MODE_64_32B_AX 0x07
355#define CURSOR_MODE_64_ARGB_AX 0x27
356#define CURSOR_PIPE_SELECT_SHIFT 28
357#define CURSOR_MOBILE_GAMMA_ENABLE (1 << 26)
358#define CURSOR_MEM_TYPE_LOCAL (1 << 25)
359
360/* All platforms (desktop has no pipe B) */
361#define CURSOR_A_BASEADDR 0x70084
362#define CURSOR_B_BASEADDR 0x700c4
363#define CURSOR_BASE_MASK 0xffffff00
364
365#define CURSOR_A_POSITION 0x70088
366#define CURSOR_B_POSITION 0x700c8
367#define CURSOR_POS_SIGN (1 << 15)
368#define CURSOR_POS_MASK 0x7ff
369#define CURSOR_X_SHIFT 0
370#define CURSOR_Y_SHIFT 16
371
372#define CURSOR_A_PALETTE0 0x70090
373#define CURSOR_A_PALETTE1 0x70094
374#define CURSOR_A_PALETTE2 0x70098
375#define CURSOR_A_PALETTE3 0x7009c
376#define CURSOR_B_PALETTE0 0x700d0
377#define CURSOR_B_PALETTE1 0x700d4
378#define CURSOR_B_PALETTE2 0x700d8
379#define CURSOR_B_PALETTE3 0x700dc
380#define CURSOR_COLOR_MASK 0xff
381#define CURSOR_RED_SHIFT 16
382#define CURSOR_GREEN_SHIFT 8
383#define CURSOR_BLUE_SHIFT 0
384#define CURSOR_PALETTE_MASK 0xffffff
385
386/* Desktop only */
387#define CURSOR_SIZE 0x700a0
388#define CURSOR_SIZE_MASK 0x3ff
389#define CURSOR_SIZE_H_SHIFT 0
390#define CURSOR_SIZE_V_SHIFT 12
391
392#define DSPACNTR 0x70180
393#define DSPBCNTR 0x71180
394#define DISPPLANE_PLANE_ENABLE (1 << 31)
395#define DISPPLANE_PLANE_DISABLE 0
396#define DISPPLANE_GAMMA_ENABLE (1<<30)
397#define DISPPLANE_GAMMA_DISABLE 0
398#define DISPPLANE_PIXFORMAT_MASK (0xf<<26)
399#define DISPPLANE_8BPP (0x2<<26)
400#define DISPPLANE_15_16BPP (0x4<<26)
401#define DISPPLANE_16BPP (0x5<<26)
402#define DISPPLANE_32BPP_NO_ALPHA (0x6<<26)
403#define DISPPLANE_32BPP (0x7<<26)
404#define DISPPLANE_STEREO_ENABLE (1<<25)
405#define DISPPLANE_STEREO_DISABLE 0
406#define DISPPLANE_SEL_PIPE_SHIFT 24
407#define DISPPLANE_SRC_KEY_ENABLE (1<<22)
408#define DISPPLANE_SRC_KEY_DISABLE 0
409#define DISPPLANE_LINE_DOUBLE (1<<20)
410#define DISPPLANE_NO_LINE_DOUBLE 0
411#define DISPPLANE_STEREO_POLARITY_FIRST 0
412#define DISPPLANE_STEREO_POLARITY_SECOND (1<<18)
413/* plane B only */
414#define DISPPLANE_ALPHA_TRANS_ENABLE (1<<15)
415#define DISPPLANE_ALPHA_TRANS_DISABLE 0
416#define DISPPLANE_SPRITE_ABOVE_DISPLAYA 0
417#define DISPPLANE_SPRITE_ABOVE_OVERLAY 1
418
419#define DSPABASE 0x70184
420#define DSPASTRIDE 0x70188
421
422#define DSPBBASE 0x71184
423#define DSPBSTRIDE 0x71188
424
425#define VGACNTRL 0x71400
426#define VGA_DISABLE (1 << 31)
427#define VGA_ENABLE 0
428#define VGA_PIPE_SELECT_SHIFT 29
429#define VGA_PALETTE_READ_SELECT 23
430#define VGA_PALETTE_A_WRITE_DISABLE (1 << 22)
431#define VGA_PALETTE_B_WRITE_DISABLE (1 << 21)
432#define VGA_LEGACY_PALETTE (1 << 20)
433#define VGA_6BIT_DAC 0
434#define VGA_8BIT_DAC (1 << 20)
435
436#define ADD_ID 0x71408
437#define ADD_ID_MASK 0xff
438
439/* BIOS scratch area registers (830M and 845G). */
440#define SWF0 0x71410
441#define SWF1 0x71414
442#define SWF2 0x71418
443#define SWF3 0x7141c
444#define SWF4 0x71420
445#define SWF5 0x71424
446#define SWF6 0x71428
447
448/* BIOS scratch area registers (852GM, 855GM, 865G). */
449#define SWF00 0x70410
450#define SWF01 0x70414
451#define SWF02 0x70418
452#define SWF03 0x7041c
453#define SWF04 0x70420
454#define SWF05 0x70424
455#define SWF06 0x70428
456
457#define SWF10 SWF0
458#define SWF11 SWF1
459#define SWF12 SWF2
460#define SWF13 SWF3
461#define SWF14 SWF4
462#define SWF15 SWF5
463#define SWF16 SWF6
464
465#define SWF30 0x72414
466#define SWF31 0x72418
467#define SWF32 0x7241c
468
469/* Memory Commands */
470#define MI_NOOP (0x00 << 23)
471#define MI_NOOP_WRITE_ID (1 << 22)
472#define MI_NOOP_ID_MASK ((1 << 22) - 1)
473
474#define MI_FLUSH (0x04 << 23)
475#define MI_WRITE_DIRTY_STATE (1 << 4)
476#define MI_END_SCENE (1 << 3)
477#define MI_INHIBIT_RENDER_CACHE_FLUSH (1 << 2)
478#define MI_INVALIDATE_MAP_CACHE (1 << 0)
479
480#define MI_STORE_DWORD_IMM ((0x20 << 23) | 1)
481
482/* 2D Commands */
483#define COLOR_BLT_CMD ((2 << 29) | (0x40 << 22) | 3)
484#define XY_COLOR_BLT_CMD ((2 << 29) | (0x50 << 22) | 4)
485#define XY_SETUP_CLIP_BLT_CMD ((2 << 29) | (0x03 << 22) | 1)
486#define XY_SRC_COPY_BLT_CMD ((2 << 29) | (0x53 << 22) | 6)
487#define SRC_COPY_BLT_CMD ((2 << 29) | (0x43 << 22) | 4)
488#define XY_MONO_PAT_BLT_CMD ((2 << 29) | (0x52 << 22) | 7)
489#define XY_MONO_SRC_BLT_CMD ((2 << 29) | (0x54 << 22) | 6)
490#define XY_MONO_SRC_IMM_BLT_CMD ((2 << 29) | (0x71 << 22) | 5)
491#define TXT_IMM_BLT_CMD ((2 << 29) | (0x30 << 22) | 2)
492#define SETUP_BLT_CMD ((2 << 29) | (0x00 << 22) | 6)
493
494#define DW_LENGTH_MASK 0xff
495
496#define WRITE_ALPHA (1 << 21)
497#define WRITE_RGB (1 << 20)
498#define VERT_SEED (3 << 8)
499#define HORIZ_SEED (3 << 12)
500
501#define COLOR_DEPTH_8 (0 << 24)
502#define COLOR_DEPTH_16 (1 << 24)
503#define COLOR_DEPTH_32 (3 << 24)
504
505#define SRC_ROP_GXCOPY 0xcc
506#define SRC_ROP_GXXOR 0x66
507
508#define PAT_ROP_GXCOPY 0xf0
509#define PAT_ROP_GXXOR 0x5a
510
511#define PITCH_SHIFT 0
512#define ROP_SHIFT 16
513#define WIDTH_SHIFT 0
514#define HEIGHT_SHIFT 16
515
516/* in bytes */
517#define MAX_MONO_IMM_SIZE 128
518
519
520/*** Macros ***/
521
522/* I/O macros */
523#define INREG8(addr) readb((u8 __iomem *)(dinfo->mmio_base + (addr)))
524#define INREG16(addr) readw((u16 __iomem *)(dinfo->mmio_base + (addr)))
525#define INREG(addr) readl((u32 __iomem *)(dinfo->mmio_base + (addr)))
526#define OUTREG8(addr, val) writeb((val),(u8 __iomem *)(dinfo->mmio_base + \
527 (addr)))
528#define OUTREG16(addr, val) writew((val),(u16 __iomem *)(dinfo->mmio_base + \
529 (addr)))
530#define OUTREG(addr, val) writel((val),(u32 __iomem *)(dinfo->mmio_base + \
531 (addr)))
532
533/* Ring buffer macros */
534#define OUT_RING(n) do { \
535 writel((n), (u32 __iomem *)(dinfo->ring.virtual + dinfo->ring_tail));\
536 dinfo->ring_tail += 4; \
537 dinfo->ring_tail &= dinfo->ring_tail_mask; \
538} while (0)
539
540#define START_RING(n) do { \
541 if (dinfo->ring_space < (n) * 4) \
542 wait_ring(dinfo,(n) * 4); \
543 dinfo->ring_space -= (n) * 4; \
544} while (0)
545
546#define ADVANCE_RING() do { \
547 OUTREG(PRI_RING_TAIL, dinfo->ring_tail); \
548} while (0)
549
550#define DO_RING_IDLE() do { \
551 u32 head, tail; \
552 do { \
553 head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK; \
554 tail = INREG(PRI_RING_TAIL) & RING_TAIL_MASK; \
555 udelay(10); \
556 } while (head != tail); \
557} while (0)
558
559
560/* function protoypes */
561extern int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo);
562extern int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
563 int *stolen_size);
564extern int intelfbhw_check_non_crt(struct intelfb_info *dinfo);
565extern const char *intelfbhw_dvo_to_string(int dvo);
566extern int intelfbhw_validate_mode(struct intelfb_info *dinfo,
567 struct fb_var_screeninfo *var);
568extern int intelfbhw_pan_display(struct fb_var_screeninfo *var,
569 struct fb_info *info);
570extern void intelfbhw_do_blank(int blank, struct fb_info *info);
571extern void intelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno,
572 unsigned red, unsigned green, unsigned blue,
573 unsigned transp);
574extern int intelfbhw_read_hw_state(struct intelfb_info *dinfo,
575 struct intelfb_hwstate *hw, int flag);
576extern void intelfbhw_print_hw_state(struct intelfb_info *dinfo,
577 struct intelfb_hwstate *hw);
578extern int intelfbhw_mode_to_hw(struct intelfb_info *dinfo,
579 struct intelfb_hwstate *hw,
580 struct fb_var_screeninfo *var);
581extern int intelfbhw_program_mode(struct intelfb_info *dinfo,
582 const struct intelfb_hwstate *hw, int blank);
583extern void intelfbhw_do_sync(struct intelfb_info *dinfo);
584extern void intelfbhw_2d_stop(struct intelfb_info *dinfo);
585extern void intelfbhw_2d_start(struct intelfb_info *dinfo);
586extern void intelfbhw_do_fillrect(struct intelfb_info *dinfo, u32 x, u32 y,
587 u32 w, u32 h, u32 color, u32 pitch, u32 bpp,
588 u32 rop);
589extern void intelfbhw_do_bitblt(struct intelfb_info *dinfo, u32 curx, u32 cury,
590 u32 dstx, u32 dsty, u32 w, u32 h, u32 pitch,
591 u32 bpp);
592extern int intelfbhw_do_drawglyph(struct intelfb_info *dinfo, u32 fg, u32 bg,
593 u32 w, u32 h, const u8* cdat, u32 x, u32 y,
594 u32 pitch, u32 bpp);
595extern void intelfbhw_cursor_init(struct intelfb_info *dinfo);
596extern void intelfbhw_cursor_hide(struct intelfb_info *dinfo);
597extern void intelfbhw_cursor_show(struct intelfb_info *dinfo);
598extern void intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y);
599extern void intelfbhw_cursor_setcolor(struct intelfb_info *dinfo, u32 bg,
600 u32 fg);
601extern void intelfbhw_cursor_load(struct intelfb_info *dinfo, int width,
602 int height, u8 *data);
603extern void intelfbhw_cursor_reset(struct intelfb_info *dinfo);
604extern int intelfbhw_enable_irq(struct intelfb_info *dinfo);
605extern void intelfbhw_disable_irq(struct intelfb_info *dinfo);
606extern int intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe);
607extern int intelfbhw_active_pipe(const struct intelfb_hwstate *hw);
608
609#endif /* _INTELFBHW_H */