intel_fbdev.c 23.8 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
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);
66
		intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT);
67 68 69 70 71 72
		mutex_unlock(&fb_helper->dev->struct_mutex);
	}

	return ret;
}

73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
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) {
		/*
		 * 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);
91
		intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT);
92 93 94 95 96 97
		mutex_unlock(&fb_helper->dev->struct_mutex);
	}

	return ret;
}

98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
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) {
		/*
		 * 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);
117
		intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT);
118 119 120 121 122 123
		mutex_unlock(&fb_helper->dev->struct_mutex);
	}

	return ret;
}

J
Jesse Barnes 已提交
124 125
static struct fb_ops intelfb_ops = {
	.owner = THIS_MODULE,
126
	.fb_check_var = drm_fb_helper_check_var,
127
	.fb_set_par = intel_fbdev_set_par,
J
Jesse Barnes 已提交
128 129 130
	.fb_fillrect = cfb_fillrect,
	.fb_copyarea = cfb_copyarea,
	.fb_imageblit = cfb_imageblit,
131
	.fb_pan_display = intel_fbdev_pan_display,
132
	.fb_blank = intel_fbdev_blank,
133
	.fb_setcmap = drm_fb_helper_setcmap,
J
Jesse Barnes 已提交
134 135
	.fb_debug_enter = drm_fb_helper_debug_enter,
	.fb_debug_leave = drm_fb_helper_debug_leave,
J
Jesse Barnes 已提交
136 137
};

138 139
static int intelfb_alloc(struct drm_fb_helper *helper,
			 struct drm_fb_helper_surface_size *sizes)
J
Jesse Barnes 已提交
140
{
141 142
	struct intel_fbdev *ifbdev =
		container_of(helper, struct intel_fbdev, helper);
143
	struct drm_framebuffer *fb;
144
	struct drm_device *dev = helper->dev;
145
	struct drm_mode_fb_cmd2 mode_cmd = {};
146
	struct drm_i915_gem_object *obj;
147
	int size, ret;
J
Jesse Barnes 已提交
148

149
	/* we don't do packed 24bpp */
150 151
	if (sizes->surface_bpp == 24)
		sizes->surface_bpp = 32;
152

153 154
	mode_cmd.width = sizes->surface_width;
	mode_cmd.height = sizes->surface_height;
J
Jesse Barnes 已提交
155

156 157
	mode_cmd.pitches[0] = ALIGN(mode_cmd.width *
				    DIV_ROUND_UP(sizes->surface_bpp, 8), 64);
158 159
	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
							  sizes->surface_depth);
J
Jesse Barnes 已提交
160

161
	size = mode_cmd.pitches[0] * mode_cmd.height;
162
	size = PAGE_ALIGN(size);
163 164 165
	obj = i915_gem_object_create_stolen(dev, size);
	if (obj == NULL)
		obj = i915_gem_alloc_object(dev, size);
166
	if (!obj) {
167
		DRM_ERROR("failed to allocate framebuffer\n");
J
Jesse Barnes 已提交
168 169 170 171
		ret = -ENOMEM;
		goto out;
	}

172 173 174
	fb = __intel_framebuffer_create(dev, &mode_cmd, obj);
	if (IS_ERR(fb)) {
		ret = PTR_ERR(fb);
175 176 177 178
		goto out_unref;
	}

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

	ifbdev->fb = to_intel_framebuffer(fb);
186 187 188

	return 0;

189 190
out_fb:
	drm_framebuffer_remove(fb);
191 192 193 194 195 196 197 198 199 200 201
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);
202
	struct intel_framebuffer *intel_fb = ifbdev->fb;
203 204 205 206 207 208
	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;
209
	bool prealloc = false;
210 211 212

	mutex_lock(&dev->struct_mutex);

213 214 215 216 217 218 219 220 221 222
	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;
	}
223
	if (!intel_fb || WARN_ON(!intel_fb->obj)) {
224
		DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n");
225 226 227
		ret = intelfb_alloc(helper, sizes);
		if (ret)
			goto out_unlock;
228
		intel_fb = ifbdev->fb;
229
	} else {
230
		DRM_DEBUG_KMS("re-using BIOS fb\n");
231
		prealloc = true;
232 233 234 235 236 237 238 239
		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 已提交
240 241
	if (!info) {
		ret = -ENOMEM;
242
		goto out_unpin;
J
Jesse Barnes 已提交
243 244
	}

245
	info->par = helper;
J
Jesse Barnes 已提交
246

247
	fb = &ifbdev->fb->base;
J
Jesse Barnes 已提交
248

249 250
	ifbdev->helper.fb = fb;
	ifbdev->helper.fbdev = info;
251

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

254
	info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
J
Jesse Barnes 已提交
255 256
	info->fbops = &intelfb_ops;

257 258 259 260 261
	ret = fb_alloc_cmap(&info->cmap, 256, 0);
	if (ret) {
		ret = -ENOMEM;
		goto out_unpin;
	}
262
	/* setup aperture base/size for vesafb takeover */
263 264 265 266 267 268
	info->apertures = alloc_apertures(1);
	if (!info->apertures) {
		ret = -ENOMEM;
		goto out_unpin;
	}
	info->apertures->ranges[0].base = dev->mode_config.fb_base;
269
	info->apertures->ranges[0].size = dev_priv->gtt.mappable_end;
270

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

274
	info->screen_base =
275
		ioremap_wc(dev_priv->gtt.mappable_base + i915_gem_obj_ggtt_offset(obj),
276
			   size);
J
Jesse Barnes 已提交
277 278
	if (!info->screen_base) {
		ret = -ENOSPC;
279
		goto out_unpin;
J
Jesse Barnes 已提交
280 281 282
	}
	info->screen_size = size;

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

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

289 290 291 292
	/* 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.
	 */
293
	if (ifbdev->fb->obj->stolen && !prealloc)
294 295
		memset_io(info->screen_base, 0, info->screen_size);

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

298
	DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08lx, bo %p\n",
299
		      fb->width, fb->height,
300
		      i915_gem_obj_ggtt_offset(obj), obj);
J
Jesse Barnes 已提交
301 302

	mutex_unlock(&dev->struct_mutex);
303
	vga_switcheroo_client_fb_set(dev->pdev, info);
J
Jesse Barnes 已提交
304 305
	return 0;

306
out_unpin:
B
Ben Widawsky 已提交
307
	i915_gem_object_ggtt_unpin(obj);
308
	drm_gem_object_unreference(&obj->base);
309
out_unlock:
J
Jesse Barnes 已提交
310 311 312 313
	mutex_unlock(&dev->struct_mutex);
	return ret;
}

314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
/** 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;
}

335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
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,
377
				    struct drm_fb_offset *offsets,
378 379
				    bool *enabled, int width, int height)
{
380
	struct drm_device *dev = fb_helper->dev;
381
	int i, j;
382
	bool *save_enabled;
383
	bool fallback = true;
384 385
	int num_connectors_enabled = 0;
	int num_connectors_detected = 0;
386 387
	uint64_t conn_configured = 0, mask;
	int pass = 0;
388 389 390 391 392 393 394

	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);
395 396
	mask = (1 << fb_helper->connector_count) - 1;
retry:
397 398 399 400 401 402 403 404
	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;
405

406 407 408 409 410 411
		if (conn_configured & (1 << i))
			continue;

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

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

415
		if (!enabled[i]) {
416
			DRM_DEBUG_KMS("connector %s not enabled, skipping\n",
417
				      connector->name);
418
			conn_configured |= (1 << i);
419 420 421
			continue;
		}

422 423 424 425 426 427 428
		if (connector->force == DRM_FORCE_OFF) {
			DRM_DEBUG_KMS("connector %s is disabled by user, skipping\n",
				      connector->name);
			enabled[i] = false;
			continue;
		}

429 430
		encoder = connector->encoder;
		if (!encoder || WARN_ON(!encoder->crtc)) {
431 432 433
			if (connector->force > DRM_FORCE_OFF)
				goto bail;

434
			DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n",
435
				      connector->name);
436
			enabled[i] = false;
437
			conn_configured |= (1 << i);
438 439 440
			continue;
		}

441 442
		num_connectors_enabled++;

443 444 445 446 447 448 449 450
		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++) {
451
			if (crtcs[j] == new_crtc) {
452
				DRM_DEBUG_KMS("fallback: cloned configuration\n");
453
				goto bail;
454
			}
455 456
		}

457
		DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n",
458
			      connector->name);
459 460 461 462 463 464

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

		/* try for preferred next */
		if (!modes[i]) {
465 466
			DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n",
				      connector->name, connector->has_tile);
