Переглянути джерело

video: driver: add queue buffer support

Add queue buffer support for sending buffers to
firmware.

Change-Id: Ie573c10a9b2f32a3eb202f97227b5e7edea26705
Signed-off-by: Maheshwar Ajja <[email protected]>
Maheshwar Ajja 4 роки тому
батько
коміт
ec2f06a4ba

+ 1 - 0
driver/vidc/inc/msm_vdec.h

@@ -13,6 +13,7 @@ int msm_vdec_stop_input(struct msm_vidc_inst *inst);
 int msm_vdec_start_input(struct msm_vidc_inst *inst);
 int msm_vdec_stop_output(struct msm_vidc_inst *inst);
 int msm_vdec_start_output(struct msm_vidc_inst *inst);
+int msm_vdec_qbuf(struct msm_vidc_inst *inst, struct vb2_buffer *vb2);
 int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
 int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
 int msm_vdec_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f);

+ 27 - 11
driver/vidc/inc/msm_vidc_driver.h

@@ -66,11 +66,17 @@ static inline bool is_thumbnail_session(struct msm_vidc_inst *inst)
 	return false; // TODO: fix it
 }
 
-u32 get_v4l2_codec_from_vidc(enum msm_vidc_codec_type codec);
-enum msm_vidc_codec_type get_vidc_codec_from_v4l2(u32 v4l2_codec);
-u32 get_v4l2_colorformat_from_vidc(enum msm_vidc_colorformat_type colorformat);
-enum msm_vidc_colorformat_type get_vidc_colorformat_from_v4l2(u32 colorformat);
-u32 get_media_colorformat_from_v4l2(u32 v4l2_fmt);
+void print_vidc_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
+		struct msm_vidc_buffer *vbuf);
+void print_vb2_buffer(const char *str, struct msm_vidc_inst *inst,
+		struct vb2_buffer *vb2);
+enum msm_vidc_codec_type v4l2_codec_to_driver(u32 v4l2_codec);
+u32 v4l2_codec_from_driver(enum msm_vidc_codec_type codec);
+u32 v4l2_colorformat_to_media(u32 v4l2_fmt);
+enum msm_vidc_colorformat_type v4l2_colorformat_to_driver(u32 colorformat);
+u32 v4l2_colorformat_from_driver(enum msm_vidc_colorformat_type colorformat);
+int v4l2_type_to_driver_port(struct msm_vidc_inst *inst, u32 type,
+	const char *func);
 int msm_vidc_change_inst_state(struct msm_vidc_inst *inst,
 	enum msm_vidc_inst_state state, const char *func);
 int msm_vidc_create_internal_buffers(struct msm_vidc_inst *inst,
@@ -94,16 +100,26 @@ void msm_vidc_batch_handler(struct work_struct *work);
 int msm_vidc_setup_event_queue(struct msm_vidc_inst *inst);
 int msm_vidc_vb2_queue_init(struct msm_vidc_inst *inst);
 int msm_vidc_get_control(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl);
-int msm_vidc_get_port_from_v4l2_type(struct msm_vidc_inst *inst, u32 type,
-	const char *func);
 u32 msm_vidc_get_buffer_region(struct msm_vidc_inst *inst,
 	enum msm_vidc_buffer_type buffer_type, const char *func);
-struct msm_vidc_buffer_info *msm_vidc_get_buffer_info(struct msm_vidc_inst *inst,
+struct msm_vidc_buffers *msm_vidc_get_buffers(struct msm_vidc_inst *inst,
 	enum msm_vidc_buffer_type buffer_type, const char *func);
-struct msm_vidc_map_info *msm_vidc_get_map_info(struct msm_vidc_inst *inst,
-	enum msm_vidc_buffer_type buffer_type, const char *func);
-struct msm_vidc_alloc_info *msm_vidc_get_alloc_info(struct msm_vidc_inst *inst,
+struct msm_vidc_mappings *msm_vidc_get_mappings(struct msm_vidc_inst *inst,
 	enum msm_vidc_buffer_type buffer_type, const char *func);
+struct msm_vidc_allocations *msm_vidc_get_allocations(
+	struct msm_vidc_inst *inst, enum msm_vidc_buffer_type buffer_type,
+	const char *func);
+struct msm_vidc_buffer *msm_vidc_get_driver_buf(struct msm_vidc_inst *inst,
+	struct vb2_buffer *vb2);
+int msm_vidc_unmap_driver_buf(struct msm_vidc_inst *inst,
+	struct msm_vidc_buffer *buf);
+int msm_vidc_map_driver_buf(struct msm_vidc_inst *inst,
+	struct msm_vidc_buffer *buf);
+int msm_vidc_put_driver_buf(struct msm_vidc_inst *inst,
+	struct msm_vidc_buffer *buf);
+int msm_vidc_queue_buffer(struct msm_vidc_inst *inst, struct vb2_buffer *vb2);
+struct msm_vidc_buffer *get_meta_buffer(struct msm_vidc_inst *inst,
+	struct msm_vidc_buffer *vbuf);
 struct msm_vidc_inst *get_inst(struct msm_vidc_core *core,
 		u32 session_id);
 void put_inst(struct msm_vidc_inst *inst);

+ 29 - 29
driver/vidc/inc/msm_vidc_inst.h

@@ -25,36 +25,36 @@ struct msm_vidc_session_ops {
 	int (*extra_count)(struct msm_vidc_inst *inst, enum msm_vidc_buffer_type type);
 };
 
-struct msm_vidc_allocations {
-	struct msm_vidc_alloc_info        scratch;
-	struct msm_vidc_alloc_info        scratch_1;
-	struct msm_vidc_alloc_info        scratch_2;
-	struct msm_vidc_alloc_info        persist;
-	struct msm_vidc_alloc_info        persist_1;
+struct msm_vidc_allocations_info {
+	struct msm_vidc_allocations     scratch;
+	struct msm_vidc_allocations     scratch_1;
+	struct msm_vidc_allocations     scratch_2;
+	struct msm_vidc_allocations     persist;
+	struct msm_vidc_allocations     persist_1;
 };
 
-struct msm_vidc_maps {
-	struct msm_vidc_map_info        input;
-	struct msm_vidc_map_info        output;
-	struct msm_vidc_map_info        input_meta;
-	struct msm_vidc_map_info        output_meta;
-	struct msm_vidc_map_info        scratch;
-	struct msm_vidc_map_info        scratch_1;
-	struct msm_vidc_map_info        scratch_2;
-	struct msm_vidc_map_info        persist;
-	struct msm_vidc_map_info        persist_1;
+struct msm_vidc_mappings_info {
+	struct msm_vidc_mappings        input;
+	struct msm_vidc_mappings        output;
+	struct msm_vidc_mappings        input_meta;
+	struct msm_vidc_mappings        output_meta;
+	struct msm_vidc_mappings        scratch;
+	struct msm_vidc_mappings        scratch_1;
+	struct msm_vidc_mappings        scratch_2;
+	struct msm_vidc_mappings        persist;
+	struct msm_vidc_mappings        persist_1;
 };
 
-struct msm_vidc_buffers {
-	struct msm_vidc_buffer_info        input;
-	struct msm_vidc_buffer_info        output;
-	struct msm_vidc_buffer_info        input_meta;
-	struct msm_vidc_buffer_info        output_meta;
-	struct msm_vidc_buffer_info        scratch;
-	struct msm_vidc_buffer_info        scratch_1;
-	struct msm_vidc_buffer_info        scratch_2;
-	struct msm_vidc_buffer_info        persist;
-	struct msm_vidc_buffer_info        persist_1;
+struct msm_vidc_buffers_info {
+	struct msm_vidc_buffers        input;
+	struct msm_vidc_buffers        output;
+	struct msm_vidc_buffers        input_meta;
+	struct msm_vidc_buffers        output_meta;
+	struct msm_vidc_buffers        scratch;
+	struct msm_vidc_buffers        scratch_1;
+	struct msm_vidc_buffers        scratch_2;
+	struct msm_vidc_buffers        persist;
+	struct msm_vidc_buffers        persist_1;
 };
 
 enum msm_vidc_inst_state {
@@ -96,9 +96,9 @@ struct msm_vidc_inst {
 	struct msm_vidc_crop               crop;
 	struct msm_vidc_properties         prop;
 	struct msm_vidc_power              power;
-	struct msm_vidc_buffers            buffers;
-	struct msm_vidc_maps               maps;
-	struct msm_vidc_allocations        allocations;
+	struct msm_vidc_buffers_info       buffers;
+	struct msm_vidc_mappings_info      mappings;
+	struct msm_vidc_allocations_info   allocations;
 	bool                               subscribed_input_psc;
 	bool                               subscribed_output_psc;
 	bool                               subscribed_input_prop;

+ 6 - 6
driver/vidc/inc/msm_vidc_internal.h

@@ -115,7 +115,7 @@ enum msm_vidc_buffer_type {
 };
 
 enum msm_vidc_buffer_attributes {
-	MSM_VIDC_ATTR_DEFERRED_SUBMISSION       = BIT(0),
+	MSM_VIDC_ATTR_DEFERRED                  = BIT(0),
 	MSM_VIDC_ATTR_READ_ONLY                 = BIT(1),
 	MSM_VIDC_ATTR_PENDING_RELEASE           = BIT(2),
 	MSM_VIDC_ATTR_QUEUED                    = BIT(3),
@@ -487,7 +487,7 @@ struct msm_vidc_power {
 
 struct msm_vidc_alloc {
 	struct list_head            list;
-	enum msm_vidc_buffer_type   buffer_type;
+	enum msm_vidc_buffer_type   type;
 	enum msm_vidc_buffer_region region;
 	u32                         size;
 	u8                          cached:1;
@@ -497,14 +497,14 @@ struct msm_vidc_alloc {
 	void                       *kvaddr;
 };
 
-struct msm_vidc_alloc_info {
+struct msm_vidc_allocations {
 	struct list_head            list; // list of "struct msm_vidc_alloc"
 };
 
 struct msm_vidc_map {
 	struct list_head            list;
 	bool                        valid;
-	enum msm_vidc_buffer_type   buffer_type;
+	enum msm_vidc_buffer_type   type;
 	enum msm_vidc_buffer_region region;
 	struct dma_buf             *dmabuf;
 	u32                         refcount;
@@ -513,7 +513,7 @@ struct msm_vidc_map {
 	struct dma_buf_attachment  *attach;
 };
 
-struct msm_vidc_map_info {
+struct msm_vidc_mappings {
 	struct list_head            list; // list of "struct msm_vidc_map"
 };
 
@@ -533,7 +533,7 @@ struct msm_vidc_buffer {
 	enum msm_vidc_buffer_attributes    attr;
 };
 
-struct msm_vidc_buffer_info {
+struct msm_vidc_buffers {
 	struct list_head       list; // list of "struct msm_vidc_buffer"
 	u32                    min_count;
 	u32                    extra_count;

+ 54 - 15
driver/vidc/src/msm_vdec.c

@@ -22,7 +22,7 @@ static int msm_vdec_codec_change(struct msm_vidc_inst *inst, u32 codec)
 
 	d_vpr_h("%s()\n", __func__);
 
-	inst->codec = get_vidc_codec_from_v4l2(codec);
+	inst->codec = v4l2_codec_to_driver(codec);
 	rc = msm_vidc_get_inst_capability(inst);
 	return rc;
 }
@@ -45,7 +45,6 @@ static int msm_vdec_get_input_internal_buffers(struct msm_vidc_inst *inst)
 	int rc = 0;
 	struct msm_vidc_core *core;
 
-	d_vpr_h("%s()\n", __func__);
 	if (!inst || !inst->core) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
@@ -66,6 +65,17 @@ static int msm_vdec_get_input_internal_buffers(struct msm_vidc_inst *inst)
 	inst->buffers.persist_1.min_count = call_session_op(core, min_count,
 			inst, MSM_VIDC_BUF_PERSIST_1);
 
+	s_vpr_h(inst->sid, "internal buffer: min     size\n");
+        s_vpr_h(inst->sid, "scratch  buffer: %d      %d\n",
+		inst->buffers.scratch.min_count,
+		inst->buffers.scratch.size);
+	s_vpr_h(inst->sid, "scratch1 buffer: %d      %d\n",
+		inst->buffers.scratch_1.min_count,
+		inst->buffers.scratch_1.size);
+	s_vpr_h(inst->sid, "persist1 buffer: %d      %d\n",
+		inst->buffers.persist_1.min_count,
+		inst->buffers.persist_1.size);
+
 	return rc;
 }
 
@@ -298,8 +308,8 @@ int msm_vdec_start_input(struct msm_vidc_inst *inst)
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
 	}
-	d_vpr_h("%s()\n", __func__);
 	core = inst->core;
+	s_vpr_h(inst->sid, "%s()\n", __func__);
 
 	//rc = msm_vidc_check_session_supported(inst);
 	if (rc)
@@ -330,24 +340,30 @@ int msm_vdec_start_input(struct msm_vidc_inst *inst)
 	//msm_vidc_scale_power(inst);
 
 	rc = msm_vdec_set_input_properties(inst);
+	rc = 0; // TODO
 	if (rc)
 		goto error;
 	rc = msm_vdec_create_input_internal_buffers(inst);
+	rc = 0; // TODO
 	if (rc)
 		goto error;
 	rc = msm_vdec_queue_input_internal_buffers(inst);
+	rc = 0; // TODO
 	if (rc)
 		goto error;
 
 	rc = msm_vdec_port_settings_subscription(inst, INPUT_PORT);
+	rc = 0; // TODO
 	if (rc)
 		goto error;
 
 	rc = msm_vdec_property_subscription(inst, INPUT_PORT);
+	rc = 0; // TODO
 	if (rc)
 		goto error;
 
 	rc = msm_vdec_metadata_delivery(inst, INPUT_PORT);
+	rc = 0; // TODO
 	if (rc)
 		goto error;
 
@@ -355,14 +371,11 @@ int msm_vdec_start_input(struct msm_vidc_inst *inst)
 	if (rc)
 		goto error;
 
-	rc = msm_vidc_change_inst_state(inst, MSM_VIDC_START_INPUT, __func__);
-	if (rc)
-		goto error;
-
-	d_vpr_h("%s: done\n", __func__);
+	s_vpr_h(inst->sid, "%s: done\n", __func__);
 	return 0;
 
 error:
+	s_vpr_e(inst->sid, "%s: failed\n", __func__);
 	msm_vdec_stop_input(inst);
 	return rc;
 }
@@ -410,6 +423,32 @@ error:
 	return rc;
 }
 
+static int msm_vdec_qbuf_batch(struct msm_vidc_inst *inst,
+	struct vb2_buffer *vb2)
+{
+	int rc = 0;
+
+	if (!inst || !vb2) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+	d_vpr_h("%s()\n", __func__);
+
+	return rc;
+}
+
+int msm_vdec_qbuf(struct msm_vidc_inst *inst, struct vb2_buffer *vb2)
+{
+	int rc = 0;
+
+	if (inst->decode_batch.enable)
+		rc = msm_vdec_qbuf_batch(inst, vb2);
+	else
+		rc = msm_vidc_queue_buffer(inst, vb2);
+
+	return rc;
+}
+
 int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
 {
 	int rc = 0;
@@ -515,10 +554,10 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
 		fmt->type = OUTPUT_PLANE;
 		fmt->fmt.pix.pixelformat = f->fmt.pix.pixelformat;
 		fmt->fmt.pix.width = VENUS_Y_STRIDE(
-			get_media_colorformat_from_v4l2(fmt->fmt.pix.pixelformat),
+			v4l2_colorformat_to_media(fmt->fmt.pix.pixelformat),
 			f->fmt.pix.width);
 		fmt->fmt.pix.height = VENUS_Y_SCANLINES(
-			get_media_colorformat_from_v4l2(fmt->fmt.pix.pixelformat),
+			v4l2_colorformat_to_media(fmt->fmt.pix.pixelformat),
 			f->fmt.pix.height);
 		fmt->fmt.pix.bytesperline = fmt->fmt.pix.width;
 		fmt->fmt.pix.sizeimage = call_session_op(core, buffer_size,
@@ -588,7 +627,7 @@ int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
 		return -EINVAL;
 	}
 
-	port = msm_vidc_get_port_from_v4l2_type(inst, f->type, __func__);
+	port = v4l2_type_to_driver_port(inst, f->type, __func__);
 	if (port < 0)
 		return -EINVAL;
 
@@ -623,7 +662,7 @@ int msm_vdec_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f)
 			i++;
 			codecs >>= 1;
 		}
-		f->pixelformat = get_v4l2_codec_from_vidc(array[f->index]);
+		f->pixelformat = v4l2_codec_from_driver(array[f->index]);
 		if (!f->pixelformat)
 			return -EINVAL;
 		f->flags = V4L2_FMT_FLAG_COMPRESSED;
@@ -641,7 +680,7 @@ int msm_vdec_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f)
 			i++;
 			formats >>= 1;
 		}
-		f->pixelformat = get_v4l2_colorformat_from_vidc(array[f->index]);
+		f->pixelformat = v4l2_colorformat_from_driver(array[f->index]);
 		if (!f->pixelformat)
 			return -EINVAL;
 		strlcpy(f->description, "colorformat", sizeof(f->description));
@@ -710,9 +749,9 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst)
 	f->type = OUTPUT_PLANE;
 	f->fmt.pix.pixelformat = V4L2_PIX_FMT_NV12_UBWC;
 	f->fmt.pix.width = VENUS_Y_STRIDE(
-		get_media_colorformat_from_v4l2(f->fmt.pix.pixelformat), DEFAULT_WIDTH);
+		v4l2_colorformat_to_media(f->fmt.pix.pixelformat), DEFAULT_WIDTH);
 	f->fmt.pix.height = VENUS_Y_SCANLINES(
-		get_media_colorformat_from_v4l2(f->fmt.pix.pixelformat), DEFAULT_HEIGHT);
+		v4l2_colorformat_to_media(f->fmt.pix.pixelformat), DEFAULT_HEIGHT);
 	f->fmt.pix.bytesperline = f->fmt.pix.width;
 	f->fmt.pix.sizeimage = call_session_op(core, buffer_size,
 			inst, MSM_VIDC_BUF_OUTPUT);

+ 8 - 8
driver/vidc/src/msm_venc.c

@@ -20,7 +20,7 @@ static int msm_venc_codec_change(struct msm_vidc_inst *inst, u32 codec)
 
 	d_vpr_h("%s()\n", __func__);
 
-	inst->codec = get_vidc_codec_from_v4l2(codec);
+	inst->codec = v4l2_codec_to_driver(codec);
 	rc = msm_vidc_get_inst_capability(inst);
 	return rc;
 }
@@ -52,10 +52,10 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
 		fmt->type = INPUT_PLANE;
 		fmt->fmt.pix.pixelformat = f->fmt.pix.pixelformat;
 		fmt->fmt.pix.width = VENUS_Y_STRIDE(
-			get_media_colorformat_from_v4l2(fmt->fmt.pix.pixelformat),
+			v4l2_colorformat_to_media(fmt->fmt.pix.pixelformat),
 			f->fmt.pix.width);
 		fmt->fmt.pix.height = VENUS_Y_SCANLINES(
-			get_media_colorformat_from_v4l2(fmt->fmt.pix.pixelformat),
+			v4l2_colorformat_to_media(fmt->fmt.pix.pixelformat),
 			f->fmt.pix.height);
 		fmt->fmt.pix.bytesperline = fmt->fmt.pix.width;
 		fmt->fmt.pix.sizeimage = call_session_op(core, buffer_size,
@@ -205,7 +205,7 @@ int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
 		return -EINVAL;
 	}
 
-	port = msm_vidc_get_port_from_v4l2_type(inst, f->type, __func__);
+	port = v4l2_type_to_driver_port(inst, f->type, __func__);
 	if (port < 0)
 		return -EINVAL;
 
@@ -240,7 +240,7 @@ int msm_venc_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f)
 			i++;
 			codecs >>= 1;
 		}
-		f->pixelformat = get_v4l2_codec_from_vidc(array[f->index]);
+		f->pixelformat = v4l2_codec_from_driver(array[f->index]);
 		if (!f->pixelformat)
 			return -EINVAL;
 		f->flags = V4L2_FMT_FLAG_COMPRESSED;
@@ -258,7 +258,7 @@ int msm_venc_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f)
 			i++;
 			formats >>= 1;
 		}
