summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2009-09-18 05:14:41 +0400
committerDave Airlie <airlied@redhat.com>2009-09-18 08:34:05 +0400
commite87b2c42b397ae64ac13a390011931f7ef222321 (patch)
tree04a057e8a48f1bfaffbcf788be7a984336ce90bb
parent8dfaa8a7779ad2667d539aca6ae11cd87f562db6 (diff)
downloadlinux-e87b2c42b397ae64ac13a390011931f7ef222321.tar.xz
drm: fix drm_fb_helper handling of kernel crtcs
The drm_fb_helper shouldn't mess with CRTCs that aren't enabled or in its initial config. Ideally it shouldn't even include CRTCs in its initial config if they're not in use, but my old fix for that no longer works. At any rate, this fixes a real bug I was seeing where after a console blank, both pipes would come back on, even though only one had been enabled before that. Since the other pipe had a bogus config, this led to some screen corruption. Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c80
1 files changed, 43 insertions, 37 deletions
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 8eee4a620376..2c4671314884 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -116,27 +116,30 @@ static void drm_fb_helper_on(struct fb_info *info)
* For each CRTC in this fb, turn the crtc on then,
* find all associated encoders and turn them on.
*/
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+ for (i = 0; i < fb_helper->crtc_count; i++) {
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ struct drm_crtc_helper_funcs *crtc_funcs =
+ crtc->helper_private;
- for (i = 0; i < fb_helper->crtc_count; i++) {
- if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
- break;
- }
+ /* Only mess with CRTCs in this fb */
+ if (crtc->base.id != fb_helper->crtc_info[i].crtc_id ||
+ !crtc->enabled)
+ continue;
- mutex_lock(&dev->mode_config.mutex);
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
- mutex_unlock(&dev->mode_config.mutex);
+ mutex_lock(&dev->mode_config.mutex);
+ crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
+ mutex_unlock(&dev->mode_config.mutex);
- /* Found a CRTC on this fb, now find encoders */
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- if (encoder->crtc == crtc) {
- struct drm_encoder_helper_funcs *encoder_funcs;
+ /* Found a CRTC on this fb, now find encoders */
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ if (encoder->crtc == crtc) {
+ struct drm_encoder_helper_funcs *encoder_funcs;
- encoder_funcs = encoder->helper_private;
- mutex_lock(&dev->mode_config.mutex);
- encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
- mutex_unlock(&dev->mode_config.mutex);
+ encoder_funcs = encoder->helper_private;
+ mutex_lock(&dev->mode_config.mutex);
+ encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
+ mutex_unlock(&dev->mode_config.mutex);
+ }
}
}
}
@@ -154,30 +157,33 @@ static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)
* For each CRTC in this fb, find all associated encoders
* and turn them off, then turn off the CRTC.
*/
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
-
- for (i = 0; i < fb_helper->crtc_count; i++) {
- if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
- break;
- }
-
- /* Found a CRTC on this fb, now find encoders */
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- if (encoder->crtc == crtc) {
- struct drm_encoder_helper_funcs *encoder_funcs;
-
- encoder_funcs = encoder->helper_private;
+ for (i = 0; i < fb_helper->crtc_count; i++) {
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ struct drm_crtc_helper_funcs *crtc_funcs =
+ crtc->helper_private;
+
+ /* Only mess with CRTCs in this fb */
+ if (crtc->base.id != fb_helper->crtc_info[i].crtc_id ||
+ !crtc->enabled)
+ continue;
+
+ /* Found a CRTC on this fb, now find encoders */
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ if (encoder->crtc == crtc) {
+ struct drm_encoder_helper_funcs *encoder_funcs;
+
+ encoder_funcs = encoder->helper_private;
+ mutex_lock(&dev->mode_config.mutex);
+ encoder_funcs->dpms(encoder, dpms_mode);
+ mutex_unlock(&dev->mode_config.mutex);
+ }
+ }
+ if (dpms_mode == DRM_MODE_DPMS_OFF) {
mutex_lock(&dev->mode_config.mutex);
- encoder_funcs->dpms(encoder, dpms_mode);
+ crtc_funcs->dpms(crtc, dpms_mode);
mutex_unlock(&dev->mode_config.mutex);
}
}
- if (dpms_mode == DRM_MODE_DPMS_OFF) {
- mutex_lock(&dev->mode_config.mutex);
- crtc_funcs->dpms(crtc, dpms_mode);
- mutex_unlock(&dev->mode_config.mutex);
- }
}
}