intel_fbdev.c 21.6 KB
Newer Older
J
Jesse Barnes 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/*
 * Copyright © 2007 David Airlie
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * Authors:
 *     David Airlie
 */

27
#include <linux/async.h>
J
Jesse Barnes 已提交
28 29
#include <linux/module.h>
#include <linux/kernel.h>
30
#include <linux/console.h>
J
Jesse Barnes 已提交
31 32 33 34 35 36 37 38
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/tty.h>
#include <linux/sysrq.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h>
39
#include <linux/vga_switcheroo.h>
J
Jesse Barnes 已提交
40

41 42 43
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
#include <drm/drm_fb_helper.h>
J
Jesse Barnes 已提交
44
#include "intel_drv.h"
45
#include <drm/i915_drm.h>
J
Jesse Barnes 已提交
46 47
#include "i915_drv.h"

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
static int intel_fbdev_set_par(struct fb_info *info)
{
	struct drm_fb_helper *fb_helper = info->par;
	struct intel_fbdev *ifbdev =
		container_of(fb_helper, struct intel_fbdev, helper);
	int ret;

	ret = drm_fb_helper_set_par(info);

	if (ret == 0) {
		/*
		 * FIXME: fbdev presumes that all callbacks also work from
		 * atomic contexts and relies on that for emergency oops
		 * printing. KMS totally doesn't do that and the locking here is
		 * by far not the only place this goes wrong.  Ignore this for
		 * now until we solve this for real.
		 */
		mutex_lock(&fb_helper->dev->struct_mutex);
		ret = i915_gem_object_set_to_gtt_domain(ifbdev->fb->obj,
							true);
		mutex_unlock(&fb_helper->dev->struct_mutex);
	}

	return ret;
}

J
Jesse Barnes 已提交
74 75
static struct fb_ops intelfb_ops = {
	.owner = THIS_MODULE,
76
	.fb_check_var = drm_fb_helper_check_var,
77
	.fb_set_par = intel_fbdev_set_par,
J
Jesse Barnes 已提交
78 79 80
	.fb_fillrect = cfb_fillrect,
	.fb_copyarea = cfb_copyarea,
	.fb_imageblit = cfb_imageblit,
81 82
	.fb_pan_display = drm_fb_helper_pan_display,
	.fb_blank = drm_fb_helper_blank,
83
	.fb_setcmap = drm_fb_helper_setcmap,
J
Jesse Barnes 已提交
84 85
	.fb_debug_enter = drm_fb_helper_debug_enter,
	.fb_debug_leave = drm_fb_helper_debug_leave,
J
Jesse Barnes 已提交
86 87
};

88 89
static int intelfb_alloc(struct drm_fb_helper *helper,
			 struct drm_fb_helper_surface_size *sizes)
J
Jesse Barnes 已提交
90
{
91 92
	struct intel_fbdev *ifbdev =
		container_of(helper, struct intel_fbdev, helper);
93
	struct drm_framebuffer *fb;
94
	struct drm_device *dev = helper->dev;
95
	struct drm_mode_fb_cmd2 mode_cmd = {};
96
	struct drm_i915_gem_object *obj;
97
	int size, ret;
J
Jesse Barnes 已提交
98

99
	/* we don't do packed 24bpp */
100 101
	if (sizes->surface_bpp == 24)
		sizes->surface_bpp = 32;
102

103 104
	mode_cmd.width = sizes->surface_width;
	mode_cmd.height = sizes->surface_height;
J
Jesse Barnes 已提交
105

106 107
	mode_cmd.pitches[0] = ALIGN(mode_cmd.width *
				    DIV_ROUND_UP(sizes->surface_bpp, 8), 64);
108 109
	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
							  sizes->surface_depth);
J
Jesse Barnes 已提交
110

111
	size = mode_cmd.pitches[0] * mode_cmd.height;
112
	size = PAGE_ALIGN(size);
113 114 115
	obj = i915_gem_object_create_stolen(dev, size);
	if (obj == NULL)
		obj = i915_gem_alloc_object(dev, size);
