blob: 7c55784ebaed81ed52433174415242ca03abcbf0 [file] [log] [blame]
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
*/
#include "video_core_type.h"
#include "vid_frame_scheduler_api.h"
#include "vid_frame_scheduler.h"
enum sched_status sched_create(
struct sched_init_param *init_param, void **handle)
{
struct sched_ctx *sched_ctx;
SCHED_MSG_HIGH("sched_create API");
if (!handle || !init_param) {
SCHED_MSG_ERR
("Bad input parameters: handle=%p, init_param=%p",
handle, init_param);
return SCHED_S_EBADPARM;
}
if (!init_param->perf_lvl) {
SCHED_MSG_ERR("Invalid Perf level=%u",
init_param->perf_lvl);
return SCHED_S_EBADPARM;
}
sched_ctx =
(struct sched_ctx *)
SCHED_MALLOC(sizeof(struct sched_ctx));
if (!sched_ctx) {
SCHED_MSG_ERR("Could not allocate sched ctx. Out of memory");
return SCHED_S_ENOMEM;
}
SCHED_MEMSET(sched_ctx, 0, sizeof(struct sched_ctx));
sched_ctx->perf_lvl = init_param->perf_lvl;
if (SCHED_FAILED(SCHED_CRITSEC_CREATE(&sched_ctx->sched_cs))) {
SCHED_FREE(sched_ctx);
return SCHED_S_EFAIL;
}
*handle = sched_ctx;
SCHED_MSG_MED("Sched instance created. All went well");
return SCHED_S_OK;
}
enum sched_status sched_destroy(void *handle)
{
struct sched_ctx *sched_ctx = (struct sched_ctx *)handle;
SCHED_MSG_HIGH("sched_destroy API");
if (!sched_ctx) {
SCHED_MSG_ERR("Bad input parameters");
return SCHED_S_EBADPARM;
}
(void)SCHED_CRITSEC_ENTER(sched_ctx->sched_cs);
(void)sched_clear_clnt_list(sched_ctx->rt_head);
(void)sched_clear_clnt_list(sched_ctx->rt_head);
SCHED_MSG_MED("Sched clnt lists are cleared & released");
(void)SCHED_CRITSEC_LEAVE(sched_ctx->sched_cs);
(void)SCHED_CRITSEC_RELEASE(sched_ctx->sched_cs);
SCHED_MEMSET(sched_ctx, 0, sizeof(struct sched_ctx));
SCHED_FREE(sched_ctx);
SCHED_MSG_MED("Sched instance deleted");
return SCHED_S_OK;
}
enum sched_status sched_get_param(
void *handle,
enum sched_index param_index,
union sched_value_type *param_value)
{
struct sched_ctx *sched_ctx = (struct sched_ctx *)handle;
enum sched_status status;
SCHED_MSG_HIGH("sched_get_param API");
if (!sched_ctx || !param_value) {
SCHED_MSG_ERR
("Bad input parameters: sched_ctx=%p, param_value=%p",
sched_ctx, param_value);
return SCHED_S_EBADPARM;
}
(void)SCHED_CRITSEC_ENTER(sched_ctx->sched_cs);
status =
sched_process_sched_lvl_get_param(sched_ctx, param_index,
param_value);
(void)SCHED_CRITSEC_LEAVE(sched_ctx->sched_cs);
return status;
}
enum sched_status sched_set_param(
void *handle,
enum sched_index param_index,
union sched_value_type *param_value)
{
struct sched_ctx *sched_ctx = (struct sched_ctx *)handle;
enum sched_status status;
SCHED_MSG_HIGH("sched_set_param API");
if (!sched_ctx || !param_value) {
SCHED_MSG_ERR
("Bad input parameters: sched_ctx=%p, param_value=%p",
sched_ctx, param_value);
return SCHED_S_EBADPARM;
}
(void)SCHED_CRITSEC_ENTER(sched_ctx->sched_cs);
status =
sched_process_sched_lvl_set_param(sched_ctx, param_index,
param_value);
(void)SCHED_CRITSEC_LEAVE(sched_ctx->sched_cs);
return status;
}
enum sched_status sched_add_client(
void *handle,
struct sched_client_init_param *init_param,
void **client_hdl)
{
struct sched_ctx *sched_ctx = (struct sched_ctx *)handle;
enum sched_status status = SCHED_S_OK;
struct _sched_clnt_list_node *new_clnt;
SCHED_MSG_HIGH("sched_add_client API");
if (!sched_ctx || !init_param ||
!client_hdl) {
SCHED_MSG_ERR("Bad input parameters");
return SCHED_S_EBADPARM;
}
new_clnt = (struct _sched_clnt_list_node *)
SCHED_MALLOC(sizeof(struct _sched_clnt_list_node));
if (!new_clnt) {
SCHED_MSG_ERR("Could not allocate client ctx. Out of memory");
return SCHED_S_ENOMEM;
}
(void)SCHED_CRITSEC_ENTER(sched_ctx->sched_cs);
status = sched_process_add_clnt(sched_ctx, new_clnt, init_param);
if (SCHED_FAILED(status)) {
SCHED_MSG_ERR("Add_client failed with err=%d", status);
sched_free_clnt_node(new_clnt);
new_clnt = NULL;
}
(void)SCHED_CRITSEC_LEAVE(sched_ctx->sched_cs);
*client_hdl = new_clnt;
SCHED_MSG_MED("Sched client instance created. All went well");
return status;
}
enum sched_status sched_remove_client(void *handle, void *client_hdl)
{
struct sched_ctx *sched_ctx = (struct sched_ctx *)handle;
struct _sched_clnt_list_node *clnt_node =
(struct _sched_clnt_list_node *)client_hdl;
enum sched_status status = SCHED_S_OK;
SCHED_MSG_HIGH("sched_remove_client API");
if (!sched_ctx || !clnt_node) {
SCHED_MSG_ERR
("Bad input parameters: sched_ctx=%p, clnt_node=%p",
sched_ctx, clnt_node);
return SCHED_S_EBADPARM;
}
(void)SCHED_CRITSEC_ENTER(sched_ctx->sched_cs);
status = sched_process_remove_clnt(sched_ctx, clnt_node);
(void)SCHED_CRITSEC_LEAVE(sched_ctx->sched_cs);
return status;
}
enum sched_status sched_flush_client_buffer(
void *handle, void *client_hdl, void **pp_frm_data)
{
struct sched_ctx *sched_ctx = (struct sched_ctx *)handle;
struct _sched_clnt_list_node *clnt_node =
(struct _sched_clnt_list_node *)client_hdl;
enum sched_status status = SCHED_S_OK;
SCHED_MSG_HIGH("sched_flush_client_buffer API");
if (!sched_ctx || !clnt_node || !pp_frm_data) {
SCHED_MSG_ERR
("Bad input parameters: sched_ctx=%p, clnt_node=%p",
sched_ctx, clnt_node);
return SCHED_S_EBADPARM;
}
(void)SCHED_CRITSEC_ENTER(clnt_node->data.clnt_cs);
status =
sched_process_flush_clnt_buff(sched_ctx, clnt_node,
pp_frm_data);
(void)SCHED_CRITSEC_LEAVE(clnt_node->data.clnt_cs);
return status;
}
enum sched_status sched_mark_client_eof(void *handle, void *client_hdl)
{
struct sched_ctx *sched_ctx = (struct sched_ctx *)handle;
struct _sched_clnt_list_node *clnt_node =
(struct _sched_clnt_list_node *)client_hdl;
enum sched_status status = SCHED_S_OK;
SCHED_MSG_HIGH("sched_mark_client_eof API");
if (!sched_ctx || !clnt_node) {
SCHED_MSG_ERR
("Bad input parameters: sched_ctx=%p, clnt_node=%p",
sched_ctx, clnt_node);
return SCHED_S_EBADPARM;
}
(void)SCHED_CRITSEC_ENTER(clnt_node->data.clnt_cs);
status = sched_process_mark_clnt_eof(sched_ctx, clnt_node);
(void)SCHED_CRITSEC_LEAVE(clnt_node->data.clnt_cs);
return status;
}
enum sched_status sched_update_client_o_tkn(
void *handle, void *client_hdl, u32 type, u32 o_tkn)
{
struct sched_ctx *sched_ctx = (struct sched_ctx *)handle;
struct _sched_clnt_list_node *clnt_node =
(struct _sched_clnt_list_node *)client_hdl;
enum sched_status status = SCHED_S_OK;
SCHED_MSG_HIGH("sched_restore_client_o_tkn API");
if (!sched_ctx || !clnt_node) {
SCHED_MSG_ERR
("Bad input parameters: sched_ctx=%p, clnt_node=%p",
sched_ctx, clnt_node);
return SCHED_S_EBADPARM;
}
(void)SCHED_CRITSEC_ENTER(clnt_node->data.clnt_cs);
status =
sched_process_update_clnt_o_tkn(sched_ctx, clnt_node, type,
o_tkn);
(void)SCHED_CRITSEC_LEAVE(clnt_node->data.clnt_cs);
return status;
}
enum sched_status sched_queue_frame(
void *handle, void *client_hdl, void *frm_data)
{
struct sched_ctx *sched_ctx = (struct sched_ctx *)handle;
struct _sched_clnt_list_node *clnt_node =
(struct _sched_clnt_list_node *)client_hdl;
enum sched_status status = SCHED_S_OK;
SCHED_MSG_HIGH("sched_queue_frame API");
if (!sched_ctx || !clnt_node) {
SCHED_MSG_ERR
("Bad input parameters: sched_ctx=%p, clnt_node=%p",
sched_ctx, clnt_node);
return SCHED_S_EBADPARM;
}
(void)SCHED_CRITSEC_ENTER(clnt_node->data.clnt_cs);
status = sched_process_en_q_frm(sched_ctx, clnt_node, frm_data);
(void)SCHED_CRITSEC_LEAVE(clnt_node->data.clnt_cs);
return status;
}
enum sched_status sched_re_queue_frame(
void *handle, void *client_hdl, void *frm_data)
{
struct sched_ctx* sched_ctx = (struct sched_ctx *)handle;
struct _sched_clnt_list_node *clnt_node =
(struct _sched_clnt_list_node *)client_hdl;
enum sched_status status = SCHED_S_OK;
SCHED_MSG_HIGH("\n sched_re_queue_frame API");
if (!sched_ctx || !clnt_node) {
SCHED_MSG_ERR("Bad input parameters:"
"sched_ctx=%p, clnt_node=%p",
sched_ctx, clnt_node);
return SCHED_S_EBADPARM;
}
(void)SCHED_CRITSEC_ENTER(clnt_node->data.clnt_cs);
status = sched_process_re_en_q_frm(sched_ctx, clnt_node,
frm_data);
(void)SCHED_CRITSEC_LEAVE(clnt_node->data.clnt_cs);
return status;
}
enum sched_status sched_de_queue_frame(
void *handle, void **pp_frm_data, void **pp_client_data)
{
struct sched_ctx *sched_ctx = (struct sched_ctx *)handle;
enum sched_status status = SCHED_S_OK;
SCHED_MSG_HIGH("sched_de_queue_frame API");
if (!sched_ctx || !pp_frm_data
|| !pp_client_data) {
SCHED_MSG_ERR("Bad input parameters: sched_ctx=%p, "
"pp_frm_data=%p, pp_client_data=%p",
sched_ctx, pp_frm_data,
pp_client_data);
return SCHED_S_EBADPARM;
}
(void)SCHED_CRITSEC_ENTER(sched_ctx->sched_cs);
status =
sched_process_de_q_frm(sched_ctx, pp_frm_data, pp_client_data);
(void)SCHED_CRITSEC_LEAVE(sched_ctx->sched_cs);
return status;
}
enum sched_status sched_get_client_param(
void *handle, void *client_hdl,
enum sched_index param_index,
union sched_value_type *param_value)
{
struct sched_ctx *sched_ctx = (struct sched_ctx *)handle;
struct _sched_clnt_list_node *clnt_node =
(struct _sched_clnt_list_node *)client_hdl;
enum sched_status status;
SCHED_MSG_HIGH("sched_get_client_param API");
if (!sched_ctx || !clnt_node ||
!param_value) {
SCHED_MSG_ERR("Bad input parameters: sched_ctx=%p, "
"clnt_node=%p, param_value=%p",
sched_ctx, clnt_node,
param_value);
return SCHED_S_EBADPARM;
}
(void)SCHED_CRITSEC_ENTER(clnt_node->data.clnt_cs);
status = sched_process_clnt_lvl_get_param(sched_ctx,
&clnt_node->data,
param_index, param_value);
(void)SCHED_CRITSEC_LEAVE(clnt_node->data.clnt_cs);
return status;
}
enum sched_status sched_set_client_param(
void *handle, void *client_hdl,
enum sched_index param_index,
union sched_value_type *param_value)
{
struct sched_ctx *sched_ctx = (struct sched_ctx *)handle;
struct _sched_clnt_list_node *clnt_node =
(struct _sched_clnt_list_node *)client_hdl;
enum sched_status status;
SCHED_MSG_HIGH("sched_set_client_param API");
if (!sched_ctx || !clnt_node ||
!param_value) {
SCHED_MSG_ERR("Bad input parameters: "
"sched_ctx=%p, clnt_node=%p, "
"param_value=%p", sched_ctx, clnt_node,
param_value);
return SCHED_S_EBADPARM;
}
(void)SCHED_CRITSEC_ENTER(sched_ctx->sched_cs);
(void)SCHED_CRITSEC_ENTER(clnt_node->data.clnt_cs);
status = sched_process_clnt_lvl_set_param(sched_ctx,
&clnt_node->data, param_index, param_value);
(void)SCHED_CRITSEC_LEAVE(clnt_node->data.clnt_cs);
(void)SCHED_CRITSEC_LEAVE(sched_ctx->sched_cs);
return status;
}
enum sched_status sched_suspend_resume_client(
void *handle, void *client_hdl, u32 state)
{
struct sched_ctx *sched_ctx = (struct sched_ctx *)handle;
struct _sched_clnt_list_node *clnt_node =
(struct _sched_clnt_list_node *)client_hdl;
enum sched_status status;
SCHED_MSG_HIGH("sched_client_suspend_resume API");
if (!sched_ctx || !clnt_node) {
SCHED_MSG_ERR
("Bad input parameters: sched_ctx=%p, clnt_node=%p",
sched_ctx, clnt_node);
return SCHED_S_EBADPARM;
}
(void)SCHED_CRITSEC_ENTER(clnt_node->data.clnt_cs);
status =
sched_process_suspend_resume_clnt(sched_ctx, clnt_node,
state);
(void)SCHED_CRITSEC_LEAVE(clnt_node->data.clnt_cs);
return status;
}