-		f->pixelformat = get_v4l2_colorformat_from_vidc(array[f->index]);
+		f->pixelformat = v4l2_colorformat_from_driver(array[f->index]);
 		if (!f->pixelformat)
 			return -EINVAL;
 		strlcpy(f->description, "colorformat", sizeof(f->description));
@@ -325,9 +325,9 @@ int msm_venc_inst_init(struct msm_vidc_inst *inst)
 	f->type = INPUT_PLANE;
 	f->fmt.pix.pixelformat = V4L2_PIX_FMT_NV12_UBWC;
 	f->fmt.pix.width = VENUS_Y_STRIDE(
-		get_media_colorformat_from_v4l2(f->fmt.pix.pixelformat), DEFAULT_WIDTH);
+		v4l2_colorformat_to_media(f->fmt.pix.pixelformat), DEFAULT_WIDTH);
 	f->fmt.pix.height = VENUS_Y_SCANLINES(
-		get_media_colorformat_from_v4l2(f->fmt.pix.pixelformat), DEFAULT_HEIGHT);
+		v4l2_colorformat_to_media(f->fmt.pix.pixelformat), DEFAULT_HEIGHT);
 	f->fmt.pix.bytesperline = f->fmt.pix.width;
 	f->fmt.pix.sizeimage = call_session_op(core, buffer_size,
 			inst, MSM_VIDC_BUF_INPUT);