116
	if (!obj) {
117
		DRM_ERROR("failed to allocate framebuffer\n");
J
Jesse Barnes 已提交
118 119 120 121
		ret = -ENOMEM;
		goto out;
	}

122
	/* Flush everything out, we'll be doing GTT only from now on */
123
	ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
J
Jesse Barnes 已提交
124
	if (ret) {
125
		DRM_ERROR("failed to pin obj: %d\n", ret);
J
Jesse Barnes 已提交
126 127 128
		goto out_unref;
	}

129 130 131
	fb = __intel_framebuffer_create(dev, &mode_cmd, obj);
	if (IS_ERR(fb)) {
		ret = PTR_ERR(fb);
132
		goto out_unpin;
133 134 135
	}

	ifbdev->fb = to_intel_framebuffer(fb);
136 137 138 139

	return 0;

out_unpin:
B
Ben Widawsky 已提交
140
	i915_gem_object_ggtt_unpin(obj);
141 142 143 144 145 146 147 148 149 150 151
out_unref:
	drm_gem_object_unreference(&obj->base);
out:
	return ret;
}

static int intelfb_create(struct drm_fb_helper *helper,
			  struct drm_fb_helper_surface_size *sizes)
{
	struct intel_fbdev *ifbdev =
		container_of(helper, struct intel_fbdev, helper);
152
	struct intel_framebuffer *intel_fb = ifbdev->fb;
153 154 155 156 157 158
	struct drm_device *dev = helper->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct fb_info *info;
	struct drm_framebuffer *fb;
	struct drm_i915_gem_object *obj;
	int size, ret;
159
	bool prealloc = false;
160 161 162

	mutex_lock(&dev->struct_mutex);

163 164 165 166 167 168 169 170 171 172
	if (intel_fb &&
	    (sizes->fb_width > intel_fb->base.width ||
	     sizes->fb_height > intel_fb->base.height)) {
		DRM_DEBUG_KMS("BIOS fb too small (%dx%d), we require (%dx%d),"
			      " releasing it\n",
			      intel_fb->base.width, intel_fb->base.height,
			      sizes->fb_width, sizes->fb_height);
		drm_framebuffer_unreference(&intel_fb->base);
		intel_fb = ifbdev->fb = NULL;
	}
173
	if (!intel_fb || WARN_ON(!intel_fb->obj)) {
174
		DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n");
175 176 177
		ret = intelfb_alloc(helper, sizes);
		if (ret)
			goto out_unlock;
178
		intel_fb = ifbdev->fb;
179
	} else {
180
		DRM_DEBUG_KMS("re-using BIOS fb\n");
181
		prealloc = true;
182 183 184 185 186 187 188 189
		sizes->fb_width = intel_fb->base.width;
		sizes->fb_height = intel_fb->base.height;
	}

	obj = intel_fb->obj;
	size = obj->base.size;

	info = framebuffer_alloc(0, &dev->pdev->dev);
J
Jesse Barnes 已提交
190 191
	if (!info) {
		ret = -ENOMEM;
192
		goto out_unpin;
J
Jesse Barnes 已提交
193 194
	}

195
	info->par = helper;
J
Jesse Barnes 已提交
196

197
	fb = &ifbdev->fb->base;
J
Jesse Barnes 已提交
198

199 200
	ifbdev->helper.fb = fb;
	ifbdev->helper.fbdev = info;
201

J
Jesse Barnes 已提交
202 203
	strcpy(info->fix.id, "inteldrmfb");

204
	info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
J
Jesse Barnes 已提交
205 206
	info->fbops = &intelfb_ops;

207 208 209 210 211
	ret = fb_alloc_cmap(&info->cmap, 256, 0);
	if (ret) {
		ret = -ENOMEM;
		goto out_unpin;
	}
212
	/* setup aperture base/size for vesafb takeover */
213 214 215 216 217 218
	info->apertures = alloc_apertures(1);
	if (!info->apertures) {
		ret = -ENOMEM;
		goto out_unpin;
	}
	info->apertures->ranges[0].base = dev->mode_config.fb_base;
219
	info->apertures->ranges[0].size = dev_priv->gtt.mappable_end;
220

221
	info->fix.smem_start = dev->mode_config.fb_base + i915_gem_obj_ggtt_offset(obj);
J
Jesse Barnes 已提交
222 223
	info->fix.smem_len = size;

224
	info->screen_base =
225
		ioremap_wc(dev_priv->gtt.mappable_base + i915_gem_obj_ggtt_offset(obj),
226
			   size);
J
Jesse Barnes 已提交
227 228
	if (!info->screen_base) {
		ret = -ENOSPC;
229
		goto out_unpin;
J
Jesse Barnes 已提交
230 231 232
	}
	info->screen_size = size;

233 234 235
	/* This driver doesn't need a VT switch to restore the mode on resume */
	info->skip_vt_switch = true;

236
	drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
237
	drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height);
