All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/14] drm/i915: ValleyView mode setting limits and PLL functions
@ 2012-06-15 18:55 Jesse Barnes
  2012-06-15 18:55 ` [PATCH 02/14] drm/i915: Enable DP panel power sequencing for ValleyView Jesse Barnes
                   ` (12 more replies)
  0 siblings, 13 replies; 25+ messages in thread
From: Jesse Barnes @ 2012-06-15 18:55 UTC (permalink / raw)
  To: intel-gfx

Add some VLV limit structures and update the PLL code.

v2: resolve conflicts, Vijay to re-post with PLL valid checks and fixed limits
v3: re-add dpio write function
v4: squash in Vijay's fixes for the PLL limits and clean up the m/n finder

Signed-off-by: Shobhit Kumar <shobhit.kumar@intel.com>
Signed-off-by: Vijay Purushothaman <vijay.a.purushothaman@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_reg.h      |    1 +
 drivers/gpu/drm/i915/intel_display.c |  240 +++++++++++++++++++++++++++++++++-
 2 files changed, 239 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 7dcc04f..281446d 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -900,6 +900,7 @@
 #define   DPLL_P2_CLOCK_DIV_MASK	0x03000000 /* i915 */
 #define   DPLL_FPA01_P1_POST_DIV_MASK	0x00ff0000 /* i915 */
 #define   DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW	0x00ff8000 /* Pineview */
+#define   DPLL_LOCK_VLV			(1<<15)
 #define   DPLL_INTEGRATED_CLOCK_VLV	(1<<13)
 
 #define SRX_INDEX		0x3c4
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0161d94..f8ea7bc 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -98,6 +98,11 @@ intel_find_pll_ironlake_dp(const intel_limit_t *, 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,
+			intel_clock_t *best_clock);
+
 static inline u32 /* units of 100MHz */
 intel_fdi_link_freq(struct drm_device *dev)
 {
@@ -359,6 +364,48 @@ static const intel_limit_t intel_limits_ironlake_display_port = {
 	.find_pll = intel_find_pll_ironlake_dp,
 };
 
+static const intel_limit_t intel_limits_vlv_dac = {
+	.dot = { .min = 25000, .max = 270000 },
+	.vco = { .min = 4000000, .max = 6000000 },
+	.n = { .min = 1, .max = 7 },
+	.m = { .min = 22, .max = 450 }, /* guess */
+	.m1 = { .min = 2, .max = 3 },
+	.m2 = { .min = 11, .max = 156 },
+	.p = { .min = 10, .max = 30 },
+	.p1 = { .min = 2, .max = 3 },
+	.p2 = { .dot_limit = 270000,
+		.p2_slow = 2, .p2_fast = 20 },
+	.find_pll = intel_vlv_find_best_pll,
+};
+
+static const intel_limit_t intel_limits_vlv_hdmi = {
+	.dot = { .min = 20000, .max = 165000 },
+	.vco = { .min = 5994000, .max = 4000000 },
+	.n = { .min = 1, .max = 7 },
+	.m = { .min = 60, .max = 300 }, /* guess */
+	.m1 = { .min = 2, .max = 3 },
+	.m2 = { .min = 11, .max = 156 },
+	.p = { .min = 10, .max = 30 },
+	.p1 = { .min = 2, .max = 3 },
+	.p2 = { .dot_limit = 270000,
+		.p2_slow = 2, .p2_fast = 20 },
+	.find_pll = intel_vlv_find_best_pll,
+};
+
+static const intel_limit_t intel_limits_vlv_dp = {
+	.dot = { .min = 162000, .max = 270000 },
+	.vco = { .min = 5994000, .max = 4000000 },
+	.n = { .min = 1, .max = 7 },
+	.m = { .min = 60, .max = 300 }, /* guess */
+	.m1 = { .min = 2, .max = 3 },
+	.m2 = { .min = 11, .max = 156 },
+	.p = { .min = 10, .max = 30 },
+	.p1 = { .min = 2, .max = 3 },
+	.p2 = { .dot_limit = 270000,
+		.p2_slow = 2, .p2_fast = 20 },
+	.find_pll = intel_vlv_find_best_pll,
+};
+
 u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg)
 {
 	unsigned long flags;
@@ -384,6 +431,28 @@ out_unlock:
 	return val;
 }
 
+static void intel_dpio_write(struct drm_i915_private *dev_priv, int reg,
+			     u32 val)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_priv->dpio_lock, flags);
+	if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) {
+		DRM_ERROR("DPIO idle wait timed out\n");
+		goto out_unlock;
+	}
+
+	I915_WRITE(DPIO_DATA, val);
+	I915_WRITE(DPIO_REG, reg);
+	I915_WRITE(DPIO_PKT, DPIO_RID | DPIO_OP_WRITE | DPIO_PORTID |
+		   DPIO_BYTE);
+	if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100))
+		DRM_ERROR("DPIO write wait timed out\n");
+
+out_unlock:
+       spin_unlock_irqrestore(&dev_priv->dpio_lock, flags);
+}
+
 static void vlv_init_dpio(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -510,6 +579,13 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc, int refclk)
 			limit = &intel_limits_pineview_lvds;
 		else
 			limit = &intel_limits_pineview_sdvo;
+	} else if (IS_VALLEYVIEW(dev)) {
+		if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG))
+			limit = &intel_limits_vlv_dac;
+		else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI))
+			limit = &intel_limits_vlv_hdmi;
+		else
+			limit = &intel_limits_vlv_dp;
 	} else if (!IS_GEN2(dev)) {
 		if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
 			limit = &intel_limits_i9xx_lvds;
@@ -783,6 +859,73 @@ intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
 	memcpy(best_clock, &clock, sizeof(intel_clock_t));
 	return true;
 }
+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,
+			intel_clock_t *best_clock)
+{
+	u32 p1, p2, m1, m2, vco, bestn, bestm1, bestm2, bestp1, bestp2;
+	u32 m, n, fastclk;
+	u32 updrate, minupdate, fracbits, p;
+	unsigned long bestppm, ppm, absppm;
+	int dotclk, flag;
+
+	dotclk = target * 1000;
+	bestppm = 1000000;
+	ppm = absppm = 0;
+	fastclk = dotclk / (2*100);
+	updrate = 0;
+	minupdate = 19200;
+	fracbits = 1;
+	n = p = p1 = p2 = m = m1 = m2 = vco = bestn = 0;
+	bestm1 = bestm2 = bestp1 = bestp2 = 0;
+
+	/* based on hardware requirement, prefer smaller n to precision */
+	for (n = limit->n.min; n <= ((refclk) / minupdate); n++) {
+		updrate = refclk / n;
+		for (p1 = limit->p1.max; p1 > limit->p1.min; p1--) {
+			for (p2 = limit->p2.p2_fast+1; p2 > 0; p2--) {
+				if (p2 > 10)
+					p2 = p2 - 1;
+				p = p1 * p2;
+				/* based on hardware requirement, prefer bigger m1,m2 values */
+				for (m1 = limit->m1.min; m1 <= limit->m1.max; m1++) {
+					m2 = (((2*(fastclk * p * n / m1 )) +
+					       refclk) / (2*refclk));
+					m = m1 * m2;
+					vco = updrate * m;
+					if (vco >= limit->vco.min && vco < limit->vco.max) {
+						ppm = 1000000 * ((vco / p) - fastclk) / fastclk;
+						absppm = (ppm > 0) ? ppm : (-ppm);
+						if (absppm < 100 && ((p1 * p2) > (bestp1 * bestp2))) {
+							bestppm = 0;
+							flag = 1;
+						}
+						if (absppm < bestppm - 10) {
+							bestppm = absppm;
+							flag = 1;
+						}
+						if (flag) {
+							bestn = n;
+							bestm1 = m1;
+							bestm2 = m2;
+							bestp1 = p1;
+							bestp2 = p2;
+							flag = 0;
+						}
+					}
+				}
+			}
+		}
+	}
+	best_clock->n = bestn;
+	best_clock->m1 = bestm1;
+	best_clock->m2 = bestm2;
+	best_clock->p1 = bestp1;
+	best_clock->p2 = bestp2;
+
+	return true;
+}
 
 static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe)
 {
@@ -1287,7 +1430,7 @@ static void intel_enable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
 	u32 val;
 
 	/* No really, not for ILK+ */
-	BUG_ON(dev_priv->info->gen >= 5);
+	BUG_ON(!IS_VALLEYVIEW(dev_priv->dev) && dev_priv->info->gen >= 5);
 
 	/* PLL is protected by panel, make sure we can write it */
 	if (IS_MOBILE(dev_priv->dev) && !IS_I830(dev_priv->dev))
@@ -3666,13 +3809,37 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
 	return display_bpc != bpc;
 }
 
+static int vlv_get_refclk(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int refclk = 27000; /* for DP & HDMI */
+
+	return 100000; /* only one validated so far */
+
+	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) {
+		refclk = 96000;
+	} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
+		if (intel_panel_use_ssc(dev_priv))
+			refclk = 100000;
+		else
+			refclk = 96000;
+	} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
+		refclk = 100000;
+	}
+
+	return refclk;
+}
+
 static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int refclk;
 
-	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
+	if (IS_VALLEYVIEW(dev)) {
+		refclk = vlv_get_refclk(crtc);
+	} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
 	    intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
 		refclk = dev_priv->lvds_ssc_freq * 1000;
 		DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
@@ -3787,6 +3954,72 @@ static void intel_update_lvds(struct drm_crtc *crtc, intel_clock_t *clock,
 	I915_WRITE(LVDS, temp);
 }
 
+static void vlv_update_pll(struct drm_crtc *crtc,
+			   struct drm_display_mode *mode,
+			   struct drm_display_mode *adjusted_mode,
+			   intel_clock_t *clock, intel_clock_t *reduced_clock,
+			   int refclk, int num_connectors)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+	u32 dpll, mdiv, pdiv;
+	u32 bestn, bestm1, bestm2, bestp1, bestp2;
+	bool is_hdmi;
+
+	is_hdmi = intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI);
+
+	bestn = clock->n;
+	bestm1 = clock->m1;
+	bestm2 = clock->m2;
+	bestp1 = clock->p1;
+	bestp2 = clock->p2;
+
+	/* Enable DPIO clock input */
+	dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV |
+		DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV;
+	I915_WRITE(DPLL(pipe), dpll);
+	POSTING_READ(DPLL(pipe));
+
+	mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK));
+	mdiv |= ((bestp1 << DPIO_P1_SHIFT) | (bestp2 << DPIO_P2_SHIFT));
+	mdiv |= ((bestn << DPIO_N_SHIFT));
+	mdiv |= (1 << DPIO_POST_DIV_SHIFT);
+	mdiv |= (1 << DPIO_K_SHIFT);
+	mdiv |= DPIO_ENABLE_CALIBRATION;
+	intel_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv);
+
+	intel_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), 0x01000000);
+
+	pdiv = DPIO_REFSEL_OVERRIDE | (5 << DPIO_PLL_MODESEL_SHIFT) |
+		(3 << DPIO_BIAS_CURRENT_CTL_SHIFT) | (1<<20) |
+		(8 << DPIO_DRIVER_CTL_SHIFT) | (5 << DPIO_CLK_BIAS_CTL_SHIFT);
+	intel_dpio_write(dev_priv, DPIO_REFSFR(pipe), pdiv);
+
+	intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe), 0x009f0051);
+
+	dpll |= DPLL_VCO_ENABLE;
+	I915_WRITE(DPLL(pipe), dpll);
+	POSTING_READ(DPLL(pipe));
+	if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
+		DRM_ERROR("DPLL %d failed to lock\n", pipe);
+
+	if (is_hdmi) {
+		u32 temp = intel_mode_get_pixel_multiplier(adjusted_mode);
+
+		if (temp > 1)
+			temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
+		else
+			temp = 0;
+
+		I915_WRITE(DPLL_MD(pipe), temp);
+		POSTING_READ(DPLL_MD(pipe));
+	}
+
+	intel_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x641); /* ??? */
+}
+
 static void i9xx_update_pll(struct drm_crtc *crtc,
 			    struct drm_display_mode *mode,
 			    struct drm_display_mode *adjusted_mode,
@@ -4044,6 +4277,9 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 
 	if (IS_GEN2(dev))
 		i8xx_update_pll(crtc, adjusted_mode, &clock, num_connectors);
+	else if (IS_VALLEYVIEW(dev))
+		vlv_update_pll(crtc, mode,adjusted_mode, &clock, NULL,
+			       refclk, num_connectors);
 	else
 		i9xx_update_pll(crtc, mode, adjusted_mode, &clock,
 				has_reduced_clock ? &reduced_clock : NULL,
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 02/14] drm/i915: Enable DP panel power sequencing for ValleyView
  2012-06-15 18:55 [PATCH 01/14] drm/i915: ValleyView mode setting limits and PLL functions Jesse Barnes
@ 2012-06-15 18:55 ` Jesse Barnes
  2012-06-20 12:50   ` Daniel Vetter
  2012-06-15 18:55 ` [PATCH 03/14] drm/i915: add ValleyView specific CRT detect function Jesse Barnes
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 25+ messages in thread
From: Jesse Barnes @ 2012-06-15 18:55 UTC (permalink / raw)
  To: intel-gfx; +Cc: Beeresh G

From: Shobhit Kumar <shobhit.kumar@intel.com>

VLV supports two dp panels, there are two set of panel power sequence
registers which needed to be programmed based on the configured
pipe. This patch add supports for the same

Acked-by: Acked-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Beeresh G <beeresh.g@intel.com>
Reviewed-by: Vijay Purushothaman <vijay.a.purushothaman@intel.com>
Reviewed-by: Jesse Barnes <jesse.barnes@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_reg.h |   12 ++++++++++++
 drivers/gpu/drm/i915/intel_dp.c |    8 +++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 281446d..a9e9d92 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3854,6 +3854,18 @@
 
 #define BLC_PWM_PCH_CTL2	0xc8254
 
+#define PIPEA_PP_STATUS         0x61200
+#define PIPEA_PP_CONTROL        0x61204
+#define PIPEA_PP_ON_DELAYS      0x61208
+#define PIPEA_PP_OFF_DELAYS     0x6120c
+#define PIPEA_PP_DIVISOR        0x61210
+
+#define PIPEB_PP_STATUS         0x61300
+#define PIPEB_PP_CONTROL        0x61304
+#define PIPEB_PP_ON_DELAYS      0x61308
+#define PIPEB_PP_OFF_DELAYS     0x6130c
+#define PIPEB_PP_DIVISOR        0x61310
+
 #define PCH_PP_STATUS		0xc7200
 #define PCH_PP_CONTROL		0xc7204
 #define  PANEL_UNLOCK_REGS	(0xabcd << 16)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 6538c46..d59af24 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -342,7 +342,13 @@ static bool ironlake_edp_have_panel_power(struct intel_dp *intel_dp)
 	struct drm_device *dev = intel_dp->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	return (I915_READ(PCH_PP_STATUS) & PP_ON) != 0;
+	if (IS_VALLEYVIEW(dev)) {
+		if (I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT)
+			return (I915_READ(PIPEB_PP_STATUS) & PP_ON) != 0;
+		else
+			return (I915_READ(PIPEA_PP_STATUS) & PP_ON) != 0;
+	} else
+		return (I915_READ(PCH_PP_STATUS) & PP_ON) != 0;
 }
 
 static bool ironlake_edp_have_panel_vdd(struct intel_dp *intel_dp)
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 03/14] drm/i915: add ValleyView specific CRT detect function
  2012-06-15 18:55 [PATCH 01/14] drm/i915: ValleyView mode setting limits and PLL functions Jesse Barnes
  2012-06-15 18:55 ` [PATCH 02/14] drm/i915: Enable DP panel power sequencing for ValleyView Jesse Barnes
@ 2012-06-15 18:55 ` Jesse Barnes
  2012-06-15 18:55 ` [PATCH 04/14] drm/i915: add HDMI and DP port enumeration on ValleyView Jesse Barnes
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Jesse Barnes @ 2012-06-15 18:55 UTC (permalink / raw)
  To: intel-gfx

Might be able to merge this back in at some point, but we're seeing bugs
with ADPA based detection, so keep it separate for now with explicit
hotplug trigger usage.

v2: drop superfluous debug message
v3: comment forced detection, need to debug (Eugeni)

Reviewed-by: Eugeni Dodonov <eugeni.dodonov@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/intel_crt.c |   39 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 75a70c4..1333a65 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -230,6 +230,42 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector)
 	return ret;
 }
 
