drm: correctly update connector DPMS status in drm_fb_helper
Jesse Barnes [Fri, 2 Jul 2010 17:48:08 +0000 (10:48 -0700)]
We don't currently update the DPMS status of the connector (both in the
connector itself and the connector's DPMS property) in the fb helper
code.  This means that if the kernel FB core has blanked the screen,
sysfs will still show a DPMS status of "on".  It also means that when X
starts, it will try to light up the connectors, but the drm_crtc_helper
code will ignore the DPMS change since according to the connector, the
DPMS status is already on.

Fixes https://bugs.freedesktop.org/show_bug.cgi?id=28436 (the annoying
"my screen was blanked when I started X and now it won't light up" bug).

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Dave Airlie <airlied@redhat.com>

drivers/gpu/drm/drm_fb_helper.c

index 1f2cc6b..7196620 100644 (file)
@@ -315,8 +315,9 @@ static void drm_fb_helper_on(struct fb_info *info)
        struct drm_device *dev = fb_helper->dev;
        struct drm_crtc *crtc;
        struct drm_crtc_helper_funcs *crtc_funcs;
+       struct drm_connector *connector;
        struct drm_encoder *encoder;
-       int i;
+       int i, j;
 
        /*
         * For each CRTC in this fb, turn the crtc on then,
@@ -332,7 +333,14 @@ static void drm_fb_helper_on(struct fb_info *info)
 
                crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
 
-
+               /* Walk the connectors & encoders on this fb turning them on */
+               for (j = 0; j < fb_helper->connector_count; j++) {
+                       connector = fb_helper->connector_info[j]->connector;
+                       connector->dpms = DRM_MODE_DPMS_ON;
+                       drm_connector_property_set_value(connector,
+                                                        dev->mode_config.dpms_property,
+                                                        DRM_MODE_DPMS_ON);
+               }
                /* Found a CRTC on this fb, now find encoders */
                list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
                        if (encoder->crtc == crtc) {
@@ -352,8 +360,9 @@ static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)
        struct drm_device *dev = fb_helper->dev;
        struct drm_crtc *crtc;
        struct drm_crtc_helper_funcs *crtc_funcs;
+       struct drm_connector *connector;
        struct drm_encoder *encoder;
-       int i;
+       int i, j;
 
        /*
         * For each CRTC in this fb, find all associated encoders
@@ -367,6 +376,14 @@ static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)
                if (!crtc->enabled)
                        continue;
 
+               /* Walk the connectors on this fb and mark them off */
+               for (j = 0; j < fb_helper->connector_count; j++) {
+                       connector = fb_helper->connector_info[j]->connector;
+                       connector->dpms = dpms_mode;
+                       drm_connector_property_set_value(connector,
+                                                        dev->mode_config.dpms_property,
+                                                        dpms_mode);
+               }
                /* Found a CRTC on this fb, now find encoders */
                list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
                        if (encoder->crtc == crtc) {