diff --git a/packages/linux/patches/3.15-rc2/linux-997-03-drm-radeon-more-pll-bits-more-logging.patch b/packages/linux/patches/3.15-rc2/linux-997-03-drm-radeon-more-pll-bits-more-logging.patch deleted file mode 100644 index b577238b23..0000000000 --- a/packages/linux/patches/3.15-rc2/linux-997-03-drm-radeon-more-pll-bits-more-logging.patch +++ /dev/null @@ -1,57 +0,0 @@ -Signed-off-by: Christian König ---- -diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c -index fb3b505..037db45 100644 ---- a/drivers/gpu/drm/radeon/radeon_display.c -+++ b/drivers/gpu/drm/radeon/radeon_display.c -@@ -820,6 +820,9 @@ static void avivo_reduce_ratio(unsigned *nom, unsigned *den, - { - unsigned tmp; - -+ DRM_DEBUG_KMS("nom: %d den: %d nom_min %d den_min %d\n", -+ *nom, *den, nom_min, den_min); -+ - /* reduce the numbers to a simpler ratio */ - tmp = gcd(*nom, *den); - *nom /= tmp; -@@ -876,6 +879,9 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, - fb_div_max *= 10; - } - -+ DRM_DEBUG_KMS("fb_div_min: %d fb_div_max: %d\n", -+ fb_div_min, fb_div_max); -+ - /* determine allowed ref divider range */ - if (pll->flags & RADEON_PLL_USE_REF_DIV) - ref_div_min = pll->reference_div; -@@ -883,6 +889,9 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, - ref_div_min = pll->min_ref_div; - ref_div_max = pll->max_ref_div; - -+ DRM_DEBUG_KMS("ref_div_min: %d ref_div_max: %d\n", -+ ref_div_min, ref_div_max); -+ - /* determine allowed post divider range */ - if (pll->flags & RADEON_PLL_USE_POST_DIV) { - post_div_min = pll->post_div; -@@ -912,6 +921,9 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, - post_div_max = pll->max_post_div; - } - -+ DRM_DEBUG_KMS("post_div_min: %d post_div_max: %d\n", -+ post_div_min, post_div_max); -+ - /* represent the searched ratio as fractional number */ - nom = pll->flags & RADEON_PLL_USE_FRAC_FB_DIV ? freq : freq / 10; - den = pll->reference_freq; -@@ -980,7 +992,7 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, - *post_div_p = post_div; - - DRM_DEBUG_KMS("%d - %d, pll dividers - fb: %d.%d ref: %d, post %d\n", -- freq, *dot_clock_p, *fb_div_p, *frac_fb_div_p, -+ freq, *dot_clock_p * 10, *fb_div_p, *frac_fb_div_p, - ref_div, post_div); - } - --- -cgit v0.9.0.2-2-gbebe diff --git a/packages/linux/patches/3.15-rc2/linux-997-drm-radeon-rework-finding-display-PLL-numbers-fix-range.patch b/packages/linux/patches/3.15-rc2/linux-997-drm-radeon-rework-finding-display-PLL-numbers-fix-range.patch deleted file mode 100644 index a12ae3d7aa..0000000000 --- a/packages/linux/patches/3.15-rc2/linux-997-drm-radeon-rework-finding-display-PLL-numbers-fix-range.patch +++ /dev/null @@ -1,27 +0,0 @@ -From: Christian König - -Letting post and refernce divider get to big is bad for signal stability. - -v2: increase the limit to 210 - -Signed-off-by: Christian König ---- - drivers/gpu/drm/radeon/radeon_display.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c -index 386cfa4..2f42912 100644 ---- a/drivers/gpu/drm/radeon/radeon_display.c -+++ b/drivers/gpu/drm/radeon/radeon_display.c -@@ -937,6 +937,9 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, - } - post_div = post_div_best; - -+ /* limit reference * post divider to a maximum */ -+ ref_div_max = min(210 / post_div, ref_div_max); -+ - /* get matching reference and feedback divider */ - ref_div = max(den / post_div, 1u); - fb_div = nom; --- -1.9.1 diff --git a/packages/linux/patches/3.15-rc2/linux-999.03-drm-radeon-PLL-fixes.patch b/packages/linux/patches/3.15-rc2/linux-999.03-drm-radeon-PLL-fixes.patch new file mode 100644 index 0000000000..f3573213e6 --- /dev/null +++ b/packages/linux/patches/3.15-rc2/linux-999.03-drm-radeon-PLL-fixes.patch @@ -0,0 +1,570 @@ +From 514738e09ec3ec0d1fb15cc3eabe4698b0d51358 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20K=C3=B6nig?= +Date: Fri, 4 Apr 2014 13:45:42 +0200 +Subject: [PATCH 2/6] drm/radeon: apply more strict limits for PLL params v2 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Letting post and refernce divider get to big is bad for signal stability. + +v2: increase the limit to 210 + +Signed-off-by: Christian König +--- + drivers/gpu/drm/radeon/radeon_display.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c +index 4e83ffd..35129ad 100644 +--- a/drivers/gpu/drm/radeon/radeon_display.c ++++ b/drivers/gpu/drm/radeon/radeon_display.c +@@ -936,6 +936,9 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, + } + post_div = post_div_best; + ++ /* limit reference * post divider to a maximum */ ++ ref_div_max = min(210 / post_div, ref_div_max); ++ + /* get matching reference and feedback divider */ + ref_div = max(den / post_div, 1u); + fb_div = nom; +-- +1.9.1 + +From 537669e14063df59dd0b1004382842e278e19aa2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20K=C3=B6nig?= +Date: Sat, 19 Apr 2014 18:57:14 +0200 +Subject: [PATCH 4/6] drm/radeon: use fixed PPL ref divider if needed +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Christian König +--- + drivers/gpu/drm/radeon/radeon_display.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c +index 00f63d28..0c26b3c 100644 +--- a/drivers/gpu/drm/radeon/radeon_display.c ++++ b/drivers/gpu/drm/radeon/radeon_display.c +@@ -880,7 +880,12 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, + ref_div_min = pll->reference_div; + else + ref_div_min = pll->min_ref_div; +- ref_div_max = pll->max_ref_div; ++ ++ if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV && ++ pll->flags & RADEON_PLL_USE_REF_DIV) ++ ref_div_max = pll->reference_div; ++ else ++ ref_div_max = pll->max_ref_div; + + /* determine allowed post divider range */ + if (pll->flags & RADEON_PLL_USE_POST_DIV) { +-- +1.9.1 + +From 09535920958a819e90f0178e9d6831dba0577aa0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20K=C3=B6nig?= +Date: Sun, 20 Apr 2014 13:24:32 +0200 +Subject: [PATCH 5/6] drm/radeon: improve PLL limit handling in post div + calculation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This improves the PLL parameters when we work at +the limits of the allowed ranges. + +Signed-off-by: Christian König +--- + drivers/gpu/drm/radeon/radeon_display.c | 77 ++++++++++++++++++++++----------- + 1 file changed, 51 insertions(+), 26 deletions(-) + +diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c +index 0c26b3c..12a01e9 100644 +--- a/drivers/gpu/drm/radeon/radeon_display.c ++++ b/drivers/gpu/drm/radeon/radeon_display.c +@@ -840,6 +840,38 @@ static void avivo_reduce_ratio(unsigned *nom, unsigned *den, + } + + /** ++ * avivo_get_fb_ref_div - feedback and ref divider calculation ++ * ++ * @nom: nominator ++ * @den: denominator ++ * @post_div: post divider ++ * @fb_div_max: feedback divider maximum ++ * @ref_div_max: reference divider maximum ++ * @fb_div: resulting feedback divider ++ * @ref_div: resulting reference divider ++ * ++ * Calculate feedback and reference divider for a given post divider. Makes ++ * sure we stay within the limits. ++ */ ++static void avivo_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_div, ++ unsigned fb_div_max, unsigned ref_div_max, ++ unsigned *fb_div, unsigned *ref_div) ++{ ++ /* limit reference * post divider to a maximum */ ++ ref_div_max = min(210 / post_div, ref_div_max); ++ ++ /* get matching reference and feedback divider */ ++ *ref_div = min(max(DIV_ROUND_CLOSEST(den, post_div), 1u), ref_div_max); ++ *fb_div = DIV_ROUND_CLOSEST(nom * *ref_div * post_div, den); ++ ++ /* limit fb divider to its maximum */ ++ if (*fb_div > fb_div_max) { ++ *ref_div = DIV_ROUND_CLOSEST(*ref_div * fb_div_max, *fb_div); ++ *fb_div = fb_div_max; ++ } ++} ++ ++/** + * radeon_compute_pll_avivo - compute PLL paramaters + * + * @pll: information about the PLL +@@ -860,6 +892,9 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, + u32 *ref_div_p, + u32 *post_div_p) + { ++ unsigned target_clock = pll->flags & RADEON_PLL_USE_FRAC_FB_DIV ? ++ freq : freq / 10; ++ + unsigned fb_div_min, fb_div_max, fb_div; + unsigned post_div_min, post_div_max, post_div; + unsigned ref_div_min, ref_div_max, ref_div; +@@ -892,7 +927,6 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, + post_div_min = pll->post_div; + post_div_max = pll->post_div; + } else { +- unsigned target_clock = freq / 10; + unsigned vco_min, vco_max; + + if (pll->flags & RADEON_PLL_IS_LCD) { +@@ -903,6 +937,11 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, + vco_max = pll->pll_out_max; + } + ++ if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) { ++ vco_min *= 10; ++ vco_max *= 10; ++ } ++ + post_div_min = vco_min / target_clock; + if ((target_clock * post_div_min) < vco_min) + ++post_div_min; +@@ -917,7 +956,7 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, + } + + /* represent the searched ratio as fractional number */ +- nom = pll->flags & RADEON_PLL_USE_FRAC_FB_DIV ? freq : freq / 10; ++ nom = target_clock; + den = pll->reference_freq; + + /* reduce the numbers to a simpler ratio */ +@@ -931,7 +970,12 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, + diff_best = ~0; + + for (post_div = post_div_min; post_div <= post_div_max; ++post_div) { +- unsigned diff = abs(den - den / post_div * post_div); ++ unsigned diff; ++ avivo_get_fb_ref_div(nom, den, post_div, fb_div_max, ++ ref_div_max, &fb_div, &ref_div); ++ diff = abs(target_clock - (pll->reference_freq * fb_div) / ++ (ref_div * post_div)); ++ + if (diff < diff_best || (diff == diff_best && + !(pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP))) { + +@@ -941,28 +985,9 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, + } + post_div = post_div_best; + +- /* limit reference * post divider to a maximum */ +- ref_div_max = min(210 / post_div, ref_div_max); +- +- /* get matching reference and feedback divider */ +- ref_div = max(DIV_ROUND_CLOSEST(den, post_div), 1u); +- fb_div = DIV_ROUND_CLOSEST(nom * ref_div * post_div, den); +- +- /* we're almost done, but reference and feedback +- divider might be to large now */ +- +- nom = fb_div; +- den = ref_div; +- +- if (fb_div > fb_div_max) { +- ref_div = DIV_ROUND_CLOSEST(den * fb_div_max, nom); +- fb_div = fb_div_max; +- } +- +- if (ref_div > ref_div_max) { +- ref_div = ref_div_max; +- fb_div = DIV_ROUND_CLOSEST(nom * ref_div_max, den); +- } ++ /* get the feedback and reference divider for the optimal value */ ++ avivo_get_fb_ref_div(nom, den, post_div, fb_div_max, ref_div_max, ++ &fb_div, &ref_div); + + /* reduce the numbers to a simpler ratio once more */ + /* this also makes sure that the reference divider is large enough */ +@@ -984,7 +1009,7 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, + *post_div_p = post_div; + + DRM_DEBUG_KMS("%d - %d, pll dividers - fb: %d.%d ref: %d, post %d\n", +- freq, *dot_clock_p, *fb_div_p, *frac_fb_div_p, ++ freq, *dot_clock_p * 10, *fb_div_p, *frac_fb_div_p, + ref_div, post_div); + } + +-- +1.9.1 + +From 6e26c28955078c20a78a41e03911d67b5f85bd55 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20K=C3=B6nig?= +Date: Wed, 23 Apr 2014 20:46:06 +0200 +Subject: [PATCH 6/6] drm/radeon: use pflip irq on R600+ +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Christian König +--- + drivers/gpu/drm/radeon/cik.c | 76 +++++++++++++++++++++++++++++++++ + drivers/gpu/drm/radeon/cikd.h | 9 ++++ + drivers/gpu/drm/radeon/evergreen.c | 28 +++++++++--- + drivers/gpu/drm/radeon/r600.c | 10 +++-- + drivers/gpu/drm/radeon/radeon.h | 6 +++ + drivers/gpu/drm/radeon/radeon_display.c | 4 ++ + drivers/gpu/drm/radeon/si.c | 28 +++++++++--- + 7 files changed, 144 insertions(+), 17 deletions(-) + +diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c +index bbb1784..e29c9b2 100644 +--- a/drivers/gpu/drm/radeon/cik.c ++++ b/drivers/gpu/drm/radeon/cik.c +@@ -6662,6 +6662,19 @@ static void cik_disable_interrupt_state(struct radeon_device *rdev) + WREG32(LB_INTERRUPT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); + WREG32(LB_INTERRUPT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + } ++ /* pflip */ ++ if (rdev->num_crtc >= 2) { ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); ++ } ++ if (rdev->num_crtc >= 4) { ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); ++ } ++ if (rdev->num_crtc >= 6) { ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); ++ } + + /* dac hotplug */ + WREG32(DAC_AUTODETECT_INT_CONTROL, 0); +@@ -7018,6 +7031,25 @@ int cik_irq_set(struct radeon_device *rdev) + WREG32(LB_INTERRUPT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6); + } + ++ if (rdev->num_crtc >= 2) { ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_MASK); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_MASK); ++ } ++ if (rdev->num_crtc >= 4) { ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_MASK); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_MASK); ++ } ++ if (rdev->num_crtc >= 6) { ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_MASK); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_MASK); ++ } ++ + WREG32(DC_HPD1_INT_CONTROL, hpd1); + WREG32(DC_HPD2_INT_CONTROL, hpd2); + WREG32(DC_HPD3_INT_CONTROL, hpd3); +@@ -7054,6 +7086,29 @@ static inline void cik_irq_ack(struct radeon_device *rdev) + rdev->irq.stat_regs.cik.disp_int_cont5 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE5); + rdev->irq.stat_regs.cik.disp_int_cont6 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE6); + ++ rdev->irq.stat_regs.cik.d1grph_int = RREG32(GRPH_INT_STATUS + ++ EVERGREEN_CRTC0_REGISTER_OFFSET); ++ rdev->irq.stat_regs.cik.d2grph_int = RREG32(GRPH_INT_STATUS + ++ EVERGREEN_CRTC1_REGISTER_OFFSET); ++ if (rdev->num_crtc >= 4) { ++ rdev->irq.stat_regs.cik.d3grph_int = RREG32(GRPH_INT_STATUS + ++ EVERGREEN_CRTC2_REGISTER_OFFSET); ++ rdev->irq.stat_regs.cik.d4grph_int = RREG32(GRPH_INT_STATUS + ++ EVERGREEN_CRTC3_REGISTER_OFFSET); ++ } ++ if (rdev->num_crtc >= 6) { ++ rdev->irq.stat_regs.cik.d5grph_int = RREG32(GRPH_INT_STATUS + ++ EVERGREEN_CRTC4_REGISTER_OFFSET); ++ rdev->irq.stat_regs.cik.d6grph_int = RREG32(GRPH_INT_STATUS + ++ EVERGREEN_CRTC5_REGISTER_OFFSET); ++ } ++ ++ if (rdev->irq.stat_regs.cik.d1grph_int & GRPH_PFLIP_INT_OCCURRED) ++ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_CLEAR); ++ if (rdev->irq.stat_regs.cik.d2grph_int & GRPH_PFLIP_INT_OCCURRED) ++ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VBLANK_INTERRUPT) + WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK); + if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VLINE_INTERRUPT) +@@ -7064,6 +7119,12 @@ static inline void cik_irq_ack(struct radeon_device *rdev) + WREG32(LB_VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK); + + if (rdev->num_crtc >= 4) { ++ if (rdev->irq.stat_regs.cik.d3grph_int & GRPH_PFLIP_INT_OCCURRED) ++ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_CLEAR); ++ if (rdev->irq.stat_regs.cik.d4grph_int & GRPH_PFLIP_INT_OCCURRED) ++ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) + WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK); + if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) +@@ -7075,6 +7136,12 @@ static inline void cik_irq_ack(struct radeon_device *rdev) + } + + if (rdev->num_crtc >= 6) { ++ if (rdev->irq.stat_regs.cik.d5grph_int & GRPH_PFLIP_INT_OCCURRED) ++ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_CLEAR); ++ if (rdev->irq.stat_regs.cik.d6grph_int & GRPH_PFLIP_INT_OCCURRED) ++ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) + WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK); + if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) +@@ -7426,6 +7493,15 @@ restart_ih: + break; + } + break; ++ case 8: /* D1 page flip */ ++ case 9: /* D2 page flip */ ++ case 10: /* D3 page flip */ ++ case 11: /* D4 page flip */ ++ case 12: /* D5 page flip */ ++ case 13: /* D6 page flip */ ++ DRM_DEBUG("IH: D%d flip\n", src_id - 7); ++ radeon_crtc_handle_flip(rdev, src_id - 8); ++ break; + case 42: /* HPD hotplug */ + switch (src_data) { + case 0: +diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h +index 98bae9d7..d1b2c71 100644 +--- a/drivers/gpu/drm/radeon/cikd.h ++++ b/drivers/gpu/drm/radeon/cikd.h +@@ -882,6 +882,15 @@ + # define DC_HPD6_RX_INTERRUPT (1 << 18) + #define DISP_INTERRUPT_STATUS_CONTINUE6 0x6780 + ++/* 0x6858, 0x7458, 0x10058, 0x10c58, 0x11858, 0x12458 */ ++#define GRPH_INT_STATUS 0x6858 ++# define GRPH_PFLIP_INT_OCCURRED (1 << 0) ++# define GRPH_PFLIP_INT_CLEAR (1 << 8) ++/* 0x685c, 0x745c, 0x1005c, 0x10c5c, 0x1185c, 0x1245c */ ++#define GRPH_INT_CONTROL 0x685c ++# define GRPH_PFLIP_INT_MASK (1 << 0) ++# define GRPH_PFLIP_INT_TYPE (1 << 8) ++ + #define DAC_AUTODETECT_INT_CONTROL 0x67c8 + + #define DC_HPD1_INT_STATUS 0x601c +diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c +index 27b0ff1..8ffee2b 100644 +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -4375,7 +4375,6 @@ int evergreen_irq_set(struct radeon_device *rdev) + u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0; + u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6; + u32 grbm_int_cntl = 0; +- u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0; + u32 afmt1 = 0, afmt2 = 0, afmt3 = 0, afmt4 = 0, afmt5 = 0, afmt6 = 0; + u32 dma_cntl, dma_cntl1 = 0; + u32 thermal_int = 0; +@@ -4558,15 +4557,21 @@ int evergreen_irq_set(struct radeon_device *rdev) + WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6); + } + +- WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, grph1); +- WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, grph2); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_MASK); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_MASK); + if (rdev->num_crtc >= 4) { +- WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3); +- WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_MASK); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_MASK); + } + if (rdev->num_crtc >= 6) { +- WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, grph5); +- WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_MASK); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_MASK); + } + + WREG32(DC_HPD1_INT_CONTROL, hpd1); +@@ -4955,6 +4960,15 @@ restart_ih: + break; + } + break; ++ case 8: /* D1 page flip */ ++ case 9: /* D2 page flip */ ++ case 10: /* D3 page flip */ ++ case 11: /* D4 page flip */ ++ case 12: /* D5 page flip */ ++ case 13: /* D6 page flip */ ++ DRM_DEBUG("IH: D%d flip\n", src_id - 7); ++ radeon_crtc_handle_flip(rdev, src_id - 8); ++ break; + case 42: /* HPD hotplug */ + switch (src_data) { + case 0: +diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c +index 647ef40..114a3ef 100644 +--- a/drivers/gpu/drm/radeon/r600.c ++++ b/drivers/gpu/drm/radeon/r600.c +@@ -3509,7 +3509,6 @@ int r600_irq_set(struct radeon_device *rdev) + u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0; + u32 grbm_int_cntl = 0; + u32 hdmi0, hdmi1; +- u32 d1grph = 0, d2grph = 0; + u32 dma_cntl; + u32 thermal_int = 0; + +@@ -3618,8 +3617,8 @@ int r600_irq_set(struct radeon_device *rdev) + WREG32(CP_INT_CNTL, cp_int_cntl); + WREG32(DMA_CNTL, dma_cntl); + WREG32(DxMODE_INT_MASK, mode_int); +- WREG32(D1GRPH_INTERRUPT_CONTROL, d1grph); +- WREG32(D2GRPH_INTERRUPT_CONTROL, d2grph); ++ WREG32(D1GRPH_INTERRUPT_CONTROL, DxGRPH_PFLIP_INT_MASK); ++ WREG32(D2GRPH_INTERRUPT_CONTROL, DxGRPH_PFLIP_INT_MASK); + WREG32(GRBM_INT_CNTL, grbm_int_cntl); + if (ASIC_IS_DCE3(rdev)) { + WREG32(DC_HPD1_INT_CONTROL, hpd1); +@@ -3922,6 +3921,11 @@ restart_ih: + break; + } + break; ++ case 9: /* D1 pflip */ ++ case 10: /* D2 pflip */ ++ DRM_DEBUG("IH: D%d flip\n", src_id - 8); ++ radeon_crtc_handle_flip(rdev, src_id - 9); ++ break; + case 19: /* HPD/DAC hotplug */ + switch (src_data) { + case 0: +diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h +index e887d02..5587de9 100644 +--- a/drivers/gpu/drm/radeon/radeon.h ++++ b/drivers/gpu/drm/radeon/radeon.h +@@ -733,6 +733,12 @@ struct cik_irq_stat_regs { + u32 disp_int_cont4; + u32 disp_int_cont5; + u32 disp_int_cont6; ++ u32 d1grph_int; ++ u32 d2grph_int; ++ u32 d3grph_int; ++ u32 d4grph_int; ++ u32 d5grph_int; ++ u32 d6grph_int; + }; + + union radeon_irq_stat_regs { +diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c +index 12a01e9..5e4326f 100644 +--- a/drivers/gpu/drm/radeon/radeon_display.c ++++ b/drivers/gpu/drm/radeon/radeon_display.c +@@ -284,6 +284,10 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) + u32 update_pending; + int vpos, hpos; + ++ /* can happen during initialization */ ++ if (radeon_crtc == NULL) ++ return; ++ + spin_lock_irqsave(&rdev->ddev->event_lock, flags); + work = radeon_crtc->unpin_work; + if (work == NULL || +diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c +index 9a124d0..2b47e53 100644 +--- a/drivers/gpu/drm/radeon/si.c ++++ b/drivers/gpu/drm/radeon/si.c +@@ -5777,7 +5777,6 @@ int si_irq_set(struct radeon_device *rdev) + u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0; + u32 hpd1 = 0, hpd2 = 0, hpd3 = 0, hpd4 = 0, hpd5 = 0, hpd6 = 0; + u32 grbm_int_cntl = 0; +- u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0; + u32 dma_cntl, dma_cntl1; + u32 thermal_int = 0; + +@@ -5916,16 +5915,22 @@ int si_irq_set(struct radeon_device *rdev) + } + + if (rdev->num_crtc >= 2) { +- WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, grph1); +- WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, grph2); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_MASK); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_MASK); + } + if (rdev->num_crtc >= 4) { +- WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3); +- WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_MASK); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_MASK); + } + if (rdev->num_crtc >= 6) { +- WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, grph5); +- WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_MASK); ++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, ++ GRPH_PFLIP_INT_MASK); + } + + if (!ASIC_IS_NODCE(rdev)) { +@@ -6289,6 +6294,15 @@ restart_ih: + break; + } + break; ++ case 8: /* D1 page flip */ ++ case 9: /* D2 page flip */ ++ case 10: /* D3 page flip */ ++ case 11: /* D4 page flip */ ++ case 12: /* D5 page flip */ ++ case 13: /* D6 page flip */ ++ DRM_DEBUG("IH: D%d flip\n", src_id - 7); ++ radeon_crtc_handle_flip(rdev, src_id - 8); ++ break; + case 42: /* HPD hotplug */ + switch (src_data) { + case 0: +-- +1.9.1 + +