Преглед изворни кода

Merge branch 'drm-intel-next' of git://git.kernel.org/pub/scm/linux/kernel/git/anholt/drm-intel

* 'drm-intel-next' of git://git.kernel.org/pub/scm/linux/kernel/git/anholt/drm-intel:
  drm/i915: Add new GET_PIPE_FROM_CRTC_ID ioctl.
  drm/i915: Set HDMI hot plug interrupt enable for only the output in question.
  drm/i915: Include 965GME pci ID in IS_I965GM(dev) to match UMS.
  drm/i915: Use the GM45 VGA hotplug workaround on G45 as well.
  drm/i915: ignore LVDS on intel graphics systems that lie about having it
  drm/i915: sanity check IER at wait_request time
  drm/i915: workaround IGD i2c bus issue in kernel side (v2)
  drm/i915: Don't allow binding objects into the last page of the aperture.
  drm/i915: save/restore fence registers across suspend/resume
  drm/i915: x86 always has writeq. Add I915_READ64 for symmetry.
Linus Torvalds пре 16 година
родитељ
комит
40f293ff83

+ 11 - 2
drivers/gpu/drm/i915/i915_dma.c

@@ -1011,8 +1011,16 @@ static int i915_load_modeset_init(struct drm_device *dev)
 	/* Basic memrange allocator for stolen space (aka vram) */
 	drm_mm_init(&dev_priv->vram, 0, prealloc_size);
 
-	/* Let GEM Manage from end of prealloc space to end of aperture */
-	i915_gem_do_init(dev, prealloc_size, agp_size);
+	/* Let GEM Manage from end of prealloc space to end of aperture.
+	 *
+	 * However, leave one page at the end still bound to the scratch page.
+	 * There are a number of places where the hardware apparently
+	 * prefetches past the end of the object, and we've seen multiple
+	 * hangs with the GPU head pointer stuck in a batchbuffer bound
+	 * at the last page of the aperture.  One page should be enough to
+	 * keep any prefetching inside of the aperture.
+	 */
+	i915_gem_do_init(dev, prealloc_size, agp_size - 4096);
 
 	ret = i915_gem_init_ringbuffer(dev);
 	if (ret)
@@ -1350,6 +1358,7 @@ struct drm_ioctl_desc i915_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0),
 	DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, 0),
 	DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, 0),
+	DRM_IOCTL_DEF(DRM_I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, 0),
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);

+ 4 - 7
drivers/gpu/drm/i915/i915_drv.h

@@ -283,6 +283,7 @@ typedef struct drm_i915_private {
 	u8 saveAR[21];
 	u8 saveDACMASK;
 	u8 saveCR[37];
+	uint64_t saveFENCE[16];
 
 	struct {
 		struct drm_mm gtt_space;
@@ -705,13 +706,8 @@ extern void intel_modeset_cleanup(struct drm_device *dev);
 #define I915_WRITE16(reg, val)	writel(val, dev_priv->regs + (reg))
 #define I915_READ8(reg)		readb(dev_priv->regs + (reg))
 #define I915_WRITE8(reg, val)	writeb(val, dev_priv->regs + (reg))
-#ifdef writeq
 #define I915_WRITE64(reg, val)	writeq(val, dev_priv->regs + (reg))
-#else
-#define I915_WRITE64(reg, val)	(writel(val, dev_priv->regs + (reg)), \
-				 writel(upper_32_bits(val), dev_priv->regs + \
-					(reg) + 4))
-#endif
+#define I915_READ64(reg)	readq(dev_priv->regs + (reg))
 #define POSTING_READ(reg)	(void)I915_READ(reg)
 
 #define I915_VERBOSE 0
@@ -790,7 +786,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
 		       (dev)->pci_device == 0x2E22 || \
 		       (dev)->pci_device == 0x2E32)
 
-#define IS_I965GM(dev) ((dev)->pci_device == 0x2A02)
+#define IS_I965GM(dev) ((dev)->pci_device == 0x2A02 || \
+			(dev)->pci_device == 0x2A12)
 
 #define IS_GM45(dev) ((dev)->pci_device == 0x2A42)
 

+ 9 - 0
drivers/gpu/drm/i915/i915_gem.c

@@ -1691,11 +1691,20 @@ static int
 i915_wait_request(struct drm_device *dev, uint32_t seqno)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	u32 ier;
 	int ret = 0;
 
 	BUG_ON(seqno == 0);
 
 	if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) {
+		ier = I915_READ(IER);
+		if (!ier) {
+			DRM_ERROR("something (likely vbetool) disabled "
+				  "interrupts, re-enabling\n");
+			i915_driver_irq_preinstall(dev);
+			i915_driver_irq_postinstall(dev);
+		}
+
 		dev_priv->mm.waiting_gem_seqno = seqno;
 		i915_user_irq_get(dev);
 		ret = wait_event_interruptible(dev_priv->irq_queue,

+ 1 - 0
drivers/gpu/drm/i915/i915_reg.h

@@ -526,6 +526,7 @@
 #define   DPLLA_INPUT_BUFFER_ENABLE	(1 << 0)
 #define D_STATE		0x6104
 #define CG_2D_DIS	0x6200
+#define DPCUNIT_CLOCK_GATE_DISABLE	(1 << 24)
 #define CG_3D_DIS	0x6204
 
 /*

+ 24 - 0
drivers/gpu/drm/i915/i915_suspend.c

@@ -349,6 +349,18 @@ int i915_save_state(struct drm_device *dev)
 	for (i = 0; i < 3; i++)
 		dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2));
 
+	/* Fences */
+	if (IS_I965G(dev)) {
+		for (i = 0; i < 16; i++)
+			dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_965_0 + (i * 8));
+	} else {
+		for (i = 0; i < 8; i++)
+			dev_priv->saveFENCE[i] = I915_READ(FENCE_REG_830_0 + (i * 4));
+
+		if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
+			for (i = 0; i < 8; i++)
+				dev_priv->saveFENCE[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4));
+	}
 	i915_save_vga(dev);
 
 	return 0;
@@ -371,6 +383,18 @@ int i915_restore_state(struct drm_device *dev)
 	/* Display arbitration */
 	I915_WRITE(DSPARB, dev_priv->saveDSPARB);
 
+	/* Fences */
+	if (IS_I965G(dev)) {
+		for (i = 0; i < 16; i++)
+			I915_WRITE64(FENCE_REG_965_0 + (i * 8), dev_priv->saveFENCE[i]);
+	} else {
+		for (i = 0; i < 8; i++)
+			I915_WRITE(FENCE_REG_830_0 + (i * 4), dev_priv->saveFENCE[i]);
+		if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
+			for (i = 0; i < 8; i++)
+				I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]);
+	}
+
 	/* Pipe & plane A info */
 	/* Prime the clock */
 	if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {

+ 1 - 1
drivers/gpu/drm/i915/intel_crt.c

@@ -161,7 +161,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
 	hotplug_en &= CRT_FORCE_HOTPLUG_MASK;
 	hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
 
-	if (IS_GM45(dev))
+	if (IS_G4X(dev))
 		hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
 
 	hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;

+ 31 - 0
drivers/gpu/drm/i915/intel_display.c

@@ -1804,6 +1804,37 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 	}
 }
 
