Rev 4126 | Rev 5060 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4126 | Rev 4560 | ||
---|---|---|---|
Line 37... | Line 37... | ||
37 | #include |
37 | #include |
38 | #include |
38 | #include |
39 | #include |
39 | #include |
40 | #include |
40 | #include |
Line -... | Line 41... | ||
- | 41 | ||
- | 42 | MODULE_AUTHOR("David Airlie, Jesse Barnes"); |
|
- | 43 | MODULE_DESCRIPTION("DRM KMS helper"); |
|
- | 44 | MODULE_LICENSE("GPL and additional rights"); |
|
41 | 45 | ||
42 | /** |
46 | /** |
43 | * drm_helper_move_panel_connectors_to_head() - move panels to the front in the |
47 | * drm_helper_move_panel_connectors_to_head() - move panels to the front in the |
44 | * connector list |
48 | * connector list |
45 | * @dev: drm device to operate on |
49 | * @dev: drm device to operate on |
Line 74... | Line 78... | ||
74 | static void drm_mode_validate_flag(struct drm_connector *connector, |
78 | static void drm_mode_validate_flag(struct drm_connector *connector, |
75 | int flags) |
79 | int flags) |
76 | { |
80 | { |
77 | struct drm_display_mode *mode; |
81 | struct drm_display_mode *mode; |
Line 78... | Line 82... | ||
78 | 82 | ||
- | 83 | if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE | |
|
79 | if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE)) |
84 | DRM_MODE_FLAG_3D_MASK)) |
Line 80... | Line 85... | ||
80 | return; |
85 | return; |
81 | 86 | ||
82 | list_for_each_entry(mode, &connector->modes, head) { |
87 | list_for_each_entry(mode, &connector->modes, head) { |
83 | if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && |
88 | if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && |
84 | !(flags & DRM_MODE_FLAG_INTERLACE)) |
89 | !(flags & DRM_MODE_FLAG_INTERLACE)) |
85 | mode->status = MODE_NO_INTERLACE; |
90 | mode->status = MODE_NO_INTERLACE; |
86 | if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) && |
91 | if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) && |
- | 92 | !(flags & DRM_MODE_FLAG_DBLSCAN)) |
|
- | 93 | mode->status = MODE_NO_DBLESCAN; |
|
- | 94 | if ((mode->flags & DRM_MODE_FLAG_3D_MASK) && |
|
87 | !(flags & DRM_MODE_FLAG_DBLSCAN)) |
95 | !(flags & DRM_MODE_FLAG_3D_MASK)) |
Line 88... | Line 96... | ||
88 | mode->status = MODE_NO_DBLESCAN; |
96 | mode->status = MODE_NO_STEREO; |
89 | } |
97 | } |
Line 103... | Line 111... | ||
103 | * Based on the helper callbacks implemented by @connector try to detect all |
111 | * Based on the helper callbacks implemented by @connector try to detect all |
104 | * valid modes. Modes will first be added to the connector's probed_modes list, |
112 | * valid modes. Modes will first be added to the connector's probed_modes list, |
105 | * then culled (based on validity and the @maxX, @maxY parameters) and put into |
113 | * then culled (based on validity and the @maxX, @maxY parameters) and put into |
106 | * the normal modes list. |
114 | * the normal modes list. |
107 | * |
115 | * |
108 | * Intended to be use as a generic implementation of the ->probe() @connector |
116 | * Intended to be use as a generic implementation of the ->fill_modes() |
109 | * callback for drivers that use the crtc helpers for output mode filtering and |
117 | * @connector vfunc for drivers that use the crtc helpers for output mode |
110 | * detection. |
118 | * filtering and detection. |
111 | * |
119 | * |
112 | * RETURNS: |
120 | * RETURNS: |
113 | * Number of modes found on @connector. |
121 | * Number of modes found on @connector. |
114 | */ |
122 | */ |
115 | int drm_helper_probe_single_connector_modes(struct drm_connector *connector, |
123 | int drm_helper_probe_single_connector_modes(struct drm_connector *connector, |
Line 173... | Line 181... | ||
173 | 181 | ||
174 | if (connector->interlace_allowed) |
182 | if (connector->interlace_allowed) |
175 | mode_flags |= DRM_MODE_FLAG_INTERLACE; |
183 | mode_flags |= DRM_MODE_FLAG_INTERLACE; |
176 | if (connector->doublescan_allowed) |
184 | if (connector->doublescan_allowed) |
- | 185 | mode_flags |= DRM_MODE_FLAG_DBLSCAN; |
|
- | 186 | if (connector->stereo_allowed) |
|
177 | mode_flags |= DRM_MODE_FLAG_DBLSCAN; |
187 | mode_flags |= DRM_MODE_FLAG_3D_MASK; |
Line 178... | Line 188... | ||
178 | drm_mode_validate_flag(connector, mode_flags); |
188 | drm_mode_validate_flag(connector, mode_flags); |
179 | 189 | ||
180 | list_for_each_entry(mode, &connector->modes, head) { |
190 | list_for_each_entry(mode, &connector->modes, head) { |
Line 312... | Line 322... | ||
312 | } |
322 | } |
313 | } |
323 | } |
314 | } |
324 | } |
315 | EXPORT_SYMBOL(drm_helper_disable_unused_functions); |
325 | EXPORT_SYMBOL(drm_helper_disable_unused_functions); |
Line 316... | Line -... | ||
316 | - | ||
317 | /** |
- | |
318 | * drm_encoder_crtc_ok - can a given crtc drive a given encoder? |
- | |
319 | * @encoder: encoder to test |
- | |
320 | * @crtc: crtc to test |
- | |
321 | * |
- | |
322 | * Return false if @encoder can't be driven by @crtc, true otherwise. |
- | |
323 | */ |
- | |
324 | static bool drm_encoder_crtc_ok(struct drm_encoder *encoder, |
- | |
325 | struct drm_crtc *crtc) |
- | |
326 | { |
- | |
327 | struct drm_device *dev; |
- | |
328 | struct drm_crtc *tmp; |
- | |
329 | int crtc_mask = 1; |
- | |
330 | - | ||
331 | WARN(!crtc, "checking null crtc?\n"); |
- | |
332 | - | ||
333 | dev = crtc->dev; |
- | |
334 | - | ||
335 | list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) { |
- | |
336 | if (tmp == crtc) |
- | |
337 | break; |
- | |
338 | crtc_mask <<= 1; |
- | |
339 | } |
- | |
340 | - | ||
341 | if (encoder->possible_crtcs & crtc_mask) |
- | |
342 | return true; |
- | |
343 | return false; |
- | |
344 | } |
- | |
345 | 326 | ||
346 | /* |
327 | /* |
347 | * Check the CRTC we're going to map each output to vs. its current |
328 | * Check the CRTC we're going to map each output to vs. its current |
348 | * CRTC. If they don't match, we have to disable the output and the CRTC |
329 | * CRTC. If they don't match, we have to disable the output and the CRTC |
349 | * since the driver will have to re-route things. |
330 | * since the driver will have to re-route things. |
Line 393... | Line 374... | ||
393 | struct drm_display_mode *mode, |
374 | struct drm_display_mode *mode, |
394 | int x, int y, |
375 | int x, int y, |
395 | struct drm_framebuffer *old_fb) |
376 | struct drm_framebuffer *old_fb) |
396 | { |
377 | { |
397 | struct drm_device *dev = crtc->dev; |
378 | struct drm_device *dev = crtc->dev; |
398 | struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode; |
379 | struct drm_display_mode *adjusted_mode, saved_mode; |
399 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
380 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
400 | struct drm_encoder_helper_funcs *encoder_funcs; |
381 | struct drm_encoder_helper_funcs *encoder_funcs; |
401 | int saved_x, saved_y; |
382 | int saved_x, saved_y; |
- | 383 | bool saved_enabled; |
|
402 | struct drm_encoder *encoder; |
384 | struct drm_encoder *encoder; |
403 | bool ret = true; |
385 | bool ret = true; |
Line -... | Line 386... | ||
- | 386 | ||
404 | 387 | saved_enabled = crtc->enabled; |
|
405 | crtc->enabled = drm_helper_crtc_in_use(crtc); |
388 | crtc->enabled = drm_helper_crtc_in_use(crtc); |
406 | if (!crtc->enabled) |
389 | if (!crtc->enabled) |
Line 407... | Line 390... | ||
407 | return true; |
390 | return true; |
408 | 391 | ||
- | 392 | adjusted_mode = drm_mode_duplicate(dev, mode); |
|
409 | adjusted_mode = drm_mode_duplicate(dev, mode); |
393 | if (!adjusted_mode) { |
- | 394 | crtc->enabled = saved_enabled; |
|
Line 410... | Line -... | ||
410 | if (!adjusted_mode) |
- | |
411 | return false; |
395 | return false; |
412 | 396 | } |
|
413 | saved_hwmode = crtc->hwmode; |
397 | |
Line 414... | Line 398... | ||
414 | saved_mode = crtc->mode; |
398 | saved_mode = crtc->mode; |
Line 521... | Line 505... | ||
521 | 505 | ||
522 | /* Calculate and store various constants which |
506 | /* Calculate and store various constants which |
523 | * are later needed by vblank and swap-completion |
507 | * are later needed by vblank and swap-completion |
524 | * timestamping. They are derived from true hwmode. |
508 | * timestamping. They are derived from true hwmode. |
525 | */ |
509 | */ |
Line 526... | Line 510... | ||
526 | drm_calc_timestamping_constants(crtc); |
510 | drm_calc_timestamping_constants(crtc, &crtc->hwmode); |
527 | 511 | ||
528 | /* FIXME: add subpixel order */ |
512 | /* FIXME: add subpixel order */ |
529 | done: |
513 | done: |
530 | drm_mode_destroy(dev, adjusted_mode); |
514 | drm_mode_destroy(dev, adjusted_mode); |
531 | if (!ret) { |
515 | if (!ret) { |
532 | crtc->hwmode = saved_hwmode; |
516 | crtc->enabled = saved_enabled; |
533 | crtc->mode = saved_mode; |
517 | crtc->mode = saved_mode; |
534 | crtc->x = saved_x; |
518 | crtc->x = saved_x; |
Line 555... | Line 539... | ||
555 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
539 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
556 | if (connector->encoder != encoder) |
540 | if (connector->encoder != encoder) |
557 | continue; |
541 | continue; |
Line 558... | Line 542... | ||
558 | 542 | ||
- | 543 | connector->encoder = NULL; |
|
- | 544 | ||
- | 545 | /* |
|
- | 546 | * drm_helper_disable_unused_functions() ought to be |
|
- | 547 | * doing this, but since we've decoupled the encoder |
|
- | 548 | * from the connector above, the required connection |
|
- | 549 | * between them is henceforth no longer available. |
|
- | 550 | */ |
|
559 | connector->encoder = NULL; |
551 | connector->dpms = DRM_MODE_DPMS_OFF; |
560 | } |
552 | } |
Line 561... | Line 553... | ||
561 | } |
553 | } |
562 | 554 | ||
Line 581... | Line 573... | ||
581 | * Returns 0 on success, -ERRNO on failure. |
573 | * Returns 0 on success, -ERRNO on failure. |
582 | */ |
574 | */ |
583 | int drm_crtc_helper_set_config(struct drm_mode_set *set) |
575 | int drm_crtc_helper_set_config(struct drm_mode_set *set) |
584 | { |
576 | { |
585 | struct drm_device *dev; |
577 | struct drm_device *dev; |
586 | struct drm_crtc *save_crtcs, *new_crtc, *crtc; |
578 | struct drm_crtc *new_crtc; |
587 | struct drm_encoder *save_encoders, *new_encoder, *encoder; |
579 | struct drm_encoder *save_encoders, *new_encoder, *encoder; |
588 | struct drm_framebuffer *old_fb = NULL; |
- | |
589 | bool mode_changed = false; /* if true do a full mode set */ |
580 | bool mode_changed = false; /* if true do a full mode set */ |
590 | bool fb_changed = false; /* if true and !mode_changed just do a flip */ |
581 | bool fb_changed = false; /* if true and !mode_changed just do a flip */ |
591 | struct drm_connector *save_connectors, *connector; |
582 | struct drm_connector *save_connectors, *connector; |
592 | int count = 0, ro, fail = 0; |
583 | int count = 0, ro, fail = 0; |
593 | struct drm_crtc_helper_funcs *crtc_funcs; |
584 | struct drm_crtc_helper_funcs *crtc_funcs; |
Line 619... | Line 610... | ||
619 | return drm_crtc_helper_disable(set->crtc); |
610 | return drm_crtc_helper_disable(set->crtc); |
620 | } |
611 | } |
Line 621... | Line 612... | ||
621 | 612 | ||
Line -... | Line 613... | ||
- | 613 | dev = set->crtc->dev; |
|
622 | dev = set->crtc->dev; |
614 | |
623 | 615 | /* |
|
624 | /* Allocate space for the backup of all (non-pointer) crtc, encoder and |
- | |
625 | * connector data. */ |
- | |
626 | save_crtcs = kzalloc(dev->mode_config.num_crtc * |
- | |
627 | sizeof(struct drm_crtc), GFP_KERNEL); |
- | |
628 | if (!save_crtcs) |
616 | * Allocate space for the backup of all (non-pointer) encoder and |
629 | return -ENOMEM; |
617 | * connector data. |
630 | 618 | */ |
|
631 | save_encoders = kzalloc(dev->mode_config.num_encoder * |
619 | save_encoders = kzalloc(dev->mode_config.num_encoder * |
632 | sizeof(struct drm_encoder), GFP_KERNEL); |
- | |
633 | if (!save_encoders) { |
620 | sizeof(struct drm_encoder), GFP_KERNEL); |
634 | kfree(save_crtcs); |
- | |
Line 635... | Line 621... | ||
635 | return -ENOMEM; |
621 | if (!save_encoders) |
636 | } |
622 | return -ENOMEM; |
637 | 623 | ||
638 | save_connectors = kzalloc(dev->mode_config.num_connector * |
- | |
639 | sizeof(struct drm_connector), GFP_KERNEL); |
624 | save_connectors = kzalloc(dev->mode_config.num_connector * |
640 | if (!save_connectors) { |
625 | sizeof(struct drm_connector), GFP_KERNEL); |
641 | kfree(save_crtcs); |
626 | if (!save_connectors) { |
Line -... | Line 627... | ||
- | 627 | kfree(save_encoders); |
|
642 | kfree(save_encoders); |
628 | return -ENOMEM; |
643 | return -ENOMEM; |
629 | } |
644 | } |
630 | |
645 | 631 | /* |
|
646 | /* Copy data. Note that driver private data is not affected. |
632 | * Copy data. Note that driver private data is not affected. |
647 | * Should anything bad happen only the expected state is |
- | |
648 | * restored, not the drivers personal bookkeeping. |
- | |
649 | */ |
- | |