15f3510a38
In decoder, window based bitrate check will help identify usecases where, input bitrate exceeds hw capabilities. CRs-Fixed: 2497423 Change-Id: Ic68bd66584ed84382ba03777d39775d08278a8a0 Signed-off-by: Qiwei Liu <qiweil@codeaurora.org> Signed-off-by: Chinmay Sawarkar <chinmays@codeaurora.org>
1329 lines
39 KiB
C
1329 lines
39 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/bitops.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/list.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/hash.h>
|
|
#include <linux/soc/qcom/smem.h>
|
|
#include <soc/qcom/socinfo.h>
|
|
#include "vidc_hfi_helper.h"
|
|
#include "msm_vidc_debug.h"
|
|
#include "vidc_hfi.h"
|
|
|
|
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_NOC_ERROR:
|
|
vidc_err = VIDC_ERR_NOC_ERROR;
|
|
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;
|
|
}
|
|
|
|
static int get_hal_pixel_depth(u32 hfi_bit_depth)
|
|
{
|
|
switch (hfi_bit_depth) {
|
|
case HFI_BITDEPTH_8: return MSM_VIDC_BIT_DEPTH_8;
|
|
case HFI_BITDEPTH_9:
|
|
case HFI_BITDEPTH_10: return MSM_VIDC_BIT_DEPTH_10;
|
|
}
|
|
dprintk(VIDC_ERR, "Unsupported bit depth: %d\n", hfi_bit_depth);
|
|
return MSM_VIDC_BIT_DEPTH_UNSUPPORTED;
|
|
}
|
|
|
|
static inline int validate_pkt_size(u32 rem_size, u32 msg_size)
|
|
{
|
|
if (rem_size < msg_size) {
|
|
dprintk(VIDC_ERR, "%s: bad_packet_size: %d\n",
|
|
__func__, rem_size);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int hfi_process_sess_evt_seq_changed(u32 device_id,
|
|
struct hfi_msg_event_notify_packet *pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct msm_vidc_cb_event event_notify = {0};
|
|
u32 num_properties_changed;
|
|
struct hfi_frame_size *frame_sz;
|
|
struct hfi_profile_level *profile_level;
|
|
struct hfi_bit_depth *pixel_depth;
|
|
struct hfi_pic_struct *pic_struct;
|
|
struct hfi_buffer_requirements *buf_req;
|
|
struct hfi_index_extradata_input_crop_payload *crop_info;
|
|
u32 rem_size,entropy_mode = 0;
|
|
u8 *data_ptr;
|
|
int prop_id;
|
|
int luma_bit_depth, chroma_bit_depth;
|
|
struct hfi_colour_space *colour_info;
|
|
|
|
if (!validate_pkt_size(pkt->size,
|
|
sizeof(struct hfi_msg_event_notify_packet)))
|
|
return -E2BIG;
|
|
|
|
event_notify.device_id = device_id;
|
|
event_notify.session_id = (void *)(uintptr_t)pkt->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 -E2BIG;
|
|
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 -E2BIG;
|
|
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_HIGH|VIDC_PERF,
|
|
"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 -E2BIG;
|
|
data_ptr = data_ptr + sizeof(u32);
|
|
profile_level =
|
|
(struct hfi_profile_level *) data_ptr;
|
|
event_notify.profile = profile_level->profile;
|
|
event_notify.level = profile_level->level;
|
|
dprintk(VIDC_HIGH|VIDC_PERF,
|
|
"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;
|
|
case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH:
|
|
if (!validate_pkt_size(rem_size, sizeof(struct
|
|
hfi_bit_depth)))
|
|
return -E2BIG;
|
|
data_ptr = data_ptr + sizeof(u32);
|
|
pixel_depth = (struct hfi_bit_depth *) data_ptr;
|
|
/*
|
|
* Luma and chroma can have different bitdepths.
|
|
* Driver should rely on luma and chroma
|
|
* bitdepth for determining output bitdepth
|
|
* type.
|
|
*
|
|
* pixel_depth->bitdepth will include luma
|
|
* bitdepth info in bits 0..15 and chroma
|
|
* bitdept in bits 16..31.
|
|
*/
|
|
luma_bit_depth = get_hal_pixel_depth(
|
|
pixel_depth->bit_depth &
|
|
GENMASK(15, 0));
|
|
chroma_bit_depth = get_hal_pixel_depth(
|
|
(pixel_depth->bit_depth &
|
|
GENMASK(31, 16)) >> 16);
|
|
if (luma_bit_depth == MSM_VIDC_BIT_DEPTH_10 ||
|
|
chroma_bit_depth ==
|
|
MSM_VIDC_BIT_DEPTH_10)
|
|
event_notify.bit_depth =
|
|
MSM_VIDC_BIT_DEPTH_10;
|
|
else
|
|
event_notify.bit_depth = luma_bit_depth;
|
|
dprintk(VIDC_HIGH|VIDC_PERF,
|
|
"bitdepth(%d), luma_bit_depth(%d), chroma_bit_depth(%d)\n",
|
|
event_notify.bit_depth, luma_bit_depth,
|
|
chroma_bit_depth);
|
|
data_ptr += sizeof(struct hfi_bit_depth);
|
|
rem_size -= sizeof(struct hfi_bit_depth);
|
|
break;
|
|
case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT:
|
|
if (!validate_pkt_size(rem_size, sizeof(struct
|
|
hfi_pic_struct)))
|
|
return -E2BIG;
|
|
data_ptr = data_ptr + sizeof(u32);
|
|
pic_struct = (struct hfi_pic_struct *) data_ptr;
|
|
event_notify.pic_struct =
|
|
pic_struct->progressive_only;
|
|
dprintk(VIDC_HIGH|VIDC_PERF,
|
|
"Progressive only flag: %d\n",
|
|
pic_struct->progressive_only);
|
|
data_ptr +=
|
|
sizeof(struct hfi_pic_struct);
|
|
rem_size -= sizeof(struct hfi_pic_struct);
|
|
break;
|
|
case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE:
|
|
if (!validate_pkt_size(rem_size, sizeof(struct
|
|
hfi_colour_space)))
|
|
return -E2BIG;
|
|
data_ptr = data_ptr + sizeof(u32);
|
|
colour_info =
|
|
(struct hfi_colour_space *) data_ptr;
|
|
event_notify.colour_space =
|
|
colour_info->colour_space;
|
|
dprintk(VIDC_HIGH,
|
|
"Colour space value is: %d\n",
|
|
colour_info->colour_space);
|
|
data_ptr +=
|
|
sizeof(struct hfi_colour_space);
|
|
rem_size -= sizeof(struct hfi_colour_space);
|
|
break;
|
|
case HFI_PROPERTY_CONFIG_VDEC_ENTROPY:
|
|
if (!validate_pkt_size(rem_size, sizeof(u32)))
|
|
return -E2BIG;
|
|
data_ptr = data_ptr + sizeof(u32);
|
|
entropy_mode = *(u32 *)data_ptr;
|
|
event_notify.entropy_mode = entropy_mode;
|
|
dprintk(VIDC_HIGH|VIDC_PERF,
|
|
"Entropy Mode: 0x%x\n", entropy_mode);
|
|
data_ptr +=
|
|
sizeof(u32);
|
|
rem_size -= sizeof(u32);
|
|
break;
|
|
case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
|
|
if (!validate_pkt_size(rem_size, sizeof(struct
|
|
hfi_buffer_requirements)))
|
|
return -E2BIG;
|
|
data_ptr = data_ptr + sizeof(u32);
|
|
buf_req =
|
|
(struct hfi_buffer_requirements *)
|
|
data_ptr;
|
|
event_notify.capture_buf_count =
|
|
buf_req->buffer_count_min;
|
|
dprintk(VIDC_HIGH|VIDC_PERF,
|
|
"Capture Count : 0x%x\n",
|
|
event_notify.capture_buf_count);
|
|
data_ptr +=
|
|
sizeof(struct hfi_buffer_requirements);
|
|
rem_size -=
|
|
sizeof(struct hfi_buffer_requirements);
|
|
break;
|
|
case HFI_INDEX_EXTRADATA_INPUT_CROP:
|
|
if (!validate_pkt_size(rem_size, sizeof(struct
|
|
hfi_index_extradata_input_crop_payload)))
|
|
return -E2BIG;
|
|
data_ptr = data_ptr + sizeof(u32);
|
|
crop_info = (struct
|
|
hfi_index_extradata_input_crop_payload *)
|
|
data_ptr;
|
|
event_notify.crop_data.left = crop_info->left;
|
|
event_notify.crop_data.top = crop_info->top;
|
|
event_notify.crop_data.width = crop_info->width;
|
|
event_notify.crop_data.height =
|
|
crop_info->height;
|
|
dprintk(VIDC_HIGH,
|
|
"CROP info : Left = %d Top = %d\n",
|
|
crop_info->left,
|
|
crop_info->top);
|
|
dprintk(VIDC_HIGH,
|
|
"CROP info : Width = %d Height = %d\n",
|
|
crop_info->width,
|
|
crop_info->height);
|
|
data_ptr +=
|
|
sizeof(struct
|
|
hfi_index_extradata_input_crop_payload);
|
|
rem_size -= sizeof(struct
|
|
hfi_index_extradata_input_crop_payload);
|
|
break;
|
|
default:
|
|
dprintk(VIDC_ERR,
|
|
"%s cmd: %#x not supported\n",
|
|
__func__, prop_id);
|
|
break;
|
|
}
|
|
num_properties_changed--;
|
|
} while (num_properties_changed > 0);
|
|
}
|
|
|
|
info->response_type = HAL_SESSION_EVENT_CHANGE;
|
|
info->response.event = event_notify;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_evt_release_buffer_ref(u32 device_id,
|
|
struct hfi_msg_event_notify_packet *pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct msm_vidc_cb_event event_notify = {0};
|
|
struct hfi_msg_release_buffer_ref_event_packet *data;
|
|
|
|
dprintk(VIDC_LOW,
|
|
"RECEIVED: EVENT_NOTIFY - release_buffer_reference\n");
|
|
if (sizeof(struct hfi_msg_event_notify_packet)
|
|
> pkt->size) {
|
|
dprintk(VIDC_ERR, "%s: bad_pkt_size\n", __func__);
|
|
return -E2BIG;
|
|
}
|
|
if (pkt->size < sizeof(struct hfi_msg_event_notify_packet) - sizeof(u32)
|
|
+ sizeof(struct hfi_msg_release_buffer_ref_event_packet)) {
|
|
dprintk(VIDC_ERR, "%s: bad_pkt_size: %d\n",
|
|
__func__, pkt->size);
|
|
return -E2BIG;
|
|
}
|
|
|
|
data = (struct hfi_msg_release_buffer_ref_event_packet *)
|
|
pkt->rg_ext_event_data;
|
|
|
|
event_notify.device_id = device_id;
|
|
event_notify.session_id = (void *)(uintptr_t)pkt->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;
|
|
|
|
info->response_type = HAL_SESSION_EVENT_CHANGE;
|
|
info->response.event = event_notify;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_sys_error(u32 device_id,
|
|
struct hfi_msg_event_notify_packet *pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->event_data1);
|
|
|
|
info->response_type = HAL_SYS_ERROR;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_session_error(u32 device_id,
|
|
struct hfi_msg_event_notify_packet *pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->event_data1);
|
|
info->response.cmd = cmd_done;
|
|
dprintk(VIDC_HIGH, "Received: SESSION_ERROR with event id : %#x %#x\n",
|
|
pkt->event_data1, pkt->event_data2);
|
|
switch (pkt->event_data1) {
|
|
/* Ignore below errors */
|
|
case HFI_ERR_SESSION_INVALID_SCALE_FACTOR:
|
|
case HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED:
|
|
dprintk(VIDC_HIGH, "Non Fatal: HFI_EVENT_SESSION_ERROR\n");
|
|
info->response_type = HAL_RESPONSE_UNUSED;
|
|
break;
|
|
default:
|
|
dprintk(VIDC_ERR,
|
|
"%s: session %x data1 %#x, data2 %#x\n", __func__,
|
|
pkt->session_id, pkt->event_data1, pkt->event_data2);
|
|
info->response_type = HAL_SESSION_ERROR;
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_event_notify(u32 device_id,
|
|
void *_pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct hfi_msg_event_notify_packet *pkt = _pkt;
|
|
dprintk(VIDC_LOW, "Received: EVENT_NOTIFY\n");
|
|
|
|
if (pkt->size < sizeof(struct hfi_msg_event_notify_packet)) {
|
|
dprintk(VIDC_ERR, "Invalid Params\n");
|
|
return -E2BIG;
|
|
}
|
|
|
|
switch (pkt->event_id) {
|
|
case HFI_EVENT_SYS_ERROR:
|
|
dprintk(VIDC_ERR, "HFI_EVENT_SYS_ERROR: %d, %#x\n",
|
|
pkt->event_data1, pkt->event_data2);
|
|
return hfi_process_sys_error(device_id, pkt, info);
|
|
case HFI_EVENT_SESSION_ERROR:
|
|
dprintk(VIDC_HIGH, "HFI_EVENT_SESSION_ERROR[%#x]\n",
|
|
pkt->session_id);
|
|
return hfi_process_session_error(device_id, pkt, info);
|
|
|
|
case HFI_EVENT_SESSION_SEQUENCE_CHANGED:
|
|
dprintk(VIDC_HIGH, "HFI_EVENT_SESSION_SEQUENCE_CHANGED[%#x]\n",
|
|
pkt->session_id);
|
|
return hfi_process_sess_evt_seq_changed(device_id, pkt, info);
|
|
|
|
case HFI_EVENT_RELEASE_BUFFER_REFERENCE:
|
|
dprintk(VIDC_LOW, "HFI_EVENT_RELEASE_BUFFER_REFERENCE[%#x]\n",
|
|
pkt->session_id);
|
|
return hfi_process_evt_release_buffer_ref(device_id, pkt, info);
|
|
|
|
case HFI_EVENT_SESSION_PROPERTY_CHANGED:
|
|
default:
|
|
*info = (struct msm_vidc_cb_info) {
|
|
.response_type = HAL_RESPONSE_UNUSED,
|
|
};
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static int hfi_process_sys_init_done(u32 device_id,
|
|
void *_pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct hfi_msg_sys_init_done_packet *pkt = _pkt;
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
enum vidc_status status = VIDC_ERR_NONE;
|
|
|
|
dprintk(VIDC_HIGH, "RECEIVED: SYS_INIT_DONE\n");
|
|
if (sizeof(struct hfi_msg_sys_init_done_packet) > pkt->size) {
|
|
dprintk(VIDC_ERR, "%s: bad_pkt_size: %d\n", __func__,
|
|
pkt->size);
|
|
return -E2BIG;
|
|
}
|
|
status = hfi_map_err_status(pkt->error_type);
|
|
if (status)
|
|
dprintk(VIDC_ERR, "%s: status %#x\n",
|
|
__func__, status);
|
|
|
|
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);
|
|
|
|
info->response_type = HAL_SYS_INIT_DONE;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_sys_rel_resource_done(u32 device_id,
|
|
void *_pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct hfi_msg_sys_release_resource_done_packet *pkt = _pkt;
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
enum vidc_status status = VIDC_ERR_NONE;
|
|
u32 pkt_size;
|
|
|
|
dprintk(VIDC_HIGH, "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 -E2BIG;
|
|
}
|
|
|
|
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;
|
|
|
|
info->response_type = HAL_SYS_RELEASE_RESOURCE_DONE;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
}
|
|
|
|
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) {
|
|
dprintk(VIDC_HIGH, "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_COMMON_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_COMMON_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_COMMON_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;
|
|
case HFI_BUFFER_COMMON_INTERNAL_RECON:
|
|
memcpy(&buffreq->buffer[11], hfi_buf_req,
|
|
sizeof(struct hfi_buffer_requirements));
|
|
buffreq->buffer[11].buffer_type =
|
|
HAL_BUFFER_INTERNAL_RECON;
|
|
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 int hfi_process_session_prop_info(u32 device_id,
|
|
void *_pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct hfi_msg_session_property_info_packet *pkt = _pkt;
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
struct buffer_requirements buff_req = { { {0} } };
|
|
|
|
dprintk(VIDC_HIGH, "Received SESSION_PROPERTY_INFO[%#x]\n",
|
|
pkt->session_id);
|
|
|
|
if (pkt->size < sizeof(struct hfi_msg_session_property_info_packet)) {
|
|
dprintk(VIDC_ERR,
|
|
"hal_process_session_prop_info: bad_pkt_size\n");
|
|
return -E2BIG;
|
|
} else if (!pkt->num_properties) {
|
|
dprintk(VIDC_ERR,
|
|
"hal_process_session_prop_info: no_properties\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
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 = (void *)(uintptr_t)pkt->session_id;
|
|
cmd_done.status = VIDC_ERR_NONE;
|
|
cmd_done.data.property.buf_req = buff_req;
|
|
cmd_done.size = sizeof(buff_req);
|
|
|
|
info->response_type = HAL_SESSION_PROPERTY_INFO;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
default:
|
|
dprintk(VIDC_HIGH,
|
|
"hal_process_session_prop_info: unknown_prop_id: %x\n",
|
|
pkt->rg_property_data[0]);
|
|
return -ENOTSUPP;
|
|
}
|
|
}
|
|
|
|
static int hfi_process_session_init_done(u32 device_id,
|
|
void *_pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct hfi_msg_sys_session_init_done_packet *pkt = _pkt;
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
|
|
dprintk(VIDC_HIGH, "RECEIVED: SESSION_INIT_DONE[%x]\n", pkt->session_id);
|
|
|
|
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 -E2BIG;
|
|
}
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
|
|
info->response_type = HAL_SESSION_INIT_DONE;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_session_load_res_done(u32 device_id,
|
|
void *_pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct hfi_msg_session_load_resources_done_packet *pkt = _pkt;
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
|
|
dprintk(VIDC_HIGH, "RECEIVED: SESSION_LOAD_RESOURCES_DONE[%#x]\n",
|
|
pkt->session_id);
|
|
|
|
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 -E2BIG;
|
|
}
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.size = 0;
|
|
|
|
info->response_type = HAL_SESSION_LOAD_RESOURCE_DONE;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_session_flush_done(u32 device_id,
|
|
void *_pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct hfi_msg_session_flush_done_packet *pkt = _pkt;
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
|
|
dprintk(VIDC_HIGH, "RECEIVED: SESSION_FLUSH_DONE[%#x]\n",
|
|
pkt->session_id);
|
|
|
|
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 -E2BIG;
|
|
}
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.size = sizeof(u32);
|
|
|
|
switch (pkt->flush_type) {
|
|
case HFI_FLUSH_OUTPUT:
|
|
cmd_done.data.flush_type = HAL_FLUSH_OUTPUT;
|
|
break;
|
|
case HFI_FLUSH_INPUT:
|
|
cmd_done.data.flush_type = HAL_FLUSH_INPUT;
|
|
break;
|
|
case HFI_FLUSH_ALL:
|
|
cmd_done.data.flush_type = HAL_FLUSH_ALL;
|
|
break;
|
|
default:
|
|
dprintk(VIDC_ERR,
|
|
"%s: invalid flush type!", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
info->response_type = HAL_SESSION_FLUSH_DONE;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_session_etb_done(u32 device_id,
|
|
void *_pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct hfi_msg_session_empty_buffer_done_packet *pkt = _pkt;
|
|
struct msm_vidc_cb_data_done data_done = {0};
|
|
|
|
dprintk(VIDC_LOW, "RECEIVED: SESSION_ETB_DONE[%#x]\n", pkt->session_id);
|
|
|
|
if (!pkt || pkt->size <
|
|
sizeof(struct hfi_msg_session_empty_buffer_done_packet))
|
|
goto bad_packet_size;
|
|
|
|
data_done.device_id = device_id;
|
|
data_done.session_id = (void *)(uintptr_t)pkt->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.recon_stats.buffer_index =
|
|
pkt->ubwc_cr_stats.frame_index;
|
|
memcpy(&data_done.input_done.recon_stats.ubwc_stats_info,
|
|
&pkt->ubwc_cr_stats.ubwc_stats_info,
|
|
sizeof(data_done.input_done.recon_stats.ubwc_stats_info));
|
|
data_done.input_done.recon_stats.complexity_number =
|
|
pkt->ubwc_cr_stats.complexity_number;
|
|
data_done.input_done.offset = pkt->offset;
|
|
data_done.input_done.filled_len = pkt->filled_len;
|
|
data_done.input_done.flags = pkt->flags;
|
|
data_done.input_done.packet_buffer = pkt->packet_buffer;
|
|
data_done.input_done.extra_data_buffer = 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);
|
|
|
|
info->response_type = HAL_SESSION_ETB_DONE;
|
|
info->response.data = data_done;
|
|
|
|
return 0;
|
|
bad_packet_size:
|
|
dprintk(VIDC_ERR, "%s: bad_pkt_size: %d\n",
|
|
__func__, pkt ? pkt->size : 0);
|
|
return -E2BIG;
|
|
}
|
|
|
|
static int hfi_process_session_ftb_done(
|
|
u32 device_id, void *_pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct vidc_hal_msg_pkt_hdr *msg_hdr = _pkt;
|
|
struct msm_vidc_cb_data_done data_done = {0};
|
|
bool is_decoder = false, is_encoder = false;
|
|
|
|
if (!msg_hdr) {
|
|
dprintk(VIDC_ERR, "Invalid Params\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
is_encoder = msg_hdr->size == sizeof(struct
|
|
hfi_msg_session_fill_buffer_done_compressed_packet) + 4;
|
|
is_decoder = msg_hdr->size == sizeof(struct
|
|
hfi_msg_session_fbd_uncompressed_plane0_packet) + 4;
|
|
|
|
if (!(is_encoder ^ is_decoder)) {
|
|
dprintk(VIDC_ERR, "Ambiguous packet (%#x) received (size %d)\n",
|
|
msg_hdr->packet, msg_hdr->size);
|
|
return -EBADHANDLE;
|
|
}
|
|
|
|
if (is_encoder) {
|
|
struct hfi_msg_session_fill_buffer_done_compressed_packet *pkt =
|
|
(struct hfi_msg_session_fill_buffer_done_compressed_packet *)
|
|
msg_hdr;
|
|
dprintk(VIDC_LOW, "RECEIVED: SESSION_FTB_DONE[%#x]\n",
|
|
pkt->session_id);
|
|
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 -E2BIG;
|
|
} 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 = (void *)(uintptr_t)pkt->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 = pkt->packet_buffer;
|
|
data_done.output_done.extra_data_buffer =
|
|
pkt->extra_data_buffer;
|
|
data_done.output_done.buffer_type = HAL_BUFFER_OUTPUT;
|
|
} else /* if (is_decoder) */ {
|
|
struct hfi_msg_session_fbd_uncompressed_plane0_packet *pkt =
|
|
(struct hfi_msg_session_fbd_uncompressed_plane0_packet *)
|
|
msg_hdr;
|
|
|
|
dprintk(VIDC_LOW, "RECEIVED: SESSION_FTB_DONE[%#x]\n",
|
|
pkt->session_id);
|
|
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 -E2BIG;
|
|
}
|
|
|
|
data_done.device_id = device_id;
|
|
data_done.session_id = (void *)(uintptr_t)pkt->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)
|
|
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);
|
|
|
|
info->response_type = HAL_SESSION_FTB_DONE;
|
|
info->response.data = data_done;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_session_start_done(u32 device_id,
|
|
void *_pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct hfi_msg_session_start_done_packet *pkt = _pkt;
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
|
|
dprintk(VIDC_HIGH, "RECEIVED: SESSION_START_DONE[%#x]\n",
|
|
pkt->session_id);
|
|
|
|
if (!pkt || pkt->size !=
|
|
sizeof(struct hfi_msg_session_start_done_packet)) {
|
|
dprintk(VIDC_ERR, "%s: bad packet/packet size\n",
|
|
__func__);
|
|
return -E2BIG;
|
|
}
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.size = 0;
|
|
|
|
info->response_type = HAL_SESSION_START_DONE;
|
|
info->response.cmd = cmd_done;
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_session_stop_done(u32 device_id,
|
|
void *_pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct hfi_msg_session_stop_done_packet *pkt = _pkt;
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
|
|
dprintk(VIDC_HIGH, "RECEIVED: SESSION_STOP_DONE[%#x]\n",
|
|
pkt->session_id);
|
|
|
|
if (!pkt || pkt->size !=
|
|
sizeof(struct hfi_msg_session_stop_done_packet)) {
|
|
dprintk(VIDC_ERR, "%s: bad packet/packet size\n",
|
|
__func__);
|
|
return -E2BIG;
|
|
}
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.size = 0;
|
|
|
|
info->response_type = HAL_SESSION_STOP_DONE;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_session_rel_res_done(u32 device_id,
|
|
void *_pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct hfi_msg_session_release_resources_done_packet *pkt = _pkt;
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
|
|
dprintk(VIDC_HIGH, "RECEIVED: SESSION_RELEASE_RESOURCES_DONE[%#x]\n",
|
|
pkt->session_id);
|
|
|
|
if (!pkt || pkt->size !=
|
|
sizeof(struct hfi_msg_session_release_resources_done_packet)) {
|
|
dprintk(VIDC_ERR, "%s: bad packet/packet size\n",
|
|
__func__);
|
|
return -E2BIG;
|
|
}
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.size = 0;
|
|
|
|
info->response_type = HAL_SESSION_RELEASE_RESOURCE_DONE;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_session_rel_buf_done(u32 device_id,
|
|
void *_pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct hfi_msg_session_release_buffers_done_packet *pkt = _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 -E2BIG;
|
|
}
|
|
dprintk(VIDC_HIGH, "RECEIVED:SESSION_RELEASE_BUFFER_DONE[%#x]\n",
|
|
pkt->session_id);
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.size = sizeof(struct msm_vidc_cb_cmd_done);
|
|
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.data.buffer_info.buffer_addr = *pkt->rg_buffer_info;
|
|
cmd_done.size = sizeof(struct hal_buffer_info);
|
|
|
|
info->response_type = HAL_SESSION_RELEASE_BUFFER_DONE;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_session_register_buffer_done(u32 device_id,
|
|
void *_pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct hfi_msg_session_register_buffers_done_packet *pkt = _pkt;
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
|
|
if (!pkt || pkt->size <
|
|
sizeof(struct hfi_msg_session_register_buffers_done_packet)) {
|
|
dprintk(VIDC_ERR, "%s: bad packet/packet size %d\n",
|
|
__func__, pkt ? pkt->size : 0);
|
|
return -E2BIG;
|
|
}
|
|
dprintk(VIDC_HIGH, "RECEIVED: SESSION_REGISTER_BUFFERS_DONE[%#x]\n",
|
|
pkt->session_id);
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.size = sizeof(struct msm_vidc_cb_cmd_done);
|
|
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.data.regbuf.client_data = pkt->client_data;
|
|
|
|
info->response_type = HAL_SESSION_REGISTER_BUFFER_DONE;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_session_unregister_buffer_done(u32 device_id,
|
|
void *_pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct hfi_msg_session_unregister_buffers_done_packet *pkt = _pkt;
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
|
|
if (!pkt || pkt->size <
|
|
sizeof(struct hfi_msg_session_unregister_buffers_done_packet)) {
|
|
dprintk(VIDC_ERR, "%s: bad packet/packet size %d\n",
|
|
__func__, pkt ? pkt->size : 0);
|
|
return -E2BIG;
|
|
}
|
|
dprintk(VIDC_HIGH, "RECEIVED: SESSION_UNREGISTER_BUFFERS_DONE[%#x]\n",
|
|
pkt->session_id);
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.size = sizeof(struct msm_vidc_cb_cmd_done);
|
|
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.data.unregbuf.client_data = pkt->client_data;
|
|
|
|
info->response_type = HAL_SESSION_UNREGISTER_BUFFER_DONE;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_session_end_done(u32 device_id,
|
|
void *_pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct hfi_msg_sys_session_end_done_packet *pkt = _pkt;
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
|
|
dprintk(VIDC_HIGH, "RECEIVED: SESSION_END_DONE[%#x]\n", pkt->session_id);
|
|
|
|
if (!pkt || pkt->size !=
|
|
sizeof(struct hfi_msg_sys_session_end_done_packet)) {
|
|
dprintk(VIDC_ERR, "%s: bad packet/packet size\n", __func__);
|
|
return -E2BIG;
|
|
}
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.size = 0;
|
|
|
|
info->response_type = HAL_SESSION_END_DONE;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_session_abort_done(u32 device_id,
|
|
void *_pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct hfi_msg_sys_session_abort_done_packet *pkt = _pkt;
|
|
struct msm_vidc_cb_cmd_done cmd_done = {0};
|
|
|
|
dprintk(VIDC_HIGH, "RECEIVED: SESSION_ABORT_DONE[%#x]\n",
|
|
pkt->session_id);
|
|
|
|
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 -E2BIG;
|
|
}
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.size = 0;
|
|
|
|
info->response_type = HAL_SESSION_ABORT_DONE;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void hfi_process_sys_get_prop_image_version(
|
|
struct hfi_msg_sys_property_info_packet *pkt)
|
|
{
|
|
u32 i = 0;
|
|
size_t 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;
|
|
u32 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, "%s: bad_pkt: %d\n", __func__, 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_HIGH, "F/W version: %s\n", version);
|
|
|
|
smem_table_ptr = qcom_smem_get(QCOM_SMEM_HOST_ANY,
|
|
SMEM_IMAGE_VERSION_TABLE, &smem_block_size);
|
|
if ((smem_image_index_venus + version_string_size) <= smem_block_size &&
|
|
smem_table_ptr)
|
|
memcpy(smem_table_ptr + smem_image_index_venus,
|
|
str_image_version, version_string_size);
|
|
}
|
|
|
|
static int hfi_process_sys_property_info(u32 device_id,
|
|
void *_pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
struct hfi_msg_sys_property_info_packet *pkt = _pkt;
|
|
if (!pkt) {
|
|
dprintk(VIDC_ERR, "%s: invalid param\n", __func__);
|
|
return -EINVAL;
|
|
} else if (pkt->size < sizeof(*pkt)) {
|
|
dprintk(VIDC_ERR,
|
|
"%s: bad_pkt_size\n", __func__);
|
|
return -E2BIG;
|
|
} else if (!pkt->num_properties) {
|
|
dprintk(VIDC_ERR,
|
|
"%s: no_properties\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
switch (pkt->rg_property_data[0]) {
|
|
case HFI_PROPERTY_SYS_IMAGE_VERSION:
|
|
hfi_process_sys_get_prop_image_version(pkt);
|
|
|
|
*info = (struct msm_vidc_cb_info) {
|
|
.response_type = HAL_RESPONSE_UNUSED,
|
|
};
|
|
return 0;
|
|
default:
|
|
dprintk(VIDC_HIGH,
|
|
"%s: unknown_prop_id: %x\n",
|
|
__func__, pkt->rg_property_data[0]);
|
|
return -ENOTSUPP;
|
|
}
|
|
|
|
}
|
|
|
|
static int hfi_process_ignore(u32 device_id,
|
|
void *_pkt,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
*info = (struct msm_vidc_cb_info) {
|
|
.response_type = HAL_RESPONSE_UNUSED,
|
|
};
|
|
|
|
return 0;
|
|
}
|
|
|
|
int hfi_process_msg_packet(u32 device_id, struct vidc_hal_msg_pkt_hdr *msg_hdr,
|
|
struct msm_vidc_cb_info *info)
|
|
{
|
|
typedef int (*pkt_func_def)(u32, void *, struct msm_vidc_cb_info *info);
|
|
pkt_func_def pkt_func = NULL;
|
|
|
|
if (!info || !msg_hdr || msg_hdr->size < VIDC_IFACEQ_MIN_PKT_SIZE) {
|
|
dprintk(VIDC_ERR, "%s: bad packet/packet size\n",
|
|
__func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
dprintk(VIDC_LOW, "Parse response %#x\n", msg_hdr->packet);
|
|
switch (msg_hdr->packet) {
|
|
case HFI_MSG_EVENT_NOTIFY:
|
|
pkt_func = (pkt_func_def)hfi_process_event_notify;
|
|
break;
|
|
case HFI_MSG_SYS_INIT_DONE:
|
|
pkt_func = (pkt_func_def)hfi_process_sys_init_done;
|
|
break;
|
|
case HFI_MSG_SYS_SESSION_INIT_DONE:
|
|
pkt_func = (pkt_func_def)hfi_process_session_init_done;
|
|
break;
|
|
case HFI_MSG_SYS_PROPERTY_INFO:
|
|
pkt_func = (pkt_func_def)hfi_process_sys_property_info;
|
|
break;
|
|
case HFI_MSG_SYS_SESSION_END_DONE:
|
|
pkt_func = (pkt_func_def)hfi_process_session_end_done;
|
|
break;
|
|
case HFI_MSG_SESSION_LOAD_RESOURCES_DONE:
|
|
pkt_func = (pkt_func_def)hfi_process_session_load_res_done;
|
|
break;
|
|
case HFI_MSG_SESSION_START_DONE:
|
|
pkt_func = (pkt_func_def)hfi_process_session_start_done;
|
|
break;
|
|
case HFI_MSG_SESSION_STOP_DONE:
|
|
pkt_func = (pkt_func_def)hfi_process_session_stop_done;
|
|
break;
|
|
case HFI_MSG_SESSION_EMPTY_BUFFER_DONE:
|
|
pkt_func = (pkt_func_def)hfi_process_session_etb_done;
|
|
break;
|
|
case HFI_MSG_SESSION_FILL_BUFFER_DONE:
|
|
pkt_func = (pkt_func_def)hfi_process_session_ftb_done;
|
|
break;
|
|
case HFI_MSG_SESSION_FLUSH_DONE:
|
|
pkt_func = (pkt_func_def)hfi_process_session_flush_done;
|
|
break;
|
|
case HFI_MSG_SESSION_PROPERTY_INFO:
|
|
pkt_func = (pkt_func_def)hfi_process_session_prop_info;
|
|
break;
|
|
case HFI_MSG_SESSION_RELEASE_RESOURCES_DONE:
|
|
pkt_func = (pkt_func_def)hfi_process_session_rel_res_done;
|
|
break;
|
|
case HFI_MSG_SYS_RELEASE_RESOURCE:
|
|
pkt_func = (pkt_func_def)hfi_process_sys_rel_resource_done;
|
|
break;
|
|
case HFI_MSG_SESSION_RELEASE_BUFFERS_DONE:
|
|
pkt_func = (pkt_func_def)hfi_process_session_rel_buf_done;
|
|
break;
|
|
case HFI_MSG_SESSION_REGISTER_BUFFERS_DONE:
|
|
pkt_func = (pkt_func_def)
|
|
hfi_process_session_register_buffer_done;
|
|
break;
|
|
case HFI_MSG_SESSION_UNREGISTER_BUFFERS_DONE:
|
|
pkt_func = (pkt_func_def)
|
|
hfi_process_session_unregister_buffer_done;
|
|
break;
|
|
case HFI_MSG_SYS_SESSION_ABORT_DONE:
|
|
pkt_func = (pkt_func_def)hfi_process_session_abort_done;
|
|
break;
|
|
case HFI_MSG_SESSION_SYNC_DONE:
|
|
pkt_func = (pkt_func_def)hfi_process_ignore;
|
|
break;
|
|
default:
|
|
dprintk(VIDC_LOW, "Unable to parse message: %#x\n",
|
|
msg_hdr->packet);
|
|
break;
|
|
}
|
|
|
|
return pkt_func ?
|
|
pkt_func(device_id, (void *)msg_hdr, info) : -ENOTSUPP;
|
|
}
|