blob: d6b311245d8fbe6be7a7991b52fbb94e917891c7 [file] [log] [blame]
/*
* Samsung Exynos SoC series VPU driver
*
* Copyright (c) 2015 Samsung Electronics Co., Ltd
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include "vpu-debug.h"
#include "vpu-framemgr.h"
#include "vpu-graphmgr.h"
void vpu_frame_s_free(struct vpu_framemgr *framemgr, struct vpu_frame *frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
frame->state = VPU_FRAME_STATE_FREE;
list_add_tail(&frame->list, &framemgr->fre_list);
framemgr->fre_cnt++;
}
void vpu_frame_g_free(struct vpu_framemgr *framemgr, struct vpu_frame **frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
if (framemgr->fre_cnt &&
(*frame = container_of(framemgr->fre_list.next, struct vpu_frame, list))) {
list_del(&(*frame)->list);
framemgr->fre_cnt--;
(*frame)->state = VPU_FRAME_STATE_INVALID;
} else {
*frame = NULL;
}
}
void vpu_frame_free_head(struct vpu_framemgr *framemgr, struct vpu_frame **frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
if (framemgr->fre_cnt)
*frame = container_of(framemgr->fre_list.next, struct vpu_frame, list);
else
*frame = NULL;
}
void vpu_frame_free_tail(struct vpu_framemgr *framemgr, struct vpu_frame **frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
if (framemgr->fre_cnt)
*frame = container_of(framemgr->fre_list.prev, struct vpu_frame, list);
else
*frame = NULL;
}
void vpu_frame_print_free_list(struct vpu_framemgr *framemgr)
{
DLOG_INIT();
struct vpu_frame *frame, *temp;
DLOG("[FRM] fre(%d, %d) :", framemgr->id, framemgr->fre_cnt);
list_for_each_entry_safe(frame, temp, &framemgr->fre_list, list) {
DLOG("%d->", frame->index);
}
DLOG("X");
vpu_info("%s\n", DLOG_OUT());
}
void vpu_frame_s_request(struct vpu_framemgr *framemgr, struct vpu_frame *frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
frame->state = VPU_FRAME_STATE_REQUEST;
list_add_tail(&frame->list, &framemgr->req_list);
framemgr->req_cnt++;
}
void vpu_frame_g_request(struct vpu_framemgr *framemgr, struct vpu_frame **frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
if (framemgr->req_cnt &&
(*frame = container_of(framemgr->req_list.next, struct vpu_frame, list))) {
list_del(&(*frame)->list);
framemgr->req_cnt--;
(*frame)->state = VPU_FRAME_STATE_INVALID;
} else {
*frame = NULL;
}
}
void vpu_frame_request_head(struct vpu_framemgr *framemgr, struct vpu_frame **frame)
{
if (framemgr->req_cnt)
*frame = container_of(framemgr->req_list.next, struct vpu_frame, list);
else
*frame = NULL;
}
void vpu_frame_request_tail(struct vpu_framemgr *framemgr, struct vpu_frame **frame)
{
if (framemgr->req_cnt)
*frame = container_of(framemgr->req_list.prev, struct vpu_frame, list);
else
*frame = NULL;
}
void vpu_frame_print_request_list(struct vpu_framemgr *framemgr)
{
DLOG_INIT();
struct vpu_frame *frame, *temp;
DLOG("[FRM] req(%d, %d) :", framemgr->id, framemgr->req_cnt);
list_for_each_entry_safe(frame, temp, &framemgr->req_list, list) {
DLOG("%d->", frame->index);
}
DLOG("X");
vpu_info("%s\n", DLOG_OUT());
}
void vpu_frame_s_prepare(struct vpu_framemgr *framemgr, struct vpu_frame *frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
frame->state = VPU_FRAME_STATE_PREPARE;
list_add_tail(&frame->list, &framemgr->pre_list);
framemgr->pre_cnt++;
}
void vpu_frame_g_prepare(struct vpu_framemgr *framemgr, struct vpu_frame **frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
if (framemgr->pre_cnt &&
(*frame = container_of(framemgr->pre_list.next, struct vpu_frame, list))) {
list_del(&(*frame)->list);
framemgr->pre_cnt--;
(*frame)->state = VPU_FRAME_STATE_INVALID;
} else {
*frame = NULL;
}
}
void vpu_frame_prepare_head(struct vpu_framemgr *framemgr, struct vpu_frame **frame)
{
if (framemgr->pre_cnt)
*frame = container_of(framemgr->pre_list.next, struct vpu_frame, list);
else
*frame = NULL;
}
void vpu_frame_prepare_tail(struct vpu_framemgr *framemgr, struct vpu_frame **frame)
{
if (framemgr->pre_cnt)
*frame = container_of(framemgr->pre_list.prev, struct vpu_frame, list);
else
*frame = NULL;
}
void vpu_frame_print_prepare_list(struct vpu_framemgr *framemgr)
{
DLOG_INIT();
struct vpu_frame *frame, *temp;
DLOG("[FRM] pre(%d, %d) :", framemgr->id, framemgr->pre_cnt);
list_for_each_entry_safe(frame, temp, &framemgr->pre_list, list) {
DLOG("%d->", frame->index);
}
DLOG("X");
vpu_info("%s\n", DLOG_OUT());
}
void vpu_frame_s_process(struct vpu_framemgr *framemgr, struct vpu_frame *frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
frame->state = VPU_FRAME_STATE_PROCESS;
list_add_tail(&frame->list, &framemgr->pro_list);
framemgr->pro_cnt++;
}
void vpu_frame_g_process(struct vpu_framemgr *framemgr, struct vpu_frame **frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
if (framemgr->pro_cnt &&
(*frame = container_of(framemgr->pro_list.next, struct vpu_frame, list))) {
list_del(&(*frame)->list);
framemgr->pro_cnt--;
(*frame)->state = VPU_FRAME_STATE_INVALID;
} else {
*frame = NULL;
}
}
void vpu_frame_process_head(struct vpu_framemgr *framemgr, struct vpu_frame **frame)
{
if (framemgr->pro_cnt)
*frame = container_of(framemgr->pro_list.next, struct vpu_frame, list);
else
*frame = NULL;
}
void vpu_frame_process_tail(struct vpu_framemgr *framemgr, struct vpu_frame **frame)
{
if (framemgr->pro_cnt)
*frame = container_of(framemgr->pro_list.prev, struct vpu_frame, list);
else
*frame = NULL;
}
void vpu_frame_print_process_list(struct vpu_framemgr *framemgr)
{
DLOG_INIT();
struct vpu_frame *frame, *temp;
DLOG("[FRM] pro(%d, %d) :", framemgr->id, framemgr->pro_cnt);
list_for_each_entry_safe(frame, temp, &framemgr->pro_list, list) {
DLOG("%d->", frame->index);
}
DLOG("X");
vpu_info("%s\n", DLOG_OUT());
}
void vpu_frame_s_complete(struct vpu_framemgr *framemgr, struct vpu_frame *frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
frame->state = VPU_FRAME_STATE_COMPLETE;
list_add_tail(&frame->list, &framemgr->com_list);
framemgr->com_cnt++;
}
void vpu_frame_g_complete(struct vpu_framemgr *framemgr, struct vpu_frame **frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
if (framemgr->com_cnt &&
(*frame = container_of(framemgr->com_list.next, struct vpu_frame, list))) {
list_del(&(*frame)->list);
framemgr->com_cnt--;
(*frame)->state = VPU_FRAME_STATE_INVALID;
} else {
*frame = NULL;
}
}
void vpu_frame_complete_head(struct vpu_framemgr *framemgr, struct vpu_frame **frame)
{
if (framemgr->com_cnt)
*frame = container_of(framemgr->com_list.next, struct vpu_frame, list);
else
*frame = NULL;
}
void vpu_frame_complete_tail(struct vpu_framemgr *framemgr, struct vpu_frame **frame)
{
if (framemgr->com_cnt)
*frame = container_of(framemgr->com_list.prev, struct vpu_frame, list);
else
*frame = NULL;
}
void vpu_frame_print_complete_list(struct vpu_framemgr *framemgr)
{
DLOG_INIT();
struct vpu_frame *frame, *temp;
DLOG("[FRM] com(%d, %d) :", framemgr->id, framemgr->com_cnt);
list_for_each_entry_safe(frame, temp, &framemgr->com_list, list) {
DLOG("%d->", frame->index);
}
DLOG("X");
vpu_info("%s\n", DLOG_OUT());
}
void vpu_frame_trans_fre_to_req(struct vpu_framemgr *framemgr, struct vpu_frame *frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
BUG_ON(!framemgr->fre_cnt);
BUG_ON(frame->state != VPU_FRAME_STATE_FREE);
list_del(&frame->list);
framemgr->fre_cnt--;
vpu_frame_s_request(framemgr, frame);
}
void vpu_frame_trans_req_to_pre(struct vpu_framemgr *framemgr, struct vpu_frame *frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
BUG_ON(!framemgr->req_cnt);
BUG_ON(frame->state != VPU_FRAME_STATE_REQUEST);
list_del(&frame->list);
framemgr->req_cnt--;
vpu_frame_s_prepare(framemgr, frame);
}
void vpu_frame_trans_req_to_pro(struct vpu_framemgr *framemgr, struct vpu_frame *frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
BUG_ON(!framemgr->req_cnt);
BUG_ON(frame->state != VPU_FRAME_STATE_REQUEST);
list_del(&frame->list);
framemgr->req_cnt--;
vpu_frame_s_process(framemgr, frame);
}
void vpu_frame_trans_req_to_com(struct vpu_framemgr *framemgr, struct vpu_frame *frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
BUG_ON(!framemgr->req_cnt);
BUG_ON(frame->state != VPU_FRAME_STATE_REQUEST);
list_del(&frame->list);
framemgr->req_cnt--;
vpu_frame_s_complete(framemgr, frame);
}
void vpu_frame_trans_req_to_fre(struct vpu_framemgr *framemgr, struct vpu_frame *frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
BUG_ON(!framemgr->req_cnt);
BUG_ON(frame->state != VPU_FRAME_STATE_REQUEST);
list_del(&frame->list);
framemgr->req_cnt--;
vpu_frame_s_free(framemgr, frame);
}
void vpu_frame_trans_pre_to_pro(struct vpu_framemgr *framemgr, struct vpu_frame *frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
BUG_ON(!framemgr->pre_cnt);
BUG_ON(frame->state != VPU_FRAME_STATE_PREPARE);
list_del(&frame->list);
framemgr->pre_cnt--;
vpu_frame_s_process(framemgr, frame);
}
void vpu_frame_trans_pre_to_com(struct vpu_framemgr *framemgr, struct vpu_frame *frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
BUG_ON(!framemgr->pre_cnt);
BUG_ON(frame->state != VPU_FRAME_STATE_PREPARE);
list_del(&frame->list);
framemgr->pre_cnt--;
vpu_frame_s_complete(framemgr, frame);
}
void vpu_frame_trans_pre_to_fre(struct vpu_framemgr *framemgr, struct vpu_frame *frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
BUG_ON(!framemgr->pre_cnt);
BUG_ON(frame->state != VPU_FRAME_STATE_PREPARE);
list_del(&frame->list);
framemgr->pre_cnt--;
vpu_frame_s_free(framemgr, frame);
}
void vpu_frame_trans_pro_to_com(struct vpu_framemgr *framemgr, struct vpu_frame *frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
BUG_ON(!framemgr->pro_cnt);
BUG_ON(frame->state != VPU_FRAME_STATE_PROCESS);
list_del(&frame->list);
framemgr->pro_cnt--;
vpu_frame_s_complete(framemgr, frame);
}
void vpu_frame_trans_pro_to_fre(struct vpu_framemgr *framemgr, struct vpu_frame *frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
BUG_ON(!framemgr->pro_cnt);
BUG_ON(frame->state != VPU_FRAME_STATE_PROCESS);
list_del(&frame->list);
framemgr->pro_cnt--;
vpu_frame_s_free(framemgr, frame);
}
void vpu_frame_trans_com_to_fre(struct vpu_framemgr *framemgr, struct vpu_frame *frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
BUG_ON(!framemgr->com_cnt);
BUG_ON(frame->state != VPU_FRAME_STATE_COMPLETE);
list_del(&frame->list);
framemgr->com_cnt--;
vpu_frame_s_free(framemgr, frame);
}
void vpu_frame_trans_any_to_fre(struct vpu_framemgr *framemgr, struct vpu_frame *frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
list_del(&frame->list);
switch (frame->state) {
case VPU_FRAME_STATE_REQUEST:
framemgr->req_cnt--;
break;
case VPU_FRAME_STATE_PREPARE:
framemgr->pre_cnt--;
break;
case VPU_FRAME_STATE_PROCESS:
framemgr->pro_cnt--;
break;
case VPU_FRAME_STATE_COMPLETE:
framemgr->com_cnt--;
break;
default:
BUG();
break;
}
vpu_frame_s_free(framemgr, frame);
}
void vpu_frame_pick_fre_to_req(struct vpu_framemgr *framemgr, struct vpu_frame **frame)
{
BUG_ON(!framemgr);
BUG_ON(!frame);
vpu_frame_free_head(framemgr, frame);
if (*frame)
vpu_frame_trans_fre_to_req(framemgr, *frame);
}
void vpu_frame_print_all(struct vpu_framemgr *framemgr)
{
BUG_ON(!framemgr);
vpu_frame_print_request_list(framemgr);
vpu_frame_print_prepare_list(framemgr);
vpu_frame_print_process_list(framemgr);
vpu_frame_print_complete_list(framemgr);
}
int vpu_frame_init(struct vpu_framemgr *framemgr, void *owner)
{
int ret = 0;
unsigned long flags;
u32 index;
spin_lock_irqsave(&framemgr->slock, flags);
INIT_LIST_HEAD(&framemgr->fre_list);
INIT_LIST_HEAD(&framemgr->req_list);
INIT_LIST_HEAD(&framemgr->pre_list);
INIT_LIST_HEAD(&framemgr->pro_list);
INIT_LIST_HEAD(&framemgr->com_list);
framemgr->tot_cnt = VPU_MAX_FRAME;
framemgr->fre_cnt = 0;
framemgr->req_cnt = 0;
framemgr->pre_cnt = 0;
framemgr->pro_cnt = 0;
framemgr->com_cnt = 0;
/* frame index 0 means invalid because firmware can't accept 0 invocation id */
for (index = 1; index < framemgr->tot_cnt; ++index) {
framemgr->frame[index].index = index;
framemgr->frame[index].owner = owner;
framemgr->frame[index].findex = VPU_MAX_FRAME;
framemgr->frame[index].gindex = VPU_MAX_GFRAME;
vpu_frame_s_free(framemgr, &framemgr->frame[index]);
}
spin_unlock_irqrestore(&framemgr->slock, flags);
return ret;
}
int vpu_frame_deinit(struct vpu_framemgr *framemgr)
{
int ret = 0;
unsigned long flags;
u32 index;
spin_lock_irqsave(&framemgr->slock, flags);
for (index = 0; index < framemgr->tot_cnt; ++index)
vpu_frame_s_free(framemgr, &framemgr->frame[index]);
spin_unlock_irqrestore(&framemgr->slock, flags);
return ret;
}
void vpu_frame_flush(struct vpu_framemgr *framemgr)
{
unsigned long flag;
struct vpu_frame *frame, *temp;
BUG_ON(!framemgr);
spin_lock_irqsave(&framemgr->slock, flag);
list_for_each_entry_safe(frame, temp, &framemgr->req_list, list) {
vpu_frame_trans_req_to_fre(framemgr, frame);
vpu_warn("req frame%d is flushed(count : %d)", frame->id, framemgr->req_cnt);
}
list_for_each_entry_safe(frame, temp, &framemgr->pre_list, list) {
vpu_frame_trans_pre_to_fre(framemgr, frame);
vpu_warn("pre frame%d is flushed(count : %d)", frame->id, framemgr->pre_cnt);
}
list_for_each_entry_safe(frame, temp, &framemgr->pro_list, list) {
vpu_frame_trans_pro_to_fre(framemgr, frame);
vpu_warn("pro frame%d is flushed(count : %d)", frame->id, framemgr->pro_cnt);
}
list_for_each_entry_safe(frame, temp, &framemgr->com_list, list) {
vpu_frame_trans_com_to_fre(framemgr, frame);
vpu_warn("com frame%d is flushed(count : %d)", frame->id, framemgr->com_cnt);
}
spin_unlock_irqrestore(&framemgr->slock, flag);
BUG_ON(framemgr->fre_cnt != (framemgr->tot_cnt - 1));
}