intel_fbdev.c 22.4 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
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) {
		mutex_lock(&fb_helper->dev->struct_mutex);
59
		intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT);
60 61 62 63 64 65
		mutex_unlock(&fb_helper->dev->struct_mutex);
	}

	return ret;
}

66 67 68 69 70 71 72 73 74 75 76
static int intel_fbdev_blank(int blank, 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_blank(blank, info);

	if (ret == 0) {
		mutex_lock(&fb_helper->dev->struct_mutex);
77
		intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT);
78 79 80 81 82 83
		mutex_unlock(&fb_helper->dev->struct_mutex);
	}

	return ret;
}

84 85 86 87 88 89 90 91 92 93 94 95
static int intel_fbdev_pan_display(struct fb_var_screeninfo *var,
				   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_pan_display(var, info);

	if (ret == 0) {
		mutex_lock(&fb_helper->dev->struct_mutex);
96
		intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT);
97 98 99 100 101 102
		mutex_unlock(&fb_helper->dev->struct_mutex);
	}

	return ret;
}

J
Jesse Barnes 已提交
103 104
static struct fb_ops intelfb_ops = {
	.owner = THIS_MODULE,
105
	.fb_check_var = drm_fb_helper_check_var,
106
	.fb_set_par = intel_fbdev_set_par,
107 108 109
	.fb_fillrect = drm_fb_helper_cfb_fillrect,
	.fb_copyarea = drm_fb_helper_cfb_copyarea,
	.fb_imageblit = drm_fb_helper_cfb_imageblit,
110
	.fb_pan_display = intel_fbdev_pan_display,
111
	.fb_blank = intel_fbdev_blank,
112
	.fb_setcmap = drm_fb_helper_setcmap,
J
Jesse Barnes 已提交
113 114
	.fb_debug_enter = drm_fb_helper_debug_enter,
	.fb_debug_leave = drm_fb_helper_debug_leave,
J
Jesse Barnes 已提交
115 116
};

117 118
static int intelfb_alloc(struct drm_fb_helper *helper,
			 struct drm_fb_helper_surface_size *sizes)
J
Jesse Barnes 已提交
119
{
120 121
	struct intel_fbdev *ifbdev =
		container_of(helper, struct intel_fbdev, helper);
122
	struct drm_framebuffer *fb;
123
	struct drm_device *dev = helper->dev;
124
	struct drm_mode_fb_cmd2 mode_cmd = {};
125
	struct drm_i915_gem_object *obj;
126
	int size, ret;
J
Jesse Barnes 已提交
127

128
	/* we don't do packed 24bpp */
129 130
	if (sizes->surface_bpp == 24)
		sizes->surface_bpp = 32;
131

132 133
	mode_cmd.width = sizes->surface_width;
	mode_cmd.height = sizes->surface_height;
J
Jesse Barnes 已提交
134

135 136
	mode_cmd.pitches[0] = ALIGN(mode_cmd.width *
				    DIV_ROUND_UP(sizes->surface_bpp, 8), 64);
137 138
	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
							  sizes->surface_depth);
J
Jesse Barnes 已提交
139

140
	size = mode_cmd.pitches[0] * mode_cmd.height;
141
	size = PAGE_ALIGN(size);
142 143 144
	obj = i915_gem_object_create_stolen(dev, size);
	if (obj == NULL)
		obj = i915_gem_alloc_object(dev, size);
145
	if (!obj) {
146
		DRM_ERROR("failed to allocate framebuffer\n");
J
Jesse Barnes 已提交
147 148 149 150
		ret = -ENOMEM;
		goto out;
	}

151 152 153
	fb = __intel_framebuffer_create(dev, &mode_cmd, obj);
	if (IS_ERR(fb)) {
		ret = PTR_ERR(fb);
154 155 156 157
		goto out_unref;
	}

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

	ifbdev->fb = to_intel_framebuffer(fb);
165 166 167

	return 0;

168 169
out_fb:
	drm_framebuffer_remove(fb);
170 171 172 173 174 175 176 177 178 179 180
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);
181
	struct intel_framebuffer *intel_fb = ifbdev->fb;
182 183 184 185 186 187
	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;
188
	bool prealloc = false;
189 190 191

	mutex_lock(&dev->struct_mutex);

192 193 194 195 196 197 198 199 200 201
	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;
	}