+static bool valleyview_crt_detect_hotplug(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 adpa;
+	bool ret;
+	u32 save_adpa;
+
+	save_adpa = adpa = I915_READ(ADPA);
+	DRM_DEBUG_KMS("trigger hotplug detect cycle: adpa=0x%x\n", adpa);
+
+	adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER;
+
+	I915_WRITE(ADPA, adpa);
+
+	if (wait_for((I915_READ(ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0,
+		     1000)) {
+		DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER");
+		I915_WRITE(ADPA, save_adpa);
+	}
+
+	/* Check the status to see if both blue and green are on now */
+	adpa = I915_READ(ADPA);
+	if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0)
+		ret = true;
+	else
+		ret = false;
+
+	DRM_DEBUG_KMS("valleyview hotplug adpa=0x%x, result %d\n", adpa, ret);
+
+	/* FIXME: debug force function and remove */
+	ret = true;
+
+	return ret;
+}
+
 /**
  * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
  *
@@ -249,6 +285,9 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
 	if (HAS_PCH_SPLIT(dev))
 		return intel_ironlake_crt_detect_hotplug(connector);
 
+	if (IS_VALLEYVIEW(dev))
+		return valleyview_crt_detect_hotplug(connector);
+
 	/*
 	 * On 4 series desktop, CRT detect sequence need to be done twice
 	 * to get a reliable result.
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 04/14] drm/i915: add HDMI and DP port enumeration on ValleyView
  2012-06-15 18:55 [PATCH 01/14] drm/i915: ValleyView mode setting limits and PLL functions Jesse Barnes
  2012-06-15 18:55 ` [PATCH 02/14] drm/i915: Enable DP panel power sequencing for ValleyView Jesse Barnes
  2012-06-15 18:55 ` [PATCH 03/14] drm/i915: add ValleyView specific CRT detect function Jesse Barnes
@ 2012-06-15 18:55 ` Jesse Barnes
  2012-06-15 18:55 ` [PATCH 05/14] drm/i915: access VLV regs through read/write switch Jesse Barnes
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Jesse Barnes @ 2012-06-15 18:55 UTC (permalink / raw)
  To: intel-gfx

ValleyView is similar to IbexPeak here, but with different register
offsets.

v2: use SDVOB instead ov VLV_HDMIB (Daniel)
    drop unnecessary eDP check in DP_C init (Daniel)

eDP support will be coming later from Shobit.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_reg.h      |    1 -
 drivers/gpu/drm/i915/intel_display.c |   17 +++++++++++++++++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index a9e9d92..263b50c 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3808,7 +3808,6 @@
 #define  ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16)
 
 /* or SDVOB */
-#define VLV_HDMIB 0x61140
 #define HDMIB   0xe1140
 #define  PORT_ENABLE    (1 << 31)
 #define  TRANSCODER(pipe)       ((pipe) << 30)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f8ea7bc..e2d23a3 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6762,7 +6762,24 @@ static void intel_setup_outputs(struct drm_device *dev)
 
 		if (!dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED))
 			intel_dp_init(dev, PCH_DP_D);
+	} else if (IS_VALLEYVIEW(dev)) {
+		int found;
+
+		if (I915_READ(SDVOB) & PORT_DETECTED) {
+			/* SDVOB multiplex with HDMIB */
+			found = intel_sdvo_init(dev, SDVOB, true);
+			if (!found)
+				intel_hdmi_init(dev, SDVOB);
+			if (!found && (I915_READ(DP_B) & DP_DETECTED))
+				intel_dp_init(dev, DP_B);
+		}
+
+		if (I915_READ(SDVOC) & PORT_DETECTED)
+			intel_hdmi_init(dev, SDVOC);
 
+		/* Shares lanes with HDMI on SDVOC */
+		if (I915_READ(DP_C) & DP_DETECTED)
+			intel_dp_init(dev, DP_C);
 	} else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) {
 		bool found = false;
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 05/14] drm/i915: access VLV regs through read/write switch
  2012-06-15 18:55 [PATCH 01/14] drm/i915: ValleyView mode setting limits and PLL functions Jesse Barnes
                   ` (2 preceding siblings ...)
  2012-06-15 18:55 ` [PATCH 04/14] drm/i915: add HDMI and DP port enumeration on ValleyView Jesse Barnes
@ 2012-06-15 18:55 ` Jesse Barnes
  2012-06-15 18:55 ` [PATCH 06/14] drm/i915: VLV VGA port only handles on & off, like PCH VGA Jesse Barnes
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Jesse Barnes @ 2012-06-15 18:55 UTC (permalink / raw)
  To: intel-gfx

Since the offsets have all moved around.

v2: switch IS_DISPLAYREG and IS_VALLEYVIEW checks around since the latter is
    cheaper (Daniel)
    bail out early in IS_DISPLAYREG if the reg is in the new range (Daniel)

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_drv.c |   87 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 85 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 238a521..9e772bd 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1144,6 +1144,84 @@ MODULE_LICENSE("GPL and additional rights");
         ((reg) != FORCEWAKE)) && \
        (!IS_VALLEYVIEW((dev_priv)->dev))
 
+static bool IS_DISPLAYREG(u32 reg)
+{
+	/*
+	 * This should make it easier to transition modules over to the
+	 * new register block scheme, since we can do it incrementally.
+	 */
+	if (reg >= 0x180000)
+		return false;
+
+	if (reg >= RENDER_RING_BASE &&
+	    reg < RENDER_RING_BASE + 0xff)
+		return false;
+	if (reg >= GEN6_BSD_RING_BASE &&
+	    reg < GEN6_BSD_RING_BASE + 0xff)
+		return false;
+	if (reg >= BLT_RING_BASE &&
+	    reg < BLT_RING_BASE + 0xff)
+		return false;
+
+	if (reg == PGTBL_ER)
+		return false;
+
+	if (reg >= IPEIR_I965 &&
+	    reg < HWSTAM)
+		return false;
+
+	if (reg == MI_MODE)
+		return false;
+
+	if (reg == GFX_MODE_GEN7)
+		return false;
+
+	if (reg == RENDER_HWS_PGA_GEN7 ||
+	    reg == BSD_HWS_PGA_GEN7 ||
+	    reg == BLT_HWS_PGA_GEN7)
+		return false;
+
+	if (reg == GEN6_BSD_SLEEP_PSMI_CONTROL ||
+	    reg == GEN6_BSD_RNCID)
+		return false;
+
+	if (reg == GEN6_BLITTER_ECOSKPD)
+		return false;
+
+	if (reg >= 0x4000c &&
+	    reg <= 0x4002c)
+		return false;
+
+	if (reg >= 0x4f000 &&
+	    reg <= 0x4f08f)
+		return false;
+
+	if (reg >= 0x4f100 &&
+	    reg <= 0x4f11f)
+		return false;
+
+	if (reg >= VLV_MASTER_IER &&
+	    reg <= GEN6_PMIER)
+		return false;
+
+	if (reg >= FENCE_REG_SANDYBRIDGE_0 &&
+	    reg < (FENCE_REG_SANDYBRIDGE_0 + (16*8)))
+		return false;
+
+	if (reg >= VLV_IIR_RW &&
+	    reg <= VLV_ISR)
+		return false;
+
+	if (reg == FORCEWAKE_VLV ||
+	    reg == FORCEWAKE_ACK_VLV)
+		return false;
+
+	if (reg == GEN6_GDRST)
+		return false;
+
+	return true;
+}
+
 #define __i915_read(x, y) \
 u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
 	u##x val = 0; \
@@ -1156,6 +1234,8 @@ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
 		if (dev_priv->forcewake_count == 0) \
 			dev_priv->display.force_wake_put(dev_priv); \
 		spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \
+	} else if (IS_VALLEYVIEW(dev_priv->dev) && IS_DISPLAYREG(reg)) { \
+		val = read##y(dev_priv->regs + reg + 0x180000);		\
 	} else { \
 		val = read##y(dev_priv->regs + reg); \
 	} \
@@ -1175,8 +1255,11 @@ void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
 	trace_i915_reg_rw(true, reg, val, sizeof(val)); \
 	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
 		__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
-	} \
-	write##y(val, dev_priv->regs + reg); \
+	} else if (IS_VALLEYVIEW(dev_priv->dev) && IS_DISPLAYREG(reg)) { \
+		write##y(val, dev_priv->regs + reg + 0x180000);		\
+	} else {							\
+		write##y(val, dev_priv->regs + reg);			\
+	}								\
 	if (unlikely(__fifo_ret)) { \
 		gen6_gt_check_fifodbg(dev_priv); \
 	} \
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 06/14] drm/i915: VLV VGA port only handles on & off, like PCH VGA
  2012-06-15 18:55 [PATCH 01/14] drm/i915: ValleyView mode setting limits and PLL functions Jesse Barnes
                   ` (3 preceding siblings ...)
  2012-06-15 18:55 ` [PATCH 05/14] drm/i915: access VLV regs through read/write switch Jesse Barnes
@ 2012-06-15 18:55 ` Jesse Barnes
  2012-06-15 18:55 ` [PATCH 07/14] agp/intel: allow cacheable and GDFT PTEs on ValleyView Jesse Barnes
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Jesse Barnes @ 2012-06-15 18:55 UTC (permalink / raw)
  To: intel-gfx

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/intel_crt.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 1333a65..ac62f24 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -88,6 +88,9 @@ static void gmch_crt_dpms(struct drm_encoder *encoder, int mode)
 	temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
 	temp &= ~ADPA_DAC_ENABLE;
 
+	if (IS_VALLEYVIEW(dev) && mode != DRM_MODE_DPMS_ON)
+		mode = DRM_MODE_DPMS_OFF;
+
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
 		temp |= ADPA_DAC_ENABLE;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 07/14] agp/intel: allow cacheable and GDFT PTEs on ValleyView
  2012-06-15 18:55 [PATCH 01/14] drm/i915: ValleyView mode setting limits and PLL functions Jesse Barnes
                   ` (4 preceding siblings ...)
  2012-06-15 18:55 ` [PATCH 06/14] drm/i915: VLV VGA port only handles on & off, like PCH VGA Jesse Barnes
