From: Ezequiel Garcia <ezequiel-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>
To: linux-media-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Hans Verkuil
<hans.verkuil-FYB4Gu1CFyUAvxtiuMwx3w@public.gmane.org>
Cc: Nicolas Dufresne
<nicolas.dufresne-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>,
Heiko Stuebner <heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org>,
Jonas Karlman <jonas-uIzNG4q0ceqzQB+pC5nmwQ@public.gmane.org>,
Tomasz Figa <tfiga-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
Boris Brezillon
<boris.brezillon-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>,
Philipp Zabel <p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>,
kernel-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org,
Ezequiel Garcia
<ezequiel-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>
Subject: [PATCH v6 05/16] rockchip/vpu: Open-code media controller register
Date: Tue, 28 May 2019 14:02:21 -0300 [thread overview]
Message-ID: <20190528170232.2091-6-ezequiel@collabora.com> (raw)
In-Reply-To: <20190528170232.2091-1-ezequiel-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>
In preparation to support decoders, using a single memory-to-memory
device, we need to roll our own media controller entities registration.
To do that, we define a rockchip_vpu_func object that embeds the
video_device object plus all the elements that are needed to attach this
vdev to the media device.
Signed-off-by: Ezequiel Garcia <ezequiel-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>
Signed-off-by: Boris Brezillon <boris.brezillon-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>
--
Changes from v3:
* Rework the media controller registration logic (Boris)
* Fix media controller deregistration (Jonas)
Changes from v2:
* Use kvasprintf instead of kmalloc and snprintf.
* Fix missing kfree in error paths.
* Remove unneeded media_remove_intf_links on error paths.
.../staging/media/rockchip/vpu/rockchip_vpu.h | 39 +++-
.../media/rockchip/vpu/rockchip_vpu_drv.c | 207 +++++++++++++++---
2 files changed, 215 insertions(+), 31 deletions(-)
diff --git a/drivers/staging/media/rockchip/vpu/rockchip_vpu.h b/drivers/staging/media/rockchip/vpu/rockchip_vpu.h
index b15c02333a70..aba257c663a7 100644
--- a/drivers/staging/media/rockchip/vpu/rockchip_vpu.h
+++ b/drivers/staging/media/rockchip/vpu/rockchip_vpu.h
@@ -71,12 +71,47 @@ enum rockchip_vpu_codec_mode {
RK_VPU_MODE_JPEG_ENC,
};
+/*
+ * struct rockchip_vpu_func - rockchip VPU functionality
+ *
+ * @id: processing functionality ID (can be
+ * %MEDIA_ENT_F_PROC_VIDEO_ENCODER or
+ * %MEDIA_ENT_F_PROC_VIDEO_DECODER)
+ * @vdev: &struct video_device that exposes the encoder or
+ * decoder functionality
+ * @source_pad: &struct media_pad with the source pad.
+ * @sink: &struct media_entity pointer with the sink entity
+ * @sink_pad: &struct media_pad with the sink pad.
+ * @proc: &struct media_entity pointer with the M2M device itself.
+ * @proc_pads: &struct media_pad with the @proc pads.
+ * @intf_devnode: &struct media_intf devnode pointer with the interface
+ * with controls the M2M device.
+ *
+ * Contains everything needed to attach the video device to the media device.
+ */
+struct rockchip_vpu_func {
+ unsigned int id;
+ struct video_device vdev;
+ struct media_pad source_pad;
+ struct media_entity sink;
+ struct media_pad sink_pad;
+ struct media_entity proc;
+ struct media_pad proc_pads[2];
+ struct media_intf_devnode *intf_devnode;
+};
+
+static inline struct rockchip_vpu_func *
+rockchip_vpu_vdev_to_func(struct video_device *vdev)
+{
+ return container_of(vdev, struct rockchip_vpu_func, vdev);
+}
+
/**
* struct rockchip_vpu_dev - driver data
* @v4l2_dev: V4L2 device to register video devices for.
* @m2m_dev: mem2mem device associated to this device.
* @mdev: media device associated to this device.
- * @vfd_enc: Video device for encoder.
+ * @encoder: encoder functionality.
* @pdev: Pointer to VPU platform device.
* @dev: Pointer to device for convenient logging using
* dev_ macros.
@@ -93,7 +128,7 @@ struct rockchip_vpu_dev {
struct v4l2_device v4l2_dev;
struct v4l2_m2m_dev *m2m_dev;
struct media_device mdev;
- struct video_device *vfd_enc;
+ struct rockchip_vpu_func *encoder;
struct platform_device *pdev;
struct device *dev;
struct clk_bulk_data clocks[ROCKCHIP_VPU_MAX_CLOCKS];
diff --git a/drivers/staging/media/rockchip/vpu/rockchip_vpu_drv.c b/drivers/staging/media/rockchip/vpu/rockchip_vpu_drv.c
index 3c3ce3baeb6d..fa02354a0f8a 100644
--- a/drivers/staging/media/rockchip/vpu/rockchip_vpu_drv.c
+++ b/drivers/staging/media/rockchip/vpu/rockchip_vpu_drv.c
@@ -239,6 +239,7 @@ static int rockchip_vpu_open(struct file *filp)
{
struct rockchip_vpu_dev *vpu = video_drvdata(filp);
struct video_device *vdev = video_devdata(filp);
+ struct rockchip_vpu_func *func = rockchip_vpu_vdev_to_func(vdev);
struct rockchip_vpu_ctx *ctx;
int ret;
@@ -256,7 +257,7 @@ static int rockchip_vpu_open(struct file *filp)
return -ENOMEM;
ctx->dev = vpu;
- if (vdev == vpu->vfd_enc)
+ if (func->id == MEDIA_ENT_F_PROC_VIDEO_ENCODER)
ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(vpu->m2m_dev, ctx,
&enc_queue_init);
else
@@ -324,52 +325,206 @@ static const struct of_device_id of_rockchip_vpu_match[] = {
};
MODULE_DEVICE_TABLE(of, of_rockchip_vpu_match);
-static int rockchip_vpu_video_device_register(struct rockchip_vpu_dev *vpu)
+static int rockchip_vpu_register_entity(struct media_device *mdev,
+ struct media_entity *entity,
+ const char *entity_name,
+ struct media_pad *pads, int num_pads,
+ int function,
+ struct video_device *vdev)
+{
+ char *name;
+ int ret;
+
+ entity->obj_type = MEDIA_ENTITY_TYPE_BASE;
+ if (function == MEDIA_ENT_F_IO_V4L) {
+ entity->info.dev.major = VIDEO_MAJOR;
+ entity->info.dev.minor = vdev->minor;
+ }
+
+ name = devm_kasprintf(mdev->dev, GFP_KERNEL, "%s-%s", vdev->name,
+ entity_name);
+ if (!name)
+ return -ENOMEM;
+
+ entity->name = name;
+ entity->function = function;
+
+ ret = media_entity_pads_init(entity, num_pads, pads);
+ if (ret)
+ return ret;
+
+ ret = media_device_register_entity(mdev, entity);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int rockchip_attach_func(struct rockchip_vpu_dev *vpu,
+ struct rockchip_vpu_func *func)
+{
+ struct media_device *mdev = &vpu->mdev;
+ struct media_link *link;
+ int ret;
+
+ /* Create the three encoder entities with their pads */
+ func->source_pad.flags = MEDIA_PAD_FL_SOURCE;
+ ret = rockchip_vpu_register_entity(mdev, &func->vdev.entity,
+ "source", &func->source_pad, 1,
+ MEDIA_ENT_F_IO_V4L, &func->vdev);
+ if (ret)
+ return ret;
+
+ func->proc_pads[0].flags = MEDIA_PAD_FL_SINK;
+ func->proc_pads[1].flags = MEDIA_PAD_FL_SOURCE;
+ ret = rockchip_vpu_register_entity(mdev, &func->proc, "proc",
+ func->proc_pads, 2, func->id,
+ &func->vdev);
+ if (ret)
+ goto err_rel_entity0;
+
+ func->sink_pad.flags = MEDIA_PAD_FL_SINK;
+ ret = rockchip_vpu_register_entity(mdev, &func->sink, "sink",
+ &func->sink_pad, 1,
+ MEDIA_ENT_F_IO_V4L, &func->vdev);
+ if (ret)
+ goto err_rel_entity1;
+
+ /* Connect the three entities */
+ ret = media_create_pad_link(&func->vdev.entity, 0, &func->proc, 1,
+ MEDIA_LNK_FL_IMMUTABLE |
+ MEDIA_LNK_FL_ENABLED);
+ if (ret)
+ goto err_rel_entity2;
+
+ ret = media_create_pad_link(&func->proc, 0, &func->sink, 0,
+ MEDIA_LNK_FL_IMMUTABLE |
+ MEDIA_LNK_FL_ENABLED);
+ if (ret)
+ goto err_rm_links0;
+
+ /* Create video interface */
+ func->intf_devnode = media_devnode_create(mdev, MEDIA_INTF_T_V4L_VIDEO,
+ 0, VIDEO_MAJOR,
+ func->vdev.minor);
+ if (!func->intf_devnode) {
+ ret = -ENOMEM;
+ goto err_rm_links1;
+ }
+
+ /* Connect the two DMA engines to the interface */
+ link = media_create_intf_link(&func->vdev.entity,
+ &func->intf_devnode->intf,
+ MEDIA_LNK_FL_IMMUTABLE |
+ MEDIA_LNK_FL_ENABLED);
+ if (!link) {
+ ret = -ENOMEM;
+ goto err_rm_devnode;
+ }
+
+ link = media_create_intf_link(&func->sink, &func->intf_devnode->intf,
+ MEDIA_LNK_FL_IMMUTABLE |
+ MEDIA_LNK_FL_ENABLED);
+ if (!link) {
+ ret = -ENOMEM;
+ goto err_rm_devnode;
+ }
+ return 0;
+
+err_rm_devnode:
+ media_devnode_remove(func->intf_devnode);
+
+err_rm_links1:
+ media_entity_remove_links(&func->sink);
+
+err_rm_links0:
+ media_entity_remove_links(&func->proc);
+ media_entity_remove_links(&func->vdev.entity);
+
+err_rel_entity2:
+ media_device_unregister_entity(&func->sink);
+
+err_rel_entity1:
+ media_device_unregister_entity(&func->proc);
+
+err_rel_entity0:
+ media_device_unregister_entity(&func->vdev.entity);
+ return ret;
+}
+
+static void rockchip_detach_func(struct rockchip_vpu_func *func)
+{
+ media_devnode_remove(func->intf_devnode);
+ media_entity_remove_links(&func->sink);
+ media_entity_remove_links(&func->proc);
+ media_entity_remove_links(&func->vdev.entity);
+ media_device_unregister_entity(&func->sink);
+ media_device_unregister_entity(&func->proc);
+ media_device_unregister_entity(&func->vdev.entity);
+}
+
+static int rockchip_vpu_add_enc_func(struct rockchip_vpu_dev *vpu)
{
const struct of_device_id *match;
+ struct rockchip_vpu_func *func;
struct video_device *vfd;
- int function, ret;
+ int ret;
match = of_match_node(of_rockchip_vpu_match, vpu->dev->of_node);
- vfd = video_device_alloc();
- if (!vfd) {
+ func = devm_kzalloc(vpu->dev, sizeof(*func), GFP_KERNEL);
+ if (!func) {
v4l2_err(&vpu->v4l2_dev, "Failed to allocate video device\n");
return -ENOMEM;
}
+ func->id = MEDIA_ENT_F_PROC_VIDEO_ENCODER;
+
+ vfd = &func->vdev;
vfd->fops = &rockchip_vpu_fops;
- vfd->release = video_device_release;
+ vfd->release = video_device_release_empty;
vfd->lock = &vpu->vpu_mutex;
vfd->v4l2_dev = &vpu->v4l2_dev;
vfd->vfl_dir = VFL_DIR_M2M;
vfd->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE;
vfd->ioctl_ops = &rockchip_vpu_enc_ioctl_ops;
snprintf(vfd->name, sizeof(vfd->name), "%s-enc", match->compatible);
- vpu->vfd_enc = vfd;
+
+ vpu->encoder = func;
video_set_drvdata(vfd, vpu);
ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
if (ret) {
v4l2_err(&vpu->v4l2_dev, "Failed to register video device\n");
- goto err_free_dev;
+ return ret;
}
- v4l2_info(&vpu->v4l2_dev, "registered as /dev/video%d\n", vfd->num);
- function = MEDIA_ENT_F_PROC_VIDEO_ENCODER;
- ret = v4l2_m2m_register_media_controller(vpu->m2m_dev, vfd, function);
+ ret = rockchip_attach_func(vpu, func);
if (ret) {
- v4l2_err(&vpu->v4l2_dev, "Failed to init mem2mem media controller\n");
- goto err_unreg_video;
+ v4l2_err(&vpu->v4l2_dev,
+ "Failed to attach functionality to the media device\n");
+ goto err_unreg_dev;
}
+
+ v4l2_info(&vpu->v4l2_dev, "registered as /dev/video%d\n", vfd->num);
+
return 0;
-err_unreg_video:
+err_unreg_dev:
video_unregister_device(vfd);
-err_free_dev:
- video_device_release(vfd);
return ret;
}
+static void rockchip_vpu_remove_enc_func(struct rockchip_vpu_dev *vpu)
+{
+ struct rockchip_vpu_func *func = vpu->encoder;
+
+ if (!func)
+ return;
+
+ rockchip_detach_func(func);
+ video_unregister_device(&func->vdev);
+}
+
static int rockchip_vpu_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
@@ -464,7 +619,7 @@ static int rockchip_vpu_probe(struct platform_device *pdev)
media_device_init(&vpu->mdev);
vpu->v4l2_dev.mdev = &vpu->mdev;
- ret = rockchip_vpu_video_device_register(vpu);
+ ret = rockchip_vpu_add_enc_func(vpu);
if (ret) {
dev_err(&pdev->dev, "Failed to register encoder\n");
goto err_m2m_rel;
@@ -473,15 +628,13 @@ static int rockchip_vpu_probe(struct platform_device *pdev)
ret = media_device_register(&vpu->mdev);
if (ret) {
v4l2_err(&vpu->v4l2_dev, "Failed to register mem2mem media device\n");
- goto err_video_dev_unreg;
+ goto err_rm_enc_func;
}
+
return 0;
-err_video_dev_unreg:
- if (vpu->vfd_enc) {
- v4l2_m2m_unregister_media_controller(vpu->m2m_dev);
- video_unregister_device(vpu->vfd_enc);
- video_device_release(vpu->vfd_enc);
- }
+
+err_rm_enc_func:
+ rockchip_vpu_remove_enc_func(vpu);
err_m2m_rel:
media_device_cleanup(&vpu->mdev);
v4l2_m2m_release(vpu->m2m_dev);
@@ -501,11 +654,7 @@ static int rockchip_vpu_remove(struct platform_device *pdev)
v4l2_info(&vpu->v4l2_dev, "Removing %s\n", pdev->name);
media_device_unregister(&vpu->mdev);
- if (vpu->vfd_enc) {
- v4l2_m2m_unregister_media_controller(vpu->m2m_dev);
- video_unregister_device(vpu->vfd_enc);
- video_device_release(vpu->vfd_enc);
- }
+ rockchip_vpu_remove_enc_func(vpu);
media_device_cleanup(&vpu->mdev);
v4l2_m2m_release(vpu->m2m_dev);
v4l2_device_unregister(&vpu->v4l2_dev);
--
2.20.1
next prev parent reply other threads:[~2019-05-28 17:02 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-05-28 17:02 [PATCH v6 00/16] Add MPEG-2 decoding to Rockchip VPU Ezequiel Garcia
[not found] ` <20190528170232.2091-1-ezequiel-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>
2019-05-28 17:02 ` [PATCH v6 01/16] media: v4l2-common: Fix v4l2_fill_pixfmt[_mp]() prototypes Ezequiel Garcia
2019-05-28 17:02 ` [PATCH v6 02/16] media: v4l2-common: Add an helper to apply frmsize constraints Ezequiel Garcia
2019-05-28 17:02 ` [PATCH v6 03/16] media: v4l2-common: Support custom imagesize in fill_pixfmt() Ezequiel Garcia
[not found] ` <20190528170232.2091-4-ezequiel-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>
2019-05-29 11:28 ` Mauro Carvalho Chehab
[not found] ` <20190529082809.0b9f3553-qA1ZUp+OV9c@public.gmane.org>
2019-05-29 11:43 ` Hans Verkuil
[not found] ` <cc51be76-81c3-1c54-2005-1b99d00a8ac1-qWit8jRvyhVmR6Xm/wNWPw@public.gmane.org>
2019-05-29 11:58 ` Mauro Carvalho Chehab
[not found] ` <20190529085854.6c689f8d-qA1ZUp+OV9c@public.gmane.org>
2019-05-29 12:16 ` Boris Brezillon
[not found] ` <20190529141633.19c5079b-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>
2019-05-29 12:26 ` Mauro Carvalho Chehab
[not found] ` <20190529092632.779f5f1b-qA1ZUp+OV9c@public.gmane.org>
2019-05-29 12:29 ` Mauro Carvalho Chehab
2019-05-29 12:31 ` Boris Brezillon
2019-05-29 12:31 ` Hans Verkuil
[not found] ` <223a757d-f008-398c-64ce-18b0aaf390c5-qWit8jRvyhVmR6Xm/wNWPw@public.gmane.org>
2019-05-29 12:39 ` Boris Brezillon
2019-05-29 14:04 ` Ezequiel Garcia
[not found] ` <04cb574b530c987a04b098962c93940c49e944d8.camel-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>
2019-05-29 14:06 ` Boris Brezillon
[not found] ` <20190529160610.169c6e00-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>
2019-05-29 14:17 ` Boris Brezillon
[not found] ` <20190529161753.7ffa5276-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>
2019-05-29 14:47 ` Ezequiel Garcia
2019-05-29 13:54 ` Nicolas Dufresne
[not found] ` <4ef64e22f4035fccf09fbb7f0be04a9778b1230d.camel-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>
2019-05-29 14:02 ` Mauro Carvalho Chehab
2019-05-28 17:02 ` [PATCH v6 04/16] rockchip/vpu: Use v4l2_apply_frmsize_constraints() where appropriate Ezequiel Garcia
2019-05-28 17:02 ` Ezequiel Garcia [this message]
2019-05-28 17:02 ` [PATCH v6 06/16] rockchip/vpu: Support the Request API Ezequiel Garcia
2019-05-28 17:02 ` [PATCH v6 07/16] rockchip/vpu: Rename rockchip_vpu_common.h into rockchip_vpu_v4l2.h Ezequiel Garcia
2019-05-28 17:02 ` [PATCH v6 08/16] rockchip/vpu: Move encoder logic to a common place Ezequiel Garcia
2019-05-28 17:02 ` [PATCH v6 09/16] rockchip/vpu: Provide a helper to reset both src and dst formats Ezequiel Garcia
2019-05-28 17:02 ` [PATCH v6 10/16] rockchip/vpu: Prepare things to support decoders Ezequiel Garcia
2019-05-28 17:02 ` [PATCH v6 11/16] rockchip/vpu: Add decoder boilerplate Ezequiel Garcia
2019-05-28 17:02 ` [PATCH v6 12/16] rockchip/vpu: Add support for non-standard controls Ezequiel Garcia
2019-05-28 17:02 ` [PATCH v6 13/16] rockchip/vpu: Add infra to support MPEG-2 decoding Ezequiel Garcia
2019-05-28 17:02 ` [PATCH v6 14/16] rockchip/vpu: Add MPEG2 decoding support to RK3399 Ezequiel Garcia
2019-05-28 17:02 ` [PATCH v6 15/16] rockchip/vpu: Add support for MPEG-2 decoding on RK3288 Ezequiel Garcia
2019-05-28 17:02 ` [PATCH v6 16/16] rockchip/vpu: Add support for MPEG-2 decoding on RK3328 Ezequiel Garcia
[not found] ` <20190528170232.2091-17-ezequiel-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org>
2019-05-29 8:11 ` Hans Verkuil
[not found] ` <2ef056a2-e9dc-52b1-855b-2bef759af9b6-qWit8jRvyhVmR6Xm/wNWPw@public.gmane.org>
2019-05-29 8:50 ` Jonas Karlman
[not found] ` <VI1PR03MB42066B8C9F364ACF7CFFF241AC1F0-269e4kb9IIlWSsgAM8bhN8eAHadYHfrlvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2019-05-29 9:00 ` Hans Verkuil
2019-05-29 14:59 ` Ezequiel Garcia
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190528170232.2091-6-ezequiel@collabora.com \
--to=ezequiel-zgy8ohtn/8qb+jhodadfcq@public.gmane.org \
--cc=boris.brezillon-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org \
--cc=hans.verkuil-FYB4Gu1CFyUAvxtiuMwx3w@public.gmane.org \
--cc=heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org \
--cc=jonas-uIzNG4q0ceqzQB+pC5nmwQ@public.gmane.org \
--cc=kernel-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org \
--cc=linux-media-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
--cc=nicolas.dufresne-ZGY8ohtN/8qB+jHODAdFcQ@public.gmane.org \
--cc=p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org \
--cc=tfiga-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).