202
	if (!intel_fb || WARN_ON(!intel_fb->obj)) {
203
		DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n");
204 205 206
		ret = intelfb_alloc(helper, sizes);
		if (ret)
			goto out_unlock;
207
		intel_fb = ifbdev->fb;
208
	} else {
209
		DRM_DEBUG_KMS("re-using BIOS fb\n");
210
		prealloc = true;
211 212 213 214 215 216 217
		sizes->fb_width = intel_fb->base.width;
		sizes->fb_height = intel_fb->base.height;
	}

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

218 219 220
	info = drm_fb_helper_alloc_fbi(helper);
	if (IS_ERR(info)) {
		ret = PTR_ERR(info);
221
		goto out_unpin;
J
Jesse Barnes 已提交
222 223
	}

224
	info->par = helper;
J
Jesse Barnes 已提交
225

226
	fb = &ifbdev->fb->base;
J
Jesse Barnes 已提交
227

228
	ifbdev->helper.fb = fb;
229

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

232
	info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
J
Jesse Barnes 已提交
233 234
	info->fbops = &intelfb_ops;

235
	/* setup aperture base/size for vesafb takeover */
236
	info->apertures->ranges[0].base = dev->mode_config.fb_base;
237
	info->apertures->ranges[0].size = dev_priv->gtt.mappable_end;
238

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

242
	info->screen_base =
243
		ioremap_wc(dev_priv->gtt.mappable_base + i915_gem_obj_ggtt_offset(obj),
244
			   size);
J
Jesse Barnes 已提交
245 246
	if (!info->screen_base) {
		ret = -ENOSPC;
247
		goto out_destroy_fbi;
J
Jesse Barnes 已提交
248 249 250
	}
	info->screen_size = size;

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

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

257 258 259 260
	/* 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.
	 */
261
	if (ifbdev->fb->obj->stolen && !prealloc)
262 263
		memset_io(info->screen_base, 0, info->screen_size);

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

266
	DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08llx, bo %p\n",
267
		      fb->width, fb->height,
268
		      i915_gem_obj_ggtt_offset(obj), obj);
J
Jesse Barnes 已提交
269 270

	mutex_unlock(&dev->struct_mutex);
271
	vga_switcheroo_client_fb_set(dev->pdev, info);
J
Jesse Barnes 已提交
272 273
	return 0;

274 275
out_destroy_fbi:
	drm_fb_helper_release_fbi(helper);
276
out_unpin:
B
Ben Widawsky 已提交
277
	i915_gem_object_ggtt_unpin(obj);
278
	drm_gem_object_unreference(&obj->base);
279
out_unlock:
J
Jesse Barnes 已提交
280 281 282 283
	mutex_unlock(&dev->struct_mutex);
	return ret;
}

284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
/** 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;
}

305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
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,
347
				    struct drm_fb_offset *offsets,
348 349
				    bool *enabled, int width, int height)
{
350
	struct drm_device *dev = fb_helper->dev;
351
	int i, j;
352
	bool *save_enabled;
353
	bool fallback = true;
354 355
	int num_connectors_enabled = 0;
	int num_connectors_detected = 0;
356 357
	uint64_t conn_configured = 0, mask;
	int pass = 0;
358 359 360 361 362 363 364

	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);
365 366
	mask = (1 << fb_helper->connector_count) - 1;
retry:
367 368 369 370 371 372 373 374
	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;
375

376 377 378 379 380 381
		if (conn_configured & (1 << i))
			continue;

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

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

385
		if (!enabled[i]) {
386
			DRM_DEBUG_KMS("connector %s not enabled, skipping\n",
387
				      connector->name);
388
			conn_configured |= (1 << i);
389 390 391
			continue;
		}

392 393 394 395 396 397 398
		if (connector->force == DRM_FORCE_OFF) {
			DRM_DEBUG_KMS("connector %s is disabled by user, skipping\n",
				      connector->name);
			enabled[i] = false;
			continue;
		}

399 400
		encoder = connector->encoder;
		if (!encoder || WARN_ON(!encoder->crtc)) {
401 402 403
			if (connector->force > DRM_FORCE_OFF)
				goto bail;

404
			DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n",
405
				      connector->name);
406
			enabled[i] = false;
407
			conn_configured |= (1 << i);
408 409 410
			continue;
		}

411 412
		num_connectors_enabled++;

413 414 415 416 417 418 419 420
		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++) {
421
			if (crtcs[j] == new_crtc) {
422
				DRM_DEBUG_KMS("fallback: cloned configuration\n");
423
				goto bail;
424
			}
425 426
		}

427
		DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n",
428
			      connector->name);
429 430 431 432 433 434

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

		/* try for preferred next */
		if (!modes[i]) {
435 436
			DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n",
				      connector->name, connector->has_tile);