467 468 469 470
			modes[i] = drm_has_preferred_mode(fb_conn, width,
							  height);
		}

471 472 473
		/* 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",
474
				      connector->name);
475 476 477 478 479
			modes[i] = list_first_entry(&connector->modes,
						    struct drm_display_mode,
						    head);
		}

480 481 482 483 484 485 486 487 488 489 490 491 492
		/* 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.
			 */
493
			DRM_DEBUG_KMS("looking for current mode on connector %s\n",
494
				      connector->name);
495
			intel_mode_from_pipe_config(&encoder->crtc->hwmode,
496
						    to_intel_crtc(encoder->crtc)->config);
497 498 499 500
			modes[i] = &encoder->crtc->hwmode;
		}
		crtcs[i] = new_crtc;

501
		DRM_DEBUG_KMS("connector %s on pipe %c [CRTC:%d]: %dx%d%s\n",
502
			      connector->name,
503
			      pipe_name(to_intel_crtc(encoder->crtc)->pipe),
504
			      encoder->crtc->base.id,
505 506
			      modes[i]->hdisplay, modes[i]->vdisplay,
			      modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" :"");
507

508
		fallback = false;
509 510 511 512 513 514
		conn_configured |= (1 << i);
	}

	if ((conn_configured & mask) != mask) {
		pass++;
		goto retry;
515 516
	}

517 518 519 520 521 522 523 524 525 526 527 528 529
	/*
	 * 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;
	}

530
	if (fallback) {
531
bail:
532
		DRM_DEBUG_KMS("Not using firmware configuration\n");
533 534 535
		memcpy(enabled, save_enabled, dev->mode_config.num_connector);
		kfree(save_enabled);
		return false;
536 537
	}

538
	kfree(save_enabled);
539 540 541
	return true;
}

542
static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
543
	.initial_config = intel_fb_initial_config,
544 545
	.gamma_set = intel_crtc_fb_gamma_set,
	.gamma_get = intel_crtc_fb_gamma_get,
546
	.fb_probe = intelfb_create,
547
};
J
Jesse Barnes 已提交
548

549 550
static void intel_fbdev_destroy(struct drm_device *dev,
				struct intel_fbdev *ifbdev)
J
Jesse Barnes 已提交
551
{
552
	if (ifbdev->helper.fbdev) {
553 554
		struct fb_info *info = ifbdev->helper.fbdev;

J
Jesse Barnes 已提交
555 556
		unregister_framebuffer(info);
		iounmap(info->screen_base);
557 558
		if (info->cmap.len)
			fb_dealloc_cmap(&info->cmap);
559

J
Jesse Barnes 已提交
560 561 562
		framebuffer_release(info);
	}

563
	drm_fb_helper_fini(&ifbdev->helper);
J
Jesse Barnes 已提交
564

565
	drm_framebuffer_unregister_private(&ifbdev->fb->base);
566
	drm_framebuffer_remove(&ifbdev->fb->base);
J
Jesse Barnes 已提交
567
}
568

569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
/*
 * 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;
584
	struct intel_initial_plane_config *plane_config = NULL;
585 586 587 588 589 590
	unsigned int max_size = 0;

	if (!i915.fastboot)
		return false;

	/* Find the largest fb */