J
Jesse Barnes 已提交
238

239 240 241 242
	/* If the object is shmemfs backed, it will have given us zeroed pages.
	 * If the object is stolen however, it will be full of whatever
	 * garbage was left in there.
	 */
243
	if (ifbdev->fb->obj->stolen && !prealloc)
244 245
		memset_io(info->screen_base, 0, info->screen_size);

246
	/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
J
Jesse Barnes 已提交
247

248
	DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08lx, bo %p\n",
249
		      fb->width, fb->height,
250
		      i915_gem_obj_ggtt_offset(obj), obj);
J
Jesse Barnes 已提交
251 252

	mutex_unlock(&dev->struct_mutex);
253
	vga_switcheroo_client_fb_set(dev->pdev, info);
J
Jesse Barnes 已提交
254 255
	return 0;

256
out_unpin:
B
Ben Widawsky 已提交
257
	i915_gem_object_ggtt_unpin(obj);
258
	drm_gem_object_unreference(&obj->base);
259
out_unlock:
J
Jesse Barnes 已提交
260 261 262 263
	mutex_unlock(&dev->struct_mutex);
	return ret;
}

264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
/** Sets the color ramps on behalf of RandR */
static void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
				    u16 blue, int regno)
{
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);

	intel_crtc->lut_r[regno] = red >> 8;
	intel_crtc->lut_g[regno] = green >> 8;
	intel_crtc->lut_b[regno] = blue >> 8;
}

static void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
				    u16 *blue, int regno)
{
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);

	*red = intel_crtc->lut_r[regno] << 8;
	*green = intel_crtc->lut_g[regno] << 8;
	*blue = intel_crtc->lut_b[regno] << 8;
}

285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
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;
}

