浏览代码

Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux

Pull drm fixes from Dave Airlie:
 "Regression fixers for the big 3:

   - nouveau: hdmi audio, dac load detect, s/r regressions fixed
   - radeon: long standing system hang fixed, hdmi audio and rs780 fast
     fb fixes
   - intel: one old regression, a WARN removal, and a stop X dying fix

  Otherwise one mgag200 fix, a couple of arm build fixes, and a core use
  after free fix."

* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux:
  drm/nv50/kms: use dac loadval from vbios, where it's available
  drm/nv50/disp: force dac power state during load detect
  drm/nv50-nv84/fifo: fix resume regression introduced by playlist race fix
  drm/nv84/disp: Fix HDMI audio regression
  drm/i915/sdvo: Use &intel_sdvo->ddc instead of intel_sdvo->i2c for DDC.
  drm/radeon: don't allow audio on DCE6
  drm/radeon: Use direct mapping for fast fb access on RS780/RS880 (v2)
  radeon: Fix system hang issue when using KMS with older cards
  drm/i915: no lvds quirk for hp t5740
  drm/i915: Quirk the pipe A quirk in the modeset state checker
  drm/i915: Fix spurious -EIO/SIGBUS on wedged gpus
  drm/mgag200: Add missing write to index before accessing data register
  drm/nouveau: use mdelay instead of large udelay constants
  drm/tilcd: select BACKLIGHT_LCD_SUPPORT
  drm: fix a use-after-free when GPU acceleration disabled
Linus Torvalds 12 年之前
父节点
当前提交
6ea31c56a5

+ 5 - 1
drivers/gpu/drm/drm_irq.c

@@ -1054,7 +1054,7 @@ EXPORT_SYMBOL(drm_vblank_off);
  */
  */
 void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
 void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
 {
 {
-	/* vblank is not initialized (IRQ not installed ?) */
+	/* vblank is not initialized (IRQ not installed ?), or has been freed */
 	if (!dev->num_crtcs)
 	if (!dev->num_crtcs)
 		return;
 		return;
 	/*
 	/*
@@ -1076,6 +1076,10 @@ void drm_vblank_post_modeset(struct drm_device *dev, int crtc)
 {
 {
 	unsigned long irqflags;
 	unsigned long irqflags;
 
 
+	/* vblank is not initialized (IRQ not installed ?), or has been freed */
+	if (!dev->num_crtcs)
+		return;
+
 	if (dev->vblank_inmodeset[crtc]) {
 	if (dev->vblank_inmodeset[crtc]) {
 		spin_lock_irqsave(&dev->vbl_lock, irqflags);
 		spin_lock_irqsave(&dev->vbl_lock, irqflags);
 		dev->vblank_disable_allowed = 1;
 		dev->vblank_disable_allowed = 1;

+ 2 - 5
drivers/gpu/drm/i915/i915_gem.c

@@ -91,14 +91,11 @@ i915_gem_wait_for_error(struct i915_gpu_error *error)
 {
 {
 	int ret;
 	int ret;
 
 
-#define EXIT_COND (!i915_reset_in_progress(error))
+#define EXIT_COND (!i915_reset_in_progress(error) || \
+		   i915_terminally_wedged(error))
 	if (EXIT_COND)
 	if (EXIT_COND)
 		return 0;
 		return 0;
 
 
-	/* GPU is already declared terminally dead, give up. */
-	if (i915_terminally_wedged(error))
-		return -EIO;
-
 	/*
 	/*
 	 * Only wait 10 seconds for the gpu reset to complete to avoid hanging
 	 * Only wait 10 seconds for the gpu reset to complete to avoid hanging
 	 * userspace. If it takes that long something really bad is going on and
 	 * userspace. If it takes that long something really bad is going on and

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

@@ -7937,6 +7937,11 @@ intel_modeset_check_state(struct drm_device *dev)
 		memset(&pipe_config, 0, sizeof(pipe_config));
 		memset(&pipe_config, 0, sizeof(pipe_config));
 		active = dev_priv->display.get_pipe_config(crtc,
 		active = dev_priv->display.get_pipe_config(crtc,
 							   &pipe_config);
 							   &pipe_config);
+
+		/* hw state is inconsistent with the pipe A quirk */
+		if (crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)
+			active = crtc->active;
+
 		WARN(crtc->active != active,
 		WARN(crtc->active != active,
 		     "crtc active state doesn't match with hw state "
 		     "crtc active state doesn't match with hw state "
 		     "(expected %i, found %i)\n", crtc->active, active);
 		     "(expected %i, found %i)\n", crtc->active, active);

+ 2 - 2
drivers/gpu/drm/i915/intel_lvds.c

@@ -815,10 +815,10 @@ static const struct dmi_system_id intel_no_lvds[] = {
 	},
 	},
 	{
 	{
 		.callback = intel_no_lvds_dmi_callback,
 		.callback = intel_no_lvds_dmi_callback,
-		.ident = "Hewlett-Packard HP t5740e Thin Client",
+		.ident = "Hewlett-Packard HP t5740",
 		.matches = {
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
 			DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "HP t5740e Thin Client"),
+			DMI_MATCH(DMI_PRODUCT_NAME, " t5740"),
 		},
 		},
 	},
 	},
 	{
 	{

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

@@ -1776,7 +1776,7 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
 	 * Assume that the preferred modes are
 	 * Assume that the preferred modes are
 	 * arranged in priority order.
 	 * arranged in priority order.
 	 */
 	 */
-	intel_ddc_get_modes(connector, intel_sdvo->i2c);
+	intel_ddc_get_modes(connector, &intel_sdvo->ddc);
 	if (list_empty(&connector->probed_modes) == false)
 	if (list_empty(&connector->probed_modes) == false)
 		goto end;
 		goto end;
 
 

+ 5 - 4
drivers/gpu/drm/mgag200/mgag200_mode.c

@@ -1034,13 +1034,14 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
 			else
 			else
 				hi_pri_lvl = 5;
 				hi_pri_lvl = 5;
 
 
-			WREG8(0x1fde, 0x06);
-			WREG8(0x1fdf, hi_pri_lvl);
+			WREG8(MGAREG_CRTCEXT_INDEX, 0x06);
+			WREG8(MGAREG_CRTCEXT_DATA, hi_pri_lvl);
 		} else {
 		} else {
+			WREG8(MGAREG_CRTCEXT_INDEX, 0x06);
 			if (mdev->reg_1e24 >= 0x01)
 			if (mdev->reg_1e24 >= 0x01)
-				WREG8(0x1fdf, 0x03);
+				WREG8(MGAREG_CRTCEXT_DATA, 0x03);
 			else
 			else
-				WREG8(0x1fdf, 0x04);
+				WREG8(MGAREG_CRTCEXT_DATA, 0x04);
 		}
 		}
 	}
 	}
 	return 0;
 	return 0;

