]> granicus.if.org Git - esp-idf/commitdiff
I2S: Enable Power Management locks
authorSachin Parekh <sachin.parekh@espressif.com>
Fri, 22 Feb 2019 12:17:42 +0000 (17:47 +0530)
committerSachin Parekh <sachin.parekh@espressif.com>
Wed, 21 Aug 2019 12:45:41 +0000 (18:15 +0530)
Acquires PM_APB_FREQ_MAX lock when carrying any transaction on I2S if
Power Management Framework is enabled.

Signed-off-by: Sachin Parekh <sachin.parekh@espressif.com>
components/driver/i2s.c

index 0d33a45b9f1d3baf4cdeb29816eacf164ea61fe2..1d050f8241ff4eecfbe82b92300b38442cf78498 100644 (file)
 #include "esp_intr.h"
 #include "esp_err.h"
 #include "esp_log.h"
+#include "esp_pm.h"
 
 static const char* I2S_TAG = "I2S";
+
 #define I2S_CHECK(a, str, ret) if (!(a)) {                                              \
         ESP_LOGE(I2S_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str);       \
         return (ret);                                                                   \
@@ -88,6 +90,9 @@ typedef struct {
     bool use_apll;               /*!< I2S use APLL clock */
     bool tx_desc_auto_clear;    /*!< I2S auto clear tx descriptor on underflow */
     int fixed_mclk;             /*!< I2S fixed MLCK clock */
+#ifdef CONFIG_PM_ENABLE
+    esp_pm_lock_handle_t pm_lock;
+#endif
 } i2s_obj_t;
 
 static i2s_obj_t *p_i2s_obj[I2S_NUM_MAX] = {0};
@@ -528,7 +533,6 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg)
             }
             xQueueSendFromISR(p_i2s->i2s_queue, (void * )&i2s_event, &high_priority_task_awoken);
         }
-
     }
 
     if (i2s_reg->int_st.in_suc_eof && p_i2s->rx) {
@@ -1060,6 +1064,14 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config,
         p_i2s_obj[i2s_num]->bytes_per_sample = 0; // Not initialized yet
         p_i2s_obj[i2s_num]->channel_num = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 2 : 1;
 
+#ifdef CONFIG_PM_ENABLE
+    err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "i2s_driver",
+            &p_i2s_obj[i2s_num]->pm_lock);
+    if (err != ESP_OK) {
+        return err;
+    }
+
+#endif //CONFIG_PM_ENABLE
         //To make sure hardware is enabled before any hardware register operations.
         if (i2s_num == I2S_NUM_1) {
             periph_module_enable(PERIPH_I2S1_MODULE);
@@ -1070,6 +1082,11 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config,
         //initial interrupt
         err = i2s_isr_register(i2s_num, i2s_config->intr_alloc_flags, i2s_intr_handler_default, p_i2s_obj[i2s_num], &p_i2s_obj[i2s_num]->i2s_isr_handle);
         if (err != ESP_OK) {
+#ifdef CONFIG_PM_ENABLE
+            if (p_i2s_obj[i2s_num]->pm_lock) {
+                esp_pm_lock_delete(p_i2s_obj[i2s_num]->pm_lock);
+            }
+#endif
             free(p_i2s_obj[i2s_num]);
             p_i2s_obj[i2s_num] = NULL;
             ESP_LOGE(I2S_TAG, "Register I2S Interrupt error");
@@ -1125,6 +1142,11 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num)
     if(p_i2s_obj[i2s_num]->use_apll) {
         rtc_clk_apll_enable(0, 0, 0, 0, 0);
     }
+#ifdef CONFIG_PM_ENABLE
+    if (p_i2s_obj[i2s_num]->pm_lock) {
+            esp_pm_lock_delete(p_i2s_obj[i2s_num]->pm_lock);
+    }
+#endif
 
     free(p_i2s_obj[i2s_num]);
     p_i2s_obj[i2s_num] = NULL;
@@ -1158,6 +1180,9 @@ esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *by
     I2S_CHECK((size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_ERR_INVALID_ARG);
     I2S_CHECK((p_i2s_obj[i2s_num]->tx), "tx NULL", ESP_ERR_INVALID_ARG);
     xSemaphoreTake(p_i2s_obj[i2s_num]->tx->mux, (portTickType)portMAX_DELAY);
+#ifdef CONFIG_PM_ENABLE
+    esp_pm_lock_acquire(p_i2s_obj[i2s_num]->pm_lock);
+#endif
     src_byte = (char *)src;
     while (size > 0) {
         if (p_i2s_obj[i2s_num]->tx->rw_pos == p_i2s_obj[i2s_num]->tx->buf_size || p_i2s_obj[i2s_num]->tx->curr_ptr == NULL) {
@@ -1179,6 +1204,10 @@ esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *by
         p_i2s_obj[i2s_num]->tx->rw_pos += bytes_can_write;
         (*bytes_written) += bytes_can_write;
     }
+#ifdef CONFIG_PM_ENABLE
+    esp_pm_lock_release(p_i2s_obj[i2s_num]->pm_lock);
+#endif
+
     xSemaphoreGive(p_i2s_obj[i2s_num]->tx->mux);
     return ESP_OK;
 }
@@ -1289,6 +1318,9 @@ esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_re
     I2S_CHECK((size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_ERR_INVALID_ARG);
     I2S_CHECK((p_i2s_obj[i2s_num]->rx), "rx NULL", ESP_ERR_INVALID_ARG);
     xSemaphoreTake(p_i2s_obj[i2s_num]->rx->mux, (portTickType)portMAX_DELAY);
+#ifdef CONFIG_PM_ENABLE
+    esp_pm_lock_acquire(p_i2s_obj[i2s_num]->pm_lock);
+#endif
     while (size > 0) {
         if (p_i2s_obj[i2s_num]->rx->rw_pos == p_i2s_obj[i2s_num]->rx->buf_size || p_i2s_obj[i2s_num]->rx->curr_ptr == NULL) {
             if (xQueueReceive(p_i2s_obj[i2s_num]->rx->queue, &p_i2s_obj[i2s_num]->rx->curr_ptr, ticks_to_wait) == pdFALSE) {
@@ -1308,6 +1340,9 @@ esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_re
         p_i2s_obj[i2s_num]->rx->rw_pos += bytes_can_read;
         (*bytes_read) += bytes_can_read;
     }
+#ifdef CONFIG_PM_ENABLE
+    esp_pm_lock_release(p_i2s_obj[i2s_num]->pm_lock);
+#endif
     xSemaphoreGive(p_i2s_obj[i2s_num]->rx->mux);
     return ESP_OK;
 }
@@ -1337,5 +1372,3 @@ int i2s_pop_sample(i2s_port_t i2s_num, void *sample, TickType_t ticks_to_wait)
         return bytes_pop;
     }
 }
-
-