@ 2012-06-15 18:55 ` Jesse Barnes
  2012-06-20 12:57   ` Daniel Vetter
  2012-06-15 18:55 ` [PATCH 08/14] drm/i915: support page flipping " Jesse Barnes
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 25+ messages in thread
From: Jesse Barnes @ 2012-06-15 18:55 UTC (permalink / raw)
  To: intel-gfx

The PTE format is similar to SNB, but we don't support an MLC and don't
need chipset flushing.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/char/agp/intel-gtt.c |   11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index 1237e75..c1e2943 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -1182,9 +1182,17 @@ static void gen6_write_entry(dma_addr_t addr, unsigned int entry,
 static void valleyview_write_entry(dma_addr_t addr, unsigned int entry,
 				   unsigned int flags)
 {
+	unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT;
+	unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT;
 	u32 pte_flags;
 
-	pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID;
+	if (type_mask == AGP_USER_MEMORY)
+		pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID;
+	else {
+		pte_flags = GEN6_PTE_LLC | I810_PTE_VALID;
+		if (gfdt)
+			pte_flags |= GEN6_PTE_GFDT;
+	}
 
 	/* gen6 has bit11-4 for physical addr bit39-32 */
 	addr |= (addr >> 28) & 0xff0;
@@ -1379,7 +1387,6 @@ static const struct intel_gtt_driver valleyview_gtt_driver = {
 	.write_entry = valleyview_write_entry,
 	.dma_mask_size = 40,
 	.check_flags = gen6_check_flags,
-	.chipset_flush = i9xx_chipset_flush,
 };
 
 /* Table to describe Intel GMCH and AGP/PCIE GART drivers.  At least one of
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 08/14] drm/i915: support page flipping on ValleyView
  2012-06-15 18:55 [PATCH 01/14] drm/i915: ValleyView mode setting limits and PLL functions Jesse Barnes
                   ` (5 preceding siblings ...)
  2012-06-15 18:55 ` [PATCH 07/14] agp/intel: allow cacheable and GDFT PTEs on ValleyView Jesse Barnes
@ 2012-06-15 18:55 ` Jesse Barnes
  2012-06-15 18:55 ` [PATCH 09/14] drm/i915: enable display messages to GT " Jesse Barnes
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Jesse Barnes @ 2012-06-15 18:55 UTC (permalink / raw)
  To: intel-gfx

And restructure the IRQ handling a little.  We can use pipestat for most
things, and make sure we don't affect pipe events when enabling and
disabling vblank interupts.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_irq.c |   62 +++++++++++++++++----------------------
 1 file changed, 27 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 0e87664..453ea7c 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -513,15 +513,10 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)
 	unsigned long irqflags;
 	int pipe;
 	u32 pipe_stats[I915_MAX_PIPES];
-	u32 vblank_status;
-	int vblank = 0;
 	bool blc_event;
 
 	atomic_inc(&dev_priv->irq_received);
 
-	vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS |
-		PIPE_VBLANK_INTERRUPT_STATUS;
-
 	while (true) {
 		iir = I915_READ(VLV_IIR);
 		gt_iir = I915_READ(GTIIR);
@@ -551,6 +546,16 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)
 		}
 		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
+		for_each_pipe(pipe) {
+			if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
+				drm_handle_vblank(dev, pipe);
+
+			if (pipe_stats[pipe] & PLANE_FLIPDONE_INT_STATUS_VLV) {
+				intel_prepare_page_flip(dev, pipe);
+				intel_finish_page_flip(dev, pipe);
+			}
+		}
+
 		/* Consume port.  Then clear IIR or we'll miss events */
 		if (iir & I915_DISPLAY_PORT_INTERRUPT) {
 			u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
@@ -565,19 +570,6 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)
 			I915_READ(PORT_HOTPLUG_STAT);
 		}
 
-
-		if (iir & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT) {
-			drm_handle_vblank(dev, 0);
-			vblank++;
-			intel_finish_page_flip(dev, 0);
-		}
-
-		if (iir & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT) {
-			drm_handle_vblank(dev, 1);
-			vblank++;
-			intel_finish_page_flip(dev, 0);
-		}
-
 		if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
 			blc_event = true;
 
@@ -1478,23 +1470,20 @@ static int valleyview_enable_vblank(struct drm_device *dev, int pipe)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	unsigned long irqflags;
-	u32 dpfl, imr;
+	u32 imr;
 
 	if (!i915_pipe_enabled(dev, pipe))
 		return -EINVAL;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-	dpfl = I915_READ(VLV_DPFLIPSTAT);
 	imr = I915_READ(VLV_IMR);
-	if (pipe == 0) {
-		dpfl |= PIPEA_VBLANK_INT_EN;
+	if (pipe == 0)
 		imr &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
-	} else {
-		dpfl |= PIPEA_VBLANK_INT_EN;
+	else
 		imr &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
-	}
-	I915_WRITE(VLV_DPFLIPSTAT, dpfl);
 	I915_WRITE(VLV_IMR, imr);
+	i915_enable_pipestat(dev_priv, pipe,
+			     PIPE_START_VBLANK_INTERRUPT_ENABLE);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
 	return 0;
@@ -1544,20 +1533,17 @@ static void valleyview_disable_vblank(struct drm_device *dev, int pipe)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	unsigned long irqflags;
-	u32 dpfl, imr;
+	u32 imr;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-	dpfl = I915_READ(VLV_DPFLIPSTAT);
+	i915_disable_pipestat(dev_priv, pipe,
+			      PIPE_START_VBLANK_INTERRUPT_ENABLE);
 	imr = I915_READ(VLV_IMR);
-	if (pipe == 0) {
-		dpfl &= ~PIPEA_VBLANK_INT_EN;
+	if (pipe == 0)
 		imr |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
-	} else {
-		dpfl &= ~PIPEB_VBLANK_INT_EN;
+	else
 		imr |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
-	}
 	I915_WRITE(VLV_IMR, imr);
-	I915_WRITE(VLV_DPFLIPSTAT, dpfl);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
@@ -1894,10 +1880,13 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
 	u32 render_irqs;
 	u32 enable_mask;
 	u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
+	u32 pipestat_enable = PLANE_FLIP_DONE_INT_EN_VLV;
 	u16 msid;
 
 	enable_mask = I915_DISPLAY_PORT_INTERRUPT;
-	enable_mask |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
+	enable_mask |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
+		I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
+		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
 		I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
 
 	dev_priv->irq_mask = ~enable_mask;
@@ -1919,6 +1908,9 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
 	I915_WRITE(PIPESTAT(1), 0xffff);
 	POSTING_READ(VLV_IER);
 
+	i915_enable_pipestat(dev_priv, 0, pipestat_enable);
+	i915_enable_pipestat(dev_priv, 1, pipestat_enable);
+
 	I915_WRITE(VLV_IIR, 0xffffffff);
 	I915_WRITE(VLV_IIR, 0xffffffff);
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 09/14] drm/i915: enable display messages to GT on ValleyView
  2012-06-15 18:55 [PATCH 01/14] drm/i915: ValleyView mode setting limits and PLL functions Jesse Barnes
                   ` (6 preceding siblings ...)
  2012-06-15 18:55 ` [PATCH 08/14] drm/i915: support page flipping " Jesse Barnes
@ 2012-06-15 18:55 ` Jesse Barnes
  2012-06-20 13:12   ` Daniel Vetter
  2012-06-15 18:55 ` [PATCH 10/14] agp/intel: use correct GTT offset on VLV Jesse Barnes
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 25+ messages in thread
From: Jesse Barnes @ 2012-06-15 18:55 UTC (permalink / raw)
  To: intel-gfx

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/intel_pm.c |    7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index d0ce2a5..4fa1a78 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3474,6 +3474,13 @@ static void valleyview_init_clock_gating(struct drm_device *dev)
 
 	I915_WRITE(CACHE_MODE_1,
 		   _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE));
+
+	/*
+	 * On ValleyView, the GUnit needs to signal the GT
+	 * when flip and other events complete.  So enable
+	 * all the GUnit->GT interrupts here
+	 */
+	I915_WRITE(VLV_DPFLIPSTAT, 0x3f7f0000);
 }
 
 static void g4x_init_clock_gating(struct drm_device *dev)
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 10/14] agp/intel: use correct GTT offset on VLV
  2012-06-15 18:55 [PATCH 01/14] drm/i915: ValleyView mode setting limits and PLL functions Jesse Barnes
                   ` (7 preceding siblings ...)
  2012-06-15 18:55 ` [PATCH 09/14] drm/i915: enable display messages to GT " Jesse Barnes
@ 2012-06-15 18:55 ` Jesse Barnes
  2012-06-15 18:55 ` [PATCH 11/14] drm/i915: don't enable PPGTT on VLV yet Jesse Barnes
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Jesse Barnes @ 2012-06-15 18:55 UTC (permalink / raw)
  To: intel-gfx

VLV is a gen7 device, but we don't currently handle that in the switch.
So add it and write the PTEs correctly.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/char/agp/intel-gtt.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index c1e2943..5bbc90d 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -1252,6 +1252,7 @@ static int i9xx_setup(void)
 		switch (INTEL_GTT_GEN) {
 		case 5:
 		case 6:
+		case 7:
 			gtt_offset = MB(2);
 			break;
 		case 4:
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 11/14] drm/i915: don't enable PPGTT on VLV yet
  2012-06-15 18:55 [PATCH 01/14] drm/i915: ValleyView mode setting limits and PLL functions Jesse Barnes
                   ` (8 preceding siblings ...)
  2012-06-15 18:55 ` [PATCH 10/14] agp/intel: use correct GTT offset on VLV Jesse Barnes
@ 2012-06-15 18:55 ` Jesse Barnes
  2012-06-15 18:55 ` [PATCH 12/14] drm/i915: don't account for shared interrupts on VLV Jesse Barnes
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Jesse Barnes @ 2012-06-15 18:55 UTC (permalink / raw)
  To: intel-gfx

Needs some more work and testing.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_drv.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ccabadd..f44ae6f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1074,7 +1074,7 @@ struct drm_i915_file_private {
 #define HAS_LLC(dev)            (INTEL_INFO(dev)->has_llc)
 #define I915_NEED_GFX_HWS(dev)	(INTEL_INFO(dev)->need_gfx_hws)
 
-#define HAS_ALIASING_PPGTT(dev)	(INTEL_INFO(dev)->gen >=6)
+#define HAS_ALIASING_PPGTT(dev)	(INTEL_INFO(dev)->gen >=6 && !IS_VALLEYVIEW(dev))
 
 #define HAS_OVERLAY(dev)		(INTEL_INFO(dev)->has_overlay)
 #define OVERLAY_NEEDS_PHYSICAL(dev)	(INTEL_INFO(dev)->overlay_needs_physical)
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 12/14] drm/i915: don't account for shared interrupts on VLV
  2012-06-15 18:55 [PATCH 01/14] drm/i915: ValleyView mode setting limits and PLL functions Jesse Barnes
                   ` (9 preceding siblings ...)
  2012-06-15 18:55 ` [PATCH 11/14] drm/i915: don't enable PPGTT on VLV yet Jesse Barnes
@ 2012-06-15 18:55 ` Jesse Barnes
  2012-06-20 13:18   ` Daniel Vetter
       [not found]   ` <15842_1340198260_4FE1CD73_15842_15371_1_20120620131831.GJ7170@phenom.ffwll.local>
  2012-06-15 18:55 ` [PATCH 13/14] drm/i915: fix initial IRQ masking on VLV Jesse Barnes
  2012-06-15 18:55 ` [PATCH 14/14] drm/i915: bind driver to ValleyView chipsets Jesse Barnes
  12 siblings, 2 replies; 25+ messages in thread
From: Jesse Barnes @ 2012-06-15 18:55 UTC (permalink / raw)
  To: intel-gfx

Only count interrupts we find came from the GPU.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_irq.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 453ea7c..36732f7 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -515,8 +515,6 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)
 	u32 pipe_stats[I915_MAX_PIPES];
 	bool blc_event;
 
-	atomic_inc(&dev_priv->irq_received);
-
 	while (true) {
 		iir = I915_READ(VLV_IIR);
 		gt_iir = I915_READ(GTIIR);
@@ -525,6 +523,8 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)
 		if (gt_iir == 0 && pm_iir == 0 && iir == 0)
 			goto out;
 
+		atomic_inc(&dev_priv->irq_received);
+
 		ret = IRQ_HANDLED;
 
 		snb_gt_irq_handler(dev, dev_priv, gt_iir);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 13/14] drm/i915: fix initial IRQ masking on VLV
  2012-06-15 18:55 [PATCH 01/14] drm/i915: ValleyView mode setting limits and PLL functions Jesse Barnes
                   ` (10 preceding siblings ...)
  2012-06-15 18:55 ` [PATCH 12/14] drm/i915: don't account for shared interrupts on VLV Jesse Barnes
@ 2012-06-15 18:55 ` Jesse Barnes
  2012-06-20 13:12   ` Daniel Vetter
  2012-06-15 18:55 ` [PATCH 14/14] drm/i915: bind driver to ValleyView chipsets Jesse Barnes
  12 siblings, 1 reply; 25+ messages in thread
From: Jesse Barnes @ 2012-06-15 18:55 UTC (permalink / raw)
  To: intel-gfx

We can leave vblank interrupts masked but enabled so we're not dependent
on the first client to toggle the disable timer.  We can also mask all
render based interrupts, since the ring code will handle unmasking them
for us.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_irq.c |   12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 36732f7..5c6c5e9 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1889,7 +1889,13 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
 		I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
 
-	dev_priv->irq_mask = ~enable_mask;
+	/*
+	 *Leave vblank interrupts masked initially.  enable/disable will
+	 * toggle them based on usage.
+	 */
+	dev_priv->irq_mask = (~enable_mask) |
+		I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
+		I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
 
 	dev_priv->pipestat[0] = 0;
 	dev_priv->pipestat[1] = 0;
@@ -1925,11 +1931,11 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
 		GT_SYNC_STATUS |
 		GT_USER_INTERRUPT;
 
-	dev_priv->gt_irq_mask = ~render_irqs;
+	dev_priv->gt_irq_mask = ~0;
 
 	I915_WRITE(GTIIR, I915_READ(GTIIR));
 	I915_WRITE(GTIIR, I915_READ(GTIIR));
-	I915_WRITE(GTIMR, 0);
+	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
 	I915_WRITE(GTIER, render_irqs);
 	POSTING_READ(GTIER);
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 14/14] drm/i915: bind driver to ValleyView chipsets
  2012-06-15 18:55 [PATCH 01/14] drm/i915: ValleyView mode setting limits and PLL functions Jesse Barnes
                   ` (11 preceding siblings ...)
  2012-06-15 18:55 ` [PATCH 13/14] drm/i915: fix initial IRQ masking on VLV Jesse Barnes
@ 2012-06-15 18:55 ` Jesse Barnes
  2012-06-20 13:20   ` Daniel Vetter
  12 siblings, 1 reply; 25+ messages in thread
From: Jesse Barnes @ 2012-06-15 18:55 UTC (permalink / raw)
  To: intel-gfx

