videotunnel: support ask refresh [1/1]

PD#SWPL-138027

Problem:
videotunnel drive support ask refresh

Solution:
support ask refresh, when use space ask refresh
at leas send one vt buffer

Verify:
ohm

Change-Id: I2255f2b329e09b46ed3218d3b39fdf84ae0d969d
Signed-off-by: baocheng sun <baocheng.sun@amlogic.com>
(cherry picked from commit 575498273e)
This commit is contained in:
baocheng sun
2023-09-14 14:57:45 +08:00
committed by gerrit autosubmit
parent 5b92b285f7
commit cb8ef17327
3 changed files with 180 additions and 76 deletions
@@ -27,6 +27,7 @@ enum vt_ctrl_cmd_e {
VT_CTRL_REPLY_CMD,
VT_CTRL_POLL_CMD,
VT_CTRL_CANCEL_BUFFER,
VT_CTRL_REFRESH,
};
enum vt_video_cmd_e {
@@ -39,6 +40,17 @@ enum vt_video_cmd_e {
VT_VIDEO_SET_COLOR_BLUE,
VT_VIDEO_SET_COLOR_GREEN,
VT_VIDEO_SET_DISPLAY_FRAME,
VT_VIDEO_CMD_INVALID,
};
enum vt_video_status_e {
VT_VIDEO_STATUS_BLANK = 1,
VT_VIDEO_STATUS_HIDE = 2,
VT_VIDEO_STATUS_SHOW = 3,
VT_VIDEO_STATUS_COLOR_ONCE = 4,
VT_VIDEO_STATUS_COLOR_ALWAYS = 5,
VT_VIDEO_STATUS_COLOR_DISABLE = 6,
VT_VIDEO_STATUS_HOLD_FRAME = 7,
};
enum vt_video_type_e {
@@ -190,6 +190,8 @@ static int vt_debug_instance_show(struct seq_file *s, void *unused)
instance->state.dequeue_count,
instance->state.dequeue_invalid);
seq_puts(s, "-----------------------------------------------\n");
seq_printf(s, "need refresh: %d\n", instance->need_refresh);
seq_puts(s, "-----------------------------------------------\n");
mutex_unlock(&instance->lock);
mutex_unlock(&debugfs_mutex);
@@ -445,6 +447,7 @@ static struct vt_instance *vt_instance_create_lock(struct vt_dev *dev)
memset(&instance->backup_sourcecrop, -1, sizeof(instance->backup_sourcecrop));
memset(&instance->backup_displayframe, -1, sizeof(instance->backup_displayframe));
instance->last_cmd.cmd = VT_VIDEO_CMD_INVALID;
instance->dev = dev;
instance->fcount = 0;
instance->mode = VT_MODE_NONE_BLOCK;
@@ -640,6 +643,9 @@ static void vt_session_trim_lock(struct vt_session *session,
}
if (instance->consumer && instance->consumer == session) {
if (instance->need_refresh)
return;
while (kfifo_get(&instance->fifo_to_consumer, &buffer)) {
if (buffer->file_buffer) {
fput(buffer->file_buffer);
@@ -915,15 +921,108 @@ static int vt_free_id_process(struct vt_alloc_id_data *data,
return ret;
}
static int vt_resend_rect_process_locked(struct vt_instance *instance,
enum vt_video_cmd_e type)
{
struct vt_krect *rect = NULL;
struct vt_cmd *cmd_rect;
if (!instance)
return -EINVAL;
if (type == VT_VIDEO_SET_SOURCE_CROP)
rect = &instance->backup_sourcecrop;
else if (type == VT_VIDEO_SET_DISPLAY_FRAME)
rect = &instance->backup_displayframe;
else
return -EINVAL;
if (rect->left >= 0 || rect->top >= 0 ||
rect->right >= 0 || rect->bottom >= 0) {
cmd_rect = kzalloc(sizeof(*cmd_rect), GFP_KERNEL);
if (!cmd_rect)
return -ENOMEM;
cmd_rect->cmd = type;
cmd_rect->rect = *rect;
mutex_lock(&instance->cmd_lock);
kfifo_put(&instance->fifo_cmd, cmd_rect);
vt_debug(VT_DEBUG_CMD, "restore %s rect (%d %d %d %d)\n",
type == VT_VIDEO_SET_SOURCE_CROP ? "source crop" : "disp frame",
cmd_rect->rect.left, cmd_rect->rect.top,
cmd_rect->rect.right, cmd_rect->rect.bottom);
mutex_unlock(&instance->cmd_lock);
}
return 0;
}
static int vt_resend_cmd_process_locked(struct vt_instance *instance,
struct vt_session *session)
{
int ret = 0;
struct vt_cmd *cmd = NULL;
if (!instance || !session)
return -EINVAL;
/* consumer connect, send game mode cmd if needed */
if (instance->mode == VT_MODE_GAME) {
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
cmd->cmd = VT_VIDEO_SET_GAME_MODE;
cmd->cmd_data = 1;
mutex_lock(&instance->cmd_lock);
kfifo_put(&instance->fifo_cmd, cmd);
session->cmd_status++;
vt_debug(VT_DEBUG_CMD, "vt [%d] resend cmd:%d data:%d\n",
instance->id, cmd->cmd, cmd->cmd_data);
mutex_unlock(&instance->cmd_lock);
}
if (instance->last_cmd.cmd == VT_VIDEO_SET_STATUS) {
if (instance->last_cmd.cmd_data == VT_VIDEO_STATUS_HIDE ||
instance->last_cmd.cmd_data == VT_VIDEO_STATUS_COLOR_ALWAYS ||
instance->last_cmd.cmd_data == VT_VIDEO_STATUS_HOLD_FRAME) {
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
cmd->cmd = instance->last_cmd.cmd;
cmd->cmd_data = instance->last_cmd.cmd_data;
mutex_lock(&instance->cmd_lock);
kfifo_put(&instance->fifo_cmd, cmd);
session->cmd_status++;
vt_debug(VT_DEBUG_CMD, "vt [%d] resend cmd:%d data:%d\n",
instance->id, cmd->cmd, cmd->cmd_data);
mutex_unlock(&instance->cmd_lock);
}
}
ret = vt_resend_rect_process_locked(instance, VT_VIDEO_SET_SOURCE_CROP);
if (ret != 0)
return ret;
ret = vt_resend_rect_process_locked(instance, VT_VIDEO_SET_DISPLAY_FRAME);
if (ret != 0)
return ret;
return 0;
}
static int vt_connect_process(struct vt_ctrl_data *data,
struct vt_session *session)
{
struct vt_dev *dev = session->dev;
struct vt_instance *instance;
struct vt_instance *replace;
struct vt_cmd *cmd;
struct vt_cmd *cmd_sourcecrop;
struct vt_cmd *cmd_displayframe;
int id = data->tunnel_id;
int ret = 0;
char name[64];
@@ -990,6 +1089,7 @@ static int vt_connect_process(struct vt_ctrl_data *data,
instance->producer = session;
memset(&instance->backup_sourcecrop, -1, sizeof(instance->backup_sourcecrop));
memset(&instance->backup_displayframe, -1, sizeof(instance->backup_displayframe));
instance->last_cmd.cmd = VT_VIDEO_CMD_INVALID;
} else if (data->role == VT_ROLE_CONSUMER) {
if (instance->consumer &&
instance->consumer != session) {
@@ -1000,81 +1100,17 @@ static int vt_connect_process(struct vt_ctrl_data *data,
return -EINVAL;
}
/* consumer connect, send game mode cmd if needed */
if (instance->mode == VT_MODE_GAME) {
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
mutex_unlock(&instance->lock);
vt_instance_put(instance);
pr_err("Connect to vt [%d] err, resend cmd fail\n",
id);
return -ENOMEM;
}
cmd->cmd = VT_VIDEO_SET_GAME_MODE;
cmd->cmd_data = 1;
mutex_lock(&instance->cmd_lock);
kfifo_put(&instance->fifo_cmd, cmd);
session->cmd_status++;
vt_debug(VT_DEBUG_CMD, "vt [%d] resend cmd:%d data:%d\n",
instance->id, cmd->cmd, cmd->cmd_data);
mutex_unlock(&instance->cmd_lock);
ret = vt_resend_cmd_process_locked(instance, session);
if (ret != 0) {
mutex_unlock(&instance->lock);
vt_instance_put(instance);
pr_err("Connect to vt [%d], resend cmd fail\n", id);
return ret;
}
if (instance->backup_sourcecrop.left >= 0 ||
instance->backup_sourcecrop.top >= 0 ||
instance->backup_sourcecrop.right >= 0 ||
instance->backup_sourcecrop.bottom >= 0) {
cmd_sourcecrop = kzalloc(sizeof(*cmd_sourcecrop), GFP_KERNEL);
if (!cmd_sourcecrop) {
mutex_unlock(&instance->lock);
vt_instance_put(instance);
pr_err("Connect to vt [%d] err, resend cmd fail\n",
id);
return -ENOMEM;
}
cmd_sourcecrop->cmd = VT_VIDEO_SET_SOURCE_CROP;
cmd_sourcecrop->rect = instance->backup_sourcecrop;
mutex_lock(&instance->cmd_lock);
kfifo_put(&instance->fifo_cmd, cmd_sourcecrop);
session->cmd_status++;
vt_debug(VT_DEBUG_CMD, "restore source crop rect (%d %d %d %d)\n",
cmd_sourcecrop->rect.left, cmd_sourcecrop->rect.top,
cmd_sourcecrop->rect.right, cmd_sourcecrop->rect.bottom);
mutex_unlock(&instance->cmd_lock);
}
if (instance->backup_displayframe.left >= 0 ||
instance->backup_displayframe.top >= 0 ||
instance->backup_displayframe.right >= 0 ||
instance->backup_displayframe.bottom >= 0) {
cmd_displayframe = kzalloc(sizeof(*cmd_displayframe), GFP_KERNEL);
if (!cmd_displayframe) {
mutex_unlock(&instance->lock);
vt_instance_put(instance);
pr_err("Connect to vt [%d] err, resend cmd fail\n",
id);
return -ENOMEM;
}
cmd_displayframe->cmd = VT_VIDEO_SET_DISPLAY_FRAME;
cmd_displayframe->rect = instance->backup_displayframe;
mutex_lock(&instance->cmd_lock);
kfifo_put(&instance->fifo_cmd, cmd_displayframe);
session->cmd_status++;
vt_debug(VT_DEBUG_CMD, "restore display frame rect (%d %d %d %d)\n",
cmd_displayframe->rect.left, cmd_displayframe->rect.top,
cmd_displayframe->rect.right, cmd_displayframe->rect.bottom);
mutex_unlock(&instance->cmd_lock);
}
instance->consumer = session;
instance->need_refresh = false;
}
session->cid = vt_get_connected_id();
session->role = data->role;
instance->used = true;
@@ -1114,6 +1150,7 @@ static int vt_disconnect_process(struct vt_ctrl_data *data,
instance->mode = VT_MODE_NONE_BLOCK;
memset(&instance->backup_sourcecrop, -1, sizeof(instance->backup_sourcecrop));
memset(&instance->backup_displayframe, -1, sizeof(instance->backup_displayframe));
instance->last_cmd.cmd = VT_VIDEO_CMD_INVALID;
} else if (data->role == VT_ROLE_CONSUMER) {
if (!instance->consumer)
goto disconnect_fail;
@@ -1122,6 +1159,7 @@ static int vt_disconnect_process(struct vt_ctrl_data *data,
vt_session_trim_lock(session, instance);
instance->consumer = NULL;
instance->need_refresh = false;
}
vt_debug(VT_DEBUG_USER, "vt [%d] %s-%d disconnect, instance ref %d, fcount %d\n",
@@ -1200,6 +1238,7 @@ static int vt_send_cmd_process(struct vt_ctrl_data *data,
cmd->rect.right, cmd->rect.bottom);
else
vt_debug(VT_DEBUG_CMD, "data:%d\n", cmd->cmd_data);
instance->last_cmd = *cmd;
mutex_unlock(&instance->cmd_lock);
mutex_lock(&instance->lock);
@@ -1383,6 +1422,30 @@ static int vt_cancel_buffer_process(struct vt_ctrl_data *data,
return 0;
}
static int vt_refresh_process(struct vt_ctrl_data *data, struct vt_session *session)
{
struct vt_dev *dev = session->dev;
struct vt_instance *instance = NULL;
int id = data->tunnel_id;
instance = idr_find(&dev->instance_idr, id);
if (!instance)
return -EINVAL;
if (instance->consumer && instance->consumer != session)
return -EINVAL;
mutex_lock(&instance->lock);
if (data->video_cmd_data == 0)
instance->need_refresh = false;
else
instance->need_refresh = true;
vt_debug(VT_DEBUG_CMD, "vt [%d] ask refresh\n", instance->id);
mutex_unlock(&instance->lock);
return 0;
}
static int vt_ctrl_process(struct vt_ctrl_data *data,
struct vt_session *session)
{
@@ -1427,6 +1490,11 @@ static int vt_ctrl_process(struct vt_ctrl_data *data,
ret = vt_cancel_buffer_process(data, session);
break;
}
case VT_CTRL_REFRESH: {
ret = vt_refresh_process(data, session);
break;
}
default:
pr_err("unknown videotunnel cmd:%d\n", data->ctrl_cmd);
return -EINVAL;
@@ -1855,7 +1923,29 @@ static int vt_release_buffer_process(struct vt_buffer_data *data,
"vt [%d] releasebuffer fence file(%px) fence fd(%d)\n",
instance->id, buffer->file_fence, data->fence_fd);
kfifo_put(&instance->fifo_to_producer, buffer);
if (instance->need_refresh && kfifo_is_empty(&instance->fifo_to_consumer)) {
if (buffer->file_fence) {
fput(buffer->file_fence);
dev->state.fence_put++;
instance->state.fence_put++;
buffer->file_fence = NULL;
}
/* need add ref of buffer file */
get_file(buffer->file_buffer);
buffer->buffer_fd_con = -1;
buffer->item.buffer_status = VT_BUFFER_QUEUE;
kfifo_put(&instance->fifo_to_consumer, buffer);
dev->state.queue_count++;
instance->state.queue_count++;
vt_debug(VT_DEBUG_BUFFERS,
"vt [%d] refresh once pfd: %d, buffer(%p) buffer file(%px) timestamp(%lld)\n",
instance->id, buffer->buffer_fd_pro, buffer,
buffer->file_buffer, buffer->item.time_stamp);
} else {
kfifo_put(&instance->fifo_to_producer, buffer);
}
mutex_unlock(&instance->lock);
if (instance->producer) {
@@ -240,6 +240,8 @@ struct vt_instance {
struct vt_state state;
struct vt_krect backup_sourcecrop;
struct vt_krect backup_displayframe;
bool need_refresh;
struct vt_cmd last_cmd;
};
#endif /* __VIDEO_TUNNEL_PRIV_H */