waipio: driver: Add support for work mode and route

Iris2 specific calculations for Work Mode and Route.
Also add quality mode support.

Change-Id: I7a1e2fa27236aa749978d146d85fd0af6177084c
Signed-off-by: Chinmay Sawarkar <chinmays@codeaurora.org>
This commit is contained in:
Chinmay Sawarkar
2021-01-15 18:38:56 -08:00
rodzic 11556af3f4
commit dca32dc984
4 zmienionych plików z 177 dodań i 6 usunięć

Wyświetl plik

@@ -17,7 +17,6 @@
#include "msm_vidc_buffer.h"
#include "msm_vidc_debug.h"
#define VBIF_BASE_OFFS_IRIS2 0x00080000
#define CPU_BASE_OFFS_IRIS2 0x000A0000
#define AON_BASE_OFFS 0x000E0000
@@ -484,6 +483,170 @@ static int __boot_firmware_iris2(struct msm_vidc_core *vidc_core)
return rc;
}
bool res_is_greater_than(u32 width, u32 height,
u32 ref_width, u32 ref_height)
{
u32 num_mbs = NUM_MBS_PER_FRAME(height, width);
u32 max_side = max(ref_width, ref_height);
if (num_mbs > NUM_MBS_PER_FRAME(ref_height, ref_width) ||
width > max_side ||
height > max_side)
return true;
else
return false;
}
bool res_is_less_than_or_equal_to(u32 width, u32 height,
u32 ref_width, u32 ref_height)
{
u32 num_mbs = NUM_MBS_PER_FRAME(height, width);
u32 max_side = max(ref_width, ref_height);
if (num_mbs <= NUM_MBS_PER_FRAME(ref_height, ref_width) &&
width <= max_side &&
height <= max_side)
return true;
else
return false;
}
int msm_vidc_decide_work_mode_iris2(struct msm_vidc_inst* inst)
{
u32 work_mode;
struct v4l2_format* out_f;
struct v4l2_format* inp_f;
u32 width, height;
bool res_ok = false;
bool lowlatency = false;
if (!inst || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
work_mode = MSM_VIDC_STAGE_2;
out_f = &inst->fmts[OUTPUT_PORT];
inp_f = &inst->fmts[INPUT_PORT];
if (is_decode_session(inst)) {
height = out_f->fmt.pix_mp.height;
width = out_f->fmt.pix_mp.width;
res_ok = res_is_less_than_or_equal_to(width, height, 1280, 720);
if (inst->capabilities->cap[CODED_FRAMES].value ==
CODED_FRAMES_ADAPTIVE_FIELDS ||
inst->capabilities->cap[LOWLATENCY_MODE].value ||
res_ok) {
work_mode = MSM_VIDC_STAGE_1;
}
} else if (is_encode_session(inst)) {
height = inp_f->fmt.pix_mp.height;
width = inp_f->fmt.pix_mp.width;
res_ok = !res_is_greater_than(width, height, 4096, 2160);
if (res_ok &&
(inst->capabilities->cap[LOWLATENCY_MODE].value)) {
work_mode = MSM_VIDC_STAGE_1;
/* For WORK_MODE_1, set Low Latency mode by default */
lowlatency = true;
}
if (inst->capabilities->cap[LOSSLESS].value) {
/*TODO Set 2 stage in case of ALL INTRA */
work_mode = MSM_VIDC_STAGE_2;
lowlatency = false;
}
}
else {
d_vpr_e("%s: invalid session type\n", __func__);
return -EINVAL;
}
s_vpr_h(inst->sid, "Configuring work mode = %u low latency = %u",
work_mode, lowlatency);
inst->capabilities->cap[STAGE].value = work_mode;
/* TODO If Encode then Set Low Latency (Enable/Disable)
* and Update internal cap struct
*/
return 0;
}
int msm_vidc_decide_work_route_iris2(struct msm_vidc_inst* inst)
{
u32 work_route;
struct msm_vidc_core* core;
if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
core = inst->core;
work_route = core->capabilities[NUM_VPP_PIPE].value;
if (is_decode_session(inst)) {
if (inst->capabilities->cap[CODED_FRAMES].value ==
CODED_FRAMES_ADAPTIVE_FIELDS)
work_route = MSM_VIDC_PIPE_1;
} else if (is_encode_session(inst)) {
u32 slice_mode, width, height;
struct v4l2_format* f;
f = &inst->fmts[INPUT_PORT];
height = f->fmt.pix_mp.height;
width = f->fmt.pix_mp.width;
slice_mode = inst->capabilities->cap[SLICE_MODE].value;
/*TODO Pipe=1 for legacy CBR*/
if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES)
work_route = MSM_VIDC_PIPE_1;
} else {
d_vpr_e("%s: invalid session type\n", __func__);
return -EINVAL;
}
s_vpr_h(inst->sid, "Configuring work route = %u", work_route);
inst->capabilities->cap[PIPE].value = work_route;
return 0;
}
int msm_vidc_decide_quality_mode_iris2(struct msm_vidc_inst* inst)
{
struct msm_vidc_inst_capability* capability = inst->capabilities;
struct msm_vidc_core *core;
u32 mbpf, mbps, max_hq_mbpf, max_hq_mbps;
u32 mode;
if (!inst || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
if (!is_encode_session(inst))
return 0;
mode = MSM_VIDC_POWER_SAVE_MODE;
mbpf = msm_vidc_get_mbs_per_frame(inst);
mbps = mbpf * msm_vidc_get_fps(inst);
core = inst->core;
max_hq_mbpf = core->capabilities[MAX_MBPF_HQ].value;;
max_hq_mbps = core->capabilities[MAX_MBPS_HQ].value;;
/* Power saving always disabled for CQ and LOSSLESS RC modes. */
if (inst->capabilities->cap[LOSSLESS].value ||
(mbpf <= max_hq_mbpf && mbps <= max_hq_mbps))
mode = MSM_VIDC_MAX_QUALITY_MODE;
inst->flags = mode == MSM_VIDC_POWER_SAVE_MODE ?
inst->flags | VIDC_LOW_POWER :
inst->flags & ~VIDC_LOW_POWER;
capability->cap[QUALITY_MODE].value = mode;
return 0;
}
static struct msm_vidc_venus_ops iris2_ops = {
.boot_firmware = __boot_firmware_iris2,
.interrupt_init = __interrupt_init_iris2,
@@ -504,9 +667,9 @@ static struct msm_vidc_session_ops msm_session_ops = {
.extra_count = msm_buffer_extra_count_iris2,
.calc_freq = msm_vidc_calc_freq_iris2,
.calc_bw = msm_vidc_calc_bw_iris2,
.decide_work_route = NULL,
.decide_work_mode = NULL,
.decide_core_and_power_mode = NULL,
.decide_work_route = msm_vidc_decide_work_route_iris2,
.decide_work_mode = msm_vidc_decide_work_mode_iris2,
.decide_quality_mode = msm_vidc_decide_quality_mode_iris2,
};
int msm_vidc_init_iris2(struct msm_vidc_core *core)