|
@@ -43,12 +43,14 @@
|
|
|
* @manager: specific encoder has its own manager to control a hardware
|
|
|
* appropriately and we can access a hardware drawing on this manager.
|
|
|
* @dpms: store the encoder dpms value.
|
|
|
+ * @updated: indicate whether overlay data updating is needed or not.
|
|
|
*/
|
|
|
struct exynos_drm_encoder {
|
|
|
struct drm_crtc *old_crtc;
|
|
|
struct drm_encoder drm_encoder;
|
|
|
struct exynos_drm_manager *manager;
|
|
|
- int dpms;
|
|
|
+ int dpms;
|
|
|
+ bool updated;
|
|
|
};
|
|
|
|
|
|
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) {
|
|
|
case DRM_MODE_DPMS_ON:
|
|
|
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_encoder->dpms = mode;
|
|
|
break;
|
|
@@ -94,6 +98,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
|
|
|
case DRM_MODE_DPMS_OFF:
|
|
|
exynos_drm_connector_power(encoder, mode);
|
|
|
exynos_encoder->dpms = mode;
|
|
|
+ exynos_encoder->updated = false;
|
|
|
break;
|
|
|
default:
|
|
|
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)
|
|
|
{
|
|
|
- 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;
|
|
|
|
|
|
DRM_DEBUG_KMS("%s\n", __FILE__);
|
|
|
|
|
|
if (manager_ops && manager_ops->commit)
|
|
|
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)
|
|
@@ -400,19 +414,6 @@ void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
|
|
|
if (manager_ops && manager_ops->dpms)
|
|
|
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
|
|
|
* detached from encoder and last function for detaching is properly
|