+ 6 - 1
drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c

@@ -50,11 +50,16 @@ nv50_dac_sense(struct nv50_disp_priv *priv, int or, u32 loadval)
 {
 {
 	const u32 doff = (or * 0x800);
 	const u32 doff = (or * 0x800);
 	int load = -EINVAL;
 	int load = -EINVAL;
+	nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80150000);
+	nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
 	nv_wr32(priv, 0x61a00c + doff, 0x00100000 | loadval);
 	nv_wr32(priv, 0x61a00c + doff, 0x00100000 | loadval);
-	udelay(9500);
+	mdelay(9);
+	udelay(500);
 	nv_wr32(priv, 0x61a00c + doff, 0x80000000);
 	nv_wr32(priv, 0x61a00c + doff, 0x80000000);
 	load = (nv_rd32(priv, 0x61a00c + doff) & 0x38000000) >> 27;
 	load = (nv_rd32(priv, 0x61a00c + doff) & 0x38000000) >> 27;
 	nv_wr32(priv, 0x61a00c + doff, 0x00000000);
 	nv_wr32(priv, 0x61a00c + doff, 0x00000000);
+	nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80550000);
+	nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
 	return load;
 	return load;
 }
 }
 
 

+ 4 - 0
drivers/gpu/drm/nouveau/core/engine/disp/hdminv84.c

@@ -55,6 +55,10 @@ nv84_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
 	nv_wr32(priv, 0x616510 + hoff, 0x00000000);
 	nv_wr32(priv, 0x616510 + hoff, 0x00000000);
 	nv_mask(priv, 0x616500 + hoff, 0x00000001, 0x00000001);
 	nv_mask(priv, 0x616500 + hoff, 0x00000001, 0x00000001);
 
 
