aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c1
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h5
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c116
3 files changed, 106 insertions, 16 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index e4d2b9f15ae2..65876c0e0499 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1672,6 +1672,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
1672 goto out_mtrrfree; 1672 goto out_mtrrfree;
1673 } 1673 }
1674 1674
1675 dev_priv->display_irqs_enabled = true;
1675 intel_irq_init(dev); 1676 intel_irq_init(dev);
1676 intel_uncore_sanitize(dev); 1677 intel_uncore_sanitize(dev);
1677 1678
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9387c56647ba..8702893a64f6 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1469,6 +1469,8 @@ typedef struct drm_i915_private {
1469 /* protects the irq masks */ 1469 /* protects the irq masks */
1470 spinlock_t irq_lock; 1470 spinlock_t irq_lock;
1471 1471
1472 bool display_irqs_enabled;
1473
1472 /* To control wakeup latency, e.g. for irq-driven dp aux transfers. */ 1474 /* To control wakeup latency, e.g. for irq-driven dp aux transfers. */
1473 struct pm_qos_request pm_qos; 1475 struct pm_qos_request pm_qos;
1474 1476
@@ -2063,6 +2065,9 @@ void
2063i915_disable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, 2065i915_disable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe,
2064 u32 status_mask); 2066 u32 status_mask);
2065 2067
2068void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv);
2069void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv);
2070
2066/* i915_gem.c */ 2071/* i915_gem.c */
2067int i915_gem_init_ioctl(struct drm_device *dev, void *data, 2072int i915_gem_init_ioctl(struct drm_device *dev, void *data,
2068 struct drm_file *file_priv); 2073 struct drm_file *file_priv);
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 4a19306b2d73..d6f827ab8f01 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -3025,36 +3025,113 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
3025 return 0; 3025 return 0;
3026} 3026}
3027 3027
3028static void valleyview_display_irqs_install(struct drm_i915_private *dev_priv)
3029{
3030 u32 pipestat_mask;
3031 u32 iir_mask;
3032
3033 pipestat_mask = PIPESTAT_INT_STATUS_MASK |
3034 PIPE_FIFO_UNDERRUN_STATUS;
3035
3036 I915_WRITE(PIPESTAT(PIPE_A), pipestat_mask);
3037 I915_WRITE(PIPESTAT(PIPE_B), pipestat_mask);
3038 POSTING_READ(PIPESTAT(PIPE_A));
3039
3040 pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
3041 PIPE_CRC_DONE_INTERRUPT_STATUS;
3042
3043 i915_enable_pipestat(dev_priv, PIPE_A, pipestat_mask |
3044 PIPE_GMBUS_INTERRUPT_STATUS);
3045 i915_enable_pipestat(dev_priv, PIPE_B, pipestat_mask);
3046
3047 iir_mask = I915_DISPLAY_PORT_INTERRUPT |
3048 I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
3049 I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
3050 dev_priv->irq_mask &= ~iir_mask;
3051
3052 I915_WRITE(VLV_IIR, iir_mask);
3053 I915_WRITE(VLV_IIR, iir_mask);
3054 I915_WRITE(VLV_IMR, dev_priv->irq_mask);
3055 I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
3056 POSTING_READ(VLV_IER);
3057}
3058
3059static void valleyview_display_irqs_uninstall(struct drm_i915_private *dev_priv)
3060{
3061 u32 pipestat_mask;
3062 u32 iir_mask;
3063
3064 iir_mask = I915_DISPLAY_PORT_INTERRUPT |
3065 I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
3066 I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
3067
3068 dev_priv->irq_mask |= iir_mask;
3069 I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
3070 I915_WRITE(VLV_IMR, dev_priv->irq_mask);
3071 I915_WRITE(VLV_IIR, iir_mask);
3072 I915_WRITE(VLV_IIR, iir_mask);
3073 POSTING_READ(VLV_IIR);
3074
3075 pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
3076 PIPE_CRC_DONE_INTERRUPT_STATUS;
3077
3078 i915_disable_pipestat(dev_priv, PIPE_A, pipestat_mask |
3079 PIPE_GMBUS_INTERRUPT_STATUS);
3080 i915_disable_pipestat(dev_priv, PIPE_B, pipestat_mask);
3081
3082 pipestat_mask = PIPESTAT_INT_STATUS_MASK |
3083 PIPE_FIFO_UNDERRUN_STATUS;
3084 I915_WRITE(PIPESTAT(PIPE_A), pipestat_mask);
3085 I915_WRITE(PIPESTAT(PIPE_B), pipestat_mask);
3086 POSTING_READ(PIPESTAT(PIPE_A));
3087}
3088
3089void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv)
3090{
3091 assert_spin_locked(&dev_priv->irq_lock);
3092
3093 if (dev_priv->display_irqs_enabled)
3094 return;
3095
3096 dev_priv->display_irqs_enabled = true;
3097
3098 if (dev_priv->dev->irq_enabled)
3099 valleyview_display_irqs_install(dev_priv);
3100}
3101
3102void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv)
3103{
3104 assert_spin_locked(&dev_priv->irq_lock);
3105
3106 if (!dev_priv->display_irqs_enabled)
3107 return;
3108
3109 dev_priv->display_irqs_enabled = false;
3110
3111 if (dev_priv->dev->irq_enabled)
3112 valleyview_display_irqs_uninstall(dev_priv);
3113}
3114
3028static int valleyview_irq_postinstall(struct drm_device *dev) 3115static int valleyview_irq_postinstall(struct drm_device *dev)
3029{ 3116{
3030 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 3117 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
3031 u32 enable_mask;
3032 u32 pipestat_enable = PLANE_FLIP_DONE_INT_STATUS_VLV |
3033 PIPE_CRC_DONE_INTERRUPT_STATUS;
3034 unsigned long irqflags; 3118 unsigned long irqflags;
3035 3119
3036 enable_mask = I915_DISPLAY_PORT_INTERRUPT; 3120 dev_priv->irq_mask = ~0;
3037 enable_mask |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
3038 I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
3039
3040 dev_priv->irq_mask = ~enable_mask;
3041 3121
3042 I915_WRITE(PORT_HOTPLUG_EN, 0); 3122 I915_WRITE(PORT_HOTPLUG_EN, 0);
3043 POSTING_READ(PORT_HOTPLUG_EN); 3123 POSTING_READ(PORT_HOTPLUG_EN);
3044 3124
3045 I915_WRITE(VLV_IMR, dev_priv->irq_mask); 3125 I915_WRITE(VLV_IMR, dev_priv->irq_mask);
3046 I915_WRITE(VLV_IER, enable_mask); 3126 I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
3047 I915_WRITE(VLV_IIR, 0xffffffff); 3127 I915_WRITE(VLV_IIR, 0xffffffff);
3048 I915_WRITE(PIPESTAT(0), 0xffff);
3049 I915_WRITE(PIPESTAT(1), 0xffff);
3050 POSTING_READ(VLV_IER); 3128 POSTING_READ(VLV_IER);
3051 3129
3052 /* Interrupt setup is already guaranteed to be single-threaded, this is 3130 /* Interrupt setup is already guaranteed to be single-threaded, this is
3053 * just to make the assert_spin_locked check happy. */ 3131 * just to make the assert_spin_locked check happy. */
3054 spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 3132 spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
3055 i915_enable_pipestat(dev_priv, PIPE_A, pipestat_enable); 3133 if (dev_priv->display_irqs_enabled)
3056 i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); 3134 valleyview_display_irqs_install(dev_priv);
3057 i915_enable_pipestat(dev_priv, PIPE_B, pipestat_enable);
3058 spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 3135 spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
3059 3136
3060 I915_WRITE(VLV_IIR, 0xffffffff); 3137 I915_WRITE(VLV_IIR, 0xffffffff);
@@ -3185,6 +3262,7 @@ static void gen8_irq_uninstall(struct drm_device *dev)
3185static void valleyview_irq_uninstall(struct drm_device *dev) 3262static void valleyview_irq_uninstall(struct drm_device *dev)
3186{ 3263{
3187 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 3264 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
3265 unsigned long irqflags;
3188 int pipe; 3266 int pipe;
3189 3267
3190 if (!dev_priv) 3268 if (!dev_priv)
@@ -3198,8 +3276,14 @@ static void valleyview_irq_uninstall(struct drm_device *dev)
3198 I915_WRITE(HWSTAM, 0xffffffff); 3276 I915_WRITE(HWSTAM, 0xffffffff);
3199 I915_WRITE(PORT_HOTPLUG_EN, 0); 3277 I915_WRITE(PORT_HOTPLUG_EN, 0);
3200 I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); 3278 I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
3201 for_each_pipe(pipe) 3279
3202 I915_WRITE(PIPESTAT(pipe), 0xffff); 3280 spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
3281 if (dev_priv->display_irqs_enabled)
3282 valleyview_display_irqs_uninstall(dev_priv);
3283 spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
3284
3285 dev_priv->irq_mask = 0;
3286
3203 I915_WRITE(VLV_IIR, 0xffffffff); 3287 I915_WRITE(VLV_IIR, 0xffffffff);
3204 I915_WRITE(VLV_IMR, 0xffffffff); 3288 I915_WRITE(VLV_IMR, 0xffffffff);
3205 I915_WRITE(VLV_IER, 0x0); 3289 I915_WRITE(VLV_IER, 0x0);