/*
 * 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 and connectors are active
 * and stuffs them into the crtcs and modes array given to us by the
 * drm_fb_helper code.
 *
 * The overall sequence is:
 *   intel_fbdev_init - from driver load
 *     intel_fbdev_init_bios - initialize the intel_fbdev using BIOS data
 *     drm_fb_helper_init - build fb helper structs
 *     drm_fb_helper_single_add_all_connectors - more fb helper structs
 *   intel_fbdev_initial_config - apply the config
 *     drm_fb_helper_initial_config - call ->probe then register_framebuffer()
 *         drm_setup_crtcs - build crtc config for fbdev
 *           intel_fb_initial_config - find active connectors etc
 *         drm_fb_helper_single_fb_probe - set up fbdev
 *           intelfb_create - re-use or alloc fb, build out fbdev structs
 *
 * Note that we don't make special consideration whether we could actually
 * switch to the selected modes without a full modeset. E.g. when the display
 * is in VGA mode we need to recalculate watermarks and set a new high-res
 * framebuffer anyway.
 */
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)
{
329
	struct drm_device *dev = fb_helper->dev;
330
	int i, j;
331
	bool *save_enabled;
332
	bool fallback = true;
333 334
	int num_connectors_enabled = 0;
	int num_connectors_detected = 0;
335 336 337 338 339 340 341

	save_enabled = kcalloc(dev->mode_config.num_connector, sizeof(bool),
			       GFP_KERNEL);
	if (!save_enabled)
		return false;

	memcpy(save_enabled, enabled, dev->mode_config.num_connector);
342 343 344 345 346 347 348 349 350

	for (i = 0; i < fb_helper->connector_count; i++) {
		struct drm_fb_helper_connector *fb_conn;
		struct drm_connector *connector;
		struct drm_encoder *encoder;
		struct drm_fb_helper_crtc *new_crtc;

		fb_conn = fb_helper->connector_info[i];
		connector = fb_conn->connector;
351 352 353 354

		if (connector->status == connector_status_connected)
			num_connectors_detected++;

355
		if (!enabled[i]) {
356
			DRM_DEBUG_KMS("connector %s not enabled, skipping\n",
357
				      connector->name);
358 359 360
			continue;
		}

361 362 363 364 365 366 367
		if (connector->force == DRM_FORCE_OFF) {
			DRM_DEBUG_KMS("connector %s is disabled by user, skipping\n",
				      connector->name);
			enabled[i] = false;
			continue;
		}

368 369
		encoder = connector->encoder;
		if (!encoder || WARN_ON(!encoder->crtc)) {
370 371 372
			if (connector->force > DRM_FORCE_OFF)
				goto bail;

373
			DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n",
374
				      connector->name);
375 376 377 378
			enabled[i] = false;
			continue;
		}

379 380
		num_connectors_enabled++;

381 382 383 384 385 386 387 388
		new_crtc = intel_fb_helper_crtc(fb_helper, encoder->crtc);

		/*
		 * Make sure we're not trying to drive multiple connectors
		 * with a single CRTC, since our cloning support may not
		 * match the BIOS.
		 */
		for (j = 0; j < fb_helper->connector_count; j++) {
389
			if (crtcs[j] == new_crtc) {
390
				DRM_DEBUG_KMS("fallback: cloned configuration\n");
391
				goto bail;
392
			}
393 394
		}

395
		DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n",
396
			      connector->name);
397 398 399 400 401 402

		/* go for command line mode first */
		modes[i] = drm_pick_cmdline_mode(fb_conn, width, height);

		/* try for preferred next */
		if (!modes[i]) {
403
			DRM_DEBUG_KMS("looking for preferred mode on connector %s\n",
404
				      connector->name);
405 406 407 408
			modes[i] = drm_has_preferred_mode(fb_conn, width,
							  height);
		}

409 410 411
		/* No preferred mode marked by the EDID? Are there any modes? */
		if (!modes[i] && !list_empty(&connector->modes)) {
			DRM_DEBUG_KMS("using first mode listed on connector %s\n",
412
				      connector->name);
413 414 415 416 417
			modes[i] = list_first_entry(&connector->modes,
						    struct drm_display_mode,
						    head);
		}

418 419 420 421 422 423 424 425 426 427 428 429 430
		/* last resort: use current mode */
		if (!modes[i]) {
			/*
			 * IMPORTANT: We want to use the adjusted mode (i.e.
			 * after the panel fitter upscaling) as the initial
			 * config, not the input mode, which is what crtc->mode
			 * usually contains. But since our current fastboot
			 * code puts a mode derived from the post-pfit timings
			 * into crtc->mode this works out correctly. We don't
			 * use hwmode anywhere right now, so use it for this
			 * since the fb helper layer wants a pointer to
			 * something we own.
			 */
431
			DRM_DEBUG_KMS("looking for current mode on connector %s\n",
432
				      connector->name);
433 434 435 436 437 438
			intel_mode_from_pipe_config(&encoder->crtc->hwmode,
						    &to_intel_crtc(encoder->crtc)->config);
			modes[i] = &encoder->crtc->hwmode;
		}
		crtcs[i] = new_crtc;

439
		DRM_DEBUG_KMS("connector %s on pipe %c [CRTC:%d]: %dx%d%s\n",
440
			      connector->name,
441
			      pipe_name(to_intel_crtc(encoder->crtc)->pipe),
442
			      encoder->crtc->base.id,
443 444
			      modes[i]->hdisplay, modes[i]->vdisplay,
			      modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" :"");
445

446
		fallback = false;
447 448
	}