+	nv_mask(priv, 0x6165d0 + hoff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */
+	nv_mask(priv, 0x616568 + hoff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */
+	nv_mask(priv, 0x616578 + hoff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */
+
 	/* ??? */
 	/* ??? */
 	nv_mask(priv, 0x61733c, 0x00100000, 0x00100000); /* RESETF */
 	nv_mask(priv, 0x61733c, 0x00100000, 0x00100000); /* RESETF */
 	nv_mask(priv, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */
 	nv_mask(priv, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */

+ 10 - 4
drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c

@@ -40,14 +40,13 @@
  * FIFO channel objects
  * FIFO channel objects
  ******************************************************************************/
  ******************************************************************************/
 
 
-void
-nv50_fifo_playlist_update(struct nv50_fifo_priv *priv)
+static void
+nv50_fifo_playlist_update_locked(struct nv50_fifo_priv *priv)
 {
 {
 	struct nouveau_bar *bar = nouveau_bar(priv);
 	struct nouveau_bar *bar = nouveau_bar(priv);
 	struct nouveau_gpuobj *cur;
 	struct nouveau_gpuobj *cur;
 	int i, p;
 	int i, p;
 
 
-	mutex_lock(&nv_subdev(priv)->mutex);
 	cur = priv->playlist[priv->cur_playlist];
 	cur = priv->playlist[priv->cur_playlist];
 	priv->cur_playlist = !priv->cur_playlist;
 	priv->cur_playlist = !priv->cur_playlist;
 
 
@@ -61,6 +60,13 @@ nv50_fifo_playlist_update(struct nv50_fifo_priv *priv)
 	nv_wr32(priv, 0x0032f4, cur->addr >> 12);
 	nv_wr32(priv, 0x0032f4, cur->addr >> 12);
 	nv_wr32(priv, 0x0032ec, p);
 	nv_wr32(priv, 0x0032ec, p);
 	nv_wr32(priv, 0x002500, 0x00000101);
 	nv_wr32(priv, 0x002500, 0x00000101);
+}
+
+void
+nv50_fifo_playlist_update(struct nv50_fifo_priv *priv)
+{
+	mutex_lock(&nv_subdev(priv)->mutex);
+	nv50_fifo_playlist_update_locked(priv);
 	mutex_unlock(&nv_subdev(priv)->mutex);
 	mutex_unlock(&nv_subdev(priv)->mutex);
 }
 }
 
 
@@ -489,7 +495,7 @@ nv50_fifo_init(struct nouveau_object *object)
 
 
 	for (i = 0; i < 128; i++)
 	for (i = 0; i < 128; i++)
 		nv_wr32(priv, 0x002600 + (i * 4), 0x00000000);
 		nv_wr32(priv, 0x002600 + (i * 4), 0x00000000);
-	nv50_fifo_playlist_update(priv);
+	nv50_fifo_playlist_update_locked(priv);
 
 
 	nv_wr32(priv, 0x003200, 0x00000001);
 	nv_wr32(priv, 0x003200, 0x00000001);
 	nv_wr32(priv, 0x003250, 0x00000001);
 	nv_wr32(priv, 0x003250, 0x00000001);

+ 1 - 1
drivers/gpu/drm/nouveau/core/include/core/class.h

@@ -218,7 +218,7 @@ struct nv04_display_class {
 #define NV50_DISP_DAC_PWR_STATE                                      0x00000040
 #define NV50_DISP_DAC_PWR_STATE                                      0x00000040
 #define NV50_DISP_DAC_PWR_STATE_ON                                   0x00000000
 #define NV50_DISP_DAC_PWR_STATE_ON                                   0x00000000
 #define NV50_DISP_DAC_PWR_STATE_OFF                                  0x00000040
 #define NV50_DISP_DAC_PWR_STATE_OFF                                  0x00000040
-#define NV50_DISP_DAC_LOAD                                           0x0002000c
+#define NV50_DISP_DAC_LOAD                                           0x00020100
 #define NV50_DISP_DAC_LOAD_VALUE                                     0x00000007
 #define NV50_DISP_DAC_LOAD_VALUE                                     0x00000007
 
 
 #define NV50_DISP_PIOR_MTHD                                          0x00030000
 #define NV50_DISP_PIOR_MTHD                                          0x00030000

+ 3 - 1
drivers/gpu/drm/nouveau/nv50_display.c

@@ -1554,7 +1554,9 @@ nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
 {
 {
 	struct nv50_disp *disp = nv50_disp(encoder->dev);
 	struct nv50_disp *disp = nv50_disp(encoder->dev);
 	int ret, or = nouveau_encoder(encoder)->or;
 	int ret, or = nouveau_encoder(encoder)->or;
-	u32 load = 0;
+	u32 load = nouveau_drm(encoder->dev)->vbios.dactestval;
+	if (load == 0)
+		load = 340;
 
 
 	ret = nv_exec(disp->core, NV50_DISP_DAC_LOAD + or, &load, sizeof(load));
 	ret = nv_exec(disp->core, NV50_DISP_DAC_LOAD + or, &load, sizeof(load));
 	if (ret || load != 7)
 	if (ret || load != 7)

+ 8 - 3
drivers/gpu/drm/radeon/atombios_encoders.c

@@ -667,6 +667,8 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
 int
 int
 atombios_get_encoder_mode(struct drm_encoder *encoder)
 atombios_get_encoder_mode(struct drm_encoder *encoder)
 {
 {
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct drm_connector *connector;
 	struct drm_connector *connector;
 	struct radeon_connector *radeon_connector;
 	struct radeon_connector *radeon_connector;
@@ -693,7 +695,8 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
 	case DRM_MODE_CONNECTOR_DVII:
 	case DRM_MODE_CONNECTOR_DVII:
 	case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
 	case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
 		if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
 		if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
-		    radeon_audio)
+		    radeon_audio &&
+		    !ASIC_IS_DCE6(rdev)) /* remove once we support DCE6 */
 			return ATOM_ENCODER_MODE_HDMI;
 			return ATOM_ENCODER_MODE_HDMI;
 		else if (radeon_connector->use_digital)
 		else if (radeon_connector->use_digital)
 			return ATOM_ENCODER_MODE_DVI;
 			return ATOM_ENCODER_MODE_DVI;
@@ -704,7 +707,8 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
 	case DRM_MODE_CONNECTOR_HDMIA:
 	case DRM_MODE_CONNECTOR_HDMIA:
 	default:
 	default:
 		if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
 		if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
-		    radeon_audio)
+		    radeon_audio &&
+		    !ASIC_IS_DCE6(rdev)) /* remove once we support DCE6 */
 			return ATOM_ENCODER_MODE_HDMI;
 			return ATOM_ENCODER_MODE_HDMI;
 		else
 		else
 			return ATOM_ENCODER_MODE_DVI;
 			return ATOM_ENCODER_MODE_DVI;
@@ -718,7 +722,8 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
 		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
 		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
 			return ATOM_ENCODER_MODE_DP;
 			return ATOM_ENCODER_MODE_DP;
 		else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
 		else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
-			 radeon_audio)
+			 radeon_audio &&
+			 !ASIC_IS_DCE6(rdev)) /* remove once we support DCE6 */
 			return ATOM_ENCODER_MODE_HDMI;
 			return ATOM_ENCODER_MODE_HDMI;
 		else
 		else
 			return ATOM_ENCODER_MODE_DVI;
 			return ATOM_ENCODER_MODE_DVI;

+ 6 - 4
drivers/gpu/drm/radeon/evergreen.c

@@ -4754,6 +4754,12 @@ static int evergreen_startup(struct radeon_device *rdev)
 		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
 		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
 
 
 	/* Enable IRQ */
 	/* Enable IRQ */
+	if (!rdev->irq.installed) {
+		r = radeon_irq_kms_init(rdev);
+		if (r)
+			return r;
+	}
+
 	r = r600_irq_init(rdev);
 	r = r600_irq_init(rdev);
 	if (r) {
 	if (r) {
 		DRM_ERROR("radeon: IH init failed (%d).\n", r);
 		DRM_ERROR("radeon: IH init failed (%d).\n", r);
@@ -4923,10 +4929,6 @@ int evergreen_init(struct radeon_device *rdev)
 	if (r)
 	if (r)
 		return r;
 		return r;
 
 
-	r = radeon_irq_kms_init(rdev);
-	if (r)
-		return r;
-
 	rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
 	rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
 	r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
 	r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
 
 

+ 6 - 4
drivers/gpu/drm/radeon/ni.c

@@ -2025,6 +2025,12 @@ static int cayman_startup(struct radeon_device *rdev)
 	}
 	}
 
 
 	/* Enable IRQ */
 	/* Enable IRQ */
+	if (!rdev->irq.installed) {
+		r = radeon_irq_kms_init(rdev);
+		if (r)
+			return r;
+	}
+
 	r = r600_irq_init(rdev);
 	r = r600_irq_init(rdev);
 	if (r) {
 	if (r) {
 		DRM_ERROR("radeon: IH init failed (%d).\n", r);
 		DRM_ERROR("radeon: IH init failed (%d).\n", r);
@@ -2190,10 +2196,6 @@ int cayman_init(struct radeon_device *rdev)
 	if (r)
 	if (r)
 		return r;
 		return r;
 
 
-	r = radeon_irq_kms_init(rdev);
-	if (r)
-		return r;
-
 	ring->ring_obj = NULL;
 	ring->ring_obj = NULL;
 	r600_ring_init(rdev, ring, 1024 * 1024);
 	r600_ring_init(rdev, ring, 1024 * 1024);
 
 

+ 6 - 3
drivers/gpu/drm/radeon/r100.c

@@ -3869,6 +3869,12 @@ static int r100_startup(struct radeon_device *rdev)
 	}
 	}
 
 
 	/* Enable IRQ */
 	/* Enable IRQ */
+	if (!rdev->irq.installed) {
+		r = radeon_irq_kms_init(rdev);
+		if (r)
+			return r;
+	}
+
 	r100_irq_set(rdev);
 	r100_irq_set(rdev);
 	rdev->config.r100.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	rdev->config.r100.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	/* 1M ring buffer */
 	/* 1M ring buffer */
@@ -4022,9 +4028,6 @@ int r100_init(struct radeon_device *rdev)
 	r100_mc_init(rdev);
 	r100_mc_init(rdev);
 	/* Fence driver */
 	/* Fence driver */
 	r = radeon_fence_driver_init(rdev);
 	r = radeon_fence_driver_init(rdev);
-	if (r)
-		return r;
-	r = radeon_irq_kms_init(rdev);
 	if (r)
 	if (r)
 		return r;
 		return r;
 	/* Memory manager */
 	/* Memory manager */

+ 6 - 3
drivers/gpu/drm/radeon/r300.c

@@ -1382,6 +1382,12 @@ static int r300_startup(struct radeon_device *rdev)
 	}
 	}
 
 
 	/* Enable IRQ */
 	/* Enable IRQ */
+	if (!rdev->irq.installed) {
+		r = radeon_irq_kms_init(rdev);
+		if (r)
+			return r;
+	}
+
 	r100_irq_set(rdev);
 	r100_irq_set(rdev);
 	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	/* 1M ring buffer */
 	/* 1M ring buffer */
@@ -1514,9 +1520,6 @@ int r300_init(struct radeon_device *rdev)
 	r300_mc_init(rdev);
 	r300_mc_init(rdev);
 	/* Fence driver */
 	/* Fence driver */
 	r = radeon_fence_driver_init(rdev);
 	r = radeon_fence_driver_init(rdev);
-	if (r)
-		return r;
-	r = radeon_irq_kms_init(rdev);
 	if (r)
 	if (r)
 		return r;
 		return r;
 	/* Memory manager */
 	/* Memory manager */

+ 6 - 4
drivers/gpu/drm/radeon/r420.c

@@ -265,6 +265,12 @@ static int r420_startup(struct radeon_device *rdev)
 	}
 	}
 
 
 	/* Enable IRQ */
 	/* Enable IRQ */
