video: driver: enable decoder batching support

Added change to enable decoder batching feature.

Batching willbe enabled only when below conditions were met.

[1] platform supports batching
[2] decode session
[3] realtime session
[4] non-thumbnail session
[5] non-heif session
[6] 2-stage decode only(low_latency not supported).

Change-Id: I54b601814c3b5fa2077dc41c5b0ac84964c2674a
Signed-off-by: Govindaraj Rajagopal <grajagop@codeaurora.org>
This commit is contained in:
Govindaraj Rajagopal
2021-03-02 20:35:55 +05:30
parent 596ca194de
commit a7670d7f42
12 changed files with 355 additions and 78 deletions

View File

@@ -166,8 +166,10 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
/* (4096 * 2304) / 256 */ /* (4096 * 2304) / 256 */
{LOSSLESS_MBPF, ENC, H264|HEVC, 64, 36864, 1, 36864}, {LOSSLESS_MBPF, ENC, H264|HEVC, 64, 36864, 1, 36864},
/* Batch Mode Decode */ /* Batch Mode Decode */
/* TODO: update with new values based on updated voltage corner */
{BATCH_MBPF, DEC, CODECS_ALL, 64, 34816, 1, 34816}, {BATCH_MBPF, DEC, CODECS_ALL, 64, 34816, 1, 34816},
/* (4096 * 2304) / 256 */ /* (4096 * 2304) / 256 */
{BATCH_FPS, DEC, CODECS_ALL, 1, 120, 1, 120},
{SECURE_MBPF, ENC|DEC, CODECS_ALL, 64, 36864, 1, 36864}, {SECURE_MBPF, ENC|DEC, CODECS_ALL, 64, 36864, 1, 36864},
/* ((1920 * 1088) / 256) * 480 fps */ /* ((1920 * 1088) / 256) * 480 fps */
{MBPS, ENC, CODECS_ALL, 64, 3916800, 1, 3916800}, {MBPS, ENC, CODECS_ALL, 64, 3916800, 1, 3916800},

View File

@@ -12,6 +12,7 @@
#include "msm_vidc_inst.h" #include "msm_vidc_inst.h"
#include "msm_vidc_core.h" #include "msm_vidc_core.h"
#include "msm_vidc_driver.h" #include "msm_vidc_driver.h"
#include "msm_vidc_control.h"
#include "msm_vidc_dt.h" #include "msm_vidc_dt.h"
#include "msm_vidc_internal.h" #include "msm_vidc_internal.h"
#include "msm_vidc_buffer.h" #include "msm_vidc_buffer.h"
@@ -564,7 +565,7 @@ int msm_vidc_decide_work_mode_iris2(struct msm_vidc_inst* inst)
i_vpr_h(inst, "Configuring work mode = %u low latency = %u", i_vpr_h(inst, "Configuring work mode = %u low latency = %u",
work_mode, lowlatency); work_mode, lowlatency);
inst->capabilities->cap[STAGE].value = work_mode; msm_vidc_update_cap_value(inst, STAGE, work_mode, __func__);
/* TODO If Encode then Set Low Latency (Enable/Disable) /* TODO If Encode then Set Low Latency (Enable/Disable)
* and Update internal cap struct * and Update internal cap struct
@@ -609,7 +610,7 @@ int msm_vidc_decide_work_route_iris2(struct msm_vidc_inst* inst)
} }
i_vpr_h(inst, "Configuring work route = %u", work_route); i_vpr_h(inst, "Configuring work route = %u", work_route);
inst->capabilities->cap[PIPE].value = work_route; msm_vidc_update_cap_value(inst, PIPE, work_route, __func__);
return 0; return 0;
} }
@@ -643,7 +644,7 @@ int msm_vidc_decide_quality_mode_iris2(struct msm_vidc_inst* inst)
(mbpf <= max_hq_mbpf && mbps <= max_hq_mbps)) (mbpf <= max_hq_mbpf && mbps <= max_hq_mbps))
mode = MSM_VIDC_MAX_QUALITY_MODE; mode = MSM_VIDC_MAX_QUALITY_MODE;
capability->cap[QUALITY_MODE].value = mode; msm_vidc_update_cap_value(inst, QUALITY_MODE, mode, __func__);
return 0; return 0;
} }

View File

@@ -29,5 +29,6 @@ int msm_vdec_init_input_subcr_params(struct msm_vidc_inst *inst);
int msm_vdec_input_port_settings_change(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); int msm_vdec_output_port_settings_change(struct msm_vidc_inst *inst);
int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd); int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd);
int msm_vidc_queue_buffer_batch(struct msm_vidc_inst *inst);
#endif // _MSM_VDEC_H_ #endif // _MSM_VDEC_H_

View File

@@ -70,5 +70,7 @@ int msm_vidc_v4l2_menu_to_hfi(struct msm_vidc_inst *inst,
enum msm_vidc_inst_capability_type cap_id, u32 *value); enum msm_vidc_inst_capability_type cap_id, u32 *value);
int msm_vidc_v4l2_to_hfi_enum(struct msm_vidc_inst *inst, int msm_vidc_v4l2_to_hfi_enum(struct msm_vidc_inst *inst,
enum msm_vidc_inst_capability_type cap_id, u32 *value); enum msm_vidc_inst_capability_type cap_id, u32 *value);
int msm_vidc_update_cap_value(struct msm_vidc_inst *inst, u32 cap,
s32 adjusted_val, const char *func);
#endif #endif

View File

@@ -88,8 +88,8 @@ struct msm_vidc_core {
struct workqueue_struct *device_workq; struct workqueue_struct *device_workq;
struct delayed_work pm_work; struct delayed_work pm_work;
struct workqueue_struct *pm_workq; struct workqueue_struct *pm_workq;
struct workqueue_struct *batch_workq;
struct delayed_work fw_unload_work; struct delayed_work fw_unload_work;
struct delayed_work batch_work;
struct work_struct ssr_work; struct work_struct ssr_work;
struct msm_vidc_core_power power; struct msm_vidc_core_power power;
struct msm_vidc_ssr ssr; struct msm_vidc_ssr ssr;

View File

@@ -162,6 +162,11 @@ static inline bool is_realtime_session(struct msm_vidc_inst *inst)
return !inst->capabilities->cap[PRIORITY].value; return !inst->capabilities->cap[PRIORITY].value;
} }
static inline bool is_lowlatency_session(struct msm_vidc_inst *inst)
{
return !!(inst->capabilities->cap[LOWLATENCY_MODE].value);
}
static inline bool is_active_session(u64 prev, u64 curr) static inline bool is_active_session(u64 prev, u64 curr)
{ {
u64 ts_delta; u64 ts_delta;
@@ -270,7 +275,7 @@ int msm_vidc_map_driver_buf(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buf); struct msm_vidc_buffer *buf);
int msm_vidc_put_driver_buf(struct msm_vidc_inst *inst, int msm_vidc_put_driver_buf(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buf); struct msm_vidc_buffer *buf);
int msm_vidc_queue_buffer(struct msm_vidc_inst *inst, struct vb2_buffer *vb2); int msm_vidc_queue_buffer_single(struct msm_vidc_inst *inst, struct vb2_buffer *vb2);
int msm_vidc_destroy_internal_buffer(struct msm_vidc_inst *inst, int msm_vidc_destroy_internal_buffer(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buffer); struct msm_vidc_buffer *buffer);
void msm_vidc_destroy_buffers(struct msm_vidc_inst *inst); void msm_vidc_destroy_buffers(struct msm_vidc_inst *inst);
@@ -317,5 +322,6 @@ int msm_vidc_init_instance_caps(struct msm_vidc_core* core);
int msm_vidc_deinit_core_caps(struct msm_vidc_core* core); int msm_vidc_deinit_core_caps(struct msm_vidc_core* core);
int msm_vidc_deinit_instance_caps(struct msm_vidc_core* core); int msm_vidc_deinit_instance_caps(struct msm_vidc_core* core);
int msm_vidc_update_debug_str(struct msm_vidc_inst *inst); int msm_vidc_update_debug_str(struct msm_vidc_inst *inst);
bool msm_vidc_allow_decode_batch(struct msm_vidc_inst *inst);
#endif // _MSM_VIDC_DRIVER_H_ #endif // _MSM_VIDC_DRIVER_H_

View File

@@ -307,6 +307,7 @@ enum msm_vidc_inst_capability_type {
MBPF, MBPF,
LOSSLESS_MBPF, LOSSLESS_MBPF,
BATCH_MBPF, BATCH_MBPF,
BATCH_FPS,
SECURE_MBPF, SECURE_MBPF,
MBPS, MBPS,
POWER_SAVE_MBPS, POWER_SAVE_MBPS,

View File

@@ -18,6 +18,9 @@
#include "msm_vidc_control.h" #include "msm_vidc_control.h"
#include "venus_hfi.h" #include "venus_hfi.h"
#include "hfi_packet.h" #include "hfi_packet.h"
/* TODO: update based on clips */
#define MAX_DEC_BATCH_SIZE 6
#define SKIP_BATCH_WINDOW 100
u32 msm_vdec_subscribe_for_psc_avc[] = { u32 msm_vdec_subscribe_for_psc_avc[] = {
HFI_PROP_BITSTREAM_RESOLUTION, HFI_PROP_BITSTREAM_RESOLUTION,
@@ -206,7 +209,7 @@ static int msm_vdec_set_bit_depth(struct msm_vidc_inst *inst,
bitdepth = 10 << 16 | 10; bitdepth = 10 << 16 | 10;
inst->subcr_params[port].bit_depth = bitdepth; inst->subcr_params[port].bit_depth = bitdepth;
inst->capabilities->cap[BIT_DEPTH].value = bitdepth; msm_vidc_update_cap_value(inst, BIT_DEPTH, bitdepth, __func__);
i_vpr_h(inst, "%s: bit depth: %d", __func__, bitdepth); i_vpr_h(inst, "%s: bit depth: %d", __func__, bitdepth);
rc = venus_hfi_session_property(inst, rc = venus_hfi_session_property(inst,
HFI_PROP_LUMA_CHROMA_BIT_DEPTH, HFI_PROP_LUMA_CHROMA_BIT_DEPTH,
@@ -1393,17 +1396,17 @@ static int msm_vdec_read_input_subcr_params(struct msm_vidc_inst *inst)
inst->crop.width = inst->fmts[INPUT_PORT].fmt.pix_mp.width - inst->crop.width = inst->fmts[INPUT_PORT].fmt.pix_mp.width -
((subsc_params.crop_offsets[1] >> 16) & 0xFFFF); ((subsc_params.crop_offsets[1] >> 16) & 0xFFFF);
inst->capabilities->cap[PROFILE].value = subsc_params.profile; msm_vidc_update_cap_value(inst, PROFILE, subsc_params.profile, __func__);
inst->capabilities->cap[LEVEL].value = subsc_params.level; msm_vidc_update_cap_value(inst, LEVEL, subsc_params.level, __func__);
inst->capabilities->cap[HEVC_TIER].value = subsc_params.tier; msm_vidc_update_cap_value(inst, HEVC_TIER, subsc_params.tier, __func__);
inst->capabilities->cap[POC].value = subsc_params.pic_order_cnt; msm_vidc_update_cap_value(inst, POC, subsc_params.pic_order_cnt, __func__);
inst->capabilities->cap[BIT_DEPTH].value = subsc_params.bit_depth; msm_vidc_update_cap_value(inst, BIT_DEPTH, subsc_params.bit_depth, __func__);
if (subsc_params.coded_frames & HFI_BITMASK_FRAME_MBS_ONLY_FLAG) if (subsc_params.coded_frames & HFI_BITMASK_FRAME_MBS_ONLY_FLAG)
inst->capabilities->cap[CODED_FRAMES].value = msm_vidc_update_cap_value(inst, CODED_FRAMES, CODED_FRAMES_PROGRESSIVE, __func__);
CODED_FRAMES_PROGRESSIVE;
else else
inst->capabilities->cap[CODED_FRAMES].value = msm_vidc_update_cap_value(inst, CODED_FRAMES, CODED_FRAMES_INTERLACE, __func__);
CODED_FRAMES_INTERLACE;
inst->decode_batch.enable = msm_vidc_allow_decode_batch(inst);
return 0; return 0;
} }
@@ -1543,6 +1546,8 @@ int msm_vdec_streamon_input(struct msm_vidc_inst *inst)
if (rc) if (rc)
goto error; goto error;
inst->decode_batch.enable = msm_vidc_allow_decode_batch(inst);
return 0; return 0;
error: error:
@@ -1551,6 +1556,33 @@ error:
return rc; return rc;
} }
static int schedule_batch_work(struct msm_vidc_inst *inst)
{
struct msm_vidc_core *core;
if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
core = inst->core;
cancel_delayed_work(&inst->decode_batch.work);
queue_delayed_work(core->batch_workq, &inst->decode_batch.work,
msecs_to_jiffies(core->capabilities[DECODE_BATCH_TIMEOUT].value));
return 0;
}
static int cancel_batch_work(struct msm_vidc_inst *inst)
{
if (!inst) {
d_vpr_e("%s: Invalid arguments\n", __func__);
return -EINVAL;
}
cancel_delayed_work(&inst->decode_batch.work);
return 0;
}
int msm_vdec_streamoff_output(struct msm_vidc_inst *inst) int msm_vdec_streamoff_output(struct msm_vidc_inst *inst)
{ {
int rc = 0; int rc = 0;
@@ -1560,6 +1592,8 @@ int msm_vdec_streamoff_output(struct msm_vidc_inst *inst)
return -EINVAL; return -EINVAL;
} }
/* cancel pending batch work */
cancel_batch_work(inst);
rc = msm_vidc_session_streamoff(inst, OUTPUT_PORT); rc = msm_vidc_session_streamoff(inst, OUTPUT_PORT);
if (rc) if (rc)
return rc; return rc;
@@ -1754,6 +1788,8 @@ int msm_vdec_streamon_output(struct msm_vidc_inst *inst)
if (rc) if (rc)
goto error; goto error;
inst->decode_batch.enable = msm_vidc_allow_decode_batch(inst);
return 0; return 0;
error: error:
@@ -1765,13 +1801,43 @@ error:
static int msm_vdec_qbuf_batch(struct msm_vidc_inst *inst, static int msm_vdec_qbuf_batch(struct msm_vidc_inst *inst,
struct vb2_buffer *vb2) struct vb2_buffer *vb2)
{ {
int rc = 0; struct msm_vidc_buffer *buf;
enum msm_vidc_allow allow;
int count, rc;
if (!inst || !vb2) { if (!inst || !vb2 || !inst->decode_batch.size) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} }
i_vpr_h(inst, "%s()\n", __func__);
buf = msm_vidc_get_driver_buf(inst, vb2);
if (!buf)
return -EINVAL;
allow = msm_vidc_allow_qbuf(inst, vb2->type);
if (allow == MSM_VIDC_DISALLOW) {
i_vpr_e(inst, "%s: qbuf not allowed\n", __func__);
return -EINVAL;
} else if (allow == MSM_VIDC_DEFER) {
print_vidc_buffer(VIDC_HIGH, "high", "qbuf deferred", inst, buf);
return 0;
}
/* do not defer buffers initially to avoid latency issues */
if (inst->power.buffer_counter > SKIP_BATCH_WINDOW) {
count = msm_vidc_num_buffers(inst, MSM_VIDC_BUF_OUTPUT, MSM_VIDC_ATTR_DEFERRED);
if (count < inst->decode_batch.size) {
print_vidc_buffer(VIDC_HIGH, "high", "batch-qbuf deferred", inst, buf);
schedule_batch_work(inst);
return 0;
}
cancel_batch_work(inst);
}
rc = msm_vidc_queue_buffer_batch(inst);
if (rc)
return rc;
return rc; return rc;
} }
@@ -1780,10 +1846,16 @@ int msm_vdec_qbuf(struct msm_vidc_inst *inst, struct vb2_buffer *vb2)
{ {
int rc = 0; int rc = 0;
if (inst->decode_batch.enable) if (!inst || !vb2) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
/* batch decoder output & meta buffer only */
if (inst->decode_batch.enable && vb2->type == OUTPUT_MPLANE)
rc = msm_vdec_qbuf_batch(inst, vb2); rc = msm_vdec_qbuf_batch(inst, vb2);
else else
rc = msm_vidc_queue_buffer(inst, vb2); rc = msm_vidc_queue_buffer_single(inst, vb2);
return rc; return rc;
} }
@@ -2142,11 +2214,9 @@ set_default:
i_vpr_h(inst, "%s: type %u value %#x\n", i_vpr_h(inst, "%s: type %u value %#x\n",
__func__, s_parm->type, q16_rate); __func__, s_parm->type, q16_rate);
if (is_frame_rate) { msm_vidc_update_cap_value(inst,
capability->cap[FRAME_RATE].value = q16_rate; is_frame_rate ? FRAME_RATE : OPERATING_RATE,
} else { q16_rate, __func__);
capability->cap[OPERATING_RATE].value = q16_rate;
}
exit: exit:
return rc; return rc;
@@ -2290,6 +2360,10 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst)
core = inst->core; core = inst->core;
INIT_DELAYED_WORK(&inst->decode_batch.work, msm_vidc_batch_handler); INIT_DELAYED_WORK(&inst->decode_batch.work, msm_vidc_batch_handler);
if (core->capabilities[DECODE_BATCH].value) {
inst->decode_batch.enable = true;
inst->decode_batch.size = MAX_DEC_BATCH_SIZE;
}
f = &inst->fmts[INPUT_PORT]; f = &inst->fmts[INPUT_PORT];
f->type = INPUT_MPLANE; f->type = INPUT_MPLANE;
@@ -2372,6 +2446,8 @@ int msm_vdec_inst_deinit(struct msm_vidc_inst *inst)
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} }
/* cancel pending batch work */
cancel_batch_work(inst);
rc = msm_vidc_ctrl_deinit(inst); rc = msm_vidc_ctrl_deinit(inst);
return rc; return rc;

