intel_fbdev.c 22.1 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 123 124
	fb = __intel_framebuffer_create(dev, &mode_cmd, obj);
	if (IS_ERR(fb)) {
		ret = PTR_ERR(fb);
125 126 127 128 129 130 131 132
		goto out_unref;
	}

	/* Flush everything out, we'll be doing GTT only from now on */
	ret = intel_pin_and_fence_fb_obj(NULL, fb, NULL);
	if (ret) {
		DRM_ERROR("failed to pin obj: %d\n", ret);
		goto out_fb;
133 134 135
	}

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

	return 0;

139 140
out_fb:
	drm_framebuffer_remove(fb);
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
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,
327
				    struct drm_fb_offset *offsets,
328 329
				    bool *enabled, int width, int height)
{
330
	struct drm_device *dev = fb_helper->dev;
331
	int i, j;
332
	bool *save_enabled;
333
	bool fallback = true;
334 335
	int num_connectors_enabled = 0;
	int num_connectors_detected = 0;
336 337
	uint64_t conn_configured = 0, mask;
	int pass = 0;
338 339 340 341 342 343 344

	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);
345 346
	mask = (1 << fb_helper->connector_count) - 1;
retry:
347 348 349 350 351 352 353 354
	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;
355

356 357 358 359 360 361
		if (conn_configured & (1 << i))
			continue;

		if (pass == 0 && !connector->has_tile)
			continue;

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

365
		if (!enabled[i]) {
366
			DRM_DEBUG_KMS("connector %s not enabled, skipping\n",
367
				      connector->name);
368
			conn_configured |= (1 << i);
369 370 371
			continue;
		}

372 373 374 375 376 377 378
		if (connector->force == DRM_FORCE_OFF) {
			DRM_DEBUG_KMS("connector %s is disabled by user, skipping\n",
				      connector->name);
			enabled[i] = false;
			continue;
		}

379 380
		encoder = connector->encoder;
		if (!encoder || WARN_ON(!encoder->crtc)) {
381 382 383
			if (connector->force > DRM_FORCE_OFF)
				goto bail;

384
			DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n",
385
				      connector->name);
386
			enabled[i] = false;
387
			conn_configured |= (1 << i);
388 389 390
			continue;
		}

391 392
		num_connectors_enabled++;

393 394 395 396 397 398 399 400
		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++) {
401
			if (crtcs[j] == new_crtc) {
402
				DRM_DEBUG_KMS("fallback: cloned configuration\n");
403
				goto bail;
404
			}
405 406
		}

407
		DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n",
408
			      connector->name);
409 410 411 412 413 414

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

		/* try for preferred next */
		if (!modes[i]) {
415 416
			DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n",
				      connector->name, connector->has_tile);
417 418 419 420
			modes[i] = drm_has_preferred_mode(fb_conn, width,
							  height);
		}

421 422 423
		/* 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",
424
				      connector->name);
425 426 427 428 429
			modes[i] = list_first_entry(&connector->modes,
						    struct drm_display_mode,
						    head);
		}

430 431 432 433 434 435 436 437 438 439 440 441 442
		/* 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.
			 */
443
			DRM_DEBUG_KMS("looking for current mode on connector %s\n",
444
				      connector->name);
445
			intel_mode_from_pipe_config(&encoder->crtc->hwmode,
446
						    to_intel_crtc(encoder->crtc)->config);
447 448 449 450
			modes[i] = &encoder->crtc->hwmode;
		}
		crtcs[i] = new_crtc;

451
		DRM_DEBUG_KMS("connector %s on pipe %c [CRTC:%d]: %dx%d%s\n",
452
			      connector->name,
453
			      pipe_name(to_intel_crtc(encoder->crtc)->pipe),
454
			      encoder->crtc->base.id,
455 456
			      modes[i]->hdisplay, modes[i]->vdisplay,
			      modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" :"");
457

458
		fallback = false;
459 460 461 462 463 464
		conn_configured |= (1 << i);
	}

	if ((conn_configured & mask) != mask) {
		pass++;
		goto retry;
465 466
	}

467 468 469 470 471 472 473 474 475 476 477 478 479
	/*
	 * 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;
	}

480
	if (fallback) {
481
bail:
482
		DRM_DEBUG_KMS("Not using firmware configuration\n");
483 484 485
		memcpy(enabled, save_enabled, dev->mode_config.num_connector);
		kfree(save_enabled);
		return false;
486 487
	}

488
	kfree(save_enabled);
489 490 491
	return true;
}

492
static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
493
	.initial_config = intel_fb_initial_config,
494 495
	.gamma_set = intel_crtc_fb_gamma_set,
	.gamma_get = intel_crtc_fb_gamma_get,
496
	.fb_probe = intelfb_create,
497
};
J
Jesse Barnes 已提交
498

499 500
static void intel_fbdev_destroy(struct drm_device *dev,
				struct intel_fbdev *ifbdev)
J
Jesse Barnes 已提交
501
{
502
	if (ifbdev->helper.fbdev) {
503 504
		struct fb_info *info = ifbdev->helper.fbdev;

J
Jesse Barnes 已提交
505 506
		unregister_framebuffer(info);
		iounmap(info->screen_base);
507 508
		if (info->cmap.len)
			fb_dealloc_cmap(&info->cmap);
509

J
Jesse Barnes 已提交
510 511 512
		framebuffer_release(info);
	}

513
	drm_fb_helper_fini(&ifbdev->helper);
J
Jesse Barnes 已提交
514

515
	drm_framebuffer_unregister_private(&ifbdev->fb->base);
516
	drm_framebuffer_remove(&ifbdev->fb->base);
J
Jesse Barnes 已提交
517
}
518

519 520 521 522 523 524 525 526 527 528 529 530 531 532 533
/*
 * 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;
534
	struct intel_initial_plane_config *plane_config = NULL;
535 536 537 538 539 540
	unsigned int max_size = 0;

	if (!i915.fastboot)
		return false;

	/* Find the largest fb */
