mirror of
https://github.com/Qortal/Brooklyn.git
synced 2025-02-01 07:42:18 +00:00
04c1822c0a
Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey!
790 lines
20 KiB
C
790 lines
20 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
|
|
* Copyright (C) 2017 Linaro Ltd.
|
|
*/
|
|
#include <linux/hash.h>
|
|
#include <linux/list.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/soc/qcom/smem.h>
|
|
#include <media/videobuf2-v4l2.h>
|
|
|
|
#include "core.h"
|
|
#include "hfi.h"
|
|
#include "hfi_helper.h"
|
|
#include "hfi_msgs.h"
|
|
#include "hfi_parser.h"
|
|
|
|
#define SMEM_IMG_VER_TBL 469
|
|
#define VER_STR_SZ 128
|
|
#define SMEM_IMG_OFFSET_VENUS (14 * 128)
|
|
|
|
static void event_seq_changed(struct venus_core *core, struct venus_inst *inst,
|
|
struct hfi_msg_event_notify_pkt *pkt)
|
|
{
|
|
enum hfi_version ver = core->res->hfi_version;
|
|
struct hfi_event_data event = {0};
|
|
int num_properties_changed;
|
|
struct hfi_framesize *frame_sz;
|
|
struct hfi_profile_level *profile_level;
|
|
struct hfi_bit_depth *pixel_depth;
|
|
struct hfi_pic_struct *pic_struct;
|
|
struct hfi_colour_space *colour_info;
|
|
struct hfi_buffer_requirements *bufreq;
|
|
struct hfi_extradata_input_crop *crop;
|
|
u8 *data_ptr;
|
|
u32 ptype;
|
|
|
|
inst->error = HFI_ERR_NONE;
|
|
|
|
switch (pkt->event_data1) {
|
|
case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES:
|
|
case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES:
|
|
break;
|
|
default:
|
|
inst->error = HFI_ERR_SESSION_INVALID_PARAMETER;
|
|
goto done;
|
|
}
|
|
|
|
event.event_type = pkt->event_data1;
|
|
|
|
num_properties_changed = pkt->event_data2;
|
|
if (!num_properties_changed) {
|
|
inst->error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES;
|
|
goto done;
|
|
}
|
|
|
|
data_ptr = (u8 *)&pkt->ext_event_data[0];
|
|
do {
|
|
ptype = *((u32 *)data_ptr);
|
|
switch (ptype) {
|
|
case HFI_PROPERTY_PARAM_FRAME_SIZE:
|
|
data_ptr += sizeof(u32);
|
|
frame_sz = (struct hfi_framesize *)data_ptr;
|
|
event.width = frame_sz->width;
|
|
event.height = frame_sz->height;
|
|
data_ptr += sizeof(*frame_sz);
|
|
break;
|
|
case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
|
|
data_ptr += sizeof(u32);
|
|
profile_level = (struct hfi_profile_level *)data_ptr;
|
|
event.profile = profile_level->profile;
|
|
event.level = profile_level->level;
|
|
data_ptr += sizeof(*profile_level);
|
|
break;
|
|
case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH:
|
|
data_ptr += sizeof(u32);
|
|
pixel_depth = (struct hfi_bit_depth *)data_ptr;
|
|
event.bit_depth = pixel_depth->bit_depth;
|
|
data_ptr += sizeof(*pixel_depth);
|
|
break;
|
|
case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT:
|
|
data_ptr += sizeof(u32);
|
|
pic_struct = (struct hfi_pic_struct *)data_ptr;
|
|
event.pic_struct = pic_struct->progressive_only;
|
|
data_ptr += sizeof(*pic_struct);
|
|
break;
|
|
case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE:
|
|
data_ptr += sizeof(u32);
|
|
colour_info = (struct hfi_colour_space *)data_ptr;
|
|
event.colour_space = colour_info->colour_space;
|
|
data_ptr += sizeof(*colour_info);
|
|
break;
|
|
case HFI_PROPERTY_CONFIG_VDEC_ENTROPY:
|
|
data_ptr += sizeof(u32);
|
|
event.entropy_mode = *(u32 *)data_ptr;
|
|
data_ptr += sizeof(u32);
|
|
break;
|
|
case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
|
|
data_ptr += sizeof(u32);
|
|
bufreq = (struct hfi_buffer_requirements *)data_ptr;
|
|
event.buf_count = HFI_BUFREQ_COUNT_MIN(bufreq, ver);
|
|
data_ptr += sizeof(*bufreq);
|
|
break;
|
|
case HFI_INDEX_EXTRADATA_INPUT_CROP:
|
|
data_ptr += sizeof(u32);
|
|
crop = (struct hfi_extradata_input_crop *)data_ptr;
|
|
event.input_crop.left = crop->left;
|
|
event.input_crop.top = crop->top;
|
|
event.input_crop.width = crop->width;
|
|
event.input_crop.height = crop->height;
|
|
data_ptr += sizeof(*crop);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
num_properties_changed--;
|
|
} while (num_properties_changed > 0);
|
|
|
|
done:
|
|
inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event);
|
|
}
|
|
|
|
static void event_release_buffer_ref(struct venus_core *core,
|
|
struct venus_inst *inst,
|
|
struct hfi_msg_event_notify_pkt *pkt)
|
|
{
|
|
struct hfi_event_data event = {0};
|
|
struct hfi_msg_event_release_buffer_ref_pkt *data;
|
|
|
|
data = (struct hfi_msg_event_release_buffer_ref_pkt *)
|
|
pkt->ext_event_data;
|
|
|
|
event.event_type = HFI_EVENT_RELEASE_BUFFER_REFERENCE;
|
|
event.packet_buffer = data->packet_buffer;
|
|
event.extradata_buffer = data->extradata_buffer;
|
|
event.tag = data->output_tag;
|
|
|
|
inst->error = HFI_ERR_NONE;
|
|
inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event);
|
|
}
|
|
|
|
static void event_sys_error(struct venus_core *core, u32 event,
|
|
struct hfi_msg_event_notify_pkt *pkt)
|
|
{
|
|
if (pkt)
|
|
dev_dbg(core->dev, VDBGH
|
|
"sys error (session id:%x, data1:%x, data2:%x)\n",
|
|
pkt->shdr.session_id, pkt->event_data1,
|
|
pkt->event_data2);
|
|
|
|
core->core_ops->event_notify(core, event);
|
|
}
|
|
|
|
static void
|
|
event_session_error(struct venus_core *core, struct venus_inst *inst,
|
|
struct hfi_msg_event_notify_pkt *pkt)
|
|
{
|
|
struct device *dev = core->dev;
|
|
|
|
dev_dbg(dev, VDBGH "session error: event id:%x, session id:%x\n",
|
|
pkt->event_data1, pkt->shdr.session_id);
|
|
|
|
if (!inst)
|
|
return;
|
|
|
|
switch (pkt->event_data1) {
|
|
/* non fatal session errors */
|
|
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:
|
|
inst->error = HFI_ERR_NONE;
|
|
break;
|
|
default:
|
|
dev_err(dev, "session error: event id:%x (%x), session id:%x\n",
|
|
pkt->event_data1, pkt->event_data2,
|
|
pkt->shdr.session_id);
|
|
|
|
inst->error = pkt->event_data1;
|
|
inst->ops->event_notify(inst, EVT_SESSION_ERROR, NULL);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void hfi_event_notify(struct venus_core *core, struct venus_inst *inst,
|
|
void *packet)
|
|
{
|
|
struct hfi_msg_event_notify_pkt *pkt = packet;
|
|
|
|
if (!packet)
|
|
return;
|
|
|
|
switch (pkt->event_id) {
|
|
case HFI_EVENT_SYS_ERROR:
|
|
event_sys_error(core, EVT_SYS_ERROR, pkt);
|
|
break;
|
|
case HFI_EVENT_SESSION_ERROR:
|
|
event_session_error(core, inst, pkt);
|
|
break;
|
|
case HFI_EVENT_SESSION_SEQUENCE_CHANGED:
|
|
event_seq_changed(core, inst, pkt);
|
|
break;
|
|
case HFI_EVENT_RELEASE_BUFFER_REFERENCE:
|
|
event_release_buffer_ref(core, inst, pkt);
|
|
break;
|
|
case HFI_EVENT_SESSION_PROPERTY_CHANGED:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void hfi_sys_init_done(struct venus_core *core, struct venus_inst *inst,
|
|
void *packet)
|
|
{
|
|
struct hfi_msg_sys_init_done_pkt *pkt = packet;
|
|
int rem_bytes;
|
|
u32 error;
|
|
|
|
error = pkt->error_type;
|
|
if (error != HFI_ERR_NONE)
|
|
goto done;
|
|
|
|
if (!pkt->num_properties) {
|
|
error = HFI_ERR_SYS_INVALID_PARAMETER;
|
|
goto done;
|
|
}
|
|
|
|
rem_bytes = pkt->hdr.size - sizeof(*pkt) + sizeof(u32);
|
|
if (rem_bytes <= 0) {
|
|
/* missing property data */
|
|
error = HFI_ERR_SYS_INSUFFICIENT_RESOURCES;
|
|
goto done;
|
|
}
|
|
|
|
error = hfi_parser(core, inst, pkt->data, rem_bytes);
|
|
|
|
done:
|
|
core->error = error;
|
|
complete(&core->done);
|
|
}
|
|
|
|
static void
|
|
sys_get_prop_image_version(struct device *dev,
|
|
struct hfi_msg_sys_property_info_pkt *pkt)
|
|
{
|
|
u8 *smem_tbl_ptr;
|
|
u8 *img_ver;
|
|
int req_bytes;
|
|
size_t smem_blk_sz;
|
|
|
|
req_bytes = pkt->hdr.size - sizeof(*pkt);
|
|
|
|
if (req_bytes < VER_STR_SZ || !pkt->data[0] || pkt->num_properties > 1)
|
|
/* bad packet */
|
|
return;
|
|
|
|
img_ver = pkt->data;
|
|
|
|
dev_dbg(dev, VDBGL "F/W version: %s\n", img_ver);
|
|
|
|
smem_tbl_ptr = qcom_smem_get(QCOM_SMEM_HOST_ANY,
|
|
SMEM_IMG_VER_TBL, &smem_blk_sz);
|
|
if (!IS_ERR(smem_tbl_ptr) && smem_blk_sz >= SMEM_IMG_OFFSET_VENUS + VER_STR_SZ)
|
|
memcpy(smem_tbl_ptr + SMEM_IMG_OFFSET_VENUS,
|
|
img_ver, VER_STR_SZ);
|
|
}
|
|
|
|
static void hfi_sys_property_info(struct venus_core *core,
|
|
struct venus_inst *inst, void *packet)
|
|
{
|
|
struct hfi_msg_sys_property_info_pkt *pkt = packet;
|
|
struct device *dev = core->dev;
|
|
|
|
if (!pkt->num_properties) {
|
|
dev_dbg(dev, VDBGL "no properties\n");
|
|
return;
|
|
}
|
|
|
|
switch (pkt->property) {
|
|
case HFI_PROPERTY_SYS_IMAGE_VERSION:
|
|
sys_get_prop_image_version(dev, pkt);
|
|
break;
|
|
default:
|
|
dev_dbg(dev, VDBGL "unknown property data\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void hfi_sys_rel_resource_done(struct venus_core *core,
|
|
struct venus_inst *inst,
|
|
void *packet)
|
|
{
|
|
struct hfi_msg_sys_release_resource_done_pkt *pkt = packet;
|
|
|
|
core->error = pkt->error_type;
|
|
complete(&core->done);
|
|
}
|
|
|
|
static void hfi_sys_ping_done(struct venus_core *core, struct venus_inst *inst,
|
|
void *packet)
|
|
{
|
|
struct hfi_msg_sys_ping_ack_pkt *pkt = packet;
|
|
|
|
core->error = HFI_ERR_NONE;
|
|
|
|
if (pkt->client_data != 0xbeef)
|
|
core->error = HFI_ERR_SYS_FATAL;
|
|
|
|
complete(&core->done);
|
|
}
|
|
|
|
static void hfi_sys_idle_done(struct venus_core *core, struct venus_inst *inst,
|
|
void *packet)
|
|
{
|
|
dev_dbg(core->dev, VDBGL "sys idle\n");
|
|
}
|
|
|
|
static void hfi_sys_pc_prepare_done(struct venus_core *core,
|
|
struct venus_inst *inst, void *packet)
|
|
{
|
|
struct hfi_msg_sys_pc_prep_done_pkt *pkt = packet;
|
|
|
|
dev_dbg(core->dev, VDBGL "pc prepare done (error %x)\n",
|
|
pkt->error_type);
|
|
}
|
|
|
|
static unsigned int
|
|
session_get_prop_profile_level(struct hfi_msg_session_property_info_pkt *pkt,
|
|
struct hfi_profile_level *profile_level)
|
|
{
|
|
struct hfi_profile_level *hfi;
|
|
u32 req_bytes;
|
|
|
|
req_bytes = pkt->shdr.hdr.size - sizeof(*pkt);
|
|
|
|
if (!req_bytes || req_bytes % sizeof(struct hfi_profile_level))
|
|
/* bad packet */
|
|
return HFI_ERR_SESSION_INVALID_PARAMETER;
|
|
|
|
hfi = (struct hfi_profile_level *)&pkt->data[0];
|
|
profile_level->profile = hfi->profile;
|
|
profile_level->level = hfi->level;
|
|
|
|
return HFI_ERR_NONE;
|
|
}
|
|
|
|
static unsigned int
|
|
session_get_prop_buf_req(struct hfi_msg_session_property_info_pkt *pkt,
|
|
struct hfi_buffer_requirements *bufreq)
|
|
{
|
|
struct hfi_buffer_requirements *buf_req;
|
|
u32 req_bytes;
|
|
unsigned int idx = 0;
|
|
|
|
req_bytes = pkt->shdr.hdr.size - sizeof(*pkt);
|
|
|
|
if (!req_bytes || req_bytes % sizeof(*buf_req) || !pkt->data[0])
|
|
/* bad packet */
|
|
return HFI_ERR_SESSION_INVALID_PARAMETER;
|
|
|
|
buf_req = (struct hfi_buffer_requirements *)&pkt->data[0];
|
|
if (!buf_req)
|
|
return HFI_ERR_SESSION_INVALID_PARAMETER;
|
|
|
|
while (req_bytes) {
|
|
memcpy(&bufreq[idx], buf_req, sizeof(*bufreq));
|
|
idx++;
|
|
|
|
if (idx > HFI_BUFFER_TYPE_MAX)
|
|
return HFI_ERR_SESSION_INVALID_PARAMETER;
|
|
|
|
req_bytes -= sizeof(struct hfi_buffer_requirements);
|
|
buf_req++;
|
|
}
|
|
|
|
return HFI_ERR_NONE;
|
|
}
|
|
|
|
static void hfi_session_prop_info(struct venus_core *core,
|
|
struct venus_inst *inst, void *packet)
|
|
{
|
|
struct hfi_msg_session_property_info_pkt *pkt = packet;
|
|
struct device *dev = core->dev;
|
|
union hfi_get_property *hprop = &inst->hprop;
|
|
unsigned int error = HFI_ERR_NONE;
|
|
|
|
if (!pkt->num_properties) {
|
|
error = HFI_ERR_SESSION_INVALID_PARAMETER;
|
|
dev_err(dev, "%s: no properties\n", __func__);
|
|
goto done;
|
|
}
|
|
|
|
switch (pkt->property) {
|
|
case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
|
|
memset(hprop->bufreq, 0, sizeof(hprop->bufreq));
|
|
error = session_get_prop_buf_req(pkt, hprop->bufreq);
|
|
break;
|
|
case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
|
|
memset(&hprop->profile_level, 0, sizeof(hprop->profile_level));
|
|
error = session_get_prop_profile_level(pkt,
|
|
&hprop->profile_level);
|
|
break;
|
|
case HFI_PROPERTY_CONFIG_VDEC_ENTROPY:
|
|
break;
|
|
default:
|
|
dev_dbg(dev, VDBGM "unknown property id:%x\n", pkt->property);
|
|
return;
|
|
}
|
|
|
|
done:
|
|
inst->error = error;
|
|
complete(&inst->done);
|
|
}
|
|
|
|
static void hfi_session_init_done(struct venus_core *core,
|
|
struct venus_inst *inst, void *packet)
|
|
{
|
|
struct hfi_msg_session_init_done_pkt *pkt = packet;
|
|
int rem_bytes;
|
|
u32 error;
|
|
|
|
error = pkt->error_type;
|
|
if (error != HFI_ERR_NONE)
|
|
goto done;
|
|
|
|
if (!IS_V1(core))
|
|
goto done;
|
|
|
|
rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt) + sizeof(u32);
|
|
if (rem_bytes <= 0) {
|
|
error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES;
|
|
goto done;
|
|
}
|
|
|
|
error = hfi_parser(core, inst, pkt->data, rem_bytes);
|
|
done:
|
|
inst->error = error;
|
|
complete(&inst->done);
|
|
}
|
|
|
|
static void hfi_session_load_res_done(struct venus_core *core,
|
|
struct venus_inst *inst, void *packet)
|
|
{
|
|
struct hfi_msg_session_load_resources_done_pkt *pkt = packet;
|
|
|
|
inst->error = pkt->error_type;
|
|
complete(&inst->done);
|
|
}
|
|
|
|
static void hfi_session_flush_done(struct venus_core *core,
|
|
struct venus_inst *inst, void *packet)
|
|
{
|
|
struct hfi_msg_session_flush_done_pkt *pkt = packet;
|
|
|
|
inst->error = pkt->error_type;
|
|
complete(&inst->done);
|
|
if (inst->ops->flush_done)
|
|
inst->ops->flush_done(inst);
|
|
}
|
|
|
|
static void hfi_session_etb_done(struct venus_core *core,
|
|
struct venus_inst *inst, void *packet)
|
|
{
|
|
struct hfi_msg_session_empty_buffer_done_pkt *pkt = packet;
|
|
|
|
inst->error = pkt->error_type;
|
|
inst->ops->buf_done(inst, HFI_BUFFER_INPUT, pkt->input_tag,
|
|
pkt->filled_len, pkt->offset, 0, 0, 0);
|
|
}
|
|
|
|
static void hfi_session_ftb_done(struct venus_core *core,
|
|
struct venus_inst *inst, void *packet)
|
|
{
|
|
u32 session_type = inst->session_type;
|
|
u64 timestamp_us = 0;
|
|
u32 timestamp_hi = 0, timestamp_lo = 0;
|
|
unsigned int error;
|
|
u32 flags = 0, hfi_flags = 0, offset = 0, filled_len = 0;
|
|
u32 pic_type = 0, buffer_type = 0, output_tag = -1;
|
|
|
|
if (session_type == VIDC_SESSION_TYPE_ENC) {
|
|
struct hfi_msg_session_fbd_compressed_pkt *pkt = packet;
|
|
|
|
timestamp_hi = pkt->time_stamp_hi;
|
|
timestamp_lo = pkt->time_stamp_lo;
|
|
hfi_flags = pkt->flags;
|
|
offset = pkt->offset;
|
|
filled_len = pkt->filled_len;
|
|
pic_type = pkt->picture_type;
|
|
output_tag = pkt->output_tag;
|
|
buffer_type = HFI_BUFFER_OUTPUT;
|
|
|
|
error = pkt->error_type;
|
|
} else if (session_type == VIDC_SESSION_TYPE_DEC) {
|
|
struct hfi_msg_session_fbd_uncompressed_plane0_pkt *pkt =
|
|
packet;
|
|
|
|
timestamp_hi = pkt->time_stamp_hi;
|
|
timestamp_lo = pkt->time_stamp_lo;
|
|
hfi_flags = pkt->flags;
|
|
offset = pkt->offset;
|
|
filled_len = pkt->filled_len;
|
|
pic_type = pkt->picture_type;
|
|
output_tag = pkt->output_tag;
|
|
|
|
if (pkt->stream_id == 0)
|
|
buffer_type = HFI_BUFFER_OUTPUT;
|
|
else if (pkt->stream_id == 1)
|
|
buffer_type = HFI_BUFFER_OUTPUT2;
|
|
|
|
error = pkt->error_type;
|
|
} else {
|
|
error = HFI_ERR_SESSION_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (buffer_type != HFI_BUFFER_OUTPUT &&
|
|
buffer_type != HFI_BUFFER_OUTPUT2)
|
|
goto done;
|
|
|
|
if (hfi_flags & HFI_BUFFERFLAG_EOS)
|
|
flags |= V4L2_BUF_FLAG_LAST;
|
|
|
|
switch (pic_type) {
|
|
case HFI_PICTURE_IDR:
|
|
case HFI_PICTURE_I:
|
|
flags |= V4L2_BUF_FLAG_KEYFRAME;
|
|
break;
|
|
case HFI_PICTURE_P:
|
|
flags |= V4L2_BUF_FLAG_PFRAME;
|
|
break;
|
|
case HFI_PICTURE_B:
|
|
flags |= V4L2_BUF_FLAG_BFRAME;
|
|
break;
|
|
case HFI_FRAME_NOTCODED:
|
|
case HFI_UNUSED_PICT:
|
|
case HFI_FRAME_YUV:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (!(hfi_flags & HFI_BUFFERFLAG_TIMESTAMPINVALID) && filled_len) {
|
|
timestamp_us = timestamp_hi;
|
|
timestamp_us = (timestamp_us << 32) | timestamp_lo;
|
|
}
|
|
|
|
done:
|
|
inst->error = error;
|
|
inst->ops->buf_done(inst, buffer_type, output_tag, filled_len,
|
|
offset, flags, hfi_flags, timestamp_us);
|
|
}
|
|
|
|
static void hfi_session_start_done(struct venus_core *core,
|
|
struct venus_inst *inst, void *packet)
|
|
{
|
|
struct hfi_msg_session_start_done_pkt *pkt = packet;
|
|
|
|
inst->error = pkt->error_type;
|
|
complete(&inst->done);
|
|
}
|
|
|
|
static void hfi_session_stop_done(struct venus_core *core,
|
|
struct venus_inst *inst, void *packet)
|
|
{
|
|
struct hfi_msg_session_stop_done_pkt *pkt = packet;
|
|
|
|
inst->error = pkt->error_type;
|
|
complete(&inst->done);
|
|
}
|
|
|
|
static void hfi_session_rel_res_done(struct venus_core *core,
|
|
struct venus_inst *inst, void *packet)
|
|
{
|
|
struct hfi_msg_session_release_resources_done_pkt *pkt = packet;
|
|
|
|
inst->error = pkt->error_type;
|
|
complete(&inst->done);
|
|
}
|
|
|
|
static void hfi_session_rel_buf_done(struct venus_core *core,
|
|
struct venus_inst *inst, void *packet)
|
|
{
|
|
struct hfi_msg_session_release_buffers_done_pkt *pkt = packet;
|
|
|
|
inst->error = pkt->error_type;
|
|
complete(&inst->done);
|
|
}
|
|
|
|
static void hfi_session_end_done(struct venus_core *core,
|
|
struct venus_inst *inst, void *packet)
|
|
{
|
|
struct hfi_msg_session_end_done_pkt *pkt = packet;
|
|
|
|
inst->error = pkt->error_type;
|
|
complete(&inst->done);
|
|
}
|
|
|
|
static void hfi_session_abort_done(struct venus_core *core,
|
|
struct venus_inst *inst, void *packet)
|
|
{
|
|
struct hfi_msg_sys_session_abort_done_pkt *pkt = packet;
|
|
|
|
inst->error = pkt->error_type;
|
|
complete(&inst->done);
|
|
}
|
|
|
|
static void hfi_session_get_seq_hdr_done(struct venus_core *core,
|
|
struct venus_inst *inst, void *packet)
|
|
{
|
|
struct hfi_msg_session_get_sequence_hdr_done_pkt *pkt = packet;
|
|
|
|
inst->error = pkt->error_type;
|
|
complete(&inst->done);
|
|
}
|
|
|
|
struct hfi_done_handler {
|
|
u32 pkt;
|
|
u32 pkt_sz;
|
|
u32 pkt_sz2;
|
|
void (*done)(struct venus_core *, struct venus_inst *, void *);
|
|
bool is_sys_pkt;
|
|
};
|
|
|
|
static const struct hfi_done_handler handlers[] = {
|
|
{.pkt = HFI_MSG_EVENT_NOTIFY,
|
|
.pkt_sz = sizeof(struct hfi_msg_event_notify_pkt),
|
|
.done = hfi_event_notify,
|
|
},
|
|
{.pkt = HFI_MSG_SYS_INIT,
|
|
.pkt_sz = sizeof(struct hfi_msg_sys_init_done_pkt),
|
|
.done = hfi_sys_init_done,
|
|
.is_sys_pkt = true,
|
|
},
|
|
{.pkt = HFI_MSG_SYS_PROPERTY_INFO,
|
|
.pkt_sz = sizeof(struct hfi_msg_sys_property_info_pkt),
|
|
.done = hfi_sys_property_info,
|
|
.is_sys_pkt = true,
|
|
},
|
|
{.pkt = HFI_MSG_SYS_RELEASE_RESOURCE,
|
|
.pkt_sz = sizeof(struct hfi_msg_sys_release_resource_done_pkt),
|
|
.done = hfi_sys_rel_resource_done,
|
|
.is_sys_pkt = true,
|
|
},
|
|
{.pkt = HFI_MSG_SYS_PING_ACK,
|
|
.pkt_sz = sizeof(struct hfi_msg_sys_ping_ack_pkt),
|
|
.done = hfi_sys_ping_done,
|
|
.is_sys_pkt = true,
|
|
},
|
|
{.pkt = HFI_MSG_SYS_IDLE,
|
|
.pkt_sz = sizeof(struct hfi_msg_sys_idle_pkt),
|
|
.done = hfi_sys_idle_done,
|
|
.is_sys_pkt = true,
|
|
},
|
|
{.pkt = HFI_MSG_SYS_PC_PREP,
|
|
.pkt_sz = sizeof(struct hfi_msg_sys_pc_prep_done_pkt),
|
|
.done = hfi_sys_pc_prepare_done,
|
|
.is_sys_pkt = true,
|
|
},
|
|
{.pkt = HFI_MSG_SYS_SESSION_INIT,
|
|
.pkt_sz = sizeof(struct hfi_msg_session_init_done_pkt),
|
|
.done = hfi_session_init_done,
|
|
},
|
|
{.pkt = HFI_MSG_SYS_SESSION_END,
|
|
.pkt_sz = sizeof(struct hfi_msg_session_end_done_pkt),
|
|
.done = hfi_session_end_done,
|
|
},
|
|
{.pkt = HFI_MSG_SESSION_LOAD_RESOURCES,
|
|
.pkt_sz = sizeof(struct hfi_msg_session_load_resources_done_pkt),
|
|
.done = hfi_session_load_res_done,
|
|
},
|
|
{.pkt = HFI_MSG_SESSION_START,
|
|
.pkt_sz = sizeof(struct hfi_msg_session_start_done_pkt),
|
|
.done = hfi_session_start_done,
|
|
},
|
|
{.pkt = HFI_MSG_SESSION_STOP,
|
|
.pkt_sz = sizeof(struct hfi_msg_session_stop_done_pkt),
|
|
.done = hfi_session_stop_done,
|
|
},
|
|
{.pkt = HFI_MSG_SYS_SESSION_ABORT,
|
|
.pkt_sz = sizeof(struct hfi_msg_sys_session_abort_done_pkt),
|
|
.done = hfi_session_abort_done,
|
|
},
|
|
{.pkt = HFI_MSG_SESSION_EMPTY_BUFFER,
|
|
.pkt_sz = sizeof(struct hfi_msg_session_empty_buffer_done_pkt),
|
|
.done = hfi_session_etb_done,
|
|
},
|
|
{.pkt = HFI_MSG_SESSION_FILL_BUFFER,
|
|
.pkt_sz = sizeof(struct hfi_msg_session_fbd_uncompressed_plane0_pkt),
|
|
.pkt_sz2 = sizeof(struct hfi_msg_session_fbd_compressed_pkt),
|
|
.done = hfi_session_ftb_done,
|
|
},
|
|
{.pkt = HFI_MSG_SESSION_FLUSH,
|
|
.pkt_sz = sizeof(struct hfi_msg_session_flush_done_pkt),
|
|
.done = hfi_session_flush_done,
|
|
},
|
|
{.pkt = HFI_MSG_SESSION_PROPERTY_INFO,
|
|
.pkt_sz = sizeof(struct hfi_msg_session_property_info_pkt),
|
|
.done = hfi_session_prop_info,
|
|
},
|
|
{.pkt = HFI_MSG_SESSION_RELEASE_RESOURCES,
|
|
.pkt_sz = sizeof(struct hfi_msg_session_release_resources_done_pkt),
|
|
.done = hfi_session_rel_res_done,
|
|
},
|
|
{.pkt = HFI_MSG_SESSION_GET_SEQUENCE_HEADER,
|
|
.pkt_sz = sizeof(struct hfi_msg_session_get_sequence_hdr_done_pkt),
|
|
.done = hfi_session_get_seq_hdr_done,
|
|
},
|
|
{.pkt = HFI_MSG_SESSION_RELEASE_BUFFERS,
|
|
.pkt_sz = sizeof(struct hfi_msg_session_release_buffers_done_pkt),
|
|
.done = hfi_session_rel_buf_done,
|
|
},
|
|
};
|
|
|
|
void hfi_process_watchdog_timeout(struct venus_core *core)
|
|
{
|
|
event_sys_error(core, EVT_SYS_WATCHDOG_TIMEOUT, NULL);
|
|
}
|
|
|
|
static struct venus_inst *to_instance(struct venus_core *core, u32 session_id)
|
|
{
|
|
struct venus_inst *inst;
|
|
|
|
mutex_lock(&core->lock);
|
|
list_for_each_entry(inst, &core->instances, list)
|
|
if (hash32_ptr(inst) == session_id) {
|
|
mutex_unlock(&core->lock);
|
|
return inst;
|
|
}
|
|
mutex_unlock(&core->lock);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
u32 hfi_process_msg_packet(struct venus_core *core, struct hfi_pkt_hdr *hdr)
|
|
{
|
|
const struct hfi_done_handler *handler;
|
|
struct device *dev = core->dev;
|
|
struct venus_inst *inst;
|
|
bool found = false;
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(handlers); i++) {
|
|
handler = &handlers[i];
|
|
if (handler->pkt != hdr->pkt_type)
|
|
continue;
|
|
found = true;
|
|
break;
|
|
}
|
|
|
|
if (!found)
|
|
return hdr->pkt_type;
|
|
|
|
if (hdr->size && hdr->size < handler->pkt_sz &&
|
|
hdr->size < handler->pkt_sz2) {
|
|
dev_err(dev, "bad packet size (%d should be %d, pkt type:%x)\n",
|
|
hdr->size, handler->pkt_sz, hdr->pkt_type);
|
|
|
|
return hdr->pkt_type;
|
|
}
|
|
|
|
if (handler->is_sys_pkt) {
|
|
inst = NULL;
|
|
} else {
|
|
struct hfi_session_pkt *pkt;
|
|
|
|
pkt = (struct hfi_session_pkt *)hdr;
|
|
inst = to_instance(core, pkt->shdr.session_id);
|
|
|
|
if (!inst)
|
|
dev_warn(dev, "no valid instance(pkt session_id:%x, pkt:%x)\n",
|
|
pkt->shdr.session_id,
|
|
handler ? handler->pkt : 0);
|
|
|
|
/*
|
|
* Event of type HFI_EVENT_SYS_ERROR will not have any session
|
|
* associated with it
|
|
*/
|
|
if (!inst && hdr->pkt_type != HFI_MSG_EVENT_NOTIFY) {
|
|
dev_err(dev, "got invalid session id:%x\n",
|
|
pkt->shdr.session_id);
|
|
goto invalid_session;
|
|
}
|
|
}
|
|
|
|
handler->done(core, inst, hdr);
|
|
|
|
invalid_session:
|
|
return hdr->pkt_type;
|
|
}
|