📄 intelfbdrv.c
字号:
mmio_bar = 0; } dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar); dinfo->aperture.size = pci_resource_len(pdev, aperture_bar); dinfo->mmio_base_phys = pci_resource_start(pdev, mmio_bar); DBG_MSG("fb aperture: 0x%llx/0x%llx, MMIO region: 0x%llx/0x%llx\n", (unsigned long long)pci_resource_start(pdev, aperture_bar), (unsigned long long)pci_resource_len(pdev, aperture_bar), (unsigned long long)pci_resource_start(pdev, mmio_bar), (unsigned long long)pci_resource_len(pdev, mmio_bar)); /* Reserve the fb and MMIO regions */ if (!request_mem_region(dinfo->aperture.physical, dinfo->aperture.size, INTELFB_MODULE_NAME)) { ERR_MSG("Cannot reserve FB region.\n"); cleanup(dinfo); return -ENODEV; } dinfo->flag |= INTELFB_FB_ACQUIRED; if (!request_mem_region(dinfo->mmio_base_phys, INTEL_REG_SIZE, INTELFB_MODULE_NAME)) { ERR_MSG("Cannot reserve MMIO region.\n"); cleanup(dinfo); return -ENODEV; } dinfo->flag |= INTELFB_MMIO_ACQUIRED; /* Get the chipset info. */ dinfo->pci_chipset = pdev->device; if (intelfbhw_get_chipset(pdev, dinfo)) { cleanup(dinfo); return -ENODEV; } if (intelfbhw_get_memory(pdev, &aperture_size,&stolen_size)) { cleanup(dinfo); return -ENODEV; } INF_MSG("%02x:%02x.%d: %s, aperture size %dMB, " "stolen memory %dkB\n", pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dinfo->name, BtoMB(aperture_size), BtoKB(stolen_size)); /* Set these from the options. */ dinfo->accel = accel; dinfo->hwcursor = hwcursor; if (NOACCEL_CHIPSET(dinfo) && dinfo->accel == 1) { INF_MSG("Acceleration is not supported for the %s chipset.\n", dinfo->name); dinfo->accel = 0; } /* Framebuffer parameters - Use all the stolen memory if >= vram */ if (ROUND_UP_TO_PAGE(stolen_size) >= MB(vram)) { dinfo->fb.size = ROUND_UP_TO_PAGE(stolen_size); dinfo->fbmem_gart = 0; } else { dinfo->fb.size = MB(vram); dinfo->fbmem_gart = 1; } /* Allocate space for the ring buffer and HW cursor if enabled. */ if (dinfo->accel) { dinfo->ring.size = RINGBUFFER_SIZE; dinfo->ring_tail_mask = dinfo->ring.size - 1; } if (dinfo->hwcursor) dinfo->cursor.size = HW_CURSOR_SIZE; /* Use agpgart to manage the GATT */ if (!(bridge = agp_backend_acquire(pdev))) { ERR_MSG("cannot acquire agp\n"); cleanup(dinfo); return -ENODEV; } /* get the current gatt info */ if (agp_copy_info(bridge, >t_info)) { ERR_MSG("cannot get agp info\n"); agp_backend_release(bridge); cleanup(dinfo); return -ENODEV; } if (MB(voffset) < stolen_size) offset = (stolen_size >> 12); else offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE; /* set the mem offsets - set them after the already used pages */ if (dinfo->accel) dinfo->ring.offset = offset + gtt_info.current_memory; if (dinfo->hwcursor) dinfo->cursor.offset = offset + + gtt_info.current_memory + (dinfo->ring.size >> 12); if (dinfo->fbmem_gart) dinfo->fb.offset = offset + + gtt_info.current_memory + (dinfo->ring.size >> 12) + (dinfo->cursor.size >> 12); /* Allocate memories (which aren't stolen) */ /* Map the fb and MMIO regions */ /* ioremap only up to the end of used aperture */ dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache (dinfo->aperture.physical, ((offset + dinfo->fb.offset) << 12) + dinfo->fb.size); if (!dinfo->aperture.virtual) { ERR_MSG("Cannot remap FB region.\n"); cleanup(dinfo); return -ENODEV; } dinfo->mmio_base = (u8 __iomem *)ioremap_nocache(dinfo->mmio_base_phys, INTEL_REG_SIZE); if (!dinfo->mmio_base) { ERR_MSG("Cannot remap MMIO region.\n"); cleanup(dinfo); return -ENODEV; } if (dinfo->accel) { if (!(dinfo->gtt_ring_mem = agp_allocate_memory(bridge, dinfo->ring.size >> 12, AGP_NORMAL_MEMORY))) { ERR_MSG("cannot allocate ring buffer memory\n"); agp_backend_release(bridge); cleanup(dinfo); return -ENOMEM; } if (agp_bind_memory(dinfo->gtt_ring_mem, dinfo->ring.offset)) { ERR_MSG("cannot bind ring buffer memory\n"); agp_backend_release(bridge); cleanup(dinfo); return -EBUSY; } dinfo->ring.physical = dinfo->aperture.physical + (dinfo->ring.offset << 12); dinfo->ring.virtual = dinfo->aperture.virtual + (dinfo->ring.offset << 12); dinfo->ring_head = 0; } if (dinfo->hwcursor) { agp_memtype = dinfo->mobile ? AGP_PHYSICAL_MEMORY : AGP_NORMAL_MEMORY; if (!(dinfo->gtt_cursor_mem = agp_allocate_memory(bridge, dinfo->cursor.size >> 12, agp_memtype))) { ERR_MSG("cannot allocate cursor memory\n"); agp_backend_release(bridge); cleanup(dinfo); return -ENOMEM; } if (agp_bind_memory(dinfo->gtt_cursor_mem, dinfo->cursor.offset)) { ERR_MSG("cannot bind cursor memory\n"); agp_backend_release(bridge); cleanup(dinfo); return -EBUSY; } if (dinfo->mobile) dinfo->cursor.physical = dinfo->gtt_cursor_mem->physical; else dinfo->cursor.physical = dinfo->aperture.physical + (dinfo->cursor.offset << 12); dinfo->cursor.virtual = dinfo->aperture.virtual + (dinfo->cursor.offset << 12); } if (dinfo->fbmem_gart) { if (!(dinfo->gtt_fb_mem = agp_allocate_memory(bridge, dinfo->fb.size >> 12, AGP_NORMAL_MEMORY))) { WRN_MSG("cannot allocate framebuffer memory - use " "the stolen one\n"); dinfo->fbmem_gart = 0; } if (agp_bind_memory(dinfo->gtt_fb_mem, dinfo->fb.offset)) { WRN_MSG("cannot bind framebuffer memory - use " "the stolen one\n"); dinfo->fbmem_gart = 0; } } /* update framebuffer memory parameters */ if (!dinfo->fbmem_gart) dinfo->fb.offset = 0; /* starts at offset 0 */ dinfo->fb.physical = dinfo->aperture.physical + (dinfo->fb.offset << 12); dinfo->fb.virtual = dinfo->aperture.virtual + (dinfo->fb.offset << 12); dinfo->fb_start = dinfo->fb.offset << 12; /* release agpgart */ agp_backend_release(bridge); if (mtrr) set_mtrr(dinfo); DBG_MSG("fb: 0x%x(+ 0x%x)/0x%x (0x%p)\n", dinfo->fb.physical, dinfo->fb.offset, dinfo->fb.size, dinfo->fb.virtual); DBG_MSG("MMIO: 0x%x/0x%x (0x%p)\n", dinfo->mmio_base_phys, INTEL_REG_SIZE, dinfo->mmio_base); DBG_MSG("ring buffer: 0x%x/0x%x (0x%p)\n", dinfo->ring.physical, dinfo->ring.size, dinfo->ring.virtual); DBG_MSG("HW cursor: 0x%x/0x%x (0x%p) (offset 0x%x) (phys 0x%x)\n", dinfo->cursor.physical, dinfo->cursor.size, dinfo->cursor.virtual, dinfo->cursor.offset, dinfo->cursor.physical); DBG_MSG("options: vram = %d, accel = %d, hwcursor = %d, fixed = %d, " "noinit = %d\n", vram, accel, hwcursor, fixed, noinit); DBG_MSG("options: mode = \"%s\"\n", mode ? mode : ""); if (probeonly) bailout(dinfo); /* * Check if the LVDS port or any DVO ports are enabled. If so, * don't allow mode switching */ dvo = intelfbhw_check_non_crt(dinfo); if (dvo) { dinfo->fixed_mode = 1; WRN_MSG("Non-CRT device is enabled ( "); i = 0; while (dvo) { if (dvo & 1) { s = intelfbhw_dvo_to_string(1 << i); if (s) printk("%s ", s); } dvo >>= 1; ++i; } printk("). Disabling mode switching.\n"); } if (bailearly == 1) bailout(dinfo); if (FIXED_MODE(dinfo) && screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) { ERR_MSG("Video mode must be programmed at boot time.\n"); cleanup(dinfo); return -ENODEV; } if (bailearly == 2) bailout(dinfo); /* Initialise dinfo and related data. */ /* If an initial mode was programmed at boot time, get its details. */ if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB) get_initial_mode(dinfo); if (bailearly == 3) bailout(dinfo); if (FIXED_MODE(dinfo)) /* remap fb address */ update_dinfo(dinfo, &dinfo->initial_var); if (bailearly == 4) bailout(dinfo); if (intelfb_set_fbinfo(dinfo)) { cleanup(dinfo); return -ENODEV; } if (bailearly == 5) bailout(dinfo);#ifdef CONFIG_FB_INTEL_I2C /* register I2C bus */ intelfb_create_i2c_busses(dinfo);#endif if (bailearly == 6) bailout(dinfo); pci_set_drvdata(pdev, dinfo); /* Save the initial register state. */ i = intelfbhw_read_hw_state(dinfo, &dinfo->save_state, bailearly > 6 ? bailearly - 6 : 0); if (i != 0) { DBG_MSG("intelfbhw_read_hw_state returned %d\n", i); bailout(dinfo); } intelfbhw_print_hw_state(dinfo, &dinfo->save_state); if (bailearly == 18) bailout(dinfo); /* Cursor initialisation */ if (dinfo->hwcursor) { intelfbhw_cursor_init(dinfo); intelfbhw_cursor_reset(dinfo); } if (bailearly == 19) bailout(dinfo); /* 2d acceleration init */ if (dinfo->accel) intelfbhw_2d_start(dinfo); if (bailearly == 20) bailout(dinfo); if (noregister) bailout(dinfo); if (register_framebuffer(dinfo->info) < 0) { ERR_MSG("Cannot register framebuffer.\n"); cleanup(dinfo); return -ENODEV; } dinfo->registered = 1; dinfo->open = 0; init_waitqueue_head(&dinfo->vsync.wait); spin_lock_init(&dinfo->int_lock); dinfo->irq_flags = 0; dinfo->vsync.pan_display = 0; dinfo->vsync.pan_offset = 0; return 0;err_out_pixmap: fb_dealloc_cmap(&info->cmap);err_out_cmap: framebuffer_release(info); return -ENODEV;}static void __devexitintelfb_pci_unregister(struct pci_dev *pdev){ struct intelfb_info *dinfo = pci_get_drvdata(pdev); DBG_MSG("intelfb_pci_unregister\n"); if (!dinfo) return; cleanup(dinfo); pci_set_drvdata(pdev, NULL);}/*************************************************************** * helper functions * ***************************************************************/int __inline__ intelfb_var_to_depth(const struct fb_var_screeninfo *var){ DBG_MSG("intelfb_var_to_depth: bpp: %d, green.length is %d\n", var->bits_per_pixel, var->green.length); switch (var->bits_per_pixel) { case 16: return (var->green.length == 6) ? 16 : 15; case 32: return 24; default: return var->bits_per_pixel; }}static __inline__ int var_to_refresh(const struct fb_var_screeninfo *var){ int xtot = var->xres + var->left_margin + var->right_margin + var->hsync_len; int ytot = var->yres + var->upper_margin + var->lower_margin + var->vsync_len; return (1000000000 / var->pixclock * 1000 + 500) / xtot / ytot;}/*************************************************************** * Various intialisation functions * ***************************************************************/static void __devinit get_initial_mode(struct intelfb_info *dinfo){ struct fb_var_screeninfo *var; int xtot, ytot; DBG_MSG("get_initial_mode\n"); dinfo->initial_vga = 1; dinfo->initial_fb_base = screen_info.lfb_base; dinfo->initial_video_ram = screen_info.lfb_size * KB(64); dinfo->initial_pitch = screen_info.lfb_linelength; var = &dinfo->initial_var; memset(var, 0, sizeof(*var)); var->xres = screen_info.lfb_width; var->yres = screen_info.lfb_height; var->bits_per_pixel = screen_info.lfb_depth; switch (screen_info.lfb_depth) { case 15: var->bits_per_pixel = 16; break; case 24: var->bits_per_pixel = 32; break; } DBG_MSG("Initial info: FB is 0x%x/0x%x (%d kByte)\n", dinfo->initial_fb_base, dinfo->initial_video_ram, BtoKB(dinfo->initial_video_ram)); DBG_MSG("Initial info: mode is %dx%d-%d (%d)\n", var->xres, var->yres, var->bits_per_pixel, dinfo->initial_pitch); /* Dummy timing values (assume 60Hz) */ var->left_margin = (var->xres / 8) & 0xf8; var->right_margin = 32; var->upper_margin = 16; var->lower_margin = 4; var->hsync_len = (var->xres / 8) & 0xf8; var->vsync_len = 4; xtot = var->xres + var->left_margin + var->right_margin + var->hsync_len; ytot = var->yres + var->upper_margin + var->lower_margin + var->vsync_len; var->pixclock = 10000000 / xtot * 1000 / ytot * 100 / 60; var->height = -1; var->width = -1; if (var->bits_per_pixel > 8) { var->red.offset = screen_info.red_pos; var->red.length = screen_info.red_size; var->green.offset = screen_info.green_pos; var->green.length = screen_info.green_size; var->blue.offset = screen_info.blue_pos; var->blue.length = screen_info.blue_size; var->transp.offset = screen_info.rsvd_pos; var->transp.length = screen_info.rsvd_size; } else { var->red.length = 8; var->green.length = 8; var->blue.length = 8; }}static int __devinit intelfb_init_var(struct intelfb_info *dinfo){ struct fb_var_screeninfo *var; int msrc = 0; DBG_MSG("intelfb_init_var\n"); var = &dinfo->info->var; if (FIXED_MODE(dinfo)) { memcpy(var, &dinfo->initial_var, sizeof(struct fb_var_screeninfo)); msrc = 5; } else { const u8 *edid_s = fb_firmware_edid(&dinfo->pdev->dev); u8 *edid_d = NULL; if (edid_s) { edid_d = kmemdup(edid_s, EDID_LENGTH, GFP_KERNEL); if (edid_d) { fb_edid_to_monspecs(edid_d, &dinfo->info->monspecs); kfree(edid_d); } } if (mode) { printk("intelfb: Looking for mode in private " "database\n"); msrc = fb_find_mode(var, dinfo->info, mode, dinfo->info->monspecs.modedb, dinfo->info->monspecs.modedb_len, NULL, 0); if (msrc && msrc > 1) { printk("intelfb: No mode in private database, " "intelfb: looking for mode in global " "database "); msrc = fb_find_mode(var, dinfo->info, mode, NULL, 0, NULL, 0); if (msrc) msrc |= 8; } } if (!msrc) msrc = fb_find_mode(var, dinfo->info, PREFERRED_MODE, NULL, 0, NULL, 0); } if (!msrc) { ERR_MSG("Cannot find a suitable video mode.\n"); return 1; } INF_MSG("Initial video mode is %dx%d-%d@%d.\n", var->xres, var->yres, var->bits_per_pixel, var_to_refresh(var)); DBG_MSG("Initial video mode is from %d.\n", msrc);#if ALLOCATE_FOR_PANNING /* Allow use of half of the video ram for panning */ var->xres_virtual = var->xres; var->yres_virtual = dinfo->fb.size / 2 / (var->bits_per_pixel * var->xres); if (var->yres_virtual < var->yres) var->yres_virtual = var->yres;#else var->yres_virtual = var->yres;#endif if (dinfo->accel) var->accel_flags |= FB_ACCELF_TEXT; else var->accel_flags &= ~FB_ACCELF_TEXT; return 0;}static int __devinit intelfb_set_fbinfo(struct intelfb_info *dinfo){ struct fb_info *info = dinfo->info; DBG_MSG("intelfb_set_fbinfo\n"); info->flags = FBINFO_FLAG_DEFAULT; info->fbops = &intel_fb_ops; info->pseudo_palette = dinfo->pseudo_palette; info->pixmap.size = 64*1024; info->pixmap.buf_align = 8; info->pixmap.access_align = 32; info->pixmap.flags = FB_PIXMAP_SYSTEM; if (intelfb_init_var(dinfo)) return 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -