Re: [PATCH] media: venus: Add support for H265 controls required by gstreamer V4L2 H265 module
Hi Kelvin, Thanks for the patch! On 11/30/18 7:31 PM, Kelvin Lawson wrote: > Add support for V4L2_CID_MPEG_VIDEO_HEVC_PROFILE and > V4L2_CID_MPEG_VIDEO_HEVC_LEVEL controls required by gstreamer V4L2 H265 > encoder module. > > Signed-off-by: Kelvin Lawson > --- > drivers/media/platform/qcom/venus/venc_ctrls.c | 19 +++ > 1 file changed, 19 insertions(+) > > diff --git a/drivers/media/platform/qcom/venus/venc_ctrls.c > b/drivers/media/platform/qcom/venus/venc_ctrls.c > index 45910172..ad1a4d8 100644 > --- a/drivers/media/platform/qcom/venus/venc_ctrls.c > +++ b/drivers/media/platform/qcom/venus/venc_ctrls.c > @@ -101,6 +101,9 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) > case V4L2_CID_MPEG_VIDEO_H264_PROFILE: > ctr->profile.h264 = ctrl->val; > break; > + case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE: > + ctr->profile.hevc = ctrl->val; > + break; > case V4L2_CID_MPEG_VIDEO_VP8_PROFILE: > ctr->profile.vpx = ctrl->val; > break; > @@ -110,6 +113,9 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) > case V4L2_CID_MPEG_VIDEO_H264_LEVEL: > ctr->level.h264 = ctrl->val; > break; > + case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL: > + ctr->level.hevc = ctrl->val; > + break; > case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP: > ctr->h264_i_qp = ctrl->val; > break; > @@ -217,6 +223,19 @@ int venc_ctrl_init(struct venus_inst *inst) > 0, V4L2_MPEG_VIDEO_MPEG4_LEVEL_0); > > v4l2_ctrl_new_std_menu(>ctrl_handler, _ctrl_ops, > + V4L2_CID_MPEG_VIDEO_HEVC_PROFILE, > + V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10, > + ~((1 << V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) | > + (1 << V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) | > + (1 << V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10)), > + V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN); > + > + v4l2_ctrl_new_std_menu(>ctrl_handler, _ctrl_ops, > + V4L2_CID_MPEG_VIDEO_HEVC_LEVEL, > + V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2, > + 0, V4L2_MPEG_VIDEO_HEVC_LEVEL_1); > + > + v4l2_ctrl_new_std_menu(>ctrl_handler, _ctrl_ops, you are adding two new menu controls but forgot to increment the count of controls in v4l2_ctrl_handler_init(). Can you resend with that fixed? > V4L2_CID_MPEG_VIDEO_H264_PROFILE, > V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH, > ~((1 << V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | > -- regards, Stan
Re: [PATCH v2] media: venus: Support V4L2 QP parameters in Venus encoder
Hi Kelvin, Thanks for the patch! On 11/30/18 2:07 AM, Kelvin Lawson wrote: > Support V4L2 QP parameters in Venus encoder: > * V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP > * V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP > * V4L2_CID_MPEG_VIDEO_H264_MIN_QP > * V4L2_CID_MPEG_VIDEO_H264_MAX_QP > > Signed-off-by: Kelvin Lawson > --- > drivers/media/platform/qcom/venus/venc.c | 19 +++ > 1 file changed, 19 insertions(+) Acked-by: Stanimir Varbanov -- regards, Stan
Re: [PATCH] media: venus: Support V4L2 QP parameters in Venus encoder
Hi Kelvin, Thanks for the patch! On 11/12/18 12:59 PM, Kelvin Lawson wrote: > Support V4L2 QP parameters in Venus encoder: > * V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP > * V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP > * V4L2_CID_MPEG_VIDEO_H264_MIN_QP > * V4L2_CID_MPEG_VIDEO_H264_MAX_QP > > Signed-off-by: Kelvin Lawson > --- > drivers/media/platform/qcom/venus/venc.c | 19 +++ > 1 file changed, 19 insertions(+) As functional changes the patch is fine, but it has many coding style issues. Did you read [1]? > > diff --git a/drivers/media/platform/qcom/venus/venc.c > b/drivers/media/platform/qcom/venus/venc.c > index ce85962..321d612 100644 > --- a/drivers/media/platform/qcom/venus/venc.c > +++ b/drivers/media/platform/qcom/venus/venc.c > @@ -651,6 +651,8 @@ static int venc_set_properties(struct venus_inst *inst) > struct hfi_framerate frate; > struct hfi_bitrate brate; > struct hfi_idr_period idrp; > + struct hfi_quantization quant; > + struct hfi_quantization_range quant_range; > u32 ptype, rate_control, bitrate, profile = 0, level = 0; > int ret; > > @@ -770,6 +772,23 @@ static int venc_set_properties(struct venus_inst *inst) > if (ret) > return ret; > > + ptype = HFI_PROPERTY_PARAM_VENC_SESSION_QP; > + quant.qp_i = ctr->h264_i_qp; > + quant.qp_p = ctr->h264_p_qp; > + quant.qp_b = ctr->h264_b_qp; > + quant.layer_id = 0; > + ret = hfi_session_set_property(inst, ptype, ); > + if (ret) > + return ret; please fix the indentation according to coding style > + > + ptype = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE; > + quant_range.min_qp = ctr->h264_min_qp; > + quant_range.max_qp = ctr->h264_max_qp; > + quant_range.layer_id = 0; > + ret = hfi_session_set_property(inst, ptype, _range); > + if (ret) > + return ret; ditto > + > if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264) { > profile = venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_H264_PROFILE, > ctr->profile.h264); > Maybe your mail server is mangling the patches, but also please run checkpatch before sending patches. -- regards, Stan [1] https://www.kernel.org/doc/html/v4.19/process/submitting-patches.html
Re: [PATCH 0/2] Clarify H.264 loop filter offset controls and fix them for coda
Hi Philipp, On 11/28/18 3:01 PM, Philipp Zabel wrote: > Hi, > > the coda driver handles the H.264 loop filter alpha/beta offset controls > incorrectly. When trying to fix them, I noticed that the documentation > is not clear about what these values actually are. > > From the value range of -6 to +6 used in the existing drivers (s5p-mfc, > venus), it looks like they currently correspond directly to the values > stored into the slice headers: slice_alpha_c0_offset_div2 and > slice_beta_offset_div2. These are only half of the actual alpha/beta > filter offsets. > > The ITU-T Rec. H.264 (02/2016) states: > > slice_alpha_c0_offset_div2 specifies the offset used in accessing the > α [...] deblocking filter tables for filtering operations controlled > by the macroblocks within the slice. From this value, the offset that > shall be applied when addressing these tables shall be computed as > > FilterOffsetA = slice_alpha_c0_offset_div2 << 1 (7-32) > > The value of slice_alpha_c0_offset_div2 shall be in the range of −6 to > +6, inclusive. When slice_alpha_c0_offset_div2 is not present in the > slice header, the value of slice_alpha_c0_offset_div2 shall be inferred > to be equal to 0. > > And the same for slice_beta_offset_div2 / FilterOffsetB. > > Do the s5p-mfc and venus drivers use the controls > V4L2_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA and _BETA directly as slice > header fields, and thus their values are to be interpreted as half of > FilterOffsetA/B defined in the H.264 spec, respectively? That is correct for Venus encoder, it uses slice header fields directly [-6, 6]. -- regards, Stan
Re: [PATCH] media: venus: support VB2_USERPTR IO mode
Hi Alex, On 10/11/2018 09:50 AM, Alexandre Courbot wrote: > Please ignore this patch - I did not notice that a similar one has > been sent before. The difference is that you made it for decoder as well. Do you need userptr for decoder? -- regards, Stan
Re: [PATCH v3] vb2: check for sane values from queue_setup
Hi, On 09/11/2018 03:46 PM, Johan Fjeldtvedt wrote: > Warn and return error from the reqbufs ioctl when driver sets 0 number > of planes or 0 as plane sizes, as these values don't make any sense. typo: planes -> buffers > Checking this here stops obviously wrong values from propagating > further and causing various problems that are hard to trace back to > either of these values being 0. > > Signed-off-by: Johan Fjeldtvedt > --- > drivers/media/common/videobuf2/videobuf2-core.c | 9 + > 1 file changed, 9 insertions(+) > > diff --git a/drivers/media/common/videobuf2/videobuf2-core.c > b/drivers/media/common/videobuf2/videobuf2-core.c > index f32ec7342ef0..5741e95e6af1 100644 > --- a/drivers/media/common/videobuf2/videobuf2-core.c > +++ b/drivers/media/common/videobuf2/videobuf2-core.c > @@ -662,6 +662,7 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory > memory, > unsigned int num_buffers, allocated_buffers, num_planes = 0; > unsigned plane_sizes[VB2_MAX_PLANES] = { }; > int ret; > + int i; > > if (q->streaming) { > dprintk(1, "streaming active\n"); > @@ -718,6 +719,14 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum > vb2_memory memory, > if (ret) > return ret; > > + /* Check that driver has set sane values */ > + if (WARN_ON(!num_buffers)) > + return -EINVAL; > + > + for (i = 0; i < num_buffers; i++) > + if (WARN_ON(!plane_sizes[i])) > + return -EINVAL; > + > /* Finally, allocate buffers and video memory */ > allocated_buffers = > __vb2_queue_alloc(q, memory, num_buffers, num_planes, > plane_sizes); > -- regards, Stan
Re: [PATCH 4/4] venus: firmware: register separate platform_device for firmware loader
Hi Vikash, Could you give a try below patch on your environment? You should keep your 1/4 to 3/4 patches and replace your 4/4 with the below one. You have to drop the compatible string in firmware DT subnode (keep only iommus). On 08/22/2018 03:34 PM, Stanimir Varbanov wrote: > This registers a firmware platform_device and associate it with > video-firmware DT subnode. Then calls dma configure to initialize > dma and iommu. > > Signed-off-by: Stanimir Varbanov > --- > .../devicetree/bindings/media/qcom,venus.txt | 13 +- > drivers/media/platform/qcom/venus/core.c | 14 +-- > drivers/media/platform/qcom/venus/firmware.c | 49 > ++ > drivers/media/platform/qcom/venus/firmware.h | 2 + > 4 files changed, 73 insertions(+), 5 deletions(-) > > diff --git a/Documentation/devicetree/bindings/media/qcom,venus.txt > b/Documentation/devicetree/bindings/media/qcom,venus.txt > index 00d0d1bf7647..7e045862c3fe 100644 > --- a/Documentation/devicetree/bindings/media/qcom,venus.txt > +++ b/Documentation/devicetree/bindings/media/qcom,venus.txt > @@ -53,7 +53,7 @@ > > * Subnodes > The Venus video-codec node must contain two subnodes representing > -video-decoder and video-encoder. > +video-decoder and video-encoder, and one optional firmware subnode. > > Every of video-encoder or video-decoder subnode should have: > > @@ -79,6 +79,13 @@ Every of video-encoder or video-decoder subnode should > have: > power domain which is responsible for collapsing > and restoring power to the subcore. > > +The firmware subnode must have: > + > +- iommus: > + Usage: required > + Value type: > + Definition: A list of phandle and IOMMU specifier pairs. > + > * An Example > video-codec@1d0 { > compatible = "qcom,msm8916-venus"; > @@ -105,4 +112,8 @@ Every of video-encoder or video-decoder subnode should > have: > clock-names = "core"; > power-domains = < VENUS_CORE1_GDSC>; > }; > + > + video-firmware { > + iommus = <_iommu 0x10b2 0x0>; > + }; > }; > diff --git a/drivers/media/platform/qcom/venus/core.c > b/drivers/media/platform/qcom/venus/core.c > index 393994ecab26..3bd3b8ab1f82 100644 > --- a/drivers/media/platform/qcom/venus/core.c > +++ b/drivers/media/platform/qcom/venus/core.c > @@ -284,6 +284,14 @@ static int venus_probe(struct platform_device *pdev) > if (ret < 0) > goto err_runtime_disable; > > + ret = of_platform_populate(dev->of_node, NULL, NULL, dev); > + if (ret) > + goto err_runtime_disable; > + > + ret = venus_firmware_init(core); > + if (ret) > + goto err_runtime_disable; > + > ret = venus_boot(core); > if (ret) > goto err_runtime_disable; > @@ -308,10 +316,6 @@ static int venus_probe(struct platform_device *pdev) > if (ret) > goto err_core_deinit; > > - ret = of_platform_populate(dev->of_node, NULL, NULL, dev); > - if (ret) > - goto err_dev_unregister; > - > ret = pm_runtime_put_sync(dev); > if (ret) > goto err_dev_unregister; > @@ -347,6 +351,8 @@ static int venus_remove(struct platform_device *pdev) > venus_shutdown(core); > of_platform_depopulate(dev); > > + venus_firmware_deinit(core); > + > pm_runtime_put_sync(dev); > pm_runtime_disable(dev); > > diff --git a/drivers/media/platform/qcom/venus/firmware.c > b/drivers/media/platform/qcom/venus/firmware.c > index 80c3d1362c04..2a9fcbb71216 100644 > --- a/drivers/media/platform/qcom/venus/firmware.c > +++ b/drivers/media/platform/qcom/venus/firmware.c > @@ -20,6 +20,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -228,3 +229,51 @@ int venus_shutdown(struct venus_core *core) > > return ret; > } > + > +int venus_firmware_init(struct venus_core *core) > +{ > + struct platform_device_info info; > + struct platform_device *pdev; > + struct device_node *np; > + int ret; > + > + np = of_get_child_by_name(core->dev->of_node, "video-firmware"); > + if (!np) > + return 0; > + > + memset(, 0, sizeof(info)); > + info.fwnode = >fwnode; > + info.parent = core->dev; > + info.name = np->name; > + info.dma_mask = DMA_BIT_MASK(32); > + > + pdev = platform_device_register_ful
[PATCH 4/4] venus: firmware: register separate platform_device for firmware loader
This registers a firmware platform_device and associate it with video-firmware DT subnode. Then calls dma configure to initialize dma and iommu. Signed-off-by: Stanimir Varbanov --- .../devicetree/bindings/media/qcom,venus.txt | 13 +- drivers/media/platform/qcom/venus/core.c | 14 +-- drivers/media/platform/qcom/venus/firmware.c | 49 ++ drivers/media/platform/qcom/venus/firmware.h | 2 + 4 files changed, 73 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/media/qcom,venus.txt b/Documentation/devicetree/bindings/media/qcom,venus.txt index 00d0d1bf7647..7e045862c3fe 100644 --- a/Documentation/devicetree/bindings/media/qcom,venus.txt +++ b/Documentation/devicetree/bindings/media/qcom,venus.txt @@ -53,7 +53,7 @@ * Subnodes The Venus video-codec node must contain two subnodes representing -video-decoder and video-encoder. +video-decoder and video-encoder, and one optional firmware subnode. Every of video-encoder or video-decoder subnode should have: @@ -79,6 +79,13 @@ Every of video-encoder or video-decoder subnode should have: power domain which is responsible for collapsing and restoring power to the subcore. +The firmware subnode must have: + +- iommus: + Usage: required + Value type: + Definition: A list of phandle and IOMMU specifier pairs. + * An Example video-codec@1d0 { compatible = "qcom,msm8916-venus"; @@ -105,4 +112,8 @@ Every of video-encoder or video-decoder subnode should have: clock-names = "core"; power-domains = < VENUS_CORE1_GDSC>; }; + + video-firmware { + iommus = <_iommu 0x10b2 0x0>; + }; }; diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index 393994ecab26..3bd3b8ab1f82 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -284,6 +284,14 @@ static int venus_probe(struct platform_device *pdev) if (ret < 0) goto err_runtime_disable; + ret = of_platform_populate(dev->of_node, NULL, NULL, dev); + if (ret) + goto err_runtime_disable; + + ret = venus_firmware_init(core); + if (ret) + goto err_runtime_disable; + ret = venus_boot(core); if (ret) goto err_runtime_disable; @@ -308,10 +316,6 @@ static int venus_probe(struct platform_device *pdev) if (ret) goto err_core_deinit; - ret = of_platform_populate(dev->of_node, NULL, NULL, dev); - if (ret) - goto err_dev_unregister; - ret = pm_runtime_put_sync(dev); if (ret) goto err_dev_unregister; @@ -347,6 +351,8 @@ static int venus_remove(struct platform_device *pdev) venus_shutdown(core); of_platform_depopulate(dev); + venus_firmware_deinit(core); + pm_runtime_put_sync(dev); pm_runtime_disable(dev); diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c index 80c3d1362c04..2a9fcbb71216 100644 --- a/drivers/media/platform/qcom/venus/firmware.c +++ b/drivers/media/platform/qcom/venus/firmware.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -228,3 +229,51 @@ int venus_shutdown(struct venus_core *core) return ret; } + +int venus_firmware_init(struct venus_core *core) +{ + struct platform_device_info info; + struct platform_device *pdev; + struct device_node *np; + int ret; + + np = of_get_child_by_name(core->dev->of_node, "video-firmware"); + if (!np) + return 0; + + memset(, 0, sizeof(info)); + info.fwnode = >fwnode; + info.parent = core->dev; + info.name = np->name; + info.dma_mask = DMA_BIT_MASK(32); + + pdev = platform_device_register_full(); + if (IS_ERR(pdev)) { + of_node_put(np); + return PTR_ERR(pdev); + } + + pdev->dev.of_node = np; + + ret = of_dma_configure(>dev, np); + if (ret) + dev_err(core->dev, "dma configure fail\n"); + + of_node_put(np); + + if (ret) + return ret; + + core->no_tz = true; + core->fw.dev = >dev; + + return 0; +} + +void venus_firmware_deinit(struct venus_core *core) +{ + if (!core->fw.dev) + return; + + platform_device_unregister(to_platform_device(core->fw.dev)); +} diff --git a/drivers/media/platform/qcom/venus/firmware.h b/drivers/media/platform/qcom/venus/firmware.h index f41b615b96f1..119a9a4fc1a2 100644 --- a/drivers/media/platform/qcom/venus/firm
Re: [PATCH v3 1/4] venus: firmware: add routine to reset ARM9
Hi, On 07/04/2018 10:06 PM, Vikash Garodia wrote: > Add routine to reset the ARM9 and brings it out of reset. Also > abstract the Venus CPU state handling with a new function. This > is in preparation to add PIL functionality in venus driver. > > Signed-off-by: Vikash Garodia > --- > drivers/media/platform/qcom/venus/core.h | 1 + > drivers/media/platform/qcom/venus/firmware.c | 36 > > drivers/media/platform/qcom/venus/firmware.h | 1 + > drivers/media/platform/qcom/venus/hfi_venus.c| 13 +++-- > drivers/media/platform/qcom/venus/hfi_venus_io.h | 5 > 5 files changed, 47 insertions(+), 9 deletions(-) > > diff --git a/drivers/media/platform/qcom/venus/core.h > b/drivers/media/platform/qcom/venus/core.h > index 2f02365..eb5ee66 100644 > --- a/drivers/media/platform/qcom/venus/core.h > +++ b/drivers/media/platform/qcom/venus/core.h > @@ -129,6 +129,7 @@ struct venus_core { > struct device *dev; > struct device *dev_dec; > struct device *dev_enc; > + bool no_tz; > struct mutex lock; > struct list_head instances; > atomic_t insts_count; > diff --git a/drivers/media/platform/qcom/venus/firmware.c > b/drivers/media/platform/qcom/venus/firmware.c > index 521d4b3..3968553d 100644 > --- a/drivers/media/platform/qcom/venus/firmware.c > +++ b/drivers/media/platform/qcom/venus/firmware.c > @@ -22,11 +22,47 @@ > #include > #include > > +#include "core.h" > #include "firmware.h" > +#include "hfi_venus_io.h" > > #define VENUS_PAS_ID 9 > #define VENUS_FW_MEM_SIZE(6 * SZ_1M) > > +static void venus_reset_cpu(struct venus_core *core) > +{ > + void __iomem *base = core->base; > + > + writel(0, base + WRAPPER_FW_START_ADDR); > + writel(VENUS_FW_MEM_SIZE, base + WRAPPER_FW_END_ADDR); > + writel(0, base + WRAPPER_CPA_START_ADDR); > + writel(VENUS_FW_MEM_SIZE, base + WRAPPER_CPA_END_ADDR); > + writel(0x0, base + WRAPPER_CPU_CGC_DIS); > + writel(0x0, base + WRAPPER_CPU_CLOCK_CONFIG); > + > + /* Make sure all register writes are committed. */ > + mb(); > + > + /* Bring ARM9 out of reset */ > + writel_relaxed(0, base + WRAPPER_A9SS_SW_RESET); > +} > + > +int venus_set_hw_state(struct venus_core *core, bool resume) > +{ > + void __iomem *base = core->base; > + > + if (!core->no_tz) > + return qcom_scm_set_remote_state(resume, 0); > + > + if (resume) > + venus_reset_cpu(core); > + else > + writel(1, base + WRAPPER_A9SS_SW_RESET); > + > + return 0; > +} > +EXPORT_SYMBOL_GPL(venus_set_hw_state); This export_symbol shouldn't be needed -- regards, Stan
Re: [PATCH v3 3/4] venus: firmware: add no TZ boot and shutdown routine
Hi Vikash, On 07/04/2018 10:06 PM, Vikash Garodia wrote: > Video hardware is mainly comprised of vcodec subsystem and video > control subsystem. Video control has ARM9 which executes the video > firmware instructions whereas vcodec does the video frame processing. > This change adds support to load the video firmware and bring ARM9 > out of reset for platforms which does not have trustzone. > > Signed-off-by: Vikash Garodia > --- > drivers/media/platform/qcom/venus/core.c | 6 +- > drivers/media/platform/qcom/venus/core.h | 5 ++ > drivers/media/platform/qcom/venus/firmware.c | 93 > ++-- > drivers/media/platform/qcom/venus/firmware.h | 2 +- > 4 files changed, 98 insertions(+), 8 deletions(-) > > diff --git a/drivers/media/platform/qcom/venus/core.c > b/drivers/media/platform/qcom/venus/core.c > index 75b9785..393994e 100644 > --- a/drivers/media/platform/qcom/venus/core.c > +++ b/drivers/media/platform/qcom/venus/core.c > @@ -76,7 +76,7 @@ static void venus_sys_error_handler(struct work_struct > *work) > hfi_core_deinit(core, true); > hfi_destroy(core); > mutex_lock(>lock); > - venus_shutdown(core->dev); > + venus_shutdown(core); > > pm_runtime_put_sync(core->dev); > > @@ -323,7 +323,7 @@ static int venus_probe(struct platform_device *pdev) > err_core_deinit: > hfi_core_deinit(core, false); > err_venus_shutdown: > - venus_shutdown(dev); > + venus_shutdown(core); > err_runtime_disable: > pm_runtime_set_suspended(dev); > pm_runtime_disable(dev); > @@ -344,7 +344,7 @@ static int venus_remove(struct platform_device *pdev) > WARN_ON(ret); > > hfi_destroy(core); > - venus_shutdown(dev); > + venus_shutdown(core); > of_platform_depopulate(dev); > > pm_runtime_put_sync(dev); > diff --git a/drivers/media/platform/qcom/venus/core.h > b/drivers/media/platform/qcom/venus/core.h > index eb5ee66..abe4ddf 100644 > --- a/drivers/media/platform/qcom/venus/core.h > +++ b/drivers/media/platform/qcom/venus/core.h > @@ -81,6 +81,10 @@ struct venus_caps { > bool valid; /* used only for Venus v1xx */ > }; > > +struct video_firmware { > + struct device *dev; > + struct iommu_domain *iommu_domain; > +}; add an empty line here > /** > * struct venus_core - holds core parameters valid for all instances > * > @@ -129,6 +133,7 @@ struct venus_core { > struct device *dev; > struct device *dev_dec; > struct device *dev_enc; > + struct video_firmware fw; > bool no_tz; > struct mutex lock; > struct list_head instances; > diff --git a/drivers/media/platform/qcom/venus/firmware.c > b/drivers/media/platform/qcom/venus/firmware.c > index 6d6cca4..2a98d9e 100644 > --- a/drivers/media/platform/qcom/venus/firmware.c > +++ b/drivers/media/platform/qcom/venus/firmware.c > @@ -12,8 +12,10 @@ > * > */ > > +#include > #include > #include > +#include > #include > #include > #include > @@ -27,7 +29,8 @@ > #include "hfi_venus_io.h" > > #define VENUS_PAS_ID 9 > -#define VENUS_FW_MEM_SIZE(6 * SZ_1M) > +#define VENUS_FW_MEM_SIZE(5 * SZ_1M) This change should be subject to a separate patch. > +#define VENUS_FW_START_ADDR 0x0 > > static void venus_reset_cpu(struct venus_core *core) > { > @@ -121,6 +124,76 @@ static int venus_load_fw(struct venus_core *core, const > char *fwname, > return ret; > } > > +int venus_boot_noTZ(struct venus_core *core, phys_addr_t mem_phys, > + size_t mem_size) please use lowercase for function names and correct the size_t mem_size indentation. > +{ > + struct iommu_domain *iommu; s/iommu/iommu_dom ? > + struct device *dev; > + int ret; > + > + if (!core->fw.dev) > + return -EPROBE_DEFER; > + > + dev = core->fw.dev; you could make this initialization in declaration and check for !dev above in the if statement. > + > + iommu = iommu_domain_alloc(_bus_type); > + if (!iommu) { > + dev_err(dev, "Failed to allocate iommu domain\n"); > + return -ENOMEM; > + } > + > + ret = iommu_attach_device(iommu, dev); > + if (ret) { > + dev_err(dev, "could not attach device\n"); > + goto err_attach; > + } > + > + ret = iommu_map(iommu, VENUS_FW_START_ADDR, mem_phys, mem_size, > + IOMMU_READ|IOMMU_WRITE|IOMMU_PRIV); spaces between IOMMU_xxx > + if (ret) { > + dev_err(dev, "could not map video firmware region\n"); > + goto err_map; > + } add blank line here > + core->fw.iommu_domain = iommu; > + venus_reset_cpu(core); > + > + return 0; > + > +err_map: > + iommu_detach_device(iommu, dev); > +err_attach: > + iommu_domain_free(iommu); > + return ret; > +} > + > +int venus_shutdown_noTZ(struct venus_core *core)
Re: [PATCH v3 2/4] venus: firmware: move load firmware in a separate function
Hi Vikash, On 07/04/2018 10:06 PM, Vikash Garodia wrote: > Separate firmware loading part into a new function. I cannot apply this patch in order to test the series. > > Signed-off-by: Vikash Garodia > --- > drivers/media/platform/qcom/venus/core.c | 4 +- > drivers/media/platform/qcom/venus/firmware.c | 58 > +--- > drivers/media/platform/qcom/venus/firmware.h | 2 +- > 3 files changed, 39 insertions(+), 25 deletions(-) > > diff --git a/drivers/media/platform/qcom/venus/core.c > b/drivers/media/platform/qcom/venus/core.c > index bb6add9..75b9785 100644 > --- a/drivers/media/platform/qcom/venus/core.c > +++ b/drivers/media/platform/qcom/venus/core.c > @@ -84,7 +84,7 @@ static void venus_sys_error_handler(struct work_struct > *work) > > pm_runtime_get_sync(core->dev); > > - ret |= venus_boot(core->dev, core->res->fwname); > + ret |= venus_boot(core); > > ret |= hfi_core_resume(core, true); > > @@ -284,7 +284,7 @@ static int venus_probe(struct platform_device *pdev) > if (ret < 0) > goto err_runtime_disable; > > - ret = venus_boot(dev, core->res->fwname); > + ret = venus_boot(core); > if (ret) > goto err_runtime_disable; > > diff --git a/drivers/media/platform/qcom/venus/firmware.c > b/drivers/media/platform/qcom/venus/firmware.c > index 3968553d..6d6cca4 100644 > --- a/drivers/media/platform/qcom/venus/firmware.c > +++ b/drivers/media/platform/qcom/venus/firmware.c > @@ -63,40 +63,37 @@ int venus_set_hw_state(struct venus_core *core, bool > resume) > } > EXPORT_SYMBOL_GPL(venus_set_hw_state); > > -int venus_boot(struct device *dev, const char *fwname) > +static int venus_load_fw(struct venus_core *core, const char *fwname, > + phys_addr_t *mem_phys, size_t *mem_size) the next function argument on new line should be just below open brace > { > const struct firmware *mdt; > struct device_node *node; > - phys_addr_t mem_phys; > + struct device *dev; > struct resource r; > ssize_t fw_size; > - size_t mem_size; > void *mem_va; > int ret; > > - if (!IS_ENABLED(CONFIG_QCOM_MDT_LOADER) || !qcom_scm_is_available()) > - return -EPROBE_DEFER; > - > + dev = core->dev; > node = of_parse_phandle(dev->of_node, "memory-region", 0); > if (!node) { > dev_err(dev, "no memory-region specified\n"); > return -EINVAL; > } > - please don't delete above blank line > ret = of_address_to_resource(node, 0, ); > if (ret) > return ret; > > - mem_phys = r.start; > - mem_size = resource_size(); > + *mem_phys = r.start; > + *mem_size = resource_size(); > > - if (mem_size < VENUS_FW_MEM_SIZE) > + if (*mem_size < VENUS_FW_MEM_SIZE) > return -EINVAL; > > - mem_va = memremap(r.start, mem_size, MEMREMAP_WC); > + mem_va = memremap(r.start, *mem_size, MEMREMAP_WC); > if (!mem_va) { > dev_err(dev, "unable to map memory region: %pa+%zx\n", > - , mem_size); > + , *mem_size); > return -ENOMEM; > } > > @@ -110,24 +107,41 @@ int venus_boot(struct device *dev, const char *fwname) > release_firmware(mdt); > goto err_unmap; > } > - > - ret = qcom_mdt_load(dev, mdt, fwname, VENUS_PAS_ID, mem_va, mem_phys, > - mem_size); > + if (core->no_tz) > + ret = qcom_mdt_load_no_init(dev, mdt, fwname, VENUS_PAS_ID, > + mem_va, *mem_phys, *mem_size, NULL); indentation is wrong see the original code > + else > + ret = qcom_mdt_load(dev, mdt, fwname, VENUS_PAS_ID, mem_va, > + *mem_phys, *mem_size); indentation again > > release_firmware(mdt); > > - if (ret) > - goto err_unmap; > - > - ret = qcom_scm_pas_auth_and_reset(VENUS_PAS_ID); > - if (ret) > - goto err_unmap; > - > err_unmap: > memunmap(mem_va); > return ret; > } > > +int venus_boot(struct venus_core *core) > +{ > + phys_addr_t mem_phys; > + size_t mem_size; > + int ret; > + struct device *dev; please order declarations from longer to shorter. > + > + if (!IS_ENABLED(CONFIG_QCOM_MDT_LOADER)) > + return -EPROBE_DEFER; the original venus_boot was checking for || !qcom_scm_is_available() why is that removed? It was done on purpose. > + > + dev = core->dev; this could be done when dev is declared. > + > + ret = venus_load_fw(core, core->res->fwname, _phys, _size); > + if (ret) { > + dev_err(dev, "fail to load video firmware\n"); > + return -EINVAL; > + } > + > + return qcom_scm_pas_auth_and_reset(VENUS_PAS_ID); > +} > + > int venus_shutdown(struct device *dev) > { > return
Re: [PATCH v3 1/4] venus: firmware: add routine to reset ARM9
Hi Vikash, On 07/04/2018 10:06 PM, Vikash Garodia wrote: > Add routine to reset the ARM9 and brings it out of reset. Also > abstract the Venus CPU state handling with a new function. This > is in preparation to add PIL functionality in venus driver. > > Signed-off-by: Vikash Garodia > --- > drivers/media/platform/qcom/venus/core.h | 1 + > drivers/media/platform/qcom/venus/firmware.c | 36 > > drivers/media/platform/qcom/venus/firmware.h | 1 + > drivers/media/platform/qcom/venus/hfi_venus.c| 13 +++-- > drivers/media/platform/qcom/venus/hfi_venus_io.h | 5 > 5 files changed, 47 insertions(+), 9 deletions(-) > > diff --git a/drivers/media/platform/qcom/venus/core.h > b/drivers/media/platform/qcom/venus/core.h > index 2f02365..eb5ee66 100644 > --- a/drivers/media/platform/qcom/venus/core.h > +++ b/drivers/media/platform/qcom/venus/core.h > @@ -129,6 +129,7 @@ struct venus_core { > struct device *dev; > struct device *dev_dec; > struct device *dev_enc; > + bool no_tz; > struct mutex lock; > struct list_head instances; > atomic_t insts_count; > diff --git a/drivers/media/platform/qcom/venus/firmware.c > b/drivers/media/platform/qcom/venus/firmware.c > index 521d4b3..3968553d 100644 > --- a/drivers/media/platform/qcom/venus/firmware.c > +++ b/drivers/media/platform/qcom/venus/firmware.c > @@ -22,11 +22,47 @@ > #include > #include > > +#include "core.h" > #include "firmware.h" > +#include "hfi_venus_io.h" > > #define VENUS_PAS_ID 9 > #define VENUS_FW_MEM_SIZE(6 * SZ_1M) > > +static void venus_reset_cpu(struct venus_core *core) > +{ > + void __iomem *base = core->base; > + > + writel(0, base + WRAPPER_FW_START_ADDR); > + writel(VENUS_FW_MEM_SIZE, base + WRAPPER_FW_END_ADDR); > + writel(0, base + WRAPPER_CPA_START_ADDR); > + writel(VENUS_FW_MEM_SIZE, base + WRAPPER_CPA_END_ADDR); > + writel(0x0, base + WRAPPER_CPU_CGC_DIS); > + writel(0x0, base + WRAPPER_CPU_CLOCK_CONFIG); > + > + /* Make sure all register writes are committed. */ > + mb(); > + > + /* Bring ARM9 out of reset */ > + writel_relaxed(0, base + WRAPPER_A9SS_SW_RESET); replace writel_relaxed with writel and drop above mb. The writel has wmb just before writing so I think using writel here is better choice. > +} > + > +int venus_set_hw_state(struct venus_core *core, bool resume) s/resume/suspend as it is done in the function prototype in firmware.h. > +{ > + void __iomem *base = core->base; > + > + if (!core->no_tz) > + return qcom_scm_set_remote_state(resume, 0); > + > + if (resume) > + venus_reset_cpu(core); > + else > + writel(1, base + WRAPPER_A9SS_SW_RESET); > + > + return 0; > +} > +EXPORT_SYMBOL_GPL(venus_set_hw_state); > + > int venus_boot(struct device *dev, const char *fwname) > { > const struct firmware *mdt; > diff --git a/drivers/media/platform/qcom/venus/firmware.h > b/drivers/media/platform/qcom/venus/firmware.h > index 428efb5..ff2e70e 100644 > --- a/drivers/media/platform/qcom/venus/firmware.h > +++ b/drivers/media/platform/qcom/venus/firmware.h > @@ -18,5 +18,6 @@ > > int venus_boot(struct device *dev, const char *fwname); > int venus_shutdown(struct device *dev); > +int venus_set_hw_state(struct venus_core *core, bool suspend); could you make two inline functions here, call them venus_set_hw_state_suspend() and venus_set_hw_state_resume() which just call venus_set_hw_state with the right state. > > #endif > diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c > b/drivers/media/platform/qcom/venus/hfi_venus.c > index 9366dae..5b56925 100644 > --- a/drivers/media/platform/qcom/venus/hfi_venus.c > +++ b/drivers/media/platform/qcom/venus/hfi_venus.c > @@ -19,7 +19,6 @@ > #include > #include > #include > -#include > #include > > #include "core.h" > @@ -27,6 +26,7 @@ > #include "hfi_msgs.h" > #include "hfi_venus.h" > #include "hfi_venus_io.h" > +#include "firmware.h" > > #define HFI_MASK_QHDR_TX_TYPE0xff00 > #define HFI_MASK_QHDR_RX_TYPE0x00ff > @@ -55,11 +55,6 @@ > #define IFACEQ_VAR_LARGE_PKT_SIZE512 > #define IFACEQ_VAR_HUGE_PKT_SIZE (1024 * 12) > > -enum tzbsp_video_state { > - TZBSP_VIDEO_STATE_SUSPEND = 0, > - TZBSP_VIDEO_STATE_RESUME > -}; > - > struct hfi_queue_table_header { > u32 version; > u32 size; > @@ -575,7 +570,7 @@ static int venus_power_off(struct venus_hfi_device *hdev) > if (!hdev->power_enabled) > return 0; > > - ret = qcom_scm_set_remote_state(TZBSP_VIDEO_STATE_SUSPEND, 0); > + ret = venus_set_hw_state(hdev->core, false); ... and use venus_set_hw_state_suspend() > if (ret) > return ret; > > @@ -595,7 +590,7 @@ static int venus_power_on(struct venus_hfi_device *hdev) > if (hdev->power_enabled) >
[PATCH v5 10/27] venus: hfi_venus: add suspend functionality for Venus 4xx
This adds suspend (power collapse) functionality by reusing the suspend function for Venus 3xx and also enables idle indicator property for Venus 4xx (where it is disabled by default). Signed-off-by: Stanimir Varbanov Reviewed-by: Tomasz Figa --- drivers/media/platform/qcom/venus/hfi_venus.c | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index 7a83e967a8ea..124085556b94 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -879,6 +879,14 @@ static int venus_sys_set_default_properties(struct venus_hfi_device *hdev) if (ret) dev_warn(dev, "setting fw debug msg ON failed (%d)\n", ret); + /* +* Idle indicator is disabled by default on some 4xx firmware versions, +* enable it explicitly in order to make suspend functional by checking +* WFI (wait-for-interrupt) bit. +*/ + if (IS_V4(hdev->core)) + venus_sys_idle_indicator = true; + ret = venus_sys_set_idle_message(hdev, venus_sys_idle_indicator); if (ret) dev_warn(dev, "setting idle response ON failed (%d)\n", ret); @@ -1533,7 +1541,7 @@ static int venus_suspend_3xx(struct venus_core *core) static int venus_suspend(struct venus_core *core) { - if (core->res->hfi_version == HFI_VERSION_3XX) + if (IS_V3(core) || IS_V4(core)) return venus_suspend_3xx(core); return venus_suspend_1xx(core); -- 2.14.1
Re: [PATCH v2 11/29] venus: venc,vdec: adds clocks needed for venus 4xx
Hi Tomasz, On 05/24/2018 09:11 AM, Tomasz Figa wrote: > Hi Stanimir, > > On Tue, May 15, 2018 at 5:10 PM Stanimir Varbanov < > stanimir.varba...@linaro.org> wrote: > >> This extends the clocks number to support suspend and resume >> on Venus version 4xx. > >> Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> >> --- >> drivers/media/platform/qcom/venus/core.h | 4 +-- >> drivers/media/platform/qcom/venus/vdec.c | 42 > ++-- >> drivers/media/platform/qcom/venus/venc.c | 42 > ++-- >> 3 files changed, 72 insertions(+), 16 deletions(-) > >> diff --git a/drivers/media/platform/qcom/venus/core.h > b/drivers/media/platform/qcom/venus/core.h >> index 8d3e150800c9..b5b9a84e9155 100644 >> --- a/drivers/media/platform/qcom/venus/core.h >> +++ b/drivers/media/platform/qcom/venus/core.h >> @@ -92,8 +92,8 @@ struct venus_core { >> void __iomem *base; >> int irq; >> struct clk *clks[VIDC_CLKS_NUM_MAX]; >> - struct clk *core0_clk; >> - struct clk *core1_clk; >> + struct clk *core0_clk, *core0_bus_clk; >> + struct clk *core1_clk, *core1_bus_clk; >> struct video_device *vdev_dec; >> struct video_device *vdev_enc; >> struct v4l2_device v4l2_dev; >> diff --git a/drivers/media/platform/qcom/venus/vdec.c > b/drivers/media/platform/qcom/venus/vdec.c >> index 261a51adeef2..c45452634e7e 100644 >> --- a/drivers/media/platform/qcom/venus/vdec.c >> +++ b/drivers/media/platform/qcom/venus/vdec.c >> @@ -1081,12 +1081,18 @@ static int vdec_probe(struct platform_device > *pdev) >> if (!core) >> return -EPROBE_DEFER; > >> - if (core->res->hfi_version == HFI_VERSION_3XX) { >> + if (IS_V3(core) || IS_V4(core)) { >> core->core0_clk = devm_clk_get(dev, "core"); >> if (IS_ERR(core->core0_clk)) >> return PTR_ERR(core->core0_clk); >> } > >> + if (IS_V4(core)) { >> + core->core0_bus_clk = devm_clk_get(dev, "bus"); >> + if (IS_ERR(core->core0_bus_clk)) >> + return PTR_ERR(core->core0_bus_clk); >> + } >> + > > Rather than doing this conditional dance, wouldn't it make more sense to > just list all the clocks in variant data struct and use clk_bulk_get()? Do you mean the same as it is done for venus/core.c ? > >> platform_set_drvdata(pdev, core); > >> vdev = video_device_alloc(); >> @@ -1132,12 +1138,23 @@ static __maybe_unused int > vdec_runtime_suspend(struct device *dev) >> { >> struct venus_core *core = dev_get_drvdata(dev); > >> - if (core->res->hfi_version == HFI_VERSION_1XX) >> + if (IS_V1(core)) >> return 0; > >> - writel(0, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); >> + if (IS_V3(core)) >> + writel(0, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); >> + else if (IS_V4(core)) >> + writel(0, core->base + > WRAPPER_VCODEC0_MMCC_POWER_CONTROL); >> + >> + if (IS_V4(core)) >> + clk_disable_unprepare(core->core0_bus_clk); >> + >> clk_disable_unprepare(core->core0_clk); >> - writel(1, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); >> + >> + if (IS_V3(core)) >> + writel(1, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); >> + else if (IS_V4(core)) >> + writel(1, core->base + > WRAPPER_VCODEC0_MMCC_POWER_CONTROL); > > Almost every step here differs between version. I'd suggest splitting this > into separate functions for both versions. I think it will be better to squash this patch with 13/29. -- regards, Stan
Re: [PATCH 3/4] venus: add check to make scm calls
Hi Jordan, On 22.05.2018 22:50, Jordan Crouse wrote: On Tue, May 22, 2018 at 04:04:51PM +0300, Stanimir Varbanov wrote: Hi Vikash, On 05/17/2018 02:32 PM, Vikash Garodia wrote: In order to invoke scm calls, ensure that the platform has the required support to invoke the scm calls in secure world. This code is in preparation to add PIL functionality in venus driver. Signed-off-by: Vikash Garodia <vgaro...@codeaurora.org> --- drivers/media/platform/qcom/venus/hfi_venus.c | 26 +++--- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index f61d34b..9bcce94 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -27,6 +27,7 @@ #include "hfi_msgs.h" #include "hfi_venus.h" #include "hfi_venus_io.h" +#include "firmware.h" #define HFI_MASK_QHDR_TX_TYPE 0xff00 #define HFI_MASK_QHDR_RX_TYPE 0x00ff @@ -570,13 +571,19 @@ static int venus_halt_axi(struct venus_hfi_device *hdev) static int venus_power_off(struct venus_hfi_device *hdev) { int ret; + void __iomem *reg_base; if (!hdev->power_enabled) return 0; - ret = qcom_scm_set_remote_state(TZBSP_VIDEO_STATE_SUSPEND, 0); - if (ret) - return ret; + if (qcom_scm_is_available()) { + ret = qcom_scm_set_remote_state(TZBSP_VIDEO_STATE_SUSPEND, 0); I think it will be clearer if we abstract qcom_scm_set_remote_state to something like venus_set_state(SUSPEND|RESUME) in firmware.c and export the functions to be used here. This specific function is a little odd because the SCM function got overloaded and used as a hardware workaround for the adreno a5xx zap shader. When we added it for the GPU we knew the day would come that we would need it for Venus so we kept the name purposely generic. You can wrap if if you want but just know that there are other non video entities out there using it. Sorry I wasn't clear, by abstract it I meant to introduce a new venus_set_state function in venus/firmware.c where we'll select tz/non-tz functions for suspend / resume depending on the configuration. regards, Stan
Re: [PATCH 4/4] media: venus: add PIL support
Hi, On 05/22/2018 04:02 PM, Stanimir Varbanov wrote: > Hi Vikash, > > On 05/17/2018 02:32 PM, Vikash Garodia wrote: >> This adds support to load the video firmware >> and bring ARM9 out of reset. This is useful >> for platforms which does not have trustzone >> to reset the ARM9. >> >> Signed-off-by: Vikash Garodia <vgaro...@codeaurora.org> >> --- >> .../devicetree/bindings/media/qcom,venus.txt | 8 +- >> drivers/media/platform/qcom/venus/core.c | 67 +++-- >> drivers/media/platform/qcom/venus/core.h | 6 + >> drivers/media/platform/qcom/venus/firmware.c | 163 >> + >> drivers/media/platform/qcom/venus/firmware.h | 10 +- >> 5 files changed, 217 insertions(+), 37 deletions(-) >> >> >> -int venus_shutdown(struct device *dev) >> +int venus_boot_noTZ(struct venus_core *core, phys_addr_t mem_phys, >> +size_t mem_size) >> { >> -return qcom_scm_pas_shutdown(VENUS_PAS_ID); >> +struct iommu_domain *iommu; >> +struct device *dev; >> +int ret; >> + >> +if (!core->fw.dev) >> +return -EPROBE_DEFER; >> + >> +dev = core->fw.dev; >> + >> +iommu = iommu_domain_alloc(_bus_type); >> +if (!iommu) { >> +dev_err(dev, "Failed to allocate iommu domain\n"); >> +return -ENOMEM; >> +} >> + >> +iommu->geometry.aperture_start = 0x0; >> +iommu->geometry.aperture_end = VENUS_FW_MEM_SIZE; > > The same comment for geometry params as for venus_probe is valid here. Infact aperture_end will be overwritten by arm-smmu driver in the next call to iommu_attach_device(), and by chance geometry.force_aperture will become true. I wonder is that geometry params are supposed to be used by drivers or by iommu drivers? > >> + >> +ret = iommu_attach_device(iommu, dev); >> +if (ret) { >> +dev_err(dev, "could not attach device\n"); >> +goto err_attach; >> +} >> + >> +ret = iommu_map(iommu, core->fw.iova, mem_phys, mem_size, >> +IOMMU_READ|IOMMU_WRITE|IOMMU_PRIV); > > iova is not initialized and is zero, maybe we don't need that variable > in the venus_firmware structure? > >> +if (ret) { >> +dev_err(dev, "could not map video firmware region\n"); >> +goto err_map; >> +} >> +core->fw.iommu_domain = iommu; >> +venus_reset_hw(core); >> + >> +return 0; >> + >> +err_map: >> +iommu_detach_device(iommu, dev); >> +err_attach: >> +iommu_domain_free(iommu); >> +return ret; >> } >> + -- regards, Stan
Re: [PATCH 3/4] venus: add check to make scm calls
Hi Vikash, On 05/17/2018 02:32 PM, Vikash Garodia wrote: > In order to invoke scm calls, ensure that the platform > has the required support to invoke the scm calls in > secure world. This code is in preparation to add PIL > functionality in venus driver. > > Signed-off-by: Vikash Garodia> --- > drivers/media/platform/qcom/venus/hfi_venus.c | 26 +++--- > 1 file changed, 19 insertions(+), 7 deletions(-) > > diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c > b/drivers/media/platform/qcom/venus/hfi_venus.c > index f61d34b..9bcce94 100644 > --- a/drivers/media/platform/qcom/venus/hfi_venus.c > +++ b/drivers/media/platform/qcom/venus/hfi_venus.c > @@ -27,6 +27,7 @@ > #include "hfi_msgs.h" > #include "hfi_venus.h" > #include "hfi_venus_io.h" > +#include "firmware.h" > > #define HFI_MASK_QHDR_TX_TYPE0xff00 > #define HFI_MASK_QHDR_RX_TYPE0x00ff > @@ -570,13 +571,19 @@ static int venus_halt_axi(struct venus_hfi_device *hdev) > static int venus_power_off(struct venus_hfi_device *hdev) > { > int ret; > + void __iomem *reg_base; > > if (!hdev->power_enabled) > return 0; > > - ret = qcom_scm_set_remote_state(TZBSP_VIDEO_STATE_SUSPEND, 0); > - if (ret) > - return ret; > + if (qcom_scm_is_available()) { > + ret = qcom_scm_set_remote_state(TZBSP_VIDEO_STATE_SUSPEND, 0); I think it will be clearer if we abstract qcom_scm_set_remote_state to something like venus_set_state(SUSPEND|RESUME) in firmware.c and export the functions to be used here. -- regards, Stan
Re: [PATCH 4/4] media: venus: add PIL support
Hi Vikash, On 05/17/2018 02:32 PM, Vikash Garodia wrote: > This adds support to load the video firmware > and bring ARM9 out of reset. This is useful > for platforms which does not have trustzone > to reset the ARM9. > > Signed-off-by: Vikash Garodia> --- > .../devicetree/bindings/media/qcom,venus.txt | 8 +- > drivers/media/platform/qcom/venus/core.c | 67 +++-- > drivers/media/platform/qcom/venus/core.h | 6 + > drivers/media/platform/qcom/venus/firmware.c | 163 > + > drivers/media/platform/qcom/venus/firmware.h | 10 +- > 5 files changed, 217 insertions(+), 37 deletions(-) > > diff --git a/Documentation/devicetree/bindings/media/qcom,venus.txt > b/Documentation/devicetree/bindings/media/qcom,venus.txt > index 00d0d1b..0ff0f2d 100644 > --- a/Documentation/devicetree/bindings/media/qcom,venus.txt > +++ b/Documentation/devicetree/bindings/media/qcom,venus.txt for this change in DT binding you have to cc devicetree ML. And probably it could be separate patch. > @@ -53,7 +53,7 @@ > > * Subnodes > The Venus video-codec node must contain two subnodes representing > -video-decoder and video-encoder. > +video-decoder and video-encoder, one optional firmware subnode. > > Every of video-encoder or video-decoder subnode should have: > > @@ -79,6 +79,8 @@ Every of video-encoder or video-decoder subnode should have: > power domain which is responsible for collapsing > and restoring power to the subcore. > > +The firmware sub node must contain the iommus specifiers for ARM9. > + > * An Example > video-codec@1d0 { > compatible = "qcom,msm8916-venus"; > @@ -105,4 +107,8 @@ Every of video-encoder or video-decoder subnode should > have: > clock-names = "core"; > power-domains = < VENUS_CORE1_GDSC>; > }; > + firmware { venus-firmware > + compatible = "qcom,venus-pil-no-tz"; this should be following the other subnodes compatible names: compatible = "venus-firmware"; > + iommus = <_smmu 0x10b2 0x0>; > + } > }; > diff --git a/drivers/media/platform/qcom/venus/core.c > b/drivers/media/platform/qcom/venus/core.c > index 1308488..16910558 100644 > --- a/drivers/media/platform/qcom/venus/core.c > +++ b/drivers/media/platform/qcom/venus/core.c > @@ -22,6 +22,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -30,6 +31,7 @@ > #include "vdec.h" > #include "venc.h" > #include "firmware.h" > +#include "hfi_venus.h" > > static void venus_event_notify(struct venus_core *core, u32 event) > { > @@ -76,7 +78,7 @@ static void venus_sys_error_handler(struct work_struct > *work) > hfi_core_deinit(core, true); > hfi_destroy(core); > mutex_lock(>lock); > - venus_shutdown(core->dev); > + venus_shutdown(core); > > pm_runtime_put_sync(core->dev); > > @@ -84,7 +86,7 @@ static void venus_sys_error_handler(struct work_struct > *work) > > pm_runtime_get_sync(core->dev); > > - ret |= venus_boot(core->dev, core->res->fwname); > + ret |= venus_boot(core); > > ret |= hfi_core_resume(core, true); > > @@ -179,6 +181,20 @@ static u32 to_v4l2_codec_type(u32 codec) > } > } > > +static int store_firmware_dev(struct device *dev, void *data) > +{ > + struct venus_core *core; > + > + core = (struct venus_core *)data; > + if (!core) > + return -EINVAL; > + > + if (of_device_is_compatible(dev->of_node, "qcom,venus-pil-no-tz")) > + core->fw.dev = dev; > + > + return 0; > +} > + > static int venus_enumerate_codecs(struct venus_core *core, u32 type) > { > const struct hfi_inst_ops dummy_ops = {}; > @@ -229,6 +245,7 @@ static int venus_probe(struct platform_device *pdev) > struct device *dev = >dev; > struct venus_core *core; > struct resource *r; > + struct iommu_domain *iommu_domain; > int ret; > > core = devm_kzalloc(dev, sizeof(*core), GFP_KERNEL); > @@ -279,7 +296,14 @@ static int venus_probe(struct platform_device *pdev) > if (ret < 0) > goto err_runtime_disable; > > - ret = venus_boot(dev, core->res->fwname); > + ret = of_platform_populate(dev->of_node, NULL, NULL, dev); > + if (ret) > + goto err_runtime_disable; > + > + /* Attempt to register child devices */ This comment is wrong, the child devices are created by of_platform_populate above. > + ret = device_for_each_child(dev, core, store_firmware_dev); Why we need these complex gymnastics to get struct device pointer when that could be done in venus_firmware .probe method? I think the answer is because you want to avoid having venus-firmware.ko (because you have to have separate struct device for iommu SID). In that case it would
Re: [PATCH v2 04/29] venus: hfi_cmds: add set_properties for 4xx version
Hi Tomasz, On 05/18/2018 05:16 PM, Tomasz Figa wrote: > On Tue, May 15, 2018 at 5:13 PM Stanimir Varbanov < > stanimir.varba...@linaro.org> wrote: > >> Adds set_properties method to handle newer 4xx properties and >> fall-back to 3xx for the rest. > >> Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> >> --- >> drivers/media/platform/qcom/venus/hfi_cmds.c | 64 > +++- >> 1 file changed, 63 insertions(+), 1 deletion(-) > >> diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.c > b/drivers/media/platform/qcom/venus/hfi_cmds.c >> index 1cfeb7743041..6bd287154796 100644 >> --- a/drivers/media/platform/qcom/venus/hfi_cmds.c >> +++ b/drivers/media/platform/qcom/venus/hfi_cmds.c > > [snip] > >> + case HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE: >> + /* not implemented on Venus 4xx */ > > Shouldn't return -EINVAL here, similar to what > pkt_session_set_property_1x() does for unknown property? Probably the right error code should be ENOTSUPP, but I kind of following the rule to silently not return the error to simplify the callers of set_property (otherwise I have to have a version conditional code in the callers). > >> + break; >> + default: >> + ret = pkt_session_set_property_3xx(pkt, cookie, ptype, > pdata); >> + break; > > nit: How about simply return pkt_session_set_property_3xx(pkt, cookie, > ptype, pdata); and removing the |ret| variable completely, since the return > below the switch can just return 0 all the time? OK, I will do that way. > >> + } >> + >> + return ret; >> +} >> + >> int pkt_session_get_property(struct hfi_session_get_property_pkt *pkt, >> void *cookie, u32 ptype) >> { >> @@ -1181,7 +1240,10 @@ int pkt_session_set_property(struct > hfi_session_set_property_pkt *pkt, >> if (hfi_ver == HFI_VERSION_1XX) >> return pkt_session_set_property_1x(pkt, cookie, ptype, > pdata); > >> - return pkt_session_set_property_3xx(pkt, cookie, ptype, pdata); >> + if (hfi_ver == HFI_VERSION_3XX) >> + return pkt_session_set_property_3xx(pkt, cookie, ptype, > pdata); >> + >> + return pkt_session_set_property_4xx(pkt, cookie, ptype, pdata); > > nit: Since we're adding third variant, I'd consider using function pointers > here, but no strong opinion. Let's keep that for future improvements. -- regards, Stan
Re: [PATCH v2 03/29] venus: hfi: update sequence event to handle more properties
Hi Tomasz, On 05/18/2018 04:53 PM, Tomasz Figa wrote: > On Tue, May 15, 2018 at 5:14 PM Stanimir Varbanov < > stanimir.varba...@linaro.org> wrote: > >> HFI version 4xx can pass more properties in the sequence change >> event, extend the event structure with them. > >> Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> >> --- >> drivers/media/platform/qcom/venus/hfi.h | 9 ++ >> drivers/media/platform/qcom/venus/hfi_msgs.c | 46 > >> 2 files changed, 55 insertions(+) > >> diff --git a/drivers/media/platform/qcom/venus/hfi.h > b/drivers/media/platform/qcom/venus/hfi.h >> index 5466b7d60dd0..21376d93170f 100644 >> --- a/drivers/media/platform/qcom/venus/hfi.h >> +++ b/drivers/media/platform/qcom/venus/hfi.h >> @@ -74,6 +74,15 @@ struct hfi_event_data { >> u32 tag; >> u32 profile; >> u32 level; > > nit; Could we add a comment saying that it showed in 4xx? Sure, I can add a comment. > > [snip] > >> + case HFI_PROPERTY_CONFIG_VDEC_ENTROPY: >> + data_ptr += sizeof(u32); >> + entropy_mode = *(u32 *)data_ptr; >> + event.entropy_mode = entropy_mode; > > Is the |entropy_mode| local variable necessary? Isn't GCC smart enough ;) Sure, I can drop entropy_mode local variable. -- regards, Stan
Re: [PATCH v2 02/29] venus: hfi: preparation to support venus 4xx
Hi Tomasz, Thanks for the comments! On 05/18/2018 12:44 PM, Tomasz Figa wrote: > Hi Stanimir, > > On Tue, May 15, 2018 at 5:14 PM Stanimir Varbanov < > stanimir.varba...@linaro.org> wrote: > >> This covers the differences between 1xx,3xx and 4xx. > >> Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> >> --- >>drivers/media/platform/qcom/venus/core.h | 4 ++ >>drivers/media/platform/qcom/venus/helpers.c | 37 +++ >>drivers/media/platform/qcom/venus/hfi_helper.h | 84 > ++-- >>drivers/media/platform/qcom/venus/hfi_venus_io.h | 24 +++ >>drivers/media/platform/qcom/venus/vdec.c | 5 +- >>drivers/media/platform/qcom/venus/venc.c | 5 +- >>6 files changed, 137 insertions(+), 22 deletions(-) > > Please see my comments inline. > > [snip] > >> @@ -257,12 +273,11 @@ static int load_scale_clocks(struct venus_core > *core) > >>set_freq: > >> - if (core->res->hfi_version == HFI_VERSION_3XX) { >> - ret = clk_set_rate(clk, freq); >> + ret = clk_set_rate(clk, freq); >> + >> + if (IS_V3(core) || IS_V4(core)) { >> ret |= clk_set_rate(core->core0_clk, freq); >> ret |= clk_set_rate(core->core1_clk, freq); >> - } else { >> - ret = clk_set_rate(clk, freq); >> } > > nit: The clock API defines NULL clock as a special no-op value and so > clk_set_rate(NULL, ...) would return 0 instantly. Maybe it would just make > sense to have core0_clk and core1_clk set to NULL for V1 and remove the > condition here? OK, we could avoid the condition but I'll add a comment that those clocks exist from v3 onwards. > >> if (ret) { >> diff --git a/drivers/media/platform/qcom/venus/hfi_helper.h > b/drivers/media/platform/qcom/venus/hfi_helper.h >> index 55d8eb21403a..1bc5aab1ce6b 100644 >> --- a/drivers/media/platform/qcom/venus/hfi_helper.h >> +++ b/drivers/media/platform/qcom/venus/hfi_helper.h >> @@ -121,6 +121,7 @@ >>#define HFI_EXTRADATA_METADATA_FILLER 0x7fe2 > >>#define HFI_INDEX_EXTRADATA_INPUT_CROP 0x070e >> +#define HFI_INDEX_EXTRADATA_OUTPUT_CROP0x070f > > nit: Would it make sense to suffix this _4XX, so that reader could know > that it was introduced in this version? Similarly for other newly added > definitions. I personally don't like the version suffix on defines. Also seems this is not used in the code, so I'll drop it for now. > >>#define HFI_INDEX_EXTRADATA_DIGITAL_ZOOM 0x0710 >>#define HFI_INDEX_EXTRADATA_ASPECT_RATIO 0x7f13 > >> @@ -376,13 +377,18 @@ >>#define HFI_BUFFER_OUTPUT2 0x3 >>#define HFI_BUFFER_INTERNAL_PERSIST0x4 >>#define HFI_BUFFER_INTERNAL_PERSIST_1 0x5 >> -#define HFI_BUFFER_INTERNAL_SCRATCH0x101 >> -#define HFI_BUFFER_EXTRADATA_INPUT 0x102 >> -#define HFI_BUFFER_EXTRADATA_OUTPUT0x103 >> -#define HFI_BUFFER_EXTRADATA_OUTPUT2 0x104 >> -#define HFI_BUFFER_INTERNAL_SCRATCH_1 0x105 >> -#define HFI_BUFFER_INTERNAL_SCRATCH_2 0x106 >> - >> +#define HFI_BUFFER_INTERNAL_SCRATCH(ver) \ >> + (((ver) == HFI_VERSION_4XX) ? 0x6 : 0x101) >> +#define HFI_BUFFER_INTERNAL_SCRATCH_1(ver) \ >> + (((ver) == HFI_VERSION_4XX) ? 0x7 : 0x105) >> +#define HFI_BUFFER_INTERNAL_SCRATCH_2(ver) \ >> + (((ver) == HFI_VERSION_4XX) ? 0x8 : 0x106) >> +#define HFI_BUFFER_EXTRADATA_INPUT(ver)\ >> + (((ver) == HFI_VERSION_4XX) ? 0xc : 0x102) >> +#define HFI_BUFFER_EXTRADATA_OUTPUT(ver) \ >> + (((ver) == HFI_VERSION_4XX) ? 0xa : 0x103) >> +#define HFI_BUFFER_EXTRADATA_OUTPUT2(ver) \ >> + (((ver) == HFI_VERSION_4XX) ? 0xb : 0x104) > > nit: Does it make sense to add an argument, rather than simply defining > separate HFI_BUFFER_INTERNAL_SCRATCH_1XX and > HFI_BUFFER_INTERNAL_SCRATCH_4XX? In my subjective opinion, the argument I'd like to keep the name of the define version agnostic. > just makes it harder to read, as it's not clear how it is used inside the > macro from reading just the call to it. Also it would get messy when adding > further variants in future. > > [snip] > >> +/* HFI 4XX reorder the fields, use these macros */ >> +#define HFI_BUFREQ_HOLD_COUNT(bufreq, ver)
Re: [PATCH v2 08/29] venus: hfi_venus: fix suspend function for venus 3xx versions
Hi Tomasz, On 05/18/2018 06:14 PM, Tomasz Figa wrote: > On Tue, May 15, 2018 at 5:11 PM Stanimir Varbanov < > stanimir.varba...@linaro.org> wrote: > >> This fixes the suspend function for Venus 3xx versions by >> add a check for WFI (wait for interrupt) bit. This bit >> is on when the ARM9 is idle and entered in low power mode. > >> Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> >> --- >> drivers/media/platform/qcom/venus/hfi_venus.c| 59 > >> drivers/media/platform/qcom/venus/hfi_venus_io.h | 1 + >> 2 files changed, 41 insertions(+), 19 deletions(-) > >> diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c > b/drivers/media/platform/qcom/venus/hfi_venus.c >> index 53546174aab8..aac351f699a0 100644 >> --- a/drivers/media/platform/qcom/venus/hfi_venus.c >> +++ b/drivers/media/platform/qcom/venus/hfi_venus.c >> @@ -1447,7 +1447,7 @@ static int venus_suspend_3xx(struct venus_core > *core) >> { >> struct venus_hfi_device *hdev = to_hfi_priv(core); >> struct device *dev = core->dev; >> - u32 ctrl_status, wfi_status; >> + u32 ctrl_status, cpu_status; >> int ret; >> int cnt = 100; > >> @@ -1463,29 +1463,50 @@ static int venus_suspend_3xx(struct venus_core > *core) >> return -EINVAL; >> } > >> - ctrl_status = venus_readl(hdev, CPU_CS_SCIACMDARG0); >> - if (!(ctrl_status & CPU_CS_SCIACMDARG0_PC_READY)) { >> - wfi_status = venus_readl(hdev, WRAPPER_CPU_STATUS); >> + /* >> +* Power collapse sequence for Venus 3xx and 4xx versions: >> +* 1. Check for ARM9 and video core to be idle by checking WFI bit >> +*(bit 0) in CPU status register and by checking Idle (bit > 30) in >> +*Control status register for video core. >> +* 2. Send a command to prepare for power collapse. >> +* 3. Check for WFI and PC_READY bits. >> +*/ >> + >> + while (--cnt) { >> + cpu_status = venus_readl(hdev, WRAPPER_CPU_STATUS); >> ctrl_status = venus_readl(hdev, CPU_CS_SCIACMDARG0); > >> - ret = venus_prepare_power_collapse(hdev, false); >> - if (ret) { >> - dev_err(dev, "prepare for power collapse fail > (%d)\n", >> - ret); >> - return ret; >> - } >> + if (cpu_status & WRAPPER_CPU_STATUS_WFI && >> + ctrl_status & CPU_CS_SCIACMDARG0_INIT_IDLE_MSG_MASK) >> + break; > >> - cnt = 100; >> - while (cnt--) { >> - wfi_status = venus_readl(hdev, > WRAPPER_CPU_STATUS); >> - ctrl_status = venus_readl(hdev, > CPU_CS_SCIACMDARG0); >> - if (ctrl_status & CPU_CS_SCIACMDARG0_PC_READY && >> - wfi_status & BIT(0)) >> - break; >> - usleep_range(1000, 1500); >> - } >> + usleep_range(1000, 1500); >> } > > To avoid opencoding the polling, I'd suggest doing a readx_poll_timeout() > trick: I like the idea, will try to rework that and use readx_poll_timeout. -- regards, Stan
Re: [PATCH v2 07/29] venus: hfi_venus: add halt AXI support for Venus 4xx
Hi Tomasz, On 05/18/2018 05:23 PM, Tomasz Figa wrote: > On Tue, May 15, 2018 at 5:12 PM Stanimir Varbanov < > stanimir.varba...@linaro.org> wrote: > >> Add AXI halt support for version 4xx by using venus wrapper >> registers. > >> Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> >> --- >> drivers/media/platform/qcom/venus/hfi_venus.c | 17 + >> 1 file changed, 17 insertions(+) > >> diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c > b/drivers/media/platform/qcom/venus/hfi_venus.c >> index 734ce11b0ed0..53546174aab8 100644 >> --- a/drivers/media/platform/qcom/venus/hfi_venus.c >> +++ b/drivers/media/platform/qcom/venus/hfi_venus.c >> @@ -532,6 +532,23 @@ static int venus_halt_axi(struct venus_hfi_device > *hdev) >> u32 val; >> int ret; > >> + if (hdev->core->res->hfi_version == HFI_VERSION_4XX) { >> + val = venus_readl(hdev, WRAPPER_CPU_AXI_HALT); >> + val |= BIT(16); > > Can we have the bit defined? > >> + venus_writel(hdev, WRAPPER_CPU_AXI_HALT, val); >> + >> + ret = readl_poll_timeout(base + > WRAPPER_CPU_AXI_HALT_STATUS, >> +val, val & BIT(24), > > Ditto. Sure will add defines. -- regards, Stan
[PATCH v3 27/29] venus: implementing multi-stream support
This is implementing multi-stream decoder support. The multi-stream will be used to enable/disable the primary/secondary decoder outputs. Depending on formats on both decoder outputs we could implement downscale, dithering and supporting UBWC (universal bandwidth compression) formats. The UBWC compressed raw format is used to optimize interconnect bandwidth for bigger resolutions like 4K and hence we will get some power-saving benefits as well. Both decoder outputs are distinguished by buffer_type field in the HFI packets. For example HFI_BUFFER_OUTPUT is the buffer type for primary decoder output and HFI_BUFFER_OUTPUT2 is for secondary decoder output. Starting from Venus 4xx the DPB buffers format must be UBWC, so the multi-stream becomes mandatory for this Venus version. That means that we need to allocate internally in the driver a set of DPB buffers (with UBWC NV12 format) and give them to the firmware. The other decoder output (we called it OPB) format will be NV12 linear format and with the same resolution (or smaller in case the user wants to downscale). Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- Hi Hans, I have updated patch description a bit. Is it now clearer? If you have some particular questions I could try to answer and extend the description. Also, as Tomasz Figa started to review the patchset I'll postpone patchset v3 a bit. drivers/media/platform/qcom/venus/core.h| 2 + drivers/media/platform/qcom/venus/helpers.c | 204 +++- drivers/media/platform/qcom/venus/helpers.h | 6 + drivers/media/platform/qcom/venus/vdec.c| 93 - drivers/media/platform/qcom/venus/venc.c| 1 + 5 files changed, 302 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 1cac8dc79cd1..afa4e49e0e06 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -210,6 +210,7 @@ struct venus_buffer { * @list: used for attach an instance to the core * @lock: instance lock * @core: a reference to the core struct + * @dpbbufs: a list of decoded picture buffers * @internalbufs: a list of internal bufferes * @registeredbufs:a list of registered capture bufferes * @delayed_processa list of delayed buffers @@ -259,6 +260,7 @@ struct venus_inst { struct list_head list; struct mutex lock; struct venus_core *core; + struct list_head dpbbufs; struct list_head internalbufs; struct list_head registeredbufs; struct list_head delayed_process; diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index ed569705ecac..87dcf9973e6f 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -85,6 +85,112 @@ bool venus_helper_check_codec(struct venus_inst *inst, u32 v4l2_pixfmt) } EXPORT_SYMBOL_GPL(venus_helper_check_codec); +static int venus_helper_queue_dpb_bufs(struct venus_inst *inst) +{ + struct intbuf *buf; + int ret = 0; + + if (list_empty(>dpbbufs)) + return 0; + + list_for_each_entry(buf, >dpbbufs, list) { + struct hfi_frame_data fdata; + + memset(, 0, sizeof(fdata)); + fdata.alloc_len = buf->size; + fdata.device_addr = buf->da; + fdata.buffer_type = buf->type; + + ret = hfi_session_process_buf(inst, ); + if (ret) + goto fail; + } + +fail: + return ret; +} + +int venus_helper_free_dpb_bufs(struct venus_inst *inst) +{ + struct intbuf *buf, *n; + + if (list_empty(>dpbbufs)) + return 0; + + list_for_each_entry_safe(buf, n, >dpbbufs, list) { + list_del_init(>list); + dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da, + buf->attrs); + kfree(buf); + } + + INIT_LIST_HEAD(>dpbbufs); + + return 0; +} +EXPORT_SYMBOL_GPL(venus_helper_free_dpb_bufs); + +int venus_helper_alloc_dpb_bufs(struct venus_inst *inst) +{ + struct venus_core *core = inst->core; + struct device *dev = core->dev; + enum hfi_version ver = core->res->hfi_version; + struct hfi_buffer_requirements bufreq; + u32 buftype = inst->dpb_buftype; + unsigned int dpb_size = 0; + struct intbuf *buf; + unsigned int i; + u32 count; + int ret; + + /* no need to allocate dpb buffers */ + if (!inst->dpb_fmt) + return 0; + + if (inst->dpb_buftype == HFI_BUFFER_OUTPUT) + dpb_size = inst->output_buf_size; + else if (inst->dpb_buftype == HFI_BUFFER_OUTPUT2) + dpb_size = inst->o
Re: [PATCH 01/28] venus: hfi_msgs: correct pointer increment
Hi Tomasz, Thanks for the review! On 05/18/2018 11:33 AM, Tomasz Figa wrote: > Hi Stanimir, > > Thanks for the series. I'll be gradually reviewing subsequent patches. Stay > tuned. :) > Please consider that there is a v2 of this patchset. :) > > Reviewed-by: Tomasz Figa> Thanks! -- regards, Stan
Re: [PATCH v2 27/29] venus: implementing multi-stream support
Hi Hans, On 05/15/2018 11:17 AM, Hans Verkuil wrote: > Hi Stanimir, > > On 05/15/18 09:58, Stanimir Varbanov wrote: >> This is implementing a multi-stream decoder support. The multi >> stream gives an option to use the secondary decoder output >> with different raw format (or the same in case of crop). > > You told me that multi-stream support is currently internal only. > > It would be good if you could elaborate a bit about that in this > commit log and (I think) also add some comments in the code that > reflect this. > > It's also not clear to me how and why this is used in the driver > if this is just internal. Does it enable a feature you would > otherwise not be able to use? > > I have no complaints about the code, I would just like to see a > bit more background information in the source and commit log. Thanks for the fast comments! Sure I will try to document multi-stream support in the patch description and in the code if it makes sense. -- regards, Stan
[PATCH v2 00/29] Venus updates
Hello, Here is v2 with following comments addressed: * reworked venus suspend 3xx and reuse it for 4xx. * drop 10/28 patch from v1, i.e. call of session_continue when buffer requirements are not sufficient. * fixed kbuild test robot warning in 11/28 by allocating instance variable from heap. * spelling typo in 15/28. * added Reviewed-by for DT changes. * extended 28/28 HEVC support for encoder, now the profile and level are selected properly. Comments are welcome! regards, Stan Stanimir Varbanov (29): venus: hfi_msgs: correct pointer increment venus: hfi: preparation to support venus 4xx venus: hfi: update sequence event to handle more properties venus: hfi_cmds: add set_properties for 4xx version venus: hfi: support session continue for 4xx version venus: hfi: handle buffer output2 type as well venus: hfi_venus: add halt AXI support for Venus 4xx venus: hfi_venus: fix suspend function for venus 3xx versions venus: hfi_venus: move set of default properties to core init venus: hfi_venus: add suspend functionality for Venus 4xx venus: venc,vdec: adds clocks needed for venus 4xx venus: add common capability parser venus: helpers: make a commmon function for power_enable venus: core: delete not used flag for buffer mode venus: helpers: rename a helper function and use buffer mode from caps venus: add a helper function to set dynamic buffer mode venus: add helper function to set actual buffer size venus: delete no longer used bufmode flag from instance venus: helpers: add buffer type argument to a helper venus: helpers: add a new helper to set raw format venus: helpers,vdec,venc: add helpers to set work mode and core usage venus: helpers: extend set_num_bufs helper with one more argument venus: helpers: add a helper to return opb buffer sizes venus: vdec: get required input buffers as well venus: vdec: new function for output configuration venus: move frame size calculations in common place venus: implementing multi-stream support venus: add sdm845 compatible and resource data venus: add HEVC codec support .../devicetree/bindings/media/qcom,venus.txt | 1 + drivers/media/platform/qcom/venus/Makefile | 3 +- drivers/media/platform/qcom/venus/core.c | 107 drivers/media/platform/qcom/venus/core.h | 93 ++-- drivers/media/platform/qcom/venus/helpers.c| 558 +++-- drivers/media/platform/qcom/venus/helpers.h| 23 +- drivers/media/platform/qcom/venus/hfi.c| 12 +- drivers/media/platform/qcom/venus/hfi.h| 9 + drivers/media/platform/qcom/venus/hfi_cmds.c | 64 ++- drivers/media/platform/qcom/venus/hfi_helper.h | 112 - drivers/media/platform/qcom/venus/hfi_msgs.c | 401 +++ drivers/media/platform/qcom/venus/hfi_parser.c | 291 +++ drivers/media/platform/qcom/venus/hfi_parser.h | 45 ++ drivers/media/platform/qcom/venus/hfi_venus.c | 95 +++- drivers/media/platform/qcom/venus/hfi_venus_io.h | 25 + drivers/media/platform/qcom/venus/vdec.c | 316 +++- drivers/media/platform/qcom/venus/venc.c | 211 17 files changed, 1689 insertions(+), 677 deletions(-) create mode 100644 drivers/media/platform/qcom/venus/hfi_parser.c create mode 100644 drivers/media/platform/qcom/venus/hfi_parser.h -- 2.14.1
[PATCH v2 03/29] venus: hfi: update sequence event to handle more properties
HFI version 4xx can pass more properties in the sequence change event, extend the event structure with them. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/hfi.h | 9 ++ drivers/media/platform/qcom/venus/hfi_msgs.c | 46 2 files changed, 55 insertions(+) diff --git a/drivers/media/platform/qcom/venus/hfi.h b/drivers/media/platform/qcom/venus/hfi.h index 5466b7d60dd0..21376d93170f 100644 --- a/drivers/media/platform/qcom/venus/hfi.h +++ b/drivers/media/platform/qcom/venus/hfi.h @@ -74,6 +74,15 @@ struct hfi_event_data { u32 tag; u32 profile; u32 level; + u32 bit_depth; + u32 pic_struct; + u32 colour_space; + u32 entropy_mode; + u32 buf_count; + struct { + u32 left, top; + u32 width, height; + } input_crop; }; /* define core states */ diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c index 589e1a6b36a9..5970e9b1716b 100644 --- a/drivers/media/platform/qcom/venus/hfi_msgs.c +++ b/drivers/media/platform/qcom/venus/hfi_msgs.c @@ -25,10 +25,17 @@ static void event_seq_changed(struct venus_core *core, struct venus_inst *inst, struct hfi_msg_event_notify_pkt *pkt) { + enum hfi_version ver = core->res->hfi_version; struct hfi_event_data event = {0}; int num_properties_changed; struct hfi_framesize *frame_sz; struct hfi_profile_level *profile_level; + struct hfi_bit_depth *pixel_depth; + struct hfi_pic_struct *pic_struct; + struct hfi_colour_space *colour_info; + struct hfi_buffer_requirements *bufreq; + struct hfi_extradata_input_crop *crop; + u32 entropy_mode = 0; u8 *data_ptr; u32 ptype; @@ -69,6 +76,45 @@ static void event_seq_changed(struct venus_core *core, struct venus_inst *inst, event.level = profile_level->level; data_ptr += sizeof(*profile_level); break; + case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH: + data_ptr += sizeof(u32); + pixel_depth = (struct hfi_bit_depth *)data_ptr; + event.bit_depth = pixel_depth->bit_depth; + data_ptr += sizeof(*pixel_depth); + break; + case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT: + data_ptr += sizeof(u32); + pic_struct = (struct hfi_pic_struct *)data_ptr; + event.pic_struct = pic_struct->progressive_only; + data_ptr += sizeof(*pic_struct); + break; + case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE: + data_ptr += sizeof(u32); + colour_info = (struct hfi_colour_space *)data_ptr; + event.colour_space = colour_info->colour_space; + data_ptr += sizeof(*colour_info); + break; + case HFI_PROPERTY_CONFIG_VDEC_ENTROPY: + data_ptr += sizeof(u32); + entropy_mode = *(u32 *)data_ptr; + event.entropy_mode = entropy_mode; + data_ptr += sizeof(u32); + break; + case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS: + data_ptr += sizeof(u32); + bufreq = (struct hfi_buffer_requirements *)data_ptr; + event.buf_count = HFI_BUFREQ_COUNT_MIN(bufreq, ver); + data_ptr += sizeof(*bufreq); + break; + case HFI_INDEX_EXTRADATA_INPUT_CROP: + data_ptr += sizeof(u32); + crop = (struct hfi_extradata_input_crop *)data_ptr; + event.input_crop.left = crop->left; + event.input_crop.top = crop->top; + event.input_crop.width = crop->width; + event.input_crop.height = crop->height; + data_ptr += sizeof(*crop); + break; default: break; } -- 2.14.1
[PATCH v2 02/29] venus: hfi: preparation to support venus 4xx
This covers the differences between 1xx,3xx and 4xx. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/core.h | 4 ++ drivers/media/platform/qcom/venus/helpers.c | 37 +++ drivers/media/platform/qcom/venus/hfi_helper.h | 84 ++-- drivers/media/platform/qcom/venus/hfi_venus_io.h | 24 +++ drivers/media/platform/qcom/venus/vdec.c | 5 +- drivers/media/platform/qcom/venus/venc.c | 5 +- 6 files changed, 137 insertions(+), 22 deletions(-) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 0360d295f4c8..8d3e150800c9 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -305,6 +305,10 @@ struct venus_inst { struct hfi_buffer_requirements bufreq[HFI_BUFFER_TYPE_MAX]; }; +#define IS_V1(core)((core)->res->hfi_version == HFI_VERSION_1XX) +#define IS_V3(core)((core)->res->hfi_version == HFI_VERSION_3XX) +#define IS_V4(core)((core)->res->hfi_version == HFI_VERSION_4XX) + #define ctrl_to_inst(ctrl) \ container_of((ctrl)->handler, struct venus_inst, ctrl_handler) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 0ce9559a2924..d9065cc8a7d3 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -166,21 +166,37 @@ static int intbufs_unset_buffers(struct venus_inst *inst) return ret; } -static const unsigned int intbuf_types[] = { - HFI_BUFFER_INTERNAL_SCRATCH, - HFI_BUFFER_INTERNAL_SCRATCH_1, - HFI_BUFFER_INTERNAL_SCRATCH_2, +static const unsigned int intbuf_types_1xx[] = { + HFI_BUFFER_INTERNAL_SCRATCH(HFI_VERSION_1XX), + HFI_BUFFER_INTERNAL_SCRATCH_1(HFI_VERSION_1XX), + HFI_BUFFER_INTERNAL_SCRATCH_2(HFI_VERSION_1XX), + HFI_BUFFER_INTERNAL_PERSIST, + HFI_BUFFER_INTERNAL_PERSIST_1, +}; + +static const unsigned int intbuf_types_4xx[] = { + HFI_BUFFER_INTERNAL_SCRATCH(HFI_VERSION_4XX), + HFI_BUFFER_INTERNAL_SCRATCH_1(HFI_VERSION_4XX), + HFI_BUFFER_INTERNAL_SCRATCH_2(HFI_VERSION_4XX), HFI_BUFFER_INTERNAL_PERSIST, HFI_BUFFER_INTERNAL_PERSIST_1, }; static int intbufs_alloc(struct venus_inst *inst) { - unsigned int i; + size_t arr_sz; + size_t i; int ret; - for (i = 0; i < ARRAY_SIZE(intbuf_types); i++) { - ret = intbufs_set_buffer(inst, intbuf_types[i]); + if (IS_V4(inst->core)) + arr_sz = ARRAY_SIZE(intbuf_types_4xx); + else + arr_sz = ARRAY_SIZE(intbuf_types_1xx); + + for (i = 0; i < arr_sz; i++) { + ret = intbufs_set_buffer(inst, + IS_V4(inst->core) ? intbuf_types_4xx[i] : + intbuf_types_1xx[i]); if (ret) goto error; } @@ -257,12 +273,11 @@ static int load_scale_clocks(struct venus_core *core) set_freq: - if (core->res->hfi_version == HFI_VERSION_3XX) { - ret = clk_set_rate(clk, freq); + ret = clk_set_rate(clk, freq); + + if (IS_V3(core) || IS_V4(core)) { ret |= clk_set_rate(core->core0_clk, freq); ret |= clk_set_rate(core->core1_clk, freq); - } else { - ret = clk_set_rate(clk, freq); } if (ret) { diff --git a/drivers/media/platform/qcom/venus/hfi_helper.h b/drivers/media/platform/qcom/venus/hfi_helper.h index 55d8eb21403a..1bc5aab1ce6b 100644 --- a/drivers/media/platform/qcom/venus/hfi_helper.h +++ b/drivers/media/platform/qcom/venus/hfi_helper.h @@ -121,6 +121,7 @@ #define HFI_EXTRADATA_METADATA_FILLER 0x7fe2 #define HFI_INDEX_EXTRADATA_INPUT_CROP 0x070e +#define HFI_INDEX_EXTRADATA_OUTPUT_CROP0x070f #define HFI_INDEX_EXTRADATA_DIGITAL_ZOOM 0x0710 #define HFI_INDEX_EXTRADATA_ASPECT_RATIO 0x7f13 @@ -376,13 +377,18 @@ #define HFI_BUFFER_OUTPUT2 0x3 #define HFI_BUFFER_INTERNAL_PERSIST0x4 #define HFI_BUFFER_INTERNAL_PERSIST_1 0x5 -#define HFI_BUFFER_INTERNAL_SCRATCH0x101 -#define HFI_BUFFER_EXTRADATA_INPUT 0x102 -#define HFI_BUFFER_EXTRADATA_OUTPUT0x103 -#define HFI_BUFFER_EXTRADATA_OUTPUT2 0x104 -#define HFI_BUFFER_INTERNAL_SCRATCH_1 0x105 -#define HFI_BUFFER_INTERNAL_SCRATCH_2 0x106 - +#define HFI_BUFFER_INTERNAL_SCRATCH(ver) \ + (((ver) == HFI_VERSION_4XX) ? 0x6 : 0x101) +#define HFI_BUFFER_INTERNAL_SCRATCH_1(ver) \ + (((ver) == HFI_VERSION_4XX) ? 0x7 : 0x105) +#define HFI_BUFFER_INTERNAL_SCRATCH_2(v
[PATCH v2 01/29] venus: hfi_msgs: correct pointer increment
Data pointer should be incremented by size of the structure not the size of a pointer, correct the mistake. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/hfi_msgs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c index 90c93d9603dc..589e1a6b36a9 100644 --- a/drivers/media/platform/qcom/venus/hfi_msgs.c +++ b/drivers/media/platform/qcom/venus/hfi_msgs.c @@ -60,14 +60,14 @@ static void event_seq_changed(struct venus_core *core, struct venus_inst *inst, frame_sz = (struct hfi_framesize *)data_ptr; event.width = frame_sz->width; event.height = frame_sz->height; - data_ptr += sizeof(frame_sz); + data_ptr += sizeof(*frame_sz); break; case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT: data_ptr += sizeof(u32); profile_level = (struct hfi_profile_level *)data_ptr; event.profile = profile_level->profile; event.level = profile_level->level; - data_ptr += sizeof(profile_level); + data_ptr += sizeof(*profile_level); break; default: break; -- 2.14.1
[PATCH v2 04/29] venus: hfi_cmds: add set_properties for 4xx version
Adds set_properties method to handle newer 4xx properties and fall-back to 3xx for the rest. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/hfi_cmds.c | 64 +++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.c b/drivers/media/platform/qcom/venus/hfi_cmds.c index 1cfeb7743041..6bd287154796 100644 --- a/drivers/media/platform/qcom/venus/hfi_cmds.c +++ b/drivers/media/platform/qcom/venus/hfi_cmds.c @@ -1166,6 +1166,65 @@ pkt_session_set_property_3xx(struct hfi_session_set_property_pkt *pkt, return ret; } +static int +pkt_session_set_property_4xx(struct hfi_session_set_property_pkt *pkt, +void *cookie, u32 ptype, void *pdata) +{ + void *prop_data; + int ret = 0; + + if (!pkt || !cookie || !pdata) + return -EINVAL; + + prop_data = >data[1]; + + pkt->shdr.hdr.size = sizeof(*pkt); + pkt->shdr.hdr.pkt_type = HFI_CMD_SESSION_SET_PROPERTY; + pkt->shdr.session_id = hash32_ptr(cookie); + pkt->num_properties = 1; + pkt->data[0] = ptype; + + /* +* Any session set property which is different in 3XX packetization +* should be added as a new case below. All unchanged session set +* properties will be handled in the default case. +*/ + switch (ptype) { + case HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL: { + struct hfi_buffer_count_actual *in = pdata; + struct hfi_buffer_count_actual_4xx *count = prop_data; + + count->count_actual = in->count_actual; + count->type = in->type; + count->count_min_host = in->count_actual; + pkt->shdr.hdr.size += sizeof(u32) + sizeof(*count); + break; + } + case HFI_PROPERTY_PARAM_WORK_MODE: { + struct hfi_video_work_mode *in = pdata, *wm = prop_data; + + wm->video_work_mode = in->video_work_mode; + pkt->shdr.hdr.size += sizeof(u32) + sizeof(*wm); + break; + } + case HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE: { + struct hfi_videocores_usage_type *in = pdata, *cu = prop_data; + + cu->video_core_enable_mask = in->video_core_enable_mask; + pkt->shdr.hdr.size += sizeof(u32) + sizeof(*cu); + break; + } + case HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE: + /* not implemented on Venus 4xx */ + break; + default: + ret = pkt_session_set_property_3xx(pkt, cookie, ptype, pdata); + break; + } + + return ret; +} + int pkt_session_get_property(struct hfi_session_get_property_pkt *pkt, void *cookie, u32 ptype) { @@ -1181,7 +1240,10 @@ int pkt_session_set_property(struct hfi_session_set_property_pkt *pkt, if (hfi_ver == HFI_VERSION_1XX) return pkt_session_set_property_1x(pkt, cookie, ptype, pdata); - return pkt_session_set_property_3xx(pkt, cookie, ptype, pdata); + if (hfi_ver == HFI_VERSION_3XX) + return pkt_session_set_property_3xx(pkt, cookie, ptype, pdata); + + return pkt_session_set_property_4xx(pkt, cookie, ptype, pdata); } void pkt_set_version(enum hfi_version version) -- 2.14.1
[PATCH v2 06/29] venus: hfi: handle buffer output2 type as well
This adds handling of buffers of type OUTPUT2 which is needed to support Venus 4xx version. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/hfi.c | 3 ++- drivers/media/platform/qcom/venus/hfi_msgs.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi.c b/drivers/media/platform/qcom/venus/hfi.c index cbc6fad05e47..a570fdad0de0 100644 --- a/drivers/media/platform/qcom/venus/hfi.c +++ b/drivers/media/platform/qcom/venus/hfi.c @@ -473,7 +473,8 @@ int hfi_session_process_buf(struct venus_inst *inst, struct hfi_frame_data *fd) if (fd->buffer_type == HFI_BUFFER_INPUT) return ops->session_etb(inst, fd); - else if (fd->buffer_type == HFI_BUFFER_OUTPUT) + else if (fd->buffer_type == HFI_BUFFER_OUTPUT || +fd->buffer_type == HFI_BUFFER_OUTPUT2) return ops->session_ftb(inst, fd); return -EINVAL; diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c index 5970e9b1716b..023802e62833 100644 --- a/drivers/media/platform/qcom/venus/hfi_msgs.c +++ b/drivers/media/platform/qcom/venus/hfi_msgs.c @@ -825,7 +825,8 @@ static void hfi_session_ftb_done(struct venus_core *core, error = HFI_ERR_SESSION_INVALID_PARAMETER; } - if (buffer_type != HFI_BUFFER_OUTPUT) + if (buffer_type != HFI_BUFFER_OUTPUT && + buffer_type != HFI_BUFFER_OUTPUT2) goto done; if (hfi_flags & HFI_BUFFERFLAG_EOS) -- 2.14.1
[PATCH v2 07/29] venus: hfi_venus: add halt AXI support for Venus 4xx
Add AXI halt support for version 4xx by using venus wrapper registers. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/hfi_venus.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index 734ce11b0ed0..53546174aab8 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -532,6 +532,23 @@ static int venus_halt_axi(struct venus_hfi_device *hdev) u32 val; int ret; + if (hdev->core->res->hfi_version == HFI_VERSION_4XX) { + val = venus_readl(hdev, WRAPPER_CPU_AXI_HALT); + val |= BIT(16); + venus_writel(hdev, WRAPPER_CPU_AXI_HALT, val); + + ret = readl_poll_timeout(base + WRAPPER_CPU_AXI_HALT_STATUS, +val, val & BIT(24), +POLL_INTERVAL_US, +VBIF_AXI_HALT_ACK_TIMEOUT_US); + if (ret) { + dev_err(dev, "AXI bus port halt timeout\n"); + return ret; + } + + return 0; + } + /* Halt AXI and AXI IMEM VBIF Access */ val = venus_readl(hdev, VBIF_AXI_HALT_CTRL0); val |= VBIF_AXI_HALT_CTRL0_HALT_REQ; -- 2.14.1
[PATCH v2 05/29] venus: hfi: support session continue for 4xx version
This makes possible to handle session_continue for 4xx as well. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/hfi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/venus/hfi.c b/drivers/media/platform/qcom/venus/hfi.c index bca894a00c07..cbc6fad05e47 100644 --- a/drivers/media/platform/qcom/venus/hfi.c +++ b/drivers/media/platform/qcom/venus/hfi.c @@ -312,7 +312,7 @@ int hfi_session_continue(struct venus_inst *inst) { struct venus_core *core = inst->core; - if (core->res->hfi_version != HFI_VERSION_3XX) + if (core->res->hfi_version == HFI_VERSION_1XX) return 0; return core->ops->session_continue(inst); -- 2.14.1
[PATCH v2 09/29] venus: hfi_venus: move set of default properties to core init
This moves setting of default properties (firmware debug, idle indicator and low power mode) from session init to core init. All of those properties are need to be enabled/disabled early so that they could be used before the clients are even initialized. The other reason is to set idle indicator property early before we enter into venus_suspend function where we need to check for ARM9 WFI. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/hfi_venus.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index aac351f699a0..284da69eb81b 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -1090,6 +1090,10 @@ static int venus_core_init(struct venus_core *core) if (ret) dev_warn(dev, "failed to send image version pkt to fw\n"); + ret = venus_sys_set_default_properties(hdev); + if (ret) + return ret; + return 0; } @@ -1134,10 +1138,6 @@ static int venus_session_init(struct venus_inst *inst, u32 session_type, struct hfi_session_init_pkt pkt; int ret; - ret = venus_sys_set_default_properties(hdev); - if (ret) - return ret; - ret = pkt_session_init(, inst, session_type, codec); if (ret) goto err; -- 2.14.1
[PATCH v2 08/29] venus: hfi_venus: fix suspend function for venus 3xx versions
This fixes the suspend function for Venus 3xx versions by add a check for WFI (wait for interrupt) bit. This bit is on when the ARM9 is idle and entered in low power mode. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/hfi_venus.c| 59 drivers/media/platform/qcom/venus/hfi_venus_io.h | 1 + 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index 53546174aab8..aac351f699a0 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -1447,7 +1447,7 @@ static int venus_suspend_3xx(struct venus_core *core) { struct venus_hfi_device *hdev = to_hfi_priv(core); struct device *dev = core->dev; - u32 ctrl_status, wfi_status; + u32 ctrl_status, cpu_status; int ret; int cnt = 100; @@ -1463,29 +1463,50 @@ static int venus_suspend_3xx(struct venus_core *core) return -EINVAL; } - ctrl_status = venus_readl(hdev, CPU_CS_SCIACMDARG0); - if (!(ctrl_status & CPU_CS_SCIACMDARG0_PC_READY)) { - wfi_status = venus_readl(hdev, WRAPPER_CPU_STATUS); + /* +* Power collapse sequence for Venus 3xx and 4xx versions: +* 1. Check for ARM9 and video core to be idle by checking WFI bit +*(bit 0) in CPU status register and by checking Idle (bit 30) in +*Control status register for video core. +* 2. Send a command to prepare for power collapse. +* 3. Check for WFI and PC_READY bits. +*/ + + while (--cnt) { + cpu_status = venus_readl(hdev, WRAPPER_CPU_STATUS); ctrl_status = venus_readl(hdev, CPU_CS_SCIACMDARG0); - ret = venus_prepare_power_collapse(hdev, false); - if (ret) { - dev_err(dev, "prepare for power collapse fail (%d)\n", - ret); - return ret; - } + if (cpu_status & WRAPPER_CPU_STATUS_WFI && + ctrl_status & CPU_CS_SCIACMDARG0_INIT_IDLE_MSG_MASK) + break; - cnt = 100; - while (cnt--) { - wfi_status = venus_readl(hdev, WRAPPER_CPU_STATUS); - ctrl_status = venus_readl(hdev, CPU_CS_SCIACMDARG0); - if (ctrl_status & CPU_CS_SCIACMDARG0_PC_READY && - wfi_status & BIT(0)) - break; - usleep_range(1000, 1500); - } + usleep_range(1000, 1500); } + if (!cnt) + return -ETIMEDOUT; + + ret = venus_prepare_power_collapse(hdev, false); + if (ret) { + dev_err(dev, "prepare for power collapse fail (%d)\n", ret); + return ret; + } + + cnt = 100; + while (--cnt) { + cpu_status = venus_readl(hdev, WRAPPER_CPU_STATUS); + ctrl_status = venus_readl(hdev, CPU_CS_SCIACMDARG0); + + if (cpu_status & WRAPPER_CPU_STATUS_WFI && + ctrl_status & CPU_CS_SCIACMDARG0_PC_READY) + break; + + usleep_range(1000, 1500); + } + + if (!cnt) + return -ETIMEDOUT; + mutex_lock(>lock); ret = venus_power_off(hdev); diff --git a/drivers/media/platform/qcom/venus/hfi_venus_io.h b/drivers/media/platform/qcom/venus/hfi_venus_io.h index 76f47936d0fa..12e3d33a3d82 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus_io.h +++ b/drivers/media/platform/qcom/venus/hfi_venus_io.h @@ -108,6 +108,7 @@ #define WRAPPER_CPU_CGC_DIS(WRAPPER_BASE + 0x2010) #define WRAPPER_CPU_STATUS (WRAPPER_BASE + 0x2014) +#define WRAPPER_CPU_STATUS_WFI BIT(0) #define WRAPPER_SW_RESET (WRAPPER_BASE + 0x3000) /* Venus 4xx */ -- 2.14.1
[PATCH v2 11/29] venus: venc,vdec: adds clocks needed for venus 4xx
This extends the clocks number to support suspend and resume on Venus version 4xx. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/core.h | 4 +-- drivers/media/platform/qcom/venus/vdec.c | 42 ++-- drivers/media/platform/qcom/venus/venc.c | 42 ++-- 3 files changed, 72 insertions(+), 16 deletions(-) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 8d3e150800c9..b5b9a84e9155 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -92,8 +92,8 @@ struct venus_core { void __iomem *base; int irq; struct clk *clks[VIDC_CLKS_NUM_MAX]; - struct clk *core0_clk; - struct clk *core1_clk; + struct clk *core0_clk, *core0_bus_clk; + struct clk *core1_clk, *core1_bus_clk; struct video_device *vdev_dec; struct video_device *vdev_enc; struct v4l2_device v4l2_dev; diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 261a51adeef2..c45452634e7e 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -1081,12 +1081,18 @@ static int vdec_probe(struct platform_device *pdev) if (!core) return -EPROBE_DEFER; - if (core->res->hfi_version == HFI_VERSION_3XX) { + if (IS_V3(core) || IS_V4(core)) { core->core0_clk = devm_clk_get(dev, "core"); if (IS_ERR(core->core0_clk)) return PTR_ERR(core->core0_clk); } + if (IS_V4(core)) { + core->core0_bus_clk = devm_clk_get(dev, "bus"); + if (IS_ERR(core->core0_bus_clk)) + return PTR_ERR(core->core0_bus_clk); + } + platform_set_drvdata(pdev, core); vdev = video_device_alloc(); @@ -1132,12 +1138,23 @@ static __maybe_unused int vdec_runtime_suspend(struct device *dev) { struct venus_core *core = dev_get_drvdata(dev); - if (core->res->hfi_version == HFI_VERSION_1XX) + if (IS_V1(core)) return 0; - writel(0, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); + if (IS_V3(core)) + writel(0, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); + else if (IS_V4(core)) + writel(0, core->base + WRAPPER_VCODEC0_MMCC_POWER_CONTROL); + + if (IS_V4(core)) + clk_disable_unprepare(core->core0_bus_clk); + clk_disable_unprepare(core->core0_clk); - writel(1, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); + + if (IS_V3(core)) + writel(1, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); + else if (IS_V4(core)) + writel(1, core->base + WRAPPER_VCODEC0_MMCC_POWER_CONTROL); return 0; } @@ -1147,12 +1164,23 @@ static __maybe_unused int vdec_runtime_resume(struct device *dev) struct venus_core *core = dev_get_drvdata(dev); int ret; - if (core->res->hfi_version == HFI_VERSION_1XX) + if (IS_V1(core)) return 0; - writel(0, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); + if (IS_V3(core)) + writel(0, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); + else if (IS_V4(core)) + writel(0, core->base + WRAPPER_VCODEC0_MMCC_POWER_CONTROL); + ret = clk_prepare_enable(core->core0_clk); - writel(1, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); + + if (IS_V4(core)) + ret |= clk_prepare_enable(core->core0_bus_clk); + + if (IS_V3(core)) + writel(1, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); + else if (IS_V4(core)) + writel(1, core->base + WRAPPER_VCODEC0_MMCC_POWER_CONTROL); return ret; } diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index 947001170a77..bc8c2e7a8d2c 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -1225,12 +1225,18 @@ static int venc_probe(struct platform_device *pdev) if (!core) return -EPROBE_DEFER; - if (core->res->hfi_version == HFI_VERSION_3XX) { + if (IS_V3(core) || IS_V4(core)) { core->core1_clk = devm_clk_get(dev, "core"); if (IS_ERR(core->core1_clk)) return PTR_ERR(core->core1_clk); } + if (IS_V4(core)) { + core->core1_bus_clk = devm_clk_get(dev, "bus"); + if (IS_ERR(core->core1_bus_clk)) + return PTR_ERR(core->core1_bus_clk); + } + platform_set_drvdata(pdev, core);
[PATCH v2 19/29] venus: helpers: add buffer type argument to a helper
This adds one more function argument to pass buffer type to set_output_resolution() helper function. That is a preparation to support secondary decoder output. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/helpers.c | 5 +++-- drivers/media/platform/qcom/venus/helpers.h | 3 ++- drivers/media/platform/qcom/venus/venc.c| 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 94664a3ce3e2..5512fbfdebb9 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -456,12 +456,13 @@ int venus_helper_set_input_resolution(struct venus_inst *inst, EXPORT_SYMBOL_GPL(venus_helper_set_input_resolution); int venus_helper_set_output_resolution(struct venus_inst *inst, - unsigned int width, unsigned int height) + unsigned int width, unsigned int height, + u32 buftype) { u32 ptype = HFI_PROPERTY_PARAM_FRAME_SIZE; struct hfi_framesize fs; - fs.buffer_type = HFI_BUFFER_OUTPUT; + fs.buffer_type = buftype; fs.width = width; fs.height = height; diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h index cd306bd8978f..0de9989adcdb 100644 --- a/drivers/media/platform/qcom/venus/helpers.h +++ b/drivers/media/platform/qcom/venus/helpers.h @@ -36,7 +36,8 @@ int venus_helper_get_bufreq(struct venus_inst *inst, u32 type, int venus_helper_set_input_resolution(struct venus_inst *inst, unsigned int width, unsigned int height); int venus_helper_set_output_resolution(struct venus_inst *inst, - unsigned int width, unsigned int height); + unsigned int width, unsigned int height, + u32 buftype); int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, unsigned int output_bufs); int venus_helper_set_color_format(struct venus_inst *inst, u32 fmt); diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index f87d891325ea..8970f14b3a82 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -795,7 +795,8 @@ static int venc_init_session(struct venus_inst *inst) goto deinit; ret = venus_helper_set_output_resolution(inst, inst->width, -inst->height); +inst->height, +HFI_BUFFER_OUTPUT); if (ret) goto deinit; -- 2.14.1
[PATCH v2 18/29] venus: delete no longer used bufmode flag from instance
Delete no longer used flag cap_bufs_mode_dynamic from instance structure. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/core.h | 2 -- drivers/media/platform/qcom/venus/hfi_parser.c | 6 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index c46334454cd9..255292899204 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -249,7 +249,6 @@ struct venus_buffer { * @priv: a private for HFI operations callbacks * @session_type: the type of the session (decoder or encoder) * @hprop: a union used as a holder by get property - * @cap_bufs_mode_dynamic: buffers allocation mode capability */ struct venus_inst { struct list_head list; @@ -298,7 +297,6 @@ struct venus_inst { const struct hfi_inst_ops *ops; u32 session_type; union hfi_get_property hprop; - bool cap_bufs_mode_dynamic; }; #define IS_V1(core)((core)->res->hfi_version == HFI_VERSION_1XX) diff --git a/drivers/media/platform/qcom/venus/hfi_parser.c b/drivers/media/platform/qcom/venus/hfi_parser.c index f9181d999b23..ad039a3444b8 100644 --- a/drivers/media/platform/qcom/venus/hfi_parser.c +++ b/drivers/media/platform/qcom/venus/hfi_parser.c @@ -75,13 +75,9 @@ static void parse_alloc_mode(struct venus_core *core, struct venus_inst *inst, 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; - + mode->buffer_type == HFI_BUFFER_OUTPUT2) for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain, fill_buf_mode, type, 1); - } type++; } -- 2.14.1
[PATCH v2 12/29] venus: add common capability parser
This adds common capability parser for all supported Venus versions. Having it will help to enumerate better the supported raw formars and codecs and also the capabilities for every codec like max/min width/height, framerate, bitrate and so on. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/Makefile | 3 +- drivers/media/platform/qcom/venus/core.c | 85 ++ drivers/media/platform/qcom/venus/core.h | 68 +++-- drivers/media/platform/qcom/venus/hfi.c| 5 +- drivers/media/platform/qcom/venus/hfi_helper.h | 28 +- drivers/media/platform/qcom/venus/hfi_msgs.c | 348 ++--- drivers/media/platform/qcom/venus/hfi_parser.c | 295 + drivers/media/platform/qcom/venus/hfi_parser.h | 45 drivers/media/platform/qcom/venus/vdec.c | 38 +-- drivers/media/platform/qcom/venus/venc.c | 52 ++-- 10 files changed, 530 insertions(+), 437 deletions(-) create mode 100644 drivers/media/platform/qcom/venus/hfi_parser.c create mode 100644 drivers/media/platform/qcom/venus/hfi_parser.h diff --git a/drivers/media/platform/qcom/venus/Makefile b/drivers/media/platform/qcom/venus/Makefile index bfd4edf7c83f..b44b11b03e12 100644 --- a/drivers/media/platform/qcom/venus/Makefile +++ b/drivers/media/platform/qcom/venus/Makefile @@ -2,7 +2,8 @@ # Makefile for Qualcomm Venus driver 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-enc-objs += venc.o venc_ctrls.o diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index 41eef376eb2d..381bfdd688db 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -152,6 +152,83 @@ static void venus_clks_disable(struct venus_core *core) 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(>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, _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(>lock); + kfree(inst); + + return ret; +} + static int venus_probe(struct platform_device *pdev) { struct device *dev = >dev; @@ -219,6 +296,14 @@ static int venus_probe(struct platform_device *pdev) if (ret) 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, >v4l2_dev); if (ret) goto err_core_deinit; diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index b5b9a84e9155..fe2d2b9e8af8 100644 --- a/dr
[PATCH v2 13/29] venus: helpers: make a commmon function for power_enable
Make common function which will enable power when enabling/disabling clocks and also covers Venus 3xx/4xx versions. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/helpers.c | 51 + drivers/media/platform/qcom/venus/helpers.h | 2 ++ drivers/media/platform/qcom/venus/vdec.c| 25 -- drivers/media/platform/qcom/venus/venc.c| 25 -- 4 files changed, 67 insertions(+), 36 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index d9065cc8a7d3..2b21f6ed7502 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -13,6 +13,7 @@ * */ #include +#include #include #include #include @@ -24,6 +25,7 @@ #include "core.h" #include "helpers.h" #include "hfi_helper.h" +#include "hfi_venus_io.h" struct intbuf { struct list_head list; @@ -781,3 +783,52 @@ void venus_helper_init_instance(struct venus_inst *inst) } } EXPORT_SYMBOL_GPL(venus_helper_init_instance); + +int venus_helper_power_enable(struct venus_core *core, u32 session_type, + bool enable) +{ + void __iomem *ctrl, *stat; + u32 val; + int ret; + + if (!IS_V3(core) && !IS_V4(core)) + return -EINVAL; + + if (IS_V3(core)) { + if (session_type == VIDC_SESSION_TYPE_DEC) + ctrl = core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL; + else + ctrl = core->base + WRAPPER_VENC_VCODEC_POWER_CONTROL; + if (enable) + writel(0, ctrl); + else + writel(1, ctrl); + + return 0; + } + + if (session_type == VIDC_SESSION_TYPE_DEC) { + ctrl = core->base + WRAPPER_VCODEC0_MMCC_POWER_CONTROL; + stat = core->base + WRAPPER_VCODEC0_MMCC_POWER_STATUS; + } else { + ctrl = core->base + WRAPPER_VCODEC1_MMCC_POWER_CONTROL; + stat = core->base + WRAPPER_VCODEC1_MMCC_POWER_STATUS; + } + + if (enable) { + writel(0, ctrl); + + ret = readl_poll_timeout(stat, val, val & BIT(1), 1, 100); + if (ret) + return ret; + } else { + writel(1, ctrl); + + ret = readl_poll_timeout(stat, val, !(val & BIT(1)), 1, 100); + if (ret) + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(venus_helper_power_enable); diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h index 971392be5df5..0e64aa95624a 100644 --- a/drivers/media/platform/qcom/venus/helpers.h +++ b/drivers/media/platform/qcom/venus/helpers.h @@ -43,4 +43,6 @@ int venus_helper_set_color_format(struct venus_inst *inst, u32 fmt); void venus_helper_acquire_buf_ref(struct vb2_v4l2_buffer *vbuf); void venus_helper_release_buf_ref(struct venus_inst *inst, unsigned int idx); void venus_helper_init_instance(struct venus_inst *inst); +int venus_helper_power_enable(struct venus_core *core, u32 session_type, + bool enable); #endif diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 3b38bd1241b0..2bd81de6328a 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -1123,26 +1123,21 @@ static int vdec_remove(struct platform_device *pdev) static __maybe_unused int vdec_runtime_suspend(struct device *dev) { struct venus_core *core = dev_get_drvdata(dev); + int ret; if (IS_V1(core)) return 0; - if (IS_V3(core)) - writel(0, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); - else if (IS_V4(core)) - writel(0, core->base + WRAPPER_VCODEC0_MMCC_POWER_CONTROL); + ret = venus_helper_power_enable(core, VIDC_SESSION_TYPE_DEC, true); if (IS_V4(core)) clk_disable_unprepare(core->core0_bus_clk); clk_disable_unprepare(core->core0_clk); - if (IS_V3(core)) - writel(1, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); - else if (IS_V4(core)) - writel(1, core->base + WRAPPER_VCODEC0_MMCC_POWER_CONTROL); + ret |= venus_helper_power_enable(core, VIDC_SESSION_TYPE_DEC, false); - return 0; + return ret; } static __maybe_unused int vdec_runtime_resume(struct device *dev) @@ -1153,20 +1148,14 @@ static __maybe_unused int vdec_runtime_resume(struct device *dev) if (IS_V1(core)) return 0; - if (IS_V3(core)) - writel(0, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); -
[PATCH v2 15/29] venus: helpers: rename a helper function and use buffer mode from caps
Rename is_reg_unreg_needed() to better name is_dynamic_bufmode() and use buffer mode from enumerated per codec capabilities. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/helpers.c | 21 +++-- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 2b21f6ed7502..1eda19adbf28 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -354,18 +354,19 @@ session_process_buf(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf) return 0; } -static inline int is_reg_unreg_needed(struct venus_inst *inst) +static inline int is_dynamic_bufmode(struct venus_inst *inst) { - if (inst->session_type == VIDC_SESSION_TYPE_DEC && - inst->core->res->hfi_version == HFI_VERSION_3XX) - return 0; + struct venus_core *core = inst->core; + struct venus_caps *caps; - if (inst->session_type == VIDC_SESSION_TYPE_DEC && - inst->cap_bufs_mode_dynamic && - inst->core->res->hfi_version == HFI_VERSION_1XX) + caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type); + if (!caps) return 0; - return 1; + if (caps->cap_bufs_mode_dynamic) + return 1; + + return 0; } static int session_unregister_bufs(struct venus_inst *inst) @@ -374,7 +375,7 @@ static int session_unregister_bufs(struct venus_inst *inst) struct hfi_buffer_desc bd; int ret = 0; - if (!is_reg_unreg_needed(inst)) + if (is_dynamic_bufmode(inst)) return 0; list_for_each_entry_safe(buf, n, >registeredbufs, reg_list) { @@ -394,7 +395,7 @@ static int session_register_bufs(struct venus_inst *inst) struct venus_buffer *buf; int ret = 0; - if (!is_reg_unreg_needed(inst)) + if (is_dynamic_bufmode(inst)) return 0; list_for_each_entry(buf, >registeredbufs, reg_list) { -- 2.14.1
[PATCH v2 20/29] venus: helpers: add a new helper to set raw format
The new helper will has one more argument for buffer type, that way the decoder can configure the format on it's secondary output. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/helpers.c | 52 ++--- drivers/media/platform/qcom/venus/helpers.h | 2 ++ 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 5512fbfdebb9..0d55604f7484 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -410,6 +410,20 @@ static int session_register_bufs(struct venus_inst *inst) return ret; } +static u32 to_hfi_raw_fmt(u32 v4l2_fmt) +{ + switch (v4l2_fmt) { + case V4L2_PIX_FMT_NV12: + return HFI_COLOR_FORMAT_NV12; + case V4L2_PIX_FMT_NV21: + return HFI_COLOR_FORMAT_NV21; + default: + break; + } + + return 0; +} + int venus_helper_get_bufreq(struct venus_inst *inst, u32 type, struct hfi_buffer_requirements *req) { @@ -491,35 +505,35 @@ int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, } EXPORT_SYMBOL_GPL(venus_helper_set_num_bufs); -int venus_helper_set_color_format(struct venus_inst *inst, u32 pixfmt) +int venus_helper_set_raw_format(struct venus_inst *inst, u32 hfi_format, + u32 buftype) { - struct hfi_uncompressed_format_select fmt; u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT; - int ret; + struct hfi_uncompressed_format_select fmt; + + fmt.buffer_type = buftype; + fmt.format = hfi_format; + + return hfi_session_set_property(inst, ptype, ); +} +EXPORT_SYMBOL_GPL(venus_helper_set_raw_format); + +int venus_helper_set_color_format(struct venus_inst *inst, u32 pixfmt) +{ + u32 hfi_format, buftype; if (inst->session_type == VIDC_SESSION_TYPE_DEC) - fmt.buffer_type = HFI_BUFFER_OUTPUT; + buftype = HFI_BUFFER_OUTPUT; else if (inst->session_type == VIDC_SESSION_TYPE_ENC) - fmt.buffer_type = HFI_BUFFER_INPUT; + buftype = HFI_BUFFER_INPUT; else return -EINVAL; - switch (pixfmt) { - case V4L2_PIX_FMT_NV12: - fmt.format = HFI_COLOR_FORMAT_NV12; - break; - case V4L2_PIX_FMT_NV21: - fmt.format = HFI_COLOR_FORMAT_NV21; - break; - default: + hfi_format = to_hfi_raw_fmt(pixfmt); + if (!hfi_format) return -EINVAL; - } - ret = hfi_session_set_property(inst, ptype, ); - if (ret) - return ret; - - return 0; + return venus_helper_set_raw_format(inst, hfi_format, buftype); } EXPORT_SYMBOL_GPL(venus_helper_set_color_format); diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h index 0de9989adcdb..79af7845efbd 100644 --- a/drivers/media/platform/qcom/venus/helpers.h +++ b/drivers/media/platform/qcom/venus/helpers.h @@ -40,6 +40,8 @@ int venus_helper_set_output_resolution(struct venus_inst *inst, u32 buftype); int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, unsigned int output_bufs); +int venus_helper_set_raw_format(struct venus_inst *inst, u32 hfi_format, + u32 buftype); int venus_helper_set_color_format(struct venus_inst *inst, u32 fmt); int venus_helper_set_dyn_bufmode(struct venus_inst *inst); int venus_helper_set_bufsize(struct venus_inst *inst, u32 bufsize, u32 buftype); -- 2.14.1
[PATCH v2 16/29] venus: add a helper function to set dynamic buffer mode
Adds a new helper function to set dynamic buffer mode if it is supported by current HFI version. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/helpers.c | 22 ++ drivers/media/platform/qcom/venus/helpers.h | 1 + drivers/media/platform/qcom/venus/vdec.c| 15 +++ 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 1eda19adbf28..824ad4d2d064 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -522,6 +522,28 @@ int venus_helper_set_color_format(struct venus_inst *inst, u32 pixfmt) } EXPORT_SYMBOL_GPL(venus_helper_set_color_format); +int venus_helper_set_dyn_bufmode(struct venus_inst *inst) +{ + u32 ptype = HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE; + struct hfi_buffer_alloc_mode mode; + int ret; + + if (!is_dynamic_bufmode(inst)) + return 0; + + mode.type = HFI_BUFFER_OUTPUT; + mode.mode = HFI_BUFFER_MODE_DYNAMIC; + + ret = hfi_session_set_property(inst, ptype, ); + if (ret) + return ret; + + mode.type = HFI_BUFFER_OUTPUT2; + + return hfi_session_set_property(inst, ptype, ); +} +EXPORT_SYMBOL_GPL(venus_helper_set_dyn_bufmode); + static void delayed_process_buf_func(struct work_struct *work) { struct venus_buffer *buf, *n; diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h index 0e64aa95624a..52b961ed491e 100644 --- a/drivers/media/platform/qcom/venus/helpers.h +++ b/drivers/media/platform/qcom/venus/helpers.h @@ -40,6 +40,7 @@ int venus_helper_set_output_resolution(struct venus_inst *inst, int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, unsigned int output_bufs); int venus_helper_set_color_format(struct venus_inst *inst, u32 fmt); +int venus_helper_set_dyn_bufmode(struct venus_inst *inst); void venus_helper_acquire_buf_ref(struct vb2_v4l2_buffer *vbuf); void venus_helper_release_buf_ref(struct venus_inst *inst, unsigned int idx); void venus_helper_init_instance(struct venus_inst *inst); diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 2bd81de6328a..271192273953 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -557,18 +557,9 @@ static int vdec_set_properties(struct venus_inst *inst) return ret; } - if (core->res->hfi_version == HFI_VERSION_3XX || - inst->cap_bufs_mode_dynamic) { - struct hfi_buffer_alloc_mode mode; - - ptype = HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE; - mode.type = HFI_BUFFER_OUTPUT; - mode.mode = HFI_BUFFER_MODE_DYNAMIC; - - ret = hfi_session_set_property(inst, ptype, ); - if (ret) - return ret; - } + ret = venus_helper_set_dyn_bufmode(inst); + if (ret) + return ret; if (ctr->post_loop_deb_mode) { ptype = HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER; -- 2.14.1
[PATCH v2 22/29] venus: helpers: extend set_num_bufs helper with one more argument
Extend venus_helper_set_num_bufs() helper function with one more argument to set number of output buffers for the secondary decoder output. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/helpers.c | 16 ++-- drivers/media/platform/qcom/venus/helpers.h | 3 ++- drivers/media/platform/qcom/venus/vdec.c| 2 +- drivers/media/platform/qcom/venus/venc.c| 2 +- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index adf8701a64bb..f04d16953b3a 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -513,7 +513,8 @@ int venus_helper_set_core_usage(struct venus_inst *inst, u32 usage) EXPORT_SYMBOL_GPL(venus_helper_set_core_usage); int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, - unsigned int output_bufs) + unsigned int output_bufs, + unsigned int output2_bufs) { u32 ptype = HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL; struct hfi_buffer_count_actual buf_count; @@ -529,7 +530,18 @@ int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, buf_count.type = HFI_BUFFER_OUTPUT; buf_count.count_actual = output_bufs; - return hfi_session_set_property(inst, ptype, _count); + ret = hfi_session_set_property(inst, ptype, _count); + if (ret) + return ret; + + if (output2_bufs) { + buf_count.type = HFI_BUFFER_OUTPUT2; + buf_count.count_actual = output2_bufs; + + ret = hfi_session_set_property(inst, ptype, _count); + } + + return ret; } EXPORT_SYMBOL_GPL(venus_helper_set_num_bufs); diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h index d5e727e1ecab..8ff4bd3ef958 100644 --- a/drivers/media/platform/qcom/venus/helpers.h +++ b/drivers/media/platform/qcom/venus/helpers.h @@ -41,7 +41,8 @@ int venus_helper_set_output_resolution(struct venus_inst *inst, int venus_helper_set_work_mode(struct venus_inst *inst, u32 mode); int venus_helper_set_core_usage(struct venus_inst *inst, u32 usage); int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, - unsigned int output_bufs); + unsigned int output_bufs, + unsigned int output2_bufs); int venus_helper_set_raw_format(struct venus_inst *inst, u32 hfi_format, u32 buftype); int venus_helper_set_color_format(struct venus_inst *inst, u32 fmt); diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 3c7ffebe4bad..898c5edb91f5 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -758,7 +758,7 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count) goto deinit_sess; ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs, - VB2_MAX_FRAME); + VB2_MAX_FRAME, VB2_MAX_FRAME); if (ret) goto deinit_sess; diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index 3b3299bff1cd..c9c40d1ce7c6 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -963,7 +963,7 @@ static int venc_start_streaming(struct vb2_queue *q, unsigned int count) goto deinit_sess; ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs, - inst->num_output_bufs); + inst->num_output_bufs, 0); if (ret) goto deinit_sess; -- 2.14.1
[PATCH v2 21/29] venus: helpers,vdec,venc: add helpers to set work mode and core usage
These are new properties applicable to Venus version 4xx. Add the helpers and call them from decoder and encoder drivers. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/helpers.c | 28 drivers/media/platform/qcom/venus/helpers.h | 2 ++ drivers/media/platform/qcom/venus/vdec.c| 8 drivers/media/platform/qcom/venus/venc.c| 8 4 files changed, 46 insertions(+) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 0d55604f7484..adf8701a64bb 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -484,6 +484,34 @@ int venus_helper_set_output_resolution(struct venus_inst *inst, } EXPORT_SYMBOL_GPL(venus_helper_set_output_resolution); +int venus_helper_set_work_mode(struct venus_inst *inst, u32 mode) +{ + u32 ptype = HFI_PROPERTY_PARAM_WORK_MODE; + struct hfi_video_work_mode wm; + + if (!IS_V4(inst->core)) + return 0; + + wm.video_work_mode = mode; + + return hfi_session_set_property(inst, ptype, ); +} +EXPORT_SYMBOL_GPL(venus_helper_set_work_mode); + +int venus_helper_set_core_usage(struct venus_inst *inst, u32 usage) +{ + u32 ptype = HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE; + struct hfi_videocores_usage_type cu; + + if (!IS_V4(inst->core)) + return 0; + + cu.video_core_enable_mask = usage; + + return hfi_session_set_property(inst, ptype, ); +} +EXPORT_SYMBOL_GPL(venus_helper_set_core_usage); + int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, unsigned int output_bufs) { diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h index 79af7845efbd..d5e727e1ecab 100644 --- a/drivers/media/platform/qcom/venus/helpers.h +++ b/drivers/media/platform/qcom/venus/helpers.h @@ -38,6 +38,8 @@ int venus_helper_set_input_resolution(struct venus_inst *inst, int venus_helper_set_output_resolution(struct venus_inst *inst, unsigned int width, unsigned int height, u32 buftype); +int venus_helper_set_work_mode(struct venus_inst *inst, u32 mode); +int venus_helper_set_core_usage(struct venus_inst *inst, u32 usage); int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, unsigned int output_bufs); int venus_helper_set_raw_format(struct venus_inst *inst, u32 hfi_format, diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index e8e00d0650e9..3c7ffebe4bad 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -550,6 +550,14 @@ static int vdec_set_properties(struct venus_inst *inst) u32 ptype; int ret; + ret = venus_helper_set_work_mode(inst, VIDC_WORK_MODE_2); + if (ret) + return ret; + + ret = venus_helper_set_core_usage(inst, VIDC_CORE_ID_1); + if (ret) + return ret; + if (core->res->hfi_version == HFI_VERSION_1XX) { ptype = HFI_PROPERTY_PARAM_VDEC_CONTINUE_DATA_TRANSFER; ret = hfi_session_set_property(inst, ptype, ); diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index 8970f14b3a82..3b3299bff1cd 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -643,6 +643,14 @@ static int venc_set_properties(struct venus_inst *inst) u32 ptype, rate_control, bitrate, profile = 0, level = 0; int ret; + ret = venus_helper_set_work_mode(inst, VIDC_WORK_MODE_2); + if (ret) + return ret; + + ret = venus_helper_set_core_usage(inst, VIDC_CORE_ID_2); + if (ret) + return ret; + ptype = HFI_PROPERTY_CONFIG_FRAME_RATE; frate.buffer_type = HFI_BUFFER_OUTPUT; frate.framerate = inst->fps * (1 << 16); -- 2.14.1
[PATCH v2 14/29] venus: core: delete not used flag for buffer mode
Delete not used flag for capture buffer allocation mode. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/core.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index fe2d2b9e8af8..c46334454cd9 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -249,7 +249,6 @@ struct venus_buffer { * @priv: a private for HFI operations callbacks * @session_type: the type of the session (decoder or encoder) * @hprop: a union used as a holder by get property - * @cap_bufs_mode_static: buffers allocation mode capability * @cap_bufs_mode_dynamic: buffers allocation mode capability */ struct venus_inst { @@ -299,7 +298,6 @@ struct venus_inst { const struct hfi_inst_ops *ops; u32 session_type; union hfi_get_property hprop; - bool cap_bufs_mode_static; bool cap_bufs_mode_dynamic; }; -- 2.14.1
[PATCH v2 23/29] venus: helpers: add a helper to return opb buffer sizes
Add a helper function to return current output picture buffer size. OPB sizes can vary depending on the selected decoder output(s). Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/core.h| 10 ++ drivers/media/platform/qcom/venus/helpers.c | 15 +++ drivers/media/platform/qcom/venus/helpers.h | 1 + 3 files changed, 26 insertions(+) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 255292899204..4d6c05f156c4 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -234,6 +234,11 @@ struct venus_buffer { * @num_output_bufs: holds number of output buffers * @input_buf_size holds input buffer size * @output_buf_size: holds output buffer size + * @output2_buf_size: holds secondary decoder output buffer size + * @dpb_buftype: decoded picture buffer type + * @dpb_fmt: decodec picture buffre raw format + * @opb_buftype: output picture buffer type + * @opb_fmt: output picture buffer raw format * @reconfig: a flag raised by decoder when the stream resolution changed * @reconfig_width:holds the new width * @reconfig_height: holds the new height @@ -282,6 +287,11 @@ struct venus_inst { unsigned int num_output_bufs; unsigned int input_buf_size; unsigned int output_buf_size; + unsigned int output2_buf_size; + u32 dpb_buftype; + u32 dpb_fmt; + u32 opb_buftype; + u32 opb_fmt; bool reconfig; u32 reconfig_width; u32 reconfig_height; diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index f04d16953b3a..f0a0fca60c76 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -611,6 +611,21 @@ int venus_helper_set_bufsize(struct venus_inst *inst, u32 bufsize, u32 buftype) } EXPORT_SYMBOL_GPL(venus_helper_set_bufsize); +unsigned int venus_helper_get_opb_size(struct venus_inst *inst) +{ + /* the encoder has only one output */ + if (inst->session_type == VIDC_SESSION_TYPE_ENC) + return inst->output_buf_size; + + if (inst->opb_buftype == HFI_BUFFER_OUTPUT) + return inst->output_buf_size; + else if (inst->opb_buftype == HFI_BUFFER_OUTPUT2) + return inst->output2_buf_size; + + return 0; +} +EXPORT_SYMBOL_GPL(venus_helper_get_opb_size); + static void delayed_process_buf_func(struct work_struct *work) { struct venus_buffer *buf, *n; diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h index 8ff4bd3ef958..92be45894a69 100644 --- a/drivers/media/platform/qcom/venus/helpers.h +++ b/drivers/media/platform/qcom/venus/helpers.h @@ -48,6 +48,7 @@ int venus_helper_set_raw_format(struct venus_inst *inst, u32 hfi_format, int venus_helper_set_color_format(struct venus_inst *inst, u32 fmt); int venus_helper_set_dyn_bufmode(struct venus_inst *inst); int venus_helper_set_bufsize(struct venus_inst *inst, u32 bufsize, u32 buftype); +unsigned int venus_helper_get_opb_size(struct venus_inst *inst); void venus_helper_acquire_buf_ref(struct vb2_v4l2_buffer *vbuf); void venus_helper_release_buf_ref(struct venus_inst *inst, unsigned int idx); void venus_helper_init_instance(struct venus_inst *inst); -- 2.14.1
[PATCH v2 24/29] venus: vdec: get required input buffers as well
Rework and rename vdec_cap_num_buffers() to get the number of input buffers too. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/vdec.c | 41 +++- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 898c5edb91f5..5a5e3e2fece4 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -603,19 +603,32 @@ static int vdec_init_session(struct venus_inst *inst) return ret; } -static int vdec_cap_num_buffers(struct venus_inst *inst, unsigned int *num) +static int vdec_num_buffers(struct venus_inst *inst, unsigned int *in_num, + unsigned int *out_num) { + enum hfi_version ver = inst->core->res->hfi_version; struct hfi_buffer_requirements bufreq; int ret; + *in_num = *out_num = 0; + ret = vdec_init_session(inst); if (ret) return ret; + ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, ); + if (ret) + goto deinit; + + *in_num = HFI_BUFREQ_COUNT_MIN(, ver); + ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, ); + if (ret) + goto deinit; - *num = bufreq.count_actual; + *out_num = HFI_BUFREQ_COUNT_MIN(, ver); +deinit: hfi_session_deinit(inst); return ret; @@ -626,7 +639,7 @@ static int vdec_queue_setup(struct vb2_queue *q, unsigned int sizes[], struct device *alloc_devs[]) { struct venus_inst *inst = vb2_get_drv_priv(q); - unsigned int p, num; + unsigned int p, in_num, out_num; int ret = 0; if (*num_planes) { @@ -649,35 +662,29 @@ static int vdec_queue_setup(struct vb2_queue *q, return 0; } + ret = vdec_num_buffers(inst, _num, _num); + if (ret) + return ret; + switch (q->type) { case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: *num_planes = inst->fmt_out->num_planes; sizes[0] = get_framesize_compressed(inst->out_width, inst->out_height); inst->input_buf_size = sizes[0]; + *num_buffers = max(*num_buffers, in_num); inst->num_input_bufs = *num_buffers; - - ret = vdec_cap_num_buffers(inst, ); - if (ret) - break; - - inst->num_output_bufs = num; + inst->num_output_bufs = out_num; break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: *num_planes = inst->fmt_cap->num_planes; - ret = vdec_cap_num_buffers(inst, ); - if (ret) - break; - - *num_buffers = max(*num_buffers, num); - for (p = 0; p < *num_planes; p++) sizes[p] = get_framesize_uncompressed(p, inst->width, inst->height); - - inst->num_output_bufs = *num_buffers; inst->output_buf_size = sizes[0]; + *num_buffers = max(*num_buffers, out_num); + inst->num_output_bufs = *num_buffers; break; default: ret = -EINVAL; -- 2.14.1
[PATCH v2 17/29] venus: add helper function to set actual buffer size
Add and use a helper function to set actual buffer size for particular buffer type. This is also preparation to use the second decoder output. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/helpers.c | 12 drivers/media/platform/qcom/venus/helpers.h | 1 + drivers/media/platform/qcom/venus/vdec.c| 10 ++ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 824ad4d2d064..94664a3ce3e2 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -544,6 +544,18 @@ int venus_helper_set_dyn_bufmode(struct venus_inst *inst) } EXPORT_SYMBOL_GPL(venus_helper_set_dyn_bufmode); +int venus_helper_set_bufsize(struct venus_inst *inst, u32 bufsize, u32 buftype) +{ + u32 ptype = HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL; + struct hfi_buffer_size_actual bufsz; + + bufsz.type = buftype; + bufsz.size = bufsize; + + return hfi_session_set_property(inst, ptype, ); +} +EXPORT_SYMBOL_GPL(venus_helper_set_bufsize); + static void delayed_process_buf_func(struct work_struct *work) { struct venus_buffer *buf, *n; diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h index 52b961ed491e..cd306bd8978f 100644 --- a/drivers/media/platform/qcom/venus/helpers.h +++ b/drivers/media/platform/qcom/venus/helpers.h @@ -41,6 +41,7 @@ int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, unsigned int output_bufs); int venus_helper_set_color_format(struct venus_inst *inst, u32 fmt); int venus_helper_set_dyn_bufmode(struct venus_inst *inst); +int venus_helper_set_bufsize(struct venus_inst *inst, u32 bufsize, u32 buftype); void venus_helper_acquire_buf_ref(struct vb2_v4l2_buffer *vbuf); void venus_helper_release_buf_ref(struct venus_inst *inst, unsigned int idx); void venus_helper_init_instance(struct venus_inst *inst); diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 271192273953..e8e00d0650e9 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -710,7 +710,6 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count) { struct venus_inst *inst = vb2_get_drv_priv(q); struct venus_core *core = inst->core; - u32 ptype; int ret; mutex_lock(>lock); @@ -740,13 +739,8 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count) goto deinit_sess; if (core->res->hfi_version == HFI_VERSION_3XX) { - struct hfi_buffer_size_actual buf_sz; - - ptype = HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL; - buf_sz.type = HFI_BUFFER_OUTPUT; - buf_sz.size = inst->output_buf_size; - - ret = hfi_session_set_property(inst, ptype, _sz); + ret = venus_helper_set_bufsize(inst, inst->output_buf_size, + HFI_BUFFER_OUTPUT); if (ret) goto deinit_sess; } -- 2.14.1
[PATCH v2 26/29] venus: move frame size calculations in common place
move calculations of raw and compressed in a common helper and make it identical for encoder and decoder. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/helpers.c | 98 + drivers/media/platform/qcom/venus/helpers.h | 2 + drivers/media/platform/qcom/venus/vdec.c| 54 drivers/media/platform/qcom/venus/venc.c| 56 - 4 files changed, 126 insertions(+), 84 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index f0a0fca60c76..ed569705ecac 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -455,6 +455,104 @@ int venus_helper_get_bufreq(struct venus_inst *inst, u32 type, } EXPORT_SYMBOL_GPL(venus_helper_get_bufreq); +static u32 get_framesize_raw_nv12(u32 width, u32 height) +{ + u32 y_stride, uv_stride, y_plane; + u32 y_sclines, uv_sclines, uv_plane; + u32 size; + + y_stride = ALIGN(width, 128); + uv_stride = ALIGN(width, 128); + y_sclines = ALIGN(height, 32); + uv_sclines = ALIGN(((height + 1) >> 1), 16); + + y_plane = y_stride * y_sclines; + uv_plane = uv_stride * uv_sclines + SZ_4K; + size = y_plane + uv_plane + SZ_8K; + + return ALIGN(size, SZ_4K); +} + +static u32 get_framesize_raw_nv12_ubwc(u32 width, u32 height) +{ + u32 y_meta_stride, y_meta_plane; + u32 y_stride, y_plane; + u32 uv_meta_stride, uv_meta_plane; + u32 uv_stride, uv_plane; + u32 extradata = SZ_16K; + + y_meta_stride = ALIGN(DIV_ROUND_UP(width, 32), 64); + y_meta_plane = y_meta_stride * ALIGN(DIV_ROUND_UP(height, 8), 16); + y_meta_plane = ALIGN(y_meta_plane, SZ_4K); + + y_stride = ALIGN(width, 128); + y_plane = ALIGN(y_stride * ALIGN(height, 32), SZ_4K); + + uv_meta_stride = ALIGN(DIV_ROUND_UP(width / 2, 16), 64); + uv_meta_plane = uv_meta_stride * ALIGN(DIV_ROUND_UP(height / 2, 8), 16); + uv_meta_plane = ALIGN(uv_meta_plane, SZ_4K); + + uv_stride = ALIGN(width, 128); + uv_plane = ALIGN(uv_stride * ALIGN(height / 2, 32), SZ_4K); + + return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane + +max(extradata, y_stride * 48), SZ_4K); +} + +u32 venus_helper_get_framesz_raw(u32 hfi_fmt, u32 width, u32 height) +{ + switch (hfi_fmt) { + case HFI_COLOR_FORMAT_NV12: + case HFI_COLOR_FORMAT_NV21: + return get_framesize_raw_nv12(width, height); + case HFI_COLOR_FORMAT_NV12_UBWC: + return get_framesize_raw_nv12_ubwc(width, height); + default: + return 0; + } +} +EXPORT_SYMBOL_GPL(venus_helper_get_framesz_raw); + +u32 venus_helper_get_framesz(u32 v4l2_fmt, u32 width, u32 height) +{ + u32 hfi_fmt, sz; + bool compressed; + + switch (v4l2_fmt) { + case V4L2_PIX_FMT_MPEG: + case V4L2_PIX_FMT_H264: + case V4L2_PIX_FMT_H264_NO_SC: + case V4L2_PIX_FMT_H264_MVC: + case V4L2_PIX_FMT_H263: + case V4L2_PIX_FMT_MPEG1: + case V4L2_PIX_FMT_MPEG2: + case V4L2_PIX_FMT_MPEG4: + case V4L2_PIX_FMT_XVID: + case V4L2_PIX_FMT_VC1_ANNEX_G: + case V4L2_PIX_FMT_VC1_ANNEX_L: + case V4L2_PIX_FMT_VP8: + case V4L2_PIX_FMT_VP9: + case V4L2_PIX_FMT_HEVC: + compressed = true; + break; + default: + compressed = false; + break; + } + + if (compressed) { + sz = ALIGN(height, 32) * ALIGN(width, 32) * 3 / 2 / 2; + return ALIGN(sz, SZ_4K); + } + + hfi_fmt = to_hfi_raw_fmt(v4l2_fmt); + if (!hfi_fmt) + return 0; + + return venus_helper_get_framesz_raw(hfi_fmt, width, height); +} +EXPORT_SYMBOL_GPL(venus_helper_get_framesz); + int venus_helper_set_input_resolution(struct venus_inst *inst, unsigned int width, unsigned int height) { diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h index 92be45894a69..92b167a47166 100644 --- a/drivers/media/platform/qcom/venus/helpers.h +++ b/drivers/media/platform/qcom/venus/helpers.h @@ -33,6 +33,8 @@ void venus_helper_m2m_device_run(void *priv); void venus_helper_m2m_job_abort(void *priv); int venus_helper_get_bufreq(struct venus_inst *inst, u32 type, struct hfi_buffer_requirements *req); +u32 venus_helper_get_framesz_raw(u32 hfi_fmt, u32 width, u32 height); +u32 venus_helper_get_framesz(u32 v4l2_fmt, u32 width, u32 height); int venus_helper_set_input_resolution(struct venus_inst *inst, unsigned int width, unsigned int height); int venus_helper_set_output_resolution(struct venus_inst *inst, diff --git a/drivers/media/platform/qcom/ven
[PATCH v2 25/29] venus: vdec: new function for output configuration
Make a new function vdec_output_conf() for decoder output configuration. vdec_output_conf() will set properties via HFI interface related to the output configuration, and keep vdec_set_properties() which will set properties related to decoding parameters. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/vdec.c | 35 ++-- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 5a5e3e2fece4..3a699af0ab58 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -545,6 +545,23 @@ static const struct v4l2_ioctl_ops vdec_ioctl_ops = { static int vdec_set_properties(struct venus_inst *inst) { struct vdec_controls *ctr = >controls.dec; + struct hfi_enable en = { .enable = 1 }; + u32 ptype; + int ret; + + if (ctr->post_loop_deb_mode) { + ptype = HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER; + en.enable = 1; + ret = hfi_session_set_property(inst, ptype, ); + if (ret) + return ret; + } + + return 0; +} + +static int vdec_output_conf(struct venus_inst *inst) +{ struct venus_core *core = inst->core; struct hfi_enable en = { .enable = 1 }; u32 ptype; @@ -569,14 +586,6 @@ static int vdec_set_properties(struct venus_inst *inst) if (ret) return ret; - if (ctr->post_loop_deb_mode) { - ptype = HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER; - en.enable = 1; - ret = hfi_session_set_property(inst, ptype, ); - if (ret) - return ret; - } - return 0; } @@ -724,7 +733,6 @@ static int vdec_verify_conf(struct venus_inst *inst) static int vdec_start_streaming(struct vb2_queue *q, unsigned int count) { struct venus_inst *inst = vb2_get_drv_priv(q); - struct venus_core *core = inst->core; int ret; mutex_lock(>lock); @@ -753,12 +761,9 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count) if (ret) goto deinit_sess; - if (core->res->hfi_version == HFI_VERSION_3XX) { - ret = venus_helper_set_bufsize(inst, inst->output_buf_size, - HFI_BUFFER_OUTPUT); - if (ret) - goto deinit_sess; - } + ret = vdec_output_conf(inst); + if (ret) + goto deinit_sess; ret = vdec_verify_conf(inst); if (ret) -- 2.14.1
[PATCH v2 28/29] venus: add sdm845 compatible and resource data
This adds sdm845 DT compatible string with it's resource data table. Reviewed-by: Rob Herring <r...@kernel.org> Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- .../devicetree/bindings/media/qcom,venus.txt | 1 + drivers/media/platform/qcom/venus/core.c | 22 ++ 2 files changed, 23 insertions(+) diff --git a/Documentation/devicetree/bindings/media/qcom,venus.txt b/Documentation/devicetree/bindings/media/qcom,venus.txt index 2693449daf73..00d0d1bf7647 100644 --- a/Documentation/devicetree/bindings/media/qcom,venus.txt +++ b/Documentation/devicetree/bindings/media/qcom,venus.txt @@ -6,6 +6,7 @@ Definition: Value should contain one of: - "qcom,msm8916-venus" - "qcom,msm8996-venus" + - "qcom,sdm845-venus" - reg: Usage: required Value type: diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index 381bfdd688db..bb6add9d340e 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -450,9 +450,31 @@ static const struct venus_resources msm8996_res = { .fwname = "qcom/venus-4.2/venus.mdt", }; +static const struct freq_tbl sdm845_freq_table[] = { + { 1944000, 38000 }, /* 4k UHD @ 60 */ + { 972000, 32000 }, /* 4k UHD @ 30 */ + { 489600, 2 }, /* 1080p @ 60 */ + { 244800, 1 }, /* 1080p @ 30 */ +}; + +static const struct venus_resources sdm845_res = { + .freq_tbl = sdm845_freq_table, + .freq_tbl_size = ARRAY_SIZE(sdm845_freq_table), + .clks = {"core", "iface", "bus" }, + .clks_num = 3, + .max_load = 2563200, + .hfi_version = HFI_VERSION_4XX, + .vmem_id = VIDC_RESOURCE_NONE, + .vmem_size = 0, + .vmem_addr = 0, + .dma_mask = 0xe000 - 1, + .fwname = "qcom/venus-5.2/venus.mdt", +}; + static const struct of_device_id venus_dt_match[] = { { .compatible = "qcom,msm8916-venus", .data = _res, }, { .compatible = "qcom,msm8996-venus", .data = _res, }, + { .compatible = "qcom,sdm845-venus", .data = _res, }, { } }; MODULE_DEVICE_TABLE(of, venus_dt_match); -- 2.14.1
[PATCH v2 29/29] venus: add HEVC codec support
This add HEVC codec support for venus versions 3xx and 4xx. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/core.h| 2 ++ drivers/media/platform/qcom/venus/helpers.c | 3 ++ drivers/media/platform/qcom/venus/hfi.c | 2 ++ drivers/media/platform/qcom/venus/vdec.c| 4 +++ drivers/media/platform/qcom/venus/venc.c| 49 + 5 files changed, 60 insertions(+) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 85e66e2dd672..2a956d1b9bd1 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -185,10 +185,12 @@ struct venc_controls { u32 mpeg4; u32 h264; u32 vpx; + u32 hevc; } profile; struct { u32 mpeg4; u32 h264; + u32 hevc; } level; }; diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 87dcf9973e6f..fecadba039cf 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -71,6 +71,9 @@ bool venus_helper_check_codec(struct venus_inst *inst, u32 v4l2_pixfmt) case V4L2_PIX_FMT_XVID: codec = HFI_VIDEO_CODEC_DIVX; break; + case V4L2_PIX_FMT_HEVC: + codec = HFI_VIDEO_CODEC_HEVC; + break; default: return false; } diff --git a/drivers/media/platform/qcom/venus/hfi.c b/drivers/media/platform/qcom/venus/hfi.c index 94ca27b0bb99..24207829982f 100644 --- a/drivers/media/platform/qcom/venus/hfi.c +++ b/drivers/media/platform/qcom/venus/hfi.c @@ -49,6 +49,8 @@ static u32 to_codec_type(u32 pixfmt) return HFI_VIDEO_CODEC_VP9; case V4L2_PIX_FMT_XVID: return HFI_VIDEO_CODEC_DIVX; + case V4L2_PIX_FMT_HEVC: + return HFI_VIDEO_CODEC_HEVC; default: return 0; } diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index d2d082009686..d2ffd9bd44de 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -77,6 +77,10 @@ static const struct venus_format vdec_formats[] = { .pixfmt = V4L2_PIX_FMT_XVID, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + }, { + .pixfmt = V4L2_PIX_FMT_HEVC, + .num_planes = 1, + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, }, }; diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index a703bce78abc..50a04cb1cc22 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -59,6 +59,10 @@ static const struct venus_format venc_formats[] = { .pixfmt = V4L2_PIX_FMT_VP8, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + }, { + .pixfmt = V4L2_PIX_FMT_HEVC, + .num_planes = 1, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, }, }; @@ -220,6 +224,46 @@ static int venc_v4l2_to_hfi(int id, int value) case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY: return HFI_H264_DB_MODE_SKIP_SLICE_BOUNDARY; } + case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE: + switch (value) { + case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN: + default: + return HFI_HEVC_PROFILE_MAIN; + case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE: + return HFI_HEVC_PROFILE_MAIN_STILL_PIC; + case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10: + return HFI_HEVC_PROFILE_MAIN10; + } + case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL: + switch (value) { + case V4L2_MPEG_VIDEO_HEVC_LEVEL_1: + default: + return HFI_HEVC_LEVEL_1; + case V4L2_MPEG_VIDEO_HEVC_LEVEL_2: + return HFI_HEVC_LEVEL_2; + case V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1: + return HFI_HEVC_LEVEL_21; + case V4L2_MPEG_VIDEO_HEVC_LEVEL_3: + return HFI_HEVC_LEVEL_3; + case V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1: + return HFI_HEVC_LEVEL_31; + case V4L2_MPEG_VIDEO_HEVC_LEVEL_4: + return HFI_HEVC_LEVEL_4; + case V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1: + return HFI_HEVC_LEVEL_41; + case V4L2_MPEG_VIDEO_HEVC_LEVEL_5: + return HFI_HEVC_LEVEL_5; +
[PATCH v2 27/29] venus: implementing multi-stream support
This is implementing a multi-stream decoder support. The multi stream gives an option to use the secondary decoder output with different raw format (or the same in case of crop). Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/core.h| 1 + drivers/media/platform/qcom/venus/helpers.c | 204 +++- drivers/media/platform/qcom/venus/helpers.h | 6 + drivers/media/platform/qcom/venus/vdec.c| 91 - drivers/media/platform/qcom/venus/venc.c| 1 + 5 files changed, 299 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 4d6c05f156c4..85e66e2dd672 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -259,6 +259,7 @@ struct venus_inst { struct list_head list; struct mutex lock; struct venus_core *core; + struct list_head dpbbufs; struct list_head internalbufs; struct list_head registeredbufs; struct list_head delayed_process; diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index ed569705ecac..87dcf9973e6f 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -85,6 +85,112 @@ bool venus_helper_check_codec(struct venus_inst *inst, u32 v4l2_pixfmt) } EXPORT_SYMBOL_GPL(venus_helper_check_codec); +static int venus_helper_queue_dpb_bufs(struct venus_inst *inst) +{ + struct intbuf *buf; + int ret = 0; + + if (list_empty(>dpbbufs)) + return 0; + + list_for_each_entry(buf, >dpbbufs, list) { + struct hfi_frame_data fdata; + + memset(, 0, sizeof(fdata)); + fdata.alloc_len = buf->size; + fdata.device_addr = buf->da; + fdata.buffer_type = buf->type; + + ret = hfi_session_process_buf(inst, ); + if (ret) + goto fail; + } + +fail: + return ret; +} + +int venus_helper_free_dpb_bufs(struct venus_inst *inst) +{ + struct intbuf *buf, *n; + + if (list_empty(>dpbbufs)) + return 0; + + list_for_each_entry_safe(buf, n, >dpbbufs, list) { + list_del_init(>list); + dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da, + buf->attrs); + kfree(buf); + } + + INIT_LIST_HEAD(>dpbbufs); + + return 0; +} +EXPORT_SYMBOL_GPL(venus_helper_free_dpb_bufs); + +int venus_helper_alloc_dpb_bufs(struct venus_inst *inst) +{ + struct venus_core *core = inst->core; + struct device *dev = core->dev; + enum hfi_version ver = core->res->hfi_version; + struct hfi_buffer_requirements bufreq; + u32 buftype = inst->dpb_buftype; + unsigned int dpb_size = 0; + struct intbuf *buf; + unsigned int i; + u32 count; + int ret; + + /* no need to allocate dpb buffers */ + if (!inst->dpb_fmt) + return 0; + + if (inst->dpb_buftype == HFI_BUFFER_OUTPUT) + dpb_size = inst->output_buf_size; + else if (inst->dpb_buftype == HFI_BUFFER_OUTPUT2) + dpb_size = inst->output2_buf_size; + + if (!dpb_size) + return 0; + + ret = venus_helper_get_bufreq(inst, buftype, ); + if (ret) + return ret; + + count = HFI_BUFREQ_COUNT_MIN(, ver); + + for (i = 0; i < count; i++) { + buf = kzalloc(sizeof(*buf), GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto fail; + } + + buf->type = buftype; + buf->size = dpb_size; + buf->attrs = DMA_ATTR_WRITE_COMBINE | +DMA_ATTR_NO_KERNEL_MAPPING; + buf->va = dma_alloc_attrs(dev, buf->size, >da, GFP_KERNEL, + buf->attrs); + if (!buf->va) { + kfree(buf); + ret = -ENOMEM; + goto fail; + } + + list_add_tail(>list, >dpbbufs); + } + + return 0; + +fail: + venus_helper_free_dpb_bufs(inst); + return ret; +} +EXPORT_SYMBOL_GPL(venus_helper_alloc_dpb_bufs); + static int intbufs_set_buffer(struct venus_inst *inst, u32 type) { struct venus_core *core = inst->core; @@ -342,7 +448,10 @@ session_process_buf(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf) if (vbuf->flags & V4L2_BUF_FLAG_LAST || !fdata.filled_len) fdata.flags |= HFI_BUFFERFLAG_EOS; } else if (type == V4L2_BU
[PATCH v2 10/29] venus: hfi_venus: add suspend functionality for Venus 4xx
This adds suspend (power collapse) functionality by reusing the suspend function for Venus 3xx and also enables idle indicator property for Venus 4xx (where it is disabled by default). Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/hfi_venus.c | 11 ++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index 284da69eb81b..109116e1545d 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -878,6 +878,14 @@ static int venus_sys_set_default_properties(struct venus_hfi_device *hdev) if (ret) dev_warn(dev, "setting fw debug msg ON failed (%d)\n", ret); + /* +* Idle indicator is disabled by default on some 4xx firmware versions, +* enable it explicitly in order to make suspend functional by checking +* WFI (wait-for-interrupt) bit. +*/ + if (IS_V4(hdev->core)) + venus_sys_idle_indicator = true; + ret = venus_sys_set_idle_message(hdev, venus_sys_idle_indicator); if (ret) dev_warn(dev, "setting idle response ON failed (%d)\n", ret); @@ -1525,7 +1533,8 @@ static int venus_suspend_3xx(struct venus_core *core) static int venus_suspend(struct venus_core *core) { - if (core->res->hfi_version == HFI_VERSION_3XX) + if (core->res->hfi_version == HFI_VERSION_3XX || + core->res->hfi_version == HFI_VERSION_4XX) return venus_suspend_3xx(core); return venus_suspend_1xx(core); -- 2.14.1
Re: [PATCH 08/28] venus: hfi_venus: add suspend function for 4xx version
Hi, On 05/09/2018 05:14 PM, Vikash Garodia wrote: > Hi Stanimir, > > On 2018-05-09 16:45, Stanimir Varbanov wrote: >> Hi Vikash, >> >> On 05/02/2018 09:07 AM, vgaro...@codeaurora.org wrote: >>> Hello Stanimir, >>> >>> On 2018-04-24 18:14, Stanimir Varbanov wrote: >>>> This adds suspend (power collapse) function with slightly >>>> different order of calls comparing with Venus 3xx. >>>> >>>> Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> >>>> --- >>>> drivers/media/platform/qcom/venus/hfi_venus.c | 52 >>>> +++ >>>> 1 file changed, 52 insertions(+) >>>> >>>> diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c >>>> b/drivers/media/platform/qcom/venus/hfi_venus.c >>>> index 53546174aab8..f61d34bf61b4 100644 >>>> --- a/drivers/media/platform/qcom/venus/hfi_venus.c >>>> +++ b/drivers/media/platform/qcom/venus/hfi_venus.c >>>> @@ -1443,6 +1443,55 @@ static int venus_suspend_1xx(struct venus_core >>>> *core) >>>> return 0; >>>> } >>>> >>>> +static int venus_suspend_4xx(struct venus_core *core) >>>> +{ >>>> + struct venus_hfi_device *hdev = to_hfi_priv(core); >>>> + struct device *dev = core->dev; >>>> + u32 val; >>>> + int ret; >>>> + >>>> + if (!hdev->power_enabled || hdev->suspended) >>>> + return 0; >>>> + >>>> + mutex_lock(>lock); >>>> + ret = venus_is_valid_state(hdev); >>>> + mutex_unlock(>lock); >>>> + >>>> + if (!ret) { >>>> + dev_err(dev, "bad state, cannot suspend\n"); >>>> + return -EINVAL; >>>> + } >>>> + >>>> + ret = venus_prepare_power_collapse(hdev, false); >>>> + if (ret) { >>>> + dev_err(dev, "prepare for power collapse fail (%d)\n", ret); >>>> + return ret; >>>> + } >>>> + >>>> + ret = readl_poll_timeout(core->base + CPU_CS_SCIACMDARG0, val, >>>> + val & CPU_CS_SCIACMDARG0_PC_READY, >>>> + POLL_INTERVAL_US, 10); >>>> + if (ret) { >>>> + dev_err(dev, "Polling power collapse ready timed out\n"); >>>> + return ret; >>>> + } >>>> + >>>> + mutex_lock(>lock); >>>> + >>>> + ret = venus_power_off(hdev); >>>> + if (ret) { >>>> + dev_err(dev, "venus_power_off (%d)\n", ret); >>>> + mutex_unlock(>lock); >>>> + return ret; >>>> + } >>>> + >>>> + hdev->suspended = true; >>>> + >>>> + mutex_unlock(>lock); >>>> + >>>> + return 0; >>>> +} >>>> + >>>> static int venus_suspend_3xx(struct venus_core *core) >>>> { >>>> struct venus_hfi_device *hdev = to_hfi_priv(core); >>>> @@ -1507,6 +1556,9 @@ static int venus_suspend(struct venus_core *core) >>>> if (core->res->hfi_version == HFI_VERSION_3XX) >>>> return venus_suspend_3xx(core); >>>> >>>> + if (core->res->hfi_version == HFI_VERSION_4XX) >>>> + return venus_suspend_4xx(core); >>>> + >>>> return venus_suspend_1xx(core); >>>> } >>> >>> Let me brief on the power collapse sequence for Venus_4xx >>> 1. Host checks for ARM9 and Video core to be idle. >>> This can be done by checking for WFI bit (bit 0) in CPU status >>> register for ARM9 and by checking bit 30 in Control status reg for video >>> core/s. >>> 2. Host then sends command to ARM9 to prepare for power collapse. >>> 3. Host then checks for WFI bit and PC_READY bit before withdrawing >>> going for power off. >>> >>> As per this patch, host is preparing for power collapse without checking >>> for #1. >>> Update the code to handle #3. >> >> This looks similar to suspend for Venus 3xx. Can you confirm that the >> sequence of checks for 4xx is the same as 3xx? > > Do you mean the driver implementation for Suspend Venus 3xx or the hardware > expectation for Venus 3xx ? If hardware expectation wise, the sequence is > same for 3xx and 4xx. > In the suspend implementation for 3xx, i see that the host just reads > the WFI > and idle status bits, but does not validate those bit value before > preparing > Venus for power collapse. Sequence #2 and #3 is followed for Venus 3xx > implementation. OK, than we can reuse venus_suspend_3xx function for 4xx, just need to fix WFI and idle bit for #1. -- regards, Stan
Re: [PATCH 08/28] venus: hfi_venus: add suspend function for 4xx version
Hi Vikash, On 05/02/2018 09:07 AM, vgaro...@codeaurora.org wrote: > Hello Stanimir, > > On 2018-04-24 18:14, Stanimir Varbanov wrote: >> This adds suspend (power collapse) function with slightly >> different order of calls comparing with Venus 3xx. >> >> Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> >> --- >> drivers/media/platform/qcom/venus/hfi_venus.c | 52 >> +++ >> 1 file changed, 52 insertions(+) >> >> diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c >> b/drivers/media/platform/qcom/venus/hfi_venus.c >> index 53546174aab8..f61d34bf61b4 100644 >> --- a/drivers/media/platform/qcom/venus/hfi_venus.c >> +++ b/drivers/media/platform/qcom/venus/hfi_venus.c >> @@ -1443,6 +1443,55 @@ static int venus_suspend_1xx(struct venus_core >> *core) >> return 0; >> } >> >> +static int venus_suspend_4xx(struct venus_core *core) >> +{ >> + struct venus_hfi_device *hdev = to_hfi_priv(core); >> + struct device *dev = core->dev; >> + u32 val; >> + int ret; >> + >> + if (!hdev->power_enabled || hdev->suspended) >> + return 0; >> + >> + mutex_lock(>lock); >> + ret = venus_is_valid_state(hdev); >> + mutex_unlock(>lock); >> + >> + if (!ret) { >> + dev_err(dev, "bad state, cannot suspend\n"); >> + return -EINVAL; >> + } >> + >> + ret = venus_prepare_power_collapse(hdev, false); >> + if (ret) { >> + dev_err(dev, "prepare for power collapse fail (%d)\n", ret); >> + return ret; >> + } >> + >> + ret = readl_poll_timeout(core->base + CPU_CS_SCIACMDARG0, val, >> + val & CPU_CS_SCIACMDARG0_PC_READY, >> + POLL_INTERVAL_US, 10); >> + if (ret) { >> + dev_err(dev, "Polling power collapse ready timed out\n"); >> + return ret; >> + } >> + >> + mutex_lock(>lock); >> + >> + ret = venus_power_off(hdev); >> + if (ret) { >> + dev_err(dev, "venus_power_off (%d)\n", ret); >> + mutex_unlock(>lock); >> + return ret; >> + } >> + >> + hdev->suspended = true; >> + >> + mutex_unlock(>lock); >> + >> + return 0; >> +} >> + >> static int venus_suspend_3xx(struct venus_core *core) >> { >> struct venus_hfi_device *hdev = to_hfi_priv(core); >> @@ -1507,6 +1556,9 @@ static int venus_suspend(struct venus_core *core) >> if (core->res->hfi_version == HFI_VERSION_3XX) >> return venus_suspend_3xx(core); >> >> + if (core->res->hfi_version == HFI_VERSION_4XX) >> + return venus_suspend_4xx(core); >> + >> return venus_suspend_1xx(core); >> } > > Let me brief on the power collapse sequence for Venus_4xx > 1. Host checks for ARM9 and Video core to be idle. > This can be done by checking for WFI bit (bit 0) in CPU status > register for ARM9 and by checking bit 30 in Control status reg for video > core/s. > 2. Host then sends command to ARM9 to prepare for power collapse. > 3. Host then checks for WFI bit and PC_READY bit before withdrawing > going for power off. > > As per this patch, host is preparing for power collapse without checking > for #1. > Update the code to handle #3. This looks similar to suspend for Venus 3xx. Can you confirm that the sequence of checks for 4xx is the same as 3xx? -- regards, Stan
Re: [PATCH 10/28] venus: vdec: call session_continue in insufficient event
Hi Vikash, On 05/04/2018 02:09 PM, Vikash Garodia wrote: > Hi Stanimir, > > On 2018-05-03 17:06, Stanimir Varbanov wrote: >> Hi Vikash, >> >> Thanks for the comments! >> >> On 2.05.2018 09:26, Vikash Garodia wrote: >>> Hello Stanimir, >>> >>> On 2018-04-24 18:14, Stanimir Varbanov wrote: >>>> Call session_continue for Venus 4xx version even when the event >>>> says that the buffer resources are not sufficient. Leaving a >>>> comment with more information about the workaround. >>>> >>>> Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> >>>> --- >>>> drivers/media/platform/qcom/venus/vdec.c | 8 >>>> 1 file changed, 8 insertions(+) >>>> >>>> diff --git a/drivers/media/platform/qcom/venus/vdec.c >>>> b/drivers/media/platform/qcom/venus/vdec.c >>>> index c45452634e7e..91c7384ff9c8 100644 >>>> --- a/drivers/media/platform/qcom/venus/vdec.c >>>> +++ b/drivers/media/platform/qcom/venus/vdec.c >>>> @@ -873,6 +873,14 @@ static void vdec_event_notify(struct venus_inst >>>> *inst, u32 event, >>>> >>>> dev_dbg(dev, "event not sufficient resources (%ux%u)\n", >>>> data->width, data->height); >>>> + /* >>>> + * Workaround: Even that the firmware send and event for >>>> + * insufficient buffer resources it is safe to call >>>> + * session_continue because actually the event says that >>>> + * the number of capture buffers is lower. >>>> + */ >>>> + if (IS_V4(core)) >>>> + hfi_session_continue(inst); >>>> break; >>>> case HFI_EVENT_RELEASE_BUFFER_REFERENCE: >>>> venus_helper_release_buf_ref(inst, data->tag); >>> >>> Insufficient event from video firmware could be sent either, >>> 1. due to insufficient buffer resources >>> 2. due to lower capture buffers >>> >>> It cannot be assumed that the event received by the host is due to >>> lower capture >>> buffers. Incase the buffer resource is insufficient, let say there is >>> a bitstream >>> resolution switch from 720p to 1080p, capture buffers needs to be >>> reallocated. >> >> I agree with you. I will rework this part and call session_continue >> only for case #2. > > Even if the capture buffers are lower, driver should consider > reallocation of capture > buffers with required higher count. Without this, it may happen that for > a given video > frame, the decoded output will not be generated. Thanks for the comments, I realized that this workaround is not needed anymore, so I will drop the patch. -- regards, Stan
Re: [PATCH 00/28] Venus updates
Hi Hans, On 7.05.2018 13:41, Hans Verkuil wrote: On 24/04/18 14:44, Stanimir Varbanov wrote: Hello, This patch set aims to: * add initial support for Venus version 4xx (found on sdm845). * introduce a common capability parser to enumerate better supported uncompressed formats, capabilities by codec, supported codecs and so on. * also contains various cleanups, readability improvements and fixes. * adds HEVC codec support for the Venus versions which has support for it. * add multi-stream support (secondary decoder output), which will give as an opportunity to use UBWC compressed formats to optimize internal interconnect bandwidth on higher resolutions. I'm a bit confused about this: is this a purely driver-internal thing, or is this exposed somehow to userspace as well? It seems to be purely internal. For now it'll be internal for the driver. In downstream driver it is exposed to userspace via custom v4l_control but that is not generic and I decided to not expose it. regards, Stan
Re: [PATCH 28/28] venus: add HEVC codec support
Hi Hans, On 7.05.2018 13:39, Hans Verkuil wrote: On 24/04/18 14:44, Stanimir Varbanov wrote: This add HEVC codec support for venus versions 3xx and 4xx. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/helpers.c | 3 +++ drivers/media/platform/qcom/venus/hfi.c | 2 ++ drivers/media/platform/qcom/venus/vdec.c| 4 drivers/media/platform/qcom/venus/venc.c| 4 4 files changed, 13 insertions(+) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 87dcf9973e6f..fecadba039cf 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -71,6 +71,9 @@ bool venus_helper_check_codec(struct venus_inst *inst, u32 v4l2_pixfmt) case V4L2_PIX_FMT_XVID: codec = HFI_VIDEO_CODEC_DIVX; break; + case V4L2_PIX_FMT_HEVC: + codec = HFI_VIDEO_CODEC_HEVC; + break; default: return false; } diff --git a/drivers/media/platform/qcom/venus/hfi.c b/drivers/media/platform/qcom/venus/hfi.c index 94ca27b0bb99..24207829982f 100644 --- a/drivers/media/platform/qcom/venus/hfi.c +++ b/drivers/media/platform/qcom/venus/hfi.c @@ -49,6 +49,8 @@ static u32 to_codec_type(u32 pixfmt) return HFI_VIDEO_CODEC_VP9; case V4L2_PIX_FMT_XVID: return HFI_VIDEO_CODEC_DIVX; + case V4L2_PIX_FMT_HEVC: + return HFI_VIDEO_CODEC_HEVC; default: return 0; } diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 7deee104ac56..a114f421edad 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -77,6 +77,10 @@ static const struct venus_format vdec_formats[] = { .pixfmt = V4L2_PIX_FMT_XVID, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + }, { + .pixfmt = V4L2_PIX_FMT_HEVC, + .num_planes = 1, + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, }, }; diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index a703bce78abc..fdb76b69786f 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -59,6 +59,10 @@ static const struct venus_format venc_formats[] = { .pixfmt = V4L2_PIX_FMT_VP8, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + }, { + .pixfmt = V4L2_PIX_FMT_HEVC, + .num_planes = 1, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, }, }; No changes are necessary to venc_set_properties() for HEVC support? Just checking, I kind of expected that. yes, I think so, but will leave that for future updates. regards, Stan
Re: [PATCH 10/28] venus: vdec: call session_continue in insufficient event
Hi Vikash, Thanks for the comments! On 2.05.2018 09:26, Vikash Garodia wrote: Hello Stanimir, On 2018-04-24 18:14, Stanimir Varbanov wrote: Call session_continue for Venus 4xx version even when the event says that the buffer resources are not sufficient. Leaving a comment with more information about the workaround. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/vdec.c | 8 1 file changed, 8 insertions(+) diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index c45452634e7e..91c7384ff9c8 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -873,6 +873,14 @@ static void vdec_event_notify(struct venus_inst *inst, u32 event, dev_dbg(dev, "event not sufficient resources (%ux%u)\n", data->width, data->height); + /* + * Workaround: Even that the firmware send and event for + * insufficient buffer resources it is safe to call + * session_continue because actually the event says that + * the number of capture buffers is lower. + */ + if (IS_V4(core)) + hfi_session_continue(inst); break; case HFI_EVENT_RELEASE_BUFFER_REFERENCE: venus_helper_release_buf_ref(inst, data->tag); Insufficient event from video firmware could be sent either, 1. due to insufficient buffer resources 2. due to lower capture buffers It cannot be assumed that the event received by the host is due to lower capture buffers. Incase the buffer resource is insufficient, let say there is a bitstream resolution switch from 720p to 1080p, capture buffers needs to be reallocated. I agree with you. I will rework this part and call session_continue only for case #2. The driver should be sending the V4L2_EVENT_SOURCE_CHANGE to client instead of ignoring the event from firmware. The v4l2 event is sent always to v4l clients. regards, Stan
Re: [PATCH 26/28] venus: implementing multi-stream support
Hi Vikash, Please write the comments for the chunk of code for which they are refer to. On 2.05.2018 10:40, Vikash Garodia wrote: Hello Stanimir, On 2018-04-24 18:14, Stanimir Varbanov wrote: This is implementing a multi-stream decoder support. The multi stream gives an option to use the secondary decoder output with different raw format (or the same in case of crop). Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/core.h | 1 + drivers/media/platform/qcom/venus/helpers.c | 204 +++- drivers/media/platform/qcom/venus/helpers.h | 6 + drivers/media/platform/qcom/venus/vdec.c | 91 - drivers/media/platform/qcom/venus/venc.c | 1 + 5 files changed, 299 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 4d6c05f156c4..85e66e2dd672 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -259,6 +259,7 @@ struct venus_inst { struct list_head list; struct mutex lock; struct venus_core *core; + struct list_head dpbbufs; struct list_head internalbufs; struct list_head registeredbufs; struct list_head delayed_process; The dpb buffers queued to hardware will be returned back to host either during flush or when the session is stopped. Host should not send these buffers to client. That's correct. vdec_buf_done should be handling in a way to drop dpb buffers from sending to client. That is also correct, vdec_buf_done is trying to find the buffer by index from a list of queued buffers from v4l2 clients. See venus_helper_vb2_buf_queue where it is calling v4l2_m2m_buf_queue. So for the dpb buffers venus_helper_find_buf() will return NULL. regards, Stan
[PATCH 01/28] venus: hfi_msgs: correct pointer increment
Data pointer should be incremented by size of the structure not the size of a pointer, correct the mistake. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/hfi_msgs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c index 90c93d9603dc..589e1a6b36a9 100644 --- a/drivers/media/platform/qcom/venus/hfi_msgs.c +++ b/drivers/media/platform/qcom/venus/hfi_msgs.c @@ -60,14 +60,14 @@ static void event_seq_changed(struct venus_core *core, struct venus_inst *inst, frame_sz = (struct hfi_framesize *)data_ptr; event.width = frame_sz->width; event.height = frame_sz->height; - data_ptr += sizeof(frame_sz); + data_ptr += sizeof(*frame_sz); break; case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT: data_ptr += sizeof(u32); profile_level = (struct hfi_profile_level *)data_ptr; event.profile = profile_level->profile; event.level = profile_level->level; - data_ptr += sizeof(profile_level); + data_ptr += sizeof(*profile_level); break; default: break; -- 2.14.1
[PATCH 03/28] venus: hfi: update sequence event to handle more properties
HFI version 4xx can pass more properties in the sequence change event, extend the event structure with them. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/hfi.h | 9 ++ drivers/media/platform/qcom/venus/hfi_msgs.c | 46 2 files changed, 55 insertions(+) diff --git a/drivers/media/platform/qcom/venus/hfi.h b/drivers/media/platform/qcom/venus/hfi.h index 5466b7d60dd0..21376d93170f 100644 --- a/drivers/media/platform/qcom/venus/hfi.h +++ b/drivers/media/platform/qcom/venus/hfi.h @@ -74,6 +74,15 @@ struct hfi_event_data { u32 tag; u32 profile; u32 level; + u32 bit_depth; + u32 pic_struct; + u32 colour_space; + u32 entropy_mode; + u32 buf_count; + struct { + u32 left, top; + u32 width, height; + } input_crop; }; /* define core states */ diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c index 589e1a6b36a9..5970e9b1716b 100644 --- a/drivers/media/platform/qcom/venus/hfi_msgs.c +++ b/drivers/media/platform/qcom/venus/hfi_msgs.c @@ -25,10 +25,17 @@ static void event_seq_changed(struct venus_core *core, struct venus_inst *inst, struct hfi_msg_event_notify_pkt *pkt) { + enum hfi_version ver = core->res->hfi_version; struct hfi_event_data event = {0}; int num_properties_changed; struct hfi_framesize *frame_sz; struct hfi_profile_level *profile_level; + struct hfi_bit_depth *pixel_depth; + struct hfi_pic_struct *pic_struct; + struct hfi_colour_space *colour_info; + struct hfi_buffer_requirements *bufreq; + struct hfi_extradata_input_crop *crop; + u32 entropy_mode = 0; u8 *data_ptr; u32 ptype; @@ -69,6 +76,45 @@ static void event_seq_changed(struct venus_core *core, struct venus_inst *inst, event.level = profile_level->level; data_ptr += sizeof(*profile_level); break; + case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH: + data_ptr += sizeof(u32); + pixel_depth = (struct hfi_bit_depth *)data_ptr; + event.bit_depth = pixel_depth->bit_depth; + data_ptr += sizeof(*pixel_depth); + break; + case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT: + data_ptr += sizeof(u32); + pic_struct = (struct hfi_pic_struct *)data_ptr; + event.pic_struct = pic_struct->progressive_only; + data_ptr += sizeof(*pic_struct); + break; + case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE: + data_ptr += sizeof(u32); + colour_info = (struct hfi_colour_space *)data_ptr; + event.colour_space = colour_info->colour_space; + data_ptr += sizeof(*colour_info); + break; + case HFI_PROPERTY_CONFIG_VDEC_ENTROPY: + data_ptr += sizeof(u32); + entropy_mode = *(u32 *)data_ptr; + event.entropy_mode = entropy_mode; + data_ptr += sizeof(u32); + break; + case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS: + data_ptr += sizeof(u32); + bufreq = (struct hfi_buffer_requirements *)data_ptr; + event.buf_count = HFI_BUFREQ_COUNT_MIN(bufreq, ver); + data_ptr += sizeof(*bufreq); + break; + case HFI_INDEX_EXTRADATA_INPUT_CROP: + data_ptr += sizeof(u32); + crop = (struct hfi_extradata_input_crop *)data_ptr; + event.input_crop.left = crop->left; + event.input_crop.top = crop->top; + event.input_crop.width = crop->width; + event.input_crop.height = crop->height; + data_ptr += sizeof(*crop); + break; default: break; } -- 2.14.1
[PATCH 02/28] venus: hfi: preparation to support venus 4xx
This covers the differences between 1xx,3xx and 4xx. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/core.h | 4 ++ drivers/media/platform/qcom/venus/helpers.c | 37 +++ drivers/media/platform/qcom/venus/hfi_helper.h | 84 ++-- drivers/media/platform/qcom/venus/hfi_venus_io.h | 24 +++ drivers/media/platform/qcom/venus/vdec.c | 5 +- drivers/media/platform/qcom/venus/venc.c | 5 +- 6 files changed, 137 insertions(+), 22 deletions(-) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 0360d295f4c8..8d3e150800c9 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -305,6 +305,10 @@ struct venus_inst { struct hfi_buffer_requirements bufreq[HFI_BUFFER_TYPE_MAX]; }; +#define IS_V1(core)((core)->res->hfi_version == HFI_VERSION_1XX) +#define IS_V3(core)((core)->res->hfi_version == HFI_VERSION_3XX) +#define IS_V4(core)((core)->res->hfi_version == HFI_VERSION_4XX) + #define ctrl_to_inst(ctrl) \ container_of((ctrl)->handler, struct venus_inst, ctrl_handler) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 0ce9559a2924..d9065cc8a7d3 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -166,21 +166,37 @@ static int intbufs_unset_buffers(struct venus_inst *inst) return ret; } -static const unsigned int intbuf_types[] = { - HFI_BUFFER_INTERNAL_SCRATCH, - HFI_BUFFER_INTERNAL_SCRATCH_1, - HFI_BUFFER_INTERNAL_SCRATCH_2, +static const unsigned int intbuf_types_1xx[] = { + HFI_BUFFER_INTERNAL_SCRATCH(HFI_VERSION_1XX), + HFI_BUFFER_INTERNAL_SCRATCH_1(HFI_VERSION_1XX), + HFI_BUFFER_INTERNAL_SCRATCH_2(HFI_VERSION_1XX), + HFI_BUFFER_INTERNAL_PERSIST, + HFI_BUFFER_INTERNAL_PERSIST_1, +}; + +static const unsigned int intbuf_types_4xx[] = { + HFI_BUFFER_INTERNAL_SCRATCH(HFI_VERSION_4XX), + HFI_BUFFER_INTERNAL_SCRATCH_1(HFI_VERSION_4XX), + HFI_BUFFER_INTERNAL_SCRATCH_2(HFI_VERSION_4XX), HFI_BUFFER_INTERNAL_PERSIST, HFI_BUFFER_INTERNAL_PERSIST_1, }; static int intbufs_alloc(struct venus_inst *inst) { - unsigned int i; + size_t arr_sz; + size_t i; int ret; - for (i = 0; i < ARRAY_SIZE(intbuf_types); i++) { - ret = intbufs_set_buffer(inst, intbuf_types[i]); + if (IS_V4(inst->core)) + arr_sz = ARRAY_SIZE(intbuf_types_4xx); + else + arr_sz = ARRAY_SIZE(intbuf_types_1xx); + + for (i = 0; i < arr_sz; i++) { + ret = intbufs_set_buffer(inst, + IS_V4(inst->core) ? intbuf_types_4xx[i] : + intbuf_types_1xx[i]); if (ret) goto error; } @@ -257,12 +273,11 @@ static int load_scale_clocks(struct venus_core *core) set_freq: - if (core->res->hfi_version == HFI_VERSION_3XX) { - ret = clk_set_rate(clk, freq); + ret = clk_set_rate(clk, freq); + + if (IS_V3(core) || IS_V4(core)) { ret |= clk_set_rate(core->core0_clk, freq); ret |= clk_set_rate(core->core1_clk, freq); - } else { - ret = clk_set_rate(clk, freq); } if (ret) { diff --git a/drivers/media/platform/qcom/venus/hfi_helper.h b/drivers/media/platform/qcom/venus/hfi_helper.h index 55d8eb21403a..1bc5aab1ce6b 100644 --- a/drivers/media/platform/qcom/venus/hfi_helper.h +++ b/drivers/media/platform/qcom/venus/hfi_helper.h @@ -121,6 +121,7 @@ #define HFI_EXTRADATA_METADATA_FILLER 0x7fe2 #define HFI_INDEX_EXTRADATA_INPUT_CROP 0x070e +#define HFI_INDEX_EXTRADATA_OUTPUT_CROP0x070f #define HFI_INDEX_EXTRADATA_DIGITAL_ZOOM 0x0710 #define HFI_INDEX_EXTRADATA_ASPECT_RATIO 0x7f13 @@ -376,13 +377,18 @@ #define HFI_BUFFER_OUTPUT2 0x3 #define HFI_BUFFER_INTERNAL_PERSIST0x4 #define HFI_BUFFER_INTERNAL_PERSIST_1 0x5 -#define HFI_BUFFER_INTERNAL_SCRATCH0x101 -#define HFI_BUFFER_EXTRADATA_INPUT 0x102 -#define HFI_BUFFER_EXTRADATA_OUTPUT0x103 -#define HFI_BUFFER_EXTRADATA_OUTPUT2 0x104 -#define HFI_BUFFER_INTERNAL_SCRATCH_1 0x105 -#define HFI_BUFFER_INTERNAL_SCRATCH_2 0x106 - +#define HFI_BUFFER_INTERNAL_SCRATCH(ver) \ + (((ver) == HFI_VERSION_4XX) ? 0x6 : 0x101) +#define HFI_BUFFER_INTERNAL_SCRATCH_1(ver) \ + (((ver) == HFI_VERSION_4XX) ? 0x7 : 0x105) +#define HFI_BUFFER_INTERNAL_SCRATCH_2(v
[PATCH 05/28] venus: hfi: support session continue for 4xx version
This makes possible to handle session_continue for 4xx as well. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/hfi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/venus/hfi.c b/drivers/media/platform/qcom/venus/hfi.c index bca894a00c07..cbc6fad05e47 100644 --- a/drivers/media/platform/qcom/venus/hfi.c +++ b/drivers/media/platform/qcom/venus/hfi.c @@ -312,7 +312,7 @@ int hfi_session_continue(struct venus_inst *inst) { struct venus_core *core = inst->core; - if (core->res->hfi_version != HFI_VERSION_3XX) + if (core->res->hfi_version == HFI_VERSION_1XX) return 0; return core->ops->session_continue(inst); -- 2.14.1
[PATCH 06/28] venus: hfi: handle buffer output2 type as well
This adds handling of buffers of type OUTPUT2 which is needed to support Venus 4xx version. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/hfi.c | 3 ++- drivers/media/platform/qcom/venus/hfi_msgs.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi.c b/drivers/media/platform/qcom/venus/hfi.c index cbc6fad05e47..a570fdad0de0 100644 --- a/drivers/media/platform/qcom/venus/hfi.c +++ b/drivers/media/platform/qcom/venus/hfi.c @@ -473,7 +473,8 @@ int hfi_session_process_buf(struct venus_inst *inst, struct hfi_frame_data *fd) if (fd->buffer_type == HFI_BUFFER_INPUT) return ops->session_etb(inst, fd); - else if (fd->buffer_type == HFI_BUFFER_OUTPUT) + else if (fd->buffer_type == HFI_BUFFER_OUTPUT || +fd->buffer_type == HFI_BUFFER_OUTPUT2) return ops->session_ftb(inst, fd); return -EINVAL; diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c index 5970e9b1716b..023802e62833 100644 --- a/drivers/media/platform/qcom/venus/hfi_msgs.c +++ b/drivers/media/platform/qcom/venus/hfi_msgs.c @@ -825,7 +825,8 @@ static void hfi_session_ftb_done(struct venus_core *core, error = HFI_ERR_SESSION_INVALID_PARAMETER; } - if (buffer_type != HFI_BUFFER_OUTPUT) + if (buffer_type != HFI_BUFFER_OUTPUT && + buffer_type != HFI_BUFFER_OUTPUT2) goto done; if (hfi_flags & HFI_BUFFERFLAG_EOS) -- 2.14.1
[PATCH 08/28] venus: hfi_venus: add suspend function for 4xx version
This adds suspend (power collapse) function with slightly different order of calls comparing with Venus 3xx. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/hfi_venus.c | 52 +++ 1 file changed, 52 insertions(+) diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index 53546174aab8..f61d34bf61b4 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -1443,6 +1443,55 @@ static int venus_suspend_1xx(struct venus_core *core) return 0; } +static int venus_suspend_4xx(struct venus_core *core) +{ + struct venus_hfi_device *hdev = to_hfi_priv(core); + struct device *dev = core->dev; + u32 val; + int ret; + + if (!hdev->power_enabled || hdev->suspended) + return 0; + + mutex_lock(>lock); + ret = venus_is_valid_state(hdev); + mutex_unlock(>lock); + + if (!ret) { + dev_err(dev, "bad state, cannot suspend\n"); + return -EINVAL; + } + + ret = venus_prepare_power_collapse(hdev, false); + if (ret) { + dev_err(dev, "prepare for power collapse fail (%d)\n", ret); + return ret; + } + + ret = readl_poll_timeout(core->base + CPU_CS_SCIACMDARG0, val, +val & CPU_CS_SCIACMDARG0_PC_READY, +POLL_INTERVAL_US, 10); + if (ret) { + dev_err(dev, "Polling power collapse ready timed out\n"); + return ret; + } + + mutex_lock(>lock); + + ret = venus_power_off(hdev); + if (ret) { + dev_err(dev, "venus_power_off (%d)\n", ret); + mutex_unlock(>lock); + return ret; + } + + hdev->suspended = true; + + mutex_unlock(>lock); + + return 0; +} + static int venus_suspend_3xx(struct venus_core *core) { struct venus_hfi_device *hdev = to_hfi_priv(core); @@ -1507,6 +1556,9 @@ static int venus_suspend(struct venus_core *core) if (core->res->hfi_version == HFI_VERSION_3XX) return venus_suspend_3xx(core); + if (core->res->hfi_version == HFI_VERSION_4XX) + return venus_suspend_4xx(core); + return venus_suspend_1xx(core); } -- 2.14.1
[PATCH 07/28] venus: hfi_venus: add halt AXI support for Venus 4xx
Add AXI halt support for version 4xx by using venus wrapper registers. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/hfi_venus.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index 734ce11b0ed0..53546174aab8 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -532,6 +532,23 @@ static int venus_halt_axi(struct venus_hfi_device *hdev) u32 val; int ret; + if (hdev->core->res->hfi_version == HFI_VERSION_4XX) { + val = venus_readl(hdev, WRAPPER_CPU_AXI_HALT); + val |= BIT(16); + venus_writel(hdev, WRAPPER_CPU_AXI_HALT, val); + + ret = readl_poll_timeout(base + WRAPPER_CPU_AXI_HALT_STATUS, +val, val & BIT(24), +POLL_INTERVAL_US, +VBIF_AXI_HALT_ACK_TIMEOUT_US); + if (ret) { + dev_err(dev, "AXI bus port halt timeout\n"); + return ret; + } + + return 0; + } + /* Halt AXI and AXI IMEM VBIF Access */ val = venus_readl(hdev, VBIF_AXI_HALT_CTRL0); val |= VBIF_AXI_HALT_CTRL0_HALT_REQ; -- 2.14.1
[PATCH 09/28] venus: venc,vdec: adds clocks needed for venus 4xx
This extends the clocks number to support suspend and resume on Venus version 4xx. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/core.h | 4 +-- drivers/media/platform/qcom/venus/vdec.c | 42 ++-- drivers/media/platform/qcom/venus/venc.c | 42 ++-- 3 files changed, 72 insertions(+), 16 deletions(-) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 8d3e150800c9..b5b9a84e9155 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -92,8 +92,8 @@ struct venus_core { void __iomem *base; int irq; struct clk *clks[VIDC_CLKS_NUM_MAX]; - struct clk *core0_clk; - struct clk *core1_clk; + struct clk *core0_clk, *core0_bus_clk; + struct clk *core1_clk, *core1_bus_clk; struct video_device *vdev_dec; struct video_device *vdev_enc; struct v4l2_device v4l2_dev; diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 261a51adeef2..c45452634e7e 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -1081,12 +1081,18 @@ static int vdec_probe(struct platform_device *pdev) if (!core) return -EPROBE_DEFER; - if (core->res->hfi_version == HFI_VERSION_3XX) { + if (IS_V3(core) || IS_V4(core)) { core->core0_clk = devm_clk_get(dev, "core"); if (IS_ERR(core->core0_clk)) return PTR_ERR(core->core0_clk); } + if (IS_V4(core)) { + core->core0_bus_clk = devm_clk_get(dev, "bus"); + if (IS_ERR(core->core0_bus_clk)) + return PTR_ERR(core->core0_bus_clk); + } + platform_set_drvdata(pdev, core); vdev = video_device_alloc(); @@ -1132,12 +1138,23 @@ static __maybe_unused int vdec_runtime_suspend(struct device *dev) { struct venus_core *core = dev_get_drvdata(dev); - if (core->res->hfi_version == HFI_VERSION_1XX) + if (IS_V1(core)) return 0; - writel(0, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); + if (IS_V3(core)) + writel(0, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); + else if (IS_V4(core)) + writel(0, core->base + WRAPPER_VCODEC0_MMCC_POWER_CONTROL); + + if (IS_V4(core)) + clk_disable_unprepare(core->core0_bus_clk); + clk_disable_unprepare(core->core0_clk); - writel(1, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); + + if (IS_V3(core)) + writel(1, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); + else if (IS_V4(core)) + writel(1, core->base + WRAPPER_VCODEC0_MMCC_POWER_CONTROL); return 0; } @@ -1147,12 +1164,23 @@ static __maybe_unused int vdec_runtime_resume(struct device *dev) struct venus_core *core = dev_get_drvdata(dev); int ret; - if (core->res->hfi_version == HFI_VERSION_1XX) + if (IS_V1(core)) return 0; - writel(0, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); + if (IS_V3(core)) + writel(0, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); + else if (IS_V4(core)) + writel(0, core->base + WRAPPER_VCODEC0_MMCC_POWER_CONTROL); + ret = clk_prepare_enable(core->core0_clk); - writel(1, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); + + if (IS_V4(core)) + ret |= clk_prepare_enable(core->core0_bus_clk); + + if (IS_V3(core)) + writel(1, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); + else if (IS_V4(core)) + writel(1, core->base + WRAPPER_VCODEC0_MMCC_POWER_CONTROL); return ret; } diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index 947001170a77..bc8c2e7a8d2c 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -1225,12 +1225,18 @@ static int venc_probe(struct platform_device *pdev) if (!core) return -EPROBE_DEFER; - if (core->res->hfi_version == HFI_VERSION_3XX) { + if (IS_V3(core) || IS_V4(core)) { core->core1_clk = devm_clk_get(dev, "core"); if (IS_ERR(core->core1_clk)) return PTR_ERR(core->core1_clk); } + if (IS_V4(core)) { + core->core1_bus_clk = devm_clk_get(dev, "bus"); + if (IS_ERR(core->core1_bus_clk)) + return PTR_ERR(core->core1_bus_clk); + } + platform_set_drvdata(pdev, core);
[PATCH 11/28] venus: add common capability parser
This adds common capability parser for all supported Venus versions. Having it will help to enumerate better the supported raw formars and codecs and also the capabilities for every codec like max/min width/height, framerate, bitrate and so on. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/Makefile | 3 +- drivers/media/platform/qcom/venus/core.c | 80 ++ drivers/media/platform/qcom/venus/core.h | 68 +++-- drivers/media/platform/qcom/venus/hfi.c| 5 +- drivers/media/platform/qcom/venus/hfi_helper.h | 28 +- drivers/media/platform/qcom/venus/hfi_msgs.c | 348 ++--- drivers/media/platform/qcom/venus/hfi_parser.c | 294 + drivers/media/platform/qcom/venus/hfi_parser.h | 45 drivers/media/platform/qcom/venus/vdec.c | 38 +-- drivers/media/platform/qcom/venus/venc.c | 52 ++-- 10 files changed, 524 insertions(+), 437 deletions(-) create mode 100644 drivers/media/platform/qcom/venus/hfi_parser.c create mode 100644 drivers/media/platform/qcom/venus/hfi_parser.h diff --git a/drivers/media/platform/qcom/venus/Makefile b/drivers/media/platform/qcom/venus/Makefile index bfd4edf7c83f..b44b11b03e12 100644 --- a/drivers/media/platform/qcom/venus/Makefile +++ b/drivers/media/platform/qcom/venus/Makefile @@ -2,7 +2,8 @@ # Makefile for Qualcomm Venus driver 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-enc-objs += venc.o venc_ctrls.o diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index 41eef376eb2d..1b72bfbb6297 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -152,6 +152,78 @@ static void venus_clks_disable(struct venus_core *core) 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; + unsigned int i; + u32 codec, codecs; + int ret; + + if (core->res->hfi_version != HFI_VERSION_1XX) + return 0; + + memset(, 0, sizeof(inst)); + mutex_init(); + 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(, _ops); + if (ret) + return ret; + + for (i = 0; i < MAX_CODEC_NUM; i++) { + codec = (1 << i) & codecs; + if (!codec) + continue; + + ret = hfi_session_init(, to_v4l2_codec_type(codec)); + if (ret) + goto done; + + ret = hfi_session_deinit(); + if (ret) + goto done; + } + +done: + hfi_session_destroy(); + mutex_destroy(); + + return ret; +} + static int venus_probe(struct platform_device *pdev) { struct device *dev = >dev; @@ -219,6 +291,14 @@ static int venus_probe(struct platform_device *pdev) if (ret) 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, >v4l2_dev); if (ret) goto err_core_deinit; diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index b5b9a84e9155..fe2d2b9e8af8 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -57,6 +57,29 @@ struct venus_format {
[PATCH 10/28] venus: vdec: call session_continue in insufficient event
Call session_continue for Venus 4xx version even when the event says that the buffer resources are not sufficient. Leaving a comment with more information about the workaround. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/vdec.c | 8 1 file changed, 8 insertions(+) diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index c45452634e7e..91c7384ff9c8 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -873,6 +873,14 @@ static void vdec_event_notify(struct venus_inst *inst, u32 event, dev_dbg(dev, "event not sufficient resources (%ux%u)\n", data->width, data->height); + /* +* Workaround: Even that the firmware send and event for +* insufficient buffer resources it is safe to call +* session_continue because actually the event says that +* the number of capture buffers is lower. +*/ + if (IS_V4(core)) + hfi_session_continue(inst); break; case HFI_EVENT_RELEASE_BUFFER_REFERENCE: venus_helper_release_buf_ref(inst, data->tag); -- 2.14.1
[PATCH 04/28] venus: hfi_cmds: add set_properties for 4xx version
Adds set_properties method to handle newer 4xx properties and fall-back to 3xx for the rest. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/hfi_cmds.c | 64 +++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.c b/drivers/media/platform/qcom/venus/hfi_cmds.c index 1cfeb7743041..6bd287154796 100644 --- a/drivers/media/platform/qcom/venus/hfi_cmds.c +++ b/drivers/media/platform/qcom/venus/hfi_cmds.c @@ -1166,6 +1166,65 @@ pkt_session_set_property_3xx(struct hfi_session_set_property_pkt *pkt, return ret; } +static int +pkt_session_set_property_4xx(struct hfi_session_set_property_pkt *pkt, +void *cookie, u32 ptype, void *pdata) +{ + void *prop_data; + int ret = 0; + + if (!pkt || !cookie || !pdata) + return -EINVAL; + + prop_data = >data[1]; + + pkt->shdr.hdr.size = sizeof(*pkt); + pkt->shdr.hdr.pkt_type = HFI_CMD_SESSION_SET_PROPERTY; + pkt->shdr.session_id = hash32_ptr(cookie); + pkt->num_properties = 1; + pkt->data[0] = ptype; + + /* +* Any session set property which is different in 3XX packetization +* should be added as a new case below. All unchanged session set +* properties will be handled in the default case. +*/ + switch (ptype) { + case HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL: { + struct hfi_buffer_count_actual *in = pdata; + struct hfi_buffer_count_actual_4xx *count = prop_data; + + count->count_actual = in->count_actual; + count->type = in->type; + count->count_min_host = in->count_actual; + pkt->shdr.hdr.size += sizeof(u32) + sizeof(*count); + break; + } + case HFI_PROPERTY_PARAM_WORK_MODE: { + struct hfi_video_work_mode *in = pdata, *wm = prop_data; + + wm->video_work_mode = in->video_work_mode; + pkt->shdr.hdr.size += sizeof(u32) + sizeof(*wm); + break; + } + case HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE: { + struct hfi_videocores_usage_type *in = pdata, *cu = prop_data; + + cu->video_core_enable_mask = in->video_core_enable_mask; + pkt->shdr.hdr.size += sizeof(u32) + sizeof(*cu); + break; + } + case HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE: + /* not implemented on Venus 4xx */ + break; + default: + ret = pkt_session_set_property_3xx(pkt, cookie, ptype, pdata); + break; + } + + return ret; +} + int pkt_session_get_property(struct hfi_session_get_property_pkt *pkt, void *cookie, u32 ptype) { @@ -1181,7 +1240,10 @@ int pkt_session_set_property(struct hfi_session_set_property_pkt *pkt, if (hfi_ver == HFI_VERSION_1XX) return pkt_session_set_property_1x(pkt, cookie, ptype, pdata); - return pkt_session_set_property_3xx(pkt, cookie, ptype, pdata); + if (hfi_ver == HFI_VERSION_3XX) + return pkt_session_set_property_3xx(pkt, cookie, ptype, pdata); + + return pkt_session_set_property_4xx(pkt, cookie, ptype, pdata); } void pkt_set_version(enum hfi_version version) -- 2.14.1
[PATCH 21/28] venus: helpers: extend set_num_bufs helper with one more argument
Extend venus_helper_set_num_bufs() helper function with one more argument to set number of output buffers for the secondary decoder output. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/helpers.c | 16 ++-- drivers/media/platform/qcom/venus/helpers.h | 3 ++- drivers/media/platform/qcom/venus/vdec.c| 2 +- drivers/media/platform/qcom/venus/venc.c| 2 +- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index adf8701a64bb..f04d16953b3a 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -513,7 +513,8 @@ int venus_helper_set_core_usage(struct venus_inst *inst, u32 usage) EXPORT_SYMBOL_GPL(venus_helper_set_core_usage); int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, - unsigned int output_bufs) + unsigned int output_bufs, + unsigned int output2_bufs) { u32 ptype = HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL; struct hfi_buffer_count_actual buf_count; @@ -529,7 +530,18 @@ int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, buf_count.type = HFI_BUFFER_OUTPUT; buf_count.count_actual = output_bufs; - return hfi_session_set_property(inst, ptype, _count); + ret = hfi_session_set_property(inst, ptype, _count); + if (ret) + return ret; + + if (output2_bufs) { + buf_count.type = HFI_BUFFER_OUTPUT2; + buf_count.count_actual = output2_bufs; + + ret = hfi_session_set_property(inst, ptype, _count); + } + + return ret; } EXPORT_SYMBOL_GPL(venus_helper_set_num_bufs); diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h index d5e727e1ecab..8ff4bd3ef958 100644 --- a/drivers/media/platform/qcom/venus/helpers.h +++ b/drivers/media/platform/qcom/venus/helpers.h @@ -41,7 +41,8 @@ int venus_helper_set_output_resolution(struct venus_inst *inst, int venus_helper_set_work_mode(struct venus_inst *inst, u32 mode); int venus_helper_set_core_usage(struct venus_inst *inst, u32 usage); int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, - unsigned int output_bufs); + unsigned int output_bufs, + unsigned int output2_bufs); int venus_helper_set_raw_format(struct venus_inst *inst, u32 hfi_format, u32 buftype); int venus_helper_set_color_format(struct venus_inst *inst, u32 fmt); diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index ceaf1a338eb3..8d188b11b85a 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -758,7 +758,7 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count) goto deinit_sess; ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs, - VB2_MAX_FRAME); + VB2_MAX_FRAME, VB2_MAX_FRAME); if (ret) goto deinit_sess; diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index 3b3299bff1cd..c9c40d1ce7c6 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -963,7 +963,7 @@ static int venc_start_streaming(struct vb2_queue *q, unsigned int count) goto deinit_sess; ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs, - inst->num_output_bufs); + inst->num_output_bufs, 0); if (ret) goto deinit_sess; -- 2.14.1
[PATCH 12/28] venus: helpers: make a commmon function for power_enable
Make common function which will enable power when enabling/disabling clocks and also covers Venus 3xx/4xx versions. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/helpers.c | 51 + drivers/media/platform/qcom/venus/helpers.h | 2 ++ drivers/media/platform/qcom/venus/vdec.c| 25 -- drivers/media/platform/qcom/venus/venc.c| 25 -- 4 files changed, 67 insertions(+), 36 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index d9065cc8a7d3..2b21f6ed7502 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -13,6 +13,7 @@ * */ #include +#include #include #include #include @@ -24,6 +25,7 @@ #include "core.h" #include "helpers.h" #include "hfi_helper.h" +#include "hfi_venus_io.h" struct intbuf { struct list_head list; @@ -781,3 +783,52 @@ void venus_helper_init_instance(struct venus_inst *inst) } } EXPORT_SYMBOL_GPL(venus_helper_init_instance); + +int venus_helper_power_enable(struct venus_core *core, u32 session_type, + bool enable) +{ + void __iomem *ctrl, *stat; + u32 val; + int ret; + + if (!IS_V3(core) && !IS_V4(core)) + return -EINVAL; + + if (IS_V3(core)) { + if (session_type == VIDC_SESSION_TYPE_DEC) + ctrl = core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL; + else + ctrl = core->base + WRAPPER_VENC_VCODEC_POWER_CONTROL; + if (enable) + writel(0, ctrl); + else + writel(1, ctrl); + + return 0; + } + + if (session_type == VIDC_SESSION_TYPE_DEC) { + ctrl = core->base + WRAPPER_VCODEC0_MMCC_POWER_CONTROL; + stat = core->base + WRAPPER_VCODEC0_MMCC_POWER_STATUS; + } else { + ctrl = core->base + WRAPPER_VCODEC1_MMCC_POWER_CONTROL; + stat = core->base + WRAPPER_VCODEC1_MMCC_POWER_STATUS; + } + + if (enable) { + writel(0, ctrl); + + ret = readl_poll_timeout(stat, val, val & BIT(1), 1, 100); + if (ret) + return ret; + } else { + writel(1, ctrl); + + ret = readl_poll_timeout(stat, val, !(val & BIT(1)), 1, 100); + if (ret) + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(venus_helper_power_enable); diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h index 971392be5df5..0e64aa95624a 100644 --- a/drivers/media/platform/qcom/venus/helpers.h +++ b/drivers/media/platform/qcom/venus/helpers.h @@ -43,4 +43,6 @@ int venus_helper_set_color_format(struct venus_inst *inst, u32 fmt); void venus_helper_acquire_buf_ref(struct vb2_v4l2_buffer *vbuf); void venus_helper_release_buf_ref(struct venus_inst *inst, unsigned int idx); void venus_helper_init_instance(struct venus_inst *inst); +int venus_helper_power_enable(struct venus_core *core, u32 session_type, + bool enable); #endif diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index cd278a695899..0ddc2c4df934 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -1131,26 +1131,21 @@ static int vdec_remove(struct platform_device *pdev) static __maybe_unused int vdec_runtime_suspend(struct device *dev) { struct venus_core *core = dev_get_drvdata(dev); + int ret; if (IS_V1(core)) return 0; - if (IS_V3(core)) - writel(0, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); - else if (IS_V4(core)) - writel(0, core->base + WRAPPER_VCODEC0_MMCC_POWER_CONTROL); + ret = venus_helper_power_enable(core, VIDC_SESSION_TYPE_DEC, true); if (IS_V4(core)) clk_disable_unprepare(core->core0_bus_clk); clk_disable_unprepare(core->core0_clk); - if (IS_V3(core)) - writel(1, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); - else if (IS_V4(core)) - writel(1, core->base + WRAPPER_VCODEC0_MMCC_POWER_CONTROL); + ret |= venus_helper_power_enable(core, VIDC_SESSION_TYPE_DEC, false); - return 0; + return ret; } static __maybe_unused int vdec_runtime_resume(struct device *dev) @@ -1161,20 +1156,14 @@ static __maybe_unused int vdec_runtime_resume(struct device *dev) if (IS_V1(core)) return 0; - if (IS_V3(core)) - writel(0, core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL); -
[PATCH 19/28] venus: helpers: add a new helper to set raw format
The new helper will has one more argument for buffer type, that way the decoder can configure the format on it's secondary output. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/helpers.c | 52 ++--- drivers/media/platform/qcom/venus/helpers.h | 2 ++ 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 5512fbfdebb9..0d55604f7484 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -410,6 +410,20 @@ static int session_register_bufs(struct venus_inst *inst) return ret; } +static u32 to_hfi_raw_fmt(u32 v4l2_fmt) +{ + switch (v4l2_fmt) { + case V4L2_PIX_FMT_NV12: + return HFI_COLOR_FORMAT_NV12; + case V4L2_PIX_FMT_NV21: + return HFI_COLOR_FORMAT_NV21; + default: + break; + } + + return 0; +} + int venus_helper_get_bufreq(struct venus_inst *inst, u32 type, struct hfi_buffer_requirements *req) { @@ -491,35 +505,35 @@ int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, } EXPORT_SYMBOL_GPL(venus_helper_set_num_bufs); -int venus_helper_set_color_format(struct venus_inst *inst, u32 pixfmt) +int venus_helper_set_raw_format(struct venus_inst *inst, u32 hfi_format, + u32 buftype) { - struct hfi_uncompressed_format_select fmt; u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT; - int ret; + struct hfi_uncompressed_format_select fmt; + + fmt.buffer_type = buftype; + fmt.format = hfi_format; + + return hfi_session_set_property(inst, ptype, ); +} +EXPORT_SYMBOL_GPL(venus_helper_set_raw_format); + +int venus_helper_set_color_format(struct venus_inst *inst, u32 pixfmt) +{ + u32 hfi_format, buftype; if (inst->session_type == VIDC_SESSION_TYPE_DEC) - fmt.buffer_type = HFI_BUFFER_OUTPUT; + buftype = HFI_BUFFER_OUTPUT; else if (inst->session_type == VIDC_SESSION_TYPE_ENC) - fmt.buffer_type = HFI_BUFFER_INPUT; + buftype = HFI_BUFFER_INPUT; else return -EINVAL; - switch (pixfmt) { - case V4L2_PIX_FMT_NV12: - fmt.format = HFI_COLOR_FORMAT_NV12; - break; - case V4L2_PIX_FMT_NV21: - fmt.format = HFI_COLOR_FORMAT_NV21; - break; - default: + hfi_format = to_hfi_raw_fmt(pixfmt); + if (!hfi_format) return -EINVAL; - } - ret = hfi_session_set_property(inst, ptype, ); - if (ret) - return ret; - - return 0; + return venus_helper_set_raw_format(inst, hfi_format, buftype); } EXPORT_SYMBOL_GPL(venus_helper_set_color_format); diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h index 0de9989adcdb..79af7845efbd 100644 --- a/drivers/media/platform/qcom/venus/helpers.h +++ b/drivers/media/platform/qcom/venus/helpers.h @@ -40,6 +40,8 @@ int venus_helper_set_output_resolution(struct venus_inst *inst, u32 buftype); int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, unsigned int output_bufs); +int venus_helper_set_raw_format(struct venus_inst *inst, u32 hfi_format, + u32 buftype); int venus_helper_set_color_format(struct venus_inst *inst, u32 fmt); int venus_helper_set_dyn_bufmode(struct venus_inst *inst); int venus_helper_set_bufsize(struct venus_inst *inst, u32 bufsize, u32 buftype); -- 2.14.1
[PATCH 18/28] venus: helpers: add buffer type argument to a helper
This adds one more function argument to pass buffer type to set_output_resolution() helper function. That is a preparation to support secondary decoder output. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/helpers.c | 5 +++-- drivers/media/platform/qcom/venus/helpers.h | 3 ++- drivers/media/platform/qcom/venus/venc.c| 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 94664a3ce3e2..5512fbfdebb9 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -456,12 +456,13 @@ int venus_helper_set_input_resolution(struct venus_inst *inst, EXPORT_SYMBOL_GPL(venus_helper_set_input_resolution); int venus_helper_set_output_resolution(struct venus_inst *inst, - unsigned int width, unsigned int height) + unsigned int width, unsigned int height, + u32 buftype) { u32 ptype = HFI_PROPERTY_PARAM_FRAME_SIZE; struct hfi_framesize fs; - fs.buffer_type = HFI_BUFFER_OUTPUT; + fs.buffer_type = buftype; fs.width = width; fs.height = height; diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h index cd306bd8978f..0de9989adcdb 100644 --- a/drivers/media/platform/qcom/venus/helpers.h +++ b/drivers/media/platform/qcom/venus/helpers.h @@ -36,7 +36,8 @@ int venus_helper_get_bufreq(struct venus_inst *inst, u32 type, int venus_helper_set_input_resolution(struct venus_inst *inst, unsigned int width, unsigned int height); int venus_helper_set_output_resolution(struct venus_inst *inst, - unsigned int width, unsigned int height); + unsigned int width, unsigned int height, + u32 buftype); int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, unsigned int output_bufs); int venus_helper_set_color_format(struct venus_inst *inst, u32 fmt); diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index f87d891325ea..8970f14b3a82 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -795,7 +795,8 @@ static int venc_init_session(struct venus_inst *inst) goto deinit; ret = venus_helper_set_output_resolution(inst, inst->width, -inst->height); +inst->height, +HFI_BUFFER_OUTPUT); if (ret) goto deinit; -- 2.14.1
[PATCH 17/28] venus: delete no longer used bufmode flag from instance
Delete no longer used flag cap_bufs_mode_dynamic from instance structure. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/core.h | 2 -- drivers/media/platform/qcom/venus/hfi_parser.c | 6 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index c46334454cd9..255292899204 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -249,7 +249,6 @@ struct venus_buffer { * @priv: a private for HFI operations callbacks * @session_type: the type of the session (decoder or encoder) * @hprop: a union used as a holder by get property - * @cap_bufs_mode_dynamic: buffers allocation mode capability */ struct venus_inst { struct list_head list; @@ -298,7 +297,6 @@ struct venus_inst { const struct hfi_inst_ops *ops; u32 session_type; union hfi_get_property hprop; - bool cap_bufs_mode_dynamic; }; #define IS_V1(core)((core)->res->hfi_version == HFI_VERSION_1XX) diff --git a/drivers/media/platform/qcom/venus/hfi_parser.c b/drivers/media/platform/qcom/venus/hfi_parser.c index 4b155997abbb..ac92fd347ce1 100644 --- a/drivers/media/platform/qcom/venus/hfi_parser.c +++ b/drivers/media/platform/qcom/venus/hfi_parser.c @@ -74,13 +74,9 @@ static void parse_alloc_mode(struct venus_core *core, struct venus_inst *inst, 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; - + mode->buffer_type == HFI_BUFFER_OUTPUT2) for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain, fill_buf_mode, type, 1); - } type++; } -- 2.14.1
[PATCH 15/28] venus: add a helper function to set dynamic buffer mode
Adds a new helper function to set dymaic buffer mode if it is supported by current HFI version. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/helpers.c | 22 ++ drivers/media/platform/qcom/venus/helpers.h | 1 + drivers/media/platform/qcom/venus/vdec.c| 15 +++ 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 1eda19adbf28..824ad4d2d064 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -522,6 +522,28 @@ int venus_helper_set_color_format(struct venus_inst *inst, u32 pixfmt) } EXPORT_SYMBOL_GPL(venus_helper_set_color_format); +int venus_helper_set_dyn_bufmode(struct venus_inst *inst) +{ + u32 ptype = HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE; + struct hfi_buffer_alloc_mode mode; + int ret; + + if (!is_dynamic_bufmode(inst)) + return 0; + + mode.type = HFI_BUFFER_OUTPUT; + mode.mode = HFI_BUFFER_MODE_DYNAMIC; + + ret = hfi_session_set_property(inst, ptype, ); + if (ret) + return ret; + + mode.type = HFI_BUFFER_OUTPUT2; + + return hfi_session_set_property(inst, ptype, ); +} +EXPORT_SYMBOL_GPL(venus_helper_set_dyn_bufmode); + static void delayed_process_buf_func(struct work_struct *work) { struct venus_buffer *buf, *n; diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h index 0e64aa95624a..52b961ed491e 100644 --- a/drivers/media/platform/qcom/venus/helpers.h +++ b/drivers/media/platform/qcom/venus/helpers.h @@ -40,6 +40,7 @@ int venus_helper_set_output_resolution(struct venus_inst *inst, int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, unsigned int output_bufs); int venus_helper_set_color_format(struct venus_inst *inst, u32 fmt); +int venus_helper_set_dyn_bufmode(struct venus_inst *inst); void venus_helper_acquire_buf_ref(struct vb2_v4l2_buffer *vbuf); void venus_helper_release_buf_ref(struct venus_inst *inst, unsigned int idx); void venus_helper_init_instance(struct venus_inst *inst); diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 0ddc2c4df934..1de9cc64cf2f 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -557,18 +557,9 @@ static int vdec_set_properties(struct venus_inst *inst) return ret; } - if (core->res->hfi_version == HFI_VERSION_3XX || - inst->cap_bufs_mode_dynamic) { - struct hfi_buffer_alloc_mode mode; - - ptype = HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE; - mode.type = HFI_BUFFER_OUTPUT; - mode.mode = HFI_BUFFER_MODE_DYNAMIC; - - ret = hfi_session_set_property(inst, ptype, ); - if (ret) - return ret; - } + ret = venus_helper_set_dyn_bufmode(inst); + if (ret) + return ret; if (ctr->post_loop_deb_mode) { ptype = HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER; -- 2.14.1
[PATCH 14/28] venus: helpers: rename a helper function and use buffer mode from caps
Rename is_reg_unreg_needed() to better name is_dynamic_bufmode() and use buffer mode from enumerated per codec capabilities. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/helpers.c | 21 +++-- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 2b21f6ed7502..1eda19adbf28 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -354,18 +354,19 @@ session_process_buf(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf) return 0; } -static inline int is_reg_unreg_needed(struct venus_inst *inst) +static inline int is_dynamic_bufmode(struct venus_inst *inst) { - if (inst->session_type == VIDC_SESSION_TYPE_DEC && - inst->core->res->hfi_version == HFI_VERSION_3XX) - return 0; + struct venus_core *core = inst->core; + struct venus_caps *caps; - if (inst->session_type == VIDC_SESSION_TYPE_DEC && - inst->cap_bufs_mode_dynamic && - inst->core->res->hfi_version == HFI_VERSION_1XX) + caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type); + if (!caps) return 0; - return 1; + if (caps->cap_bufs_mode_dynamic) + return 1; + + return 0; } static int session_unregister_bufs(struct venus_inst *inst) @@ -374,7 +375,7 @@ static int session_unregister_bufs(struct venus_inst *inst) struct hfi_buffer_desc bd; int ret = 0; - if (!is_reg_unreg_needed(inst)) + if (is_dynamic_bufmode(inst)) return 0; list_for_each_entry_safe(buf, n, >registeredbufs, reg_list) { @@ -394,7 +395,7 @@ static int session_register_bufs(struct venus_inst *inst) struct venus_buffer *buf; int ret = 0; - if (!is_reg_unreg_needed(inst)) + if (is_dynamic_bufmode(inst)) return 0; list_for_each_entry(buf, >registeredbufs, reg_list) { -- 2.14.1
[PATCH 13/28] venus: core: delete not used flag for buffer mode
Delete not used flag for capture buffer allocation mode. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/core.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index fe2d2b9e8af8..c46334454cd9 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -249,7 +249,6 @@ struct venus_buffer { * @priv: a private for HFI operations callbacks * @session_type: the type of the session (decoder or encoder) * @hprop: a union used as a holder by get property - * @cap_bufs_mode_static: buffers allocation mode capability * @cap_bufs_mode_dynamic: buffers allocation mode capability */ struct venus_inst { @@ -299,7 +298,6 @@ struct venus_inst { const struct hfi_inst_ops *ops; u32 session_type; union hfi_get_property hprop; - bool cap_bufs_mode_static; bool cap_bufs_mode_dynamic; }; -- 2.14.1
[PATCH 27/28] venus: add sdm845 compatible and resource data
This adds sdm845 DT compatible string with it's resource data table. Cc: devicet...@vger.kernel.org Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- .../devicetree/bindings/media/qcom,venus.txt | 1 + drivers/media/platform/qcom/venus/core.c | 22 ++ 2 files changed, 23 insertions(+) diff --git a/Documentation/devicetree/bindings/media/qcom,venus.txt b/Documentation/devicetree/bindings/media/qcom,venus.txt index 2693449daf73..00d0d1bf7647 100644 --- a/Documentation/devicetree/bindings/media/qcom,venus.txt +++ b/Documentation/devicetree/bindings/media/qcom,venus.txt @@ -6,6 +6,7 @@ Definition: Value should contain one of: - "qcom,msm8916-venus" - "qcom,msm8996-venus" + - "qcom,sdm845-venus" - reg: Usage: required Value type: diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index 1b72bfbb6297..13084880cc42 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -445,9 +445,31 @@ static const struct venus_resources msm8996_res = { .fwname = "qcom/venus-4.2/venus.mdt", }; +static const struct freq_tbl sdm845_freq_table[] = { + { 1944000, 38000 }, /* 4k UHD @ 60 */ + { 972000, 32000 }, /* 4k UHD @ 30 */ + { 489600, 2 }, /* 1080p @ 60 */ + { 244800, 1 }, /* 1080p @ 30 */ +}; + +static const struct venus_resources sdm845_res = { + .freq_tbl = sdm845_freq_table, + .freq_tbl_size = ARRAY_SIZE(sdm845_freq_table), + .clks = {"core", "iface", "bus" }, + .clks_num = 3, + .max_load = 2563200, + .hfi_version = HFI_VERSION_4XX, + .vmem_id = VIDC_RESOURCE_NONE, + .vmem_size = 0, + .vmem_addr = 0, + .dma_mask = 0xe000 - 1, + .fwname = "qcom/venus-5.2/venus.mdt", +}; + static const struct of_device_id venus_dt_match[] = { { .compatible = "qcom,msm8916-venus", .data = _res, }, { .compatible = "qcom,msm8996-venus", .data = _res, }, + { .compatible = "qcom,sdm845-venus", .data = _res, }, { } }; MODULE_DEVICE_TABLE(of, venus_dt_match); -- 2.14.1
[PATCH 20/28] venus: helpers,vdec,venc: add helpers to set work mode and core usage
These are new properties applicable to Venus version 4xx. Add the helpers and call them from decoder and encoder drivers. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/helpers.c | 28 drivers/media/platform/qcom/venus/helpers.h | 2 ++ drivers/media/platform/qcom/venus/vdec.c| 8 drivers/media/platform/qcom/venus/venc.c| 8 4 files changed, 46 insertions(+) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 0d55604f7484..adf8701a64bb 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -484,6 +484,34 @@ int venus_helper_set_output_resolution(struct venus_inst *inst, } EXPORT_SYMBOL_GPL(venus_helper_set_output_resolution); +int venus_helper_set_work_mode(struct venus_inst *inst, u32 mode) +{ + u32 ptype = HFI_PROPERTY_PARAM_WORK_MODE; + struct hfi_video_work_mode wm; + + if (!IS_V4(inst->core)) + return 0; + + wm.video_work_mode = mode; + + return hfi_session_set_property(inst, ptype, ); +} +EXPORT_SYMBOL_GPL(venus_helper_set_work_mode); + +int venus_helper_set_core_usage(struct venus_inst *inst, u32 usage) +{ + u32 ptype = HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE; + struct hfi_videocores_usage_type cu; + + if (!IS_V4(inst->core)) + return 0; + + cu.video_core_enable_mask = usage; + + return hfi_session_set_property(inst, ptype, ); +} +EXPORT_SYMBOL_GPL(venus_helper_set_core_usage); + int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, unsigned int output_bufs) { diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h index 79af7845efbd..d5e727e1ecab 100644 --- a/drivers/media/platform/qcom/venus/helpers.h +++ b/drivers/media/platform/qcom/venus/helpers.h @@ -38,6 +38,8 @@ int venus_helper_set_input_resolution(struct venus_inst *inst, int venus_helper_set_output_resolution(struct venus_inst *inst, unsigned int width, unsigned int height, u32 buftype); +int venus_helper_set_work_mode(struct venus_inst *inst, u32 mode); +int venus_helper_set_core_usage(struct venus_inst *inst, u32 usage); int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, unsigned int output_bufs); int venus_helper_set_raw_format(struct venus_inst *inst, u32 hfi_format, diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index b43607dee4fe..ceaf1a338eb3 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -550,6 +550,14 @@ static int vdec_set_properties(struct venus_inst *inst) u32 ptype; int ret; + ret = venus_helper_set_work_mode(inst, VIDC_WORK_MODE_2); + if (ret) + return ret; + + ret = venus_helper_set_core_usage(inst, VIDC_CORE_ID_1); + if (ret) + return ret; + if (core->res->hfi_version == HFI_VERSION_1XX) { ptype = HFI_PROPERTY_PARAM_VDEC_CONTINUE_DATA_TRANSFER; ret = hfi_session_set_property(inst, ptype, ); diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index 8970f14b3a82..3b3299bff1cd 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -643,6 +643,14 @@ static int venc_set_properties(struct venus_inst *inst) u32 ptype, rate_control, bitrate, profile = 0, level = 0; int ret; + ret = venus_helper_set_work_mode(inst, VIDC_WORK_MODE_2); + if (ret) + return ret; + + ret = venus_helper_set_core_usage(inst, VIDC_CORE_ID_2); + if (ret) + return ret; + ptype = HFI_PROPERTY_CONFIG_FRAME_RATE; frate.buffer_type = HFI_BUFFER_OUTPUT; frate.framerate = inst->fps * (1 << 16); -- 2.14.1
[PATCH 26/28] venus: implementing multi-stream support
This is implementing a multi-stream decoder support. The multi stream gives an option to use the secondary decoder output with different raw format (or the same in case of crop). Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/core.h| 1 + drivers/media/platform/qcom/venus/helpers.c | 204 +++- drivers/media/platform/qcom/venus/helpers.h | 6 + drivers/media/platform/qcom/venus/vdec.c| 91 - drivers/media/platform/qcom/venus/venc.c| 1 + 5 files changed, 299 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 4d6c05f156c4..85e66e2dd672 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -259,6 +259,7 @@ struct venus_inst { struct list_head list; struct mutex lock; struct venus_core *core; + struct list_head dpbbufs; struct list_head internalbufs; struct list_head registeredbufs; struct list_head delayed_process; diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index ed569705ecac..87dcf9973e6f 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -85,6 +85,112 @@ bool venus_helper_check_codec(struct venus_inst *inst, u32 v4l2_pixfmt) } EXPORT_SYMBOL_GPL(venus_helper_check_codec); +static int venus_helper_queue_dpb_bufs(struct venus_inst *inst) +{ + struct intbuf *buf; + int ret = 0; + + if (list_empty(>dpbbufs)) + return 0; + + list_for_each_entry(buf, >dpbbufs, list) { + struct hfi_frame_data fdata; + + memset(, 0, sizeof(fdata)); + fdata.alloc_len = buf->size; + fdata.device_addr = buf->da; + fdata.buffer_type = buf->type; + + ret = hfi_session_process_buf(inst, ); + if (ret) + goto fail; + } + +fail: + return ret; +} + +int venus_helper_free_dpb_bufs(struct venus_inst *inst) +{ + struct intbuf *buf, *n; + + if (list_empty(>dpbbufs)) + return 0; + + list_for_each_entry_safe(buf, n, >dpbbufs, list) { + list_del_init(>list); + dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da, + buf->attrs); + kfree(buf); + } + + INIT_LIST_HEAD(>dpbbufs); + + return 0; +} +EXPORT_SYMBOL_GPL(venus_helper_free_dpb_bufs); + +int venus_helper_alloc_dpb_bufs(struct venus_inst *inst) +{ + struct venus_core *core = inst->core; + struct device *dev = core->dev; + enum hfi_version ver = core->res->hfi_version; + struct hfi_buffer_requirements bufreq; + u32 buftype = inst->dpb_buftype; + unsigned int dpb_size = 0; + struct intbuf *buf; + unsigned int i; + u32 count; + int ret; + + /* no need to allocate dpb buffers */ + if (!inst->dpb_fmt) + return 0; + + if (inst->dpb_buftype == HFI_BUFFER_OUTPUT) + dpb_size = inst->output_buf_size; + else if (inst->dpb_buftype == HFI_BUFFER_OUTPUT2) + dpb_size = inst->output2_buf_size; + + if (!dpb_size) + return 0; + + ret = venus_helper_get_bufreq(inst, buftype, ); + if (ret) + return ret; + + count = HFI_BUFREQ_COUNT_MIN(, ver); + + for (i = 0; i < count; i++) { + buf = kzalloc(sizeof(*buf), GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto fail; + } + + buf->type = buftype; + buf->size = dpb_size; + buf->attrs = DMA_ATTR_WRITE_COMBINE | +DMA_ATTR_NO_KERNEL_MAPPING; + buf->va = dma_alloc_attrs(dev, buf->size, >da, GFP_KERNEL, + buf->attrs); + if (!buf->va) { + kfree(buf); + ret = -ENOMEM; + goto fail; + } + + list_add_tail(>list, >dpbbufs); + } + + return 0; + +fail: + venus_helper_free_dpb_bufs(inst); + return ret; +} +EXPORT_SYMBOL_GPL(venus_helper_alloc_dpb_bufs); + static int intbufs_set_buffer(struct venus_inst *inst, u32 type) { struct venus_core *core = inst->core; @@ -342,7 +448,10 @@ session_process_buf(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf) if (vbuf->flags & V4L2_BUF_FLAG_LAST || !fdata.filled_len) fdata.flags |= HFI_BUFFERFLAG_EOS; } else if (type == V4L2_BU
[PATCH 23/28] venus: vdec: get required input buffers as well
Rework and rename vdec_cap_num_buffers() to get the number of input buffers too. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/vdec.c | 41 +++- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 8d188b11b85a..6ed9b7c4bd6e 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -603,19 +603,32 @@ static int vdec_init_session(struct venus_inst *inst) return ret; } -static int vdec_cap_num_buffers(struct venus_inst *inst, unsigned int *num) +static int vdec_num_buffers(struct venus_inst *inst, unsigned int *in_num, + unsigned int *out_num) { + enum hfi_version ver = inst->core->res->hfi_version; struct hfi_buffer_requirements bufreq; int ret; + *in_num = *out_num = 0; + ret = vdec_init_session(inst); if (ret) return ret; + ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, ); + if (ret) + goto deinit; + + *in_num = HFI_BUFREQ_COUNT_MIN(, ver); + ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, ); + if (ret) + goto deinit; - *num = bufreq.count_actual; + *out_num = HFI_BUFREQ_COUNT_MIN(, ver); +deinit: hfi_session_deinit(inst); return ret; @@ -626,7 +639,7 @@ static int vdec_queue_setup(struct vb2_queue *q, unsigned int sizes[], struct device *alloc_devs[]) { struct venus_inst *inst = vb2_get_drv_priv(q); - unsigned int p, num; + unsigned int p, in_num, out_num; int ret = 0; if (*num_planes) { @@ -649,35 +662,29 @@ static int vdec_queue_setup(struct vb2_queue *q, return 0; } + ret = vdec_num_buffers(inst, _num, _num); + if (ret) + return ret; + switch (q->type) { case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: *num_planes = inst->fmt_out->num_planes; sizes[0] = get_framesize_compressed(inst->out_width, inst->out_height); inst->input_buf_size = sizes[0]; + *num_buffers = max(*num_buffers, in_num); inst->num_input_bufs = *num_buffers; - - ret = vdec_cap_num_buffers(inst, ); - if (ret) - break; - - inst->num_output_bufs = num; + inst->num_output_bufs = out_num; break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: *num_planes = inst->fmt_cap->num_planes; - ret = vdec_cap_num_buffers(inst, ); - if (ret) - break; - - *num_buffers = max(*num_buffers, num); - for (p = 0; p < *num_planes; p++) sizes[p] = get_framesize_uncompressed(p, inst->width, inst->height); - - inst->num_output_bufs = *num_buffers; inst->output_buf_size = sizes[0]; + *num_buffers = max(*num_buffers, out_num); + inst->num_output_bufs = *num_buffers; break; default: ret = -EINVAL; -- 2.14.1
[PATCH 22/28] venus: helpers: add a helper to return opb buffer sizes
Add a helper function to return current output picture buffer size. OPB sizes can vary depending on the selected decoder output(s). Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/core.h| 10 ++ drivers/media/platform/qcom/venus/helpers.c | 15 +++ drivers/media/platform/qcom/venus/helpers.h | 1 + 3 files changed, 26 insertions(+) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 255292899204..4d6c05f156c4 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -234,6 +234,11 @@ struct venus_buffer { * @num_output_bufs: holds number of output buffers * @input_buf_size holds input buffer size * @output_buf_size: holds output buffer size + * @output2_buf_size: holds secondary decoder output buffer size + * @dpb_buftype: decoded picture buffer type + * @dpb_fmt: decodec picture buffre raw format + * @opb_buftype: output picture buffer type + * @opb_fmt: output picture buffer raw format * @reconfig: a flag raised by decoder when the stream resolution changed * @reconfig_width:holds the new width * @reconfig_height: holds the new height @@ -282,6 +287,11 @@ struct venus_inst { unsigned int num_output_bufs; unsigned int input_buf_size; unsigned int output_buf_size; + unsigned int output2_buf_size; + u32 dpb_buftype; + u32 dpb_fmt; + u32 opb_buftype; + u32 opb_fmt; bool reconfig; u32 reconfig_width; u32 reconfig_height; diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index f04d16953b3a..f0a0fca60c76 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -611,6 +611,21 @@ int venus_helper_set_bufsize(struct venus_inst *inst, u32 bufsize, u32 buftype) } EXPORT_SYMBOL_GPL(venus_helper_set_bufsize); +unsigned int venus_helper_get_opb_size(struct venus_inst *inst) +{ + /* the encoder has only one output */ + if (inst->session_type == VIDC_SESSION_TYPE_ENC) + return inst->output_buf_size; + + if (inst->opb_buftype == HFI_BUFFER_OUTPUT) + return inst->output_buf_size; + else if (inst->opb_buftype == HFI_BUFFER_OUTPUT2) + return inst->output2_buf_size; + + return 0; +} +EXPORT_SYMBOL_GPL(venus_helper_get_opb_size); + static void delayed_process_buf_func(struct work_struct *work) { struct venus_buffer *buf, *n; diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h index 8ff4bd3ef958..92be45894a69 100644 --- a/drivers/media/platform/qcom/venus/helpers.h +++ b/drivers/media/platform/qcom/venus/helpers.h @@ -48,6 +48,7 @@ int venus_helper_set_raw_format(struct venus_inst *inst, u32 hfi_format, int venus_helper_set_color_format(struct venus_inst *inst, u32 fmt); int venus_helper_set_dyn_bufmode(struct venus_inst *inst); int venus_helper_set_bufsize(struct venus_inst *inst, u32 bufsize, u32 buftype); +unsigned int venus_helper_get_opb_size(struct venus_inst *inst); void venus_helper_acquire_buf_ref(struct vb2_v4l2_buffer *vbuf); void venus_helper_release_buf_ref(struct venus_inst *inst, unsigned int idx); void venus_helper_init_instance(struct venus_inst *inst); -- 2.14.1
[PATCH 24/28] venus: vdec: new function for output configuration
Make a new function vdec_output_conf() for decoder output configuration. vdec_output_conf() will set properties via HFI interface related to the output configuration, and keep vdec_set_properties() which will set properties related to decoding parameters. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/vdec.c | 35 ++-- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 6ed9b7c4bd6e..ced3330c396a 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -545,6 +545,23 @@ static const struct v4l2_ioctl_ops vdec_ioctl_ops = { static int vdec_set_properties(struct venus_inst *inst) { struct vdec_controls *ctr = >controls.dec; + struct hfi_enable en = { .enable = 1 }; + u32 ptype; + int ret; + + if (ctr->post_loop_deb_mode) { + ptype = HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER; + en.enable = 1; + ret = hfi_session_set_property(inst, ptype, ); + if (ret) + return ret; + } + + return 0; +} + +static int vdec_output_conf(struct venus_inst *inst) +{ struct venus_core *core = inst->core; struct hfi_enable en = { .enable = 1 }; u32 ptype; @@ -569,14 +586,6 @@ static int vdec_set_properties(struct venus_inst *inst) if (ret) return ret; - if (ctr->post_loop_deb_mode) { - ptype = HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER; - en.enable = 1; - ret = hfi_session_set_property(inst, ptype, ); - if (ret) - return ret; - } - return 0; } @@ -724,7 +733,6 @@ static int vdec_verify_conf(struct venus_inst *inst) static int vdec_start_streaming(struct vb2_queue *q, unsigned int count) { struct venus_inst *inst = vb2_get_drv_priv(q); - struct venus_core *core = inst->core; int ret; mutex_lock(>lock); @@ -753,12 +761,9 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count) if (ret) goto deinit_sess; - if (core->res->hfi_version == HFI_VERSION_3XX) { - ret = venus_helper_set_bufsize(inst, inst->output_buf_size, - HFI_BUFFER_OUTPUT); - if (ret) - goto deinit_sess; - } + ret = vdec_output_conf(inst); + if (ret) + goto deinit_sess; ret = vdec_verify_conf(inst); if (ret) -- 2.14.1
[PATCH 25/28] venus: move frame size calculations in common place
move calculations of raw and compressed in a common helper and make it identical for encoder and decoder. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/helpers.c | 98 + drivers/media/platform/qcom/venus/helpers.h | 2 + drivers/media/platform/qcom/venus/vdec.c| 54 drivers/media/platform/qcom/venus/venc.c| 56 - 4 files changed, 126 insertions(+), 84 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index f0a0fca60c76..ed569705ecac 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -455,6 +455,104 @@ int venus_helper_get_bufreq(struct venus_inst *inst, u32 type, } EXPORT_SYMBOL_GPL(venus_helper_get_bufreq); +static u32 get_framesize_raw_nv12(u32 width, u32 height) +{ + u32 y_stride, uv_stride, y_plane; + u32 y_sclines, uv_sclines, uv_plane; + u32 size; + + y_stride = ALIGN(width, 128); + uv_stride = ALIGN(width, 128); + y_sclines = ALIGN(height, 32); + uv_sclines = ALIGN(((height + 1) >> 1), 16); + + y_plane = y_stride * y_sclines; + uv_plane = uv_stride * uv_sclines + SZ_4K; + size = y_plane + uv_plane + SZ_8K; + + return ALIGN(size, SZ_4K); +} + +static u32 get_framesize_raw_nv12_ubwc(u32 width, u32 height) +{ + u32 y_meta_stride, y_meta_plane; + u32 y_stride, y_plane; + u32 uv_meta_stride, uv_meta_plane; + u32 uv_stride, uv_plane; + u32 extradata = SZ_16K; + + y_meta_stride = ALIGN(DIV_ROUND_UP(width, 32), 64); + y_meta_plane = y_meta_stride * ALIGN(DIV_ROUND_UP(height, 8), 16); + y_meta_plane = ALIGN(y_meta_plane, SZ_4K); + + y_stride = ALIGN(width, 128); + y_plane = ALIGN(y_stride * ALIGN(height, 32), SZ_4K); + + uv_meta_stride = ALIGN(DIV_ROUND_UP(width / 2, 16), 64); + uv_meta_plane = uv_meta_stride * ALIGN(DIV_ROUND_UP(height / 2, 8), 16); + uv_meta_plane = ALIGN(uv_meta_plane, SZ_4K); + + uv_stride = ALIGN(width, 128); + uv_plane = ALIGN(uv_stride * ALIGN(height / 2, 32), SZ_4K); + + return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane + +max(extradata, y_stride * 48), SZ_4K); +} + +u32 venus_helper_get_framesz_raw(u32 hfi_fmt, u32 width, u32 height) +{ + switch (hfi_fmt) { + case HFI_COLOR_FORMAT_NV12: + case HFI_COLOR_FORMAT_NV21: + return get_framesize_raw_nv12(width, height); + case HFI_COLOR_FORMAT_NV12_UBWC: + return get_framesize_raw_nv12_ubwc(width, height); + default: + return 0; + } +} +EXPORT_SYMBOL_GPL(venus_helper_get_framesz_raw); + +u32 venus_helper_get_framesz(u32 v4l2_fmt, u32 width, u32 height) +{ + u32 hfi_fmt, sz; + bool compressed; + + switch (v4l2_fmt) { + case V4L2_PIX_FMT_MPEG: + case V4L2_PIX_FMT_H264: + case V4L2_PIX_FMT_H264_NO_SC: + case V4L2_PIX_FMT_H264_MVC: + case V4L2_PIX_FMT_H263: + case V4L2_PIX_FMT_MPEG1: + case V4L2_PIX_FMT_MPEG2: + case V4L2_PIX_FMT_MPEG4: + case V4L2_PIX_FMT_XVID: + case V4L2_PIX_FMT_VC1_ANNEX_G: + case V4L2_PIX_FMT_VC1_ANNEX_L: + case V4L2_PIX_FMT_VP8: + case V4L2_PIX_FMT_VP9: + case V4L2_PIX_FMT_HEVC: + compressed = true; + break; + default: + compressed = false; + break; + } + + if (compressed) { + sz = ALIGN(height, 32) * ALIGN(width, 32) * 3 / 2 / 2; + return ALIGN(sz, SZ_4K); + } + + hfi_fmt = to_hfi_raw_fmt(v4l2_fmt); + if (!hfi_fmt) + return 0; + + return venus_helper_get_framesz_raw(hfi_fmt, width, height); +} +EXPORT_SYMBOL_GPL(venus_helper_get_framesz); + int venus_helper_set_input_resolution(struct venus_inst *inst, unsigned int width, unsigned int height) { diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h index 92be45894a69..92b167a47166 100644 --- a/drivers/media/platform/qcom/venus/helpers.h +++ b/drivers/media/platform/qcom/venus/helpers.h @@ -33,6 +33,8 @@ void venus_helper_m2m_device_run(void *priv); void venus_helper_m2m_job_abort(void *priv); int venus_helper_get_bufreq(struct venus_inst *inst, u32 type, struct hfi_buffer_requirements *req); +u32 venus_helper_get_framesz_raw(u32 hfi_fmt, u32 width, u32 height); +u32 venus_helper_get_framesz(u32 v4l2_fmt, u32 width, u32 height); int venus_helper_set_input_resolution(struct venus_inst *inst, unsigned int width, unsigned int height); int venus_helper_set_output_resolution(struct venus_inst *inst, diff --git a/drivers/media/platform/qcom/ven
[PATCH 28/28] venus: add HEVC codec support
This add HEVC codec support for venus versions 3xx and 4xx. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/helpers.c | 3 +++ drivers/media/platform/qcom/venus/hfi.c | 2 ++ drivers/media/platform/qcom/venus/vdec.c| 4 drivers/media/platform/qcom/venus/venc.c| 4 4 files changed, 13 insertions(+) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 87dcf9973e6f..fecadba039cf 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -71,6 +71,9 @@ bool venus_helper_check_codec(struct venus_inst *inst, u32 v4l2_pixfmt) case V4L2_PIX_FMT_XVID: codec = HFI_VIDEO_CODEC_DIVX; break; + case V4L2_PIX_FMT_HEVC: + codec = HFI_VIDEO_CODEC_HEVC; + break; default: return false; } diff --git a/drivers/media/platform/qcom/venus/hfi.c b/drivers/media/platform/qcom/venus/hfi.c index 94ca27b0bb99..24207829982f 100644 --- a/drivers/media/platform/qcom/venus/hfi.c +++ b/drivers/media/platform/qcom/venus/hfi.c @@ -49,6 +49,8 @@ static u32 to_codec_type(u32 pixfmt) return HFI_VIDEO_CODEC_VP9; case V4L2_PIX_FMT_XVID: return HFI_VIDEO_CODEC_DIVX; + case V4L2_PIX_FMT_HEVC: + return HFI_VIDEO_CODEC_HEVC; default: return 0; } diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 7deee104ac56..a114f421edad 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -77,6 +77,10 @@ static const struct venus_format vdec_formats[] = { .pixfmt = V4L2_PIX_FMT_XVID, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + }, { + .pixfmt = V4L2_PIX_FMT_HEVC, + .num_planes = 1, + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, }, }; diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index a703bce78abc..fdb76b69786f 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -59,6 +59,10 @@ static const struct venus_format venc_formats[] = { .pixfmt = V4L2_PIX_FMT_VP8, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + }, { + .pixfmt = V4L2_PIX_FMT_HEVC, + .num_planes = 1, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, }, }; -- 2.14.1
[PATCH 16/28] venus: add helper function to set actual buffer size
Add and use a helper function to set actual buffer size for particular buffer type. This is also preparation to use the second decoder output. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/helpers.c | 12 drivers/media/platform/qcom/venus/helpers.h | 1 + drivers/media/platform/qcom/venus/vdec.c| 10 ++ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 824ad4d2d064..94664a3ce3e2 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -544,6 +544,18 @@ int venus_helper_set_dyn_bufmode(struct venus_inst *inst) } EXPORT_SYMBOL_GPL(venus_helper_set_dyn_bufmode); +int venus_helper_set_bufsize(struct venus_inst *inst, u32 bufsize, u32 buftype) +{ + u32 ptype = HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL; + struct hfi_buffer_size_actual bufsz; + + bufsz.type = buftype; + bufsz.size = bufsize; + + return hfi_session_set_property(inst, ptype, ); +} +EXPORT_SYMBOL_GPL(venus_helper_set_bufsize); + static void delayed_process_buf_func(struct work_struct *work) { struct venus_buffer *buf, *n; diff --git a/drivers/media/platform/qcom/venus/helpers.h b/drivers/media/platform/qcom/venus/helpers.h index 52b961ed491e..cd306bd8978f 100644 --- a/drivers/media/platform/qcom/venus/helpers.h +++ b/drivers/media/platform/qcom/venus/helpers.h @@ -41,6 +41,7 @@ int venus_helper_set_num_bufs(struct venus_inst *inst, unsigned int input_bufs, unsigned int output_bufs); int venus_helper_set_color_format(struct venus_inst *inst, u32 fmt); int venus_helper_set_dyn_bufmode(struct venus_inst *inst); +int venus_helper_set_bufsize(struct venus_inst *inst, u32 bufsize, u32 buftype); void venus_helper_acquire_buf_ref(struct vb2_v4l2_buffer *vbuf); void venus_helper_release_buf_ref(struct venus_inst *inst, unsigned int idx); void venus_helper_init_instance(struct venus_inst *inst); diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 1de9cc64cf2f..b43607dee4fe 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -710,7 +710,6 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count) { struct venus_inst *inst = vb2_get_drv_priv(q); struct venus_core *core = inst->core; - u32 ptype; int ret; mutex_lock(>lock); @@ -740,13 +739,8 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count) goto deinit_sess; if (core->res->hfi_version == HFI_VERSION_3XX) { - struct hfi_buffer_size_actual buf_sz; - - ptype = HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL; - buf_sz.type = HFI_BUFFER_OUTPUT; - buf_sz.size = inst->output_buf_size; - - ret = hfi_session_set_property(inst, ptype, _sz); + ret = venus_helper_set_bufsize(inst, inst->output_buf_size, + HFI_BUFFER_OUTPUT); if (ret) goto deinit_sess; } -- 2.14.1
[PATCH 00/28] Venus updates
Hello, This patch set aims to: * add initial support for Venus version 4xx (found on sdm845). * introduce a common capability parser to enumerate better supported uncompressed formats, capabilities by codec, supported codecs and so on. * also contains various cleanups, readability improvements and fixes. * adds HEVC codec support for the Venus versions which has support for it. * add multi-stream support (secondary decoder output), which will give as an opportunity to use UBWC compressed formats to optimize internal interconnect bandwidth on higher resolutions. Comments are welcome! regards, Stan Stanimir Varbanov (28): venus: hfi_msgs: correct pointer increment venus: hfi: preparation to support venus 4xx venus: hfi: update sequence event to handle more properties venus: hfi_cmds: add set_properties for 4xx version venus: hfi: support session continue for 4xx version venus: hfi: handle buffer output2 type as well venus: hfi_venus: add halt AXI support for Venus 4xx venus: hfi_venus: add suspend function for 4xx version venus: venc,vdec: adds clocks needed for venus 4xx venus: vdec: call session_continue in insufficient event venus: add common capability parser venus: helpers: make a commmon function for power_enable venus: core: delete not used flag for buffer mode venus: helpers: rename a helper function and use buffer mode from caps venus: add a helper function to set dynamic buffer mode venus: add helper function to set actual buffer size venus: delete no longer used bufmode flag from instance venus: helpers: add buffer type argument to a helper venus: helpers: add a new helper to set raw format venus: helpers,vdec,venc: add helpers to set work mode and core usage venus: helpers: extend set_num_bufs helper with one more argument venus: helpers: add a helper to return opb buffer sizes venus: vdec: get required input buffers as well venus: vdec: new function for output configuration venus: move frame size calculations in common place venus: implementing multi-stream support venus: add sdm845 compatible and resource data venus: add HEVC codec support .../devicetree/bindings/media/qcom,venus.txt | 1 + drivers/media/platform/qcom/venus/Makefile | 3 +- drivers/media/platform/qcom/venus/core.c | 102 drivers/media/platform/qcom/venus/core.h | 91 ++-- drivers/media/platform/qcom/venus/helpers.c| 558 +++-- drivers/media/platform/qcom/venus/helpers.h| 23 +- drivers/media/platform/qcom/venus/hfi.c| 12 +- drivers/media/platform/qcom/venus/hfi.h| 9 + drivers/media/platform/qcom/venus/hfi_cmds.c | 64 ++- drivers/media/platform/qcom/venus/hfi_helper.h | 112 - drivers/media/platform/qcom/venus/hfi_msgs.c | 401 +++ drivers/media/platform/qcom/venus/hfi_parser.c | 290 +++ drivers/media/platform/qcom/venus/hfi_parser.h | 45 ++ drivers/media/platform/qcom/venus/hfi_venus.c | 69 +++ drivers/media/platform/qcom/venus/hfi_venus_io.h | 24 + drivers/media/platform/qcom/venus/vdec.c | 324 +++- drivers/media/platform/qcom/venus/venc.c | 166 +++--- 17 files changed, 1641 insertions(+), 653 deletions(-) create mode 100644 drivers/media/platform/qcom/venus/hfi_parser.c create mode 100644 drivers/media/platform/qcom/venus/hfi_parser.h -- 2.14.1
Re: [PATCH v2] venus: vdec: fix format enumeration
Hi Hans, Could you take this patch it not too late. On 20.03.2018 15:42, Stanimir Varbanov wrote: Hi Alex, Thanks! On 03/19/2018 11:32 AM, Alexandre Courbot wrote: find_format_by_index() stops enumerating formats as soon as the index matches, and returns NULL if venus_helper_check_codec() finds out that the format is not supported. This prevents formats to be properly enumerated if a non-supported format is present, as the enumeration will end with it. Fix this by moving the call to venus_helper_check_codec() into the loop, and keep enumerating when it fails. Fixes: 29f0133ec6 media: venus: use helper function to check supported codecs Signed-off-by: Alexandre Courbot <acour...@chromium.org> --- drivers/media/platform/qcom/venus/vdec.c | 13 +++-- drivers/media/platform/qcom/venus/venc.c | 13 +++-- 2 files changed, 14 insertions(+), 12 deletions(-) Acked-by: Stanimir Varbanov <stanimir.varba...@linaro.org> regards, Stan
Re: [PATCH v2] venus: vdec: fix format enumeration
Hi Alex, Thanks! On 03/19/2018 11:32 AM, Alexandre Courbot wrote: > find_format_by_index() stops enumerating formats as soon as the index > matches, and returns NULL if venus_helper_check_codec() finds out that > the format is not supported. This prevents formats to be properly > enumerated if a non-supported format is present, as the enumeration will > end with it. > > Fix this by moving the call to venus_helper_check_codec() into the loop, > and keep enumerating when it fails. > > Fixes: 29f0133ec6 media: venus: use helper function to check supported codecs > > Signed-off-by: Alexandre Courbot <acour...@chromium.org> > --- > drivers/media/platform/qcom/venus/vdec.c | 13 +++-- > drivers/media/platform/qcom/venus/venc.c | 13 +++-- > 2 files changed, 14 insertions(+), 12 deletions(-) Acked-by: Stanimir Varbanov <stanimir.varba...@linaro.org> -- regards, Stan
Re: [PATCH] venus: vdec: fix format enumeration
Hi Alex, Thanks for the patch! On 13.03.2018 11:11, Alexandre Courbot wrote: > find_format_by_index() stops enumerating formats as soon as the index > matches, and returns NULL if venus_helper_check_codec() finds out that > the format is not supported. This prevents formats to be properly > enumerated if a non-supported format is present, as the enumeration will > end with it. Please add fixes tag, Fixes: 29f0133ec6 media: venus: use helper function to check supported codecs > > Fix this by moving the call to venus_helper_check_codec() into the loop, > and keep enumerating when it fails. Good catch! > > Signed-off-by: Alexandre Courbot> > Change-Id: I4ff66e0b85172598efa59a6f01da8cb60597a6a5 You forgot to delete gerrit id. > --- > drivers/media/platform/qcom/venus/vdec.c | 13 +++-- > drivers/media/platform/qcom/venus/venc.c | 9 +++-- > 2 files changed, 14 insertions(+), 8 deletions(-) > > diff --git a/drivers/media/platform/qcom/venus/vdec.c > b/drivers/media/platform/qcom/venus/vdec.c > index c9e9576bb08a..3677302cfe43 100644 > --- a/drivers/media/platform/qcom/venus/vdec.c > +++ b/drivers/media/platform/qcom/venus/vdec.c > @@ -135,20 +135,21 @@ find_format_by_index(struct venus_inst *inst, unsigned > int index, u32 type) > return NULL; > > for (i = 0; i < size; i++) { > + bool valid; > + > if (fmt[i].type != type) > continue; > - if (k == index) > + valid = (type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE || > + venus_helper_check_codec(inst, fmt[i].pixfmt)); open and close braces are not needed. > + if (k == index && valid) > break; > - k++; > + if (valid) > + k++; > } > > if (i == size) > return NULL; > > - if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && > - !venus_helper_check_codec(inst, fmt[i].pixfmt)) > - return NULL; > - > return [i]; > } > > diff --git a/drivers/media/platform/qcom/venus/venc.c > b/drivers/media/platform/qcom/venus/venc.c > index e3a10a852cad..5eba4c7cd52e 100644 > --- a/drivers/media/platform/qcom/venus/venc.c > +++ b/drivers/media/platform/qcom/venus/venc.c > @@ -120,11 +120,16 @@ find_format_by_index(struct venus_inst *inst, unsigned > int index, u32 type) > return NULL; > > for (i = 0; i < size; i++) { > + bool valid; > + > if (fmt[i].type != type) > continue; > - if (k == index) > + valid = (type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE || > + venus_helper_check_codec(inst, fmt[i].pixfmt)); > + if (k == index && valid) > break; > - k++; > + if (valid) > + k++; > } > > if (i == size) maybe we should delete the condition: if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && !venus_helper_check_codec(inst, fmt[i].pixfmt)) as we do for the decoder? regards, Stan
Re: [Patch v6 10/12] [media] v4l2: Add v4l2 control IDs for HEVC encoder
Hi Smitha, Thanks for the patches! On 12/08/2017 11:08 AM, Smitha T Murthy wrote: Add v4l2 controls for HEVC encoder Signed-off-by: Smitha T MurthyReviewed-by: Andrzej Hajda --- drivers/media/v4l2-core/v4l2-ctrls.c | 118 +++ include/uapi/linux/v4l2-controls.h | 92 ++- 2 files changed, 209 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 4e53a86..3f98318 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -480,6 +480,56 @@ const char * const *v4l2_ctrl_get_menu(u32 id) NULL, }; + static const char * const hevc_profile[] = { + "Main", You forgot "Main 10" profile. + "Main Still Picture", + NULL, + }; + static const char * const hevc_level[] = { + "1", + "2", + "2.1", + "3", + "3.1", + "4", + "4.1", + "5", + "5.1", + "5.2", + "6", + "6.1", + "6.2", + NULL, + }; + static const char * const hevc_hierarchial_coding_type[] = { + "B", + "P", + NULL, + }; + static const char * const hevc_refresh_type[] = { + "None", + "CRA", + "IDR", + NULL, + }; + static const char * const hevc_size_of_length_field[] = { + "0", + "1", + "2", + "4", + NULL, + }; + static const char * const hevc_tier_flag[] = { + "Main", + "High", + NULL, + }; + static const char * const hevc_loop_filter_mode[] = { + "Disabled", + "Enabled", + "Disabled at slice boundary", + "NULL", + }; switch (id) { case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: @@ -575,6 +625,20 @@ const char * const *v4l2_ctrl_get_menu(u32 id) return dv_it_content_type; case V4L2_CID_DETECT_MD_MODE: return detect_md_mode; + case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE: + return hevc_profile; + case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL: + return hevc_level; + case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE: + return hevc_hierarchial_coding_type; + case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE: + return hevc_refresh_type; + case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD: + return hevc_size_of_length_field; + case V4L2_CID_MPEG_VIDEO_HEVC_TIER_FLAG: Could you drop _FLAG suffix? Looking (briefly) into the spec they not specify `tier flag` but just `tier`. + return hevc_tier_flag; + case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE: + return hevc_loop_filter_mode; default: return NULL; @@ -776,6 +840,53 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP:return "VPX P-Frame QP Value"; case V4L2_CID_MPEG_VIDEO_VPX_PROFILE: return "VPX Profile"; + /* HEVC controls */ + case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP: return "HEVC I-Frame QP Value"; + case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP: return "HEVC P-Frame QP Value"; + case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP: return "HEVC B-Frame QP Value"; + case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP: return "HEVC Minimum QP Value"; + case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP: return "HEVC Maximum QP Value"; + case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE: return "HEVC Profile"; + case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:return "HEVC Level"; + case V4L2_CID_MPEG_VIDEO_HEVC_TIER_FLAG:return "HEVC Tier Flag"; + case V4L2_CID_MPEG_VIDEO_HEVC_FRAME_RATE_RESOLUTION:return "HEVC Frame Rate Resolution"; + case V4L2_CID_MPEG_VIDEO_HEVC_MAX_PARTITION_DEPTH: return "HEVC Maximum Coding Unit Depth"; + case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE: return "HEVC Refresh Type"; + case V4L2_CID_MPEG_VIDEO_HEVC_CONST_INTRA_PRED: return "HEVC Constant Intra Prediction"; + case V4L2_CID_MPEG_VIDEO_HEVC_LOSSLESS_CU: return "HEVC Lossless Encoding"; + case V4L2_CID_MPEG_VIDEO_HEVC_WAVEFRONT:return "HEVC Wavefront"; + case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE: return "HEVC Loop Filter"; + case V4L2_CID_MPEG_VIDEO_HEVC_HIER_QP: return "HEVC QP Values"; + case
[PATCH v2] venus: venc: set correctly GOP size and number of B-frames
This change fixes the calculation of B-frames and GOP size by adopt v4l2 controls with the firmware interface expectations. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- Drop usage of do_div to avoid compiler warnings on 32bit systems. drivers/media/platform/qcom/venus/venc.c | 15 --- drivers/media/platform/qcom/venus/venc_ctrls.c | 59 +- 2 files changed, 68 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index 36d31540c59d..e3a10a852cad 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -685,8 +685,13 @@ static int venc_set_properties(struct venus_inst *inst) return ret; } + /* IDR periodicity, n: +* n = 0 - only the first I-frame is IDR frame +* n = 1 - all I-frames will be IDR frames +* n > 1 - every n-th I-frame will be IDR frame +*/ ptype = HFI_PROPERTY_CONFIG_VENC_IDR_PERIOD; - idrp.idr_period = ctr->gop_size; + idrp.idr_period = 0; ret = hfi_session_set_property(inst, ptype, ); if (ret) return ret; @@ -700,10 +705,6 @@ static int venc_set_properties(struct venus_inst *inst) return ret; } - /* intra_period = pframes + bframes + 1 */ - if (!ctr->num_p_frames) - ctr->num_p_frames = 2 * 15 - 1, - ptype = HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD; intra_period.pframes = ctr->num_p_frames; intra_period.bframes = ctr->num_b_frames; @@ -800,6 +801,10 @@ static int venc_init_session(struct venus_inst *inst) if (ret) goto deinit; + ret = venc_set_properties(inst); + if (ret) + goto deinit; + return 0; deinit: hfi_session_deinit(inst); diff --git a/drivers/media/platform/qcom/venus/venc_ctrls.c b/drivers/media/platform/qcom/venus/venc_ctrls.c index ab0fe51ff0f7..8dbb32ebae89 100644 --- a/drivers/media/platform/qcom/venus/venc_ctrls.c +++ b/drivers/media/platform/qcom/venus/venc_ctrls.c @@ -30,10 +30,57 @@ #define AT_SLICE_BOUNDARY \ V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY +static int venc_calc_bpframes(u32 gop_size, u32 conseq_b, u32 *bf, u32 *pf) +{ + uint32_t half = (gop_size - 1) >> 1; + uint32_t b, p, ratio; + bool found = false; + + if (!gop_size) + return -EINVAL; + + *bf = *pf = 0; + + if (!conseq_b) { + *pf = gop_size - 1; + return 0; + } + + b = p = half; + + for (; b <= gop_size - 1; b++, p--) { + if (b % p) + continue; + + ratio = b / p; + + if (ratio == conseq_b) { + found = true; + break; + } + + if (ratio > conseq_b) + break; + } + + if (found == false) + return -EINVAL; + + if (b + p + 1 != gop_size) + return -EINVAL; + + *bf = b; + *pf = p; + + return 0; +} + static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) { struct venus_inst *inst = ctrl_to_inst(ctrl); struct venc_controls *ctr = >controls.enc; + u32 bframes; + int ret; switch (ctrl->id) { case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: @@ -102,6 +149,11 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB: break; case V4L2_CID_MPEG_VIDEO_GOP_SIZE: + ret = venc_calc_bpframes(ctrl->val, ctr->num_b_frames, , +>num_p_frames); + if (ret) + return ret; + ctr->gop_size = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD: @@ -114,7 +166,12 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) ctr->vp8_max_qp = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_B_FRAMES: - ctr->num_b_frames = ctrl->val; + ret = venc_calc_bpframes(ctr->gop_size, ctrl->val, , +>num_p_frames); + if (ret) + return ret; + + ctr->num_b_frames = bframes; break; default: return -EINVAL; -- 2.11.0
[PATCH 2/2] venus: venc: set correctly GOP size and number of B-frames
This change fixes the calculation of B-frames and GOP size by adopt v4l2 controls with the firmware interface expectations. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/venc.c | 15 --- drivers/media/platform/qcom/venus/venc_ctrls.c | 60 +- 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index 36d31540c59d..e3a10a852cad 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -685,8 +685,13 @@ static int venc_set_properties(struct venus_inst *inst) return ret; } + /* IDR periodicity, n: +* n = 0 - only the first I-frame is IDR frame +* n = 1 - all I-frames will be IDR frames +* n > 1 - every n-th I-frame will be IDR frame +*/ ptype = HFI_PROPERTY_CONFIG_VENC_IDR_PERIOD; - idrp.idr_period = ctr->gop_size; + idrp.idr_period = 0; ret = hfi_session_set_property(inst, ptype, ); if (ret) return ret; @@ -700,10 +705,6 @@ static int venc_set_properties(struct venus_inst *inst) return ret; } - /* intra_period = pframes + bframes + 1 */ - if (!ctr->num_p_frames) - ctr->num_p_frames = 2 * 15 - 1, - ptype = HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD; intra_period.pframes = ctr->num_p_frames; intra_period.bframes = ctr->num_b_frames; @@ -800,6 +801,10 @@ static int venc_init_session(struct venus_inst *inst) if (ret) goto deinit; + ret = venc_set_properties(inst); + if (ret) + goto deinit; + return 0; deinit: hfi_session_deinit(inst); diff --git a/drivers/media/platform/qcom/venus/venc_ctrls.c b/drivers/media/platform/qcom/venus/venc_ctrls.c index ab0fe51ff0f7..53130d4774d3 100644 --- a/drivers/media/platform/qcom/venus/venc_ctrls.c +++ b/drivers/media/platform/qcom/venus/venc_ctrls.c @@ -30,10 +30,58 @@ #define AT_SLICE_BOUNDARY \ V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY +static int venc_calc_bpframes(u32 gop_size, u32 conseq_b, u32 *bf, u32 *pf) +{ + uint32_t half = (gop_size - 1) >> 1; + uint32_t b, p, ratio; + bool found = false; + + if (!gop_size) + return -EINVAL; + + *bf = *pf = 0; + + if (!conseq_b) { + *pf = gop_size - 1; + return 0; + } + + b = p = half; + + for (; b <= gop_size - 1; b++, p--) { + if (b % p) + continue; + + ratio = b; + do_div(ratio, p); + + if (ratio == conseq_b) { + found = true; + break; + } + + if (ratio > conseq_b) + break; + } + + if (found == false) + return -EINVAL; + + if (b + p + 1 != gop_size) + return -EINVAL; + + *bf = b; + *pf = p; + + return 0; +} + static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) { struct venus_inst *inst = ctrl_to_inst(ctrl); struct venc_controls *ctr = >controls.enc; + u32 bframes; + int ret; switch (ctrl->id) { case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: @@ -102,6 +150,11 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB: break; case V4L2_CID_MPEG_VIDEO_GOP_SIZE: + ret = venc_calc_bpframes(ctrl->val, ctr->num_b_frames, , +>num_p_frames); + if (ret) + return ret; + ctr->gop_size = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD: @@ -114,7 +167,12 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) ctr->vp8_max_qp = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_B_FRAMES: - ctr->num_b_frames = ctrl->val; + ret = venc_calc_bpframes(ctr->gop_size, ctrl->val, , +>num_p_frames); + if (ret) + return ret; + + ctr->num_b_frames = bframes; break; default: return -EINVAL; -- 2.11.0
[PATCH 1/2] venus: cleanup set_property controls
Move ptype (property type) initialization out of switch case and save few lines of code. Signed-off-by: Stanimir Varbanov <stanimir.varba...@linaro.org> --- drivers/media/platform/qcom/venus/hfi_cmds.c | 73 +--- 1 file changed, 2 insertions(+), 71 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.c b/drivers/media/platform/qcom/venus/hfi_cmds.c index b83c5b8ddccb..1cfeb7743041 100644 --- a/drivers/media/platform/qcom/venus/hfi_cmds.c +++ b/drivers/media/platform/qcom/venus/hfi_cmds.c @@ -421,12 +421,12 @@ static int pkt_session_set_property_1x(struct hfi_session_set_property_pkt *pkt, pkt->shdr.hdr.pkt_type = HFI_CMD_SESSION_SET_PROPERTY; pkt->shdr.session_id = hash32_ptr(cookie); pkt->num_properties = 1; + pkt->data[0] = ptype; switch (ptype) { case HFI_PROPERTY_CONFIG_FRAME_RATE: { struct hfi_framerate *in = pdata, *frate = prop_data; - pkt->data[0] = HFI_PROPERTY_CONFIG_FRAME_RATE; frate->buffer_type = in->buffer_type; frate->framerate = in->framerate; pkt->shdr.hdr.size += sizeof(u32) + sizeof(*frate); @@ -436,7 +436,6 @@ static int pkt_session_set_property_1x(struct hfi_session_set_property_pkt *pkt, struct hfi_uncompressed_format_select *in = pdata; struct hfi_uncompressed_format_select *hfi = prop_data; - pkt->data[0] = HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT; hfi->buffer_type = in->buffer_type; hfi->format = in->format; pkt->shdr.hdr.size += sizeof(u32) + sizeof(*hfi); @@ -445,7 +444,6 @@ static int pkt_session_set_property_1x(struct hfi_session_set_property_pkt *pkt, case HFI_PROPERTY_PARAM_FRAME_SIZE: { struct hfi_framesize *in = pdata, *fsize = prop_data; - pkt->data[0] = HFI_PROPERTY_PARAM_FRAME_SIZE; fsize->buffer_type = in->buffer_type; fsize->height = in->height; fsize->width = in->width; @@ -455,7 +453,6 @@ static int pkt_session_set_property_1x(struct hfi_session_set_property_pkt *pkt, case HFI_PROPERTY_CONFIG_REALTIME: { struct hfi_enable *in = pdata, *en = prop_data; - pkt->data[0] = HFI_PROPERTY_CONFIG_REALTIME; en->enable = in->enable; pkt->shdr.hdr.size += sizeof(u32) * 2; break; @@ -463,7 +460,6 @@ static int pkt_session_set_property_1x(struct hfi_session_set_property_pkt *pkt, case HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL: { struct hfi_buffer_count_actual *in = pdata, *count = prop_data; - pkt->data[0] = HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL; count->count_actual = in->count_actual; count->type = in->type; pkt->shdr.hdr.size += sizeof(u32) + sizeof(*count); @@ -472,7 +468,6 @@ static int pkt_session_set_property_1x(struct hfi_session_set_property_pkt *pkt, case HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL: { struct hfi_buffer_size_actual *in = pdata, *sz = prop_data; - pkt->data[0] = HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL; sz->size = in->size; sz->type = in->type; pkt->shdr.hdr.size += sizeof(u32) + sizeof(*sz); @@ -482,8 +477,6 @@ static int pkt_session_set_property_1x(struct hfi_session_set_property_pkt *pkt, struct hfi_buffer_display_hold_count_actual *in = pdata; struct hfi_buffer_display_hold_count_actual *count = prop_data; - pkt->data[0] = - HFI_PROPERTY_PARAM_BUFFER_DISPLAY_HOLD_COUNT_ACTUAL; count->hold_count = in->hold_count; count->type = in->type; pkt->shdr.hdr.size += sizeof(u32) + sizeof(*count); @@ -493,7 +486,6 @@ static int pkt_session_set_property_1x(struct hfi_session_set_property_pkt *pkt, struct hfi_nal_stream_format_select *in = pdata; struct hfi_nal_stream_format_select *fmt = prop_data; - pkt->data[0] = HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT; fmt->format = in->format; pkt->shdr.hdr.size += sizeof(u32) + sizeof(*fmt); break; @@ -510,7 +502,6 @@ static int pkt_session_set_property_1x(struct hfi_session_set_property_pkt *pkt, break; } - pkt->data[0] = HFI_PROPERTY_PARAM_VDEC_OUTPUT_ORDER; pkt->data[1] = *in; pkt->shdr.hdr.size += sizeof(u32) * 2; break; @@ -518,7 +509,6 @@ static int pkt_session_set_property_1x(struct hfi_session_set_property_pkt *pkt,
Re: [PATCH 2/2] media: venus: venc: Apply inloop deblocking filter
Hi Loic, Thanks for the patch! On 11/24/2017 11:34 AM, Loic Poulain wrote: > Deblocking filter allows to reduce blocking artifacts and improve > visual quality. This is configurable via the V4L2 API but eventually > not applied to the encoder. > > Note that alpha and beta deblocking values are 32-bit signed (-6;+6). > > Signed-off-by: Loic Poulain <loic.poul...@linaro.org> > --- > drivers/media/platform/qcom/venus/core.h | 4 ++-- > drivers/media/platform/qcom/venus/hfi_helper.h | 4 ++-- > drivers/media/platform/qcom/venus/venc.c | 22 ++ > 3 files changed, 26 insertions(+), 4 deletions(-) Reviewed-by: Stanimir Varbanov <stanimir.varba...@linaro.org> -- regards, Stan