diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-06-11 01:58:01 -0700 | 
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-06-11 01:58:01 -0700 | 
| commit | 4894e4aca82aca927d0404ce61f021f790de4b1e (patch) | |
| tree | bbe0d083829f5858295298f188d885367cf4b1f6 /drivers/gpu/drm/drm_crtc_helper.c | |
| parent | 05e882f890038c702a4f15d385135d03cf74ad48 (diff) | |
| parent | 07a2039b8eb0af4ff464efd3dfd95de5c02648c6 (diff) | |
| download | olio-linux-3.10-4894e4aca82aca927d0404ce61f021f790de4b1e.tar.xz olio-linux-3.10-4894e4aca82aca927d0404ce61f021f790de4b1e.zip  | |
Merge commit 'v2.6.30' into next
Diffstat (limited to 'drivers/gpu/drm/drm_crtc_helper.c')
| -rw-r--r-- | drivers/gpu/drm/drm_crtc_helper.c | 109 | 
1 files changed, 107 insertions, 2 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 45890447fee..a6f73f1e99d 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -199,6 +199,29 @@ static void drm_helper_add_std_modes(struct drm_device *dev,  }  /** + * drm_helper_encoder_in_use - check if a given encoder is in use + * @encoder: encoder to check + * + * LOCKING: + * Caller must hold mode config lock. + * + * Walk @encoders's DRM device's mode_config and see if it's in use. + * + * RETURNS: + * True if @encoder is part of the mode_config, false otherwise. + */ +bool drm_helper_encoder_in_use(struct drm_encoder *encoder) +{ +	struct drm_connector *connector; +	struct drm_device *dev = encoder->dev; +	list_for_each_entry(connector, &dev->mode_config.connector_list, head) +		if (connector->encoder == encoder) +			return true; +	return false; +} +EXPORT_SYMBOL(drm_helper_encoder_in_use); + +/**   * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config   * @crtc: CRTC to check   * @@ -216,7 +239,7 @@ bool drm_helper_crtc_in_use(struct drm_crtc *crtc)  	struct drm_device *dev = crtc->dev;  	/* FIXME: Locking around list access? */  	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) -		if (encoder->crtc == crtc) +		if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder))  			return true;  	return false;  } @@ -240,7 +263,7 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)  	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {  		encoder_funcs = encoder->helper_private; -		if (!encoder->crtc) +		if (!drm_helper_encoder_in_use(encoder))  			(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);  	} @@ -935,6 +958,88 @@ bool drm_helper_initial_config(struct drm_device *dev)  }  EXPORT_SYMBOL(drm_helper_initial_config); +static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder) +{ +	int dpms = DRM_MODE_DPMS_OFF; +	struct drm_connector *connector; +	struct drm_device *dev = encoder->dev; + +	list_for_each_entry(connector, &dev->mode_config.connector_list, head) +		if (connector->encoder == encoder) +			if (connector->dpms < dpms) +				dpms = connector->dpms; +	return dpms; +} + +static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc) +{ +	int dpms = DRM_MODE_DPMS_OFF; +	struct drm_connector *connector; +	struct drm_device *dev = crtc->dev; + +	list_for_each_entry(connector, &dev->mode_config.connector_list, head) +		if (connector->encoder && connector->encoder->crtc == crtc) +			if (connector->dpms < dpms) +				dpms = connector->dpms; +	return dpms; +} + +/** + * drm_helper_connector_dpms + * @connector affected connector + * @mode DPMS mode + * + * Calls the low-level connector DPMS function, then + * calls appropriate encoder and crtc DPMS functions as well + */ +void drm_helper_connector_dpms(struct drm_connector *connector, int mode) +{ +	struct drm_encoder *encoder = connector->encoder; +	struct drm_crtc *crtc = encoder ? encoder->crtc : NULL; +	int old_dpms; + +	if (mode == connector->dpms) +		return; + +	old_dpms = connector->dpms; +	connector->dpms = mode; + +	/* from off to on, do crtc then encoder */ +	if (mode < old_dpms) { +		if (crtc) { +			struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; +			if (crtc_funcs->dpms) +				(*crtc_funcs->dpms) (crtc, +						     drm_helper_choose_crtc_dpms(crtc)); +		} +		if (encoder) { +			struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; +			if (encoder_funcs->dpms) +				(*encoder_funcs->dpms) (encoder, +							drm_helper_choose_encoder_dpms(encoder)); +		} +	} + +	/* from on to off, do encoder then crtc */ +	if (mode > old_dpms) { +		if (encoder) { +			struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; +			if (encoder_funcs->dpms) +				(*encoder_funcs->dpms) (encoder, +							drm_helper_choose_encoder_dpms(encoder)); +		} +		if (crtc) { +			struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; +			if (crtc_funcs->dpms) +				(*crtc_funcs->dpms) (crtc, +						     drm_helper_choose_crtc_dpms(crtc)); +		} +	} + +	return; +} +EXPORT_SYMBOL(drm_helper_connector_dpms); +  /**   * drm_hotplug_stage_two   * @dev DRM device  |