[Intel-gfx] [PATCH 9/9] drm/i915: Add LVDS support for IGDNG

Zhenyu Wang zhenyuw at linux.intel.com
Fri Jun 5 09:38:44 CEST 2009


Signed-off-by: Zhenyu Wang <zhenyuw at linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   13 +++-
 drivers/gpu/drm/i915/intel_lvds.c    |  127 ++++++++++++++++++++++++++++------
 2 files changed, 114 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 53cf6ef..05bd97e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1542,6 +1542,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 	int pch_fp_reg = (pipe == 0) ? PCH_FPA0 : PCH_FPB0;
 	int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B;
 	int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
+	int lvds_reg = LVDS;
 	u32 temp;
 	int sdvo_pixel_multiply;
 
@@ -1772,8 +1773,12 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 	 * things on.
 	 */
 	if (is_lvds) {
-		u32 lvds = I915_READ(LVDS);
+		u32 lvds;
 
+		if (IS_IGDNG(dev))
+			lvds_reg = PCH_LVDS;
+
+		lvds = I915_READ(lvds_reg);
 		lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT;
 		/* Set the B0-B3 data pairs corresponding to whether we're going to
 		 * set the DPLLs for dual-channel mode or not.
@@ -1788,8 +1793,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 		 * panels behave in the two modes.
 		 */
 
-		I915_WRITE(LVDS, lvds);
-		I915_READ(LVDS);
+		I915_WRITE(lvds_reg, lvds);
+		I915_READ(lvds_reg);
 	}
 
 	I915_WRITE(fp_reg, fp);
@@ -2428,7 +2433,7 @@ static void intel_setup_outputs(struct drm_device *dev)
 	intel_crt_init(dev);
 
 	/* Set up integrated LVDS */
-	if (IS_MOBILE(dev) && !IS_I830(dev) && !IS_IGDNG(dev))
+	if (IS_MOBILE(dev) && !IS_I830(dev))
 		intel_lvds_init(dev);
 
 	if (IS_IGDNG(dev)) {
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 53731f0..eea3a54 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -45,10 +45,15 @@
 static void intel_lvds_set_backlight(struct drm_device *dev, int level)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 blc_pwm_ctl;
+	u32 blc_pwm_ctl, reg;
 
-	blc_pwm_ctl = I915_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
-	I915_WRITE(BLC_PWM_CTL, (blc_pwm_ctl |
+	if (IS_IGDNG(dev))
+		reg = BLC_PWM_CPU_CTL;
+	else
+		reg = BLC_PWM_CTL;
+
+	blc_pwm_ctl = I915_READ(reg) & ~BACKLIGHT_DUTY_CYCLE_MASK;
+	I915_WRITE(reg, (blc_pwm_ctl |
 				 (level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
 }
 
@@ -58,8 +63,14 @@ static void intel_lvds_set_backlight(struct drm_device *dev, int level)
 static u32 intel_lvds_get_max_backlight(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 reg;
+
+	if (IS_IGDNG(dev))
+		reg = BLC_PWM_PCH_CTL2;
+	else
+		reg = BLC_PWM_CTL;
 
-	return ((I915_READ(BLC_PWM_CTL) & BACKLIGHT_MODULATION_FREQ_MASK) >>
+	return ((I915_READ(reg) & BACKLIGHT_MODULATION_FREQ_MASK) >>
 		BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
 }
 
@@ -69,23 +80,31 @@ static u32 intel_lvds_get_max_backlight(struct drm_device *dev)
 static void intel_lvds_set_power(struct drm_device *dev, bool on)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 pp_status;
+	u32 pp_status, ctl_reg, status_reg;
+
+	if (IS_IGDNG(dev)) {
+		ctl_reg = PCH_PP_CONTROL;
+		status_reg = PCH_PP_STATUS;
+	} else {
+		ctl_reg = PP_CONTROL;
+		status_reg = PP_STATUS;
+	}
 
 	if (on) {
-		I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) |
+		I915_WRITE(ctl_reg, I915_READ(ctl_reg) |
 			   POWER_TARGET_ON);
 		do {
-			pp_status = I915_READ(PP_STATUS);
+			pp_status = I915_READ(status_reg);
 		} while ((pp_status & PP_ON) == 0);
 
 		intel_lvds_set_backlight(dev, dev_priv->backlight_duty_cycle);
 	} else {
 		intel_lvds_set_backlight(dev, 0);
 
-		I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) &
+		I915_WRITE(ctl_reg, I915_READ(ctl_reg) &
 			   ~POWER_TARGET_ON);
 		do {
-			pp_status = I915_READ(PP_STATUS);
+			pp_status = I915_READ(status_reg);
 		} while (pp_status & PP_ON);
 	}
 }
@@ -106,12 +125,28 @@ static void intel_lvds_save(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
+	u32 pwm_ctl_reg;
+
+	if (IS_IGDNG(dev)) {
+		pp_on_reg = PCH_PP_ON_DELAYS;
+		pp_off_reg = PCH_PP_OFF_DELAYS;
+		pp_ctl_reg = PCH_PP_CONTROL;
+		pp_div_reg = PCH_PP_DIVISOR;
+		pwm_ctl_reg = BLC_PWM_CPU_CTL;
+	} else {
+		pp_on_reg = PP_ON_DELAYS;
+		pp_off_reg = PP_OFF_DELAYS;
+		pp_ctl_reg = PP_CONTROL;
+		pp_div_reg = PP_DIVISOR;
+		pwm_ctl_reg = BLC_PWM_CTL;
+	}
 
-	dev_priv->savePP_ON = I915_READ(PP_ON_DELAYS);
-	dev_priv->savePP_OFF = I915_READ(PP_OFF_DELAYS);
-	dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL);
-	dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR);
-	dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
+	dev_priv->savePP_ON = I915_READ(pp_on_reg);
+	dev_priv->savePP_OFF = I915_READ(pp_off_reg);
+	dev_priv->savePP_CONTROL = I915_READ(pp_ctl_reg);
+	dev_priv->savePP_DIVISOR = I915_READ(pp_div_reg);
+	dev_priv->saveBLC_PWM_CTL = I915_READ(pwm_ctl_reg);
 	dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL &
 				       BACKLIGHT_DUTY_CYCLE_MASK);
 
@@ -127,12 +162,28 @@ static void intel_lvds_restore(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
+	u32 pwm_ctl_reg;
+
+	if (IS_IGDNG(dev)) {
+		pp_on_reg = PCH_PP_ON_DELAYS;
+		pp_off_reg = PCH_PP_OFF_DELAYS;
+		pp_ctl_reg = PCH_PP_CONTROL;
+		pp_div_reg = PCH_PP_DIVISOR;
+		pwm_ctl_reg = BLC_PWM_CPU_CTL;
+	} else {
+		pp_on_reg = PP_ON_DELAYS;
+		pp_off_reg = PP_OFF_DELAYS;
+		pp_ctl_reg = PP_CONTROL;
+		pp_div_reg = PP_DIVISOR;
+		pwm_ctl_reg = BLC_PWM_CTL;
+	}
 
-	I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
-	I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON);
-	I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF);
-	I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR);
-	I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
+	I915_WRITE(pwm_ctl_reg, dev_priv->saveBLC_PWM_CTL);
+	I915_WRITE(pp_on_reg, dev_priv->savePP_ON);
+	I915_WRITE(pp_off_reg, dev_priv->savePP_OFF);
+	I915_WRITE(pp_div_reg, dev_priv->savePP_DIVISOR);
+	I915_WRITE(pp_ctl_reg, dev_priv->savePP_CONTROL);
 	if (dev_priv->savePP_CONTROL & POWER_TARGET_ON)
 		intel_lvds_set_power(dev, true);
 	else
