• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/video/intelfb/
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#include <linux/module.h>
26#include <linux/kernel.h>
27#include <linux/errno.h>
28#include <linux/string.h>
29#include <linux/mm.h>
30#include <linux/slab.h>
31#include <linux/delay.h>
32#include <linux/fb.h>
33#include <linux/ioport.h>
34#include <linux/init.h>
35#include <linux/pci.h>
36#include <linux/vmalloc.h>
37#include <linux/pagemap.h>
38#include <linux/screen_info.h>
39
40#include <asm/io.h>
41
42#ifdef CONFIG_MTRR
43#include <asm/mtrr.h>
44#endif
45
46#include "intelfb.h"
47#include "intelfbhw.h"
48#include "../edid.h"
49
50static void __devinit get_initial_mode(struct intelfb_info *dinfo);
51static void update_dinfo(struct intelfb_info *dinfo,
52			 struct fb_var_screeninfo *var);
53static int intelfb_open(struct fb_info *info, int user);
54static int intelfb_release(struct fb_info *info, int user);
55static int intelfb_check_var(struct fb_var_screeninfo *var,
56			     struct fb_info *info);
57static int intelfb_set_par(struct fb_info *info);
58static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
59			     unsigned blue, unsigned transp,
60			     struct fb_info *info);
61
62static int intelfb_blank(int blank, struct fb_info *info);
63static int intelfb_pan_display(struct fb_var_screeninfo *var,
64			       struct fb_info *info);
65
66static void intelfb_fillrect(struct fb_info *info,
67			     const struct fb_fillrect *rect);
68static void intelfb_copyarea(struct fb_info *info,
69			     const struct fb_copyarea *region);
70static void intelfb_imageblit(struct fb_info *info,
71			      const struct fb_image *image);
72static int intelfb_cursor(struct fb_info *info,
73			   struct fb_cursor *cursor);
74
75static int intelfb_sync(struct fb_info *info);
76
77static int intelfb_ioctl(struct fb_info *info,
78			 unsigned int cmd, unsigned long arg);
79
80static int __devinit intelfb_pci_register(struct pci_dev *pdev,
81					  const struct pci_device_id *ent);
82static void __devexit intelfb_pci_unregister(struct pci_dev *pdev);
83static int __devinit intelfb_set_fbinfo(struct intelfb_info *dinfo);
84
85/*
86 * Limiting the class to PCI_CLASS_DISPLAY_VGA prevents function 1 of the
87 * mobile chipsets from being registered.
88 */
89#if DETECT_VGA_CLASS_ONLY
90#define INTELFB_CLASS_MASK ~0 << 8
91#else
92#define INTELFB_CLASS_MASK 0
93#endif
94
95static struct pci_device_id intelfb_pci_table[] __devinitdata = {
96	{ 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 },
97	{ 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 },
98	{ 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 },
99	{ 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 },
100	{ 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 },
101	{ 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 },
102	{ 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 },
103	{ 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 },
104	{ 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 },
105	{ 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 },
106	{ 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 },
107	{ 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 },
108	{ 0, }
109};
110
111/* Global data */
112static int num_registered = 0;
113
114/* fb ops */
115static struct fb_ops intel_fb_ops = {
116	.owner =		THIS_MODULE,
117	.fb_open =              intelfb_open,
118	.fb_release =           intelfb_release,
119	.fb_check_var =         intelfb_check_var,
120	.fb_set_par =           intelfb_set_par,
121	.fb_setcolreg =		intelfb_setcolreg,
122	.fb_blank =		intelfb_blank,
123	.fb_pan_display =       intelfb_pan_display,
124	.fb_fillrect  =         intelfb_fillrect,
125	.fb_copyarea  =         intelfb_copyarea,
126	.fb_imageblit =         intelfb_imageblit,
127	.fb_cursor =            intelfb_cursor,
128	.fb_sync =              intelfb_sync,
129	.fb_ioctl =		intelfb_ioctl
130};
131
132/* PCI driver module table */
133static struct pci_driver intelfb_driver = {
134	.name =		"intelfb",
135	.id_table =	intelfb_pci_table,
136	.probe =	intelfb_pci_register,
137	.remove =	__devexit_p(intelfb_pci_unregister)
138};
139
140/* Module description/parameters */
141MODULE_AUTHOR("David Dawes <dawes@tungstengraphics.com>, "
142	      "Sylvain Meyer <sylvain.meyer@worldonline.fr>");
143MODULE_DESCRIPTION("Framebuffer driver for Intel(R) " SUPPORTED_CHIPSETS
144		   " chipsets");
145MODULE_LICENSE("Dual BSD/GPL");
146MODULE_DEVICE_TABLE(pci, intelfb_pci_table);
147
148static int accel        = 1;
149static int vram         = 4;
150static int hwcursor     = 0;
151static int mtrr         = 1;
152static int fixed        = 0;
153static int noinit       = 0;
154static int noregister   = 0;
155static int probeonly    = 0;
156static int idonly       = 0;
157static int bailearly    = 0;
158static int voffset	= 48;
159static char *mode       = NULL;
160
161module_param(accel, bool, S_IRUGO);
162MODULE_PARM_DESC(accel, "Enable hardware acceleration");
163module_param(vram, int, S_IRUGO);
164MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB");
165module_param(voffset, int, S_IRUGO);
166MODULE_PARM_DESC(voffset, "Offset of framebuffer in MiB");
167module_param(hwcursor, bool, S_IRUGO);
168MODULE_PARM_DESC(hwcursor, "Enable HW cursor");
169module_param(mtrr, bool, S_IRUGO);
170MODULE_PARM_DESC(mtrr, "Enable MTRR support");
171module_param(fixed, bool, S_IRUGO);
172MODULE_PARM_DESC(fixed, "Disable mode switching");
173module_param(noinit, bool, 0);
174MODULE_PARM_DESC(noinit, "Don't initialise graphics mode when loading");
175module_param(noregister, bool, 0);
176MODULE_PARM_DESC(noregister, "Don't register, just probe and exit (debug)");
177module_param(probeonly, bool, 0);
178MODULE_PARM_DESC(probeonly, "Do a minimal probe (debug)");
179module_param(idonly, bool, 0);
180MODULE_PARM_DESC(idonly, "Just identify without doing anything else (debug)");
181module_param(bailearly, bool, 0);
182MODULE_PARM_DESC(bailearly, "Bail out early, depending on value (debug)");
183module_param(mode, charp, S_IRUGO);
184MODULE_PARM_DESC(mode,
185		 "Initial video mode \"<xres>x<yres>[-<depth>][@<refresh>]\"");
186
187#ifndef MODULE
188#define OPT_EQUAL(opt, name) (!strncmp(opt, name, strlen(name)))
189#define OPT_INTVAL(opt, name) simple_strtoul(opt + strlen(name) + 1, NULL, 0)
190#define OPT_STRVAL(opt, name) (opt + strlen(name))
191
192static __inline__ char * get_opt_string(const char *this_opt, const char *name)
193{
194	const char *p;
195	int i;
196	char *ret;
197
198	p = OPT_STRVAL(this_opt, name);
199	i = 0;
200	while (p[i] && p[i] != ' ' && p[i] != ',')
201		i++;
202	ret = kmalloc(i + 1, GFP_KERNEL);
203	if (ret) {
204		strncpy(ret, p, i);
205		ret[i] = '\0';
206	}
207	return ret;
208}
209
210static __inline__ int get_opt_int(const char *this_opt, const char *name,
211				  int *ret)
212{
213	if (!ret)
214		return 0;
215
216	if (!OPT_EQUAL(this_opt, name))
217		return 0;
218
219	*ret = OPT_INTVAL(this_opt, name);
220	return 1;
221}
222
223static __inline__ int get_opt_bool(const char *this_opt, const char *name,
224				   int *ret)
225{
226	if (!ret)
227		return 0;
228
229	if (OPT_EQUAL(this_opt, name)) {
230		if (this_opt[strlen(name)] == '=')
231			*ret = simple_strtoul(this_opt + strlen(name) + 1,
232					      NULL, 0);
233		else
234			*ret = 1;
235	} else {
236		if (OPT_EQUAL(this_opt, "no") && OPT_EQUAL(this_opt + 2, name))
237			*ret = 0;
238		else
239			return 0;
240	}
241	return 1;
242}
243
244static int __init intelfb_setup(char *options)
245{
246	char *this_opt;
247
248	DBG_MSG("intelfb_setup\n");
249
250	if (!options || !*options) {
251		DBG_MSG("no options\n");
252		return 0;
253	} else
254		DBG_MSG("options: %s\n", options);
255
256	/*
257	 * These are the built-in options analogous to the module parameters
258	 * defined above.
259	 *
260	 * The syntax is:
261	 *
262	 *    video=intelfb:[mode][,<param>=<val>] ...
263	 *
264	 * e.g.,
265	 *
266	 *    video=intelfb:1024x768-16@75,accel=0
267	 */
268
269	while ((this_opt = strsep(&options, ","))) {
270		if (!*this_opt)
271			continue;
272		if (get_opt_bool(this_opt, "accel", &accel))
273			;
274		else if (get_opt_int(this_opt, "vram", &vram))
275			;
276		else if (get_opt_bool(this_opt, "hwcursor", &hwcursor))
277			;
278		else if (get_opt_bool(this_opt, "mtrr", &mtrr))
279			;
280		else if (get_opt_bool(this_opt, "fixed", &fixed))
281			;
282		else if (get_opt_bool(this_opt, "init", &noinit))
283			noinit = !noinit;
284		else if (OPT_EQUAL(this_opt, "mode="))
285			mode = get_opt_string(this_opt, "mode=");
286		else
287			mode = this_opt;
288	}
289
290	return 0;
291}
292
293#endif
294
295static int __init intelfb_init(void)
296{
297#ifndef MODULE
298	char *option = NULL;
299#endif
300
301	DBG_MSG("intelfb_init\n");
302
303	INF_MSG("Framebuffer driver for "
304		"Intel(R) " SUPPORTED_CHIPSETS " chipsets\n");
305	INF_MSG("Version " INTELFB_VERSION "\n");
306
307	if (idonly)
308		return -ENODEV;
309
310#ifndef MODULE
311	if (fb_get_options("intelfb", &option))
312		return -ENODEV;
313	intelfb_setup(option);
314#endif
315
316	return pci_register_driver(&intelfb_driver);
317}
318
319static void __exit intelfb_exit(void)
320{
321	DBG_MSG("intelfb_exit\n");
322	pci_unregister_driver(&intelfb_driver);
323}
324
325module_init(intelfb_init);
326module_exit(intelfb_exit);
327
328/***************************************************************
329 *                     mtrr support functions                  *
330 ***************************************************************/
331
332#ifdef CONFIG_MTRR
333static inline void __devinit set_mtrr(struct intelfb_info *dinfo)
334{
335	dinfo->mtrr_reg = mtrr_add(dinfo->aperture.physical,
336				   dinfo->aperture.size, MTRR_TYPE_WRCOMB, 1);
337	if (dinfo->mtrr_reg < 0) {
338		ERR_MSG("unable to set MTRR\n");
339		return;
340	}
341	dinfo->has_mtrr = 1;
342}
343static inline void unset_mtrr(struct intelfb_info *dinfo)
344{
345	if (dinfo->has_mtrr)
346		mtrr_del(dinfo->mtrr_reg, dinfo->aperture.physical,
347			 dinfo->aperture.size);
348}
349#else
350#define set_mtrr(x) WRN_MSG("MTRR is disabled in the kernel\n")
351
352#define unset_mtrr(x) do { } while (0)
353#endif /* CONFIG_MTRR */
354
355/***************************************************************
356 *                        driver init / cleanup                *
357 ***************************************************************/
358
359static void cleanup(struct intelfb_info *dinfo)
360{
361	DBG_MSG("cleanup\n");
362
363	if (!dinfo)
364		return;
365
366	intelfbhw_disable_irq(dinfo);
367
368	fb_dealloc_cmap(&dinfo->info->cmap);
369	kfree(dinfo->info->pixmap.addr);
370
371	if (dinfo->registered)
372		unregister_framebuffer(dinfo->info);
373
374	unset_mtrr(dinfo);
375
376	if (dinfo->fbmem_gart && dinfo->gtt_fb_mem) {
377		agp_unbind_memory(dinfo->gtt_fb_mem);
378		agp_free_memory(dinfo->gtt_fb_mem);
379	}
380	if (dinfo->gtt_cursor_mem) {
381		agp_unbind_memory(dinfo->gtt_cursor_mem);
382		agp_free_memory(dinfo->gtt_cursor_mem);
383	}
384	if (dinfo->gtt_ring_mem) {
385		agp_unbind_memory(dinfo->gtt_ring_mem);
386		agp_free_memory(dinfo->gtt_ring_mem);
387	}
388
389#ifdef CONFIG_FB_INTEL_I2C
390	/* un-register I2C bus */
391	intelfb_delete_i2c_busses(dinfo);
392#endif
393
394	if (dinfo->mmio_base)
395		iounmap((void __iomem *)dinfo->mmio_base);
396	if (dinfo->aperture.virtual)
397		iounmap((void __iomem *)dinfo->aperture.virtual);
398
399	if (dinfo->flag & INTELFB_MMIO_ACQUIRED)
400		release_mem_region(dinfo->mmio_base_phys, INTEL_REG_SIZE);
401	if (dinfo->flag & INTELFB_FB_ACQUIRED)
402		release_mem_region(dinfo->aperture.physical,
403				   dinfo->aperture.size);
404	framebuffer_release(dinfo->info);
405}
406
407#define bailout(dinfo) do {						\
408	DBG_MSG("bailout\n");						\
409	cleanup(dinfo);							\
410	INF_MSG("Not going to register framebuffer, exiting...\n");	\
411	return -ENODEV;							\
412} while (0)
413
414
415static int __devinit intelfb_pci_register(struct pci_dev *pdev,
416					  const struct pci_device_id *ent)
417{
418	struct fb_info *info;
419	struct intelfb_info *dinfo;
420	int i, err, dvo;
421	int aperture_size, stolen_size;
422	struct agp_kern_info gtt_info;
423	int agp_memtype;
424	const char *s;
425	struct agp_bridge_data *bridge;
426	int aperture_bar = 0;
427	int mmio_bar = 1;
428	int offset;
429
430	DBG_MSG("intelfb_pci_register\n");
431
432	num_registered++;
433	if (num_registered != 1) {
434		ERR_MSG("Attempted to register %d devices "
435			"(should be only 1).\n", num_registered);
436		return -ENODEV;
437	}
438
439	info = framebuffer_alloc(sizeof(struct intelfb_info), &pdev->dev);
440	if (!info) {
441		ERR_MSG("Could not allocate memory for intelfb_info.\n");
442		return -ENODEV;
443	}
444	if (fb_alloc_cmap(&info->cmap, 256, 1) < 0) {
445		ERR_MSG("Could not allocate cmap for intelfb_info.\n");
446		goto err_out_cmap;
447		return -ENODEV;
448	}
449
450	dinfo = info->par;
451	dinfo->info  = info;
452	dinfo->fbops = &intel_fb_ops;
453	dinfo->pdev  = pdev;
454
455	/* Reserve pixmap space. */
456	info->pixmap.addr = kzalloc(64 * 1024, GFP_KERNEL);
457	if (info->pixmap.addr == NULL) {
458		ERR_MSG("Cannot reserve pixmap memory.\n");
459		goto err_out_pixmap;
460	}
461
462	/* set early this option because it could be changed by tv encoder
463	   driver */
464	dinfo->fixed_mode = fixed;
465
466	/* Enable device. */
467	if ((err = pci_enable_device(pdev))) {
468		ERR_MSG("Cannot enable device.\n");
469		cleanup(dinfo);
470		return -ENODEV;
471	}
472
473	/* Set base addresses. */
474	if ((ent->device == PCI_DEVICE_ID_INTEL_915G) ||
475	    (ent->device == PCI_DEVICE_ID_INTEL_915GM) ||
476	    (ent->device == PCI_DEVICE_ID_INTEL_945G)  ||
477	    (ent->device == PCI_DEVICE_ID_INTEL_945GM) ||
478	    (ent->device == PCI_DEVICE_ID_INTEL_945GME) ||
479	    (ent->device == PCI_DEVICE_ID_INTEL_965G) ||
480	    (ent->device == PCI_DEVICE_ID_INTEL_965GM)) {
481
482		aperture_bar = 2;
483		mmio_bar = 0;
484	}
485	dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar);
486	dinfo->aperture.size     = pci_resource_len(pdev, aperture_bar);
487	dinfo->mmio_base_phys    = pci_resource_start(pdev, mmio_bar);
488	DBG_MSG("fb aperture: 0x%llx/0x%llx, MMIO region: 0x%llx/0x%llx\n",
489		(unsigned long long)pci_resource_start(pdev, aperture_bar),
490		(unsigned long long)pci_resource_len(pdev, aperture_bar),
491		(unsigned long long)pci_resource_start(pdev, mmio_bar),
492		(unsigned long long)pci_resource_len(pdev, mmio_bar));
493
494	/* Reserve the fb and MMIO regions */
495	if (!request_mem_region(dinfo->aperture.physical, dinfo->aperture.size,
496				INTELFB_MODULE_NAME)) {
497		ERR_MSG("Cannot reserve FB region.\n");
498		cleanup(dinfo);
499		return -ENODEV;
500	}
501
502	dinfo->flag |= INTELFB_FB_ACQUIRED;
503
504	if (!request_mem_region(dinfo->mmio_base_phys,
505				INTEL_REG_SIZE,
506				INTELFB_MODULE_NAME)) {
507		ERR_MSG("Cannot reserve MMIO region.\n");
508		cleanup(dinfo);
509		return -ENODEV;
510	}
511
512	dinfo->flag |= INTELFB_MMIO_ACQUIRED;
513
514	/* Get the chipset info. */
515	dinfo->pci_chipset = pdev->device;
516
517	if (intelfbhw_get_chipset(pdev, dinfo)) {
518		cleanup(dinfo);
519		return -ENODEV;
520	}
521
522	if (intelfbhw_get_memory(pdev, &aperture_size,&stolen_size)) {
523		cleanup(dinfo);
524		return -ENODEV;
525	}
526
527	INF_MSG("%02x:%02x.%d: %s, aperture size %dMB, "
528		"stolen memory %dkB\n",
529		pdev->bus->number, PCI_SLOT(pdev->devfn),
530		PCI_FUNC(pdev->devfn), dinfo->name,
531		BtoMB(aperture_size), BtoKB(stolen_size));
532
533	/* Set these from the options. */
534	dinfo->accel    = accel;
535	dinfo->hwcursor = hwcursor;
536
537	if (NOACCEL_CHIPSET(dinfo) && dinfo->accel == 1) {
538		INF_MSG("Acceleration is not supported for the %s chipset.\n",
539			dinfo->name);
540		dinfo->accel = 0;
541	}
542
543	/* Framebuffer parameters - Use all the stolen memory if >= vram */
544	if (ROUND_UP_TO_PAGE(stolen_size) >= MB(vram)) {
545		dinfo->fb.size = ROUND_UP_TO_PAGE(stolen_size);
546		dinfo->fbmem_gart = 0;
547	} else {
548		dinfo->fb.size =  MB(vram);
549		dinfo->fbmem_gart = 1;
550	}
551
552	/* Allocate space for the ring buffer and HW cursor if enabled. */
553	if (dinfo->accel) {
554		dinfo->ring.size = RINGBUFFER_SIZE;
555		dinfo->ring_tail_mask = dinfo->ring.size - 1;
556	}
557	if (dinfo->hwcursor)
558		dinfo->cursor.size = HW_CURSOR_SIZE;
559
560	/* Use agpgart to manage the GATT */
561	if (!(bridge = agp_backend_acquire(pdev))) {
562		ERR_MSG("cannot acquire agp\n");
563		cleanup(dinfo);
564		return -ENODEV;
565	}
566
567	/* get the current gatt info */
568	if (agp_copy_info(bridge, &gtt_info)) {
569		ERR_MSG("cannot get agp info\n");
570		agp_backend_release(bridge);
571		cleanup(dinfo);
572		return -ENODEV;
573	}
574
575	if (MB(voffset) < stolen_size)
576		offset = (stolen_size >> 12);
577	else
578		offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE;
579
580	/* set the mem offsets - set them after the already used pages */
581	if (dinfo->accel)
582		dinfo->ring.offset = offset + gtt_info.current_memory;
583	if (dinfo->hwcursor)
584		dinfo->cursor.offset = offset +
585			+ gtt_info.current_memory + (dinfo->ring.size >> 12);
586	if (dinfo->fbmem_gart)
587		dinfo->fb.offset = offset +
588			+ gtt_info.current_memory + (dinfo->ring.size >> 12)
589			+ (dinfo->cursor.size >> 12);
590
591	/* Allocate memories (which aren't stolen) */
592	/* Map the fb and MMIO regions */
593	/* ioremap only up to the end of used aperture */
594	dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache
595		(dinfo->aperture.physical, ((offset + dinfo->fb.offset) << 12)
596		 + dinfo->fb.size);
597	if (!dinfo->aperture.virtual) {
598		ERR_MSG("Cannot remap FB region.\n");
599		cleanup(dinfo);
600		return -ENODEV;
601	}
602
603	dinfo->mmio_base =
604		(u8 __iomem *)ioremap_nocache(dinfo->mmio_base_phys,
605					      INTEL_REG_SIZE);
606	if (!dinfo->mmio_base) {
607		ERR_MSG("Cannot remap MMIO region.\n");
608		cleanup(dinfo);
609		return -ENODEV;
610	}
611
612	if (dinfo->accel) {
613		if (!(dinfo->gtt_ring_mem =
614		      agp_allocate_memory(bridge, dinfo->ring.size >> 12,
615					  AGP_NORMAL_MEMORY))) {
616			ERR_MSG("cannot allocate ring buffer memory\n");
617			agp_backend_release(bridge);
618			cleanup(dinfo);
619			return -ENOMEM;
620		}
621		if (agp_bind_memory(dinfo->gtt_ring_mem,
622				    dinfo->ring.offset)) {
623			ERR_MSG("cannot bind ring buffer memory\n");
624			agp_backend_release(bridge);
625			cleanup(dinfo);
626			return -EBUSY;
627		}
628		dinfo->ring.physical = dinfo->aperture.physical
629			+ (dinfo->ring.offset << 12);
630		dinfo->ring.virtual  = dinfo->aperture.virtual
631			+ (dinfo->ring.offset << 12);
632		dinfo->ring_head = 0;
633	}
634	if (dinfo->hwcursor) {
635		agp_memtype = dinfo->mobile ? AGP_PHYSICAL_MEMORY
636			: AGP_NORMAL_MEMORY;
637		if (!(dinfo->gtt_cursor_mem =
638		      agp_allocate_memory(bridge, dinfo->cursor.size >> 12,
639					  agp_memtype))) {
640			ERR_MSG("cannot allocate cursor memory\n");
641			agp_backend_release(bridge);
642			cleanup(dinfo);
643			return -ENOMEM;
644		}
645		if (agp_bind_memory(dinfo->gtt_cursor_mem,
646				    dinfo->cursor.offset)) {
647			ERR_MSG("cannot bind cursor memory\n");
648			agp_backend_release(bridge);
649			cleanup(dinfo);
650			return -EBUSY;
651		}
652		if (dinfo->mobile)
653			dinfo->cursor.physical
654				= dinfo->gtt_cursor_mem->physical;
655		else
656			dinfo->cursor.physical = dinfo->aperture.physical
657				+ (dinfo->cursor.offset << 12);
658		dinfo->cursor.virtual = dinfo->aperture.virtual
659			+ (dinfo->cursor.offset << 12);
660	}
661	if (dinfo->fbmem_gart) {
662		if (!(dinfo->gtt_fb_mem =
663		      agp_allocate_memory(bridge, dinfo->fb.size >> 12,
664					  AGP_NORMAL_MEMORY))) {
665			WRN_MSG("cannot allocate framebuffer memory - use "
666				"the stolen one\n");
667			dinfo->fbmem_gart = 0;
668		}
669		if (agp_bind_memory(dinfo->gtt_fb_mem,
670				    dinfo->fb.offset)) {
671			WRN_MSG("cannot bind framebuffer memory - use "
672				"the stolen one\n");
673			dinfo->fbmem_gart = 0;
674		}
675	}
676
677	/* update framebuffer memory parameters */
678	if (!dinfo->fbmem_gart)
679		dinfo->fb.offset = 0;   /* starts at offset 0 */
680	dinfo->fb.physical = dinfo->aperture.physical
681		+ (dinfo->fb.offset << 12);
682	dinfo->fb.virtual = dinfo->aperture.virtual + (dinfo->fb.offset << 12);
683	dinfo->fb_start = dinfo->fb.offset << 12;
684
685	/* release agpgart */
686	agp_backend_release(bridge);
687
688	if (mtrr)
689		set_mtrr(dinfo);
690
691	DBG_MSG("fb: 0x%x(+ 0x%x)/0x%x (0x%p)\n",
692		dinfo->fb.physical, dinfo->fb.offset, dinfo->fb.size,
693		dinfo->fb.virtual);
694	DBG_MSG("MMIO: 0x%x/0x%x (0x%p)\n",
695		dinfo->mmio_base_phys, INTEL_REG_SIZE,
696		dinfo->mmio_base);
697	DBG_MSG("ring buffer: 0x%x/0x%x (0x%p)\n",
698		dinfo->ring.physical, dinfo->ring.size,
699		dinfo->ring.virtual);
700	DBG_MSG("HW cursor: 0x%x/0x%x (0x%p) (offset 0x%x) (phys 0x%x)\n",
701		dinfo->cursor.physical, dinfo->cursor.size,
702		dinfo->cursor.virtual, dinfo->cursor.offset,
703		dinfo->cursor.physical);
704
705	DBG_MSG("options: vram = %d, accel = %d, hwcursor = %d, fixed = %d, "
706		"noinit = %d\n", vram, accel, hwcursor, fixed, noinit);
707	DBG_MSG("options: mode = \"%s\"\n", mode ? mode : "");
708
709	if (probeonly)
710		bailout(dinfo);
711
712	/*
713	 * Check if the LVDS port or any DVO ports are enabled.  If so,
714	 * don't allow mode switching
715	 */
716	dvo = intelfbhw_check_non_crt(dinfo);
717	if (dvo) {
718		dinfo->fixed_mode = 1;
719		WRN_MSG("Non-CRT device is enabled ( ");
720		i = 0;
721		while (dvo) {
722			if (dvo & 1) {
723				s = intelfbhw_dvo_to_string(1 << i);
724				if (s)
725					printk("%s ", s);
726			}
727			dvo >>= 1;
728			++i;
729		}
730		printk(").  Disabling mode switching.\n");
731	}
732
733	if (bailearly == 1)
734		bailout(dinfo);
735
736	if (FIXED_MODE(dinfo) &&
737	    screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) {
738		ERR_MSG("Video mode must be programmed at boot time.\n");
739		cleanup(dinfo);
740		return -ENODEV;
741	}
742
743	if (bailearly == 2)
744		bailout(dinfo);
745
746	/* Initialise dinfo and related data. */
747	/* If an initial mode was programmed at boot time, get its details. */
748	if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB)
749		get_initial_mode(dinfo);
750
751	if (bailearly == 3)
752		bailout(dinfo);
753
754	if (FIXED_MODE(dinfo))	/* remap fb address */
755		update_dinfo(dinfo, &dinfo->initial_var);
756
757	if (bailearly == 4)
758		bailout(dinfo);
759
760
761	if (intelfb_set_fbinfo(dinfo)) {
762		cleanup(dinfo);
763		return -ENODEV;
764	}
765
766	if (bailearly == 5)
767		bailout(dinfo);
768
769#ifdef CONFIG_FB_INTEL_I2C
770	/* register I2C bus */
771	intelfb_create_i2c_busses(dinfo);
772#endif
773
774	if (bailearly == 6)
775		bailout(dinfo);
776
777	pci_set_drvdata(pdev, dinfo);
778
779	/* Save the initial register state. */
780	i = intelfbhw_read_hw_state(dinfo, &dinfo->save_state,
781				    bailearly > 6 ? bailearly - 6 : 0);
782	if (i != 0) {
783		DBG_MSG("intelfbhw_read_hw_state returned %d\n", i);
784		bailout(dinfo);
785	}
786
787	intelfbhw_print_hw_state(dinfo, &dinfo->save_state);
788
789	if (bailearly == 18)
790		bailout(dinfo);
791
792	/* read active pipe */
793	dinfo->pipe = intelfbhw_active_pipe(&dinfo->save_state);
794
795	/* Cursor initialisation */
796	if (dinfo->hwcursor) {
797		intelfbhw_cursor_init(dinfo);
798		intelfbhw_cursor_reset(dinfo);
799	}
800
801	if (bailearly == 19)
802		bailout(dinfo);
803
804	/* 2d acceleration init */
805	if (dinfo->accel)
806		intelfbhw_2d_start(dinfo);
807
808	if (bailearly == 20)
809		bailout(dinfo);
810
811	if (noregister)
812		bailout(dinfo);
813
814	if (register_framebuffer(dinfo->info) < 0) {
815		ERR_MSG("Cannot register framebuffer.\n");
816		cleanup(dinfo);
817		return -ENODEV;
818	}
819
820	dinfo->registered = 1;
821	dinfo->open = 0;
822
823	init_waitqueue_head(&dinfo->vsync.wait);
824	spin_lock_init(&dinfo->int_lock);
825	dinfo->irq_flags = 0;
826	dinfo->vsync.pan_display = 0;
827	dinfo->vsync.pan_offset = 0;
828
829	return 0;
830
831err_out_pixmap:
832	fb_dealloc_cmap(&info->cmap);
833err_out_cmap:
834	framebuffer_release(info);
835	return -ENODEV;
836}
837
838static void __devexit
839intelfb_pci_unregister(struct pci_dev *pdev)
840{
841	struct intelfb_info *dinfo = pci_get_drvdata(pdev);
842
843	DBG_MSG("intelfb_pci_unregister\n");
844
845	if (!dinfo)
846		return;
847
848	cleanup(dinfo);
849
850	pci_set_drvdata(pdev, NULL);
851}
852
853/***************************************************************
854 *                       helper functions                      *
855 ***************************************************************/
856
857int __inline__ intelfb_var_to_depth(const struct fb_var_screeninfo *var)
858{
859	DBG_MSG("intelfb_var_to_depth: bpp: %d, green.length is %d\n",
860		var->bits_per_pixel, var->green.length);
861
862	switch (var->bits_per_pixel) {
863	case 16:
864		return (var->green.length == 6) ? 16 : 15;
865	case 32:
866		return 24;
867	default:
868		return var->bits_per_pixel;
869	}
870}
871
872
873static __inline__ int var_to_refresh(const struct fb_var_screeninfo *var)
874{
875	int xtot = var->xres + var->left_margin + var->right_margin +
876		   var->hsync_len;
877	int ytot = var->yres + var->upper_margin + var->lower_margin +
878		   var->vsync_len;
879
880	return (1000000000 / var->pixclock * 1000 + 500) / xtot / ytot;
881}
882
883/***************************************************************
884 *                Various intialisation functions              *
885 ***************************************************************/
886
887static void __devinit get_initial_mode(struct intelfb_info *dinfo)
888{
889	struct fb_var_screeninfo *var;
890	int xtot, ytot;
891
892	DBG_MSG("get_initial_mode\n");
893
894	dinfo->initial_vga = 1;
895	dinfo->initial_fb_base = screen_info.lfb_base;
896	dinfo->initial_video_ram = screen_info.lfb_size * KB(64);
897	dinfo->initial_pitch = screen_info.lfb_linelength;
898
899	var = &dinfo->initial_var;
900	memset(var, 0, sizeof(*var));
901	var->xres = screen_info.lfb_width;
902	var->yres = screen_info.lfb_height;
903	var->bits_per_pixel = screen_info.lfb_depth;
904	switch (screen_info.lfb_depth) {
905	case 15:
906		var->bits_per_pixel = 16;
907		break;
908	case 24:
909		var->bits_per_pixel = 32;
910		break;
911	}
912
913	DBG_MSG("Initial info: FB is 0x%x/0x%x (%d kByte)\n",
914		dinfo->initial_fb_base, dinfo->initial_video_ram,
915		BtoKB(dinfo->initial_video_ram));
916
917	DBG_MSG("Initial info: mode is %dx%d-%d (%d)\n",
918		var->xres, var->yres, var->bits_per_pixel,
919		dinfo->initial_pitch);
920
921	/* Dummy timing values (assume 60Hz) */
922	var->left_margin = (var->xres / 8) & 0xf8;
923	var->right_margin = 32;
924	var->upper_margin = 16;
925	var->lower_margin = 4;
926	var->hsync_len = (var->xres / 8) & 0xf8;
927	var->vsync_len = 4;
928
929	xtot = var->xres + var->left_margin +
930		var->right_margin + var->hsync_len;
931	ytot = var->yres + var->upper_margin +
932		var->lower_margin + var->vsync_len;
933	var->pixclock = 10000000 / xtot * 1000 / ytot * 100 / 60;
934
935	var->height = -1;
936	var->width = -1;
937
938	if (var->bits_per_pixel > 8) {
939		var->red.offset = screen_info.red_pos;
940		var->red.length = screen_info.red_size;
941		var->green.offset = screen_info.green_pos;
942		var->green.length = screen_info.green_size;
943		var->blue.offset = screen_info.blue_pos;
944		var->blue.length = screen_info.blue_size;
945		var->transp.offset = screen_info.rsvd_pos;
946		var->transp.length = screen_info.rsvd_size;
947	} else {
948		var->red.length = 8;
949		var->green.length = 8;
950		var->blue.length = 8;
951	}
952}
953
954static int __devinit intelfb_init_var(struct intelfb_info *dinfo)
955{
956	struct fb_var_screeninfo *var;
957	int msrc = 0;
958
959	DBG_MSG("intelfb_init_var\n");
960
961	var = &dinfo->info->var;
962	if (FIXED_MODE(dinfo)) {
963	        memcpy(var, &dinfo->initial_var,
964		       sizeof(struct fb_var_screeninfo));
965		msrc = 5;
966	} else {
967		const u8 *edid_s = fb_firmware_edid(&dinfo->pdev->dev);
968		u8 *edid_d = NULL;
969
970		if (edid_s) {
971			edid_d = kmemdup(edid_s, EDID_LENGTH, GFP_KERNEL);
972
973			if (edid_d) {
974				fb_edid_to_monspecs(edid_d,
975						    &dinfo->info->monspecs);
976				kfree(edid_d);
977			}
978		}
979
980		if (mode) {
981			printk("intelfb: Looking for mode in private "
982			       "database\n");
983			msrc = fb_find_mode(var, dinfo->info, mode,
984					    dinfo->info->monspecs.modedb,
985					    dinfo->info->monspecs.modedb_len,
986					    NULL, 0);
987
988			if (msrc && msrc > 1) {
989				printk("intelfb: No mode in private database, "
990				       "intelfb: looking for mode in global "
991				       "database ");
992				msrc = fb_find_mode(var, dinfo->info, mode,
993						    NULL, 0, NULL, 0);
994
995				if (msrc)
996					msrc |= 8;
997			}
998
999		}
1000
1001		if (!msrc)
1002			msrc = fb_find_mode(var, dinfo->info, PREFERRED_MODE,
1003					    NULL, 0, NULL, 0);
1004	}
1005
1006	if (!msrc) {
1007		ERR_MSG("Cannot find a suitable video mode.\n");
1008		return 1;
1009	}
1010
1011	INF_MSG("Initial video mode is %dx%d-%d@%d.\n", var->xres, var->yres,
1012		var->bits_per_pixel, var_to_refresh(var));
1013
1014	DBG_MSG("Initial video mode is from %d.\n", msrc);
1015
1016#if ALLOCATE_FOR_PANNING
1017	/* Allow use of half of the video ram for panning */
1018	var->xres_virtual = var->xres;
1019	var->yres_virtual =
1020		dinfo->fb.size / 2 / (var->bits_per_pixel * var->xres);
1021	if (var->yres_virtual < var->yres)
1022		var->yres_virtual = var->yres;
1023#else
1024	var->yres_virtual = var->yres;
1025#endif
1026
1027	if (dinfo->accel)
1028		var->accel_flags |= FB_ACCELF_TEXT;
1029	else
1030		var->accel_flags &= ~FB_ACCELF_TEXT;
1031
1032	return 0;
1033}
1034
1035static int __devinit intelfb_set_fbinfo(struct intelfb_info *dinfo)
1036{
1037	struct fb_info *info = dinfo->info;
1038
1039	DBG_MSG("intelfb_set_fbinfo\n");
1040
1041	info->flags = FBINFO_FLAG_DEFAULT;
1042	info->fbops = &intel_fb_ops;
1043	info->pseudo_palette = dinfo->pseudo_palette;
1044
1045	info->pixmap.size = 64*1024;
1046	info->pixmap.buf_align = 8;
1047	info->pixmap.access_align = 32;
1048	info->pixmap.flags = FB_PIXMAP_SYSTEM;
1049
1050	if (intelfb_init_var(dinfo))
1051		return 1;
1052
1053	info->pixmap.scan_align = 1;
1054	strcpy(info->fix.id, dinfo->name);
1055	info->fix.smem_start = dinfo->fb.physical;
1056	info->fix.smem_len = dinfo->fb.size;
1057	info->fix.type = FB_TYPE_PACKED_PIXELS;
1058	info->fix.type_aux = 0;
1059	info->fix.xpanstep = 8;
1060	info->fix.ypanstep = 1;
1061	info->fix.ywrapstep = 0;
1062	info->fix.mmio_start = dinfo->mmio_base_phys;
1063	info->fix.mmio_len = INTEL_REG_SIZE;
1064	info->fix.accel = FB_ACCEL_I830;
1065	update_dinfo(dinfo, &info->var);
1066
1067	return 0;
1068}
1069
1070/* Update dinfo to match the active video mode. */
1071static void update_dinfo(struct intelfb_info *dinfo,
1072			 struct fb_var_screeninfo *var)
1073{
1074	DBG_MSG("update_dinfo\n");
1075
1076	dinfo->bpp = var->bits_per_pixel;
1077	dinfo->depth = intelfb_var_to_depth(var);
1078	dinfo->xres = var->xres;
1079	dinfo->yres = var->xres;
1080	dinfo->pixclock = var->pixclock;
1081
1082	dinfo->info->fix.visual = dinfo->visual;
1083	dinfo->info->fix.line_length = dinfo->pitch;
1084
1085	switch (dinfo->bpp) {
1086	case 8:
1087		dinfo->visual = FB_VISUAL_PSEUDOCOLOR;
1088		dinfo->pitch = var->xres_virtual;
1089		break;
1090	case 16:
1091		dinfo->visual = FB_VISUAL_TRUECOLOR;
1092		dinfo->pitch = var->xres_virtual * 2;
1093		break;
1094	case 32:
1095		dinfo->visual = FB_VISUAL_TRUECOLOR;
1096		dinfo->pitch = var->xres_virtual * 4;
1097		break;
1098	}
1099
1100	/* Make sure the line length is a aligned correctly. */
1101	if (IS_I9XX(dinfo))
1102		dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT_I9XX);
1103	else
1104		dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT);
1105
1106	if (FIXED_MODE(dinfo))
1107		dinfo->pitch = dinfo->initial_pitch;
1108
1109	dinfo->info->screen_base = (char __iomem *)dinfo->fb.virtual;
1110	dinfo->info->fix.line_length = dinfo->pitch;
1111	dinfo->info->fix.visual = dinfo->visual;
1112}
1113
1114/* fbops functions */
1115
1116/***************************************************************
1117 *                       fbdev interface                       *
1118 ***************************************************************/
1119
1120static int intelfb_open(struct fb_info *info, int user)
1121{
1122	struct intelfb_info *dinfo = GET_DINFO(info);
1123
1124	if (user)
1125		dinfo->open++;
1126
1127	return 0;
1128}
1129
1130static int intelfb_release(struct fb_info *info, int user)
1131{
1132	struct intelfb_info *dinfo = GET_DINFO(info);
1133
1134	if (user) {
1135		dinfo->open--;
1136		msleep(1);
1137		if (!dinfo->open)
1138			intelfbhw_disable_irq(dinfo);
1139	}
1140
1141	return 0;
1142}
1143
1144static int intelfb_check_var(struct fb_var_screeninfo *var,
1145			     struct fb_info *info)
1146{
1147	int change_var = 0;
1148	struct fb_var_screeninfo v;
1149	struct intelfb_info *dinfo;
1150	static int first = 1;
1151	int i;
1152	/* Good pitches to allow tiling.  Don't care about pitches < 1024. */
1153	static const int pitches[] = {
1154		128 * 8,
1155		128 * 16,
1156		128 * 32,
1157		128 * 64,
1158		0
1159	};
1160
1161	DBG_MSG("intelfb_check_var: accel_flags is %d\n", var->accel_flags);
1162
1163	dinfo = GET_DINFO(info);
1164
1165	/* update the pitch */
1166	if (intelfbhw_validate_mode(dinfo, var) != 0)
1167		return -EINVAL;
1168
1169	v = *var;
1170
1171	for (i = 0; pitches[i] != 0; i++) {
1172		if (pitches[i] >= v.xres_virtual) {
1173			v.xres_virtual = pitches[i];
1174			break;
1175		}
1176	}
1177
1178	/* Check for a supported bpp. */
1179	if (v.bits_per_pixel <= 8)
1180		v.bits_per_pixel = 8;
1181	else if (v.bits_per_pixel <= 16) {
1182		if (v.bits_per_pixel == 16)
1183			v.green.length = 6;
1184		v.bits_per_pixel = 16;
1185	} else if (v.bits_per_pixel <= 32)
1186		v.bits_per_pixel = 32;
1187	else
1188		return -EINVAL;
1189
1190	change_var = ((info->var.xres != var->xres) ||
1191		      (info->var.yres != var->yres) ||
1192		      (info->var.xres_virtual != var->xres_virtual) ||
1193		      (info->var.yres_virtual != var->yres_virtual) ||
1194		      (info->var.bits_per_pixel != var->bits_per_pixel) ||
1195		      memcmp(&info->var.red, &var->red, sizeof(var->red)) ||
1196		      memcmp(&info->var.green, &var->green,
1197			     sizeof(var->green)) ||
1198		      memcmp(&info->var.blue, &var->blue, sizeof(var->blue)));
1199
1200	if (FIXED_MODE(dinfo) &&
1201	    (change_var ||
1202	     var->yres_virtual > dinfo->initial_var.yres_virtual ||
1203	     var->yres_virtual < dinfo->initial_var.yres ||
1204	     var->xoffset || var->nonstd)) {
1205		if (first) {
1206			ERR_MSG("Changing the video mode is not supported.\n");
1207			first = 0;
1208		}
1209		return -EINVAL;
1210	}
1211
1212	switch (intelfb_var_to_depth(&v)) {
1213	case 8:
1214		v.red.offset = v.green.offset = v.blue.offset = 0;
1215		v.red.length = v.green.length = v.blue.length = 8;
1216		v.transp.offset = v.transp.length = 0;
1217		break;
1218	case 15:
1219		v.red.offset = 10;
1220		v.green.offset = 5;
1221		v.blue.offset = 0;
1222		v.red.length = v.green.length = v.blue.length = 5;
1223		v.transp.offset = v.transp.length = 0;
1224		break;
1225	case 16:
1226		v.red.offset = 11;
1227		v.green.offset = 5;
1228		v.blue.offset = 0;
1229		v.red.length = 5;
1230		v.green.length = 6;
1231		v.blue.length = 5;
1232		v.transp.offset = v.transp.length = 0;
1233		break;
1234	case 24:
1235		v.red.offset = 16;
1236		v.green.offset = 8;
1237		v.blue.offset = 0;
1238		v.red.length = v.green.length = v.blue.length = 8;
1239		v.transp.offset = v.transp.length = 0;
1240		break;
1241	case 32:
1242		v.red.offset = 16;
1243		v.green.offset = 8;
1244		v.blue.offset = 0;
1245		v.red.length = v.green.length = v.blue.length = 8;
1246		v.transp.offset = 24;
1247		v.transp.length = 8;
1248		break;
1249	}
1250
1251	if (v.xoffset < 0)
1252		v.xoffset = 0;
1253	if (v.yoffset < 0)
1254		v.yoffset = 0;
1255
1256	if (v.xoffset > v.xres_virtual - v.xres)
1257		v.xoffset = v.xres_virtual - v.xres;
1258	if (v.yoffset > v.yres_virtual - v.yres)
1259		v.yoffset = v.yres_virtual - v.yres;
1260
1261	v.red.msb_right = v.green.msb_right = v.blue.msb_right =
1262			  v.transp.msb_right = 0;
1263
1264        *var = v;
1265
1266	return 0;
1267}
1268
1269static int intelfb_set_par(struct fb_info *info)
1270{
1271	struct intelfb_hwstate *hw;
1272        struct intelfb_info *dinfo = GET_DINFO(info);
1273
1274	if (FIXED_MODE(dinfo)) {
1275		ERR_MSG("Changing the video mode is not supported.\n");
1276		return -EINVAL;
1277	}
1278
1279	hw = kmalloc(sizeof(*hw), GFP_ATOMIC);
1280	if (!hw)
1281		return -ENOMEM;
1282
1283	DBG_MSG("intelfb_set_par (%dx%d-%d)\n", info->var.xres,
1284		info->var.yres, info->var.bits_per_pixel);
1285
1286	/*
1287	 * Disable VCO prior to timing register change.
1288	 */
1289	OUTREG(DPLL_A, INREG(DPLL_A) & ~DPLL_VCO_ENABLE);
1290
1291	intelfb_blank(FB_BLANK_POWERDOWN, info);
1292
1293	if (ACCEL(dinfo, info))
1294		intelfbhw_2d_stop(dinfo);
1295
1296	memcpy(hw, &dinfo->save_state, sizeof(*hw));
1297	if (intelfbhw_mode_to_hw(dinfo, hw, &info->var))
1298		goto invalid_mode;
1299	if (intelfbhw_program_mode(dinfo, hw, 0))
1300		goto invalid_mode;
1301
1302#if REGDUMP > 0
1303	intelfbhw_read_hw_state(dinfo, hw, 0);
1304	intelfbhw_print_hw_state(dinfo, hw);
1305#endif
1306
1307	update_dinfo(dinfo, &info->var);
1308
1309	if (ACCEL(dinfo, info))
1310		intelfbhw_2d_start(dinfo);
1311
1312	intelfb_pan_display(&info->var, info);
1313
1314	intelfb_blank(FB_BLANK_UNBLANK, info);
1315
1316	if (ACCEL(dinfo, info)) {
1317		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
1318		FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
1319		FBINFO_HWACCEL_IMAGEBLIT;
1320	} else
1321		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1322
1323	kfree(hw);
1324	return 0;
1325invalid_mode:
1326	kfree(hw);
1327	return -EINVAL;
1328}
1329
1330static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1331			     unsigned blue, unsigned transp,
1332			     struct fb_info *info)
1333{
1334	struct intelfb_info *dinfo = GET_DINFO(info);
1335
1336#if VERBOSE > 0
1337	DBG_MSG("intelfb_setcolreg: regno %d, depth %d\n", regno, dinfo->depth);
1338#endif
1339
1340	if (regno > 255)
1341		return 1;
1342
1343	if (dinfo->depth == 8) {
1344		red >>= 8;
1345		green >>= 8;
1346		blue >>= 8;
1347
1348		intelfbhw_setcolreg(dinfo, regno, red, green, blue,
1349				    transp);
1350	}
1351
1352	if (regno < 16) {
1353		switch (dinfo->depth) {
1354		case 15:
1355			dinfo->pseudo_palette[regno] = ((red & 0xf800) >>  1) |
1356				((green & 0xf800) >>  6) |
1357				((blue & 0xf800) >> 11);
1358			break;
1359		case 16:
1360			dinfo->pseudo_palette[regno] = (red & 0xf800) |
1361				((green & 0xfc00) >>  5) |
1362				((blue  & 0xf800) >> 11);
1363			break;
1364		case 24:
1365			dinfo->pseudo_palette[regno] = ((red & 0xff00) << 8) |
1366				(green & 0xff00) |
1367				((blue  & 0xff00) >> 8);
1368			break;
1369		}
1370	}
1371
1372	return 0;
1373}
1374
1375static int intelfb_blank(int blank, struct fb_info *info)
1376{
1377	intelfbhw_do_blank(blank, info);
1378	return 0;
1379}
1380
1381static int intelfb_pan_display(struct fb_var_screeninfo *var,
1382			       struct fb_info *info)
1383{
1384	intelfbhw_pan_display(var, info);
1385	return 0;
1386}
1387
1388/* When/if we have our own ioctls. */
1389static int intelfb_ioctl(struct fb_info *info, unsigned int cmd,
1390			 unsigned long arg)
1391{
1392	int retval = 0;
1393	struct intelfb_info *dinfo = GET_DINFO(info);
1394	u32 pipe = 0;
1395
1396	switch (cmd) {
1397		case FBIO_WAITFORVSYNC:
1398			if (get_user(pipe, (__u32 __user *)arg))
1399				return -EFAULT;
1400
1401			retval = intelfbhw_wait_for_vsync(dinfo, pipe);
1402			break;
1403		default:
1404			break;
1405	}
1406
1407	return retval;
1408}
1409
1410static void intelfb_fillrect (struct fb_info *info,
1411			      const struct fb_fillrect *rect)
1412{
1413        struct intelfb_info *dinfo = GET_DINFO(info);
1414	u32 rop, color;
1415
1416#if VERBOSE > 0
1417	DBG_MSG("intelfb_fillrect\n");
1418#endif
1419
1420	if (!ACCEL(dinfo, info) || dinfo->depth == 4) {
1421		cfb_fillrect(info, rect);
1422		return;
1423	}
1424
1425	if (rect->rop == ROP_COPY)
1426		rop = PAT_ROP_GXCOPY;
1427	else /* ROP_XOR */
1428		rop = PAT_ROP_GXXOR;
1429
1430	if (dinfo->depth != 8)
1431		color = dinfo->pseudo_palette[rect->color];
1432	else
1433		color = rect->color;
1434
1435	intelfbhw_do_fillrect(dinfo, rect->dx, rect->dy,
1436			      rect->width, rect->height, color,
1437			      dinfo->pitch, info->var.bits_per_pixel,
1438			      rop);
1439}
1440
1441static void intelfb_copyarea(struct fb_info *info,
1442			     const struct fb_copyarea *region)
1443{
1444        struct intelfb_info *dinfo = GET_DINFO(info);
1445
1446#if VERBOSE > 0
1447	DBG_MSG("intelfb_copyarea\n");
1448#endif
1449
1450	if (!ACCEL(dinfo, info) || dinfo->depth == 4) {
1451		cfb_copyarea(info, region);
1452		return;
1453	}
1454
1455	intelfbhw_do_bitblt(dinfo, region->sx, region->sy, region->dx,
1456			    region->dy, region->width, region->height,
1457			    dinfo->pitch, info->var.bits_per_pixel);
1458}
1459
1460static void intelfb_imageblit(struct fb_info *info,
1461			      const struct fb_image *image)
1462{
1463        struct intelfb_info *dinfo = GET_DINFO(info);
1464	u32 fgcolor, bgcolor;
1465
1466#if VERBOSE > 0
1467	DBG_MSG("intelfb_imageblit\n");
1468#endif
1469
1470	if (!ACCEL(dinfo, info) || dinfo->depth == 4
1471	    || image->depth != 1) {
1472		cfb_imageblit(info, image);
1473		return;
1474	}
1475
1476	if (dinfo->depth != 8) {
1477		fgcolor = dinfo->pseudo_palette[image->fg_color];
1478		bgcolor = dinfo->pseudo_palette[image->bg_color];
1479	} else {
1480		fgcolor = image->fg_color;
1481		bgcolor = image->bg_color;
1482	}
1483
1484	if (!intelfbhw_do_drawglyph(dinfo, fgcolor, bgcolor, image->width,
1485				    image->height, image->data,
1486				    image->dx, image->dy,
1487				    dinfo->pitch, info->var.bits_per_pixel)) {
1488		cfb_imageblit(info, image);
1489		return;
1490	}
1491}
1492
1493static int intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1494{
1495        struct intelfb_info *dinfo = GET_DINFO(info);
1496	u32 physical;
1497#if VERBOSE > 0
1498	DBG_MSG("intelfb_cursor\n");
1499#endif
1500
1501	if (!dinfo->hwcursor)
1502		return -ENODEV;
1503
1504	intelfbhw_cursor_hide(dinfo);
1505
1506	/* If XFree killed the cursor - restore it */
1507	physical = (dinfo->mobile || IS_I9XX(dinfo)) ? dinfo->cursor.physical :
1508		   (dinfo->cursor.offset << 12);
1509
1510	if (INREG(CURSOR_A_BASEADDR) != physical) {
1511		u32 fg, bg;
1512
1513		DBG_MSG("the cursor was killed - restore it !!\n");
1514		DBG_MSG("size %d, %d   pos %d, %d\n",
1515			cursor->image.width, cursor->image.height,
1516			cursor->image.dx, cursor->image.dy);
1517
1518		intelfbhw_cursor_init(dinfo);
1519		intelfbhw_cursor_reset(dinfo);
1520		intelfbhw_cursor_setpos(dinfo, cursor->image.dx,
1521					cursor->image.dy);
1522
1523		if (dinfo->depth != 8) {
1524			fg =dinfo->pseudo_palette[cursor->image.fg_color];
1525			bg =dinfo->pseudo_palette[cursor->image.bg_color];
1526		} else {
1527			fg = cursor->image.fg_color;
1528			bg = cursor->image.bg_color;
1529		}
1530		intelfbhw_cursor_setcolor(dinfo, bg, fg);
1531		intelfbhw_cursor_load(dinfo, cursor->image.width,
1532				      cursor->image.height,
1533				      dinfo->cursor_src);
1534
1535		if (cursor->enable)
1536			intelfbhw_cursor_show(dinfo);
1537		return 0;
1538	}
1539
1540	if (cursor->set & FB_CUR_SETPOS) {
1541		u32 dx, dy;
1542
1543		dx = cursor->image.dx - info->var.xoffset;
1544		dy = cursor->image.dy - info->var.yoffset;
1545
1546		intelfbhw_cursor_setpos(dinfo, dx, dy);
1547	}
1548
1549	if (cursor->set & FB_CUR_SETSIZE) {
1550		if (cursor->image.width > 64 || cursor->image.height > 64)
1551			return -ENXIO;
1552
1553		intelfbhw_cursor_reset(dinfo);
1554	}
1555
1556	if (cursor->set & FB_CUR_SETCMAP) {
1557		u32 fg, bg;
1558
1559		if (dinfo->depth != 8) {
1560			fg = dinfo->pseudo_palette[cursor->image.fg_color];
1561			bg = dinfo->pseudo_palette[cursor->image.bg_color];
1562		} else {
1563			fg = cursor->image.fg_color;
1564			bg = cursor->image.bg_color;
1565		}
1566
1567		intelfbhw_cursor_setcolor(dinfo, bg, fg);
1568	}
1569
1570	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
1571		u32 s_pitch = (ROUND_UP_TO(cursor->image.width, 8) / 8);
1572		u32 size = s_pitch * cursor->image.height;
1573		u8 *dat = (u8 *) cursor->image.data;
1574		u8 *msk = (u8 *) cursor->mask;
1575		u8 src[64];
1576		u32 i;
1577
1578		if (cursor->image.depth != 1)
1579			return -ENXIO;
1580
1581		switch (cursor->rop) {
1582		case ROP_XOR:
1583			for (i = 0; i < size; i++)
1584				src[i] = dat[i] ^ msk[i];
1585			break;
1586		case ROP_COPY:
1587		default:
1588			for (i = 0; i < size; i++)
1589				src[i] = dat[i] & msk[i];
1590			break;
1591		}
1592
1593		/* save the bitmap to restore it when XFree will
1594		   make the cursor dirty */
1595		memcpy(dinfo->cursor_src, src, size);
1596
1597		intelfbhw_cursor_load(dinfo, cursor->image.width,
1598				      cursor->image.height, src);
1599	}
1600
1601	if (cursor->enable)
1602		intelfbhw_cursor_show(dinfo);
1603
1604	return 0;
1605}
1606
1607static int intelfb_sync(struct fb_info *info)
1608{
1609        struct intelfb_info *dinfo = GET_DINFO(info);
1610
1611#if VERBOSE > 0
1612	DBG_MSG("intelfb_sync\n");
1613#endif
1614
1615	if (dinfo->ring_lockup)
1616		return 0;
1617
1618	intelfbhw_do_sync(dinfo);
1619	return 0;
1620}
1621