driver: video: handle input port settings change

add support for input port settings change raised
by fw. update driver subscribed port settings
properties with instance. Raise event to client.
Release, get, create and queue input internal buffers.
Send resume commond to fw on input port.
Add support to destroy internal buffers.

Change-Id: Ic979cf2d0c7298b8083347173a973d553ed52af8
Signed-off-by: Darshana Patil <darshana@codeaurora.org>
This commit is contained in:
Darshana Patil
2020-11-10 16:41:47 -08:00
parent 9f4ffee965
commit 3858225faf
9 changed files with 591 additions and 90 deletions

View File

@@ -905,6 +905,10 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
DEFAULT_VIDEO_CONCEAL_COLOR_BLACK,
V4L2_CID_MPEG_VIDEO_MUTE_YUV,
HFI_PROP_CONCEAL_COLOR_10BIT},
{STAGE, DEC|ENC, CODECS_ALL, 1, 2, 1, 2},
{PIPE, DEC|ENC, CODECS_ALL, 1, 4, 1, 4},
{POC, DEC, H264, 0, 1, 1, 0},
};
/*

View File

@@ -18,5 +18,7 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
int msm_vdec_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f);
int msm_vdec_inst_init(struct msm_vidc_inst *inst);
int msm_vdec_input_port_settings_change(struct msm_vidc_inst *inst);
int msm_vdec_output_port_settings_change(struct msm_vidc_inst *inst);
#endif // _MSM_VDEC_H_

View File

@@ -132,6 +132,8 @@ int msm_vidc_map_driver_buf(struct msm_vidc_inst *inst,
int msm_vidc_put_driver_buf(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buf);
int msm_vidc_queue_buffer(struct msm_vidc_inst *inst, struct vb2_buffer *vb2);
int msm_vidc_destroy_internal_buffer(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buffer);
struct msm_vidc_buffer *get_meta_buffer(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *vbuf);
struct msm_vidc_inst *get_inst(struct msm_vidc_core *core,

View File

@@ -111,8 +111,7 @@ struct msm_vidc_inst {
bool subscribed_output_psc;
bool subscribed_input_prop;
bool subscribed_output_prop;
struct msm_vidc_subscription_params vidc_subcr[MAX_PORT];
struct msm_vidc_subscription_params hfi_subcr[MAX_PORT];
struct msm_vidc_subscription_params subcr_params[MAX_PORT];
struct msm_vidc_decode_batch decode_batch;
struct msm_vidc_decode_vpp_delay decode_vpp_delay;
struct msm_vidc_session_idle session_idle;
@@ -124,6 +123,9 @@ struct msm_vidc_inst {
struct msm_vidc_debug debug;
struct msm_vidc_inst_capability *capabilities;
struct completion completions[MAX_SIGNAL];
u32 hfi_cmd_type;
u32 hfi_port;
};
#endif // _MSM_VIDC_INST_H_

View File

@@ -323,6 +323,9 @@ enum msm_vidc_inst_capability_type {
DISPLAY_DELAY,
CONCEAL_COLOR_8BIT,
CONCEAL_COLOR_10BIT,
STAGE,
PIPE,
POC,
INST_CAP_MAX,
};
@@ -539,16 +542,17 @@ struct msm_vidc_properties {
};
struct msm_vidc_subscription_params {
u32 align_width;
u32 align_height;
struct msm_vidc_crop crop;
struct msm_vidc_color_info color_info;
u32 bitstream_resolution;
u64 crop_offsets;
u32 bit_depth;
u32 cabac;
u32 interlace;
u32 min_count;
u32 coded_frames;
u32 fw_min_count;
u32 pic_order_cnt;
u32 color_info;
u32 profile;
u32 level;
u32 tier;
};
struct msm_vidc_decode_vpp_delay {

View File

@@ -82,6 +82,7 @@ static int msm_vdec_set_bitstream_resolution(struct msm_vidc_inst *inst,
s_vpr_h(inst->sid, "%s: width: %d height: %d\n", __func__,
inst->fmts[INPUT_PORT].fmt.pix_mp.width,
inst->fmts[INPUT_PORT].fmt.pix_mp.height);
inst->subcr_params[port].bitstream_resolution = resolution;
rc = venus_hfi_session_property(inst,
HFI_PROP_BITSTREAM_RESOLUTION,
HFI_HOST_FLAGS_NONE,
@@ -135,7 +136,7 @@ static int msm_vdec_set_crop_offsets(struct msm_vidc_inst *inst,
{
int rc = 0;
u32 left_offset, top_offset, right_offset, bottom_offset;
u32 payload[2];
u64 payload;
if (inst->fmts[INPUT_PORT].fmt.pix_mp.width <
inst->crop.width)
@@ -152,16 +153,17 @@ static int msm_vdec_set_crop_offsets(struct msm_vidc_inst *inst,
bottom_offset = (inst->fmts[INPUT_PORT].fmt.pix_mp.height -
inst->crop.height);
payload[0] = right_offset << 16 | bottom_offset;
payload[1] = left_offset << 16 | top_offset;
payload = (u64)right_offset << 48 | (u64)bottom_offset << 32 |
(u64)left_offset << 16 | top_offset;
s_vpr_h(inst->sid, "%s: left_offset: %d top_offset: %d "
"right_offset: %d bottom_offset: %d", __func__,
left_offset, top_offset, right_offset, bottom_offset);
inst->subcr_params[port].crop_offsets = payload;
rc = venus_hfi_session_property(inst,
HFI_PROP_CROP_OFFSETS,
HFI_HOST_FLAGS_NONE,
get_hfi_port(inst, port),
HFI_PAYLOAD_U64,
HFI_PAYLOAD_64_PACKED,
&payload,
sizeof(u64));
if (rc)
@@ -186,6 +188,8 @@ static int msm_vdec_set_bit_depth(struct msm_vidc_inst *inst,
if (colorformat == V4L2_PIX_FMT_VIDC_P010 ||
colorformat == V4L2_PIX_FMT_VIDC_TP10C)
bitdepth = 10 << 16 | 10;
inst->subcr_params[port].bit_depth = bitdepth;
s_vpr_h(inst->sid, "%s: bit depth: %d", __func__, bitdepth);
rc = venus_hfi_session_property(inst,
HFI_PROP_LUMA_CHROMA_BIT_DEPTH,
@@ -214,6 +218,8 @@ static int msm_vdec_set_cabac(struct msm_vidc_inst *inst,
rc = msm_vidc_v4l2_menu_to_hfi(inst, ENTROPY_MODE, &cabac);
if (rc)
return rc;
inst->subcr_params[port].cabac = cabac;
s_vpr_h(inst->sid, "%s: entropy mode: %d", __func__, cabac);
rc = venus_hfi_session_property(inst,
HFI_PROP_CABAC_SESSION,
@@ -241,6 +247,7 @@ static int msm_vdec_set_coded_frames(struct msm_vidc_inst *inst,
/* (mb_adaptive_frame_field_flag << 1) | frame_mbs_only_flag */
coded_frames = 0;
inst->subcr_params[port].coded_frames = coded_frames;
s_vpr_h(inst->sid, "%s: coded frames: %d", __func__, coded_frames);
rc = venus_hfi_session_property(inst,
HFI_PROP_CODED_FRAMES,
@@ -267,6 +274,7 @@ static int msm_vdec_set_min_output_count(struct msm_vidc_inst *inst,
}
min_output = inst->buffers.output.min_count;
inst->subcr_params[port].fw_min_count = min_output;
s_vpr_h(inst->sid, "%s: firmware min output count: %d",
__func__, min_output);
rc = venus_hfi_session_property(inst,
@@ -293,6 +301,7 @@ static int msm_vdec_set_picture_order_count(struct msm_vidc_inst *inst,
return -EINVAL;
}
inst->subcr_params[port].pic_order_cnt = poc;
s_vpr_h(inst->sid, "%s: picture order count: %d", __func__, poc);
rc = venus_hfi_session_property(inst,
HFI_PROP_PIC_ORDER_CNT_TYPE,
@@ -311,7 +320,7 @@ static int msm_vdec_set_colorspace(struct msm_vidc_inst *inst,
enum msm_vidc_port_type port)
{
int rc = 0;
u32 colorspace;
u32 colorspace, xfer_func, ycbcr_enc, color_info;
if (port != INPUT_PORT && port != OUTPUT_PORT) {
s_vpr_e(inst->sid, "%s: invalid port %d\n", __func__, port);
@@ -319,13 +328,19 @@ static int msm_vdec_set_colorspace(struct msm_vidc_inst *inst,
}
colorspace = inst->fmts[OUTPUT_PORT].fmt.pix_mp.colorspace;
s_vpr_h(inst->sid, "%s: colorspace: %d", __func__, colorspace);
xfer_func = inst->fmts[OUTPUT_PORT].fmt.pix_mp.xfer_func;
ycbcr_enc = inst->fmts[OUTPUT_PORT].fmt.pix_mp.ycbcr_enc;
color_info = ((ycbcr_enc << 16) & 0xFF0000) |
((xfer_func << 8) & 0xFF00) | (colorspace & 0xFF);
inst->subcr_params[port].color_info = color_info;
s_vpr_h(inst->sid, "%s: color info: %d", __func__, color_info);
rc = venus_hfi_session_property(inst,
HFI_PROP_SIGNAL_COLOR_INFO,
HFI_HOST_FLAGS_NONE,
get_hfi_port(inst, port),
HFI_PAYLOAD_U32,
&colorspace,
&color_info,
sizeof(u32));
if (rc)
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
@@ -345,6 +360,7 @@ static int msm_vdec_set_profile(struct msm_vidc_inst *inst,
}
profile = inst->capabilities->cap[PROFILE].value;
inst->subcr_params[port].profile = profile;
s_vpr_h(inst->sid, "%s: profile: %d", __func__, profile);
rc = venus_hfi_session_property(inst,
HFI_PROP_PROFILE,
@@ -371,6 +387,7 @@ static int msm_vdec_set_level(struct msm_vidc_inst *inst,
}
level = inst->capabilities->cap[LEVEL].value;
inst->subcr_params[port].level = level;
s_vpr_h(inst->sid, "%s: level: %d", __func__, level);
rc = venus_hfi_session_property(inst,
HFI_PROP_LEVEL,
@@ -397,6 +414,7 @@ static int msm_vdec_set_tier(struct msm_vidc_inst *inst,
}
tier = inst->capabilities->cap[HEVC_TIER].value;
inst->subcr_params[port].tier = tier;
s_vpr_h(inst->sid, "%s: tier: %d", __func__, tier);
rc = venus_hfi_session_property(inst,
HFI_PROP_TIER,
@@ -818,7 +836,7 @@ static int msm_vdec_queue_input_internal_buffers(struct msm_vidc_inst *inst)
return 0;
}
/*
static int msm_vdec_release_input_internal_buffers(struct msm_vidc_inst *inst)
{
int rc = 0;
@@ -829,21 +847,26 @@ static int msm_vdec_release_input_internal_buffers(struct msm_vidc_inst *inst)
return -EINVAL;
}
rc = msm_vidc_release_internal_buffers(inst, MSM_VIDC_BUF_SCRATCH);
rc = msm_vidc_release_internal_buffers(inst, MSM_VIDC_BUF_BIN);
if (rc)
return rc;
rc = msm_vidc_release_internal_buffers(inst, MSM_VIDC_BUF_SCRATCH_1);
rc = msm_vidc_release_internal_buffers(inst, MSM_VIDC_BUF_COMV);
if (rc)
return rc;
rc = msm_vidc_release_internal_buffers(inst, MSM_VIDC_BUF_PERSIST_1);
rc = msm_vidc_release_internal_buffers(inst, MSM_VIDC_BUF_NON_COMV);
if (rc)
return rc;
rc = msm_vidc_release_internal_buffers(inst, MSM_VIDC_BUF_LINE);
if (rc)
return rc;
rc = msm_vidc_release_internal_buffers(inst, MSM_VIDC_BUF_PERSIST);
if (rc)
return rc;
return 0;
}
*/
static int msm_vdec_port_settings_subscription(struct msm_vidc_inst *inst,
static int msm_vdec_subscribe_port_settings_change(struct msm_vidc_inst *inst,
enum msm_vidc_port_type port)
{
int rc = 0;
@@ -918,7 +941,7 @@ static int msm_vdec_port_settings_subscription(struct msm_vidc_inst *inst,
return rc;
}
static int msm_vdec_property_subscription(struct msm_vidc_inst *inst,
static int msm_vdec_subscribe_property(struct msm_vidc_inst *inst,
enum msm_vidc_port_type port)
{
int rc = 0;
@@ -948,7 +971,7 @@ static int msm_vdec_property_subscription(struct msm_vidc_inst *inst,
return rc;
}
static int msm_vdec_metadata_subscription(struct msm_vidc_inst *inst,
static int msm_vdec_subscribe_metadata(struct msm_vidc_inst *inst,
enum msm_vidc_port_type port)
{
int rc = 0;
@@ -978,7 +1001,7 @@ static int msm_vdec_metadata_subscription(struct msm_vidc_inst *inst,
return rc;
}
static int msm_vdec_metadata_delivery(struct msm_vidc_inst *inst,
static int msm_vdec_set_delivery_mode_metadata(struct msm_vidc_inst *inst,
enum msm_vidc_port_type port)
{
int rc = 0;
@@ -1008,6 +1031,125 @@ static int msm_vdec_metadata_delivery(struct msm_vidc_inst *inst,
return rc;
}
static int msm_vdec_session_resume(struct msm_vidc_inst *inst,
enum msm_vidc_port_type port)
{
int rc = 0;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
d_vpr_h("%s()\n", __func__);
rc = venus_hfi_session_command(inst,
HFI_CMD_RESUME,
port,
HFI_PAYLOAD_NONE,
NULL,
0);
return rc;
}
static msm_vdec_update_input_properties(struct msm_vidc_inst *inst)
{
struct msm_vidc_subscription_params subsc_params;
u32 width, height;
subsc_params = inst->subcr_params[INPUT_PORT];
width = (subsc_params.bitstream_resolution &
HFI_BITMASK_BITSTREAM_WIDTH) >> 16;
height = subsc_params.bitstream_resolution &
HFI_BITMASK_BITSTREAM_HEIGHT;
inst->fmts[INPUT_PORT].fmt.pix_mp.width = width;
inst->fmts[INPUT_PORT].fmt.pix_mp.height = height;
inst->fmts[OUTPUT_PORT].fmt.pix_mp.width = VENUS_Y_STRIDE(
v4l2_colorformat_to_media(
inst->fmts[OUTPUT_PORT].fmt.pix_mp.pixelformat, __func__),
width);
inst->fmts[OUTPUT_PORT].fmt.pix_mp.height = VENUS_Y_SCANLINES(
v4l2_colorformat_to_media(
inst->fmts[OUTPUT_PORT].fmt.pix_mp.pixelformat, __func__),
height);
//inst->fmts[OUTPUT_PORT].fmt.pix_mp.bytesperline =
//inst->fmts[OUTPUT_PORT].fmt.pix_mp.width;
inst->fmts[OUTPUT_PORT].fmt.pix_mp.colorspace =
(subsc_params.color_info & 0xFF0000) >> 16;
inst->fmts[OUTPUT_PORT].fmt.pix_mp.xfer_func =
(subsc_params.color_info & 0xFF00) >> 8;
inst->fmts[OUTPUT_PORT].fmt.pix_mp.ycbcr_enc =
subsc_params.color_info & 0xFF;
inst->buffers.output.min_count = subsc_params.fw_min_count;
inst->crop.top = subsc_params.crop_offsets & 0xFFFF;
inst->crop.left = (subsc_params.crop_offsets >> 16) & 0xFFFF;
inst->crop.height = inst->fmts[INPUT_PORT].fmt.pix_mp.height -
((subsc_params.crop_offsets >> 32) & 0xFFFF);
inst->crop.width = inst->fmts[INPUT_PORT].fmt.pix_mp.width -
((subsc_params.crop_offsets >> 48) & 0xFFFF);
inst->capabilities->cap[PROFILE].value = subsc_params.profile;
inst->capabilities->cap[LEVEL].value = subsc_params.level;
inst->capabilities->cap[HEVC_TIER].value = subsc_params.tier;
inst->capabilities->cap[ENTROPY_MODE].value = subsc_params.cabac;
inst->capabilities->cap[POC].value = subsc_params.pic_order_cnt;
return 0;
}
int msm_vdec_input_port_settings_change(struct msm_vidc_inst *inst)
{
u32 rc = 0;
struct v4l2_event event = {0};
if (!inst->vb2q[INPUT_PORT].streaming) {
s_vpr_e(inst->sid, "%s: input port not streaming\n",
__func__);
return 0;
}
rc = msm_vdec_update_input_properties(inst);
if (rc)
return rc;
event.type = V4L2_EVENT_SRC_CH_RESOLUTION;//todo
event.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION;
v4l2_event_queue_fh(&inst->event_handler, &event);
rc = msm_vdec_release_input_internal_buffers(inst);
if (rc)
return rc;
rc = msm_vdec_get_input_internal_buffers(inst);
if (rc)
return rc;
rc = msm_vdec_create_input_internal_buffers(inst);
if (rc)
return rc;
rc = msm_vdec_queue_input_internal_buffers(inst);
if (rc)
return rc;
rc = msm_vdec_session_resume(inst, INPUT_PORT);
if (rc)
return rc;
return rc;
}
int msm_vdec_output_port_settings_change(struct msm_vidc_inst *inst)
{
//todo
return 0;
}
int msm_vdec_stop_input(struct msm_vidc_inst *inst)
{
int rc = 0;
@@ -1070,15 +1212,15 @@ int msm_vdec_start_input(struct msm_vidc_inst *inst)
if (rc)
goto error;
rc = msm_vdec_port_settings_subscription(inst, INPUT_PORT);
rc = msm_vdec_subscribe_port_settings_change(inst, INPUT_PORT);
if (rc)
return rc;
rc = msm_vdec_property_subscription(inst, INPUT_PORT);
rc = msm_vdec_subscribe_property(inst, INPUT_PORT);
if (rc)
return rc;
rc = msm_vdec_metadata_delivery(inst, INPUT_PORT);
rc = msm_vdec_set_delivery_mode_metadata(inst, INPUT_PORT);
if (rc)
return rc;
@@ -1125,11 +1267,11 @@ int msm_vdec_start_output(struct msm_vidc_inst *inst)
if (rc)
goto error;
rc = msm_vdec_port_settings_subscription(inst, OUTPUT_PORT);
rc = msm_vdec_subscribe_port_settings_change(inst, OUTPUT_PORT);
if (rc)
return rc;
rc = msm_vdec_metadata_subscription(inst, OUTPUT_PORT);
rc = msm_vdec_subscribe_metadata(inst, OUTPUT_PORT);
if (rc)
return rc;

View File

@@ -789,6 +789,8 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
inst->domain = session_type;
inst->state = MSM_VIDC_OPEN;
inst->request = false;
inst->hfi_cmd_type = 0;
inst->hfi_port = 0;
for (i = 0; i < MAX_SIGNAL; i++)
init_completion(&inst->completions[i]);

View File

@@ -34,14 +34,14 @@ void print_vidc_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
mbuf = get_meta_buffer(inst, vbuf);
if (!mbuf)
dprintk(tag, inst->sid,
"%s: %s: idx %2d fd %3d off %d daddr %#x size %d filled %d flags %#x ts %lld attr %#x\n",
"%s: %s: idx %2d fd %3d off %d daddr %#llx size %d filled %d flags %#x ts %lld attr %#x\n",
str, vbuf->type == MSM_VIDC_BUF_INPUT ? "INPUT" : "OUTPUT",
vbuf->index, vbuf->fd, vbuf->data_offset,
vbuf->device_addr, vbuf->buffer_size, vbuf->data_size,
vbuf->flags, vbuf->timestamp, vbuf->attr);
else
dprintk(tag, inst->sid,
"%s: %s: idx %2d fd %3d off %d daddr %#x size %d filled %d flags %#x ts %lld attr %#x meta: fd %3d daddr %#x size %d\n",
"%s: %s: idx %2d fd %3d off %d daddr %#llx size %d filled %d flags %#x ts %lld attr %#x meta: fd %3d daddr %#llx size %d\n",
str, vbuf->type == MSM_VIDC_BUF_INPUT ? "INPUT" : "OUTPUT",
vbuf->index, vbuf->fd, vbuf->data_offset,
vbuf->device_addr, vbuf->buffer_size, vbuf->data_size,
@@ -784,14 +784,78 @@ int msm_vidc_queue_buffer(struct msm_vidc_inst *inst, struct vb2_buffer *vb2)
return rc;
}
int msm_vidc_create_internal_buffers(struct msm_vidc_inst *inst,
enum msm_vidc_buffer_type buffer_type)
int msm_vidc_destroy_internal_buffer(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buffer)
{
struct msm_vidc_buffers *buffers;
struct msm_vidc_allocations *allocations;
struct msm_vidc_mappings *mappings;
struct msm_vidc_alloc *alloc, *alloc_dummy;
struct msm_vidc_map *map, *map_dummy;
struct msm_vidc_buffer *buf, *dummy;
if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
if (!is_internal_buffer(buffer->type)) {
s_vpr_e(inst->sid, "%s: buffer type %#x is not internal\n",
__func__, buffer->type);
return 0;
}
s_vpr_h(inst->sid,
"%s: destroy buffer_type %#x, size %d device_addr %#x\n",
__func__, buffer->type, buffer->buffer_size,
buffer->device_addr);
buffers = msm_vidc_get_buffers(inst, buffer->type, __func__);
if (!buffers)
return -EINVAL;
allocations = msm_vidc_get_allocations(inst, buffer->type, __func__);
if (!allocations)
return -EINVAL;
mappings = msm_vidc_get_mappings(inst, buffer->type, __func__);
if (!mappings)
return -EINVAL;
list_for_each_entry_safe(map, map_dummy, &mappings->list, list) {
if (map->dmabuf == buffer->dmabuf) {
msm_vidc_memory_unmap(inst->core, map);
list_del(&map->list);
kfree(map);
}
}
list_for_each_entry_safe(alloc, alloc_dummy, &allocations->list, list) {
if (alloc->dmabuf == buffer->dmabuf) {
msm_vidc_memory_free(inst->core, alloc);
list_del(&alloc->list);
kfree(alloc);
}
}
list_for_each_entry_safe(buf, dummy, &buffers->list, list) {
if (buf->dmabuf == buffer->dmabuf) {
list_del(&buf->list);
kfree(buf);
}
}
return 0;
}
int msm_vidc_create_internal_buffer(struct msm_vidc_inst *inst,
enum msm_vidc_buffer_type buffer_type, u32 index)
{
int rc = 0;
struct msm_vidc_buffers *buffers;
struct msm_vidc_allocations *allocations;
struct msm_vidc_mappings *mappings;
int i;
struct msm_vidc_buffer *buffer;
struct msm_vidc_alloc *alloc;
struct msm_vidc_map *map;
d_vpr_h("%s()\n", __func__);
if (!inst || !inst->core) {
@@ -814,67 +878,85 @@ int msm_vidc_create_internal_buffers(struct msm_vidc_inst *inst,
if (!mappings)
return -EINVAL;
for (i = 0; i < buffers->min_count; i++) {
struct msm_vidc_buffer *buffer;
struct msm_vidc_alloc *alloc;
struct msm_vidc_map *map;
if (!buffers->size) {
s_vpr_e(inst->sid, "%s: invalid buffer %#x\n",
__func__, buffer_type);
return -EINVAL;
}
buffer = kzalloc(sizeof(struct msm_vidc_buffer), GFP_KERNEL);
if (!buffer) {
s_vpr_e(inst->sid, "%s: buf alloc failed\n", __func__);
return -ENOMEM;
}
INIT_LIST_HEAD(&buffer->list);
buffer->valid = true;
buffer->type = buffer_type;
buffer->index = i;
buffer->buffer_size = buffers->size;
list_add_tail(&buffer->list, &buffers->list);
alloc = kzalloc(sizeof(struct msm_vidc_alloc), GFP_KERNEL);
if (!alloc) {
s_vpr_e(inst->sid, "%s: alloc failed\n", __func__);
return -ENOMEM;
}
INIT_LIST_HEAD(&alloc->list);
alloc->type = buffer_type;
alloc->region = msm_vidc_get_buffer_region(inst,
buffer_type, __func__);
alloc->size = buffer->buffer_size;
rc = msm_vidc_memory_alloc(inst->core, alloc);
if (rc)
return -ENOMEM;
list_add_tail(&alloc->list, &allocations->list);
map = kzalloc(sizeof(struct msm_vidc_map), GFP_KERNEL);
if (!map) {
s_vpr_e(inst->sid, "%s: map alloc failed\n", __func__);
return -ENOMEM;
}
INIT_LIST_HEAD(&map->list);
map->type = alloc->type;
map->region = alloc->region;
map->dmabuf = alloc->dmabuf;
rc = msm_vidc_memory_map(inst->core, map);
if (rc)
return -ENOMEM;
list_add_tail(&map->list, &mappings->list);
buffer->device_addr = map->device_addr;
s_vpr_h(inst->sid,
"%s: created buffer_type %#x, size %d device_addr %#x\n",
__func__, buffer_type, buffers->size,
buffer->device_addr);
if (!buffers->size) {
s_vpr_e(inst->sid, "%s: invalid buffer %#x\n",
__func__, buffer_type);
return -EINVAL;
}
buffer = kzalloc(sizeof(struct msm_vidc_buffer), GFP_KERNEL);
if (!buffer) {
s_vpr_e(inst->sid, "%s: buf alloc failed\n", __func__);
return -ENOMEM;
}
INIT_LIST_HEAD(&buffer->list);
buffer->valid = true;
buffer->type = buffer_type;
buffer->index = index;
buffer->buffer_size = buffers->size;
list_add_tail(&buffer->list, &buffers->list);
alloc = kzalloc(sizeof(struct msm_vidc_alloc), GFP_KERNEL);
if (!alloc) {
s_vpr_e(inst->sid, "%s: alloc failed\n", __func__);
return -ENOMEM;
}
INIT_LIST_HEAD(&alloc->list);
alloc->type = buffer_type;
alloc->region = msm_vidc_get_buffer_region(inst,
buffer_type, __func__);
alloc->size = buffer->buffer_size;
rc = msm_vidc_memory_alloc(inst->core, alloc);
if (rc)
return -ENOMEM;
list_add_tail(&alloc->list, &allocations->list);
map = kzalloc(sizeof(struct msm_vidc_map), GFP_KERNEL);
if (!map) {
s_vpr_e(inst->sid, "%s: map alloc failed\n", __func__);
return -ENOMEM;
}
INIT_LIST_HEAD(&map->list);
map->type = alloc->type;
map->region = alloc->region;
map->dmabuf = alloc->dmabuf;
rc = msm_vidc_memory_map(inst->core, map);
if (rc)
return -ENOMEM;
list_add_tail(&map->list, &mappings->list);
buffer->dmabuf = alloc->dmabuf;
buffer->device_addr = map->device_addr;
s_vpr_h(inst->sid,
"%s: created buffer_type %#x, size %d device_addr %#x\n",
__func__, buffer_type, buffers->size,
buffer->device_addr);
return 0;
}
int msm_vidc_create_internal_buffers(struct msm_vidc_inst *inst,
enum msm_vidc_buffer_type buffer_type)
{
int rc = 0;
struct msm_vidc_buffers *buffers;
int i;
d_vpr_h("%s()\n", __func__);
if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
buffers = msm_vidc_get_buffers(inst, buffer_type, __func__);
if (!buffers)
return -EINVAL;
for (i = 0; i < buffers->min_count; i++)
rc = msm_vidc_create_internal_buffer(inst, buffer_type, i);
return rc;
}
int msm_vidc_queue_internal_buffers(struct msm_vidc_inst *inst,
enum msm_vidc_buffer_type buffer_type)
{

View File

@@ -8,6 +8,46 @@
#include "venus_hfi_response.h"
#include "msm_vidc_debug.h"
#include "msm_vidc_driver.h"
#include "msm_vdec.h"
u32 vidc_port_from_hfi(struct msm_vidc_inst *inst,
enum hfi_packet_port_type hfi_port)
{
enum msm_vidc_port_type port = MAX_PORT;
if (is_decode_session(inst)) {
switch (hfi_port) {
case HFI_PORT_BITSTREAM:
port = INPUT_PORT;
break;
case HFI_PORT_RAW:
port = OUTPUT_PORT;
break;
default:
s_vpr_e(inst->sid, "%s: invalid hfi port type %d\n",
__func__, hfi_port);
break;
}
} else if (is_encode_session(inst)) {
switch (hfi_port) {
case HFI_PORT_RAW:
port = INPUT_PORT;
break;
case HFI_PORT_BITSTREAM:
port = OUTPUT_PORT;
break;
default:
s_vpr_e(inst->sid, "%s: invalid hfi port type %d\n",
__func__, hfi_port);
break;
}
} else {
s_vpr_e(inst->sid, "%s: invalid domain %#x\n",
__func__, inst->domain);
}
return port;
}
bool is_valid_hfi_port(struct msm_vidc_inst *inst, u32 port,
const char *func)
@@ -426,6 +466,151 @@ static int handle_output_metadata_buffer(struct msm_vidc_inst *inst,
return rc;
}
static int handle_persist_buffer(struct msm_vidc_inst *inst,
struct hfi_buffer *buffer)
{
int rc = 0;
struct msm_vidc_buffers *buffers;
struct msm_vidc_buffer *buf;
bool found;
buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_PERSIST, __func__);
if (!buffers)
return -EINVAL;
found = false;
list_for_each_entry(buf, &buffers->list, list) {
if (buf->device_addr == buffer->base_address) {
found = true;
break;
}
}
if (found) {
rc = msm_vidc_destroy_internal_buffer(inst, buf);
} else {
s_vpr_e(inst->sid, "%s: invalid idx %d daddr %#x\n",
__func__, buffer->index, buffer->base_address);
return -EINVAL;
}
return rc;
}
static int handle_line_buffer(struct msm_vidc_inst *inst,
struct hfi_buffer *buffer)
{
int rc = 0;
struct msm_vidc_buffers *buffers;
struct msm_vidc_buffer *buf;
bool found;
buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_LINE, __func__);
if (!buffers)
return -EINVAL;
found = false;
list_for_each_entry(buf, &buffers->list, list) {
if (buf->device_addr == buffer->base_address) {
found = true;
break;
}
}
if (found) {
rc = msm_vidc_destroy_internal_buffer(inst, buf);
} else {
s_vpr_e(inst->sid, "%s: invalid idx %d daddr %#x\n",
__func__, buffer->index, buffer->base_address);
return -EINVAL;
}
return rc;
}
static int handle_non_comv_buffer(struct msm_vidc_inst *inst,
struct hfi_buffer *buffer)
{
int rc = 0;
struct msm_vidc_buffers *buffers;
struct msm_vidc_buffer *buf;
bool found;
buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_NON_COMV, __func__);
if (!buffers)
return -EINVAL;
found = false;
list_for_each_entry(buf, &buffers->list, list) {
if (buf->device_addr == buffer->base_address) {
found = true;
break;
}
}
if (found) {
rc = msm_vidc_destroy_internal_buffer(inst, buf);
} else {
s_vpr_e(inst->sid, "%s: invalid idx %d daddr %#x\n",
__func__, buffer->index, buffer->base_address);
return -EINVAL;
}
return rc;
}
static int handle_comv_buffer(struct msm_vidc_inst *inst,
struct hfi_buffer *buffer)
{
int rc = 0;
struct msm_vidc_buffers *buffers;
struct msm_vidc_buffer *buf;
bool found;
buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_COMV, __func__);
if (!buffers)
return -EINVAL;
found = false;
list_for_each_entry(buf, &buffers->list, list) {
if (buf->device_addr == buffer->base_address) {
found = true;
break;
}
}
if (found) {
rc = msm_vidc_destroy_internal_buffer(inst, buf);
} else {
s_vpr_e(inst->sid, "%s: invalid idx %d daddr %#x\n",
__func__, buffer->index, buffer->base_address);
return -EINVAL;
}
return rc;
}
static int handle_bin_buffer(struct msm_vidc_inst *inst,
struct hfi_buffer *buffer)
{
int rc = 0;
struct msm_vidc_buffers *buffers;
struct msm_vidc_buffer *buf;
bool found;
buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_BIN, __func__);
if (!buffers)
return -EINVAL;
found = false;
list_for_each_entry(buf, &buffers->list, list) {
if (buf->device_addr == buffer->base_address) {
found = true;
break;
}
}
if (found) {
rc = msm_vidc_destroy_internal_buffer(inst, buf);
} else {
s_vpr_e(inst->sid, "%s: invalid idx %d daddr %#x\n",
__func__, buffer->index, buffer->base_address);
return -EINVAL;
}
return rc;
}
static int handle_session_buffer(struct msm_vidc_inst *inst,
struct hfi_packet *pkt)
{
@@ -470,6 +655,16 @@ static int handle_session_buffer(struct msm_vidc_inst *inst,
rc = handle_input_metadata_buffer(inst, buffer);
else if (buf_type == HFI_BUFFER_BITSTREAM)
rc = handle_input_buffer(inst, buffer);
else if (buf_type == HFI_BUFFER_BIN)
rc = handle_bin_buffer(inst, buffer);
else if (buf_type == HFI_BUFFER_COMV)
rc = handle_comv_buffer(inst, buffer);
else if (buf_type == HFI_BUFFER_NON_COMV)
rc = handle_non_comv_buffer(inst, buffer);
else if (buf_type == HFI_BUFFER_LINE)
rc = handle_line_buffer(inst, buffer);
else if (buf_type == HFI_BUFFER_PERSIST)
rc = handle_persist_buffer(inst, buffer);
} else if (port_type == HFI_PORT_RAW) {
if (buf_type == HFI_BUFFER_METADATA)
rc = handle_output_metadata_buffer(inst, buffer);
@@ -552,7 +747,54 @@ static int handle_session_command(struct msm_vidc_inst *inst,
static int handle_session_property(struct msm_vidc_inst *inst,
struct hfi_packet *pkt)
{
u32 port;
u32 *payload_ptr;
s_vpr_h(inst->sid, "%s: property type %#x\n", __func__, pkt->type);
port = vidc_port_from_hfi(inst, pkt->port);
payload_ptr = (u32 *)((u8 *)pkt + sizeof(struct hfi_packet));
switch (pkt->type) {
case HFI_PROP_BITSTREAM_RESOLUTION:
inst->subcr_params[port].bitstream_resolution = payload_ptr[0];
break;
case HFI_PROP_CROP_OFFSETS:
inst->subcr_params[port].crop_offsets =
(u64)payload_ptr[0] << 32 | payload_ptr[1];
break;
case HFI_PROP_LUMA_CHROMA_BIT_DEPTH:
inst->subcr_params[port].bit_depth = payload_ptr[0];
break;
case HFI_PROP_CABAC_SESSION:
inst->subcr_params[port].cabac = payload_ptr[0];
break;
case HFI_PROP_CODED_FRAMES:
inst->subcr_params[port].coded_frames = payload_ptr[0];
break;
case HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT:
inst->subcr_params[port].fw_min_count = payload_ptr[0];
break;
case HFI_PROP_PIC_ORDER_CNT_TYPE:
inst->subcr_params[port].pic_order_cnt = payload_ptr[0];
break;
case HFI_PROP_SIGNAL_COLOR_INFO:
inst->subcr_params[port].color_info = payload_ptr[0];
break;
case HFI_PROP_PROFILE:
inst->subcr_params[port].profile = payload_ptr[0];
break;
case HFI_PROP_LEVEL:
inst->subcr_params[port].level = payload_ptr[0];
break;
case HFI_PROP_TIER:
inst->subcr_params[port].tier = payload_ptr[0];
break;
default:
s_vpr_e(inst->sid, "%s: invalid port settings property %#x\n",
__func__, pkt->type);
return -EINVAL;
}
return 0;
}
@@ -662,6 +904,8 @@ static int handle_session_response(struct msm_vidc_core *core,
}
mutex_lock(&inst->lock);
inst->hfi_cmd_type = 0;
inst->hfi_port = 0;
pkt = (u8 *)((u8 *)hdr + sizeof(struct hfi_header));
for (i = 0; i < hdr->num_packets; i++) {
@@ -673,6 +917,15 @@ static int handle_session_response(struct msm_vidc_core *core,
packet = (struct hfi_packet *)pkt;
if (packet->type < HFI_CMD_END &&
packet->type > HFI_CMD_BEGIN) {
if (inst->hfi_cmd_type || inst->hfi_port) {
s_vpr_e(inst->sid,
"%s: invalid cmd %d, port %d \n",
__func__, inst->hfi_cmd_type,
inst->hfi_port);
return -EINVAL;
}
inst->hfi_cmd_type = packet->type;
inst->hfi_port = packet->port;
rc = handle_session_command(inst, packet);
} else if (packet->type > HFI_PROP_BEGIN &&
packet->type < HFI_PROP_END) {
@@ -688,6 +941,14 @@ static int handle_session_response(struct msm_vidc_core *core,
}
pkt += packet->size;
}
if (inst->hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {
if (inst->hfi_port == HFI_PORT_BITSTREAM)
rc = msm_vdec_input_port_settings_change(inst);
else if (inst->hfi_port == HFI_PORT_RAW)
rc = msm_vdec_output_port_settings_change(inst);
}
exit:
mutex_unlock(&inst->lock);
put_inst(inst);