+int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
+				struct drm_file *file_priv)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_get_pipe_from_crtc_id *pipe_from_crtc_id = data;
+	struct drm_crtc *crtc = NULL;
+	int pipe = -1;
+
+	if (!dev_priv) {
+		DRM_ERROR("called with no initialization\n");
+		return -EINVAL;
+	}
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+		if (crtc->base.id == pipe_from_crtc_id->crtc_id) {
+			pipe = intel_crtc->pipe;
+			break;
+		}
+	}
+
+	if (pipe == -1) {
+		DRM_ERROR("no such CRTC id\n");
+		return -EINVAL;
+	}
+
+	pipe_from_crtc_id->pipe = pipe;
+
+       return 0;
+}
+
 struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe)
 {
 	struct drm_crtc *crtc = NULL;

+ 3 - 1
drivers/gpu/drm/i915/intel_drv.h

@@ -109,7 +109,7 @@ struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg,
 void intel_i2c_destroy(struct intel_i2c_chan *chan);
 int intel_ddc_get_modes(struct intel_output *intel_output);
 extern bool intel_ddc_probe(struct intel_output *intel_output);
-
+void intel_i2c_quirk_set(struct drm_device *dev, bool enable);
 extern void intel_crt_init(struct drm_device *dev);
 extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
 extern bool intel_sdvo_init(struct drm_device *dev, int output_device);
@@ -125,6 +125,8 @@ extern struct drm_encoder *intel_best_encoder(struct drm_connector *connector);
 
 extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
 						    struct drm_crtc *crtc);
+int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
+				struct drm_file *file_priv);
 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_crtc *intel_get_load_detect_pipe(struct intel_output *intel_output,

+ 12 - 5
drivers/gpu/drm/i915/intel_hdmi.c

@@ -155,11 +155,18 @@ intel_hdmi_detect(struct drm_connector *connector)
 
 	temp = I915_READ(PORT_HOTPLUG_EN);
 
-	I915_WRITE(PORT_HOTPLUG_EN,
-		   temp |
-		   HDMIB_HOTPLUG_INT_EN |
-		   HDMIC_HOTPLUG_INT_EN |
-		   HDMID_HOTPLUG_INT_EN);
+	switch (hdmi_priv->sdvox_reg) {
+	case SDVOB:
+		temp |= HDMIB_HOTPLUG_INT_EN;
+		break;
+	case SDVOC:
+		temp |= HDMIC_HOTPLUG_INT_EN;
+		break;
+	default:
+		return connector_status_unknown;
+	}
+
+	I915_WRITE(PORT_HOTPLUG_EN, temp);
 
 	POSTING_READ(PORT_HOTPLUG_EN);
 

+ 17 - 0
drivers/gpu/drm/i915/intel_i2c.c

@@ -34,6 +34,21 @@
 #include "i915_drm.h"
 #include "i915_drv.h"
 
+void intel_i2c_quirk_set(struct drm_device *dev, bool enable)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	/* When using bit bashing for I2C, this bit needs to be set to 1 */
+	if (!IS_IGD(dev))
+		return;
+	if (enable)
+		I915_WRITE(CG_2D_DIS,
+			I915_READ(CG_2D_DIS) | DPCUNIT_CLOCK_GATE_DISABLE);
+	else
+		I915_WRITE(CG_2D_DIS,
+			I915_READ(CG_2D_DIS) & (~DPCUNIT_CLOCK_GATE_DISABLE));
+}
+
 /*
  * Intel GPIO access functions
  */
@@ -153,8 +168,10 @@ struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg,
 		goto out_free;
 
 	/* JJJ:  raise SCL and SDA? */
+	intel_i2c_quirk_set(dev, true);
 	set_data(chan, 1);
 	set_clock(chan, 1);
+	intel_i2c_quirk_set(dev, false);
 	udelay(20);
 
 	return chan;

+ 46 - 8
drivers/gpu/drm/i915/intel_lvds.c

@@ -384,7 +384,51 @@ static const struct drm_encoder_funcs intel_lvds_enc_funcs = {
 	.destroy = intel_lvds_enc_destroy,
 };
 
+static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
+{
+	DRM_DEBUG("Skipping LVDS initialization for %s\n", id->ident);
+	return 1;
+}
 
