Merge branch 'drm-intel-fixes' of git://people.freedesktop.org/~danvet/drm-intel into drm-fixes

* 'drm-intel-fixes' of git://people.freedesktop.org/~danvet/drm-intel:
  drm/i915: pch_irq_handler -> {ibx, cpt}_irq_handler
  char/agp: add another Ironlake host bridge
  drm/i915: fix up ivb plane 3 pageflips
  drm/i915: hold forcewake around ring hw init
  drm/i915: Mark the ringbuffers as being in the GTT domain
  drm/i915/crt: Do not rely upon the HPD presence pin
  drm/i915: Reset last_retired_head when resetting ring
This commit is contained in:
Dave Airlie 2012-06-08 09:42:35 +01:00
commit 6cf98d6ebb
9 changed files with 130 additions and 17 deletions

View File

@ -898,6 +898,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
ID(PCI_DEVICE_ID_INTEL_B43_HB), ID(PCI_DEVICE_ID_INTEL_B43_HB),
ID(PCI_DEVICE_ID_INTEL_B43_1_HB), ID(PCI_DEVICE_ID_INTEL_B43_1_HB),
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB),
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D2_HB),
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB),
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB),
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB),

View File

@ -212,6 +212,7 @@
#define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30 #define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30
#define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32 #define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32
#define PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB 0x0040 #define PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB 0x0040
#define PCI_DEVICE_ID_INTEL_IRONLAKE_D2_HB 0x0069
#define PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG 0x0042 #define PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG 0x0042
#define PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB 0x0044 #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB 0x0044
#define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062 #define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062

View File

