// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. */ #include "msm_vdec.h" #include "msm_vidc_internal.h" #include "msm_vidc_common.h" #include "vidc_hfi.h" #include "vidc_hfi_helper.h" #include "vidc_hfi_api.h" #include "msm_vidc_debug.h" #include "msm_vidc_clocks.h" #include "msm_vidc_buffer_calculations.h" #define MIN_NUM_DEC_OUTPUT_BUFFERS 4 #define MIN_NUM_DEC_CAPTURE_BUFFERS 4 /* Y=16(0-9bits), Cb(10-19bits)=Cr(20-29bits)=128, black by default */ #define DEFAULT_VIDEO_CONCEAL_COLOR_BLACK 0x8020010 #define MAX_VP9D_INST_COUNT 6 static const char *const vp8_profile_level[] = { "Unused", "0.0", "1.0", "2.0", "3.0", NULL }; static const char *const vp9_level[] = { "Unused", "1.0", "1.1", "2.0", "2.1", "3.0", "3.1", "4.0", "4.1", "5.0", "5.1", "6.0", "6.1", NULL }; static const char *const mpeg2_profile[] = { "Simple", "Main", "High", NULL }; static const char *const mpeg2_level[] = { "0", "1", "2", "3", NULL }; static struct msm_vidc_ctrl msm_vdec_ctrls[] = { { .id = V4L2_CID_MPEG_VIDC_VIDEO_UNKNOWN, .name = "Invalid control", .type = V4L2_CTRL_TYPE_INTEGER, .minimum = 0, .maximum = 0, .default_value = 0, .step = 1, .qmenu = NULL, }, { .id = V4L2_CID_MPEG_VIDC_VIDEO_DECODE_ORDER, .name = "Decode Order", .type = V4L2_CTRL_TYPE_BOOLEAN, .minimum = V4L2_MPEG_MSM_VIDC_DISABLE, .maximum = V4L2_MPEG_MSM_VIDC_ENABLE, .default_value = V4L2_MPEG_MSM_VIDC_DISABLE, .step = 1, }, { .id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE, .name = "Sync Frame Decode", .type = V4L2_CTRL_TYPE_BOOLEAN, .minimum = V4L2_MPEG_MSM_VIDC_DISABLE, .maximum = V4L2_MPEG_MSM_VIDC_ENABLE, .default_value = V4L2_MPEG_MSM_VIDC_DISABLE, .step = 1, }, { .id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE, .name = "Secure mode", .type = V4L2_CTRL_TYPE_BOOLEAN, .minimum = V4L2_MPEG_MSM_VIDC_DISABLE, .maximum = V4L2_MPEG_MSM_VIDC_ENABLE, .default_value = V4L2_MPEG_MSM_VIDC_DISABLE, .step = 1, }, { .id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA, .name = "Extradata Type", .type = V4L2_CTRL_TYPE_BITMASK, .minimum = EXTRADATA_NONE, .maximum = EXTRADATA_DEFAULT | EXTRADATA_ADVANCED, .default_value = EXTRADATA_DEFAULT, .qmenu = NULL, }, { .id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE, .name = "Video decoder multi stream", .type = V4L2_CTRL_TYPE_BOOLEAN, .minimum = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY, .maximum = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY, .default_value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY, .step = 1, .qmenu = NULL, }, { .id = V4L2_CID_MPEG_VIDEO_H264_PROFILE, .name = "H264 Profile", .type = V4L2_CTRL_TYPE_MENU, .minimum = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, .maximum = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH, .default_value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, .menu_skip_mask = ~( (1 << V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | (1 << V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) | (1 << V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH) ), .qmenu = NULL, }, { .id = V4L2_CID_MPEG_VIDEO_H264_LEVEL, .name = "H264 Level", .type = V4L2_CTRL_TYPE_MENU, .minimum = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, .maximum = V4L2_MPEG_VIDEO_H264_LEVEL_6_2, .default_value = V4L2_MPEG_VIDEO_H264_LEVEL_5_0, .menu_skip_mask = ~( (1 << V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | (1 << V4L2_MPEG_VIDEO_H264_LEVEL_1B) | (1 << V4L2_MPEG_VIDEO_H264_LEVEL_1_1) | (1 << V4L2_MPEG_VIDEO_H264_LEVEL_1_2) | (1 << V4L2_MPEG_VIDEO_H264_LEVEL_1_3) | (1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | (1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_1) | (1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_2) | (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_0) | (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_1) | (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_2) | (1 << V4L2_MPEG_VIDEO_H264_LEVEL_5_0) | (1 << V4L2_MPEG_VIDEO_H264_LEVEL_5_1) | (1 << V4L2_MPEG_VIDEO_H264_LEVEL_5_2) | (1 << V4L2_MPEG_VIDEO_H264_LEVEL_6_0) | (1 << V4L2_MPEG_VIDEO_H264_LEVEL_6_1) | (1 << V4L2_MPEG_VIDEO_H264_LEVEL_6_2) ), .qmenu = NULL, }, { .id = V4L2_CID_MPEG_VIDEO_HEVC_PROFILE, .name = "HEVC Profile", .type = V4L2_CTRL_TYPE_MENU, .minimum = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, .maximum = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10, .default_value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, .menu_skip_mask = ~( (1 << V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) | (1 << V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) | (1 << V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10) ), .qmenu = NULL, }, { .id = V4L2_CID_MPEG_VIDEO_HEVC_LEVEL, .name = "HEVC Level", .type = V4L2_CTRL_TYPE_MENU, .minimum = V4L2_MPEG_VIDEO_HEVC_LEVEL_1, .maximum = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2, .default_value = V4L2_MPEG_VIDEO_HEVC_LEVEL_5, .menu_skip_mask = ~( (1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_1) | (1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_2) | (1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) | (1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_3) | (1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) | (1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_4) | (1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) | (1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_5) | (1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) | (1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) | (1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_6) | (1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) | (1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2) ), .qmenu = NULL, }, { .id = V4L2_CID_MPEG_VIDEO_HEVC_TIER, .name = "HEVC Tier", .type = V4L2_CTRL_TYPE_MENU, .minimum = V4L2_MPEG_VIDEO_HEVC_TIER_MAIN, .maximum = V4L2_MPEG_VIDEO_HEVC_TIER_HIGH, .default_value = V4L2_MPEG_VIDEO_HEVC_TIER_HIGH, .menu_skip_mask = ~( (1 << V4L2_MPEG_VIDEO_HEVC_TIER_MAIN) | (1 << V4L2_MPEG_VIDEO_HEVC_TIER_HIGH) ), .qmenu = NULL, }, { .id = V4L2_CID_MPEG_VIDEO_VP8_PROFILE, .name = "VP8 Profile", .type = V4L2_CTRL_TYPE_MENU, .minimum = V4L2_MPEG_VIDEO_VP8_PROFILE_0, .maximum = V4L2_MPEG_VIDEO_VP8_PROFILE_0, .default_value = V4L2_MPEG_VIDEO_VP8_PROFILE_0, .menu_skip_mask = ~(1 << V4L2_MPEG_VIDEO_VP8_PROFILE_0), .qmenu = NULL, }, { .id = V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL, .name = "VP8 Profile Level", .type = V4L2_CTRL_TYPE_MENU, .minimum = V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED, .maximum = V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_3, .default_value = V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_3, .menu_skip_mask = ~( (1 << V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED) | (1 << V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0) | (1 << V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_1) | (1 << V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_2) | (1 << V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_3) ), .qmenu = vp8_profile_level, }, { .id = V4L2_CID_MPEG_VIDEO_VP9_PROFILE, .name = "VP9 Profile", .type = V4L2_CTRL_TYPE_MENU, .minimum = V4L2_MPEG_VIDEO_VP9_PROFILE_0, .maximum = V4L2_MPEG_VIDEO_VP9_PROFILE_2, .default_value = V4L2_MPEG_VIDEO_VP9_PROFILE_0, .menu_skip_mask = ~( (1 << V4L2_MPEG_VIDEO_VP9_PROFILE_0) | (1 << V4L2_MPEG_VIDEO_VP9_PROFILE_1) | (1 << V4L2_MPEG_VIDEO_VP9_PROFILE_2) ), .qmenu = NULL, }, { .id = V4L2_CID_MPEG_VIDC_VIDEO_VP9_LEVEL, .name = "VP9 Level", .type = V4L2_CTRL_TYPE_MENU, .minimum = V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_UNUSED, .maximum = V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_61, .default_value = V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_61, .menu_skip_mask = ~( (1 << V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_UNUSED) | (1 << V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_1) | (1 << V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_11) | (1 << V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_2) | (1 << V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_21) | (1 << V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_3) | (1 << V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_31) | (1 << V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_4) | (1 << V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_41) | (1 << V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_5) | (1 << V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_51) | (1 << V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_6) | (1 << V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_61) ), .qmenu = vp9_level, }, { .id = V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_PROFILE, .name = "MPEG2 Profile", .type = V4L2_CTRL_TYPE_MENU, .minimum = V4L2_MPEG_VIDC_VIDEO_MPEG2_PROFILE_SIMPLE, .maximum = V4L2_MPEG_VIDC_VIDEO_MPEG2_PROFILE_MAIN, .default_value = V4L2_MPEG_VIDC_VIDEO_MPEG2_PROFILE_MAIN, .menu_skip_mask = ~( (1 << V4L2_MPEG_VIDC_VIDEO_MPEG2_PROFILE_SIMPLE) | (1 << V4L2_MPEG_VIDC_VIDEO_MPEG2_PROFILE_MAIN) ), .qmenu = mpeg2_profile, }, { .id = V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_LEVEL, .name = "MPEG2 Level", .type = V4L2_CTRL_TYPE_MENU, .minimum = V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_0, .maximum = V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_2, .default_value = V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_2, .menu_skip_mask = ~( (1 << V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_0) | (1 << V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_1) | (1 << V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_2) ), .qmenu = mpeg2_level, }, { .id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR_8BIT, .name = "Picture concealed color 8bit", .type = V4L2_CTRL_TYPE_INTEGER, .minimum = 0x0, .maximum = 0xff3fcff, .default_value = DEFAULT_VIDEO_CONCEAL_COLOR_BLACK, .step = 1, }, { .id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR_10BIT, .name = "Picture concealed color 10bit", .type = V4L2_CTRL_TYPE_INTEGER, .minimum = 0x0, .maximum = 0x3fffffff, .default_value = DEFAULT_VIDEO_CONCEAL_COLOR_BLACK, .step = 1, }, { .id = V4L2_CID_MPEG_VIDC_VIDEO_BUFFER_SIZE_LIMIT, .name = "Buffer size limit", .type = V4L2_CTRL_TYPE_INTEGER, .minimum = 0, .maximum = INT_MAX, .default_value = 0, .step = 1, .qmenu = NULL, }, { .id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, .name = "CAPTURE Count", .type = V4L2_CTRL_TYPE_INTEGER, .minimum = SINGLE_OUTPUT_BUFFER, .maximum = MAX_NUM_OUTPUT_BUFFERS, .default_value = SINGLE_OUTPUT_BUFFER, .step = 1, .qmenu = NULL, }, { .id = V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, .name = "OUTPUT Count", .type = V4L2_CTRL_TYPE_INTEGER, .minimum = SINGLE_INPUT_BUFFER, .maximum = MAX_NUM_INPUT_BUFFERS, .default_value = SINGLE_INPUT_BUFFER, .step = 1, .qmenu = NULL, }, { .id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY, .name = "Session Priority", .type = V4L2_CTRL_TYPE_BOOLEAN, .minimum = V4L2_MPEG_MSM_VIDC_DISABLE, .maximum = V4L2_MPEG_MSM_VIDC_ENABLE, .default_value = V4L2_MPEG_MSM_VIDC_ENABLE, .step = 1, }, { .id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE, .name = "Decoder Operating rate", .type = V4L2_CTRL_TYPE_INTEGER, .minimum = (DEFAULT_FPS << 16),/* Power Vote min fps */ .maximum = INT_MAX, .default_value = (DEFAULT_FPS << 16), .step = 1, .qmenu = NULL, }, { .id = V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_MODE, .name = "Low Latency Mode", .type = V4L2_CTRL_TYPE_BOOLEAN, .minimum = V4L2_MPEG_MSM_VIDC_DISABLE, .maximum = V4L2_MPEG_MSM_VIDC_ENABLE, .default_value = V4L2_MPEG_MSM_VIDC_DISABLE, .step = 1, }, { .id = V4L2_CID_MPEG_VIDC_SUPERFRAME, .name = "Superframe", .type = V4L2_CTRL_TYPE_INTEGER, .minimum = 0, .maximum = 0, .default_value = 0, .step = 1, }, }; #define NUM_CTRLS ARRAY_SIZE(msm_vdec_ctrls) struct msm_vidc_format_desc vdec_output_formats[] = { { .name = "YCbCr Semiplanar 4:2:0", .description = "Y/CbCr 4:2:0", .fourcc = V4L2_PIX_FMT_NV12, }, { .name = "YCbCr Semiplanar 4:2:0 10bit", .description = "Y/CbCr 4:2:0 10bit", .fourcc = V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS, }, { .name = "UBWC YCbCr Semiplanar 4:2:0", .description = "UBWC Y/CbCr 4:2:0", .fourcc = V4L2_PIX_FMT_NV12_UBWC, }, { .name = "UBWC YCbCr Semiplanar 4:2:0 10bit", .description = "UBWC Y/CbCr 4:2:0 10bit", .fourcc = V4L2_PIX_FMT_NV12_TP10_UBWC, }, }; struct msm_vidc_format_desc vdec_input_formats[] = { { .name = "Mpeg2", .description = "Mpeg2 compressed format", .fourcc = V4L2_PIX_FMT_MPEG2, }, { .name = "H264", .description = "H264 compressed format", .fourcc = V4L2_PIX_FMT_H264, }, { .name = "HEVC", .description = "HEVC compressed format", .fourcc = V4L2_PIX_FMT_HEVC, }, { .name = "VP8", .description = "VP8 compressed format", .fourcc = V4L2_PIX_FMT_VP8, }, { .name = "VP9", .description = "VP9 compressed format", .fourcc = V4L2_PIX_FMT_VP9, }, }; struct msm_vidc_format_constraint dec_pix_format_constraints[] = { { .fourcc = V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS, .num_planes = 2, .y_max_stride = 8192, .y_buffer_alignment = 256, .uv_max_stride = 8192, .uv_buffer_alignment = 256, }, { .fourcc = V4L2_PIX_FMT_NV12, .num_planes = 2, .y_max_stride = 8192, .y_buffer_alignment = 512, .uv_max_stride = 8192, .uv_buffer_alignment = 256, }, { .fourcc = V4L2_PIX_FMT_NV21, .num_planes = 2, .y_max_stride = 8192, .y_buffer_alignment = 512, .uv_max_stride = 8192, .uv_buffer_alignment = 256, }, }; static bool msm_vidc_check_for_vp9d_overload(struct msm_vidc_core *core) { u32 vp9d_instance_count = 0; struct msm_vidc_inst *inst = NULL; mutex_lock(&core->lock); list_for_each_entry(inst, &core->instances, list) { if (inst->session_type == MSM_VIDC_DECODER && get_v4l2_codec(inst) == V4L2_PIX_FMT_VP9) vp9d_instance_count++; } mutex_unlock(&core->lock); if (vp9d_instance_count > MAX_VP9D_INST_COUNT) return true; return false; } int msm_vdec_update_stream_output_mode(struct msm_vidc_inst *inst) { struct v4l2_format *f; u32 format; u32 stream_output_mode; u32 fourcc; if (!inst) { d_vpr_e("%s: invalid parameters\n", __func__); return -EINVAL; } f = &inst->fmts[OUTPUT_PORT].v4l2_fmt; format = f->fmt.pix_mp.pixelformat; stream_output_mode = HAL_VIDEO_DECODER_PRIMARY; if ((format == V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS) || (format == V4L2_PIX_FMT_NV12)) { stream_output_mode = HAL_VIDEO_DECODER_SECONDARY; } msm_comm_set_stream_output_mode(inst, stream_output_mode); fourcc = V4L2_PIX_FMT_NV12_UBWC; if (inst->bit_depth == MSM_VIDC_BIT_DEPTH_10) fourcc = V4L2_PIX_FMT_NV12_TP10_UBWC; inst->clk_data.dpb_fourcc = fourcc; return 0; } int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) { struct msm_vidc_format *fmt = NULL; struct msm_vidc_format_desc *fmt_desc = NULL; struct v4l2_pix_format_mplane *mplane = NULL; int rc = 0; u32 color_format; if (!inst || !f) { d_vpr_e("%s: invalid parameters %pK %pK\n", __func__, inst, f); return -EINVAL; } /* * First update inst format with new width/height/format * Recalculate sizes/strides etc * Perform necessary checks to continue with session * Copy recalculated info into user format */ if (f->type == OUTPUT_MPLANE) { fmt = &inst->fmts[OUTPUT_PORT]; fmt_desc = msm_comm_get_pixel_fmt_fourcc(vdec_output_formats, ARRAY_SIZE(vdec_output_formats), f->fmt.pix_mp.pixelformat, inst->sid); if (!fmt_desc) { s_vpr_e(inst->sid, "Invalid fmt set : %x\n", f->fmt.pix_mp.pixelformat); return -EINVAL; } strlcpy(fmt->name, fmt_desc->name, sizeof(fmt->name)); strlcpy(fmt->description, fmt_desc->description, sizeof(fmt->description)); inst->clk_data.opb_fourcc = f->fmt.pix_mp.pixelformat; fmt->v4l2_fmt.type = f->type; mplane = &fmt->v4l2_fmt.fmt.pix_mp; mplane->width = f->fmt.pix_mp.width; mplane->height = f->fmt.pix_mp.height; mplane->pixelformat = f->fmt.pix_mp.pixelformat; mplane->plane_fmt[0].sizeimage = msm_vidc_calculate_dec_output_frame_size(inst); if (mplane->num_planes > 1) mplane->plane_fmt[1].sizeimage = msm_vidc_calculate_dec_output_extra_size(inst); color_format = msm_comm_convert_color_fmt( f->fmt.pix_mp.pixelformat, inst->sid); mplane->plane_fmt[0].bytesperline = VENUS_Y_STRIDE(color_format, f->fmt.pix_mp.width); mplane->plane_fmt[0].reserved[0] = VENUS_Y_SCANLINES(color_format, f->fmt.pix_mp.height); inst->bit_depth = MSM_VIDC_BIT_DEPTH_8; if ((f->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_NV12_TP10_UBWC) || (f->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS)) { inst->bit_depth = MSM_VIDC_BIT_DEPTH_10; } rc = msm_vidc_check_session_supported(inst); if (rc) { s_vpr_e(inst->sid, "%s: session not supported\n", __func__); goto err_invalid_fmt; } rc = msm_vdec_update_stream_output_mode(inst); if (rc) { s_vpr_e(inst->sid, "%s: failed to update output stream mode\n", __func__); goto err_invalid_fmt; } memcpy(f, &fmt->v4l2_fmt, sizeof(struct v4l2_format)); } else if (f->type == INPUT_MPLANE) { fmt = &inst->fmts[INPUT_PORT]; fmt_desc = msm_comm_get_pixel_fmt_fourcc(vdec_input_formats, ARRAY_SIZE(vdec_input_formats), f->fmt.pix_mp.pixelformat, inst->sid); if (!fmt_desc) { s_vpr_e(inst->sid, "Invalid fmt set : %x\n", f->fmt.pix_mp.pixelformat); return -EINVAL; } strlcpy(fmt->name, fmt_desc->name, sizeof(fmt->name)); strlcpy(fmt->description, fmt_desc->description, sizeof(fmt->description)); if (f->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_VP9) { if (msm_vidc_check_for_vp9d_overload(inst->core)) { s_vpr_e(inst->sid, "VP9 Decode overload\n"); rc = -ENOTSUPP; goto err_invalid_fmt; } } fmt->v4l2_fmt.type = f->type; mplane = &fmt->v4l2_fmt.fmt.pix_mp; mplane->width = f->fmt.pix_mp.width; mplane->height = f->fmt.pix_mp.height; mplane->pixelformat = f->fmt.pix_mp.pixelformat; rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE); if (rc) { s_vpr_e(inst->sid, "Failed to open instance\n"); goto err_invalid_fmt; } mplane->plane_fmt[0].sizeimage = msm_vidc_calculate_dec_input_frame_size(inst); /* Driver can recalculate buffer count only for * only for bitstream port. Decoder YUV port reconfig * should not overwrite the FW calculated buffer * count. */ rc = msm_vidc_calculate_buffer_counts(inst); if (rc) { s_vpr_e(inst->sid, "%s failed to calculate buffer count\n", __func__); return rc; } rc = msm_vidc_check_session_supported(inst); if (rc) { s_vpr_e(inst->sid, "%s: session not supported\n", __func__); goto err_invalid_fmt; } update_log_ctxt(inst->sid, inst->session_type, mplane->pixelformat); memcpy(f, &fmt->v4l2_fmt, sizeof(struct v4l2_format)); } inst->batch.enable = is_batching_allowed(inst); msm_dcvs_try_enable(inst); err_invalid_fmt: return rc; } int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) { struct v4l2_format *fmt; if (f->type == OUTPUT_MPLANE) { fmt = &inst->fmts[OUTPUT_PORT].v4l2_fmt; fmt->fmt.pix_mp.plane_fmt[0].sizeimage = msm_vidc_calculate_dec_output_frame_size(inst); if (fmt->fmt.pix_mp.num_planes > 1) fmt->fmt.pix_mp.plane_fmt[1].sizeimage = msm_vidc_calculate_dec_output_extra_size(inst); memcpy(f, fmt, sizeof(struct v4l2_format)); } else if (f->type == INPUT_MPLANE) { fmt = &inst->fmts[INPUT_PORT].v4l2_fmt; fmt->fmt.pix_mp.plane_fmt[0].sizeimage = msm_vidc_calculate_dec_input_frame_size(inst); memcpy(f, fmt, sizeof(struct v4l2_format)); } else { s_vpr_e(inst->sid, "%s: Unsupported buf type: %d\n", __func__, f->type); return -EINVAL; } return 0; } int msm_vdec_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f) { const struct msm_vidc_format_desc *fmt_desc = NULL; int rc = 0; if (!inst || !f) { d_vpr_e("Invalid input, inst = %pK, f = %pK\n", inst, f); return -EINVAL; } if (f->type == OUTPUT_MPLANE) { fmt_desc = msm_comm_get_pixel_fmt_index(vdec_output_formats, ARRAY_SIZE(vdec_output_formats), f->index, inst->sid); } else if (f->type == INPUT_MPLANE) { fmt_desc = msm_comm_get_pixel_fmt_index(vdec_input_formats, ARRAY_SIZE(vdec_input_formats), f->index, inst->sid); f->flags = V4L2_FMT_FLAG_COMPRESSED; } memset(f->reserved, 0, sizeof(f->reserved)); if (fmt_desc) { strlcpy(f->description, fmt_desc->description, sizeof(f->description)); f->pixelformat = fmt_desc->fourcc; } else { s_vpr_h(inst->sid, "No more formats found\n"); rc = -EINVAL; } return rc; } int msm_vdec_inst_init(struct msm_vidc_inst *inst) { int rc = 0; struct msm_vidc_core *core; struct msm_vidc_format_desc *fmt_desc = NULL; struct v4l2_format *f = NULL; if (!inst || !inst->core) { d_vpr_e("Invalid input = %pK\n", inst); return -EINVAL; } core = inst->core; inst->prop.extradata_ctrls = EXTRADATA_DEFAULT; f = &inst->fmts[OUTPUT_PORT].v4l2_fmt; f->type = OUTPUT_MPLANE; f->fmt.pix_mp.height = DEFAULT_HEIGHT; f->fmt.pix_mp.width = DEFAULT_WIDTH; f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12_UBWC; f->fmt.pix_mp.num_planes = 2; f->fmt.pix_mp.plane_fmt[0].sizeimage = msm_vidc_calculate_dec_output_frame_size(inst); f->fmt.pix_mp.plane_fmt[1].sizeimage = msm_vidc_calculate_dec_output_extra_size(inst); fmt_desc = msm_comm_get_pixel_fmt_fourcc(vdec_output_formats, ARRAY_SIZE(vdec_output_formats), f->fmt.pix_mp.pixelformat, inst->sid); if (!fmt_desc) { s_vpr_e(inst->sid, "Invalid fmt set: %x\n", f->fmt.pix_mp.pixelformat); return -EINVAL; } strlcpy(inst->fmts[OUTPUT_PORT].name, fmt_desc->name, sizeof(inst->fmts[OUTPUT_PORT].name)); strlcpy(inst->fmts[OUTPUT_PORT].description, fmt_desc->description, sizeof(inst->fmts[OUTPUT_PORT].description)); f = &inst->fmts[INPUT_PORT].v4l2_fmt; f->type = INPUT_MPLANE; f->fmt.pix_mp.height = DEFAULT_HEIGHT; f->fmt.pix_mp.width = DEFAULT_WIDTH; f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264; f->fmt.pix_mp.num_planes = 1; f->fmt.pix_mp.plane_fmt[0].sizeimage = msm_vidc_calculate_dec_input_frame_size(inst); fmt_desc = msm_comm_get_pixel_fmt_fourcc(vdec_input_formats, ARRAY_SIZE(vdec_input_formats), f->fmt.pix_mp.pixelformat, inst->sid); if (!fmt_desc) { s_vpr_e(inst->sid, "Invalid fmt set: %x\n", f->fmt.pix_mp.pixelformat); return -EINVAL; } strlcpy(inst->fmts[INPUT_PORT].name, fmt_desc->name, sizeof(inst->fmts[INPUT_PORT].name)); strlcpy(inst->fmts[INPUT_PORT].description, fmt_desc->description, sizeof(inst->fmts[INPUT_PORT].description)); inst->buffer_mode_set[INPUT_PORT] = HAL_BUFFER_MODE_STATIC; inst->buffer_mode_set[OUTPUT_PORT] = HAL_BUFFER_MODE_DYNAMIC; inst->stream_output_mode = HAL_VIDEO_DECODER_PRIMARY; inst->clk_data.frame_rate = (DEFAULT_FPS << 16); inst->clk_data.operating_rate = (DEFAULT_FPS << 16); if (core->resources.decode_batching) { inst->batch.enable = true; inst->batch.size = MAX_DEC_BATCH_SIZE; } inst->buff_req.buffer[1].buffer_type = HAL_BUFFER_INPUT; inst->buff_req.buffer[1].buffer_count_min_host = inst->buff_req.buffer[1].buffer_count_actual = MIN_NUM_DEC_OUTPUT_BUFFERS; inst->buff_req.buffer[2].buffer_type = HAL_BUFFER_OUTPUT; inst->buff_req.buffer[2].buffer_count_min_host = inst->buff_req.buffer[2].buffer_count_actual = MIN_NUM_DEC_CAPTURE_BUFFERS; inst->buff_req.buffer[3].buffer_type = HAL_BUFFER_OUTPUT2; inst->buff_req.buffer[3].buffer_count_min_host = inst->buff_req.buffer[3].buffer_count_actual = MIN_NUM_DEC_CAPTURE_BUFFERS; inst->buff_req.buffer[4].buffer_type = HAL_BUFFER_EXTRADATA_INPUT; inst->buff_req.buffer[5].buffer_type = HAL_BUFFER_EXTRADATA_OUTPUT; inst->buff_req.buffer[6].buffer_type = HAL_BUFFER_EXTRADATA_OUTPUT2; inst->buff_req.buffer[7].buffer_type = HAL_BUFFER_INTERNAL_SCRATCH; inst->buff_req.buffer[8].buffer_type = HAL_BUFFER_INTERNAL_SCRATCH_1; inst->buff_req.buffer[9].buffer_type = HAL_BUFFER_INTERNAL_SCRATCH_2; inst->buff_req.buffer[10].buffer_type = HAL_BUFFER_INTERNAL_PERSIST; inst->buff_req.buffer[11].buffer_type = HAL_BUFFER_INTERNAL_PERSIST_1; inst->buff_req.buffer[12].buffer_type = HAL_BUFFER_INTERNAL_CMD_QUEUE; inst->buff_req.buffer[13].buffer_type = HAL_BUFFER_INTERNAL_RECON; msm_vidc_init_buffer_size_calculators(inst); return rc; } int msm_vdec_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) { int rc = 0; if (!inst || !inst->core || !inst->core->device) { d_vpr_e("%s: invalid parameters\n", __func__); return -EINVAL; } s_vpr_h(inst->sid, "%s: control name = %s, id = 0x%x value = %d\n", __func__, ctrl->name, ctrl->id, ctrl->val); switch (ctrl->id) { case V4L2_CID_MPEG_VIDEO_H264_PROFILE: case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE: case V4L2_CID_MPEG_VIDEO_VP8_PROFILE: case V4L2_CID_MPEG_VIDEO_VP9_PROFILE: case V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_PROFILE: inst->profile = msm_comm_v4l2_to_hfi(ctrl->id, ctrl->val, inst->sid); break; case V4L2_CID_MPEG_VIDEO_H264_LEVEL: case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL: case V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL: case V4L2_CID_MPEG_VIDC_VIDEO_VP9_LEVEL: case V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_LEVEL: inst->level = msm_comm_v4l2_to_hfi(ctrl->id, ctrl->val, inst->sid); break; case V4L2_CID_MPEG_VIDEO_HEVC_TIER: inst->level |= (msm_comm_v4l2_to_hfi(ctrl->id, ctrl->val, inst->sid) << 28); break; case V4L2_CID_MPEG_VIDC_VIDEO_DECODE_ORDER: case V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR_8BIT: case V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR_10BIT: break; case V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE: inst->flags &= ~VIDC_THUMBNAIL; if (ctrl->val) inst->flags |= VIDC_THUMBNAIL; inst->batch.enable = is_batching_allowed(inst); rc = msm_vidc_calculate_buffer_counts(inst); if (rc) { s_vpr_e(inst->sid, "%s: failed to calculate thumbnail buffer count\n", __func__); return rc; } break; case V4L2_CID_MPEG_VIDC_VIDEO_SECURE: inst->flags &= ~VIDC_SECURE; if (ctrl->val) inst->flags |= VIDC_SECURE; if (msm_comm_check_for_inst_overload(inst->core)) { s_vpr_e(inst->sid, "%s: Instance count reached Max limit, rejecting session", __func__); return -ENOTSUPP; } msm_comm_memory_prefetch(inst); break; case V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA: if (ctrl->val == EXTRADATA_NONE) inst->prop.extradata_ctrls = 0; else inst->prop.extradata_ctrls |= ctrl->val; /* * nothing to do here as inst->bufq[OUTPUT_PORT].num_planes * and inst->bufq[OUTPUT_PORT].plane_sizes[1] are already * initialized to proper values */ break; case V4L2_CID_MPEG_VIDC_VIDEO_BUFFER_SIZE_LIMIT: inst->buffer_size_limit = ctrl->val; break; case V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY: break; case V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE: inst->flags &= ~VIDC_TURBO; if (ctrl->val == INT_MAX) inst->flags |= VIDC_TURBO; else inst->clk_data.operating_rate = ctrl->val; break; case V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_MODE: inst->clk_data.low_latency_mode = !!ctrl->val; inst->batch.enable = is_batching_allowed(inst); break; default: s_vpr_e(inst->sid, "Unknown control %#x\n", ctrl->id); break; } return rc; } int msm_vdec_set_frame_size(struct msm_vidc_inst *inst) { int rc = 0; struct hfi_device *hdev; struct hfi_frame_size frame_size; struct v4l2_format *f; if (!inst || !inst->core) { d_vpr_e("%s: invalid params %pK\n", __func__, inst); return -EINVAL; } hdev = inst->core->device; f = &inst->fmts[INPUT_PORT].v4l2_fmt; frame_size.buffer_type = HFI_BUFFER_INPUT; frame_size.width = f->fmt.pix_mp.width; frame_size.height = f->fmt.pix_mp.height; s_vpr_h(inst->sid, "%s: input wxh %dx%d\n", __func__, frame_size.width, frame_size.height); rc = call_hfi_op(hdev, session_set_property, inst->session, HFI_PROPERTY_PARAM_FRAME_SIZE, &frame_size, sizeof(frame_size)); if (rc) s_vpr_e(inst->sid, "%s: set property failed\n", __func__); return rc; } int msm_vdec_set_color_format(struct msm_vidc_inst *inst) { int rc = 0; struct hfi_device *hdev; struct msm_vidc_format_constraint *fmt_constraint; if (!inst || !inst->core) { d_vpr_e("%s: invalid params %pK\n", __func__, inst); return -EINVAL; } hdev = inst->core->device; rc = msm_comm_set_color_format(inst, msm_comm_get_hal_output_buffer(inst), inst->clk_data.opb_fourcc); if (rc) { s_vpr_e(inst->sid, "%s: set color format (%#x) failed\n", __func__, inst->clk_data.opb_fourcc); return rc; } fmt_constraint = msm_comm_get_pixel_fmt_constraints( dec_pix_format_constraints, ARRAY_SIZE(dec_pix_format_constraints), inst->clk_data.opb_fourcc, inst->sid); if (fmt_constraint) { rc = msm_comm_set_color_format_constraints(inst, msm_comm_get_hal_output_buffer(inst), fmt_constraint); if (rc) { s_vpr_e(inst->sid, "%s: Set constraints for color format %#x failed\n", __func__, inst->clk_data.opb_fourcc); return rc; } } return rc; } int msm_vdec_set_input_buffer_counts(struct msm_vidc_inst *inst) { int rc = 0; struct hfi_device *hdev; struct msm_vidc_format *fmt; enum hal_buffer buffer_type; if (!inst || !inst->core) { d_vpr_e("%s: invalid params %pK\n", __func__, inst); return -EINVAL; } hdev = inst->core->device; buffer_type = HAL_BUFFER_INPUT; fmt = &inst->fmts[INPUT_PORT]; rc = msm_comm_set_buffer_count(inst, fmt->count_min, fmt->count_actual, buffer_type); if (rc) { s_vpr_e(inst->sid, "%s: failed to set bufreqs(%#x)\n", __func__, buffer_type); return -EINVAL; } return rc; } int msm_vdec_set_output_buffer_counts(struct msm_vidc_inst *inst) { int rc = 0; struct hfi_device *hdev; struct msm_vidc_format *fmt; enum hal_buffer buffer_type; if (!inst || !inst->core) { d_vpr_e("%s: invalid params %pK\n", __func__, inst); return -EINVAL; } hdev = inst->core->device; buffer_type = msm_comm_get_hal_output_buffer(inst); /* Correct buffer counts is always stored in HAL_BUFFER_OUTPUT */ fmt = &inst->fmts[OUTPUT_PORT]; if (buffer_type == HAL_BUFFER_OUTPUT2) { /* * For split mode set DPB count as well * For DPB actual count is same as min output count */ rc = msm_comm_set_buffer_count(inst, fmt->count_min, fmt->count_min, HAL_BUFFER_OUTPUT); if (rc) { s_vpr_e(inst->sid, "%s: failed to set buffer count(%#x)\n", __func__, buffer_type); return -EINVAL; } } rc = msm_comm_set_buffer_count(inst, fmt->count_min, fmt->count_actual, buffer_type); if (rc) { s_vpr_e(inst->sid, "%s: failed to set bufreqs(%#x)\n", __func__, buffer_type); return -EINVAL; } return rc; } int msm_vdec_set_profile_level(struct msm_vidc_inst *inst) { int rc = 0; struct hfi_device *hdev; struct hfi_profile_level profile_level; if (!inst || !inst->core) { d_vpr_e("%s: invalid params %pK\n", __func__, inst); return -EINVAL; } hdev = inst->core->device; profile_level.profile = inst->profile; profile_level.level = inst->level; s_vpr_h(inst->sid, "%s: %#x %#x\n", __func__, profile_level.profile, profile_level.level); rc = call_hfi_op(hdev, session_set_property, inst->session, HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT, &profile_level, sizeof(profile_level)); if (rc) s_vpr_e(inst->sid, "%s: set property failed\n", __func__); return rc; } int msm_vdec_set_output_order(struct msm_vidc_inst *inst) { int rc = 0; struct hfi_device *hdev; struct v4l2_ctrl *ctrl; u32 output_order; if (!inst || !inst->core) { d_vpr_e("%s: invalid params %pK\n", __func__, inst); return -EINVAL; } hdev = inst->core->device; ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_DECODE_ORDER); s_vpr_h(inst->sid, "%s: %d\n", __func__, ctrl->val); if (ctrl->val == V4L2_MPEG_MSM_VIDC_ENABLE) output_order = HFI_OUTPUT_ORDER_DECODE; else output_order = HFI_OUTPUT_ORDER_DISPLAY; rc = call_hfi_op(hdev, session_set_property, inst->session, HFI_PROPERTY_PARAM_VDEC_OUTPUT_ORDER, &output_order, sizeof(u32)); if (rc) s_vpr_e(inst->sid, "%s: set property failed\n", __func__); return rc; } int msm_vdec_set_sync_frame_mode(struct msm_vidc_inst *inst) { int rc = 0; struct hfi_device *hdev; struct v4l2_ctrl *ctrl; struct hfi_enable hfi_property; if (!inst || !inst->core) { d_vpr_e("%s: invalid params %pK\n", __func__, inst); return -EINVAL; } hdev = inst->core->device; ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE); hfi_property.enable = (bool)ctrl->val; s_vpr_h(inst->sid, "%s: %#x\n", __func__, hfi_property.enable); rc = call_hfi_op(hdev, session_set_property, inst->session, HFI_PROPERTY_PARAM_VDEC_THUMBNAIL_MODE, &hfi_property, sizeof(hfi_property)); if (rc) s_vpr_e(inst->sid, "%s: set property failed\n", __func__); return rc; } int msm_vdec_set_secure_mode(struct msm_vidc_inst *inst) { int rc = 0; struct hfi_device *hdev; struct v4l2_ctrl *ctrl; u32 codec; if (!inst || !inst->core) { d_vpr_e("%s: invalid params %pK\n", __func__, inst); return -EINVAL; } hdev = inst->core->device; ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_SECURE); codec = get_v4l2_codec(inst); if (ctrl->val) { if (!(codec == V4L2_PIX_FMT_HEVC || codec == V4L2_PIX_FMT_H264 || codec == V4L2_PIX_FMT_VP9 || codec == V4L2_PIX_FMT_MPEG2)) { s_vpr_e(inst->sid, "%s: Secure allowed for HEVC/H264/VP9/MPEG2\n", __func__); return -EINVAL; } } s_vpr_h(inst->sid, "%s: %#x\n", __func__, ctrl->val); rc = call_hfi_op(hdev, session_set_property, inst->session, HFI_PROPERTY_PARAM_SECURE_SESSION, &ctrl->val, sizeof(u32)); if (rc) s_vpr_e(inst->sid, "%s: set property failed\n", __func__); return rc; } int msm_vdec_set_output_stream_mode(struct msm_vidc_inst *inst) { int rc = 0; struct hfi_device *hdev; struct hfi_multi_stream multi_stream; struct hfi_frame_size frame_sz; struct v4l2_format *f; u32 sid; if (!inst || !inst->core) { d_vpr_e("%s: invalid params %pK\n", __func__, inst); return -EINVAL; } hdev = inst->core->device; sid = inst->sid; if (is_primary_output_mode(inst)) { multi_stream.buffer_type = HFI_BUFFER_OUTPUT; multi_stream.enable = true; rc = call_hfi_op(hdev, session_set_property, inst->session, HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM, &multi_stream, sizeof(multi_stream)); if (rc) { s_vpr_e(sid, "%s: set prop multistream primary failed: %d\n", __func__, rc); return rc; } multi_stream.buffer_type = HFI_BUFFER_OUTPUT2; multi_stream.enable = false; rc = call_hfi_op(hdev, session_set_property, inst->session, HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM, &multi_stream, sizeof(multi_stream)); if (rc) { s_vpr_e(sid, "%s: set prop multistream primary2 failed : %d\n", __func__, rc); return rc; } } else { rc = msm_comm_set_color_format(inst, HAL_BUFFER_OUTPUT, inst->clk_data.dpb_fourcc); if (rc) return rc; multi_stream.buffer_type = HFI_BUFFER_OUTPUT2; multi_stream.enable = true; rc = call_hfi_op(hdev, session_set_property, inst->session, HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM, &multi_stream, sizeof(multi_stream)); if (rc) { s_vpr_e(sid, "%s: set prop multistream secondary failed : %d\n", __func__, rc); return rc; } multi_stream.buffer_type = HFI_BUFFER_OUTPUT; multi_stream.enable = false; rc = call_hfi_op(hdev, session_set_property, inst->session, HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM, &multi_stream, sizeof(multi_stream)); if (rc) { s_vpr_e(sid, "%s: set prop multistream secondary2 failed: %d\n", __func__, rc); return rc; } frame_sz.buffer_type = HFI_BUFFER_OUTPUT2; f = &inst->fmts[OUTPUT_PORT].v4l2_fmt; frame_sz.width = f->fmt.pix_mp.width; frame_sz.height = f->fmt.pix_mp.height; s_vpr_h(sid, "frame_size: hal buffer type %d, width %d, height %d\n", frame_sz.buffer_type, frame_sz.width, frame_sz.height); rc = call_hfi_op(hdev, session_set_property, inst->session, HFI_PROPERTY_PARAM_FRAME_SIZE, &frame_sz, sizeof(frame_sz)); if (rc) { s_vpr_e(sid, "%s: set prop frame_size failed\n", __func__); return rc; } } return rc; } int msm_vdec_set_priority(struct msm_vidc_inst *inst) { int rc = 0; struct hfi_device *hdev; struct hfi_enable hfi_property; if (!inst || !inst->core) { d_vpr_e("%s: invalid params %pK\n", __func__, inst); return -EINVAL; } hdev = inst->core->device; hfi_property.enable = is_realtime_session(inst); s_vpr_h(inst->sid, "%s: %#x\n", __func__, hfi_property.enable); rc = call_hfi_op(hdev, session_set_property, inst->session, HFI_PROPERTY_CONFIG_REALTIME, &hfi_property, sizeof(hfi_property)); if (rc) s_vpr_e(inst->sid, "%s: set property failed\n", __func__); return rc; } int msm_vdec_set_conceal_color(struct msm_vidc_inst *inst) { int rc = 0; struct hfi_device *hdev; struct v4l2_ctrl *ctrl_8b; struct v4l2_ctrl *ctrl_10b; struct hfi_conceal_color conceal_color; if (!inst || !inst->core) { d_vpr_e("%s: invalid params %pK\n", __func__, inst); return -EINVAL; } hdev = inst->core->device; ctrl_8b = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR_8BIT); ctrl_10b = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR_10BIT); conceal_color.conceal_color_8bit = ctrl_8b->val; conceal_color.conceal_color_10bit = ctrl_10b->val; s_vpr_h(inst->sid, "%s: %#x %#x\n", __func__, conceal_color.conceal_color_8bit, conceal_color.conceal_color_10bit); rc = call_hfi_op(hdev, session_set_property, inst->session, HFI_PROPERTY_PARAM_VDEC_CONCEAL_COLOR, &conceal_color, sizeof(conceal_color)); if (rc) s_vpr_e(inst->sid, "%s: set property failed\n", __func__); return rc; } int msm_vdec_set_extradata(struct msm_vidc_inst *inst) { uint32_t display_info = HFI_PROPERTY_PARAM_VUI_DISPLAY_INFO_EXTRADATA; u32 value = 0x0; u32 codec; codec = get_v4l2_codec(inst); switch (codec) { case V4L2_PIX_FMT_H264: case V4L2_PIX_FMT_HEVC: display_info = HFI_PROPERTY_PARAM_VUI_DISPLAY_INFO_EXTRADATA; break; case V4L2_PIX_FMT_VP8: case V4L2_PIX_FMT_VP9: display_info = HFI_PROPERTY_PARAM_VDEC_VPX_COLORSPACE_EXTRADATA; break; case V4L2_PIX_FMT_MPEG2: display_info = HFI_PROPERTY_PARAM_VDEC_MPEG2_SEQDISP_EXTRADATA; break; } /* Enable Default Extradata */ msm_comm_set_index_extradata(inst, MSM_VIDC_EXTRADATA_OUTPUT_CROP, 0x1); msm_comm_set_extradata(inst, HFI_PROPERTY_PARAM_VDEC_INTERLACE_VIDEO_EXTRADATA, 0x1); msm_comm_set_extradata(inst, display_info, 0x1); if (codec == V4L2_PIX_FMT_VP9 || codec == V4L2_PIX_FMT_HEVC) { msm_comm_set_extradata(inst, HFI_PROPERTY_PARAM_VDEC_HDR10_HIST_EXTRADATA, 0x1); } msm_comm_set_extradata(inst, HFI_PROPERTY_PARAM_VDEC_NUM_CONCEALED_MB, 0x1); if (codec == V4L2_PIX_FMT_HEVC) { msm_comm_set_extradata(inst, HFI_PROPERTY_PARAM_VDEC_MASTER_DISP_COL_SEI_EXTRADATA, 0x1); msm_comm_set_extradata(inst, HFI_PROPERTY_PARAM_VDEC_CLL_SEI_EXTRADATA, 0x1); msm_comm_set_extradata(inst, HFI_PROPERTY_PARAM_VDEC_STREAM_USERDATA_EXTRADATA, 0x1); } /* Enable / Disable Advanced Extradata */ if (inst->prop.extradata_ctrls & EXTRADATA_ADVANCED) value = 0x1; msm_comm_set_extradata(inst, HFI_PROPERTY_PARAM_VDEC_STREAM_USERDATA_EXTRADATA, value); msm_comm_set_extradata(inst, HFI_PROPERTY_PARAM_VDEC_TIMESTAMP_EXTRADATA, value); msm_comm_set_extradata(inst, HFI_PROPERTY_PARAM_S3D_FRAME_PACKING_EXTRADATA, value); msm_comm_set_extradata(inst, HFI_PROPERTY_PARAM_VDEC_FRAME_RATE_EXTRADATA, value); msm_comm_set_extradata(inst, HFI_PROPERTY_PARAM_VDEC_PANSCAN_WNDW_EXTRADATA, value); msm_comm_set_extradata(inst, HFI_PROPERTY_PARAM_VDEC_RECOVERY_POINT_SEI_EXTRADATA, value); msm_comm_set_index_extradata(inst, MSM_VIDC_EXTRADATA_ASPECT_RATIO, value); msm_comm_set_extradata(inst, HFI_PROPERTY_PARAM_VDEC_FRAME_QP_EXTRADATA, value); return 0; } int msm_vdec_set_properties(struct msm_vidc_inst *inst) { int rc = 0; if (!in_port_reconfig(inst)) { /* do not allow these settings in port reconfiration */ rc = msm_vdec_set_frame_size(inst); if (rc) goto exit; rc = msm_vdec_set_input_buffer_counts(inst); if (rc) goto exit; rc = msm_vdec_set_profile_level(inst); if (rc) goto exit; rc = msm_vdec_set_output_order(inst); if (rc) goto exit; rc = msm_vdec_set_sync_frame_mode(inst); if (rc) goto exit; rc = msm_vdec_set_secure_mode(inst); if (rc) goto exit; rc = msm_vdec_set_extradata(inst); if (rc) goto exit; rc = msm_vdec_set_priority(inst); if (rc) goto exit; rc = msm_vdec_set_conceal_color(inst); if (rc) goto exit; } rc = msm_vdec_set_color_format(inst); if (rc) goto exit; rc = msm_vdec_set_output_stream_mode(inst); if (rc) goto exit; rc = msm_vdec_set_output_buffer_counts(inst); if (rc) goto exit; exit: if (rc) s_vpr_e(inst->sid, "%s: failed with %d\n", __func__, rc); else s_vpr_h(inst->sid, "%s: set properties successful\n", __func__); return rc; } int msm_vdec_ctrl_init(struct msm_vidc_inst *inst, const struct v4l2_ctrl_ops *ctrl_ops) { return msm_comm_ctrl_init(inst, msm_vdec_ctrls, ARRAY_SIZE(msm_vdec_ctrls), ctrl_ops); }