+	if (!rdev->irq.installed) {
+		r = radeon_irq_kms_init(rdev);
+		if (r)
+			return r;
+	}
+
 	r100_irq_set(rdev);
 	r100_irq_set(rdev);
 	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	/* 1M ring buffer */
 	/* 1M ring buffer */
@@ -411,10 +417,6 @@ int r420_init(struct radeon_device *rdev)
 	if (r) {
 	if (r) {
 		return r;
 		return r;
 	}
 	}
-	r = radeon_irq_kms_init(rdev);
-	if (r) {
-		return r;
-	}
 	/* Memory manager */
 	/* Memory manager */
 	r = radeon_bo_init(rdev);
 	r = radeon_bo_init(rdev);
 	if (r) {
 	if (r) {

+ 6 - 3
drivers/gpu/drm/radeon/r520.c

@@ -194,6 +194,12 @@ static int r520_startup(struct radeon_device *rdev)
 	}
 	}
 
 
 	/* Enable IRQ */
 	/* Enable IRQ */
+	if (!rdev->irq.installed) {
+		r = radeon_irq_kms_init(rdev);
+		if (r)
+			return r;
+	}
+
 	rs600_irq_set(rdev);
 	rs600_irq_set(rdev);
 	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	/* 1M ring buffer */
 	/* 1M ring buffer */