With the code in place, we can bind the driver, should make bisect possible.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_drv.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 9e772bd..ae46c3d 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -352,6 +352,9 @@ static const struct pci_device_id pciidlist[] = {		/* aka */
 	INTEL_VGA_DEVICE(0x0406, &intel_haswell_m_info), /* GT1 mobile */
 	INTEL_VGA_DEVICE(0x0416, &intel_haswell_m_info), /* GT2 mobile */
 	INTEL_VGA_DEVICE(0x0c16, &intel_haswell_d_info), /* SDV */
+	INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info),
+	INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info),
+	INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info),
 	{0, 0, 0}
 };
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH 02/14] drm/i915: Enable DP panel power sequencing for ValleyView
  2012-06-15 18:55 ` [PATCH 02/14] drm/i915: Enable DP panel power sequencing for ValleyView Jesse Barnes
@ 2012-06-20 12:50   ` Daniel Vetter
  2012-06-20 15:33     ` Jesse Barnes
  0 siblings, 1 reply; 25+ messages in thread
From: Daniel Vetter @ 2012-06-20 12:50 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Beeresh G, intel-gfx

On Fri, Jun 15, 2012 at 11:55:14AM -0700, Jesse Barnes wrote:
> From: Shobhit Kumar <shobhit.kumar@intel.com>
> 
> VLV supports two dp panels, there are two set of panel power sequence
> registers which needed to be programmed based on the configured
> pipe. This patch add supports for the same
> 
> Acked-by: Acked-by: Ben Widawsky <ben@bwidawsk.net>
> Signed-off-by: Beeresh G <beeresh.g@intel.com>
> Reviewed-by: Vijay Purushothaman <vijay.a.purushothaman@intel.com>
> Reviewed-by: Jesse Barnes <jesse.barnes@intel.com>
> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>

I've dropped the code change below - this clearly needs a more complete
solution. Also, I still fail at getting access to vlv docs :(
-Daniel
> ---
>  drivers/gpu/drm/i915/i915_reg.h |   12 ++++++++++++
>  drivers/gpu/drm/i915/intel_dp.c |    8 +++++++-
>  2 files changed, 19 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 281446d..a9e9d92 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -3854,6 +3854,18 @@
>  
>  #define BLC_PWM_PCH_CTL2	0xc8254
>  
> +#define PIPEA_PP_STATUS         0x61200
> +#define PIPEA_PP_CONTROL        0x61204
> +#define PIPEA_PP_ON_DELAYS      0x61208
> +#define PIPEA_PP_OFF_DELAYS     0x6120c
> +#define PIPEA_PP_DIVISOR        0x61210
> +
> +#define PIPEB_PP_STATUS         0x61300
> +#define PIPEB_PP_CONTROL        0x61304
> +#define PIPEB_PP_ON_DELAYS      0x61308
> +#define PIPEB_PP_OFF_DELAYS     0x6130c
> +#define PIPEB_PP_DIVISOR        0x61310
> +
>  #define PCH_PP_STATUS		0xc7200
>  #define PCH_PP_CONTROL		0xc7204
>  #define  PANEL_UNLOCK_REGS	(0xabcd << 16)
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 6538c46..d59af24 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -342,7 +342,13 @@ static bool ironlake_edp_have_panel_power(struct intel_dp *intel_dp)
>  	struct drm_device *dev = intel_dp->base.base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  
> -	return (I915_READ(PCH_PP_STATUS) & PP_ON) != 0;
> +	if (IS_VALLEYVIEW(dev)) {
> +		if (I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT)
> +			return (I915_READ(PIPEB_PP_STATUS) & PP_ON) != 0;
> +		else
> +			return (I915_READ(PIPEA_PP_STATUS) & PP_ON) != 0;
> +	} else
> +		return (I915_READ(PCH_PP_STATUS) & PP_ON) != 0;
>  }
>  
>  static bool ironlake_edp_have_panel_vdd(struct intel_dp *intel_dp)
> -- 
> 1.7.9.5
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 07/14] agp/intel: allow cacheable and GDFT PTEs on ValleyView
  2012-06-15 18:55 ` [PATCH 07/14] agp/intel: allow cacheable and GDFT PTEs on ValleyView Jesse Barnes
@ 2012-06-20 12:57   ` Daniel Vetter
  2012-06-20 15:35     ` Jesse Barnes
  0 siblings, 1 reply; 25+ messages in thread
From: Daniel Vetter @ 2012-06-20 12:57 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx

On Fri, Jun 15, 2012 at 11:55:19AM -0700, Jesse Barnes wrote:
> The PTE format is similar to SNB, but we don't support an MLC and don't
> need chipset flushing.
> 
> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>

I have my questions whether this is right, given that MLC died for snb &
ivb, that ivb has grown a L3$ cache instead (which vlv seems to have, too)
and that the LLC bit here isn't actually LLC, but just means 'snoop cpu
caches'.

But I plan to burn this all with the heat of a thousands suns in my gtt
rework, so who cares ;-)
-Daniel

> ---
>  drivers/char/agp/intel-gtt.c |   11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
> index 1237e75..c1e2943 100644
> --- a/drivers/char/agp/intel-gtt.c
> +++ b/drivers/char/agp/intel-gtt.c
> @@ -1182,9 +1182,17 @@ static void gen6_write_entry(dma_addr_t addr, unsigned int entry,
>  static void valleyview_write_entry(dma_addr_t addr, unsigned int entry,
>  				   unsigned int flags)
>  {
> +	unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT;
> +	unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT;
>  	u32 pte_flags;
>  
> -	pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID;
> +	if (type_mask == AGP_USER_MEMORY)
> +		pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID;
> +	else {
> +		pte_flags = GEN6_PTE_LLC | I810_PTE_VALID;
> +		if (gfdt)
> +			pte_flags |= GEN6_PTE_GFDT;
> +	}
>  
>  	/* gen6 has bit11-4 for physical addr bit39-32 */
>  	addr |= (addr >> 28) & 0xff0;
> @@ -1379,7 +1387,6 @@ static const struct intel_gtt_driver valleyview_gtt_driver = {
>  	.write_entry = valleyview_write_entry,
>  	.dma_mask_size = 40,
>  	.check_flags = gen6_check_flags,
> -	.chipset_flush = i9xx_chipset_flush,
>  };
>  
>  /* Table to describe Intel GMCH and AGP/PCIE GART drivers.  At least one of
> -- 
> 1.7.9.5
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 13/14] drm/i915: fix initial IRQ masking on VLV
  2012-06-15 18:55 ` [PATCH 13/14] drm/i915: fix initial IRQ masking on VLV Jesse Barnes
@ 2012-06-20 13:12   ` Daniel Vetter
  0 siblings, 0 replies; 25+ messages in thread
From: Daniel Vetter @ 2012-06-20 13:12 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx

On Fri, Jun 15, 2012 at 11:55:25AM -0700, Jesse Barnes wrote:
> We can leave vblank interrupts masked but enabled so we're not dependent
> on the first client to toggle the disable timer.  We can also mask all
> render based interrupts, since the ring code will handle unmasking them
> for us.
> 
> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> ---
>  drivers/gpu/drm/i915/i915_irq.c |   12 +++++++++---
>  1 file changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 36732f7..5c6c5e9 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -1889,7 +1889,13 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
>  		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
>  		I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
>  
> -	dev_priv->irq_mask = ~enable_mask;
> +	/*
> +	 *Leave vblank interrupts masked initially.  enable/disable will
> +	 * toggle them based on usage.
> +	 */
> +	dev_priv->irq_mask = (~enable_mask) |
> +		I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
> +		I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
>  
>  	dev_priv->pipestat[0] = 0;
>  	dev_priv->pipestat[1] = 0;

Please squash this hunk here with the vlv pageflip patch - this little
fumble decently confused me while reviewing the patchflip patch.

> @@ -1925,11 +1931,11 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
>  		GT_SYNC_STATUS |
>  		GT_USER_INTERRUPT;
>  
> -	dev_priv->gt_irq_mask = ~render_irqs;
> +	dev_priv->gt_irq_mask = ~0;
>  
>  	I915_WRITE(GTIIR, I915_READ(GTIIR));
>  	I915_WRITE(GTIIR, I915_READ(GTIIR));
> -	I915_WRITE(GTIMR, 0);
> +	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
>  	I915_WRITE(GTIER, render_irqs);
>  	POSTING_READ(GTIER);

Presuming I haven't missed anything, render_irqs is now an unused
variable. Please also rip that out, but leave the gt_irq frobbing in a
separate patch.
-Daniel

>  
> -- 
> 1.7.9.5
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 09/14] drm/i915: enable display messages to GT on ValleyView
  2012-06-15 18:55 ` [PATCH 09/14] drm/i915: enable display messages to GT " Jesse Barnes
@ 2012-06-20 13:12   ` Daniel Vetter
  0 siblings, 0 replies; 25+ messages in thread
From: Daniel Vetter @ 2012-06-20 13:12 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx

On Fri, Jun 15, 2012 at 11:55:21AM -0700, Jesse Barnes wrote:
> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> ---
>  drivers/gpu/drm/i915/intel_pm.c |    7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index d0ce2a5..4fa1a78 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3474,6 +3474,13 @@ static void valleyview_init_clock_gating(struct drm_device *dev)
>  
>  	I915_WRITE(CACHE_MODE_1,
>  		   _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE));
> +
> +	/*
> +	 * On ValleyView, the GUnit needs to signal the GT
> +	 * when flip and other events complete.  So enable
> +	 * all the GUnit->GT interrupts here
> +	 */
> +	I915_WRITE(VLV_DPFLIPSTAT, 0x3f7f0000);

... can we have less magic here, please? Not that anyone but you seems to
have access to docs :(
-Daniel

>  }
>  
>  static void g4x_init_clock_gating(struct drm_device *dev)
> -- 
> 1.7.9.5
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 12/14] drm/i915: don't account for shared interrupts on VLV
  2012-06-15 18:55 ` [PATCH 12/14] drm/i915: don't account for shared interrupts on VLV Jesse Barnes
@ 2012-06-20 13:18   ` Daniel Vetter
       [not found]   ` <15842_1340198260_4FE1CD73_15842_15371_1_20120620131831.GJ7170@phenom.ffwll.local>
  1 sibling, 0 replies; 25+ messages in thread
From: Daniel Vetter @ 2012-06-20 13:18 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx

On Fri, Jun 15, 2012 at 11:55:24AM -0700, Jesse Barnes wrote:
> Only count interrupts we find came from the GPU.
> 
> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>

We have this on every generation's irq handler this way. I guess we should
either fix this everywhere or not bother with it. Dropped for now.
-Daniel

> ---
>  drivers/gpu/drm/i915/i915_irq.c |    4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 453ea7c..36732f7 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -515,8 +515,6 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)
>  	u32 pipe_stats[I915_MAX_PIPES];
>  	bool blc_event;
>  
> -	atomic_inc(&dev_priv->irq_received);
> -
>  	while (true) {
>  		iir = I915_READ(VLV_IIR);
>  		gt_iir = I915_READ(GTIIR);
> @@ -525,6 +523,8 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)
>  		if (gt_iir == 0 && pm_iir == 0 && iir == 0)
>  			goto out;
>  
> +		atomic_inc(&dev_priv->irq_received);
> +
>  		ret = IRQ_HANDLED;
>  
>  		snb_gt_irq_handler(dev, dev_priv, gt_iir);
> -- 
> 1.7.9.5
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 14/14] drm/i915: bind driver to ValleyView chipsets
  2012-06-15 18:55 ` [PATCH 14/14] drm/i915: bind driver to ValleyView chipsets Jesse Barnes
@ 2012-06-20 13:20   ` Daniel Vetter
  0 siblings, 0 replies; 25+ messages in thread
From: Daniel Vetter @ 2012-06-20 13:20 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx

On Fri, Jun 15, 2012 at 11:55:26AM -0700, Jesse Barnes wrote:
> With the code in place, we can bind the driver, should make bisect possible.
>
> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>

Ok, I've merged most of these patches, safe for the pageflip/irq stuff
(bikesheds dropped in separate mails) and obviously patch 14. Thanks
for the patches.
-Daniel

> ---
>  drivers/gpu/drm/i915/i915_drv.c |    3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 9e772bd..ae46c3d 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -352,6 +352,9 @@ static const struct pci_device_id pciidlist[] = {		/* aka */
>  	INTEL_VGA_DEVICE(0x0406, &intel_haswell_m_info), /* GT1 mobile */
>  	INTEL_VGA_DEVICE(0x0416, &intel_haswell_m_info), /* GT2 mobile */
>  	INTEL_VGA_DEVICE(0x0c16, &intel_haswell_d_info), /* SDV */
> +	INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info),
> +	INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info),
> +	INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info),
>  	{0, 0, 0}
>  };
>
> --
> 1.7.9.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 02/14] drm/i915: Enable DP panel power sequencing for ValleyView
  2012-06-20 12:50   ` Daniel Vetter
@ 2012-06-20 15:33     ` Jesse Barnes
  0 siblings, 0 replies; 25+ messages in thread
From: Jesse Barnes @ 2012-06-20 15:33 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Beeresh G, intel-gfx

On Wed, 20 Jun 2012 14:50:51 +0200
Daniel Vetter <daniel@ffwll.ch> wrote:

> On Fri, Jun 15, 2012 at 11:55:14AM -0700, Jesse Barnes wrote:
> > From: Shobhit Kumar <shobhit.kumar@intel.com>
> > 
> > VLV supports two dp panels, there are two set of panel power sequence
> > registers which needed to be programmed based on the configured
> > pipe. This patch add supports for the same
> > 
> > Acked-by: Acked-by: Ben Widawsky <ben@bwidawsk.net>
> > Signed-off-by: Beeresh G <beeresh.g@intel.com>
> > Reviewed-by: Vijay Purushothaman <vijay.a.purushothaman@intel.com>
> > Reviewed-by: Jesse Barnes <jesse.barnes@intel.com>
> > Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> 
> I've dropped the code change below - this clearly needs a more complete
> solution. Also, I still fail at getting access to vlv docs :(

Yeah sounds good.  I actually dropped it too in a local rebase.

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 07/14] agp/intel: allow cacheable and GDFT PTEs on ValleyView
  2012-06-20 12:57   ` Daniel Vetter
@ 2012-06-20 15:35     ` Jesse Barnes
  0 siblings, 0 replies; 25+ messages in thread
From: Jesse Barnes @ 2012-06-20 15:35 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Wed, 20 Jun 2012 14:57:17 +0200
Daniel Vetter <daniel@ffwll.ch> wrote:

> On Fri, Jun 15, 2012 at 11:55:19AM -0700, Jesse Barnes wrote:
> > The PTE format is similar to SNB, but we don't support an MLC and don't
> > need chipset flushing.
> > 
> > Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> 
> I have my questions whether this is right, given that MLC died for snb &
> ivb, that ivb has grown a L3$ cache instead (which vlv seems to have, too)
> and that the LLC bit here isn't actually LLC, but just means 'snoop cpu
> caches'.

Yeah I dropped the MLC part and didn't rename the LLC bit which might
be a little confusing, but afaict from the VLV docs this is correct and
actually works here (i.e. my last "cacheability is different" patch is
unneeded).

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v4] Added support for the ns2501 DVO
       [not found]   ` <15842_1340198260_4FE1CD73_15842_15371_1_20120620131831.GJ7170@phenom.ffwll.local>
@ 2012-06-20 17:41     ` Thomas Richter
  2012-06-20 18:03       ` Daniel Vetter
  0 siblings, 1 reply; 25+ messages in thread
From: Thomas Richter @ 2012-06-20 17:41 UTC (permalink / raw)
  To: intel-gfx, Daniel Vetter

This patch adds support for the ns2501 DVO, found in some older 
Fujitsu/Siemens Labtops. It is in the state of "works for me".
Includes now proper DPMS support. Includes switching between resolutions 
- from 640x480 to 1024x768. Currently assumes that the native display 
resolution is 1024x768.

The ns2501 seems to be rather critical - if the output PLL is not
running, the chip doesn't seem to be clocked and then doesn't react
on i2c messages. Thus, a quick'n-dirty trick ensures that the DVO
is active before submitting any i2c messages to it. This is
probably to be reviewed.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=17902

