diff --git a/drivers/media/platform/vimc/vimc-capture.c b/drivers/media/platform/vimc/vimc-capture.c
index a5d79fb25dff..6f7bbfc4446d 100644
--- a/drivers/media/platform/vimc/vimc-capture.c
+++ b/drivers/media/platform/vimc/vimc-capture.c
@@ -239,6 +239,7 @@ static int vimc_cap_start_streaming(struct vb2_queue *vq, unsigned int count)
 		vimc_cap_return_all_buffers(vcap, VB2_BUF_STATE_QUEUED);
 		return ret;
 	}
+	kref_get(&vcap->ved.ref);
 
 	ret = vimc_streamer_s_stream(&vcap->stream, &vcap->ved, 1);
 	if (ret) {
@@ -250,6 +251,24 @@ static int vimc_cap_start_streaming(struct vb2_queue *vq, unsigned int count)
 	return 0;
 }
 
+static void vimc_cap_free(struct kref *kref)
+{
+	struct vimc_cap_device *vcap = container_of(kref, struct vimc_cap_device, ved.ref);
+
+	pr_debug("freeing capture: '%s'\n", vcap->vdev.name);
+	kfree(vcap);
+}
+
+static void vimc_cap_release(struct video_device *vdev)
+{
+	struct vimc_cap_device *vcap =
+		container_of(vdev, struct vimc_cap_device, vdev);
+
+	media_entity_cleanup(vcap->ved.ent);
+	kref_put(&vcap->ved.ref, vimc_cap_free);
+}
+
+
 /*
  * Stop the stream engine. Any remaining buffers in the stream queue are
  * dequeued and passed on to the vb2 framework marked as STATE_ERROR.
@@ -265,6 +284,7 @@ static void vimc_cap_stop_streaming(struct vb2_queue *vq)
 
 	/* Release all active buffers */
 	vimc_cap_return_all_buffers(vcap, VB2_BUF_STATE_ERROR);
+	kref_put(&vcap->ved.ref, vimc_cap_free);
 }
 
 static void vimc_cap_buf_queue(struct vb2_buffer *vb2_buf)
@@ -325,15 +345,6 @@ static const struct media_entity_operations vimc_cap_mops = {
 	.link_validate		= vimc_link_validate,
 };
 
-static void vimc_cap_release(struct video_device *vdev)
-{
-	struct vimc_cap_device *vcap =
-		container_of(vdev, struct vimc_cap_device, vdev);
-
-	media_entity_cleanup(vcap->ved.ent);
-	kfree(vcap);
-}
-
 void vimc_cap_rm(struct vimc_device *vimc, struct vimc_ent_device *ved)
 {
 	struct vimc_cap_device *vcap;
@@ -467,6 +478,7 @@ struct vimc_ent_device *vimc_cap_add(struct vimc_device *vimc,
 		goto err_release_queue;
 	}
 
+	kref_init(&vcap->ved.ref);
 	return &vcap->ved;
 
 err_release_queue:
diff --git a/drivers/media/platform/vimc/vimc-common.c b/drivers/media/platform/vimc/vimc-common.c
index 2a0c40e9ae88..9d93c3c40d3c 100644
--- a/drivers/media/platform/vimc/vimc-common.c
+++ b/drivers/media/platform/vimc/vimc-common.c
@@ -351,6 +351,7 @@ int vimc_ent_sd_register(struct vimc_ent_device *ved,
 			name, ret);
 		goto err_clean_m_ent;
 	}
+	kref_init(&ved->ref);
 
 	return 0;
 
diff --git a/drivers/media/platform/vimc/vimc-common.h b/drivers/media/platform/vimc/vimc-common.h
index c75401a36312..a8699ac0a783 100644
--- a/drivers/media/platform/vimc/vimc-common.h
+++ b/drivers/media/platform/vimc/vimc-common.h
@@ -85,6 +85,7 @@ struct vimc_pix_map {
  * @vdev_get_format:	callback that returns the current format a pad, used
  *			only when is_media_entity_v4l2_video_device(ent) returns
  *			true
+ * @kref		ref count
  *
  * Each node of the topology must create a vimc_ent_device struct. Depending on
  * the node it will be of an instance of v4l2_subdev or video_device struct
@@ -101,6 +102,7 @@ struct vimc_ent_device {
 				const void *frame);
 	void (*vdev_get_format)(struct vimc_ent_device *ved,
 			      struct v4l2_pix_format *fmt);
+	struct kref ref;
 };
 
 /**
diff --git a/drivers/media/platform/vimc/vimc-debayer.c b/drivers/media/platform/vimc/vimc-debayer.c
index 5d1b67d684bb..8860ca3bf400 100644
--- a/drivers/media/platform/vimc/vimc-debayer.c
+++ b/drivers/media/platform/vimc/vimc-debayer.c
@@ -298,6 +298,30 @@ static void vimc_deb_set_rgb_mbus_fmt_rgb888_1x24(struct vimc_deb_device *vdeb,
 		vdeb->src_frame[index + i] = rgb[i];
 }
 
+static void vimc_deb_free(struct kref *kref)
+{
+	struct vimc_deb_device *vdeb = container_of(kref, struct vimc_deb_device, ved.ref);
+
+	pr_debug("freeing debayer '%s'", vdeb->sd.name);
+	kfree(vdeb);
+}
+
+static void vimc_deb_release(struct v4l2_subdev *sd)
+{
+	struct vimc_deb_device *vdeb =
+		container_of(sd, struct vimc_deb_device, sd);
+
+	dev_dbg(vdeb->ved.dev, "release: put debayer '%s'\n", vdeb->sd.name);
+	media_entity_cleanup(vdeb->ved.ent);
+	kref_put(&vdeb->ved.ref, vimc_deb_free);
+}
+
+
+static const struct v4l2_subdev_internal_ops vimc_deb_int_ops = {
+	.release = vimc_deb_release,
+};
+
+
 static int vimc_deb_s_stream(struct v4l2_subdev *sd, int enable)
 {
 	struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd);
@@ -329,6 +353,7 @@ static int vimc_deb_s_stream(struct v4l2_subdev *sd, int enable)
 		vdeb->src_frame = vmalloc(frame_size);
 		if (!vdeb->src_frame)
 			return -ENOMEM;
+		kref_get(&vdeb->ved.ref);
 
 	} else {
 		if (!vdeb->src_frame)
@@ -336,6 +361,7 @@ static int vimc_deb_s_stream(struct v4l2_subdev *sd, int enable)
 
 		vfree(vdeb->src_frame);
 		vdeb->src_frame = NULL;
+		kref_put(&vdeb->ved.ref, vimc_deb_free);
 	}
 
 	return 0;
@@ -494,20 +520,6 @@ static const struct v4l2_ctrl_ops vimc_deb_ctrl_ops = {
 	.s_ctrl = vimc_deb_s_ctrl,
 };
 
-static void vimc_deb_release(struct v4l2_subdev *sd)
-{
-	struct vimc_deb_device *vdeb =
-				container_of(sd, struct vimc_deb_device, sd);
-
-	v4l2_ctrl_handler_free(&vdeb->hdl);
-	media_entity_cleanup(vdeb->ved.ent);
-	kfree(vdeb);
-}
-
-static const struct v4l2_subdev_internal_ops vimc_deb_int_ops = {
-	.release = vimc_deb_release,
-};
-
 void vimc_deb_rm(struct vimc_device *vimc, struct vimc_ent_device *ved)
 {
 	struct vimc_deb_device *vdeb;
diff --git a/drivers/media/platform/vimc/vimc-scaler.c b/drivers/media/platform/vimc/vimc-scaler.c
index 2f88a7d9d67b..cb04408834b5 100644
--- a/drivers/media/platform/vimc/vimc-scaler.c
+++ b/drivers/media/platform/vimc/vimc-scaler.c
@@ -197,6 +197,29 @@ static const struct v4l2_subdev_pad_ops vimc_sca_pad_ops = {
 	.set_fmt		= vimc_sca_set_fmt,
 };
 
+static void vimc_sca_free(struct kref *kref)
+{
+	struct vimc_sca_device *vsca = container_of(kref, struct vimc_sca_device, ved.ref);
+
+	pr_debug("freeing scaler '%s'", vsca->sd.name);
+	kfree(vsca);
+}
+
+static void vimc_sca_release(struct v4l2_subdev *sd)
+{
+	struct vimc_sca_device *vsca =
+		container_of(sd, struct vimc_sca_device, sd);
+
+	dev_dbg(vsca->ved.dev, "release: put scaler '%s'\n", vsca->sd.name);
+	media_entity_cleanup(vsca->ved.ent);
+	kref_put(&vsca->ved.ref, vimc_sca_free);
+}
+
+static const struct v4l2_subdev_internal_ops vimc_sca_int_ops = {
+	.release = vimc_sca_release,
+};
+
+
 static int vimc_sca_s_stream(struct v4l2_subdev *sd, int enable)
 {
 	struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd);
@@ -227,12 +250,14 @@ static int vimc_sca_s_stream(struct v4l2_subdev *sd, int enable)
 		if (!vsca->src_frame)
 			return -ENOMEM;
 
+		kref_get(&vsca->ved.ref);
 	} else {
 		if (!vsca->src_frame)
 			return 0;
 
 		vfree(vsca->src_frame);
 		vsca->src_frame = NULL;
+		kref_put(&vsca->ved.ref, vimc_sca_free);
 	}
 
 	return 0;
@@ -331,19 +356,6 @@ static void *vimc_sca_process_frame(struct vimc_ent_device *ved,
 	return vsca->src_frame;
 };
 
-static void vimc_sca_release(struct v4l2_subdev *sd)
-{
-	struct vimc_sca_device *vsca =
-				container_of(sd, struct vimc_sca_device, sd);
-
-	media_entity_cleanup(vsca->ved.ent);
-	kfree(vsca);
-}
-
-static const struct v4l2_subdev_internal_ops vimc_sca_int_ops = {
-	.release = vimc_sca_release,
-};
-
 void vimc_sca_rm(struct vimc_device *vimc, struct vimc_ent_device *ved)
 {
 	struct vimc_sca_device *vsca;
diff --git a/drivers/media/platform/vimc/vimc-sensor.c b/drivers/media/platform/vimc/vimc-sensor.c
index 25ee89a067f7..f137ff23b892 100644
--- a/drivers/media/platform/vimc/vimc-sensor.c
+++ b/drivers/media/platform/vimc/vimc-sensor.c
@@ -193,6 +193,25 @@ static void *vimc_sen_process_frame(struct vimc_ent_device *ved,
 	return vsen->frame;
 }
 
+static void vimc_sen_free(struct kref *kref)
+{
+	struct vimc_sen_device *vsen = container_of(kref, struct vimc_sen_device, ved.ref);
+
+	pr_debug("freeing sensor '%s'", vsen->sd.name);
+	v4l2_ctrl_handler_free(&vsen->hdl);
+	tpg_free(&vsen->tpg);
+	kfree(vsen);
+}
+
+static void vimc_sen_release(struct v4l2_subdev *sd)
+{
+	struct vimc_sen_device *vsen =
+		container_of(sd, struct vimc_sen_device, sd);
+
+	dev_dbg(vsen->ved.dev, "release: put sensor '%s'\n", vsen->sd.name);
+	kref_put(&vsen->ved.ref, vimc_sen_free);
+}
+
 static int vimc_sen_s_stream(struct v4l2_subdev *sd, int enable)
 {
 	struct vimc_sen_device *vsen =
@@ -221,11 +240,13 @@ static int vimc_sen_s_stream(struct v4l2_subdev *sd, int enable)
 
 		/* configure the test pattern generator */
 		vimc_sen_tpg_s_format(vsen);
+		kref_get(&vsen->ved.ref);
 
 	} else {
 
 		vfree(vsen->frame);
 		vsen->frame = NULL;
+		kref_put(&vsen->ved.ref, vimc_sen_free);
 	}
 
 	return 0;
@@ -284,17 +305,6 @@ static const struct v4l2_ctrl_ops vimc_sen_ctrl_ops = {
 	.s_ctrl = vimc_sen_s_ctrl,
 };
 
-static void vimc_sen_release(struct v4l2_subdev *sd)
-{
-	struct vimc_sen_device *vsen =
-				container_of(sd, struct vimc_sen_device, sd);
-
-	v4l2_ctrl_handler_free(&vsen->hdl);
-	tpg_free(&vsen->tpg);
-	media_entity_cleanup(vsen->ved.ent);
-	kfree(vsen);
-}
-
 static const struct v4l2_subdev_internal_ops vimc_sen_int_ops = {
 	.release = vimc_sen_release,
 };