449 450 451 452 453 454 455 456 457 458 459 460 461
	/*
	 * If the BIOS didn't enable everything it could, fall back to have the
	 * same user experiencing of lighting up as much as possible like the
	 * fbdev helper library.
	 */
	if (num_connectors_enabled != num_connectors_detected &&
	    num_connectors_enabled < INTEL_INFO(dev)->num_pipes) {
		DRM_DEBUG_KMS("fallback: Not all outputs enabled\n");
		DRM_DEBUG_KMS("Enabled: %i, detected: %i\n", num_connectors_enabled,
			      num_connectors_detected);
		fallback = true;
	}

462
	if (fallback) {
463
bail:
464
		DRM_DEBUG_KMS("Not using firmware configuration\n");
465 466 467
		memcpy(enabled, save_enabled, dev->mode_config.num_connector);
		kfree(save_enabled);
		return false;
468 469
	}

470
	kfree(save_enabled);
471 472 473
	return true;
}

474
static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
475
	.initial_config = intel_fb_initial_config,
476 477
	.gamma_set = intel_crtc_fb_gamma_set,
	.gamma_get = intel_crtc_fb_gamma_get,
478
	.fb_probe = intelfb_create,
479
};
J
Jesse Barnes 已提交
480

481 482
static void intel_fbdev_destroy(struct drm_device *dev,
				struct intel_fbdev *ifbdev)
J
Jesse Barnes 已提交
483
{
484
	if (ifbdev->helper.fbdev) {
485 486
		struct fb_info *info = ifbdev->helper.fbdev;

J
Jesse Barnes 已提交
487 488
		unregister_framebuffer(info);
		iounmap(info->screen_base);
489 490
		if (info->cmap.len)
			fb_dealloc_cmap(&info->cmap);
491

J
Jesse Barnes 已提交
492 493 494
		framebuffer_release(info);
	}

495
	drm_fb_helper_fini(&ifbdev->helper);
J
Jesse Barnes 已提交
496

497
	drm_framebuffer_unregister_private(&ifbdev->fb->base);
498
	drm_framebuffer_remove(&ifbdev->fb->base);
J
Jesse Barnes 已提交
499
}
500

501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522
/*
 * Build an intel_fbdev struct using a BIOS allocated framebuffer, if possible.
 * The core display code will have read out the current plane configuration,
 * so we use that to figure out if there's an object for us to use as the
 * fb, and if so, we re-use it for the fbdev configuration.
 *
 * Note we only support a single fb shared across pipes for boot (mostly for
 * fbcon), so we just find the biggest and use that.
 */
static bool intel_fbdev_init_bios(struct drm_device *dev,
				 struct intel_fbdev *ifbdev)
{
	struct intel_framebuffer *fb = NULL;
	struct drm_crtc *crtc;
	struct intel_crtc *intel_crtc;
	struct intel_plane_config *plane_config = NULL;
	unsigned int max_size = 0;

	if (!i915.fastboot)
		return false;

	/* Find the largest fb */
523
	for_each_crtc(dev, crtc) {
524 525
		intel_crtc = to_intel_crtc(crtc);

526
		if (!intel_crtc->active || !crtc->primary->fb) {
527 528 529 530 531 532 533 534 535
			DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n",
				      pipe_name(intel_crtc->pipe));
			continue;
		}

		if (intel_crtc->plane_config.size > max_size) {
			DRM_DEBUG_KMS("found possible fb from plane %c\n",
				      pipe_name(intel_crtc->pipe));
			plane_config = &intel_crtc->plane_config;
536
			fb = to_intel_framebuffer(crtc->primary->fb);
537 538 539 540 541 542 543 544 545 546
			max_size = plane_config->size;
		}
	}

	if (!fb) {
		DRM_DEBUG_KMS("no active fbs found, not using BIOS config\n");
		goto out;
	}

	/* Now make sure all the pipes will fit into it */
