summaryrefslogtreecommitdiff
path: root/src/i830_lvds.c
diff options
context:
space:
mode:
authorOwain G. Ainsworth <oga@openbsd.org>2010-05-29 14:50:40 +0100
committerOwain G. Ainsworth <oga@openbsd.org>2010-05-29 14:50:40 +0100
commit0b03a6cf1409d58996ba1d69dd7d8b1d64278d46 (patch)
treef383880e987ac20c661f36a9fa9592468a202c7f /src/i830_lvds.c
parente275a0001c4d30aa9327cabd9efd5db0dd33ae7e (diff)
Initial Ironlake support
VGA works. LVDS is still screwy. panel fitting hasn't been messed with (yet). Mostly from RHEL5's 2.2.1 branch, courtesy of airlied.
Diffstat (limited to 'src/i830_lvds.c')
-rw-r--r--src/i830_lvds.c164
1 files changed, 137 insertions, 27 deletions
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index b33b461d..34b3cbce 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -140,6 +140,10 @@ i830_set_lvds_backlight_method(xf86OutputPtr output)
if (i830_kernel_backlight_available(output)) {
method = BCM_KERNEL;
+#if 0
+ } else if (IS_IGDNG(intel)) {
+ method = BCM_IRONLAKE_NULL;
+#endif
} else if (IS_I965GM(intel) || IS_GM45(intel)) {
blc_pwm_ctl2 = INREG(BLC_PWM_CTL2);
if (blc_pwm_ctl2 & BLM_LEGACY_MODE2)
@@ -161,11 +165,16 @@ i830_lvds_set_backlight_native(xf86OutputPtr output, int level)
{
ScrnInfoPtr scrn = output->scrn;
intel_screen_private *intel = intel_get_screen_private(scrn);
- uint32_t blc_pwm_ctl;
+ uint32_t blc_pwm_ctl, reg;
- blc_pwm_ctl = INREG(BLC_PWM_CTL);
+ if (IS_IGDNG(intel))
+ reg = BLC_PWM_CPU_CTL;
+ else
+ reg = BLC_PWM_CTL;
+
+ blc_pwm_ctl = INREG(reg);
blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;
- OUTREG(BLC_PWM_CTL, blc_pwm_ctl | (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
+ OUTREG(reg, blc_pwm_ctl | (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
}
static int
@@ -185,8 +194,15 @@ i830_lvds_get_backlight_max_native(xf86OutputPtr output)
{
ScrnInfoPtr scrn = output->scrn;
intel_screen_private *intel = intel_get_screen_private(scrn);
- uint32_t pwm_ctl = INREG(BLC_PWM_CTL);
- int val;
+ uint32_t pwm_ctl;
+ int val, reg;
+
+ if (IS_IGDNG(intel))
+ reg = BLC_PWM_PCH_CTL2;
+ else
+ reg = BLC_PWM_CTL;
+
+ pwm_ctl = INREG(reg);
if (IS_I965GM(intel) || IS_GM45(intel)) {
val = ((pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK2) >>
@@ -278,6 +294,18 @@ i830_lvds_get_backlight_max_combo(xf86OutputPtr output)
return i830_lvds_get_backlight_max_native(output) >> 1;
}
+/* null methods */
+static int
+i830_lvds_get_backlight_null(xf86OutputPtr output)
+{
+ return 1;
+}
+
+static void
+i830_lvds_set_backlight_null(xf86OutputPtr output, int level)
+{
+}
+
/*
* Kernel methods
*/
@@ -482,11 +510,33 @@ i830SetLVDSPanelPower(xf86OutputPtr output, Bool on)
struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
ScrnInfoPtr scrn = output->scrn;
intel_screen_private *intel = intel_get_screen_private(scrn);
- uint32_t pp_status;
+ uint32_t pp_status, ctl_reg, status_reg;
+
+ if (IS_IGDNG(intel)) {
+ ctl_reg = PCH_PP_CONTROL;
+ status_reg = PCH_PP_STATUS;
+ } else {
+ ctl_reg = PP_CONTROL;
+ status_reg = PP_STATUS;
+ }
+
+ if (IS_IGDNG(intel)) {
+ CARD32 temp;
+ if (on) {
+ temp = INREG(PCH_LVDS);
+ OUTREG(PCH_LVDS, temp | PORT_ENABLE);
+ temp = INREG(PCH_LVDS);
+ } else {
+ temp = INREG(PCH_LVDS);
+ OUTREG(PCH_LVDS, temp & ~PORT_ENABLE);
+ temp = INREG(PCH_LVDS);
+ }
+ usleep(100);
+ }
if (on) {
/* if we're going from on->on, be aware to current level. */
- if ((INREG(PP_CONTROL) & POWER_TARGET_ON) && !dev_priv->dpmsoff)
+ if ((INREG(ctl_reg) & POWER_TARGET_ON) && !dev_priv->dpmsoff)
dev_priv->backlight_duty_cycle = dev_priv->get_backlight(output);
/*
@@ -496,14 +546,14 @@ i830SetLVDSPanelPower(xf86OutputPtr output, Bool on)
* controller for example), so on them, when turning LVDS back on,
* they'll always re-maximize the brightness.
*/
- if (!(INREG(PP_CONTROL) & POWER_TARGET_ON) &&
+ if (!(INREG(ctl_reg) & POWER_TARGET_ON) &&
dev_priv->backlight_duty_cycle == 0 &&
intel->backlight_control_method < BCM_KERNEL)
dev_priv->backlight_duty_cycle = dev_priv->backlight_max;
- OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON);
+ OUTREG(ctl_reg, INREG(ctl_reg) | POWER_TARGET_ON);
do {
- pp_status = INREG(PP_STATUS);
+ pp_status = INREG(status_reg);
} while ((pp_status & PP_ON) == 0);
dev_priv->set_backlight(output, dev_priv->backlight_duty_cycle);
@@ -513,13 +563,13 @@ i830SetLVDSPanelPower(xf86OutputPtr output, Bool on)
* Only save the current backlight value if we're going from
* on to off.
*/
- if ((INREG(PP_CONTROL) & POWER_TARGET_ON) && !dev_priv->dpmsoff)
+ if ((INREG(ctl_reg) & POWER_TARGET_ON) && !dev_priv->dpmsoff)
dev_priv->backlight_duty_cycle = dev_priv->get_backlight(output);
dev_priv->set_backlight(output, 0);
- OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON);
+ OUTREG(ctl_reg, INREG(ctl_reg) & ~POWER_TARGET_ON);
do {
- pp_status = INREG(PP_STATUS);
+ pp_status = INREG(status_reg);
} while (pp_status & PP_ON);
dev_priv->dpmsoff = TRUE;
@@ -544,14 +594,29 @@ i830_lvds_save (xf86OutputPtr output)
struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
ScrnInfoPtr scrn = output->scrn;
intel_screen_private *intel = intel_get_screen_private(scrn);
+ uint32_t pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg, pwm_ctl_reg;
+
+ if (IS_IGDNG(intel)) {
+ 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;
+ }
if (IS_I965GM(intel) || IS_GM45(intel))
intel->saveBLC_PWM_CTL2 = INREG(BLC_PWM_CTL2);
- intel->savePP_ON = INREG(PP_ON_DELAYS);
- intel->savePP_OFF = INREG(PP_OFF_DELAYS);
- intel->savePP_CONTROL = INREG(PP_CONTROL);
- intel->savePP_DIVISOR = INREG(PP_DIVISOR);
- intel->saveBLC_PWM_CTL = INREG(BLC_PWM_CTL);
+ intel->savePP_ON = INREG(pp_on_reg);
+ intel->savePP_OFF = INREG(pp_off_reg);
+ intel->savePP_CONTROL = INREG(pp_ctl_reg);
+ intel->savePP_DIVISOR = INREG(pp_div_reg);
+ intel->saveBLC_PWM_CTL = INREG(pwm_ctl_reg);
if ((INREG(PP_CONTROL) & POWER_TARGET_ON) && !dev_priv->dpmsoff)
dev_priv->backlight_duty_cycle = dev_priv->get_backlight(output);
}
@@ -561,14 +626,31 @@ i830_lvds_restore(xf86OutputPtr output)
{
ScrnInfoPtr scrn = output->scrn;
intel_screen_private *intel = intel_get_screen_private(scrn);
+ uint32_t pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
+ uint32_t pwm_ctl_reg;
+
+ if (IS_IGDNG(intel)) {
+ 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;
+ }
if (IS_I965GM(intel) || IS_GM45(intel))
OUTREG(BLC_PWM_CTL2, intel->saveBLC_PWM_CTL2);
- OUTREG(BLC_PWM_CTL, intel->saveBLC_PWM_CTL);
- OUTREG(PP_ON_DELAYS, intel->savePP_ON);
- OUTREG(PP_OFF_DELAYS, intel->savePP_OFF);
- OUTREG(PP_DIVISOR, intel->savePP_DIVISOR);
- OUTREG(PP_CONTROL, intel->savePP_CONTROL);
+ OUTREG(pwm_ctl_reg, intel->saveBLC_PWM_CTL);
+ OUTREG(pp_on_reg, intel->savePP_ON);
+ OUTREG(pp_off_reg, intel->savePP_OFF);
+ OUTREG(pp_div_reg, intel->savePP_DIVISOR);
+ OUTREG(pp_ctl_reg, intel->savePP_CONTROL);
+
if (intel->savePP_CONTROL & POWER_TARGET_ON)
i830SetLVDSPanelPower(output, TRUE);
else
@@ -624,7 +706,7 @@ i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
}
}
- if (intel_crtc->pipe == 0) {
+ if (!IS_IGDNG(intel) && intel_crtc->pipe == 0) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
"Can't support LVDS on pipe A\n");
return FALSE;
@@ -1070,12 +1152,13 @@ static Atom backlight_atom;
* or not at all.
*/
#define BACKLIGHT_CONTROL_NAME "BACKLIGHT_CONTROL"
-#define NUM_BACKLIGHT_CONTROL_METHODS 4
+#define NUM_BACKLIGHT_CONTROL_METHODS 5
static char *backlight_control_names[] = {
"native",
"legacy",
"combination",
"kernel",
+ "null",
};
static Atom backlight_control_atom;
static Atom backlight_control_name_atoms[NUM_BACKLIGHT_CONTROL_METHODS];
@@ -1135,6 +1218,11 @@ i830_lvds_set_backlight_control(xf86OutputPtr output)
dev_priv->backlight_max =
i830_lvds_get_backlight_max_kernel(output);
break;
+ case BCM_IRONLAKE_NULL:
+ dev_priv->set_backlight = i830_lvds_set_backlight_null;
+ dev_priv->get_backlight = i830_lvds_get_backlight_null;
+ dev_priv->backlight_max = 1;
+ break;
default:
/*
* Should be impossible to get here unless the caller set a bogus
@@ -1447,6 +1535,7 @@ i830_lvds_init(ScrnInfoPtr scrn)
DisplayModePtr modes, scan;
DisplayModePtr lvds_ddc_mode = NULL;
struct i830_lvds_priv *dev_priv;
+ int gpio = GPIOC;
if (!intel->integrated_lvds) {
if (intel->debug_modes)
@@ -1458,6 +1547,12 @@ i830_lvds_init(ScrnInfoPtr scrn)
if (intel->quirk_flag & QUIRK_IGNORE_LVDS)
return;
+ if (IS_IGDNG(intel)) {
+ if ((INREG(PCH_LVDS) & LVDS_DETECTED) == 0)
+ return;
+ gpio = PCH_GPIOC;
+ }
+
output = xf86OutputCreate (scrn, &i830_lvds_output_funcs, "LVDS");
if (!output)
return;
@@ -1470,6 +1565,8 @@ i830_lvds_init(ScrnInfoPtr scrn)
}
intel_output->type = I830_OUTPUT_LVDS;
intel_output->pipe_mask = (1 << 1);
+ if (0 && IS_IGDNG(intel)) /* XXX put me back */
+ intel_output->pipe_mask |= (1 << 0);
intel_output->clone_mask = (1 << I830_OUTPUT_LVDS);
output->driver_private = intel_output;
@@ -1492,7 +1589,7 @@ i830_lvds_init(ScrnInfoPtr scrn)
/* Set up the LVDS DDC channel. Most panels won't support it, but it can
* be useful if available.
*/
- I830I2CInit(scrn, &intel_output->pDDCBus, GPIOC, "LVDSDDC_C");
+ I830I2CInit(scrn, &intel_output->pDDCBus, gpio, "LVDSDDC_C");
if (intel->skip_panel_detect) {
xf86DrvMsg(scrn->scrnIndex, X_INFO,
@@ -1541,7 +1638,7 @@ i830_lvds_init(ScrnInfoPtr scrn)
* turned on. If so, assume that whatever is currently programmed is the
* correct mode.
*/
- if (!intel->lvds_fixed_mode) {
+ if (!intel->lvds_fixed_mode && !IS_IGDNG(intel)) {
uint32_t lvds = INREG(LVDS);
int pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
@@ -1619,6 +1716,19 @@ found_mode:
*/
dev_priv->fitting_mode = FULL_ASPECT;
+ if (IS_IGDNG(intel)) {
+ CARD32 pwm;
+ /* make sure PWM is enabled */
+ pwm = INREG(BLC_PWM_CPU_CTL2);
+ pwm |= (PWM_ENABLE | PWM_PIPE_B);
+ OUTREG(BLC_PWM_CPU_CTL2, pwm);
+
+ pwm = INREG(BLC_PWM_PCH_CTL1);
+ pwm |= PWM_PCH_ENABLE;
+ OUTREG(BLC_PWM_PCH_CTL1, pwm);
+ }
+
+
return;
disable_exit: