From 60a472d3b2fef8ea1ff221d0e7ef32aa6db31ff0 Mon Sep 17 00:00:00 2001 From: Deva Ramasubramanian Date: Thu, 30 May 2013 20:16:48 -0700 Subject: [PATCH] msm: vidc: Add support for V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL allows for clients to request higher than normal performance from the core. Change-Id: I0cd4e56854f35bacd2aa26146e990e0537b3909f Signed-off-by: Deva Ramasubramanian --- drivers/media/platform/msm/vidc/msm_vdec.c | 37 ++++++++++++++++++- drivers/media/platform/msm/vidc/msm_venc.c | 35 ++++++++++++++++++ .../media/platform/msm/vidc/msm_vidc_common.c | 37 +++++++++++++++++-- .../platform/msm/vidc/msm_vidc_internal.h | 1 + include/linux/videodev2.h | 6 ++- 5 files changed, 110 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c index f83896fb79e..8f5c32b3317 100644 --- a/drivers/media/platform/msm/vidc/msm_vdec.c +++ b/drivers/media/platform/msm/vidc/msm_vdec.c @@ -69,6 +69,12 @@ static const char *const mpeg_video_vidc_extradata[] = { "Extradata mpeg2 seqdisp", }; +static const char *const perf_level[] = { + "Nominal", + "Performance", + "Turbo" +}; + static struct msm_vidc_ctrl msm_vdec_ctrls[] = { { .id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT, @@ -230,6 +236,19 @@ static struct msm_vidc_ctrl msm_vdec_ctrls[] = { .qmenu = mpeg_video_vidc_extradata, .step = 0, }, + { + .id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL, + .name = "Encoder Performance Level", + .type = V4L2_CTRL_TYPE_MENU, + .minimum = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL, + .maximum = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO, + .default_value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL, + .menu_skip_mask = ~( + (1 << V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL) | + (1 << V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO)), + .qmenu = perf_level, + .step = 0, + }, }; #define NUM_CTRLS ARRAY_SIZE(msm_vdec_ctrls) @@ -1240,7 +1259,7 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) u32 control_idx = 0; enum hal_property property_id = 0; u32 property_val = 0; - void *pdata; + void *pdata = NULL; struct hfi_device *hdev; if (!inst || !inst->core || !inst->core->device) { @@ -1317,6 +1336,22 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) pdata = &extra; break; } + case V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL: + switch (ctrl->val) { + case V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL: + inst->flags &= ~VIDC_TURBO; + break; + case V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO: + inst->flags |= VIDC_TURBO; + break; + default: + dprintk(VIDC_ERR, "Perf mode %x not supported", + ctrl->val); + rc = -ENOTSUPP; + break; + } + + break; default: break; } diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c index 0995fcac57c..3956f0a1579 100644 --- a/drivers/media/platform/msm/vidc/msm_venc.c +++ b/drivers/media/platform/msm/vidc/msm_venc.c @@ -108,6 +108,12 @@ static const char *const mpeg_video_vidc_extradata[] = { "Extradata aspect ratio", }; +static const char *const perf_level[] = { + "Nominal", + "Performance", + "Turbo" +}; + enum msm_venc_ctrl_cluster { MSM_VENC_CTRL_CLUSTER_QP = 1 << 0, MSM_VENC_CTRL_CLUSTER_INTRA_PERIOD = 1 << 1, @@ -664,6 +670,19 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = { .default_value = V4L2_MPEG_VIDC_VIDEO_H264_AU_DELIMITER_DISABLED, }, + { + .id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL, + .name = "Encoder Performance Level", + .type = V4L2_CTRL_TYPE_MENU, + .minimum = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL, + .maximum = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO, + .default_value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL, + .menu_skip_mask = ~( + (1 << V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL) | + (1 << V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO)), + .qmenu = perf_level, + .step = 0, + }, }; #define NUM_CTRLS ARRAY_SIZE(msm_venc_ctrls) @@ -1762,6 +1781,22 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) } pdata = &enable; + break; + case V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL: + switch (ctrl->val) { + case V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL: + inst->flags &= ~VIDC_TURBO; + break; + case V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO: + inst->flags |= VIDC_TURBO; + break; + default: + dprintk(VIDC_ERR, "Perf mode %x not supported", + ctrl->val); + rc = -ENOTSUPP; + break; + } + break; default: rc = -ENOTSUPP; diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index efb76b62b21..8ccd1924d9e 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -46,6 +46,28 @@ u32 __mbs = (__h >> 4) * (__w >> 4);\ __mbs;\ }) +static bool is_turbo_requested(struct msm_vidc_core *core, + enum session_type type) +{ + struct msm_vidc_inst *inst = NULL; + + list_for_each_entry(inst, &core->instances, list) { + bool wants_turbo = false; + + mutex_lock(&inst->lock); + if (inst->session_type == type && + inst->state >= MSM_VIDC_OPEN_DONE && + inst->state < MSM_VIDC_STOP_DONE) { + wants_turbo = inst->flags & VIDC_TURBO; + } + mutex_unlock(&inst->lock); + + if (wants_turbo) + return true; + } + + return false; +} static int msm_comm_get_load(struct msm_vidc_core *core, enum session_type type) @@ -87,7 +109,10 @@ static int msm_comm_scale_bus(struct msm_vidc_core *core, return -EINVAL; } - load = msm_comm_get_load(core, type); + if (is_turbo_requested(core, type)) + load = core->resources.max_load; + else + load = msm_comm_get_load(core, type); rc = call_hfi_op(hdev, scale_bus, hdev->hfi_device_data, load, type, mtype); @@ -932,8 +957,14 @@ static int msm_comm_scale_clocks(struct msm_vidc_core *core) __func__, hdev); return -EINVAL; } - num_mbs_per_sec = msm_comm_get_load(core, MSM_VIDC_ENCODER); - num_mbs_per_sec += msm_comm_get_load(core, MSM_VIDC_DECODER); + + if (is_turbo_requested(core, MSM_VIDC_ENCODER) || + is_turbo_requested(core, MSM_VIDC_DECODER)) { + num_mbs_per_sec = core->resources.max_load; + } else { + num_mbs_per_sec = msm_comm_get_load(core, MSM_VIDC_ENCODER); + num_mbs_per_sec += msm_comm_get_load(core, MSM_VIDC_DECODER); + } dprintk(VIDC_INFO, "num_mbs_per_sec = %d\n", num_mbs_per_sec); rc = call_hfi_op(hdev, scale_clocks, diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h index e9cb1595569..965cb8f2d26 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h @@ -170,6 +170,7 @@ struct msm_vidc_debug { enum msm_vidc_modes { VIDC_SECURE = 1 << 0, + VIDC_TURBO = 1 << 1, }; struct msm_vidc_core_capability { diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index e883ad7600a..c6da2c38561 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -1844,9 +1844,11 @@ enum v4l2_mpeg_vidc_video_h264_vui_timing_info { #define V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL (V4L2_CID_MPEG_MSM_VIDC_BASE + 26) enum v4l2_mpeg_vidc_perf_level { - V4L2_CID_MPEG_VIDC_PERF_LEVEL_PERFORMANCE = 0, - V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO = 1, + V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL = 0, + V4L2_CID_MPEG_VIDC_PERF_LEVEL_PERFORMANCE = 1, + V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO = 2, }; + #define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_GOB \ (V4L2_CID_MPEG_MSM_VIDC_BASE+27) #define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_DELIVERY_MODE \