547
	for_each_crtc(dev, crtc) {
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562
		unsigned int cur_size;

		intel_crtc = to_intel_crtc(crtc);

		if (!intel_crtc->active) {
			DRM_DEBUG_KMS("pipe %c not active, skipping\n",
				      pipe_name(intel_crtc->pipe));
			continue;
		}

		DRM_DEBUG_KMS("checking plane %c for BIOS fb\n",
			      pipe_name(intel_crtc->pipe));

		/*
		 * See if the plane fb we found above will fit on this
563 564
		 * pipe.  Note we need to use the selected fb's pitch and bpp
		 * rather than the current pipe's, since they differ.
565
		 */
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
		cur_size = intel_crtc->config.adjusted_mode.crtc_hdisplay;
		cur_size = cur_size * fb->base.bits_per_pixel / 8;
		if (fb->base.pitches[0] < cur_size) {
			DRM_DEBUG_KMS("fb not wide enough for plane %c (%d vs %d)\n",
				      pipe_name(intel_crtc->pipe),
				      cur_size, fb->base.pitches[0]);
			plane_config = NULL;
			fb = NULL;
			break;
		}

		cur_size = intel_crtc->config.adjusted_mode.crtc_vdisplay;
		cur_size = ALIGN(cur_size, plane_config->tiled ? (IS_GEN2(dev) ? 16 : 8) : 1);
		cur_size *= fb->base.pitches[0];
		DRM_DEBUG_KMS("pipe %c area: %dx%d, bpp: %d, size: %d\n",
			      pipe_name(intel_crtc->pipe),
			      intel_crtc->config.adjusted_mode.crtc_hdisplay,
			      intel_crtc->config.adjusted_mode.crtc_vdisplay,
			      fb->base.bits_per_pixel,
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605
			      cur_size);

		if (cur_size > max_size) {
			DRM_DEBUG_KMS("fb not big enough for plane %c (%d vs %d)\n",
				      pipe_name(intel_crtc->pipe),
				      cur_size, max_size);
			plane_config = NULL;
			fb = NULL;
			break;
		}

		DRM_DEBUG_KMS("fb big enough for plane %c (%d >= %d)\n",
			      pipe_name(intel_crtc->pipe),
			      max_size, cur_size);
	}

	if (!fb) {
		DRM_DEBUG_KMS("BIOS fb not suitable for all pipes, not using\n");
		goto out;
	}

606
	ifbdev->preferred_bpp = fb->base.bits_per_pixel;
607 608
	ifbdev->fb = fb;

609
	drm_framebuffer_reference(&ifbdev->fb->base);
610 611

	/* Final pass to check if any active pipes don't have fbs */
612
	for_each_crtc(dev, crtc) {
613 614 615 616 617
		intel_crtc = to_intel_crtc(crtc);

		if (!intel_crtc->active)
			continue;

618
		WARN(!crtc->primary->fb,
619 620 621 622 623 624 625 626 627 628 629 630 631
		     "re-used BIOS config but lost an fb on crtc %d\n",
		     crtc->base.id);
	}


	DRM_DEBUG_KMS("using BIOS fb for initial console\n");
	return true;

out:

	return false;
}

632 633 634 635 636 637 638 639 640
static void intel_fbdev_suspend_worker(struct work_struct *work)
{
	intel_fbdev_set_suspend(container_of(work,
					     struct drm_i915_private,
					     fbdev_suspend_work)->dev,
				FBINFO_STATE_RUNNING,
				true);
}

641 642
int intel_fbdev_init(struct drm_device *dev)
{
643
	struct intel_fbdev *ifbdev;
644
	struct drm_i915_private *dev_priv = dev->dev_private;
645
	int ret;
646

647 648 649 650 651
	if (WARN_ON(INTEL_INFO(dev)->num_pipes == 0))
		return -ENODEV;

	ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
	if (ifbdev == NULL)
652 653
		return -ENOMEM;

654 655
	drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);

