aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_fb_helper.c
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2009-09-17 21:14:41 -0400
committerDave Airlie <airlied@redhat.com>2009-09-18 00:34:05 -0400
commite87b2c42b397ae64ac13a390011931f7ef222321 (patch)
tree04a057e8a48f1bfaffbcf788be7a984336ce90bb /drivers/gpu/drm/drm_fb_helper.c
parent8dfaa8a7779ad2667d539aca6ae11cd87f562db6 (diff)
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>
Diffstat (limited to 'drivers/gpu/drm/drm_fb_helper.c')
-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)
116 * For each CRTC in this fb, turn the crtc on then, 116 * For each CRTC in this fb, turn the crtc on then,
117 * find all associated encoders and turn them on. 117 * find all associated encoders and turn them on.
118 */ 118 */
119 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 119 for (i = 0; i < fb_helper->crtc_count; i++) {
120 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 120 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
121 struct drm_crtc_helper_funcs *crtc_funcs =
122 crtc->helper_private;
121 123
122 for (i = 0; i < fb_helper->crtc_count; i++) { 124 /* Only mess with CRTCs in this fb */
123 if (crtc->base.id == fb_helper->crtc_info[i].crtc_id) 125 if (crtc->base.id != fb_helper->crtc_info[i].crtc_id ||
124 break; 126 !crtc->enabled)
125 } 127 continue;
126 128
127 mutex_lock(&dev->mode_config.mutex); 129 mutex_lock(&dev->mode_config.mutex);
128 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); 130 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
129 mutex_unlock(&dev->mode_config.mutex); 131 mutex_unlock(&dev->mode_config.mutex);
130 132
131 /* Found a CRTC on this fb, now find encoders */ 133 /* Found a CRTC on this fb, now find encoders */
132 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 134 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
133 if (encoder->crtc == crtc) { 135 if (encoder->crtc == crtc) {
134 struct drm_encoder_helper_funcs *encoder_funcs; 136 struct drm_encoder_helper_funcs *encoder_funcs;
135 137
136 encoder_funcs = encoder->helper_private; 138 encoder_funcs = encoder->helper_private;
137 mutex_lock(&dev->mode_config.mutex); 139 mutex_lock(&dev->mode_config.mutex);
138 encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); 140 encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
139 mutex_unlock(&dev->mode_config.mutex); 141 mutex_unlock(&dev->mode_config.mutex);
142 }
140 } 143 }
141 } 144 }
142 } 145 }
@@ -154,30 +157,33 @@ static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)
154 * For each CRTC in this fb, find all associated encoders 157 * For each CRTC in this fb, find all associated encoders
155 * and turn them off, then turn off the CRTC. 158 * and turn them off, then turn off the CRTC.
156 */ 159 */
157 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 160 for (i = 0; i < fb_helper->crtc_count; i++) {
158 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 161 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
159 162 struct drm_crtc_helper_funcs *crtc_funcs =
160 for (i = 0; i < fb_helper->crtc_count; i++) { 163 crtc->helper_private;
161 if (crtc->base.id == fb_helper->crtc_info[i].crtc_id) 164
162 break; 165 /* Only mess with CRTCs in this fb */
163 } 166 if (crtc->base.id != fb_helper->crtc_info[i].crtc_id ||
164 167 !crtc->enabled)
165 /* Found a CRTC on this fb, now find encoders */ 168 continue;
166 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 169
167 if (encoder->crtc == crtc) { 170 /* Found a CRTC on this fb, now find encoders */
168 struct drm_encoder_helper_funcs *encoder_funcs; 171 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
169 172 if (encoder->crtc == crtc) {
170 encoder_funcs = encoder->helper_private; 173 struct drm_encoder_helper_funcs *encoder_funcs;
174
175 encoder_funcs = encoder->helper_private;
176 mutex_lock(&dev->mode_config.mutex);
177 encoder_funcs->dpms(encoder, dpms_mode);
178 mutex_unlock(&dev->mode_config.mutex);
179 }
180 }
181 if (dpms_mode == DRM_MODE_DPMS_OFF) {
171 mutex_lock(&dev->mode_config.mutex); 182 mutex_lock(&dev->mode_config.mutex);
172 encoder_funcs->dpms(encoder, dpms_mode); 183 crtc_funcs->dpms(crtc, dpms_mode);
173 mutex_unlock(&dev->mode_config.mutex); 184 mutex_unlock(&dev->mode_config.mutex);
174 } 185 }
175 } 186 }
176 if (dpms_mode == DRM_MODE_DPMS_OFF) {
177 mutex_lock(&dev->mode_config.mutex);
178 crtc_funcs->dpms(crtc, dpms_mode);
179 mutex_unlock(&dev->mode_config.mutex);
180 }
181 } 187 }
182} 188}
183 189