Rev 5271 | Rev 6937 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5271 | Rev 6084 | ||
---|---|---|---|
Line 109... | Line 109... | ||
109 | */ |
109 | */ |
110 | bool drm_helper_encoder_in_use(struct drm_encoder *encoder) |
110 | bool drm_helper_encoder_in_use(struct drm_encoder *encoder) |
111 | { |
111 | { |
112 | struct drm_connector *connector; |
112 | struct drm_connector *connector; |
113 | struct drm_device *dev = encoder->dev; |
113 | struct drm_device *dev = encoder->dev; |
- | 114 | ||
- | 115 | /* |
|
- | 116 | * We can expect this mutex to be locked if we are not panicking. |
|
- | 117 | * Locking is currently fubar in the panic handler. |
|
- | 118 | */ |
|
- | 119 | if (!oops_in_progress) { |
|
- | 120 | WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); |
|
114 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
121 | WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); |
- | 122 | } |
|
- | 123 | ||
- | 124 | drm_for_each_connector(connector, dev) |
|
115 | if (connector->encoder == encoder) |
125 | if (connector->encoder == encoder) |
116 | return true; |
126 | return true; |
117 | return false; |
127 | return false; |
118 | } |
128 | } |
119 | EXPORT_SYMBOL(drm_helper_encoder_in_use); |
129 | EXPORT_SYMBOL(drm_helper_encoder_in_use); |
Line 131... | Line 141... | ||
131 | */ |
141 | */ |
132 | bool drm_helper_crtc_in_use(struct drm_crtc *crtc) |
142 | bool drm_helper_crtc_in_use(struct drm_crtc *crtc) |
133 | { |
143 | { |
134 | struct drm_encoder *encoder; |
144 | struct drm_encoder *encoder; |
135 | struct drm_device *dev = crtc->dev; |
145 | struct drm_device *dev = crtc->dev; |
- | 146 | ||
- | 147 | /* |
|
- | 148 | * We can expect this mutex to be locked if we are not panicking. |
|
136 | /* FIXME: Locking around list access? */ |
149 | * Locking is currently fubar in the panic handler. |
- | 150 | */ |
|
- | 151 | if (!oops_in_progress) |
|
137 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) |
152 | WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); |
- | 153 | ||
- | 154 | drm_for_each_encoder(encoder, dev) |
|
138 | if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder)) |
155 | if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder)) |
139 | return true; |
156 | return true; |
140 | return false; |
157 | return false; |
141 | } |
158 | } |
142 | EXPORT_SYMBOL(drm_helper_crtc_in_use); |
159 | EXPORT_SYMBOL(drm_helper_crtc_in_use); |
Line 143... | Line 160... | ||
143 | 160 | ||
144 | static void |
161 | static void |
145 | drm_encoder_disable(struct drm_encoder *encoder) |
162 | drm_encoder_disable(struct drm_encoder *encoder) |
146 | { |
163 | { |
Line 147... | Line -... | ||
147 | struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; |
- | |
148 | 164 | const struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; |
|
Line 149... | Line 165... | ||
149 | if (encoder->bridge) |
165 | |
150 | encoder->bridge->funcs->disable(encoder->bridge); |
166 | drm_bridge_disable(encoder->bridge); |
151 | 167 | ||
152 | if (encoder_funcs->disable) |
168 | if (encoder_funcs->disable) |
Line 153... | Line -... | ||
153 | (*encoder_funcs->disable)(encoder); |
- | |
154 | else |
169 | (*encoder_funcs->disable)(encoder); |
155 | (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); |
170 | else |
Line 156... | Line 171... | ||
156 | 171 | (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); |
|
157 | if (encoder->bridge) |
172 | |
158 | encoder->bridge->funcs->post_disable(encoder->bridge); |
173 | drm_bridge_post_disable(encoder->bridge); |
159 | } |
174 | } |
Line 160... | Line 175... | ||
160 | 175 | ||
Line 161... | Line 176... | ||
161 | static void __drm_helper_disable_unused_functions(struct drm_device *dev) |
176 | static void __drm_helper_disable_unused_functions(struct drm_device *dev) |
162 | { |
177 | { |
163 | struct drm_encoder *encoder; |
178 | struct drm_encoder *encoder; |
164 | struct drm_crtc *crtc; |
179 | struct drm_crtc *crtc; |
165 | 180 | ||
166 | drm_warn_on_modeset_not_all_locked(dev); |
181 | drm_warn_on_modeset_not_all_locked(dev); |
167 | 182 | ||
Line 168... | Line 183... | ||
168 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
183 | drm_for_each_encoder(encoder, dev) { |
169 | if (!drm_helper_encoder_in_use(encoder)) { |
184 | if (!drm_helper_encoder_in_use(encoder)) { |
170 | drm_encoder_disable(encoder); |
185 | drm_encoder_disable(encoder); |
171 | /* disconnect encoder from any connector */ |
186 | /* disconnect encoder from any connector */ |
172 | encoder->crtc = NULL; |
187 | encoder->crtc = NULL; |
173 | } |
188 | } |
174 | } |
189 | } |
Line 210... | Line 225... | ||
210 | * since the driver will have to re-route things. |
225 | * since the driver will have to re-route things. |
211 | */ |
226 | */ |
212 | static void |
227 | static void |
213 | drm_crtc_prepare_encoders(struct drm_device *dev) |
228 | drm_crtc_prepare_encoders(struct drm_device *dev) |
214 | { |
229 | { |
215 | struct drm_encoder_helper_funcs *encoder_funcs; |
230 | const struct drm_encoder_helper_funcs *encoder_funcs; |
216 | struct drm_encoder *encoder; |
231 | struct drm_encoder *encoder; |
Line 217... | Line 232... | ||
217 | 232 | ||
218 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
233 | drm_for_each_encoder(encoder, dev) { |
219 | encoder_funcs = encoder->helper_private; |
234 | encoder_funcs = encoder->helper_private; |
220 | /* Disable unused encoders */ |
235 | /* Disable unused encoders */ |
221 | if (encoder->crtc == NULL) |
236 | if (encoder->crtc == NULL) |
222 | drm_encoder_disable(encoder); |
237 | drm_encoder_disable(encoder); |
Line 251... | Line 266... | ||
251 | struct drm_display_mode *mode, |
266 | struct drm_display_mode *mode, |
252 | int x, int y, |
267 | int x, int y, |
253 | struct drm_framebuffer *old_fb) |
268 | struct drm_framebuffer *old_fb) |
254 | { |
269 | { |
255 | struct drm_device *dev = crtc->dev; |
270 | struct drm_device *dev = crtc->dev; |
256 | struct drm_display_mode *adjusted_mode, saved_mode; |
271 | struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode; |
257 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
272 | const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
258 | struct drm_encoder_helper_funcs *encoder_funcs; |
273 | const struct drm_encoder_helper_funcs *encoder_funcs; |
259 | int saved_x, saved_y; |
274 | int saved_x, saved_y; |
260 | bool saved_enabled; |
275 | bool saved_enabled; |
261 | struct drm_encoder *encoder; |
276 | struct drm_encoder *encoder; |
262 | bool ret = true; |
277 | bool ret = true; |
Line 273... | Line 288... | ||
273 | crtc->enabled = saved_enabled; |
288 | crtc->enabled = saved_enabled; |
274 | return false; |
289 | return false; |
275 | } |
290 | } |
Line 276... | Line 291... | ||
276 | 291 | ||
- | 292 | saved_mode = crtc->mode; |
|
277 | saved_mode = crtc->mode; |
293 | saved_hwmode = crtc->hwmode; |
278 | saved_x = crtc->x; |
294 | saved_x = crtc->x; |
Line 279... | Line 295... | ||
279 | saved_y = crtc->y; |
295 | saved_y = crtc->y; |
280 | 296 | ||
Line 287... | Line 303... | ||
287 | 303 | ||
288 | /* Pass our mode to the connectors and the CRTC to give them a chance to |
304 | /* Pass our mode to the connectors and the CRTC to give them a chance to |
289 | * adjust it according to limitations or connector properties, and also |
305 | * adjust it according to limitations or connector properties, and also |
290 | * a chance to reject the mode entirely. |
306 | * a chance to reject the mode entirely. |
291 | */ |
307 | */ |
Line 292... | Line 308... | ||
292 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
308 | drm_for_each_encoder(encoder, dev) { |
293 | 309 | ||
Line 294... | Line -... | ||
294 | if (encoder->crtc != crtc) |
- | |
295 | continue; |
310 | if (encoder->crtc != crtc) |
296 | 311 | continue; |
|
297 | if (encoder->bridge && encoder->bridge->funcs->mode_fixup) { |
312 | |
298 | ret = encoder->bridge->funcs->mode_fixup( |
313 | ret = drm_bridge_mode_fixup(encoder->bridge, |
299 | encoder->bridge, mode, adjusted_mode); |
314 | mode, adjusted_mode); |
300 | if (!ret) { |
315 | if (!ret) { |
301 | DRM_DEBUG_KMS("Bridge fixup failed\n"); |
- | |
Line 302... | Line 316... | ||
302 | goto done; |
316 | DRM_DEBUG_KMS("Bridge fixup failed\n"); |
303 | } |
317 | goto done; |
304 | } |
318 | } |
305 | 319 | ||
Line 315... | Line 329... | ||
315 | DRM_DEBUG_KMS("CRTC fixup failed\n"); |
329 | DRM_DEBUG_KMS("CRTC fixup failed\n"); |
316 | goto done; |
330 | goto done; |
317 | } |
331 | } |
318 | DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); |
332 | DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); |
Line -... | Line 333... | ||
- | 333 | ||
- | 334 | crtc->hwmode = *adjusted_mode; |
|
319 | 335 | ||
320 | /* Prepare the encoders and CRTCs before setting the mode. */ |
336 | /* Prepare the encoders and CRTCs before setting the mode. */ |
Line 321... | Line 337... | ||
321 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
337 | drm_for_each_encoder(encoder, dev) { |
322 | 338 | ||
Line 323... | Line -... | ||
323 | if (encoder->crtc != crtc) |
- | |
324 | continue; |
339 | if (encoder->crtc != crtc) |
Line 325... | Line 340... | ||
325 | 340 | continue; |
|
326 | if (encoder->bridge) |
341 | |
327 | encoder->bridge->funcs->disable(encoder->bridge); |
342 | drm_bridge_disable(encoder->bridge); |
Line 328... | Line -... | ||
328 | - | ||
329 | encoder_funcs = encoder->helper_private; |
343 | |
330 | /* Disable the encoders as the first thing we do. */ |
344 | encoder_funcs = encoder->helper_private; |
Line 331... | Line 345... | ||
331 | encoder_funcs->prepare(encoder); |
345 | /* Disable the encoders as the first thing we do. */ |
Line 332... | Line 346... | ||
332 | 346 | encoder_funcs->prepare(encoder); |
|
Line 343... | Line 357... | ||
343 | */ |
357 | */ |
344 | ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb); |
358 | ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb); |
345 | if (!ret) |
359 | if (!ret) |
346 | goto done; |
360 | goto done; |
Line 347... | Line 361... | ||
347 | 361 | ||
Line 348... | Line 362... | ||
348 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
362 | drm_for_each_encoder(encoder, dev) { |
349 | 363 | ||
Line 350... | Line 364... | ||
350 | if (encoder->crtc != crtc) |
364 | if (encoder->crtc != crtc) |
351 | continue; |
365 | continue; |
352 | 366 | ||
353 | DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n", |
367 | DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n", |
354 | encoder->base.id, encoder->name, |
368 | encoder->base.id, encoder->name, |
Line 355... | Line -... | ||
355 | mode->base.id, mode->name); |
- | |
356 | encoder_funcs = encoder->helper_private; |
369 | mode->base.id, mode->name); |
357 | encoder_funcs->mode_set(encoder, mode, adjusted_mode); |
- | |
358 | 370 | encoder_funcs = encoder->helper_private; |
|
Line 359... | Line 371... | ||
359 | if (encoder->bridge && encoder->bridge->funcs->mode_set) |
371 | encoder_funcs->mode_set(encoder, mode, adjusted_mode); |
360 | encoder->bridge->funcs->mode_set(encoder->bridge, mode, |
372 | |
Line 361... | Line 373... | ||
361 | adjusted_mode); |
373 | drm_bridge_mode_set(encoder->bridge, mode, adjusted_mode); |
Line 362... | Line 374... | ||
362 | } |
374 | } |
363 | 375 | ||
Line 364... | Line -... | ||
364 | /* Now enable the clocks, plane, pipe, and connectors that we set up. */ |
- | |
365 | crtc_funcs->commit(crtc); |
376 | /* Now enable the clocks, plane, pipe, and connectors that we set up. */ |
Line 366... | Line 377... | ||
366 | 377 | crtc_funcs->commit(crtc); |
|
367 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
378 | |
Line 368... | Line -... | ||
368 | - | ||
369 | if (encoder->crtc != crtc) |
379 | drm_for_each_encoder(encoder, dev) { |
370 | continue; |
380 | |
Line 371... | Line -... | ||
371 | - | ||
372 | if (encoder->bridge) |
- | |
373 | encoder->bridge->funcs->pre_enable(encoder->bridge); |
- | |
374 | 381 | if (encoder->crtc != crtc) |
|
375 | encoder_funcs = encoder->helper_private; |
382 | continue; |
376 | encoder_funcs->commit(encoder); |
383 | |
377 | 384 | drm_bridge_pre_enable(encoder->bridge); |
|
378 | if (encoder->bridge) |
385 | |
Line 392... | Line 399... | ||
392 | done: |
399 | done: |
393 | drm_mode_destroy(dev, adjusted_mode); |
400 | drm_mode_destroy(dev, adjusted_mode); |
394 | if (!ret) { |
401 | if (!ret) { |
395 | crtc->enabled = saved_enabled; |
402 | crtc->enabled = saved_enabled; |
396 | crtc->mode = saved_mode; |
403 | crtc->mode = saved_mode; |
- | 404 | crtc->hwmode = saved_hwmode; |
|
397 | crtc->x = saved_x; |
405 | crtc->x = saved_x; |
398 | crtc->y = saved_y; |
406 | crtc->y = saved_y; |
399 | } |
407 | } |
Line 400... | Line 408... | ||
400 | 408 | ||
Line 408... | Line 416... | ||
408 | struct drm_device *dev = crtc->dev; |
416 | struct drm_device *dev = crtc->dev; |
409 | struct drm_connector *connector; |
417 | struct drm_connector *connector; |
410 | struct drm_encoder *encoder; |
418 | struct drm_encoder *encoder; |
Line 411... | Line 419... | ||
411 | 419 | ||
412 | /* Decouple all encoders and their attached connectors from this crtc */ |
420 | /* Decouple all encoders and their attached connectors from this crtc */ |
413 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
421 | drm_for_each_encoder(encoder, dev) { |
414 | if (encoder->crtc != crtc) |
422 | if (encoder->crtc != crtc) |
Line 415... | Line 423... | ||
415 | continue; |
423 | continue; |
416 | 424 | ||
417 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
425 | drm_for_each_connector(connector, dev) { |
Line 418... | Line 426... | ||
418 | if (connector->encoder != encoder) |
426 | if (connector->encoder != encoder) |
Line 453... | Line 461... | ||
453 | struct drm_encoder *save_encoders, *new_encoder, *encoder; |
461 | struct drm_encoder *save_encoders, *new_encoder, *encoder; |
454 | bool mode_changed = false; /* if true do a full mode set */ |
462 | bool mode_changed = false; /* if true do a full mode set */ |
455 | bool fb_changed = false; /* if true and !mode_changed just do a flip */ |
463 | bool fb_changed = false; /* if true and !mode_changed just do a flip */ |
456 | struct drm_connector *save_connectors, *connector; |
464 | struct drm_connector *save_connectors, *connector; |
457 | int count = 0, ro, fail = 0; |
465 | int count = 0, ro, fail = 0; |
458 | struct drm_crtc_helper_funcs *crtc_funcs; |
466 | const struct drm_crtc_helper_funcs *crtc_funcs; |
459 | struct drm_mode_set save_set; |
467 | struct drm_mode_set save_set; |
460 | int ret; |
468 | int ret; |
461 | int i; |
469 | int i; |
Line 462... | Line 470... | ||
462 | 470 | ||
Line 509... | Line 517... | ||
509 | * Copy data. Note that driver private data is not affected. |
517 | * Copy data. Note that driver private data is not affected. |
510 | * Should anything bad happen only the expected state is |
518 | * Should anything bad happen only the expected state is |
511 | * restored, not the drivers personal bookkeeping. |
519 | * restored, not the drivers personal bookkeeping. |
512 | */ |
520 | */ |
513 | count = 0; |
521 | count = 0; |
514 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
522 | drm_for_each_encoder(encoder, dev) { |
515 | save_encoders[count++] = *encoder; |
523 | save_encoders[count++] = *encoder; |
516 | } |
524 | } |
Line 517... | Line 525... | ||
517 | 525 | ||
518 | count = 0; |
526 | count = 0; |
519 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
527 | drm_for_each_connector(connector, dev) { |
520 | save_connectors[count++] = *connector; |
528 | save_connectors[count++] = *connector; |
Line 521... | Line 529... | ||
521 | } |
529 | } |
522 | 530 | ||
Line 552... | Line 560... | ||
552 | mode_changed = true; |
560 | mode_changed = true; |
553 | } |
561 | } |
Line 554... | Line 562... | ||
554 | 562 | ||
555 | /* a) traverse passed in connector list and get encoders for them */ |
563 | /* a) traverse passed in connector list and get encoders for them */ |
556 | count = 0; |
564 | count = 0; |
557 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
565 | drm_for_each_connector(connector, dev) { |
558 | struct drm_connector_helper_funcs *connector_funcs = |
566 | const struct drm_connector_helper_funcs *connector_funcs = |
559 | connector->helper_private; |
567 | connector->helper_private; |
560 | new_encoder = connector->encoder; |
568 | new_encoder = connector->encoder; |
561 | for (ro = 0; ro < set->num_connectors; ro++) { |
569 | for (ro = 0; ro < set->num_connectors; ro++) { |
562 | if (set->connectors[ro] == connector) { |
570 | if (set->connectors[ro] == connector) { |
Line 592... | Line 600... | ||
592 | ret = -EINVAL; |
600 | ret = -EINVAL; |
593 | goto fail; |
601 | goto fail; |
594 | } |
602 | } |
Line 595... | Line 603... | ||
595 | 603 | ||
596 | count = 0; |
604 | count = 0; |
597 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
605 | drm_for_each_connector(connector, dev) { |
598 | if (!connector->encoder) |
606 | if (!connector->encoder) |
Line 599... | Line 607... | ||
599 | continue; |
607 | continue; |
600 | 608 | ||
Line 675... | Line 683... | ||
675 | return 0; |
683 | return 0; |
Line 676... | Line 684... | ||
676 | 684 | ||
677 | fail: |
685 | fail: |
678 | /* Restore all previous data. */ |
686 | /* Restore all previous data. */ |
679 | count = 0; |
687 | count = 0; |
680 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
688 | drm_for_each_encoder(encoder, dev) { |
681 | *encoder = save_encoders[count++]; |
689 | *encoder = save_encoders[count++]; |
Line 682... | Line 690... | ||
682 | } |
690 | } |
683 | 691 | ||
684 | count = 0; |
692 | count = 0; |
685 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
693 | drm_for_each_connector(connector, dev) { |
Line 686... | Line 694... | ||
686 | *connector = save_connectors[count++]; |
694 | *connector = save_connectors[count++]; |
687 | } |
695 | } |
Line 702... | Line 710... | ||
702 | { |
710 | { |
703 | int dpms = DRM_MODE_DPMS_OFF; |
711 | int dpms = DRM_MODE_DPMS_OFF; |
704 | struct drm_connector *connector; |
712 | struct drm_connector *connector; |
705 | struct drm_device *dev = encoder->dev; |
713 | struct drm_device *dev = encoder->dev; |
Line 706... | Line 714... | ||
706 | 714 | ||
707 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
715 | drm_for_each_connector(connector, dev) |
708 | if (connector->encoder == encoder) |
716 | if (connector->encoder == encoder) |
709 | if (connector->dpms < dpms) |
717 | if (connector->dpms < dpms) |
710 | dpms = connector->dpms; |
718 | dpms = connector->dpms; |
711 | return dpms; |
719 | return dpms; |
Line 712... | Line 720... | ||
712 | } |
720 | } |
713 | 721 | ||
714 | /* Helper which handles bridge ordering around encoder dpms */ |
722 | /* Helper which handles bridge ordering around encoder dpms */ |
715 | static void drm_helper_encoder_dpms(struct drm_encoder *encoder, int mode) |
723 | static void drm_helper_encoder_dpms(struct drm_encoder *encoder, int mode) |
716 | { |
724 | { |
Line 717... | Line -... | ||
717 | struct drm_bridge *bridge = encoder->bridge; |
- | |
718 | struct drm_encoder_helper_funcs *encoder_funcs; |
725 | struct drm_bridge *bridge = encoder->bridge; |
719 | 726 | const struct drm_encoder_helper_funcs *encoder_funcs; |
|
720 | if (bridge) { |
727 | |
721 | if (mode == DRM_MODE_DPMS_ON) |
728 | if (mode == DRM_MODE_DPMS_ON) |
722 | bridge->funcs->pre_enable(bridge); |
- | |
Line 723... | Line 729... | ||
723 | else |
729 | drm_bridge_pre_enable(bridge); |
724 | bridge->funcs->disable(bridge); |
730 | else |
725 | } |
731 | drm_bridge_disable(bridge); |
Line 726... | Line -... | ||
726 | - | ||
727 | encoder_funcs = encoder->helper_private; |
732 | |
728 | if (encoder_funcs->dpms) |
733 | encoder_funcs = encoder->helper_private; |
729 | encoder_funcs->dpms(encoder, mode); |
734 | if (encoder_funcs->dpms) |
730 | 735 | encoder_funcs->dpms(encoder, mode); |
|
731 | if (bridge) { |
- | |
732 | if (mode == DRM_MODE_DPMS_ON) |
736 | |
Line 733... | Line 737... | ||
733 | bridge->funcs->enable(bridge); |
737 | if (mode == DRM_MODE_DPMS_ON) |
734 | else |
738 | drm_bridge_enable(bridge); |
735 | bridge->funcs->post_disable(bridge); |
739 | else |
736 | } |
740 | drm_bridge_post_disable(bridge); |
737 | } |
741 | } |
Line 738... | Line 742... | ||
738 | 742 | ||
739 | static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc) |
743 | static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc) |
740 | { |
744 | { |
741 | int dpms = DRM_MODE_DPMS_OFF; |
745 | int dpms = DRM_MODE_DPMS_OFF; |
742 | struct drm_connector *connector; |
746 | struct drm_connector *connector; |
743 | struct drm_device *dev = crtc->dev; |
747 | struct drm_device *dev = crtc->dev; |
Line 756... | Line 760... | ||
756 | * |
760 | * |
757 | * This is the main helper function provided by the crtc helper framework for |
761 | * This is the main helper function provided by the crtc helper framework for |
758 | * implementing the DPMS connector attribute. It computes the new desired DPMS |
762 | * implementing the DPMS connector attribute. It computes the new desired DPMS |
759 | * state for all encoders and crtcs in the output mesh and calls the ->dpms() |
763 | * state for all encoders and crtcs in the output mesh and calls the ->dpms() |
760 | * callback provided by the driver appropriately. |
764 | * callback provided by the driver appropriately. |
- | 765 | * |
|
- | 766 | * Returns: |
|
- | 767 | * Always returns 0. |
|
761 | */ |
768 | */ |
762 | void drm_helper_connector_dpms(struct drm_connector *connector, int mode) |
769 | int drm_helper_connector_dpms(struct drm_connector *connector, int mode) |
763 | { |
770 | { |
764 | struct drm_encoder *encoder = connector->encoder; |
771 | struct drm_encoder *encoder = connector->encoder; |
765 | struct drm_crtc *crtc = encoder ? encoder->crtc : NULL; |
772 | struct drm_crtc *crtc = encoder ? encoder->crtc : NULL; |
766 | int old_dpms, encoder_dpms = DRM_MODE_DPMS_OFF; |
773 | int old_dpms, encoder_dpms = DRM_MODE_DPMS_OFF; |
Line 767... | Line 774... | ||
767 | 774 | ||
768 | if (mode == connector->dpms) |
775 | if (mode == connector->dpms) |
Line 769... | Line 776... | ||
769 | return; |
776 | return 0; |
770 | 777 | ||
Line 771... | Line 778... | ||
771 | old_dpms = connector->dpms; |
778 | old_dpms = connector->dpms; |
772 | connector->dpms = mode; |
779 | connector->dpms = mode; |
Line 773... | Line 780... | ||
773 | 780 | ||
774 | if (encoder) |
781 | if (encoder) |
775 | encoder_dpms = drm_helper_choose_encoder_dpms(encoder); |
782 | encoder_dpms = drm_helper_choose_encoder_dpms(encoder); |
776 | 783 | ||
777 | /* from off to on, do crtc then encoder */ |
784 | /* from off to on, do crtc then encoder */ |
778 | if (mode < old_dpms) { |
785 | if (mode < old_dpms) { |
779 | if (crtc) { |
786 | if (crtc) { |
780 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
787 | const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
781 | if (crtc_funcs->dpms) |
788 | if (crtc_funcs->dpms) |
Line 789... | Line 796... | ||
789 | /* from on to off, do encoder then crtc */ |
796 | /* from on to off, do encoder then crtc */ |
790 | if (mode > old_dpms) { |
797 | if (mode > old_dpms) { |
791 | if (encoder) |
798 | if (encoder) |
792 | drm_helper_encoder_dpms(encoder, encoder_dpms); |
799 | drm_helper_encoder_dpms(encoder, encoder_dpms); |
793 | if (crtc) { |
800 | if (crtc) { |
794 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
801 | const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
795 | if (crtc_funcs->dpms) |
802 | if (crtc_funcs->dpms) |
796 | (*crtc_funcs->dpms) (crtc, |
803 | (*crtc_funcs->dpms) (crtc, |
797 | drm_helper_choose_crtc_dpms(crtc)); |
804 | drm_helper_choose_crtc_dpms(crtc)); |
798 | } |
805 | } |
799 | } |
806 | } |
Line 800... | Line 807... | ||
800 | 807 | ||
801 | return; |
808 | return 0; |
802 | } |
809 | } |
Line 803... | Line 810... | ||
803 | EXPORT_SYMBOL(drm_helper_connector_dpms); |
810 | EXPORT_SYMBOL(drm_helper_connector_dpms); |
804 | 811 | ||
Line 818... | Line 825... | ||
818 | fb->width = mode_cmd->width; |
825 | fb->width = mode_cmd->width; |
819 | fb->height = mode_cmd->height; |
826 | fb->height = mode_cmd->height; |
820 | for (i = 0; i < 4; i++) { |
827 | for (i = 0; i < 4; i++) { |
821 | fb->pitches[i] = mode_cmd->pitches[i]; |
828 | fb->pitches[i] = mode_cmd->pitches[i]; |
822 | fb->offsets[i] = mode_cmd->offsets[i]; |
829 | fb->offsets[i] = mode_cmd->offsets[i]; |
- | 830 | fb->modifier[i] = mode_cmd->modifier[i]; |
|
823 | } |
831 | } |
824 | drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth, |
832 | drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth, |
825 | &fb->bits_per_pixel); |
833 | &fb->bits_per_pixel); |
826 | fb->pixel_format = mode_cmd->pixel_format; |
834 | fb->pixel_format = mode_cmd->pixel_format; |
827 | fb->flags = mode_cmd->flags; |
835 | fb->flags = mode_cmd->flags; |
Line 850... | Line 858... | ||
850 | */ |
858 | */ |
851 | void drm_helper_resume_force_mode(struct drm_device *dev) |
859 | void drm_helper_resume_force_mode(struct drm_device *dev) |
852 | { |
860 | { |
853 | struct drm_crtc *crtc; |
861 | struct drm_crtc *crtc; |
854 | struct drm_encoder *encoder; |
862 | struct drm_encoder *encoder; |
855 | struct drm_crtc_helper_funcs *crtc_funcs; |
863 | const struct drm_crtc_helper_funcs *crtc_funcs; |
856 | int encoder_dpms; |
864 | int encoder_dpms; |
857 | bool ret; |
865 | bool ret; |
Line 858... | Line 866... | ||
858 | 866 | ||
859 | drm_modeset_lock_all(dev); |
867 | drm_modeset_lock_all(dev); |
Line 860... | Line 868... | ||
860 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
868 | drm_for_each_crtc(crtc, dev) { |
861 | 869 | ||
Line 862... | Line 870... | ||
862 | if (!crtc->enabled) |
870 | if (!crtc->enabled) |
Line 869... | Line 877... | ||
869 | if (ret == false) |
877 | if (ret == false) |
870 | DRM_ERROR("failed to set mode on crtc %p\n", crtc); |
878 | DRM_ERROR("failed to set mode on crtc %p\n", crtc); |
Line 871... | Line 879... | ||
871 | 879 | ||
872 | /* Turn off outputs that were already powered off */ |
880 | /* Turn off outputs that were already powered off */ |
873 | if (drm_helper_choose_crtc_dpms(crtc)) { |
881 | if (drm_helper_choose_crtc_dpms(crtc)) { |
Line 874... | Line 882... | ||
874 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
882 | drm_for_each_encoder(encoder, dev) { |
875 | 883 | ||
Line 876... | Line 884... | ||
876 | if(encoder->crtc != crtc) |
884 | if(encoder->crtc != crtc) |
Line 915... | Line 923... | ||
915 | int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, |
923 | int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, |
916 | struct drm_display_mode *adjusted_mode, int x, int y, |
924 | struct drm_display_mode *adjusted_mode, int x, int y, |
917 | struct drm_framebuffer *old_fb) |
925 | struct drm_framebuffer *old_fb) |
918 | { |
926 | { |
919 | struct drm_crtc_state *crtc_state; |
927 | struct drm_crtc_state *crtc_state; |
920 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
928 | const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
921 | int ret; |
929 | int ret; |
Line 922... | Line 930... | ||
922 | 930 | ||
923 | if (crtc->funcs->atomic_duplicate_state) |
931 | if (crtc->funcs->atomic_duplicate_state) |
- | 932 | crtc_state = crtc->funcs->atomic_duplicate_state(crtc); |
|
924 | crtc_state = crtc->funcs->atomic_duplicate_state(crtc); |
933 | else { |
925 | else if (crtc->state) |
934 | if (!crtc->state) |
926 | crtc_state = kmemdup(crtc->state, sizeof(*crtc_state), |
- | |
927 | GFP_KERNEL); |
935 | drm_atomic_helper_crtc_reset(crtc); |
928 | else |
936 | |
- | 937 | crtc_state = drm_atomic_helper_crtc_duplicate_state(crtc); |
|
- | 938 | } |
|
929 | crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL); |
939 | |
930 | if (!crtc_state) |
940 | if (!crtc_state) |
Line 931... | Line -... | ||
931 | return -ENOMEM; |
- | |
932 | 941 | return -ENOMEM; |
|
933 | crtc_state->enable = true; |
942 | |
934 | crtc_state->planes_changed = true; |
943 | crtc_state->planes_changed = true; |
- | 944 | crtc_state->mode_changed = true; |
|
- | 945 | ret = drm_atomic_set_mode_for_crtc(crtc_state, mode); |
|
935 | crtc_state->mode_changed = true; |
946 | if (ret) |
Line 936... | Line 947... | ||
936 | drm_mode_copy(&crtc_state->mode, mode); |
947 | goto out; |
937 | drm_mode_copy(&crtc_state->adjusted_mode, adjusted_mode); |
948 | drm_mode_copy(&crtc_state->adjusted_mode, adjusted_mode); |
938 | 949 | ||
939 | if (crtc_funcs->atomic_check) { |
- | |
940 | ret = crtc_funcs->atomic_check(crtc, crtc_state); |
- | |
941 | if (ret) { |
950 | if (crtc_funcs->atomic_check) { |
942 | kfree(crtc_state); |
- | |
943 | 951 | ret = crtc_funcs->atomic_check(crtc, crtc_state); |
|
Line 944... | Line 952... | ||
944 | return ret; |
952 | if (ret) |
Line 945... | Line 953... | ||
945 | } |
953 | goto out; |
Line -... | Line 954... | ||
- | 954 | } |
|
- | 955 | ||
- | 956 | swap(crtc->state, crtc_state); |
|
946 | } |
957 | |
947 | 958 | crtc_funcs->mode_set_nofb(crtc); |
|
948 | swap(crtc->state, crtc_state); |
959 | |
949 | 960 | ret = drm_helper_crtc_mode_set_base(crtc, x, y, old_fb); |
|
950 | crtc_funcs->mode_set_nofb(crtc); |
961 | |
951 | 962 | out: |
|
Line 952... | Line 963... | ||
952 | if (crtc_state) { |
963 | if (crtc_state) { |
953 | if (crtc->funcs->atomic_destroy_state) |
964 | if (crtc->funcs->atomic_destroy_state) |
954 | crtc->funcs->atomic_destroy_state(crtc, crtc_state); |
965 | crtc->funcs->atomic_destroy_state(crtc, crtc_state); |
Line 955... | Line 966... | ||
955 | else |
966 | else |
956 | kfree(crtc_state); |
967 | drm_atomic_helper_crtc_destroy_state(crtc, crtc_state); |
Line 986... | Line 997... | ||
986 | plane_state = drm_atomic_helper_plane_duplicate_state(plane); |
997 | plane_state = drm_atomic_helper_plane_duplicate_state(plane); |
987 | else |
998 | else |
988 | plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); |
999 | plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); |
989 | if (!plane_state) |
1000 | if (!plane_state) |
990 | return -ENOMEM; |
1001 | return -ENOMEM; |
- | 1002 | plane_state->plane = plane; |
|
Line 991... | Line 1003... | ||
991 | 1003 | ||
992 | plane_state->crtc = crtc; |
1004 | plane_state->crtc = crtc; |
993 | drm_atomic_set_fb_for_plane(plane_state, crtc->primary->fb); |
1005 | drm_atomic_set_fb_for_plane(plane_state, crtc->primary->fb); |
994 | plane_state->crtc_x = 0; |
1006 | plane_state->crtc_x = 0; |