591
	for_each_crtc(dev, crtc) {
592 593
		intel_crtc = to_intel_crtc(crtc);

594
		if (!intel_crtc->active || !crtc->primary->fb) {
595 596 597 598 599 600 601 602 603
			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;
604
			fb = to_intel_framebuffer(crtc->primary->fb);
605 606 607 608 609 610 611 612 613 614
			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 */
615
	for_each_crtc(dev, crtc) {
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630
		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
631 632
		 * pipe.  Note we need to use the selected fb's pitch and bpp
		 * rather than the current pipe's, since they differ.
633
		 */
634
		cur_size = intel_crtc->config->base.adjusted_mode.crtc_hdisplay;
635 636 637 638 639 640 641 642 643 644
		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;
		}

645
		cur_size = intel_crtc->config->base.adjusted_mode.crtc_vdisplay;
646
		cur_size = intel_fb_align_height(dev, cur_size,
647 648
						 fb->base.pixel_format,
						 fb->base.modifier[0]);
649 650 651
		cur_size *= fb->base.pitches[0];
		DRM_DEBUG_KMS("pipe %c area: %dx%d, bpp: %d, size: %d\n",
			      pipe_name(intel_crtc->pipe),
652 653
			      intel_crtc->config->base.adjusted_mode.crtc_hdisplay,
			      intel_crtc->config->base.adjusted_mode.crtc_vdisplay,
654
			      fb->base.bits_per_pixel,
655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675
			      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;
	}

676
	ifbdev->preferred_bpp = fb->base.bits_per_pixel;
677 678
	ifbdev->fb = fb;

679
	drm_framebuffer_reference(&ifbdev->fb->base);
680 681

	/* Final pass to check if any active pipes don't have fbs */
682
	for_each_crtc(dev, crtc) {
683 684 685 686 687
		intel_crtc = to_intel_crtc(crtc);

		if (!intel_crtc->active)
			continue;

688
		WARN(!crtc->primary->fb,
689 690 691 692 693 694 695 696 697 698 699 700 701
		     "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;
}

702 703 704 705 706 707 708 709 710
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);
}

711 712
int intel_fbdev_init(struct drm_device *dev)
{
713
	struct intel_fbdev *ifbdev;
714
	struct drm_i915_private *dev_priv = dev->dev_private;
715
	int ret;
716

717 718 719 720 721
	if (WARN_ON(INTEL_INFO(dev)->num_pipes == 0))
		return -ENODEV;

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

724 725
	drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);

726 727
	if (!intel_fbdev_init_bios(dev, ifbdev))
		ifbdev->preferred_bpp = 32;
728

729
	ret = drm_fb_helper_init(dev, &ifbdev->helper,
730
				 INTEL_INFO(dev)->num_pipes, 4);
731 732 733 734
	if (ret) {
		kfree(ifbdev);
		return ret;
	}
735

736
	dev_priv->fbdev = ifbdev;
737 738
	INIT_WORK(&dev_priv->fbdev_suspend_work, intel_fbdev_suspend_worker);

739
	drm_fb_helper_single_add_all_connectors(&ifbdev->helper);
740

J
Jesse Barnes 已提交
741 742
	return 0;
}
743

744
void intel_fbdev_initial_config(void *data, async_cookie_t cookie)
745
{
746
	struct drm_i915_private *dev_priv = data;
747
	struct intel_fbdev *ifbdev = dev_priv->fbdev;
748 749

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

753 754
void intel_fbdev_fini(struct drm_device *dev)
{
755
	struct drm_i915_private *dev_priv = dev->dev_private;
756 757 758
	if (!dev_priv->fbdev)
		return;

759 760
	flush_work(&dev_priv->fbdev_suspend_work);

761
	async_synchronize_full();
762
	intel_fbdev_destroy(dev, dev_priv->fbdev);
763
	kfree(dev_priv->fbdev);
764 765
	dev_priv->fbdev = NULL;
}
766

767
void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous)
768
{
769
	struct drm_i915_private *dev_priv = dev->dev_private;
770 771 772 773
	struct intel_fbdev *ifbdev = dev_priv->fbdev;
	struct fb_info *info;

	if (!ifbdev)
774 775
		return;

776 777
	info = ifbdev->helper.fbdev;

778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804
	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;
		}
	}

805 806 807 808
	/* 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.
	 */
809
	if (state == FBINFO_STATE_RUNNING && ifbdev->fb->obj->stolen)
810 811 812
		memset_io(info->screen_base, 0, info->screen_size);

	fb_set_suspend(info, state);
813
	console_unlock();
814 815
}

816
void intel_fbdev_output_poll_changed(struct drm_device *dev)
817
{
818
	struct drm_i915_private *dev_priv = dev->dev_private;
819 820
	if (dev_priv->fbdev)
		drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
821
}
822

823
void intel_fbdev_restore_mode(struct drm_device *dev)
824 825
{
	int ret;
826
	struct drm_i915_private *dev_priv = dev->dev_private;
827 828
	struct intel_fbdev *ifbdev = dev_priv->fbdev;
	struct drm_fb_helper *fb_helper;
829

830
	if (!ifbdev)
B
Ben Widawsky 已提交
831 832
		return;

833 834 835 836
	fb_helper = &ifbdev->helper;

	ret = drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
	if (ret) {
837
		DRM_DEBUG("failed to restore crtc mode\n");
838 839 840 841 842
	} else {
		mutex_lock(&fb_helper->dev->struct_mutex);
		intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT);
		mutex_unlock(&fb_helper->dev->struct_mutex);
	}
843
}