From 0618ac8a07d834e469cb96818a1dfee6f50662b8 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Thu, 7 Feb 2008 19:24:58 +0100 Subject: Added kernel part of hotplug ioctl --- linux-core/drm_crtc.c | 28 ++++++++++++++++++++++++++-- linux-core/drm_crtc.h | 8 +++++++- linux-core/drm_drv.c | 2 +- shared-core/i915_irq.c | 19 +++++++++++++------ 4 files changed, 47 insertions(+), 10 deletions(-) diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 03e5ffe9..55390a82 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -770,6 +770,7 @@ void drm_mode_config_init(struct drm_device *dev) dev->mode_config.num_fb = 0; dev->mode_config.num_output = 0; dev->mode_config.num_crtc = 0; + dev->mode_config.hotplug_counter = 0; } EXPORT_SYMBOL(drm_mode_config_init); @@ -1130,10 +1131,18 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, * RETURNS: * Zero on success, errno on failure. */ -int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output) +int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output, + bool connected) { int has_config = 0; + /* We might want to do something more here */ + if (!connected) { + DRM_DEBUG("not connected\n"); + dev->mode_config.hotplug_counter++; + return 0; + } + if (output->crtc && output->crtc->desired_mode) { DRM_DEBUG("drm thinks that the output already has a config\n"); has_config = 1; @@ -1146,7 +1155,7 @@ int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output) if (!output->crtc || !output->crtc->desired_mode) { DRM_DEBUG("could not find a desired mode or crtc for output\n"); - return 1; + goto out_err; } /* We should realy check if there is a fb using this crtc */ @@ -1161,10 +1170,25 @@ int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output) drm_disable_unused_functions(dev); + dev->mode_config.hotplug_counter++; return 0; + +out_err: + dev->mode_config.hotplug_counter++; + return 1; } EXPORT_SYMBOL(drm_hotplug_stage_two); +int drm_mode_hotplug_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_hotplug *arg = data; + + arg->counter = dev->mode_config.hotplug_counter; + + return 0; +} + /** * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo * @out: drm_mode_modeinfo struct to return to the user diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h index 3b22e886..db5fd34c 100644 --- a/linux-core/drm_crtc.h +++ b/linux-core/drm_crtc.h @@ -547,6 +547,9 @@ struct drm_mode_config { struct drm_property *dpms_property; struct drm_property *connector_type_property; struct drm_property *connector_num_property; + + /* hotplug */ + uint32_t hotplug_counter; }; struct drm_output *drm_output_create(struct drm_device *dev, @@ -603,7 +606,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); +extern int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output, bool connected); extern int drm_output_attach_property(struct drm_output *output, struct drm_property *property, uint64_t init_val); @@ -646,5 +649,8 @@ extern int drm_mode_getblob_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_mode_output_property_set_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int drm_mode_hotplug_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); + #endif /* __DRM_CRTC_H__ */ diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index 927225f1..5077f067 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -135,7 +135,7 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode_ioctl, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_MASTER | DRM_ROOT_ONLY | DRM_CONTROL_ALLOW), - + DRM_IOCTL_DEF(DRM_IOCTL_MODE_HOTPLUG, drm_mode_hotplug_ioctl, DRM_CONTROL_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_MM_INIT, drm_mm_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 836a8c46..5f6fa56d 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -413,6 +413,7 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int plane) } #define HOTPLUG_CMD_CRT 1 +#define HOTPLUG_CMD_CRT_DIS 2 #define HOTPLUG_CMD_SDVOB 4 #define HOTPLUG_CMD_SDVOC 8 @@ -420,7 +421,7 @@ static struct drm_device *hotplug_dev; static int hotplug_cmd = 0; static spinlock_t hotplug_lock = SPIN_LOCK_UNLOCKED; -static void i915_hotplug_crt(struct drm_device *dev) +static void i915_hotplug_crt(struct drm_device *dev, bool connected) { struct drm_output *output; struct intel_output *iout; @@ -439,7 +440,7 @@ static void i915_hotplug_crt(struct drm_device *dev) if (iout == 0) goto unlock; - drm_hotplug_stage_two(dev, output); + drm_hotplug_stage_two(dev, output, connected); unlock: mutex_unlock(&dev->mode_config.mutex); @@ -462,9 +463,9 @@ static void i915_hotplug_sdvo(struct drm_device *dev, int sdvoB) status = output->funcs->detect(output); if (status != output_status_connected) - DRM_DEBUG("disconnect or unkown we don't do anything then\n"); + drm_hotplug_stage_two(dev, output, false); else - drm_hotplug_stage_two(dev, output); + drm_hotplug_stage_two(dev, output, true); /* wierd hw bug, sdvo stop sending interupts */ intel_sdvo_set_hotplug(output, 1); @@ -484,18 +485,22 @@ static void i915_hotplug_work_func(struct work_struct *work) { struct drm_device *dev = hotplug_dev; int crt; + int crtDis; int sdvoB; int sdvoC; spin_lock(&hotplug_lock); crt = hotplug_cmd & HOTPLUG_CMD_CRT; + crtDis = hotplug_cmd & HOTPLUG_CMD_CRT_DIS; sdvoB = hotplug_cmd & HOTPLUG_CMD_SDVOB; sdvoC = hotplug_cmd & HOTPLUG_CMD_SDVOC; hotplug_cmd = 0; spin_unlock(&hotplug_lock); if (crt) - i915_hotplug_crt(dev); + i915_hotplug_crt(dev, true); + if (crtDis) + i915_hotplug_crt(dev, false); if (sdvoB) i915_hotplug_sdvo(dev, 1); @@ -524,7 +529,9 @@ static int i915_run_hotplug_tasklet(struct drm_device *dev, uint32_t stat) hotplug_cmd |= HOTPLUG_CMD_CRT; spin_unlock(&hotplug_lock); } else { - /* handle crt disconnects */ + spin_lock(&hotplug_lock); + hotplug_cmd |= HOTPLUG_CMD_CRT_DIS; + spin_unlock(&hotplug_lock); } } -- cgit v1.2.3