Commit 1a73374a authored by Stanimir Varbanov's avatar Stanimir Varbanov Committed by Mauro Carvalho Chehab

media: venus: hfi_parser: add common capability parser

This adds common capability parser for all supported Venus
versions. Having it will help to enumerate better the supported
raw formats and codecs and also the capabilities for every
codec like max/min width/height, framerate, bitrate and so on.
Signed-off-by: default avatarStanimir Varbanov <stanimir.varbanov@linaro.org>
Reviewed-by: default avatarTomasz Figa <tfiga@chromium.org>
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent aa3a8414
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
# Makefile for Qualcomm Venus driver # Makefile for Qualcomm Venus driver
venus-core-objs += core.o helpers.o firmware.o \ venus-core-objs += core.o helpers.o firmware.o \
hfi_venus.o hfi_msgs.o hfi_cmds.o hfi.o hfi_venus.o hfi_msgs.o hfi_cmds.o hfi.o \
hfi_parser.o
venus-dec-objs += vdec.o vdec_ctrls.o venus-dec-objs += vdec.o vdec_ctrls.o
venus-enc-objs += venc.o venc_ctrls.o venus-enc-objs += venc.o venc_ctrls.o
......
...@@ -152,6 +152,83 @@ static void venus_clks_disable(struct venus_core *core) ...@@ -152,6 +152,83 @@ static void venus_clks_disable(struct venus_core *core)
clk_disable_unprepare(core->clks[i]); clk_disable_unprepare(core->clks[i]);
} }
static u32 to_v4l2_codec_type(u32 codec)
{
switch (codec) {
case HFI_VIDEO_CODEC_H264:
return V4L2_PIX_FMT_H264;
case HFI_VIDEO_CODEC_H263:
return V4L2_PIX_FMT_H263;
case HFI_VIDEO_CODEC_MPEG1:
return V4L2_PIX_FMT_MPEG1;
case HFI_VIDEO_CODEC_MPEG2:
return V4L2_PIX_FMT_MPEG2;
case HFI_VIDEO_CODEC_MPEG4:
return V4L2_PIX_FMT_MPEG4;
case HFI_VIDEO_CODEC_VC1:
return V4L2_PIX_FMT_VC1_ANNEX_G;
case HFI_VIDEO_CODEC_VP8:
return V4L2_PIX_FMT_VP8;
case HFI_VIDEO_CODEC_VP9:
return V4L2_PIX_FMT_VP9;
case HFI_VIDEO_CODEC_DIVX:
case HFI_VIDEO_CODEC_DIVX_311:
return V4L2_PIX_FMT_XVID;
default:
return 0;
}
}
static int venus_enumerate_codecs(struct venus_core *core, u32 type)
{
const struct hfi_inst_ops dummy_ops = {};
struct venus_inst *inst;
u32 codec, codecs;
unsigned int i;
int ret;
if (core->res->hfi_version != HFI_VERSION_1XX)
return 0;
inst = kzalloc(sizeof(*inst), GFP_KERNEL);
if (!inst)
return -ENOMEM;
mutex_init(&inst->lock);
inst->core = core;
inst->session_type = type;
if (type == VIDC_SESSION_TYPE_DEC)
codecs = core->dec_codecs;
else
codecs = core->enc_codecs;
ret = hfi_session_create(inst, &dummy_ops);
if (ret)
goto err;
for (i = 0; i < MAX_CODEC_NUM; i++) {
codec = (1 << i) & codecs;
if (!codec)
continue;
ret = hfi_session_init(inst, to_v4l2_codec_type(codec));
if (ret)
goto done;
ret = hfi_session_deinit(inst);
if (ret)
goto done;
}
done:
hfi_session_destroy(inst);
err:
mutex_destroy(&inst->lock);
kfree(inst);
return ret;
}
static int venus_probe(struct platform_device *pdev) static int venus_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
...@@ -219,6 +296,14 @@ static int venus_probe(struct platform_device *pdev) ...@@ -219,6 +296,14 @@ static int venus_probe(struct platform_device *pdev)
if (ret) if (ret)
goto err_venus_shutdown; goto err_venus_shutdown;
ret = venus_enumerate_codecs(core, VIDC_SESSION_TYPE_DEC);
if (ret)
goto err_venus_shutdown;
ret = venus_enumerate_codecs(core, VIDC_SESSION_TYPE_ENC);
if (ret)
goto err_venus_shutdown;
ret = v4l2_device_register(dev, &core->v4l2_dev); ret = v4l2_device_register(dev, &core->v4l2_dev);
if (ret) if (ret)
goto err_core_deinit; goto err_core_deinit;
......
...@@ -57,6 +57,30 @@ struct venus_format { ...@@ -57,6 +57,30 @@ struct venus_format {
u32 type; u32 type;
}; };
#define MAX_PLANES 4
#define MAX_FMT_ENTRIES 32
#define MAX_CAP_ENTRIES 32
#define MAX_ALLOC_MODE_ENTRIES 16
#define MAX_CODEC_NUM 32
struct raw_formats {
u32 buftype;
u32 fmt;
};
struct venus_caps {
u32 codec;
u32 domain;
bool cap_bufs_mode_dynamic;
unsigned int num_caps;
struct hfi_capability caps[MAX_CAP_ENTRIES];
unsigned int num_pl;
struct hfi_profile_level pl[HFI_MAX_PROFILE_COUNT];
unsigned int num_fmts;
struct raw_formats fmts[MAX_FMT_ENTRIES];
bool valid; /* used only for Venus v1xx */
};
/** /**
* struct venus_core - holds core parameters valid for all instances * struct venus_core - holds core parameters valid for all instances
* *
...@@ -113,8 +137,8 @@ struct venus_core { ...@@ -113,8 +137,8 @@ struct venus_core {
unsigned int error; unsigned int error;
bool sys_error; bool sys_error;
const struct hfi_core_ops *core_ops; const struct hfi_core_ops *core_ops;
u32 enc_codecs; unsigned long enc_codecs;
u32 dec_codecs; unsigned long dec_codecs;
unsigned int max_sessions_supported; unsigned int max_sessions_supported;
#define ENC_ROTATION_CAPABILITY 0x1 #define ENC_ROTATION_CAPABILITY 0x1
#define ENC_SCALING_CAPABILITY 0x2 #define ENC_SCALING_CAPABILITY 0x2
...@@ -124,6 +148,8 @@ struct venus_core { ...@@ -124,6 +148,8 @@ struct venus_core {
void *priv; void *priv;
const struct hfi_ops *ops; const struct hfi_ops *ops;
struct delayed_work work; struct delayed_work work;
struct venus_caps caps[MAX_CODEC_NUM];
unsigned int codecs_count;
}; };
struct vdec_controls { struct vdec_controls {
...@@ -216,6 +242,7 @@ struct venus_buffer { ...@@ -216,6 +242,7 @@ struct venus_buffer {
* @reconfig: a flag raised by decoder when the stream resolution changed * @reconfig: a flag raised by decoder when the stream resolution changed
* @reconfig_width: holds the new width * @reconfig_width: holds the new width
* @reconfig_height: holds the new height * @reconfig_height: holds the new height
* @hfi_codec: current codec for this instance in HFI space
* @sequence_cap: a sequence counter for capture queue * @sequence_cap: a sequence counter for capture queue
* @sequence_out: a sequence counter for output queue * @sequence_out: a sequence counter for output queue
* @m2m_dev: a reference to m2m device structure * @m2m_dev: a reference to m2m device structure
...@@ -228,22 +255,8 @@ struct venus_buffer { ...@@ -228,22 +255,8 @@ struct venus_buffer {
* @priv: a private for HFI operations callbacks * @priv: a private for HFI operations callbacks
* @session_type: the type of the session (decoder or encoder) * @session_type: the type of the session (decoder or encoder)
* @hprop: a union used as a holder by get property * @hprop: a union used as a holder by get property
* @cap_width: width capability
* @cap_height: height capability
* @cap_mbs_per_frame: macroblocks per frame capability
* @cap_mbs_per_sec: macroblocks per second capability
* @cap_framerate: framerate capability
* @cap_scale_x: horizontal scaling capability
* @cap_scale_y: vertical scaling capability
* @cap_bitrate: bitrate capability
* @cap_hier_p: hier capability
* @cap_ltr_count: LTR count capability
* @cap_secure_output2_threshold: secure OUTPUT2 threshold capability
* @cap_bufs_mode_static: buffers allocation mode capability * @cap_bufs_mode_static: buffers allocation mode capability
* @cap_bufs_mode_dynamic: buffers allocation mode capability * @cap_bufs_mode_dynamic: buffers allocation mode capability
* @pl_count: count of supported profiles/levels
* @pl: supported profiles/levels
* @bufreq: holds buffer requirements
*/ */
struct venus_inst { struct venus_inst {
struct list_head list; struct list_head list;
...@@ -280,6 +293,7 @@ struct venus_inst { ...@@ -280,6 +293,7 @@ struct venus_inst {
bool reconfig; bool reconfig;
u32 reconfig_width; u32 reconfig_width;
u32 reconfig_height; u32 reconfig_height;
u32 hfi_codec;
u32 sequence_cap; u32 sequence_cap;
u32 sequence_out; u32 sequence_out;
struct v4l2_m2m_dev *m2m_dev; struct v4l2_m2m_dev *m2m_dev;
...@@ -291,22 +305,8 @@ struct venus_inst { ...@@ -291,22 +305,8 @@ struct venus_inst {
const struct hfi_inst_ops *ops; const struct hfi_inst_ops *ops;
u32 session_type; u32 session_type;
union hfi_get_property hprop; union hfi_get_property hprop;
struct hfi_capability cap_width;
struct hfi_capability cap_height;
struct hfi_capability cap_mbs_per_frame;
struct hfi_capability cap_mbs_per_sec;
struct hfi_capability cap_framerate;
struct hfi_capability cap_scale_x;
struct hfi_capability cap_scale_y;
struct hfi_capability cap_bitrate;
struct hfi_capability cap_hier_p;
struct hfi_capability cap_ltr_count;
struct hfi_capability cap_secure_output2_threshold;
bool cap_bufs_mode_static; bool cap_bufs_mode_static;
bool cap_bufs_mode_dynamic; bool cap_bufs_mode_dynamic;
unsigned int pl_count;
struct hfi_profile_level pl[HFI_MAX_PROFILE_COUNT];
struct hfi_buffer_requirements bufreq[HFI_BUFFER_TYPE_MAX];
}; };
#define IS_V1(core) ((core)->res->hfi_version == HFI_VERSION_1XX) #define IS_V1(core) ((core)->res->hfi_version == HFI_VERSION_1XX)
...@@ -326,4 +326,18 @@ static inline void *to_hfi_priv(struct venus_core *core) ...@@ -326,4 +326,18 @@ static inline void *to_hfi_priv(struct venus_core *core)
return core->priv; return core->priv;
} }
static inline struct venus_caps *
venus_caps_by_codec(struct venus_core *core, u32 codec, u32 domain)
{
unsigned int c;
for (c = 0; c < core->codecs_count; c++) {
if (core->caps[c].codec == codec &&
core->caps[c].domain == domain)
return &core->caps[c];
}
return NULL;
}
#endif #endif
...@@ -203,13 +203,12 @@ int hfi_session_init(struct venus_inst *inst, u32 pixfmt) ...@@ -203,13 +203,12 @@ int hfi_session_init(struct venus_inst *inst, u32 pixfmt)
{ {
struct venus_core *core = inst->core; struct venus_core *core = inst->core;
const struct hfi_ops *ops = core->ops; const struct hfi_ops *ops = core->ops;
u32 codec;
int ret; int ret;
codec = to_codec_type(pixfmt); inst->hfi_codec = to_codec_type(pixfmt);
reinit_completion(&inst->done); reinit_completion(&inst->done);
ret = ops->session_init(inst, inst->session_type, codec); ret = ops->session_init(inst, inst->session_type, inst->hfi_codec);
if (ret) if (ret)
return ret; return ret;
......
...@@ -858,10 +858,23 @@ struct hfi_uncompressed_format_select { ...@@ -858,10 +858,23 @@ struct hfi_uncompressed_format_select {
u32 format; u32 format;
}; };
struct hfi_uncompressed_plane_constraints {
u32 stride_multiples;
u32 max_stride;
u32 min_plane_buffer_height_multiple;
u32 buffer_alignment;
};
struct hfi_uncompressed_plane_info {
u32 format;
u32 num_planes;
struct hfi_uncompressed_plane_constraints plane_constraints[1];
};
struct hfi_uncompressed_format_supported { struct hfi_uncompressed_format_supported {
u32 buffer_type; u32 buffer_type;
u32 format_entries; u32 format_entries;
u32 format_info[1]; struct hfi_uncompressed_plane_info plane_info[1];
}; };
struct hfi_uncompressed_plane_actual { struct hfi_uncompressed_plane_actual {
...@@ -875,19 +888,6 @@ struct hfi_uncompressed_plane_actual_info { ...@@ -875,19 +888,6 @@ struct hfi_uncompressed_plane_actual_info {
struct hfi_uncompressed_plane_actual plane_format[1]; struct hfi_uncompressed_plane_actual plane_format[1];
}; };
struct hfi_uncompressed_plane_constraints {
u32 stride_multiples;
u32 max_stride;
u32 min_plane_buffer_height_multiple;
u32 buffer_alignment;
};
struct hfi_uncompressed_plane_info {
u32 format;
u32 num_planes;
struct hfi_uncompressed_plane_constraints plane_format[1];
};
struct hfi_uncompressed_plane_actual_constraints_info { struct hfi_uncompressed_plane_actual_constraints_info {
u32 buffer_type; u32 buffer_type;
u32 num_planes; u32 num_planes;
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2018 Linaro Ltd.
*
* Author: Stanimir Varbanov <stanimir.varbanov@linaro.org>
*/
#include <linux/bitops.h>
#include <linux/kernel.h>
#include "core.h"
#include "hfi_helper.h"
#include "hfi_parser.h"
typedef void (*func)(struct venus_caps *cap, const void *data,
unsigned int size);
static void init_codecs(struct venus_core *core)
{
struct venus_caps *caps = core->caps, *cap;
unsigned long bit;
for_each_set_bit(bit, &core->dec_codecs, MAX_CODEC_NUM) {
cap = &caps[core->codecs_count++];
cap->codec = BIT(bit);
cap->domain = VIDC_SESSION_TYPE_DEC;
cap->valid = false;
}
for_each_set_bit(bit, &core->enc_codecs, MAX_CODEC_NUM) {
cap = &caps[core->codecs_count++];
cap->codec = BIT(bit);
cap->domain = VIDC_SESSION_TYPE_ENC;
cap->valid = false;
}
}
static void for_each_codec(struct venus_caps *caps, unsigned int caps_num,
u32 codecs, u32 domain, func cb, void *data,
unsigned int size)
{
struct venus_caps *cap;
unsigned int i;
for (i = 0; i < caps_num; i++) {
cap = &caps[i];
if (cap->valid && cap->domain == domain)
continue;
if (cap->codec & codecs && cap->domain == domain)
cb(cap, data, size);
}
}
static void
fill_buf_mode(struct venus_caps *cap, const void *data, unsigned int num)
{
const u32 *type = data;
if (*type == HFI_BUFFER_MODE_DYNAMIC)
cap->cap_bufs_mode_dynamic = true;
}
static void
parse_alloc_mode(struct venus_core *core, struct venus_inst *inst, u32 codecs,
u32 domain, void *data)
{
struct hfi_buffer_alloc_mode_supported *mode = data;
u32 num_entries = mode->num_entries;
u32 *type;
if (num_entries > MAX_ALLOC_MODE_ENTRIES)
return;
type = mode->data;
while (num_entries--) {
if (mode->buffer_type == HFI_BUFFER_OUTPUT ||
mode->buffer_type == HFI_BUFFER_OUTPUT2) {
if (*type == HFI_BUFFER_MODE_DYNAMIC && inst)
inst->cap_bufs_mode_dynamic = true;
for_each_codec(core->caps, ARRAY_SIZE(core->caps),
codecs, domain, fill_buf_mode, type, 1);
}
type++;
}
}
static void fill_profile_level(struct venus_caps *cap, const void *data,
unsigned int num)
{
const struct hfi_profile_level *pl = data;
memcpy(&cap->pl[cap->num_pl], pl, num * sizeof(*pl));
cap->num_pl += num;
}
static void
parse_profile_level(struct venus_core *core, u32 codecs, u32 domain, void *data)
{
struct hfi_profile_level_supported *pl = data;
struct hfi_profile_level *proflevel = pl->profile_level;
struct hfi_profile_level pl_arr[HFI_MAX_PROFILE_COUNT] = {};
if (pl->profile_count > HFI_MAX_PROFILE_COUNT)
return;
memcpy(pl_arr, proflevel, pl->profile_count * sizeof(*proflevel));
for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain,
fill_profile_level, pl_arr, pl->profile_count);
}
static void
fill_caps(struct venus_caps *cap, const void *data, unsigned int num)
{
const struct hfi_capability *caps = data;
memcpy(&cap->caps[cap->num_caps], caps, num * sizeof(*caps));
cap->num_caps += num;
}
static void
parse_caps(struct venus_core *core, u32 codecs, u32 domain, void *data)
{
struct hfi_capabilities *caps = data;
struct hfi_capability *cap = caps->data;
u32 num_caps = caps->num_capabilities;
struct hfi_capability caps_arr[MAX_CAP_ENTRIES] = {};
if (num_caps > MAX_CAP_ENTRIES)
return;
memcpy(caps_arr, cap, num_caps * sizeof(*cap));
for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain,
fill_caps, caps_arr, num_caps);
}
static void fill_raw_fmts(struct venus_caps *cap, const void *fmts,
unsigned int num_fmts)
{
const struct raw_formats *formats = fmts;
memcpy(&cap->fmts[cap->num_fmts], formats, num_fmts * sizeof(*formats));
cap->num_fmts += num_fmts;
}
static void
parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data)
{
struct hfi_uncompressed_format_supported *fmt = data;
struct hfi_uncompressed_plane_info *pinfo = fmt->plane_info;
struct hfi_uncompressed_plane_constraints *constr;
struct raw_formats rawfmts[MAX_FMT_ENTRIES] = {};
u32 entries = fmt->format_entries;
unsigned int i = 0;
u32 num_planes;
while (entries) {
num_planes = pinfo->num_planes;
rawfmts[i].fmt = pinfo->format;
rawfmts[i].buftype = fmt->buffer_type;
i++;
if (pinfo->num_planes > MAX_PLANES)
break;
pinfo = (void *)pinfo + sizeof(*constr) * num_planes +
2 * sizeof(u32);
entries--;
}
for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain,
fill_raw_fmts, rawfmts, i);
}
static void parse_codecs(struct venus_core *core, void *data)
{
struct hfi_codec_supported *codecs = data;
core->dec_codecs = codecs->dec_codecs;
core->enc_codecs = codecs->enc_codecs;
if (IS_V1(core)) {
core->dec_codecs &= ~HFI_VIDEO_CODEC_HEVC;
core->dec_codecs &= ~HFI_VIDEO_CODEC_SPARK;
}
}
static void parse_max_sessions(struct venus_core *core, const void *data)
{
const struct hfi_max_sessions_supported *sessions = data;
core->max_sessions_supported = sessions->max_sessions;
}
static void parse_codecs_mask(u32 *codecs, u32 *domain, void *data)
{
struct hfi_codec_mask_supported *mask = data;
*codecs = mask->codecs;
*domain = mask->video_domains;
}
static void parser_init(struct venus_inst *inst, u32 *codecs, u32 *domain)
{
if (!inst || !IS_V1(inst->core))
return;
*codecs = inst->hfi_codec;
*domain = inst->session_type;
}
static void parser_fini(struct venus_inst *inst, u32 codecs, u32 domain)
{
struct venus_caps *caps, *cap;
unsigned int i;
u32 dom;
if (!inst || !IS_V1(inst->core))
return;
caps = inst->core->caps;
dom = inst->session_type;
for (i = 0; i < MAX_CODEC_NUM; i++) {
cap = &caps[i];
if (cap->codec & codecs && cap->domain == dom)
cap->valid = true;
}
}
u32 hfi_parser(struct venus_core *core, struct venus_inst *inst, void *buf,
u32 size)
{
unsigned int words_count = size >> 2;
u32 *word = buf, *data, codecs = 0, domain = 0;
if (size % 4)
return HFI_ERR_SYS_INSUFFICIENT_RESOURCES;
parser_init(inst, &codecs, &domain);
while (words_count) {
data = word + 1;
switch (*word) {
case HFI_PROPERTY_PARAM_CODEC_SUPPORTED:
parse_codecs(core, data);
init_codecs(core);
break;
case HFI_PROPERTY_PARAM_MAX_SESSIONS_SUPPORTED:
parse_max_sessions(core, data);
break;
case HFI_PROPERTY_PARAM_CODEC_MASK_SUPPORTED:
parse_codecs_mask(&codecs, &domain, data);
break;
case HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED:
parse_raw_formats(core, codecs, domain, data);
break;
case HFI_PROPERTY_PARAM_CAPABILITY_SUPPORTED:
parse_caps(core, codecs, domain, data);
break;
case HFI_PROPERTY_PARAM_PROFILE_LEVEL_SUPPORTED:
parse_profile_level(core, codecs, domain, data);
break;
case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE_SUPPORTED:
parse_alloc_mode(core, inst, codecs, domain, data);
break;
default:
break;
}
word++;
words_count--;
}
parser_fini(inst, codecs, domain);
return HFI_ERR_NONE;
}
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2018 Linaro Ltd. */
#ifndef __VENUS_HFI_PARSER_H__
#define __VENUS_HFI_PARSER_H__
#include "core.h"
u32 hfi_parser(struct venus_core *core, struct venus_inst *inst,
void *buf, u32 size);
#define WHICH_CAP_MIN 0
#define WHICH_CAP_MAX 1
#define WHICH_CAP_STEP 2
static inline u32 get_cap(struct venus_inst *inst, u32 type, u32 which)
{
struct venus_core *core = inst->core;
struct hfi_capability *cap = NULL;
struct venus_caps *caps;
unsigned int i;
caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type);
if (!caps)
return 0;
for (i = 0; i < caps->num_caps; i++) {
if (caps->caps[i].capability_type == type) {
cap = &caps->caps[i];
break;
}
}
if (!cap)
return 0;
switch (which) {
case WHICH_CAP_MIN:
return cap->min;
case WHICH_CAP_MAX:
return cap->max;
case WHICH_CAP_STEP:
return cap->step_size;
default:
break;
}
return 0;
}
static inline u32 cap_min(struct venus_inst *inst, u32 type)
{
return get_cap(inst, type, WHICH_CAP_MIN);
}
static inline u32 cap_max(struct venus_inst *inst, u32 type)
{
return get_cap(inst, type, WHICH_CAP_MAX);
}
static inline u32 cap_step(struct venus_inst *inst, u32 type)
{
return get_cap(inst, type, WHICH_CAP_STEP);
}
static inline u32 frame_width_min(struct venus_inst *inst)
{
return cap_min(inst, HFI_CAPABILITY_FRAME_WIDTH);
}
static inline u32 frame_width_max(struct venus_inst *inst)
{
return cap_max(inst, HFI_CAPABILITY_FRAME_WIDTH);
}
static inline u32 frame_width_step(struct venus_inst *inst)
{
return cap_step(inst, HFI_CAPABILITY_FRAME_WIDTH);
}
static inline u32 frame_height_min(struct venus_inst *inst)
{
return cap_min(inst, HFI_CAPABILITY_FRAME_HEIGHT);
}
static inline u32 frame_height_max(struct venus_inst *inst)
{
return cap_max(inst, HFI_CAPABILITY_FRAME_HEIGHT);
}
static inline u32 frame_height_step(struct venus_inst *inst)
{
return cap_step(inst, HFI_CAPABILITY_FRAME_HEIGHT);
}
static inline u32 frate_min(struct venus_inst *inst)
{
return cap_min(inst, HFI_CAPABILITY_FRAMERATE);
}
static inline u32 frate_max(struct venus_inst *inst)
{
return cap_max(inst, HFI_CAPABILITY_FRAMERATE);
}
static inline u32 frate_step(struct venus_inst *inst)
{
return cap_step(inst, HFI_CAPABILITY_FRAMERATE);
}
#endif
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <media/videobuf2-dma-sg.h> #include <media/videobuf2-dma-sg.h>
#include "hfi_venus_io.h" #include "hfi_venus_io.h"
#include "hfi_parser.h"
#include "core.h" #include "core.h"
#include "helpers.h" #include "helpers.h"
#include "vdec.h" #include "vdec.h"
...@@ -175,10 +176,10 @@ vdec_try_fmt_common(struct venus_inst *inst, struct v4l2_format *f) ...@@ -175,10 +176,10 @@ vdec_try_fmt_common(struct venus_inst *inst, struct v4l2_format *f)
fmt = find_format(inst, pixmp->pixelformat, f->type); fmt = find_format(inst, pixmp->pixelformat, f->type);
} }
pixmp->width = clamp(pixmp->width, inst->cap_width.min, pixmp->width = clamp(pixmp->width, frame_width_min(inst),
inst->cap_width.max); frame_width_max(inst));
pixmp->height = clamp(pixmp->height, inst->cap_height.min, pixmp->height = clamp(pixmp->height, frame_height_min(inst),
inst->cap_height.max); frame_height_max(inst));
if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
pixmp->height = ALIGN(pixmp->height, 32); pixmp->height = ALIGN(pixmp->height, 32);
...@@ -440,12 +441,12 @@ static int vdec_enum_framesizes(struct file *file, void *fh, ...@@ -440,12 +441,12 @@ static int vdec_enum_framesizes(struct file *file, void *fh,
fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
fsize->stepwise.min_width = inst->cap_width.min; fsize->stepwise.min_width = frame_width_min(inst);
fsize->stepwise.max_width = inst->cap_width.max; fsize->stepwise.max_width = frame_width_max(inst);
fsize->stepwise.step_width = inst->cap_width.step_size; fsize->stepwise.step_width = frame_width_step(inst);
fsize->stepwise.min_height = inst->cap_height.min; fsize->stepwise.min_height = frame_height_min(inst);
fsize->stepwise.max_height = inst->cap_height.max; fsize->stepwise.max_height = frame_height_max(inst);
fsize->stepwise.step_height = inst->cap_height.step_size; fsize->stepwise.step_height = frame_height_step(inst);
return 0; return 0;
} }
...@@ -900,22 +901,7 @@ static void vdec_inst_init(struct venus_inst *inst) ...@@ -900,22 +901,7 @@ static void vdec_inst_init(struct venus_inst *inst)
inst->fps = 30; inst->fps = 30;
inst->timeperframe.numerator = 1; inst->timeperframe.numerator = 1;
inst->timeperframe.denominator = 30; inst->timeperframe.denominator = 30;
inst->hfi_codec = HFI_VIDEO_CODEC_H264;
inst->cap_width.min = 64;
inst->cap_width.max = 1920;
if (inst->core->res->hfi_version == HFI_VERSION_3XX)
inst->cap_width.max = 3840;
inst->cap_width.step_size = 1;
inst->cap_height.min = 64;
inst->cap_height.max = ALIGN(1080, 32);
if (inst->core->res->hfi_version == HFI_VERSION_3XX)
inst->cap_height.max = ALIGN(2160, 32);
inst->cap_height.step_size = 1;
inst->cap_framerate.min = 1;
inst->cap_framerate.max = 30;
inst->cap_framerate.step_size = 1;
inst->cap_mbs_per_frame.min = 16;
inst->cap_mbs_per_frame.max = 8160;
} }
static const struct v4l2_m2m_ops vdec_m2m_ops = { static const struct v4l2_m2m_ops vdec_m2m_ops = {
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include "hfi_venus_io.h" #include "hfi_venus_io.h"
#include "hfi_parser.h"
#include "core.h" #include "core.h"
#include "helpers.h" #include "helpers.h"
#include "venc.h" #include "venc.h"
...@@ -299,10 +300,10 @@ venc_try_fmt_common(struct venus_inst *inst, struct v4l2_format *f) ...@@ -299,10 +300,10 @@ venc_try_fmt_common(struct venus_inst *inst, struct v4l2_format *f)
fmt = find_format(inst, pixmp->pixelformat, f->type); fmt = find_format(inst, pixmp->pixelformat, f->type);
} }
pixmp->width = clamp(pixmp->width, inst->cap_width.min, pixmp->width = clamp(pixmp->width, frame_width_min(inst),
inst->cap_width.max); frame_width_max(inst));
pixmp->height = clamp(pixmp->height, inst->cap_height.min, pixmp->height = clamp(pixmp->height, frame_height_min(inst),
inst->cap_height.max); frame_height_max(inst));
if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
pixmp->height = ALIGN(pixmp->height, 32); pixmp->height = ALIGN(pixmp->height, 32);
...@@ -551,12 +552,12 @@ static int venc_enum_framesizes(struct file *file, void *fh, ...@@ -551,12 +552,12 @@ static int venc_enum_framesizes(struct file *file, void *fh,
if (fsize->index) if (fsize->index)
return -EINVAL; return -EINVAL;
fsize->stepwise.min_width = inst->cap_width.min; fsize->stepwise.min_width = frame_width_min(inst);
fsize->stepwise.max_width = inst->cap_width.max; fsize->stepwise.max_width = frame_width_max(inst);
fsize->stepwise.step_width = inst->cap_width.step_size; fsize->stepwise.step_width = frame_width_step(inst);
fsize->stepwise.min_height = inst->cap_height.min; fsize->stepwise.min_height = frame_height_min(inst);
fsize->stepwise.max_height = inst->cap_height.max; fsize->stepwise.max_height = frame_height_max(inst);
fsize->stepwise.step_height = inst->cap_height.step_size; fsize->stepwise.step_height = frame_height_step(inst);
return 0; return 0;
} }
...@@ -584,18 +585,18 @@ static int venc_enum_frameintervals(struct file *file, void *fh, ...@@ -584,18 +585,18 @@ static int venc_enum_frameintervals(struct file *file, void *fh,
if (!fival->width || !fival->height) if (!fival->width || !fival->height)
return -EINVAL; return -EINVAL;
if (fival->width > inst->cap_width.max || if (fival->width > frame_width_max(inst) ||
fival->width < inst->cap_width.min || fival->width < frame_width_min(inst) ||
fival->height > inst->cap_height.max || fival->height > frame_height_max(inst) ||
fival->height < inst->cap_height.min) fival->height < frame_height_min(inst))
return -EINVAL; return -EINVAL;
fival->stepwise.min.numerator = 1; fival->stepwise.min.numerator = 1;
fival->stepwise.min.denominator = inst->cap_framerate.max; fival->stepwise.min.denominator = frate_max(inst);
fival->stepwise.max.numerator = 1; fival->stepwise.max.numerator = 1;
fival->stepwise.max.denominator = inst->cap_framerate.min; fival->stepwise.max.denominator = frate_min(inst);
fival->stepwise.step.numerator = 1; fival->stepwise.step.numerator = 1;
fival->stepwise.step.denominator = inst->cap_framerate.max; fival->stepwise.step.denominator = frate_max(inst);
return 0; return 0;
} }
...@@ -1089,22 +1090,7 @@ static void venc_inst_init(struct venus_inst *inst) ...@@ -1089,22 +1090,7 @@ static void venc_inst_init(struct venus_inst *inst)
inst->fps = 15; inst->fps = 15;
inst->timeperframe.numerator = 1; inst->timeperframe.numerator = 1;
inst->timeperframe.denominator = 15; inst->timeperframe.denominator = 15;
inst->hfi_codec = HFI_VIDEO_CODEC_H264;
inst->cap_width.min = 96;
inst->cap_width.max = 1920;
if (inst->core->res->hfi_version == HFI_VERSION_3XX)
inst->cap_width.max = 3840;
inst->cap_width.step_size = 2;
inst->cap_height.min = 64;
inst->cap_height.max = ALIGN(1080, 32);
if (inst->core->res->hfi_version == HFI_VERSION_3XX)
inst->cap_height.max = ALIGN(2160, 32);
inst->cap_height.step_size = 2;
inst->cap_framerate.min = 1;
inst->cap_framerate.max = 30;
inst->cap_framerate.step_size = 1;
inst->cap_mbs_per_frame.min = 24;
inst->cap_mbs_per_frame.max = 8160;
} }
static int venc_open(struct file *file) static int venc_open(struct file *file)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment