All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [WIP] Wrap fb objects from BIOS/bootloader
@ 2013-11-06 19:02 Jesse Barnes
  2013-11-06 19:25 ` [PATCH] drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v4 Jesse Barnes
  0 siblings, 1 reply; 7+ messages in thread
From: Jesse Barnes @ 2013-11-06 19:02 UTC (permalink / raw
  To: intel-gfx

There was a TODO from last time that Daniel and I talked about:
  - reconstruct fb state in our get_config callbacks instead
  - reconstruct per-crtc fb state and allocate separate buffers if
    needed
  - make sure we only preserve the buffer if it's the preferred mode

Just wanted to get this refreshed version out there to get some eyes on
it.

Thanks,
Jesse

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

* [PATCH] drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v4
  2013-11-06 19:02 [WIP] Wrap fb objects from BIOS/bootloader Jesse Barnes
@ 2013-11-06 19:25 ` Jesse Barnes
  2013-11-07 14:22   ` Chris Wilson
                     ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Jesse Barnes @ 2013-11-06 19:25 UTC (permalink / raw
  To: intel-gfx

Retrieve current framebuffer config info from the regs and create an fb
object for the buffer the BIOS or boot loader left us.  This should
allow for smooth transitions to userspace apps once we finish the
initial configuration construction.

v2: check for non-native modes and adjust (Jesse)
    fixup aperture and cmap frees (Imre)
    use unlocked unref if init_bios fails (Jesse)
    fix curly brace around DSPADDR check (Imre)
    comment failure path for pin_and_fence (Imre)
v3: fixup fixup of aperture frees (Chris)
v4: update to current bits (locking & pin_and_fence hack) (Jesse)

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_dma.c      |   8 +-
 drivers/gpu/drm/i915/i915_drv.h      |   2 +-
 drivers/gpu/drm/i915/intel_display.c |  14 +-
 drivers/gpu/drm/i915/intel_drv.h     |   4 +
 drivers/gpu/drm/i915/intel_fbdev.c   | 295 +++++++++++++++++++++++++++++++++--
 5 files changed, 308 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 0cab2d0..d8eed45 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1277,6 +1277,7 @@ static const struct vga_switcheroo_client_ops i915_switcheroo_ops = {
 static int i915_load_modeset_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	bool was_vga_enabled;
 	int ret;
 
 	ret = intel_parse_bios(dev);
@@ -1315,7 +1316,11 @@ static int i915_load_modeset_init(struct drm_device *dev)
 
 	/* Important: The output setup functions called by modeset_init need
 	 * working irqs for e.g. gmbus and dp aux transfers. */
-	intel_modeset_init(dev);
+	intel_modeset_init(dev, &was_vga_enabled);
+
+	/* Wrap existing BIOS mode configuration prior to GEM takeover */
+	if (!was_vga_enabled)
+		intel_fbdev_init_bios(dev);
 
 	ret = i915_gem_init(dev);
 	if (ret)
@@ -1333,6 +1338,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
 		return 0;
 	}
 
+	/* Install a default KMS/GEM fbcon if we failed to wrap the BIOS fb */
 	ret = intel_fbdev_init(dev);
 	if (ret)
 		goto cleanup_gem;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index d1590f7..100d3cf 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2372,7 +2372,7 @@ static inline void intel_unregister_dsm_handler(void) { return; }
 /* modesetting */
 extern void intel_modeset_init_hw(struct drm_device *dev);
 extern void intel_modeset_suspend_hw(struct drm_device *dev);
-extern void intel_modeset_init(struct drm_device *dev);
+extern void intel_modeset_init(struct drm_device *dev, bool *was_vga_enabled);
 extern void intel_modeset_gem_init(struct drm_device *dev);
 extern void intel_modeset_cleanup(struct drm_device *dev);
 extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 71b3bb7..f6e4792 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -10735,12 +10735,17 @@ static void intel_init_quirks(struct drm_device *dev)
 }
 
 /* Disable the VGA plane that we never use */
-static void i915_disable_vga(struct drm_device *dev)
+static bool i915_disable_vga(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	bool was_enabled;
 	u8 sr1;
 	u32 vga_reg = i915_vgacntrl_reg(dev);
 
+	was_enabled = !(I915_READ(vga_reg) & VGA_DISP_DISABLE);
+	DRM_DEBUG_KMS("VGA output is currently %s\n",
+		      was_enabled ? "enabled" : "disabled");
+
 	vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
 	outb(SR01, VGA_SR_INDEX);
 	sr1 = inb(VGA_SR_DATA);
@@ -10750,6 +10755,8 @@ static void i915_disable_vga(struct drm_device *dev)
 
 	I915_WRITE(vga_reg, VGA_DISP_DISABLE);
 	POSTING_READ(vga_reg);
+
+	return was_enabled;
 }
 
 void intel_modeset_init_hw(struct drm_device *dev)
@@ -10777,7 +10784,8 @@ void intel_modeset_suspend_hw(struct drm_device *dev)
 	intel_suspend_hw(dev);
 }
 
-void intel_modeset_init(struct drm_device *dev)
+void intel_modeset_init(struct drm_device *dev,
+			bool *was_vga_enabled)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int i, j, ret;
@@ -10831,7 +10839,7 @@ void intel_modeset_init(struct drm_device *dev)
 	intel_shared_dpll_init(dev);
 
 	/* Just disable it once at startup */
-	i915_disable_vga(dev);
+	*was_vga_enabled = i915_disable_vga(dev);
 	intel_setup_outputs(dev);
 
 	/* Just in case the BIOS is doing something questionable. */
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1876ea1..be048d9 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -113,6 +113,8 @@ struct intel_fbdev {
 	struct intel_framebuffer ifb;
 	struct list_head fbdev_list;
 	struct drm_display_mode *our_mode;
+	bool stolen;
+	int preferred_bpp;
 };
 
 struct intel_encoder {
@@ -320,6 +322,7 @@ struct intel_crtc {
 	enum pipe pipe;
 	enum plane plane;
 	u8 lut_r[256], lut_g[256], lut_b[256];
+	bool mode_valid;
 	/*
 	 * Whether the crtc and the connected output pipeline is active. Implies
 	 * that crtc->enabled is set, i.e. the current mode configuration has
@@ -652,6 +655,7 @@ int intel_framebuffer_init(struct drm_device *dev,
 			   struct intel_framebuffer *ifb,
 			   struct drm_mode_fb_cmd2 *mode_cmd,
 			   struct drm_i915_gem_object *obj);
+void intel_fbdev_init_bios(struct drm_device *dev);
 void intel_framebuffer_fini(struct intel_framebuffer *fb);
 void intel_prepare_page_flip(struct drm_device *dev, int plane);
 void intel_finish_page_flip(struct drm_device *dev, int pipe);
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 895fcb4..2d71312 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -170,9 +170,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
 		      fb->width, fb->height,
 		      i915_gem_obj_ggtt_offset(obj), obj);
 
-
 	mutex_unlock(&dev->struct_mutex);
-	vga_switcheroo_client_fb_set(dev->pdev, info);
 	return 0;
 
 out_unpin:
@@ -205,6 +203,69 @@ static void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
 	*blue = intel_crtc->lut_b[regno] << 8;
 }
 
+static struct drm_fb_helper_crtc *
+intel_fb_helper_crtc(struct drm_fb_helper *fb_helper, struct drm_crtc *crtc)
+{
+	int i;
+
+	for (i = 0; i < fb_helper->crtc_count; i++)
+		if (fb_helper->crtc_info[i].mode_set.crtc == crtc)
+			return &fb_helper->crtc_info[i];
+
+	return NULL;
+}
+
+static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
+				    struct drm_fb_helper_crtc **crtcs,
+				    struct drm_display_mode **modes,
+				    bool *enabled, int width, int height)
+{
+	int i;
+
+	for (i = 0; i < fb_helper->connector_count; i++) {
+		struct drm_connector *connector;
+		struct drm_encoder *encoder;
+
+		connector = fb_helper->connector_info[i]->connector;
+		if (!enabled[i]) {
+			DRM_DEBUG_KMS("connector %d not enabled, skipping\n",
+				      connector->base.id);
+			continue;
+		}
+
+		encoder = connector->encoder;
+		if (!encoder || !encoder->crtc) {
+			DRM_DEBUG_KMS("connector %d has no encoder or crtc, skipping\n",
+				      connector->base.id);
+			continue;
+		}
+
+		if (WARN_ON(!encoder->crtc->enabled)) {
+			DRM_DEBUG_KMS("connector %s on crtc %d has inconsistent state, aborting\n",
+				      drm_get_connector_name(connector),
+				      encoder->crtc->base.id);
+			return false;
+		}
+
+		if (!to_intel_crtc(encoder->crtc)->mode_valid) {
+			DRM_DEBUG_KMS("connector %s on crtc %d has an invalid mode, aborting\n",
+				      drm_get_connector_name(connector),
+				      encoder->crtc->base.id);
+			return false;
+		}
+
+		modes[i] = &encoder->crtc->mode;
+		crtcs[i] = intel_fb_helper_crtc(fb_helper, encoder->crtc);
+
+		DRM_DEBUG_KMS("connector %s on crtc %d: %s\n",
+			      drm_get_connector_name(connector),
+			      encoder->crtc->base.id,
+			      modes[i]->name);
+	}
+
+	return true;
+}
+
 static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
 	.gamma_set = intel_crtc_fb_gamma_set,
 	.gamma_get = intel_crtc_fb_gamma_get,
@@ -219,8 +280,7 @@ static void intel_fbdev_destroy(struct drm_device *dev,
 
 		unregister_framebuffer(info);
 		iounmap(info->screen_base);
-		if (info->cmap.len)
-			fb_dealloc_cmap(&info->cmap);
+		fb_dealloc_cmap(&info->cmap);
 
 		framebuffer_release(info);
 	}
@@ -231,23 +291,236 @@ static void intel_fbdev_destroy(struct drm_device *dev,
 	intel_framebuffer_fini(&ifbdev->ifb);
 }
 
+static bool pipe_enabled(struct drm_i915_private *dev_priv, enum pipe pipe)
+{
+	enum transcoder cpu_transcoder =
+		intel_pipe_to_cpu_transcoder(dev_priv, pipe);
+	return !!(I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_ENABLE);
+}
+
+static u32
+intel_framebuffer_pitch_for_width(int width, int bpp)
+{
+	u32 pitch = DIV_ROUND_UP(width * bpp, 8);
+	return ALIGN(pitch, 64);
+}
+
+/*
+ * Try to read the BIOS display configuration and use it for the initial
+ * fb configuration.
+ *
+ * The BIOS or boot loader will generally create an initial display
+ * configuration for us that includes some set of active pipes and displays.
+ * This routine tries to figure out which pipes are active, what resolutions
+ * are being displayed, and then allocates a framebuffer and initial fb
+ * config based on that data.
+ *
+ * If the BIOS or boot loader leaves the display in VGA mode, there's not
+ * much we can do; switching out of that mode involves allocating a new,
+ * high res buffer, and also recalculating bandwidth requirements for the
+ * new bpp configuration.
+ *
+ * However, if we're loaded into an existing, high res mode, we should
+ * be able to allocate a buffer big enough to handle the largest active
+ * mode, create a mode_set for it, and pass it to the fb helper to create
+ * the configuration.
+ */
+void intel_fbdev_init_bios(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_fbdev *ifbdev;
+	struct drm_crtc *crtc;
+	struct drm_mode_fb_cmd2 mode_cmd = { 0 };
+	struct drm_i915_gem_object *obj;
+	u32 obj_offset = 0;
+	int mode_bpp = 0;
+	u32 active = 0;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+		int pipe = intel_crtc->pipe, plane = intel_crtc->plane;
+		u32 val, bpp, offset, format;
+		int pitch, width, height;
+
+		if (!pipe_enabled(dev_priv, pipe)) {
+			DRM_DEBUG_KMS("pipe %c not active, skipping\n",
+				      pipe_name(pipe));
+			continue;
+		}
+
+		val = I915_READ(DSPCNTR(plane));
+
+		if (INTEL_INFO(dev)->gen >= 4) {
+			if (val & DISPPLANE_TILED) {
+				DRM_DEBUG_KMS("tiled BIOS fb?\n");
+				continue; /* unexpected! */
+			}
+		}
+
+		switch (val & DISPPLANE_PIXFORMAT_MASK) {
+		case DISPPLANE_YUV422:
+		default:
+			DRM_DEBUG_KMS("pipe %c unsupported pixel format %x, skipping\n",
+				      pipe_name(pipe), (val & DISPPLANE_PIXFORMAT_MASK) >> 26);
+			continue;
+		case DISPPLANE_8BPP:
+			format = DRM_FORMAT_C8;
+			bpp = 8;
+			break;
+		case DISPPLANE_BGRX555:
+			format = DRM_FORMAT_XRGB1555;
+			bpp = 16;
+			break;
+		case DISPPLANE_BGRX565:
+			format = DRM_FORMAT_RGB565;
+			bpp = 16;
+			break;
+		case DISPPLANE_BGRX888:
+			format = DRM_FORMAT_XRGB8888;
+			bpp = 32;
+			break;
+		}
+
+		if (mode_cmd.pixel_format == 0) {
+			mode_bpp = bpp;
+			mode_cmd.pixel_format = format;
+		}
+
+		if (mode_cmd.pixel_format != format) {
+			DRM_DEBUG_KMS("pipe %c has format/bpp (%d, %d) mismatch: skipping\n",
+				      pipe_name(pipe), format, bpp);
+			continue;
+		}
+
+		if (INTEL_INFO(dev)->gen >= 4) {
+			if (I915_READ(DSPTILEOFF(plane))) {
+				DRM_DEBUG_KMS("pipe %c is offset: skipping\n",
+					      pipe_name(pipe));
+				continue;
+			}
+
+			offset = I915_READ(DSPSURF(plane)) & 0xfffff000;
+		} else {
+			offset = I915_READ(DSPADDR(plane));
+		}
+		if (!obj_offset)
+			obj_offset = offset;
+
+		if (offset != obj_offset) {
+			DRM_DEBUG_KMS("multiple pipe setup not in clone mode, skipping\n");
+			continue;
+		}
+
+		val = I915_READ(PIPESRC(pipe));
+		width = ((val >> 16) & 0xfff) + 1;
+		height = ((val >> 0) & 0xfff) + 1;
+
+		/* Adjust fitted modes */
+		val = I915_READ(HTOTAL(pipe));
+		if (((val & 0xffff) + 1) != width) {
+			DRM_DEBUG_DRIVER("BIOS fb not native width (%d vs %d), overriding\n", width, (val & 0xffff) + 1);
+			width = (val & 0xffff) + 1;
+		}
+		val = I915_READ(VTOTAL(pipe));
+		if (((val & 0xffff) + 1) != height) {
+			DRM_DEBUG_DRIVER("BIOS fb not native height (%d vs %d), overriding\n", height, (val & 0xffff) + 1);
+			height = (val & 0xffff) + 1;
+		}
+
+		DRM_DEBUG_KMS("Found active pipe [%d/%d]: size=%dx%d@%d, offset=%x\n",
+			      pipe, plane, width, height, bpp, offset);
+
+		if (width > mode_cmd.width)
+			mode_cmd.width = width;
+
+		if (height > mode_cmd.height)
+			mode_cmd.height = height;
+
+		pitch = intel_framebuffer_pitch_for_width(width, bpp);
+		if (pitch > mode_cmd.pitches[0])
+			mode_cmd.pitches[0] = pitch;
+
+		active |= 1 << pipe;
+	}
+
+	if (active == 0) {
+		DRM_DEBUG_KMS("no active pipes found, not using BIOS config\n");
+		return;
+	}
+
+	ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
+	if (ifbdev == NULL) {
+		DRM_DEBUG_KMS("failed to alloc intel fbdev\n");
+		return;
+	}
+
+	ifbdev->stolen = true;
+	ifbdev->preferred_bpp = mode_bpp;
+	ifbdev->helper.funcs = &intel_fb_helper_funcs;
+	ifbdev->helper.funcs->initial_config = intel_fb_initial_config;
+
+	/* assume a 1:1 linear mapping between stolen and GTT */
+	obj = i915_gem_object_create_stolen_for_preallocated(dev,
+							     obj_offset,
+							     obj_offset,
+							     ALIGN(mode_cmd.pitches[0] * mode_cmd.height, PAGE_SIZE));
+	if (obj == NULL) {
+		DRM_DEBUG_KMS("failed to create stolen fb\n");
+		goto out_free_ifbdev;
+	}
+
+	mutex_lock(&dev->struct_mutex);
+
+	if (intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj)) {
+		DRM_DEBUG_KMS("intel fb init failed\n");
+		goto out_unref_obj;
+	}
+
+	/* Assuming a single fb across all pipes here */
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		if ((active & (1 << to_intel_crtc(crtc)->pipe)) == 0)
+			continue;
+
+		crtc->fb = &ifbdev->ifb.base;
+	}
+
+	dev_priv->fbdev = ifbdev;
+
+	DRM_DEBUG_KMS("using BIOS fb for initial console\n");
+	mutex_unlock(&dev->struct_mutex);
+	return;
+
+out_unref_obj:
+	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_unreference_unlocked(&obj->base);
+out_free_ifbdev:
+	kfree(ifbdev);
+}
+
 int intel_fbdev_init(struct drm_device *dev)
 {
 	struct intel_fbdev *ifbdev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
-	ifbdev = kzalloc(sizeof(*ifbdev), GFP_KERNEL);
-	if (!ifbdev)
-		return -ENOMEM;
+	if ((ifbdev = dev_priv->fbdev) == NULL) {
+		ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
+		if (ifbdev == NULL)
+			return -ENOMEM;
+
+		ifbdev->helper.funcs = &intel_fb_helper_funcs;
+		ifbdev->preferred_bpp = 32;
+
+		dev_priv->fbdev = ifbdev;
+	}
 
-	dev_priv->fbdev = ifbdev;
 	ifbdev->helper.funcs = &intel_fb_helper_funcs;
 
 	ret = drm_fb_helper_init(dev, &ifbdev->helper,
 				 INTEL_INFO(dev)->num_pipes,
 				 4);
 	if (ret) {
+		dev_priv->fbdev = NULL;
 		kfree(ifbdev);
 		return ret;
 	}
@@ -260,9 +533,10 @@ int intel_fbdev_init(struct drm_device *dev)
 void intel_fbdev_initial_config(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_fbdev *ifbdev = dev_priv->fbdev;
 
 	/* Due to peculiar init order wrt to hpd handling this is separate. */
-	drm_fb_helper_initial_config(&dev_priv->fbdev->helper, 32);
+	drm_fb_helper_initial_config(&ifbdev->helper, ifbdev->preferred_bpp);
 }
 
 void intel_fbdev_fini(struct drm_device *dev)
@@ -302,7 +576,8 @@ MODULE_LICENSE("GPL and additional rights");
 void intel_fbdev_output_poll_changed(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
+	if (dev_priv->fbdev)
+		drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
 }
 
 void intel_fbdev_restore_mode(struct drm_device *dev)
-- 
1.8.4.2

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

* Re: [PATCH] drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v4
  2013-11-06 19:25 ` [PATCH] drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v4 Jesse Barnes
@ 2013-11-07 14:22   ` Chris Wilson
  2013-11-07 16:28     ` Jesse Barnes
  2013-11-07 16:39   ` Chris Wilson
  2013-11-07 19:40   ` [PATCH] drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v5 Jesse Barnes
  2 siblings, 1 reply; 7+ messages in thread
From: Chris Wilson @ 2013-11-07 14:22 UTC (permalink / raw
  To: Jesse Barnes; +Cc: intel-gfx

On Wed, Nov 06, 2013 at 11:25:55AM -0800, Jesse Barnes wrote:
> Retrieve current framebuffer config info from the regs and create an fb
> object for the buffer the BIOS or boot loader left us.  This should
> allow for smooth transitions to userspace apps once we finish the
> initial configuration construction.
> 
> v2: check for non-native modes and adjust (Jesse)
>     fixup aperture and cmap frees (Imre)
>     use unlocked unref if init_bios fails (Jesse)
>     fix curly brace around DSPADDR check (Imre)
>     comment failure path for pin_and_fence (Imre)
> v3: fixup fixup of aperture frees (Chris)
> v4: update to current bits (locking & pin_and_fence hack) (Jesse)

The only thing that I noticed was that the bookkeeping for the fb/obj is
incorrect - which is presumably the hack mentioned above.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH] drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v4
  2013-11-07 14:22   ` Chris Wilson
@ 2013-11-07 16:28     ` Jesse Barnes
  0 siblings, 0 replies; 7+ messages in thread
