aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2009-08-31 15:16:30 +1000
committerDave Airlie <airlied@linux.ie>2009-09-02 09:42:59 +1000
commita3a0544b2c84e1d7a2022b558ecf66d8c6a8dd93 (patch)
tree03debf96cac31e7661999d937f5ffaba6ada9e08
parented017d9fb17af3162f5acf922eb5731c541e1f3a (diff)
drm/kms: add explicit encoder disable function and detach harder.
For shared tv-out and VGA encoders, we really need to know if the encoder is just being switched off temporarily in blanking or if we are really disabling it hard. Also we need to try harder to disconnect encoders from unused connectors so we can share more efficently. (shared encoders stuff is coming in radeon tv-out support) Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c24
-rw-r--r--include/drm/drm_crtc_helper.h2
2 files changed, 22 insertions, 4 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 205349ea107..eea5e6c4099 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -260,13 +260,27 @@ EXPORT_SYMBOL(drm_helper_crtc_in_use);
void drm_helper_disable_unused_functions(struct drm_device *dev)
{
struct drm_encoder *encoder;
+ struct drm_connector *connector;
struct drm_encoder_helper_funcs *encoder_funcs;
struct drm_crtc *crtc;
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ if (!connector->encoder)
+ continue;
+ if (connector->status == connector_status_disconnected)
+ connector->encoder = NULL;
+ }
+
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
encoder_funcs = encoder->helper_private;
- if (!drm_helper_encoder_in_use(encoder))
- (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
+ if (!drm_helper_encoder_in_use(encoder)) {
+ if (encoder_funcs->disable)
+ (*encoder_funcs->disable)(encoder);
+ else
+ (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
+ }
+ /* disconnector encoder from any connector */
+ encoder->crtc = NULL;
}
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -411,7 +425,7 @@ static int drm_pick_crtcs(struct drm_device *dev,
c = 0;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- if ((connector->encoder->possible_crtcs & (1 << c)) == 0) {
+ if ((encoder->possible_crtcs & (1 << c)) == 0) {
c++;
continue;
}
@@ -496,8 +510,10 @@ static void drm_setup_crtcs(struct drm_device *dev)
mode->name, crtc->base.id);
crtc->desired_mode = mode;
connector->encoder->crtc = crtc;
- } else
+ } else {
connector->encoder->crtc = NULL;
+ connector->encoder = NULL;
+ }
i++;
}
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index e44a4f87303..4c8dacaf4f5 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -79,6 +79,8 @@ struct drm_encoder_helper_funcs {
/* detect for DAC style encoders */
enum drm_connector_status (*detect)(struct drm_encoder *encoder,
struct drm_connector *connector);
+ /* disable encoder when not in use - more explicit than dpms off */
+ void (*disable)(struct drm_encoder *encoder);
};
struct drm_connector_helper_funcs {