+/* These systems claim to have LVDS, but really don't */
+static const struct dmi_system_id __initdata intel_no_lvds[] = {
+	{
+		.callback = intel_no_lvds_dmi_callback,
+		.ident = "Apple Mac Mini (Core series)",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"),
+		},
+	},
+	{
+		.callback = intel_no_lvds_dmi_callback,
+		.ident = "Apple Mac Mini (Core 2 series)",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Macmini2,1"),
+		},
+	},
+	{
+		.callback = intel_no_lvds_dmi_callback,
+		.ident = "MSI IM-945GSE-A",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MSI"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "A9830IMS"),
+		},
+	},
+	{
+		.callback = intel_no_lvds_dmi_callback,
+		.ident = "Dell Studio Hybrid",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Studio Hybrid 140g"),
+		},
+	},
+
+	/* FIXME: add a check for the Aopen Mini PC */
+
+	{ }	/* terminating entry */
+};
 
 /**
  * intel_lvds_init - setup LVDS connectors on this device
@@ -404,15 +448,9 @@ void intel_lvds_init(struct drm_device *dev)
 	u32 lvds;
 	int pipe;
 
-	/* Blacklist machines that we know falsely report LVDS. */
-	/* FIXME: add a check for the Aopen Mini PC */
-
-	/* Apple Mac Mini Core Duo and Mac Mini Core 2 Duo */
-	if(dmi_match(DMI_PRODUCT_NAME, "Macmini1,1") ||
-	   dmi_match(DMI_PRODUCT_NAME, "Macmini2,1")) {
-		DRM_DEBUG("Skipping LVDS initialization for Apple Mac Mini\n");
+	/* Skip init on machines we know falsely report LVDS */
+	if (dmi_check_system(intel_no_lvds))
 		return;
-	}
 
 	intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
 	if (!intel_output) {

+ 6 - 0
drivers/gpu/drm/i915/intel_modes.c

@@ -27,6 +27,7 @@
 #include <linux/fb.h>
 #include "drmP.h"
 #include "intel_drv.h"
+#include "i915_drv.h"
 
 /**
  * intel_ddc_probe
@@ -52,7 +53,10 @@ bool intel_ddc_probe(struct intel_output *intel_output)
 		}
 	};
 
+	intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true);
 	ret = i2c_transfer(&intel_output->ddc_bus->adapter, msgs, 2);
+	intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false);
+
 	if (ret == 2)
 		return true;
 
@@ -70,8 +74,10 @@ int intel_ddc_get_modes(struct intel_output *intel_output)
 	struct edid *edid;
 	int ret = 0;
 
+	intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true);
 	edid = drm_get_edid(&intel_output->base,
 			    &intel_output->ddc_bus->adapter);
+	intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false);
 	if (edid) {
 		drm_mode_connector_update_edid_property(&intel_output->base,
 							edid);

+ 10 - 0
include/drm/i915_drm.h

@@ -184,6 +184,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_GEM_GET_TILING	0x22
 #define DRM_I915_GEM_GET_APERTURE 0x23
 #define DRM_I915_GEM_MMAP_GTT	0x24
+#define DRM_I915_GET_PIPE_FROM_CRTC_ID	0x25
 
 #define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -219,6 +220,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_GEM_SET_TILING	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling)
 #define DRM_IOCTL_I915_GEM_GET_TILING	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling)
 #define DRM_IOCTL_I915_GEM_GET_APERTURE	DRM_IOR  (DRM_COMMAND_BASE + DRM_I915_GEM_GET_APERTURE, struct drm_i915_gem_get_aperture)
+#define DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_PIPE_FROM_CRTC_ID, struct drm_intel_get_pipe_from_crtc_id)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -657,4 +659,12 @@ struct drm_i915_gem_get_aperture {
 	__u64 aper_available_size;
 };
 
+struct drm_i915_get_pipe_from_crtc_id {
+	/** ID of CRTC being requested **/
+	__u32 crtc_id;
+
+	/** pipe of requested CRTC **/
+	__u32 pipe;
+};
+
 #endif				/* _I915_DRM_H_ */