Skip to content

Commit 3cfe581

Browse files
Dikshita Agarwalmchehab
authored andcommitted
media: venus: Enable low power setting for encoder
Set the FW to run in low power for encoder to accommodate more session without losing much on quality. Signed-off-by: Dikshita Agarwal <[email protected]> Signed-off-by: Stanimir Varbanov <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent 51bb398 commit 3cfe581

File tree

8 files changed

+167
-35
lines changed

8 files changed

+167
-35
lines changed

drivers/media/platform/qcom/venus/core.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ struct clock_data {
292292
unsigned long freq;
293293
unsigned long vpp_freq;
294294
unsigned long vsp_freq;
295+
unsigned long low_power_freq;
295296
};
296297

297298
#define to_venus_buffer(ptr) container_of(ptr, struct venus_buffer, vb)
@@ -315,6 +316,10 @@ struct venus_ts_metadata {
315316
struct v4l2_timecode tc;
316317
};
317318

319+
enum venus_inst_modes {
320+
VENUS_LOW_POWER = BIT(0),
321+
};
322+
318323
/**
319324
* struct venus_inst - holds per instance parameters
320325
*
@@ -444,6 +449,7 @@ struct venus_inst {
444449
unsigned int pic_struct;
445450
bool next_buf_last;
446451
bool drain_active;
452+
enum venus_inst_modes flags;
447453
};
448454

449455
#define IS_V1(core) ((core)->res->hfi_version == HFI_VERSION_1XX)

drivers/media/platform/qcom/venus/helpers.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1627,6 +1627,8 @@ int venus_helper_session_init(struct venus_inst *inst)
16271627
session_type);
16281628
inst->clk_data.vsp_freq = hfi_platform_get_codec_vsp_freq(version, codec,
16291629
session_type);
1630+
inst->clk_data.low_power_freq = hfi_platform_get_codec_lp_freq(version, codec,
1631+
session_type);
16301632

16311633
return 0;
16321634
}

drivers/media/platform/qcom/venus/hfi_helper.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -415,9 +415,6 @@
415415
#define HFI_BUFFER_MODE_RING 0x1000002
416416
#define HFI_BUFFER_MODE_DYNAMIC 0x1000003
417417

418-
#define HFI_VENC_PERFMODE_MAX_QUALITY 0x1
419-
#define HFI_VENC_PERFMODE_POWER_SAVE 0x2
420-
421418
/*
422419
* HFI_PROPERTY_SYS_COMMON_START
423420
* HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET + 0x0000
@@ -848,6 +845,13 @@ struct hfi_framesize {
848845
u32 height;
849846
};
850847

848+
#define HFI_VENC_PERFMODE_MAX_QUALITY 0x1
849+
#define HFI_VENC_PERFMODE_POWER_SAVE 0x2
850+
851+
struct hfi_perf_mode {
852+
u32 video_perf_mode;
853+
};
854+
851855
#define VIDC_CORE_ID_DEFAULT 0
852856
#define VIDC_CORE_ID_1 1
853857
#define VIDC_CORE_ID_2 2

drivers/media/platform/qcom/venus/hfi_platform.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,22 @@ hfi_platform_get_codec_vsp_freq(enum hfi_version version, u32 codec, u32 session
5050
return freq;
5151
}
5252

53+
unsigned long
54+
hfi_platform_get_codec_lp_freq(enum hfi_version version, u32 codec, u32 session_type)
55+
{
56+
const struct hfi_platform *plat;
57+
unsigned long freq = 0;
58+
59+
plat = hfi_platform_get(version);
60+
if (!plat)
61+
return 0;
62+
63+
if (plat->codec_lp_freq)
64+
freq = plat->codec_lp_freq(session_type, codec);
65+
66+
return freq;
67+
}
68+
5369
u8 hfi_platform_num_vpp_pipes(enum hfi_version version)
5470
{
5571
const struct hfi_platform *plat;

drivers/media/platform/qcom/venus/hfi_platform.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,13 @@ struct hfi_platform_codec_freq_data {
4343
u32 session_type;
4444
unsigned long vpp_freq;
4545
unsigned long vsp_freq;
46+
unsigned long low_power_freq;
4647
};
4748

4849
struct hfi_platform {
4950
unsigned long (*codec_vpp_freq)(u32 session_type, u32 codec);
5051
unsigned long (*codec_vsp_freq)(u32 session_type, u32 codec);
52+
unsigned long (*codec_lp_freq)(u32 session_type, u32 codec);
5153
void (*codecs)(u32 *enc_codecs, u32 *dec_codecs, u32 *count);
5254
const struct hfi_plat_caps *(*capabilities)(unsigned int *entries);
5355
u8 (*num_vpp_pipes)(void);
@@ -63,5 +65,7 @@ unsigned long hfi_platform_get_codec_vpp_freq(enum hfi_version version, u32 code
6365
u32 session_type);
6466
unsigned long hfi_platform_get_codec_vsp_freq(enum hfi_version version, u32 codec,
6567
u32 session_type);
68+
unsigned long hfi_platform_get_codec_lp_freq(enum hfi_version version, u32 codec,
69+
u32 session_type);
6670
u8 hfi_platform_num_vpp_pipes(enum hfi_version version);
6771
#endif

drivers/media/platform/qcom/venus/hfi_platform_v4.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -262,14 +262,14 @@ static void get_codecs(u32 *enc_codecs, u32 *dec_codecs, u32 *count)
262262
}
263263

264264
static const struct hfi_platform_codec_freq_data codec_freq_data[] = {
265-
{ V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_ENC, 675, 10 },
266-
{ V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_ENC, 675, 10 },
267-
{ V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_ENC, 675, 10 },
268-
{ V4L2_PIX_FMT_MPEG2, VIDC_SESSION_TYPE_DEC, 200, 10 },
269-
{ V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_DEC, 200, 10 },
270-
{ V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_DEC, 200, 10 },
271-
{ V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_DEC, 200, 10 },
272-
{ V4L2_PIX_FMT_VP9, VIDC_SESSION_TYPE_DEC, 200, 10 },
265+
{ V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_ENC, 675, 10, 320 },
266+
{ V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_ENC, 675, 10, 320 },
267+
{ V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_ENC, 675, 10, 320 },
268+
{ V4L2_PIX_FMT_MPEG2, VIDC_SESSION_TYPE_DEC, 200, 10, 200 },
269+
{ V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_DEC, 200, 10, 200 },
270+
{ V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_DEC, 200, 10, 200 },
271+
{ V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_DEC, 200, 10, 200 },
272+
{ V4L2_PIX_FMT_VP9, VIDC_SESSION_TYPE_DEC, 200, 10, 200 },
273273
};
274274

275275
static const struct hfi_platform_codec_freq_data *
@@ -311,9 +311,21 @@ static unsigned long codec_vsp_freq(u32 session_type, u32 codec)
311311
return 0;
312312
}
313313

314+
static unsigned long codec_lp_freq(u32 session_type, u32 codec)
315+
{
316+
const struct hfi_platform_codec_freq_data *data;
317+
318+
data = get_codec_freq_data(session_type, codec);
319+
if (data)
320+
return data->low_power_freq;
321+
322+
return 0;
323+
}
324+
314325
const struct hfi_platform hfi_plat_v4 = {
315326
.codec_vpp_freq = codec_vpp_freq,
316327
.codec_vsp_freq = codec_vsp_freq,
328+
.codec_lp_freq = codec_lp_freq,
317329
.codecs = get_codecs,
318330
.capabilities = get_capabilities,
319331
};

drivers/media/platform/qcom/venus/hfi_platform_v6.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -262,14 +262,14 @@ static void get_codecs(u32 *enc_codecs, u32 *dec_codecs, u32 *count)
262262
}
263263

264264
static const struct hfi_platform_codec_freq_data codec_freq_data[] = {
265-
{ V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_ENC, 675, 25 },
266-
{ V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_ENC, 675, 25 },
267-
{ V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_ENC, 675, 60 },
268-
{ V4L2_PIX_FMT_MPEG2, VIDC_SESSION_TYPE_DEC, 200, 25 },
269-
{ V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_DEC, 200, 25 },
270-
{ V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_DEC, 200, 25 },
271-
{ V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_DEC, 200, 60 },
272-
{ V4L2_PIX_FMT_VP9, VIDC_SESSION_TYPE_DEC, 200, 60 },
265+
{ V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_ENC, 675, 25, 320 },
266+
{ V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_ENC, 675, 25, 320 },
267+
{ V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_ENC, 675, 60, 320 },
268+
{ V4L2_PIX_FMT_MPEG2, VIDC_SESSION_TYPE_DEC, 200, 25, 200 },
269+
{ V4L2_PIX_FMT_H264, VIDC_SESSION_TYPE_DEC, 200, 25, 200 },
270+
{ V4L2_PIX_FMT_HEVC, VIDC_SESSION_TYPE_DEC, 200, 25, 200 },
271+
{ V4L2_PIX_FMT_VP8, VIDC_SESSION_TYPE_DEC, 200, 60, 200 },
272+
{ V4L2_PIX_FMT_VP9, VIDC_SESSION_TYPE_DEC, 200, 60, 200 },
273273
};
274274

275275
static const struct hfi_platform_codec_freq_data *
@@ -311,6 +311,17 @@ static unsigned long codec_vsp_freq(u32 session_type, u32 codec)
311311
return 0;
312312
}
313313

314+
static unsigned long codec_lp_freq(u32 session_type, u32 codec)
315+
{
316+
const struct hfi_platform_codec_freq_data *data;
317+
318+
data = get_codec_freq_data(session_type, codec);
319+
if (data)
320+
return data->low_power_freq;
321+
322+
return 0;
323+
}
324+
314325
static u8 num_vpp_pipes(void)
315326
{
316327
return 4;
@@ -319,6 +330,7 @@ static u8 num_vpp_pipes(void)
319330
const struct hfi_platform hfi_plat_v6 = {
320331
.codec_vpp_freq = codec_vpp_freq,
321332
.codec_vsp_freq = codec_vsp_freq,
333+
.codec_lp_freq = codec_lp_freq,
322334
.codecs = get_codecs,
323335
.capabilities = get_capabilities,
324336
.num_vpp_pipes = num_vpp_pipes,

drivers/media/platform/qcom/venus/pm_helpers.c

Lines changed: 92 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -523,8 +523,50 @@ static int poweron_coreid(struct venus_core *core, unsigned int coreid_mask)
523523
return 0;
524524
}
525525

526+
static inline int power_save_mode_enable(struct venus_inst *inst,
527+
bool enable)
528+
{
529+
struct venc_controls *enc_ctr = &inst->controls.enc;
530+
const u32 ptype = HFI_PROPERTY_CONFIG_VENC_PERF_MODE;
531+
u32 venc_mode;
532+
int ret = 0;
533+
534+
if (inst->session_type != VIDC_SESSION_TYPE_ENC)
535+
return 0;
536+
537+
if (enc_ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
538+
enable = false;
539+
540+
venc_mode = enable ? HFI_VENC_PERFMODE_POWER_SAVE :
541+
HFI_VENC_PERFMODE_MAX_QUALITY;
542+
543+
ret = hfi_session_set_property(inst, ptype, &venc_mode);
544+
if (ret)
545+
return ret;
546+
547+
inst->flags = enable ? inst->flags | VENUS_LOW_POWER :
548+
inst->flags & ~VENUS_LOW_POWER;
549+
550+
return ret;
551+
}
552+
553+
static int move_core_to_power_save_mode(struct venus_core *core,
554+
u32 core_id)
555+
{
556+
struct venus_inst *inst = NULL;
557+
558+
mutex_lock(&core->lock);
559+
list_for_each_entry(inst, &core->instances, list) {
560+
if (inst->clk_data.core_id == core_id &&
561+
inst->session_type == VIDC_SESSION_TYPE_ENC)
562+
power_save_mode_enable(inst, true);
563+
}
564+
mutex_unlock(&core->lock);
565+
return 0;
566+
}
567+
526568
static void
527-
min_loaded_core(struct venus_inst *inst, u32 *min_coreid, u32 *min_load)
569+
min_loaded_core(struct venus_inst *inst, u32 *min_coreid, u32 *min_load, bool low_power)
528570
{
529571
u32 mbs_per_sec, load, core1_load = 0, core2_load = 0;
530572
u32 cores_max = core_num_max(inst);
@@ -542,7 +584,14 @@ min_loaded_core(struct venus_inst *inst, u32 *min_coreid, u32 *min_load)
542584
if (inst_pos->state != INST_START)
543585
continue;
544586

545-
vpp_freq = inst_pos->clk_data.vpp_freq;
587+
if (inst->session_type == VIDC_SESSION_TYPE_DEC)
588+
vpp_freq = inst_pos->clk_data.vpp_freq;
589+
else if (inst->session_type == VIDC_SESSION_TYPE_ENC)
590+
vpp_freq = low_power ? inst_pos->clk_data.vpp_freq :
591+
inst_pos->clk_data.low_power_freq;
592+
else
593+
continue;
594+
546595
coreid = inst_pos->clk_data.core_id;
547596

548597
mbs_per_sec = load_per_instance(inst_pos);
@@ -574,9 +623,11 @@ static int decide_core(struct venus_inst *inst)
574623
{
575624
const u32 ptype = HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE;
576625
struct venus_core *core = inst->core;
577-
u32 min_coreid, min_load, inst_load;
626+
u32 min_coreid, min_load, cur_inst_load;
627+
u32 min_lp_coreid, min_lp_load, cur_inst_lp_load;
578628
struct hfi_videocores_usage_type cu;
579629
unsigned long max_freq;
630+
int ret = 0;
580631

581632
if (legacy_binding) {
582633
if (inst->session_type == VIDC_SESSION_TYPE_DEC)
@@ -590,23 +641,43 @@ static int decide_core(struct venus_inst *inst)
590641
if (inst->clk_data.core_id != VIDC_CORE_ID_DEFAULT)
591642
return 0;
592643

593-
inst_load = load_per_instance(inst);
594-
inst_load *= inst->clk_data.vpp_freq;
595-
max_freq = core->res->freq_tbl[0].freq;
644+
cur_inst_load = load_per_instance(inst);
645+
cur_inst_load *= inst->clk_data.vpp_freq;
646+
/*TODO : divide this inst->load by work_route */
596647

