intel_fbdev.c 23.5 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_i915_private *dev_priv = to_i915(dev);
125
	struct drm_mode_fb_cmd2 mode_cmd = {};
126
	struct drm_i915_gem_object *obj = NULL;
127
	int size, ret;
J
Jesse Barnes 已提交
128

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

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

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

141 142
	mutex_lock(&dev->struct_mutex);

143
	size = mode_cmd.pitches[0] * mode_cmd.height;
144
	size = PAGE_ALIGN(size);
145 146 147 148

	/* If the FB is too big, just don't use it since fbdev is not very
	 * important and we should probably use that space with FBC or other
	 * features. */
149
	if (size * 2 < dev_priv->ggtt.stolen_usable_size)
150
		obj = i915_gem_object_create_stolen(dev, size);
151 152
	if (obj == NULL)
		obj = i915_gem_alloc_object(dev, size);
153
	if (!obj) {
154
		DRM_ERROR("failed to allocate framebuffer\n");
J
Jesse Barnes 已提交
155 156 157 158
		ret = -ENOMEM;
		goto out;
	}

159 160
	fb = __intel_framebuffer_create(dev, &mode_cmd, obj);
	if (IS_ERR(fb)) {
161
		drm_gem_object_unreference(&obj->base);
162
		ret = PTR_ERR(fb);
163
		goto out;
164 165
	}

166 167
	mutex_unlock(&dev->struct_mutex);

168
	ifbdev->fb = to_intel_framebuffer(fb);
169 170 171 172

	return 0;

out:
173
	mutex_unlock(&dev->struct_mutex);
174 175 176 177 178 179 180 181
	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);
182
	struct intel_framebuffer *intel_fb = ifbdev->fb;
183 184 185 186 187 188
	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;
189
	bool prealloc = false;
190

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

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

217 218
	mutex_lock(&dev->struct_mutex);

219 220 221 222
	/* Pin the GGTT vma for our access via info->screen_base.
	 * This also validates that any existing fb inherited from the
	 * BIOS is suitable for own access.
	 */
223
	ret = intel_pin_and_fence_fb_obj(&ifbdev->fb->base, BIT(DRM_ROTATE_0));
224 225 226
	if (ret)
		goto out_unlock;

227 228
	info = drm_fb_helper_alloc_fbi(helper);
	if (IS_ERR(info)) {
229
		DRM_ERROR("Failed to allocate fb_info\n");
230
		ret = PTR_ERR(info);
231
		goto out_unpin;
J
Jesse Barnes 已提交
232 233
	}

234
	info->par = helper;
J
Jesse Barnes 已提交
235

236
	fb = &ifbdev->fb->base;
J
Jesse Barnes 已提交
237

238
	ifbdev->helper.fb = fb;
239

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

242
	info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
J
Jesse Barnes 已提交
243 244
	info->fbops = &intelfb_ops;

245
	/* setup aperture base/size for vesafb takeover */
246
	info->apertures->ranges[0].base = dev->mode_config.fb_base;
247
	info->apertures->ranges[0].size = dev_priv->ggtt.mappable_end;
248

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

252
	info->screen_base =
253
		ioremap_wc(dev_priv->ggtt.mappable_base + i915_gem_obj_ggtt_offset(obj),
254
			   size);
J
Jesse Barnes 已提交
255
	if (!info->screen_base) {
256
		DRM_ERROR("Failed to remap framebuffer into virtual memory\n");
J
Jesse Barnes 已提交
257
		ret = -ENOSPC;
258
		goto out_destroy_fbi;
J
Jesse Barnes 已提交
259 260 261
	}
	info->screen_size = size;

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

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

268 269 270 271
	/* 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.
	 */
272
	if (ifbdev->fb->obj->stolen && !prealloc)
273 274
		memset_io(info->screen_base, 0, info->screen_size);

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

277
	DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08llx, bo %p\n",
278
		      fb->width, fb->height,
279
		      i915_gem_obj_ggtt_offset(obj), obj);
J
Jesse Barnes 已提交
280 281

	mutex_unlock(&dev->struct_mutex);
282
	vga_switcheroo_client_fb_set(dev->pdev, info);
J
Jesse Barnes 已提交
283 284
	return 0;