From: Jesse Barnes @ 2013-11-07 16:28 UTC (permalink / raw
  To: Chris Wilson; +Cc: intel-gfx

On Thu, 7 Nov 2013 14:22:55 +0000
Chris Wilson <chris@chris-wilson.co.uk> wrote:

> On Wed, Nov 06, 2013 at 11:25:55AM -0800, Jesse Barnes wrote:
> > Retrieve current framebuffer config info from the regs and create an fb
> > object for the buffer the BIOS or boot loader left us.  This should
> > allow for smooth transitions to userspace apps once we finish the
> > initial configuration construction.
> > 
> > v2: check for non-native modes and adjust (Jesse)
> >     fixup aperture and cmap frees (Imre)
> >     use unlocked unref if init_bios fails (Jesse)
> >     fix curly brace around DSPADDR check (Imre)
> >     comment failure path for pin_and_fence (Imre)
> > v3: fixup fixup of aperture frees (Chris)
> > v4: update to current bits (locking & pin_and_fence hack) (Jesse)
> 
> The only thing that I noticed was that the bookkeeping for the fb/obj is
> incorrect - which is presumably the hack mentioned above.

Yeah I should have left the pin_and_fence in with an #if 0 to make that
clearer... is that the only thing that's missing?

Any thoughts on why the pin_and_fence falls over on the preallocated
object?

-- 
Jesse Barnes, Intel Open Source Technology Center

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

* Re: [PATCH] drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v4
  2013-11-06 19:25 ` [PATCH] drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v4 Jesse Barnes
  2013-11-07 14:22   ` Chris Wilson
@ 2013-11-07 16:39   ` Chris Wilson
  2013-11-07 19:40   ` [PATCH] drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v5 Jesse Barnes
  2 siblings, 0 replies; 7+ messages in thread
From: Chris Wilson @ 2013-11-07 16:39 UTC (permalink / raw
  To: Jesse Barnes; +Cc: intel-gfx

On Wed, Nov 06, 2013 at 11:25:55AM -0800, Jesse Barnes wrote:
> Retrieve current framebuffer config info from the regs and create an fb
> object for the buffer the BIOS or boot loader left us.  This should
> allow for smooth transitions to userspace apps once we finish the
> initial configuration construction.
> 
> v2: check for non-native modes and adjust (Jesse)
>     fixup aperture and cmap frees (Imre)
>     use unlocked unref if init_bios fails (Jesse)
>     fix curly brace around DSPADDR check (Imre)
>     comment failure path for pin_and_fence (Imre)
> v3: fixup fixup of aperture frees (Chris)
> v4: update to current bits (locking & pin_and_fence hack) (Jesse)
> 
> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> ---
>  drivers/gpu/drm/i915/i915_dma.c      |   8 +-
>  drivers/gpu/drm/i915/i915_drv.h      |   2 +-
>  drivers/gpu/drm/i915/intel_display.c |  14 +-
>  drivers/gpu/drm/i915/intel_drv.h     |   4 +
>  drivers/gpu/drm/i915/intel_fbdev.c   | 295 +++++++++++++++++++++++++++++++++--
>  5 files changed, 308 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index 0cab2d0..d8eed45 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -1277,6 +1277,7 @@ static const struct vga_switcheroo_client_ops i915_switcheroo_ops = {
>  static int i915_load_modeset_init(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> +	bool was_vga_enabled;
>  	int ret;
>  
>  	ret = intel_parse_bios(dev);
> @@ -1315,7 +1316,11 @@ static int i915_load_modeset_init(struct drm_device *dev)
>  
>  	/* Important: The output setup functions called by modeset_init need
>  	 * working irqs for e.g. gmbus and dp aux transfers. */
> -	intel_modeset_init(dev);
> +	intel_modeset_init(dev, &was_vga_enabled);
> +
> +	/* Wrap existing BIOS mode configuration prior to GEM takeover */
> +	if (!was_vga_enabled)
> +		intel_fbdev_init_bios(dev);

We attempt to pin into the GTT here, but...
 
>  	ret = i915_gem_init(dev);

GTT drm_mm range manager is only now initialised.

That would seem to explain an oops in drm_mm.c
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* [PATCH] drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v5
  2013-11-06 19:25 ` [PATCH] drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v4 Jesse Barnes
  2013-11-07 14:22   ` Chris Wilson
  2013-11-07 16:39   ` Chris Wilson
@ 2013-11-07 19:40   ` Jesse Barnes
  2013-11-07 19:56     ` Jesse Barnes
  2 siblings, 1 reply; 7+ messages in thread
From: Jesse Barnes @ 2013-11-07 19:40 UTC (permalink / raw
  To: intel-gfx

Retrieve current framebuffer config info from the regs and create an fb
object for the buffer the BIOS or boot loader left us.  This should
allow for smooth transitions to userspace apps once we finish the
initial configuration construction.

v2: check for non-native modes and adjust (Jesse)
    fixup aperture and cmap frees (Imre)
    use unlocked unref if init_bios fails (Jesse)
    fix curly brace around DSPADDR check (Imre)
    comment failure path for pin_and_fence (Imre)
v3: fixup fixup of aperture frees (Chris)
v4: update to current bits (locking & pin_and_fence hack) (Jesse)
v5: move fb config fetch to display code (Jesse)
    re-order hw state readout on initial load to suit fb inherit (Jesse)
    re-add pin_and_fence in fbdev code to make sure we refcount properly (Jesse)

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/i915_dma.c      |   4 -
 drivers/gpu/drm/i915/i915_drv.c      |   5 ++
 drivers/gpu/drm/i915/i915_drv.h      |   2 +
 drivers/gpu/drm/i915/intel_display.c | 139 +++++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/intel_dp.c      |   2 +-
 drivers/gpu/drm/i915/intel_drv.h     |  14 ++++
 drivers/gpu/drm/i915/intel_fbdev.c   | 149 +++++++----------------------------
 7 files changed, 176 insertions(+), 139 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index d8eed45..805cdfe 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1318,10 +1318,6 @@ static int i915_load_modeset_init(struct drm_device *dev)
 	 * working irqs for e.g. gmbus and dp aux transfers. */
 	intel_modeset_init(dev, &was_vga_enabled);
 
-	/* Wrap existing BIOS mode configuration prior to GEM takeover */
-	if (!was_vga_enabled)
-		intel_fbdev_init_bios(dev);
-
 	ret = i915_gem_init(dev);
 	if (ret)
 		goto cleanup_power;
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index a78e779..a23a9c2 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -154,6 +154,11 @@ module_param_named(prefault_disable, i915_prefault_disable, bool, 0600);
 MODULE_PARM_DESC(prefault_disable,
 		"Disable page prefaulting for pread/pwrite/reloc (default:false). For developers only.");
 
+bool i915_use_bios_fb __read_mostly = 1;
+module_param_named(use_bios_fb, i915_use_bios_fb, bool, 0600);
+MODULE_PARM_DESC(use_bios_fb,
+		 "Use BIOS allocated framebuffer for fbcon (default: true)");
+
 static struct drm_driver driver;
 extern int intel_agp_enabled;
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 100d3cf..ff40c7f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -390,6 +390,7 @@ struct drm_i915_display_funcs {
 	 * fills out the pipe-config with the hw state. */
 	bool (*get_pipe_config)(struct intel_crtc *,
 				struct intel_crtc_config *);
+	void (*get_fb_config)(struct intel_crtc *, struct intel_crtc_config *);
 	int (*crtc_mode_set)(struct drm_crtc *crtc,
 			     int x, int y,
 			     struct drm_framebuffer *old_fb);
@@ -1861,6 +1862,7 @@ extern bool i915_fastboot __read_mostly;
 extern int i915_enable_pc8 __read_mostly;
 extern int i915_pc8_timeout __read_mostly;
 extern bool i915_prefault_disable __read_mostly;
+extern bool i915_use_bios_fb __read_mostly;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
 extern int i915_resume(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f6e4792..d47f894 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1994,6 +1994,27 @@ unsigned long intel_gen4_compute_page_offset(int *x, int *y,
 	}
 }
 
+int intel_format_to_fourcc(int format)
+{
+	switch (format) {
+	case DISPPLANE_8BPP:
+		return DRM_FORMAT_C8;
+	case DISPPLANE_BGRX555:
+		return DRM_FORMAT_ARGB1555;
+	case DISPPLANE_BGRX565:
+		return DRM_FORMAT_RGB565;
+	default:
+	case DISPPLANE_BGRX888:
+		return DRM_FORMAT_XRGB8888;
+	case DISPPLANE_RGBX888:
+		return DRM_FORMAT_XBGR8888;
+	case DISPPLANE_BGRX101010:
+		return DRM_FORMAT_XRGB2101010;
+	case DISPPLANE_RGBX101010:
+		return DRM_FORMAT_XBGR2101010;
+	}
+}
+
 static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 			     int x, int y)
 {
@@ -5444,6 +5465,93 @@ static void vlv_crtc_clock_get(struct intel_crtc *crtc,
 	pipe_config->port_clock = clock.dot / 5;
 }
 
+static u32
+intel_framebuffer_pitch_for_width(int width, int bpp, bool tiled)
+{
+	u32 pitch = DIV_ROUND_UP(width * bpp, 8);
+
+	if (tiled)
+		return ALIGN(pitch, 512);
+	else
+		return ALIGN(pitch, 64);
+}
+
+static void i9xx_get_fb_config(struct intel_crtc *crtc,
+			       struct intel_crtc_config *pipe_config)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_fb_config *fb_config = &pipe_config->fb_config;
+	int pipe = crtc->pipe, plane = crtc->plane, size;
+	u32 val;
+
+	WARN(1, "getting config for pipe %d\n", pipe);
+
+	val = I915_READ(DSPCNTR(plane));
+
+	if (INTEL_INFO(dev)->gen >= 4)
+		if (val & DISPPLANE_TILED)
+			fb_config->tiled = true;
+
+	fb_config->pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
+
+	switch (fb_config->pixel_format) {
+	case DISPPLANE_8BPP:
+	case DISPPLANE_YUV422:
+		fb_config->bpp = 8;
+		break;
+	case DISPPLANE_BGRX555:
+	case DISPPLANE_BGRX565:
+	case DISPPLANE_BGRA555:
+		fb_config->bpp = 16;
+		break;
+	case DISPPLANE_BGRX888:
+	case DISPPLANE_BGRA888:
+	case DISPPLANE_RGBX888:
+	case DISPPLANE_RGBA888:
+	case DISPPLANE_RGBX101010:
+	case DISPPLANE_RGBA101010:
+	case DISPPLANE_BGRX101010:
+		fb_config->bpp = 32;
+		break;
+	}
+
+	if (INTEL_INFO(dev)->gen >= 4) {
+		if (fb_config->tiled)
+			fb_config->offset = I915_READ(DSPTILEOFF(plane));
+		else
+			fb_config->offset = I915_READ(DSPLINOFF(plane));
+		fb_config->base = I915_READ(DSPSURF(plane)) & 0xfffff000;
+	} else {
+		fb_config->base = I915_READ(DSPADDR(plane));
+	}
+
+	val = I915_READ(PIPESRC(pipe));
+	fb_config->pipe_width = ((val >> 16) & 0xfff) + 1;
+	fb_config->pipe_height = ((val >> 0) & 0xfff) + 1;
+
+	val = I915_READ(HTOTAL(pipe));
+	fb_config->fb_width = (val & 0xffff) + 1;
+	val = I915_READ(VTOTAL(pipe));
+	fb_config->fb_height = (val & 0xffff) + 1;
+
+	DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x\n",
+		      pipe, plane, fb_config->fb_width, fb_config->fb_height,
+		      fb_config->bpp, fb_config->base);
+
+	fb_config->pitch =
+		intel_framebuffer_pitch_for_width(fb_config->fb_width,
+						  fb_config->bpp,
+						  fb_config->tiled);
+
+	size = ALIGN(fb_config->pitch * fb_config->fb_height, PAGE_SIZE);
+	fb_config->obj =
+		i915_gem_object_create_stolen_for_preallocated(dev,
+							       fb_config->base,
+							       fb_config->base,
+							       size);
+}
+
 static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
 				 struct intel_crtc_config *pipe_config)
 {
@@ -7621,16 +7729,10 @@ err:
 }
 
 static u32
-intel_framebuffer_pitch_for_width(int width, int bpp)
-{
-	u32 pitch = DIV_ROUND_UP(width * bpp, 8);
-	return ALIGN(pitch, 64);
-}
-
-static u32
 intel_framebuffer_size_for_mode(struct drm_display_mode *mode, int bpp)
 {
-	u32 pitch = intel_framebuffer_pitch_for_width(mode->hdisplay, bpp);
+	u32 pitch = intel_framebuffer_pitch_for_width(mode->hdisplay, bpp,
+						      false);
 	return ALIGN(pitch * mode->vdisplay, PAGE_SIZE);
 }
 
@@ -7650,7 +7752,7 @@ intel_framebuffer_create_for_mode(struct drm_device *dev,
 	mode_cmd.width = mode->hdisplay;
 	mode_cmd.height = mode->vdisplay;
 	mode_cmd.pitches[0] = intel_framebuffer_pitch_for_width(mode_cmd.width,
-								bpp);
+								bpp, false);
 	mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
 
 	return intel_framebuffer_create(dev, &mode_cmd, obj);
@@ -7674,7 +7776,8 @@ mode_fits_in_fbdev(struct drm_device *dev,
 
 	fb = &dev_priv->fbdev->ifb.base;
 	if (fb->pitches[0] < intel_framebuffer_pitch_for_width(mode->hdisplay,
-							       fb->bits_per_pixel))
+							       fb->bits_per_pixel,
+							       false))
 		return NULL;
 
 	if (obj->base.size < mode->vdisplay * fb->pitches[0])
@@ -10505,6 +10608,7 @@ static void intel_init_display(struct drm_device *dev)
 		dev_priv->display.update_plane = ironlake_update_plane;
 	} else if (IS_VALLEYVIEW(dev)) {
 		dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
+		dev_priv->display.get_fb_config = i9xx_get_fb_config;
 		dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
 		dev_priv->display.crtc_enable = valleyview_crtc_enable;
 		dev_priv->display.crtc_disable = i9xx_crtc_disable;
@@ -10512,6 +10616,7 @@ static void intel_init_display(struct drm_device *dev)
 		dev_priv->display.update_plane = i9xx_update_plane;
 	} else {
 		dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
+		dev_priv->display.get_fb_config = i9xx_get_fb_config;
 		dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
 		dev_priv->display.crtc_enable = i9xx_crtc_enable;
 		dev_priv->display.crtc_disable = i9xx_crtc_disable;
@@ -10788,6 +10893,7 @@ void intel_modeset_init(struct drm_device *dev,
 			bool *was_vga_enabled)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *crtc;
 	int i, j, ret;
 
 	drm_mode_config_init(dev);
@@ -10844,6 +10950,17 @@ void intel_modeset_init(struct drm_device *dev,
 
 	/* Just in case the BIOS is doing something questionable. */
 	intel_disable_fbc(dev);
+
+	intel_modeset_setup_hw_state(dev, false);
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list,
+			    base.head) {
+		if (!crtc->active)
+			continue;
+
+		if (dev_priv->display.get_fb_config)
+			dev_priv->display.get_fb_config(crtc, &crtc->config);
+	}
 }
 
 static void
@@ -11214,8 +11331,6 @@ void intel_modeset_gem_init(struct drm_device *dev)
 	intel_modeset_init_hw(dev);
 
 	intel_setup_overlay(dev);
-
-	intel_modeset_setup_hw_state(dev, false);
 }
 
 void intel_modeset_cleanup(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 28abeea..c7137e8 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1230,7 +1230,7 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 	WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
 
 	pp = ironlake_get_pp_control(intel_dp);
-	pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE);
+	pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE);
 
 	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index be048d9..7b4281c 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -200,6 +200,17 @@ typedef struct dpll {
 	int	p;
 } intel_clock_t;
 
+struct intel_fb_config {
+	int pixel_format; /* DRM fourcc code */
+	int bpp;
+	bool tiled;
+	int base, offset;
+	int fb_width, fb_height;
+	int pipe_width, pipe_height;
+	int pitch;
+	struct drm_i915_gem_object *obj;
+};
+
 struct intel_crtc_config {
 	/**
 	 * quirks - bitfield with hw state readout quirks
@@ -222,6 +233,8 @@ struct intel_crtc_config {
 	 * registers. adjusted_mode.crtc_clock is the pipe pixel clock. */
 	struct drm_display_mode adjusted_mode;
 
+	struct intel_fb_config fb_config;
+
 	/* Pipe source size (ie. panel fitter input size)
 	 * All planes will be positioned inside this space,
 	 * and get clipped at the edges. */
@@ -699,6 +712,7 @@ void hsw_enable_ips(struct intel_crtc *crtc);
 void hsw_disable_ips(struct intel_crtc *crtc);
 void intel_display_set_init_power(struct drm_device *dev, bool enable);
 int valleyview_get_vco(struct drm_i915_private *dev_priv);
+int intel_format_to_fourcc(int format);
 
 /* intel_dp.c */
 void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 2d71312..237b6e4 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -298,13 +298,6 @@ static bool pipe_enabled(struct drm_i915_private *dev_priv, enum pipe pipe)
 	return !!(I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_ENABLE);
 }
 
-static u32
-intel_framebuffer_pitch_for_width(int width, int bpp)
-{
-	u32 pitch = DIV_ROUND_UP(width * bpp, 8);
-	return ALIGN(pitch, 64);
-}
-
 /*
  * Try to read the BIOS display configuration and use it for the initial
  * fb configuration.
@@ -330,119 +323,26 @@ void intel_fbdev_init_bios(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_fbdev *ifbdev;
 	struct drm_crtc *crtc;
+	struct intel_crtc *intel_crtc;
+	struct intel_fb_config *fb_config;
 	struct drm_mode_fb_cmd2 mode_cmd = { 0 };
-	struct drm_i915_gem_object *obj;
-	u32 obj_offset = 0;
-	int mode_bpp = 0;
 	u32 active = 0;
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-		int pipe = intel_crtc->pipe, plane = intel_crtc->plane;
-		u32 val, bpp, offset, format;
-		int pitch, width, height;
+		intel_crtc = to_intel_crtc(crtc);
 
-		if (!pipe_enabled(dev_priv, pipe)) {
+		if (!pipe_enabled(dev_priv, intel_crtc->pipe)) {
 			DRM_DEBUG_KMS("pipe %c not active, skipping\n",
-				      pipe_name(pipe));
+				      pipe_name(intel_crtc->pipe));
 			continue;
 		}
 
-		val = I915_READ(DSPCNTR(plane));
-
-		if (INTEL_INFO(dev)->gen >= 4) {
-			if (val & DISPPLANE_TILED) {
-				DRM_DEBUG_KMS("tiled BIOS fb?\n");
-				continue; /* unexpected! */
-			}
-		}
-
-		switch (val & DISPPLANE_PIXFORMAT_MASK) {
-		case DISPPLANE_YUV422:
-		default:
-			DRM_DEBUG_KMS("pipe %c unsupported pixel format %x, skipping\n",
-				      pipe_name(pipe), (val & DISPPLANE_PIXFORMAT_MASK) >> 26);
-			continue;
-		case DISPPLANE_8BPP:
-			format = DRM_FORMAT_C8;
-			bpp = 8;
-			break;
-		case DISPPLANE_BGRX555:
-			format = DRM_FORMAT_XRGB1555;
-			bpp = 16;
-			break;
-		case DISPPLANE_BGRX565:
-			format = DRM_FORMAT_RGB565;
-			bpp = 16;
-			break;
-		case DISPPLANE_BGRX888:
-			format = DRM_FORMAT_XRGB8888;
-			bpp = 32;
-			break;
-		}
-
-		if (mode_cmd.pixel_format == 0) {
-			mode_bpp = bpp;
-			mode_cmd.pixel_format = format;
-		}
-
-		if (mode_cmd.pixel_format != format) {
-			DRM_DEBUG_KMS("pipe %c has format/bpp (%d, %d) mismatch: skipping\n",
-				      pipe_name(pipe), format, bpp);
-			continue;
-		}
-
-		if (INTEL_INFO(dev)->gen >= 4) {
-			if (I915_READ(DSPTILEOFF(plane))) {
-				DRM_DEBUG_KMS("pipe %c is offset: skipping\n",
-					      pipe_name(pipe));
-				continue;
-			}
-
-			offset = I915_READ(DSPSURF(plane)) & 0xfffff000;
-		} else {
-			offset = I915_READ(DSPADDR(plane));
-		}
-		if (!obj_offset)
-			obj_offset = offset;
-
-		if (offset != obj_offset) {
-			DRM_DEBUG_KMS("multiple pipe setup not in clone mode, skipping\n");
-			continue;
-		}
-
-		val = I915_READ(PIPESRC(pipe));
-		width = ((val >> 16) & 0xfff) + 1;
-		height = ((val >> 0) & 0xfff) + 1;
-
-		/* Adjust fitted modes */
-		val = I915_READ(HTOTAL(pipe));
-		if (((val & 0xffff) + 1) != width) {
-			DRM_DEBUG_DRIVER("BIOS fb not native width (%d vs %d), overriding\n", width, (val & 0xffff) + 1);
-			width = (val & 0xffff) + 1;
-		}
-		val = I915_READ(VTOTAL(pipe));
-		if (((val & 0xffff) + 1) != height) {
-			DRM_DEBUG_DRIVER("BIOS fb not native height (%d vs %d), overriding\n", height, (val & 0xffff) + 1);
-			height = (val & 0xffff) + 1;
-		}
-
-		DRM_DEBUG_KMS("Found active pipe [%d/%d]: size=%dx%d@%d, offset=%x\n",
-			      pipe, plane, width, height, bpp, offset);
-
-		if (width > mode_cmd.width)
-			mode_cmd.width = width;
-
-		if (height > mode_cmd.height)
-			mode_cmd.height = height;
-
-		pitch = intel_framebuffer_pitch_for_width(width, bpp);
-		if (pitch > mode_cmd.pitches[0])
-			mode_cmd.pitches[0] = pitch;
-
-		active |= 1 << pipe;
+		active |= 1 << intel_crtc->pipe;
+		break;
 	}
 
+	fb_config = &intel_crtc->config.fb_config;
+
 	if (active == 0) {
 		DRM_DEBUG_KMS("no active pipes found, not using BIOS config\n");
 		return;
@@ -455,23 +355,19 @@ void intel_fbdev_init_bios(struct drm_device *dev)
 	}
 
 	ifbdev->stolen = true;
-	ifbdev->preferred_bpp = mode_bpp;
+	ifbdev->preferred_bpp = fb_config->bpp;
 	ifbdev->helper.funcs = &intel_fb_helper_funcs;
 	ifbdev->helper.funcs->initial_config = intel_fb_initial_config;
 
-	/* assume a 1:1 linear mapping between stolen and GTT */
-	obj = i915_gem_object_create_stolen_for_preallocated(dev,
-							     obj_offset,
-							     obj_offset,
-							     ALIGN(mode_cmd.pitches[0] * mode_cmd.height, PAGE_SIZE));
-	if (obj == NULL) {
-		DRM_DEBUG_KMS("failed to create stolen fb\n");
-		goto out_free_ifbdev;
-	}
+	mode_cmd.pixel_format = intel_format_to_fourcc(fb_config->pixel_format);
+	mode_cmd.width = fb_config->fb_width;
+	mode_cmd.height = fb_config->fb_height;
+	mode_cmd.pitches[0] = fb_config->pitch;
 
 	mutex_lock(&dev->struct_mutex);
 
-	if (intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj)) {
+	if (intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd,
+				   fb_config->obj)) {
 		DRM_DEBUG_KMS("intel fb init failed\n");
 		goto out_unref_obj;
 	}
@@ -481,6 +377,13 @@ void intel_fbdev_init_bios(struct drm_device *dev)
 		if ((active & (1 << to_intel_crtc(crtc)->pipe)) == 0)
 			continue;
 
+		/*
+		 * This should only fail on the first one so we don't need
+		 * to cleanup any secondary crtc->fbs
+		 */
+		if (intel_pin_and_fence_fb_obj(dev, fb_config->obj, NULL))
+			goto out_unref_obj;
+
 		crtc->fb = &ifbdev->ifb.base;
 	}
 
@@ -492,8 +395,7 @@ void intel_fbdev_init_bios(struct drm_device *dev)
 
 out_unref_obj:
 	mutex_unlock(&dev->struct_mutex);
-	drm_gem_object_unreference_unlocked(&obj->base);
-out_free_ifbdev:
+	drm_gem_object_unreference_unlocked(&fb_config->obj->base);
 	kfree(ifbdev);
 }
 
@@ -503,6 +405,9 @@ int intel_fbdev_init(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
+	if (i915_use_bios_fb)
+		intel_fbdev_init_bios(dev);
+
 	if ((ifbdev = dev_priv->fbdev) == NULL) {
 		ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
 		if (ifbdev == NULL)
-- 
1.8.4.2

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

* Re: [PATCH] drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v5
  2013-11-07 19:40   ` [PATCH] drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v5 Jesse Barnes
@ 2013-11-07 19:56     ` Jesse Barnes
  0 siblings, 0 replies; 7+ messages in thread
From: Jesse Barnes @ 2013-11-07 19:56 UTC (permalink / raw
  Cc: intel-gfx

Note that with this patch I see this on boot when the preallocated
objects are scanned:

[    3.951078] WARNING: CPU: 1 PID: 398 at lib/list_debug.c:36 __list_add+0x8a/0
xc0()
[    3.951081] list_add double add: new=ffff88003fa42ba8, prev=ffff88003f9903c0,
 next=ffff88003fa42ba8.
[    3.951083] Modules linked in: coretemp snd_hda_intel(+) kvm_intel kvm vfat f
at i915(OF+) snd_hda_codec snd_hwdep crc32_pclmul snd_seq crc32c_intel snd_seq_d
evice snd_pcm ghash_clmulni_intel microcode snd_page_alloc snd_timer snd asix se
rio_raw soundcore usbnet shpchp mii i2c_algo_bit drm_kms_helper(OF) drm(OF) i2c_
core sdhci_acpi video nfsd sdhci mmc_core acpi_cpufreq auth_rpcgss nfs_acl lockd
 sunrpc usb_storage
[    3.951122] CPU: 1 PID: 398 Comm: systemd-udevd Tainted: GF       W  O 3.12.0+ #8
[    3.951125] Hardware name: Intel Corp. VALLEYVIEW B3 PLATFORM/NOTEBOOK, BIOS BBAYCRB1.X64.0060.R40.1309121618 BBAY_X64_R_V60_40 09/12/2013
[    3.951127]  0000000000000009 ffff88003ffd3790 ffffffff81640eb8 ffff88003ffd37d8
[    3.951132]  ffff88003ffd37c8 ffffffff810680dd ffff88003fa42ba8 ffff88003fa42ba8
[    3.951136]  ffff88003f9903c0 ffff8800752ce870 ffff88003f990300 ffff88003ffd3828
[    3.951140] Call Trace:
[    3.951148]  [<ffffffff81640eb8>] dump_stack+0x45/0x56
[    3.951154]  [<ffffffff810680dd>] warn_slowpath_common+0x7d/0xa0
[    3.951158]  [<ffffffff8106814c>] warn_slowpath_fmt+0x4c/0x50
[    3.951178]  [<ffffffffa01313f5>] ? drm_mm_reserve_node+0xe5/0x170 [drm]
[    3.951199]  [<ffffffff8130e6ea>] __list_add+0x8a/0xc0
[    3.951230]  [<ffffffffa02863a0>] i915_gem_setup_global_gtt+0xc0/0x280 [i915]
[    3.951256]  [<ffffffffa02869a4>] i915_gem_init_global_gtt+0x444/0x980 [i915]
[    3.951280]  [<ffffffffa0290f38>] ? i9xx_get_fb_config+0x268/0x370 [i915]
[    3.951304]  [<ffffffffa027c2a2>] i915_gem_init+0x42/0x180 [i915]
[    3.951324]  [<ffffffffa0266080>] i915_driver_load+0xc50/0xf10 [i915]
...

So something is still off with the block management of stolen objects
in this patch...

-- 
Jesse Barnes, Intel Open Source Technology Center

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

end of thread, other threads:[~2013-11-07 20:02 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-11-06 19:02 [WIP] Wrap fb objects from BIOS/bootloader Jesse Barnes
2013-11-06 19:25 ` [PATCH] drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v4 Jesse Barnes
2013-11-07 14:22   ` Chris Wilson
2013-11-07 16:28     ` Jesse Barnes
2013-11-07 16:39   ` Chris Wilson
2013-11-07 19:40   ` [PATCH] drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v5 Jesse Barnes
2013-11-07 19:56     ` Jesse Barnes

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.