M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions
@@ -0,0 +1,408 @@
/* Copyright (c) 2010-2012, The Linux Foundation. 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.
*
*/
#ifndef _VCD_H_
#define _VCD_H_
#include <media/msm/vcd_api.h>
#include "vcd_util.h"
#include "vcd_ddl_api.h"
#include "vcd_res_tracker_api.h"
#include "vcd_client_sm.h"
#include "vcd_core.h"
#include "vcd_device_sm.h"
void vcd_reset_device_channels(struct vcd_dev_ctxt *dev_ctxt);
u32 vcd_get_command_channel
(struct vcd_dev_ctxt *dev_ctxt, struct vcd_transc **transc);
u32 vcd_get_command_channel_in_loop
(struct vcd_dev_ctxt *dev_ctxt, struct vcd_transc **transc);
void vcd_mark_command_channel
(struct vcd_dev_ctxt *dev_ctxt, struct vcd_transc *transc);
void vcd_release_command_channel
(struct vcd_dev_ctxt *dev_ctxt, struct vcd_transc *transc);
void vcd_release_multiple_command_channels(struct vcd_dev_ctxt *dev_ctxt,
u32 channels);
void vcd_release_interim_command_channels(struct vcd_dev_ctxt *dev_ctxt);
u32 vcd_get_frame_channel
(struct vcd_dev_ctxt *dev_ctxt, struct vcd_transc **transc);
u32 vcd_get_frame_channel_in_loop
(struct vcd_dev_ctxt *dev_ctxt, struct vcd_transc **transc);
void vcd_mark_frame_channel(struct vcd_dev_ctxt *dev_ctxt);
void vcd_release_frame_channel
(struct vcd_dev_ctxt *dev_ctxt, struct vcd_transc *transc);
void vcd_release_multiple_frame_channels(struct vcd_dev_ctxt *dev_ctxt,
u32 channels);
void vcd_release_interim_frame_channels(struct vcd_dev_ctxt *dev_ctxt);
u32 vcd_core_is_busy(struct vcd_dev_ctxt *dev_ctxt);
void vcd_device_timer_start(struct vcd_dev_ctxt *dev_ctxt);
void vcd_device_timer_stop(struct vcd_dev_ctxt *dev_ctxt);
u32 vcd_init_device_context
(struct vcd_drv_ctxt *drv_ctxt, u32 ev_code);
u32 vcd_deinit_device_context
(struct vcd_drv_ctxt *drv_ctxt, u32 ev_code);
u32 vcd_init_client_context(struct vcd_clnt_ctxt *cctxt);
void vcd_destroy_client_context(struct vcd_clnt_ctxt *cctxt);
u32 vcd_check_for_client_context
(struct vcd_dev_ctxt *dev_ctxt, s32 driver_id);
u32 vcd_validate_driver_handle
(struct vcd_dev_ctxt *dev_ctxt, s32 driver_handle);
void vcd_handle_for_last_clnt_close
(struct vcd_dev_ctxt *dev_ctxt, u32 send_deinit);
u32 vcd_common_allocate_set_buffer
(struct vcd_clnt_ctxt *cctxt,
enum vcd_buffer_type buffer,
u32 buf_size, struct vcd_buffer_pool **buf_pool);
u32 vcd_set_buffer_internal
(struct vcd_clnt_ctxt *cctxt,
struct vcd_buffer_pool *buf_pool, u8 *buffer, u32 buf_size);
u32 vcd_allocate_buffer_internal
(struct vcd_clnt_ctxt *cctxt,
struct vcd_buffer_pool *buf_pool,
u32 buf_size, u8 **vir_buf_addr, u8 **phy_buf_addr);
u32 vcd_free_one_buffer_internal
(struct vcd_clnt_ctxt *cctxt,
enum vcd_buffer_type buffer_type, u8 *buffer);
u32 vcd_free_buffers_internal
(struct vcd_clnt_ctxt *cctxt,
struct vcd_buffer_pool *buf_pool);
u32 vcd_alloc_buffer_pool_entries
(struct vcd_buffer_pool *buf_pool,
struct vcd_buffer_requirement *buf_req);
void vcd_free_buffer_pool_entries(struct vcd_buffer_pool *buf_pool);
void vcd_flush_in_use_buffer_pool_entries(struct vcd_clnt_ctxt *cctxt,
struct vcd_buffer_pool *buf_pool, u32 event);
void vcd_reset_buffer_pool_for_reuse(struct vcd_buffer_pool *buf_pool);
struct vcd_buffer_entry *vcd_get_free_buffer_pool_entry
(struct vcd_buffer_pool *pool);
struct vcd_buffer_entry *vcd_find_buffer_pool_entry
(struct vcd_buffer_pool *pool, u8 *v_addr);
struct vcd_buffer_entry *vcd_buffer_pool_entry_de_q
(struct vcd_buffer_pool *pool);
u32 vcd_buffer_pool_entry_en_q
(struct vcd_buffer_pool *pool,
struct vcd_buffer_entry *entry);
u32 vcd_check_if_buffer_req_met(struct vcd_clnt_ctxt *cctxt,
enum vcd_buffer_type buffer_type);
u32 vcd_client_cmd_en_q
(struct vcd_clnt_ctxt *cctxt, enum vcd_command command);
void vcd_client_cmd_flush_and_en_q
(struct vcd_clnt_ctxt *cctxt, enum vcd_command command);
u32 vcd_client_cmd_de_q
(struct vcd_clnt_ctxt *cctxt, enum vcd_command *command);
u32 vcd_handle_recvd_eos
(struct vcd_clnt_ctxt *cctxt,
struct vcd_frame_data *input_frame, u32 * pb_eos_handled);
u32 vcd_handle_first_decode_frame(struct vcd_clnt_ctxt *cctxt);
u32 vcd_handle_input_frame
(struct vcd_clnt_ctxt *cctxt,
struct vcd_frame_data *input_frame);
u32 vcd_store_seq_hdr
(struct vcd_clnt_ctxt *cctxt,
struct vcd_sequence_hdr *seq_hdr);
u32 vcd_set_frame_size
(struct vcd_clnt_ctxt *cctxt,
struct vcd_property_frame_size *frm_size);
u32 vcd_set_frame_rate
(struct vcd_clnt_ctxt *cctxt,
struct vcd_property_frame_rate *fps);
u32 vcd_calculate_frame_delta
(struct vcd_clnt_ctxt *cctxt, struct vcd_frame_data *frame);
struct vcd_buffer_entry *vcd_check_fill_output_buffer
(struct vcd_clnt_ctxt *cctxt,
struct vcd_frame_data *buffer);
u32 vcd_handle_first_fill_output_buffer
(struct vcd_clnt_ctxt *cctxt,
struct vcd_frame_data *buffer, u32 *b_handled);
u32 vcd_handle_first_fill_output_buffer_for_enc
(struct vcd_clnt_ctxt *cctxt,
struct vcd_frame_data *frm_entry, u32 *b_handled);
u32 vcd_handle_first_fill_output_buffer_for_dec
(struct vcd_clnt_ctxt *cctxt,
struct vcd_frame_data *frm_entry, u32 *b_handled);
u32 vcd_schedule_frame(struct vcd_dev_ctxt *dev_ctxt,
struct vcd_clnt_ctxt **cctxt, struct vcd_buffer_entry
**ip_buf_entry);
u32 vcd_submit_command_in_continue
(struct vcd_dev_ctxt *dev_ctxt, struct vcd_transc *transc);
u32 vcd_submit_cmd_sess_start(struct vcd_transc *transc);
u32 vcd_submit_cmd_sess_end(struct vcd_transc *transc);
void vcd_submit_cmd_client_close(struct vcd_clnt_ctxt *cctxt);
u32 vcd_submit_frame
(struct vcd_dev_ctxt *dev_ctxt, struct vcd_transc *transc);
u32 vcd_try_submit_frame_in_continue(struct vcd_dev_ctxt *dev_ctxt,
struct vcd_transc *transc);
u32 vcd_process_cmd_sess_start(struct vcd_clnt_ctxt *cctxt);
void vcd_try_submit_frame(struct vcd_dev_ctxt *dev_ctxt);
u32 vcd_setup_with_ddl_capabilities(struct vcd_dev_ctxt *dev_ctxt);
void vcd_handle_submit_frame_failed(struct vcd_dev_ctxt *dev_ctxt,
struct vcd_transc *transc);
struct vcd_transc *vcd_get_free_trans_tbl_entry
(struct vcd_dev_ctxt *dev_ctxt);
void vcd_release_trans_tbl_entry(struct vcd_transc *trans_entry);
void vcd_release_all_clnt_frm_transc(struct vcd_clnt_ctxt *cctxt);
void vcd_release_all_clnt_transc(struct vcd_clnt_ctxt *cctxt);
u32 vcd_handle_input_done
(struct vcd_clnt_ctxt *cctxt,
void *payload, u32 event, u32 status);
u32 vcd_handle_input_done_in_eos
(struct vcd_clnt_ctxt *cctxt, void *payload, u32 status);
void vcd_handle_input_done_failed
(struct vcd_clnt_ctxt *cctxt, struct vcd_transc *transc);
void vcd_handle_input_done_with_codec_config
(struct vcd_clnt_ctxt *cctxt,
struct vcd_transc *transc,
struct ddl_frame_data_tag *frm);
void vcd_handle_input_done_for_interlacing
(struct vcd_clnt_ctxt *cctxt);
void vcd_handle_input_done_with_trans_end
(struct vcd_clnt_ctxt *cctxt);
u32 vcd_handle_frame_done
(struct vcd_clnt_ctxt *cctxt,
void *payload, u32 event, u32 status);
void vcd_handle_frame_done_for_interlacing
(struct vcd_clnt_ctxt *cctxt,
struct vcd_transc *transc_ip1,
struct ddl_frame_data_tag *op_frm, u32 status);
u32 vcd_handle_frame_done_in_eos
(struct vcd_clnt_ctxt *cctxt, void *payload, u32 status);
u32 vcd_handle_output_required(struct vcd_clnt_ctxt *cctxt,
void *payload, u32 status);
u32 vcd_handle_output_required_in_flushing(struct vcd_clnt_ctxt *cctxt,
void *payload);
u32 vcd_handle_output_req_tran_end_in_eos(struct vcd_clnt_ctxt *cctxt);
u32 vcd_validate_io_done_pyld
(struct vcd_clnt_ctxt *cctxt, void *payload, u32 status);
void vcd_handle_eos_trans_end(struct vcd_clnt_ctxt *cctxt);
void vcd_handle_eos_done
(struct vcd_clnt_ctxt *cctxt,
struct vcd_transc *transc, u32 status);
void vcd_send_frame_done_in_eos
(struct vcd_clnt_ctxt *cctxt,
struct vcd_frame_data *input_frame, u32 valid_opbuf);
void vcd_send_frame_done_in_eos_for_dec
(struct vcd_clnt_ctxt *cctxt,
struct vcd_frame_data *input_frame);
void vcd_send_frame_done_in_eos_for_enc
(struct vcd_clnt_ctxt *cctxt,
struct vcd_frame_data *input_frame);
void vcd_handle_start_done(struct vcd_clnt_ctxt *cctxt,
struct vcd_transc *transc, u32 status);
void vcd_handle_stop_done(struct vcd_clnt_ctxt *cctxt,
struct vcd_transc *transc, u32 status);
void vcd_handle_stop_done_in_starting(struct vcd_clnt_ctxt *cctxt,
struct vcd_transc *transc, u32 status);
void vcd_handle_stop_done_in_invalid(struct vcd_clnt_ctxt *cctxt,
struct vcd_transc *transc, u32 status);
void vcd_send_flush_done(struct vcd_clnt_ctxt *cctxt, u32 status);
void vcd_process_pending_flush_in_eos(struct vcd_clnt_ctxt *cctxt);
void vcd_process_pending_stop_in_eos(struct vcd_clnt_ctxt *cctxt);
void vcd_handle_trans_pending(struct vcd_clnt_ctxt *cctxt);
u32 vcd_handle_ind_output_reconfig
(struct vcd_clnt_ctxt *cctxt, void* payload, u32 status);
u32 vcd_handle_ind_output_reconfig_in_flushing
(struct vcd_clnt_ctxt *cctxt, void* payload, u32 status);
void vcd_flush_output_buffers(struct vcd_clnt_ctxt *cctxt);
void vcd_flush_bframe_buffers(struct vcd_clnt_ctxt *cctxt, u32 mode);
u32 vcd_flush_buffers(struct vcd_clnt_ctxt *cctxt, u32 mode);
void vcd_flush_buffers_in_err_fatal(struct vcd_clnt_ctxt *cctxt);
u32 vcd_power_event
(struct vcd_dev_ctxt *dev_ctxt,
struct vcd_clnt_ctxt *cctxt, u32 event);
u32 vcd_device_power_event(struct vcd_dev_ctxt *dev_ctxt, u32 event,
struct vcd_clnt_ctxt *cctxt);
u32 vcd_client_power_event
(struct vcd_dev_ctxt *dev_ctxt,
struct vcd_clnt_ctxt *cctxt, u32 event);
u32 vcd_enable_clock(struct vcd_dev_ctxt *dev_ctxt,
struct vcd_clnt_ctxt *cctxt);
u32 vcd_disable_clock(struct vcd_dev_ctxt *dev_ctxt);
u32 vcd_set_perf_level(struct vcd_dev_ctxt *dev_ctxt, u32 perf_lvl);
u32 vcd_update_clnt_perf_lvl
(struct vcd_clnt_ctxt *cctxt,
struct vcd_property_frame_rate *fps, u32 frm_p_units);
u32 vcd_gate_clock(struct vcd_dev_ctxt *dev_ctxt);
u32 vcd_un_gate_clock(struct vcd_dev_ctxt *dev_ctxt);
void vcd_handle_err_fatal(struct vcd_clnt_ctxt *cctxt,
u32 event, u32 status);
void vcd_handle_device_err_fatal(struct vcd_dev_ctxt *dev_ctxt,
struct vcd_clnt_ctxt *cctxt);
void vcd_clnt_handle_device_err_fatal(struct vcd_clnt_ctxt *cctxt,
u32 event);
void vcd_handle_err_in_starting(struct vcd_clnt_ctxt *cctxt,
u32 status);
void vcd_handle_ind_hw_err_fatal(struct vcd_clnt_ctxt *cctxt,
u32 event, u32 status);
u32 vcd_return_op_buffer_to_hw(struct vcd_clnt_ctxt *cctxt,
struct vcd_buffer_entry *buf_entry);
u32 vcd_sched_create(struct list_head *sched_list);
void vcd_sched_destroy(struct list_head *sched_clnt_list);
u32 vcd_sched_add_client(struct vcd_clnt_ctxt *cctxt);
u32 vcd_sched_remove_client(struct vcd_sched_clnt_ctx *sched_cctxt);
u32 vcd_sched_update_config(struct vcd_clnt_ctxt *cctxt);
u32 vcd_sched_queue_buffer(
struct vcd_sched_clnt_ctx *sched_cctxt,
struct vcd_buffer_entry *buffer, u32 b_tail);
u32 vcd_sched_dequeue_buffer(
struct vcd_sched_clnt_ctx *sched_cctxt,
struct vcd_buffer_entry **buffer);
u32 vcd_sched_mark_client_eof(struct vcd_sched_clnt_ctx *sched_cctxt);
u32 vcd_sched_suspend_resume_clnt(
struct vcd_clnt_ctxt *cctxt, u32 b_state);
u32 vcd_sched_get_client_frame(struct list_head *sched_clnt_list,
struct vcd_clnt_ctxt **cctxt,
struct vcd_buffer_entry **buffer);
void vcd_handle_clnt_fatal(struct vcd_clnt_ctxt *cctxt, u32 trans_end);
void vcd_handle_clnt_fatal_input_done(struct vcd_clnt_ctxt *cctxt,
u32 trans_end);
void vcd_handle_ind_info_output_reconfig
(struct vcd_clnt_ctxt *cctxt, u32 status);
u32 vcd_req_perf_level(struct vcd_clnt_ctxt *cctxt,
struct vcd_property_perf_level *);
u32 vcd_set_num_slices(struct vcd_clnt_ctxt *cctxt);
u32 vcd_update_decoder_perf_level(struct vcd_dev_ctxt *dev_ctxt, u32 perf_lvl);
u32 vcd_set_perf_turbo_level(struct vcd_clnt_ctxt *cctxt);
struct vcd_transc *vcd_get_first_in_use_trans_for_clnt(
struct vcd_clnt_ctxt *cctxt);
u32 vcd_handle_ltr_use_failed(struct vcd_clnt_ctxt *cctxt,
void *payload, size_t sz, u32 status);
#endif
@@ -0,0 +1,981 @@
/* Copyright (c) 2012-2013, The Linux Foundation. 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.
*
*/
#include <linux/export.h>
#include <media/msm/vidc_type.h>
#include <media/msm/vidc_init.h>
#include "vcd.h"
u32 vcd_init(struct vcd_init_config *config, s32 *driver_handle)
{
u32 rc = VCD_S_SUCCESS;
struct vcd_drv_ctxt *drv_ctxt;
VCD_MSG_MED("vcd_init:");
if (!config ||
!driver_handle || !config->map_dev_base_addr) {
VCD_MSG_ERROR("Bad parameters");
return VCD_ERR_ILLEGAL_PARM;
}
drv_ctxt = vcd_get_drv_context();
mutex_init(&drv_ctxt->dev_mutex);
mutex_lock(&drv_ctxt->dev_mutex);
if (drv_ctxt->dev_state.state_table->ev_hdlr.init) {
rc = drv_ctxt->dev_state.state_table->ev_hdlr.
init(drv_ctxt, config, driver_handle);
} else {
VCD_MSG_ERROR("Unsupported API in device state %d",
drv_ctxt->dev_state.state);
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
return rc;
}
EXPORT_SYMBOL(vcd_init);
u32 vcd_term(s32 driver_handle)
{
u32 rc = VCD_S_SUCCESS;
struct vcd_drv_ctxt *drv_ctxt;
VCD_MSG_MED("vcd_term:");
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (drv_ctxt->dev_state.state_table->ev_hdlr.term) {
rc = drv_ctxt->dev_state.state_table->ev_hdlr.
term(drv_ctxt, driver_handle);
} else {
VCD_MSG_ERROR("Unsupported API in device state %d",
drv_ctxt->dev_state.state);
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
return rc;
}
EXPORT_SYMBOL(vcd_term);
struct client_security_info {
int secure_enc;
int secure_dec;
int non_secure_enc;
int non_secure_dec;
};
static int vcd_get_clients_security_info(struct client_security_info *sec_info)
{
struct vcd_drv_ctxt *drv_ctxt;
struct vcd_clnt_ctxt *cctxt;
int count = 0;
if (!sec_info) {
VCD_MSG_ERROR("Invalid argument\n");
return -EINVAL;
}
memset(sec_info, 0 , sizeof(*sec_info));
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
cctxt = drv_ctxt->dev_ctxt.cctxt_list_head;
while (cctxt) {
if (cctxt->secure && cctxt->decoding)
sec_info->secure_dec++;
else if (cctxt->secure && !cctxt->decoding)
sec_info->secure_enc++;
else if (!cctxt->secure && cctxt->decoding)
sec_info->non_secure_dec++;
else
sec_info->non_secure_enc++;
count++;
cctxt = cctxt->next;
}
mutex_unlock(&drv_ctxt->dev_mutex);
return count;
}
static int is_session_invalid(u32 decoding, u32 flags)
{
int is_secure;
struct client_security_info sec_info;
int client_count = 0;
int secure_session_running = 0, non_secure_runnung = 0;
is_secure = (flags & VCD_CP_SESSION) ? 1 : 0;
client_count = vcd_get_clients_security_info(&sec_info);
secure_session_running = (sec_info.secure_enc > 0) ||
(sec_info.secure_dec > 0);
non_secure_runnung = sec_info.non_secure_dec + sec_info.non_secure_enc;
if (!is_secure) {
if (secure_session_running) {
pr_err("non secure session failed secure running\n");
return -EACCES;
}
} else {
if (non_secure_runnung) {
pr_err("Secure session failed non secure running\n");
return -EACCES;
}
}
return 0;
}
u32 vcd_open(s32 driver_handle, u32 decoding,
void (*callback) (u32 event, u32 status, void *info, size_t sz,
void *handle, void *const client_data),
void *client_data, int flags)
{
u32 rc = 0, num_of_instances = 0;
struct vcd_drv_ctxt *drv_ctxt;
struct vcd_clnt_ctxt *cctxt;
int is_secure = (flags & VCD_CP_SESSION) ? 1 : 0;
VCD_MSG_MED("vcd_open:");
if (!callback) {
VCD_MSG_ERROR("Bad parameters");
return -EINVAL;
}
drv_ctxt = vcd_get_drv_context();
cctxt = drv_ctxt->dev_ctxt.cctxt_list_head;
while (cctxt) {
num_of_instances++;
cctxt = cctxt->next;
}
if (num_of_instances == VIDC_MAX_NUM_CLIENTS) {
pr_err(" %s(): Max number of clients reached\n", __func__);
return -ENODEV;
}
rc = is_session_invalid(decoding, flags);
if (rc) {
VCD_MSG_ERROR("Invalid Session: is_decoder: %d, secure: %d\n",
decoding, flags);
return rc;
}
if (is_secure)
res_trk_secure_set();
mutex_lock(&drv_ctxt->dev_mutex);
if (drv_ctxt->dev_state.state_table->ev_hdlr.open) {
rc = drv_ctxt->dev_state.state_table->ev_hdlr.
open(drv_ctxt, driver_handle, decoding, callback,
client_data);
if (rc) {
rc = -ENODEV;
}
} else {
VCD_MSG_ERROR("Unsupported API in device state %d",
drv_ctxt->dev_state.state);
rc = -EPERM;
}
if (!rc) {
cctxt = drv_ctxt->dev_ctxt.cctxt_list_head;
cctxt->secure = is_secure;
} else if (is_secure)
res_trk_secure_unset();
mutex_unlock(&drv_ctxt->dev_mutex);
return rc;
}
EXPORT_SYMBOL(vcd_open);
u32 vcd_close(void *handle)
{
struct vcd_clnt_ctxt *cctxt =
(struct vcd_clnt_ctxt *)handle;
struct vcd_drv_ctxt *drv_ctxt;
u32 rc;
int is_secure = 0;
VCD_MSG_MED("vcd_close:");
if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
VCD_MSG_ERROR("Bad client handle");
return VCD_ERR_BAD_HANDLE;
}
is_secure = cctxt->secure;
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (drv_ctxt->dev_state.state_table->ev_hdlr.close) {
rc = drv_ctxt->dev_state.state_table->ev_hdlr.
close(drv_ctxt, cctxt);
} else {
VCD_MSG_ERROR("Unsupported API in device state %d",
drv_ctxt->dev_state.state);
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
if (is_secure)
res_trk_secure_unset();
return rc;
}
EXPORT_SYMBOL(vcd_close);
u32 vcd_encode_start(void *handle)
{
struct vcd_clnt_ctxt *cctxt =
(struct vcd_clnt_ctxt *)handle;
struct vcd_drv_ctxt *drv_ctxt;
u32 rc;
VCD_MSG_MED("vcd_encode_start:");
if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
VCD_MSG_ERROR("Bad client handle");
return VCD_ERR_BAD_HANDLE;
}
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (cctxt->clnt_state.state_table->ev_hdlr.encode_start &&
drv_ctxt->dev_ctxt.pwr_state != VCD_PWR_STATE_SLEEP) {
rc = cctxt->clnt_state.state_table->ev_hdlr.
encode_start(cctxt);
} else {
VCD_MSG_ERROR
("Unsupported API in dev power state %d OR client state %d",
drv_ctxt->dev_ctxt.pwr_state,
cctxt->clnt_state.state);
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
return rc;
}
EXPORT_SYMBOL(vcd_encode_start);
u32 vcd_encode_frame(void *handle, struct vcd_frame_data *input_frame)
{
struct vcd_clnt_ctxt *cctxt =
(struct vcd_clnt_ctxt *)handle;
struct vcd_drv_ctxt *drv_ctxt;
u32 rc;
VCD_MSG_MED("vcd_encode_frame:");
if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
VCD_MSG_ERROR("Bad client handle");
return VCD_ERR_BAD_HANDLE;
}
if (!input_frame) {
VCD_MSG_ERROR("Bad parameters");
return VCD_ERR_BAD_POINTER;
}
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (cctxt->clnt_state.state_table->ev_hdlr.encode_frame) {
rc = cctxt->clnt_state.state_table->ev_hdlr.
encode_frame(cctxt, input_frame);
} else {
VCD_MSG_ERROR("Unsupported API in client state %d",
cctxt->clnt_state.state);
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
return rc;
}
EXPORT_SYMBOL(vcd_encode_frame);
u32 vcd_decode_start(void *handle, struct vcd_sequence_hdr *seq_hdr)
{
struct vcd_clnt_ctxt *cctxt =
(struct vcd_clnt_ctxt *)handle;
struct vcd_drv_ctxt *drv_ctxt;
u32 rc;
VCD_MSG_MED("vcd_decode_start:");
if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
VCD_MSG_ERROR("Bad client handle");
return VCD_ERR_BAD_HANDLE;
}
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (cctxt->clnt_state.state_table->ev_hdlr.decode_start &&
drv_ctxt->dev_ctxt.pwr_state != VCD_PWR_STATE_SLEEP) {
rc = cctxt->clnt_state.state_table->ev_hdlr.
decode_start(cctxt, seq_hdr);
} else {
VCD_MSG_ERROR
("Unsupported API in dev power state %d OR client state %d",
drv_ctxt->dev_ctxt.pwr_state,
cctxt->clnt_state.state);
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
return rc;
}
EXPORT_SYMBOL(vcd_decode_start);
u32 vcd_decode_frame(void *handle, struct vcd_frame_data *input_frame)
{
struct vcd_clnt_ctxt *cctxt =
(struct vcd_clnt_ctxt *)handle;
struct vcd_drv_ctxt *drv_ctxt;
u32 rc;
VCD_MSG_MED("vcd_decode_frame:");
if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
VCD_MSG_ERROR("Bad client handle");
return VCD_ERR_BAD_HANDLE;
}
if (!input_frame) {
VCD_MSG_ERROR("Bad parameters");
return VCD_ERR_BAD_POINTER;
}
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (cctxt->clnt_state.state_table->ev_hdlr.decode_frame) {
rc = cctxt->clnt_state.state_table->ev_hdlr.
decode_frame(cctxt, input_frame);
} else {
VCD_MSG_ERROR("Unsupported API in client state %d",
cctxt->clnt_state.state);
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
return rc;
}
EXPORT_SYMBOL(vcd_decode_frame);
u32 vcd_pause(void *handle)
{
struct vcd_drv_ctxt *drv_ctxt;
struct vcd_clnt_ctxt *cctxt =
(struct vcd_clnt_ctxt *)handle;
u32 rc;
VCD_MSG_MED("vcd_pause:");
if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
VCD_MSG_ERROR("Bad client handle");
return VCD_ERR_BAD_HANDLE;
}
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (cctxt->clnt_state.state_table->ev_hdlr.pause) {
rc = cctxt->clnt_state.state_table->ev_hdlr.
pause(cctxt);
} else {
VCD_MSG_ERROR("Unsupported API in client state %d",
cctxt->clnt_state.state);
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
return rc;
}
EXPORT_SYMBOL(vcd_pause);
u32 vcd_resume(void *handle)
{
struct vcd_drv_ctxt *drv_ctxt;
struct vcd_clnt_ctxt *cctxt =
(struct vcd_clnt_ctxt *)handle;
u32 rc;
VCD_MSG_MED("vcd_resume:");
if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
VCD_MSG_ERROR("Bad client handle");
return VCD_ERR_BAD_HANDLE;
}
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (drv_ctxt->dev_state.state_table->ev_hdlr.resume &&
drv_ctxt->dev_ctxt.pwr_state != VCD_PWR_STATE_SLEEP) {
rc = drv_ctxt->dev_state.state_table->ev_hdlr.
resume(drv_ctxt, cctxt);
} else {
VCD_MSG_ERROR
("Unsupported API in dev power state %d OR client state %d",
drv_ctxt->dev_ctxt.pwr_state,
cctxt->clnt_state.state);
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
return rc;
}
EXPORT_SYMBOL(vcd_resume);
u32 vcd_flush(void *handle, u32 mode)
{
struct vcd_clnt_ctxt *cctxt =
(struct vcd_clnt_ctxt *)handle;
struct vcd_drv_ctxt *drv_ctxt;
u32 rc;
VCD_MSG_MED("vcd_flush:");
if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
VCD_MSG_ERROR("Bad client handle");
return VCD_ERR_BAD_HANDLE;
}
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (cctxt->clnt_state.state_table->ev_hdlr.flush) {
rc = cctxt->clnt_state.state_table->ev_hdlr.
flush(cctxt, mode);
} else {
VCD_MSG_ERROR("Unsupported API in client state %d",
cctxt->clnt_state.state);
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
return rc;
}
EXPORT_SYMBOL(vcd_flush);
u32 vcd_stop(void *handle)
{
struct vcd_clnt_ctxt *cctxt =
(struct vcd_clnt_ctxt *)handle;
struct vcd_drv_ctxt *drv_ctxt;
u32 rc;
VCD_MSG_MED("vcd_stop:");
if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
VCD_MSG_ERROR("Bad client handle");
return VCD_ERR_BAD_HANDLE;
}
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (cctxt->clnt_state.state_table->ev_hdlr.stop &&
drv_ctxt->dev_ctxt.pwr_state != VCD_PWR_STATE_SLEEP) {
rc = cctxt->clnt_state.state_table->ev_hdlr.
stop(cctxt);
} else {
VCD_MSG_ERROR
("Unsupported API in dev power state %d OR client state %d",
drv_ctxt->dev_ctxt.pwr_state,
cctxt->clnt_state.state);
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
return rc;
}
EXPORT_SYMBOL(vcd_stop);
u32 vcd_set_property(void *handle,
struct vcd_property_hdr *prop_hdr, void *prop_val)
{
struct vcd_clnt_ctxt *cctxt =
(struct vcd_clnt_ctxt *)handle;
struct vcd_drv_ctxt *drv_ctxt;
u32 rc;
VCD_MSG_MED("vcd_set_property:");
if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
VCD_MSG_ERROR("Bad client handle");
return VCD_ERR_BAD_HANDLE;
}
if (!prop_hdr || !prop_val) {
VCD_MSG_ERROR("Bad parameters");
return VCD_ERR_BAD_POINTER;
}
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (cctxt->clnt_state.state_table->ev_hdlr.set_property) {
rc = cctxt->clnt_state.state_table->ev_hdlr.
set_property(cctxt, prop_hdr, prop_val);
} else {
VCD_MSG_ERROR("Unsupported API in client state %d",
cctxt->clnt_state.state);
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
return rc;
}
EXPORT_SYMBOL(vcd_set_property);
u32 vcd_get_property(void *handle,
struct vcd_property_hdr *prop_hdr, void *prop_val)
{
struct vcd_clnt_ctxt *cctxt =
(struct vcd_clnt_ctxt *)handle;
struct vcd_drv_ctxt *drv_ctxt;
u32 rc;
VCD_MSG_MED("vcd_get_property:");
if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
VCD_MSG_ERROR("Bad client handle");
return VCD_ERR_BAD_HANDLE;
}
if (!prop_hdr || !prop_val) {
VCD_MSG_ERROR("Bad parameters");
return VCD_ERR_BAD_POINTER;
}
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (cctxt->clnt_state.state_table->ev_hdlr.get_property) {
rc = cctxt->clnt_state.state_table->ev_hdlr.
get_property(cctxt, prop_hdr, prop_val);
} else {
VCD_MSG_ERROR("Unsupported API in client state %d",
cctxt->clnt_state.state);
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
return rc;
}
EXPORT_SYMBOL(vcd_get_property);
u32 vcd_set_buffer_requirements(void *handle,
enum vcd_buffer_type buffer,
struct vcd_buffer_requirement *buffer_req)
{
struct vcd_clnt_ctxt *cctxt =
(struct vcd_clnt_ctxt *)handle;
struct vcd_drv_ctxt *drv_ctxt;
u32 rc;
VCD_MSG_MED("vcd_set_buffer_requirements:");
if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
VCD_MSG_ERROR("Bad client handle");
return VCD_ERR_BAD_HANDLE;
}
if (!buffer_req) {
VCD_MSG_ERROR("Bad parameters");
return VCD_ERR_BAD_POINTER;
}
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (cctxt->clnt_state.state_table->ev_hdlr.
set_buffer_requirements) {
rc = cctxt->clnt_state.state_table->ev_hdlr.
set_buffer_requirements(cctxt, buffer, buffer_req);
} else {
VCD_MSG_ERROR("Unsupported API in client state %d",
cctxt->clnt_state.state);
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
return rc;
}
EXPORT_SYMBOL(vcd_set_buffer_requirements);
u32 vcd_get_buffer_requirements(void *handle,
enum vcd_buffer_type buffer,
struct vcd_buffer_requirement *buffer_req)
{
struct vcd_clnt_ctxt *cctxt =
(struct vcd_clnt_ctxt *)handle;
struct vcd_drv_ctxt *drv_ctxt;
u32 rc;
VCD_MSG_MED("vcd_get_buffer_requirements:");
if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
VCD_MSG_ERROR("Bad client handle");
return VCD_ERR_BAD_HANDLE;
}
if (!buffer_req) {
VCD_MSG_ERROR("Bad parameters");
return VCD_ERR_BAD_POINTER;
}
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (cctxt->clnt_state.state_table->ev_hdlr.
get_buffer_requirements) {
rc = cctxt->clnt_state.state_table->ev_hdlr.
get_buffer_requirements(cctxt, buffer, buffer_req);
} else {
VCD_MSG_ERROR("Unsupported API in client state %d",
cctxt->clnt_state.state);
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
return rc;
}
EXPORT_SYMBOL(vcd_get_buffer_requirements);
u32 vcd_set_buffer(void *handle,
enum vcd_buffer_type buffer_type, u8 *buffer, u32 buf_size)
{
struct vcd_clnt_ctxt *cctxt =
(struct vcd_clnt_ctxt *)handle;
struct vcd_drv_ctxt *drv_ctxt;
u32 rc;
VCD_MSG_MED("vcd_set_buffer:");
if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
VCD_MSG_ERROR("Bad client handle");
return VCD_ERR_BAD_HANDLE;
}
if (!buffer || !buf_size) {
VCD_MSG_ERROR("Bad parameters");
return VCD_ERR_BAD_POINTER;
}
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (cctxt->clnt_state.state_table->ev_hdlr.set_buffer) {
rc = cctxt->clnt_state.state_table->ev_hdlr.
set_buffer(cctxt, buffer_type, buffer, buf_size);
} else {
VCD_MSG_ERROR("Unsupported API in client state %d",
cctxt->clnt_state.state);
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
return rc;
}
EXPORT_SYMBOL(vcd_set_buffer);
u32 vcd_allocate_buffer(void *handle,
enum vcd_buffer_type buffer,
u32 buf_size, u8 **vir_buf_addr, u8 **phy_buf_addr)
{
struct vcd_clnt_ctxt *cctxt =
(struct vcd_clnt_ctxt *)handle;
struct vcd_drv_ctxt *drv_ctxt;
u32 rc;
VCD_MSG_MED("vcd_allocate_buffer:");
if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
VCD_MSG_ERROR("Bad client handle");
return VCD_ERR_BAD_HANDLE;
}
if (!vir_buf_addr || !phy_buf_addr
|| !buf_size) {
VCD_MSG_ERROR("Bad parameters");
return VCD_ERR_BAD_POINTER;
}
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (cctxt->clnt_state.state_table->ev_hdlr.allocate_buffer) {
rc = cctxt->clnt_state.state_table->ev_hdlr.
allocate_buffer(cctxt, buffer, buf_size,
vir_buf_addr, phy_buf_addr);
} else {
VCD_MSG_ERROR("Unsupported API in client state %d",
cctxt->clnt_state.state);
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
return rc;
}
EXPORT_SYMBOL(vcd_allocate_buffer);
u32 vcd_free_buffer(void *handle, enum vcd_buffer_type buffer_type, u8 *buffer)
{
struct vcd_clnt_ctxt *cctxt =
(struct vcd_clnt_ctxt *)handle;
struct vcd_drv_ctxt *drv_ctxt;
u32 rc;
VCD_MSG_MED("vcd_free_buffer:");
if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
VCD_MSG_ERROR("Bad client handle");
return VCD_ERR_BAD_HANDLE;
}
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (cctxt->clnt_state.state_table->ev_hdlr.free_buffer) {
rc = cctxt->clnt_state.state_table->ev_hdlr.
free_buffer(cctxt, buffer_type, buffer);
} else {
VCD_MSG_ERROR("Unsupported API in client state %d",
cctxt->clnt_state.state);
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
return rc;
}
EXPORT_SYMBOL(vcd_free_buffer);
u32 vcd_fill_output_buffer(void *handle, struct vcd_frame_data *buffer)
{
struct vcd_clnt_ctxt *cctxt =
(struct vcd_clnt_ctxt *)handle;
struct vcd_drv_ctxt *drv_ctxt;
u32 rc;
VCD_MSG_MED("vcd_fill_output_buffer:");
if (!cctxt || cctxt->signature != VCD_SIGNATURE) {
VCD_MSG_ERROR("Bad client handle");
return VCD_ERR_BAD_HANDLE;
}
if (!buffer) {
VCD_MSG_ERROR("Bad parameters");
return VCD_ERR_BAD_POINTER;
}
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (cctxt->clnt_state.state_table->ev_hdlr.fill_output_buffer) {
rc = cctxt->clnt_state.state_table->ev_hdlr.
fill_output_buffer(cctxt, buffer);
} else {
VCD_MSG_ERROR("Unsupported API in client state %d",
cctxt->clnt_state.state);
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
return rc;
}
EXPORT_SYMBOL(vcd_fill_output_buffer);
u32 vcd_set_device_power(s32 driver_handle,
enum vcd_power_state pwr_state)
{
u32 rc = VCD_S_SUCCESS;
struct vcd_drv_ctxt *drv_ctxt;
VCD_MSG_MED("vcd_set_device_power:");
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (drv_ctxt->dev_state.state_table->ev_hdlr.set_dev_pwr) {
rc = drv_ctxt->dev_state.state_table->ev_hdlr.
set_dev_pwr(drv_ctxt, pwr_state);
} else {
VCD_MSG_ERROR("Unsupported API in device state %d",
drv_ctxt->dev_state.state);
rc = VCD_ERR_BAD_STATE;
}
mutex_unlock(&drv_ctxt->dev_mutex);
return rc;
}
EXPORT_SYMBOL(vcd_set_device_power);
void vcd_read_and_clear_interrupt(void)
{
VCD_MSG_LOW("vcd_read_and_clear_interrupt:");
ddl_read_and_clear_interrupt();
}
void vcd_response_handler(void)
{
struct vcd_drv_ctxt *drv_ctxt;
VCD_MSG_LOW("vcd_response_handler:");
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
if (!ddl_process_core_response()) {
VCD_MSG_HIGH
("ddl_process_core_response indicated no further"
"processing");
mutex_unlock(&drv_ctxt->dev_mutex);
return;
}
if (drv_ctxt->dev_ctxt.command_continue)
vcd_continue();
mutex_unlock(&drv_ctxt->dev_mutex);
}
EXPORT_SYMBOL(vcd_response_handler);
u8 vcd_get_num_of_clients(void)
{
struct vcd_drv_ctxt *drv_ctxt;
struct vcd_clnt_ctxt *cctxt;
u8 count = 0;
VCD_MSG_LOW("vcd_get_num_of_clients:");
drv_ctxt = vcd_get_drv_context();
mutex_lock(&drv_ctxt->dev_mutex);
cctxt = drv_ctxt->dev_ctxt.cctxt_list_head;
while (cctxt) {
count++;
cctxt = cctxt->next;
}
mutex_unlock(&drv_ctxt->dev_mutex);
return count;
}
EXPORT_SYMBOL(vcd_get_num_of_clients);
u32 vcd_get_ion_status(void)
{
return res_trk_get_enable_ion();
}
EXPORT_SYMBOL(vcd_get_ion_status);
struct ion_client *vcd_get_ion_client(void)
{
return res_trk_get_ion_client();
}
EXPORT_SYMBOL(vcd_get_ion_client);
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,110 @@
/* Copyright (c) 2010-2012, The Linux Foundation. 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.
*
*/
#ifndef _VCD_CLIENT_SM_H_
#define _VCD_CLIENT_SM_H_
#include <media/msm/vcd_api.h>
#include "vcd_ddl_api.h"
struct vcd_clnt_state_table;
struct vcd_clnt_state_ctxt;
struct vcd_clnt_ctxt;
enum vcd_clnt_state_enum {
VCD_CLIENT_STATE_NULL = 0,
VCD_CLIENT_STATE_OPEN,
VCD_CLIENT_STATE_STARTING,
VCD_CLIENT_STATE_RUN,
VCD_CLIENT_STATE_FLUSHING,
VCD_CLIENT_STATE_PAUSING,
VCD_CLIENT_STATE_PAUSED,
VCD_CLIENT_STATE_STOPPING,
VCD_CLIENT_STATE_EOS,
VCD_CLIENT_STATE_INVALID,
VCD_CLIENT_STATE_MAX,
VCD_CLIENT_STATE_32BIT = 0x7FFFFFFF
};
#define CLIENT_STATE_EVENT_NUMBER(ppf) \
((u32 *) (&(((struct vcd_clnt_state_table*)0)->ev_hdlr.ppf)) - \
(u32 *) (&(((struct vcd_clnt_state_table*)0)->ev_hdlr.close)) \
+ 1)
struct vcd_clnt_state_table {
struct {
u32(*close) (struct vcd_clnt_ctxt *cctxt);
u32(*encode_start) (struct vcd_clnt_ctxt *cctxt);
u32(*encode_frame) (struct vcd_clnt_ctxt *cctxt,
struct vcd_frame_data *input_frame);
u32(*decode_start) (struct vcd_clnt_ctxt *cctxt,
struct vcd_sequence_hdr *seq_hdr);
u32(*decode_frame) (struct vcd_clnt_ctxt *cctxt,
struct vcd_frame_data *input_frame);
u32(*pause) (struct vcd_clnt_ctxt *cctxt);
u32(*resume) (struct vcd_clnt_ctxt *cctxt);
u32(*flush) (struct vcd_clnt_ctxt *cctxt,
u32 mode);
u32(*stop) (struct vcd_clnt_ctxt *cctxt);
u32(*set_property) (struct vcd_clnt_ctxt *cctxt,
struct vcd_property_hdr *prop_hdr,
void *prop);
u32(*get_property) (struct vcd_clnt_ctxt *cctxt,
struct vcd_property_hdr *prop_hdr,
void *prop);
u32(*set_buffer_requirements) (struct vcd_clnt_ctxt *
cctxt,
enum vcd_buffer_type buffer,
struct
vcd_buffer_requirement *
buffer_req);
u32(*get_buffer_requirements) (struct vcd_clnt_ctxt *
cctxt,
enum vcd_buffer_type buffer,
struct
vcd_buffer_requirement *
buffer_req);
u32(*set_buffer) (struct vcd_clnt_ctxt *cctxt,
enum vcd_buffer_type buffer_type, u8 *buffer,
u32 buf_size);
u32(*allocate_buffer) (struct vcd_clnt_ctxt *cctxt,
enum vcd_buffer_type buffer, u32 buf_size,
u8 **vir_buf_addr, u8 **phy_buf_addr);
u32(*free_buffer) (struct vcd_clnt_ctxt *cctxt,
enum vcd_buffer_type buffer_type, u8 *buffer);
u32(*fill_output_buffer) (
struct vcd_clnt_ctxt *cctxt,
struct vcd_frame_data *buffer);
void (*clnt_cb) (struct vcd_clnt_ctxt *cctxt,
u32 event, u32 status, void *payload,
size_t sz, u32 *ddl_handle,
void *const client_data);
} ev_hdlr;
void (*entry) (struct vcd_clnt_ctxt *cctxt,
s32 state_event);
void (*exit) (struct vcd_clnt_ctxt *cctxt,
s32 state_event);
};
struct vcd_clnt_state_ctxt {
const struct vcd_clnt_state_table *state_table;
enum vcd_clnt_state_enum state;
};
extern void vcd_do_client_state_transition
(struct vcd_clnt_ctxt *cctxt,
enum vcd_clnt_state_enum to_state, u32 ev_code);
extern const struct vcd_clnt_state_table *vcd_get_client_state_table(
enum vcd_clnt_state_enum state);
#endif
@@ -0,0 +1,229 @@
/* Copyright (c) 2010-2012, The Linux Foundation. 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.
*
*/
#ifndef _VCD_CORE_H_
#define _VCD_CORE_H_
#include <linux/msm_ion.h>
#include <media/msm/vcd_api.h>
#include "vcd_ddl_api.h"
#include "vcd_util.h"
#include "vcd_client_sm.h"
#include "vcd_power_sm.h"
#define VCD_SIGNATURE 0x75017591U
#define VCD_MIN_PERF_LEVEL 37900
#define VCD_DRIVER_CLIENTS_MAX 6
#define VCD_MAX_CLIENT_TRANSACTIONS 32
#define VCD_MAX_BUFFER_ENTRIES 32
#define VCD_SEQ_HDR_PADDING_BYTES 256
#define VCD_DEC_NUM_INTERLACED_FIELDS 2
#define VCD_TIMESTAMP_RESOLUTION 1000000
#define VCD_DEC_INITIAL_FRAME_RATE 30
#define VCD_MAXPERF_FPS_THRESHOLD_X_1000 (59*1000)
#define VCD_FIRST_IP_RCVD 0x00000004
#define VCD_FIRST_OP_RCVD 0x00000008
#define VCD_EOS_PREV_VALID 0x00000010
#define VCD_EOS_WAIT_OP_BUF 0x00000020
#define VCD_CLEANING_UP 0x00000040
#define VCD_STOP_PENDING 0x00000080
#define VCD_CLOSE_PENDING 0x00000100
#define VCD_IN_RECONFIG 0x00000200
#define VCD_FIRST_IP_DONE 0x00000400
enum vcd_command {
VCD_CMD_NONE,
VCD_CMD_DEVICE_INIT,
VCD_CMD_DEVICE_TERM,
VCD_CMD_DEVICE_RESET,
VCD_CMD_CODEC_START,
VCD_CMD_CODEC_STOP,
VCD_CMD_CODE_FRAME,
VCD_CMD_OUTPUT_FLUSH,
VCD_CMD_CLIENT_CLOSE
};
enum vcd_core_type {
VCD_CORE_1080P,
VCD_CORE_720P
};
struct vcd_cmd_q_element {
enum vcd_command pending_cmd;
};
struct vcd_buffer_entry {
struct list_head sched_list;
struct list_head list;
u32 valid;
u8 *alloc;
u8 *virtual;
u8 *physical;
size_t sz;
u32 allocated;
u32 in_use;
struct vcd_frame_data frame;
};
struct vcd_buffer_pool {
struct vcd_buffer_entry *entries;
u32 count;
struct vcd_buffer_requirement buf_req;
u32 validated;
u32 allocated;
u32 in_use;
struct list_head queue;
u16 q_len;
};
struct vcd_transc {
u32 in_use;
enum vcd_command type;
struct vcd_clnt_ctxt *cctxt;
struct vcd_buffer_entry *ip_buf_entry;
s64 time_stamp;
u32 flags;
u32 ip_frm_tag;
enum vcd_frame frame;
struct vcd_buffer_entry *op_buf_entry;
u32 input_done;
u32 frame_done;
};
struct vcd_dev_ctxt {
u32 ddl_cmd_concurrency;
u32 ddl_frame_ch_depth;
u32 ddl_cmd_ch_depth;
u32 ddl_frame_ch_interim;
u32 ddl_cmd_ch_interim;
u32 ddl_frame_ch_free;
u32 ddl_cmd_ch_free;
struct list_head sched_clnt_list;
struct vcd_init_config config;
u32 driver_ids[VCD_DRIVER_CLIENTS_MAX];
u32 refs;
u8 *device_base_addr;
void *hw_timer_handle;
u32 hw_time_out;
struct vcd_clnt_ctxt *cctxt_list_head;
enum vcd_command pending_cmd;
u32 command_continue;
struct vcd_transc *trans_tbl;
u32 trans_tbl_size;
enum vcd_power_state pwr_state;
enum vcd_pwr_clk_state pwr_clk_state;
u32 active_clnts;
u32 max_perf_lvl;
u32 reqd_perf_lvl;
u32 curr_perf_lvl;
u32 set_perf_lvl_pending;
};
struct vcd_clnt_status {
u32 req_perf_lvl;
u32 frame_submitted;
u32 frame_delayed;
u32 cmd_submitted;
u32 int_field_cnt;
s64 first_ts;
s64 prev_ts;
u64 time_elapsed;
struct vcd_frame_data eos_trig_ip_frm;
struct ddl_frame_data_tag eos_prev_op_frm;
u32 eos_prev_op_frm_status;
u32 last_err;
u32 last_evt;
u32 mask;
};
struct vcd_sched_clnt_ctx {
struct list_head list;
u32 clnt_active;
void *clnt_data;
u32 tkns;
u32 round_perfrm;
u32 rounds;
struct list_head ip_frm_list;
};
struct vcd_clnt_ctxt {
u32 signature;
struct vcd_clnt_state_ctxt clnt_state;
s32 driver_id;
u32 live;
u32 decoding;
u32 bframe;
u32 num_slices;
struct vcd_property_frame_rate frm_rate;
u32 frm_p_units;
u32 reqd_perf_lvl;
u32 time_resoln;
u32 time_frame_delta;
struct vcd_buffer_pool in_buf_pool;
struct vcd_buffer_pool out_buf_pool;
void (*callback) (u32 event, u32 status, void *info, size_t sz,
void *handle, void *const client_data);
void *client_data;
struct vcd_sched_clnt_ctx *sched_clnt_hdl;
u32 ddl_hdl_valid;
u32 *ddl_handle;
struct vcd_dev_ctxt *dev_ctxt;
struct vcd_cmd_q_element cmd_q;
struct vcd_sequence_hdr seq_hdr;
u8 *seq_hdr_phy_addr;
struct vcd_clnt_status status;
struct ion_client *vcd_ion_client;
u32 vcd_enable_ion;
struct vcd_clnt_ctxt *next;
u32 meta_mode;
int perf_set_by_client;
int secure;
bool is_turbo_enabled;
};
#define VCD_BUFFERPOOL_INUSE_DECREMENT(val) \
do { \
if ((val) > 0) \
val--; \
else { \
VCD_MSG_ERROR("%s(): Inconsistent val given in " \
" VCD_BUFFERPOOL_INUSE_DECREMENT\n", __func__); \
} \
} while (0)
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,96 @@
/* Copyright (c) 2010-2012, The Linux Foundation. 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.
*
*/
#ifndef _VCD_DEVICE_SM_H_
#define _VCD_DEVICE_SM_H_
#include <media/msm/vcd_api.h>
#include "vcd_ddl_api.h"
#include "vcd_core.h"
struct vcd_dev_state_table;
struct vcd_dev_state_ctxt;
struct vcd_drv_ctxt;
enum vcd_dev_state_enum {
VCD_DEVICE_STATE_NULL = 0,
VCD_DEVICE_STATE_NOT_INIT,
VCD_DEVICE_STATE_INITING,
VCD_DEVICE_STATE_READY,
VCD_DEVICE_STATE_INVALID,
VCD_DEVICE_STATE_MAX,
VCD_DEVICE_STATE_32BIT = 0x7FFFFFFF
};
struct vcd_dev_state_table {
struct {
u32(*init) (struct vcd_drv_ctxt *drv_ctxt,
struct vcd_init_config *config,
s32 *driver_handle);
u32(*term) (struct vcd_drv_ctxt *drv_ctxt,
s32 driver_handle);
u32(*open) (struct vcd_drv_ctxt *drv_ctxt,
s32 driver_handle, u32 decoding,
void (*callback) (u32 event, u32 status,
void *info, size_t sz, void *handle,
void *const client_data),
void *client_data);
u32(*close) (struct vcd_drv_ctxt *drv_ctxt,
struct vcd_clnt_ctxt *cctxt);
u32(*resume) (struct vcd_drv_ctxt *drv_ctxt,
struct vcd_clnt_ctxt *cctxt);
u32(*set_dev_pwr) (struct vcd_drv_ctxt *drv_ctxt,
enum vcd_power_state pwr_state);
void (*dev_cb) (struct vcd_drv_ctxt *drv_ctxt,
u32 event, u32 status, void *payload,
size_t sz, u32 *ddl_handle,
void *const client_data);
void (*timeout) (struct vcd_drv_ctxt *drv_ctxt,
void *user_data);
} ev_hdlr;
void (*entry) (struct vcd_drv_ctxt *drv_ctxt,
s32 state_event);
void (*exit) (struct vcd_drv_ctxt *drv_ctxt,
s32 state_event);
};
#define DEVICE_STATE_EVENT_NUMBER(ppf) \
((u32 *) (&(((struct vcd_dev_state_table*)0)->ev_hdlr.ppf)) - \
(u32 *) (&(((struct vcd_dev_state_table*)0)->ev_hdlr.init)) \
+ 1)
struct vcd_dev_state_ctxt {
const struct vcd_dev_state_table *state_table;
enum vcd_dev_state_enum state;
};
struct vcd_drv_ctxt {
struct vcd_dev_state_ctxt dev_state;
struct vcd_dev_ctxt dev_ctxt;
struct mutex dev_mutex;
};
extern struct vcd_drv_ctxt *vcd_get_drv_context(void);
void vcd_continue(void);
#endif
@@ -0,0 +1,398 @@
/* Copyright (c) 2010-2012, The Linux Foundation. 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.
*
*/
#include <media/msm/vidc_type.h>
#include "vcd_power_sm.h"
#include "vcd_core.h"
#include "vcd.h"
#include "vcd_res_tracker.h"
u32 vcd_power_event(
struct vcd_dev_ctxt *dev_ctxt,
struct vcd_clnt_ctxt *cctxt, u32 event)
{
u32 rc = VCD_S_SUCCESS;
VCD_MSG_MED("Device power state = %d", dev_ctxt->pwr_clk_state);
VCD_MSG_MED("event = 0x%x", event);
switch (event) {
case VCD_EVT_PWR_DEV_INIT_BEGIN:
case VCD_EVT_PWR_DEV_INIT_END:
case VCD_EVT_PWR_DEV_INIT_FAIL:
case VCD_EVT_PWR_DEV_TERM_BEGIN:
case VCD_EVT_PWR_DEV_TERM_END:
case VCD_EVT_PWR_DEV_TERM_FAIL:
case VCD_EVT_PWR_DEV_SLEEP_BEGIN:
case VCD_EVT_PWR_DEV_SLEEP_END:
case VCD_EVT_PWR_DEV_SET_PERFLVL:
case VCD_EVT_PWR_DEV_HWTIMEOUT:
{
rc = vcd_device_power_event(dev_ctxt, event,
cctxt);
break;
}
case VCD_EVT_PWR_CLNT_CMD_BEGIN:
case VCD_EVT_PWR_CLNT_CMD_END:
case VCD_EVT_PWR_CLNT_CMD_FAIL:
case VCD_EVT_PWR_CLNT_PAUSE:
case VCD_EVT_PWR_CLNT_RESUME:
case VCD_EVT_PWR_CLNT_FIRST_FRAME:
case VCD_EVT_PWR_CLNT_LAST_FRAME:
case VCD_EVT_PWR_CLNT_ERRFATAL:
{
rc = vcd_client_power_event(dev_ctxt, cctxt, event);
break;
}
}
if (VCD_FAILED(rc))
VCD_MSG_ERROR("vcd_power_event: event 0x%x failed", event);
return rc;
}
u32 vcd_device_power_event(struct vcd_dev_ctxt *dev_ctxt, u32 event,
struct vcd_clnt_ctxt *cctxt)
{
u32 rc = VCD_ERR_FAIL;
u32 set_perf_lvl;
switch (event) {
case VCD_EVT_PWR_DEV_INIT_BEGIN:
{
if (dev_ctxt->pwr_clk_state ==
VCD_PWRCLK_STATE_OFF) {
if (res_trk_get_max_perf_level(&dev_ctxt->
max_perf_lvl)) {
if (res_trk_power_up()) {
dev_ctxt->pwr_clk_state =
VCD_PWRCLK_STATE_ON_NOTCLOCKED;
dev_ctxt->curr_perf_lvl = 0;
dev_ctxt->reqd_perf_lvl = 0;
dev_ctxt->active_clnts = 0;
dev_ctxt->
set_perf_lvl_pending = false;
rc = vcd_enable_clock(dev_ctxt,
cctxt);
if (VCD_FAILED(rc)) {
(void)res_trk_power_down();
dev_ctxt->pwr_clk_state =
VCD_PWRCLK_STATE_OFF;
}
}
}
}
break;
}
case VCD_EVT_PWR_DEV_INIT_END:
case VCD_EVT_PWR_DEV_TERM_FAIL:
case VCD_EVT_PWR_DEV_SLEEP_BEGIN:
case VCD_EVT_PWR_DEV_HWTIMEOUT:
{
rc = vcd_gate_clock(dev_ctxt);
break;
}
case VCD_EVT_PWR_DEV_INIT_FAIL:
case VCD_EVT_PWR_DEV_TERM_END:
{
if (dev_ctxt->pwr_clk_state !=
VCD_PWRCLK_STATE_OFF) {
(void)vcd_disable_clock(dev_ctxt);
(void)res_trk_power_down();
dev_ctxt->pwr_clk_state =
VCD_PWRCLK_STATE_OFF;
dev_ctxt->curr_perf_lvl = 0;
dev_ctxt->reqd_perf_lvl = 0;
dev_ctxt->active_clnts = 0;
dev_ctxt->set_perf_lvl_pending = false;
rc = VCD_S_SUCCESS;
}
break;
}
case VCD_EVT_PWR_DEV_TERM_BEGIN:
case VCD_EVT_PWR_DEV_SLEEP_END:
{
rc = vcd_un_gate_clock(dev_ctxt);
break;
}
case VCD_EVT_PWR_DEV_SET_PERFLVL:
{
set_perf_lvl =
dev_ctxt->reqd_perf_lvl >
0 ? dev_ctxt->
reqd_perf_lvl : VCD_MIN_PERF_LEVEL;
rc = vcd_set_perf_level(dev_ctxt, set_perf_lvl);
break;
}
}
return rc;
}
u32 vcd_client_power_event(
struct vcd_dev_ctxt *dev_ctxt,
struct vcd_clnt_ctxt *cctxt, u32 event)
{
u32 rc = VCD_ERR_FAIL;
switch (event) {
case VCD_EVT_PWR_CLNT_CMD_BEGIN:
{
rc = vcd_un_gate_clock(dev_ctxt);
break;
}
case VCD_EVT_PWR_CLNT_CMD_END:
{
rc = vcd_gate_clock(dev_ctxt);
break;
}
case VCD_EVT_PWR_CLNT_CMD_FAIL:
{
if (!vcd_core_is_busy(dev_ctxt))
rc = vcd_gate_clock(dev_ctxt);
break;
}
case VCD_EVT_PWR_CLNT_PAUSE:
case VCD_EVT_PWR_CLNT_LAST_FRAME:
case VCD_EVT_PWR_CLNT_ERRFATAL:
{
if (cctxt) {
rc = VCD_S_SUCCESS;
if (cctxt->status.req_perf_lvl) {
dev_ctxt->reqd_perf_lvl -=
cctxt->reqd_perf_lvl;
cctxt->status.req_perf_lvl = false;
rc = vcd_set_perf_level(dev_ctxt,
dev_ctxt->reqd_perf_lvl);
}
}
break;
}
case VCD_EVT_PWR_CLNT_RESUME:
case VCD_EVT_PWR_CLNT_FIRST_FRAME:
{
if (cctxt) {
rc = VCD_S_SUCCESS;
if (!cctxt->status.req_perf_lvl) {
dev_ctxt->reqd_perf_lvl +=
cctxt->reqd_perf_lvl;
cctxt->status.req_perf_lvl = true;
rc = vcd_set_perf_level(dev_ctxt,
dev_ctxt->reqd_perf_lvl);
}
}
break;
}
}
return rc;
}
u32 vcd_enable_clock(struct vcd_dev_ctxt *dev_ctxt,
struct vcd_clnt_ctxt *cctxt)
{
u32 rc = VCD_S_SUCCESS;
u32 set_perf_lvl;
if (dev_ctxt->pwr_clk_state == VCD_PWRCLK_STATE_OFF) {
VCD_MSG_ERROR("vcd_enable_clock(): Already in state "
"VCD_PWRCLK_STATE_OFF\n");
rc = VCD_ERR_FAIL;
} else if (dev_ctxt->pwr_clk_state ==
VCD_PWRCLK_STATE_ON_NOTCLOCKED) {
set_perf_lvl =
dev_ctxt->reqd_perf_lvl >
0 ? dev_ctxt->
reqd_perf_lvl : VCD_MIN_PERF_LEVEL;
rc = vcd_set_perf_level(dev_ctxt, set_perf_lvl);
if (!VCD_FAILED(rc)) {
if (res_trk_enable_clocks()) {
dev_ctxt->pwr_clk_state =
VCD_PWRCLK_STATE_ON_CLOCKED;
}
} else {
rc = VCD_ERR_FAIL;
}
}
if (!VCD_FAILED(rc))
dev_ctxt->active_clnts++;
return rc;
}
u32 vcd_disable_clock(struct vcd_dev_ctxt *dev_ctxt)
{
u32 rc = VCD_S_SUCCESS;
if (dev_ctxt->pwr_clk_state == VCD_PWRCLK_STATE_OFF) {
VCD_MSG_ERROR("vcd_disable_clock(): Already in state "
"VCD_PWRCLK_STATE_OFF\n");
rc = VCD_ERR_FAIL;
} else if (dev_ctxt->pwr_clk_state == VCD_PWRCLK_STATE_ON_CLOCKED ||
dev_ctxt->pwr_clk_state == VCD_PWRCLK_STATE_ON_CLOCKGATED) {
dev_ctxt->active_clnts--;
if (!dev_ctxt->active_clnts) {
if (!res_trk_disable_clocks())
rc = VCD_ERR_FAIL;
dev_ctxt->pwr_clk_state =
VCD_PWRCLK_STATE_ON_NOTCLOCKED;
dev_ctxt->curr_perf_lvl = 0;
}
}
return rc;
}
u32 vcd_set_perf_level(struct vcd_dev_ctxt *dev_ctxt, u32 perf_lvl)
{
u32 rc = VCD_S_SUCCESS;
if (!vcd_core_is_busy(dev_ctxt)) {
if (res_trk_set_perf_level(perf_lvl,
&dev_ctxt->curr_perf_lvl, dev_ctxt)) {
dev_ctxt->set_perf_lvl_pending = false;
} else {
rc = VCD_ERR_FAIL;
dev_ctxt->set_perf_lvl_pending = true;
}
} else {
dev_ctxt->set_perf_lvl_pending = true;
}
return rc;
}
u32 vcd_set_perf_turbo_level(struct vcd_clnt_ctxt *cctxt)
{
u32 rc = VCD_S_SUCCESS;
#ifdef CONFIG_MSM_BUS_SCALING
struct vcd_dev_ctxt *dev_ctxt = cctxt->dev_ctxt;
pr_err("\n Setting Turbo mode !!");
if (res_trk_update_bus_perf_level(dev_ctxt,
RESTRK_1080P_TURBO_PERF_LEVEL) < 0) {
pr_err("\n %s(): update buf perf level failed\n",
__func__);
return false;
}
dev_ctxt->curr_perf_lvl = RESTRK_1080P_TURBO_PERF_LEVEL;
vcd_update_decoder_perf_level(dev_ctxt, RESTRK_1080P_TURBO_PERF_LEVEL);
#endif
return rc;
}
u32 vcd_update_decoder_perf_level(struct vcd_dev_ctxt *dev_ctxt, u32 perf_lvl)
{
u32 rc = VCD_S_SUCCESS;
if (res_trk_set_perf_level(perf_lvl,
&dev_ctxt->curr_perf_lvl, dev_ctxt)) {
dev_ctxt->set_perf_lvl_pending = false;
} else {
rc = VCD_ERR_FAIL;
dev_ctxt->set_perf_lvl_pending = true;
}
return rc;
}
u32 vcd_update_clnt_perf_lvl(
struct vcd_clnt_ctxt *cctxt,
struct vcd_property_frame_rate *fps, u32 frm_p_units)
{
u32 rc = VCD_S_SUCCESS;
struct vcd_dev_ctxt *dev_ctxt = cctxt->dev_ctxt;
u32 new_perf_lvl;
new_perf_lvl = frm_p_units *\
(fps->fps_numerator / fps->fps_denominator);
if ((fps->fps_numerator * 1000) / fps->fps_denominator
> VCD_MAXPERF_FPS_THRESHOLD_X_1000) {
u32 max_perf_level = 0;
if (res_trk_get_max_perf_level(&max_perf_level)) {
new_perf_lvl = max_perf_level;
VCD_MSG_HIGH("Using max perf level(%d) for >60fps\n",
new_perf_lvl);
} else {
VCD_MSG_ERROR("Failed to get max perf level\n");
}
}
if (cctxt->status.req_perf_lvl) {
dev_ctxt->reqd_perf_lvl =
dev_ctxt->reqd_perf_lvl - cctxt->reqd_perf_lvl +
new_perf_lvl;
rc = vcd_set_perf_level(cctxt->dev_ctxt,
dev_ctxt->reqd_perf_lvl);
}
cctxt->reqd_perf_lvl = new_perf_lvl;
return rc;
}
u32 vcd_gate_clock(struct vcd_dev_ctxt *dev_ctxt)
{
u32 rc = VCD_S_SUCCESS;
if (dev_ctxt->pwr_clk_state == VCD_PWRCLK_STATE_OFF ||
dev_ctxt->pwr_clk_state == VCD_PWRCLK_STATE_ON_NOTCLOCKED) {
VCD_MSG_ERROR("%s(): Clk is Off or Not Clked yet\n", __func__);
rc = VCD_ERR_FAIL;
} else if (dev_ctxt->pwr_clk_state == VCD_PWRCLK_STATE_ON_CLOCKGATED)
rc = VCD_S_SUCCESS;
else if (res_trk_disable_clocks())
dev_ctxt->pwr_clk_state = VCD_PWRCLK_STATE_ON_CLOCKGATED;
else
rc = VCD_ERR_FAIL;
return rc;
}
u32 vcd_un_gate_clock(struct vcd_dev_ctxt *dev_ctxt)
{
u32 rc = VCD_S_SUCCESS;
if (dev_ctxt->pwr_clk_state == VCD_PWRCLK_STATE_OFF ||
dev_ctxt->pwr_clk_state == VCD_PWRCLK_STATE_ON_NOTCLOCKED) {
VCD_MSG_ERROR("%s(): Clk is Off or Not Clked yet\n", __func__);
rc = VCD_ERR_FAIL;
} else if (dev_ctxt->pwr_clk_state == VCD_PWRCLK_STATE_ON_CLOCKED)
rc = VCD_S_SUCCESS;
else if (res_trk_enable_clocks())
dev_ctxt->pwr_clk_state = VCD_PWRCLK_STATE_ON_CLOCKED;
else
rc = VCD_ERR_FAIL;
return rc;
}
@@ -0,0 +1,43 @@
/* Copyright (c) 2010, The Linux Foundation. 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.
*
*/
#ifndef _VCD_POWERSM_H_
#define _VCD_POWERSM_H_
#define VCD_EVT_PWR_BASE 0x5000
#define VCD_EVT_PWR_DEV_INIT_BEGIN (VCD_EVT_PWR_BASE + 0x1)
#define VCD_EVT_PWR_DEV_INIT_END (VCD_EVT_PWR_BASE + 0x2)
#define VCD_EVT_PWR_DEV_INIT_FAIL (VCD_EVT_PWR_BASE + 0x3)
#define VCD_EVT_PWR_DEV_TERM_BEGIN (VCD_EVT_PWR_BASE + 0x4)
#define VCD_EVT_PWR_DEV_TERM_END (VCD_EVT_PWR_BASE + 0x5)
#define VCD_EVT_PWR_DEV_TERM_FAIL (VCD_EVT_PWR_BASE + 0x6)
#define VCD_EVT_PWR_DEV_SLEEP_BEGIN (VCD_EVT_PWR_BASE + 0x7)
#define VCD_EVT_PWR_DEV_SLEEP_END (VCD_EVT_PWR_BASE + 0x8)
#define VCD_EVT_PWR_DEV_SET_PERFLVL (VCD_EVT_PWR_BASE + 0x9)
#define VCD_EVT_PWR_DEV_HWTIMEOUT (VCD_EVT_PWR_BASE + 0xa)
#define VCD_EVT_PWR_CLNT_CMD_BEGIN (VCD_EVT_PWR_BASE + 0xb)
#define VCD_EVT_PWR_CLNT_CMD_END (VCD_EVT_PWR_BASE + 0xc)
#define VCD_EVT_PWR_CLNT_CMD_FAIL (VCD_EVT_PWR_BASE + 0xd)
#define VCD_EVT_PWR_CLNT_PAUSE (VCD_EVT_PWR_BASE + 0xe)
#define VCD_EVT_PWR_CLNT_RESUME (VCD_EVT_PWR_BASE + 0xf)
#define VCD_EVT_PWR_CLNT_FIRST_FRAME (VCD_EVT_PWR_BASE + 0x10)
#define VCD_EVT_PWR_CLNT_LAST_FRAME (VCD_EVT_PWR_BASE + 0x11)
#define VCD_EVT_PWR_CLNT_ERRFATAL (VCD_EVT_PWR_BASE + 0x12)
enum vcd_pwr_clk_state {
VCD_PWRCLK_STATE_OFF = 0,
VCD_PWRCLK_STATE_ON_NOTCLOCKED,
VCD_PWRCLK_STATE_ON_CLOCKED,
VCD_PWRCLK_STATE_ON_CLOCKGATED
};
#endif
@@ -0,0 +1,296 @@
/* Copyright (c) 2010-2013, Linux Foundation. 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.
*
*/
#include <media/msm/vidc_type.h>
#include "vcd.h"
#define NORMALIZATION_FACTOR 3600
#define ADJUST_CLIENT_ROUNDS(client, round_adjustment) \
do {\
if ((client)->rounds < round_adjustment) {\
(client)->rounds = 0;\
VCD_MSG_HIGH("%s(): WARNING: Scheduler list unsorted",\
__func__);\
} else\
(client)->rounds -= round_adjustment;\
} while (0)
u32 vcd_sched_create(struct list_head *sched_list)
{
u32 rc = VCD_S_SUCCESS;
if (!sched_list) {
VCD_MSG_ERROR("%s(): Invalid parameter", __func__);
rc = VCD_ERR_ILLEGAL_PARM;
} else
INIT_LIST_HEAD(sched_list);
return rc;
}
void vcd_sched_destroy(struct list_head *sched_clnt_list)
{
struct vcd_sched_clnt_ctx *sched_clnt, *sched_clnt_next;
if (sched_clnt_list)
list_for_each_entry_safe(sched_clnt,
sched_clnt_next, sched_clnt_list, list) {
list_del_init(&sched_clnt->list);
sched_clnt->clnt_active = false;
}
}
void insert_client_in_list(struct list_head *sched_clnt_list,
struct vcd_sched_clnt_ctx *sched_new_clnt, bool tail)
{
struct vcd_sched_clnt_ctx *sched_clnt;
if (!list_empty(sched_clnt_list)) {
if (tail)
sched_clnt = list_entry(sched_clnt_list->prev,
struct vcd_sched_clnt_ctx, list);
else
sched_clnt = list_first_entry(sched_clnt_list,
struct vcd_sched_clnt_ctx, list);
sched_new_clnt->rounds = sched_clnt->rounds;
} else
sched_new_clnt->rounds = 0;
if (tail)
list_add_tail(&sched_new_clnt->list, sched_clnt_list);
else
list_add(&sched_new_clnt->list, sched_clnt_list);
}
u32 vcd_sched_add_client(struct vcd_clnt_ctxt *cctxt)
{
struct vcd_property_hdr prop_hdr;
struct vcd_sched_clnt_ctx *sched_cctxt;
u32 rc = VCD_S_SUCCESS;
if (!cctxt) {
VCD_MSG_ERROR("%s(): Invalid parameter", __func__);
rc = VCD_ERR_ILLEGAL_PARM;
} else if (cctxt->sched_clnt_hdl)
VCD_MSG_HIGH(
"%s(): Scheduler client already exists!", __func__);
else {
sched_cctxt = (struct vcd_sched_clnt_ctx *)
kmalloc(sizeof(struct vcd_sched_clnt_ctx),
GFP_KERNEL);
if (sched_cctxt) {
prop_hdr.prop_id = DDL_I_FRAME_PROC_UNITS;
prop_hdr.sz = sizeof(cctxt->frm_p_units);
rc = ddl_get_property(cctxt->ddl_handle, &prop_hdr,
&cctxt->frm_p_units);
if (VCD_FAILED(rc)) {
kfree(sched_cctxt);
VCD_MSG_ERROR(
"Failed: Get DDL_I_FRAME_PROC_UNITS");
return rc;
}
if (cctxt->decoding) {
cctxt->frm_rate.fps_numerator =
VCD_DEC_INITIAL_FRAME_RATE;
cctxt->frm_rate.fps_denominator = 1;
} else {
prop_hdr.prop_id = VCD_I_FRAME_RATE;
prop_hdr.sz = sizeof(cctxt->frm_rate);
rc = ddl_get_property(cctxt->ddl_handle,
&prop_hdr, &cctxt->frm_rate);
if (VCD_FAILED(rc)) {
kfree(sched_cctxt);
VCD_MSG_ERROR(
"Failed: Get VCD_I_FRAME_RATE");
return rc;
}
}
if (!cctxt->perf_set_by_client)
cctxt->reqd_perf_lvl = cctxt->frm_p_units *
cctxt->frm_rate.fps_numerator /
cctxt->frm_rate.fps_denominator;
cctxt->sched_clnt_hdl = sched_cctxt;
memset(sched_cctxt, 0,
sizeof(struct vcd_sched_clnt_ctx));
sched_cctxt->tkns = 0;
sched_cctxt->round_perfrm = NORMALIZATION_FACTOR *
cctxt->frm_rate.fps_denominator /
cctxt->frm_rate.fps_numerator;
sched_cctxt->clnt_active = true;
sched_cctxt->clnt_data = cctxt;
INIT_LIST_HEAD(&sched_cctxt->ip_frm_list);
insert_client_in_list(
&cctxt->dev_ctxt->sched_clnt_list,
sched_cctxt, false);
}
}
return rc;
}
u32 vcd_sched_remove_client(struct vcd_sched_clnt_ctx *sched_cctxt)
{
u32 rc = VCD_S_SUCCESS;
struct vcd_clnt_ctxt *cctxt;
if (!sched_cctxt) {
VCD_MSG_ERROR("%s(): Invalid handle ptr", __func__);
rc = VCD_ERR_ILLEGAL_PARM;
} else if (!list_empty(&sched_cctxt->ip_frm_list)) {
VCD_MSG_ERROR(
"%s(): Cannot remove client, queue no empty", __func__);
rc = VCD_ERR_ILLEGAL_OP;
} else {
cctxt = sched_cctxt->clnt_data;
list_del(&sched_cctxt->list);
memset(sched_cctxt, 0,
sizeof(struct vcd_sched_clnt_ctx));
kfree(sched_cctxt);
}
return rc;
}
u32 vcd_sched_update_config(struct vcd_clnt_ctxt *cctxt)
{
u32 rc = VCD_S_SUCCESS;
if (!cctxt || !cctxt->sched_clnt_hdl) {
VCD_MSG_ERROR("%s(): Invalid parameter", __func__);
rc = VCD_ERR_ILLEGAL_PARM;
} else {
cctxt->sched_clnt_hdl->rounds /=
cctxt->sched_clnt_hdl->round_perfrm;
cctxt->sched_clnt_hdl->round_perfrm =
NORMALIZATION_FACTOR *
cctxt->frm_rate.fps_denominator /
cctxt->frm_rate.fps_numerator;
cctxt->sched_clnt_hdl->rounds *=
cctxt->sched_clnt_hdl->round_perfrm;
}
return rc;
}
u32 vcd_sched_queue_buffer(
struct vcd_sched_clnt_ctx *sched_cctxt,
struct vcd_buffer_entry *buffer, u32 tail)
{
u32 rc = VCD_S_SUCCESS;
if (!sched_cctxt || !buffer) {
VCD_MSG_ERROR("%s(): Invalid parameter", __func__);
rc = VCD_ERR_ILLEGAL_PARM;
} else if (tail)
list_add_tail(&buffer->sched_list,
&sched_cctxt->ip_frm_list);
else
list_add(&buffer->sched_list, &sched_cctxt->ip_frm_list);
return rc;
}
u32 vcd_sched_dequeue_buffer(
struct vcd_sched_clnt_ctx *sched_cctxt,
struct vcd_buffer_entry **buffer)
{
u32 rc = VCD_ERR_QEMPTY;
if (!sched_cctxt || !buffer) {
VCD_MSG_ERROR("%s(): Invalid parameter", __func__);
rc = VCD_ERR_ILLEGAL_PARM;
} else {
*buffer = NULL;
if (!list_empty(&sched_cctxt->ip_frm_list)) {
*buffer = list_first_entry(
&sched_cctxt->ip_frm_list,
struct vcd_buffer_entry,
sched_list);
list_del(&(*buffer)->sched_list);
rc = VCD_S_SUCCESS;
}
}
return rc;
}
u32 vcd_sched_mark_client_eof(struct vcd_sched_clnt_ctx *sched_cctxt)
{
u32 rc = VCD_S_SUCCESS;
struct vcd_buffer_entry *buffer = NULL;
if (!sched_cctxt) {
VCD_MSG_ERROR("%s(): Invalid parameter", __func__);
rc = VCD_ERR_ILLEGAL_PARM;
} else if (!list_empty(&sched_cctxt->ip_frm_list)) {
buffer = list_entry(sched_cctxt->ip_frm_list.prev,
struct vcd_buffer_entry, sched_list);
buffer->frame.flags |= VCD_FRAME_FLAG_EOS;
} else
rc = VCD_ERR_QEMPTY;
return rc;
}
u32 vcd_sched_suspend_resume_clnt(
struct vcd_clnt_ctxt *cctxt, u32 state)
{
u32 rc = VCD_S_SUCCESS;
struct vcd_sched_clnt_ctx *sched_cctxt;
if (!cctxt || !cctxt->sched_clnt_hdl) {
VCD_MSG_ERROR("%s(): Invalid parameter", __func__);
rc = VCD_ERR_ILLEGAL_PARM;
} else {
sched_cctxt = cctxt->sched_clnt_hdl;
if (state != sched_cctxt->clnt_active) {
sched_cctxt->clnt_active = state;
if (state)
insert_client_in_list(&cctxt->dev_ctxt->\
sched_clnt_list, sched_cctxt, false);
else
list_del_init(&sched_cctxt->list);
}
}
return rc;
}
u32 vcd_sched_get_client_frame(struct list_head *sched_clnt_list,
struct vcd_clnt_ctxt **cctxt,
struct vcd_buffer_entry **buffer)
{
u32 rc = VCD_ERR_QEMPTY, round_adjustment = 0;
struct vcd_sched_clnt_ctx *sched_clnt, *clnt_nxt;
if (!sched_clnt_list || !cctxt || !buffer) {
VCD_MSG_ERROR("%s(): Invalid parameter", __func__);
rc = VCD_ERR_ILLEGAL_PARM;
} else if (!list_empty(sched_clnt_list)) {
*cctxt = NULL;
*buffer = NULL;
list_for_each_entry_safe(sched_clnt,
clnt_nxt, sched_clnt_list, list) {
if (&sched_clnt->list == sched_clnt_list->next)
round_adjustment = sched_clnt->rounds;
if (*cctxt) {
if ((*cctxt)->sched_clnt_hdl->rounds >=
sched_clnt->rounds)
list_move(&(*cctxt)->sched_clnt_hdl\
->list, &sched_clnt->list);
ADJUST_CLIENT_ROUNDS(sched_clnt,
round_adjustment);
} else if (sched_clnt->tkns &&
!list_empty(&sched_clnt->ip_frm_list)) {
*cctxt = sched_clnt->clnt_data;
sched_clnt->rounds += sched_clnt->round_perfrm;
} else
ADJUST_CLIENT_ROUNDS(sched_clnt,
round_adjustment);
}
if (*cctxt) {
rc = vcd_sched_dequeue_buffer(
(*cctxt)->sched_clnt_hdl, buffer);
if (rc == VCD_S_SUCCESS) {
(*cctxt)->sched_clnt_hdl->tkns--;
ADJUST_CLIENT_ROUNDS((*cctxt)->\
sched_clnt_hdl, round_adjustment);
}
}
}
return rc;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,106 @@
/* Copyright (c) 2010, The Linux Foundation. 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.
*
*/
#include "vidc_type.h"
#include "vcd_util.h"
u32 vcd_critical_section_create(u32 **p_cs)
{
struct mutex *lock;
if (!p_cs) {
VCD_MSG_ERROR("Bad critical section ptr");
return VCD_ERR_BAD_POINTER;
} else {
lock = kmalloc(sizeof(struct mutex), GFP_KERNEL);
if (!lock) {
VCD_MSG_ERROR("Failed: vcd_critical_section_create");
return VCD_ERR_ALLOC_FAIL;
}
mutex_init(lock);
*p_cs = (u32 *) lock;
return VCD_S_SUCCESS;
}
}
u32 vcd_critical_section_release(u32 *cs)
{
struct mutex *lock = (struct mutex *)cs;
if (!lock) {
VCD_MSG_ERROR("Bad critical section object");
return VCD_ERR_BAD_POINTER;
}
mutex_destroy(lock);
kfree(cs);
return VCD_S_SUCCESS;
}
u32 vcd_critical_section_enter(u32 *cs)
{
struct mutex *lock = (struct mutex *)cs;
if (!lock) {
VCD_MSG_ERROR("Bad critical section object");
return VCD_ERR_BAD_POINTER;
} else
mutex_lock(lock);
return VCD_S_SUCCESS;
}
u32 vcd_critical_section_leave(u32 *cs)
{
struct mutex *lock = (struct mutex *)cs;
if (!lock) {
VCD_MSG_ERROR("Bad critical section object");
return VCD_ERR_BAD_POINTER;
} else
mutex_unlock(lock);
return VCD_S_SUCCESS;
}
int vcd_pmem_alloc(u32 size, u8 **kernel_vaddr, u8 **phy_addr)
{
*phy_addr =
(u8 *) pmem_kalloc(size, PMEM_MEMTYPE | PMEM_ALIGNMENT_4K);
if (!IS_ERR((void *)*phy_addr)) {
*kernel_vaddr = ioremap((unsigned long)*phy_addr, size);
if (!*kernel_vaddr) {
pr_err("%s: could not ioremap in kernel pmem buffers\n",
__func__);
pmem_kfree((s32) *phy_addr);
return -ENOMEM;
}
pr_debug("write buf: phy addr 0x%08x kernel addr 0x%08x\n",
(u32) *phy_addr, (u32) *kernel_vaddr);
return 0;
} else {
pr_err("%s: could not allocte in kernel pmem buffers\n",
__func__);
return -ENOMEM;
}
}
int vcd_pmem_free(u8 *kernel_vaddr, u8 *phy_addr)
{
iounmap((void *)kernel_vaddr);
pmem_kfree((s32) phy_addr);
return 0;
}
@@ -0,0 +1,52 @@
/* Copyright (c) 2010-2012, The Linux Foundation. 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.
*
*/
#ifndef _VCD_UTIL_H_
#define _VCD_UTIL_H_
#include <media/msm/vidc_type.h>
#include <media/msm/vcd_api.h>
#if DEBUG
#define VCD_MSG_LOW(xx_fmt...) printk(KERN_INFO "\n\t* " xx_fmt)
#define VCD_MSG_MED(xx_fmt...) printk(KERN_INFO "\n * " xx_fmt)
#define VCD_MSG_HIGH(xx_fmt...) printk(KERN_WARNING "\n" xx_fmt)
#define VCD_MSG_ERROR(xx_fmt...) printk(KERN_ERR "\n err: " xx_fmt)
#else
#define VCD_MSG_LOW(xx_fmt...)
#define VCD_MSG_MED(xx_fmt...)
#define VCD_MSG_HIGH(xx_fmt...)
#define VCD_MSG_ERROR(xx_fmt...)
#endif
#define VCD_MSG_FATAL(xx_fmt...) printk(KERN_ERR "\n<FATAL> " xx_fmt)
#define VCD_FAILED_RETURN(rc, xx_fmt...) \
do { \
if (VCD_FAILED(rc)) { \
printk(KERN_ERR xx_fmt); \
return rc; \
} \
} while (0)
#define VCD_FAILED_DEVICE_FATAL(rc) \
(rc == VCD_ERR_HW_FATAL ? true : false)
#define VCD_FAILED_CLIENT_FATAL(rc) \
(rc == VCD_ERR_CLIENT_FATAL ? true : false)
#define VCD_FAILED_FATAL(rc) \
((VCD_FAILED_DEVICE_FATAL(rc) || VCD_FAILED_CLIENT_FATAL(rc)) \
? true : false)
#endif