1884 lines
53 KiB
C
1884 lines
53 KiB
C
/* Copyright (c) 2012-2016,2019 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/slab.h>
|
|
#include <linux/list.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/hash.h>
|
|
#include <soc/qcom/smem.h>
|
|
#include "vidc_hfi_helper.h"
|
|
#include "vidc_hfi_io.h"
|
|
#include "msm_vidc_debug.h"
|
|
#include "vidc_hfi.h"
|
|
|
|
static enum vidc_status hfi_parse_init_done_properties(
|
|
struct msm_vidc_capability *capability,
|
|
u32 num_sessions, u8 *data_ptr, u32 num_properties,
|
|
u32 rem_bytes, u32 codec, u32 domain);
|
|
|
|
static enum vidc_status hfi_map_err_status(u32 hfi_err)
|
|
{
|
|
enum vidc_status vidc_err;
|
|
switch (hfi_err) {
|
|
case HFI_ERR_NONE:
|
|
case HFI_ERR_SESSION_SAME_STATE_OPERATION:
|
|
vidc_err = VIDC_ERR_NONE;
|
|
break;
|
|
case HFI_ERR_SYS_FATAL:
|
|
vidc_err = VIDC_ERR_HW_FATAL;
|
|
break;
|
|
case HFI_ERR_SYS_VERSION_MISMATCH:
|
|
case HFI_ERR_SYS_INVALID_PARAMETER:
|
|
case HFI_ERR_SYS_SESSION_ID_OUT_OF_RANGE:
|
|
case HFI_ERR_SESSION_INVALID_PARAMETER:
|
|
case HFI_ERR_SESSION_INVALID_SESSION_ID:
|
|
case HFI_ERR_SESSION_INVALID_STREAM_ID:
|
|
vidc_err = VIDC_ERR_BAD_PARAM;
|
|
break;
|
|
case HFI_ERR_SYS_INSUFFICIENT_RESOURCES:
|
|
case HFI_ERR_SYS_UNSUPPORTED_DOMAIN:
|
|
case HFI_ERR_SYS_UNSUPPORTED_CODEC:
|
|
case HFI_ERR_SESSION_UNSUPPORTED_PROPERTY:
|
|
case HFI_ERR_SESSION_UNSUPPORTED_SETTING:
|
|
case HFI_ERR_SESSION_INSUFFICIENT_RESOURCES:
|
|
case HFI_ERR_SESSION_UNSUPPORTED_STREAM:
|
|
vidc_err = VIDC_ERR_NOT_SUPPORTED;
|
|
break;
|
|
case HFI_ERR_SYS_MAX_SESSIONS_REACHED:
|
|
vidc_err = VIDC_ERR_MAX_CLIENTS;
|
|
break;
|
|
case HFI_ERR_SYS_SESSION_IN_USE:
|
|
vidc_err = VIDC_ERR_CLIENT_PRESENT;
|
|
break;
|
|
case HFI_ERR_SESSION_FATAL:
|
|
vidc_err = VIDC_ERR_CLIENT_FATAL;
|
|
break;
|
|
case HFI_ERR_SESSION_BAD_POINTER:
|
|
vidc_err = VIDC_ERR_BAD_PARAM;
|
|
break;
|
|
case HFI_ERR_SESSION_INCORRECT_STATE_OPERATION:
|
|
vidc_err = VIDC_ERR_BAD_STATE;
|
|
break;
|
|
case HFI_ERR_SESSION_STREAM_CORRUPT:
|
|
case HFI_ERR_SESSION_STREAM_CORRUPT_OUTPUT_STALLED:
|
|
vidc_err = VIDC_ERR_BITSTREAM_ERR;
|
|
break;
|
|
case HFI_ERR_SESSION_SYNC_FRAME_NOT_DETECTED:
|
|
vidc_err = VIDC_ERR_IFRAME_EXPECTED;
|
|
break;
|
|
case HFI_ERR_SESSION_START_CODE_NOT_FOUND:
|
|
vidc_err = VIDC_ERR_START_CODE_NOT_FOUND;
|
|
break;
|
|
case HFI_ERR_SESSION_EMPTY_BUFFER_DONE_OUTPUT_PENDING:
|
|
default:
|
|
vidc_err = VIDC_ERR_FAIL;
|
|
break;
|
|
}
|
|
return vidc_err;
|
|
}
|
|
|
|
struct hal_session *hfi_process_get_session(
|
|
struct list_head *sessions, u32 session_id)
|
|
{
|
|
struct hal_session *session = NULL;
|
|
bool found_session = false;
|
|
|
|
list_for_each_entry(session, sessions, list) {
|
|
if (hash32_ptr(session) == session_id) {
|
|
found_session = true;
|
|
break;
|
|
}
|
|
}
|
|
return found_session ? session : NULL;
|
|
}
|
|
|
|
static inline int VALIDATE_PKT_SIZE(u32 rem_size, u32 msg_size)
|
|
{
|
|
if (rem_size < msg_size) {
|
|
dprintk(VIDC_ERR,
|
|
"session_init_donesys_init_done: bad_pkt_size\n");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static void hfi_process_sess_evt_seq_changed(
|
|
msm_vidc_callback callback, u32 device_id,
|
|
struct hal_session *session,
|
|
struct hfi_msg_event_notify_packet *pkt)
|
|
{
|
|
struct msm_vidc_cb_event event_notify = {0};
|
|
u32 num_properties_changed, rem_size;
|
|
struct hfi_frame_size *frame_sz;
|
|
struct hfi_profile_level *profile_level;
|
|
u8 *data_ptr;
|
|
int prop_id;
|
|
if (!VALIDATE_PKT_SIZE(pkt->size,
|
|
sizeof(struct hfi_msg_event_notify_packet)))
|
|
return;
|
|
|
|
event_notify.device_id = device_id;
|
|
event_notify.session_id = session->session_id;
|
|
event_notify.status = VIDC_ERR_NONE;
|
|
num_properties_changed = pkt->event_data2;
|
|
switch (pkt->event_data1) {
|
|
case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUFFER_RESOURCES:
|
|
event_notify.hal_event_type =
|
|
HAL_EVENT_SEQ_CHANGED_SUFFICIENT_RESOURCES;
|
|
break;
|
|
case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUFFER_RESOURCES:
|
|
event_notify.hal_event_type =
|
|
HAL_EVENT_SEQ_CHANGED_INSUFFICIENT_RESOURCES;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (num_properties_changed) {
|
|
data_ptr = (u8 *) &pkt->rg_ext_event_data[0];
|
|
rem_size = pkt->size - sizeof(struct
|
|
hfi_msg_event_notify_packet) + sizeof(u32);
|
|
do {
|
|
if (!VALIDATE_PKT_SIZE(rem_size, sizeof(u32)))
|
|
return;
|
|
prop_id = (int) *((u32 *)data_ptr);
|
|
rem_size -= sizeof(u32);
|
|
switch (prop_id) {
|
|
case HFI_PROPERTY_PARAM_FRAME_SIZE:
|
|
if (!VALIDATE_PKT_SIZE(rem_size, sizeof(struct
|
|
hfi_frame_size)))
|
|
return;
|
|
data_ptr = data_ptr + sizeof(u32);
|
|
frame_sz =
|
|
(struct hfi_frame_size *) data_ptr;
|
|
event_notify.width = frame_sz->width;
|
|
event_notify.height = frame_sz->height;
|
|
dprintk(VIDC_DBG, "height: %d width: %d\n",
|
|
frame_sz->height, frame_sz->width);
|
|
data_ptr +=
|
|
sizeof(struct hfi_frame_size);
|
|
rem_size -= sizeof(struct hfi_frame_size);
|
|
break;
|
|
case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
|
|
if (!VALIDATE_PKT_SIZE(rem_size, sizeof(struct
|
|
hfi_profile_level)))
|
|
return;
|
|
data_ptr = data_ptr + sizeof(u32);
|
|
profile_level =
|
|
(struct hfi_profile_level *) data_ptr;
|
|
dprintk(VIDC_DBG, "profile: %d level: %d\n",
|
|
profile_level->profile,
|
|
profile_level->level);
|
|
data_ptr +=
|
|
sizeof(struct hfi_profile_level);
|
|
rem_size -= sizeof(struct hfi_profile_level);
|
|
break;
|
|
default:
|
|
dprintk(VIDC_ERR,
|
|
"%s cmd: 0x%x not supported\n",
|
|
__func__, prop_id);
|
|
break;
|
|
}
|
|
num_properties_changed--;
|
|
} while (num_properties_changed > 0);
|
|
}
|
|
callback(VIDC_EVENT_CHANGE, &event_notify);
|
|
}
|
|
|
|
static void hfi_process_evt_release_buffer_ref(
|
|
msm_vidc_callback callback, u32 device_id,
|
|
struct hal_session *session,
|
|
struct hfi_msg_event_notify_packet *pkt)
|
|
{
|
|
struct msm_vidc_cb_event event_notify = {0};
|
|
struct hfi_msg_release_buffer_ref_event_packet *data;
|
|
|
|
dprintk(VIDC_DBG,
|
|
"RECEIVED: EVENT_NOTIFY - release_buffer_reference\n");
|
|
if (sizeof(struct hfi_msg_event_notify_packet)
|
|
> pkt->size) {
|
|
dprintk(VIDC_ERR,
|
|
"hal_process_session_init_done: bad_pkt_size\n");
|
|
return;
|
|
}
|
|
|
|
data = (struct hfi_msg_release_buffer_ref_event_packet *)
|
|
pkt->rg_ext_event_data;
|
|
|
|
event_notify.device_id = device_id;
|
|
event_notify.session_id = session->session_id;
|
|
event_notify.status = VIDC_ERR_NONE;
|
|
event_notify.hal_event_type = HAL_EVENT_RELEASE_BUFFER_REFERENCE;
|
|
event_notify.packet_buffer = data->packet_buffer;
|
|
event_notify.extra_data_buffer = data->extra_data_buffer;
|
|
callback(VIDC_EVENT_CHANGE, &event_notify);
|
|
}
|
|
|
|
static void hfi_process_sys_error(
|
|
msm_vidc_callback callback, u32 device_id)
|
|
{
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
cmd_done.device_id = device_id;
|
|
callback(SYS_ERROR, &cmd_done);
|
|
}
|
|
static void hfi_process_session_error(
|
|
msm_vidc_callback callback, u32 device_id,
|
|
struct hal_session *session,
|
|
struct hfi_msg_event_notify_packet *pkt)
|
|
{
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = session->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->event_data1);
|
|
dprintk(VIDC_INFO, "Received : SESSION_ERROR with event id : %d\n",
|
|
pkt->event_data1);
|
|
switch (pkt->event_data1) {
|
|
case HFI_ERR_SESSION_INVALID_SCALE_FACTOR:
|
|
case HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE:
|
|
case HFI_ERR_SESSION_UNSUPPORTED_SETTING:
|
|
case HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED:
|
|
cmd_done.status = VIDC_ERR_NONE;
|
|
dprintk(VIDC_INFO, "Non Fatal : HFI_EVENT_SESSION_ERROR\n");
|
|
break;
|
|
default:
|
|
dprintk(VIDC_ERR, "HFI_EVENT_SESSION_ERROR\n");
|
|
callback(SESSION_ERROR, &cmd_done);
|
|
break;
|
|
}
|
|
}
|
|
static void hfi_process_event_notify(msm_vidc_callback callback, u32 device_id,
|
|
struct hal_session *session,
|
|
struct hfi_msg_event_notify_packet *pkt)
|
|
{
|
|
dprintk(VIDC_DBG, "Received: EVENT_NOTIFY\n");
|
|
|
|
if (!callback || !pkt ||
|
|
pkt->size < sizeof(struct hfi_msg_event_notify_packet)) {
|
|
dprintk(VIDC_ERR, "Invalid Params\n");
|
|
return;
|
|
}
|
|
|
|
switch (pkt->event_id) {
|
|
case HFI_EVENT_SYS_ERROR:
|
|
dprintk(VIDC_ERR, "HFI_EVENT_SYS_ERROR: %d, 0x%x\n",
|
|
pkt->event_data1, pkt->event_data2);
|
|
hfi_process_sys_error(callback, device_id);
|
|
break;
|
|
case HFI_EVENT_SESSION_PROPERTY_CHANGED:
|
|
dprintk(VIDC_INFO, "HFI_EVENT_SESSION_PROPERTY_CHANGED[%pK]\n",
|
|
session);
|
|
break;
|
|
}
|
|
|
|
if (!session) {
|
|
dprintk(VIDC_ERR, "%s Got invalid session id\n", __func__);
|
|
return;
|
|
}
|
|
|
|
switch (pkt->event_id) {
|
|
case HFI_EVENT_SESSION_ERROR:
|
|
dprintk(VIDC_INFO, "HFI_EVENT_SESSION_ERROR[%pK]\n", session);
|
|
hfi_process_session_error(callback, device_id, session, pkt);
|
|
break;
|
|
case HFI_EVENT_SESSION_SEQUENCE_CHANGED:
|
|
dprintk(VIDC_INFO, "HFI_EVENT_SESSION_SEQUENCE_CHANGED[%pK]\n",
|
|
session);
|
|
hfi_process_sess_evt_seq_changed(callback, device_id,
|
|
session, pkt);
|
|
break;
|
|
case HFI_EVENT_RELEASE_BUFFER_REFERENCE:
|
|
dprintk(VIDC_INFO, "HFI_EVENT_RELEASE_BUFFER_REFERENCE[%pK]\n",
|
|
session);
|
|
hfi_process_evt_release_buffer_ref(callback, device_id,
|
|
session, pkt);
|
|
break;
|
|
default:
|
|
dprintk(VIDC_WARN,
|
|
"hal_process_event_notify: unknown_event_id[%pK]\n",
|
|
session);
|
|
break;
|
|
}
|
|
}
|
|
static void hfi_process_sys_init_done(
|
|
msm_vidc_callback callback, u32 device_id,
|
|
struct hfi_msg_sys_init_done_packet *pkt)
|
|
{
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
struct vidc_hal_sys_init_done sys_init_done = {0};
|
|
enum vidc_status status = VIDC_ERR_NONE;
|
|
|
|
dprintk(VIDC_DBG, "RECEIVED: SYS_INIT_DONE\n");
|
|
if (sizeof(struct hfi_msg_sys_init_done_packet) > pkt->size) {
|
|
dprintk(VIDC_ERR,
|
|
"hal_process_sys_init_done: bad_pkt_size: %d\n",
|
|
pkt->size);
|
|
return;
|
|
}
|
|
if (pkt->num_properties == 0) {
|
|
dprintk(VIDC_ERR,
|
|
"hal_process_sys_init_done: no_properties\n");
|
|
status = VIDC_ERR_FAIL;
|
|
goto err_no_prop;
|
|
}
|
|
|
|
status = hfi_map_err_status(pkt->error_type);
|
|
if (status) {
|
|
dprintk(VIDC_ERR, "%s: status %#x\n",
|
|
__func__, status);
|
|
goto err_no_prop;
|
|
}
|
|
|
|
sys_init_done.capabilities =
|
|
kzalloc(sizeof(struct msm_vidc_capability) *
|
|
VIDC_MAX_SESSIONS, GFP_TEMPORARY);
|
|
if (!sys_init_done.capabilities) {
|
|
status = VIDC_ERR_FAIL;
|
|
dprintk(VIDC_ERR,
|
|
"%s: failed to allocate capabilities\n", __func__);
|
|
goto err_no_prop;
|
|
}
|
|
|
|
status = hfi_process_sys_init_done_prop_read(
|
|
pkt, &sys_init_done);
|
|
err_no_prop:
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = NULL;
|
|
cmd_done.status = (u32) status;
|
|
cmd_done.size = sizeof(struct vidc_hal_sys_init_done);
|
|
cmd_done.data = (void *) &sys_init_done;
|
|
callback(SYS_INIT_DONE, &cmd_done);
|
|
|
|
kfree(sys_init_done.capabilities);
|
|
sys_init_done.capabilities = NULL;
|
|
}
|
|
|
|
static void hfi_process_sys_rel_resource_done(
|
|
msm_vidc_callback callback, u32 device_id,
|
|
struct hfi_msg_sys_release_resource_done_packet *pkt)
|
|
{
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
enum vidc_status status = VIDC_ERR_NONE;
|
|
u32 pkt_size;
|
|
dprintk(VIDC_DBG, "RECEIVED: SYS_RELEASE_RESOURCE_DONE\n");
|
|
pkt_size = sizeof(struct hfi_msg_sys_release_resource_done_packet);
|
|
if (pkt_size > pkt->size) {
|
|
dprintk(VIDC_ERR,
|
|
"hal_process_sys_rel_resource_done: bad size: %d\n",
|
|
pkt->size);
|
|
return;
|
|
}
|
|
status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = NULL;
|
|
cmd_done.status = (u32) status;
|
|
cmd_done.size = 0;
|
|
cmd_done.data = NULL;
|
|
callback(RELEASE_RESOURCE_DONE, &cmd_done);
|
|
}
|
|
|
|
enum hal_capability get_hal_cap_type(u32 capability_type)
|
|
{
|
|
enum hal_capability hal_cap = 0;
|
|
|
|
switch (capability_type) {
|
|
case HFI_CAPABILITY_FRAME_WIDTH:
|
|
hal_cap = HAL_CAPABILITY_FRAME_WIDTH;
|
|
break;
|
|
case HFI_CAPABILITY_FRAME_HEIGHT:
|
|
hal_cap = HAL_CAPABILITY_FRAME_HEIGHT;
|
|
break;
|
|
case HFI_CAPABILITY_MBS_PER_FRAME:
|
|
hal_cap = HAL_CAPABILITY_MBS_PER_FRAME;
|
|
break;
|
|
case HFI_CAPABILITY_MBS_PER_SECOND:
|
|
hal_cap = HAL_CAPABILITY_MBS_PER_SECOND;
|
|
break;
|
|
case HFI_CAPABILITY_FRAMERATE:
|
|
hal_cap = HAL_CAPABILITY_FRAMERATE;
|
|
break;
|
|
case HFI_CAPABILITY_SCALE_X:
|
|
hal_cap = HAL_CAPABILITY_SCALE_X;
|
|
break;
|
|
case HFI_CAPABILITY_SCALE_Y:
|
|
hal_cap = HAL_CAPABILITY_SCALE_Y;
|
|
break;
|
|
case HFI_CAPABILITY_BITRATE:
|
|
hal_cap = HAL_CAPABILITY_BITRATE;
|
|
break;
|
|
case HFI_CAPABILITY_BFRAME:
|
|
hal_cap = HAL_CAPABILITY_BFRAME;
|
|
break;
|
|
case HFI_CAPABILITY_PEAKBITRATE:
|
|
hal_cap = HAL_CAPABILITY_PEAKBITRATE;
|
|
break;
|
|
case HFI_CAPABILITY_HIER_P_NUM_ENH_LAYERS:
|
|
hal_cap = HAL_CAPABILITY_HIER_P_NUM_ENH_LAYERS;
|
|
break;
|
|
case HFI_CAPABILITY_ENC_LTR_COUNT:
|
|
hal_cap = HAL_CAPABILITY_ENC_LTR_COUNT;
|
|
break;
|
|
case HFI_CAPABILITY_CP_OUTPUT2_THRESH:
|
|
hal_cap = HAL_CAPABILITY_SECURE_OUTPUT2_THRESHOLD;
|
|
break;
|
|
case HFI_CAPABILITY_HIER_B_NUM_ENH_LAYERS:
|
|
hal_cap = HAL_CAPABILITY_HIER_B_NUM_ENH_LAYERS;
|
|
break;
|
|
case HFI_CAPABILITY_LCU_SIZE:
|
|
hal_cap = HAL_CAPABILITY_LCU_SIZE;
|
|
break;
|
|
case HFI_CAPABILITY_HIER_P_HYBRID_NUM_ENH_LAYERS:
|
|
hal_cap = HAL_CAPABILITY_HIER_P_HYBRID_NUM_ENH_LAYERS;
|
|
break;
|
|
}
|
|
|
|
return hal_cap;
|
|
}
|
|
|
|
static inline void copy_cap_prop(
|
|
struct hfi_capability_supported *in,
|
|
struct msm_vidc_capability *capability)
|
|
{
|
|
struct hal_capability_supported *out = NULL;
|
|
|
|
if (!in || !capability) {
|
|
dprintk(VIDC_ERR, "%s Invalid input parameters\n",
|
|
__func__);
|
|
return;
|
|
}
|
|
|
|
switch (in->capability_type) {
|
|
case HFI_CAPABILITY_FRAME_WIDTH:
|
|
out = &capability->width;
|
|
break;
|
|
case HFI_CAPABILITY_FRAME_HEIGHT:
|
|
out = &capability->height;
|
|
break;
|
|
case HFI_CAPABILITY_MBS_PER_FRAME:
|
|
out = &capability->mbs_per_frame;
|
|
break;
|
|
case HFI_CAPABILITY_MBS_PER_SECOND:
|
|
out = &capability->mbs_per_sec;
|
|
break;
|
|
case HFI_CAPABILITY_FRAMERATE:
|
|
out = &capability->frame_rate;
|
|
break;
|
|
case HFI_CAPABILITY_SCALE_X:
|
|
out = &capability->scale_x;
|
|
break;
|
|
case HFI_CAPABILITY_SCALE_Y:
|
|
out = &capability->scale_y;
|
|
break;
|
|
case HFI_CAPABILITY_BITRATE:
|
|
out = &capability->bitrate;
|
|
break;
|
|
case HFI_CAPABILITY_BFRAME:
|
|
out = &capability->bframe;
|
|
break;
|
|
case HFI_CAPABILITY_PEAKBITRATE:
|
|
out = &capability->peakbitrate;
|
|
break;
|
|
case HFI_CAPABILITY_HIER_P_NUM_ENH_LAYERS:
|
|
out = &capability->hier_p;
|
|
break;
|
|
case HFI_CAPABILITY_ENC_LTR_COUNT:
|
|
out = &capability->ltr_count;
|
|
break;
|
|
case HFI_CAPABILITY_CP_OUTPUT2_THRESH:
|
|
out = &capability->secure_output2_threshold;
|
|
break;
|
|
case HFI_CAPABILITY_HIER_B_NUM_ENH_LAYERS:
|
|
out = &capability->hier_b;
|
|
break;
|
|
case HFI_CAPABILITY_LCU_SIZE:
|
|
out = &capability->lcu_size;
|
|
break;
|
|
case HFI_CAPABILITY_HIER_P_HYBRID_NUM_ENH_LAYERS:
|
|
out = &capability->hier_p_hybrid;
|
|
break;
|
|
default:
|
|
dprintk(VIDC_DBG, "%s: unknown capablity %#x\n",
|
|
__func__, in->capability_type);
|
|
break;
|
|
}
|
|
|
|
if (out) {
|
|
out->capability_type = get_hal_cap_type(in->capability_type);
|
|
out->min = in->min;
|
|
out->max = in->max;
|
|
out->step_size = in->step_size;
|
|
capability->capability_set = true;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
int hfi_fill_codec_info(u8 *data_ptr,
|
|
struct vidc_hal_sys_init_done *sys_init_done, u32 rem_size) {
|
|
u32 i;
|
|
u32 codecs = 0, codec_count = 0, size = 0;
|
|
struct msm_vidc_capability *capability;
|
|
u32 prop_id = *((u32 *)data_ptr);
|
|
|
|
if (prop_id == HFI_PROPERTY_PARAM_CODEC_SUPPORTED) {
|
|
struct hfi_codec_supported *prop;
|
|
|
|
if (!VALIDATE_PKT_SIZE(rem_size - sizeof(u32),
|
|
sizeof(struct hfi_codec_supported)))
|
|
return -E2BIG;
|
|
data_ptr = data_ptr + sizeof(u32);
|
|
prop = (struct hfi_codec_supported *) data_ptr;
|
|
sys_init_done->dec_codec_supported =
|
|
prop->decoder_codec_supported;
|
|
sys_init_done->enc_codec_supported =
|
|
prop->encoder_codec_supported;
|
|
size = sizeof(struct hfi_codec_supported) + sizeof(u32);
|
|
rem_size -=
|
|
sizeof(struct hfi_codec_supported) + sizeof(u32);
|
|
} else {
|
|
dprintk(VIDC_WARN,
|
|
"%s: prop_id 0x%x, expected codec_supported property\n",
|
|
__func__, prop_id);
|
|
}
|
|
|
|
codecs = sys_init_done->dec_codec_supported;
|
|
for (i = 0; i < 8 * sizeof(codecs); i++) {
|
|
if ((1 << i) & codecs) {
|
|
capability =
|
|
&sys_init_done->capabilities[codec_count++];
|
|
capability->codec =
|
|
vidc_get_hal_codec((1 << i) & codecs);
|
|
capability->domain =
|
|
vidc_get_hal_domain(HFI_VIDEO_DOMAIN_DECODER);
|
|
if (codec_count == VIDC_MAX_DECODE_SESSIONS) {
|
|
dprintk(VIDC_ERR,
|
|
"Max supported decoder sessions reached");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
codecs = sys_init_done->enc_codec_supported;
|
|
for (i = 0; i < 8 * sizeof(codecs); i++) {
|
|
if ((1 << i) & codecs) {
|
|
capability =
|
|
&sys_init_done->capabilities[codec_count++];
|
|
capability->codec =
|
|
vidc_get_hal_codec((1 << i) & codecs);
|
|
capability->domain =
|
|
vidc_get_hal_domain(HFI_VIDEO_DOMAIN_ENCODER);
|
|
if (codec_count == VIDC_MAX_SESSIONS) {
|
|
dprintk(VIDC_ERR,
|
|
"Max supported sessions reached");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
sys_init_done->codec_count = codec_count;
|
|
if (!VALIDATE_PKT_SIZE(rem_size, sizeof(u32)))
|
|
return -E2BIG;
|
|
return size;
|
|
}
|
|
enum vidc_status hfi_process_session_init_done_prop_read(
|
|
struct hfi_msg_sys_session_init_done_packet *pkt,
|
|
struct vidc_hal_session_init_done *session_init_done)
|
|
{
|
|
enum vidc_status status = VIDC_ERR_NONE;
|
|
struct msm_vidc_capability *capability = NULL;
|
|
u32 rem_bytes, num_properties;
|
|
u8 *data_ptr;
|
|
|
|
rem_bytes = pkt->size - sizeof(struct
|
|
hfi_msg_sys_session_init_done_packet) + sizeof(u32);
|
|
if (rem_bytes == 0) {
|
|
dprintk(VIDC_ERR, "%s: invalid property info\n", __func__);
|
|
return VIDC_ERR_FAIL;
|
|
}
|
|
|
|
status = hfi_map_err_status(pkt->error_type);
|
|
if (status) {
|
|
dprintk(VIDC_ERR, "%s: error status 0x%x\n", __func__, status);
|
|
return status;
|
|
}
|
|
|
|
data_ptr = (u8 *)&pkt->rg_property_data[0];
|
|
num_properties = pkt->num_properties;
|
|
|
|
capability = &session_init_done->capability;
|
|
status = hfi_parse_init_done_properties(
|
|
capability, 1, data_ptr, num_properties, rem_bytes,
|
|
vidc_get_hfi_codec(capability->codec),
|
|
vidc_get_hfi_domain(capability->domain));
|
|
if (status) {
|
|
dprintk(VIDC_ERR, "%s: parse status 0x%x\n", __func__, status);
|
|
return status;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static int copy_caps_to_sessions(struct hfi_capability_supported *cap,
|
|
u32 num_caps, struct msm_vidc_capability *capabilities,
|
|
u32 num_sessions, u32 codecs, u32 domain)
|
|
{
|
|
u32 i = 0, j = 0;
|
|
struct msm_vidc_capability *capability;
|
|
u32 sess_codec;
|
|
u32 sess_domain;
|
|
|
|
/*
|
|
* iterate over num_sessions and copy all the capabilities
|
|
* to matching sessions.
|
|
*/
|
|
for (i = 0; i < num_sessions; i++) {
|
|
sess_codec = 0;
|
|
sess_domain = 0;
|
|
capability = &capabilities[i];
|
|
|
|
if (capability->codec)
|
|
sess_codec =
|
|
vidc_get_hfi_codec(capability->codec);
|
|
if (capability->domain)
|
|
sess_domain =
|
|
vidc_get_hfi_domain(capability->domain);
|
|
|
|
if (!(sess_codec & codecs && sess_domain & domain))
|
|
continue;
|
|
|
|
for (j = 0; j < num_caps; j++)
|
|
copy_cap_prop(&cap[j], capability);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int copy_alloc_mode_to_sessions(
|
|
struct hfi_buffer_alloc_mode_supported *prop,
|
|
struct msm_vidc_capability *capabilities,
|
|
u32 num_sessions, u32 codecs, u32 domain)
|
|
{
|
|
u32 i = 0, j = 0;
|
|
struct msm_vidc_capability *capability;
|
|
u32 sess_codec;
|
|
u32 sess_domain;
|
|
|
|
/*
|
|
* iterate over num_sessions and copy all the entries
|
|
* to matching sessions.
|
|
*/
|
|
for (i = 0; i < num_sessions; i++) {
|
|
sess_codec = 0;
|
|
sess_domain = 0;
|
|
capability = &capabilities[i];
|
|
|
|
if (capability->codec)
|
|
sess_codec =
|
|
vidc_get_hfi_codec(capability->codec);
|
|
if (capability->domain)
|
|
sess_domain =
|
|
vidc_get_hfi_domain(capability->domain);
|
|
|
|
if (!(sess_codec & codecs && sess_domain & domain))
|
|
continue;
|
|
|
|
for (j = 0; j < prop->num_entries; j++) {
|
|
if (prop->buffer_type == HFI_BUFFER_OUTPUT ||
|
|
prop->buffer_type == HFI_BUFFER_OUTPUT2) {
|
|
switch (prop->rg_data[j]) {
|
|
case HFI_BUFFER_MODE_STATIC:
|
|
capability->alloc_mode_out |=
|
|
HAL_BUFFER_MODE_STATIC;
|
|
break;
|
|
case HFI_BUFFER_MODE_RING:
|
|
capability->alloc_mode_out |=
|
|
HAL_BUFFER_MODE_RING;
|
|
break;
|
|
case HFI_BUFFER_MODE_DYNAMIC:
|
|
capability->alloc_mode_out |=
|
|
HAL_BUFFER_MODE_DYNAMIC;
|
|
break;
|
|
}
|
|
} else if (prop->buffer_type == HFI_BUFFER_INPUT) {
|
|
switch (prop->rg_data[j]) {
|
|
case HFI_BUFFER_MODE_STATIC:
|
|
capability->alloc_mode_in |=
|
|
HAL_BUFFER_MODE_STATIC;
|
|
break;
|
|
case HFI_BUFFER_MODE_RING:
|
|
capability->alloc_mode_in |=
|
|
HAL_BUFFER_MODE_RING;
|
|
break;
|
|
case HFI_BUFFER_MODE_DYNAMIC:
|
|
capability->alloc_mode_in |=
|
|
HAL_BUFFER_MODE_DYNAMIC;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static enum vidc_status hfi_parse_init_done_properties(
|
|
struct msm_vidc_capability *capabilities,
|
|
u32 num_sessions, u8 *data_ptr, u32 num_properties,
|
|
u32 rem_bytes, u32 codecs, u32 domain)
|
|
{
|
|
enum vidc_status status = VIDC_ERR_NONE;
|
|
u32 prop_id, next_offset;
|
|
#define VALIDATE_PROPERTY_STRUCTURE_SIZE(pkt_size, property_size) ({\
|
|
if (pkt_size < property_size) { \
|
|
status = VIDC_ERR_BAD_PARAM; \
|
|
break; \
|
|
} \
|
|
})
|
|
|
|
#define VALIDATE_PROPERTY_PAYLOAD_SIZE(pkt_size, payload_size, \
|
|
property_count) ({\
|
|
if (pkt_size/payload_size < property_count) { \
|
|
status = VIDC_ERR_BAD_PARAM; \
|
|
break; \
|
|
} \
|
|
})
|
|
|
|
while (status == VIDC_ERR_NONE && num_properties &&
|
|
rem_bytes >= sizeof(u32)) {
|
|
|
|
prop_id = *((u32 *)data_ptr);
|
|
next_offset = sizeof(u32);
|
|
|
|
switch (prop_id) {
|
|
case HFI_PROPERTY_PARAM_CODEC_MASK_SUPPORTED:
|
|
{
|
|
struct hfi_codec_mask_supported *prop =
|
|
(struct hfi_codec_mask_supported *)
|
|
(data_ptr + next_offset);
|
|
|
|
VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
|
|
next_offset,
|
|
sizeof(*prop));
|
|
|
|
codecs = prop->codecs;
|
|
domain = prop->video_domains;
|
|
next_offset += sizeof(struct hfi_codec_mask_supported);
|
|
num_properties--;
|
|
break;
|
|
}
|
|
case HFI_PROPERTY_PARAM_CAPABILITY_SUPPORTED:
|
|
{
|
|
struct hfi_capability_supported_info *prop =
|
|
(struct hfi_capability_supported_info *)
|
|
(data_ptr + next_offset);
|
|
|
|
VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
|
|
next_offset,
|
|
sizeof(*prop));
|
|
|
|
VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes -
|
|
next_offset - sizeof(u32),
|
|
sizeof(struct hfi_capability_supported),
|
|
prop->num_capabilities);
|
|
next_offset += sizeof(u32) +
|
|
prop->num_capabilities *
|
|
sizeof(struct hfi_capability_supported);
|
|
|
|
copy_caps_to_sessions(&prop->rg_data[0],
|
|
prop->num_capabilities,
|
|
capabilities, num_sessions,
|
|
codecs, domain);
|
|
|
|
num_properties--;
|
|
break;
|
|
}
|
|
case HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED:
|
|
{
|
|
struct hfi_uncompressed_format_supported *prop =
|
|
(struct hfi_uncompressed_format_supported *)
|
|
(data_ptr + next_offset);
|
|
u32 num_format_entries;
|
|
char *fmt_ptr;
|
|
struct hfi_uncompressed_plane_info *plane_info;
|
|
|
|
VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
|
|
next_offset,
|
|
sizeof(*prop));
|
|
|
|
num_format_entries = prop->format_entries;
|
|
next_offset = sizeof(*prop);
|
|
fmt_ptr = (char *)&prop->rg_format_info[0];
|
|
|
|
while (num_format_entries) {
|
|
u32 bytes_to_skip;
|
|
plane_info =
|
|
(struct hfi_uncompressed_plane_info *) fmt_ptr;
|
|
|
|
VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
|
|
next_offset,
|
|
sizeof(*plane_info));
|
|
|
|
bytes_to_skip = sizeof(*plane_info) -
|
|
sizeof(struct
|
|
hfi_uncompressed_plane_constraints) +
|
|
plane_info->num_planes *
|
|
sizeof(struct
|
|
hfi_uncompressed_plane_constraints);
|
|
|
|
VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
|
|
next_offset,
|
|
bytes_to_skip);
|
|
|
|
fmt_ptr += bytes_to_skip;
|
|
next_offset += bytes_to_skip;
|
|
num_format_entries--;
|
|
}
|
|
num_properties--;
|
|
break;
|
|
}
|
|
case HFI_PROPERTY_PARAM_PROPERTIES_SUPPORTED:
|
|
{
|
|
struct hfi_properties_supported *prop =
|
|
(struct hfi_properties_supported *)
|
|
(data_ptr + next_offset);
|
|
|
|
VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
|
|
next_offset,
|
|
sizeof(*prop));
|
|
VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes -
|
|
next_offset - sizeof(*prop) +
|
|
sizeof(u32), sizeof(u32),
|
|
prop->num_properties);
|
|
|
|
next_offset += sizeof(*prop) - sizeof(u32)
|
|
+ prop->num_properties * sizeof(u32);
|
|
num_properties--;
|
|
break;
|
|
}
|
|
case HFI_PROPERTY_PARAM_PROFILE_LEVEL_SUPPORTED:
|
|
{
|
|
struct msm_vidc_capability capability;
|
|
char *ptr = NULL;
|
|
u32 count = 0;
|
|
u32 prof_count = 0;
|
|
struct hfi_profile_level *prof_level;
|
|
struct hfi_profile_level_supported *prop =
|
|
(struct hfi_profile_level_supported *)
|
|
(data_ptr + next_offset);
|
|
VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
|
|
next_offset,
|
|
sizeof(*prop));
|
|
VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes -
|
|
next_offset -
|
|
sizeof(u32),
|
|
sizeof(struct hfi_profile_level),
|
|
prop->profile_count);
|
|
ptr = (char *) &prop->rg_profile_level[0];
|
|
prof_count = prop->profile_count;
|
|
next_offset += sizeof(u32);
|
|
|
|
if (prof_count > MAX_PROFILE_COUNT) {
|
|
prof_count = MAX_PROFILE_COUNT;
|
|
dprintk(VIDC_WARN,
|
|
"prop count exceeds max profile count\n");
|
|
break;
|
|
}
|
|
while (prof_count) {
|
|
prof_level = (struct hfi_profile_level *)ptr;
|
|
capability.
|
|
profile_level.profile_level[count].profile
|
|
= prof_level->profile;
|
|
capability.
|
|
profile_level.profile_level[count].level
|
|
= prof_level->level;
|
|
prof_count--;
|
|
count++;
|
|
ptr += sizeof(struct hfi_profile_level);
|
|
next_offset += sizeof(struct hfi_profile_level);
|
|
}
|
|
num_properties--;
|
|
break;
|
|
}
|
|
case HFI_PROPERTY_PARAM_INTERLACE_FORMAT_SUPPORTED:
|
|
{
|
|
VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
|
|
next_offset,
|
|
sizeof(struct hfi_interlace_format_supported));
|
|
next_offset +=
|
|
sizeof(struct hfi_interlace_format_supported);
|
|
num_properties--;
|
|
break;
|
|
}
|
|
case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SUPPORTED:
|
|
{
|
|
VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
|
|
next_offset,
|
|
sizeof(struct hfi_nal_stream_format_supported));
|
|
|
|
next_offset +=
|
|
sizeof(struct hfi_nal_stream_format_supported);
|
|
num_properties--;
|
|
break;
|
|
}
|
|
case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT:
|
|
{
|
|
VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
|
|
next_offset,
|
|
sizeof(u32));
|
|
next_offset += sizeof(u32);
|
|
num_properties--;
|
|
break;
|
|
}
|
|
case HFI_PROPERTY_PARAM_MAX_SEQUENCE_HEADER_SIZE:
|
|
{
|
|
VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
|
|
next_offset,
|
|
sizeof(u32));
|
|
next_offset += sizeof(u32);
|
|
num_properties--;
|
|
break;
|
|
}
|
|
case HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH:
|
|
{
|
|
VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
|
|
next_offset,
|
|
sizeof(struct hfi_intra_refresh));
|
|
next_offset +=
|
|
sizeof(struct hfi_intra_refresh);
|
|
num_properties--;
|
|
break;
|
|
}
|
|
case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE_SUPPORTED:
|
|
{
|
|
struct hfi_buffer_alloc_mode_supported *prop =
|
|
(struct hfi_buffer_alloc_mode_supported *)
|
|
(data_ptr + next_offset);
|
|
VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes -
|
|
next_offset,
|
|
sizeof(*prop));
|
|
VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes -
|
|
next_offset - sizeof(*prop) +
|
|
sizeof(u32), sizeof(u32),
|
|
prop->num_entries);
|
|
|
|
if (prop->num_entries >= 32) {
|
|
dprintk(VIDC_ERR,
|
|
"%s - num_entries: %d from f/w seems suspect\n",
|
|
__func__, prop->num_entries);
|
|
break;
|
|
}
|
|
next_offset +=
|
|
sizeof(struct hfi_buffer_alloc_mode_supported) -
|
|
sizeof(u32) + prop->num_entries * sizeof(u32);
|
|
|
|
copy_alloc_mode_to_sessions(prop,
|
|
capabilities, num_sessions,
|
|
codecs, domain);
|
|
|
|
num_properties--;
|
|
break;
|
|
}
|
|
default:
|
|
dprintk(VIDC_DBG,
|
|
"%s: default case - data_ptr %pK, prop_id 0x%x\n",
|
|
__func__, data_ptr, prop_id);
|
|
break;
|
|
}
|
|
|
|
if (rem_bytes > next_offset) {
|
|
rem_bytes -= next_offset;
|
|
data_ptr += next_offset;
|
|
} else {
|
|
rem_bytes = 0;
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
enum vidc_status hfi_process_sys_init_done_prop_read(
|
|
struct hfi_msg_sys_init_done_packet *pkt,
|
|
struct vidc_hal_sys_init_done *sys_init_done)
|
|
{
|
|
enum vidc_status status = VIDC_ERR_NONE;
|
|
int bytes_read;
|
|
u32 rem_bytes, num_properties;
|
|
u8 *data_ptr;
|
|
u32 codecs = 0, domain = 0;
|
|
|
|
if (pkt->size < sizeof(struct hfi_msg_sys_init_done_packet)) {
|
|
dprintk(VIDC_ERR, "%s: bad_packet_size: %d\n",
|
|
__func__, pkt->size);
|
|
return VIDC_ERR_FAIL;
|
|
}
|
|
|
|
rem_bytes = pkt->size - sizeof(struct
|
|
hfi_msg_sys_init_done_packet) + sizeof(u32);
|
|
|
|
if (rem_bytes == 0) {
|
|
dprintk(VIDC_ERR,
|
|
"hfi_msg_sys_init_done: missing_prop_info\n");
|
|
return VIDC_ERR_FAIL;
|
|
}
|
|
|
|
status = hfi_map_err_status(pkt->error_type);
|
|
if (status) {
|
|
dprintk(VIDC_ERR, "%s: status %#x\n", __func__, status);
|
|
return status;
|
|
}
|
|
|
|
data_ptr = (u8 *) &pkt->rg_property_data[0];
|
|
num_properties = pkt->num_properties;
|
|
dprintk(VIDC_DBG,
|
|
"%s: data_start %pK, num_properties %#x\n",
|
|
__func__, data_ptr, num_properties);
|
|
|
|
bytes_read = hfi_fill_codec_info(data_ptr, sys_init_done, rem_bytes);
|
|
if (bytes_read < 0)
|
|
return VIDC_ERR_FAIL;
|
|
data_ptr += bytes_read;
|
|
rem_bytes -= bytes_read;
|
|
num_properties--;
|
|
|
|
status = hfi_parse_init_done_properties(
|
|
sys_init_done->capabilities,
|
|
VIDC_MAX_SESSIONS, data_ptr, num_properties,
|
|
rem_bytes, codecs, domain);
|
|
if (status) {
|
|
dprintk(VIDC_ERR, "%s: parse status %#x\n",
|
|
__func__, status);
|
|
return status;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static void hfi_process_sess_get_prop_profile_level(
|
|
struct hfi_msg_session_property_info_packet *prop,
|
|
struct hfi_profile_level *profile_level)
|
|
{
|
|
struct hfi_profile_level *hfi_profile_level;
|
|
u32 req_bytes;
|
|
dprintk(VIDC_DBG, "Entered %s\n", __func__);
|
|
if (!prop) {
|
|
dprintk(VIDC_ERR,
|
|
"hal_process_sess_get_profile_level: bad_prop: %pK\n",
|
|
prop);
|
|
return;
|
|
}
|
|
req_bytes = prop->size - sizeof(
|
|
struct hfi_msg_session_property_info_packet);
|
|
|
|
if (!req_bytes || (req_bytes % sizeof(struct hfi_profile_level))) {
|
|
dprintk(VIDC_ERR,
|
|
"hal_process_sess_get_profile_level: bad_pkt: %d\n",
|
|
req_bytes);
|
|
return;
|
|
}
|
|
hfi_profile_level = (struct hfi_profile_level *)
|
|
&prop->rg_property_data[1];
|
|
profile_level->profile = hfi_profile_level->profile;
|
|
profile_level->level = hfi_profile_level->level;
|
|
dprintk(VIDC_DBG, "%s profile: %d level: %d\n",
|
|
__func__, profile_level->profile,
|
|
profile_level->level);
|
|
}
|
|
|
|
static void hfi_process_sess_get_prop_buf_req(
|
|
struct hfi_msg_session_property_info_packet *prop,
|
|
struct buffer_requirements *buffreq)
|
|
{
|
|
struct hfi_buffer_requirements *hfi_buf_req;
|
|
u32 req_bytes;
|
|
|
|
if (!prop) {
|
|
dprintk(VIDC_ERR,
|
|
"hal_process_sess_get_prop_buf_req: bad_prop: %pK\n",
|
|
prop);
|
|
return;
|
|
}
|
|
req_bytes = prop->size - sizeof(
|
|
struct hfi_msg_session_property_info_packet);
|
|
|
|
if (!req_bytes || (req_bytes % sizeof(
|
|
struct hfi_buffer_requirements)) ||
|
|
(!prop->rg_property_data[1])) {
|
|
dprintk(VIDC_ERR,
|
|
"hal_process_sess_get_prop_buf_req: bad_pkt: %d\n",
|
|
req_bytes);
|
|
return;
|
|
}
|
|
|
|
hfi_buf_req = (struct hfi_buffer_requirements *)
|
|
&prop->rg_property_data[1];
|
|
|
|
if (!hfi_buf_req) {
|
|
dprintk(VIDC_ERR, "%s - invalid buffer req pointer\n",
|
|
__func__);
|
|
return;
|
|
}
|
|
|
|
while (req_bytes) {
|
|
if ((hfi_buf_req->buffer_size) &&
|
|
((hfi_buf_req->buffer_count_min > hfi_buf_req->
|
|
buffer_count_actual)))
|
|
dprintk(VIDC_WARN,
|
|
"hal_process_sess_get_prop_buf_req:"
|
|
"bad_buf_req\n");
|
|
|
|
dprintk(VIDC_DBG, "got buffer requirements for: %d\n",
|
|
hfi_buf_req->buffer_type);
|
|
switch (hfi_buf_req->buffer_type) {
|
|
case HFI_BUFFER_INPUT:
|
|
memcpy(&buffreq->buffer[0], hfi_buf_req,
|
|
sizeof(struct hfi_buffer_requirements));
|
|
buffreq->buffer[0].buffer_type = HAL_BUFFER_INPUT;
|
|
break;
|
|
case HFI_BUFFER_OUTPUT:
|
|
memcpy(&buffreq->buffer[1], hfi_buf_req,
|
|
sizeof(struct hfi_buffer_requirements));
|
|
buffreq->buffer[1].buffer_type = HAL_BUFFER_OUTPUT;
|
|
break;
|
|
case HFI_BUFFER_OUTPUT2:
|
|
memcpy(&buffreq->buffer[2], hfi_buf_req,
|
|
sizeof(struct hfi_buffer_requirements));
|
|
buffreq->buffer[2].buffer_type = HAL_BUFFER_OUTPUT2;
|
|
break;
|
|
case HFI_BUFFER_EXTRADATA_INPUT:
|
|
memcpy(&buffreq->buffer[3], hfi_buf_req,
|
|
sizeof(struct hfi_buffer_requirements));
|
|
buffreq->buffer[3].buffer_type =
|
|
HAL_BUFFER_EXTRADATA_INPUT;
|
|
break;
|
|
case HFI_BUFFER_EXTRADATA_OUTPUT:
|
|
memcpy(&buffreq->buffer[4], hfi_buf_req,
|
|
sizeof(struct hfi_buffer_requirements));
|
|
buffreq->buffer[4].buffer_type =
|
|
HAL_BUFFER_EXTRADATA_OUTPUT;
|
|
break;
|
|
case HFI_BUFFER_EXTRADATA_OUTPUT2:
|
|
memcpy(&buffreq->buffer[5], hfi_buf_req,
|
|
sizeof(struct hfi_buffer_requirements));
|
|
buffreq->buffer[5].buffer_type =
|
|
HAL_BUFFER_EXTRADATA_OUTPUT2;
|
|
break;
|
|
case HFI_BUFFER_INTERNAL_SCRATCH:
|
|
memcpy(&buffreq->buffer[6], hfi_buf_req,
|
|
sizeof(struct hfi_buffer_requirements));
|
|
buffreq->buffer[6].buffer_type =
|
|
HAL_BUFFER_INTERNAL_SCRATCH;
|
|
break;
|
|
case HFI_BUFFER_INTERNAL_SCRATCH_1:
|
|
memcpy(&buffreq->buffer[7], hfi_buf_req,
|
|
sizeof(struct hfi_buffer_requirements));
|
|
buffreq->buffer[7].buffer_type =
|
|
HAL_BUFFER_INTERNAL_SCRATCH_1;
|
|
break;
|
|
case HFI_BUFFER_INTERNAL_SCRATCH_2:
|
|
memcpy(&buffreq->buffer[8], hfi_buf_req,
|
|
sizeof(struct hfi_buffer_requirements));
|
|
buffreq->buffer[8].buffer_type =
|
|
HAL_BUFFER_INTERNAL_SCRATCH_2;
|
|
break;
|
|
case HFI_BUFFER_INTERNAL_PERSIST:
|
|
memcpy(&buffreq->buffer[9], hfi_buf_req,
|
|
sizeof(struct hfi_buffer_requirements));
|
|
buffreq->buffer[9].buffer_type =
|
|
HAL_BUFFER_INTERNAL_PERSIST;
|
|
break;
|
|
case HFI_BUFFER_INTERNAL_PERSIST_1:
|
|
memcpy(&buffreq->buffer[10], hfi_buf_req,
|
|
sizeof(struct hfi_buffer_requirements));
|
|
buffreq->buffer[10].buffer_type =
|
|
HAL_BUFFER_INTERNAL_PERSIST_1;
|
|
break;
|
|
default:
|
|
dprintk(VIDC_ERR,
|
|
"hal_process_sess_get_prop_buf_req: bad_buffer_type: %d\n",
|
|
hfi_buf_req->buffer_type);
|
|
break;
|
|
}
|
|
req_bytes -= sizeof(struct hfi_buffer_requirements);
|
|
hfi_buf_req++;
|
|
}
|
|
}
|
|
|
|
static void hfi_process_session_prop_info(msm_vidc_callback callback,
|
|
u32 device_id, struct hal_session *session,
|
|
struct hfi_msg_session_property_info_packet *pkt)
|
|
{
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
struct hfi_profile_level profile_level = {0};
|
|
struct buffer_requirements buff_req;
|
|
|
|
memset(&buff_req, 0, sizeof(struct buffer_requirements));
|
|
dprintk(VIDC_DBG, "Received SESSION_PROPERTY_INFO[%pK]\n", session);
|
|
|
|
if (pkt->size < sizeof(struct hfi_msg_session_property_info_packet)) {
|
|
dprintk(VIDC_ERR,
|
|
"hal_process_session_prop_info: bad_pkt_size\n");
|
|
return;
|
|
}
|
|
|
|
if (pkt->num_properties == 0) {
|
|
dprintk(VIDC_ERR,
|
|
"hal_process_session_prop_info: no_properties\n");
|
|
return;
|
|
}
|
|
|
|
switch (pkt->rg_property_data[0]) {
|
|
case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
|
|
hfi_process_sess_get_prop_buf_req(pkt, &buff_req);
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = session->session_id;
|
|
cmd_done.status = VIDC_ERR_NONE;
|
|
cmd_done.data = &buff_req;
|
|
cmd_done.size = sizeof(struct buffer_requirements);
|
|
callback(SESSION_PROPERTY_INFO, &cmd_done);
|
|
break;
|
|
case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
|
|
hfi_process_sess_get_prop_profile_level(pkt, &profile_level);
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = session->session_id;
|
|
cmd_done.status = VIDC_ERR_NONE;
|
|
cmd_done.data = &profile_level;
|
|
cmd_done.size = sizeof(struct hal_profile_level);
|
|
callback(SESSION_PROPERTY_INFO, &cmd_done);
|
|
break;
|
|
default:
|
|
dprintk(VIDC_DBG,
|
|
"hal_process_session_prop_info: unknown_prop_id: %x\n",
|
|
pkt->rg_property_data[0]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void hfi_process_session_init_done(
|
|
msm_vidc_callback callback, u32 device_id,
|
|
struct hal_session *session,
|
|
struct hfi_msg_sys_session_init_done_packet *pkt)
|
|
{
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
struct vidc_hal_session_init_done session_init_done;
|
|
|
|
if (!session) {
|
|
dprintk(VIDC_ERR, "%s - invalid session\n", __func__);
|
|
return;
|
|
}
|
|
|
|
memset(&session_init_done, 0, sizeof(struct
|
|
vidc_hal_session_init_done));
|
|
dprintk(VIDC_DBG, "RECEIVED: SESSION_INIT_DONE[%pK]\n", session);
|
|
|
|
if (sizeof(struct hfi_msg_sys_session_init_done_packet)
|
|
> pkt->size) {
|
|
dprintk(VIDC_ERR,
|
|
"hal_process_session_init_done: bad_pkt_size\n");
|
|
return;
|
|
}
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = session->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.data = &session_init_done;
|
|
if (!cmd_done.status) {
|
|
session_init_done.capability.codec = session->codec;
|
|
session_init_done.capability.domain = session->domain;
|
|
cmd_done.status = hfi_process_session_init_done_prop_read(
|
|
pkt, &session_init_done);
|
|
} else {
|
|
dprintk(VIDC_WARN,
|
|
"Sess init failed: 0x%pK, 0x%pK\n",
|
|
session->session_id, session);
|
|
}
|
|
cmd_done.size = sizeof(struct vidc_hal_session_init_done);
|
|
callback(SESSION_INIT_DONE, &cmd_done);
|
|
}
|
|
|
|
static void hfi_process_session_load_res_done(msm_vidc_callback callback,
|
|
u32 device_id, struct hal_session *session,
|
|
struct hfi_msg_session_load_resources_done_packet *pkt)
|
|
{
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
dprintk(VIDC_DBG, "RECEIVED: SESSION_LOAD_RESOURCES_DONE[%pK]\n",
|
|
session);
|
|
|
|
if (sizeof(struct hfi_msg_session_load_resources_done_packet) !=
|
|
pkt->size) {
|
|
dprintk(VIDC_ERR,
|
|
"hal_process_session_load_res_done: bad packet size: %d\n",
|
|
pkt->size);
|
|
return;
|
|
}
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = session->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.data = NULL;
|
|
cmd_done.size = 0;
|
|
callback(SESSION_LOAD_RESOURCE_DONE, &cmd_done);
|
|
}
|
|
|
|
static void hfi_process_session_flush_done(msm_vidc_callback callback,
|
|
u32 device_id, struct hal_session *session,
|
|
struct hfi_msg_session_flush_done_packet *pkt)
|
|
{
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
struct vidc_hal_session_flush_done session_flush_done;
|
|
|
|
dprintk(VIDC_DBG, "RECEIVED: SESSION_FLUSH_DONE[%pK]\n", session);
|
|
|
|
if (sizeof(struct hfi_msg_session_flush_done_packet) != pkt->size) {
|
|
dprintk(VIDC_ERR,
|
|
"hal_process_session_flush_done: bad packet size: %d\n",
|
|
pkt->size);
|
|
return;
|
|
}
|
|
|
|
cmd_done.session_id = session->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.size = sizeof(session_flush_done);
|
|
|
|
switch (pkt->flush_type) {
|
|
case HFI_FLUSH_OUTPUT:
|
|
session_flush_done.flush_type = HAL_FLUSH_OUTPUT;
|
|
break;
|
|
case HFI_FLUSH_INPUT:
|
|
session_flush_done.flush_type = HAL_FLUSH_INPUT;
|
|
break;
|
|
case HFI_FLUSH_ALL:
|
|
session_flush_done.flush_type = HAL_FLUSH_ALL;
|
|
break;
|
|
default:
|
|
dprintk(VIDC_ERR,
|
|
"%s: invalid flush type!", __func__);
|
|
return;
|
|
}
|
|
cmd_done.data = &session_flush_done;
|
|
callback(SESSION_FLUSH_DONE, &cmd_done);
|
|
}
|
|
|
|
static void hfi_process_session_etb_done(msm_vidc_callback callback,
|
|
u32 device_id, struct hal_session *session,
|
|
struct hfi_msg_session_empty_buffer_done_packet *pkt)
|
|
{
|
|
struct msm_vidc_cb_data_done data_done = {0};
|
|
|
|
dprintk(VIDC_DBG, "RECEIVED: SESSION_ETB_DONE[%pK]\n", session);
|
|
|
|
if (!pkt || pkt->size <
|
|
sizeof(struct hfi_msg_session_empty_buffer_done_packet)) {
|
|
dprintk(VIDC_ERR,
|
|
"hal_process_session_etb_done: bad_pkt_size\n");
|
|
return;
|
|
}
|
|
|
|
data_done.device_id = device_id;
|
|
data_done.session_id = session->session_id;
|
|
data_done.status = hfi_map_err_status(pkt->error_type);
|
|
data_done.size = sizeof(struct msm_vidc_cb_data_done);
|
|
data_done.clnt_data = pkt->input_tag;
|
|
data_done.input_done.offset = pkt->offset;
|
|
data_done.input_done.filled_len = pkt->filled_len;
|
|
data_done.input_done.packet_buffer =
|
|
(ion_phys_addr_t)pkt->packet_buffer;
|
|
data_done.input_done.extra_data_buffer =
|
|
(ion_phys_addr_t)pkt->extra_data_buffer;
|
|
data_done.input_done.status =
|
|
hfi_map_err_status(pkt->error_type);
|
|
|
|
trace_msm_v4l2_vidc_buffer_event_end("ETB",
|
|
(u32)pkt->packet_buffer, -1, -1,
|
|
pkt->filled_len, pkt->offset);
|
|
callback(SESSION_ETB_DONE, &data_done);
|
|
}
|
|
|
|
static void hfi_process_session_ftb_done(msm_vidc_callback callback,
|
|
u32 device_id, struct hal_session *session,
|
|
void *msg_hdr)
|
|
{
|
|
struct msm_vidc_cb_data_done data_done = {0};
|
|
u32 is_decoder = session->is_decoder;
|
|
|
|
if (!msg_hdr) {
|
|
dprintk(VIDC_ERR, "Invalid Params\n");
|
|
return;
|
|
}
|
|
|
|
dprintk(VIDC_DBG, "RECEIVED: SESSION_FTB_DONE[%pK]\n", session);
|
|
|
|
if (is_decoder == 0) {
|
|
struct hfi_msg_session_fill_buffer_done_compressed_packet *pkt =
|
|
(struct hfi_msg_session_fill_buffer_done_compressed_packet *)
|
|
msg_hdr;
|
|
if (sizeof(struct
|
|
hfi_msg_session_fill_buffer_done_compressed_packet)
|
|
> pkt->size) {
|
|
dprintk(VIDC_ERR,
|
|
"hal_process_session_ftb_done: bad_pkt_size\n");
|
|
return;
|
|
} else if (pkt->error_type != HFI_ERR_NONE) {
|
|
dprintk(VIDC_ERR,
|
|
"got buffer back with error %x\n",
|
|
pkt->error_type);
|
|
/* Proceed with the FBD */
|
|
}
|
|
|
|
data_done.device_id = device_id;
|
|
data_done.session_id = session->session_id;
|
|
data_done.status = hfi_map_err_status(pkt->error_type);
|
|
data_done.size = sizeof(struct msm_vidc_cb_data_done);
|
|
data_done.clnt_data = 0;
|
|
|
|
data_done.output_done.timestamp_hi = pkt->time_stamp_hi;
|
|
data_done.output_done.timestamp_lo = pkt->time_stamp_lo;
|
|
data_done.output_done.flags1 = pkt->flags;
|
|
data_done.output_done.mark_target = pkt->mark_target;
|
|
data_done.output_done.mark_data = pkt->mark_data;
|
|
data_done.output_done.stats = pkt->stats;
|
|
data_done.output_done.offset1 = pkt->offset;
|
|
data_done.output_done.alloc_len1 = pkt->alloc_len;
|
|
data_done.output_done.filled_len1 = pkt->filled_len;
|
|
data_done.output_done.picture_type = pkt->picture_type;
|
|
data_done.output_done.packet_buffer1 =
|
|
(ion_phys_addr_t)pkt->packet_buffer;
|
|
data_done.output_done.extra_data_buffer =
|
|
(ion_phys_addr_t)pkt->extra_data_buffer;
|
|
data_done.output_done.buffer_type = HAL_BUFFER_OUTPUT;
|
|
} else if (is_decoder == 1) {
|
|
struct hfi_msg_session_fbd_uncompressed_plane0_packet *pkt =
|
|
(struct hfi_msg_session_fbd_uncompressed_plane0_packet *)
|
|
msg_hdr;
|
|
if (sizeof(
|
|
struct hfi_msg_session_fbd_uncompressed_plane0_packet) >
|
|
pkt->size) {
|
|
dprintk(VIDC_ERR,
|
|
"hal_process_session_ftb_done: bad_pkt_size\n");
|
|
return;
|
|
}
|
|
|
|
data_done.device_id = device_id;
|
|
data_done.session_id = session->session_id;
|
|
data_done.status = hfi_map_err_status(pkt->error_type);
|
|
data_done.size = sizeof(struct msm_vidc_cb_data_done);
|
|
data_done.clnt_data = 0;
|
|
|
|
data_done.output_done.stream_id = pkt->stream_id;
|
|
data_done.output_done.view_id = pkt->view_id;
|
|
data_done.output_done.timestamp_hi = pkt->time_stamp_hi;
|
|
data_done.output_done.timestamp_lo = pkt->time_stamp_lo;
|
|
data_done.output_done.flags1 = pkt->flags;
|
|
data_done.output_done.mark_target = pkt->mark_target;
|
|
data_done.output_done.mark_data = pkt->mark_data;
|
|
data_done.output_done.stats = pkt->stats;
|
|
data_done.output_done.alloc_len1 = pkt->alloc_len;
|
|
data_done.output_done.filled_len1 = pkt->filled_len;
|
|
data_done.output_done.offset1 = pkt->offset;
|
|
data_done.output_done.frame_width = pkt->frame_width;
|
|
data_done.output_done.frame_height = pkt->frame_height;
|
|
data_done.output_done.start_x_coord = pkt->start_x_coord;
|
|
data_done.output_done.start_y_coord = pkt->start_y_coord;
|
|
data_done.output_done.input_tag1 = pkt->input_tag;
|
|
data_done.output_done.picture_type = pkt->picture_type;
|
|
data_done.output_done.packet_buffer1 = pkt->packet_buffer;
|
|
data_done.output_done.extra_data_buffer =
|
|
pkt->extra_data_buffer;
|
|
|
|
if (pkt->stream_id == 0)
|
|
data_done.output_done.buffer_type = HAL_BUFFER_OUTPUT;
|
|
else if (pkt->stream_id == 1)
|
|
data_done.output_done.buffer_type = HAL_BUFFER_OUTPUT2;
|
|
}
|
|
trace_msm_v4l2_vidc_buffer_event_end("FTB",
|
|
(u32)data_done.output_done.packet_buffer1,
|
|
(((u64)data_done.output_done.timestamp_hi) << 32)
|
|
+ ((u64)data_done.output_done.timestamp_lo),
|
|
data_done.output_done.alloc_len1,
|
|
data_done.output_done.filled_len1,
|
|
data_done.output_done.offset1);
|
|
callback(SESSION_FTB_DONE, &data_done);
|
|
}
|
|
|
|
static void hfi_process_session_start_done(msm_vidc_callback callback,
|
|
u32 device_id, struct hal_session *session,
|
|
struct hfi_msg_session_start_done_packet *pkt)
|
|
{
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
|
|
dprintk(VIDC_DBG, "RECEIVED: SESSION_START_DONE[%pK]\n", session);
|
|
|
|
if (!pkt || pkt->size !=
|
|
sizeof(struct hfi_msg_session_start_done_packet)) {
|
|
dprintk(VIDC_ERR, "%s: bad packet/packet size\n",
|
|
__func__);
|
|
return;
|
|
}
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = session->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.data = NULL;
|
|
cmd_done.size = 0;
|
|
callback(SESSION_START_DONE, &cmd_done);
|
|
}
|
|
|
|
static void hfi_process_session_stop_done(msm_vidc_callback callback,
|
|
u32 device_id, struct hal_session *session,
|
|
struct hfi_msg_session_stop_done_packet *pkt)
|
|
{
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
|
|
dprintk(VIDC_DBG, "RECEIVED: SESSION_STOP_DONE[%pK]\n", session);
|
|
|
|
if (!pkt || pkt->size !=
|
|
sizeof(struct hfi_msg_session_stop_done_packet)) {
|
|
dprintk(VIDC_ERR, "%s: bad packet/packet size\n",
|
|
__func__);
|
|
return;
|
|
}
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = session->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.data = NULL;
|
|
cmd_done.size = 0;
|
|
callback(SESSION_STOP_DONE, &cmd_done);
|
|
}
|
|
|
|
static void hfi_process_session_rel_res_done(msm_vidc_callback callback,
|
|
u32 device_id, struct hal_session *session,
|
|
struct hfi_msg_session_release_resources_done_packet *pkt)
|
|
{
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
|
|
dprintk(VIDC_DBG, "RECEIVED: SESSION_RELEASE_RESOURCES_DONE[%pK]\n",
|
|
session);
|
|
|
|
if (!pkt || pkt->size !=
|
|
sizeof(struct hfi_msg_session_release_resources_done_packet)) {
|
|
dprintk(VIDC_ERR, "%s: bad packet/packet size\n",
|
|
__func__);
|
|
return;
|
|
}
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = session->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.data = NULL;
|
|
cmd_done.size = 0;
|
|
callback(SESSION_RELEASE_RESOURCE_DONE, &cmd_done);
|
|
}
|
|
|
|
static void hfi_process_session_rel_buf_done(msm_vidc_callback callback,
|
|
u32 device_id, struct hal_session *session,
|
|
struct hfi_msg_session_release_buffers_done_packet *pkt)
|
|
{
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
|
|
if (!pkt || pkt->size <
|
|
sizeof(struct
|
|
hfi_msg_session_release_buffers_done_packet)) {
|
|
dprintk(VIDC_ERR, "bad packet/packet size %d\n",
|
|
pkt ? pkt->size : 0);
|
|
return;
|
|
}
|
|
dprintk(VIDC_DBG, "RECEIVED:SESSION_RELEASE_BUFFER_DONE[%pK]\n",
|
|
session);
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.size = sizeof(struct msm_vidc_cb_cmd_done);
|
|
cmd_done.session_id = session->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
if (pkt->rg_buffer_info) {
|
|
cmd_done.data = (void *) &pkt->rg_buffer_info;
|
|
cmd_done.size = sizeof(struct hfi_buffer_info);
|
|
} else {
|
|
dprintk(VIDC_ERR, "invalid payload in rel_buff_done\n");
|
|
}
|
|
callback(SESSION_RELEASE_BUFFER_DONE, &cmd_done);
|
|
}
|
|
|
|
static void hfi_process_session_end_done(msm_vidc_callback callback,
|
|
u32 device_id, struct hal_session *session,
|
|
struct hfi_msg_sys_session_end_done_packet *pkt)
|
|
{
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
|
|
dprintk(VIDC_DBG, "RECEIVED: SESSION_END_DONE[%pK]\n", session);
|
|
|
|
if (!pkt || pkt->size !=
|
|
sizeof(struct hfi_msg_sys_session_end_done_packet)) {
|
|
dprintk(VIDC_ERR, "%s: bad packet/packet size\n", __func__);
|
|
return;
|
|
}
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = session->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.data = NULL;
|
|
cmd_done.size = 0;
|
|
callback(SESSION_END_DONE, &cmd_done);
|
|
}
|
|
|
|
static void hfi_process_session_abort_done(msm_vidc_callback callback,
|
|
u32 device_id, struct hal_session *session,
|
|
struct hfi_msg_sys_session_abort_done_packet *pkt)
|
|
{
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
|
|
dprintk(VIDC_DBG, "RECEIVED: SESSION_ABORT_DONE[%pK]\n", session);
|
|
|
|
if (!pkt || pkt->size !=
|
|
sizeof(struct hfi_msg_sys_session_abort_done_packet)) {
|
|
dprintk(VIDC_ERR, "%s: bad packet/packet size: %d\n",
|
|
__func__, pkt ? pkt->size : 0);
|
|
return;
|
|
}
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = session->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.data = NULL;
|
|
cmd_done.size = 0;
|
|
|
|
callback(SESSION_ABORT_DONE, &cmd_done);
|
|
}
|
|
|
|
static void hfi_process_sys_idle(msm_vidc_callback callback,
|
|
u32 device_id, struct hfi_msg_sys_idle_packet *pkt)
|
|
{
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
cmd_done.device_id = device_id;
|
|
callback(SYS_IDLE, &cmd_done);
|
|
}
|
|
|
|
static void hfi_process_session_get_seq_hdr_done(msm_vidc_callback callback,
|
|
u32 device_id, struct hal_session *session,
|
|
struct hfi_msg_session_get_sequence_header_done_packet *pkt)
|
|
{
|
|
struct msm_vidc_cb_data_done data_done = {0};
|
|
if (!pkt || pkt->size !=
|
|
sizeof(struct
|
|
hfi_msg_session_get_sequence_header_done_packet)) {
|
|
dprintk(VIDC_ERR, "%s: bad packet/packet size\n",
|
|
__func__);
|
|
return;
|
|
}
|
|
dprintk(VIDC_DBG, "RECEIVED:SESSION_GET_SEQ_HDR_DONE[%pK]\n", session);
|
|
|
|
data_done.device_id = device_id;
|
|
data_done.size = sizeof(struct msm_vidc_cb_data_done);
|
|
data_done.session_id = session->session_id;
|
|
data_done.status = hfi_map_err_status(pkt->error_type);
|
|
data_done.output_done.packet_buffer1 =
|
|
(ion_phys_addr_t)pkt->sequence_header;
|
|
data_done.output_done.filled_len1 = pkt->header_len;
|
|
dprintk(VIDC_INFO, "seq_hdr: 0x%x, Length: %d\n",
|
|
pkt->sequence_header, pkt->header_len);
|
|
callback(SESSION_GET_SEQ_HDR_DONE, &data_done);
|
|
}
|
|
|
|
static void hfi_process_sys_get_prop_image_version(
|
|
struct hfi_msg_sys_property_info_packet *pkt)
|
|
{
|
|
int i = 0;
|
|
u32 smem_block_size = 0;
|
|
u8 *smem_table_ptr;
|
|
char version[256];
|
|
const u32 version_string_size = 128;
|
|
const u32 smem_image_index_venus = 14 * 128;
|
|
u8 *str_image_version;
|
|
int req_bytes;
|
|
|
|
req_bytes = pkt->size - sizeof(*pkt);
|
|
if (req_bytes < version_string_size ||
|
|
!pkt->rg_property_data[1] ||
|
|
pkt->num_properties > 1) {
|
|
dprintk(VIDC_ERR,
|
|
"hfi_process_sys_get_prop_image_version: bad_pkt: %d\n",
|
|
req_bytes);
|
|
return;
|
|
}
|
|
str_image_version = (u8 *)&pkt->rg_property_data[1];
|
|
/*
|
|
* The version string returned by firmware includes null
|
|
* characters at the start and in between. Replace the null
|
|
* characters with space, to print the version info.
|
|
*/
|
|
for (i = 0; i < version_string_size; i++) {
|
|
if (str_image_version[i] != '\0')
|
|
version[i] = str_image_version[i];
|
|
else
|
|
version[i] = ' ';
|
|
}
|
|
version[i] = '\0';
|
|
dprintk(VIDC_DBG, "F/W version: %s\n", version);
|
|
|
|
smem_table_ptr = smem_get_entry(SMEM_IMAGE_VERSION_TABLE,
|
|
&smem_block_size, 0, SMEM_ANY_HOST_FLAG);
|
|
if (smem_table_ptr &&
|
|
((smem_image_index_venus +
|
|
version_string_size) <= smem_block_size))
|
|
memcpy(smem_table_ptr + smem_image_index_venus,
|
|
str_image_version, version_string_size);
|
|
}
|
|
|
|
static void hfi_process_sys_property_info(
|
|
msm_vidc_callback callback, u32 device_id,
|
|
struct hfi_msg_sys_property_info_packet *pkt)
|
|
{
|
|
if (!pkt) {
|
|
dprintk(VIDC_ERR, "%s: invalid param\n", __func__);
|
|
return;
|
|
}
|
|
if (pkt->size < sizeof(*pkt)) {
|
|
dprintk(VIDC_ERR,
|
|
"hfi_process_sys_property_info: bad_pkt_size\n");
|
|
return;
|
|
}
|
|
if (pkt->num_properties == 0) {
|
|
dprintk(VIDC_ERR,
|
|
"hfi_process_sys_property_info: no_properties\n");
|
|
return;
|
|
}
|
|
|
|
switch (pkt->rg_property_data[0]) {
|
|
case HFI_PROPERTY_SYS_IMAGE_VERSION:
|
|
hfi_process_sys_get_prop_image_version(pkt);
|
|
break;
|
|
default:
|
|
dprintk(VIDC_DBG,
|
|
"hfi_process_sys_property_info: unknown_prop_id: %x\n",
|
|
pkt->rg_property_data[0]);
|
|
}
|
|
}
|
|
|
|
u32 hfi_process_msg_packet(msm_vidc_callback callback, u32 device_id,
|
|
struct vidc_hal_msg_pkt_hdr *msg_hdr,
|
|
struct list_head *sessions, struct mutex *session_lock)
|
|
{
|
|
u32 rc = 0;
|
|
struct hal_session *session = NULL;
|
|
typedef void (*session_pkt_func_def)(msm_vidc_callback, u32,
|
|
void *, void *);
|
|
typedef void (*sys_pkt_func_def)(msm_vidc_callback, u32, void *);
|
|
session_pkt_func_def session_pkt_func = NULL;
|
|
sys_pkt_func_def sys_pkt_func = NULL;
|
|
|
|
if (!callback || !session_lock || !msg_hdr ||
|
|
msg_hdr->size < VIDC_IFACEQ_MIN_PKT_SIZE) {
|
|
dprintk(VIDC_ERR, "%s: bad packet/packet size\n",
|
|
__func__);
|
|
rc = -EINVAL;
|
|
return rc;
|
|
}
|
|
|
|
dprintk(VIDC_INFO, "Received: 0x%x\n", msg_hdr->packet);
|
|
rc = (u32) msg_hdr->packet;
|
|
switch (msg_hdr->packet) {
|
|
case HFI_MSG_EVENT_NOTIFY:
|
|
session_pkt_func =
|
|
(session_pkt_func_def)hfi_process_event_notify;
|
|
break;
|
|
case HFI_MSG_SYS_INIT_DONE:
|
|
sys_pkt_func = (sys_pkt_func_def)hfi_process_sys_init_done;
|
|
break;
|
|
case HFI_MSG_SYS_SESSION_INIT_DONE:
|
|
session_pkt_func =
|
|
(session_pkt_func_def)hfi_process_session_init_done;
|
|
break;
|
|
case HFI_MSG_SYS_PROPERTY_INFO:
|
|
sys_pkt_func = (sys_pkt_func_def)hfi_process_sys_property_info;
|
|
break;
|
|
case HFI_MSG_SYS_SESSION_END_DONE:
|
|
session_pkt_func =
|
|
(session_pkt_func_def)hfi_process_session_end_done;
|
|
break;
|
|
case HFI_MSG_SESSION_LOAD_RESOURCES_DONE:
|
|
session_pkt_func =
|
|
(session_pkt_func_def)hfi_process_session_load_res_done;
|
|
break;
|
|
case HFI_MSG_SESSION_START_DONE:
|
|
session_pkt_func =
|
|
(session_pkt_func_def)hfi_process_session_start_done;
|
|
break;
|
|
case HFI_MSG_SESSION_STOP_DONE:
|
|
session_pkt_func =
|
|
(session_pkt_func_def)hfi_process_session_stop_done;
|
|
break;
|
|
case HFI_MSG_SESSION_EMPTY_BUFFER_DONE:
|
|
session_pkt_func =
|
|
(session_pkt_func_def)hfi_process_session_etb_done;
|
|
break;
|
|
case HFI_MSG_SESSION_FILL_BUFFER_DONE:
|
|
session_pkt_func =
|
|
(session_pkt_func_def)hfi_process_session_ftb_done;
|
|
break;
|
|
case HFI_MSG_SESSION_FLUSH_DONE:
|
|
session_pkt_func =
|
|
(session_pkt_func_def)hfi_process_session_flush_done;
|
|
break;
|
|
case HFI_MSG_SESSION_PROPERTY_INFO:
|
|
session_pkt_func =
|
|
(session_pkt_func_def)hfi_process_session_prop_info;
|
|
break;
|
|
case HFI_MSG_SESSION_RELEASE_RESOURCES_DONE:
|
|
session_pkt_func =
|
|
(session_pkt_func_def)hfi_process_session_rel_res_done;
|
|
break;
|
|
case HFI_MSG_SYS_RELEASE_RESOURCE:
|
|
sys_pkt_func =
|
|
(sys_pkt_func_def)hfi_process_sys_rel_resource_done;
|
|
break;
|
|
case HFI_MSG_SESSION_GET_SEQUENCE_HEADER_DONE:
|
|
session_pkt_func =
|
|
(session_pkt_func_def)
|
|
hfi_process_session_get_seq_hdr_done;
|
|
break;
|
|
case HFI_MSG_SESSION_RELEASE_BUFFERS_DONE:
|
|
session_pkt_func =
|
|
(session_pkt_func_def)hfi_process_session_rel_buf_done;
|
|
break;
|
|
case HFI_MSG_SYS_SESSION_ABORT_DONE:
|
|
session_pkt_func =
|
|
(session_pkt_func_def)hfi_process_session_abort_done;
|
|
break;
|
|
case HFI_MSG_SYS_IDLE:
|
|
sys_pkt_func =
|
|
(sys_pkt_func_def)hfi_process_sys_idle;
|
|
break;
|
|
case HFI_MSG_SYS_PC_PREP_DONE:
|
|
break;
|
|
default:
|
|
dprintk(VIDC_DBG, "UNKNOWN_MSG_TYPE : %d\n", msg_hdr->packet);
|
|
break;
|
|
}
|
|
mutex_lock(session_lock);
|
|
if (session_pkt_func) {
|
|
struct vidc_hal_session_cmd_pkt *pkt =
|
|
(struct vidc_hal_session_cmd_pkt *)msg_hdr;
|
|
session = hfi_process_get_session(sessions, pkt->session_id);
|
|
/* Event of type HFI_EVENT_SYS_ERROR will not have any session
|
|
* associated with it */
|
|
if (!session && (msg_hdr->packet != HFI_MSG_EVENT_NOTIFY)) {
|
|
dprintk(VIDC_ERR, "%s Got invalid session id: %d\n",
|
|
__func__, pkt->session_id);
|
|
goto invalid_session;
|
|
}
|
|
}
|
|
|
|
if (session_pkt_func)
|
|
session_pkt_func(callback, device_id, session, msg_hdr);
|
|
if (sys_pkt_func)
|
|
sys_pkt_func(callback, device_id, msg_hdr);
|
|
|
|
invalid_session:
|
|
mutex_unlock(session_lock);
|
|
return rc;
|
|
}
|