From 9bb2d6f94aeb9a185d69aedbd19421b6da4e3309 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 23 Dec 2008 18:42:32 -0800 Subject: drm/i915: Don't allow objects to get bound while VT switched. This avoids a BUG_ON in the enter_vt path due to objects being in the GTT when we shouldn't have ever let them be (as we're not supposed to touch the device during that time). This was triggered by a change in the 2D driver to use the GTT mapping of objects after pinning them to improve software fallback performance. Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index cc2ca55..14afc23 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1623,6 +1623,8 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) struct drm_mm_node *free_space; int page_count, ret; + if (dev_priv->mm.suspended) + return -EBUSY; if (alignment == 0) alignment = PAGE_SIZE; if (alignment & (PAGE_SIZE - 1)) { @@ -2641,7 +2643,7 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) if (obj_priv->gtt_space == NULL) { ret = i915_gem_object_bind_to_gtt(obj, alignment); if (ret != 0) { - if (ret != -ERESTARTSYS) + if (ret != -EBUSY && ret != -ERESTARTSYS) DRM_ERROR("Failure to bind: %d", ret); return ret; } @@ -3219,20 +3221,21 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data, dev_priv->mm.wedged = 0; } - ret = i915_gem_init_ringbuffer(dev); - if (ret != 0) - return ret; - dev_priv->mm.gtt_mapping = io_mapping_create_wc(dev->agp->base, dev->agp->agp_info.aper_size * 1024 * 1024); mutex_lock(&dev->struct_mutex); + dev_priv->mm.suspended = 0; + + ret = i915_gem_init_ringbuffer(dev); + if (ret != 0) + return ret; + BUG_ON(!list_empty(&dev_priv->mm.active_list)); BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); BUG_ON(!list_empty(&dev_priv->mm.request_list)); - dev_priv->mm.suspended = 0; mutex_unlock(&dev->struct_mutex); drm_irq_install(dev); -- cgit v0.10.2 From 3f8bc370ac679a5fe5c098f30d3cf8e80f62a9f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 17 Dec 2008 22:14:59 -0500 Subject: drm/i915: Pin cursor bo and unpin old bo when setting cursor. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We also didn't track the cursor bo before and would leak a reference when the cursor image was change. Signed-off-by: Kristian Høgsberg Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e5c1c80..1204d26 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -986,19 +986,17 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; uint32_t temp; size_t addr; + int ret; DRM_DEBUG("\n"); /* if we want to turn off the cursor ignore width and height */ if (!handle) { DRM_DEBUG("cursor off\n"); - /* turn of the cursor */ - temp = 0; - temp |= CURSOR_MODE_DISABLE; - - I915_WRITE(control, temp); - I915_WRITE(base, 0); - return 0; + temp = CURSOR_MODE_DISABLE; + addr = 0; + bo = NULL; + goto finish; } /* Currently we only support 64x64 cursors */ @@ -1025,15 +1023,30 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, addr = obj_priv->gtt_offset; } - intel_crtc->cursor_addr = addr; + ret = i915_gem_object_pin(bo, PAGE_SIZE); + if (ret) { + DRM_ERROR("failed to pin cursor bo\n"); + drm_gem_object_unreference(bo); + return ret; + } + temp = 0; /* set the pipe for the cursor */ temp |= (pipe << 28); temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; + finish: I915_WRITE(control, temp); I915_WRITE(base, addr); + if (intel_crtc->cursor_bo) { + i915_gem_object_unpin(intel_crtc->cursor_bo); + drm_gem_object_unreference(intel_crtc->cursor_bo); + } + + intel_crtc->cursor_addr = addr; + intel_crtc->cursor_bo = bo; + return 0; } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 407edd5..94981ee 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -88,6 +88,7 @@ struct intel_crtc { struct drm_crtc base; int pipe; int plane; + struct drm_gem_object *cursor_bo; uint32_t cursor_addr; u8 lut_r[256], lut_g[256], lut_b[256]; int dpms_mode; -- cgit v0.10.2 From 7d57382e65994ab7d01741373bd1c420370aed9f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 2 Jan 2009 13:33:00 -0800 Subject: drm/i915: Add support for integrated HDMI on G4X hardware. This is ported directly from the userland 2D driver code. The HDMI audio bits aren't hooked up yet. Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index dd57a5b..793cba3 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -13,6 +13,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ intel_crt.o \ intel_lvds.o \ intel_bios.o \ + intel_hdmi.o \ intel_sdvo.o \ intel_modes.o \ intel_i2c.o \ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4756e5c..563de18 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -664,6 +664,7 @@ extern void intel_modeset_cleanup(struct drm_device *dev); writel(upper_32_bits(val), dev_priv->regs + \ (reg) + 4)) #endif +#define POSTING_READ(reg) (void)I915_READ(reg) #define I915_VERBOSE 0 @@ -760,6 +761,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev)) #define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev)) +#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev)) #define PRIMARY_RINGBUFFER_SIZE (128*1024) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 47e6baf..1024315 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -549,6 +549,8 @@ /** GM965 GM45 render standby register */ #define MCHBAR_RENDER_STANDBY 0x111B8 +#define PEG_BAND_GAP_DATA 0x14d68 + /* * Overlay regs */ @@ -612,6 +614,9 @@ /* Hotplug control (945+ only) */ #define PORT_HOTPLUG_EN 0x61110 +#define HDMIB_HOTPLUG_INT_EN (1 << 29) +#define HDMIC_HOTPLUG_INT_EN (1 << 28) +#define HDMID_HOTPLUG_INT_EN (1 << 27) #define SDVOB_HOTPLUG_INT_EN (1 << 26) #define SDVOC_HOTPLUG_INT_EN (1 << 25) #define TV_HOTPLUG_INT_EN (1 << 18) @@ -619,6 +624,9 @@ #define CRT_HOTPLUG_FORCE_DETECT (1 << 3) #define PORT_HOTPLUG_STAT 0x61114 +#define HDMIB_HOTPLUG_INT_STATUS (1 << 29) +#define HDMIC_HOTPLUG_INT_STATUS (1 << 28) +#define HDMID_HOTPLUG_INT_STATUS (1 << 27) #define CRT_HOTPLUG_INT_STATUS (1 << 11) #define TV_HOTPLUG_INT_STATUS (1 << 10) #define CRT_HOTPLUG_MONITOR_MASK (3 << 8) @@ -648,7 +656,16 @@ #define SDVO_PHASE_SELECT_DEFAULT (6 << 19) #define SDVO_CLOCK_OUTPUT_INVERT (1 << 18) #define SDVOC_GANG_MODE (1 << 16) +#define SDVO_ENCODING_SDVO (0x0 << 10) +#define SDVO_ENCODING_HDMI (0x2 << 10) +/** Requird for HDMI operation */ +#define SDVO_NULL_PACKETS_DURING_VSYNC (1 << 9) #define SDVO_BORDER_ENABLE (1 << 7) +#define SDVO_AUDIO_ENABLE (1 << 6) +/** New with 965, default is to be set */ +#define SDVO_VSYNC_ACTIVE_HIGH (1 << 4) +/** New with 965, default is to be set */ +#define SDVO_HSYNC_ACTIVE_HIGH (1 << 3) #define SDVOB_PCIE_CONCURRENCY (1 << 3) #define SDVO_DETECTED (1 << 2) /* Bits to be preserved when writing */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1204d26..67d06fd 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -751,6 +751,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, is_lvds = true; break; case INTEL_OUTPUT_SDVO: + case INTEL_OUTPUT_HDMI: is_sdvo = true; break; case INTEL_OUTPUT_DVO: @@ -1443,8 +1444,15 @@ static void intel_setup_outputs(struct drm_device *dev) intel_lvds_init(dev); if (IS_I9XX(dev)) { - intel_sdvo_init(dev, SDVOB); - intel_sdvo_init(dev, SDVOC); + int found; + + found = intel_sdvo_init(dev, SDVOB); + if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) + intel_hdmi_init(dev, SDVOB); + + found = intel_sdvo_init(dev, SDVOC); + if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) + intel_hdmi_init(dev, SDVOC); } else intel_dvo_init(dev); @@ -1458,6 +1466,11 @@ static void intel_setup_outputs(struct drm_device *dev) /* valid crtcs */ switch(intel_output->type) { + case INTEL_OUTPUT_HDMI: + crtc_mask = ((1 << 0)| + (1 << 1)); + clone_mask = ((1 << INTEL_OUTPUT_HDMI)); + break; case INTEL_OUTPUT_DVO: case INTEL_OUTPUT_SDVO: crtc_mask = ((1 << 0)| diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 94981ee..8a4cc50 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -53,6 +53,7 @@ #define INTEL_OUTPUT_SDVO 3 #define INTEL_OUTPUT_LVDS 4 #define INTEL_OUTPUT_TVOUT 5 +#define INTEL_OUTPUT_HDMI 6 #define INTEL_DVO_CHIP_NONE 0 #define INTEL_DVO_CHIP_LVDS 1 @@ -109,7 +110,8 @@ int intel_ddc_get_modes(struct intel_output *intel_output); extern bool intel_ddc_probe(struct intel_output *intel_output); extern void intel_crt_init(struct drm_device *dev); -extern void intel_sdvo_init(struct drm_device *dev, int output_device); +extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg); +extern bool intel_sdvo_init(struct drm_device *dev, int output_device); extern void intel_dvo_init(struct drm_device *dev); extern void intel_tv_init(struct drm_device *dev); extern void intel_lvds_init(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c new file mode 100644 index 0000000..b06a4a3 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -0,0 +1,280 @@ +/* + * Copyright 2006 Dave Airlie + * Copyright © 2006-2009 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * Jesse Barnes + */ + +#include +#include +#include "drmP.h" +#include "drm.h" +#include "drm_crtc.h" +#include "intel_drv.h" +#include "i915_drm.h" +#include "i915_drv.h" + +struct intel_hdmi_priv { + u32 sdvox_reg; + u32 save_SDVOX; + int has_hdmi_sink; +}; + +static void intel_hdmi_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_crtc *crtc = encoder->crtc; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_output *intel_output = enc_to_intel_output(encoder); + struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; + u32 sdvox; + + sdvox = SDVO_ENCODING_HDMI | + SDVO_BORDER_ENABLE | + SDVO_VSYNC_ACTIVE_HIGH | + SDVO_HSYNC_ACTIVE_HIGH; + + if (hdmi_priv->has_hdmi_sink) + sdvox |= SDVO_AUDIO_ENABLE; + + if (intel_crtc->pipe == 1) + sdvox |= SDVO_PIPE_B_SELECT; + + I915_WRITE(hdmi_priv->sdvox_reg, sdvox); + POSTING_READ(hdmi_priv->sdvox_reg); +} + +static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_output *intel_output = enc_to_intel_output(encoder); + struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; + u32 temp; + + if (mode != DRM_MODE_DPMS_ON) { + temp = I915_READ(hdmi_priv->sdvox_reg); + I915_WRITE(hdmi_priv->sdvox_reg, temp & ~SDVO_ENABLE); + } else { + temp = I915_READ(hdmi_priv->sdvox_reg); + I915_WRITE(hdmi_priv->sdvox_reg, temp | SDVO_ENABLE); + } + POSTING_READ(hdmi_priv->sdvox_reg); +} + +static void intel_hdmi_save(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_output *intel_output = to_intel_output(connector); + struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; + + hdmi_priv->save_SDVOX = I915_READ(hdmi_priv->sdvox_reg); +} + +static void intel_hdmi_restore(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_output *intel_output = to_intel_output(connector); + struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; + + I915_WRITE(hdmi_priv->sdvox_reg, hdmi_priv->save_SDVOX); + POSTING_READ(hdmi_priv->sdvox_reg); +} + +static int intel_hdmi_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + if (mode->clock > 165000) + return MODE_CLOCK_HIGH; + if (mode->clock < 20000) + return MODE_CLOCK_HIGH; + + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) + return MODE_NO_DBLESCAN; + + return MODE_OK; +} + +static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static enum drm_connector_status +intel_hdmi_detect(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_output *intel_output = to_intel_output(connector); + struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; + u32 temp, bit; + + temp = I915_READ(PORT_HOTPLUG_EN); + + I915_WRITE(PORT_HOTPLUG_EN, + temp | + HDMIB_HOTPLUG_INT_EN | + HDMIC_HOTPLUG_INT_EN | + HDMID_HOTPLUG_INT_EN); + + POSTING_READ(PORT_HOTPLUG_EN); + + switch (hdmi_priv->sdvox_reg) { + case SDVOB: + bit = HDMIB_HOTPLUG_INT_STATUS; + break; + case SDVOC: + bit = HDMIC_HOTPLUG_INT_STATUS; + break; + default: + return connector_status_unknown; + } + + if ((I915_READ(PORT_HOTPLUG_STAT) & bit) != 0) + return connector_status_connected; + else + return connector_status_disconnected; +} + +static int intel_hdmi_get_modes(struct drm_connector *connector) +{ + struct intel_output *intel_output = to_intel_output(connector); + + /* We should parse the EDID data and find out if it's an HDMI sink so + * we can send audio to it. + */ + + return intel_ddc_get_modes(intel_output); +} + +static void intel_hdmi_destroy(struct drm_connector *connector) +{ + struct intel_output *intel_output = to_intel_output(connector); + + if (intel_output->i2c_bus) + intel_i2c_destroy(intel_output->i2c_bus); + drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); + kfree(intel_output); +} + +static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = { + .dpms = intel_hdmi_dpms, + .mode_fixup = intel_hdmi_mode_fixup, + .prepare = intel_encoder_prepare, + .mode_set = intel_hdmi_mode_set, + .commit = intel_encoder_commit, +}; + +static const struct drm_connector_funcs intel_hdmi_connector_funcs = { + .save = intel_hdmi_save, + .restore = intel_hdmi_restore, + .detect = intel_hdmi_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = intel_hdmi_destroy, +}; + +static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = { + .get_modes = intel_hdmi_get_modes, + .mode_valid = intel_hdmi_mode_valid, + .best_encoder = intel_best_encoder, +}; + +static void intel_hdmi_enc_destroy(struct drm_encoder *encoder) +{ + drm_encoder_cleanup(encoder); +} + +static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { + .destroy = intel_hdmi_enc_destroy, +}; + + +void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_connector *connector; + struct intel_output *intel_output; + struct intel_hdmi_priv *hdmi_priv; + + intel_output = kcalloc(sizeof(struct intel_output) + + sizeof(struct intel_hdmi_priv), 1, GFP_KERNEL); + if (!intel_output) + return; + hdmi_priv = (struct intel_hdmi_priv *)(intel_output + 1); + + connector = &intel_output->base; + drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, + DRM_MODE_CONNECTOR_DVID); + drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); + + intel_output->type = INTEL_OUTPUT_HDMI; + + connector->interlace_allowed = 0; + connector->doublescan_allowed = 0; + + /* Set up the DDC bus. */ + if (sdvox_reg == SDVOB) + intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB"); + else + intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC"); + + if (!intel_output->ddc_bus) + goto err_connector; + + hdmi_priv->sdvox_reg = sdvox_reg; + intel_output->dev_priv = hdmi_priv; + + drm_encoder_init(dev, &intel_output->enc, &intel_hdmi_enc_funcs, + DRM_MODE_ENCODER_TMDS); + drm_encoder_helper_add(&intel_output->enc, &intel_hdmi_helper_funcs); + + drm_mode_connector_attach_encoder(&intel_output->base, + &intel_output->enc); + drm_sysfs_connector_add(connector); + + /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written + * 0xd. Failure to do so will result in spurious interrupts being + * generated on the port when a cable is not attached. + */ + if (IS_G4X(dev) && !IS_GM45(dev)) { + u32 temp = I915_READ(PEG_BAND_GAP_DATA); + I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); + } + + return; + +err_connector: + drm_connector_cleanup(connector); + kfree(intel_output); + + return; +} diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index fbbaa4f..4072154 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -978,7 +978,7 @@ static const struct drm_encoder_funcs intel_sdvo_enc_funcs = { }; -void intel_sdvo_init(struct drm_device *dev, int output_device) +bool intel_sdvo_init(struct drm_device *dev, int output_device) { struct drm_connector *connector; struct intel_output *intel_output; @@ -991,7 +991,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); if (!intel_output) { - return; + return false; } connector = &intel_output->base; @@ -1116,7 +1116,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) intel_output->ddc_bus = i2cbus; - return; + return true; err_i2c: intel_i2c_destroy(intel_output->i2c_bus); @@ -1124,5 +1124,5 @@ err_connector: drm_connector_cleanup(connector); kfree(intel_output); - return; + return false; } -- cgit v0.10.2 From 1fc45d84d616cec00566152c1080903c461eb537 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 2 Jan 2009 15:57:35 -0800 Subject: drm/i915: Non-mobile parts don't have integrated TV-out. Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 67d06fd..8ccb9c3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1456,7 +1456,7 @@ static void intel_setup_outputs(struct drm_device *dev) } else intel_dvo_init(dev); - if (IS_I9XX(dev) && !IS_I915G(dev)) + if (IS_I9XX(dev) && IS_MOBILE(dev)) intel_tv_init(dev); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { -- cgit v0.10.2 From 241fa85b2bb655224357d713c251077dee3585ce Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 2 Jan 2009 18:05:51 -0800 Subject: drm/i915: Respect the other stolen memory sizes we know of. fd.o bug #19336. Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 3d7082a..62a4bf7 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -827,6 +827,7 @@ static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size, struct pci_dev *bridge_dev; u16 tmp = 0; unsigned long overhead; + unsigned long stolen; bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0)); if (!bridge_dev) { @@ -866,36 +867,55 @@ static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size, else overhead = (*aperture_size / 1024) + 4096; - switch (tmp & INTEL_855_GMCH_GMS_MASK) { + switch (tmp & INTEL_GMCH_GMS_MASK) { + case INTEL_855_GMCH_GMS_DISABLED: + DRM_ERROR("video memory is disabled\n"); + return -1; case INTEL_855_GMCH_GMS_STOLEN_1M: - break; /* 1M already */ + stolen = 1 * 1024 * 1024; + break; case INTEL_855_GMCH_GMS_STOLEN_4M: - *preallocated_size *= 4; + stolen = 4 * 1024 * 1024; break; case INTEL_855_GMCH_GMS_STOLEN_8M: - *preallocated_size *= 8; + stolen = 8 * 1024 * 1024; break; case INTEL_855_GMCH_GMS_STOLEN_16M: - *preallocated_size *= 16; + stolen = 16 * 1024 * 1024; break; case INTEL_855_GMCH_GMS_STOLEN_32M: - *preallocated_size *= 32; + stolen = 32 * 1024 * 1024; break; case INTEL_915G_GMCH_GMS_STOLEN_48M: - *preallocated_size *= 48; + stolen = 48 * 1024 * 1024; break; case INTEL_915G_GMCH_GMS_STOLEN_64M: - *preallocated_size *= 64; + stolen = 64 * 1024 * 1024; + break; + case INTEL_GMCH_GMS_STOLEN_128M: + stolen = 128 * 1024 * 1024; + break; + case INTEL_GMCH_GMS_STOLEN_256M: + stolen = 256 * 1024 * 1024; + break; + case INTEL_GMCH_GMS_STOLEN_96M: + stolen = 96 * 1024 * 1024; + break; + case INTEL_GMCH_GMS_STOLEN_160M: + stolen = 160 * 1024 * 1024; + break; + case INTEL_GMCH_GMS_STOLEN_224M: + stolen = 224 * 1024 * 1024; + break; + case INTEL_GMCH_GMS_STOLEN_352M: + stolen = 352 * 1024 * 1024; break; - case INTEL_855_GMCH_GMS_DISABLED: - DRM_ERROR("video memory is disabled\n"); - return -1; default: DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n", - tmp & INTEL_855_GMCH_GMS_MASK); + tmp & INTEL_GMCH_GMS_MASK); return -1; } - *preallocated_size -= overhead; + *preallocated_size = stolen - overhead; return 0; } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 1024315..2731625 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -35,7 +35,7 @@ #define INTEL_GMCH_MEM_64M 0x1 #define INTEL_GMCH_MEM_128M 0 -#define INTEL_855_GMCH_GMS_MASK (0x7 << 4) +#define INTEL_GMCH_GMS_MASK (0xf << 4) #define INTEL_855_GMCH_GMS_DISABLED (0x0 << 4) #define INTEL_855_GMCH_GMS_STOLEN_1M (0x1 << 4) #define INTEL_855_GMCH_GMS_STOLEN_4M (0x2 << 4) @@ -45,6 +45,12 @@ #define INTEL_915G_GMCH_GMS_STOLEN_48M (0x6 << 4) #define INTEL_915G_GMCH_GMS_STOLEN_64M (0x7 << 4) +#define INTEL_GMCH_GMS_STOLEN_128M (0x8 << 4) +#define INTEL_GMCH_GMS_STOLEN_256M (0x9 << 4) +#define INTEL_GMCH_GMS_STOLEN_96M (0xa << 4) +#define INTEL_GMCH_GMS_STOLEN_160M (0xb << 4) +#define INTEL_GMCH_GMS_STOLEN_224M (0xc << 4) +#define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4) /* PCI config space */ -- cgit v0.10.2 From a75f28419a7efff611a81293d41d0e2137d7591e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 7 Jan 2009 11:54:57 +1000 Subject: drm: fix ordering of driver unload vs agp unload. For KMS drivers, we really need to cleanup the driver before disabling the AGP subsystem. Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index febb517..5ff88d9 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -314,14 +314,14 @@ static void drm_cleanup(struct drm_device * dev) DRM_DEBUG("mtrr_del=%d\n", retval); } + if (dev->driver->unload) + dev->driver->unload(dev); + if (drm_core_has_AGP(dev) && dev->agp) { drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS); dev->agp = NULL; } - if (dev->driver->unload) - dev->driver->unload(dev); - drm_ht_remove(&dev->map_hash); drm_ctxbitmap_cleanup(dev); -- cgit v0.10.2