597-
min_loaded_core(inst, &min_coreid, &min_load);
648+
cur_inst_lp_load = load_per_instance(inst);
649+
cur_inst_lp_load *= inst->clk_data.low_power_freq;
650+
/*TODO : divide this inst->load by work_route */
598651

599-
if ((inst_load + min_load) > max_freq) {
600-
dev_warn(core->dev, "HW is overloaded, needed: %u max: %lu\n",
601-
inst_load, max_freq);
652+
max_freq = core->res->freq_tbl[0].freq;
653+
654+
min_loaded_core(inst, &min_coreid, &min_load, false);
655+
min_loaded_core(inst, &min_lp_coreid, &min_lp_load, true);
656+
657+
if (cur_inst_load + min_load <= max_freq) {
658+
inst->clk_data.core_id = min_coreid;
659+
cu.video_core_enable_mask = min_coreid;
660+
} else if (cur_inst_lp_load + min_load <= max_freq) {
661+
/* Move current instance to LP and return */
662+
inst->clk_data.core_id = min_coreid;
663+
cu.video_core_enable_mask = min_coreid;
664+
power_save_mode_enable(inst, true);
665+
} else if (cur_inst_lp_load + min_lp_load <= max_freq) {
666+
/* Move all instances to LP mode and return */
667+
inst->clk_data.core_id = min_lp_coreid;
668+
cu.video_core_enable_mask = min_lp_coreid;
669+
move_core_to_power_save_mode(core, min_lp_coreid);
670+
} else {
671+
dev_warn(core->dev, "HW can't support this load");
602672
return -EINVAL;
603673
}
604674

605-
inst->clk_data.core_id = min_coreid;
606-
cu.video_core_enable_mask = min_coreid;
607-
608675
done:
609-
return hfi_session_set_property(inst, ptype, &cu);
676+
ret = hfi_session_set_property(inst, ptype, &cu);
677+
if (ret)
678+
return ret;
679+
680+
return ret;
610681
}
611682

