/* calculate ss amount and step size */
                if (ASIC_IS_DCE4(rdev)) {
                        u32 step_size;
-                       u32 amount = (((fb_div * 10) + frac_fb_div) * radeon_crtc->ss.percentage) / 10000;
+                       u32 amount = (((fb_div * 10) + frac_fb_div) *
+                                     (u32)radeon_crtc->ss.percentage) /
+                               (100 * (u32)radeon_crtc->ss.percentage_divider);
                        radeon_crtc->ss.amount = (amount / 10) & ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK;
                        radeon_crtc->ss.amount |= ((amount - (amount / 10)) << ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) &
                                ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK;
                        if (radeon_crtc->ss.type & ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD)
-                               step_size = (4 * amount * ref_div * (radeon_crtc->ss.rate * 2048)) /
+                               step_size = (4 * amount * ref_div * ((u32)radeon_crtc->ss.rate * 2048)) /
                                        (125 * 25 * pll->reference_freq / 100);
                        else
-                               step_size = (2 * amount * ref_div * (radeon_crtc->ss.rate * 2048)) /
+                               step_size = (2 * amount * ref_div * ((u32)radeon_crtc->ss.rate * 2048)) /
                                        (125 * 25 * pll->reference_freq / 100);
                        radeon_crtc->ss.step = step_size;
                }
 
                                                le16_to_cpu(ss_assign->v1.usSpreadSpectrumPercentage);
                                        ss->type = ss_assign->v1.ucSpreadSpectrumMode;
                                        ss->rate = le16_to_cpu(ss_assign->v1.usSpreadRateInKhz);
+                                       ss->percentage_divider = 100;
                                        return true;
                                }
                                ss_assign = (union asic_ss_assignment *)
                                                le16_to_cpu(ss_assign->v2.usSpreadSpectrumPercentage);
                                        ss->type = ss_assign->v2.ucSpreadSpectrumMode;
                                        ss->rate = le16_to_cpu(ss_assign->v2.usSpreadRateIn10Hz);
+                                       ss->percentage_divider = 100;
                                        if ((crev == 2) &&
                                            ((id == ASIC_INTERNAL_ENGINE_SS) ||
                                             (id == ASIC_INTERNAL_MEMORY_SS)))
                                                le16_to_cpu(ss_assign->v3.usSpreadSpectrumPercentage);
                                        ss->type = ss_assign->v3.ucSpreadSpectrumMode;
                                        ss->rate = le16_to_cpu(ss_assign->v3.usSpreadRateIn10Hz);
+                                       if (ss_assign->v3.ucSpreadSpectrumMode &
+                                           SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK)
+                                               ss->percentage_divider = 1000;
+                                       else
+                                               ss->percentage_divider = 100;
                                        if ((id == ASIC_INTERNAL_ENGINE_SS) ||
                                            (id == ASIC_INTERNAL_MEMORY_SS))
                                                ss->rate /= 100;