Rev 2160 | Rev 3192 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2160 | Rev 3031 | ||
---|---|---|---|
Line 29... | Line 29... | ||
29 | */ |
29 | */ |
30 | #include |
30 | #include |
31 | #include |
31 | #include |
32 | #include |
32 | #include |
33 | #include |
33 | #include |
- | 34 | #include |
|
34 | #include "drmP.h" |
35 | #include |
35 | #include "drm_crtc.h" |
36 | #include |
36 | #include "drm_fb_helper.h" |
37 | #include |
37 | #include "drm_crtc_helper.h" |
38 | #include |
Line 38... | Line 39... | ||
38 | 39 | ||
39 | MODULE_AUTHOR("David Airlie, Jesse Barnes"); |
40 | MODULE_AUTHOR("David Airlie, Jesse Barnes"); |
40 | MODULE_DESCRIPTION("DRM KMS helper"); |
41 | MODULE_DESCRIPTION("DRM KMS helper"); |
Line 85... | Line 86... | ||
85 | 86 | ||
86 | static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc) |
87 | static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc) |
87 | { |
88 | { |
Line -... | Line 89... | ||
- | 89 | uint16_t *r_base, *g_base, *b_base; |
|
- | 90 | ||
- | 91 | if (crtc->funcs->gamma_set == NULL) |
|
88 | uint16_t *r_base, *g_base, *b_base; |
92 | return; |
89 | 93 | ||
90 | r_base = crtc->gamma_store; |
94 | r_base = crtc->gamma_store; |
Line 91... | Line 95... | ||
91 | g_base = r_base + crtc->gamma_size; |
95 | g_base = r_base + crtc->gamma_size; |
92 | b_base = g_base + crtc->gamma_size; |
96 | b_base = g_base + crtc->gamma_size; |
Line 93... | Line -... | ||
93 | - | ||
94 | crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size); |
- | |
95 | } |
- | |
96 | - | ||
97 | - | ||
98 | static void drm_fb_helper_on(struct fb_info *info) |
- | |
99 | { |
- | |
100 | struct drm_fb_helper *fb_helper = info->par; |
- | |
101 | struct drm_device *dev = fb_helper->dev; |
- | |
102 | struct drm_crtc *crtc; |
- | |
103 | struct drm_crtc_helper_funcs *crtc_funcs; |
- | |
104 | struct drm_connector *connector; |
- | |
105 | struct drm_encoder *encoder; |
- | |
106 | int i, j; |
- | |
107 | - | ||
108 | /* |
- | |
109 | * For each CRTC in this fb, turn the crtc on then, |
- | |
110 | * find all associated encoders and turn them on. |
- | |
111 | */ |
- | |
112 | mutex_lock(&dev->mode_config.mutex); |
- | |
113 | for (i = 0; i < fb_helper->crtc_count; i++) { |
- | |
114 | crtc = fb_helper->crtc_info[i].mode_set.crtc; |
- | |
115 | crtc_funcs = crtc->helper_private; |
- | |
116 | - | ||
117 | if (!crtc->enabled) |
- | |
118 | continue; |
- | |
119 | - | ||
120 | crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); |
- | |
121 | - | ||
122 | /* Walk the connectors & encoders on this fb turning them on */ |
- | |
123 | for (j = 0; j < fb_helper->connector_count; j++) { |
- | |
124 | connector = fb_helper->connector_info[j]->connector; |
- | |
125 | connector->dpms = DRM_MODE_DPMS_ON; |
- | |
126 | drm_connector_property_set_value(connector, |
- | |
127 | dev->mode_config.dpms_property, |
- | |
128 | DRM_MODE_DPMS_ON); |
- | |
129 | } |
- | |
130 | /* Found a CRTC on this fb, now find encoders */ |
- | |
131 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
- | |
132 | if (encoder->crtc == crtc) { |
- | |
133 | struct drm_encoder_helper_funcs *encoder_funcs; |
- | |
134 | - | ||
135 | encoder_funcs = encoder->helper_private; |
- | |
136 | encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); |
- | |
Line 137... | Line 97... | ||
137 | } |
97 | |
138 | } |
98 | crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size); |
139 | } |
99 | } |
140 | mutex_unlock(&dev->mode_config.mutex); |
100 | |
141 | } |
101 | |
142 | - | ||
143 | static void drm_fb_helper_off(struct fb_info *info, int dpms_mode) |
102 | |
144 | { |
- | |
145 | struct drm_fb_helper *fb_helper = info->par; |
103 | static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) |
Line 146... | Line 104... | ||
146 | struct drm_device *dev = fb_helper->dev; |
104 | { |
147 | struct drm_crtc *crtc; |
105 | struct drm_fb_helper *fb_helper = info->par; |
148 | struct drm_crtc_helper_funcs *crtc_funcs; |
- | |
149 | struct drm_connector *connector; |
106 | struct drm_device *dev = fb_helper->dev; |
150 | struct drm_encoder *encoder; |
107 | struct drm_crtc *crtc; |
151 | int i, j; |
108 | struct drm_connector *connector; |
152 | 109 | int i, j; |
|
153 | /* |
- | |
Line 154... | Line 110... | ||
154 | * For each CRTC in this fb, find all associated encoders |
110 | |
155 | * and turn them off, then turn off the CRTC. |
111 | /* |
Line 156... | Line 112... | ||
156 | */ |
112 | * For each CRTC in this fb, turn the connectors on/off. |
157 | mutex_lock(&dev->mode_config.mutex); |
113 | */ |
158 | for (i = 0; i < fb_helper->crtc_count; i++) { |
114 | mutex_lock(&dev->mode_config.mutex); |
159 | crtc = fb_helper->crtc_info[i].mode_set.crtc; |
115 | for (i = 0; i < fb_helper->crtc_count; i++) { |
160 | crtc_funcs = crtc->helper_private; |
116 | crtc = fb_helper->crtc_info[i].mode_set.crtc; |
161 | 117 | ||
162 | if (!crtc->enabled) |
- | |
163 | continue; |
- | |
164 | - | ||
165 | /* Walk the connectors on this fb and mark them off */ |
- | |
166 | for (j = 0; j < fb_helper->connector_count; j++) { |
- | |
167 | connector = fb_helper->connector_info[j]->connector; |
- | |
168 | connector->dpms = dpms_mode; |
- | |
169 | drm_connector_property_set_value(connector, |
- | |
170 | dev->mode_config.dpms_property, |
- | |
171 | dpms_mode); |
- | |
172 | } |
118 | if (!crtc->enabled) |
173 | /* Found a CRTC on this fb, now find encoders */ |
- | |
174 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
119 | continue; |
175 | if (encoder->crtc == crtc) { |
120 | |
176 | struct drm_encoder_helper_funcs *encoder_funcs; |
121 | /* Walk the connectors & encoders on this fb turning them on/off */ |
Line 177... | Line 122... | ||
177 | 122 | for (j = 0; j < fb_helper->connector_count; j++) { |
|
178 | encoder_funcs = encoder->helper_private; |
123 | connector = fb_helper->connector_info[j]->connector; |
179 | encoder_funcs->dpms(encoder, dpms_mode); |
124 | connector->funcs->dpms(connector, dpms_mode); |
180 | } |
125 | drm_connector_property_set_value(connector, |
181 | } |
126 | dev->mode_config.dpms_property, dpms_mode); |
182 | crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); |
127 | } |
183 | } |
128 | } |
184 | mutex_unlock(&dev->mode_config.mutex); |
129 | mutex_unlock(&dev->mode_config.mutex); |
185 | } |
130 | } |
186 | 131 | ||
187 | int drm_fb_helper_blank(int blank, struct fb_info *info) |
132 | int drm_fb_helper_blank(int blank, struct fb_info *info) |
188 | { |
133 | { |
189 | switch (blank) { |
134 | switch (blank) { |
190 | /* Display: On; HSync: On, VSync: On */ |
135 | /* Display: On; HSync: On, VSync: On */ |
191 | case FB_BLANK_UNBLANK: |
136 | case FB_BLANK_UNBLANK: |
192 | drm_fb_helper_on(info); |
137 | drm_fb_helper_dpms(info, DRM_MODE_DPMS_ON); |
193 | break; |
138 | break; |
194 | /* Display: Off; HSync: On, VSync: On */ |
139 | /* Display: Off; HSync: On, VSync: On */ |
195 | case FB_BLANK_NORMAL: |
140 | case FB_BLANK_NORMAL: |
196 | drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY); |
141 | drm_fb_helper_dpms(info, DRM_MODE_DPMS_STANDBY); |
197 | break; |
142 | break; |
198 | /* Display: Off; HSync: Off, VSync: On */ |
143 | /* Display: Off; HSync: Off, VSync: On */ |
199 | case FB_BLANK_HSYNC_SUSPEND: |
144 | case FB_BLANK_HSYNC_SUSPEND: |
200 | drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY); |
145 | drm_fb_helper_dpms(info, DRM_MODE_DPMS_STANDBY); |
201 | break; |
146 | break; |
202 | /* Display: Off; HSync: On, VSync: Off */ |
147 | /* Display: Off; HSync: On, VSync: Off */ |
203 | case FB_BLANK_VSYNC_SUSPEND: |
148 | case FB_BLANK_VSYNC_SUSPEND: |
Line 217... | Line 162... | ||
217 | int i; |
162 | int i; |
Line 218... | Line 163... | ||
218 | 163 | ||
219 | for (i = 0; i < helper->connector_count; i++) |
164 | for (i = 0; i < helper->connector_count; i++) |
220 | kfree(helper->connector_info[i]); |
165 | kfree(helper->connector_info[i]); |
221 | kfree(helper->connector_info); |
166 | kfree(helper->connector_info); |
222 | for (i = 0; i < helper->crtc_count; i++) |
167 | for (i = 0; i < helper->crtc_count; i++) { |
- | 168 | kfree(helper->crtc_info[i].mode_set.connectors); |
|
- | 169 | if (helper->crtc_info[i].mode_set.mode) |
|
- | 170 | drm_mode_destroy(helper->dev, helper->crtc_info[i].mode_set.mode); |
|
223 | kfree(helper->crtc_info[i].mode_set.connectors); |
171 | } |
224 | kfree(helper->crtc_info); |
172 | kfree(helper->crtc_info); |
Line 225... | Line 173... | ||
225 | } |
173 | } |
226 | 174 | ||
227 | int drm_fb_helper_init(struct drm_device *dev, |
175 | int drm_fb_helper_init(struct drm_device *dev, |
228 | struct drm_fb_helper *fb_helper, |
176 | struct drm_fb_helper *fb_helper, |
229 | int crtc_count, int max_conn_count) |
177 | int crtc_count, int max_conn_count) |
230 | { |
- | |
231 | struct drm_crtc *crtc; |
178 | { |
Line 232... | Line 179... | ||
232 | int ret = 0; |
179 | struct drm_crtc *crtc; |
Line 233... | Line 180... | ||
233 | int i; |
180 | int i; |
Line 252... | Line 199... | ||
252 | fb_helper->crtc_info[i].mode_set.connectors = |
199 | fb_helper->crtc_info[i].mode_set.connectors = |
253 | kcalloc(max_conn_count, |
200 | kcalloc(max_conn_count, |
254 | sizeof(struct drm_connector *), |
201 | sizeof(struct drm_connector *), |
255 | GFP_KERNEL); |
202 | GFP_KERNEL); |
Line 256... | Line 203... | ||
256 | 203 | ||
257 | if (!fb_helper->crtc_info[i].mode_set.connectors) { |
- | |
258 | ret = -ENOMEM; |
204 | if (!fb_helper->crtc_info[i].mode_set.connectors) |
259 | goto out_free; |
- | |
260 | } |
205 | goto out_free; |
261 | fb_helper->crtc_info[i].mode_set.num_connectors = 0; |
206 | fb_helper->crtc_info[i].mode_set.num_connectors = 0; |
Line 262... | Line 207... | ||
262 | } |
207 | } |
263 | 208 | ||
264 | i = 0; |
- | |
265 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
209 | i = 0; |
266 | fb_helper->crtc_info[i].crtc_id = crtc->base.id; |
210 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
267 | fb_helper->crtc_info[i].mode_set.crtc = crtc; |
211 | fb_helper->crtc_info[i].mode_set.crtc = crtc; |
268 | i++; |
- | |
- | 212 | i++; |
|
269 | } |
213 | } |
270 | fb_helper->conn_limit = max_conn_count; |
214 | |
271 | return 0; |
215 | return 0; |
272 | out_free: |
216 | out_free: |
273 | drm_fb_helper_crtc_free(fb_helper); |
217 | drm_fb_helper_crtc_free(fb_helper); |
Line 387... | Line 331... | ||
387 | 331 | ||
388 | if (var->pixclock != 0 || in_dbg_master()) |
332 | if (var->pixclock != 0 || in_dbg_master()) |
Line 389... | Line 333... | ||
389 | return -EINVAL; |
333 | return -EINVAL; |
- | 334 | ||
- | 335 | /* Need to resize the fb object !!! */ |
|
390 | 336 | if (var->bits_per_pixel > fb->bits_per_pixel || |
|
391 | /* Need to resize the fb object !!! */ |
337 | var->xres > fb->width || var->yres > fb->height || |
- | 338 | var->xres_virtual > fb->width || var->yres_virtual > fb->height) { |
|
392 | if (var->bits_per_pixel > fb->bits_per_pixel || var->xres > fb->width || var->yres > fb->height) { |
339 | DRM_DEBUG("fb userspace requested width/height/bpp is greater than current fb " |
- | 340 | "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n", |
|
393 | DRM_DEBUG("fb userspace requested width/height/bpp is greater than current fb " |
341 | var->xres, var->yres, var->bits_per_pixel, |
394 | "object %dx%d-%d > %dx%d-%d\n", var->xres, var->yres, var->bits_per_pixel, |
342 | var->xres_virtual, var->yres_virtual, |
395 | fb->width, fb->height, fb->bits_per_pixel); |
343 | fb->width, fb->height, fb->bits_per_pixel); |
Line 396... | Line 344... | ||
396 | return -EINVAL; |
344 | return -EINVAL; |
Line 546... | Line 494... | ||
546 | sizes.surface_depth = 24; |
494 | sizes.surface_depth = 24; |
547 | sizes.surface_bpp = 32; |
495 | sizes.surface_bpp = 32; |
548 | sizes.fb_width = (unsigned)-1; |
496 | sizes.fb_width = (unsigned)-1; |
549 | sizes.fb_height = (unsigned)-1; |
497 | sizes.fb_height = (unsigned)-1; |
Line -... | Line 498... | ||
- | 498 | ||
- | 499 | /* if driver picks 8 or 16 by default use that |
|
- | 500 | for both depth/bpp */ |
|
- | 501 | if (preferred_bpp != sizes.surface_bpp) { |
|
- | 502 | sizes.surface_depth = sizes.surface_bpp = preferred_bpp; |
|
- | 503 | } |
|
- | 504 | /* 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++) { |
|
- | 506 | struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i]; |
|
- | 507 | struct drm_cmdline_mode *cmdline_mode; |
|
- | 508 | ||
- | 509 | cmdline_mode = &fb_helper_conn->cmdline_mode; |
|
- | 510 | ||
- | 511 | if (cmdline_mode->bpp_specified) { |
|
- | 512 | switch (cmdline_mode->bpp) { |
|
- | 513 | case 8: |
|
- | 514 | sizes.surface_depth = sizes.surface_bpp = 8; |
|
- | 515 | break; |
|
- | 516 | case 15: |
|
- | 517 | sizes.surface_depth = 15; |
|
- | 518 | sizes.surface_bpp = 16; |
|
- | 519 | break; |
|
- | 520 | case 16: |
|
- | 521 | sizes.surface_depth = sizes.surface_bpp = 16; |
|
- | 522 | break; |
|
- | 523 | case 24: |
|
- | 524 | sizes.surface_depth = sizes.surface_bpp = 24; |
|
- | 525 | break; |
|
550 | 526 | case 32: |
|
551 | sizes.surface_depth = 24; |
527 | sizes.surface_depth = 24; |
- | 528 | sizes.surface_bpp = 32; |
|
- | 529 | break; |
|
- | 530 | } |
|
- | 531 | break; |
|
- | 532 | } |
|
Line 552... | Line 533... | ||
552 | sizes.surface_bpp = 32; |
533 | } |
553 | 534 | ||
554 | crtc_count = 0; |
535 | crtc_count = 0; |
555 | for (i = 0; i < fb_helper->crtc_count; i++) { |
536 | for (i = 0; i < fb_helper->crtc_count; i++) { |
Line 902... | Line 883... | ||
902 | static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) |
883 | static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) |
903 | { |
884 | { |
904 | struct drm_device *dev = fb_helper->dev; |
885 | struct drm_device *dev = fb_helper->dev; |
905 | struct drm_fb_helper_crtc **crtcs; |
886 | struct drm_fb_helper_crtc **crtcs; |
906 | struct drm_display_mode **modes; |
887 | struct drm_display_mode **modes; |
907 | struct drm_encoder *encoder; |
- | |
908 | struct drm_mode_set *modeset; |
888 | struct drm_mode_set *modeset; |
909 | bool *enabled; |
889 | bool *enabled; |
910 | int width, height; |
890 | int width, height; |
911 | int i, ret; |
891 | int i, ret; |
Line 912... | Line 892... | ||
912 | 892 | ||
Line 913... | Line 893... | ||
913 | DRM_DEBUG_KMS("\n"); |
893 | DRM_DEBUG_KMS("\n"); |
914 | 894 | ||
Line 915... | Line -... | ||
915 | width = dev->mode_config.max_width; |
- | |
916 | height = dev->mode_config.max_height; |
- | |
917 | - | ||
918 | /* clean out all the encoder/crtc combos */ |
- | |
919 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
- | |
920 | encoder->crtc = NULL; |
895 | width = dev->mode_config.max_width; |
921 | } |
896 | height = dev->mode_config.max_height; |
922 | 897 | ||
923 | crtcs = kcalloc(dev->mode_config.num_connector, |
898 | crtcs = kcalloc(dev->mode_config.num_connector, |
924 | sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL); |
899 | sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL); |
Line 990... | Line 965... | ||
990 | { |
965 | { |
991 | struct drm_device *dev = fb_helper->dev; |
966 | struct drm_device *dev = fb_helper->dev; |
992 | int count = 0; |
967 | int count = 0; |
Line 993... | Line 968... | ||
993 | 968 | ||
994 | /* disable all the possible outputs/crtcs before entering KMS mode */ |
969 | /* disable all the possible outputs/crtcs before entering KMS mode */ |
Line 995... | Line 970... | ||
995 | // drm_helper_disable_unused_functions(fb_helper->dev); |
970 | drm_helper_disable_unused_functions(fb_helper->dev); |
Line 996... | Line 971... | ||
996 | 971 | ||
997 | // drm_fb_helper_parse_command_line(fb_helper); |
972 | // drm_fb_helper_parse_command_line(fb_helper); |