diff --git a/packages/linux/patches/3.14.2/linux-996-drm-radeon-rework-finding-display-PLL-numbers.patch b/packages/linux/patches/3.14.2/linux-996-drm-radeon-rework-finding-display-PLL-numbers.patch deleted file mode 100644 index 3062919ad7..0000000000 --- a/packages/linux/patches/3.14.2/linux-996-drm-radeon-rework-finding-display-PLL-numbers.patch +++ /dev/null @@ -1,303 +0,0 @@ -From: Christian K?nig - -This completely reworks how the PLL parameters are generated and -should result in better matching dot clock frequencies. - -Probably needs quite a bit of testing. - -bugs: https://bugs.freedesktop.org/show_bug.cgi?id=76564 - -v2: more cleanup and comments. - -Signed-off-by: Christian K?nig ---- - drivers/gpu/drm/radeon/radeon_display.c | 243 ++++++++++++++++++++------------ - 1 file changed, 153 insertions(+), 90 deletions(-) - -diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c -index fbd8b93..4e83ffd 100644 ---- a/drivers/gpu/drm/radeon/radeon_display.c -+++ b/drivers/gpu/drm/radeon/radeon_display.c -@@ -34,6 +34,8 @@ - #include - #include - -+#include -+ - static void avivo_crtc_load_lut(struct drm_crtc *crtc) - { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); -@@ -799,66 +801,57 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) - } - - /* avivo */ --static void avivo_get_fb_div(struct radeon_pll *pll, -- u32 target_clock, -- u32 post_div, -- u32 ref_div, -- u32 *fb_div, -- u32 *frac_fb_div) --{ -- u32 tmp = post_div * ref_div; - -- tmp *= target_clock; -- *fb_div = tmp / pll->reference_freq; -- *frac_fb_div = tmp % pll->reference_freq; -- -- if (*fb_div > pll->max_feedback_div) -- *fb_div = pll->max_feedback_div; -- else if (*fb_div < pll->min_feedback_div) -- *fb_div = pll->min_feedback_div; --} -- --static u32 avivo_get_post_div(struct radeon_pll *pll, -- u32 target_clock) -+/** -+ * avivo_reduce_ratio - fractional number reduction -+ * -+ * @nom: nominator -+ * @den: denominator -+ * @nom_min: minimum value for nominator -+ * @den_min: minimum value for denominator -+ * -+ * Find the greatest common divisor and apply it on both nominator and -+ * denominator, but make nominator and denominator are at least as large -+ * as their minimum values. -+ */ -+static void avivo_reduce_ratio(unsigned *nom, unsigned *den, -+ unsigned nom_min, unsigned den_min) - { -- u32 vco, post_div, tmp; -- -- if (pll->flags & RADEON_PLL_USE_POST_DIV) -- return pll->post_div; -- -- if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) { -- if (pll->flags & RADEON_PLL_IS_LCD) -- vco = pll->lcd_pll_out_min; -- else -- vco = pll->pll_out_min; -- } else { -- if (pll->flags & RADEON_PLL_IS_LCD) -- vco = pll->lcd_pll_out_max; -- else -- vco = pll->pll_out_max; -+ unsigned tmp; -+ -+ /* reduce the numbers to a simpler ratio */ -+ tmp = gcd(*nom, *den); -+ *nom /= tmp; -+ *den /= tmp; -+ -+ /* make sure nominator is large enough */ -+ if (*nom < nom_min) { -+ tmp = (nom_min + *nom - 1) / *nom; -+ *nom *= tmp; -+ *den *= tmp; - } - -- post_div = vco / target_clock; -- tmp = vco % target_clock; -- -- if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) { -- if (tmp) -- post_div++; -- } else { -- if (!tmp) -- post_div--; -+ /* make sure the denominator is large enough */ -+ if (*den < den_min) { -+ tmp = (den_min + *den - 1) / *den; -+ *nom *= tmp; -+ *den *= tmp; - } -- -- if (post_div > pll->max_post_div) -- post_div = pll->max_post_div; -- else if (post_div < pll->min_post_div) -- post_div = pll->min_post_div; -- -- return post_div; - } - --#define MAX_TOLERANCE 10 -- -+/** -+ * radeon_compute_pll_avivo - compute PLL paramaters -+ * -+ * @pll: information about the PLL -+ * @dot_clock_p: resulting pixel clock -+ * fb_div_p: resulting feedback divider -+ * frac_fb_div_p: fractional part of the feedback divider -+ * ref_div_p: resulting reference divider -+ * post_div_p: resulting reference divider -+ * -+ * Try to calculate the PLL parameters to generate the given frequency: -+ * dot_clock = (ref_freq * feedback_div) / (ref_div * post_div) -+ */ - void radeon_compute_pll_avivo(struct radeon_pll *pll, - u32 freq, - u32 *dot_clock_p, -@@ -867,53 +860,123 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, - u32 *ref_div_p, - u32 *post_div_p) - { -- u32 target_clock = freq / 10; -- u32 post_div = avivo_get_post_div(pll, target_clock); -- u32 ref_div = pll->min_ref_div; -- u32 fb_div = 0, frac_fb_div = 0, tmp; -+ 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; -+ unsigned post_div_best, diff_best; -+ unsigned nom, den, tmp; - -- if (pll->flags & RADEON_PLL_USE_REF_DIV) -- ref_div = pll->reference_div; -+ /* determine allowed feedback divider range */ -+ fb_div_min = pll->min_feedback_div; -+ fb_div_max = pll->max_feedback_div; - - if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) { -- avivo_get_fb_div(pll, target_clock, post_div, ref_div, &fb_div, &frac_fb_div); -- frac_fb_div = (100 * frac_fb_div) / pll->reference_freq; -- if (frac_fb_div >= 5) { -- frac_fb_div -= 5; -- frac_fb_div = frac_fb_div / 10; -- frac_fb_div++; -+ fb_div_min *= 10; -+ fb_div_max *= 10; -+ } -+ -+ /* determine allowed ref divider range */ -+ if (pll->flags & RADEON_PLL_USE_REF_DIV) -+ ref_div_min = pll->reference_div; -+ else -+ ref_div_min = pll->min_ref_div; -+ ref_div_max = pll->max_ref_div; -+ -+ /* determine allowed post divider range */ -+ if (pll->flags & RADEON_PLL_USE_POST_DIV) { -+ 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) { -+ vco_min = pll->lcd_pll_out_min; -+ vco_max = pll->lcd_pll_out_max; -+ } else { -+ vco_min = pll->pll_out_min; -+ vco_max = pll->pll_out_max; - } -- if (frac_fb_div >= 10) { -- fb_div++; -- frac_fb_div = 0; -+ -+ post_div_min = vco_min / target_clock; -+ if ((target_clock * post_div_min) < vco_min) -+ ++post_div_min; -+ if (post_div_min < pll->min_post_div) -+ post_div_min = pll->min_post_div; -+ -+ post_div_max = vco_max / target_clock; -+ if ((target_clock * post_div_max) > vco_max) -+ --post_div_max; -+ if (post_div_max > pll->max_post_div) -+ post_div_max = pll->max_post_div; -+ } -+ -+ /* represent the searched ratio as fractional number */ -+ nom = pll->flags & RADEON_PLL_USE_FRAC_FB_DIV ? freq : freq / 10; -+ den = pll->reference_freq; -+ -+ /* reduce the numbers to a simpler ratio */ -+ avivo_reduce_ratio(&nom, &den, fb_div_min, post_div_min); -+ -+ /* now search for a post divider */ -+ if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) -+ post_div_best = post_div_min; -+ else -+ post_div_best = post_div_max; -+ 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); -+ if (diff < diff_best || (diff == diff_best && -+ !(pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP))) { -+ -+ post_div_best = post_div; -+ diff_best = diff; - } -+ } -+ post_div = post_div_best; -+ -+ /* get matching reference and feedback divider */ -+ ref_div = max(den / post_div, 1u); -+ fb_div = nom; -+ -+ /* we're almost done, but reference and feedback -+ divider might be to large now */ -+ -+ tmp = ref_div; -+ -+ if (fb_div > fb_div_max) { -+ ref_div = ref_div * fb_div_max / fb_div; -+ fb_div = fb_div_max; -+ } -+ -+ if (ref_div > ref_div_max) { -+ ref_div = ref_div_max; -+ fb_div = nom * ref_div_max / tmp; -+ } -+ -+ /* reduce the numbers to a simpler ratio once more */ -+ /* this also makes sure that the reference divider is large enough */ -+ avivo_reduce_ratio(&fb_div, &ref_div, fb_div_min, ref_div_min); -+ -+ /* and finally save the result */ -+ if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) { -+ *fb_div_p = fb_div / 10; -+ *frac_fb_div_p = fb_div % 10; - } else { -- while (ref_div <= pll->max_ref_div) { -- avivo_get_fb_div(pll, target_clock, post_div, ref_div, -- &fb_div, &frac_fb_div); -- if (frac_fb_div >= (pll->reference_freq / 2)) -- fb_div++; -- frac_fb_div = 0; -- tmp = (pll->reference_freq * fb_div) / (post_div * ref_div); -- tmp = (tmp * 10000) / target_clock; -- -- if (tmp > (10000 + MAX_TOLERANCE)) -- ref_div++; -- else if (tmp >= (10000 - MAX_TOLERANCE)) -- break; -- else -- ref_div++; -- } -+ *fb_div_p = fb_div; -+ *frac_fb_div_p = 0; - } - -- *dot_clock_p = ((pll->reference_freq * fb_div * 10) + (pll->reference_freq * frac_fb_div)) / -- (ref_div * post_div * 10); -- *fb_div_p = fb_div; -- *frac_fb_div_p = frac_fb_div; -+ *dot_clock_p = ((pll->reference_freq * *fb_div_p * 10) + -+ (pll->reference_freq * *frac_fb_div_p)) / -+ (ref_div * post_div * 10); - *ref_div_p = ref_div; - *post_div_p = post_div; -- DRM_DEBUG_KMS("%d, pll dividers - fb: %d.%d ref: %d, post %d\n", -- *dot_clock_p, fb_div, frac_fb_div, ref_div, 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, -+ ref_div, post_div); - } - - /* pre-avivo */ --- -1.9.1 diff --git a/packages/linux/patches/3.14.2/linux-997-02-drm-radeon-more-pll-bits.patch b/packages/linux/patches/3.14.2/linux-997-02-drm-radeon-more-pll-bits.patch deleted file mode 100644 index 96fea36a66..0000000000 --- a/packages/linux/patches/3.14.2/linux-997-02-drm-radeon-more-pll-bits.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 19de393134c00989b5b1cc5e6dd4ed444a897ace Mon Sep 17 00:00:00 2001 -From: Christian König -Date: Wed, 16 Apr 2014 09:54:21 +0000 -Subject: drm/radeon: improve PLL params if we don't match exactly - -Otherwise we might be quite off on older chipsets. - -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 2f42912..fb3b505 100644 ---- a/drivers/gpu/drm/radeon/radeon_display.c -+++ b/drivers/gpu/drm/radeon/radeon_display.c -@@ -865,7 +865,7 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, - unsigned post_div_min, post_div_max, post_div; - unsigned ref_div_min, ref_div_max, ref_div; - unsigned post_div_best, diff_best; -- unsigned nom, den, tmp; -+ unsigned nom, den; - - /* determine allowed feedback divider range */ - fb_div_min = pll->min_feedback_div; -@@ -941,22 +941,23 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, - 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; -+ ref_div = DIV_ROUND_CLOSEST(den, post_div); -+ 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 */ - -- tmp = ref_div; -+ nom = fb_div; -+ den = ref_div; - - if (fb_div > fb_div_max) { -- ref_div = ref_div * fb_div_max / fb_div; -+ 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 = nom * ref_div_max / tmp; -+ fb_div = DIV_ROUND_CLOSEST(nom * ref_div_max, den); - } - - /* reduce the numbers to a simpler ratio once more */ --- -cgit v0.9.0.2-2-gbebe diff --git a/packages/linux/patches/3.14.2/linux-997-03-drm-radeon-more-pll-bits-more-logging.patch b/packages/linux/patches/3.14.2/linux-997-03-drm-radeon-more-pll-bits-more-logging.patch deleted file mode 100644 index b577238b23..0000000000 --- a/packages/linux/patches/3.14.2/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.14.2/linux-997-drm-radeon-rework-finding-display-PLL-numbers-fix-range.patch b/packages/linux/patches/3.14.2/linux-997-drm-radeon-rework-finding-display-PLL-numbers-fix-range.patch deleted file mode 100644 index a12ae3d7aa..0000000000 --- a/packages/linux/patches/3.14.2/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.14.2/linux-999.03-drm-radeon-PLL-fixes.patch b/packages/linux/patches/3.14.2/linux-999.03-drm-radeon-PLL-fixes.patch new file mode 100644 index 0000000000..19536aea52 --- /dev/null +++ b/packages/linux/patches/3.14.2/linux-999.03-drm-radeon-PLL-fixes.patch @@ -0,0 +1,944 @@ +From 709b25580e01df28a97152a81010ce40f06ec01e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20K=C3=B6nig?= +Date: Fri, 28 Mar 2014 18:55:10 +0100 +Subject: [PATCH 1/6] drm/radeon: rework finding display PLL numbers v2 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This completely reworks how the PLL parameters are generated and +should result in better matching dot clock frequencies. + +Probably needs quite a bit of testing. + +bugs: https://bugs.freedesktop.org/show_bug.cgi?id=76564 + +v2: more cleanup and comments. + +Signed-off-by: Christian König +Reviewed-by: Alex Deucher +--- + drivers/gpu/drm/radeon/radeon_display.c | 243 ++++++++++++++++++++------------ + 1 file changed, 153 insertions(+), 90 deletions(-) + +diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c +index fbd8b93..4e83ffd 100644 +--- a/drivers/gpu/drm/radeon/radeon_display.c ++++ b/drivers/gpu/drm/radeon/radeon_display.c +@@ -34,6 +34,8 @@ + #include + #include + ++#include ++ + static void avivo_crtc_load_lut(struct drm_crtc *crtc) + { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); +@@ -799,66 +801,57 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) + } + + /* avivo */ +-static void avivo_get_fb_div(struct radeon_pll *pll, +- u32 target_clock, +- u32 post_div, +- u32 ref_div, +- u32 *fb_div, +- u32 *frac_fb_div) +-{ +- u32 tmp = post_div * ref_div; + +- tmp *= target_clock; +- *fb_div = tmp / pll->reference_freq; +- *frac_fb_div = tmp % pll->reference_freq; +- +- if (*fb_div > pll->max_feedback_div) +- *fb_div = pll->max_feedback_div; +- else if (*fb_div < pll->min_feedback_div) +- *fb_div = pll->min_feedback_div; +-} +- +-static u32 avivo_get_post_div(struct radeon_pll *pll, +- u32 target_clock) ++/** ++ * avivo_reduce_ratio - fractional number reduction ++ * ++ * @nom: nominator ++ * @den: denominator ++ * @nom_min: minimum value for nominator ++ * @den_min: minimum value for denominator ++ * ++ * Find the greatest common divisor and apply it on both nominator and ++ * denominator, but make nominator and denominator are at least as large ++ * as their minimum values. ++ */ ++static void avivo_reduce_ratio(unsigned *nom, unsigned *den, ++ unsigned nom_min, unsigned den_min) + { +- u32 vco, post_div, tmp; +- +- if (pll->flags & RADEON_PLL_USE_POST_DIV) +- return pll->post_div; +- +- if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) { +- if (pll->flags & RADEON_PLL_IS_LCD) +- vco = pll->lcd_pll_out_min; +- else +- vco = pll->pll_out_min; +- } else { +- if (pll->flags & RADEON_PLL_IS_LCD) +- vco = pll->lcd_pll_out_max; +- else +- vco = pll->pll_out_max; ++ unsigned tmp; ++ ++ /* reduce the numbers to a simpler ratio */ ++ tmp = gcd(*nom, *den); ++ *nom /= tmp; ++ *den /= tmp; ++ ++ /* make sure nominator is large enough */ ++ if (*nom < nom_min) { ++ tmp = (nom_min + *nom - 1) / *nom; ++ *nom *= tmp; ++ *den *= tmp; + } + +- post_div = vco / target_clock; +- tmp = vco % target_clock; +- +- if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) { +- if (tmp) +- post_div++; +- } else { +- if (!tmp) +- post_div--; ++ /* make sure the denominator is large enough */ ++ if (*den < den_min) { ++ tmp = (den_min + *den - 1) / *den; ++ *nom *= tmp; ++ *den *= tmp; + } +- +- if (post_div > pll->max_post_div) +- post_div = pll->max_post_div; +- else if (post_div < pll->min_post_div) +- post_div = pll->min_post_div; +- +- return post_div; + } + +-#define MAX_TOLERANCE 10 +- ++/** ++ * radeon_compute_pll_avivo - compute PLL paramaters ++ * ++ * @pll: information about the PLL ++ * @dot_clock_p: resulting pixel clock ++ * fb_div_p: resulting feedback divider ++ * frac_fb_div_p: fractional part of the feedback divider ++ * ref_div_p: resulting reference divider ++ * post_div_p: resulting reference divider ++ * ++ * Try to calculate the PLL parameters to generate the given frequency: ++ * dot_clock = (ref_freq * feedback_div) / (ref_div * post_div) ++ */ + void radeon_compute_pll_avivo(struct radeon_pll *pll, + u32 freq, + u32 *dot_clock_p, +@@ -867,53 +860,123 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, + u32 *ref_div_p, + u32 *post_div_p) + { +- u32 target_clock = freq / 10; +- u32 post_div = avivo_get_post_div(pll, target_clock); +- u32 ref_div = pll->min_ref_div; +- u32 fb_div = 0, frac_fb_div = 0, tmp; ++ 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; ++ unsigned post_div_best, diff_best; ++ unsigned nom, den, tmp; + +- if (pll->flags & RADEON_PLL_USE_REF_DIV) +- ref_div = pll->reference_div; ++ /* determine allowed feedback divider range */ ++ fb_div_min = pll->min_feedback_div; ++ fb_div_max = pll->max_feedback_div; + + if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) { +- avivo_get_fb_div(pll, target_clock, post_div, ref_div, &fb_div, &frac_fb_div); +- frac_fb_div = (100 * frac_fb_div) / pll->reference_freq; +- if (frac_fb_div >= 5) { +- frac_fb_div -= 5; +- frac_fb_div = frac_fb_div / 10; +- frac_fb_div++; ++ fb_div_min *= 10; ++ fb_div_max *= 10; ++ } ++ ++ /* determine allowed ref divider range */ ++ if (pll->flags & RADEON_PLL_USE_REF_DIV) ++ ref_div_min = pll->reference_div; ++ else ++ ref_div_min = pll->min_ref_div; ++ ref_div_max = pll->max_ref_div; ++ ++ /* determine allowed post divider range */ ++ if (pll->flags & RADEON_PLL_USE_POST_DIV) { ++ 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) { ++ vco_min = pll->lcd_pll_out_min; ++ vco_max = pll->lcd_pll_out_max; ++ } else { ++ vco_min = pll->pll_out_min; ++ vco_max = pll->pll_out_max; + } +- if (frac_fb_div >= 10) { +- fb_div++; +- frac_fb_div = 0; ++ ++ post_div_min = vco_min / target_clock; ++ if ((target_clock * post_div_min) < vco_min) ++ ++post_div_min; ++ if (post_div_min < pll->min_post_div) ++ post_div_min = pll->min_post_div; ++ ++ post_div_max = vco_max / target_clock; ++ if ((target_clock * post_div_max) > vco_max) ++ --post_div_max; ++ if (post_div_max > pll->max_post_div) ++ post_div_max = pll->max_post_div; ++ } ++ ++ /* represent the searched ratio as fractional number */ ++ nom = pll->flags & RADEON_PLL_USE_FRAC_FB_DIV ? freq : freq / 10; ++ den = pll->reference_freq; ++ ++ /* reduce the numbers to a simpler ratio */ ++ avivo_reduce_ratio(&nom, &den, fb_div_min, post_div_min); ++ ++ /* now search for a post divider */ ++ if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) ++ post_div_best = post_div_min; ++ else ++ post_div_best = post_div_max; ++ 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); ++ if (diff < diff_best || (diff == diff_best && ++ !(pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP))) { ++ ++ post_div_best = post_div; ++ diff_best = diff; + } ++ } ++ post_div = post_div_best; ++ ++ /* get matching reference and feedback divider */ ++ ref_div = max(den / post_div, 1u); ++ fb_div = nom; ++ ++ /* we're almost done, but reference and feedback ++ divider might be to large now */ ++ ++ tmp = ref_div; ++ ++ if (fb_div > fb_div_max) { ++ ref_div = ref_div * fb_div_max / fb_div; ++ fb_div = fb_div_max; ++ } ++ ++ if (ref_div > ref_div_max) { ++ ref_div = ref_div_max; ++ fb_div = nom * ref_div_max / tmp; ++ } ++ ++ /* reduce the numbers to a simpler ratio once more */ ++ /* this also makes sure that the reference divider is large enough */ ++ avivo_reduce_ratio(&fb_div, &ref_div, fb_div_min, ref_div_min); ++ ++ /* and finally save the result */ ++ if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) { ++ *fb_div_p = fb_div / 10; ++ *frac_fb_div_p = fb_div % 10; + } else { +- while (ref_div <= pll->max_ref_div) { +- avivo_get_fb_div(pll, target_clock, post_div, ref_div, +- &fb_div, &frac_fb_div); +- if (frac_fb_div >= (pll->reference_freq / 2)) +- fb_div++; +- frac_fb_div = 0; +- tmp = (pll->reference_freq * fb_div) / (post_div * ref_div); +- tmp = (tmp * 10000) / target_clock; +- +- if (tmp > (10000 + MAX_TOLERANCE)) +- ref_div++; +- else if (tmp >= (10000 - MAX_TOLERANCE)) +- break; +- else +- ref_div++; +- } ++ *fb_div_p = fb_div; ++ *frac_fb_div_p = 0; + } + +- *dot_clock_p = ((pll->reference_freq * fb_div * 10) + (pll->reference_freq * frac_fb_div)) / +- (ref_div * post_div * 10); +- *fb_div_p = fb_div; +- *frac_fb_div_p = frac_fb_div; ++ *dot_clock_p = ((pll->reference_freq * *fb_div_p * 10) + ++ (pll->reference_freq * *frac_fb_div_p)) / ++ (ref_div * post_div * 10); + *ref_div_p = ref_div; + *post_div_p = post_div; +- DRM_DEBUG_KMS("%d, pll dividers - fb: %d.%d ref: %d, post %d\n", +- *dot_clock_p, fb_div, frac_fb_div, ref_div, 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, ++ ref_div, post_div); + } + + /* pre-avivo */ +-- +1.9.1 + +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 97856db97ccbf06adf0cd6ede973b922e59d3eaa Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20K=C3=B6nig?= +Date: Wed, 16 Apr 2014 11:54:21 +0200 +Subject: [PATCH 3/6] drm/radeon: improve PLL params if we don't match exactly + v2 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Otherwise we might be quite off on older chipsets. + +v2: keep ref_div minimum + +Signed-off-by: Christian König +--- + drivers/gpu/drm/radeon/radeon_display.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c +index 35129ad..00f63d28 100644 +--- a/drivers/gpu/drm/radeon/radeon_display.c ++++ b/drivers/gpu/drm/radeon/radeon_display.c +@@ -864,7 +864,7 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, + unsigned post_div_min, post_div_max, post_div; + unsigned ref_div_min, ref_div_max, ref_div; + unsigned post_div_best, diff_best; +- unsigned nom, den, tmp; ++ unsigned nom, den; + + /* determine allowed feedback divider range */ + fb_div_min = pll->min_feedback_div; +@@ -940,22 +940,23 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, + 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; ++ 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 */ + +- tmp = ref_div; ++ nom = fb_div; ++ den = ref_div; + + if (fb_div > fb_div_max) { +- ref_div = ref_div * fb_div_max / fb_div; ++ 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 = nom * ref_div_max / tmp; ++ fb_div = DIV_ROUND_CLOSEST(nom * ref_div_max, den); + } + + /* reduce the numbers to a simpler ratio once more */ +-- +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 + + 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 + +