Files
gk-sdk/source/gmp/usr/pm/xmedia_pm.c
T

341 lines
7.3 KiB
C

/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#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(&param);
}
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 */