541
	for_each_crtc(dev, crtc) {
542 543
		intel_crtc = to_intel_crtc(crtc);

544
		if (!intel_crtc->active || !crtc->primary->fb) {
545 546 547 548 549 550 551 552 553
			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;
554
			fb = to_intel_framebuffer(crtc->primary->fb);
555 556 557 558 559 560 561 562 563 564
			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 */
565
	for_each_crtc(dev, crtc) {
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580
		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
581 582
		 * pipe.  Note we need to use the selected fb's pitch and bpp
		 * rather than the current pipe's, since they differ.
583
		 */
584
		cur_size = intel_crtc->config->base.adjusted_mode.crtc_hdisplay;
585 586 587 588 589 590 591 592 593 594
		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;
		}

595
		cur_size = intel_crtc->config->base.adjusted_mode.crtc_vdisplay;
596
		cur_size = intel_fb_align_height(dev, cur_size,
597 598
						 fb->base.pixel_format,
						 fb->base.modifier[0]);
599 600 601
		cur_size *= fb->base.pitches[0];
		DRM_DEBUG_KMS("pipe %c area: %dx%d, bpp: %d, size: %d\n",
			      pipe_name(intel_crtc->pipe),
602 603
			      intel_crtc->config->base.adjusted_mode.crtc_hdisplay,
			      intel_crtc->config->base.adjusted_mode.crtc_vdisplay,
604
			      fb->base.bits_per_pixel,
605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625
			      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;
	}

626
	ifbdev->preferred_bpp = fb->base.bits_per_pixel;
627 628
	ifbdev->fb = fb;

629
	drm_framebuffer_reference(&ifbdev->fb->base);
630 631

	/* Final pass to check if any active pipes don't have fbs */
632
	for_each_crtc(dev, crtc) {
633 634 635 636 637
		intel_crtc = to_intel_crtc(crtc);

		if (!intel_crtc->active)
			continue;

638
		WARN(!crtc->primary->fb,
639 640 641 642 643 644 645 646 647 648 649 650 651
		     "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;
}

652 653 654 655 656 657 658 659 660
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);
}

661 662
int intel_fbdev_init(struct drm_device *dev)
{
663
	struct intel_fbdev *ifbdev;
664
	struct drm_i915_private *dev_priv = dev->dev_private;
665
	int ret;
666

667 668 669 670 671
	if (WARN_ON(INTEL_INFO(dev)->num_pipes == 0))
		return -ENODEV;

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

674 675
	drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);

676 677
	if (!intel_fbdev_init_bios(dev, ifbdev))
		ifbdev->preferred_bpp = 32;
678

679
	ret = drm_fb_helper_init(dev, &ifbdev->helper,
680
				 INTEL_INFO(dev)->num_pipes, 4);
681 682 683 684
	if (ret) {
		kfree(ifbdev);
		return ret;
	}
685

686
	dev_priv->fbdev = ifbdev;
687 688
	INIT_WORK(&dev_priv->fbdev_suspend_work, intel_fbdev_suspend_worker);

689
	drm_fb_helper_single_add_all_connectors(&ifbdev->helper);
690

J
Jesse Barnes 已提交
691 692
	return 0;
}
693

694
void intel_fbdev_initial_config(void *data, async_cookie_t cookie)
695
{
696
	struct drm_i915_private *dev_priv = data;
697
	struct intel_fbdev *ifbdev = dev_priv->fbdev;
698 699

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

703 704
void intel_fbdev_fini(struct drm_device *dev)
{
705
	struct drm_i915_private *dev_priv = dev->dev_private;
706 707 708
	if (!dev_priv->fbdev)
		return;

709 710
	flush_work(&dev_priv->fbdev_suspend_work);

711
	async_synchronize_full();
712
	intel_fbdev_destroy(dev, dev_priv->fbdev);
713
	kfree(dev_priv->fbdev);
714 715
	dev_priv->fbdev = NULL;
}
716

717
void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous)
718
{
719
	struct drm_i915_private *dev_priv = dev->dev_private;
720 721 722 723
	struct intel_fbdev *ifbdev = dev_priv->fbdev;
	struct fb_info *info;

	if (!ifbdev)
724 725
		return;

726 727
	info = ifbdev->helper.fbdev;

728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754
	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;
		}
	}

755 756 757 758
	/* 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.
	 */
759
	if (state == FBINFO_STATE_RUNNING && ifbdev->fb->obj->stolen)
760 761 762
		memset_io(info->screen_base, 0, info->screen_size);

	fb_set_suspend(info, state);
763
	console_unlock();
764 765
}

766
void intel_fbdev_output_poll_changed(struct drm_device *dev)
767
{
768
	struct drm_i915_private *dev_priv = dev->dev_private;
769 770
	if (dev_priv->fbdev)
		drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
771
}
772

773
void intel_fbdev_restore_mode(struct drm_device *dev)
774 775
{
	int ret;
776
	struct drm_i915_private *dev_priv = dev->dev_private;
777

778
	if (!dev_priv->fbdev)
B
Ben Widawsky 已提交
779 780
		return;

781
	ret = drm_fb_helper_restore_fbdev_mode_unlocked(&dev_priv->fbdev->helper);
782 783 784
	if (ret)
		DRM_DEBUG("failed to restore crtc mode\n");
}