Commit e87b2c42 authored by Jesse Barnes's avatar Jesse Barnes Committed by Dave Airlie

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: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 8dfaa8a7
...@@ -116,27 +116,30 @@ static void drm_fb_helper_on(struct fb_info *info) ...@@ -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, * For each CRTC in this fb, turn the crtc on then,
* find all associated encoders and turn them on. * find all associated encoders and turn them on.
*/ */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { for (i = 0; i < fb_helper->crtc_count; i++) {
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 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++) { /* Only mess with CRTCs in this fb */
if (crtc->base.id == fb_helper->crtc_info[i].crtc_id) if (crtc->base.id != fb_helper->crtc_info[i].crtc_id ||
break; !crtc->enabled)
} continue;
mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->mode_config.mutex);
crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex);
/* Found a CRTC on this fb, now find encoders */ /* Found a CRTC on this fb, now find encoders */
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if (encoder->crtc == crtc) { if (encoder->crtc == crtc) {
struct drm_encoder_helper_funcs *encoder_funcs; struct drm_encoder_helper_funcs *encoder_funcs;
encoder_funcs = encoder->helper_private; encoder_funcs = encoder->helper_private;
mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->mode_config.mutex);
encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex);
}
} }
} }
} }
...@@ -154,30 +157,33 @@ static void drm_fb_helper_off(struct fb_info *info, int dpms_mode) ...@@ -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 * For each CRTC in this fb, find all associated encoders
* and turn them off, then turn off the CRTC. * and turn them off, then turn off the CRTC.
*/ */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { for (i = 0; i < fb_helper->crtc_count; i++) {
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct drm_crtc_helper_funcs *crtc_funcs =
for (i = 0; i < fb_helper->crtc_count; i++) { crtc->helper_private;
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)
/* Found a CRTC on this fb, now find encoders */ continue;
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if (encoder->crtc == crtc) { /* Found a CRTC on this fb, now find encoders */
struct drm_encoder_helper_funcs *encoder_funcs; list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if (encoder->crtc == crtc) {
encoder_funcs = encoder->helper_private; 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); mutex_lock(&dev->mode_config.mutex);
encoder_funcs->dpms(encoder, dpms_mode); crtc_funcs->dpms(crtc, dpms_mode);
mutex_unlock(&dev->mode_config.mutex); 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);
}
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment