mirror of
https://github.com/torvalds/linux.git
synced 2024-11-16 09:02:00 +00:00
drm/exynos: fix display on issue
When crtc_funcs->dpms callback is called, exynos_crtc->dpms and exynos_encoder->dpms are changed to new mode. But if user requests dpms mode operation, OFF -> ON, when crtc's dpms callback is called, exynos_encoder->dpms is also changed to ON. This makes encoder's dpms callback call be ignored so display power couldn't become on again. This patch removes exynos_encoder->dpms changing and adds 'updated' variable to exynos_drm_encoder structure to avoid duplicated overlay updating. Signed-off-by: Inki Dae <inki.dae@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
This commit is contained in:
parent
4936b172d6
commit
44c91697fb
@ -374,6 +374,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
|
|||||||
exynos_connector->encoder_id = encoder->base.id;
|
exynos_connector->encoder_id = encoder->base.id;
|
||||||
exynos_connector->manager = manager;
|
exynos_connector->manager = manager;
|
||||||
exynos_connector->dpms = DRM_MODE_DPMS_OFF;
|
exynos_connector->dpms = DRM_MODE_DPMS_OFF;
|
||||||
|
connector->dpms = DRM_MODE_DPMS_OFF;
|
||||||
connector->encoder = encoder;
|
connector->encoder = encoder;
|
||||||
|
|
||||||
err = drm_mode_connector_attach_encoder(connector, encoder);
|
err = drm_mode_connector_attach_encoder(connector, encoder);
|
||||||
|
@ -43,12 +43,14 @@
|
|||||||
* @manager: specific encoder has its own manager to control a hardware
|
* @manager: specific encoder has its own manager to control a hardware
|
||||||
* appropriately and we can access a hardware drawing on this manager.
|
* appropriately and we can access a hardware drawing on this manager.
|
||||||
* @dpms: store the encoder dpms value.
|
* @dpms: store the encoder dpms value.
|
||||||
|
* @updated: indicate whether overlay data updating is needed or not.
|
||||||
*/
|
*/
|
||||||
struct exynos_drm_encoder {
|
struct exynos_drm_encoder {
|
||||||
struct drm_crtc *old_crtc;
|
struct drm_crtc *old_crtc;
|
||||||
struct drm_encoder drm_encoder;
|
struct drm_encoder drm_encoder;
|
||||||
struct exynos_drm_manager *manager;
|
struct exynos_drm_manager *manager;
|
||||||
int dpms;
|
int dpms;
|
||||||
|
bool updated;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode)
|
static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode)
|
||||||
@ -85,7 +87,9 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
|
|||||||
switch (mode) {
|
switch (mode) {
|
||||||
case DRM_MODE_DPMS_ON:
|
case DRM_MODE_DPMS_ON:
|
||||||
if (manager_ops && manager_ops->apply)
|
if (manager_ops && manager_ops->apply)
|
||||||
manager_ops->apply(manager->dev);
|
if (!exynos_encoder->updated)
|
||||||
|
manager_ops->apply(manager->dev);
|
||||||
|
|
||||||
exynos_drm_connector_power(encoder, mode);
|
exynos_drm_connector_power(encoder, mode);
|
||||||
exynos_encoder->dpms = mode;
|
exynos_encoder->dpms = mode;
|
||||||
break;
|
break;
|
||||||
@ -94,6 +98,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
|
|||||||
case DRM_MODE_DPMS_OFF:
|
case DRM_MODE_DPMS_OFF:
|
||||||
exynos_drm_connector_power(encoder, mode);
|
exynos_drm_connector_power(encoder, mode);
|
||||||
exynos_encoder->dpms = mode;
|
exynos_encoder->dpms = mode;
|
||||||
|
exynos_encoder->updated = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DRM_ERROR("unspecified mode %d\n", mode);
|
DRM_ERROR("unspecified mode %d\n", mode);
|
||||||
@ -205,13 +210,22 @@ static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
|
|||||||
|
|
||||||
static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
|
static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
|
||||||
{
|
{
|
||||||
struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
|
struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
|
||||||
|
struct exynos_drm_manager *manager = exynos_encoder->manager;
|
||||||
struct exynos_drm_manager_ops *manager_ops = manager->ops;
|
struct exynos_drm_manager_ops *manager_ops = manager->ops;
|
||||||
|
|
||||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||||
|
|
||||||
if (manager_ops && manager_ops->commit)
|
if (manager_ops && manager_ops->commit)
|
||||||
manager_ops->commit(manager->dev);
|
manager_ops->commit(manager->dev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this will avoid one issue that overlay data is updated to
|
||||||
|
* real hardware two times.
|
||||||
|
* And this variable will be used to check if the data was
|
||||||
|
* already updated or not by exynos_drm_encoder_dpms function.
|
||||||
|
*/
|
||||||
|
exynos_encoder->updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
|
static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
|
||||||
@ -400,19 +414,6 @@ void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
|
|||||||
if (manager_ops && manager_ops->dpms)
|
if (manager_ops && manager_ops->dpms)
|
||||||
manager_ops->dpms(manager->dev, mode);
|
manager_ops->dpms(manager->dev, mode);
|
||||||
|
|
||||||
/*
|
|
||||||
* set current mode to new one so that data aren't updated into
|
|
||||||
* registers by drm_helper_connector_dpms two times.
|
|
||||||
*
|
|
||||||
* in case that drm_crtc_helper_set_mode() is called,
|
|
||||||
* overlay_ops->commit() and manager_ops->commit() callbacks
|
|
||||||
* can be called two times, first at drm_crtc_helper_set_mode()
|
|
||||||
* and second at drm_helper_connector_dpms().
|
|
||||||
* so with this setting, when drm_helper_connector_dpms() is called
|
|
||||||
* encoder->funcs->dpms() will be ignored.
|
|
||||||
*/
|
|
||||||
exynos_encoder->dpms = mode;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if this condition is ok then it means that the crtc is already
|
* if this condition is ok then it means that the crtc is already
|
||||||
* detached from encoder and last function for detaching is properly
|
* detached from encoder and last function for detaching is properly
|
||||||
|
Loading…
Reference in New Issue
Block a user