*/
#include <linux/module.h>
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci_ids.h>
#include <linux/resource.h>
#include <linux/unistd.h>
+#include <linux/console.h>
#include <asm/io.h>
#include <asm/div64.h>
-
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
#include <asm/page.h>
#include "i810_regs.h"
#include "i810.h"
#include "i810_main.h"
+/*
+ * voffset - framebuffer offset in MiB from aperture start address. In order for
+ * the driver to work with X, we must try to use memory holes left untouched by X. The
+ * following table lists where X's different surfaces start at.
+ *
+ * ---------------------------------------------
+ * : : 64 MiB : 32 MiB :
+ * ----------------------------------------------
+ * : FrontBuffer : 0 : 0 :
+ * : DepthBuffer : 48 : 16 :
+ * : BackBuffer : 56 : 24 :
+ * ----------------------------------------------
+ *
+ * So for chipsets with 64 MiB Aperture sizes, 32 MiB for v_offset is okay, allowing up to
+ * 15 + 1 MiB of Framebuffer memory. For 32 MiB Aperture sizes, a v_offset of 8 MiB should
+ * work, allowing 7 + 1 MiB of Framebuffer memory.
+ * Note, the size of the hole may change depending on how much memory you allocate to X,
+ * and how the memory is split up between these surfaces.
+ *
+ * Note: Anytime the DepthBuffer or FrontBuffer is overlapped, X would still run but with
+ * DRI disabled. But if the Frontbuffer is overlapped, X will fail to load.
+ *
+ * Experiment with v_offset to find out which works best for you.
+ */
+static u32 v_offset_default __devinitdata; /* For 32 MiB Aper size, 8 should be the default */
+static u32 voffset __devinitdata;
+
+static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
+static int __devinit i810fb_init_pci (struct pci_dev *dev,
+ const struct pci_device_id *entry);
+static void __exit i810fb_remove_pci(struct pci_dev *dev);
+static int i810fb_resume(struct pci_dev *dev);
+static int i810fb_suspend(struct pci_dev *dev, pm_message_t state);
+
+/* Chipset Specific Functions */
+static int i810fb_set_par (struct fb_info *info);
+static int i810fb_getcolreg (u8 regno, u8 *red, u8 *green, u8 *blue,
+ u8 *transp, struct fb_info *info);
+static int i810fb_setcolreg (unsigned regno, unsigned red, unsigned green, unsigned blue,
+ unsigned transp, struct fb_info *info);
+static int i810fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
+static int i810fb_blank (int blank_mode, struct fb_info *info);
+
+/* Initialization */
+static void i810fb_release_resource (struct fb_info *info, struct i810fb_par *par);
+
/* PCI */
static const char *i810_pci_list[] __devinitdata = {
"Intel(R) 810 Framebuffer Device" ,
.resume = i810fb_resume,
};
-static int vram __initdata = 4;
-static int bpp __initdata = 8;
-static int mtrr __initdata = 0;
-static int accel __initdata = 0;
-static int hsync1 __initdata = 0;
-static int hsync2 __initdata = 0;
-static int vsync1 __initdata = 0;
-static int vsync2 __initdata = 0;
-static int xres __initdata = 640;
-static int yres __initdata = 480;
-static int vyres __initdata = 0;
-static int sync __initdata = 0;
-static int ext_vga __initdata = 0;
-static int dcolor __initdata = 0;
+static char *mode_option __devinitdata = NULL;
+static int vram __devinitdata = 4;
+static int bpp __devinitdata = 8;
+static int mtrr __devinitdata;
+static int accel __devinitdata;
+static int hsync1 __devinitdata;
+static int hsync2 __devinitdata;
+static int vsync1 __devinitdata;
+static int vsync2 __devinitdata;
+static int xres __devinitdata;
+static int yres __devinitdata;
+static int vyres __devinitdata;
+static int sync __devinitdata;
+static int extvga __devinitdata;
+static int dcolor __devinitdata;
+static int ddc3 __devinitdata = 2;
/*------------------------------------------------------------*/
* DESCRIPTION:
* Blanks/unblanks the display
*/
-static void i810_screen_off(u8 *mmio, u8 mode)
+static void i810_screen_off(u8 __iomem *mmio, u8 mode)
{
u32 count = WAIT_COUNT;
u8 val;
* Turns off DRAM refresh. Must be off for only 2 vsyncs
* before data becomes corrupt
*/
-static void i810_dram_off(u8 *mmio, u8 mode)
+static void i810_dram_off(u8 __iomem *mmio, u8 mode)
{
u8 val;
* The IBM VGA standard allows protection of certain VGA registers.
* This will protect or unprotect them.
*/
-static void i810_protect_regs(u8 *mmio, int mode)
+static void i810_protect_regs(u8 __iomem *mmio, int mode)
{
u8 reg;
static void i810_load_pll(struct i810fb_par *par)
{
u32 tmp1, tmp2;
- u8 *mmio = par->mmio_start_virtual;
+ u8 __iomem *mmio = par->mmio_start_virtual;
tmp1 = par->regs.M | par->regs.N << 16;
tmp2 = i810_readl(DCLK_2D, mmio);
*/
static void i810_load_vga(struct i810fb_par *par)
{
- u8 *mmio = par->mmio_start_virtual;
+ u8 __iomem *mmio = par->mmio_start_virtual;
/* interlace */
i810_writeb(CR_INDEX_CGA, mmio, CR70);
*/
static void i810_load_vgax(struct i810fb_par *par)
{
- u8 *mmio = par->mmio_start_virtual;
+ u8 __iomem *mmio = par->mmio_start_virtual;
i810_writeb(CR_INDEX_CGA, mmio, CR30);
i810_writeb(CR_DATA_CGA, mmio, par->regs.cr30);
static void i810_load_2d(struct i810fb_par *par)
{
u32 tmp;
- u8 tmp8, *mmio = par->mmio_start_virtual;
+ u8 tmp8;
+ u8 __iomem *mmio = par->mmio_start_virtual;
i810_writel(FW_BLC, mmio, par->watermark);
tmp = i810_readl(PIXCONF, mmio);
* i810_hires - enables high resolution mode
* @mmio: address of register space
*/
-static void i810_hires(u8 *mmio)
+static void i810_hires(u8 __iomem *mmio)
{
u8 val;
val = i810_readb(CR_DATA_CGA, mmio);
i810_writeb(CR_INDEX_CGA, mmio, CR80);
i810_writeb(CR_DATA_CGA, mmio, val | 1);
+ /* Stop LCD displays from flickering */
+ i810_writel(MEM_MODE, mmio, i810_readl(MEM_MODE, mmio) | 4);
}
/**
static void i810_load_pitch(struct i810fb_par *par)
{
u32 tmp, pitch;
- u8 val, *mmio = par->mmio_start_virtual;
+ u8 val;
+ u8 __iomem *mmio = par->mmio_start_virtual;
pitch = par->pitch >> 3;
i810_writeb(SR_INDEX, mmio, SR01);
*/
static void i810_load_color(struct i810fb_par *par)
{
- u8 *mmio = par->mmio_start_virtual;
+ u8 __iomem *mmio = par->mmio_start_virtual;
u32 reg1;
u16 reg2;
+
reg1 = i810_readl(PIXCONF, mmio) & ~(0xF0000 | 1 << 27);
reg2 = i810_readw(BLTCNTL, mmio) & ~0x30;
*/
static void i810_load_regs(struct i810fb_par *par)
{
- u8 *mmio = par->mmio_start_virtual;
+ u8 __iomem *mmio = par->mmio_start_virtual;
i810_screen_off(mmio, OFF);
i810_protect_regs(mmio, OFF);
}
static void i810_write_dac(u8 regno, u8 red, u8 green, u8 blue,
- u8 *mmio)
+ u8 __iomem *mmio)
{
i810_writeb(CLUT_INDEX_WRITE, mmio, regno);
i810_writeb(CLUT_DATA, mmio, red);
}
static void i810_read_dac(u8 regno, u8 *red, u8 *green, u8 *blue,
- u8 *mmio)
+ u8 __iomem *mmio)
{
i810_writeb(CLUT_INDEX_READ, mmio, regno);
*red = i810_readb(CLUT_DATA, mmio);
static void i810_restore_pll(struct i810fb_par *par)
{
u32 tmp1, tmp2;
- u8 *mmio = par->mmio_start_virtual;
+ u8 __iomem *mmio = par->mmio_start_virtual;
tmp1 = par->hw_state.dclk_2d;
tmp2 = i810_readl(DCLK_2D, mmio);
static void i810_restore_dac(struct i810fb_par *par)
{
u32 tmp1, tmp2;
- u8 *mmio = par->mmio_start_virtual;
+ u8 __iomem *mmio = par->mmio_start_virtual;
tmp1 = par->hw_state.pixconf;
tmp2 = i810_readl(PIXCONF, mmio);
static void i810_restore_vgax(struct i810fb_par *par)
{
- u8 i, j, *mmio = par->mmio_start_virtual;
+ u8 i, j;
+ u8 __iomem *mmio = par->mmio_start_virtual;
for (i = 0; i < 4; i++) {
i810_writeb(CR_INDEX_CGA, mmio, CR30+i);
static void i810_restore_vga(struct i810fb_par *par)
{
- u8 i, *mmio = par->mmio_start_virtual;
+ u8 i;
+ u8 __iomem *mmio = par->mmio_start_virtual;
for (i = 0; i < 10; i++) {
i810_writeb(CR_INDEX_CGA, mmio, CR00 + i);
static void i810_restore_addr_map(struct i810fb_par *par)
{
- u8 tmp, *mmio = par->mmio_start_virtual;
+ u8 tmp;
+ u8 __iomem *mmio = par->mmio_start_virtual;
i810_writeb(GR_INDEX, mmio, GR10);
tmp = i810_readb(GR_DATA, mmio);
{
u32 tmp_long;
u16 tmp_word;
- u8 *mmio = par->mmio_start_virtual;
+ u8 __iomem *mmio = par->mmio_start_virtual;
tmp_word = i810_readw(BLTCNTL, mmio);
tmp_word &= ~(3 << 4);
static void i810_restore_vga_state(struct i810fb_par *par)
{
- u8 *mmio = par->mmio_start_virtual;
+ u8 __iomem *mmio = par->mmio_start_virtual;
i810_screen_off(mmio, OFF);
i810_protect_regs(mmio, OFF);
static void i810_save_vgax(struct i810fb_par *par)
{
- u8 i, *mmio = par->mmio_start_virtual;
+ u8 i;
+ u8 __iomem *mmio = par->mmio_start_virtual;
for (i = 0; i < 4; i++) {
i810_writeb(CR_INDEX_CGA, mmio, CR30 + i);
static void i810_save_vga(struct i810fb_par *par)
{
- u8 i, *mmio = par->mmio_start_virtual;
+ u8 i;
+ u8 __iomem *mmio = par->mmio_start_virtual;
for (i = 0; i < 10; i++) {
i810_writeb(CR_INDEX_CGA, mmio, CR00 + i);
static void i810_save_2d(struct i810fb_par *par)
{
- u8 *mmio = par->mmio_start_virtual;
+ u8 __iomem *mmio = par->mmio_start_virtual;
par->hw_state.dclk_2d = i810_readl(DCLK_2D, mmio);
par->hw_state.dclk_1d = i810_readl(DCLK_1D, mmio);
* DESCRIPTION:
* Calculates buffer pitch in bytes.
*/
-u32 get_line_length(struct i810fb_par *par, int xres_virtual, int bpp)
+static u32 get_line_length(struct i810fb_par *par, int xres_virtual, int bpp)
{
u32 length;
* Description:
* Shows or hides the hardware cursor
*/
-void i810_enable_cursor(u8 *mmio, int mode)
+static void i810_enable_cursor(u8 __iomem *mmio, int mode)
{
u32 temp;
static void i810_reset_cursor_image(struct i810fb_par *par)
{
- u8 *addr = par->cursor_heap.virtual;
+ u8 __iomem *addr = par->cursor_heap.virtual;
int i, j;
for (i = 64; i--; ) {
static void i810_load_cursor_image(int width, int height, u8 *data,
struct i810fb_par *par)
{
- u8 *addr = par->cursor_heap.virtual;
+ u8 __iomem *addr = par->cursor_heap.virtual;
int i, j, w = width/8;
int mod = width % 8, t_mask, d_mask;
static void i810_load_cursor_colors(int fg, int bg, struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
- u8 *mmio = par->mmio_start_virtual, temp;
- u8 red, green, blue, trans;
+ struct i810fb_par *par = info->par;
+ u8 __iomem *mmio = par->mmio_start_virtual;
+ u8 red, green, blue, trans, temp;
i810fb_getcolreg(bg, &red, &green, &blue, &trans, info);
*/
static void i810_init_cursor(struct i810fb_par *par)
{
- u8 *mmio = par->mmio_start_virtual;
+ u8 __iomem *mmio = par->mmio_start_virtual;
i810_enable_cursor(mmio, OFF);
i810_writel(CURBASE, mmio, par->cursor_heap.physical);
static int i810_check_params(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
- int line_length, vidmem;
- u32 xres, yres, vxres, vyres;
-
- xres = var->xres;
- yres = var->yres;
- vxres = var->xres_virtual;
- vyres = var->yres_virtual;
-
+ struct i810fb_par *par = info->par;
+ int line_length, vidmem, mode_valid = 0, retval = 0;
+ u32 vyres = var->yres_virtual, vxres = var->xres_virtual;
/*
* Memory limit
*/
- line_length = get_line_length(par, vxres,
- var->bits_per_pixel);
-
+ line_length = get_line_length(par, vxres, var->bits_per_pixel);
vidmem = line_length*vyres;
+
if (vidmem > par->fb.size) {
vyres = par->fb.size/line_length;
- if (vyres < yres) {
+ if (vyres < var->yres) {
vyres = yres;
vxres = par->fb.size/vyres;
vxres /= var->bits_per_pixel >> 3;
line_length = get_line_length(par, vxres,
var->bits_per_pixel);
vidmem = line_length * yres;
- if (vxres < xres) {
+ if (vxres < var->xres) {
printk("i810fb: required video memory, "
"%d bytes, for %dx%d-%d (virtual) "
"is out of range\n",
}
}
}
+
+ var->xres_virtual = vxres;
+ var->yres_virtual = vyres;
+
/*
* Monitor limit
*/
info->monspecs.dclkmax = 204000000;
break;
}
+
info->monspecs.dclkmin = 15000000;
- if (fb_validate_mode(var, info)) {
- if (fb_get_mode(FB_MAXTIMINGS, 0, var, info))
- return -EINVAL;
+ if (!fb_validate_mode(var, info))
+ mode_valid = 1;
+
+#ifdef CONFIG_FB_I810_I2C
+ if (!mode_valid && info->monspecs.gtf &&
+ !fb_get_mode(FB_MAXTIMINGS, 0, var, info))
+ mode_valid = 1;
+
+ if (!mode_valid && info->monspecs.modedb_len) {
+ struct fb_videomode *mode;
+
+ mode = fb_find_best_mode(var, &info->modelist);
+ if (mode) {
+ fb_videomode_to_var(var, mode);
+ mode_valid = 1;
+ }
}
-
- var->xres = xres;
- var->yres = yres;
- var->xres_virtual = vxres;
- var->yres_virtual = vyres;
- return 0;
+#endif
+ if (!mode_valid && info->monspecs.modedb_len == 0) {
+ if (fb_get_mode(FB_MAXTIMINGS, 0, var, info)) {
+ int default_sync = (info->monspecs.hfmin-HFMIN)
+ |(info->monspecs.hfmax-HFMAX)
+ |(info->monspecs.vfmin-VFMIN)
+ |(info->monspecs.vfmax-VFMAX);
+ printk("i810fb: invalid video mode%s\n",
+ default_sync ? "" : ". Specifying "
+ "vsyncN/hsyncN parameters may help");
+ retval = -EINVAL;
+ }
+ }
+
+ return retval;
}
/**
*/
static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue,
u8 *transp, struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
- u8 *mmio = par->mmio_start_virtual, temp;
+ struct i810fb_par *par = info->par;
+ u8 __iomem *mmio = par->mmio_start_virtual;
+ u8 temp;
if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
if ((info->var.green.length == 5 && regno > 31) ||
static int i810fb_open(struct fb_info *info, int user)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u32 count = atomic_read(&par->use_count);
if (count == 0) {
memset(&par->state, 0, sizeof(struct vgastate));
par->state.flags = VGA_SAVE_CMAP;
- par->state.vgabase = (caddr_t) par->mmio_start_virtual;
+ par->state.vgabase = par->mmio_start_virtual;
save_vga(&par->state);
i810_save_vga_state(par);
static int i810fb_release(struct fb_info *info, int user)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u32 count;
count = atomic_read(&par->use_count);
unsigned blue, unsigned transp,
struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
- u8 *mmio = par->mmio_start_virtual, temp;
+ struct i810fb_par *par = info->par;
+ u8 __iomem *mmio = par->mmio_start_virtual;
+ u8 temp;
int i;
if (regno > 255) return 1;
static int i810fb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u32 total;
total = var->xoffset * par->depth +
static int i810fb_blank (int blank_mode, struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
- u8 *mmio = par->mmio_start_virtual;
+ struct i810fb_par *par = info->par;
+ u8 __iomem *mmio = par->mmio_start_virtual;
int mode = 0, pwr, scr_off = 0;
pwr = i810_readl(PWR_CLKC, mmio);
- switch(blank_mode) {
- case VESA_NO_BLANKING:
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
mode = POWERON;
pwr |= 1;
scr_off = ON;
break;
- case VESA_VSYNC_SUSPEND:
+ case FB_BLANK_NORMAL:
+ mode = POWERON;
+ pwr |= 1;
+ scr_off = OFF;
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
mode = STANDBY;
pwr |= 1;
scr_off = OFF;
break;
- case VESA_HSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
mode = SUSPEND;
pwr |= 1;
scr_off = OFF;
break;
- case VESA_POWERDOWN:
+ case FB_BLANK_POWERDOWN:
mode = POWERDOWN;
pwr &= ~1;
scr_off = OFF;
default:
return -EINVAL;
}
+
i810_screen_off(mmio, scr_off);
i810_writel(HVSYNC, mmio, mode);
i810_writel(PWR_CLKC, mmio, pwr);
+
return 0;
}
static int i810fb_set_par(struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
decode_var(&info->var, par);
i810_load_regs(par);
i810_init_cursor(par);
-
encode_fix(&info->fix, info);
- if (info->var.accel_flags && !(par->dev_flags & LOCKUP))
+ if (info->var.accel_flags && !(par->dev_flags & LOCKUP)) {
+ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
+ FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
+ FBINFO_HWACCEL_IMAGEBLIT;
info->pixmap.scan_align = 2;
- else
+ } else {
info->pixmap.scan_align = 1;
-
+ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+ }
return 0;
}
static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
- struct i810fb_par *par = (struct i810fb_par *)info->par;
- u8 *mmio = par->mmio_start_virtual;
- u8 data[64 * 8];
-
- if (!info->var.accel_flags || par->dev_flags & LOCKUP)
- return soft_cursor(info, cursor);
+ struct i810fb_par *par = info->par;
+ u8 __iomem *mmio = par->mmio_start_virtual;
+
+ if (!par->dev_flags & LOCKUP)
+ return -ENXIO;
if (cursor->image.width > 64 || cursor->image.height > 64)
return -ENXIO;
- if ((i810_readl(CURBASE, mmio) & 0xf) != par->cursor_heap.physical)
+ if ((i810_readl(CURBASE, mmio) & 0xf) != par->cursor_heap.physical) {
i810_init_cursor(par);
+ cursor->set |= FB_CUR_SETALL;
+ }
i810_enable_cursor(mmio, OFF);
- if (cursor->set & FB_CUR_SETHOT)
- info->cursor.hot = cursor->hot;
-
if (cursor->set & FB_CUR_SETPOS) {
u32 tmp;
- info->cursor.image.dx = cursor->image.dx;
- info->cursor.image.dy = cursor->image.dy;
-
- tmp = cursor->image.dx - info->var.xoffset;
+ tmp = (cursor->image.dx - info->var.xoffset) & 0xffff;
tmp |= (cursor->image.dy - info->var.yoffset) << 16;
-
i810_writel(CURPOS, mmio, tmp);
}
- if (cursor->set & FB_CUR_SETSIZE) {
- info->cursor.image.height = cursor->image.height;
- info->cursor.image.width = cursor->image.width;
+ if (cursor->set & FB_CUR_SETSIZE)
i810_reset_cursor_image(par);
- }
- if (cursor->set & FB_CUR_SETCMAP) {
- info->cursor.image.fg_color = cursor->image.fg_color;
- info->cursor.image.bg_color = cursor->image.bg_color;
+ if (cursor->set & FB_CUR_SETCMAP)
i810_load_cursor_colors(cursor->image.fg_color,
cursor->image.bg_color,
info);
- }
- if (cursor->set & FB_CUR_SETSHAPE) {
- int size = ((info->cursor.image.width + 7) >> 3) *
- info->cursor.image.height;
+ if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
+ int size = ((cursor->image.width + 7) >> 3) *
+ cursor->image.height;
int i;
+ u8 *data = kmalloc(64 * 8, GFP_ATOMIC);
- switch (info->cursor.rop) {
+ if (data == NULL)
+ return -ENOMEM;
+
+ switch (cursor->rop) {
case ROP_XOR:
for (i = 0; i < size; i++)
- data[i] = cursor->image.data[i] ^ info->cursor.mask[i];
+ data[i] = cursor->image.data[i] ^ cursor->mask[i];
break;
case ROP_COPY:
default:
for (i = 0; i < size; i++)
- data[i] = cursor->image.data[i] & info->cursor.mask[i];
+ data[i] = cursor->image.data[i] & cursor->mask[i];
break;
}
- i810_load_cursor_image(info->cursor.image.width,
- info->cursor.image.height, data,
+
+ i810_load_cursor_image(cursor->image.width,
+ cursor->image.height, data,
par);
+ kfree(data);
}
- if (info->cursor.enable)
+ if (cursor->enable)
i810_enable_cursor(mmio, ON);
+
return 0;
}
/***********************************************************************
* Power Management *
***********************************************************************/
-static int i810fb_suspend(struct pci_dev *dev, u32 state)
+static int i810fb_suspend(struct pci_dev *dev, pm_message_t mesg)
{
struct fb_info *info = pci_get_drvdata(dev);
- struct i810fb_par *par = (struct i810fb_par *) info->par;
- int blank = 0, prev_state = par->cur_state;
+ struct i810fb_par *par = info->par;
+
+ par->cur_state = mesg.event;
- if (state == prev_state)
+ switch (mesg.event) {
+ case PM_EVENT_FREEZE:
+ case PM_EVENT_PRETHAW:
+ dev->dev.power.power_state = mesg;
return 0;
+ }
- par->cur_state = state;
+ acquire_console_sem();
+ fb_set_suspend(info, 1);
- switch (state) {
- case 1:
- blank = VESA_VSYNC_SUSPEND;
- break;
- case 2:
- blank = VESA_HSYNC_SUSPEND;
- break;
- case 3:
- blank = VESA_POWERDOWN;
- break;
- default:
- return -EINVAL;
- }
- info->fbops->fb_blank(blank, info);
+ if (info->fbops->fb_sync)
+ info->fbops->fb_sync(info);
- if (!prev_state) {
- par->drm_agp->unbind_memory(par->i810_gtt.i810_fb_memory);
- par->drm_agp->unbind_memory(par->i810_gtt.i810_cursor_memory);
- pci_disable_device(dev);
- }
- pci_save_state(dev, par->pci_state);
- pci_set_power_state(dev, state);
+ i810fb_blank(FB_BLANK_POWERDOWN, info);
+ agp_unbind_memory(par->i810_gtt.i810_fb_memory);
+ agp_unbind_memory(par->i810_gtt.i810_cursor_memory);
+
+ pci_save_state(dev);
+ pci_disable_device(dev);
+ pci_set_power_state(dev, pci_choose_state(dev, mesg));
+ release_console_sem();
return 0;
}
static int i810fb_resume(struct pci_dev *dev)
{
struct fb_info *info = pci_get_drvdata(dev);
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
+ int cur_state = par->cur_state;
- if (par->cur_state == 0)
- return 0;
+ par->cur_state = PM_EVENT_ON;
- pci_restore_state(dev, par->pci_state);
- pci_set_power_state(dev, 0);
- pci_enable_device(dev);
- par->drm_agp->bind_memory(par->i810_gtt.i810_fb_memory,
- par->fb.offset);
- par->drm_agp->bind_memory(par->i810_gtt.i810_cursor_memory,
- par->cursor_heap.offset);
+ if (cur_state == PM_EVENT_FREEZE) {
+ pci_set_power_state(dev, PCI_D0);
+ return 0;
+ }
- info->fbops->fb_blank(VESA_NO_BLANKING, info);
+ acquire_console_sem();
+ pci_set_power_state(dev, PCI_D0);
+ pci_restore_state(dev);
- par->cur_state = 0;
+ if (pci_enable_device(dev))
+ goto fail;
+ pci_set_master(dev);
+ agp_bind_memory(par->i810_gtt.i810_fb_memory,
+ par->fb.offset);
+ agp_bind_memory(par->i810_gtt.i810_cursor_memory,
+ par->cursor_heap.offset);
+ i810fb_set_par(info);
+ fb_set_suspend (info, 0);
+ info->fbops->fb_blank(VESA_NO_BLANKING, info);
+fail:
+ release_console_sem();
return 0;
}
/***********************************************************************
static int __devinit i810_alloc_agp_mem(struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
int size;
+ struct agp_bridge_data *bridge;
i810_fix_offsets(par);
size = par->fb.size + par->iring.size;
- par->drm_agp = (drm_agp_t *) inter_module_get("drm_agp");
- if (!par->drm_agp) {
- printk("i810fb: cannot acquire agp\n");
+ if (!(bridge = agp_backend_acquire(par->dev))) {
+ printk("i810fb_alloc_fbmem: cannot acquire agpgart\n");
return -ENODEV;
}
- par->drm_agp->acquire();
-
if (!(par->i810_gtt.i810_fb_memory =
- par->drm_agp->allocate_memory(size >> 12, AGP_NORMAL_MEMORY))) {
+ agp_allocate_memory(bridge, size >> 12, AGP_NORMAL_MEMORY))) {
printk("i810fb_alloc_fbmem: can't allocate framebuffer "
"memory\n");
- par->drm_agp->release();
+ agp_backend_release(bridge);
return -ENOMEM;
}
- if (par->drm_agp->bind_memory(par->i810_gtt.i810_fb_memory,
- par->fb.offset)) {
+ if (agp_bind_memory(par->i810_gtt.i810_fb_memory,
+ par->fb.offset)) {
printk("i810fb_alloc_fbmem: can't bind framebuffer memory\n");
- par->drm_agp->release();
+ agp_backend_release(bridge);
return -EBUSY;
}
if (!(par->i810_gtt.i810_cursor_memory =
- par->drm_agp->allocate_memory(par->cursor_heap.size >> 12,
- AGP_PHYSICAL_MEMORY))) {
+ agp_allocate_memory(bridge, par->cursor_heap.size >> 12,
+ AGP_PHYSICAL_MEMORY))) {
printk("i810fb_alloc_cursormem: can't allocate"
"cursor memory\n");
- par->drm_agp->release();
+ agp_backend_release(bridge);
return -ENOMEM;
}
- if (par->drm_agp->bind_memory(par->i810_gtt.i810_cursor_memory,
+ if (agp_bind_memory(par->i810_gtt.i810_cursor_memory,
par->cursor_heap.offset)) {
printk("i810fb_alloc_cursormem: cannot bind cursor memory\n");
- par->drm_agp->release();
+ agp_backend_release(bridge);
return -EBUSY;
}
i810_fix_pointers(par);
- par->drm_agp->release();
+ agp_backend_release(bridge);
return 0;
}
hsync1 = HFMIN;
if (!hsync2)
hsync2 = HFMAX;
- info->monspecs.hfmax = hsync2;
- info->monspecs.hfmin = hsync1;
- if (hsync2 < hsync1)
+ if (!info->monspecs.hfmax)
+ info->monspecs.hfmax = hsync2;
+ if (!info->monspecs.hfmin)
+ info->monspecs.hfmin = hsync1;
+ if (hsync2 < hsync1)
info->monspecs.hfmin = hsync2;
if (!vsync1)
vsync2 = VFMAX;
if (IS_DVT && vsync1 < 60)
vsync1 = 60;
- info->monspecs.vfmax = vsync2;
- info->monspecs.vfmin = vsync1;
+ if (!info->monspecs.vfmax)
+ info->monspecs.vfmax = vsync2;
+ if (!info->monspecs.vfmin)
+ info->monspecs.vfmin = vsync1;
if (vsync2 < vsync1)
info->monspecs.vfmin = vsync2;
}
if (sync)
par->dev_flags |= ALWAYS_SYNC;
+ par->ddc_num = ddc3;
+
if (bpp < 8)
bpp = 8;
+ par->i810fb_ops = i810fb_ops;
+
+ if (xres)
+ info->var.xres = xres;
+ else
+ info->var.xres = 640;
+
+ if (yres)
+ info->var.yres = yres;
+ else
+ info->var.yres = 480;
+
if (!vyres)
- vyres = (vram << 20)/(xres*bpp >> 3);
+ vyres = (vram << 20)/(info->var.xres*bpp >> 3);
- par->i810fb_ops = i810fb_ops;
- info->var.xres = xres;
- info->var.yres = yres;
info->var.yres_virtual = vyres;
info->var.bits_per_pixel = bpp;
*/
static void __devinit i810_init_device(struct i810fb_par *par)
{
- u8 reg, *mmio = par->mmio_start_virtual;
+ u8 reg;
+ u8 __iomem *mmio = par->mmio_start_virtual;
if (mtrr) set_mtrr(par);
i810_init_cursor(par);
/* mvo: enable external vga-connector (for laptops) */
- if (ext_vga) {
+ if (extvga) {
i810_writel(HVSYNC, mmio, 0);
i810_writel(PWR_CLKC, mmio, 3);
}
pci_read_config_byte(par->dev, 0x50, ®);
reg &= FREQ_MASK;
par->mem_freq = (reg) ? 133 : 100;
+
}
static int __devinit
return 0;
}
-
-int __init i810fb_setup(char *options)
+
+static void __devinit i810fb_find_init_mode(struct fb_info *info)
+{
+ struct fb_videomode mode;
+ struct fb_var_screeninfo var;
+ struct fb_monspecs *specs = &info->monspecs;
+ int found = 0;
+#ifdef CONFIG_FB_I810_I2C
+ int i;
+ int err = 1;
+ struct i810fb_par *par = info->par;
+#endif
+
+ INIT_LIST_HEAD(&info->modelist);
+ memset(&mode, 0, sizeof(struct fb_videomode));
+ var = info->var;
+#ifdef CONFIG_FB_I810_I2C
+ i810_create_i2c_busses(par);
+
+ for (i = 0; i < par->ddc_num + 1; i++) {
+ err = i810_probe_i2c_connector(info, &par->edid, i);
+ if (!err)
+ break;
+ }
+
+ if (!err)
+ printk("i810fb_init_pci: DDC probe successful\n");
+
+ fb_edid_to_monspecs(par->edid, specs);
+
+ if (specs->modedb == NULL)
+ printk("i810fb_init_pci: Unable to get Mode Database\n");
+
+ fb_videomode_to_modelist(specs->modedb, specs->modedb_len,
+ &info->modelist);
+ if (specs->modedb != NULL) {
+ struct fb_videomode *m;
+
+ if (xres && yres) {
+ if ((m = fb_find_best_mode(&var, &info->modelist))) {
+ mode = *m;
+ found = 1;
+ }
+ }
+
+ if (!found) {
+ m = fb_find_best_display(&info->monspecs, &info->modelist);
+ mode = *m;
+ found = 1;
+ }
+
+ fb_videomode_to_var(&var, &mode);
+ }
+#endif
+ if (mode_option)
+ fb_find_mode(&var, info, mode_option, specs->modedb,
+ specs->modedb_len, (found) ? &mode : NULL,
+ info->var.bits_per_pixel);
+
+ info->var = var;
+ fb_destroy_modedb(specs->modedb);
+ specs->modedb = NULL;
+}
+
+#ifndef MODULE
+static int __devinit i810fb_setup(char *options)
{
char *this_opt, *suffix = NULL;
mtrr = 1;
else if (!strncmp(this_opt, "accel", 5))
accel = 1;
- else if (!strncmp(this_opt, "ext_vga", 7))
- ext_vga = 1;
+ else if (!strncmp(this_opt, "extvga", 6))
+ extvga = 1;
else if (!strncmp(this_opt, "sync", 4))
sync = 1;
else if (!strncmp(this_opt, "vram:", 5))
vsync2 = simple_strtoul(this_opt+7, NULL, 0);
else if (!strncmp(this_opt, "dcolor", 6))
dcolor = 1;
+ else if (!strncmp(this_opt, "ddc3", 4))
+ ddc3 = 3;
+ else
+ mode_option = this_opt;
}
return 0;
}
+#endif
static int __devinit i810fb_init_pci (struct pci_dev *dev,
const struct pci_device_id *entry)
{
struct fb_info *info;
struct i810fb_par *par = NULL;
- int err, vfreq, hfreq, pixclock;
+ struct fb_videomode mode;
+ int i, err = -1, vfreq, hfreq, pixclock;
- if (!(info = kmalloc(sizeof(struct fb_info), GFP_KERNEL))) {
- i810fb_release_resource(info, par);
- return -ENOMEM;
- }
- memset(info, 0, sizeof(struct fb_info));
+ i = 0;
- if(!(par = kmalloc(sizeof(struct i810fb_par), GFP_KERNEL))) {
- i810fb_release_resource(info, par);
+ info = framebuffer_alloc(sizeof(struct i810fb_par), &dev->dev);
+ if (!info)
return -ENOMEM;
- }
- memset(par, 0, sizeof(struct i810fb_par));
+ par = info->par;
par->dev = dev;
- info->par = par;
- if (!(info->pixmap.addr = kmalloc(64*1024, GFP_KERNEL))) {
+ if (!(info->pixmap.addr = kmalloc(8*1024, GFP_KERNEL))) {
i810fb_release_resource(info, par);
return -ENOMEM;
}
- memset(info->pixmap.addr, 0, 64*1024);
- info->pixmap.size = 64*1024;
+ memset(info->pixmap.addr, 0, 8*1024);
+ info->pixmap.size = 8*1024;
info->pixmap.buf_align = 8;
+ info->pixmap.access_align = 32;
info->pixmap.flags = FB_PIXMAP_SYSTEM;
if ((err = i810_allocate_pci_resource(par, entry))) {
info->screen_base = par->fb.virtual;
info->fbops = &par->i810fb_ops;
info->pseudo_palette = par->pseudo_palette;
- info->flags = FBINFO_FLAG_DEFAULT;
-
fb_alloc_cmap(&info->cmap, 256, 0);
+ i810fb_find_init_mode(info);
if ((err = info->fbops->fb_check_var(&info->var, info))) {
i810fb_release_resource(info, par);
return err;
}
+
+ fb_var_to_videomode(&mode, &info->var);
+ fb_add_videomode(&mode, &info->modelist);
encode_fix(&info->fix, info);
i810fb_init_ringbuffer(info);
err = register_framebuffer(info);
+
if (err < 0) {
i810fb_release_resource(info, par);
printk("i810fb_init: cannot register framebuffer device\n");
static void i810fb_release_resource(struct fb_info *info,
struct i810fb_par *par)
{
- if (par) {
- unset_mtrr(par);
- if (par->drm_agp) {
- drm_agp_t *agp = par->drm_agp;
- struct gtt_data *gtt = &par->i810_gtt;
-
- if (par->i810_gtt.i810_cursor_memory)
- agp->free_memory(gtt->i810_cursor_memory);
- if (par->i810_gtt.i810_fb_memory)
- agp->free_memory(gtt->i810_fb_memory);
-
- inter_module_put("drm_agp");
- par->drm_agp = NULL;
- }
+ struct gtt_data *gtt = &par->i810_gtt;
+ unset_mtrr(par);
- if (par->mmio_start_virtual)
- iounmap(par->mmio_start_virtual);
- if (par->aperture.virtual)
- iounmap(par->aperture.virtual);
+ i810_delete_i2c_busses(par);
- if (par->res_flags & FRAMEBUFFER_REQ)
- release_mem_region(par->aperture.physical,
- par->aperture.size);
- if (par->res_flags & MMIO_REQ)
- release_mem_region(par->mmio_start_phys, MMIO_SIZE);
+ if (par->i810_gtt.i810_cursor_memory)
+ agp_free_memory(gtt->i810_cursor_memory);
+ if (par->i810_gtt.i810_fb_memory)
+ agp_free_memory(gtt->i810_fb_memory);
- if (par->res_flags & PCI_DEVICE_ENABLED)
- pci_disable_device(par->dev);
+ if (par->mmio_start_virtual)
+ iounmap(par->mmio_start_virtual);
+ if (par->aperture.virtual)
+ iounmap(par->aperture.virtual);
+ kfree(par->edid);
+ if (par->res_flags & FRAMEBUFFER_REQ)
+ release_mem_region(par->aperture.physical,
+ par->aperture.size);
+ if (par->res_flags & MMIO_REQ)
+ release_mem_region(par->mmio_start_phys, MMIO_SIZE);
+
+ framebuffer_release(info);
- kfree(par);
- }
- if (info)
- kfree(info);
}
static void __exit i810fb_remove_pci(struct pci_dev *dev)
{
struct fb_info *info = pci_get_drvdata(dev);
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
unregister_framebuffer(info);
i810fb_release_resource(info, par);
}
#ifndef MODULE
-int __init i810fb_init(void)
+static int __devinit i810fb_init(void)
{
- if (agp_intel_init()) {
- printk("i810fb_init: cannot initialize intel agpgart\n");
+ char *option = NULL;
+
+ if (fb_get_options("i810fb", &option))
return -ENODEV;
- }
+ i810fb_setup(option);
- if (pci_register_driver(&i810fb_driver) > 0)
- return 0;
- pci_unregister_driver(&i810fb_driver);
- return -ENODEV;
+ return pci_register_driver(&i810fb_driver);
}
#endif
#ifdef MODULE
-int __init i810fb_init(void)
+static int __devinit i810fb_init(void)
{
hsync1 *= 1000;
hsync2 *= 1000;
- if (pci_register_driver(&i810fb_driver) > 0)
- return 0;
- pci_unregister_driver(&i810fb_driver);
- return -ENODEV;
+ return pci_register_driver(&i810fb_driver);
}
-MODULE_PARM(vram, "i");
+module_param(vram, int, 0);
MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB"
" (default=4)");
-MODULE_PARM(voffset, "i");
+module_param(voffset, int, 0);
MODULE_PARM_DESC(voffset, "at what offset to place start of framebuffer "
"memory (0 to maximum aperture size), in MiB (default = 48)");
-MODULE_PARM(bpp, "i");
+module_param(bpp, int, 0);
MODULE_PARM_DESC(bpp, "Color depth for display in bits per pixel"
" (default = 8)");
-MODULE_PARM(xres, "i");
+module_param(xres, int, 0);
MODULE_PARM_DESC(xres, "Horizontal resolution in pixels (default = 640)");
-MODULE_PARM(yres, "i");
+module_param(yres, int, 0);
MODULE_PARM_DESC(yres, "Vertical resolution in scanlines (default = 480)");
-MODULE_PARM(vyres, "i");
+module_param(vyres,int, 0);
MODULE_PARM_DESC(vyres, "Virtual vertical resolution in scanlines"
" (default = 480)");
-MODULE_PARM(hsync1, "i");
+module_param(hsync1, int, 0);
MODULE_PARM_DESC(hsync1, "Minimum horizontal frequency of monitor in KHz"
- " (default = 31)");
-MODULE_PARM(hsync2, "i");
+ " (default = 29)");
+module_param(hsync2, int, 0);
MODULE_PARM_DESC(hsync2, "Maximum horizontal frequency of monitor in KHz"
- " (default = 31)");
-MODULE_PARM(vsync1, "i");
+ " (default = 30)");
+module_param(vsync1, int, 0);
MODULE_PARM_DESC(vsync1, "Minimum vertical frequency of monitor in Hz"
" (default = 50)");
-MODULE_PARM(vsync2, "i");
+module_param(vsync2, int, 0);
MODULE_PARM_DESC(vsync2, "Maximum vertical frequency of monitor in Hz"
" (default = 60)");
-MODULE_PARM(accel, "i");
+module_param(accel, bool, 0);
MODULE_PARM_DESC(accel, "Use Acceleration (BLIT) engine (default = 0)");
-MODULE_PARM(mtrr, "i");
+module_param(mtrr, bool, 0);
MODULE_PARM_DESC(mtrr, "Use MTRR (default = 0)");
-MODULE_PARM(ext_vga, "i");
-MODULE_PARM_DESC(ext_vga, "Enable external VGA connector (default = 0)");
-MODULE_PARM(sync, "i");
+module_param(extvga, bool, 0);
+MODULE_PARM_DESC(extvga, "Enable external VGA connector (default = 0)");
+module_param(sync, bool, 0);
MODULE_PARM_DESC(sync, "wait for accel engine to finish drawing"
" (default = 0)");
-MODULE_PARM(dcolor, "i");
+module_param(dcolor, bool, 0);
MODULE_PARM_DESC(dcolor, "use DirectColor visuals"
" (default = 0 = TrueColor)");
+module_param(ddc3, bool, 0);
+MODULE_PARM_DESC(ddc3, "Probe DDC bus 3 (default = 0 = no)");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Specify initial video mode");
MODULE_AUTHOR("Tony A. Daplas");
MODULE_DESCRIPTION("Framebuffer device for the Intel 810/815 and"
{
pci_unregister_driver(&i810fb_driver);
}
-module_init(i810fb_init);
module_exit(i810fb_exit);
#endif /* MODULE */
-
+module_init(i810fb_init);