diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 83 |
1 files changed, 61 insertions, 22 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2e242270e270..d447d7d508f4 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -2887,21 +2887,39 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) | |||
2887 | return ret; | 2887 | return ret; |
2888 | } | 2888 | } |
2889 | 2889 | ||
2890 | static inline u32 gen8_master_intr_disable(void __iomem * const regs) | ||
2891 | { | ||
2892 | raw_reg_write(regs, GEN8_MASTER_IRQ, 0); | ||
2893 | |||
2894 | /* | ||
2895 | * Now with master disabled, get a sample of level indications | ||
2896 | * for this interrupt. Indications will be cleared on related acks. | ||
2897 | * New indications can and will light up during processing, | ||
2898 | * and will generate new interrupt after enabling master. | ||
2899 | */ | ||
2900 | return raw_reg_read(regs, GEN8_MASTER_IRQ); | ||
2901 | } | ||
2902 | |||
2903 | static inline void gen8_master_intr_enable(void __iomem * const regs) | ||
2904 | { | ||
2905 | raw_reg_write(regs, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); | ||
2906 | } | ||
2907 | |||
2890 | static irqreturn_t gen8_irq_handler(int irq, void *arg) | 2908 | static irqreturn_t gen8_irq_handler(int irq, void *arg) |
2891 | { | 2909 | { |
2892 | struct drm_i915_private *dev_priv = to_i915(arg); | 2910 | struct drm_i915_private *dev_priv = to_i915(arg); |
2911 | void __iomem * const regs = dev_priv->regs; | ||
2893 | u32 master_ctl; | 2912 | u32 master_ctl; |
2894 | u32 gt_iir[4]; | 2913 | u32 gt_iir[4]; |
2895 | 2914 | ||
2896 | if (!intel_irqs_enabled(dev_priv)) | 2915 | if (!intel_irqs_enabled(dev_priv)) |
2897 | return IRQ_NONE; | 2916 | return IRQ_NONE; |
2898 | 2917 | ||
2899 | master_ctl = I915_READ_FW(GEN8_MASTER_IRQ); | 2918 | master_ctl = gen8_master_intr_disable(regs); |
2900 | master_ctl &= ~GEN8_MASTER_IRQ_CONTROL; | 2919 | if (!master_ctl) { |
2901 | if (!master_ctl) | 2920 | gen8_master_intr_enable(regs); |
2902 | return IRQ_NONE; | 2921 | return IRQ_NONE; |
2903 | 2922 | } | |
2904 | I915_WRITE_FW(GEN8_MASTER_IRQ, 0); | ||
2905 | 2923 | ||
2906 | /* Find, clear, then process each source of interrupt */ | 2924 | /* Find, clear, then process each source of interrupt */ |
2907 | gen8_gt_irq_ack(dev_priv, master_ctl, gt_iir); | 2925 | gen8_gt_irq_ack(dev_priv, master_ctl, gt_iir); |
@@ -2913,7 +2931,7 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) | |||
2913 | enable_rpm_wakeref_asserts(dev_priv); | 2931 | enable_rpm_wakeref_asserts(dev_priv); |
2914 | } | 2932 | } |
2915 | 2933 | ||
2916 | I915_WRITE_FW(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); | 2934 | gen8_master_intr_enable(regs); |
2917 | 2935 | ||
2918 | gen8_gt_irq_handler(dev_priv, master_ctl, gt_iir); | 2936 | gen8_gt_irq_handler(dev_priv, master_ctl, gt_iir); |
2919 | 2937 | ||
@@ -3111,6 +3129,24 @@ gen11_gu_misc_irq_handler(struct drm_i915_private *dev_priv, const u32 iir) | |||
3111 | intel_opregion_asle_intr(dev_priv); | 3129 | intel_opregion_asle_intr(dev_priv); |
3112 | } | 3130 | } |
3113 | 3131 | ||
3132 | static inline u32 gen11_master_intr_disable(void __iomem * const regs) | ||
3133 | { | ||
3134 | raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, 0); | ||
3135 | |||
3136 | /* | ||
3137 | * Now with master disabled, get a sample of level indications | ||
3138 | * for this interrupt. Indications will be cleared on related acks. | ||
3139 | * New indications can and will light up during processing, | ||
3140 | * and will generate new interrupt after enabling master. | ||
3141 | */ | ||
3142 | return raw_reg_read(regs, GEN11_GFX_MSTR_IRQ); | ||
3143 | } | ||
3144 | |||
3145 | static inline void gen11_master_intr_enable(void __iomem * const regs) | ||
3146 | { | ||
3147 | raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, GEN11_MASTER_IRQ); | ||
3148 | } | ||
3149 | |||
3114 | static irqreturn_t gen11_irq_handler(int irq, void *arg) | 3150 | static irqreturn_t gen11_irq_handler(int irq, void *arg) |
3115 | { | 3151 | { |
3116 | struct drm_i915_private * const i915 = to_i915(arg); | 3152 | struct drm_i915_private * const i915 = to_i915(arg); |
@@ -3121,13 +3157,11 @@ static irqreturn_t gen11_irq_handler(int irq, void *arg) | |||
3121 | if (!intel_irqs_enabled(i915)) | 3157 | if (!intel_irqs_enabled(i915)) |
3122 | return IRQ_NONE; | 3158 | return IRQ_NONE; |
3123 | 3159 | ||
3124 | master_ctl = raw_reg_read(regs, GEN11_GFX_MSTR_IRQ); | 3160 | master_ctl = gen11_master_intr_disable(regs); |
3125 | master_ctl &= ~GEN11_MASTER_IRQ; | 3161 | if (!master_ctl) { |
3126 | if (!master_ctl) | 3162 | gen11_master_intr_enable(regs); |
3127 | return IRQ_NONE; | 3163 | return IRQ_NONE; |
3128 | 3164 | } | |
3129 | /* Disable interrupts. */ | ||
3130 | raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, 0); | ||
3131 | 3165 | ||
3132 | /* Find, clear, then process each source of interrupt. */ | 3166 | /* Find, clear, then process each source of interrupt. */ |
3133 | gen11_gt_irq_handler(i915, master_ctl); | 3167 | gen11_gt_irq_handler(i915, master_ctl); |
@@ -3147,8 +3181,7 @@ static irqreturn_t gen11_irq_handler(int irq, void *arg) | |||
3147 | 3181 | ||
3148 | gu_misc_iir = gen11_gu_misc_irq_ack(i915, master_ctl); | 3182 | gu_misc_iir = gen11_gu_misc_irq_ack(i915, master_ctl); |
3149 | 3183 | ||
3150 | /* Acknowledge and enable interrupts. */ | 3184 | gen11_master_intr_enable(regs); |
3151 | raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, GEN11_MASTER_IRQ | master_ctl); | ||
3152 | 3185 | ||
3153 | gen11_gu_misc_irq_handler(i915, gu_misc_iir); | 3186 | gen11_gu_misc_irq_handler(i915, gu_misc_iir); |
3154 | 3187 | ||
@@ -3598,8 +3631,7 @@ static void gen8_irq_reset(struct drm_device *dev) | |||
3598 | struct drm_i915_private *dev_priv = to_i915(dev); | 3631 | struct drm_i915_private *dev_priv = to_i915(dev); |
3599 | int pipe; | 3632 | int pipe; |
3600 | 3633 | ||
3601 | I915_WRITE(GEN8_MASTER_IRQ, 0); | 3634 | gen8_master_intr_disable(dev_priv->regs); |
3602 | POSTING_READ(GEN8_MASTER_IRQ); | ||
3603 | 3635 | ||
3604 | gen8_gt_irq_reset(dev_priv); | 3636 | gen8_gt_irq_reset(dev_priv); |
3605 | 3637 | ||
@@ -3641,13 +3673,15 @@ static void gen11_irq_reset(struct drm_device *dev) | |||
3641 | struct drm_i915_private *dev_priv = dev->dev_private; | 3673 | struct drm_i915_private *dev_priv = dev->dev_private; |
3642 | int pipe; | 3674 | int pipe; |
3643 | 3675 | ||
3644 | I915_WRITE(GEN11_GFX_MSTR_IRQ, 0); | 3676 | gen11_master_intr_disable(dev_priv->regs); |
3645 | POSTING_READ(GEN11_GFX_MSTR_IRQ); | ||
3646 | 3677 | ||
3647 | gen11_gt_irq_reset(dev_priv); | 3678 | gen11_gt_irq_reset(dev_priv); |
3648 | 3679 | ||
3649 | I915_WRITE(GEN11_DISPLAY_INT_CTL, 0); | 3680 | I915_WRITE(GEN11_DISPLAY_INT_CTL, 0); |
3650 | 3681 | ||
3682 | I915_WRITE(EDP_PSR_IMR, 0xffffffff); | ||
3683 | I915_WRITE(EDP_PSR_IIR, 0xffffffff); | ||
3684 | |||
3651 | for_each_pipe(dev_priv, pipe) | 3685 | for_each_pipe(dev_priv, pipe) |
3652 | if (intel_display_power_is_enabled(dev_priv, | 3686 | if (intel_display_power_is_enabled(dev_priv, |
3653 | POWER_DOMAIN_PIPE(pipe))) | 3687 | POWER_DOMAIN_PIPE(pipe))) |
@@ -4244,8 +4278,7 @@ static int gen8_irq_postinstall(struct drm_device *dev) | |||
4244 | if (HAS_PCH_SPLIT(dev_priv)) | 4278 | if (HAS_PCH_SPLIT(dev_priv)) |
4245 | ibx_irq_postinstall(dev); | 4279 | ibx_irq_postinstall(dev); |
4246 | 4280 | ||
4247 | I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); | 4281 | gen8_master_intr_enable(dev_priv->regs); |
4248 | POSTING_READ(GEN8_MASTER_IRQ); | ||
4249 | 4282 | ||
4250 | return 0; | 4283 | return 0; |
4251 | } | 4284 | } |
@@ -4307,8 +4340,7 @@ static int gen11_irq_postinstall(struct drm_device *dev) | |||
4307 | 4340 | ||
4308 | I915_WRITE(GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE); | 4341 | I915_WRITE(GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE); |
4309 | 4342 | ||
4310 | I915_WRITE(GEN11_GFX_MSTR_IRQ, GEN11_MASTER_IRQ); | 4343 | gen11_master_intr_enable(dev_priv->regs); |
4311 | POSTING_READ(GEN11_GFX_MSTR_IRQ); | ||
4312 | 4344 | ||
4313 | return 0; | 4345 | return 0; |
4314 | } | 4346 | } |
@@ -4834,6 +4866,13 @@ void intel_irq_init(struct drm_i915_private *dev_priv) | |||
4834 | dev_priv->display_irqs_enabled = false; | 4866 | dev_priv->display_irqs_enabled = false; |
4835 | 4867 | ||
4836 | dev_priv->hotplug.hpd_storm_threshold = HPD_STORM_DEFAULT_THRESHOLD; | 4868 | dev_priv->hotplug.hpd_storm_threshold = HPD_STORM_DEFAULT_THRESHOLD; |
4869 | /* If we have MST support, we want to avoid doing short HPD IRQ storm | ||
4870 | * detection, as short HPD storms will occur as a natural part of | ||
4871 | * sideband messaging with MST. | ||
4872 | * On older platforms however, IRQ storms can occur with both long and | ||
4873 | * short pulses, as seen on some G4x systems. | ||
4874 | */ | ||
4875 | dev_priv->hotplug.hpd_short_storm_enabled = !HAS_DP_MST(dev_priv); | ||
4837 | 4876 | ||
4838 | dev->driver->get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos; | 4877 | dev->driver->get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos; |
4839 | dev->driver->get_scanout_position = i915_get_crtc_scanoutpos; | 4878 | dev->driver->get_scanout_position = i915_get_crtc_scanoutpos; |