+ 95 - 18
driver/vidc/src/msm_vidc.c

@@ -319,7 +319,8 @@ int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b)
 			s_vpr_e(inst->sid,
 				"%s: reqbufs(%d) not allowed in %d state\n",
 				__func__, b->type, inst->state);
-			return -EINVAL;
+			rc = -EINVAL;
+			goto unlock;
 		}
 	} else if (b->type == OUTPUT_PLANE) {
 		if (inst->state != MSM_VIDC_OPEN &&
@@ -328,13 +329,16 @@ int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b)
 			s_vpr_e(inst->sid,
 				"%s: reqbufs(%d) not allowed in %d state\n",
 				__func__, b->type, inst->state);
-			return -EINVAL;
+			rc = -EINVAL;
+			goto unlock;
 		}
 	}
 
-	port = msm_vidc_get_port_from_v4l2_type(inst, b->type, __func__);
-	if (port < 0)
-		return -EINVAL;
+	port = v4l2_type_to_driver_port(inst, b->type, __func__);
+	if (port < 0) {
+		rc = -EINVAL;
+		goto unlock;
+	}
 
 	rc = vb2_reqbufs(&inst->vb2q[port], b);
 	if (rc) {
@@ -352,13 +356,85 @@ EXPORT_SYMBOL(msm_vidc_reqbufs);
 int msm_vidc_qbuf(void *instance, struct media_device *mdev,
 		struct v4l2_buffer *b)
 {
-	return 0;
+	int rc = 0;
+	struct msm_vidc_inst *inst = instance;
+	struct vb2_queue *q;
+
+	if (!inst || !inst->core || !b || !valid_v4l2_buffer(b, inst)) {
+		d_vpr_e("%s: invalid params %pK %pK\n", __func__, inst, b);
+		return -EINVAL;
+	}
+
+	mutex_lock(&inst->lock);
+
+	if (inst->state == MSM_VIDC_ERROR) {
+		s_vpr_e(inst->sid, "%s: error state\n", __func__);
+		rc = -EINVAL;
+		goto unlock;
+	}
+	if (b->type == INPUT_PLANE) {
+		q = &inst->vb2q[INPUT_PORT];
+	} else if (b->type == OUTPUT_PLANE) {
+		q = &inst->vb2q[OUTPUT_PORT];
+	} else if (b->type == INPUT_META_PLANE) {
+		q = &inst->vb2q[INPUT_META_PORT];
+	} else if (b->type == OUTPUT_META_PLANE) {
+		q = &inst->vb2q[OUTPUT_META_PORT];
+	} else {
+		s_vpr_e(inst->sid, "%s: invalid buffer type %d\n",
+			__func__, b->type);
+		rc = -EINVAL;
+		goto unlock;
+	}
+
+	rc = vb2_qbuf(q, mdev, b);
+	if (rc)
+		s_vpr_e(inst->sid, "%s: failed with %d\n", __func__, rc);
+
+unlock:
+	mutex_unlock(&inst->lock);
+	return rc;
 }
 EXPORT_SYMBOL(msm_vidc_qbuf);
 
 int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b)
 {
-	return 0;
+	int rc = 0;
+	struct msm_vidc_inst *inst = instance;
+	struct vb2_queue *q;
+
+	if (!inst || !b || !valid_v4l2_buffer(b, inst)) {
+		d_vpr_e("%s: invalid params %pK %pK\n", __func__, inst, b);
+		return -EINVAL;
+	}
+
+	mutex_lock(&inst->lock);
+	if (b->type == INPUT_PLANE) {
+		q = &inst->vb2q[INPUT_PORT];
+	} else if (b->type == OUTPUT_PLANE) {
+		q = &inst->vb2q[OUTPUT_PORT];
+	} else if (b->type == INPUT_META_PLANE) {
+		q = &inst->vb2q[INPUT_META_PORT];
+	} else if (b->type == OUTPUT_META_PLANE) {
+		q = &inst->vb2q[OUTPUT_META_PORT];
+	} else {
+		s_vpr_e(inst->sid, "%s: invalid buffer type %d\n",
+			__func__, b->type);
+		rc = -EINVAL;
+		goto unlock;
+	}
+
+	rc = vb2_dqbuf(q, b, true);
+	if (rc == -EAGAIN) {
+		goto unlock;
+	} else if (rc) {
+		s_vpr_e(inst->sid, "%s: failed with %d\n", __func__, rc);
+		goto unlock;
+	}
+
+unlock:
+	mutex_unlock(&inst->lock);
+	return rc;
 }
 EXPORT_SYMBOL(msm_vidc_dqbuf);
 
