0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110 #include <linux/module.h>
0111 #include <linux/kernel.h>
0112 #include <linux/errno.h>
0113 #include <linux/string.h>
0114 #include <linux/mm.h>
0115 #include <linux/slab.h>
0116 #include <linux/delay.h>
0117 #include <linux/fb.h>
0118 #include <linux/ioport.h>
0119 #include <linux/init.h>
0120 #include <linux/pci.h>
0121 #include <linux/vmalloc.h>
0122 #include <linux/pagemap.h>
0123 #include <linux/screen_info.h>
0124
0125 #include <asm/io.h>
0126
0127 #include "intelfb.h"
0128 #include "intelfbhw.h"
0129 #include "../edid.h"
0130
0131 static void get_initial_mode(struct intelfb_info *dinfo);
0132 static void update_dinfo(struct intelfb_info *dinfo,
0133 struct fb_var_screeninfo *var);
0134 static int intelfb_open(struct fb_info *info, int user);
0135 static int intelfb_release(struct fb_info *info, int user);
0136 static int intelfb_check_var(struct fb_var_screeninfo *var,
0137 struct fb_info *info);
0138 static int intelfb_set_par(struct fb_info *info);
0139 static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
0140 unsigned blue, unsigned transp,
0141 struct fb_info *info);
0142
0143 static int intelfb_blank(int blank, struct fb_info *info);
0144 static int intelfb_pan_display(struct fb_var_screeninfo *var,
0145 struct fb_info *info);
0146
0147 static void intelfb_fillrect(struct fb_info *info,
0148 const struct fb_fillrect *rect);
0149 static void intelfb_copyarea(struct fb_info *info,
0150 const struct fb_copyarea *region);
0151 static void intelfb_imageblit(struct fb_info *info,
0152 const struct fb_image *image);
0153 static int intelfb_cursor(struct fb_info *info,
0154 struct fb_cursor *cursor);
0155
0156 static int intelfb_sync(struct fb_info *info);
0157
0158 static int intelfb_ioctl(struct fb_info *info,
0159 unsigned int cmd, unsigned long arg);
0160
0161 static int intelfb_pci_register(struct pci_dev *pdev,
0162 const struct pci_device_id *ent);
0163 static void intelfb_pci_unregister(struct pci_dev *pdev);
0164 static int intelfb_set_fbinfo(struct intelfb_info *dinfo);
0165
0166
0167
0168
0169
0170 #if DETECT_VGA_CLASS_ONLY
0171 #define INTELFB_CLASS_MASK ~0 << 8
0172 #else
0173 #define INTELFB_CLASS_MASK 0
0174 #endif
0175
0176 static const struct pci_device_id intelfb_pci_table[] = {
0177 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_830M, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_830M },
0178 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_845G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_845G },
0179 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_85XGM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_85XGM },
0180 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_865G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_865G },
0181 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_854, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_854 },
0182 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915G },
0183 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM },
0184 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945G },
0185 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GM },
0186 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GME, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GME },
0187 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965G },
0188 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965GM },
0189 { 0, }
0190 };
0191
0192
0193 static int num_registered = 0;
0194
0195
0196 static const struct fb_ops intel_fb_ops = {
0197 .owner = THIS_MODULE,
0198 .fb_open = intelfb_open,
0199 .fb_release = intelfb_release,
0200 .fb_check_var = intelfb_check_var,
0201 .fb_set_par = intelfb_set_par,
0202 .fb_setcolreg = intelfb_setcolreg,
0203 .fb_blank = intelfb_blank,
0204 .fb_pan_display = intelfb_pan_display,
0205 .fb_fillrect = intelfb_fillrect,
0206 .fb_copyarea = intelfb_copyarea,
0207 .fb_imageblit = intelfb_imageblit,
0208 .fb_cursor = intelfb_cursor,
0209 .fb_sync = intelfb_sync,
0210 .fb_ioctl = intelfb_ioctl
0211 };
0212
0213
0214 static struct pci_driver intelfb_driver = {
0215 .name = "intelfb",
0216 .id_table = intelfb_pci_table,
0217 .probe = intelfb_pci_register,
0218 .remove = intelfb_pci_unregister,
0219 };
0220
0221
0222 MODULE_AUTHOR("David Dawes <dawes@tungstengraphics.com>, "
0223 "Sylvain Meyer <sylvain.meyer@worldonline.fr>");
0224 MODULE_DESCRIPTION("Framebuffer driver for Intel(R) " SUPPORTED_CHIPSETS
0225 " chipsets");
0226 MODULE_LICENSE("Dual BSD/GPL");
0227 MODULE_DEVICE_TABLE(pci, intelfb_pci_table);
0228
0229 static bool accel = 1;
0230 static int vram = 4;
0231 static bool hwcursor = 0;
0232 static bool mtrr = 1;
0233 static bool fixed = 0;
0234 static bool noinit = 0;
0235 static bool noregister = 0;
0236 static bool probeonly = 0;
0237 static bool idonly = 0;
0238 static int bailearly = 0;
0239 static int voffset = 48;
0240 static char *mode = NULL;
0241
0242 module_param(accel, bool, S_IRUGO);
0243 MODULE_PARM_DESC(accel, "Enable hardware acceleration");
0244 module_param(vram, int, S_IRUGO);
0245 MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB");
0246 module_param(voffset, int, S_IRUGO);
0247 MODULE_PARM_DESC(voffset, "Offset of framebuffer in MiB");
0248 module_param(hwcursor, bool, S_IRUGO);
0249 MODULE_PARM_DESC(hwcursor, "Enable HW cursor");
0250 module_param(mtrr, bool, S_IRUGO);
0251 MODULE_PARM_DESC(mtrr, "Enable MTRR support");
0252 module_param(fixed, bool, S_IRUGO);
0253 MODULE_PARM_DESC(fixed, "Disable mode switching");
0254 module_param(noinit, bool, 0);
0255 MODULE_PARM_DESC(noinit, "Don't initialise graphics mode when loading");
0256 module_param(noregister, bool, 0);
0257 MODULE_PARM_DESC(noregister, "Don't register, just probe and exit (debug)");
0258 module_param(probeonly, bool, 0);
0259 MODULE_PARM_DESC(probeonly, "Do a minimal probe (debug)");
0260 module_param(idonly, bool, 0);
0261 MODULE_PARM_DESC(idonly, "Just identify without doing anything else (debug)");
0262 module_param(bailearly, int, 0);
0263 MODULE_PARM_DESC(bailearly, "Bail out early, depending on value (debug)");
0264 module_param(mode, charp, S_IRUGO);
0265 MODULE_PARM_DESC(mode,
0266 "Initial video mode \"<xres>x<yres>[-<depth>][@<refresh>]\"");
0267
0268 #ifndef MODULE
0269 #define OPT_EQUAL(opt, name) (!strncmp(opt, name, strlen(name)))
0270 #define OPT_INTVAL(opt, name) simple_strtoul(opt + strlen(name) + 1, NULL, 0)
0271 #define OPT_STRVAL(opt, name) (opt + strlen(name))
0272
0273 static __inline__ char * get_opt_string(const char *this_opt, const char *name)
0274 {
0275 const char *p;
0276 int i;
0277 char *ret;
0278
0279 p = OPT_STRVAL(this_opt, name);
0280 i = 0;
0281 while (p[i] && p[i] != ' ' && p[i] != ',')
0282 i++;
0283 ret = kmalloc(i + 1, GFP_KERNEL);
0284 if (ret) {
0285 strncpy(ret, p, i);
0286 ret[i] = '\0';
0287 }
0288 return ret;
0289 }
0290
0291 static __inline__ int get_opt_int(const char *this_opt, const char *name,
0292 int *ret)
0293 {
0294 if (!ret)
0295 return 0;
0296
0297 if (!OPT_EQUAL(this_opt, name))
0298 return 0;
0299
0300 *ret = OPT_INTVAL(this_opt, name);
0301 return 1;
0302 }
0303
0304 static __inline__ int get_opt_bool(const char *this_opt, const char *name,
0305 bool *ret)
0306 {
0307 if (!ret)
0308 return 0;
0309
0310 if (OPT_EQUAL(this_opt, name)) {
0311 if (this_opt[strlen(name)] == '=')
0312 *ret = simple_strtoul(this_opt + strlen(name) + 1,
0313 NULL, 0);
0314 else
0315 *ret = 1;
0316 } else {
0317 if (OPT_EQUAL(this_opt, "no") && OPT_EQUAL(this_opt + 2, name))
0318 *ret = 0;
0319 else
0320 return 0;
0321 }
0322 return 1;
0323 }
0324
0325 static int __init intelfb_setup(char *options)
0326 {
0327 char *this_opt;
0328
0329 DBG_MSG("intelfb_setup\n");
0330
0331 if (!options || !*options) {
0332 DBG_MSG("no options\n");
0333 return 0;
0334 } else
0335 DBG_MSG("options: %s\n", options);
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350 while ((this_opt = strsep(&options, ","))) {
0351 if (!*this_opt)
0352 continue;
0353 if (get_opt_bool(this_opt, "accel", &accel))
0354 ;
0355 else if (get_opt_int(this_opt, "vram", &vram))
0356 ;
0357 else if (get_opt_bool(this_opt, "hwcursor", &hwcursor))
0358 ;
0359 else if (get_opt_bool(this_opt, "mtrr", &mtrr))
0360 ;
0361 else if (get_opt_bool(this_opt, "fixed", &fixed))
0362 ;
0363 else if (get_opt_bool(this_opt, "init", &noinit))
0364 noinit = !noinit;
0365 else if (OPT_EQUAL(this_opt, "mode="))
0366 mode = get_opt_string(this_opt, "mode=");
0367 else
0368 mode = this_opt;
0369 }
0370
0371 return 0;
0372 }
0373
0374 #endif
0375
0376 static int __init intelfb_init(void)
0377 {
0378 #ifndef MODULE
0379 char *option = NULL;
0380 #endif
0381
0382 DBG_MSG("intelfb_init\n");
0383
0384 INF_MSG("Framebuffer driver for "
0385 "Intel(R) " SUPPORTED_CHIPSETS " chipsets\n");
0386 INF_MSG("Version " INTELFB_VERSION "\n");
0387
0388 if (idonly)
0389 return -ENODEV;
0390
0391 #ifndef MODULE
0392 if (fb_get_options("intelfb", &option))
0393 return -ENODEV;
0394 intelfb_setup(option);
0395 #endif
0396
0397 return pci_register_driver(&intelfb_driver);
0398 }
0399
0400 static void __exit intelfb_exit(void)
0401 {
0402 DBG_MSG("intelfb_exit\n");
0403 pci_unregister_driver(&intelfb_driver);
0404 }
0405
0406 module_init(intelfb_init);
0407 module_exit(intelfb_exit);
0408
0409
0410
0411
0412
0413 static void cleanup(struct intelfb_info *dinfo)
0414 {
0415 DBG_MSG("cleanup\n");
0416
0417 if (!dinfo)
0418 return;
0419
0420 intelfbhw_disable_irq(dinfo);
0421
0422 fb_dealloc_cmap(&dinfo->info->cmap);
0423 kfree(dinfo->info->pixmap.addr);
0424
0425 if (dinfo->registered)
0426 unregister_framebuffer(dinfo->info);
0427
0428 arch_phys_wc_del(dinfo->wc_cookie);
0429
0430 if (dinfo->fbmem_gart && dinfo->gtt_fb_mem) {
0431 agp_unbind_memory(dinfo->gtt_fb_mem);
0432 agp_free_memory(dinfo->gtt_fb_mem);
0433 }
0434 if (dinfo->gtt_cursor_mem) {
0435 agp_unbind_memory(dinfo->gtt_cursor_mem);
0436 agp_free_memory(dinfo->gtt_cursor_mem);
0437 }
0438 if (dinfo->gtt_ring_mem) {
0439 agp_unbind_memory(dinfo->gtt_ring_mem);
0440 agp_free_memory(dinfo->gtt_ring_mem);
0441 }
0442
0443 #ifdef CONFIG_FB_INTEL_I2C
0444
0445 intelfb_delete_i2c_busses(dinfo);
0446 #endif
0447
0448 if (dinfo->mmio_base)
0449 iounmap((void __iomem *)dinfo->mmio_base);
0450 if (dinfo->aperture.virtual)
0451 iounmap((void __iomem *)dinfo->aperture.virtual);
0452
0453 if (dinfo->flag & INTELFB_MMIO_ACQUIRED)
0454 release_mem_region(dinfo->mmio_base_phys, INTEL_REG_SIZE);
0455 if (dinfo->flag & INTELFB_FB_ACQUIRED)
0456 release_mem_region(dinfo->aperture.physical,
0457 dinfo->aperture.size);
0458 framebuffer_release(dinfo->info);
0459 }
0460
0461 #define bailout(dinfo) do { \
0462 DBG_MSG("bailout\n"); \
0463 cleanup(dinfo); \
0464 INF_MSG("Not going to register framebuffer, exiting...\n"); \
0465 return -ENODEV; \
0466 } while (0)
0467
0468
0469 static int intelfb_pci_register(struct pci_dev *pdev,
0470 const struct pci_device_id *ent)
0471 {
0472 struct fb_info *info;
0473 struct intelfb_info *dinfo;
0474 int i, err, dvo;
0475 int aperture_size, stolen_size = 0;
0476 struct agp_kern_info gtt_info;
0477 int agp_memtype;
0478 const char *s;
0479 struct agp_bridge_data *bridge;
0480 int aperture_bar = 0;
0481 int mmio_bar = 1;
0482 int offset;
0483
0484 DBG_MSG("intelfb_pci_register\n");
0485
0486 num_registered++;
0487 if (num_registered != 1) {
0488 ERR_MSG("Attempted to register %d devices "
0489 "(should be only 1).\n", num_registered);
0490 return -ENODEV;
0491 }
0492
0493 info = framebuffer_alloc(sizeof(struct intelfb_info), &pdev->dev);
0494 if (!info)
0495 return -ENOMEM;
0496
0497 if (fb_alloc_cmap(&info->cmap, 256, 1) < 0) {
0498 ERR_MSG("Could not allocate cmap for intelfb_info.\n");
0499 goto err_out_cmap;
0500 }
0501
0502 dinfo = info->par;
0503 dinfo->info = info;
0504 dinfo->fbops = &intel_fb_ops;
0505 dinfo->pdev = pdev;
0506
0507
0508 info->pixmap.addr = kzalloc(64 * 1024, GFP_KERNEL);
0509 if (info->pixmap.addr == NULL) {
0510 ERR_MSG("Cannot reserve pixmap memory.\n");
0511 goto err_out_pixmap;
0512 }
0513
0514
0515
0516 dinfo->fixed_mode = fixed;
0517
0518
0519 if ((err = pci_enable_device(pdev))) {
0520 ERR_MSG("Cannot enable device.\n");
0521 cleanup(dinfo);
0522 return -ENODEV;
0523 }
0524
0525
0526 if ((ent->device == PCI_DEVICE_ID_INTEL_915G) ||
0527 (ent->device == PCI_DEVICE_ID_INTEL_915GM) ||
0528 (ent->device == PCI_DEVICE_ID_INTEL_945G) ||
0529 (ent->device == PCI_DEVICE_ID_INTEL_945GM) ||
0530 (ent->device == PCI_DEVICE_ID_INTEL_945GME) ||
0531 (ent->device == PCI_DEVICE_ID_INTEL_965G) ||
0532 (ent->device == PCI_DEVICE_ID_INTEL_965GM)) {
0533
0534 aperture_bar = 2;
0535 mmio_bar = 0;
0536 }
0537 dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar);
0538 dinfo->aperture.size = pci_resource_len(pdev, aperture_bar);
0539 dinfo->mmio_base_phys = pci_resource_start(pdev, mmio_bar);
0540 DBG_MSG("fb aperture: 0x%llx/0x%llx, MMIO region: 0x%llx/0x%llx\n",
0541 (unsigned long long)pci_resource_start(pdev, aperture_bar),
0542 (unsigned long long)pci_resource_len(pdev, aperture_bar),
0543 (unsigned long long)pci_resource_start(pdev, mmio_bar),
0544 (unsigned long long)pci_resource_len(pdev, mmio_bar));
0545
0546
0547 if (!request_mem_region(dinfo->aperture.physical, dinfo->aperture.size,
0548 INTELFB_MODULE_NAME)) {
0549 ERR_MSG("Cannot reserve FB region.\n");
0550 cleanup(dinfo);
0551 return -ENODEV;
0552 }
0553
0554 dinfo->flag |= INTELFB_FB_ACQUIRED;
0555
0556 if (!request_mem_region(dinfo->mmio_base_phys,
0557 INTEL_REG_SIZE,
0558 INTELFB_MODULE_NAME)) {
0559 ERR_MSG("Cannot reserve MMIO region.\n");
0560 cleanup(dinfo);
0561 return -ENODEV;
0562 }
0563
0564 dinfo->flag |= INTELFB_MMIO_ACQUIRED;
0565
0566
0567 dinfo->pci_chipset = pdev->device;
0568
0569 if (intelfbhw_get_chipset(pdev, dinfo)) {
0570 cleanup(dinfo);
0571 return -ENODEV;
0572 }
0573
0574 if (intelfbhw_get_memory(pdev, &aperture_size, &stolen_size)) {
0575 cleanup(dinfo);
0576 return -ENODEV;
0577 }
0578
0579 INF_MSG("%02x:%02x.%d: %s, aperture size %dMB, "
0580 "stolen memory %dkB\n",
0581 pdev->bus->number, PCI_SLOT(pdev->devfn),
0582 PCI_FUNC(pdev->devfn), dinfo->name,
0583 BtoMB(aperture_size), BtoKB(stolen_size));
0584
0585
0586 dinfo->accel = accel;
0587 dinfo->hwcursor = hwcursor;
0588
0589 if (NOACCEL_CHIPSET(dinfo) && dinfo->accel == 1) {
0590 INF_MSG("Acceleration is not supported for the %s chipset.\n",
0591 dinfo->name);
0592 dinfo->accel = 0;
0593 }
0594
0595
0596 if (ROUND_UP_TO_PAGE(stolen_size) >= MB(vram)) {
0597 dinfo->fb.size = ROUND_UP_TO_PAGE(stolen_size);
0598 dinfo->fbmem_gart = 0;
0599 } else {
0600 dinfo->fb.size = MB(vram);
0601 dinfo->fbmem_gart = 1;
0602 }
0603
0604
0605 if (dinfo->accel) {
0606 dinfo->ring.size = RINGBUFFER_SIZE;
0607 dinfo->ring_tail_mask = dinfo->ring.size - 1;
0608 }
0609 if (dinfo->hwcursor)
0610 dinfo->cursor.size = HW_CURSOR_SIZE;
0611
0612
0613 if (!(bridge = agp_backend_acquire(pdev))) {
0614 ERR_MSG("cannot acquire agp\n");
0615 cleanup(dinfo);
0616 return -ENODEV;
0617 }
0618
0619
0620 if (agp_copy_info(bridge, >t_info)) {
0621 ERR_MSG("cannot get agp info\n");
0622 agp_backend_release(bridge);
0623 cleanup(dinfo);
0624 return -ENODEV;
0625 }
0626
0627 if (MB(voffset) < stolen_size)
0628 offset = (stolen_size >> 12);
0629 else
0630 offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE;
0631
0632
0633 if (dinfo->accel)
0634 dinfo->ring.offset = offset + gtt_info.current_memory;
0635 if (dinfo->hwcursor)
0636 dinfo->cursor.offset = offset +
0637 + gtt_info.current_memory + (dinfo->ring.size >> 12);
0638 if (dinfo->fbmem_gart)
0639 dinfo->fb.offset = offset +
0640 + gtt_info.current_memory + (dinfo->ring.size >> 12)
0641 + (dinfo->cursor.size >> 12);
0642
0643
0644
0645
0646 dinfo->aperture.virtual = (u8 __iomem *)ioremap_wc
0647 (dinfo->aperture.physical, ((offset + dinfo->fb.offset) << 12)
0648 + dinfo->fb.size);
0649 if (!dinfo->aperture.virtual) {
0650 ERR_MSG("Cannot remap FB region.\n");
0651 agp_backend_release(bridge);
0652 cleanup(dinfo);
0653 return -ENODEV;
0654 }
0655
0656 dinfo->mmio_base =
0657 (u8 __iomem *)ioremap(dinfo->mmio_base_phys,
0658 INTEL_REG_SIZE);
0659 if (!dinfo->mmio_base) {
0660 ERR_MSG("Cannot remap MMIO region.\n");
0661 agp_backend_release(bridge);
0662 cleanup(dinfo);
0663 return -ENODEV;
0664 }
0665
0666 if (dinfo->accel) {
0667 if (!(dinfo->gtt_ring_mem =
0668 agp_allocate_memory(bridge, dinfo->ring.size >> 12,
0669 AGP_NORMAL_MEMORY))) {
0670 ERR_MSG("cannot allocate ring buffer memory\n");
0671 agp_backend_release(bridge);
0672 cleanup(dinfo);
0673 return -ENOMEM;
0674 }
0675 if (agp_bind_memory(dinfo->gtt_ring_mem,
0676 dinfo->ring.offset)) {
0677 ERR_MSG("cannot bind ring buffer memory\n");
0678 agp_backend_release(bridge);
0679 cleanup(dinfo);
0680 return -EBUSY;
0681 }
0682 dinfo->ring.physical = dinfo->aperture.physical
0683 + (dinfo->ring.offset << 12);
0684 dinfo->ring.virtual = dinfo->aperture.virtual
0685 + (dinfo->ring.offset << 12);
0686 dinfo->ring_head = 0;
0687 }
0688 if (dinfo->hwcursor) {
0689 agp_memtype = dinfo->mobile ? AGP_PHYSICAL_MEMORY
0690 : AGP_NORMAL_MEMORY;
0691 if (!(dinfo->gtt_cursor_mem =
0692 agp_allocate_memory(bridge, dinfo->cursor.size >> 12,
0693 agp_memtype))) {
0694 ERR_MSG("cannot allocate cursor memory\n");
0695 agp_backend_release(bridge);
0696 cleanup(dinfo);
0697 return -ENOMEM;
0698 }
0699 if (agp_bind_memory(dinfo->gtt_cursor_mem,
0700 dinfo->cursor.offset)) {
0701 ERR_MSG("cannot bind cursor memory\n");
0702 agp_backend_release(bridge);
0703 cleanup(dinfo);
0704 return -EBUSY;
0705 }
0706 if (dinfo->mobile)
0707 dinfo->cursor.physical
0708 = dinfo->gtt_cursor_mem->physical;
0709 else
0710 dinfo->cursor.physical = dinfo->aperture.physical
0711 + (dinfo->cursor.offset << 12);
0712 dinfo->cursor.virtual = dinfo->aperture.virtual
0713 + (dinfo->cursor.offset << 12);
0714 }
0715 if (dinfo->fbmem_gart) {
0716 if (!(dinfo->gtt_fb_mem =
0717 agp_allocate_memory(bridge, dinfo->fb.size >> 12,
0718 AGP_NORMAL_MEMORY))) {
0719 WRN_MSG("cannot allocate framebuffer memory - use "
0720 "the stolen one\n");
0721 dinfo->fbmem_gart = 0;
0722 }
0723 if (agp_bind_memory(dinfo->gtt_fb_mem,
0724 dinfo->fb.offset)) {
0725 WRN_MSG("cannot bind framebuffer memory - use "
0726 "the stolen one\n");
0727 dinfo->fbmem_gart = 0;
0728 }
0729 }
0730
0731
0732 if (!dinfo->fbmem_gart)
0733 dinfo->fb.offset = 0;
0734 dinfo->fb.physical = dinfo->aperture.physical
0735 + (dinfo->fb.offset << 12);
0736 dinfo->fb.virtual = dinfo->aperture.virtual + (dinfo->fb.offset << 12);
0737 dinfo->fb_start = dinfo->fb.offset << 12;
0738
0739
0740 agp_backend_release(bridge);
0741
0742 if (mtrr)
0743 dinfo->wc_cookie = arch_phys_wc_add(dinfo->aperture.physical,
0744 dinfo->aperture.size);
0745
0746 DBG_MSG("fb: 0x%x(+ 0x%x)/0x%x (0x%p)\n",
0747 dinfo->fb.physical, dinfo->fb.offset, dinfo->fb.size,
0748 dinfo->fb.virtual);
0749 DBG_MSG("MMIO: 0x%x/0x%x (0x%p)\n",
0750 dinfo->mmio_base_phys, INTEL_REG_SIZE,
0751 dinfo->mmio_base);
0752 DBG_MSG("ring buffer: 0x%x/0x%x (0x%p)\n",
0753 dinfo->ring.physical, dinfo->ring.size,
0754 dinfo->ring.virtual);
0755 DBG_MSG("HW cursor: 0x%x/0x%x (0x%p) (offset 0x%x) (phys 0x%x)\n",
0756 dinfo->cursor.physical, dinfo->cursor.size,
0757 dinfo->cursor.virtual, dinfo->cursor.offset,
0758 dinfo->cursor.physical);
0759
0760 DBG_MSG("options: vram = %d, accel = %d, hwcursor = %d, fixed = %d, "
0761 "noinit = %d\n", vram, accel, hwcursor, fixed, noinit);
0762 DBG_MSG("options: mode = \"%s\"\n", mode ? mode : "");
0763
0764 if (probeonly)
0765 bailout(dinfo);
0766
0767
0768
0769
0770
0771 dvo = intelfbhw_check_non_crt(dinfo);
0772 if (dvo) {
0773 dinfo->fixed_mode = 1;
0774 WRN_MSG("Non-CRT device is enabled ( ");
0775 i = 0;
0776 while (dvo) {
0777 if (dvo & 1) {
0778 s = intelfbhw_dvo_to_string(1 << i);
0779 if (s)
0780 printk("%s ", s);
0781 }
0782 dvo >>= 1;
0783 ++i;
0784 }
0785 printk("). Disabling mode switching.\n");
0786 }
0787
0788 if (bailearly == 1)
0789 bailout(dinfo);
0790
0791 if (FIXED_MODE(dinfo) &&
0792 screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) {
0793 ERR_MSG("Video mode must be programmed at boot time.\n");
0794 cleanup(dinfo);
0795 return -ENODEV;
0796 }
0797
0798 if (bailearly == 2)
0799 bailout(dinfo);
0800
0801
0802
0803 if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB)
0804 get_initial_mode(dinfo);
0805
0806 if (bailearly == 3)
0807 bailout(dinfo);
0808
0809 if (FIXED_MODE(dinfo))
0810 update_dinfo(dinfo, &dinfo->initial_var);
0811
0812 if (bailearly == 4)
0813 bailout(dinfo);
0814
0815
0816 if (intelfb_set_fbinfo(dinfo)) {
0817 cleanup(dinfo);
0818 return -ENODEV;
0819 }
0820
0821 if (bailearly == 5)
0822 bailout(dinfo);
0823
0824 #ifdef CONFIG_FB_INTEL_I2C
0825
0826 intelfb_create_i2c_busses(dinfo);
0827 #endif
0828
0829 if (bailearly == 6)
0830 bailout(dinfo);
0831
0832 pci_set_drvdata(pdev, dinfo);
0833
0834
0835 i = intelfbhw_read_hw_state(dinfo, &dinfo->save_state,
0836 bailearly > 6 ? bailearly - 6 : 0);
0837 if (i != 0) {
0838 DBG_MSG("intelfbhw_read_hw_state returned %d\n", i);
0839 bailout(dinfo);
0840 }
0841
0842 intelfbhw_print_hw_state(dinfo, &dinfo->save_state);
0843
0844 if (bailearly == 18)
0845 bailout(dinfo);
0846
0847
0848 dinfo->pipe = intelfbhw_active_pipe(&dinfo->save_state);
0849
0850
0851 if (dinfo->hwcursor) {
0852 intelfbhw_cursor_init(dinfo);
0853 intelfbhw_cursor_reset(dinfo);
0854 }
0855
0856 if (bailearly == 19)
0857 bailout(dinfo);
0858
0859
0860 if (dinfo->accel)
0861 intelfbhw_2d_start(dinfo);
0862
0863 if (bailearly == 20)
0864 bailout(dinfo);
0865
0866 if (noregister)
0867 bailout(dinfo);
0868
0869 if (register_framebuffer(dinfo->info) < 0) {
0870 ERR_MSG("Cannot register framebuffer.\n");
0871 cleanup(dinfo);
0872 return -ENODEV;
0873 }
0874
0875 dinfo->registered = 1;
0876 dinfo->open = 0;
0877
0878 init_waitqueue_head(&dinfo->vsync.wait);
0879 spin_lock_init(&dinfo->int_lock);
0880 dinfo->irq_flags = 0;
0881 dinfo->vsync.pan_display = 0;
0882 dinfo->vsync.pan_offset = 0;
0883
0884 return 0;
0885
0886 err_out_pixmap:
0887 fb_dealloc_cmap(&info->cmap);
0888 err_out_cmap:
0889 framebuffer_release(info);
0890 return -ENODEV;
0891 }
0892
0893 static void intelfb_pci_unregister(struct pci_dev *pdev)
0894 {
0895 struct intelfb_info *dinfo = pci_get_drvdata(pdev);
0896
0897 DBG_MSG("intelfb_pci_unregister\n");
0898
0899 if (!dinfo)
0900 return;
0901
0902 cleanup(dinfo);
0903 }
0904
0905
0906
0907
0908
0909 __inline__ int intelfb_var_to_depth(const struct fb_var_screeninfo *var)
0910 {
0911 DBG_MSG("intelfb_var_to_depth: bpp: %d, green.length is %d\n",
0912 var->bits_per_pixel, var->green.length);
0913
0914 switch (var->bits_per_pixel) {
0915 case 16:
0916 return (var->green.length == 6) ? 16 : 15;
0917 case 32:
0918 return 24;
0919 default:
0920 return var->bits_per_pixel;
0921 }
0922 }
0923
0924
0925 static __inline__ int var_to_refresh(const struct fb_var_screeninfo *var)
0926 {
0927 int xtot = var->xres + var->left_margin + var->right_margin +
0928 var->hsync_len;
0929 int ytot = var->yres + var->upper_margin + var->lower_margin +
0930 var->vsync_len;
0931
0932 return (1000000000 / var->pixclock * 1000 + 500) / xtot / ytot;
0933 }
0934
0935
0936
0937
0938
0939 static void get_initial_mode(struct intelfb_info *dinfo)
0940 {
0941 struct fb_var_screeninfo *var;
0942 int xtot, ytot;
0943
0944 DBG_MSG("get_initial_mode\n");
0945
0946 dinfo->initial_vga = 1;
0947 dinfo->initial_fb_base = screen_info.lfb_base;
0948 dinfo->initial_video_ram = screen_info.lfb_size * KB(64);
0949 dinfo->initial_pitch = screen_info.lfb_linelength;
0950
0951 var = &dinfo->initial_var;
0952 memset(var, 0, sizeof(*var));
0953 var->xres = screen_info.lfb_width;
0954 var->yres = screen_info.lfb_height;
0955 var->bits_per_pixel = screen_info.lfb_depth;
0956 switch (screen_info.lfb_depth) {
0957 case 15:
0958 var->bits_per_pixel = 16;
0959 break;
0960 case 24:
0961 var->bits_per_pixel = 32;
0962 break;
0963 }
0964
0965 DBG_MSG("Initial info: FB is 0x%x/0x%x (%d kByte)\n",
0966 dinfo->initial_fb_base, dinfo->initial_video_ram,
0967 BtoKB(dinfo->initial_video_ram));
0968
0969 DBG_MSG("Initial info: mode is %dx%d-%d (%d)\n",
0970 var->xres, var->yres, var->bits_per_pixel,
0971 dinfo->initial_pitch);
0972
0973
0974 var->left_margin = (var->xres / 8) & 0xf8;
0975 var->right_margin = 32;
0976 var->upper_margin = 16;
0977 var->lower_margin = 4;
0978 var->hsync_len = (var->xres / 8) & 0xf8;
0979 var->vsync_len = 4;
0980
0981 xtot = var->xres + var->left_margin +
0982 var->right_margin + var->hsync_len;
0983 ytot = var->yres + var->upper_margin +
0984 var->lower_margin + var->vsync_len;
0985 var->pixclock = 10000000 / xtot * 1000 / ytot * 100 / 60;
0986
0987 var->height = -1;
0988 var->width = -1;
0989
0990 if (var->bits_per_pixel > 8) {
0991 var->red.offset = screen_info.red_pos;
0992 var->red.length = screen_info.red_size;
0993 var->green.offset = screen_info.green_pos;
0994 var->green.length = screen_info.green_size;
0995 var->blue.offset = screen_info.blue_pos;
0996 var->blue.length = screen_info.blue_size;
0997 var->transp.offset = screen_info.rsvd_pos;
0998 var->transp.length = screen_info.rsvd_size;
0999 } else {
1000 var->red.length = 8;
1001 var->green.length = 8;
1002 var->blue.length = 8;
1003 }
1004 }
1005
1006 static int intelfb_init_var(struct intelfb_info *dinfo)
1007 {
1008 struct fb_var_screeninfo *var;
1009 int msrc = 0;
1010
1011 DBG_MSG("intelfb_init_var\n");
1012
1013 var = &dinfo->info->var;
1014 if (FIXED_MODE(dinfo)) {
1015 memcpy(var, &dinfo->initial_var,
1016 sizeof(struct fb_var_screeninfo));
1017 msrc = 5;
1018 } else {
1019 const u8 *edid_s = fb_firmware_edid(&dinfo->pdev->dev);
1020 u8 *edid_d = NULL;
1021
1022 if (edid_s) {
1023 edid_d = kmemdup(edid_s, EDID_LENGTH, GFP_KERNEL);
1024
1025 if (edid_d) {
1026 fb_edid_to_monspecs(edid_d,
1027 &dinfo->info->monspecs);
1028 kfree(edid_d);
1029 }
1030 }
1031
1032 if (mode) {
1033 printk("intelfb: Looking for mode in private "
1034 "database\n");
1035 msrc = fb_find_mode(var, dinfo->info, mode,
1036 dinfo->info->monspecs.modedb,
1037 dinfo->info->monspecs.modedb_len,
1038 NULL, 0);
1039
1040 if (msrc && msrc > 1) {
1041 printk("intelfb: No mode in private database, "
1042 "intelfb: looking for mode in global "
1043 "database ");
1044 msrc = fb_find_mode(var, dinfo->info, mode,
1045 NULL, 0, NULL, 0);
1046
1047 if (msrc)
1048 msrc |= 8;
1049 }
1050
1051 }
1052
1053 if (!msrc)
1054 msrc = fb_find_mode(var, dinfo->info, PREFERRED_MODE,
1055 NULL, 0, NULL, 0);
1056 }
1057
1058 if (!msrc) {
1059 ERR_MSG("Cannot find a suitable video mode.\n");
1060 return 1;
1061 }
1062
1063 INF_MSG("Initial video mode is %dx%d-%d@%d.\n", var->xres, var->yres,
1064 var->bits_per_pixel, var_to_refresh(var));
1065
1066 DBG_MSG("Initial video mode is from %d.\n", msrc);
1067
1068 #if ALLOCATE_FOR_PANNING
1069
1070 var->xres_virtual = var->xres;
1071 var->yres_virtual =
1072 dinfo->fb.size / 2 / (var->bits_per_pixel * var->xres);
1073 if (var->yres_virtual < var->yres)
1074 var->yres_virtual = var->yres;
1075 #else
1076 var->yres_virtual = var->yres;
1077 #endif
1078
1079 if (dinfo->accel)
1080 var->accel_flags |= FB_ACCELF_TEXT;
1081 else
1082 var->accel_flags &= ~FB_ACCELF_TEXT;
1083
1084 return 0;
1085 }
1086
1087 static int intelfb_set_fbinfo(struct intelfb_info *dinfo)
1088 {
1089 struct fb_info *info = dinfo->info;
1090
1091 DBG_MSG("intelfb_set_fbinfo\n");
1092
1093 info->flags = FBINFO_FLAG_DEFAULT;
1094 info->fbops = &intel_fb_ops;
1095 info->pseudo_palette = dinfo->pseudo_palette;
1096
1097 info->pixmap.size = 64*1024;
1098 info->pixmap.buf_align = 8;
1099 info->pixmap.access_align = 32;
1100 info->pixmap.flags = FB_PIXMAP_SYSTEM;
1101
1102 if (intelfb_init_var(dinfo))
1103 return 1;
1104
1105 info->pixmap.scan_align = 1;
1106 strcpy(info->fix.id, dinfo->name);
1107 info->fix.smem_start = dinfo->fb.physical;
1108 info->fix.smem_len = dinfo->fb.size;
1109 info->fix.type = FB_TYPE_PACKED_PIXELS;
1110 info->fix.type_aux = 0;
1111 info->fix.xpanstep = 8;
1112 info->fix.ypanstep = 1;
1113 info->fix.ywrapstep = 0;
1114 info->fix.mmio_start = dinfo->mmio_base_phys;
1115 info->fix.mmio_len = INTEL_REG_SIZE;
1116 info->fix.accel = FB_ACCEL_I830;
1117 update_dinfo(dinfo, &info->var);
1118
1119 return 0;
1120 }
1121
1122
1123 static void update_dinfo(struct intelfb_info *dinfo,
1124 struct fb_var_screeninfo *var)
1125 {
1126 DBG_MSG("update_dinfo\n");
1127
1128 dinfo->bpp = var->bits_per_pixel;
1129 dinfo->depth = intelfb_var_to_depth(var);
1130 dinfo->xres = var->xres;
1131 dinfo->yres = var->xres;
1132 dinfo->pixclock = var->pixclock;
1133
1134 dinfo->info->fix.visual = dinfo->visual;
1135 dinfo->info->fix.line_length = dinfo->pitch;
1136
1137 switch (dinfo->bpp) {
1138 case 8:
1139 dinfo->visual = FB_VISUAL_PSEUDOCOLOR;
1140 dinfo->pitch = var->xres_virtual;
1141 break;
1142 case 16:
1143 dinfo->visual = FB_VISUAL_TRUECOLOR;
1144 dinfo->pitch = var->xres_virtual * 2;
1145 break;
1146 case 32:
1147 dinfo->visual = FB_VISUAL_TRUECOLOR;
1148 dinfo->pitch = var->xres_virtual * 4;
1149 break;
1150 }
1151
1152
1153 if (IS_I9XX(dinfo))
1154 dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT_I9XX);
1155 else
1156 dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT);
1157
1158 if (FIXED_MODE(dinfo))
1159 dinfo->pitch = dinfo->initial_pitch;
1160
1161 dinfo->info->screen_base = (char __iomem *)dinfo->fb.virtual;
1162 dinfo->info->fix.line_length = dinfo->pitch;
1163 dinfo->info->fix.visual = dinfo->visual;
1164 }
1165
1166
1167
1168
1169
1170
1171
1172 static int intelfb_open(struct fb_info *info, int user)
1173 {
1174 struct intelfb_info *dinfo = GET_DINFO(info);
1175
1176 if (user)
1177 dinfo->open++;
1178
1179 return 0;
1180 }
1181
1182 static int intelfb_release(struct fb_info *info, int user)
1183 {
1184 struct intelfb_info *dinfo = GET_DINFO(info);
1185
1186 if (user) {
1187 dinfo->open--;
1188 msleep(1);
1189 if (!dinfo->open)
1190 intelfbhw_disable_irq(dinfo);
1191 }
1192
1193 return 0;
1194 }
1195
1196 static int intelfb_check_var(struct fb_var_screeninfo *var,
1197 struct fb_info *info)
1198 {
1199 int change_var = 0;
1200 struct fb_var_screeninfo v;
1201 struct intelfb_info *dinfo;
1202 static int first = 1;
1203 int i;
1204
1205 static const int pitches[] = {
1206 128 * 8,
1207 128 * 16,
1208 128 * 32,
1209 128 * 64,
1210 0
1211 };
1212
1213 DBG_MSG("intelfb_check_var: accel_flags is %d\n", var->accel_flags);
1214
1215 dinfo = GET_DINFO(info);
1216
1217
1218 if (intelfbhw_validate_mode(dinfo, var) != 0)
1219 return -EINVAL;
1220
1221 v = *var;
1222
1223 for (i = 0; pitches[i] != 0; i++) {
1224 if (pitches[i] >= v.xres_virtual) {
1225 v.xres_virtual = pitches[i];
1226 break;
1227 }
1228 }
1229
1230
1231 if (v.bits_per_pixel <= 8)
1232 v.bits_per_pixel = 8;
1233 else if (v.bits_per_pixel <= 16) {
1234 if (v.bits_per_pixel == 16)
1235 v.green.length = 6;
1236 v.bits_per_pixel = 16;
1237 } else if (v.bits_per_pixel <= 32)
1238 v.bits_per_pixel = 32;
1239 else
1240 return -EINVAL;
1241
1242 change_var = ((info->var.xres != var->xres) ||
1243 (info->var.yres != var->yres) ||
1244 (info->var.xres_virtual != var->xres_virtual) ||
1245 (info->var.yres_virtual != var->yres_virtual) ||
1246 (info->var.bits_per_pixel != var->bits_per_pixel) ||
1247 memcmp(&info->var.red, &var->red, sizeof(var->red)) ||
1248 memcmp(&info->var.green, &var->green,
1249 sizeof(var->green)) ||
1250 memcmp(&info->var.blue, &var->blue, sizeof(var->blue)));
1251
1252 if (FIXED_MODE(dinfo) &&
1253 (change_var ||
1254 var->yres_virtual > dinfo->initial_var.yres_virtual ||
1255 var->yres_virtual < dinfo->initial_var.yres ||
1256 var->xoffset || var->nonstd)) {
1257 if (first) {
1258 ERR_MSG("Changing the video mode is not supported.\n");
1259 first = 0;
1260 }
1261 return -EINVAL;
1262 }
1263
1264 switch (intelfb_var_to_depth(&v)) {
1265 case 8:
1266 v.red.offset = v.green.offset = v.blue.offset = 0;
1267 v.red.length = v.green.length = v.blue.length = 8;
1268 v.transp.offset = v.transp.length = 0;
1269 break;
1270 case 15:
1271 v.red.offset = 10;
1272 v.green.offset = 5;
1273 v.blue.offset = 0;
1274 v.red.length = v.green.length = v.blue.length = 5;
1275 v.transp.offset = v.transp.length = 0;
1276 break;
1277 case 16:
1278 v.red.offset = 11;
1279 v.green.offset = 5;
1280 v.blue.offset = 0;
1281 v.red.length = 5;
1282 v.green.length = 6;
1283 v.blue.length = 5;
1284 v.transp.offset = v.transp.length = 0;
1285 break;
1286 case 24:
1287 v.red.offset = 16;
1288 v.green.offset = 8;
1289 v.blue.offset = 0;
1290 v.red.length = v.green.length = v.blue.length = 8;
1291 v.transp.offset = v.transp.length = 0;
1292 break;
1293 case 32:
1294 v.red.offset = 16;
1295 v.green.offset = 8;
1296 v.blue.offset = 0;
1297 v.red.length = v.green.length = v.blue.length = 8;
1298 v.transp.offset = 24;
1299 v.transp.length = 8;
1300 break;
1301 }
1302
1303 if (v.xoffset > v.xres_virtual - v.xres)
1304 v.xoffset = v.xres_virtual - v.xres;
1305 if (v.yoffset > v.yres_virtual - v.yres)
1306 v.yoffset = v.yres_virtual - v.yres;
1307
1308 v.red.msb_right = v.green.msb_right = v.blue.msb_right =
1309 v.transp.msb_right = 0;
1310
1311 *var = v;
1312
1313 return 0;
1314 }
1315
1316 static int intelfb_set_par(struct fb_info *info)
1317 {
1318 struct intelfb_hwstate *hw;
1319 struct intelfb_info *dinfo = GET_DINFO(info);
1320
1321 if (FIXED_MODE(dinfo)) {
1322 ERR_MSG("Changing the video mode is not supported.\n");
1323 return -EINVAL;
1324 }
1325
1326 hw = kmalloc(sizeof(*hw), GFP_ATOMIC);
1327 if (!hw)
1328 return -ENOMEM;
1329
1330 DBG_MSG("intelfb_set_par (%dx%d-%d)\n", info->var.xres,
1331 info->var.yres, info->var.bits_per_pixel);
1332
1333
1334
1335
1336 OUTREG(DPLL_A, INREG(DPLL_A) & ~DPLL_VCO_ENABLE);
1337
1338 intelfb_blank(FB_BLANK_POWERDOWN, info);
1339
1340 if (ACCEL(dinfo, info))
1341 intelfbhw_2d_stop(dinfo);
1342
1343 memcpy(hw, &dinfo->save_state, sizeof(*hw));
1344 if (intelfbhw_mode_to_hw(dinfo, hw, &info->var))
1345 goto invalid_mode;
1346 if (intelfbhw_program_mode(dinfo, hw, 0))
1347 goto invalid_mode;
1348
1349 #if REGDUMP > 0
1350 intelfbhw_read_hw_state(dinfo, hw, 0);
1351 intelfbhw_print_hw_state(dinfo, hw);
1352 #endif
1353
1354 update_dinfo(dinfo, &info->var);
1355
1356 if (ACCEL(dinfo, info))
1357 intelfbhw_2d_start(dinfo);
1358
1359 intelfb_pan_display(&info->var, info);
1360
1361 intelfb_blank(FB_BLANK_UNBLANK, info);
1362
1363 if (ACCEL(dinfo, info)) {
1364 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
1365 FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
1366 FBINFO_HWACCEL_IMAGEBLIT;
1367 } else
1368 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1369
1370 kfree(hw);
1371 return 0;
1372 invalid_mode:
1373 kfree(hw);
1374 return -EINVAL;
1375 }
1376
1377 static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1378 unsigned blue, unsigned transp,
1379 struct fb_info *info)
1380 {
1381 struct intelfb_info *dinfo = GET_DINFO(info);
1382
1383 #if VERBOSE > 0
1384 DBG_MSG("intelfb_setcolreg: regno %d, depth %d\n", regno, dinfo->depth);
1385 #endif
1386
1387 if (regno > 255)
1388 return 1;
1389
1390 if (dinfo->depth == 8) {
1391 red >>= 8;
1392 green >>= 8;
1393 blue >>= 8;
1394
1395 intelfbhw_setcolreg(dinfo, regno, red, green, blue,
1396 transp);
1397 }
1398
1399 if (regno < 16) {
1400 switch (dinfo->depth) {
1401 case 15:
1402 dinfo->pseudo_palette[regno] = ((red & 0xf800) >> 1) |
1403 ((green & 0xf800) >> 6) |
1404 ((blue & 0xf800) >> 11);
1405 break;
1406 case 16:
1407 dinfo->pseudo_palette[regno] = (red & 0xf800) |
1408 ((green & 0xfc00) >> 5) |
1409 ((blue & 0xf800) >> 11);
1410 break;
1411 case 24:
1412 dinfo->pseudo_palette[regno] = ((red & 0xff00) << 8) |
1413 (green & 0xff00) |
1414 ((blue & 0xff00) >> 8);
1415 break;
1416 }
1417 }
1418
1419 return 0;
1420 }
1421
1422 static int intelfb_blank(int blank, struct fb_info *info)
1423 {
1424 intelfbhw_do_blank(blank, info);
1425 return 0;
1426 }
1427
1428 static int intelfb_pan_display(struct fb_var_screeninfo *var,
1429 struct fb_info *info)
1430 {
1431 intelfbhw_pan_display(var, info);
1432 return 0;
1433 }
1434
1435
1436 static int intelfb_ioctl(struct fb_info *info, unsigned int cmd,
1437 unsigned long arg)
1438 {
1439 int retval = 0;
1440 struct intelfb_info *dinfo = GET_DINFO(info);
1441 u32 pipe = 0;
1442
1443 switch (cmd) {
1444 case FBIO_WAITFORVSYNC:
1445 if (get_user(pipe, (__u32 __user *)arg))
1446 return -EFAULT;
1447
1448 retval = intelfbhw_wait_for_vsync(dinfo, pipe);
1449 break;
1450 default:
1451 break;
1452 }
1453
1454 return retval;
1455 }
1456
1457 static void intelfb_fillrect (struct fb_info *info,
1458 const struct fb_fillrect *rect)
1459 {
1460 struct intelfb_info *dinfo = GET_DINFO(info);
1461 u32 rop, color;
1462
1463 #if VERBOSE > 0
1464 DBG_MSG("intelfb_fillrect\n");
1465 #endif
1466
1467 if (!ACCEL(dinfo, info) || dinfo->depth == 4) {
1468 cfb_fillrect(info, rect);
1469 return;
1470 }
1471
1472 if (rect->rop == ROP_COPY)
1473 rop = PAT_ROP_GXCOPY;
1474 else
1475 rop = PAT_ROP_GXXOR;
1476
1477 if (dinfo->depth != 8)
1478 color = dinfo->pseudo_palette[rect->color];
1479 else
1480 color = rect->color;
1481
1482 intelfbhw_do_fillrect(dinfo, rect->dx, rect->dy,
1483 rect->width, rect->height, color,
1484 dinfo->pitch, info->var.bits_per_pixel,
1485 rop);
1486 }
1487
1488 static void intelfb_copyarea(struct fb_info *info,
1489 const struct fb_copyarea *region)
1490 {
1491 struct intelfb_info *dinfo = GET_DINFO(info);
1492
1493 #if VERBOSE > 0
1494 DBG_MSG("intelfb_copyarea\n");
1495 #endif
1496
1497 if (!ACCEL(dinfo, info) || dinfo->depth == 4) {
1498 cfb_copyarea(info, region);
1499 return;
1500 }
1501
1502 intelfbhw_do_bitblt(dinfo, region->sx, region->sy, region->dx,
1503 region->dy, region->width, region->height,
1504 dinfo->pitch, info->var.bits_per_pixel);
1505 }
1506
1507 static void intelfb_imageblit(struct fb_info *info,
1508 const struct fb_image *image)
1509 {
1510 struct intelfb_info *dinfo = GET_DINFO(info);
1511 u32 fgcolor, bgcolor;
1512
1513 #if VERBOSE > 0
1514 DBG_MSG("intelfb_imageblit\n");
1515 #endif
1516
1517 if (!ACCEL(dinfo, info) || dinfo->depth == 4
1518 || image->depth != 1) {
1519 cfb_imageblit(info, image);
1520 return;
1521 }
1522
1523 if (dinfo->depth != 8) {
1524 fgcolor = dinfo->pseudo_palette[image->fg_color];
1525 bgcolor = dinfo->pseudo_palette[image->bg_color];
1526 } else {
1527 fgcolor = image->fg_color;
1528 bgcolor = image->bg_color;
1529 }
1530
1531 if (!intelfbhw_do_drawglyph(dinfo, fgcolor, bgcolor, image->width,
1532 image->height, image->data,
1533 image->dx, image->dy,
1534 dinfo->pitch, info->var.bits_per_pixel)) {
1535 cfb_imageblit(info, image);
1536 return;
1537 }
1538 }
1539
1540 static int intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1541 {
1542 struct intelfb_info *dinfo = GET_DINFO(info);
1543 u32 physical;
1544 #if VERBOSE > 0
1545 DBG_MSG("intelfb_cursor\n");
1546 #endif
1547
1548 if (!dinfo->hwcursor)
1549 return -ENODEV;
1550
1551 intelfbhw_cursor_hide(dinfo);
1552
1553
1554 physical = (dinfo->mobile || IS_I9XX(dinfo)) ? dinfo->cursor.physical :
1555 (dinfo->cursor.offset << 12);
1556
1557 if (INREG(CURSOR_A_BASEADDR) != physical) {
1558 u32 fg, bg;
1559
1560 DBG_MSG("the cursor was killed - restore it !!\n");
1561 DBG_MSG("size %d, %d pos %d, %d\n",
1562 cursor->image.width, cursor->image.height,
1563 cursor->image.dx, cursor->image.dy);
1564
1565 intelfbhw_cursor_init(dinfo);
1566 intelfbhw_cursor_reset(dinfo);
1567 intelfbhw_cursor_setpos(dinfo, cursor->image.dx,
1568 cursor->image.dy);
1569
1570 if (dinfo->depth != 8) {
1571 fg =dinfo->pseudo_palette[cursor->image.fg_color];
1572 bg =dinfo->pseudo_palette[cursor->image.bg_color];
1573 } else {
1574 fg = cursor->image.fg_color;
1575 bg = cursor->image.bg_color;
1576 }
1577 intelfbhw_cursor_setcolor(dinfo, bg, fg);
1578 intelfbhw_cursor_load(dinfo, cursor->image.width,
1579 cursor->image.height,
1580 dinfo->cursor_src);
1581
1582 if (cursor->enable)
1583 intelfbhw_cursor_show(dinfo);
1584 return 0;
1585 }
1586
1587 if (cursor->set & FB_CUR_SETPOS) {
1588 u32 dx, dy;
1589
1590 dx = cursor->image.dx - info->var.xoffset;
1591 dy = cursor->image.dy - info->var.yoffset;
1592
1593 intelfbhw_cursor_setpos(dinfo, dx, dy);
1594 }
1595
1596 if (cursor->set & FB_CUR_SETSIZE) {
1597 if (cursor->image.width > 64 || cursor->image.height > 64)
1598 return -ENXIO;
1599
1600 intelfbhw_cursor_reset(dinfo);
1601 }
1602
1603 if (cursor->set & FB_CUR_SETCMAP) {
1604 u32 fg, bg;
1605
1606 if (dinfo->depth != 8) {
1607 fg = dinfo->pseudo_palette[cursor->image.fg_color];
1608 bg = dinfo->pseudo_palette[cursor->image.bg_color];
1609 } else {
1610 fg = cursor->image.fg_color;
1611 bg = cursor->image.bg_color;
1612 }
1613
1614 intelfbhw_cursor_setcolor(dinfo, bg, fg);
1615 }
1616
1617 if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
1618 u32 s_pitch = (ROUND_UP_TO(cursor->image.width, 8) / 8);
1619 u32 size = s_pitch * cursor->image.height;
1620 u8 *dat = (u8 *) cursor->image.data;
1621 u8 *msk = (u8 *) cursor->mask;
1622 u8 src[64];
1623 u32 i;
1624
1625 if (cursor->image.depth != 1)
1626 return -ENXIO;
1627
1628 switch (cursor->rop) {
1629 case ROP_XOR:
1630 for (i = 0; i < size; i++)
1631 src[i] = dat[i] ^ msk[i];
1632 break;
1633 case ROP_COPY:
1634 default:
1635 for (i = 0; i < size; i++)
1636 src[i] = dat[i] & msk[i];
1637 break;
1638 }
1639
1640
1641
1642 memcpy(dinfo->cursor_src, src, size);
1643
1644 intelfbhw_cursor_load(dinfo, cursor->image.width,
1645 cursor->image.height, src);
1646 }
1647
1648 if (cursor->enable)
1649 intelfbhw_cursor_show(dinfo);
1650
1651 return 0;
1652 }
1653
1654 static int intelfb_sync(struct fb_info *info)
1655 {
1656 struct intelfb_info *dinfo = GET_DINFO(info);
1657
1658 #if VERBOSE > 0
1659 DBG_MSG("intelfb_sync\n");
1660 #endif
1661
1662 if (dinfo->ring_lockup)
1663 return 0;
1664
1665 intelfbhw_do_sync(dinfo);
1666 return 0;
1667 }
1668