@@ -216,8 +267,14 @@ static void intel_lvds_prepare(struct drm_encoder *encoder)
 {
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 reg;
 
-	dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
+	if (IS_IGDNG(dev))
+		reg = BLC_PWM_CPU_CTL;
+	else
+		reg = BLC_PWM_CTL;
+
+	dev_priv->saveBLC_PWM_CTL = I915_READ(reg);
 	dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL &
 				       BACKLIGHT_DUTY_CYCLE_MASK);
 
@@ -251,6 +308,10 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
 	 * settings.
 	 */
 
+	/* No panel fitting yet, fixme */
+	if (IS_IGDNG(dev))
+		return;
+
 	/*
 	 * Enable automatic panel scaling so that non-native modes fill the
 	 * screen.  Should be enabled before the pipe is enabled, according to
@@ -446,12 +507,18 @@ void intel_lvds_init(struct drm_device *dev)
 	struct drm_display_mode *scan; /* *modes, *bios_mode; */
 	struct drm_crtc *crtc;
 	u32 lvds;
-	int pipe;
+	int pipe, gpio = GPIOC;
 
 	/* Skip init on machines we know falsely report LVDS */
 	if (dmi_check_system(intel_no_lvds))
 		return;
 
+	if (IS_IGDNG(dev)) {
+		if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0)
+			return;
+		gpio = PCH_GPIOC;
+	}
+
 	intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
 	if (!intel_output) {
 		return;
@@ -486,7 +553,7 @@ void intel_lvds_init(struct drm_device *dev)
 	 */
 
 	/* Set up the DDC bus. */
-	intel_output->ddc_bus = intel_i2c_create(dev, GPIOC, "LVDSDDC_C");
+	intel_output->ddc_bus = intel_i2c_create(dev, gpio, "LVDSDDC_C");
 	if (!intel_output->ddc_bus) {
 		dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
 			   "failed.\n");
@@ -528,6 +595,11 @@ void intel_lvds_init(struct drm_device *dev)
 	 * on.  If so, assume that whatever is currently programmed is the
 	 * correct mode.
 	 */
+
+	/* IGDNG: FIXME if still fail, not try pipe mode now */
+	if (IS_IGDNG(dev))
+		goto failed;
+
 	lvds = I915_READ(LVDS);
 	pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
 	crtc = intel_get_crtc_from_pipe(dev, pipe);
@@ -546,6 +618,17 @@ void intel_lvds_init(struct drm_device *dev)
 		goto failed;
 
 out:
+	if (IS_IGDNG(dev)) {
+		u32 pwm;
+		/* make sure PWM is enabled */
+		pwm = I915_READ(BLC_PWM_CPU_CTL2);
+		pwm |= (PWM_ENABLE | PWM_PIPE_B);
+		I915_WRITE(BLC_PWM_CPU_CTL2, pwm);
+
+		pwm = I915_READ(BLC_PWM_PCH_CTL1);
+		pwm |= PWM_PCH_ENABLE;
+		I915_WRITE(BLC_PWM_PCH_CTL1, pwm);
+	}
 	drm_sysfs_connector_add(connector);
 	return;
 
-- 
1.6.3




More information about the Intel-gfx mailing list