summaryrefslogtreecommitdiff
path: root/drivers/media/platform/qcom/venus
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/qcom/venus')
-rw-r--r--drivers/media/platform/qcom/venus/core.h39
-rw-r--r--drivers/media/platform/qcom/venus/helpers.c33
-rw-r--r--drivers/media/platform/qcom/venus/hfi_cmds.c19
-rw-r--r--drivers/media/platform/qcom/venus/hfi_cmds.h4
-rw-r--r--drivers/media/platform/qcom/venus/hfi_helper.h2
-rw-r--r--drivers/media/platform/qcom/venus/hfi_msgs.c34
-rw-r--r--drivers/media/platform/qcom/venus/hfi_msgs.h14
-rw-r--r--drivers/media/platform/qcom/venus/hfi_plat_bufs.h3
-rw-r--r--drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c11
-rw-r--r--drivers/media/platform/qcom/venus/hfi_venus.c28
-rw-r--r--drivers/media/platform/qcom/venus/vdec.c94
-rw-r--r--drivers/media/platform/qcom/venus/venc.c35
12 files changed, 217 insertions, 99 deletions
diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h
index 4f81669986ba..320bde0f83cb 100644
--- a/drivers/media/platform/qcom/venus/core.h
+++ b/drivers/media/platform/qcom/venus/core.h
@@ -83,6 +83,23 @@ struct venus_resources {
const char *fwname;
};
+enum venus_fmt {
+ VENUS_FMT_NV12 = 0,
+ VENUS_FMT_QC08C = 1,
+ VENUS_FMT_QC10C = 2,
+ VENUS_FMT_P010 = 3,
+ VENUS_FMT_H264 = 4,
+ VENUS_FMT_VP8 = 5,
+ VENUS_FMT_VP9 = 6,
+ VENUS_FMT_HEVC = 7,
+ VENUS_FMT_VC1_ANNEX_G = 8,
+ VENUS_FMT_VC1_ANNEX_L = 9,
+ VENUS_FMT_MPEG4 = 10,
+ VENUS_FMT_MPEG2 = 11,
+ VENUS_FMT_H263 = 12,
+ VENUS_FMT_XVID = 13,
+};
+
struct venus_format {
u32 pixfmt;
unsigned int num_planes;
@@ -201,6 +218,11 @@ struct venus_core {
unsigned int core0_usage_count;
unsigned int core1_usage_count;
struct dentry *root;
+ struct venus_img_version {
+ u32 major;
+ u32 minor;
+ u32 rev;
+ } venus_ver;
};
struct vdec_controls {
@@ -389,6 +411,7 @@ enum venus_inst_modes {
* @sequence_out: a sequence counter for output queue
* @m2m_dev: a reference to m2m device structure
* @m2m_ctx: a reference to m2m context structure
+ * @ctx_q_lock: a lock to serialize video device ioctl calls
* @state: current state of the instance
* @done: a completion for sync HFI operation
* @error: an error returned during last HFI sync operation
@@ -460,6 +483,7 @@ struct venus_inst {
u32 sequence_out;
struct v4l2_m2m_dev *m2m_dev;
struct v4l2_m2m_ctx *m2m_ctx;
+ struct mutex ctx_q_lock;
unsigned int state;
struct completion done;
unsigned int error;
@@ -508,4 +532,19 @@ venus_caps_by_codec(struct venus_core *core, u32 codec, u32 domain)
return NULL;
}
+static inline bool
+is_fw_rev_or_newer(struct venus_core *core, u32 vmajor, u32 vminor, u32 vrev)
+{
+ return ((core)->venus_ver.major == vmajor &&
+ (core)->venus_ver.minor == vminor &&
+ (core)->venus_ver.rev >= vrev);
+}
+
+static inline bool
+is_fw_rev_or_older(struct venus_core *core, u32 vmajor, u32 vminor, u32 vrev)
+{
+ return ((core)->venus_ver.major == vmajor &&
+ (core)->venus_ver.minor == vminor &&
+ (core)->venus_ver.rev <= vrev);
+}
#endif
diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c
index a2ceab7f9ddb..1822e85ab6bf 100644
--- a/drivers/media/platform/qcom/venus/helpers.c
+++ b/drivers/media/platform/qcom/venus/helpers.c
@@ -502,7 +502,6 @@ session_process_buf(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf)
struct vb2_buffer *vb = &vbuf->vb2_buf;
unsigned int type = vb->type;
struct hfi_frame_data fdata;
- int ret;
memset(&fdata, 0, sizeof(fdata));
fdata.alloc_len = buf->size;
@@ -533,11 +532,7 @@ session_process_buf(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf)
fdata.offset = 0;
}
- ret = hfi_session_process_buf(inst, &fdata);
- if (ret)
- return ret;
-
- return 0;
+ return hfi_session_process_buf(inst, &fdata);
}
static bool is_dynamic_bufmode(struct venus_inst *inst)
@@ -612,6 +607,8 @@ static u32 to_hfi_raw_fmt(u32 v4l2_fmt)
return HFI_COLOR_FORMAT_NV12_UBWC;
case V4L2_PIX_FMT_QC10C:
return HFI_COLOR_FORMAT_YUV420_TP10_UBWC;
+ case V4L2_PIX_FMT_P010:
+ return HFI_COLOR_FORMAT_P010;
default:
break;
}
@@ -639,12 +636,16 @@ static int platform_get_bufreq(struct venus_inst *inst, u32 buftype,
if (is_dec) {
params.width = inst->width;
params.height = inst->height;
+ params.out_width = inst->out_width;
+ params.out_height = inst->out_height;
params.codec = inst->fmt_out->pixfmt;
params.hfi_color_fmt = to_hfi_raw_fmt(inst->fmt_cap->pixfmt);
params.dec.max_mbs_per_frame = mbs_per_frame_max(inst);
params.dec.buffer_size_limit = 0;
params.dec.is_secondary_output =
inst->opb_buftype == HFI_BUFFER_OUTPUT2;
+ if (params.dec.is_secondary_output)
+ params.hfi_dpb_color_fmt = inst->dpb_fmt;
params.dec.is_interlaced =
inst->pic_struct != HFI_INTERLACE_FRAME_PROGRESSIVE;
} else {
@@ -1036,8 +1037,8 @@ static u32 get_framesize_raw_yuv420_tp10_ubwc(u32 width, u32 height)
u32 extradata = SZ_16K;
u32 size;
- y_stride = ALIGN(ALIGN(width, 192) * 4 / 3, 256);
- uv_stride = ALIGN(ALIGN(width, 192) * 4 / 3, 256);
+ y_stride = ALIGN(width * 4 / 3, 256);
+ uv_stride = ALIGN(width * 4 / 3, 256);
y_sclines = ALIGN(height, 16);
uv_sclines = ALIGN((height + 1) >> 1, 16);
@@ -1764,6 +1765,22 @@ 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, fmt);
+ if (found_ubwc && found) {
+ /*
+ * Hard-code DPB buffers to be 10bit UBWC
+ * until V4L2 is able to expose compressed/tiled
+ * formats to applications.
+ */
+ *out_fmt = HFI_COLOR_FORMAT_YUV420_TP10_UBWC;
+ *out2_fmt = fmt;
+ return 0;
+ }
+ }
+
if (ubwc) {
ubwc_fmt = fmt | HFI_COLOR_FORMAT_UBWC_BASE;
found_ubwc = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT,
diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.c b/drivers/media/platform/qcom/venus/hfi_cmds.c
index bc3f8ff05840..7f0802a5518c 100644
--- a/drivers/media/platform/qcom/venus/hfi_cmds.c
+++ b/drivers/media/platform/qcom/venus/hfi_cmds.c
@@ -83,7 +83,7 @@ int pkt_sys_set_resource(struct hfi_sys_set_resource_pkt *pkt, u32 id, u32 size,
res->size = size;
res->mem = addr;
pkt->resource_type = HFI_RESOURCE_OCMEM;
- pkt->hdr.size += sizeof(*res) - sizeof(u32);
+ pkt->hdr.size += sizeof(*res);
break;
}
case VIDC_RESOURCE_NONE:
@@ -200,8 +200,8 @@ int pkt_session_set_buffers(struct hfi_session_set_buffers_pkt *pkt,
struct hfi_buffer_info *bi;
pkt->extradata_size = bd->extradata_size;
- pkt->shdr.hdr.size = sizeof(*pkt) - sizeof(u32) +
- (bd->num_buffers * sizeof(*bi));
+ pkt->shdr.hdr.size = sizeof(*pkt) +
+ bd->num_buffers * sizeof(*bi);
bi = (struct hfi_buffer_info *)pkt->buffer_info;
for (i = 0; i < pkt->num_buffers; i++) {
bi->buffer_addr = bd->device_addr;
@@ -209,8 +209,8 @@ int pkt_session_set_buffers(struct hfi_session_set_buffers_pkt *pkt,
}
} else {
pkt->extradata_size = 0;
- pkt->shdr.hdr.size = sizeof(*pkt) +
- ((bd->num_buffers - 1) * sizeof(u32));
+ pkt->shdr.hdr.size = struct_size(pkt, buffer_info,
+ bd->num_buffers);
for (i = 0; i < pkt->num_buffers; i++)
pkt->buffer_info[i] = bd->device_addr;
}
@@ -243,16 +243,16 @@ int pkt_session_unset_buffers(struct hfi_session_release_buffer_pkt *pkt,
bi->extradata_addr = bd->extradata_addr;
}
pkt->shdr.hdr.size =
- sizeof(struct hfi_session_set_buffers_pkt) -
- sizeof(u32) + (bd->num_buffers * sizeof(*bi));
+ sizeof(struct hfi_session_set_buffers_pkt) +
+ bd->num_buffers * sizeof(*bi);
} else {
for (i = 0; i < pkt->num_buffers; i++)
pkt->buffer_info[i] = bd->device_addr;
pkt->extradata_size = 0;
pkt->shdr.hdr.size =
- sizeof(struct hfi_session_set_buffers_pkt) +
- ((bd->num_buffers - 1) * sizeof(u32));
+ struct_size((struct hfi_session_set_buffers_pkt *)0,
+ buffer_info, bd->num_buffers);
}
pkt->response_req = bd->response_required;
@@ -521,6 +521,7 @@ static int pkt_session_set_property_1x(struct hfi_session_set_property_pkt *pkt,
pkt->shdr.hdr.size += sizeof(u32) + sizeof(*en);
break;
}
+ case HFI_PROPERTY_PARAM_VDEC_ENABLE_SUFFICIENT_SEQCHANGE_EVENT:
case HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER: {
struct hfi_enable *in = pdata;
struct hfi_enable *en = prop_data;
diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.h b/drivers/media/platform/qcom/venus/hfi_cmds.h
index 99bc0b6db67c..dd9c5066442d 100644
--- a/drivers/media/platform/qcom/venus/hfi_cmds.h
+++ b/drivers/media/platform/qcom/venus/hfi_cmds.h
@@ -56,7 +56,7 @@ struct hfi_sys_set_resource_pkt {
struct hfi_pkt_hdr hdr;
u32 resource_handle;
u32 resource_type;
- u32 resource_data[1];
+ u32 resource_data[];
};
struct hfi_sys_release_resource_pkt {
@@ -117,7 +117,7 @@ struct hfi_session_set_buffers_pkt {
u32 extradata_size;
u32 min_buffer_size;
u32 num_buffers;
- u32 buffer_info[1];
+ u32 buffer_info[];
};
struct hfi_session_get_sequence_header_pkt {
diff --git a/drivers/media/platform/qcom/venus/hfi_helper.h b/drivers/media/platform/qcom/venus/hfi_helper.h
index 105792a68060..0abbc50c5864 100644
--- a/drivers/media/platform/qcom/venus/hfi_helper.h
+++ b/drivers/media/platform/qcom/venus/hfi_helper.h
@@ -469,6 +469,8 @@
#define HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH 0x1003007
#define HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT 0x1003009
#define HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE 0x100300a
+#define HFI_PROPERTY_PARAM_VDEC_ENABLE_SUFFICIENT_SEQCHANGE_EVENT \
+ 0x100300b
/*
* HFI_PROPERTY_CONFIG_VDEC_COMMON_START
diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c
index df96db3761a7..3d5dadfa1900 100644
--- a/drivers/media/platform/qcom/venus/hfi_msgs.c
+++ b/drivers/media/platform/qcom/venus/hfi_msgs.c
@@ -233,7 +233,7 @@ static void hfi_sys_init_done(struct venus_core *core, struct venus_inst *inst,
goto done;
}
- rem_bytes = pkt->hdr.size - sizeof(*pkt) + sizeof(u32);
+ rem_bytes = pkt->hdr.size - sizeof(*pkt);
if (rem_bytes <= 0) {
/* missing property data */
error = HFI_ERR_SYS_INSUFFICIENT_RESOURCES;
@@ -248,13 +248,15 @@ done:
}
static void
-sys_get_prop_image_version(struct device *dev,
+sys_get_prop_image_version(struct venus_core *core,
struct hfi_msg_sys_property_info_pkt *pkt)
{
+ struct device *dev = core->dev;
u8 *smem_tbl_ptr;
u8 *img_ver;
int req_bytes;
size_t smem_blk_sz;
+ int ret;
req_bytes = pkt->hdr.size - sizeof(*pkt);
@@ -263,8 +265,30 @@ sys_get_prop_image_version(struct device *dev,
return;
img_ver = pkt->data;
+ if (!img_ver)
+ return;
+
+ ret = sscanf(img_ver, "14:video-firmware.%u.%u-%u",
+ &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev);
+ if (ret)
+ goto done;
+
+ ret = sscanf(img_ver, "14:VIDEO.VPU.%u.%u-%u",
+ &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev);
+ if (ret)
+ goto done;
+
+ ret = sscanf(img_ver, "14:VIDEO.VE.%u.%u-%u",
+ &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev);
+ if (ret)
+ goto done;
- dev_dbg(dev, VDBGL "F/W version: %s\n", img_ver);
+ dev_err(dev, VDBGL "error reading F/W version\n");
+ return;
+
+done:
+ dev_dbg(dev, VDBGL "F/W version: %s, major %u, minor %u, revision %u\n",
+ img_ver, core->venus_ver.major, core->venus_ver.minor, core->venus_ver.rev);
smem_tbl_ptr = qcom_smem_get(QCOM_SMEM_HOST_ANY,
SMEM_IMG_VER_TBL, &smem_blk_sz);
@@ -286,7 +310,7 @@ static void hfi_sys_property_info(struct venus_core *core,
switch (pkt->property) {
case HFI_PROPERTY_SYS_IMAGE_VERSION:
- sys_get_prop_image_version(dev, pkt);
+ sys_get_prop_image_version(core, pkt);
break;
default:
dev_dbg(dev, VDBGL "unknown property data\n");
@@ -434,7 +458,7 @@ static void hfi_session_init_done(struct venus_core *core,
if (!IS_V1(core))
goto done;
- rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt) + sizeof(u32);
+ rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt);
if (rem_bytes <= 0) {
error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES;
goto done;
diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.h b/drivers/media/platform/qcom/venus/hfi_msgs.h
index 510513697335..8c2e17b0d36f 100644
--- a/drivers/media/platform/qcom/venus/hfi_msgs.h
+++ b/drivers/media/platform/qcom/venus/hfi_msgs.h
@@ -50,7 +50,7 @@ struct hfi_msg_event_notify_pkt {
u32 event_id;
u32 event_data1;
u32 event_data2;
- u32 ext_event_data[1];
+ u32 ext_event_data[];
};
struct hfi_msg_event_release_buffer_ref_pkt {
@@ -63,7 +63,7 @@ struct hfi_msg_sys_init_done_pkt {
struct hfi_pkt_hdr hdr;
u32 error_type;
u32 num_properties;
- u32 data[1];
+ u32 data[];
};
struct hfi_msg_sys_pc_prep_done_pkt {
@@ -81,7 +81,7 @@ struct hfi_msg_session_init_done_pkt {
struct hfi_session_hdr_pkt shdr;
u32 error_type;
u32 num_properties;
- u32 data[1];
+ u32 data[];
};
struct hfi_msg_session_end_done_pkt {
@@ -228,7 +228,7 @@ struct hfi_msg_session_parse_sequence_header_done_pkt {
struct hfi_session_hdr_pkt shdr;
u32 error_type;
u32 num_properties;
- u32 data[1];
+ u32 data[];
};
struct hfi_msg_session_property_info_pkt {
@@ -247,7 +247,7 @@ struct hfi_msg_session_release_buffers_done_pkt {
struct hfi_session_hdr_pkt shdr;
u32 error_type;
u32 num_buffers;
- u32 buffer_info[1];
+ u32 buffer_info[];
};
struct hfi_msg_sys_debug_pkt {
@@ -256,7 +256,7 @@ struct hfi_msg_sys_debug_pkt {
u32 msg_size;
u32 time_stamp_hi;
u32 time_stamp_lo;
- u8 msg_data[1];
+ u8 msg_data[];
};
struct hfi_msg_sys_coverage_pkt {
@@ -264,7 +264,7 @@ struct hfi_msg_sys_coverage_pkt {
u32 msg_size;
u32 time_stamp_hi;
u32 time_stamp_lo;
- u8 msg_data[1];
+ u8 msg_data[];
};
struct venus_core;
diff --git a/drivers/media/platform/qcom/venus/hfi_plat_bufs.h b/drivers/media/platform/qcom/venus/hfi_plat_bufs.h
index 52a51a3b964a..25e607452096 100644
--- a/drivers/media/platform/qcom/venus/hfi_plat_bufs.h
+++ b/drivers/media/platform/qcom/venus/hfi_plat_bufs.h
@@ -12,8 +12,11 @@
struct hfi_plat_buffers_params {
u32 width;
u32 height;
+ u32 out_width;
+ u32 out_height;
u32 codec;
u32 hfi_color_fmt;
+ u32 hfi_dpb_color_fmt;
enum hfi_version version;
u32 num_vpp_pipes;
union {
diff --git a/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c b/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c
index a9be31ec6927..e97ff8cf6d64 100644
--- a/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c
+++ b/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c
@@ -1185,6 +1185,7 @@ static int bufreq_dec(struct hfi_plat_buffers_params *params, u32 buftype,
enum hfi_version version = params->version;
u32 codec = params->codec;
u32 width = params->width, height = params->height, out_min_count;
+ u32 out_width = params->out_width, out_height = params->out_height;
struct dec_bufsize_ops *dec_ops;
bool is_secondary_output = params->dec.is_secondary_output;
bool is_interlaced = params->dec.is_interlaced;
@@ -1230,12 +1231,16 @@ static int bufreq_dec(struct hfi_plat_buffers_params *params, u32 buftype,
calculate_dec_input_frame_size(width, height, codec,
max_mbs_per_frame,
buffer_size_limit);
- } else if (buftype == HFI_BUFFER_OUTPUT ||
- buftype == HFI_BUFFER_OUTPUT2) {
+ } else if (buftype == HFI_BUFFER_OUTPUT || buftype == HFI_BUFFER_OUTPUT2) {
bufreq->count_min = out_min_count;
bufreq->size =
venus_helper_get_framesz_raw(params->hfi_color_fmt,
- width, height);
+ out_width, out_height);
+ if (buftype == HFI_BUFFER_OUTPUT &&
+ params->dec.is_secondary_output)
+ bufreq->size =
+ venus_helper_get_framesz_raw(params->hfi_dpb_color_fmt,
+ out_width, out_height);
} else if (buftype == HFI_BUFFER_INTERNAL_SCRATCH(version)) {
bufreq->size = dec_ops->scratch(width, height, is_interlaced);
} else if (buftype == HFI_BUFFER_INTERNAL_SCRATCH_1(version)) {
diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c
index 2ad40b3945b0..f0b46389e8d5 100644
--- a/drivers/media/platform/qcom/venus/hfi_venus.c
+++ b/drivers/media/platform/qcom/venus/hfi_venus.c
@@ -835,34 +835,24 @@ static int venus_sys_set_debug(struct venus_hfi_device *hdev, u32 debug)
{
struct hfi_sys_set_property_pkt *pkt;
u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE];
- int ret;
pkt = (struct hfi_sys_set_property_pkt *)packet;
pkt_sys_debug_config(pkt, HFI_DEBUG_MODE_QUEUE, debug);
- ret = venus_iface_cmdq_write(hdev, pkt, false);
- if (ret)
- return ret;
-
- return 0;
+ return venus_iface_cmdq_write(hdev, pkt, false);
}
static int venus_sys_set_coverage(struct venus_hfi_device *hdev, u32 mode)
{
struct hfi_sys_set_property_pkt *pkt;
u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE];
- int ret;
pkt = (struct hfi_sys_set_property_pkt *)packet;
pkt_sys_coverage_config(pkt, mode);
- ret = venus_iface_cmdq_write(hdev, pkt, false);
- if (ret)
- return ret;
-
- return 0;
+ return venus_iface_cmdq_write(hdev, pkt, false);
}
static int venus_sys_set_idle_message(struct venus_hfi_device *hdev,
@@ -870,7 +860,6 @@ static int venus_sys_set_idle_message(struct venus_hfi_device *hdev,
{
struct hfi_sys_set_property_pkt *pkt;
u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE];
- int ret;
if (!enable)
return 0;
@@ -879,11 +868,7 @@ static int venus_sys_set_idle_message(struct venus_hfi_device *hdev,
pkt_sys_idle_indicator(pkt, enable);
- ret = venus_iface_cmdq_write(hdev, pkt, false);
- if (ret)
- return ret;
-
- return 0;
+ return venus_iface_cmdq_write(hdev, pkt, false);
}
static int venus_sys_set_power_control(struct venus_hfi_device *hdev,
@@ -891,17 +876,12 @@ static int venus_sys_set_power_control(struct venus_hfi_device *hdev,
{
struct hfi_sys_set_property_pkt *pkt;
u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE];
- int ret;
pkt = (struct hfi_sys_set_property_pkt *)packet;
pkt_sys_power_control(pkt, enable);
- ret = venus_iface_cmdq_write(hdev, pkt, false);
- if (ret)
- return ret;
-
- return 0;
+ return venus_iface_cmdq_write(hdev, pkt, false);
}
static int venus_sys_set_ubwc_config(struct venus_hfi_device *hdev)
diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c
index 51a53bf82bd3..f5676440dd36 100644
--- a/drivers/media/platform/qcom/venus/vdec.c
+++ b/drivers/media/platform/qcom/venus/vdec.c
@@ -30,69 +30,87 @@
* - future firmware versions could add support for >1 planes
*/
static const struct venus_format vdec_formats[] = {
- {
+ [VENUS_FMT_NV12] = {
.pixfmt = V4L2_PIX_FMT_NV12,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
- }, {
+ },
+ [VENUS_FMT_QC08C] = {
.pixfmt = V4L2_PIX_FMT_QC08C,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
- }, {
+ },
+ [VENUS_FMT_QC10C] = {
.pixfmt = V4L2_PIX_FMT_QC10C,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
- }, {
- .pixfmt = V4L2_PIX_FMT_MPEG4,
+ },
+ [VENUS_FMT_P010] = {
+ .pixfmt = V4L2_PIX_FMT_P010,
+ .num_planes = 1,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+ },
+ [VENUS_FMT_H264] = {
+ .pixfmt = V4L2_PIX_FMT_H264,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
- }, {
- .pixfmt = V4L2_PIX_FMT_MPEG2,
+ },
+ [VENUS_FMT_VP8] = {
+ .pixfmt = V4L2_PIX_FMT_VP8,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
- }, {
- .pixfmt = V4L2_PIX_FMT_H263,
+ },
+ [VENUS_FMT_VP9] = {
+ .pixfmt = V4L2_PIX_FMT_VP9,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
- }, {
- .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_G,
+ },
+ [VENUS_FMT_HEVC] = {
+ .pixfmt = V4L2_PIX_FMT_HEVC,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
- }, {
- .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_L,
+ },
+ [VENUS_FMT_VC1_ANNEX_G] = {
+ .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_G,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
- }, {
- .pixfmt = V4L2_PIX_FMT_H264,
+ },
+ [VENUS_FMT_VC1_ANNEX_L] = {
+ .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_L,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
- }, {
- .pixfmt = V4L2_PIX_FMT_VP8,
+ },
+ [VENUS_FMT_MPEG4] = {
+ .pixfmt = V4L2_PIX_FMT_MPEG4,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
- }, {
- .pixfmt = V4L2_PIX_FMT_VP9,
+ },
+ [VENUS_FMT_MPEG2] = {
+ .pixfmt = V4L2_PIX_FMT_MPEG2,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
- }, {
- .pixfmt = V4L2_PIX_FMT_XVID,
+ },
+ [VENUS_FMT_H263] = {
+ .pixfmt = V4L2_PIX_FMT_H263,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
- }, {
- .pixfmt = V4L2_PIX_FMT_HEVC,
+ },
+ [VENUS_FMT_XVID] = {
+ .pixfmt = V4L2_PIX_FMT_XVID,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
.flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
},
+
};
static const struct venus_format *
@@ -551,7 +569,7 @@ vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd)
fdata.buffer_type = HFI_BUFFER_INPUT;
fdata.flags |= HFI_BUFFERFLAG_EOS;
- if (IS_V6(inst->core))
+ if (IS_V6(inst->core) && is_fw_rev_or_older(inst->core, 1, 0, 87))
fdata.device_addr = 0;
else
fdata.device_addr = 0xdeadb000;
@@ -684,6 +702,14 @@ static int vdec_set_properties(struct venus_inst *inst)
return ret;
}
+ /* Enabling sufficient sequence change support for VP9 */
+ if (is_fw_rev_or_newer(inst->core, 5, 4, 51)) {
+ ptype = HFI_PROPERTY_PARAM_VDEC_ENABLE_SUFFICIENT_SEQCHANGE_EVENT;
+ ret = hfi_session_set_property(inst, ptype, &en);
+ if (ret)
+ return ret;
+ }
+
ptype = HFI_PROPERTY_PARAM_VDEC_CONCEAL_COLOR;
conceal = ctr->conceal_color & 0xffff;
conceal |= ((ctr->conceal_color >> 16) & 0xffff) << 10;
@@ -710,6 +736,9 @@ static int vdec_set_work_route(struct venus_inst *inst)
}
#define is_ubwc_fmt(fmt) (!!((fmt) & HFI_COLOR_FORMAT_UBWC_BASE))
+#define is_10bit_ubwc_fmt(fmt) (!!((fmt) & HFI_COLOR_FORMAT_10_BIT_BASE & \
+ HFI_COLOR_FORMAT_UBWC_BASE))
+
static int vdec_output_conf(struct venus_inst *inst)
{
@@ -757,7 +786,7 @@ static int vdec_output_conf(struct venus_inst *inst)
inst->opb_fmt = out2_fmt;
inst->dpb_buftype = HFI_BUFFER_OUTPUT;
inst->dpb_fmt = out_fmt;
- } else if (is_ubwc_fmt(out2_fmt)) {
+ } else if (is_ubwc_fmt(out2_fmt) || is_10bit_ubwc_fmt(out_fmt)) {
inst->opb_buftype = HFI_BUFFER_OUTPUT;
inst->opb_fmt = out_fmt;
inst->dpb_buftype = HFI_BUFFER_OUTPUT2;
@@ -1474,8 +1503,13 @@ static void vdec_event_change(struct venus_inst *inst,
inst->out_width = ev_data->width;
inst->out_height = ev_data->height;
- if (inst->bit_depth != ev_data->bit_depth)
+ if (inst->bit_depth != ev_data->bit_depth) {
inst->bit_depth = ev_data->bit_depth;
+ if (inst->bit_depth == VIDC_BITDEPTH_10)
+ inst->fmt_cap = &vdec_formats[VENUS_FMT_P010];
+ else
+ inst->fmt_cap = &vdec_formats[VENUS_FMT_NV12];
+ }
if (inst->pic_struct != ev_data->pic_struct)
inst->pic_struct = ev_data->pic_struct;
@@ -1567,8 +1601,8 @@ 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[8];
- inst->fmt_cap = &vdec_formats[0];
+ inst->fmt_out = &vdec_formats[VENUS_FMT_H264];
+ inst->fmt_cap = &vdec_formats[VENUS_FMT_NV12];
inst->width = frame_width_min(inst);
inst->height = ALIGN(frame_height_min(inst), 32);
inst->crop.left = 0;
@@ -1609,6 +1643,7 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
src_vq->allow_zero_bytesused = 1;
src_vq->min_buffers_needed = 0;
src_vq->dev = inst->core->dev;
+ src_vq->lock = &inst->ctx_q_lock;
ret = vb2_queue_init(src_vq);
if (ret)
return ret;
@@ -1623,6 +1658,7 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
dst_vq->allow_zero_bytesused = 1;
dst_vq->min_buffers_needed = 0;
dst_vq->dev = inst->core->dev;
+ dst_vq->lock = &inst->ctx_q_lock;
return vb2_queue_init(dst_vq);
}
@@ -1641,6 +1677,7 @@ static int vdec_open(struct file *file)
INIT_LIST_HEAD(&inst->internalbufs);
INIT_LIST_HEAD(&inst->list);
mutex_init(&inst->lock);
+ mutex_init(&inst->ctx_q_lock);
inst->core = core;
inst->session_type = VIDC_SESSION_TYPE_DEC;
@@ -1716,6 +1753,7 @@ static int vdec_close(struct file *file)
ida_destroy(&inst->dpb_ids);
hfi_session_destroy(inst);
mutex_destroy(&inst->lock);
+ mutex_destroy(&inst->ctx_q_lock);
v4l2_fh_del(&inst->fh);
v4l2_fh_exit(&inst->fh);
diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c
index 4666f42feea3..6d773b000e8a 100644
--- a/drivers/media/platform/qcom/venus/venc.c
+++ b/drivers/media/platform/qcom/venus/venc.c
@@ -32,28 +32,33 @@
* - future firmware versions could add support for >1 planes
*/
static const struct venus_format venc_formats[] = {
- {
+ [VENUS_FMT_NV12] = {
.pixfmt = V4L2_PIX_FMT_NV12,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
- }, {
- .pixfmt = V4L2_PIX_FMT_MPEG4,
+ },
+ [VENUS_FMT_H264] = {
+ .pixfmt = V4L2_PIX_FMT_H264,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
- }, {
- .pixfmt = V4L2_PIX_FMT_H263,
+ },
+ [VENUS_FMT_VP8] = {
+ .pixfmt = V4L2_PIX_FMT_VP8,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
- }, {
- .pixfmt = V4L2_PIX_FMT_H264,
+ },
+ [VENUS_FMT_HEVC] = {
+ .pixfmt = V4L2_PIX_FMT_HEVC,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
- }, {
- .pixfmt = V4L2_PIX_FMT_VP8,
+ },
+ [VENUS_FMT_MPEG4] = {
+ .pixfmt = V4L2_PIX_FMT_MPEG4,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
- }, {
- .pixfmt = V4L2_PIX_FMT_HEVC,
+ },
+ [VENUS_FMT_H263] = {
+ .pixfmt = V4L2_PIX_FMT_H263,
.num_planes = 1,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
},
@@ -1395,6 +1400,7 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
src_vq->allow_zero_bytesused = 1;
src_vq->min_buffers_needed = 1;
src_vq->dev = inst->core->dev;
+ src_vq->lock = &inst->ctx_q_lock;
if (inst->core->res->hfi_version == HFI_VERSION_1XX)
src_vq->bidirectional = 1;
ret = vb2_queue_init(src_vq);
@@ -1411,13 +1417,14 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
dst_vq->allow_zero_bytesused = 1;
dst_vq->min_buffers_needed = 1;
dst_vq->dev = inst->core->dev;
+ dst_vq->lock = &inst->ctx_q_lock;
return vb2_queue_init(dst_vq);
}
static void venc_inst_init(struct venus_inst *inst)
{
- inst->fmt_cap = &venc_formats[3];
- inst->fmt_out = &venc_formats[0];
+ inst->fmt_cap = &venc_formats[VENUS_FMT_H264];
+ inst->fmt_out = &venc_formats[VENUS_FMT_NV12];
inst->width = 1280;
inst->height = ALIGN(720, 32);
inst->out_width = 1280;
@@ -1443,6 +1450,7 @@ static int venc_open(struct file *file)
INIT_LIST_HEAD(&inst->internalbufs);
INIT_LIST_HEAD(&inst->list);
mutex_init(&inst->lock);
+ mutex_init(&inst->ctx_q_lock);
inst->core = core;
inst->session_type = VIDC_SESSION_TYPE_ENC;
@@ -1512,6 +1520,7 @@ static int venc_close(struct file *file)
venc_ctrl_deinit(inst);
hfi_session_destroy(inst);
mutex_destroy(&inst->lock);
+ mutex_destroy(&inst->ctx_q_lock);
v4l2_fh_del(&inst->fh);
v4l2_fh_exit(&inst->fh);