mirror of https://github.com/torvalds/linux.git
media: iris: Add support for G/S_PARM for encoder video device
Add supports for the G/S_PARM V4L2 ioctls for encoder video device with necessary hooks. This allows userspace to query the current streaming parameters such as frame intervals and set desired streaming parameters primarily the frame rate. Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100 Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com> Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-HDK Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8650-HDK Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com> Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # x1e80100-crd Signed-off-by: Bryan O'Donoghue <bod@kernel.org> Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
This commit is contained in:
parent
bed072b48e
commit
4ff586ff28
|
|
@ -61,6 +61,9 @@ struct iris_fmt {
|
|||
* @metadata_idx: index for metadata buffer
|
||||
* @codec: codec type
|
||||
* @last_buffer_dequeued: a flag to indicate that last buffer is sent by driver
|
||||
* @frame_rate: frame rate of current instance
|
||||
* @operating_rate: operating rate of current instance
|
||||
|
||||
*/
|
||||
|
||||
struct iris_inst {
|
||||
|
|
@ -96,6 +99,8 @@ struct iris_inst {
|
|||
u32 metadata_idx;
|
||||
u32 codec;
|
||||
bool last_buffer_dequeued;
|
||||
u32 frame_rate;
|
||||
u32 operating_rate;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -83,6 +83,8 @@ struct platform_inst_caps {
|
|||
u32 mb_cycles_fw;
|
||||
u32 mb_cycles_fw_vpp;
|
||||
u32 num_comv;
|
||||
u32 max_frame_rate;
|
||||
u32 max_operating_rate;
|
||||
};
|
||||
|
||||
enum platform_inst_fw_cap_type {
|
||||
|
|
|
|||
|
|
@ -211,6 +211,8 @@ static struct platform_inst_caps platform_inst_cap_sm8550 = {
|
|||
.mb_cycles_fw = 489583,
|
||||
.mb_cycles_fw_vpp = 66234,
|
||||
.num_comv = 0,
|
||||
.max_frame_rate = MAXIMUM_FPS,
|
||||
.max_operating_rate = MAXIMUM_FPS,
|
||||
};
|
||||
|
||||
static void iris_set_sm8550_preset_registers(struct iris_core *core)
|
||||
|
|
|
|||
|
|
@ -197,4 +197,6 @@ static struct platform_inst_caps platform_inst_cap_qcs8300 = {
|
|||
.mb_cycles_fw = 326389,
|
||||
.mb_cycles_fw_vpp = 44156,
|
||||
.num_comv = 0,
|
||||
.max_frame_rate = MAXIMUM_FPS,
|
||||
.max_operating_rate = MAXIMUM_FPS,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ static struct platform_inst_caps platform_inst_cap_sm8250 = {
|
|||
.max_mbpf = 138240,
|
||||
.mb_cycles_vsp = 25,
|
||||
.mb_cycles_vpp = 200,
|
||||
.max_frame_rate = MAXIMUM_FPS,
|
||||
.max_operating_rate = MAXIMUM_FPS,
|
||||
};
|
||||
|
||||
static void iris_set_sm8250_preset_registers(struct iris_core *core)
|
||||
|
|
|
|||
|
|
@ -88,3 +88,39 @@ struct iris_inst *iris_get_instance(struct iris_core *core, u32 session_id)
|
|||
mutex_unlock(&core->lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int iris_check_core_mbpf(struct iris_inst *inst)
|
||||
{
|
||||
struct iris_core *core = inst->core;
|
||||
struct iris_inst *instance;
|
||||
u32 total_mbpf = 0;
|
||||
|
||||
mutex_lock(&core->lock);
|
||||
list_for_each_entry(instance, &core->instances, list)
|
||||
total_mbpf += iris_get_mbpf(instance);
|
||||
mutex_unlock(&core->lock);
|
||||
|
||||
if (total_mbpf > core->iris_platform_data->max_core_mbpf)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iris_check_core_mbps(struct iris_inst *inst)
|
||||
{
|
||||
struct iris_core *core = inst->core;
|
||||
struct iris_inst *instance;
|
||||
u32 total_mbps = 0, fps = 0;
|
||||
|
||||
mutex_lock(&core->lock);
|
||||
list_for_each_entry(instance, &core->instances, list) {
|
||||
fps = max(instance->frame_rate, instance->operating_rate);
|
||||
total_mbps += iris_get_mbpf(instance) * fps;
|
||||
}
|
||||
mutex_unlock(&core->lock);
|
||||
|
||||
if (total_mbps > core->iris_platform_data->max_core_mbps)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,5 +49,7 @@ struct iris_inst *iris_get_instance(struct iris_core *core, u32 session_id);
|
|||
void iris_helper_buffers_done(struct iris_inst *inst, unsigned int type,
|
||||
enum vb2_buffer_state state);
|
||||
int iris_wait_for_session_response(struct iris_inst *inst, bool is_flush);
|
||||
int iris_check_core_mbpf(struct iris_inst *inst);
|
||||
int iris_check_core_mbps(struct iris_inst *inst);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -12,23 +12,6 @@
|
|||
#include "iris_vdec.h"
|
||||
#include "iris_power.h"
|
||||
|
||||
static int iris_check_core_mbpf(struct iris_inst *inst)
|
||||
{
|
||||
struct iris_core *core = inst->core;
|
||||
struct iris_inst *instance;
|
||||
u32 total_mbpf = 0;
|
||||
|
||||
mutex_lock(&core->lock);
|
||||
list_for_each_entry(instance, &core->instances, list)
|
||||
total_mbpf += iris_get_mbpf(instance);
|
||||
mutex_unlock(&core->lock);
|
||||
|
||||
if (total_mbpf > core->iris_platform_data->max_core_mbpf)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iris_check_inst_mbpf(struct iris_inst *inst)
|
||||
{
|
||||
struct platform_inst_caps *caps;
|
||||
|
|
|
|||
|
|
@ -61,6 +61,9 @@ int iris_venc_inst_init(struct iris_inst *inst)
|
|||
inst->crop.width = f->fmt.pix_mp.width;
|
||||
inst->crop.height = f->fmt.pix_mp.height;
|
||||
|
||||
inst->operating_rate = DEFAULT_FPS;
|
||||
inst->frame_rate = DEFAULT_FPS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -326,3 +329,94 @@ int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s)
|
|||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int iris_venc_s_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm)
|
||||
{
|
||||
struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps;
|
||||
struct vb2_queue *src_q = v4l2_m2m_get_src_vq(inst->m2m_ctx);
|
||||
struct vb2_queue *dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx);
|
||||
struct v4l2_fract *timeperframe = NULL;
|
||||
u32 default_rate = DEFAULT_FPS;
|
||||
bool is_frame_rate = false;
|
||||
u64 us_per_frame, fps;
|
||||
u32 max_rate;
|
||||
|
||||
int ret = 0;
|
||||
|
||||
if (s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
|
||||
timeperframe = &s_parm->parm.output.timeperframe;
|
||||
max_rate = caps->max_operating_rate;
|
||||
s_parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
|
||||
} else {
|
||||
timeperframe = &s_parm->parm.capture.timeperframe;
|
||||
is_frame_rate = true;
|
||||
max_rate = caps->max_frame_rate;
|
||||
s_parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
|
||||
}
|
||||
|
||||
if (!timeperframe->denominator || !timeperframe->numerator) {
|
||||
if (!timeperframe->numerator)
|
||||
timeperframe->numerator = 1;
|
||||
if (!timeperframe->denominator)
|
||||
timeperframe->denominator = default_rate;
|
||||
}
|
||||
|
||||
us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC;
|
||||
do_div(us_per_frame, timeperframe->denominator);
|
||||
|
||||
if (!us_per_frame)
|
||||
return -EINVAL;
|
||||
|
||||
fps = (u64)USEC_PER_SEC;
|
||||
do_div(fps, us_per_frame);
|
||||
if (fps > max_rate) {
|
||||
ret = -ENOMEM;
|
||||
goto reset_rate;
|
||||
}
|
||||
|
||||
if (is_frame_rate)
|
||||
inst->frame_rate = (u32)fps;
|
||||
else
|
||||
inst->operating_rate = (u32)fps;
|
||||
|
||||
if ((s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && vb2_is_streaming(src_q)) ||
|
||||
(s_parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && vb2_is_streaming(dst_q))) {
|
||||
ret = iris_check_core_mbpf(inst);
|
||||
if (ret)
|
||||
goto reset_rate;
|
||||
ret = iris_check_core_mbps(inst);
|
||||
if (ret)
|
||||
goto reset_rate;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
reset_rate:
|
||||
if (ret) {
|
||||
if (is_frame_rate)
|
||||
inst->frame_rate = default_rate;
|
||||
else
|
||||
inst->operating_rate = default_rate;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iris_venc_g_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm)
|
||||
{
|
||||
struct v4l2_fract *timeperframe = NULL;
|
||||
|
||||
if (s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
|
||||
timeperframe = &s_parm->parm.output.timeperframe;
|
||||
timeperframe->numerator = 1;
|
||||
timeperframe->denominator = inst->operating_rate;
|
||||
s_parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
|
||||
} else {
|
||||
timeperframe = &s_parm->parm.capture.timeperframe;
|
||||
timeperframe->numerator = 1;
|
||||
timeperframe->denominator = inst->frame_rate;
|
||||
s_parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,5 +16,7 @@ int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
|
|||
int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat);
|
||||
int iris_venc_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub);
|
||||
int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s);
|
||||
int iris_venc_g_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm);
|
||||
int iris_venc_s_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -530,6 +530,34 @@ static int iris_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subs
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int iris_s_parm(struct file *filp, void *fh, struct v4l2_streamparm *a)
|
||||
{
|
||||
struct iris_inst *inst = iris_get_inst(filp);
|
||||
|
||||
if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
|
||||
a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
|
||||
return -EINVAL;
|
||||
|
||||
if (inst->domain == ENCODER)
|
||||
return iris_venc_s_param(inst, a);
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int iris_g_parm(struct file *filp, void *fh, struct v4l2_streamparm *a)
|
||||
{
|
||||
struct iris_inst *inst = iris_get_inst(filp);
|
||||
|
||||
if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
|
||||
a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
|
||||
return -EINVAL;
|
||||
|
||||
if (inst->domain == ENCODER)
|
||||
return iris_venc_g_param(inst, a);
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int iris_dec_cmd(struct file *filp, void *fh,
|
||||
struct v4l2_decoder_cmd *dec)
|
||||
{
|
||||
|
|
@ -626,6 +654,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = {
|
|||
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
|
||||
.vidioc_g_selection = iris_g_selection,
|
||||
.vidioc_s_selection = iris_s_selection,
|
||||
.vidioc_s_parm = iris_s_parm,
|
||||
.vidioc_g_parm = iris_g_parm,
|
||||
};
|
||||
|
||||
void iris_init_ops(struct iris_core *core)
|
||||
|
|
|
|||
Loading…
Reference in New Issue