Linux Audio

Check our new training course

Loading...
   1/*
   2 * i740fb - framebuffer driver for Intel740
   3 * Copyright (c) 2011 Ondrej Zary
   4 *
   5 * Based on old i740fb driver (c) 2001-2002 Andrey Ulanov <drey@rt.mipt.ru>
   6 * which was partially based on:
   7 *  VGA 16-color framebuffer driver (c) 1999 Ben Pfaff <pfaffben@debian.org>
   8 *	and Petr Vandrovec <VANDROVE@vc.cvut.cz>
   9 *  i740 driver from XFree86 (c) 1998-1999 Precision Insight, Inc., Cedar Park,
  10 *	Texas.
  11 *  i740fb by Patrick LERDA, v0.9
  12 */
  13
  14#include <linux/module.h>
  15#include <linux/kernel.h>
  16#include <linux/errno.h>
  17#include <linux/string.h>
  18#include <linux/mm.h>
  19#include <linux/slab.h>
  20#include <linux/delay.h>
  21#include <linux/fb.h>
  22#include <linux/init.h>
  23#include <linux/pci.h>
  24#include <linux/pci_ids.h>
  25#include <linux/i2c.h>
  26#include <linux/i2c-algo-bit.h>
  27#include <linux/console.h>
  28#include <video/vga.h>
  29
  30#ifdef CONFIG_MTRR
  31#include <asm/mtrr.h>
  32#endif
  33
  34#include "i740_reg.h"
  35
  36static char *mode_option __devinitdata;
  37
  38#ifdef CONFIG_MTRR
  39static int mtrr __devinitdata = 1;
  40#endif
  41
  42struct i740fb_par {
  43	unsigned char __iomem *regs;
  44	bool has_sgram;
  45#ifdef CONFIG_MTRR
  46	int mtrr_reg;
  47#endif
  48	bool ddc_registered;
  49	struct i2c_adapter ddc_adapter;
  50	struct i2c_algo_bit_data ddc_algo;
  51	u32 pseudo_palette[16];
  52	struct mutex open_lock;
  53	unsigned int ref_count;
  54
  55	u8 crtc[VGA_CRT_C];
  56	u8 atc[VGA_ATT_C];
  57	u8 gdc[VGA_GFX_C];
  58	u8 seq[VGA_SEQ_C];
  59	u8 misc;
  60	u8 vss;
  61
  62	/* i740 specific registers */
  63	u8 display_cntl;
  64	u8 pixelpipe_cfg0;
  65	u8 pixelpipe_cfg1;
  66	u8 pixelpipe_cfg2;
  67	u8 video_clk2_m;
  68	u8 video_clk2_n;
  69	u8 video_clk2_mn_msbs;
  70	u8 video_clk2_div_sel;
  71	u8 pll_cntl;
  72	u8 address_mapping;
  73	u8 io_cntl;
  74	u8 bitblt_cntl;
  75	u8 ext_vert_total;
  76	u8 ext_vert_disp_end;
  77	u8 ext_vert_sync_start;
  78	u8 ext_vert_blank_start;
  79	u8 ext_horiz_total;
  80	u8 ext_horiz_blank;
  81	u8 ext_offset;
  82	u8 interlace_cntl;
  83	u32 lmi_fifo_watermark;
  84	u8 ext_start_addr;
  85	u8 ext_start_addr_hi;
  86};
  87
  88#define DACSPEED8	203
  89#define DACSPEED16	163
  90#define DACSPEED24_SG	136
  91#define DACSPEED24_SD	128
  92#define DACSPEED32	86
  93
  94static struct fb_fix_screeninfo i740fb_fix __devinitdata = {
  95	.id =		"i740fb",
  96	.type =		FB_TYPE_PACKED_PIXELS,
  97	.visual =	FB_VISUAL_TRUECOLOR,
  98	.xpanstep =	8,
  99	.ypanstep =	1,
 100	.accel =	FB_ACCEL_NONE,
 101};
 102
 103static inline void i740outb(struct i740fb_par *par, u16 port, u8 val)
 104{
 105	vga_mm_w(par->regs, port, val);
 106}
 107static inline u8 i740inb(struct i740fb_par *par, u16 port)
 108{
 109	return vga_mm_r(par->regs, port);
 110}
 111static inline void i740outreg(struct i740fb_par *par, u16 port, u8 reg, u8 val)
 112{
 113	vga_mm_w_fast(par->regs, port, reg, val);
 114}
 115static inline u8 i740inreg(struct i740fb_par *par, u16 port, u8 reg)
 116{
 117	vga_mm_w(par->regs, port, reg);
 118	return vga_mm_r(par->regs, port+1);
 119}
 120static inline void i740outreg_mask(struct i740fb_par *par, u16 port, u8 reg,
 121				   u8 val, u8 mask)
 122{
 123	vga_mm_w_fast(par->regs, port, reg, (val & mask)
 124		| (i740inreg(par, port, reg) & ~mask));
 125}
 126
 127#define REG_DDC_DRIVE	0x62
 128#define REG_DDC_STATE	0x63
 129#define DDC_SCL		(1 << 3)
 130#define DDC_SDA		(1 << 2)
 131
 132static void i740fb_ddc_setscl(void *data, int val)
 133{
 134	struct i740fb_par *par = data;
 135
 136	i740outreg_mask(par, XRX, REG_DDC_DRIVE, DDC_SCL, DDC_SCL);
 137	i740outreg_mask(par, XRX, REG_DDC_STATE, val ? DDC_SCL : 0, DDC_SCL);
 138}
 139
 140static void i740fb_ddc_setsda(void *data, int val)
 141{
 142	struct i740fb_par *par = data;
 143
 144	i740outreg_mask(par, XRX, REG_DDC_DRIVE, DDC_SDA, DDC_SDA);
 145	i740outreg_mask(par, XRX, REG_DDC_STATE, val ? DDC_SDA : 0, DDC_SDA);
 146}
 147
 148static int i740fb_ddc_getscl(void *data)
 149{
 150	struct i740fb_par *par = data;
 151
 152	i740outreg_mask(par, XRX, REG_DDC_DRIVE, 0, DDC_SCL);
 153
 154	return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SCL);
 155}
 156
 157static int i740fb_ddc_getsda(void *data)
 158{
 159	struct i740fb_par *par = data;
 160
 161	i740outreg_mask(par, XRX, REG_DDC_DRIVE, 0, DDC_SDA);
 162
 163	return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SDA);
 164}
 165
 166static int __devinit i740fb_setup_ddc_bus(struct fb_info *info)
 167{
 168	struct i740fb_par *par = info->par;
 169
 170	strlcpy(par->ddc_adapter.name, info->fix.id,
 171		sizeof(par->ddc_adapter.name));
 172	par->ddc_adapter.owner		= THIS_MODULE;
 173	par->ddc_adapter.class		= I2C_CLASS_DDC;
 174	par->ddc_adapter.algo_data	= &par->ddc_algo;
 175	par->ddc_adapter.dev.parent	= info->device;
 176	par->ddc_algo.setsda		= i740fb_ddc_setsda;
 177	par->ddc_algo.setscl		= i740fb_ddc_setscl;
 178	par->ddc_algo.getsda		= i740fb_ddc_getsda;
 179	par->ddc_algo.getscl		= i740fb_ddc_getscl;
 180	par->ddc_algo.udelay		= 10;
 181	par->ddc_algo.timeout		= 20;
 182	par->ddc_algo.data		= par;
 183
 184	i2c_set_adapdata(&par->ddc_adapter, par);
 185
 186	return i2c_bit_add_bus(&par->ddc_adapter);
 187}
 188
 189static int i740fb_open(struct fb_info *info, int user)
 190{
 191	struct i740fb_par *par = info->par;
 192
 193	mutex_lock(&(par->open_lock));
 194	par->ref_count++;
 195	mutex_unlock(&(par->open_lock));
 196
 197	return 0;
 198}
 199
 200static int i740fb_release(struct fb_info *info, int user)
 201{
 202	struct i740fb_par *par = info->par;
 203
 204	mutex_lock(&(par->open_lock));
 205	if (par->ref_count == 0) {
 206		printk(KERN_ERR "fb%d: release called with zero refcount\n",
 207			info->node);
 208		mutex_unlock(&(par->open_lock));
 209		return -EINVAL;
 210	}
 211
 212	par->ref_count--;
 213	mutex_unlock(&(par->open_lock));
 214
 215	return 0;
 216}
 217
 218static u32 i740_calc_fifo(struct i740fb_par *par, u32 freq, int bpp)
 219{
 220	/*
 221	 * Would like to calculate these values automatically, but a generic
 222	 * algorithm does not seem possible.  Note: These FIFO water mark
 223	 * values were tested on several cards and seem to eliminate the
 224	 * all of the snow and vertical banding, but fine adjustments will
 225	 * probably be required for other cards.
 226	 */
 227
 228	u32 wm;
 229
 230	switch (bpp) {
 231	case 8:
 232		if	(freq > 200)
 233			wm = 0x18120000;
 234		else if (freq > 175)
 235			wm = 0x16110000;
 236		else if (freq > 135)
 237			wm = 0x120E0000;
 238		else
 239			wm = 0x100D0000;
 240		break;
 241	case 15:
 242	case 16:
 243		if (par->has_sgram) {
 244			if	(freq > 140)
 245				wm = 0x2C1D0000;
 246			else if (freq > 120)
 247				wm = 0x2C180000;
 248			else if (freq > 100)
 249				wm = 0x24160000;
 250			else if (freq >  90)
 251				wm = 0x18120000;
 252			else if (freq >  50)
 253				wm = 0x16110000;
 254			else if (freq >  32)
 255				wm = 0x13100000;
 256			else
 257				wm = 0x120E0000;
 258		} else {
 259			if	(freq > 160)
 260				wm = 0x28200000;
 261			else if (freq > 140)
 262				wm = 0x2A1E0000;
 263			else if (freq > 130)
 264				wm = 0x2B1A0000;
 265			else if (freq > 120)
 266				wm = 0x2C180000;
 267			else if (freq > 100)
 268				wm = 0x24180000;
 269			else if (freq >  90)
 270				wm = 0x18120000;
 271			else if (freq >  50)
 272				wm = 0x16110000;
 273			else if (freq >  32)
 274				wm = 0x13100000;
 275			else
 276				wm = 0x120E0000;
 277		}
 278		break;
 279	case 24:
 280		if (par->has_sgram) {
 281			if	(freq > 130)
 282				wm = 0x31200000;
 283			else if (freq > 120)
 284				wm = 0x2E200000;
 285			else if (freq > 100)
 286				wm = 0x2C1D0000;
 287			else if (freq >  80)
 288				wm = 0x25180000;
 289			else if (freq >  64)
 290				wm = 0x24160000;
 291			else if (freq >  49)
 292				wm = 0x18120000;
 293			else if (freq >  32)
 294				wm = 0x16110000;
 295			else
 296				wm = 0x13100000;
 297		} else {
 298			if	(freq > 120)
 299				wm = 0x311F0000;
 300			else if (freq > 100)
 301				wm = 0x2C1D0000;
 302			else if (freq >  80)
 303				wm = 0x25180000;
 304			else if (freq >  64)
 305				wm = 0x24160000;
 306			else if (freq >  49)
 307				wm = 0x18120000;
 308			else if (freq >  32)
 309				wm = 0x16110000;
 310			else
 311				wm = 0x13100000;
 312		}
 313		break;
 314	case 32:
 315		if (par->has_sgram) {
 316			if	(freq >  80)
 317				wm = 0x2A200000;
 318			else if (freq >  60)
 319				wm = 0x281A0000;
 320			else if (freq >  49)
 321				wm = 0x25180000;
 322			else if (freq >  32)
 323				wm = 0x18120000;
 324			else
 325				wm = 0x16110000;
 326		} else {
 327			if	(freq >  80)
 328				wm = 0x29200000;
 329			else if (freq >  60)
 330				wm = 0x281A0000;
 331			else if (freq >  49)
 332				wm = 0x25180000;
 333			else if (freq >  32)
 334				wm = 0x18120000;
 335			else
 336				wm = 0x16110000;
 337		}
 338		break;
 339	}
 340
 341	return wm;
 342}
 343
 344/* clock calculation from i740fb by Patrick LERDA */
 345
 346#define I740_RFREQ		1000000
 347#define TARGET_MAX_N		30
 348#define I740_FFIX		(1 << 8)
 349#define I740_RFREQ_FIX		(I740_RFREQ / I740_FFIX)
 350#define I740_REF_FREQ		(6667 * I740_FFIX / 100)	/* 66.67 MHz */
 351#define I740_MAX_VCO_FREQ	(450 * I740_FFIX)		/* 450 MHz */
 352
 353static void i740_calc_vclk(u32 freq, struct i740fb_par *par)
 354{
 355	const u32 err_max    = freq / (200  * I740_RFREQ / I740_FFIX);
 356	const u32 err_target = freq / (1000 * I740_RFREQ / I740_FFIX);
 357	u32 err_best = 512 * I740_FFIX;
 358	u32 f_err, f_vco;
 359	int m_best = 0, n_best = 0, p_best = 0, d_best = 0;
 360	int m, n;
 361
 362	p_best = min(15, ilog2(I740_MAX_VCO_FREQ / (freq / I740_RFREQ_FIX)));
 363	d_best = 0;
 364	f_vco = (freq * (1 << p_best)) / I740_RFREQ_FIX;
 365	freq = freq / I740_RFREQ_FIX;
 366
 367	n = 2;
 368	do {
 369		n++;
 370		m = ((f_vco * n) / I740_REF_FREQ + 2) / 4;
 371
 372		if (m < 3)
 373			m = 3;
 374
 375		{
 376			u32 f_out = (((m * I740_REF_FREQ * (4 << 2 * d_best))
 377				 / n) + ((1 << p_best) / 2)) / (1 << p_best);
 378
 379			f_err = (freq - f_out);
 380
 381			if (abs(f_err) < err_max) {
 382				m_best = m;
 383				n_best = n;
 384				err_best = f_err;
 385			}
 386		}
 387	} while ((abs(f_err) >= err_target) &&
 388		 ((n <= TARGET_MAX_N) || (abs(err_best) > err_max)));
 389
 390	if (abs(f_err) < err_target) {
 391		m_best = m;
 392		n_best = n;
 393	}
 394
 395	par->video_clk2_m = (m_best - 2) & 0xFF;
 396	par->video_clk2_n = (n_best - 2) & 0xFF;
 397	par->video_clk2_mn_msbs = ((((n_best - 2) >> 4) & VCO_N_MSBS)
 398				 | (((m_best - 2) >> 8) & VCO_M_MSBS));
 399	par->video_clk2_div_sel =
 400		((p_best << 4) | (d_best ? 4 : 0) | REF_DIV_1);
 401}
 402
 403static int i740fb_decode_var(const struct fb_var_screeninfo *var,
 404			     struct i740fb_par *par, struct fb_info *info)
 405{
 406	/*
 407	 * Get the video params out of 'var'.
 408	 * If a value doesn't fit, round it up, if it's too big, return -EINVAL.
 409	 */
 410
 411	u32 xres, right, hslen, left, xtotal;
 412	u32 yres, lower, vslen, upper, ytotal;
 413	u32 vxres, xoffset, vyres, yoffset;
 414	u32 bpp, base, dacspeed24, mem;
 415	u8 r7;
 416	int i;
 417
 418	dev_dbg(info->device, "decode_var: xres: %i, yres: %i, xres_v: %i, xres_v: %i\n",
 419		  var->xres, var->yres, var->xres_virtual, var->xres_virtual);
 420	dev_dbg(info->device, "	xoff: %i, yoff: %i, bpp: %i, graysc: %i\n",
 421		  var->xoffset, var->yoffset, var->bits_per_pixel,
 422		  var->grayscale);
 423	dev_dbg(info->device, "	activate: %i, nonstd: %i, vmode: %i\n",
 424		  var->activate, var->nonstd, var->vmode);
 425	dev_dbg(info->device, "	pixclock: %i, hsynclen:%i, vsynclen:%i\n",
 426		  var->pixclock, var->hsync_len, var->vsync_len);
 427	dev_dbg(info->device, "	left: %i, right: %i, up:%i, lower:%i\n",
 428		  var->left_margin, var->right_margin, var->upper_margin,
 429		  var->lower_margin);
 430
 431
 432	bpp = var->bits_per_pixel;
 433	switch (bpp) {
 434	case 1 ... 8:
 435		bpp = 8;
 436		if ((1000000 / var->pixclock) > DACSPEED8) {
 437			dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 8bpp)\n",
 438				1000000 / var->pixclock, DACSPEED8);
 439			return -EINVAL;
 440		}
 441		break;
 442	case 9 ... 15:
 443		bpp = 15;
 444	case 16:
 445		if ((1000000 / var->pixclock) > DACSPEED16) {
 446			dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 15/16bpp)\n",
 447				1000000 / var->pixclock, DACSPEED16);
 448			return -EINVAL;
 449		}
 450		break;
 451	case 17 ... 24:
 452		bpp = 24;
 453		dacspeed24 = par->has_sgram ? DACSPEED24_SG : DACSPEED24_SD;
 454		if ((1000000 / var->pixclock) > dacspeed24) {
 455			dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 24bpp)\n",
 456				1000000 / var->pixclock, dacspeed24);
 457			return -EINVAL;
 458		}
 459		break;
 460	case 25 ... 32:
 461		bpp = 32;
 462		if ((1000000 / var->pixclock) > DACSPEED32) {
 463			dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 32bpp)\n",
 464				1000000 / var->pixclock, DACSPEED32);
 465			return -EINVAL;
 466		}
 467		break;
 468	default:
 469		return -EINVAL;
 470	}
 471
 472	xres = ALIGN(var->xres, 8);
 473	vxres = ALIGN(var->xres_virtual, 16);
 474	if (vxres < xres)
 475		vxres = xres;
 476
 477	xoffset = ALIGN(var->xoffset, 8);
 478	if (xres + xoffset > vxres)
 479		xoffset = vxres - xres;
 480
 481	left = ALIGN(var->left_margin, 8);
 482	right = ALIGN(var->right_margin, 8);
 483	hslen = ALIGN(var->hsync_len, 8);
 484
 485	yres = var->yres;
 486	vyres = var->yres_virtual;
 487	if (yres > vyres)
 488		vyres = yres;
 489
 490	yoffset = var->yoffset;
 491	if (yres + yoffset > vyres)
 492		yoffset = vyres - yres;
 493
 494	lower = var->lower_margin;
 495	vslen = var->vsync_len;
 496	upper = var->upper_margin;
 497
 498	mem = vxres * vyres * ((bpp + 1) / 8);
 499	if (mem > info->screen_size) {
 500		dev_err(info->device, "not enough video memory (%d KB requested, %ld KB avaliable)\n",
 501			mem >> 10, info->screen_size >> 10);
 502		return -ENOMEM;
 503	}
 504
 505	if (yoffset + yres > vyres)
 506		yoffset = vyres - yres;
 507
 508	xtotal = xres + right + hslen + left;
 509	ytotal = yres + lower + vslen + upper;
 510
 511	par->crtc[VGA_CRTC_H_TOTAL] = (xtotal >> 3) - 5;
 512	par->crtc[VGA_CRTC_H_DISP] = (xres >> 3) - 1;
 513	par->crtc[VGA_CRTC_H_BLANK_START] = ((xres + right) >> 3) - 1;
 514	par->crtc[VGA_CRTC_H_SYNC_START] = (xres + right) >> 3;
 515	par->crtc[VGA_CRTC_H_SYNC_END] = (((xres + right + hslen) >> 3) & 0x1F)
 516		| ((((xres + right + hslen) >> 3) & 0x20) << 2);
 517	par->crtc[VGA_CRTC_H_BLANK_END] = ((xres + right + hslen) >> 3 & 0x1F)
 518		| 0x80;
 519
 520	par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2;
 521
 522	r7 = 0x10;	/* disable linecompare */
 523	if (ytotal & 0x100)
 524		r7 |= 0x01;
 525	if (ytotal & 0x200)
 526		r7 |= 0x20;
 527
 528	par->crtc[VGA_CRTC_PRESET_ROW] = 0;
 529	par->crtc[VGA_CRTC_MAX_SCAN] = 0x40;	/* 1 scanline, no linecmp */
 530	if (var->vmode & FB_VMODE_DOUBLE)
 531		par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80;
 532	par->crtc[VGA_CRTC_CURSOR_START] = 0x00;
 533	par->crtc[VGA_CRTC_CURSOR_END] = 0x00;
 534	par->crtc[VGA_CRTC_CURSOR_HI] = 0x00;
 535	par->crtc[VGA_CRTC_CURSOR_LO] = 0x00;
 536	par->crtc[VGA_CRTC_V_DISP_END] = yres-1;
 537	if ((yres-1) & 0x100)
 538		r7 |= 0x02;
 539	if ((yres-1) & 0x200)
 540		r7 |= 0x40;
 541
 542	par->crtc[VGA_CRTC_V_BLANK_START] = yres + lower - 1;
 543	par->crtc[VGA_CRTC_V_SYNC_START] = yres + lower - 1;
 544	if ((yres + lower - 1) & 0x100)
 545		r7 |= 0x0C;
 546	if ((yres + lower - 1) & 0x200) {
 547		par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20;
 548		r7 |= 0x80;
 549	}
 550
 551	/* disabled IRQ */
 552	par->crtc[VGA_CRTC_V_SYNC_END] =
 553		((yres + lower - 1 + vslen) & 0x0F) & ~0x10;
 554	/* 0x7F for VGA, but some SVGA chips require all 8 bits to be set */
 555	par->crtc[VGA_CRTC_V_BLANK_END] = (yres + lower - 1 + vslen) & 0xFF;
 556
 557	par->crtc[VGA_CRTC_UNDERLINE] = 0x00;
 558	par->crtc[VGA_CRTC_MODE] = 0xC3 ;
 559	par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF;
 560	par->crtc[VGA_CRTC_OVERFLOW] = r7;
 561
 562	par->vss = 0x00;	/* 3DA */
 563
 564	for (i = 0x00; i < 0x10; i++)
 565		par->atc[i] = i;
 566	par->atc[VGA_ATC_MODE] = 0x81;
 567	par->atc[VGA_ATC_OVERSCAN] = 0x00;	/* 0 for EGA, 0xFF for VGA */
 568	par->atc[VGA_ATC_PLANE_ENABLE] = 0x0F;
 569	par->atc[VGA_ATC_COLOR_PAGE] = 0x00;
 570
 571	par->misc = 0xC3;
 572	if (var->sync & FB_SYNC_HOR_HIGH_ACT)
 573		par->misc &= ~0x40;
 574	if (var->sync & FB_SYNC_VERT_HIGH_ACT)
 575		par->misc &= ~0x80;
 576
 577	par->seq[VGA_SEQ_CLOCK_MODE] = 0x01;
 578	par->seq[VGA_SEQ_PLANE_WRITE] = 0x0F;
 579	par->seq[VGA_SEQ_CHARACTER_MAP] = 0x00;
 580	par->seq[VGA_SEQ_MEMORY_MODE] = 0x06;
 581
 582	par->gdc[VGA_GFX_SR_VALUE] = 0x00;
 583	par->gdc[VGA_GFX_SR_ENABLE] = 0x00;
 584	par->gdc[VGA_GFX_COMPARE_VALUE] = 0x00;
 585	par->gdc[VGA_GFX_DATA_ROTATE] = 0x00;
 586	par->gdc[VGA_GFX_PLANE_READ] = 0;
 587	par->gdc[VGA_GFX_MODE] = 0x02;
 588	par->gdc[VGA_GFX_MISC] = 0x05;
 589	par->gdc[VGA_GFX_COMPARE_MASK] = 0x0F;
 590	par->gdc[VGA_GFX_BIT_MASK] = 0xFF;
 591
 592	base = (yoffset * vxres + (xoffset & ~7)) >> 2;
 593	switch (bpp) {
 594	case 8:
 595		par->crtc[VGA_CRTC_OFFSET] = vxres >> 3;
 596		par->ext_offset = vxres >> 11;
 597		par->pixelpipe_cfg1 = DISPLAY_8BPP_MODE;
 598		par->bitblt_cntl = COLEXP_8BPP;
 599		break;
 600	case 15: /* 0rrrrrgg gggbbbbb */
 601	case 16: /* rrrrrggg gggbbbbb */
 602		par->pixelpipe_cfg1 = (var->green.length == 6) ?
 603			DISPLAY_16BPP_MODE : DISPLAY_15BPP_MODE;
 604		par->crtc[VGA_CRTC_OFFSET] = vxres >> 2;
 605		par->ext_offset = vxres >> 10;
 606		par->bitblt_cntl = COLEXP_16BPP;
 607		base *= 2;
 608		break;
 609	case 24:
 610		par->crtc[VGA_CRTC_OFFSET] = (vxres * 3) >> 3;
 611		par->ext_offset = (vxres * 3) >> 11;
 612		par->pixelpipe_cfg1 = DISPLAY_24BPP_MODE;
 613		par->bitblt_cntl = COLEXP_24BPP;
 614		base &= 0xFFFFFFFE; /* ...ignore the last bit. */
 615		base *= 3;
 616		break;
 617	case 32:
 618		par->crtc[VGA_CRTC_OFFSET] = vxres >> 1;
 619		par->ext_offset = vxres >> 9;
 620		par->pixelpipe_cfg1 = DISPLAY_32BPP_MODE;
 621		par->bitblt_cntl = COLEXP_RESERVED; /* Unimplemented on i740 */
 622		base *= 4;
 623		break;
 624	}
 625
 626	par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
 627	par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >>  8;
 628	par->ext_start_addr =
 629		((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
 630	par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
 631
 632	par->pixelpipe_cfg0 = DAC_8_BIT;
 633
 634	par->pixelpipe_cfg2 = DISPLAY_GAMMA_ENABLE | OVERLAY_GAMMA_ENABLE;
 635	par->io_cntl = EXTENDED_CRTC_CNTL;
 636	par->address_mapping = LINEAR_MODE_ENABLE | PAGE_MAPPING_ENABLE;
 637	par->display_cntl = HIRES_MODE;
 638
 639	/* Set the MCLK freq */
 640	par->pll_cntl = PLL_MEMCLK_100000KHZ; /* 100 MHz -- use as default */
 641
 642	/* Calculate the extended CRTC regs */
 643	par->ext_vert_total = (ytotal - 2) >> 8;
 644	par->ext_vert_disp_end = (yres - 1) >> 8;
 645	par->ext_vert_sync_start = (yres + lower) >> 8;
 646	par->ext_vert_blank_start = (yres + lower) >> 8;
 647	par->ext_horiz_total = ((xtotal >> 3) - 5) >> 8;
 648	par->ext_horiz_blank = (((xres + right) >> 3) & 0x40) >> 6;
 649
 650	par->interlace_cntl = INTERLACE_DISABLE;
 651
 652	/* Set the overscan color to 0. (NOTE: This only affects >8bpp mode) */
 653	par->atc[VGA_ATC_OVERSCAN] = 0;
 654
 655	/* Calculate VCLK that most closely matches the requested dot clock */
 656	i740_calc_vclk((((u32)1e9) / var->pixclock) * (u32)(1e3), par);
 657
 658	/* Since we program the clocks ourselves, always use VCLK2. */
 659	par->misc |= 0x0C;
 660
 661	/* Calculate the FIFO Watermark and Burst Length. */
 662	par->lmi_fifo_watermark =
 663		i740_calc_fifo(par, 1000000 / var->pixclock, bpp);
 664
 665	return 0;
 666}
 667
 668static int i740fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 669{
 670	switch (var->bits_per_pixel) {
 671	case 8:
 672		var->red.offset	= var->green.offset = var->blue.offset = 0;
 673		var->red.length	= var->green.length = var->blue.length = 8;
 674		break;
 675	case 16:
 676		switch (var->green.length) {
 677		default:
 678		case 5:
 679			var->red.offset = 10;
 680			var->green.offset = 5;
 681			var->blue.offset = 0;
 682			var->red.length	= 5;
 683			var->green.length = 5;
 684			var->blue.length = 5;
 685			break;
 686		case 6:
 687			var->red.offset = 11;
 688			var->green.offset = 5;
 689			var->blue.offset = 0;
 690			var->red.length = var->blue.length = 5;
 691			break;
 692		}
 693		break;
 694	case 24:
 695		var->red.offset = 16;
 696		var->green.offset = 8;
 697		var->blue.offset = 0;
 698		var->red.length	= var->green.length = var->blue.length = 8;
 699		break;
 700	case 32:
 701		var->transp.offset = 24;
 702		var->red.offset = 16;
 703		var->green.offset = 8;
 704		var->blue.offset = 0;
 705		var->transp.length = 8;
 706		var->red.length = var->green.length = var->blue.length = 8;
 707		break;
 708	default:
 709		return -EINVAL;
 710	}
 711
 712	if (var->xres > var->xres_virtual)
 713		var->xres_virtual = var->xres;
 714
 715	if (var->yres > var->yres_virtual)
 716		var->yres_virtual = var->yres;
 717
 718	if (info->monspecs.hfmax && info->monspecs.vfmax &&
 719	    info->monspecs.dclkmax && fb_validate_mode(var, info) < 0)
 720		return -EINVAL;
 721
 722	return 0;
 723}
 724
 725static void vga_protect(struct i740fb_par *par)
 726{
 727	/* disable the display */
 728	i740outreg_mask(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, 0x20, 0x20);
 729
 730	i740inb(par, 0x3DA);
 731	i740outb(par, VGA_ATT_W, 0x00);	/* enable pallete access */
 732}
 733
 734static void vga_unprotect(struct i740fb_par *par)
 735{
 736	/* reenable display */
 737	i740outreg_mask(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, 0, 0x20);
 738
 739	i740inb(par, 0x3DA);
 740	i740outb(par, VGA_ATT_W, 0x20);	/* disable pallete access */
 741}
 742
 743static int i740fb_set_par(struct fb_info *info)
 744{
 745	struct i740fb_par *par = info->par;
 746	u32 itemp;
 747	int i;
 748
 749	i = i740fb_decode_var(&info->var, par, info);
 750	if (i)
 751		return i;
 752
 753	memset(info->screen_base, 0, info->screen_size);
 754
 755	vga_protect(par);
 756
 757	i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_DISABLE);
 758
 759	mdelay(1);
 760
 761	i740outreg(par, XRX, VCLK2_VCO_M, par->video_clk2_m);
 762	i740outreg(par, XRX, VCLK2_VCO_N, par->video_clk2_n);
 763	i740outreg(par, XRX, VCLK2_VCO_MN_MSBS, par->video_clk2_mn_msbs);
 764	i740outreg(par, XRX, VCLK2_VCO_DIV_SEL, par->video_clk2_div_sel);
 765
 766	i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0,
 767			par->pixelpipe_cfg0 & DAC_8_BIT, 0x80);
 768
 769	i740inb(par, 0x3DA);
 770	i740outb(par, 0x3C0, 0x00);
 771
 772	/* update misc output register */
 773	i740outb(par, VGA_MIS_W, par->misc | 0x01);
 774
 775	/* synchronous reset on */
 776	i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x01);
 777	/* write sequencer registers */
 778	i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE,
 779			par->seq[VGA_SEQ_CLOCK_MODE] | 0x20);
 780	for (i = 2; i < VGA_SEQ_C; i++)
 781		i740outreg(par, VGA_SEQ_I, i, par->seq[i]);
 782
 783	/* synchronous reset off */
 784	i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x03);
 785
 786	/* deprotect CRT registers 0-7 */
 787	i740outreg(par, VGA_CRT_IC, VGA_CRTC_V_SYNC_END,
 788			par->crtc[VGA_CRTC_V_SYNC_END]);
 789
 790	/* write CRT registers */
 791	for (i = 0; i < VGA_CRT_C; i++)
 792		i740outreg(par, VGA_CRT_IC, i, par->crtc[i]);
 793
 794	/* write graphics controller registers */
 795	for (i = 0; i < VGA_GFX_C; i++)
 796		i740outreg(par, VGA_GFX_I, i, par->gdc[i]);
 797
 798	/* write attribute controller registers */
 799	for (i = 0; i < VGA_ATT_C; i++) {
 800		i740inb(par, VGA_IS1_RC);		/* reset flip-flop */
 801		i740outb(par, VGA_ATT_IW, i);
 802		i740outb(par, VGA_ATT_IW, par->atc[i]);
 803	}
 804
 805	i740inb(par, VGA_IS1_RC);
 806	i740outb(par, VGA_ATT_IW, 0x20);
 807
 808	i740outreg(par, VGA_CRT_IC, EXT_VERT_TOTAL, par->ext_vert_total);
 809	i740outreg(par, VGA_CRT_IC, EXT_VERT_DISPLAY, par->ext_vert_disp_end);
 810	i740outreg(par, VGA_CRT_IC, EXT_VERT_SYNC_START,
 811			par->ext_vert_sync_start);
 812	i740outreg(par, VGA_CRT_IC, EXT_VERT_BLANK_START,
 813			par->ext_vert_blank_start);
 814	i740outreg(par, VGA_CRT_IC, EXT_HORIZ_TOTAL, par->ext_horiz_total);
 815	i740outreg(par, VGA_CRT_IC, EXT_HORIZ_BLANK, par->ext_horiz_blank);
 816	i740outreg(par, VGA_CRT_IC, EXT_OFFSET, par->ext_offset);
 817	i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI, par->ext_start_addr_hi);
 818	i740outreg(par, VGA_CRT_IC, EXT_START_ADDR, par->ext_start_addr);
 819
 820	i740outreg_mask(par, VGA_CRT_IC, INTERLACE_CNTL,
 821			par->interlace_cntl, INTERLACE_ENABLE);
 822	i740outreg_mask(par, XRX, ADDRESS_MAPPING, par->address_mapping, 0x1F);
 823	i740outreg_mask(par, XRX, BITBLT_CNTL, par->bitblt_cntl, COLEXP_MODE);
 824	i740outreg_mask(par, XRX, DISPLAY_CNTL,
 825			par->display_cntl, VGA_WRAP_MODE | GUI_MODE);
 826	i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0, par->pixelpipe_cfg0, 0x9B);
 827	i740outreg_mask(par, XRX, PIXPIPE_CONFIG_2, par->pixelpipe_cfg2, 0x0C);
 828
 829	i740outreg(par, XRX, PLL_CNTL, par->pll_cntl);
 830
 831	i740outreg_mask(par, XRX, PIXPIPE_CONFIG_1,
 832			par->pixelpipe_cfg1, DISPLAY_COLOR_MODE);
 833
 834	itemp = readl(par->regs + FWATER_BLC);
 835	itemp &= ~(LMI_BURST_LENGTH | LMI_FIFO_WATERMARK);
 836	itemp |= par->lmi_fifo_watermark;
 837	writel(itemp, par->regs + FWATER_BLC);
 838
 839	i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_60HZ);
 840
 841	i740outreg_mask(par, MRX, COL_KEY_CNTL_1, 0, BLANK_DISP_OVERLAY);
 842	i740outreg_mask(par, XRX, IO_CTNL,
 843			par->io_cntl, EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
 844
 845	if (par->pixelpipe_cfg1 != DISPLAY_8BPP_MODE) {
 846		i740outb(par, VGA_PEL_MSK, 0xFF);
 847		i740outb(par, VGA_PEL_IW, 0x00);
 848		for (i = 0; i < 256; i++) {
 849			itemp = (par->pixelpipe_cfg0 & DAC_8_BIT) ? i : i >> 2;
 850			i740outb(par, VGA_PEL_D, itemp);
 851			i740outb(par, VGA_PEL_D, itemp);
 852			i740outb(par, VGA_PEL_D, itemp);
 853		}
 854	}
 855
 856	/* Wait for screen to stabilize. */
 857	mdelay(50);
 858	vga_unprotect(par);
 859
 860	info->fix.line_length =
 861			info->var.xres_virtual * info->var.bits_per_pixel / 8;
 862	if (info->var.bits_per_pixel == 8)
 863		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
 864	else
 865		info->fix.visual = FB_VISUAL_TRUECOLOR;
 866
 867	return 0;
 868}
 869
 870static int i740fb_setcolreg(unsigned regno, unsigned red, unsigned green,
 871			   unsigned blue, unsigned transp,
 872			   struct fb_info *info)
 873{
 874	u32 r, g, b;
 875
 876	dev_dbg(info->device, "setcolreg: regno: %i, red=%d, green=%d, blue=%d, transp=%d, bpp=%d\n",
 877		regno, red, green, blue, transp, info->var.bits_per_pixel);
 878
 879	switch (info->fix.visual) {
 880	case FB_VISUAL_PSEUDOCOLOR:
 881		if (regno >= 256)
 882			return -EINVAL;
 883		i740outb(info->par, VGA_PEL_IW, regno);
 884		i740outb(info->par, VGA_PEL_D, red >> 8);
 885		i740outb(info->par, VGA_PEL_D, green >> 8);
 886		i740outb(info->par, VGA_PEL_D, blue >> 8);
 887		break;
 888	case FB_VISUAL_TRUECOLOR:
 889		if (regno >= 16)
 890			return -EINVAL;
 891		r = (red >> (16 - info->var.red.length))
 892			<< info->var.red.offset;
 893		b = (blue >> (16 - info->var.blue.length))
 894			<< info->var.blue.offset;
 895		g = (green >> (16 - info->var.green.length))
 896			<< info->var.green.offset;
 897		((u32 *) info->pseudo_palette)[regno] = r | g | b;
 898		break;
 899	default:
 900		return -EINVAL;
 901	}
 902
 903	return 0;
 904}
 905
 906static int i740fb_pan_display(struct fb_var_screeninfo *var,
 907				 struct fb_info *info)
 908{
 909	struct i740fb_par *par = info->par;
 910	u32 base = (var->yoffset * info->var.xres_virtual
 911		 + (var->xoffset & ~7)) >> 2;
 912
 913	dev_dbg(info->device, "pan_display: xoffset: %i yoffset: %i base: %i\n",
 914		var->xoffset, var->yoffset, base);
 915
 916	switch (info->var.bits_per_pixel) {
 917	case 8:
 918		break;
 919	case 15:
 920	case 16:
 921		base *= 2;
 922		break;
 923	case 24:
 924		/*
 925		 * The last bit does not seem to have any effect on the start
 926		 * address register in 24bpp mode, so...
 927		 */
 928		base &= 0xFFFFFFFE; /* ...ignore the last bit. */
 929		base *= 3;
 930		break;
 931	case 32:
 932		base *= 4;
 933		break;
 934	}
 935
 936	par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
 937	par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >>  8;
 938	par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
 939	par->ext_start_addr =
 940			((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
 941
 942	i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_LO,  base & 0x000000FF);
 943	i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_HI,
 944			(base & 0x0000FF00) >> 8);
 945	i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI,
 946			(base & 0x3FC00000) >> 22);
 947	i740outreg(par, VGA_CRT_IC, EXT_START_ADDR,
 948			((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE);
 949
 950	return 0;
 951}
 952
 953static int i740fb_blank(int blank_mode, struct fb_info *info)
 954{
 955	struct i740fb_par *par = info->par;
 956
 957	unsigned char SEQ01;
 958	int DPMSSyncSelect;
 959
 960	switch (blank_mode) {
 961	case FB_BLANK_UNBLANK:
 962	case FB_BLANK_NORMAL:
 963		SEQ01 = 0x00;
 964		DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
 965		break;
 966	case FB_BLANK_VSYNC_SUSPEND:
 967		SEQ01 = 0x20;
 968		DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
 969		break;
 970	case FB_BLANK_HSYNC_SUSPEND:
 971		SEQ01 = 0x20;
 972		DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
 973		break;
 974	case FB_BLANK_POWERDOWN:
 975		SEQ01 = 0x20;
 976		DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
 977		break;
 978	default:
 979		return -EINVAL;
 980	}
 981	/* Turn the screen on/off */
 982	i740outb(par, SRX, 0x01);
 983	SEQ01 |= i740inb(par, SRX + 1) & ~0x20;
 984	i740outb(par, SRX, 0x01);
 985	i740outb(par, SRX + 1, SEQ01);
 986
 987	/* Set the DPMS mode */
 988	i740outreg(par, XRX, DPMS_SYNC_SELECT, DPMSSyncSelect);
 989
 990	/* Let fbcon do a soft blank for us */
 991	return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
 992}
 993
 994static struct fb_ops i740fb_ops = {
 995	.owner		= THIS_MODULE,
 996	.fb_open	= i740fb_open,
 997	.fb_release	= i740fb_release,
 998	.fb_check_var	= i740fb_check_var,
 999	.fb_set_par	= i740fb_set_par,
1000	.fb_setcolreg	= i740fb_setcolreg,
1001	.fb_blank	= i740fb_blank,
1002	.fb_pan_display	= i740fb_pan_display,
1003	.fb_fillrect	= cfb_fillrect,
1004	.fb_copyarea	= cfb_copyarea,
1005	.fb_imageblit	= cfb_imageblit,
1006};
1007
1008/* ------------------------------------------------------------------------- */
1009
1010static int __devinit i740fb_probe(struct pci_dev *dev,
1011				  const struct pci_device_id *ent)
1012{
1013	struct fb_info *info;
1014	struct i740fb_par *par;
1015	int ret, tmp;
1016	bool found = false;
1017	u8 *edid;
1018
1019	info = framebuffer_alloc(sizeof(struct i740fb_par), &(dev->dev));
1020	if (!info) {
1021		dev_err(&(dev->dev), "cannot allocate framebuffer\n");
1022		return -ENOMEM;
1023	}
1024
1025	par = info->par;
1026	mutex_init(&par->open_lock);
1027
1028	info->var.activate = FB_ACTIVATE_NOW;
1029	info->var.bits_per_pixel = 8;
1030	info->fbops = &i740fb_ops;
1031	info->pseudo_palette = par->pseudo_palette;
1032
1033	ret = pci_enable_device(dev);
1034	if (ret) {
1035		dev_err(info->device, "cannot enable PCI device\n");
1036		goto err_enable_device;
1037	}
1038
1039	ret = pci_request_regions(dev, info->fix.id);
1040	if (ret) {
1041		dev_err(info->device, "error requesting regions\n");
1042		goto err_request_regions;
1043	}
1044
1045	info->screen_base = pci_ioremap_bar(dev, 0);
1046	if (!info->screen_base) {
1047		dev_err(info->device, "error remapping base\n");
1048		ret = -ENOMEM;
1049		goto err_ioremap_1;
1050	}
1051
1052	par->regs = pci_ioremap_bar(dev, 1);
1053	if (!par->regs) {
1054		dev_err(info->device, "error remapping MMIO\n");
1055		ret = -ENOMEM;
1056		goto err_ioremap_2;
1057	}
1058
1059	/* detect memory size */
1060	if ((i740inreg(par, XRX, DRAM_ROW_TYPE) & DRAM_ROW_1)
1061							== DRAM_ROW_1_SDRAM)
1062		i740outb(par, XRX, DRAM_ROW_BNDRY_1);
1063	else
1064		i740outb(par, XRX, DRAM_ROW_BNDRY_0);
1065	info->screen_size = i740inb(par, XRX + 1) * 1024 * 1024;
1066	/* detect memory type */
1067	tmp = i740inreg(par, XRX, DRAM_ROW_CNTL_LO);
1068	par->has_sgram = !((tmp & DRAM_RAS_TIMING) ||
1069			   (tmp & DRAM_RAS_PRECHARGE));
1070
1071	printk(KERN_INFO "fb%d: Intel740 on %s, %ld KB %s\n", info->node,
1072		pci_name(dev), info->screen_size >> 10,
1073		par->has_sgram ? "SGRAM" : "SDRAM");
1074
1075	info->fix = i740fb_fix;
1076	info->fix.mmio_start = pci_resource_start(dev, 1);
1077	info->fix.mmio_len = pci_resource_len(dev, 1);
1078	info->fix.smem_start = pci_resource_start(dev, 0);
1079	info->fix.smem_len = info->screen_size;
1080	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1081
1082	if (i740fb_setup_ddc_bus(info) == 0) {
1083		par->ddc_registered = true;
1084		edid = fb_ddc_read(&par->ddc_adapter);
1085		if (edid) {
1086			fb_edid_to_monspecs(edid, &info->monspecs);
1087			kfree(edid);
1088			if (!info->monspecs.modedb)
1089				dev_err(info->device,
1090					"error getting mode database\n");
1091			else {
1092				const struct fb_videomode *m;
1093
1094				fb_videomode_to_modelist(
1095					info->monspecs.modedb,
1096					info->monspecs.modedb_len,
1097					&info->modelist);
1098				m = fb_find_best_display(&info->monspecs,
1099							 &info->modelist);
1100				if (m) {
1101					fb_videomode_to_var(&info->var, m);
1102					/* fill all other info->var's fields */
1103					if (!i740fb_check_var(&info->var, info))
1104						found = true;
1105				}
1106			}
1107		}
1108	}
1109
1110	if (!mode_option && !found)
1111		mode_option = "640x480-8@60";
1112
1113	if (mode_option) {
1114		ret = fb_find_mode(&info->var, info, mode_option,
1115				   info->monspecs.modedb,
1116				   info->monspecs.modedb_len,
1117				   NULL, info->var.bits_per_pixel);
1118		if (!ret || ret == 4) {
1119			dev_err(info->device, "mode %s not found\n",
1120				mode_option);
1121			ret = -EINVAL;
1122		}
1123	}
1124
1125	fb_destroy_modedb(info->monspecs.modedb);
1126	info->monspecs.modedb = NULL;
1127
1128	/* maximize virtual vertical size for fast scrolling */
1129	info->var.yres_virtual = info->fix.smem_len * 8 /
1130			(info->var.bits_per_pixel * info->var.xres_virtual);
1131
1132	if (ret == -EINVAL)
1133		goto err_find_mode;
1134
1135	ret = fb_alloc_cmap(&info->cmap, 256, 0);
1136	if (ret) {
1137		dev_err(info->device, "cannot allocate colormap\n");
1138		goto err_alloc_cmap;
1139	}
1140
1141	ret = register_framebuffer(info);
1142	if (ret) {
1143		dev_err(info->device, "error registering framebuffer\n");
1144		goto err_reg_framebuffer;
1145	}
1146
1147	printk(KERN_INFO "fb%d: %s frame buffer device\n",
1148		info->node, info->fix.id);
1149	pci_set_drvdata(dev, info);
1150#ifdef CONFIG_MTRR
1151	if (mtrr) {
1152		par->mtrr_reg = -1;
1153		par->mtrr_reg = mtrr_add(info->fix.smem_start,
1154				info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
1155	}
1156#endif
1157	return 0;
1158
1159err_reg_framebuffer:
1160	fb_dealloc_cmap(&info->cmap);
1161err_alloc_cmap:
1162err_find_mode:
1163	if (par->ddc_registered)
1164		i2c_del_adapter(&par->ddc_adapter);
1165	pci_iounmap(dev, par->regs);
1166err_ioremap_2:
1167	pci_iounmap(dev, info->screen_base);
1168err_ioremap_1:
1169	pci_release_regions(dev);
1170err_request_regions:
1171/*	pci_disable_device(dev); */
1172err_enable_device:
1173	framebuffer_release(info);
1174	return ret;
1175}
1176
1177static void __devexit i740fb_remove(struct pci_dev *dev)
1178{
1179	struct fb_info *info = pci_get_drvdata(dev);
1180
1181	if (info) {
1182		struct i740fb_par *par = info->par;
1183
1184#ifdef CONFIG_MTRR
1185		if (par->mtrr_reg >= 0) {
1186			mtrr_del(par->mtrr_reg, 0, 0);
1187			par->mtrr_reg = -1;
1188		}
1189#endif
1190		unregister_framebuffer(info);
1191		fb_dealloc_cmap(&info->cmap);
1192		if (par->ddc_registered)
1193			i2c_del_adapter(&par->ddc_adapter);
1194		pci_iounmap(dev, par->regs);
1195		pci_iounmap(dev, info->screen_base);
1196		pci_release_regions(dev);
1197/*		pci_disable_device(dev); */
1198		pci_set_drvdata(dev, NULL);
1199		framebuffer_release(info);
1200	}
1201}
1202
1203#ifdef CONFIG_PM
1204static int i740fb_suspend(struct pci_dev *dev, pm_message_t state)
1205{
1206	struct fb_info *info = pci_get_drvdata(dev);
1207	struct i740fb_par *par = info->par;
1208
1209	/* don't disable console during hibernation and wakeup from it */
1210	if (state.event == PM_EVENT_FREEZE || state.event == PM_EVENT_PRETHAW)
1211		return 0;
1212
1213	console_lock();
1214	mutex_lock(&(par->open_lock));
1215
1216	/* do nothing if framebuffer is not active */
1217	if (par->ref_count == 0) {
1218		mutex_unlock(&(par->open_lock));
1219		console_unlock();
1220		return 0;
1221	}
1222
1223	fb_set_suspend(info, 1);
1224
1225	pci_save_state(dev);
1226	pci_disable_device(dev);
1227	pci_set_power_state(dev, pci_choose_state(dev, state));
1228
1229	mutex_unlock(&(par->open_lock));
1230	console_unlock();
1231
1232	return 0;
1233}
1234
1235static int i740fb_resume(struct pci_dev *dev)
1236{
1237	struct fb_info *info = pci_get_drvdata(dev);
1238	struct i740fb_par *par = info->par;
1239
1240	console_lock();
1241	mutex_lock(&(par->open_lock));
1242
1243	if (par->ref_count == 0)
1244		goto fail;
1245
1246	pci_set_power_state(dev, PCI_D0);
1247	pci_restore_state(dev);
1248	if (pci_enable_device(dev))
1249		goto fail;
1250
1251	i740fb_set_par(info);
1252	fb_set_suspend(info, 0);
1253
1254fail:
1255	mutex_unlock(&(par->open_lock));
1256	console_unlock();
1257	return 0;
1258}
1259#else
1260#define i740fb_suspend NULL
1261#define i740fb_resume NULL
1262#endif /* CONFIG_PM */
1263
1264#define I740_ID_PCI 0x00d1
1265#define I740_ID_AGP 0x7800
1266
1267static DEFINE_PCI_DEVICE_TABLE(i740fb_id_table) = {
1268	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_PCI) },
1269	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_AGP) },
1270	{ 0 }
1271};
1272MODULE_DEVICE_TABLE(pci, i740fb_id_table);
1273
1274static struct pci_driver i740fb_driver = {
1275	.name		= "i740fb",
1276	.id_table	= i740fb_id_table,
1277	.probe		= i740fb_probe,
1278	.remove		= __devexit_p(i740fb_remove),
1279	.suspend	= i740fb_suspend,
1280	.resume		= i740fb_resume,
1281};
1282
1283#ifndef MODULE
1284static int  __init i740fb_setup(char *options)
1285{
1286	char *opt;
1287
1288	if (!options || !*options)
1289		return 0;
1290
1291	while ((opt = strsep(&options, ",")) != NULL) {
1292		if (!*opt)
1293			continue;
1294#ifdef CONFIG_MTRR
1295		else if (!strncmp(opt, "mtrr:", 5))
1296			mtrr = simple_strtoul(opt + 5, NULL, 0);
1297#endif
1298		else
1299			mode_option = opt;
1300	}
1301
1302	return 0;
1303}
1304#endif
1305
1306int __init i740fb_init(void)
1307{
1308#ifndef MODULE
1309	char *option = NULL;
1310
1311	if (fb_get_options("i740fb", &option))
1312		return -ENODEV;
1313	i740fb_setup(option);
1314#endif
1315
1316	return pci_register_driver(&i740fb_driver);
1317}
1318
1319static void __exit i740fb_exit(void)
1320{
1321	pci_unregister_driver(&i740fb_driver);
1322}
1323
1324module_init(i740fb_init);
1325module_exit(i740fb_exit);
1326
1327MODULE_AUTHOR("(c) 2011 Ondrej Zary <linux@rainbow-software.org>");
1328MODULE_LICENSE("GPL");
1329MODULE_DESCRIPTION("fbdev driver for Intel740");
1330
1331module_param(mode_option, charp, 0444);
1332MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
1333
1334#ifdef CONFIG_MTRR
1335module_param(mtrr, int, 0444);
1336MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
1337#endif