Rev 3031 | Rev 3243 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3031 | Rev 3192 | ||
---|---|---|---|
Line 25... | Line 25... | ||
25 | * |
25 | * |
26 | * Authors: |
26 | * Authors: |
27 | * Dave Airlie |
27 | * Dave Airlie |
28 | * Jesse Barnes |
28 | * Jesse Barnes |
29 | */ |
29 | */ |
- | 30 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|
- | 31 | ||
30 | #include |
32 | #include |
31 | #include |
33 | #include |
32 | #include |
34 | #include |
33 | #include |
35 | #include |
34 | #include |
36 | #include |
Line 41... | Line 43... | ||
41 | MODULE_DESCRIPTION("DRM KMS helper"); |
43 | MODULE_DESCRIPTION("DRM KMS helper"); |
42 | MODULE_LICENSE("GPL and additional rights"); |
44 | MODULE_LICENSE("GPL and additional rights"); |
Line 43... | Line 45... | ||
43 | 45 | ||
Line -... | Line 46... | ||
- | 46 | static LIST_HEAD(kernel_fb_helper_list); |
|
- | 47 | ||
- | 48 | /** |
|
- | 49 | * DOC: fbdev helpers |
|
- | 50 | * |
|
- | 51 | * The fb helper functions are useful to provide an fbdev on top of a drm kernel |
|
- | 52 | * mode setting driver. They can be used mostly independantely from the crtc |
|
- | 53 | * helper functions used by many drivers to implement the kernel mode setting |
|
- | 54 | * interfaces. |
|
44 | static LIST_HEAD(kernel_fb_helper_list); |
55 | */ |
45 | 56 | ||
46 | /* simple single crtc case helper function */ |
57 | /* simple single crtc case helper function */ |
47 | int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) |
58 | int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) |
48 | { |
59 | { |
49 | struct drm_device *dev = fb_helper->dev; |
60 | struct drm_device *dev = fb_helper->dev; |
Line -... | Line 61... | ||
- | 61 | struct drm_connector *connector; |
|
- | 62 | int i; |
|
50 | struct drm_connector *connector; |
63 | |
51 | int i; |
64 | ENTER(); |
Line 52... | Line 65... | ||
52 | 65 | ||
53 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
66 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
54 | struct drm_fb_helper_connector *fb_helper_connector; |
67 | struct drm_fb_helper_connector *fb_helper_connector; |
Line 55... | Line 68... | ||
55 | 68 | ||
56 | fb_helper_connector = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL); |
69 | fb_helper_connector = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL); |
57 | if (!fb_helper_connector) |
70 | if (!fb_helper_connector) |
- | 71 | goto fail; |
|
58 | goto fail; |
72 | |
59 | 73 | fb_helper_connector->connector = connector; |
|
60 | fb_helper_connector->connector = connector; |
74 | fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector; |
61 | fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector; |
75 | } |
62 | } |
76 | LEAVE(); |
63 | return 0; |
77 | return 0; |
64 | fail: |
78 | fail: |
- | 79 | for (i = 0; i < fb_helper->connector_count; i++) { |
|
65 | for (i = 0; i < fb_helper->connector_count; i++) { |
80 | kfree(fb_helper->connector_info[i]); |
66 | kfree(fb_helper->connector_info[i]); |
81 | fb_helper->connector_info[i] = NULL; |
67 | fb_helper->connector_info[i] = NULL; |
82 | } |
Line 68... | Line 83... | ||
68 | } |
83 | fb_helper->connector_count = 0; |
Line 120... | Line 135... | ||
120 | 135 | ||
121 | /* Walk the connectors & encoders on this fb turning them on/off */ |
136 | /* Walk the connectors & encoders on this fb turning them on/off */ |
122 | for (j = 0; j < fb_helper->connector_count; j++) { |
137 | for (j = 0; j < fb_helper->connector_count; j++) { |
123 | connector = fb_helper->connector_info[j]->connector; |
138 | connector = fb_helper->connector_info[j]->connector; |
124 | connector->funcs->dpms(connector, dpms_mode); |
139 | connector->funcs->dpms(connector, dpms_mode); |
125 | drm_connector_property_set_value(connector, |
140 | drm_object_property_set_value(&connector->base, |
126 | dev->mode_config.dpms_property, dpms_mode); |
141 | dev->mode_config.dpms_property, dpms_mode); |
127 | } |
142 | } |
128 | } |
143 | } |
129 | mutex_unlock(&dev->mode_config.mutex); |
144 | mutex_unlock(&dev->mode_config.mutex); |
Line 177... | Line 192... | ||
177 | int crtc_count, int max_conn_count) |
192 | int crtc_count, int max_conn_count) |
178 | { |
193 | { |
179 | struct drm_crtc *crtc; |
194 | struct drm_crtc *crtc; |
180 | int i; |
195 | int i; |
Line -... | Line 196... | ||
- | 196 | ||
- | 197 | ENTER(); |
|
- | 198 | ||
- | 199 | dbgprintf("crtc_count %d max_conn_count %d\n", crtc_count, max_conn_count); |
|
181 | 200 | ||
Line 182... | Line 201... | ||
182 | fb_helper->dev = dev; |
201 | fb_helper->dev = dev; |
Line 183... | Line 202... | ||
183 | 202 | ||
184 | INIT_LIST_HEAD(&fb_helper->kernel_fb_list); |
203 | INIT_LIST_HEAD(&fb_helper->kernel_fb_list); |
- | 204 | ||
- | 205 | fb_helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL); |
|
185 | 206 | if (!fb_helper->crtc_info) |
|
- | 207 | { |
|
Line 186... | Line 208... | ||
186 | fb_helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL); |
208 | FAIL(); |
187 | if (!fb_helper->crtc_info) |
209 | return -ENOMEM; |
188 | return -ENOMEM; |
210 | }; |
189 | 211 | ||
- | 212 | fb_helper->crtc_count = crtc_count; |
|
190 | fb_helper->crtc_count = crtc_count; |
213 | fb_helper->connector_info = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_fb_helper_connector *), GFP_KERNEL); |
191 | fb_helper->connector_info = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_fb_helper_connector *), GFP_KERNEL); |
214 | if (!fb_helper->connector_info) { |
192 | if (!fb_helper->connector_info) { |
215 | kfree(fb_helper->crtc_info); |
Line 193... | Line 216... | ||
193 | kfree(fb_helper->crtc_info); |
216 | FAIL(); |
Line 210... | Line 233... | ||
210 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
233 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
211 | fb_helper->crtc_info[i].mode_set.crtc = crtc; |
234 | fb_helper->crtc_info[i].mode_set.crtc = crtc; |
212 | i++; |
235 | i++; |
213 | } |
236 | } |
Line -... | Line 237... | ||
- | 237 | ||
214 | 238 | LEAVE(); |
|
215 | return 0; |
239 | return 0; |
216 | out_free: |
240 | out_free: |
- | 241 | drm_fb_helper_crtc_free(fb_helper); |
|
217 | drm_fb_helper_crtc_free(fb_helper); |
242 | FAIL(); |
218 | return -ENOMEM; |
243 | return -ENOMEM; |
219 | } |
244 | } |
Line 220... | Line 245... | ||
220 | EXPORT_SYMBOL(drm_fb_helper_init); |
245 | EXPORT_SYMBOL(drm_fb_helper_init); |
Line 496... | Line 521... | ||
496 | sizes.fb_width = (unsigned)-1; |
521 | sizes.fb_width = (unsigned)-1; |
497 | sizes.fb_height = (unsigned)-1; |
522 | sizes.fb_height = (unsigned)-1; |
Line 498... | Line 523... | ||
498 | 523 | ||
499 | /* if driver picks 8 or 16 by default use that |
524 | /* if driver picks 8 or 16 by default use that |
500 | for both depth/bpp */ |
525 | for both depth/bpp */ |
501 | if (preferred_bpp != sizes.surface_bpp) { |
526 | if (preferred_bpp != sizes.surface_bpp) |
502 | sizes.surface_depth = sizes.surface_bpp = preferred_bpp; |
527 | sizes.surface_depth = sizes.surface_bpp = preferred_bpp; |
503 | } |
528 | |
504 | /* first up get a count of crtcs now in use and new min/maxes width/heights */ |
529 | /* first up get a count of crtcs now in use and new min/maxes width/heights */ |
505 | for (i = 0; i < fb_helper->connector_count; i++) { |
530 | for (i = 0; i < fb_helper->connector_count; i++) { |
506 | struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i]; |
531 | struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i]; |
Line 566... | Line 591... | ||
566 | return new_fb; |
591 | return new_fb; |
Line 567... | Line 592... | ||
567 | 592 | ||
Line 568... | Line 593... | ||
568 | info = fb_helper->fbdev; |
593 | info = fb_helper->fbdev; |
569 | 594 | ||
570 | /* set the fb pointer */ |
595 | /* set the fb pointer */ |
571 | for (i = 0; i < fb_helper->crtc_count; i++) { |
- | |
Line 572... | Line 596... | ||
572 | fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb; |
596 | for (i = 0; i < fb_helper->crtc_count; i++) |
573 | } |
597 | fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb; |
Line 574... | Line 598... | ||
574 | 598 | ||
Line 724... | Line 748... | ||
724 | 748 | ||
725 | static bool drm_connector_enabled(struct drm_connector *connector, bool strict) |
749 | static bool drm_connector_enabled(struct drm_connector *connector, bool strict) |
726 | { |
750 | { |
Line 727... | Line 751... | ||
727 | bool enable; |
751 | bool enable; |
728 | 752 | ||
729 | if (strict) { |
753 | if (strict) |
730 | enable = connector->status == connector_status_connected; |
754 | enable = connector->status == connector_status_connected; |
731 | } else { |
755 | else |
732 | enable = connector->status != connector_status_disconnected; |
756 | enable = connector->status != connector_status_disconnected; |
733 | } |
757 | |
Line 734... | Line 758... | ||
734 | return enable; |
758 | return enable; |
735 | } |
759 | } |
Line 844... | Line 868... | ||
844 | /* select a crtc for this connector and then attempt to configure |
868 | /* select a crtc for this connector and then attempt to configure |
845 | remaining connectors */ |
869 | remaining connectors */ |
846 | for (c = 0; c < fb_helper->crtc_count; c++) { |
870 | for (c = 0; c < fb_helper->crtc_count; c++) { |
847 | crtc = &fb_helper->crtc_info[c]; |
871 | crtc = &fb_helper->crtc_info[c]; |
Line 848... | Line 872... | ||
848 | 872 | ||
849 | if ((encoder->possible_crtcs & (1 << c)) == 0) { |
873 | if ((encoder->possible_crtcs & (1 << c)) == 0) |
850 | continue; |
- | |
Line 851... | Line 874... | ||
851 | } |
874 | continue; |
852 | 875 | ||
853 | for (o = 0; o < n; o++) |
876 | for (o = 0; o < n; o++) |
Line 899... | Line 922... | ||
899 | sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL); |
922 | sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL); |
900 | modes = kcalloc(dev->mode_config.num_connector, |
923 | modes = kcalloc(dev->mode_config.num_connector, |
901 | sizeof(struct drm_display_mode *), GFP_KERNEL); |
924 | sizeof(struct drm_display_mode *), GFP_KERNEL); |
902 | enabled = kcalloc(dev->mode_config.num_connector, |
925 | enabled = kcalloc(dev->mode_config.num_connector, |
903 | sizeof(bool), GFP_KERNEL); |
926 | sizeof(bool), GFP_KERNEL); |
- | 927 | if (!crtcs || !modes || !enabled) { |
|
- | 928 | DRM_ERROR("Memory allocation failed\n"); |
|
- | 929 | goto out; |
|
- | 930 | } |
|
- | 931 | ||
Line 904... | Line 932... | ||
904 | 932 | ||
Line 905... | Line 933... | ||
905 | drm_enable_connectors(fb_helper, enabled); |
933 | drm_enable_connectors(fb_helper, enabled); |
Line 940... | Line 968... | ||
940 | fb_crtc->desired_mode); |
968 | fb_crtc->desired_mode); |
941 | modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector; |
969 | modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector; |
942 | } |
970 | } |
943 | } |
971 | } |
Line -... | Line 972... | ||
- | 972 | ||
944 | 973 | out: |
|
945 | kfree(crtcs); |
974 | kfree(crtcs); |
946 | kfree(modes); |
975 | kfree(modes); |
947 | kfree(enabled); |
976 | kfree(enabled); |
Line 948... | Line 977... | ||
948 | } |
977 | } |
949 | 978 | ||
950 | /** |
979 | /** |
- | 980 | * drm_helper_initial_config - setup a sane initial connector configuration |
|
951 | * drm_helper_initial_config - setup a sane initial connector configuration |
981 | * @fb_helper: fb_helper device struct |
952 | * @dev: DRM device |
982 | * @bpp_sel: bpp value to use for the framebuffer configuration |
- | 983 | * |
|
953 | * |
984 | * LOCKING: |
954 | * LOCKING: |
985 | * Called at init time by the driver to set up the @fb_helper initial |
955 | * Called at init time, must take mode config lock. |
986 | * configuration, must take the mode config lock. |
956 | * |
987 | * |
957 | * Scan the CRTCs and connectors and try to put together an initial setup. |
988 | * Scans the CRTCs and connectors and tries to put together an initial setup. |
958 | * At the moment, this is a cloned configuration across all heads with |
989 | * At the moment, this is a cloned configuration across all heads with |
959 | * a new framebuffer object as the backing store. |
990 | * a new framebuffer object as the backing store. |
960 | * |
991 | * |
961 | * RETURNS: |
992 | * RETURNS: |
962 | * Zero if everything went ok, nonzero otherwise. |
993 | * Zero if everything went ok, nonzero otherwise. |
963 | */ |
994 | */ |
964 | bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) |
995 | bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) |
965 | { |
996 | { |
- | 997 | struct drm_device *dev = fb_helper->dev; |
|
- | 998 | int count = 0; |
|
- | 999 | bool ret; |
|
Line 966... | Line 1000... | ||
966 | struct drm_device *dev = fb_helper->dev; |
1000 | |
967 | int count = 0; |
1001 | ENTER(); |
Line 968... | Line 1002... | ||
968 | 1002 | ||
Line 975... | Line 1009... | ||