summaryrefslogtreecommitdiff
path: root/drivers/media/platform/qcom/venus
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-05-25 04:09:16 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2022-05-25 04:09:16 +0300
commit827060261cf3c7b79ee7185d5aa61c851beb9403 (patch)
treeea33be6609b189d31d1e56c09c92c967078eb3f8 /drivers/media/platform/qcom/venus
parent268db333b561c77dee3feb6831806412293b4a7e (diff)
parent340ce50f75a6bdfe6d1850ca49ef37a8e2765dd1 (diff)
downloadlinux-827060261cf3c7b79ee7185d5aa61c851beb9403.tar.xz
Merge tag 'media/v5.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - dvb-usb drivers entries got reworked to avoid usage of magic numbers to refer to data position inside tables - vcodec driver has gained support for MT8186 and for vp8 and vp9 stateless codecs - hantro has gained support for Hantro G1 on RK366x - Added more h264 levels on coda960 - ccs gained support for MIPI CSI-2 28 bits per pixel raw data type - venus driver gained support for Qualcomm custom compressed pixel formats - lots of driver fixes and updates * tag 'media/v5.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (308 commits) media: hantro: Enable HOLD_CAPTURE_BUF for H.264 media: hantro: Add H.264 field decoding support media: hantro: h264: Make dpb entry management more robust media: hantro: Stop using H.264 parameter pic_num media: rkvdec: Enable capture buffer holding for H264 media: rkvdec-h264: Add field decoding support media: rkvdec: Ensure decoded resolution fit coded resolution media: rkvdec: h264: Fix reference frame_num wrap for second field media: rkvdec: h264: Validate and use pic width and height in mbs media: rkvdec: Move H264 SPS validation in rkvdec-h264 media: rkvdec: h264: Fix bit depth wrap in pps packet media: rkvdec: h264: Fix dpb_valid implementation media: rkvdec: Stop overclocking the decoder media: v4l2: Reorder field reflist media: h264: Sort p/b reflist using frame_num media: v4l2: Trace calculated p/b0/b1 initial reflist media: h264: Store all fields into the unordered list media: h264: Store current picture fields media: h264: Increase reference lists size to 32 media: h264: Use v4l2_h264_reference for reflist ...
Diffstat (limited to 'drivers/media/platform/qcom/venus')
-rw-r--r--drivers/media/platform/qcom/venus/core.h1
-rw-r--r--drivers/media/platform/qcom/venus/helpers.c85
-rw-r--r--drivers/media/platform/qcom/venus/helpers.h1
-rw-r--r--drivers/media/platform/qcom/venus/hfi.c3
-rw-r--r--drivers/media/platform/qcom/venus/hfi_platform_v4.c4
-rw-r--r--drivers/media/platform/qcom/venus/hfi_platform_v6.c4
-rw-r--r--drivers/media/platform/qcom/venus/hfi_venus.c4
-rw-r--r--drivers/media/platform/qcom/venus/vdec.c37
-rw-r--r--drivers/media/platform/qcom/venus/venc.c6
-rw-r--r--drivers/media/platform/qcom/venus/venc_ctrls.c8
10 files changed, 111 insertions, 42 deletions
diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h
index c3023340d95c..d33825553edc 100644
--- a/drivers/media/platform/qcom/venus/core.h
+++ b/drivers/media/platform/qcom/venus/core.h
@@ -261,6 +261,7 @@ struct venc_controls {
u32 header_mode;
bool aud_enable;
+ u32 intra_refresh_type;
u32 intra_refresh_period;
struct {
diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c
index 0bca95d01650..5c1104379c49 100644
--- a/drivers/media/platform/qcom/venus/helpers.c
+++ b/drivers/media/platform/qcom/venus/helpers.c
@@ -90,12 +90,28 @@ bool venus_helper_check_codec(struct venus_inst *inst, u32 v4l2_pixfmt)
}
EXPORT_SYMBOL_GPL(venus_helper_check_codec);
+static void free_dpb_buf(struct venus_inst *inst, struct intbuf *buf)
+{
+ ida_free(&inst->dpb_ids, buf->dpb_out_tag);
+
+ list_del_init(&buf->list);
+ dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da,
+ buf->attrs);
+ kfree(buf);
+}
+
int venus_helper_queue_dpb_bufs(struct venus_inst *inst)
{
- struct intbuf *buf;
+ struct intbuf *buf, *next;
+ unsigned int dpb_size = 0;
int ret = 0;
- list_for_each_entry(buf, &inst->dpbbufs, list) {
+ 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;
+
+ list_for_each_entry_safe(buf, next, &inst->dpbbufs, list) {
struct hfi_frame_data fdata;
memset(&fdata, 0, sizeof(fdata));
@@ -106,6 +122,12 @@ int venus_helper_queue_dpb_bufs(struct venus_inst *inst)
if (buf->owned_by == FIRMWARE)
continue;
+ /* free buffer from previous sequence which was released later */
+ if (dpb_size > buf->size) {
+ free_dpb_buf(inst, buf);
+ continue;
+ }
+
fdata.clnt_data = buf->dpb_out_tag;
ret = hfi_session_process_buf(inst, &fdata);
@@ -127,13 +149,7 @@ int venus_helper_free_dpb_bufs(struct venus_inst *inst)
list_for_each_entry_safe(buf, n, &inst->dpbbufs, list) {
if (buf->owned_by == FIRMWARE)
continue;
-
- ida_free(&inst->dpb_ids, buf->dpb_out_tag);
-
- list_del_init(&buf->list);
- dma_free_attrs(inst->core->dev, buf->size, buf->va, buf->da,
- buf->attrs);
- kfree(buf);
+ free_dpb_buf(inst, buf);
}
if (list_empty(&inst->dpbbufs))
@@ -592,6 +608,10 @@ static u32 to_hfi_raw_fmt(u32 v4l2_fmt)
return HFI_COLOR_FORMAT_NV12;
case V4L2_PIX_FMT_NV21:
return HFI_COLOR_FORMAT_NV21;
+ case V4L2_PIX_FMT_QC08C:
+ return HFI_COLOR_FORMAT_NV12_UBWC;
+ case V4L2_PIX_FMT_QC10C:
+ return HFI_COLOR_FORMAT_YUV420_TP10_UBWC;
default:
break;
}
@@ -1174,7 +1194,8 @@ int venus_helper_set_format_constraints(struct venus_inst *inst)
if (!IS_V6(inst->core))
return 0;
- if (inst->opb_fmt == HFI_COLOR_FORMAT_NV12_UBWC)
+ if (inst->opb_fmt == HFI_COLOR_FORMAT_NV12_UBWC ||
+ inst->opb_fmt == HFI_COLOR_FORMAT_YUV420_TP10_UBWC)
return 0;
pconstraint.buffer_type = HFI_BUFFER_OUTPUT2;
@@ -1745,27 +1766,6 @@ int venus_helper_get_out_fmts(struct venus_inst *inst, u32 v4l2_fmt,
if (!caps)
return -EINVAL;
- if (inst->bit_depth == VIDC_BITDEPTH_10 &&
- inst->session_type == VIDC_SESSION_TYPE_DEC) {
- found_ubwc =
- find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT,
- HFI_COLOR_FORMAT_YUV420_TP10_UBWC);
- found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2,
- HFI_COLOR_FORMAT_NV12);
- if (found_ubwc && found) {
- /*
- * Hard-code DPB buffers to be 10bit UBWC and decoder
- * output buffers in 8bit NV12 until V4L2 is able to
- * expose compressed/tiled formats to applications.
- */
- *out_fmt = HFI_COLOR_FORMAT_YUV420_TP10_UBWC;
- *out2_fmt = HFI_COLOR_FORMAT_NV12;
- return 0;
- }
-
- return -EINVAL;
- }
-
if (ubwc) {
ubwc_fmt = fmt | HFI_COLOR_FORMAT_UBWC_BASE;
found_ubwc = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT,
@@ -1797,6 +1797,29 @@ int venus_helper_get_out_fmts(struct venus_inst *inst, u32 v4l2_fmt,
}
EXPORT_SYMBOL_GPL(venus_helper_get_out_fmts);
+bool venus_helper_check_format(struct venus_inst *inst, u32 v4l2_pixfmt)
+{
+ struct venus_core *core = inst->core;
+ u32 fmt = to_hfi_raw_fmt(v4l2_pixfmt);
+ struct hfi_plat_caps *caps;
+ u32 buftype;
+
+ if (!fmt)
+ return false;
+
+ caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type);
+ if (!caps)
+ return false;
+
+ if (inst->session_type == VIDC_SESSION_TYPE_DEC)
+ buftype = HFI_BUFFER_OUTPUT2;
+ else
+ buftype = HFI_BUFFER_OUTPUT;
+
+ return find_fmt_from_caps(caps, buftype, fmt);
+}
+EXPORT_SYMBOL_GPL(venus_helper_check_format);
+
int venus_helper_set_stride(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 32619c3e8c97..358e4f39c9c0 100644
--- a/drivers/media/platform/qcom/venus/helpers.h
+++ b/drivers/media/platform/qcom/venus/helpers.h
@@ -55,6 +55,7 @@ void venus_helper_init_instance(struct venus_inst *inst);
int venus_helper_session_init(struct venus_inst *inst);
int venus_helper_get_out_fmts(struct venus_inst *inst, u32 fmt, u32 *out_fmt,
u32 *out2_fmt, bool ubwc);
+bool venus_helper_check_format(struct venus_inst *inst, u32 v4l2_pixfmt);
int venus_helper_alloc_dpb_bufs(struct venus_inst *inst);
int venus_helper_free_dpb_bufs(struct venus_inst *inst);
int venus_helper_intbufs_alloc(struct venus_inst *inst);
diff --git a/drivers/media/platform/qcom/venus/hfi.c b/drivers/media/platform/qcom/venus/hfi.c
index 4e2151fb47f0..1968f09ad177 100644
--- a/drivers/media/platform/qcom/venus/hfi.c
+++ b/drivers/media/platform/qcom/venus/hfi.c
@@ -104,6 +104,9 @@ int hfi_core_deinit(struct venus_core *core, bool blocking)
mutex_lock(&core->lock);
}
+ if (!core->ops)
+ goto unlock;
+
ret = core->ops->core_deinit(core);
if (!ret)
diff --git a/drivers/media/platform/qcom/venus/hfi_platform_v4.c b/drivers/media/platform/qcom/venus/hfi_platform_v4.c
index 3f7f5277a50e..e3f0a90a567b 100644
--- a/drivers/media/platform/qcom/venus/hfi_platform_v4.c
+++ b/drivers/media/platform/qcom/venus/hfi_platform_v4.c
@@ -55,7 +55,7 @@ static const struct hfi_plat_caps caps[] = {
.fmts[3] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV12},
.fmts[4] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV21},
.fmts[5] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_P010},
- .fmts[6] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_YUV420_TP10},
+ .fmts[6] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_YUV420_TP10_UBWC},
.num_fmts = 7,
}, {
.codec = HFI_VIDEO_CODEC_VP8,
@@ -106,7 +106,7 @@ static const struct hfi_plat_caps caps[] = {
.fmts[3] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV12},
.fmts[4] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV21},
.fmts[5] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_P010},
- .fmts[6] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_YUV420_TP10},
+ .fmts[6] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_YUV420_TP10_UBWC},
.num_fmts = 7,
}, {
.codec = HFI_VIDEO_CODEC_MPEG2,
diff --git a/drivers/media/platform/qcom/venus/hfi_platform_v6.c b/drivers/media/platform/qcom/venus/hfi_platform_v6.c
index c10618e44f5d..4e8af645f8b9 100644
--- a/drivers/media/platform/qcom/venus/hfi_platform_v6.c
+++ b/drivers/media/platform/qcom/venus/hfi_platform_v6.c
@@ -55,7 +55,7 @@ static const struct hfi_plat_caps caps[] = {
.fmts[3] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV12},
.fmts[4] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV21},
.fmts[5] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_P010},
- .fmts[6] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_YUV420_TP10},
+ .fmts[6] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_YUV420_TP10_UBWC},
.num_fmts = 7,
}, {
.codec = HFI_VIDEO_CODEC_VP8,
@@ -106,7 +106,7 @@ static const struct hfi_plat_caps caps[] = {
.fmts[3] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV12},
.fmts[4] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_NV21},
.fmts[5] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_P010},
- .fmts[6] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_YUV420_TP10},
+ .fmts[6] = {HFI_BUFFER_OUTPUT2, HFI_COLOR_FORMAT_YUV420_TP10_UBWC},
.num_fmts = 7,
}, {
.codec = HFI_VIDEO_CODEC_MPEG2,
diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c
index 3a75a27632fb..9a34662fea38 100644
--- a/drivers/media/platform/qcom/venus/hfi_venus.c
+++ b/drivers/media/platform/qcom/venus/hfi_venus.c
@@ -1583,8 +1583,10 @@ static int venus_suspend_3xx(struct venus_core *core)
*/
ret = readx_poll_timeout(venus_cpu_and_video_core_idle, hdev, val, val,
1500, 100 * 1500);
- if (ret)
+ if (ret) {
+ dev_err(dev, "wait for cpu and video core idle fail (%d)\n", ret);
return ret;
+ }
ret = venus_prepare_power_collapse(hdev, false);
if (ret) {
diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c
index 91da3f509724..ac0bb45d07f4 100644
--- a/drivers/media/platform/qcom/venus/vdec.c
+++ b/drivers/media/platform/qcom/venus/vdec.c
@@ -31,6 +31,14 @@
*/
static const struct venus_format vdec_formats[] = {
{
+ .pixfmt = V4L2_PIX_FMT_QC08C,
+ .num_planes = 1,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+ }, {
+ .pixfmt = V4L2_PIX_FMT_QC10C,
+ .num_planes = 1,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+ },{
.pixfmt = V4L2_PIX_FMT_NV12,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
@@ -106,6 +114,14 @@ find_format(struct venus_inst *inst, u32 pixfmt, u32 type)
!venus_helper_check_codec(inst, fmt[i].pixfmt))
return NULL;
+ if (V4L2_TYPE_IS_CAPTURE(type) &&
+ !venus_helper_check_format(inst, fmt[i].pixfmt))
+ return NULL;
+
+ if (V4L2_TYPE_IS_CAPTURE(type) && fmt[i].pixfmt == V4L2_PIX_FMT_QC10C &&
+ !(inst->bit_depth == VIDC_BITDEPTH_10))
+ return NULL;
+
return &fmt[i];
}
@@ -124,8 +140,17 @@ find_format_by_index(struct venus_inst *inst, unsigned int index, u32 type)
if (fmt[i].type != type)
continue;
- valid = type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ||
- venus_helper_check_codec(inst, fmt[i].pixfmt);
+
+ if (V4L2_TYPE_IS_OUTPUT(type)) {
+ valid = venus_helper_check_codec(inst, fmt[i].pixfmt);
+ } else if (V4L2_TYPE_IS_CAPTURE(type)) {
+ valid = venus_helper_check_format(inst, fmt[i].pixfmt);
+
+ if (fmt[i].pixfmt == V4L2_PIX_FMT_QC10C &&
+ !(inst->bit_depth == VIDC_BITDEPTH_10))
+ valid = false;
+ }
+
if (k == index && valid)
break;
if (valid)
@@ -676,8 +701,8 @@ static int vdec_output_conf(struct venus_inst *inst)
struct venus_core *core = inst->core;
struct hfi_enable en = { .enable = 1 };
struct hfi_buffer_requirements bufreq;
- u32 width = inst->out_width;
- u32 height = inst->out_height;
+ u32 width = inst->width;
+ u32 height = inst->height;
u32 out_fmt, out2_fmt;
bool ubwc = false;
u32 ptype;
@@ -1200,6 +1225,8 @@ static void vdec_stop_streaming(struct vb2_queue *q)
struct venus_inst *inst = vb2_get_drv_priv(q);
int ret = -EINVAL;
+ vdec_pm_get_put(inst);
+
mutex_lock(&inst->lock);
if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
@@ -1525,7 +1552,7 @@ static const struct hfi_inst_ops vdec_hfi_ops = {
static void vdec_inst_init(struct venus_inst *inst)
{
inst->hfi_codec = HFI_VIDEO_CODEC_H264;
- inst->fmt_out = &vdec_formats[6];
+ inst->fmt_out = &vdec_formats[8];
inst->fmt_cap = &vdec_formats[0];
inst->width = frame_width_min(inst);
inst->height = ALIGN(frame_height_min(inst), 32);
diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c
index adea4c3b8c20..86918aea1d24 100644
--- a/drivers/media/platform/qcom/venus/venc.c
+++ b/drivers/media/platform/qcom/venus/venc.c
@@ -893,8 +893,12 @@ static int venc_set_properties(struct venus_inst *inst)
mbs++;
mbs /= ctr->intra_refresh_period;
- intra_refresh.mode = HFI_INTRA_REFRESH_RANDOM;
intra_refresh.cir_mbs = mbs;
+ if (ctr->intra_refresh_type ==
+ V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_CYCLIC)
+ intra_refresh.mode = HFI_INTRA_REFRESH_CYCLIC;
+ else
+ intra_refresh.mode = HFI_INTRA_REFRESH_RANDOM;
}
ptype = HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH;
diff --git a/drivers/media/platform/qcom/venus/venc_ctrls.c b/drivers/media/platform/qcom/venus/venc_ctrls.c
index ea5805e71c14..ed44e5800759 100644
--- a/drivers/media/platform/qcom/venus/venc_ctrls.c
+++ b/drivers/media/platform/qcom/venus/venc_ctrls.c
@@ -316,6 +316,9 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY:
ctr->mastering = *ctrl->p_new.p_hdr10_mastering;
break;
+ case V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE:
+ ctr->intra_refresh_type = ctrl->val;
+ break;
case V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD:
ctr->intra_refresh_period = ctrl->val;
break;
@@ -582,6 +585,11 @@ int venc_ctrl_init(struct venus_inst *inst)
V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY,
v4l2_ctrl_ptr_create(NULL));
+ v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE,
+ V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_CYCLIC,
+ 0, V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM);
+
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD, 0,
((4096 * 2304) >> 8), 1, 0);