summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Bornecrantz <jakob@tungstengraphics.com>2007-10-24 14:13:24 +0200
committerJakob Bornecrantz <wallbraker@aurora.(none)>2007-10-24 14:13:24 +0200
commit3796c9671a5a9f88cbbdb75351cf1cd1fa549edb (patch)
tree4384238464f961e974a675defaed00076a2a649f
parentc8ce5cf0301bf3325b226f6c96c7160cf4cf16e7 (diff)
-rw-r--r--linux-core/drmP.h2
-rw-r--r--linux-core/drm_crtc.c48
-rw-r--r--linux-core/drm_crtc.h1
-rw-r--r--linux-core/drm_mm.c5
-rw-r--r--linux-core/i915_drv.c1
-rw-r--r--linux-core/intel_drv.h5
-rw-r--r--linux-core/intel_fb.c13
-rw-r--r--linux-core/intel_sdvo.c17
-rw-r--r--shared-core/i915_irq.c142
9 files changed, 115 insertions, 119 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 64f9a63fc..ae2cdf015 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 e8ca635dc..8754da5aa 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 d97cd1964..21f950497 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 00c4428eb..5ad48036e 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 fabc8d83e..2c02a722c 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 7de4b924c..06335b183 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 980adfbfd..47cfc5d2f 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 b8eeb60cd..fcbc43d40 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 eac1c5e5d..0d96dc573 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);
- } */
+ }
}