Commit ac58c3f0 authored by Daniel Vetter's avatar Daniel Vetter
Browse files

drm/i915: split out intel_pnv_find_best_PLL



Pineview is just different.

Also split out i9xx_clock from intel_clock and drop the now redundant
struct device * parameter.

Note that in this patch I kill an XXX comment about 100MHz clocks. I
couldn't figure out what this is about, and we don't seem to have any
bug reports about this either. I suspect that it's a remnant from when
the i9xx and ilk+ modeset code was all in the same file since ilk+
does indeed have a 100MHz clock. So I've just killed it to stop the
cargo-culting.

Reviewed-by: default avatarPaulo Zanoni <przanoni@gmail.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 1b829e05
Loading
Loading
Loading
Loading
+77 −15
Original line number Diff line number Diff line
@@ -97,10 +97,13 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
		    int target, int refclk, intel_clock_t *match_clock,
		    intel_clock_t *best_clock);
static bool
intel_pnv_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
			int target, int refclk, intel_clock_t *match_clock,
			intel_clock_t *best_clock);
static bool
intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
			int target, int refclk, intel_clock_t *match_clock,
			intel_clock_t *best_clock);

static bool
intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc,
			int target, int refclk, intel_clock_t *match_clock,
@@ -246,7 +249,7 @@ static const intel_limit_t intel_limits_pineview_sdvo = {
	.p1 = { .min = 1, .max = 8 },
	.p2 = { .dot_limit = 200000,
		.p2_slow = 10, .p2_fast = 5 },
	.find_pll = intel_find_best_PLL,
	.find_pll = intel_pnv_find_best_PLL,
};

static const intel_limit_t intel_limits_pineview_lvds = {
@@ -260,7 +263,7 @@ static const intel_limit_t intel_limits_pineview_lvds = {
	.p1 = { .min = 1, .max = 8 },
	.p2 = { .dot_limit = 112000,
		.p2_slow = 14, .p2_fast = 14 },
	.find_pll = intel_find_best_PLL,
	.find_pll = intel_pnv_find_best_PLL,
};

/* Ironlake / Sandybridge
@@ -475,12 +478,8 @@ static uint32_t i9xx_dpll_compute_m(struct dpll *dpll)
	return 5 * (dpll->m1 + 2) + (dpll->m2 + 2);
}

static void intel_clock(struct drm_device *dev, int refclk, intel_clock_t *clock)
static void i9xx_clock(int refclk, intel_clock_t *clock)
{
	if (IS_PINEVIEW(dev)) {
		pineview_clock(refclk, clock);
		return;
	}
	clock->m = i9xx_dpll_compute_m(clock);
	clock->p = clock->p1 * clock->p2;
	clock->vco = refclk * clock->m / (clock->n + 2);
@@ -541,7 +540,68 @@ static bool
intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
		    int target, int refclk, intel_clock_t *match_clock,
		    intel_clock_t *best_clock)
{
	struct drm_device *dev = crtc->dev;
	intel_clock_t clock;
	int err = target;

	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
		/*
		 * For LVDS just rely on its current settings for dual-channel.
		 * We haven't figured out how to reliably set up different
		 * single/dual channel state, if we even can.
		 */
		if (intel_is_dual_link_lvds(dev))
			clock.p2 = limit->p2.p2_fast;
		else
			clock.p2 = limit->p2.p2_slow;
	} else {
		if (target < limit->p2.dot_limit)
			clock.p2 = limit->p2.p2_slow;
		else
			clock.p2 = limit->p2.p2_fast;
	}

	memset(best_clock, 0, sizeof(*best_clock));

	for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
	     clock.m1++) {
		for (clock.m2 = limit->m2.min;
		     clock.m2 <= limit->m2.max; clock.m2++) {
			/* m1 is always 0 in Pineview */
			if (clock.m2 >= clock.m1 && !IS_PINEVIEW(dev))
				break;
			for (clock.n = limit->n.min;
			     clock.n <= limit->n.max; clock.n++) {
				for (clock.p1 = limit->p1.min;
					clock.p1 <= limit->p1.max; clock.p1++) {
					int this_err;

					i9xx_clock(refclk, &clock);
					if (!intel_PLL_is_valid(dev, limit,
								&clock))
						continue;
					if (match_clock &&
					    clock.p != match_clock->p)
						continue;

					this_err = abs(clock.dot - target);
					if (this_err < err) {
						*best_clock = clock;
						err = this_err;
					}
				}
			}
		}
	}

	return (err != target);
}

static bool
intel_pnv_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
			int target, int refclk, intel_clock_t *match_clock,
			intel_clock_t *best_clock)
{
	struct drm_device *dev = crtc->dev;
	intel_clock_t clock;
@@ -579,7 +639,7 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
					clock.p1 <= limit->p1.max; clock.p1++) {
					int this_err;

					intel_clock(dev, refclk, &clock);
					pineview_clock(refclk, &clock);
					if (!intel_PLL_is_valid(dev, limit,
								&clock))
						continue;
@@ -638,7 +698,7 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
				     clock.p1 >= limit->p1.min; clock.p1--) {
					int this_err;

					intel_clock(dev, refclk, &clock);
					i9xx_clock(refclk, &clock);
					if (!intel_PLL_is_valid(dev, limit,
								&clock))
						continue;
@@ -6910,8 +6970,10 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
			return 0;
		}

		/* XXX: Handle the 100Mhz refclk */
		intel_clock(dev, 96000, &clock);
		if (IS_PINEVIEW(dev))
			pineview_clock(96000, &clock);
		else
			i9xx_clock(96000, &clock);
	} else {
		bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN);

@@ -6923,9 +6985,9 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
			if ((dpll & PLL_REF_INPUT_MASK) ==
			    PLLB_REF_INPUT_SPREADSPECTRUMIN) {
				/* XXX: might not be 66MHz */
				intel_clock(dev, 66000, &clock);
				i9xx_clock(66000, &clock);
			} else
				intel_clock(dev, 48000, &clock);
				i9xx_clock(48000, &clock);
		} else {
			if (dpll & PLL_P1_DIVIDE_BY_TWO)
				clock.p1 = 2;
@@ -6938,7 +7000,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
			else
				clock.p2 = 2;

			intel_clock(dev, 48000, &clock);
			i9xx_clock(48000, &clock);
		}
	}