@@ -397,7 +473,7 @@ int msm_vidc_streamon(void *instance, enum v4l2_buf_type type)
 		}
 	}
 
-	port = msm_vidc_get_port_from_v4l2_type(inst, type, __func__);
+	port = v4l2_type_to_driver_port(inst, type, __func__);
 	if (port < 0) {
 		rc = -EINVAL;
 		goto unlock;
@@ -475,7 +551,7 @@ int msm_vidc_streamoff(void *instance, enum v4l2_buf_type type)
 		}
 	}
 
-	port = msm_vidc_get_port_from_v4l2_type(inst, type, __func__);
+	port = v4l2_type_to_driver_port(inst, type, __func__);
 	if (port < 0) {
 		rc = -EINVAL;
 		goto unlock;
@@ -676,6 +752,7 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
 	s_vpr_i(inst->sid, "Opening video instance: %d\n", session_type);
 
 	kref_init(&inst->kref);
+	mutex_init(&inst->lock);
 	INIT_LIST_HEAD(&inst->buffers.input.list);
 	INIT_LIST_HEAD(&inst->buffers.input_meta.list);
 	INIT_LIST_HEAD(&inst->buffers.output.list);
@@ -690,15 +767,15 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
 	INIT_LIST_HEAD(&inst->allocations.scratch_2.list);
 	INIT_LIST_HEAD(&inst->allocations.persist.list);
 	INIT_LIST_HEAD(&inst->allocations.persist_1.list);
-	INIT_LIST_HEAD(&inst->maps.input.list);
-	INIT_LIST_HEAD(&inst->maps.input_meta.list);
-	INIT_LIST_HEAD(&inst->maps.output.list);
-	INIT_LIST_HEAD(&inst->maps.output_meta.list);
-	INIT_LIST_HEAD(&inst->maps.scratch.list);
-	INIT_LIST_HEAD(&inst->maps.scratch_1.list);
-	INIT_LIST_HEAD(&inst->maps.scratch_2.list);
-	INIT_LIST_HEAD(&inst->maps.persist.list);
-	INIT_LIST_HEAD(&inst->maps.persist_1.list);
+	INIT_LIST_HEAD(&inst->mappings.input.list);
+	INIT_LIST_HEAD(&inst->mappings.input_meta.list);
+	INIT_LIST_HEAD(&inst->mappings.output.list);
+	INIT_LIST_HEAD(&inst->mappings.output_meta.list);
+	INIT_LIST_HEAD(&inst->mappings.scratch.list);
+	INIT_LIST_HEAD(&inst->mappings.scratch_1.list);
+	INIT_LIST_HEAD(&inst->mappings.scratch_2.list);
+	INIT_LIST_HEAD(&inst->mappings.persist.list);
+	INIT_LIST_HEAD(&inst->mappings.persist_1.list);
 	INIT_LIST_HEAD(&inst->children.list);
 	INIT_LIST_HEAD(&inst->firmware.list);
 	inst->domain = session_type;

+ 16 - 6
driver/vidc/src/msm_vidc_buffer.c

@@ -139,18 +139,23 @@ u32 msm_vidc_output_extra_count(struct msm_vidc_inst *inst)
 
 u32 msm_vidc_decoder_input_size(struct msm_vidc_inst *inst)
 {
-	return ALIGN(15 * 1024 * 1024, SZ_4K);
+	u32 size = ALIGN(15 * 1024 * 1024, SZ_4K);
+	size = 4; // TODO
+	return size;
 }
 
 u32 msm_vidc_decoder_output_size(struct msm_vidc_inst *inst)
 {
+	u32 size;
 	u32 format;
 	struct v4l2_format *f;
 
 	f = &inst->fmts[OUTPUT_PORT];
-	format = get_media_colorformat_from_v4l2(f->fmt.pix.pixelformat);
-	return VENUS_BUFFER_SIZE(format, f->fmt.pix.width,
+	format = v4l2_colorformat_to_media(f->fmt.pix.pixelformat);
+	size = VENUS_BUFFER_SIZE(format, f->fmt.pix.width,
 			f->fmt.pix.height);
+	size = 4; // TODO
+	return size;
 }
 
 u32 msm_vidc_decoder_input_meta_size(struct msm_vidc_inst *inst)
@@ -165,18 +170,23 @@ u32 msm_vidc_decoder_output_meta_size(struct msm_vidc_inst *inst)
 
 u32 msm_vidc_encoder_input_size(struct msm_vidc_inst *inst)
 {
+	u32 size;
 	u32 format;
 	struct v4l2_format *f;
 
 	f = &inst->fmts[INPUT_PORT];
-	format = get_media_colorformat_from_v4l2(f->fmt.pix.pixelformat);
-	return VENUS_BUFFER_SIZE(format, f->fmt.pix.width,
+	format = v4l2_colorformat_to_media(f->fmt.pix.pixelformat);
+	size = VENUS_BUFFER_SIZE(format, f->fmt.pix.width,
 			f->fmt.pix.height);
+	size = 4; // TODO
+	return size;
 }
 
 u32 msm_vidc_encoder_output_size(struct msm_vidc_inst *inst)
 {
-	return ALIGN(15 * 1024 * 1024, SZ_4K);
+	u32 size = ALIGN(15 * 1024 * 1024, SZ_4K);
+	size = 4; // TODO
+	return size;
 }
 
 u32 msm_vidc_encoder_input_meta_size(struct msm_vidc_inst *inst)

+ 1 - 6
driver/vidc/src/msm_vidc_control.c

@@ -273,7 +273,7 @@ int msm_vidc_ctrl_init(struct msm_vidc_inst *inst)
 	core = inst->core;
 	capability = inst->capabilities;
 
-	if (core->v4l2_ctrl_ops) {
+	if (!core->v4l2_ctrl_ops) {
 		s_vpr_e(inst->sid, "%s: no control ops\n", __func__);
 		return -EINVAL;
 	}
@@ -300,11 +300,6 @@ int msm_vidc_ctrl_init(struct msm_vidc_inst *inst)
 		return rc;
 	}
 
-	if (!core->v4l2_ctrl_ops) {
-		s_vpr_e(inst->sid, "%s: no control ops\n", __func__);
-		return -EINVAL;
-	}
-
 	for (idx = 0; idx < INST_CAP_MAX; idx++) {
 		struct v4l2_ctrl *ctrl;
 

+ 452 - 59
driver/vidc/src/msm_vidc_driver.c

@@ -23,11 +23,97 @@
 	}                           \
 })
 
-void print_vidc_buffer(struct msm_vidc_inst *inst, struct msm_vidc_buffer *b)
+void print_vidc_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
+		struct msm_vidc_buffer *vbuf)
 {
+	struct msm_vidc_buffer *mbuf;
+
+	if (!(tag & msm_vidc_debug) || !inst || !vbuf)
+		return;
+
+	mbuf = get_meta_buffer(inst, vbuf);
+	if (!mbuf)
+		dprintk(tag, inst->sid,
+			"%s: %s: idx %2d fd %3d off %d daddr %#x size %d filled %d flags %#x ts %lld attr %#x\n",
+			str, vbuf->type == MSM_VIDC_BUF_INPUT ? "INPUT" : "OUTPUT",
+			vbuf->index, vbuf->fd, vbuf->data_offset,
+			vbuf->device_addr, vbuf->buffer_size, vbuf->data_size,
+			vbuf->flags, vbuf->timestamp, vbuf->attr);
+	else
+		dprintk(tag, inst->sid,
+			"%s: %s: idx %2d fd %3d off %d daddr %#x size %d filled %d flags %#x ts %lld attr %#x meta: fd %3d daddr %#x size %d\n",
+			str, vbuf->type == MSM_VIDC_BUF_INPUT ? "INPUT" : "OUTPUT",
+			vbuf->index, vbuf->fd, vbuf->data_offset,
+			vbuf->device_addr, vbuf->buffer_size, vbuf->data_size,
+			vbuf->flags, vbuf->timestamp, vbuf->attr,
+			mbuf->fd, mbuf->device_addr, mbuf->buffer_size);
 }
 