285 286
out_destroy_fbi:
	drm_fb_helper_release_fbi(helper);
287
out_unpin:
B
Ben Widawsky 已提交
288
	i915_gem_object_ggtt_unpin(obj);
289
out_unlock:
J
Jesse Barnes 已提交
290 291 292 293
	mutex_unlock(&dev->struct_mutex);
	return ret;
}

294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
/** 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;
}

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 347 348 349 350 351 352 353 354 355 356
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,
357
				    struct drm_fb_offset *offsets,
358 359
				    bool *enabled, int width, int height)
{
360
	struct drm_device *dev = fb_helper->dev;
361
	int i, j;
362
	bool *save_enabled;
363
	bool fallback = true;
364 365
	int num_connectors_enabled = 0;
	int num_connectors_detected = 0;
366 367
	uint64_t conn_configured = 0, mask;
	int pass = 0;
368 369 370 371 372 373 374

	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);
375 376
	mask = (1 << fb_helper->connector_count) - 1;
retry:
377 378 379 380 381 382 383 384
	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;
385

386 387 388 389 390 391
		if (conn_configured & (1 << i))
			continue;

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

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

395
		if (!enabled[i]) {
396
			DRM_DEBUG_KMS("connector %s not enabled, skipping\n",
397
				      connector->name);
398
			conn_configured |= (1 << i);
399 400 401
			continue;
		}

402 403 404 405 406 407 408
		if (connector->force == DRM_FORCE_OFF) {
			DRM_DEBUG_KMS("connector %s is disabled by user, skipping\n",
				      connector->name);
			enabled[i] = false;
			continue;
		}

409 410
		encoder = connector->state->best_encoder;
		if (!encoder || WARN_ON(!connector->state->crtc)) {
411 412 413
			if (connector->force > DRM_FORCE_OFF)
				goto bail;

414
			DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n",
415
				      connector->name);
416
			enabled[i] = false;
417
			conn_configured |= (1 << i);
418 419 420
			continue;
		}

421 422
		num_connectors_enabled++;

423
		new_crtc = intel_fb_helper_crtc(fb_helper, connector->state->crtc);
424 425 426 427 428 429 430

		/*
		 * 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++) {
431
			if (crtcs[j] == new_crtc) {
432
				DRM_DEBUG_KMS("fallback: cloned configuration\n");
433
				goto bail;
434
			}
435 436
		}

437
		DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n",
438
			      connector->name);
439 440 441 442 443 444

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

		/* try for preferred next */
		if (!modes[i]) {
445 446
			DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n",
				      connector->name, connector->has_tile);
447 448 449 450
			modes[i] = drm_has_preferred_mode(fb_conn, width,
							  height);
		}

451 452 453
		/* 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",
454
				      connector->name);
455 456 457 458 459
			modes[i] = list_first_entry(&connector->modes,
						    struct drm_display_mode,
						    head);
		}

460 461 462 463 464 465
		/* 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
466
			 * usually contains. But since our current
467
			 * code puts a mode derived from the post-pfit timings
468
			 * into crtc->mode this works out correctly.
469 470 471 472 473
			 *
			 * This is crtc->mode and not crtc->state->mode for the
			 * fastboot check to work correctly. crtc_state->mode has
			 * I915_MODE_FLAG_INHERITED, which we clear to force check
			 * state.
474
			 */
475
			DRM_DEBUG_KMS("looking for current mode on connector %s\n",
476
				      connector->name);
477
			modes[i] = &connector->state->crtc->mode;
478 479 480
		}
		crtcs[i] = new_crtc;

481
		DRM_DEBUG_KMS("connector %s on pipe %c [CRTC:%d]: %dx%d%s\n",
482
			      connector->name,
483 484
			      pipe_name(to_intel_crtc(connector->state->crtc)->pipe),
			      connector->state->crtc->base.id,
485 486
			      modes[i]->hdisplay, modes[i]->vdisplay,
			      modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" :"");
487

488
		fallback = false;
489 490 491 492 493 494
		conn_configured |= (1 << i);
	}

	if ((conn_configured & mask) != mask) {
		pass++;
		goto retry;
495 496
	}

