xf86-video-intel: Branch 'modesetting-rotation' - 6 commits - src/i810_reg.h src/i830_edid_modes.c src/i830_lvds.c src/i830_randr.c src/i830_xf86Crtc.c src/i830_xf86Crtc.h src/i830_xf86Rotate.c

Eric Anholt anholt at kemper.freedesktop.org
Thu Jan 18 21:37:49 EET 2007


 src/i810_reg.h        |   13 +++++
 src/i830_edid_modes.c |   22 ++++++++
 src/i830_lvds.c       |  124 +++++++++++++++++++++++++++++++++++++++++++-------
 src/i830_randr.c      |   21 ++++++++
 src/i830_xf86Crtc.c   |   30 ++++++++----
 src/i830_xf86Crtc.h   |   15 ++++++
 src/i830_xf86Rotate.c |   55 ++++++++++++++--------
 7 files changed, 235 insertions(+), 45 deletions(-)

New commits:
diff-tree d2ae2e2ccc3a8e7dc84745c235836cba150754d8 (from 92b0f3d2013c32d94fe57fe674da1b195288f347)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 18 11:37:14 2007 -0800

    Update CRTC values first so they can be used by the driver in mode setting.
    
    With this, the screen now gets rotated, though there are major issues.

diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index a926e9f..c879d99 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -154,6 +154,9 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, Displ
     Bool		ret = FALSE;
     Bool		didLock = FALSE;
     DisplayModePtr	adjusted_mode;
+    DisplayModeRec	saved_mode;
+    int			saved_x, saved_y;
+    Rotation		saved_rotation;
 
     adjusted_mode = xf86DuplicateMode(mode);
 
@@ -167,6 +170,18 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, Displ
 
     didLock = crtc->funcs->lock (crtc);
 
+    saved_mode = crtc->mode;
+    saved_x = crtc->x;
+    saved_y = crtc->y;
+    saved_rotation = crtc->rotation;
+    /* Update crtc values up front so the driver can rely on them for mode
+     * setting.
+     */
+    crtc->mode = *mode;
+    crtc->x = x;
+    crtc->y = y;
+    crtc->rotation = rotation;
+
     /* XXX short-circuit changes to base location only */
     
     /* Pass our mode to the outputs and the CRTC to give them a chance to
@@ -180,18 +195,15 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, Displ
 	    continue;
 
 	if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) {
-	    ret = FALSE;
 	    goto done;
 	}
     }
 
     if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) {
-	ret = FALSE;
 	goto done;
     }
 
     if (!xf86CrtcRotate (crtc, mode, rotation)) {
-	ret = FALSE;
 	goto done;
     }
 
@@ -228,14 +240,16 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, Displ
 	    output->funcs->dpms(output, DPMSModeOn);
     }
 
-    crtc->mode = *mode;
-    crtc->x = x;
-    crtc->y = y;
-    crtc->rotation = rotation;
-
     /* XXX free adjustedmode */
     ret = TRUE;
 done:
+    if (!ret) {
+	crtc->x = saved_x;
+	crtc->y = saved_y;
+	crtc->rotation = saved_rotation;
+	crtc->mode = saved_mode;
+    }
+
     if (didLock)
 	crtc->funcs->unlock (crtc);
 
diff-tree 92b0f3d2013c32d94fe57fe674da1b195288f347 (from 14d265a02312e9cda7a21614d77525c7140c0ca8)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 18 11:23:22 2007 -0800

    Disable the clipping for now, since it won't work.

diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
index 39733fd..670ad7a 100644
--- a/src/i830_xf86Rotate.c
+++ b/src/i830_xf86Rotate.c
@@ -127,7 +127,13 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
 	ErrorF("couldn't create src pict\n");
 	return;
     }
-    SetPictureClipRegion (src, 0, 0, region);
+    /* Unfortunately, we don't do clipping on transformed source pictures.
+     * So we can't use this.  Instead, we'll just repaint the whole screen
+     * for now, and do transform of the source region into a dest region
+     * later.
+     */
+    /* SetPictureClipRegion (src, 0, 0, region); */
+
     memset (&transform, '\0', sizeof (transform));
     transform.matrix[2][2] = IntToxFixed(1);
     transform.matrix[0][2] = IntToxFixed(crtc->x);
diff-tree 14d265a02312e9cda7a21614d77525c7140c0ca8 (from cc09dc3efe7279bf67512babb0f6cdaeba654772)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 18 11:21:58 2007 -0800

    Store fixed values, not integers, in the transformation matrix.
    
    Also, add a bit more error checking.

diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
index 14c0c5d..39733fd 100644
--- a/src/i830_xf86Rotate.c
+++ b/src/i830_xf86Rotate.c
@@ -112,8 +112,10 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
 			 NULL,
 			 serverClient,
 			 &error);
-    if (!src)
+    if (!src) {
+	ErrorF("couldn't create src pict\n");
 	return;
+    }
     dst = CreatePicture (None,
 			 &dst_pixmap->drawable,
 			 format,
@@ -121,38 +123,41 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
 			 NULL,
 			 serverClient,
 			 &error);
-    if (!dst)
+    if (!dst) {
+	ErrorF("couldn't create src pict\n");
 	return;
+    }
     SetPictureClipRegion (src, 0, 0, region);
     memset (&transform, '\0', sizeof (transform));
-    transform.matrix[2][2] = 1;
-    transform.matrix[0][2] = crtc->x;
-    transform.matrix[1][2] = crtc->y;
+    transform.matrix[2][2] = IntToxFixed(1);
+    transform.matrix[0][2] = IntToxFixed(crtc->x);
+    transform.matrix[1][2] = IntToxFixed(crtc->y);
     switch (crtc->rotation & 0xf) {
     case RR_Rotate_0:
-	transform.matrix[0][0] = 1;
-	transform.matrix[1][1] = 1;
+	transform.matrix[0][0] = IntToxFixed(1);
+	transform.matrix[1][1] = IntToxFixed(1);
 	break;
     case RR_Rotate_90:
 	/* XXX probably wrong */
-	transform.matrix[0][1] = 1;
-	transform.matrix[1][0] = -1;
-	transform.matrix[1][2] += crtc->mode.HDisplay;
+	transform.matrix[0][1] = IntToxFixed(1);
+	transform.matrix[1][0] = IntToxFixed(-1);
+	transform.matrix[1][2] += IntToxFixed(crtc->mode.HDisplay);
 	break;
     case RR_Rotate_180:
 	/* XXX probably wrong */
-	transform.matrix[0][0] = -1;
-	transform.matrix[1][1] = -1;
-	transform.matrix[0][2] += crtc->mode.HDisplay;
-	transform.matrix[1][2] += crtc->mode.VDisplay;
+	transform.matrix[0][0] = IntToxFixed(-1);
+	transform.matrix[1][1] = IntToxFixed(-1);
+	transform.matrix[0][2] += IntToxFixed(crtc->mode.HDisplay);
+	transform.matrix[1][2] += IntToxFixed(crtc->mode.VDisplay);
 	break;
     case RR_Rotate_270:
 	/* XXX probably wrong */
-	transform.matrix[0][1] = -1;
-	transform.matrix[1][0] = 1;
-	transform.matrix[0][2] += crtc->mode.VDisplay;
+	transform.matrix[0][1] = IntToxFixed(-1);
+	transform.matrix[1][0] = IntToxFixed(1);
+	transform.matrix[0][2] += IntToxFixed(crtc->mode.VDisplay);
 	break;
     }
+
     /* handle reflection */
     if (crtc->rotation & RR_Reflect_X)
     {
@@ -162,7 +167,13 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
     {
 	/* XXX figure this out too */
     }
-    SetPictureTransform (src, &transform);
+
+    error = SetPictureTransform (src, &transform);
+    if (error) {
+	ErrorF("Couldn't set transform\n");
+	return;
+    }
+
     CompositePicture (PictOpSrc,
 		      src, NULL, dst,
 		      0, 0, 0, 0, 0, 0,
diff-tree cc09dc3efe7279bf67512babb0f6cdaeba654772 (from parents)
Merge: 53e765d1cf5016961c25a798a27f0fe09bd1f237 3094100cdd04560af1b098bbe8024ae5270a10f4
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 18 10:20:36 2007 -0800

    Merge branch 'modesetting' into modesetting-rotation

diff-tree 3094100cdd04560af1b098bbe8024ae5270a10f4 (from 66c6427cc83e5e381932b0c10743cba4cb9ac883)
Author: Gary Wong <gtw at gnu.org>
Date:   Tue Jan 16 13:25:24 2007 -0800

    Bug #9550: Add a quirk for too-high clock from EDID on the EN-7100e.

diff --git a/src/i830_edid_modes.c b/src/i830_edid_modes.c
index 249f87a..1bab4cd 100644
--- a/src/i830_edid_modes.c
+++ b/src/i830_edid_modes.c
@@ -52,6 +52,8 @@ typedef enum {
     DDC_QUIRK_DT_SYNC_HM_VP = 1 << 0,
     /* First detailed mode is bogus, prefer largest mode at 60hz */
     DDC_QUIRK_PREFER_LARGE_60 = 1 << 1,
+    /* 135MHz clock is too high, drop a bit */
+    DDC_QUIRK_135_CLOCK_TOO_HIGH = 1 << 2
 } ddc_quirk_t;
 
 static Bool quirk_dt_sync_hm_vp (int scrnIndex, xf86MonPtr DDC)
@@ -78,6 +80,16 @@ static Bool quirk_prefer_large_60 (int s
     return FALSE;
 }
 
+static Bool quirk_135_clock_too_high (int scrnIndex, xf86MonPtr DDC)
+{
+    /* Envision Peripherals, Inc. EN-7100e.  See bug #9550. */
+    if (memcmp (DDC->vendor.name, "EPI", 4) == 0 &&
+	DDC->vendor.prod_id == 59264)
+	return TRUE;
+    
+    return FALSE;
+}
+
 typedef struct {
     Bool	(*detect) (int scrnIndex, xf86MonPtr DDC);
     ddc_quirk_t	quirk;
@@ -93,6 +105,10 @@ static const ddc_quirk_map_t ddc_quirks[
 	quirk_prefer_large_60,   DDC_QUIRK_PREFER_LARGE_60,
 	"Detailed timing is not preferred, use largest mode at 60Hz"
     },
+    {
+	quirk_135_clock_too_high,   DDC_QUIRK_135_CLOCK_TOO_HIGH,
+	"Recommended 135MHz pixel clock is too high"
+    },
     { 
 	NULL,		DDC_QUIRK_NONE,
 	"No known quirks"
@@ -197,7 +213,11 @@ DDCModeFromDetailedTiming(int scrnIndex,
     if (preferred)
 	Mode->type |= M_T_PREFERRED;
 
-    Mode->Clock = timing->clock / 1000.0;
+    if( ( quirks & DDC_QUIRK_135_CLOCK_TOO_HIGH ) &&
+	timing->clock == 135000000 )
+        Mode->Clock = 108880;
+    else
+        Mode->Clock = timing->clock / 1000.0;
 
     Mode->HDisplay = timing->h_active;
     Mode->HSyncStart = timing->h_active + timing->h_sync_off;
diff-tree 66c6427cc83e5e381932b0c10743cba4cb9ac883 (from 45696aa29124e2852f94880642e70bb2e0cee827)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Jan 16 12:54:29 2007 -0800

    Add a settable backlight property for LVDS.
    
    This extends the output funcs to have a callback for when it's time to
    configure properties, and another for when the server has changed a property
    whose value isn't pending a mode set. (Pending properties are to be picked up
    by the driver at mode_set time).

diff --git a/src/i810_reg.h b/src/i810_reg.h
index c2eb854..33b059d 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -937,8 +937,21 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 #define BLC_PWM_CTL		0x61254
 #define BACKLIGHT_MODULATION_FREQ_SHIFT		(17)
+/**
+ * This is the most significant 15 bits of the number of backlight cycles in a
+ * complete cycle of the modulated backlight control.
+ *
+ * The actual value is this field multiplied by two.
+ */
 #define BACKLIGHT_MODULATION_FREQ_MASK		(0x7fff << 17)
 #define BLM_LEGACY_MODE				(1 << 16)
+/**
+ * This is the number of cycles out of the backlight modulation cycle for which
+ * the backlight is on.
+ *
+ * This field must be no greater than the number of cycles in the complete
+ * backlight modulation cycle.
+ */
 #define BACKLIGHT_DUTY_CYCLE_SHIFT		(0)
 #define BACKLIGHT_DUTY_CYCLE_MASK		(0xffff)
 
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 18ac76b..223c6ab 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -32,6 +32,34 @@
 #include "xf86.h"
 #include "i830.h"
 #include "i830_bios.h"
+#include "X11/Xatom.h"
+
+/**
+ * Sets the backlight level.
+ *
+ * \param level backlight level, from 0 to i830_lvds_get_max_backlight().
+ */
+static void
+i830_lvds_set_backlight(ScrnInfoPtr pScrn, int level)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 blc_pwm_ctl;
+
+    blc_pwm_ctl = INREG(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
+    OUTREG(BLC_PWM_CTL, blc_pwm_ctl | (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
+}
+
+/**
+ * Returns the maximum level of the backlight duty cycle field.
+ */
+static CARD32
+i830_lvds_get_max_backlight(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    
+    return ((INREG(BLC_PWM_CTL) & BACKLIGHT_MODULATION_FREQ_MASK) >>
+	BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
+}
 
 /**
  * Sets the power state for the panel.
@@ -41,25 +69,16 @@ i830SetLVDSPanelPower(ScrnInfoPtr pScrn,
 {
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 pp_status;
-    CARD32 blc_pwm_ctl;
-    int backlight_duty_cycle;
-
-    blc_pwm_ctl = INREG (BLC_PWM_CTL);
-    backlight_duty_cycle = blc_pwm_ctl & BACKLIGHT_DUTY_CYCLE_MASK;
-    if (backlight_duty_cycle)
-        pI830->backlight_duty_cycle = backlight_duty_cycle;
 
     if (on) {
 	OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON);
 	do {
 	    pp_status = INREG(PP_STATUS);
 	} while ((pp_status & PP_ON) == 0);
-	OUTREG(BLC_PWM_CTL,
-	       (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK) |
-	       pI830->backlight_duty_cycle);
+
+	i830_lvds_set_backlight(pScrn, pI830->backlight_duty_cycle);
     } else {
-	OUTREG(BLC_PWM_CTL,
-	       (blc_pwm_ctl & ~BACKLIGHT_DUTY_CYCLE_MASK));
+	i830_lvds_set_backlight(pScrn, 0);
 
 	OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON);
 	do {
@@ -99,11 +118,8 @@ i830_lvds_save (xf86OutputPtr output)
     /*
      * If the light is off at server startup, just make it full brightness
      */
-    if (pI830->backlight_duty_cycle == 0) {
-	pI830->backlight_duty_cycle =
-	    (pI830->saveBLC_PWM_CTL & BACKLIGHT_MODULATION_FREQ_MASK) >>
-	    BACKLIGHT_MODULATION_FREQ_SHIFT;
-    }
+    if (pI830->backlight_duty_cycle == 0)
+	pI830->backlight_duty_cycle = i830_lvds_get_max_backlight(pScrn);
 }
 
 static void
@@ -294,7 +310,80 @@ i830_lvds_destroy (xf86OutputPtr output)
 	xfree (intel_output);
 }
 
+#ifdef RANDR_12_INTERFACE
+#define BACKLIGHT_NAME	"BACKLIGHT"
+static Atom backlight_atom;
+#endif /* RANDR_12_INTERFACE */
+
+static void
+i830_lvds_create_resources(xf86OutputPtr output)
+{
+#ifdef RANDR_12_INTERFACE
+    ScrnInfoPtr pScrn = output->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    INT32 range[2];
+    int data, err;
+
+    /* Set up the backlight property, which takes effect immediately
+     * and accepts values only within the range.
+     *
+     * XXX: Currently, RandR doesn't verify that properties set are
+     * within the range.
+     */
+    backlight_atom = MakeAtom(BACKLIGHT_NAME, sizeof(BACKLIGHT_NAME) - 1,
+	TRUE);
+
+    range[0] = 0;
+    range[1] = i830_lvds_get_max_backlight(pScrn);
+    err = RRConfigureOutputProperty(output->randr_output, backlight_atom,
+				    FALSE, TRUE, FALSE, 2, range);
+    if (err != 0) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "RRConfigureOutputProperty error, %d\n", err);
+    }
+    /* Set the current value of the backlight property */
+    data = pI830->backlight_duty_cycle;
+    err = RRChangeOutputProperty(output->randr_output, backlight_atom,
+				 XA_INTEGER, 32, PropModeReplace, 4, &data,
+				 FALSE);
+    if (err != 0) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "RRChangeOutputProperty error, %d\n", err);
+    }
+
+#endif /* RANDR_12_INTERFACE */
+}
+
+static Bool
+i830_lvds_set_property(xf86OutputPtr output, Atom property,
+		       RRPropertyValuePtr value)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    
+    if (property == backlight_atom) {
+	INT32 val;
+
+	if (value->type != XA_INTEGER || value->format != 32 ||
+	    value->size != 1)
+	{
+	    return FALSE;
+	}
+
+	val = *(INT32 *)value->data;
+	if (val < 0 || val > i830_lvds_get_max_backlight(pScrn))
+	    return FALSE;
+
+	i830_lvds_set_backlight(pScrn, val);
+	pI830->backlight_duty_cycle = val;
+	return TRUE;
+    }
+
+    return TRUE;
+}
+
 static const xf86OutputFuncsRec i830_lvds_output_funcs = {
+    .create_resources = i830_lvds_create_resources,
     .dpms = i830_lvds_dpms,
     .save = i830_lvds_save,
     .restore = i830_lvds_restore,
@@ -303,6 +392,7 @@ static const xf86OutputFuncsRec i830_lvd
     .mode_set = i830_lvds_mode_set,
     .detect = i830_lvds_detect,
     .get_modes = i830_lvds_get_modes,
+    .set_property = i830_lvds_set_property,
     .destroy = i830_lvds_destroy
 };
 
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 18f84c4..6388849 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -672,6 +672,23 @@ xf86RandR12CrtcSetGamma (ScreenPtr    pS
     return TRUE;
 }
 
+static Bool
+xf86RandR12OutputSetProperty (ScreenPtr pScreen,
+			      RROutputPtr randr_output,
+			      Atom property,
+			      RRPropertyValuePtr value)
+{
+    xf86OutputPtr output = randr_output->devPrivate;
+
+    /* If we don't have any property handler, then we don't care what the
+     * user is setting properties to.
+     */
+    if (output->funcs->set_property == NULL)
+	return TRUE;
+
+    return output->funcs->set_property(output, property, value);
+}
+
 /**
  * Given a list of xf86 modes and a RandR Output object, construct
  * RandR modes and assign them to the output
@@ -861,6 +878,9 @@ xf86RandR12CreateObjects12 (ScreenPtr pS
 					       strlen (output->name),
 					       output);
 	RROutputAttachScreen (output->randr_output, pScreen);
+
+	if (output->funcs->create_resources != NULL)
+	    output->funcs->create_resources(output);
     }
     return TRUE;
 }
@@ -897,6 +917,7 @@ xf86RandR12Init12 (ScreenPtr pScreen)
     rp->rrScreenSetSize = xf86RandR12ScreenSetSize;
     rp->rrCrtcSet = xf86RandR12CrtcSet;
     rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma;
+    rp->rrOutputSetProperty = xf86RandR12OutputSetProperty;
     rp->rrSetConfig = NULL;
     pScrn->PointerMoved = xf86RandR12PointerMoved;
     if (!xf86RandR12CreateObjects12 (pScreen))
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index 8fea162..b5f2fc2 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -171,6 +171,13 @@ struct _xf86Crtc {
 
 typedef struct _xf86OutputFuncs {
     /**
+     * Called to allow the output a chance to create properties after the
+     * RandR objects have been created.
+     */
+    void
+    (*create_resources)(xf86OutputPtr output);
+
+    /**
      * Turns the output on/off, or sets intermediate power levels if available.
      *
      * Unsupported intermediate modes drop to the lower power setting.  If the
@@ -246,6 +253,14 @@ typedef struct _xf86OutputFuncs {
     (*get_modes)(xf86OutputPtr	    output);
 
     /**
+     * Callback when an output's property has changed.
+     */
+    Bool
+    (*set_property)(xf86OutputPtr output,
+		    Atom property,
+		    RRPropertyValuePtr value);
+
+    /**
      * Clean up driver-specific bits of the output
      */
     void



More information about the xorg-commit mailing list