Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6db8148c authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux

Pull radeon drm fixes from Dave Airlie:
 "This is just radeon fixes, primarily the two pll fix and the aux fix,
  it also disables dpm on rv770 gpus, fixes driver reloading, and fixes
  two issues with runtime PM on some GPUS"

* 'drm-fixes' of git://people.freedesktop.org/~airlied/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
parents 1b17844b abaafc0a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);
+1 −1
Original line number Diff line number Diff line
@@ -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;
+19 −16
Original line number Diff line number Diff line
@@ -158,6 +158,7 @@ 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 */

	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) {
@@ -170,6 +171,7 @@ u32 r600_dpm_get_vblank_time(struct radeon_device *rdev)
				break;
			}
		}
	}

	return vblank_time_us;
}
@@ -181,6 +183,7 @@ u32 r600_dpm_get_vrefresh(struct radeon_device *rdev)
	struct radeon_crtc *radeon_crtc;
	u32 vrefresh = 0;

	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) {
@@ -188,7 +191,7 @@ u32 r600_dpm_get_vrefresh(struct radeon_device *rdev)
				break;
			}
		}

	}
	return vrefresh;
}

+7 −0
Original line number Diff line number Diff line
@@ -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",
+57 −27
Original line number Diff line number Diff line
@@ -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,6 +915,11 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
		ref_div_min = pll->reference_div;
	else
		ref_div_min = pll->min_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 */
@@ -887,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) {
@@ -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);
}

Loading