612683
static int acquire_core(struct venus_inst *inst)
@@ -1005,7 +1076,7 @@ static int core_power_v4(struct venus_core *core, int on)
10051076
static unsigned long calculate_inst_freq(struct venus_inst *inst,
10061077
unsigned long filled_len)
10071078
{
1008-
unsigned long vpp_freq = 0, vsp_freq = 0;
1079+
unsigned long vpp_freq_per_mb = 0, vpp_freq = 0, vsp_freq = 0;
10091080
u32 fps = (u32)inst->fps;
10101081
u32 mbs_per_sec;
10111082

@@ -1014,7 +1085,12 @@ static unsigned long calculate_inst_freq(struct venus_inst *inst,
10141085
if (inst->state != INST_START)
10151086
return 0;
10161087

1017-
vpp_freq = mbs_per_sec * inst->clk_data.vpp_freq;
1088+
if (inst->session_type == VIDC_SESSION_TYPE_ENC)
1089+
vpp_freq_per_mb = inst->flags & VENUS_LOW_POWER ?
1090+
inst->clk_data.low_power_freq :
1091+
inst->clk_data.vpp_freq;
1092+
1093+
vpp_freq = mbs_per_sec * vpp_freq_per_mb;
10181094
/* 21 / 20 is overhead factor */
10191095
vpp_freq += vpp_freq / 20;
10201096
vsp_freq = mbs_per_sec * inst->clk_data.vsp_freq;

0 commit comments

Comments
 (0)