Rev 5060 | Rev 5367 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5060 | Rev 5354 | ||
---|---|---|---|
Line 22... | Line 22... | ||
22 | * |
22 | * |
23 | * Authors: |
23 | * Authors: |
24 | * David Airlie |
24 | * David Airlie |
25 | */ |
25 | */ |
Line -... | Line 26... | ||
- | 26 | ||
26 | 27 | #include |
|
27 | #include |
28 | #include |
28 | #include |
29 | #include |
29 | #include |
30 | #include |
30 | #include |
31 | #include |
31 | //#include |
32 | //#include |
32 | //#include |
33 | //#include |
33 | #include |
34 | #include |
34 | //#include |
35 | #include |
35 | #include |
36 | #include |
36 | //#include |
37 | //#include |
Line 37... | Line 38... | ||
37 | //#include |
38 | //#include |
Line 68... | Line 69... | ||
68 | return info; |
69 | return info; |
69 | #undef PADDING |
70 | #undef PADDING |
70 | #undef BYTES_PER_LONG |
71 | #undef BYTES_PER_LONG |
71 | } |
72 | } |
Line -... | Line 73... | ||
- | 73 | ||
- | 74 | static int intel_fbdev_set_par(struct fb_info *info) |
|
- | 75 | { |
|
- | 76 | struct drm_fb_helper *fb_helper = info->par; |
|
- | 77 | struct intel_fbdev *ifbdev = |
|
- | 78 | container_of(fb_helper, struct intel_fbdev, helper); |
|
- | 79 | int ret; |
|
- | 80 | ||
- | 81 | ret = drm_fb_helper_set_par(info); |
|
- | 82 | ||
- | 83 | if (ret == 0) { |
|
- | 84 | /* |
|
- | 85 | * FIXME: fbdev presumes that all callbacks also work from |
|
- | 86 | * atomic contexts and relies on that for emergency oops |
|
- | 87 | * printing. KMS totally doesn't do that and the locking here is |
|
- | 88 | * by far not the only place this goes wrong. Ignore this for |
|
- | 89 | * now until we solve this for real. |
|
- | 90 | */ |
|
- | 91 | mutex_lock(&fb_helper->dev->struct_mutex); |
|
- | 92 | ret = i915_gem_object_set_to_gtt_domain(ifbdev->fb->obj, |
|
- | 93 | true); |
|
- | 94 | mutex_unlock(&fb_helper->dev->struct_mutex); |
|
- | 95 | } |
|
- | 96 | ||
- | 97 | return ret; |
|
Line 72... | Line 98... | ||
72 | 98 | } |
|
73 | 99 | ||
74 | static struct fb_ops intelfb_ops = { |
100 | static struct fb_ops intelfb_ops = { |
75 | .owner = THIS_MODULE, |
101 | .owner = THIS_MODULE, |
76 | .fb_check_var = drm_fb_helper_check_var, |
102 | .fb_check_var = drm_fb_helper_check_var, |
77 | .fb_set_par = drm_fb_helper_set_par, |
103 | .fb_set_par = intel_fbdev_set_par, |
78 | // .fb_fillrect = cfb_fillrect, |
104 | // .fb_fillrect = cfb_fillrect, |
79 | // .fb_copyarea = cfb_copyarea, |
105 | // .fb_copyarea = cfb_copyarea, |
80 | // .fb_imageblit = cfb_imageblit, |
106 | // .fb_imageblit = cfb_imageblit, |
Line 101... | Line 127... | ||
101 | sizes->surface_bpp = 32; |
127 | sizes->surface_bpp = 32; |
Line 102... | Line 128... | ||
102 | 128 | ||
103 | mode_cmd.width = sizes->surface_width; |
129 | mode_cmd.width = sizes->surface_width; |
Line 104... | Line 130... | ||
104 | mode_cmd.height = sizes->surface_height; |
130 | mode_cmd.height = sizes->surface_height; |
105 | 131 | ||
106 | mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((sizes->surface_bpp + 7) / |
132 | mode_cmd.pitches[0] = ALIGN(mode_cmd.width * |
107 | 8), 512); |
133 | DIV_ROUND_UP(sizes->surface_bpp, 8), 64); |
Line 108... | Line 134... | ||
108 | mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, |
134 | mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, |
109 | sizes->surface_depth); |
135 | sizes->surface_depth); |
110 | 136 | ||
- | 137 | size = mode_cmd.pitches[0] * mode_cmd.height; |
|
111 | size = mode_cmd.pitches[0] * mode_cmd.height; |
138 | size = ALIGN(size, PAGE_SIZE); |
112 | size = ALIGN(size, PAGE_SIZE); |
139 | obj = main_fb_obj; |
113 | obj = main_fb_obj; |
140 | obj->stride = mode_cmd.pitches[0]; |
114 | if (!obj) { |
141 | if (!obj) { |
115 | DRM_ERROR("failed to allocate framebuffer\n"); |
142 | DRM_ERROR("failed to allocate framebuffer\n"); |
116 | ret = -ENOMEM; |
- | |
117 | goto out; |
- | |
118 | } |
- | |
119 | obj->stride = mode_cmd.pitches[0]; |
- | |
120 | - | ||
121 | /* Flush everything out, we'll be doing GTT only from now on */ |
- | |
122 | ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); |
- | |
123 | if (ret) { |
- | |
Line 124... | Line 143... | ||
124 | DRM_ERROR("failed to pin obj: %d\n", ret); |
143 | ret = -ENOMEM; |
125 | goto out_unref; |
144 | goto out; |
126 | } |
145 | } |
127 | 146 | ||
- | 147 | fb = __intel_framebuffer_create(dev, &mode_cmd, obj); |
|
- | 148 | if (IS_ERR(fb)) { |
|
- | 149 | ret = PTR_ERR(fb); |
|
- | 150 | goto out_unref; |
|
- | 151 | } |
|
- | 152 | ||
- | 153 | /* Flush everything out, we'll be doing GTT only from now on */ |
|
128 | fb = __intel_framebuffer_create(dev, &mode_cmd, obj); |
154 | ret = intel_pin_and_fence_fb_obj(NULL, fb, NULL); |
Line 129... | Line 155... | ||
129 | if (IS_ERR(fb)) { |
155 | if (ret) { |
Line 130... | Line 156... | ||
130 | ret = PTR_ERR(fb); |
156 | DRM_ERROR("failed to pin obj: %d\n", ret); |
Line 131... | Line 157... | ||
131 | goto out_unpin; |
157 | goto out_fb; |
132 | } |
158 | } |
133 | 159 | ||
134 | ifbdev->fb = to_intel_framebuffer(fb); |
160 | ifbdev->fb = to_intel_framebuffer(fb); |
135 | 161 | ||
136 | return 0; |
162 | return 0; |
137 | 163 | ||
Line 300... | Line 326... | ||
300 | * framebuffer anyway. |
326 | * framebuffer anyway. |
301 | */ |
327 | */ |
302 | static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper, |
328 | static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper, |
303 | struct drm_fb_helper_crtc **crtcs, |
329 | struct drm_fb_helper_crtc **crtcs, |
304 | struct drm_display_mode **modes, |
330 | struct drm_display_mode **modes, |
- | 331 | struct drm_fb_offset *offsets, |
|
305 | bool *enabled, int width, int height) |
332 | bool *enabled, int width, int height) |
306 | { |
333 | { |
307 | struct drm_device *dev = fb_helper->dev; |
334 | struct drm_device *dev = fb_helper->dev; |
308 | int i, j; |
335 | int i, j; |
309 | bool *save_enabled; |
336 | bool *save_enabled; |
310 | bool fallback = true; |
337 | bool fallback = true; |
311 | int num_connectors_enabled = 0; |
338 | int num_connectors_enabled = 0; |
312 | int num_connectors_detected = 0; |
339 | 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; |
340 | uint64_t conn_configured = 0, mask; |
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; |
341 | int pass = 0; |
330 | } |
- | |
Line 331... | Line 342... | ||
331 | 342 | ||
332 | save_enabled = kcalloc(dev->mode_config.num_connector, sizeof(bool), |
343 | save_enabled = kcalloc(dev->mode_config.num_connector, sizeof(bool), |
333 | GFP_KERNEL); |
344 | GFP_KERNEL); |
334 | if (!save_enabled) |
345 | if (!save_enabled) |
Line 335... | Line 346... | ||
335 | return false; |
346 | return false; |
- | 347 | ||
336 | 348 | memcpy(save_enabled, enabled, dev->mode_config.num_connector); |
|
337 | memcpy(save_enabled, enabled, dev->mode_config.num_connector); |
349 | mask = (1 << fb_helper->connector_count) - 1; |
338 | 350 | retry: |
|
339 | for (i = 0; i < fb_helper->connector_count; i++) { |
351 | for (i = 0; i < fb_helper->connector_count; i++) { |
340 | struct drm_fb_helper_connector *fb_conn; |
352 | struct drm_fb_helper_connector *fb_conn; |
341 | struct drm_connector *connector; |
353 | struct drm_connector *connector; |
Line 342... | Line 354... | ||
342 | struct drm_encoder *encoder; |
354 | struct drm_encoder *encoder; |
343 | struct drm_fb_helper_crtc *new_crtc; |
355 | struct drm_fb_helper_crtc *new_crtc; |
Line -... | Line 356... | ||
- | 356 | ||
- | 357 | fb_conn = fb_helper->connector_info[i]; |
|
- | 358 | connector = fb_conn->connector; |
|
- | 359 | ||
- | 360 | if (conn_configured & (1 << i)) |
|
- | 361 | continue; |
|
344 | 362 | ||
345 | fb_conn = fb_helper->connector_info[i]; |
363 | if (pass == 0 && !connector->has_tile) |
Line 346... | Line 364... | ||
346 | connector = fb_conn->connector; |
364 | continue; |
347 | 365 | ||
348 | if (connector->status == connector_status_connected) |
366 | if (connector->status == connector_status_connected) |
- | 367 | num_connectors_detected++; |
|
- | 368 | ||
- | 369 | if (!enabled[i]) { |
|
- | 370 | DRM_DEBUG_KMS("connector %s not enabled, skipping\n", |
|
- | 371 | connector->name); |
|
- | 372 | conn_configured |= (1 << i); |
|
- | 373 | continue; |
|
- | 374 | } |
|
349 | num_connectors_detected++; |
375 | |
350 | 376 | if (connector->force == DRM_FORCE_OFF) { |
|
Line 351... | Line 377... | ||
351 | if (!enabled[i]) { |
377 | DRM_DEBUG_KMS("connector %s is disabled by user, skipping\n", |
352 | DRM_DEBUG_KMS("connector %s not enabled, skipping\n", |
378 | connector->name); |
- | 379 | enabled[i] = false; |
|
- | 380 | continue; |
|
- | 381 | } |
|
353 | connector->name); |
382 | |
354 | continue; |
383 | encoder = connector->encoder; |
355 | } |
384 | if (!encoder || WARN_ON(!encoder->crtc)) { |
- | 385 | if (connector->force > DRM_FORCE_OFF) |
|
356 | 386 | goto bail; |
|
357 | encoder = connector->encoder; |
387 | |
Line 358... | Line 388... | ||
358 | if (!encoder || WARN_ON(!encoder->crtc)) { |
388 | DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n", |
Line 372... | Line 402... | ||
372 | * match the BIOS. |
402 | * match the BIOS. |
373 | */ |
403 | */ |
374 | for (j = 0; j < fb_helper->connector_count; j++) { |
404 | for (j = 0; j < fb_helper->connector_count; j++) { |
375 | if (crtcs[j] == new_crtc) { |
405 | if (crtcs[j] == new_crtc) { |
376 | DRM_DEBUG_KMS("fallback: cloned configuration\n"); |
406 | DRM_DEBUG_KMS("fallback: cloned configuration\n"); |
377 | fallback = true; |
- | |
378 | goto out; |
407 | goto bail; |
379 | } |
408 | } |
380 | } |
409 | } |
Line 381... | Line 410... | ||
381 | 410 | ||
382 | DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n", |
411 | DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n", |
Line 385... | Line 414... | ||
385 | /* go for command line mode first */ |
414 | /* go for command line mode first */ |
386 | modes[i] = drm_pick_cmdline_mode(fb_conn, width, height); |
415 | modes[i] = drm_pick_cmdline_mode(fb_conn, width, height); |
Line 387... | Line 416... | ||
387 | 416 | ||
388 | /* try for preferred next */ |
417 | /* try for preferred next */ |
389 | if (!modes[i]) { |
418 | if (!modes[i]) { |
390 | DRM_DEBUG_KMS("looking for preferred mode on connector %s\n", |
419 | DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n", |
391 | connector->name); |
420 | connector->name, connector->has_tile); |
392 | modes[i] = drm_has_preferred_mode(fb_conn, width, |
421 | modes[i] = drm_has_preferred_mode(fb_conn, width, |
393 | height); |
422 | height); |
Line 394... | Line 423... | ||
394 | } |
423 | } |
Line 429... | Line 458... | ||
429 | encoder->crtc->base.id, |
458 | encoder->crtc->base.id, |
430 | modes[i]->hdisplay, modes[i]->vdisplay, |
459 | modes[i]->hdisplay, modes[i]->vdisplay, |
431 | modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" :""); |
460 | modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" :""); |
Line 432... | Line 461... | ||
432 | 461 | ||
- | 462 | fallback = false; |
|
- | 463 | conn_configured |= (1 << i); |
|
- | 464 | } |
|
- | 465 | ||
- | 466 | if ((conn_configured & mask) != mask) { |
|
- | 467 | pass++; |
|
433 | fallback = false; |
468 | goto retry; |
Line 434... | Line 469... | ||
434 | } |
469 | } |
435 | 470 | ||
436 | /* |
471 | /* |
Line 444... | Line 479... | ||
444 | DRM_DEBUG_KMS("Enabled: %i, detected: %i\n", num_connectors_enabled, |
479 | DRM_DEBUG_KMS("Enabled: %i, detected: %i\n", num_connectors_enabled, |
445 | num_connectors_detected); |
480 | num_connectors_detected); |
446 | fallback = true; |
481 | fallback = true; |
447 | } |
482 | } |
Line 448... | Line -... | ||
448 | - | ||
449 | out: |
483 | |
- | 484 | if (fallback) { |
|
450 | if (fallback) { |
485 | bail: |
451 | DRM_DEBUG_KMS("Not using firmware configuration\n"); |
486 | DRM_DEBUG_KMS("Not using firmware configuration\n"); |
452 | memcpy(enabled, save_enabled, dev->mode_config.num_connector); |
487 | memcpy(enabled, save_enabled, dev->mode_config.num_connector); |
453 | kfree(save_enabled); |
488 | kfree(save_enabled); |
454 | return false; |
489 | return false; |
Line 625... | Line 660... | ||
625 | drm_fb_helper_single_add_all_connectors(&ifbdev->helper); |
660 | drm_fb_helper_single_add_all_connectors(&ifbdev->helper); |
Line 626... | Line 661... | ||
626 | 661 | ||
627 | return 0; |
662 | return 0; |
Line 628... | Line 663... | ||
628 | } |
663 | } |
629 | 664 | ||
630 | void intel_fbdev_initial_config(struct drm_device *dev) |
665 | void intel_fbdev_initial_config(void *data, async_cookie_t cookie) |
631 | { |
666 | { |
Line 632... | Line 667... | ||
632 | struct drm_i915_private *dev_priv = dev->dev_private; |
667 | struct drm_i915_private *dev_priv = data; |
633 | struct intel_fbdev *ifbdev = dev_priv->fbdev; |
668 | struct intel_fbdev *ifbdev = dev_priv->fbdev; |
634 | 669 |