diff options
-rw-r--r-- | linux-core/drmP.h | 2 | ||||
-rw-r--r-- | linux-core/drm_crtc.c | 48 | ||||
-rw-r--r-- | linux-core/drm_crtc.h | 1 | ||||
-rw-r--r-- | linux-core/drm_mm.c | 5 | ||||
-rw-r--r-- | linux-core/i915_drv.c | 1 | ||||
-rw-r--r-- | linux-core/intel_drv.h | 5 | ||||
-rw-r--r-- | linux-core/intel_fb.c | 13 | ||||
-rw-r--r-- | linux-core/intel_sdvo.c | 17 | ||||
-rw-r--r-- | shared-core/i915_irq.c | 142 |
9 files changed, 115 insertions, 119 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 64f9a63f..ae2cdf01 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -667,6 +667,7 @@ struct drm_driver { /* FB routines, if present */ int (*fb_probe)(struct drm_device *dev, struct drm_crtc *crtc); int (*fb_remove)(struct drm_device *dev, struct drm_crtc *crtc); + int (*fb_resize)(struct drm_device *dev, struct drm_crtc *crtc); struct drm_fence_driver *fence_driver; struct drm_bo_driver *bo_driver; @@ -1195,6 +1196,7 @@ extern int drm_mm_clean(struct drm_mm *mm); extern unsigned long drm_mm_tail_space(struct drm_mm *mm); extern int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size); extern int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size); +extern void drm_mm_print(struct drm_mm *mm, const char *name); static inline struct drm_mm *drm_get_mm(struct drm_mm_node *block) { diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index e8ca635d..8754da5a 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1053,6 +1053,54 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, } /** + * drm_hotplug_stage_two + * @dev DRM device + * @output hotpluged output + * + * LOCKING. + * Caller must hold mode config lock, function might grap struct lock. + * + * Stage two of a hotplug. + * + * RETURNS: + * Zero on success, errno on failure. + */ +int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output) +{ + int has_config = 0; + + if (output->crtc && output->crtc->desired_mode) { + DRM_DEBUG("drm thinks that output already has a config\n"); + has_config = 1; + } + + drm_crtc_probe_output_modes(dev, 2048, 2048); + + if (!has_config) + drm_pick_crtcs(dev); + + if (!output->crtc || !output->crtc->desired_mode) { + DRM_DEBUG("could not find a desired mode or crtc for output\n"); + return 1; + } + + /* We should realy check if there is a fb using this crtc */ + if (!has_config) + dev->driver->fb_probe(dev, output->crtc); + else { + dev->driver->fb_resize(dev, output->crtc); + + if (!drm_crtc_set_mode(output->crtc, output->crtc->desired_mode, 0, 0)) + DRM_ERROR("failed to set mode after hotplug\n"); + } + + drm_disable_unused_functions(dev); + + return 0; +} +EXPORT_SYMBOL(drm_hotplug_stage_two); + +/** * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo * @out: drm_mode_modeinfo struct to return to the user * @in: drm_display_mode to use diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h index d97cd196..21f95049 100644 --- a/linux-core/drm_crtc.h +++ b/linux-core/drm_crtc.h @@ -526,6 +526,7 @@ extern int drmfb_probe(struct drm_device *dev, struct drm_crtc *crtc); extern int drmfb_remove(struct drm_device *dev, struct drm_framebuffer *fb); extern bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, int x, int y); +extern int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output); /* IOCTLs */ extern int drm_mode_getresources(struct drm_device *dev, diff --git a/linux-core/drm_mm.c b/linux-core/drm_mm.c index 00c4428e..5ad48036 100644 --- a/linux-core/drm_mm.c +++ b/linux-core/drm_mm.c @@ -295,10 +295,9 @@ void drm_mm_takedown(struct drm_mm * mm) EXPORT_SYMBOL(drm_mm_takedown); -int drm_mm_print(struct drm_mm *mm, const char *name) +void drm_mm_print(struct drm_mm *mm, const char *name) { struct list_head *list; - const struct list_head *free_stack = &mm->fl_entry; const struct list_head *mm_stack = &mm->ml_entry; struct drm_mm_node *entry; @@ -308,7 +307,5 @@ int drm_mm_print(struct drm_mm *mm, const char *name) DRM_DEBUG("\t0x%08lx %li %s pages\n", entry->start, entry->size, entry->free ? "free" : "used"); } - - return 0; } EXPORT_SYMBOL(drm_mm_print); diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index fabc8d83..2c02a722 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -321,6 +321,7 @@ static struct drm_driver driver = { .get_reg_ofs = drm_core_get_reg_ofs, .fb_probe = intelfb_probe, .fb_remove = intelfb_remove, + .fb_resize = intelfb_resize, .ioctls = i915_ioctls, .fops = { .owner = THIS_MODULE, diff --git a/linux-core/intel_drv.h b/linux-core/intel_drv.h index 7de4b924..06335b18 100644 --- a/linux-core/intel_drv.h +++ b/linux-core/intel_drv.h @@ -76,7 +76,12 @@ extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, extern void intel_wait_for_vblank(struct drm_device *dev); extern struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe); +extern struct drm_output* intel_sdvo_find(struct drm_device *dev, int sdvoB); +extern int intel_sdvo_supports_hotplug(struct drm_output *output); +extern void intel_sdvo_set_hotplug(struct drm_output *output, int enable); + extern int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc); extern int intelfb_remove(struct drm_device *dev, struct drm_crtc *crtc); +extern int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc); #endif /* __INTEL_DRV_H__ */ diff --git a/linux-core/intel_fb.c b/linux-core/intel_fb.c index 980adfbf..47cfc5d2 100644 --- a/linux-core/intel_fb.c +++ b/linux-core/intel_fb.c @@ -466,14 +466,16 @@ static struct fb_ops intelfb_ops = { .fb_imageblit = cfb_imageblit, //intelfb_imageblit, }; -/* +/** * Curretly it is assumed that the old framebuffer is reused. + * + * LOCKING + * caller should hold the mode config lock. + * */ int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc) { struct fb_info *info; - struct intelfb_par *par; - struct device *device = &dev->pdev->dev; struct drm_framebuffer *fb; struct drm_display_mode *mode = crtc->desired_mode; @@ -527,8 +529,9 @@ int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc) } crtc->fb = fb; - fb->width = 2048;//crtc->desired_mode->hdisplay; - fb->height = 2048;//crtc->desired_mode->vdisplay; + /* To allow resizeing without swapping buffers */ + fb->width = 2048;/* crtc->desired_mode->hdisplay; */ + fb->height = 2048;/* crtc->desired_mode->vdisplay; */ fb->bits_per_pixel = 32; fb->pitch = fb->width * ((fb->bits_per_pixel + 1) / 8); diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index b8eeb60c..fcbc43d4 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -891,23 +891,20 @@ struct drm_output* intel_sdvo_find(struct drm_device *dev, int sdvoB) list_for_each_entry(output, &dev->mode_config.output_list, head) { iout = output->driver_private; - if (iout->type != INTEL_OUTPUT_SDVO) { - iout = 0; + if (iout->type != INTEL_OUTPUT_SDVO) continue; - } sdvo = iout->dev_priv; if (sdvo->output_device == SDVOB && sdvoB) - break; + return output; if (sdvo->output_device == SDVOC && !sdvoB) - break; + return output; - sdvo = 0; } - return output; + return 0; } int intel_sdvo_supports_hotplug(struct drm_output *output) @@ -916,6 +913,9 @@ int intel_sdvo_supports_hotplug(struct drm_output *output) u8 status; DRM_DEBUG("\n"); + if (!output) + return 0; + intel_sdvo_write_cmd(output, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0); status = intel_sdvo_read_response(output, &response, 2); @@ -930,11 +930,9 @@ void intel_sdvo_set_hotplug(struct drm_output *output, int on) u8 response[2]; u8 status; - DRM_DEBUG("read\n"); intel_sdvo_write_cmd(output, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0); intel_sdvo_read_response(output, &response, 2); - DRM_DEBUG("write\n"); if (on) { intel_sdvo_write_cmd(output, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0); status = intel_sdvo_read_response(output, &response, 2); @@ -946,7 +944,6 @@ void intel_sdvo_set_hotplug(struct drm_output *output, int on) intel_sdvo_write_cmd(output, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2); } - DRM_DEBUG("readback\n"); intel_sdvo_write_cmd(output, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0); intel_sdvo_read_response(output, &response, 2); } diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index eac1c5e5..0d96dc57 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -307,60 +307,11 @@ static struct drm_device *hotplug_dev; static int hotplug_cmd = 0; static spinlock_t hotplug_lock = SPIN_LOCK_UNLOCKED; -/* TODO - * The locking in these functions are realy messed up. - * Currently the stage 1 functions takes both the locks. - * But have to release it since intel_fb_probe grabs the - * struct_mTODO utex. So to do this as cleanly as possible - * you need to release the locks between stage 1 and 2. - */ - -static void i915_hotplug_stage2(struct drm_device *dev, struct drm_output *output) -{ - int has_config = 0; - - mutex_lock(&dev->struct_mutex); - - if (output->crtc && output->crtc->desired_mode) { - DRM_DEBUG("monkey has banana\n"); - has_config = 1; - } - - drm_crtc_probe_output_modes(dev, 2048, 2048); - - if (!has_config) - drm_pick_crtcs(dev); - - if (!output->crtc || !output->crtc->desired_mode) { - DRM_DEBUG("no desired mode or no crtc found\n"); - goto unlock; - } - - mutex_unlock(&dev->struct_mutex); - - DRM_DEBUG("monkey eating banana\n"); - /* We should realy check if there is a fb using this crtc */ - if (!has_config) - dev->driver->fb_probe(dev, output->crtc); - else { - intelfb_resize(dev, output->crtc); - if (!drm_crtc_set_mode(output->crtc, output->crtc->desired_mode, 0, 0)) - DRM_ERROR("setting mode failed\n"); - } - - drm_disable_unused_functions(dev); - -unlock: - mutex_unlock(&dev->struct_mutex); - -} - static void i915_hotplug_crt(struct drm_device *dev) { struct drm_output *output; struct intel_output *iout; - mutex_lock(&dev->struct_mutex); mutex_lock(&dev->mode_config.mutex); /* find the crt output */ @@ -375,19 +326,10 @@ static void i915_hotplug_crt(struct drm_device *dev) if (iout == 0) goto unlock; - /* TODO ugly locking */ - mutex_unlock(&dev->struct_mutex); - - i915_hotplug_stage2(dev, output); - - mutex_unlock(&dev->mode_config.mutex); - return; + drm_hotplug_stage_two(dev, output); unlock: mutex_unlock(&dev->mode_config.mutex); - mutex_unlock(&dev->struct_mutex); - - DRM_DEBUG("monkey hunt done\n"); } static void i915_hotplug_sdvo(struct drm_device *dev, int sdvoB) @@ -395,7 +337,6 @@ static void i915_hotplug_sdvo(struct drm_device *dev, int sdvoB) struct drm_output *output = 0; enum drm_output_status status; - mutex_lock(&dev->struct_mutex); mutex_lock(&dev->mode_config.mutex); output = intel_sdvo_find(dev, sdvoB); @@ -407,25 +348,16 @@ static void i915_hotplug_sdvo(struct drm_device *dev, int sdvoB) status = output->funcs->detect(output); - if (status != output_status_connected) { + if (status != output_status_connected) DRM_DEBUG("disconnect or unkown we don't do anything then\n"); - intel_sdvo_set_hotplug(output, 1); - goto unlock; - } - - /* TODO ugly locking */ - mutex_unlock(&dev->struct_mutex); - - i915_hotplug_stage2(dev, output); + else + drm_hotplug_stage_two(dev, output); + /* wierd hw bug, sdvo stop sending interupts */ intel_sdvo_set_hotplug(output, 1); - mutex_unlock(&dev->mode_config.mutex); - return; - unlock: mutex_unlock(&dev->mode_config.mutex); - mutex_unlock(&dev->struct_mutex); } static void i915_hotplug_work_func(struct work_struct *work) @@ -497,7 +429,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; - u32 temp; + u32 temp = 0; u32 temp2; u32 pipea_stats, pipeb_stats; @@ -505,39 +437,39 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) pipeb_stats = I915_READ(I915REG_PIPEBSTAT); /* On i8xx hw the IIR and IER are 16bit on i9xx its 32bit */ - /* if (IS_I9XX(dev)) */ { + if (IS_I9XX(dev)) { temp = I915_READ(I915REG_INT_IDENTITY_R); - } /* else { + } else { temp = I915_READ16(I915REG_INT_IDENTITY_R); - } */ + } temp2 = temp; temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG); -#if 1 +#if 0 /* ugly despamification of pipeb event irq */ if (temp & (0xFFFFFFF ^ ((1 << 5) | (1 << 7)))) { DRM_DEBUG("IIR %08x\n", temp2); DRM_DEBUG("MSK %08x\n", dev_priv->irq_enable_reg | USER_INT_FLAG); DRM_DEBUG("M&I %08x\n", temp); DRM_DEBUG("HOT %08x\n", I915_READ(PORT_HOTPLUG_STAT)); - } else { - /* DRM_DEBUG("v\n"); */ } #else +#if 0 DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp); #endif +#endif if (temp == 0) return IRQ_NONE; - /* if (IS_I9XX(dev)) */ { + if (IS_I9XX(dev)) { I915_WRITE(I915REG_INT_IDENTITY_R, temp); (void) I915_READ(I915REG_INT_IDENTITY_R); - } /* else { + } else { I915_WRITE16(I915REG_INT_IDENTITY_R, temp); (void) I915_READ16(I915REG_INT_IDENTITY_R); - } */ + } DRM_READMEMORYBARRIER(); @@ -762,27 +694,33 @@ void i915_enable_interrupt (struct drm_device *dev) if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B) dev_priv->irq_enable_reg |= VSYNC_PIPEB_FLAG; - /* if (dev_priv->mode_setting) */ { + if (IS_I9XX(dev) && dev->mode_config.funcs) { dev_priv->irq_enable_reg |= (1 << 17); - /* Activate the CRT and SDVOB hotplug detection */ - I915_WRITE(PORT_HOTPLUG_EN, (1 << 9) | (1 << 26)); + /* Activate the CRT */ + I915_WRITE(PORT_HOTPLUG_EN, (1 << 9)); + /* SDVOB */ o = intel_sdvo_find(dev, 1); - if (o) { - intel_sdvo_supports_hotplug(o); + if (o && intel_sdvo_supports_hotplug(o)) { + intel_sdvo_set_hotplug(o, 1); + I915_WRITE(PORT_HOTPLUG_EN, (1 << 26)); + } + /* SDVOC */ + o = intel_sdvo_find(dev, 0); + if (o && intel_sdvo_supports_hotplug(o)) { intel_sdvo_set_hotplug(o, 1); - I915_WRITE(SDVOB, I915_READ(SDVOB) | (1 << 26)); - I915_WRITE(SDVOB, I915_READ(SDVOB) | (1 << 26)); + I915_WRITE(PORT_HOTPLUG_EN, (1 << 25)); } + } - /* if (IS_I9XX(dev_priv)) */ { + if (IS_I9XX(dev)) { I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); - } /* else { + } else { I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); - } */ + } DRM_DEBUG("HEN %08x\n",I915_READ(PORT_HOTPLUG_EN)); DRM_DEBUG("HST %08x\n",I915_READ(PORT_HOTPLUG_STAT)); @@ -792,8 +730,6 @@ void i915_enable_interrupt (struct drm_device *dev) I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); dev_priv->irq_enabled = 1; - - DRM_DEBUG("enabled\n"); } /* Set the vblank monitor pipe @@ -997,8 +933,14 @@ void i915_driver_irq_preinstall(struct drm_device * dev) struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; I915_WRITE16(I915REG_HWSTAM, 0xeffe); - I915_WRITE(I915REG_INT_MASK_R, 0x0); - I915_WRITE(I915REG_INT_ENABLE_R, 0x0); + if (IS_I9XX(dev)) { + I915_WRITE(I915REG_INT_MASK_R, 0x0); + I915_WRITE(I915REG_INT_ENABLE_R, 0x0); + } else { + I915_WRITE16(I915REG_INT_MASK_R, 0x0); + I915_WRITE16(I915REG_INT_ENABLE_R, 0x0); + } + } void i915_driver_irq_postinstall(struct drm_device * dev) @@ -1033,19 +975,19 @@ void i915_driver_irq_uninstall(struct drm_device * dev) dev_priv->irq_enabled = 0; - /* if(IS_I9XX(dev_priv) */ { + if(IS_I9XX(dev)) { I915_WRITE(I915REG_HWSTAM, 0xffffffff); I915_WRITE(I915REG_INT_MASK_R, 0xffffffff); I915_WRITE(I915REG_INT_ENABLE_R, 0x0); temp = I915_READ(I915REG_INT_IDENTITY_R); I915_WRITE(I915REG_INT_IDENTITY_R, temp); - } /* else { + } else { I915_WRITE16(I915REG_HWSTAM, 0xffff); I915_WRITE16(I915REG_INT_MASK_R, 0xffff); I915_WRITE16(I915REG_INT_ENABLE_R, 0x0); temp = I915_READ16(I915REG_INT_IDENTITY_R); I915_WRITE16(I915REG_INT_IDENTITY_R, temp); - } */ + } } |