@ -233,6 +233,7 @@ static const struct intel_device_info intel_sandybridge_d_info = {
.has_blt_ring = 1, .has_blt_ring = 1,
.has_llc = 1, .has_llc = 1,
.has_pch_split = 1, .has_pch_split = 1,
.has_force_wake = 1,
}; };
static const struct intel_device_info intel_sandybridge_m_info = { static const struct intel_device_info intel_sandybridge_m_info = {
@ -243,6 +244,7 @@ static const struct intel_device_info intel_sandybridge_m_info = {
.has_blt_ring = 1, .has_blt_ring = 1,
.has_llc = 1, .has_llc = 1,
.has_pch_split = 1, .has_pch_split = 1,
.has_force_wake = 1,
}; };
static const struct intel_device_info intel_ivybridge_d_info = { static const struct intel_device_info intel_ivybridge_d_info = {
@ -252,6 +254,7 @@ static const struct intel_device_info intel_ivybridge_d_info = {
.has_blt_ring = 1, .has_blt_ring = 1,
.has_llc = 1, .has_llc = 1,
.has_pch_split = 1, .has_pch_split = 1,
.has_force_wake = 1,
}; };
static const struct intel_device_info intel_ivybridge_m_info = { static const struct intel_device_info intel_ivybridge_m_info = {
@ -262,6 +265,7 @@ static const struct intel_device_info intel_ivybridge_m_info = {
.has_blt_ring = 1, .has_blt_ring = 1,
.has_llc = 1, .has_llc = 1,
.has_pch_split = 1, .has_pch_split = 1,
.has_force_wake = 1,
}; };
static const struct intel_device_info intel_valleyview_m_info = { static const struct intel_device_info intel_valleyview_m_info = {
@ -289,6 +293,7 @@ static const struct intel_device_info intel_haswell_d_info = {
.has_blt_ring = 1, .has_blt_ring = 1,
.has_llc = 1, .has_llc = 1,
.has_pch_split = 1, .has_pch_split = 1,
.has_force_wake = 1,
}; };
static const struct intel_device_info intel_haswell_m_info = { static const struct intel_device_info intel_haswell_m_info = {
@ -298,6 +303,7 @@ static const struct intel_device_info intel_haswell_m_info = {
.has_blt_ring = 1, .has_blt_ring = 1,
.has_llc = 1, .has_llc = 1,
.has_pch_split = 1, .has_pch_split = 1,
.has_force_wake = 1,
}; };
static const struct pci_device_id pciidlist[] = { /* aka */ static const struct pci_device_id pciidlist[] = { /* aka */
@ -1139,10 +1145,9 @@ MODULE_LICENSE("GPL and additional rights");
/* We give fast paths for the really cool registers */ /* We give fast paths for the really cool registers */
#define NEEDS_FORCE_WAKE(dev_priv, reg) \ #define NEEDS_FORCE_WAKE(dev_priv, reg) \
(((dev_priv)->info->gen >= 6) && \ ((HAS_FORCE_WAKE((dev_priv)->dev)) && \
((reg) < 0x40000) && \ ((reg) < 0x40000) && \
((reg) != FORCEWAKE)) && \ ((reg) != FORCEWAKE))
(!IS_VALLEYVIEW((dev_priv)->dev))
#define __i915_read(x, y) \ #define __i915_read(x, y) \
u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \

View File

@ -285,6 +285,7 @@ struct intel_device_info {
u8 is_ivybridge:1; u8 is_ivybridge:1;
u8 is_valleyview:1; u8 is_valleyview:1;
u8 has_pch_split:1; u8 has_pch_split:1;
u8 has_force_wake:1;
u8 is_haswell:1; u8 is_haswell:1;
u8 has_fbc:1; u8 has_fbc:1;
u8 has_pipe_cxsr:1; u8 has_pipe_cxsr:1;
@ -1101,6 +1102,8 @@ struct drm_i915_file_private {
#define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT)
#define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) #define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX)
#define HAS_FORCE_WAKE(dev) (INTEL_INFO(dev)->has_force_wake)
#include "i915_trace.h" #include "i915_trace.h"
/** /**

View File

@ -510,7 +510,7 @@ out:
return ret; return ret;
} }
static void pch_irq_handler(struct drm_device *dev, u32 pch_iir) static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir)
{ {
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
int pipe; int pipe;
@ -550,6 +550,35 @@ static void pch_irq_handler(struct drm_device *dev, u32 pch_iir)
DRM_DEBUG_DRIVER("PCH transcoder A underrun interrupt\n"); DRM_DEBUG_DRIVER("PCH transcoder A underrun interrupt\n");
} }
static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
int pipe;
if (pch_iir & SDE_AUDIO_POWER_MASK_CPT)
DRM_DEBUG_DRIVER("PCH audio power change on port %d\n",
(pch_iir & SDE_AUDIO_POWER_MASK_CPT) >>
SDE_AUDIO_POWER_SHIFT_CPT);
if (pch_iir & SDE_AUX_MASK_CPT)
DRM_DEBUG_DRIVER("AUX channel interrupt\n");
if (pch_iir & SDE_GMBUS_CPT)
DRM_DEBUG_DRIVER("PCH GMBUS interrupt\n");
if (pch_iir & SDE_AUDIO_CP_REQ_CPT)
DRM_DEBUG_DRIVER("Audio CP request interrupt\n");
if (pch_iir & SDE_AUDIO_CP_CHG_CPT)
DRM_DEBUG_DRIVER("Audio CP change interrupt\n");
if (pch_iir & SDE_FDI_MASK_CPT)
for_each_pipe(pipe)
DRM_DEBUG_DRIVER(" pipe %c FDI IIR: 0x%08x\n",
pipe_name(pipe),
I915_READ(FDI_RX_IIR(pipe)));
}
static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
{ {
struct drm_device *dev = (struct drm_device *) arg; struct drm_device *dev = (struct drm_device *) arg;
@ -591,7 +620,7 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
if (pch_iir & SDE_HOTPLUG_MASK_CPT) if (pch_iir & SDE_HOTPLUG_MASK_CPT)
queue_work(dev_priv->wq, &dev_priv->hotplug_work); queue_work(dev_priv->wq, &dev_priv->hotplug_work);
pch_irq_handler(dev, pch_iir); cpt_irq_handler(dev, pch_iir);
/* clear PCH hotplug event before clear CPU irq */ /* clear PCH hotplug event before clear CPU irq */
I915_WRITE(SDEIIR, pch_iir); I915_WRITE(SDEIIR, pch_iir);
@ -684,7 +713,10 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
if (de_iir & DE_PCH_EVENT) { if (de_iir & DE_PCH_EVENT) {
if (pch_iir & hotplug_mask) if (pch_iir & hotplug_mask)
queue_work(dev_priv->wq, &dev_priv->hotplug_work); queue_work(dev_priv->wq, &dev_priv->hotplug_work);
pch_irq_handler(dev, pch_iir); if (HAS_PCH_CPT(dev))
cpt_irq_handler(dev, pch_iir);
else
ibx_irq_handler(dev, pch_iir);
} }
if (de_iir & DE_PCU_EVENT) { if (de_iir & DE_PCU_EVENT) {

View File

@ -210,6 +210,14 @@
#define MI_DISPLAY_FLIP MI_INSTR(0x14, 2) #define MI_DISPLAY_FLIP MI_INSTR(0x14, 2)
#define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1) #define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1)
#define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20) #define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20)
/* IVB has funny definitions for which plane to flip. */
#define MI_DISPLAY_FLIP_IVB_PLANE_A (0 << 19)
#define MI_DISPLAY_FLIP_IVB_PLANE_B (1 << 19)
#define MI_DISPLAY_FLIP_IVB_SPRITE_A (2 << 19)
#define MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19)
#define MI_DISPLAY_FLIP_IVB_PLANE_C (4 << 19)
#define MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19)
#define MI_SET_CONTEXT MI_INSTR(0x18, 0) #define MI_SET_CONTEXT MI_INSTR(0x18, 0)
#define MI_MM_SPACE_GTT (1<<8) #define MI_MM_SPACE_GTT (1<<8)
#define MI_MM_SPACE_PHYSICAL (0<<8) #define MI_MM_SPACE_PHYSICAL (0<<8)
@ -3313,7 +3321,7 @@
/* PCH */ /* PCH */
/* south display engine interrupt */ /* south display engine interrupt: IBX */
#define SDE_AUDIO_POWER_D (1 << 27) #define SDE_AUDIO_POWER_D (1 << 27)
#define SDE_AUDIO_POWER_C (1 << 26) #define SDE_AUDIO_POWER_C (1 << 26)
#define SDE_AUDIO_POWER_B (1 << 25) #define SDE_AUDIO_POWER_B (1 << 25)
@ -3349,15 +3357,44 @@
#define SDE_TRANSA_CRC_ERR (1 << 1) #define SDE_TRANSA_CRC_ERR (1 << 1)
#define SDE_TRANSA_FIFO_UNDER (1 << 0) #define SDE_TRANSA_FIFO_UNDER (1 << 0)
#define SDE_TRANS_MASK (0x3f) #define SDE_TRANS_MASK (0x3f)
/* CPT */
#define SDE_CRT_HOTPLUG_CPT (1 << 19) /* south display engine interrupt: CPT/PPT */
#define SDE_AUDIO_POWER_D_CPT (1 << 31)
#define SDE_AUDIO_POWER_C_CPT (1 << 30)
#define SDE_AUDIO_POWER_B_CPT (1 << 29)
#define SDE_AUDIO_POWER_SHIFT_CPT 29
#define SDE_AUDIO_POWER_MASK_CPT (7 << 29)
#define SDE_AUXD_CPT (1 << 27)
#define SDE_AUXC_CPT (1 << 26)
#define SDE_AUXB_CPT (1 << 25)
#define SDE_AUX_MASK_CPT (7 << 25)
#define SDE_PORTD_HOTPLUG_CPT (1 << 23) #define SDE_PORTD_HOTPLUG_CPT (1 << 23)
#define SDE_PORTC_HOTPLUG_CPT (1 << 22) #define SDE_PORTC_HOTPLUG_CPT (1 << 22)
#define SDE_PORTB_HOTPLUG_CPT (1 << 21) #define SDE_PORTB_HOTPLUG_CPT (1 << 21)
#define SDE_CRT_HOTPLUG_CPT (1 << 19)
#define SDE_HOTPLUG_MASK_CPT (SDE_CRT_HOTPLUG_CPT | \ #define SDE_HOTPLUG_MASK_CPT (SDE_CRT_HOTPLUG_CPT | \
SDE_PORTD_HOTPLUG_CPT | \ SDE_PORTD_HOTPLUG_CPT | \
SDE_PORTC_HOTPLUG_CPT | \ SDE_PORTC_HOTPLUG_CPT | \
SDE_PORTB_HOTPLUG_CPT) SDE_PORTB_HOTPLUG_CPT)
#define SDE_GMBUS_CPT (1 << 17)
#define SDE_AUDIO_CP_REQ_C_CPT (1 << 10)
#define SDE_AUDIO_CP_CHG_C_CPT (1 << 9)
#define SDE_FDI_RXC_CPT (1 << 8)
#define SDE_AUDIO_CP_REQ_B_CPT (1 << 6)
#define SDE_AUDIO_CP_CHG_B_CPT (1 << 5)
#define SDE_FDI_RXB_CPT (1 << 4)
#define SDE_AUDIO_CP_REQ_A_CPT (1 << 2)
#define SDE_AUDIO_CP_CHG_A_CPT (1 << 1)
#define SDE_FDI_RXA_CPT (1 << 0)
#define SDE_AUDIO_CP_REQ_CPT (SDE_AUDIO_CP_REQ_C_CPT | \
SDE_AUDIO_CP_REQ_B_CPT | \
SDE_AUDIO_CP_REQ_A_CPT)
#define SDE_AUDIO_CP_CHG_CPT (SDE_AUDIO_CP_CHG_C_CPT | \
SDE_AUDIO_CP_CHG_B_CPT | \
SDE_AUDIO_CP_CHG_A_CPT)
#define SDE_FDI_MASK_CPT (SDE_FDI_RXC_CPT | \
SDE_FDI_RXB_CPT | \
SDE_FDI_RXA_CPT)
#define SDEISR 0xc4000 #define SDEISR 0xc4000
#define SDEIMR 0xc4004 #define SDEIMR 0xc4004

View File

@ -453,13 +453,15 @@ intel_crt_detect(struct drm_connector *connector, bool force)
struct intel_load_detect_pipe tmp; struct intel_load_detect_pipe tmp;
if (I915_HAS_HOTPLUG(dev)) { if (I915_HAS_HOTPLUG(dev)) {
/* We can not rely on the HPD pin always being correctly wired
* up, for example many KVM do not pass it through, and so
* only trust an assertion that the monitor is connected.
*/
if (intel_crt_detect_hotplug(connector)) { if (intel_crt_detect_hotplug(connector)) {
DRM_DEBUG_KMS("CRT detected via hotplug\n"); DRM_DEBUG_KMS("CRT detected via hotplug\n");
return connector_status_connected; return connector_status_connected;
} else { } else
DRM_DEBUG_KMS("CRT not detected via hotplug\n"); DRM_DEBUG_KMS("CRT not detected via hotplug\n");
return connector_status_disconnected;
}
} }
if (intel_crt_detect_ddc(connector)) if (intel_crt_detect_ddc(connector))

View File

@ -6158,17 +6158,34 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_ring_buffer *ring = &dev_priv->ring[BCS]; struct intel_ring_buffer *ring = &dev_priv->ring[BCS];
uint32_t plane_bit = 0;
int ret; int ret;
ret = intel_pin_and_fence_fb_obj(dev, obj, ring); ret = intel_pin_and_fence_fb_obj(dev, obj, ring);
if (ret) if (ret)
goto err; goto err;
switch(intel_crtc->plane) {
case PLANE_A:
plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_A;
break;
case PLANE_B:
plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_B;
break;
case PLANE_C:
plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_C;
break;
default:
WARN_ONCE(1, "unknown plane in flip command\n");
ret = -ENODEV;
goto err;
}
ret = intel_ring_begin(ring, 4); ret = intel_ring_begin(ring, 4);
if (ret) if (ret)
goto err_unpin; goto err_unpin;
intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | (intel_crtc->plane << 19)); intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit);
intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode));
intel_ring_emit(ring, (obj->gtt_offset)); intel_ring_emit(ring, (obj->gtt_offset));
intel_ring_emit(ring, (MI_NOOP)); intel_ring_emit(ring, (MI_NOOP));

View File

@ -266,10 +266,15 @@ u32 intel_ring_get_active_head(struct intel_ring_buffer *ring)
static int init_ring_common(struct intel_ring_buffer *ring) static int init_ring_common(struct intel_ring_buffer *ring)
{ {
drm_i915_private_t *dev_priv = ring->dev->dev_private; struct drm_device *dev = ring->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj = ring->obj; struct drm_i915_gem_object *obj = ring->obj;
int ret = 0;
u32 head; u32 head;
if (HAS_FORCE_WAKE(dev))
gen6_gt_force_wake_get(dev_priv);
/* Stop the ring if it's running. */ /* Stop the ring if it's running. */
I915_WRITE_CTL(ring, 0); I915_WRITE_CTL(ring, 0);
I915_WRITE_HEAD(ring, 0); I915_WRITE_HEAD(ring, 0);
@ -317,7 +322,8 @@ static int init_ring_common(struct intel_ring_buffer *ring)
I915_READ_HEAD(ring), I915_READ_HEAD(ring),
I915_READ_TAIL(ring), I915_READ_TAIL(ring),
I915_READ_START(ring)); I915_READ_START(ring));
return -EIO; ret = -EIO;
goto out;
} }
if (!drm_core_check_feature(ring->dev, DRIVER_MODESET)) if (!drm_core_check_feature(ring->dev, DRIVER_MODESET))
@ -326,9 +332,14 @@ static int init_ring_common(struct intel_ring_buffer *ring)
ring->head = I915_READ_HEAD(ring); ring->head = I915_READ_HEAD(ring);
ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR; ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR;
ring->space = ring_space(ring); ring->space = ring_space(ring);
ring->last_retired_head = -1;
} }
return 0; out:
if (HAS_FORCE_WAKE(dev))
gen6_gt_force_wake_put(dev_priv);
return ret;
} }
static int static int
@ -987,6 +998,10 @@ static int intel_init_ring_buffer(struct drm_device *dev,
if (ret) if (ret)
goto err_unref; goto err_unref;
ret = i915_gem_object_set_to_gtt_domain(obj, true);
if (ret)
goto err_unpin;
ring->virtual_start = ioremap_wc(dev->agp->base + obj->gtt_offset, ring->virtual_start = ioremap_wc(dev->agp->base + obj->gtt_offset,
ring->size); ring->size);
if (ring->virtual_start == NULL) { if (ring->virtual_start == NULL) {