Signed-off-by: Thomas Richter <thor@math.tu-berlin.de>
---
  drivers/gpu/drm/i915/Makefile        |    1 +
  drivers/gpu/drm/i915/dvo.h           |    1 +
  drivers/gpu/drm/i915/dvo_ns2501.c    |  566 
++++++++++++++++++++++++++++++++++
  drivers/gpu/drm/i915/intel_display.c |    4 +-
  drivers/gpu/drm/i915/intel_dvo.c     |   10 +-
  5 files changed, 580 insertions(+), 2 deletions(-)
  create mode 100644 drivers/gpu/drm/i915/dvo_ns2501.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 2e9268d..8e8e41f 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -39,6 +39,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
  	  dvo_ivch.o \
  	  dvo_tfp410.o \
  	  dvo_sil164.o \
+	  dvo_ns2501.o \
  	  i915_gem_dmabuf.o

  i915-$(CONFIG_COMPAT)   += i915_ioc32.o
diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h
index 8c2ad01..a2af75c 100644
--- a/drivers/gpu/drm/i915/dvo.h
+++ b/drivers/gpu/drm/i915/dvo.h
@@ -140,5 +140,6 @@ extern struct intel_dvo_dev_ops ch7xxx_ops;
  extern struct intel_dvo_dev_ops ivch_ops;
  extern struct intel_dvo_dev_ops tfp410_ops;
  extern struct intel_dvo_dev_ops ch7017_ops;
+extern struct intel_dvo_dev_ops ns2501_ops;

  #endif /* _INTEL_DVO_H */
