add tdm_output_set_dpms_async 40/139440/1
authorBoram Park <boram1288.park@samsung.com>
Wed, 19 Jul 2017 03:23:44 +0000 (12:23 +0900)
committerBoram Park <boram1288.park@samsung.com>
Wed, 19 Jul 2017 03:26:50 +0000 (12:26 +0900)
Change-Id: I9775ea2e5e78e8a4b11ec85b2b7481b670959b13

include/tdm.h
include/tdm_backend.h
src/tdm_output.c
src/tdm_private.h

index 29c819300a8a365fe308e4d39e07af2dbb628454..a7695c16f06a131ac4a4ad414d132fe5cf656caa 100644 (file)
@@ -524,14 +524,31 @@ tdm_error
 tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode);
 
 /**
- * @brief Set DPMS of a output object
+ * @brief Set DPMS of a output object synchronously
  * @param[in] output A output object
  * @param[in] dpms_value DPMS value
  * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ * @see tdm_output_set_dpms_async
  */
 tdm_error
 tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value);
 
+/**
+ * @brief Set DPMS of a output object asynchronously
+ * @details This function can be used when a output supports the asynchronous DPMS
+ * control. The output has #TDM_OUTPUT_CAPABILITY_ASYNC_DPMS flags which
+ * #tdm_output_get_capabilities returns. If an output change handler is added with
+ * #tdm_output_add_change_handler, the output change handler will be called when
+ * the DPMS status is changed indeed.
+ * @param[in] output A output object
+ * @param[in] dpms_value DPMS value
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ * @see tdm_output_add_change_handler, tdm_output_set_dpms,
+ *      tdm_output_get_capabilities, #TDM_OUTPUT_CAPABILITY_ASYNC_DPMS.
+ */
+tdm_error
+tdm_output_set_dpms_async(tdm_output *output, tdm_output_dpms dpms_value);
+
 /**
  * @brief Get DPMS of a output object
  * @param[in] output A output object
index 0949372c7ab7bf5e56f80d860612cd1ebfb2bd63..2de8c7b35879f97a4950289c03277e5a15d1b93f 100644 (file)
@@ -451,7 +451,7 @@ typedef struct _tdm_func_output {
                                                                                   tdm_output_commit_handler func);
 
        /**
-        * @brief Set DPMS of a output object
+        * @brief Set DPMS of a output object synchronously
         * @param[in] output A output object
         * @param[in] dpms_value DPMS value
         * @return #TDM_ERROR_NONE if success. Otherwise, error value.
@@ -512,18 +512,35 @@ typedef struct _tdm_func_output {
 
        /**
         * @brief Set a output dpms handler
-        * @details A backend module needs to call the output dpms handler when the
-        * output DPMS has been changed to let the TDM frontend know the change.
+        * @details This function can be NULL if an output doesn't support asynchronous
+        * DPMS control. Otherwise, a backend module needs to call the output dpms handler
+        * to let the TDM frontend know the output DPMS change indeed.
         * @param[in] output A output object
         * @param[in] func A output dpms handler
         * @param[in] user_data The user data
         * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+        * @see #output_set_dpms_async, #TDM_OUTPUT_CAPABILITY_ASYNC_DPMS
         * @since 1.4.0
         */
        tdm_error (*output_set_dpms_handler)(tdm_output *output,
                                                                                 tdm_output_dpms_handler func,
                                                                                 void *user_data);
-       void (*reserved2)(void);
+
+       /**
+        * @brief Set DPMS of a output object asynchronously
+        * @param[in] output A output object
+        * @details This function can be NULL if an output doesn't support asynchronous
+        * DPMS control. Otherwise, an output should have #TDM_OUTPUT_CAPABILITY_ASYNC_DPMS
+        * flags which #output_get_capability returns. And if a output dpms handler is added with
+        * #output_set_dpms_handler, a backend module needs to call the output dpms handler
+        * to let the TDM frontend know the output DPMS change indeed.
+        * @param[in] dpms_value DPMS value
+        * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+        * @see #output_set_dpms_handler, #TDM_OUTPUT_CAPABILITY_ASYNC_DPMS
+        * @since 1.7.0
+        */
+       tdm_error (*output_set_dpms_async)(tdm_output *output, tdm_output_dpms dpms_value);
+
        void (*reserved3)(void);
        void (*reserved4)(void);
        void (*reserved5)(void);
index 62ba065a3ef8c9a45c39130e0ad76bfb4be5f9ac..8b7abd480774413f5e89bebac394201a8d4bf8aa 100644 (file)
@@ -1087,6 +1087,7 @@ tdm_output_cb_dpms(tdm_output *output_backend, tdm_output_dpms dpms, void *user_
        }
 
        private_output->current_dpms_value = dpms;
+       private_output->waiting_dpms_change = 0;
 
        TDM_INFO("output(%d) dpms %s", private_output->pipe, tdm_dpms_str(dpms));
 
@@ -1108,6 +1109,12 @@ tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
 
        _pthread_mutex_lock(&private_display->lock);
 