-enum msm_vidc_codec_type get_vidc_codec_from_v4l2(u32 v4l2_codec)
+void print_vb2_buffer(const char *str, struct msm_vidc_inst *inst,
+		struct vb2_buffer *vb2)
+{
+	if (!inst || !vb2)
+		return;
+
+	s_vpr_e(inst->sid,
+		"%s: %s: idx %2d fd %d off %d size %d filled %d\n",
+		str, vb2->type == INPUT_PLANE ? "INPUT" : "OUTPUT",
+		vb2->index, vb2->planes[0].m.fd,
+		vb2->planes[0].data_offset, vb2->planes[0].length,
+		vb2->planes[0].bytesused);
+}
+
+enum msm_vidc_buffer_type v4l2_type_to_driver(u32 type)
+{
+	enum msm_vidc_buffer_type buffer_type = 0;
+
+	switch (type) {
+	case INPUT_PLANE:
+		buffer_type = MSM_VIDC_BUF_INPUT;
+		break;
+	case OUTPUT_PLANE:
+		buffer_type = MSM_VIDC_BUF_OUTPUT;
+		break;
+	case INPUT_META_PLANE:
+		buffer_type = MSM_VIDC_BUF_INPUT_META;
+		break;
+	case OUTPUT_META_PLANE:
+		buffer_type = MSM_VIDC_BUF_OUTPUT_META;
+		break;
+	default:
+		d_vpr_e("%s: vidc buffer type not found for %#x\n",
+			__func__, type);
+		break;
+	}
+	return buffer_type;
+}
+
+u32 v4l2_type_from_driver(enum msm_vidc_buffer_type buffer_type)
+{
+	u32 type = 0;
+
+	switch (buffer_type) {
+	case MSM_VIDC_BUF_INPUT:
+		type = INPUT_PLANE;
+		break;
+	case MSM_VIDC_BUF_OUTPUT:
+		type = OUTPUT_PLANE;
+		break;
+	case MSM_VIDC_BUF_INPUT_META:
+		type = INPUT_META_PLANE;
+		break;
+	case MSM_VIDC_BUF_OUTPUT_META:
+		type = OUTPUT_META_PLANE;
+		break;
+	default:
+		d_vpr_e("%s: v4l2 type not found for %#x\n",
+			__func__, buffer_type);
+		break;
+	}
+	return buffer_type;
+}
+
+enum msm_vidc_codec_type v4l2_codec_to_driver(u32 v4l2_codec)
 {
 	enum msm_vidc_codec_type codec = 0;
 
@@ -51,7 +137,7 @@ enum msm_vidc_codec_type get_vidc_codec_from_v4l2(u32 v4l2_codec)
 	return codec;
 }
 
-u32 get_v4l2_codec_from_vidc(enum msm_vidc_codec_type codec)
+u32 v4l2_codec_from_driver(enum msm_vidc_codec_type codec)
 {
 	u32 v4l2_codec = 0;
 
@@ -75,7 +161,7 @@ u32 get_v4l2_codec_from_vidc(enum msm_vidc_codec_type codec)
 	return v4l2_codec;
 }
 