diff --git a/drivers/gpu/drm/i915/dvo_ns2501.c 
b/drivers/gpu/drm/i915/dvo_ns2501.c
new file mode 100644
index 0000000..1b15a23
--- /dev/null
+++ b/drivers/gpu/drm/i915/dvo_ns2501.c
@@ -0,0 +1,566 @@
+/**************************************************************************
+
+Copyright © 2012 Gilles Dartiguelongue, Thomas Richter
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include "dvo.h"
+#include "i915_reg.h"
+#include "i915_drv.h"
+
+#define NS2501_VID 0x1305
+#define NS2501_DID 0x6726
+
+#define NS2501_VID_LO 0x00
+#define NS2501_VID_HI 0x01
+#define NS2501_DID_LO 0x02
+#define NS2501_DID_HI 0x03
+#define NS2501_REV 0x04
+#define NS2501_RSVD 0x05
+#define NS2501_FREQ_LO 0x06
+#define NS2501_FREQ_HI 0x07
+
+#define NS2501_REG8 0x08
+#define NS2501_8_VEN (1<<5)
+#define NS2501_8_HEN (1<<4)
+#define NS2501_8_DSEL (1<<3)
+#define NS2501_8_BPAS (1<<2)
+#define NS2501_8_RSVD (1<<1)
+#define NS2501_8_PD (1<<0)
+
+#define NS2501_REG9 0x09
+#define NS2501_9_VLOW (1<<7)
+#define NS2501_9_MSEL_MASK (0x7<<4)
+#define NS2501_9_TSEL (1<<3)
+#define NS2501_9_RSEN (1<<2)
+#define NS2501_9_RSVD (1<<1)
+#define NS2501_9_MDI (1<<0)
+
+#define NS2501_REGC 0x0c
+
+struct ns2501_priv {
+  //I2CDevRec d;
+  bool quiet;
+  int reg_8_shadow;
+  int reg_8_set;
+  // Shadow registers for i915
+  int dvoc;
+  int pll_a;
+  int srcdim;
+  int fw_blc;
+};
+
+#define NSPTR(d) ((NS2501Ptr)(d->DriverPrivate.ptr))
+
+/*
+** Include the PLL launcher prototype
+*/
+extern void intel_enable_pll(struct drm_i915_private *dev_priv, enum 
pipe pipe);
+
+/*
+** For reasons unclear to me, the ns2501 at least on the Fujitsu/Siemens
+** laptops does not react on the i2c bus unless
+** both the PLL is running and the display is configured in its native
+** resolution.
+** This function forces the DVO on, and stores the registers it touches.
+** Afterwards, registers are restored to regular values.
+**
+** This is pretty much a hack, though it works.
+** Without that, ns2501_readb and ns2501_writeb fail
+** when switching the resolution.
+*/
+
+static void enable_dvo(struct intel_dvo_device *dvo)
+{
+  struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
+  struct i2c_adapter *adapter = dvo->i2c_bus;
+  struct intel_gmbus *bus     = container_of(adapter,
+                                             struct intel_gmbus,
+                                             adapter);
+  struct drm_i915_private *dev_priv = bus->dev_priv;
+
+  DRM_DEBUG_KMS("%s: Trying to re-enable the DVO\n",__FUNCTION__);
+
+  ns->dvoc   = I915_READ(DVO_C);
+  ns->pll_a  = I915_READ(_DPLL_A);
+  ns->srcdim = I915_READ(DVOC_SRCDIM);
+  ns->fw_blc = I915_READ(FW_BLC);
+
+  I915_WRITE(DVOC, 0x10004084);
+  I915_WRITE(_DPLL_A,0xd0820000);
+  I915_WRITE(DVOC_SRCDIM,0x400300); // 1024x768
+  I915_WRITE(FW_BLC,0x1080304);
+
+  intel_enable_pll(dev_priv,0);
+
+  I915_WRITE(DVOC, 0x90004084);
+}
+
+/*
+** Restore the I915 registers modified by the above
+** trigger function.
+*/
+static void restore_dvo(struct intel_dvo_device *dvo)
+{
+  struct i2c_adapter *adapter = dvo->i2c_bus;
+  struct intel_gmbus *bus     = container_of(adapter,
+                                             struct intel_gmbus,
+                                             adapter);
+  struct drm_i915_private *dev_priv = bus->dev_priv;
+  struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
+
+  I915_WRITE(DVOC       ,ns->dvoc);
+  I915_WRITE(_DPLL_A    ,ns->pll_a);
+  I915_WRITE(DVOC_SRCDIM,ns->srcdim);
+  I915_WRITE(FW_BLC     ,ns->fw_blc);
+}
+
+/*
+** Read a register from the ns2501.
+** Returns true if successful, false otherwise.
+** If it returns false, it might be wise to enable the
+** DVO with the above function.
+*/
+static bool ns2501_readb(struct intel_dvo_device *dvo, int addr, 
uint8_t *ch)
+{
+  struct ns2501_priv *ns = dvo->dev_priv;
+  struct i2c_adapter *adapter = dvo->i2c_bus;
+  u8 out_buf[2];
+  u8 in_buf[2];
+
+  struct i2c_msg msgs[] = {
+    {
+      .addr = dvo->slave_addr,
+      .flags = 0,
+      .len = 1,
+      .buf = out_buf,
+    },
+    {
+      .addr = dvo->slave_addr,
+      .flags = I2C_M_RD,
+      .len = 1,
+      .buf = in_buf,
+    }
+  };
+
+  out_buf[0] = addr;
+  out_buf[1] = 0;
+
+  if (i2c_transfer(adapter, msgs, 2) == 2) {
+    *ch = in_buf[0];
+    return true;
+  };
+
+  if (!ns->quiet) {
+    DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:0x%02x.\n",
+		  addr, adapter->name, dvo->slave_addr);
+  }
+
+  return false;
+}
+
+/*
+** Write a register to the ns2501.
+** Returns true if successful, false otherwise.
+** If it returns false, it might be wise to enable the
+** DVO with the above function.
+*/
+static bool ns2501_writeb(struct intel_dvo_device *dvo, int addr, 
uint8_t ch)
+{
+  struct ns2501_priv *ns = dvo->dev_priv;
+  struct i2c_adapter *adapter = dvo->i2c_bus;
+  uint8_t out_buf[2];
+
+  struct i2c_msg msg = {
+    .addr = dvo->slave_addr,
+    .flags = 0,
+    .len = 2,
+    .buf = out_buf,
+  };
+
+  out_buf[0] = addr;
+  out_buf[1] = ch;
+
+  if (i2c_transfer(adapter, &msg, 1) == 1) {
+    return true;
+  }
+
+  if (!ns->quiet) {
+    DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d\n",
+                  addr, adapter->name, dvo->slave_addr);
+  }
+
+  return false;
+}
+
+/* National Semiconductor 2501 driver for chip on i2c bus
+** scan for the chip on the bus.
+** Hope the VBIOS initialized the PLL correctly so we can
+** talk to it. If not, it will not be seen and not detected.
+** Bummer!
+*/
+static bool ns2501_init(struct intel_dvo_device *dvo,
+			struct i2c_adapter *adapter)
+{
+  /* this will detect the NS2501 chip on the specified i2c bus */
+  struct ns2501_priv *ns;
+  unsigned char ch;
+
+  ns = kzalloc(sizeof(struct ns2501_priv), GFP_KERNEL);
+  if (ns == NULL)
+    return false;
+
+  dvo->i2c_bus = adapter;
+  dvo->dev_priv = ns;
+  ns->quiet = true;
+
+  if (!ns2501_readb(dvo, NS2501_VID_LO, &ch))
+    goto out;
+
+  if (ch != (NS2501_VID & 0xff)) {
+    DRM_DEBUG_KMS("ns2501 not detected got %d: from %s Slave %d.\n",
+		  ch, adapter->name, dvo->slave_addr);
+    goto out;
+  }
+
+  if (!ns2501_readb(dvo, NS2501_DID_LO, &ch))
+    goto out;
+
+  if (ch != (NS2501_DID & 0xff)) {
+    DRM_DEBUG_KMS("ns2501 not detected got %d: from %s Slave %d.\n",
+		  ch, adapter->name, dvo->slave_addr);
+    goto out;
+  }
+  ns->quiet        = false;
+  ns->reg_8_set    = 0;
+  ns->reg_8_shadow = NS2501_8_PD | NS2501_8_BPAS | NS2501_8_VEN | 
NS2501_8_HEN;
+
+  DRM_DEBUG_KMS("init ns2501 dvo controller successfully!\n");
+  return true;
+
+ out:
+  kfree(ns);
+  return false;
+}
+
+static enum drm_connector_status ns2501_detect(struct intel_dvo_device 
*dvo)
+{
+  /*
+  ** This is a Laptop display, it doesn't have hotplugging.
+  ** Even if not, the detection bit of the 2501 is unreliable as
+  ** it only works for some display types.
+  ** It is even more unreliable as the PLL must be active for
+  ** allowing reading from the chiop.
+  */
+  return connector_status_connected;
+}
+
+static enum drm_mode_status ns2501_mode_valid(struct intel_dvo_device *dvo,
+					      struct drm_display_mode *mode)
+{
+  DRM_DEBUG_KMS("%s: is mode valid 
(hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d)\n",__FUNCTION__,
+		mode->hdisplay,mode->htotal,mode->vdisplay,mode->vtotal);
+
+
+  /*
+  ** Currently, these are all the modes I have data from.
+  ** More might exist. Unclear how to find the native resolution
+  ** of the panel in here so we could always accept it
+  ** by disabling the scaler.
+  */
+  if ((mode->hdisplay == 800 && mode->vdisplay == 600) ||
+      (mode->hdisplay == 640 && mode->vdisplay == 480) ||
+      (mode->hdisplay == 1024 && mode->vdisplay == 768)) {
+    return MODE_OK;
+  } else {
+    return MODE_ONE_SIZE; /* Is this a reasonable error? */
+  }
+}
+
+static void ns2501_mode_set(struct intel_dvo_device *dvo,
+			    struct drm_display_mode *mode,
+			    struct drm_display_mode *adjusted_mode)
+{
+  bool ok;
+  bool restore = false;
+  struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
+
+  DRM_DEBUG_KMS("%s: set mode 
(hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d).\n",__FUNCTION__,
+		mode->hdisplay,mode->htotal,mode->vdisplay,mode->vtotal);
+
+  /*
+  ** Where do I find the native resolution for which scaling is not 
required???
+  **
+  ** First trigger the DVO on as otherwise the chip does not appear on 
the i2c
+  ** bus.
+  */
+  do {
+    ok = true;
+
+    if (mode->hdisplay == 800 && mode->vdisplay == 600) {
+      /* mode 277 */
+      ns->reg_8_shadow &= ~NS2501_8_BPAS;
+      DRM_DEBUG_KMS("%s: switching to 800x600\n",__FUNCTION__);
+
+      /*
+      ** No, I do not know where this data comes from.
+      ** It is just what the video bios left in the DVO, so
+      ** I'm just copying it here over.
+      ** This also means that I cannot support any other modes
+      ** except the ones supported by the bios.
+      */
+      ok &= ns2501_writeb(dvo, 0x11, 0xc8); // 0xc7 also works.
+      ok &= ns2501_writeb(dvo, 0x1b, 0x19);
+      ok &= ns2501_writeb(dvo, 0x1c, 0x62); // VBIOS left 0x64 here, 
but 0x62 works nicer
+      ok &= ns2501_writeb(dvo, 0x1d, 0x02);
+
+      ok &= ns2501_writeb(dvo, 0x34, 0x03);
+      ok &= ns2501_writeb(dvo, 0x35, 0xff);
+
+      ok &= ns2501_writeb(dvo, 0x80, 0x27);
+      ok &= ns2501_writeb(dvo, 0x81, 0x03);
+      ok &= ns2501_writeb(dvo, 0x82, 0x41);
+      ok &= ns2501_writeb(dvo, 0x83, 0x05);
+
+      ok &= ns2501_writeb(dvo, 0x8d, 0x02);
+      ok &= ns2501_writeb(dvo, 0x8e, 0x04);
+      ok &= ns2501_writeb(dvo, 0x8f, 0x00);
+
+      ok &= ns2501_writeb(dvo, 0x90, 0xfe); /* vertical. VBIOS left 
0xff here, but 0xfe works better */
+      ok &= ns2501_writeb(dvo, 0x91, 0x07);
+      ok &= ns2501_writeb(dvo, 0x94, 0x00);
+      ok &= ns2501_writeb(dvo, 0x95, 0x00);
+
+      ok &= ns2501_writeb(dvo, 0x96, 0x00);
+
+      ok &= ns2501_writeb(dvo, 0x99, 0x00);
+      ok &= ns2501_writeb(dvo, 0x9a, 0x88);
+
+      ok &= ns2501_writeb(dvo, 0x9c, 0x23); /* Looks like first and 
last line of the image. */
+      ok &= ns2501_writeb(dvo, 0x9d, 0x00);
+      ok &= ns2501_writeb(dvo, 0x9e, 0x25);
+      ok &= ns2501_writeb(dvo, 0x9f, 0x03);
+
+      ok &= ns2501_writeb(dvo, 0xa4, 0x80);
+
+      ok &= ns2501_writeb(dvo, 0xb6, 0x00);
+
+      ok &= ns2501_writeb(dvo, 0xb9, 0xc8); /* horizontal? */
+      ok &= ns2501_writeb(dvo, 0xba, 0x00); /* horizontal? */
+
+      ok &= ns2501_writeb(dvo, 0xc0, 0x05); /* horizontal? */
+      ok &= ns2501_writeb(dvo, 0xc1, 0xd7);
+
+      ok &= ns2501_writeb(dvo, 0xc2, 0x00);
+      ok &= ns2501_writeb(dvo, 0xc3, 0xf8);
+
+      ok &= ns2501_writeb(dvo, 0xc4, 0x03);
+      ok &= ns2501_writeb(dvo, 0xc5, 0x1a);
+
+      ok &= ns2501_writeb(dvo, 0xc6, 0x00);
+      ok &= ns2501_writeb(dvo, 0xc7, 0x73);
+      ok &= ns2501_writeb(dvo, 0xc8, 0x02);
+
+    } else if (mode->hdisplay == 640 && mode->vdisplay == 480) {
+      /* mode 274 */
+      DRM_DEBUG_KMS("%s: switching to 640x480\n",__FUNCTION__);
+      /*
+      ** No, I do not know where this data comes from.
+      ** It is just what the video bios left in the DVO, so
+      ** I'm just copying it here over.
+      ** This also means that I cannot support any other modes
+      ** except the ones supported by the bios.
+      */
+      ns->reg_8_shadow &= ~NS2501_8_BPAS;
+
+      ok &= ns2501_writeb(dvo, 0x11, 0xa0);
+      ok &= ns2501_writeb(dvo, 0x1b, 0x11);
+      ok &= ns2501_writeb(dvo, 0x1c, 0x54);
+      ok &= ns2501_writeb(dvo, 0x1d, 0x03);
+
+      ok &= ns2501_writeb(dvo, 0x34, 0x03);
+      ok &= ns2501_writeb(dvo, 0x35, 0xff);
+
+      ok &= ns2501_writeb(dvo, 0x80, 0xff);
+      ok &= ns2501_writeb(dvo, 0x81, 0x07);
+      ok &= ns2501_writeb(dvo, 0x82, 0x3d);
+      ok &= ns2501_writeb(dvo, 0x83, 0x05);
+
+      ok &= ns2501_writeb(dvo, 0x8d, 0x02);
+      ok &= ns2501_writeb(dvo, 0x8e, 0x10);
+      ok &= ns2501_writeb(dvo, 0x8f, 0x00);
+
+      ok &= ns2501_writeb(dvo, 0x90, 0xff); /* vertical */
+      ok &= ns2501_writeb(dvo, 0x91, 0x07);
+      ok &= ns2501_writeb(dvo, 0x94, 0x00);
+      ok &= ns2501_writeb(dvo, 0x95, 0x00);
+
+      ok &= ns2501_writeb(dvo, 0x96, 0x05);
+
+      ok &= ns2501_writeb(dvo, 0x99, 0x00);
+      ok &= ns2501_writeb(dvo, 0x9a, 0x88);
+
+      ok &= ns2501_writeb(dvo, 0x9c, 0x24);
+      ok &= ns2501_writeb(dvo, 0x9d, 0x00);
+      ok &= ns2501_writeb(dvo, 0x9e, 0x25);
+      ok &= ns2501_writeb(dvo, 0x9f, 0x03);
+
+      ok &= ns2501_writeb(dvo, 0xa4, 0x84);
+
+      ok &= ns2501_writeb(dvo, 0xb6, 0x09);
+
+      ok &= ns2501_writeb(dvo, 0xb9, 0xa0); /* horizontal? */
+      ok &= ns2501_writeb(dvo, 0xba, 0x00); /* horizontal? */
+
+      ok &= ns2501_writeb(dvo, 0xc0, 0x05); /* horizontal? */
+      ok &= ns2501_writeb(dvo, 0xc1, 0x90);
+
+      ok &= ns2501_writeb(dvo, 0xc2, 0x00);
+      ok &= ns2501_writeb(dvo, 0xc3, 0x0f);
+
+      ok &= ns2501_writeb(dvo, 0xc4, 0x03);
+      ok &= ns2501_writeb(dvo, 0xc5, 0x16);
+
+      ok &= ns2501_writeb(dvo, 0xc6, 0x00);
+      ok &= ns2501_writeb(dvo, 0xc7, 0x02);
+      ok &= ns2501_writeb(dvo, 0xc8, 0x02);
+
+    } else if (mode->hdisplay == 1024 && mode->vdisplay == 768) {
+      /* mode 280 */
+      DRM_DEBUG_KMS("%s: switching to 1024x768\n",__FUNCTION__);
+      /*
+      ** This might or might not work, actually. I'm silently
+      ** assuming here that the native panel resolution is
+      ** 1024x768. If not, then this leaves the scaler disabled
+      ** generating a picture that is likely not the expected.
+      **
+      ** Problem is that I do not know where to take the panel
+      ** dimensions from.
+      **
+      ** Enable the bypass, scaling not required.
+      **
+      ** The scaler registers are irrelevant here....
+      **
+      */
+      ns->reg_8_shadow |= NS2501_8_BPAS;
+      ok &= ns2501_writeb(dvo, 0x37, 0x44);
+    } else {
+      /* Data not known. Bummer!
+      ** Hopefully, the code should not go here
+      ** as mode_OK delivered no other modes.
+      */
+      ns->reg_8_shadow |= NS2501_8_BPAS;
+    }
+    ok &= ns2501_writeb(dvo, NS2501_REG8, ns->reg_8_shadow);
+
+    if (!ok) {
+      if (restore)
+	restore_dvo(dvo);
+      enable_dvo(dvo);
+      restore = true;
+    }
+  } while(!ok);
+  /*
+  ** Restore the old i915 registers before
+  ** forcing the ns2501 on.
+  */
+  if (restore)
+    restore_dvo(dvo);
+}
+
+/* set the NS2501 power state */
+static void ns2501_dpms(struct intel_dvo_device *dvo, int mode)
+{
+  bool ok;
+  bool restore = false;
+  struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
+  unsigned char ch;
+
+  DRM_DEBUG_KMS("%s: Trying set the dpms of the DVO to 
%d\n",__FUNCTION__,mode);
+
+  ch = ns->reg_8_shadow;
+
+  if (mode == DRM_MODE_DPMS_ON)
+    ch |= NS2501_8_PD;
+  else
+    ch &= ~NS2501_8_PD;
+
+  if (ns->reg_8_set == 0 || ns->reg_8_shadow != ch) {
+    ns->reg_8_set    = 1;
+    ns->reg_8_shadow = ch;
+
+    do {
+      ok = true;
+      ok &= ns2501_writeb(dvo, NS2501_REG8, ch);
+      ok &= ns2501_writeb(dvo, 0x34       ,(mode == 
DRM_MODE_DPMS_ON)?(0x03):(0x00));
+      ok &= ns2501_writeb(dvo, 0x35       ,(mode == 
DRM_MODE_DPMS_ON)?(0xff):(0x00));
+      if (!ok) {
+	if (restore)
+	  restore_dvo(dvo);
+	enable_dvo(dvo);
+	restore = true;
+      }
+    } while(!ok);
+
+    if (restore)
+      restore_dvo(dvo);
+  }
+}
+
+static void ns2501_dump_regs(struct intel_dvo_device *dvo)
+{
+  uint8_t val;
+
+  ns2501_readb(dvo, NS2501_FREQ_LO, &val);
+  DRM_LOG_KMS("NS2501_FREQ_LO: 0x%02x\n", val);
+  ns2501_readb(dvo, NS2501_FREQ_HI, &val);
+  DRM_LOG_KMS("NS2501_FREQ_HI: 0x%02x\n", val);
+  ns2501_readb(dvo, NS2501_REG8, &val);
+  DRM_LOG_KMS("NS2501_REG8: 0x%02x\n", val);
+  ns2501_readb(dvo, NS2501_REG9, &val);
+  DRM_LOG_KMS("NS2501_REG9: 0x%02x\n", val);
+  ns2501_readb(dvo, NS2501_REGC, &val);
+  DRM_LOG_KMS("NS2501_REGC: 0x%02x\n", val);
+}
+
+static void ns2501_destroy(struct intel_dvo_device *dvo)
+{
+  struct ns2501_priv *ns = dvo->dev_priv;
+
+  if (ns) {
+    kfree(ns);
+    dvo->dev_priv = NULL;
+  }
+}
+
+struct intel_dvo_dev_ops ns2501_ops = {
+  .init = ns2501_init,
+  .detect = ns2501_detect,
+  .mode_valid = ns2501_mode_valid,
+  .mode_set = ns2501_mode_set,
+  .dpms = ns2501_dpms,
+  .dump_regs = ns2501_dump_regs,
+  .destroy = ns2501_destroy,
+};
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 0161d94..70b83a1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1280,8 +1280,10 @@ static void assert_pch_ports_disabled(struct 
drm_i915_private *dev_priv,
   * protect mechanism may be enabled.
   *
   * Note!  This is for pre-ILK only.
+ *
+ * Unfortunately needed by dvo_ns2501 since the dvo depends on it running.
   */
-static void intel_enable_pll(struct drm_i915_private *dev_priv, enum 
pipe pipe)
+void intel_enable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
  {
  	int reg;
  	u32 val;
diff --git a/drivers/gpu/drm/i915/intel_dvo.c 
b/drivers/gpu/drm/i915/intel_dvo.c
index 60ba50b9..68c1893 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -37,6 +37,7 @@
  #define SIL164_ADDR	0x38
  #define CH7xxx_ADDR	0x76
  #define TFP410_ADDR	0x38
+#define NS2501_ADDR     0x38

  static const struct intel_dvo_device intel_dvo_devices[] = {
  	{
@@ -74,7 +75,14 @@ static const struct intel_dvo_device 
intel_dvo_devices[] = {
  		.slave_addr = 0x75,
  		.gpio = GMBUS_PORT_DPB,
  		.dev_ops = &ch7017_ops,
-	}
+	},
+	{
+	        .type = INTEL_DVO_CHIP_TMDS,
+		.name = "ns2501",
+		.dvo_reg = DVOC,
+		.slave_addr = NS2501_ADDR,
+		.dev_ops = &ns2501_ops,
+       }
  };

  struct intel_dvo {
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH v4] Added support for the ns2501 DVO
  2012-06-20 17:41     ` [PATCH v4] Added support for the ns2501 DVO Thomas Richter
@ 2012-06-20 18:03       ` Daniel Vetter
  2012-06-20 22:35         ` Paul Menzel
  0 siblings, 1 reply; 25+ messages in thread
From: Daniel Vetter @ 2012-06-20 18:03 UTC (permalink / raw)
  To: Thomas Richter; +Cc: intel-gfx

On Wed, Jun 20, 2012 at 07:41:51PM +0200, Thomas Richter wrote:
> This patch adds support for the ns2501 DVO, found in some older
> Fujitsu/Siemens Labtops. It is in the state of "works for me".
> Includes now proper DPMS support. Includes switching between
> resolutions - from 640x480 to 1024x768. Currently assumes that the
> native display resolution is 1024x768.
> 
> The ns2501 seems to be rather critical - if the output PLL is not
> running, the chip doesn't seem to be clocked and then doesn't react
> on i2c messages. Thus, a quick'n-dirty trick ensures that the DVO
> is active before submitting any i2c messages to it. This is
> probably to be reviewed.
> 
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=17902
> 
> Signed-off-by: Thomas Richter <thor@math.tu-berlin.de>

Patch is still massively whitespace-mangling. Just export it to a file
with

git format-patch -1 HEAD

and then attach that file, please.
-Daniel

> ---
>  drivers/gpu/drm/i915/Makefile        |    1 +
>  drivers/gpu/drm/i915/dvo.h           |    1 +
>  drivers/gpu/drm/i915/dvo_ns2501.c    |  566
> ++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_display.c |    4 +-
>  drivers/gpu/drm/i915/intel_dvo.c     |   10 +-
>  5 files changed, 580 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/dvo_ns2501.c
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 2e9268d..8e8e41f 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -39,6 +39,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
>  	  dvo_ivch.o \
>  	  dvo_tfp410.o \
>  	  dvo_sil164.o \
> +	  dvo_ns2501.o \
>  	  i915_gem_dmabuf.o
> 
>  i915-$(CONFIG_COMPAT)   += i915_ioc32.o
> diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h
> index 8c2ad01..a2af75c 100644
> --- a/drivers/gpu/drm/i915/dvo.h
> +++ b/drivers/gpu/drm/i915/dvo.h
> @@ -140,5 +140,6 @@ extern struct intel_dvo_dev_ops ch7xxx_ops;
>  extern struct intel_dvo_dev_ops ivch_ops;
>  extern struct intel_dvo_dev_ops tfp410_ops;
>  extern struct intel_dvo_dev_ops ch7017_ops;
> +extern struct intel_dvo_dev_ops ns2501_ops;
> 
>  #endif /* _INTEL_DVO_H */
> diff --git a/drivers/gpu/drm/i915/dvo_ns2501.c
> b/drivers/gpu/drm/i915/dvo_ns2501.c
> new file mode 100644
> index 0000000..1b15a23
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/dvo_ns2501.c
> @@ -0,0 +1,566 @@
> +/**************************************************************************
> +
> +Copyright © 2012 Gilles Dartiguelongue, Thomas Richter
> +
> +All Rights Reserved.
> +
> +Permission is hereby granted, free of charge, to any person obtaining a
> +copy of this software and associated documentation files (the
> +"Software"), to deal in the Software without restriction, including
> +without limitation the rights to use, copy, modify, merge, publish,
> +distribute, sub license, and/or sell copies of the Software, and to
> +permit persons to whom the Software is furnished to do so, subject to
> +the following conditions:
> +
> +The above copyright notice and this permission notice (including the
> +next paragraph) shall be included in all copies or substantial portions
> +of the Software.
> +
> +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
> +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
> +
> +**************************************************************************/
> +
> +#include "dvo.h"
> +#include "i915_reg.h"
> +#include "i915_drv.h"
> +
> +#define NS2501_VID 0x1305
> +#define NS2501_DID 0x6726
> +
> +#define NS2501_VID_LO 0x00
> +#define NS2501_VID_HI 0x01
> +#define NS2501_DID_LO 0x02
> +#define NS2501_DID_HI 0x03
> +#define NS2501_REV 0x04
> +#define NS2501_RSVD 0x05
> +#define NS2501_FREQ_LO 0x06
> +#define NS2501_FREQ_HI 0x07
> +
> +#define NS2501_REG8 0x08
> +#define NS2501_8_VEN (1<<5)
> +#define NS2501_8_HEN (1<<4)
> +#define NS2501_8_DSEL (1<<3)
> +#define NS2501_8_BPAS (1<<2)
> +#define NS2501_8_RSVD (1<<1)
> +#define NS2501_8_PD (1<<0)
> +
> +#define NS2501_REG9 0x09
> +#define NS2501_9_VLOW (1<<7)
> +#define NS2501_9_MSEL_MASK (0x7<<4)
> +#define NS2501_9_TSEL (1<<3)
> +#define NS2501_9_RSEN (1<<2)
> +#define NS2501_9_RSVD (1<<1)
> +#define NS2501_9_MDI (1<<0)
> +
> +#define NS2501_REGC 0x0c
> +
> +struct ns2501_priv {
> +  //I2CDevRec d;
> +  bool quiet;
> +  int reg_8_shadow;
> +  int reg_8_set;
> +  // Shadow registers for i915
> +  int dvoc;
> +  int pll_a;
> +  int srcdim;
> +  int fw_blc;
> +};
> +
> +#define NSPTR(d) ((NS2501Ptr)(d->DriverPrivate.ptr))
> +
> +/*
> +** Include the PLL launcher prototype
> +*/
> +extern void intel_enable_pll(struct drm_i915_private *dev_priv,
> enum pipe pipe);
> +
> +/*
> +** For reasons unclear to me, the ns2501 at least on the Fujitsu/Siemens
> +** laptops does not react on the i2c bus unless
> +** both the PLL is running and the display is configured in its native
> +** resolution.
> +** This function forces the DVO on, and stores the registers it touches.
> +** Afterwards, registers are restored to regular values.
> +**
> +** This is pretty much a hack, though it works.
> +** Without that, ns2501_readb and ns2501_writeb fail
> +** when switching the resolution.
> +*/
> +
> +static void enable_dvo(struct intel_dvo_device *dvo)
> +{
> +  struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
> +  struct i2c_adapter *adapter = dvo->i2c_bus;
> +  struct intel_gmbus *bus     = container_of(adapter,
> +                                             struct intel_gmbus,
> +                                             adapter);
> +  struct drm_i915_private *dev_priv = bus->dev_priv;
> +
> +  DRM_DEBUG_KMS("%s: Trying to re-enable the DVO\n",__FUNCTION__);
> +
> +  ns->dvoc   = I915_READ(DVO_C);
> +  ns->pll_a  = I915_READ(_DPLL_A);
> +  ns->srcdim = I915_READ(DVOC_SRCDIM);
> +  ns->fw_blc = I915_READ(FW_BLC);
> +
> +  I915_WRITE(DVOC, 0x10004084);
> +  I915_WRITE(_DPLL_A,0xd0820000);
> +  I915_WRITE(DVOC_SRCDIM,0x400300); // 1024x768
> +  I915_WRITE(FW_BLC,0x1080304);
> +
> +  intel_enable_pll(dev_priv,0);
> +
> +  I915_WRITE(DVOC, 0x90004084);
> +}
> +
> +/*
> +** Restore the I915 registers modified by the above
> +** trigger function.
> +*/
> +static void restore_dvo(struct intel_dvo_device *dvo)
> +{
> +  struct i2c_adapter *adapter = dvo->i2c_bus;
> +  struct intel_gmbus *bus     = container_of(adapter,
> +                                             struct intel_gmbus,
> +                                             adapter);
> +  struct drm_i915_private *dev_priv = bus->dev_priv;
> +  struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
> +
> +  I915_WRITE(DVOC       ,ns->dvoc);
> +  I915_WRITE(_DPLL_A    ,ns->pll_a);
> +  I915_WRITE(DVOC_SRCDIM,ns->srcdim);
> +  I915_WRITE(FW_BLC     ,ns->fw_blc);
> +}
> +
> +/*
> +** Read a register from the ns2501.
> +** Returns true if successful, false otherwise.
> +** If it returns false, it might be wise to enable the
> +** DVO with the above function.
> +*/
> +static bool ns2501_readb(struct intel_dvo_device *dvo, int addr,
> uint8_t *ch)
> +{
> +  struct ns2501_priv *ns = dvo->dev_priv;
> +  struct i2c_adapter *adapter = dvo->i2c_bus;
> +  u8 out_buf[2];
> +  u8 in_buf[2];
> +
> +  struct i2c_msg msgs[] = {
> +    {
> +      .addr = dvo->slave_addr,
> +      .flags = 0,
> +      .len = 1,
> +      .buf = out_buf,
> +    },
> +    {
> +      .addr = dvo->slave_addr,
> +      .flags = I2C_M_RD,
> +      .len = 1,
> +      .buf = in_buf,
> +    }
> +  };
> +
> +  out_buf[0] = addr;
> +  out_buf[1] = 0;
> +
> +  if (i2c_transfer(adapter, msgs, 2) == 2) {
> +    *ch = in_buf[0];
> +    return true;
> +  };
> +
> +  if (!ns->quiet) {
> +    DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:0x%02x.\n",
> +		  addr, adapter->name, dvo->slave_addr);
> +  }
> +
> +  return false;
> +}
> +
> +/*
> +** Write a register to the ns2501.
> +** Returns true if successful, false otherwise.
> +** If it returns false, it might be wise to enable the
> +** DVO with the above function.
> +*/
> +static bool ns2501_writeb(struct intel_dvo_device *dvo, int addr,
> uint8_t ch)
> +{
> +  struct ns2501_priv *ns = dvo->dev_priv;
> +  struct i2c_adapter *adapter = dvo->i2c_bus;
> +  uint8_t out_buf[2];
> +
> +  struct i2c_msg msg = {
> +    .addr = dvo->slave_addr,
> +    .flags = 0,
> +    .len = 2,
> +    .buf = out_buf,
> +  };
> +
> +  out_buf[0] = addr;
> +  out_buf[1] = ch;
> +
> +  if (i2c_transfer(adapter, &msg, 1) == 1) {
> +    return true;
> +  }
> +
> +  if (!ns->quiet) {
> +    DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d\n",
> +                  addr, adapter->name, dvo->slave_addr);
> +  }
> +
> +  return false;
> +}
> +
> +/* National Semiconductor 2501 driver for chip on i2c bus
> +** scan for the chip on the bus.
> +** Hope the VBIOS initialized the PLL correctly so we can
> +** talk to it. If not, it will not be seen and not detected.
> +** Bummer!
> +*/
> +static bool ns2501_init(struct intel_dvo_device *dvo,
> +			struct i2c_adapter *adapter)
> +{
> +  /* this will detect the NS2501 chip on the specified i2c bus */
> +  struct ns2501_priv *ns;
> +  unsigned char ch;
> +
> +  ns = kzalloc(sizeof(struct ns2501_priv), GFP_KERNEL);
> +  if (ns == NULL)
> +    return false;
> +
> +  dvo->i2c_bus = adapter;
> +  dvo->dev_priv = ns;
> +  ns->quiet = true;
> +
> +  if (!ns2501_readb(dvo, NS2501_VID_LO, &ch))
> +    goto out;
> +
> +  if (ch != (NS2501_VID & 0xff)) {
> +    DRM_DEBUG_KMS("ns2501 not detected got %d: from %s Slave %d.\n",
> +		  ch, adapter->name, dvo->slave_addr);
> +    goto out;
> +  }
> +
> +  if (!ns2501_readb(dvo, NS2501_DID_LO, &ch))
> +    goto out;
> +
> +  if (ch != (NS2501_DID & 0xff)) {
> +    DRM_DEBUG_KMS("ns2501 not detected got %d: from %s Slave %d.\n",
> +		  ch, adapter->name, dvo->slave_addr);
> +    goto out;
> +  }
> +  ns->quiet        = false;
> +  ns->reg_8_set    = 0;
> +  ns->reg_8_shadow = NS2501_8_PD | NS2501_8_BPAS | NS2501_8_VEN |
> NS2501_8_HEN;
> +
> +  DRM_DEBUG_KMS("init ns2501 dvo controller successfully!\n");
> +  return true;
> +
> + out:
> +  kfree(ns);
> +  return false;
> +}
> +
> +static enum drm_connector_status ns2501_detect(struct
> intel_dvo_device *dvo)
> +{
> +  /*
> +  ** This is a Laptop display, it doesn't have hotplugging.
> +  ** Even if not, the detection bit of the 2501 is unreliable as
> +  ** it only works for some display types.
> +  ** It is even more unreliable as the PLL must be active for
> +  ** allowing reading from the chiop.
> +  */
> +  return connector_status_connected;
> +}
> +
> +static enum drm_mode_status ns2501_mode_valid(struct intel_dvo_device *dvo,
> +					      struct drm_display_mode *mode)
> +{
> +  DRM_DEBUG_KMS("%s: is mode valid
> (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d)\n",__FUNCTION__,
> +		mode->hdisplay,mode->htotal,mode->vdisplay,mode->vtotal);
> +
> +
> +  /*
> +  ** Currently, these are all the modes I have data from.
> +  ** More might exist. Unclear how to find the native resolution
> +  ** of the panel in here so we could always accept it
> +  ** by disabling the scaler.
> +  */
> +  if ((mode->hdisplay == 800 && mode->vdisplay == 600) ||
> +      (mode->hdisplay == 640 && mode->vdisplay == 480) ||
> +      (mode->hdisplay == 1024 && mode->vdisplay == 768)) {
> +    return MODE_OK;
> +  } else {
> +    return MODE_ONE_SIZE; /* Is this a reasonable error? */
> +  }
> +}
> +
> +static void ns2501_mode_set(struct intel_dvo_device *dvo,
> +			    struct drm_display_mode *mode,
> +			    struct drm_display_mode *adjusted_mode)
> +{
> +  bool ok;
> +  bool restore = false;
> +  struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
> +
> +  DRM_DEBUG_KMS("%s: set mode
> (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d).\n",__FUNCTION__,
> +		mode->hdisplay,mode->htotal,mode->vdisplay,mode->vtotal);
> +
> +  /*
> +  ** Where do I find the native resolution for which scaling is not
> required???
> +  **
> +  ** First trigger the DVO on as otherwise the chip does not appear
> on the i2c
> +  ** bus.
> +  */
> +  do {
> +    ok = true;
> +
> +    if (mode->hdisplay == 800 && mode->vdisplay == 600) {
> +      /* mode 277 */
> +      ns->reg_8_shadow &= ~NS2501_8_BPAS;
> +      DRM_DEBUG_KMS("%s: switching to 800x600\n",__FUNCTION__);
> +
> +      /*
> +      ** No, I do not know where this data comes from.
> +      ** It is just what the video bios left in the DVO, so
> +      ** I'm just copying it here over.
> +      ** This also means that I cannot support any other modes
> +      ** except the ones supported by the bios.
> +      */
> +      ok &= ns2501_writeb(dvo, 0x11, 0xc8); // 0xc7 also works.
> +      ok &= ns2501_writeb(dvo, 0x1b, 0x19);
> +      ok &= ns2501_writeb(dvo, 0x1c, 0x62); // VBIOS left 0x64
> here, but 0x62 works nicer
> +      ok &= ns2501_writeb(dvo, 0x1d, 0x02);
> +
> +      ok &= ns2501_writeb(dvo, 0x34, 0x03);
> +      ok &= ns2501_writeb(dvo, 0x35, 0xff);
> +
> +      ok &= ns2501_writeb(dvo, 0x80, 0x27);
> +      ok &= ns2501_writeb(dvo, 0x81, 0x03);
> +      ok &= ns2501_writeb(dvo, 0x82, 0x41);
> +      ok &= ns2501_writeb(dvo, 0x83, 0x05);
> +
> +      ok &= ns2501_writeb(dvo, 0x8d, 0x02);
> +      ok &= ns2501_writeb(dvo, 0x8e, 0x04);
> +      ok &= ns2501_writeb(dvo, 0x8f, 0x00);
> +
> +      ok &= ns2501_writeb(dvo, 0x90, 0xfe); /* vertical. VBIOS left
> 0xff here, but 0xfe works better */
> +      ok &= ns2501_writeb(dvo, 0x91, 0x07);
> +      ok &= ns2501_writeb(dvo, 0x94, 0x00);
> +      ok &= ns2501_writeb(dvo, 0x95, 0x00);
> +
> +      ok &= ns2501_writeb(dvo, 0x96, 0x00);
> +
> +      ok &= ns2501_writeb(dvo, 0x99, 0x00);
> +      ok &= ns2501_writeb(dvo, 0x9a, 0x88);
> +
> +      ok &= ns2501_writeb(dvo, 0x9c, 0x23); /* Looks like first and
> last line of the image. */
> +      ok &= ns2501_writeb(dvo, 0x9d, 0x00);
> +      ok &= ns2501_writeb(dvo, 0x9e, 0x25);
> +      ok &= ns2501_writeb(dvo, 0x9f, 0x03);
> +
> +      ok &= ns2501_writeb(dvo, 0xa4, 0x80);
> +
> +      ok &= ns2501_writeb(dvo, 0xb6, 0x00);
> +
> +      ok &= ns2501_writeb(dvo, 0xb9, 0xc8); /* horizontal? */
> +      ok &= ns2501_writeb(dvo, 0xba, 0x00); /* horizontal? */
> +
> +      ok &= ns2501_writeb(dvo, 0xc0, 0x05); /* horizontal? */
> +      ok &= ns2501_writeb(dvo, 0xc1, 0xd7);
> +
> +      ok &= ns2501_writeb(dvo, 0xc2, 0x00);
> +      ok &= ns2501_writeb(dvo, 0xc3, 0xf8);
> +
> +      ok &= ns2501_writeb(dvo, 0xc4, 0x03);
> +      ok &= ns2501_writeb(dvo, 0xc5, 0x1a);
> +
> +      ok &= ns2501_writeb(dvo, 0xc6, 0x00);
> +      ok &= ns2501_writeb(dvo, 0xc7, 0x73);
> +      ok &= ns2501_writeb(dvo, 0xc8, 0x02);
> +
> +    } else if (mode->hdisplay == 640 && mode->vdisplay == 480) {
> +      /* mode 274 */
> +      DRM_DEBUG_KMS("%s: switching to 640x480\n",__FUNCTION__);
> +      /*
> +      ** No, I do not know where this data comes from.
> +      ** It is just what the video bios left in the DVO, so
> +      ** I'm just copying it here over.
> +      ** This also means that I cannot support any other modes
> +      ** except the ones supported by the bios.
> +      */
> +      ns->reg_8_shadow &= ~NS2501_8_BPAS;
> +
> +      ok &= ns2501_writeb(dvo, 0x11, 0xa0);
> +      ok &= ns2501_writeb(dvo, 0x1b, 0x11);
> +      ok &= ns2501_writeb(dvo, 0x1c, 0x54);
> +      ok &= ns2501_writeb(dvo, 0x1d, 0x03);
> +
> +      ok &= ns2501_writeb(dvo, 0x34, 0x03);
> +      ok &= ns2501_writeb(dvo, 0x35, 0xff);
> +
> +      ok &= ns2501_writeb(dvo, 0x80, 0xff);
> +      ok &= ns2501_writeb(dvo, 0x81, 0x07);
> +      ok &= ns2501_writeb(dvo, 0x82, 0x3d);
> +      ok &= ns2501_writeb(dvo, 0x83, 0x05);
> +
> +      ok &= ns2501_writeb(dvo, 0x8d, 0x02);
> +      ok &= ns2501_writeb(dvo, 0x8e, 0x10);
> +      ok &= ns2501_writeb(dvo, 0x8f, 0x00);
> +
> +      ok &= ns2501_writeb(dvo, 0x90, 0xff); /* vertical */
> +      ok &= ns2501_writeb(dvo, 0x91, 0x07);
> +      ok &= ns2501_writeb(dvo, 0x94, 0x00);
> +      ok &= ns2501_writeb(dvo, 0x95, 0x00);
> +
> +      ok &= ns2501_writeb(dvo, 0x96, 0x05);
> +
> +      ok &= ns2501_writeb(dvo, 0x99, 0x00);
> +      ok &= ns2501_writeb(dvo, 0x9a, 0x88);
> +
> +      ok &= ns2501_writeb(dvo, 0x9c, 0x24);
> +      ok &= ns2501_writeb(dvo, 0x9d, 0x00);
> +      ok &= ns2501_writeb(dvo, 0x9e, 0x25);
> +      ok &= ns2501_writeb(dvo, 0x9f, 0x03);
> +
> +      ok &= ns2501_writeb(dvo, 0xa4, 0x84);
> +
> +      ok &= ns2501_writeb(dvo, 0xb6, 0x09);
> +
> +      ok &= ns2501_writeb(dvo, 0xb9, 0xa0); /* horizontal? */
> +      ok &= ns2501_writeb(dvo, 0xba, 0x00); /* horizontal? */
> +
> +      ok &= ns2501_writeb(dvo, 0xc0, 0x05); /* horizontal? */
> +      ok &= ns2501_writeb(dvo, 0xc1, 0x90);
> +
> +      ok &= ns2501_writeb(dvo, 0xc2, 0x00);
> +      ok &= ns2501_writeb(dvo, 0xc3, 0x0f);
> +
> +      ok &= ns2501_writeb(dvo, 0xc4, 0x03);
> +      ok &= ns2501_writeb(dvo, 0xc5, 0x16);
> +
> +      ok &= ns2501_writeb(dvo, 0xc6, 0x00);
> +      ok &= ns2501_writeb(dvo, 0xc7, 0x02);
> +      ok &= ns2501_writeb(dvo, 0xc8, 0x02);
> +
> +    } else if (mode->hdisplay == 1024 && mode->vdisplay == 768) {
> +      /* mode 280 */
> +      DRM_DEBUG_KMS("%s: switching to 1024x768\n",__FUNCTION__);
> +      /*
> +      ** This might or might not work, actually. I'm silently
> +      ** assuming here that the native panel resolution is
> +      ** 1024x768. If not, then this leaves the scaler disabled
> +      ** generating a picture that is likely not the expected.
> +      **
> +      ** Problem is that I do not know where to take the panel
> +      ** dimensions from.
> +      **
> +      ** Enable the bypass, scaling not required.
> +      **
> +      ** The scaler registers are irrelevant here....
> +      **
> +      */
> +      ns->reg_8_shadow |= NS2501_8_BPAS;
> +      ok &= ns2501_writeb(dvo, 0x37, 0x44);
> +    } else {
> +      /* Data not known. Bummer!
> +      ** Hopefully, the code should not go here
> +      ** as mode_OK delivered no other modes.
> +      */
> +      ns->reg_8_shadow |= NS2501_8_BPAS;
> +    }
> +    ok &= ns2501_writeb(dvo, NS2501_REG8, ns->reg_8_shadow);
> +
> +    if (!ok) {
> +      if (restore)
> +	restore_dvo(dvo);
> +      enable_dvo(dvo);
> +      restore = true;
> +    }
> +  } while(!ok);
> +  /*
> +  ** Restore the old i915 registers before
> +  ** forcing the ns2501 on.
> +  */
> +  if (restore)
> +    restore_dvo(dvo);
> +}
> +
> +/* set the NS2501 power state */
> +static void ns2501_dpms(struct intel_dvo_device *dvo, int mode)
> +{
> +  bool ok;
> +  bool restore = false;
> +  struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
> +  unsigned char ch;
> +
> +  DRM_DEBUG_KMS("%s: Trying set the dpms of the DVO to
> %d\n",__FUNCTION__,mode);
> +
> +  ch = ns->reg_8_shadow;
> +
> +  if (mode == DRM_MODE_DPMS_ON)
> +    ch |= NS2501_8_PD;
> +  else
> +    ch &= ~NS2501_8_PD;
> +
> +  if (ns->reg_8_set == 0 || ns->reg_8_shadow != ch) {
> +    ns->reg_8_set    = 1;
> +    ns->reg_8_shadow = ch;
> +
> +    do {
> +      ok = true;
> +      ok &= ns2501_writeb(dvo, NS2501_REG8, ch);
> +      ok &= ns2501_writeb(dvo, 0x34       ,(mode ==
> DRM_MODE_DPMS_ON)?(0x03):(0x00));
> +      ok &= ns2501_writeb(dvo, 0x35       ,(mode ==
> DRM_MODE_DPMS_ON)?(0xff):(0x00));
> +      if (!ok) {
> +	if (restore)
> +	  restore_dvo(dvo);
> +	enable_dvo(dvo);
> +	restore = true;
> +      }
> +    } while(!ok);
> +
> +    if (restore)
> +      restore_dvo(dvo);
> +  }
> +}
> +
> +static void ns2501_dump_regs(struct intel_dvo_device *dvo)
> +{
> +  uint8_t val;
> +
> +  ns2501_readb(dvo, NS2501_FREQ_LO, &val);
> +  DRM_LOG_KMS("NS2501_FREQ_LO: 0x%02x\n", val);
> +  ns2501_readb(dvo, NS2501_FREQ_HI, &val);
> +  DRM_LOG_KMS("NS2501_FREQ_HI: 0x%02x\n", val);
> +  ns2501_readb(dvo, NS2501_REG8, &val);
> +  DRM_LOG_KMS("NS2501_REG8: 0x%02x\n", val);
> +  ns2501_readb(dvo, NS2501_REG9, &val);
> +  DRM_LOG_KMS("NS2501_REG9: 0x%02x\n", val);
> +  ns2501_readb(dvo, NS2501_REGC, &val);
> +  DRM_LOG_KMS("NS2501_REGC: 0x%02x\n", val);
> +}
> +
> +static void ns2501_destroy(struct intel_dvo_device *dvo)
> +{
> +  struct ns2501_priv *ns = dvo->dev_priv;
> +
> +  if (ns) {
> +    kfree(ns);
> +    dvo->dev_priv = NULL;
> +  }
> +}
> +
> +struct intel_dvo_dev_ops ns2501_ops = {
> +  .init = ns2501_init,
> +  .detect = ns2501_detect,
> +  .mode_valid = ns2501_mode_valid,
> +  .mode_set = ns2501_mode_set,
> +  .dpms = ns2501_dpms,
> +  .dump_regs = ns2501_dump_regs,
> +  .destroy = ns2501_destroy,
> +};
> diff --git a/drivers/gpu/drm/i915/intel_display.c
> b/drivers/gpu/drm/i915/intel_display.c
> index 0161d94..70b83a1 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -1280,8 +1280,10 @@ static void assert_pch_ports_disabled(struct
> drm_i915_private *dev_priv,
>   * protect mechanism may be enabled.
>   *
>   * Note!  This is for pre-ILK only.
> + *
> + * Unfortunately needed by dvo_ns2501 since the dvo depends on it running.
>   */
> -static void intel_enable_pll(struct drm_i915_private *dev_priv,
> enum pipe pipe)
> +void intel_enable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
>  {
>  	int reg;
>  	u32 val;
> diff --git a/drivers/gpu/drm/i915/intel_dvo.c
> b/drivers/gpu/drm/i915/intel_dvo.c
> index 60ba50b9..68c1893 100644
> --- a/drivers/gpu/drm/i915/intel_dvo.c
> +++ b/drivers/gpu/drm/i915/intel_dvo.c
> @@ -37,6 +37,7 @@
>  #define SIL164_ADDR	0x38
>  #define CH7xxx_ADDR	0x76
>  #define TFP410_ADDR	0x38
> +#define NS2501_ADDR     0x38
> 
>  static const struct intel_dvo_device intel_dvo_devices[] = {
>  	{
> @@ -74,7 +75,14 @@ static const struct intel_dvo_device
> intel_dvo_devices[] = {
>  		.slave_addr = 0x75,
>  		.gpio = GMBUS_PORT_DPB,
>  		.dev_ops = &ch7017_ops,
> -	}
> +	},
> +	{
> +	        .type = INTEL_DVO_CHIP_TMDS,
> +		.name = "ns2501",
> +		.dvo_reg = DVOC,
> +		.slave_addr = NS2501_ADDR,
> +		.dev_ops = &ns2501_ops,
> +       }
>  };
> 
>  struct intel_dvo {
> -- 
> 1.7.2.5
> 

-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v4] Added support for the ns2501 DVO
  2012-06-20 18:03       ` Daniel Vetter
@ 2012-06-20 22:35         ` Paul Menzel
  0 siblings, 0 replies; 25+ messages in thread
From: Paul Menzel @ 2012-06-20 22:35 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx, Thomas Richter


[-- Attachment #1.1: Type: text/plain, Size: 1389 bytes --]

Dear Thomas,


thanks for the iteration.

Am Mittwoch, den 20.06.2012, 20:03 +0200 schrieb Daniel Vetter:
> On Wed, Jun 20, 2012 at 07:41:51PM +0200, Thomas Richter wrote:
> > This patch adds support for the ns2501 DVO, found in some older

Please also use present tense in the commit summary.

    git commit --amend

should do the trick.

> > Fujitsu/Siemens Labtops. It is in the state of "works for me".

laptops

> > Includes now proper DPMS support. Includes switching between
> > resolutions - from 640x480 to 1024x768. Currently assumes that the
> > native display resolution is 1024x768.
> > 
> > The ns2501 seems to be rather critical - if the output PLL is not
> > running, the chip doesn't seem to be clocked and then doesn't react
> > on i2c messages. Thus, a quick'n-dirty trick ensures that the DVO
> > is active before submitting any i2c messages to it. This is
> > probably to be reviewed.
> > 
> > Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=17902
> > 
> > Signed-off-by: Thomas Richter <thor@math.tu-berlin.de>
> 
> Patch is still massively whitespace-mangling. Just export it to a file
> with
> 
> git format-patch -1 HEAD
> 
> and then attach that file, please.

Thomas, Thunderbird should allow you to select certain parts of the
message and disable automatic line wrapping for that.

[…]


Thanks,

Paul

[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2012-06-20 22:35 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-15 18:55 [PATCH 01/14] drm/i915: ValleyView mode setting limits and PLL functions Jesse Barnes
2012-06-15 18:55 ` [PATCH 02/14] drm/i915: Enable DP panel power sequencing for ValleyView Jesse Barnes
2012-06-20 12:50   ` Daniel Vetter
2012-06-20 15:33     ` Jesse Barnes
2012-06-15 18:55 ` [PATCH 03/14] drm/i915: add ValleyView specific CRT detect function Jesse Barnes
2012-06-15 18:55 ` [PATCH 04/14] drm/i915: add HDMI and DP port enumeration on ValleyView Jesse Barnes
2012-06-15 18:55 ` [PATCH 05/14] drm/i915: access VLV regs through read/write switch Jesse Barnes
2012-06-15 18:55 ` [PATCH 06/14] drm/i915: VLV VGA port only handles on & off, like PCH VGA Jesse Barnes
2012-06-15 18:55 ` [PATCH 07/14] agp/intel: allow cacheable and GDFT PTEs on ValleyView Jesse Barnes
2012-06-20 12:57   ` Daniel Vetter
2012-06-20 15:35     ` Jesse Barnes
2012-06-15 18:55 ` [PATCH 08/14] drm/i915: support page flipping " Jesse Barnes
2012-06-15 18:55 ` [PATCH 09/14] drm/i915: enable display messages to GT " Jesse Barnes
2012-06-20 13:12   ` Daniel Vetter
2012-06-15 18:55 ` [PATCH 10/14] agp/intel: use correct GTT offset on VLV Jesse Barnes
2012-06-15 18:55 ` [PATCH 11/14] drm/i915: don't enable PPGTT on VLV yet Jesse Barnes
2012-06-15 18:55 ` [PATCH 12/14] drm/i915: don't account for shared interrupts on VLV Jesse Barnes
2012-06-20 13:18   ` Daniel Vetter
     [not found]   ` <15842_1340198260_4FE1CD73_15842_15371_1_20120620131831.GJ7170@phenom.ffwll.local>
2012-06-20 17:41     ` [PATCH v4] Added support for the ns2501 DVO Thomas Richter
2012-06-20 18:03       ` Daniel Vetter
2012-06-20 22:35         ` Paul Menzel
2012-06-15 18:55 ` [PATCH 13/14] drm/i915: fix initial IRQ masking on VLV Jesse Barnes
2012-06-20 13:12   ` Daniel Vetter
2012-06-15 18:55 ` [PATCH 14/14] drm/i915: bind driver to ValleyView chipsets Jesse Barnes
2012-06-20 13:20   ` Daniel Vetter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.