diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 116 |
1 files changed, 100 insertions, 16 deletions
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 | ||
3028 | static 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 | |||
3059 | static 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 | |||
3089 | void 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 | |||
3102 | void 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 | |||
3028 | static int valleyview_irq_postinstall(struct drm_device *dev) | 3115 | static 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) | |||
3185 | static void valleyview_irq_uninstall(struct drm_device *dev) | 3262 | static 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); |