497 498 499 500 501 502 503 504 505 506 507 508 509
	/*
	 * 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;
	}

510
	if (fallback) {
511
bail:
512
		DRM_DEBUG_KMS("Not using firmware configuration\n");
513 514 515
		memcpy(enabled, save_enabled, dev->mode_config.num_connector);
		kfree(save_enabled);
		return false;
516 517
	}

518
	kfree(save_enabled);
519 520 521
	return true;
}

522
static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
523
	.initial_config = intel_fb_initial_config,
524 525
	.gamma_set = intel_crtc_fb_gamma_set,
	.gamma_get = intel_crtc_fb_gamma_get,
526
	.fb_probe = intelfb_create,
527
};
J
Jesse Barnes 已提交
528

529 530
static void intel_fbdev_destroy(struct drm_device *dev,
				struct intel_fbdev *ifbdev)
J
Jesse Barnes 已提交
531
{
532 533 534 535
	/* We rely on the object-free to release the VMA pinning for
	 * the info->screen_base mmaping. Leaking the VMA is simpler than
	 * trying to rectify all the possible error paths leading here.
	 */
536

537 538
	drm_fb_helper_unregister_fbi(&ifbdev->helper);
	drm_fb_helper_release_fbi(&ifbdev->helper);
J
Jesse Barnes 已提交
539

540
	drm_fb_helper_fini(&ifbdev->helper);
J
Jesse Barnes 已提交
541

542 543 544 545
	if (ifbdev->fb) {
		drm_framebuffer_unregister_private(&ifbdev->fb->base);
		drm_framebuffer_remove(&ifbdev->fb->base);
	}
J
Jesse Barnes 已提交
546
}
547

548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
/*
 * 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;

	/* Find the largest fb */
566
	for_each_crtc(dev, crtc) {
567 568
		struct drm_i915_gem_object *obj =
			intel_fb_obj(crtc->primary->state->fb);
569 570
		intel_crtc = to_intel_crtc(crtc);

571
		if (!crtc->state->active || !obj) {
572 573 574 575 576
			DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n",
				      pipe_name(intel_crtc->pipe));
			continue;
		}

577
		if (obj->base.size > max_size) {
578 579
			DRM_DEBUG_KMS("found possible fb from plane %c\n",
				      pipe_name(intel_crtc->pipe));
580 581
			fb = to_intel_framebuffer(crtc->primary->state->fb);
			max_size = obj->base.size;
582 583 584 585 586 587 588 589 590
		}
	}

	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 */
591
	for_each_crtc(dev, crtc) {
592 593 594 595
		unsigned int cur_size;

		intel_crtc = to_intel_crtc(crtc);

596
		if (!crtc->state->active) {
597 598 599 600 601 602 603 604 605 606
			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
607 608
		 * pipe.  Note we need to use the selected fb's pitch and bpp
		 * rather than the current pipe's, since they differ.
609
		 */
610
		cur_size = intel_crtc->config->base.adjusted_mode.crtc_hdisplay;
611 612 613 614 615 616 617 618 619
		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;
		}

620
		cur_size = intel_crtc->config->base.adjusted_mode.crtc_vdisplay;
621
		cur_size = intel_fb_align_height(dev, cur_size,
622 623
						 fb->base.pixel_format,
						 fb->base.modifier[0]);
624 625 626
		cur_size *= fb->base.pitches[0];
		DRM_DEBUG_KMS("pipe %c area: %dx%d, bpp: %d, size: %d\n",
			      pipe_name(intel_crtc->pipe),
627 628
			      intel_crtc->config->base.adjusted_mode.crtc_hdisplay,
			      intel_crtc->config->base.adjusted_mode.crtc_vdisplay,
629
			      fb->base.bits_per_pixel,
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
			      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;
	}

650
	ifbdev->preferred_bpp = fb->base.bits_per_pixel;
651 652
	ifbdev->fb = fb;

653
	drm_framebuffer_reference(&ifbdev->fb->base);
654 655

	/* Final pass to check if any active pipes don't have fbs */
656
	for_each_crtc(dev, crtc) {
657 658
		intel_crtc = to_intel_crtc(crtc);

659
		if (!crtc->state->active)
660 661
			continue;

662
		WARN(!crtc->primary->fb,
663 664 665 666 667 668 669 670 671 672 673 674 675
		     "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;
}

676 677 678 679 680 681 682 683 684
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);
}