437 438 439 440
			modes[i] = drm_has_preferred_mode(fb_conn, width,
							  height);
		}

441 442 443
		/* 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",
444
				      connector->name);
445 446 447 448 449
			modes[i] = list_first_entry(&connector->modes,
						    struct drm_display_mode,
						    head);
		}

450 451 452 453 454 455
		/* 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
456
			 * usually contains. But since our current
457
			 * code puts a mode derived from the post-pfit timings
458
			 * into crtc->mode this works out correctly.
459
			 */
460
			DRM_DEBUG_KMS("looking for current mode on connector %s\n",
461
				      connector->name);
462
			modes[i] = &encoder->crtc->mode;
463 464 465
		}
		crtcs[i] = new_crtc;

466
		DRM_DEBUG_KMS("connector %s on pipe %c [CRTC:%d]: %dx%d%s\n",
467
			      connector->name,
468
			      pipe_name(to_intel_crtc(encoder->crtc)->pipe),
469
			      encoder->crtc->base.id,
470 471
			      modes[i]->hdisplay, modes[i]->vdisplay,
			      modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" :"");
472

473
		fallback = false;
474 475 476 477 478 479
		conn_configured |= (1 << i);
	}

	if ((conn_configured & mask) != mask) {
		pass++;
		goto retry;
480 481
	}

482 483 484 485 486 487 488 489 490 491 492 493 494
	/*
	 * 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;
	}

495
	if (fallback) {
496
bail:
497
		DRM_DEBUG_KMS("Not using firmware configuration\n");
498 499 500
		memcpy(enabled, save_enabled, dev->mode_config.num_connector);
		kfree(save_enabled);
		return false;
501 502
	}

503
	kfree(save_enabled);
504 505 506
	return true;
}

507
static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
508
	.initial_config = intel_fb_initial_config,
509 510
	.gamma_set = intel_crtc_fb_gamma_set,
	.gamma_get = intel_crtc_fb_gamma_get,
511
	.fb_probe = intelfb_create,
512
};
J
Jesse Barnes 已提交
513

514 515
static void intel_fbdev_destroy(struct drm_device *dev,
				struct intel_fbdev *ifbdev)
J
Jesse Barnes 已提交
516
{
517

518 519
	drm_fb_helper_unregister_fbi(&ifbdev->helper);
	drm_fb_helper_release_fbi(&ifbdev->helper);
J
Jesse Barnes 已提交
520

521
	drm_fb_helper_fini(&ifbdev->helper);
J
Jesse Barnes 已提交
522

523
	drm_framebuffer_unregister_private(&ifbdev->fb->base);
524
	drm_framebuffer_remove(&ifbdev->fb->base);
J
Jesse Barnes 已提交
525
}
526

527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547
/*
 * 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;
	unsigned int max_size = 0;

	if (!i915.fastboot)
		return false;

	/* Find the largest fb */
548
	for_each_crtc(dev, crtc) {
549 550
		struct drm_i915_gem_object *obj =
			intel_fb_obj(crtc->primary->state->fb);
551 552
		intel_crtc = to_intel_crtc(crtc);

553
		if (!intel_crtc->active || !obj) {
554 555 556 557 558
			DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n",
				      pipe_name(intel_crtc->pipe));
			continue;
		}

559
		if (obj->base.size > max_size) {
560 561
			DRM_DEBUG_KMS("found possible fb from plane %c\n",
				      pipe_name(intel_crtc->pipe));
562 563
			fb = to_intel_framebuffer(crtc->primary->state->fb);
			max_size = obj->base.size;
564 565 566 567 568 569 570 571 572
		}
	}

	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 */
573
	for_each_crtc(dev, crtc) {
574 575 576 577 578 579 580 581 582 583 584 585 586 587 588
		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
589 590
		 * pipe.  Note we need to use the selected fb's pitch and bpp
		 * rather than the current pipe's, since they differ.
591
		 */
592
		cur_size = intel_crtc->config->base.adjusted_mode.crtc_hdisplay;
593 594 595 596 597 598 599 600 601
		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]);
			fb = NULL;
			break;
		}

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