656 657
	if (!intel_fbdev_init_bios(dev, ifbdev))
		ifbdev->preferred_bpp = 32;
658

659
	ret = drm_fb_helper_init(dev, &ifbdev->helper,
660
				 INTEL_INFO(dev)->num_pipes, 4);
661 662 663 664
	if (ret) {
		kfree(ifbdev);
		return ret;
	}
665

666
	dev_priv->fbdev = ifbdev;
667 668
	INIT_WORK(&dev_priv->fbdev_suspend_work, intel_fbdev_suspend_worker);

669
	drm_fb_helper_single_add_all_connectors(&ifbdev->helper);
670

J
Jesse Barnes 已提交
671 672
	return 0;
}
673

674
void intel_fbdev_initial_config(void *data, async_cookie_t cookie)
675
{
676
	struct drm_i915_private *dev_priv = data;
677
	struct intel_fbdev *ifbdev = dev_priv->fbdev;
678 679

	/* Due to peculiar init order wrt to hpd handling this is separate. */
680
	drm_fb_helper_initial_config(&ifbdev->helper, ifbdev->preferred_bpp);
681 682
}

683 684
void intel_fbdev_fini(struct drm_device *dev)
{
685
	struct drm_i915_private *dev_priv = dev->dev_private;
686 687 688
	if (!dev_priv->fbdev)
		return;

689 690
	flush_work(&dev_priv->fbdev_suspend_work);

691
	async_synchronize_full();
692
	intel_fbdev_destroy(dev, dev_priv->fbdev);
693
	kfree(dev_priv->fbdev);
694 695
	dev_priv->fbdev = NULL;
}
696

697
void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous)
698
{
699
	struct drm_i915_private *dev_priv = dev->dev_private;
700 701 702 703
	struct intel_fbdev *ifbdev = dev_priv->fbdev;
	struct fb_info *info;

	if (!ifbdev)
704 705
		return;

706 707
	info = ifbdev->helper.fbdev;

708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734
	if (synchronous) {
		/* Flush any pending work to turn the console on, and then
		 * wait to turn it off. It must be synchronous as we are
		 * about to suspend or unload the driver.
		 *
		 * Note that from within the work-handler, we cannot flush
		 * ourselves, so only flush outstanding work upon suspend!
		 */
		if (state != FBINFO_STATE_RUNNING)
			flush_work(&dev_priv->fbdev_suspend_work);
		console_lock();
	} else {
		/*
		 * The console lock can be pretty contented on resume due
		 * to all the printk activity.  Try to keep it out of the hot
		 * path of resume if possible.
		 */
		WARN_ON(state != FBINFO_STATE_RUNNING);
		if (!console_trylock()) {
			/* Don't block our own workqueue as this can
			 * be run in parallel with other i915.ko tasks.
			 */
			schedule_work(&dev_priv->fbdev_suspend_work);
			return;
		}
	}

735 736 737 738
	/* On resume from hibernation: If the object is shmemfs backed, it has
	 * been restored from swap. If the object is stolen however, it will be
	 * full of whatever garbage was left in there.
	 */
739
	if (state == FBINFO_STATE_RUNNING && ifbdev->fb->obj->stolen)
740 741 742
		memset_io(info->screen_base, 0, info->screen_size);

	fb_set_suspend(info, state);
743
	console_unlock();
744 745
}

746
void intel_fbdev_output_poll_changed(struct drm_device *dev)
747
{
748
	struct drm_i915_private *dev_priv = dev->dev_private;
749 750
	if (dev_priv->fbdev)
		drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
751
}
752

753
void intel_fbdev_restore_mode(struct drm_device *dev)
754 755
{
	int ret;
756
	struct drm_i915_private *dev_priv = dev->dev_private;
757

758
	if (!dev_priv->fbdev)
B
Ben Widawsky 已提交
759 760
		return;

761
	ret = drm_fb_helper_restore_fbdev_mode_unlocked(&dev_priv->fbdev->helper);
762 763 764
	if (ret)
		DRM_DEBUG("failed to restore crtc mode\n");
}