@@ -295,9 +301,6 @@ int r520_init(struct radeon_device *rdev)
 	rv515_debugfs(rdev);
 	rv515_debugfs(rdev);
 	/* Fence driver */
 	/* Fence driver */
 	r = radeon_fence_driver_init(rdev);
 	r = radeon_fence_driver_init(rdev);
-	if (r)
-		return r;
-	r = radeon_irq_kms_init(rdev);
 	if (r)
 	if (r)
 		return r;
 		return r;
 	/* Memory manager */
 	/* Memory manager */

+ 49 - 4
drivers/gpu/drm/radeon/r600.c

@@ -1046,6 +1046,24 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev)
 	return -1;
 	return -1;
 }
 }
 
 
+uint32_t rs780_mc_rreg(struct radeon_device *rdev, uint32_t reg)
+{
+	uint32_t r;
+
+	WREG32(R_0028F8_MC_INDEX, S_0028F8_MC_IND_ADDR(reg));
+	r = RREG32(R_0028FC_MC_DATA);
+	WREG32(R_0028F8_MC_INDEX, ~C_0028F8_MC_IND_ADDR);
+	return r;
+}
+
+void rs780_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
+{
+	WREG32(R_0028F8_MC_INDEX, S_0028F8_MC_IND_ADDR(reg) |
+		S_0028F8_MC_IND_WR_EN(1));
+	WREG32(R_0028FC_MC_DATA, v);
+	WREG32(R_0028F8_MC_INDEX, 0x7F);
+}
+
 static void r600_mc_program(struct radeon_device *rdev)
 static void r600_mc_program(struct radeon_device *rdev)
 {
 {
 	struct rv515_mc_save save;
 	struct rv515_mc_save save;
@@ -1181,6 +1199,8 @@ static int r600_mc_init(struct radeon_device *rdev)
 {
 {
 	u32 tmp;
 	u32 tmp;
 	int chansize, numchan;
 	int chansize, numchan;
+	uint32_t h_addr, l_addr;
+	unsigned long long k8_addr;
 
 
 	/* Get VRAM informations */
 	/* Get VRAM informations */
 	rdev->mc.vram_is_ddr = true;
 	rdev->mc.vram_is_ddr = true;
@@ -1221,7 +1241,30 @@ static int r600_mc_init(struct radeon_device *rdev)
 	if (rdev->flags & RADEON_IS_IGP) {
 	if (rdev->flags & RADEON_IS_IGP) {
 		rs690_pm_info(rdev);
 		rs690_pm_info(rdev);
 		rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
 		rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
+
+		if (rdev->family == CHIP_RS780 || rdev->family == CHIP_RS880) {
+			/* Use K8 direct mapping for fast fb access. */
+			rdev->fastfb_working = false;
+			h_addr = G_000012_K8_ADDR_EXT(RREG32_MC(R_000012_MC_MISC_UMA_CNTL));
+			l_addr = RREG32_MC(R_000011_K8_FB_LOCATION);
+			k8_addr = ((unsigned long long)h_addr) << 32 | l_addr;
+#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_PAE)
+			if (k8_addr + rdev->mc.visible_vram_size < 0x100000000ULL)
+#endif
+			{
+				/* FastFB shall be used with UMA memory. Here it is simply disabled when sideport
+		 		* memory is present.
+		 		*/
+				if (rdev->mc.igp_sideport_enabled == false && radeon_fastfb == 1) {
+					DRM_INFO("Direct mapping: aper base at 0x%llx, replaced by direct mapping base 0x%llx.\n",
+						(unsigned long long)rdev->mc.aper_base, k8_addr);
+					rdev->mc.aper_base = (resource_size_t)k8_addr;
+					rdev->fastfb_working = true;
+				}
+			}
+  		}
 	}
 	}
+
 	radeon_update_bandwidth_info(rdev);
 	radeon_update_bandwidth_info(rdev);
 	return 0;
 	return 0;
 }
 }
@@ -3202,6 +3245,12 @@ static int r600_startup(struct radeon_device *rdev)
 	}
 	}
 
 
 	/* Enable IRQ */
 	/* Enable IRQ */