+       if (private_output->waiting_dpms_change) {
+               TDM_ERR("DPMS is not changed yet. Can't be changed twice");
+               _pthread_mutex_unlock(&private_display->lock);
+               return TDM_ERROR_BAD_REQUEST;
+       }
+
        if (private_output->current_dpms_value == dpms_value) {
                _pthread_mutex_unlock(&private_display->lock);
                return TDM_ERROR_NONE;
@@ -1132,30 +1139,16 @@ tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
 
        func_output = &private_display->func_output;
 
-       if (!func_output->output_set_dpms) {
-               _pthread_mutex_unlock(&private_display->lock);
-               private_output->current_dpms_value = dpms_value;
-               TDM_INFO("output(%d) dpms %s", private_output->pipe, tdm_dpms_str(dpms_value));
+       if (func_output->output_set_dpms)
+               ret = func_output->output_set_dpms(private_output->output_backend, dpms_value);
+       else {
+               ret = TDM_ERROR_NONE;
                TDM_WRN("not implemented!!");
-               return TDM_ERROR_NONE;
+               goto done;
        }
 
-       if (func_output->output_set_dpms_handler) {
-               if (!private_output->regist_dpms_cb) {
-                       private_output->regist_dpms_cb = 1;
-                       ret = func_output->output_set_dpms_handler(private_output->output_backend,
-                                       tdm_output_cb_dpms, private_output);
-                       if (ret != TDM_ERROR_NONE) {
-                               _pthread_mutex_unlock(&private_display->lock);
-                               TDM_ERR("Can't set the dpms handler!!");
-                               return ret;
-                       }
-               }
-       }
-
-       ret = func_output->output_set_dpms(private_output->output_backend, dpms_value);
-
-       if (ret == TDM_ERROR_NONE && !func_output->output_set_dpms_handler) {
+done:
+       if (ret == TDM_ERROR_NONE) {
                tdm_value value;
 
                private_output->current_dpms_value = dpms_value;
@@ -1179,6 +1172,67 @@ tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
        return ret;
 }
 
+EXTERN tdm_error
+tdm_output_set_dpms_async(tdm_output *output, tdm_output_dpms dpms_value)
+{
+       tdm_func_output *func_output;
+       OUTPUT_FUNC_ENTRY();
+
+       if (!(private_output->caps.capabilities & TDM_OUTPUT_CAPABILITY_ASYNC_DPMS)) {
+               TDM_ERR("output doesn't support the asynchronous DPMS control!");
+               return TDM_ERROR_BAD_REQUEST;
+       }
+
+       if (dpms_value > TDM_OUTPUT_DPMS_OFF)
+               dpms_value = TDM_OUTPUT_DPMS_OFF;
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       if (private_output->waiting_dpms_change) {
+               TDM_ERR("DPMS is not changed yet. Can't be changed twice");
+               _pthread_mutex_unlock(&private_display->lock);
+               return TDM_ERROR_BAD_REQUEST;
+       }
+
+       if (private_output->current_dpms_value == dpms_value) {
+               _pthread_mutex_unlock(&private_display->lock);
+               return TDM_ERROR_NONE;
+       }
+
+       func_output = &private_display->func_output;
+       if (!func_output->output_set_dpms_handler) {
+               TDM_ERR("not implemented: output_set_dpms_handler");
+               _pthread_mutex_unlock(&private_display->lock);
+               return TDM_ERROR_NOT_IMPLEMENTED;
+       }
+
+       if (!func_output->output_set_dpms_async) {
+               TDM_ERR("not implemented: output_set_dpms_async");
+               _pthread_mutex_unlock(&private_display->lock);
+               return TDM_ERROR_NOT_IMPLEMENTED;
+       }
+
+       if (!private_output->regist_dpms_cb) {
+               private_output->regist_dpms_cb = 1;
+               ret = func_output->output_set_dpms_handler(private_output->output_backend,
+                               tdm_output_cb_dpms, private_output);
+               if (ret != TDM_ERROR_NONE) {
+                       _pthread_mutex_unlock(&private_display->lock);
+                       TDM_ERR("Can't set the dpms handler!!");
+                       return ret;
+               }
+       }
+
+       ret = func_output->output_set_dpms_async(private_output->output_backend, dpms_value);
+
+       if (ret == TDM_ERROR_NONE)
+               private_output->waiting_dpms_change = 1;
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return ret;
+}
+
 INTERN tdm_error
 tdm_output_get_dpms_internal(tdm_output *output, tdm_output_dpms *dpms_value)
 {
index 4ea122d62adaae484f3b02e5f4bf07edf39809e1..12ac38574fcc3baca560548158f121cc25a7b0c5 100644 (file)
@@ -193,6 +193,7 @@ struct _tdm_private_output {
 
        unsigned int pipe;
        tdm_output_dpms current_dpms_value;
+       unsigned int waiting_dpms_change;
        const tdm_output_mode *current_mode;
 
        int regist_vblank_cb;