From: Hans Verkuil <hverkuil@xs4all.nl>
To: Mikhail Ulyanov <mikhail.ulyanov@cogentembedded.com>,
horms@verge.net.au, magnus.damm@gmail.com
Cc: laurent.pinchart@ideasonboard.com,
sergei.shtylyov@cogentembedded.com, linux-media@vger.kernel.org,
linux-sh@vger.kernel.org
Subject: Re: [PATCH v3 1/1] V4L2: platform: Renesas R-Car JPEG codec driver
Date: Sun, 03 May 2015 10:21:34 +0000 [thread overview]
Message-ID: <5545F6AE.1000607@xs4all.nl> (raw)
In-Reply-To: <1430344409-11928-1-git-send-email-mikhail.ulyanov@cogentembedded.com>
Hi Mikhail,
Thank you for the patch!
I have one high-level comment: please rename the source to r-car-jpu.c. It's
good practice to start with the SoC name since 'jpu' by itself is not very
descriptive.
I have a few more comments (mostly easy ones) below:
On 04/29/2015 11:53 PM, Mikhail Ulyanov wrote:
> Here's the the driver for the Renesas R-Car JPEG processing unit driver.
>
> The driver is implemented within the V4L2 framework as a mem-to-mem device. It
> presents two video nodes to userspace, one for the encoding part, and one for
> the decoding part.
>
> It was found that the only working mode for encoding is no markers output, so we
> generate it with software. In current version of driver we also use software
> JPEG header parsing because with hardware parsing performance is lower then
> desired.
>
> From a userspace point of view the encoding process is typical (S_FMT, REQBUF,
> optionally QUERYBUF, QBUF, STREAMON, DQBUF) for both the source and destination
> queues. The decoding process requires that the source queue performs S_FMT,
> REQBUF, (QUERYBUF), QBUF and STREAMON. After STREAMON on the source queue, it is
> possible to perform G_FMT on the destination queue to find out the processed
> image width and height in order to be able to allocate an appropriate buffer -
> it is assumed that the user does not pass the compressed image width and height
> but instead this information is parsed from the JPEG input. This is done in
> kernel. Then REQBUF, QBUF and STREAMON on the destination queue complete the
> decoding and it is possible to DQBUF from both queues and finish the operation.
>
> During encoding the available formats are: V4L2_PIX_FMT_NV12M and
> V4L2_PIX_FMT_NV16M for source and V4L2_PIX_FMT_JPEG for destination.
>
> During decoding the available formats are: V4L2_PIX_FMT_JPEG for source and
> V4L2_PIX_FMT_NV12M and V4L2_PIX_FMT_NV16M for destination.
>
> Performance of current version:
> 1280x800 NV12 image encoding/decoding
> decoding ~121 FPS
> encoding ~190 FPS
>
> Signed-off-by: Mikhail Ulyanov <mikhail.ulyanov@cogentembedded.com>
> ---
> Changes since v2:
> - Kconfig entry reordered
> - unnecessary clk_disable_unprepare(jpu->clk) removed
> - ref_count fixed in jpu_resume
> - enable DMABUF in src_vq->io_modes
> - remove jpu_s_priority jpu_g_priority
> - jpu_g_selection fixed
> - timeout in jpu_reset added and hardware reset reworked
> - remove unused macros
> - JPEG header parsing now is software because of performance issues
> based on s5p-jpu code
> - JPEG header generation redesigned:
> JPEG header(s) pre-generated and memcpy'ed on encoding
> we only fill the necessary fields
> more "transparent" header format description
> - S_FMT, G_FMT and TRY_FMT hooks redesigned
> partially inspired by VSP1 driver code
> - some code was reformatted
> - image formats handling redesigned
> - multi-planar V4L2 API now in use
> - now passes v4l2-compliance tool check
>
> Cnanges since v1:
> - s/g_fmt function simplified
> - default format for queues added
> - dumb vidioc functions added to be in compliance with standard api:
> jpu_s_priority, jpu_g_priority
> - standard v4l2_ctrl_subscribe_event and v4l2_event_unsubscribe
> now in use by the same reason
>
> drivers/media/platform/Kconfig | 11 +
> drivers/media/platform/Makefile | 1 +
> drivers/media/platform/jpu.c | 1724 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 1736 insertions(+)
> create mode 100644 drivers/media/platform/jpu.c
>
<snip>
> diff --git a/drivers/media/platform/jpu.c b/drivers/media/platform/jpu.c
> new file mode 100644
> index 0000000..6c658cc
> --- /dev/null
> +++ b/drivers/media/platform/jpu.c
<snip>
> +/**
> + * struct jpu - JPEG IP abstraction
> + * @mutex: the mutex protecting this structure
> + * @lock: spinlock protecting the device contexts
> + * @v4l2_dev: v4l2 device for mem2mem mode
> + * @vfd_encoder: video device node for encoder mem2mem mode
> + * @vfd_decoder: video device node for decoder mem2mem mode
> + * @m2m_dev: v4l2 mem2mem device data
> + * @regs: JPEG IP registers mapping
> + * @irq: JPEG IP irq
> + * @clk: JPEG IP clock
> + * @dev: JPEG IP struct device
> + * @alloc_ctx: videobuf2 memory allocator's context
> + * @ref_counter: reference counter
> + */
> +struct jpu {
> + struct mutex mutex;
> + spinlock_t lock;
> + struct v4l2_device v4l2_dev;
> + struct video_device *vfd_encoder;
> + struct video_device *vfd_decoder;
Please just embed these video_device structs (so remove the '*'). This means
that the release callback of each video_device should be set to
video_device_release_empty() and that the video_device_alloc/release can be
removed.
The use of video_device_alloc/release is deprecated and will eventually
disappear.
> + struct v4l2_m2m_dev *m2m_dev;
> +
> + void __iomem *regs;
> + unsigned int irq;
> + struct clk *clk;
> + struct device *dev;
> + void *alloc_ctx;
> + int ref_count;
> +};
> +
<snip>
> +static struct jpu_fmt jpu_formats[] = {
> + { "JPEG JFIF", V4L2_PIX_FMT_JPEG, V4L2_COLORSPACE_JPEG,
> + {0, 0}, 0, 0, 0, 1, JPU_ENC_CAPTURE | JPU_DEC_OUTPUT },
> + { "YUV 4:2:2 planar, Y/CbCr", V4L2_PIX_FMT_NV16M, V4L2_COLORSPACE_SRGB,
> + {8, 16}, 2, 2, JPU_JPEG_422, 2, JPU_ENC_OUTPUT | JPU_DEC_CAPTURE },
> + { "YUV 4:2:0 planar, Y/CbCr", V4L2_PIX_FMT_NV12M, V4L2_COLORSPACE_SRGB,
> + {8, 16}, 2, 2, JPU_JPEG_420, 2, JPU_ENC_OUTPUT | JPU_DEC_CAPTURE }
> +};
Drop the 'name' field: the v4l2 core will now fill in the format description
based on the fourcc value. This change was merged a few days ago in the media_tree
repo.
<snip>
> +static int jpu_enum_fmt(struct v4l2_fmtdesc *f, u32 type)
> +{
> + unsigned int i, num = 0;
> +
> + for (i = 0; i < ARRAY_SIZE(jpu_formats); ++i) {
> + if (jpu_formats[i].types & type) {
> + if (num = f->index)
> + break;
> + ++num;
> + }
> + }
> +
> + if (i >= ARRAY_SIZE(jpu_formats))
> + return -EINVAL;
> +
> + strlcpy(f->description, jpu_formats[i].name, sizeof(f->description));
So this line can be dropped as well.
> + f->pixelformat = jpu_formats[i].fourcc;
> +
> + return 0;
> +}
<snip>
> +static int jpu_g_selection(struct file *file, void *priv,
> + struct v4l2_selection *s)
> +{
> + struct jpu_ctx *ctx = fh_to_ctx(priv);
> +
> + switch (s->target) {
> + case V4L2_SEL_TGT_CROP:
> + case V4L2_SEL_TGT_CROP_BOUNDS:
> + case V4L2_SEL_TGT_CROP_DEFAULT:
> + case V4L2_SEL_TGT_COMPOSE:
> + case V4L2_SEL_TGT_COMPOSE_DEFAULT:
> + s->r.width = ctx->out_q.format.width;
> + s->r.height = ctx->out_q.format.height;
> + break;
> + case V4L2_SEL_TGT_COMPOSE_BOUNDS:
> + case V4L2_SEL_TGT_COMPOSE_PADDED:
> + s->r.width = ctx->cap_q.format.width;
> + s->r.height = ctx->cap_q.format.height;
> + break;
> + default:
> + return -EINVAL;
> + }
> + s->r.left = 0;
> + s->r.top = 0;
> + return 0;
> +}
Why do you implement g_selection? You cannot crop or compose, so what's the point?
The code is wrong anyway since it does not check s->type. CROP for a CAPTURE vs an
OUTPUT buffer should result in different values.
<snip>
> +static int jpu_start_streaming(struct vb2_queue *q, unsigned int count)
> +{
> + return 0;
> +}
> +
> +static void jpu_stop_streaming(struct vb2_queue *q)
> +{
> +}
You can drop these empty start/stop functions.
> +
> +static struct vb2_ops jpu_qops = {
> + .queue_setup = jpu_queue_setup,
> + .buf_prepare = jpu_buf_prepare,
> + .buf_queue = jpu_buf_queue,
> + .wait_prepare = vb2_ops_wait_prepare,
> + .wait_finish = vb2_ops_wait_finish,
> + .start_streaming = jpu_start_streaming,
> + .stop_streaming = jpu_stop_streaming,
> +};
> +
<snip>
Regards,
Hans
WARNING: multiple messages have this Message-ID (diff)
From: Hans Verkuil <hverkuil@xs4all.nl>
To: Mikhail Ulyanov <mikhail.ulyanov@cogentembedded.com>,
horms@verge.net.au, magnus.damm@gmail.com
Cc: laurent.pinchart@ideasonboard.com,
sergei.shtylyov@cogentembedded.com, linux-media@vger.kernel.org,
linux-sh@vger.kernel.org
Subject: Re: [PATCH v3 1/1] V4L2: platform: Renesas R-Car JPEG codec driver
Date: Sun, 03 May 2015 12:21:34 +0200 [thread overview]
Message-ID: <5545F6AE.1000607@xs4all.nl> (raw)
In-Reply-To: <1430344409-11928-1-git-send-email-mikhail.ulyanov@cogentembedded.com>
Hi Mikhail,
Thank you for the patch!
I have one high-level comment: please rename the source to r-car-jpu.c. It's
good practice to start with the SoC name since 'jpu' by itself is not very
descriptive.
I have a few more comments (mostly easy ones) below:
On 04/29/2015 11:53 PM, Mikhail Ulyanov wrote:
> Here's the the driver for the Renesas R-Car JPEG processing unit driver.
>
> The driver is implemented within the V4L2 framework as a mem-to-mem device. It
> presents two video nodes to userspace, one for the encoding part, and one for
> the decoding part.
>
> It was found that the only working mode for encoding is no markers output, so we
> generate it with software. In current version of driver we also use software
> JPEG header parsing because with hardware parsing performance is lower then
> desired.
>
> From a userspace point of view the encoding process is typical (S_FMT, REQBUF,
> optionally QUERYBUF, QBUF, STREAMON, DQBUF) for both the source and destination
> queues. The decoding process requires that the source queue performs S_FMT,
> REQBUF, (QUERYBUF), QBUF and STREAMON. After STREAMON on the source queue, it is
> possible to perform G_FMT on the destination queue to find out the processed
> image width and height in order to be able to allocate an appropriate buffer -
> it is assumed that the user does not pass the compressed image width and height
> but instead this information is parsed from the JPEG input. This is done in
> kernel. Then REQBUF, QBUF and STREAMON on the destination queue complete the
> decoding and it is possible to DQBUF from both queues and finish the operation.
>
> During encoding the available formats are: V4L2_PIX_FMT_NV12M and
> V4L2_PIX_FMT_NV16M for source and V4L2_PIX_FMT_JPEG for destination.
>
> During decoding the available formats are: V4L2_PIX_FMT_JPEG for source and
> V4L2_PIX_FMT_NV12M and V4L2_PIX_FMT_NV16M for destination.
>
> Performance of current version:
> 1280x800 NV12 image encoding/decoding
> decoding ~121 FPS
> encoding ~190 FPS
>
> Signed-off-by: Mikhail Ulyanov <mikhail.ulyanov@cogentembedded.com>
> ---
> Changes since v2:
> - Kconfig entry reordered
> - unnecessary clk_disable_unprepare(jpu->clk) removed
> - ref_count fixed in jpu_resume
> - enable DMABUF in src_vq->io_modes
> - remove jpu_s_priority jpu_g_priority
> - jpu_g_selection fixed
> - timeout in jpu_reset added and hardware reset reworked
> - remove unused macros
> - JPEG header parsing now is software because of performance issues
> based on s5p-jpu code
> - JPEG header generation redesigned:
> JPEG header(s) pre-generated and memcpy'ed on encoding
> we only fill the necessary fields
> more "transparent" header format description
> - S_FMT, G_FMT and TRY_FMT hooks redesigned
> partially inspired by VSP1 driver code
> - some code was reformatted
> - image formats handling redesigned
> - multi-planar V4L2 API now in use
> - now passes v4l2-compliance tool check
>
> Cnanges since v1:
> - s/g_fmt function simplified
> - default format for queues added
> - dumb vidioc functions added to be in compliance with standard api:
> jpu_s_priority, jpu_g_priority
> - standard v4l2_ctrl_subscribe_event and v4l2_event_unsubscribe
> now in use by the same reason
>
> drivers/media/platform/Kconfig | 11 +
> drivers/media/platform/Makefile | 1 +
> drivers/media/platform/jpu.c | 1724 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 1736 insertions(+)
> create mode 100644 drivers/media/platform/jpu.c
>
<snip>
> diff --git a/drivers/media/platform/jpu.c b/drivers/media/platform/jpu.c
> new file mode 100644
> index 0000000..6c658cc
> --- /dev/null
> +++ b/drivers/media/platform/jpu.c
<snip>
> +/**
> + * struct jpu - JPEG IP abstraction
> + * @mutex: the mutex protecting this structure
> + * @lock: spinlock protecting the device contexts
> + * @v4l2_dev: v4l2 device for mem2mem mode
> + * @vfd_encoder: video device node for encoder mem2mem mode
> + * @vfd_decoder: video device node for decoder mem2mem mode
> + * @m2m_dev: v4l2 mem2mem device data
> + * @regs: JPEG IP registers mapping
> + * @irq: JPEG IP irq
> + * @clk: JPEG IP clock
> + * @dev: JPEG IP struct device
> + * @alloc_ctx: videobuf2 memory allocator's context
> + * @ref_counter: reference counter
> + */
> +struct jpu {
> + struct mutex mutex;
> + spinlock_t lock;
> + struct v4l2_device v4l2_dev;
> + struct video_device *vfd_encoder;
> + struct video_device *vfd_decoder;
Please just embed these video_device structs (so remove the '*'). This means
that the release callback of each video_device should be set to
video_device_release_empty() and that the video_device_alloc/release can be
removed.
The use of video_device_alloc/release is deprecated and will eventually
disappear.
> + struct v4l2_m2m_dev *m2m_dev;
> +
> + void __iomem *regs;
> + unsigned int irq;
> + struct clk *clk;
> + struct device *dev;
> + void *alloc_ctx;
> + int ref_count;
> +};
> +
<snip>
> +static struct jpu_fmt jpu_formats[] = {
> + { "JPEG JFIF", V4L2_PIX_FMT_JPEG, V4L2_COLORSPACE_JPEG,
> + {0, 0}, 0, 0, 0, 1, JPU_ENC_CAPTURE | JPU_DEC_OUTPUT },
> + { "YUV 4:2:2 planar, Y/CbCr", V4L2_PIX_FMT_NV16M, V4L2_COLORSPACE_SRGB,
> + {8, 16}, 2, 2, JPU_JPEG_422, 2, JPU_ENC_OUTPUT | JPU_DEC_CAPTURE },
> + { "YUV 4:2:0 planar, Y/CbCr", V4L2_PIX_FMT_NV12M, V4L2_COLORSPACE_SRGB,
> + {8, 16}, 2, 2, JPU_JPEG_420, 2, JPU_ENC_OUTPUT | JPU_DEC_CAPTURE }
> +};
Drop the 'name' field: the v4l2 core will now fill in the format description
based on the fourcc value. This change was merged a few days ago in the media_tree
repo.
<snip>
> +static int jpu_enum_fmt(struct v4l2_fmtdesc *f, u32 type)
> +{
> + unsigned int i, num = 0;
> +
> + for (i = 0; i < ARRAY_SIZE(jpu_formats); ++i) {
> + if (jpu_formats[i].types & type) {
> + if (num == f->index)
> + break;
> + ++num;
> + }
> + }
> +
> + if (i >= ARRAY_SIZE(jpu_formats))
> + return -EINVAL;
> +
> + strlcpy(f->description, jpu_formats[i].name, sizeof(f->description));
So this line can be dropped as well.
> + f->pixelformat = jpu_formats[i].fourcc;
> +
> + return 0;
> +}
<snip>
> +static int jpu_g_selection(struct file *file, void *priv,
> + struct v4l2_selection *s)
> +{
> + struct jpu_ctx *ctx = fh_to_ctx(priv);
> +
> + switch (s->target) {
> + case V4L2_SEL_TGT_CROP:
> + case V4L2_SEL_TGT_CROP_BOUNDS:
> + case V4L2_SEL_TGT_CROP_DEFAULT:
> + case V4L2_SEL_TGT_COMPOSE:
> + case V4L2_SEL_TGT_COMPOSE_DEFAULT:
> + s->r.width = ctx->out_q.format.width;
> + s->r.height = ctx->out_q.format.height;
> + break;
> + case V4L2_SEL_TGT_COMPOSE_BOUNDS:
> + case V4L2_SEL_TGT_COMPOSE_PADDED:
> + s->r.width = ctx->cap_q.format.width;
> + s->r.height = ctx->cap_q.format.height;
> + break;
> + default:
> + return -EINVAL;
> + }
> + s->r.left = 0;
> + s->r.top = 0;
> + return 0;
> +}
Why do you implement g_selection? You cannot crop or compose, so what's the point?
The code is wrong anyway since it does not check s->type. CROP for a CAPTURE vs an
OUTPUT buffer should result in different values.
<snip>
> +static int jpu_start_streaming(struct vb2_queue *q, unsigned int count)
> +{
> + return 0;
> +}
> +
> +static void jpu_stop_streaming(struct vb2_queue *q)
> +{
> +}
You can drop these empty start/stop functions.
> +
> +static struct vb2_ops jpu_qops = {
> + .queue_setup = jpu_queue_setup,
> + .buf_prepare = jpu_buf_prepare,
> + .buf_queue = jpu_buf_queue,
> + .wait_prepare = vb2_ops_wait_prepare,
> + .wait_finish = vb2_ops_wait_finish,
> + .start_streaming = jpu_start_streaming,
> + .stop_streaming = jpu_stop_streaming,
> +};
> +
<snip>
Regards,
Hans
next prev parent reply other threads:[~2015-05-03 10:21 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-04-29 21:53 [PATCH v3 1/1] V4L2: platform: Renesas R-Car JPEG codec driver Mikhail Ulyanov
2015-04-29 21:53 ` Mikhail Ulyanov
2015-04-29 21:59 ` Sergei Shtylyov
2015-04-29 21:59 ` Sergei Shtylyov
2015-04-29 22:08 ` Sergei Shtylyov
2015-04-29 22:08 ` Sergei Shtylyov
2015-05-03 10:21 ` Hans Verkuil [this message]
2015-05-03 10:21 ` Hans Verkuil
2015-05-03 23:32 ` Laurent Pinchart
2015-05-03 23:32 ` Laurent Pinchart
2015-05-05 22:03 ` Mikhail Ulianov
2015-05-05 22:03 ` Mikhail Ulianov
2015-06-18 19:48 ` Laurent Pinchart
2015-06-18 19:48 ` Laurent Pinchart
2015-06-22 14:54 ` Kamil Debski
2015-06-22 14:54 ` Kamil Debski
2015-06-26 11:34 ` Mikhail Ulyanov
2015-06-26 11:34 ` Mikhail Ulyanov
2015-06-26 12:14 ` Kamil Debski
2015-06-26 12:14 ` Kamil Debski
2015-06-26 12:23 ` Mikhail Ulyanov
2015-06-26 12:23 ` Mikhail Ulyanov
2015-05-06 5:46 ` Mikhail Ulianov
2015-05-06 5:46 ` Mikhail Ulianov
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=5545F6AE.1000607@xs4all.nl \
--to=hverkuil@xs4all.nl \
--cc=horms@verge.net.au \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-media@vger.kernel.org \
--cc=linux-sh@vger.kernel.org \
--cc=magnus.damm@gmail.com \
--cc=mikhail.ulyanov@cogentembedded.com \
--cc=sergei.shtylyov@cogentembedded.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.