added main files (not finished)
[my-code/i830.git] / i830.c
1 /*
2  *      linux/drivers/video/i830/i830.c
3  *      -- Intel 830 framebuffer device
4  *
5  *      Copyright (C) 2004 Frank Zirkelbach <hackbard@hackdaworld.dyndns.org>
6  *      All Rights Reserved
7  *
8  *      Code based on vfb.c (Geert Uytterhoeven), i810fb (Tony Daplas),
9  *      xorg i830 drivers and intelfb (David Dawes).
10  *
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.
13  *
14  */
15
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>
21 #include <linux/mm.h>
22 #include <linux/tty.h>
23 #include <linux/slab.h>
24 #include <linux/fb.h>
25 #include <linux/init.h>
26 #include <linux/pci.h>
27 #include <linux/resource.h>
28 #include <linux/unistd.h>
29 #include <asm/io.h>
30 #include <asm/div64.h>
31 #include <asm/page.h>
32
33 #ifdef CONFIG_MTRR
34 #include <asm/mtrr.h>
35 #endif
36
37 #include "i830_regs.h"
38 #include "i830.h"
39
40 static const char *i830_pci_list[] __devinitdata = {
41         "Intel(R) 830 Chipset Graphics Controller Framebuffer Device"
42 };
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 },
46         { 0 }
47 };
48 satic struct pci_driver i830fb_driver = {
49         .name           =       "i830fb",
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
55 };
56 static struct fb_ops i830fb_ops __devinitdata = {
57         .owner          =       THIS_MODULE,
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
71 };
72
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;
86
87
88
89
90 int __init i830fb_init(void) {
91
92 #ifdef MODULE
93
94         hsync1 *= 1000;
95         hsync2 *= 1000;
96
97 #endif
98
99 #ifndef MODULE
100
101         if(agp_intel_init()) {
102                 printk("i830fb_init: unable to initialize intel agpgart\n");
103                 return -ENODEV;
104         }
105
106 #endif
107
108         if(pci_register_driver(&i830fb_driver) > 0) return 0;
109
110         pci_unregister_driver(&i830fb_driver);
111
112         return -ENODEV;
113 }
114
115 #ifdef MODULE
116
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));
137 MODULE_PARAM(sync);
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));
141
142 MODULE_LICENSE("GPL");
143
144 static void __exit i830fb_exit(void) {
145         pci_unregister_driver(&i830fb_driver);
146 }
147 module_init(i830fb_init);
148 module_exit(i830fb_exit);
149
150 #endif
151
152 static int i830fb_ioctl(struct inode *inode, struct file *file,
153                         unsigned int cmd, unsigned long arg,
154                         struct fb_info *info) {
155
156                 printk("i830fb_ioctl: no specific ioctl (yet)\n")
157                 return -EINVAL;
158
159 }
160
161 static int __devinit i830fb_init_pci(struct pci_dev *dev,
162                                         const struct pci_device_id *entry) {
163
164         struct fb_info *info;
165         struct i830fb_par *par;
166         int err, vfreq, hfreq, pixclock, size;
167
168         par = NULL;
169
170         if(!(info = kmalloc(sizeof(struct fb_info), GFP_KERNEL))) {
171                 i830fb_release_resource(info, par);
172                 return -ENOMEM;
173         }
174         memset(info, 0, sizeof(struct fb_info));
175
176         if(!(par = kmalloc(sizeof(struct i830fb_par), GFP_KERNEL))) {
177                 i830fb_release_resource(info, par);
178                 return -ENOMEM;
179         }
180         memset(par, 0, sizeof(struct i830fb_par));
181
182         par->dev = dev;
183         info->par = par;
184
185         if(!(info->pixmap.addr = kmalloc(64*1024, FGP_KERNEL))) {
186                 i830fb_release_resource(info, par);
187                 return -ENOMEM;
188         }
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;
193
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);
198                 return err;
199         }
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);
206         }
207         else {
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);
212         }
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);
218                 return -ENOMEM;
219         }
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);
224                 return -ENODEV;
225         }
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);
231                 return -ENODEV;
232         }
233         par->res_flags |= MMIO_MEM_REGION_REQ;
234         par->aperture.virtual = ioremap_nocache(par->aperture.physical,
235                                                         par->aperture.size);
236         if(!par->aperture.virtual) {
237                 printk("i830fb_init_pci: unable to remap fb region\n");
238                 i830fb_release_resource(info, par);
239                 return -ENODEV;
240         }
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);
245                 return -ENODEV;
246         }
247
248         /* initialize values to use */
249         // TODO: check with voffset!
250         if(!vram) vram=1;
251         if(accel) {
252                 par->dev_flags |= ACCEL;
253                 info->var.accel_flags = 1;
254         }
255         if(sync) par->dev_flags |= SYNC;
256         if(bpp < 8) bpp = 8;
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;
272
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;
278         par->fb.offset = 0;
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);
288                 return -ENODEV;
289         }
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);
296                 return -ENOMEM;
297         }
298         if(par->drm_agp->bind_memory(par->i830_gtt.i830_fb_mem,
299                                         par->fb.offset)) {
300                 printk("i830fb_init_pci: unable to bind fb memory (agp)\n");
301                 par->drm_agp->release();
302                 i830fb_release_resource(info, par);
303                 return -EBUSY;
304         }
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);
311                 return -ENOMEM;
312         }
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);
318                 return -EBUSY;
319         }
320         par->cursor.physical = par->i830_gtt.i830_cursor_mem->physical;
321         par->fb.physical = par->aperture.physical + (par->fb.offset << 12);
322
323                 
324
325