View File

@@ -353,10 +353,8 @@ static int msm_venc_set_csc(struct msm_vidc_inst* inst,
return -EINVAL; return -EINVAL;
} }
if (msm_venc_csc_required(inst)) msm_vidc_update_cap_value(inst, CSC,
inst->capabilities->cap[CSC].value = 1; msm_venc_csc_required(inst) ? 1 : 0, __func__);
else
inst->capabilities->cap[CSC].value = 0;
csc = inst->capabilities->cap[CSC].value; csc = inst->capabilities->cap[CSC].value;
i_vpr_h(inst, "%s: csc: %u\n", __func__, csc); i_vpr_h(inst, "%s: csc: %u\n", __func__, csc);
@@ -955,7 +953,7 @@ int msm_venc_qbuf(struct msm_vidc_inst *inst, struct vb2_buffer *vb2)
{ {
int rc = 0; int rc = 0;
rc = msm_vidc_queue_buffer(inst, vb2); rc = msm_vidc_queue_buffer_single(inst, vb2);
if (rc) if (rc)
return rc; return rc;
@@ -1590,12 +1588,9 @@ set_default:
i_vpr_h(inst, "%s: type %u value %#x\n", i_vpr_h(inst, "%s: type %u value %#x\n",
__func__, s_parm->type, q16_rate); __func__, s_parm->type, q16_rate);
if (!is_frame_rate) { msm_vidc_update_cap_value(inst,
capability->cap[OPERATING_RATE].value = q16_rate; is_frame_rate ? FRAME_RATE : OPERATING_RATE,
goto exit; q16_rate, __func__);
} else {
capability->cap[FRAME_RATE].value = q16_rate;
}
/* /*
* In static case, frame rate is set via * In static case, frame rate is set via

View File

@@ -359,9 +359,14 @@ static bool is_parent_available(struct msm_vidc_inst* inst,
return false; return false;
} }
static int msm_vidc_update_cap_value(struct msm_vidc_inst* inst, u32 cap, int msm_vidc_update_cap_value(struct msm_vidc_inst *inst, u32 cap,
s32 adjusted_val, const char *func) s32 adjusted_val, const char *func)
{ {
if (!inst || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
if (inst->capabilities->cap[cap].value != adjusted_val) if (inst->capabilities->cap[cap].value != adjusted_val)
i_vpr_h(inst, i_vpr_h(inst,
"%s: updated database value from %#x to %#x\n", "%s: updated database value from %#x to %#x\n",
@@ -508,7 +513,7 @@ static int msm_vidc_adjust_dynamic_property(struct msm_vidc_inst *inst,
if (rc) if (rc)
goto exit; goto exit;
} else if (ctrl) { } else if (ctrl) {
capability->cap[cap_id].value = ctrl->val; msm_vidc_update_cap_value(inst, cap_id, ctrl->val, __func__);
} }
/* add children if cap value modified */ /* add children if cap value modified */
@@ -741,7 +746,7 @@ int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl)
capability->cap[cap_id].flags |= CAP_FLAG_CLIENT_SET; capability->cap[cap_id].flags |= CAP_FLAG_CLIENT_SET;
/* Static setting */ /* Static setting */
if (!inst->vb2q[OUTPUT_PORT].streaming) { if (!inst->vb2q[OUTPUT_PORT].streaming) {
capability->cap[cap_id].value = ctrl->val; msm_vidc_update_cap_value(inst, cap_id, ctrl->val, __func__);
if (is_meta_ctrl(ctrl->id)) if (is_meta_ctrl(ctrl->id))
msm_vidc_update_meta_port_settings(inst); msm_vidc_update_meta_port_settings(inst);

View File

@@ -11,6 +11,7 @@
#include "msm_vidc_driver.h" #include "msm_vidc_driver.h"
#include "msm_vidc_platform.h" #include "msm_vidc_platform.h"
#include "msm_vidc_internal.h" #include "msm_vidc_internal.h"
#include "msm_vidc_control.h"
#include "msm_vidc_memory.h" #include "msm_vidc_memory.h"
#include "msm_vidc_debug.h" #include "msm_vidc_debug.h"
#include "msm_vidc_power.h" #include "msm_vidc_power.h"
@@ -20,6 +21,7 @@
#include "venus_hfi.h" #include "venus_hfi.h"
#include "venus_hfi_response.h" #include "venus_hfi_response.h"
#include "hfi_packet.h" #include "hfi_packet.h"
extern struct msm_vidc_core *g_core;
#define COUNT_BITS(a, out) { \ #define COUNT_BITS(a, out) { \
while ((a) >= 1) { \ while ((a) >= 1) { \
@@ -1024,6 +1026,8 @@ bool msm_vidc_allow_streamoff(struct msm_vidc_inst *inst, u32 type)
enum msm_vidc_allow msm_vidc_allow_qbuf(struct msm_vidc_inst *inst, u32 type) enum msm_vidc_allow msm_vidc_allow_qbuf(struct msm_vidc_inst *inst, u32 type)
{ {
int port = 0;
if (!inst) { if (!inst) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return MSM_VIDC_DISALLOW; return MSM_VIDC_DISALLOW;
@@ -1032,6 +1036,15 @@ enum msm_vidc_allow msm_vidc_allow_qbuf(struct msm_vidc_inst *inst, u32 type)
i_vpr_e(inst, "%s: inst in error state\n", __func__); i_vpr_e(inst, "%s: inst in error state\n", __func__);
return MSM_VIDC_DISALLOW; return MSM_VIDC_DISALLOW;
} }
port = v4l2_type_to_driver_port(inst, type, __func__);
if (port < 0)
return MSM_VIDC_DISALLOW;
/* defer queuing if streamon not completed */
if (!inst->vb2q[port].streaming)
return MSM_VIDC_DEFER;
if (type == INPUT_META_PLANE || type == OUTPUT_META_PLANE) if (type == INPUT_META_PLANE || type == OUTPUT_META_PLANE)
return MSM_VIDC_DEFER; return MSM_VIDC_DEFER;
@@ -1679,6 +1692,9 @@ struct msm_vidc_buffer *msm_vidc_get_driver_buf(struct msm_vidc_inst *inst,
buf->attr &= MSM_VIDC_ATTR_READ_ONLY; buf->attr &= MSM_VIDC_ATTR_READ_ONLY;
} }
/* treat every buffer as deferred buffer initially */
buf->attr |= MSM_VIDC_ATTR_DEFERRED;
rc = vb2_buffer_to_driver(vb2, buf); rc = vb2_buffer_to_driver(vb2, buf);
if (rc) if (rc)
goto error; goto error;
@@ -1736,7 +1752,7 @@ bool msm_vidc_is_super_buffer(struct msm_vidc_inst *inst)
struct msm_vidc_inst_capability *capability = NULL; struct msm_vidc_inst_capability *capability = NULL;
if (!inst || !inst->capabilities) { if (!inst || !inst->capabilities) {
i_vpr_e(inst, "%s: Invalid params\n", __func__); d_vpr_e("%s: Invalid params\n", __func__);
return false; return false;
} }
@@ -1745,49 +1761,98 @@ bool msm_vidc_is_super_buffer(struct msm_vidc_inst *inst)
return !!capability->cap[SUPER_FRAME].value; return !!capability->cap[SUPER_FRAME].value;
} }
int msm_vidc_queue_buffer(struct msm_vidc_inst *inst, struct vb2_buffer *vb2) static bool is_single_session(struct msm_vidc_inst *inst)
{ {
int rc = 0; struct msm_vidc_core *core;
struct msm_vidc_buffer *buf; u32 count = 0;
struct msm_vidc_buffer *meta;
enum msm_vidc_allow allow;
int port;
if (!inst || !vb2) { if (!inst) {
d_vpr_e("%s: Invalid params\n", __func__);
return false;
}
core = inst->core;
core_lock(core, __func__);
list_for_each_entry(inst, &core->instances, list)
count++;
core_unlock(core, __func__);
return count == 1;
}
bool msm_vidc_allow_decode_batch(struct msm_vidc_inst *inst)
{
struct msm_vidc_core *core;
bool allow = false;
if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
core = inst->core;
allow = inst->decode_batch.enable;
if (!allow) {
i_vpr_h(inst, "%s: batching already disabled\n", __func__);
goto exit;
}
allow = core->capabilities[DECODE_BATCH].value;
if (!allow) {
i_vpr_h(inst, "%s: core doesn't support batching\n", __func__);
goto exit;
}
allow = is_single_session(inst);
if (!allow) {
i_vpr_h(inst, "%s: multiple sessions running\n", __func__);
goto exit;
}
allow = is_decode_session(inst);
if (!allow) {
i_vpr_h(inst, "%s: not a decoder session\n", __func__);
goto exit;
}
allow = !is_thumbnail_session(inst);
if (!allow) {
i_vpr_h(inst, "%s: thumbnail session\n", __func__);
goto exit;
}
allow = is_realtime_session(inst);
if (!allow) {
i_vpr_h(inst, "%s: non-realtime session\n", __func__);
goto exit;
}
allow = !is_lowlatency_session(inst);
if (!allow) {
i_vpr_h(inst, "%s: lowlatency session\n", __func__);
goto exit;
}
exit:
i_vpr_h(inst, "%s: batching %s\n", __func__, allow ? "enabled" : "disabled");
return allow;
}
static int msm_vidc_queue_buffer(struct msm_vidc_inst *inst, struct msm_vidc_buffer *buf)
{
struct msm_vidc_buffer *meta;
int rc = 0;
if (!inst || !buf || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} }
buf = msm_vidc_get_driver_buf(inst, vb2); if (is_decode_session(inst) && is_input_buffer(buf->type) &&
if (!buf)
return -EINVAL;
/* skip queuing if streamon not completed */
port = v4l2_type_to_driver_port(inst, vb2->type, __func__);
if (port < 0)
return -EINVAL;
allow = msm_vidc_allow_qbuf(inst, vb2->type);
if (allow == MSM_VIDC_DISALLOW) {
i_vpr_e(inst, "%s: qbuf not allowed\n", __func__);
return -EINVAL;
}
if (!inst->vb2q[port].streaming || allow == MSM_VIDC_DEFER) {
buf->attr |= MSM_VIDC_ATTR_DEFERRED;
print_vidc_buffer(VIDC_HIGH, "high", "qbuf deferred", inst, buf);
return 0;
}
if (is_decode_session(inst) &&
inst->capabilities->cap[CODEC_CONFIG].value) { inst->capabilities->cap[CODEC_CONFIG].value) {
buf->flags |= MSM_VIDC_BUF_FLAG_CODECCONFIG; buf->flags |= MSM_VIDC_BUF_FLAG_CODECCONFIG;
inst->capabilities->cap[CODEC_CONFIG].value = 0; msm_vidc_update_cap_value(inst, CODEC_CONFIG, 0, __func__);
}
if (buf->type == MSM_VIDC_BUF_INPUT) {
inst->power.buffer_counter++;
msm_vidc_scale_power(inst, true);
} }
print_vidc_buffer(VIDC_HIGH, "high", "qbuf", inst, buf); print_vidc_buffer(VIDC_HIGH, "high", "qbuf", inst, buf);
@@ -1819,6 +1884,70 @@ int msm_vidc_queue_buffer(struct msm_vidc_inst *inst, struct vb2_buffer *vb2)
else if (buf->type == MSM_VIDC_BUF_OUTPUT) else if (buf->type == MSM_VIDC_BUF_OUTPUT)
msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_FTB); msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_FTB);
return 0;
}
int msm_vidc_queue_buffer_batch(struct msm_vidc_inst *inst)
{
struct msm_vidc_buffers *buffers;
struct msm_vidc_buffer *buf;
int rc = 0;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_OUTPUT, __func__);
if (!buffers)
return -EINVAL;
msm_vidc_scale_power(inst, true);
list_for_each_entry(buf, &buffers->list, list) {
if (!(buf->attr & MSM_VIDC_ATTR_DEFERRED))
continue;
rc = msm_vidc_queue_buffer(inst, buf);
if (rc)
return rc;
}
return 0;
}
int msm_vidc_queue_buffer_single(struct msm_vidc_inst *inst, struct vb2_buffer *vb2)
{
int rc = 0;
struct msm_vidc_buffer *buf;
enum msm_vidc_allow allow;
if (!inst || !vb2) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
buf = msm_vidc_get_driver_buf(inst, vb2);
if (!buf)
return -EINVAL;
allow = msm_vidc_allow_qbuf(inst, vb2->type);
if (allow == MSM_VIDC_DISALLOW) {
i_vpr_e(inst, "%s: qbuf not allowed\n", __func__);
return -EINVAL;
} else if (allow == MSM_VIDC_DEFER) {
print_vidc_buffer(VIDC_HIGH, "high", "qbuf deferred", inst, buf);
return 0;
}
if (buf->type == MSM_VIDC_BUF_INPUT) {
inst->power.buffer_counter++;
msm_vidc_scale_power(inst, true);
}
rc = msm_vidc_queue_buffer(inst, buf);
if (rc)
return rc;
return rc; return rc;
} }
@@ -2558,6 +2687,9 @@ int msm_vidc_session_streamoff(struct msm_vidc_inst *inst,
rc = -EINVAL; rc = -EINVAL;
goto error; goto error;
} }
/* flush deferred buffers */
msm_vidc_flush_buffers(inst, buffer_type);
return 0; return 0;
error: error:
@@ -3106,6 +3238,39 @@ void msm_vidc_fw_unload_handler(struct work_struct *work)
void msm_vidc_batch_handler(struct work_struct *work) void msm_vidc_batch_handler(struct work_struct *work)
{ {
struct msm_vidc_inst *inst;
enum msm_vidc_allow allow;
int rc = 0;
inst = container_of(work, struct msm_vidc_inst, decode_batch.work.work);
inst = get_inst_ref(g_core, inst);
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return;
}
inst_lock(inst, __func__);
if (is_session_error(inst)) {
i_vpr_e(inst, "%s: failled. Session error\n", __func__);
goto exit;
}
allow = msm_vidc_allow_qbuf(inst, OUTPUT_MPLANE);
if (allow != MSM_VIDC_ALLOW) {
i_vpr_e(inst, "%s: not allowed in state: %s\n", __func__, state_name(inst->state));
goto exit;
}
i_vpr_h(inst, "%s: queue pending batch buffers\n", __func__);
rc = msm_vidc_queue_buffer_batch(inst);
if (rc) {
i_vpr_e(inst, "%s: batch qbufs failed\n", __func__);
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
}
exit:
inst_unlock(inst, __func__);
put_inst(inst);
} }
int msm_vidc_flush_buffers(struct msm_vidc_inst* inst, int msm_vidc_flush_buffers(struct msm_vidc_inst* inst,

View File

@@ -180,12 +180,19 @@ static int msm_vidc_deinitialize_core(struct msm_vidc_core *core)
mutex_destroy(&core->lock); mutex_destroy(&core->lock);
msm_vidc_change_core_state(core, MSM_VIDC_CORE_DEINIT, __func__); msm_vidc_change_core_state(core, MSM_VIDC_CORE_DEINIT, __func__);
if (core->batch_workq)
destroy_workqueue(core->batch_workq);
if (core->pm_workq) if (core->pm_workq)
destroy_workqueue(core->pm_workq); destroy_workqueue(core->pm_workq);
if (core->device_workq) if (core->device_workq)
destroy_workqueue(core->device_workq); destroy_workqueue(core->device_workq);
core->batch_workq = NULL;
core->pm_workq = NULL;
core->device_workq = NULL;
return rc; return rc;
} }
@@ -211,7 +218,13 @@ static int msm_vidc_initialize_core(struct msm_vidc_core *core)
core->pm_workq = create_singlethread_workqueue("pm_workq"); core->pm_workq = create_singlethread_workqueue("pm_workq");
if (!core->pm_workq) { if (!core->pm_workq) {
d_vpr_e("%s: create pm workq failed\n", __func__); d_vpr_e("%s: create pm workq failed\n", __func__);
destroy_workqueue(core->device_workq); rc = -EINVAL;
goto exit;
}
core->batch_workq = create_singlethread_workqueue("batch_workq");
if (!core->batch_workq) {
d_vpr_e("%s: create batch workq failed\n", __func__);
rc = -EINVAL; rc = -EINVAL;
goto exit; goto exit;
} }
@@ -224,10 +237,20 @@ static int msm_vidc_initialize_core(struct msm_vidc_core *core)
INIT_WORK(&core->smmu_fault_work, msm_vidc_smmu_fault_work_handler); INIT_WORK(&core->smmu_fault_work, msm_vidc_smmu_fault_work_handler);
INIT_DELAYED_WORK(&core->pm_work, venus_hfi_pm_work_handler); INIT_DELAYED_WORK(&core->pm_work, venus_hfi_pm_work_handler);
INIT_DELAYED_WORK(&core->fw_unload_work, msm_vidc_fw_unload_handler); INIT_DELAYED_WORK(&core->fw_unload_work, msm_vidc_fw_unload_handler);
INIT_DELAYED_WORK(&core->batch_work, msm_vidc_batch_handler);
INIT_WORK(&core->ssr_work, msm_vidc_ssr_handler); INIT_WORK(&core->ssr_work, msm_vidc_ssr_handler);
return 0;
exit: exit:
if (core->batch_workq)
destroy_workqueue(core->batch_workq);
if (core->pm_workq)
destroy_workqueue(core->pm_workq);
if (core->device_workq)
destroy_workqueue(core->device_workq);
core->batch_workq = NULL;
core->pm_workq = NULL;
core->device_workq = NULL;
return rc; return rc;
} }