632
	ifbdev->preferred_bpp = fb->base.bits_per_pixel;
633 634
	ifbdev->fb = fb;

635
	drm_framebuffer_reference(&ifbdev->fb->base);
636 637

	/* Final pass to check if any active pipes don't have fbs */
638
	for_each_crtc(dev, crtc) {
639 640 641 642 643
		intel_crtc = to_intel_crtc(crtc);

		if (!intel_crtc->active)
			continue;

644
		WARN(!crtc->primary->fb,
645 646 647 648 649 650 651 652 653 654 655 656 657
		     "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;
}

658 659 660 661 662 663 664 665 666
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);
}

667 668
int intel_fbdev_init(struct drm_device *dev)
{
669
	struct intel_fbdev *ifbdev;
670
	struct drm_i915_private *dev_priv = dev->dev_private;
671
	int ret;
672

673 674 675 676 677
	if (WARN_ON(INTEL_INFO(dev)->num_pipes == 0))
		return -ENODEV;

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

680 681
	drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);

682 683
	if (!intel_fbdev_init_bios(dev, ifbdev))
		ifbdev->preferred_bpp = 32;
684

685
	ret = drm_fb_helper_init(dev, &ifbdev->helper,
686
				 INTEL_INFO(dev)->num_pipes, 4);
687 688 689 690
	if (ret) {
		kfree(ifbdev);
		return ret;
	}
691

692
	dev_priv->fbdev = ifbdev;
693 694
	INIT_WORK(&dev_priv->fbdev_suspend_work, intel_fbdev_suspend_worker);

695
	drm_fb_helper_single_add_all_connectors(&ifbdev->helper);
696

J
Jesse Barnes 已提交
697 698
	return 0;
}
699

700
void intel_fbdev_initial_config(void *data, async_cookie_t cookie)
701
{
702
	struct drm_i915_private *dev_priv = data;
703
	struct intel_fbdev *ifbdev = dev_priv->fbdev;
704 705

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

709 710
void intel_fbdev_fini(struct drm_device *dev)
{
711
	struct drm_i915_private *dev_priv = dev->dev_private;
712 713 714
	if (!dev_priv->fbdev)
		return;

715 716
	flush_work(&dev_priv->fbdev_suspend_work);

717
	async_synchronize_full();
718
	intel_fbdev_destroy(dev, dev_priv->fbdev);
719
	kfree(dev_priv->fbdev);
720 721
	dev_priv->fbdev = NULL;
}
722

723
void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous)
724
{
725
	struct drm_i915_private *dev_priv = dev->dev_private;
726 727 728 729
	struct intel_fbdev *ifbdev = dev_priv->fbdev;
	struct fb_info *info;

	if (!ifbdev)
730 731
		return;

732 733
	info = ifbdev->helper.fbdev;

734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760
	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;
		}
	}

761 762 763 764
	/* 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.
	 */
765
	if (state == FBINFO_STATE_RUNNING && ifbdev->fb->obj->stolen)
766 767
		memset_io(info->screen_base, 0, info->screen_size);

768
	drm_fb_helper_set_suspend(&ifbdev->helper, state);
769
	console_unlock();
770 771
}

772
void intel_fbdev_output_poll_changed(struct drm_device *dev)
773
{
774
	struct drm_i915_private *dev_priv = dev->dev_private;
775 776
	if (dev_priv->fbdev)
		drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
777
}
778

779
void intel_fbdev_restore_mode(struct drm_device *dev)
780 781
{
	int ret;
782
	struct drm_i915_private *dev_priv = dev->dev_private;
783 784
	struct intel_fbdev *ifbdev = dev_priv->fbdev;
	struct drm_fb_helper *fb_helper;
785

786
	if (!ifbdev)
B
Ben Widawsky 已提交
787 788
		return;

789 790 791 792
	fb_helper = &ifbdev->helper;

	ret = drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
	if (ret) {
793
		DRM_DEBUG("failed to restore crtc mode\n");
794 795 796 797 798
	} else {
		mutex_lock(&fb_helper->dev->struct_mutex);
		intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT);
		mutex_unlock(&fb_helper->dev->struct_mutex);
	}
799
}