685 686
int intel_fbdev_init(struct drm_device *dev)
{
687
	struct intel_fbdev *ifbdev;
688
	struct drm_i915_private *dev_priv = dev->dev_private;
689
	int ret;
690

691 692 693 694 695
	if (WARN_ON(INTEL_INFO(dev)->num_pipes == 0))
		return -ENODEV;

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

698 699
	drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);

700 701
	if (!intel_fbdev_init_bios(dev, ifbdev))
		ifbdev->preferred_bpp = 32;
702

703
	ret = drm_fb_helper_init(dev, &ifbdev->helper,
704
				 INTEL_INFO(dev)->num_pipes, 4);
705 706 707 708
	if (ret) {
		kfree(ifbdev);
		return ret;
	}
709

R
Rob Clark 已提交
710 711
	ifbdev->helper.atomic = true;

712
	dev_priv->fbdev = ifbdev;
713 714
	INIT_WORK(&dev_priv->fbdev_suspend_work, intel_fbdev_suspend_worker);

715
	drm_fb_helper_single_add_all_connectors(&ifbdev->helper);
716

J
Jesse Barnes 已提交
717 718
	return 0;
}
719

720
static void intel_fbdev_initial_config(void *data, async_cookie_t cookie)
721
{
722
	struct drm_i915_private *dev_priv = data;
723
	struct intel_fbdev *ifbdev = dev_priv->fbdev;
724 725

	/* Due to peculiar init order wrt to hpd handling this is separate. */
726 727 728
	if (drm_fb_helper_initial_config(&ifbdev->helper,
					 ifbdev->preferred_bpp))
		intel_fbdev_fini(dev_priv->dev);
729 730
}

731 732 733 734 735
void intel_fbdev_initial_config_async(struct drm_device *dev)
{
	async_schedule(intel_fbdev_initial_config, to_i915(dev));
}

736 737
void intel_fbdev_fini(struct drm_device *dev)
{
738
	struct drm_i915_private *dev_priv = dev->dev_private;
739 740 741
	if (!dev_priv->fbdev)
		return;

742 743
	flush_work(&dev_priv->fbdev_suspend_work);

744 745
	if (!current_is_async())
		async_synchronize_full();
746
	intel_fbdev_destroy(dev, dev_priv->fbdev);
747
	kfree(dev_priv->fbdev);
748 749
	dev_priv->fbdev = NULL;
}
750

751
void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous)
752
{
753
	struct drm_i915_private *dev_priv = dev->dev_private;
754 755 756 757
	struct intel_fbdev *ifbdev = dev_priv->fbdev;
	struct fb_info *info;

	if (!ifbdev)
758 759
		return;

760 761
	info = ifbdev->helper.fbdev;

762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788
	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;
		}
	}

789 790 791 792
	/* 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.
	 */
793
	if (state == FBINFO_STATE_RUNNING && ifbdev->fb->obj->stolen)
794 795
		memset_io(info->screen_base, 0, info->screen_size);

796
	drm_fb_helper_set_suspend(&ifbdev->helper, state);
797
	console_unlock();
798 799
}

800
void intel_fbdev_output_poll_changed(struct drm_device *dev)
801
{
802
	struct drm_i915_private *dev_priv = dev->dev_private;
803 804
	if (dev_priv->fbdev)
		drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
805
}
806

807
void intel_fbdev_restore_mode(struct drm_device *dev)
808 809
{
	int ret;
810
	struct drm_i915_private *dev_priv = dev->dev_private;
811 812
	struct intel_fbdev *ifbdev = dev_priv->fbdev;
	struct drm_fb_helper *fb_helper;
813

814
	if (!ifbdev)
B
Ben Widawsky 已提交
815 816
		return;

817 818 819 820
	fb_helper = &ifbdev->helper;

	ret = drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
	if (ret) {
821
		DRM_DEBUG("failed to restore crtc mode\n");
822 823 824 825 826
	} else {
		mutex_lock(&fb_helper->dev->struct_mutex);
		intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT);
		mutex_unlock(&fb_helper->dev->struct_mutex);
	}
827
}