Rev 4560 | Rev 5354 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4560 | Rev 5060 | ||
---|---|---|---|
Line 88... | Line 88... | ||
88 | static int intelfb_alloc(struct drm_fb_helper *helper, |
88 | static int intelfb_alloc(struct drm_fb_helper *helper, |
89 | struct drm_fb_helper_surface_size *sizes) |
89 | struct drm_fb_helper_surface_size *sizes) |
90 | { |
90 | { |
91 | struct intel_fbdev *ifbdev = |
91 | struct intel_fbdev *ifbdev = |
92 | container_of(helper, struct intel_fbdev, helper); |
92 | container_of(helper, struct intel_fbdev, helper); |
- | 93 | struct drm_framebuffer *fb; |
|
93 | struct drm_device *dev = helper->dev; |
94 | struct drm_device *dev = helper->dev; |
94 | struct drm_mode_fb_cmd2 mode_cmd = {}; |
95 | struct drm_mode_fb_cmd2 mode_cmd = {}; |
95 | struct drm_i915_gem_object *obj; |
96 | struct drm_i915_gem_object *obj; |
96 | int size, ret; |
97 | int size, ret; |
Line 113... | Line 114... | ||
113 | if (!obj) { |
114 | if (!obj) { |
114 | DRM_ERROR("failed to allocate framebuffer\n"); |
115 | DRM_ERROR("failed to allocate framebuffer\n"); |
115 | ret = -ENOMEM; |
116 | ret = -ENOMEM; |
116 | goto out; |
117 | goto out; |
117 | } |
118 | } |
118 | obj->has_global_gtt_mapping = 0; |
- | |
119 | obj->stride = mode_cmd.pitches[0]; |
119 | obj->stride = mode_cmd.pitches[0]; |
Line 120... | Line 120... | ||
120 | 120 | ||
121 | /* Flush everything out, we'll be doing GTT only from now on */ |
121 | /* Flush everything out, we'll be doing GTT only from now on */ |
122 | ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); |
122 | ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); |
123 | if (ret) { |
123 | if (ret) { |
124 | DRM_ERROR("failed to pin fb: %d\n", ret); |
124 | DRM_ERROR("failed to pin obj: %d\n", ret); |
125 | goto out_unref; |
125 | goto out_unref; |
Line 126... | Line 126... | ||
126 | } |
126 | } |
127 | 127 | ||
- | 128 | fb = __intel_framebuffer_create(dev, &mode_cmd, obj); |
|
128 | ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj); |
129 | if (IS_ERR(fb)) { |
- | 130 | ret = PTR_ERR(fb); |
|
- | 131 | goto out_unpin; |
|
- | 132 | } |
|
Line 129... | Line 133... | ||
129 | if (ret) |
133 | |
Line 130... | Line 134... | ||
130 | goto out_unpin; |
134 | ifbdev->fb = to_intel_framebuffer(fb); |
131 | 135 | ||
132 | return 0; |
136 | return 0; |
133 | 137 | ||
134 | out_unpin: |
138 | out_unpin: |
135 | i915_gem_object_unpin(obj); |
139 | i915_gem_object_ggtt_unpin(obj); |
136 | out_unref: |
140 | out_unref: |
Line 142... | Line 146... | ||
142 | static int intelfb_create(struct drm_fb_helper *helper, |
146 | static int intelfb_create(struct drm_fb_helper *helper, |
143 | struct drm_fb_helper_surface_size *sizes) |
147 | struct drm_fb_helper_surface_size *sizes) |
144 | { |
148 | { |
145 | struct intel_fbdev *ifbdev = |
149 | struct intel_fbdev *ifbdev = |
146 | container_of(helper, struct intel_fbdev, helper); |
150 | container_of(helper, struct intel_fbdev, helper); |
147 | struct intel_framebuffer *intel_fb = &ifbdev->ifb; |
151 | struct intel_framebuffer *intel_fb = ifbdev->fb; |
148 | struct drm_device *dev = helper->dev; |
152 | struct drm_device *dev = helper->dev; |
149 | struct drm_i915_private *dev_priv = dev->dev_private; |
153 | struct drm_i915_private *dev_priv = dev->dev_private; |
150 | struct fb_info *info; |
154 | struct fb_info *info; |
151 | struct drm_framebuffer *fb; |
155 | struct drm_framebuffer *fb; |
152 | struct drm_i915_gem_object *obj; |
156 | struct drm_i915_gem_object *obj; |
153 | int size, ret; |
157 | int size, ret; |
- | 158 | bool prealloc = false; |
|
Line 154... | Line 159... | ||
154 | 159 | ||
Line 155... | Line 160... | ||
155 | mutex_lock(&dev->struct_mutex); |
160 | mutex_lock(&dev->struct_mutex); |
- | 161 | ||
- | 162 | if (intel_fb && |
|
- | 163 | (sizes->fb_width > intel_fb->base.width || |
|
- | 164 | sizes->fb_height > intel_fb->base.height)) { |
|
- | 165 | DRM_DEBUG_KMS("BIOS fb too small (%dx%d), we require (%dx%d)," |
|
- | 166 | " releasing it\n", |
|
- | 167 | intel_fb->base.width, intel_fb->base.height, |
|
- | 168 | sizes->fb_width, sizes->fb_height); |
|
- | 169 | drm_framebuffer_unreference(&intel_fb->base); |
|
- | 170 | intel_fb = ifbdev->fb = NULL; |
|
156 | 171 | } |
|
157 | if (!intel_fb->obj) { |
172 | if (!intel_fb || WARN_ON(!intel_fb->obj)) { |
158 | DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n"); |
173 | DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n"); |
159 | ret = intelfb_alloc(helper, sizes); |
174 | ret = intelfb_alloc(helper, sizes); |
- | 175 | if (ret) |
|
160 | if (ret) |
176 | goto out_unlock; |
161 | goto out_unlock; |
177 | intel_fb = ifbdev->fb; |
- | 178 | } else { |
|
162 | } else { |
179 | DRM_DEBUG_KMS("re-using BIOS fb\n"); |
163 | DRM_DEBUG_KMS("re-using BIOS fb\n"); |
180 | prealloc = true; |
164 | sizes->fb_width = intel_fb->base.width; |
181 | sizes->fb_width = intel_fb->base.width; |
Line 165... | Line 182... | ||
165 | sizes->fb_height = intel_fb->base.height; |
182 | sizes->fb_height = intel_fb->base.height; |
Line 174... | Line 191... | ||
174 | goto out_unpin; |
191 | goto out_unpin; |
175 | } |
192 | } |
Line 176... | Line 193... | ||
176 | 193 | ||
Line 177... | Line 194... | ||
177 | info->par = helper; |
194 | info->par = helper; |
Line 178... | Line 195... | ||
178 | 195 | ||
179 | fb = &ifbdev->ifb.base; |
196 | fb = &ifbdev->fb->base; |
Line 180... | Line 197... | ||
180 | 197 | ||
Line 213... | Line 230... | ||
213 | 230 | ||
214 | mutex_unlock(&dev->struct_mutex); |
231 | mutex_unlock(&dev->struct_mutex); |
Line 215... | Line 232... | ||
215 | return 0; |
232 | return 0; |
216 | 233 | ||
217 | out_unpin: |
234 | out_unpin: |
218 | i915_gem_object_unpin(obj); |
235 | i915_gem_object_ggtt_unpin(obj); |
219 | drm_gem_object_unreference(&obj->base); |
236 | drm_gem_object_unreference(&obj->base); |
220 | out_unlock: |
237 | out_unlock: |
221 | mutex_unlock(&dev->struct_mutex); |
238 | mutex_unlock(&dev->struct_mutex); |
Line 241... | Line 258... | ||
241 | *red = intel_crtc->lut_r[regno] << 8; |
258 | *red = intel_crtc->lut_r[regno] << 8; |
242 | *green = intel_crtc->lut_g[regno] << 8; |
259 | *green = intel_crtc->lut_g[regno] << 8; |
243 | *blue = intel_crtc->lut_b[regno] << 8; |
260 | *blue = intel_crtc->lut_b[regno] << 8; |
244 | } |
261 | } |
Line -... | Line 262... | ||
- | 262 | ||
- | 263 | static struct drm_fb_helper_crtc * |
|
- | 264 | intel_fb_helper_crtc(struct drm_fb_helper *fb_helper, struct drm_crtc *crtc) |
|
- | 265 | { |
|
- | 266 | int i; |
|
- | 267 | ||
- | 268 | for (i = 0; i < fb_helper->crtc_count; i++) |
|
- | 269 | if (fb_helper->crtc_info[i].mode_set.crtc == crtc) |
|
- | 270 | return &fb_helper->crtc_info[i]; |
|
- | 271 | ||
- | 272 | return NULL; |
|
- | 273 | } |
|
- | 274 | ||
- | 275 | /* |
|
- | 276 | * Try to read the BIOS display configuration and use it for the initial |
|
- | 277 | * fb configuration. |
|
- | 278 | * |
|
- | 279 | * The BIOS or boot loader will generally create an initial display |
|
- | 280 | * configuration for us that includes some set of active pipes and displays. |
|
- | 281 | * This routine tries to figure out which pipes and connectors are active |
|
- | 282 | * and stuffs them into the crtcs and modes array given to us by the |
|
- | 283 | * drm_fb_helper code. |
|
- | 284 | * |
|
- | 285 | * The overall sequence is: |
|
- | 286 | * intel_fbdev_init - from driver load |
|
- | 287 | * intel_fbdev_init_bios - initialize the intel_fbdev using BIOS data |
|
- | 288 | * drm_fb_helper_init - build fb helper structs |
|
- | 289 | * drm_fb_helper_single_add_all_connectors - more fb helper structs |
|
- | 290 | * intel_fbdev_initial_config - apply the config |
|
- | 291 | * drm_fb_helper_initial_config - call ->probe then register_framebuffer() |
|
- | 292 | * drm_setup_crtcs - build crtc config for fbdev |
|
- | 293 | * intel_fb_initial_config - find active connectors etc |
|
- | 294 | * drm_fb_helper_single_fb_probe - set up fbdev |
|
- | 295 | * intelfb_create - re-use or alloc fb, build out fbdev structs |
|
- | 296 | * |
|
- | 297 | * Note that we don't make special consideration whether we could actually |
|
- | 298 | * switch to the selected modes without a full modeset. E.g. when the display |
|
- | 299 | * is in VGA mode we need to recalculate watermarks and set a new high-res |
|
- | 300 | * framebuffer anyway. |
|
- | 301 | */ |
|
- | 302 | static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper, |
|
- | 303 | struct drm_fb_helper_crtc **crtcs, |
|
- | 304 | struct drm_display_mode **modes, |
|
- | 305 | bool *enabled, int width, int height) |
|
- | 306 | { |
|
- | 307 | struct drm_device *dev = fb_helper->dev; |
|
- | 308 | int i, j; |
|
- | 309 | bool *save_enabled; |
|
- | 310 | bool fallback = true; |
|
- | 311 | int num_connectors_enabled = 0; |
|
- | 312 | int num_connectors_detected = 0; |
|
- | 313 | ||
- | 314 | /* |
|
- | 315 | * If the user specified any force options, just bail here |
|
- | 316 | * and use that config. |
|
- | 317 | */ |
|
- | 318 | for (i = 0; i < fb_helper->connector_count; i++) { |
|
- | 319 | struct drm_fb_helper_connector *fb_conn; |
|
- | 320 | struct drm_connector *connector; |
|
- | 321 | ||
- | 322 | fb_conn = fb_helper->connector_info[i]; |
|
- | 323 | connector = fb_conn->connector; |
|
- | 324 | ||
- | 325 | if (!enabled[i]) |
|
- | 326 | continue; |
|
- | 327 | ||
- | 328 | if (connector->force != DRM_FORCE_UNSPECIFIED) |
|
- | 329 | return false; |
|
- | 330 | } |
|
- | 331 | ||
- | 332 | save_enabled = kcalloc(dev->mode_config.num_connector, sizeof(bool), |
|
- | 333 | GFP_KERNEL); |
|
- | 334 | if (!save_enabled) |
|
- | 335 | return false; |
|
- | 336 | ||
- | 337 | memcpy(save_enabled, enabled, dev->mode_config.num_connector); |
|
- | 338 | ||
- | 339 | for (i = 0; i < fb_helper->connector_count; i++) { |
|
- | 340 | struct drm_fb_helper_connector *fb_conn; |
|
- | 341 | struct drm_connector *connector; |
|
- | 342 | struct drm_encoder *encoder; |
|
- | 343 | struct drm_fb_helper_crtc *new_crtc; |
|
- | 344 | ||
- | 345 | fb_conn = fb_helper->connector_info[i]; |
|
- | 346 | connector = fb_conn->connector; |
|
- | 347 | ||
- | 348 | if (connector->status == connector_status_connected) |
|
- | 349 | num_connectors_detected++; |
|
- | 350 | ||
- | 351 | if (!enabled[i]) { |
|
- | 352 | DRM_DEBUG_KMS("connector %s not enabled, skipping\n", |
|
- | 353 | connector->name); |
|
- | 354 | continue; |
|
- | 355 | } |
|
- | 356 | ||
- | 357 | encoder = connector->encoder; |
|
- | 358 | if (!encoder || WARN_ON(!encoder->crtc)) { |
|
- | 359 | DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n", |
|
- | 360 | connector->name); |
|
- | 361 | enabled[i] = false; |
|
- | 362 | continue; |
|
- | 363 | } |
|
- | 364 | ||
- | 365 | num_connectors_enabled++; |
|
- | 366 | ||
- | 367 | new_crtc = intel_fb_helper_crtc(fb_helper, encoder->crtc); |
|
- | 368 | ||
- | 369 | /* |
|
- | 370 | * Make sure we're not trying to drive multiple connectors |
|
- | 371 | * with a single CRTC, since our cloning support may not |
|
- | 372 | * match the BIOS. |
|
- | 373 | */ |
|
- | 374 | for (j = 0; j < fb_helper->connector_count; j++) { |
|
- | 375 | if (crtcs[j] == new_crtc) { |
|
- | 376 | DRM_DEBUG_KMS("fallback: cloned configuration\n"); |
|
- | 377 | fallback = true; |
|
- | 378 | goto out; |
|
- | 379 | } |
|
- | 380 | } |
|
- | 381 | ||
- | 382 | DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n", |
|
- | 383 | connector->name); |
|
- | 384 | ||
- | 385 | /* go for command line mode first */ |
|
- | 386 | modes[i] = drm_pick_cmdline_mode(fb_conn, width, height); |
|
- | 387 | ||
- | 388 | /* try for preferred next */ |
|
- | 389 | if (!modes[i]) { |
|
- | 390 | DRM_DEBUG_KMS("looking for preferred mode on connector %s\n", |
|
- | 391 | connector->name); |
|
- | 392 | modes[i] = drm_has_preferred_mode(fb_conn, width, |
|
- | 393 | height); |
|
- | 394 | } |
|
- | 395 | ||
- | 396 | /* No preferred mode marked by the EDID? Are there any modes? */ |
|
- | 397 | if (!modes[i] && !list_empty(&connector->modes)) { |
|
- | 398 | DRM_DEBUG_KMS("using first mode listed on connector %s\n", |
|
- | 399 | connector->name); |
|
- | 400 | modes[i] = list_first_entry(&connector->modes, |
|
- | 401 | struct drm_display_mode, |
|
- | 402 | head); |
|
- | 403 | } |
|
- | 404 | ||
- | 405 | /* last resort: use current mode */ |
|
- | 406 | if (!modes[i]) { |
|
- | 407 | /* |
|
- | 408 | * IMPORTANT: We want to use the adjusted mode (i.e. |
|
- | 409 | * after the panel fitter upscaling) as the initial |
|
- | 410 | * config, not the input mode, which is what crtc->mode |
|
- | 411 | * usually contains. But since our current fastboot |
|
- | 412 | * code puts a mode derived from the post-pfit timings |
|
- | 413 | * into crtc->mode this works out correctly. We don't |
|
- | 414 | * use hwmode anywhere right now, so use it for this |
|
- | 415 | * since the fb helper layer wants a pointer to |
|
- | 416 | * something we own. |
|
- | 417 | */ |
|
- | 418 | DRM_DEBUG_KMS("looking for current mode on connector %s\n", |
|
- | 419 | connector->name); |
|
- | 420 | intel_mode_from_pipe_config(&encoder->crtc->hwmode, |
|
- | 421 | &to_intel_crtc(encoder->crtc)->config); |
|
- | 422 | modes[i] = &encoder->crtc->hwmode; |
|
- | 423 | } |
|
- | 424 | crtcs[i] = new_crtc; |
|
- | 425 | ||
- | 426 | DRM_DEBUG_KMS("connector %s on pipe %c [CRTC:%d]: %dx%d%s\n", |
|
- | 427 | connector->name, |
|
- | 428 | pipe_name(to_intel_crtc(encoder->crtc)->pipe), |
|
- | 429 | encoder->crtc->base.id, |
|
- | 430 | modes[i]->hdisplay, modes[i]->vdisplay, |
|
- | 431 | modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" :""); |
|
- | 432 | ||
- | 433 | fallback = false; |
|
- | 434 | } |
|
- | 435 | ||
- | 436 | /* |
|
- | 437 | * If the BIOS didn't enable everything it could, fall back to have the |
|
- | 438 | * same user experiencing of lighting up as much as possible like the |
|
- | 439 | * fbdev helper library. |
|
- | 440 | */ |
|
- | 441 | if (num_connectors_enabled != num_connectors_detected && |
|
- | 442 | num_connectors_enabled < INTEL_INFO(dev)->num_pipes) { |
|
- | 443 | DRM_DEBUG_KMS("fallback: Not all outputs enabled\n"); |
|
- | 444 | DRM_DEBUG_KMS("Enabled: %i, detected: %i\n", num_connectors_enabled, |
|
- | 445 | num_connectors_detected); |
|
- | 446 | fallback = true; |
|
- | 447 | } |
|
- | 448 | ||
- | 449 | out: |
|
- | 450 | if (fallback) { |
|
- | 451 | DRM_DEBUG_KMS("Not using firmware configuration\n"); |
|
- | 452 | memcpy(enabled, save_enabled, dev->mode_config.num_connector); |
|
- | 453 | kfree(save_enabled); |
|
- | 454 | return false; |
|
- | 455 | } |
|
- | 456 | ||
- | 457 | kfree(save_enabled); |
|
- | 458 | return true; |
|
- | 459 | } |
|
245 | 460 | ||
- | 461 | static const struct drm_fb_helper_funcs intel_fb_helper_funcs = { |
|
246 | static struct drm_fb_helper_funcs intel_fb_helper_funcs = { |
462 | .initial_config = intel_fb_initial_config, |
247 | .gamma_set = intel_crtc_fb_gamma_set, |
463 | .gamma_set = intel_crtc_fb_gamma_set, |
248 | .gamma_get = intel_crtc_fb_gamma_get, |
464 | .gamma_get = intel_crtc_fb_gamma_get, |
249 | .fb_probe = intelfb_create, |
465 | .fb_probe = intelfb_create, |
Line -... | Line 466... | ||
- | 466 | }; |
|
- | 467 | ||
- | 468 | /* |
|
- | 469 | * Build an intel_fbdev struct using a BIOS allocated framebuffer, if possible. |
|
- | 470 | * The core display code will have read out the current plane configuration, |
|
- | 471 | * so we use that to figure out if there's an object for us to use as the |
|
- | 472 | * fb, and if so, we re-use it for the fbdev configuration. |
|
- | 473 | * |
|
- | 474 | * Note we only support a single fb shared across pipes for boot (mostly for |
|
- | 475 | * fbcon), so we just find the biggest and use that. |
|
- | 476 | */ |
|
- | 477 | static bool intel_fbdev_init_bios(struct drm_device *dev, |
|
- | 478 | struct intel_fbdev *ifbdev) |
|
- | 479 | { |
|
- | 480 | struct intel_framebuffer *fb = NULL; |
|
- | 481 | struct drm_crtc *crtc; |
|
- | 482 | struct intel_crtc *intel_crtc; |
|
- | 483 | struct intel_plane_config *plane_config = NULL; |
|
- | 484 | unsigned int max_size = 0; |
|
- | 485 | ||
- | 486 | if (!i915.fastboot) |
|
- | 487 | return false; |
|
- | 488 | ||
- | 489 | /* Find the largest fb */ |
|
- | 490 | for_each_crtc(dev, crtc) { |
|
- | 491 | intel_crtc = to_intel_crtc(crtc); |
|
- | 492 | ||
- | 493 | if (!intel_crtc->active || !crtc->primary->fb) { |
|
- | 494 | DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n", |
|
- | 495 | pipe_name(intel_crtc->pipe)); |
|
- | 496 | continue; |
|
- | 497 | } |
|
- | 498 | ||
- | 499 | if (intel_crtc->plane_config.size > max_size) { |
|
- | 500 | DRM_DEBUG_KMS("found possible fb from plane %c\n", |
|
- | 501 | pipe_name(intel_crtc->pipe)); |
|
- | 502 | plane_config = &intel_crtc->plane_config; |
|
- | 503 | fb = to_intel_framebuffer(crtc->primary->fb); |
|
- | 504 | max_size = plane_config->size; |
|
- | 505 | } |
|
- | 506 | } |
|
- | 507 | ||
- | 508 | if (!fb) { |
|
- | 509 | DRM_DEBUG_KMS("no active fbs found, not using BIOS config\n"); |
|
- | 510 | goto out; |
|
- | 511 | } |
|
- | 512 | ||
- | 513 | /* Now make sure all the pipes will fit into it */ |
|
- | 514 | for_each_crtc(dev, crtc) { |
|
- | 515 | unsigned int cur_size; |
|
- | 516 | ||
- | 517 | intel_crtc = to_intel_crtc(crtc); |
|
- | 518 | ||
- | 519 | if (!intel_crtc->active) { |
|
- | 520 | DRM_DEBUG_KMS("pipe %c not active, skipping\n", |
|
- | 521 | pipe_name(intel_crtc->pipe)); |
|
- | 522 | continue; |
|
- | 523 | } |
|
- | 524 | ||
- | 525 | DRM_DEBUG_KMS("checking plane %c for BIOS fb\n", |
|
- | 526 | pipe_name(intel_crtc->pipe)); |
|
- | 527 | ||
- | 528 | /* |
|
- | 529 | * See if the plane fb we found above will fit on this |
|
- | 530 | * pipe. Note we need to use the selected fb's pitch and bpp |
|
- | 531 | * rather than the current pipe's, since they differ. |
|
- | 532 | */ |
|
- | 533 | cur_size = intel_crtc->config.adjusted_mode.crtc_hdisplay; |
|
- | 534 | cur_size = cur_size * fb->base.bits_per_pixel / 8; |
|
- | 535 | if (fb->base.pitches[0] < cur_size) { |
|
- | 536 | DRM_DEBUG_KMS("fb not wide enough for plane %c (%d vs %d)\n", |
|
- | 537 | pipe_name(intel_crtc->pipe), |
|
- | 538 | cur_size, fb->base.pitches[0]); |
|
- | 539 | plane_config = NULL; |
|
- | 540 | fb = NULL; |
|
- | 541 | break; |
|
- | 542 | } |
|
- | 543 | ||
- | 544 | cur_size = intel_crtc->config.adjusted_mode.crtc_vdisplay; |
|
- | 545 | cur_size = ALIGN(cur_size, plane_config->tiled ? (IS_GEN2(dev) ? 16 : 8) : 1); |
|
- | 546 | cur_size *= fb->base.pitches[0]; |
|
- | 547 | DRM_DEBUG_KMS("pipe %c area: %dx%d, bpp: %d, size: %d\n", |
|
- | 548 | pipe_name(intel_crtc->pipe), |
|
- | 549 | intel_crtc->config.adjusted_mode.crtc_hdisplay, |
|
- | 550 | intel_crtc->config.adjusted_mode.crtc_vdisplay, |
|
- | 551 | fb->base.bits_per_pixel, |
|
- | 552 | cur_size); |
|
- | 553 | ||
- | 554 | if (cur_size > max_size) { |
|
- | 555 | DRM_DEBUG_KMS("fb not big enough for plane %c (%d vs %d)\n", |
|
- | 556 | pipe_name(intel_crtc->pipe), |
|
- | 557 | cur_size, max_size); |
|
- | 558 | plane_config = NULL; |
|
- | 559 | fb = NULL; |
|
- | 560 | break; |
|
- | 561 | } |
|
- | 562 | ||
- | 563 | DRM_DEBUG_KMS("fb big enough for plane %c (%d >= %d)\n", |
|
- | 564 | pipe_name(intel_crtc->pipe), |
|
- | 565 | max_size, cur_size); |
|
- | 566 | } |
|
- | 567 | ||
- | 568 | if (!fb) { |
|
- | 569 | DRM_DEBUG_KMS("BIOS fb not suitable for all pipes, not using\n"); |
|
- | 570 | goto out; |
|
- | 571 | } |
|
- | 572 | ||
- | 573 | ifbdev->preferred_bpp = fb->base.bits_per_pixel; |
|
- | 574 | ifbdev->fb = fb; |
|
- | 575 | ||
- | 576 | drm_framebuffer_reference(&ifbdev->fb->base); |
|
- | 577 | ||
- | 578 | /* Final pass to check if any active pipes don't have fbs */ |
|
- | 579 | for_each_crtc(dev, crtc) { |
|
- | 580 | intel_crtc = to_intel_crtc(crtc); |
|
- | 581 | ||
- | 582 | if (!intel_crtc->active) |
|
- | 583 | continue; |
|
- | 584 | ||
- | 585 | WARN(!crtc->primary->fb, |
|
- | 586 | "re-used BIOS config but lost an fb on crtc %d\n", |
|
- | 587 | crtc->base.id); |
|
- | 588 | } |
|
- | 589 | ||
- | 590 | ||
- | 591 | DRM_DEBUG_KMS("using BIOS fb for initial console\n"); |
|
- | 592 | return true; |
|
- | 593 | ||
- | 594 | out: |
|
- | 595 | ||
Line 250... | Line 596... | ||
250 | }; |
596 | return false; |
251 | 597 | } |
|
252 | 598 | ||
253 | int intel_fbdev_init(struct drm_device *dev) |
599 | int intel_fbdev_init(struct drm_device *dev) |
254 | { |
600 | { |
Line -... | Line 601... | ||
- | 601 | struct intel_fbdev *ifbdev; |
|
- | 602 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 603 | int ret; |
|
255 | struct intel_fbdev *ifbdev; |
604 | |
256 | struct drm_i915_private *dev_priv = dev->dev_private; |
605 | if (WARN_ON(INTEL_INFO(dev)->num_pipes == 0)) |
257 | int ret; |
606 | return -ENODEV; |
Line -... | Line 607... | ||
- | 607 | ||
- | 608 | ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL); |
|
258 | 609 | if (ifbdev == NULL) |
|
259 | ifbdev = kzalloc(sizeof(*ifbdev), GFP_KERNEL); |
610 | return -ENOMEM; |
Line 260... | Line 611... | ||
260 | if (!ifbdev) |
611 | |
261 | return -ENOMEM; |
612 | drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs); |
262 | - | ||
263 | dev_priv->fbdev = ifbdev; |
613 | |
264 | ifbdev->helper.funcs = &intel_fb_helper_funcs; |
614 | if (!intel_fbdev_init_bios(dev, ifbdev)) |
265 | 615 | ifbdev->preferred_bpp = 32; |
|
266 | ret = drm_fb_helper_init(dev, &ifbdev->helper, |
616 | |
Line -... | Line 617... | ||
- | 617 | ret = drm_fb_helper_init(dev, &ifbdev->helper, |
|
267 | INTEL_INFO(dev)->num_pipes, |
618 | INTEL_INFO(dev)->num_pipes, 4); |
Line 268... | Line 619... | ||
268 | 4); |
619 | if (ret) { |
269 | if (ret) { |
620 | kfree(ifbdev); |
Line 270... | Line 621... | ||
270 | kfree(ifbdev); |
621 | return ret; |
271 | return ret; |
622 | } |
272 | } |
623 | |
- | 624 | dev_priv->fbdev = ifbdev; |
|
Line 273... | Line 625... | ||
273 | 625 | drm_fb_helper_single_add_all_connectors(&ifbdev->helper); |
|
274 | drm_fb_helper_single_add_all_connectors(&ifbdev->helper); |
626 | |
275 | 627 | return 0; |
|
Line 276... | Line 628... | ||
276 | return 0; |
628 | } |
277 | } |
629 | |
278 | 630 | void intel_fbdev_initial_config(struct drm_device *dev) |
|
- | 631 | { |
|
279 | void intel_fbdev_initial_config(struct drm_device *dev) |
632 | struct drm_i915_private *dev_priv = dev->dev_private; |
280 | { |
633 | struct intel_fbdev *ifbdev = dev_priv->fbdev; |