2361 lines
58 KiB
C
2361 lines
58 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2019 MediaTek Inc.
|
|
*/
|
|
|
|
#define LOG_TAG "ddp_manager"
|
|
|
|
#include <linux/slab.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/spinlock.h>
|
|
|
|
#include "disp_helper.h"
|
|
#include "lcm_drv.h"
|
|
#include "ddp_reg.h"
|
|
#include "ddp_path.h"
|
|
#include "ddp_irq.h"
|
|
#include "ddp_drv.h"
|
|
#include "ddp_debug.h"
|
|
#include "ddp_manager.h"
|
|
#include "ddp_rdma.h"
|
|
#include "ddp_rdma_ex.h"
|
|
#include "ddp_ovl.h"
|
|
#include "ddp_color.h"
|
|
#include "ddp_clkmgr.h"
|
|
|
|
#include "ddp_log.h"
|
|
#include "disp_drv_platform.h"
|
|
|
|
/* #define __GED_NOTIFICATION_SUPPORT__ */
|
|
#ifdef __GED_NOTIFICATION_SUPPORT__
|
|
# include "ged.h"
|
|
#endif
|
|
|
|
static int ddp_manager_init;
|
|
#define DDP_MAX_MANAGER_HANDLE (DISP_MUTEX_DDP_COUNT+DISP_MUTEX_DDP_FIRST)
|
|
|
|
static CmdqDumpInfoCB cmdq_dump_callback_table[MAX_SESSION_COUNT];
|
|
static spinlock_t cmdq_dump_lock;
|
|
|
|
struct DPMGR_WQ_HANDLE {
|
|
unsigned int init;
|
|
enum DISP_PATH_EVENT event;
|
|
wait_queue_head_t wq;
|
|
unsigned long long data;
|
|
};
|
|
|
|
struct DDP_IRQ_EVENT_MAPPING {
|
|
enum DDP_IRQ_BIT irq_bit;
|
|
};
|
|
|
|
struct ddp_path_handle {
|
|
struct cmdqRecStruct *cmdqhandle;
|
|
int hwmutexid;
|
|
int power_state;
|
|
enum DDP_MODE mode;
|
|
struct mutex mutex_lock;
|
|
struct DDP_IRQ_EVENT_MAPPING irq_event_map[DISP_PATH_EVENT_NUM];
|
|
struct DPMGR_WQ_HANDLE wq_list[DISP_PATH_EVENT_NUM];
|
|
enum DDP_SCENARIO_ENUM scenario;
|
|
enum DISP_MODULE_ENUM mem_module;
|
|
struct disp_ddp_path_config last_config;
|
|
};
|
|
|
|
struct DDP_MANAGER_CONTEXT {
|
|
int handle_cnt;
|
|
int mutex_idx;
|
|
int power_state;
|
|
struct mutex mutex_lock;
|
|
int module_usage_table[DISP_MODULE_NUM];
|
|
struct ddp_path_handle *module_path_table[DISP_MODULE_NUM];
|
|
struct ddp_path_handle *handle_pool[DDP_MAX_MANAGER_HANDLE];
|
|
};
|
|
|
|
static bool ddp_valid_engine[DISP_MODULE_NUM] = {
|
|
[DISP_MODULE_OVL0] = 1,
|
|
[DISP_MODULE_OVL0_2L] = 1,
|
|
[DISP_MODULE_OVL1_2L] = 1,
|
|
[DISP_MODULE_RDMA0] = 1,
|
|
[DISP_MODULE_RDMA1] = 0,
|
|
[DISP_MODULE_WDMA0] = 1,
|
|
[DISP_MODULE_WDMA_VIRTUAL0] = 0,
|
|
[DISP_MODULE_WDMA_VIRTUAL1] = 0,
|
|
[DISP_MODULE_COLOR0] = 1,
|
|
[DISP_MODULE_CCORR0] = 1,
|
|
[DISP_MODULE_AAL0] = 1,
|
|
[DISP_MODULE_GAMMA0] = 1,
|
|
[DISP_MODULE_DITHER0] = 1,
|
|
[DISP_MODULE_DSI0] = 0,
|
|
[DISP_MODULE_DSI1] = 0,
|
|
[DISP_MODULE_DSIDUAL] = 0,
|
|
[DISP_MODULE_PWM0] = 0,
|
|
[DISP_MODULE_CONFIG] = 0,
|
|
[DISP_MODULE_MUTEX] = 0,
|
|
[DISP_MODULE_SMI_COMMON] = 0,
|
|
[DISP_MODULE_SMI_LARB0] = 0,
|
|
[DISP_MODULE_SMI_LARB1] = 0,
|
|
[DISP_MODULE_MIPI0] = 0,
|
|
[DISP_MODULE_MIPI1] = 0,
|
|
[DISP_MODULE_DPI] = 0,
|
|
[DISP_MODULE_RSZ0] = 1,
|
|
[DISP_MODULE_POSTMASK] = 1,
|
|
[DISP_MODULE_UNKNOWN] = 0,
|
|
};
|
|
|
|
int get_ddp_valid_engine(int module_num)
|
|
{
|
|
return ddp_valid_engine[module_num];
|
|
}
|
|
|
|
#define DEFAULT_IRQ_EVENT_SCENARIO (4)
|
|
|
|
static struct DDP_IRQ_EVENT_MAPPING
|
|
ddp_irq_event_list[DEFAULT_IRQ_EVENT_SCENARIO][DISP_PATH_EVENT_NUM] = {
|
|
{ /* ovl0 path */
|
|
{DDP_IRQ_RDMA0_DONE}, /* FRAME_DONE */
|
|
{DDP_IRQ_RDMA0_START}, /* FRAME_START */
|
|
{DDP_IRQ_RDMA0_REG_UPDATE}, /* FRAME_REG_UPDATE */
|
|
{DDP_IRQ_RDMA0_TARGET_LINE}, /* FRAME_TARGET_LINE */
|
|
{DDP_IRQ_WDMA0_FRAME_COMPLETE}, /* FRAME_COMPLETE */
|
|
{DDP_IRQ_RDMA0_TARGET_LINE}, /* FRAME_STOP */
|
|
{DDP_IRQ_RDMA0_REG_UPDATE}, /* IF_CMD_DONE */
|
|
{DDP_IRQ_DSI0_EXT_TE}, /* IF_VSYNC */
|
|
{DDP_IRQ_UNKNOWN}, /* TRIGER */
|
|
{DDP_IRQ_AAL0_OUT_END_FRAME}, /* AAL_OUT_END_EVENT */
|
|
},
|
|
{ /* ovl1 path */
|
|
{DDP_IRQ_RDMA1_DONE}, /* FRAME_DONE */
|
|
{DDP_IRQ_RDMA1_START}, /* FRAME_START */
|
|
{DDP_IRQ_RDMA1_REG_UPDATE}, /* FRAME_REG_UPDATE */
|
|
{DDP_IRQ_RDMA1_TARGET_LINE}, /* FRAME_TARGET_LINE */
|
|
{DDP_IRQ_WDMA0_FRAME_COMPLETE}, /* FRAME_COMPLETE */
|
|
{DDP_IRQ_RDMA1_TARGET_LINE}, /* FRAME_STOP */
|
|
{DDP_IRQ_RDMA1_REG_UPDATE}, /* IF_CMD_DONE */
|
|
{DDP_IRQ_DPI_VSYNC}, /* IF_VSYNC */
|
|
{DDP_IRQ_UNKNOWN}, /* TRIGER */
|
|
{DDP_IRQ_AAL0_OUT_END_FRAME}, /* AAL_OUT_END_EVENT */
|
|
},
|
|
{ /* rdma path */
|
|
{DDP_IRQ_RDMA1_DONE}, /* FRAME_DONE */
|
|
{DDP_IRQ_RDMA1_START}, /* FRAME_START */
|
|
{DDP_IRQ_RDMA1_REG_UPDATE}, /* FRAME_REG_UPDATE */
|
|
{DDP_IRQ_RDMA1_TARGET_LINE}, /* FRAME_TARGET_LINE */
|
|
{DDP_IRQ_UNKNOWN}, /* FRAME_COMPLETE */
|
|
{DDP_IRQ_RDMA1_TARGET_LINE}, /* FRAME_STOP */
|
|
{DDP_IRQ_RDMA1_REG_UPDATE}, /* IF_CMD_DONE */
|
|
{DDP_IRQ_RDMA1_TARGET_LINE}, /* IF_VSYNC */
|
|
{DDP_IRQ_UNKNOWN}, /* TRIGER */
|
|
{DDP_IRQ_UNKNOWN}, /* AAL_OUT_END_EVENT */
|
|
},
|
|
{ /* ovl0 path */
|
|
{DDP_IRQ_RDMA0_DONE}, /* FRAME_DONE */
|
|
{DDP_IRQ_MUTEX1_SOF}, /* FRAME_START */
|
|
{DDP_IRQ_RDMA0_REG_UPDATE}, /* FRAME_REG_UPDATE */
|
|
{DDP_IRQ_RDMA0_TARGET_LINE}, /* FRAME_TARGET_LINE */
|
|
{DDP_IRQ_WDMA0_FRAME_COMPLETE}, /* FRAME_COMPLETE */
|
|
{DDP_IRQ_RDMA0_TARGET_LINE}, /* FRAME_STOP */
|
|
{DDP_IRQ_RDMA0_REG_UPDATE}, /* IF_CMD_DONE */
|
|
{DDP_IRQ_DSI0_EXT_TE}, /* IF_VSYNC */
|
|
{DDP_IRQ_UNKNOWN}, /* TRIGER */
|
|
{DDP_IRQ_AAL0_OUT_END_FRAME}, /* AAL_OUT_END_EVENT */
|
|
}
|
|
};
|
|
|
|
static char *path_event_name(enum DISP_PATH_EVENT event)
|
|
{
|
|
switch (event) {
|
|
case DISP_PATH_EVENT_FRAME_START:
|
|
return "FRAME_START";
|
|
case DISP_PATH_EVENT_FRAME_DONE:
|
|
return "FRAME_DONE";
|
|
case DISP_PATH_EVENT_FRAME_REG_UPDATE:
|
|
return "REG_UPDATE";
|
|
case DISP_PATH_EVENT_FRAME_TARGET_LINE:
|
|
return "TARGET_LINE";
|
|
case DISP_PATH_EVENT_FRAME_COMPLETE:
|
|
return "FRAME COMPLETE";
|
|
case DISP_PATH_EVENT_FRAME_STOP:
|
|
return "FRAME_STOP";
|
|
case DISP_PATH_EVENT_IF_CMD_DONE:
|
|
return "FRAME_STOP";
|
|
case DISP_PATH_EVENT_IF_VSYNC:
|
|
return "VSYNC";
|
|
case DISP_PATH_EVENT_TRIGGER:
|
|
return "TRIGGER";
|
|
case DISP_PATH_EVENT_DELAYED_TRIGGER_33ms:
|
|
return "DELAY_TRIG";
|
|
default:
|
|
return "unknown event";
|
|
}
|
|
return "unknown event";
|
|
}
|
|
|
|
static struct DDP_MANAGER_CONTEXT *_get_context(void)
|
|
{
|
|
static int is_context_inited;
|
|
static struct DDP_MANAGER_CONTEXT context;
|
|
|
|
if (is_context_inited)
|
|
return &context;
|
|
|
|
memset((void *)&context, 0, sizeof(struct DDP_MANAGER_CONTEXT));
|
|
context.mutex_idx = (1 << DISP_MUTEX_DDP_COUNT) - 1;
|
|
mutex_init(&context.mutex_lock);
|
|
is_context_inited = 1;
|
|
|
|
return &context;
|
|
}
|
|
|
|
static int path_top_clock_off(void)
|
|
{
|
|
int i = 0;
|
|
struct DDP_MANAGER_CONTEXT *c = _get_context();
|
|
|
|
if (!c->power_state)
|
|
return 0;
|
|
|
|
for (i = 0; i < DDP_MAX_MANAGER_HANDLE; i++) {
|
|
if (c->handle_pool[i] && c->handle_pool[i]->power_state)
|
|
return 0;
|
|
}
|
|
|
|
c->power_state = 0;
|
|
for (i = 0; i < DISP_MODULE_NUM; i++) {
|
|
if (ddp_valid_engine[i])
|
|
ddp_clk_disable_by_module(i);
|
|
}
|
|
|
|
ddp_path_top_clock_off();
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int path_top_clock_on(void)
|
|
{
|
|
struct DDP_MANAGER_CONTEXT *c = _get_context();
|
|
int i = 0;
|
|
|
|
if (c->power_state)
|
|
return 0;
|
|
|
|
c->power_state = 1;
|
|
ddp_path_top_clock_on();
|
|
for (i = 0; i < DISP_MODULE_NUM; i++) {
|
|
if (ddp_valid_engine[i])
|
|
ddp_clk_enable_by_module(i);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int module_power_off(enum DISP_MODULE_ENUM module)
|
|
{
|
|
struct DDP_MODULE_DRIVER *m_drv = NULL;
|
|
|
|
if (module == DISP_MODULE_DSI0)
|
|
return 0;
|
|
|
|
m_drv = ddp_get_module_driver(module);
|
|
if (m_drv && m_drv->power_off)
|
|
m_drv->power_off(module, NULL);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int module_power_on(enum DISP_MODULE_ENUM module)
|
|
{
|
|
struct DDP_MODULE_DRIVER *m_drv = NULL;
|
|
|
|
if (module == DISP_MODULE_DSI0)
|
|
return 0;
|
|
|
|
m_drv = ddp_get_module_driver(module);
|
|
if (m_drv && m_drv->power_on)
|
|
m_drv->power_on(module, NULL);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct ddp_path_handle
|
|
*find_handle_by_module(enum DISP_MODULE_ENUM module)
|
|
{
|
|
if ((module == DISP_MODULE_DSI0) &&
|
|
(!_get_context()->module_path_table[DISP_MODULE_DSI0]))
|
|
return _get_context()->module_path_table[DISP_MODULE_DSIDUAL];
|
|
|
|
return _get_context()->module_path_table[module];
|
|
}
|
|
|
|
int dpmgr_module_notify(enum DISP_MODULE_ENUM module,
|
|
enum DISP_PATH_EVENT event)
|
|
{
|
|
int ret = 0;
|
|
|
|
struct ddp_path_handle *phandle = find_handle_by_module(module);
|
|
|
|
if (phandle)
|
|
ret = dpmgr_signal_event(phandle, event);
|
|
|
|
mmprofile_log_ex(ddp_mmp_get_events()->primary_display_aalod_trigger,
|
|
MMPROFILE_FLAG_PULSE, module, event);
|
|
return ret;
|
|
}
|
|
|
|
static int assign_default_irqs_table(enum DDP_SCENARIO_ENUM scenario,
|
|
struct DDP_IRQ_EVENT_MAPPING *irq_events)
|
|
{
|
|
int idx = 0;
|
|
|
|
switch (scenario) {
|
|
case DDP_SCENARIO_PRIMARY_DISP:
|
|
case DDP_SCENARIO_PRIMARY_BYPASS_PQ_DISP:
|
|
case DDP_SCENARIO_PRIMARY_RDMA0_COLOR0_DISP:
|
|
case DDP_SCENARIO_PRIMARY_RDMA0_DISP:
|
|
case DDP_SCENARIO_PRIMARY_ALL:
|
|
idx = 0;
|
|
break;
|
|
case DDP_SCENARIO_SUB_DISP:
|
|
case DDP_SCENARIO_SUB_RDMA1_DISP:
|
|
case DDP_SCENARIO_SUB_OVL_MEMOUT:
|
|
case DDP_SCENARIO_SUB_ALL:
|
|
idx = 1;
|
|
break;
|
|
case DDP_SCENARIO_PRIMARY_OVL_MEMOUT:
|
|
idx = 3;
|
|
break;
|
|
default:
|
|
DISP_LOG_E("unknown scenario %d\n", scenario);
|
|
break;
|
|
}
|
|
memcpy(irq_events, ddp_irq_event_list[idx],
|
|
sizeof(ddp_irq_event_list[idx]));
|
|
return 0;
|
|
}
|
|
|
|
static int __maybe_unused acquire_free_bit(unsigned int total)
|
|
{
|
|
int free_id = 0;
|
|
|
|
while (total) {
|
|
if (total & 0x1)
|
|
return free_id;
|
|
|
|
total >>= 1;
|
|
++free_id;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static int acquire_mutex(enum DDP_SCENARIO_ENUM scenario)
|
|
{
|
|
/* /: primay use mutex 0 */
|
|
int mutex_id = 0;
|
|
int mutex_idx_free = 0;
|
|
struct DDP_MANAGER_CONTEXT *ctx = _get_context();
|
|
|
|
ASSERT(scenario >= 0 && scenario < DDP_SCENARIO_MAX);
|
|
mutex_lock(&ctx->mutex_lock);
|
|
mutex_idx_free = ctx->mutex_idx;
|
|
while (mutex_idx_free) {
|
|
if (mutex_idx_free & 0x1) {
|
|
ctx->mutex_idx &= (~(0x1 << mutex_id));
|
|
mutex_id += DISP_MUTEX_DDP_FIRST;
|
|
break;
|
|
}
|
|
mutex_idx_free >>= 1;
|
|
++mutex_id;
|
|
}
|
|
mutex_unlock(&ctx->mutex_lock);
|
|
ASSERT(mutex_id < (DISP_MUTEX_DDP_FIRST + DISP_MUTEX_DDP_COUNT));
|
|
DDPDBG("scenario %s acquire mutex %d, left mutex 0x%x!\n",
|
|
ddp_get_scenario_name(scenario), mutex_id, ctx->mutex_idx);
|
|
return mutex_id;
|
|
}
|
|
|
|
static int release_mutex(int mutex_idx)
|
|
{
|
|
struct DDP_MANAGER_CONTEXT *ctx = _get_context();
|
|
|
|
ASSERT(mutex_idx < (DISP_MUTEX_DDP_FIRST + DISP_MUTEX_DDP_COUNT));
|
|
mutex_lock(&ctx->mutex_lock);
|
|
ctx->mutex_idx |= 1 << (mutex_idx - DISP_MUTEX_DDP_FIRST);
|
|
mutex_unlock(&ctx->mutex_lock);
|
|
DDPDBG("release mutex %d, left mutex 0x%x!\n", mutex_idx,
|
|
ctx->mutex_idx);
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_set_video_mode(disp_path_handle dp_handle, int is_vdo_mode)
|
|
{
|
|
struct ddp_path_handle *phandle = NULL;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
phandle->mode = is_vdo_mode ? DDP_VIDEO_MODE : DDP_CMD_MODE;
|
|
DDPDBG("set scenario %s mode: %s\n",
|
|
ddp_get_scenario_name(phandle->scenario),
|
|
is_vdo_mode ? "Video_Mode" : "Cmd_Mode");
|
|
return 0;
|
|
}
|
|
|
|
disp_path_handle dpmgr_create_path(enum DDP_SCENARIO_ENUM scenario,
|
|
struct cmdqRecStruct *cmdq_handle)
|
|
{
|
|
int i = 0;
|
|
int m;
|
|
struct ddp_path_handle *path_handle = NULL;
|
|
int *list = ddp_get_scenario_list(scenario);
|
|
int m_num = ddp_get_module_num(scenario);
|
|
struct DDP_MANAGER_CONTEXT *c = _get_context();
|
|
|
|
path_handle = kzalloc(sizeof(*path_handle), GFP_KERNEL);
|
|
if (!path_handle) {
|
|
DISP_LOG_E("fail to create handle on scenario %s\n",
|
|
ddp_get_scenario_name(scenario));
|
|
return path_handle;
|
|
}
|
|
if (path_handle->hwmutexid < 0 ||
|
|
path_handle->hwmutexid >= DDP_MAX_MANAGER_HANDLE) {
|
|
DISP_LOG_E("%s: error hwmutexid:%d\n",
|
|
__func__, path_handle->hwmutexid);
|
|
kfree(path_handle);
|
|
return NULL;
|
|
}
|
|
path_handle->cmdqhandle = cmdq_handle;
|
|
path_handle->scenario = scenario;
|
|
path_handle->hwmutexid = acquire_mutex(scenario);
|
|
path_handle->last_config.path_handle = path_handle;
|
|
assign_default_irqs_table(scenario, path_handle->irq_event_map);
|
|
|
|
DDPDBG("create handle %p on scenario %s\n",
|
|
path_handle, ddp_get_scenario_name(scenario));
|
|
DDPDBG("scenario %s include module:\n",
|
|
ddp_get_scenario_name(scenario));
|
|
for (i = 0; i < m_num; i++) {
|
|
m = list[i];
|
|
if (m < 0 || m >= DISP_MODULE_NUM) {
|
|
DISP_LOG_E("%s: error module_id:%d\n",
|
|
__func__, m);
|
|
return 1;
|
|
}
|
|
DDPDBG("%s\n", ddp_get_module_name(m));
|
|
c->module_usage_table[m]++;
|
|
c->module_path_table[m] = path_handle;
|
|
}
|
|
|
|
c->handle_cnt++;
|
|
c->handle_pool[path_handle->hwmutexid] = path_handle;
|
|
|
|
return path_handle;
|
|
}
|
|
|
|
int dpmgr_get_scenario(disp_path_handle dp_handle)
|
|
{
|
|
struct ddp_path_handle *phandle = (struct ddp_path_handle *)dp_handle;
|
|
|
|
return phandle->scenario;
|
|
}
|
|
|
|
static int _dpmgr_path_connect(enum DDP_SCENARIO_ENUM scenario, void *qhandle)
|
|
{
|
|
int i = 0, m;
|
|
int *list = ddp_get_scenario_list(scenario);
|
|
int m_num = ddp_get_module_num(scenario);
|
|
struct DDP_MODULE_DRIVER *m_drv = NULL;
|
|
|
|
ddp_connect_path(scenario, qhandle);
|
|
|
|
for (i = 0; i < m_num; i++) {
|
|
int prev = i == 0 ? DISP_MODULE_UNKNOWN : list[i - 1];
|
|
int next = i == m_num - 1 ? DISP_MODULE_UNKNOWN : list[i + 1];
|
|
|
|
m = list[i];
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (!(m_drv && m_drv->connect))
|
|
continue;
|
|
|
|
m_drv->connect(m, prev, next, 1, qhandle);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int _dpmgr_path_disconnect(enum DDP_SCENARIO_ENUM scenario,
|
|
void *qhandle)
|
|
{
|
|
int i = 0, m;
|
|
int *list = ddp_get_scenario_list(scenario);
|
|
int m_num = ddp_get_module_num(scenario);
|
|
struct DDP_MODULE_DRIVER *m_drv = NULL;
|
|
|
|
ddp_disconnect_path(scenario, qhandle);
|
|
|
|
for (i = 0; i < m_num; i++) {
|
|
int prev = i == 0 ? DISP_MODULE_UNKNOWN : list[i - 1];
|
|
int next = i == m_num - 1 ? DISP_MODULE_UNKNOWN : list[i + 1];
|
|
|
|
m = list[i];
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (!(m_drv && m_drv->connect))
|
|
continue;
|
|
|
|
m_drv->connect(m, prev, next, 1, qhandle);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_modify_path_power_on_new_modules(disp_path_handle dp_handle,
|
|
enum DDP_SCENARIO_ENUM new_scenario,
|
|
int sw_only)
|
|
{
|
|
int i = 0;
|
|
int m = 0;
|
|
struct DDP_MANAGER_CONTEXT *c = _get_context();
|
|
struct ddp_path_handle *phandle = (struct ddp_path_handle *)dp_handle;
|
|
|
|
int *new_list = ddp_get_scenario_list(new_scenario);
|
|
int new_m_num = ddp_get_module_num(new_scenario);
|
|
|
|
for (i = 0; i < new_m_num; i++) {
|
|
m = new_list[i];
|
|
/* new module's count is 0 */
|
|
if (m < DISP_MODULE_OVL0 || m >= DISP_MODULE_NUM) {
|
|
DISP_LOG_E("%s: error module_id:%d\n",
|
|
__func__, m);
|
|
return 1;
|
|
}
|
|
if (c->module_usage_table[m] == 0) {
|
|
c->module_usage_table[m]++;
|
|
c->module_path_table[m] = phandle;
|
|
if (!sw_only)
|
|
module_power_on(m);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* NOTES: modify_path should call API like this:
|
|
* old_scenario = dpmgr_get_scenario(handle);
|
|
* dpmgr_modify_path_power_on_new_modules();
|
|
* dpmgr_modify_path();
|
|
*
|
|
* after cmdq handle exec done:
|
|
* dpmgr_modify_path_power_off_old_modules();
|
|
*/
|
|
int dpmgr_modify_path(disp_path_handle dp_handle,
|
|
enum DDP_SCENARIO_ENUM new_scn,
|
|
struct cmdqRecStruct *cmdq_handle,
|
|
enum DDP_MODE mode, int sw_only)
|
|
{
|
|
struct ddp_path_handle *phandle;
|
|
enum DDP_SCENARIO_ENUM old_scn;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
old_scn = phandle->scenario;
|
|
phandle->cmdqhandle = cmdq_handle;
|
|
phandle->scenario = new_scn;
|
|
DISP_LOG_I("modify handle %p from %s to %s\n",
|
|
phandle, ddp_get_scenario_name(old_scn),
|
|
ddp_get_scenario_name(new_scn));
|
|
|
|
if (sw_only)
|
|
return 0;
|
|
|
|
/* mutex_set will clear old settings */
|
|
ddp_mutex_set(phandle->hwmutexid, new_scn, mode, cmdq_handle);
|
|
ddp_mutex_interrupt_enable(phandle->hwmutexid, cmdq_handle);
|
|
/* disconnect old path first */
|
|
_dpmgr_path_disconnect(old_scn, cmdq_handle);
|
|
/* connect new path */
|
|
_dpmgr_path_connect(new_scn, cmdq_handle);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_modify_path_power_off_old_modules(enum DDP_SCENARIO_ENUM old_scn,
|
|
enum DDP_SCENARIO_ENUM new_scn, int sw_only)
|
|
{
|
|
int i = 0;
|
|
int m = 0;
|
|
struct DDP_MANAGER_CONTEXT *c = _get_context();
|
|
int *old_list = ddp_get_scenario_list(old_scn);
|
|
int old_m_num = ddp_get_module_num(old_scn);
|
|
|
|
for (i = 0; i < old_m_num; i++) {
|
|
m = old_list[i];
|
|
if (m < 0 || m >= DISP_MODULE_NUM) {
|
|
DISP_LOG_E("%s: error module_id:%d\n",
|
|
__func__, m);
|
|
return 1;
|
|
}
|
|
if (ddp_is_module_in_scenario(new_scn, m))
|
|
continue;
|
|
|
|
c->module_usage_table[m]--;
|
|
c->module_path_table[m] = NULL;
|
|
if (!sw_only)
|
|
module_power_off(m);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_destroy_path_handle(disp_path_handle dp_handle)
|
|
{
|
|
int i = 0;
|
|
int m;
|
|
struct ddp_path_handle *phandle;
|
|
int *list;
|
|
int m_num;
|
|
struct DDP_MANAGER_CONTEXT *c;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
if (!phandle) {
|
|
DDP_PR_ERR("%s: error: path handle is NULL\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
if (phandle->hwmutexid < 0) {
|
|
DISP_LOG_E("%s: error hwmutexid:%d\n",
|
|
__func__, phandle->hwmutexid);
|
|
return 1;
|
|
}
|
|
list = ddp_get_scenario_list(phandle->scenario);
|
|
m_num = ddp_get_module_num(phandle->scenario);
|
|
c = _get_context();
|
|
|
|
DDPDBG("destroy path handle %p on scenario %s\n", phandle,
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
|
|
release_mutex(phandle->hwmutexid);
|
|
for (i = 0; i < m_num; i++) {
|
|
m = list[i];
|
|
if (m < 0 || m >= DISP_MODULE_NUM) {
|
|
DISP_LOG_E("%s: error module_id:%d\n",
|
|
__func__, m);
|
|
return 1;
|
|
}
|
|
c->module_usage_table[m]--;
|
|
c->module_path_table[m] = NULL;
|
|
}
|
|
c->handle_cnt--;
|
|
ASSERT(c->handle_cnt >= 0);
|
|
if (phandle->hwmutexid < 0 ||
|
|
phandle->hwmutexid >= DDP_MAX_MANAGER_HANDLE) {
|
|
DISP_LOG_E("%s: error hwmutexid:%d\n",
|
|
__func__, phandle->hwmutexid);
|
|
return 1;
|
|
}
|
|
c->handle_pool[phandle->hwmutexid] = NULL;
|
|
kfree(phandle);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_destroy_path(disp_path_handle dp_handle,
|
|
struct cmdqRecStruct *cmdq_handle)
|
|
{
|
|
struct ddp_path_handle *phandle = (struct ddp_path_handle *)dp_handle;
|
|
|
|
if (phandle)
|
|
_dpmgr_path_disconnect(phandle->scenario, cmdq_handle);
|
|
|
|
dpmgr_destroy_path_handle(dp_handle);
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_memout_clock(disp_path_handle dp_handle, int clock_switch)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_add_memout(disp_path_handle dp_handle,
|
|
enum DISP_MODULE_ENUM engine, void *cmdq_handle)
|
|
{
|
|
struct ddp_path_handle *phandle;
|
|
enum DISP_MODULE_ENUM wdma;
|
|
struct DDP_MANAGER_CONTEXT *c;
|
|
struct DDP_MODULE_DRIVER *m_drv = NULL;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
ASSERT(phandle->scenario == DDP_SCENARIO_PRIMARY_DISP ||
|
|
phandle->scenario == DDP_SCENARIO_SUB_DISP ||
|
|
phandle->scenario == DDP_SCENARIO_PRIMARY_OVL_MEMOUT);
|
|
|
|
wdma = DISP_MODULE_WDMA0;
|
|
|
|
if (ddp_is_module_in_scenario(phandle->scenario, wdma) == 1) {
|
|
DDP_PR_ERR("%s: error, wdma is already in scenario=%s\n",
|
|
__func__, ddp_get_scenario_name(phandle->scenario));
|
|
return -1;
|
|
}
|
|
/* update context */
|
|
c = _get_context();
|
|
c->module_usage_table[wdma]++;
|
|
c->module_path_table[wdma] = phandle;
|
|
if (engine == DISP_MODULE_OVL0) {
|
|
phandle->scenario = DDP_SCENARIO_PRIMARY_ALL;
|
|
} else {
|
|
pr_err("%s error: engine=%d\n", __func__, engine);
|
|
ASSERT(0);
|
|
return 0;
|
|
}
|
|
/* update connection */
|
|
_dpmgr_path_connect(phandle->scenario, cmdq_handle);
|
|
ddp_mutex_set(phandle->hwmutexid, phandle->scenario, phandle->mode,
|
|
cmdq_handle);
|
|
|
|
/* wdma just needs to start */
|
|
m_drv = ddp_get_module_driver(wdma);
|
|
if (m_drv) {
|
|
if (m_drv->init)
|
|
m_drv->init(wdma, cmdq_handle);
|
|
|
|
if (m_drv->start)
|
|
m_drv->start(wdma, cmdq_handle);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_remove_memout(disp_path_handle dp_handle, void *cmdq_handle)
|
|
{
|
|
enum DDP_SCENARIO_ENUM old_scn;
|
|
enum DDP_SCENARIO_ENUM new_scn;
|
|
struct ddp_path_handle *phandle;
|
|
enum DISP_MODULE_ENUM wdma;
|
|
struct DDP_MANAGER_CONTEXT *c;
|
|
struct DDP_MODULE_DRIVER *m_drv = NULL;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
ASSERT(phandle->scenario == DDP_SCENARIO_PRIMARY_DISP ||
|
|
phandle->scenario == DDP_SCENARIO_PRIMARY_ALL ||
|
|
phandle->scenario == DDP_SCENARIO_SUB_DISP ||
|
|
phandle->scenario == DDP_SCENARIO_SUB_ALL);
|
|
|
|
wdma = DISP_MODULE_WDMA0;
|
|
|
|
if (ddp_is_module_in_scenario(phandle->scenario, wdma) == 0) {
|
|
DDP_PR_ERR("%s: error: wdma is not in scenario=%s\n", __func__,
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
return -1;
|
|
}
|
|
/* update context */
|
|
c = _get_context();
|
|
c->module_usage_table[wdma]--;
|
|
c->module_path_table[wdma] = 0;
|
|
/* wdma just need stop */
|
|
m_drv = ddp_get_module_driver(wdma);
|
|
if (m_drv && m_drv->stop) {
|
|
m_drv->stop(wdma, cmdq_handle);
|
|
|
|
/* note: deinit is moved to cmdq callback */
|
|
/* if (m_drv->deinit != 0)
|
|
* m_drv->deinit(wdma, cmdq_handle);
|
|
*/
|
|
}
|
|
if (phandle->scenario == DDP_SCENARIO_PRIMARY_ALL) {
|
|
old_scn = DDP_SCENARIO_PRIMARY_OVL_MEMOUT;
|
|
new_scn = DDP_SCENARIO_PRIMARY_DISP;
|
|
} else if (phandle->scenario == DDP_SCENARIO_SUB_ALL) {
|
|
old_scn = DDP_SCENARIO_SUB_OVL_MEMOUT;
|
|
new_scn = DDP_SCENARIO_SUB_DISP;
|
|
} else {
|
|
pr_err("%s: error scenario=%s\n", __func__,
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
ASSERT(0);
|
|
return 0;
|
|
}
|
|
_dpmgr_path_disconnect(old_scn, cmdq_handle);
|
|
phandle->scenario = new_scn;
|
|
/* update connected */
|
|
_dpmgr_path_connect(phandle->scenario, cmdq_handle);
|
|
ddp_mutex_set(phandle->hwmutexid, phandle->scenario,
|
|
phandle->mode, cmdq_handle);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_set_dst_module(disp_path_handle dp_handle,
|
|
enum DISP_MODULE_ENUM dst_module)
|
|
{
|
|
struct ddp_path_handle *phandle;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
ASSERT((phandle->scenario >= 0 &&
|
|
phandle->scenario < DDP_SCENARIO_MAX));
|
|
DDPDBG("set dst module on scenario %s, module %s\n",
|
|
ddp_get_scenario_name(phandle->scenario),
|
|
ddp_get_module_name(dst_module));
|
|
return ddp_set_dst_module(phandle->scenario, dst_module);
|
|
}
|
|
|
|
int dpmgr_path_get_mutex(disp_path_handle dp_handle)
|
|
{
|
|
struct ddp_path_handle *phandle = NULL;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
return phandle->hwmutexid;
|
|
}
|
|
|
|
enum DISP_MODULE_ENUM dpmgr_path_get_dst_module(disp_path_handle dp_handle)
|
|
{
|
|
struct ddp_path_handle *phandle;
|
|
enum DISP_MODULE_ENUM dst_module;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 0;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
ASSERT((phandle->scenario >= 0 &&
|
|
phandle->scenario < DDP_SCENARIO_MAX));
|
|
dst_module = ddp_get_dst_module(phandle->scenario);
|
|
|
|
DISP_LOG_V("get dst module on scenario %s, module %s\n",
|
|
ddp_get_scenario_name(phandle->scenario),
|
|
ddp_get_module_name(dst_module));
|
|
return dst_module;
|
|
}
|
|
|
|
enum dst_module_type dpmgr_path_get_dst_module_type(disp_path_handle dp_handle)
|
|
{
|
|
enum DISP_MODULE_ENUM dst_module = dpmgr_path_get_dst_module(dp_handle);
|
|
|
|
if (dst_module == DISP_MODULE_WDMA0)
|
|
return DST_MOD_WDMA;
|
|
|
|
return DST_MOD_REAL_TIME;
|
|
}
|
|
|
|
int dpmgr_path_connect(disp_path_handle dp_handle, int encmdq)
|
|
{
|
|
struct ddp_path_handle *phandle;
|
|
struct cmdqRecStruct *cmdqHandle;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
cmdqHandle = encmdq ? phandle->cmdqhandle : NULL;
|
|
|
|
_dpmgr_path_connect(phandle->scenario, cmdqHandle);
|
|
|
|
ddp_mutex_set(phandle->hwmutexid, phandle->scenario, phandle->mode,
|
|
cmdqHandle);
|
|
ddp_mutex_interrupt_enable(phandle->hwmutexid, cmdqHandle);
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_disconnect(disp_path_handle dp_handle, int encmdq)
|
|
{
|
|
struct ddp_path_handle *phandle;
|
|
struct cmdqRecStruct *cmdqHandle;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
cmdqHandle = encmdq ? phandle->cmdqhandle : NULL;
|
|
|
|
DDPDBG("%s on scenario %s\n", __func__,
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
ddp_mutex_clear(phandle->hwmutexid, cmdqHandle);
|
|
ddp_mutex_interrupt_disable(phandle->hwmutexid, cmdqHandle);
|
|
_dpmgr_path_disconnect(phandle->scenario, cmdqHandle);
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_init_with_cmdq(disp_path_handle dp_handle,
|
|
struct cmdqRecStruct *cmdq_handle)
|
|
{
|
|
int i = 0;
|
|
int m, m_num;
|
|
struct ddp_path_handle *phandle;
|
|
int *list;
|
|
struct DDP_MANAGER_CONTEXT *c = _get_context();
|
|
struct DDP_MODULE_DRIVER *m_drv = NULL;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
list = ddp_get_scenario_list(phandle->scenario);
|
|
m_num = ddp_get_module_num(phandle->scenario);
|
|
|
|
DDPDBG("path init on scenario %s\n",
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
mutex_lock(&c->mutex_lock);
|
|
/* open top clock */
|
|
path_top_clock_on();
|
|
|
|
/* setting mutex */
|
|
ddp_mutex_set(phandle->hwmutexid, phandle->scenario, phandle->mode,
|
|
cmdq_handle);
|
|
ddp_mutex_interrupt_enable(phandle->hwmutexid, cmdq_handle);
|
|
/* connect path */
|
|
_dpmgr_path_connect(phandle->scenario, cmdq_handle);
|
|
|
|
/* each module init */
|
|
for (i = 0; i < m_num; i++) {
|
|
m = list[i];
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (!m_drv)
|
|
continue;
|
|
|
|
if (m_drv->init)
|
|
m_drv->init(m, cmdq_handle);
|
|
|
|
if (m_drv->set_listener)
|
|
m_drv->set_listener(m, dpmgr_module_notify);
|
|
}
|
|
/* after init this path will power on */
|
|
phandle->power_state = 1;
|
|
mutex_unlock(&c->mutex_lock);
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_start(disp_path_handle dp_handle, int encmdq)
|
|
{
|
|
struct ddp_path_handle *handle;
|
|
struct cmdqRecStruct *cmdqHandle;
|
|
|
|
ASSERT(dp_handle != NULL);
|
|
handle = (struct ddp_path_handle *)dp_handle;
|
|
cmdqHandle = encmdq ? handle->cmdqhandle : NULL;
|
|
|
|
return dpmgr_path_start_with_cmdq(dp_handle, cmdqHandle);
|
|
}
|
|
|
|
int dpmgr_path_init(disp_path_handle dp_handle, int encmdq)
|
|
{
|
|
struct ddp_path_handle *handle;
|
|
struct cmdqRecStruct *cmdqHandle;
|
|
|
|
ASSERT(dp_handle != NULL);
|
|
handle = (struct ddp_path_handle *)dp_handle;
|
|
cmdqHandle = encmdq ? handle->cmdqhandle : NULL;
|
|
|
|
return dpmgr_path_init_with_cmdq(dp_handle, cmdqHandle);
|
|
}
|
|
|
|
int dpmgr_path_deinit(disp_path_handle dp_handle, int encmdq)
|
|
{
|
|
int i = 0;
|
|
int m, m_num;
|
|
int *list;
|
|
struct cmdqRecStruct *cmdqHandle;
|
|
struct ddp_path_handle *phandle;
|
|
struct DDP_MANAGER_CONTEXT *c = _get_context();
|
|
struct DDP_MODULE_DRIVER *m_drv = NULL;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
list = ddp_get_scenario_list(phandle->scenario);
|
|
m_num = ddp_get_module_num(phandle->scenario);
|
|
cmdqHandle = encmdq ? phandle->cmdqhandle : NULL;
|
|
|
|
DDPDBG("path deinit on scenario %s\n",
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
|
|
mutex_lock(&c->mutex_lock);
|
|
ddp_mutex_interrupt_disable(phandle->hwmutexid, cmdqHandle);
|
|
ddp_mutex_clear(phandle->hwmutexid, cmdqHandle);
|
|
_dpmgr_path_disconnect(phandle->scenario, cmdqHandle);
|
|
for (i = 0; i < m_num; i++) {
|
|
m = list[i];
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (m_drv) {
|
|
if (m_drv->deinit)
|
|
m_drv->deinit(m, cmdqHandle);
|
|
|
|
if (m_drv->set_listener)
|
|
m_drv->set_listener(m, NULL);
|
|
}
|
|
}
|
|
phandle->power_state = 0;
|
|
/* close top clock when last path init */
|
|
path_top_clock_off();
|
|
mutex_unlock(&c->mutex_lock);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_start_with_cmdq(disp_path_handle dp_handle,
|
|
struct cmdqRecStruct *cmdq_handle)
|
|
{
|
|
int i = 0;
|
|
int m, m_num;
|
|
struct ddp_path_handle *phandle;
|
|
int *list;
|
|
struct DDP_MODULE_DRIVER *m_drv = NULL;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
list = ddp_get_scenario_list(phandle->scenario);
|
|
m_num = ddp_get_module_num(phandle->scenario);
|
|
|
|
DISP_LOG_I("path start on scenario %s\n",
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
|
|
for (i = 0; i < m_num; i++) {
|
|
m = list[i];
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (m_drv && m_drv->start)
|
|
m_drv->start(m, cmdq_handle);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_stop(disp_path_handle dp_handle, int encmdq)
|
|
{
|
|
int i = 0;
|
|
int m, m_num;
|
|
struct ddp_path_handle *phandle;
|
|
int *list;
|
|
struct cmdqRecStruct *cmdqHandle;
|
|
struct DDP_MODULE_DRIVER *m_drv;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
list = ddp_get_scenario_list(phandle->scenario);
|
|
m_num = ddp_get_module_num(phandle->scenario);
|
|
cmdqHandle = encmdq ? phandle->cmdqhandle : NULL;
|
|
|
|
DISP_LOG_I("path stop on scenario %s\n",
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
for (i = m_num - 1; i >= 0; i--) {
|
|
m = list[i];
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (m_drv && m_drv->stop)
|
|
m_drv->stop(m, cmdqHandle);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_ioctl(disp_path_handle dp_handle, void *cmdq_handle,
|
|
enum DDP_IOCTL_NAME ioctl_cmd, void *params)
|
|
{
|
|
int i = 0;
|
|
int ret = 0;
|
|
int m, m_num;
|
|
int *list;
|
|
struct ddp_path_handle *phandle;
|
|
struct DDP_MODULE_DRIVER *m_drv;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
list = ddp_get_scenario_list(phandle->scenario);
|
|
m_num = ddp_get_module_num(phandle->scenario);
|
|
|
|
DDPDBG("path IOCTL(%s) on scenario %s\n",
|
|
ddp_get_ioctl_name(ioctl_cmd),
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
|
|
for (i = m_num - 1; i >= 0; i--) {
|
|
m = list[i];
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (m_drv && m_drv->ioctl)
|
|
ret += m_drv->ioctl(m, cmdq_handle,
|
|
ioctl_cmd, params);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int dpmgr_path_enable_irq(disp_path_handle dp_handle, void *cmdq_handle,
|
|
enum DDP_IRQ_LEVEL irq_level)
|
|
{
|
|
int i = 0;
|
|
int ret = 0;
|
|
int m, m_num;
|
|
struct ddp_path_handle *phandle;
|
|
int *list;
|
|
struct DDP_MODULE_DRIVER *m_drv;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
list = ddp_get_scenario_list(phandle->scenario);
|
|
m_num = ddp_get_module_num(phandle->scenario);
|
|
|
|
DDPDBG("path enable irq on scenario %s, level %d\n",
|
|
ddp_get_scenario_name(phandle->scenario), irq_level);
|
|
|
|
if (irq_level != DDP_IRQ_LEVEL_ALL)
|
|
ddp_mutex_interrupt_disable(phandle->hwmutexid, cmdq_handle);
|
|
else
|
|
ddp_mutex_interrupt_enable(phandle->hwmutexid, cmdq_handle);
|
|
|
|
for (i = m_num - 1; i >= 0; i--) {
|
|
m = list[i];
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (m_drv && m_drv->enable_irq) {
|
|
DDPDBG("scenario %s, module %s enable irq level %d\n",
|
|
ddp_get_scenario_name(phandle->scenario),
|
|
ddp_get_module_name(m), irq_level);
|
|
ret += m_drv->enable_irq(m, cmdq_handle, irq_level);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int dpmgr_path_reset(disp_path_handle dp_handle, int encmdq)
|
|
{
|
|
int i = 0;
|
|
int ret = 0;
|
|
int error = 0;
|
|
int m, m_num;
|
|
int *list;
|
|
struct ddp_path_handle *phandle;
|
|
struct cmdqRecStruct *cmdqHandle;
|
|
struct DDP_MODULE_DRIVER *m_drv;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
list = ddp_get_scenario_list(phandle->scenario);
|
|
m_num = ddp_get_module_num(phandle->scenario);
|
|
cmdqHandle = encmdq ? phandle->cmdqhandle : NULL;
|
|
|
|
DISP_LOG_I("path reset on scenario %s\n",
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
/* first reset mutex */
|
|
ddp_mutex_reset(phandle->hwmutexid, cmdqHandle);
|
|
|
|
for (i = 0; i < m_num; i++) {
|
|
m = list[i];
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (m_drv && m_drv->reset) {
|
|
ret = m_drv->reset(m, cmdqHandle);
|
|
if (ret)
|
|
error++;
|
|
}
|
|
}
|
|
return error > 0 ? -1 : 0;
|
|
}
|
|
|
|
static unsigned int dpmgr_is_PQ(enum DISP_MODULE_ENUM module)
|
|
{
|
|
unsigned int isPQ = 0;
|
|
|
|
switch (module) {
|
|
case DISP_MODULE_COLOR0:
|
|
case DISP_MODULE_CCORR0:
|
|
case DISP_MODULE_AAL0:
|
|
case DISP_MODULE_GAMMA0:
|
|
case DISP_MODULE_DITHER0:
|
|
isPQ = 1;
|
|
break;
|
|
default:
|
|
isPQ = 0;
|
|
break;
|
|
}
|
|
|
|
return isPQ;
|
|
}
|
|
|
|
int dpmgr_path_update_partial_roi(disp_path_handle dp_handle,
|
|
struct disp_rect partial, void *cmdq_handle)
|
|
{
|
|
return dpmgr_path_ioctl(dp_handle, cmdq_handle, DDP_PARTIAL_UPDATE,
|
|
&partial);
|
|
}
|
|
|
|
int dpmgr_path_config(disp_path_handle dp_handle,
|
|
struct disp_ddp_path_config *config, void *cmdq_handle)
|
|
{
|
|
int i = 0;
|
|
int m, m_num;
|
|
struct ddp_path_handle *phandle;
|
|
int *list;
|
|
struct DDP_MODULE_DRIVER *m_drv;
|
|
const int len = 160;
|
|
char msg[len];
|
|
int n = 0;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
list = ddp_get_scenario_list(phandle->scenario);
|
|
m_num = ddp_get_module_num(phandle->scenario);
|
|
|
|
n = scnprintf(msg, len,
|
|
"path config ovl %d,rdma %d,wdma %d,dst %d on path handle %p scenario %s\n",
|
|
config->ovl_dirty, config->rdma_dirty,
|
|
config->wdma_dirty, config->dst_dirty,
|
|
phandle, ddp_get_scenario_name(phandle->scenario));
|
|
DISP_LOG_V("%s", msg);
|
|
|
|
memcpy(&phandle->last_config, config, sizeof(*config));
|
|
for (i = 0; i < m_num; i++) {
|
|
m = list[i];
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (!m_drv)
|
|
continue;
|
|
|
|
if (m_drv->config)
|
|
m_drv->config(m, config, cmdq_handle);
|
|
|
|
if (!disp_helper_get_option(DISP_OPT_USE_PQ) &&
|
|
dpmgr_is_PQ(m) == 1) {
|
|
if (m_drv->bypass)
|
|
m_drv->bypass(m, 1);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
struct disp_ddp_path_config
|
|
*dpmgr_path_get_last_config_notclear(disp_path_handle dp_handle)
|
|
{
|
|
struct ddp_path_handle *phandle = (struct ddp_path_handle *)dp_handle;
|
|
|
|
return &phandle->last_config;
|
|
}
|
|
|
|
struct disp_ddp_path_config
|
|
*dpmgr_path_get_last_config(disp_path_handle dp_handle)
|
|
{
|
|
struct ddp_path_handle *phandle = (struct ddp_path_handle *)dp_handle;
|
|
|
|
phandle->last_config.ovl_dirty = 0;
|
|
phandle->last_config.rdma_dirty = 0;
|
|
phandle->last_config.wdma_dirty = 0;
|
|
phandle->last_config.dst_dirty = 0;
|
|
phandle->last_config.ovl_layer_dirty = 0;
|
|
phandle->last_config.ovl_layer_scanned = 0;
|
|
phandle->last_config.ovl_partial_dirty = 0;
|
|
phandle->last_config.sbch_enable = 0;
|
|
return &phandle->last_config;
|
|
}
|
|
|
|
void dpmgr_get_input_address(disp_path_handle dp_handle, unsigned long *addr)
|
|
{
|
|
struct ddp_path_handle *phandle = (struct ddp_path_handle *)dp_handle;
|
|
int *list = ddp_get_scenario_list(phandle->scenario);
|
|
|
|
if (list[0] == DISP_MODULE_OVL0 || list[0] == DISP_MODULE_OVL1_2L)
|
|
ovl_get_address(list[0], addr);
|
|
else if (list[0] == DISP_MODULE_RDMA0 || list[0] == DISP_MODULE_RDMA1)
|
|
rdma_get_address(list[0], addr);
|
|
}
|
|
|
|
int dpmgr_path_build_cmdq(disp_path_handle dp_handle, void *trigger_loop_handle,
|
|
enum CMDQ_STATE state, int reverse)
|
|
{
|
|
int ret = 0;
|
|
int i = 0;
|
|
int m, m_num;
|
|
struct ddp_path_handle *phandle;
|
|
int *list;
|
|
struct DDP_MODULE_DRIVER *m_drv;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
list = ddp_get_scenario_list(phandle->scenario);
|
|
m_num = ddp_get_module_num(phandle->scenario);
|
|
|
|
if (reverse) {
|
|
for (i = m_num - 1; i >= 0; i--) {
|
|
m = list[i];
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (!(m_drv && m_drv->build_cmdq))
|
|
continue;
|
|
|
|
ret = m_drv->build_cmdq(m, trigger_loop_handle, state);
|
|
}
|
|
} else {
|
|
for (i = 0; i < m_num; i++) {
|
|
m = list[i];
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (!(m_drv && m_drv->build_cmdq))
|
|
continue;
|
|
|
|
ret = m_drv->build_cmdq(m, trigger_loop_handle, state);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int dpmgr_path_trigger(disp_path_handle dp_handle, void *trigger_loop_handle,
|
|
int encmdq)
|
|
{
|
|
struct ddp_path_handle *phandle;
|
|
int *list;
|
|
int m_num, m;
|
|
int i;
|
|
struct DDP_MODULE_DRIVER *m_drv;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
DISP_LOG_I("%s on scenario %s\n", __func__,
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
list = ddp_get_scenario_list(phandle->scenario);
|
|
m_num = ddp_get_module_num(phandle->scenario);
|
|
|
|
ddp_mutex_enable(phandle->hwmutexid, phandle->scenario, phandle->mode,
|
|
trigger_loop_handle);
|
|
for (i = 0; i < m_num; i++) {
|
|
m = list[i];
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (!(m_drv && m_drv->trigger))
|
|
continue;
|
|
|
|
m_drv->trigger(m, trigger_loop_handle);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_mutex_sof(disp_path_handle dp_handle, void *trigger_loop_handle,
|
|
int encmdq)
|
|
{
|
|
struct ddp_path_handle *phandle;
|
|
int *list;
|
|
int m_num;
|
|
|
|
ASSERT(dp_handle != NULL);
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
DISP_LOG_I("%s scenario %s\n", __func__,
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
list = ddp_get_scenario_list(phandle->scenario);
|
|
m_num = ddp_get_module_num(phandle->scenario);
|
|
|
|
ddp_mutex_enable(phandle->hwmutexid, phandle->scenario, phandle->mode,
|
|
trigger_loop_handle);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_trigger_no_mutex(disp_path_handle dp_handle,
|
|
void *trigger_loop_handle, int encmdq)
|
|
{
|
|
struct ddp_path_handle *phandle;
|
|
int *list;
|
|
int m_num;
|
|
int i;
|
|
int m_n;
|
|
|
|
ASSERT(dp_handle != NULL);
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
DISP_LOG_I("%s on scenario %s\n", __func__,
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
list = ddp_get_scenario_list(phandle->scenario);
|
|
m_num = ddp_get_module_num(phandle->scenario);
|
|
|
|
for (i = 0; i < m_num; i++) {
|
|
m_n = list[i];
|
|
if (ddp_get_module_driver(m_n) != 0) {
|
|
if (ddp_get_module_driver(m_n)->trigger != 0) {
|
|
ddp_get_module_driver(m_n)->trigger(m_n,
|
|
trigger_loop_handle);
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_flush(disp_path_handle dp_handle, int encmdq)
|
|
{
|
|
struct ddp_path_handle *phandle;
|
|
struct cmdqRecStruct *cmdqHandle;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
cmdqHandle = encmdq ? phandle->cmdqhandle : NULL;
|
|
DDPDBG("path flush on scenario %s\n",
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
return ddp_mutex_enable(phandle->hwmutexid, phandle->scenario,
|
|
phandle->mode, cmdqHandle);
|
|
}
|
|
|
|
int dpmgr_path_power_off(disp_path_handle dp_handle, enum CMDQ_SWITCH encmdq)
|
|
{
|
|
int i = 0;
|
|
int m, m_num;
|
|
struct ddp_path_handle *phandle;
|
|
int *list;
|
|
struct DDP_MANAGER_CONTEXT *c = _get_context();
|
|
struct DDP_MODULE_DRIVER *m_drv;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
list = ddp_get_scenario_list(phandle->scenario);
|
|
m_num = ddp_get_module_num(phandle->scenario);
|
|
|
|
DISP_LOG_I("path power off on scenario %s\n",
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
|
|
mutex_lock(&c->mutex_lock);
|
|
for (i = 0; i < m_num; i++) {
|
|
m = list[i];
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (!(m_drv && m_drv->power_off))
|
|
continue;
|
|
|
|
m_drv->power_off(m, encmdq ? phandle->cmdqhandle : NULL);
|
|
}
|
|
phandle->power_state = 0;
|
|
path_top_clock_off();
|
|
mutex_unlock(&c->mutex_lock);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_power_on(disp_path_handle dp_handle, enum CMDQ_SWITCH encmdq)
|
|
{
|
|
int i = 0;
|
|
int m, m_num;
|
|
int *list;
|
|
struct ddp_path_handle *phandle;
|
|
struct DDP_MANAGER_CONTEXT *c = _get_context();
|
|
struct DDP_MODULE_DRIVER *m_drv;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
list = ddp_get_scenario_list(phandle->scenario);
|
|
m_num = ddp_get_module_num(phandle->scenario);
|
|
|
|
DISP_LOG_I("path power on scenario %s\n",
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
mutex_lock(&c->mutex_lock);
|
|
path_top_clock_on();
|
|
for (i = 0; i < m_num; i++) {
|
|
m = list[i];
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (!(m_drv && m_drv->power_on))
|
|
continue;
|
|
|
|
m_drv->power_on(m, encmdq ? phandle->cmdqhandle : NULL);
|
|
}
|
|
/* module list on this path will resume power on */
|
|
phandle->power_state = 1;
|
|
mutex_unlock(&c->mutex_lock);
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_power_off_bypass_pwm(disp_path_handle dp_handle,
|
|
enum CMDQ_SWITCH encmdq)
|
|
{
|
|
int i = 0;
|
|
int m, m_num;
|
|
struct ddp_path_handle *phandle;
|
|
int *list;
|
|
struct DDP_MANAGER_CONTEXT *c = _get_context();
|
|
struct DDP_MODULE_DRIVER *m_drv;
|
|
|
|
ASSERT(dp_handle != NULL);
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
list = ddp_get_scenario_list(phandle->scenario);
|
|
m_num = ddp_get_module_num(phandle->scenario);
|
|
|
|
DISP_LOG_I("path power off on scenario %s\n",
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
|
|
mutex_lock(&c->mutex_lock);
|
|
|
|
if (disp_helper_get_option(DISP_OPT_IDLEMGR_KEEP_LP11))
|
|
dpmgr_path_ioctl(dp_handle, encmdq ? phandle->cmdqhandle : NULL,
|
|
DDP_DSI_ENTER_IDLE, NULL);
|
|
|
|
for (i = 0; i < m_num; i++) {
|
|
m = list[i];
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (!(m_drv && m_drv->power_off))
|
|
continue;
|
|
|
|
if (m == DISP_MODULE_PWM0) {
|
|
DDPMSG(" %s power off -- bypass\n",
|
|
ddp_get_module_name(m));
|
|
continue;
|
|
}
|
|
|
|
m_drv->power_off(m, encmdq ? phandle->cmdqhandle : NULL);
|
|
}
|
|
phandle->power_state = 0;
|
|
path_top_clock_off();
|
|
mutex_unlock(&c->mutex_lock);
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_power_on_bypass_pwm(disp_path_handle dp_handle,
|
|
enum CMDQ_SWITCH encmdq)
|
|
{
|
|
int i = 0;
|
|
int m, m_num;
|
|
int *list;
|
|
struct ddp_path_handle *phandle;
|
|
struct DDP_MANAGER_CONTEXT *c = _get_context();
|
|
struct DDP_MODULE_DRIVER *m_drv;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
list = ddp_get_scenario_list(phandle->scenario);
|
|
m_num = ddp_get_module_num(phandle->scenario);
|
|
|
|
DISP_LOG_I("path power on scenario %s\n",
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
|
|
mutex_lock(&c->mutex_lock);
|
|
path_top_clock_on();
|
|
for (i = 0; i < m_num; i++) {
|
|
m = list[i];
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (!m_drv || !m_drv->power_on)
|
|
continue;
|
|
|
|
if (m == DISP_MODULE_PWM0) {
|
|
DDPMSG(" %s power on -- bypass\n",
|
|
ddp_get_module_name(m));
|
|
continue;
|
|
}
|
|
|
|
m_drv->power_on(m, encmdq ? phandle->cmdqhandle : NULL);
|
|
}
|
|
|
|
if (disp_helper_get_option(DISP_OPT_IDLEMGR_KEEP_LP11))
|
|
dpmgr_path_ioctl(dp_handle, encmdq ? phandle->cmdqhandle : NULL,
|
|
DDP_DSI_EXIT_IDLE, NULL);
|
|
|
|
/* module list on this path will resume power on */
|
|
phandle->power_state = 1;
|
|
mutex_unlock(&c->mutex_lock);
|
|
return 0;
|
|
}
|
|
|
|
static int is_module_in_path(enum DISP_MODULE_ENUM module,
|
|
struct ddp_path_handle *phandle)
|
|
{
|
|
struct DDP_MANAGER_CONTEXT *c = _get_context();
|
|
if (module >= DISP_MODULE_NUM) {
|
|
DISP_LOG_E("%s: error module_id:%d\n",
|
|
__func__, module);
|
|
return -1;
|
|
}
|
|
|
|
ASSERT(module < DISP_MODULE_UNKNOWN);
|
|
if (c->module_path_table[module] == phandle)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_user_cmd(disp_path_handle dp_handle, unsigned int msg,
|
|
unsigned long arg, void *cmdqhandle)
|
|
{
|
|
int ret = -1;
|
|
struct ddp_path_handle *phandle = NULL;
|
|
struct DDP_MODULE_DRIVER *m_drv = NULL;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
/* DISP_LOG_W("%s msg 0x%08x\n", __func__, msg); */
|
|
|
|
switch (msg) {
|
|
case DISP_IOCTL_AAL_EVENTCTL:
|
|
case DISP_IOCTL_AAL_GET_HIST:
|
|
case DISP_IOCTL_AAL_INIT_REG:
|
|
case DISP_IOCTL_AAL_SET_PARAM:
|
|
case DISP_IOCTL_AAL_INIT_DRE30:
|
|
case DISP_IOCTL_AAL_GET_SIZE:
|
|
/* TODO: just for verify rootcause, will be removed soon */
|
|
#ifndef CONFIG_FOR_SOURCE_PQ
|
|
if (!is_module_in_path(DISP_MODULE_AAL0, phandle))
|
|
break;
|
|
|
|
m_drv = ddp_get_module_driver(DISP_MODULE_AAL0);
|
|
if (!m_drv || !m_drv->cmd)
|
|
break;
|
|
|
|
ret = m_drv->cmd(DISP_MODULE_AAL0, msg, arg, cmdqhandle);
|
|
#endif
|
|
break;
|
|
case DISP_IOCTL_SET_GAMMALUT:
|
|
m_drv = ddp_get_module_driver(DISP_MODULE_GAMMA0);
|
|
if (!m_drv || !m_drv->cmd)
|
|
break;
|
|
|
|
ret = m_drv->cmd(DISP_MODULE_GAMMA0, msg, arg, cmdqhandle);
|
|
break;
|
|
case DISP_IOCTL_SET_CCORR:
|
|
case DISP_IOCTL_CCORR_EVENTCTL:
|
|
case DISP_IOCTL_CCORR_GET_IRQ:
|
|
case DISP_IOCTL_SUPPORT_COLOR_TRANSFORM:
|
|
m_drv = ddp_get_module_driver(DISP_MODULE_CCORR0);
|
|
if (!m_drv || !m_drv->cmd)
|
|
break;
|
|
|
|
ret = m_drv->cmd(DISP_MODULE_CCORR0, msg, arg, cmdqhandle);
|
|
break;
|
|
case DISP_IOCTL_SET_PQPARAM:
|
|
case DISP_IOCTL_GET_PQPARAM:
|
|
case DISP_IOCTL_SET_PQINDEX:
|
|
case DISP_IOCTL_GET_PQINDEX:
|
|
case DISP_IOCTL_SET_COLOR_REG:
|
|
case DISP_IOCTL_SET_TDSHPINDEX:
|
|
case DISP_IOCTL_GET_TDSHPINDEX:
|
|
case DISP_IOCTL_SET_PQ_CAM_PARAM:
|
|
case DISP_IOCTL_GET_PQ_CAM_PARAM:
|
|
case DISP_IOCTL_SET_PQ_GAL_PARAM:
|
|
case DISP_IOCTL_GET_PQ_GAL_PARAM:
|
|
case DISP_IOCTL_PQ_SET_BYPASS_COLOR:
|
|
case DISP_IOCTL_PQ_SET_WINDOW:
|
|
case DISP_IOCTL_WRITE_REG:
|
|
case DISP_IOCTL_READ_REG:
|
|
case DISP_IOCTL_MUTEX_CONTROL:
|
|
case DISP_IOCTL_PQ_GET_TDSHP_FLAG:
|
|
case DISP_IOCTL_PQ_SET_TDSHP_FLAG:
|
|
case DISP_IOCTL_PQ_GET_DC_PARAM:
|
|
case DISP_IOCTL_PQ_SET_DC_PARAM:
|
|
case DISP_IOCTL_PQ_GET_DS_PARAM:
|
|
case DISP_IOCTL_PQ_GET_MDP_COLOR_CAP:
|
|
case DISP_IOCTL_PQ_GET_MDP_TDSHP_REG:
|
|
case DISP_IOCTL_WRITE_SW_REG:
|
|
case DISP_IOCTL_READ_SW_REG:
|
|
/* use function in COLOR module to do ioctl */
|
|
ret = disp_color_ioctl(DISP_MODULE_COLOR0, msg, arg,
|
|
cmdqhandle);
|
|
break;
|
|
default:
|
|
DISP_LOG_W("%s io not supported\n", __func__);
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int dpmgr_path_set_parameter(disp_path_handle dp_handle, int io_evnet,
|
|
void *data)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_get_parameter(disp_path_handle dp_handle, int io_evnet,
|
|
void *data)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_is_idle(disp_path_handle dp_handle)
|
|
{
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
return !dpmgr_path_is_busy(dp_handle);
|
|
}
|
|
|
|
int dpmgr_path_is_busy(disp_path_handle dp_handle)
|
|
{
|
|
int i = 0;
|
|
int m, m_num;
|
|
struct ddp_path_handle *phandle;
|
|
int *list;
|
|
struct DDP_MODULE_DRIVER *m_drv;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
list = ddp_get_scenario_list(phandle->scenario);
|
|
m_num = ddp_get_module_num(phandle->scenario);
|
|
|
|
DISP_LOG_V("path check busy on scenario %s\n",
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
for (i = m_num - 1; i >= 0; i--) {
|
|
m = list[i];
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (!m_drv || !m_drv->is_busy)
|
|
continue;
|
|
|
|
if (m_drv->is_busy(m)) {
|
|
DISP_LOG_V("%s is busy\n", ddp_get_module_name(m));
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_set_lcm_utils(disp_path_handle dp_handle, void *lcm_drv)
|
|
{
|
|
int i = 0;
|
|
int m, m_num;
|
|
int *list;
|
|
struct ddp_path_handle *phandle;
|
|
struct DDP_MODULE_DRIVER *m_drv;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
list = ddp_get_scenario_list(phandle->scenario);
|
|
m_num = ddp_get_module_num(phandle->scenario);
|
|
|
|
DISP_LOG_V("path set lcm drv path handle %p\n", phandle);
|
|
for (i = 0; i < m_num; i++) {
|
|
m = list[i];
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (!m_drv || !m_drv->set_lcm_utils || !lcm_drv)
|
|
continue;
|
|
|
|
DDPDBG("%s set lcm utils\n", ddp_get_module_name(m));
|
|
m_drv->set_lcm_utils(m, lcm_drv);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_enable_event(disp_path_handle dp_handle, enum DISP_PATH_EVENT event)
|
|
{
|
|
struct ddp_path_handle *phandle;
|
|
struct DPMGR_WQ_HANDLE *wq_handle;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
if (event >= DISP_PATH_EVENT_NUM) {
|
|
DISP_LOG_E("%s: error:event:%d\n", __func__, event);
|
|
return 1;
|
|
}
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
wq_handle = &phandle->wq_list[event];
|
|
|
|
DDPDBG("enable event %s on scenario %s, irq_bit 0x%x\n",
|
|
path_event_name(event), ddp_get_scenario_name(phandle->scenario),
|
|
phandle->irq_event_map[event].irq_bit);
|
|
|
|
if (!wq_handle->init) {
|
|
init_waitqueue_head(&(wq_handle->wq));
|
|
wq_handle->init = 1;
|
|
wq_handle->data = 0;
|
|
wq_handle->event = event;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_map_event_to_irq(disp_path_handle dp_handle,
|
|
enum DISP_PATH_EVENT event, enum DDP_IRQ_BIT irq_bit)
|
|
{
|
|
struct ddp_path_handle *phandle;
|
|
struct DDP_IRQ_EVENT_MAPPING *irq_table;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
irq_table = phandle->irq_event_map;
|
|
|
|
if (event < DISP_PATH_EVENT_NUM) {
|
|
DDPDBG("map event %s to irq 0x%x on scenario %s\n",
|
|
path_event_name(event), irq_bit,
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
irq_table[event].irq_bit = irq_bit;
|
|
return 0;
|
|
}
|
|
DISP_LOG_E("fail to map event %s to irq 0x%x on scenario %s\n",
|
|
path_event_name(event), irq_bit,
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
return -1;
|
|
}
|
|
|
|
int dpmgr_disable_event(disp_path_handle dp_handle, enum DISP_PATH_EVENT event)
|
|
{
|
|
struct ddp_path_handle *phandle;
|
|
struct DPMGR_WQ_HANDLE *wq_handle;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
|
|
DDPDBG("disable event %s on scenario %s\n", path_event_name(event),
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
|
|
wq_handle = &phandle->wq_list[event];
|
|
wq_handle->init = 0;
|
|
wq_handle->data = 0;
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_check_status_by_scenario(enum DDP_SCENARIO_ENUM scenario)
|
|
{
|
|
int i = 0;
|
|
int *list = ddp_get_scenario_list(scenario);
|
|
int m_num = ddp_get_module_num(scenario);
|
|
struct DDP_MANAGER_CONTEXT *c = _get_context();
|
|
|
|
DDPDUMP("--> check status on scenario %s\n",
|
|
ddp_get_scenario_name(scenario));
|
|
|
|
if (!c->power_state) {
|
|
DDPDUMP("cannot check ddp status due to already power off\n");
|
|
return 0;
|
|
}
|
|
|
|
ddp_check_path(scenario);
|
|
|
|
DDPDUMP("path:\n");
|
|
for (i = 0; i < m_num; i++)
|
|
DDPDUMP("%s-\n", ddp_get_module_name(list[i]));
|
|
|
|
DDPDUMP("\n");
|
|
|
|
for (i = 0; i < m_num; i++)
|
|
ddp_dump_analysis(list[i]);
|
|
|
|
for (i = 0; i < m_num; i++)
|
|
ddp_dump_reg(list[i]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool dpmgr_is_power_on(void)
|
|
{
|
|
struct DDP_MANAGER_CONTEXT *context = _get_context();
|
|
|
|
return context->power_state;
|
|
}
|
|
|
|
int dpmgr_check_status(disp_path_handle dp_handle)
|
|
{
|
|
int i = 0;
|
|
int *modules;
|
|
int module_num;
|
|
struct ddp_path_handle *handle;
|
|
struct DDP_MANAGER_CONTEXT *context = _get_context();
|
|
|
|
if (!dp_handle) {
|
|
ASSERT(0);
|
|
return -1;
|
|
}
|
|
|
|
handle = (struct ddp_path_handle *)dp_handle;
|
|
modules = ddp_get_scenario_list(handle->scenario);
|
|
module_num = ddp_get_module_num(handle->scenario);
|
|
|
|
DDPDUMP("--> check status on scenario %s\n",
|
|
ddp_get_scenario_name(handle->scenario));
|
|
|
|
if (!(context->power_state)) {
|
|
DDPDUMP("cannot check ddp status due to already power off\n");
|
|
return 0;
|
|
}
|
|
ddp_dump_analysis(DISP_MODULE_CONFIG);
|
|
ddp_check_path(handle->scenario);
|
|
ddp_check_mutex(handle->hwmutexid, handle->scenario, handle->mode);
|
|
/* dump path */
|
|
{
|
|
DDPDUMP("path:\n");
|
|
for (i = 0; i < module_num; i++)
|
|
DDPDUMP("%s-\n", ddp_get_module_name(modules[i]));
|
|
DDPDUMP("\n");
|
|
}
|
|
ddp_dump_analysis(DISP_MODULE_MUTEX);
|
|
for (i = 0; i < module_num; i++)
|
|
ddp_dump_analysis(modules[i]);
|
|
for (i = 0; i < module_num; i++) {
|
|
if (!dpmgr_is_PQ(modules[i]))
|
|
ddp_dump_reg(modules[i]);
|
|
}
|
|
ddp_dump_reg(DISP_MODULE_CONFIG);
|
|
ddp_dump_reg(DISP_MODULE_MUTEX);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void dpmgr_debug_path_status(int mutex_id)
|
|
{
|
|
int i = 0;
|
|
struct DDP_MANAGER_CONTEXT *c = _get_context();
|
|
disp_path_handle phandle = NULL;
|
|
|
|
mutex_lock(&c->mutex_lock);
|
|
if (mutex_id >= DISP_MUTEX_DDP_FIRST &&
|
|
mutex_id < (DISP_MUTEX_DDP_FIRST + DISP_MUTEX_DDP_COUNT)) {
|
|
phandle = (disp_path_handle)c->handle_pool[mutex_id];
|
|
if (phandle)
|
|
dpmgr_check_status(phandle);
|
|
} else {
|
|
for (i = DISP_MUTEX_DDP_FIRST;
|
|
i < (DISP_MUTEX_DDP_FIRST + DISP_MUTEX_DDP_COUNT); i++) {
|
|
phandle = (disp_path_handle)c->handle_pool[i];
|
|
if (phandle)
|
|
dpmgr_check_status(phandle);
|
|
}
|
|
}
|
|
mutex_unlock(&c->mutex_lock);
|
|
}
|
|
|
|
int dpmgr_wait_event_timeout(disp_path_handle dp_handle,
|
|
enum DISP_PATH_EVENT event, int timeout)
|
|
{
|
|
int ret = -1;
|
|
struct ddp_path_handle *phandle;
|
|
struct DPMGR_WQ_HANDLE *wq_handle;
|
|
unsigned long long cur_time;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
wq_handle = &phandle->wq_list[event];
|
|
|
|
if (!wq_handle->init) {
|
|
DISP_LOG_E("wait event %s not initialized on scenario %s\n",
|
|
path_event_name(event),
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
return ret;
|
|
}
|
|
|
|
cur_time = ktime_to_ns(ktime_get());
|
|
|
|
ret = wait_event_interruptible_timeout(wq_handle->wq,
|
|
cur_time < wq_handle->data, timeout);
|
|
if (ret == 0) {
|
|
DISP_LOG_E("wait %s timeout on scenario %s\n",
|
|
path_event_name(event),
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
/* dpmgr_check_status(dp_handle); */
|
|
} else if (ret < 0) {
|
|
DISP_LOG_E("wait %s interrupt by other timeleft %d on scn %s\n",
|
|
path_event_name(event), ret,
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
} else {
|
|
DISP_LOG_V("received event %s timeleft %d on scn %s\n",
|
|
path_event_name(event), ret,
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int _dpmgr_wait_event(disp_path_handle dp_handle, enum DISP_PATH_EVENT event,
|
|
unsigned long long *event_ts)
|
|
{
|
|
int ret = -1;
|
|
struct ddp_path_handle *phandle;
|
|
struct DPMGR_WQ_HANDLE *wq_handle;
|
|
unsigned long long cur_time;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
wq_handle = &phandle->wq_list[event];
|
|
|
|
if (!wq_handle->init) {
|
|
DISP_LOG_E("wait event %s not initialized on scenario %s\n",
|
|
path_event_name(event),
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
return -2;
|
|
}
|
|
|
|
cur_time = ktime_to_ns(ktime_get());
|
|
|
|
ret = wait_event_interruptible(wq_handle->wq,
|
|
cur_time < wq_handle->data);
|
|
if (ret < 0) {
|
|
DISP_LOG_E("wait %s interrupt by other ret %d on scenario %s\n",
|
|
path_event_name(event), ret,
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
}
|
|
if (event_ts)
|
|
*event_ts = wq_handle->data;
|
|
|
|
return ret;
|
|
}
|
|
|
|
int dpmgr_wait_event(disp_path_handle dp_handle, enum DISP_PATH_EVENT event)
|
|
{
|
|
return _dpmgr_wait_event(dp_handle, event, NULL);
|
|
}
|
|
|
|
int dpmgr_wait_event_ts(disp_path_handle dp_handle, enum DISP_PATH_EVENT event,
|
|
unsigned long long *event_ts)
|
|
{
|
|
return _dpmgr_wait_event(dp_handle, event, event_ts);
|
|
}
|
|
|
|
int dpmgr_signal_event(disp_path_handle dp_handle, enum DISP_PATH_EVENT event)
|
|
{
|
|
struct ddp_path_handle *phandle;
|
|
struct DPMGR_WQ_HANDLE *wq_handle;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
if (event >= DISP_PATH_EVENT_NUM) {
|
|
DISP_LOG_E("%s: error:event:%d\n", __func__, event);
|
|
return 1;
|
|
}
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
wq_handle = &phandle->wq_list[event];
|
|
|
|
if (phandle->wq_list[event].init) {
|
|
wq_handle->data = ktime_to_ns(ktime_get());
|
|
wake_up_interruptible(&(phandle->wq_list[event].wq));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void dpmgr_irq_handler(enum DISP_MODULE_ENUM module,
|
|
unsigned int regvalue)
|
|
{
|
|
int i = 0, j = 0;
|
|
int irq_bits_num = 0;
|
|
int irq_bit = 0;
|
|
struct ddp_path_handle *phandle = NULL;
|
|
|
|
phandle = find_handle_by_module(module);
|
|
if (!phandle)
|
|
return;
|
|
|
|
irq_bits_num = ddp_get_module_max_irq_bit(module);
|
|
for (i = 0; i <= irq_bits_num; i++) {
|
|
if (!(regvalue & (0x1 << i)))
|
|
continue;
|
|
|
|
irq_bit = MAKE_DDP_IRQ_BIT(module, i);
|
|
dprec_stub_irq(irq_bit);
|
|
for (j = 0; j < DISP_PATH_EVENT_NUM; j++) {
|
|
if (!phandle->wq_list[j].init ||
|
|
irq_bit != phandle->irq_event_map[j].irq_bit)
|
|
continue;
|
|
|
|
dprec_stub_event(j);
|
|
DDPIRQ("irq signal event %s on cycle %llu on scn %s\n",
|
|
path_event_name(j), phandle->wq_list[j].data,
|
|
ddp_get_scenario_name(phandle->scenario));
|
|
|
|
dpmgr_signal_event(phandle, j);
|
|
}
|
|
}
|
|
}
|
|
|
|
int dpmgr_init(void)
|
|
{
|
|
DISP_LOG_I("ddp manager init\n");
|
|
if (ddp_manager_init)
|
|
return 0;
|
|
|
|
ddp_manager_init = 1;
|
|
ddp_debug_init();
|
|
disp_init_irq();
|
|
disp_register_irq_callback(dpmgr_irq_handler);
|
|
spin_lock_init(&cmdq_dump_lock);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* dpmgr_factory_mode_test
|
|
* dpmgr_factory_mode_reset
|
|
* to be implemented in dsi driver
|
|
* these two functions are used for external display factory mode
|
|
*/
|
|
int dpmgr_factory_mode_test(int m, void *cmdqhandle, void *config)
|
|
{
|
|
struct DDP_MODULE_DRIVER *m_drv = NULL;
|
|
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (!m_drv || !m_drv->ioctl)
|
|
return 0;
|
|
|
|
DISP_LOG_I(" %s factory_mode_test\n",
|
|
ddp_get_module_name(DISP_MODULE_DPI));
|
|
|
|
m_drv = ddp_get_module_driver(DISP_MODULE_DPI);
|
|
if (!m_drv || !m_drv->ioctl)
|
|
return 0;
|
|
|
|
m_drv->ioctl(m, cmdqhandle, DDP_DPI_FACTORY_TEST, config);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_factory_mode_reset(int m, void *cmdqhandle, void *config)
|
|
{
|
|
struct DDP_MODULE_DRIVER *m_drv = NULL;
|
|
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (!m_drv || !m_drv->ioctl)
|
|
return 0;
|
|
|
|
DISP_LOG_I(" %s factory_mode_test\n",
|
|
ddp_get_module_name(DISP_MODULE_DPI));
|
|
|
|
m_drv = ddp_get_module_driver(DISP_MODULE_DPI);
|
|
if (!m_drv || !m_drv->ioctl)
|
|
return 0;
|
|
|
|
m_drv->ioctl(m, cmdqhandle, DDP_DPI_FACTORY_TEST, config);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_wait_ovl_available(int ovl_num)
|
|
{
|
|
int ret = 1;
|
|
|
|
return ret;
|
|
}
|
|
|
|
int switch_module_to_nonsec(disp_path_handle dp_handle, void *cmdqhandle,
|
|
int m, const char *caller)
|
|
{
|
|
int i = 0;
|
|
struct ddp_path_handle *phandle;
|
|
int m_num;
|
|
int *modules;
|
|
struct DDP_MODULE_DRIVER *m_drv;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
modules = ddp_get_scenario_list(phandle->scenario);
|
|
m_num = ddp_get_module_num(phandle->scenario);
|
|
DDPMSG("[SVP] switch module to nonsec on scenario %s, caller=%s\n",
|
|
ddp_get_scenario_name(phandle->scenario), caller);
|
|
|
|
if (m == DISP_MODULE_NUM) {
|
|
for (i = m_num - 1; i >= 0; i--) {
|
|
m = modules[i];
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (m_drv && m_drv->switch_to_nonsec)
|
|
m_drv->switch_to_nonsec(m, cmdqhandle);
|
|
}
|
|
} else {
|
|
m_drv = ddp_get_module_driver(m);
|
|
if (m_drv && m_drv->switch_to_nonsec)
|
|
m_drv->switch_to_nonsec(m, cmdqhandle);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_dsi_power_off(disp_path_handle dp_handle, void *cmdqhandle)
|
|
{
|
|
int m;
|
|
struct ddp_path_handle *phandle;
|
|
enum DISP_MODULE_ENUM dst_module;
|
|
struct DDP_MODULE_DRIVER *m_drv;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
dst_module = ddp_get_dst_module(phandle->scenario);
|
|
|
|
m = dst_module;
|
|
m_drv = ddp_get_module_driver(dst_module);
|
|
if (!m_drv || !m_drv->power_off)
|
|
return 0;
|
|
|
|
DDPDBG("%s power off\n", ddp_get_module_name(dst_module));
|
|
m_drv->power_off(dst_module, cmdqhandle);
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_path_dsi_power_on(disp_path_handle dp_handle, void *cmdqhandle)
|
|
{
|
|
int m;
|
|
struct ddp_path_handle *phandle;
|
|
enum DISP_MODULE_ENUM dst_module;
|
|
struct DDP_MODULE_DRIVER *m_drv;
|
|
|
|
ASSERT(dp_handle);
|
|
|
|
if (dp_handle == NULL)
|
|
return 1;
|
|
|
|
phandle = (struct ddp_path_handle *)dp_handle;
|
|
dst_module = ddp_get_dst_module(phandle->scenario);
|
|
|
|
m = dst_module;
|
|
m_drv = ddp_get_module_driver(dst_module);
|
|
if (!m_drv || !m_drv->power_on)
|
|
return 0;
|
|
|
|
DDPDBG("%s power on\n", ddp_get_module_name(dst_module));
|
|
m_drv->power_on(dst_module, cmdqhandle);
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_register_cmdq_dump_callback(CmdqDumpInfoCB cb)
|
|
{
|
|
int i = 0;
|
|
unsigned long flags;
|
|
|
|
spin_lock_irqsave(&cmdq_dump_lock, flags);
|
|
for (i = 0; i < MAX_SESSION_COUNT; i++) {
|
|
if (cmdq_dump_callback_table[i] == cb)
|
|
break;
|
|
}
|
|
if (i < MAX_SESSION_COUNT) {
|
|
spin_unlock_irqrestore(&cmdq_dump_lock, flags);
|
|
return 0;
|
|
}
|
|
|
|
for (i = 0; i < MAX_SESSION_COUNT; i++) {
|
|
if (cmdq_dump_callback_table[i] == NULL)
|
|
break;
|
|
}
|
|
if (i == MAX_SESSION_COUNT) {
|
|
DDPAEE("not enough cmdq dump callback entries for session\n");
|
|
spin_unlock_irqrestore(&cmdq_dump_lock, flags);
|
|
return -1;
|
|
}
|
|
DDPMSG("register callback on %d\n", i);
|
|
cmdq_dump_callback_table[i] = cb;
|
|
spin_unlock_irqrestore(&cmdq_dump_lock, flags);
|
|
return 0;
|
|
}
|
|
|
|
int dpmgr_unregister_cmdq_dump_callback(CmdqDumpInfoCB cb)
|
|
{
|
|
int i;
|
|
unsigned long flags;
|
|
|
|
spin_lock_irqsave(&cmdq_dump_lock, flags);
|
|
for (i = 0; i < MAX_SESSION_COUNT; i++) {
|
|
if (cmdq_dump_callback_table[i] == cb) {
|
|
cmdq_dump_callback_table[i] = NULL;
|
|
break;
|
|
}
|
|
}
|
|
if (i == MAX_SESSION_COUNT) {
|
|
DDPMSG("%s, fail to unregister callback function %p\n",
|
|
__func__, cb);
|
|
spin_unlock_irqrestore(&cmdq_dump_lock, flags);
|
|
return -1;
|
|
}
|
|
spin_unlock_irqrestore(&cmdq_dump_lock, flags);
|
|
return 0;
|
|
}
|
|
|
|
void dpmgr_invoke_cmdq_dump_callbacks(uint64_t engineFlag, int level)
|
|
{
|
|
int i;
|
|
unsigned long flags;
|
|
|
|
spin_lock_irqsave(&cmdq_dump_lock, flags);
|
|
for (i = 0; i < MAX_SESSION_COUNT; i++) {
|
|
|
|
if (cmdq_dump_callback_table[i])
|
|
cmdq_dump_callback_table[i](engineFlag, level);
|
|
}
|
|
spin_unlock_irqrestore(&cmdq_dump_lock, flags);
|
|
}
|