+	if (!rdev->irq.installed) {
+		r = radeon_irq_kms_init(rdev);
+		if (r)
+			return r;
+	}
+
 	r = r600_irq_init(rdev);
 	r = r600_irq_init(rdev);
 	if (r) {
 	if (r) {
 		DRM_ERROR("radeon: IH init failed (%d).\n", r);
 		DRM_ERROR("radeon: IH init failed (%d).\n", r);
@@ -3356,10 +3405,6 @@ int r600_init(struct radeon_device *rdev)
 	if (r)
 	if (r)
 		return r;
 		return r;
 
 
-	r = radeon_irq_kms_init(rdev);
-	if (r)
-		return r;
-
 	rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
 	rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
 	r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
 	r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
 
 

+ 8 - 0
drivers/gpu/drm/radeon/r600d.h

@@ -1342,6 +1342,14 @@
 #define	PACKET3_STRMOUT_BASE_UPDATE			0x72 /* r7xx */
 #define	PACKET3_STRMOUT_BASE_UPDATE			0x72 /* r7xx */
 #define	PACKET3_SURFACE_BASE_UPDATE			0x73
 #define	PACKET3_SURFACE_BASE_UPDATE			0x73
 
 
+#define R_000011_K8_FB_LOCATION                 0x11
+#define R_000012_MC_MISC_UMA_CNTL               0x12
+#define   G_000012_K8_ADDR_EXT(x)               (((x) >> 0) & 0xFF)
+#define R_0028F8_MC_INDEX			0x28F8
+#define   	S_0028F8_MC_IND_ADDR(x)                 (((x) & 0x1FF) << 0)
+#define   	C_0028F8_MC_IND_ADDR                    0xFFFFFE00
+#define   	S_0028F8_MC_IND_WR_EN(x)                (((x) & 0x1) << 9)
+#define R_0028FC_MC_DATA                        0x28FC
 
 
 #define	R_008020_GRBM_SOFT_RESET		0x8020
 #define	R_008020_GRBM_SOFT_RESET		0x8020
 #define		S_008020_SOFT_RESET_CP(x)		(((x) & 1) << 0)
 #define		S_008020_SOFT_RESET_CP(x)		(((x) & 1) << 0)

+ 4 - 0
drivers/gpu/drm/radeon/radeon_asic.c

@@ -122,6 +122,10 @@ static void radeon_register_accessor_init(struct radeon_device *rdev)
 		rdev->mc_rreg = &rs600_mc_rreg;
 		rdev->mc_rreg = &rs600_mc_rreg;
 		rdev->mc_wreg = &rs600_mc_wreg;
 		rdev->mc_wreg = &rs600_mc_wreg;
 	}
 	}