-enum msm_vidc_colorformat_type get_vidc_colorformat_from_v4l2(u32 v4l2_colorformat)
+enum msm_vidc_colorformat_type v4l2_colorformat_to_driver(u32 v4l2_colorformat)
 {
 	enum msm_vidc_colorformat_type colorformat = 0;
 
@@ -108,7 +194,7 @@ enum msm_vidc_colorformat_type get_vidc_colorformat_from_v4l2(u32 v4l2_colorform
 	return colorformat;
 }
 
-u32 get_v4l2_colorformat_from_vidc(enum msm_vidc_colorformat_type colorformat)
+u32 v4l2_colorformat_from_driver(enum msm_vidc_colorformat_type colorformat)
 {
 	u32 v4l2_colorformat = 0;
 
@@ -141,7 +227,7 @@ u32 get_v4l2_colorformat_from_vidc(enum msm_vidc_colorformat_type colorformat)
 	return v4l2_colorformat;
 }
 
-u32 get_media_colorformat_from_v4l2(u32 v4l2_fmt)
+u32 v4l2_colorformat_to_media(u32 v4l2_fmt)
 {
 	switch (v4l2_fmt) {
 	case V4L2_PIX_FMT_NV12:
@@ -166,7 +252,7 @@ u32 get_media_colorformat_from_v4l2(u32 v4l2_fmt)
 	}
 }
 
-int msm_vidc_get_port_from_v4l2_type(struct msm_vidc_inst *inst, u32 type,
+int v4l2_type_to_driver_port(struct msm_vidc_inst *inst, u32 type,
 	const char *func)
 {
 	int port;
@@ -237,8 +323,9 @@ u32 msm_vidc_get_buffer_region(struct msm_vidc_inst *inst,
 	return region;
 }
 
-struct msm_vidc_buffer_info *msm_vidc_get_buffer_info(struct msm_vidc_inst *inst,
-	enum msm_vidc_buffer_type buffer_type, const char *func)
+struct msm_vidc_buffers *msm_vidc_get_buffers(
+	struct msm_vidc_inst *inst, enum msm_vidc_buffer_type buffer_type,
+	const char *func)
 {
 	switch (buffer_type) {
 	case MSM_VIDC_BUF_INPUT:
@@ -261,42 +348,44 @@ struct msm_vidc_buffer_info *msm_vidc_get_buffer_info(struct msm_vidc_inst *inst
 		return &inst->buffers.persist_1;
 	default:
 		s_vpr_e(inst->sid, "%s: invalid buffer type %d\n",
-			__func__, buffer_type);
+			func, buffer_type);
 		return NULL;
 	}
 }
 
-struct msm_vidc_map_info *msm_vidc_get_map_info(struct msm_vidc_inst *inst,
-	enum msm_vidc_buffer_type buffer_type, const char *func)
+struct msm_vidc_mappings *msm_vidc_get_mappings(
+	struct msm_vidc_inst *inst, enum msm_vidc_buffer_type buffer_type,
+	const char *func)
 {
 	switch (buffer_type) {
 	case MSM_VIDC_BUF_INPUT:
-		return &inst->maps.input;
+		return &inst->mappings.input;
 	case MSM_VIDC_BUF_INPUT_META:
-		return &inst->maps.input_meta;
+		return &inst->mappings.input_meta;
 	case MSM_VIDC_BUF_OUTPUT:
-		return &inst->maps.output;
+		return &inst->mappings.output;
 	case MSM_VIDC_BUF_OUTPUT_META:
-		return &inst->maps.output_meta;
+		return &inst->mappings.output_meta;
 	case MSM_VIDC_BUF_SCRATCH:
-		return &inst->maps.scratch;
+		return &inst->mappings.scratch;
 	case MSM_VIDC_BUF_SCRATCH_1:
-		return &inst->maps.scratch_1;
+		return &inst->mappings.scratch_1;
 	case MSM_VIDC_BUF_SCRATCH_2:
-		return &inst->maps.scratch_2;
+		return &inst->mappings.scratch_2;
 	case MSM_VIDC_BUF_PERSIST:
-		return &inst->maps.persist;
+		return &inst->mappings.persist;
 	case MSM_VIDC_BUF_PERSIST_1:
-		return &inst->maps.persist_1;
+		return &inst->mappings.persist_1;
 	default:
 		s_vpr_e(inst->sid, "%s: invalid buffer type %d\n",
-			__func__, buffer_type);
+			func, buffer_type);
 		return NULL;
 	}
 }
 
-struct msm_vidc_alloc_info *msm_vidc_get_alloc_info(struct msm_vidc_inst *inst,
-	enum msm_vidc_buffer_type buffer_type, const char *func)
+struct msm_vidc_allocations *msm_vidc_get_allocations(
+	struct msm_vidc_inst *inst, enum msm_vidc_buffer_type buffer_type,
+	const char *func)
 {
 	switch (buffer_type) {
 	case MSM_VIDC_BUF_SCRATCH:
@@ -311,7 +400,7 @@ struct msm_vidc_alloc_info *msm_vidc_get_alloc_info(struct msm_vidc_inst *inst,
 		return &inst->allocations.persist_1;
 	default:
 		s_vpr_e(inst->sid, "%s: invalid buffer type %d\n",
-			__func__, buffer_type);
+			func, buffer_type);
 		return NULL;
 	}
 }
@@ -368,13 +457,314 @@ int msm_vidc_get_control(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
 	return rc;
 }
 
+static int vb2_buffer_to_driver(struct vb2_buffer *vb2, struct msm_vidc_buffer *buf)
+{
+	int rc = 0;
+
+	if (!vb2 || !buf) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	buf->valid = true;
+	buf->type = v4l2_type_to_driver(vb2->type);
+	if (!buf->type)
+		return -EINVAL;
+	buf->index = vb2->index;
+	buf->fd = vb2->planes[0].m.fd;
+	buf->data_offset = vb2->planes[0].data_offset;
+	buf->data_size = vb2->planes[0].bytesused;
+	buf->buffer_size = vb2->planes[0].length;
+	buf->timestamp = vb2->timestamp;
+
+	return rc;
+}
+
+int msm_vidc_unmap_driver_buf(struct msm_vidc_inst *inst,
+	struct msm_vidc_buffer *buf)
+{
+	int rc = 0;
+	struct msm_vidc_mappings *mappings;
+	struct msm_vidc_map *map = NULL;
+	bool found = false;
+
+	if (!inst || !buf) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	mappings = msm_vidc_get_mappings(inst, buf->type, __func__);
+	if (!mappings)
+		return -EINVAL;
+
+	/* sanity check to see if it was not removed */
+	list_for_each_entry(map, &mappings->list, list) {
+		if (map->dmabuf == buf->dmabuf) {
+			found = true;
+			break;
+		}
+	}
+	if (!found) {
+		print_vidc_buffer(VIDC_ERR, "no buf in mappings", inst, buf);
+		return -EINVAL;
+	}
+
+	rc = msm_vidc_memory_unmap(inst->core, map);
+	if (rc) {
+		print_vidc_buffer(VIDC_ERR, "unmap failed", inst, buf);
+		return -EINVAL;
+	}
+
+	/* finally delete if refcount is zero */
+	if (!map->refcount) {
+		list_del(&map->list);
+		kfree(map);
+	}
+
+	return 0;
+}
+
+int msm_vidc_put_driver_buf(struct msm_vidc_inst *inst,
+	struct msm_vidc_buffer *buf)
+{
+	int rc = 0;
+
+	if (!inst || !buf) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	/* do not unmap / delete read only buffer */
+	if (buf->attr & MSM_VIDC_ATTR_READ_ONLY)
+		return 0;
+
+	rc = msm_vidc_unmap_driver_buf(inst, buf);
+	if (rc)
+		return rc;
+
+	/* delete the buffer from buffers->list */
+	list_del(&buf->list);
+	kfree(buf);
+
+	return 0;
+}
+
+int msm_vidc_map_driver_buf(struct msm_vidc_inst *inst,
+	struct msm_vidc_buffer *buf)
+{
+	int rc = 0;
+	struct msm_vidc_mappings *mappings;
+	struct msm_vidc_map *map = NULL;
+	bool found = false;
+
+	if (!inst || !buf) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	mappings = msm_vidc_get_mappings(inst, buf->type, __func__);
+	if (!mappings)
+		return -EINVAL;
+
+	/* check if it is an existing one */
+	list_for_each_entry(map, &mappings->list, list) {
+		if (map->dmabuf == buf->dmabuf) {
+			found = true;
+			break;
+		}
+	}
+	if (found) {
+		/* skip mapping for RO buffer */
+		if (!(buf->attr & MSM_VIDC_ATTR_READ_ONLY)) {
+			rc = msm_vidc_memory_map(inst->core, map);
+			if (rc)
+				return -ENOMEM;
+			buf->device_addr = map->device_addr;
+		}
+		return 0;
+	}
+	map = kzalloc(sizeof(struct msm_vidc_map), GFP_KERNEL);
+	if (!map) {
+		s_vpr_e(inst->sid, "%s: alloc failed\n", __func__);
+		return -ENOMEM;
+	}
+	INIT_LIST_HEAD(&map->list);
+	map->type = buf->type;
+	map->dmabuf = buf->dmabuf;
+	map->region = msm_vidc_get_buffer_region(inst, buf->type, __func__);
+	rc = msm_vidc_memory_map(inst->core, map);
+	if (rc) {
+		kfree(map);
+		return -ENOMEM;
+	}
+	buf->device_addr = map->device_addr;
+	list_add_tail(&map->list, &mappings->list);
+
+	return 0;
+}
+
+struct msm_vidc_buffer *msm_vidc_get_driver_buf(struct msm_vidc_inst *inst,
+	struct vb2_buffer *vb2)
+{
+	int rc = 0;
+	struct msm_vidc_buffer *buf = NULL;
+	struct msm_vidc_buffers *buffers;
+	struct dma_buf *dmabuf;
+	enum msm_vidc_buffer_type buf_type;
+	bool found = false;
+
+	if (!inst || !vb2) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return NULL;
+	}
+
+	buf_type = v4l2_type_to_driver(vb2->type);
+	if (!buf_type)
+		return NULL;
+
+	buffers = msm_vidc_get_buffers(inst, buf_type, __func__);
+	if (!buffers)
+		return NULL;
+
+	dmabuf = msm_vidc_memory_get_dmabuf(vb2->planes[0].m.fd);
+	if (!dmabuf)
+		return NULL;
+	msm_vidc_memory_put_dmabuf(dmabuf);
+
+	/* check if it is an existing buffer */
+	list_for_each_entry(buf, &buffers->list, list) {
+		if (buf->dmabuf == dmabuf &&
+		    buf->data_offset == vb2->planes[0].data_offset) {
+			found = true;
+			break;
+		}
+	}
+	if (found) {
+		/* only YUV buffers are allowed to repeat */
+		if ((is_decode_session(inst) && vb2->type != OUTPUT_PLANE) ||
+		    (is_encode_session(inst) && vb2->type != INPUT_PLANE)) {
+			print_vidc_buffer(VIDC_ERR,
+				"existing buffer", inst, buf);
+			goto error;
+		}
+		/* for decoder, YUV with RO flag are allowed to repeat */
+		if (is_decode_session(inst) &&
+		    !(buf->attr & MSM_VIDC_ATTR_READ_ONLY)) {
+			print_vidc_buffer(VIDC_ERR,
+				"existing buffer without RO flag", inst, buf);
+			goto error;
+		}
+		/* for encoder, treat the repeated buffer as new buffer */
+		if (is_encode_session(inst) && vb2->type == INPUT_PLANE)
+			found = false;
+	} else {
+		buf = kzalloc(sizeof(struct msm_vidc_buffer), GFP_KERNEL);
+		if (!buf) {
+			s_vpr_e(inst->sid, "%s: alloc failed\n", __func__);
+			goto error;
+		}
+		buf->dmabuf = dmabuf;
+	}
+	rc = vb2_buffer_to_driver(vb2, buf);
+	if (rc)
+		goto error;
+
+	if (!found)
+		list_add_tail(&buf->list, &buffers->list);
+
+	rc = msm_vidc_map_driver_buf(inst, buf);
+	if (rc)
+		goto error;
+
+	return buf;
+
+error:
+	if (!found)
+		kfree(buf);
+	return NULL;
+}
+
+struct msm_vidc_buffer *get_meta_buffer(struct msm_vidc_inst *inst,
+	struct msm_vidc_buffer *buf)
+{
+	struct msm_vidc_buffer *mbuf;
+	struct msm_vidc_buffers *meta;
+	bool found = false;
+
+	if (!inst || !buf) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return NULL;
+	}
+
+	if (buf->type == MSM_VIDC_BUF_INPUT) {
+		meta = &inst->buffers.input_meta;
+	} else if (buf->type == MSM_VIDC_BUF_OUTPUT) {
+		meta = &inst->buffers.output_meta;
+	} else {
+		s_vpr_e(inst->sid, "%s: invalid buffer type %d\n",
+			__func__, buf->type);
+		return NULL;
+	}
+	list_for_each_entry(mbuf, &meta->list, list) {
+		if (!mbuf->valid)
+			continue;
+		if (mbuf->type == buf->type &&
+		    mbuf->index == buf->index) {
+			found = true;
+			break;
+		}
+	}
+	if (!found)
+		return NULL;
+
+	return mbuf;
+}
+
+int msm_vidc_queue_buffer(struct msm_vidc_inst *inst, struct vb2_buffer *vb2)
+{
+	int rc = 0;
+	struct msm_vidc_buffer *buf;
+	int port;
+
+	if (!inst || !vb2) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	buf = msm_vidc_get_driver_buf(inst, vb2);
+	if (!buf)
+		return -EINVAL;
+
+	/* meta buffer will be queued along with actual buffer */
+	if (buf->type == MSM_VIDC_BUF_INPUT_META ||
+	    buf->type == MSM_VIDC_BUF_OUTPUT_META)
+		return 0;
+
+	/* skip queuing if streamon not completed */
+	port = v4l2_type_to_driver_port(inst, vb2->type, __func__);
+	if (port < 0)
+		return -EINVAL;
+	if (!inst->vb2q[port].streaming) {
+		buf->attr |= MSM_VIDC_ATTR_DEFERRED;
+		print_vidc_buffer(VIDC_HIGH, "qbuf deferred", inst, buf);
+		return 0;
+	}
+
+	print_vidc_buffer(VIDC_HIGH, "qbuf", inst, buf);
+	rc = venus_hfi_queue_buffer(inst, buf, get_meta_buffer(inst, buf));
+	if (rc)
+		return rc;
+
+	return rc;
+}
+
 int msm_vidc_create_internal_buffers(struct msm_vidc_inst *inst,
 		enum msm_vidc_buffer_type buffer_type)
 {
 	int rc = 0;
-	struct msm_vidc_buffer_info *buffer_info;
-	struct msm_vidc_alloc_info *alloc_info;
-	struct msm_vidc_map_info *map_info;
+	struct msm_vidc_buffers *buffers;
+	struct msm_vidc_allocations *allocations;
+	struct msm_vidc_mappings *mappings;
 	int i;
 
 	d_vpr_h("%s()\n", __func__);
@@ -388,22 +778,22 @@ int msm_vidc_create_internal_buffers(struct msm_vidc_inst *inst,
 		return 0;
 	}
 
-	buffer_info = msm_vidc_get_buffer_info(inst, buffer_type, __func__);
-	if (!buffer_info)
+	buffers = msm_vidc_get_buffers(inst, buffer_type, __func__);
+	if (!buffers)
 		return -EINVAL;
-	alloc_info = msm_vidc_get_alloc_info(inst, buffer_type, __func__);
-	if (!alloc_info)
+	allocations = msm_vidc_get_allocations(inst, buffer_type, __func__);
+	if (!allocations)
 		return -EINVAL;
-	map_info = msm_vidc_get_map_info(inst, buffer_type, __func__);
-	if (!alloc_info)
+	mappings = msm_vidc_get_mappings(inst, buffer_type, __func__);
+	if (!mappings)
 		return -EINVAL;
 
-	for (i = 0; i < buffer_info->min_count; i++) {
+	for (i = 0; i < buffers->min_count; i++) {
 		struct msm_vidc_buffer *buffer;
 		struct msm_vidc_alloc *alloc;
 		struct msm_vidc_map *map;
 
-		if (!buffer_info->size) {
+		if (!buffers->size) {
 			s_vpr_e(inst->sid, "%s: invalid buffer %#x\n",
 				__func__, buffer_type);
 			return -EINVAL;
@@ -417,8 +807,8 @@ int msm_vidc_create_internal_buffers(struct msm_vidc_inst *inst,
 		buffer->valid = true;
 		buffer->type = buffer_type;
 		buffer->index = i;
-		buffer->buffer_size = buffer_info->size;
-		list_add_tail(&buffer->list, &buffer_info->list);
+		buffer->buffer_size = buffers->size;
+		list_add_tail(&buffer->list, &buffers->list);
 
 		alloc = kzalloc(sizeof(struct msm_vidc_alloc), GFP_KERNEL);
 		if (!alloc) {
@@ -426,14 +816,14 @@ int msm_vidc_create_internal_buffers(struct msm_vidc_inst *inst,
 			return -ENOMEM;
 		}
 		INIT_LIST_HEAD(&alloc->list);
-		alloc->buffer_type = buffer_type;
-		alloc->region      = msm_vidc_get_buffer_region(inst,
+		alloc->type = buffer_type;
+		alloc->region = msm_vidc_get_buffer_region(inst,
 					buffer_type, __func__);
-		alloc->size        = buffer->buffer_size;
+		alloc->size = buffer->buffer_size;
 		rc = msm_vidc_memory_alloc(inst->core, alloc);
 		if (rc)
 			return -ENOMEM;
-		list_add_tail(&alloc->list, &alloc_info->list);
+		list_add_tail(&alloc->list, &allocations->list);
 
 		map = kzalloc(sizeof(struct msm_vidc_map), GFP_KERNEL);
 		if (!map) {
@@ -441,16 +831,16 @@ int msm_vidc_create_internal_buffers(struct msm_vidc_inst *inst,
 			return -ENOMEM;
 		}
 		INIT_LIST_HEAD(&map->list);
-		map->buffer_type  = alloc->buffer_type;
-		map->region       = alloc->region;
-		map->dmabuf       = alloc->dmabuf;
+		map->type = alloc->type;
+		map->region = alloc->region;
+		map->dmabuf = alloc->dmabuf;
 		rc = msm_vidc_memory_map(inst->core, map);
 		if (rc)
 			return -ENOMEM;
-		list_add_tail(&map->list, &map_info->list);
+		list_add_tail(&map->list, &mappings->list);
 
 		s_vpr_e(inst->sid, "%s: created buffer_type %#x, size %d\n",
-			__func__, buffer_type, buffer_info->size);
+			__func__, buffer_type, buffers->size);
 	}
 
 	return 0;
@@ -460,7 +850,7 @@ int msm_vidc_queue_internal_buffers(struct msm_vidc_inst *inst,
 		enum msm_vidc_buffer_type buffer_type)
 {
 	int rc = 0;
-	struct msm_vidc_buffer_info *buffer_info;
+	struct msm_vidc_buffers *buffers;
 	struct msm_vidc_buffer *buffer, *dummy;
 
 	d_vpr_h("%s()\n", __func__);
@@ -474,11 +864,11 @@ int msm_vidc_queue_internal_buffers(struct msm_vidc_inst *inst,
 		return 0;
 	}
 
-	buffer_info = msm_vidc_get_buffer_info(inst, buffer_type, __func__);
-	if (!buffer_info)
+	buffers = msm_vidc_get_buffers(inst, buffer_type, __func__);
+	if (!buffers)
 		return -EINVAL;
 
-	list_for_each_entry_safe(buffer, dummy, &buffer_info->list, list) {
+	list_for_each_entry_safe(buffer, dummy, &buffers->list, list) {
 		/* do not queue pending release buffers */
 		if (buffer->flags & MSM_VIDC_ATTR_PENDING_RELEASE)
 			continue;
@@ -492,7 +882,7 @@ int msm_vidc_queue_internal_buffers(struct msm_vidc_inst *inst,
 		buffer->attr |= MSM_VIDC_ATTR_QUEUED;
 
 		s_vpr_h(inst->sid, "%s: queued buffer_type %#x, size %d\n",
-			__func__, buffer_type, buffer_info->size);
+			__func__, buffer_type, buffers->size);
 	}
 
 	return 0;
@@ -502,7 +892,7 @@ int msm_vidc_release_internal_buffers(struct msm_vidc_inst *inst,
 		enum msm_vidc_buffer_type buffer_type)
 {
 	int rc = 0;
-	struct msm_vidc_buffer_info *buffer_info;
+	struct msm_vidc_buffers *buffers;
 	struct msm_vidc_buffer *buffer, *dummy;
 
 	d_vpr_h("%s()\n", __func__);
@@ -516,11 +906,11 @@ int msm_vidc_release_internal_buffers(struct msm_vidc_inst *inst,
 		return 0;
 	}
 
-	buffer_info = msm_vidc_get_buffer_info(inst, buffer_type, __func__);
-	if (!buffer_info)
+	buffers = msm_vidc_get_buffers(inst, buffer_type, __func__);
+	if (!buffers)
 		return -EINVAL;
 
-	list_for_each_entry_safe(buffer, dummy, &buffer_info->list, list) {
+	list_for_each_entry_safe(buffer, dummy, &buffers->list, list) {
 		/* do not release already pending release buffers */
 		if (buffer->attr & MSM_VIDC_ATTR_PENDING_RELEASE)
 			continue;
@@ -534,7 +924,7 @@ int msm_vidc_release_internal_buffers(struct msm_vidc_inst *inst,
 		buffer->attr |= MSM_VIDC_ATTR_PENDING_RELEASE;
 
 		s_vpr_e(inst->sid, "%s: released buffer_type %#x, size %d\n",
-			__func__, buffer_type, buffer_info->size);
+			__func__, buffer_type, buffers->size);
 	}
 
 	return 0;
@@ -918,13 +1308,16 @@ int msm_vidc_core_init(struct msm_vidc_core *core)
 
 	mutex_unlock(&core->lock);
 	/*TODO: acquire lock or not */
+	d_vpr_h("%s(): waiting for sys init done, %d ms\n", __func__,
+		core->platform->data.core_data[HW_RESPONSE_TIMEOUT].value);
 	rc = wait_for_completion_timeout(&core->init_done, msecs_to_jiffies(
-			core->platform->data.core_data[DEBUG_TIMEOUT].value));
+			core->platform->data.core_data[HW_RESPONSE_TIMEOUT].value));
 	if (!rc) {
 		d_vpr_e("%s: system init timed out\n", __func__);
 		//msm_comm_kill_session(inst);
-		rc = -EIO;
+		//rc = -EIO;
 	} else {
+		d_vpr_h("%s: system init wait completed\n", __func__);
 		rc = 0;
 	}
 	mutex_lock(&core->lock);

+ 2 - 4
driver/vidc/src/msm_vidc_memory.c

@@ -248,8 +248,7 @@ int msm_vidc_memory_alloc(struct msm_vidc_core *core, struct msm_vidc_alloc *mem
 
 	d_vpr_h(
 		"%s: dmabuf = %pK, size = %d, kvaddr = %pK, buffer_type = %#x\n",
-		__func__, mem->dmabuf, mem->size,
-		mem->kvaddr, mem->buffer_type);
+		__func__, mem->dmabuf, mem->size, mem->kvaddr, mem->type);
 	return 0;
 
 error:
@@ -268,8 +267,7 @@ int msm_vidc_memory_free(struct msm_vidc_core *core, struct msm_vidc_alloc *mem)
 
 	d_vpr_h(
 		"%s: dmabuf = %pK, size = %d, kvaddr = %pK, buffer_type = %#x\n",
-		__func__, mem->dmabuf, mem->size,
-		mem->kvaddr, mem->buffer_type);
+		__func__, mem->dmabuf, mem->size, mem->kvaddr, mem->type);
 
 	if (mem->kvaddr) {
 		dma_buf_vunmap(mem->dmabuf, mem->kvaddr);

+ 4 - 0
driver/vidc/src/msm_vidc_platform.c

@@ -29,8 +29,12 @@ static struct v4l2_ioctl_ops msm_v4l2_ioctl_ops = {
 	.vidioc_enum_framesizes         = msm_v4l2_enum_framesizes,
 	.vidioc_s_fmt_vid_cap           = msm_v4l2_s_fmt,
 	.vidioc_s_fmt_vid_out           = msm_v4l2_s_fmt,
+	.vidioc_s_fmt_meta_out          = msm_v4l2_s_fmt,
+	.vidioc_s_fmt_meta_cap          = msm_v4l2_s_fmt,
 	.vidioc_g_fmt_vid_cap           = msm_v4l2_g_fmt,
 	.vidioc_g_fmt_vid_out           = msm_v4l2_g_fmt,
+	.vidioc_g_fmt_meta_out          = msm_v4l2_g_fmt,
+	.vidioc_g_fmt_meta_cap          = msm_v4l2_g_fmt,
 	.vidioc_reqbufs                 = msm_v4l2_reqbufs,
 	.vidioc_qbuf                    = msm_v4l2_qbuf,
 	.vidioc_dqbuf                   = msm_v4l2_dqbuf,

+ 27 - 3
driver/vidc/src/msm_vidc_vb2.c

@@ -46,7 +46,7 @@ int msm_vidc_queue_setup(struct vb2_queue *q,
 		return -EINVAL;
 	}
 
-	port = msm_vidc_get_port_from_v4l2_type(inst, q->type, __func__);
+	port = v4l2_type_to_driver_port(inst, q->type, __func__);
 	if (port < 0)
 		return -EINVAL;
 
@@ -69,8 +69,11 @@ int msm_vidc_queue_setup(struct vb2_queue *q,
 		inst->buffers.input.extra_count)
 		*num_buffers = inst->buffers.input.min_count +
 			inst->buffers.input.extra_count;
-	sizes[0] = inst->fmts[port].fmt.pix.sizeimage;
 	inst->buffers.input.actual_count = *num_buffers;
+	if (port == INPUT_PORT || port == OUTPUT_PORT)
+		sizes[0] = inst->fmts[port].fmt.pix.sizeimage;
+	else if (port == INPUT_META_PORT || port == OUTPUT_META_PORT)
+		sizes[0] = inst->fmts[port].fmt.meta.buffersize;
 
 	s_vpr_h(inst->sid,
 		"queue_setup: type %d num_buffers %d sizes[0] %d\n",
@@ -151,8 +154,29 @@ void msm_vidc_stop_streaming(struct vb2_queue *q)
 
 void msm_vidc_buf_queue(struct vb2_buffer *vb2)
 {
+	int rc = 0;
+	struct msm_vidc_inst *inst;
+
+	inst = vb2_get_drv_priv(vb2->vb2_queue);
+	if (!inst) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return;
+	}
+
+	if (is_decode_session(inst))
+		rc = msm_vdec_qbuf(inst, vb2);
+	else if (is_encode_session(inst))
+		rc = msm_vdec_qbuf(inst, vb2);
+	else
+		rc = -EINVAL;
+
+	if (rc) {
+		print_vb2_buffer("failed vb2-qbuf", inst, vb2);
+		msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
+		vb2_buffer_done(vb2, VB2_BUF_STATE_ERROR);
+	}
 }
 
 void msm_vidc_buf_cleanup(struct vb2_buffer *vb)
 {
-}
+}

+ 5 - 5
driver/vidc/src/venus_hfi.c

@@ -144,7 +144,7 @@ static void __dump_packet(u8 *packet)
 static void __fatal_error(struct msm_vidc_core *core, bool fatal)
 {
 	return;
-	fatal &= core->platform->data.core_data[DEBUG_TIMEOUT].value;
+	fatal &= core->platform->data.core_data[HW_RESPONSE_TIMEOUT].value;
 	MSM_VIDC_ERROR(fatal);
 }
 
@@ -2082,7 +2082,7 @@ static int __interface_queues_init(struct msm_vidc_core *core)
 	q_size = SHARED_QSIZE - ALIGNED_SFR_SIZE - ALIGNED_QDSS_SIZE;
 
 	memset(&alloc, 0, sizeof(alloc));
-	alloc.buffer_type = MSM_VIDC_BUF_QUEUE;
+	alloc.type       = MSM_VIDC_BUF_QUEUE;
 	alloc.region     = MSM_VIDC_NON_SECURE;
 	alloc.size       = q_size;
 	alloc.cached     = false;
@@ -2095,7 +2095,7 @@ static int __interface_queues_init(struct msm_vidc_core *core)
 	}
 
 	memset(&map, 0, sizeof(map));
-	map.buffer_type  = alloc.buffer_type;
+	map.type         = alloc.type;
 	map.region       = alloc.region;
 	map.dmabuf       = alloc.dmabuf;
 	rc = msm_vidc_memory_map(core, &map);
@@ -2155,7 +2155,7 @@ static int __interface_queues_init(struct msm_vidc_core *core)
 
 	/* sfr buffer */
 	memset(&alloc, 0, sizeof(alloc));
-	alloc.buffer_type = MSM_VIDC_BUF_QUEUE;
+	alloc.type       = MSM_VIDC_BUF_QUEUE;
 	alloc.region     = MSM_VIDC_NON_SECURE;
 	alloc.size       = ALIGNED_SFR_SIZE;
 	alloc.cached     = false;
@@ -2167,7 +2167,7 @@ static int __interface_queues_init(struct msm_vidc_core *core)
 		goto fail_alloc_queue;
 	}
 	memset(&map, 0, sizeof(map));
-	map.buffer_type  = alloc.buffer_type;
+	map.type         = alloc.type;
 	map.region       = alloc.region;
 	map.dmabuf       = alloc.dmabuf;
 	rc = msm_vidc_memory_map(core, &map);

+ 0 - 13
include/uapi/vidc/media/msm_vidc_utils.h

@@ -27,19 +27,6 @@
 /* vendor controls start */
 #define V4L2_CID_MPEG_MSM_VIDC_BASE             (V4L2_CTRL_CLASS_MPEG | 0x2000)
 
-#define V4L2_CID_MPEG_VIDC_VIDEO_DECODE_ORDER                                 \
-		(V4L2_CID_MPEG_MSM_VIDC_BASE + 0x1)
-#define V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE                            \
-		(V4L2_CID_MPEG_MSM_VIDC_BASE + 0x2)
-#define V4L2_CID_MPEG_VIDC_VIDEO_SECURE                                       \
-		(V4L2_CID_MPEG_MSM_VIDC_BASE + 0x3)
-#define V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_MODE                              \
-		(V4L2_CID_MPEG_MSM_VIDC_BASE + 0x4)
-#define V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_HINT                              \
-		(V4L2_CID_MPEG_MSM_VIDC_BASE + 0x5)
-#define V4L2_CID_MPEG_VIDC_VIDEO_BUFFER_SIZE_LIMIT                            \
-		(V4L2_CID_MPEG_MSM_VIDC_BASE + 0x6)
-
 #define V4L2_CID_MPEG_VIDC_VIDEO_DECODE_ORDER                                 \
 		(V4L2_CID_MPEG_MSM_VIDC_BASE + 0x1)
 #define V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE                            \