2 * linux/drivers/video/i830/i830.c
3 * -- Intel 830 framebuffer device
5 * Copyright (C) 2004 Frank Zirkelbach <hackbard@hackdaworld.dyndns.org>
8 * Code based on vfb.c (Geert Uytterhoeven), i810fb (Tony Daplas),
9 * xorg i830 drivers and intelfb (David Dawes).
11 * This driver is subject to the terms of the GNU General Public License.
12 * See file COPYING in the main directory for more details.
16 #include <linux/module.h>
17 #include <linux/config.h>
18 #include <linux/kernel.h>
19 #include <linux/errno.h>
20 #include <linux/string.h>
22 #include <linux/tty.h>
23 #include <linux/slab.h>
25 #include <linux/init.h>
26 #include <linux/pci.h>
27 #include <linux/resource.h>
28 #include <linux/unistd.h>
30 #include <asm/div64.h>
37 #include "i830_regs.h"
40 static const char *i830_pci_list[] __devinitdata = {
41 "Intel(R) 830 Chipset Graphics Controller Framebuffer Device"
43 static struct pci_device_id i830fb_pci_table[] = {
44 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82830_CGC,
45 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
48 satic struct pci_driver i830fb_driver = {
50 .id_table = i830fb_pci_table,
51 .probe = i830fb_init_pci,
52 .remove = __exit_p(i830fb_remove_pci),
53 .suspend = i830fb_suspend,
54 .resume = i830fb_resume
56 static struct fb_ops i830fb_ops __devinitdata = {
58 .fb_open = i830fb_open,
59 .fb_release = i830fb_release,
60 .fb_check_var = i830fb_check_var,
61 .fb_set_par = i830fb_set_par,
62 .fb_setcolreg = i830fb_setcolreg,
63 .fb_blank = i830fb_blank,
64 .fb_pan_display = i830fb_pan_display,
65 .fb_fillrect = i830fb_fillrect,
66 .fb_copyarea = i830fb_copyarea,
67 .fb_imageblit = i830fb_imageblit,
68 .fb_cursor = i830fb_cursor,
69 .fb_sync = i830fb_sync,
70 .fb_ioctl = i830fb_ioctl
73 /* drivers default values */
74 static int vram __initdata = 4;
75 static int bpp __initdata = 8;
76 static int mtrr __initdata = 0;
77 static int accel __initdata = 0;
78 static int hsync1 __initdata = 0;
79 static int hsync2 __initdata = 0;
80 static int vsync1 __initdata = 0;
81 static int vsync2 __initdata = 0;
82 static int xres __initdata = 640;
83 static int yres __initdata = 480;
84 static int sync __initdata = 0;
85 static int ext_vga __initdata = 0;
90 int __init i830fb_init(void) {
101 if(agp_intel_init()) {
102 printk("i830fb_init: unable to initialize intel agpgart\n");
108 if(pci_register_driver(&i830fb_driver) > 0) return 0;
110 pci_unregister_driver(&i830fb_driver);
117 MODULE_PARAM(vram, "i");
118 MODULE_PARAM_DESC(vram, "Allocated system RAM in MB (default=4));
119 MODULE_PARAM(bpp, "i");
120 MODULE_PARAM_DESC(bpp, "Display depth in bits per pixel (default=8));
121 MODULE_PARAM(mtrr, "i");
122 MODULE_PARAM_DESC(mtrr, "Use MTRR (default=0));
123 MODULE_PARAM(accel, "i");
124 MODULE_PARAM_DESC(accel, "Use acceleration (default=0));
125 MODULE_PARAM(hsync1, "i");
126 MODULE_PARAM_DESC(hsync1, "Minimum horizontal frequency in kHz (default=29));
127 MODULE_PARAM(hsync2, "i");
128 MODULE_PARAM_DESC(hsync2, "Maximum horizontal frequency in kHz (default=30));
129 MODULE_PARAM(vsync1, "i");
130 MODULE_PARAM_DESC(vsync1, "Minimum vertical frequency in Hz (default=60));
131 MODULE_PARAM(vsync2, "i");
132 MODULE_PARAM_DESC(vsync2, "Maximum vertical frequency in Hz (default=60));
133 MODULE_PARAM(xres, "i");
134 MODULE_PARAM_DESC(xres, "Horizontal resolution in pixels (default=640));
135 MODULE_PARAM(yres, "i");
136 MODULE_PARAM_DESC(yres, "Vertical resolution in pixels (default=480));
138 MODULE_PARAM_DESC(sync, "Wait for hardware blit (default=0));
139 MODULE_PARAM(ext_vga);
140 MODULE_PARAM_DESC(ext_vga, "Enable external vga port (default=0));
142 MODULE_LICENSE("GPL");
144 static void __exit i830fb_exit(void) {
145 pci_unregister_driver(&i830fb_driver);
147 module_init(i830fb_init);
148 module_exit(i830fb_exit);
152 static int i830fb_ioctl(struct inode *inode, struct file *file,
153 unsigned int cmd, unsigned long arg,
154 struct fb_info *info) {
156 printk("i830fb_ioctl: no specific ioctl (yet)\n")
161 static int __devinit i830fb_init_pci(struct pci_dev *dev,
162 const struct pci_device_id *entry) {
164 struct fb_info *info;
165 struct i830fb_par *par;
166 int err, vfreq, hfreq, pixclock, size;
170 if(!(info = kmalloc(sizeof(struct fb_info), GFP_KERNEL))) {
171 i830fb_release_resource(info, par);
174 memset(info, 0, sizeof(struct fb_info));
176 if(!(par = kmalloc(sizeof(struct i830fb_par), GFP_KERNEL))) {
177 i830fb_release_resource(info, par);
180 memset(par, 0, sizeof(struct i830fb_par));
185 if(!(info->pixmap.addr = kmalloc(64*1024, FGP_KERNEL))) {
186 i830fb_release_resource(info, par);
189 memset(info->pixmap.addr, 0, 64*1024));
190 info->pixmap.size = 64*1024;
191 info->pixmap.buf_align = 8;
192 info->pixmap.flags = FB_PIXMAP_SYSTEM;
194 /* allocate pci resource */
195 if((err = pci_enable_device(dev))) {
196 printk("i830fb_init_pci: unable to enable device\n");
197 i830fb_release_resource(info, par);
200 par->res_flags |= PCI_DEVICE_ENABLED;
201 if(pci_resource_len(dev, 0) > 512 * 1024) {
202 par->aperture.physical = pci_resource_start(dev, 0);
203 par->aperture.size = pci_resource_len(dev, 0);
204 par->mmio.physical = pci_resource_start(dev, 1);
205 par->mmio.size = pci_resource_len(dev, 1);
208 par->aperture.physical = pci_resource_start(dev, 1);
209 par->aperture.size = pci_resource_len(dev, 1);
210 par->mmio.physical = pci_resource_start(dev, 0);
211 par->mmio.size = pci_resource_len(dev, 0);
213 if(par->mmio.size != MMIO_SIZE)
214 printk("i830fb_init_pci: warning - mmio size not 512 kB !\n");
215 if(!par->aperture.size) {
216 printk("i830fb_init_pci: unable to get resource start/len\n");
217 i830fb_release_resource(info, par);
220 if(!request_mem_region(par->aperture.physical, par->aperture.size,
221 i830_pci_list[entry->driver_data])) {
222 printk("i830fb_init_pci: unable to request fb region\n");
223 i830fb_release_resource(info, par);
226 par->res_flags |= FB_MEM_REGION_REQ;
227 if(!request_mem_region(par->mmio.physical, MMIO_SIZE,
228 i830_pci_list[entry->driver_data])) {
229 printk("i830fb_init_pci: unable to request mmio region\n");
230 i830fb_release_resource(info, par);
233 par->res_flags |= MMIO_MEM_REGION_REQ;
234 par->aperture.virtual = ioremap_nocache(par->aperture.physical,
236 if(!par->aperture.virtual) {
237 printk("i830fb_init_pci: unable to remap fb region\n");
238 i830fb_release_resource(info, par);
241 par->mmio.virtual = ioremap_nocache(par->mmio.physical, MMIO_SIZE);
242 if(!par->mmio.virtual) {
243 printk("i830fb_init_pci: unable to remap mmio region\n");
244 i830fb_release_resource(info, par);
248 /* initialize values to use */
249 // TODO: check with voffset!
252 par->dev_flags |= ACCEL;
253 info->var.accel_flags = 1;
255 if(sync) par->dev_flags |= SYNC;
257 if(bpp > 32) bpp = 32;
258 par->i830fb_ops = i830fb_ops;
259 info->var.xres = xres;
260 info->var.yres = yres;
261 info->var.bits_per_pixel = bpp;
262 if(!hsync1) hsync1 = 29000
263 if(!hsync2) hsync2 = 30000
264 if(!vsync1) vsync1 = 60
265 if(!vsync2) vsync2 = 60
266 info->monospecs.hfmax = hsync2;
267 info->monospecs.hfmin = hsync1;
268 info->monospecs.vfmax = vsync2;
269 info->monospecs.vfmin = vsync1;
270 if(hsync2 < hsync1) info->monospecs.hfmin = hsync2;
271 if(vsync2 < vsync1) info->monospecs.vfmin = vsync2;
273 /* fix offsets and allocate agp memory */
274 if(vram > ((par->aperture.size >> 20) - 1)
275 vram = (par->aperture.size >> 20) - 1;
276 // v_offset_default ? (0 here)
277 par->fb.size = vram << 20;
279 par->fb.offset >>= 12; /* what is all this devision by 4kB for? */
280 par->ring.offset = par->fb.offset + (par->fb.size >> 12);
281 par->ring.size = RINGBUF_SIZE;
282 par->cursor.offset = par->ring.offset + (RINGBUF_SIZE >> 12);
283 par->cursor.size = CURSOR_SIZE;
284 size=par->fb.size + par->ring.size;
285 if(!(par->drm_agp = (drm_agp_t *) inter_module_get("drm_agp"))) {
286 printk("i830fb_init_pci: unable to acquire agp\n");
287 i830fb_release_resource(info, par);
290 par->drm_agp->acquire();
291 if(!(par->i830_gtt.i830_fb_mem =
292 par->drm_agp->allocate_memory(size >> 12, AGP_NORMAL_MEMORY))) {
293 printk("i830fb_init_pci: unable to allocate fb memory (agp)\n");
294 par->drm_agp->release();
295 i830fb_release_resource(info, par);
298 if(par->drm_agp->bind_memory(par->i830_gtt.i830_fb_mem,
300 printk("i830fb_init_pci: unable to bind fb memory (agp)\n");
301 par->drm_agp->release();
302 i830fb_release_resource(info, par);
305 if(!(par->i830_gtt.i830_cursor_mem =
306 par->drm_agp->allocate_memory(par->cursor.size >> 12,
307 AGP_NORMAL_MEMORY))) {
308 printk("i830fb_init_pci: unable to allocate cursor mem(agp)\n");
309 par->drm_agp->release();
310 i830fb_release_resource(info, par);
313 if(par->drm_agp->bind_memory(par->i830_gtt.i830_cursor_mem,
314 par->cursor.offset)) {
315 printk("i830fb_init_pci: unable to bind cursor mem (agp)\n");
316 par->drm_agp->release();
317 i830fb_release_resource(info, par);
320 par->cursor.physical = par->i830_gtt.i830_cursor_mem->physical;
321 par->fb.physical = par->aperture.physical + (par->fb.offset << 12);