drm/i915: Add atomic_get_property entrypoint for connectors (v2)
[deliverable/linux.git] / drivers / gpu / drm / i915 / i915_irq.c
index 996c2931c49945d86a595c6f38104c475fc32f1b..2399eaed2ca370f6cc276ce28f50adefb59f9f7d 100644 (file)
@@ -45,7 +45,7 @@
  * and related files, but that will be described in separate chapters.
  */
 
-static const u32 hpd_ibx[] = {
+static const u32 hpd_ibx[HPD_NUM_PINS] = {
        [HPD_CRT] = SDE_CRT_HOTPLUG,
        [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG,
        [HPD_PORT_B] = SDE_PORTB_HOTPLUG,
@@ -53,7 +53,7 @@ static const u32 hpd_ibx[] = {
        [HPD_PORT_D] = SDE_PORTD_HOTPLUG
 };
 
-static const u32 hpd_cpt[] = {
+static const u32 hpd_cpt[HPD_NUM_PINS] = {
        [HPD_CRT] = SDE_CRT_HOTPLUG_CPT,
        [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG_CPT,
        [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT,
@@ -61,7 +61,7 @@ static const u32 hpd_cpt[] = {
        [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT
 };
 
-static const u32 hpd_mask_i915[] = {
+static const u32 hpd_mask_i915[HPD_NUM_PINS] = {
        [HPD_CRT] = CRT_HOTPLUG_INT_EN,
        [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN,
        [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_EN,
@@ -70,7 +70,7 @@ static const u32 hpd_mask_i915[] = {
        [HPD_PORT_D] = PORTD_HOTPLUG_INT_EN
 };
 
-static const u32 hpd_status_g4x[] = {
+static const u32 hpd_status_g4x[HPD_NUM_PINS] = {
        [HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
        [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_G4X,
        [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_G4X,
@@ -79,7 +79,7 @@ static const u32 hpd_status_g4x[] = {
        [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS
 };
 
-static const u32 hpd_status_i915[] = { /* i915 and valleyview are the same */
+static const u32 hpd_status_i915[HPD_NUM_PINS] = { /* i915 and valleyview are the same */
        [HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
        [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I915,
        [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I915,
@@ -183,6 +183,8 @@ static void ilk_update_gt_irq(struct drm_i915_private *dev_priv,
 {
        assert_spin_locked(&dev_priv->irq_lock);
 
+       WARN_ON(enabled_irq_mask & ~interrupt_mask);
+
        if (WARN_ON(!intel_irqs_enabled(dev_priv)))
                return;
 
@@ -229,6 +231,8 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv,
 {
        uint32_t new_val;
 
+       WARN_ON(enabled_irq_mask & ~interrupt_mask);
+
        assert_spin_locked(&dev_priv->irq_lock);
 
        new_val = dev_priv->pm_irq_mask;
@@ -292,6 +296,23 @@ void gen6_enable_rps_interrupts(struct drm_device *dev)
        spin_unlock_irq(&dev_priv->irq_lock);
 }
 
+u32 gen6_sanitize_rps_pm_mask(struct drm_i915_private *dev_priv, u32 mask)
+{
+       /*
+        * SNB,IVB can while VLV,CHV may hard hang on looping batchbuffer
+        * if GEN6_PM_UP_EI_EXPIRED is masked.
+        *
+        * TODO: verify if this can be reproduced on VLV,CHV.
+        */
+       if (INTEL_INFO(dev_priv)->gen <= 7 && !IS_HASWELL(dev_priv))
+               mask &= ~GEN6_PM_RP_UP_EI_EXPIRED;
+
+       if (INTEL_INFO(dev_priv)->gen >= 8)
+               mask &= ~GEN8_PMINTR_REDIRECT_TO_NON_DISP;
+
+       return mask;
+}
+
 void gen6_disable_rps_interrupts(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -304,8 +325,7 @@ void gen6_disable_rps_interrupts(struct drm_device *dev)
 
        spin_lock_irq(&dev_priv->irq_lock);
 
-       I915_WRITE(GEN6_PMINTRMSK, INTEL_INFO(dev_priv)->gen >= 8 ?
-                  ~GEN8_PMINTR_REDIRECT_TO_NON_DISP : ~0);
+       I915_WRITE(GEN6_PMINTRMSK, gen6_sanitize_rps_pm_mask(dev_priv, ~0));
 
        __gen6_disable_pm_irq(dev_priv, dev_priv->pm_rps_events);
        I915_WRITE(gen6_pm_ier(dev_priv), I915_READ(gen6_pm_ier(dev_priv)) &
@@ -332,6 +352,8 @@ void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
        sdeimr &= ~interrupt_mask;
        sdeimr |= (~enabled_irq_mask & interrupt_mask);
 
+       WARN_ON(enabled_irq_mask & ~interrupt_mask);
+
        assert_spin_locked(&dev_priv->irq_lock);
 
        if (WARN_ON(!intel_irqs_enabled(dev_priv)))
@@ -571,7 +593,7 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
                struct intel_crtc *intel_crtc =
                        to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
                const struct drm_display_mode *mode =
-                       &intel_crtc->config.adjusted_mode;
+                       &intel_crtc->config->base.adjusted_mode;
 
                htotal = mode->crtc_htotal;
                hsync_start = mode->crtc_hsync_start;
@@ -642,7 +664,7 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       const struct drm_display_mode *mode = &crtc->config.adjusted_mode;
+       const struct drm_display_mode *mode = &crtc->config->base.adjusted_mode;
        enum pipe pipe = crtc->pipe;
        int position, vtotal;
 
@@ -669,7 +691,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       const struct drm_display_mode *mode = &intel_crtc->config.adjusted_mode;
+       const struct drm_display_mode *mode = &intel_crtc->config->base.adjusted_mode;
        int position;
        int vbl_start, vbl_end, hsync_start, htotal, vtotal;
        bool in_vbl = true;
@@ -827,7 +849,7 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe,
        return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error,
                                                     vblank_time, flags,
                                                     crtc,
-                                                    &to_intel_crtc(crtc)->config.adjusted_mode);
+                                                    &to_intel_crtc(crtc)->config->base.adjusted_mode);
 }
 
 static bool intel_hpd_irq_event(struct drm_device *dev,
@@ -857,7 +879,7 @@ static void i915_digport_work_func(struct work_struct *work)
                container_of(work, struct drm_i915_private, dig_port_work);
        u32 long_port_mask, short_port_mask;
        struct intel_digital_port *intel_dig_port;
-       int i, ret;
+       int i;
        u32 old_bits = 0;
 
        spin_lock_irq(&dev_priv->irq_lock);
@@ -881,9 +903,11 @@ static void i915_digport_work_func(struct work_struct *work)
                        valid = true;
 
                if (valid) {
+                       enum irqreturn ret;
+
                        ret = intel_dig_port->hpd_pulse(intel_dig_port, long_hpd);
-                       if (ret == true) {
-                               /* if we get true fallback to old school hpd */
+                       if (ret == IRQ_NONE) {
+                               /* fall back to old school hpd */
                                old_bits |= (1 << intel_dig_port->base.hpd_pin);
                        }
                }
@@ -1017,7 +1041,7 @@ static void notify_ring(struct drm_device *dev,
        if (!intel_ring_initialized(ring))
                return;
 
-       trace_i915_gem_request_complete(ring);
+       trace_i915_gem_request_notify(ring);
 
        wake_up_all(&ring->irq_queue);
 }
@@ -1383,14 +1407,14 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
                        if (rcs & GT_RENDER_USER_INTERRUPT)
                                notify_ring(dev, ring);
                        if (rcs & GT_CONTEXT_SWITCH_INTERRUPT)
-                               intel_execlists_handle_ctx_events(ring);
+                               intel_lrc_irq_handler(ring);
 
                        bcs = tmp >> GEN8_BCS_IRQ_SHIFT;
                        ring = &dev_priv->ring[BCS];
                        if (bcs & GT_RENDER_USER_INTERRUPT)
                                notify_ring(dev, ring);
                        if (bcs & GT_CONTEXT_SWITCH_INTERRUPT)
-                               intel_execlists_handle_ctx_events(ring);
+                               intel_lrc_irq_handler(ring);
                } else
                        DRM_ERROR("The master control interrupt lied (GT0)!\n");
        }
@@ -1406,14 +1430,14 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
                        if (vcs & GT_RENDER_USER_INTERRUPT)
                                notify_ring(dev, ring);
                        if (vcs & GT_CONTEXT_SWITCH_INTERRUPT)
-                               intel_execlists_handle_ctx_events(ring);
+                               intel_lrc_irq_handler(ring);
 
                        vcs = tmp >> GEN8_VCS2_IRQ_SHIFT;
                        ring = &dev_priv->ring[VCS2];
                        if (vcs & GT_RENDER_USER_INTERRUPT)
                                notify_ring(dev, ring);
                        if (vcs & GT_CONTEXT_SWITCH_INTERRUPT)
-                               intel_execlists_handle_ctx_events(ring);
+                               intel_lrc_irq_handler(ring);
                } else
                        DRM_ERROR("The master control interrupt lied (GT1)!\n");
        }
@@ -1440,7 +1464,7 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
                        if (vcs & GT_RENDER_USER_INTERRUPT)
                                notify_ring(dev, ring);
                        if (vcs & GT_CONTEXT_SWITCH_INTERRUPT)
-                               intel_execlists_handle_ctx_events(ring);
+                               intel_lrc_irq_handler(ring);
                } else
                        DRM_ERROR("The master control interrupt lied (GT3)!\n");
        }
@@ -1500,7 +1524,7 @@ static inline enum port get_port_from_pin(enum hpd_pin pin)
 static inline void intel_hpd_irq_handler(struct drm_device *dev,
                                         u32 hotplug_trigger,
                                         u32 dig_hotplug_reg,
-                                        const u32 *hpd)
+                                        const u32 hpd[HPD_NUM_PINS])
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        int i;
@@ -2753,18 +2777,18 @@ static void gen8_disable_vblank(struct drm_device *dev, int pipe)
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
-static u32
-ring_last_seqno(struct intel_engine_cs *ring)
+static struct drm_i915_gem_request *
+ring_last_request(struct intel_engine_cs *ring)
 {
        return list_entry(ring->request_list.prev,
-                         struct drm_i915_gem_request, list)->seqno;
+                         struct drm_i915_gem_request, list);
 }
 
 static bool
-ring_idle(struct intel_engine_cs *ring, u32 seqno)
+ring_idle(struct intel_engine_cs *ring)
 {
        return (list_empty(&ring->request_list) ||
-               i915_seqno_passed(seqno, ring_last_seqno(ring)));
+               i915_gem_request_completed(ring_last_request(ring), false));
 }
 
 static bool
@@ -2984,7 +3008,7 @@ static void i915_hangcheck_elapsed(unsigned long data)
                acthd = intel_ring_get_active_head(ring);
 
                if (ring->hangcheck.seqno == seqno) {
-                       if (ring_idle(ring, seqno)) {
+                       if (ring_idle(ring)) {
                                ring->hangcheck.action = HANGCHECK_IDLE;
 
                                if (waitqueue_active(&ring->irq_queue)) {
@@ -3725,8 +3749,6 @@ static bool i8xx_handle_vblank(struct drm_device *dev,
        if ((iir & flip_pending) == 0)
                goto check_page_flip;
 
-       intel_prepare_page_flip(dev, plane);
-
        /* We detect FlipDone by looking for the change in PendingFlip from '1'
         * to '0' on the following vblank, i.e. IIR has the Pendingflip
         * asserted following the MI_DISPLAY_FLIP, but ISR is deasserted, hence
@@ -3736,6 +3758,7 @@ static bool i8xx_handle_vblank(struct drm_device *dev,
        if (I915_READ16(ISR) & flip_pending)
                goto check_page_flip;
 
+       intel_prepare_page_flip(dev, plane);
        intel_finish_page_flip(dev, pipe);
        return true;
 
@@ -3907,8 +3930,6 @@ static bool i915_handle_vblank(struct drm_device *dev,
        if ((iir & flip_pending) == 0)
                goto check_page_flip;
 
-       intel_prepare_page_flip(dev, plane);
-
        /* We detect FlipDone by looking for the change in PendingFlip from '1'
         * to '0' on the following vblank, i.e. IIR has the Pendingflip
         * asserted following the MI_DISPLAY_FLIP, but ISR is deasserted, hence
@@ -3918,6 +3939,7 @@ static bool i915_handle_vblank(struct drm_device *dev,
        if (I915_READ(ISR) & flip_pending)
                goto check_page_flip;
 
+       intel_prepare_page_flip(dev, plane);
        intel_finish_page_flip(dev, pipe);
        return true;
 
@@ -4125,26 +4147,24 @@ static void i915_hpd_irq_setup(struct drm_device *dev)
 
        assert_spin_locked(&dev_priv->irq_lock);
 
-       if (I915_HAS_HOTPLUG(dev)) {
-               hotplug_en = I915_READ(PORT_HOTPLUG_EN);
-               hotplug_en &= ~HOTPLUG_INT_EN_MASK;
-               /* Note HDMI and DP share hotplug bits */
-               /* enable bits are the same for all generations */
-               for_each_intel_encoder(dev, intel_encoder)
-                       if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
-                               hotplug_en |= hpd_mask_i915[intel_encoder->hpd_pin];
-               /* Programming the CRT detection parameters tends
-                  to generate a spurious hotplug event about three
-                  seconds later.  So just do it once.
-               */
-               if (IS_G4X(dev))
-                       hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
-               hotplug_en &= ~CRT_HOTPLUG_VOLTAGE_COMPARE_MASK;
-               hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
-
-               /* Ignore TV since it's buggy */
-               I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
-       }
+       hotplug_en = I915_READ(PORT_HOTPLUG_EN);
+       hotplug_en &= ~HOTPLUG_INT_EN_MASK;
+       /* Note HDMI and DP share hotplug bits */
+       /* enable bits are the same for all generations */
+       for_each_intel_encoder(dev, intel_encoder)
+               if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
+                       hotplug_en |= hpd_mask_i915[intel_encoder->hpd_pin];
+       /* Programming the CRT detection parameters tends
+          to generate a spurious hotplug event about three
+          seconds later.  So just do it once.
+       */
+       if (IS_G4X(dev))
+               hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
+       hotplug_en &= ~CRT_HOTPLUG_VOLTAGE_COMPARE_MASK;
+       hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
+
+       /* Ignore TV since it's buggy */
+       I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
 }
 
 static irqreturn_t i965_irq_handler(int irq, void *arg)
@@ -4408,14 +4428,14 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
                        dev->driver->irq_postinstall = i915_irq_postinstall;
                        dev->driver->irq_uninstall = i915_irq_uninstall;
                        dev->driver->irq_handler = i915_irq_handler;
-                       dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
                } else {
                        dev->driver->irq_preinstall = i965_irq_preinstall;
                        dev->driver->irq_postinstall = i965_irq_postinstall;
                        dev->driver->irq_uninstall = i965_irq_uninstall;
                        dev->driver->irq_handler = i965_irq_handler;
-                       dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
                }
+               if (I915_HAS_HOTPLUG(dev_priv))
+                       dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
                dev->driver->enable_vblank = i915_enable_vblank;
                dev->driver->disable_vblank = i915_disable_vblank;
        }
This page took 0.031686 seconds and 5 git commands to generate.