+	if (rdev->family == CHIP_RS780 || rdev->family == CHIP_RS880) {
+		rdev->mc_rreg = &rs780_mc_rreg;
+		rdev->mc_wreg = &rs780_mc_wreg;
+	}
 	if (rdev->family >= CHIP_R600) {
 	if (rdev->family >= CHIP_R600) {
 		rdev->pciep_rreg = &r600_pciep_rreg;
 		rdev->pciep_rreg = &r600_pciep_rreg;
 		rdev->pciep_wreg = &r600_pciep_wreg;
 		rdev->pciep_wreg = &r600_pciep_wreg;

+ 2 - 0
drivers/gpu/drm/radeon/radeon_asic.h

@@ -347,6 +347,8 @@ extern bool r600_gui_idle(struct radeon_device *rdev);
 extern void r600_pm_misc(struct radeon_device *rdev);
 extern void r600_pm_misc(struct radeon_device *rdev);
 extern void r600_pm_init_profile(struct radeon_device *rdev);
 extern void r600_pm_init_profile(struct radeon_device *rdev);
 extern void rs780_pm_init_profile(struct radeon_device *rdev);
 extern void rs780_pm_init_profile(struct radeon_device *rdev);
+extern uint32_t rs780_mc_rreg(struct radeon_device *rdev, uint32_t reg);
+extern void rs780_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 extern void r600_pm_get_dynpm_state(struct radeon_device *rdev);
 extern void r600_pm_get_dynpm_state(struct radeon_device *rdev);
 extern void r600_set_pcie_lanes(struct radeon_device *rdev, int lanes);
 extern void r600_set_pcie_lanes(struct radeon_device *rdev, int lanes);
 extern int r600_get_pcie_lanes(struct radeon_device *rdev);
 extern int r600_get_pcie_lanes(struct radeon_device *rdev);

+ 6 - 3
drivers/gpu/drm/radeon/rs400.c

@@ -417,6 +417,12 @@ static int rs400_startup(struct radeon_device *rdev)
 	}
 	}
 
 
 	/* Enable IRQ */
 	/* Enable IRQ */
+	if (!rdev->irq.installed) {
+		r = radeon_irq_kms_init(rdev);
+		if (r)
+			return r;
+	}
+
 	r100_irq_set(rdev);
 	r100_irq_set(rdev);
 	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	/* 1M ring buffer */
 	/* 1M ring buffer */
@@ -533,9 +539,6 @@ int rs400_init(struct radeon_device *rdev)
 	rs400_mc_init(rdev);
 	rs400_mc_init(rdev);
 	/* Fence driver */
 	/* Fence driver */
 	r = radeon_fence_driver_init(rdev);
 	r = radeon_fence_driver_init(rdev);
-	if (r)
-		return r;
-	r = radeon_irq_kms_init(rdev);
 	if (r)
 	if (r)
 		return r;
 		return r;
 	/* Memory manager */
 	/* Memory manager */

+ 6 - 3
drivers/gpu/drm/radeon/rs600.c

@@ -923,6 +923,12 @@ static int rs600_startup(struct radeon_device *rdev)
 	}
 	}
 
 
 	/* Enable IRQ */
 	/* Enable IRQ */
+	if (!rdev->irq.installed) {
+		r = radeon_irq_kms_init(rdev);
+		if (r)
+			return r;
+	}
+
 	rs600_irq_set(rdev);
 	rs600_irq_set(rdev);
 	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	/* 1M ring buffer */
 	/* 1M ring buffer */
@@ -1045,9 +1051,6 @@ int rs600_init(struct radeon_device *rdev)
 	rs600_debugfs(rdev);
 	rs600_debugfs(rdev);
 	/* Fence driver */
 	/* Fence driver */
 	r = radeon_fence_driver_init(rdev);
 	r = radeon_fence_driver_init(rdev);
-	if (r)
-		return r;
-	r = radeon_irq_kms_init(rdev);
 	if (r)
 	if (r)
 		return r;
 		return r;
 	/* Memory manager */
 	/* Memory manager */

+ 6 - 3
drivers/gpu/drm/radeon/rs690.c

@@ -651,6 +651,12 @@ static int rs690_startup(struct radeon_device *rdev)
 	}
 	}
 
 
 	/* Enable IRQ */
 	/* Enable IRQ */
