From: <jb...@ke...> - 2007-04-11 00:59:16
|
linux-core/Makefile.kernel | 2 linux-core/drm_crtc.c | 9 linux-core/drm_crtc.h | 6 linux-core/drm_edid.c | 173 ------------------ linux-core/drm_edid.h | 176 +++++++++++++++++++ linux-core/drm_fops.c | 3 linux-core/i915_init.c | 1 linux-core/intel_display.c | 116 ++++++++++++ linux-core/intel_drv.h | 3 linux-core/intel_i2c.c | 6 linux-core/intel_lvds.c | 412 ++++++++++++++++++++++++++++++++++++++++----- shared-core/i915_dma.c | 78 -------- shared-core/i915_drv.h | 63 ++++++ shared-core/i915_init.c | 159 +++++++++++++++++ 14 files changed, 903 insertions(+), 304 deletions(-) New commits: diff-tree f50eec752c8754595ba99f0ec7a7c8138316a819 (from parents) Merge: 44a8761302888080f1cb6596d4573d88c1746da4 b62ffb8e91dafbe46b4daa5be13a867b149b0170 Author: Jesse Barnes <jb...@ho...> Date: Tue Apr 10 17:58:30 2007 -0700 Merge branch 'modesetting-101' of git+ssh://git.freedesktop.org/git/mesa/drm into origin/modesetting-101 diff-tree 44a8761302888080f1cb6596d4573d88c1746da4 (from parents) Merge: e114b981bc291049fa6996d487334a408acc1ce2 50672adb3142abca743535a8e60c360ef47b2a08 Author: Jesse Barnes <jb...@ho...> Date: Tue Apr 10 10:45:55 2007 -0700 Merge branch 'modesetting-101' of git+ssh://git.freedesktop.org/git/mesa/drm into origin/modesetting-101 Conflicts: linux-core/drm_crtc.c - trivial merge linux-core/drm_crtc.h - trivial merge linux-core/intel_display.c - crtc_config -> mode_config shared-core/i915_dma.c - accommodate new init code in i915_init.c diff --cc linux-core/Makefile.kernel index ac403f6,ac403f6..c767116 @@@ -21,7 -21,7 +21,7 @@@ i810-objs := i810_drv.o i810_dma.o i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \ i915_buffer.o intel_display.o intel_crt.o intel_lvds.o \ -- intel_sdvo.o intel_modes.o intel_i2c.o ++ intel_sdvo.o intel_modes.o intel_i2c.o i915_init.o nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \ nouveau_object.o nouveau_irq.o \ nv04_timer.o \ diff --cc linux-core/drm_crtc.c index 6874265,cc082d9..1899df2 @@@ -116,8 -116,7 +116,8 @@@ { struct drm_output *output; drm_device_t *dev = crtc->dev; + /* FIXME: Locking around list access? */ - list_for_each_entry(output, &dev->crtc_config.output_list, head) + list_for_each_entry(output, &dev->mode_config.output_list, head) if (output->crtc == crtc) return true; return false; @@@ -518,11 -512,12 +513,12 @@@ fb->height = 768; fb->depth = 24; fb->bits_per_pixel = 32; - + #endif + /* bind both CRTCs to this fb */ /* only initialise one crtc to enabled state */ - list_for_each_entry(crtc, &dev->crtc_config.crtc_list, head) { - crtc->fb = fb; + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + // crtc->fb = fb; if (!vga_crtc) { vga_crtc = crtc; crtc->enabled = 1; diff --cc linux-core/drm_crtc.h index 775d21e,142e0ec..57bfb10 @@@ -455,11 -444,20 +445,25 @@@ extern int drm_mode_vrefresh(struct drm_display_mode *mode); extern void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags); +extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev); +extern bool drm_initial_config(struct drm_device *dev, bool cangrow); +extern void drm_framebuffer_set_object(struct drm_device *dev, + unsigned long handle); +extern bool drm_set_desired_modes(struct drm_device *dev); + /* IOCTLs */ + extern int drm_mode_getresources(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + + extern int drm_mode_getcrtc(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + extern int drm_mode_getoutput(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + extern int drm_mode_setcrtc(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + extern int drm_mode_addfb(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + extern int drm_mode_rmfb(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); #endif /* __DRM_CRTC_H__ */ diff --cc linux-core/intel_display.c index 90c894e,9fb497d..1eed71f @@@ -349,9 -351,10 +349,10 @@@ int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); - Start = crtc->fb->offset; + Start = crtc->fb->offset + dev_priv->baseaddr; Offset = ((y * crtc->fb->width + x) * (crtc->fb->bits_per_pixel / 8)); - DRM_DEBUG("Writing base %08X %08X %d %d\n", Start, Offset, x, y); ++ DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); if (IS_I965G(dev)) { I915_WRITE(dspbase, Offset); I915_READ(dspbase); @@@ -1209,8 -1097,7 +1202,8 @@@ intel_setup_outputs(dev); - drm_initial_config(dev, false); - drm_set_desired_modes(dev); + //drm_initial_config(dev, false); ++ //drm_set_desired_modes(dev); } void intel_modeset_cleanup(drm_device_t *dev) diff --cc linux-core/intel_lvds.c index 4638fb3,a444f14..90a2610 @@@ -62,251 -63,25 +62,251 @@@ BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; } -int lvds_backlight(DRM_IOCTL_ARGS) +/** + * Sets the power state for the panel. + */ +static void intel_lvds_set_power(struct drm_device *dev, bool on) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + u32 pp_status; + + if (on) { + I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | + POWER_TARGET_ON); + do { + pp_status = I915_READ(PP_STATUS); + } while ((pp_status & PP_ON) == 0); + + intel_lvds_set_backlight(dev, dev_priv->backlight_duty_cycle); + } else { + intel_lvds_set_backlight(dev, 0); + + I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & + ~POWER_TARGET_ON); + do { + pp_status = I915_READ(PP_STATUS); + } while (pp_status & PP_ON); + } +} + +static void intel_lvds_dpms(struct drm_output *output, int mode) +{ + struct drm_device *dev = output->dev; + + if (mode == DPMSModeOn) + intel_lvds_set_power(dev, true); + else + intel_lvds_set_power(dev, false); + + /* XXX: We never power down the LVDS pairs. */ +} + +static void intel_lvds_save(struct drm_output *output) +{ + struct drm_device *dev = output->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + + dev_priv->savePP_ON = I915_READ(LVDSPP_ON); + dev_priv->savePP_OFF = I915_READ(LVDSPP_OFF); + dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL); + dev_priv->savePP_CYCLE = I915_READ(PP_CYCLE); + dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); + dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL & + BACKLIGHT_DUTY_CYCLE_MASK); + + /* + * If the light is off at server startup, just make it full brightness + */ + if (dev_priv->backlight_duty_cycle == 0) + dev_priv->backlight_duty_cycle = + intel_lvds_get_max_backlight(dev); +} + +static void intel_lvds_restore(struct drm_output *output) +{ + struct drm_device *dev = output->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + + I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL); + I915_WRITE(LVDSPP_ON, dev_priv->savePP_ON); + I915_WRITE(LVDSPP_OFF, dev_priv->savePP_OFF); + I915_WRITE(PP_CYCLE, dev_priv->savePP_CYCLE); + I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL); + if (dev_priv->savePP_CONTROL & POWER_TARGET_ON) + intel_lvds_set_power(dev, true); + else + intel_lvds_set_power(dev, false); +} + +static int intel_lvds_mode_valid(struct drm_output *output, + struct drm_display_mode *mode) +{ + struct drm_device *dev = output->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_display_mode *fixed_mode = dev_priv->panel_fixed_mode; + + if (fixed_mode) { + if (mode->hdisplay > fixed_mode->hdisplay) + return MODE_PANEL; + if (mode->vdisplay > fixed_mode->vdisplay) + return MODE_PANEL; + } + + return MODE_OK; +} + +static bool intel_lvds_mode_fixup(struct drm_output *output, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { - DRM_DEVICE; - unsigned long dvoa_enabled, dvob_enabled, dvoc_enabled, lvds_enabled; + struct drm_device *dev = output->dev; drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = output->crtc->driver_private; + struct drm_output *tmp_output; + - spin_lock(&dev->crtc_config.config_lock); - list_for_each_entry(tmp_output, &dev->crtc_config.output_list, head) { ++ spin_lock(&dev->mode_config.config_lock); ++ list_for_each_entry(tmp_output, &dev->mode_config.output_list, head) { + if (tmp_output != output && tmp_output->crtc == output->crtc) { + printk(KERN_ERR "Can't enable LVDS and another " + "output on the same pipe\n"); + return false; + } + } - spin_lock(&dev->crtc_config.config_lock); ++ spin_lock(&dev->mode_config.config_lock); + + if (intel_crtc->pipe == 0) { + printk(KERN_ERR "Can't support LVDS on pipe A\n"); + return false; + } + + /* + * If we have timings from the BIOS for the panel, put them in + * to the adjusted mode. The CRTC will be set up for this mode, + * with the panel scaling set up to source from the H/VDisplay + * of the original mode. + */ + if (dev_priv->panel_fixed_mode != NULL) { + adjusted_mode->hdisplay = dev_priv->panel_fixed_mode->hdisplay; + adjusted_mode->hsync_start = + dev_priv->panel_fixed_mode->hsync_start; + adjusted_mode->hsync_end = + dev_priv->panel_fixed_mode->hsync_end; + adjusted_mode->htotal = dev_priv->panel_fixed_mode->htotal; + adjusted_mode->vdisplay = dev_priv->panel_fixed_mode->vdisplay; + adjusted_mode->vsync_start = + dev_priv->panel_fixed_mode->vsync_start; + adjusted_mode->vsync_end = + dev_priv->panel_fixed_mode->vsync_end; + adjusted_mode->vtotal = dev_priv->panel_fixed_mode->vtotal; + adjusted_mode->clock = dev_priv->panel_fixed_mode->clock; +// xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V); + } + + /* + * XXX: It would be nice to support lower refresh rates on the + * panels to reduce power consumption, and perhaps match the + * user's requested refresh rate. + */ + + return true; +} + +static void intel_lvds_mode_set(struct drm_output *output, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = output->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = output->crtc->driver_private; + u32 pfit_control; + + /* + * The LVDS pin pair will already have been turned on in the + * intel_crtc_mode_set since it has a large impact on the DPLL + * settings. + */ + + /* + * Enable automatic panel scaling so that non-native modes fill the + * screen. Should be enabled before the pipe is enabled, according to + * register description and PRM. + */ + pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | + VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR); + + if (!IS_I965G(dev)) { + if (dev_priv->panel_wants_dither) + pfit_control |= PANEL_8TO6_DITHER_ENABLE; + } + else + pfit_control |= intel_crtc->pipe << PFIT_PIPE_SHIFT; + + I915_WRITE(PFIT_CONTROL, pfit_control); +} + +/** + * Detect the LVDS connection. + * + * This always returns OUTPUT_STATUS_CONNECTED. This output should only have + * been set up if the LVDS was actually connected anyway. + */ +static enum drm_output_status intel_lvds_detect(struct drm_output *output) +{ + return output_status_connected; +} + +/** + * Return the list of DDC modes if available, or the BIOS fixed mode otherwise. + */ +static int intel_lvds_get_modes(struct drm_output *output) +{ + struct intel_output *intel_output = output->driver_private; + struct drm_device *dev = output->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct edid *edid_info; + int ret = 0; + + intel_output->ddc_bus = intel_i2c_create(dev, GPIOC, "LVDSDDC_C"); + if (!intel_output->ddc_bus) { + dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " + "failed.\n"); + return 0; + } + intel_i2c_destroy(intel_output->ddc_bus); + + ret = intel_ddc_get_modes(output); + if (ret) + return ret; + + /* Didn't get an EDID */ + if (!output->monitor_info) { + struct detailed_data_monitor_range *edid_range; + edid_info = kzalloc(sizeof(*output->monitor_info), GFP_KERNEL); + if (!edid_info) + goto out; + + edid_info->detailed_timings[0].data.other_data.type = + EDID_DETAIL_MONITOR_RANGE; + edid_range = &edid_info->detailed_timings[0].data.other_data.data.range; + + /* Set wide sync ranges so we get all modes + * handed to valid_mode for checking + */ + edid_range->min_vfreq = 0; + edid_range->max_vfreq = 200; + edid_range->min_hfreq_khz = 0; + edid_range->max_hfreq_khz = 200; + output->monitor_info = edid_info; + } + +out: + if (dev_priv->panel_fixed_mode != NULL) { + struct drm_display_mode *mode = + drm_mode_duplicate(dev, dev_priv->panel_fixed_mode); + drm_mode_probed_add(output, mode); + return 1; + } - printk(KERN_ERR "max backlight value: %d\n", - lvds_get_max_backlight(dev)); - dvoa_enabled = I915_READ(DVOA); - dvob_enabled = I915_READ(DVOB); - dvoc_enabled = I915_READ(DVOC); - lvds_enabled = I915_READ(LVDS); - - printk(KERN_ERR "dvoa_enabled: 0x%08lx\n", dvoa_enabled); - printk(KERN_ERR "dvob_enabled: 0x%08lx\n", dvob_enabled); - printk(KERN_ERR "dvoc_enabled: 0x%08lx\n", dvoc_enabled); - printk(KERN_ERR "lvds_enabled: 0x%08lx\n", lvds_enabled); - printk(KERN_ERR "BLC_PWM_CTL: 0x%08x\n", I915_READ(BLC_PWM_CTL)); - return 0; } @@@ -356,105 -113,18 +356,105 @@@ intel_output->type = INTEL_OUTPUT_LVDS; output->driver_private = intel_output; output->subpixel_order = SubPixelHorizontalRGB; - output->interlace_allowed = 0; - output->doublescan_allowed = 0; + output->interlace_allowed = FALSE; + output->doublescan_allowed = FALSE; - intel_output->ddc_bus = intel_i2c_create(dev, GPIOC, "LVDSDDC_C"); - if (!intel_output->ddc_bus) { - dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " - "failed.\n"); - return; + /* + * Attempt to get the fixed panel mode from DDC. Assume that the + * preferred mode is the right one. + */ + intel_ddc_get_modes(output); + list_for_each_entry(scan, &output->probed_modes, head) { + if (scan->type & DRM_MODE_TYPE_PREFERRED) + break; } - modes = intel_ddc_get_modes(output); - intel_i2c_destroy(intel_output->ddc_bus); - drm_output_destroy(output); -} + if (scan) + dev_priv->panel_fixed_mode = scan; + + /* + * If we didn't get EDID, try checking if the panel is already turned + * on. If so, assume that whatever is currently programmed is the + * correct mode. + */ + if (!dev_priv->panel_fixed_mode) { + u32 lvds = I915_READ(LVDS); + int pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; - struct drm_crtc_config *crtc_config = &dev->crtc_config; ++ struct drm_mode_config *mode_config = &dev->mode_config; + struct drm_crtc *crtc; + /* FIXME: need drm_crtc_from_pipe */ - //crtc = drm_crtc_from_pipe(crtc_config, pipe); ++ //crtc = drm_crtc_from_pipe(mode_config, pipe); + + if (lvds & LVDS_PORT_EN && 0) { + dev_priv->panel_fixed_mode = + intel_crtc_mode_get(dev, crtc); + if (dev_priv->panel_fixed_mode) + dev_priv->panel_fixed_mode->type |= + DRM_MODE_TYPE_PREFERRED; + } + } +/* No BIOS poking yet... */ +#if 0 + /* Get the LVDS fixed mode out of the BIOS. We should support LVDS + * with the BIOS being unavailable or broken, but lack the + * configuration options for now. + */ + bios_mode = intel_bios_get_panel_mode(pScrn); + if (bios_mode != NULL) { + if (dev_priv->panel_fixed_mode != NULL) { + if (dev_priv->debug_modes && + !xf86ModesEqual(dev_priv->panel_fixed_mode, + bios_mode)) + { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "BIOS panel mode data doesn't match probed data, " + "continuing with probed.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS mode:\n"); + xf86PrintModeline(pScrn->scrnIndex, bios_mode); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "probed mode:\n"); + xf86PrintModeline(pScrn->scrnIndex, dev_priv->panel_fixed_mode); + xfree(bios_mode->name); + xfree(bios_mode); + } + } else { + dev_priv->panel_fixed_mode = bios_mode; + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Couldn't detect panel mode. Disabling panel\n"); + goto disable_exit; + } + + /* Blacklist machines with BIOSes that list an LVDS panel without actually + * having one. + */ + if (dev_priv->PciInfo->chipType == PCI_CHIP_I945_GM) { + if (dev_priv->PciInfo->subsysVendor == 0xa0a0) /* aopen mini pc */ + goto disable_exit; + + if ((dev_priv->PciInfo->subsysVendor == 0x8086) && + (dev_priv->PciInfo->subsysCard == 0x7270)) { + /* It's a Mac Mini or Macbook Pro. + * + * Apple hardware is out to get us. The macbook pro has a real + * LVDS panel, but the mac mini does not, and they have the same + * device IDs. We'll distinguish by panel size, on the assumption + * that Apple isn't about to make any machines with an 800x600 + * display. + */ + + if (dev_priv->panel_fixed_mode != NULL && + dev_priv->panel_fixed_mode->HDisplay == 800 && + dev_priv->panel_fixed_mode->VDisplay == 600) + { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Suspected Mac Mini, ignoring the LVDS\n"); + goto disable_exit; + } + } + } + +#endif + return; +} diff --cc shared-core/i915_init.c index e03ed42,0000000..e454c9f mode 100644,000000..100644 @@@ -1,157 -1,0 +1,159 @@@ +#include "drmP.h" +#include "drm.h" +#include "drm_sarea.h" +#include "i915_drm.h" +#include "i915_drv.h" + +int i915_driver_load(drm_device_t *dev, unsigned long flags) +{ + drm_i915_private_t *dev_priv; + drm_i915_init_t init; + int ret; + + dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER); + if (dev_priv == NULL) + return DRM_ERR(ENOMEM); + + memset(dev_priv, 0, sizeof(drm_i915_private_t)); + dev->dev_private = (void *)dev_priv; +// dev_priv->flags = flags; + + /* i915 has 4 more counters */ + dev->counters += 4; + dev->types[6] = _DRM_STAT_IRQ; + dev->types[7] = _DRM_STAT_PRIMARY; + dev->types[8] = _DRM_STAT_SECONDARY; + dev->types[9] = _DRM_STAT_DMA; + + if (IS_I9XX(dev)) { + dev_priv->mmiobase = drm_get_resource_start(dev, 0); + dev_priv->mmiolen = drm_get_resource_len(dev, 0); ++ dev_priv->baseaddr = drm_get_resource_start(dev, 2) & 0xff000000; + } else if (drm_get_resource_start(dev, 1)) { + dev_priv->mmiobase = drm_get_resource_start(dev, 1); + dev_priv->mmiolen = drm_get_resource_len(dev, 1); ++ dev_priv->baseaddr = drm_get_resource_start(dev, 0) & 0xff000000; + } else { + DRM_ERROR("Unable to find MMIO registers\n"); + return -ENODEV; + } + + ret = drm_addmap(dev, dev_priv->mmiobase, dev_priv->mmiolen, + _DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->mmio_map); + if (ret != 0) { + DRM_ERROR("Cannot add mapping for MMIO registers\n"); + return ret; + } + + + ret = drm_setup(dev); + if (ret) { + DRM_ERROR("drm_setup failed\n"); + return ret; + } + + DRM_GETSAREA(); + if (!dev_priv->sarea) { + DRM_ERROR("can not find sarea!\n"); + dev->dev_private = (void *)dev_priv; + i915_dma_cleanup(dev); + return DRM_ERR(EINVAL); + } + + /* FIXME: where does the sarea_priv really go? */ + dev_priv->sarea_priv = kmalloc(sizeof(drm_i915_sarea_t), GFP_KERNEL); + + /* FIXME: need real front buffer offset */ + dev_priv->sarea_priv->front_handle = 0xa0000000 + 1024*1024; + + drm_bo_driver_init(dev); + /* this probably doesn't belong here - TODO */ - drm_framebuffer_set_object(dev, dev_priv->sarea_priv->front_handle); ++ //drm_framebuffer_set_object(dev, dev_priv->sarea_priv->front_handle); + intel_modeset_init(dev); + drm_set_desired_modes(dev); + + /* FIXME: command ring needs AGP space, do we own it at this point? */ + dev_priv->ring.Start = 0xa0000000; + dev_priv->ring.End = 128*1024; + dev_priv->ring.Size = 128*1024; + dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; + + dev_priv->ring.map.offset = dev_priv->ring.Start; + dev_priv->ring.map.size = dev_priv->ring.Size; + dev_priv->ring.map.type = 0; + dev_priv->ring.map.flags = 0; + dev_priv->ring.map.mtrr = 0; + + drm_core_ioremap(&dev_priv->ring.map, dev); + + if (dev_priv->ring.map.handle == NULL) { + dev->dev_private = (void *)dev_priv; + i915_dma_cleanup(dev); + DRM_ERROR("can not ioremap virtual address for" + " ring buffer\n"); + return DRM_ERR(ENOMEM); + } + + dev_priv->ring.virtual_start = dev_priv->ring.map.handle; + dev_priv->cpp = 4; + dev_priv->sarea_priv->pf_current_page = 0; + + /* We are using separate values as placeholders for mechanisms for + * private backbuffer/depthbuffer usage. + */ + dev_priv->use_mi_batchbuffer_start = 0; + + /* Allow hardware batchbuffers unless told otherwise. + */ + dev_priv->allow_batchbuffer = 1; + + /* Program Hardware Status Page */ + dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, + 0xffffffff); + + if (!dev_priv->status_page_dmah) { + dev->dev_private = (void *)dev_priv; + i915_dma_cleanup(dev); + DRM_ERROR("Can not allocate hardware status page\n"); + return DRM_ERR(ENOMEM); + } + dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr; + dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; + + memset(dev_priv->hw_status_page, 0, PAGE_SIZE); + DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page); + + I915_WRITE(0x02080, dev_priv->dma_status_page); + DRM_DEBUG("Enabled hardware status page\n"); + + return 0; +} + +int i915_driver_unload(drm_device_t *dev) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + + intel_modeset_cleanup(dev); + drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); + + dev->dev_private = NULL; + return 0; +} + +void i915_driver_lastclose(drm_device_t * dev) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + + i915_mem_takedown(&(dev_priv->agp_heap)); + + i915_dma_cleanup(dev); + + dev_priv->mmio_map = NULL; +} + +void i915_driver_preclose(drm_device_t * dev, DRMFILE filp) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + i915_mem_release(dev, filp, dev_priv->agp_heap); +} + diff-tree e114b981bc291049fa6996d487334a408acc1ce2 (from b59285d738b1a832b12d9258bd6f1db8f7e61f08) Author: Jesse Barnes <jb...@ho...> Date: Tue Apr 10 10:31:58 2007 -0700 Export drm_setup for use by new driver init code. diff --git a/linux-core/drm_fops.c b/linux-core/drm_fops.c index d400a4d..6f0465f 100644 --- a/linux-core/drm_fops.c +++ b/linux-core/drm_fops.c @@ -41,7 +41,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t * dev); -static int drm_setup(drm_device_t * dev) +int drm_setup(drm_device_t * dev) { drm_local_map_t *map; int i; @@ -121,6 +121,7 @@ static int drm_setup(drm_device_t * dev) return 0; } +EXPORT_SYMBOL(drm_setup); /** * Open file. diff-tree b59285d738b1a832b12d9258bd6f1db8f7e61f08 (from 5130918e2531b9a8f6f6b65cdfce81f4f0904329) Author: Jesse Barnes <jb...@ho...> Date: Tue Apr 10 10:31:10 2007 -0700 Move i915 init code to new file, i915_init.c, and create a new high level init routine that runs at driver load time. diff --git a/linux-core/i915_init.c b/linux-core/i915_init.c new file mode 120000 index 0000000..473ddf7 --- /dev/null +++ b/linux-core/i915_init.c @@ -0,0 +1 @@ +../shared-core/i915_init.c \ No newline at end of file diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index a5f1473..0ba3048 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -78,7 +78,7 @@ void i915_kernel_lost_context(drm_device dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY; } -static int i915_dma_cleanup(drm_device_t * dev) +int i915_dma_cleanup(drm_device_t * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; /* Make sure interrupts are disabled here because the uninstall ioctl @@ -855,78 +855,6 @@ static int i915_mmio(DRM_IOCTL_ARGS) return 0; } -int i915_driver_load(drm_device_t *dev, unsigned long flags) -{ - drm_i915_private_t *dev_priv; - int ret; - unsigned long mmiobase, mmiolen; - - dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER); - if (dev_priv == NULL) - return DRM_ERR(ENOMEM); - - memset(dev_priv, 0, sizeof(drm_i915_private_t)); - dev->dev_private = (void *)dev_priv; -// dev_priv->flags = flags; - - /* i915 has 4 more counters */ - dev->counters += 4; - dev->types[6] = _DRM_STAT_IRQ; - dev->types[7] = _DRM_STAT_PRIMARY; - dev->types[8] = _DRM_STAT_SECONDARY; - dev->types[9] = _DRM_STAT_DMA; - - if (IS_I9XX(dev)) { - dev_priv->mmiobase = drm_get_resource_start(dev, 0); - dev_priv->mmiolen = drm_get_resource_len(dev, 0); - } else if (drm_get_resource_start(dev, 1)) { - dev_priv->mmiobase = drm_get_resource_start(dev, 1); - dev_priv->mmiolen = drm_get_resource_len(dev, 1); - } else { - DRM_ERROR("Unable to find MMIO registers\n"); - return -ENODEV; - } - - ret = drm_addmap(dev, dev_priv->mmiobase, dev_priv->mmiolen, - _DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->mmio_map); - if (ret != 0) { - DRM_ERROR("Cannot add mapping for MMIO registers\n"); - return ret; - } - - DRM_DEBUG("dev_priv->mmio map is %08X\n", dev_priv->mmio_map); - intel_modeset_init(dev); - return 0; -} - -int i915_driver_unload(drm_device_t *dev) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - - intel_modeset_cleanup(dev); - drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); - - dev->dev_private = NULL; - return 0; -} - -void i915_driver_lastclose(drm_device_t * dev) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - - i915_mem_takedown(&(dev_priv->agp_heap)); - - i915_dma_cleanup(dev); - - dev_priv->mmio_map = NULL; -} - -void i915_driver_preclose(drm_device_t * dev, DRMFILE filp) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - i915_mem_release(dev, filp, dev_priv->agp_heap); -} - drm_ioctl_desc_t i915_ioctls[] = { [DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, [DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, DRM_AUTH}, @@ -981,7 +909,7 @@ int i915_driver_firstopen(struct drm_dev } } - DRM_DEBUG("dev_priv->mmio map is %08X\n", dev_priv->mmio_map); + DRM_DEBUG("dev_priv->mmio map is %p\n", dev_priv->mmio_map); return 0; } diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c new file mode 100644 index 0000000..e03ed42 --- /dev/null +++ b/shared-core/i915_init.c @@ -0,0 +1,157 @@ +#include "drmP.h" +#include "drm.h" +#include "drm_sarea.h" +#include "i915_drm.h" +#include "i915_drv.h" + +int i915_driver_load(drm_device_t *dev, unsigned long flags) +{ + drm_i915_private_t *dev_priv; + drm_i915_init_t init; + int ret; + + dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER); + if (dev_priv == NULL) + return DRM_ERR(ENOMEM); + + memset(dev_priv, 0, sizeof(drm_i915_private_t)); + dev->dev_private = (void *)dev_priv; +// dev_priv->flags = flags; + + /* i915 has 4 more counters */ + dev->counters += 4; + dev->types[6] = _DRM_STAT_IRQ; + dev->types[7] = _DRM_STAT_PRIMARY; + dev->types[8] = _DRM_STAT_SECONDARY; + dev->types[9] = _DRM_STAT_DMA; + + if (IS_I9XX(dev)) { + dev_priv->mmiobase = drm_get_resource_start(dev, 0); + dev_priv->mmiolen = drm_get_resource_len(dev, 0); + } else if (drm_get_resource_start(dev, 1)) { + dev_priv->mmiobase = drm_get_resource_start(dev, 1); + dev_priv->mmiolen = drm_get_resource_len(dev, 1); + } else { + DRM_ERROR("Unable to find MMIO registers\n"); + return -ENODEV; + } + + ret = drm_addmap(dev, dev_priv->mmiobase, dev_priv->mmiolen, + _DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->mmio_map); + if (ret != 0) { + DRM_ERROR("Cannot add mapping for MMIO registers\n"); + return ret; + } + + + ret = drm_setup(dev); + if (ret) { + DRM_ERROR("drm_setup failed\n"); + return ret; + } + + DRM_GETSAREA(); + if (!dev_priv->sarea) { + DRM_ERROR("can not find sarea!\n"); + dev->dev_private = (void *)dev_priv; + i915_dma_cleanup(dev); + return DRM_ERR(EINVAL); + } + + /* FIXME: where does the sarea_priv really go? */ + dev_priv->sarea_priv = kmalloc(sizeof(drm_i915_sarea_t), GFP_KERNEL); + + /* FIXME: need real front buffer offset */ + dev_priv->sarea_priv->front_handle = 0xa0000000 + 1024*1024; + + drm_bo_driver_init(dev); + /* this probably doesn't belong here - TODO */ + drm_framebuffer_set_object(dev, dev_priv->sarea_priv->front_handle); + intel_modeset_init(dev); + drm_set_desired_modes(dev); + + /* FIXME: command ring needs AGP space, do we own it at this point? */ + dev_priv->ring.Start = 0xa0000000; + dev_priv->ring.End = 128*1024; + dev_priv->ring.Size = 128*1024; + dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; + + dev_priv->ring.map.offset = dev_priv->ring.Start; + dev_priv->ring.map.size = dev_priv->ring.Size; + dev_priv->ring.map.type = 0; + dev_priv->ring.map.flags = 0; + dev_priv->ring.map.mtrr = 0; + + drm_core_ioremap(&dev_priv->ring.map, dev); + + if (dev_priv->ring.map.handle == NULL) { + dev->dev_private = (void *)dev_priv; + i915_dma_cleanup(dev); + DRM_ERROR("can not ioremap virtual address for" + " ring buffer\n"); + return DRM_ERR(ENOMEM); + } + + dev_priv->ring.virtual_start = dev_priv->ring.map.handle; + dev_priv->cpp = 4; + dev_priv->sarea_priv->pf_current_page = 0; + + /* We are using separate values as placeholders for mechanisms for + * private backbuffer/depthbuffer usage. + */ + dev_priv->use_mi_batchbuffer_start = 0; + + /* Allow hardware batchbuffers unless told otherwise. + */ + dev_priv->allow_batchbuffer = 1; + + /* Program Hardware Status Page */ + dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, + 0xffffffff); + + if (!dev_priv->status_page_dmah) { + dev->dev_private = (void *)dev_priv; + i915_dma_cleanup(dev); + DRM_ERROR("Can not allocate hardware status page\n"); + return DRM_ERR(ENOMEM); + } + dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr; + dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; + + memset(dev_priv->hw_status_page, 0, PAGE_SIZE); + DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page); + + I915_WRITE(0x02080, dev_priv->dma_status_page); + DRM_DEBUG("Enabled hardware status page\n"); + + return 0; +} + +int i915_driver_unload(drm_device_t *dev) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + + intel_modeset_cleanup(dev); + drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); + + dev->dev_private = NULL; + return 0; +} + +void i915_driver_lastclose(drm_device_t * dev) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + + i915_mem_takedown(&(dev_priv->agp_heap)); + + i915_dma_cleanup(dev); + + dev_priv->mmio_map = NULL; +} + +void i915_driver_preclose(drm_device_t * dev, DRMFILE filp) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + i915_mem_release(dev, filp, dev_priv->agp_heap); +} + diff-tree 5130918e2531b9a8f6f6b65cdfce81f4f0904329 (from 8785679f893ef9257c589a70113ac731edba0194) Author: Jesse Barnes <jb...@ho...> Date: Tue Apr 10 09:51:17 2007 -0700 Add save/restore state for LVDS code, along with a few other LVDS related items to i915 private structure. diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index f37f587..6e81f6f 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -133,6 +133,67 @@ typedef struct drm_i915_private { spinlock_t swaps_lock; drm_i915_vbl_swap_t vbl_swaps; unsigned int swaps_pending; + + /* LVDS info */ + int backlight_duty_cycle; /* restore backlight to this value */ + bool panel_wants_dither; + struct drm_display_mode *panel_fixed_mode; + + /* Register state */ + u32 saveDSPACNTR; + u32 saveDSPBCNTR; + u32 savePIPEACONF; + u32 savePIPEBCONF; + u32 savePIPEASRC; + u32 savePIPEBSRC; + u32 saveFPA0; + u32 saveFPA1; + u32 saveDPLL_A; + u32 saveDPLL_A_MD; + u32 saveHTOTAL_A; + u32 saveHBLANK_A; + u32 saveHSYNC_A; + u32 saveVTOTAL_A; + u32 saveVBLANK_A; + u32 saveVSYNC_A; + u32 saveDSPASTRIDE; + u32 saveDSPASIZE; + u32 saveDSPAPOS; + u32 saveDSPABASE; + u32 saveDSPASURF; + u32 saveFPB0; + u32 saveFPB1; + u32 saveDPLL_B; + u32 saveDPLL_B_MD; + u32 saveHTOTAL_B; + u32 saveHBLANK_B; + u32 saveHSYNC_B; + u32 saveVTOTAL_B; + u32 saveVBLANK_B; + u32 saveVSYNC_B; + u32 saveDSPBSTRIDE; + u32 saveDSPBSIZE; + u32 saveDSPBPOS; + u32 saveDSPBBASE; + u32 saveDSPBSURF; + u32 saveVCLK_DIVISOR_VGA0; + u32 saveVCLK_DIVISOR_VGA1; + u32 saveVCLK_POST_DIV; + u32 saveVGACNTRL; + u32 saveADPA; + u32 saveLVDS; + u32 saveDVOA; + u32 saveDVOB; + u32 saveDVOC; + u32 savePP_ON; + u32 savePP_OFF; + u32 savePP_CONTROL; + u32 savePP_CYCLE; + u32 savePFIT_CONTROL; + u32 savePaletteA[256]; + u32 savePaletteB[256]; + u32 saveSWF[17]; + u32 saveBLC_PWM_CTL; } drm_i915_private_t; enum intel_chip_family { @@ -478,6 +539,8 @@ extern int i915_wait_ring(drm_device_t * #define PFIT_CONTROL 0x61230 # define PFIT_ENABLE (1 << 31) +# define PFIT_PIPE_MASK (3 << 29) +# define PFIT_PIPE_SHIFT 29 # define VERT_INTERP_DISABLE (0 << 10) # define VERT_INTERP_BILINEAR (1 << 10) # define VERT_INTERP_MASK (3 << 10) diff-tree 8785679f893ef9257c589a70113ac731edba0194 (from c0336989884e75bcd05284257e884754bb5f85b6) Author: Jesse Barnes <jb...@ho...> Date: Tue Apr 10 09:49:02 2007 -0700 Remove some debug #if 0 codes and add a reminder to check locking around output enumeration stuff. diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index fe27e38..6874265 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -116,6 +116,7 @@ bool drm_crtc_in_use(struct drm_crtc *cr { struct drm_output *output; drm_device_t *dev = crtc->dev; + /* FIXME: Locking around list access? */ list_for_each_entry(output, &dev->crtc_config.output_list, head) if (output->crtc == crtc) return true; @@ -504,7 +505,7 @@ bool drm_initial_config(drm_device_t *de { /* do a hardcoded initial configuration here */ struct drm_crtc *crtc, *vga_crtc = NULL, *dvi_crtc = NULL, - *lvds_crtc = NULL;; + *lvds_crtc = NULL; struct drm_framebuffer *fb; struct drm_output *output, *use_output = NULL; @@ -517,7 +518,7 @@ bool drm_initial_config(drm_device_t *de fb->height = 768; fb->depth = 24; fb->bits_per_pixel = 32; - + /* bind both CRTCs to this fb */ /* only initialise one crtc to enabled state */ list_for_each_entry(crtc, &dev->crtc_config.crtc_list, head) { @@ -533,14 +534,12 @@ bool drm_initial_config(drm_device_t *de crtc->desired_x = 0; crtc->desired_y = 0; } -#if 0 else if (!dvi_crtc) { dvi_crtc = crtc; crtc->enabled = 1; crtc->desired_x = 0; crtc->desired_y = 0; } -#endif } drm_crtc_probe_output_modes(dev, 1024, 768); @@ -565,10 +564,8 @@ bool drm_initial_config(drm_device_t *de use_output = output; } else if (!strncmp(output->name, "TMDS", 4)) { output->crtc = vga_crtc; -#if 0 drm_mode_debug_printmodeline(dev, des_mode); output->crtc->desired_mode = des_mode; -#endif output->initial_x = 0; output->initial_y = 0; } else if (!strncmp(output->name, "LVDS", 3)) { diff-tree c0336989884e75bcd05284257e884754bb5f85b6 (from 183cbd92dd016f8935f9b58ef9345fde1391173e) Author: Jesse Barnes <jb...@ho...> Date: Tue Apr 10 09:48:20 2007 -0700 Remove some delays from Intel i2c code, we'll need a more comprehensive fix in the Linux i2c layer to make DDC reliable on old monitors. diff --git a/linux-core/intel_i2c.c b/linux-core/intel_i2c.c index d4cf7ee..e23283f 100644 --- a/linux-core/intel_i2c.c +++ b/linux-core/intel_i2c.c @@ -80,8 +80,8 @@ static void set_clock(void *data, int st else clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | GPIO_CLOCK_VAL_MASK; + I915_WRITE(chan->reg, reserved | clock_bits); - udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */ } static void set_data(void *data, int state_high) @@ -103,7 +103,6 @@ static void set_data(void *data, int sta GPIO_DATA_VAL_MASK; I915_WRITE(chan->reg, reserved | data_bits); - udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */ } /** @@ -147,7 +146,7 @@ struct intel_i2c_chan *intel_i2c_create( chan->algo.setscl = set_clock; chan->algo.getsda = get_data; chan->algo.getscl = get_clock; - chan->algo.udelay = 20; + chan->algo.udelay = 20; /* between calls to (set|get)_(clock|data) */ chan->algo.timeout = usecs_to_jiffies(2200); chan->algo.data = chan; @@ -159,7 +158,6 @@ struct intel_i2c_chan *intel_i2c_create( /* JJJ: raise SCL and SDA? */ set_data(chan, 1); set_clock(chan, 1); - udelay(20); return chan; diff-tree 183cbd92dd016f8935f9b58ef9345fde1391173e (from c446bf50e3ae730f272c6842f4ad04d523bd40c3) Author: Jesse Barnes <jb...@ho...> Date: Tue Apr 10 09:47:37 2007 -0700 Finish bringing in LVDS code, re-add to Makefile. Needed other changes too: - move EDID structures to drm_edid.h - add EDID info structure to drm_output - add a few routines to intel_display for getting current mode info - add some prototypes to intel_drv.h and drm_crtc.h diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index 1b767b6..ac403f6 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -20,7 +20,7 @@ r128-objs := r128_drv.o r128_cce.o r12 mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o i810-objs := i810_drv.o i810_dma.o i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \ - i915_buffer.o intel_display.o intel_crt.o \ + i915_buffer.o intel_display.o intel_crt.o intel_lvds.o \ intel_sdvo.o intel_modes.o intel_i2c.o nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \ nouveau_object.o nouveau_irq.o \ diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h index 21908f0..775d21e 100644 --- a/linux-core/drm_crtc.h +++ b/linux-core/drm_crtc.h @@ -369,6 +369,7 @@ struct drm_output { /* xf86MonPtr MonInfo; */ enum subpixel_order subpixel_order; int mm_width, mm_height; + struct edid *monitor_info; char name[DRM_OUTPUT_LEN]; const struct drm_output_funcs *funcs; void *driver_private; @@ -455,6 +456,10 @@ extern int drm_mode_vrefresh(struct drm_ extern void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags); extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev); +extern bool drm_initial_config(struct drm_device *dev, bool cangrow); +extern void drm_framebuffer_set_object(struct drm_device *dev, + unsigned long handle); +extern bool drm_set_desired_modes(struct drm_device *dev); #endif /* __DRM_CRTC_H__ */ diff --git a/linux-core/drm_edid.c b/linux-core/drm_edid.c index fcd97d6..b79bc2d 100644 --- a/linux-core/drm_edid.c +++ b/linux-core/drm_edid.c @@ -4,181 +4,14 @@ * * DDC probing routines (drm_ddc_read & drm_do_probe_ddc_edid) originally from * FB layer. + * Copyright (C) 2006 Dennis Munsie <dm...@ce...> */ #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> #include "drmP.h" +#include "drm_edid.h" -#define EDID_LENGTH 128 -#define DDC_ADDR 0x50 - -#ifdef BIG_ENDIAN -#error "EDID structure is little endian, need big endian versions" -#endif - -struct est_timings { - u8 t1; - u8 t2; - u8 mfg_rsvd; -} __attribute__((packed)); - -struct std_timing { - u8 hsize; /* need to multiply by 8 then add 248 */ - u8 vfreq:6; /* need to add 60 */ - u8 aspect_ratio:2; /* 00=16:10, 01=4:3, 10=5:4, 11=16:9 */ -} __attribute__((packed)); - -/* If detailed data is pixel timing */ -struct detailed_pixel_timing { - u8 hactive_lo; - u8 hblank_lo; - u8 hblank_hi:4; - u8 hactive_hi:4; - u8 vactive_lo; - u8 vblank_lo; - u8 vblank_hi:4; - u8 vactive_hi:4; - u8 hsync_offset_lo; - u8 hsync_pulse_width_lo; - u8 vsync_pulse_width_lo:4; - u8 vsync_offset_lo:4; - u8 hsync_pulse_width_hi:2; - u8 hsync_offset_hi:2; - u8 vsync_pulse_width_hi:2; - u8 vsync_offset_hi:2; - u8 width_mm_lo; - u8 height_mm_lo; - u8 height_mm_hi:4; - u8 width_mm_hi:4; - u8 hborder; - u8 vborder; - u8 unknown0:1; - u8 vsync_positive:1; - u8 hsync_positive:1; - u8 separate_sync:2; - u8 stereo:1; - u8 unknown6:1; - u8 interlaced:1; -} __attribute__((packed)); - -/* If it's not pixel timing, it'll be one of the below */ -struct detailed_data_string { - u8 str[13]; -} __attribute__((packed)); - -struct detailed_data_monitor_range { - u8 min_vfreq; - u8 max_vfreq; - u8 min_hfreq_khz; - u8 max_hfreq_khz; - u8 pixel_clock_mhz; /* need to multiply by 10 */ - u16 sec_gtf_toggle; /* A000=use above, 20=use below */ /* FIXME: byte order */ - u8 hfreq_start_khz; /* need to multiply by 2 */ - u8 c; /* need to divide by 2 */ - u16 m; /* FIXME: byte order */ - u8 k; - u8 j; /* need to divide by 2 */ -} __attribute__((packed)); - -struct detailed_data_wpindex { - u8 white_y_lo:2; - u8 white_x_lo:2; - u8 pad:4; - u8 white_x_hi; - u8 white_y_hi; - u8 gamma; /* need to divide by 100 then add 1 */ -} __attribute__((packed)); - -struct detailed_data_color_point { - u8 windex1; - u8 wpindex1[3]; - u8 windex2; - u8 wpindex2[3]; -} __attribute__((packed)); - -struct detailed_non_pixel { - u8 pad1; - u8 type; /* ff=serial, fe=string, fd=monitor range, fc=monitor name - fb=color point data, fa=standard timing data, - f9=undefined, f8=mfg. reserved */ - u8 pad2; - union { - struct detailed_data_string str; - struct detailed_data_monitor_range range; - struct detailed_data_wpindex color; - struct std_timing timings[5]; - } data; -} __attribute__((packed)); - -#define EDID_DETAIL_STD_MODES 0xfa -#define EDID_DETAIL_MONITOR_CPDATA 0xfb -#define EDID_DETAIL_MONITOR_NAME 0xfc -#define EDID_DETAIL_MONITOR_RANGE 0xfd -#define EDID_DETAIL_MONITOR_STRING 0xfe -#define EDID_DETAIL_MONITOR_SERIAL 0xff - -struct detailed_timing { - u16 pixel_clock; /* need to multiply by 10 KHz */ /* FIXME: byte order */ - union { - struct detailed_pixel_timing pixel_data; - struct detailed_non_pixel other_data; - } data; -} __attribute__((packed)); - -struct edid { - u8 header[8]; - /* Vendor & product info */ - u16 mfg_id; /* FIXME: byte order */ - u16 prod_code; /* FIXME: byte order */ - u32 serial; /* FIXME: byte order */ - u8 mfg_week; - u8 mfg_year; - /* EDID version */ - u8 version; - u8 revision; - /* Display info: */ - /* input definition */ - u8 serration_vsync:1; - u8 sync_on_green:1; - u8 composite_sync:1; - u8 separate_syncs:1; - u8 blank_to_black:1; - u8 video_level:2; - u8 digital:1; /* bits below must be zero if set */ - u8 width_cm; - u8 height_cm; - u8 gamma; - /* feature support */ - u8 default_gtf:1; - u8 preferred_timing:1; - u8 standard_color:1; - u8 display_type:2; /* 00=mono, 01=rgb, 10=non-rgb, 11=unknown */ - u8 pm_active_off:1; - u8 pm_suspend:1; - u8 pm_standby:1; - /* Color characteristics */ - u8 red_green_lo; - u8 black_white_lo; - u8 red_x; - u8 red_y; - u8 green_x; - u8 green_y; - u8 blue_x; - u8 blue_y; - u8 white_x; - u8 white_y; - /* Est. timings and mfg rsvd timings*/ - struct est_timings established_timings; - /* Standard timings 1-8*/ - struct std_timing standard_timings[8]; - /* Detailing timings 1-4 */ - struct detailed_timing detailed_timings[4]; - /* Number of 128 byte ext. blocks */ - u8 extensions; - /* Checksum */ - u8 checksum; -} __attribute__((packed)); - +/* Valid EDID header has these bytes */ static u8 edid_header[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; /** diff --git a/linux-core/drm_edid.h b/linux-core/drm_edid.h new file mode 100644 index 0000000..0d2eeaa --- /dev/null +++ b/linux-core/drm_edid.h @@ -0,0 +1,176 @@ +#ifndef __DRM_EDID_H__ +#define __DRM_EDID_H__ + +#include <linux/types.h> + +#define EDID_LENGTH 128 +#define DDC_ADDR 0x50 + +#ifdef BIG_ENDIAN +#error "EDID structure is little endian, need big endian versions" +#endif + +struct est_timings { + u8 t1; + u8 t2; + u8 mfg_rsvd; +} __attribute__((packed)); + +struct std_timing { + u8 hsize; /* need to multiply by 8 then add 248 */ + u8 vfreq:6; /* need to add 60 */ + u8 aspect_ratio:2; /* 00=16:10, 01=4:3, 10=5:4, 11=16:9 */ +} __attribute__((packed)); + +/* If detailed data is pixel timing */ +struct detailed_pixel_timing { + u8 hactive_lo; + u8 hblank_lo; + u8 hblank_hi:4; + u8 hactive_hi:4; + u8 vactive_lo; + u8 vblank_lo; + u8 vblank_hi:4; + u8 vactive_hi:4; + u8 hsync_offset_lo; + u8 hsync_pulse_width_lo; + u8 vsync_pulse_width_lo:4; + u8 vsync_offset_lo:4; + u8 hsync_pulse_width_hi:2; + u8 hsync_offset_hi:2; + u8 vsync_pulse_width_hi:2; + u8 vsync_offset_hi:2; + u8 width_mm_lo; + u8 height_mm_lo; + u8 height_mm_hi:4; + u8 width_mm_hi:4; + u8 hborder; + u8 vborder; + u8 unknown0:1; + u8 vsync_positive:1; + u8 hsync_positive:1; + u8 separate_sync:2; + u8 stereo:1; + u8 unknown6:1; + u8 interlaced:1; +} __attribute__((packed)); + +/* If it's not pixel timing, it'll be one of the below */ +struct detailed_data_string { + u8 str[13]; +} __attribute__((packed)); + +struct detailed_data_monitor_range { + u8 min_vfreq; + u8 max_vfreq; + u8 min_hfreq_khz; + u8 max_hfreq_khz; + u8 pixel_clock_mhz; /* need to multiply by 10 */ + u16 sec_gtf_toggle; /* A000=use above, 20=use below */ /* FIXME: byte order */ + u8 hfreq_start_khz; /* need to multiply by 2 */ + u8 c; /* need to divide by 2 */ + u16 m; /* FIXME: byte order */ + u8 k; + u8 j; /* need to divide by 2 */ +} __attribute__((packed)); + +struct detailed_data_wpindex { + u8 white_y_lo:2; + u8 white_x_lo:2; + u8 pad:4; + u8 white_x_hi; + u8 white_y_hi; + u8 gamma; /* need to divide by 100 then add 1 */ +} __attribute__((packed)); + +struct detailed_data_color_point { + u8 windex1; + u8 wpindex1[3]; + u8 windex2; + u8 wpindex2[3]; +} __attribute__((packed)); + +struct detailed_non_pixel { + u8 pad1; + u8 type; /* ff=serial, fe=string, fd=monitor range, fc=monitor name + fb=color point data, fa=standard timing data, + f9=undefined, f8=mfg. reserved */ + u8 pad2; + union { + struct detailed_data_string str; + struct detailed_data_monitor_range range; + struct detailed_data_wpindex color; + struct std_timing timings[5]; + } data; +} __attribute__((packed)); + +#define EDID_DETAIL_STD_MODES 0xfa +#define EDID_DETAIL_MONITOR_CPDATA 0xfb +#define EDID_DETAIL_MONITOR_NAME 0xfc +#define EDID_DETAIL_MONITOR_RANGE 0xfd +#define EDID_DETAIL_MONITOR_STRING 0xfe +#define EDID_DETAIL_MONITOR_SERIAL 0xff + +struct detailed_timing { + u16 pixel_clock; /* need to multiply by 10 KHz */ /* FIXME: byte order */ + union { + struct detailed_pixel_timing pixel_data; + struct detailed_non_pixel other_data; + } data; +} __attribute__((packed)); + +struct edid { + u8 header[8]; + /* Vendor & product info */ + u16 mfg_id; /* FIXME: byte order */ + u16 prod_code; /* FIXME: byte order */ + u32 serial; /* FIXME: byte order */ + u8 mfg_week; + u8 mfg_year; + /* EDID version */ + u8 version; + u8 revision; + /* Display info: */ + /* input definition */ + u8 serration_vsync:1; + u8 sync_on_green:1; + u8 composite_sync:1; + u8 separate_syncs:1; + u8 blank_to_black:1; + u8 video_level:2; + u8 digital:1; /* bits below must be zero if set */ + u8 width_cm; + u8 height_cm; + u8 gamma; + /* feature support */ + u8 default_gtf:1; + u8 preferred_timing:1; + u8 standard_color:1; + u8 display_type:2; /* 00=mono, 01=rgb, 10=non-rgb, 11=unknown */ + u8 pm_active_off:1; + u8 pm_suspend:1; + u8 pm_standby:1; + /* Color characteristics */ + u8 red_green_lo; + u8 black_white_lo; + u8 red_x; + u8 red_y; + u8 green_x; + u8 green_y; + u8 blue_x; + u8 blue_y; + u8 white_x; + u8 white_y; + /* Est. timings and mfg rsvd timings*/ + struct est_timings established_timings; + /* Standard timings 1-8*/ + struct std_timing standard_timings[8]; + /* Detailing timings 1-4 */ + struct detailed_timing detailed_timings[4]; + /* Number of 128 byte ext. blocks */ + u8 extensions; + /* Checksum */ + u8 checksum; +} __attribute__((packed)); + +#endif /* __DRM_EDID_H__ */ diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 58d6698..90c894e 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -26,8 +26,6 @@ #include <linux/i2c.h> #include "drmP.h" -#include "drm.h" -#include "drm_crtc.h" #include "intel_drv.h" #include "i915_drm.h" #include "i915_drv.h" @@ -973,10 +971,115 @@ static void intel_crtc_gamma_set(struct intel_crtc_load_lut(crtc); } +/* Returns the clock of the currently programmed mode of the given pipe. */ +static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = crtc->driver_private; + int pipe = intel_crtc->pipe; + u32 dpll = I915_READ((pipe == 0) ? DPLL_A : DPLL_B); + u32 fp; + intel_clock_t clock; + + if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) + fp = I915_READ((pipe == 0) ? FPA0 : FPB0); + else + fp = I915_READ((pipe == 0) ? FPA1 : FPB1); + + clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; + clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; + clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT; + if (IS_I9XX(dev)) { + clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >> + DPLL_FPA01_P1_POST_DIV_SHIFT); + + switch (dpll & DPLL_MODE_MASK) { + case DPLLB_MODE_DAC_SERIAL: + clock.p2 = dpll & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ? + 5 : 10; + break; + case DPLLB_MODE_LVDS: + clock.p2 = dpll & DPLLB_LVDS_P2_CLOCK_DIV_7 ? + 7 : 14; + break; + default: + DRM_DEBUG("Unknown DPLL mode %08x in programmed " + "mode\n", (int)(dpll & DPLL_MODE_MASK)); + return 0; + } + + /* XXX: Handle the 100Mhz refclk */ + i9xx_clock(96000, &clock); + } else { + bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN); + + if (is_lvds) { + clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >> + DPLL_FPA01_P1_POST_DIV_SHIFT); + clock.p2 = 14; + + if ((dpll & PLL_REF_INPUT_MASK) == + PLLB_REF_INPUT_SPREADSPECTRUMIN) { + /* XXX: might not be 66MHz */ + i8xx_clock(66000, &clock); + } else + i8xx_clock(48000, &clock); + } else { + if (dpll & PLL_P1_DIVIDE_BY_TWO) + clock.p1 = 2; + else { + clock.p1 = ((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830) >> + DPLL_FPA01_P1_POST_DIV_SHIFT) + 2; + } + if (dpll & PLL_P2_DIVIDE_BY_4) + clock.p2 = 4; + else + clock.p2 = 2; + + i8xx_clock(48000, &clock); + } + } + + /* XXX: It would be nice to validate the clocks, but we can't reuse + * i830PllIsValid() because it relies on the xf86_config output + * configuration being accurate, which it isn't necessarily. + */ + + return clock.dot; +} + +/** Returns the currently programmed mode of the given pipe. */ struct drm_display_mode *intel_crtc_mode_get(drm_device_t *dev, struct drm_crtc *crtc) { - return NULL; + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = crtc->driver_private; + int pipe = intel_crtc->pipe; + struct drm_display_mode *mode; + int htot = I915_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B); + int hsync = I915_READ((pipe == 0) ? HSYNC_A : HSYNC_B); + int vtot = I915_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B); + int vsync = I915_READ((pipe == 0) ? VSYNC_A : VSYNC_B); + + mode = kzalloc(sizeof(*mode), GFP_KERNEL); + if (!mode) + return NULL; + + mode->clock = intel_crtc_clock_get(dev, crtc); + mode->hdisplay = (htot & 0xffff) + 1; + mode->htotal = ((htot & 0xffff0000) >> 16) + 1; + mode->hsync_start = (hsync & 0xffff) + 1; + mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1; + mode->vdisplay = (vtot & 0xffff) + 1; + mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1; + mode->vsync_start = (vsync & 0xffff) + 1; + mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1; + /* FIXME: pull name generation into a common routine */ + snprintf(mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d", mode->hdisplay, + mode->vdisplay); + drm_mode_set_crtcinfo(mode, 0); + + return mode; } static const struct drm_crtc_funcs intel_crtc_funcs = { @@ -1017,7 +1120,7 @@ void intel_crtc_init(drm_device_t *dev, crtc->driver_private = intel_crtc; } -int intel_output_clones (drm_device_t *dev, int type_mask) +int intel_output_clones(drm_device_t *dev, int type_mask) { int index_mask = 0; struct drm_output *output; @@ -1039,9 +1142,11 @@ static void intel_setup_outputs(drm_devi intel_crt_init(dev); +#if 0 /* Set up integrated LVDS */ if (IS_MOBILE(dev) && !IS_I830(dev)) intel_lvds_init(dev); +#endif if (IS_I9XX(dev)) { intel_sdvo_init(dev, SDVOB); @@ -1105,6 +1210,7 @@ void intel_modeset_init(drm_device_t *de intel_setup_outputs(dev); drm_initial_config(dev, false); + drm_set_desired_modes(dev); } void intel_modeset_cleanup(drm_device_t *dev) diff --git a/linux-core/intel_drv.h b/linux-core/intel_drv.h index 7b02d35..0675e06 100644 --- a/linux-core/intel_drv.h +++ b/linux-core/intel_drv.h @@ -71,4 +71,7 @@ extern void intel_lvds_init(drm_device_t extern void intel_crtc_load_lut(struct drm_crtc *crtc); extern void intel_output_prepare (struct drm_output *output); extern void intel_output_commit (struct drm_output *output); +extern struct drm_display_mode *intel_crtc_mode_get(drm_device_t *dev, + struct drm_crtc *crtc); + #endif /* __INTEL_DRV_H__ */ diff --git a/linux-core/intel_lvds.c b/linux-core/intel_lvds.c index 7527dfc..4638fb3 100644 --- a/linux-core/intel_lvds.c +++ b/linux-core/intel_lvds.c @@ -31,6 +31,7 @@ #include "drmP.h" #include "drm.h" #include "drm_crtc.h" +#include "drm_edid.h" #include "intel_drv.h" #include "i915_drm.h" #include "i915_drv.h" @@ -262,7 +263,7 @@ static int intel_lvds_get_modes(struct d struct intel_output *intel_output = output->driver_private; struct drm_device *dev = output->dev; drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_monitor_info *edid_mon; + struct edid *edid_info; int ret = 0; intel_output->ddc_bus = intel_i2c_create(dev, GPIOC, "LVDSDDC_C"); @@ -276,23 +277,29 @@ static int intel_lvds_get_modes(struct d ret = intel_ddc_get_modes(output); if (ret) return ret; -#if 0 + + /* Didn't get an EDID */ if (!output->monitor_info) { - edid_mon = kzalloc(sizeof(*output->monitor_info), GFP_KERNEL); - if (edid_mon) { - /* Set wide sync ranges so we get all modes - * handed to valid_mode for checking - */ - edid_mon->det_mon[0].type = DS_RANGES; - edid_mon->det_mon[0].section.ranges.min_v = 0; - edid_mon->det_mon[0].section.ranges.max_v = 200; - edid_mon->det_mon[0].section.ranges.min_h = 0; - edid_mon->det_mon[0].section.ranges.max_h = 200; - - output->monitor_info = edid_mon; - } + struct detailed_data_monitor_range *edid_range; + edid_info = kzalloc(sizeof(*output->monitor_info), GFP_KERNEL); + if (!edid_info) + goto out; + + edid_info->detailed_timings[0].data.other_data.type = + EDID_DETAIL_MONITOR_RANGE; + edid_range = &edid_info->detailed_timings[0].data.other_data.data.range; + + /* Set wide sync ranges so we get all modes + * handed to valid_mode for checking + */ + edid_range->min_vfreq = 0; + edid_range->max_vfreq = 200; + edid_range->min_hfreq_khz = 0; + edid_range->max_hfreq_khz = 200; + output->monitor_info = edid_info; } -#endif + +out: if (dev_priv->panel_fixed_mode != NULL) { struct drm_display_mode *mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode); @@ -322,13 +329,19 @@ static const struct drm_output_funcs int .cleanup = intel_lvds_destroy }; -void -intel_lvds_init(struct drm_device *dev) +/** + * intel_lvds_init - setup LVDS outputs on this device + * @dev: drm device + * + * Create the output, register the LVDS DDC bus, and try to figure out what + * modes we can display on the LVDS panel (if present). + */ +void intel_lvds_init(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; struct drm_output *output; struct intel_output *intel_output; - struct drm_display_mode *modes, scan, bios_mode; + struct drm_display_mode *scan; /* *modes, *bios_mode; */ output = drm_output_create(dev, &intel_lvds_output_funcs, "LVDS"); if (!output) @@ -356,37 +369,43 @@ intel_lvds_init(struct drm_device *dev) break; } - if (scan != NULL) + if (scan) dev_priv->panel_fixed_mode = scan; -#if 0 /* * If we didn't get EDID, try checking if the panel is already turned * on. If so, assume that whatever is currently programmed is the * correct mode. */ - if (dev_priv->panel_fixed_mode == NULL) { + if (!dev_priv->panel_fixed_mode) { u32 lvds = I915_READ(LVDS); int pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; - struct drm_crtc_config *crtc_config = dev->crtc_config; - struct drm_crtc *crtc = crtc_config->crtc[pipe]; - - if (lvds & LVDS_PORT_EN) { - dev_priv->panel_fixed_mode = intel_crtc_mode_get(pScrn, crtc); - if (dev_priv->panel_fixed_mode != NULL) - dev_priv->panel_fixed_mode->type |= M_T_PREFERRED; + struct drm_crtc_config *crtc_config = &dev->crtc_config; + struct drm_crtc *crtc; + /* FIXME: need drm_crtc_from_pipe */ + //crtc = drm_crtc_from_pipe(crtc_config, pipe); + + if (lvds & LVDS_PORT_EN && 0) { + dev_priv->panel_fixed_mode = + intel_crtc_mode_get(dev, crtc); + if (dev_priv->panel_fixed_mode) + dev_priv->panel_fixed_mode->type |= + DRM_MODE_TYPE_PREFERRED; } } - /* Get the LVDS fixed mode out of the BIOS. We should support LVDS with - * the BIOS being unavailable or broken, but lack the configuration options - * for now. +/* No BIOS poking yet... */ +#if 0 + /* Get the LVDS fixed mode out of the BIOS. We should support LVDS + * with the BIOS being unavailable or broken, but lack the + * configuration options for now. */ bios_mode = intel_bios_get_panel_mode(pScrn); if (bios_mode != NULL) { if (dev_priv->panel_fixed_mode != NULL) { if (dev_priv->debug_modes && - !xf86ModesEqual(dev_priv->panel_fixed_mode, bios_mode)) + !xf86ModesEqual(dev_priv->panel_fixed_mode, + bios_mode)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "BIOS panel mode data doesn't match probed data, " @@ -439,35 +458,3 @@ intel_lvds_init(struct drm_device *dev) #endif return; } - -#if 0 -/** - * intel_lvds_init - setup LVDS outputs on this device - * @dev: drm device - * - * Create the output, register the LVDS DDC bus, and try to figure out what - * modes we can display on the LVDS panel (if present). - */ -void intel_lvds_init(drm_device_t *dev) -{ - struct drm_output *output; - struct intel_output *intel_output; - int modes; - - output = drm_output_create(dev, &intel_lvds_output_funcs, "LVDS"); - if (!output) - return; - - intel_output = kmalloc(sizeof(struct intel_output), GFP_KERNEL); - if (!intel_output) { - drm_output_destroy(output); - return; - } - - intel_output->type = INTEL_OUTPUT_LVDS; - output->driver_private = intel_output; - output->subpixel_order = SubPixelHorizontalRGB; - output->interlace_allowed = 0; - output->doublescan_allowed = 0; -} -#endif diff-tree c446bf50e3ae730f272c6842f4ad04d523bd40c3 (from 7e2b1a6cf55579c6f8b1fd56a97e9f41e34b88fc) Author: Jesse Barnes <jb...@ho...> Date: Mon Apr 9 20:46:38 2007 -0700 Slam in most of X.Org's i830_lvds (not quite done yet so removed from Makefile.kernel too). diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index ac403f6..1b767b6 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -20,7 +20,7 @@ r128-objs := r128_drv.o r128_cce.o r12 mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o i810-objs := i810_drv.o i810_dma.o i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \ - i915_buffer.o intel_display.o intel_crt.o intel_lvds.o \ + i915_buffer.o intel_display.o intel_crt.o \ intel_sdvo.o intel_modes.o intel_i2c.o nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \ nouveau_object.o nouveau_irq.o \ diff --git a/linux-core/intel_lvds.c b/linux-core/intel_lvds.c index a444f14..7527dfc 100644 --- a/linux-core/intel_lvds.c +++ b/linux-core/intel_lvds.c @@ -1,5 +1,6 @@ /* * Copyright © 2006-2007 Intel Corporation + * Copyright (c) 2006 Dave Airlie <ai...@li...> * * Permission is hereby grante... [truncated message content] |
From: <al...@ke...> - 2008-02-26 15:42:53
|
linux-core/i915_drv.c | 1 shared-core/i915_dma.c | 282 ++++++++++++++++++++++++++++++++------------- shared-core/nouveau_dma.c | 29 +--- shared-core/nouveau_drm.h | 6 shared-core/nouveau_fifo.c | 5 shared-core/radeon_state.c | 14 +- 6 files changed, 230 insertions(+), 107 deletions(-) New commits: commit 1e66322633943bc27bf5e68609f564fa95e6e6a1 Merge: 73cb02b... e87cec1... Author: Alan Hourihane <al...@tu...> Date: Tue Feb 26 15:42:41 2008 +0000 Merge branch 'master' of git+ssh://git.freedesktop.org/git/mesa/drm into modesetting-101 Conflicts: shared-core/i915_dma.c diff --cc shared-core/i915_dma.c index 727aeee,b916441..eee24dd --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@@ -1032,48 -1109,146 +1069,146 @@@ int i915_validate_buffer_list(struct dr DRM_MEMORYBARRIER(); } - rep.ret = drm_bo_handle_validate(file_priv, req->bo_req.handle, - req->bo_req.flags, req->bo_req.mask, - req->bo_req.hint, - req->bo_req.fence_class, 0, - &rep.bo_info, - &buffers[buf_count].buffer); + ret = drm_bo_handle_validate(file_priv, req->bo_req.handle, + req->bo_req.flags, req->bo_req.mask, + req->bo_req.hint, + req->bo_req.fence_class, 0, + &item->rep, + &item->buffer); + + if (ret) { + DRM_ERROR("error on handle validate %d\n", ret); + goto out_err; + } + + buf_count++; - if (rep.ret) { - DRM_ERROR("error on handle validate %d\n", rep.ret); + ret = i915_check_presumed(&arg, item->buffer, + (uint32_t __user *) + (unsigned long) data, + &item->presumed_offset_correct); + if (ret) goto out_err; + + data = arg.next; + } while (data != 0); + out_err: + *num_buffers = buf_count; + item->ret = (ret != -EAGAIN) ? ret : 0; + return ret; + } + + + /* + * Remove all buffers from the unfenced list. + * If the execbuffer operation was aborted, for example due to a signal, + * this also make sure that buffers retain their original state and + * fence pointers. + * Copy back buffer information to user-space unless we were interrupted + * by a signal. In which case the IOCTL must be rerun. + */ + + static int i915_handle_copyback(struct drm_device *dev, + struct drm_i915_validate_buffer *buffers, + unsigned int num_buffers, int ret) + { + int err = ret; + int i; + struct drm_i915_op_arg arg; + + if (ret) + drm_putback_buffer_objects(dev); + + if (ret != -EAGAIN) { + for (i = 0; i < num_buffers; ++i) { + arg.handled = 1; + arg.d.rep.ret = buffers->ret; + arg.d.rep.bo_info = buffers->rep; + if (__copy_to_user(buffers->data, &arg, sizeof(arg))) + err = -EFAULT; + buffers++; } + } + + return err; + } + + /* + * Create a fence object, and if that fails, pretend that everything is + * OK and just idle the GPU. + */ + + void i915_fence_or_sync(struct drm_file *file_priv, + uint32_t fence_flags, + struct drm_fence_arg *fence_arg, + struct drm_fence_object **fence_p) + { - struct drm_device *dev = file_priv->head->dev; ++ struct drm_device *dev = file_priv->minor->dev; + int ret; + struct drm_fence_object *fence; + + ret = drm_fence_buffer_objects(dev, NULL, fence_flags, + NULL, &fence); + + if (ret) { + /* - * If the user provided a presumed offset hint, check whether - * the buffer is in the same place, if so, relocations relative to - * this buffer need not be performed + * Fence creation failed. + * Fall back to synchronous operation and idle the engine. */ - if ((req->bo_req.hint & DRM_BO_HINT_PRESUMED_OFFSET) && - buffers[buf_count].buffer->offset == req->bo_req.presumed_offset) { - buffers[buf_count].presumed_offset_correct = 1; - } - next = arg.next; - arg.handled = 1; - arg.d.rep = rep; + (void) i915_emit_mi_flush(dev, MI_READ_FLUSH); + (void) i915_quiescent(dev); - if (copy_to_user((void __user *)(unsigned long)data, &arg, sizeof(arg))) - return -EFAULT; + if (!(fence_flags & DRM_FENCE_FLAG_NO_USER)) { - data = next; - buf_count++; + /* + * Communicate to user-space that + * fence creation has failed and that + * the engine is idle. + */ - } while (next != 0); - *num_buffers = buf_count; - return 0; - out_err: - mutex_lock(&dev->struct_mutex); - i915_dereference_buffers_locked(buffers, buf_count); - mutex_unlock(&dev->struct_mutex); - *num_buffers = 0; - return (ret) ? ret : rep.ret; + fence_arg->handle = ~0; + fence_arg->error = ret; + } + + drm_putback_buffer_objects(dev); + if (fence_p) + *fence_p = NULL; + return; + } + + if (!(fence_flags & DRM_FENCE_FLAG_NO_USER)) { + + ret = drm_fence_add_user_object(file_priv, fence, + fence_flags & + DRM_FENCE_FLAG_SHAREABLE); + if (!ret) + drm_fence_fill_arg(fence, fence_arg); + else { + /* + * Fence user object creation failed. + * We must idle the engine here as well, as user- + * space expects a fence object to wait on. Since we + * have a fence object we wait for it to signal + * to indicate engine "sufficiently" idle. + */ + + (void) drm_fence_object_wait(fence, 0, 1, + fence->type); + drm_fence_usage_deref_unlocked(&fence); + fence_arg->handle = ~0; + fence_arg->error = ret; + } + } + + if (fence_p) + *fence_p = fence; + else if (fence) + drm_fence_usage_deref_unlocked(&fence); } + static int i915_execbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) { commit e87cec19687089f9f268ec0eb81b57e6fb8de6a9 Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> Date: Tue Feb 26 10:47:05 2008 +0100 [i915] Relocation fixes. diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 4f41a68..b916441 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -833,6 +833,10 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, int ret, i; int buf_index = -1; + /* + * FIXME: O(relocs * buffers) complexity. + */ + for (i = 0; i <= num_buffers; i++) if (buffers[i].buffer) if (reloc[2] == buffers[i].buffer->base.hash.key) @@ -854,21 +858,14 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, if (!relocatee->data_page || !drm_bo_same_page(relocatee->offset, new_cmd_offset)) { drm_bo_kunmap(&relocatee->kmap); + relocatee->data_page = NULL; relocatee->offset = new_cmd_offset; - mutex_lock (&relocatee->buf->mutex); - ret = drm_bo_wait (relocatee->buf, 0, 0, FALSE); - mutex_unlock (&relocatee->buf->mutex); - if (ret) { - DRM_ERROR("Could not wait for buffer to apply relocs\n %08lx", new_cmd_offset); - return ret; - } ret = drm_bo_kmap(relocatee->buf, new_cmd_offset >> PAGE_SHIFT, 1, &relocatee->kmap); if (ret) { DRM_ERROR("Could not map command buffer to apply relocs\n %08lx", new_cmd_offset); return ret; } - relocatee->data_page = drm_bmo_virtual(&relocatee->kmap, &relocatee->is_iomem); relocatee->page_offset = (relocatee->offset & PAGE_MASK); @@ -887,7 +884,11 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, reloc[0], reloc[1], buf_index, relocatee->data_page[index], val); } } - relocatee->data_page[index] = val; + + if (relocatee->is_iomem) + iowrite32(val, relocatee->data_page + index); + else + relocatee->data_page[index] = val; return 0; } @@ -955,11 +956,13 @@ int i915_process_relocs(struct drm_file *file_priv, } out: - if (reloc_buf) kfree(reloc_buf); - drm_bo_kunmap(&relocatee->kmap); - relocatee->data_page = NULL; + + if (relocatee->data_page) { + drm_bo_kunmap(&relocatee->kmap); + relocatee->data_page = NULL; + } return ret; } @@ -999,18 +1002,22 @@ static int i915_exec_reloc(struct drm_file *file_priv, drm_handle_t buf_handle, goto out_err; } + mutex_lock (&relocatee.buf->mutex); + ret = drm_bo_wait (relocatee.buf, 0, 0, FALSE); + if (ret) + goto out_err1; + while (reloc_user_ptr) { ret = i915_process_relocs(file_priv, buf_handle, &reloc_user_ptr, &relocatee, buffers, buf_count); if (ret) { DRM_ERROR("process relocs failed\n"); - break; + goto out_err1; } } - mutex_lock(&dev->struct_mutex); - drm_bo_usage_deref_locked(&relocatee.buf); - mutex_unlock(&dev->struct_mutex); - +out_err1: + mutex_unlock (&relocatee.buf->mutex); + drm_bo_usage_deref_unlocked(&relocatee.buf); out_err: return ret; } @@ -1190,12 +1197,9 @@ void i915_fence_or_sync(struct drm_file *file_priv, * Fall back to synchronous operation and idle the engine. */ + (void) i915_emit_mi_flush(dev, MI_READ_FLUSH); (void) i915_quiescent(dev); - /* - * FIXME: Might need a sync flush here. - */ - if (!(fence_flags & DRM_FENCE_FLAG_NO_USER)) { /* commit 56bb29cf37c27b283efcd1a32d3583393e5208ea Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> Date: Tue Feb 26 00:01:09 2008 +0100 Make the execbuffer code reasonably safe against errors. In particular -EAGAINs, which should be common during Xserver operation. Also handle the fence creation failure case. diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 7da8d55..4f41a68 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -809,7 +809,10 @@ struct i915_relocatee_info { struct drm_i915_validate_buffer { struct drm_buffer_object *buffer; + struct drm_bo_info_rep rep; int presumed_offset_correct; + void __user *data; + int ret; }; static void i915_dereference_buffers_locked(struct drm_i915_validate_buffer *buffers, @@ -1012,6 +1015,40 @@ out_err: return ret; } +static int i915_check_presumed(struct drm_i915_op_arg *arg, + struct drm_buffer_object *bo, + uint32_t __user *data, + int *presumed_ok) +{ + struct drm_bo_op_req *req = &arg->d.req; + uint32_t hint_offset; + uint32_t hint = req->bo_req.hint; + + *presumed_ok = 0; + + if (!(hint & DRM_BO_HINT_PRESUMED_OFFSET)) + return 0; + if (bo->offset == req->bo_req.presumed_offset) { + *presumed_ok = 1; + return 0; + } + + /* + * We need to turn off the HINT_PRESUMED_OFFSET for this buffer in + * the user-space IOCTL argument list, since the buffer has moved, + * we're about to apply relocations and we might subsequently + * hit an -EAGAIN. In that case the argument list will be reused by + * user-space, but the presumed offset is no longer valid. + * + * Needless to say, this is a bit ugly. + */ + + hint_offset = (uint32_t *)&req->bo_req.hint - (uint32_t *)arg; + hint &= ~DRM_BO_HINT_PRESUMED_OFFSET; + return __put_user(hint, data + hint_offset); +} + + /* * Validate, add fence and relocate a block of bos from a userspace list */ @@ -1022,13 +1059,11 @@ int i915_validate_buffer_list(struct drm_file *file_priv, { struct drm_i915_op_arg arg; struct drm_bo_op_req *req = &arg.d.req; - struct drm_bo_arg_rep rep; - unsigned long next = 0; int ret = 0; unsigned buf_count = 0; - struct drm_device *dev = file_priv->head->dev; uint32_t buf_handle; uint32_t __user *reloc_user_ptr; + struct drm_i915_validate_buffer *item = buffers; do { if (buf_count >= *num_buffers) { @@ -1036,31 +1071,26 @@ int i915_validate_buffer_list(struct drm_file *file_priv, ret = -EINVAL; goto out_err; } + item = buffers + buf_count; + item->buffer = NULL; + item->presumed_offset_correct = 0; buffers[buf_count].buffer = NULL; - buffers[buf_count].presumed_offset_correct = 0; if (copy_from_user(&arg, (void __user *)(unsigned long)data, sizeof(arg))) { ret = -EFAULT; goto out_err; } - if (arg.handled) { - data = arg.next; - mutex_lock(&dev->struct_mutex); - buffers[buf_count].buffer = drm_lookup_buffer_object(file_priv, req->arg_handle, 1); - mutex_unlock(&dev->struct_mutex); - buf_count++; - continue; - } - - rep.ret = 0; + ret = 0; if (req->op != drm_bo_validate) { DRM_ERROR ("Buffer object operation wasn't \"validate\".\n"); - rep.ret = -EINVAL; + ret = -EINVAL; goto out_err; } + item->ret = 0; + item->data = (void __user *) (unsigned long) data; buf_handle = req->bo_req.handle; reloc_user_ptr = (uint32_t *)(unsigned long)arg.reloc_ptr; @@ -1072,48 +1102,149 @@ int i915_validate_buffer_list(struct drm_file *file_priv, DRM_MEMORYBARRIER(); } - rep.ret = drm_bo_handle_validate(file_priv, req->bo_req.handle, - req->bo_req.flags, req->bo_req.mask, - req->bo_req.hint, - req->bo_req.fence_class, 0, - &rep.bo_info, - &buffers[buf_count].buffer); + ret = drm_bo_handle_validate(file_priv, req->bo_req.handle, + req->bo_req.flags, req->bo_req.mask, + req->bo_req.hint, + req->bo_req.fence_class, 0, + &item->rep, + &item->buffer); + + if (ret) { + DRM_ERROR("error on handle validate %d\n", ret); + goto out_err; + } + + buf_count++; - if (rep.ret) { - DRM_ERROR("error on handle validate %d\n", rep.ret); + ret = i915_check_presumed(&arg, item->buffer, + (uint32_t __user *) + (unsigned long) data, + &item->presumed_offset_correct); + if (ret) goto out_err; + + data = arg.next; + } while (data != 0); +out_err: + *num_buffers = buf_count; + item->ret = (ret != -EAGAIN) ? ret : 0; + return ret; +} + + +/* + * Remove all buffers from the unfenced list. + * If the execbuffer operation was aborted, for example due to a signal, + * this also make sure that buffers retain their original state and + * fence pointers. + * Copy back buffer information to user-space unless we were interrupted + * by a signal. In which case the IOCTL must be rerun. + */ + +static int i915_handle_copyback(struct drm_device *dev, + struct drm_i915_validate_buffer *buffers, + unsigned int num_buffers, int ret) +{ + int err = ret; + int i; + struct drm_i915_op_arg arg; + + if (ret) + drm_putback_buffer_objects(dev); + + if (ret != -EAGAIN) { + for (i = 0; i < num_buffers; ++i) { + arg.handled = 1; + arg.d.rep.ret = buffers->ret; + arg.d.rep.bo_info = buffers->rep; + if (__copy_to_user(buffers->data, &arg, sizeof(arg))) + err = -EFAULT; + buffers++; } + } + + return err; +} + +/* + * Create a fence object, and if that fails, pretend that everything is + * OK and just idle the GPU. + */ + +void i915_fence_or_sync(struct drm_file *file_priv, + uint32_t fence_flags, + struct drm_fence_arg *fence_arg, + struct drm_fence_object **fence_p) +{ + struct drm_device *dev = file_priv->head->dev; + int ret; + struct drm_fence_object *fence; + + ret = drm_fence_buffer_objects(dev, NULL, fence_flags, + NULL, &fence); + + if (ret) { + /* - * If the user provided a presumed offset hint, check whether - * the buffer is in the same place, if so, relocations relative to - * this buffer need not be performed + * Fence creation failed. + * Fall back to synchronous operation and idle the engine. */ - if ((req->bo_req.hint & DRM_BO_HINT_PRESUMED_OFFSET) && - buffers[buf_count].buffer->offset == req->bo_req.presumed_offset) { - buffers[buf_count].presumed_offset_correct = 1; - } - next = arg.next; - arg.handled = 1; - arg.d.rep = rep; + (void) i915_quiescent(dev); - if (copy_to_user((void __user *)(unsigned long)data, &arg, sizeof(arg))) - return -EFAULT; + /* + * FIXME: Might need a sync flush here. + */ - data = next; - buf_count++; + if (!(fence_flags & DRM_FENCE_FLAG_NO_USER)) { - } while (next != 0); - *num_buffers = buf_count; - return 0; -out_err: - mutex_lock(&dev->struct_mutex); - i915_dereference_buffers_locked(buffers, buf_count); - mutex_unlock(&dev->struct_mutex); - *num_buffers = 0; - return (ret) ? ret : rep.ret; + /* + * Communicate to user-space that + * fence creation has failed and that + * the engine is idle. + */ + + fence_arg->handle = ~0; + fence_arg->error = ret; + } + + drm_putback_buffer_objects(dev); + if (fence_p) + *fence_p = NULL; + return; + } + + if (!(fence_flags & DRM_FENCE_FLAG_NO_USER)) { + + ret = drm_fence_add_user_object(file_priv, fence, + fence_flags & + DRM_FENCE_FLAG_SHAREABLE); + if (!ret) + drm_fence_fill_arg(fence, fence_arg); + else { + /* + * Fence user object creation failed. + * We must idle the engine here as well, as user- + * space expects a fence object to wait on. Since we + * have a fence object we wait for it to signal + * to indicate engine "sufficiently" idle. + */ + + (void) drm_fence_object_wait(fence, 0, 1, + fence->type); + drm_fence_usage_deref_unlocked(&fence); + fence_arg->handle = ~0; + fence_arg->error = ret; + } + } + + if (fence_p) + *fence_p = fence; + else if (fence) + drm_fence_usage_deref_unlocked(&fence); } + static int i915_execbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -1126,7 +1257,6 @@ static int i915_execbuffer(struct drm_device *dev, void *data, int num_buffers; int ret; struct drm_i915_validate_buffer *buffers; - struct drm_fence_object *fence; if (!dev_priv->allow_batchbuffer) { DRM_ERROR("Batchbuffer ioctl disabled\n"); @@ -1171,7 +1301,7 @@ static int i915_execbuffer(struct drm_device *dev, void *data, ret = i915_validate_buffer_list(file_priv, 0, exec_buf->ops_list, buffers, &num_buffers); if (ret) - goto out_free; + goto out_err0; /* make sure all previous memory operations have passed */ DRM_MEMORYBARRIER(); @@ -1190,30 +1320,16 @@ static int i915_execbuffer(struct drm_device *dev, void *data, if (sarea_priv) sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); - /* fence */ - ret = drm_fence_buffer_objects(dev, NULL, fence_arg->flags, - NULL, &fence); - if (ret) - goto out_err0; + i915_fence_or_sync(file_priv, fence_arg->flags, fence_arg, NULL); - if (!(fence_arg->flags & DRM_FENCE_FLAG_NO_USER)) { - ret = drm_fence_add_user_object(file_priv, fence, fence_arg->flags & DRM_FENCE_FLAG_SHAREABLE); - if (!ret) { - fence_arg->handle = fence->base.hash.key; - fence_arg->fence_class = fence->fence_class; - fence_arg->type = fence->type; - fence_arg->signaled = fence->signaled_types; - } - } - drm_fence_usage_deref_unlocked(&fence); out_err0: /* handle errors */ + ret = i915_handle_copyback(dev, buffers, num_buffers, ret); mutex_lock(&dev->struct_mutex); i915_dereference_buffers_locked(buffers, num_buffers); mutex_unlock(&dev->struct_mutex); -out_free: drm_free(buffers, (exec_buf->num_buffers * sizeof(struct drm_buffer_object *)), DRM_MEM_DRIVER); mutex_unlock(&dev_priv->cmdbuf_mutex); commit d6098db1409e8ee45052920d3acdd3b6f2cb80aa Author: Roland Scheidegger <sr...@tu...> Date: Sat Feb 23 11:01:36 2008 +0100 fix texture uploads with large 3d textures (bug 13980) Texture uploads could hit the blitter coordinate limit, adjust the texture offset when uploading the pieces. Make sure to check the end address of the upload too. diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index 6f2e05b..70651d7 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -1662,7 +1662,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, u32 height; int i; u32 texpitch, microtile; - u32 offset; + u32 offset, byte_offset; RING_LOCALS; if (radeon_check_and_fixup_offset(dev_priv, file_priv, &tex->offset)) { @@ -1727,6 +1727,13 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, } else microtile = 0; + /* this might fail for zero-sized uploads - are those illegal? */ + if (!radeon_check_offset(dev_priv, tex->offset + image->height * + blit_width - 1)) { + DRM_ERROR("Invalid final destination offset\n"); + return -EINVAL; + } + DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width); do { @@ -1840,6 +1847,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, } #undef RADEON_COPY_MT + byte_offset = (image->y & ~2047) * blit_width; buf->file_priv = file_priv; buf->used = size; offset = dev_priv->gart_buffers_offset + buf->offset; @@ -1854,9 +1862,9 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, RADEON_DP_SRC_SOURCE_MEMORY | RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS); OUT_RING((spitch << 22) | (offset >> 10)); - OUT_RING((texpitch << 22) | (tex->offset >> 10)); + OUT_RING((texpitch << 22) | ((tex->offset >> 10) + (byte_offset >> 10))); OUT_RING(0); - OUT_RING((image->x << 16) | image->y); + OUT_RING((image->x << 16) | (image->y % 2048)); OUT_RING((image->width << 16) | height); RADEON_WAIT_UNTIL_2D_IDLE(); ADVANCE_RING(); commit 20d0e539160fcbdd65ecbe188ac1ce2800af1b5c Author: Jesse Barnes <jes...@in...> Date: Fri Feb 22 13:57:38 2008 -0800 i915: put ARX back into index mode before doing restore Fixes resume from hibernate in some configurations. diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index cfcb62e..e18bc8d 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -247,6 +247,7 @@ static void i915_restore_vga(struct drm_device *dev) dev_priv->saveGR[0x18]); /* Attribute controller registers */ + inb(st01); /* switch back to index mode */ for (i = 0; i < 20; i++) i915_write_ar(st01, i, dev_priv->saveAR[i], 0); inb(st01); /* switch back to index mode */ commit 0d32015974f019e8d2ea1eb48acd9e082389d9c5 Author: Maarten Maathuis <mad...@gm...> Date: Fri Feb 22 13:41:05 2008 +0100 nouveau: Remove some random (french) comment. diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 0daf9ac..056cb6d 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -45,11 +45,6 @@ int nouveau_fifo_ctx_size(struct drm_device *dev) * functions doing the actual work ***********************************/ -/* voir nv_xaa.c : NVResetGraphics - * mémoire mappée par nv_driver.c : NVMapMem - * voir nv_driver.c : NVPreInit - */ - static int nouveau_fifo_instmem_configure(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; commit 7e5f9c8bd33c503fef9bea20b955a5a48e255621 Author: Maarten Maathuis <mad...@gm...> Date: Fri Feb 22 13:35:13 2008 +0100 nouveau: A single define of dma skips is more than enough. diff --git a/shared-core/nouveau_dma.c b/shared-core/nouveau_dma.c index dff786d..e519dc4 100644 --- a/shared-core/nouveau_dma.c +++ b/shared-core/nouveau_dma.c @@ -29,11 +29,6 @@ #include "nouveau_drv.h" #include "nouveau_dma.h" -/* FIXME : should go into a nouveau_drm.h define ? - * (it's shared between DRI & DDX & DRM) - */ -#define SKIPS 8 - int nouveau_dma_channel_init(struct drm_device *dev) { @@ -76,10 +71,10 @@ nouveau_dma_channel_init(struct drm_device *dev) dchan->cur = dchan->put; dchan->free = dchan->max - dchan->cur; - /* Insert NOPS for SKIPS */ - dchan->free -= SKIPS; - dchan->push_free = SKIPS; - for (i=0; i<SKIPS; i++) + /* Insert NOPS for NOUVEAU_DMA_SKIPS */ + dchan->free -= NOUVEAU_DMA_SKIPS; + dchan->push_free = NOUVEAU_DMA_SKIPS; + for (i=0; i < NOUVEAU_DMA_SKIPS; i++) OUT_RING(0); /* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier */ @@ -131,8 +126,6 @@ nouveau_dma_channel_takedown(struct drm_device *dev) } } -#define RING_SKIPS 8 - #define READ_GET() ((NV_READ(dchan->chan->get) - \ dchan->chan->pushbuf_base) >> 2) #define WRITE_PUT(val) do { \ @@ -156,19 +149,19 @@ nouveau_dma_wait(struct drm_device *dev, int size) if (dchan->free < size) { dchan->push_free = 1; OUT_RING(0x20000000|dchan->chan->pushbuf_base); - if (get <= RING_SKIPS) { + if (get <= NOUVEAU_DMA_SKIPS) { /*corner case - will be idle*/ - if (dchan->put <= RING_SKIPS) - WRITE_PUT(RING_SKIPS + 1); + if (dchan->put <= NOUVEAU_DMA_SKIPS) + WRITE_PUT(NOUVEAU_DMA_SKIPS + 1); do { get = READ_GET(); - } while (get <= RING_SKIPS); + } while (get <= NOUVEAU_DMA_SKIPS); } - WRITE_PUT(RING_SKIPS); - dchan->cur = dchan->put = RING_SKIPS; - dchan->free = get - (RING_SKIPS + 1); + WRITE_PUT(NOUVEAU_DMA_SKIPS); + dchan->cur = dchan->put = NOUVEAU_DMA_SKIPS; + dchan->free = get - (NOUVEAU_DMA_SKIPS + 1); } } else { dchan->free = get - dchan->cur - 1; diff --git a/shared-core/nouveau_drm.h b/shared-core/nouveau_drm.h index 3bf4008..5f07fcb 100644 --- a/shared-core/nouveau_drm.h +++ b/shared-core/nouveau_drm.h @@ -70,6 +70,12 @@ struct drm_nouveau_gpuobj_free { uint32_t handle; }; +/* This is needed to avoid a race condition. + * Otherwise you may be writing in the fetch area. + * Is this large enough, as it's only 32 bytes, and the maximum fetch size is 256 bytes? + */ +#define NOUVEAU_DMA_SKIPS 8 + #define NOUVEAU_MEM_FB 0x00000001 #define NOUVEAU_MEM_AGP 0x00000002 #define NOUVEAU_MEM_FB_ACCEPTABLE 0x00000004 commit b7086e6ae5632ad3c0f7c54ffd641519959d84a6 Author: Kristian Høgsberg <kr...@re...> Date: Fri Feb 22 11:22:52 2008 -0500 Fix one last occurance of struct _drm_i915_batchbuffer. Thanks to Todd Merrill for pointing it out. diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 3874ed5..7da8d55 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1121,7 +1121,7 @@ static int i915_execbuffer(struct drm_device *dev, void *data, drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) dev_priv->sarea_priv; struct drm_i915_execbuffer *exec_buf = data; - struct _drm_i915_batchbuffer *batch = &exec_buf->batch; + struct drm_i915_batchbuffer *batch = &exec_buf->batch; struct drm_fence_arg *fence_arg = &exec_buf->fence_arg; int num_buffers; int ret; commit b0fee67a305cf37cf2a71d6c3753fba825400b71 Author: Kristian Høgsberg <kr...@re...> Date: Fri Feb 22 00:12:39 2008 -0500 i915: Remove leading underscore from struct tags. This matches the changes in mesa to use the system drm includes for the definitions of the drm ioctl structs. diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 3dcb627..b93df67 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -69,7 +69,7 @@ typedef struct _drm_i915_init { unsigned int sarea_handle; } drm_i915_init_t; -typedef struct _drm_i915_sarea { +typedef struct drm_i915_sarea { struct drm_tex_region texList[I915_NR_TEX_REGIONS + 1]; int last_upload; /* last time texture was uploaded */ int last_enqueue; /* last time a buffer was enqueued */ @@ -211,7 +211,7 @@ typedef struct drm_i915_flip { /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. */ -typedef struct _drm_i915_batchbuffer { +typedef struct drm_i915_batchbuffer { int start; /* agp offset */ int used; /* nr bytes in use */ int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ @@ -375,7 +375,7 @@ struct drm_i915_op_arg { struct drm_i915_execbuffer { uint64_t ops_list; uint32_t num_buffers; - struct _drm_i915_batchbuffer batch; + struct drm_i915_batchbuffer batch; drm_context_t context; /* for lockless use in the future */ struct drm_fence_arg fence_arg; }; |