From 25f6fd7e7ed24702cbf23b10efe704a8c2e78c79 Mon Sep 17 00:00:00 2001 From: Akshata Sahukar Date: Tue, 11 Aug 2020 18:24:13 -0700 Subject: [PATCH] video: driver: add capabilities parsing logic Parse capabilities from platform specific file. Change-Id: I46e45995f24f92d374f749fd58c200542591b6a4 Signed-off-by: Akshata Sahukar --- driver/platform/waipio/src/msm_vidc_waipio.c | 6 +- driver/vidc/inc/msm_vidc_core.h | 2 + driver/vidc/inc/msm_vidc_inst.h | 1 + driver/vidc/inc/msm_vidc_internal.h | 46 ++++- driver/vidc/inc/msm_vidc_platform.h | 29 +-- driver/vidc/src/msm_vidc_driver.c | 194 ++++++++++++++++++- include/uapi/vidc/media/msm_vidc_utils.h | 2 +- 7 files changed, 259 insertions(+), 21 deletions(-) diff --git a/driver/platform/waipio/src/msm_vidc_waipio.c b/driver/platform/waipio/src/msm_vidc_waipio.c index e1632b00f6..55c3081bcf 100644 --- a/driver/platform/waipio/src/msm_vidc_waipio.c +++ b/driver/platform/waipio/src/msm_vidc_waipio.c @@ -40,7 +40,7 @@ #define CODECS_ALL (MSM_VIDC_H264 | MSM_VIDC_HEVC | \ MSM_VIDC_VP9 | MSM_VIDC_MPEG2) -static struct msm_vidc_core_data core_data_waipio[] = { +static struct msm_platform_core_capability core_data_waipio[] = { /* {type, value} */ {ENC_CODECS, H264|HEVC}, {DEC_CODECS, H264|HEVC|VP9|MPEG2}, @@ -81,7 +81,7 @@ static struct msm_vidc_core_data core_data_waipio[] = { {AV_SYNC_WINDOW_SIZE, 40}, }; -static struct msm_vidc_instance_data instance_data_waipio[] = { +static struct msm_platform_inst_capability instance_data_waipio[] = { /* {type, domains, codecs, min, max, step_or_menu, value} */ {FRAME_WIDTH, ENC|DEC, CODECS_ALL, 128, 8192, 1, 1920}, {FRAME_HEIGHT, ENC|DEC, CODECS_ALL, 128, 8192, 1, 1080}, @@ -92,7 +92,7 @@ static struct msm_vidc_instance_data instance_data_waipio[] = { {FRAME_RATE, ENC|DEC, CODECS_ALL, 1, 960, 1, 30}, {BIT_RATE, ENC|DEC, CODECS_ALL, 1, 220000000, 1, 20000000}, {BIT_RATE, ENC, HEVC, 1, 160000000, 1, 20000000}, - {CABAC_BIT_RATE, ENC, H264, 1, 160000000, 1, 20000000}, + {CABAC_BITRATE, ENC, H264, 1, 160000000, 1, 20000000}, {SCALE_X, ENC, CODECS_ALL, 8192, 65536, 1, 8192}, {SCALE_Y, ENC, CODECS_ALL, 8192, 65536, 1, 8192}, {SCALE_X, DEC, CODECS_ALL, 65536, 65536, 1, 65536}, diff --git a/driver/vidc/inc/msm_vidc_core.h b/driver/vidc/inc/msm_vidc_core.h index 29a13d92f9..450c68cd87 100644 --- a/driver/vidc/inc/msm_vidc_core.h +++ b/driver/vidc/inc/msm_vidc_core.h @@ -76,6 +76,8 @@ struct msm_vidc_core { u32 spur_count; u32 reg_count; bool power_enabled; + struct msm_vidc_core_capability *capabilities; + struct msm_vidc_inst_capability *inst_caps; struct msm_vidc_mem_addr sfr; struct msm_vidc_mem_addr iface_q_table; struct msm_vidc_iface_q_info iface_queues[VIDC_IFACEQ_NUMQ]; diff --git a/driver/vidc/inc/msm_vidc_inst.h b/driver/vidc/inc/msm_vidc_inst.h index ad3f4b06eb..43bd43d264 100644 --- a/driver/vidc/inc/msm_vidc_inst.h +++ b/driver/vidc/inc/msm_vidc_inst.h @@ -106,6 +106,7 @@ struct msm_vidc_inst { bool session_created; struct dentry *debugfs_root; struct msm_vidc_debug debug; + struct msm_vidc_inst_capability *capabilities; }; #endif // _MSM_VIDC_INST_H_ diff --git a/driver/vidc/inc/msm_vidc_internal.h b/driver/vidc/inc/msm_vidc_internal.h index c087ad86f4..e49581d44d 100644 --- a/driver/vidc/inc/msm_vidc_internal.h +++ b/driver/vidc/inc/msm_vidc_internal.h @@ -36,6 +36,8 @@ #define MAX_SUPPORTED_INSTANCES 16 #define MAX_BSE_VPP_DELAY 6 #define DEFAULT_BSE_VPP_DELAY 2 +#define MAX_CAP_PARENTS 16 +#define MAX_CAP_CHILDREN 16 /* Maintains the number of FTB's between each FBD over a window */ #define DCVS_FTB_WINDOW 16 @@ -130,8 +132,9 @@ enum msm_vidc_port_type { MAX_PORT, }; -enum msm_vidc_core_data_type { - ENC_CODECS = 0, +enum msm_vidc_core_capability_type { + CORE_CAP_NONE = 0, + ENC_CODECS, DEC_CODECS, MAX_SESSION_COUNT, MAX_SECURE_SESSION_COUNT, @@ -159,16 +162,18 @@ enum msm_vidc_core_data_type { DECODE_BATCH_TIMEOUT, AV_SYNC_WINDOW_SIZE, CLK_FREQ_THRESHOLD, + CORE_CAP_MAX, }; -enum msm_vidc_instance_data_type { +enum msm_vidc_inst_capability_type { + INST_CAP_NONE = 0, FRAME_WIDTH, FRAME_HEIGHT, MBPF, MBPS, FRAME_RATE, BIT_RATE, - CABAC_BIT_RATE, + CABAC_BITRATE, LTR_COUNT, LCU_SIZE, POWER_SAVE_MBPS, @@ -205,6 +210,39 @@ enum msm_vidc_instance_data_type { MB_CYCLES_LP, MB_CYCLES_FW, MB_CYCLES_FW_VPP, + INST_CAP_MAX, +}; + +enum msm_vidc_inst_capability_flags { + CAP_FLAG_ROOT = BIT(0), + CAP_FLAG_DYNAMIC_ALLOWED = BIT(1), + CAP_FLAG_MENU = BIT(2), +}; + +struct msm_vidc_inst_cap { + enum msm_vidc_inst_capability_type cap; + s32 min; + s32 max; + u32 step_or_menu; + s32 value; + enum msm_vidc_inst_capability_flags flags; + u32 v4l2_id; + u32 hfi_id; + u8 parents[MAX_CAP_PARENTS]; + u8 children[MAX_CAP_CHILDREN]; + void (*adjust)(void *inst, s32 new_value); + int (*set)(void *inst, struct v4l2_ctrl *ctrl); +}; + +struct msm_vidc_inst_capability { + enum msm_vidc_domain_type domain; + enum msm_vidc_codec_type codec; + struct msm_vidc_inst_cap cap[INST_CAP_MAX]; +}; + +struct msm_vidc_core_capability { + enum msm_vidc_core_capability_type type; + u32 value; }; enum efuse_purpose { diff --git a/driver/vidc/inc/msm_vidc_platform.h b/driver/vidc/inc/msm_vidc_platform.h index 9d4b15049c..87f2cdb57f 100644 --- a/driver/vidc/inc/msm_vidc_platform.h +++ b/driver/vidc/inc/msm_vidc_platform.h @@ -10,19 +10,26 @@ #include "msm_vidc_internal.h" -struct msm_vidc_core_data { - enum msm_vidc_core_data_type type; +struct msm_platform_core_capability { + enum msm_vidc_core_capability_type type; u32 value; }; -struct msm_vidc_instance_data { - enum msm_vidc_instance_data_type type; - enum msm_vidc_domain_type domains; - enum msm_vidc_codec_type codecs; - u32 min; - u32 max; +struct msm_platform_inst_capability { + enum msm_vidc_inst_capability_type cap; + enum msm_vidc_domain_type domain; + enum msm_vidc_codec_type codec; + s32 min; + s32 max; u32 step_or_menu; - u32 value; + s32 value; + enum msm_vidc_inst_capability_flags flags; + u32 v4l2_id; + u32 hfi_id; + u8 parents[MAX_CAP_PARENTS]; + u8 children[MAX_CAP_CHILDREN]; + void (*adjust)(void *inst, s32 new_value); + int (*set)(void *inst, struct v4l2_ctrl *ctrl); }; struct msm_vidc_csc_coeff { @@ -61,9 +68,9 @@ struct msm_vidc_ubwc_config_data { }; struct msm_vidc_platform_data { - struct msm_vidc_core_data *core_data; + struct msm_platform_core_capability *core_data; u32 core_data_size; - struct msm_vidc_instance_data *instance_data; + struct msm_platform_inst_capability *instance_data; u32 instance_data_size; struct allowed_clock_rates_table *allowed_clks_tbl; u32 allowed_clks_tbl_size; diff --git a/driver/vidc/src/msm_vidc_driver.c b/driver/vidc/src/msm_vidc_driver.c index fc55340e44..00729b0e22 100644 --- a/driver/vidc/src/msm_vidc_driver.c +++ b/driver/vidc/src/msm_vidc_driver.c @@ -9,11 +9,19 @@ #include #include "msm_vidc_driver.h" +#include "msm_vidc_platform.h" #include "msm_vidc_internal.h" #include "msm_vidc_memory.h" #include "msm_vidc_debug.h" #include "venus_hfi.h" +#define COUNT_BITS(a, out) ({ \ + while ((a) >= 1) { \ + (out) += (a) & (1); \ + (a) >>= (1); \ + } \ +}) + void print_vidc_buffer(struct msm_vidc_inst *inst, struct msm_vidc_buffer *b) { } @@ -542,12 +550,187 @@ int msm_vidc_session_open(struct msm_vidc_inst *inst) return 0; } +static int msm_vidc_init_core_caps(struct msm_vidc_core *core) +{ + int rc = 0; + int i, num_platform_caps; + struct msm_platform_core_capability *platform_data; + + if (!core || !core->platform) { + d_vpr_e("%s: invalid params\n", __func__); + rc = -EINVAL; + goto exit; + } + + platform_data = core->platform->data.core_data; + if (!platform_data) { + d_vpr_e("%s: platform core data is NULL\n", + __func__); + rc = -EINVAL; + goto exit; + } + + if (!core->capabilities) { + core->capabilities = kcalloc(1, + (sizeof(struct msm_vidc_core_capability) * + CORE_CAP_MAX), GFP_KERNEL); + if (!core->capabilities) { + d_vpr_e("%s: failed to allocate core capabilities\n", + __func__); + rc = -ENOMEM; + goto exit; + } + } else { + d_vpr_e("%s: capabilities memory is expected to be freed\n", + __func__); + } + + num_platform_caps = core->platform->data.core_data_size; + + /* loop over platform caps */ + for (i = 0; i < num_platform_caps; i++) { + core->capabilities[platform_data[i].type].type = platform_data[i].type; + core->capabilities[platform_data[i].type].value = platform_data[i].value; + } + +exit: + return rc; +} + +static void update_inst_capability(struct msm_platform_inst_capability *in, + struct msm_vidc_inst_capability *capability) +{ + if (!in || !capability) { + d_vpr_e("%s: invalid params %pK %pK\n", + __func__, in, capability); + return; + } + if (in->cap < INST_CAP_MAX) { + capability->cap[in->cap].cap = in->cap; + capability->cap[in->cap].min = in->min; + capability->cap[in->cap].max = in->max; + capability->cap[in->cap].step_or_menu = in->step_or_menu; + capability->cap[in->cap].value = in->value; + capability->cap[in->cap].flags = in->flags; + capability->cap[in->cap].v4l2_id = in->v4l2_id; + capability->cap[in->cap].hfi_id = in->hfi_id; + memcpy(capability->cap[in->cap].parents, in->parents, + sizeof(capability->cap[in->cap].parents)); + memcpy(capability->cap[in->cap].children, in->children, + sizeof(capability->cap[in->cap].children)); + capability->cap[in->cap].adjust = in->adjust; + capability->cap[in->cap].set = in->set; + } else { + d_vpr_e("%s: invalid cap %d\n", + __func__, in->cap); + } +} + +static int msm_vidc_init_instance_caps(struct msm_vidc_core *core) +{ + int rc = 0; + u8 enc_valid_codecs, dec_valid_codecs; + u8 count_bits, enc_codec_count; + u8 codecs_count = 0; + int i, j, check_bit, num_platform_caps; + struct msm_platform_inst_capability *platform_data = NULL; + + if (!core || !core->platform || !core->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + rc = -EINVAL; + goto exit; + } + + platform_data = core->platform->data.instance_data; + if (!platform_data) { + d_vpr_e("%s: platform instance data is NULL\n", + __func__); + rc = -EINVAL; + goto exit; + } + + enc_valid_codecs = core->capabilities[ENC_CODECS].value; + count_bits = enc_valid_codecs; + COUNT_BITS(count_bits, codecs_count); + enc_codec_count = codecs_count; + + dec_valid_codecs = core->capabilities[DEC_CODECS].value; + count_bits = dec_valid_codecs; + COUNT_BITS(count_bits, codecs_count); + + if (!core->inst_caps) { + core->inst_caps = kcalloc(codecs_count, + sizeof(struct msm_vidc_inst_capability), + GFP_KERNEL); + if (!core->inst_caps) { + d_vpr_e("%s: failed to allocate core capabilities\n", + __func__); + rc = -ENOMEM; + goto exit; + } + } else { + d_vpr_e("%s: capabilities memory is expected to be freed\n", + __func__); + } + + check_bit = 0; + /* determine codecs for enc domain */ + for (i = 0; i < enc_codec_count; i++) { + while (check_bit < (sizeof(enc_valid_codecs) * 8)) { + if (enc_valid_codecs & BIT(check_bit)) { + core->inst_caps[i].domain = MSM_VIDC_ENCODER; + core->inst_caps[i].codec = enc_valid_codecs & + BIT(check_bit); + check_bit++; + break; + } + check_bit++; + } + } + + /* reset checkbit to check from 0th bit of decoder codecs set bits*/ + check_bit = 0; + /* determine codecs for dec domain */ + for (; i < codecs_count; i++) { + while (check_bit < (sizeof(dec_valid_codecs) * 8)) { + if (dec_valid_codecs & BIT(check_bit)) { + core->inst_caps[i].domain = MSM_VIDC_DECODER; + core->inst_caps[i].codec = dec_valid_codecs & + BIT(check_bit); + check_bit++; + break; + } + check_bit++; + } + } + + num_platform_caps = core->platform->data.instance_data_size; + + d_vpr_h("%s: num caps %d\n", __func__, num_platform_caps); + /* loop over each platform capability */ + for (i = 0; i < num_platform_caps; i++) { + /* select matching core codec and update it */ + for (j = 0; j < codecs_count; j++) { + if ((platform_data[i].domain & + core->inst_caps[j].domain) && + (platform_data[i].codec & + core->inst_caps[j].codec)) { + /* update core capability */ + update_inst_capability(&platform_data[i], + &core->inst_caps[j]); + } + } + } +exit: + return rc; +} + int msm_vidc_core_init(struct msm_vidc_core *core) { - int rc; + int rc = 0; d_vpr_h("%s()\n", __func__); - if (!core) { + if (!core || !core->platform) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } @@ -563,6 +746,13 @@ int msm_vidc_core_init(struct msm_vidc_core *core) goto unlock; } + rc = msm_vidc_init_core_caps(core); + if (rc) + goto unlock; + rc = msm_vidc_init_instance_caps(core); + if (rc) + goto unlock; + rc = venus_hfi_core_init(core); if (rc) { d_vpr_e("%s: core init failed\n", __func__); diff --git a/include/uapi/vidc/media/msm_vidc_utils.h b/include/uapi/vidc/media/msm_vidc_utils.h index 2f614d314c..8c08ced070 100644 --- a/include/uapi/vidc/media/msm_vidc_utils.h +++ b/include/uapi/vidc/media/msm_vidc_utils.h @@ -29,4 +29,4 @@ /* vendor controls end */ -#endif // __MSM_VIDC_UTILS_H__ +#endif