+	if (!rdev->irq.installed) {
+		r = radeon_irq_kms_init(rdev);
+		if (r)
+			return r;
+	}
+
 	rs600_irq_set(rdev);
 	rs600_irq_set(rdev);
 	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	/* 1M ring buffer */
 	/* 1M ring buffer */
@@ -774,9 +780,6 @@ int rs690_init(struct radeon_device *rdev)
 	rv515_debugfs(rdev);
 	rv515_debugfs(rdev);
 	/* Fence driver */
 	/* Fence driver */
 	r = radeon_fence_driver_init(rdev);
 	r = radeon_fence_driver_init(rdev);
-	if (r)
-		return r;
-	r = radeon_irq_kms_init(rdev);
 	if (r)
 	if (r)
 		return r;
 		return r;
 	/* Memory manager */
 	/* Memory manager */

+ 6 - 3
drivers/gpu/drm/radeon/rv515.c

@@ -532,6 +532,12 @@ static int rv515_startup(struct radeon_device *rdev)
 	}
 	}
 
 
 	/* Enable IRQ */
 	/* Enable IRQ */
+	if (!rdev->irq.installed) {
+		r = radeon_irq_kms_init(rdev);
+		if (r)
+			return r;
+	}
+
 	rs600_irq_set(rdev);
 	rs600_irq_set(rdev);
 	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	/* 1M ring buffer */
 	/* 1M ring buffer */
@@ -660,9 +666,6 @@ int rv515_init(struct radeon_device *rdev)
 	rv515_debugfs(rdev);
 	rv515_debugfs(rdev);
 	/* Fence driver */
 	/* Fence driver */
 	r = radeon_fence_driver_init(rdev);
 	r = radeon_fence_driver_init(rdev);
-	if (r)
-		return r;
-	r = radeon_irq_kms_init(rdev);
 	if (r)
 	if (r)
 		return r;
 		return r;
 	/* Memory manager */
 	/* Memory manager */

+ 6 - 4
drivers/gpu/drm/radeon/rv770.c

@@ -1887,6 +1887,12 @@ static int rv770_startup(struct radeon_device *rdev)
 		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
 		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
 
 
 	/* Enable IRQ */
 	/* Enable IRQ */
+	if (!rdev->irq.installed) {
+		r = radeon_irq_kms_init(rdev);
+		if (r)
+			return r;
+	}
+
 	r = r600_irq_init(rdev);
 	r = r600_irq_init(rdev);
 	if (r) {
 	if (r) {
 		DRM_ERROR("radeon: IH init failed (%d).\n", r);
 		DRM_ERROR("radeon: IH init failed (%d).\n", r);
@@ -2045,10 +2051,6 @@ int rv770_init(struct radeon_device *rdev)
 	if (r)
 	if (r)
 		return r;
 		return r;
 
 
-	r = radeon_irq_kms_init(rdev);
-	if (r)
-		return r;
-
 	rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
 	rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
 	r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
 	r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
 
 

+ 6 - 4
drivers/gpu/drm/radeon/si.c

@@ -5350,6 +5350,12 @@ static int si_startup(struct radeon_device *rdev)
 	}
 	}
 
 
 	/* Enable IRQ */
 	/* Enable IRQ */
+	if (!rdev->irq.installed) {
+		r = radeon_irq_kms_init(rdev);
+		if (r)
+			return r;
+	}
+
 	r = si_irq_init(rdev);
 	r = si_irq_init(rdev);
 	if (r) {
 	if (r) {
 		DRM_ERROR("radeon: IH init failed (%d).\n", r);
 		DRM_ERROR("radeon: IH init failed (%d).\n", r);
@@ -5533,10 +5539,6 @@ int si_init(struct radeon_device *rdev)
 	if (r)
 	if (r)
 		return r;
 		return r;
 
 
-	r = radeon_irq_kms_init(rdev);
-	if (r)
-		return r;
-
 	ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
 	ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
 	ring->ring_obj = NULL;
 	ring->ring_obj = NULL;
 	r600_ring_init(rdev, ring, 1024 * 1024);
 	r600_ring_init(rdev, ring, 1024 * 1024);

+ 1 - 0
drivers/gpu/drm/tilcdc/Kconfig

@@ -6,6 +6,7 @@ config DRM_TILCDC
 	select DRM_GEM_CMA_HELPER
 	select DRM_GEM_CMA_HELPER
 	select VIDEOMODE_HELPERS
 	select VIDEOMODE_HELPERS
 	select BACKLIGHT_CLASS_DEVICE
 	select BACKLIGHT_CLASS_DEVICE
+	select BACKLIGHT_LCD_SUPPORT
 	help
 	help
 	  Choose this option if you have an TI SoC with LCDC display
 	  Choose this option if you have an TI SoC with LCDC display
 	  controller, for example AM33xx in beagle-bone, DA8xx, or
 	  controller, for example AM33xx in beagle-bone, DA8xx, or