/* * Copyright (c) XMEDIA. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #include "common.h" #include "xmedia_debug.h" #include "xmedia_errcode.h" #include "xmedia_pm.h" #include "pm_aux.h" #include "pm_ddr.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #define PM_USR_TRACE(level, fmt, ...) \ do { \ MODULE_TRACE(level, MOD_ID_PM, "[Func]:%s [Line]:%d [Info]:" fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ } while (0) #define XMEDIA_PM_INIT _IO('n', CMD_PM_INIT) #define XMEDIA_PM_DEINIT _IO('n', CMD_PM_DEINIT) #define XMEDIA_PM_GET_WAKEUP_SOURCE _IOWR('n', CMD_PM_GET_WK_SOURCE, xmedia_pm_wakeup_source) #define XMEDIA_PM_GET_ATTR _IOWR('n', CMD_PM_GET_ALL_ATTR, xmedia_pm_attr) #define XMEDIA_PM_SET_ATTR _IOWR('n', CMD_PM_SET_ALL_ATTR, xmedia_pm_attr) #define XMEDIA_PM_SET_AUX _IOWR('n', CMD_PM_SET_AUX, struct aux_mem) #define XMEDIA_PM_GET_DDR_PARAM _IOR('n', CMD_PM_GET_DDR_PARAM, struct lpds_param) #define XMEDIA_PM_GET_WAKEUP_INFO _IOWR('n', CMD_PM_GET_WK_INFO, xmedia_pm_wakeup_info) #define XMEDIA_PM_GET_RTC_INFO _IOR('n', CMD_PM_GET_RTC_INFO, xmedia_pm_rtc_info) typedef enum { CMD_PM_INIT = 0, CMD_PM_DEINIT, CMD_PM_SET_ALL_ATTR, CMD_PM_GET_ALL_ATTR, CMD_PM_GET_RTC_ATTR, CMD_PM_SET_RTC_ATTR, CMD_PM_GET_WK_ATTR, CMD_PM_SET_WK_ATTR, CMD_PM_GET_WK_SOURCE, CMD_PM_SET_AUX, CMD_PM_GET_DDR_PARAM, CMD_PM_GET_RTC_INFO, CMD_PM_GET_WK_INFO, CMD_PM_END = 0xFFFF, } xmedia_pm_ioctl_cmd; static xmedia_s32 g_pm_mod_fd = -1; static xmedia_s32 g_suspend_fd = -1; static pthread_mutex_t g_pm_mutex = PTHREAD_MUTEX_INITIALIZER; static bool g_pm_init = XMEDIA_FALSE; #define PM_MUTEX_LOCK() \ do { \ (void)pthread_mutex_lock(&g_pm_mutex); \ } while (0) #define PM_MUTEX_UNLOCK() \ do { \ (void)pthread_mutex_unlock(&g_pm_mutex); \ } while (0) #define PM_CHECK_INIT_RETURN() \ do { \ PM_MUTEX_LOCK(); \ if (g_pm_init != XMEDIA_TRUE) { \ PM_USR_TRACE(MODULE_DBG_ERR, "pm not init!\n"); \ PM_MUTEX_UNLOCK(); \ return XMEDIA_ERRCODE_NOT_INIT; \ } \ PM_MUTEX_UNLOCK(); \ } while (0) xmedia_s32 xmedia_pm_init(xmedia_void) { xmedia_pm_init_param param; param.type = PM_INIT_TYPE_NORMAL; return xmedia_pm_init_ext(¶m); } xmedia_s32 xmedia_pm_init_ext(xmedia_pm_init_param *param) { xmedia_s32 ret = XMEDIA_SUCCESS; struct aux_mem aux; if (param == NULL) return XMEDIA_ERRCODE_NULL_PTR; if (param->type >= PM_INIT_TYPE_MAX) return XMEDIA_ERRCODE_INVALID_PARAM; if (g_pm_init == XMEDIA_TRUE) return XMEDIA_ERRCODE_BUSY; if ((!is_ram_off_str()) && (param->type == PM_INIT_TYPE_STR)) { if (read_aux_to_ddr(&aux) != XMEDIA_SUCCESS) return XMEDIA_ERRCODE_NOT_READY; } PM_MUTEX_LOCK(); if (param->type == PM_INIT_TYPE_STR) { if (g_suspend_fd < 0) { g_suspend_fd = open("/sys/power/state", O_RDWR | O_SYNC); if (g_suspend_fd < 0) { PM_USR_TRACE(MODULE_DBG_ERR, "open /dev/power/state err, ret:%d \n", g_suspend_fd); ret = XMEDIA_ERRCODE_OPEN_FAILED; goto UNLOCK; } } } if (g_pm_mod_fd < 0) { g_pm_mod_fd = open("/dev/pm", O_RDONLY); if (g_pm_mod_fd < 0) { PM_USR_TRACE(MODULE_DBG_ERR, "open /dev/pm err, ret:%d \n", g_pm_mod_fd); ret = XMEDIA_ERRCODE_OPEN_FAILED; goto UNLOCK; } ret = ioctl(g_pm_mod_fd, XMEDIA_PM_INIT, NULL, NULL); if (ret != XMEDIA_SUCCESS) { PM_USR_TRACE(MODULE_DBG_ERR, "drv pm init err\n"); goto UNLOCK; } if ((!is_ram_off_str()) && (param->type == PM_INIT_TYPE_STR)) { ret = ioctl(g_pm_mod_fd, XMEDIA_PM_SET_AUX, &aux, NULL); if (ret != XMEDIA_SUCCESS) { ioctl(g_pm_mod_fd, XMEDIA_PM_DEINIT, NULL, NULL); PM_USR_TRACE(MODULE_DBG_ERR, "drv set aux err\n"); goto UNLOCK; } } } g_pm_init = XMEDIA_TRUE; UNLOCK: PM_MUTEX_UNLOCK(); if (is_ram_off_str() && (param->type == PM_INIT_TYPE_STR)) { if (ret == XMEDIA_SUCCESS) { ret = ddr_param_check_and_save(); if (ret != XMEDIA_SUCCESS) { PM_USR_TRACE(MODULE_DBG_ERR, "ddr param check/save err ret=%d\n", ret); PM_MUTEX_LOCK(); g_pm_init = XMEDIA_FALSE; PM_MUTEX_UNLOCK(); } } } else { if (ret != XMEDIA_SUCCESS) aux_free_mem(); } if (ret != XMEDIA_SUCCESS) { PM_MUTEX_LOCK(); if (g_suspend_fd >= 0) { close(g_suspend_fd); g_suspend_fd = -1; } if (g_pm_mod_fd >= 0) { close(g_pm_mod_fd); g_pm_mod_fd = -1; } PM_MUTEX_UNLOCK(); } return ret; } xmedia_s32 xmedia_pm_deinit(xmedia_void) { xmedia_s32 ret = XMEDIA_SUCCESS; PM_CHECK_INIT_RETURN(); PM_MUTEX_LOCK(); ret = ioctl(g_pm_mod_fd, XMEDIA_PM_DEINIT, NULL, NULL); if (ret != XMEDIA_SUCCESS) { goto UNLOCK; } close(g_pm_mod_fd); g_pm_mod_fd = -1; close(g_suspend_fd); g_suspend_fd = -1; g_pm_init = XMEDIA_FALSE; UNLOCK: PM_MUTEX_UNLOCK(); if (!is_ram_off_str()) { aux_free_mem(); } return ret; } xmedia_s32 xmedia_pm_get_wakeup_source(xmedia_pm_wakeup_source *source) { xmedia_s32 ret = XMEDIA_SUCCESS; PM_CHECK_INIT_RETURN(); PM_MUTEX_LOCK(); if (source == XMEDIA_NULL) { PM_MUTEX_UNLOCK(); return XMEDIA_ERRCODE_NULL_PTR; } ret = ioctl(g_pm_mod_fd, XMEDIA_PM_GET_WAKEUP_SOURCE, (unsigned int)source, NULL); PM_MUTEX_UNLOCK(); return ret; } xmedia_s32 xmedia_pm_get_attr(xmedia_pm_attr *attr) { xmedia_s32 ret = XMEDIA_SUCCESS; PM_CHECK_INIT_RETURN(); PM_MUTEX_LOCK(); if (attr == XMEDIA_NULL) { PM_MUTEX_UNLOCK(); return XMEDIA_ERRCODE_NULL_PTR; } ret = ioctl(g_pm_mod_fd, XMEDIA_PM_GET_ATTR, (unsigned int)attr, NULL); PM_MUTEX_UNLOCK(); return ret; } xmedia_s32 xmedia_pm_set_attr(xmedia_pm_attr *attr) { xmedia_s32 ret = XMEDIA_FAILURE; PM_CHECK_INIT_RETURN(); PM_MUTEX_LOCK(); if (attr == XMEDIA_NULL) { PM_MUTEX_UNLOCK(); return XMEDIA_ERRCODE_NULL_PTR; } ret = ioctl(g_pm_mod_fd, XMEDIA_PM_SET_ATTR, (unsigned int)attr, NULL); PM_MUTEX_UNLOCK(); return ret; } xmedia_s32 xmedia_pm_get_ddr_param(struct lpds_param *p_lpds_param) { xmedia_s32 ret = XMEDIA_FAILURE; PM_CHECK_INIT_RETURN(); PM_MUTEX_LOCK(); if (p_lpds_param == XMEDIA_NULL) { PM_MUTEX_UNLOCK(); return XMEDIA_ERRCODE_NULL_PTR; } ret = ioctl(g_pm_mod_fd, XMEDIA_PM_GET_DDR_PARAM, (unsigned int)p_lpds_param, NULL); PM_MUTEX_UNLOCK(); return ret; } xmedia_s32 xmedia_pm_suspend(xmedia_void) { xmedia_s32 ret = XMEDIA_FAILURE; xmedia_char suspend_str[] = "mem"; PM_CHECK_INIT_RETURN(); PM_MUTEX_LOCK(); if (g_suspend_fd >= 0) { if (write(g_suspend_fd, suspend_str, strlen(suspend_str)) == strlen(suspend_str)) { ret = XMEDIA_SUCCESS; } else { ret = XMEDIA_ERRCODE_COPY_DATA_ERROR; } } PM_MUTEX_UNLOCK(); return ret; } xmedia_s32 xmedia_pm_get_rtc_info(xmedia_pm_rtc_info *rtc_info) { xmedia_s32 ret = XMEDIA_SUCCESS; PM_CHECK_INIT_RETURN(); PM_MUTEX_LOCK(); if (rtc_info == XMEDIA_NULL) { PM_MUTEX_UNLOCK(); return XMEDIA_ERRCODE_NULL_PTR; } ret = ioctl(g_pm_mod_fd, XMEDIA_PM_GET_RTC_INFO, (unsigned int)rtc_info, NULL); PM_MUTEX_UNLOCK(); return ret; } #ifdef __cplusplus } #endif /* __cplusplus */