Merge branch 'drm-fixes-3.15' of git://people.freedesktop.org/~deathsimple/linux into drm-next
1. Further PLL parameter fixes. 2. Fixes for HPD on DP 3. Could of different PM fixes 4. Disabling DPM on RV770 * 'drm-fixes-3.15' of git://people.freedesktop.org/~deathsimple/linux: drm/radeon: don't allow runpm=1 on systems with out ATPX drm/radeon: fix ATPX detection on non-VGA GPUs drm/radeon/pm: don't walk the crtc list before it has been initialized (v2) drm/radeon: properly unregister hwmon interface (v2) drm/radeon: fix count in cik_sdma_ring_test() drm/radeon/aux: fix hpd assignment for aux bus drm/radeon: improve PLL limit handling in post div calculation drm/radeon: use fixed PPL ref divider if needed drm/radeon: disable dpm on rv770 by default
This commit is contained in:
commit
abaafc0af9
|
@ -209,6 +209,7 @@ void radeon_dp_aux_init(struct radeon_connector *radeon_connector)
|
|||
{
|
||||
int ret;
|
||||
|
||||
radeon_connector->ddc_bus->rec.hpd = radeon_connector->hpd.hpd;
|
||||
radeon_connector->ddc_bus->aux.dev = radeon_connector->base.kdev;
|
||||
radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer;
|
||||
ret = drm_dp_aux_register_i2c_bus(&radeon_connector->ddc_bus->aux);
|
||||
|
|
|
@ -597,7 +597,7 @@ int cik_sdma_ring_test(struct radeon_device *rdev,
|
|||
tmp = 0xCAFEDEAD;
|
||||
writel(tmp, ptr);
|
||||
|
||||
r = radeon_ring_lock(rdev, ring, 4);
|
||||
r = radeon_ring_lock(rdev, ring, 5);
|
||||
if (r) {
|
||||
DRM_ERROR("radeon: dma failed to lock ring %d (%d).\n", ring->idx, r);
|
||||
return r;
|
||||
|
|
|
@ -158,16 +158,18 @@ u32 r600_dpm_get_vblank_time(struct radeon_device *rdev)
|
|||
u32 line_time_us, vblank_lines;
|
||||
u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
radeon_crtc = to_radeon_crtc(crtc);
|
||||
if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {
|
||||
line_time_us = (radeon_crtc->hw_mode.crtc_htotal * 1000) /
|
||||
radeon_crtc->hw_mode.clock;
|
||||
vblank_lines = radeon_crtc->hw_mode.crtc_vblank_end -
|
||||
radeon_crtc->hw_mode.crtc_vdisplay +
|
||||
(radeon_crtc->v_border * 2);
|
||||
vblank_time_us = vblank_lines * line_time_us;
|
||||
break;
|
||||
if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
radeon_crtc = to_radeon_crtc(crtc);
|
||||
if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {
|
||||
line_time_us = (radeon_crtc->hw_mode.crtc_htotal * 1000) /
|
||||
radeon_crtc->hw_mode.clock;
|
||||
vblank_lines = radeon_crtc->hw_mode.crtc_vblank_end -
|
||||
radeon_crtc->hw_mode.crtc_vdisplay +
|
||||
(radeon_crtc->v_border * 2);
|
||||
vblank_time_us = vblank_lines * line_time_us;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -181,14 +183,15 @@ u32 r600_dpm_get_vrefresh(struct radeon_device *rdev)
|
|||
struct radeon_crtc *radeon_crtc;
|
||||
u32 vrefresh = 0;
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
radeon_crtc = to_radeon_crtc(crtc);
|
||||
if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {
|
||||
vrefresh = radeon_crtc->hw_mode.vrefresh;
|
||||
break;
|
||||
if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
radeon_crtc = to_radeon_crtc(crtc);
|
||||
if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {
|
||||
vrefresh = radeon_crtc->hw_mode.vrefresh;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return vrefresh;
|
||||
}
|
||||
|
||||
|
|
|
@ -528,6 +528,13 @@ static bool radeon_atpx_detect(void)
|
|||
has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true);
|
||||
}
|
||||
|
||||
/* some newer PX laptops mark the dGPU as a non-VGA display device */
|
||||
while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
|
||||
vga_count++;
|
||||
|
||||
has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true);
|
||||
}
|
||||
|
||||
if (has_atpx && vga_count == 2) {
|
||||
acpi_get_name(radeon_atpx_priv.atpx.handle, ACPI_FULL_PATHNAME, &buffer);
|
||||
printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n",
|
||||
|
|
|
@ -839,6 +839,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
|
||||
*
|
||||
|
@ -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;
|
||||
|
@ -880,14 +915,18 @@ 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) {
|
||||
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) {
|
||||
|
@ -898,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;
|
||||
|
@ -912,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 */
|
||||
|
@ -926,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))) {
|
||||
|
||||
|
@ -936,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 */
|
||||
|
@ -979,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);
|
||||
}
|
||||
|
||||
|
|
|
@ -107,11 +107,9 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
|
|||
flags |= RADEON_IS_PCI;
|
||||
}
|
||||
|
||||
if (radeon_runtime_pm == 1)
|
||||
flags |= RADEON_IS_PX;
|
||||
else if ((radeon_runtime_pm == -1) &&
|
||||
radeon_has_atpx() &&
|
||||
((flags & RADEON_IS_IGP) == 0))
|
||||
if ((radeon_runtime_pm != 0) &&
|
||||
radeon_has_atpx() &&
|
||||
((flags & RADEON_IS_IGP) == 0))
|
||||
flags |= RADEON_IS_PX;
|
||||
|
||||
/* radeon_device_init should report only fatal error
|
||||
|
|
|
@ -603,7 +603,6 @@ static const struct attribute_group *hwmon_groups[] = {
|
|||
static int radeon_hwmon_init(struct radeon_device *rdev)
|
||||
{
|
||||
int err = 0;
|
||||
struct device *hwmon_dev;
|
||||
|
||||
switch (rdev->pm.int_thermal_type) {
|
||||
case THERMAL_TYPE_RV6XX:
|
||||
|
@ -616,11 +615,11 @@ static int radeon_hwmon_init(struct radeon_device *rdev)
|
|||
case THERMAL_TYPE_KV:
|
||||
if (rdev->asic->pm.get_temperature == NULL)
|
||||
return err;
|
||||
hwmon_dev = hwmon_device_register_with_groups(rdev->dev,
|
||||
"radeon", rdev,
|
||||
hwmon_groups);
|
||||
if (IS_ERR(hwmon_dev)) {
|
||||
err = PTR_ERR(hwmon_dev);
|
||||
rdev->pm.int_hwmon_dev = hwmon_device_register_with_groups(rdev->dev,
|
||||
"radeon", rdev,
|
||||
hwmon_groups);
|
||||
if (IS_ERR(rdev->pm.int_hwmon_dev)) {
|
||||
err = PTR_ERR(rdev->pm.int_hwmon_dev);
|
||||
dev_err(rdev->dev,
|
||||
"Unable to register hwmon device: %d\n", err);
|
||||
}
|
||||
|
@ -632,6 +631,12 @@ static int radeon_hwmon_init(struct radeon_device *rdev)
|
|||
return err;
|
||||
}
|
||||
|
||||
static void radeon_hwmon_fini(struct radeon_device *rdev)
|
||||
{
|
||||
if (rdev->pm.int_hwmon_dev)
|
||||
hwmon_device_unregister(rdev->pm.int_hwmon_dev);
|
||||
}
|
||||
|
||||
static void radeon_dpm_thermal_work_handler(struct work_struct *work)
|
||||
{
|
||||
struct radeon_device *rdev =
|
||||
|
@ -1257,6 +1262,7 @@ int radeon_pm_init(struct radeon_device *rdev)
|
|||
case CHIP_RV670:
|
||||
case CHIP_RS780:
|
||||
case CHIP_RS880:
|
||||
case CHIP_RV770:
|
||||
case CHIP_BARTS:
|
||||
case CHIP_TURKS:
|
||||
case CHIP_CAICOS:
|
||||
|
@ -1273,7 +1279,6 @@ int radeon_pm_init(struct radeon_device *rdev)
|
|||
else
|
||||
rdev->pm.pm_method = PM_METHOD_PROFILE;
|
||||
break;
|
||||
case CHIP_RV770:
|
||||
case CHIP_RV730:
|
||||
case CHIP_RV710:
|
||||
case CHIP_RV740:
|
||||
|
@ -1353,6 +1358,8 @@ static void radeon_pm_fini_old(struct radeon_device *rdev)
|
|||
device_remove_file(rdev->dev, &dev_attr_power_method);
|
||||
}
|
||||
|
||||
radeon_hwmon_fini(rdev);
|
||||
|
||||
if (rdev->pm.power_state)
|
||||
kfree(rdev->pm.power_state);
|
||||
}
|
||||
|
@ -1372,6 +1379,8 @@ static void radeon_pm_fini_dpm(struct radeon_device *rdev)
|
|||
}
|
||||
radeon_dpm_fini(rdev);
|
||||
|
||||
radeon_hwmon_fini(rdev);
|
||||
|
||||
if (rdev->pm.power_state)
|
||||
kfree(rdev->pm.power_state);
|
||||
}
|
||||
|
@ -1397,12 +1406,14 @@ static void radeon_pm_compute_clocks_old(struct radeon_device *rdev)
|
|||
|
||||
rdev->pm.active_crtcs = 0;
|
||||
rdev->pm.active_crtc_count = 0;
|
||||
list_for_each_entry(crtc,
|
||||
&ddev->mode_config.crtc_list, head) {
|
||||
radeon_crtc = to_radeon_crtc(crtc);
|
||||
if (radeon_crtc->enabled) {
|
||||
rdev->pm.active_crtcs |= (1 << radeon_crtc->crtc_id);
|
||||
rdev->pm.active_crtc_count++;
|
||||
if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {
|
||||
list_for_each_entry(crtc,
|
||||
&ddev->mode_config.crtc_list, head) {
|
||||
radeon_crtc = to_radeon_crtc(crtc);
|
||||
if (radeon_crtc->enabled) {
|
||||
rdev->pm.active_crtcs |= (1 << radeon_crtc->crtc_id);
|
||||
rdev->pm.active_crtc_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1469,12 +1480,14 @@ static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev)
|
|||
/* update active crtc counts */
|
||||
rdev->pm.dpm.new_active_crtcs = 0;
|
||||
rdev->pm.dpm.new_active_crtc_count = 0;
|
||||
list_for_each_entry(crtc,
|
||||
&ddev->mode_config.crtc_list, head) {
|
||||
radeon_crtc = to_radeon_crtc(crtc);
|
||||
if (crtc->enabled) {
|
||||
rdev->pm.dpm.new_active_crtcs |= (1 << radeon_crtc->crtc_id);
|
||||
rdev->pm.dpm.new_active_crtc_count++;
|
||||
if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {
|
||||
list_for_each_entry(crtc,
|
||||
&ddev->mode_config.crtc_list, head) {
|
||||
radeon_crtc = to_radeon_crtc(crtc);
|
||||
if (crtc->enabled) {
|
||||
rdev->pm.dpm.new_active_crtcs |= (1 << radeon_crtc->crtc_id);
|
||||
rdev->pm.dpm.new_active_crtc_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue