@@ -49,6 +49,10 @@ module_param_named(powersave, i915_powersave, int, 0600);
unsigned int i915_lvds_downclock = 0;
module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400);
+unsigned int i915_lvds_24bit = 0;
+module_param_named(lvds_24bit, i915_lvds_24bit, int, 0600);
+MODULE_PARM_DESC(lvds_24bit, "LVDS 24 bit pixel format: 0=leave untouched (default), 1=24 bit '2.0' format, 2=24 bit '2.1' format, 3=force older 18 bit format");
+
static struct drm_driver driver;
extern int intel_agp_enabled;
@@ -886,6 +886,7 @@ extern int i915_max_ioctl;
extern unsigned int i915_fbpercrtc;
extern unsigned int i915_powersave;
extern unsigned int i915_lvds_downclock;
+extern unsigned int i915_lvds_24bit;
extern int i915_suspend(struct drm_device *dev, pm_message_t state);
extern int i915_resume(struct drm_device *dev);
@@ -1320,6 +1320,13 @@
#define LVDS_PIPEB_SELECT (1 << 30)
/* LVDS dithering flag on 965/g4x platform */
#define LVDS_ENABLE_DITHER (1 << 25)
+/*
+ * Selects between .0 and .1 formats:
+ *
+ * 0 = 1x18.0, 2x18.0, 1x24.0 or 2x24.0
+ * 1 = 1x24.1 or 2x24.1
+ */
+#define LVDS_DATA_FORMAT_DOT_ONE (1 << 24)
/* Enable border for unscaled (or aspect-scaled) display */
#define LVDS_BORDER_ENABLE (1 << 15)
/*
@@ -4029,10 +4029,40 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
else
temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
- /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
- * appropriately here, but we need to look more thoroughly into how
- * panels behave in the two modes.
- */
+ /* Control the output pixel format. */
+ switch (i915_lvds_24bit) {
+ default:
+ case 0:
+ /* 0 means don't mess with 18 vs 24 bit LVDS pixel
+ * format. Instead we trust whatever the video
+ * BIOS should have done to set up the panel.
+ * This is normally the safest choice since most
+ * LVDS-connected panels are integral to the
+ * system and thus the video BIOS knows how to set
+ * it up appropriately. */
+ break;
+ case 1:
+ /* Enable 24 bit pixel mode using the "2.0" format */
+ temp |= LVDS_A3_POWER_UP;
+ temp &= ~LVDS_DATA_FORMAT_DOT_ONE;
+ break;
+ case 2:
+ /* Enable 24 bit pixel mode using the "2.1"
+ * format; this choice is equivalent to the
+ * LVDS24BitMode option in the old pre-KMS user
+ * space driver. */
+ temp |= LVDS_A3_POWER_UP;
+ temp |= LVDS_DATA_FORMAT_DOT_ONE;
+ break;
+ case 3:
+ /* Enable 18 bit pixel mode - this should be a
+ very rare case since this is usually the
+ power-up mode if the video BIOS didn't set
+ things up. But it's here for completeness. */
+ temp &= ~LVDS_A3_POWER_UP;
+ temp &= ~LVDS_DATA_FORMAT_DOT_ONE;
+ break;
+ }
/* set the dithering flag on non-PCH LVDS as needed */
if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
if (dev_priv->lvds_dither)