summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Bornecrantz <jakob@tungstengraphics.com>2008-02-07 19:24:58 +0100
committerJakob Bornecrantz <jakob@tungstengraphics.com>2008-02-07 19:24:58 +0100
commit0618ac8a07d834e469cb96818a1dfee6f50662b8 (patch)
tree0b147fb2bf03a090c8d9e08e0b3da97b9e46fe60
parent34b76e0fac579e4afd269ebd3cbcbdd0416ec944 (diff)
Added kernel part of hotplug ioctl
-rw-r--r--linux-core/drm_crtc.c28
-rw-r--r--linux-core/drm_crtc.h8
-rw-r--r--linux-core/drm_drv.c2
-rw-r--r--shared-core/i915_irq.c19
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);
}
}